需求:将海康的监控视频集成到钉钉的微应用中播放。
1、整体实现方案
1)钉钉开放平台创建一个应用,该应用可以在钉钉手机端的工作台使用。
2)前端功能和后台接口开发完成。
3)项目发布到服务器后,将项目地址配置为该应用的访问地址,此时需要外网访问地址。
2、前端实现方案
1)首页访问时首先获取钉钉的授权码,拿到授权码获取token
2)拿到token调用监控列表接口得到监控列表
3)点击相应的监控,获取播放url,集成海康提供的h5player播放视频
3、难点步骤
3.1 获取钉钉免登授权码
参考钉钉文档,免登授权码 - 钉钉开放平台
在utils文件夹中创建一个dingding.js,将getQuthCode方法导出,在首页调用,代码如下:
// dingding.js
import * as dd from 'dingtalk-jsapi';
import { getTokenData } from '@/api/loginApi'
dd.ready(function () {
var corpId = '';
// 获取corpId
var currentUrl = document.location.toString()
let list = currentUrl.split('corpId=')
if (list.length >1){
for (let i=0;i<list[1].length;i++){
if ('&#/'.includes(list[1].charAt(i))){
break
}
corpId+=list[1].charAt(i)
}
localStorage.setItem('corpId',corpId)
}
});
const getQuthCode=()=>{
//使用SDK 获取免登授权码
return new Promise((resolve, reject)=>{
let corpId=localStorage.getItem('corpId')
dd.runtime.permission.requestAuthCode({
corpId: corpId,
onSuccess:async function (result) {
let code = result.code; // code即为免登授权码
// 获取token
let token = await getTokenData(code)
localStorage.setItem('token', token);
resolve()
}
});
})
}
export default {
getQuthCode
}
// 首页中的部分代码
import dd from "@/utils/dingding";
const initData = async () => {
dd.getQuthCode().then(async (res) => {
// some code
})
}
需要在钉钉的环境下进行调试才能获取到免登授权码,钉钉提供多种调试方法,参考:微应用四端调试工具—网页版 - 钉钉开放平台
我用的是钉钉的四端调试能力,参考:开发者后台统一登录 - 钉钉统一身份认证
选择创建的应用,然后再免登地址中输入前端项目的运行地址,例如:http://localhost:9000?corpId=$CORPID$。地址后边加上?corpId=$CORPID$,是为了获取corpId。输入地址后,点击钉钉端内调试,即可调起钉钉的窗口。
3.2 播放视频
在海康的官网中下载demo,地址:海康开放平台
将demo中的这些文件,复制到自己的项目中。
复制到public目录下,我这里单独建了一个h5player的文件夹
在index.html中引入h5player.min.js
在播放页编写代码,注意播放器的dom元素的id必须为player,完整代码如下:
<template>
<div class="player-box">
<!-- 此处id必须为player -->
<div id="player"></div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, computed, nextTick, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { getPreviewUrl } from '@/api/monitorApi'
const IS_MOVE_DEVICE = document.body.clientWidth < 992 // 是否移动设备
const MSE_IS_SUPPORT = !!window.MediaSource // 是否支持mse
const tabActive = MSE_IS_SUPPORT ? 'mse' : 'decoder'
const mode = computed(() => {
return tabActive === 'mse' ? 0 : 1
})
const router = useRouter()
const route = useRoute()
const currentUrl = ref('')
const getUrl = async () => {
let code = route.query.code
// 获取播放视频的url
let url = await getPreviewUrl(code)
currentUrl.value = url
console.log('url', url)
}
const player = ref(null)
onMounted(() => {
getUrl()
nextTick(() => {
createPlayer()
})
window.addEventListener('resize', () => {
player.value && player.value.JS_Resize()
})
})
onBeforeUnmount(() => {
stopPlay()
})
watch(currentUrl, () => {
// 得到url后播放
console.log('change')
realplay()
})
// 初始化播放器
const createPlayer = () => {
player.value = new window.JSPlugin({
szId: 'player',
szBasePath: "/js/h5player/", // 此处配置h5player.min.js所在的文件目录
iMaxSplit: 1,
// iMaxSplit: 4,
iCurrentSplit: 2,
// iCurrentSplit: IS_MOVE_DEVICE ? 1 : 2,
bSupporDoubleClickFull: true,
openDebug: true,
oStyle: {
borderSelect: IS_MOVE_DEVICE ? '#409EFF' : '#409EFF',
}
})
// 事件回调绑定
player.value.JS_SetWindowControlCallback({
windowEventSelect: function (iWndIndex) { //插件选中窗口回调
console.log('windowSelect callback: ', iWndIndex);
},
pluginErrorHandler: function (iWndIndex, iErrorCode, oError) { //插件错误回调
console.log('插件错误回调pluginError callback: ', iWndIndex, iErrorCode, oError);
// play()
},
windowEventOver: function (iWndIndex) { //鼠标移过回调
console.log('鼠标移过回调', iWndIndex);
},
windowEventOut: function (iWndIndex) { //鼠标移出回调
//console.log(iWndIndex);
},
windowEventUp: function (iWndIndex) { //鼠标mouseup事件回调
//console.log(iWndIndex);
console.log('鼠标mouseup事件回调')
// fullScreen(false)
},
windowFullCcreenChange: function (bFull) { //全屏切换回调
console.log('全屏切换回调fullScreen callback: ', bFull);
if (!bFull) {
console.log('退出全屏')
}
},
firstFrameDisplay: function (iWndIndex, iWidth, iHeight) { //首帧显示回调
console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);
},
performanceLack: function () { //性能不足回调
console.log('performanceLack callback: ');
stopPlay()
}
});
player.value.JS_Resize(360, 260).then(
() => {
console.info('JS_Resize success')
},
(err) => {
console.info('JS_Resize failed')
}
);
}
// 开始播放
const realplay = (url, index) => {
let playURL = currentUrl.value
let modeDefault = 0 //mode.value
player.value.JS_Play(playURL, { playURL, modeDefault }, 0).then(
() => {
console.log('realplay success 播放成功')
},
e => {
console.error('playerror', e)
}
)
}
// 停止播放
const stopPlay = () => {
player.value.JS_StopRealPlayAll().then(() => {
console.log('JS_StopRealPlayAll success 停止播放')
}, err => {
console.log('JS_StopRealPlayAll fail', err)
})
}
// 整体全屏
const fullScreen = (type) => {
player.value.JS_FullScreenDisplay(type).then(() => {
console.log('JS_FullScreenDisplay success ')
}, err => {
console.log('JS_FullScreenDisplay fail', err)
})
}
</script>
<style lang="scss">
.player-box {
display: flex;
justify-content: center;
}
</style>
3.3 发布
将前端项目和后端项目发布到服务器,在钉钉开放平台的后台配置该应用的访问地址,也就是项目的访问地址即可。