初始提交

This commit is contained in:
2026-01-04 11:09:06 +08:00
commit 8fa31df250
1326 changed files with 213907 additions and 0 deletions

View File

@@ -0,0 +1,292 @@
<template>
<view class="message-v">
<view class="search-box">
<u-search :placeholder=" $t('app.apply.pleaseKeyword')" v-model="keyword" height="72" :show-action="false"
@change="search" bg-color="#f0f2f6" shape="square" style="width: 100%;">
</u-search>
</view>
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :sticky="false"
:down="downOption" :up="upOption" :bottombar="false">
<view class="message-list">
<view class="message-list-box">
<SwipeItem :list="list" :buttons="options" @action="handleRelocation" ref="swipeItem">
<template v-slot="{ item }">
<view class="reply-item u-border-bottom u-flex" @click="toIm(item)">
<view class="reply-item-img">
<u-avatar :src="baseURL+item.headIcon" mode="square" size="96" />
</view>
<view class="reply-item-txt u-flex-1">
<view class="reply-item-cell reply-item-title u-flex u-row-between">
<text class="title">{{item.realName}}/{{item.account}}</text>
<text class="u-font-24 againColor">{{jnpf.toDateText(item.latestDate)}}</text>
</view>
<view class="reply-item-cell u-flex u-row-between">
<text
class="reply-item-txt-msg u-line-1 againColor">{{getMsgText(item.latestMessage,item.messageType)}}</text>
<u-badge type="error" :count="item.unreadMessage" :absolute="false" />
</view>
</view>
</view>
</template>
</SwipeItem>
</view>
</view>
</mescroll-body>
<!-- -->
</view>
</template>
<script>
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
import SwipeItem from "@/components/SwipeItem/index"
import resources from '@/libs/resources.js'
import {
useChatStore
} from '@/store/modules/chat'
import {
getIMReply,
relocation
} from '@/api/message.js'
export default {
mixins: [MescrollMixin],
components: {
SwipeItem
},
data() {
return {
downOption: {
use: true,
auto: true
},
upOption: {
page: {
num: 0,
size: 20,
time: null
},
empty: {
use: true,
icon: resources.message.nodata,
tip: this.$t('common.noData'),
fixed: true,
top: "300rpx",
}
},
key: +new Date(),
keyword: '',
list: [],
options: [{
text: '移除',
style: {
backgroundColor: '#dd524d',
},
value: 'delete'
}],
swipeAction: false
}
},
computed: {
msgInfo() {
const chatStore = useChatStore()
return chatStore.getMsgInfo
},
baseURL() {
return this.define.baseURL
},
},
onLoad() {
this.keyword = ''
uni.$on('updateList', data => {
this.$nextTick(() => {
this.mescroll.triggerDownScroll()
})
})
uni.$on('updateMsgNum', id => {
this.updateMsgNum(id)
})
},
onUnload() {
uni.$off('updateList')
uni.$off('updateMsgNum')
},
methods: {
handleRelocation(data) {
let {
index,
action,
btn,
item
} = data
this.list.splice(index, 1)
relocation(item.id).then(res => {
this.init({
...this.upOption.page
})
})
},
upCallback(page) {
this.init(page)
},
init(page) {
let query = {
currentPage: page.num,
pageSize: page.size,
keyword: this.keyword
}
getIMReply(query).then(res => {
this.mescroll.endSuccess(res.data.list.length, false);
this.list = res.data.list || [];
this.swipeAction = true
uni.hideLoading()
}).catch(() => {
this.mescroll && this.mescroll.endErr();
})
},
search() {
this.searchTimer && clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.list = [];
this.mescroll.resetUpScroll();
}, 300)
},
updateMsgNum(id) {
const chatStore = useChatStore()
const len = this.list.length
for (let i = 0; i < len; i++) {
if (id === this.list[i].id) {
const num = this.list[i].unreadMessage
chatStore.reduceBadgeNum(num)
this.list[i].unreadMessage = 0
break
}
}
},
getMsgText(text, type) {
if (type === 'voice') return '[语音]';
if (type === 'image') return '[图片]';
return text;
},
toIm(item) {
const chatStore = useChatStore()
const name = item.realName + '/' + item.account
if (item.unreadMessage) {
chatStore.reduceBadgeNum(item.unreadMessage)
item.unreadMessage = 0
}
this.$nextTick(() => {
this.$refs.swipeItem.closeSwipe()
})
uni.navigateTo({
url: '/pages/message/im/index?name=' + item.realName + '/' + item.account + '&formUserId=' +
item.id + '&headIcon=' + item.headIcon
})
}
}
}
</script>
<style lang="scss">
page {
background-color: #f0f2f6;
}
.message-v {
.search-box {
height: 120rpx;
padding: 0rpx 20rpx;
display: flex;
align-items: center;
background-color: #fff;
margin-bottom: 16rpx;
}
.replyList {
padding: 0 20rpx;
background-color: #fff;
.againColor {
color: #909399;
}
}
.reply-item {
height: 142rpx;
background-color: #fff;
padding: 0 20rpx;
.reply-item-img-sysMsg {
width: 96rpx;
height: 96rpx;
border-radius: 16rpx;
overflow: hidden;
margin-right: 16rpx;
flex-shrink: 0;
}
.reply-item-img {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
overflow: hidden;
margin-right: 16rpx;
flex-shrink: 0;
}
.reply-item-icon-color {
background-color: #2bd34f;
}
.reply-item-icon-color2 {
background-color: #3B87F7;
}
.reply-item-icon {
.icon-ym {
color: #fff;
font-size: 50rpx;
}
}
.reply-item-txt {
.reply-item-cell {
height: 40rpx;
color: #C6C6C6;
font-size: 24rpx;
&.reply-item-title {
height: 44rpx;
margin-bottom: 4px;
.title {
font-size: 28rpx;
color: #303133;
}
}
.reply-item-txt-msg {
width: 480rpx;
}
}
}
}
}
.search-box_sticky {
padding: 0 32rpx;
}
.message-list .uni-swipe {
margin-bottom: 0px !important;
border-radius: 0px !important;
}
.message-list {
.message-list-box {
margin: 0px !important;
::v-deep .u-swipe-action {
border-radius: 0;
}
}
}
</style>

988
pages/message/im/emoji.js Normal file
View File

