Compare commits

...

30 Commits

Author SHA1 Message Date
刘洪洪
5c4993cf12 fix: 修复report编辑按钮不会disabled的问题 2024-05-11 18:17:55 +08:00
刘洪洪
b8ee685230 fix: report一系列问题修改 2024-05-11 16:28:27 +08:00
陈劲松
30b1328576 Merge branch 'cherry-pick-3513a9c1' into 'dev-24.01-m22'
fix: 修复entity的搜索测试用例报错的问题

See merge request cyber-narrator/cn-ui!72
2024-05-11 06:49:45 +00:00
刘洪洪
740e7bbae6 fix: 修复entity的搜索测试用例报错的问题
(cherry picked from commit 3513a9c145)
2024-05-11 06:49:38 +00:00
陈劲松
f020fe33b5 Merge branch 'cherry-pick-df183c18' into 'dev-24.01-m22'
fix: 修复entity和detection搜索时随意输入字段,没有错误提示且resource为空的问题

See merge request cyber-narrator/cn-ui!71
2024-05-09 09:08:56 +00:00
刘洪洪
75b47d7ba7 fix: 修复entity和detection搜索时随意输入字段,没有错误提示且resource为空的问题
(cherry picked from commit df183c1836)
2024-05-09 09:08:48 +00:00
chenjinsong
a26b0c848d fix: 修复链路四元组图字段名未升级的问题 2024-04-30 17:06:46 +08:00
陈劲松
d2ad042cf9 Merge branch 'cherry-pick-ca6f6a02' into 'dev-24.01-m22'
CN-1651 fix: 修复链路links下钻报错问题

See merge request cyber-narrator/cn-ui!69
2024-04-28 10:31:54 +00:00
chenjinsong
a844d44d1d CN-1651 fix: 修复链路links下钻报错问题
(cherry picked from commit ca6f6a02e9)
2024-04-28 10:31:45 +00:00
chenj
ad603339de fix: 隐藏detection页的policy入口 2024-04-01 21:06:04 +08:00
陈劲松
08f0cd4522 Merge branch 'cherry-pick-e645eeb1' into 'dev-24.01'
fix: 更改license失效码

See merge request cyber-narrator/cn-ui!68
2024-03-25 07:51:28 +00:00
chenjinsong
0c20757d07 fix: 更改license失效码
(cherry picked from commit e645eeb1a5)
2024-03-25 07:51:22 +00:00
陈劲松
2c7c7293b4 Merge branch 'cherry-pick-5511191c' into 'dev-24.01'
fix: license上传文件后进行页面刷新

See merge request cyber-narrator/cn-ui!67
2024-03-25 07:51:06 +00:00
hanyuxia
d035677c2f fix: license上传文件后进行页面刷新
(cherry picked from commit 5511191c90)
2024-03-25 07:50:57 +00:00
陈劲松
50cdbde8bf Merge branch 'cherry-pick-8a18fb09' into 'dev-24.01'
fix: 许可证下载文件名称从响应头中的Content-Disposition获取

See merge request cyber-narrator/cn-ui!66
2024-03-25 07:49:56 +00:00
hanyuxia
d27738b9ec fix: 许可证下载文件名称从响应头中的Content-Disposition获取
(cherry picked from commit 8a18fb09f4)
2024-03-25 07:49:49 +00:00
chenjinsong
85456c1e47 fix: 更改插件的周期信息 2024-03-20 20:08:33 +08:00
陈劲松
327cbde233 Merge branch 'cherry-pick-bcf57611' into 'dev-24.01'
feat:插件id及逻辑变动(有一些同名,但type(ip、domain)不同的,合并成一条;合并后的记录,type列既有ip标签又有domain标签)

See merge request cyber-narrator/cn-ui!65
2024-03-20 09:56:48 +00:00
hyx
cbf71eb1b9 feat:插件id及逻辑变动(有一些同名,但type(ip、domain)不同的,合并成一条;合并后的记录,type列既有ip标签又有domain标签)
(cherry picked from commit bcf57611ef)
2024-03-20 09:56:40 +00:00
chenjinsong
4e0eb3f143 fix: 修复license未认证的情况下,按回车键可以登录的问题 2024-03-19 16:03:21 +08:00
陈劲松
a17c68bb26 Merge branch 'cherry-pick-da015603' into 'dev-24.01'
fix: 修复下载license时文件名不对的问题

See merge request cyber-narrator/cn-ui!63
2024-03-19 07:46:16 +00:00
chenjinsong
d1ae513124 fix: 修复下载license时文件名不对的问题
(cherry picked from commit da0156031c)
2024-03-19 07:46:09 +00:00
陈劲松
91915996c0 Merge branch 'cherry-pick-d0b29c24' into 'dev-24.01'
feat: CN-1558 开发license页面,支持license拦截

See merge request cyber-narrator/cn-ui!62
2024-03-19 03:04:37 +00:00
hanyuxia
8f17647752 feat: CN-1558 开发license页面,支持license拦截
(cherry picked from commit d0b29c24ba)
2024-03-19 03:04:31 +00:00
陈劲松
29a319609e Merge branch 'cherry-pick-21da4f0d' into 'dev-24.01'
feat: CN-1558 开发license页面,支持license拦截

See merge request cyber-narrator/cn-ui!61
2024-03-19 03:04:10 +00:00
hanyuxia
08ae827e31 feat: CN-1558 开发license页面,支持license拦截
(cherry picked from commit 21da4f0d49)
2024-03-19 03:04:04 +00:00
陈劲松
854a846296 Merge branch 'cherry-pick-06a8bd96' into 'dev-24.01'
feat: CN-1558 开发license页面,支持license拦截

See merge request cyber-narrator/cn-ui!60
2024-03-19 03:02:37 +00:00
hanyuxia
42aa7671a3 feat: CN-1558 开发license页面,支持license拦截
(cherry picked from commit 06a8bd9626)
2024-03-19 03:02:30 +00:00
陈劲松
fb89134f95 Merge branch 'cherry-pick-4429d225' into 'dev-24.01'
feat: CN-1558 开发license页面(未完成:登陆页支持license拦截)

See merge request cyber-narrator/cn-ui!59
2024-03-19 03:01:31 +00:00
hyx
584ad8d538 feat: CN-1558 开发license页面(未完成:登陆页支持license拦截)
(cherry picked from commit 4429d225f1)
2024-03-19 03:01:23 +00:00
22 changed files with 676 additions and 179 deletions

View File

