吉安感知网项目-前端
shuishen
2026-01-09 8a7da61fc914ee49d973daf4d649dc183a02ef23
feat:退出登录跳转地址跳转,样式微调
5 files modified
1 files added
298 ■■■■■ changed files
applications/drone-command/src/store/modules/user.js 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/styles/common.scss 1 ●●●● patch | view | raw | blame | history
applications/drone-command/src/styles/element-ui.scss 8 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/styles/sidebar.scss 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/views/api.txt patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/DeviceHistoryDialog.vue 285 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/store/modules/user.js
@@ -275,7 +275,7 @@
          const env = import.meta.env.VITE_APP_ENV
          const adminUrl = import.meta.env.VITE_APP_DASHBOARD_URL
          env === 'development'
            ? window.location.href = "/manage/login"
            ? window.location.href = "/drone-command/login"
            : window.location.replace(`${adminUrl}#/login`)
        })
      }
applications/drone-command/src/styles/common.scss
@@ -71,6 +71,7 @@
    padding-top: 109px;
    width: 160px;
    height: 100%;
    box-sizing: border-box;
    .avue-sidebar {
applications/drone-command/src/styles/element-ui.scss
@@ -1019,4 +1019,12 @@
            }
        }
    }
}
.ztzf-data-cockpit-dialog {
    width: 1222px;
    height: 835px;
    background: #1A1A2A;
    border-radius: 6px 6px 6px 6px;
    border: 1px solid #2E2E46;
}
applications/drone-command/src/styles/sidebar.scss
@@ -17,7 +17,7 @@
  }
  .avue-menu {
    height: calc(100% - #{$top_height});
    height: calc(100% - 42px);
  }
  &--tip {
applications/drone-command/src/views/api.txt
applications/drone-command/src/views/dataCockpit/components/DeviceHistoryDialog.vue
@@ -1,67 +1,94 @@
<template>
    <el-dialog
        class="ztzf-dialog-mange data-cockpit-history-dialog"
        class="ztzf-data-cockpit-dialog"
        append-to-body
        v-model="visibleModel"
        :title="dialogTitle"
        width="1100px"
        :close-on-click-modal="false"
        :destroy-on-close="true"
    >
        <div class="dialog-body">
            <div class="device-summary">
                <div class="item">
                    <span class="label">设备名称</span>
                    <span class="value">{{ device?.name || '反制设备名称' }}</span>
                </div>
                <div class="item">
                    <span class="label">类型</span>
                    <span class="value">{{ device?.type || '-' }}</span>
                </div>
                <div class="item">
                    <span class="label">厂商</span>
                    <span class="value">{{ device?.vendor || '-' }}</span>
                </div>
                <div class="item">
                    <span class="label">状态</span>
                    <span class="value">{{ device?.statusText || '-' }}</span>
                </div>
            </div>
            <el-form ref="queryParamsRef" :model="searchParams" class="history-search">
                <el-row :gutter="12">
                    <el-col :span="5">
                        <el-form-item label="关键字" prop="keyword">
                            <el-input v-model="searchParams.keyword" placeholder="名称/序列号" clearable @clear="handleSearch" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="5">
                        <el-form-item label="日期" prop="dateRange">
                            <el-date-picker
                                v-model="searchParams.dateRange"
                                type="daterange"
                                range-separator="至"
                                start-placeholder="开始日期"
                                end-placeholder="结束日期"
                                value-format="YYYY/MM/DD"
                                @change="handleSearch"
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="5">
                        <el-form-item label="区域" prop="area">
                            <el-tree-select
                                v-model="searchParams.area"
                                :data="areaTree"
                                :props="areaTreeProps"
                                node-key="value"
                                check-strictly
                                clearable
                                placeholder="请选择"
                                @change="handleSearch"
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="5">
                        <el-form-item label="无人机类型" prop="droneType">
                            <el-select
                                v-model="searchParams.droneType"
                                placeholder="请选择"
                                clearable
                                @change="handleSearch"
                            >
                                <el-option v-for="item in droneTypeOptions" :key="item" :label="item" :value="item" />
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="4" class="history-search-actions">
                        <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>
            <div class="table">
                <div class="thead">
                    <div class="cell index">序号</div>
                    <div class="cell">无人机名称</div>
                    <div class="cell">无人机序列号</div>
                    <div class="cell">无人机类型</div>
                    <div class="cell">区域</div>
                    <div class="cell">数据来源</div>
                    <div class="cell">信号频段</div>
                    <div class="cell">发现时间</div>
                    <div class="cell">停留时间</div>
                    <div class="cell">反制方式</div>
                </div>
                <div class="tbody">
                    <div class="tr" v-for="(row, index) in historyList" :key="row.id">
                        <div class="cell index">{{ index + 1 }}</div>
                        <div class="cell">{{ row.droneName }}</div>
                        <div class="cell">{{ row.serialNumber }}</div>
                        <div class="cell">{{ row.droneType }}</div>
                        <div class="cell">{{ row.area }}</div>
                        <div class="cell">{{ row.dataSource }}</div>
                        <div class="cell">{{ row.frequency }}</div>
                        <div class="cell">{{ row.discoveredAt }}</div>
                        <div class="cell">{{ row.stayTime }}</div>
                        <div class="cell">{{ row.counterMethod }}</div>
                    </div>
                </div>
            <el-table v-loading="loading" :data="pagedList" height="360" class="history-table">
                <el-table-column type="index" width="60" label="序号" />
                <el-table-column prop="droneName" label="无人机名称" min-width="120" />
                <el-table-column prop="serialNumber" label="无人机序列号" min-width="140" />
                <el-table-column prop="droneType" label="无人机类型" min-width="110" />
                <el-table-column prop="area" label="区域" min-width="90" />
                <el-table-column prop="dataSource" label="数据来源" min-width="110" />
                <el-table-column prop="frequency" label="信号频段" min-width="100" />
                <el-table-column prop="discoveredAt" label="发现时间" min-width="150" />
                <el-table-column prop="stayTime" label="停留时间" min-width="110" />
                <el-table-column prop="counterMethod" label="反制方式" min-width="110" />
            </el-table>
            <div class="history-pagination">
                <el-pagination
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    :total="total"
                />
            </div>
        </div>
    </el-dialog>
</template>
<script setup>
import { computed } from 'vue'
import { computed, ref } from 'vue'
const props = defineProps({
    modelValue: {
@@ -84,6 +111,36 @@
const dialogTitle = computed(() => {
    return `反制设备名称 ${props.device?.name || ''}`.trim()
})
const initSearchParams = () => ({
    keyword: '',
    dateRange: [],
    area: '',
    droneType: '',
    current: 1,
    size: 6
})
const searchParams = ref(initSearchParams())
const queryParamsRef = ref(null)
const loading = ref(false)
const areaTree = ref([
    {
        label: '古村区',
        value: '古村区'
    },
    {
        label: '新区',
        value: '新区'
    },
    {
        label: '产业园',
        value: '产业园'
    }
])
const areaTreeProps = {
    label: 'label',
    children: 'children'
}
const historyList = computed(() => {
    const dataSource = props.device?.name || '侦测反制设备名称'
@@ -162,6 +219,50 @@
        }
    ]
})
const droneTypeOptions = computed(() => {
    const types = historyList.value.map((item) => item.droneType).filter(Boolean)
    return Array.from(new Set(types))
})
const filteredList = computed(() => {
    const { keyword, dateRange, area, droneType } = searchParams.value
    const [startDate, endDate] = dateRange || []
    return historyList.value.filter((item) => {
        const keywordMatch =
            !keyword || item.droneName.includes(keyword) || item.serialNumber.includes(keyword)
        const typeMatch = !droneType || item.droneType === droneType
        const areaMatch = !area || item.area.includes(area)
        const dateMatch =
            !startDate || !endDate || isWithinDateRange(item.discoveredAt, startDate, endDate)
        return keywordMatch && typeMatch && areaMatch && dateMatch
    })
})
const total = computed(() => filteredList.value.length)
const pagedList = computed(() => {
    const { current, size } = searchParams.value
    const start = (current - 1) * size
    return filteredList.value.slice(start, start + size)
})
function handleSearch() {
    searchParams.value.current = 1
}
function resetForm() {
    queryParamsRef.value?.resetFields()
    searchParams.value.current = 1
}
function isWithinDateRange(value, start, end) {
    const dateValue = new Date(value)
    const startDate = new Date(`${start} 00:00:00`)
    const endDate = new Date(`${end} 23:59:59`)
    return dateValue >= startDate && dateValue <= endDate
}
</script>
<style lang="scss" scoped>
@@ -172,74 +273,36 @@
    color: #C3C3DD;
}
.device-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 16px 24px;
    .item {
        display: flex;
        align-items: center;
        gap: 8px;
        font-size: 14px;
        .label {
            color: #8B8BA7;
        }
        .value {
            color: #FFFFFF;
        }
    }
}
.table {
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 6px;
    overflow: hidden;
}
.thead,
.tr {
    display: grid;
    grid-template-columns: 60px 1.1fr 1.1fr 0.9fr 0.8fr 1.2fr 0.9fr 1.3fr 0.9fr 0.9fr;
    align-items: center;
}
.thead {
    background: rgba(20, 24, 48, 0.9);
    color: #FFFFFF;
    font-size: 13px;
    height: 42px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.tbody {
    max-height: 360px;
    overflow-y: auto;
.history-search {
    padding: 8px 12px 4px;
    background: rgba(10, 14, 34, 0.6);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 6px;
}
.tr {
    font-size: 12px;
    color: #C3C3DD;
    height: 40px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    &:nth-child(2n) {
        background: rgba(255, 255, 255, 0.02);
    }
.history-search :deep(.el-date-editor),
.history-search :deep(.el-select),
.history-search :deep(.el-tree-select) {
    width: 100%;
}
.cell {
    padding: 0 10px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
.history-search-actions :deep(.el-form-item__content) {
    justify-content: flex-end;
    gap: 8px;
}
    &.index {
        text-align: center;
        color: #86909C;
    }
.history-table {
    margin-top: 8px;
    --el-table-border-color: rgba(255, 255, 255, 0.08);
    --el-table-header-bg-color: rgba(20, 24, 48, 0.9);
    --el-table-row-hover-bg-color: rgba(255, 255, 255, 0.03);
    --el-table-text-color: #C3C3DD;
    --el-table-header-text-color: #FFFFFF;
}
.history-pagination {
    display: flex;
    justify-content: flex-end;
    padding-top: 8px;
}
</style>