Files
Arbitrate-FrontendH5/src/views/room.vue
T

685 lines
19 KiB
Vue

<template>
<div class="page">
<div class="roompage" @mouseover="mouseHover" v-if="modileFlag">
<div class="txtContent">
<el-tag type="danger" @click="txtContent">会议内容</el-tag>
</div>
<div :class="userClass" :style="{ height: userHeight }" id="localStream">
<div class="userName">{{ userId }}</div>
</div>
<div :class="userClass" :style="{ height: userHeight }" v-for="(item, index) in userList" :key="index" :id="item">
<div class="userName">{{ item }}</div>
</div>
<div class="footer">
<roomFooter @exitRoom="exitRoom" :roomId="roomId"></roomFooter>
</div>
</div>
<div class="roomPhone" v-if="!modileFlag">
<div class="header">
<roomFooterPhone @exitRoom="exitRoom"></roomFooterPhone>
</div>
<div class="bodyVideo">
<div :class="userClassPhone" id="localStream">
<div class="userNamePhone">{{ userId }}</div>
</div>
<div :class="userClassPhone" v-for="(item, index) in userList" :key="index" :id="item">
<div class="userNamePhone">{{ item }}</div>
</div>
</div>
</div>
<!-- 语音转文字弹窗 -->
<el-drawer title="会议内容" :visible.sync="textVisible" :modal="false">
<div style="margin-left: 20px; margin-bottom: 10px">
<div style="
width: 100%;
display: flex;
justify-content: space-around;
margin-bottom: 10px;
">
<el-upload ref="upload" :limit="1" action="https://api.xayunmei.com/tiaojieapi/video/upload"
:headers="headers" :data="filedata" :on-change="beforeUpload" :on-success="handlSuccess"
:file-list="fileList" v-if="appFlag">
<el-button slot="trigger" size="small" type="primary">申请人上传证据</el-button>
</el-upload>
<el-upload v-if="resFlag" ref="upload1" :limit="1" action="https://api.xayunmei.com/tiaojieapi/video/upload"
:headers="headers1" :data="filedata1" :on-change="beforeUpload1" :on-success="handlSuccess1"
:file-list="fileList1">
<el-button slot="trigger" size="small" type="primary">被申请人上传证据</el-button>
</el-upload>
<el-upload v-if="editFlag" ref="upload3" :limit="1" action="https://api.xayunmei.com/tiaojieapi/video/upload"
:headers="headers3" :data="filedata3" :on-change="beforeUpload3" :on-success="handlSuccess3"
:file-list="fileList3" accept=".doc,.docx">
<el-button slot="trigger" size="small" type="primary">上传调解书</el-button>
</el-upload>
</div>
<div class="list">
<div class="applicant" v-if="applicantFile.length > 0">
<div>申请人证据</div>
<div style="color: #104fad; cursor: pointer" v-for="(item, index) in applicantFile" :key="index"
@click="preview(item, 0)">
{{ item.annexName }}
</div>
</div>
<div class="res" v-if="resFile.length > 0">
<div>被申请人证据</div>
<div style="color: #104fad; cursor: pointer" v-for="(item, index) in resFile" :key="index"
@click="preview(item, 0)">
{{ item.annexName }}
</div>
</div>
<div class="mediate" v-if="mediateFile.length > 0">
<div>调解书</div>
<div style="color: #104fad; cursor: pointer" v-for="(item, index) in mediateFile" :key="index"
@click="preview(item, 1)">
{{ item.annexName }}
</div>
</div>
</div>
</div>
<quill-editor ref="myQuillEditor" v-model="contentValue" :options="editorOption" @blur="onEditorBlur($event)"
@focus="onEditorFocus($event)" @ready="onEditorReady($event)"></quill-editor>
<el-button class="updataBtn" @click="updataClick" type="primary" :disabled="!updataFlag">确认修改内容</el-button>
</el-drawer>
</div>
</template>
<script>
import { getUsersig, reserveConferenceList } from "@/api/home";
import {
secretaryRoleByUserId,
htmlToPDF,
selectById,
selectRoleMenuByCaseId,
getMenuPermsByUser,
} from "@/api/room";
import { getWidth, getHeight, getWidthPhone, getModile } from "@/utils/utils";
import roomFooter from "./components/roomFooter.vue";
import roomFooterPhone from "./components/footerPhone.vue";
import ASR from "../utils/asr.esm.js";
import TRTC from "trtc-sdk-v5";
let trtc = null;
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import { quillEditor } from "vue-quill-editor";
export default {
name: "App",
components: {
roomFooter,
roomFooterPhone,
quillEditor,
},
data() {
return {
resFlag: null,
appFlag: null,
userClass: "userVideo5",
userClassPhone: "userVideoPhone",
userList: [],
userHeight: "100%",
userPhoneHeight: "92%",
userSign: "",
roomId: "",
userId: null,
id: null,
showFlag: false,
modileFlag: false,
localStreamAsr: null,
contentValue: "",
textVisible: false,
editorOption: {
// Some Quill options...
},
asrList: {},
updataFlag: true,
token: "",
applicantFile: [],
resFile: [],
mediateFile: [],
headers: {
// Authorization: "Bearer " + token,
Authorization: "",
},
filedata: {
annexType: 2,
officeFlag: 0,
caseId: null,
},
fileList: [],
headers1: {
// Authorization: "Bearer " + token,
Authorization: "",
},
filedata1: {
annexType: 12,
officeFlag: 0,
caseId: null,
},
fileList1: [],
headers3: {
// Authorization: "Bearer " + token,
Authorization: "",
},
filedata3: {
annexType: 7,
officeFlag: 0,
caseId: null,
},
fileList3: [],
editFlag: false,
};
},
methods: {
/**获取当前用户操作权限 */
getMenuPermsByUserFn() {
getMenuPermsByUser().then((res) => {
// console.log(res.perms, "KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK");
this.editFlag = res.perms.includes("caseManagement:list:editOffice");
});
},
beforeUpload(file, fileList) {
this.fileList = fileList;
if (file.name.indexOf("docx") == -1) {
this.filedata.officeFlag = 0;
} else {
this.filedata.officeFlag = 1;
}
},
// 文件上传成功
handlSuccess(res, file) {
this.$message({
message: "上传成功",
type: "success",
});
this.$refs.upload.clearFiles();
this.selectByIdFn(this.caseId);
},
beforeUpload1(file, fileList) {
this.fileList1 = fileList;
if (file.name.indexOf("docx") == -1) {
this.filedata1.officeFlag = 0;
} else {
this.filedata1.officeFlag = 1;
}
},
// 文件上传成功
handlSuccess1(res, file) {
this.$message({
message: "上传成功",
type: "success",
});
this.$refs.upload1.clearFiles();
this.selectByIdFn(this.caseId);
},
beforeUpload3(file, fileList) {
this.fileList3 = fileList;
this.filedata3.officeFlag = 1;
},
// 文件上传成功
handlSuccess3(res, file) {
this.$message({
message: "上传成功",
type: "success",
});
this.$refs.upload3.clearFiles();
this.selectByIdFn(this.caseId);
},
preview(item, flag) {
if (item.onlyOfficeFileId) {
this.$router.push({
path: "/onlyoffice",
query: { id: item.onlyOfficeFileId, flag: flag },
});
} else {
window.open(
"https://api.xayunmei.com/tiaojieapi" + item.annexPath,
"_black"
);
}
},
// 点击提交修改后的内容
updataClick() {
this.contentValue = this.contentValue.replace(/<br>/g, "");
htmlToPDF({
caseId: this.caseId,
htmlContent: this.contentValue,
}).then((res) => {
if (res.code == 200) {
this.$message({
message: "提交修改成功",
type: "success",
});
} else {
this.$message({
message: res.msg,
type: "error",
});
}
});
},
onEditorBlur(quill) {
console.log("editor blur!", this.content, quill);
},
onEditorFocus(quill) {
if (!this.updataFlag) {
quill.enable(false);
} else {
quill.enable(true);
}
console.log("editor focus!", quill);
},
onEditorReady(quill) {
console.log("editor ready!", quill);
},
onEditorChange({ quill, html, text }) {
console.log("editor change!", quill, html, text);
this.content = html;
},
// 点击显示修改的文本框
txtContent() {
this.textVisible = true;
setInterval(() => {
this.selectByIdFn(this.caseId);
}, 8000);
this.selectRoleMenuByCaseIdFn(this.caseId);
this.getMenuPermsByUserFn();
},
/** 获取证据列表 */
selectByIdFn(id) {
selectById(id).then((res) => {
this.applicantFile = [];
this.resFile = [];
this.mediateFile = [];
let fileList = res.data.caseAttachList;
fileList.forEach((item) => {
if (item.annexType == 2) {
this.applicantFile.push(item);
} else if (item.annexType == 12) {
this.resFile.push(item);
} else if (item.annexType == 7) {
this.mediateFile.push(item)
}
});
});
},
// 鼠标滑过显示操作栏
mouseHover() {
this.showFlag = true;
setTimeout(() => {
this.showFlag = false;
}, 4000);
},
async exitRoom() {
// // 关闭识别
Object.keys(this.asrList).forEach((key) => {
this.asrList[key].stop();
});
this.localStreamAsr.stop();
await trtc.exitRoom();
await trtc.updateLocalVideo({ publish: false });
await trtc.updateLocalAudio({ publish: false });
await trtc.destroy();
this.$router.push({
name: "Home",
});
},
// 获取拉流信息
getPushVideo() {
trtc.on(TRTC.EVENT.REMOTE_VIDEO_AVAILABLE, (event) => {
const userId = event.userId;
const streamType = event.streamType;
this.userList.push(userId);
setTimeout(() => {
let aoido = trtc.getAudioTrack(userId);
this.asrList[this.userList[this.userList.length - 1]] = new ASR({
secretKey: "INDrIXcT8YmomZBcsy0oNirnU0LTN4X7",
secretId: "AKID3xfHgroY4MQHvLXUXMwIQL1UjmbBX1Tv",
appId: 1304001529,
engine_model_type: "16k_zh",
voice_format: 1,
needvad: 1,
audioTrack: aoido,
});
this.asrList[this.userList[this.userList.length - 1]].start();
// 开始识别
this.asrList[
this.userList[this.userList.length - 1]
].OnRecognitionStart = (res) => {
console.log("远端流:开始识别", res);
};
this.asrList[this.userList[this.userList.length - 1]].OnError = (
res
) => {
console.log("远端流:识别失败", res);
};
// 一句话结束
this.asrList[this.userList[this.userList.length - 1]].OnSentenceEnd =
(res) => {
console.log("远端流:一句话结束", res);
this.contentValue =
this.contentValue +
`<h2>${userId}</h2>` +
`<span>${res.result.voice_text_str}</span>`;
};
}, 2000);
if (this.modileFlag) {
this.userClass = getWidth(this.userList);
this.userHeight = getHeight(this.userList);
} else {
this.userClassPhone = getWidthPhone(this.userList);
}
setTimeout(() => {
trtc.startRemoteVideo({ userId, streamType, view: `${userId}` });
});
// })
});
},
// 删除退出会议人员列表
deletePushVideo() {
trtc.on(TRTC.EVENT.REMOTE_VIDEO_UNAVAILABLE, (event) => {
const userId = event.userId;
if (this.hostId == userId) {
alert("主持人已经解散会议");
this.$router.push({
name: "Home",
});
this.userList = [];
return;
}
let deleteIndex = this.userList.indexOf(userId);
this.userList = this.userList.filter((item) => item !== userId);
if (deleteIndex !== -1) {
this.userList.splice(deleteIndex, 1);
}
if (this.modileFlag) {
this.userClass = getWidth(this.userList);
this.userHeight = getHeight(this.userList);
} else {
this.userClassPhone = getWidthPhone(this.userList);
}
Object.keys(this.asrList).forEach((key) => {
this.asrList[userId].stop();
});
});
},
// 根据caseId查询房间相关信息
reserveConferenceListFn(data) {
reserveConferenceList(data).then((res) => {
this.hostId = res.data[0].userName;
});
},
// 根据userid查询是否是秘书角色
secretaryRoleByUserIdFn(data, data1) {
secretaryRoleByUserId(data, data1).then((res) => {
this.updataFlag = res.data.isSecretaryRole;
});
},
/**获取申请人被申请人权限 */
selectRoleMenuByCaseIdFn(caseId) {
selectRoleMenuByCaseId(caseId).then((res) => {
if (res.appFlag && res.appFlag == "1") {
this.appFlag = true;
this.resFlag = false;
} else if (res.resFlag && res.resFlag == "1") {
this.resFlag = true;
this.appFlag = false;
}
});
},
},
computed: {
editor() {
return this.$refs.myQuillEditor.quill;
},
},
async mounted() {
// 判断设备类型
this.modileFlag = getModile();
let roomId = this.$route.query.roomId;
this.roomId = this.$route.query.roomId;
let userId = this.$route.query.userId;
this.userId = this.$route.query.userId;
this.caseId = this.$route.query.caseId;
this.id = this.$route.query.id;
this.token = this.$route.query.token;
this.headers.Authorization = "Bearer " + this.token;
this.headers1.Authorization = "Bearer " + this.token;
this.headers3.Authorization = "Bearer " + this.token;
this.filedata.caseId = this.caseId;
this.filedata1.caseId = this.caseId;
this.filedata3.caseId = this.caseId;
window.sessionStorage.setItem("token", this.token);
window.sessionStorage.setItem("userId", this.id);
this.secretaryRoleByUserIdFn(this.id, this.caseId);
// 获取主持人的userId
this.reserveConferenceListFn(this.caseId);
const sdkAppId = 1600011167;
// 获取usersign
await getUsersig(userId).then((res) => {
this.userSign = res.msg;
});
this.getPushVideo();
this.deletePushVideo();
try {
await trtc.enterRoom({
roomId: Number(roomId),
scene: "rtc",
sdkAppId,
userId,
userSig: this.userSign,
});
await trtc.startLocalVideo({
view: document.getElementById("localStream"), // 在 DOM 中的 elementId 为 localStream 的标签上预览视频。
});
await trtc.startLocalAudio();
console.log("进房成功");
this.$message({
message: "进房成功",
type: "success",
});
} catch (error) {
console.error("进房失败 " + error);
this.$message({
message: "进房失败",
type: "error",
});
// this.$router.push({
// name: 'Home'
// })
}
this.localStreamAsr = new ASR({
secretKey: "INDrIXcT8YmomZBcsy0oNirnU0LTN4X7",
secretId: "AKID3xfHgroY4MQHvLXUXMwIQL1UjmbBX1Tv",
appId: 1304001529,
engine_model_type: "16k_zh",
voice_format: 1,
needvad: 1,
audioTrack: trtc.getAudioTrack(),
});
this.localStreamAsr.start();
// 开始识别
this.localStreamAsr.OnRecognitionStart = (res) => {
console.log("本地流:开始识别", res);
};
this.localStreamAsr.OnError = (res) => {
console.log("本地流:识别失败", res);
};
// 一句话结束
this.localStreamAsr.OnSentenceEnd = (res) => {
console.log("本地流:一句话结束", res);
// this.contentValue = `<h2>${this.userId}</h2>` + `<span>${res.result.voice_text_str}</span>`;
this.contentValue =
this.contentValue +
`<h2>${this.userId}</h2>` +
`<span>${res.result.voice_text_str}</span>`;
};
},
created() {
trtc = TRTC.create();
},
};
</script>
<style scoped>
.roompage {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: space-around;
flex-wrap: wrap;
position: relative;
}
.txtContent {
width: 100px;
height: 50px;
position: absolute;
right: 5px;
top: 20px;
z-index: 10;
cursor: pointer;
}
.userVideo,
.userVideo1,
.userVideo2,
.userVideo3,
.userVideo4,
.userVideo5 {
position: relative;
}
.userVideo5 {
width: 100%;
}
.userVideo {
width: 48%;
}
.userVideo1 {
width: 33%;
}
.userVideo2 {
width: 33%;
}
.userVideo3 {
width: 33%;
}
.userVideo4 {
width: 100%;
}
.footer {
width: 100%;
height: 10%;
background: rgb(46 43 43 / 90%);
position: absolute;
bottom: 0;
z-index: 10;
}
.userName {
border-radius: 10px;
width: 90px;
height: 40px;
text-align: center;
line-height: 40px;
background-color: black;
position: absolute;
right: 0;
bottom: 0;
z-index: 9;
color: #ffffff;
}
.userNamePhone {
border-radius: 10px;
min-width: 20%;
height: 30px;
line-height: 30px;
text-align: center;
background-color: black;
font-size: 12px;
position: absolute;
right: 0;
bottom: 0;
z-index: 9;
color: #ffffff;
}
.header {
width: 100%;
height: 8%;
background-color: #716c6c;
display: flex;
flex-direction: row-reverse;
align-items: center;
}
.roomPhone {
width: 100%;
height: 100vh;
}
.bodyVideo {
width: 100%;
height: 92%;
display: flex;
flex-wrap: wrap;
/* justify-content: space-between; */
}
.userVideoPhone {
width: 100%;
height: 100%;
background-color: yellow;
position: relative;
}
.userVideoPhone1 {
width: 50%;
flex-basis: calc(33.333% - 3px);
max-width: calc(33.333% - 3px);
height: 200px;
/* height: 0; */
/* padding-bottom: calc(33.333% - 3px); */
margin-bottom: 3px;
position: relative;
}
.quill-editor {
height: 70%;
}
.updataBtn {
width: 100%;
position: absolute;
bottom: 8px;
}
.fileList {
/* max-height: 300px; */
/* overflow-y: scroll; */
}
.list {
display: flex;
flex-wrap: wrap;
}
.applicant,
.res,
.mediate {
width: 100%;
margin-left: 20px;
margin-bottom: 10px;
color: #38393b;
}
</style>