diff --git a/web/src/styles/iconfont.scss b/web/src/styles/iconfont.scss index 05d191e8f..9ab351464 100644 --- a/web/src/styles/iconfont.scss +++ b/web/src/styles/iconfont.scss @@ -1,6 +1,6 @@ @font-face { font-family: "iconfont"; /* Project id 1291092 */ - src: url('iconfont.woff2?t=1769409737891') format('woff2') + src: url('iconfont.woff2?t=1780559263294') format('woff2'); } .iconfont { @@ -11,6 +11,54 @@ -moz-osx-font-smoothing: grayscale; } +.icon-dingshirenwuguanli:before { + content: "\e800"; +} + +.icon-zhongqi:before { + content: "\e801"; +} + +.icon-yunfuyangjiaojiao:before { + content: "\e7ff"; +} + +.icon-free:before { + content: "\e7fd"; +} + +.icon-Union-32:before { + content: "\e7fe"; +} + +.icon-ruanxianwei:before { + content: "\e7fc"; +} + +.icon-sudu:before { + content: "\e7fb"; +} + +.icon-shuipingxuanzhuan:before { + content: "\e7fa"; +} + +.icon-cengdie:before { + content: "\e7f9"; +} + +.icon-yinpin:before { + content: "\e7f6"; +} + +.icon-xiangjishezhi2:before { + content: "\e7f7"; +} + +.icon-cengdie3:before { + content: "\e815"; +} + .icon-xintiao:before { content: "\e7f4"; } diff --git a/web/src/styles/iconfont.woff2 b/web/src/styles/iconfont.woff2 index 3faf60053..84acc732e 100644 Binary files a/web/src/styles/iconfont.woff2 and b/web/src/styles/iconfont.woff2 differ diff --git a/web/src/views/device/channel/index.vue b/web/src/views/device/channel/index.vue index d3ad7eb49..6426ca65f 100755 --- a/web/src/views/device/channel/index.vue +++ b/web/src/views/device/channel/index.vue @@ -223,7 +223,7 @@ import devicePlayer from '../../dialog/devicePlayer.vue' import audioTalk from '../../dialog/audioTalk.vue' import Edit from './edit.vue' -import ptzConfig from '@/views/device/common/ptzConfig.vue' +import ptzConfig from '@/views/device/channel/ptzConfig.vue' export default { name: 'ChannelList', diff --git a/web/src/views/device/common/ptzConfig.vue b/web/src/views/device/channel/ptzConfig.vue similarity index 86% rename from web/src/views/device/common/ptzConfig.vue rename to web/src/views/device/channel/ptzConfig.vue index 3da124481..9ac3581c5 100644 --- a/web/src/views/device/common/ptzConfig.vue +++ b/web/src/views/device/channel/ptzConfig.vue @@ -13,8 +13,8 @@ 巡航组 - - 自动扫描 + + 线性扫描 @@ -43,12 +43,12 @@ @@ -125,7 +113,7 @@ export default { height: 100%; } .player-section { - flex: 1; + flex: 0.8; } .ptz-section { flex-shrink: 0; diff --git a/web/src/views/device/common/ptzCruiseConfig.vue b/web/src/views/device/common/ptzCruiseConfig.vue index 68e346974..f085f2b89 100644 --- a/web/src/views/device/common/ptzCruiseConfig.vue +++ b/web/src/views/device/common/ptzCruiseConfig.vue @@ -1,65 +1,76 @@ @@ -72,18 +83,18 @@ export default { }, data() { return { - cruiseId: 1, - presetPoints: [], - allPresetList: [], - selectedPreset: null, - showAddPoint: false, - showSpeedInput: false, - showTimeInput: false, - cruiseSpeed: 5, - cruiseTime: 15, - starting: false, - stopping: false, - deleting: false + cruiseTours: [], + cruisingCruiseId: null, + formVisible: false, + editingTourId: null, + submitting: false, + clearing: false, + operatingId: null, + deletingId: null, + formId: 1, + formName: '', + formPresets: [], + allPresetList: [] } }, created() { @@ -99,99 +110,155 @@ export default { console.log('[巡航] 加载预置点列表失败', error) }) }, - addPoint() { - if (!this.selectedPreset) { - this.$message({ showClose: true, message: '请选择预置点', type: 'warning' }) + getNextAvailableId() { + const used = new Set((this.cruiseTours || []).map(t => t.id)) + for (let i = 0; i <= 255; i++) { + if (!used.has(i)) return i + } + return 0 + }, + openAdd() { + this.editingTourId = null + this.formId = this.getNextAvailableId() + this.formName = '巡航组' + this.formId + this.formPresets = [] + this.formVisible = true + }, + openEdit(tour) { + this.editingTourId = tour.id + this.formId = tour.id + this.formName = tour.name + this.formPresets = (tour.presets || []).map(p => ({ + presetId: p.presetId, + dwellTime: p.dwellTime, + speed: p.speed + })) + if (this.formPresets.length === 0) { + this.formPresets.push({ presetId: this.getFirstPresetId(), dwellTime: 15, speed: 7 }) + } + this.formVisible = true + }, + cancelForm() { + this.formVisible = false + this.editingTourId = null + this.formPresets = [] + }, + getFirstPresetId() { + const first = this.allPresetList[0] + return first ? first.presetId : 1 + }, + addPresetRow() { + this.formPresets.push({ + presetId: this.getFirstPresetId(), + dwellTime: 15, + speed: 7 + }) + }, + removePresetRow(index) { + this.formPresets.splice(index, 1) + }, + confirmSave() { + if (!this.formName.trim()) { + this.$message({ showClose: true, message: '请输入巡航组名称', type: 'warning' }) return } - this.$store.dispatch('frontEnd/addPointForCruise', [this.deviceId, this.channelDeviceId, this.cruiseId, this.selectedPreset.presetId]) - .then(() => { - this.presetPoints.push(this.selectedPreset) - this.selectedPreset = null - this.showAddPoint = false - this.$message({ showClose: true, message: '添加成功', type: 'success' }) - }).catch(error => { - this.$message({ showClose: true, message: error, type: 'error' }) - }) + if (this.formId == null || this.formId < 0 || this.formId > 255) { + this.$message({ showClose: true, message: '巡航序号必须在0-255之间', type: 'warning' }) + return + } + this.submitting = true + let chain = Promise.resolve() + if (this.editingTourId !== null) { + chain = chain.then(() => this.$store.dispatch('frontEnd/deletePointForCruise', [this.deviceId, this.channelDeviceId, this.formId, 0])) + } + this.formPresets.forEach(p => { + chain = chain.then(() => this.$store.dispatch('frontEnd/addPointForCruise', [this.deviceId, this.channelDeviceId, this.formId, p.presetId])) + }) + const speed = this.formPresets.length > 0 ? this.formPresets[0].speed : 7 + const dwellTime = this.formPresets.length > 0 ? this.formPresets[0].dwellTime : 15 + chain = chain.then(() => this.$store.dispatch('frontEnd/setCruiseSpeed', [this.deviceId, this.channelDeviceId, this.formId, speed])) + chain = chain.then(() => this.$store.dispatch('frontEnd/setCruiseTime', [this.deviceId, this.channelDeviceId, this.formId, dwellTime])) + chain.then(() => { + const idx = this.cruiseTours.findIndex(t => t.id === this.formId) + const presets = this.formPresets.map(p => ({ + presetId: p.presetId, + dwellTime: p.dwellTime, + speed: p.speed + })) + const tour = { id: this.formId, name: this.formName, presets } + if (idx !== -1) { + this.$set(this.cruiseTours, idx, tour) + } else { + this.cruiseTours.push(tour) + } + this.cancelForm() + this.$message({ showClose: true, message: '保存成功', type: 'success' }) + }).catch(error => { + this.$message({ showClose: true, message: error || '保存失败', type: 'error' }) + }).finally(() => { + this.submitting = false + }) }, - removePoint(preset, index) { - this.$store.dispatch('frontEnd/deletePointForCruise', [this.deviceId, this.channelDeviceId, this.cruiseId, preset.presetId]) - .then(() => { - this.presetPoints.splice(index, 1) - this.$message({ showClose: true, message: '删除成功', type: 'success' }) - }).catch(error => { - this.$message({ showClose: true, message: error, type: 'error' }) - }) - }, - openSpeed() { - this.showSpeedInput = true - }, - cancelSpeed() { - this.showSpeedInput = false - this.cruiseSpeed = 5 - }, - setSpeed() { - this.$store.dispatch('frontEnd/setCruiseSpeed', [this.deviceId, this.channelDeviceId, this.cruiseId, this.cruiseSpeed]) - .then(() => { - this.showSpeedInput = false - this.$message({ showClose: true, message: '速度设置成功', type: 'success' }) - }).catch(error => { - this.$message({ showClose: true, message: error, type: 'error' }) - }) - }, - openTime() { - this.showTimeInput = true - }, - cancelTime() { - this.showTimeInput = false - this.cruiseTime = 15 - }, - setTime() { - this.$store.dispatch('frontEnd/setCruiseTime', [this.deviceId, this.channelDeviceId, this.cruiseId, this.cruiseTime]) - .then(() => { - this.showTimeInput = false - this.$message({ showClose: true, message: '时间设置成功', type: 'success' }) - }).catch(error => { - this.$message({ showClose: true, message: error, type: 'error' }) - }) - }, - startCruise() { - this.starting = true - this.$store.dispatch('frontEnd/startCruise', [this.deviceId, this.channelDeviceId, this.cruiseId]) - .then(() => { - this.$message({ showClose: true, message: '巡航启动成功', type: 'success' }) - }).catch(error => { - this.$message({ showClose: true, message: error, type: 'error' }) - }).finally(() => { - this.starting = false - }) - }, - stopCruise() { - this.stopping = true - this.$store.dispatch('frontEnd/stopCruise', [this.deviceId, this.channelDeviceId, this.cruiseId]) - .then(() => { - this.$message({ showClose: true, message: '巡航停止成功', type: 'success' }) - }).catch(error => { - this.$message({ showClose: true, message: error, type: 'error' }) - }).finally(() => { - this.stopping = false - }) - }, - deleteCruise() { - this.$confirm('确定删除此巡航组所有点?', '提示', { - confirmButtonText: '确定', - cancelButtonText: '取消', - type: 'warning' + clearCruiseTours() { + if (this.cruiseTours.length === 0) return + this.$confirm('确定清空所有巡航组?', '提示', { + confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { - this.deleting = true - this.$store.dispatch('frontEnd/deletePointForCruise', [this.deviceId, this.channelDeviceId, this.cruiseId, 0]) + this.clearing = true + let chain = Promise.resolve() + this.cruiseTours.forEach(tour => { + chain = chain.then(() => this.$store.dispatch('frontEnd/deletePointForCruise', [this.deviceId, this.channelDeviceId, tour.id, 0])) + }) + chain.then(() => { + this.cruiseTours = [] + this.cruisingCruiseId = null + this.$message({ showClose: true, message: '清空成功', type: 'success' }) + }).catch(() => { + this.$message({ showClose: true, message: '清空失败', type: 'error' }) + }).finally(() => { + this.clearing = false + }) + }).catch(() => {}) + }, + startCruise(row) { + this.operatingId = row.id + this.$store.dispatch('frontEnd/startCruise', [this.deviceId, this.channelDeviceId, row.id]) + .then(() => { + this.cruisingCruiseId = row.id + this.$message({ showClose: true, message: '启用成功', type: 'success' }) + }).catch(() => { + this.$message({ showClose: true, message: '启用失败', type: 'error' }) + }).finally(() => { + this.operatingId = null + }) + }, + stopCruise(row) { + this.operatingId = row.id + this.$store.dispatch('frontEnd/stopCruise', [this.deviceId, this.channelDeviceId, row.id]) + .then(() => { + this.cruisingCruiseId = null + this.$message({ showClose: true, message: '停止成功', type: 'success' }) + }).catch(() => { + this.$message({ showClose: true, message: '停止失败', type: 'error' }) + }).finally(() => { + this.operatingId = null + }) + }, + deleteCruise(row) { + this.$confirm('确定删除此巡航组?', '提示', { + confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' + }).then(() => { + this.deletingId = row.id + this.$store.dispatch('frontEnd/deletePointForCruise', [this.deviceId, this.channelDeviceId, row.id, 0]) .then(() => { - this.presetPoints = [] + const idx = this.cruiseTours.indexOf(row) + if (idx !== -1) this.cruiseTours.splice(idx, 1) + if (this.cruisingCruiseId === row.id) this.cruisingCruiseId = null this.$message({ showClose: true, message: '删除成功', type: 'success' }) - }).catch(error => { - this.$message({ showClose: true, message: error, type: 'error' }) + }).catch(() => { + this.$message({ showClose: true, message: '删除失败', type: 'error' }) }).finally(() => { - this.deleting = false + this.deletingId = null }) }).catch(() => {}) }