<template>
|
<view class="uni-task-chat" :style="{'height':'calc(100% - ' +bottomHeight+ ')'}">
|
<view class="chat-container" @touchstart="hideDrawer">
|
<scroll-view class="uni-panel-msglist" :scroll-top="scrollTop" scroll-y="true" @scroll="onScroll"
|
@scrolltoupper="scrollStart">
|
<view v-if="showLoadMore" class="uni-loadmore">{{loadMoreText}}</view>
|
<taskMsgItem v-for="(item, index) in msgBody" :key="item.ID" :playMsgid="playId" :msgData="item"
|
@playVoice="playVoice" @playVideo="playVideo" @previewImage="previewImage">
|
</taskMsgItem>
|
</scroll-view>
|
</view>
|
|
<view class="uni-panel-msg-bottom">
|
|
<view class="uni-panel-btn-left" @click="clickChangeVoice">
|
<view class="uni-panel-btn-voice" :class="isVoiceMsg ? 'fu-imkeyboard' :'fu-yuyin'"></view>
|
</view>
|
|
<view class="uni-panel-msg-text "
|
:style="{width:(!isVoiceMsg && msgInput) ? 'calc(100% -118px)':'calc(100% - 103px)'}">
|
<textarea v-if="!isVoiceMsg" auto-height fixed maxlength="-1" :focus="focusInput" cursor-spacing="10"
|
show-confirm-bar="{{false}}" :adjust-position="flasFlag ? true:false" v-model="msgInput"
|
@focus="inputBindFocus" @blur="inputBindBlur" @input="onInput" type="text"
|
@linechange="onInputLineChange"></textarea>
|
<view class="uni-panel-btn-sound" v-else @touchstart="voiceStart" @touchmove.stop.prevent="voiceIng"
|
@touchend="voiceEnd" @touchcancel="voiceCancel">{{voiceTis}}
|
</view>
|
|
</view>
|
<view class="uni-panel-btn-right" v-if="!isVoiceMsg && msgInput">
|
<button class="uni-panel-btn-send" @click="sendTaskMsg">发送</button>
|
</view>
|
<view class="uni-panel-btn-right" v-else @click="showMore">
|
<view class="uni-panel-btn-add fu-add"></view>
|
</view>
|
</view>
|
<!-- 抽屉栏 -->
|
<view class="uni-panel-popup-layer" v-if="!hideMore">
|
<!-- 更多功能 相册-拍照-->
|
<view class="uni-panel-popup-more-layer" :class="{hidden:hideMore}">
|
<view class="uni-panel-popup-list">
|
<view class="uni-panel-popup-list-box" @click="clickChooseImage">
|
<view class="icon fs-picture"></view>
|
</view>
|
<view class="uni-panel-popup-list-box" v-if="isMobilePlatform" @click="clickCamera">
|
<view class="icon fs-photo"></view>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<view class="uni-panel-safe-bottom" :style="{height:safeAreaBottom + 'px',background:'#f1f1f1'}" />
|
<!-- 录音UI效果 v-if="isVoiceRecord"-->
|
<viewAudioRecord ref="refAudioRecord" @recordStart="recordVioceStart" @recordEnd="recordVioceEnd">
|
</viewAudioRecord>
|
|
</view>
|
</template>
|
|
<script>
|
import TaskInit from "@/common/extend.js"
|
import taskMsgItem from "@/components/msg-item.vue"
|
import viewAudioRecord from '@/components/audio-record.vue'
|
import {
|
logGetList as taskLogGetList,
|
logAdd as taskLogAdd
|
|
} from "@/api/gungho/task.js"
|
|
import {
|
uploadFile,
|
downloadFileUrl,
|
publicFileUrl,
|
downloadFileTask
|
} from "@/api/index.js"
|
import {
|
showModal,
|
showToast,
|
getGuid,
|
getCurUserId,
|
getCurUserName
|
} from "@/common/Page.js"
|
import {
|
DOMParser
|
} from "xmldom"
|
import {
|
sendMsg
|
} from "@/api/gungho/index.js"
|
// #ifndef MP-DINGTALK
|
const audioContext = uni.createInnerAudioContext();
|
// #endif
|
|
export default {
|
name: "pageTaskChat",
|
components: {
|
taskMsgItem,
|
viewAudioRecord
|
},
|
props: {
|
taskId: {
|
type: String,
|
default () {
|
return "";
|
}
|
},
|
taskInfo: {
|
type: Object,
|
default () {
|
return {};
|
}
|
},
|
},
|
data() {
|
return {
|
isMobilePlatform: false,
|
safeAreaBottom: getApp().globalData.safeAreaBottom,
|
loadMoreText: "加载中...",
|
showLoadMore: false,
|
sessionID: "",
|
pindex: 1,
|
ptotal: 0,
|
msgInput: "",
|
msgBody: [],
|
msgSendBody: [],
|
msgImages: [],
|
msgLastTime: "",
|
//bottomLstVal:(getApp().globalData.safeAreaBottom + 94) + 'px',
|
|
holdkeyboardInput: false,
|
flasFlag: false, //表示input输入时,页面不会往上推动
|
bottomHeight: '0px', //input框的数据
|
keywordHeight: 0,
|
isVoiceMsg: false,
|
voiceTis: '按住 说话',
|
|
playId: "",
|
// more参数
|
hideMore: true,
|
focusInput: false,
|
scrollTop: 0,
|
old: {
|
scrollTop: 0,
|
focusInput: false,
|
},
|
}
|
|
},
|
mounted() {
|
console.log('taskchat mounted')
|
var _this = this
|
_this.loadPlatform();
|
//语音自然播放结束
|
// #ifndef MP-DINGTALK
|
audioContext.onEnded((res) => {
|
console.log('语音自然播放结束');
|
_this.setData({
|
playId: ""
|
})
|
});
|
audioContext.onError((res) => {
|
console.log("播放错误", res);
|
});
|
audioContext.onStop = () => {
|
console.log("播放语音停止事件")
|
_this.setData({
|
playId: ""
|
})
|
return
|
}
|
// #endif
|
if (_this.taskId) {
|
_this.updateData()
|
}
|
},
|
watch: {
|
taskId: 'updateData'
|
},
|
methods: {
|
setData: function(obj) {
|
let that = this;
|
let keys = [];
|
let val, data;
|
|
Object.keys(obj).forEach(function(key) {
|
keys = key.split(".");
|
val = obj[key];
|
data = that.$data;
|
keys.forEach(function(key2, index) {
|
if (index + 1 == keys.length) {
|
that.$set(data, key2, val);
|
} else {
|
if (!data[key2]) {
|
that.$set(data, key2, {});
|
}
|
}
|
data = data[key2];
|
});
|
});
|
},
|
updateData() {
|
this.msgBody = []
|
this.msgImages = []
|
this.pindex = 1
|
this.sessionID = ""
|
this.msgLastTime = ""
|
this.totalPages = 0
|
if (this.taskId)
|
{
|
this.loadWorkLog().then((resData) => {
|
this.msgBody = resData || [];
|
this.$nextTick(function() {
|
this.scrollTop = 2000000
|
});
|
})
|
|
}
|
},
|
getLogImage(data) {
|
var _this = this
|
_this.msgImages = []
|
if (Array.isArray(data)) {
|
|
for (let log = 0; log < data.length; log++) {
|
let logs = data[log];
|
logs.imgurl = _this.getUserImage(logs.Creator)
|
if (logs.Content) {
|
let sDesc = logs.Content
|
sDesc = sDesc.replace(/ /g, "")
|
let arr = sDesc.match(new RegExp(/<img[\s\S]*>/, 'g'))
|
if (arr) {
|
// console.log("getLogImage arr",arr)
|
for (let i = 0; i < arr.length; i++) {
|
let xmlDoc = new DOMParser().parseFromString(arr[i], "text/xml");
|
let finds = xmlDoc.getElementsByTagName('img'); //获取find节点
|
for (let i = 0; i < finds.length; i++) { //循环节点
|
let finder = finds[i];
|
let src = finder.getAttribute("src")
|
if (src)
|
_this.msgImages.push(src)
|
}
|
}
|
}
|
}
|
}
|
}
|
//console.log("getLogImage",_this.msgImages)
|
return data;
|
},
|
getLogTime(createTime, isEnd) {
|
let ttime = ""; //判断是否相同
|
let timee = "";
|
if (this.msgLastTime) {
|
let timeCreate = TaskInit.dateUtils.parse(createTime)
|
let timeLast = TaskInit.dateUtils.parse(this.msgLastTime)
|
let timeMSec = timeCreate.getTime() - timeLast.getTime()
|
if (timeMSec > 900000 || isEnd) {
|
timee = TaskInit.dateUtils.openinfo_formatter_ttime(createTime, "");
|
// console.log("getLogDefault",timee);
|
if (ttime == timee)
|
timee = "";
|
else
|
ttime = timee;
|
}
|
} else {
|
timee = TaskInit.dateUtils.openinfo_formatter_ttime(createTime, "notime");
|
}
|
return timee
|
|
},
|
async getLogData(log) {
|
|
var _this = this
|
const app = getApp()
|
if (app.globalData.userdata.user_login == log.Creator)
|
log.self = true;
|
else
|
log.self = false;
|
|
log.imgurl = _this.getUserImage(log.Creator)
|
|
//判断是否是音频
|
log.isMedia = false
|
let sContent = log.Content
|
let sContent2 = log.Content
|
|
//console.log("Content:",sContent)
|
sContent = sContent.replace(/<audio[\s\S]*>/, '')
|
sContent2 = sContent2.replace(/<video[\s\S]*>/, '')
|
|
// console.log("Content :",log.Content)
|
if (sContent == "") {
|
let xmlDoc = new DOMParser().parseFromString(log.Content, "text/xml");
|
let finds = xmlDoc.getElementsByTagName('audio'); //获取find节点
|
for (let i = 0; i < finds.length; i++) { //循环节点
|
let finder = finds[i];
|
let src = finder.getAttribute("src")
|
let len = finder.getAttribute("length")
|
let fileserver = finder.getAttribute("data-fileserver")
|
let src2 = await publicFileUrl(fileserver, src)
|
// console.log("Content audio src:",src)
|
log.mediaSrc = src2
|
log.mediaLen = parseInt(len)
|
log.mediaType = "audio"
|
log.mediaWidth = 100
|
log.mediaHeight = 20
|
log.mediaPoster = ""
|
break;
|
}
|
log.isMedia = true
|
//row.msg.voice.length = 03
|
} else if (sContent2 == "") {
|
let xmlDoc = new DOMParser().parseFromString(log.Content, "text/xml");
|
let finds = xmlDoc.getElementsByTagName('video'); //获取find节点
|
for (let i = 0; i < finds.length; i++) { //循环节点
|
let finder = finds[i];
|
let src = finder.getAttribute("src")
|
let len = finder.getAttribute("length")
|
let width = finder.getAttribute("width")
|
let height = finder.getAttribute("height")
|
let poster = finder.getAttribute("poster")
|
let fileserver = finder.getAttribute("data-fileserver")
|
let src2 = await publicFileUrl(fileserver, src)
|
|
let poster2 = poster ? await publicFileUrl(fileserver, poster) : ""
|
// console.log("Content audio src:",src)
|
let nW = width
|
let nH = height
|
if (nH > 160) {
|
nH = 160
|
nW = (width * 160) / (height)
|
}
|
log.mediaSrc = src2
|
log.mediaLen = parseInt(len)
|
log.mediaType = "video"
|
log.mediaWidth = nW
|
log.mediaHeight = nH
|
log.mediaPoster = poster2
|
break;
|
}
|
log.isMedia = true
|
//row.msg.voice.length = 03
|
} else {
|
const imgRegex =
|
/<img[^>]+src="([^">]+)"[^>]*data-fileserver="([^">]+)"[^>]*>/g;
|
let arr = log.Content.match(imgRegex)
|
if (arr) {
|
for (let i = 0; i < arr.length; i++) {
|
const xmlImg = arr[i]
|
let xmlDoc = new DOMParser().parseFromString(xmlImg, "text/xml");
|
let finds = xmlDoc.getElementsByTagName('img'); //获取find节点
|
for (let j = 0; j < finds.length; j++) { //循环节点
|
let finder = finds[j];
|
let src = finder.getAttribute("src")
|
let fileserver = finder.getAttribute("data-fileserver")
|
let src2 = await publicFileUrl(fileserver, src)
|
log.Content = log.Content.replace(xmlImg,
|
`<img style="width:auto;height:auto;max-width:100%;max-height:160px;display:block;" src="${src2}"/>`
|
);
|
break
|
}
|
|
}
|
}
|
log.isMedia = false
|
}
|
|
return log
|
|
},
|
|
async getLogDefault(data) {
|
|
var _this = this
|
if (Array.isArray(data)) {
|
let resData = []
|
const app = getApp()
|
let msgLastTime = this.msgLastTime;
|
this.msgLastTime = ""
|
for (let log = 0; log < data.length; log++) {
|
let logs = data[log];
|
|
let curLogIndex = this.msgBody.findIndex((logTemp, index, arr) => {
|
return logTemp.ID == logs.ID;
|
})
|
if (curLogIndex == -1) {
|
logs.time = this.getLogTime(logs.CreateTime, log + 1 == data.length)
|
if (logs.CreateTime)
|
this.msgLastTime = logs.CreateTime
|
logs = await this.getLogData(logs)
|
resData.push(logs);
|
}
|
}
|
if (msgLastTime) {
|
this.msgLastTime = msgLastTime
|
}
|
return resData;
|
} else
|
return await this.getLogData(data);
|
|
},
|
//装载讨论记录
|
async loadWorkLog() {
|
|
var _this = this;
|
return new Promise(async (resolve) => {
|
try {
|
const param = {
|
sessionID: _this.sessionID,
|
page: _this.pindex,
|
id: _this.taskId,
|
numPerPage: 20,
|
|
}
|
if (_this.pindex == 1) {
|
param.page = 1
|
param.sessionID = ""
|
}
|
const res = await taskLogGetList(param)
|
if (res) {
|
_this.pindex = Number(res.CurPage)
|
_this.ptotal = Number(res.TotalPages)
|
_this.totalcount = Number(res.Records)
|
_this.psize = Number(res.PageSize)
|
_this.sessionID = res.SessionID
|
let list = res.Result || []
|
list.reverse()
|
list = _this.getLogDefault(list);
|
|
_this.getLogImage(list)
|
if (_this.ptotal <= _this.pindex) {
|
_this.showLoadMore = false;
|
_this.loadMoreText = ""
|
}
|
resolve(list)
|
}
|
|
} catch (ex) {
|
this.showError(ex)
|
console.log("taskchat taskLog failed", ex)
|
}
|
|
|
})
|
},
|
//发送讨论内容
|
sendTaskMsg() {
|
var _this = this;
|
console.log("sendTaskMsg", _this.msgInput)
|
let sText = _this.msgInput.trim()
|
if (sText.length < 1) {
|
showToast("不能发送空白信息", "none")
|
return
|
}
|
let guid = getGuid();
|
_this.msgInput = ""
|
_this.addTaskDiscuzMsg(guid, sText)
|
},
|
formatNewDiscuzMsg(msg) {
|
var _this = this;
|
msg.self = true
|
const app = getApp()
|
msg.Creator = app.globalData.userdata.user_login
|
msg.CreatorName = app.globalData.userdata.user_name
|
msg.imgurl = _this.getUserImage(msg.Creator)
|
if (!msg.CreateTime) {
|
msg.CreateTime = TaskInit.dateUtils.toDateTimeString(new Date());
|
}
|
msg.time = this.getLogTime(msg.CreateTime, true)
|
if (msg.CreateTime)
|
this.msgLastTime = msg.CreateTime;
|
|
msg.isMedia = false
|
if (msg.Content) {
|
let sContent = msg.Content
|
let sContent2 = msg.Content
|
let sContent3 = msg.Content
|
//console.log("Content:",sContent)
|
sContent = sContent.replace(/<audio[\s\S]*>/, '')
|
sContent2 = sContent2.replace(/<video[\s\S]*>/, '')
|
sContent3 = sContent3.replace(/<img[\s\S]*>/, '')
|
//console.log("Content replace res:",sContent)
|
if (sContent == "") {
|
let xmlDoc = new DOMParser().parseFromString(msg.Content, "text/xml");
|
let finds = xmlDoc.getElementsByTagName('audio'); //获取find节点
|
for (let i = 0; i < finds.length; i++) { //循环节点
|
let finder = finds[i];
|
let src = finder.getAttribute("src")
|
let len = finder.getAttribute("length")
|
msg.mediaSrc = src
|
// if (!msg.failedMsg && !msg.sendingMsg) {
|
// let fileserver = finder.getAttribute("data-fileserver")
|
// let src2 = await publicFileUrl(fileserver, src)
|
// msg.mediaSrc = src2
|
// }
|
msg.mediaLen = parseInt(len)
|
msg.mediaType = "audio"
|
msg.mediaWidth = 100
|
msg.mediaHeight = 20
|
msg.mediaPoster = ""
|
break;
|
}
|
msg.isMedia = true
|
//row.msg.voice.length = 03
|
} else if (sContent2 == "") {
|
let xmlDoc = new DOMParser().parseFromString(msg.Content, "text/xml");
|
let finds = xmlDoc.getElementsByTagName('video'); //获取find节点
|
for (let i = 0; i < finds.length; i++) { //循环节点
|
let finder = finds[i];
|
let src = finder.getAttribute("src")
|
let len = finder.getAttribute("length")
|
let width = finder.getAttribute("width")
|
let height = finder.getAttribute("height")
|
let poster = finder.getAttribute("poster")
|
msg.mediaSrc = src
|
msg.mediaPoster = poster
|
let nW = width
|
let nH = height
|
if (nH > 160) {
|
nH = 160
|
nW = (width * 160) / (height)
|
}
|
msg.mediaLen = parseInt(len)
|
msg.mediaType = "video"
|
msg.mediaWidth = nW
|
msg.mediaHeight = nH
|
|
break;
|
}
|
msg.isMedia = true
|
} else {
|
msg.isMedia = false
|
}
|
}
|
|
console.log("formatNewDiscuzMsg", msg)
|
return msg
|
},
|
getFileName(o) {
|
const pos = o.lastIndexOf("/");
|
return o.substring(pos + 1);
|
},
|
addTaskDiscuzMsg(guid, msgText) {
|
var _this = this;
|
return new Promise(function(resolve, reject) {
|
if (msgText.length < 1) {
|
resolve("")
|
return
|
}
|
taskLogAdd({
|
id: _this.taskId,
|
opType: "回复",
|
content: msgText
|
}).then((res) => {
|
_this.taskSendMsg(msgText);
|
_this.setSendMsgSuccess(guid, res, msgText)
|
|
resolve("")
|
}).catch((rej) => {
|
console.log("addTaskDiscuzMsg taskLogAdd failed", rej)
|
_this.setSendMsgFailed(guid)
|
_this.showError(rej)
|
reject("")
|
})
|
})
|
},
|
async setSendMsgSuccess(guid, guidNew, sText) {
|
|
let dataBody = this.msgBody
|
let curIndex = dataBody.findIndex((task, index, arr) => {
|
return task.ID == guid;
|
})
|
let msgTemp = {}
|
let app = getApp()
|
msgTemp.ID = guidNew
|
msgTemp.Creator = app.globalData.userdata.user_login
|
msgTemp.CreatorName = app.globalData.userdata.user_name
|
msgTemp.CreateTime = TaskInit.dateUtils.toDateTimeString(new Date());
|
|
msgTemp.time = this.getLogTime(msgTemp.CreateTime, true)
|
if (msgTemp.CreateTime)
|
this.msgLastTime = msgTemp.CreateTime;
|
|
msgTemp.failedMsg = false
|
msgTemp.sendingMsg = false
|
msgTemp.Content = sText
|
msgTemp = await this.getLogData(msgTemp)
|
if (curIndex == -1) {
|
dataBody.push(msgTemp)
|
} else {
|
|
dataBody[curIndex] = msgTemp
|
}
|
this.setData({
|
msgBody: dataBody
|
})
|
|
},
|
setSendMsgFailed(guid) {
|
let dataBody = this.msgBody
|
let curIndex = dataBody.findIndex((task, index, arr) => {
|
return task.ID == guid;
|
})
|
if (curIndex != -1) {
|
let msgTemp = dataBody[curIndex]
|
msgTemp.failedMsg = true
|
msgTemp.sendingMsg = false
|
dataBody[curIndex] = msgTemp
|
this.setData({
|
msgBody: dataBody
|
})
|
}
|
},
|
updateSendMsgFileProgress(guid, percent) {
|
if (percent < 0 || percent > 99)
|
return
|
let dataBody = this.msgBody
|
let curIndex = dataBody.findIndex((task, index, arr) => {
|
return task.ID == guid;
|
})
|
if (curIndex != -1) {
|
let msgTemp = dataBody[curIndex]
|
msgTemp.sendingMsg = true
|
msgTemp.percentSend = percent
|
// msgTemp = this.formatNewDiscuzMsg(msgTemp)
|
dataBody[curIndex] = msgTemp
|
this.setData({
|
msgBody: dataBody
|
})
|
}
|
},
|
|
getFileMD5(filePath, cbSuccess, cbFail) {
|
// #ifdef MP-WEIXIN
|
uni.getFileSystemManager().getFileInfo({
|
filePath,
|
digestAlgorithm: "md5",
|
success: (res) => {
|
if (typeof cbSuccess == "function") {
|
cbSuccess({
|
md5: res.digest,
|
size: res.size
|
})
|
|
}
|
},
|
fail: (res) => {
|
if (typeof cbSuccess == "function") {
|
cbFail(res)
|
|
}
|
}
|
})
|
// #endif
|
// #ifndef MP-WEIXIN
|
uni.getFileInfo({
|
filePath,
|
digestAlgorithm: "md5",
|
success: (res) => {
|
if (typeof cbSuccess == "function") {
|
cbSuccess({
|
md5: res.digest,
|
size: res.size
|
})
|
|
}
|
},
|
fail: (res) => {
|
if (typeof cbFail == "function") {
|
cbFail(res)
|
}
|
}
|
})
|
// #endif
|
},
|
uploadThumb(filePath, cbSuccess, cbFail) {
|
const _this = this;
|
this.getFileMD5(filePath, (resSuc) => {
|
|
const file = {
|
path: filePath,
|
md5: resSuc.md5,
|
size: resSuc.size,
|
public: true
|
}
|
let aaa = filePath.split('/');
|
if (aaa.length > 0) {
|
file.name = aaa[aaa.length - 1]
|
} else
|
file.name = aname
|
|
uploadFile(file, async (docSuc2) => {
|
try {
|
if (typeof cbSuccess == "function") {
|
cbSuccess(docSuc2)
|
}
|
} catch (ex) {
|
if (typeof cbFail == "function") {
|
cbFail(docFail)
|
}
|
}
|
|
}, (docFail) => {
|
if (typeof cbFail == "function") {
|
cbFail(docFail)
|
}
|
})
|
|
|
}, (resFail) => {
|
if (typeof cbFail == "function") {
|
cbFail(resFail)
|
}
|
})
|
|
},
|
|
uploadTaskMsgFile(guid, msg, isDel = false) {
|
const _this = this;
|
msg.public = true
|
uploadFile(msg, (docSuc) => {
|
let imgMsg = ''
|
if (msg.type == 'video') {
|
|
if (msg.thumb == "") {
|
imgMsg =
|
`<video controls src="${docSuc.url}" data-fileserver="${docSuc.filesflag}" length="${msg.length}" width="${msg.width}" height="${msg.height}"/>`
|
_this.addTaskDiscuzMsg(guid, imgMsg)
|
|
} else {
|
uploadThumb(msg.thumb, (docSuc2) => {
|
imgMsg =
|
`<video controls src="${docSuc.url}" poster="${docSuc2.url}" data-fileserver="${docSuc2.filesflag}" length="${msg.length}" width="${msg.width}" height="${msg.height}"/>`
|
_this.addTaskDiscuzMsg(guid, imgMsg)
|
|
}, (docFail) => {
|
imgMsg =
|
`<video controls src="${docSuc.url}" data-fileserver="${docSuc.filesflag}" length="${msg.length}" width="${msg.width}" height="${msg.height}"/>`
|
_this.addTaskDiscuzMsg(guid, imgMsg)
|
})
|
}
|
} else if (msg.type == 'audio') {
|
imgMsg =
|
`<audio controls src="${docSuc.url}" data-fileserver="${docSuc.filesflag}" length="${msg.length}"/>`
|
_this.addTaskDiscuzMsg(guid, imgMsg).then(() => {
|
if (isDel) {
|
uni.removeSavedFile({
|
filePath: path
|
})
|
}
|
})
|
} else if (msg.type == 'image') {
|
imgMsg =
|
`<img src="${docSuc.url}" data-fileserver="${docSuc.filesflag}" />`
|
|
_this.addTaskDiscuzMsg(guid, imgMsg).then(() => {})
|
} else {
|
_this.setSendMsgFailed(guid)
|
|
}
|
}, (docProgress, uploadTask) => {
|
_this.updateSendMsgFileProgress(guid, docProgress.progress)
|
},
|
(docFail) => {
|
console.log("uploadAttach uploadFile fail", docFail);
|
_this.setSendMsgFailed(guid)
|
}
|
)
|
},
|
//上传媒体
|
async uploadTaskMedia(msg, isDel = false) {
|
const _this = this;
|
let path = msg.path
|
let length = msg.length || 0
|
let bBigFile = false
|
let guid = getGuid();
|
let imgMsg = ''
|
if (msg.type == 'video') {
|
imgMsg = '<video src="' + path + '" poster="' + msg.thumb + '" width="' + msg
|
.width +
|
'" height="' +
|
msg.height + '" length="' + length + '"/>'
|
} else if (msg.type == 'audio') {
|
imgMsg = '<audio src="' + path + '" length="' + length + '" />'
|
} else if (msg.type == 'image') {
|
imgMsg =
|
'<img style="width:auto;height:auto;max-width:100%;max-height:160px;display:block;" alt="" src="' +
|
path + '" />'
|
} else {
|
return
|
}
|
let dataBody = _this.msgBody
|
let msgTemp = {}
|
msgTemp.ID = guid
|
msgTemp.failedMsg = false
|
msgTemp.sendingMsg = true
|
msgTemp.Content = imgMsg
|
msgTemp.percentSend = 0
|
msgTemp = await _this.formatNewDiscuzMsg(msgTemp)
|
dataBody.push(msgTemp)
|
this.setData({
|
msgBody: dataBody
|
})
|
this.getFileMD5(msg.path, (resSuc) => {
|
msg.md5 = resSuc.md5
|
msg.size = resSuc.size
|
_this.uploadTaskMsgFile(guid, msg, isDel)
|
}, (resFail) => {
|
_this.setSendMsgFailed(guid)
|
})
|
|
|
},
|
loadPlatform() {
|
let bRet = false
|
switch (getApp().globalData.platform) {
|
case 'android':
|
bRet = true;
|
break;
|
case 'ios':
|
bRet = true;
|
break;
|
default:
|
break;
|
}
|
this.isMobilePlatform = bRet
|
},
|
//解析需要上传的媒体文件
|
uploadMedias(tempFiles, isDel = false) {
|
let _this = this;
|
for (let i = 0; i < tempFiles.length; i++) {
|
let itemFile = tempFiles[i]
|
if (itemFile.tempFilePath)
|
itemFile.path = itemFile.tempFilePath
|
let aname = itemFile.path || itemFile.filePath || ""
|
if (itemFile.name)
|
aname = itemFile.name
|
let aaa = aname.split('/');
|
if (aaa.length > 0) {
|
itemFile.name = aaa[aaa.length - 1]
|
} else
|
itemFile.name = aname
|
|
let msg = {
|
type: itemFile.fileType,
|
size: itemFile.size,
|
path: itemFile.path,
|
name: itemFile.name,
|
length: 0,
|
}
|
if (itemFile.fileType == "image") {
|
_this.uploadTaskMedia(msg, isDel)
|
} else if (itemFile.fileType == "audio") {
|
msg.length = itemFile.duration
|
_this.uploadTaskMedia(msg, isDel)
|
} else if (itemFile.fileType == "video") {
|
msg.thumb = itemFile.thumbTempFilePath || ""
|
msg.width = itemFile.width
|
msg.height = itemFile.height
|
_this.uploadTaskMedia(msg, isDel)
|
} else {
|
showModal(itemFile.tempFilePath + '是未知类型,不能作为任务交流内容发送', '提示', false)
|
continue;
|
}
|
|
}
|
|
},
|
//获取用户头像
|
getUserImage(userID) {
|
return `${getApp().globalData.apiurl.org}/userphoto?login=${userID}`;
|
},
|
// 选择图片发送
|
clickChooseImage() {
|
uni.chooseMessageFile({
|
count: 10,
|
type: "all",
|
success: (res) => {
|
|
}
|
})
|
return
|
if (uni.canIUse('chooseMedia')) {
|
this.getMedia('album');
|
} else {
|
var _this = this
|
let app = getApp()
|
let sizeType = ['original', 'compressed']
|
//#ifdef MP-DINGTALK
|
sizeType = ['compressed']
|
// #endif
|
|
uni.chooseImage({
|
count: 10,
|
sizeType: sizeType, //original 原图,compressed 压缩图,默认二者都有
|
sourceType: ['album', 'camera'], //album 从相册选图,camera 使用相机,默认二者都有。
|
success: (res) => {
|
_this.hideDrawer();
|
let tempFiles = []
|
if (res.files) {
|
for (let i = 0; i < res.files.length; i++) {
|
let tmpFile = {
|
path: res.files[i].path,
|
size: res.files[i].size || 0,
|
fileType: "file"
|
}
|
if (TaskInit.fileUtils.isPictureType(tmpFile
|
.path)) //图片
|
{
|
tmpFile.fileType = "image"
|
}
|
tempFiles.push(tmpFile)
|
}
|
} else if (res.tempFiles) {
|
for (let i = 0; i < res.tempFiles.length; i++) {
|
let tmpFile = {
|
path: res.tempFiles[i].path,
|
size: res.tempFiles[i].size || 0,
|
fileType: "file"
|
}
|
if (TaskInit.fileUtils.isPictureType(tmpFile
|
.path)) //图片
|
{
|
tmpFile.fileType = "image"
|
}
|
tempFiles.push(tmpFile)
|
|
|
}
|
} else {
|
for (let i = 0; i < res.tempFilePaths.length; i++) {
|
|
let tmpFile = {
|
path: res.tempFilePaths[i],
|
size: 0,
|
fileType: "file"
|
}
|
if (TaskInit.fileUtils.isPictureType(tmpFile
|
.path)) //图片
|
{
|
tmpFile.fileType = "image"
|
}
|
tempFiles.push(tmpFile)
|
|
|
}
|
}
|
_this.uploadMedias(tempFiles, false)
|
|
},
|
fail: (err) => {
|
console.log('chooseImage fail', err)
|
if (_this.isMobilePlatform && err.errMsg.indexOf('cancel') <
|
0 && err.errMsg
|
.indexOf(
|
'取消') < 0) {
|
uni.getSetting({
|
success: (res) => {
|
let authStatus = res.authSetting[
|
'scope.album'];
|
if (!authStatus) {
|
showModal(
|
"需要从您的相册获取图片,请在设置界面打开相关权限",
|
"授权失败").then((
|
res) => {
|
if (res) {
|
uni.openSetting()
|
}
|
})
|
}
|
}
|
})
|
}
|
}
|
})
|
}
|
},
|
|
//拍照发送
|
clickCamera() {
|
if (uni.canIUse('chooseMedia')) {
|
this.getMedia('camera');
|
} else {
|
console.log("chooseVideo")
|
const _this = this
|
uni.chooseVideo({
|
|
sourceType: ['album', 'camera'], //album 从相册选图,camera 使用相机,默认二者都有。
|
maxDuration: 30,
|
camera: 'back',
|
success(res) {
|
_this.hideDrawer();
|
console.log("chooseVideo success", res)
|
res.fileType = "video"
|
_this.uploadMedias([res], true)
|
|
},
|
fail: (err) => {
|
console.log("chooseVideofail ", err)
|
}
|
});
|
|
}
|
|
},
|
getMedia(strType) {
|
var _this = this
|
let app = getApp()
|
console.log("chooseMedia")
|
uni.chooseMedia({
|
count: 10,
|
mediaType: ['image', 'video'],
|
sourceType: [strType], //album 从相册选图,camera 使用相机,默认二者都有。
|
sizeType: ['original'], //original 原图,compressed 压缩图,默认二者都有
|
maxDuration: 30,
|
camera: 'back',
|
success(res) {
|
console.log('chooseMedia success', res)
|
_this.hideDrawer();
|
let tempFiles = []
|
for (let i = 0; i < res.tempFiles.length; i++) {
|
let fileType = "image"
|
if (TaskInit.fileUtils.isVideoType(res.tempFiles[i].path)) //视频
|
{
|
fileType = "video"
|
tempFiles.push({
|
tempFilePath: res.tempFiles[i].path,
|
size: res.tempFiles[i].size,
|
fileType: fileType,
|
duration: 1,
|
width: 100,
|
height: 100,
|
thumbTempFilePath: ""
|
})
|
} else {
|
fileType = "image"
|
tempFiles.push({
|
tempFilePath: res.tempFiles[i].path,
|
size: res.tempFiles[i].size,
|
fileType: fileType,
|
})
|
}
|
|
|
}
|
if (strType == "camera") {
|
_this.uploadMedias(tempFiles, true)
|
} else {
|
_this.uploadMedias(tempFiles, false)
|
}
|
},
|
fail: (err) => {
|
//_this.openDrawer();
|
if (_this.isMobilePlatform && err.errMsg.indexOf('cancel') < 0) {
|
uni.getSetting({
|
success: (res) => {
|
console.log("getSetting", res)
|
let authStatus = true
|
if (strType == "album")
|
authStatus = res.authSetting[
|
'scope.album'];
|
else if (strType == "camera")
|
authStatus = res.authSetting[
|
'scope.camera'];
|
|
if (!authStatus) {
|
showModal("需要从您的相册获取图片,请在设置界面打开相关权限",
|
"授权失败").then((
|
res) => {
|
if (res) {
|
uni.openSetting()
|
}
|
})
|
}
|
}
|
})
|
}
|
}
|
})
|
},
|
|
onScroll(e) {
|
this.old.scrollTop = e.detail.scrollTop
|
},
|
|
inputBindFocus(e) {
|
var _this = this
|
// input 展示的位置
|
this.old.focusInput = true
|
if (_this.hideMore == false) {
|
_this.setData({
|
hideMore: true,
|
})
|
}
|
this.bottomHeight = (e.detail.height) + "px";
|
this.scrollTop = this.old.scrollTop
|
this.$nextTick(function() {
|
this.scrollTop = 2000000
|
});
|
|
},
|
onInputLineChange(e) {
|
console.log("inputBindLineChange", e)
|
},
|
onInput(event) {
|
console.log("onInput", event, this.$refs, this.$refs["textarea"])
|
// this.$refs.refTextarea.style.height = 'auto';
|
// this.$refs.refTextarea.style.height = `${this.$refs.refTextarea.scrollHeight}px`;
|
},
|
inputBindBlur() {
|
this.old.focusInput = false
|
// input 失去焦点,键盘隐藏,设置 input 所在盒子的 bottom 值为0
|
this.bottomHeight = "0px"
|
|
},
|
//更多功能(点击+弹出)
|
showMore() {
|
var _this = this
|
const flagVoiceMsg = _this.isVoiceMsg;
|
_this.isVoiceMsg = false;
|
|
if (flagVoiceMsg) {
|
_this.setData({
|
hideMore: false,
|
bottomHeight: '0px'
|
})
|
return
|
}
|
if (_this.hideMore) {
|
_this.focusInput = _this.old.focusInput
|
_this.$nextTick(function() {
|
_this.focusInput = false
|
});
|
_this.setData({
|
hideMore: false,
|
bottomHeight: '0px'
|
})
|
//_this.openDrawer();
|
} else {
|
_this.focusInput = _this.old.focusInput
|
_this.$nextTick(function() {
|
_this.focusInput = true
|
});
|
setTimeout(() => {
|
_this.hideMore = true;
|
}, 150);
|
}
|
},
|
// 隐藏抽屉
|
hideDrawer() {
|
console.log("hideDrawer")
|
var _this = this
|
_this.setData({
|
bottomHeight: '0px'
|
})
|
if (_this.hideMore) {
|
return
|
}
|
setTimeout(() => {
|
_this.setData({
|
hideMore: true,
|
})
|
}, 150);
|
},
|
|
clickChangeVoice() {
|
let bFlag = !this.isVoiceMsg
|
this.setData({
|
isVoiceMsg: bFlag,
|
hideMore: true,
|
bottomHeight: '0px'
|
})
|
if (!bFlag) {
|
this.focusInput = this.old.focusInput
|
this.$nextTick(function() {
|
this.focusInput = true
|
});
|
} else {
|
this.focusInput = false
|
this.old.focusInput = false
|
|
}
|
},
|
//录音开始UI效果
|
voiceStart(e) {
|
this.$refs.refAudioRecord.voiceStart(e)
|
|
},
|
// 录音中(判断是否触发上滑取消发送)
|
voiceIng(e) {
|
this.$refs.refAudioRecord.voiceIng(e)
|
},
|
// 结束录音
|
voiceEnd(e) {
|
|
this.$refs.refAudioRecord.voiceEnd(e)
|
this.voiceTis = '按住 说话';
|
},
|
// 录音被打断
|
voiceCancel() {
|
this.$refs.refAudioRecord.voiceCancel()
|
this.voiceTis = '按住 说话';
|
|
},
|
recordVioceStart() {
|
this.voiceTis = '松开 结束';
|
|
},
|
recordVioceEnd(param) {
|
|
this.uploadMedias([param]);
|
|
},
|
// 播放语音
|
playVoice(e) {
|
const _this = this
|
// #ifdef MP-DINGTALK
|
if (uni.canIUse("getBackgroundAudioManager")) {
|
|
const bgAudioManager = uni.getBackgroundAudioManager()
|
if (_this.playId == e.ID) {
|
bgAudioManager.stop()
|
return
|
}
|
bgAudioManager.onError = (err) => {
|
console.log("播放语音失败", err)
|
_this.setData({
|
playId: ""
|
})
|
this.showError("播放语音失败," + JSON.stringify(err))
|
return
|
}
|
bgAudioManager.onStop = () => {
|
console.log("播放语音停止事件")
|
_this.setData({
|
playId: ""
|
})
|
return
|
}
|
bgAudioManager.onEnded = () => {
|
console.log("播放语音结束事件")
|
_this.setData({
|
playId: ""
|
})
|
return
|
}
|
_this.setData({
|
playId: e.ID
|
})
|
bgAudioManager.title = '语音';
|
bgAudioManager.singer = '暂无';
|
bgAudioManager.src = e.mediaSrc;
|
bgAudioManager.play()
|
}
|
// #endif
|
// #ifndef MP-DINGTALK
|
audioContext.src = e.mediaSrc;
|
_this.setData({
|
playId: e.ID,
|
})
|
_this.$nextTick(function() {
|
audioContext.play();
|
});
|
// #endif
|
|
|
},
|
// 播放视频
|
playVideo(e) {
|
|
uni.navigateTo({
|
url: "/pages/common/videoPage?url=" + encodeURIComponent(e.mediaSrc)
|
})
|
},
|
// 预览图片
|
previewImage(e) {
|
uni.previewImage({
|
current: e,
|
urls: this.msgImages,
|
})
|
},
|
addPageData() {
|
var _this = this;
|
_this.pindex += 1;
|
_this.loadWorkLog().then((resData) => {
|
|
_this.msgBody = [...resData, ..._this.msgBody]
|
})
|
|
},
|
scrollStart() {
|
console.log("scrollStart", this.ptotal, this.pindex, new Date())
|
var _this = this;
|
_this.showLoadMore = true;
|
|
if (_this.ptotal <= _this.pindex) {
|
_this.showLoadMore = false;
|
_this.loadMoreText = ""
|
return
|
}
|
_this.loadMoreText = "加载中..."
|
setTimeout(() => {
|
_this.addPageData();
|
}, 500)
|
|
},
|
scrollEnd() {},
|
/* 发送消息 */
|
async taskSendMsg(desc) {
|
try {
|
const curUserId = getCurUserId()
|
let descContent = desc.replace(/<[\w\W]+?>/g, "");
|
let sender = [];
|
/* 创建人 */
|
if (
|
this.taskInfo.Creator &&
|
this.taskInfo.Creator != curUserId &&
|
!sender.includes(this.taskInfo.Creator)
|
)
|
sender.push(this.taskInfo.Creator);
|
/* 执行人 */
|
if (
|
this.taskInfo.Takeon &&
|
this.taskInfo.Takeon != curUserId &&
|
!sender.includes(this.taskInfo.Takeon)
|
)
|
sender.push(this.taskInfo.Takeon);
|
/* 负责人 */
|
if (
|
this.taskInfo.Pic &&
|
this.taskInfo.Pic != curUserId &&
|
!sender.includes(this.taskInfo.Pic)
|
)
|
sender.push(this.taskInfo.Pic);
|
/*审核人 */
|
const auditorSet = this.taskInfo.AuditorSet;
|
if (auditorSet)
|
auditorSet.forEach((a) => {
|
if (a.ID && a.ID != curUserId && !sender.includes(a.ID))
|
sender.push(a.ID);
|
});
|
/* 相关人 */
|
const relPerson = this.taskInfo.RelPerson;
|
if (relPerson)
|
relPerson.forEach((a) => {
|
if (a.id && a.id != this.curUserId && !sender.includes(a.id))
|
sender.push(a.id);
|
});
|
let content = "任务讨论";
|
content += `\n任务:${this.taskInfo.Name}`;
|
if (this.taskInfo.PrjName)
|
content += `\n项目:${this.taskInfo.PrjName}`;
|
content += `\n内容:${descContent}`;
|
content += `\n发送者:${getCurUserName()}`;
|
content += ` 日期:${TaskInit.dateUtils.toShortDateTimeString(new Date())} `;
|
|
if (sender.length > 0) {
|
const paramSendMsg = {
|
sendto: sender.join(";"),
|
msgobjtype: "1",
|
ownerid: this.taskId,
|
msgtype: 2,
|
title: `任务讨论通知`,
|
content: content,
|
contenttype: "txt",
|
};
|
await sendMsg(paramSendMsg);
|
|
|
}
|
} catch (error) {
|
this.showError(error);
|
}
|
},
|
|
showError(ex) {
|
let tip = typeof ex === 'string' ? ex :( ex.message || ex.err_msg || ex.errMsg || ex.err_info || "")
|
|
showModal(tip, "提示", false)
|
},
|
}
|
}
|
</script>
|
|
<style lang="less">
|
.uni-task-chat {
|
display: flex;
|
flex-direction: column;
|
|
.chat-container {
|
display: flex;
|
flex: 1;
|
font-size: 14px;
|
padding: 0px 1% 8px 1%;
|
width: 98%;
|
height: calc(100% - 500px);
|
}
|
|
.uni-panel-msglist {
|
display: flex;
|
width: 750rpx;
|
background-color: transparent;
|
flex-direction: column !important;
|
}
|
|
.uni-panel-popup-layer {
|
display: flex;
|
transition: all .15s linear;
|
width: 96%;
|
height: 54px;
|
padding: 12px 2% 16px;
|
background-color: #f1f1f1;
|
border-top: 1px solid #ddd;
|
//position: fixed;
|
z-index: 102;
|
//top: 100%;
|
}
|
|
.uni-panel-showLayer {
|
transform: translate3d(0, -84px, 0);
|
}
|
|
.uni-panel-popup-more-layer {
|
display: flex;
|
width: 100%;
|
height: 54px;
|
}
|
|
.uni-panel-popup-list {
|
width: 100%;
|
display: flex;
|
flex-wrap: wrap;
|
}
|
|
.uni-panel-popup-list-box {
|
width: 40px;
|
height: 40px;
|
border-radius: 8px;
|
background-color: #fff;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
margin: 5px 8px 5px 8px;
|
}
|
|
.uni-panel-popup-list-box .icon {
|
font-size: 32px;
|
}
|
|
.uni-panel-msg-bottom {
|
display: flex;
|
flex-direction: row;
|
width: 100%;
|
z-index: 101;
|
align-items: flex-end;
|
justify-content: space-between;
|
padding: 8px;
|
|
background: #f1f1f1; // //pink;
|
|
}
|
|
.uni-panel-msg-text {
|
display: flex;
|
width: calc(100% - 120px);
|
margin-bottom: 2px;
|
border: 1px solid #eeeeec;
|
border-radius: 5px;
|
background: #FFF;
|
font-size: 15px;
|
}
|
|
.uni-panel-msg-text textarea {
|
display: flex;
|
width: 96%;
|
padding: 5px;
|
min-height: 24px;
|
max-height: 150px;
|
}
|
|
|
.uni-panel-btn-sound {
|
flex: 1;
|
height: 35px;
|
line-height: 2.1;
|
font-size: 16px;
|
text-align: center;
|
margin: 0 10px;
|
|
}
|
|
|
.uni-panel-btn-left {
|
display: flex;
|
height: 100%;
|
|
.uni-panel-btn-voice {
|
display: flex;
|
margin-left: 12px;
|
font-size: 28px;
|
justify-content: center;
|
align-items: center;
|
border-radius: 10rpx;
|
padding: 4px;
|
margin-bottom: 2px;
|
}
|
}
|
|
.uni-panel-btn-right {
|
display: flex;
|
height: 100%;
|
align-items: center;
|
|
.uni-panel-btn-send {
|
display: flex;
|
font-size: 15px !important;
|
justify-content: center;
|
border-radius: 10rpx;
|
margin-right: 12px;
|
padding: 0 10rpx;
|
color: #fff;
|
background-color: #00aaff;
|
}
|
|
.uni-panel-btn-add {
|
display: flex;
|
font-size: 28px;
|
padding: 4px;
|
justify-content: center;
|
align-items: center;
|
margin-right: 12px;
|
margin-bottom: 2px;
|
}
|
}
|
|
|
|
.hidden {
|
display: none !important;
|
}
|
|
/* loadmore */
|
.uni-loadmore {
|
height: 80rpx;
|
line-height: 80rpx;
|
text-align: center;
|
padding-bottom: 30rpx;
|
}
|
}
|
</style>
|