octopus/statics/debugger.html
2023-03-22 22:45:17 +08:00

204 lines
6.5 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DEBUGGER</title>
<script src="https://cdn.tailwindcss.com/"></script>
</head>
<body>
<div id="app">
<nav class="fixed z-30 w-full bg-white border-b-2 border-indigo-600">
<div class="py-3 px-6">
<div class="flex justify-between items-center">
<div class="flex justify-start items-center">
<span class="flex items-center text-xl font-bold text-blue-800">DEBUGGER</span>
</div>
<div class="flex items-center">
<div class="hidden relative mt-1 mr-6 lg:block lg:w-64">
<div class="flex absolute inset-y-0 left-0 items-center pl-3">
<svg class="w-5 h-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
clip-rule="evenodd"
></path>
</svg>
</div>
<input
type="text"
name="name"
class="block p-2.5 pl-10 w-full text-gray-900 rounded-lg border sm:text-sm focus:ring-1 focus:outline-none"
v-model="filter"
placeholder="搜索"
/>
</div>
</div>
</div>
</div>
</nav>
<div class="pt-12 lg:flex">
<div class="flex overflow-y-auto flex-col py-8 px-4 border-b lg:h-screen lg:border-r w-128">
<div class="flex flex-col justify-between mt-6">
<aside>
<ul>
<li v-for="func in filterdFuncs">
<a
@click="handleClickFunc(func)"
:class="{ 'bg-indigo-600 text-white': func === selectedFunc }"
class="flex items-center py-2 px-4 text-gray-700 bg-gray-100 rounded-md"
href="#"
>
<span class="mx-4 font-medium">{{ func.title }}</span>
</a>
</li>
</ul>
</aside>
</div>
</div>
<div class="overflow-y-auto p-8 w-full h-full">
<p class="flex flex-col mb-8 text-xl">{{ selectedFunc.description }}</p>
<form @submit="handleClickSubmit">
<div class="grid gap-6 mb-6 md:grid-cols-2">
<div v-for="param in selectedParameters">
<label :for="selectedFuncName+param.name" class="block mb-2 text-sm font-medium text-gray-900"> {{ param.description }}</label>
<input
type="text"
:id="selectedFuncName+param.name"
class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:border-blue-500 focus:ring-blue-500"
v-model="currentParameters[param.name]"
:placeholder="param.description"
:required="param.required"
required
/>
</div>
</div>
<button
type="submit"
class="py-2.5 px-5 w-full text-sm font-medium text-center text-white bg-blue-700 rounded-lg sm:w-auto hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 focus:outline-none"
>
执行
</button>
</form>
<div class="p-4 mt-8 border-2">
<div>
<input
class="px-5 my-4 w-full h-10 text-gray-900 rounded-lg border sm:text-sm focus:ring-1 focus:outline-none"
type="text"
name="dynamicfilter"
v-model="jsonFilter"
placeholder="Javascript Query, use 'it' to refer to the response"
/>
</div>
<pre @click="copyResponse"> {{ JSON.stringify(filteredResult, null, 2) }} </pre>
</div>
</div>
</div>
</div>
</body>
<script type="module" lang="js">
import { createApp } from "https://unpkg.com/vue@3/dist/vue.esm-browser.js";
const unsecuredCopyToClipboard = (text) => {
const textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand("copy");
} catch (err) {
console.error("Unable to copy to clipboard", err);
}
document.body.removeChild(textArea);
};
createApp({
data: () => {
return {
jsonFilter: "",
funcs: [],
selectedFuncName: undefined,
filter: "",
currentParameters: {},
result: undefined,
};
},
async mounted() {
const functionsUrl = window.location.href.replace("debugger", "debugger/functions");
let resp = await fetch(functionsUrl);
this.funcs = (await resp.json()).data;
},
computed: {
selectedFunc() {
let filterd = this.funcs.filter((f) => f.name == this.selectedFuncName) || [];
return (filterd && filterd[0]) || {};
},
filterdFuncs() {
return this.funcs.filter((f) => f.name.includes(this.filter) || f.title.includes(this.filter) || f.description.includes(this.filter));
},
selectedParameters() {
return this.selectedFunc.parameters;
},
filteredResult() {
if (this.jsonFilter) {
try {
return eval(this.jsonFilter);
} catch {
return this.result;
}
} else {
return this.result;
}
},
},
methods: {
handleClickFunc(message, event) {
event && event.preventDefault();
this.selectedFuncName = message.name;
this.currentParameters = {};
for (let param of this.selectedParameters) {
this.currentParameters[param.name] = window.localStorage.getItem(`debugger_${param.name}`) || "";
}
},
async copyResponse() {
if (this.result) {
const content = JSON.stringify(this.filteredResult, null, 2);
if (window.isSecureContext && navigator.clipboard) {
navigator.clipboard.writeText(content);
} else {
unsecuredCopyToClipboard(content);
}
}
},
async handleClickSubmit(event) {
this.result = undefined;
event && event.preventDefault();
for (let key in this.currentParameters) {
window.localStorage.setItem(`debugger_${key}`, this.currentParameters[key]);
}
let executeUrl = window.location.href.replace("debugger", "debugger/execute");
let resp = await fetch(executeUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Debug_Kylin: "true",
},
body: JSON.stringify({
func: this.selectedFuncName,
params: this.currentParameters,
}),
});
this.result = await resp.json();
const obj = JSON.parse(JSON.stringify(this.result.data));
console.log(obj);
window.it = obj;
},
},
}).mount("#app");
</script>
</html>