index3.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. <template>
  2. <div class="content-management-system">
  3. <!-- 查询条件区域 -->
  4. <el-card class="filter-card">
  5. <el-form :model="queryParams" ref="queryForm" :inline="true" class="filter-form">
  6. <el-form-item label="内容ID">
  7. <el-input v-model="queryParams.contentId" placeholder="请输入内容ID" clearable />
  8. </el-form-item>
  9. <el-form-item label="内容类型">
  10. <el-select v-model="queryParams.contentType" placeholder="请选择内容类型" style="width: 180px;">
  11. <el-option label="全部" value="" />
  12. <el-option label="紧急通知" value="EMERGENCY" />
  13. <el-option label="日常通知" value="NORMAL" />
  14. <el-option label="背景音乐" value="MUSIC" />
  15. <el-option label="寻呼" value="PAGING" />
  16. <el-option label="演练" value="DRILL" />
  17. </el-select>
  18. </el-form-item>
  19. <el-form-item label="播放分区">
  20. <el-select v-model="queryParams.playZone" placeholder="请选择播放分区" style="width: 180px;">
  21. <el-option label="全部" value="" />
  22. <el-option label="全区" value="ZONE-ALL" />
  23. <el-option label="分区1" value="ZONE-001" />
  24. <el-option label="分区2" value="ZONE-002" />
  25. <el-option label="分区3" value="ZONE-003" />
  26. <el-option label="分区4" value="ZONE-004" />
  27. </el-select>
  28. </el-form-item>
  29. <el-form-item label="告警级别">
  30. <el-select v-model="queryParams.alarmLevel" placeholder="请选择告警级别" style="width: 180px;">
  31. <el-option label="全部" value="" />
  32. <el-option label="无告警" value="NONE" />
  33. <el-option label="低" value="LOW" />
  34. <el-option label="中" value="MEDIUM" />
  35. <el-option label="高" value="HIGH" />
  36. </el-select>
  37. </el-form-item>
  38. <el-form-item>
  39. <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
  40. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  41. </el-form-item>
  42. </el-form>
  43. </el-card>
  44. <!-- 数据表格区域 -->
  45. <el-card class="data-table">
  46. <el-table :data="contentList" border v-loading="loading">
  47. <el-table-column label="内容ID" prop="contentId" align="center" width="120" />
  48. <el-table-column label="内容类型" prop="contentType" align="center" width="120">
  49. <template #default="scope">
  50. {{ getContentTypeName(scope.row.contentType) }}
  51. </template>
  52. </el-table-column>
  53. <el-table-column label="音频路径" prop="audioPath" align="left" min-width="200">
  54. <template #default="scope">
  55. <!-- <el-link :href="scope.row.audioPath" type="primary" target="_blank">查看</el-link>-->
  56. <span>{{ scope.row.audioPath }}</span>
  57. </template>
  58. </el-table-column>
  59. <el-table-column label="播放分区" prop="playZones" align="center">
  60. <template #default="scope">
  61. {{ formatZones(scope.row.playZones) }}
  62. </template>
  63. </el-table-column>
  64. <el-table-column label="播放进度" prop="progress" align="center" width="120">
  65. <template #default="scope">
  66. <el-progress :percentage="parseInt(scope.row.progress)" :color="getProgressColor(scope.row.progress)" />
  67. </template>
  68. </el-table-column>
  69. <el-table-column label="分区状态" prop="zoneStatusMatrix" align="center" width="150">
  70. <template #default="scope">
  71. <span>{{ scope.row.zoneStatusMatrix.split('/')[0] }}台设备</span>
  72. <span v-if="parseInt(scope.row.zoneStatusMatrix.split('/')[1]) > 0" class="text-danger ml-2">
  73. {{ scope.row.zoneStatusMatrix.split('/')[1] }}台故障
  74. </span>
  75. </template>
  76. </el-table-column>
  77. <el-table-column label="告警级别" prop="alarmLevel" align="center" width="100">
  78. <template #default="scope">
  79. <el-tag :type="getAlarmLevelType(scope.row.alarmLevel)">{{ getAlarmLevelName(scope.row.alarmLevel) }}</el-tag>
  80. </template>
  81. </el-table-column>
  82. <el-table-column label="触发时间" prop="triggerTime" align="center" width="180" />
  83. <el-table-column label="CPU负载" prop="cpuLoad" align="right" width="100">
  84. <template #default="scope">
  85. <span>{{ scope.row.cpuLoad }}%</span>
  86. </template>
  87. </el-table-column>
  88. <el-table-column label="网络延迟" prop="networkLatency" align="right" width="100">
  89. <template #default="scope">
  90. <span>{{ scope.row.networkLatency }}ms</span>
  91. </template>
  92. </el-table-column>
  93. <el-table-column label="存储空间" prop="storageUsage" align="right" width="100">
  94. <template #default="scope">
  95. <span>{{ scope.row.storageUsage }}%</span>
  96. </template>
  97. </el-table-column>
  98. </el-table>
  99. <!-- 分页组件 -->
  100. <pagination
  101. v-show="total > 0"
  102. :total="total"
  103. v-model:page="queryParams.pageNum"
  104. v-model:limit="queryParams.pageSize"
  105. @pagination="getList"
  106. />
  107. </el-card>
  108. </div>
  109. </template>
  110. <script setup>
  111. import { ref, reactive } from 'vue';
  112. import {getBroadcastDataGenerator} from "@/api/publicBroadcasting/publicBroadcasting";
  113. // 查询参数
  114. const queryParams = reactive({
  115. contentId: '',
  116. contentType: '',
  117. playZone: '',
  118. alarmLevel: '',
  119. pageNum: 1,
  120. pageSize: 10,
  121. interfaceName: "广播内容与状态看板"
  122. });
  123. // 表格数据
  124. const contentList = ref([]);
  125. const total = ref(0);
  126. const loading = ref(false);
  127. const detailDialogVisible = ref(false);
  128. const detailContent = ref({});
  129. // 获取数据列表
  130. const getList = async () => {
  131. loading.value = true;
  132. try {
  133. let response = await getBroadcastDataGenerator(queryParams);
  134. // 处理返回数据
  135. let filteredData = [];
  136. // 内容ID过滤
  137. if (queryParams.contentId) {
  138. filteredData = filteredData.filter(item =>
  139. (item.contentId || '').includes(queryParams.contentId) // 新增空值处理
  140. );
  141. }
  142. // 内容类型过滤
  143. if (queryParams.contentType) {
  144. filteredData = filteredData.filter(item =>
  145. item.contentType === queryParams.contentType
  146. );
  147. }
  148. // 播放分区过滤(关键修复点)
  149. if (queryParams.playZone) {
  150. filteredData = filteredData.filter(item => {
  151. // 处理 playZones 可能为 undefined/null/数组的情况
  152. const playZones = item.playZones || ''; // 设默认空字符串
  153. const targetZone = queryParams.playZone;
  154. // 如果是数组,转为字符串
  155. if (Array.isArray(playZones)) {
  156. return playZones.includes(targetZone);
  157. } else {
  158. return playZones.includes(targetZone);
  159. }
  160. });
  161. }
  162. // 告警级别过滤
  163. if (queryParams.alarmLevel) {
  164. filteredData = filteredData.filter(item =>
  165. item.alarmLevel === queryParams.alarmLevel
  166. );
  167. }
  168. // 处理分页
  169. if (response.data && response.data.list) {
  170. // 使用后端分页数据
  171. contentList.value = [];
  172. total.value = 0;
  173. } else {
  174. // 手动分页(模拟数据)
  175. total.value = filteredData.length;
  176. const start = (queryParams.pageNum - 1) * queryParams.pageSize;
  177. const end = start + queryParams.pageSize;
  178. contentList.value = filteredData.slice(start, end);
  179. }
  180. } catch (error) {
  181. console.error('获取内容列表失败', error);
  182. } finally {
  183. loading.value = false;
  184. }
  185. };
  186. // 搜索方法
  187. const handleQuery = () => {
  188. queryParams.pageNum = 1; // 重置页码
  189. getList();
  190. };
  191. // 重置方法
  192. const resetQuery = () => {
  193. queryParams.contentId = '';
  194. queryParams.contentType = '';
  195. queryParams.playZone = '';
  196. queryParams.alarmLevel = '';
  197. handleQuery();
  198. };
  199. // 分页事件处理
  200. const handlePageChange = (newPage) => {
  201. queryParams.pageNum = newPage;
  202. getList();
  203. };
  204. const handleSizeChange = (newSize) => {
  205. queryParams.pageSize = newSize;
  206. queryParams.pageNum = 1; // 重置页码
  207. getList();
  208. };
  209. // 格式化分区显示
  210. const formatZones = (zones) => {
  211. if (!zones) return '-';
  212. if (zones === 'ZONE-ALL') return '全区';
  213. const zoneMap = {
  214. 'ZONE-001': '分区1',
  215. 'ZONE-002': '分区2',
  216. 'ZONE-003': '分区3',
  217. 'ZONE-004': '分区4'
  218. };
  219. return zones.split(',').map(zone => zoneMap[zone] || zone).join('、');
  220. };
  221. // 获取内容类型名称
  222. const getContentTypeName = (type) => {
  223. const typeMap = {
  224. 'EMERGENCY': '紧急通知',
  225. 'NORMAL': '日常通知',
  226. 'MUSIC': '背景音乐',
  227. 'PAGING': '寻呼',
  228. 'DRILL': '演练'
  229. };
  230. return typeMap[type] || type;
  231. };
  232. // 获取告警级别名称
  233. const getAlarmLevelName = (level) => {
  234. const levelMap = {
  235. 'NONE': '无告警',
  236. 'LOW': '低',
  237. 'MEDIUM': '中',
  238. 'HIGH': '高'
  239. };
  240. return levelMap[level] || level;
  241. };
  242. // 获取告警级别标签类型
  243. const getAlarmLevelType = (level) => {
  244. const typeMap = {
  245. 'NONE': 'success',
  246. 'LOW': 'info',
  247. 'MEDIUM': 'warning',
  248. 'HIGH': 'danger'
  249. };
  250. return typeMap[level] || '';
  251. };
  252. // 获取进度条颜色
  253. const getProgressColor = (progress) => {
  254. const value = parseInt(progress);
  255. if (value === 100) return '#52c41a'; // 完成
  256. if (value === 0) return '#f5222d'; // 未开始
  257. return '#1890ff'; // 进行中
  258. };
  259. // 查看详情
  260. const showDetail = (row) => {
  261. detailContent.value = row;
  262. detailDialogVisible.value = true;
  263. };
  264. // 初始化加载
  265. getList();
  266. </script>
  267. <style scoped>
  268. .filter-card {
  269. margin-bottom: 20px;
  270. }
  271. .data-table {
  272. min-height: 400px;
  273. }
  274. .text-danger {
  275. color: #f5222d;
  276. }
  277. .ml-2 {
  278. margin-left: 8px;
  279. }
  280. </style>