点位上传、下载

This commit is contained in:
白菜
2025-12-04 17:46:11 +08:00
parent 11d44de513
commit cd8871d45a
2 changed files with 201 additions and 161 deletions

View File

@ -1,12 +1,15 @@
<template> <template>
<el-dialog :visible.sync="show" class="ems-dialog" title="点位上传" width="400px" append-to-body :close-on-click-modal="false" :close-on-press-escape="false"> <el-dialog :visible.sync="show" class="ems-dialog" title="点位上传" width="400px" append-to-body
<!-- <file-upload :fileType='["xls", "xlsx"]' value="String" :limit="1" :drag="false" @input="updateFile"/>--> :close-on-click-modal="false" :close-on-press-escape="false">
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url" :data="upload.data" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag> <!-- <file-upload :fileType='["xls", "xlsx"]' value="String" :limit="1" :drag="false" @input="updateFile"/>-->
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url"
:data="upload.data" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div> <div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip"> <div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入xlsxlsx格式文件</span> <span>仅允许导入xlsxlsx格式文件</span>
<!-- <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>--> <!-- <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>-->
</div> </div>
</el-upload> </el-upload>
<div slot="footer"> <div slot="footer">
@ -20,33 +23,34 @@
</style> </style>
<script> <script>
import { getToken } from "@/utils/auth" import {getToken} from "@/utils/auth"
export default { export default {
data(){ data() {
return { return {
show:false, show: false,
// 用户导入参数 // 用户导入参数
upload: { upload: {
data:{}, data: {},
// 是否禁用上传 // 是否禁用上传
isUploading: false, isUploading: false,
// 设置上传的请求头部 // 设置上传的请求头部
headers: { Authorization: "Bearer " + getToken() }, headers: {Authorization: "Bearer " + getToken()},
// 上传的地址 // 上传的地址
url: process.env.VUE_APP_BASE_API + "/ems/pointMatch/importDataByDevice" url: process.env.VUE_APP_BASE_API + "/ems/pointMatch/importDataByDevice"
}, },
} }
}, },
methods:{ methods: {
showDialog({siteId,deviceId,deviceCategory}){ showDialog({siteId, code}) {
this.upload.data={siteId,deviceId,deviceCategory} this.upload.data = {siteId, deviceCategory: code}
this.show = true; this.show = true;
}, },
//关闭弹窗 重置数据 //关闭弹窗 重置数据
handleClosed(){ handleClosed() {
this.$refs.upload.clearFiles()//写在before-closed无效 this.$refs.upload.clearFiles()//写在before-closed无效
this.upload.data={} this.upload.data = {}
this.show=false this.show = false
}, },
// updateFile(data){ // updateFile(data){
// console.log('上传文件emit',data) // console.log('上传文件emit',data)
@ -60,10 +64,10 @@ export default {
}, },
// 文件上传成功处理 返回参数response, file, fileList // 文件上传成功处理 返回参数response, file, fileList
handleFileSuccess(response) { handleFileSuccess(response) {
console.log('上传文件结果',response) console.log('上传文件结果', response)
this.upload.isUploading = false this.upload.isUploading = false
if(response.code === 500 && !response.msg) response.msg = '上传失败' if (response.code === 500 && !response.msg) response.msg = '上传失败'
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + (response.msg || '上传成功' )+ "</div>", "导入结果", { dangerouslyUseHTMLString: true }) this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + (response.msg || '上传成功') + "</div>", "导入结果", {dangerouslyUseHTMLString: true})
this.$emit('update') this.$emit('update')
this.handleClosed() this.handleClosed()
}, },

View File

@ -1,56 +1,87 @@
<template> <template>
<div class="ems-dashboard-editor-container" style="background-color: #ffffff" v-loading="loading"> <div class="ems-dashboard-editor-container" style="background-color: #ffffff" v-loading="loading">
<el-form :inline="true" class="select-container"> <el-form :inline="true" class="select-container">
<el-form-item label="站点选择"> <el-form-item label="站点选择">
<el-select v-model="siteId" placeholder="请选择换电站名称" :loading="searchLoading" loading-text="正在加载数据" @change="onSearch" clearable> <el-select v-model="siteId" placeholder="请选择换电站名称" :loading="searchLoading" loading-text="正在加载数据"
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList" :key="index+'zdxeSelect'"></el-option> @change="onSearch" clearable>
</el-select> <el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList"
</el-form-item> :key="index+'zdxeSelect'"></el-option>
</el-select>
</el-form-item>
<el-form-item> <el-form-item>
<!-- <el-button type="primary" @click="onSearch" native-type="button">搜索</el-button>--> <!-- <el-button type="primary" @click="onSearch" native-type="button">搜索</el-button>-->
<!-- <el-button @click="onReset" native-type="button">重置</el-button>--> <!-- <el-button @click="onReset" native-type="button">重置</el-button>-->
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-button type="primary" @click="addDevice" native-type="button">新增设备</el-button> <el-button type="primary" @click="addDevice" native-type="button">新增设备</el-button>
<el-dropdown @command="downloadPointDetail">
<el-button
style="margin-left:10px;"
type="primary"
plain>
下载点位清单
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(item,index) in deviceCategoryList" :key="index+'deviceCategoryList'"
:command="item">
{{ item.name }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-dropdown @command="uploadPointDetail">
<el-button
style="margin-left:10px;"
type="success"
plain>
上传点位清单
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(item,index) in deviceCategoryList" :key="index+'deviceCategoryList'"
:command="item">
{{ item.name }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-table <el-table
class="common-table" class="common-table"
:data="tableData" :data="tableData"
stripe stripe
max-height="600px" max-height="600px"
style="width: 100%;margin-top: 25px"> style="width: 100%;margin-top: 25px">
<el-table-column <el-table-column
prop="siteId" prop="siteId"
label="站点ID"> label="站点ID">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="siteName" prop="siteName"
label="站点名称"> label="站点名称">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="deviceId" prop="deviceId"
label="设备ID" label="设备ID"
> >
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="deviceName" prop="deviceName"
label="设备名称"> label="设备名称">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="categoryName" prop="categoryName"
label="设备类别"> label="设备类别">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="runningStatus" prop="runningStatus"
label="在线状态"> label="在线状态">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{$store.state.ems.deviceStatusOptions[scope.row.runningStatus]}}</span> <span>{{ $store.state.ems.deviceStatusOptions[scope.row.runningStatus] }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
fixed="right" fixed="right"
label="操作" label="操作"
width="250"> width="250">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
@click="pointDetail(scope.row,'point')" @click="pointDetail(scope.row,'point')"
@ -66,56 +97,43 @@
</el-button> </el-button>
<br> <br>
<el-button <el-button
@click="downloadPointDetail(scope.row)" @click="editDevice(scope.row)"
style="margin-top:10px;" style="margin-top:10px;"
type="primary" type="warning"
plain
size="mini"> size="mini">
下载点位清单
</el-button>
<el-button
@click="uploadPointDetail(scope.row)"
style="margin-top:10px;"
type="success"
plain
size="mini">
上传点位清单
</el-button>
<br>
<el-button
@click="editDevice(scope.row)"
style="margin-top:10px;"
type="warning"
size="mini">
编辑 编辑
</el-button> </el-button>
<el-button <el-button
type="danger" type="danger"
style="margin-top:10px;" style="margin-top:10px;"
@click="deleteDevice(scope.row)" @click="deleteDevice(scope.row)"
size="mini"> size="mini">
删除 删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-pagination <el-pagination
v-show="tableData.length>0" v-show="tableData.length>0"
background background
@size-change="handleSizeChange" @size-change="handleSizeChange"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
:current-page="pageNum" :current-page="pageNum"
:page-size="pageSize" :page-size="pageSize"
:page-sizes="[10, 20, 30, 40]" :page-sizes="[10, 20, 30, 40]"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
:total="totalSize" :total="totalSize"
style="margin-top:15px;text-align: center" style="margin-top:15px;text-align: center"
> >
</el-pagination> </el-pagination>
<el-dialog :visible.sync="dialogTableVisible" class="ems-dialog" title=" 详细信息" :close-on-click-modal="false" :before-close="handleClosed"> <el-dialog :visible.sync="dialogTableVisible" class="ems-dialog" title=" 详细信息" :close-on-click-modal="false"
<div class="descriptions-main" style="padding: 0" > :before-close="handleClosed">
<div class="descriptions-main" style="padding: 0">
<el-descriptions direction="vertical" :column="2" :colon="false" border> <el-descriptions direction="vertical" :column="2" :colon="false" border>
<el-descriptions-item v-for="(item,index) in detailData" :key="index+'descriptions'" labelClassName="descriptions-label" contentClassName="descriptions-direction" :span="1" :label="item.label">{{item.value}}</el-descriptions-item> <el-descriptions-item v-for="(item,index) in detailData" :key="index+'descriptions'"
labelClassName="descriptions-label" contentClassName="descriptions-direction" :span="1"
:label="item.label">{{ item.value }}
</el-descriptions-item>
</el-descriptions> </el-descriptions>
</div> </div>
</el-dialog> </el-dialog>
@ -126,89 +144,98 @@
</template> </template>
<script> <script>
import {getDeviceInfoList,getDeviceDetailInfo,deleteService} from'@/api/ems/site' import {deleteService, getDeviceDetailInfo, getDeviceInfoList} from '@/api/ems/site'
import {getAllSites} from '@/api/ems/zddt' import {getAllSites} from '@/api/ems/zddt'
import {formatNumber} from "@/filters/ems"; import {formatNumber} from "@/filters/ems";
import {getAllDeviceCategory} from '@/api/ems/search'
import PointTable from './PointTable.vue' import PointTable from './PointTable.vue'
import AddDevice from "./AddDevice.vue"; import AddDevice from "./AddDevice.vue";
import PointUpload from "./PointUpload.vue"; import PointUpload from "./PointUpload.vue";
export default { export default {
name: "Sblb", name: "Sblb",
components:{AddDevice,PointTable,PointUpload}, components: {AddDevice, PointTable, PointUpload},
data() { data() {
return { return {
loading:false, loading: false,
searchLoading:false, searchLoading: false,
mode:'',//新增、编辑设备 mode: '',//新增、编辑设备
editDeviceId:'',//编辑设备id editDeviceId: '',//编辑设备id
siteId:'', siteId: '',
siteList:[], siteList: [],
tableData:[], tableData: [],
pageSize:10,//分页栏当前每个数据总数 deviceCategoryList: [],//设备类别
pageNum:1,//分页栏当前 pageSize: 10,//分页栏当前每个数据总
totalSize:0,//table表格数据总 pageNum: 1,//分页栏当前页
dialogTableVisible:false, totalSize: 0,//table表格数据总数
detailData:[ dialogTableVisible: false,
{label:'设备ID',value:'',attr:'deviceId'}, detailData: [
{label:'设备名称',value:'',attr:'deviceName'}, {label: '设备ID', value: '', attr: 'deviceId'},
{label:'设备类型',value:'',attr:'deviceType'}, {label: '设备名称', value: '', attr: 'deviceName'},
{label:'通信状态',value:'',attr:'communicationStatus'}, {label: '设备类型', value: '', attr: 'deviceType'},
{label:'TCP设备的IP地址',value:'',attr:'ipAddress'}, {label: '通信状态', value: '', attr: 'communicationStatus'},
{label:'TCP端口号',value:'',attr:'ipPort'}, {label: 'TCP设备的IP地址', value: '', attr: 'ipAddress'},
{label:'串口路径',value:'',attr:'serialPort'}, {label: 'TCP端口号', value: '', attr: 'ipPort'},
{label:'波特率',value:'',attr:'baudRate'}, {label: '串口路径', value: '', attr: 'serialPort'},
{label:'数据位',value:'',attr:'dataBits'}, {label: '波特率', value: '', attr: 'baudRate'},
{label:'停止位',value:'',attr:'stopBits'}, {label: '数据位', value: '', attr: 'dataBits'},
{label:'校验位',value:'',attr:'parity'}, {label: '停止位', value: '', attr: 'stopBits'},
{label:'设备描述',value:'',attr:'description'}, {label: '校验位', value: '', attr: 'parity'},
{label:'设备类别',value:'',attr:'deviceCategory'}, {label: '设备描述', value: '', attr: 'description'},
{label:'上级设备ID',value:'',attr:'parentId'}, {label: '设备类别', value: '', attr: 'deviceCategory'},
{label:'设备唯一标识符',value:'',attr:'deviceId'}, {label: '上级设备ID', value: '', attr: 'parentId'},
{label: '设备唯一标识符', value: '', attr: 'deviceId'},
], ],
detailformatAttr:{ detailformatAttr: {
'deviceType':'deviceTypeOptions', 'deviceType': 'deviceTypeOptions',
'communicationStatus':'communicationStatusOptions', 'communicationStatus': 'communicationStatusOptions',
} }
} }
}, },
methods:{ methods: {
// 获取设备类别
getDeviceCategoryList() {
getAllDeviceCategory().then(response => {
this.deviceCategoryList = response?.data || []
})
},
// 查看设备电位表格 // 查看设备电位表格
pointDetail(row,dataType){ pointDetail(row, dataType) {
this.$refs.pointTable.showTable(row,dataType) this.$refs.pointTable.showTable(row, dataType)
}, },
// 下载点位清单 // 下载点位清单
downloadPointDetail({siteId,deviceCategory,deviceName}){ downloadPointDetail(command) {
this.download('ems/pointMatch/export', { this.download('ems/pointMatch/export', {
siteId, siteId: this.siteId,
deviceCategory deviceCategory: command.code
}, `点位清单_${deviceName}_${new Date().getTime()}.xlsx`) }, `点位清单_${command.name}_${new Date().getTime()}.xlsx`)
}, },
// 上传点位清单 // 上传点位清单
uploadPointDetail(row){ uploadPointDetail(command) {
this.$refs.pointUpload.showDialog(row) this.$refs.pointUpload.showDialog({...command, siteId: this.siteId})
}, },
clearEditDeviceData(){ clearEditDeviceData() {
this.mode = ''; this.mode = '';
this.editDeviceId='' this.editDeviceId = ''
}, },
// 新增设备 展示弹窗 // 新增设备 展示弹窗
addDevice(){ addDevice() {
this.mode = 'add'; this.mode = 'add';
this.$refs.addDevice.dialogTableVisible = true this.$refs.addDevice.dialogTableVisible = true
}, },
// 编辑设备 // 编辑设备
editDevice(row){ editDevice(row) {
this.mode = 'edit'; this.mode = 'edit';
this.editDeviceId = row.id this.editDeviceId = row.id
this.$refs.addDevice.dialogTableVisible = true; this.$refs.addDevice.dialogTableVisible = true;
}, },
//删除设备 //删除设备
deleteDevice(row){ deleteDevice(row) {
this.$confirm(`确认要设备${row.deviceName}吗?`, { this.$confirm(`确认要设备${row.deviceName}吗?`, {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
showClose:false, showClose: false,
closeOnClickModal:false, closeOnClickModal: false,
type: 'warning', type: 'warning',
beforeClose: (action, instance, done) => { beforeClose: (action, instance, done) => {
if (action === 'confirm') { if (action === 'confirm') {
@ -234,73 +261,82 @@ export default {
//取消关机 //取消关机
}); });
}, },
handleClosed(done){ handleClosed(done) {
this.detailData.forEach((item)=>{item.value = ''}) this.detailData.forEach((item) => {
item.value = ''
})
done() done()
}, },
toDetail(id){ toDetail(id) {
this.loading = true this.loading = true
getDeviceDetailInfo(id).then(response => { getDeviceDetailInfo(id).then(response => {
const data = response?.data || {}; const data = response?.data || {};
this.detailData.forEach(item=>{ this.detailData.forEach(item => {
if(this.detailformatAttr[item.attr]){ if (this.detailformatAttr[item.attr]) {
item.value=formatNumber(this.$store.state.ems[this.detailformatAttr[item.attr]][data[item.attr]]); item.value = formatNumber(this.$store.state.ems[this.detailformatAttr[item.attr]][data[item.attr]]);
}else{ } else {
item.value=formatNumber(data[item.attr]); item.value = formatNumber(data[item.attr]);
} }
}) })
this.dialogTableVisible = true this.dialogTableVisible = true
}).finally(() => {this.loading = false}) }).finally(() => {
this.loading = false
})
}, },
// 分页 // 分页
handleSizeChange(val) { handleSizeChange(val) {
this.pageSize = val; this.pageSize = val;
this.$nextTick(()=>{ this.$nextTick(() => {
this.getData() this.getData()
}) })
}, },
handleCurrentChange(val) { handleCurrentChange(val) {
this.pageNum = val this.pageNum = val
this.$nextTick(()=>{ this.$nextTick(() => {
this.getData() this.getData()
}) })
}, },
// 搜索 // 搜索
onSearch(){ onSearch() {
this.pageNum =1//每次搜索从1开始搜索 this.pageNum = 1//每次搜索从1开始搜索
this.getData() this.getData()
}, },
// 重置 // 重置
onReset(){ onReset() {
this.siteId='' this.siteId = ''
this.pageNum =1//每次搜索从1开始搜索 this.pageNum = 1//每次搜索从1开始搜索
this.getData() this.getData()
}, },
// 获取数据 // 获取数据
getData(){ getData() {
this.loading=true this.loading = true
const {siteId,pageNum,pageSize} =this const {siteId, pageNum, pageSize} = this
getDeviceInfoList({siteId,pageNum,pageSize}).then(response => { getDeviceInfoList({siteId, pageNum, pageSize}).then(response => {
this.tableData=response?.rows || []; this.tableData = response?.rows || [];
this.totalSize = response?.total || 0 this.totalSize = response?.total || 0
}).finally(() => {this.loading=false}) }).finally(() => {
this.loading = false
})
}, },
//获取站点列表 //获取站点列表
getZdList(){ getZdList() {
this.searchLoading=true this.searchLoading = true
return getAllSites().then(response => { return getAllSites().then(response => {
this.siteList = response?.data || [] this.siteList = response?.data || []
if(this.siteList.length>0) this.siteId = this.siteList[0].siteId if (this.siteList.length > 0) this.siteId = this.siteList[0].siteId
}).finally(() => {this.searchLoading=false}) }).finally(() => {
this.searchLoading = false
})
} }
}, },
mounted() { mounted() {
this.loading=true this.loading = true
this.siteId='' this.siteId = ''
this.pageNum =1//每次搜索从1开始搜索 this.pageNum = 1//每次搜索从1开始搜索
this.getZdList().then(()=>{ this.getDeviceCategoryList()
this.getZdList().then(() => {
this.getData() this.getData()
}) })
} }