@@ -0,0 +1,988 @@
const emojiTree = [
[{
"url": "100.gif",
"alt": "[微笑]"
},
{
"url": "101.gif",
"alt": "[伤心]"
},
{
"url": "102.gif",
"alt": "[美女]"
},
{
"url": "103.gif",
"alt": "[发呆]"
},
{
"url": "104.gif",
"alt": "[墨镜]"
},
{
"url": "105.gif",
"alt": "[哭]"
},
{
"url": "106.gif",
"alt": "[羞]"
},
{
"url": "107.gif",
"alt": "[哑]"
},
{
"url": "108.gif",
"alt": "[睡]"
},
{
"url": "109.gif",
"alt": "[大哭]"
},
{
"url": "110.gif",
"alt": "[囧]"
},
{
"url": "111.gif",
"alt": "[怒]"
},
{
"url": "112.gif",
"alt": "[调皮]"
},
{
"url": "113.gif",
"alt": "[呲牙]"
},
{
"url": "114.gif",
"alt": "[惊讶]"
},
{
"url": "115.gif",
"alt": "[难过]"
},
{
"url": "116.gif",
"alt": "[酷]"
},
{
"url": "117.gif",
"alt": "[汗]"
},
{
"url": "118.gif",
"alt": "[抓狂]"
},
{
"url": "119.gif",
"alt": "[吐]"
},
{
"url": "120.gif",
"alt": "[笑]"
},
{
"url": "121.gif",
"alt": "[快乐]"
},
{
"url": "122.gif",
"alt": "[疑惑]"
},
{
"url": "123.gif",
"alt": "[傲]"
}
],
[{
"url": "124.gif",
"alt": "[饿]"
},
{
"url": "125.gif",
"alt": "[累]"
},
{
"url": "126.gif",
"alt": "[惊恐]"
},
{
"url": "127.gif",
"alt": "[汗1]"
},
{
"url": "128.gif",
"alt": "[高兴]"
},
{
"url": "129.gif",
"alt": "[闲]"
},
{
"url": "130.gif",
"alt": "[努力]"
},
{
"url": "131.gif",
"alt": "[骂]"
},
{
"url": "132.gif",
"alt": "[疑问]"
},
{
"url": "133.gif",
"alt": "[秘密]"
},
{
"url": "134.gif",
"alt": "[乱]"
},
{
"url": "135.gif",
"alt": "[疯]"
},
{
"url": "136.gif",
"alt": "[哀]"
},
{
"url": "137.gif",
"alt": "[鬼]"
},
{
"url": "138.gif",
"alt": "[打击]"
},
{
"url": "139.gif",
"alt": "[bye]"
},
{
"url": "140.gif",
"alt": "[擦汗]"
},
{
"url": "141.gif",
"alt": "[抠]"
},
{
"url": "142.gif",
"alt": "[鼓掌]"
},
{
"url": "143.gif",
"alt": "[糟糕]"
},
{
"url": "144.gif",
"alt": "[恶搞]"
},
{
"url": "145.gif",
"alt": "[左哼哼]"
},
{
"url": "146.gif",
"alt": "[右哼哼]"
},
{
"url": "147.gif",
"alt": "[哈欠]"
}
],
[{
"url": "148.gif",
"alt": "[看]"
},
{
"url": "149.gif",
"alt": "[委屈]"
},
{
"url": "150.gif",
"alt": "[难过1]"
},
{
"url": "151.gif",
"alt": "[坏]"
},
{
"url": "152.gif",
"alt": "[亲]"
},
{
"url": "153.gif",
"alt": "[吓]"
},
{
"url": "154.gif",
"alt": "[可怜]"
},
{
"url": "155.gif",
"alt": "[刀]"
},
{
"url": "156.gif",
"alt": "[水果]"
},
{
"url": "157.gif",
"alt": "[酒]"
},
{
"url": "158.gif",
"alt": "[篮球]"
},
{
"url": "159.gif",
"alt": "[乒乓]"
},
{
"url": "160.gif",
"alt": "[咖啡]"
},
{
"url": "161.gif",
"alt": "[美食]"
},
{
"url": "162.gif",
"alt": "[动物]"
},
{
"url": "163.gif",
"alt": "[鲜花]"
},
{
"url": "164.gif",
"alt": "[枯]"
},
{
"url": "165.gif",
"alt": "[唇]"
},
{
"url": "166.gif",
"alt": "[爱]"
},
{
"url": "167.gif",
"alt": "[分手]"
},
{
"url": "168.gif",
"alt": "[生日]"
},
{
"url": "169.gif",
"alt": "[电]"
},
{
"url": "170.gif",
"alt": "[炸弹]"
},
{
"url": "171.gif",
"alt": "[刀子]"
}
],
[{
"url": "172.gif",
"alt": "[足球]"
},
{
"url": "173.gif",
"alt": "[瓢虫]"
},
{
"url": "174.gif",
"alt": "[翔]"
},
{
"url": "175.gif",
"alt": "[月亮]"
},
{
"url": "176.gif",
"alt": "[太阳]"
},
{
"url": "177.gif",
"alt": "[礼物]"
},
{
"url": "178.gif",
"alt": "[抱抱]"
},
{
"url": "179.gif",
"alt": "[拇指]"
},
{
"url": "180.gif",
"alt": "[贬低]"
},
{
"url": "181.gif",
"alt": "[握手]"
},
{
"url": "182.gif",
"alt": "[剪刀手]"
},
{
"url": "183.gif",
"alt": "[抱拳]"
},
{
"url": "184.gif",
"alt": "[勾引]"
},
{
"url": "185.gif",
"alt": "[拳头]"
},
{
"url": "186.gif",
"alt": "[小拇指]"
},
{
"url": "187.gif",
"alt": "[拇指八]"
},
{
"url": "188.gif",
"alt": "[食指]"
},
{
"url": "189.gif",
"alt": "[ok]"
},
{
"url": "190.gif",
"alt": "[情侣]"
},
{
"url": "191.gif",
"alt": "[爱心]"
},
{
"url": "192.gif",
"alt": "[蹦哒]"
},
{
"url": "193.gif",
"alt": "[颤抖]"
},
{
"url": "194.gif",
"alt": "[怄气]"
},
{
"url": "195.gif",
"alt": "[跳舞]"
}
],
[{
"url": "196.gif",
"alt": "[拜]"
},
{
"url": "197.gif",
"alt": "[背着]"
},
{
"url": "198.gif",
"alt": "[伸手]"
},
{
"url": "199.gif",
"alt": "[耍帅]"
},
{
"url": "200.png",
"alt": "[微笑1]"
},
{
"url": "201.png",
"alt": "[生病]"
},
{
"url": "202.png",
"alt": "[哭泣]"
},
{
"url": "203.png",
"alt": "[吐舌]"
},
{
"url": "204.png",
"alt": "[迷糊]"
},
{
"url": "205.png",
"alt": "[瞪眼]"
},
{
"url": "206.png",
"alt": "[恐怖]"
},
{
"url": "207.png",
"alt": "[忧愁]"
},
{
"url": "208.png",
"alt": "[眨眉]"
},
{
"url": "209.png",
"alt": "[闭眼]"
},
{
"url": "210.png",
"alt": "[鄙视]"
},
{
"url": "211.png",
"alt": "[阴暗]"
},
{
"url": "212.png",
"alt": "[小鬼]"
},
{
"url": "213.png",
"alt": "[爱心1]"
},
{
"url": "214.png",
"alt": "[拜佛]"
},
{
"url": "215.png",
"alt": "[力量]"
},
{
"url": "216.png",
"alt": "[金钱]"
},
{
"url": "217.png",
"alt": "[蛋糕]"
},
{
"url": "218.png",
"alt": "[彩带]"
},
{
"url": "219.png",
"alt": "[礼物1]"
}
]
]
const emojiList = [{
"url": "100.gif",
"alt": "[微笑]"
},
{
"url": "101.gif",
"alt": "[伤心]"
},
{
"url": "102.gif",
"alt": "[美女]"
},
{
"url": "103.gif",
"alt": "[发呆]"
},
{
"url": "104.gif",
"alt": "[墨镜]"
},
{
"url": "105.gif",
"alt": "[哭]"
},
{
"url": "106.gif",
"alt": "[羞]"
},
{
"url": "107.gif",
"alt": "[哑]"
},
{
"url": "108.gif",
"alt": "[睡]"
},
{
"url": "109.gif",
"alt": "[大哭]"
},
{
"url": "110.gif",
"alt": "[囧]"
},
{
"url": "111.gif",
"alt": "[怒]"
},
{
"url": "112.gif",
"alt": "[调皮]"
},
{
"url": "113.gif",
"alt": "[呲牙]"
},
{
"url": "114.gif",
"alt": "[惊讶]"
},
{
"url": "115.gif",
"alt": "[难过]"
},
{
"url": "116.gif",
"alt": "[酷]"
},
{
"url": "117.gif",
"alt": "[汗]"
},
{
"url": "118.gif",
"alt": "[抓狂]"
},
{
"url": "119.gif",
"alt": "[吐]"
},
{
"url": "120.gif",
"alt": "[笑]"
},
{
"url": "121.gif",
"alt": "[快乐]"
},
{
"url": "122.gif",
"alt": "[疑惑]"
},
{
"url": "123.gif",
"alt": "[傲]"
},
{
"url": "124.gif",
"alt": "[饿]"
},
{
"url": "125.gif",
"alt": "[累]"
},
{
"url": "126.gif",
"alt": "[惊恐]"
},
{
"url": "127.gif",
"alt": "[汗1]"
},
{
"url": "128.gif",
"alt": "[高兴]"
},
{
"url": "129.gif",
"alt": "[闲]"
},
{
"url": "130.gif",
"alt": "[努力]"
},
{
"url": "131.gif",
"alt": "[骂]"
},
{
"url": "132.gif",
"alt": "[疑问]"
},
{
"url": "133.gif",
"alt": "[秘密]"
},
{
"url": "134.gif",
"alt": "[乱]"
},
{
"url": "135.gif",
"alt": "[疯]"
},
{
"url": "136.gif",
"alt": "[哀]"
},
{
"url": "137.gif",
"alt": "[鬼]"
},
{
"url": "138.gif",
"alt": "[打击]"
},
{
"url": "139.gif",
"alt": "[bye]"
},
{
"url": "140.gif",
"alt": "[擦汗]"
},
{
"url": "141.gif",
"alt": "[抠]"
},
{
"url": "142.gif",
"alt": "[鼓掌]"
},
{
"url": "143.gif",
"alt": "[糟糕]"
},
{
"url": "144.gif",
"alt": "[恶搞]"
},
{
"url": "145.gif",
"alt": "[左哼哼]"
},
{
"url": "146.gif",
"alt": "[右哼哼]"
},
{
"url": "147.gif",
"alt": "[哈欠]"
},
{
"url": "148.gif",
"alt": "[看]"
},
{
"url": "149.gif",
"alt": "[委屈]"
},
{
"url": "150.gif",
"alt": "[难过1]"
},
{
"url": "151.gif",
"alt": "[坏]"
},
{
"url": "152.gif",
"alt": "[亲]"
},
{
"url": "153.gif",
"alt": "[吓]"
},
{
"url": "154.gif",
"alt": "[可怜]"
},
{
"url": "155.gif",
"alt": "[刀]"
},
{
"url": "156.gif",
"alt": "[水果]"
},
{
"url": "157.gif",
"alt": "[酒]"
},
{
"url": "158.gif",
"alt": "[篮球]"
},
{
"url": "159.gif",
"alt": "[乒乓]"
},
{
"url": "160.gif",
"alt": "[咖啡]"
},
{
"url": "161.gif",
"alt": "[美食]"
},
{
"url": "162.gif",
"alt": "[动物]"
},
{
"url": "163.gif",
"alt": "[鲜花]"
},
{
"url": "164.gif",
"alt": "[枯]"
},
{
"url": "165.gif",
"alt": "[唇]"
},
{
"url": "166.gif",
"alt": "[爱]"
},
{
"url": "167.gif",
"alt": "[分手]"
},
{
"url": "168.gif",
"alt": "[生日]"
},
{
"url": "169.gif",
"alt": "[电]"
},
{
"url": "170.gif",
"alt": "[炸弹]"
},
{
"url": "171.gif",
"alt": "[刀子]"
},
{
"url": "172.gif",
"alt": "[足球]"
},
{
"url": "173.gif",
"alt": "[瓢虫]"
},
{
"url": "174.gif",
"alt": "[翔]"
},
{
"url": "175.gif",
"alt": "[月亮]"
},
{
"url": "176.gif",
"alt": "[太阳]"
},
{
"url": "177.gif",
"alt": "[礼物]"
},
{
"url": "178.gif",
"alt": "[抱抱]"
},
{
"url": "179.gif",
"alt": "[拇指]"
},
{
"url": "180.gif",
"alt": "[贬低]"
},
{
"url": "181.gif",
"alt": "[握手]"
},
{
"url": "182.gif",
"alt": "[剪刀手]"
},
{
"url": "183.gif",
"alt": "[抱拳]"
},
{
"url": "184.gif",
"alt": "[勾引]"
},
{
"url": "185.gif",
"alt": "[拳头]"
},
{
"url": "186.gif",
"alt": "[小拇指]"
},
{
"url": "187.gif",
"alt": "[拇指八]"
},
{
"url": "188.gif",
"alt": "[食指]"
},
{
"url": "189.gif",
"alt": "[ok]"
},
{
"url": "190.gif",
"alt": "[情侣]"
},
{
"url": "191.gif",
"alt": "[爱心]"
},
{
"url": "192.gif",
"alt": "[蹦哒]"
},
{
"url": "193.gif",
"alt": "[颤抖]"
},
{
"url": "194.gif",
"alt": "[怄气]"
},
{
"url": "195.gif",
"alt": "[跳舞]"
},
{
"url": "196.gif",
"alt": "[拜]"
},
{
"url": "197.gif",
"alt": "[背着]"
},
{
"url": "198.gif",
"alt": "[伸手]"
},
{
"url": "199.gif",
"alt": "[耍帅]"
},
{
"url": "200.png",
"alt": "[微笑1]"
},
{
"url": "201.png",
"alt": "[生病]"
},
{
"url": "202.png",
"alt": "[哭泣]"
},
{
"url": "203.png",
"alt": "[吐舌]"
},
{
"url": "204.png",
"alt": "[迷糊]"
},
{
"url": "205.png",
"alt": "[瞪眼]"
},
{
"url": "206.png",
"alt": "[恐怖]"
},
{
"url": "207.png",
"alt": "[忧愁]"
},
{
"url": "208.png",
"alt": "[眨眉]"
},
{
"url": "209.png",
"alt": "[闭眼]"
},
{
"url": "210.png",
"alt": "[鄙视]"
},
{
"url": "211.png",
"alt": "[阴暗]"
},
{
"url": "212.png",
"alt": "[小鬼]"
},
{
"url": "213.png",
"alt": "[爱心1]"
},
{
"url": "214.png",
"alt": "[拜佛]"
},
{
"url": "215.png",
"alt": "[力量]"
},
{
"url": "216.png",
"alt": "[金钱]"
},
{
"url": "217.png",
"alt": "[蛋糕]"
},
{
"url": "218.png",
"alt": "[彩带]"
},
{
"url": "219.png",
"alt": "[礼物1]"
}
]
const req = import.meta.glob('../static/emoji/*.*', {
eager: true
})
const imagesMap = {}
// 循环所有图片,将图片名设置成键,值为导入该图片的地址
for (const key in req) {
// let name = key.split('/').slice(-1)[0].split('.')[0]
let name = key.split('/').slice(-1)[0].replace('.', '')
// 抛出图片大对象后,文件页面直接引入后将图片的具体名称作为属性就能导入该图片
imagesMap[name] = req[key].default
}
export {
emojiList,
emojiTree,
imagesMap
}

