123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844 |
- <template>
- <div class="app-container">
- <el-tabs v-model="activeTab">
- <!-- 广播分区管理标签页 -->
- <el-tab-pane label="广播分区管理" name="zones">
- <el-form :model="zoneQuery" ref="zoneQueryRef" :inline="true" label-width="80px">
- <el-form-item label="分区名称" prop="zoneName">
- <el-input v-model="zoneQuery.zoneName" placeholder="请输入分区名称" clearable />
- </el-form-item>
- <el-form-item label="分区类型" prop="zoneType">
- <el-select v-model="zoneQuery.zoneType" placeholder="请选择分区类型" clearable>
- <el-option label="公共区域" value="公共区域" />
- <el-option label="办公区域" value="办公区域" />
- <el-option label="会议室" value="会议室" />
- <el-option label="走廊" value="走廊" />
- <el-option label="停车场" value="停车场" />
- </el-select>
- </el-form-item>
- <el-form-item label="楼栋" prop="buildingName">
- <el-select v-model="zoneQuery.buildingName" placeholder="请选择楼栋" clearable>
- <el-option label="A栋" value="A栋" />
- <el-option label="B栋" value="B栋" />
- <el-option label="C栋" value="C栋" />
- <el-option label="D栋" value="D栋" />
- <el-option label="E栋" value="E栋" />
- <el-option label="室外" value="室外" />
- <el-option label="地下" value="地下" />
- </el-select>
- </el-form-item>
- <el-form-item label="广播状态" prop="broadcastStatus">
- <el-select v-model="zoneQuery.broadcastStatus" placeholder="请选择状态" clearable>
- <el-option label="空闲" :value="0" />
- <el-option label="广播中" :value="1" />
- <el-option label="紧急广播" :value="2" />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" icon="Search" @click="getZoneList">搜索</el-button>
- <el-button icon="Refresh" @click="resetZoneQuery">重置</el-button>
- </el-form-item>
- </el-form>
- <!-- 快捷操作按钮 -->
- <el-row :gutter="10" class="mb8">
- <el-col :span="1.5">
- <el-button
- type="danger"
- plain
- icon="Notification"
- @click="handleEmergencyBroadcast"
- v-hasPermi="['broadcast:zone:emergency']"
- >紧急广播</el-button>
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="primary"
- plain
- icon="Microphone"
- @click="handleQuickBroadcast"
- v-hasPermi="['broadcast:zone:broadcast']"
- >快速广播</el-button>
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="warning"
- plain
- icon="Phone"
- @click="handlePaging"
- v-hasPermi="['broadcast:zone:paging']"
- >寻呼找人</el-button>
- </el-col>
- </el-row>
- <el-table
- v-loading="zoneLoading"
- :data="zoneList"
- stripe
- border
- @selection-change="handleSelectionChange"
- :row-class-name="getRowClassName"
- >
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column label="分区编码" prop="zoneCode" width="150" />
- <el-table-column label="分区名称" prop="zoneName" width="180" />
- <el-table-column label="分区类型" prop="zoneType" width="100" />
- <el-table-column label="位置" width="180">
- <template #default="scope">
- <span>{{ scope.row.spaceLocation }}</span>
- </template>
- </el-table-column>
- <el-table-column label="在线状态" prop="isOnline" width="90" align="center">
- <template #default="scope">
- <el-tag :type="scope.row.isOnline === 1 ? 'success' : 'danger'" effect="dark" size="small">
- {{ scope.row.isOnline === 1 ? '在线' : '离线' }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="广播状态" prop="broadcastStatus" width="120" align="center">
- <template #default="scope">
- <el-tag
- :type="getBroadcastStatusType(scope.row.broadcastStatus)"
- effect="dark"
- >
- <el-icon v-if="scope.row.broadcastStatus === 1" class="is-loading">
- <Loading />
- </el-icon>
- {{ getBroadcastStatusText(scope.row.broadcastStatus) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="当前播放" prop="currentContent" min-width="150" show-overflow-tooltip />
- <el-table-column label="音量控制" width="200" align="center">
- <template #default="scope">
- <div class="volume-control">
- <el-button
- :icon="scope.row.isMute ? 'MuteNotification' : 'Notification'"
- circle
- size="small"
- @click="toggleMute(scope.row)"
- :type="scope.row.isMute ? 'danger' : 'primary'"
- />
- <el-slider
- v-model="scope.row.volume"
- :disabled="scope.row.isMute || scope.row.isOnline === 0"
- @change="handleVolumeChange(scope.row)"
- style="width: 120px; margin: 0 10px;"
- />
- <span>{{ scope.row.volume }}%</span>
- </div>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="150" fixed="right">
- <template #default="scope">
- <el-button
- link
- type="primary"
- icon="VideoPlay"
- @click="handleControl(scope.row)"
- :disabled="scope.row.isOnline === 0"
- >控制</el-button>
- <el-button link type="primary" icon="View" @click="handleZoneDetail(scope.row)">详情</el-button>
- </template>
- </el-table-column>
- </el-table>
- <pagination
- v-show="zoneTotal > 0"
- :total="zoneTotal"
- v-model:page="zoneQuery.pageNum"
- v-model:limit="zoneQuery.pageSize"
- @pagination="getZoneList"
- />
- </el-tab-pane>
- <!-- 设备监控标签页 -->
- <el-tab-pane label="设备监控" name="devices">
- <el-form :model="deviceQuery" ref="deviceQueryRef" :inline="true" label-width="80px">
- <el-form-item label="设备名称" prop="deviceName">
- <el-input v-model="deviceQuery.deviceName" placeholder="请输入设备名称" clearable />
- </el-form-item>
- <el-form-item label="设备类型" prop="deviceType">
- <el-select v-model="deviceQuery.deviceType" placeholder="请选择设备类型" clearable>
- <el-option label="功放" value="功放" />
- <el-option label="音箱" value="音箱" />
- <el-option label="话筒" value="话筒" />
- <el-option label="控制器" value="控制器" />
- </el-select>
- </el-form-item>
- <el-form-item label="设备状态" prop="status">
- <el-select v-model="deviceQuery.status" placeholder="请选择状态" clearable>
- <el-option label="正常" :value="1" />
- <el-option label="故障" :value="0" />
- <el-option label="维护中" :value="2" />
- </el-select>
- </el-form-item>
- <el-form-item label="所属分区" prop="zoneName">
- <el-input v-model="deviceQuery.zoneName" placeholder="请输入分区名称" clearable />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" icon="Search" @click="getDeviceList">搜索</el-button>
- <el-button icon="Refresh" @click="resetDeviceQuery">重置</el-button>
- </el-form-item>
- </el-form>
- <!-- 设备统计卡片 -->
- <el-row :gutter="20" class="mb20">
- <el-col :span="6">
- <el-card class="stat-card">
- <div class="stat-item">
- <div class="stat-title">设备总数</div>
- <div class="stat-value total">{{ deviceStats.total }}</div>
- </div>
- </el-card>
- </el-col>
- <el-col :span="6">
- <el-card class="stat-card">
- <div class="stat-item">
- <div class="stat-title">在线设备</div>
- <div class="stat-value online">{{ deviceStats.online }}</div>
- </div>
- </el-card>
- </el-col>
- <el-col :span="6">
- <el-card class="stat-card">
- <div class="stat-item">
- <div class="stat-title">故障设备</div>
- <div class="stat-value fault">{{ deviceStats.fault }}</div>
- </div>
- </el-card>
- </el-col>
- <el-col :span="6">
- <el-card class="stat-card">
- <div class="stat-item">
- <div class="stat-title">维护中</div>
- <div class="stat-value maintenance">{{ deviceStats.maintenance }}</div>
- </div>
- </el-card>
- </el-col>
- </el-row>
- <el-table v-loading="deviceLoading" :data="deviceList" stripe border>
- <el-table-column label="设备编码" prop="deviceCode" width="150" />
- <el-table-column label="设备名称" prop="deviceName" width="180" />
- <el-table-column label="设备类型" prop="deviceType" width="100" align="center">
- <template #default="scope">
- <el-tag>{{ scope.row.deviceType }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="所属分区" prop="zoneName" width="180" />
- <el-table-column label="品牌型号" width="150">
- <template #default="scope">
- <div>{{ scope.row.brand }}</div>
- <div class="text-small">{{ scope.row.model }}</div>
- </template>
- </el-table-column>
- <el-table-column label="设备状态" prop="status" width="100" align="center">
- <template #default="scope">
- <el-tag :type="getDeviceStatusType(scope.row.status)" effect="dark">
- {{ getDeviceStatusText(scope.row.status) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="在线状态" prop="isOnline" width="100" align="center">
- <template #default="scope">
- <el-tag :type="scope.row.isOnline === 1 ? 'success' : 'danger'">
- {{ scope.row.isOnline === 1 ? '在线' : '离线' }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="故障信息" width="200" show-overflow-tooltip>
- <template #default="scope">
- <span v-if="scope.row.faultCode" class="fault-info">
- {{ scope.row.faultCode }}: {{ scope.row.faultDesc }}
- </span>
- <span v-else>-</span>
- </template>
- </el-table-column>
- <el-table-column label="最后心跳" prop="lastHeartbeat" width="160">
- <template #default="scope">
- <span>{{ parseTime(scope.row.lastHeartbeat) }}</span>
- </template>
- </el-table-column>
- </el-table>
- <pagination
- v-show="deviceTotal > 0"
- :total="deviceTotal"
- v-model:page="deviceQuery.pageNum"
- v-model:limit="deviceQuery.pageSize"
- @pagination="getDeviceList"
- />
- </el-tab-pane>
- </el-tabs>
- <!-- 分区详情抽屉 -->
- <el-drawer
- v-model="detailVisible"
- title="分区详情"
- direction="rtl"
- size="45%"
- >
- <el-descriptions :column="2" border>
- <el-descriptions-item label="分区编码">{{ currentZone.zoneCode }}</el-descriptions-item>
- <el-descriptions-item label="分区名称">{{ currentZone.zoneName }}</el-descriptions-item>
- <el-descriptions-item label="分区类型">{{ currentZone.zoneType }}</el-descriptions-item>
- <el-descriptions-item label="楼栋">{{ currentZone.buildingName }}</el-descriptions-item>
- <el-descriptions-item label="楼层">{{ currentZone.floorName }}</el-descriptions-item>
- <el-descriptions-item label="设备数量">{{ currentZone.deviceCount }}</el-descriptions-item>
- <el-descriptions-item label="空间位置" :span="2">{{ currentZone.spaceLocation }}</el-descriptions-item>
- <el-descriptions-item label="音量">{{ currentZone.volume }}%</el-descriptions-item>
- <el-descriptions-item label="静音状态">
- <el-tag :type="currentZone.isMute === 1 ? 'danger' : 'success'">
- {{ currentZone.isMute === 1 ? '已静音' : '正常' }}
- </el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="在线状态">
- <el-tag :type="currentZone.isOnline === 1 ? 'success' : 'danger'">
- {{ currentZone.isOnline === 1 ? '在线' : '离线' }}
- </el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="广播状态">
- <el-tag :type="getBroadcastStatusType(currentZone.broadcastStatus)">
- {{ getBroadcastStatusText(currentZone.broadcastStatus) }}
- </el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="当前播放内容" :span="2">
- {{ currentZone.currentContent || '无' }}
- </el-descriptions-item>
- <el-descriptions-item label="内容代号">{{ currentZone.contentCode || '-' }}</el-descriptions-item>
- <el-descriptions-item label="优先级">{{ currentZone.priority }}</el-descriptions-item>
- </el-descriptions>
- <!-- 分区内设备列表 -->
- <div class="zone-devices" v-if="zoneDevices && zoneDevices.length > 0">
- <h4>分区设备列表</h4>
- <el-table :data="zoneDevices" stripe size="small">
- <el-table-column label="设备编码" prop="deviceCode" />
- <el-table-column label="设备名称" prop="deviceName" />
- <el-table-column label="设备类型" prop="deviceType" />
- <el-table-column label="状态" prop="status" align="center">
- <template #default="scope">
- <el-tag :type="getDeviceStatusType(scope.row.status)" size="small">
- {{ getDeviceStatusText(scope.row.status) }}
- </el-tag>
- </template>
- </el-table-column>
- </el-table>
- </div>
- </el-drawer>
- <!-- 广播控制对话框 -->
- <el-dialog v-model="controlDialogVisible" title="广播控制" width="600px" append-to-body>
- <el-form ref="controlFormRef" :model="controlForm" :rules="controlRules" label-width="100px">
- <el-form-item label="分区名称">
- <el-input v-model="controlForm.zoneName" disabled />
- </el-form-item>
- <el-form-item label="广播内容" prop="contentCode">
- <el-select v-model="controlForm.contentCode" placeholder="请选择广播内容" @change="handleContentChange">
- <el-option
- v-for="item in contentList"
- :key="item.contentCode"
- :label="item.contentName"
- :value="item.contentCode"
- >
- <span style="float: left">{{ item.contentName }}</span>
- <span style="float: right; color: #8492a6; font-size: 13px">{{ item.contentType }}</span>
- </el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="播放模式" prop="playMode">
- <el-radio-group v-model="controlForm.playMode">
- <el-radio :label="1">单次播放</el-radio>
- <el-radio :label="2">循环播放</el-radio>
- <el-radio :label="3">定时播放</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="音量调节">
- <el-slider v-model="controlForm.volume" :min="0" :max="100" show-input />
- </el-form-item>
- <el-form-item label="优先级" prop="priority">
- <el-rate v-model="controlForm.priority" :max="10" show-text />
- </el-form-item>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="controlDialogVisible = false">取 消</el-button>
- <el-button type="primary" @click="submitControl">开始播放</el-button>
- <el-button type="danger" @click="stopBroadcast">停止播放</el-button>
- </span>
- </template>
- </el-dialog>
- <!-- 紧急广播对话框 -->
- <el-dialog v-model="emergencyDialogVisible" title="紧急广播" width="700px" append-to-body :close-on-click-modal="false">
- <el-alert
- title="紧急广播将中断所有正在播放的内容,请谨慎操作!"
- type="warning"
- show-icon
- :closable="false"
- style="margin-bottom: 20px"
- />
- <el-form ref="emergencyFormRef" :model="emergencyForm" :rules="emergencyRules" label-width="100px">
- <el-form-item label="广播范围" prop="broadcastRange">
- <el-radio-group v-model="emergencyForm.broadcastRange">
- <el-radio :label="1">全部分区</el-radio>
- <el-radio :label="2">选择分区</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="选择分区" v-if="emergencyForm.broadcastRange === 2" prop="selectedZones">
- <el-select
- v-model="emergencyForm.selectedZones"
- multiple
- placeholder="请选择分区"
- style="width: 100%"
- >
- <el-option
- v-for="zone in zoneList"
- :key="zone.id"
- :label="zone.zoneName"
- :value="zone.id"
- :disabled="zone.isOnline === 0"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="广播方式" prop="broadcastType">
- <el-radio-group v-model="emergencyForm.broadcastType">
- <el-radio :label="1">预设内容</el-radio>
- <el-radio :label="2">实时喊话</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="预设内容" v-if="emergencyForm.broadcastType === 1" prop="contentCode">
- <el-select v-model="emergencyForm.contentCode" placeholder="请选择紧急广播内容">
- <el-option
- v-for="item in emergencyContentList"
- :key="item.contentCode"
- :label="item.contentName"
- :value="item.contentCode"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="喊话内容" v-if="emergencyForm.broadcastType === 2" prop="message">
- <el-input
- v-model="emergencyForm.message"
- type="textarea"
- :rows="4"
- placeholder="请输入紧急广播内容"
- maxlength="200"
- show-word-limit
- />
- </el-form-item>
- <el-form-item label="循环次数" prop="loopCount">
- <el-input-number v-model="emergencyForm.loopCount" :min="1" :max="10" />
- </el-form-item>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="emergencyDialogVisible = false">取 消</el-button>
- <el-button type="danger" @click="submitEmergency">立即广播</el-button>
- </span>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup>
- import { ref, reactive, computed } from 'vue'
- import {
- listBroadcastZone,
- listBroadcastDevice,
- updateZoneVolume,
- controlBroadcast,
- emergencyBroadcast,
- getZoneDevices,
- getBroadcastContent
- } from '@/api/publicBroadcasting/broadcast'
- const { proxy } = getCurrentInstance()
- const activeTab = ref('zones')
- // 分区查询相关
- const zoneQuery = reactive({
- pageNum: 1,
- pageSize: 10,
- zoneName: null,
- zoneType: null,
- buildingName: null,
- broadcastStatus: null
- })
- const zoneList = ref([])
- const zoneTotal = ref(0)
- const zoneLoading = ref(false)
- const selectedZones = ref([])
- // 设备查询相关
- const deviceQuery = reactive({
- pageNum: 1,
- pageSize: 10,
- deviceName: null,
- deviceType: null,
- status: null,
- zoneName: null
- })
- const deviceList = ref([])
- const deviceTotal = ref(0)
- const deviceLoading = ref(false)
- // 设备统计
- const deviceStats = ref({
- total: 0,
- online: 0,
- fault: 0,
- maintenance: 0
- })
- // 详情相关
- const detailVisible = ref(false)
- const currentZone = ref({})
- const zoneDevices = ref([])
- // 广播控制相关
- const controlDialogVisible = ref(false)
- const controlForm = ref({
- zoneId: null,
- zoneName: '',
- contentCode: '',
- playMode: 1,
- volume: 50,
- priority: 5
- })
- const contentList = ref([])
- const controlRules = {
- contentCode: [
- { required: true, message: '请选择广播内容', trigger: 'change' }
- ]
- }
- // 紧急广播相关
- const emergencyDialogVisible = ref(false)
- const emergencyForm = ref({
- broadcastRange: 1,
- selectedZones: [],
- broadcastType: 1,
- contentCode: '',
- message: '',
- loopCount: 3
- })
- const emergencyContentList = ref([])
- const emergencyRules = {
- selectedZones: [
- { required: true, message: '请选择分区', trigger: 'change' }
- ],
- contentCode: [
- { required: true, message: '请选择广播内容', trigger: 'change' }
- ],
- message: [
- { required: true, message: '请输入喊话内容', trigger: 'blur' }
- ]
- }
- // 获取广播状态类型
- const getBroadcastStatusType = (status) => {
- const types = ['info', 'success', 'danger']
- return types[status] || 'info'
- }
- // 获取广播状态文本
- const getBroadcastStatusText = (status) => {
- const texts = ['空闲', '广播中', '紧急广播']
- return texts[status] || '未知'
- }
- // 获取设备状态类型
- const getDeviceStatusType = (status) => {
- const types = ['danger', 'success', 'warning']
- return types[status] || 'info'
- }
- // 获取设备状态文本
- const getDeviceStatusText = (status) => {
- const texts = ['故障', '正常', '维护中']
- return texts[status] || '未知'
- }
- // 获取行样式
- const getRowClassName = ({ row }) => {
- if (row.broadcastStatus === 2) {
- return 'emergency-row'
- } else if (row.broadcastStatus === 1) {
- return 'broadcasting-row'
- }
- return ''
- }
- // 查询分区列表
- function getZoneList() {
- zoneLoading.value = true
- listBroadcastZone(zoneQuery).then(response => {
- zoneList.value = response.rows
- zoneTotal.value = response.total
- zoneLoading.value = false
- })
- }
- // 查询设备列表
- function getDeviceList() {
- deviceLoading.value = true
- listBroadcastDevice(deviceQuery).then(response => {
- deviceList.value = response.rows
- deviceTotal.value = response.total
- // 更新统计数据
- if (response.extData) {
- deviceStats.value = response.extData
- }
- deviceLoading.value = false
- })
- }
- // 重置分区查询
- function resetZoneQuery() {
- proxy.resetForm('zoneQueryRef')
- zoneQuery.pageNum = 1
- getZoneList()
- }
- // 重置设备查询
- function resetDeviceQuery() {
- proxy.resetForm('deviceQueryRef')
- deviceQuery.pageNum = 1
- getDeviceList()
- }
- // 多选框选中数据
- function handleSelectionChange(selection) {
- selectedZones.value = selection
- }
- // 切换静音
- function toggleMute(row) {
- const newMuteStatus = row.isMute === 1 ? 0 : 1
- updateZoneVolume({
- id: row.id,
- isMute: newMuteStatus,
- volume: row.volume
- }).then(() => {
- row.isMute = newMuteStatus
- proxy.$modal.msgSuccess(newMuteStatus === 1 ? '已静音' : '已取消静音')
- })
- }
- // 音量调节
- function handleVolumeChange(row) {
- updateZoneVolume({
- id: row.id,
- volume: row.volume,
- isMute: row.isMute
- }).then(() => {
- proxy.$modal.msgSuccess('音量调节成功')
- })
- }
- // 广播控制
- function handleControl(row) {
- controlForm.value = {
- zoneId: row.id,
- zoneName: row.zoneName,
- contentCode: '',
- playMode: 1,
- volume: row.volume,
- priority: 5
- }
- // 获取广播内容列表
- getBroadcastContent({ contentType: '背景音乐,通知' }).then(response => {
- contentList.value = response.rows
- })
- controlDialogVisible.value = true
- }
- // 内容选择变化
- function handleContentChange(value) {
- const content = contentList.value.find(item => item.contentCode === value)
- if (content) {
- controlForm.value.priority = content.priority
- }
- }
- // 提交广播控制
- function submitControl() {
- proxy.$refs.controlFormRef.validate(valid => {
- if (valid) {
- controlBroadcast(controlForm.value).then(() => {
- proxy.$modal.msgSuccess('广播开始播放')
- controlDialogVisible.value = false
- getZoneList()
- })
- }
- })
- }
- // 停止广播
- function stopBroadcast() {
- proxy.$modal.confirm('确认停止当前广播吗?').then(() => {
- controlBroadcast({
- zoneId: controlForm.value.zoneId,
- action: 'stop'
- }).then(() => {
- proxy.$modal.msgSuccess('广播已停止')
- controlDialogVisible.value = false
- getZoneList()
- })
- })
- }
- // 紧急广播
- function handleEmergencyBroadcast() {
- emergencyForm.value = {
- broadcastRange: 1,
- selectedZones: [],
- broadcastType: 1,
- contentCode: '',
- message: '',
- loopCount: 3
- }
- // 获取紧急广播内容
- getBroadcastContent({ contentType: '紧急广播' }).then(response => {
- emergencyContentList.value = response.rows
- })
- emergencyDialogVisible.value = true
- }
- // 提交紧急广播
- function submitEmergency() {
- proxy.$refs.emergencyFormRef.validate(valid => {
- if (valid) {
- proxy.$modal.confirm('确认发送紧急广播吗?这将中断所有正在播放的内容!').then(() => {
- emergencyBroadcast(emergencyForm.value).then(() => {
- proxy.$modal.msgSuccess('紧急广播已发送')
- emergencyDialogVisible.value = false
- getZoneList()
- })
- })
- }
- })
- }
- // 快速广播
- function handleQuickBroadcast() {
- if (selectedZones.value.length === 0) {
- proxy.$modal.msgWarning('请先选择要广播的分区')
- return
- }
- // TODO: 实现快速广播功能
- proxy.$modal.msgWarning('快速广播功能开发中')
- }
- // 寻呼找人
- function handlePaging() {
- // TODO: 实现寻呼功能
- proxy.$modal.msgWarning('寻呼找人功能开发中')
- }
- // 查看分区详情
- function handleZoneDetail(row) {
- currentZone.value = row
- // 获取分区内设备
- getZoneDevices(row.id).then(response => {
- zoneDevices.value = response.rows
- })
- detailVisible.value = true
- }
- // 初始化
- getZoneList()
- </script>
- <style scoped>
- .volume-control {
- display: flex;
- align-items: center;
- }
- .stat-card {
- height: 100px;
- margin-bottom: 20px;
- }
- .stat-item {
- text-align: center;
- padding: 10px;
- }
- .stat-title {
- font-size: 14px;
- color: #909399;
- margin-bottom: 10px;
- }
- .stat-value {
- font-size: 28px;
- font-weight: bold;
- }
- .stat-value.total {
- color: #409EFF;
- }
- .stat-value.online {
- color: #67C23A;
- }
- .stat-value.fault {
- color: #F56C6C;
- }
- .stat-value.maintenance {
- color: #E6A23C;
- }
- .text-small {
- font-size: 12px;
- color: #909399;
- }
- .fault-info {
- color: #F56C6C;
- font-size: 12px;
- }
- .zone-devices {
- margin: 20px;
- }
- .zone-devices h4 {
- margin-bottom: 15px;
- }
- .mb20 {
- margin-bottom: 20px;
- }
- /* 表格行样式 */
- :deep(.emergency-row) {
- background-color: #fef0f0 !important;
- }
- :deep(.broadcasting-row) {
- background-color: #f0f9ff !important;
- }
- /* 加载动画 */
- .is-loading {
- animation: rotating 2s linear infinite;
- }
- @keyframes rotating {
- 0% {
- transform: rotate(0deg);
- }
- 100% {
- transform: rotate(360deg);
- }
- }
- </style>
|