序言:
最近由国产化项目,需要全套信创产品序列,涉及国产化软件和硬件的整合集成,后端工程是spring boot2,前端工程是vue2 ,记录分享一下:
1、国产化操作系统统信uos
后端java工程spring boot集成pom.xml
<properties><spring-boot.version>2.7.3</spring-boot.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.version>3.8.1</maven.compiler.version><velocity.version>1.7</velocity.version><commons.version>1.10</commons.version><spring.checkstyle.version>0.0.34</spring.checkstyle.version><git.commit.version>2.2.5</git.commit.version><swagger.fox.version>3.0.0</swagger.fox.version><jasypt.version>3.0.4</jasypt.version><ttl.version>2.12.6</ttl.version><docker.registry>172.17.0.111</docker.registry><docker.host>http://172.17.0.111:2375</docker.host><docker.namespace>library</docker.namespace><docker.username>admin</docker.username><docker.password>Harbor12345</docker.password><docker.plugin.version>0.33.0</docker.plugin.version><!-- 默认忽略docker构建 --><docker.skip>false</docker.skip></properties>
2、瀚高数据库集成
pom.xml
<!-- 瀚高数据库驱动 --><!-- https://mvnrepository.com/artifact/com.highgo/HgdbJdbc --><dependency><groupId>com.highgo</groupId><artifactId>HgdbJdbc</artifactId><version>6.2.4</version></dependency>
application-dev.yml
## 数据源
spring:cache:cache-names: menu_details,user_details,role_detailsdatasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:
# driver-class-name: com.mysql.cj.jdbc.Driver
# username: ${MYSQL_USER:root}
# password: ${MYSQL_PWD:root}
# url: jdbc:mysql://${MYSQL_HOST:ewaycloud-jw-mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:ewaycloud_json_flow}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true
# validation-query: SELECT 1# driver-class-name: dm.jdbc.driver.DmDriver
# username: SYSDBA
# password: C##qlywadmin2023
# url: jdbc:dm://127.0.0.1:5236?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8driver-class-name: com.highgo.jdbc.Driver# 本机url: jdbc:highgo://127.0.0.1:5866/highgousername: highgopassword: Password@123
3、东方通中间件
pom.xml
<!-- 东方通依赖 --><dependency><groupId>com.tongweb</groupId><artifactId>tongweb-gmssl</artifactId><version>1.0.0</version></dependency><dependency><groupId>com.tongweb.springboot</groupId><artifactId>tongweb-spring-boot-starter-2.x</artifactId><version>7.0.E.6_P6</version></dependency><dependency><groupId>com.tongweb.springboot</groupId><artifactId>tongweb-spring-boot-data-jdbc-starter-2.x</artifactId><version>7.0.E.6_P6</version></dependency><dependency><groupId>com.tongweb.springboot</groupId><artifactId>tongweb-spring-boot-websocket-2.x</artifactId><version>7.0.E.6_P6</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>
application-dev.yml
# 东方通 数据源
#server:
# tongweb:
# datasource:
# type: com.tongweb.hulk.HulkDataSource
# url: jdbc:highgo://localhost:5866/highgo
# username: highgo
# password: Password@123
# driver-class-name: com.highgo.jdbc.Driver
# license:
# typy: file
# path: classpath:license.dat
# #表示SSL功能开启,使用国密SSL,首先确保SSL功能开启。
# ssl:
# enabled: false
# #表示ssl通信协议使用国密通信协议。
# protocol: GMSSLv1.1
# #配置加密密钥库文件
# key-store: classpath:sm2.enc.pfx
# #配置加密密钥库文件的密码
# key-store-password: xxxx
# #配置加密密钥库文件的格式
# key-store-type: PKCS12
# #配置签名密钥库文件,路径支持绝对路径和classpath
# trust-store: classpath:sm2.sig.pfx
# #配置签名密钥库文件的密码
# trust-store-password: xxxx
# #配置签名密钥库文件的格式
# trust-store-type: PKCS12
4、卫士通密码机
pom.xml
<!--卫士通密码机相关--><dependency><groupId>org.apache.mina</groupId><artifactId>mina-core</artifactId><version>2.0.5</version></dependency><dependency><groupId>com.weston</groupId> <!--自定义--><artifactId>wst-hsm-api</artifactId> <!--自定义--><version>1.7.8</version> <!--自定义--><scope>system</scope> <!--system,类似provided,需要显式提供依赖的jar以后,Maven就不会在Repository中查找它--><systemPath>${project.basedir}/src/main/resources/lib/wst-hsm-api-1.7.8.jar</systemPath><!--项目根目录下的lib文件夹下--></dependency>
<!-- <dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-log4j12</artifactId>-->
<!-- <version>1.7.25</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-api</artifactId>-->
<!-- <version>1.7.25</version>-->
<!-- </dependency>--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.8</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.56</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency>
SM4Util.java
import com.westone.pboc.hsm.HSMConstant;
import com.westone.pboc.mina.client.Client;
import com.westone.pboc.mina.client.ClientThreadPool;
import com.westone.pboc.service.imp.HSMWSTApiServiceImp;
import org.eclipse.jdt.internal.compiler.batch.Main;
import org.junit.jupiter.api.Test;import java.io.File;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;//@SpringBootApplication
public class SM4Util {private static HSMWSTApiServiceImp imp ;// private static ClientThreadPool connectPool = ClientThreadPool.getInstance(URLDecoder.decode(Thread.currentThread().getContextClassLoader().getResource("hsminfo0901.properties").getPath()));// private static ClientThreadPool connectPool = ClientThreadPool.getInstance(URLDecoder.decode(Main.class.getResource("/hsminfo0901.properties").getPath()));// private static ShortClient shortClient = ShortClient.getInstance(URLDecoder.decode(Main.class.getResource("/hsminfo0901.properties").getPath()));// private static ClientThreadPool connectPool = ClientThreadPool.getInstance("D:\\share\\hsminfo0901.properties");private static ClientThreadPool connectPool = ClientThreadPool.getInstance("/usr/local/hsminfo0901.properties");static {System.out.println("静态代码块被执行");// 静态初始化,如初始化静态变量等imp = new HSMWSTApiServiceImp();try {connectPool.initClient();} catch (Exception e) {e.printStackTrace();}}//SM4加密public static Map<String,byte[]> SM4Encrypt(String inputString){// //如何按SM4 ECB_使用受SM2保护的密钥加密或解密int keyIndex = 1;int uiKeyBits = 16;int encryptAlgID = HSMConstant.SGD_SM4_ECB;Client client = null;byte[] data = inputString.getBytes();byte[] cipher = null;byte[] plain;try {client = connectPool.getClient();List<Object> list = imp.hsmSM2GenerateKeyWithIPK(keyIndex, uiKeyBits, client);byte[] keyHandle = (byte[]) list.get(0);imp.hsmDestoryKey(keyHandle, client);byte[] keyCipher = (byte[]) list.get(1);imp.hsmGetPrivateKeyAccessRight(keyIndex, "11111111", client);keyHandle = imp.hsmSM2ImportKeyWithISK(keyIndex, keyCipher, client);imp.hsmReleasePrivateKeyAccessRight(keyIndex, client);/*2、使用keyhandle加密明文数据data*/cipher = imp.hsmEncrypt(keyHandle, encryptAlgID, null, data, client); //加密plain = imp.hsmDecrypt(keyHandle, encryptAlgID, null, cipher, client); //解密imp.hsmDestoryKey(keyHandle, client);System.out.println("==============SM4加密前: "+inputString);System.out.println("==============SM4加密后byte数组: "+cipher);System.out.println("==============SM4加密后String: "+new String(cipher));System.out.println("==============SM4解密后: "+new String(plain));Map<String,byte[]> map = new HashMap<>();map.put("cipher",cipher);map.put("keyCipher",keyCipher);
// return cipher;return map;} catch (Exception e) {e.printStackTrace();} finally {connectPool.release(client);client.disposeConnector();}
// return cipher;return new HashMap<>();}//SM4解密@Testpublic static String SM4Decrypt(Map<String,byte[]> map){//如何按SM4 ECB_使用受SM2保护的密钥加密或解密int keyIndex = 1;int uiKeyBits = 16;int encryptAlgID = HSMConstant.SGD_SM4_ECB;Client client = null;
// byte[] cipher = inputBytes;byte[] plain = null;try {client = connectPool.getClient();List<Object> list = imp.hsmSM2GenerateKeyWithIPK(keyIndex, uiKeyBits, client);byte[] keyHandle = (byte[]) list.get(0);imp.hsmDestoryKey(keyHandle, client);// byte[] keyCipher = (byte[]) list.get(1);imp.hsmGetPrivateKeyAccessRight(keyIndex, "11111111", client);keyHandle = imp.hsmSM2ImportKeyWithISK(keyIndex, map.get("keyCipher"), client);imp.hsmReleasePrivateKeyAccessRight(keyIndex, client);plain = imp.hsmDecrypt(keyHandle, encryptAlgID, null, map.get("cipher"), client); //解密imp.hsmDestoryKey(keyHandle, client);// System.out.println("==============SM4解密前byte数组: "+ inputBytes);System.out.println("==============SM4解密后: "+new String(plain));return new String(plain);} catch (Exception e) {e.printStackTrace();} finally {connectPool.release(client);client.disposeConnector();}return new String(plain);}// public static void HowToEncryptOrDecryptBySM4ECB_WithKeyProtectedBySM2() {
// //如何按SM4 ECB_使用受SM2保护的密钥加密或解密
// imp = new HSMWSTApiServiceImp();
// try {
// connectPool.initClient();
// } catch (Exception e) {
// e.printStackTrace();
// }
//
//
// int keyIndex = 1;
// int uiKeyBits = 16;
// int encryptAlgID = HSMConstant.SGD_SM4_ECB;
// Client client = null;
// String string = "张店区第一谈话室";byte[] data = new byte[16];
// byte[] data = string.getBytes();
// byte[] cipher;
// byte[] plain;
//
// try {
// client = connectPool.getClient();
//
// /*前提条件:1号索引存在SM2密钥*/
// /*【系统的初始化阶段】
// * 需要准备用于数据加解密的密钥,这个或者这一些密钥的密文需要在业务系统测进行持久化存储
// * !!!!产生密钥的动作不需要在每次加密或者解密时调用,加密和解密所用密钥必须是同一个!!!!*/
//
// /*1、在某个会话通道client中产生一个会话密钥,记为keyA,这个密钥的密文由1号索引的SM2密钥加密保护*/
// List<Object> list = imp.hsmSM2GenerateKeyWithIPK(keyIndex, uiKeyBits, client);
//
// /*2、获得这个会话密钥的句柄:上述产生会话密钥的接口会在产生的同时
// * 就将该密钥放置在会话空间中形成一个会话密钥句柄,可直接调用该句柄进行数据加解密,
// * 但我们推荐将该句柄直接销毁,后续做加密解密时再重新导入密钥密文拿到新的密钥句柄来使用*/
// byte[] keyHandle = (byte[]) list.get(0);
// /*3、销毁keyHandleA:当会话密钥不再使用时,应及时销毁该句柄,以释放密钥句柄资源,否则造成句柄资源泄漏*/
// imp.hsmDestoryKey(keyHandle, client);
//
// /*4、获得这个会话密钥的密文:这个密文需要在业务系统中长期存储,
// * 将来需要将该密钥恢复回来进行数据加解密时,需要用该密文进行相应的导入接口的调用,
// * 以形成一个新的会话密钥句柄*/
// byte[] keyCipher = (byte[]) list.get(1);
//
//
// /*【加解密处理阶段】
// /*以上,我们准备产生了一个会话密钥密文keyCipher,这个密钥密文是由1号索引的SM2加密的
//
// *下面的代码展示使用这个会话密钥对数据进行处理时的接口调用
// */
//
// /*1、将会话密钥密文keyCipher导入到密码机的某个会话通道client中,得到对应的会话密钥句柄keyHandle
// * 这里将使用私钥对会话密钥进行解密,从而获得密钥句柄。
// * 使用私钥进行运算时需要先获取私钥使用权限,本例在通过密码机控制台软件进行SM2密钥产生时设置的访问口令为“11111111”
// */
// imp.hsmGetPrivateKeyAccessRight(keyIndex, "11111111", client);
// keyHandle = imp.hsmSM2ImportKeyWithISK(keyIndex, keyCipher, client);
// imp.hsmReleasePrivateKeyAccessRight(keyIndex, client);
//
// /*2、使用keyhandle加密明文数据data*/
// cipher = imp.hsmEncrypt(keyHandle, encryptAlgID, null, data, client); //加密
// plain = imp.hsmDecrypt(keyHandle, encryptAlgID, null, cipher, client); //解密
//
// /*3、销毁keyHandleA:当会话密钥不再使用时,应及时销毁该句柄,以释放密钥句柄资源*/
// imp.hsmDestoryKey(keyHandle, client);
//
// System.out.println("data length =" + data.length + "\ncipher length =" + cipher.length + "\ndecrypted plain length = " + plain.length);
//
// System.out.println("==============SM4加密前: "+string);
// System.out.println("==============SM4加密后byte数组: "+cipher);
// System.out.println("==============SM4加密后String: "+new String(cipher));
// System.out.println("==============SM4解密后: "+new String(plain));
//Assert.assertArrayEquals(data, plain);
// } catch (Exception e) {
// e.printStackTrace();
// } finally {
// connectPool.release(client);
// }
// }
//
// public void HowToCalculateSM3HMAC() {
// //如何计算SM3HMAC
// Client client = null;
// int sm2KeyIndex = 1;
// /*数据如果有中文,应约定将数据转码成byte数组时的转码方式*/
// byte[] data = "HelloWorld".getBytes();
//
// try {
// client = connectPool.getClient();
// /*这里是一个初始化动作,目的是产生一个用于计算HMAC的随机密钥,计算HMAC和校验这个HMAC的时候必须确保用到这个相同的随机密钥*/
// List<Object> wk = imp.hsmSM2GenerateKeyWithIPK(sm2KeyIndex, 16, client);
// /*这里取出的密钥句柄,如果不需要马上用于计算HMAC,可以直接调用hsmDestroyKey将其销毁,回收句柄资源*/
// byte[] keyHandle = (byte[]) wk.get(0);
// imp.hsmDestoryKey(keyHandle, client);
// /*这里的随机密钥密文是需要保存的,以便下次再使用这个密钥时用于导入后重新拿到密钥句柄*/
// byte[] keyCipher = (byte[]) wk.get(1);
//
// /*从这里开始,下面的接口调用序列为计算HMAC的完整的日常过程,
// 其中的keyCipher就是初始化阶段产生的随机密钥密文,将其导入后重新得到一个密钥句柄,并用这个句柄进行HMAC运算,
// 运算结束后必须回收该句柄资源*/
// imp.hsmGetPrivateKeyAccessRight(sm2KeyIndex, "11111111", client);
// byte[] keyHandleNew = imp.hsmSM2ImportKeyWithISK(sm2KeyIndex, keyCipher, client);
// imp.hsmReleasePrivateKeyAccessRight(sm2KeyIndex, client);
//
// byte[] context = imp.hsmHashCrossSessionInit(HSMConstant.SGD_HASH_HMAC_SM3, keyHandleNew, null, null, null, null, client);
// byte[] context11 = imp.hsmHashCrossSessionUpdate(context, data, client);
// byte[] hashResult = imp.hsmHashCrossSessionFinal(context11, client);
//
//
// /*!!!!注意!!!!*/
// /*计算完成后一定要释放密钥句柄资源*/
// boolean ok = imp.hsmDestoryKey(keyHandleNew, client);
//
// System.out.println("HMAC = " + ByteArrayUtil.toHexString(hashResult));
// } catch (Exception e1) {
// e1.printStackTrace();Assert.fail();
// } finally {
// connectPool.release(client);
// }
// }
//
// public void HowToBuildSM2PublicKeyFromRefByteArray() {
// //如何从RefByteArray构建SM2公钥
// int keyIndex = 1;
// Client client = null;
//
// try {
// client = connectPool.getClient();
//
// /*一个RefByteArray格式的SM2公钥以16进制字符串形式打印出来看起来像这样:
// *00010000e3b74ed47bbe6dabae26fba66630577a34d66f7e885cc23938db06e321d34f9344c35de1f59ef7164425484faac603df10caa369cfe72e24edfd6b2904e655a5
// * 即00010000||X||Y
// *通常解析X509证书得到的SM2公钥按照16进制字符串形式打印出来像下面这样:
// *04e3b74ed47bbe6dabae26fba66630577a34d66f7e885cc23938db06e321d34f9344c35de1f59ef7164425484faac603df10caa369cfe72e24edfd6b2904e655a5
// * 即04||X||Y
// *本例仅展示从RefByteArray构造一个PublicKey对象,如果是04||X||Y,只需要将前面的04部分替换为00010000 */
//
// /*前提条件:1号索引存在SM2密钥,且其访问口令为11111111*/
// /*为了方便验证转换的正确性,我们取出了1号索引的公钥,将其转换为00010000||X||Y形式
// *再对00010000||X||Y形式的公钥进行了PublicKey的对象构造动作*/
// PublicKey externalPK = imp.hsmSM2GetPublicKey(keyIndex, client);
// byte[] pkAsRefByteArray = SM2PKUtil.SM2PublicKey2Bytes(externalPK);
// System.out.println("pkAsRefByteArray = " + ByteArrayUtil.toHexString(pkAsRefByteArray));
//
// PublicKey builtPK = SM2PKUtil.buildPublicKey(pkAsRefByteArray);
//
// /*验证正确性:
// *由于以上构造出的公钥实际来源于1号索引,因此我们用构造出来的公钥对象进行加密,再用1号索引的SM2私钥解密,
// *如果解密结果与原始明文一致,则认为验证通过 */
// byte[] dataPlain = "1111111111111111".getBytes();
// byte[] dataCipher = imp.hsmSM2ExternalPublicKeyEnc(HSMConstant.WST_ALG_TYPE, builtPK, dataPlain, client);
// imp.hsmGetPrivateKeyAccessRight(keyIndex, "11111111", client);
// byte[] outPlain = imp.hsmSM2InternalPrivateKeyDec(keyIndex, HSMConstant.WST_ALG_TYPE, dataCipher, client);
// imp.hsmReleasePrivateKeyAccessRight(keyIndex, client);
// System.out.println("dataPlain=" + ByteArrayUtil.toHexString(dataPlain) + "\noutPlain =" + ByteArrayUtil.toHexString(outPlain));Assert.assertArrayEquals(dataPlain, outPlain);
// } catch (Exception e) {
// e.printStackTrace();
// } finally {
// connectPool.release(client);
// }
// }
//
// public void HowToInternalEncryptAndInternalDecryptBySM2() {
// //如何通过SM2进行内部加密和内部解密
// int keyIndex = 1;
// Client client = null;
// try {
// client = connectPool.getClient();
//
// byte[] data = "11111111".getBytes();
// byte[] result = imp.hsmSM2InternalPublicKeyEnc(HSMConstant.WST_ALG_TYPE, 6, keyIndex, data, client);
// System.out.println("Cipher = " + ByteArrayUtil.toHexString(result));
//
// byte[] decrypted = imp.hsmSM2InternalPrivateKeyDec(1, keyIndex, "11111111", result, client);
// System.out.println("Plain = " + ByteArrayUtil.toHexString(decrypted));
//
// } catch (Exception e) {
// e.printStackTrace();
// } finally {
// connectPool.release(client);
// }
// }
//
// @Test
// public void HowToInternalSignAndExternalVerifyBySM2() {
// //如何通过SM2进行内部签名和外部验证
// int keyIndex = 1;
// String algType = HSMConstant.WST_ALG_TYPE;
// String src = "1111111111ffffffffff000000000012";
// String userId = "1234567812345678";
// Client client = null;
// try {
// client = connectPool.getClient();
//
// /*签名方:使用keyIndex索引的私钥对数据进行签名*/
// /*1、用keyIndex索引对应的公钥对原始数据计算SM2-SM3-USERID摘要*/
// byte[] hashData1 = imp.doHash(keyIndex, null, src.getBytes(), userId, client);
// /*2、对摘要结果计算签名*/
// byte[] signData = imp.hsmSM2InternalSign(algType, keyIndex, hashData1, "11111111", client);
// System.out.println("外部SM2签名成功,签名内容:" + ByteArrayUtil.toHexString(signData));
//
// /*验签方:验签方用签名方的公钥进行验签*/
// /*0、通过某种方式,验签方获得签名方的公钥,例如从签名方的公钥证书中提取,或者从签名方直接拿到公钥明文
// * 这里为了让用例流程往下开展,我们假设性的从相同索引获取其公钥*/
// PublicKey pk = imp.hsmSM2GetPublicKey(keyIndex, client);
// System.out.println("PK = "+ByteArrayUtil.toHexString(pk.getEncoded()));
//
// /*1、用签名方提供的公钥对原始数据计算SM2-SM3-USERID摘要*/
// byte[] hashData2 = imp.doHash(-1, pk, src.getBytes(), userId, client);
// /*2、对摘要结果计算签名*/
// boolean ret = imp.hsmSM2ExternalVerify(algType, pk, signData, hashData2, client);
// System.out.println("外部SM2验签密成功,结果:" + ret);
//
// } catch (Exception e) {
// e.printStackTrace();
// } finally {
// connectPool.release(client);
// }
// }public static void main(String[] args) {
// String str = "测试加密数据";
// Map<String,byte[]> jsonObject= SM4Util.SM4Encrypt(str);
// String newstr = SM4Util.SM4Decrypt(jsonObject);HowToEncryptOrDecryptBySM4ECB_WithKeyProtectedBySM2();
// System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ");String path = System.getProperty("user.dir") + File.separator + "/hsminfo0901.properties";System.out.println(Main.class.getResource("/hsminfo0901.properties").getPath());}
}
5、海康威视 实时视频、视频回放
pom.xml
<!-- 海康威视驱动 --><dependency><groupId>com.hikvision.ga</groupId><artifactId>artemis-http-client</artifactId><version>1.1.3</version></dependency>
HikConstants.java
public class HikConstants {/** 查询监控点列表 */public static final String findCameraSearch = "/api/resource/v1/camera/advance/cameraList";
// /** 分页获取设备列表 */public static final String findCameraList = "/api/resource/v1/cameras";/** 分页获取设备列表 */
// public static final String findCameraList = "/api/resource/v2/encodeDevice/search";/** 获取视频流url */public static final String previewURLs = "/api/video/v1/cameras/previewURLs";/*** 获取电视墙预览*/
// public static final String tvWallURL = "/api/v1/preview/tvWall/get";public static final String tvWallURL = "/api/v1/preview/tvWall/getPreviewParam";/*** 释放永久有效url*/public static final String clearPlayUrls = "/api/v1/clearPlayUrls";/** 获取监控点回放取流URL */public static final String playbackURLs = "/api/video/v1/cameras/playbackURLs";}
HikController.java
import cn.hutool.json.JSONObject;
import com.ewaycloud.jw.channel.dto.ConditionBaseVO;
import com.ewaycloud.jw.channel.dto.HikCameraSearchDTO;
import com.ewaycloud.jw.channel.service.HikService;
import com.ewaycloud.jw.common.core.util.R;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/channel/hik")
public class HikController {@Autowiredprivate HikService hkService;/*** 获取监控点列表* */@GetMapping("/findCameraSearch")public R findCameraSearch(HikCameraSearchDTO hilCameraSearchDTO){try {return R.ok(hkService.findCameraSearch(hilCameraSearchDTO));}catch (Exception e){log.error("获取设备编码列表失败!"+e.getMessage());return R.failed("获取设备编码列表失败!");}}/*** 获取设备列表* */@GetMapping("/findDeviceList")public R findDeviceList(ConditionBaseVO conditionBaseVO){try {List<JSONObject> list = hkService.findCameraList(conditionBaseVO);return R.ok(list);}catch (Exception e){log.error("获取设备编码列表失败!"+e.getMessage());return R.failed("获取设备编码列表失败!");}}/*** 获取视频流url* */@GetMapping("/previewUrls")public R previewUrls(@RequestParam String cameraIndexCode){try {return R.ok(hkService.previewUrls(cameraIndexCode));}catch (Exception e){log.error("获取设备编码列表失败!"+e.getMessage());return R.failed("获取设备编码列表失败!");}}/*** 获取 电视墙预览 视频流url* */@GetMapping("/tvWallURL")public R tvWallURL(@RequestParam String cameraIndexCode){try {return R.ok(hkService.tvWallURL(cameraIndexCode));}catch (Exception e){log.error("获取设备编码列表失败!"+e.getMessage());return R.failed("获取设备编码列表失败!");}}/*** 释放永久有效url* */@GetMapping("/clearPlayUrls")public R clearPlayUrls(@RequestParam String url){try {return R.ok(hkService.clearPlayUrls(url));}catch (Exception e){log.error("释放永久有效url!"+e.getMessage());return R.failed("释放永久有效url!");}}/*** 获取 回放 视频流url* */@GetMapping("/playbackURLs")public R playbackURLs(@RequestParam String cameraIndexCode, @RequestParam String beginTime, @RequestParam String endTime){try {return R.ok(hkService.playbackURLs(cameraIndexCode, beginTime, endTime));}catch (Exception e){log.error("获取设备编码列表失败!"+e.getMessage());return R.failed("获取设备编码列表失败!");}}}
HikService.java
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.ewaycloud.jw.channel.constants.HikConstants;
import com.ewaycloud.jw.channel.dto.ConditionBaseVO;
import com.ewaycloud.jw.channel.dto.HikCameraSearchDTO;
import com.ewaycloud.jw.channel.util.GetCameraPreviewURL;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.List;/*** 海康service* */
@Service
@Slf4j
public class HikService {public List findCameraSearch(HikCameraSearchDTO hilCameraSearchDTO) throws Exception{JSONObject json = new JSONObject();
// json.put("pageNo",hilCameraSearchDTO.getPageNum());
// json.put("pageSize",hilCameraSearchDTO.getPageSize());json.put("name",hilCameraSearchDTO.getName());log.info("请求第三方参数--->"+ JSONUtil.toJsonStr(json));log.info("请求第三方接口--->"+ HikConstants.findCameraSearch);String result = GetCameraPreviewURL.GetCameraPreviewURL(json, HikConstants.findCameraSearch);log.info("第三方返回请求结果--->"+result);json = JSONObject.parseObject(result);if(!json.get("code").equals("0")){log.error("获取监控点列表失败!"+json.get("msg"));throw new Exception("获取监控点列表失败!"+json.get("msg"));}JSONObject data = json.getJSONObject("data");return data.getJSONArray("list");}public List findCameraList(ConditionBaseVO conditionBaseVO) throws Exception{JSONObject json = new JSONObject();json.put("pageNo",conditionBaseVO.getPageNum());json.put("pageSize",conditionBaseVO.getPageSize());json.put("treeCode","0");log.info("请求第三方参数--->"+JSONUtil.toJsonStr(json));log.info("请求第三方接口--->"+ HikConstants.findCameraList);String result = GetCameraPreviewURL.GetCameraPreviewURL(json, HikConstants.findCameraList);log.info("第三方返回请求结果--->"+result);json = JSONObject.parseObject(result);if(!json.get("code").equals("0")){log.error("获取设备编码列表失败!"+json.get("msg"));throw new Exception("获取设备编码列表失败!"+json.get("msg"));}JSONObject data = json.getJSONObject("data");return data.getJSONArray("list");}public JSONObject previewUrls(String cameraIndexCode) throws Exception{JSONObject json = new JSONObject();json.put("cameraIndexCode",cameraIndexCode);log.info("请求第三方参数--->"+JSONUtil.toJsonStr(json));log.info("请求第三方接口--->"+ HikConstants.previewURLs);String result = GetCameraPreviewURL.GetCameraPreviewURL(json, HikConstants.previewURLs);log.info("第三方返回请求结果--->"+result);json = JSONObject.parseObject(result);if(!json.get("code").equals("0")){log.error("获取视频url失败!"+json.get("msg"));throw new Exception("获取视频url失败!"+json.get("msg"));}JSONObject data = json.getJSONObject("data");return data;}/*** 获取 电视墙预览 视频流url* */public JSONObject tvWallURL(String cameraIndexCode) throws Exception{JSONObject json = new JSONObject();json.put("indexCode",cameraIndexCode);json.put("expand", "streamform=rtp");json.put("netZoneCode", "0");json.put("protocol", "rtsp");json.put("streamType", 0);json.put("transmode", 0);log.info("请求第三方参数--->"+JSONUtil.toJsonStr(json));log.info("请求第三方接口--->"+ HikConstants.tvWallURL);String result = GetCameraPreviewURL.GetCameraPreviewURL(json, HikConstants.tvWallURL);log.info("第三方返回请求结果--->"+result);json = JSONObject.parseObject(result);if(!json.get("code").equals("0")){log.error("获取视频url失败!"+json.get("msg"));throw new Exception("获取视频url失败!"+json.get("msg"));}JSONObject data = json.getJSONObject("data");return data;}/*** 释放永久有效url* */public JSONObject clearPlayUrls(String url) throws Exception{JSONObject json = new JSONObject();JSONArray array = new JSONArray();array.add(url);json.put("urls",array);log.info("请求第三方参数--->"+JSONUtil.toJsonStr(json));log.info("请求第三方接口--->"+ HikConstants.clearPlayUrls);String result = GetCameraPreviewURL.GetCameraPreviewURL(json, HikConstants.clearPlayUrls);log.info("第三方返回请求结果--->"+result);json = JSONObject.parseObject(result);if(!json.get("code").equals("0")){log.error("释放永久有效url!"+json.get("msg"));throw new Exception("释放永久有效url!"+json.get("msg"));}JSONObject data = json.getJSONObject("data");return data;}/*** 获取 回放 视频流url* */public JSONObject playbackURLs(String cameraIndexCode, String beginTime, String endTime) throws Exception{JSONObject json = new JSONObject();json.put("cameraIndexCode",cameraIndexCode);//String startDate = DateUtil.format(DateUtil.parse(beginTime),"yyyy-MM-dd'T'HH:mm:ss.SSSZ");//String endDate = DateUtil.format(DateUtil.parse(endTime),"yyyy-MM-dd'T'HH:mm:ss.SSSZ");String startDate = Stringios(beginTime);String endDate = Stringios(endTime);json.put("beginTime", startDate);// 开始查询时间(IOS8601格式yyyy-MM-dd'T'HH:mm:ss.SSSzzz,和结束时间相差不超过三天) "beginTime": "2024-04-15T07:50:00.000+08:00",json.put("endTime", endDate); // "endTime": "2024-04-15T08:10:00.000+08:00",json.put("recordLocation", "1");json.put("protocol", "rtsp");
// json.put("needReturnClipInfo", true);json.put("expand", "streamform=rtp");
// UUID uuid = UUID.randomUUID();
// json.put("uuid", uuid.toString());log.info("请求第三方参数--->"+JSONUtil.toJsonStr(json));log.info("请求第三方接口--->"+ HikConstants.playbackURLs);String result = GetCameraPreviewURL.GetCameraPreviewURL(json, HikConstants.playbackURLs);log.info("第三方返回请求结果--->"+result);json = JSONObject.parseObject(result);if(!json.get("code").equals("0")){log.error("获取回放视频url失败!"+json.get("msg"));System.out.println("获取回放视频url失败!:" +json.get("msg"));//throw new Exception("获取回放视频url失败!"+json.get("msg"));}JSONObject data = json.getJSONObject("data");return data;}/*** String类型的时间(yyyy-MM-dd HH:mm:ss)转换成IOS-8601格式* @param data* @return*/public String Stringios(String data) {data = data.substring(0, 19);DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");LocalDateTime dt1 = LocalDateTime.parse(data, dateTimeFormatter);ZoneOffset offset = ZoneOffset.of("+08:00");OffsetDateTime date = OffsetDateTime.of(dt1, offset);DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");String datas = date.format(formatter2);return datas;}}
GetCameraPreviewURL.java
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;import java.util.HashMap;
import java.util.Map;/*** 海康接口* */
public class GetCameraPreviewURL {public static String GetCameraPreviewURL(JSONObject jsonObject, String apiUrl) {/*** STEP1:设置平台参数,根据实际情况,设置host appkey appsecret 三个参数.*/// artemis网关服务器ip端口ArtemisConfig.host = "159.61.64.249:443";// 秘钥appkeyArtemisConfig.appKey = "22547186";// 秘钥appSecretArtemisConfig.appSecret = "sPteT21oUI2CCav79heE";/*** STEP2:设置OpenAPI接口的上下文*/final String ARTEMIS_PATH = "/artemis";/*** STEP3:设置接口的URI地址*/final String previewURLsApi = ARTEMIS_PATH + apiUrl;Map<String, String> path = new HashMap<String, String>(2) {{put("https://", previewURLsApi);//根据现场环境部署确认是http还是https}};/*** STEP4:设置参数提交方式*/String contentType = "application/json";/*** STEP5:组装请求参数*/
// JSONObject jsonBody = new JSONObject();
// jsonBody.put("cameraIndexCode", "748d84750e3a4a5bbad3cd4af9ed5101");
// jsonBody.put("streamType", 0);
// jsonBody.put("protocol", "rtsp");
// jsonBody.put("transmode", 1);
// jsonBody.put("expand", "streamform=ps");String body = JSONUtil.toJsonStr(jsonObject);/*** STEP6:调用接口*/// post请求application/json类型参数String result = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, contentType , null);return result;}
}
6、前端视频插件
实时视频:demo_embedded_for_iframe.html
<!doctype html>
<html>
<head><title>预览Demo</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta http-equiv="Pragma" content="no-cache" /><meta http-equiv="Cache-Control" content="no-cache, must-revalidate" /><meta http-equiv="Expires" content="0" />
</head>
<style>
html, body {padding: 0;margin: 0;
}
.playWnd {/* margin: 30px 0 0 50px; *///width: 800px;//height: 400px;/* border: 1px solid red; */
}
.cbInfoDiv {float: left;width: 360px;/* margin-left: 16px; */border:1px solid #7F9DB9;
}
.cbInfo {height: 200px;padding: 5px;border: 1px solid #7F9DB9;word-break: break-all;overflow: scroll auto;
}
.operate {/* margin-top: 24px; */
}
.operate::after {content: '';display: block;clear: both;
}
.operate .btns {height: 32px;
}
.module {float: left;width: 120px;min-height: 290px;margin-left: 10px;padding: 16px 8px;box-sizing: border-box;border: 1px solid #e5e5e5;
}
.module .item {margin-bottom: 4px;
}
.module .label {width: 150px;display: inline-block;vertical-align: middle;margin-right: 8px;text-align: right;
}
.module input[type="text"],
.module select {box-sizing: border-box;display: inline-block;vertical-align: middle;margin-left: 0;width: 150px;min-height: 20px;
}
.module .btn {min-width: 80px;min-height: 24px;margin-top: 16px;margin-left: 158px;
}
</style>
<body><div id="playWnd" class="playWnd" style="left: 109px; top: 133px;"></div><div id="operate" class="operate" style="display: none;"><!--初始化、反初始化、设置认证信息接口调用入口。1.插件所有接口都需要在调用初始化并返回成功后才能调用2.设置认证信息仅适用于对接多平台时的情况,具体参照开发指南3.反初始化后,插件资源销毁--><div class="module" style="left:30px;height:30px;width:280px;padding:10px;margin:10px;"><div class="item"><label >初始化相关参数:</label><!-- 4097, --><textarea id="initParam" type="text" style="width:260px;height:200px;">{"argument": {"appkey": "22547186","ip": "159.61.64.249","port": 443,"secret": "sPteT21oUI2CCav79heE","enableHTTPS": 1,"language": "zh_CN","layout": "3x3","playMode": 0,"reconnectDuration": 5,"reconnectTimes": 5,"showSmart": 0,"showToolbar": 1,"toolBarButtonIDs": "2048,2049,2050,2304,2306,2305,2307,2308,2309,4096,4097,4608,4099,4098,4609,4100","snapDir": "C:/snap","videoDir": "C:/video"},"funcName": "init"}</textarea></div><div class="item"> <button style="width:10px;padding:0;margin:0;" id="initBtn" class="btn">执行</button></div></div><!--单个点位播放、批量点位播放、批量停止播放、全部停止播放接口调用入口。1.authUuid为对接多平台时必须的播放字段,对接单平台时,可不指定--><div class="module" style="height:30px;width:280px;padding:10px;margin:10px;"><div class="item"><label >播放相关参数:</label><!-- {"argument": {"authUuid": "","cameraIndexCode": "d597b77b8c73459792c82ded3acb6eba","ezvizDirect": 0,"gpuMode": 0,"streamMode": 0,"transMode": 0,"wndId": -1,"cascade": 1},"funcName": "startPreview"} --><textarea id="playParam" type="text" style="width:260px;height:200px;">{"funcName": "startPreview","argument":{}}</textarea></div><div class="item"> <button style="width:10px;padding:0;margin:0;" id="playBtn" class="btn">执行</button></div></div><div class="module" style="height:50px;width:300px;padding:10px;margin:10px;"><legend>返回值信息</legend><div id="cbInfo" class="cbInfo"></div><button style="width:80px;height:24px;padding:30px;margin:0;" id="clear">清空</button></div></div>
</body>
<script src="jquery-1.12.4.min.js"></script>
<script src="jsencrypt.min.js"></script>
<script src="web-control_1.2.5.min.js"></script><script type="text/javascript">var div = window.parent.document.getElementById('iframeVideo');var widthData = div.offsetWidth; // 元素的宽度var heightData = div.offsetHeight; // 元素的高度// 插件对象实例,初始化为null,需要创建多个插件窗口时,需要定义多个插件对象实例变量,各个变量唯一标志对应的插件实例var oWebControl = null;var bIE = (!!window.ActiveXObject || 'ActiveXObject' in window);// 是否为IE浏览器var pubKey = ''; // demo中未使用加密,可根据需求参照开发指南自行使用加密功能var initCount = 0; // 异常重启计数var iframePos = {top:0,left:0}; // iframe相对文档的位置let default_left = 528;//默认leftlet default_top = 132;//默认toplet default_width = widthData;//默认宽度let default_height = heightData;//默认高度let deviation_top = 120; //偏移量var parentTitle = ''; // 父页面标题var iframeClientPos = null; // iframe相对视窗的位置var iframeParentShowSize = null; // 视窗大小 width heightvar videoType = ''var cameraCode =''var cameraCodeArr = []//code集合var cameraWndId = -1;// 标签关闭$(window).unload(function () {if (oWebControl != null){oWebControl.JS_HideWnd(); // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题oWebControl.JS_Disconnect().then(function(){}, function() {});}});$(window).resize(function () {var div = window.parent.document.getElementById('iframeVideo');var widthData = div.offsetWidth; // 元素的宽度var heightData = div.offsetHeight; // 元素的高度if (oWebControl != null){oWebControl.JS_Resize(widthData, heightData);}console.log('宽度: ' + widthData + ', 高度: ' + heightData);});//监听父页面的消息window.addEventListener('message', function(e){if(e && e.data){switch (e.data.action){case 'sendTitle': // 父页面将其标题发送过来,子页面保存该标题,以便创建插件窗口成功后将标题设置回给父页面parentTitle = e.data.info;// cameraCode = e.data.cameraCode;// console.log(cameraCode,'ybu')videoType = e.data.videoType;console.log(videoType,'type');break;case 'sendCameraCode': //传递codecameraCode = e.data.cameraCode;console.log('传递的参数:',cameraCode,"::",cameraWndId)//如果大于9,则从1 开始if(cameraWndId>9){cameraWndId=-1cameraCodeArr.shift();}if(videoType == 'live'){//监控let flag = false;cameraCodeArr.forEach(e=>{console.log("播放的摄像头:",e)if(e.cameraIndexCode==cameraCode){flag = true;}})if(!flag){let obj = {"cameraIndexCode": cameraCode,"transMode": 0,// "wndId": cameraWndId,"wndId": -1,"gpuMode": 0}cameraCodeArr.push(obj)cameraCode = obj;}else{console.log("存在:",cameraCode);}cameraWndId++}else{//回放let startTimeStamp = e.data.startTimelet endTimeStamp = e.data.endTimeconsole.log("回放:",startTimeStamp,endTimeStamp);let obj = {"cameraIndexCode": cameraCode,"startTimeStamp": startTimeStamp,//"1714444801","endTimeStamp": endTimeStamp,"recordLocation": 1,"transMode": 0,// "wndId": cameraWndId,//cameraCodeArr.length+1,"wndId": -1,"gpuMode": 0}cameraCodeArr.push(obj)cameraCode = obj;}console.log("封装参数:",cameraCodeArr)// getLayout();initPayBtn()break;case 'updatePos': // 更新插件位置var scrollValue = e.data.scrollValue; // 滚动条滚动偏移量console.log("~~~~~scrollValue~~~~~",scrollValue)oWebControl.JS_SetDocOffset({left: iframePos.left + scrollValue.left,top: iframePos.top + scrollValue.top}); // 更新插件窗口位置console.log("~~~~~~~~~~",oWebControl)if(oWebControl){oWebControl.JS_SetDocOffset({left: default_left,top: default_top});}oWebControl.JS_Resize(default_width, default_height);// setWndCover();break;case 'scroll':iframeParentShowSize = e.data.showSize; // 视窗大小iframePos = e.data.iframeOffset; // iframe与文档的偏移量iframeClientPos = e.data.iframeClientPos; // iframe相对视窗的位置var scrollValue = e.data.scrollValue; // 滚动条滚动偏移量if(oWebControl){oWebControl.JS_SetDocOffset({left: default_left,//iframePos.left + scrollValue.left,top: iframePos.top + scrollValue.top + deviation_top}); // 更新插件窗口位置oWebControl.JS_Resize(default_width, default_height);// setWndCover();}break;default:break;}}});let editLayout = 0;let layout = "4x4"function getLayout(){if(oWebControl){oWebControl.JS_RequestInterface({funcName: "getLayout"}).then(function (oData) {console.log("查看:",oData.responseMsg.data)if(oData.responseMsg.data){// debuggerlet data = oData.responseMsg.data;data = JSON.parse(data)let wndNum = data.wndNum;let len = cameraCodeArr.length;console.log("判断:",len);//布局不大于25,设置5*5if(len<9){}}})}}function getAndSetLayout(){if(oWebControl){oWebControl.JS_RequestInterface({funcName: "getLayout"}).then(function (oData) {console.log("查看:",oData.responseMsg.data)if(oData.responseMsg.data){// debuggerlet data = oData.responseMsg.data;data = JSON.parse(data)let wndNum = data.wndNum;let len = cameraCodeArr.length;console.log("判断:",len);//布局不大于25,设置5*5if(len<26){if(len>wndNum){//默认是3*3,第一次修改4*4,暂时这样处理,后期可以动态if(editLayout==1){layout = "5x5";}oWebControl.JS_RequestInterface({funcName: "setLayout",argument: {layout: layout}}).then(function (oData) {console.log("设置布局:",oData);})editLayout++}}}})}}// 顶部:iframe.getBoundingClientRect().top小于0并且其绝对值超过DIV.get(0).getBoundingClientRect().top部分需要剪切// 底部:(iframe.getBoundingClientRect().bottom - iframe父窗口可视域高度,为H1)为不可见部分// ($(window).height() - DIV.get(0).getBoundingClientRect().bottom)// 为DIV底部与其所在iframe底部之间的距离H2,H1-H2的值大于0则表示DIV有部分在不可见区域// 左边:iframe.getBoundingClientRect().left小于0并且其绝对值超过DIV.get(0).getBoundingClientRect().left部分需要剪切// 右边:(iframe宽度 - DIV.get(0).getBoundingClientRect().right表示DIV右边与其父iframe右边之间的距离,为W1)// (iframe父窗口可视域宽度-iframe.getBoundingClientRect().left表示iframe左边与iframe父窗口可视域右边之间的距离,为W2)// (iframe宽度 - W2 - W1)如果大于0,则表示DIV右边超出了iframe父窗口可视域,需要剪切超过的部分function setWndCover() {if (oWebControl){// 准备要用到的一些数据var iframeWndHeight = $(window).height(); // iframe窗口高度var iframeWndWidth = $(window).width(); // iframe窗口宽度var divLeft = $("#playWnd").get(0).getBoundingClientRect().left;var divTop = $("#playWnd").get(0).getBoundingClientRect().top;var divRight = $("#playWnd").get(0).getBoundingClientRect().right;var divBottom = $("#playWnd").get(0).getBoundingClientRect().bottom;var divWidth = $("#playWnd").width();var divHeight = $("#playWnd").height();oWebControl.JS_RepairPartWindow(0, 0, 801, 401); // 多1个像素点防止还原后边界缺失一个像素条// 判断剪切矩形的上边距if (iframeClientPos.top < 0 && Math.abs(iframeClientPos.top) > divTop){var deltaTop = Math.abs(iframeClientPos.top) - divTop;oWebControl.JS_CuttingPartWindow(0, 0, 801, deltaTop + 1);//console.log({deltaTop: deltaTop});}// 判断剪切矩形的左边距if (iframeClientPos.left < 0 && Math.abs(iframeClientPos.left) > divLeft){var deltaLeft = Math.abs(iframeClientPos.left) - divLeft;//console.log({deltaLeft: deltaLeft});oWebControl.JS_CuttingPartWindow(0, 0, deltaLeft, 401); // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条}// 判断剪切矩形的右边距var W1 = iframeWndWidth - divRight;var W2 = iframeParentShowSize.width - iframeClientPos.left;if (W2 < divWidth){var deltaRight = iframeWndWidth - W2 - W1;if (deltaRight > 0) {oWebControl.JS_CuttingPartWindow(800 - deltaRight, 0, deltaRight + 1, 401);}}// 判断剪切矩形的下边距var H1 = iframeClientPos.bottom - iframeParentShowSize.height;var H2 = iframeWndHeight - divBottom;var deltaBottom = H1 - H2;//console.log({deltaBottom: deltaBottom});if (deltaBottom > 0) {oWebControl.JS_CuttingPartWindow(0, 400 - deltaBottom, 801, deltaBottom + 1);}}}// 创建插件实例,并启动本地服务建立websocket连接,创建插件窗口function initPlugin () {// console.log("初始化实例:",oWebControl);// if(oWebControl){oWebControl = new WebControl({szPluginContainer: "playWnd",iServicePortStart: 15900,iServicePortEnd: 15900,szClassId:"23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsidcbConnectSuccess: function () {initCount = 0;setCallbacks();oWebControl.JS_StartService("window", {dllPath: "./VideoPluginConnect.dll"}).then(function () {// 步骤2:JS_CreateWnd时指定cbSetDocTitle回调,并在回调中向父页面发送更新标题消息,标题为回调出来的uuidoWebControl.JS_CreateWnd("playWnd", 800, 400, {bEmbed: true,cbSetDocTitle: function (uuid) {oWebControl._pendBg = false;window.parent.postMessage({action:'updateTitle',msg:'子页面通知父页面修改title',info:uuid}, '\*'); // '\*'表示跨域参数,请结合自身业务合理设置}}).then(function () {oWebControl.JS_SetDocOffset({left: default_left,top: default_top});// 步骤3:JS_CreateWnd成功后通知父页面将其标题修改回去console.log("JS_CreateWnd success",oWebControl);window.parent.postMessage({action:'updateTitle',msg:'子页面通知父页面更新title',info: parentTitle}, '\*');// 步骤4:发消息更新插件窗口位置:这里不直接更新的原因是,父页面默认可能就存在滚动条,此时有滚动量window.parent.postMessage({action:'updatePos',msg:'更新Pos'}, '\*');initBtnClicked();});}, function () {console.log("JS_CreateWnd fail");});},cbConnectError: function () {console.log("cbConnectError");oWebControl = null;$("#playWnd").html("插件未启动,正在尝试启动,请稍候...");WebControl.JS_WakeUp("VideoWebPlugin://");initCount ++;if (initCount < 3) {setTimeout(function () {initPlugin();}, 3000)} else {$("#playWnd").html("插件启动失败,请检查插件是否安装!");}},cbConnectClose: function (bNormalClose) {// 异常断开:bNormalClose = false// JS_Disconnect正常断开:bNormalClose = trueif (true == bNormalClose){console.log("cbConnectClose normal");}else{console.log("cbConnectClose exception");}oWebControl = null;$("#playWnd").html("插件未启动,正在尝试启动,请稍候...");WebControl.JS_WakeUp("VideoWebPlugin://");initCount ++;if (initCount < 3) {setTimeout(function () {initPlugin();}, 3000)} else {$("#playWnd").html("插件启动失败,请检查插件是否安装!");}}});// }}initPlugin();// 获取公钥function getPubKey (callback) {oWebControl.JS_RequestInterface({funcName: "getRSAPubKey",argument: JSON.stringify({keyLength: 1024})}).then(function (oData) {console.log(oData)if (oData.responseMsg.data) {pubKey = oData.responseMsg.datacallback()}})}// 设置窗口控制回调function setCallbacks() {oWebControl.JS_SetWindowControlCallback({cbIntegrationCallBack: cbIntegrationCallBack});}// 推送消息function cbIntegrationCallBack(oData) {showCBInfo(JSON.stringify(oData.responseMsg));}// RSA加密function setEncrypt (value) {var encrypt = new JSEncrypt();encrypt.setPublicKey(pubKey);return encrypt.encrypt(value);}function requestInterface(value){oWebControl.JS_RequestInterface(JSON.parse(value)).then(function (oData) {console.log("执行结果:",oData,value)showCBInfo(JSON.stringify(oData ? oData.responseMsg : ''));});}// 显示接口返回的消息及插件回调信息function showCBInfo(szInfo, type) {if (type === 'error') {szInfo = "<div style='color: red;'>" + dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss") + " " + szInfo + "</div>";} else {szInfo = "<div>" + dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss") + " " + szInfo + "</div>";}$("#cbInfo").html(szInfo + $("#cbInfo").html());/* oWebControl.JS_SetDocOffset({left: 150,top: 150});oWebControl.JS_Resize(400, 400);setWndCover(); */}function initBtnClicked(){var param = $("#initParam").val();//删除字符串中的回车换行console.log(param,'initpatam');const paramStr = JSON.parse(param)console.log(paramStr,'paramsta');if(videoType == "live"){paramStr.argument.playMode = 0}else{paramStr.argument.playMode = 1}param = JSON.stringify(paramStr)param = param.replace(/(\s*)/g, "");// 执行初始化requestInterface(param);}$("#initBtn").click(function() {initBtnClicked();})$("#playBtn").click(function() {var param = $("#playParam").val();//删除字符串中的回车换行param = param.replace(/(\s*)/g, "");// 执行预览requestInterface(param);})// 清空$("#clear").click(function() {$("#cbInfo").html('');})function initPayBtn(){setTimeout(() => {// initBtnClicked();}, 500);setTimeout(() => {var param = $("#playParam").val();const paramStr2 = JSON.parse(param)if(videoType == 'live'){/* paramStr2.funcName = "startMultiPreviewByCameraIndexCode"let argumentList = paramStr2.argument.list;paramStr2.argument.list =cameraCodeArr;//*/paramStr2.funcName = "startPreview"let argumentList = paramStr2.argument;paramStr2.argument =cameraCode;//console.log("摄像头参数:",paramStr2);let test = [{"cameraIndexCode": "d597b77b8c73459792c82ded3acb6eba","transMode": 0,"wndId": 1,"gpuMode": 0},{"cameraIndexCode": "b8f8e561950a4e3bbc4f2e3bf55828e7","transMode": 0,"wndId": 2,"gpuMode": 0},{"cameraIndexCode": "38e0da0b6fe04690a403abc0ed45438f","transMode": 0,"wndId": 3,"gpuMode": 0},]// paramStr2.argument.list = test;}else{/* paramStr2.funcName = "startMultiPlaybackByCameraIndexCode"let argumentList = paramStr2.argument.list;paramStr2.argument.list =cameraCodeArr;console.log("摄像头参数:",paramStr2); */paramStr2.funcName = "startPlayback"let argumentList = paramStr2.argument;paramStr2.argument =cameraCode;//console.log("摄像头参数:",paramStr2);/* {"argument": {"cameraIndexCode": "25603528001310681100","startTimeStamp": "1714444801","endTimeStamp": "1714466401","gpuMode": 0,"streamMode": 0,"transMode": 1,"wndId": -1},"funcName": "startPreview"} */let test = [{"cameraIndexCode": "4cc3b6a7961f4083b50ee8a67a840ec4","startTimeStamp": 171544320000,"endTimeStamp": 171549360000,"recordLocation": 1,"transMode": 0,"wndId": 1,"gpuMode": 0}]// paramStr2.argument.list = test;}param = JSON.stringify(paramStr2)//删除字符串中的回车换行param = param.replace(/(\s*)/g, "");// 执行预览requestInterface(param);}, 1000);}// setTimeout(function(){// initPayBtn()// },2000)// 格式化时间function dateFormat(oDate, fmt) {var o = {"M+": oDate.getMonth() + 1, //月份"d+": oDate.getDate(), //日"h+": oDate.getHours(), //小时"m+": oDate.getMinutes(), //分"s+": oDate.getSeconds(), //秒"q+": Math.floor((oDate.getMonth() + 3) / 3), //季度"S": oDate.getMilliseconds()//毫秒};if (/(y+)/.test(fmt)) {fmt = fmt.replace(RegExp.$1, (oDate.getFullYear() + "").substr(4 - RegExp.$1.length));}for (var k in o) {if (new RegExp("(" + k + ")").test(fmt)) {fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));}}return fmt;}
</script>
</html>
视频回放:playback_for_iframe.html
<!doctype html>
<html>
<head><title>视频回放</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><meta http-equiv="Pragma" content="no-cache"/><meta http-equiv="Cache-Control" content="no-cache, must-revalidate"/><meta http-equiv="Expires" content="0"/>
</head>
<style>html, body {padding: 0;margin: 0;}.playWnd {margin: 30px 0 0 30px;width: 600px;height: 400px;border: 1px solid red;}.cbInfoDiv {float: left;width: 360px;margin-left: 16px;border: 1px solid #7F9DB9;}.cbInfo {height: 200px;padding: 5px;border: 1px solid #7F9DB9;word-break: break-all;overflow: auto;}.operate {margin-top: 24px;}.operate::after {content: '';display: block;clear: both;}.operate .btns {height: 32px;}.module {float: left;width: 120px;min-height: 290px;margin-left: 10px;padding: 16px 8px;box-sizing: border-box;border: 1px solid #e5e5e5;}.module .item {margin-bottom: 4px;}.module .label {width: 150px;display: inline-block;vertical-align: middle;margin-right: 8px;text-align: right;}.module input[type="text"],.module select {box-sizing: border-box;display: inline-block;vertical-align: middle;margin-left: 0;width: 150px;min-height: 20px;}.module .btn {min-width: 80px;min-height: 24px;margin-top: 16px;margin-left: 158px;}
</style>
<body>
<div id="playWnd" class="playWnd" style="left: 109px; top: 133px;"></div>
<div id="operate" class="operate"><!--初始化、反初始化、设置认证信息接口调用入口。1.插件所有接口都需要在调用初始化并返回成功后才能调用2.设置认证信息仅适用于对接多平台时的情况,具体参照开发指南3.反初始化后,插件资源销毁--><div class="module" style="left:30px;height:30px;width:280px;padding:10px;margin:10px;"><div class="item"><label>初始化相关参数:</label><textarea id="initParam" type="text" style="width:260px;height:200px;">
{"argument": {"appkey": "22547186","ip": "159.61.64.249","port": 443,"secret": "sPteT21oUI2CCav79heE","enableHTTPS": 1,"language": "zh_CN","layout": "3x3","playMode": 0,"reconnectDuration": 5,"reconnectTimes": 5,"showSmart": 0,"showToolbar": 1,"toolBarButtonIDs": "2048,2049,2050,2304,2306,2305,2307,2308,2309,4096,4608,4097,4099,4098,4609,4100","snapDir": "C:/snap","videoDir": "C:/video"},"funcName": "init"
}</textarea></div><div class="item"> <button style="width:10px;padding:0;margin:0;" id="initBtn" class="btn">执行</button></div></div><!--单个点位播放、批量点位播放、批量停止播放、全部停止播放接口调用入口。1.authUuid为对接多平台时必须的播放字段,对接单平台时,可不指定--><div class="module" style="height:30px;width:280px;padding:10px;margin:10px;"><div class="item"><label>播放相关参数:</label><textarea id="playParam" type="text" style="width:260px;height:200px;">{"argument": {"authUuid": "","cameraIndexCode": "d597b77b8c73459792c82ded3acb6eba","ezvizDirect": 0,"gpuMode": 0,"streamMode": 0,"transMode": 0,"wndId": -1,"cascade": 1},"funcName": "startPreview"}</textarea></div><div class="item"> <button style="width:10px;padding:0;margin:0;" id="playBtn" class="btn">执行</button></div></div><div class="module" style="height:50px;width:300px;padding:10px;margin:10px;"><legend>返回值信息</legend><div id="cbInfo" class="cbInfo"></div><button style="width:80px;height:24px;padding:30px;margin:0;" id="clear">清空</button></div>
</div>
</body>
<script src="jquery-1.12.4.min.js"></script>
<script src="jsencrypt.min.js"></script>
<script src="web-control_1.2.5.min.js"></script><script type="text/javascript">// 插件对象实例,初始化为null,需要创建多个插件窗口时,需要定义多个插件对象实例变量,各个变量唯一标志对应的插件实例var oWebControl = null;var bIE = (!!window.ActiveXObject || 'ActiveXObject' in window);// 是否为IE浏览器var pubKey = ''; // demo中未使用加密,可根据需求参照开发指南自行使用加密功能var initCount = 0; // 异常重启计数var iframePos = { }; // iframe相对文档的位置var parentTitle = ''; // 父页面标题var iframeClientPos = {left:200,top:200}; // iframe相对视窗的位置var iframeParentShowSize = null; // 视窗大小 width height// 标签关闭$(window).unload(function () {if (oWebControl != null) {oWebControl.JS_HideWnd(); // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题oWebControl.JS_Disconnect().then(function () {}, function () {});}});// 监听resize事件,使插件窗口尺寸跟随DIV窗口变化$(window).resize(function () {if (oWebControl != null) {oWebControl.JS_Resize(600, 400);setWndCover();}});// 监听滚动条scroll事件,使插件窗口跟随浏览器滚动而移动$(window).scroll(function () {if (oWebControl != null) {oWebControl.JS_Resize(600, 400);setWndCover();}});//监听父页面的消息window.addEventListener('message', function (e) {if (e && e.data) {switch (e.data.action) {case 'sendTitle': // 父页面将其标题发送过来,子页面保存该标题,以便创建插件窗口成功后将标题设置回给父页面parentTitle = e.data.info;break;case 'updatePos': // 更新插件位置var scrollValue = e.data.scrollValue; // 滚动条滚动偏移量oWebControl.JS_SetDocOffset({left: iframePos.left + scrollValue.left,top: iframePos.top + scrollValue.top}); // 更新插件窗口位置console.log("~~~~~~~~~~~~~~~~~")oWebControl.JS_Resize(600, 400);setWndCover();break;case 'scroll':iframeParentShowSize = e.data.showSize; // 视窗大小iframePos = e.data.iframeOffset; // iframe与文档的偏移量iframeClientPos = e.data.iframeClientPos; // iframe相对视窗的位置var scrollValue = e.data.scrollValue; // 滚动条滚动偏移量if (oWebControl) {oWebControl.JS_SetDocOffset({left: iframePos.left + scrollValue.left,top: iframePos.top + scrollValue.top}); // 更新插件窗口位置oWebControl.JS_Resize(600, 400);setWndCover();}break;default:break;}}});// 顶部:iframe.getBoundingClientRect().top小于0并且其绝对值超过DIV.get(0).getBoundingClientRect().top部分需要剪切// 底部:(iframe.getBoundingClientRect().bottom - iframe父窗口可视域高度,为H1)为不可见部分// ($(window).height() - DIV.get(0).getBoundingClientRect().bottom)// 为DIV底部与其所在iframe底部之间的距离H2,H1-H2的值大于0则表示DIV有部分在不可见区域// 左边:iframe.getBoundingClientRect().left小于0并且其绝对值超过DIV.get(0).getBoundingClientRect().left部分需要剪切// 右边:(iframe宽度 - DIV.get(0).getBoundingClientRect().right表示DIV右边与其父iframe右边之间的距离,为W1)// (iframe父窗口可视域宽度-iframe.getBoundingClientRect().left表示iframe左边与iframe父窗口可视域右边之间的距离,为W2)// (iframe宽度 - W2 - W1)如果大于0,则表示DIV右边超出了iframe父窗口可视域,需要剪切超过的部分function setWndCover() {if (oWebControl) {// 准备要用到的一些数据var iframeWndHeight = $(window).height(); // iframe窗口高度var iframeWndWidth = $(window).width(); // iframe窗口宽度var divLeft = $("#playWnd").get(0).getBoundingClientRect().left;var divTop = $("#playWnd").get(0).getBoundingClientRect().top;var divRight = $("#playWnd").get(0).getBoundingClientRect().right;var divBottom = $("#playWnd").get(0).getBoundingClientRect().bottom;var divWidth = $("#playWnd").width();var divHeight = $("#playWnd").height();oWebControl.JS_RepairPartWindow(0, 0, 801, 401); // 多1个像素点防止还原后边界缺失一个像素条// 判断剪切矩形的上边距if (iframeClientPos.top < 0 && Math.abs(iframeClientPos.top) > divTop) {var deltaTop = Math.abs(iframeClientPos.top) - divTop;oWebControl.JS_CuttingPartWindow(0, 0, 601, deltaTop + 1);//console.log({deltaTop: deltaTop});}// 判断剪切矩形的左边距if (iframeClientPos.left < 0 && Math.abs(iframeClientPos.left) > divLeft) {var deltaLeft = Math.abs(iframeClientPos.left) - divLeft;//console.log({deltaLeft: deltaLeft});oWebControl.JS_CuttingPartWindow(0, 0, deltaLeft, 401); // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条}// 判断剪切矩形的右边距var W1 = iframeWndWidth - divRight;var W2 = iframeParentShowSize.width - iframeClientPos.left;if (W2 < divWidth) {var deltaRight = iframeWndWidth - W2 - W1;if (deltaRight > 0) {oWebControl.JS_CuttingPartWindow(600 - deltaRight, 0, deltaRight + 1, 401);}}// 判断剪切矩形的下边距var H1 = iframeClientPos.bottom - iframeParentShowSize.height;var H2 = iframeWndHeight - divBottom;var deltaBottom = H1 - H2;//console.log({deltaBottom: deltaBottom});if (deltaBottom > 0) {oWebControl.JS_CuttingPartWindow(0, 400 - deltaBottom, 601, deltaBottom + 1);}}}// 创建插件实例,并启动本地服务建立websocket连接,创建插件窗口function initPlugin() {oWebControl = new WebControl({szPluginContainer: "playWnd",iServicePortStart: 15900,iServicePortEnd: 15900,szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsidcbConnectSuccess: function () {initCount = 0;setCallbacks();oWebControl.JS_StartService("window", {dllPath: "./VideoPluginConnect.dll"}).then(function () {// 步骤2:JS_CreateWnd时指定cbSetDocTitle回调,并在回调中向父页面发送更新标题消息,标题为回调出来的uuidoWebControl.JS_CreateWnd("playWnd", 600, 400, {bEmbed: true,cbSetDocTitle: function (uuid) {oWebControl._pendBg = false;window.parent.postMessage({action: 'updateTitle',msg: '子页面通知父页面修改title',info: uuid}, '\*'); // '\*'表示跨域参数,请结合自身业务合理设置}}).then(function () {// 步骤3:JS_CreateWnd成功后通知父页面将其标题修改回去console.log("JS_CreateWnd success");oWebControl.JS_SetDocOffset({left: 300,top: 100});window.parent.postMessage({action: 'updateTitle',msg: '子页面通知父页面更新title',info: parentTitle}, '\*');// 步骤4:发消息更新插件窗口位置:这里不直接更新的原因是,父页面默认可能就存在滚动条,此时有滚动量window.parent.postMessage({action: 'updatePos',msg: '更新Pos'}, '\*');initBtnClicked();});}, function () {console.log("JS_CreateWnd fail");});},cbConnectError: function () {console.log("cbConnectError");oWebControl = null;$("#playWnd").html("插件未启动,正在尝试启动,请稍候...");WebControl.JS_WakeUp("VideoWebPlugin://");initCount++;if (initCount < 3) {setTimeout(function () {initPlugin();}, 3000)} else {$("#playWnd").html("插件启动失败,请检查插件是否安装!");}},cbConnectClose: function (bNormalClose) {// 异常断开:bNormalClose = false// JS_Disconnect正常断开:bNormalClose = trueif (true == bNormalClose) {console.log("cbConnectClose normal");} else {console.log("cbConnectClose exception");}oWebControl = null;$("#playWnd").html("插件未启动,正在尝试启动,请稍候...");WebControl.JS_WakeUp("VideoWebPlugin://");initCount++;if (initCount < 3) {setTimeout(function () {initPlugin();}, 3000)} else {$("#playWnd").html("插件启动失败,请检查插件是否安装!");}}});}initPlugin();setTimeout(() => {}, 3000)// 获取公钥function getPubKey(callback) {oWebControl.JS_RequestInterface({funcName: "getRSAPubKey",argument: JSON.stringify({keyLength: 1024})}).then(function (oData) {console.log(oData)if (oData.responseMsg.data) {pubKey = oData.responseMsg.datacallback()}})}// 设置窗口控制回调function setCallbacks() {oWebControl.JS_SetWindowControlCallback({cbIntegrationCallBack: cbIntegrationCallBack});}// 推送消息function cbIntegrationCallBack(oData) {showCBInfo(JSON.stringify(oData.responseMsg));}// RSA加密function setEncrypt(value) {var encrypt = new JSEncrypt();encrypt.setPublicKey(pubKey);return encrypt.encrypt(value);}function requestInterface(value) {oWebControl.JS_RequestInterface(JSON.parse(value)).then(function (oData) {console.log(oData)showCBInfo(JSON.stringify(oData ? oData.responseMsg : ''));});}// 显示接口返回的消息及插件回调信息function showCBInfo(szInfo, type) {if (type === 'error') {szInfo = "<div style='color: red;'>" + dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss") + " " + szInfo + "</div>";} else {szInfo = "<div>" + dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss") + " " + szInfo + "</div>";}$("#cbInfo").html(szInfo + $("#cbInfo").html());}function initBtnClicked() {var param = $("#initParam").val();//删除字符串中的回车换行param = param.replace(/(\s*)/g, "");// 执行初始化requestInterface(param);}$("#initBtn").click(function () {initBtnClicked();})$("#playBtn").click(function () {var param = $("#playParam").val();//删除字符串中的回车换行param = param.replace(/(\s*)/g, "");// 执行预览requestInterface(param);})// 清空$("#clear").click(function () {$("#cbInfo").html('');})// 格式化时间function dateFormat(oDate, fmt) {var o = {"M+": oDate.getMonth() + 1, //月份"d+": oDate.getDate(), //日"h+": oDate.getHours(), //小时"m+": oDate.getMinutes(), //分"s+": oDate.getSeconds(), //秒"q+": Math.floor((oDate.getMonth() + 3) / 3), //季度"S": oDate.getMilliseconds()//毫秒};if (/(y+)/.test(fmt)) {fmt = fmt.replace(RegExp.$1, (oDate.getFullYear() + "").substr(4 - RegExp.$1.length));}for (var k in o) {if (new RegExp("(" + k + ")").test(fmt)) {fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));}}return fmt;}
</script>
</html>
indexTab.vue
<template><div class="user" style="height: 100vh;overflow: hidden;"><basic-container><el-tabs :lazy="true" v-model="activeName"><el-tab-pane label="实时视频" name="实时视频"><Video :activeName="activeName"></Video></el-tab-pane><el-tab-pane label="视频回放" name="视频回放"><rtspPlayer :activeName="activeName"></rtspPlayer></el-tab-pane></el-tabs></basic-container></div>
</template><script>
import Video from "@/views/video/index.vue";
import rtspPlayer from "@/views/video/rtspPlayer.vue";export default {components: {Video, rtspPlayer},data() {return {activeName: '实时视频'};},computed: {},created() {},mounted() {},methods: {}
};
</script>
<style scoped lang="scss">
::v-deep .el-tabs__item {font-size: 18px !important;/* 设置你想要的字体大小 */letter-spacing: 2px
}
::v-deep #avue-view{overflow: hidden !important;
}
</style>
rtspPlayer.vue
<template><div><div><span>回放时间:</span><br><el-date-picker style="width: 12%;margin-bottom: 5px;margin-top: 5px" v-model="startTime" type="datetime"value-format="yyyy-MM-dd HH:mm:ss" @blur="dateBlur" @focus="dateFocus" placeholder="开始时间"></el-date-picker><br><el-date-picker style="width: 12%;" v-model="endTime" type="datetime"value-format="yyyy-MM-dd HH:mm:ss" @blur="dateBlur" @focus="dateFocus" placeholder="结束时间"></el-date-picker><el-row style="display: flex;"><div class="user__tree" style="margin-top: 30px;overflow:auto;height: 72vh;font-size: 18px;width: 280px;">
<!-- <avue-tree :option="treeOption" :data="treeData" style="width: 320px;">-->
<!-- <span class="el-tree-node__label" slot-scope="{ node, data }" style="display: flex;align-items: center;font-size: 18px">-->
<!--<!– <span v-if="data.isOnline===0" class="tree_icon_red"></span>–>-->
<!--<!– <span v-if="data.isOnline===1" class="tree_icon_green"></span>–>-->
<!-- <span :class="{ 'last-level-node': !data.children || data.children.length === 0 }" @dblclick="dblclick(node, data)">{{ node.label }}</span>-->
<!-- </span>-->
<!-- </avue-tree>--><el-tree:data="treeData":option="treeOption"class="disable-selection"empty-text="加载中,请稍后"node-key="areaId":default-expanded-keys="defaultExpandedKeys":props="defaultProps"><spanclass="el-tree-node__label"slot-scope="{ node, data }":class="{ 'last-level-node': !data.children || data.children.length === 0 }"@dblclick="dblclick(node, data)"style="display: flex;align-items: center;font-size: 18px;"><span>{{ data.name }}</span></span></el-tree></div><el-col :span="10" class="user__main" style="width: 100%;"><div v-if="activeName == '视频回放' && iframeShow" style="width: 100%;"><iframe style="width: 100%;height: 75vh" scrolling="no" ref="iframe":src="`${rtsp_ifarme_url}/in/demo_for_iframe.html?videoType=back`"frameborder="0"></iframe><!-- cameraCode=${cameraCode}& --></div></el-col></el-row></div></div>
</template><script>
import { deptRoleList } from "@/api/admin/role";
import { fetchTree } from "@/api/admin/dept";
import { tableOption } from "@/const/crud/admin/user";
import { mapGetters } from "vuex";import Preview from "@/views/video/rtsp_video_c/Preview.vue";
import request from "@/router/axios";
import PreviewS from "@/views/video/rtsp_video_c/PreviewS.vue";export default {name: "Video",components: {PreviewS,Preview},//父组件传过来的props: {activeName: {type: String,default: ''},},data() {return {defaultProps: {children: "children",label: "name"},defaultExpandedKeys:[],sliderShow: true,sliderValue: 0,totalPage: 0,queryParams: {},tableData: [], //列表playUrl: '', //播放的urlendUrl: '',//关闭时传的urltreeOption: {nodeKey: "id",addBtn: false,defaultExpandAll: true,menu: false,props: {label: "name",value: "id"}},treeData: [],rtsp: '',node: undefined,row: undefined,playbackTime: [],sliderUrl: '',cameraCode: '',iframeShow: true,startTime: '',endTime: '',startDate:'',endDate:'',rtsp_ifarme_url:process.env.rtsp_ifarme_url};},computed: {sliderMax() {let start = new Date(this.startTime).getTime();let end = new Date(this.endTime).getTime();console.log(start)console.log(end)let time = (end - start) / 1000this.sliderValue = time;return time;}},created() {this.init();},mounted() {this.defaultExpandedKeys = '3703';},methods: {//选择时间弹框弹出dateFocus() {this.iframeShow = false},//选择时间弹框隐藏,视频显示dateBlur() {this.iframeShow = true},convertDateStringToTimestamp(dateString) {var date = new Date(dateString);let ts = Math.round(new Date(dateString).getTime()/1000).toString();console.log("时间:",ts)// 返回时间戳return ts;},jie() {request({url: '/ewaycloud/video/record',method: 'get',params: {caseId: this.row.cameraId,streamUrl: this.endUrl,durationSceond: this.sliderValue}}).then(res => {if (res.code == 0) {this.$message.success('截取成功')this.sliderShow = false;this.sliderUrl = res.data.datathis.sliderUrlPlay()}})},formatTooltip(val) {return val + "s";val = '' + valif (val.indexOf(".") != -1) {val = val.split(".")return val[0] + ':' + (val[1] < 10 ? '0' + val[1] : val[1])} else {return val + ":00";}},closePreview() {if (this.rtsp) {request({url: process.env.STREAM_CLOSE_URL,method: 'post',data: {urls: [this.rtsp]}}).then(res => {this.talkerJob = res.data.data.records.map(item => {return {label: item.jobName,value: item.id}})})}},sliderUrlPlay() {this.sliderUrl = '/猫狗大战03.mp4';this.$nextTick(() => {this.$refs.preview.handlePlay(this.sliderUrl, 0, {});})},dblclick(node, row) {if (this.startTime.length == 0||this.endTime.length == 0) {this.$message.warning('请选择时间')return}this.node = nodethis.row = rowif (row.children == 0) {console.log("根节点")console.log('node', node)console.log('row', row)console.log(this.playbackTime, 'paytime');let parentData = node.parent.data.childrenthis.cameraCode = row.cameraCodethis.startDate = this.convertDateStringToTimestamp(this.startTime)this.endDate = this.convertDateStringToTimestamp(this.endTime)console.log(this.startTime, 'startTime', this.endTime, 'endtime',this.cameraCode,'cameracode');this.sendMesFroIframe(this.cameraCode);// this.cameraCode = row.cameraCode// request({// url: '/ewaycloud/channel/hik/playbackURLs',// method: 'get',// params: {// cameraIndexCode: this.cameraCode,// beginTime: this.playbackTime[0],// endTime: this.playbackTime[1],// },// }).then(res => {/* this.playUrl = process.env.STREAM_URL + '/live?url=' + res.data.data.url + '&&&ffmpeg=true';//this.playUrl = process.env.STREAM_URL + '/live?url=' + 'rtsp://rtspstream:e06d5bdf15e5f992e39ebb33506c805e@zephyr.rtsp.stream/movie';// this.playUrl = '/猫狗大战03.mp4';this.$nextTick(() => {this.$refs.previews.handlePlay(this.playUrl, 0, row);})this.endUrl = res.data.data.url + '&&&ffmpeg=true';//this.endUrl = 'rtsp://rtspstream:e06d5bdf15e5f992e39ebb33506c805e@zephyr.rtsp.stream/movie'this.sliderShow = true */// })}},sendMesFroIframe(cameraCode) {// 向iframe传值const mapFrame = this.$refs['iframe'];const iframeWin = mapFrame.contentWindow;iframeWin.postMessage({action:'cameraCode',cameraCode: cameraCode,startTime:this.startDate,endTime:this.endDate},'*');},// 每页数sizeChangeHandle(val) {this.queryParams.pageSize = valthis.queryParams.pageIndex = 1this.getList()},// 当前页currentChangeHandle(val) {this.pageIndex = valthis.getList()},init() {request({url: '/ewaycloud/camera/findCameraDeptTreeList',method: 'get',}).then(res => {this.treeData = res.data.data;this.$set(this.treeData[0].children[0].children[0],'status','0')this.$set(this.treeData[0].children[0].children[1],'status','1')this.$set(this.treeData[0].children[0].children[2],'status','1')console.log(this.treeData[0].children[0].children[2]);console.log(this.treeData[0].children[0].children[0],'this.treeData[0].children[3].children[0]');this.$set(this.treeData[0].children[0].children[3].children[0],'status','0')})},getList() {request({url: '/ewaycloud/camera/findCamerList',method: 'get',params: this.queryParams}).then(res => {this.tableData = res.data.data.records;this.totalPage = res.data.data.total;})},nodeClick(data) {this.queryParams.deptId = data.id;this.getList();},}
};
</script>
<style lang="scss" scoped>
.user {height: 100%;&__tree {padding-top: 3px;padding-right: 20px;}&__main {.el-card__body {padding-top: 0;}}
}.hover-cursor {cursor: pointer;/* 鼠标移入单元格时显示小手形状 */
}
.tree_icon_red{background-color: red;display: inline-block;width: 5px;height: 5px;border-radius: 50%;margin-right: 5px;
}
.tree_icon_green{background-color: green;display: inline-block;width: 5px;height: 5px;border-radius: 50%;margin-right: 5px;
}
.divSelect:hover {cursor: pointer;
}
::v-deep .avue-tree__filter{position: sticky;top: -0.15rem;left: 2rem;background-color: #fff;z-index: 99;width: 100%;
}
::v-deep .el-scrollbar{min-height: 200px;
}
::v-deep .el-tree-node__expand-icon{font-size: 18px !important;
}
.last-level-node {font-size: 16px !important;}
.disable-selection {user-select: none; /* 标准语法 */-webkit-user-select: none; /* Chrome, Safari, Opera */-moz-user-select: none; /* Firefox */-ms-user-select: none; /* IE10+/Edge */
}
</style>
Preview.vue
<template><div><divstyle="display: flex;justify-content: center;align-items: center;bottom: 0px;top: 215px;width: 100%;height: 600px;"><!-- 1*1 --><divstyle="width: 100%;height: 100%;margin-left: 20px;border: 2px solid #779BEF;margin-top: 10px"v-if="selected == 0"><el-row type="flex" style="min-height: 100%;" justify="center"><el-col :span="24"><div @click="clickVideo(0)" :class="videoIndex == 0 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video0"></cus-player></div></el-col></el-row></div><!-- 2*2 --><divstyle="width: 100%;height: 100%;margin-left: 20px;border-top: 2px solid #779BEF;border-left: 2px solid #779BEF"v-else-if="selected == 1"><el-row :gutter="1" type="flex" style="height: 50%;" justify="center"><el-col :span="12"><div @click="clickVideo(0)" :class="videoIndex == 0 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video0"></cus-player></div></el-col><el-col :span="12"><div @click="clickVideo(1)" :class="videoIndex == 1 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video1"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 50%;" class="row-bg" justify="center"><el-col :span="12"><div @click="clickVideo(2)" :class="videoIndex == 2 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video2"></cus-player></div></el-col><el-col :span="12"><div @click="clickVideo(3)" :class="videoIndex == 3 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video3"></cus-player></div></el-col></el-row></div><!-- 3*3 --><div style="height:100%;width:100%;margin-left: 20px;border-top: 2px solid #779BEF;border-left: 2px solid #779BEF"v-else-if="selected == 2"><el-row :gutter="1" type="flex" style="height: 33.333%;" justify="center"><el-col :span="8"><div @click="clickVideo(0)" :class="videoIndex == 0 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video0"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(1)" :class="videoIndex == 1 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video1"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(2)" :class="videoIndex == 2 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video2"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 33.333%;" justify="center"><el-col :span="8"><div @click="clickVideo(3)" :class="videoIndex == 3 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video3"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(4)" :class="videoIndex == 4 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video4"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(5)" :class="videoIndex == 5 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video5"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 33.333%;" class="row-bg" justify="center"><el-col :span="8"><div @click="clickVideo(6)" :class="videoIndex == 6 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video6"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(7)" :class="videoIndex == 7 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video7"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(8)" :class="videoIndex == 8 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video8"></cus-player></div></el-col></el-row></div><!-- 4*4 --><div style="height:100%;width:100%;margin-left: 20px;border-top: 2px solid #779BEF;border-left: 2px solid #779BEF"v-else-if="selected == 3"><el-row :gutter="1" type="flex" style="height: 25%;" justify="center"><el-col :span="6"><div @click="clickVideo(0)" :class="videoIndex == 0 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video0"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(1)" :class="videoIndex == 1 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video1"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(2)" :class="videoIndex == 2 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video2"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(3)" :class="videoIndex == 3 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video3"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 25%;" justify="center"><el-col :span="6"><div @click="clickVideo(4)" :class="videoIndex == 4 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video4"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(5)" :class="videoIndex == 5 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video5"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(6)" :class="videoIndex == 6 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video6"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(7)" :class="videoIndex == 7 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video7"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 25%;" justify="center"><el-col :span="6"><div @click="clickVideo(8)" :class="videoIndex == 8 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video8"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(9)" :class="videoIndex == 9 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video9"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(10)" :class="videoIndex == 10 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video10"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(11)" :class="videoIndex == 11 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video11"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 25%;" justify="center"><el-col :span="6"><div @click="clickVideo(12)" :class="videoIndex == 12 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video12"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(13)" :class="videoIndex == 13 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video13"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(14)" :class="videoIndex == 14 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video14"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(15)" :class="videoIndex == 15 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video15"></cus-player></div></el-col></el-row></div></div></div>
</template><script>
import 'xgplayer';
import FlvJsPlayer from 'xgplayer-flv.js';
import CusPlayer from './CusPlayer';
import request from "@/router/axios";export default {components: {CusPlayer},props: {playUrl: String,endUrl: String,},data() {return {selected: 0, //表格类型videoIndex: 0, //表格索引tableData: [], //列表selectValue: '', //当前选择的相机};},created() {this.getList();},methods: {selectType(selected) {this.selected = selected;},clickVideo(index) {this.videoIndex = index;},getList() {},handlePlay(url, videoIndex, row) {this.videoIndex = videoIndexif (url) {let ref = 'video' + this.videoIndex;let dynamicDiv = this.$refs[ref];dynamicDiv.createPlayer(url, true, this.videoIndex);} else {this.$message.error('请填写播放地址');}},clickPlayer(index) {this.videoIndex = index;}}
};
</script><style scoped>.video {border: 2px solid #779BEF;height: 100%;width: 100%;position: relative;
}.el-col {margin-bottom: 0px !important;border: 0px !important;
}
</style>
PreviewS.vue
<template><div><divstyle="display: flex;justify-content: center;align-items: center;bottom: 0px;top: 215px;width: 100%;height: 600px;"><!-- 1*1 --><divstyle="width: 100%;height: 100%;margin-left: 20px;border: 2px solid #779BEF;margin-top: 10px"v-if="selected == 0"><el-row type="flex" style="min-height: 100%;" justify="center"><el-col :span="24"><div @click="clickVideo(0)" :class="videoIndex == 0 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video0"></cus-player></div></el-col></el-row></div><!-- 2*2 --><divstyle="width: 100%;height: 100%;margin-left: 20px;border-top: 2px solid #779BEF;border-left: 2px solid #779BEF"v-else-if="selected == 1"><el-row :gutter="1" type="flex" style="height: 50%;" justify="center"><el-col :span="12"><div @click="clickVideo(0)" :class="videoIndex == 0 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video0"></cus-player></div></el-col><el-col :span="12"><div @click="clickVideo(1)" :class="videoIndex == 1 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video1"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 50%;" class="row-bg" justify="center"><el-col :span="12"><div @click="clickVideo(2)" :class="videoIndex == 2 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video2"></cus-player></div></el-col><el-col :span="12"><div @click="clickVideo(3)" :class="videoIndex == 3 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video3"></cus-player></div></el-col></el-row></div><!-- 3*3 --><div style="height:100%;width:100%;margin-left: 20px;border-top: 2px solid #779BEF;border-left: 2px solid #779BEF"v-else-if="selected == 2"><el-row :gutter="1" type="flex" style="height: 33.333%;" justify="center"><el-col :span="8"><div @click="clickVideo(0)" :class="videoIndex == 0 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video0"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(1)" :class="videoIndex == 1 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video1"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(2)" :class="videoIndex == 2 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video2"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 33.333%;" justify="center"><el-col :span="8"><div @click="clickVideo(3)" :class="videoIndex == 3 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video3"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(4)" :class="videoIndex == 4 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video4"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(5)" :class="videoIndex == 5 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video5"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 33.333%;" class="row-bg" justify="center"><el-col :span="8"><div @click="clickVideo(6)" :class="videoIndex == 6 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video6"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(7)" :class="videoIndex == 7 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video7"></cus-player></div></el-col><el-col :span="8"><div @click="clickVideo(8)" :class="videoIndex == 8 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video8"></cus-player></div></el-col></el-row></div><!-- 4*4 --><div style="height:100%;width:100%;margin-left: 20px;border-top: 2px solid #779BEF;border-left: 2px solid #779BEF"v-else-if="selected == 3"><el-row :gutter="1" type="flex" style="height: 25%;" justify="center"><el-col :span="6"><div @click="clickVideo(0)" :class="videoIndex == 0 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video0"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(1)" :class="videoIndex == 1 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video1"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(2)" :class="videoIndex == 2 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video2"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(3)" :class="videoIndex == 3 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video3"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 25%;" justify="center"><el-col :span="6"><div @click="clickVideo(4)" :class="videoIndex == 4 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video4"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(5)" :class="videoIndex == 5 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video5"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(6)" :class="videoIndex == 6 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video6"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(7)" :class="videoIndex == 7 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video7"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 25%;" justify="center"><el-col :span="6"><div @click="clickVideo(8)" :class="videoIndex == 8 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video8"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(9)" :class="videoIndex == 9 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video9"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(10)" :class="videoIndex == 10 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video10"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(11)" :class="videoIndex == 11 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video11"></cus-player></div></el-col></el-row><el-row :gutter="1" type="flex" style="height: 25%;" justify="center"><el-col :span="6"><div @click="clickVideo(12)" :class="videoIndex == 12 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video12"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(13)" :class="videoIndex == 13 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video13"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(14)" :class="videoIndex == 14 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video14"></cus-player></div></el-col><el-col :span="6"><div @click="clickVideo(15)" :class="videoIndex == 15 ? 'selectVideo' : 'video'"><cus-player @clickPlayer="clickPlayer" ref="video15"></cus-player></div></el-col></el-row></div></div></div>
</template><script>
import 'xgplayer';
import FlvJsPlayer from 'xgplayer-flv.js';
import CusPlayer from './CusPlayerS';
import request from "@/router/axios";export default {components: {CusPlayer},props: {playUrl: String,endUrl: String,},data() {return {selected: 0, //表格类型videoIndex: 0, //表格索引tableData: [], //列表selectValue: '', //当前选择的相机};},created() {this.getList();},methods: {selectType(selected) {this.selected = selected;},clickVideo(index) {this.videoIndex = index;},getList() {},handlePlay(url, videoIndex, row) {this.videoIndex = videoIndexif (url) {let ref = 'video' + this.videoIndex;let dynamicDiv = this.$refs[ref];dynamicDiv.createPlayer(url, true, this.videoIndex);} else {this.$message.error('请填写播放地址');}},clickPlayer(index) {this.videoIndex = index;}}
};
</script><style scoped>.video {border: 2px solid #779BEF;height: 100%;width: 100%;position: relative;
}.el-col {margin-bottom: 0px !important;border: 0px !important;
}
</style>
CusPlayerS.vue
<template><divstyle="position: absolute;height: 100%;width: 100%;display: flex;align-items: center;justify-content: center;flex-direction: column"><div class="video" v-show="isPlay" :id="elId"></div><div v-show="!isPlay" style="color: #888888;font-size: 25px;">暂无视频源</div></div>
</template><script>
import FlvJsPlayer from 'xgplayer-flv.js';
import Player from 'xgplayer';
import {v4} from 'uuid';
import request from "@/router/axios";export default {name: 'CusPlayer',components: {},data() {return {title: '',isPlay: false,player: null,elId: '',playUrl: String};},created() {this.elId = v4(); // 避免key重复},mounted() {var that = this;document.addEventListener('visibilitychange', function () {// console.log(document.visibilityState);// console.log(document.hidden);if (document.hidden) {console.log("页面隐藏")}});},methods: {createPlayer(url, hasCloseBtn, index) {if (!url) {return;}this.playUrl = url.slice(33);if (this.player) {this.changeVideo(url);return;}this.isPlay = true;this.player = new FlvJsPlayer({id: this.elId,url: url,// fitVideoSize: 'auto',fluid: true,autoplay: true,isLive: true,playsinline: false,screenShot: true,whitelist: [''],ignores: ['time'],closeVideoClick: true,// errorTips: '<span class="app-error">无视频源</span>',customConfig: {isClickPlayBack: false},flvOptionalConfig: {enableWorker: true,enableStashBuffer: true, //启用缓存stashInitialSize: 4096, //缓存大小4mlazyLoad: false,lazyLoadMaxDuration: 40 * 60,autoCleanupSourceBuffer: true,autoCleanupMaxBackwardDuration: 35 * 60,autoCleanupMinBackwardDuration: 30 * 60} //flv.js可选配置项 [flv.js配置](https://github.com/bilibili/flv.js/blob/master/docs/api.md#config)});// 自定义播放器按钮// let divStr =// '<i class="btn-hover el-icon-camera button-screen-shot" style="font-size: 23px;margin-right: 10px;pointer-events: auto;"></i>' +// '<i class="btn-hover el-icon-s-tools button-set" style="font-size: 23px;margin-right: 10px;pointer-events: auto;"></i>' +// '<i class="btn-hover el-icon-video-camera-solid button-history" style="font-size: 23px;margin-right: 10px;pointer-events: auto;"></i>';let divStr = '<i class="btn-hover el-icon-d-arrow-left button-playback" style="font-size: 23px;pointer-events: auto;"></i>';let divClose = '<i @click="closePlayer" class="btn-hover el-icon-close app-close-btn-c"></i>';let util = Player.util;// let customBtn = util.createDom('div', divStr, {}, 'flex align-center justify-center app-player-button'); //'div', divStr, {}, 'class'let customBtn = util.createDom('div',divStr,{style: 'width: 40px;heigth:40px;position: absolute;right: 155px;top: 7px;'},'flex align-center justify-center app-player-button'); //'div', divStr, {}, 'class'let closeBtn = util.createDom('div', divClose, {}, 'app-close-btn');let xgControls = this.player.root.querySelector('xg-controls');let xgError = this.player.root.querySelector('xg-error');xgControls.appendChild(customBtn);this.player.root.appendChild(closeBtn);// let shot = customBtn.querySelector('.button-screen-shot');// let set = customBtn.querySelector('.button-set');// let history = customBtn.querySelector('.button-history');let closeBtnc = closeBtn.querySelector('.app-close-btn-c');let playback = customBtn.querySelector('.button-playback');this.player.on('play', () => {});this.player.on('focus', () => {if (hasCloseBtn) {closeBtn.style.display = 'block';}});this.player.on('ended', () => {});this.player.on('blur', () => {closeBtn.style.display = 'none';});this.player.on('error', () => {});if (closeBtnc) {closeBtnc.addEventListener('click', () => {this.closePlayer();});}// 点击视频时间,设置selectIndexthis.player.video.addEventListener('click', () => {// this.selectIndex = index;// this.$parent.setSelectIndex(index);this.$emit('clickPlayer', index);});// if (shot) {// shot.addEventListener('click', () => {// this.screenShot(index);// });// }// if (set) {// set.addEventListener('click', () => {// this.setPlay(index);// });// }// if (history) {// history.addEventListener('click', () => {// this.playHistory(index);// });// }},changeVideo(url) {this.player.src = url;this.playUrl = url.slice(33);},closePlayer() {this.isPlay = false;if (this.player) {this.player.destroy();//关闭视频流request({url: '/ewaycloud/channel/hik/clearPlayUrls',method: 'get',params: {url: this.playUrl},}).then(res => {console.log(res.data.data.records);})}}},beforeDestroy() {if (this.player) {this.player.destroy();}// clearInterval(this.intvBuffer);console.log('销毁了');}// destroyed() {// if(this.player){// this.player.destroy();// }// }
};
</script>
<style>
.btn-hover:hover {color: #888888;cursor: pointer;
}.btn-hover {color: #ffffff;
}.video {position: relative !important;height: 100% !important;width: 100% !important;padding-top: 0px !important;
}.app-close-btn {position: absolute;top: 0px;right: 5px;z-index: 500;display: none;
}.app-close-btn-c {color: #aaffff;font-size: 25px;pointer-events: auto;z-index: 500;
}
</style>
video_demo.vue
<template><div class="videoMain" ref="playWndBox"><div id="playWnd" class="playWnd" :style="{height: playWndHeight + 'px',width: playWndWidth + 'px',}"></div></div>
</template><script >
export default {name: "HikVideo",data() {return {// 视频盒子的高度playWndHeight: "",// 视频盒子的宽度playWndWidth: "",oWebControl: null,initCount: 0,pubKey: "",cameraIndexCode: "25603528001310681100", // 这里面是监控点编号objData: {//海康初始化数据appkey: "22547186",ip: "159.61.64.249",secret: "sPteT21oUI2CCav79heE",port: 443,playMode: 0, // 0 预览 1回放layout: "1x1", //页面展示的模块数【16】},}},mounted() {// 首次加载时的到父容器的高度this.playWndHeight = this.$refs.playWndBox.clientHeight;// 首次加载时的到父容器的宽度this.playWndWidth = this.$refs.playWndBox.clientWidth;// 初始化播放器插件this.$nextTick(() => {this.initPlugin();});// 监听scroll事件,使插件窗口尺寸跟随DIV窗口变化window.addEventListener("scroll", () => {if (this.oWebControl != null) {this.oWebControl.JS_Resize(this.$refs.playWndBox.clientWidth,this.$refs.playWndBox.clientHeight);this.setWndCover();}});// 监听resize事件,使插件窗口尺寸跟随DIV窗口变化window.addEventListener("resize", (e) => {if (this.oWebControl != null) {this.oWebControl.JS_Resize(this.$refs.playWndBox.clientWidth,this.$refs.playWndBox.clientHeight);this.setWndCover();}});},destroyed() {if (this.oWebControl != null) {// 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题this.oWebControl.JS_HideWnd();// 销毁当前播放的视频this.oWebControl.JS_RequestInterface({ funcName: "destroyWnd" });// 断开与插件服务连接this.oWebControl.JS_Disconnect();}},methods: {// 创建播放实例initPlugin() {let that = this;this.oWebControl = null;that.oWebControl = new WebControl({szPluginContainer: "playWnd", // 指定容器idiServicePortStart: 15900, // 指定起止端口号,建议使用该值iServicePortEnd: 15909,szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsidcbConnectSuccess: () => {// 创建WebControl实例成功that.oWebControl.JS_StartService("window", {// WebControl实例创建成功后需要启动服务// 值"./VideoPluginConnect.dll"写死dllPath: "./VideoPluginConnect.dll",}).then(function () {// 设置消息回调that.oWebControl.JS_SetWindowControlCallback({cbIntegrationCallBack: that.cbIntegrationCallBack,});//JS_CreateWnd创建视频播放窗口,宽高可设定that.oWebControl.JS_CreateWnd("playWnd", 2040, 945, { bEmbed: true })//注:2040,945这是我本人项目视频盒子的大小,你们要根据自己视频盒子的大小进行修改,不然初始化插件的时候会有空白闪烁。.then(function () {// 创建播放实例成功后初始化that.init();});},function () {// 启动插件服务失败});},// 创建WebControl实例失败cbConnectError: function () {that.oWebControl = null;// alert('插件未启动,正在尝试启动,请稍候...')// that.$message.warning("插件未启动,正在尝试启动,请稍候...");// 程序未启动时执行error函数,采用wakeup来启动程序window.WebControl.JS_WakeUp("VideoWebPlugin://");that.initCount++;if (that.initCount < 3) {setTimeout(function () {that.initPlugin();}, 3000);} else {}},cbConnectClose: () => {// 异常断开:bNormalClose = false// JS_Disconnect正常断开:bNormalClose = true// console.log("cbConnectClose");that.oWebControl = null;},});},// 初始化init(callback) {let that = this;that.getPubKey(() => {let appkey = that.objData.appkey; //综合安防管理平台提供的appkey,必填let secret = that.setEncrypt(that.objData.secret); //综合安防管理平台提供的secret,必填let ip = that.objData.ip; //综合安防管理平台IP地址,必填let playMode = that.objData.playMode; //初始播放模式:0-预览,1-回放let port = that.objData.port; //综合安防管理平台端口,若启用HTTPS协议,默认443let snapDir = "D:\\SnapDir"; //抓图存储路径let videoDir = "D:\\VideoDir"; //紧急录像或录像剪辑存储路径let layout = that.objData.layout; //playMode指定模式的布局let enableHTTPS = 1; //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1let encryptedFields = "secret"; //加密字段,默认加密领域为secretlet showToolbar = 1; //是否显示工具栏,0-不显示,非0-显示let showSmart = 1; //是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示let buttonIDs = "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769"; //自定义工具条按钮// var toolBarButtonIDs = "2049,2304" // 工具栏上自定义按钮that.oWebControl.JS_RequestInterface({funcName: "init",argument: JSON.stringify({appkey: appkey, //API网关提供的appkeysecret: secret, //API网关提供的secretip: ip, //API网关IP地址playMode: playMode, //播放模式(决定显示预览还是回放界面)port: port, //端口snapDir: snapDir, //抓图存储路径videoDir: videoDir, //紧急录像或录像剪辑存储路径layout: layout, //布局enableHTTPS: enableHTTPS, //是否启用HTTPS协议encryptedFields: encryptedFields, //加密字段showToolbar: showToolbar, //是否显示工具栏showSmart: showSmart, //是否显示智能信息buttonIDs, //自定义工具条按钮}),}).then(function (oData) {that.oWebControl.JS_Resize(that.playWndWidth, that.playWndHeight); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题if (callback) {callback();}// 隐藏// that.oWebControl.JS_HideWnd()});});},// 获取公钥getPubKey(callback) {let that = this;this.oWebControl.JS_RequestInterface({funcName: "getRSAPubKey",argument: JSON.stringify({keyLength: 1024,}),}).then(function (oData) {if (oData.responseMsg.data) {that.pubKey = oData.responseMsg.data;callback();}});},// RSA 加密setEncrypt(value) {let that = this;let encrypt = new window.JSEncrypt();encrypt.setPublicKey(that.pubKey);return encrypt.encrypt(value);},// 回调的消息cbIntegrationCallBack(oData) {let { responseMsg: type } = oData;if (type === "error") {} else {}},// 视频预览功能previewVideo(data) {let that = this;let cameraIndexCode = data; // 获取输入的监控点编号值,必填let streamMode = 0; // 主子码流标识:0-主码流,1-子码流let transMode = 0; // 传输协议:0-UDP,1-TCPlet gpuMode = 0; // 是否启用GPU硬解,0-不启用,1-启用let wndId = -1; // 播放窗口序号(在2x2以上布局下可指定播放窗口)// console.log(cameraIndexCode, "-------cameraIndexCode-");that.oWebControl.JS_RequestInterface({funcName: "startPreview",argument: JSON.stringify({cameraIndexCode: cameraIndexCode.trim(), // 监控点编号streamMode: streamMode, // 主子码流标识transMode: transMode, // 传输协议gpuMode: gpuMode, // 是否开启GPU硬解wndId: wndId, // 可指定播放窗口}),});},// 停止全部预览stopAllPreview() {this.oWebControl.JS_RequestInterface({funcName: "stopAllPreview",});},// 格式化时间dateFormat(oDate, fmt) {let o = {"M+": oDate.getMonth() + 1, //月份"d+": oDate.getDate(), //日"h+": oDate.getHours(), //小时"m+": oDate.getMinutes(), //分"s+": oDate.getSeconds(), //秒"q+": Math.floor((oDate.getMonth() + 3) / 3), //季度S: oDate.getMilliseconds(), //毫秒};if (/(y+)/.test(fmt)) {fmt = fmt.replace(RegExp.$1,(oDate.getFullYear() + "").substr(4 - RegExp.$1.length));}for (let k in o) {if (new RegExp("(" + k + ")").test(fmt)) {fmt = fmt.replace(RegExp.$1,RegExp.$1.length == 1? o[k]: ("00" + o[k]).substr(("" + o[k]).length));}}return fmt;},// 设置窗口裁剪,当因滚动条滚动导致窗口需要被遮住的情况下需要JS_CuttingPartWindow部分窗口setWndCover() {var iWidth = $(window).width();var iHeight = $(window).height();var oDivRect = $("#playWnd").get(0).getBoundingClientRect();var iCoverLeft = (oDivRect.left < 0) ? Math.abs(oDivRect.left) : 0;var iCoverTop = (oDivRect.top < 0) ? Math.abs(oDivRect.top) : 0;var iCoverRight = (oDivRect.right - iWidth > 0) ? Math.round(oDivRect.right - iWidth) : 0;var iCoverBottom = (oDivRect.bottom - iHeight > 0) ? Math.round(oDivRect.bottom - iHeight) : 0;iCoverLeft = (iCoverLeft > 2041) ? 2041 : iCoverLeft;iCoverTop = (iCoverTop > 945) ? 945 : iCoverTop;iCoverRight = (iCoverRight > 2041) ? 2041 : iCoverRight;iCoverBottom = (iCoverBottom > 945) ? 945 : iCoverBottom;this.oWebControl.JS_RepairPartWindow(0, 0, 2041, 946); // 多1个像素点防止还原后边界缺失一个像素条if (iCoverLeft != 0) {this.oWebControl.JS_CuttingPartWindow(0, 0, iCoverLeft, 946);}if (iCoverTop != 0) {this.oWebControl.JS_CuttingPartWindow(0, 0, 2041, iCoverTop); // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条}if (iCoverRight != 0) {this.oWebControl.JS_CuttingPartWindow(2041 - iCoverRight, 0, iCoverRight, 946);}if (iCoverBottom != 0) {this.oWebControl.JS_CuttingPartWindow(0, 946 - iCoverBottom, 2041, iCoverBottom);}},}}
</script><style lang="less" scoped>
.videoMain {width: 50vw;height: 50vh;
}
</style>
demo_for_iframe.html
<!doctype html>
<html>
<head><title>Window Demo</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta http-equiv="Pragma" content="no-cache" /><meta http-equiv="Cache-Control" content="no-cache, must-revalidate" /><meta http-equiv="Expires" content="0" />
</head>
<style>
html, body {padding: 0;margin: 0;
}
.iframe {height: 100vh/* margin: 100px; *//* border: 1px solid blue; */
}
</style>
<body><!-- 步骤1:src指定待嵌入的子页面,scrolling指定no禁用滚动条 --><iframe id="iframeVideo" class="iframe" src="./demo_embedded_for_iframe.html" scrolling="no" frameborder="0" width="100%"></iframe>
</body>
<script src="jquery-1.12.4.min.js"></script>
<script src="jsencrypt.min.js"></script>
<script src="web-control_1.2.5.min.js"></script>
<!-- <script src="JsonToXml.js"></script>
<script src="jsWebControl-Bridge.js"></script> -->
<script type="text/javascript">console.log("进入了:::");// 步骤2:嵌入子页面的页面中在iframe的onload事件中向子页面抛以下消息var iframeWin = document.getElementById("iframeVideo");{iframeWin.onload = function(){const url = new URL(window.location.href);console.log(url,'这是url')// 使用URLSearchParams API获取查询参数const searchParams = new URLSearchParams(url.search);// 获取cameraCode参数const videoType = searchParams.get('videoType')/* const cameraCode = searchParams.get('cameraCode');if (cameraCode) {console.log('这里是成功获取 cameraCode:', cameraCode);// 在这里处理cameraCode,例如赋值给某个变量或调用相关函数} else {console.error('失败获取 cameraCode parameter found in the URL.');} */iframeWin.contentWindow.postMessage({action:'sendTitle', // 告诉子页面本页面的标题(action自行指定,但需要与子页面中监听的action保持一致msg: '将标题发给子页面',info: document.title,// cameraCode:cameraCode,videoType:videoType}, '\*');iframeWin.contentWindow.postMessage({action:'updateInitParam', // 告诉子页面一些初始值,包括浏览器视窗高度与宽度、iframe偏离文档的位置、iframe相对视窗的位置msg: '更新子页面一些初始值',showSize: { // 浏览器视窗高度与宽度width: $(window).width(),height: $(window).height()},iframeOffset: { // iframe偏离文档的位置left: iframeWin.offsetLeft,top: iframeWin.offsetTop},iframeClientPos: { // iframe相对视窗的位置left: iframeWin.getBoundingClientRect().left,right: iframeWin.getBoundingClientRect().right,top: iframeWin.getBoundingClientRect().top,bottom: iframeWin.getBoundingClientRect().bottom}}, '\*'); // '\*'表示跨域参数,请结合自身业务合理设置}}// 步骤3:监听嵌入子页面的事件window.addEventListener('message', function(e){console.log("iframe监听:",e.data);if(e && e.data){switch (e.data.action){case 'updateTitle': // 本页面收到子页面通知更新标题通知,更新本页面标题document.title = e.data.info;break;case 'updatePos':var scrollLeftValue = document.documentElement.scrollLeft;var scrollTopValue = document.documentElement.scrollTop;iframeWin.contentWindow.postMessage({action:'updatePos',msg: '更新Pos',scrollValue: { // 滚动条滚动的偏移量left: -1 * scrollLeftValue,top: -1 * scrollTopValue,}}, '\*'); // '\*'表示跨域参数,请结合自身业务合理设置break;case 'cameraCode':let cameraCode = e.data.cameraCode;let startTime = e.data.startTime;let endTime = e.data.endTime;console.log("传递参数:",cameraCode)iframeWin.contentWindow.postMessage({action:'sendCameraCode', // 告诉子页面本页面的标题(action自行指定,但需要与子页面中监听的action保持一致cameraCode:cameraCode,startTime:startTime,endTime:endTime}, '\*');break;default:break;}}});// 步骤4:兼听本页面的resize事件,并将一些状态值发送给嵌入的子页面var resizeTimer = null;var resizeDate;$(window).resize(function () {resizeDate = new Date();if (resizeTimer === null){resizeTimer = setTimeout(checkResizeEndTimer, 100);}});function checkResizeEndTimer(){if (new Date() - resizeDate > 100){ // resize结束后再发消息,避免残影问题clearTimeout(resizeTimer);resizeTimer = null;postResizeEvent();} else{setTimeout(checkResizeEndTimer, 100);}}function postResizeEvent(){iframeWin.contentWindow.postMessage({action: 'resize',msg: 'resize事件',showSize: { // 告诉嵌入的子页面视窗高度与宽度width: $(window).width(),height: $(window).height()},iframeClientPos: { // iframe相对视窗的位置left: iframeWin.getBoundingClientRect().left,right: iframeWin.getBoundingClientRect().right,top: iframeWin.getBoundingClientRect().top,bottom: iframeWin.getBoundingClientRect().bottom},iframeOffset: { // iframe偏离文档的位置left: iframeWin.offsetLeft,top: iframeWin.offsetTop}}, '\*'); // '\*'表示跨域参数,请结合自身业务合理设置}// 步骤5:兼听本页面的scroll事件,并将一些状态值发送给嵌入的子页面// 为性能考虑,可以在定时器中处理var scrollTimer = null;var scrollDate;$(window).scroll(function (event) {postScrollEvent();scrollDate = new Date();if (scrollTimer === null){scrollTimer = setTimeout(checkScrollEndTimer, 100);}});function checkScrollEndTimer(){if (new Date() - scrollDate > 100){ // resize结束后再发消息,避免残影问题clearTimeout(scrollTimer);scrollTimer = null;} else{postScrollEvent();setTimeout(checkScrollEndTimer, 100);}}function postScrollEvent(){// 计算滚动条偏移量var scrollLeftValue = document.documentElement.scrollLeft;var scrollTopValue = document.documentElement.scrollTop;iframeWin.contentWindow.postMessage({action:'scroll',msg: 'scroll事件',scrollValue: { // 滚动条滚动的偏移量left: -1 * scrollLeftValue,top: -1 * scrollTopValue,},iframeClientPos: { // iframe相对视窗的位置left: iframeWin.getBoundingClientRect().left,right: iframeWin.getBoundingClientRect().right,top: iframeWin.getBoundingClientRect().top,bottom: iframeWin.getBoundingClientRect().bottom},showSize: { // 告诉嵌入的子页面视窗高度与宽度width: $(window).width(), // 视窗宽度height: $(window).height() // 视窗高度},iframeOffset: { // iframe偏离文档的位置left: iframeWin.offsetLeft,top: iframeWin.offsetTop}}, '\*'); // '\*'表示跨域参数,请结合自身业务合理设置}</script>
</html>
index.vue
<template><div><div style="overflow-y: hidden;"><el-row style="display: flex"><div class="user__tree" style="margin-top: 30px;overflow:auto;height: 72vh;font-size: 18px;width: 280px;">
<!-- <avue-tree :option="treeOption" :data="treeData" style="width: 320px;" class="disable-selection">-->
<!-- <span-->
<!-- class="el-tree-node__label"-->
<!-- slot-scope="{ node, data }"-->
<!-- :class="{ 'last-level-node': !data.children || data.children.length === 0 }"-->
<!-- @dblclick="dblclick(node, data)"-->
<!-- style="display: flex;align-items: center;font-size: 18px;"-->
<!-- >-->
<!--<!– <span v-if="data.isOnline===0" class="tree_icon_green"></span>–>-->
<!-- <span v-if="data.isOnline===1" class="tree_icon_green"></span>-->
<!-- <span>{{ data.name }}</span>--><!-- </span>-->
<!-- </avue-tree>--><el-tree:data="treeData"class="disable-selection":option="treeOption"empty-text="加载中,请稍后"node-key="areaId":default-expanded-keys="defaultExpandedKeys":props="defaultProps"><spanclass="el-tree-node__label"slot-scope="{ node, data }":class="{ 'last-level-node': !data.children || data.children.length === 0 }"@dblclick="dblclick(node, data)"style="display: flex;align-items: center;font-size: 18px;"><span v-if="data.isOnline===1" class="tree_icon_green"></span><span>{{ data.name }}</span></span></el-tree></div><el-col :span="10" class="user__main" style="width: 100%;"><div style="width: 100%;" v-if="activeName == '实时视频'"><iframe style="width: 100%;height: 80vh" scrolling="no":src="`${rtsp_ifarme_url}/in/demo_for_iframe.html?videoType=live`"frameborder="0" ref="iframe"></iframe><!-- cameraCode=${cameraCode}& --></div></el-col></el-row></div></div>
</template><script>
import { deptRoleList } from "@/api/admin/role";
import { fetchTree } from "@/api/admin/dept";
import { tableOption } from "@/const/crud/admin/user";
import { mapGetters } from "vuex";
import videoDemo from '@/views/video/video_demo.vue'
import Preview from "@/views/video/video_c/Preview.vue";
import request from "@/router/axios";export default {name: "Video",components: {Preview,videoDemo},//父组件传过来的props: {activeName: {type: String,default: ''},},data() {return {totalPage: 0,defaultProps: {children: "children",label: "name"},defaultExpandedKeys: [],queryParams: {},openPreview: false,tableData: [], //列表playUrl: '', //播放的urlendUrl: '',//关闭时传的urltreeOption: {nodeKey: "id",addBtn: false,defaultExpandAll: true,menu: false,props: {label: "name",value: "id"}},treeData: [],rtsp: '',cameraCode: '',rtsp_ifarme_url:process.env.rtsp_ifarme_url};},computed: {},created() {this.init();},mounted() {this.defaultExpandedKeys = '3703';},deactivated() {this.activeName=""},beforeDestroy() {this.activeName=""},methods: {closePreview() {if (this.rtsp) {request({url: process.env.STREAM_CLOSE_URL,method: 'post',data: {urls: [this.rtsp]}}).then(res => {this.talkerJob = res.data.data.records.map(item => {return {label: item.jobName,value: item.id}})})}},dblclick(node, row) {console.log("点击:",node,row);if (row.children == 0) {console.log("根节点")console.log('node', node)console.log('row', row)let parentData = node.parent.data.childrenthis.cameraCode = row.cameraCodeconsole.log(this.cameraCode, 'code1')this.sendMesFroIframe(this.cameraCode);// request({// url: '/ewaycloud/channel/hik/tvWallURL',// method: 'get',// params: {// cameraIndexCode: this.cameraCode,// },// }).then(res => {// this.playUrl = process.env.STREAM_URL + '/live?url=' + res.data.data.url;// this.openPreview = true// // this.$nextTick(() => {// // this.$refs.preview.handlePlay(this.playUrl, parentData.indexOf(row), row);// // })// this.endUrl = res.data.data.url// })}},sendMesFroIframe(cameraCode) {// 向iframe传值const mapFrame = this.$refs['iframe'];const iframeWin = mapFrame.contentWindow;iframeWin.postMessage({action:'cameraCode',cameraCode: cameraCode,},'*');},// 每页数sizeChangeHandle(val) {this.queryParams.pageSize = valthis.queryParams.pageIndex = 1this.getList()},// 当前页currentChangeHandle(val) {this.pageIndex = valthis.getList()},init() {request({url: '/ewaycloud/camera/findCameraDeptTreeList',method: 'get',}).then(res => {this.treeData = res.data.data;// this.treeData.forEach((item,index)=>{// item.status = 0// item.forEach((item,index)=>{// item.t// })// })console.log("树数据:",this.treeData[0].children);// this.$set(this.treeData[0].children[0].children[0],'status','0')// this.$set(this.treeData[0].children[0].children[1],'status','1')// this.$set(this.treeData[0].children[0].children[2],'status','1')// console.log(this.treeData[0].children[0].children[2]);// console.log(this.treeData[0].children[0].children[0],'this.treeData[0].children[3].children[0]');// this.$set(this.treeData[0].children[0].children[3],'status','0')})},getList() {request({url: '/ewaycloud/camera/findCamerList',method: 'get',params: this.queryParams}).then(res => {this.tableData = res.data.data.records;this.totalPage = res.data.data.total;})},nodeClick(data) {this.queryParams.deptId = data.id;this.getList();},}
};
</script>
<style lang="scss" scoped>.last-level-node {font-size: 16px !important;}
.user {height: 100%;&__tree {padding-top: 3px;padding-right: 20px;}&__main {.el-card__body {padding-top: 0;}}
}::v-deep .avue-view {overflow: hidden;
}
::v-deep .el-scrollbar{min-height: 200px;
}
.hover-cursor {cursor: pointer;/* 鼠标移入单元格时显示小手形状 */
}
.tree_icon_red{background-color: red;display: inline-block;width: 5px;height: 5px;border-radius: 50%;margin-right: 5px;
}
.tree_icon_green{background-color: green;display: inline-block;width: 10px;height: 10px;border-radius: 50%;margin-right: 5px;
}
.divSelect:hover {cursor: pointer;
}
::v-deep .el-tree-node__expand-icon{font-size: 18px !important;
}
::v-deep .avue-tree__filter{position: sticky;top: -0.15rem;left: 2rem;background-color: #fff;z-index: 99;width: 100%;
}
.disable-selection {user-select: none; /* 标准语法 */-webkit-user-select: none; /* Chrome, Safari, Opera */-moz-user-select: none; /* Firefox */-ms-user-select: none; /* IE10+/Edge */
}
// ::v-deep .avue-tree{
// padding-top: 50px;
// }
</style>