|
@@ -0,0 +1,282 @@
|
|
|
|
+<template>
|
|
|
|
+ <ContentWrap>
|
|
|
|
+ <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"
|
|
|
|
+ >
|
|
|
|
+ {{ item.name }}
|
|
|
|
+ </el-breadcrumb-item>
|
|
|
|
+ </el-breadcrumb>
|
|
|
|
+ </ContentWrap>
|
|
|
|
+ <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-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==='pic'||scope.row.fileClassify==='jpg'||scope.row.fileClassify==='png'" icon="ep:picture-filled" color="#2183D1"/>
|
|
|
|
+ <Icon v-else-if="scope.row.fileType==='file'&&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==='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="primary" link @click="handleView( scope.row)">-->
|
|
|
|
+ <!-- <Icon icon="ep:view" />{{t('file.preview')}}-->
|
|
|
|
+ <!-- </el-button>-->
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ </el-table>
|
|
|
|
+ </ContentWrap>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup lang="ts">
|
|
|
|
+import {DICT_TYPE, getStrDictOptions} from "@/utils/dict";
|
|
|
|
+import {ref} from "vue";
|
|
|
|
+import {IotDeviceVO} from "@/api/pms/device";
|
|
|
|
+import {IotInfoApi} from "@/api/pms/iotinfo";
|
|
|
|
+import {IotTreeApi} from "@/api/system/tree";
|
|
|
|
+
|
|
|
|
+const { t } = useI18n() // 国际化
|
|
|
|
+const queryFormRef = ref()
|
|
|
|
+const formLoading = ref(false)
|
|
|
|
+const list = ref<IotDeviceVO[]>([])
|
|
|
|
+const props = defineProps<{ deviceId?: number,deviceName?:string , deviceCategoryName?:string }>()
|
|
|
|
+const topNodeId = ref('')
|
|
|
|
+
|
|
|
|
+const queryParams = reactive({
|
|
|
|
+ pageNo: 1,
|
|
|
|
+ pageSize: 10,
|
|
|
|
+ filename: null,
|
|
|
|
+ fileType: null,
|
|
|
|
+ createTime: [],
|
|
|
|
+ deviceId: null,
|
|
|
|
+ classId: null,
|
|
|
|
+ deptId: undefined,
|
|
|
|
+ allName: null,
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+const breadcrumbs = ref([
|
|
|
|
+ { id: null, name: '',type:'root' } // 根节点
|
|
|
|
+])
|
|
|
|
+
|
|
|
|
+// 面包屑点击事件
|
|
|
|
+const handleBreadcrumbClick = async (index) => {
|
|
|
|
+ queryParams.filename = ''
|
|
|
|
+ formLoading.value = true
|
|
|
|
+ // 忽略当前节点的点击
|
|
|
|
+ if (index === breadcrumbs.value.length - 1) return
|
|
|
|
+
|
|
|
|
+ // 截断面包屑到点击的节点
|
|
|
|
+ const targetBreadcrumbs = breadcrumbs.value.slice(0, index + 1)
|
|
|
|
+ breadcrumbs.value = targetBreadcrumbs
|
|
|
|
+
|
|
|
|
+ // 获取对应节点的数据
|
|
|
|
+ let targetId = targetBreadcrumbs[index].id
|
|
|
|
+ if (!targetId){
|
|
|
|
+ targetId = topNodeId.value
|
|
|
|
+ }
|
|
|
|
+ queryParams.classId = targetId
|
|
|
|
+ const data = await IotInfoApi.getChildContentFile(queryParams)
|
|
|
|
+ list.value = data
|
|
|
|
+ formLoading.value = false
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/** 搜索按钮操作 */
|
|
|
|
+const handleQuery = () => {
|
|
|
|
+ queryParams.pageNo = 1
|
|
|
|
+ getList()
|
|
|
|
+}
|
|
|
|
+const getList = async () => {
|
|
|
|
+ formLoading.value = true
|
|
|
|
+ try {
|
|
|
|
+ const data = await IotInfoApi.getChildContentFile(queryParams)
|
|
|
|
+ list.value = data
|
|
|
|
+ } finally {
|
|
|
|
+ formLoading.value = false
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const inContent = async (row) => {
|
|
|
|
+ debugger
|
|
|
|
+ if (row.fileType!='content') {
|
|
|
|
+ window.open('http://1.94.244.160:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(row.filePath)));
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ queryParams.filename = ''
|
|
|
|
+ formLoading.value = true
|
|
|
|
+ // 调用共享方法更新面包屑和表格
|
|
|
|
+ await updateBreadcrumbs(row)
|
|
|
|
+ // 可以添加其他表格行点击需要的逻辑
|
|
|
|
+ queryParams.classId = row.id;
|
|
|
|
+ const data = await IotInfoApi.getChildContentFile(queryParams)
|
|
|
|
+ formLoading.value = false
|
|
|
|
+ list.value = data
|
|
|
|
+}
|
|
|
|
+const updateBreadcrumbs = async (node) => {
|
|
|
|
+ // 查找当前节点是否已在面包屑中
|
|
|
|
+ const currentIndex = breadcrumbs.value.findIndex(item => item.id === node.id)
|
|
|
|
+
|
|
|
|
+ if (currentIndex > -1) {
|
|
|
|
+ // 如果已存在则截断后面的节点
|
|
|
|
+ breadcrumbs.value = breadcrumbs.value.slice(0, currentIndex + 1)
|
|
|
|
+ } else {
|
|
|
|
+ // 新增节点到面包屑
|
|
|
|
+ breadcrumbs.value.push({ id: node.id, name: node.filename || node.name })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 更新表格数据
|
|
|
|
+ queryParams.classId = node.id;
|
|
|
|
+ const data = await IotInfoApi.getChildContentFile(queryParams)
|
|
|
|
+ list.value = data
|
|
|
|
+}
|
|
|
|
+const handleDownload = async (url) => {
|
|
|
|
+ try {
|
|
|
|
+ const response = await fetch(url)
|
|
|
|
+ const blob = await response.blob()
|
|
|
|
+ const downloadUrl = window.URL.createObjectURL(blob)
|
|
|
|
+
|
|
|
|
+ const link = document.createElement('a')
|
|
|
|
+ link.href = downloadUrl
|
|
|
|
+ link.download = url.split('/').pop() // 自动获取文件名:ml-citation{ref="3" data="citationList"}
|
|
|
|
+ link.click()
|
|
|
|
+
|
|
|
|
+ URL.revokeObjectURL(downloadUrl)
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('下载失败:', error)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/** 重置按钮操作 */
|
|
|
|
+const resetQuery = () => {
|
|
|
|
+ queryFormRef.value?.resetFields()
|
|
|
|
+ handleQuery()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+onMounted(async ()=>{
|
|
|
|
+ const deviceid = props.deviceId
|
|
|
|
+ debugger
|
|
|
|
+ const data = await IotTreeApi.getDeviceTree(deviceid)
|
|
|
|
+ queryParams.classId = data
|
|
|
|
+ const listdata = await IotInfoApi.getChildContentFile(queryParams)
|
|
|
|
+ list.value = listdata
|
|
|
|
+ breadcrumbs.value[0].name = props.deviceName
|
|
|
|
+ breadcrumbs.value[0].id = data;
|
|
|
|
+})
|
|
|
|
+</script>
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+.custom-table {
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ --el-table-row-hover-bg-color: #f5f7fa; /* 优化悬停背景色 */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+::v-deep .breadcrumb-container {
|
|
|
|
+ padding: 12px 16px;
|
|
|
|
+ background-color: #f5f7fa;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.06);
|
|
|
|
+}
|
|
|
|
+::v-deep .custom-breadcrumb-item {
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ font-weight: bold;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* 面包屑文本样式 */
|
|
|
|
+::v-deep .el-breadcrumb__item .el-breadcrumb__inner {
|
|
|
|
+ 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 {
|
|
|
|
+ color: #409eff;
|
|
|
|
+ background-color: rgba(64, 158, 255, 0.1);
|
|
|
|
+ cursor: pointer;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* 当前项样式 */
|
|
|
|
+::v-deep .el-breadcrumb__item:last-child .el-breadcrumb__inner {
|
|
|
|
+ color: #1890ff;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ cursor: default;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* 分隔符样式优化 */
|
|
|
|
+::v-deep .el-breadcrumb__separator {
|
|
|
|
+ margin: 0 8px;
|
|
|
|
+ color: #0954f6;
|
|
|
|
+ font-size: 12px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+</style>
|