@@ -22,15 +22,39 @@
></el-input> ></el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button <el-button :disabled="licenseStatus !== 0"
v-loading="loading" v-loading="loading"
type="primary" type="primary"
class="login--input login--button" class="login--input login--button"
:class="{'login-btn__license-error':licenseStatus !== 0}"
@click="login" @click="login"
@keyup.enter="login" @keyup.enter="login"
style="font-size: 16px;" style="font-size: 16px;"
>Login</el-button >Login
> </el-button>
</el-form-item>
<el-form-item v-if="licenseStatus !== 0">
<div class="license-error-msg">{{licenseStatusErrMsg}}</div>
<div class="license-file">
<button style="position: relative;" class="license__btn margin-r-20" @click.prevent="downloadFile" @keyup.enter="login">
<i class="cn-icon-download1 cn-icon margin-r-6"></i><span>Download c2v file</span>
</button>
<el-upload :action="`${baseUrl}sys/license/upload`"
ref="licenseUpload"
id="licenseUpload"
:multiple="false"
:show-file-list="false"
:accept="fileTypeLimit"
:file-list="fileList"
:auto-upload="false"
:on-change="fileChange"
:on-success="uploadSuccess"
:on-error="uploadError">
<button style="position: relative;" class="license__btn" @click.prevent="">
<i class="cn-icon-upload1 cn-icon margin-r-6"></i><span>Upload license</span>
</button>
</el-upload>
</div>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
@@ -46,6 +70,7 @@ import { api } from '@/utils/api'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import _ from 'lodash' import _ from 'lodash'
import utc from 'dayjs/plugin/utc' import utc from 'dayjs/plugin/utc'
import { ref } from 'vue'
dayjs.extend(utc) dayjs.extend(utc)
export default { export default {
@@ -55,7 +80,11 @@ export default {
loading: false, loading: false,
username: '', username: '',
pin: '', pin: '',
language: '' language: '',
licenseStatus: 1,
licenseStatusErrMsg: '',
downloadC2vUrl: api.downloadLicenseC2v,
supportID: ''
} }
}, },
methods: { methods: {
@@ -69,6 +98,9 @@ export default {
} else { } else {
return return
} }
if (this.licenseStatus !== 0) {
return
}
this.loading = true this.loading = true
axios.post(api.login, { username: this.username, pin: this.pin }).then( axios.post(api.login, { username: this.username, pin: this.pin }).then(
res => { res => {
@@ -103,6 +135,72 @@ export default {
} }
}) })
}, },
downloadFile () {
axios.get(this.downloadC2vUrl, { responseType: 'blob' }).then(res => {
const disposition = res.headers['content-disposition']
const fileName = decodeURI(disposition.split('filename=')[1])
if (window.navigator.msSaveOrOpenBlob) {
// 兼容ie11
const blobObject = new Blob([res.data])
window.navigator.msSaveOrOpenBlob(blobObject, fileName)
} else {
const url = URL.createObjectURL(new Blob([res.data]))
const a = document.createElement('a')
document.body.appendChild(a) // 此处增加了将创建的添加到body当中
a.href = url
a.download = fileName
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)
})
},
fileChange (file, fileList) {
if (file.status !== 'ready') return
if (!_.endsWith(file.name, '.xml')) {
this.fileList = []
this.$message.error('Only support '+ this.fileTypeLimit + ' files')
} else {
this.fileList = fileList.slice(-1)
this.$refs.licenseUpload.submit()
}
},
uploadSuccess (response) {
this.$message.success('Success')
this.licenseStatus = 0
},
uploadError (error) {
let errorMsg
if (error.message) {
errorMsg = JSON.parse(error.message).message
} else {
errorMsg = 'error'
}
this.licenseStatus = 1
this.$message.error('Upload failed: ' + errorMsg)
},
checkLicenseStatus () {
axios.get(api.licenseStatus).then(res => {
if (res.status === 200) {
this.licenseStatus = res.data.data.status
}
}).catch(e => {
this.licenseStatusErrMsg = this.errorMsgHandler(e)
})
},
queryAppearance () { queryAppearance () {
axios.get(api.appearance).then(res => { axios.get(api.appearance).then(res => {
if (res.status === 200) { if (res.status === 200) {
@@ -128,13 +226,17 @@ export default {
localStorage.setItem(storageKey.sysLogo, data.system_logo) localStorage.setItem(storageKey.sysLogo, data.system_logo)
} }
}, },
mounted () { async mounted () {
this.queryAppearance() this.queryAppearance()
this.checkLicenseStatus()
}, },
setup (props) { setup (props) {
const { currentRoute } = useRouter() const { currentRoute } = useRouter()
return { return {
loginSuccessPath: currentRoute.value.query.redirect loginSuccessPath: currentRoute.value.query.redirect,
baseUrl: BASE_CONFIG.baseUrl,
fileTypeLimit: '.xml',
fileList: ref([])
} }
} }
} }
@@ -181,7 +283,7 @@ export default {
} }
.inside { .inside {
width: 414px; width: 414px;
height: 524px; height: fit-content;/*524*/
background: #0B325C; background: #0B325C;
border: 1px solid rgba(103,179,245,0.65); border: 1px solid rgba(103,179,245,0.65);
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.38); box-shadow: 0 2px 4px 0 rgba(0,0,0,0.38);
@@ -198,6 +300,7 @@ export default {
.title { .title {
margin-top: 65px; margin-top: 65px;
margin-bottom: 44px;
text-align: center; text-align: center;
} }
.title > img { .title > img {
@@ -208,6 +311,39 @@ export default {
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
.is-disabled {
background: #21B4ED;
color: #FFFFFF;
opacity: 0.6;
}
.license-error-msg {
color:#c73249;
display: flex;
align-items: flex-start;
justify-content: center;
height:40px;
}
.license-file {
display: flex;
flex-direction: row;
height: 100%;
align-items: center;
justify-content: space-between;
.license__btn {
height: 40px;
padding-left:10px;
padding-right:10px;
min-width: 74px;
color: white;
background-color: #21B4ED;
border: none;
border-radius: 4px;
outline: none;
font-size: 14px;
cursor: pointer;
transition: background-color linear .2s, color linear .1s;
}
}
} }
:deep .el-form-item { :deep .el-form-item {
width: 334px; width: 334px;
@@ -220,9 +356,8 @@ export default {
width: 17px; width: 17px;
font-size: 17px; font-size: 17px;
} }
.login__box .el-form-item:nth-of-type(3) { .login__box .el-form-item:nth-child(3){
margin-top: 25px; margin-bottom: 0px;
margin-bottom: 65px;
} }
.login--button { .login--button {
background: #21B4ED; background: #21B4ED;
@@ -234,5 +369,12 @@ export default {
line-height: 22px; line-height: 22px;
width: 334px; width: 334px;
height: 52px; height: 52px;
margin-top: 25px;
margin-bottom:65px;
}
.login-btn__license-error {
margin-top: 25px;
margin-bottom: 10px;
height:40px;
} }
</style> </style>

View File

@@ -80,6 +80,7 @@
@import 'views/administration/AdministrationTabs'; @import 'views/administration/AdministrationTabs';
@import 'views/administration/Appearance.scss'; @import 'views/administration/Appearance.scss';
@import 'views/administration/License.scss';
@import 'views/system/Plugin'; @import 'views/system/Plugin';

View File

@@ -0,0 +1,61 @@
.license{
height: 100%;
.license-form {
padding-top:40px;
padding-left:100px;
background-color: white;
position: relative;
display: flex;
flex-direction: column;
height: 100%;
.license-file {
display: flex;
flex-direction: row;
height: 100%;
margin-top: 3px;
.license__btn {
height: 30px;
min-width: 74px;
color: white;
background-color: #38ACD2;
border: none;
border-radius: 4px;
outline: none;
font-size: 14px;
cursor: pointer;
transition: background-color linear .2s, color linear .1s;
}
.license__btn:hover:not(.footer__btn--disabled) {
background-color: lighten(#38ACD2, 10%);
}
.license__btn--light {
background-color: #F5F6F7;
border: 1px solid $--border-color-primary;
color: #333;
}
.license__btn.license__btn--light:hover:not(.license__btn--disabled) {
background-color: white;
border-color: lighten(#38ACD2, 40%);
color: #38ACD2;
}
.license__btn--disabled {
opacity: .6;
cursor: default;
}
}
.el-form .el-form-item {
margin-bottom: 0;
padding:4px 0;
font-size: 14px!important;
.el-form-item__label {
color: #262626 !important;
font-weight: bold;
}
.el-form-item__content {
color: #262626 !important;
font-weight: 400;
}
}
}
}

View File

@@ -24,6 +24,7 @@
color: #046ECA; color: #046ECA;
box-shadow: 0 2px 4px 0 rgba(51,51,51,0.02); box-shadow: 0 2px 4px 0 rgba(51,51,51,0.02);
border-radius: 12px; border-radius: 12px;
margin-right:10px;
} }
.plugin-name { .plugin-name {
display: flex; display: flex;

View File

@@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "cn-icon"; /* Project id 2614877 */ font-family: "cn-icon"; /* Project id 2614877 */
src: url('iconfont.woff2?t=1703561754372') format('woff2'), src: url('iconfont.woff2?t=1706606024800') format('woff2'),
url('iconfont.woff?t=1703561754372') format('woff'), url('iconfont.woff?t=1706606024800') format('woff'),
url('iconfont.ttf?t=1703561754372') format('truetype'); url('iconfont.ttf?t=1706606024800') format('truetype');
} }
.cn-icon { .cn-icon {
@@ -13,6 +13,26 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.cn-icon-license:before {
content: "\e666";
}
.cn-icon-base-station:before {
content: "\e6cf";
}
.cn-icon-home:before {
content: "\e6d0";
}
.cn-icon-company:before {
content: "\e6d1";
}
.cn-icon-pedestrian:before {
content: "\e6d2";
}
.cn-icon-system:before { .cn-icon-system:before {
content: "\e6cc"; content: "\e6cc";
} }
@@ -373,7 +393,7 @@
content: "\e7b4"; content: "\e7b4";
} }
.cn-icon-a-GeneralSettings:before { .cn-icon-general-setting:before {
content: "\e7b5"; content: "\e7b5";
} }

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1135,12 +1135,12 @@ export default class Parser {
} }
return returnObj return returnObj
} else if (q.indexOf(' LIKE ') > -1 || q.indexOf(' like ') > -1) { } else if (q.toLowerCase().indexOf(' like ') > -1) {
return { return {
key: q, key: q,
isKey: true isKey: true
} }
} else if (q.indexOf(' IN ') > -1 || q.indexOf(' in ') > -1) { } else if (q.toLowerCase().indexOf(' in ') > -1) {
return { return {
key: q, key: q,
isKey: true isKey: true
@@ -1154,15 +1154,79 @@ export default class Parser {
return { key: '[' + key + ']', isKey: false } return { key: '[' + key + ']', isKey: false }
} }
} }
} else if (q && (q.indexOf(' IN ') > -1 || q.indexOf(' in ') > -1 || q.indexOf(' LIKE ') > -1 || q.indexOf(' like ') > -1)) { } else if (q && (q.toLowerCase().indexOf(' in ') > -1 || q.toLowerCase().indexOf(' like ') > -1 || q.toLowerCase().indexOf('has(') > -1)) {
return { const lowerQ = q.toLowerCase()
key: q, if (lowerQ.indexOf(' and ') > -1) {
isKey: true if (this.checkStrIncludeAnd(q)) {
q = q.replace(/ and /g, ' AND ')
}
const arr = q.split(' AND ')
for (let i = 0; i < arr.length; i++) {
const item = arr[i].toLowerCase()
if (item.indexOf(' like ') > -1) {
const key = item.substring(0, item.indexOf(' like '))
const obj = this.columnList.find(t => t.label.toLowerCase() === key.toLowerCase())
if (!obj) {
return { key: '[' + key + ']', isKey: false }
}
} else if (item.indexOf(' in ') > -1) {
const key = q.substring(0, q.indexOf(' in '))
const obj = this.columnList.find(t => t.label.toLowerCase() === key.toLowerCase())
if (!obj) {
return { key: '[' + key + ']', isKey: false }
}
} else if (item.indexOf('has(') > -1) {
const key = item.substring(0, 4)
if (key === 'has(') {
const label = item.substring(4, item.indexOf(','))
if (label) {
const obj = this.columnList.find(t => t.label.toLowerCase() === label.toLowerCase())
if (!obj) {
return { key: '[' + key + ']', isKey: false }
}
} else {
return { key: 'in index ' + q.indexOf('has('), isKey: false }
}
} else {
return { key: 'in index ' + q.indexOf('has('), isKey: false }
}
}
}
return { key: q, isKey: true }
} else if (lowerQ.indexOf(' like ') > -1) {
const key = q.substring(0, q.indexOf(' like '))
const obj = this.columnList.find(t => t.label.toLowerCase() === key.toLowerCase())
if (obj) {
return { key: obj.label + q.substring(lowerQ.indexOf(' like '), q.length), isKey: true }
} else {
return { key: '[' + key + ']', isKey: false }
}
} else if (lowerQ.indexOf(' in ') > -1) {
const key = lowerQ.substring(0, lowerQ.indexOf(' in '))
const obj = this.columnList.find(t => t.label.toLowerCase() === key.toLowerCase())
if (obj) {
return { key: obj.label + q.substring(lowerQ.indexOf(' in '), q.length), isKey: true }
} else {
return { key: '[' + key + ']', isKey: false }
}
} else if (lowerQ.indexOf('has(') > -1) {
const key = lowerQ.substring(0, 4)
if (key === 'has(') {
const label = lowerQ.substring(4, lowerQ.indexOf(','))
if (label) {
const obj = this.columnList.find(t => t.label.toLowerCase() === label.toLowerCase())
if (obj) {
return { key: 'has(' + obj.label + q.substring(lowerQ.indexOf(','), lowerQ.length), isKey: true }
} else {
return { key: '[' + key + ']', isKey: false }
}
} else {
return { key: 'in index 5', isKey: false }
}
} else {
return { key: 'in index 5', isKey: false }
} }
} else if (q && (q.indexOf('has(') > -1)) {
return {
key: q,
isKey: true
} }
} else { } else {
return { return {
@@ -1257,6 +1321,10 @@ export default class Parser {
}) })
return str return str
} else if (!result) { } else if (!result) {
// 此处为不能识别的字段不能当成app处理
if (str.indexOf('=') > -1 || str.toLowerCase().indexOf(' in ') > -1 || str.toLowerCase().indexOf(' like ') > -1 || str.toLowerCase().indexOf('has(') > -1) {
return str
}
const regex = /^["']|["']$/ const regex = /^["']|["']$/
// 去除两侧引号,如'1.1.1.1',避免校验时被当作app // 去除两侧引号,如'1.1.1.1',避免校验时被当作app
if (regex.test(str)) { if (regex.test(str)) {

View File

@@ -190,6 +190,7 @@
:format="dateFormat" :format="dateFormat"
prefix-icon="cn-icon cn-icon-shijian" prefix-icon="cn-icon cn-icon-shijian"
type="datetime" type="datetime"
@change="onChangeSchedulerStart"
placeholder=" " placeholder=" "
/> />
</div> </div>
@@ -206,6 +207,7 @@
:format="dateFormat" :format="dateFormat"
prefix-icon="cn-icon cn-icon-shijian" prefix-icon="cn-icon cn-icon-shijian"
type="datetime" type="datetime"
@change="onChangeSchedulerEnd"
placeholder=" " placeholder=" "
/> />
</div> </div>
@@ -242,7 +244,7 @@
placeholder=" " placeholder=" "
filterable filterable
:disabled="!!editObject.id" :disabled="!!editObject.id"
popper-class="right-box-select-dropdown right-box-select-report " popper-class="search-select right-box-select-dropdown right-box-select-report "
size="small" size="small"
> >
<template #prefix> <template #prefix>
@@ -276,7 +278,7 @@ import { storageKey, report } from '@/utils/constants'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import _ from 'lodash' import _ from 'lodash'
import axios from 'axios' import axios from 'axios'
import { dateFormat, getMillisecond } from '@/utils/date-util' import { dateFormat, getMillisecond, millTimestampDiffFromTz } from '@/utils/date-util'
import { ref, getCurrentInstance } from 'vue' import { ref, getCurrentInstance } from 'vue'
import i18n from '@/i18n' import i18n from '@/i18n'
export default { export default {
@@ -292,10 +294,12 @@ export default {
const startTime = ref('') const startTime = ref('')
const endTime = ref('') const endTime = ref('')
function endTimeChange (val) { function endTimeChange (val) {
endTime.value = val // endTime.value = val + millTimestampDiffFromTz()
endTime.value = getMillisecond(val) + millTimestampDiffFromTz()
} }
function startTimeChang (val) { function startTimeChang (val) {
startTime.value = val // startTime.value = val + millTimestampDiffFromTz()
startTime.value = getMillisecond(val) + millTimestampDiffFromTz()
} }
const endDisabledDate = (time) => { const endDisabledDate = (time) => {
if (time.getTime() > new Date()) { if (time.getTime() > new Date()) {
@@ -332,7 +336,7 @@ export default {
} }
const startTimeValidator = (rule, value, callback) => { const startTimeValidator = (rule, value, callback) => {
const form = proxy.$refs.reportForm const form = proxy.$refs.reportForm
if (form.model.config.endTime) { if (form.model && form.model.config && form.model.config.endTime) {
form.validateField('config.endTime', () => null) form.validateField('config.endTime', () => null)
} }
callback() callback()
@@ -352,9 +356,6 @@ export default {
categoryId: [ categoryId: [
{ required: true, message: i18n.global.t('validate.required'), trigger: 'change' } { required: true, message: i18n.global.t('validate.required'), trigger: 'change' }
], ],
schedulerStart: [
{ required: true, message: i18n.global.t('validate.required'), trigger: 'change' }
],
'config.startTime': [ 'config.startTime': [
{ required: true, message: i18n.global.t('validate.required'), trigger: 'change' }, { required: true, message: i18n.global.t('validate.required'), trigger: 'change' },
{ validator: startTimeValidator, trigger: 'change' } { validator: startTimeValidator, trigger: 'change' }
@@ -368,15 +369,53 @@ export default {
{ validator: paramValidator, message: i18n.global.t('validate.required'), trigger: 'blur' } { validator: paramValidator, message: i18n.global.t('validate.required'), trigger: 'blur' }
] ]
} }
const mySchedulerStart = ref('')
const mySchedulerEnd = ref('')
const onChangeSchedulerStart = (val) => {
mySchedulerStart.value = getMillisecond(val) + millTimestampDiffFromTz()
}
const onChangeSchedulerEnd = (val) => {
mySchedulerEnd.value = getMillisecond(val) + millTimestampDiffFromTz()
}
return { return {
endDisabledDate, endDisabledDate,
startDisabledDate, startDisabledDate,
startTimeChang, startTimeChang,
endTimeChange, endTimeChange,
rules rules,
startTime,
endTime,
mySchedulerStart,
mySchedulerEnd,
onChangeSchedulerStart,
onChangeSchedulerEnd
} }
}, },
data () { data () {
const schedulerStartTimeValidator = (rule, value, callback) => {
if (this.editObject.schedulerEnd) {
if (this.$refs.reportForm) {
this.$refs.reportForm.validateField('schedulerEnd')
}
}
callback()
}
const schedulerEndTimeValidator = (rule, value, callback) => {
if (value && this.editObject.schedulerStart && (getMillisecond(this.editObject.schedulerStart) >= getMillisecond(value))) {
callback(new Error(this.$t('config.user.timeVerification')))
} else {
callback()
}
}
this.rules.schedulerStart = [
{ required: true, message: i18n.global.t('validate.required'), trigger: 'change' },
{ validator: schedulerStartTimeValidator, trigger: 'change' }
]
this.rules.schedulerEnd = [
{ validator: schedulerEndTimeValidator, trigger: 'change' }
]
return { return {
url: api.reportTemp, url: api.reportTemp,
@@ -403,7 +442,9 @@ export default {
monthWeekdayCheckedAll: false, monthWeekdayCheckedAll: false,
monthWeekdayIsIndeterminate: false, monthWeekdayIsIndeterminate: false,
paramsOptions: [] paramsOptions: [],
newParamsOptions: [],
rangeNumber: 10
} }
}, },
watch: { watch: {
@@ -414,6 +455,7 @@ export default {
scheduleChecked (n) { scheduleChecked (n) {
this.editObject.config.isScheduler = n ? 1 : 0 this.editObject.config.isScheduler = n ? 1 : 0
this.cleanScheduleConfig() this.cleanScheduleConfig()
this.initDateCalendarPreIcon()
}, },
monthScheduleType (n) { monthScheduleType (n) {
this.cleanScheduleConfig() this.cleanScheduleConfig()
@@ -495,6 +537,14 @@ export default {
} }
} }
if (n.config) {
if (n.config.startTime) {
this.editObject.config.startTime = getMillisecond(n.config.startTime) - millTimestampDiffFromTz()
}
if (n.config.endTime) {
this.editObject.config.endTime = getMillisecond(n.config.endTime) - millTimestampDiffFromTz()
}
}
if (n.schedulerStart) { if (n.schedulerStart) {
this.editObject.schedulerStart = dateFormat(this.editObject.schedulerStart, this.dateFormat) this.editObject.schedulerStart = dateFormat(this.editObject.schedulerStart, this.dateFormat)
} }
@@ -521,10 +571,24 @@ export default {
} }
} }
}, },
mounted () {
this.initDateCalendarPreIcon()
},
methods: { methods: {
initDateCalendarPreIcon () {
this.$nextTick(() => {
const datePrefixIcon = document.getElementsByClassName('el-input__prefix-inner')
if (datePrefixIcon && datePrefixIcon.length > 0) {
Array.prototype.forEach.call(datePrefixIcon, function (element) {
element.innerHTML = '<i class="el-input__icon cn-icon cn-icon-shijian"></i>'
})
}
})
},
loadParamOptions () { loadParamOptions () {
if (_.isArray(this.editObject.categoryParams) && !_.isEmpty(this.editObject.categoryParams)) { if (_.isArray(this.editObject.categoryParams) && !_.isEmpty(this.editObject.categoryParams)) {
this.editObject.categoryParams.forEach(param => { this.editObject.categoryParams.forEach(param => {
// this.paramsOptions = _.cloneDeep(this.newParamsOptions)
if (!this.paramsOptions.some(p => p.key === param.key)) { if (!this.paramsOptions.some(p => p.key === param.key)) {
axios.get(api.dict, { params: { type: param.key, pageSize: -1 } }).then(response => { axios.get(api.dict, { params: { type: param.key, pageSize: -1 } }).then(response => {
if (response.status === 200) { if (response.status === 200) {
@@ -532,6 +596,7 @@ export default {
key: param.key, key: param.key,
options: response.data.data.list.map(d => d.value) options: response.data.data.list.map(d => d.value)
}) })
// this.newParamsOptions = this.paramsOptions
} }
}) })
} }
@@ -569,6 +634,7 @@ export default {
if (val === 'customize') { if (val === 'customize') {
this.scheduleChecked = false this.scheduleChecked = false
} }
this.initDateCalendarPreIcon()
}, },
scheduleTypeChange (val) { scheduleTypeChange (val) {
this.scheduleType = val this.scheduleType = val
@@ -584,10 +650,12 @@ export default {
let schedulerStart = '' let schedulerStart = ''
let schedulerEnd = '' let schedulerEnd = ''
if (this.editObject.config && this.editObject.config.startTime) { if (this.editObject.config && this.editObject.config.startTime) {
startTime = getMillisecond(this.editObject.config.startTime) // startTime = getMillisecond(this.editObject.config.startTime)
startTime = this.startTime ? this.startTime : this.object.config.startTime
} }
if (this.editObject.config && this.editObject.config.endTime) { if (this.editObject.config && this.editObject.config.endTime) {
endTime = getMillisecond(this.editObject.config.endTime) // endTime = getMillisecond(this.editObject.config.endTime)
endTime = this.endTime ? this.endTime : this.object.config.endTime
} }
if (this.editObject.config && this.editObject.config.schedulerConfig) { if (this.editObject.config && this.editObject.config.schedulerConfig) {
if (['day', 'week', 'month'].indexOf(this.editObject.config.schedulerConfig.type) > -1) { if (['day', 'week', 'month'].indexOf(this.editObject.config.schedulerConfig.type) > -1) {
@@ -597,10 +665,12 @@ export default {
} }
} }
if (this.editObject.schedulerStart) { if (this.editObject.schedulerStart) {
schedulerStart = getMillisecond(this.editObject.schedulerStart) // schedulerStart = getMillisecond(this.editObject.schedulerStart)
schedulerStart = this.mySchedulerStart ? this.mySchedulerStart : this.object.schedulerStart
} }
if (this.editObject.schedulerEnd) { if (this.editObject.schedulerEnd) {
schedulerEnd = getMillisecond(this.editObject.schedulerEnd) // schedulerEnd = getMillisecond(this.editObject.schedulerEnd)
schedulerEnd = this.mySchedulerEnd ? this.mySchedulerEnd : this.object.schedulerEnd
} }
const copyObject = _.cloneDeep(this.editObject) const copyObject = _.cloneDeep(this.editObject)
@@ -721,6 +791,36 @@ export default {
const checkedCount = val.length const checkedCount = val.length
this.monthWeekdayCheckedAll = checkedCount === this.weekdayList.length this.monthWeekdayCheckedAll = checkedCount === this.weekdayList.length
this.monthWeekdayIsIndeterminate = checkedCount > 0 && checkedCount < this.weekdayList.length this.monthWeekdayIsIndeterminate = checkedCount > 0 && checkedCount < this.weekdayList.length
},
/**
* params的option筛选方法组件自带的方法在paramsOptions的options长度超过1512后会保留部分值
* @param filterVal
*/
filterMethod (filterVal) {
const key = this.editObject.categoryParams[0].key
if (filterVal) {
const obj = this.newParamsOptions.find(d => d.key === key)
if (_.isString(filterVal) && obj) {
const filterArr = _.cloneDeep(obj.options).filter(d => d.toLowerCase().includes(filterVal.toLowerCase()))
const paramsOptionsObj = this.paramsOptions.find(d => d.key === key)
paramsOptionsObj.options = filterArr
} else if (_.isNumber(filterVal) && obj) {
const filterArr = _.cloneDeep(obj.options).filter(d => d.toLowerCase().includes(filterVal))
const paramsOptionsObj = this.paramsOptions.find(d => d.key === key)
paramsOptionsObj.options = filterArr
}
} else {
this.paramsOptions = _.cloneDeep(this.newParamsOptions)
this.rangeNumber = 10
}
},
loadMore () {
this.rangeNumber += 10
},
onVisibleChange (flag) {
if (!flag) {
this.rangeNumber = 0
}
} }
} }
} }

View File

@@ -37,19 +37,19 @@
</el-switch> </el-switch>
</template> </template>
<template v-else-if="item.prop === 'type'"> <template v-else-if="item.prop === 'type'">
<span class="type-tag">{{typeText(scope.row['id'])}}</span> <span class="type-tag" v-for="type in scope.row.type">{{type}}</span>
</template> </template>
<template v-else-if="item.prop === 'name'"> <template v-else-if="item.prop === 'name'">
<div class="plugin-name"> <div class="plugin-name">
<div class="icon-background"><img class="plugin-name-icon" :src="getIconUrl(scope.row['id'])"/></div> <div class="icon-background"><img class="plugin-name-icon" :src="scope.row['iconUrl']"/></div>
{{getName(scope.row['id'])}} {{scope.row['name']}}
</div> </div>
</template> </template>
<template v-else-if="item.prop === 'description'"> <template v-else-if="item.prop === 'description'">
<div class="two-line" :title="getDescription(scope.row['id'])">{{getDescription(scope.row['id'])}}</div> <div class="two-line" :title="$t(scope.row['desc'])">{{$t(scope.row['desc'])}}</div>
</template> </template>
<template v-else-if="item.prop === 'schedule'"> <template v-else-if="item.prop === 'schedule'">
<div class="two-line" >{{scheduleText(scope.row['id'])}}</div> <div class="two-line" >{{$t(scope.row['schedule'])}}</div>
</template> </template>
<span v-else>{{scope.row[item.prop] || '-'}}</span> <span v-else>{{scope.row[item.prop] || '-'}}</span>
</template> </template>
@@ -110,36 +110,6 @@ export default {
} }
}, },
computed: { computed: {
typeText () {
return function (id) {
const t = pluginBasicInfo.find(t => t.id === id)
return t ? t.type : 'Unknown Tag'
}
},
scheduleText () {
return function (id) {
const basicInfo = pluginBasicInfo.find(bi => bi.id === id)
return basicInfo ? this.$t(basicInfo.schedule) : ''
}
},
getIconUrl () {
return function (id) {
const basicInfo = pluginBasicInfo.find(bi => bi.id === id)
return basicInfo ? basicInfo.iconUrl : ''
}
},
getDescription () {
return function (id) {
const basicInfo = pluginBasicInfo.find(bi => bi.id === id)
return basicInfo ? this.$t(basicInfo.desc) : '-'
}
},
getName () {
return function (id) {
const basicInfo = pluginBasicInfo.find(bi => bi.id === id)
return basicInfo ? this.$t(basicInfo.name) : '-'
}
}
}, },
methods: { methods: {
statusChange (plugin) { statusChange (plugin) {

View File

@@ -179,6 +179,8 @@ export function handleComponent (code) {
return () => import('@/views/administration/OperationLog') return () => import('@/views/administration/OperationLog')
case 'appearance': case 'appearance':
return () => import('@/views/administration/Appearance') return () => import('@/views/administration/Appearance')
case 'license':
return () => import('@/views/administration/License')
case 'I18N': case 'I18N':
return () => import('@/views/administration/I18n') return () => import('@/views/administration/I18n')
case 'system': case 'system':

View File

@@ -15,6 +15,9 @@ export const api = {
logout: '/logout', logout: '/logout',
pin: 'sys/user/pin', pin: 'sys/user/pin',
appearance: '/sys/appearance', appearance: '/sys/appearance',
license: '/sys/license/detail',
licenseStatus: '/sys/license/status',
downloadLicenseC2v: '/sys/license/download',
permissions: '/sys/user/permissions', permissions: '/sys/user/permissions',
operationLog: '/sys/log', operationLog: '/sys/log',
login: '/sys/login', login: '/sys/login',

View File

@@ -1883,116 +1883,84 @@ export const performanceMetricMapping = {
export const pluginBasicInfo = [ export const pluginBasicInfo = [
{ {
id: 110, id: 109,
name: 'Psiphon3 VPN',
type: ['IP'],
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.psiphon3',
iconUrl: 'images/knowledge-base-logo/psiphon3-vpn.png'
},
{
id: 111,
name: 'HotSpot VPN', name: 'HotSpot VPN',
type: 'IP', type: ['IP'],
schedule: 'plugin.daily', schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.hotSpot', desc: 'knowledgeBase.desc.hotSpot',
iconUrl: 'images/knowledge-base-logo/hotspot-vpn.png' iconUrl: 'images/knowledge-base-logo/hotspot-vpn.png'
}, },
{ {
id: 111, id: 112,
name: 'IpVanish VPN', name: 'IpVanish VPN',
type: 'Domain', type: ['IP', 'Domain'],
schedule: 'plugin.hourly', schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.ipVanishDomain', desc: 'knowledgeBase.desc.ipVanishDomain',
iconUrl: 'images/knowledge-base-logo/ip-vanish.png' iconUrl: 'images/knowledge-base-logo/ip-vanish.png'
}, },
{
id: 112,
name: 'IpVanish VPN',
type: 'IP',
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.ipVanishIp',
iconUrl: 'images/knowledge-base-logo/ip-vanish.png'
},
{ {
id: 113, id: 113,
name: 'CyberGhost VPN',
type: 'Domain',
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.cyberGhostDomain',
iconUrl: 'images/knowledge-base-logo/cyber-ghost.png'
},
{
id: 114,
name: 'CyberGhost VPN',
type: 'IP',
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.cyberGhostIp',
iconUrl: 'images/knowledge-base-logo/cyber-ghost.png'
},
{
id: 115,
name: 'Gecko VPN',
type: 'IP',
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.geckoIp',
iconUrl: 'images/knowledge-base-logo/gecko.png'
},
{
id: 116,
name: 'Ivacy VPN', name: 'Ivacy VPN',
type: 'Domain', type: ['IP', 'Domain'],
schedule: 'plugin.hourly', schedule: 'plugin.daily',
desc: 'knowledgeBase.desc.ivacyDomain', desc: 'knowledgeBase.desc.ivacyDomain',
iconUrl: 'images/knowledge-base-logo/ivacy.png' iconUrl: 'images/knowledge-base-logo/ivacy.png'
}, },
{ {
id: 117, id: 114,
name: 'Ivacy VPN',
type: 'IP',
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.ivacyIp',
iconUrl: 'images/knowledge-base-logo/ivacy.png'
},
{
id: 118,
name: 'Turbo VPN',
type: 'IP',
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.turboIp',
iconUrl: 'images/knowledge-base-logo/turbo.png'
},
{
id: 119,
name: 'Vpnunlimited',
type: 'IP',
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.vpnunlimited',
iconUrl: 'images/knowledge-base-logo/vpnunlimited.png'
},
{
id: 120,
name: 'Windscribe VPN',
type: 'Domain',
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.windscribeDomain',
iconUrl: 'images/knowledge-base-logo/windscribe.png'
},
{
id: 121,
name: 'Windscribe VPN',
type: 'IP',
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.windscribeIp',
iconUrl: 'images/knowledge-base-logo/windscribe.png'
},
{
id: 122,
name: 'Proton VPN', name: 'Proton VPN',
type: 'IP', type: ['IP'],
schedule: 'plugin.hourly', schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.protonvpn', desc: 'knowledgeBase.desc.protonvpn',
iconUrl: 'images/knowledge-base-logo/protonvpn.png' iconUrl: 'images/knowledge-base-logo/protonvpn.png'
}, },
{ {
id: 109, id: 115,
name: 'Psiphon3 VPN', name: 'CyberGhost VPN',
type: 'IP', type: ['IP', 'Domain'],
schedule: 'plugin.always', schedule: 'plugin.daily',
desc: 'knowledgeBase.desc.psiphon3', desc: 'knowledgeBase.desc.cyberGhostDomain',
iconUrl: 'images/knowledge-base-logo/psiphon3-vpn.png' iconUrl: 'images/knowledge-base-logo/cyber-ghost.png'
},
{
id: 116,
name: 'Windscribe VPN',
type: ['IP', 'Domain'],
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.windscribeDomain',
iconUrl: 'images/knowledge-base-logo/windscribe.png'
},
{
id: 117,
name: 'Turbo VPN',
type: ['IP'],
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.turboIp',
iconUrl: 'images/knowledge-base-logo/turbo.png'
},
{
id: 118,
name: 'Gecko VPN',
type: ['IP'],
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.geckoIp',
iconUrl: 'images/knowledge-base-logo/gecko.png'
},
{
id: 119,
name: 'Vpnunlimited',
type: ['IP'],
schedule: 'plugin.hourly',
desc: 'knowledgeBase.desc.vpnunlimited',
iconUrl: 'images/knowledge-base-logo/vpnunlimited.png'
} }
] ]

View File

@@ -31,7 +31,7 @@ axios.interceptors.request.use(config => {
err => Promise.reject(err) err => Promise.reject(err)
) )
const accountErrorCode = [518003, 518004, 518005, 518006, 518007, 518008] // 账号锁定等 const accountErrorCode = [518003, 518004, 518005, 518006, 518007, 518008] // 账号锁定等
const licenceErrorCode = [711001] const licenceErrorCode = [715001]
// 若get请求的url中带问号则将url上的参数截取改为对象形式传参 // 若get请求的url中带问号则将url上的参数截取改为对象形式传参
axios.interceptors.request.use( axios.interceptors.request.use(

View File

@@ -0,0 +1,159 @@
<template>
<div class="license" :class="from">
<div class="license-form">
<el-form ref="licenseForm" :model="licenseObject" label-position="left" label-width="134px" size="small">
<el-form-item :label="`${$t('license.type')}`" prop="type">
{{licenseObject.type}}
</el-form-item>
<el-form-item :label="`${$t('license.organization')}`" prop="organization">
<div class="">{{licenseObject.organization}}</div>
</el-form-item>
<el-form-item :label="`${$t('license.supportId')}`" prop="supportID">
<div class="">{{licenseObject.supportID}}</div>
</el-form-item>
<el-form-item :label="`${$t('license.dateIssued')}`" prop="dateIssued">
<div class="">{{licenseObject.dateIssued}}</div>
</el-form-item>
<el-form-item :label="`${$t('license.dateExpires')}`" prop="dateExpires">
<div class="">{{licenseObject.dateExpires}}</div>
</el-form-item>
<el-form-item :label="`${$t('license.licenseFile')}`" >
<div class="license-file">
<button style="position: relative;" class="license__btn margin-r-20" @click.prevent="downloadFile">
<i class="cn-icon-download1 cn-icon margin-r-6"></i><span>{{$t('license.download')}}</span>
</button>
<el-upload :action="`${baseUrl}sys/license/upload`"
ref="licenseUpload"
id="licenseUpload"
:headers="uploadHeaders"
:multiple="false"
:show-file-list="false"
:accept="fileTypeLimit"
:file-list="fileList"
:auto-upload="false"
:on-change="fileChange"
:on-success="uploadSuccess"
:on-error="uploadError">
<button style="position: relative;" class="license__btn" @click.prevent="">
<i class="cn-icon-upload1 cn-icon margin-r-6"></i><span>{{$t('license.upload')}}</span>
</button>
</el-upload>
</div>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import { api } from '@/utils/api'
import { storageKey } from '@/utils/constants'
import axios from 'axios'
import { ref } from 'vue'
import { dateFormat } from '@/utils/date-util'
export default {
name: 'License',
data () {
return {
url: api.license,
downloadC2vUrl: api.downloadLicenseC2v,
licenseObject: { // 对象
type: '',
organization: '',
supportID: '',
dateIssued: '',
dateExpires: ''
}
}
},
mounted () {
this.initData()
},
methods: {
initData () {
axios.get(this.url, { pageSize: -1 }).then(response => {
if (response.status === 200) {
this.licenseObject = response.data.data.license
this.licenseObject.dateExpires = dateFormat(new Date(this.licenseObject.hasp.feature.license.exp_date * 1000))
this.licenseObject.dateIssued = dateFormat(new Date(this.licenseObject.hasp.production_date * 1000))
}
}).catch(e => {
console.error(e)
this.$message.error(this.errorMsgHandler(e))
})
},
fileChange (file, fileList) {
if (file.status !== 'ready') return
if (!_.endsWith(file.name, '.xml')) {
this.fileList = []
this.$message.error(this.$t('validate.fileTypeLimit', { types: this.fileTypeLimit }))
} else {
this.fileList = fileList.slice(-1)
this.$refs.licenseUpload.submit()
}
},
uploadSuccess (response) {
this.initData()
this.$message.success(this.$t('tip.success'))
},
uploadError (error) {
let errorMsg
if (error.message) {
errorMsg = JSON.parse(error.message).message
} else {
errorMsg = 'error'
}
this.$message.error(this.$t('tip.uploadFailed', { msg: errorMsg }))
},
downloadFile () {
axios.get(this.downloadC2vUrl, { responseType: 'blob' }).then(res => {
let fileName = ''
if(res.headers['content-disposition']) {
fileName = res.headers['content-disposition'].split(';')[1].split('filename=')[1]
}
if (window.navigator.msSaveOrOpenBlob) {
// 兼容ie11
const blobObject = new Blob([res.data])
window.navigator.msSaveOrOpenBlob(blobObject, fileName)
} else {
const url = URL.createObjectURL(new Blob([res.data]))
const a = document.createElement('a')
document.body.appendChild(a) // 此处增加了将创建的添加到body当中
a.href = url
a.download = fileName
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)
})
}
},
setup () {
return {
baseUrl: BASE_CONFIG.baseUrl,
apiVersion: BASE_CONFIG.apiVersion,
uploadHeaders: {
'Cn-Authorization': localStorage.getItem(storageKey.token)
},
fileTypeLimit: '.xml',
fileList: ref([])
}
}
}
</script>

View File

@@ -239,13 +239,7 @@ export default {
data.forEach(item => { data.forEach(item => {
item.totalBitsRate = item.outBitsRate + item.inBitsRate item.totalBitsRate = item.outBitsRate + item.inBitsRate
linkConfig.filter(info => info.interfaceName === item.interfaceName).forEach(info => { linkConfig.filter(info => info.interfaceName === item.interfaceName).forEach(info => {
if (info.direction === 0) {
item.outLinkId = info.linkId
} else if (info.direction === 1) {
item.inLinkId = info.linkId
} else if (info.direction === 2) {
item.linkId = info.linkId item.linkId = info.linkId
}
}) })
}) })
@@ -389,7 +383,7 @@ export default {
return width return width
}, },
drillLinkId (item) { drillLinkId (item) {
const queryCondition = `out_link_id = ${item.outLinkId} or in_link_id = ${item.inLinkId}` const queryCondition = `out_link_id = ${item.linkId} or in_link_id = ${item.linkId}`
beforeRouterPush() beforeRouterPush()
this.$router.push({ this.$router.push({
query: { query: {

View File

@@ -168,7 +168,7 @@ export default {
if (tab === 0) { if (tab === 0) {
result.forEach(t => { result.forEach(t => {
this.cnLinkInfo.forEach(e => { this.cnLinkInfo.forEach(e => {
if (parseInt(t.commonInLinkId) === e.linkId) { if (parseInt(t.inLinkId) === e.linkId) {
t.linkId = e.interfaceName t.linkId = e.interfaceName
t.linkDirection = e.peerCity t.linkDirection = e.peerCity
t.bandwidth = e.bandwidth t.bandwidth = e.bandwidth
@@ -182,7 +182,7 @@ export default {
} else { } else {
result.forEach(t => { result.forEach(t => {
this.cnLinkInfo.forEach(e => { this.cnLinkInfo.forEach(e => {
if (parseInt(t.commonOutLinkId) === e.linkId) { if (parseInt(t.outLinkId) === e.linkId) {
t.linkId = e.interfaceName t.linkId = e.interfaceName
t.bandwidth = e.bandwidth t.bandwidth = e.bandwidth
t.linkDirection = e.peerCity t.linkDirection = e.peerCity

View File

@@ -4,7 +4,7 @@
<div class="explorer-top-tools explorer-detection-top-tools"> <div class="explorer-top-tools explorer-detection-top-tools">
<div class="explorer-top-tools-title">{{$t('overall.detections')}}</div> <div class="explorer-top-tools-title">{{$t('overall.detections')}}</div>
<div style="display: flex"> <div style="display: flex">
<div class="explorer-top-tools-block" @click="jumpNewDetetion" v-if="hasPermission('detectionPolicy')"> <div class="explorer-top-tools-block" @click="jumpNewDetetion" v-if="false">
<i class="cn-icon cn-icon-configure-policies detection-icon-setting"></i> <i class="cn-icon cn-icon-configure-policies detection-icon-setting"></i>
<span>{{$t('config.detections.configurePolicies')}}</span> <span>{{$t('config.detections.configurePolicies')}}</span>
</div> </div>

View File

@@ -273,6 +273,7 @@ export default {
for (let i = 0; i < response.data.data.list.length; i++) { for (let i = 0; i < response.data.data.list.length; i++) {
response.data.data.list[i].status = response.data.data.list[i].status + '' response.data.data.list[i].status = response.data.data.list[i].status + ''
} }
this.tableData = []
this.$nextTick(() => { this.$nextTick(() => {
this.tableData = response.data.data.list.map(item => { this.tableData = response.data.data.list.map(item => {
return { return {
@@ -316,11 +317,18 @@ export default {
type: 'warning' type: 'warning'
}).catch(() => {}) }).catch(() => {})
} else { } else {
const curRecord = this.batchDeleteObjs[0] axios.get(`${api.reportTemp}/${this.batchDeleteObjs[0].id}`).then(response => {
if (response.status === 200) {
const curRecord = response.data.data
if (curRecord.config) {
curRecord.config = JSON.parse(curRecord.config)
}
this.initConfig(curRecord) this.initConfig(curRecord)
this.object = curRecord this.object = curRecord
this.rightBox.show = true this.rightBox.show = true
} }
})
}
}, },
initConfig (u) { initConfig (u) {
if (!u.config) { if (!u.config) {

View File

@@ -87,7 +87,7 @@ export default {
response.data.data.list[i].triggerStatus = response.data.data.list[i].triggerStatus + '' response.data.data.list[i].triggerStatus = response.data.data.list[i].triggerStatus + ''
const basicInfo = pluginBasicInfo.find(plugin => plugin.id === response.data.data.list[i].id) const basicInfo = pluginBasicInfo.find(plugin => plugin.id === response.data.data.list[i].id)
if (basicInfo) { if (basicInfo) {
filterDataList.push(response.data.data.list[i]) filterDataList.push(Object.assign({},basicInfo,response.data.data.list[i]))
} }
} }
this.tableData = filterDataList this.tableData = filterDataList