<template>
|
<b-modal
|
size="lg"
|
style="width:1000px"
|
:title="title"
|
ref="myModalRef"
|
ok-title="保存"
|
@ok="handleOk"
|
@cancel="clearName"
|
cancel-title="取消"
|
@hide="resetForm"
|
:hide-header="false"
|
:hide-footer="!isShowFooter"
|
>
|
<div>
|
<!-- <h4>{{title}}</h4> -->
|
<el-form
|
:model="addForm"
|
label-position="right"
|
:rules="rules"
|
ref="addForm"
|
label-width="110px"
|
>
|
<div class="row">
|
<div class="col-md-6 col-sm-12">
|
<el-form-item label="设备类型:" prop="type">
|
<el-select
|
v-model="addForm.type"
|
placeholder="请选择设备类型"
|
:disabled="isDisabled"
|
style="width:100%"
|
@change="setDeviceType"
|
>
|
<el-option
|
v-for="(item,index) in deviceTypeList"
|
:key="index"
|
:label="item.name"
|
:value="item.value"
|
></el-option>
|
</el-select>
|
</el-form-item>
|
</div>
|
<div class="col-md-6 col-sm-12" v-if="addForm.type == 101">
|
<el-form-item label="摄像机品牌:" prop="brand">
|
<el-select
|
v-model="addForm.brand"
|
placeholder="请选择设备品牌"
|
:disabled="isDisabled"
|
style="width:100%"
|
>
|
<el-option
|
v-for="(item,index) in deviceBrandList"
|
:key="index"
|
:label="item.name"
|
:value="item.value"
|
></el-option>
|
</el-select>
|
</el-form-item>
|
</div>
|
</div>
|
<div class="row" v-if="addForm.type == 101">
|
<div class="col-md-6 col-sm-12">
|
<el-form-item label="名称:" prop="name">
|
<el-input v-model="addForm.name" placeholder="请输入名称"></el-input>
|
</el-form-item>
|
<el-form-item label="位置:" prop="address">
|
<el-input v-model="addForm.address" placeholder="请输入位置"></el-input>
|
</el-form-item>
|
|
<el-form-item label="IP:" prop="ip">
|
<el-input v-model="addForm.ip" placeholder="请输入IP" :disabled="isDisabled"></el-input>
|
</el-form-item>
|
<el-form-item label="端口:" prop="port">
|
<el-input v-model="addForm.port" placeholder="请输入端口" :disabled="isDisabled"></el-input>
|
</el-form-item>
|
|
<el-form-item label="用户名:" prop="username">
|
<el-input v-model="addForm.username" placeholder="请输入用户名" :disabled="isDisabled"></el-input>
|
</el-form-item>
|
<el-form-item label="密码:" prop="password">
|
<el-input
|
v-model="addForm.password"
|
type="password"
|
placeholder="请输入密码"
|
:disabled="isDisabled"
|
></el-input>
|
</el-form-item>
|
<!-- <el-form-item label="编码:">
|
<el-input v-model="addForm.code" :disabled="true"></el-input>
|
</el-form-item>-->
|
</div>
|
<div class="col-md-6 col-sm-12">
|
<el-form-item label="经度:" prop="longitude">
|
<el-input v-model="addForm.longitude" placeholder="请输入经度"></el-input>
|
</el-form-item>
|
<el-form-item label="纬度:" prop="latitude" class="mb-2">
|
<el-input v-model="addForm.latitude" placeholder="请输入纬度"></el-input>
|
</el-form-item>
|
<!-- vxg 播放器 start -->
|
<!-- <vxg :url="videoUrl" width="350" height="250" refresh="videoRefresh" /> -->
|
<!-- <div class="bg-info mb-2" style="width:365px;height:200px;"></div> -->
|
<div
|
ref="vxgPlayer"
|
class="vxgplayer mb-1"
|
style="width:365px;height:200px;"
|
:id="vxgPlayerId"
|
></div>
|
<div
|
v-if="addForm.type == 101 && isTest"
|
class="text-danger text-right mb-1"
|
>必须要进行测试连接,成功后才可保存</div>
|
<!-- vxg 播放器 end -->
|
<div class="text-right">
|
<b-button variant="primary" class="mx-4" size="md" @click="testLink">测试连接</b-button>
|
</div>
|
</div>
|
</div>
|
<div class="row" v-else>
|
<div class="col-md-6 col-sm-12">
|
<el-form-item label="经度:" prop="longitude">
|
<el-input v-model="addForm.longitude" placeholder="请输入经度" :disabled="isDisabled"></el-input>
|
</el-form-item>
|
<el-form-item label="IP:" prop="ip">
|
<el-input v-model="addForm.ip" placeholder="请输入IP" :disabled="isDisabled"></el-input>
|
</el-form-item>
|
</div>
|
<div class="col-md-6 col-sm-12">
|
<el-form-item label="纬度:" prop="latitude">
|
<el-input v-model="addForm.latitude" placeholder="请输入纬度" :disabled="isDisabled"></el-input>
|
</el-form-item>
|
<el-form-item label="端口:" prop="port">
|
<el-input v-model="addForm.port" placeholder="请输入端口" :disabled="isDisabled"></el-input>
|
</el-form-item>
|
</div>
|
</div>
|
<div class="text-right mt-2 pt-4 border-top">
|
<b-button size="md" class="mx-2" @click="hideModel">取消</b-button>
|
<b-button
|
variant="primary"
|
:disabled="addForm.type == 101 && isTest"
|
class="mx-2"
|
size="md"
|
@click="submitForm('addForm')"
|
>保存</b-button>
|
</div>
|
</el-form>
|
</div>
|
</b-modal>
|
</template>
|
|
<script>
|
import {
|
Col,
|
Form,
|
FormItem,
|
Input,
|
Checkbox,
|
Radio,
|
RadioGroup,
|
Select,
|
Option
|
} from 'element-ui'
|
import vxg from '../components/vxg'
|
import {
|
saveDevice,
|
getDeviceType,
|
getDeviceBrand,
|
getDeviceById
|
} from '@/server/home.js'
|
export default {
|
props: {
|
title: String,
|
item: Object,
|
isShowFooter: {
|
default: false
|
}
|
},
|
components: {
|
elCol: Col,
|
elForm: Form,
|
elFormItem: FormItem,
|
elInput: Input,
|
elCheckbox: Checkbox,
|
elRadio: Radio,
|
elRadioGroup: RadioGroup,
|
elSelect: Select,
|
elOption: Option,
|
vxg
|
},
|
data() {
|
const isIP = (rule, value, callback) => {
|
if (!value) {
|
return callback(new Error('IP必填'))
|
}
|
const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
|
if (value && !reg.test(value)) {
|
return callback(new Error('IP不合法'))
|
} else {
|
callback()
|
}
|
}
|
return {
|
/* 测试链接使用 start */
|
vxgPlayerId: 'vxgPlayerId',
|
videoUrl: '',
|
isTest: true,
|
/* 测试链接使用 end */
|
formType: 'add',
|
deviceTypeList: [],
|
deviceBrandList: [],
|
addForm: {
|
// id
|
orgId: '',
|
type: '',
|
name: '',
|
brand: '',
|
address: '',
|
latitude: '',
|
longitude: '',
|
ip: '',
|
port: '',
|
username: '',
|
password: ''
|
// code:''
|
},
|
rules: {
|
ip: [{ required: true, validator: isIP, trigger: 'blur' }],
|
port: [
|
{ required: true, message: '端口必填', trigger: 'blur' },
|
{
|
pattern: /^([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$/,
|
message: '端口号必须是0-65535的数字',
|
trigger: 'blur'
|
}
|
],
|
type: [{ required: true, message: '选择设备类型', trigger: 'change' }],
|
name: [{ required: true, message: '请输设备名称', trigger: 'blur' }],
|
brand: [
|
{ required: true, message: '选择摄像机品牌', trigger: 'change' }
|
],
|
username: [
|
{ required: true, message: '请输用户名', trigger: 'blur' },
|
{
|
pattern: /^[a-zA-Z0-9_-]{4,16}$/,
|
message: '用户名必须是4到16位(字母,数字,下划线,减号)',
|
trigger: 'blur'
|
}
|
],
|
/* eslint-disable */
|
password: [{ required: true, message: '请输密码', trigger: 'blur' }],
|
longitude: [
|
{
|
pattern: /^(\-|\+)?(((\d|[1-9]\d|1[0-7]\d|0{1,3})\.\d{0,6})|(\d|[1-9]\d|1[0-7]\d|0{1,3})|180\.0{0,6}|180)$/,
|
message: '经度整数部分为0-180,小数部分为0到6位',
|
trigger: 'blur'
|
}
|
],
|
latitude: [
|
{
|
pattern: /^(\-|\+)?([0-8]?\d{1}\.\d{0,6}|90\.0{0,6}|[0-8]?\d{1}|90)$/,
|
message: '纬度整数部分为0-90,小数部分为0到6位',
|
trigger: 'blur'
|
}
|
]
|
}
|
}
|
},
|
computed: {
|
isDisabled() {
|
// 进行设备信息编辑时,只可修改名称、位置、经度、纬度信息
|
return this.formType === 'edit'
|
},
|
isCamera() {
|
return false
|
}
|
},
|
methods: {
|
// * 打开modal
|
showModel({ data, type = 'add' }) {
|
this.$refs.myModalRef.show()
|
this.isTest = true
|
// 控制编辑
|
this.formType = type
|
this.$nextTick(() => {
|
// 清除校验
|
this.$refs['addForm'].resetFields()
|
// 查询设备类型
|
this.getDeviceType()
|
this.getDeviceBrand()
|
})
|
if (data && type === 'add') {
|
// 添加
|
this.addForm.orgId = data.id ? data.id : ''
|
}
|
if (data && type === 'edit') {
|
// 编辑 回显
|
if (data.id) {
|
this.getDeviceById(data.id)
|
}
|
}
|
},
|
hideModel() {
|
// this.resetForm()
|
this.$refs.myModalRef.hide()
|
},
|
/* 接口 start */
|
async getDeviceType() {
|
const res = await getDeviceType()
|
this.deviceTypeList =
|
res.success && res.code === 200 && res.data ? res.data : []
|
},
|
async getDeviceBrand() {
|
const res = await getDeviceBrand()
|
this.deviceBrandList =
|
res.success && res.code === 200 && res.data ? res.data : []
|
},
|
async getDeviceById(id) {
|
const res = await getDeviceById({ id })
|
if (res.success && res.code === 200 && res.data) {
|
const json = res.data
|
const keys = Object.keys(json)
|
keys.map(name => {
|
if (json[name]) {
|
this.addForm[name] = json[name]
|
}
|
})
|
} else {
|
this.$toast({
|
type: 'error',
|
message: res && res.msg ? res.msg : '回显失败!'
|
})
|
}
|
console.log(res, 'getDeviceById---res')
|
},
|
async saveDevice(json) {
|
const res = await saveDevice(json)
|
if (res.success && res.code === 200 && res.data) {
|
/* 成功操作 */
|
this.$emit('submit')
|
/* 初始化 */
|
this.hideModel()
|
|
this.$toast({
|
type: 'success',
|
message: res && res.msg ? res.msg : '保存成功'
|
})
|
} else {
|
this.$toast({
|
type: 'error',
|
message: res && res.msg ? res.msg : '保存失败!'
|
})
|
}
|
console.log(res, 'saveDevice---res')
|
},
|
/* 接口 end */
|
// * 提交表单
|
handleOk(e) {
|
e.preventDefault()
|
if (!this.name) {
|
this.$toast({
|
type: 'warning',
|
message: '请输入角色名称'
|
})
|
return
|
}
|
this.$emit('submit', this.name, this.item ? this.item.id : '')
|
},
|
// * 取消
|
clearName() {},
|
submitForm() {
|
this.$refs['addForm'].validate(valid => {
|
if (valid) {
|
// const json = {...this.addForm,}
|
this.saveDevice(this.addForm)
|
} else {
|
console.log('error submit!!')
|
return false
|
}
|
})
|
},
|
resetForm() {
|
this.$refs['addForm'].resetFields()
|
this.videoUrl = ''
|
this.addForm = {
|
// id
|
orgId: '',
|
type: '',
|
name: '',
|
brand: '',
|
address: '',
|
latitude: '',
|
longitude: '',
|
ip: '',
|
port: '',
|
username: '',
|
password: ''
|
// code:''
|
}
|
},
|
setDeviceType(value) {
|
this.$refs['addForm'].clearValidate()
|
if (value === '101') {
|
console.log(value, '--value----选择了摄像机')
|
}
|
},
|
// 根据字典模版 拼接rtsp流地址
|
// urlTemplate: 'rtsp://[username]:[password]@[ip]:[port]/cam/realmonitor?channel=1&subtype=0'
|
getvideoUrl() {
|
if (!this.deviceBrandList.length) {
|
return ''
|
}
|
const setting = ['username', 'password', 'ip', 'port']
|
const itemArr = this.deviceBrandList.filter(
|
item => item.value === this.addForm.brand
|
)
|
if (itemArr.length === 1) {
|
let urlTemplate =
|
itemArr[0] && itemArr[0].urlTemplate ? itemArr[0].urlTemplate : ''
|
setting.map(val => {
|
urlTemplate = urlTemplate.replace(
|
`[${val}]`,
|
this.addForm[val] ? this.addForm[val] : ''
|
)
|
})
|
return urlTemplate
|
}
|
return ''
|
},
|
testLink() {
|
this.$refs['addForm'].validate(valid => {
|
if (valid) {
|
this.isTest = true
|
this.$refs.vxgPlayer.innerthml = ''
|
|
this.videoUrl = this.getvideoUrl()
|
console.log(this.videoUrl, 'this.videoUrl')
|
// 'rtsp://admin:a1234567@192.168.1.215:554/h264/ch1/main/av_stream'
|
if (!this.videoUrl) {
|
this.$toast({
|
type: 'error',
|
message: '播放路径错误!'
|
})
|
return false
|
}
|
this.vxgPlayerId = this.vxgPlayerId + new Date().getTime() + ''
|
this.$nextTick(() => {
|
this.vxgplayerInit({
|
id: this.vxgPlayerId,
|
url: this.videoUrl,
|
autostart: true
|
})
|
})
|
} else {
|
console.log('error submit!!')
|
return false
|
}
|
})
|
},
|
vxgplayerInit(optJson) {
|
const {
|
id = 'vxgplayer',
|
url = '',
|
nmf_path = 'media_player.nmf',
|
nmf_src = '/static/vxgplayer-1.8.31/pnacl/Release/media_player.nmf',
|
latency = '10000',
|
width = '360px',
|
height = '200px',
|
aspect_ratio_mode = 1,
|
autohide = 3,
|
controls = true,
|
connection_timeout = 5000,
|
connection_udp = 0,
|
custom_digital_zoom = false,
|
autostart = false
|
} = optJson
|
vxgplayer(id, {
|
...optJson,
|
url: url,
|
nmf_path,
|
nmf_src,
|
latency,
|
width,
|
height,
|
aspect_ratio_mode,
|
autohide,
|
controls,
|
connection_timeout,
|
connection_udp,
|
custom_digital_zoom
|
}).ready(data => {
|
vxgplayer(id).src(url)
|
vxgplayer(id).play()
|
/* 播放钩子函数 */
|
vxgplayer(id).onStateChange(state => {
|
if (state === 2) {
|
this.isTest = false
|
this.$toast({
|
type: 'success',
|
message: '测试连接成功,可以继续保存'
|
})
|
}
|
console.log('state', state)
|
})
|
})
|
}
|
}
|
}
|
</script>
|