|
|
@@ -1,264 +1,261 @@
|
|
|
<template>
|
|
|
- <ContentWrap>
|
|
|
- <div style="display: flex; justify-content: space-between; align-items: center">
|
|
|
+ <div
|
|
|
+ class="tree-page grid grid-cols-[auto_1fr] grid-rows-[48px_48px_1fr] gap-x-4 gap-y-3 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
|
|
|
+ <PmsTree
|
|
|
+ class="row-span-3"
|
|
|
+ @node-click="handleFileNodeClick"
|
|
|
+ @success="successList"
|
|
|
+ :currentId="queryParams.classId"
|
|
|
+ :deviceId="id" />
|
|
|
+
|
|
|
+ <el-form
|
|
|
+ class="search-panel bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-6 gap-8 flex items-center justify-between"
|
|
|
+ :model="queryParams"
|
|
|
+ ref="queryFormRef"
|
|
|
+ :inline="true"
|
|
|
+ label-width="68px">
|
|
|
+ <div class="flex items-center gap-8">
|
|
|
+ <el-form-item :label="t('file.name')" prop="filename">
|
|
|
+ <el-input
|
|
|
+ v-model="queryParams.filename"
|
|
|
+ :placeholder="t('file.nameHolder')"
|
|
|
+ size="default"
|
|
|
+ clearable
|
|
|
+ @keyup.enter="handleQuery"
|
|
|
+ class="!w-240px" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-show="false" :label="t('file.fileType')" prop="fileType">
|
|
|
+ <el-select
|
|
|
+ v-model="queryParams.fileType"
|
|
|
+ :placeholder="t('file.fileTypeHolder')"
|
|
|
+ size="default"
|
|
|
+ clearable
|
|
|
+ class="!w-200px">
|
|
|
+ <el-option
|
|
|
+ v-for="dict in getStrDictOptions(DICT_TYPE.PMS_FILE_TYPE)"
|
|
|
+ :key="dict.value"
|
|
|
+ :label="dict.label"
|
|
|
+ :value="dict.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button size="default" @click="handleQuery">
|
|
|
+ <Icon icon="ep:search" class="mr-5px" />{{ t('file.search') }}
|
|
|
+ </el-button>
|
|
|
+ <el-button size="default" @click="resetQuery">
|
|
|
+ <Icon icon="ep:refresh" class="mr-5px" />{{ t('file.reset') }}
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="default"
|
|
|
+ :loading="uploadLoading"
|
|
|
+ @click="openForm('create')">
|
|
|
+ <Icon icon="ep:plus" class="mr-5px" />{{ t('file.upload') }}
|
|
|
+ </el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="breadcrumb-panel bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-4 flex items-center justify-between">
|
|
|
<el-breadcrumb separator=">" class="breadcrumb-container">
|
|
|
<el-breadcrumb-item
|
|
|
v-for="(item, index) in breadcrumbs"
|
|
|
:key="index"
|
|
|
@click="handleBreadcrumbClick(index)"
|
|
|
:class="{ 'current-crumb': index === breadcrumbs.length - 1 }"
|
|
|
- class="custom-breadcrumb-item"
|
|
|
- >
|
|
|
+ class="custom-breadcrumb-item">
|
|
|
{{ item.name }}
|
|
|
</el-breadcrumb-item>
|
|
|
</el-breadcrumb>
|
|
|
<el-input
|
|
|
v-model="queryParams.allName"
|
|
|
:placeholder="'在' + breadcrumbs[breadcrumbs.length - 1].name + '下搜索'"
|
|
|
- style="width: 250px; height: 30px"
|
|
|
- @input="searchFolderAndFile"
|
|
|
- />
|
|
|
+ size="default"
|
|
|
+ style="width: 250px"
|
|
|
+ @input="searchFolderAndFile" />
|
|
|
</div>
|
|
|
- </ContentWrap>
|
|
|
- <div class="container-tree" ref="container">
|
|
|
- <el-row>
|
|
|
- <div class="left-tree" :style="{ width: leftWidth + 'px' }">
|
|
|
- <ContentWrapNoBottom>
|
|
|
- <PmsTree
|
|
|
- @node-click="handleFileNodeClick"
|
|
|
- @success="successList"
|
|
|
- :currentId="queryParams.classId"
|
|
|
- :deviceId="id"
|
|
|
- />
|
|
|
- </ContentWrapNoBottom>
|
|
|
- </div>
|
|
|
- <!-- </el-col>-->
|
|
|
- <div class="divider-tree" @mousedown="startDrag"></div>
|
|
|
- <div class="right-tree" :style="{ width: rightWidth + 'px' }">
|
|
|
- <ContentWrap>
|
|
|
- <el-form
|
|
|
- class="-mb-15px"
|
|
|
- :model="queryParams"
|
|
|
- ref="queryFormRef"
|
|
|
- :inline="true"
|
|
|
- label-width="68px"
|
|
|
- >
|
|
|
- <el-form-item :label="t('file.name')" prop="filename">
|
|
|
- <el-input
|
|
|
- v-model="queryParams.filename"
|
|
|
- :placeholder="t('file.nameHolder')"
|
|
|
- clearable
|
|
|
- @keyup.enter="handleQuery"
|
|
|
- class="!w-240px"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item v-show="false" :label="t('file.fileType')" prop="fileType">
|
|
|
- <el-select
|
|
|
- v-model="queryParams.fileType"
|
|
|
- :placeholder="t('file.fileTypeHolder')"
|
|
|
- clearable
|
|
|
- class="!w-200px"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="dict in getStrDictOptions(DICT_TYPE.PMS_FILE_TYPE)"
|
|
|
- :key="dict.value"
|
|
|
- :label="dict.label"
|
|
|
- :value="dict.value"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item>
|
|
|
- <el-button @click="handleQuery"
|
|
|
- ><Icon icon="ep:search" /> {{ t('file.search') }}</el-button
|
|
|
- >
|
|
|
- <el-button @click="resetQuery"
|
|
|
- ><Icon icon="ep:refresh" />{{ t('file.reset') }}</el-button
|
|
|
- >
|
|
|
- <el-button type="primary" :loading="uploadLoading" @click="openForm('create')">
|
|
|
- <Icon icon="ep:plus" /> {{ t('file.upload') }}
|
|
|
+
|
|
|
+ <div class="table-panel bg-white dark:bg-[#1d1e1f] rounded-lg shadow overflow-hidden p-3">
|
|
|
+ <zm-table
|
|
|
+ :loading="formLoading"
|
|
|
+ :data="list"
|
|
|
+ :stripe="true"
|
|
|
+ :show-overflow-tooltip="true"
|
|
|
+ settings-cache-key="system-tree-file-list"
|
|
|
+ @row-dblclick="inContent"
|
|
|
+ class="custom-table">
|
|
|
+ <zm-table-column :label="t('file.name')" align="left" prop="filename" min-width="300">
|
|
|
+ <template #default="scope">
|
|
|
+ <div style="display: flex; align-items: center; gap: 5px">
|
|
|
+ <Icon v-if="scope.row.fileType === 'content'" icon="fa:folder-open" color="orange" />
|
|
|
+ <Icon
|
|
|
+ v-else-if="scope.row.fileType === 'device'"
|
|
|
+ icon="fa:folder-open"
|
|
|
+ color="blue" />
|
|
|
+ <Icon
|
|
|
+ v-else-if="
|
|
|
+ scope.row.fileType === 'pic' ||
|
|
|
+ scope.row.fileClassify === 'jpg' ||
|
|
|
+ scope.row.fileClassify === 'png' ||
|
|
|
+ scope.row.fileClassify === 'JPG'
|
|
|
+ "
|
|
|
+ icon="ep:picture-filled"
|
|
|
+ color="#2183D1" />
|
|
|
+ <Icon
|
|
|
+ v-else-if="
|
|
|
+ scope.row.fileType === 'file' &&
|
|
|
+ (scope.row.fileClassify === 'pdf' || scope.row.fileClassify === 'PDF')
|
|
|
+ "
|
|
|
+ icon="fa-solid:file-pdf"
|
|
|
+ color="#E20012" />
|
|
|
+ <Icon
|
|
|
+ v-else-if="
|
|
|
+ scope.row.fileType === 'file' &&
|
|
|
+ (scope.row.fileClassify === 'doc' || scope.row.fileClassify === 'docx')
|
|
|
+ "
|
|
|
+ icon="fa:file-word-o"
|
|
|
+ color="blue" />
|
|
|
+ <Icon
|
|
|
+ v-else-if="
|
|
|
+ scope.row.fileType === 'file' &&
|
|
|
+ (scope.row.fileClassify === 'xls' || scope.row.fileClassify === 'xlsx')
|
|
|
+ "
|
|
|
+ icon="fa-solid:file-excel"
|
|
|
+ color="#107C41" />
|
|
|
+ <Icon
|
|
|
+ v-else-if="scope.row.fileType === 'file' && scope.row.fileClassify === 'txt'"
|
|
|
+ icon="fa:file-text-o" />
|
|
|
+ <Icon
|
|
|
+ v-else-if="scope.row.fileType === 'file' && scope.row.fileClassify === 'mp4'"
|
|
|
+ icon="fa:play-circle-o"
|
|
|
+ color="#009fff" />
|
|
|
+ <Icon
|
|
|
+ v-else-if="
|
|
|
+ scope.row.fileType === 'file' &&
|
|
|
+ (scope.row.fileClassify === 'ppt' || scope.row.fileClassify === 'pptx')
|
|
|
+ "
|
|
|
+ icon="fa-solid:file-powerpoint"
|
|
|
+ color="#C43E1C" />
|
|
|
+ <Icon v-else icon="fa-solid:file-alt" />
|
|
|
+ {{ scope.row.filename }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </zm-table-column>
|
|
|
+ <zm-table-column :label="t('file.fileType')" align="center" prop="fileType">
|
|
|
+ <template #default="scope">
|
|
|
+ <dict-tag :type="DICT_TYPE.PMS_FILE_TYPE" :value="scope.row.fileType" />
|
|
|
+ </template>
|
|
|
+ </zm-table-column>
|
|
|
+ <zm-table-column :label="t('file.fileSize')" align="center" prop="fileSize" />
|
|
|
+ <zm-table-column :label="t('file.dept')" align="center" prop="deptName" />
|
|
|
+ <zm-table-column
|
|
|
+ :label="t('file.device')"
|
|
|
+ align="center"
|
|
|
+ prop="deviceCode"
|
|
|
+ min-width="220" />
|
|
|
+ <zm-table-column
|
|
|
+ :label="t('file.operation')"
|
|
|
+ align="center"
|
|
|
+ width="160"
|
|
|
+ fixed="right"
|
|
|
+ action>
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="flex items-center justify-center">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ v-if="scope.row.fileType !== 'content'"
|
|
|
+ link
|
|
|
+ @click="handleDownload(scope.row.filePath)"
|
|
|
+ v-hasPermi="['rq:iot-info:download']">
|
|
|
+ <Icon icon="ep:download" />{{ t('file.dow') }}
|
|
|
</el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </ContentWrap>
|
|
|
- <ContentWrap>
|
|
|
- <el-table
|
|
|
- v-loading="formLoading"
|
|
|
- :data="list"
|
|
|
- :stripe="true"
|
|
|
- :show-overflow-tooltip="true"
|
|
|
- @row-dblclick="inContent"
|
|
|
- class="custom-table"
|
|
|
- >
|
|
|
- <el-table-column :label="t('file.name')" align="left" prop="filename" min-width="300">
|
|
|
- <template #default="scope">
|
|
|
- <div style="display: flex; align-items: center; gap: 5px">
|
|
|
- <Icon
|
|
|
- v-if="scope.row.fileType === 'content'"
|
|
|
- icon="fa:folder-open"
|
|
|
- color="orange"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- v-else-if="scope.row.fileType === 'device'"
|
|
|
- icon="fa:folder-open"
|
|
|
- color="blue"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- v-else-if="
|
|
|
- scope.row.fileType === 'pic' ||
|
|
|
- scope.row.fileClassify === 'jpg' ||
|
|
|
- scope.row.fileClassify === 'png' ||
|
|
|
- scope.row.fileClassify === 'JPG'
|
|
|
- "
|
|
|
- icon="ep:picture-filled"
|
|
|
- color="#2183D1"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- v-else-if="
|
|
|
- scope.row.fileType === 'file' &&
|
|
|
- (scope.row.fileClassify === 'pdf' || scope.row.fileClassify === 'PDF')
|
|
|
- "
|
|
|
- icon="fa-solid:file-pdf"
|
|
|
- color="#E20012"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- v-else-if="
|
|
|
- scope.row.fileType === 'file' &&
|
|
|
- (scope.row.fileClassify === 'doc' || scope.row.fileClassify === 'docx')
|
|
|
- "
|
|
|
- icon="fa:file-word-o"
|
|
|
- color="blue"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- v-else-if="
|
|
|
- scope.row.fileType === 'file' &&
|
|
|
- (scope.row.fileClassify === 'xls' || scope.row.fileClassify === 'xlsx')
|
|
|
- "
|
|
|
- icon="fa-solid:file-excel"
|
|
|
- color="#107C41"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- v-else-if="scope.row.fileType === 'file' && scope.row.fileClassify === 'txt'"
|
|
|
- icon="fa:file-text-o"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- v-else-if="scope.row.fileType === 'file' && scope.row.fileClassify === 'mp4'"
|
|
|
- icon="fa:play-circle-o"
|
|
|
- color="#009fff"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- v-else-if="
|
|
|
- scope.row.fileType === 'file' &&
|
|
|
- (scope.row.fileClassify === 'ppt' || scope.row.fileClassify === 'pptx')
|
|
|
- "
|
|
|
- icon="fa-solid:file-powerpoint"
|
|
|
- color="#C43E1C"
|
|
|
- />
|
|
|
- <Icon v-else icon="fa-solid:file-alt" />
|
|
|
- {{ scope.row.filename }}
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column :label="t('file.fileType')" align="center" prop="fileType">
|
|
|
- <template #default="scope">
|
|
|
- <dict-tag :type="DICT_TYPE.PMS_FILE_TYPE" :value="scope.row.fileType" />
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column :label="t('file.fileSize')" align="center" prop="fileSize" />
|
|
|
- <!-- <el-table-column :label="t('file.preview') " align="center" prop="filePath" >-->
|
|
|
- <!-- <template #default="scope">-->
|
|
|
- <!-- <el-button v-if="scope.row.fileType!=='content'" link type="primary" @click="openWeb(scope.row.filePath)"> <Icon size="19" icon="ep:view" /> </el-button>-->
|
|
|
- <!-- </template>-->
|
|
|
- <!-- </el-table-column>-->
|
|
|
- <el-table-column :label="t('file.dept')" align="center" prop="deptName" />
|
|
|
- <el-table-column
|
|
|
- :label="t('file.device')"
|
|
|
- align="center"
|
|
|
- prop="deviceCode"
|
|
|
- min-width="220"
|
|
|
- />
|
|
|
- />
|
|
|
- <el-table-column :label="t('file.operation')" align="center" width="160">
|
|
|
- <template #default="scope">
|
|
|
- <div class="flex items-center justify-center">
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- v-if="scope.row.fileType !== 'content'"
|
|
|
- link
|
|
|
- @click="handleDownload(scope.row.filePath)"
|
|
|
- v-hasPermi="['rq:iot-info:download']"
|
|
|
- >
|
|
|
- <Icon icon="ep:download" />{{ t('file.dow') }}
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- v-if="scope.row.fileType !== 'content'"
|
|
|
- link
|
|
|
- @click="deleteInfo(scope.row.id)"
|
|
|
- v-hasPermi="['rq:iot-info:download']"
|
|
|
- >
|
|
|
- <Icon icon="ep:delete" />{{ t('file.delete') }}
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
- </ContentWrap>
|
|
|
- </div>
|
|
|
- </el-row>
|
|
|
+ <el-button
|
|
|
+ type="danger"
|
|
|
+ v-if="scope.row.fileType !== 'content'"
|
|
|
+ link
|
|
|
+ @click="deleteInfo(scope.row.id)"
|
|
|
+ v-hasPermi="['rq:iot-info:download']">
|
|
|
+ <Icon icon="ep:delete" />{{ t('file.delete') }}
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </zm-table-column>
|
|
|
+ </zm-table>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+
|
|
|
<IotInfoFormTree
|
|
|
ref="formRef"
|
|
|
@success="getList"
|
|
|
:deviceId="deviceId"
|
|
|
:nodeId="nodeId"
|
|
|
- :classId="clickNodeId"
|
|
|
- />
|
|
|
+ :classId="clickNodeId" />
|
|
|
</template>
|
|
|
<script lang="ts" setup>
|
|
|
-import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
|
|
|
-import { dateFormatter } from '@/utils/formatTime'
|
|
|
import IotInfoFormTree from '@/views/pms/iotinfo/IotInfoFormTree.vue'
|
|
|
import * as IotInfoApi from '@/api/pms/iotinfo'
|
|
|
-import { IotInfoVO } from '@/api/pms/iotinfo'
|
|
|
-import { ref, onMounted, onUnmounted } from 'vue'
|
|
|
+import { ref, onMounted } from 'vue'
|
|
|
+import { Base64 } from 'js-base64'
|
|
|
|
|
|
import PmsTree from '@/views/system/tree/PmsTree.vue'
|
|
|
-import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
|
|
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
|
|
|
import { IotInfoClassifyApi } from '@/api/pms/info'
|
|
|
import { IotTreeApi } from '@/api/system/tree'
|
|
|
defineOptions({ name: 'IotTree' })
|
|
|
|
|
|
-const container = ref(null)
|
|
|
-const leftWidth = ref(350) // 初始左侧宽度
|
|
|
-const rightWidth = ref(window.innerWidth * 0.8)
|
|
|
-let isDragging = false
|
|
|
+type TreeKey = number | string
|
|
|
+
|
|
|
+interface QueryParams {
|
|
|
+ pageNo: number
|
|
|
+ pageSize: number
|
|
|
+ filename: string | null
|
|
|
+ fileType: string | null
|
|
|
+ createTime: string[]
|
|
|
+ deviceId: TreeKey | null
|
|
|
+ classId: TreeKey | null
|
|
|
+ deptId?: TreeKey
|
|
|
+ allName: string | null
|
|
|
+}
|
|
|
+
|
|
|
+interface BreadcrumbItem {
|
|
|
+ id: TreeKey | null
|
|
|
+ name: string
|
|
|
+ type?: string
|
|
|
+}
|
|
|
+
|
|
|
+interface FileRow {
|
|
|
+ id: TreeKey
|
|
|
+ originId?: TreeKey
|
|
|
+ parentId?: TreeKey
|
|
|
+ name?: string
|
|
|
+ filename?: string
|
|
|
+ fileType?: string
|
|
|
+ filePath?: string
|
|
|
+ fileSize?: string
|
|
|
+ fileClassify?: string
|
|
|
+ deptName?: string
|
|
|
+ deviceCode?: string
|
|
|
+ type?: string
|
|
|
+}
|
|
|
+
|
|
|
+interface IotInfoFormTreeExpose {
|
|
|
+ open: (type: string, id?: number) => void
|
|
|
+}
|
|
|
+
|
|
|
const uploadLoading = ref(false)
|
|
|
|
|
|
const searchFolderAndFile = async () => {
|
|
|
- debugger
|
|
|
formLoading.value = true
|
|
|
const data = await IotInfoApi.IotInfoApi.getAllChildContentFile(queryParams)
|
|
|
- debugger
|
|
|
list.value = data
|
|
|
formLoading.value = false
|
|
|
queryParams.filename = ''
|
|
|
}
|
|
|
-const openWeb = (url) => {
|
|
|
- window.open(
|
|
|
- 'http://1.94.244.160:8012/onlinePreview?url=' + encodeURIComponent(Base64.encode(url))
|
|
|
- )
|
|
|
-}
|
|
|
-const handleView = (row) => {
|
|
|
- openForm('detail', row.id)
|
|
|
-}
|
|
|
-const startDrag = (e) => {
|
|
|
- isDragging = true
|
|
|
- document.addEventListener('mousemove', onDrag)
|
|
|
- document.addEventListener('mouseup', stopDrag)
|
|
|
-}
|
|
|
-const topNodeId = ref('')
|
|
|
-const successList = async (id) => {
|
|
|
+const topNodeId = ref<TreeKey | null>(null)
|
|
|
+const successList = async (id?: TreeKey) => {
|
|
|
+ if (id === undefined) return
|
|
|
+
|
|
|
queryParams.classId = id
|
|
|
topNodeId.value = id
|
|
|
const rootItem = breadcrumbs.value.find((item) => item.type === 'root')
|
|
|
@@ -270,34 +267,15 @@ const successList = async (id) => {
|
|
|
// queryParams.classId = ''
|
|
|
}
|
|
|
|
|
|
-const onDrag = (e) => {
|
|
|
- if (!isDragging) return
|
|
|
-
|
|
|
- const containerRect = container.value.getBoundingClientRect()
|
|
|
- const newWidth = e.clientX - containerRect.left
|
|
|
-
|
|
|
- // 设置最小和最大宽度限制
|
|
|
- if (newWidth > 300 && newWidth < containerRect.width - 100) {
|
|
|
- leftWidth.value = newWidth
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const stopDrag = () => {
|
|
|
- isDragging = false
|
|
|
- document.removeEventListener('mousemove', onDrag)
|
|
|
- document.removeEventListener('mouseup', stopDrag)
|
|
|
-}
|
|
|
-
|
|
|
const queryFormRef = ref() // 搜索的表单
|
|
|
const { t } = useI18n() // 国际化
|
|
|
const message = useMessage() // 消息弹窗
|
|
|
-const loading = ref(true) // 列表的加载中
|
|
|
const { params } = useRoute() // 查询参数
|
|
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
|
|
-const list = ref<IotDeviceVO[]>([]) // 列表的数据
|
|
|
+const list = ref<FileRow[]>([]) // 列表的数据
|
|
|
// const total = ref(0) // 列表的总页数
|
|
|
-const id = ref()
|
|
|
-const queryParams = reactive({
|
|
|
+const id = ref(0)
|
|
|
+const queryParams = reactive<QueryParams>({
|
|
|
pageNo: 1,
|
|
|
pageSize: 10,
|
|
|
filename: null,
|
|
|
@@ -308,18 +286,8 @@ const queryParams = reactive({
|
|
|
deptId: undefined,
|
|
|
allName: null
|
|
|
})
|
|
|
-// SPU 表单数据
|
|
|
-const formData = ref({
|
|
|
- id: undefined,
|
|
|
- deviceId: undefined,
|
|
|
- deptId: undefined,
|
|
|
- filename: undefined,
|
|
|
- fileType: undefined,
|
|
|
- filePath: undefined,
|
|
|
- remark: undefined,
|
|
|
- classId: undefined
|
|
|
-})
|
|
|
-const handleDownload = async (url) => {
|
|
|
+const handleDownload = async (url?: string) => {
|
|
|
+ if (!url) return
|
|
|
try {
|
|
|
formLoading.value = true
|
|
|
const response = await fetch(url)
|
|
|
@@ -328,7 +296,7 @@ const handleDownload = async (url) => {
|
|
|
|
|
|
const link = document.createElement('a')
|
|
|
link.href = downloadUrl
|
|
|
- link.download = url.split('/').pop() // 自动获取文件名:ml-citation{ref="3" data="citationList"}
|
|
|
+ link.download = url.split('/').pop()! // 自动获取文件名:ml-citation{ref="3" data="citationList"}
|
|
|
link.click()
|
|
|
|
|
|
URL.revokeObjectURL(downloadUrl)
|
|
|
@@ -337,9 +305,9 @@ const handleDownload = async (url) => {
|
|
|
console.error('下载失败:', error)
|
|
|
}
|
|
|
}
|
|
|
-const deleteInfo = async (id) => {
|
|
|
+const deleteInfo = async (id: TreeKey) => {
|
|
|
await message.delConfirm()
|
|
|
- await IotInfoApi.IotInfoApi.deleteIotInfo(id).then((res) => {
|
|
|
+ await IotInfoApi.IotInfoApi.deleteIotInfo(Number(id)).then((res) => {
|
|
|
if (res) {
|
|
|
message.success('文件删除成功')
|
|
|
getList()
|
|
|
@@ -348,23 +316,7 @@ const deleteInfo = async (id) => {
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
-// const handleFileView = (url: string) => {
|
|
|
-// window.open(
|
|
|
-// 'http://1.94.244.160:8012/onlinePreview?url=' + encodeURIComponent(Base64.encode(url))
|
|
|
-// )
|
|
|
-// }
|
|
|
-const handleDelete = async (id: number) => {
|
|
|
- try {
|
|
|
- // 删除的二次确认
|
|
|
- await message.delConfirm()
|
|
|
- // 发起删除
|
|
|
- await IotInfoApi.IotInfoApi.deleteIotInfo(id)
|
|
|
- message.success(t('common.delSuccess'))
|
|
|
- // 刷新列表
|
|
|
- await getList()
|
|
|
- } catch {}
|
|
|
-}
|
|
|
-const formRef = ref()
|
|
|
+const formRef = ref<IotInfoFormTreeExpose>()
|
|
|
const openForm = async (type: string, id?: number) => {
|
|
|
// if (classType.value==='dept'){
|
|
|
// message.error(t('common.deptChoose'))
|
|
|
@@ -373,10 +325,11 @@ const openForm = async (type: string, id?: number) => {
|
|
|
uploadLoading.value = true
|
|
|
if (!queryParams.classId) {
|
|
|
message.error(t('common.leftNode'))
|
|
|
+ uploadLoading.value = false
|
|
|
return
|
|
|
}
|
|
|
- formRef.value.open(type, id)
|
|
|
- await new Promise((resolve) => {
|
|
|
+ formRef.value?.open(type, id)
|
|
|
+ await new Promise<void>((resolve) => {
|
|
|
setTimeout(() => {
|
|
|
resolve() // 操作完成后resolve
|
|
|
}, 2000) // 模拟2秒耗时
|
|
|
@@ -386,14 +339,13 @@ const openForm = async (type: string, id?: number) => {
|
|
|
const deviceId = ref('')
|
|
|
const clickNodeId = ref('')
|
|
|
const nodeId = ref('')
|
|
|
-const classType = ref('')
|
|
|
|
|
|
-const breadcrumbs = ref([
|
|
|
+const breadcrumbs = ref<BreadcrumbItem[]>([
|
|
|
{ id: null, name: '科瑞石油技术', type: 'root' } // 根节点
|
|
|
])
|
|
|
|
|
|
// 共享的面包屑更新逻辑
|
|
|
-const updateBreadcrumbs = async (node) => {
|
|
|
+const updateBreadcrumbs = async (node: FileRow) => {
|
|
|
// 查找当前节点是否已在面包屑中
|
|
|
const currentIndex = breadcrumbs.value.findIndex((item) => item.id === node.id)
|
|
|
|
|
|
@@ -402,7 +354,7 @@ const updateBreadcrumbs = async (node) => {
|
|
|
breadcrumbs.value = breadcrumbs.value.slice(0, currentIndex + 1)
|
|
|
} else {
|
|
|
// 新增节点到面包屑
|
|
|
- breadcrumbs.value.push({ id: node.id, name: node.filename || node.name })
|
|
|
+ breadcrumbs.value.push({ id: node.id, name: node.filename || node.name || '' })
|
|
|
}
|
|
|
|
|
|
// 更新表格数据
|
|
|
@@ -412,8 +364,10 @@ const updateBreadcrumbs = async (node) => {
|
|
|
}
|
|
|
|
|
|
// 表格行点击事件
|
|
|
-const inContent = async (row) => {
|
|
|
+const inContent = async (row: FileRow) => {
|
|
|
if (row.fileType != 'content') {
|
|
|
+ if (!row.filePath) return
|
|
|
+
|
|
|
window.open(
|
|
|
'http://doc.deepoil.cc:8012/onlinePreview?url=' +
|
|
|
encodeURIComponent(Base64.encode(row.filePath))
|
|
|
@@ -426,14 +380,14 @@ const inContent = async (row) => {
|
|
|
await updateBreadcrumbs(row)
|
|
|
// 可以添加其他表格行点击需要的逻辑
|
|
|
queryParams.classId = row.id
|
|
|
- nodeId.value = row.id
|
|
|
+ nodeId.value = String(row.id)
|
|
|
const data = await IotInfoApi.IotInfoApi.getChildContentFile(queryParams)
|
|
|
formLoading.value = false
|
|
|
list.value = data
|
|
|
}
|
|
|
|
|
|
// 文件树节点点击事件
|
|
|
-const handleFileNodeClick = async (row) => {
|
|
|
+const handleFileNodeClick = async (row: FileRow) => {
|
|
|
queryParams.filename = ''
|
|
|
const parentItems = await IotTreeApi.getParentIds(row.id)
|
|
|
breadcrumbs.value = []
|
|
|
@@ -443,12 +397,11 @@ const handleFileNodeClick = async (row) => {
|
|
|
|
|
|
queryParams.classId = row.id
|
|
|
if (row.type == 'device') {
|
|
|
- id.value = row.originId
|
|
|
+ id.value = Number(row.originId)
|
|
|
}
|
|
|
|
|
|
- classType.value = row.type
|
|
|
if (row.type === 'device') {
|
|
|
- deviceId.value = row.originId
|
|
|
+ deviceId.value = String(row.originId)
|
|
|
const queryParam = {
|
|
|
deviceId: row.originId,
|
|
|
pageNo: 1,
|
|
|
@@ -457,25 +410,26 @@ const handleFileNodeClick = async (row) => {
|
|
|
const data = await IotInfoClassifyApi.getIotInfoClassifyPage(queryParam)
|
|
|
if (data) {
|
|
|
const target = data.filter((item) => item.parentId === 0)
|
|
|
- clickNodeId.value = target[0].id
|
|
|
+ clickNodeId.value = String(target[0]?.id ?? '')
|
|
|
}
|
|
|
} else if (row.type === 'file') {
|
|
|
- clickNodeId.value = row.originId
|
|
|
+ clickNodeId.value = String(row.originId)
|
|
|
} else if (row.type === 'dept') {
|
|
|
// message.error("请选择设备及文件节点")
|
|
|
// return
|
|
|
}
|
|
|
- nodeId.value = row.id
|
|
|
+ nodeId.value = String(row.id)
|
|
|
await getList()
|
|
|
}
|
|
|
|
|
|
// 面包屑点击事件
|
|
|
-const handleBreadcrumbClick = async (index) => {
|
|
|
+const handleBreadcrumbClick = async (index: number) => {
|
|
|
queryParams.filename = ''
|
|
|
- formLoading.value = true
|
|
|
// 忽略当前节点的点击
|
|
|
if (index === breadcrumbs.value.length - 1) return
|
|
|
|
|
|
+ formLoading.value = true
|
|
|
+
|
|
|
// 截断面包屑到点击的节点
|
|
|
const targetBreadcrumbs = breadcrumbs.value.slice(0, index + 1)
|
|
|
breadcrumbs.value = targetBreadcrumbs
|
|
|
@@ -485,57 +439,24 @@ const handleBreadcrumbClick = async (index) => {
|
|
|
if (!targetId) {
|
|
|
targetId = topNodeId.value
|
|
|
}
|
|
|
+ if (!targetId) {
|
|
|
+ formLoading.value = false
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
queryParams.classId = targetId
|
|
|
- clickNodeId.value = targetId
|
|
|
- nodeId.value = targetId
|
|
|
- debugger
|
|
|
+ clickNodeId.value = String(targetId)
|
|
|
+ nodeId.value = String(targetId)
|
|
|
const data = await IotInfoApi.IotInfoApi.getChildContentFile(queryParams)
|
|
|
list.value = data
|
|
|
formLoading.value = false
|
|
|
}
|
|
|
|
|
|
-// const handleFileNodeClick = async (row) => {
|
|
|
-// queryParams.classId = row.id
|
|
|
-// classType.value = row.type
|
|
|
-// if (row.type==='device') {
|
|
|
-// deviceId.value = row.originId
|
|
|
-// const queryParam = {
|
|
|
-// deviceId: row.originId,
|
|
|
-// pageNo: 1,
|
|
|
-// pagesize: 10,
|
|
|
-// }
|
|
|
-// const data = await IotInfoClassifyApi.getIotInfoClassifyPage(queryParam)
|
|
|
-// debugger
|
|
|
-// if (data){
|
|
|
-// const target = data.filter((item)=> item.parentId===0)
|
|
|
-// clickNodeId.value = target[0].id
|
|
|
-// }
|
|
|
-// } else if (row.type === 'file'){
|
|
|
-// clickNodeId.value = row.originId
|
|
|
-// } else if (row.type==='dept') {
|
|
|
-// // message.error("请选择设备及文件节点")
|
|
|
-// // return
|
|
|
-// }
|
|
|
-// nodeId.value = row.id
|
|
|
-// await getList()
|
|
|
-// }
|
|
|
-/** 获得详情 */
|
|
|
-// const getDetail = async () => {
|
|
|
-// if (id) {
|
|
|
-// formLoading.value = true
|
|
|
-// try {
|
|
|
-// formData.value = (await IotDeviceApi.getIotDevice(id)) as IotDeviceVO
|
|
|
-// } finally {
|
|
|
-// formLoading.value = false
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
/** 查询列表 */
|
|
|
const getList = async () => {
|
|
|
formLoading.value = true
|
|
|
try {
|
|
|
const data = await IotInfoApi.IotInfoApi.getChildContentFile(queryParams)
|
|
|
- debugger
|
|
|
list.value = data
|
|
|
} finally {
|
|
|
formLoading.value = false
|
|
|
@@ -552,90 +473,89 @@ const resetQuery = () => {
|
|
|
queryFormRef.value?.resetFields()
|
|
|
handleQuery()
|
|
|
}
|
|
|
-const { wsCache } = useCache()
|
|
|
+
|
|
|
/** 初始化 */
|
|
|
onMounted(async () => {
|
|
|
- // await getDetail()
|
|
|
- // queryParams.deptId = wsCache.get(CACHE_KEY.USER).user.deptId;
|
|
|
- // await getList()
|
|
|
- // deviceId.value = params.id as unknown as number
|
|
|
- id.value = params.id as unknown as number
|
|
|
+ id.value = Number(params.id) || 0
|
|
|
})
|
|
|
</script>
|
|
|
<style scoped>
|
|
|
-::v-deep .breadcrumb-container {
|
|
|
- padding: 12px 16px;
|
|
|
- background-color: #f5f7fa;
|
|
|
- border-radius: 6px;
|
|
|
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.06);
|
|
|
+:deep(.el-form-item) {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.search-panel .el-form-item) {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.search-panel .el-form-item__label) {
|
|
|
+ height: 32px;
|
|
|
+ line-height: 32px;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.search-panel .el-form-item__content) {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
}
|
|
|
-::v-deep .custom-breadcrumb-item {
|
|
|
+
|
|
|
+.tree-page {
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.search-panel,
|
|
|
+.breadcrumb-panel,
|
|
|
+.table-panel {
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.breadcrumb-container) {
|
|
|
+ min-width: 0;
|
|
|
+ padding: 0;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.custom-breadcrumb-item) {
|
|
|
font-size: 14px;
|
|
|
- font-weight: bold;
|
|
|
+ font-weight: 600;
|
|
|
}
|
|
|
|
|
|
-/* 面包屑文本样式 */
|
|
|
-::v-deep .el-breadcrumb__item .el-breadcrumb__inner {
|
|
|
+:deep(.el-breadcrumb__item .el-breadcrumb__inner) {
|
|
|
+ padding: 2px 4px;
|
|
|
color: #101010;
|
|
|
text-decoration: none;
|
|
|
- padding: 2px 4px;
|
|
|
border-radius: 2px;
|
|
|
transition: all 0.2s ease;
|
|
|
}
|
|
|
|
|
|
-/* 可点击项悬停效果 */
|
|
|
-::v-deep .el-breadcrumb__item:not(:last-child) .el-breadcrumb__inner:hover {
|
|
|
+:deep(.el-breadcrumb__item:not(:last-child) .el-breadcrumb__inner:hover) {
|
|
|
color: #409eff;
|
|
|
- background-color: rgba(64, 158, 255, 0.1);
|
|
|
cursor: pointer;
|
|
|
+ background-color: rgb(64 158 255 / 10%);
|
|
|
}
|
|
|
|
|
|
-/* 当前项样式 */
|
|
|
-::v-deep .el-breadcrumb__item:last-child .el-breadcrumb__inner {
|
|
|
- color: #1890ff;
|
|
|
+:deep(.el-breadcrumb__item:last-child .el-breadcrumb__inner) {
|
|
|
font-weight: 500;
|
|
|
+ color: #1890ff;
|
|
|
cursor: default;
|
|
|
}
|
|
|
|
|
|
-/* 分隔符样式优化 */
|
|
|
-::v-deep .el-breadcrumb__separator {
|
|
|
+:deep(.el-breadcrumb__separator) {
|
|
|
margin: 0 8px;
|
|
|
- color: #0954f6;
|
|
|
font-size: 12px;
|
|
|
+ color: #0954f6;
|
|
|
}
|
|
|
|
|
|
-.custom-table {
|
|
|
- cursor: pointer;
|
|
|
- --el-table-row-hover-bg-color: #f5f7fa; /* 优化悬停背景色 */
|
|
|
-}
|
|
|
-
|
|
|
-.container-tree {
|
|
|
- display: flex;
|
|
|
- height: 100%;
|
|
|
- user-select: none; /* 防止拖动时选中文本 */
|
|
|
-}
|
|
|
-
|
|
|
-.left-tree {
|
|
|
- background: #f0f0f0;
|
|
|
+:deep(.zm-table) {
|
|
|
height: 100%;
|
|
|
- overflow: auto;
|
|
|
-}
|
|
|
|
|
|
-.right-tree {
|
|
|
- flex: 1;
|
|
|
- height: 100%;
|
|
|
- overflow: auto;
|
|
|
- margin-left: 15px;
|
|
|
-}
|
|
|
-
|
|
|
-.divider-tree {
|
|
|
- width: 2px;
|
|
|
- background: #ccc;
|
|
|
- cursor: col-resize;
|
|
|
- position: relative;
|
|
|
-}
|
|
|
+ .el-table__cell {
|
|
|
+ height: 42px;
|
|
|
+ }
|
|
|
|
|
|
-.divider-tree:hover {
|
|
|
- background: #666;
|
|
|
+ .el-table__row {
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|