#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
access_log logs/access.log main;
#access_log off;
client_max_body_size 50m;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 12345;
server_name 192.168.1.141;
#charset koi8-r;
access_log logs/host.access.log main;
#websocket相关配置
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
location / {
# root "../webs";
root "E:\HcSDK\dist";
index index.html index.htm;
}
location ~ /ISAPI|SDK/ {
if ($http_cookie ~ "webVideoCtrlProxy=(.+)") {
proxy_pass http://$cookie_webVideoCtrlProxy;
break;
}
}
location ^~ /webSocketVideoCtrlProxy {
#web socket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
if ($http_cookie ~ "webVideoCtrlProxyWs=(.+)") {
proxy_pass http://$cookie_webVideoCtrlProxyWs/$cookie_webVideoCtrlProxyWsChannel?$args;
break;
}
if ($http_cookie ~ "webVideoCtrlProxyWss=(.+)") {
proxy_pass http://$cookie_webVideoCtrlProxyWss/$cookie_webVideoCtrlProxyWsChannel?$args;
break;
}
}
}
}
<template>
<div class="HcNet">
<div class="window-title">
<div>相机名称</div>
<div class="close-div" @click="handleClose">X</div>
</div>
<div class="content">
<div id="video-window" ref="video"></div>
<div class="opt-panel">
<div class="opt-pan">
<!-- // 8个方向移动 -->
<div class="row-btn">
<div class="pan" @mousedown.left="handlePTZOption(5, false)" @mouseup.left="handlePTZOption(5, true)">↖</div>
<div class="pan" @mousedown.left="handlePTZOption(1, false)" @mouseup.left="handlePTZOption(1, true)">↑</div>
<div class="pan" @mousedown.left="handlePTZOption(6, false)" @mouseup.left="handlePTZOption(6, true)">↗</div>
</div>
<div class="row-btn">
<div class="pan" @mousedown.left="handlePTZOption(3, false)" @mouseup.left="handlePTZOption(3, true)">←</div>
<div class="pan" @mousedown.left="handlePTZOption(5, false)" @mouseup.left="handlePTZOption(5, true)"></div>
<div class="pan" @mousedown.left="handlePTZOption(4, false)" @mouseup.left="handlePTZOption(4, true)">→</div>
</div>
<div class="row-btn">
<div class="pan" @mousedown.left="handlePTZOption(7, false)" @mouseup.left="handlePTZOption(7, true)">↙</div>
<div class="pan" @mousedown.left="handlePTZOption(2, false)" @mouseup.left="handlePTZOption(2, true)">↓</div>
<div class="pan" @mousedown.left="handlePTZOption(8, false)" @mouseup.left="handlePTZOption(8, true)">↘</div>
</div>
</div>
<div class="opt-zoom row-btn">
<!-- // 缩放 -->
<div class="pan" @mousedown.left="handlePTZOption(10, false)" @mouseup.left="handlePTZOption(10, true)">+</div>
<div class="pan">缩放</div>
<div class="pan" @mousedown.left="handlePTZOption(11, false)" @mouseup.left="handlePTZOption(11, true)">-</div>
</div>
<div class="opt-aperture row-btn">
<!-- // 光圈 -->
<div class="pan" @mousedown.left="handlePTZOption(14, false)" @mouseup.left="handlePTZOption(14, true)">+</div>
<div class="pan">光圈</div>
<div class="pan" @mousedown.left="handlePTZOption(15, false)" @mouseup.left="handlePTZOption(15, true)">-</div>
</div>
<div class="opt-aperture row-btn">
<div class="pan" @click="toggleRealPlay">{{isRealPlay ? '停止预览':'开始预览'}}</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import { init, login, realPlayStart, realPlayStop, operationPTZ } from "@/api/hcnet/HcNet";
export default Vue.extend({
name: "HcNet",
props: {
isVisible: {
type: Boolean,
default: false,
required: true,
},
},
data() {
return {
visible: false,
cameraData: {
ip: "10.0.1.12",
port: "80",
user: "admin",
passwd: "",
},
isRealPlay: false
};
},
beforeMount() {
this.visible = this.isVisible;
},
mounted() {
const rect = this.$refs.video.getBoundingClientRect();
const style = window.getComputedStyle(this.$refs.video);
const paddingLeft = parseFloat(style.paddingLeft);
const paddingRight = parseFloat(style.paddingRight);
const paddingTop = parseFloat(style.paddingTop);
const paddingBottom = parseFloat(style.paddingBottom);
const borderLeft = parseFloat(style.borderLeftWidth);
const borderRight = parseFloat(style.borderRightWidth);
const borderTop = parseFloat(style.borderTopWidth);
const borderBottom = parseFloat(style.borderBottomWidth);
const width = rect.width - paddingLeft - paddingRight - borderLeft - borderRight;
const height = rect.height - paddingTop - paddingBottom - borderTop - borderBottom;
const result = init("video-window", width, height, this.messageSDK);
console.log("🚀 ~ mounted ~ result:", result)
setTimeout(() => {
login("10.195.200.24", 1 ,80, 'admin', '08A301301', this.messageSDK)
}, 2000);
},
methods: {
handleClose() {
this.$emit("close", false);
},
messageSDK(result){
if(!result.isSuccess){
console.error(result.message)
}else{
console.info(result.message)
}
},
toggleRealPlay(){
this.isRealPlay = !this.isRealPlay
const id = this.cameraData.ip + '_' + this.cameraData.port
if(this.isRealPlay){
realPlayStart(id, this.messageSDK)
}else{
realPlayStop(this.messageSDK)
}
},
handlePTZOption(type, isStop){
operationPTZ(type, isStop, this.messageSDK)
}
},
});
</script>
<style scoped>
.HcNet {
user-select: none;
width: 50vw;
height: 40vh;
display: flex;
flex-direction: column;
background-color: #808080;
}
.window-title {
color: #c9c9c9;
width: 100%;
height: 2rem;
font-size: medium;
font-weight: 600;
display: flex;
flex-direction: row;
align-items: center;
}
.close-div {
user-select: none;
width: 2rem;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
color: #c9c9c9;
background-color: brown;
margin-left: auto;
}
.close-div:hover {
color: #e2e2e2;
background-color: red;
}
.close-div:active {
color: #e2e2e2;
background-color: brown;
}
.content {
width: 100%;
height: calc(100% - 2rem);
display: flex;
flex-direction: row;
padding: 5px;
}
#video-window {
width: 80%;
max-width: calc(100% - 150px);
height: 100%;
background-color: black;
overflow: auto;
}
.opt-panel {
min-width: 150px;
width: 20%;
height: 100%;
display: flex;
flex-direction: column;
padding: 5px
}
.opt-pan {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
height: 150px;
}
.pan {
width: 25%;
height: 25%;
min-width: 2rem;
min-height: 2rem;
color: #c9c9c9;
background-color: #333333;
border: 1px solid #333333;
display: flex;
align-items: center;
justify-content: center;
border-radius: 5px;
}
.pan:hover {
color: #e2e2e2;
background-color: #676767;
border-color: #909090;
}
.pan:active {
color: #ffffff;
background-color: #232323;
}
.opt-pan > .row-btn:nth-child(2)> .pan:nth-child(2) {
visibility: hidden;
pointer-events: none;
}
.opt-zoom,
.opt-aperture {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
height: 50px;
margin: 10px 0 0 0;
}
.opt-zoom > .pan:nth-child(2),
.opt-aperture>.pan:nth-child(2) {
pointer-events: none;
background-color: transparent;
border: none;
color: #ffffff;
}
.row-btn{
width: 100%;
height: auto;
margin: 5px 0;
display: flex;
flex-direction: row;
justify-content: space-around
}
</style>
class Result{
isSuccess = true
message = ''
data = null
constructor(isSuccess, message, data) {
this.isSuccess = isSuccess
this.message = message
this.data = data
}
}
/**
* 初始化SDK,并将SDK视频播放插件插入Dom文档
* @param {String} containerID 放视频组件的div ID
* @param {Number} width div的宽
* @param {Number} height div的高
* @param {Function} callback callback 操作成功或者失败的回调,默认入参为 Result 对象。如果自定义了options对象的成功/失败回调函数,需要根据自定义的返回参数来修改入参
* @param {Object | null} options 配置对象,可选,表示采用默认配置对象
* @param {String} options.szColorProperty 插件的背景颜色。表示插件的背景颜色,子窗口的背景颜色,子窗口的边框颜色,子窗框选中的边框颜色。插件中有一套自己的默认颜色。
* @param {String} options.szOcxClassId ocx插件的 ID,OEM 时可以修改对应 ID 来实现开发包绑定不同的插件,默认为海康 WEB3.0 插件(无插件不支持该参数)
* @param {String} options.szMimeTypes 非IE插件的MIMETYPE,OEM 时可以修改对应 ID 来实现开发包绑定不同的插件,默认为海康 WEB3.0 插件
* @param {Number} options.iWndowType 分屏类型:1- 1*1,2- 2*2,3- 3*3,4- 4*4,默认值为 1,单画面
* @param {String} options.bWndFull 是否支持单窗口双击全屏,默认支持 true:支持 false:不支持
* @param {String} options.iPlayMode 播放模式,默认值为 2,正常播放模式。暂不支持其它模式。
* @param {String} options.bDebugMode 控制台打印调试信息,true(开启),false(关闭)
* @param {String} options.bNoPlugin 文档里没有该参数含义,推测为是否是无插件模式
* @param {String} options.iPackageType 封装格式,2-PS 格式 11-MP4 格式。(无插件不支持该参数)
* @param {Function} options.cbSelWnd 窗口选中事件回调函数,只包含一个字符串参数,里面的值是 XML,如果不需要该事件回调可以不定义
* @param {Function} options.cbEvent 插件事件回调函数,有三个参数,第一个参数是事件类型,第二参数是窗口号(无插件不支持该回调),第三个参数文档没讲
* @param {Function} options.cbDoubleClickWnd 窗口双击回调函数,有两个参数,第一个参数是窗口号,第二个参数是是否全屏(无插件不支持该回调),如果不需要该事件回调可以不定义
* @param {Function} options.cbRemoteConfig 远程配置库关闭回调(无插件不支持该回调),如果不需要该事件回调可以不定义
* @param {Function} options.cbInitPluginComplete 插件初始化完成回调,必须要定义,在该事件中,将SDK视频插件插入Dom文档
* @returns
*/
export function init(containerID, width = 500, height = 300, callback, options = null ) {
const webViewCtrl = window.WebVideoCtrl
const isSupportNoPlugin = webViewCtrl.I_SupportNoPlugin()
if (!isSupportNoPlugin /*&& pluginCheckRes == -1*/) {
typeof callback === 'function' && callback(new Result(false, "浏览器不支持无插件模式,请使用最新版Chrome或者Edge"))
return
}
const optionDefault = {
szColorProperty: "plugin-background:000000; sub-background:000000; sub-border:0000; sub-border-select:000000",
iWndowType: 1,
bWndFull: false,
bDebugMode: false,
bNoPlugin: true,
iPackageType: 2,
cbSelWnd: function (xmlDoc) {
// const g_iWndIndex = parseInt($(xmlDoc).find("SelectWnd").eq(0).text(), 10);
// const szInfo = "当前选择的窗口编号:" + g_iWndIndex;
console.log("🚀 ~ init ~ szInfo:", xmlDoc)
},
cbEvent: function (iEventType, iParam1, iParam2) {
console.log("🚀 ~ init ~ optionDefault.iEventType, iParam1, iParam2:", optionDefault.iEventType, iParam1, iParam2)
},
cbDoubleClickWnd: function (windowNumer, isFullScreen) {
console.log("🚀 ~ init ~ optionDefault.windowNumer, isFullScreen:", optionDefault.windowNumer, isFullScreen)
},
cbRemoteConfig: function () {
},
cbInitPluginComplete: function () {
const result = webViewCtrl.I_InsertOBJECTPlugin(containerID)
if (result != 0) { // 成功返回0 ,失败返回-1
typeof callback === 'function' && callback(new Result(false, "SDK组件插入网页元素失败"))
return
}
// 检查插件是否最新
if (-1 == webViewCtrl.I_CheckPluginVersion()) {
typeof callback === 'function' && callback(new Result(true, "插件有新版本的了"))
return;
}
typeof callback === 'function' && callback(new Result(true, "SDK初始化成功"))
}
}
options = options || optionDefault
webViewCtrl.I_InitPlugin(width, height, options)
}
/**
* 登录
* @param {String} ip 设备IP
* @param {Number} protocol http 协议,1 表示 http 协议 2 表示 https 协议
* @param {Number} port 设备登录的http/https端口号
* @param {String} username 登录用户名
* @param {String} passwd 密码
* @param {Function} callback 操作成功或者失败的回调,默认入参为 Result对象。如果自定义了options对象的成功/失败回调函数,需要根据自定义的返回参数来修改入参
* @param {Object | null} options 配置对象,可选,表示采用默认配置对象
* @param {Boolean} options.async http 交互方式,可选,true 表示异步,false 表示同步,有默认值,但是未指明
* @param {Number} options.cgi CGI 协议选择,可选,1 表示 ISAPI,2 表示 PSIA,如果不传这个参数,会自动选择一种设备支持的协议
* @param {Function} options.success 成功回调函数,有一个参数,表示返回的 XML 内容。
* @param {Function} options.error 失败回调函数,有两个参数,第一个是 http 状态码,第二个是设备返回的 XML(可能为空)
*/
export function login(ip, protocol = 1, port, username, passwd, callback, options = null) {
const webViewCtrl = window.WebVideoCtrl
const defaultOption = {
// async: true // http 交互方式,true 表示异步,false 表示同步
// cgi: 1 // CGI 协议选择,1 表示 ISAPI,2 表示 PSIA,如果不传这个参数,会自动选择一种设备支持的协议
success: function (xmlDoc) {
console.log("🚀 ~ login ~ xmlDoc:", xmlDoc)
typeof callback === 'function' && callback(new Result(true, "登录成功"))
},
error: function (httpCode, xmlDoc) {
console.log("🚀 ~ login ~ httpCode, xmlDoc:", httpCode, xmlDoc)
typeof callback === 'function' && callback(new Result(false, "登录失败"))
}
}
const option = options || defaultOption
webViewCtrl.I_Login(ip, protocol, port, username, passwd, option)
}
/**
* 登出设备
* @param {String} ip_port 设备标识(ip_port)
* @returns @classdesc Result对象:包含操作结果,操作信息,数据(可能为空)
*/
export function logout(ip_port) {
const webViewCtrl = window.WebVideoCtrl
if (!ip_port) return new Result(false, "登出时ip不能为空")
const result = webViewCtrl.I_Logout(ip_port);
if (result !== 0) {
return new Result(false, "登出返回失败")
}
return new Result(true, "退出成功")
}
/**
* 获取模拟通道
* @param {String} ip_port 设备标识(IP_Port)
* @param {Function} callback 操作成功或者失败的回调,默认入参为 @classdesc Result。如果自定义了options对象的成功/失败回调函数,需要根据自定义的返回参数来修改
* @param {Object | null} options 配置对象,可选,不传该参数表示使用默认配置对象
* @param {Boolean} options.async http 交互方式,可选,true 表示异步,false 表示同步,默认值不清楚,但是有默认值
* @param {Function} options.success 成功回调函数,有一个参数,表示返回的 XML 内容。
* @param {Function} options.error 失败回调函数,有两个参数,第一个是 http 状态码,第二个是设备返回的 XML(可能为空)
*/
export function getAnalogChannel(ip_port, callback,options = null) {
const webViewCtrl = window.WebVideoCtrl
const defaultOption = {
// async: true, // demo没有写明,不清楚默认值
success: function (xmlDoc) {
console.log("🚀 ~ getAnalogChannel ~ xmlDoc:", xmlDoc)
// TODO 处理xml内容以获取有用的信息
typeof callback === 'function' && callback(new Result(true, "获取模拟通道成功"))
},
error: function (httpCode, xmlDoc) { // 此处xmlDoc 可能为null
console.log("🚀 ~ getAnalogChannel ~ httpCode, xmlDoc:", httpCode, xmlDoc)
typeof callback === 'function' && callback(new Result(false, "获取模拟通道失败"))
}
}
const option = options || defaultOption
webViewCtrl.I_GetAnalogChannelInfo(ip_port, option);
}
/**
* 获取数字通道
* @param {String} ip_port 设备标识(IP_Port)
* @param {Function} callback 操作成功或者失败的回调,默认入参为 @classdesc Result。如果自定义了options对象的成功/失败回调函数,需要根据自定义的回调来处理
* @param {Object | null} options 配置对象,可选,不传该参数表示使用默认配置对象
* @param {Boolean} options.async http 交互方式,可选,true 表示异步,false 表示同步,默认值不清楚,但是有默认值
* @param {Function} options.success 成功回调函数,有一个参数,表示返回的 XML 内容。
* @param {Function} options.error 失败回调函数,有两个参数,第一个是 http 状态码,第二个是设备返回的 XML(可能为空)
*/
export function getDigtalChannel(ip_port, callback, options = null) {
const webViewCtrl = window.WebVideoCtrl
const defaultOption = {
// async: true, // demo没有写明,不清楚默认值
success: function (xmlDoc) {
console.log("🚀 ~ getDigtalChannel ~ xmlDoc:", xmlDoc)
// TODO 处理xml内容以获取有用的信息
typeof callback === 'function' && callback(new Result(true, "获取数字通道成功"))
},
error: function (httpCode, xmlDoc) { // 此处xmlDoc 可能为null
console.log("🚀 ~ getDigtalChannel ~ httpCode, xmlDoc:", httpCode, xmlDoc)
typeof callback === 'function' && callback(new Result(false, "获取数字通道失败"))
}
}
const option = options || defaultOption
webViewCtrl.I_GetDigitalChannelInfo(ip_port, option);
}
/**
* 获取零通道
* @param {String} ip_port 设备标识(IP_Port)
* @param {Function} callback 操作成功或者失败的回调,默认入参为 @classdesc Result。如果自定义了options对象的成功/失败回调函数,需要根据自定义的回调来处理
* @param {Object | null} options 配置对象,可选,不传该参数表示使用默认配置对象
* @param {Boolean} options.async http 交互方式,可选,true 表示异步,false 表示同步,默认值不清楚,但是有默认值
* @param {Function} options.success 成功回调函数,有一个参数,表示返回的 XML 内容。
* @param {Function} options.error 失败回调函数,有两个参数,第一个是 http 状态码,第二个是设备返回的 XML(可能为空)
*/
export function getZeroChannel(ip_port, callback, options = null) {
const webViewCtrl = window.WebVideoCtrl
const defaultOption = {
success: function (xmlDoc) {
// TODO 处理xml内容以获取有用的信息
typeof callback === 'function' && callback(new Result(true, "获取零通道成功"))
console.log("🚀 ~ getZeroChannel ~ defaultOption.xmlDoc:", xmlDoc)
},
error: function (httpCode, xmlDoc) { // 此处xmlDoc 可能为null
console.log("🚀 ~ getZeroChannel ~ defaultOption.httpCode, xmlDoc:", httpCode, xmlDoc)
typeof callback === 'function' && callback(new Result(false, "获取零通道失败"))
}
}
const option = options || defaultOption
webViewCtrl.I_GetZeroChannelInfo(ip_port, option);
}
/**
* 开始实时预览
* @param {String} ip_port 设备标识(IP_Port)
* @param {Function} callback 操作成功或者失败的回调,默认入参为 @classdesc Result。如果自定义了options对象的成功/失败回调函数,需要根据自定义的回调来处理
* @param {Object | null} options 配置对象,可选,不传入该值,表示使用默认配置对象
* @param {Number} options.iWndIndex 播放窗口,可选,如果不传,则默认使用当前选择窗口播放(默认选中窗口 0)
* @param {Number} options.iStreamType 码流类型,可选,1-主码流,2-子码流,默认使用主码流预览
* @param {Number} options.iChannelID 播放通道号,可选,默认通道1
* @param {Number} options.bZeroChannel 是否播放零通道,可选,默认为 false
* @param {Number} options.iPort RTSP 端口号,可选,如果不传,开发包会自动判断设备的 RTSP 端口
* @param {Function} options.success 操作成功后的回调函数
* @param {Function} options.error 操作失败后的回调函数,有两个参数,第一个是 http 状态码,第二个是设备返回的 XML(可能为空)
*/
export function realPlayStart(ip_port, callback, options = null) {
const webViewCtrl = window.WebVideoCtrl
const defaultOption = {
success: function (sss) { // 似乎没有入参
console.log("🚀 ~ realPlayStart ~ defaultOption.sss:", sss)
typeof callback === 'function' && callback(new Result(true, "预览成功"))
},
error: function (httpCode, xmlDoc) { // 似乎没有入参
console.log("🚀 ~ realPlayStart ~ defaultOption.xmlDoc:", xmlDoc)
if (httpCode === 403) {
typeof callback === 'function' && callback(new Result(false, "设备不支持Websocket取流!"))
}else
typeof callback === 'function' && callback(new Result(false, "预览失败"))
}
}
const option = options || defaultOption
webViewCtrl.I_StartRealPlay(ip_port, option)
}
/**
* 实时预览停止
* @param {Function} callback 操作成功或者失败的回调,默认入参为 @classdesc Result。如果自定义了options对象的成功/失败回调函数,需要根据自定义的回调来处理
* @param {Object | null} options 设置对象,可选
* @param {Number} options.iWndIndex 窗口号,可选,默认为当前选中窗口
* @param {Function} options.success 操作成功后的回调函数
* @param {Function} options.error 操作失败后的回调函数
*/
export function realPlayStop(callback, options = null) {
stopPlay(callback, options)
}
/**
* 停止播放:停止预览和停止回放统一使用该函数
* @param {Function} callback 操作成功或者失败的回调,默认入参为 @classdesc Result。如果自定义了options对象的成功/失败回调函数,需要根据自定义的回调来处理
* @param {Object | null} options 设置对象,可选
* @param {Number} options.iWndIndex 窗口号,可选,默认为当前选中窗口
* @param {Function} options.success 操作成功后的回调函数
* @param {Function} options.error 操作失败后的回调函数
*/
function stopPlay(callback, options) {
const webViewCtrl = window.WebVideoCtrl
const defaultOption = {
// iWndIndex: 0,
success: function () {
typeof callback === 'function' && callback(new Result(true, "停止播放成功"))
},
error: function () {
typeof callback === 'function' && callback(new Result(false, "停止播放成功"))
}
}
const option = options || defaultOption
webViewCtrl.I_Stop(option)
}
/**
* 云台操作
* @param {Number} operationType 操作类型(1-上,2-下,3-左,4-右,5-左上,6-左下,7-右上,8-右下,9-自转,10-变倍+, 11-变倍-, 12-F 聚焦+, 13-聚焦-, 14-光圈+, 15-光圈-)
* @param {Boolean} isStop 是否停止:false-执行,true-停止
* @param {Object | null} options 设置对象,可选
* @param {Number} options.iWndIndex 窗口号,可选,默认为当前选中窗口
* @param {Number} options.iPTZSpeed 云台速度,可选,默认为 4
*/
export function operationPTZ(operationType, isStop, callback, options = null) {
console.log("🚀 ~ operationPTZ ~ operationType, isStop:", operationType, isStop)
const webViewCtrl = window.WebVideoCtrl
const defaultOption = {
iPTZSpeed: 4,
success: function (xmlDoc) {
callback(new Result(true, operationType + " 执行成功\n" + xmlDoc))
},
error: function (httpCode, xmlDoc) {
callback(new Result(false, "🚀 ~ operationPTZ ~ defaultOption.httpCode, xmlDoc:" + httpCode+"\n"+xmlDoc))
}
}
const option = options || defaultOption
webViewCtrl.I_PTZControl(operationType, isStop, option)
}
/**
* 获取设备端口数据
* @param {String} ip_port 设备唯一标识
* @returns 端口对象,失败为空,端口对象格式:{iRtspPort: 554, HttpPort: 80, iDevicePort: 8000}
*/
export function getDevicePort(ip_port) {
const webViewCtrl = window.WebVideoCtrl
const res = webViewCtrl.I_GetDevicePort(ip_port)
return res
}
能预览,但是不能PTZ,但是demo是可以PTZ操作的
,
这里是vue组件登录、播放后cookie里的数据,nginx会取该值
我感觉是nginx配置的问题,或者是vue项目配置的问题
我发现:demo发出的请求是/ISAPI/PTZCtrl/channels/1/continuous, 但是vue打包后的请求是 ISAPI/ContentMgmt/PTZCtrlProxy/channels/1/continuous
WebVideoCtrl.js 去这个文件的发请求的方法里打断点,看看是不是vue里面的function和源文件的function冲突了,被重写了
WebVideoCtrl.js 被压缩过了,里面是一大坨
@echo_lovely: 有可以解压的编辑器解压一下比如Hbuilder,你这不就是vue里用了这个js,好好的put请求被改成了get,估计fuction被重写了
@大爷我啊有低保!: 我发现:demo发出的请求是/ISAPI/PTZCtrl/channels/1/continuous, 但是vue打包后的请求是 ISAPI/ContentMgmt/PTZCtrlProxy/channels/1/continuous
然后我
去项目里查找了 ContentMgmt 这个单词,然后发现只有 WebVideoCtrl.js 用了
我把 /ContentMgmt/PTZCtrlProxy 给替换成了 /PTZCtrl , 然后就成了!
@echo_lovely: 。。。原来是地址不对,不知道怎么会put变get的,不会是nginx put404 然后转到404页面才变成get的吧。。
@echo_lovely: 估计是option里有匹配是否使用代理的选项,demo里有其它js设置好了,封装的没设置,然后走了代理接口
@大爷我啊有低保!: 应该是这个404
我发现:demo发出的请求是/ISAPI/PTZCtrl/channels/1/continuous, 但是vue打包后的请求是 ISAPI/ContentMgmt/PTZCtrlProxy/channels/1/continuous
然后我
去项目里查找了 ContentMgmt 这个单词,然后发现只有 WebVideoCtrl.js 用了
我把 /ContentMgmt/PTZCtrlProxy 给替换成了 /PTZCtrl , 然后就成了!