606
pages/message/im/index.scss Normal file
View File

@@ -0,0 +1,606 @@
@font-face {
font-family: "HMfont-home";
src: url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2');
}
.icon {
font-family: "HMfont-home" !important;
font-size: 56rpx;
font-style: normal;
color: #333;
&.biaoqing:before {
content: "\e797";
}
&.jianpan:before {
content: "\e7b2";
}
&.yuyin:before {
content: "\e805";
}
&.tupian:before {
content: "\e639";
}
&.chehui:before {
content: "\e904";
}
&.luyin:before {
content: "\e905";
}
&.luyin2:before {
content: "\e677";
}
&.other-voice:before {
content: "\e667";
}
&.my-voice:before {
content: "\e906";
}
&.hongbao:before {
content: "\e626";
}
&.tupian2:before {
content: "\e674";
}
&.paizhao:before {
content: "\e63e";
}
&.add:before {
content: "\e655";
}
&.close:before {
content: "\e607";
}
&.to:before {
content: "\e675";
}
}
page {
background-color: #f0f2f6;
}
.im-v {
.notData-box {
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
padding-top: 400rpx;
.notData-inner {
width: 280rpx;
height: 308rpx;
align-items: center;
.iconImg {
width: 100%;
height: 100%;
}
.notData-inner-text {
padding: 30rpx 0;
color: #909399;
}
}
}
.msg-end {
padding: 40rpx 0;
font-size: 28rpx;
text-align: center;
color: #999;
}
.hidden {
display: none !important;
}
.popup-layer {
&.showLayer {
transform: translate3d(0, -42vw, 0);
}
transition: all .15s linear;
width: 100%;
height: 42vw;
padding: 20rpx 2%;
background-color: #f2f2f2;
position: fixed;
z-index: 20;
top: 100%;
.emoji-swiper {
height: 40vw;
swiper-item {
display: flex;
align-content: flex-start;
flex-wrap: wrap;
.emoji-item {
width: 12vw;
height: 12vw;
display: flex;
justify-content: center;
align-items: center;
.emoji-item-img {
width: 8.4vw;
height: 8.4vw;
}
}
}
}
.more-layer {
width: 100%;
height: 42vw;
.list {
width: 100%;
display: flex;
flex-wrap: wrap;
.box {
width: 18vw;
height: 18vw;
border-radius: 20rpx;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
margin: 0 3vw 2vw 3vw;
.icon {
font-size: 70rpx;
}
}
}
}
}
.input-box {
width: 100%;
box-sizing: border-box;
min-height: 80rpx;
padding: 24rpx 32rpx;
background-color: #f2f2f2;
display: flex;
align-items: flex-end;
position: fixed;
z-index: 20;
bottom: 0;
&.showLayer {
transform: translate3d(0, -42vw, 0);
}
transition: all .15s linear;
.input-box-icon {
flex-shrink: 0;
height: 56rpx;
width: 56rpx;
margin-bottom: 6rpx;
margin-right: 16rpx;
&.add {
margin-right: 0;
}
}
.send-btn {
flex-shrink: 0;
width: 90rpx;
margin-bottom: 6rpx;
height: 56rpx;
line-height: 56rpx;
background: #339AFF;
color: #fff;
border-radius: 6rpx;
font-size: 24rpx;
text-align: center;
margin-left: 16rpx;
}
.voice-mode {
flex: 1;
height: 68rpx;
border-radius: 16rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
background-color: #fff;
color: #555;
margin-right: 16rpx;
&.recording {
background-color: #e5e5e5;
}
}
.text-mode {
flex: 1;
min-height: 68rpx;
display: flex;
background-color: #fff;
border-radius: 16rpx;
margin-right: 16rpx;
.input-area {
width: 100%;
padding: 16rpx;
display: flex;
align-items: center;
max-height: 100rpx;
overflow-y: scroll;
textarea {
width: 100%;
font-size: 28rpx;
}
}
}
}
.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%;
}
}
.icon {
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;
.icon {
color: #fff;
font-size: 150rpx;
}
}
.tis {
width: 100%;
height: 10vw;
display: flex;
justify-content: center;
font-size: 28rpx;
color: #fff;
&.change {
color: #f09b37;
}
}
}
.msg-list {
padding: 0 24rpx;
.msg-list-item {
display: flex;
align-items: flex-start;
padding: 20rpx 0;
&.msg-list-item-l {
flex-direction: row;
.avatar {
flex-shrink: 0;
width: 80rpx;
height: 80rpx;
margin-right: 20rpx;
}
}
&.msg-list-item-r {
flex-direction: row-reverse;
.avatar {
flex-shrink: 0;
width: 80rpx;
height: 80rpx;
margin-left: 20rpx;
}
}
.msg-text {
max-width: 70%;
min-height: 50rpx;
border-radius: 4rpx 30rpx 30rpx 30rpx;
padding: 16rpx 32rpx;
display: flex;
align-items: center;
font-size: 32rpx;
word-break: break-word;
flex-wrap: wrap;
background-color: #fff;
color: #303133;
.msg-text-txt {
font-size: 32rpx;
line-height: 48rpx;
}
.msg-text-emoji {
vertical-align: top;
width: 48rpx;
height: 48rpx;
display: inline-block;
}
}
.msg-img {
background-color: transparent;
padding: 0;
overflow: hidden;
image {
max-width: 350rpx;
max-height: 350rpx;
border-radius: 16rpx;
}
}
.msg-voice {
.icon {
font-size: 40rpx;
display: flex;
align-items: center;
}
.icon:after {
content: " ";
width: 53rpx;
height: 53rpx;
border-radius: 100%;
position: absolute;
box-sizing: border-box;
}
.length {
font-size: 28rpx;
}
&.play {
@keyframes my-play {
0% {
transform: translateX(80%);
}
100% {
transform: translateX(0%);
}
}
.icon:after {
border-left: solid 10rpx rgba(186, 230, 253, .8);
animation: my-play 1s linear infinite;
}
}
}
}
// .msg-list-item {
// padding: 20rpx 0;
// .content {
// width: 100%;
// display: flex;
// .msg-text {
// max-width: 70%;
// min-height: 50rpx;
// border-radius: 4rpx 30rpx 30rpx 30rpx;
// padding: 16rpx 32rpx;
// display: flex;
// align-items: center;
// font-size: 32rpx;
// word-break: break-word;
// flex-wrap: wrap;
// background-color: #fff;
// color: #3A3A3A;
// .msg-text-txt{
// font-size: 32rpx;
// line-height: 48rpx;
// }
// .msg-text-emoji{
// vertical-align: top;
// width: 48rpx;
// height: 48rpx;
// display: inline-block;
// }
// }
// .msg-img {
// background-color: transparent;
// padding: 0;
// overflow: hidden;
// image {
// max-width: 350rpx;
// max-height: 350rpx;
// border-radius: 16rpx;
// }
// }
// .msg-voice {
// .icon {
// font-size: 40rpx;
// display: flex;
// align-items: center;
// }
// .icon:after {
// content: " ";
// width: 53rpx;
// height: 53rpx;
// border-radius: 100%;
// position: absolute;
// box-sizing: border-box;
// }
// .length {
// font-size: 28rpx;
// }
// }
// }
// .avatar {
// // flex-shrink: 0;
// // width: 80rpx;
// // height: 80rpx;
// }
// .my {
// display: flex;
// justify-content: flex-end;
// .content {
// min-height: 80rpx;
// align-items: center;
// justify-content: flex-end;
// .msg-text {
// background-color: #BAE6FD;
// border-radius: 30rpx 4rpx 30rpx 30rpx;
// }
// .msg-voice {
// .length {
// margin-right: 20rpx;
// }
// &.play {
// @keyframes my-play {
// 0% {
// transform: translateX(80%);
// }
// 100% {
// transform: translateX(0%);
// }
// }
// .icon:after {
// border-left: solid 10rpx rgba(186, 230, 253, .8);
// animation: my-play 1s linear infinite;
// }
// }
// }
// }
// .avatar {
// margin-left: 16rpx;
// }
// }
// .other {
// display: flex;
// .avatar {
// margin-right: 16rpx;
// }
// .content {
// flex-wrap: wrap;
// .msg-voice {
// .icon {
// color: #333;
// }
// .length {
// margin-left: 20rpx;
// }
// &.play {
// @keyframes other-play {
// 0% {
// transform: translateX(-80%);
// }
// 100% {
// transform: translateX(0%);
// }
// }
// .icon:after {
// border-right: solid 10rpx rgba(255, 255, 255, .8);
// animation: other-play 1s linear infinite;
// }
// }
// }
// }
// }
// }
}
}

