mirror of https://github.com/alibaba/arthas.git
update web ui (#2318)
* fix(web ui): profiler * chore(web ui):perf proxy config * perf(web ui):update style * chore(web ui):update deps * perf(web ui):fix monitor category * fix(web ui):fix style of table and monitor rt chart * refactor(web ui):refactor config * feat(web ui):support debug http api with consolepull/2325/head
parent
f6fe8b9134
commit
aa2526075b
@ -0,0 +1,2 @@
|
||||
# NODE_ENV=production
|
||||
VITE_AGENT=true
|
@ -0,0 +1,2 @@
|
||||
# NODE_ENV=production
|
||||
VITE_AGENT=false
|
@ -1,57 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { PuzzleIcon, TerminalIcon, ViewGridIcon } from "@heroicons/vue/outline"
|
||||
import { DesktopComputerIcon } from "@heroicons/vue/solid"
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
const tabs = [
|
||||
{
|
||||
name: 'dashboard',
|
||||
url: "/dashboard",
|
||||
icon: DesktopComputerIcon
|
||||
},
|
||||
{
|
||||
name: 'immediacy',
|
||||
url: '/synchronize',
|
||||
icon: ViewGridIcon
|
||||
}, {
|
||||
name: "real time",
|
||||
url: '/asynchronize',
|
||||
icon: ViewGridIcon
|
||||
},
|
||||
{
|
||||
name: 'option',
|
||||
url: '/config',
|
||||
icon: PuzzleIcon
|
||||
},
|
||||
// {
|
||||
// name: 'console',
|
||||
// url: '/console',
|
||||
// icon: TerminalIcon
|
||||
// },
|
||||
|
||||
]
|
||||
const router = useRouter()
|
||||
const routePath = computed(() => useRoute().path)
|
||||
const toNext = (url: string) => {
|
||||
router.push(url)
|
||||
}
|
||||
const a: StatusResult = { type: "status", message: "", statusCode: 0 }
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ul class="menu bg-base-200 w-[10vw] menu-compact">
|
||||
<li v-for="(tab, idx) in tabs" :key="idx"
|
||||
@click="toNext(tab.url)" class="pl-2" >
|
||||
<a class="break-all" :class="{ 'bg-primary text-primary-content': routePath.includes(tab.url), }">
|
||||
<component :is="tab.icon" class="w-4 h-4" />
|
||||
{{
|
||||
tab.name
|
||||
}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,102 @@
|
||||
<script setup lang="ts">
|
||||
import permachine from '@/machines/perRequestMachine';
|
||||
import { fetchStore } from '@/stores/fetch';
|
||||
import { publicStore } from '@/stores/public';
|
||||
import { onBeforeMount, reactive, ref, Ref } from 'vue';
|
||||
import { interpret } from 'xstate';
|
||||
const fetchS = fetchStore();
|
||||
const publicS = publicStore()
|
||||
type ResultType = MergeObj<Omit<GlobalOptions, "value">, {
|
||||
value: Ref<string>, changeValue: null | (() => void)
|
||||
}>
|
||||
|
||||
const tableResultList: ResultType[] = reactive([])
|
||||
const keyList: (keyof GlobalOptions)[] = [
|
||||
"level",
|
||||
"name",
|
||||
"type",
|
||||
"value",
|
||||
"summary",
|
||||
"description",
|
||||
]
|
||||
const setVmoption = (key: string, value: string) => fetchS.baseSubmit(interpret(permachine), {
|
||||
action: "exec",
|
||||
command: `options ${key} ${value}`
|
||||
})
|
||||
|
||||
const getVmoption = () => fetchS.baseSubmit(interpret(permachine), {
|
||||
action: "exec",
|
||||
command: "options",
|
||||
}).then(res => {
|
||||
let result = (res as CommonRes).body.results[0]
|
||||
if (result.type == "options") {
|
||||
tableResultList.length = 0;
|
||||
result.options.forEach((option) => {
|
||||
let rows: ResultType[] = []
|
||||
// 用来绑定读写
|
||||
|
||||
let _raw = ref(option.value)
|
||||
let changeValue = null
|
||||
changeValue = publicS.inputDialogFactory(_raw,
|
||||
(raw) => {
|
||||
setVmoption(option.name, raw.trim())
|
||||
.then(res =>{
|
||||
let result = (res as CommonRes).body.results[0]
|
||||
if(result.type === "options") _raw.value = (result.changeResult.afterValue as string).toString()
|
||||
})
|
||||
.catch(err => {
|
||||
// 失败就回退
|
||||
_raw.value = option.value
|
||||
})
|
||||
return raw.trim()
|
||||
},
|
||||
(input) => input.value)
|
||||
rows.push({
|
||||
...option,
|
||||
value: _raw,
|
||||
changeValue,
|
||||
})
|
||||
tableResultList.push(...rows)
|
||||
})
|
||||
tableResultList.sort((a, b) => {
|
||||
if(a.level != b.level) return a.level - b.level
|
||||
else {
|
||||
return a.name > b.name ? 1 :-1
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
onBeforeMount(() => {
|
||||
getVmoption()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="table w-full table-compact">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th></th>
|
||||
<th v-for="(k, i) in keyList" :key="i">{{ k }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(map, i) in tableResultList" :key="i" class="hover">
|
||||
<th>
|
||||
<button class="btn btn-outline btn-xs btn-primary" @click.prevent="map.changeValue"
|
||||
v-if="map.changeValue !== null">edit</button>
|
||||
</th>
|
||||
<template v-for="(k, j) in keyList" :key="j">
|
||||
<th v-if="k === 'name' || k === 'level'">{{ map[k] }}</th>
|
||||
<td v-else class="break-words"> {{ map[k] }}</td>
|
||||
</template>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th v-for="(k, i) in keyList" :key="i">{{ k }}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</template>
|
@ -0,0 +1,69 @@
|
||||
<script setup lang="ts">
|
||||
import permachine from '@/machines/perRequestMachine';
|
||||
import { fetchStore } from '@/stores/fetch';
|
||||
import { onBeforeMount, reactive } from 'vue';
|
||||
import { interpret } from 'xstate';
|
||||
const fetchS = fetchStore();
|
||||
type ResultType = MergeObj<Perfcounter,{rowspan:number}>
|
||||
const perfcounterList: ResultType[] = reactive([])
|
||||
let keyList: (keyof Perfcounter)[] = [
|
||||
"name",
|
||||
"units",
|
||||
"variability",
|
||||
"value",
|
||||
]
|
||||
const getPerCounter = () => fetchS.baseSubmit(interpret(permachine), { action: "exec", command: "perfcounter -d" }).then(res => {
|
||||
const result = (res as CommonRes).body.results[0]
|
||||
if (result.type === "perfcounter") {
|
||||
const perfcounters = result.perfCounters
|
||||
perfcounterList.length = 0;
|
||||
perfcounters.forEach(perfcouter => {
|
||||
let result = {...perfcouter,rowspan:1}
|
||||
result.value = result.value.toString()
|
||||
perfcounterList.push(result)
|
||||
})
|
||||
perfcounterList.sort((a, b) => a.name > b.name ? 1 : -1)
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
getPerCounter()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="table w-full table-compact">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="(v,i) in keyList" :key="i">{{v}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="">
|
||||
<tr v-for="(map, i) in perfcounterList" :key="i" class="hover">
|
||||
<template v-for="(key,j) in keyList" :key="j">
|
||||
<!-- 展示合并的单元格且定住name -->
|
||||
<th v-if="key == 'name' && map.rowspan > 0" :rowspan="map.rowspan">
|
||||
{{map[key]}}
|
||||
</th>
|
||||
<!-- 只有value才会裂变 -->
|
||||
<td v-else-if="key === 'value'" >
|
||||
<div class="break-all">{{map[key]}}</div>
|
||||
</td>
|
||||
<!-- 展示合并的单元格 -->
|
||||
<td v-else-if="map.rowspan > 0" :rowspan="map.rowspan">
|
||||
{{map[key]}}
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th v-for="(v,i) in keyList" :key="i" class="break-words">{{v}}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,52 @@
|
||||
<script setup lang="ts">
|
||||
import permachine from '@/machines/perRequestMachine';
|
||||
import { fetchStore } from '@/stores/fetch';
|
||||
import { onBeforeMount, reactive } from 'vue';
|
||||
import { interpret } from 'xstate';
|
||||
const fetchS = fetchStore();
|
||||
type ResultType = { "key": string, "value": string, rowspan: number };
|
||||
const tableResultList: ResultType[] = reactive([])
|
||||
const getSysenv = () => fetchS.baseSubmit(interpret(permachine), {
|
||||
action: "exec",
|
||||
command: "sysenv",
|
||||
}).then(res => {
|
||||
tableResultList.length = 0
|
||||
let result = (res as CommonRes).body.results[0]
|
||||
if (result.type == "sysenv") {
|
||||
Object.entries(result.env).forEach(([key, value]) => {
|
||||
let rows: ResultType[] = []
|
||||
rows.push({
|
||||
key, value, rowspan: 1
|
||||
})
|
||||
tableResultList.push(...rows)
|
||||
})
|
||||
tableResultList.sort((a, b) => a.key > b.key ? 1 : -1)
|
||||
}
|
||||
})
|
||||
onBeforeMount(() => {
|
||||
getSysenv()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="table w-full table-compact">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>key</th>
|
||||
<th>value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(map, i) in tableResultList" :key="i" class="hover">
|
||||
<th v-if="map.rowspan > 0" :rowspan="map.rowspan">{{map.key}}</th>
|
||||
<td>{{map.value}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>key</th>
|
||||
<th>value</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</template>
|
@ -0,0 +1,78 @@
|
||||
<script setup lang="ts">
|
||||
import permachine from '@/machines/perRequestMachine';
|
||||
import { fetchStore } from '@/stores/fetch';
|
||||
import { publicStore } from '@/stores/public';
|
||||
import { onBeforeMount, reactive, ref, Ref } from 'vue';
|
||||
import { interpret } from 'xstate';
|
||||
const fetchS = fetchStore();
|
||||
const publicS = publicStore()
|
||||
type ResultType = { "key": string, "value": Ref<string>, rowspan: number, changeValue:()=>void};
|
||||
const tableResultList: ResultType[] = reactive([])
|
||||
|
||||
const setSysprop = (key:string,value:string) => fetchS.baseSubmit(interpret(permachine),{
|
||||
action: "exec",
|
||||
command:`sysprop ${key} ${value}`
|
||||
})
|
||||
|
||||
const getSysprop = () => fetchS.baseSubmit(interpret(permachine), {
|
||||
action: "exec",
|
||||
command: "sysprop",
|
||||
}).then(res => {
|
||||
let result = (res as CommonRes).body.results[0]
|
||||
if (result.type == "sysprop") {
|
||||
tableResultList.length = 0;
|
||||
Object.entries(result.props).forEach(([key, value]) => {
|
||||
let rows: ResultType[] = []
|
||||
// 用来绑定读写
|
||||
let _raw = ref(value)
|
||||
const changeValue = publicS.inputDialogFactory(_raw,
|
||||
(raw) => {
|
||||
setSysprop(key, raw.trim()).then(res=>{
|
||||
},err=>{
|
||||
// 失败就回退
|
||||
_raw.value = value
|
||||
})
|
||||
return raw.trim()
|
||||
},
|
||||
(input) => input.value)
|
||||
rows.push({
|
||||
key, value:_raw, rowspan: 1, changeValue
|
||||
})
|
||||
tableResultList.push(...rows)
|
||||
})
|
||||
tableResultList.sort((a, b) => a.key > b.key ? 1 : -1)
|
||||
}
|
||||
})
|
||||
onBeforeMount(() => {
|
||||
getSysprop()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="table w-full table-compact">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th></th>
|
||||
<th>key</th>
|
||||
<th>value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(map, i) in tableResultList" :key="i" class="hover">
|
||||
<th v-if="map.rowspan > 0" :rowspan="map.rowspan">
|
||||
<button class="btn btn-outline btn-xs btn-primary" @click.prevent="map.changeValue">edit</button>
|
||||
</th>
|
||||
<th v-if="map.rowspan > 0" :rowspan="map.rowspan">{{map.key}}</th>
|
||||
<td>{{map.value}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>key</th>
|
||||
<th>value</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</template>
|
@ -0,0 +1,92 @@
|
||||
<script setup lang="ts">
|
||||
import permachine from '@/machines/perRequestMachine';
|
||||
import { fetchStore } from '@/stores/fetch';
|
||||
import { publicStore } from '@/stores/public';
|
||||
import { onBeforeMount, reactive, ref, Ref } from 'vue';
|
||||
import { interpret } from 'xstate';
|
||||
const fetchS = fetchStore();
|
||||
const publicS = publicStore()
|
||||
type ResultType = { name: string, origin: string, value: Ref<string>, writeable: string, changeValue: null|(() => void)
|
||||
};
|
||||
const tableResultList: ResultType[] = reactive([])
|
||||
const keyList: (keyof VmOption)[] = [
|
||||
"name",
|
||||
"origin",
|
||||
"writeable",
|
||||
"value",
|
||||
]
|
||||
const setVmoption = (key: string, value: string) => fetchS.baseSubmit(interpret(permachine), {
|
||||
action: "exec",
|
||||
command: `vmoption ${key} ${value}`
|
||||
})
|
||||
|
||||
const getVmoption = () => fetchS.baseSubmit(interpret(permachine), {
|
||||
action: "exec",
|
||||
command: "vmoption",
|
||||
}).then(res => {
|
||||
let result = (res as CommonRes).body.results[0]
|
||||
if (result.type == "vmoption") {
|
||||
tableResultList.length = 0;
|
||||
result.vmOptions.forEach((vmoption) => {
|
||||
let rows: ResultType[] = []
|
||||
// 用来绑定读写
|
||||
|
||||
let _raw = ref(vmoption.value)
|
||||
let changeValue = null
|
||||
if(vmoption.writeable===true) {
|
||||
changeValue = publicS.inputDialogFactory(_raw,
|
||||
(raw) => {
|
||||
setVmoption(vmoption.name, raw.trim()).then(res => {
|
||||
}, err => {
|
||||
// 失败就回退
|
||||
_raw.value = vmoption.value
|
||||
})
|
||||
return raw.trim()
|
||||
},
|
||||
(input) => input.value)
|
||||
}
|
||||
rows.push({
|
||||
name: vmoption.name,
|
||||
value: _raw,
|
||||
changeValue,
|
||||
writeable: vmoption.writeable.toString(),
|
||||
origin: vmoption.origin
|
||||
})
|
||||
tableResultList.push(...rows)
|
||||
})
|
||||
tableResultList.sort((a, b) => a.name > b.name ? 1 : -1)
|
||||
}
|
||||
})
|
||||
onBeforeMount(() => {
|
||||
getVmoption()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="table w-full table-compact">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th></th>
|
||||
<th v-for="(k, i) in keyList" :key="i">{{k}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(map, i) in tableResultList" :key="i" class="hover">
|
||||
<th >
|
||||
<button class="btn btn-outline btn-xs btn-primary" @click.prevent="map.changeValue" v-if="map.changeValue !== null">edit</button>
|
||||
</th>
|
||||
<template v-for="(k,j) in keyList" :key="j">
|
||||
<th v-if="k==='name'">{{map[k]}}</th>
|
||||
<td v-else class="break-words"> {{map[k]}}</td>
|
||||
</template>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th v-for="(k, i) in keyList" :key="i">{{k}}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</template>
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue