eventDetails.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. <template>
  2. <div class="detail-container">
  3. <div class="common-back-box" @click="handleBack">
  4. <i class="common-back" />
  5. 返回上一级
  6. </div>
  7. <div class="common-header">
  8. <div class="common-header-left">
  9. <i class="common-title-icon" />
  10. <div>{{ detailData.event_title }}</div>
  11. </div>
  12. <div class="common-header-right">
  13. <el-button type="primary" :disabled="detailData.del_flag == '2'" @click="handleUpdate">
  14. <i class="edit-icon2" />
  15. 编辑
  16. </el-button>
  17. <el-button type="primary" :disabled="detailData.event_status != '0'" @click="handleStartEvent">
  18. <i class="command-icon" />
  19. 开始指挥
  20. </el-button>
  21. <el-button v-if="['0', '1'].includes(detailData.event_status)" type="danger" plain @click="handleCloseEvent">
  22. <i class="close-icon" />
  23. 关闭事件
  24. </el-button>
  25. <el-button type="danger" plain icon="Minus" :disabled="detailData.del_flag != '0'" @click="handleDeleteEvent">删除事件</el-button>
  26. </div>
  27. </div>
  28. <div class="common-info-box">
  29. <div class="common-info-header">
  30. <i class="line-icon" />
  31. <div class="common-info-title">基础信息</div>
  32. </div>
  33. <div class="common-info-content">
  34. <div class="common-info-item">事件编号:{{ detailData.event_id }}</div>
  35. <div class="common-info-item">事件类型:<dict-tag :options="mm_event_type" :value="detailData.event_type" /></div>
  36. <div class="common-info-item">
  37. 事件等级:
  38. <dict-tag :options="mm_event_level" :value="detailData.event_level" />
  39. <el-icon style="margin-left: 20px; cursor: pointer" @click="handleEventLevelOpen"><Fold /></el-icon>
  40. </div>
  41. <div class="common-info-item">事件状态:<dict-tag :options="mm_event_state" :value="detailData.event_status" /></div>
  42. <div class="common-info-item">事发地点:{{ detailData.address }}</div>
  43. <div class="common-info-item">事发时间:{{ detailData.event_time }}</div>
  44. <div class="common-info-item">上报时间:{{ detailData.report_time }}</div>
  45. <div class="common-info-item">
  46. 伤亡情况:
  47. <div v-if="detailData.casualties == '0'" class="flex">
  48. <span>未上报</span>
  49. <span class="link" style="margin-left: 20px" @click="uploadeCasualties">去上报</span>
  50. </div>
  51. <div v-if="detailData.casualties == '1'" class="flex">
  52. <span>已上报</span>
  53. </div>
  54. </div>
  55. <div class="common-info-item">登记人:{{ detailData.reported_by }}</div>
  56. <div class="common-info-item">登记时间:{{ detailData.report_time }}</div>
  57. <div class="common-info-item">联系方式:{{ detailData.contact }}</div>
  58. <div class="common-info-item">事件来源:{{ detailData.event_source }}</div>
  59. </div>
  60. </div>
  61. <div class="common-info-box">
  62. <div class="common-info-header">
  63. <i class="line-icon" />
  64. <div class="common-info-title">事件概要</div>
  65. </div>
  66. <div v-if="!!detailData.event_description" class="common-info-content">{{ detailData.event_description }}</div>
  67. </div>
  68. <div class="common-info-box">
  69. <div class="common-info-header">
  70. <i class="line-icon" />
  71. <div class="common-info-title">事件跟踪</div>
  72. </div>
  73. <div class="common-info-content">
  74. <Step :step-data="eventTrackState" />
  75. </div>
  76. </div>
  77. <div class="common-info-box">
  78. <div class="common-info-header">
  79. <i class="line-icon" />
  80. <div class="common-info-title">指挥记录</div>
  81. </div>
  82. <div class="common-info-content">
  83. <div class="list">
  84. <div class="list-item">
  85. <i class="img"></i>
  86. <div class="item-title">大屏指挥记录</div>
  87. </div>
  88. <div class="list-item">
  89. <i class="img"></i>
  90. <div class="item-title">中屏指挥记录</div>
  91. </div>
  92. </div>
  93. </div>
  94. </div>
  95. <div class="common-info-box">
  96. <div class="common-info-header">
  97. <i class="line-icon" />
  98. <div class="common-info-title">匹配预案</div>
  99. </div>
  100. <div v-if="!!detailData.plan_name" class="common-info-content">
  101. <div class="list">
  102. <div class="list-item">
  103. <i class="img"></i>
  104. <div class="item-title">{{ detailData.plan_name }}</div>
  105. </div>
  106. </div>
  107. </div>
  108. </div>
  109. <div class="common-info-box">
  110. <div class="common-info-header">
  111. <i class="line-icon" />
  112. <div class="common-info-title">事件总结报告</div>
  113. </div>
  114. <div v-if="!!summaryFiles && summaryFiles.length > 0" class="common-info-content">
  115. <div class="list2">
  116. <div v-for="(item, index) in summaryFiles" :key="index" class="list-item" @click="downloadSummaryFile(item)">
  117. <div class="link">{{ item.file_name }}</div>
  118. <el-icon class="icon"><Download /></el-icon>
  119. </div>
  120. </div>
  121. </div>
  122. </div>
  123. <el-dialog v-model="eventLevelState.show" title="事件等级" width="500" :before-close="handleEventLevelClose">
  124. <el-timeline>
  125. <el-timeline-item
  126. v-for="(item, index) in eventLevelState.data"
  127. :key="index"
  128. :timestamp="item.timestamp + '&nbsp;&nbsp;&nbsp;&nbsp;' + item.name"
  129. placement="top"
  130. >
  131. <div class="dict-item">
  132. <dict-tag :options="mm_event_level" :value="item.level" />
  133. </div>
  134. </el-timeline-item>
  135. </el-timeline>
  136. </el-dialog>
  137. <CloseEventDialog v-model="closeDialogState.show" :data="closeDialogState.form" :event-id="eventId" @update:model-value="fetchEventDetail" />
  138. <StartEventDialog v-model="startDialogState.show" :data="startDialogState.form" :event-id="eventId" @update:model-value="fetchEventDetail" />
  139. <EventEditDialog
  140. v-model="eventEditDialogState.show"
  141. :title="eventEditDialogState.title"
  142. :event-id="eventId"
  143. @update:model-value="fetchEventDetail"
  144. />
  145. <EditCasualtiesDialog
  146. v-model="editCasualtiesDialogState.show"
  147. :data="editCasualtiesDialogState.form"
  148. :event-id="eventId"
  149. @update:model-value="fetchEventDetail"
  150. />
  151. </div>
  152. </template>
  153. <script lang="ts" setup>
  154. import { getEventDetail, deleteEvent } from '@/api/duty/eventing';
  155. import StartEventDialog from './StartEventDialog.vue';
  156. import CloseEventDialog from './CloseEventDialog.vue';
  157. import EventEditDialog from './EventEditDialog.vue';
  158. import EditCasualtiesDialog from './EditCasualtiesDialog.vue';
  159. import { download2 } from '@/utils/request';
  160. const props = defineProps({
  161. eventId: String
  162. });
  163. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  164. const { mm_event_type, mm_event_level, mm_event_state, region } = toRefs<any>(
  165. proxy?.useDict('mm_event_type', 'mm_event_level', 'mm_event_state', 'region')
  166. );
  167. const emits = defineEmits(['close']);
  168. // 事件等级数据
  169. let eventLevelState = reactive({
  170. show: false,
  171. data: []
  172. });
  173. const handleEventLevelOpen = () => {
  174. eventLevelState.show = true;
  175. };
  176. const handleEventLevelClose = () => {
  177. eventLevelState.show = false;
  178. };
  179. // 下载总结报告
  180. let summaryFiles = ref([]);
  181. const baseUrl = import.meta.env.VITE_APP_BASE_API;
  182. // 下载方法
  183. const downloadSummaryFile = (file: any) => {
  184. download2(baseUrl + '/file/download/' + file.url, file.file_name);
  185. };
  186. // 事件跟踪数据
  187. let eventTrackState = reactive({
  188. active: 0,
  189. items: [
  190. {
  191. title: '事件登记',
  192. description: ''
  193. },
  194. {
  195. title: '进入指挥',
  196. description: ''
  197. },
  198. {
  199. title: '结束指挥',
  200. description: ''
  201. },
  202. {
  203. title: '关闭事件',
  204. description: ''
  205. }
  206. ]
  207. });
  208. // 返回上一级
  209. const handleBack = () => {
  210. emits('close');
  211. };
  212. const detailData = ref({
  213. event_id: '',
  214. event_title: '',
  215. event_type: '',
  216. event_level: '',
  217. event_status: '',
  218. event_time: '',
  219. address: '',
  220. report_time: '',
  221. event_source: '',
  222. reported_by: '',
  223. event_description: '',
  224. contact: '',
  225. plan_name: '',
  226. casualties: '',
  227. deaths: '',
  228. injuries: '',
  229. missing: '',
  230. del_flag: ''
  231. });
  232. let startDialogState = reactive({
  233. show: false,
  234. form: {
  235. eventId: '',
  236. event_level: '',
  237. deaths: '',
  238. injuries: '',
  239. missing: ''
  240. }
  241. });
  242. const closeDialogState = reactive({
  243. show: false,
  244. form: {
  245. eventId: '',
  246. deaths: '',
  247. injuries: '',
  248. missing: '',
  249. fileNames: []
  250. }
  251. });
  252. const editCasualtiesDialogState = reactive({
  253. show: false,
  254. form: {
  255. eventId: '',
  256. deaths: '',
  257. injuries: '',
  258. missing: ''
  259. }
  260. });
  261. // 开始指挥(事件)
  262. const handleStartEvent = () => {
  263. startDialogState.form.eventId = props.eventId;
  264. startDialogState.form.deaths = detailData.value.deaths;
  265. startDialogState.form.injuries = detailData.value.injuries;
  266. startDialogState.form.missing = detailData.value.missing;
  267. startDialogState.form.event_level = detailData.value.event_level;
  268. startDialogState.show = true;
  269. };
  270. // 关闭事件
  271. const handleCloseEvent = () => {
  272. closeDialogState.form.eventId = props.eventId;
  273. closeDialogState.form.deaths = detailData.value.deaths;
  274. closeDialogState.form.injuries = detailData.value.injuries;
  275. closeDialogState.form.missing = detailData.value.missing;
  276. closeDialogState.form.fileNames = [];
  277. closeDialogState.show = true;
  278. };
  279. // 删除事件
  280. const handleDeleteEvent = () => {
  281. ElMessageBox.confirm('确认删除事件吗?', '提示', {
  282. confirmButtonText: '确定',
  283. cancelButtonText: '取消',
  284. type: 'info'
  285. }).then(() => {
  286. deleteEvent({ eventId: props.eventId }).then((res) => {
  287. proxy?.$modal.msgSuccess(res.msg);
  288. fetchEventDetail();
  289. });
  290. });
  291. };
  292. // 上报伤亡情况
  293. const uploadeCasualties = () => {
  294. editCasualtiesDialogState.form.eventId = props.eventId;
  295. editCasualtiesDialogState.form.deaths = '';
  296. editCasualtiesDialogState.form.injuries = '';
  297. editCasualtiesDialogState.form.missing = '';
  298. editCasualtiesDialogState.show = true;
  299. };
  300. const eventEditDialogState = reactive({
  301. show: false,
  302. title: ''
  303. });
  304. const fetchEventDetail = () => {
  305. console.log('fetchEventDetail');
  306. closeDialogState.show = false;
  307. startDialogState.show = false;
  308. eventEditDialogState.show = false;
  309. editCasualtiesDialogState.show = false;
  310. getEventDetail({ event_id: props.eventId }).then((res) => {
  311. detailData.value = res.data;
  312. eventTrackState = res.data.event_status_tracks;
  313. eventLevelState.data = res.data.event_level_tracks;
  314. summaryFiles.value = res.data.summary_file;
  315. });
  316. };
  317. const handleUpdate = () => {
  318. console.log('handleUpdate');
  319. eventEditDialogState.title = '修改事件';
  320. eventEditDialogState.show = true;
  321. };
  322. onMounted(() => {
  323. fetchEventDetail();
  324. });
  325. </script>
  326. <style lang="scss" scoped>
  327. .list {
  328. display: flex;
  329. .list-item {
  330. display: flex;
  331. flex-direction: column;
  332. align-content: center;
  333. justify-content: center;
  334. margin-right: 40px;
  335. cursor: pointer;
  336. position: relative;
  337. .img {
  338. width: 238px;
  339. height: 142px;
  340. background: url('@/assets/images/cardBg.png') no-repeat;
  341. background-size: 100% 100%;
  342. cursor: pointer;
  343. }
  344. .item-title {
  345. position: absolute;
  346. left: 50%;
  347. bottom: 16px;
  348. transform: translateX(-50%);
  349. color: #2c81ff;
  350. }
  351. &:last-child {
  352. margin-right: 0;
  353. }
  354. }
  355. .list-item2 {
  356. margin-right: 40px;
  357. cursor: pointer;
  358. &:last-child {
  359. margin-right: 0;
  360. }
  361. }
  362. }
  363. .list2 {
  364. .list-item {
  365. display: flex;
  366. align-items: center;
  367. color: #2c81ff;
  368. cursor: pointer;
  369. .icon {
  370. margin-left: 10px;
  371. cursor: pointer;
  372. }
  373. }
  374. }
  375. .dict-item {
  376. :deep(.warning2) {
  377. background-color: #fdfbe2;
  378. border: 1px solid #fad400;
  379. color: #fad400;
  380. padding: 5px 12px;
  381. border-radius: 5px;
  382. }
  383. :deep(.primary2) {
  384. background-color: #ecf5ff;
  385. border: 1px solid #409eff;
  386. color: #409eff;
  387. padding: 5px 12px;
  388. border-radius: 5px;
  389. }
  390. :deep(.danger2) {
  391. background-color: #fef0f0;
  392. border: 1px solid #f56c6c;
  393. color: #f56c6c;
  394. padding: 5px 12px;
  395. border-radius: 5px;
  396. }
  397. :deep(.warning3) {
  398. background-color: #fdf6ec;
  399. border: 1px solid #e6a23c;
  400. color: #e6a23c;
  401. padding: 5px 12px;
  402. border-radius: 5px;
  403. }
  404. }
  405. </style>