文件服务-文件目录/下载功能
This commit is contained in:
41
src/api/cs-device-boot/fileService.ts
Normal file
41
src/api/cs-device-boot/fileService.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import createAxios from '@/utils/request'
|
||||||
|
|
||||||
|
// 设备文件根目录查询
|
||||||
|
export function getDeviceRootPath(nDid) {
|
||||||
|
return createAxios({
|
||||||
|
url: '/cs-device-boot/deviceFile/askDeviceRootPath?nDid=' + nDid,
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设备文件-目录信息询问
|
||||||
|
export function getFileServiceFileOrDir(data) {
|
||||||
|
return createAxios({
|
||||||
|
url: `cs-device-boot/deviceFile/askDeviceFileOrDir?nDid=${data.nDid}&name=${data.name}&type=${data.type}`,
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//设备文件下载
|
||||||
|
export function downLoadDeviceFile(data) {
|
||||||
|
return createAxios({
|
||||||
|
url: `/cs-device-boot/deviceFile/downloadFile?nDid=${data.nDid}&name=${data.name}&fileCheck=${data.fileCheck}&size=${data.size}`,
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//上传文件至装置
|
||||||
|
export function uploadDeviceFile(data) {
|
||||||
|
let form = new FormData()
|
||||||
|
form.append('file', data.file)
|
||||||
|
form.append('filePath', data.filePath)
|
||||||
|
form.append('id', data.id)
|
||||||
|
return createAxios({
|
||||||
|
url: `/access-boot/analyzeModel/uploadDevFile`,
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
},
|
||||||
|
data: form
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -59,7 +59,7 @@ const rules = {
|
|||||||
code: [
|
code: [
|
||||||
{ required: true, message: '标识不能为空', trigger: 'blur' },
|
{ required: true, message: '标识不能为空', trigger: 'blur' },
|
||||||
{
|
{
|
||||||
pattern: /^[a-zA-Z_]{1}[a-zA-Z0-9_]{2,15}$/,
|
pattern: /^[a-zA-Z_]{1}[a-zA-Z0-9_]{2,20}$/,
|
||||||
message: '请输入至少3-20位英文',
|
message: '请输入至少3-20位英文',
|
||||||
min: 3,
|
min: 3,
|
||||||
max: 20,
|
max: 20,
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ const updateViewportHeight = async () => {
|
|||||||
// height.value = window.innerHeight;
|
// height.value = window.innerHeight;
|
||||||
height.value = window.innerHeight < 1080 ? 180 : 400
|
height.value = window.innerHeight < 1080 ? 180 : 400
|
||||||
tableStore.table.publicHeight = height.value
|
tableStore.table.publicHeight = height.value
|
||||||
await tableStore.index()
|
// await tableStore.index()
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
239
src/views/govern/device/fileService/index.vue
Normal file
239
src/views/govern/device/fileService/index.vue
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
<!-- 文件管理 -->
|
||||||
|
<template>
|
||||||
|
<div class="default-main main" :style="{ height: pageHeight.height }">
|
||||||
|
<div class="main_left">
|
||||||
|
<DeviceTree @node-click="nodeClick" @init="nodeClick"></DeviceTree>
|
||||||
|
</div>
|
||||||
|
<div class="main_right" v-loading="loading">
|
||||||
|
<div class="menu" v-if="activePathList.length != 0">
|
||||||
|
<el-breadcrumb :separator-icon="ArrowRight">
|
||||||
|
<el-breadcrumb-item
|
||||||
|
v-for="(item, index) in activePathList"
|
||||||
|
style="cursor: pointer"
|
||||||
|
:key="index"
|
||||||
|
@click="handleIntoByPath(item)"
|
||||||
|
>
|
||||||
|
<span>{{ index > 1 ? item.path.replace(activePathList[1].path, ' ') : item.path }}</span>
|
||||||
|
</el-breadcrumb-item>
|
||||||
|
</el-breadcrumb>
|
||||||
|
</div>
|
||||||
|
<div class="list">
|
||||||
|
<div class="list_item" v-for="(item, index) in dirList" :key="index" @click="handleIntoDir(item)">
|
||||||
|
<div class="item_download">
|
||||||
|
<el-button v-if="item?.type == 'file'" size="small" circle>
|
||||||
|
<el-icon @click="handleDownLoad(item)"><Download /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<img v-if="item?.type == 'dir'" src="@/assets/img/wenjianjia.svg" />
|
||||||
|
<img class="img_file" 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, ' ')
|
||||||
|
: item?.prjDataPath
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<popup ref="fileRef"></popup>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
|
||||||
|
import { mainHeight } from '@/utils/layout'
|
||||||
|
import { ref, reactive, watch } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { ArrowLeft, ArrowRight, Download } from '@element-plus/icons-vue'
|
||||||
|
import { getDeviceRootPath, getFileServiceFileOrDir, downLoadDeviceFile,uploadDeviceFile } from '@/api/cs-device-boot/fileService.ts'
|
||||||
|
import popup from './popup.vue'
|
||||||
|
defineOptions({
|
||||||
|
name: 'govern/device/fileService'
|
||||||
|
})
|
||||||
|
const pageHeight = mainHeight(20)
|
||||||
|
const loading = ref(false)
|
||||||
|
//nDid
|
||||||
|
const nDid = ref<string>('')
|
||||||
|
// 树节点点击
|
||||||
|
|
||||||
|
//当前目录
|
||||||
|
const activePath = ref<string>('')
|
||||||
|
//储存所有点击过的目录
|
||||||
|
const activePathList: any = ref([])
|
||||||
|
const nodeClick = (e: any) => {
|
||||||
|
loading.value = true
|
||||||
|
if (e.level == 2) {
|
||||||
|
nDid.value = e.ndid
|
||||||
|
getDeviceRootPath(nDid.value).then(res => {
|
||||||
|
loading.value = false
|
||||||
|
dirList.value = [res.data]
|
||||||
|
activePath.value = res.data.prjDataPath
|
||||||
|
activePathList.value.map((item: any, index: any) => {
|
||||||
|
if (item.path.indexOf(res.data.prjDataPath) == -1) {
|
||||||
|
activePathList.value.push({ path: activePath.value })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进入文件夹
|
||||||
|
const dirList = 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 })
|
||||||
|
}
|
||||||
|
getFileServiceFileOrDir(obj).then(res => {
|
||||||
|
dirList.value = res.data
|
||||||
|
loading.value = false
|
||||||
|
activePathList.value.map((item: any, index: any) => {
|
||||||
|
if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
|
||||||
|
activePathList.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//上传文件
|
||||||
|
const uploadFile=(file:any)=>{
|
||||||
|
const obj={
|
||||||
|
id:nDid.value,
|
||||||
|
file:file,
|
||||||
|
filePath:'/'
|
||||||
|
}
|
||||||
|
uploadDeviceFile().then((res)=>{
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据面包屑导航切换
|
||||||
|
const handleIntoByPath = async (val: any) => {
|
||||||
|
const obj = {
|
||||||
|
nDid: nDid.value,
|
||||||
|
name: val.path,
|
||||||
|
type: 'dir'
|
||||||
|
}
|
||||||
|
activePath.value = val.path
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//下载文件
|
||||||
|
const fileRef = ref()
|
||||||
|
const handleDownLoad = async (row: any) => {
|
||||||
|
await fileRef.value && fileRef.value.open(row, nDid.value)
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.main {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
.main_left {
|
||||||
|
// width: 280px;
|
||||||
|
}
|
||||||
|
.main_right {
|
||||||
|
overflow: hidden;
|
||||||
|
flex: 1;
|
||||||
|
padding: 10px 10px 10px 10px;
|
||||||
|
margin-left: 10px;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
.menu {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: flex-start;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-top: 20px;
|
||||||
|
height: 100%;
|
||||||
|
padding-bottom: 200px;
|
||||||
|
z-index: 100;
|
||||||
|
.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;
|
||||||
|
.item_download {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
z-index: 2001;
|
||||||
|
}
|
||||||
|
.img_file {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
83
src/views/govern/device/fileService/popup.vue
Normal file
83
src/views/govern/device/fileService/popup.vue
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<!-- 设备文件下载 -->
|
||||||
|
<template>
|
||||||
|
<div :class="downLoading ? 'all_disabled' : ''">
|
||||||
|
<el-dialog v-model="dialogVisible" title="文件信息" width="50%" @closed="handleClose">
|
||||||
|
<el-descriptions title="" style="margin: 10px 0" :column="2" :border="true" v-loading="loading">
|
||||||
|
<el-descriptions-item label="文件名称">
|
||||||
|
{{ fileData?.prjDataPath ? fileData?.prjDataPath : '/' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="文件大小">
|
||||||
|
{{ fileData?.size ? fileData?.size + '字节' : '/' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="文件时间">
|
||||||
|
{{ fileData?.startTime ? fileData?.startTime : '/' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="文件校验码">
|
||||||
|
{{ fileData?.fileCheck ? fileData?.fileCheck : '/' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="handleClose">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleDownLoad" :loading="downLoading">
|
||||||
|
{{ downLoading ? '下载中...' : '下载' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onMounted, defineExpose, onBeforeUnmount, onUnmounted, defineEmits } from 'vue'
|
||||||
|
import { getFileServiceFileOrDir, downLoadDeviceFile } from '@/api/cs-device-boot/fileService.ts'
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const downLoading = ref(false)
|
||||||
|
const emit = defineEmits(['downLoadFile'])
|
||||||
|
const handleClose = () => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
//文件信息
|
||||||
|
const fileData: any = ref({})
|
||||||
|
const open = (row: any, id: any) => {
|
||||||
|
dialogVisible.value = true
|
||||||
|
const obj = {
|
||||||
|
nDid: id,
|
||||||
|
name: row.prjDataPath,
|
||||||
|
type: row.type
|
||||||
|
}
|
||||||
|
loading.value = true
|
||||||
|
getFileServiceFileOrDir(obj).then(res => {
|
||||||
|
if (res.code == 'A0000') {
|
||||||
|
fileData.value = res.data[0]
|
||||||
|
fileData.value.nDid = id
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const handleDownLoad = () => {
|
||||||
|
const obj = {
|
||||||
|
nDid: fileData.value.nDid,
|
||||||
|
name: fileData.value.prjDataPath,
|
||||||
|
size: fileData.value.size,
|
||||||
|
fileCheck: fileData.value.fileCheck
|
||||||
|
}
|
||||||
|
downLoading.value = true
|
||||||
|
downLoadDeviceFile(obj).then(res => {
|
||||||
|
if (res.code == 'A0000') {
|
||||||
|
window.open(res.data, '_blank')
|
||||||
|
downLoading.value = false
|
||||||
|
} else if (res.code && res.code != 'A0000') {
|
||||||
|
downLoading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onMounted(() => {})
|
||||||
|
onUnmounted(() => {})
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.all_disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user