Authored by xwx

license功能迁移

... ... @@ -96,7 +96,10 @@ layui.define(['layer', 'laytpl', 'form'], function (exports) {
$(newContent).css('cursor','pointer').on(options.type,options.action);
}
},1);
$(options.dom).append(newContainer);
//lsq 快照完成后提示框显示在最上面,需要把提示框添加到body下 20022-08-30
// $(options.dom).append(newContainer);
$('body').append(newContainer);
$('.ez_tips ').css('z-index','99999999');
} else if(options.toastType=='faultinfo'||options.toastType=='faultprogress'||options.toastType=='faultover'){
var container = "<div class='fault_ez_tips "+options.toastType+"' style="+firstDirection+":"+options.margin+"px;transform:translateX("+minus+"110%); ></div>"
... ...
<title>license</title>
<iframe class="layadmin-iframe" src="/vue3/index.html#/vue3/license" style="height: 99.5%!important;"/>
... ...
<div>
<!-- 表格-->
<el-table :border="showBorder" :data="dataList" :default-expand-all="defaultExpand" :expand-row-keys="expands"
:height="height" :row-key="getRowKeys" :size="size" @select="handleSelect"
@select-all="handleSelectAll"
@selection-change="handleSelectionChange" header-row-class-name="tbl-header-class" ref="multipleTable"
stripe
style="width: 100%;margin: 0px 0px; font-size:13.5px;" v-loading="loading"
>
<el-table-column type="expand" v-if="showExpand">
<template #default="scope">
<slot :scope="scope" name="expand">
</slot>
</template>
</el-table-column>
<el-table-column align="center" type="selection" v-if="showSelection && columns.length > 0" width="55"/>
<el-table-column :label="indexLabel" align="center" type="index" v-if="showIndex && columns.length > 0"
width="50"/>
<el-table-column :align="item.align == undefined ? 'center' : item.align " :label="item.label" :prop="item.prop"
:sortable="item.sortable == undefined ? false : item.sortable"
:width="getWidth(item.width)"
v-for="item in columns">
<template v-if="!item.columns || item.columns.lendth==0" #default="scope">
<slot :column="item" :prop="item.prop" :row="scope.row">
<div v-if="typeof(item.click) == 'function' && typeof(item.render) == 'function'">
<span @click="item.click(scope.row)" style="cursor: pointer"
v-html="item.render(scope.row)"></span>
</div>
<div v-else-if="typeof(item.click) == 'function'">
<span @click="item.click(scope.row)" style="cursor: pointer"> {{scope.row[item.prop]}}</span>
</div>
<div v-else-if="typeof(item.render) == 'function'">
<span v-html="item.render(scope.row)">{{scope.row[item.prop]}}</span>
</div>
<span v-else>
<el-tooltip placement="top">
<template #content>
<div v-html="getTextContent(scope.row[item.prop])">
</div>
</template>
<div style="overflow: hidden; text-overflow: ellipsis;display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">
{{scope.row[item.prop]}}
</div>
</el-tooltip>
</span>
</slot>
</template>
<el-table-column v-else :align="columnItem.align == undefined ? 'center' : columnItem.align " :label="columnItem.label" :prop="columnItem.prop"
:sortable="columnItem.sortable == undefined ? false : columnItem.sortable"
:width="getWidth(columnItem.width)"
v-for="columnItem in item.columns">
<template #default="scope">
<slot :column="columnItem" :prop="columnItem.prop" :row="scope.row">
<div v-if="typeof(columnItem.click) == 'function' && typeof(columnItem.render) == 'function'">
<span @click="columnItem.click(scope.row)" style="cursor: pointer"
v-html="columnItem.render(scope.row)"></span>
</div>
<div v-else-if="typeof(columnItem.click) == 'function'">
<span @click="columnItem.click(scope.row)" style="cursor: pointer"> {{scope.row[columnItem.prop]}}</span>
</div>
<div v-else-if="typeof(columnItem.render) == 'function'">
<span v-html="columnItem.render(scope.row)">{{scope.row[columnItem.prop]}}</span>
</div>
<span v-else>
<el-tooltip placement="top">
<template #content>
<div v-html="getTextContent(scope.row[columnItem.prop])">
</div>
</template>
<div style="overflow: hidden; text-overflow: ellipsis;display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">
{{scope.row[columnItem.prop]}}
</div>
</el-tooltip>
</span>
</slot>
</template>
</el-table-column>
</el-table-column>
<el-table-column align="center" label="操作" v-if="showTools && columns.length > 0" width="80">
<template #default="scope">
<slot :scope="scope" name="tools"></slot>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div style='text-align: left;background-color: white' v-if="showPage">
<el-pagination
:current-page="currentPage"
:layout="layout"
:page-size="pageSize"
:page-sizes="pageSizes"
:total="total"
@current-change="handleCurrentChange"
@next-click="nextPage"
@prev-click="prePage"
@size-change="handleSizeChange">
</el-pagination>
</div>
</div>
... ...
/**
* 分页表格组件
*/
export default {
name: 'tablePageColumnIndex',
template: '',
components: {},
props: {
// 展示分页
showPage: {
type: Boolean,
default: true
},
showBorder: {
type: Boolean,
default: true
},
// 高度
height: {
type: Number,
default: window.innerHeight
},
// 展示下标
showIndex: {
type: Boolean,
default: true
},
showSelection: {
type: Boolean,
default: false
},
indexLabel: {
type: String,
default: '序号'
},
// 分页页码设置
pageSizes: {
type: Array,
default: [10, 50, 100, 200, 300, 400]
},
// 默认展示
pageSize: {
type: Number,
default: 10
},
// 总数
total: {
type: Number,
default: 0
},
// 展示组件
layout: {
type: String,
// Start Wang 2022/1/19 14:22 上一页和下一页切花不生效,暂无解决办法
//default: "total, prev,pager,next, sizes, jumper"
default: "total, pager,sizes, jumper"
// End Wang 2022/1/19 14:22
},
// 列
columns: {
type: Array,
default: []
},
// 数据
dataList: {
type: Array,
default: []
},
// 是否展示加载
loading: {
type: Boolean,
default: false
},
maxWidth: {
type: Number,
default: window.innerWidth
},
showTools: {
type: Boolean,
default: false
},
// medium / small / mini
size: {
type: String,
default: 'small'
},
multipleSelection: {
type: Array,
default: []
},
//展开行
showExpand: {
type: Boolean,
default: false
},
//行数据的key
getRowKeys: {
type: String,
default: 'id'
},
//默认展开哪行
expands: {
type: Array,
default: []
},
//是否默认展开所有行
defaultExpand: {
type: Boolean,
default: false
}
},
data() {
return {}
},
setup(props, {attrs, slots, emit}) {
const {proxy} = Vue.getCurrentInstance();
let currentPage = Vue.ref(1);
let pageSize = Vue.ref(props.pageSize);
// let multipleSelection=Vue.ref([]);
/**
* 获取宽度
* <p>
* 作者: Wang
* 时间:2021/11/16 16:19
*/
let getWidth = (width) => {
let maxWidth = (function () {
let cols = props.columns;
if (cols && cols.length > 0) {
// 求和
let w = 0;
cols.forEach(function (v) {
w += parseFloat(v.width);
})
let max = props.maxWidth;
if (props.showTools) {
max -= 80;
}
if (w < max) {
return max / w * width;
}
}
return width;
})();
return maxWidth;
}
let callback = () => {
let params = {
page: currentPage.value, limit: pageSize.value
}
proxy.$refs.multipleTable.clearSelection();
emit('loaddata', params)
}
// 每页展示多少条
let handleSizeChange = (val) => {
// Start Wang 2021/12/15 23:46 切换页码重置初始页
currentPage.value = 1
// End Wang 2021/12/15 23:46 切换页码重置初始页
// console.log(`每页 ${val} 条`)
//props.pageSize = val;
pageSize.value = val;
callback();
}
// 切换页码
let handleCurrentChange = (val) => {
// console.log(`当前页: ${val}`)
//props.currentPage = val;
currentPage.value = val;
callback();
}
// 切换页码
let prePage = (val) => {
// console.log(`当前页: ${val}`)
// props.currentPage = val - 1;
currentPage.value = val - 1;
callback();
}
// 切换页码
let nextPage = (val) => {
// console.log(`当前页: ${val}`)
// props.currentPage = val + 1;
currentPage.value = val + 1;
callback();
}
// 监听编辑状态
// Vue.watch(() => filterText.value, (newValue, oldVlaue) => {
// proxy.$refs.tree.filter(newValue)
// });
//全选事件
let handleSelectionChange = (val) => {
// multipleSelection.value = val
emit('selectionChange', val)
}
//设置默认选中
let toggleSelection = (rows) => {
//console.log("rows",rows)
proxy.$nextTick(function () {
//console.log("set",props.dataList,props.multipleSelection)
if (rows) {
rows.forEach(row => {
//设置该表格选框选中
proxy.$refs.multipleTable.toggleRowSelection(row);
});
} else {
proxy.$refs.multipleTable.clearSelection();
}
})
}
let getTextContent = (val) => {
if (val && val != '' && val != null) {
val = val + ''.replace(/[^\x00-\xff]/g, "$&\x01").replace(/.{50}\x01?/g, "$&<br/>").replace(/\x01/g, "");
}
return val;
}
//设置父节点选中后children也选中
let setChecked = (row) => {
let arr = [];
if (row.children) {
row.children.map(j => {
arr.push(j)
setChecked(j)
})
}
toggleSelection(arr)
}
//勾选数据行的Checkbox事件
let handleSelect = (selection, row) => {
setChecked(row);
emit('handleSelect', selection)
}
//勾选全选checkbox事件
let handleSelectAll = (selection) => {
const isSelect = selection.some(el => {
const tableDataIds = props.dataList.map(j => j[props.getRowKeys])
return tableDataIds.includes(el.id)
})
const isCancel = !props.dataList.every(el => {
const selectIds = selection.map(j => j[props.getRowKeys])
return selectIds.includes(el.id)
})
if (isSelect) {
setChecked(selection);
}
if (isCancel) {
props.dataList.map(el => {
setChecked(el);
})
}
emit('handleSelectAll', selection)
}
// 挂载完
Vue.onMounted(() => {
//callback();
})
Vue.watch(() => props.dataList, (newValue, oldValue) => {
setTimeout(function () {
if (props.showSelection) {
toggleSelection(props.multipleSelection)
}
}, 100)
})
return {
handleSelect,
handleSelectAll,
toggleSelection,
handleSelectionChange,
// multipleSelection,
currentPage,
pageSize,
handleSizeChange,
handleCurrentChange,
prePage,
nextPage,
getWidth,
getTextContent
}
}
}
... ...
... ... @@ -31,6 +31,8 @@ Promise.all([
.component('cm-res-type-tree-view', Vue.defineAsyncComponent(() => myImport('components/common/restypetree/index')))
// 资源类型树
.component('cm-table-page', Vue.defineAsyncComponent(() => myImport('components/common/table-page/index')))
// 表格
.component('cm-table-page-column', Vue.defineAsyncComponent(() => myImport('components/common/table-page-column/index')))
// 弹框
.component('cm-dialog', Vue.defineAsyncComponent(() => myImport('components/common/dialog/index')))
// 用户授权
... ...
... ... @@ -93,6 +93,12 @@ const routes = [{
name: 'busyConfig',
component: () => myImport('views/busyConfig/index')
},
//license
{
path: '/vue3/license',
name: 'license',
component: () => myImport('views/license/index')
},
];
// hash模式: createWebHashHistory
... ...
<div :style="{'height':height+'px','max-height':height+'px','background-color':'#fff'}" class="container">
<div :style="{'min-height':height+'px','max-height':height+'px','height':'100%','padding-top':'3px'}"
class="cm-card">
<div class="search" >
<div class="condition" style="width: 100%;justify-content: flex-end;">
<el-form-item>
<el-upload
:auto-upload="true"
:http-request="getFile"
:multiple="false"
:show-file-list="false"
class="upload-demo-license">
<el-button size="mini" type="primary">导入</el-button>
</el-upload>
</el-form-item>
</div>
</div>
<div class="search-table">
<el-row>
<el-col :span="24" class="license-detail">
<el-descriptions title="license文件信息" :column="3" border>
<el-descriptions-item label="授权状态" label-align="right" align="center">
{{tableData.authorizeStats}}
</el-descriptions-item>
<el-descriptions-item label="导入时间" label-align="right" align="center">
{{tableData.authorizeTime}}
</el-descriptions-item>
<el-descriptions-item label="剩余" label-align="right" align="center">
<el-tag size="small" v-if="tableData.timeLeft">{{tableData.timeLeft}}天</el-tag>
</el-descriptions-item>
</el-descriptions>
</el-col>
</el-row>
<el-row>
<el-col :span="24" style="text-align: left;padding: 10px 0;font-size: 16px;font-weight: bold;">授权详情</el-col>
</el-row>
<cm-table-page-column :columns="tableData.columns" :dataList="tableData.dataList"
:height="300"
:loading="false"
:showBorder="true"
:showIndex="false"
:showPage="false"
:showSelection="false"
:showTools="false"
>
<template #default="{row,prop,column}">
<div v-if="row.usage == '已使用'">
<span v-if="tableData.dataList[1][prop]>tableData.dataList[0][prop]" :style="{'color':'red'}">{{row[prop]}}</span>
<span v-else>
{{row[prop]}}
</span>
<el-tooltip
effect="dark"
placement="bottom"
v-if="tableData.dataList[1][prop]>tableData.dataList[0][prop]"
>
<template #content>
<div>
<span>已使用资源数量大于授权数量,请及时更新liscense</span>
<span style="word-break: break-all;">{{splitDetail(prop)}}</span>
</div>
</template>
<i v-if="row[prop] && prop !='usage'" style="margin-left:6px;" class="el-icon-info"></i>
</el-tooltip>
</div>
<div v-else>
<div v-if="row[prop] != null && row[prop] != ''">
<span>
{{row[prop]}}
</span>
</div>
<div v-else>
<span>
-
</span>
<el-tooltip
effect="dark"
placement="bottom"
>
<template #content>
<span>当前协议可以无限绑定采集资源</span>
</template>
<i v-if="prop !='usage'" style="margin-left:6px;" class="el-icon-info"></i>
</el-tooltip>
</div>
</div>
</template>
</cm-table-page-column>
</div>
</div>
</div>
... ...
export default {
name: 'license',
template: '',
components: {
},
props: [],
setup(props, {attrs, slots, emit}) {
const {proxy} = Vue.getCurrentInstance();
let height = Vue.ref(window.innerHeight);
//导入或者详细信息
let isExport=Vue.ref(false);
//表格字段
let tableData = Vue.ref({
count: 0,
dataList: [],
authorizeStats: '',
authorizeTime:'',
timeLeft:'',
columns: [
{
prop: 'usage',
label: '使用情况',
sortable: true,
align: 'center',
width: '100'
},
{
prop: 'resNum',
label: '资源数量',
sortable: true,
align: 'center',
width: '100',
},
{
prop: 'protocolCate',
label: '协议(只统计已挂载任务的资源)',
align: 'center',
columns:[]
}
]
})
// license分类详细协议
let licenseCateData=Vue.ref([
{license:'SSH',protocolCode:'SSH'},
{license:'SSH',protocolCode:'SSHPUBKEY'},
{license:'SSH',protocolCode:'SSHLocalShellPlugin'},
{license:'SSH',protocolCode:'LOCALSSH'},
{license:'SSH',protocolCode:'ShellCommandPlugin'},
{license:'SNMP',protocolCode:'SNMP'},
{license:'SNMP',protocolCode:'SNMP V3'},
{license:'SNMP',protocolCode:'SNMP TRAP'},
{license:'SDK',protocolCode:'SDK'},
{license:'SDK',protocolCode:'SDK'},
{license:'SDK',protocolCode:'SDK'},
{license:'DB',protocolCode:'JDBC'},
{license:'DB',protocolCode:'MONGODB'},
{license:'DB',protocolCode:'REDISX_CLI'},
{license:'JMX',protocolCode:'TOMCAT_JMX'},
{license:'JMX',protocolCode:'ZOOKEEPER_JMX'},
{license:'JMX',protocolCode:'KAFKA_JMX'},
{license:'SYSLOG',protocolCode:'SYSLOG'},
{license:'SYSLOG',protocolCode:'SYSLOGD'},
{license:'HTTP',protocolCode:'HTTP'},
{license:'HTTP',protocolCode:'HTTPS'},
{license:'HTTP',protocolCode:'HUAWEI_CLOUD'},
{license:'HTTP',protocolCode:'ALI_CLOUD'},
{license:'HTTP',protocolCode:'HTTP-电子税务局大屏'},
{license:'HTTP',protocolCode:'HTTP-阿里回迁云'},
{license:'HTTP',protocolCode:'tongwebHttp'},
{license:'HTTP',protocolCode:'QuantumPlugin'},
{license:'HTTP',protocolCode:'CollHuaweiE9000Plugin'},
{license:'HTTP',protocolCode:'CollHuaweiCloudStackPlugin'},
{license:'HTTP',protocolCode:'Coll360'},
{license:'HTTP',protocolCode:'Ezsonar'},
{license:'HTTP',protocolCode:'RongcuoLibraryPlugin'},
{license:'HTTP',protocolCode:'AnGuanPinTaiPlugin'},
{license:'HTTP',protocolCode:'nginxPlugin'},
{license:'IPMI',protocolCode:'IPMI'},
])
//获取license分类下的字段
let cateColumn=Vue.ref([]);
let getLicenseColumn=()=>{
cateColumn.value=[
{
prop: 'ssh',
label: 'SSH',
sortable: true,
align: 'center',
},
{
prop: 'snmp',
label: 'SNMP',
sortable: true,
align: 'center',
},
{
prop: 'sdk',
label: 'SDK',
sortable: true,
align: 'center',
},
{
prop: 'db',
label: 'DB',
sortable: true,
align: 'center',
},
{
prop: 'jmx',
label: 'JMX',
sortable: true,
align: 'center',
},
{
prop: 'syslog',
label: 'SYSLOG',
sortable: true,
align: 'center',
},
{
prop: 'http',
label: 'HTTP',
sortable: true,
align: 'center',
},
{
prop: 'ipmi',
label: 'IPMI',
sortable: true,
align: 'center',
}
]
tableData.value.columns.map(item=>{
if(item.prop=='protocolCate'){
item.columns=cateColumn.value;
}
})
}
// 获取列表
let getDataList = () => {
proxy.$http.get(`/api-web/license/getList`, {}, function (res) {
if (res && res.success) {
let dataList = res.object;
dataList.license.usage='已授权';
dataList.local.usage='已使用';
tableData.value.dataList[0] = dataList.license;
tableData.value.dataList[1] = dataList.local;
if (dataList.authorizeStats){
tableData.value.authorizeStats = '已授权';
}else {
tableData.value.authorizeStats = '未授权';
}
tableData.value.authorizeTime = dataList.authorizeTime;
tableData.value.timeLeft = dataList.timeLeft;
} else {
tableData.value.dataList = [];
}
});
}
//拆分详细协议数组
let splitDetail=(propkey)=>{
let arr=[];
licenseCateData.value.map(v=>{
if(propkey==v.license){
arr.push(v.protocolCode)
}
})
let str='';
if(arr && arr.length>0){
str=arr.join(',')
}
return str;
}
let getFile = (param) => {
let fileObj = param.file
let params = {
file: fileObj,
}
// 上传文件
proxy.$http.uploadFile("/api-web/license/uploadZip", params, function (res) {
if (res && res.success) {
proxy.$global.showMsg("上传成功!");
getDataList();
}
})
}
// 挂载完
Vue.onMounted(() => {
getLicenseColumn();
getDataList();
})
return {
isExport,
getFile,
licenseCateData,
getLicenseColumn,
cateColumn,
splitDetail,
height,
tableData,
getDataList,
}
}
}
... ...
... ... @@ -192,7 +192,13 @@ const routes = [{
path: '/machineRoomRes',
name: 'machineRoomRes',
component: () => myImport('views/machineRoomRes/index')
}
},
//license
{
path: '/vue3/license',
name: 'license',
component: () => myImport('views/license/index')
},
];
// hash模式: createWebHashHistory
... ...