588
pages/message/im/index.vue Normal file
View File

@@ -0,0 +1,588 @@
<template>
<view class="im-v">
<view @click="hideDrawer">
<mescroll-body ref="mescrollRef" bottom="50%" @init="mescrollInit" :down="downOption" @down="downCallback"
:up="upOption">
<!-- 无更多消息 -->
<view v-if="isEnd && !isMsgList" class="msg-end">没有更多消息了</view>
<JnpfEmpty v-if="isMsgList" description="暂无聊天记录"></JnpfEmpty>
<view class="msg-list">
<!-- 消息列表 (必须配置id,以便定位) -->
<view class="msg-list-item" v-for="(msg,index) in msgList" :key="index" :id="'msg'+msg.id"
:class="userId === msg.sendUserId ? 'msg-list-item-r' : 'msg-list-item-l'">
<view class="avatar" v-if="userId === msg.sendUserId">
<u-avatar :src="baseURL+userInfoHeadIcon" size="80"></u-avatar>
</view>
<view class="avatar" v-else>
<u-avatar :src="baseURL+headIcon" size="80"></u-avatar>
</view>
<!-- 文字表情 -->
<view class="msg-text" v-if="msg.contentType==='text'">
<view v-for="(item,i) in msg.msgContent" :key="i">
<text class="msg-text-txt" v-if="item.type=='text'">{{item.content}}</text>
<image class="msg-text-emoji" :src="item.content" v-if="item.type=='emjio'" />
</view>
</view>
<!-- 图片消息 -->
<view v-if="msg.contentType=='image'" class="msg-img" @click="showPic(msg.msgContent.path)">
<image lazy-load="true" :src="msg.msgContent.path"
:style="{'width': msg.msgContent.width+'px','height': msg.msgContent.height+'px'}">
</image>
</view>
<!-- 语言消息 -->
<view v-if="msg.contentType==='voice'" class="msg-text msg-voice" @click="playVoice(msg)"
:class="playMsgid == msg.id?'play':''">
<view class="length">{{msg.msgContent.length}}</view>
<view class="icon my-voice"></view>
</view>
</view>
</view>
</mescroll-body>
</view>
<!-- 抽屉栏 -->
<view class="input-box" :class="popupLayerClass" @touchmove.stop.prevent="discard">
<view class="input-box-icon icon biaoqing" @click="chooseEmoji"></view>
<!-- #ifndef H5 -->
<view class="input-box-icon icon" :class="isVoice?'jianpan':'yuyin'" @click="switchVoice"></view>
<!-- #endif -->
<view class="voice-mode" :class="[isVoice?'':'hidden',recording?'recording':'']" @touchstart="voiceBegin"
@touchmove.stop.prevent="voiceIng" @touchend="voiceEnd" @touchcancel="voiceCancel">{{voiceTis}}</view>
<view class="text-mode" v-if="!isVoice">
<view class="input-area">
<textarea auto-height :cursor-spacing="8" maxlength="500" v-model="textMsg" @focus="textareaFocus"
:focus="textFocus" />
</view>
</view>
<view class="input-box-icon icon add" @click="openMore"></view>
<view class="send-btn" @click="sendText" v-if="!isVoice">发送</view>
</view>
<view class="popup-layer u-border-top" :class="popupLayerClass" @touchmove.stop.prevent="discard">
<swiper class="emoji-swiper" indicator-dots="true" duration="150" v-show="showEmoji">
<swiper-item v-for="(page,pid) in emojiTree" :key="pid">
<view v-for="(em,eid) in page" :key="eid" @click="addEmoji(em)" class="emoji-item">
<image mode="widthFix" :src="getEmojiUrl(em.url)" class="emoji-item-img"></image>
</view>
</swiper-item>
</swiper>
<view class="more-layer" v-show="showMore">
<view class="list">
<view class="box" @click="chooseImage('album')">
<text class="icon tupian2"></text>
</view>
<!-- #ifndef H5 -->
<view class="box" @click="chooseImage('camera')">
<text class="icon paizhao"></text>
</view>
<!-- #endif -->
</view>
</view>
</view>
<!-- 录音UI效果 -->
<view class="record" :class="recording?'':'hidden'">
<view class="ing" :class="willStop?'hidden':''">
<view class="icon luyin2"></view>
</view>
<view class="cancel" :class="willStop?'':'hidden'">
<view class="icon chehui"></view>
</view>
<view class="tis" :class="willStop?'change':''">{{recordTis}}</view>
</view>
</view>
</template>
<script>
import chat from '@/libs/chat.js'
import {
emojiList,
emojiTree,
imagesMap
} from './emoji.js'
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
import {
mapGetters
} from 'vuex'
import jnpf from '@/utils/jnpf'
import {
useChatStore
} from '@/store/modules/chat'
const chatStore = useChatStore()
//播放语音相关参数
const AUDIO = uni.createInnerAudioContext()
export default {
mixins: [MescrollMixin],
name: 'im',
data() {
return {
formUserId: '',
headIcon: '',
name: '',
downOption: {
auto: true,
},
upOption: {
use: false,
toTop: {
src: ''
}
},
currentPage: 1,
pageSize: 30,
//录音相关参数
// #ifndef H5
//H5不能录音
RECORDER: uni.getRecorderManager(),
// #endif
playMsgid: null,
popupLayerClass: '',
textFocus: false,
showMore: false,
showEmoji: false,
emojiList,
emojiTree,
msgList: [],
isEnd: false,
isMsgList: true,
isVoice: false,
voiceTis: '按住 说话',
recordTis: "手指上滑 取消发送",
recording: false,
willStop: false,
initPoint: {
identifier: 0,
Y: 0
},
recordTimer: null,
recordLength: 0,
textMsg: '',
msgImageList: [],
userId: '',
userInfoHeadIcon: ''
}
},
computed: {
baseURL() {
return this.define.baseURL
}
},
watch: {},
onLoad(option) {
let userInfo = uni.getStorageSync('userInfo')
this.userId = userInfo.userId
this.userInfoHeadIcon = userInfo.headIcon
this.formUserId = option.formUserId;
this.headIcon = option.headIcon;
this.name = option.name;
uni.$on('getMessageList', data => {
this.getMessageList(data)
})
uni.$on('addMsg', data => {
this.addMsg(data)
})
chatStore.setFormUserId(this.formUserId)
const updateReadMessage = {
method: "UpdateReadMessage",
formUserId: this.formUserId,
token: uni.getStorageSync('token')
}
chat.sendMsg(JSON.stringify(updateReadMessage))
uni.setNavigationBarTitle({
title: option.name
});
//语音自然播放结束
// #ifndef MP-ALIPAY
AUDIO.onEnded((res) => {
this.playMsgid = null;
});
// #endif
// #ifndef H5 || MP-ALIPAY
//录音开始事件
this.RECORDER.onStart((e) => {
this.recordBegin(e);
});
//录音结束事件
this.RECORDER.onStop((e) => {
this.recordEnd(e);
});
// #endif
},
onUnload() {
uni.$off('getMessageList')
uni.$off('addMsg')
chatStore.setFormUserId('')
// #ifndef MP-ALIPAY
AUDIO.stop();
// #endif
},
methods: {
getMessageList(data) {
let msgImageList = []
const list = data.list.map(o => {
if (o.contentType === 'image') {
if (o.content) {
let content = {}
if (typeof(o.content) === 'string') {
content = JSON.parse(o.content)
} else {
content = o.content
}
msgImageList.push(jnpf.getAuthImgUrl(content.path))
}
}
return this.dealMsg(o)
})
this.msgImageList = [...msgImageList, ...this.msgImageList]
let topMsg = this.msgList[0]
this.msgList = [...list, ...this.msgList]
if (this.msgList.length) this.isMsgList = false
if (data.list.length < data.pagination.pageSize) {
this.mescroll.lockDownScroll(true)
this.isEnd = true
}
this.$nextTick(() => {
if (this.currentPage <= 2) {
this.mescroll.scrollTo(99999, 0)
} else if (topMsg) {
let view = uni.createSelectorQuery().select('#msg' + topMsg.id);
view.boundingClientRect(v => {
this.mescroll.scrollTo(v.top - 100, 0)
}).exec();
}
})
},
downCallback() {
const messageList = {
method: "MessageList",
toUserId: this.formUserId,
formUserId: this.userId,
token: uni.getStorageSync('token'),
currentPage: this.currentPage,
pageSize: this.pageSize,
sord: "desc"
}
chat.sendMsg(JSON.stringify(messageList))
this.currentPage++;
this.mescroll.endSuccess();
},
discard() {
return;
},
switchVoice() {
this.hideDrawer();
this.isVoice = !this.isVoice;
},
openMore() {
if (this.showMore) return this.hideDrawer()
this.showMore = true;
this.showEmoji = false;
this.openDrawer();
},
openDrawer() {
this.isVoice = false;
this.popupLayerClass = 'showLayer';
},
hideDrawer() {
this.popupLayerClass = '';
setTimeout(() => {
this.showMore = false;
this.showEmoji = false;
}, 150);
},
textareaFocus() {
this.hideDrawer();
},
chooseEmoji() {
if (this.showEmoji) return this.hideDrawer()
this.showMore = false;
this.showEmoji = true;
this.openDrawer();
},
addEmoji(em) {
this.textMsg += em.alt;
},
getEmojiUrl(url) {
return imagesMap[url.replace('.', '')]
},
chooseImage(type) {
uni.chooseImage({
// #ifdef H5
count: 1,
// #endif
sourceType: [type], //从相册选择
success: (res) => {
this.hideDrawer();
if (res.tempFilePaths.length) res.tempFilePaths.map(o => (this.uploadFile(o)))
}
});
},
/* 上传图片 */
uploadFile(files) {
uni.uploadFile({
url: this.define.comUploadUrl + 'IM',
filePath: files,
name: 'file',
header: {
Authorization: uni.getStorageSync('token') || ''
},
success: (uploadFileRes) => {
const response = uploadFileRes.data ? JSON.parse(uploadFileRes
.data) : {}
if (uploadFileRes.statusCode !== 200) return this.$u.toast(
response.msg)
if (!response.data || !response.data.name) return
const name = response.data.name
this.getImageInfo(files, name)
}
})
},
/* 获取图片信息 */
getImageInfo(files, name) {
uni.getImageInfo({
src: files,
success: (image) => {
let msg = {
name,
width: image.width,
height: image.height,
};
this.sendMessage(msg, 'image');
}
})
},
addMsg(data) {
if (data.method === 'receiveMessage') {
const updateReadMessage = {
method: "UpdateReadMessage",
formUserId: this.formUserId,
token: uni.getStorageSync('token')
}
chat.sendMsg(JSON.stringify(updateReadMessage))
}
data.id = this.$u.guid()
if (data.contentType === "text") {
data.msgContent = this.replaceEmoji(data.content)
}
if (data.contentType === "image") {
this.msgImageList.push(jnpf.getAuthImgUrl(data.content.path))
data.msgContent = this.setPicSize(data.content)
data.msgContent.path = jnpf.getAuthImgUrl(data.content.path)
}
if (data.contentType === "voice") {
data.msgContent = data.content
}
this.msgList.push(data)
this.$nextTick(() => {
this.mescroll.scrollTo(99999, 0)
})
},
dealMsg(item) {
if (item.contentType === "text") {
item.msgContent = this.replaceEmoji(item.content)
}
if (item.contentType === "image") {
item.msgContent = this.setPicSize(JSON.parse(item.content))
item.msgContent.path = jnpf.getAuthImgUrl(item.msgContent.path)
}
if (item.contentType === "voice") {
item.msgContent = JSON.parse(item.content)
}
return item
},
sendText() {
if (!this.textMsg) return
this.hideDrawer()
this.sendMessage(this.textMsg, 'text')
this.textMsg = ''
},
sendMessage(content, type) {
const messageObj = {
method: "SendMessage",
token: uni.getStorageSync('token'),
toUserId: this.formUserId,
messageType: type,
messageContent: content
}
chat.sendMsg(JSON.stringify(messageObj))
this.isMsgList = false
},
voiceBegin(e) { // 录音开始
this.RECORDER.stop();
if (e.touches.length > 1) {
return;
}
this.initPoint.Y = e.touches[0].clientY;
this.initPoint.identifier = e.touches[0].identifier;
// #ifdef APP-HARMONY
this.RECORDER.start(); //录音开始,
// #endif
// #ifndef APP-HARMONY
this.RECORDER.start({
format: "mp3"
}); //录音开始,
// #endif
},
recordBegin(e) { //录音开始UI效果
this.recording = true;
this.voiceTis = '松开 结束';
this.recordLength = 0;
this.recordTimer = setInterval(() => {
this.recordLength++;
}, 1000)
},
voiceCancel() { // 录音被打断
this.recording = false;
this.voiceTis = '按住 说话';
this.recordTis = '手指上滑 取消发送'
this.willStop = true; //不发送录音
this.RECORDER.stop(); //录音结束
},
voiceIng(e) { // 录音中(判断是否触发上滑取消发送)
if (!this.recording) return
let touche = e.touches[0];
// #ifndef APP-HARMONY
let voice = uni.upx2px(100)
// #endif
// #ifdef APP-HARMONY
let voice = 100 / 2
// #endif
//上滑一个导航栏的高度触发上滑取消发送
if (this.initPoint.Y - touche.clientY >= voice) {
this.willStop = true;
this.recordTis = '松开手指 取消发送'
} else {
this.willStop = false;
this.recordTis = '手指上滑 取消发送'
}
},
voiceEnd(e) { // 结束录音
if (!this.recording) return
this.recording = false;
this.voiceTis = '按住 说话';
this.recordTis = '手指上滑 取消发送'
this.RECORDER.stop(); //录音结束
},
recordEnd(e) { //录音结束(回调文件)
if (!this.willStop) {
let min = parseInt(this.recordLength / 60);
let sec = this.recordLength % 60;
min = min < 10 ? '0' + min : min;
sec = sec < 10 ? '0' + sec : sec;
if (sec < '01') {
this.willStop = true;
this.$u.toast('说话时间太短');
return
}
uni.uploadFile({
url: this.define.comUploadUrl + 'IM',
filePath: e.tempFilePath,
name: 'file',
header: {
Authorization: uni.getStorageSync('token') || ''
},
success: (uploadFileRes) => {
const handleUploadResponse = (uploadFileRes, min, sec) => {
const response = (uploadFileRes.data && JSON.parse(uploadFileRes.data)) ||
{};
if (uploadFileRes.statusCode !== 200) {
this.$u.toast(response.msg || '上传失败,未知错误');
return;
}
const {
data = {}
} = response;
if (!data.name) {
this.$u.toast('上传的文件信息不完整');
return;
}
const msg = {
name: data.name,
length: `${min}:${sec}`
};
this.sendMessage(msg, 'voice');
};
handleUploadResponse(uploadFileRes, min, sec);
}
})
} else {
// console.log('取消发送录音');
}
this.willStop = false;
},
setPicSize(content) { //处理图片尺寸,如果不处理宽高,新进入页面加载图片时候会闪
// 让图片最长边等于设置的最大长度短边等比例缩小图片控件真实改变区别于aspectFit方式。
// #ifndef APP-HARMONY
let maxW = uni.upx2px(350); //350是定义消息图片最大宽度
let maxH = uni.upx2px(350); //350是定义消息图片最大高度
// #endif
// #ifdef APP-HARMONY
let maxW = 350 / 2; //350是定义消息图片最大宽度
let maxH = 350 / 2; //350是定义消息图片最大高度
// #endif
if (content.width > maxW || content.height > maxH) {
let scale = content.width / content.height;
content.width = scale > 1 ? maxW : maxH * scale;
content.height = scale > 1 ? maxW / scale : maxH;
}
return content;
},
replaceEmoji(str) { //替换表情符号为图片
let replacedStr = str.replace(/\[([^(\]|\[)]*)\]/g, item => 'jnpfjnpf' + item + 'jnpfjnpf');
let strArr = replacedStr.split(/jnpfjnpfjnpfjnpf|jnpfjnpf/g)
strArr = strArr.filter(o => o)
let contentList = []
for (let i = 0; i < strArr.length; i++) {
let item = {
content: strArr[i],
type: 'emjio'
}
if (/\[([^(\]|\[)]*)\]/.test(strArr[i])) {
let content = ''
for (let j = 0; j < this.emojiList.length; j++) {
let row = this.emojiList[j];
if (row.alt == strArr[i]) {
content = this.getEmojiUrl(row.url)
break
}
}
item = {
content: content,
type: 'emjio'
}
} else {
item = {
content: strArr[i],
type: 'text'
}
}
contentList.push(item)
}
return contentList
},
showPic(path) { // 预览图片
uni.previewImage({
indicator: "none",
current: path,
urls: this.msgImageList
});
},
playVoice(msg) { // 播放语音
AUDIO.stop();
AUDIO.src = jnpf.getAuthImgUrl(msg.msgContent.path, false);
if (this.playMsgid != null && this.playMsgid == msg.id) {
this.$nextTick(() => {
AUDIO.stop();
});
this.playMsgid = null;
} else {
this.$nextTick(() => {
AUDIO.play();
});
this.playMsgid = msg.id;
}
},
}
}
</script>
<style lang="scss">
@import "./index.scss";
</style>

View File

@@ -0,0 +1,155 @@
<template>
<view class="messageDetail-v u-p-l-20 u-p-r-20">
<view class="u-flex-col u-border-bottom u-p-b-40 u-m-b-40">
<text class="u-m-b-16 u-font-32 txt">{{info.title}}</text>
<view>
<text class="releaseUser u-font-24 ">{{info.releaseUser}}</text>
<text
class="releaseUser u-font-24 u-m-l-16">{{ info.releaseTime?$u.timeFormat(info.releaseTime, 'yyyy-mm-dd hh:MM:ss'):''}}</text>
</view>
</view>
<view class="u-p-b-16 excerpt" v-if="info.excerpt">
{{info.excerpt}}
</view>
<view class="messageDetail-content u-p-b-20 ">
<mp-html :content="info.bodyText" />
</view>
<view class="file-box">
<view class="file-list u-flex" v-for="(item,index) in fileList" :key="index">
<view class="file-list-l">
<u-icon name="attach" color="#969799"></u-icon>
<text class="fileName">{{item.name}}</text>
</view>
<u-icon name="download" color="#969799" @click="openFile(item)"></u-icon>
</view>
</view>
</view>
</template>
<script>
const imgTypeList = ['png', 'jpg', 'jpeg', 'bmp', 'gif']
import {
getMessageDetail
} from '@/api/message.js'
import {
getDownloadUrl
} from '@/api/common'
import jnpf from '@/utils/jnpf'
export default {
data() {
return {
info: {},
fileList: []
}
},
computed: {
baseURL() {
return this.define.baseURL
}
},
onLoad(option) {
this.initDetail(option.id)
},
methods: {
initDetail(id) {
getMessageDetail(id).then(res => {
this.info = res.data;
this.fileList = JSON.parse(this.info.files)
uni.$emit('initUnReadMsgNum')
})
},
previewImage(item) {
if (!item.url) return
const url = jnpf.getAuthImgUrl(item.url)
uni.previewImage({
urls: [url],
current: url,
success: () => {},
fail: () => {
uni.showToast({
title: '预览图片失败',
icon: 'none'
});
}
});
},
openFile(item) {
if (item.fileExtension && imgTypeList.includes(item.fileExtension)) return this.previewImage(item)
// #ifdef MP
this.previewFile(item)
// #endif
// #ifndef MP
getDownloadUrl('annex', item.fileId).then(res => {
// #ifdef H5
window.location.href = this.baseURL + res.data.url + '&name=' + item.name;
// #endif
// #ifndef H5
uni.downloadFile({
url: this.baseURL + res.data.url + '&name=' + item.name,
success: function(res) {
var filePath = res.tempFilePath;
uni.openDocument({
filePath: encodeURI(filePath),
showMenu: true,
success: function(res) {
}
});
}
});
// #endif
})
// #endif
},
previewFile(item) {
let url = item.url
uni.downloadFile({
url: this.baseURL + url,
success: (res) => {
var filePath = res.tempFilePath;
uni.openDocument({
filePath: encodeURI(filePath),
success: (res) => {
console.log('打开文档成功');
}
});
}
});
},
}
}
</script>
<style lang="scss">
.messageDetail-v {
.excerpt {
word-break: break-all;
}
.txt {
font-weight: 700;
}
.messageDetail-content {
color: #606266;
word-break: break-all;
}
.releaseUser {
color: #606266;
}
.file-box {
.file-list {
margin-top: 20rpx;
justify-content: space-between;
.file-list-l {
.fileName {
margin-left: 10rpx;
}
}
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Some files were not shown because too many files have changed in this diff Show More