NEZ-3243 feat:License management二级页面开发

This commit is contained in:
zhangyu
2023-10-20 16:40:47 +08:00
parent e66a253055
commit cbaf385be0
16 changed files with 437 additions and 21 deletions

View File

@@ -237,6 +237,15 @@
width: 175px !important;
}
}
.license-management-active {
.el-tabs__header .el-tabs__item {
width: auto !important;
min-width: 120px !important;
}
.el-tabs__active-bar {
width: 141px;
}
}
.nz-dashboard-dropdown {
z-index: 3001 !important;
}

View File

@@ -40,3 +40,21 @@
}
}
}
.license-mange-expand {
display: flex;
margin: 10px;
width: calc(100% - 20px);
box-sizing: border-box;
border-left: 1px solid $--border-color-light;
border-top: 1px solid $--border-color-light;
flex-wrap: wrap;
.license-mange-expand-item {
width: 20%;
flex-shrink: 0;
border-bottom: 1px solid $--border-color-light;
border-right: 1px solid $--border-color-light;
text-align: center;
height: 36px;
line-height: 36px;
}
}

View File

@@ -199,7 +199,6 @@ export default {
this.snapshotVisible = true
},
linkClick (data) {
console.log(data)
if (data.openIn === 'newTab') {
window.open(data.url)
} else {

View File

@@ -83,7 +83,9 @@
<!-- notebook Tab -->
<notebook-tab @getTableData="getTableData" v-if="from === fromRoute.notebook && targetTab === 'notebookTab'" :from="from" :obj="obj" :tabs="tabs.notebook" @changeTab="changeTab" :targetTab.sync="targetTab"></notebook-tab>
<!--softwareAsset列表的tab-->
<endpointTabNew v-if="from === fromRoute.softwareAsset && targetTab === 'endpoint'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.softwareAsset.softwareAssetTabTitle" :targetTab="targetTab" @changeTab="changeTab"></endpointTabNew>
<endpointTabNew v-if="from === fromRoute.softwareAsset && targetTab === 'endpoint'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="softwareAssetTbas" :targetTab="targetTab" @changeTab="changeTab"></endpointTabNew>
<licenseManagementTab v-if="from === fromRoute.softwareAsset && targetTab === 'licenseManagement'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="softwareAssetTbas" :targetTab="targetTab" @changeTab="changeTab"></licenseManagementTab>
<!--softwareType 下滑-->
<softwareAsset v-if="(from === fromRoute.softwareType) && targetTab === 'softwareAsset'" :tabs="tabs.softwareType" ref="assetTab" :from="from" :obj="obj" @changeTab="changeTab" @exit="closeSubList" :targetTab.sync="targetTab"></softwareAsset>
</div>
@@ -125,6 +127,7 @@ import IpDetails from '@/components/common/bottomBox/tabs/IpDetails'
import recordRuleEvalLog from '@/components/common/bottomBox/tabs/recordRuleEvalLog'
import notebookTab from '@/components/common/bottomBox/tabs/notebookTab'
import softwareAsset from '@/components/common/bottomBox/tabs/softwareAsset'
import licenseManagementTab from '@/components/common/bottomBox/tabs/licenseManagementTab'
export default {
name: 'bottomBox',
@@ -160,7 +163,8 @@ export default {
vsysBottomTab,
rolesTab,
notebookTab,
softwareAsset
softwareAsset,
licenseManagementTab
},
props: {
isFullScreen: Boolean, // 是否全屏
@@ -202,6 +206,12 @@ export default {
this.changeTab('dashboardTab')
}
}
if (this.from === this.fromRoute.softwareAsset) {
const hasLog = this.obj.type.name == 'ACC'
if (this.targetTab === 'licenseManagement' && !hasLog) {
this.changeTab('endpoint')
}
}
}
}
},
@@ -250,6 +260,7 @@ export default {
softwareAsset: {
softwareAssetTabTitle: [
{ prop: 'endpoint', name: this.$t('asset.endpoint') },
{ prop: 'licenseManagement', name: this.$t('License Management'), class: 'license-management' }
]
},
endpoint: {
@@ -399,6 +410,15 @@ export default {
tabs.push({ prop: 'log', name: this.$t('dashboard.dashboard.chartForm.typeVal.log.label') })
}
return tabs
},
softwareAssetTbas () {
const tabs = [
{ prop: 'endpoint', name: this.$t('asset.endpoint') }
]
if (this.obj.typeId == 1) {
tabs.push({ prop: 'licenseManagement', name: this.$t('License Management'), class: 'license-management' })
}
return tabs
}
},
methods: {

View File

@@ -20,7 +20,7 @@
<div class="sub-list-tabs">
<!-- <div v-for="tab in tabs" :key="tab.prop" :class="{'sub-list-tab&#45;&#45;active': tab.active || tab.prop == targetTab }" :title='tab.name' class="sub-list-tab" @click="changeTab(tab.prop)">{{tab.name}}</div>-->
<el-tabs v-model="activeTargetTab" @tab-click="changeTab" class="sub-list-tabs-nz-tabs" :class="customClassName">
<el-tab-pane v-for="tab in tabs" :label="tab.name" :name="tab.prop" :key="tab.prop" class="sub-list-tab"></el-tab-pane>
<el-tab-pane v-for="tab in tabs" :label="tab.name" :name="tab.prop" :key="tab.prop" :class="tab.class" class="sub-list-tab"></el-tab-pane>
</el-tabs>
</div>
</div>

View File

@@ -0,0 +1,211 @@
<template>
<div class="full-width-height">
<nz-bottom-data-list
:showTitle='showTitle'
:obj='obj'
:api="url"
:tableId="tableId"
:custom-table-title.sync="tools.customTableTitle"
:layout="['elementSet']"
:search-msg="searchMsg"
:tabs="tabs"
:targetTab="targetTab"
:customClassName="'license-management-active'"
@search="search"
@changeTab="changeTab"
class="full-width-height"
>
<template v-slot:title><span :title="obj ? obj.name: '-'">{{obj.name}}</span></template>
<template v-slot:top-tool-right>
<button id="license-mange-export" class="top-tool-btn margin-l-10" @click.stop="exportLicense()" :title="$t('overall.exportExcel')">
<i class="nz-icon nz-icon-download1"></i>
</button>
<el-upload
action=""
:auto-upload="false"
accept=".v2c,.V2CP,.H2R,.R2H,.H2H,.ID "
:on-change="uploadChange"
style="display: none"
ref="upload"
>
</el-upload>
<button id="license-mange-import" class="top-tool-btn margin-l-10 margin-r-10" @click.stop="importLicense" :title="$t('overall.importExcel')">
<i class="nz-icon nz-icon-upload"></i>
</button>
</template>
<template v-slot>
<licenseMangeTable
ref="dataTable"
:orderByFa="'id'"
v-my-loading="tools.loading"
:api="url"
:custom-table-title="tools.customTableTitle"
:height="subTableHeight"
:now-time="nowTime"
:table-data="tableData"
:endpointTab="true"
class="bottom-box__top"
@del="del"
@edit="edit"
@copy="copy"
@orderBy="tableDataSort"
@addSilence="addSilence"
@reload="getTableData"
@topology="topology"
@metricTarget="metricTarget"
@selectionChange="selectionChange"
@export="exportLicense"
></licenseMangeTable>
</template>
<!-- <template v-slot:pagination>-->
<!-- <Pagination ref="Pagination" :pageObj="pageObj" :tableId="tableId" @pageNo='pageNo' @pageSize='pageSize'></Pagination>-->
<!-- </template>-->
</nz-bottom-data-list>
</div>
</template>
<script>
import dataListMixin from '@/components/common/mixin/dataList'
import subDataListMixin from '@/components/common/mixin/subDataList'
import nzBottomDataList from '@/components/common/bottomBox/nzBottomDataList'
import licenseMangeTable from '@/components/common/table/asset/licenseMangeTable'
import { fromRoute } from '@/components/common/js/constants'
import detailViewRightMixin from '@/components/common/mixin/detailViewRightMixin'
import axios from 'axios'
export default {
name: 'licenseMangeTab',
mixins: [dataListMixin, subDataListMixin, detailViewRightMixin],
components: {
nzBottomDataList,
licenseMangeTable
},
watch: {
obj: {
immediate: true,
async handler (n) {
if (n) {
this.searchLabel = {}
this.getTableData()
}
}
}
},
data () {
return {
url: 'license/product',
tableId: 'licenseMangeTable', // 需要分页的table的id用于记录每页数量
searchMsg: { // 给搜索框子组件传递的信息
zheze_none: true,
searchLabelList: [{
id: 13,
name: this.$t('project.endpoint.endpointId'),
type: 'input',
label: 'ids',
disabled: false
},
{
id: 12,
name: this.$t('project.endpoint.endpointName'),
type: 'input',
label: 'name',
disabled: false
}
]
},
blankSilenceObject: {
startAt: ''
},
objectSilence: {},
silenceBoxShow: false,
nowTime: '',
rightBox: {
editShow: false,
show: false
},
fromBottom: true,
needAlertDaysData: true,
trendKey: 'endpointId'
}
},
methods: {
getTableData () {
this.tools.loading = true
const params = {
// ...this.searchLabel,
// pageNo: this.pageObj.pageNo,
// pageSize: this.pageObj.pageSize
}
params.saId = this.obj.id
this.$get(this.url, params).then(response => {
this.tools.loading = false
if (response.code === 200) {
response.data.list.forEach(item => {
item.haspid += ''
})
this.tableData = response.data.list
this.nowTime = this.utcTimeToTimezoneStr(response.time)
this.pageObj.total = response.data.total
if (!this.scrollbarWrap && this.$refs.dataTable && this.$refs.dataTable.$refs.dataTable) {
this.$nextTick(() => {
this.scrollbarWrap = this.$refs.dataTable.$refs.dataTable.bodyWrapper
this.toTopBtnHandler(this.scrollbarWrap)
})
}
}
})
},
importLicense () {
this.$refs.upload.$children[0].$refs.input.click()
},
exportLicense (params) {
if (this.paramsType) {
params.type = this.paramsType
}
if (!params) {
params = {}
}
params.saId = this.obj.id
axios.get('/license/downloadC2V', { responseType: 'blob', params: params }).then(res => {
if (window.navigator.msSaveOrOpenBlob) {
// 兼容ie11
const blobObject = new Blob([res.data])
window.navigator.msSaveOrOpenBlob(blobObject)
} else {
const url = URL.createObjectURL(new Blob([res.data]))
const a = document.createElement('a')
document.body.appendChild(a) // 此处增加了将创建的添加到body当中
a.href = url
a.target = '_blank'
a.click()
a.remove() // 将a标签移除
}
}, error => {
const $self = this
const reader = new FileReader()
reader.onload = function (event) {
const responseText = reader.result
const exception = JSON.parse(responseText)
if (exception.message) {
$self.$message.error(exception.message)
} else {
console.error(error)
}
}
reader.readAsText(error.response.data)
})
},
async uploadChange (file) {
const form = new FormData()
form.append('file', file.raw)
form.append('saId', this.obj.id)
const res = await this.$post('/license/uploadV2C', form, { 'Content-Type': 'multipart/form-data' })
if (res.code === 200) {
this.$message.success()
} else {
this.$message.error(res.msg)
}
}
}
}
</script>

View File

@@ -61,7 +61,7 @@ export default {
if (this.detailType) {
params.detailType = this.detailType
}
if (this.detailType === 'list' && this.$refs[detailType]) {
if (this.detailType === 'list' && this.$refs[detailType] && this.$refs[detailType].bottomBox) {
params.bottomBox = this.$refs[detailType].bottomBox.showSubList
params.targetTab = this.$refs[detailType].bottomBox.targetTab
} else {
@@ -74,6 +74,7 @@ export default {
const obj = {
id: this.$refs[detailType].bottomBox.object.id,
name: this.$refs[detailType].bottomBox.object.name,
typeId: this.$refs[detailType].bottomBox.object.typeId,
childrenNum: this.$refs[detailType].bottomBox.object.childrenNum || '',
clientState: this.$refs[detailType].bottomBox.object.clientState || '',
protocol: this.$refs[detailType].bottomBox.object.protocol || '',
@@ -100,6 +101,7 @@ export default {
const obj = {
id: this.$refs[detailType].detailViewRightObj.id,
name: this.$refs[detailType].detailViewRightObj.name,
typeId: this.$refs[detailType].detailViewRightObj.typeId,
childrenNum: this.$refs[detailType].detailViewRightObj.childrenNum || '',
clientState: this.$refs[detailType].detailViewRightObj.clientState || '',
protocol: this.$refs[detailType].detailViewRightObj.protocol || '',
@@ -133,6 +135,7 @@ export default {
const obj = {
id: this.bottomBox.object.id,
name: this.bottomBox.object.name,
typeId: this.bottomBox.object.typeId,
childrenNum: this.bottomBox.object.childrenNum || '',
clientState: this.bottomBox.object.clientState || '',
protocol: this.bottomBox.object.protocol || '',
@@ -164,6 +167,7 @@ export default {
const obj = {
id: this.detailViewRightObj.id,
name: this.detailViewRightObj.name,
typeId: this.detailViewRightObj.typeId,
childrenNum: this.detailViewRightObj.childrenNum || '',
clientState: this.detailViewRightObj.clientState || '',
protocol: this.detailViewRightObj.protocol || '',
@@ -203,7 +207,7 @@ export default {
setTimeout(() => {
const obj = lodash.cloneDeep(val.defaultJson)
obj[val.jsonKey] = qv
if (obj[val.jsonKey]) {
if (obj[val.jsonKey] && this.$refs[dataList].$refs.searchInput) {
this.$refs[dataList].$refs.searchInput.select_list.push(obj)
this.$refs[dataList].$refs.searchInput.sreach_num++
}

View File

@@ -30,7 +30,6 @@ export default {
getTopology(this.meta2dId)._setValue(node)
},
getQueryValues (elements, startTime, endTime) {
console.log(startTime, endTime)
this.meta2dLoading = true
return new Promise(resolve => {
const step = bus.getStep(startTime, endTime)

View File

@@ -439,7 +439,6 @@ export default {
img.src = _URL.createObjectURL(file.raw)
}).then(() => {
if (isJPG) {
console.log(file.raw)
this.getBase64(file.raw).then(base64Str => {
this.imageUrl = base64Str
})

View File

@@ -0,0 +1,170 @@
<template>
<div style="height: 100%">
<el-table
id="softwareTypeTable"
ref="dataTable"
:data="tableData"
:height="height"
border
:default-sort="orderBy"
@header-dragend="dragend"
@sort-change="tableDataSort"
@selection-change="selectionChange"
@row-dblclick="(row)=>{}"
>
<el-table-column
:resizable="false"
align="center"
type="expand"
width="55">
<template slot-scope="scope">
<div class="license-mange-expand" style="" v-if="scope.row.sessions.length">
<div v-for="(item,index) in scope.row.sessions" :key="index" class="license-mange-expand-item">
{{item}}
</div>
</div>
<div v-else class="table-no-data" style="text-align: center;padding: 10px;box-sizing: border-box;">
<svg class="icon" aria-hidden="true">
<use xlink:href="#nz-icon-no-data-list"></use>
</svg>
<div class="table-no-data__title">No results found</div>
</div>
</template>
</el-table-column>
<el-table-column
v-for="(item, index) in customTableTitle"
v-if="item.show"
:key="`col-${index}-${item.prop}`"
:fixed="item.fixed"
:label="item.label"
:min-width="`${item.minWidth}`"
:prop="item.prop"
:resizable="true"
:sort-orders="['ascending', 'descending']"
:sortable="item.sortable"
:width="`${item.width}`"
>
<template slot="header">
<span class="data-column__span">{{item.label}}</span>
<div class="col-resize-area"></div>
</template>
<template slot-scope="scope" :column="item">
<template v-if="item.prop === 'name' || item.prop === 'typename'">
<div class="document-copy-block">
<span class="document-copy-text" :title="scope.row[item.prop]">{{scope.row[item.prop]}}</span>
<i v-if="scope.row[item.prop]" class="nz-icon nz-icon-override" style="visibility: hidden" @click="onCopy(scope.row.name)" :title="$t('overall.copyText')"></i>
</div>
</template>
<template v-else-if="item.prop === 'category'">
<div>
{{scope.row.type ? scope.row.type.category : '-'}}
</div>
</template>
<span v-else-if="item.prop === 'production_date' || item.prop === 'expiration_date'">{{ scope.row[item.prop] ? momentTz(scope.row[item.prop]) : '-'}}</span>
<span v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column
:resizable="false"
:width="operationWidth"
fixed="right">
<div slot="header" class="table-operation-title">{{$t('overall.option')}}</div>
<div slot-scope="scope" class="table-operation-items">
<!-- <button class="table-operation-item" v-has="'softwareAsset_edit'" @click="$emit('edit', scope.row)" :title="$t('overall.edit')"><i class="nz-icon nz-icon-edit"></i></button> -->
<button class="table-operation-item" @click="exportLicense(scope.row)" :title="$t('overall.view')"><i class="nz-icon nz-icon-download1"></i></button>
</div>
</el-table-column>
<template slot="empty">
<div v-if="!loading" class="table-no-data">
<svg class="icon" aria-hidden="true">
<use xlink:href="#nz-icon-no-data-list"></use>
</svg>
<div class="table-no-data__title">No results found</div>
</div>
<div v-else>&nbsp;</div>
</template>
</el-table>
<alertLabel
v-if="alertLabelShow"
:id="alertLabelId"
:that="alertLabelObj"
:type="alertLabelType"
></alertLabel>
</div>
</template>
<script>
import table from '@/components/common/mixin/table'
import copy from '@/components/common/copy'
import alertLabelMixin from '@/components/common/mixin/alertLabelMixin'
export default {
name: 'licenseMangeTable',
mixins: [table, alertLabelMixin],
components: { copy },
props: {
loading: Boolean
},
data () {
return {
tableTitle: [ // 原始table列
{
label: this.$t('licenseMange.product'),
prop: 'typename',
show: true,
width: 350
// sortable: 'custom'
}, {
label: this.$t('licenseMange.keyType'),
prop: 'name',
minWidth: 200,
show: true
}, {
label: this.$t('licenseMange.keyId'),
prop: 'haspid',
show: true,
width: 350
}, {
label: this.$t('licenseMange.dateIssue'),
prop: 'production_date',
show: true,
minWidth: 200
},
{
label: this.$t('licenseMange.dateExpire'),
prop: 'expiration_date',
minWidth: 200,
show: true
},
{
label: this.$t('licenseMange.concurrency'),
prop: 'loginlimit',
minWidth: 200,
show: true
}, {
label: this.$t('licenseMange.logins'),
prop: 'logincount',
minWidth: 200,
show: true
}
]
}
},
methods: {
copyValue (item) {
const str = item
this.$copyText(JSON.stringify(str)).then(() => {
this.$message.success({ message: this.$t('overall.copySuccess') })
})
},
exportLicense (row) {
this.$emit('export', { haspid: row.haspid })
}
},
created () {
},
computed: {
}
}
</script>

View File

@@ -612,15 +612,12 @@ export default {
const endTime = this.momentStrToTimestamp(start + ' 23:59:59', 'YYYY-MM-DD HH:mm:ss')
start = this.momentSetMonthDate(noTime, 1)
end = this.momentSetMonthDate(endTime, 31)
console.log(end)
}
if (nowTimeType.id === 20) { // Previous month 需要判断当前是否是 1号
unit = 'm'
const noTime = this.momentStrToTimestamp(start + ' 00:00:00', 'YYYY-MM-DD HH:mm:ss')
end = this.momentStrToTimestamp(this.momentSetMonthDate(noTime, 1)) - 1000 // 当月1号 00:00:00 减1s 则是上月最后一天 23:59:59
console.log(end, '1')
start = this.momentSetMonthDate(end, 1, 'YYYY-MM-DD') + ' 00:00:00'
console.log(start, '1')
start = this.momentTz(this.momentStrToTimestamp(start, 'YYYY-MM-DD HH:mm:ss'))
end = this.momentTz(end)
}

View File

@@ -4149,13 +4149,11 @@ export default {
}
},
async queryTableData () {
console.log(this.expressions)
this.tools.loading = true
if (this.expressions.length > 0) {
const requestArr = []
this.expressions.forEach((item, index) => {
// 过滤掉state为0的元素
console.log(this.promqlKeys[index].queryType)
if (item !== '' && this.promqlKeys[index].state && this.promqlKeys[index].queryType == 2) {
// requestArr.push(this.$get('/prom/api/v1/query?query=' + encodeURIComponent(item)))
this.showTable = true

View File

@@ -310,7 +310,6 @@ export default {
this.expressions = []
this.expressionsShow = []
this.expressionName = []
console.log(this.promqlKeys.length)
if (!this.promqlKeys.length) {
this.addExpression()
} else {
@@ -406,7 +405,6 @@ export default {
if (!item) {
this.expressions.push('')
const expressionName = this.getExpressionName()
console.log(expressionName)
this.expressionName.push(expressionName)
this.expressionsShow.push({
id: getUUID(),
@@ -469,7 +467,6 @@ export default {
this.$set(this.expressionsShow, index - 1, this.expressionsShow[index - 1])
},
showHistoryBox (index) {
console.log(this.$refs['promql-' + (index)])
const historyshow = this.$refs['promql-' + (index)][0]?.historyshow
this.$refs['promql-' + (index)][0]?.showHistoryBox(!historyshow)
}

View File

@@ -1043,7 +1043,6 @@ export default {
const boxHeight = 400
const parentHeight = this.$refs.queryRow.offsetHeight + 10
let top = 0
console.log()
const left = position.left
if (position.top + parentHeight + boxHeight > windowHeight - 100) {
top = position.top - boxHeight - 10
@@ -1054,7 +1053,6 @@ export default {
top: top,
left: left
}
console.log(position, this.queryPromptWidth)
},
selectMetric (item) {
if (!item.id) {

View File

@@ -262,7 +262,6 @@ export default {
} else {
this.logValues = []
}
console.log(this.logValues)
})
},
selectValue (obj) {

View File

@@ -55,11 +55,9 @@ export default {
const nowTime = new Date().getTime()
const start = this.start ? this.start : nowTime - 60 * 60 * 10000
const end = this.end ? this.end : nowTime
console.log(start, end)
url += `start=${start}&end=${end}&step=15s&nullType=zero`
url += `&query=${encodeURIComponent(this.metrics)}`
this.$get(url).then(res => {
console.log(res)
this.oldData = res.data
})
}