| | |
| | | # @Author : yuan |
| | | # @Date : 2026-01-07 14:58:30 |
| | | # @LastEditors : yuan |
| | | # @LastEditTime : 2026-01-13 16:28:33 |
| | | # @LastEditTime : 2026-01-15 10:25:10 |
| | | # @FilePath : \applications\drone-command\env\.env.development |
| | | # @Description : |
| | | # Copyright 2026 OBKoro1, All Rights Reserved. |
| | |
| | | |
| | | #开发环境代理地址(推荐本地新建文件 .env.development.local 来进行覆盖) |
| | | # VITE_APP_URL = https://wrj.shuixiongit.com/api |
| | | VITE_APP_URL= http://192.168.1.168 |
| | | VITE_APP_URL= http://192.168.1.204 |
| | | |
| | | #新大屏地址 |
| | | VITE_APP_DASHBOARD_URL = 'https://wrj.shuixiongit.com/command-center-dashboard/' |
| | |
| | | <div class="top-bar__right"> |
| | | <div class="top-user"> |
| | | <div class="icon-box"> |
| | | <img class="gateway" @click="jumpMH" src="@/assets/images/mh.png" alt="进入门户" title="进入门户"> |
| | | <img class="gateway" @click="jumpMH" src="@/assets/images/mh.png" alt="进入门户" title="进入门户"> |
| | | </div> |
| | | |
| | | <el-dropdown> |
| | | <span class="el-dropdown-link"> |
| | | <img class="top-bar__img" :src="userInfo.avatar" alt="" /> |
| | | <!-- <img v-if="userInfo.avatar" class="top-bar__img top-bar__user__img" :src="userInfo.avatar" alt="" /> --> |
| | | <img class="top-bar__img" :src="defaultAva" alt="" /> |
| | | </span> |
| | | |
| | | <template #dropdown> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import defaultAva from '@/assets/images/defaultava.png' |
| | | |
| | | import logo from '@/assets/images/topContainer/logo.png' |
| | | |
| | | import { mapGetters } from 'vuex' |
| | |
| | | data () { |
| | | return { |
| | | logoUrl: logo, |
| | | defaultAva: defaultAva |
| | | } |
| | | }, |
| | | filters: {}, |
| | |
| | | height: 21px; |
| | | } |
| | | |
| | | .top-bar__user__img { |
| | | width: 24px; |
| | | height: 24px; |
| | | } |
| | | |
| | | .el-dropdown-link { |
| | | cursor: pointer; |
| | | color: #606266; |
| | |
| | | const systemupdateFilePath = ref(null); |
| | | const rumenPath = ref(null); |
| | | const fileData = ref([]); |
| | | const loading = ref(false); |
| | | const loading = ref(true); |
| | | const getlistDataAPI = async () => { |
| | | loading.value = true; |
| | | try { |
| | |
| | | import { setStore, getStore } from '@/utils/store'; |
| | | import { validatenull } from '@/utils/validate'; |
| | | import { deepClone } from '@/utils/util'; |
| | | import defaultAva from '@/assets/images/defaultava.png' |
| | | import { |
| | | loginByUsername, |
| | | loginBySocial, |
| | |
| | | if (validatenull(userInfo.user_id) && validatenull(userInfo.account)) { |
| | | state.userInfo = { user_name: 'unauth', role_name: 'unauth' }; |
| | | } else { |
| | | if (validatenull(userInfo.avatar)) { |
| | | userInfo.avatar = defaultAva; |
| | | } |
| | | state.userInfo = userInfo; |
| | | } |
| | | setStore({ name: 'userInfo', content: state.userInfo }); |
| | |
| | | |
| | | .ztzf-data-cockpit-date-picker-popper { |
| | | background: #161B2C !important; |
| | | border: 1px solid !important; |
| | | border: none !important; |
| | | border-radius: 0px 0px 8px 8px; |
| | | border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important; |
| | | |
| | | .el-date-picker__prev-btn, |
| | | .el-date-picker__next-btn { |
| | |
| | | .el-picker-panel__body { |
| | | background: #161B2C !important; |
| | | color: #fff !important; |
| | | |
| | | .el-date-range-picker__time-header { |
| | | .el-input__wrapper { |
| | | box-shadow: none; |
| | | background: #2E2E48 !important; |
| | | } |
| | | } |
| | | |
| | | .el-date-picker__time-header { |
| | | border: none; |
| | |
| | | } |
| | | |
| | | .el-time-panel__footer { |
| | | background: #012350 !important; |
| | | background: #161B2C !important; |
| | | border-top: 1px solid rgba(71, 157, 255, 0.3) !important; |
| | | |
| | | .el-button { |
| | |
| | | td.start-date span, |
| | | td.start-date span, |
| | | td.end-date span { |
| | | background-color: #012350 !important; |
| | | background-color: #161B2C !important; |
| | | } |
| | | |
| | | td.in-range div, |
| | |
| | | } |
| | | |
| | | .el-picker-panel__sidebar { |
| | | background: #012350; |
| | | background: #161B2C; |
| | | color: #fff; |
| | | |
| | | .el-picker-panel__shortcut { |
| | |
| | | |
| | | .el-picker-panel__body { |
| | | .el-input.is-disabled .el-input__wrapper { |
| | | background: #012350; |
| | | background: #161B2C; |
| | | box-shadow: 0 0 0 0.1rem#409eff; |
| | | color: #fff; |
| | | |
| | |
| | | |
| | | .el-button.is-disabled, |
| | | .el-button.is-disabled:hover { |
| | | background: #012350; |
| | | background: #161B2C; |
| | | } |
| | | |
| | | .el-input__wrapper { |
| | | background: #012350; |
| | | background: #161B2C; |
| | | box-shadow: 0 0 0 0.1rem#409eff; |
| | | color: #fff; |
| | | |
| | |
| | | } |
| | | |
| | | .el-picker-panel__footer { |
| | | background: #012350; |
| | | background: #161B2C; |
| | | color: #fff; |
| | | border-top: none; |
| | | |
| | | .el-button--small { |
| | | box-shadow: 0 0 0 0.1rem#409eff; |
| | | background-color: #012350; |
| | | background-color: #161B2C; |
| | | color: #fff; |
| | | border: none; |
| | | |
| | | &:hover { |
| | | background-color: #012350; |
| | | background-color: #161B2C; |
| | | color: #fff; |
| | | border-color: #409eff; |
| | | } |
| | |
| | | } |
| | | |
| | | .el-select__wrapper { |
| | | padding: 0 8px; |
| | | background: #2E2E48; |
| | | box-shadow: none !important; |
| | | border: none; |
| | |
| | | } |
| | | |
| | | .el-select .el-input__wrapper { |
| | | background-color: #012350 !important; |
| | | background-color: #161B2C !important; |
| | | } |
| | | |
| | | .el-input__wrapper { |
| | | --el-input-text-color: #012350 !important; |
| | | --el-input-text-color: #161B2C !important; |
| | | } |
| | | } |
| | | |
| | |
| | | .el-button { |
| | | min-width: 88px; |
| | | } |
| | | |
| | | .el-button.is-disabled, .el-button.is-disabled:hover { |
| | | background: #1A2652; |
| | | border: none; |
| | | } |
| | | } |
| | | |
| | | .ztzf-table-container { |
| | |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .ztzf-data-cockpit-table { |
| | | height: 0; |
| | | flex: 1; |
| | | background: transparent !important; |
| | | |
| | | .el-table--border .el-table__inner-wrapper:after, |
| | | .el-table--border:after, |
| | | .el-table--border:before, |
| | | .el-table__inner-wrapper:before { |
| | | height: 0; |
| | | } |
| | | |
| | | tr { |
| | | background: transparent !important; |
| | | } |
| | | |
| | | th.el-table__cell { |
| | | height: 40px; |
| | | border-bottom: 1px solid #323241; |
| | | background: transparent !important; |
| | | |
| | | .cell { |
| | | padding: 0; |
| | | padding-left: 16px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #FFFFFF; |
| | | line-height: 22px; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | } |
| | | |
| | | td.el-table__cell { |
| | | padding: 9px 0; |
| | | height: 56px; |
| | | border-bottom: 1px solid #323241; |
| | | background: transparent !important; |
| | | |
| | | .cell { |
| | | padding: 0; |
| | | padding-left: 16px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #D2D2E7; |
| | | line-height: 18px; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | } |
| | | |
| | | td.operation-btns .cell { |
| | | display: flex; |
| | | flex-wrap: nowrap; |
| | | gap: 12px; |
| | | /* 按钮间距(推荐) */ |
| | | white-space: nowrap; |
| | | /* 双保险 */ |
| | | |
| | | a { |
| | | min-width: 28px; |
| | | color: #6A89FF; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .ztzf-table-content-bg { |
| | | background: #1A1A2A; |
| | | } |
| | | } |
| | | |
| | | .ztzf-data-cockpit-table { |
| | | height: 0; |
| | | flex: 1; |
| | | background: transparent !important; |
| | | |
| | | .el-table--border .el-table__inner-wrapper:after, |
| | | .el-table--border:after, |
| | | .el-table--border:before, |
| | | .el-table__inner-wrapper:before { |
| | | height: 0; |
| | | } |
| | | |
| | | tr { |
| | | background: transparent !important; |
| | | } |
| | | |
| | | th.el-table__cell { |
| | | height: 40px; |
| | | border-bottom: 1px solid #323241; |
| | | background: transparent !important; |
| | | |
| | | .cell { |
| | | padding: 0; |
| | | padding-left: 16px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #FFFFFF; |
| | | line-height: 22px; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | } |
| | | |
| | | td.el-table__cell { |
| | | padding: 9px 0; |
| | | height: 56px; |
| | | border-bottom: 1px solid #323241; |
| | | background: transparent !important; |
| | | |
| | | .cell { |
| | | padding: 0; |
| | | padding-left: 16px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #D2D2E7; |
| | | line-height: 18px; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | } |
| | | |
| | | td.operation-btns .cell { |
| | | display: flex; |
| | | flex-wrap: nowrap; |
| | | gap: 12px; |
| | | /* 按钮间距(推荐) */ |
| | | white-space: nowrap; |
| | | /* 双保险 */ |
| | | |
| | | a { |
| | | min-width: 28px; |
| | | color: #6A89FF; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | .ztzf-page-view-dialog { |
| | | padding: 30px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 770px; |
| | |
| | | } |
| | | |
| | | .dialog-form { |
| | | |
| | | .el-form-item { |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | .el-form-item__content { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | |
| | | .el-input { |
| | | width: 0; |
| | | flex: 1; |
| | |
| | | background: #2E2E48 !important; |
| | | border: none; |
| | | box-shadow: none; |
| | | } |
| | | |
| | | .ztzf-data-cockpit-date-picker { |
| | | background: #2E2E48; |
| | | } |
| | | |
| | | .ztzf-data-cockpit-date-picker-popper { |
| | | background: #2E2E48 !important; |
| | | |
| | | .el-picker-panel { |
| | | .el-picker-panel__body-wrapper { |
| | | .el-picker-panel__body { |
| | | background: #2E2E48 !important; |
| | | |
| | | .el-date-picker__time-header { |
| | | |
| | | .el-date-picker__editor-wrap { |
| | | .el-time-panel { |
| | | background: #2E2E48 !important; |
| | | |
| | | // 将 time-picker-popper 的样式移到这里 |
| | | .el-time-panel__header { |
| | | background: #2E2E48 !important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-popper__arrow { |
| | | &::before { |
| | | background: #2E2E48 !important; |
| | | border: 1px solid #2E2E48 !important; |
| | | box-sizing: border-box; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | border-color: #2B2B4C !important; |
| | | color: #FFFFFF !important; |
| | | } |
| | | |
| | | .ztzf-page-map-view-dialog { |
| | | padding: 30px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 80%; |
| | | height: 812px; |
| | | background: #1A1A2A; |
| | | border-radius: 6px 6px 6px 6px; |
| | | border: 1px solid #2E2E46; |
| | | |
| | | .el-dialog__header, |
| | | .el-dialog__footer { |
| | | margin: 0; |
| | | padding: 0; |
| | | } |
| | | |
| | | .el-dialog__footer { |
| | | .el-button { |
| | | margin-top: 30px; |
| | | } |
| | | } |
| | | |
| | | .el-dialog__body { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 0; |
| | | flex: 1; |
| | | |
| | | .dialog-container { |
| | | display: flex; |
| | | height: 0; |
| | | flex: 1; |
| | | |
| | | .left-container { |
| | | width: 0; |
| | | flex: 1; |
| | | height: 100%; |
| | | |
| | | .leftMap { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .right-container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 344px; |
| | | height: 100%; |
| | | |
| | | .header { |
| | | padding: 0 16px; |
| | | padding-bottom: 16px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 18px; |
| | | color: #FFFFFF; |
| | | text-align: left; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | |
| | | .dialog-container { |
| | | padding: 0 16px; |
| | | height: 0; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .detail-title { |
| | | margin-bottom: 30px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 18px; |
| | | color: #FFFFFF; |
| | | text-align: left; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | |
| | | .el-row { |
| | | .el-col { |
| | | margin-bottom: 20px; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .label { |
| | | width: 112px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #D4D5D7; |
| | | line-height: 22px; |
| | | text-align: right; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | |
| | | .val { |
| | | width: 0; |
| | | flex: 1; |
| | | margin-left: 12px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #9E9EBA; |
| | | text-align: left; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | .ztzf-table-container { |
| | | height: 360px; |
| | | |
| | | .ztzf-table-pagination { |
| | | justify-content: center; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .dialog-form { |
| | | padding-left: 16px; |
| | | height: 0; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .el-form-item { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .el-form-item__label { |
| | | display: flex; |
| | | align-items: center; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #D4D5D7; |
| | | line-height: 22px; |
| | | text-align: right; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | } |
| | | |
| | | .el-form-item__content { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .el-input, |
| | | .el-input-number { |
| | | width: 0; |
| | | flex: 1; |
| | | } |
| | | |
| | | .el-textarea { |
| | | |
| | | .el-textarea__inner { |
| | | color: #fff; |
| | | background: #2E2E48 !important; |
| | | border: none; |
| | | box-shadow: none; |
| | | } |
| | | } |
| | | |
| | | .el-button { |
| | | color: #fff; |
| | | background: #2E2E48 !important; |
| | | border: none; |
| | | box-shadow: none; |
| | | } |
| | | |
| | | >div.val { |
| | | color: #fff; |
| | | } |
| | | |
| | | .ztzf-data-cockpit-date-picker { |
| | | background: #2E2E48; |
| | | } |
| | | |
| | | .ztzf-data-cockpit-date-picker-popper { |
| | | background: #2E2E48 !important; |
| | | |
| | | .el-picker-panel { |
| | | .el-picker-panel__body-wrapper { |
| | | .el-picker-panel__body { |
| | | background: #2E2E48 !important; |
| | | |
| | | .el-date-picker__time-header { |
| | | |
| | | .el-date-picker__editor-wrap { |
| | | .el-time-panel { |
| | | background: #2E2E48 !important; |
| | | |
| | | // 将 time-picker-popper 的样式移到这里 |
| | | .el-time-panel__header { |
| | | background: #2E2E48 !important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-popper__arrow { |
| | | &::before { |
| | | background: #2E2E48 !important; |
| | | border: 1px solid #2E2E48 !important; |
| | | box-sizing: border-box; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-input { |
| | | .el-input__wrapper { |
| | | background: #2E2E48 !important; |
| | | |
| | | .el-input__inner { |
| | | color: #ffffff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .search-table-container { |
| | | height: 0; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .search-box { |
| | | display: flex; |
| | | margin-bottom: 18px; |
| | | |
| | | .label { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | |
| | | padding-right: 12px; |
| | | width: 96px; |
| | | |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #D4D5D7; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .el-input { |
| | | width: 0; |
| | | flex: 1; |
| | | |
| | | .el-input__wrapper { |
| | | background: #2E2E48 !important; |
| | | |
| | | .el-input__inner { |
| | | color: #ffffff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-form-item { |
| | | height: 0; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .el-form-item__content { |
| | | width: 100%; |
| | | height: 0; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .el-table { |
| | | height: 0; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .footer { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .el-button { |
| | | margin-left: 16px; |
| | | width: 96px; |
| | | height: 36px; |
| | | |
| | | &:first-child { |
| | | margin-left: 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的设备ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | |
| | | <div class="ztzf-table-content ztzf-table-content-bg"> |
| | | <el-table class="ztzf-data-cockpit-table" :data="list"> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="areaName" show-overflow-tooltip width="150" label="区域名称" /> |
| | | <el-table-column prop="areaType" show-overflow-tooltip width="130" label="区域类型"> |
| | | <el-table-column prop="areaName" show-overflow-tooltip label="区域名称" /> |
| | | <el-table-column prop="areaType" show-overflow-tooltip label="区域类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.areaType, dictObj.areaType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="sceneName" show-overflow-tooltip width="150" label="关联场景" /> |
| | | <el-table-column prop="sceneType" show-overflow-tooltip width="130" label="场景类型"> |
| | | <el-table-column prop="sceneName" show-overflow-tooltip label="关联场景" /> |
| | | <el-table-column prop="sceneType" show-overflow-tooltip label="场景类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.sceneType, dictObj.sceneType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceCount" show-overflow-tooltip width="110" label="设备数量" /> |
| | | <el-table-column prop="alarmCount" show-overflow-tooltip width="110" label="告警次数" /> |
| | | <el-table-column prop="counterCount" show-overflow-tooltip width="120" label="侦测反制次数" /> |
| | | <el-table-column prop="counterSuccessCount" show-overflow-tooltip width="130" label="反制成功次数" /> |
| | | <el-table-column prop="controlEffect" show-overflow-tooltip width="110" label="管控效果" /> |
| | | <el-table-column prop="deviceCount" show-overflow-tooltip label="设备数量" /> |
| | | <el-table-column prop="alarmCount" show-overflow-tooltip label="告警次数" /> |
| | | <el-table-column prop="counterCount" show-overflow-tooltip label="侦测反制次数" /> |
| | | <el-table-column prop="counterSuccessCount" show-overflow-tooltip label="反制成功次数" /> |
| | | <el-table-column prop="controlEffect" show-overflow-tooltip label="管控效果" /> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm(row)">查看</el-link> |
| | |
| | | |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="titleEnum[dialogMode]" :close-on-click-modal="false" width="80%"> |
| | | <div class="bodyBox"> |
| | | <div class="leftMap ztzf-cesium" id="mapContainer"></div> |
| | | <div class="rightInfo"> |
| | | <div v-if="readonly"> |
| | | <div>防区名称: {{ formData.zoneName }}</div> |
| | | <div>防区面积: {{ formatZoneArea(formData.zoneArea) }}</div> |
| | | <el-table :data="sceneList" row-key="id"> |
| | | <el-table-column prop="sceneName" label="场景名称" /> |
| | | <el-table-column prop="sceneType" label="场景类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.sceneType, dictObj.sceneType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-dialog class="ztzf-page-map-view-dialog" v-model="visible" :show-close="false" :close-on-click-modal="false"> |
| | | <div class="dialog-container"> |
| | | <div class="left-container"> |
| | | <div class="leftMap ztzf-cesium" id="mapContainer"></div> |
| | | </div> |
| | | |
| | | <div class="right-container"> |
| | | <div class="header"> |
| | | {{ titleEnum[dialogMode] }} |
| | | </div> |
| | | <el-form v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly" label-width="100px"> |
| | | |
| | | <div class="dialog-container" v-if="readonly"> |
| | | <div class="detail-title">防区详情</div> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="防区名称" prop="zoneName"> |
| | | <el-input v-model="formData.zoneName" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <div class="label">防区名称</div> |
| | | <div class="val">{{ formData.zoneName }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="防区面积" prop="zoneArea">{{ formatZoneArea(formData.zoneArea) }}</el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div> |
| | | <div> |
| | | 关联场景 |
| | | <el-input v-model="searchName" placeholder="请输入" clearable></el-input> |
| | | </div> |
| | | <el-form-item label="关联场景" prop="defenseSceneIds" label-width="0"> |
| | | <el-table |
| | | ref="sceneTableRef" |
| | | :data="sceneList.filter(item => item.sceneName.includes(searchName))" |
| | | row-key="id" |
| | | @selection-change="handleSceneSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55" :reserve-selection="true" /> |
| | | <el-table-column prop="sceneName" label="场景名称" /> |
| | | <el-table-column prop="sceneType" label="场景类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.sceneType, dictObj.sceneType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form-item> |
| | | </div> |
| | | <div class="label">防区面积</div> |
| | | <div class="val">{{ formatZoneArea(formData.zoneArea) }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <div class="detail-title">关联场景</div> |
| | | <div class="ztzf-table-container"> |
| | | <div class="ztzf-table-content"> |
| | | <el-table class="ztzf-data-cockpit-table" :data="sceneList" row-key="id"> |
| | | <el-table-column prop="sceneName" label="场景名称" /> |
| | | <el-table-column prop="sceneType" label="场景类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.sceneType, dictObj.sceneType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-form class="dialog-form" v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly" |
| | | label-width="96px"> |
| | | <el-form-item label="防区名称" prop="zoneName"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.zoneName" maxlength="50" |
| | | placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="防区面积" prop="zoneArea"> |
| | | <div class="val">{{ formatZoneArea(formData.zoneArea) }}</div> |
| | | </el-form-item> |
| | | |
| | | <div class="search-table-container"> |
| | | <div class="search-box"> |
| | | <div class="label"> |
| | | 关联场景 |
| | | </div> |
| | | |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="searchName" placeholder="请输入" |
| | | clearable></el-input> |
| | | </div> |
| | | |
| | | <el-form-item prop="defenseSceneIds" label-width="0"> |
| | | <el-table class="ztzf-data-cockpit-table" ref="sceneTableRef" |
| | | :data="sceneList.filter(item => item.sceneName.includes(searchName))" row-key="id" |
| | | @selection-change="handleSceneSelectionChange"> |
| | | <el-table-column type="selection" width="55" :reserve-selection="true" /> |
| | | <el-table-column prop="sceneName" label="场景名称" /> |
| | | <el-table-column prop="sceneType" label="场景类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.sceneType, dictObj.sceneType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form-item> |
| | | </div> |
| | | </el-form> |
| | | |
| | | <div class="footer"> |
| | | <el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting" |
| | | :disabled="submitting" @click="handleSubmit"> |
| | | 确定 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit"> |
| | | 确定 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | function handleCancel () { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | async function handleSubmit () { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | if (!pointList.length) { |
| | |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | async function loadDetail () { |
| | | if (!formData.value.id) return |
| | | const res = await fwDefenseZoneDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? initForm() |
| | | } |
| | | |
| | | // 获取场景列表 |
| | | async function getSceneList() { |
| | | async function getSceneList () { |
| | | const res = await fwDefenseSceneListApi({ filterSelected: 1, zoneId: formData.value.id }) |
| | | sceneList.value = res?.data?.data ?? [] |
| | | if (readonly.value) { |
| | |
| | | } |
| | | |
| | | // 获取场景ID列表 |
| | | function getSceneIdList() { |
| | | function getSceneIdList () { |
| | | if (!formData.value.defenseSceneIds) return [] |
| | | return formData.value.defenseSceneIds.split(',') |
| | | } |
| | | |
| | | // 关联场景变更 |
| | | function handleSceneSelectionChange(rows) { |
| | | function handleSceneSelectionChange (rows) { |
| | | selectedSceneRows.value = rows |
| | | formData.value.defenseSceneIds = rows.map(item => item.id).join(',') |
| | | } |
| | | |
| | | // 同步关联场景 |
| | | function syncSceneSelection() { |
| | | function syncSceneSelection () { |
| | | if (!sceneTableRef.value) return |
| | | sceneTableRef.value.clearSelection() |
| | | const ids = getSceneIdList() |
| | |
| | | } |
| | | |
| | | // 格式化防区面积 |
| | | function formatZoneArea(value) { |
| | | function formatZoneArea (value) { |
| | | if (value == null || value === '') return '' |
| | | return `${value}k㎡` |
| | | } |
| | | |
| | | // 初始化地图实例 |
| | | function initMap() { |
| | | function initMap () { |
| | | const publicCesiumInstance = new PublicCesium({ |
| | | dom: 'mapContainer', |
| | | flatMode: false, |
| | |
| | | } |
| | | |
| | | // 新增模式绘制 |
| | | function addPolygon() { |
| | | function addPolygon () { |
| | | drawPolygonExample = new DrawPolygon(viewer) |
| | | drawPolygonExample.initHandler(viewer) |
| | | drawPolygonExample.subscribe('getPolygonPositions', drawFinished) |
| | | } |
| | | |
| | | // 编辑面 |
| | | function editPolygon() { |
| | | function editPolygon () { |
| | | if (!formData.value?.geom) return |
| | | pointList = geomAnalysis(formData.value.geom) |
| | | drawPolygonExample?.destroy() |
| | |
| | | } |
| | | |
| | | // 查看面 |
| | | function viewPolygon() { |
| | | function viewPolygon () { |
| | | if (!formData.value?.geom) return |
| | | pointList = geomAnalysis(formData.value.geom) |
| | | const result = pointList.map(item => [item.longitude, item.latitude]).flat() |
| | |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | async function open ({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | selectedSceneRows.value = [] |
| | |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .bodyBox { |
| | | display: flex; |
| | | height: 600px; |
| | | .leftMap { |
| | | width: 70%; |
| | | height: 100%; |
| | | } |
| | | .rightInfo { |
| | | width: 30%; |
| | | height: 100%; |
| | | overflow: auto; |
| | | } |
| | | } |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| | |
| | | |
| | | <div class="ztzf-table-toolbar"> |
| | | <el-button :icon="Plus" color="#284FE3" type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | <el-button :icon="Delete" color="#1A2652" type="primary" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | |
| | | <el-table class="ztzf-data-cockpit-table" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="zoneName" show-overflow-tooltip width="150" label="防区名称" /> |
| | | <el-table-column prop="zoneArea" show-overflow-tooltip width="130" label="防区面积(k㎡)" /> |
| | | <el-table-column prop="sceneCount" show-overflow-tooltip width="120" label="场景数量" /> |
| | | <el-table-column prop="areaCount" show-overflow-tooltip width="120" label="区域数量" /> |
| | | <el-table-column prop="deviceCount" show-overflow-tooltip width="120" label="设备数量" /> |
| | | <el-table-column prop="zoneName" show-overflow-tooltip label="防区名称" /> |
| | | <el-table-column prop="zoneArea" show-overflow-tooltip label="防区面积(k㎡)" /> |
| | | <el-table-column prop="sceneCount" show-overflow-tooltip label="场景数量" /> |
| | | <el-table-column prop="areaCount" show-overflow-tooltip label="区域数量" /> |
| | | <el-table-column prop="deviceCount" show-overflow-tooltip label="设备数量" /> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('view', row)">查看</el-link> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search, RefreshRight, Plus } from '@element-plus/icons-vue' |
| | | import { Search, RefreshRight, Plus, Delete } from '@element-plus/icons-vue' |
| | | import { nextTick, onMounted, provide, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { fwDefenseZonePageApi, fwDefenseZoneRemoveApi } from './defenseZoneApi' |
| | |
| | | |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | |
| | | <template> |
| | | <el-dialog class="ztzf-page-view-dialog" v-model="visible" :title="titleEnum[dialogMode]" |
| | | :close-on-click-modal="false" width="80%"> |
| | | <div class="bodyBox"> |
| | | <div class="leftMap ztzf-cesium" id="mapContainer"></div> |
| | | <div class="rightInfo"> |
| | | <div class="detail-container" v-if="readonly"> |
| | | <el-dialog class="ztzf-page-map-view-dialog" v-model="visible" :show-close="false" |
| | | :close-on-click-modal="false"> |
| | | <div class="dialog-container"> |
| | | <div class="left-container"> |
| | | <div class="leftMap ztzf-cesium" id="mapContainer"></div> |
| | | </div> |
| | | |
| | | <div class="right-container"> |
| | | <div class="header"> |
| | | {{ titleEnum[dialogMode] }} |
| | | </div> |
| | | |
| | | <div class="dialog-container" v-if="readonly"> |
| | | <div class="detail-title">区域详情</div> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-form class="dialog-form" v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly" |
| | | label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="区域名称" prop="areaName"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.areaName" |
| | | maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="区域位置" prop="longitude"> |
| | | <div>{{ formatLocation(formData) }}</div> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="区域面积" prop="areaSize">{{ formData.areaSize || '-' }}k㎡</el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="区域类型" prop="areaType"> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.areaType" placeholder="请选择" clearable> |
| | | <el-option |
| | | v-for="item in dictObj.areaType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="响应机制" prop="responseMechanism"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.responseMechanism" |
| | | maxlength="200" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="触发条件" prop="triggerCondition"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.triggerCondition" |
| | | maxlength="200" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="管控级别" prop="controlLevel"> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.controlLevel" placeholder="请选择" clearable> |
| | | <el-option |
| | | v-for="item in dictObj.controlLevel" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="可飞行时段" prop="flyDateStart"> |
| | | <el-date-picker |
| | | class="ztzf-data-cockpit-date-picker" |
| | | popper-class="ztzf-data-cockpit-date-picker-popper" |
| | | v-model="flyDateRange" |
| | | type="datetimerange" |
| | | range-separator="至" |
| | | start-placeholder="开始时间" |
| | | end-placeholder="结束时间" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="关联派出所" prop="policeStationId"> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.policeStationId" placeholder="请选择" clearable> |
| | | <el-option |
| | | v-for="item in policeStationOptions" |
| | | :key="item.id" |
| | | :label="item.stationName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div> |
| | | <div> |
| | | 关联设备 |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="searchName" placeholder="请输入" |
| | | clearable></el-input> |
| | | </div> |
| | | <el-form-item prop="deviceIds" label-width="0"> |
| | | <el-table |
| | | class="ztzf-data-cockpit-table" |
| | | ref="deviceTableRef" |
| | | :data="deviceOptions.filter(item => item.deviceName.includes(searchName))" |
| | | row-key="id" |
| | | @selection-change="handleDeviceSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55" :reserve-selection="true" /> |
| | | <el-table-column prop="deviceName" label="设备名称" /> |
| | | <el-table-column prop="deviceType" label="类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceType, dictObj.deviceType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form-item> |
| | | label-width="96px"> |
| | | <el-form-item label="区域名称" prop="areaName"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.areaName" maxlength="50" |
| | | placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="区域位置" prop="longitude"> |
| | | <div class="val">{{ formatLocation(formData) }}</div> |
| | | </el-form-item> |
| | | <el-form-item label="区域面积" prop="areaSize"> |
| | | <div class="val">{{ formData.areaSize || '-' }}k㎡</div> |
| | | </el-form-item> |
| | | <el-form-item label="区域类型" prop="areaType"> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.areaType" placeholder="请选择" clearable> |
| | | <el-option v-for="item in dictObj.areaType" :key="item.dictKey" :label="item.dictValue" |
| | | :value="item.dictKey" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="响应机制" prop="responseMechanism"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.responseMechanism" |
| | | maxlength="200" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="触发条件" prop="triggerCondition"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.triggerCondition" |
| | | maxlength="200" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="管控级别" prop="controlLevel"> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.controlLevel" placeholder="请选择" clearable> |
| | | <el-option v-for="item in dictObj.controlLevel" :key="item.dictKey" :label="item.dictValue" |
| | | :value="item.dictKey" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="可飞行时段" prop="flyDateStart"> |
| | | <el-date-picker class="ztzf-data-cockpit-date-picker" |
| | | popper-class="ztzf-data-cockpit-date-picker-popper" v-model="flyDateRange" |
| | | type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" |
| | | value-format="YYYY-MM-DD HH:mm:ss" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="关联派出所" prop="policeStationId"> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.policeStationId" placeholder="请选择" clearable> |
| | | <el-option v-for="item in policeStationOptions" :key="item.id" :label="item.stationName" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <div class="search-table-container"> |
| | | <div class="search-box"> |
| | | <div class="label"> |
| | | 关联设备 |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="searchName" placeholder="请输入" |
| | | clearable></el-input> |
| | | </div> |
| | | |
| | | <el-form-item prop="deviceIds" label-width="0"> |
| | | <el-table class="ztzf-data-cockpit-table" ref="deviceTableRef" |
| | | :data="deviceOptions.filter(item => item.deviceName.includes(searchName))" row-key="id" |
| | | @selection-change="handleDeviceSelectionChange"> |
| | | <el-table-column type="selection" width="55" :reserve-selection="true" /> |
| | | <el-table-column prop="deviceName" label="设备名称" /> |
| | | <el-table-column prop="deviceType" label="类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceType, dictObj.deviceType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form-item> |
| | | </div> |
| | | </el-form> |
| | | |
| | | <div class="footer"> |
| | | <el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting" |
| | | :disabled="submitting" @click="handleSubmit"> |
| | | 确定 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting" |
| | | @click="handleSubmit"> |
| | | 确定 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const readonly = computed(() => dialogMode.value === 'view') |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '新增' }) |
| | | const titleEnum = ref({ edit: '编辑场景', view: '查看场景', add: '新增场景' }) |
| | | const flyDateRange = ref([]) // 飞行时间 |
| | | const deviceTableRef = ref(null) |
| | | const searchName = ref('') |
| | |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | function handleCancel () { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | async function handleSubmit () { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | |
| | | ) |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | async function loadDetail () { |
| | | if (!formData.value.id) return |
| | | const res = await fwAreaDivideDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? initForm() |
| | |
| | | } |
| | | |
| | | // 格式化区域位置 |
| | | function formatLocation(row) { |
| | | function formatLocation (row) { |
| | | if (row?.longitude == null || row?.latitude == null) return '' |
| | | return `${_.round(row.longitude, 6)}, ${_.round(row.latitude, 6)}` |
| | | } |
| | | |
| | | // 格式化可飞行时间段 |
| | | function formatFlyDate(row) { |
| | | function formatFlyDate (row) { |
| | | if (!row?.flyDateStart && !row?.flyDateEnd) return '' |
| | | return `${row.flyDateStart || '-'} ~ ${row.flyDateEnd || '-'}` |
| | | } |
| | | |
| | | // 初始化地图实例 |
| | | function initMap() { |
| | | function initMap () { |
| | | const publicCesiumInstance = new PublicCesium({ |
| | | dom: 'mapContainer', |
| | | flatMode: false, |
| | |
| | | } |
| | | |
| | | // 新增模式绘制 |
| | | function addPolygon() { |
| | | function addPolygon () { |
| | | drawPolygonExample = new DrawPolygon(viewer) |
| | | drawPolygonExample.initHandler(viewer) |
| | | drawPolygonExample.subscribe('getPolygonPositions', drawFinished) |
| | | } |
| | | |
| | | // 编辑面 |
| | | function editPolygon() { |
| | | function editPolygon () { |
| | | if (!formData.value?.geom) return |
| | | pointList = geomAnalysis(formData.value.geom) |
| | | drawPolygonExample?.destroy() |
| | |
| | | } |
| | | |
| | | // 查看面 |
| | | function viewPolygon() { |
| | | function viewPolygon () { |
| | | if (!formData.value?.geom) return |
| | | pointList = geomAnalysis(formData.value.geom) |
| | | const result = pointList.map(item => [item.longitude, item.latitude]).flat() |
| | |
| | | } |
| | | |
| | | // 获取派出所列表 |
| | | async function getPoliceStationList() { |
| | | async function getPoliceStationList () { |
| | | const res = await fwPoliceStationListApi() |
| | | policeStationOptions.value = res?.data?.data ?? [] |
| | | } |
| | | |
| | | // 获取设备列表 |
| | | async function getDeviceList() { |
| | | async function getDeviceList () { |
| | | if (deviceOptions.value.length) return |
| | | const res = await fwDeviceListApi({ isAreaSelect: 1, areaId: formData.value.id }) |
| | | deviceOptions.value = res?.data?.data ?? [] |
| | |
| | | } |
| | | |
| | | // 关联设备变更 |
| | | function handleDeviceSelectionChange(rows) { |
| | | function handleDeviceSelectionChange (rows) { |
| | | selectedDeviceRows.value = rows |
| | | const ids = rows.map(item => item.id) |
| | | formData.value.deviceIds = ids.join(',') |
| | | } |
| | | |
| | | // 同步选择状态 |
| | | function syncDeviceSelection() { |
| | | function syncDeviceSelection () { |
| | | if (!deviceTableRef.value) return |
| | | deviceTableRef.value.clearSelection() |
| | | const rows = [] |
| | |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | async function open ({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | selectedDeviceRows.value = [] |
| | |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .bodyBox { |
| | | display: flex; |
| | | height: 600px; |
| | | .leftMap { |
| | | width: 70%; |
| | | height: 100%; |
| | | } |
| | | .rightInfo { |
| | | width: 30%; |
| | | height: 100%; |
| | | overflow: auto; |
| | | |
| | | .ztzf-table-container, |
| | | .ztzf-table-content { |
| | | height: auto; |
| | | flex: none; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| | |
| | | |
| | | <div class="ztzf-table-toolbar"> |
| | | <el-button :icon="Plus" color="#284FE3" type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | <el-button :icon="Delete" color="#1A2652" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | |
| | | {{ getDictLabel(row.controlLevel, dictObj.controlLevel) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="policeStationName" show-overflow-tooltip width="140" label="关联派出所" /> |
| | | <el-table-column show-overflow-tooltip width="160" label="可飞行时间段"> |
| | | <el-table-column prop="policeStationName" show-overflow-tooltip label="关联派出所" /> |
| | | <el-table-column show-overflow-tooltip label="可飞行时间段"> |
| | | <template v-slot="{ row }"> |
| | | {{ formatFlyDate(row) }} |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search, RefreshRight, Plus } from '@element-plus/icons-vue' |
| | | import { Search, RefreshRight, Plus, Delete } from '@element-plus/icons-vue' |
| | | import { nextTick, onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { fwAreaDividePageApi, fwAreaDivideRemoveApi } from './partitionApi' |
| | |
| | | |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | |
| | | <el-col :span="24"> |
| | | <el-form-item label="位置" prop="longitude"> |
| | | <el-button @click="selectLocation" style="width: 100%"> |
| | | {{ formData.longitude }}, {{ formData.longitude }}, {{ formData.address }} |
| | | {{ formData.longitude }}, {{ formData.latitude }}, {{ formData.address }} |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-button> |
| | | </template> |
| | | |
| | | <el-dialog v-model="visible1" title="选择位置" destroy-on-close @closed="positionClosed"> |
| | | <div class="ztzf-cesium" id="mapContainer"></div> |
| | | <el-dialog class="ztzf-page-map-view-dialog" v-model="visible1" :show-close="false" |
| | | :close-on-click-modal="false" destroy-on-close @closed="positionClosed"> |
| | | <div class="dialog-container"> |
| | | <div class="left-container"> |
| | | <div class="leftMap ztzf-cesium" id="mapContainer"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <el-button @click="handleMapCancel">取消</el-button> |
| | | <el-button type="primary" @click="handleMapConfirm">确定</el-button> |
| | | <el-button color="#2B2B4C" @click="handleMapCancel">取消</el-button> |
| | | <el-button color="#284FE3" type="primary" @click="handleMapConfirm">确定</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </el-dialog> |
| | |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | function handleCancel () { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | async function handleSubmit () { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | async function loadDetail () { |
| | | if (!formData.value.id) return |
| | | const res = await fwPoliceStationDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? {} |
| | | } |
| | | |
| | | function LeftClickEvent(click) { |
| | | function LeftClickEvent (click) { |
| | | const pos = click.position // Cartesian2 屏幕坐标 |
| | | // 屏幕坐标 -> 椭球面坐标(不考虑地形/模型) |
| | | const cartesian3 = viewer.camera.pickEllipsoid(pos, viewer.scene.globe.ellipsoid) |
| | |
| | | } |
| | | } |
| | | |
| | | function positionClosed() { |
| | | function positionClosed () { |
| | | redPointEntity = null |
| | | } |
| | | |
| | | let viewer |
| | | let redPointEntity |
| | | async function selectLocation() { |
| | | function setMapPoint (longitude, latitude) { |
| | | if (!viewer || longitude == null || latitude == null) return |
| | | if (!redPointEntity) { |
| | | redPointEntity = viewer.entities.add({ |
| | | position: Cesium.Cartesian3.fromDegrees(longitude, latitude), |
| | | point: { |
| | | color: Cesium.Color.RED, |
| | | pixelSize: 10, |
| | | }, |
| | | label: { |
| | | text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`, |
| | | font: '14px', |
| | | fillColor: Cesium.Color.WHITE, |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.45), |
| | | backgroundPadding: new Cesium.Cartesian2(5, 5), |
| | | pixelOffset: new Cesium.Cartesian2(0, -20), |
| | | showBackground: true, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | horizontalOrigin: Cesium.HorizontalOrigin.CENTER, |
| | | verticalOrigin: Cesium.VerticalOrigin.CENTER, |
| | | outlineWidth: 1, |
| | | outlineColor: Cesium.Color.WHITE, |
| | | eyeOffset: new Cesium.Cartesian3(0, 0, -20), |
| | | }, |
| | | }) |
| | | } else { |
| | | redPointEntity.position = Cesium.Cartesian3.fromDegrees(longitude, latitude) |
| | | redPointEntity.label.text = `${longitude.toFixed(6)}, ${latitude.toFixed(6)}` |
| | | } |
| | | } |
| | | |
| | | function formatCoord (value) { |
| | | if (value == null || value === '') return '-' |
| | | return _.round(Number(value), 6) |
| | | } |
| | | |
| | | async function selectLocation () { |
| | | visible1.value = true |
| | | await nextTick() |
| | | const publicCesiumInstance = new PublicCesium({ |
| | |
| | | }) |
| | | publicCesiumInstance.addLeftClickEvent(null, LeftClickEvent) |
| | | viewer = publicCesiumInstance.getViewer() |
| | | if (formData.value.longitude != null && formData.value.latitude != null) { |
| | | tempLocation.value = { longitude: formData.value.longitude, latitude: formData.value.latitude } |
| | | setMapPoint(formData.value.longitude, formData.value.latitude) |
| | | } |
| | | } |
| | | |
| | | function handleMapCancel() { |
| | | function handleMapCancel () { |
| | | tempLocation.value = { longitude: null, latitude: null } |
| | | visible1.value = false |
| | | } |
| | | |
| | | async function getLocationName() { |
| | | async function getLocationName () { |
| | | const tk = import.meta.env.VITE_APP_TDT_TOKEN |
| | | const { latitude, longitude } = tempLocation.value |
| | | const http = axios.create({ withCredentials: false }) |
| | |
| | | formData.value.address = res.data.result.formatted_address |
| | | } |
| | | |
| | | function handleMapConfirm() { |
| | | function handleMapConfirm () { |
| | | if (tempLocation.value.longitude != null && tempLocation.value.latitude != null) { |
| | | formData.value.longitude = _.round(tempLocation.value.longitude, 6) |
| | | formData.value.latitude = _.round(tempLocation.value.latitude, 6) |
| | |
| | | visible1.value = false |
| | | } |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | async function open ({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | dialogMode.value !== 'add' && (await loadDetail()) |
| | |
| | | defineExpose({ open }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | #mapContainer { |
| | | width: 100%; |
| | | height: 500px; |
| | | } |
| | | </style> |
| | |
| | | |
| | | <div class="ztzf-table-toolbar"> |
| | | <el-button :icon="Plus" color="#284FE3" type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | <el-button :icon="Delete" color="#1A2652" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | |
| | | <el-table class="ztzf-data-cockpit-table" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="stationName" show-overflow-tooltip width="160" label="派出所名称" /> |
| | | <el-table-column prop="address" show-overflow-tooltip width="200" label="位置" /> |
| | | <el-table-column prop="longitude" show-overflow-tooltip width="120" label="经度" /> |
| | | <el-table-column prop="latitude" show-overflow-tooltip width="120" label="纬度" /> |
| | | <el-table-column prop="contactPerson" show-overflow-tooltip width="120" label="联系人" /> |
| | | <el-table-column prop="contactPhone" show-overflow-tooltip width="140" label="联系方式" /> |
| | | <el-table-column prop="stationName" show-overflow-tooltip label="派出所名称" /> |
| | | <el-table-column prop="address" show-overflow-tooltip label="位置" /> |
| | | <el-table-column prop="longitude" show-overflow-tooltip label="经度" /> |
| | | <el-table-column prop="latitude" show-overflow-tooltip label="纬度" /> |
| | | <el-table-column prop="contactPerson" show-overflow-tooltip label="联系人" /> |
| | | <el-table-column prop="contactPhone" show-overflow-tooltip label="联系方式" /> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('edit', row)">编辑</el-link> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search, RefreshRight, Plus } from '@element-plus/icons-vue' |
| | | import { Search, RefreshRight, Plus, Delete } from '@element-plus/icons-vue' |
| | | import { nextTick, onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { fwPoliceStationPageApi, fwPoliceStationRemoveApi } from './precinctInfoApi' |
| | |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="titleEnum[dialogMode]" :close-on-click-modal="false" width="80%"> |
| | | <div class="bodyBox"> |
| | | <div class="leftMap ztzf-cesium" id="mapContainer"></div> |
| | | <div class="rightInfo"> |
| | | <div v-if="readonly"> |
| | | <div>场景名称: {{ formData.sceneName }}</div> |
| | | <div>指挥点位置: {{ formatLocation(formData) }}</div> |
| | | <div>场景类型: {{ getDictLabel(formData.sceneType, dictObj.sceneType) }}</div> |
| | | <div>防控负责人: {{ formData.defenseLeader }}</div> |
| | | <div>防控负责人电话: {{ formData.leaderPhone }}</div> |
| | | <div>设备模式: {{ getDictLabel(formData.deviceMode, dictObj.deviceMode) }}</div> |
| | | <div>防控面积: {{ formatDefenseArea(formData.defenseArea) }}</div> |
| | | <el-table ref="areaTableRef" :data="areaList" row-key="id"> |
| | | <el-table-column prop="areaName" label="区域名称" /> |
| | | <el-table-column prop="areaType" label="区域类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.areaType, dictObj.areaType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-dialog class="ztzf-page-map-view-dialog" v-model="visible" :show-close="false" :close-on-click-modal="false"> |
| | | <div class="dialog-container"> |
| | | <div class="left-container"> |
| | | <div class="leftMap ztzf-cesium" id="mapContainer"></div> |
| | | </div> |
| | | <div class="right-container"> |
| | | <div class="header"> |
| | | {{ titleEnum[dialogMode] }} |
| | | </div> |
| | | <el-form v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly" label-width="100px"> |
| | | |
| | | <div class="dialog-container" v-if="readonly"> |
| | | <div class="detail-title">场景详情</div> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="场景名称" prop="sceneName"> |
| | | <el-input v-model="formData.sceneName" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <div class="label">场景名称</div> |
| | | <div class="val">{{ formData.sceneName }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="指挥点位置" prop="longitude"> |
| | | <div>{{ formatLocation(formData) }}</div> |
| | | </el-form-item> |
| | | <div class="label">指挥点位置</div> |
| | | <div class="val">{{ formatLocation(formData) }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="场景类型" prop="sceneType"> |
| | | <el-select v-model="formData.sceneType" placeholder="请选择" clearable> |
| | | <el-option |
| | | v-for="item in dictObj.sceneType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <div class="label">场景类型</div> |
| | | <div class="val">{{ getDictLabel(formData.sceneType, dictObj.sceneType) }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="防控负责人" prop="defenseLeader"> |
| | | <el-input v-model="formData.defenseLeader" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <div class="label">负责人</div> |
| | | <div class="val">{{ formData.defenseLeader }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="防控负责人电话" prop="leaderPhone"> |
| | | <el-input v-model="formData.leaderPhone" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <div class="label">负责人电话</div> |
| | | <div class="val">{{ formData.leaderPhone }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="设备模式" prop="deviceMode"> |
| | | <el-select v-model="formData.deviceMode" placeholder="请选择" clearable> |
| | | <el-option |
| | | v-for="item in dictObj.deviceMode" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <div class="label">设备模式</div> |
| | | <div class="val">{{ getDictLabel(formData.deviceMode, dictObj.deviceMode) }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="防控面积" prop="defenseArea"> |
| | | <div>{{ formatDefenseArea(formData.defenseArea) }}</div> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div> |
| | | <div> |
| | | 关联区域 |
| | | <el-input v-model="searchName" placeholder="请输入" clearable></el-input> |
| | | </div> |
| | | |
| | | <el-form-item prop="areaDivideIds" label-width="0"> |
| | | <el-table |
| | | ref="areaTableRef" |
| | | :data="areaList.filter(item => item.areaName.includes(searchName))" |
| | | row-key="id" |
| | | @selection-change="handleAreaSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55" :reserve-selection="true" /> |
| | | <el-table-column prop="areaName" label="区域名称" /> |
| | | <el-table-column prop="areaType" label="区域类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.areaType, dictObj.areaType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form-item> |
| | | </div> |
| | | <div class="label">防控面积</div> |
| | | <div class="val">{{ formatDefenseArea(formData.defenseArea) }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <div class="detail-title">关联区域</div> |
| | | <div class="ztzf-table-container"> |
| | | <div class="ztzf-table-content"> |
| | | <el-table class="ztzf-data-cockpit-table" ref="areaTableRef" :data="areaList" row-key="id"> |
| | | <el-table-column prop="areaName" label="区域名称" /> |
| | | <el-table-column prop="areaType" label="区域类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.areaType, dictObj.areaType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-form class="dialog-form" v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly" |
| | | label-width="96px"> |
| | | <el-form-item label="场景名称" prop="sceneName"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.sceneName" maxlength="50" |
| | | placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="指挥点位置" prop="longitude"> |
| | | <div class="val">{{ formatLocation(formData) }}</div> |
| | | </el-form-item> |
| | | <el-form-item label="场景类型" prop="sceneType"> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.sceneType" placeholder="请选择" clearable> |
| | | <el-option v-for="item in dictObj.sceneType" :key="item.dictKey" :label="item.dictValue" |
| | | :value="item.dictKey" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="负责人" prop="defenseLeader"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.defenseLeader" maxlength="50" |
| | | placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="负责人电话" prop="leaderPhone"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.leaderPhone" maxlength="50" |
| | | placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="设备模式" prop="deviceMode"> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.deviceMode" placeholder="请选择" clearable> |
| | | <el-option v-for="item in dictObj.deviceMode" :key="item.dictKey" :label="item.dictValue" |
| | | :value="item.dictKey" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="防控面积" prop="defenseArea"> |
| | | <div class="val">{{ formatDefenseArea(formData.defenseArea) }}</div> |
| | | </el-form-item> |
| | | |
| | | <div class="search-table-container"> |
| | | <div class="search-box"> |
| | | <div class="label"> |
| | | 关联区域 |
| | | </div> |
| | | |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="searchName" placeholder="请输入" |
| | | clearable></el-input> |
| | | </div> |
| | | |
| | | <el-form-item prop="areaDivideIds" label-width="0"> |
| | | <el-table class="ztzf-data-cockpit-table" ref="areaTableRef" |
| | | :data="areaList.filter(item => item.areaName.includes(searchName))" row-key="id" |
| | | @selection-change="handleAreaSelectionChange"> |
| | | <el-table-column type="selection" width="55" :reserve-selection="true" /> |
| | | <el-table-column prop="areaName" label="区域名称" /> |
| | | <el-table-column prop="areaType" label="区域类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.areaType, dictObj.areaType) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form-item> |
| | | </div> |
| | | </el-form> |
| | | |
| | | <div class="footer"> |
| | | <el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting" |
| | | :disabled="submitting" @click="handleSubmit"> |
| | | 确定 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit"> |
| | | 确定 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, inject, nextTick, onMounted, ref } from 'vue' |
| | | import { computed, inject, nextTick, onMounted, ref, watch } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fwDefenseSceneDetailApi, fwDefenseSceneSubmitApi } from './sceneConfigApi' |
| | | import { fieldRules, geomAnalysis, getDictLabel } from '@ztzf/utils' |
| | |
| | | const initForm = () => ({ |
| | | sceneName: '', // 场景名称 |
| | | sceneType: '', // 场景类型 |
| | | defenseLeader: '', // 防控负责人 |
| | | leaderPhone: '', // 防控负责人电话 |
| | | defenseLeader: '', // 负责人 |
| | | leaderPhone: '', // 负责人电话 |
| | | deviceMode: '', // 设备模式 |
| | | areaDivideIds: '', // 关联区域ID |
| | | areaCount: 0, // 区域数量 |
| | |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | function handleCancel () { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | async function handleSubmit () { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | async function loadDetail () { |
| | | if (!formData.value.id) return |
| | | const res = await fwDefenseSceneDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? initForm() |
| | | } |
| | | |
| | | // 获取区域列表 |
| | | async function getAreaList() { |
| | | async function getAreaList () { |
| | | if (areaList.value.length) return |
| | | const res = await fwAreaDivideListApi({ filterSelected: 1, sceneId: formData.value.id }) |
| | | areaList.value = res?.data?.data ?? [] |
| | | } |
| | | |
| | | // 关联区域变更 |
| | | function handleAreaSelectionChange(rows) { |
| | | function handleAreaSelectionChange (rows) { |
| | | selectedAreaRows.value = rows |
| | | formData.value.areaDivideIds = rows.map(item => item.id) |
| | | formData.value.areaCount = rows.length |
| | |
| | | } |
| | | |
| | | // 渲染面 |
| | | function renderingSurface() { |
| | | function renderingSurface () { |
| | | geometricSource && geometricSource.entities.removeAll() |
| | | selectedAreaRows.value.forEach(item => { |
| | | if (item.geom) { |
| | |
| | | |
| | | watch(() => selectedAreaRows.value, renderingSurface) |
| | | |
| | | function calcDefenseArea(rows) { |
| | | function calcDefenseArea (rows) { |
| | | const total = rows.reduce((sum, item) => sum + (Number(item.areaSize) || 0), 0) |
| | | return _.round(total, 2) |
| | | } |
| | | |
| | | // 同步关联区域 |
| | | function syncAreaSelection() { |
| | | function syncAreaSelection () { |
| | | if (!areaTableRef.value) return |
| | | areaTableRef.value.clearSelection() |
| | | const rows = [] |
| | |
| | | formData.value.defenseArea = calcDefenseArea(rows) |
| | | } |
| | | |
| | | function formatDefenseArea(value) { |
| | | function formatDefenseArea (value) { |
| | | if (value == null || value === '') return '' |
| | | return `${value}k㎡` |
| | | } |
| | | |
| | | // 格式化指挥点位置 |
| | | function formatLocation(row) { |
| | | function formatLocation (row) { |
| | | if (row?.longitude == null || row?.latitude == null) return '' |
| | | return `${_.round(row.longitude, 6)}, ${_.round(row.latitude, 6)}` |
| | | } |
| | | |
| | | let geometricSource |
| | | // 初始化地图实例 |
| | | function initMap() { |
| | | function initMap () { |
| | | const publicCesiumInstance = new PublicCesium({ |
| | | dom: 'mapContainer', |
| | | flatMode: false, |
| | |
| | | viewer.dataSources.add(geometricSource) |
| | | } |
| | | |
| | | function LeftClickEvent(click) { |
| | | function LeftClickEvent (click) { |
| | | const pos = click.position |
| | | const cartesian3 = viewer.camera.pickEllipsoid(pos, viewer.scene.globe.ellipsoid) |
| | | if (!cartesian3) return |
| | |
| | | setMapPoint(formData.value.longitude, formData.value.latitude) |
| | | } |
| | | |
| | | function setMapPoint(longitude, latitude) { |
| | | function setMapPoint (longitude, latitude) { |
| | | if (!viewer || longitude == null || latitude == null) return |
| | | if (!redPointEntity) { |
| | | redPointEntity = viewer.entities.add({ |
| | |
| | | label: { |
| | | text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`, |
| | | font: '14px', |
| | | fillColor: Cesium.Color.WHITE, // 文字颜色:白色 |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.45), //背景颜色 |
| | | backgroundPadding: new Cesium.Cartesian2(5, 5), // 水平/垂直内边距(像素) |
| | | pixelOffset: new Cesium.Cartesian2(0, -20), // 可选:微调位置 |
| | | showBackground: true, // 确保背景显示(某些版本需要) |
| | | fillColor: Cesium.Color.WHITE, |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.45), |
| | | backgroundPadding: new Cesium.Cartesian2(5, 5), |
| | | pixelOffset: new Cesium.Cartesian2(0, -20), |
| | | showBackground: true, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | horizontalOrigin: Cesium.HorizontalOrigin.CENTER, |
| | | verticalOrigin: Cesium.VerticalOrigin.CENTER, |
| | | outlineWidth: 1, |
| | | outlineColor: Cesium.Color.WHITE, |
| | | eyeOffset: new Cesium.Cartesian3(0, 0, -20), // 负值更靠近相机(显示在前) |
| | | eyeOffset: new Cesium.Cartesian3(0, 0, -20), |
| | | }, |
| | | }) |
| | | } else { |
| | |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | async function open ({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | selectedAreaRows.value = [] |
| | |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .bodyBox { |
| | | display: flex; |
| | | height: 600px; |
| | | .leftMap { |
| | | width: 70%; |
| | | height: 100%; |
| | | } |
| | | .rightInfo { |
| | | width: 30%; |
| | | height: 100%; |
| | | overflow: auto; |
| | | } |
| | | } |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| | |
| | | |
| | | <div class="ztzf-table-toolbar"> |
| | | <el-button :icon="Plus" color="#284FE3" type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | <el-button :icon="Delete" color="#1A2652" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | |
| | | <el-table-column prop="sceneName" show-overflow-tooltip width="130" label="场景名称" /> |
| | | <el-table-column prop="sceneType" show-overflow-tooltip width="120" label="场景类型"> |
| | | <el-table-column prop="sceneName" show-overflow-tooltip label="场景名称" /> |
| | | <el-table-column prop="sceneType" show-overflow-tooltip label="场景类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.sceneType, dictObj.sceneType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column show-overflow-tooltip width="150" label="指挥点位置"> |
| | | <el-table-column show-overflow-tooltip label="指挥点位置"> |
| | | <template v-slot="{ row }"> |
| | | {{ formatLocation(row) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="defenseLeader" show-overflow-tooltip width="120" label="防控负责人" /> |
| | | <el-table-column prop="leaderPhone" show-overflow-tooltip width="140" label="防控负责人电话" /> |
| | | <el-table-column prop="areaCount" show-overflow-tooltip width="110" label="区域数量" /> |
| | | <el-table-column prop="counterDeviceCount" show-overflow-tooltip width="120" label="反制设备数量" /> |
| | | <el-table-column prop="detectDeviceCount" show-overflow-tooltip width="120" label="探测设备数量" /> |
| | | <el-table-column prop="defenseLeader" show-overflow-tooltip label="防控负责人" /> |
| | | <el-table-column prop="leaderPhone" show-overflow-tooltip label="防控负责人电话" /> |
| | | <el-table-column prop="areaCount" show-overflow-tooltip label="区域数量" /> |
| | | <el-table-column prop="counterDeviceCount" show-overflow-tooltip label="反制设备数量" /> |
| | | <el-table-column prop="detectDeviceCount" show-overflow-tooltip label="探测设备数量" /> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('view', row)">查看</el-link> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search, RefreshRight, Plus } from '@element-plus/icons-vue' |
| | | import { Search, RefreshRight, Plus, Delete } from '@element-plus/icons-vue' |
| | | import { nextTick, onMounted, provide, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { fwDefenseScenePageApi, fwDefenseSceneRemoveApi } from './sceneConfigApi' |
| | |
| | | |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | |
| | | <el-table class="ztzf-data-cockpit-table" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip width="130" label="设备名称" /> |
| | | <el-table-column prop="deviceType" show-overflow-tooltip width="130" label="设备类型"> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" /> |
| | | <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceType, dictObj.deviceType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceModel" show-overflow-tooltip width="98" label="型号" /> |
| | | <el-table-column prop="manufacturer" show-overflow-tooltip width="130" label="生产厂商" /> |
| | | <el-table-column prop="createTime" show-overflow-tooltip width="96" label="入库时间" /> |
| | | <el-table-column prop="source" show-overflow-tooltip width="112" label="来源" /> |
| | | <el-table-column prop="charger" show-overflow-tooltip width="100" label="负责人" /> |
| | | <el-table-column prop="scrapTime" show-overflow-tooltip width="96" label="报废时间" /> |
| | | <el-table-column prop="scrapReason" show-overflow-tooltip width="136" label="报废原因" /> |
| | | <el-table-column prop="disposeWay" show-overflow-tooltip width="116" label="处置方式" /> |
| | | <el-table-column prop="maintainReminder" show-overflow-tooltip width="116" label="维护提醒" /> |
| | | <el-table-column prop="deviceModel" show-overflow-tooltip label="型号" /> |
| | | <el-table-column prop="manufacturer" show-overflow-tooltip label="生产厂商" /> |
| | | <el-table-column prop="createTime" show-overflow-tooltip label="入库时间" /> |
| | | <el-table-column prop="source" show-overflow-tooltip label="来源" /> |
| | | <el-table-column prop="charger" show-overflow-tooltip label="负责人" /> |
| | | <el-table-column prop="scrapTime" show-overflow-tooltip label="报废时间" /> |
| | | <el-table-column prop="scrapReason" show-overflow-tooltip label="报废原因" /> |
| | | <el-table-column prop="disposeWay" show-overflow-tooltip label="处置方式" /> |
| | | <el-table-column prop="maintainReminder" show-overflow-tooltip label="维护提醒" /> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="handleView(row)">查看</el-link> |
| | |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | |
| | | formData.value = initForm() |
| | | } |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | async function getList () { |
| | | loading.value = true |
| | |
| | | |
| | | <div class="ztzf-table-toolbar"> |
| | | <el-button :icon="Plus" color="#284FE3" type="primary" @click="handleAdd">新增</el-button> |
| | | <el-button :icon="Download" type="primary" @click="exportFile" :loading="exportLoading">导出</el-button> |
| | | <el-button :icon="Download" color="#1A2652" type="primary" @click="exportFile" :loading="exportLoading">导出</el-button> |
| | | <!-- <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button>--> |
| | | </div> |
| | | |
| | |
| | | size: 10, // 每页大小 |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const total = ref(0) // 总数 |
| | | const selectedIds = ref([]) // 勾选的设备ID列表 |
| | |
| | | }) |
| | | const searchParams = ref(initSearchParams()) |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | async function getList() { |
| | | loading.value = true |
| | |
| | | |
| | | <div class="ztzf-table-toolbar"> |
| | | <el-button :icon="Plus" color="#284FE3" type="primary" @click="handleAdd">维护计划</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | <el-button :icon="Delete" color="#1A2652" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | |
| | | <el-table class="ztzf-data-cockpit-table" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip width="130" label="设备名称" /> |
| | | <el-table-column prop="deviceType" show-overflow-tooltip width="130" label="设备类型"> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" /> |
| | | <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceType, dictObj.deviceType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceModel" show-overflow-tooltip width="98" label="型号" /> |
| | | <el-table-column prop="manufacturer" show-overflow-tooltip width="130" label="生产厂商" /> |
| | | <el-table-column prop="charger" show-overflow-tooltip width="100" label="负责人" /> |
| | | <el-table-column prop="maintainReminder" show-overflow-tooltip width="116" label="维护提醒" /> |
| | | <el-table-column prop="planCycleType" show-overflow-tooltip width="160" label="维护计划"> |
| | | <el-table-column prop="deviceModel" show-overflow-tooltip label="型号" /> |
| | | <el-table-column prop="manufacturer" show-overflow-tooltip label="生产厂商" /> |
| | | <el-table-column prop="charger" show-overflow-tooltip label="负责人" /> |
| | | <el-table-column prop="maintainReminder" show-overflow-tooltip label="维护提醒" /> |
| | | <el-table-column prop="planCycleType" show-overflow-tooltip label="维护计划"> |
| | | <template v-slot="{ row }"> |
| | | {{ getPlanCycleLabel(row) }} |
| | | </template> |
| | |
| | | </basic-container> |
| | | </template> |
| | | <script setup> |
| | | import { Search, RefreshRight, Plus } from '@element-plus/icons-vue' |
| | | import { Search, RefreshRight, Plus, Delete } from '@element-plus/icons-vue' |
| | | import { onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz' |
| | |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | |
| | | }; |
| | | |
| | | // 地图接口 |
| | | const loading = ref(false); |
| | | const loading = ref(true); |
| | | const getMapInfoAPIFun = async ids => { |
| | | try { |
| | | const res = await getMapInfoAPI(ids); |
| | |
| | | }) |
| | | const searchParams = ref(initSearchParams()) |
| | | const queryParamsRef = ref(null) |
| | | const loading = ref(false) |
| | | const loading = ref(true) |
| | | const list = ref([]) |
| | | const total = ref(0) |
| | | const areaTree = ref([ |
| | |
| | | import EmptyState from './EmptyState.vue' |
| | | |
| | | const equipmentWarningData = ref([]) |
| | | const loading = ref(false) |
| | | const loading = ref(true) |
| | | const minLoadingMs = 400 |
| | | |
| | | const statusMap = { |
| | |
| | | import EmptyState from './EmptyState.vue' |
| | | |
| | | const historyWarningData = ref([]) |
| | | const loading = ref(false) |
| | | const loading = ref(true) |
| | | const minLoadingMs = 400 |
| | | |
| | | // 查询条件:keyword + dateRange(YYYY-MM-DD数组) |
| | |
| | | import { ElMessage } from 'element-plus' |
| | | |
| | | const realWarningData = ref([]) |
| | | const loading = ref(false) |
| | | const loading = ref(true) |
| | | const minLoadingMs = 400 |
| | | |
| | | const actionTextMap = { |
| | |
| | | |
| | | const historyVisible = ref(false) |
| | | const historyDevice = ref(null) |
| | | const loading = ref(false) |
| | | const loading = ref(true) |
| | | const minLoadingMs = 400 |
| | | |
| | | const onHistory = (item) => { |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="titleEnum[dialogMode]" :close-on-click-modal="false"> |
| | | <div v-if="readonly"> |
| | | <template> |
| | | <el-dialog |
| | | class="ztzf-page-view-dialog" |
| | | v-model="visible" |
| | | :title="titleEnum[dialogMode]" |
| | | :close-on-click-modal="false" |
| | | width="520px" |
| | | > |
| | | <div class="detail-container"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <div>无人机名称: {{ formData.droneName }}</div> |
| | | <div class="label">无人机名称</div> |
| | | <div class="val">{{ formData.droneName || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>无人机类型: {{ formData.droneType }}</div> |
| | | <div class="label">无人机类型</div> |
| | | <div class="val">{{ formData.droneType || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>无人机设备编码: {{ formData.droneDeviceCode }}</div> |
| | | <div class="label">无人机设备编码</div> |
| | | <div class="val">{{ formData.droneDeviceCode || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>发现时间: {{ formData.findTime }}</div> |
| | | <div class="label">发现时间</div> |
| | | <div class="val">{{ formData.findTime || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>反制效果: {{ getDictLabel(formData.counterEffect, dictObj.counterEffect) }}</div> |
| | | <div class="label">反制效果</div> |
| | | <div class="val">{{ getDictLabel(formData.counterEffect, dictObj.counterEffect) || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>反制方式: {{ getCounterWayLabel(formData.counterWay) }}</div> |
| | | <div class="label">反制方式</div> |
| | | <div class="val">{{ getCounterWayLabel(formData.counterWay) || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>反制设备名称: {{ formData.deviceName }}</div> |
| | | <div class="label">反制设备名称</div> |
| | | <div class="val">{{ formData.deviceName || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>反制设备型号: {{ formData.deviceModel }}</div> |
| | | <div class="label">反制设备型号</div> |
| | | <div class="val">{{ formData.deviceModel || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>反制设备类型: {{ getDeviceTypeLabel(formData.deviceType) }}</div> |
| | | <div class="label">反制设备类型</div> |
| | | <div class="val">{{ getDeviceTypeLabel(formData.deviceType) || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>反制设备编码: {{ formData.deviceSn }}</div> |
| | | <div class="label">反制设备编码</div> |
| | | <div class="val">{{ formData.deviceSn || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>区域编码: {{ formData.areaCode }}</div> |
| | | <div class="label">区域编码</div> |
| | | <div class="val">{{ formData.areaCode || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>部署位置: {{ getDeployPosition() }}</div> |
| | | <div class="label">部署位置</div> |
| | | <div class="val">{{ getDeployPosition() || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>覆盖范围: {{ formData.coverRadiusM ? `${formData.coverRadiusM}米` : '' }}</div> |
| | | <div class="label">覆盖范围</div> |
| | | <div class="val">{{ formData.coverRadiusM ? `${formData.coverRadiusM}米` : '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>工作模式: {{ getWorkModeLabel(formData.workMode) }}</div> |
| | | <div class="label">工作模式</div> |
| | | <div class="val">{{ getWorkModeLabel(formData.workMode) || '-' }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">关闭</el-button> |
| | | <el-button color="#2B2B4C" @click="handleCancel">关闭</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | |
| | | |
| | | // 注入字典数据 |
| | | const dictObj = inject('dictObj') |
| | | // 注入反制效果选项 |
| | | |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = defineModel() // 弹框显隐 |
| | |
| | | // 获取反制方式标签 |
| | | function getCounterWayLabel(value) { |
| | | const map = { '1': '信号干扰', '2': '诱导驱离' } |
| | | return map[value] || value || '无' |
| | | return map[value] || value || '暂无' |
| | | } |
| | | |
| | | // 获取设备类型标签 |
| | |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'view' |
| | | formData.value = row ? { ...row } : initForm() |
| | | dialogMode.value === 'view' && (await loadDetail()) |
| | | if (readonly.value) { |
| | | await loadDetail() |
| | | } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | |
| | | <template> |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams"> |
| | | <el-row :gutter="16"> |
| | | <el-col :span="4"> |
| | | <el-form-item label="设备名称" prop="deviceName"> |
| | | <el-input v-model="searchParams.deviceName" placeholder="请输入" clearable @clear="handleSearch" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="设备类型" prop="deviceType"> |
| | | <el-select v-model="searchParams.deviceType" placeholder="请选择" clearable @change="handleSearch"> |
| | | <el-option |
| | | v-for="item in dictObj.deviceType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="反制效果" prop="counterEffect"> |
| | | <el-select v-model="searchParams.counterEffect" placeholder="请选择" clearable @change="handleSearch"> |
| | | <el-option |
| | | v-for="item in dictObj.counterEffect" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button @click="resetForm">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="ztzf-page-history-search"> |
| | | <el-form-item label="设备名称" prop="deviceName"> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="searchParams.deviceName" |
| | | placeholder="请输入" |
| | | clearable |
| | | @clear="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="设备类型" prop="deviceType"> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="searchParams.deviceType" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="handleSearch" |
| | | > |
| | | <el-option |
| | | v-for="item in dictObj.deviceType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="反制效果" prop="counterEffect"> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="searchParams.counterEffect" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="handleSearch" |
| | | > |
| | | <el-option |
| | | v-for="item in dictObj.counterEffect" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item class="history-search-actions"> |
| | | <el-button :icon="RefreshRight" @click="resetForm"></el-button> |
| | | <el-button class="search-btn" :icon="Search" @click="handleSearch"></el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column prop="droneName" label="无人机名称" /> |
| | | <el-table-column prop="droneType" label="无人机类型" /> |
| | | <el-table-column prop="droneDeviceCode" label="无人机设备编码" /> |
| | | <el-table-column prop="findTime" label="发现时间" /> |
| | | <el-table-column prop="counterEffect" label="反制效果"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.counterEffect, dictObj.counterEffect) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceName" label="反制设备名称" /> |
| | | <el-table-column prop="deviceModel" label="反制设备型号" /> |
| | | <el-table-column prop="deviceType" label="反制设备类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceType, dictObj.deviceType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceSn" label="反制设备编码" /> |
| | | <el-table-column prop="areaCode" label="场景" /> |
| | | <el-table-column prop="areaCode" label="区域" /> |
| | | <el-table-column label="部署位置"> |
| | | <template v-slot="{ row }"> |
| | | {{ row.deployLongitude && row.deployLatitude ? `${row.deployLongitude}, ${row.deployLatitude}` : '' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="coverRadiusM" label="覆盖范围"> |
| | | <template v-slot="{ row }"> |
| | | {{ row.coverRadiusM ? `${row.coverRadiusM}米` : '' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="workMode" label="工作模式"> |
| | | <template v-slot="{ row }"> |
| | | {{ getWorkModeLabel(row.workMode) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="100"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('view', row)" type="primary">查看</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div> |
| | | <el-pagination |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | | <div class="ztzf-table-content ztzf-table-content-bg"> |
| | | <el-table class="ztzf-data-cockpit-table" :data="list"> |
| | | <el-table-column type="index" width="64" show-overflow-tooltip label="序号" /> |
| | | <el-table-column prop="droneName" show-overflow-tooltip width="130" label="无人机名称" /> |
| | | <el-table-column prop="droneType" show-overflow-tooltip width="130" label="无人机类型" /> |
| | | <el-table-column prop="droneDeviceCode" show-overflow-tooltip width="140" label="无人机设备编码" /> |
| | | <el-table-column prop="findTime" show-overflow-tooltip width="140" label="发现时间" /> |
| | | <el-table-column prop="counterEffect" show-overflow-tooltip width="120" label="反制效果"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.counterEffect, dictObj.counterEffect) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip width="130" label="反制设备名称" /> |
| | | <el-table-column prop="deviceModel" show-overflow-tooltip width="120" label="反制设备型号" /> |
| | | <el-table-column prop="deviceType" show-overflow-tooltip width="120" label="反制设备类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceType, dictObj.deviceType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceSn" show-overflow-tooltip width="140" label="反制设备编码" /> |
| | | <el-table-column prop="areaCode" show-overflow-tooltip width="120" label="场景" /> |
| | | <el-table-column prop="areaCode" show-overflow-tooltip width="120" label="区域" /> |
| | | <el-table-column show-overflow-tooltip width="160" label="部署位置"> |
| | | <template v-slot="{ row }"> |
| | | {{ row.deployLongitude && row.deployLatitude ? `${row.deployLongitude}, ${row.deployLatitude}` : '' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="coverRadiusM" show-overflow-tooltip width="120" label="覆盖范围"> |
| | | <template v-slot="{ row }"> |
| | | {{ row.coverRadiusM ? `${row.coverRadiusM}米` : '' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="workMode" show-overflow-tooltip width="120" label="工作模式"> |
| | | <template v-slot="{ row }"> |
| | | {{ getWorkModeLabel(row.workMode) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" class-name="operation-btns" width="100"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('view', row)" type="primary">查看</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-pagination"> |
| | | <el-pagination |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | layout="total, prev, pager, next, sizes" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | </div> |
| | | |
| | | <FormDiaLog v-if="dialogVisible" v-model="dialogVisible" ref="dialogRef" /> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { RefreshRight, Search } from '@element-plus/icons-vue' |
| | | import { onMounted, ref, nextTick, provide } from 'vue' |
| | | import { fwEffectEvalPageApi } from './countermeasureEvaluationApi' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | |
| | | |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | | const dialogVisible = ref(null) // 弹框显隐 |
| | | const dialogVisible = ref(false) // 弹框显隐 |
| | | const dictObj = ref({ |
| | | deviceType: [], // 设备类型 |
| | | counterEffect: [], // 反制效果 |
| | | }) |
| | | |
| | | // 注入字典和反制效果选项供FormDiaLog使用 |
| | | // 注入字典和反制效果选项供 FormDiaLog 使用 |
| | | provide('dictObj', dictObj) |
| | | |
| | | // 获取列表 |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="visible" |
| | | :title="dialogTitle" |
| | | class="detection-range-dialog" |
| | | destroy-on-close |
| | | @closed="handleClosed" |
| | | > |
| | | <div class="dialog-body"> |
| | | <div class="dialog-map"> |
| | | <DeviceMapContainer |
| | | :online-devices="mapDevices" |
| | | :show-layer-control="false" |
| | | container-id="detection-range-map" |
| | | /> |
| | | <div class="map-toolbar"> |
| | | <button class="map-btn" type="button" aria-label="编辑范围"></button> |
| | | <button class="map-btn" type="button" aria-label="定位设备"></button> |
| | | </div> |
| | | <div class="map-mini-controls"> |
| | | <button class="map-mini-btn" type="button" aria-label="放大">+</button> |
| | | <button class="map-mini-btn" type="button" aria-label="缩小">-</button> |
| | | </div> |
| | | <el-dialog v-model="visible" class="ztzf-page-map-view-dialog" :show-close="false" :close-on-click-modal="false" |
| | | destroy-on-close @closed="handleClosed"> |
| | | <div class="dialog-container"> |
| | | <div class="left-container"> |
| | | <div class="leftMap ztzf-cesium" id="detectionRangeMap"></div> |
| | | </div> |
| | | <div class="dialog-form"> |
| | | <div class="form-title">{{ formTitle }}</div> |
| | | <el-form ref="formRef" :model="formData" :rules="rules" label-width="84px" :disabled="dialogReadonly"> |
| | | |
| | | <div class="right-container"> |
| | | <div class="header">{{ formTitle }}</div> |
| | | |
| | | <div class="dialog-container" v-if="dialogReadonly"> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <div class="label">侦测设备</div> |
| | | <div class="val">{{ formData.deviceName || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">设备类型</div> |
| | | <div class="val">{{ getDeviceTypeLabel(formData.deviceType) }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">设备位置</div> |
| | | <div class="val">{{ formData.deployLocation || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">设备编号</div> |
| | | <div class="val">{{ formData.deviceSn || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">设备型号</div> |
| | | <div class="val">{{ formData.deviceModel || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">覆盖范围</div> |
| | | <div class="val">{{ formatRange(formData.effectiveRangeKm) }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <el-form v-else ref="formRef" class="dialog-form" :model="formData" :rules="rules" label-width="96px"> |
| | | <el-form-item label="侦测设备" prop="deviceId"> |
| | | <el-select v-model="formData.deviceId" placeholder="请选择" clearable @change="handleDeviceChange"> |
| | | <el-option v-for="item in deviceOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.deviceId" placeholder="请选择" clearable @change="handleDeviceChange"> |
| | | <el-option v-for="item in deviceOptions" :key="item.value" :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="设备类型" prop="deviceType"> |
| | | <el-select v-model="formData.deviceType" placeholder="请选择" clearable> |
| | | <el-option |
| | | v-for="item in dictObj.deviceType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | <el-select class="ztzf-data-cockpit-select" popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.deviceType" placeholder="请选择" clearable> |
| | | <el-option v-for="item in dictObj.deviceType" :key="item.dictKey" :label="item.dictValue" |
| | | :value="item.dictKey" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="设备位置" prop="deployLocation"> |
| | | <el-input v-model="formData.deployLocation" placeholder="请选择位置"> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.deployLocation" |
| | | placeholder="请选择位置"> |
| | | <template #suffix> |
| | | <span class="suffix-action">地图选点</span> |
| | | </template> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="设备编号" prop="deviceSn"> |
| | | <el-input v-model="formData.deviceSn" placeholder="请输入" clearable /> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.deviceSn" placeholder="请输入" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="设备型号" prop="deviceModel"> |
| | | <el-input v-model="formData.deviceModel" placeholder="请输入" clearable /> |
| | | <el-input class="ztzf-data-cockpit-search-input" v-model="formData.deviceModel" |
| | | placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="覆盖范围" prop="effectiveRangeKm"> |
| | | <el-input-number |
| | | v-model="formData.effectiveRangeKm" |
| | | :min="0" |
| | | :precision="2" |
| | | :controls="false" |
| | | placeholder="请输入" |
| | | /> |
| | | <el-input-number class="ztzf-data-cockpit-search-input" v-model="formData.effectiveRangeKm" :min="0" :precision="2" :controls="false" |
| | | placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="footer"> |
| | | <el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button color="#284FE3" v-if="!dialogReadonly" type="primary" :loading="submitting" |
| | | :disabled="submitting" @click="handleSubmit"> |
| | | 保存 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <template v-if="!dialogReadonly" #footer> |
| | | <el-button @click="handleCancel">取消</el-button> |
| | | <el-button type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit">保存</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, inject, ref } from 'vue' |
| | | import { computed, inject, nextTick, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import DeviceMapContainer from '@/components/map-container/device-map-container.vue' |
| | | import { |
| | | detectionRangeDetailApi, |
| | | detectionRangePageApi, |
| | | detectionRangeSubmitApi, |
| | | } from '@/api/detectionCountermeasure/detectionRange' |
| | | import { PublicCesium } from '@/utils/cesium/publicCesium' |
| | | import * as Cesium from 'cesium' |
| | | |
| | | const initForm = () => ({ |
| | | deviceId: '', // 侦测设备ID |
| | |
| | | const visible = ref(false) // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const mapDevices = ref([]) |
| | | const deviceOptions = ref([]) |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const dialogTitle = computed(() => { |
| | | if (dialogMode.value === 'edit') { |
| | | return '编辑' |
| | | } else if (dialogMode.value === 'view') { |
| | | return '查看' |
| | | } |
| | | return '新增' |
| | | }) |
| | | let viewer |
| | | let redPointEntity |
| | | const formTitle = computed(() => { |
| | | if (dialogMode.value === 'edit') { |
| | | return '编辑侦测范围' |
| | |
| | | const rules = { |
| | | deviceId: [{ required: true, message: '请选择侦测设备', trigger: ['blur', 'change'] }], |
| | | deviceType: [{ required: true, message: '请选择设备类型', trigger: ['blur', 'change'] }], |
| | | deployLocation: [{ required: true, message: '请选择设备位置', trigger: ['blur', 'change'] }], |
| | | effectiveRangeKm: [{ required: true, message: '请输入覆盖范围', trigger: ['blur', 'change'] }], |
| | | } |
| | | |
| | | function handleDeviceChange(value) { |
| | | function handleDeviceChange (value) { |
| | | const target = deviceOptions.value.find(item => item.value === value) |
| | | const raw = target?.raw |
| | | if (!raw) return |
| | |
| | | raw.deployLocation ?? raw.address ?? raw.location ?? raw.deployAddress ?? formData.value.deployLocation |
| | | } |
| | | |
| | | function getDeviceTypeLabel (value) { |
| | | const list = dictObj?.deviceType ?? [] |
| | | const target = list.find(item => item.dictKey === value) |
| | | return target?.dictValue ?? value ?? '-' |
| | | } |
| | | |
| | | function formatRange (value) { |
| | | if (value == null || value === '') return '-' |
| | | return `${value}km` |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | function handleCancel () { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | async function handleSubmit () { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail(id) { |
| | | async function loadDetail (id) { |
| | | if (!id) return null |
| | | const res = await detectionRangeDetailApi({ id }) |
| | | return res?.data?.data ?? null |
| | | } |
| | | |
| | | async function loadDeviceOptions() { |
| | | async function loadDeviceOptions () { |
| | | const res = await detectionRangePageApi({ |
| | | current: 1, |
| | | size: 200, |
| | |
| | | } |
| | | |
| | | // 关闭后重置 |
| | | function handleClosed() { |
| | | function handleClosed () { |
| | | formData.value = initForm() |
| | | viewer = null |
| | | redPointEntity = null |
| | | } |
| | | |
| | | function setMapPoint (longitude, latitude) { |
| | | if (!viewer || longitude == null || latitude == null) return |
| | | if (!redPointEntity) { |
| | | redPointEntity = viewer.entities.add({ |
| | | position: Cesium.Cartesian3.fromDegrees(longitude, latitude), |
| | | point: { |
| | | color: Cesium.Color.RED, |
| | | pixelSize: 10, |
| | | }, |
| | | label: { |
| | | text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`, |
| | | font: '14px', |
| | | fillColor: Cesium.Color.WHITE, |
| | | backgroundColor: Cesium.Color.BLACK.withAlpha(0.45), |
| | | backgroundPadding: new Cesium.Cartesian2(5, 5), |
| | | pixelOffset: new Cesium.Cartesian2(0, -20), |
| | | showBackground: true, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | horizontalOrigin: Cesium.HorizontalOrigin.CENTER, |
| | | verticalOrigin: Cesium.VerticalOrigin.CENTER, |
| | | outlineWidth: 1, |
| | | outlineColor: Cesium.Color.WHITE, |
| | | eyeOffset: new Cesium.Cartesian3(0, 0, -20), |
| | | }, |
| | | }) |
| | | } else { |
| | | redPointEntity.position = Cesium.Cartesian3.fromDegrees(longitude, latitude) |
| | | redPointEntity.label.text = `${longitude.toFixed(6)}, ${latitude.toFixed(6)}` |
| | | } |
| | | } |
| | | |
| | | function initMap () { |
| | | if (viewer) return |
| | | const publicCesiumInstance = new PublicCesium({ |
| | | dom: 'detectionRangeMap', |
| | | flatMode: false, |
| | | terrain: true, |
| | | layerMode: 4, |
| | | boundary: false, |
| | | }) |
| | | if (!dialogReadonly.value) { |
| | | publicCesiumInstance.addLeftClickEvent(null, handleMapClick) |
| | | } |
| | | viewer = publicCesiumInstance.getViewer() |
| | | } |
| | | |
| | | function handleMapClick (click) { |
| | | const pos = click.position |
| | | const cartesian3 = viewer.camera.pickEllipsoid(pos, viewer.scene.globe.ellipsoid) |
| | | if (!cartesian3) return |
| | | const carto = Cesium.Cartographic.fromCartesian(cartesian3) |
| | | const longitude = Number(Cesium.Math.toDegrees(carto.longitude).toFixed(6)) |
| | | const latitude = Number(Cesium.Math.toDegrees(carto.latitude).toFixed(6)) |
| | | formData.value.deployLocation = `${longitude}, ${latitude}` |
| | | setMapPoint(longitude, latitude) |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | async function open ({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | visible.value = true |
| | | await nextTick() |
| | | initMap() |
| | | if (dialogMode.value === 'add') { |
| | | await loadDeviceOptions() |
| | | formData.value = initForm() |
| | |
| | | if (currentId && !deviceOptions.value.some(item => item.value === currentId)) { |
| | | deviceOptions.value.unshift({ label: currentName || '-', value: currentId }) |
| | | } |
| | | const location = formData.value.deployLocation |
| | | if (location) { |
| | | const [longitude, latitude] = location.split(',').map(item => Number(item.trim())) |
| | | if (!Number.isNaN(longitude) && !Number.isNaN(latitude)) { |
| | | setMapPoint(longitude, latitude) |
| | | } |
| | | } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .detection-range-dialog { |
| | | :deep(.el-dialog) { |
| | | width: 1100px; |
| | | background: #071833; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | :deep(.el-dialog__header) { |
| | | border-bottom: 1px solid rgba(70, 110, 180, 0.35); |
| | | } |
| | | } |
| | | |
| | | .dialog-body { |
| | | display: flex; |
| | | gap: 16px; |
| | | min-height: 560px; |
| | | } |
| | | |
| | | .dialog-map { |
| | | position: relative; |
| | | flex: 1; |
| | | min-height: 520px; |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | border: 1px solid rgba(70, 110, 180, 0.35); |
| | | background: #031024; |
| | | } |
| | | |
| | | .map-toolbar { |
| | | position: absolute; |
| | | top: 16px; |
| | | right: 16px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 8px; |
| | | z-index: 2; |
| | | } |
| | | |
| | | .map-btn { |
| | | width: 34px; |
| | | height: 34px; |
| | | border-radius: 6px; |
| | | border: 1px solid rgba(80, 120, 180, 0.6); |
| | | background: rgba(7, 18, 44, 0.9); |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .map-mini-controls { |
| | | position: absolute; |
| | | left: 16px; |
| | | bottom: 16px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 6px; |
| | | z-index: 2; |
| | | } |
| | | |
| | | .map-mini-btn { |
| | | width: 28px; |
| | | height: 28px; |
| | | border-radius: 4px; |
| | | border: 1px solid rgba(80, 120, 180, 0.6); |
| | | background: rgba(7, 18, 44, 0.9); |
| | | color: #cfe3ff; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .dialog-form { |
| | | width: 300px; |
| | | padding: 12px 12px 0; |
| | | border-radius: 8px; |
| | | background: linear-gradient(180deg, rgba(10, 28, 58, 0.95), rgba(6, 16, 34, 0.95)); |
| | | border: 1px solid rgba(70, 110, 180, 0.35); |
| | | color: #d7e7ff; |
| | | } |
| | | |
| | | .form-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | margin-bottom: 12px; |
| | | letter-spacing: 1px; |
| | | } |
| | | |
| | | :deep(.el-form-item__label) { |
| | | color: rgba(210, 230, 255, 0.85); |
| | | } |
| | | |
| | | :deep(.el-input__wrapper), |
| | | :deep(.el-select__wrapper), |
| | | :deep(.el-input-number .el-input__wrapper) { |
| | | background: rgba(7, 20, 44, 0.85); |
| | | border: 1px solid rgba(80, 120, 190, 0.45); |
| | | box-shadow: none; |
| | | } |
| | | |
| | | :deep(.el-input__inner) { |
| | | color: #d5e6ff; |
| | | } |
| | | |
| | | .suffix-action { |
| | | font-size: 12px; |
| | | color: #7fb6ff; |
| | | cursor: pointer; |
| | | } |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| | |
| | | <template> |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="ztzf-page-history-search"> |
| | | <el-form-item label="名称" prop="deviceName"> |
| | |
| | | <div class="ztzf-table-content ztzf-table-content-bg"> |
| | | <el-table class="ztzf-data-cockpit-table" :data="list"> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip width="140" label="设备名称" /> |
| | | <el-table-column prop="deviceType" show-overflow-tooltip width="120" label="设备类型"> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" /> |
| | | <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceType, dictObj.deviceType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column show-overflow-tooltip width="160" label="部署位置"> |
| | | <el-table-column show-overflow-tooltip label="部署位置"> |
| | | <template v-slot="{ row }"> |
| | | {{ formatDeployLocation(row) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceModel" show-overflow-tooltip width="110" label="型号" /> |
| | | <el-table-column show-overflow-tooltip width="120" label="覆盖范围"> |
| | | <el-table-column prop="deviceModel" show-overflow-tooltip label="型号" /> |
| | | <el-table-column show-overflow-tooltip label="覆盖范围"> |
| | | <template v-slot="{ row }"> |
| | | {{ formatRange(row) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column show-overflow-tooltip width="150" label="设备编码"> |
| | | <el-table-column show-overflow-tooltip label="设备编码"> |
| | | <template v-slot="{ row }"> |
| | | {{ formatDeviceCode(row) }} |
| | | </template> |
| | |
| | | size: 10, // 每页大小 |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const total = ref(0) // 总数 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | |
| | | |
| | | // 删除 |
| | | async function handleDelete(row) { |
| | | await ElMessageBox.confirm('确认删除该条数据吗?', '提示', { type: 'warning' }) |
| | | await ElMessageBox.confirm('确认删除该条数据吗?', '提示', { |
| | | type: 'warning', |
| | | customClass: 'ztzf-page-view-message-box', |
| | | confirmButtonClass: 'ztzf-message-box-confirm', |
| | | cancelButtonClass: 'ztzf-message-box-cancel', |
| | | }) |
| | | await detectionRangeSubmitApi({ id: row.id, effectiveRangeKm: 0 }) |
| | | ElMessage.success('删除成功') |
| | | getList() |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="titleEnum[dialogMode]" :close-on-click-modal="false"> |
| | | <div v-if="readonly"> |
| | | <template> |
| | | <el-dialog |
| | | class="ztzf-page-view-dialog" |
| | | v-model="visible" |
| | | :title="titleEnum[dialogMode]" |
| | | :close-on-click-modal="false" |
| | | @closed="handleClosed" |
| | | destroy-on-close |
| | | > |
| | | <div v-if="readonly" class="detail-container"> |
| | | <div class="detail-title">配置详情</div> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <div>起始扇区: {{ formData.startSector }}</div> |
| | | <div class="label">起始扇区</div> |
| | | <div class="val">{{ formData.startSector }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>终止扇区: {{ formData.endSector }}</div> |
| | | <div class="label">终止扇区</div> |
| | | <div class="val">{{ formData.endSector }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>搜索模式: {{ formData.searchMode }}</div> |
| | | <div class="label">搜索模式</div> |
| | | <div class="val">{{ formData.searchMode }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>雷达频点: {{ formData.radarFreq }}</div> |
| | | <div class="label">雷达频点</div> |
| | | <div class="val">{{ formData.radarFreq }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>伺服模式: {{ formData.servoMode }}</div> |
| | | <div class="label">伺服模式</div> |
| | | <div class="val">{{ formData.servoMode }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>伺服数据模式: {{ formData.servoDataMode }}</div> |
| | | <div class="label">伺服数据模式</div> |
| | | <div class="val">{{ formData.servoDataMode }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>轴选择: {{ formData.axisSelect }}</div> |
| | | <div class="label">轴选择</div> |
| | | <div class="val">{{ formData.axisSelect }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>伺服转速度: {{ formData.servoTurnSpeed }}</div> |
| | | <div class="label">伺服转速度</div> |
| | | <div class="val">{{ formData.servoTurnSpeed }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <el-form v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly" label-width="120px"> |
| | | |
| | | <el-form v-else ref="formRef" :model="formData" :rules="rules" label-width="120px" class="dialog-form"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="起始扇区" prop="startSector"> |
| | | <el-input v-model="formData.startSector" maxlength="50" placeholder="请输入" clearable /> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="formData.startSector" |
| | | maxlength="50" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="终止扇区" prop="endSector"> |
| | | <el-input v-model="formData.endSector" maxlength="50" placeholder="请输入" clearable /> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="formData.endSector" |
| | | maxlength="50" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="搜索模式" prop="searchMode"> |
| | | <el-select v-model="formData.searchMode" placeholder="请选择" clearable> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.searchMode" |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option v-for="item in searchModeOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="雷达频点" prop="radarFreq"> |
| | | <el-input v-model="formData.radarFreq" maxlength="50" placeholder="请输入" clearable /> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="formData.radarFreq" |
| | | maxlength="50" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="伺服模式" prop="servoMode"> |
| | | <el-select v-model="formData.servoMode" placeholder="请选择" clearable> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.servoMode" |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option v-for="item in servoModeOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="伺服数据模式" prop="servoDataMode"> |
| | | <el-select v-model="formData.servoDataMode" placeholder="请选择" clearable> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.servoDataMode" |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in servoDataModeOptions" |
| | | :key="item.value" |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="轴选择" prop="axisSelect"> |
| | | <el-select v-model="formData.axisSelect" placeholder="请选择" clearable> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.axisSelect" |
| | | placeholder="请选择" |
| | | clearable |
| | | > |
| | | <el-option v-for="item in axisSelectOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="伺服转速度" prop="servoTurnSpeed"> |
| | | <el-input v-model="formData.servoTurnSpeed" maxlength="50" placeholder="请输入" clearable /> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="formData.servoTurnSpeed" |
| | | maxlength="50" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit"> |
| | | 确定 |
| | | <el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button |
| | | color="#284FE3" |
| | | v-if="!readonly" |
| | | type="primary" |
| | | :loading="submitting" |
| | | :disabled="submitting" |
| | | @click="handleSubmit" |
| | | > |
| | | 保存 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fwDeviceConfigDetailApi, fwDeviceConfigSubmitApi } from './deviceAppConfigApi' |
| | | import { fwDeviceConfigSubmitApi } from './deviceAppConfigApi' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | |
| | | const configKeys = [ |
| | |
| | | { label: '扇区', value: '扇区' }, |
| | | { label: '定位', value: '定位' }, |
| | | ] |
| | | const servoDataModeOptions = [{ label: '编码器', value: '编码器' }] |
| | | const servoDataModeOptions = [{ label: '编码模式', value: '编码模式' }] |
| | | const axisSelectOptions = [{ label: '方位', value: '方位' }] |
| | | |
| | | const rules = { |
| | |
| | | visible.value = false |
| | | } |
| | | |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | // 提交更新 |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | |
| | | <template> |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams"> |
| | | <el-row :gutter="16"> |
| | | <el-col :span="4"> |
| | | <el-form-item label="设备名称" prop="deviceName"> |
| | | <el-input v-model="searchParams.deviceName" placeholder="请输入" clearable @clear="handleSearch" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="设备类型" prop="deviceType"> |
| | | <el-select v-model="searchParams.deviceType" placeholder="请选择" clearable @change="handleSearch"> |
| | | <el-option |
| | | v-for="item in dictObj.deviceType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button @click="resetForm">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="ztzf-page-history-search"> |
| | | <el-form-item label="设备名称" prop="deviceName"> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="searchParams.deviceName" |
| | | placeholder="请输入" |
| | | clearable |
| | | @clear="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="设备类型" prop="deviceType"> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="searchParams.deviceType" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="handleSearch" |
| | | > |
| | | <el-option |
| | | v-for="item in dictObj.deviceType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item class="history-search-actions"> |
| | | <el-button :icon="RefreshRight" @click="resetForm"></el-button> |
| | | <el-button class="search-btn" :icon="Search" @click="handleSearch"></el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column prop="deviceType" label="设备类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceType, dictObj.deviceType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceModel" label="设备型号" /> |
| | | <el-table-column prop="deviceName" label="设备名称" /> |
| | | <el-table-column prop="deviceSn" label="设备编码" /> |
| | | <el-table-column prop="deployLocation" label="部署位置" /> |
| | | <el-table-column prop="manufacturer" label="厂商" /> |
| | | <el-table-column prop="contactPhone" label="联系方式" /> |
| | | <el-table-column prop="sceneName" label="所属场景" /> |
| | | <el-table-column label="操作"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('edit', row)" type="warning">配置接口</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div> |
| | | <el-pagination |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | | <div class="ztzf-table-content ztzf-table-content-bg"> |
| | | <el-table class="ztzf-data-cockpit-table" :data="list"> |
| | | <el-table-column type="index" width="64" show-overflow-tooltip label="序号" /> |
| | | <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceType, dictObj.deviceType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceModel" show-overflow-tooltip label="设备型号" /> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" /> |
| | | <el-table-column prop="deviceSn" show-overflow-tooltip label="设备编码" /> |
| | | <el-table-column prop="deployLocation" show-overflow-tooltip label="部署位置" /> |
| | | <el-table-column prop="manufacturer" show-overflow-tooltip label="厂商" /> |
| | | <el-table-column prop="contactPhone" show-overflow-tooltip label="联系方式" /> |
| | | <el-table-column prop="sceneName" show-overflow-tooltip label="所属场景" /> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('edit', row)" type="warning">配置接口</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-pagination"> |
| | | <el-pagination |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | layout="total, prev, pager, next, sizes" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | </div> |
| | | |
| | | <FormDiaLog v-if="dialogVisible" v-model="dialogVisible" ref="dialogRef" @success="getList" /> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { RefreshRight, Search } from '@element-plus/icons-vue' |
| | | import { nextTick, onMounted, provide, ref } from 'vue' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz' |
| | |
| | | |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="titleEnum[dialogMode]"> |
| | | <div v-if="readonly"> |
| | | <template> |
| | | <el-dialog |
| | | class="ztzf-page-view-dialog" |
| | | v-model="visible" |
| | | :title="titleEnum[dialogMode]" |
| | | destroy-on-close |
| | | :close-on-click-modal="false" |
| | | @closed="handleClosed" |
| | | > |
| | | <div v-if="readonly" class="detail-container"> |
| | | <div class="detail-title">调度详情</div> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <div>设备名称: {{ formData.deviceName }}</div> |
| | | <div class="label">设备名称</div> |
| | | <div class="val">{{ formData.deviceName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>设备编码: {{ formData.deviceSn }}</div> |
| | | <div class="label">设备编码</div> |
| | | <div class="val">{{ formData.deviceSn }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>场景: {{ formData.defenseSceneName }}</div> |
| | | <div class="label">场景</div> |
| | | <div class="val">{{ formData.defenseSceneName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>区域: {{ formData.areaDivideName }}</div> |
| | | <div class="label">区域</div> |
| | | <div class="val">{{ formData.areaDivideName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>调度人员: {{ formData.dispatchUser }}</div> |
| | | <div class="label">调度人员</div> |
| | | <div class="val">{{ formData.dispatchUser }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>调度位置: {{ formData.longitude }}, {{ formData.latitude }}</div> |
| | | <div class="label">调度位置</div> |
| | | <div class="val">{{ formData.longitude }}, {{ formData.latitude }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>调度日期: {{ formData.dispatchStartTime }} ~ {{ formData.dispatchEndTime }}</div> |
| | | <div class="label">调度日期</div> |
| | | <div class="val">{{ formData.dispatchStartTime }} ~ {{ formData.dispatchEndTime }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div>调度内容: {{ formData.dispatchContent }}</div> |
| | | <div class="label">调度内容</div> |
| | | <div class="val">{{ formData.dispatchContent }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div>调度结果: {{ formData.dispatchResult }}</div> |
| | | <div class="label">调度结果</div> |
| | | <div class="val">{{ formData.dispatchResult }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div>处理措施: {{ formData.disposeMeasure }}</div> |
| | | <div class="label">处理措施</div> |
| | | <div class="val">{{ formData.disposeMeasure }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <el-form v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly" label-width="100px"> |
| | | <el-form |
| | | v-else |
| | | ref="formRef" |
| | | :model="formData" |
| | | :rules="rules" |
| | | :disabled="readonly" |
| | | label-width="100px" |
| | | class="dialog-form" |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备" prop="deviceId"> |
| | | <el-select v-model="formData.deviceId" placeholder="请选择" clearable @change="handleDeviceChange"> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.deviceId" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="handleDeviceChange" |
| | | > |
| | | <el-option v-for="item in deviceList" :key="item.id" :label="item.deviceName" :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备编码" prop="deviceSn"> |
| | | <el-input v-model="formData.deviceSn" disabled placeholder="选择设备后自动带出" /> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="formData.deviceSn" |
| | | disabled |
| | | placeholder="选择设备后自动带出" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="场景" prop="defenseSceneId"> |
| | | <el-select v-model="formData.defenseSceneId" placeholder="请选择" clearable @change="handleSceneChange"> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.defenseSceneId" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="handleSceneChange" |
| | | > |
| | | <el-option v-for="item in sceneList" :key="item.id" :label="item.sceneName" :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="区域" prop="areaDivideId"> |
| | | <el-select |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="formData.areaDivideId" |
| | | placeholder="请先选择场景" |
| | | clearable |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="调度人员" prop="dispatchUser"> |
| | | <el-input v-model="formData.dispatchUser" maxlength="50" placeholder="请输入" clearable /> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="formData.dispatchUser" |
| | | maxlength="50" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="调度日期" prop="dispatchDateRange"> |
| | | <el-date-picker |
| | | class="ztzf-data-cockpit-date-picker" |
| | | popper-class="ztzf-data-cockpit-date-picker-popper" |
| | | v-model="formData.dispatchDateRange" |
| | | type="datetimerange" |
| | | range-separator="至" |
| | |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="调度位置" prop="longitude"> |
| | | <!-- <el-button @click="selectLocation" style="width: 100%">--> |
| | | <!-- <el-button @click="selectLocation" style="width: 100%">--> |
| | | <el-button style="width: 100%"> |
| | | {{ |
| | | formData.longitude && formData.latitude ? `${formData.longitude}, ${formData.latitude}` : '选择区域后自动带出' |
| | |
| | | <el-col :span="24"> |
| | | <el-form-item label="调度内容" prop="dispatchContent"> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="formData.dispatchContent" |
| | | type="textarea" |
| | | :rows="3" |
| | |
| | | <el-col :span="24"> |
| | | <el-form-item label="调度结果" prop="dispatchResult"> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="formData.dispatchResult" |
| | | type="textarea" |
| | | :rows="3" |
| | |
| | | <el-col :span="24"> |
| | | <el-form-item label="处理措施" prop="disposeMeasure"> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | | v-model="formData.disposeMeasure" |
| | | type="textarea" |
| | | :rows="3" |
| | |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit"> |
| | | 确定 |
| | | <el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button |
| | | color="#284FE3" |
| | | v-if="!readonly" |
| | | type="primary" |
| | | :loading="submitting" |
| | | :disabled="submitting" |
| | | @click="handleSubmit" |
| | | > |
| | | 保存 |
| | | </el-button> |
| | | </template> |
| | | |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, nextTick, ref, inject } from 'vue' |
| | | import { computed, nextTick, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fwTaskScheduleDetailApi, fwTaskScheduleSubmitApi } from './taskScheduleApi' |
| | | import { fwAreaDivideListApi } from '@/views/areaManage/partition/partitionApi' |
| | |
| | | visible.value = false |
| | | } |
| | | |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | |
| | | <template> |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="ztzf-page-history-search"> |
| | | <el-form-item label="设备名称" prop="deviceId"> |
| | | <el-select |
| | | class="ztzf-data-cockpit-search-input" |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="searchParams.deviceId" |
| | | placeholder="请选择" |
| | | clearable |
| | |
| | | <el-option v-for="item in deviceList" :key="item.id" :label="item.deviceName" :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="设备类型" prop="deviceType"> |
| | | <el-select |
| | | class="ztzf-data-cockpit-search-input" |
| | | class="ztzf-data-cockpit-select" |
| | | popper-class="ztzf-data-cockpit-select-popper" |
| | | v-model="searchParams.deviceType" |
| | | placeholder="请选择" |
| | | clearable |
| | |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="设备编号" prop="deviceSn"> |
| | | <el-input |
| | | class="ztzf-data-cockpit-search-input" |
| | |
| | | |
| | | <div class="ztzf-table-toolbar"> |
| | | <el-button :icon="Plus" color="#284FE3" type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | <el-button :icon="Delete" color="#1A2652" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | |
| | | <el-table-column prop="deviceName" show-overflow-tooltip width="140" label="设备名称" /> |
| | | <el-table-column prop="deviceSn" show-overflow-tooltip width="140" label="设备编码" /> |
| | | <!-- <el-table-column prop="deviceStatus" show-overflow-tooltip width="100" label="设备状态"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceStatus, dictObj.deviceStatus) }} |
| | | </template> |
| | | </el-table-column>--> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceStatus, dictObj.deviceStatus) }} |
| | | </template> |
| | | </el-table-column>--> |
| | | <el-table-column prop="areaName" show-overflow-tooltip width="120" label="区域" /> |
| | | <el-table-column prop="defenseZoneName" show-overflow-tooltip width="120" label="场景" /> |
| | | <el-table-column show-overflow-tooltip width="200" label="调度位置"> |
| | | <el-table-column show-overflow-tooltip label="调度位置"> |
| | | <template v-slot="{ row }">{{ row.longitude }}, {{ row.latitude }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="dispatchUser" show-overflow-tooltip width="100" label="调度人员" /> |
| | | <el-table-column show-overflow-tooltip width="180" label="调度日期"> |
| | | <el-table-column show-overflow-tooltip label="调度日期"> |
| | | <template v-slot="{ row }"> |
| | | {{ formatDispatchDate(row) }} |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search, RefreshRight, Plus } from '@element-plus/icons-vue' |
| | | import { Search, RefreshRight, Plus, Delete } from '@element-plus/icons-vue' |
| | | import { nextTick, onMounted, ref, provide } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { fwTaskSchedulePageApi, fwTaskScheduleRemoveApi } from './taskScheduleApi' |
| | |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | |
| | | params.value.ai_types = val |
| | | handleSearch() |
| | | } |
| | | const loading = ref(false) |
| | | const loading = ref(true) |
| | | const list = ref() |
| | | const params = ref({ |
| | | way_line_job_info_id: null, |
| | |
| | | }) |
| | | const isShowAddTask = defineModel('show') |
| | | |
| | | const loading = ref(false) |
| | | const loading = ref(true) |
| | | |
| | | // 禁用当天之前的日期 |
| | | const disabledDate = time => { |
| | |
| | | const deviseName = ref(null) |
| | | const devisejobInfoId = ref('') |
| | | const devisebatchNo = ref(null) |
| | | const loading = ref(false) |
| | | const loading = ref(true) |
| | | const isShowContinuingToFly = code => { |
| | | return ContinuingToFly.find(i => i.code === code) |
| | | } |
| | |
| | | dkbh: '', |
| | | patchesName: '', |
| | | }); |
| | | const loading = ref(false); |
| | | const loading = ref(true); |
| | | const treeData = ref([]); |
| | | const treeAllData = ref([]); |
| | | // 存储过滤后显示的节点ID(返回true的节点) |
| | |
| | | geo_data: '', |
| | | |
| | | }); |
| | | const loading = ref(false); |
| | | const loading = ref(true); |
| | | const detailData = ref(null); |
| | | const fenceArea = ref(0); |
| | | detailData.value = layerParams.value.editDetailData; |
| | |
| | | </el-form> |
| | | |
| | | <div class="ztzf-table-toolbar"> |
| | | <el-button :icon="Download" type="primary" @click="exportFile" :loading="exportLoading">导出</el-button> |
| | | <el-button :icon="Download" color="#1A2652" type="primary" @click="exportFile" :loading="exportLoading">导出</el-button> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | |
| | | <el-table class="ztzf-data-cockpit-table" :data="list"> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="droneName" show-overflow-tooltip width="140" label="无人机名称" /> |
| | | <el-table-column prop="droneSerialNo" show-overflow-tooltip width="160" label="无人机序列号" /> |
| | | <el-table-column prop="alarmTime" show-overflow-tooltip width="160" label="告警时间" /> |
| | | <el-table-column prop="areaName" show-overflow-tooltip width="120" label="区域" /> |
| | | <el-table-column prop="triggerReason" show-overflow-tooltip width="160" label="触发原因" /> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip width="160" label="侦测反制设备" /> |
| | | <el-table-column prop="droneType" show-overflow-tooltip width="120" label="设备类型"> |
| | | <el-table-column prop="droneSerialNo" show-overflow-tooltip label="无人机序列号" /> |
| | | <el-table-column prop="alarmTime" show-overflow-tooltip label="告警时间" /> |
| | | <el-table-column prop="areaName" show-overflow-tooltip label="区域" /> |
| | | <el-table-column prop="triggerReason" show-overflow-tooltip label="触发原因" /> |
| | | <el-table-column prop="deviceName" show-overflow-tooltip label="侦测反制设备" /> |
| | | <el-table-column prop="droneType" show-overflow-tooltip label="设备类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDeviceTypeName(row.droneType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceSn" show-overflow-tooltip width="140" label="设备编码" /> |
| | | <el-table-column show-overflow-tooltip width="120" label="设备状态"> |
| | | <el-table-column prop="deviceSn" show-overflow-tooltip label="设备编码" /> |
| | | <el-table-column show-overflow-tooltip label="设备状态"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDictLabel(row.deviceStatus, dictObj.deviceStatus) }} |
| | | </template> |
| | |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close> |
| | | <div class="bodyBox"> |
| | | <div class="leftMap ztzf-cesium" id="leftMapContainer"></div> |
| | | <div class="rightInfo"> |
| | | <div> |
| | | <div>无人机名称:{{ formData.droneName }}</div> |
| | | <div>序列号: {{ formData.serialNo }}</div> |
| | | <div>告警时间: {{ formData.alarmTime }}</div> |
| | | <div>触发原因: {{ formData.triggerType }}</div> |
| | | <div>停留时长: {{ formData.stayDuration }}</div> |
| | | <template> |
| | | <el-dialog class="ztzf-page-map-view-dialog" v-model="visible" :show-close="false" |
| | | :close-on-click-modal="false" @closed="handleClosed" destroy-on-close> |
| | | <div class="dialog-container"> |
| | | <div class="left-container"> |
| | | <div class="leftMap ztzf-cesium" id="leftMapContainer"></div> |
| | | </div> |
| | | <div class="right-container"> |
| | | <div class="header">{{ dialogTitle }}</div> |
| | | <div class="dialog-container"> |
| | | <div class="detail-title">轨迹信息</div> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <div class="label">无人机名称</div> |
| | | <div class="val">{{ formData.droneName }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">序列号</div> |
| | | <div class="val">{{ formData.serialNo }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">告警时间</div> |
| | | <div class="val">{{ formData.alarmTime }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">触发原因</div> |
| | | <div class="val">{{ formData.triggerType }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="label">停留时长</div> |
| | | <div class="val">{{ formData.stayDuration }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | <div class="detail-title">轨迹点</div> |
| | | <div class="ztzf-table-container"> |
| | | <div class="ztzf-table-content"> |
| | | <el-table class="ztzf-data-cockpit-table" :data="list"> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column label="经纬度"> |
| | | <template #default="{ row }">{{ row.longitude }},{{ row.latitude }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="时间" /> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <el-table :data="list"> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column label="经纬度"> |
| | | <template #default="{ row }">{{ row.longitude }},{{ row.latitude }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="时间" /> |
| | | </el-table> |
| | | <div class="footer"> |
| | | <el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { computed, nextTick, ref } from 'vue' |
| | | import { fwDroneFlightRecordDetailApi } from '@/views/recordManage/historyTracks/fwDroneFlightRecord' |
| | | import { fwDroneFlightRecordDetailPageApi } from '@/views/recordManage/historyTracks/flyTrajectory' |
| | | import { PublicCesium } from '@/utils/cesium/publicCesium' |
| | |
| | | }) |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | function handleCancel () { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | async function loadDetail () { |
| | | if (!formData.value.id) return |
| | | const res = await fwDroneFlightRecordDetailApi({ id: formData.value.id }) |
| | | const res1 = await fwDroneFlightRecordDetailPageApi({ flightRecordId: formData.value.id }) |
| | |
| | | } |
| | | |
| | | // 角度转c3 |
| | | function degreesToC3({ longitude, latitude, height = 0 }) { |
| | | function degreesToC3 ({ longitude, latitude, height = 0 }) { |
| | | return Cesium.Cartesian3.fromDegrees(longitude, latitude, height) |
| | | } |
| | | // 渲染航线 |
| | | function drawFlightPath() { |
| | | function drawFlightPath () { |
| | | const positions = list.value.map(p => degreesToC3(p)) |
| | | droneLineEntity && geometricSource.entities.remove(droneLineEntity) |
| | | const color = Cesium.Color.fromCssColorString('#00D690') |
| | |
| | | } |
| | | |
| | | // 关闭后重置 |
| | | function handleClosed() { |
| | | function handleClosed () { |
| | | formData.value = initForm() |
| | | list.value = [] |
| | | viewer = null |
| | | geometricSource = null |
| | | droneLineEntity = null |
| | | } |
| | | |
| | | let viewer, geometricSource, droneLineEntity |
| | | function initMap() { |
| | | function initMap () { |
| | | if (viewer) return |
| | | const publicCesiumInstance = new PublicCesium({ |
| | | dom: 'leftMapContainer', |
| | | flatMode: false, |
| | |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | async function open ({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | visible.value = true |
| | | await nextTick(() => { |
| | | initMap() |
| | | }) |
| | | await nextTick() |
| | | initMap() |
| | | if (dialogMode.value === 'add') { |
| | | formData.value = initForm() |
| | | } else { |
| | |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .bodyBox { |
| | | display: flex; |
| | | .rightInfo { |
| | | width: 50%; |
| | | height: 500px; |
| | | } |
| | | .leftMap { |
| | | width: 50%; |
| | | height: 500px; |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | <style scoped lang="scss"></style> |
| | |
| | | </el-form> |
| | | |
| | | <div class="ztzf-table-toolbar"> |
| | | <el-button :icon="Download" type="primary" @click="exportFile" :loading="exportLoading">导出</el-button> |
| | | <el-button :icon="Download" color="#1A2652" type="primary" @click="exportFile" :loading="exportLoading">导出</el-button> |
| | | </div> |
| | | |
| | | <div class="ztzf-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | |
| | | <el-table class="ztzf-data-cockpit-table" :data="list"> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="droneName" show-overflow-tooltip width="140" label="无人机名称" /> |
| | | <el-table-column prop="serialNo" show-overflow-tooltip width="160" label="序列号" /> |
| | | <el-table-column prop="alarmTime" show-overflow-tooltip width="160" label="告警时间" /> |
| | | <el-table-column prop="areaName" show-overflow-tooltip width="120" label="区域" /> |
| | | <el-table-column prop="triggerType" show-overflow-tooltip width="160" label="触发原因" /> |
| | | <el-table-column show-overflow-tooltip width="140" label="停留时长"> |
| | | <el-table-column prop="serialNo" show-overflow-tooltip label="序列号" /> |
| | | <el-table-column prop="alarmTime" show-overflow-tooltip label="告警时间" /> |
| | | <el-table-column prop="areaName" show-overflow-tooltip label="区域" /> |
| | | <el-table-column prop="triggerType" show-overflow-tooltip label="触发原因" /> |
| | | <el-table-column show-overflow-tooltip label="停留时长"> |
| | | <template v-slot="{ row }"> |
| | | {{ formatStayDuration(row.stayDuration) }} |
| | | </template> |
| | |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const loading = ref(true) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dateRange = ref([]) |
| | |
| | | const viewInstance = shallowRef(null); |
| | | const homeViewer = shallowRef(null); |
| | | let tbJwdList = []; |
| | | const loading = ref(false); |
| | | const loading = ref(true); |
| | | const tableLoading = ref(true); |
| | | const tableData = ref([]); |
| | | const AlltableData = ref([]); |
| | |
| | | const detailVisible = ref(false) |
| | | const currentDetail = ref({}) |
| | | const departmentUsers = ref({}) |
| | | const loading = ref(false) |
| | | const loading = ref(true) |
| | | const globalCounts = ref({}) |
| | | const mapLoaded = ref(false) |
| | | const isFetching = ref(false) |
| | |
| | | }); |
| | | const emit = defineEmits(['update:modelValue', 'dispatch-success', 'dispatch-error']); |
| | | const formRef = ref(null); // 表单引用 |
| | | const loading = ref(false); |
| | | const loading = ref(true); |
| | | const form = ref({ |
| | | department: '', |
| | | handler: '' |