This commit is contained in:
GGJ
2024-09-11 18:57:06 +08:00
18 changed files with 828 additions and 100 deletions

View File

@@ -0,0 +1,49 @@
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 reStartDevice(data) {
return createAxios({
url: `/cs-device-boot/EquipmentDelivery/rebootDevice?nDid=${data.nDid}`,
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
})
}

View File

@@ -0,0 +1,17 @@
import createAxios from '@/utils/request'
// 获取设备补招页面数据
export function getMakeUpData(data: any) {
return createAxios({
url: '/cs-harmonic-boot/offlineDataUpload/makeUpData?lineId='+data,
method: 'POST'
})
}
//查询装置目录-文件
export function getAskDirOrFile(data: any) {
return createAxios({
url: `/cs-harmonic-boot/offlineDataUpload/askDirOrFile?fileType=${data.fileType}&nDid=${data.nDid}&path=${data.path}&prjName=${data.prjName}`,
method: 'POST'
})
}

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1724384468716" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6792" width="24" height="24" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M834.6624 409.6a40.8576 40.8576 0 0 0-13.7728-30.63808l-254.32064-254.32064a40.87296 40.87296 0 0 0-31.1552-11.84768c-0.97792-0.07168-1.9456-0.1536-2.93376-0.1536H230.4a40.96 40.96 0 0 0-40.96 40.96v716.8a40.96 40.96 0 0 0 40.96 40.96h563.2a40.96 40.96 0 0 0 40.96-40.96V419.84c0-1.62304-0.11776-3.21536-0.3072-4.79232a40.6528 40.6528 0 0 0 0.4096-5.44768zM578.56 252.48256L694.71744 368.64H578.56V252.48256zM271.36 829.44V194.56h225.28v215.04a40.96 40.96 0 0 0 40.96 40.96h215.04v378.88H271.36z" p-id="6793" fill="#012B6A"></path><path d="M371.2 660.48h133.12a40.96 40.96 0 0 0 0-81.92h-133.12a40.96 40.96 0 0 0 0 81.92zM650.24 696.32H363.52a40.96 40.96 0 0 0 0 81.92h286.72a40.96 40.96 0 0 0 0-81.92z" p-id="6794" fill="#012B6A"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1724374828868" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14992" width="48" height="48" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M912 208H427.872l-50.368-94.176A63.936 63.936 0 0 0 321.056 80H112c-35.296 0-64 28.704-64 64v736c0 35.296 28.704 64 64 64h800c35.296 0 64-28.704 64-64v-608c0-35.296-28.704-64-64-64z m-800-64h209.056l68.448 128H912v97.984c-0.416 0-0.8-0.128-1.216-0.128H113.248c-0.416 0-0.8 0.128-1.248 0.128V144z m0 736v-96l1.248-350.144 798.752 1.216V784h0.064v96H112z" fill="#012B6A" p-id="14993"></path></svg>

After

Width:  |  Height:  |  Size: 727 B

View File

