Merge branch 'dev-3.9' of git.mesalab.cn:nezha/nezha-fronted into dev-3.9

This commit is contained in:
zyh
2023-08-28 18:07:44 +08:00
55 changed files with 14539 additions and 175 deletions

1
.gitignore vendored
View File

@@ -19,4 +19,3 @@ nezha-fronted/src/components/common/rightBox/tempRoghtBox.vue
nezha-fronted/exportHtml/
nezha-fronted/src/a.txt
nezha-fronted/src/components/common/testTopology.vue
nezha-fronted/static/

View File

@@ -8,9 +8,9 @@ const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
//const ExtractTextPlugin = require('extract-text-webpack-plugin')
// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
const fileManagerPlugin = require('filemanager-webpack-plugin')
const WebpackZipPlugin = require('webpack-zip-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
@@ -19,14 +19,13 @@ const GenerateAssetPlugin = require('generate-asset-webpack-plugin')
const WebpackShellPlugin = require('webpack-shell-plugin')
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin')
const serverConfig = require('../static/config.json')// 引入根目录下的配置文件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
// const smp = new SpeedMeasurePlugin();
// const gitRevisionPlugin = new GitRevisionPlugin();
const createJson = function () {
// serverConfig.version=config.build.version +"-"+gitRevisionPlugin.commithash();
@@ -61,7 +60,7 @@ if (arg === 'html') {
plugins: [
new VueLoaderPlugin(),
new webpack.ProvidePlugin({
introJs: ['intro.js'],
introJs: ['intro.js']
}),
/* new GenerateAssetPlugin({
filename: 'config.json',
@@ -76,7 +75,7 @@ if (arg === 'html') {
}),
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
chunkFilename: "[name].[contenthash].css"
chunkFilename: '[name].[contenthash].css'
}),
new UglifyJsPlugin({
uglifyOptions: {
@@ -91,14 +90,14 @@ if (arg === 'html') {
parallel: true
}),
// extract css into its own file
/*new ExtractTextPlugin({
/* new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true
}),*/
}), */
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
@@ -186,7 +185,7 @@ if (arg === 'html') {
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['*']
ignore: ['**/Titles/**']
}
])
]
@@ -240,11 +239,11 @@ if (arg === 'html') {
new webpack.DefinePlugin({
'process.env': env
}),
new MiniCssExtractPlugin({ //替换 ExtractTextPlugin 用于css抽取
new MiniCssExtractPlugin({ // 替换 ExtractTextPlugin 用于css抽取
filename: utils.assetsPath('css/[name].[contenthash].css')
// chunkFilename: "[name].[contenthash].css"
}),
/* new UglifyJsPlugin({
/* new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false,
@@ -255,16 +254,16 @@ if (arg === 'html') {
exclude: /manifest.+js/,
sourceMap: config.build.productionSourceMap,
parallel: true
}),*/
}), */
// extract css into its own file
/*new ExtractTextPlugin({
/* new ExtractTextPlugin({
filename: utils.assetsPath('css/[name]_[md5:contenthash:hex:8].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true
}),*/
}), */
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
// new OptimizeCSSPlugin({
@@ -289,7 +288,7 @@ if (arg === 'html') {
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
//chunksSortMode: 'auto',
// chunksSortMode: 'auto',
excludeChunks: ['exportHtml']
}),
new GenerateAssetPlugin({
@@ -303,7 +302,7 @@ if (arg === 'html') {
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
/* new webpack.optimize.CommonsChunkPlugin({
/* new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
@@ -330,14 +329,14 @@ if (arg === 'html') {
async: 'vendor-async',
children: true,
minChunks: 3
}),*/
}), */
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['*']
ignore: ['**/Titles/**']
}
])
],
@@ -347,13 +346,13 @@ if (arg === 'html') {
new TerserPlugin({ // 压缩JS代码
terserOptions: {
compress: {
warnings: false,
drop_console: true, // 去除console
pure_funcs: ['console.log']
warnings: false,
drop_console: true, // 去除console
pure_funcs: ['console.log']
}
},
exclude: /manifest.+js/,
sourceMap: config.build.productionSourceMap,
sourceMap: config.build.productionSourceMap
})
],
splitChunks: { //
@@ -364,7 +363,7 @@ if (arg === 'html') {
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
automaticNameMaxLength: 30,
automaticNameMaxLength: 30
}
}
})
@@ -380,7 +379,7 @@ if (process.env.NODE_ENV == 'development') {
onEnd: [
{
move: [
{ source: path.join(__dirname, '../dist', '/static/config.json'), destination: path.join(__dirname, '../dist/config.json') },
{ source: path.join(__dirname, '../dist', '/static/config.json'), destination: path.join(__dirname, '../dist/config.json') }
// { source: path.join(__dirname, '../exportHtml', '/snapshot_template.html'), destination: path.join(__dirname, '../dist/snapshot_template.html') }
],
@@ -414,7 +413,7 @@ if (process.env.NODE_ENV == 'development') {
onEnd: [
{
move: [
{ source: path.join(__dirname, '../dist', '/static/config.json'), destination: path.join(__dirname, '../dist/config.json') },
{ source: path.join(__dirname, '../dist', '/static/config.json'), destination: path.join(__dirname, '../dist/config.json') }
// { source: path.join(__dirname, '../exportHtml', '/snapshot_template.html'), destination: path.join(__dirname, '../dist/snapshot_template.html') }
],

View File

@@ -14340,7 +14340,7 @@
},
"node-sass": {
"version": "4.14.1",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz",
"resolved": "https://registry.npmmirror.com/node-sass/-/node-sass-4.14.1.tgz",
"integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==",
"dev": true,
"requires": {
@@ -20727,7 +20727,7 @@
},
"webpack-bundle-analyzer": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz",
"resolved": "https://registry.npmmirror.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz",
"integrity": "sha512-rwxyfecTAxoarCC9VlHlIpfQCmmJ/qWD5bpbjkof+7HrNhTNZIwZITxN6CdlYL2axGmwNUQ+tFgcSOiNXMf/sQ==",
"dev": true,
"requires": {

View File

@@ -735,3 +735,11 @@ i.nz-icon-override{
.xterm .xterm-viewport {
background-color: transparent !important;
}
.downloading {
opacity: .6;
color: $--color-primary;
margin-left: 10px;
}
.el-form-item__error {
padding-top: 0;
}

View File

@@ -41,4 +41,24 @@
width: 48px;
}
}
.append_unit{
display: flex;
.el-input--small .el-input__inner {
border-radius: 4px 0 0 4px;
border-right: none;
}
&::after{
content: attr(data-unit);
//position: absolute;
display: inline-block;
top: 0;
right: 100%;
padding: 0 20px;
color: $--color-text-secondary;
background-color: $--background-color-base;
border: 1px solid $--border-color-light;
border-radius:0 4px 4px 0;
width: auto;
}
}

View File

@@ -375,4 +375,9 @@
.nz-icon-sort{
color: #FF8C0E !important;
}
}
}
.datasource-log {
.el-tabs__content {
overflow: unset;
}
}

View File

@@ -198,7 +198,6 @@ export default {
const series = this.$lodash.cloneDeep(this.series)
const dataArg = series.filter((seriesItem, seriesIndex) => !this.isGrey[seriesIndex])
const option = this.renderYAxis(dataArg, chartInfo, 'legend')
console.log(option)
getChart(this.chartId) && getChart(this.chartId).setOption({
yAxis: [
...option.yAxis

View File

@@ -594,7 +594,6 @@ export default {
})
this.onScroll(this.scrollTop)
},
// group设置repeat 便利变量重复渲染图表
repeatVariableFn () {
// 防止group中的chartList执行
@@ -742,7 +741,6 @@ export default {
handler (newVal, oldVal) {
// 比较变量 图表是否显示/隐藏
this.compareVariables()
this.repeatVariableFn()
}
},
@@ -785,7 +783,8 @@ export default {
const position = getLayoutPosition(n)
this.$store.commit('setChartLastPosition', position)
}
const tempList = n.map(item => {
const cloneDataList = this.$lodash.cloneDeep(n)
const tempList = cloneDataList.map(item => {
let param = ''
let height = item.height || ''
if (this.isPhone && item.type !== 'group') {
@@ -848,11 +847,10 @@ export default {
})
}
this.$nextTick(() => {
this.copyDataList = JSON.parse(JSON.stringify(tempList))
this.copyDataList = this.$lodash.cloneDeep(tempList)
this.tempList = JSON.parse(JSON.stringify(this.copyDataList))
// 比较变量 图表是否显示/隐藏
this.compareVariables()
this.repeatVariableFn()
setTimeout(() => {
this.gridLayoutShow = true

View File

@@ -6,7 +6,6 @@ export default {
methods: {
renderYAxis (chartDatas, chartInfo, type) {
let chartData = lodash.cloneDeep(chartDatas)
console.log(chartData)
if (type === 'legend') {
chartData.forEach(item => {
item.values = item.data
@@ -30,13 +29,12 @@ export default {
]
}
// 左y轴
const leftData = chartData.filter(item => !item[0].yAxisIndex)
const leftData = chartData.filter(item => item[0] && !item[0].yAxisIndex)
const leftInfo = this.getMinMaxFromData(leftData, chartInfo.unit, chartInfo.param) //
console.log(leftData, leftInfo)
chartOption.yAxis[0].minInterval = chartDataFormat.Interval(leftInfo.maxValue, leftInfo.copies, leftInfo.unit.type, 'min')
chartOption.yAxis[0].maxInterval = chartDataFormat.Interval(leftInfo.maxValue, leftInfo.copies, leftInfo.unit.type, 'max') * Math.ceil(this.series.length / 5)
if (chartInfo.param.stack) {
chartOption.yAxis[0].maxInterval = chartOption.yAxis[0].maxInterval * (Math.ceil(chartOption.series.length / 5) + 1)
chartOption.yAxis[0].maxInterval = chartOption.yAxis[0].maxInterval * (Math.ceil(leftData.length / 5) + 1)
}
if (leftInfo.unit.type === 'Time' || leftInfo.unit.type === 'Date & Time') {
delete chartOption.yAxis[0].minInterval
@@ -64,13 +62,12 @@ export default {
const unit = chartDataFormat.getUnit(lodash.get(chartInfo, 'param.rightYAxis.unit', 2))
const allRight = this.series.every(item => item.yAxisIndex == 1)
chartOption.yAxis[1].splitLine.show = allRight
const rightData = chartData.filter(item => item[0].yAxisIndex)
console.log(rightData, unit)
const rightData = chartData.filter(item => item[0] && item[0].yAxisIndex)
const rightInfo = this.getMinMaxFromData(rightData, lodash.get(chartInfo, 'param.rightYAxis.unit', 2), lodash.get(chartInfo, 'param.rightYAxis', {}))//
chartOption.yAxis[1].minInterval = chartDataFormat.Interval(rightInfo.maxValue, rightInfo.copies, rightInfo.unit.type, 'min')
chartOption.yAxis[1].maxInterval = chartDataFormat.Interval(rightInfo.maxValue, rightInfo.copies, rightInfo.unit.type, 'max') * Math.ceil(this.series.length / 5)
if (chartInfo.param.stack) {
chartOption.yAxis[1].maxInterval = chartOption.yAxis[1].maxInterval * (Math.ceil(chartOption.series.length / 5) + 1)
chartOption.yAxis[1].maxInterval = chartOption.yAxis[1].maxInterval * (Math.ceil(rightData.length / 5) + 1)
}
if (unit.type === 'Time' || unit.type === 'Date & Time') {
delete chartOption.yAxis[1].minInterval
@@ -95,7 +92,6 @@ export default {
delete chartOption.yAxis[1].max
}
}
console.log(chartOption)
return chartOption
},
getMinMaxFromData (originalDatas, chartUnit = 2, params) {

View File

@@ -114,9 +114,6 @@ export default {
const consoleBox = document.getElementById('ternimalContainer' + this.idIndex)
const width = document.body.clientWidth - 10// 可视宽度
const height = parseInt(consoleBox.offsetHeight) - 10
console.log(width, height)
console.log(this.term.cols)
console.log(this.term.rows)
const winStyle = {
width: width,
height: height,
@@ -367,14 +364,12 @@ export default {
// }
},
renderTerminalSetting () {
console.log('renderTerminalSetting')
this.showWatermark = this.terminalSetting.watermark
this.wordSeparator = this.terminalSetting.wordSeparator
this.term.options = {
scrollback: this.terminalSetting.scrollbackLines,
wordSeparator: this.terminalSetting.wordSeparator
}
console.log(this.term)
},
copySelection () {
let str = this.term.getSelection()

View File

@@ -160,7 +160,6 @@ export default {
methods: {
init () {
this.loading = false
console.log(this.alertLabelData)
},
getRemoteText (record) {
return `${record.loginUser}@${record.host}:${record.port}`

View File

@@ -221,7 +221,6 @@ export default {
if (simpleTemp.indexOf(',') !== -1) {
simpleTemp = simpleTemp.substr(0, simpleTemp.length - 1)
}
console.log(simpleTemp)
tableData.tableDateAll = simpleTemp
tableDates.push(tableData)
}

View File

@@ -81,7 +81,6 @@ export default {
methods: {
// 创建连接
create () {
console.log('create')
const that = this
if (this.terminalSocket) {
this.terminalSocket.close()
@@ -206,7 +205,6 @@ export default {
},
consoleResize () {
console.log('consoleResize')
this.$nextTick(() => {
this.termFitAddon.fit()
})

View File

@@ -86,25 +86,37 @@
:show-close="true" width="620px" class="nz-dialog" >
<div v-my-loading="dialogLoading">
<div class="login-dialog-title">
1 Download your preferred authenticator app to your phone (any will work). If you don't
<div class="login-dialog-title" v-if="lang=== 'en'">
1. Download your preferred authenticator app to your phone (any will work). If you don't
have a preferred app, we recommend using <span @click="jumpDlw" class="verify-link">Google Authenticator.</span>
</div>
<div class="login-dialog-title">
2 Use your app to take a photo of the QR code.
<div class="login-dialog-title" v-else-if="lang=== 'zh'">
1. 将您喜欢的验证器应用程序下载到您的手机上任何应用程序都可以
如果您没有首选应用程序我们建议您使用 <span @click="jumpDlw" class="verify-link">Google Authenticator.</span>
</div>
<div class="login-dialog-title" v-if="lang=== 'en'">
2. Use your app to take a photo of the QR code.
</div>
<div class="login-dialog-title" v-else-if="lang=== 'zh'">
2. 使用您的应用程序为二维码拍照
</div>
<div class="qrCode-box">
<div id="qrCode" ref="qrCodeDiv" class="qrCode-content"></div>
<div class="qrCode-text">
<div>Type this code down if you can't take a photo.</div>
<div v-if="lang=== 'en'">Type this code down if you can't take a photo.</div>
<div v-else-if="lang=== 'zh'">如果你不能拍照请键入此代码</div>
<div class="qrCode-authKey">{{authKey}}</div>
</div>
</div>
<div class="login-dialog-title">
<div class="login-dialog-title" v-if="lang=== 'en'">
3. Enter the 6-digit code provided by your app and then verify.
</div>
<div class="enter-code">Enter Code</div>
<div class="login-dialog-title" v-else-if="lang=== 'zh'">
3. 输入应用程序提供的6位数代码然后进行验证
</div>
<div class="enter-code" v-if="lang=== 'en'">Enter Code</div>
<div class="enter-code" v-else-if="lang=== 'zh'">输入代码</div>
<el-input v-model="bindAuthCode" size="small" style="width: 50%" @keydown.enter="bindCode"></el-input>
</div>
<div slot="footer" class="footer">
@@ -120,11 +132,15 @@
:show-close="true" width="620px" class="nz-dialog" >
<div>
<div class="login-dialog-title">
<div class="login-dialog-title" v-if="lang=== 'en'">
Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account.
Please save them in a safe place, or you will lose access to your account.
</div>
<div class="login-dialog-title2">
<div class="login-dialog-title" v-else-if="lang=== 'zh'">
如果您丢失了您的手机或一次性密码密码每个恢复代码都可以使用一次以重新访问您的帐户
请将它们保存在安全的地方否则您将无法访问您的帐户
</div>
<div class="login-dialog-title2" >
<div class="login-dialog-recover">
<div v-for="(item, index) in recoveryCode" :key="index" style="color: #999999;">
<span class="circle"></span>
@@ -142,9 +158,12 @@
</el-dialog>
<el-dialog :modal-append-to-body='false' :fullscreen="dialogQrType === 'all'" :show-close="true" :visible.sync="qrCodeShow" @close="closeQrCode" :title="'QR code'" class="nz-dialog overview" width="650px">
<div slot="title">
<span class="el-dialog__header-title">
<span class="el-dialog__header-title" v-if="lang=== 'en'">
QR code
</span>
<span class="el-dialog__header-title" v-else-if="lang=== 'zh'">
二维码
</span>
<div style="float: right; margin-right: 25px">
<el-button-group>
<el-button class="top-tool-btn" :class="{active: dialogQrType == 'item' }" size="small" @click="dialogQrType = 'item'"><i class="nz-icon nz-icon-dangemoshi"/></el-button>

View File

@@ -383,8 +383,7 @@ export default {
this.$set(this.$parent.showPanel, 'starred', this.starredList.some(item => item.id === this.showPanel.id) ? 1 : 0)
}
})
},
300, true),
}, 300, true),
// 删除收藏
delStarred: bus.debounceFn(function (data) {
this.$delete('/sys/user/starred?type=dashboard&tid=' + data.id).then(async response => {

View File

@@ -459,7 +459,6 @@ export default {
reader.onload = (evt) => { // 读取完文件之后会回来这里
let fileString = evt.target.result // 读取文件内容
fileString = JSON.parse(fileString)
console.log(fileString)
if (!fileString.topo) {
this.$message.error(this.$t('IMPORT_FORMAT_ERROR', { 0: '' }))
return
@@ -468,7 +467,6 @@ export default {
fileString.topo.pens.forEach(item => {
item.imageId = ''
})
console.log(fileString)
this.$post(this.importUrl, fileString).then(response => {
if (response.code == 200 && response.msg == 'success') {
this.$message.success(this.$t('overall.result.success'))

View File

@@ -332,7 +332,6 @@ export default {
this.renderTopology()
},
renderTopology () {
console.log('render')
getTopology(this.meta2dId).render()
},
penEnter (pen, e) { // 移入节点

View File

@@ -124,7 +124,22 @@
</div>
<!--inr-->
<el-form-item v-if="showSnmpTrap" :label="$t('alert.config.inr')" prop="inr" class="half-form-item">
<el-input-number :min="15" :max="86400" id="alert-box-input-inr" :controls="false" v-model="editAlertRule.inr" :placeholder="$t('alert.config.inrPlaceholder')" size="small" type="text" :disabled="!showSnmpTrap"></el-input-number>
<el-input-number
:min="15"
:max="86400"
id="alert-box-input-inr"
:controls="false"
v-model="editAlertRule.inr"
:placeholder="$t('alert.config.inrPlaceholder')"
size="small"
type="text"
:disabled="!showSnmpTrap"
class="append_unit"
:data-unit="$t('overall.seconds')"
>
</el-input-number>
</el-form-item>
<!--last-->
<el-form-item v-if="showSnmpTrap" :label="$t('alert.config.for')" prop="last" class="half-form-item alert-box-duration" :rules=" [
@@ -132,7 +147,7 @@
]"
>
<el-input id="alert-box-input-last" :controls="false" v-model.number="editAlertRule.last" placeholder="" size="small" :disabled="!showSnmpTrap" type="text">
<template slot="append">{{$t('alert.config.second')}}</template>
<template slot="append">{{$t('overall.seconds')}}</template>
</el-input>
</el-form-item>
<!--unit-->

View File

@@ -175,7 +175,7 @@
<vue-tags-input
v-model="tag"
:maxlength="32"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="chartConfig.param.tags"
@tags-changed="(newTags)=>{tagsChange(newTags)}"
/>

View File

@@ -75,7 +75,7 @@
<chart-config :variables="variables" ref="childrenFrommetrics" :type="'metrics'" v-if="editChart.datasource == 'metrics'" :params.sync="editChart" @change="editChartChange"/>
</el-tab-pane>
<el-tab-pane :label="$t('overall.logs')" name="logs">
<chart-config :variables="variables" ref="childrenFromlogs" :type="'log'" v-if="editChart.datasource == 'logs'" :params.sync="editChart" @change="editChartChange"/>
<chart-config :variables="variables" ref="childrenFromlogs" :type="'log'" v-if="editChart.datasource == 'logs'" :params.sync="editChart" @change="editChartChange" class="datasource-log"/>
</el-tab-pane>
<el-tab-pane :label="$t('overall.system')" name="system">
<system-chart-config :variables="variables" ref="childrenFromsystem" v-if="editChart.datasource == 'system'" :params.sync="editChart" @change="editChartChange"/>

View File

@@ -31,13 +31,13 @@ export default {
spanList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
unitOptions: chartDataFormat.unitOptions(),
nullTypeList: [{
label: 'connected',
label: this.$t('chart.connected'),
value: 'connected'
}, {
label: 'null',
label: this.$t('chart.null'),
value: 'null'
}, {
label: 'zero',
label: this.$t('chart.zero'),
value: 'zero'
}],
statisticsList: this.$CONSTANTS.statisticsList,

View File

@@ -189,7 +189,7 @@
<vue-tags-input
v-model="tag"
:maxlength="32"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="chartConfig.param.tags"
@tags-changed="(newTags)=>{tagsChange(newTags)}"
/>

View File

@@ -209,7 +209,7 @@
<vue-tags-input
v-model="item.tags"
:maxlength="32"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="item.value"
@tags-changed="(newTags)=>{tagsChange(newTags, index)}"
/>
@@ -271,7 +271,7 @@
:maxlength="32"
ref="relabelTag"
tabindex="9999"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="item.source_labels"
@before-adding-tag="beforeAddingTag"
@blur="relabelTabBlur"
@@ -440,7 +440,7 @@
<vue-tags-input
v-model="item.namespaces.tags"
:maxlength="32"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="item.namespaces.names"
@tags-changed="(newTags)=>{logsTagsChange(newTags,item)}"
/>
@@ -474,7 +474,7 @@
:maxlength="32"
:ref="'logsRelabelTag'+index+subIndex"
tabindex="9999"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="subItem.source_labels"
@before-adding-tag="beforeAddingTag"
@blur="logsRelabelTabBlur(index,subIndex)"

View File

@@ -188,7 +188,7 @@
<vue-tags-input
v-model="item.tags"
:maxlength="32"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="item.value"
@tags-changed="(newTags)=>{tagsChange(newTags, index)}"
/>
@@ -250,7 +250,7 @@
:maxlength="32"
ref="relabelTag"
tabindex="9999"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="item.source_labels"
@before-adding-tag="beforeAddingTag"
@blur="relabelTabBlur"
@@ -421,7 +421,7 @@
<vue-tags-input
v-model="item.namespaces.tags"
:maxlength="32"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="item.namespaces.names"
@tags-changed="(newTags)=>{logsTagsChange(newTags,item)}"
/>
@@ -475,7 +475,7 @@
:maxlength="32"
:ref="'logsRelabelTag'+index+subIndex"
tabindex="9999"
:placeholder="$t('overall.addParameter')"
:placeholder="$t('tagsInput.placeholder')"
:tags="subItem.source_labels"
@before-adding-tag="beforeAddingTag"
@blur="logsRelabelTabBlur(index,subIndex)"

View File

@@ -145,7 +145,6 @@ export default {
} else {
this.$emit('clickProfile', false)
}
console.log(this.editProfile)
localStorage.setItem('nz-userInfo', JSON.stringify(this.editProfile))
bus.$emit('login')
} else {

View File

@@ -69,7 +69,20 @@
</el-form-item>
<!-- inr -->
<el-form-item :label='$t("config.assetLabel.interval")' prop="inr">
<el-input v-model="editRecordRule.inr" maxlength="10" show-word-limit :placeholder="''" size="small"></el-input>
<el-input-number
v-model="editRecordRule.inr"
size="small"
style="width: 100%"
:placeholder="$t('recordRule.defalutInterval')"
:max="9999999999"
:precision="0"
:min="0"
:controls="false"
class="append_unit"
:data-unit="$t('overall.seconds')"
@change="changeInr"
>
</el-input-number>
</el-form-item>
<!--state-->
<el-form-item :label="$t('overall.state')" prop="state" >
@@ -196,7 +209,7 @@ export default {
...this.editRecordRule,
state: Number(this.editRecordRule.state),
type: Number(this.editRecordRule.type),
inr: Number(this.editRecordRule.inr),
inr: this.editRecordRule.inr ? Number(this.editRecordRule.inr) : '',
labels: this.editRecordRule.labels[0].label != '' ? JSON.stringify(obj) : '{}'
}
@@ -264,6 +277,13 @@ export default {
return result
}
return obj
},
changeInr () {
if (!this.editRecordRule.inr) {
setTimeout(() => {
this.editRecordRule.inr = undefined
}, 100)
}
}
},
watch: {
@@ -276,7 +296,7 @@ export default {
this.editRecordRule = {
...editObj,
type: editObj.type + '',
inr: editObj.inr + '',
inr: isNaN(editObj.inr) || !editObj.inr ? undefined : editObj.inr,
labels: typeof editObj.labels != 'object' ? this.labelsSort(editObj.labels) : editObj.labels,
state: editObj.state + ''
}

View File

@@ -21,9 +21,6 @@
</el-select>
</el-form-item>
<el-form-item :label='$t("asset.asset")' label-width="125px" prop="assetId" v-if="!disabled">
<!-- <el-select id="module-box-input-asset" @change="renderEndpoint" v-model="editEndpoint.assetId" :disabled="disabled" class="right-box__select" placeholder="" popper-class="right-box-select-top right-public-box-dropdown-top prevent-clickoutside" size="small" value-key="id">-->
<!-- <el-option v-for="item in assetList" :id="'asset-'+item.id" :key="item.id" :label="item.name" :value="item.id"></el-option>-->
<!-- </el-select>-->
<v-selectpage
:data="assetList"
:tb-columns="columns"
@@ -57,6 +54,92 @@
<div class="form__sub-title" >
<span>{{$t('softwareAsset.Connector')}}</span>
</div>
<!-- <el-form-item v-for="(value, key) in editSoftwareAsset.params" :label="key" :key="key">-->
<!-- <el-input maxlength="128" show-word-limit v-model="editSoftwareAsset.params[key]" size="small" type="text" @input="$forceUpdate()"></el-input>-->
<!-- </el-form-item>-->
<el-form-item prop="paramObj">
<div v-for="(label, i) in editSoftwareAsset.paramObj" :key="i" class="form__dotted-item form__dotted-item-required">
<el-form-item :prop="'paramObj.' + i + '.value.0'" :rules="[ { required: JSON.parse(label.param).required === '1', message: $t('validate.required'), trigger: 'blur' }]">
<template v-slot:label>
<div class="form__labels-label">
<span>{{label.name}}</span>
</div>
</template>
<template v-if="label.action !== 1">
<template v-if="label.type.toUpperCase() === assetConstants.labelTypeData.TEXT">
<el-input v-model="label.value[0]" size="small"/>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.PASSWORD">
<el-input v-model="label.value[0]" type="password" size="small"/>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.TEXTAREA">
<el-input v-model="label.value[0]" :maxlength="4096" show-word-limit size="small" :rows="2" type="textarea"/>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.RADIO">
<el-radio-group v-model="label.value[0]">
<el-radio v-for="item in JSON.parse(label.param).items" :key="item.name" :label="item.name">{{item.name}}</el-radio>
</el-radio-group>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.CHECKBOX">
<el-checkbox-group v-model="label.value">
<el-checkbox v-for="item in JSON.parse(label.param).items" :key="item.name" :label="item.name" :value="item.name"></el-checkbox>
</el-checkbox-group>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.SELECT">
<el-select v-model="label.value[0]" class="right-box__select" :placeholder="$t('el.select.placeholder')" popper-class="right-box-select-top prevent-clickoutside" size="small">
<el-option v-for="item in JSON.parse(label.param).items" :key="item.name" :label="item.name" :value="item.name"></el-option>
</el-select>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.INTEGER">
<el-input v-model="label.value[0]" oninput="value=value.replace(/[^\d]/g,'')" size="small"></el-input>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.DOUBLE">
<el-input-number v-model="label.value[0]" :controls="false" size="small" :precision="JSON.parse(label.param).decimals" style="width: 100%;text-align: left" :max="10000000000000000000" :min="-10000000000000000000"></el-input-number>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.DATETIME">
<template v-if="JSON.parse(label.param).subType === assetConstants.labelSubTypeData.time">
<div v-if="JSON.parse(label.param).interval" style="display: flex; justify-content: space-between">
<el-time-select v-model="label.value[0]" size="small"></el-time-select>
<el-time-select v-model="label.value[1]" size="small"></el-time-select>
</div>
<template v-else>
<el-time-select v-model="label.value[0]" size="small" style="width: 100%"></el-time-select>
</template>
</template>
<template v-else>
<template v-if="JSON.parse(label.param).interval">
<my-date-picker
id="asset-box-input-purchase-date"
v-model="label.value"
:type="JSON.parse(label.param).subType === assetConstants.labelSubTypeData.date ? 'daterange' : 'datetimerange'"
placeholder=""
popper-class="right-box-select-top"
size="small"
:format="timeFormatStrToDatePickFormat(timeFormatMain,JSON.parse(label.param).subType === assetConstants.labelSubTypeData.date)"
style="width: 100%">
</my-date-picker>
</template>
<template v-else>
<my-date-picker
id="asset-box-input-parchase-date"
v-model="label.value[0]"
:type="JSON.parse(label.param).subType"
placeholder=""
popper-class="right-box-select-top"
size="small"
style="width: 100%"
:format="timeFormatStrToDatePickFormat(timeFormatMain, JSON.parse(label.param).subType === assetConstants.labelSubTypeData.date)">
</my-date-picker>
</template>
</template>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.EMAIL">
<el-input v-model="label.value[0]" size="small"/>
</template>
</template>
</el-form-item>
</div>
</el-form-item>
</el-form>
</div>
</div>
@@ -100,6 +183,7 @@ export default {
const vm = this
return {
assetConstants,
disabled: false,
editSoftwareAsset: {
id: '',
name: '',
@@ -157,7 +241,7 @@ export default {
return row.dc ? row.dc.name : ''
}
}
],
]
}
},
watch: {
@@ -167,9 +251,16 @@ export default {
handler (n) {
this.isEdit = true
const editSoftwareAsset = JSON.parse(JSON.stringify(n))
editSoftwareAsset.paramObj = []
// if (editSoftwareAsset.params) {
// Object.keys(editSoftwareAsset.params).forEach(key => {
// editSoftwareAsset.paramObj.push(editSoftwareAsset.params[key])
// })
// }
editSoftwareAsset.assetId = ''
this.editSoftwareAsset = editSoftwareAsset
}
},
}
},
created () {
this.getProjectList()
@@ -177,13 +268,15 @@ export default {
this.getSoftwareTypeList()
},
mounted () {
setTimeout(() => {
this.editSoftwareAsset.assetId = this.obj.assetId + ''
}, 500)
},
methods: {
clickOutside () {
this.esc(false)
},
iconActive (subItem) {
console.log(subItem, this.editSoftwareAsset.icon)
if (this.editSoftwareAsset.icon === subItem.value) {
this.editSoftwareAsset.icon = undefined
this.$set(this.editSoftwareAsset, 'icon', '')
@@ -203,11 +296,17 @@ export default {
const params = {
...this.editSoftwareAsset
}
params.icon = this.imageUrl
params.params = {}
params.paramObj.forEach(item => {
params.params[item.name] = item
if (item.type === 'CHECKBOX') {
params.params[item.name] = item.value
} else if (item.type === 'DATETIME' && JSON.parse(item.param).interval) {
params.params[item.name] = item.value
} else {
params.params[item.name] = item.value[0]
}
})
params.icon = this.imageUrl
if (this.editSoftwareAsset.id) {
this.$put(this.url, params).then(res => {
this.prevent_opt.save = false
@@ -254,6 +353,9 @@ export default {
this.$get('asset/software/type', { pageSize: -1, pageNo: 1 }).then(response => {
if (response.code === 200) {
this.softwareTypeArr = response.data.list
if (this.editSoftwareAsset.typeId) {
this.renderParams()
}
}
})
},
@@ -266,7 +368,20 @@ export default {
}
},
renderParams () {
this.editSoftwareAsset.params = {}
this.editSoftwareAsset.paramObj = []
const findItem = this.softwareTypeArr.find(item => item.id == this.editSoftwareAsset.typeId)
if (findItem.params) {
Object.keys(findItem.params).forEach(key => {
if (findItem.params[key].type === 'CHECKBOX') {
findItem.params[key].value = this.editSoftwareAsset.params[key] ? this.editSoftwareAsset.params[key] : findItem.params[key].value
} else if (findItem.params[key].type === 'DATETIME' && JSON.parse(findItem.params[key].param).interval) {
findItem.params[key].value = this.editSoftwareAsset.params[key] ? this.editSoftwareAsset.params[key] : findItem.params[key].value
} else {
findItem.params[key].value = this.editSoftwareAsset.params[key] ? [this.editSoftwareAsset.params[key]] : findItem.params[key].value
}
this.editSoftwareAsset.paramObj.push(findItem.params[key])
})
}
}
}
}

View File

@@ -293,7 +293,6 @@ export default {
})
},
iconActive (subItem) {
console.log(subItem, this.editSoftwareType.icon)
if (this.editSoftwareType.icon === subItem.value) {
this.editSoftwareType.icon = undefined
this.$set(this.editSoftwareType, 'icon', '')

View File

@@ -1113,6 +1113,9 @@ export default {
if (this.targetTab) {
switch (this.targetTab) {
case 'alertMessageTab':
case 'moduleAlertMessage':
case 'endpointAlertMessage':
case 'alertRuleAlertMessage':
return 'alertmessage'
}
}

View File

@@ -67,6 +67,9 @@
<i v-if="scope.row[item.prop].name" class="nz-icon nz-icon-override" style="visibility: hidden" @click="onCopy(scope.row[item.prop].name)" :title="$t('overall.copyText')"></i>
</div>
</template>
<template v-else-if="item.prop === 'type'">
{{scope.row.type ? scope.row.type.name : '-'}}
</template>
<span v-else-if="scope.row[item.prop]" :class="item.prop === 'remark'? 'el-table-remark':''">{{scope.row[item.prop]}}</span>
<span v-else>-</span>
</template>

View File

@@ -52,10 +52,10 @@
</div>
</span>
<template v-else-if="item.prop === 'cts'">
<template>{{scope.row[item.prop] ? utcTimeToTimezoneStr(scope.row[item.prop]) : '-'}}</template>
<template>{{scope.row[item.prop] ? momentTz(scope.row[item.prop]) : '-'}}</template>
</template>
<template v-else-if="item.prop === 'uts'">
<template>{{scope.row[item.prop] ? utcTimeToTimezoneStr(scope.row[item.prop]) : '-'}}</template>
<template>{{scope.row[item.prop] ? momentTz(scope.row[item.prop]) : '-'}}</template>
</template>
<div v-else-if="item.prop === 'icon'"
@mouseenter="labelHover(scope.row, 'icon', true, false, $event)"

View File

@@ -226,7 +226,6 @@ export default {
if (timePickerLocked) {
const timePickerRange = localStorage.getItem('nz-time-picker-range') ? JSON.parse(localStorage.getItem('nz-time-picker-range')) : {}
this.$store.dispatch('dispatchTimePickerRange', timePickerRange)
console.log('mounted', timePickerRange, this.timePickerLocked)
}
this.$store.dispatch('dispatchTimePickerLocked', timePickerLocked)
},
@@ -353,7 +352,6 @@ export default {
localStorage.setItem('nz-time-picker-locked', JSON.stringify(this.timePickerLocked))
this.$store.dispatch('dispatchTimePickerLocked', this.timePickerLocked)
if (this.timePickerLocked) {
console.log(this.searchTime, this.nowTimeType)
this.$store.dispatch('dispatchTimePickerRange', {
time: this.searchTime,
nowTimeType: this.nowTimeType
@@ -381,10 +379,14 @@ export default {
this.oldSearchTime[1] = bus.timeFormate(this.oldSearchTime[1])
}
}
if (moment(this.oldSearchTime[0], timeFormatMain).isValid() && moment(this.oldSearchTime[1], timeFormatMain).isValid() && !moment(this.oldSearchTime[0]).isBefore(this.oldSearchTime[1])) {
let isBefore = true
if (moment(this.oldSearchTime[0], timeFormatMain).isValid() && moment(this.oldSearchTime[1], timeFormatMain).isValid()) {
isBefore = this.momentStrToTimestamp(this.oldSearchTime[0]) < this.momentStrToTimestamp(this.oldSearchTime[1])
}
if (moment(this.oldSearchTime[0], timeFormatMain).isValid() && moment(this.oldSearchTime[1], timeFormatMain).isValid() && !isBefore) {
this.oldSearchTimeError[0] = true
this.inputError = this.$t('date.fromGreaterTo')
} else if (moment(this.oldSearchTime[0], timeFormatMain).isValid() && moment(this.oldSearchTime[1], timeFormatMain).isValid() && moment(this.oldSearchTime[0]).isBefore(this.oldSearchTime[1])) {
} else if (moment(this.oldSearchTime[0], timeFormatMain).isValid() && moment(this.oldSearchTime[1], timeFormatMain).isValid() && isBefore) {
this.oldSearchTimeError[0] = false
}
},

View File

@@ -78,6 +78,7 @@ import bus from '../../libs/bus'
import { mapActions } from 'vuex'
import guide from '@/components/common/popBox/guide'
import intro from '@/components/common/intro'
import { theme } from '@/components/common/js/constants'
export default {
name: 'Header',
components: {
@@ -171,12 +172,28 @@ export default {
})
},
changeLocal (lang) {
localStorage.setItem('nz-language', lang)
this.$store.commit('setLanguage', lang)
this.$i18n.locale = lang
setTimeout(() => {
window.location.reload()
}, 800)
this.$get('/sys/user/profile').then(response => {
if (response.code === 200) {
const userInfo = response.user
userInfo.roleIds = userInfo.roles[0].id
userInfo.lang = lang
this.$put('sys/user/profile', userInfo).then(res => {
this.prevent_opt.save = false
if (res.code === 200) {
localStorage.setItem('nz-language', lang)
this.$store.commit('setLanguage', lang)
this.$i18n.locale = lang
setTimeout(() => {
window.location.reload()
}, 800)
} else {
this.$message.error(res.msg)
}
})
} else {
this.$message.error(response.msg)
}
})
},
logout () {
this.$get('logout').then(() => {

View File

@@ -155,7 +155,6 @@ export default {
if (timePickerLocked) {
const timePickerRange = localStorage.getItem('nz-time-picker-range') ? JSON.parse(localStorage.getItem('nz-time-picker-range')) : {}
this.$store.dispatch('dispatchTimePickerRange', timePickerRange)
console.log('mounted', timePickerRange, this.timePickerLocked)
}
this.$store.dispatch('dispatchTimePickerLocked', timePickerLocked)
}

View File

@@ -457,7 +457,6 @@ export default {
if (!q.startAt) {
this.searchTime[2] = 'all'
}
console.log(this.searchTime[2], this.searchTime[0], this.searchTime[1])
switch (this.searchTime[2]) {
case '5m' :
this.defaultPick = 1
@@ -864,7 +863,6 @@ export default {
const path = this.fromRoute.alertMessage
const routePathParams = this.$lodash.cloneDeep(param)
delete routePathParams.statistics
console.log(this.searchTime)
routePathParams.body.startAt = this.searchTime[0] ? this.momentStrToTimestamp(this.searchTime[0]) : ''
routePathParams.body.endAt = this.searchTime[1] ? this.momentStrToTimestamp(this.searchTime[1]) : ''
routePathParams.body.timeType = this.searchTime[2]

View File

@@ -70,6 +70,7 @@
</el-form-item>
<el-form-item class="half-form-item">
<button :class="{'nz-btn-disabled':downloadAgentFlag}" :disabled="downloadAgentFlag" class="nz-btn nz-btn-size-normal nz-btn-style-normal" type="button" @click="downloadAgent">{{$t('overall.download')}}</button>
<span class="downloading" v-if="downloadAgentFlag">{{$t('overall.downloading')}}</span>
</el-form-item>
<div class="right-box-sub-title">{{$t('config.agent.agent.autoScript')}}</div>
<div style="margin-bottom: 20px;width: 100%"></div>

View File

@@ -32,7 +32,7 @@
v-model="tag"
:maxlength="32"
:class="monitor.interface_name.length !== 0 ? 'interface-name' : ''"
:placeholder="$t('overall.add.interface_name')"
:placeholder="$t('tagsInput.placeholder')"
:tags="monitor.interface_name"
@tags-changed="newTags=> monitor.interface_name = newTags"
/>

View File

@@ -76,25 +76,37 @@
:show-close="true" width="620px" class="nz-dialog" @closed="closeDialog">
<div v-my-loading="dialogLoading">
<div class="login-dialog-title">
1 Download your preferred authenticator app to your phone (any will work). If you don't
<div class="login-dialog-title" v-if="lang === 'en'">
1. Download your preferred authenticator app to your phone (any will work). If you don't
have a preferred app, we recommend using <span @click="jumpDlw" class="verify-link">Google Authenticator.</span>
</div>
<div class="login-dialog-title">
2 Use your app to take a photo of the QR code.
<div class="login-dialog-title" v-else-if="lang=== 'zh'">
1. 将您喜欢的验证器应用程序下载到您的手机上任何应用程序都可以
如果您没有首选应用程序我们建议您使用 <span @click="jumpDlw" class="verify-link">Google Authenticator.</span>
</div>
<div class="login-dialog-title" v-if="lang=== 'en'">
2. Use your app to take a photo of the QR code.
</div>
<div class="login-dialog-title" v-else-if="lang=== 'zh'">
2. 使用您的应用程序为二维码拍照
</div>
<div class="qrCode-box">
<div id="qrCode" ref="qrCodeDiv" class="qrCode-content"></div>
<div class="qrCode-text">
<div>Type this code down if you can't take a photo.</div>
<div v-if="lang=== 'en'">Type this code down if you can't take a photo.</div>
<div v-else-if="lang=== 'zh'">如果你不能拍照请键入此代码</div>
<div class="qrCode-authKey">{{authKey}}</div>
</div>
</div>
<div class="login-dialog-title">
<div class="login-dialog-title" v-if="lang=== 'en'">
3. Enter the 6-digit code provided by your app and then verify.
</div>
<div class="enter-code">Enter Code</div>
<div class="login-dialog-title" v-else-if="lang=== 'zh'">
3. 输入应用程序提供的6位数代码然后进行验证
</div>
<div class="enter-code" v-if="lang=== 'en'">Enter Code</div>
<div class="enter-code" v-else-if="lang=== 'zh'">输入代码</div>
<el-input v-model="bindAuthCode" size="small" style="width: 50%" @keydown.enter="bindCode"></el-input>
</div>
<div slot="footer" class="footer">
@@ -108,10 +120,14 @@
</el-dialog>
<el-dialog :visible.sync="fileShow" :title="$t('login.verifyDialogTitle')" :modal-append-to-body='false' :show-close="true" width="620px" class="nz-dialog" @closed="fileClosed">
<div>
<div class="login-dialog-title">
<div class="login-dialog-title" v-if="lang=== 'en'">
Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account.
Please save them in a safe place, or you will lose access to your account.
</div>
<div class="login-dialog-title" v-else-if="lang=== 'zh'">
如果您丢失了您的手机或一次性密码密码每个恢复代码都可以使用一次以重新访问您的帐户
请将它们保存在安全的地方否则您将无法访问您的帐户
</div>
<div class="login-dialog-title2">
<div class="login-dialog-recover">
<div v-for="(item, index) in recoveryCode" :key="index">
@@ -214,6 +230,7 @@ export default {
],
// 后台数据
userList: {},
lang: this.$store.getters.getLanguage || 'en',
// 头像 name
profileName: '',
rules: {

View File

@@ -39,10 +39,10 @@
<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>&nbsp;&nbsp;&nbsp;&nbsp; Notification account</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; Alert message(json)
<div>. {{$t('noftiyMethod.permissions')}}</div>
<div>. {{$t('noftiyMethod.parameters')}}</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; {{$t('noftiyMethod.account')}}</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; {{$t('noftiyMethod.json')}}
<el-tooltip placement="top" effect="light">
<pre slot="content" style="word-break: break-all">
{

View File

@@ -3535,6 +3535,8 @@ import logTab from './logTab'
import promqlInputMixin from '@/components/common/mixin/promqlInput'
import chartRightBox from '@/components/common/rightBox/chart/chartRightBox'
import copy from '@/components/common/copy'
import './promqlparser/wasm_exec.js'
export default {
name: 'exploreItem',
components: {
@@ -3624,19 +3626,33 @@ export default {
scrollbarWrap: null
}
},
created () {
async created () {
this.getPanelData()
this.resetExpression()
await this.loadWebAssembly()
this.initQueryFromPath()
},
mounted () {
this.scrollbarWrap = this.$refs.exploreScrollbar
this.scrollbarWrap.addEventListener('scroll', this.onScroll)
this.initQueryFromPath()
},
beforeDestroy () {
this.scrollbarWrap.removeEventListener('scroll', this.onScroll)
},
methods: {
async loadWebAssembly () {
try {
// eslint-disable-next-line no-undef
const go = new Go()
const result = await WebAssembly.instantiateStreaming(fetch('/static/wasm/promqlparser.wasm'), go.importObject)
go.run(result.instance)
// eslint-disable-next-line no-undef
this.parsePromQL = parsePromQL
} catch (error) {
console.error(error)
}
},
parsePromQL () {},
onScroll: bus.debounce(function () {
this.showTopBtn = this.scrollbarWrap.scrollTop > 50
}, 300),
@@ -3658,7 +3674,6 @@ export default {
},
setTimePickerRange () {
this.$nextTick(() => {
console.log(this.timePickerLocked, !this.timePickerRange.nowTimeType)
if (!this.timePickerLocked || !this.timePickerRange.nowTimeType) {
return
}
@@ -3953,7 +3968,7 @@ export default {
} else {
if (response.error) {
this.$refs['promql-' + promqlIndex][0].setError(response.error)
} else if(response.msg) {
} else if (response.msg) {
this.$refs['promql-' + promqlIndex][0].setError(response.msg)
} else {
this.$refs['promql-' + promqlIndex][0].setError(response)
@@ -4102,6 +4117,24 @@ export default {
this.setSearchTime(nowTimeType.type, nowTimeType.value)
}
if (this.expressions && this.expressions.length >= 1) {
let error = false
// 对 promql 格式校验及format
if (this.showMetrics) {
this.expressions.forEach((item, index) => {
if (item != '' && this.promqlKeys[index].state) {
const res = this.parsePromQL(item)
if (res.status === 'error') {
error = true
this.$refs['promql-' + index][0].setError(res.message)
} else {
this.$set(this.expressions, index, res.result)
this.$refs['promql-' + index][0].prettyCode()
this.$refs['promql-' + index][0].setError('')
}
}
})
}
if (error) { return }
if (this.showMetrics) {
this.queryTableData()
this.queryChartData()

View File

@@ -163,12 +163,13 @@
>
<el-dropdown
class="metric-selector"
style="width: 100%"
v-if="plugins.indexOf('metric-selector') > -1"
>
<el-dropdown-menu style="display: none"></el-dropdown-menu>
<span
:class="{ 'expr-title': projectRightBox }"
style="cursor: pointer"
style="cursor: pointer;width: 100%;display: inline-block"
@click="toggleDropdown"
>{{
type === "log"
@@ -1157,10 +1158,20 @@ export default {
this.expressionList[this.index] = insertTxt
this.codeMirrorValue[this.index] = insertTxt
this.initCodeMirror()
}
},
/* setMsg:function(){
this.appendMsg
} */
prettyCode () {
this.$nextTick(() => {
const text = this.newView.state.doc.toString()
this.newView.dispatch(
this.newView.state.update({
changes: { from: 0, to: text.length, insert: this.codeMirrorValue[this.index] }
})
)
})
}
},
watch: {
dropDownVisible (n, o) {

View File

@@ -0,0 +1,30 @@
module test.go
go 1.20
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dennwc/varint v1.0.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.0 // indirect
github.com/prometheus/prometheus v0.46.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/goleak v1.2.1 // indirect
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect
golang.org/x/sys v0.10.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -0,0 +1,91 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE=
github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww=
github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk=
github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/prometheus/prometheus v0.46.0 h1:9JSdXnsuT6YsbODEhSQMwxNkGwPExfmzqG73vCMk/Kw=
github.com/prometheus/prometheus v0.46.0/go.mod h1:10L5IJE5CEsjee1FnOcVswYXlPIscDWWt3IJ2UDYrz4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,33 @@
// 编译为wasm文件 在页面中引入
package main
import (
"syscall/js"
"github.com/prometheus/prometheus/promql/parser"
)
func parsePromQL(this js.Value, args []js.Value) interface{} {
promql := args[0].String()
expr, err := parser.ParseExpr(promql)
if err != nil {
return map[string]interface{}{
"status": "error",
"message": err.Error(),
}
}
return map[string]interface{}{
"status": "success",
"result": expr.Pretty(0),
}
}
func main() {
c := make(chan struct{}, 0)
// 注册函数
js.Global().Set("parsePromQL", js.FuncOf(parsePromQL))
<-c
}

View File

@@ -0,0 +1,554 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
'use strict';
(() => {
const enosys = () => {
const err = new Error('not implemented')
err.code = 'ENOSYS'
return err
}
if (!globalThis.fs) {
let outputBuf = ''
globalThis.fs = {
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
writeSync (fd, buf) {
outputBuf += decoder.decode(buf)
const nl = outputBuf.lastIndexOf('\n')
if (nl != -1) {
console.log(outputBuf.substring(0, nl))
outputBuf = outputBuf.substring(nl + 1)
}
return buf.length
},
write (fd, buf, offset, length, position, callback) {
if (offset !== 0 || length !== buf.length || position !== null) {
callback(enosys())
return
}
const n = this.writeSync(fd, buf)
callback(null, n)
},
chmod (path, mode, callback) { callback(enosys()) },
chown (path, uid, gid, callback) { callback(enosys()) },
close (fd, callback) { callback(enosys()) },
fchmod (fd, mode, callback) { callback(enosys()) },
fchown (fd, uid, gid, callback) { callback(enosys()) },
fstat (fd, callback) { callback(enosys()) },
fsync (fd, callback) { callback(null) },
ftruncate (fd, length, callback) { callback(enosys()) },
lchown (path, uid, gid, callback) { callback(enosys()) },
link (path, link, callback) { callback(enosys()) },
lstat (path, callback) { callback(enosys()) },
mkdir (path, perm, callback) { callback(enosys()) },
open (path, flags, mode, callback) { callback(enosys()) },
read (fd, buffer, offset, length, position, callback) { callback(enosys()) },
readdir (path, callback) { callback(enosys()) },
readlink (path, callback) { callback(enosys()) },
rename (from, to, callback) { callback(enosys()) },
rmdir (path, callback) { callback(enosys()) },
stat (path, callback) { callback(enosys()) },
symlink (path, link, callback) { callback(enosys()) },
truncate (path, length, callback) { callback(enosys()) },
unlink (path, callback) { callback(enosys()) },
utimes (path, atime, mtime, callback) { callback(enosys()) }
}
}
if (!globalThis.process) {
globalThis.process = {
getuid () { return -1 },
getgid () { return -1 },
geteuid () { return -1 },
getegid () { return -1 },
getgroups () { throw enosys() },
pid: -1,
ppid: -1,
umask () { throw enosys() },
cwd () { throw enosys() },
chdir () { throw enosys() }
}
}
if (!globalThis.crypto) {
throw new Error('globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)')
}
if (!globalThis.performance) {
throw new Error('globalThis.performance is not available, polyfill required (performance.now only)')
}
if (!globalThis.TextEncoder) {
throw new Error('globalThis.TextEncoder is not available, polyfill required')
}
if (!globalThis.TextDecoder) {
throw new Error('globalThis.TextDecoder is not available, polyfill required')
}
const encoder = new TextEncoder('utf-8')
const decoder = new TextDecoder('utf-8')
globalThis.Go = class {
constructor () {
this.argv = ['js']
this.env = {}
this.exit = (code) => {
if (code !== 0) {
console.warn('exit code:', code)
}
}
this._exitPromise = new Promise((resolve) => {
this._resolveExitPromise = resolve
})
this._pendingEvent = null
this._scheduledTimeouts = new Map()
this._nextCallbackTimeoutID = 1
const setInt64 = (addr, v) => {
this.mem.setUint32(addr + 0, v, true)
this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true)
}
const getInt64 = (addr) => {
const low = this.mem.getUint32(addr + 0, true)
const high = this.mem.getInt32(addr + 4, true)
return low + high * 4294967296
}
const loadValue = (addr) => {
const f = this.mem.getFloat64(addr, true)
if (f === 0) {
return undefined
}
if (!isNaN(f)) {
return f
}
const id = this.mem.getUint32(addr, true)
return this._values[id]
}
const storeValue = (addr, v) => {
const nanHead = 0x7FF80000
if (typeof v === 'number' && v !== 0) {
if (isNaN(v)) {
this.mem.setUint32(addr + 4, nanHead, true)
this.mem.setUint32(addr, 0, true)
return
}
this.mem.setFloat64(addr, v, true)
return
}
if (v === undefined) {
this.mem.setFloat64(addr, 0, true)
return
}
let id = this._ids.get(v)
if (id === undefined) {
id = this._idPool.pop()
if (id === undefined) {
id = this._values.length
}
this._values[id] = v
this._goRefCounts[id] = 0
this._ids.set(v, id)
}
this._goRefCounts[id]++
let typeFlag = 0
switch (typeof v) {
case 'object':
if (v !== null) {
typeFlag = 1
}
break
case 'string':
typeFlag = 2
break
case 'symbol':
typeFlag = 3
break
case 'function':
typeFlag = 4
break
}
this.mem.setUint32(addr + 4, nanHead | typeFlag, true)
this.mem.setUint32(addr, id, true)
}
const loadSlice = (addr) => {
const array = getInt64(addr + 0)
const len = getInt64(addr + 8)
return new Uint8Array(this._inst.exports.mem.buffer, array, len)
}
const loadSliceOfValues = (addr) => {
const array = getInt64(addr + 0)
const len = getInt64(addr + 8)
const a = new Array(len)
for (let i = 0; i < len; i++) {
a[i] = loadValue(array + i * 8)
}
return a
}
const loadString = (addr) => {
const saddr = getInt64(addr + 0)
const len = getInt64(addr + 8)
return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len))
}
const timeOrigin = Date.now() - performance.now()
this.importObject = {
go: {
// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
// may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
// function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
// This changes the SP, thus we have to update the SP used by the imported function.
// func wasmExit(code int32)
'runtime.wasmExit': (sp) => {
sp >>>= 0
const code = this.mem.getInt32(sp + 8, true)
this.exited = true
delete this._inst
delete this._values
delete this._goRefCounts
delete this._ids
delete this._idPool
this.exit(code)
},
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
'runtime.wasmWrite': (sp) => {
sp >>>= 0
const fd = getInt64(sp + 8)
const p = getInt64(sp + 16)
const n = this.mem.getInt32(sp + 24, true)
fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n))
},
// func resetMemoryDataView()
'runtime.resetMemoryDataView': (sp) => {
sp >>>= 0
this.mem = new DataView(this._inst.exports.mem.buffer)
},
// func nanotime1() int64
'runtime.nanotime1': (sp) => {
sp >>>= 0
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000)
},
// func walltime() (sec int64, nsec int32)
'runtime.walltime': (sp) => {
sp >>>= 0
const msec = (new Date()).getTime()
setInt64(sp + 8, msec / 1000)
this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true)
},
// func scheduleTimeoutEvent(delay int64) int32
'runtime.scheduleTimeoutEvent': (sp) => {
sp >>>= 0
const id = this._nextCallbackTimeoutID
this._nextCallbackTimeoutID++
this._scheduledTimeouts.set(id, setTimeout(
() => {
this._resume()
while (this._scheduledTimeouts.has(id)) {
// for some reason Go failed to register the timeout event, log and try again
// (temporary workaround for https://github.com/golang/go/issues/28975)
console.warn('scheduleTimeoutEvent: missed timeout event')
this._resume()
}
},
getInt64(sp + 8) + 1 // setTimeout has been seen to fire up to 1 millisecond early
))
this.mem.setInt32(sp + 16, id, true)
},
// func clearTimeoutEvent(id int32)
'runtime.clearTimeoutEvent': (sp) => {
sp >>>= 0
const id = this.mem.getInt32(sp + 8, true)
clearTimeout(this._scheduledTimeouts.get(id))
this._scheduledTimeouts.delete(id)
},
// func getRandomData(r []byte)
'runtime.getRandomData': (sp) => {
sp >>>= 0
crypto.getRandomValues(loadSlice(sp + 8))
},
// func finalizeRef(v ref)
'syscall/js.finalizeRef': (sp) => {
sp >>>= 0
const id = this.mem.getUint32(sp + 8, true)
this._goRefCounts[id]--
if (this._goRefCounts[id] === 0) {
const v = this._values[id]
this._values[id] = null
this._ids.delete(v)
this._idPool.push(id)
}
},
// func stringVal(value string) ref
'syscall/js.stringVal': (sp) => {
sp >>>= 0
storeValue(sp + 24, loadString(sp + 8))
},
// func valueGet(v ref, p string) ref
'syscall/js.valueGet': (sp) => {
sp >>>= 0
const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16))
sp = this._inst.exports.getsp() >>> 0 // see comment above
storeValue(sp + 32, result)
},
// func valueSet(v ref, p string, x ref)
'syscall/js.valueSet': (sp) => {
sp >>>= 0
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32))
},
// func valueDelete(v ref, p string)
'syscall/js.valueDelete': (sp) => {
sp >>>= 0
Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16))
},
// func valueIndex(v ref, i int) ref
'syscall/js.valueIndex': (sp) => {
sp >>>= 0
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)))
},
// valueSetIndex(v ref, i int, x ref)
'syscall/js.valueSetIndex': (sp) => {
sp >>>= 0
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24))
},
// func valueCall(v ref, m string, args []ref) (ref, bool)
'syscall/js.valueCall': (sp) => {
sp >>>= 0
try {
const v = loadValue(sp + 8)
const m = Reflect.get(v, loadString(sp + 16))
const args = loadSliceOfValues(sp + 32)
const result = Reflect.apply(m, v, args)
sp = this._inst.exports.getsp() >>> 0 // see comment above
storeValue(sp + 56, result)
this.mem.setUint8(sp + 64, 1)
} catch (err) {
sp = this._inst.exports.getsp() >>> 0 // see comment above
storeValue(sp + 56, err)
this.mem.setUint8(sp + 64, 0)
}
},
// func valueInvoke(v ref, args []ref) (ref, bool)
'syscall/js.valueInvoke': (sp) => {
sp >>>= 0
try {
const v = loadValue(sp + 8)
const args = loadSliceOfValues(sp + 16)
const result = Reflect.apply(v, undefined, args)
sp = this._inst.exports.getsp() >>> 0 // see comment above
storeValue(sp + 40, result)
this.mem.setUint8(sp + 48, 1)
} catch (err) {
sp = this._inst.exports.getsp() >>> 0 // see comment above
storeValue(sp + 40, err)
this.mem.setUint8(sp + 48, 0)
}
},
// func valueNew(v ref, args []ref) (ref, bool)
'syscall/js.valueNew': (sp) => {
sp >>>= 0
try {
const v = loadValue(sp + 8)
const args = loadSliceOfValues(sp + 16)
const result = Reflect.construct(v, args)
sp = this._inst.exports.getsp() >>> 0 // see comment above
storeValue(sp + 40, result)
this.mem.setUint8(sp + 48, 1)
} catch (err) {
sp = this._inst.exports.getsp() >>> 0 // see comment above
storeValue(sp + 40, err)
this.mem.setUint8(sp + 48, 0)
}
},
// func valueLength(v ref) int
'syscall/js.valueLength': (sp) => {
sp >>>= 0
setInt64(sp + 16, parseInt(loadValue(sp + 8).length))
},
// valuePrepareString(v ref) (ref, int)
'syscall/js.valuePrepareString': (sp) => {
sp >>>= 0
const str = encoder.encode(String(loadValue(sp + 8)))
storeValue(sp + 16, str)
setInt64(sp + 24, str.length)
},
// valueLoadString(v ref, b []byte)
'syscall/js.valueLoadString': (sp) => {
sp >>>= 0
const str = loadValue(sp + 8)
loadSlice(sp + 16).set(str)
},
// func valueInstanceOf(v ref, t ref) bool
'syscall/js.valueInstanceOf': (sp) => {
sp >>>= 0
this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0)
},
// func copyBytesToGo(dst []byte, src ref) (int, bool)
'syscall/js.copyBytesToGo': (sp) => {
sp >>>= 0
const dst = loadSlice(sp + 8)
const src = loadValue(sp + 32)
if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
this.mem.setUint8(sp + 48, 0)
return
}
const toCopy = src.subarray(0, dst.length)
dst.set(toCopy)
setInt64(sp + 40, toCopy.length)
this.mem.setUint8(sp + 48, 1)
},
// func copyBytesToJS(dst ref, src []byte) (int, bool)
'syscall/js.copyBytesToJS': (sp) => {
sp >>>= 0
const dst = loadValue(sp + 8)
const src = loadSlice(sp + 16)
if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
this.mem.setUint8(sp + 48, 0)
return
}
const toCopy = src.subarray(0, dst.length)
dst.set(toCopy)
setInt64(sp + 40, toCopy.length)
this.mem.setUint8(sp + 48, 1)
},
debug: (value) => {
console.log(value)
}
}
}
}
async run (instance) {
if (!(instance instanceof WebAssembly.Instance)) {
throw new Error('Go.run: WebAssembly.Instance expected')
}
this._inst = instance
this.mem = new DataView(this._inst.exports.mem.buffer)
this._values = [ // JS values that Go currently has references to, indexed by reference id
NaN,
0,
null,
true,
false,
globalThis,
this
]
this._goRefCounts = new Array(this._values.length).fill(Infinity) // number of references that Go has to a JS value, indexed by reference id
this._ids = new Map([ // mapping from JS values to reference ids
[0, 1],
[null, 2],
[true, 3],
[false, 4],
[globalThis, 5],
[this, 6]
])
this._idPool = [] // unused ids that have been garbage collected
this.exited = false // whether the Go program has exited
// Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
let offset = 4096
const strPtr = (str) => {
const ptr = offset
const bytes = encoder.encode(str + '\0')
new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes)
offset += bytes.length
if (offset % 8 !== 0) {
offset += 8 - (offset % 8)
}
return ptr
}
const argc = this.argv.length
const argvPtrs = []
this.argv.forEach((arg) => {
argvPtrs.push(strPtr(arg))
})
argvPtrs.push(0)
const keys = Object.keys(this.env).sort()
keys.forEach((key) => {
argvPtrs.push(strPtr(`${key}=${this.env[key]}`))
})
argvPtrs.push(0)
const argv = offset
argvPtrs.forEach((ptr) => {
this.mem.setUint32(offset, ptr, true)
this.mem.setUint32(offset + 4, 0, true)
offset += 8
})
// The linker guarantees global data starts from at least wasmMinDataAddr.
// Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
const wasmMinDataAddr = 4096 + 8192
if (offset >= wasmMinDataAddr) {
throw new Error('total length of command line and environment variables exceeds limit')
}
this._inst.exports.run(argc, argv)
if (this.exited) {
this._resolveExitPromise()
}
await this._exitPromise
}
_resume () {
if (this.exited) {
throw new Error('Go program has already exited')
}
this._inst.exports.resume()
if (this.exited) {
this._resolveExitPromise()
}
}
_makeFuncWrapper (id) {
const go = this
return function () {
const event = { id: id, this: this, args: arguments }
go._pendingEvent = event
go._resume()
return event.result
}
}
}
})()

View File

@@ -16,6 +16,7 @@
<button :class="{'nz-btn-disabled':newDownloadFlag}" :disabled="newDownloadFlag" class="nz-btn nz-btn-size-normal nz-btn-style-normal" type="button" @click="newDownload">
<i class="nz-icon nz-icon-download"></i>{{$t('overall.download')}}
</button>
<span class="downloading" v-if="newDownloadFlag">{{$t('overall.downloading')}}</span>
</div>
</div>
</div>
@@ -71,6 +72,7 @@
<button :class="{'nz-btn-disabled':upDownloadFlag}" :disabled="upDownloadFlag" class="nz-btn nz-btn-size-normal nz-btn-style-normal" type="button" @click="upDownload">
<i class="nz-icon nz-icon-download"></i>{{$t('overall.download')}}
</button>
<span class="downloading" v-if="upDownloadFlag">{{$t('overall.downloading')}}</span>
</div>
</div>
</div>

View File

@@ -13,7 +13,7 @@
class="ipInput"
style="height: 190px"
v-model="ip"
:placeholder="$t('overall.placeHolder')+' IP'"
:placeholder="$t('tagsInput.placeholder')+' IP'"
:add-from-paste="false"
:tags="tags"
@tags-changed="newTags => tags = newTags"

View File

@@ -12,7 +12,7 @@
<vue-tags-input
class="ipInput"
v-model="ip"
:placeholder="$t('overall.placeHolder')+' IP'"
:placeholder="$t('tagsInput.placeholder')+' IP'"
:add-from-paste="false"
:tags="tags"
@tags-changed="newTags => tags = newTags"

View File

@@ -18,7 +18,7 @@
<span> {{dateFormat(dataJson.start * 1000)}} - {{dateFormat(dataJson.end * 1000)}} ({{dataJson.timezone}})</span>
</div>
</div>
<div v-if="!dataJson.type" id="dashboardScrollbar" class="box-content" ref="dashboardScrollbar" style='overflow:hidden; overflow-y: auto;height: calc(100% - 72px);display: flex;flex-direction: column'>
<div v-if="dataJson.type === 'dashboard'" id="dashboardScrollbar" class="box-content" ref="dashboardScrollbar" style='overflow:hidden; overflow-y: auto;height: calc(100% - 72px);display: flex;flex-direction: column'>
<chartList
ref="chartList"
name="dashboard"
@@ -38,7 +38,7 @@
:loading="chartListLoading"
/>
</div>
<div v-if="dataJson.type" id="explore" class="explores" style='overflow:hidden;background: #fffffe; height: calc(100% - 72px);display: flex;flex-direction: column'>
<div v-if="dataJson.type == 1" id="explore" class="explores" style='overflow:hidden;background: #fffffe; height: calc(100% - 72px);display: flex;flex-direction: column'>
<exploreItem
ref="exploreItem"
:key="dataJson.type"

View File

@@ -31,13 +31,27 @@ import VueClipboard from 'vue-clipboard2'
// 二次封装message 显示自动关闭进度条
import Message from '@/components/common/message/index'
// v-md-editor 预览组件
import VMdPreview from '@kangc/v-md-editor/lib/preview'
import githubTheme from '@kangc/v-md-editor/lib/theme/github'
import hljs from 'highlight.js'
import createCopyCodePlugin from '@/components/common/copy-code'
Vue.component('element-set', elementSet) // 公用设置表头
Vue.component('pick-time', pickTime)
Vue.component('nzDataList', nzDataList)
Vue.component('chartList', chartList)
Vue.component('Pagination', Pagination) // 公用分页组件
VMdPreview.xss.extend({
// extend white list
whiteList: {
button: ['title']
}
})
VMdPreview.use(githubTheme, {
Hljs: hljs
})
VMdPreview.use(createCopyCodePlugin())
Vue.use(VMdPreview)
Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.use(Vuex)

File diff suppressed because one or more lines are too long

View File

@@ -25,7 +25,6 @@ const timePicker = {
store.commit('setTimePickerLocked', flag)
},
dispatchTimePickerRange (store, range) {
console.log('dispatchTimePickerRange', range)
store.commit('setTimePickerRange', range)
}
}

View File

@@ -1,35 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>
<script>
function clacArr (arr, x, y) {
arr.forEach(item => {
item.x += x
item.y += y
})
return JSON.stringify(arr)
}
console.log(
clacArr([
{ x: 80, y: 220 },
{ x: 110, y: 210 },
{ x: 120, y: 200 },
{ x: 140, y: 160 },
{ x: 180, y: 200 },
{ x: 170, y: 260 },
{ x: 130, y: 280 },
{ x: 128, y: 300 },
{ x: 130, y: 280 },
{ x: 170, y: 260 },
{ x: 140, y: 160 }],
-70, -150
)
)
</script>

Binary file not shown.