fix:导入导出功能&细节调整
1.asset、endpoint导入导出功能 2.header- asset点击变为单选 3.asset列表ping列悬浮显示调整
This commit is contained in:
@@ -1094,6 +1094,8 @@ li{
|
||||
width:10px;
|
||||
height:10px;
|
||||
border-radius:50%;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.red {
|
||||
background-color:#ff6347;
|
||||
|
||||
325
nezha-fronted/src/components/common/exportXLSX.vue
Normal file
325
nezha-fronted/src/components/common/exportXLSX.vue
Normal file
@@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<el-dropdown split-button type="primary" size="mini">
|
||||
<slot name="optionZone" class="option-button"></slot>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="showImportBox(1)">{{$t('overall.importExcelLower')}}</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="showImportBox(2)">{{$t('overall.exportExcelLower')}}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div>
|
||||
<el-dialog :visible.sync="importBox.show" :title="importBox.title" :modal-append-to-body='false' :show-close="true" :width="importBox.width" @close="closeDialog">
|
||||
<div v-if="importBox.type==1">
|
||||
<div class="upload-body">
|
||||
<el-upload class="upload-demo" ref="uploadExcel" action="" :file-list="importFileList" :on-change="importChange" :auto-upload="false" accept=".xlsx,.xls">
|
||||
<div slot="tip" class="el-upload__tip" >{{$t('overall.importTip')}}</div>
|
||||
<button type="button" class="nz-btn nz-btn-size-normal nz-btn-style-normal">
|
||||
<span class="top-tool-btn-txt" >{{$t('overall.upload')}}</span>
|
||||
</button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div slot="footer" class="footer">
|
||||
<div class="right-box-bottom-btns">
|
||||
<button @click="downloadTemplate" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-min-width-100">
|
||||
<span>{{$t('overall.template')}}</span>
|
||||
</button>
|
||||
<button @click="closeDialog" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-min-width-100" style="margin-left: 0px">
|
||||
<span>{{$t('overall.cancel')}}</span>
|
||||
</button>
|
||||
<button @click="importExcel" class="nz-btn nz-btn-size-normal nz-btn-style-normal nz-btn-min-width-100">
|
||||
<span>{{$t('overall.importExcel')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="importBox.type == 2">
|
||||
<div class="upload-body">
|
||||
<button @click="exportCur" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-min-width-100">
|
||||
<span>{{$t('overall.exportCur')}}</span>
|
||||
</button>
|
||||
<button @click="exportAll" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-min-width-100">
|
||||
<span>{{$t('overall.exportAll')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div slot="footer" class="footer">
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="importBox.type==3">
|
||||
<div class="upload-body result-body">
|
||||
<div>
|
||||
<span class="result-title">{{$t('overall.result.total')}}:</span>
|
||||
<span>{{importResult&&importResult.totalNum?importResult.totalNum:0}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="result-title">{{$t('overall.result.failed')}}:</span>
|
||||
<span>{{importResult&&importResult.failNum?importResult.failNum:0}}</span>
|
||||
<span class="result-title">{{$t('overall.result.success')}}:</span>
|
||||
<span>{{importResult&&importResult.successNum?importResult.successNum:0}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="result-title">{{$t('overall.result.failedDetail')}}:</div>
|
||||
<div class="result-detail" v-if="importResult&&importResult.failDetail">
|
||||
<ul>
|
||||
<li v-for="(item,index) in importResult.failDetail"><span>{{item.lineNo}}</span>:<span>{{item.errorMsg}}</span> </li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="footer">
|
||||
<div class="right-box-bottom-btns">
|
||||
<button @click="rollbackImport" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-min-width-100">
|
||||
<span>{{$t('overall.rollbackImport')}}</span>
|
||||
</button>
|
||||
<button @click="closeDialog" class="nz-btn nz-btn-size-normal nz-btn-style-light nz-btn-min-width-100">
|
||||
<span>{{$t('overall.cancel')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
name: "exportXLSX",
|
||||
props:{
|
||||
exportUrl:{type:String,required:true},
|
||||
params:{type:Object},
|
||||
exportFileName:{type:String},
|
||||
|
||||
},
|
||||
data:function(){
|
||||
return {
|
||||
importBox:{show:false,title:this.$t('overall.importExcel'),type:1},
|
||||
importFile:null,
|
||||
importFileList:[],
|
||||
importResult:null,
|
||||
}
|
||||
},
|
||||
created(){
|
||||
},
|
||||
methods: {
|
||||
importChange:function(file,fileList){
|
||||
if (fileList.length > 0) {
|
||||
this.importFileList = [fileList[fileList.length - 1]]
|
||||
}
|
||||
this.importFile = this.importFileList[0];
|
||||
this.validateFile();
|
||||
},
|
||||
validateFile:function(){
|
||||
|
||||
},
|
||||
rollbackImport:function(){
|
||||
this.$delete('/asset/cancelImport?seq='+this.importResult.seq).then(response=>{
|
||||
if(response.code == 200 ){
|
||||
this.$message({duration: 2000, type: 'success', message: this.$t("tip.saveSuccess")});
|
||||
}else{
|
||||
this.$message.error(response.msg);
|
||||
}
|
||||
this.closeDialog();
|
||||
})
|
||||
},
|
||||
importExcel:function(){
|
||||
if(this.importFile && this.importFile.raw){
|
||||
let form = new FormData();
|
||||
form.append('assetsExcelFile',this.importFile.raw);
|
||||
this.$post('/asset/import',form,{'Content-Type': 'multipart/form-data'}).then(response=>{
|
||||
if(response.code==200 && response.msg=='success'){
|
||||
this.importResult=response.data;
|
||||
this.$emit('afterImport')
|
||||
this.importBox.type=3;
|
||||
this.importBox.width='600px';
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
closeDialog:function(){
|
||||
this.importBox.show=false;
|
||||
this.importResult=null;
|
||||
this.importFileList=[];
|
||||
this.importFile=null;
|
||||
},
|
||||
downloadTemplate:function(){
|
||||
let language=localStorage.getItem('nz-language-' + localStorage.getItem('nz-username')) || 'en'; //初始未选择默认 en 英文
|
||||
let fileName=this.exportFileName+'-'+'template'+'.xlsx';
|
||||
let xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.responseType = "blob";
|
||||
xmlHttp.onload=function(){
|
||||
if(this.status === 200){
|
||||
let blob=this.response;
|
||||
let reader = new FileReader();
|
||||
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a标签href
|
||||
reader.onload = function(e) {
|
||||
// 转换完成后创建a标签下载
|
||||
let a = document.createElement('a');
|
||||
a.download = fileName;
|
||||
a.href = e.target.result;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlHttp.open("GET",'/static/template/'+language+'/'+fileName,true);
|
||||
xmlHttp.send();
|
||||
},
|
||||
formatJson(filterVal, jsonData) {
|
||||
return jsonData.map(v => filterVal.map(j => v[j]))
|
||||
},
|
||||
exportCur:function(){
|
||||
this.exportExcel();
|
||||
this.closeDialog();
|
||||
},
|
||||
exportAll:function(){
|
||||
let params=JSON.parse(JSON.stringify(this.params));
|
||||
params.pageSize=-1;
|
||||
this.exportExcel(params);
|
||||
this.closeDialog();
|
||||
},
|
||||
exportExcel:function(params){
|
||||
let temp=this;
|
||||
if(!params){
|
||||
params=temp.params;
|
||||
}
|
||||
axios.get(this.exportUrl,{responseType:'blob',params:params}).then(res=>{
|
||||
let fileName=temp.exportFileName+'-'+temp.getTimeString()+'.xlsx';
|
||||
if(window.navigator.msSaveOrOpenBlob){
|
||||
// 兼容ie11
|
||||
let blobObject = new Blob([res.data]);
|
||||
window.navigator.msSaveOrOpenBlob(blobObject, fileName);
|
||||
}else{
|
||||
let url = URL.createObjectURL(new Blob([res.data]));
|
||||
let a = document.createElement('a');
|
||||
document.body.appendChild(a); //此处增加了将创建的添加到body当中
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
a.target = '_blank';
|
||||
a.click();
|
||||
a.remove(); //将a标签移除
|
||||
}
|
||||
})
|
||||
},
|
||||
showImportBox:function(type){
|
||||
this.importBox.show=true;
|
||||
this.importBox.type=type;
|
||||
if(type == 1){//import
|
||||
this.importBox.title=this.$t('overall.importExcel');
|
||||
this.importBox.width='600px';
|
||||
}else if(type == 2){//export
|
||||
this.importBox.title=this.$t('overall.exportExcel');
|
||||
this.importBox.width='300px';
|
||||
}
|
||||
},
|
||||
getTimeString:function(){
|
||||
let split='-';
|
||||
let date=new Date();
|
||||
let year=date.getFullYear();
|
||||
let month=this.formatNum(date.getMonth()+1);
|
||||
let day=this.formatNum(date.getDay());
|
||||
let hours=this.formatNum(date.getHours());
|
||||
let minutes=this.formatNum(date.getMinutes());
|
||||
let seconds=this.formatNum(date.getSeconds());
|
||||
return year + split + month + split + day + ' ' + hours + split + minutes + split + seconds;
|
||||
},
|
||||
formatNum:function(num){
|
||||
return num>9?num:'0'+num;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/*去除上传文件动画start*/
|
||||
/*.upload-demo {*/
|
||||
/* display: flex;*/
|
||||
/*}*/
|
||||
/deep/ .el-list-enter-active,
|
||||
/deep/ .el-list-leave-active {
|
||||
transition: none;
|
||||
}
|
||||
.nz-tab {
|
||||
margin-bottom: 22px;
|
||||
margin-left: 13px;
|
||||
}
|
||||
/deep/ .el-list-enter,
|
||||
/deep/ .el-list-leave-active {
|
||||
opacity: 0;
|
||||
}
|
||||
/deep/ .el-upload-list {
|
||||
height: 40px;
|
||||
}
|
||||
/*去除上传文件动画end*/
|
||||
</style>
|
||||
<style>
|
||||
.el-dialog__body{
|
||||
padding: 10px 20px 20px 20px;
|
||||
}
|
||||
.el-button:focus, .el-button:hover {
|
||||
color: unset;
|
||||
border-color: unset;
|
||||
background-color:unset;
|
||||
}
|
||||
.el-button--primary{
|
||||
top:2px;
|
||||
padding: 0 8px;
|
||||
background-image: linear-gradient(180deg, #fff 0%, #E0E0E0 100%);
|
||||
border: 0px;
|
||||
color: #666;
|
||||
-webkit-box-shadow: 0 0 1px 1px rgba(162,162,162,0.5);
|
||||
box-shadow: 0 0 1px 1px rgba(162,162,162,0.5);
|
||||
letter-spacing: 0;
|
||||
background-color: unset;
|
||||
}
|
||||
.el-button--primary:hover{
|
||||
background-image: linear-gradient(180deg, #F0F0F0 0%, #D8D8D8 99%) !important;
|
||||
}
|
||||
.el-button--mini{
|
||||
font-size: 12px;
|
||||
height: 24px;
|
||||
}
|
||||
.el-dropdown .el-button-group{
|
||||
display: block;
|
||||
position: relative;
|
||||
top:-2px;
|
||||
}
|
||||
.el-dropdown .el-dropdown__caret-button {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
border-left: none;
|
||||
top:0px;
|
||||
left:2px;
|
||||
}
|
||||
.footer:before{
|
||||
content: '';
|
||||
clear:both;
|
||||
display: block;
|
||||
height: 40px;
|
||||
}
|
||||
.upload-body{
|
||||
text-align: center;
|
||||
}
|
||||
.result-detail li{
|
||||
line-height: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.result-detail{
|
||||
height: 100px;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.result-body{
|
||||
text-align: left;
|
||||
line-height: 20px;
|
||||
font-size: 12px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.result-title{
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
@@ -280,11 +280,13 @@
|
||||
},
|
||||
jumpToAsset(id) {
|
||||
let index = this.indOf(this.activeItemIndexes, id);
|
||||
if (index > -1) {
|
||||
this.activeItemIndexes.splice(index, 1);
|
||||
} else {
|
||||
this.activeItemIndexes=[];//2020-02-25 修改为单选
|
||||
this.activeItemIndexes.push(id);
|
||||
}
|
||||
// if (index > -1) {
|
||||
// this.activeItemIndexes.splice(index, 1);
|
||||
// } else {
|
||||
// this.activeItemIndexes.push(id);
|
||||
// }
|
||||
this.$store.state.assetData = {selectedData: this.activeItemIndexes, step: this.$store.state.assetData.step+1, type: 1};
|
||||
this.jumpTo('asset');
|
||||
},
|
||||
|
||||
@@ -42,7 +42,24 @@ const en = {
|
||||
createAlertRule:'create alert rule',
|
||||
createAccount:'create account',
|
||||
createPrometheusServer:'create prometheus server',
|
||||
createDatacenter:'create datacenter'
|
||||
createDatacenter:'create datacenter',
|
||||
exportExcel:'Export',
|
||||
importExcel:'Import',
|
||||
importExcelLower:'import',
|
||||
exportExcelLower:'export',
|
||||
rollbackImport:'rollback',
|
||||
exportCur:'current page',
|
||||
exportAll:'all',
|
||||
importFile:'please upload file',
|
||||
importTip:'only allowed xlsx/xls file',
|
||||
upload:'upload',
|
||||
template:'Template',
|
||||
result:{
|
||||
total:'Total',
|
||||
failed:'Failed',
|
||||
success:'Success',
|
||||
failedDetail:'Failed Detail'
|
||||
}
|
||||
},
|
||||
dashboard:{
|
||||
title:'Dashboard',
|
||||
|
||||
@@ -33,11 +33,19 @@
|
||||
<div class="top-tools">
|
||||
<div></div>
|
||||
<div>
|
||||
<button @click.stop="tagShow('showAdd')" :title="$t('overall.createAsset')" class="nz-btn nz-btn-size-normal nz-btn-style-light float-right " id="asset-add">
|
||||
<i class="nz-icon-create-square nz-icon"></i>
|
||||
<!-- ADD按钮 -->
|
||||
</button>
|
||||
<div class="top-tool-search float-right"><search-input :searchMsg="searchMsg" @search="search"></search-input></div>
|
||||
<export-excel
|
||||
export-file-name="asset"
|
||||
export-url="/asset/export"
|
||||
:params="searchLabel"
|
||||
:template-key="templateKey"
|
||||
@afterImport="getAssetData"
|
||||
class="float-right">
|
||||
<template slot="optionZone">
|
||||
<i class="nz-icon nz-icon-create-square" @click.stop="tagShow('showAdd')" :title="$t('overall.createAsset')" ></i>
|
||||
</template>
|
||||
</export-excel>
|
||||
|
||||
<div class="top-tool-search float-left"><search-input :searchMsg="searchMsg" @search="search"></search-input></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -75,14 +83,15 @@
|
||||
<div v-if="item.prop=='state'">
|
||||
<span>{{scope.row.state==1 ? $t('asset.createAssetTab.inStock') : $t('asset.createAssetTab.notInStock')}}</span>
|
||||
</div>
|
||||
<!-- :content="scope.row.pingRtt ? (scope.row.pingLastUpdate&&scope.row.pingLastUpdate!=''?(new Date(scope.row.pingLastUpdate).getHours()+':'+new Date(scope.row.pingLastUpdate).getMinutes()):'--')+'['+ scope.row.pingRtt+'ms'+']':(scope.row.pingLastUpdate&&scope.row.pingLastUpdate!=''?(new Date(scope.row.pingLastUpdate).getHours()+':'+new Date(scope.row.pingLastUpdate).getMinutes()):'--')+'[unreachable]'"-->
|
||||
<div v-if="item.prop == 'pingStatus'">
|
||||
<el-popover
|
||||
placement="right"
|
||||
width="50"
|
||||
trigger="hover"
|
||||
:content="scope.row.pingRtt ? (scope.row.pingLastUpdate&&scope.row.pingLastUpdate!=''?(new Date(scope.row.pingLastUpdate).getHours()+':'+new Date(scope.row.pingLastUpdate).getMinutes()):'--')+'['+ scope.row.pingRtt+'ms'+']':(scope.row.pingLastUpdate&&scope.row.pingLastUpdate!=''?(new Date(scope.row.pingLastUpdate).getHours()+':'+new Date(scope.row.pingLastUpdate).getMinutes()):'--')+'[unreachable]'">
|
||||
:content="formatPingTime(scope.row.pingLastUpdate)">
|
||||
<div slot="reference" style="width: 20px">
|
||||
<div :class="{'active-icon green':scope.row.pingState == 1,'active-icon red':scope.row.pingState == 0}"></div>
|
||||
<div :class="{'active-icon green':scope.row.pingState == 1,'active-icon red':scope.row.pingState == 0}"></div><span>{{scope.row.pingRtt?scope.row.pingRtt+'ms':''}}</span>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
@@ -186,8 +195,10 @@
|
||||
|
||||
<script>
|
||||
import bus from "../../../libs/bus";
|
||||
import exportXLSX from "../../common/exportXLSX";
|
||||
export default {
|
||||
name: "asset",
|
||||
components:{'export-excel':exportXLSX},
|
||||
data() {
|
||||
return {
|
||||
searchMsg: { //给搜索框子组件传递的信息
|
||||
@@ -360,6 +371,25 @@
|
||||
checkAllFlag: false,
|
||||
checkAllHandler: false,
|
||||
assetClick: false,
|
||||
templateHeader:['*Sn','*Type','*Vendor','*Model','*Idc','Cabinet','*Host','State','PurchaseDate','AuthType','User','Pwd','PrivateKey','Port','Exporter'],
|
||||
templateDate:[{
|
||||
sn:'0001',
|
||||
type:'server/net',
|
||||
vendor:'huawei',
|
||||
model:'rongyao',
|
||||
idc:'beijing',
|
||||
cabinet:'cab-01',
|
||||
host:'192.168.1.1',
|
||||
state:'1:在库 2:出库 默认:在库',
|
||||
purchaseData:'2020-02-11 19:30:33',
|
||||
authType:'认证类型,1:密码,2:私钥证书',
|
||||
user:'root',
|
||||
pwd:'111111',
|
||||
privateKey:'xxxxxxxx',
|
||||
port:'22',
|
||||
exporter:'是否安装node_exporter,1:安装,0:不安装'
|
||||
}],
|
||||
templateKey:['sn','type','vendor','model','idc','cabinet','host','state','purchaseData','authType','user','pwd','privateKey','port','exporter']
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -699,6 +729,23 @@
|
||||
}
|
||||
}
|
||||
this.getAssetData();
|
||||
},
|
||||
formatPingTime:function(str){
|
||||
if(!str || str == ''){
|
||||
return 'Never';
|
||||
}
|
||||
let ds='-';
|
||||
let ts=':';
|
||||
let time=new Date(str);
|
||||
let year=time.getFullYear();
|
||||
let month=time.getMonth()+1 > 9 ? time.getMonth()+1 : ('0'+(time.getMonth()+1));
|
||||
let day=time.getDay() > 9 ? time.getDay():('0'+time.getDay());
|
||||
let hours=time.getHours() > 9? time.getHours():('0'+time.getHours());
|
||||
let minutes=time.getMinutes() > 9 ?time.getMinutes():('0'+time.getMinutes());
|
||||
let seconds=time.getSeconds() > 9 ? time.getSeconds():('0'+time.getSeconds());
|
||||
|
||||
return year+ds+month+ds+day+' '+hours+ts+minutes+ts+seconds;
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
@@ -99,9 +99,19 @@
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<div>
|
||||
<button @click="toCreateEndpoint" :title="$t('overall.createProject')" class="nz-btn nz-btn-size-normal nz-btn-style-light float-right " id="project-add-ep">
|
||||
<i class="nz-icon-create-square nz-icon"></i>
|
||||
</button>
|
||||
<export-excel
|
||||
export-file-name="endpoint"
|
||||
export-url="/endpoint/export"
|
||||
:params="endpointSearchLabel"
|
||||
@afterImport="getEndpointTableData"
|
||||
class="float-right">
|
||||
<template slot="optionZone">
|
||||
<i class="nz-icon nz-icon-create-square" @click.stop="toCreateEndpoint" :title="$t('overall.createProject')" ></i>
|
||||
</template>
|
||||
</export-excel>
|
||||
<!-- <button @click="toCreateEndpoint" :title="$t('overall.createProject')" class="nz-btn nz-btn-size-normal nz-btn-style-light float-right " id="project-add-ep">-->
|
||||
<!-- <i class="nz-icon-create-square nz-icon"></i>-->
|
||||
<!-- </button>-->
|
||||
<div class="top-tool-search float-right"><search-input :searchMsg="endpointSearchMsg" @search="endpointSearch" ref="projectSearch"></search-input></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -300,11 +310,13 @@
|
||||
import bus from "../../../libs/bus";
|
||||
import metricSearch from "./metricSearch";
|
||||
import axios from 'axios';
|
||||
import exportXLSX from "../../common/exportXLSX";
|
||||
export default {
|
||||
name: "project2",
|
||||
components: {
|
||||
'chart-box': chartBox,
|
||||
'metric-search':metricSearch
|
||||
'metric-search':metricSearch,
|
||||
'export-excel':exportXLSX
|
||||
},
|
||||
data() {
|
||||
let temp=this;
|
||||
|
||||
Reference in New Issue
Block a user