962 lines
34 KiB
Vue
962 lines
34 KiB
Vue
<!-- 文件管理 -->
|
||
<template>
|
||
<div class="default-main main" :style="{ height: pageHeight.height }">
|
||
<div class="main_left">
|
||
<DeviceTree @node-click="nodeClick" @deviceTypeChange="deviceTypeChange"></DeviceTree>
|
||
</div>
|
||
<div class="main_right" v-loading="loading">
|
||
<div class="right_nav">
|
||
<div class="menu" v-if="activePathList.length != 0">
|
||
<el-breadcrumb separator="/">
|
||
<el-breadcrumb-item
|
||
v-for="(item, index) in activePathList"
|
||
style="cursor: pointer"
|
||
:key="index"
|
||
@click="handleIntoByPath(item)"
|
||
>
|
||
<span>{{ outPutPath(item, index) }}</span>
|
||
</el-breadcrumb-item>
|
||
</el-breadcrumb>
|
||
</div>
|
||
<!-- <el-button :icon="Refresh" @click="handleRestartDevice" type="primary" :loading="deviceRestartLoading">
|
||
设备重启
|
||
</el-button> -->
|
||
</div>
|
||
|
||
<div class="filter" v-if="activePathList.length != 0">
|
||
<el-input
|
||
maxlength="32"
|
||
show-word-limit
|
||
style="width: 240px; height: 32px"
|
||
placeholder="请输入文件或文件夹名称"
|
||
clearable
|
||
v-model.trim="filterText"
|
||
type="text"
|
||
></el-input>
|
||
<el-button type="primary" @click="handleSearch" :icon="Search">搜索</el-button>
|
||
<!-- <el-button @click="handleRefresh" :icon="Refresh">重置</el-button> -->
|
||
<el-upload
|
||
v-if="activePath != '/'"
|
||
action=""
|
||
:auto-upload="false"
|
||
:show-file-list="false"
|
||
:on-change="(file: any, fileList: any) => {
|
||
handleUpload(file, fileList, activePath)
|
||
}
|
||
"
|
||
>
|
||
<el-button>
|
||
文件上传
|
||
<el-icon class="el-icon--right">
|
||
<Upload />
|
||
</el-icon>
|
||
</el-button>
|
||
</el-upload>
|
||
<el-button @click="handleAddNewDir" v-if="activePath != '/'" type="primary" :icon="Plus">
|
||
新建文件夹
|
||
</el-button>
|
||
<div class="upload_progress" v-if="status != 0 && status != 100 && changeType == 'upload'">
|
||
正在上传:{{ fileName }}
|
||
<el-progress :percentage="status" />
|
||
</div>
|
||
</div>
|
||
<!-- 以列表形式展示 -->
|
||
<div :style="tableHeight">
|
||
<vxe-table
|
||
style="margin-top: 10px"
|
||
border
|
||
auto-resize
|
||
height="auto"
|
||
:data="dirList"
|
||
v-bind="defaultAttribute"
|
||
>
|
||
<vxe-column type="seq" title="序号" width="80"></vxe-column>
|
||
<vxe-column field="prjDataPath" align="center" title="名称" minWidth="180" #default="{ row }">
|
||
<span
|
||
style="cursor: pointer; color: #551a8b"
|
||
:style="{
|
||
'text-decoration': row.type == 'dir' ? 'underline' : 'none',
|
||
color: row.type == 'dir' ? '#551a8b' : '#000'
|
||
}"
|
||
@click="handleIntoDir(row)"
|
||
>
|
||
{{
|
||
row &&
|
||
row?.prjDataPath &&
|
||
row?.prjDataPath.includes(activePath) &&
|
||
row?.prjDataPath.length > activePath.length
|
||
? row?.prjDataPath.replace(activePath, ' ').replace('/', ' ')
|
||
: row?.prjDataPath.replace('/', ' ')
|
||
}}
|
||
</span>
|
||
</vxe-column>
|
||
|
||
<vxe-column field="startTime" align="center" title="文件时间" minWidth="140" #default="{ row }">
|
||
{{ row.startTime ? row.startTime : '/' }}
|
||
</vxe-column>
|
||
<vxe-column field="type" align="center" title="类型" minWidth="100" #default="{ row }">
|
||
<span>
|
||
{{ row.type == 'dir' ? '文件夹' : row.type == 'file' ? '文件' : '/' }}
|
||
</span>
|
||
</vxe-column>
|
||
<vxe-column field="size" align="center" minWidth="100" title="大小" #default="{ row }">
|
||
<span>
|
||
{{ row.size && row.type == 'file' ? row.size + 'KB' : '/' }}
|
||
</span>
|
||
</vxe-column>
|
||
<!--<vxe-column field="fileCheck" align="center" title="文件校验码" width="100" #default="{ row }">
|
||
{{ row.fileCheck ? row.fileCheck : '/' }}
|
||
</vxe-column> -->
|
||
<vxe-column title="操作" width="120px" fixed="right">
|
||
<template #default="{ row }">
|
||
<el-button link size="small" type="danger" @click="handleDelDirOrFile(row)">删除</el-button>
|
||
<el-button
|
||
v-if="row.type == 'file'"
|
||
link
|
||
size="small"
|
||
type="primary"
|
||
@click="handleDownLoad(row)"
|
||
>
|
||
下载
|
||
</el-button>
|
||
</template>
|
||
</vxe-column>
|
||
</vxe-table>
|
||
</div>
|
||
|
||
<div class="list" v-if="dirList.length != 0 && !loading" style="display: none">
|
||
<div class="list_item" v-for="(item, index) in dirList" :key="index">
|
||
<div class="item_download">
|
||
<el-button
|
||
v-if="activePath && activePath != '/'"
|
||
type="danger"
|
||
size="small"
|
||
@click="handleDelDirOrFile(item)"
|
||
circle
|
||
>
|
||
<el-icon>
|
||
<Delete />
|
||
</el-icon>
|
||
</el-button>
|
||
<el-button v-if="item?.type == 'file'" size="small" @click="handleDownLoad(item)" circle>
|
||
<el-icon>
|
||
<Download />
|
||
</el-icon>
|
||
</el-button>
|
||
</div>
|
||
<img v-if="item?.type == 'dir'" @click="handleIntoDir(item)" src="@/assets/img/wenjianjia.svg" />
|
||
<img
|
||
class="img_file"
|
||
@click="handleIntoDir(item)"
|
||
v-if="item?.type == 'file'"
|
||
src="@/assets/img/wenjian.svg"
|
||
/>
|
||
<!-- <span v-if="!item.type">暂无数据</span> -->
|
||
<p>
|
||
{{
|
||
item &&
|
||
item?.prjDataPath &&
|
||
item?.prjDataPath.includes(activePath) &&
|
||
item?.prjDataPath.length > activePath.length
|
||
? item?.prjDataPath.replace(activePath, ' ').replace('/', ' ')
|
||
: item?.prjDataPath.replace('/', ' ')
|
||
}}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<!-- <el-empty v-if="dirList.length === 0" /> -->
|
||
</div>
|
||
<popup ref="fileRef"></popup>
|
||
<el-dialog
|
||
v-model.trim="addDeviceDirOpen"
|
||
:destroy-on-close="true"
|
||
title="新建文件夹目录"
|
||
width="500"
|
||
@closed="close"
|
||
>
|
||
<el-form
|
||
ref="formRef"
|
||
:model="form"
|
||
:rules="{ path: [{ required: true, message: '请输入文件夹名称', trigger: 'blur' }] }"
|
||
>
|
||
<el-form-item label="文件夹名称" prop="path">
|
||
<el-input maxlength="32" show-word-limit v-model.trim="form.path" placeholder="请输入文件夹名称" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button @click="close">取消</el-button>
|
||
<el-button type="primary" @click="submitDeviceDir">确定</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
|
||
import { mainHeight } from '@/utils/layout'
|
||
import { ref, watch, onMounted, onBeforeUnmount, h, inject } from 'vue'
|
||
import { ElMessage, ElMessageBox, ElInput, ElSegmented } from 'element-plus'
|
||
import {
|
||
getFileServiceFileOrDir,
|
||
uploadDeviceFile,
|
||
reStartDevice,
|
||
addDeviceDir,
|
||
delDeviceDir,
|
||
listDir,
|
||
downloadFileFromFrontr,
|
||
deleteCld,
|
||
uploadFileToFront,
|
||
mkdir
|
||
} from '@/api/cs-device-boot/fileService'
|
||
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||
import { Delete, Download, Upload, Plus, Refresh, Search } from '@element-plus/icons-vue'
|
||
import popup from './popup.vue'
|
||
import mqtt from 'mqtt'
|
||
import { useAdminInfo } from '@/stores/adminInfo'
|
||
import { passwordConfirm } from '@/api/user-boot/user'
|
||
import { downLoadFile } from '@/utils/downloadFile.ts'
|
||
defineOptions({
|
||
name: 'govern/device/fileService/index'
|
||
})
|
||
const pageHeight = mainHeight(20)
|
||
const tableHeight = mainHeight(130)
|
||
const adminInfo = useAdminInfo()
|
||
const loading = ref(false)
|
||
//nDid
|
||
const nDid = ref<string>('')
|
||
const devId = ref<string>('')
|
||
//当前目录
|
||
const activePath = ref<string>('')
|
||
//判断是否是根目录
|
||
const isRoot = ref<boolean>(true)
|
||
//储存所有点击过的目录
|
||
const activePathList: any = ref([])
|
||
const devConType = ref<string>('')
|
||
const deviceTypeChange = (val: any, obj: any) => {
|
||
nodeClick(obj)
|
||
}
|
||
const nodeClick = (e: any) => {
|
||
if (e && (e.level == 2 || e.level == 3 || e.type == 'device')) {
|
||
loading.value = true
|
||
nDid.value = e.ndid
|
||
devId.value = e.id
|
||
dirList.value = []
|
||
activePathList.value = []
|
||
activePath.value = '/'
|
||
devConType.value = e.devConType
|
||
if (devConType.value == 'CLD') {
|
||
listDir({ devId: devId.value, filePath: activePath.value })
|
||
.then((resp: any) => {
|
||
if (resp.code == 'A0000') {
|
||
dirList.value = resp.data
|
||
currentDirList.value = resp.data
|
||
activePathList.value = [{ path: activePath.value }]
|
||
loading.value = false
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
} else {
|
||
getFileServiceFileOrDir({ nDid: nDid.value, name: activePath.value, type: 'dir' })
|
||
.then((resp: any) => {
|
||
if (resp.code == 'A0000') {
|
||
dirList.value = resp.data
|
||
currentDirList.value = resp.data
|
||
activePathList.value = [{ path: activePath.value }]
|
||
loading.value = false
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
}
|
||
}
|
||
}
|
||
//搜索文件或文件夹
|
||
const filterText = ref('')
|
||
const handleSearch = () => {
|
||
let filterList: any = []
|
||
dirList.value = currentDirList.value
|
||
dirList.value.map(item => {
|
||
if (filterText.value && item.prjDataPath.includes(filterText.value)) {
|
||
filterList.push(item)
|
||
}
|
||
})
|
||
if (filterList.length != 0) {
|
||
dirList.value = filterList
|
||
}
|
||
if (filterList.length == 0) {
|
||
dirList.value = []
|
||
}
|
||
if (!filterText.value) {
|
||
dirList.value = currentDirList.value
|
||
}
|
||
}
|
||
//重置搜索
|
||
const handleRefresh = () => {
|
||
loading.value = true
|
||
filterText.value = ''
|
||
dirList.value = currentDirList.value
|
||
reloadCurrentMenu('')
|
||
}
|
||
|
||
const reboot: any = ref('')
|
||
const vNode = () => {
|
||
return h('div', {}, [
|
||
h(ElInput, {
|
||
modelValue: reboot.value,
|
||
'onUpdate:modelValue': ($event: any) => {
|
||
reboot.value = $event
|
||
},
|
||
placeholder: '请输入姓名',
|
||
type: 'password',
|
||
autocomplete: 'off',
|
||
class: 'displayPass'
|
||
})
|
||
])
|
||
}
|
||
|
||
//设备重启
|
||
const deviceRestartLoading = ref<boolean>(false)
|
||
const handleRestartDevice = () => {
|
||
deviceRestartLoading.value = true
|
||
ElMessageBox.prompt('二次校验密码确认', '设备重启', {
|
||
confirmButtonText: '确认',
|
||
cancelButtonText: '取消',
|
||
customClass: 'customInput',
|
||
inputType: 'text',
|
||
beforeClose: (action, instance, done) => {
|
||
if (action === 'confirm') {
|
||
if (instance.inputValue == null) {
|
||
return ElMessage.warning('请输入密码')
|
||
} else if (instance.inputValue?.length > 32) {
|
||
return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
|
||
} else {
|
||
done()
|
||
}
|
||
} else {
|
||
done()
|
||
}
|
||
}
|
||
})
|
||
.then(({ value }) => {
|
||
if (!value) {
|
||
ElMessage.warning('请输入密码')
|
||
loading.value = false
|
||
deviceRestartLoading.value = false
|
||
} else {
|
||
passwordConfirm(value)
|
||
.then((resp: any) => {
|
||
if (resp.code == 'A0000') {
|
||
reStartDevice({ nDid: nDid.value }).then((res: any) => {
|
||
if (res.code == 'A0000') {
|
||
deviceRestartLoading.value = false
|
||
ElMessage({ message: res.message, type: 'success', duration: 5000 })
|
||
} else {
|
||
deviceRestartLoading.value = false
|
||
}
|
||
})
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
deviceRestartLoading.value = false
|
||
})
|
||
}
|
||
})
|
||
.catch(() => {
|
||
deviceRestartLoading.value = false
|
||
})
|
||
}
|
||
// 进入文件夹
|
||
const dirList = ref([])
|
||
// 当前目录数据
|
||
const currentDirList = ref([])
|
||
const handleIntoDir = (row: any) => {
|
||
if (!row.type || row.type == 'file') return
|
||
loading.value = true
|
||
const obj = {
|
||
nDid: nDid.value,
|
||
name: row.prjDataPath,
|
||
type: row.type
|
||
}
|
||
//当前点击的目录
|
||
activePath.value = row.prjDataPath
|
||
if (activePathList.value.indexOf(obj.name) == -1) {
|
||
activePathList.value.push({ path: obj.name })
|
||
}
|
||
|
||
if (devConType.value == 'CLD') {
|
||
listDir({ devId: devId.value, filePath: row.prjDataPath })
|
||
.then((resp: any) => {
|
||
if (resp.code == 'A0000') {
|
||
dirList.value = resp.data
|
||
currentDirList.value = resp.data
|
||
activePathList.value.map((item: any, index: any) => {
|
||
if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
|
||
activePathList.value.splice(index, 1)
|
||
}
|
||
})
|
||
loading.value = false
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
} else {
|
||
getFileServiceFileOrDir(obj)
|
||
.then(res => {
|
||
dirList.value = res.data
|
||
loading.value = false
|
||
currentDirList.value = res.data
|
||
activePathList.value.map((item: any, index: any) => {
|
||
if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
|
||
activePathList.value.splice(index, 1)
|
||
}
|
||
})
|
||
isRoot.value = false
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
}
|
||
}
|
||
|
||
//处理导航栏路径
|
||
const outPutPath = (row: any, key: any) => {
|
||
let path = ''
|
||
if (key == 0) {
|
||
path = '/根目录'
|
||
}
|
||
if (key == 1) {
|
||
path = row.path
|
||
}
|
||
if (key > 1) {
|
||
if (row.path.includes(activePathList.value[1].path)) {
|
||
path = row.path.replace(activePathList.value[1].path, ' ')
|
||
}
|
||
if (row.path.split('/').length !== 0) {
|
||
path = '/' + row.path.split('/')[row.path.split('/').length - 1]
|
||
}
|
||
}
|
||
return path.split('/')[1]
|
||
}
|
||
|
||
//根据面包屑导航切换
|
||
const handleIntoByPath = async (val: any) => {
|
||
const obj = {
|
||
nDid: nDid.value,
|
||
name: val.path,
|
||
type: 'dir'
|
||
}
|
||
activePath.value = val.path
|
||
loading.value = true
|
||
if (devConType.value == 'CLD') {
|
||
listDir({ devId: devId.value, filePath: val.path })
|
||
.then((resp: any) => {
|
||
if (resp.code == 'A0000') {
|
||
dirList.value = resp.data
|
||
|
||
activePathList.value.map((item: any, index: any) => {
|
||
if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
|
||
activePathList.value.splice(index, 1)
|
||
}
|
||
})
|
||
loading.value = false
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
} else {
|
||
getFileServiceFileOrDir(obj)
|
||
.then(res => {
|
||
dirList.value = res.data
|
||
activePathList.value.map((item: any, index: any) => {
|
||
if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
|
||
activePathList.value.splice(index, 1)
|
||
}
|
||
})
|
||
loading.value = false
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
}
|
||
}
|
||
const form = ref({
|
||
path: ''
|
||
})
|
||
//新建文件夹弹框flag
|
||
const addDeviceDirOpen = ref<boolean>(false)
|
||
const close = () => {
|
||
addDeviceDirOpen.value = false
|
||
}
|
||
//打开新建文件夹弹框
|
||
const handleAddNewDir = () => {
|
||
form.value.path = ''
|
||
addDeviceDirOpen.value = true
|
||
}
|
||
const formRef = ref()
|
||
//重新加载当前页面菜单
|
||
const reloadCurrentMenu = (msg: string) => {
|
||
loading.value = true
|
||
|
||
if (devConType.value == 'CLD') {
|
||
listDir({ devId: devId.value, filePath: activePath.value })
|
||
.then((resp: any) => {
|
||
if (resp.code == 'A0000') {
|
||
dirList.value = resp.data
|
||
currentDirList.value = resp.data
|
||
activePathList.value.map((item: any, index: any) => {
|
||
if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
|
||
activePathList.value.splice(index, 1)
|
||
}
|
||
})
|
||
loading.value = false
|
||
if (!msg) return
|
||
ElMessage({ message: msg, type: 'success', duration: 5000 })
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
} else {
|
||
getFileServiceFileOrDir({ nDid: nDid.value, name: activePath.value, type: 'dir' })
|
||
.then((resp: any) => {
|
||
if (resp.code == 'A0000') {
|
||
loading.value = false
|
||
dirList.value = resp.data
|
||
currentDirList.value = resp.data
|
||
activePathList.value.map((item: any, index: any) => {
|
||
if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
|
||
activePathList.value.splice(index, 1)
|
||
}
|
||
})
|
||
loading.value = false
|
||
|
||
if (!msg) return
|
||
ElMessage({ message: msg, type: 'success', duration: 5000 })
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
}
|
||
}
|
||
//新建文件夹
|
||
const submitDeviceDir = () => {
|
||
formRef.value.validate((valid: any) => {
|
||
if (valid) {
|
||
if (devConType.value == 'CLD') {
|
||
let obj = {
|
||
devId: devId.value,
|
||
filePath:
|
||
activePath.value == '/'
|
||
? activePath.value + form.value.path
|
||
: activePath.value + '/' + form.value.path
|
||
}
|
||
loading.value = true
|
||
mkdir(obj).then((res: any) => {
|
||
if (res.code == 'A0000') {
|
||
reloadCurrentMenu(res.message)
|
||
addDeviceDirOpen.value = false
|
||
}
|
||
})
|
||
} else {
|
||
let obj = {
|
||
nDid: nDid.value,
|
||
path:
|
||
activePath.value == '/'
|
||
? activePath.value + form.value.path
|
||
: activePath.value + '/' + form.value.path
|
||
}
|
||
loading.value = true
|
||
addDeviceDir(obj).then((res: any) => {
|
||
if (res.code == 'A0000') {
|
||
reloadCurrentMenu(res.message)
|
||
addDeviceDirOpen.value = false
|
||
}
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
//删除文件夹或文件
|
||
const handleDelDirOrFile = (row: any) => {
|
||
ElMessageBox.prompt('二次校验密码确认', '', {
|
||
confirmButtonText: '确认',
|
||
cancelButtonText: '取消',
|
||
customClass: 'customInput',
|
||
inputType: 'text',
|
||
beforeClose: (action, instance, done) => {
|
||
if (action === 'confirm') {
|
||
if (instance.inputValue == null) {
|
||
return ElMessage.warning('请输入密码')
|
||
} else if (instance.inputValue?.length > 32) {
|
||
return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
|
||
} else {
|
||
done()
|
||
}
|
||
} else {
|
||
done()
|
||
}
|
||
}
|
||
}).then(({ value }) => {
|
||
if (!value) {
|
||
ElMessage.warning('请输入密码')
|
||
} else {
|
||
loading.value = true
|
||
passwordConfirm(value)
|
||
.then((resp: any) => {
|
||
if (resp.code == 'A0000') {
|
||
if (devConType.value == 'CLD') {
|
||
deleteCld({
|
||
devId: devId.value,
|
||
filePath: row.prjDataPath
|
||
})
|
||
.then((res: any) => {
|
||
if (res.code == 'A0000') {
|
||
reloadCurrentMenu(res.message)
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
} else {
|
||
delDeviceDir({ nDid: nDid.value, path: row.prjDataPath })
|
||
.then((res: any) => {
|
||
if (res.code == 'A0000') {
|
||
reloadCurrentMenu(res.message)
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
}
|
||
}
|
||
})
|
||
.catch(e => {
|
||
loading.value = false
|
||
})
|
||
}
|
||
})
|
||
}
|
||
const changeType = ref<any>('')
|
||
//下载文件
|
||
const fileRef = ref()
|
||
const handleDownLoad = async (row: any) => {
|
||
if (devConType.value == 'CLD') {
|
||
ElMessage.info('下载中,请稍等...')
|
||
downloadFileFromFrontr({
|
||
devId: devId.value,
|
||
filePath: row.prjDataPath
|
||
}).then(res => {
|
||
downLoadFile(row.name, row.name, res)
|
||
})
|
||
} else {
|
||
;(await nDid.value) && fileRef.value && fileRef.value.open(row, nDid.value)
|
||
// fileName.value = row?.prjDataPath.split('/')[row?.prjDataPath.split('/').length - 1]
|
||
// localStorage.setItem('fileName', fileName.value)
|
||
changeType.value = 'download'
|
||
localStorage.setItem('changeType', changeType.value)
|
||
}
|
||
}
|
||
//上传文件
|
||
const fileName = ref<any>('')
|
||
const handleUpload = (e: any, fileList: any, row: any) => {
|
||
// loading.value=true
|
||
fileName.value = e.name
|
||
localStorage.setItem('fileName', fileName.value)
|
||
changeType.value = 'upload'
|
||
localStorage.setItem('changeType', changeType.value)
|
||
|
||
if (devConType.value == 'CLD') {
|
||
const obj = {
|
||
devId: devId.value,
|
||
file: e.raw,
|
||
dirPath: row || row.prjDataPath
|
||
}
|
||
uploadFileToFront(obj).then((res: any) => {
|
||
if (res.code == 'A0000') {
|
||
reloadCurrentMenu(res.message)
|
||
status.value = 100
|
||
}
|
||
})
|
||
} else {
|
||
const obj = {
|
||
id: nDid.value,
|
||
file: e.raw,
|
||
filePath: row || row.prjDataPath
|
||
}
|
||
uploadDeviceFile(obj).then((res: any) => {
|
||
if (res.code == 'A0000') {
|
||
reloadCurrentMenu(res.message)
|
||
status.value = 100
|
||
}
|
||
})
|
||
}
|
||
}
|
||
watch(
|
||
() => activePathList.value,
|
||
async (val, oldVal) => {
|
||
if (val) {
|
||
val.map((item: any, index: any) => {
|
||
if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
|
||
val.splice(index, 1)
|
||
}
|
||
})
|
||
}
|
||
},
|
||
{
|
||
immediate: true,
|
||
deep: true
|
||
}
|
||
)
|
||
const mqttRef = ref()
|
||
const url: any = window.localStorage.getItem('MQTTURL')
|
||
const connectMqtt = () => {
|
||
if (mqttRef.value) {
|
||
if (mqttRef.value.connected) {
|
||
return
|
||
}
|
||
}
|
||
const options = {
|
||
protocolId: 'MQTT',
|
||
qos: 2,
|
||
clean: true,
|
||
connectTimeout: 30 * 1000,
|
||
clientId: 'mqttjs' + Math.random(),
|
||
username: 't_user',
|
||
password: 'njcnpqs'
|
||
}
|
||
mqttRef.value = mqtt.connect(url, options)
|
||
}
|
||
connectMqtt()
|
||
mqttRef.value.on('connect', (e: any) => {
|
||
// ElMessage.success('连接mqtt服务器成功!')
|
||
console.log('mqtt客户端已连接....')
|
||
// mqttRef.value.subscribe('/Web/Progress')
|
||
mqttRef.value.subscribe('/Web/Progress/+')
|
||
})
|
||
const mqttMessage = ref<any>({})
|
||
const status: any = ref()
|
||
function parseStringToObject(str: string) {
|
||
const content = str.replace(/^{|}$/g, '')
|
||
const result: any = {}
|
||
|
||
// 正则匹配:key:value 格式,支持 value 里带 : / 等字符
|
||
const regex = /([^,:]+):([^,]+)(?=,|$)/g
|
||
let match
|
||
|
||
while ((match = regex.exec(content)) !== null) {
|
||
const key = match[1].trim()
|
||
const value = match[2].trim()
|
||
// 数字自动转 Number
|
||
result[key] = isNaN(Number(value)) ? value : Number(value)
|
||
}
|
||
|
||
return result
|
||
}
|
||
mqttRef.value.on('message', (topic: any, message: any) => {
|
||
// console.log('mqtt接收到消息', JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message)))))
|
||
|
||
let str = JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
|
||
mqttMessage.value = parseStringToObject(str)
|
||
if (adminInfo.id != mqttMessage.value.userId) return
|
||
|
||
// console.log("🚀 ~ str.match(regex3)[1]:", str.match(regex3)[1])
|
||
status.value = parseInt(Number((mqttMessage.value.nowStep / mqttMessage.value.allStep) * 100))
|
||
fileRef.value.setStatus(mqttMessage.value)
|
||
fileName.value = mqttMessage.value.fileName
|
||
localStorage.setItem('fileName', fileName.value)
|
||
if (status.value == 100) {
|
||
status.value = 99
|
||
}
|
||
})
|
||
|
||
mqttRef.value.on('error', (error: any) => {
|
||
console.log('mqtt连接失败...', error)
|
||
mqttRef.value.end()
|
||
})
|
||
|
||
mqttRef.value.on('close', function () {
|
||
console.log('mqtt客户端已断开连接.....')
|
||
})
|
||
onMounted(() => {
|
||
status.value = 0
|
||
fileName.value = localStorage.getItem('fileName') ? localStorage.getItem('fileName') : ''
|
||
changeType.value = localStorage.getItem('changeType') ? localStorage.getItem('changeType') : ''
|
||
})
|
||
onBeforeUnmount(() => {
|
||
if (mqttRef.value) {
|
||
mqttRef.value.end()
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.main {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding-bottom: 10px;
|
||
|
||
.main_left {
|
||
// width: 280px;
|
||
}
|
||
|
||
.main_right {
|
||
overflow: hidden;
|
||
flex: 1;
|
||
padding: 10px 10px 10px 10px;
|
||
//margin-left: 10px;
|
||
border: 1px solid #eee;
|
||
|
||
.el-input__wrapper {
|
||
-webkit-text-security: disc !important;
|
||
}
|
||
|
||
.right_nav {
|
||
width: 100%;
|
||
height: 32px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.menu {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
overflow-x: auto;
|
||
align-items: center;
|
||
background-color: var(--el-color-primary);
|
||
border-radius: 4px;
|
||
|
||
span {
|
||
font-size: 14px;
|
||
font-weight: 800;
|
||
padding: 0 5px;
|
||
color: #fff;
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
|
||
.el-button {
|
||
margin: 0 10px;
|
||
}
|
||
}
|
||
|
||
.filter {
|
||
width: 100%;
|
||
height: 30px;
|
||
display: flex;
|
||
margin-top: 10px;
|
||
justify-content: flex-start;
|
||
|
||
.el-button {
|
||
margin-left: 10px;
|
||
}
|
||
|
||
.upload_progress {
|
||
flex: 1;
|
||
height: 30px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
margin-left: 10px;
|
||
|
||
.el-progress {
|
||
width: 300px;
|
||
margin-left: 10px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.list {
|
||
// display: flex;
|
||
// flex-wrap: wrap;
|
||
// align-items: flex-start;
|
||
// justify-content: space-between;
|
||
overflow-y: auto;
|
||
margin-top: 10px;
|
||
max-height: 100%;
|
||
padding-bottom: 200px;
|
||
z-index: 100;
|
||
position: relative;
|
||
|
||
.list_item {
|
||
flex: none;
|
||
width: 23.3%;
|
||
height: 100px;
|
||
border: 1px solid var(--el-color-primary);
|
||
margin: 10px 0.5%;
|
||
display: flex;
|
||
align-items: center;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
// border-radius: 6px;
|
||
cursor: pointer;
|
||
position: relative;
|
||
z-index: 1001 !important;
|
||
width: 100%;
|
||
height: 40px;
|
||
margin: 0;
|
||
border: 1px solid #eee;
|
||
|
||
.item_download,
|
||
.item_upload {
|
||
position: absolute;
|
||
top: 10px;
|
||
right: 10px;
|
||
z-index: 2001;
|
||
}
|
||
|
||
.img_file {
|
||
// width: 60px;
|
||
// height: 60px;
|
||
width: 30px;
|
||
height: 30px;
|
||
}
|
||
|
||
img {
|
||
// width: 50px;
|
||
// height: 50px;
|
||
width: 30px;
|
||
height: 30px;
|
||
cursor: pointer !important;
|
||
}
|
||
|
||
p {
|
||
margin-top: 10px;
|
||
}
|
||
}
|
||
|
||
.list_item:nth-child(4n + 2),
|
||
.list_item:nth-child(4n + 3) {
|
||
// margin: 10px 0.8%;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.el-form {
|
||
padding: 20px 10px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
:deep(.el-breadcrumb__separator) {
|
||
margin: 0px -10px 0px 0px;
|
||
}
|
||
</style>
|
||
<style lang="scss">
|
||
.customInput {
|
||
.el-input__inner {
|
||
-webkit-text-security: disc !important;
|
||
}
|
||
}
|
||
</style>
|