@@ -1,5 +1,5 @@
<template>
<Tree ref="treRef" :width="width" :data="tree" />
<Tree ref="treRef" :width="width" :data="tree" @changePointType="changePointType" />
</template>
<script lang="ts" setup>
@@ -10,13 +10,15 @@ import { useConfig } from '@/stores/config'
defineOptions({
name: 'govern/deviceTree'
})
const emit = defineEmits(['init', 'checkChange'])
const emit = defineEmits(['init', 'checkChange', 'pointTypeChange'])
const config = useConfig()
const tree = ref()
const treRef = ref()
const width = ref('')
const changePointType = (val: any, obj: any) => {
emit('pointTypeChange', val, obj)
}
getLineTree().then(res => {
console.log(res.data, '设备监控666')
let arr1: any[] = []
let arr2: any[] = []
//治理设备
@@ -30,10 +32,12 @@ getLineTree().then(res => {
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach((item3: any) => {
item3.icon = 'el-icon-Platform'
item3.color = item3.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item3.color =
item3.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item3.children.forEach((item4: any) => {
item4.icon = 'el-icon-Platform'
item4.color = item4.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item4.color =
item4.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
// item4.color = '#e26257 !important'
arr1.push(item4)
})
@@ -44,11 +48,9 @@ getLineTree().then(res => {
item.children.forEach((item: any) => {
item.icon = 'el-icon-Platform'
item.color = config.getColorVal('elementUiPrimary')
console.log(item.comFlag,"88888");
item.color = item.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
item.children.forEach((item2: any) => {
item2.icon = 'el-icon-Platform'
console.log(item2.comFlag,"88888");
item2.color = item2.comFlag === 2 ? config.getColorVal('elementUiPrimary') : '#e26257 !important'
arr2.push(item2)
})

View File

@@ -31,9 +31,8 @@
v-if="props.canExpand && route.path != '/admin/govern/reportCore/statistics/index'"
/>
</div>
<el-collapse accordion v-model="activeName" style="flex: 1; height: 100%" @change="changeDevice">
<el-collapse-item title="治理设备" :name="0">
<el-collapse-item title="治理设备" name="0">
<el-tree
style="height: calc(100vh - 350px); overflow: auto"
ref="treeRef1"
@@ -58,7 +57,7 @@
</template>
</el-tree>
</el-collapse-item>
<el-collapse-item title="便携式设备" :name="1">
<el-collapse-item title="便携式设备" name="1">
<el-tree
style="height: calc(100vh - 270px); overflow: auto"
ref="treeRef2"
@@ -91,12 +90,12 @@
<script lang="ts" setup>
import useCurrentInstance from '@/utils/useCurrentInstance'
import { ElTree } from 'element-plus'
import { ref, watch } from 'vue'
import { ref, watch, defineEmits } from 'vue'
import { useRoute } from 'vue-router'
defineOptions({
name: 'govern/tree'
})
const emit = defineEmits(['changePointType'])
interface Props {
width?: string
canExpand?: boolean
@@ -112,10 +111,9 @@ const props = withDefaults(defineProps<Props>(), {
})
const route = useRoute()
console.log(route, '6666677788889')
const { proxy } = useCurrentInstance()
const menuCollapse = ref(false)
const activeName = ref(0)
const activeName = ref('0')
const filterText = ref('')
const defaultProps = {
label: 'name',
@@ -149,7 +147,7 @@ watch(
)
watch(filterText, val => {
if (activeName.value == 0) {
if (activeName.value == '0') {
treeRef1.value!.filter(val)
} else {
treeRef2.value!.filter(val)
@@ -172,17 +170,22 @@ const changeDevice = (val: any) => {
arr2.push(item2)
})
})
if (val == 0) {
arr2.map(item => {
if (val == '0') {
arr2.map((item: any) => {
item.checked = false
})
treeRef1.value.setCurrentKey(arr1[0]?.id)
treeRef1?.value.setCurrentKey(arr1[0]?.id)
emit('changePointType', activeName.value, arr1[0])
} else {
arr1.map(item => {
arr1.map((item: any) => {
item.checked = false
})
treeRef2.value.setCurrentKey(arr2[0]?.id)
treeRef2?.value.setCurrentKey(arr2[0]?.id)
emit('changePointType', activeName.value, arr2[0])
}
// if(activeName.value){
// emit('changePointType', activeName.value)
// }
}
const onMenuCollapse = () => {
menuCollapse.value = !menuCollapse.value

View File

@@ -44,7 +44,13 @@ const tableStore = new TableStore({
url: '/user-boot/function/getButtonById',
column: [
{ title: '普通接口/接口名称', field: 'name' },
{ title: '接口类型', field: 'type' },
{
title: '接口类型',
field: 'type',
formatter: row => {
return row.cellValue == 1 ? '普通借口' : '公用接口'
}
},
{ title: 'URL接口路径', field: 'path' },
{
title: '操作',

View File

@@ -59,7 +59,7 @@ const rules = {
code: [
{ 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位英文',
min: 3,
max: 20,

View File

@@ -1,9 +1,6 @@
<!-- 解析列表 -->
<template>
<el-dialog v-model="dialogVisible" title="解析列表" width="70%" draggable @closed="close">
<!-- <div class="header_btn">
<el-button type="primary" size="small" @click="handleBack" :icon="ArrowLeft">返回</el-button>
</div> -->
<TableHeader date-picker></TableHeader>
<Table ref="tableRef" />
<template #footer>
@@ -15,16 +12,19 @@
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, onMounted, provide } from 'vue'
import { ref, onMounted, provide, watch, onBeforeUnmount } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { ArrowLeft } from '@element-plus/icons-vue'
const emit = defineEmits(['back'])
const dialogVisible = ref(false)
const height = ref(0)
height.value = window.innerHeight < 1080 ? 180 : 400
const tableStore: any = new TableStore({
url: '/cs-device-boot/portableOfflLog/queryPage',
publicHeight: 210,
publicHeight: height.value,
method: 'POST',
column: [
// { width: '60', type: 'checkbox', fixed: 'left' },
@@ -76,8 +76,28 @@ const open = () => {
const close = () => {
dialogVisible.value = false
}
const initTable = () => {}
onMounted(() => {})
const updateViewportHeight = async () => {
// height.value = window.innerHeight;
height.value = window.innerHeight < 1080 ? 180 : 400
tableStore.table.publicHeight = height.value
// await tableStore.index()
}
onMounted(() => {
updateViewportHeight() // 初始化视口高度
window.addEventListener('resize', updateViewportHeight) // 监听窗口大小变化
})
onBeforeUnmount(() => {
window.removeEventListener('resize', updateViewportHeight) // 移除监听
})
defineExpose({ open })
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
::v-deep .el-dialog_body {
overflow-y: hidden !important;
.analysisTable {
height: 400px !important;
}
}
</style>

View File

@@ -5,40 +5,20 @@
v-loading="loading"
style="position: relative"
>
<PointTree @node-click="nodeClick" @init="nodeClick"></PointTree>
<PointTree @node-click="nodeClick" @init="nodeClick" @pointTypeChange="pointTypeChange"></PointTree>
<div class="device-control-right" v-if="deviceData">
<el-descriptions title="设备基本信息" class="mb10" :column="3" border>
<template #extra>
<el-button
v-if="dataSet.indexOf('_realtimedata') != -1"
size="small"
type="primary"
@click="handleDownLoadTemplate"
>
<el-button v-if="deviceType == '1'" size="small" type="primary" @click="handleDownLoadTemplate">
模版下载
</el-button>
<el-button
v-if="dataSet.indexOf('_realtimedata') != -1"
size="small"
type="primary"
@click="handleImport"
>
<el-button v-if="deviceType == '1'" size="small" type="primary" @click="handleImport">
离线数据导入
</el-button>
<el-button
v-if="dataSet.indexOf('_realtimedata') != -1"
size="small"
type="primary"
@click="handleaddDevice"
>
<el-button v-if="deviceType == '1'" size="small" type="primary" @click="handleaddDevice">
设备补招
</el-button>
<el-button
v-if="dataSet.indexOf('_realtimedata') != -1"
size="small"
type="primary"
@click="handleAnalysisList"
>
<el-button v-if="deviceType == '1'" size="small" type="primary" @click="handleAnalysisList">
解析列表
</el-button>
</template>
@@ -100,7 +80,16 @@
<el-button type="primary" icon="el-icon-Search" @click="handleClick">查询</el-button>
</el-form-item>
</el-form>
<div style="height: calc(100vh - 300px)" v-if="tableData.length == 0" v-loading="tableLoading"></div>
<div
style="height: calc(100vh - 300px)"
v-if="
dataSet.indexOf('_trenddata') == -1 &&
dataSet.indexOf('_realtimedata') == -1 &&
dataSet.indexOf('_event') == -1 &&
tableData.length == 0
"
v-loading="tableLoading"
></div>
<div
style="overflow: auto"
:style="{ height: tableHeight }"
@@ -360,7 +349,8 @@ const handleaddDevice = () => {
push({
path: '/supplementaryRecruitment',
query: {
id: '1111'
id: lineId.value,
ndid:deviceData.value.ndid
}
})
}
@@ -416,6 +406,12 @@ const nodeClick = async (e: anyObj) => {
loading.value = false
}
}
//治理设备和便携式设备切换判断
const deviceType = ref('0')
const pointTypeChange = (val: any, obj: any) => {
deviceType.value = val
nodeClick(obj)
}
const realTimeRef: any = ref()
const intRealTime = async (val: any) => {
await getTabsDataByType(val).then(res => {
@@ -526,17 +522,11 @@ const handleClick = async (tab?: any) => {
//模版下载
const handleDownLoadTemplate = () => {}
//解析列表
// const isAnalysisList = ref(false)
const analysisListRef = ref()
//打开解析列表
const handleAnalysisList = () => {
// isAnalysisList.value = true
analysisListRef.value && analysisListRef.value.open()
}
//返回
// const handleBackAnalysisList=()=>{
// isAnalysisList.value = false
// }
//离线数据导入
const offLineDataImportRef = ref()
const handleImport = () => {
@@ -591,18 +581,6 @@ const openGroup = () => {
})
})
}
watch(
() => dataSet.value,
(val: any, oldVal: any) => {
if (val) {
// handleClick()
}
}
)
watch(
() => tableData.value,
(val: any, oldVal: any) => {}
)
onMounted(() => {})
</script>

View File

@@ -2,7 +2,8 @@
<div class="default-main">
<el-tabs v-model="activeName" type="border-card">
<el-tab-pane label="当前设备补招" name="0">
<current v-if="activeName == '0'" />
<!-- <current v-if="activeName == '0'" /> -->
<currentDevice v-if="activeName == '0'" ref="currentDeviceRef"/>
</el-tab-pane>
<el-tab-pane label="历史设备补招" name="1">
<history v-if="activeName == '1'" />
@@ -10,14 +11,33 @@
</el-tabs>
</div>
</template>
<script lang='ts' setup>
import {ref,onMounted} from 'vue';
import current from './supplementaryRecruitment/current.vue'
<script lang="ts" setup>
import { ref, onMounted,watch ,nextTick} from 'vue'
// import current from './supplementaryRecruitment/current.vue'
import currentDevice from './supplementaryRecruitment/currentDevice.vue'
import history from './supplementaryRecruitment/history.vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const activeName = ref('0')
const currentDeviceRef=ref()
watch(
()=>activeName.value,
(val,oldVal)=>{
if(val=='0'){
nextTick(()=>{
currentDeviceRef.value&&currentDeviceRef.value.getMakeUpDataList(route.query)
})
}
},
{
immediate:true,
deep:true
}
)
onMounted(() => {
console.log()
currentDeviceRef.value&&currentDeviceRef.value.getMakeUpDataList(route.query)
})
</script>
<style lang='scss' scoped>
</style>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,97 @@
<template>
<div class="default-main current_device" v-loading="loading">
<!-- <div class="file_path" v-if="dirCheckedList.value && dirCheckedList.value.length != 0">
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="(item, index) in dirCheckedList" :key="index">
{{ item.prjName }}
</el-breadcrumb-item>
</el-breadcrumb>
</div> -->
<div class="device_dir" v-for="(item, index) in dirList" :key="index">
<img v-if="item.type == 'dir'" src="@/assets/img/wenjianjia.svg" @click="handleIntoDir(item)" />
<img
class="device_dir_file"
v-if="item.type == 'file'"
src="@/assets/img/wenjian.svg"
@click="handleIntoDir(item)"
/>
<p>{{ item.prjName }}>{{ item.prjDataPath }}</p>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, defineProps, defineExpose } from 'vue'
import { getMakeUpData, getAskDirOrFile } from '@/api/cs-harmonic-boot/recruitment.ts'
// const props = defineProps(['lineId'])
const loading = ref(false)
const dirList = ref([])
const route: any = ref({})
const getMakeUpDataList = (row: any) => {
route.value = row
loading.value = true
getMakeUpData(row.id).then(res => {
console.log(res, '????????????')
dirList.value = res.data
loading.value = false
})
}
// 进入文件夹
const dirCheckedList: any = ref([])
const handleIntoDir = (row: any) => {
if (dirCheckedList.value.indexOf(row) == -1) {
dirCheckedList.value.push(row)
}
console.log(row, 'hhhhh', dirCheckedList.value)
const obj = {
fileType: row.type,
nDid: route.value.ndid,
path: row.prjDataPath,
prjName: row.prjName
}
getAskDirOrFile(obj).then(res => {
console.log(res, '查询3333333333333333')
dirList.value = res.data
})
}
onMounted(() => {
console.log()
// getMakeUpDataList()
})
defineExpose({ getMakeUpDataList })
</script>
<style lang="scss" scoped>
.current_device {
width: 100%;
height: calc(100vh - 200px);
display: flex;
flex-wrap: wrap;
align-items: flex-start;
// justify-content: space-between;
overflow-y: auto;
.device_dir {
width: 24.1%;
height: 120px;
border: 1px solid #eee;
margin: 0 0.3%;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
.device_dir_file {
width: 60px;
height: 60px;
}
img {
width: 50px;
height: 50px;
}
img:hover {
cursor: pointer;
}
p {
margin-top: 10px;
}
// margin:10px;
}
}
</style>

View File

@@ -75,10 +75,10 @@
<div class="tbody">
<div class="tbody_cell" v-for="(vv, key) in item" :key="key">
{{
tableData.find(item => {
tableData.find((item: any) => {
return item.anotherName == vv.showName && item.phase == vv.phase
})?.statisticalData
? tableData.find(item => {
? tableData.find((item: any) => {
return item.anotherName == vv.showName && item.phase == vv.phase
})?.statisticalData
: '/'
@@ -582,8 +582,8 @@ onMounted(() => {
height: auto;
display: flex;
justify-content: space-between;
border: 1px solid #eee;
padding: 10px;
//border: 1px solid #eee;
// padding: 10px;
.view_top_left,
.view_top_right {
width: 30%;
@@ -650,7 +650,7 @@ onMounted(() => {
.table_info {
width: 100%;
height: 120px;
border: 1px solid #eee;
// border: 1px solid #eee;
border-bottom: 2px solid #eee;
margin-bottom: 20px;
display: flex;

View File

@@ -0,0 +1,432 @@
<!-- 文件管理 -->
<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="right_nav">
<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> -->
<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
style="width: 200px; height: 32px"
placeholder="请输入文件或文件夹名称"
clearable
v-model="filterFileName"
></el-input>
<el-button type="primary" @click="handleSearch" :icon="Search">搜索</el-button>
<el-button @click="handleRefresh" :icon="Refresh">重置</el-button>
<el-upload
v-if="!progressVisibile"
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>
<div class="upload_progress" v-if="progressVisibile">
{{ fileName }}
<el-progress :percentage="30" :indeterminate="true">
<el-button text>上传中...</el-button>
</el-progress>
</div>
</div>
<div class="list" v-if="dirList.length != 0 && !loading">
<div class="list_item" v-for="(item, index) in dirList" :key="index">
<div class="item_download">
<el-button v-if="item?.type == 'file'" size="small" @click="handleDownLoad(item)" circle>
<el-icon><Download /></el-icon>
</el-button>
</div>
<!-- <div class="item_upload">
<el-upload
v-if="item?.type == 'dir'"
style="display: inline-block"
action=""
class="upload-demo"
:auto-upload="false"
:on-change="
(file:any, fileList:any) => {
handleUpload(file, fileList, item)
}
"
>
<el-button size="small" circle>
<el-icon><Upload /></el-icon>
</el-button>
</el-upload>
</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, ' ')
: item?.prjDataPath
}}
</p>
</div>
</div>
<el-empty v-if="dirList.length == 0 || !dirList[0].type" />
</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 {
getDeviceRootPath,
getFileServiceFileOrDir,
downLoadDeviceFile,
uploadDeviceFile,
reStartDevice
} from '@/api/cs-device-boot/fileService.ts'
import {
CirclePlus,
Delete,
EditPen,
ArrowLeft,
ArrowRight,
Download,
Upload,
View,
Check,
Plus,
Refresh,
Search
} from '@element-plus/icons-vue'
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 })
}
})
})
.catch(e => {
loading.value = false
})
}
}
//搜索文件或文件夹
const filterFileName = ref('')
const handleSearch = () => {
let filterList = []
dirList.value = currentDirList.value
dirList.value.map(item => {
if (filterFileName.value && item.prjDataPath.includes(filterFileName.value)) {
filterList.push(item)
}
})
if (filterList.length != 0) {
dirList.value = filterList
}
if (!filterFileName) {
dirList.value = currentDirList.value
}
}
//重置搜索
const handleRefresh = () => {
filterFileName.value = ''
dirList.value = currentDirList.value
}
//装置重启
const deviceRestartLoading = ref<boolean>(false)
const handleRestartDevice = () => {
deviceRestartLoading.value = true
reStartDevice({ nDid: nDid.value }).then((res: any) => {
if (res.code == 'A0000') {
deviceRestartLoading.value = false
ElMessage.success(res.message)
}
})
}
// 进入文件夹
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 })
}
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)
}
})
})
}
//处理导航栏路径
const outPutPath = (row: any, key: any) => {
let 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
}
//根据面包屑导航切换
const handleIntoByPath = async (val: any) => {
const obj = {
nDid: nDid.value,
name: val.path,
type: 'dir'
}
activePath.value = val.path
loading.value = true
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
})
}
//下载文件
const fileRef = ref()
const handleDownLoad = async (row: any) => {
;(await nDid.value) && fileRef.value && fileRef.value.open(row, nDid.value)
}
//上传文件
const progressVisibile = ref<boolean>(false)
const fileName = ref<string>('')
const handleUpload = (e: any, fileList: any, row: any) => {
fileName.value = e.name
const obj = {
id: nDid.value,
file: e.raw,
filePath: row || row.prjDataPath
}
progressVisibile.value = true
uploadDeviceFile(obj).then(res => {
if (res.code == 'A0000') {
ElMessage.success(res.message)
progressVisibile.value = false
}
})
}
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;
.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_upload {
position: absolute;
width: 100px;
height: 40px;
right: 20px;
top: 10px;
}
.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,
.item_upload {
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;
}
}
.list_item:nth-child(4n + 2),
.list_item:nth-child(4n + 3) {
margin: 10px 0.8%;
}
}
}
}
</style>

View File

@@ -0,0 +1,93 @@
<!-- 设备文件下载 -->
<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.split("/")[fileData?.prjDataPath.split("/").length-1]: '/' }}
</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'
import { ElMessage } from 'element-plus'
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 = async (row: any, id: any) => {
fileData.value = {}
dialogVisible.value = true
loading.value = true
const obj = {
nDid: id,
name: row.prjDataPath,
type: row.type
}
await getFileServiceFileOrDir(obj).then(res => {
if (res.code == 'A0000') {
if (res.data && res.data.length != 0) {
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
ElMessage.success(res.message)
handleClose()
}
})
.catch(e => {
if (e) {
downLoading.value = false
}
})
}
onMounted(() => {})
onUnmounted(() => {})
defineExpose({ open })
</script>
<style lang="scss" scoped>
.all_disabled {
// pointer-events: none;
}
</style>

View File

@@ -34,6 +34,15 @@
<el-descriptions-item label="接入时间">
{{ deviceData.time }}
</el-descriptions-item>
<el-descriptions-item label="应用程序版本号">
{{ deviceData.appVersion }}
</el-descriptions-item>
<el-descriptions-item label="应用程序发布日期">
{{ deviceData.appDate }}
</el-descriptions-item>
<el-descriptions-item label="应用程序校验码">
{{ deviceData.appCheck }}
</el-descriptions-item>
</el-descriptions>
<el-tabs v-model="dataSet" type="border-card" class="device-manage-box-card" @tab-click="handleClick">
<el-tab-pane

View File

@@ -191,7 +191,6 @@ queryByCode('Device_Type').then(res => {
}
})
})
tableStore.index()
})
const devModelOptionsFilter = computed(() => {
return devModelOptions.value.filter((item: any) => {
@@ -570,7 +569,7 @@ provide('tableStore', tableStore)
onMounted(() => {
setTimeout(() => {
// tableStore.index()
tableStore.index()
}, 100)
})

View File

@@ -17,7 +17,8 @@ export default defineConfig({
// target: 'http://192.168.1.122:10215', //gfh
// target: 'http://192.168.1.127:10215', //cdf
// target: 'http://192.168.1.125:10215',
target: 'https://pqmcn.com:8092/api', //治理
target: 'http://192.168.1.126:10215',
// target: 'https://pqmcn.com:8092/api', //治理
// target:'http://www.zhilitest.com:8089/api',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '') //路径重写,把'/api'替换为''