[1078] 合并新UI

This commit is contained in:
lin
2025-05-12 18:01:10 +08:00
parent c4ab55a456
commit e4a0a37f0b
6 changed files with 266 additions and 273 deletions

View File

@@ -24,6 +24,22 @@ export function queryDeviceById(deviceId) {
})
}
export function update(form) {
return request({
method: 'post',
url: `/api/jt1078/terminal/update`,
params: form
})
}
export function add(form) {
return request({
method: 'post',
url: `/api/jt1078/terminal/add`,
params: form
})
}
export function deleteDeviceById(deviceId) {
return request({
method: 'delete',

View File

@@ -22,6 +22,7 @@ import userApiKeys from './modules/userApiKeys'
import gbRecord from './modules/gbRecord'
import log from './modules/log'
import frontEnd from './modules/frontEnd'
import jtDevice from './modules/jtDevice'
Vue.use(Vuex)
@@ -47,7 +48,8 @@ const store = new Vuex.Store({
userApiKeys,
gbRecord,
log,
frontEnd
frontEnd,
jtDevice
},
getters
})

View File

@@ -1,4 +1,6 @@
import { deleteDeviceById, queryChannels, queryDeviceById, queryDevices } from '@/api/jtDevice'
import { add } from '@/api/user'
import { update } from '@/api/group'
const actions = {
queryDevices({ commit }, params) {
@@ -11,6 +13,26 @@ const actions = {
})
})
},
add({ commit }, params) {
return new Promise((resolve, reject) => {
add(params).then(response => {
const { data } = response
resolve(data)
}).catch(error => {
reject(error)
})
})
},
update({ commit }, params) {
return new Promise((resolve, reject) => {
update(params).then(response => {
const { data } = response
resolve(data)
}).catch(error => {
reject(error)
})
})
},
queryDeviceById({ commit }, deviceId) {
return new Promise((resolve, reject) => {
queryDeviceById(deviceId).then(response => {

View File

@@ -1,61 +1,81 @@
<template>
<div id="channelList" style="width: 100%">
<div id="channelList" style="height: calc(100vh - 124px);">
<div v-if="!jtChannel">
<div class="page-header" >
<div class="page-header">
<div class="page-title">
<el-button icon="el-icon-back" size="mini" style="font-size: 20px; color: #000;" type="text" @click="showDevice" ></el-button>
<el-divider direction="vertical"></el-divider>
<el-button icon="el-icon-back" size="mini" style="font-size: 20px; color: #000;" type="text" @click="showDevice" />
<el-divider direction="vertical" />
通道列表
</div>
<div class="page-header-btn">
<div style="display: inline;">
搜索:
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
<el-input
v-model="searchSrt"
style="margin-right: 1rem; width: auto;"
size="mini"
placeholder="关键字"
prefix-icon="el-icon-search"
clearable
@input="search"
/>
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加通道</el-button>
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
<el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()" />
</div>
</div>
</div>
<el-container v-loading="isLoging" style="height: 82vh;">
<el-main style="padding: 5px;">
<el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" style="width: 100%"
header-row-class-name="table-header">
<el-table-column prop="channelId" label="通道编号" min-width="180">
</el-table-column>
<el-table-column prop="name" label="名称" min-width="180">
</el-table-column>
<el-table
ref="channelListTable"
:data="deviceChannelList"
:height="winHeight"
style="width: 100%"
header-row-class-name="table-header"
>
<el-table-column prop="channelId" label="通道编号" min-width="180" />
<el-table-column prop="name" label="名称" min-width="180" />
<el-table-column label="快照" min-width="100">
<template v-slot:default="scope">
<el-image
:src="getSnap(scope.row)"
:preview-src-list="getBigSnap(scope.row)"
@error="getSnapErrorEvent(scope.row.deviceId, scope.row.channelId)"
:fit="'contain'"
style="width: 60px">
style="width: 60px"
@error="getSnapErrorEvent(scope.row.deviceId, scope.row.channelId)"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
<i class="el-icon-picture-outline" />
</div>
</el-image>
</template>
</el-table-column>
<el-table-column label="开启音频" min-width="100">
<template slot-scope="scope">
<el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
</el-switch>
<el-switch v-model="scope.row.hasAudio" active-color="#409EFF" @change="updateChannel(scope.row)" />
</template>
</el-table-column>
<el-table-column label="操作" min-width="340" fixed="right">
<template slot-scope="scope">
<el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play"
type="text" @click="sendDevicePush(scope.row)">播放
<el-button
size="medium"
:disabled="device == null || device.online === 0"
icon="el-icon-video-play"
type="text"
@click="sendDevicePush(scope.row)"
>播放
</el-button>
<el-button size="medium" v-bind:disabled="device == null || device.online === 0"
icon="el-icon-switch-button"
type="text" style="color: #f56c6c" v-if="!!scope.row.stream"
@click="stopDevicePush(scope.row)">停止
<el-button
v-if="!!scope.row.stream"
size="medium"
:disabled="device == null || device.online === 0"
icon="el-icon-switch-button"
type="text"
style="color: #f56c6c"
@click="stopDevicePush(scope.row)"
>停止
</el-button>
<el-divider direction="vertical"></el-divider>
<el-divider direction="vertical" />
<el-button
size="medium"
type="text"
@@ -64,15 +84,15 @@
>
编辑
</el-button>
<el-divider direction="vertical"></el-divider>
<el-divider direction="vertical" />
<el-dropdown @command="(command)=>{moreClick(command, scope.row)}">
<el-button size="medium" type="text" >
更多功能<i class="el-icon-arrow-down el-icon--right"></i>
<el-button size="medium" type="text">
更多功能<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="records" v-bind:disabled="device == null || device.online === 0">
<el-dropdown-item command="records" :disabled="device == null || device.online === 0">
设备录像</el-dropdown-item>
<el-dropdown-item command="cloudRecords" v-bind:disabled="device == null || device.online === 0" >
<el-dropdown-item command="cloudRecords" :disabled="device == null || device.online === 0">
云端录像</el-dropdown-item>
<!-- <el-dropdown-item command="shooting" v-bind:disabled="device == null || device.online === 0" >-->
<!-- 立即拍摄</el-dropdown-item>-->
@@ -83,38 +103,33 @@
</el-table>
<el-pagination
style="float: right"
@size-change="handleSizeChange"
@current-change="currentChange"
:current-page="currentPage"
:page-size="count"
:page-sizes="[15, 25, 35, 50]"
layout="total, sizes, prev, pager, next"
:total="total">
</el-pagination>
:total="total"
@size-change="handleSizeChange"
@current-change="currentChange"
/>
</el-main>
</el-container>
</div>
<devicePlayer ref="devicePlayer"></devicePlayer>
<channelEdit v-if="jtChannel" ref="channelEdit" :jtChannel="jtChannel" :closeEdit="closeEdit"></channelEdit>
<devicePlayer ref="devicePlayer" />
<channelEdit v-if="jtChannel" ref="channelEdit" :jt-channel="jtChannel" :close-edit="closeEdit" />
<!--设备列表-->
</div>
</template>
<script>
import devicePlayer from './dialog/jtDevicePlayer.vue'
import uiHeader from '../layout/UiHeader.vue'
import DeviceTree from "./common/DeviceTree";
import channelEdit from "./JTChannelEdit.vue";
import JTDeviceService from "./service/JTDeviceService";
import devicePlayer from '../jtDevicePlayer.vue'
import channelEdit from './edit.vue'
export default {
name: 'channelList',
name: 'ChannelList',
components: {
channelEdit,
devicePlayer,
uiHeader,
DeviceTree
devicePlayer
},
data() {
return {
@@ -122,205 +137,201 @@ export default {
device: null,
deviceId: this.$route.params.deviceId,
deviceChannelList: [],
updateLooper: 0, //数据刷新轮训标志
searchSrt: "",
channelType: "",
online: "",
updateLooper: 0, // 数据刷新轮训标志
searchSrt: '',
channelType: '',
online: '',
winHeight: window.innerHeight - 200,
currentPage: 1,
count: 15,
total: 0,
beforeUrl: "/jtDeviceList",
beforeUrl: '/jtDeviceList',
isLoging: false,
loadSnap: {},
jtChannel: null,
};
jtChannel: null
}
},
mounted() {
this.initParam();
this.initData();
this.initParam()
this.initData()
},
destroyed() {
this.$destroy('videojs');
clearTimeout(this.updateLooper);
this.$destroy('videojs')
clearTimeout(this.updateLooper)
},
methods: {
initData: function () {
this.getDeviceChannelList();
initData: function() {
this.getDeviceChannelList()
},
initParam: function () {
this.deviceId = this.$route.params.deviceId;
this.currentPage = 1;
this.count = 15;
initParam: function() {
this.deviceId = this.$route.params.deviceId
this.currentPage = 1
this.count = 15
this.deviceService.getDevice(this.deviceId, (result) => {
if (result.code === 0) {
this.device = result.data;
this.device = result.data
}
}, (error) => {
console.log("获取设备信息失败")
console.log('获取设备信息失败')
console.error(error)
})
},
currentChange: function (val) {
this.currentPage = val;
this.initData();
currentChange: function(val) {
this.currentPage = val
this.initData()
},
handleSizeChange: function (val) {
this.count = val;
this.getDeviceChannelList();
handleSizeChange: function(val) {
this.count = val
this.getDeviceChannelList()
},
getDeviceChannelList: function () {
if (typeof (this.deviceId) == "undefined") return;
this.deviceService.getAllChannel(this.currentPage, this.count, this.searchSrt, this.deviceId, (data)=>{
getDeviceChannelList: function() {
if (typeof (this.deviceId) === 'undefined') return
this.deviceService.getAllChannel(this.currentPage, this.count, this.searchSrt, this.deviceId, (data) => {
console.log(data)
if (data.code === 0) {
this.total = data.data.total;
this.deviceChannelList = data.data.list;
this.total = data.data.total
this.deviceChannelList = data.data.list
// 防止出现表格错位
this.$nextTick(() => {
this.$refs.channelListTable.doLayout();
this.$refs.channelListTable.doLayout()
})
}
})
},
//通知设备上传媒体流
sendDevicePush: function (itemData) {
this.isLoging = true;
let channelId = itemData.channelId;
console.log("通知设备推流1" + this.device.phoneNumber + " : " + channelId);
// 通知设备上传媒体流
sendDevicePush: function(itemData) {
this.isLoging = true
const channelId = itemData.channelId
console.log('通知设备推流1' + this.device.phoneNumber + ' : ' + channelId)
this.$axios({
method: 'get',
url: '/api/jt1078/live/start',
params: {
phoneNumber: this.device.phoneNumber,
channelId: channelId,
type: 0,
type: 0
}
}).then((res)=> {
this.isLoging = false;
}).then((res) => {
this.isLoging = false
if (res.data.code === 0) {
setTimeout(() => {
let snapId = this.device.phoneNumber + "_" + channelId;
this.loadSnap[this.device.phoneNumber + channelId] = 0;
const snapId = this.device.phoneNumber + '_' + channelId
this.loadSnap[this.device.phoneNumber + channelId] = 0
this.getSnapErrorEvent(snapId)
}, 5000)
itemData.streamId = res.data.data.stream;
this.$refs.devicePlayer.openDialog("media", this.device.phoneNumber, channelId, {
itemData.streamId = res.data.data.stream
this.$refs.devicePlayer.openDialog('media', this.device.phoneNumber, channelId, {
streamInfo: res.data.data,
hasAudio: itemData.hasAudio
});
})
setTimeout(() => {
this.initData();
this.initData()
}, 1000)
} else {
this.$message.error(res.data.msg);
this.$message.error(res.data.msg)
}
}).catch((e)=> {
}).catch((e) => {
console.error(e)
this.isLoging = false;
this.isLoging = false
// that.$message.error("请求超时");
});
})
},
moreClick: function (command, itemData) {
if (command === "records") {
moreClick: function(command, itemData) {
if (command === 'records') {
this.queryRecords(itemData)
}else if (command === "cloudRecords") {
} else if (command === 'cloudRecords') {
this.queryCloudRecords(itemData)
}else {
this.$message.info("尚不支持");
} else {
this.$message.info('尚不支持')
}
},
queryRecords: function (itemData) {
queryRecords: function(itemData) {
this.$router.push(`/jtRecordDetail/${this.device.phoneNumber}/${itemData.channelId}`)
},
queryCloudRecords: function (itemData) {
let deviceId = this.deviceId;
let channelId = itemData.channelId;
queryCloudRecords: function(itemData) {
const deviceId = this.deviceId
const channelId = itemData.channelId
this.$router.push(`/cloudRecordDetail/rtp/${deviceId}_${channelId}`)
},
stopDevicePush: function (itemData) {
stopDevicePush: function(itemData) {
this.$axios({
method: 'get',
url: '/api/jt1078/live/stop',
params: {
phoneNumber: this.device.phoneNumber,
channelId: itemData.channelId,
channelId: itemData.channelId
}
}).then((res)=> {
}).then((res) => {
console.log(res)
if (res.data.code === 0) {
this.initData();
}else {
this.$message.error(res.data.msg);
this.initData()
} else {
this.$message.error(res.data.msg)
}
}).catch(function (error) {
}).catch(function(error) {
console.error(error)
});
},
getSnap: function (row) {
let baseUrl = window.baseUrl ? window.baseUrl : "";
return ((process.env.NODE_ENV === 'development') ? process.env.BASE_API : baseUrl) + '/api/device/query/snap/' + this.device.phoneNumber + '/' + row.channelId;
},
getBigSnap: function (row) {
return [this.getSnap(row)]
},
getSnapErrorEvent: function (deviceId, channelId) {
if (typeof (this.loadSnap[deviceId + channelId]) != "undefined") {
console.log("下载截图" + this.loadSnap[deviceId + channelId])
if (this.loadSnap[deviceId + channelId] > 5) {
delete this.loadSnap[deviceId + channelId];
return;
}
setTimeout(() => {
let url = (process.env.NODE_ENV === 'development' ? "debug" : "") + '/api/device/query/snap/' + deviceId + '/' + channelId
this.loadSnap[deviceId + channelId]++
document.getElementById(deviceId + channelId).setAttribute("src", url + '?' + new Date().getTime())
}, 1000)
}
},
showDevice: function () {
this.$router.push(this.beforeUrl).then(() => {
this.initParam();
this.initData();
})
},
search: function () {
this.currentPage = 1;
this.total = 0;
this.initData();
getSnap: function(row) {
const baseUrl = window.baseUrl ? window.baseUrl : ''
return ((process.env.NODE_ENV === 'development') ? process.env.BASE_API : baseUrl) + '/api/device/query/snap/' + this.device.phoneNumber + '/' + row.channelId
},
updateChannel: function (row) {
getBigSnap: function(row) {
return [this.getSnap(row)]
},
getSnapErrorEvent: function(deviceId, channelId) {
if (typeof (this.loadSnap[deviceId + channelId]) !== 'undefined') {
console.log('下载截图' + this.loadSnap[deviceId + channelId])
if (this.loadSnap[deviceId + channelId] > 5) {
delete this.loadSnap[deviceId + channelId]
return
}
setTimeout(() => {
const url = (process.env.NODE_ENV === 'development' ? 'debug' : '') + '/api/device/query/snap/' + deviceId + '/' + channelId
this.loadSnap[deviceId + channelId]++
document.getElementById(deviceId + channelId).setAttribute('src', url + '?' + new Date().getTime())
}, 1000)
}
},
showDevice: function() {
this.$router.push(this.beforeUrl).then(() => {
this.initParam()
this.initData()
})
},
search: function() {
this.currentPage = 1
this.total = 0
this.initData()
},
updateChannel: function(row) {
this.$axios({
method: 'post',
url: `/api/jt1078/terminal/channel/update`,
params: row
}).then(function (res) {
console.log(JSON.stringify(res));
});
}).then(function(res) {
console.log(JSON.stringify(res))
})
},
refresh: function () {
this.initData();
refresh: function() {
this.initData()
},
add: function () {
add: function() {
this.jtChannel = {
terminalDbId: this.deviceId
};
}
},
// 编辑
handleEdit(row) {
this.jtChannel = row;
this.jtChannel = row
},
// 编辑
closeEdit(row) {
this.jtChannel = null;
this.jtChannel = null
}
}
};
}
</script>

View File

@@ -10,13 +10,13 @@
@close="close()"
>
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
<el-form ref="form" :rules="rules" :model="form" label-width="200px" >
<el-form ref="form" :rules="rules" :model="form" label-width="200px">
<el-form-item label="终端手机号" prop="phoneNumber">
<el-input v-model="form.phoneNumber" clearable></el-input>
<el-input v-model="form.phoneNumber" clearable />
</el-form-item>
<el-form-item>
<div style="float: right;">
<el-button type="primary" @click="onSubmit" >确认</el-button>
<el-button type="primary" @click="onSubmit">确认</el-button>
<el-button @click="close">取消</el-button>
</div>
</el-form-item>
@@ -28,10 +28,8 @@
<script>
export default {
name: "deviceEdit",
name: 'DeviceEdit',
props: {},
computed: {},
created() {},
data() {
return {
listChangeCallback: null,
@@ -40,49 +38,50 @@ export default {
form: {},
isEdit: false,
rules: {
deviceId: [{ required: true, message: "请输入设备编号", trigger: "blur" }]
},
};
deviceId: [{ required: true, message: '请输入设备编号', trigger: 'blur' }]
}
}
},
computed: {},
created() {},
methods: {
openDialog: function (row, callback) {
openDialog: function(row, callback) {
console.log(row)
this.showDialog = true;
this.isEdit = false;
this.showDialog = true
this.isEdit = false
if (row) {
this.isEdit = true;
this.isEdit = true
}
this.form = {};
this.listChangeCallback = callback;
this.form = {}
this.listChangeCallback = callback
if (row != null) {
this.form = row;
this.form = row
}
},
onSubmit: function () {
console.log("onSubmit");
this.$axios({
method: 'post',
url:`/api/jt1078/terminal/${this.isEdit?'update':'add'}/`,
params: this.form
}).then((res) => {
console.log(res.data)
if (res.data.code === 0) {
this.listChangeCallback()
}else {
this.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
}).catch(function (error) {
console.log(error);
});
onSubmit: function() {
console.log('onSubmit')
if (this.isEdit) {
this.$store.dispatch('jtDevice/update', this.form)
.then(data => {
this.listChangeCallback()
})
.catch(function(error) {
console.log(error)
})
} else {
this.$store.dispatch('jtDevice/add', this.form)
.then(data => {
this.listChangeCallback()
})
.catch(function(error) {
console.log(error)
})
}
},
close: function () {
this.showDialog = false;
this.$refs.form.resetFields();
},
},
};
close: function() {
this.showDialog = false
this.$refs.form.resetFields()
}
}
}
</script>

View File

@@ -124,19 +124,16 @@
@current-change="currentChange"
/>
<deviceEdit ref="deviceEdit" />
<syncChannelProgress ref="syncChannelProgress" />
</div>
</template>
<script>
import deviceEdit from './edit.vue'
import syncChannelProgress from '../dialog/SyncChannelProgress.vue'
export default {
name: 'App',
components: {
deviceEdit,
syncChannelProgress
deviceEdit
},
data() {
return {
@@ -171,17 +168,17 @@ export default {
},
getList: function() {
this.getListLoading = true
this.$store.dispatch('jtDevice/getList', {})
this.deviceService.getDeviceList(this.currentPage, this.count, (data) => {
if (data.code === 0) {
this.total = data.data.total
this.deviceList = data.data.list
}
this.getListLoading = false
}, () => {
this.getListLoading = false
}
)
this.$store.dispatch('jtDevice/queryDevices', {
page: this.currentPage,
count: this.count
})
.then(data => {
this.total = data.total
this.deviceList = data.list
})
.finally(() => {
this.getListLoading = false
})
},
deleteDevice: function(row) {
this.$confirm('确定删除此设备?', '提示', {
@@ -191,9 +188,10 @@ export default {
center: true,
type: 'warning'
}).then(() => {
this.deviceService.deleteDevice(row.id, (data) => {
this.getList()
})
this.$store.dispatch('jtDevice/deleteDeviceById', row.id)
.then(data => {
this.getList()
})
}).catch(() => {
})
@@ -210,7 +208,7 @@ export default {
})
},
showChannelList: function(row) {
this.$router.push(`/jtChannelList/${row.id}`)
this.$emit('show-channel', row.id)
},
add: function() {
this.$refs.deviceEdit.openDialog(null, () => {
@@ -236,58 +234,3 @@ export default {
}
}
</script>
<style>
.videoList {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
.video-item {
position: relative;
width: 15rem;
height: 10rem;
margin-right: 1rem;
background-color: #000000;
}
.video-item-img {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
width: 100%;
height: 100%;
}
.video-item-img:after {
content: "";
display: inline-block;
position: absolute;
z-index: 2;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
width: 3rem;
height: 3rem;
background-image: url("../assets/loading.png");
background-size: cover;
background-color: #000000;
}
.video-item-title {
position: absolute;
bottom: 0;
color: #000000;
background-color: #ffffff;
line-height: 1.5rem;
padding: 0.3rem;
width: 14.4rem;
}
</style>