feat:新增api key 、license 重写link 、notify 面包屑bug修复
This commit is contained in:
@@ -291,6 +291,13 @@ li{
|
|||||||
min-width: 60px;
|
min-width: 60px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
.nz-btn.nz-btn-size-mini-new{
|
||||||
|
height: 22px;
|
||||||
|
line-height: 22px;
|
||||||
|
text-align: center;
|
||||||
|
min-width: 40px;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
.nz-btn.nz-btn-style-normal-new { /* 新版橙色按钮 */
|
.nz-btn.nz-btn-style-normal-new { /* 新版橙色按钮 */
|
||||||
background: $btn-normal-background-color-new;
|
background: $btn-normal-background-color-new;
|
||||||
color: $btn-normal-txt-color-new;
|
color: $btn-normal-txt-color-new;
|
||||||
|
|||||||
@@ -180,5 +180,8 @@ export const fromRoute = {
|
|||||||
endpointQuery: 'endpointQuery',
|
endpointQuery: 'endpointQuery',
|
||||||
terminalLog: 'terminalLog',
|
terminalLog: 'terminalLog',
|
||||||
operationLog: 'operationLog',
|
operationLog: 'operationLog',
|
||||||
menus: 'menus'
|
menus: 'menus',
|
||||||
|
notify: 'notify',
|
||||||
|
link: 'link',
|
||||||
|
apiKey: 'apiKey'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -946,7 +946,8 @@ const cn = {
|
|||||||
update: '更新',
|
update: '更新',
|
||||||
del: '删除',
|
del: '删除',
|
||||||
nameMaxLength: '长度应小于64',
|
nameMaxLength: '长度应小于64',
|
||||||
uriRequired: '请填写正确的网址'
|
uriRequired: '请填写正确的网址',
|
||||||
|
create: '创建人'
|
||||||
},
|
},
|
||||||
notification: {
|
notification: {
|
||||||
notification: 'Notification',
|
notification: 'Notification',
|
||||||
@@ -958,7 +959,10 @@ const cn = {
|
|||||||
del: '删除',
|
del: '删除',
|
||||||
nameMaxLength: '长度应小于64',
|
nameMaxLength: '长度应小于64',
|
||||||
uriRequired: '必填项',
|
uriRequired: '必填项',
|
||||||
filePathReg: '请输入正确的文件路径'
|
filePathReg: '请输入正确的文件路径',
|
||||||
|
create: '新建通知方式',
|
||||||
|
invalid: '停用',
|
||||||
|
valid: '可用'
|
||||||
},
|
},
|
||||||
reset: {
|
reset: {
|
||||||
reset: '重置',
|
reset: '重置',
|
||||||
@@ -971,6 +975,13 @@ const cn = {
|
|||||||
promptTitle: '确认密码',
|
promptTitle: '确认密码',
|
||||||
yes: '是',
|
yes: '是',
|
||||||
no: '否'
|
no: '否'
|
||||||
|
},
|
||||||
|
apiKey: {
|
||||||
|
apiKey: 'API key',
|
||||||
|
role: '角色',
|
||||||
|
create: '创建人',
|
||||||
|
creatAt: '创建时间',
|
||||||
|
expireAt: '过期时间'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
assetType: {
|
assetType: {
|
||||||
|
|||||||
@@ -173,7 +173,8 @@ const en = {
|
|||||||
login: {
|
login: {
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
password: 'Password',
|
password: 'Password',
|
||||||
login: 'Login'
|
login: 'Login',
|
||||||
|
upload: 'Upload license'
|
||||||
},
|
},
|
||||||
dashboard: {
|
dashboard: {
|
||||||
title: 'Dashboard',
|
title: 'Dashboard',
|
||||||
@@ -898,7 +899,7 @@ const en = {
|
|||||||
second: 'second',
|
second: 'second',
|
||||||
day: 'day',
|
day: 'day',
|
||||||
maxSeries: 'Query max series',
|
maxSeries: 'Query max series',
|
||||||
unsaved: 'Unsaved tip',
|
unsaved: 'Unsaved prompt',
|
||||||
mapConfig: 'Map center',
|
mapConfig: 'Map center',
|
||||||
mapTitle: 'Configurate map',
|
mapTitle: 'Configurate map',
|
||||||
lat: 'latitude',
|
lat: 'latitude',
|
||||||
@@ -950,19 +951,26 @@ const en = {
|
|||||||
update: 'Update',
|
update: 'Update',
|
||||||
del: 'Delete',
|
del: 'Delete',
|
||||||
nameMaxLength: 'The length should be less than 64',
|
nameMaxLength: 'The length should be less than 64',
|
||||||
uriRequired: 'Please fill in the correct url'
|
uriRequired: 'Please fill in the correct url',
|
||||||
|
create: 'Creator'
|
||||||
},
|
},
|
||||||
notification: {
|
notification: {
|
||||||
notification: 'Notification',
|
notification: 'Notification',
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
filePath: 'File path',
|
filePath: 'File path',
|
||||||
operation: 'Operation',
|
operation: 'Operation',
|
||||||
|
account: 'Account',
|
||||||
|
state: 'State',
|
||||||
|
buildIn: 'Build in',
|
||||||
add: 'Add',
|
add: 'Add',
|
||||||
update: 'Update',
|
update: 'Update',
|
||||||
del: 'Delete',
|
del: 'Delete',
|
||||||
nameMaxLength: 'The length should be less than 64',
|
nameMaxLength: 'The length should be less than 64',
|
||||||
uriRequired: 'Required',
|
uriRequired: 'Required',
|
||||||
filePathReg: 'Please enter the correct file path'
|
filePathReg: 'Please enter the correct file path',
|
||||||
|
create: 'Create notification',
|
||||||
|
invalid: 'Invalid',
|
||||||
|
valid: 'Valid'
|
||||||
},
|
},
|
||||||
reset: {
|
reset: {
|
||||||
reset: 'Reset',
|
reset: 'Reset',
|
||||||
@@ -975,6 +983,13 @@ const en = {
|
|||||||
promptTitle: 'Confirm',
|
promptTitle: 'Confirm',
|
||||||
yes: 'Yes',
|
yes: 'Yes',
|
||||||
no: 'No'
|
no: 'No'
|
||||||
|
},
|
||||||
|
apiKey: {
|
||||||
|
apiKey: 'API key',
|
||||||
|
role: 'Role',
|
||||||
|
create: 'Creator',
|
||||||
|
creatAt: 'Create at',
|
||||||
|
expireAt: 'Expire at'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
assetType: {
|
assetType: {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<input v-model="loginData.pin" type="password" name="password" autocomplete="on" :placeholder="$t('login.password')"></input>
|
<input v-model="loginData.pin" type="password" name="password" autocomplete="on" :placeholder="$t('login.password')"></input>
|
||||||
</div>
|
</div>
|
||||||
<div class="login-foot">
|
<div class="login-foot">
|
||||||
<button @click="login" class="login-btn" id="login" v-loading="loading">{{$t("login.login")}}</button>
|
<button @click="login" class="login-btn" id="login" v-loading="loading" :class="{'nz-btn-disabled btn-disabled-cursor-not-allowed':!license.valid}">{{$t("login.login")}}</button>
|
||||||
<div class="login-foot-lang" @click.stop="langListShow = !langListShow">
|
<div class="login-foot-lang" @click.stop="langListShow = !langListShow">
|
||||||
<i v-if="lang == 'en'" class="nz-icon nz-icon-lang-en"></i>
|
<i v-if="lang == 'en'" class="nz-icon nz-icon-lang-en"></i>
|
||||||
<i v-else-if="lang == 'cn'" class="nz-icon nz-icon-lang-zh"></i>
|
<i v-else-if="lang == 'cn'" class="nz-icon nz-icon-lang-zh"></i>
|
||||||
@@ -25,6 +25,22 @@
|
|||||||
<i v-if="lang != 'cn'" @click="changeLang('cn')" class="nz-icon nz-icon-lang-zh"></i>
|
<i v-if="lang != 'cn'" @click="changeLang('cn')" class="nz-icon nz-icon-lang-zh"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="login-license">
|
||||||
|
<div class="license-warn" v-if="license.warnInfo">{{license.warnInfo}}</div>
|
||||||
|
<div class="license-info" v-if="!license.valid">INSTALLATION ID:{{license.token}}</div>
|
||||||
|
<div class="license-upload" v-if="!license.valid">
|
||||||
|
<el-upload
|
||||||
|
ref="upload"
|
||||||
|
accept=".xml"
|
||||||
|
action=""
|
||||||
|
:file-list="uploadFileList"
|
||||||
|
:auto-upload="false"
|
||||||
|
:on-change="handleChange"
|
||||||
|
>
|
||||||
|
<button type="button" class="login-btn" ><span style="margin-right: 5px"><i class="nz-icon nz-icon-upload"></i></span>{{$t('login.upload')}}</button>
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="login-foot-buildOn">
|
<div class="login-foot-buildOn">
|
||||||
<span><a target="_blank" rel="noopener noreferrer" href='https://prometheus.io'>Build on Prometheus</a></span>
|
<span><a target="_blank" rel="noopener noreferrer" href='https://prometheus.io'>Build on Prometheus</a></span>
|
||||||
@@ -43,6 +59,13 @@ export default {
|
|||||||
pin: '',
|
pin: '',
|
||||||
remember: false
|
remember: false
|
||||||
},
|
},
|
||||||
|
license: {
|
||||||
|
warnInfo: '',
|
||||||
|
token: '',
|
||||||
|
valid: false
|
||||||
|
},
|
||||||
|
uploadFileList: [],
|
||||||
|
uploadFile: { file: '', path: '', uuid: '' },
|
||||||
loading: false,
|
loading: false,
|
||||||
lang: localStorage.getItem('nz-language') ? localStorage.getItem('nz-language') : 'en', // en/cn
|
lang: localStorage.getItem('nz-language') ? localStorage.getItem('nz-language') : 'en', // en/cn
|
||||||
langListShow: false
|
langListShow: false
|
||||||
@@ -54,7 +77,7 @@ export default {
|
|||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.validateLogin() && (this.$route.path == '/' || this.$route.path == '/login')) {
|
if (this.license.valid && this.validateLogin() && (this.$route.path == '/' || this.$route.path == '/login')) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.$post('sys/login', this.loginData).then(res => {
|
this.$post('sys/login', this.loginData).then(res => {
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
@@ -85,6 +108,36 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
licenseStat: function () {
|
||||||
|
this.$get('/sys/license/state').then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.license.warnInfo = ''
|
||||||
|
this.license.valid = true
|
||||||
|
} else {
|
||||||
|
this.license.valid = false
|
||||||
|
this.license.warnInfo = response.msg
|
||||||
|
}
|
||||||
|
this.license.token = response.token
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleChange: function (file, fileList) {
|
||||||
|
if (fileList.length > 0) {
|
||||||
|
this.uploadFileList = [fileList[fileList.length - 1]]
|
||||||
|
}
|
||||||
|
this.uploadFile.file = this.uploadFileList[0]
|
||||||
|
this.upload()
|
||||||
|
},
|
||||||
|
upload () {
|
||||||
|
const form = new FormData()
|
||||||
|
form.append('file', this.uploadFile.file.raw)
|
||||||
|
this.$post('/sys/license/upload', form, { 'Content-Type': 'multipart/form-data' }).then(res => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
this.licenseStat()
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -105,6 +158,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.getElementById('usernameInput').focus()
|
document.getElementById('usernameInput').focus()
|
||||||
|
this.licenseStat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -247,4 +301,31 @@ export default {
|
|||||||
right: 0;
|
right: 0;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
|
.login-license{
|
||||||
|
margin-top: 40px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 30px;
|
||||||
|
.license-warn{
|
||||||
|
color: #EF7458;
|
||||||
|
}
|
||||||
|
.license-info{
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.login-btn{
|
||||||
|
height: 30px;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.login-btn.nz-btn-disabled{
|
||||||
|
background-image: none;
|
||||||
|
color: #e5e5e5;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-color: #e5e5e5 ;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.license-upload .el-upload-list{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -57,7 +57,12 @@ export default {
|
|||||||
selectionChange (objs) {
|
selectionChange (objs) {
|
||||||
this.batchDeleteObjs = objs
|
this.batchDeleteObjs = objs
|
||||||
},
|
},
|
||||||
getTableData () {
|
getTableData (params) {
|
||||||
|
if (params && Object.keys(params).length > 0) {
|
||||||
|
for (const key in params) {
|
||||||
|
this.$set(this.searchLabel, key, params[key])
|
||||||
|
}
|
||||||
|
}
|
||||||
this.$set(this.searchLabel, 'pageNo', this.pageObj.pageNo)
|
this.$set(this.searchLabel, 'pageNo', this.pageObj.pageNo)
|
||||||
this.$set(this.searchLabel, 'pageSize', this.pageObj.pageSize)
|
this.$set(this.searchLabel, 'pageSize', this.pageObj.pageSize)
|
||||||
this.tools.loading = true
|
this.tools.loading = true
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: '100%'
|
default: '100%'
|
||||||
},
|
},
|
||||||
url: {
|
api: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
tableId: {
|
||||||
type: String
|
type: String
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<search-input ref="searchInput" :inTransform="bottomBox.inTransform" :searchMsg="searchMsg" @search="search"></search-input>
|
<search-input ref="searchInput" :inTransform="bottomBox.inTransform" :searchMsg="searchMsg" @search="search"></search-input>
|
||||||
</div>
|
</div>
|
||||||
<slot name="top-tool-right"></slot>
|
<slot name="top-tool-right"></slot>
|
||||||
<button v-if="layout.indexOf('elementSet') > -1" id="account-column-setting" class="top-tool-btn"
|
<button v-if="layout.indexOf('elementSet') > -1" class="top-tool-btn table-column-setting"
|
||||||
type="button" @click="tools.showCustomTableTitle = true">
|
type="button" @click="tools.showCustomTableTitle = true">
|
||||||
<i class="nz-icon-gear nz-icon"></i>
|
<i class="nz-icon-gear nz-icon"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -492,6 +492,7 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
if (getBreadCrumb(list[i].children, crumb)) {
|
if (getBreadCrumb(list[i].children, crumb)) {
|
||||||
crumb.unshift(list[i])
|
crumb.unshift(list[i])
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
route: {
|
$routePath: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler (n, o) {
|
handler (n, o) {
|
||||||
if (n.indexOf('mib') != -1 && this.$route.params.tab) {
|
if (n.indexOf('mib') != -1 && this.$route.params.tab) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="system">
|
<div class="system">
|
||||||
<el-tabs type="border-card" @tab-click="selectTab" v-model="activeTab" class="system-tabs" >
|
<el-tabs type="border-card" @tab-click="selectTab" v-model="activeTab" class="system-tabs" :class="{'full-table':activeTab == 'notification'||activeTab == 'link'||activeTab == 'apiKey'}">
|
||||||
<el-tab-pane :label="$t('config.system.basic.basic')" name="basic">
|
<el-tab-pane :label="$t('config.system.basic.basic')" name="basic">
|
||||||
<div class="system-config-form basicForm">
|
<div class="system-config-form basicForm">
|
||||||
<el-form :model="basic" label-width="180px" size="small" ref="basicForm" :rules="basic.asset_ping_switch == 'on'?basicRules:basicRules2" :validate-on-rule-change="false">
|
<el-form :model="basic" label-width="180px" size="small" ref="basicForm" :rules="basic.asset_ping_switch == 'on'?basicRules:basicRules2" :validate-on-rule-change="false">
|
||||||
@@ -156,172 +156,14 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('config.system.notification.notification')" name="notification"><!--$t('config.system.reset.reset')-->
|
<el-tab-pane :label="$t('config.system.notification.notification')" name="notification" style="height: 100%;"><!--$t('config.system.reset.reset')-->
|
||||||
<div class="linkBox notificationMessage">
|
<notify-method v-if="activeTab === 'notification'"></notify-method>
|
||||||
<i class="nz-icon nz-icon-info-normal"></i>
|
|
||||||
<div style="margin-left: 15px">
|
|
||||||
<div>. Please make sure the script file exists and has executable permissions</div>
|
|
||||||
<div>. The script file receives two parameters:</div>
|
|
||||||
<div> ① Notification account</div>
|
|
||||||
<div> ② Alert message(json)
|
|
||||||
<el-tooltip placement="right" effect="light">
|
|
||||||
<pre slot="content" style="word-break: break-all">
|
|
||||||
{
|
|
||||||
"assetId": 1,
|
|
||||||
"dcId": 1,
|
|
||||||
"description": "The endpoint is down, the detailed information
|
|
||||||
Asset : 192.168.40.161, Project: system, Module: node_exporter,
|
|
||||||
Data center: center, EndpointId: 1",
|
|
||||||
"endAt": 1606240496000,
|
|
||||||
"endpointId": 1,
|
|
||||||
"hashKey": "34a17b57f289592a94ff65ee0864094b",
|
|
||||||
"id": 1,
|
|
||||||
"labels": "{\"severity\":\"P2\",\"endpoint\":\"1\",\"alertname\":\"1\",
|
|
||||||
\"module\":\"node_exporter\",\"project\":\"system\",\"datacenter\":
|
|
||||||
\"center\",\"asset\":\"192.168.40.161\"}",
|
|
||||||
"moduleId": 1,
|
|
||||||
"projectId": 1,
|
|
||||||
"ruleId": 1,
|
|
||||||
"severity": "P2",
|
|
||||||
"startAt": 1606009916000,
|
|
||||||
"state": 2,
|
|
||||||
"summary": "The endpoint is down, endpointId is 1"
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
<span class="more">...</span>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="linkBox" >
|
|
||||||
<div class="linkTitle">
|
|
||||||
<span class="linkTitleHandle"></span>
|
|
||||||
<div class="linkTitleName">{{$t('config.system.notification.name')}}</div>
|
|
||||||
<div class="linkTitleUrl">{{$t('config.system.notification.filePath')}}</div>
|
|
||||||
<div class="linkTitleBtn">{{$t('config.system.notification.operation')}}</div>
|
|
||||||
</div>
|
|
||||||
<!--linkAdd-->
|
|
||||||
<div class="linkContent linkAddBox">
|
|
||||||
<span class="linkTitleHandle"></span>
|
|
||||||
<el-form :inline="true" :model="notificationTemp" :rules="notificationRules" :validate-on-rule-change="false" class="reset-form" label-width="160px" ref="notificationTempForm" size="small">
|
|
||||||
<el-form-item prop="name">
|
|
||||||
<el-input v-model="notificationTemp.name" class="linkName" id="system-notification-name"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="filePath">
|
|
||||||
<el-input v-model="notificationTemp.filePath" class="linkUrl" id="system-notification-filepath"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="btn">
|
|
||||||
<i @click="notificationAdd" id="system-notification-add" class="nz-icon-create-square nz-icon" v-has="'system_notification_add'"></i>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
<!--notificationEdit-->
|
|
||||||
<div class="scrollBox">
|
|
||||||
<draggable v-model="notification"
|
|
||||||
:options="{group:'people',animation:150,ghostClass:'sortable-ghost',chosenClass:'chosenClass',scroll:true,scrollSensitivity:200}"
|
|
||||||
@change="change"
|
|
||||||
@start="start"
|
|
||||||
@end="notificationEnd"
|
|
||||||
:move="move"
|
|
||||||
handle=".handle"
|
|
||||||
>
|
|
||||||
<div v-for="(item,index) in notification" :id="'notificationDiv'+item.id" :key="index" class="linkContent">
|
|
||||||
<i class="nz-icon nz-icon-sort4 handle" style="display:none"></i>
|
|
||||||
<span style="display: inline-block;width: 26px"></span>
|
|
||||||
<el-form v-if="item.isEdit" :key="index" :ref="'notificationForm'+item.id" :inline="true" :model="notification[index]" :rules="notificationRules" :validate-on-rule-change="false" class="reset-form" label-width="180px" size="small" >
|
|
||||||
<el-form-item prop="name" class="linkName">
|
|
||||||
<el-input v-model="item.name" width="140px" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="filePath" class="linkUrl">
|
|
||||||
<el-input v-model="item.filePath" width="460px" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="btn">
|
|
||||||
<button @click="notificationUpdate(item)" class="linkBtn nz-btn nz-btn-size-small-new nz-btn-style-normal-new" type="button" v-has="'system_notification_save'">Update</button>
|
|
||||||
<button type="button" class="linkBtn nz-btn nz-btn-size-small-new nz-btn-style-light-new" @click="notificationCancel(item)">Cancel</button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div class="linkFormContent" v-else>
|
|
||||||
<div class="linkTitleName" :title="item.name">{{item.name}}</div>
|
|
||||||
<div class="linkTitleUrl">
|
|
||||||
<!--<span class="linkTitleUrlContent" @click="openUrl(item)" @dblclick.stop="linkEdit(item)">-->
|
|
||||||
<!--<el-tooltip class="item" effect="dark" :content="item.url" placement="top" popper-class="linkUrlTip">-->
|
|
||||||
<span>{{item.filePath}}</span>
|
|
||||||
<!--</el-tooltip>-->
|
|
||||||
<!--</span>-->
|
|
||||||
</div>
|
|
||||||
<div class="linkFormBtn">
|
|
||||||
<i @click.stop="notificationEdit(item)" class="nz-icon nz-icon-edit" v-has="'system_notification_toEdit'"></i>
|
|
||||||
<i @click="notificationDel(item)" class="nz-icon nz-icon-delete" v-has="'system_notification_delete'"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</draggable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('config.system.link.link')" name="link"><!--$t('config.system.reset.reset')-->
|
<el-tab-pane :label="$t('config.system.link.link')" name="link" style="height: 100%;"><!--$t('config.system.reset.reset')-->
|
||||||
<div class="linkBox" >
|
<link-tab v-if="activeTab === 'link'"></link-tab>
|
||||||
<div class="linkTitle">
|
</el-tab-pane>
|
||||||
<span class="linkTitleHandle"></span>
|
<el-tab-pane :label="$t('config.system.apiKey.apiKey')" name="apiKey" style="height: 100%;"><!--$t('config.system.reset.reset')-->
|
||||||
<div class="linkTitleName">{{$t('config.system.link.name')}}</div>
|
<api-key-tab v-if="activeTab === 'apiKey'"></api-key-tab>
|
||||||
<div class="linkTitleUrl">{{$t('config.system.link.url')}}</div>
|
|
||||||
<div class="linkTitleBtn">{{$t('config.system.link.operation')}}</div>
|
|
||||||
</div>
|
|
||||||
<!--linkAdd-->
|
|
||||||
<div class="linkContent linkAddBox">
|
|
||||||
<span class="linkTitleHandle"></span>
|
|
||||||
<el-form :inline="true" :model="linkTemp" label-width="180px" size="small" ref="linkTempForm" :rules="linkRules" :validate-on-rule-change="false" class="reset-form">
|
|
||||||
<el-form-item prop="name">
|
|
||||||
<el-input v-model="linkTemp.name" class="linkName" id="system-link-name"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="url">
|
|
||||||
<el-input v-model="linkTemp.url" class="linkUrl" id="system-link-url"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="btn">
|
|
||||||
<i @click="linkAdd" class="nz-icon-create-square nz-icon" v-has="'system_link_add'" id="system-link-add"></i>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
<!--linkEdit-->
|
|
||||||
<div class="scrollBox">
|
|
||||||
<draggable v-model="link"
|
|
||||||
:options="{group:'people',animation:150,ghostClass:'sortable-ghost',chosenClass:'chosenClass',scroll:true,scrollSensitivity:200}"
|
|
||||||
@change="change"
|
|
||||||
@start="start"
|
|
||||||
@end="end"
|
|
||||||
:move="move"
|
|
||||||
handle=".handle"
|
|
||||||
>
|
|
||||||
<div v-for="(item,index) in link" :id="'linkDiv'+item.id" :key="index" class="linkContent">
|
|
||||||
<i class="nz-icon nz-icon-sort4 handle"></i>
|
|
||||||
<el-form v-if="item.isEdit" :key="index" :ref="'linkForm'+item.id" :inline="true" :model="link[index]" :rules="linkRules" :validate-on-rule-change="false" class="reset-form" label-width="180px" size="small" >
|
|
||||||
<el-form-item prop="name" class="linkName">
|
|
||||||
<el-input v-model="item.name" width="140px" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="url" class="linkUrl">
|
|
||||||
<el-input v-model="item.url" width="460px" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="btn">
|
|
||||||
<button @click="linkUpdate(item)" class="linkBtn nz-btn nz-btn-size-small-new nz-btn-style-normal-new" type="button" v-has="'system_link_save'">Update</button>
|
|
||||||
<button type="button" class="linkBtn nz-btn nz-btn-size-small-new nz-btn-style-light-new" @click="linkCancel(item)">Cancel</button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div class="linkFormContent" v-else>
|
|
||||||
<div class="linkTitleName" :title="item.name">{{item.name}}</div>
|
|
||||||
<div class="linkTitleUrl">
|
|
||||||
<span @click="openUrl(item)" @dblclick.stop="linkEdit(item)" class="linkTitleUrlContent" v-has="'system_link_toEdit'">
|
|
||||||
<span>{{item.url}}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="linkFormBtn">
|
|
||||||
<i @click.stop="linkEdit(item)" class="nz-icon nz-icon-edit" v-has="'system_link_toEdit'" v-if="item.buildIn=='0'"></i>
|
|
||||||
<i @click="linkDel(item)" class="nz-icon nz-icon-delete" v-has="'system_link_delete'" v-if="item.buildIn=='0'"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</draggable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('config.system.reset.reset')" name="reset">
|
<el-tab-pane :label="$t('config.system.reset.reset')" name="reset">
|
||||||
<div class="system-config-form">
|
<div class="system-config-form">
|
||||||
@@ -359,10 +201,12 @@ import { positiveInteger, port, hostPlus, host, uSize } from '../../common/js/va
|
|||||||
import latlngPicker from '../../common/latlngPicker'
|
import latlngPicker from '../../common/latlngPicker'
|
||||||
import bus from '../../../libs/bus'
|
import bus from '../../../libs/bus'
|
||||||
import draggable from 'vuedraggable'
|
import draggable from 'vuedraggable'
|
||||||
|
import notifyMethod from './system/notifyMethodTab'
|
||||||
|
import linkTab from './system/linkTab'
|
||||||
|
import apiKeyTab from './system/apiKeyTab'
|
||||||
export default {
|
export default {
|
||||||
name: 'system',
|
name: 'system',
|
||||||
components: { draggable, latlngPicker },
|
components: { draggable, latlngPicker, notifyMethod, linkTab, apiKeyTab },
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
basic: {
|
basic: {
|
||||||
@@ -501,11 +345,6 @@ export default {
|
|||||||
// { type: 'url', message: this.$t('config.system.link.uriRequired'), trigger: 'blur' } /*检验网址是否正确*/
|
// { type: 'url', message: this.$t('config.system.link.uriRequired'), trigger: 'blur' } /*检验网址是否正确*/
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
notificationTemp: {
|
|
||||||
name: '', filePath: ''
|
|
||||||
},
|
|
||||||
notification: [],
|
|
||||||
notificationReserved: [],
|
|
||||||
notificationRules: {
|
notificationRules: {
|
||||||
name: [
|
name: [
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' },
|
{ required: true, message: this.$t('validate.required'), trigger: 'blur' },
|
||||||
@@ -535,7 +374,7 @@ export default {
|
|||||||
value: 'sysconfig'
|
value: 'sysconfig'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
activeTab: 'basic'
|
activeTab: 'notification'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -547,15 +386,7 @@ export default {
|
|||||||
console.error('type is required')
|
console.error('type is required')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (type == 'reset') {
|
if (type == 'reset' || type == 'link' || type == 'notification' || type == 'apiKey') {
|
||||||
return
|
|
||||||
}
|
|
||||||
if (type == 'link') {
|
|
||||||
this.getLinkData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (type == 'notification') {
|
|
||||||
this.getNotificationData()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.$get('sysConfig?type=' + type).then(response => {
|
this.$get('sysConfig?type=' + type).then(response => {
|
||||||
@@ -727,12 +558,7 @@ export default {
|
|||||||
// console.log(originalEvent) //鼠标位置
|
// console.log(originalEvent) //鼠标位置
|
||||||
},
|
},
|
||||||
getLinkData () {
|
getLinkData () {
|
||||||
this.linkTemp = { name: '', url: '' }
|
|
||||||
this.$refs.linkTempForm.clearValidate()
|
|
||||||
this.$get('/link').then(response => {
|
|
||||||
this.link = response.data
|
|
||||||
this.linkReserved = [...this.link]
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
// link add
|
// link add
|
||||||
linkAdd () {
|
linkAdd () {
|
||||||
@@ -821,12 +647,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getNotificationData () {
|
getNotificationData () {
|
||||||
this.notificationTemp = { name: '', filePath: '' }
|
|
||||||
this.$refs.notificationTempForm.clearValidate()
|
|
||||||
this.$get('/alert/script').then(response => {
|
|
||||||
this.notification = response.data.list
|
|
||||||
this.notificationReserved = [...this.notification]
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
// link add
|
// link add
|
||||||
notificationAdd () {
|
notificationAdd () {
|
||||||
@@ -919,7 +740,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.querySetInfo('basic')
|
this.querySetInfo(this.activeTab)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -1041,27 +862,16 @@ export default {
|
|||||||
.system-config-form /deep/ .el-input input{
|
.system-config-form /deep/ .el-input input{
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
.notificationMessage{
|
|
||||||
display: flex;
|
|
||||||
width: 780px;
|
|
||||||
background: #F6F6F6;
|
|
||||||
color: #999999;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding: 10px 10px 5px 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
justify-content: left;
|
|
||||||
justify-items: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.notificationMessage .more{
|
|
||||||
font-size: 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.system {
|
.system {
|
||||||
.el-tabs__nav-scroll {
|
background-color: #FFF;
|
||||||
background-color: #eee;
|
padding: 10px;
|
||||||
|
.el-tabs__nav-scroll{
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
.el-tabs__nav-scroll,.el-tabs__header,。el-tabs__nav-wrap{
|
||||||
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
.el-form-item:last-of-type {
|
.el-form-item:last-of-type {
|
||||||
|
|
||||||
@@ -1073,8 +883,20 @@ export default {
|
|||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.full-table {
|
||||||
|
.el-tabs__content{
|
||||||
|
height: 90%;
|
||||||
|
}
|
||||||
|
.list-page .main-container{
|
||||||
|
padding: unset;
|
||||||
|
}
|
||||||
|
.table-column-setting,.pagination-bottom{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
.el-tabs__content {
|
.el-tabs__content {
|
||||||
padding-top: 25px;
|
padding-top: 25px;
|
||||||
|
border: 1px solid #E7EAED;
|
||||||
}
|
}
|
||||||
.el-tabs__item {
|
.el-tabs__item {
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -1082,20 +904,24 @@ export default {
|
|||||||
}
|
}
|
||||||
.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active {
|
.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active {
|
||||||
color: $global-text-color-active;
|
color: $global-text-color-active;
|
||||||
|
background: #FFFFFF;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
border-left: none;
|
margin-left: .1px;
|
||||||
border-right: none;
|
|
||||||
border-top: 4px solid $global-text-color-active;
|
|
||||||
}
|
}
|
||||||
.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover {
|
.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover {
|
||||||
color: $global-text-color-active;
|
color: $global-text-color-active;
|
||||||
opacity: .8;
|
opacity: .8;
|
||||||
}
|
}
|
||||||
.el-tabs--border-card>.el-tabs__header .el-tabs__item {
|
.el-tabs--border-card>.el-tabs__header .el-tabs__item {
|
||||||
border-bottom: none;
|
height: 40px;
|
||||||
border-left: none;
|
background: #F6F6F6;
|
||||||
border-right: none;
|
border: 1px solid #E7EAED;
|
||||||
border-top: 4px solid transparent;
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(:first-child) {
|
||||||
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.system-config-form .el-form-item__content{
|
.system-config-form .el-form-item__content{
|
||||||
@@ -1113,7 +939,9 @@ export default {
|
|||||||
}
|
}
|
||||||
.system-tabs {
|
.system-tabs {
|
||||||
box-shadow: unset !important;
|
box-shadow: unset !important;
|
||||||
border-color: #eee !important;
|
border:unset;
|
||||||
|
border-top: unset;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
.system-tabs .el-tabs--border-card{
|
.system-tabs .el-tabs--border-card{
|
||||||
webkit-box-shadow: unset !important;
|
webkit-box-shadow: unset !important;
|
||||||
@@ -1168,5 +996,19 @@ export default {
|
|||||||
.el-form-item.has-tip--two-row {
|
.el-form-item.has-tip--two-row {
|
||||||
margin-bottom: 54px;
|
margin-bottom: 54px;
|
||||||
}
|
}
|
||||||
|
@keyframes warnBackground {
|
||||||
|
0% {background-color: #FFFFFF;}
|
||||||
|
25% {background-color: #EF7458;}
|
||||||
|
50% {background-color: #FFFFFF;}
|
||||||
|
75% {background-color: #EF7458;}
|
||||||
|
100% {background-color: #FFFFFF;}
|
||||||
|
}
|
||||||
|
.warn-pop {
|
||||||
|
background-color: #FEF0F0;
|
||||||
|
border-color: #FEF0F0;
|
||||||
|
color:#F66C6C;
|
||||||
|
}
|
||||||
|
.warn-pop .popper__arrow:after{
|
||||||
|
border-top-color: #FEF0F0 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
<template>
|
||||||
|
<div style="height: 100%">
|
||||||
|
<nz-data-list
|
||||||
|
ref="dataList"
|
||||||
|
:api="url"
|
||||||
|
:custom-table-title.sync="tools.customTableTitle"
|
||||||
|
:from="fromRoute.apiKey"
|
||||||
|
:layout="['searchInput', 'elementSet']"
|
||||||
|
:search-msg="searchMsg">
|
||||||
|
<template v-slot:top-tool-left>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<template v-slot:top-tool-right>
|
||||||
|
<button id="api-key-add" v-has="'snmp_mibFile_add'" :title="$t('config.system.notification.create')" class="top-tool-btn margin-r-10" type="button" @click="addApiKey">
|
||||||
|
<i class="nz-icon-create-square nz-icon"></i>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-slot:default="slotProps">
|
||||||
|
<api-key-table
|
||||||
|
ref="dataTable"
|
||||||
|
v-loading="slotProps.loading"
|
||||||
|
:table-id="tableId"
|
||||||
|
:api="url"
|
||||||
|
:custom-table-title="tools.customTableTitle"
|
||||||
|
:height="mainTableHeight"
|
||||||
|
:table-data="tableData"
|
||||||
|
@del="del"
|
||||||
|
@edit="edit"
|
||||||
|
@orderBy="tableDataSort"
|
||||||
|
@reload="getTableData"
|
||||||
|
@selectionChange="selectionChange"
|
||||||
|
@showBottomBox="(targetTab, object) => { $refs.dataList.showBottomBox(targetTab, object) }"
|
||||||
|
></api-key-table>
|
||||||
|
</template>
|
||||||
|
</nz-data-list>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import apiKeyTable from './apiKeyTable'
|
||||||
|
import dataListMixin from '@/components/common/mixin/dataList'
|
||||||
|
import nzDataList from '@/components/common/table/nzDataList'
|
||||||
|
import { parentTableCommon } from './systemCommon'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'apiKeyTab',
|
||||||
|
components: { nzDataList, apiKeyTable },
|
||||||
|
mixins: [dataListMixin, parentTableCommon],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
url: '/sys/apiKey',
|
||||||
|
tableId: 'apiKeyTable',
|
||||||
|
searchMsg: { // 给搜索框子组件传递的信息
|
||||||
|
zheze_none: true,
|
||||||
|
searchLabelList: [{
|
||||||
|
id: 1,
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input',
|
||||||
|
label: 'ids',
|
||||||
|
disabled: false
|
||||||
|
}, {
|
||||||
|
id: 5,
|
||||||
|
name: this.$t('overall.name'),
|
||||||
|
type: 'input',
|
||||||
|
label: 'name',
|
||||||
|
disabled: false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addApiKey: function () {
|
||||||
|
this.$refs.dataTable.addApiKey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
191
nezha-fronted/src/components/page/config/system/apiKeyTable.vue
Normal file
191
nezha-fronted/src/components/page/config/system/apiKeyTable.vue
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
<template>
|
||||||
|
<el-table
|
||||||
|
:id="tableId"
|
||||||
|
ref="dataTable"
|
||||||
|
:data="tableData"
|
||||||
|
:height="height"
|
||||||
|
border
|
||||||
|
@header-dragend="dragend"
|
||||||
|
@sort-change="tableDataSort"
|
||||||
|
@selection-change="selectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
:resizable="false"
|
||||||
|
align="center"
|
||||||
|
type="selection"
|
||||||
|
width="55">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="(item, index) in customTableTitle"
|
||||||
|
v-if="item.show"
|
||||||
|
:key="`col-${index}`"
|
||||||
|
:fixed="item.fixed"
|
||||||
|
:label="item.label"
|
||||||
|
:min-width="`${item.minWidth}`"
|
||||||
|
:prop="item.prop"
|
||||||
|
:resizable="true"
|
||||||
|
:sort-orders="['ascending', 'descending']"
|
||||||
|
:width="`${item.width}`"
|
||||||
|
class="data-column"
|
||||||
|
>
|
||||||
|
<template slot="header">
|
||||||
|
<span>{{item.label}}</span>
|
||||||
|
<div class="col-resize-area"></div>
|
||||||
|
</template>
|
||||||
|
<template slot-scope="scope" :column="item">
|
||||||
|
<template v-if="scope.row.edit">
|
||||||
|
<template v-if="item.prop == 'name'">
|
||||||
|
<el-popover :content="rules.name.message" placement="top" trigger="manual" v-model="rules.name.switch" popper-class="small-pop warn-pop" @after-enter="popShow(rules.name)">
|
||||||
|
<el-input slot="reference" v-model="scope.row[item.prop]" size="small" ></el-input>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
<template v-if="item.prop == 'roles'">
|
||||||
|
<el-popover :content="rules.roleId.message" placement="top" trigger="manual" v-model="rules.roleId.switch" popper-class="small-pop warn-pop" @after-enter="popShow(rules.roleId)">
|
||||||
|
<el-select v-model="scope.row[item.prop]" size="small" value-key="id" slot="reference">
|
||||||
|
<template v-for="role in roles" >
|
||||||
|
<el-option :label="role.name" :value="role"></el-option>
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
<template v-if="item.prop == 'expireAt'">
|
||||||
|
<el-popover :content="rules.expireAt.message" placement="top" trigger="manual" v-model="rules.expireAt.switch" popper-class="small-pop warn-pop" @after-enter="popShow(rules.expireAt)">
|
||||||
|
<el-date-picker
|
||||||
|
slot="reference"
|
||||||
|
style="width: 100%;"
|
||||||
|
v-model="scope.row[item.prop]"
|
||||||
|
prefix-icon=" " size="small" ref="calendar"
|
||||||
|
format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
type="datetime"
|
||||||
|
:picker-options="pickerOptions"
|
||||||
|
:placeholder="$t('el.datepicker.selectTime')">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<template v-if="item.prop == 'creator'">
|
||||||
|
{{scope.row[item.prop]?scope.row[item.prop].name:'-'}}
|
||||||
|
</template>
|
||||||
|
<template v-if="item.prop == 'roles'">
|
||||||
|
{{scope.row[item.prop]?scope.row[item.prop].name:'-'}}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</template>
|
||||||
|
<template v-else>-</template>
|
||||||
|
</template>
|
||||||
|
</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">
|
||||||
|
<template v-if="scope.row.edit">
|
||||||
|
<button type="button" class="nz-btn nz-btn-size-mini-new nz-btn-style-normal-new" :disabled="prevent_opt.save" @click="save(scope.row)" style="margin-right: 10px"><span>{{$t('overall.save')}}</span></button>
|
||||||
|
<button type="button" class="nz-btn nz-btn-size-mini-new nz-btn-style-light-new" @click="cancel(scope.row)" :disabled="prevent_opt.save"><span>{{$t('overall.cancel')}}</span></button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<button class="table-operation-item" :command="['delete', scope.row]" :disabled="isBuiltIn(scope.row)"><i class="nz-icon nz-icon-delete"></i></button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { tableCommon } from './systemCommon'
|
||||||
|
import table from '@/components/common/mixin/table'
|
||||||
|
export default {
|
||||||
|
name: 'apiKeyTable',
|
||||||
|
mixins: [table, tableCommon],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
tableTitle: [
|
||||||
|
{
|
||||||
|
label: 'ID',
|
||||||
|
prop: 'id',
|
||||||
|
show: true,
|
||||||
|
width: 80
|
||||||
|
}, {
|
||||||
|
label: this.$t('overall.name'),
|
||||||
|
prop: 'name',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: 'Token',
|
||||||
|
prop: 'token',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: this.$t('config.system.apiKey.role'),
|
||||||
|
prop: 'roles',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: this.$t('config.system.apiKey.expireAt'),
|
||||||
|
prop: 'expireAt',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: this.$t('config.system.apiKey.create'),
|
||||||
|
prop: 'createUser',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: this.$t('config.system.apiKey.creatAt'),
|
||||||
|
prop: 'createAt',
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
roles: [],
|
||||||
|
rules: {
|
||||||
|
name: { required: true, message: this.$t('validate.required'), switch: false },
|
||||||
|
roleId: { required: true, message: this.$t('validate.required'), switch: false },
|
||||||
|
expireAt: { required: true, message: this.$t('validate.required'), switch: false }
|
||||||
|
},
|
||||||
|
pickerOptions: {
|
||||||
|
// 限制预约时间
|
||||||
|
disabledDate (time) {
|
||||||
|
return time.getTime() < Date.now() - 24 * 60 * 60 * 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addApiKey: function () {
|
||||||
|
if (this.tableData.every(t => !t.edit)) {
|
||||||
|
this.tableData.unshift({
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
roles: {
|
||||||
|
id: '',
|
||||||
|
name: ''
|
||||||
|
},
|
||||||
|
expireAt: '',
|
||||||
|
edit: true
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setWarning()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getRoles: function () {
|
||||||
|
this.$get('sys/role?pageSize=-1').then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.roles = response.data.list
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
save: function (obj) {
|
||||||
|
const copy = JSON.parse(JSON.stringify(obj))
|
||||||
|
if (copy.roles) {
|
||||||
|
copy.roleId = copy.roles.id
|
||||||
|
}
|
||||||
|
delete copy.roles
|
||||||
|
this.saveOrUpdate(copy)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.getRoles()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
80
nezha-fronted/src/components/page/config/system/linkTab.vue
Normal file
80
nezha-fronted/src/components/page/config/system/linkTab.vue
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<template>
|
||||||
|
<div style="height: 100%">
|
||||||
|
<nz-data-list
|
||||||
|
ref="dataList"
|
||||||
|
:api="url"
|
||||||
|
:custom-table-title.sync="tools.customTableTitle"
|
||||||
|
:from="fromRoute.link"
|
||||||
|
:layout="['searchInput', 'elementSet']"
|
||||||
|
:search-msg="searchMsg">
|
||||||
|
<template v-slot:top-tool-left>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<template v-slot:top-tool-right>
|
||||||
|
<button id="link-add" v-has="'snmp_mibFile_add'" :title="$t('config.system.notification.create')" class="top-tool-btn margin-r-10" type="button" @click="addLink">
|
||||||
|
<i class="nz-icon-create-square nz-icon"></i>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-slot:default="slotProps">
|
||||||
|
<link-table
|
||||||
|
ref="dataTable"
|
||||||
|
v-loading="slotProps.loading"
|
||||||
|
:table-id="tableId"
|
||||||
|
:api="url"
|
||||||
|
:custom-table-title="tools.customTableTitle"
|
||||||
|
:height="mainTableHeight"
|
||||||
|
:table-data="tableData"
|
||||||
|
@del="del"
|
||||||
|
@edit="edit"
|
||||||
|
@orderBy="tableDataSort"
|
||||||
|
@reload="getTableData"
|
||||||
|
@selectionChange="selectionChange"
|
||||||
|
@showBottomBox="(targetTab, object) => { $refs.dataList.showBottomBox(targetTab, object) }"
|
||||||
|
></link-table>
|
||||||
|
</template>
|
||||||
|
</nz-data-list>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import linkTable from './linkTable'
|
||||||
|
import dataListMixin from '@/components/common/mixin/dataList'
|
||||||
|
import nzDataList from '@/components/common/table/nzDataList'
|
||||||
|
import { parentTableCommon } from './systemCommon'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'linkTab',
|
||||||
|
components: { nzDataList, linkTable },
|
||||||
|
mixins: [dataListMixin, parentTableCommon],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
url: '/link',
|
||||||
|
tableId: 'linkTable',
|
||||||
|
searchMsg: { // 给搜索框子组件传递的信息
|
||||||
|
zheze_none: true,
|
||||||
|
searchLabelList: [{
|
||||||
|
id: 1,
|
||||||
|
name: this.$t('config.system.link.create'),
|
||||||
|
type: 'input',
|
||||||
|
label: 'createBy',
|
||||||
|
disabled: false
|
||||||
|
}, {
|
||||||
|
id: 5,
|
||||||
|
name: this.$t('overall.name'),
|
||||||
|
type: 'input',
|
||||||
|
label: 'name',
|
||||||
|
disabled: false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addLink: function () {
|
||||||
|
this.$refs.dataTable.addLink()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
135
nezha-fronted/src/components/page/config/system/linkTable.vue
Normal file
135
nezha-fronted/src/components/page/config/system/linkTable.vue
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<template>
|
||||||
|
<el-table
|
||||||
|
:id="tableId"
|
||||||
|
ref="dataTable"
|
||||||
|
:data="tableData"
|
||||||
|
:height="height"
|
||||||
|
border
|
||||||
|
@header-dragend="dragend"
|
||||||
|
@sort-change="tableDataSort"
|
||||||
|
@selection-change="selectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
:resizable="false"
|
||||||
|
align="center"
|
||||||
|
type="selection"
|
||||||
|
width="55">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="(item, index) in customTableTitle"
|
||||||
|
v-if="item.show"
|
||||||
|
:key="`col-${index}`"
|
||||||
|
:fixed="item.fixed"
|
||||||
|
:label="item.label"
|
||||||
|
:min-width="`${item.minWidth}`"
|
||||||
|
:prop="item.prop"
|
||||||
|
:resizable="true"
|
||||||
|
:sort-orders="['ascending', 'descending']"
|
||||||
|
:width="`${item.width}`"
|
||||||
|
class="data-column"
|
||||||
|
>
|
||||||
|
<template slot="header">
|
||||||
|
<span>{{item.label}}</span>
|
||||||
|
<div class="col-resize-area"></div>
|
||||||
|
</template>
|
||||||
|
<template slot-scope="scope" :column="item">
|
||||||
|
<template v-if="scope.row.edit">
|
||||||
|
<template v-if="item.prop == 'name'">
|
||||||
|
<el-popover :content="rules.name.message" placement="top" trigger="manual" v-model="rules.name.switch" popper-class="small-pop warn-pop" @after-enter="popShow(rules.name)">
|
||||||
|
<el-input slot="reference" v-model="scope.row[item.prop]" size="small" ></el-input>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
<template v-if="item.prop == 'url'">
|
||||||
|
<el-popover :content="rules.url.message" placement="top" trigger="manual" v-model="rules.url.switch" popper-class="small-pop warn-pop" @after-enter="popShow(rules.url)">
|
||||||
|
<el-input slot="reference" v-model="scope.row[item.prop]" size="small" ></el-input>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<template v-if="item.prop == 'creator'">
|
||||||
|
{{scope.row[item.prop]?scope.row[item.prop].name:'-'}}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</template>
|
||||||
|
<template v-else>-</template>
|
||||||
|
</template>
|
||||||
|
</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">
|
||||||
|
<template v-if="scope.row.edit">
|
||||||
|
<button type="button" class="nz-btn nz-btn-size-mini-new nz-btn-style-normal-new" :disabled="prevent_opt.save" @click="saveOrUpdate(scope.row)" style="margin-right: 10px"><span>{{$t('overall.save')}}</span></button>
|
||||||
|
<button type="button" class="nz-btn nz-btn-size-mini-new nz-btn-style-light-new" @click="cancel(scope.row)" :disabled="prevent_opt.save"><span>{{$t('overall.cancel')}}</span></button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<button class="table-operation-item" @click="toEdit(scope.row)"><i class="nz-icon nz-icon-edit"></i></button>
|
||||||
|
<el-dropdown size="medium" trigger="hover" @command="tableOperation">
|
||||||
|
<div class="table-operation-item table-operation-item--more">
|
||||||
|
<span>…</span><i class="nz-icon nz-icon-arrow-down"></i>
|
||||||
|
</div>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item :command="['delete', scope.row]" :disabled="isBuiltIn(scope.row)"><i class="nz-icon nz-icon-delete"></i><span class="operation-dropdown-text">{{$t('overall.delete')}}</span></el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { tableCommon } from './systemCommon'
|
||||||
|
import table from '@/components/common/mixin/table'
|
||||||
|
export default {
|
||||||
|
name: 'linkTable',
|
||||||
|
mixins: [table, tableCommon],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
tableTitle: [
|
||||||
|
{
|
||||||
|
label: 'ID',
|
||||||
|
prop: 'id',
|
||||||
|
show: true,
|
||||||
|
width: 80
|
||||||
|
}, {
|
||||||
|
label: this.$t('overall.name'),
|
||||||
|
prop: 'name',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: 'URL',
|
||||||
|
prop: 'url',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: this.$t('config.system.link.create'),
|
||||||
|
prop: 'creator',
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
name: { required: true, message: this.$t('validate.required'), switch: false },
|
||||||
|
url: { required: true, message: this.$t('validate.required'), switch: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addLink: function () {
|
||||||
|
if (this.tableData.every(t => !t.edit)) {
|
||||||
|
this.tableData.unshift({
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
url: '',
|
||||||
|
edit: true
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setWarning()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
<template>
|
||||||
|
<div style="height: 100%">
|
||||||
|
<nz-data-list
|
||||||
|
ref="dataList"
|
||||||
|
class="notify-table"
|
||||||
|
:api="url"
|
||||||
|
:custom-table-title.sync="tools.customTableTitle"
|
||||||
|
:from="fromRoute.notify"
|
||||||
|
:layout="['searchInput', 'elementSet']"
|
||||||
|
:search-msg="searchMsg">
|
||||||
|
<template v-slot:top-tool-left>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<template v-slot:top-tool-right>
|
||||||
|
<button id="notify-add" v-has="'snmp_mibFile_add'" :title="$t('config.system.notification.create')" class="top-tool-btn margin-r-10" type="button" @click="addNotify">
|
||||||
|
<i class="nz-icon-create-square nz-icon"></i>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-slot:default="slotProps">
|
||||||
|
<notify-method-table
|
||||||
|
ref="dataTable"
|
||||||
|
v-loading="slotProps.loading"
|
||||||
|
:table-id="tableId"
|
||||||
|
:api="url"
|
||||||
|
:custom-table-title="tools.customTableTitle"
|
||||||
|
:height="mainTableHeight"
|
||||||
|
:table-data="tableData"
|
||||||
|
@del="del"
|
||||||
|
@edit="edit"
|
||||||
|
@orderBy="tableDataSort"
|
||||||
|
@reload="getTableData"
|
||||||
|
@selectionChange="selectionChange"
|
||||||
|
@showBottomBox="(targetTab, object) => { $refs.dataList.showBottomBox(targetTab, object) }"
|
||||||
|
></notify-method-table>
|
||||||
|
</template>
|
||||||
|
</nz-data-list>
|
||||||
|
<div class="notificationMessage">
|
||||||
|
<i class="nz-icon nz-icon-info-normal"></i>
|
||||||
|
<div style="margin-left: 15px">
|
||||||
|
<div>. Please make sure the script file exists and has executable permissions</div>
|
||||||
|
<div>. The script file receives two parameters:</div>
|
||||||
|
<div> ① Notification account</div>
|
||||||
|
<div> ② Alert message(json)
|
||||||
|
<el-tooltip placement="top" effect="light">
|
||||||
|
<pre slot="content" style="word-break: break-all">
|
||||||
|
{
|
||||||
|
"assetId": 1,
|
||||||
|
"dcId": 1,
|
||||||
|
"description": "The endpoint is down, the detailed information
|
||||||
|
Asset : 192.168.40.161, Project: system, Module: node_exporter,
|
||||||
|
Data center: center, EndpointId: 1",
|
||||||
|
"endAt": 1606240496000,
|
||||||
|
"endpointId": 1,
|
||||||
|
"hashKey": "34a17b57f289592a94ff65ee0864094b",
|
||||||
|
"id": 1,
|
||||||
|
"labels": "{\"severity\":\"P2\",\"endpoint\":\"1\",\"alertname\":\"1\",
|
||||||
|
\"module\":\"node_exporter\",\"project\":\"system\",\"datacenter\":
|
||||||
|
\"center\",\"asset\":\"192.168.40.161\"}",
|
||||||
|
"moduleId": 1,
|
||||||
|
"projectId": 1,
|
||||||
|
"ruleId": 1,
|
||||||
|
"severity": "P2",
|
||||||
|
"startAt": 1606009916000,
|
||||||
|
"state": 2,
|
||||||
|
"summary": "The endpoint is down, endpointId is 1"
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
<span class="more">...</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { parentTableCommon } from './systemCommon'
|
||||||
|
import notifyMethodTable from './notifyMethodTable'
|
||||||
|
import dataListMixin from '@/components/common/mixin/dataList'
|
||||||
|
import nzDataList from '@/components/common/table/nzDataList'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'notifyMethodTab',
|
||||||
|
components: { nzDataList, notifyMethodTable },
|
||||||
|
mixins: [dataListMixin, parentTableCommon],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
url: 'alert/notify/method',
|
||||||
|
tableId: 'notifyTable',
|
||||||
|
searchMsg: { // 给搜索框子组件传递的信息
|
||||||
|
zheze_none: true,
|
||||||
|
searchLabelList: [{
|
||||||
|
id: 1,
|
||||||
|
name: 'ID',
|
||||||
|
type: 'input',
|
||||||
|
label: 'id',
|
||||||
|
disabled: false
|
||||||
|
}, {
|
||||||
|
id: 5,
|
||||||
|
name: this.$t('overall.name'),
|
||||||
|
type: 'input',
|
||||||
|
label: 'name',
|
||||||
|
disabled: false
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addNotify: function () {
|
||||||
|
this.$refs.dataTable.addNotify()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.notify-table{
|
||||||
|
height: 90%;
|
||||||
|
|
||||||
|
}
|
||||||
|
.notify-table .el-table{
|
||||||
|
height: calc(100% - 10px) !important;
|
||||||
|
}
|
||||||
|
.notificationMessage{
|
||||||
|
margin-left: 20px;
|
||||||
|
display: flex;
|
||||||
|
width: calc(100% - 60px);
|
||||||
|
background: #F6F6F6;
|
||||||
|
color: #999999;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 10px 10px 5px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
justify-content: left;
|
||||||
|
justify-items: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.notificationMessage .more{
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<el-table
|
||||||
|
:id="tableId"
|
||||||
|
ref="dataTable"
|
||||||
|
:data="tableData"
|
||||||
|
:height="height"
|
||||||
|
border
|
||||||
|
@header-dragend="dragend"
|
||||||
|
@sort-change="tableDataSort"
|
||||||
|
@selection-change="selectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
:resizable="false"
|
||||||
|
align="center"
|
||||||
|
type="selection"
|
||||||
|
width="55">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="(item, index) in customTableTitle"
|
||||||
|
v-if="item.show"
|
||||||
|
:key="`col-${index}`"
|
||||||
|
:fixed="item.fixed"
|
||||||
|
:label="item.label"
|
||||||
|
:min-width="`${item.minWidth}`"
|
||||||
|
:prop="item.prop"
|
||||||
|
:resizable="true"
|
||||||
|
:sort-orders="['ascending', 'descending']"
|
||||||
|
:width="`${item.width}`"
|
||||||
|
class="data-column"
|
||||||
|
>
|
||||||
|
<template slot="header">
|
||||||
|
<span>{{item.label}}</span>
|
||||||
|
<div class="col-resize-area"></div>
|
||||||
|
</template>
|
||||||
|
<template slot-scope="scope" :column="item">
|
||||||
|
<template v-if="scope.row.edit">
|
||||||
|
<template v-if="item.prop == 'name'">
|
||||||
|
<el-popover :content="rules.name.message" placement="top" trigger="manual" v-model="rules.name.switch" popper-class="small-pop warn-pop" @after-enter="popShow(rules.name)">
|
||||||
|
<el-input slot="reference" v-model="scope.row[item.prop]" size="small" ></el-input>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
<template v-if="item.prop == 'filePath'">
|
||||||
|
<el-popover :content="rules.filePath.message" placement="top" trigger="manual" v-model="rules.filePath.switch" popper-class="small-pop warn-pop" @after-enter="popShow(rules.filePath)">
|
||||||
|
<el-input slot="reference" v-model="scope.row[item.prop]" size="small" ></el-input>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
<template v-if="item.prop == 'account'">
|
||||||
|
<el-popover :content="rules.account.message" placement="top" trigger="manual" v-model="rules.account.switch" popper-class="small-pop warn-pop" @after-enter="popShow(rules.account)">
|
||||||
|
<el-select slot="reference" v-model="scope.row[item.prop]" size="small">
|
||||||
|
<template v-for="param in accountParams">
|
||||||
|
<el-option :label="param.label" :value="param.value"></el-option>
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
<template v-if="item.prop == 'state'"><el-switch v-model="scope.row.state" active-color="#ee9d3f" :active-value="1" :inactive-value="0" /></template>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<template v-if="item.prop == 'state'">
|
||||||
|
<div :class="{'active-icon green':scope.row[item.prop] == '1','active-icon red':scope.row[item.prop] == '0'}"></div><span>{{scope.row[item.prop] == '1'?$t(''):$t('')}}</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</template>
|
||||||
|
<template v-else>-</template>
|
||||||
|
</template>
|
||||||
|
</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">
|
||||||
|
<template v-if="scope.row.edit">
|
||||||
|
<button type="button" class="nz-btn nz-btn-size-mini-new nz-btn-style-normal-new" @click="saveOrUpdate(scope.row)" :disabled="prevent_opt.save" style="margin-right: 10px"><span>{{$t('overall.save')}}</span></button>
|
||||||
|
<button type="button" class="nz-btn nz-btn-size-mini-new nz-btn-style-light-new" @click="cancel(scope.row)" :disabled="prevent_opt.save"><span>{{$t('overall.cancel')}}</span></button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<button class="table-operation-item" @click="toEdit(scope.row)"><i class="nz-icon nz-icon-edit"></i></button>
|
||||||
|
<el-dropdown size="medium" trigger="hover" @command="tableOperation">
|
||||||
|
<div class="table-operation-item table-operation-item--more">
|
||||||
|
<span>…</span><i class="nz-icon nz-icon-arrow-down"></i>
|
||||||
|
</div>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item :command="['delete', scope.row]" :disabled="isBuiltIn(scope.row)"><i class="nz-icon nz-icon-delete"></i><span class="operation-dropdown-text">{{$t('overall.delete')}}</span></el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import table from '@/components/common/mixin/table'
|
||||||
|
import { tableCommon } from './systemCommon'
|
||||||
|
export default {
|
||||||
|
name: 'notifyMethodTable',
|
||||||
|
mixins: [table, tableCommon],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
tableTitle: [
|
||||||
|
{
|
||||||
|
label: 'ID',
|
||||||
|
prop: 'id',
|
||||||
|
show: true,
|
||||||
|
width: 80
|
||||||
|
}, {
|
||||||
|
label: this.$t('overall.name'),
|
||||||
|
prop: 'name',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: this.$t('config.system.notification.filePath'),
|
||||||
|
prop: 'filePath',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: this.$t('config.system.notification.account'),
|
||||||
|
prop: 'account',
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: this.$t('config.system.notification.state'),
|
||||||
|
prop: 'state',
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
accountParams: [
|
||||||
|
{
|
||||||
|
label: 'id',
|
||||||
|
value: 'id'
|
||||||
|
}, {
|
||||||
|
label: 'name',
|
||||||
|
value: 'name'
|
||||||
|
}, {
|
||||||
|
label: 'username',
|
||||||
|
value: 'username'
|
||||||
|
}, {
|
||||||
|
label: 'email',
|
||||||
|
value: 'email'
|
||||||
|
}, {
|
||||||
|
label: 'mobile',
|
||||||
|
value: 'mobile'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
name: { required: true, message: this.$t('validate.required'), switch: false },
|
||||||
|
account: { required: true, message: this.$t('validate.required'), switch: false },
|
||||||
|
filePath: { required: true, message: this.$t('validate.required'), switch: false }
|
||||||
|
},
|
||||||
|
copy: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addNotify: function () {
|
||||||
|
if (this.tableData.every(t => !t.edit)) {
|
||||||
|
this.tableData.unshift({
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
account: '',
|
||||||
|
state: 1,
|
||||||
|
filePath: '',
|
||||||
|
edit: true
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setWarning()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
115
nezha-fronted/src/components/page/config/system/systemCommon.js
Normal file
115
nezha-fronted/src/components/page/config/system/systemCommon.js
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import { file } from '@topology/core/src/middles/nodes/file'
|
||||||
|
|
||||||
|
export const tableCommon = {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
copy: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
saveOrUpdate: function (obj) {
|
||||||
|
if (this.prevent_opt.save) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.validateData(obj)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.prevent_opt.save = true
|
||||||
|
const param = JSON.parse(JSON.stringify(obj))
|
||||||
|
if (param.id) {
|
||||||
|
this.$put(this.api, param).then(response => {
|
||||||
|
this.prevent_opt.save = false
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
|
||||||
|
this.$emit('reload')
|
||||||
|
} else {
|
||||||
|
this.$message.error(response.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$post(this.api, param).then(response => {
|
||||||
|
this.prevent_opt.save = false
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
|
||||||
|
this.$emit('reload')
|
||||||
|
} else {
|
||||||
|
this.$message.error(response.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toEdit: function (obj) {
|
||||||
|
if (this.tableData.every(t => !t.edit)) {
|
||||||
|
this.copy = JSON.parse(JSON.stringify(obj))
|
||||||
|
this.$set(obj, 'edit', true)
|
||||||
|
} else {
|
||||||
|
this.setWarning()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancel: function (obj) {
|
||||||
|
if (obj.id) {
|
||||||
|
for (const key in obj) {
|
||||||
|
this.$set(obj, key, this.copy[key])
|
||||||
|
}
|
||||||
|
this.$set(obj, 'edit', false)
|
||||||
|
} else {
|
||||||
|
this.tableData.shift()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setWarning: function () {
|
||||||
|
const getArrayIndex = function (arr) {
|
||||||
|
let i = arr.length
|
||||||
|
while (i--) {
|
||||||
|
if (arr[i].edit) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
const index = getArrayIndex(this.tableData)
|
||||||
|
const trs = document.querySelectorAll('#' + this.tableId + ' .el-table__body .el-table__row')
|
||||||
|
trs[index].style = 'animation-name: warnBackground;animation-duration: 1s;'
|
||||||
|
setTimeout(() => {
|
||||||
|
trs[index].style = ''
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
validateData: function (data) {
|
||||||
|
let result = true
|
||||||
|
for (const field in this.rules) {
|
||||||
|
const rule = this.rules[field]
|
||||||
|
console.log(field, !data[field])
|
||||||
|
if (rule.required && !data[field]) {
|
||||||
|
rule.switch = true
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
popShow: function (rule) {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
rule.switch = false
|
||||||
|
clearTimeout(timeout)
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const parentTableCommon = {
|
||||||
|
methods: {
|
||||||
|
getTableData: function () {
|
||||||
|
this.searchLabel.pageSize = -1
|
||||||
|
this.$get(this.url, this.searchLabel).then(response => {
|
||||||
|
this.tools.loading = false
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.tableData = []
|
||||||
|
this.tableData = response.data.list
|
||||||
|
if (!this.scrollbarWrap) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollbarWrap = this.$refs.dataTable.$refs.dataTable.bodyWrapper
|
||||||
|
this.toTopBtnHandler(this.scrollbarWrap)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -167,7 +167,7 @@ Vue.mixin({
|
|||||||
getButtonList () {
|
getButtonList () {
|
||||||
return this.$store.state.buttonList
|
return this.$store.state.buttonList
|
||||||
},
|
},
|
||||||
route: function () {
|
$routePath: function () {
|
||||||
return this.$route.path
|
return this.$route.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import VueResource from 'vue-resource'
|
|||||||
|
|
||||||
Vue.use(VueResource)
|
Vue.use(VueResource)
|
||||||
|
|
||||||
const loginWhiteList = ['/login', '/setup'] // 免登陆白名单
|
const loginWhiteList = ['/login', '/setup', '/sys/license/upload', '/sys/license/state'] // 免登陆白名单
|
||||||
const permissionWhiteList = ['/menu', ...loginWhiteList] // 权限白名单
|
const permissionWhiteList = ['/menu', ...loginWhiteList] // 权限白名单
|
||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user