You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
14 KiB
482 lines
14 KiB
7 months ago
|
<template>
|
||
|
<div class="flex-col gap-16 wh-full">
|
||
|
<el-button type="primary" @click="onBack" class="w-150px">
|
||
5 months ago
|
<i class="i-line-md:arrow-left"></i>返回站点数据
|
||
7 months ago
|
</el-button>
|
||
4 months ago
|
<EdfsWrap
|
||
|
:title="isonLineTransfer ? `在线设备列表` : `历史设备列表`"
|
||
|
class="flex-1"
|
||
|
useScrollBar
|
||
|
:shapeColor="isonLineTransfer ? '#4B9E5F' : '#F1BF63'"
|
||
|
>
|
||
5 months ago
|
<template #title-right>
|
||
5 months ago
|
<template v-if="env.VITE_APP_ENV == 'local'">
|
||
|
<template v-if="isBatchTransfer || isBatchUpgrade">
|
||
4 months ago
|
<el-button type="primary" @click="onBatchSave">
|
||
|
确定{{ batchText }}
|
||
|
</el-button>
|
||
1 month ago
|
<el-button type="info" @click="onBatchCancel"> 取消</el-button>
|
||
5 months ago
|
</template>
|
||
|
<template v-else>
|
||
4 months ago
|
<el-button type="primary" @click="onBatchTransfer">
|
||
1 month ago
|
<i class="i-mdi:database-arrow-right-outline mr-1"/>
|
||
4 months ago
|
{{ isonLineTransfer ? '数据迁移' : '数据导出' }}
|
||
|
</el-button>
|
||
|
<el-button v-if="isonLineTransfer" type="primary" @click="onBatchUpgrade">
|
||
1 month ago
|
<i class="i-codicon:chip mr-1"/>批量升级
|
||
5 months ago
|
</el-button>
|
||
|
</template>
|
||
7 months ago
|
</template>
|
||
|
</template>
|
||
|
<div class="device-list-wrap">
|
||
5 months ago
|
<el-checkbox-group v-model="checkDeviceList">
|
||
7 months ago
|
<div class="device-item" v-for="item in devices">
|
||
|
<div class="device-item-header">
|
||
|
<div class="flex items-center">
|
||
4 months ago
|
<el-checkbox
|
||
|
:value="item.sn"
|
||
|
v-if="(isBatchTransfer || isBatchUpgrade) && item.status !== '离线'"
|
||
|
>
|
||
7 months ago
|
<div>设备ID: {{ item.sn }}</div>
|
||
|
</el-checkbox>
|
||
1 month ago
|
<div v-else
|
||
|
class="h-32 leading-32px">
|
||
|
<div class="overflow-hidden text-ellipsis whitespace-nowrap w-140">设备ID:
|
||
|
{{ item.sn }}
|
||
|
</div>
|
||
7 months ago
|
</div>
|
||
|
</div>
|
||
4 months ago
|
<div
|
||
1 month ago
|
class="flex items-center gap-col-1"
|
||
4 months ago
|
v-if="!(isBatchTransfer || isBatchUpgrade)"
|
||
|
>
|
||
5 months ago
|
<template v-if="env.VITE_APP_ENV == 'local'">
|
||
4 months ago
|
<el-tooltip
|
||
|
:content="isonLineTransfer ? '数据迁移' : '数据导出'"
|
||
|
v-if="isonLineTransfer ? item.status === '在线' : true"
|
||
|
>
|
||
|
<i
|
||
|
class="i-mdi:database-arrow-right-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
|
||
|
@click="onBatchTransferSave([item])"
|
||
1 month ago
|
/>
|
||
5 months ago
|
</el-tooltip>
|
||
4 months ago
|
<el-tooltip
|
||
|
content="固件升级"
|
||
|
v-if="isonLineTransfer && item.status === '在线'"
|
||
|
>
|
||
|
<i
|
||
|
class="i-codicon:chip :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
|
||
|
@click="onFirmwareUpload([item])"
|
||
1 month ago
|
/>
|
||
5 months ago
|
</el-tooltip>
|
||
|
</template>
|
||
|
|
||
1 month ago
|
<el-tooltip content="数据详情">
|
||
|
<i
|
||
7 months ago
|
class="i-material-symbols:info-outline :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
|
||
4 months ago
|
@click="onDeviceDetails(item)"
|
||
1 month ago
|
/>
|
||
|
</el-tooltip>
|
||
|
<el-tooltip content="拓扑详情">
|
||
|
<i
|
||
|
class="i-hugeicons:node-edit :hover:color-[#8ACE6A] color-[#4B9E5F] cursor-pointer text-20px"
|
||
|
@click="onTopology(item)"
|
||
|
/>
|
||
7 months ago
|
</el-tooltip>
|
||
1 month ago
|
|
||
7 months ago
|
</div>
|
||
|
</div>
|
||
|
|
||
5 months ago
|
<div class="device-item-body relative">
|
||
5 months ago
|
<template v-if="isonLineTransfer">
|
||
7 months ago
|
<template v-for="key in Object.keys(onlineDeviceMap)">
|
||
5 months ago
|
<div class="info-item" v-if="isonLineTransfer && key === 'status'">
|
||
7 months ago
|
<div>{{ onlineDeviceMap.status }}:</div>
|
||
|
<el-tag :type="item.status === '在线' ? 'success' : 'danger'">
|
||
|
{{ item.status }}
|
||
|
</el-tag>
|
||
|
</div>
|
||
|
<div class="info-item" v-else>
|
||
|
<div>{{ onlineDeviceMap[key as keyof typeof onlineDeviceMap] }}:</div>
|
||
|
<div>{{ item[key] }}</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
</template>
|
||
|
<template v-else>
|
||
|
<template v-for="key in Object.keys(offlineDeviceMap)">
|
||
|
<div class="info-item" v-if="key === 'create_time'">
|
||
|
<div>
|
||
|
{{ offlineDeviceMap[key as keyof typeof offlineDeviceMap] }}:
|
||
|
</div>
|
||
|
<div>{{ dayjs(item[key]).format('YYYY-MM-DD HH:mm:ss') }}</div>
|
||
|
</div>
|
||
|
<div class="info-item" v-else>
|
||
|
<div>
|
||
|
{{ offlineDeviceMap[key as keyof typeof offlineDeviceMap] }}:
|
||
|
</div>
|
||
|
<div>{{ item[key] }}</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
</template>
|
||
|
</div>
|
||
|
</div>
|
||
|
</el-checkbox-group>
|
||
|
</div>
|
||
|
</EdfsWrap>
|
||
|
</div>
|
||
|
|
||
4 months ago
|
<OnLineTransferDlg
|
||
|
ref="onLineTransferDlgRef"
|
||
|
@on-save="onLineDeviceTransfer"
|
||
|
:is-batch-transfer="isBatchTransfer"
|
||
|
/>
|
||
|
<OffTransferDlg
|
||
|
ref="offTransferDlgRef"
|
||
|
:isBatchTransfer="false"
|
||
|
:siteInfo="siteInfo"
|
||
|
@on-save="onOffDeviceTransfer"
|
||
|
/>
|
||
|
<DeviceDrawer
|
||
|
v-model="isShowDetails"
|
||
|
ref="deviceDrawerRef"
|
||
|
:siteInfo="siteInfo"
|
||
|
:is-transfer="isonLineTransfer"
|
||
|
/>
|
||
7 months ago
|
</template>
|
||
|
|
||
|
<script setup lang="ts">
|
||
|
import dayjs from 'dayjs'
|
||
5 months ago
|
import OnLineTransferDlg from './components/onLineTransferDlg.vue'
|
||
5 months ago
|
import OffTransferDlg from './components/offTransferDlg.vue'
|
||
7 months ago
|
import { useTransferDataStore } from '@/stores/transferData'
|
||
|
import { storeToRefs } from 'pinia'
|
||
1 month ago
|
import type { IDevice, IOfflineDevice, IOnlineDevice } from '../type'
|
||
7 months ago
|
import { useMessage } from '@/composables/useMessage'
|
||
5 months ago
|
import { getDeviceList, type ISite } from '@/api/module/transfer'
|
||
7 months ago
|
import DeviceDrawer from './components/deviceDrawer.vue'
|
||
5 months ago
|
|
||
5 months ago
|
import { getFirmwarePath } from '@/api/module/firmware'
|
||
4 months ago
|
import { createTask, type TaskCreateParams } from '@/api/module/taks'
|
||
2 months ago
|
import EdfsWrap from "@/components/Edfs-wrap.vue";
|
||
1 month ago
|
|
||
5 months ago
|
const env = import.meta.env
|
||
5 months ago
|
const onLineTransferDlgRef = ref<typeof OnLineTransferDlg>()
|
||
7 months ago
|
const router = useRouter()
|
||
|
const route = useRoute()
|
||
5 months ago
|
const siteInfo = ref<ISite>(
|
||
7 months ago
|
route.query.site ? JSON.parse(route.query.site as string) : null
|
||
|
)
|
||
|
|
||
4 months ago
|
const type = ref<'export' | 'details'>(route.query.type as 'export' | 'details')
|
||
5 months ago
|
const isonLineTransfer = computed(() => type.value === 'export')
|
||
7 months ago
|
const message = useMessage()
|
||
|
|
||
|
const transferDataStore = useTransferDataStore()
|
||
|
const { devicesMap } = storeToRefs(transferDataStore)
|
||
|
|
||
4 months ago
|
const transferStatus = ref<
|
||
|
'progress' | 'success' | 'failed' | 'timeout' | 'stop' | undefined
|
||
|
>()
|
||
7 months ago
|
|
||
|
const devices = computed(() => {
|
||
4 months ago
|
return isonLineTransfer.value
|
||
|
? Array.from(devicesMap.value.values())
|
||
|
: offLineDeviceList.value
|
||
7 months ago
|
}) as Ref<any[]>
|
||
|
|
||
4 months ago
|
// 在线设备批量迁移
|
||
|
function onLineDeviceTransfer() {
|
||
7 months ago
|
if (isBatchTransfer.value) {
|
||
|
onBatchCancel()
|
||
|
}
|
||
|
}
|
||
1 month ago
|
|
||
7 months ago
|
const onlineDeviceMap: Record<
|
||
5 months ago
|
keyof Omit<
|
||
|
IOnlineDevice,
|
||
5 months ago
|
'lastUpdated' | 'sn' | 'isChecked' | 'upFirmware' | 'upFirmwareStatus' | 'versions'
|
||
5 months ago
|
>,
|
||
7 months ago
|
string
|
||
|
> = {
|
||
|
status: '状态',
|
||
5 months ago
|
site_id: '站点名称',
|
||
7 months ago
|
clientIp: '客户端IP',
|
||
|
footprint: '数据占用空间',
|
||
|
}
|
||
|
const offlineDeviceMap: Record<
|
||
5 months ago
|
keyof Pick<IOfflineDevice, 'site_id' | 'db' | 'create_time'>,
|
||
7 months ago
|
string
|
||
|
> = {
|
||
5 months ago
|
site_id: '站点名称',
|
||
7 months ago
|
db: '数据库',
|
||
|
create_time: '创建时间',
|
||
|
}
|
||
|
|
||
5 months ago
|
const checkDeviceList = ref<string[]>([])
|
||
7 months ago
|
|
||
|
const isBatchTransfer = ref(false)
|
||
1 month ago
|
|
||
7 months ago
|
function onBatchTransfer() {
|
||
5 months ago
|
checkDeviceList.value = []
|
||
7 months ago
|
isBatchTransfer.value = true
|
||
|
}
|
||
|
|
||
5 months ago
|
function onBatchTransferSave(checkDeviceList: IOnlineDevice[] | IOfflineDevice[]) {
|
||
|
if (isonLineTransfer.value) {
|
||
4 months ago
|
const lineDevices = checkDeviceList as IOnlineDevice[]
|
||
|
const site = lineDevices[0]?.site_id
|
||
|
if (!site) {
|
||
|
message.error('请选择站点')
|
||
|
return
|
||
|
}
|
||
|
const deivcesParms = lineDevices.map(item => ({
|
||
|
sn: item.sn,
|
||
|
host: item.clientIp,
|
||
4 months ago
|
disk: item.footprint,
|
||
4 months ago
|
}))
|
||
|
|
||
|
const parmas: TaskCreateParams = {
|
||
|
site,
|
||
|
devices: deivcesParms,
|
||
|
mode: 'export',
|
||
|
}
|
||
|
onLineTransferDlgRef.value?.open(parmas)
|
||
5 months ago
|
} else {
|
||
4 months ago
|
const offlineDevices = checkDeviceList as IOfflineDevice[]
|
||
|
const site = offlineDevices[0]?.site_id
|
||
|
const deivcesParms = offlineDevices.map(item => ({
|
||
|
sn: item.sn,
|
||
|
}))
|
||
|
|
||
|
const parmas: TaskCreateParams = {
|
||
|
site,
|
||
|
devices: deivcesParms,
|
||
|
mode: 'import',
|
||
|
}
|
||
|
|
||
|
offTransferDlgRef.value?.open(parmas)
|
||
5 months ago
|
}
|
||
7 months ago
|
}
|
||
|
|
||
5 months ago
|
const isBatchUpgrade = ref(false)
|
||
1 month ago
|
|
||
5 months ago
|
function onBatchUpgrade() {
|
||
5 months ago
|
checkDeviceList.value = []
|
||
5 months ago
|
isBatchUpgrade.value = true
|
||
|
}
|
||
|
|
||
|
const batchText = computed(() => {
|
||
|
return isBatchTransfer.value ? '迁移' : '升级'
|
||
|
})
|
||
|
|
||
|
function onBatchSave() {
|
||
5 months ago
|
if (!checkDeviceList.value.length) {
|
||
5 months ago
|
message.error(`请选择要${batchText.value}的设备`)
|
||
|
return
|
||
|
}
|
||
5 months ago
|
|
||
|
const checkList = isonLineTransfer.value
|
||
|
? getOnlineDeviceList()
|
||
|
: getOfflineDeviceList()
|
||
|
|
||
5 months ago
|
if (isBatchTransfer.value) {
|
||
|
onBatchTransferSave(checkList)
|
||
|
}
|
||
5 months ago
|
|
||
|
if (isBatchUpgrade.value && isonLineTransfer.value) {
|
||
|
onFirmwareUpload(checkList as IOnlineDevice[])
|
||
5 months ago
|
}
|
||
|
}
|
||
|
|
||
5 months ago
|
function getOnlineDeviceList(): IOnlineDevice[] {
|
||
|
return checkDeviceList.value
|
||
|
.map(sn => {
|
||
|
return devicesMap.value.get(sn) ?? undefined
|
||
|
})
|
||
|
.filter(Boolean) as IOnlineDevice[]
|
||
|
}
|
||
|
|
||
|
function getOfflineDeviceList(): IOfflineDevice[] {
|
||
4 months ago
|
return offLineDeviceList.value.filter(item => checkDeviceList.value.includes(item.sn))
|
||
5 months ago
|
}
|
||
|
|
||
7 months ago
|
function onBatchCancel() {
|
||
|
isBatchTransfer.value = false
|
||
5 months ago
|
isBatchUpgrade.value = false
|
||
5 months ago
|
checkDeviceList.value = []
|
||
7 months ago
|
}
|
||
|
|
||
|
function onBack() {
|
||
|
router.push('/station')
|
||
|
}
|
||
|
|
||
|
// 监听页面刷新
|
||
|
window.onbeforeunload = function () {
|
||
|
stop()
|
||
|
}
|
||
|
|
||
|
onBeforeRouteLeave(async (to, from, next) => {
|
||
|
if (transferStatus.value === 'progress') {
|
||
|
try {
|
||
|
await message.confirm('当前迁移尚未完成,是否确认离开?')
|
||
|
window.location.href = to.fullPath
|
||
|
} catch (error) {
|
||
|
next(false)
|
||
|
}
|
||
|
} else {
|
||
|
next()
|
||
|
}
|
||
|
})
|
||
|
|
||
5 months ago
|
const offLineDeviceList = ref<IOfflineDevice[]>([])
|
||
7 months ago
|
|
||
|
async function loadDeviceList() {
|
||
5 months ago
|
const res = await getDeviceList(siteInfo.value.name)
|
||
7 months ago
|
if (res.code === 200 || res.code === 0) {
|
||
5 months ago
|
offLineDeviceList.value = res.data
|
||
7 months ago
|
}
|
||
|
}
|
||
|
|
||
5 months ago
|
const firmwarePath = ref('')
|
||
|
|
||
|
onMounted(async () => {
|
||
5 months ago
|
if (!isonLineTransfer.value) {
|
||
7 months ago
|
loadDeviceList()
|
||
5 months ago
|
} else {
|
||
|
const res = await getFirmwarePath()
|
||
|
if (res.code === 200 || res.code === 0) {
|
||
5 months ago
|
firmwarePath.value = res.data.path
|
||
5 months ago
|
}
|
||
7 months ago
|
}
|
||
|
})
|
||
|
|
||
|
const isShowDetails = ref(false)
|
||
|
const deviceDrawerRef = ref<typeof DeviceDrawer>()
|
||
1 month ago
|
|
||
7 months ago
|
function onDeviceDetails(item: IOfflineDevice) {
|
||
7 months ago
|
deviceDrawerRef.value?.openFullScreen()
|
||
7 months ago
|
deviceDrawerRef.value?.open(item)
|
||
|
}
|
||
5 months ago
|
|
||
1 month ago
|
function onTopology(item: IDevice) {
|
||
|
console.log(item)
|
||
|
}
|
||
|
|
||
5 months ago
|
const isCanFirmwareUpload = computed(() => !!firmwarePath.value && isonLineTransfer.value)
|
||
5 months ago
|
|
||
|
const upgradeSnList = ref<string[]>([])
|
||
1 month ago
|
|
||
4 months ago
|
async function onFirmwareUpload(devices: IOnlineDevice[]) {
|
||
5 months ago
|
upgradeSnList.value = []
|
||
|
if (!isCanFirmwareUpload.value) {
|
||
|
message.error('升级失败,请检查固件路径')
|
||
|
onBatchCancel()
|
||
|
return
|
||
|
}
|
||
4 months ago
|
const site = devices[0]?.site_id
|
||
|
if (!site) {
|
||
|
message.error('请选择站点')
|
||
|
return
|
||
5 months ago
|
}
|
||
4 months ago
|
const deivcesParms = devices.map(item => ({
|
||
|
sn: item.sn,
|
||
|
host: item.clientIp,
|
||
4 months ago
|
disk: item.footprint,
|
||
4 months ago
|
}))
|
||
5 months ago
|
|
||
4 months ago
|
const parmas: TaskCreateParams = {
|
||
|
site,
|
||
|
devices: deivcesParms,
|
||
|
mode: 'update',
|
||
1 month ago
|
firmware: firmwarePath.value,
|
||
5 months ago
|
}
|
||
4 months ago
|
const res = await createTask(parmas)
|
||
|
if (res.code !== 0) {
|
||
|
message.error(`任务创建失败`)
|
||
|
} else {
|
||
|
message.success('任务创建成功,请在任务列表中查看')
|
||
5 months ago
|
}
|
||
|
|
||
|
onBatchCancel()
|
||
5 months ago
|
}
|
||
|
|
||
4 months ago
|
// ================ 离线数据导入 =========
|
||
|
const offTransferDlgRef = ref<typeof OffTransferDlg>()
|
||
1 month ago
|
|
||
4 months ago
|
function onOffDeviceTransfer() {
|
||
|
onBatchCancel()
|
||
5 months ago
|
}
|
||
5 months ago
|
|
||
|
// ================ 离线数据导入 end =========
|
||
5 months ago
|
|
||
|
// const transferLogScrollbar = ref()
|
||
|
|
||
|
// watch(siteTransferLogList, () => {
|
||
|
// nextTick(() => {
|
||
|
// if (transferLogScrollbar.value) {
|
||
|
// const scrollbar = transferLogScrollbar.value
|
||
|
// scrollbar.setScrollTop(scrollbar.wrap$.scrollHeight)
|
||
|
// }
|
||
|
// })
|
||
|
// }, { deep: true })
|
||
7 months ago
|
</script>
|
||
|
|
||
|
<style scoped lang="scss">
|
||
|
.transfer-log-wrap {
|
||
7 months ago
|
margin-top: 10px;
|
||
7 months ago
|
@apply border-radius-8px bg-[#F9FAFB] p-10;
|
||
5 months ago
|
|
||
7 months ago
|
:deep(.el-scrollbar) {
|
||
|
height: calc(100% - 20px);
|
||
|
}
|
||
|
}
|
||
5 months ago
|
|
||
7 months ago
|
.device-list-wrap {
|
||
|
@apply wh-full;
|
||
5 months ago
|
|
||
7 months ago
|
:deep(.el-checkbox-group) {
|
||
|
@apply wh-full flex flex-wrap gap-col-6 gap-row-4;
|
||
|
}
|
||
5 months ago
|
|
||
7 months ago
|
:deep(.el-checkbox__inner) {
|
||
|
width: 18px;
|
||
|
height: 18px;
|
||
|
}
|
||
5 months ago
|
|
||
7 months ago
|
:deep(.el-checkbox__label) {
|
||
|
@apply text-14px font-500 text-[#313131];
|
||
|
}
|
||
5 months ago
|
|
||
7 months ago
|
:deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
|
||
|
color: var(--el-color-primary);
|
||
|
}
|
||
5 months ago
|
|
||
7 months ago
|
.device-item {
|
||
|
@apply w-289 h-160 border border-solid border-[#E0E0E0] rounded-8px p-x-14 p-y-10 flex-col;
|
||
5 months ago
|
|
||
7 months ago
|
.device-item-header {
|
||
5 months ago
|
@apply w-full text-black text-18px font-500 flex items-center justify-between;
|
||
|
|
||
7 months ago
|
.info {
|
||
|
font-size: 14px;
|
||
|
color: #f1bf63;
|
||
|
cursor: pointer;
|
||
|
text-decoration: underline;
|
||
5 months ago
|
|
||
7 months ago
|
&:hover {
|
||
|
color: #8ace6a;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
5 months ago
|
|
||
7 months ago
|
.device-item-body {
|
||
5 months ago
|
@apply flex-col m-t-10 text-sm gap-6;
|
||
|
|
||
7 months ago
|
.info-item {
|
||
5 months ago
|
@apply flex items-center gap-col-2;
|
||
7 months ago
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</style>
|