前端页面
This commit is contained in:
4
EdgeAdmin/web/views/@default/httpdns/sandbox/@menu.html
Normal file
4
EdgeAdmin/web/views/@default/httpdns/sandbox/@menu.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<!-- 左侧菜单由 Go Backend 自动生成注入,此处加首行子菜单使其符合标准平台样式 -->
|
||||
<first-menu>
|
||||
<menu-item href="/httpdns/sandbox" code="index">API 在线沙盒</menu-item>
|
||||
</first-menu>
|
||||
171
EdgeAdmin/web/views/@default/httpdns/sandbox/index.html
Normal file
171
EdgeAdmin/web/views/@default/httpdns/sandbox/index.html
Normal file
@@ -0,0 +1,171 @@
|
||||
{$layout}
|
||||
{$template "menu"}
|
||||
<style>
|
||||
.httpdns-sdns-row {
|
||||
display: flex;
|
||||
gap: .5em;
|
||||
align-items: center;
|
||||
margin-bottom: .45em;
|
||||
}
|
||||
.httpdns-sdns-row .field {
|
||||
margin: 0 !important;
|
||||
flex: 1;
|
||||
}
|
||||
.httpdns-sdns-actions {
|
||||
margin-top: .2em;
|
||||
}
|
||||
.httpdns-sdns-actions .count {
|
||||
color: #8f9aa6;
|
||||
margin-left: .4em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<div class="ui grid stackable">
|
||||
<!-- Left: 解析配置 -->
|
||||
<div class="six wide column">
|
||||
<div class="ui segment">
|
||||
<h4 class="ui header" style="margin-top:0;">解析配置</h4>
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<label>目标应用 *</label>
|
||||
<select class="ui dropdown" name="appId" v-model="request.appId">
|
||||
<option value="">[请选择应用]</option>
|
||||
<option v-for="app in apps" :value="app.appId">{{app.name}} ({{app.appId}})</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>解析域名 *</label>
|
||||
<input type="text" v-model="request.domain" placeholder="例如 www.example.com" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>模拟客户端 IP</label>
|
||||
<input type="text" v-model="request.clientIp" placeholder="留空使用当前 IP" />
|
||||
<p class="comment">用于测试 ECS 掩码与区域调度效果。</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>解析类型</label>
|
||||
<div class="ui buttons mini">
|
||||
<button class="ui button" :class="{primary: request.qtype=='A'}"
|
||||
@click.prevent="request.qtype='A'" type="button">A</button>
|
||||
<button class="ui button" :class="{primary: request.qtype=='AAAA'}"
|
||||
@click.prevent="request.qtype='AAAA'" type="button">AAAA</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>SDNS 参数</label>
|
||||
<div class="httpdns-sdns-row" v-for="(param, index) in sdnsParams">
|
||||
<div class="field">
|
||||
<input type="text" maxlength="64" placeholder="参数名称" v-model="param.name" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<input type="text" maxlength="64" placeholder="参数值" v-model="param.value" />
|
||||
</div>
|
||||
<a href="" @click.prevent="removeSDNSParam(index)" title="删除"><i class="icon trash alternate outline"></i></a>
|
||||
</div>
|
||||
<div class="httpdns-sdns-actions">
|
||||
<a href="" @click.prevent="addSDNSParam" :class="{disabled: sdnsParams.length >= 10}">
|
||||
<i class="icon plus circle"></i>添加参数
|
||||
</a>
|
||||
<span class="count">{{sdnsParams.length}}/10</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui divider"></div>
|
||||
|
||||
<button class="ui button primary" type="button" @click.prevent="sendTestRequest"
|
||||
:class="{loading: isRequesting, disabled: isRequesting}">
|
||||
<i class="icon search"></i> 在线解析
|
||||
</button>
|
||||
<button class="ui button basic" type="button" @click.prevent="resetForm">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right: 解析结果 -->
|
||||
<div class="ten wide column">
|
||||
<!-- Empty state -->
|
||||
<div v-show="!response.hasResult && !isRequesting" class="ui segment placeholder">
|
||||
<p class="grey" style="text-align:center;">请在左侧配置参数后点击「在线解析」。</p>
|
||||
</div>
|
||||
|
||||
<!-- Loading -->
|
||||
<div v-show="isRequesting" class="ui segment" style="min-height:200px;">
|
||||
<div class="ui active dimmer">
|
||||
<div class="ui text loader">解析中...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Result -->
|
||||
<div v-show="response.hasResult && !isRequesting">
|
||||
<!-- Status banner -->
|
||||
<div class="ui message small" :class="{positive: response.code === 0, negative: response.code !== 0}">
|
||||
<div class="header">
|
||||
<span v-if="response.code === 0"><i class="icon check circle"></i> 解析成功</span>
|
||||
<span v-else><i class="icon times circle"></i> 解析失败 ({{response.code}})</span>
|
||||
</div>
|
||||
<p v-if="response.code !== 0">{{response.message}}</p>
|
||||
<p class="grey small" style="margin-top:.3em;">Request ID: <code>{{response.requestId}}</code></p>
|
||||
</div>
|
||||
|
||||
<!-- Result details -->
|
||||
<div v-if="response.code === 0 && response.data" style="margin-top: 1em;">
|
||||
<h5 class="ui header">解析结果</h5>
|
||||
<div class="ui segment" style="margin-top:.4em;">
|
||||
<div style="font-weight: 600; margin-bottom: .5em;">请求URL</div>
|
||||
<div style="word-break: break-all;">
|
||||
<code>{{response.data.request_url || '-'}}</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5 class="ui header" style="margin-top:1.2em;">解析结果详情</h5>
|
||||
<div class="ui three column stackable grid" style="margin-top:0;">
|
||||
<div class="column">
|
||||
<div class="ui segment">
|
||||
<div class="grey">客户端 IP</div>
|
||||
<div style="margin-top:.4em;"><code>{{response.data.client_ip || request.clientIp || '-'}}</code></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="ui segment">
|
||||
<div class="grey">地区</div>
|
||||
<div style="margin-top:.4em;">{{response.data.client_region || '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="ui segment">
|
||||
<div class="grey">线路</div>
|
||||
<div style="margin-top:.4em;">{{response.data.line_name || '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IP results table -->
|
||||
<h5 class="ui header" style="margin-top:1.2em;">解析记录</h5>
|
||||
<table class="ui table celled compact">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>解析域名</th>
|
||||
<th>解析类型</th>
|
||||
<th>IP地址</th>
|
||||
<th>TTL</th>
|
||||
<th>地区</th>
|
||||
<th>线路</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(row, idx) in response.resultRows">
|
||||
<td v-if="idx === 0" :rowspan="response.resultRows.length">{{row.domain || request.domain}}</td>
|
||||
<td>{{row.type || request.qtype}}</td>
|
||||
<td><code>{{row.ip}}</code></td>
|
||||
<td>{{row.ttl}}s</td>
|
||||
<td>{{row.region || '-'}}</td>
|
||||
<td>{{row.line || '-'}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
135
EdgeAdmin/web/views/@default/httpdns/sandbox/index.js
Normal file
135
EdgeAdmin/web/views/@default/httpdns/sandbox/index.js
Normal file
@@ -0,0 +1,135 @@
|
||||
Tea.context(function () {
|
||||
this.newRequest = function () {
|
||||
return {
|
||||
appId: "",
|
||||
domain: "",
|
||||
clientIp: "",
|
||||
qtype: "A"
|
||||
}
|
||||
}
|
||||
|
||||
this.request = this.newRequest()
|
||||
this.sdnsParams = [{name: "", value: ""}]
|
||||
|
||||
this.response = {
|
||||
hasResult: false,
|
||||
code: -1,
|
||||
message: "",
|
||||
data: null,
|
||||
requestId: "",
|
||||
resultRows: []
|
||||
}
|
||||
|
||||
this.isRequesting = false
|
||||
|
||||
if (typeof this.apps == "undefined") {
|
||||
this.apps = []
|
||||
}
|
||||
|
||||
this.addSDNSParam = function () {
|
||||
if (this.sdnsParams.length >= 10) {
|
||||
return
|
||||
}
|
||||
this.sdnsParams.push({name: "", value: ""})
|
||||
}
|
||||
|
||||
this.removeSDNSParam = function (index) {
|
||||
if (index < 0 || index >= this.sdnsParams.length) {
|
||||
return
|
||||
}
|
||||
this.sdnsParams.splice(index, 1)
|
||||
if (this.sdnsParams.length == 0) {
|
||||
this.sdnsParams.push({name: "", value: ""})
|
||||
}
|
||||
}
|
||||
|
||||
this.cleanSDNSParams = function () {
|
||||
let list = []
|
||||
this.sdnsParams.forEach(function (item) {
|
||||
let name = (item.name || "").trim()
|
||||
let value = (item.value || "").trim()
|
||||
if (name.length == 0 && value.length == 0) {
|
||||
return
|
||||
}
|
||||
list.push({
|
||||
name: name,
|
||||
value: value
|
||||
})
|
||||
})
|
||||
return list
|
||||
}
|
||||
|
||||
this.normalizeResultRows = function (data) {
|
||||
if (typeof data == "undefined" || data == null) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(data.records) && data.records.length > 0) {
|
||||
return data.records
|
||||
}
|
||||
|
||||
let rows = []
|
||||
let ips = []
|
||||
if (Array.isArray(data.ips)) {
|
||||
ips = data.ips
|
||||
}
|
||||
let domain = this.request.domain
|
||||
let qtype = this.request.qtype
|
||||
let ttl = data.ttl || 0
|
||||
let region = data.client_region || "-"
|
||||
let line = data.line_name || "-"
|
||||
|
||||
ips.forEach(function (ip) {
|
||||
rows.push({
|
||||
domain: domain,
|
||||
type: qtype,
|
||||
ip: ip,
|
||||
ttl: ttl,
|
||||
region: region,
|
||||
line: line
|
||||
})
|
||||
})
|
||||
return rows
|
||||
}
|
||||
|
||||
this.sendTestRequest = function () {
|
||||
if (this.request.appId.length == 0) {
|
||||
teaweb.warn("请选择目标应用")
|
||||
return
|
||||
}
|
||||
if (this.request.domain.length == 0) {
|
||||
teaweb.warn("请填写解析域名")
|
||||
return
|
||||
}
|
||||
|
||||
this.isRequesting = true
|
||||
this.response.hasResult = false
|
||||
|
||||
let payload = Object.assign({}, this.request)
|
||||
payload.sdnsParamsJSON = JSON.stringify(this.cleanSDNSParams())
|
||||
|
||||
this.$post("/httpdns/sandbox/test")
|
||||
.params(payload)
|
||||
.success(function (resp) {
|
||||
this.response = resp.data.result
|
||||
this.response.hasResult = true
|
||||
this.response.resultRows = this.normalizeResultRows(this.response.data)
|
||||
})
|
||||
.done(function () {
|
||||
this.isRequesting = false
|
||||
})
|
||||
}
|
||||
|
||||
this.resetForm = function () {
|
||||
this.request = this.newRequest()
|
||||
this.sdnsParams = [{name: "", value: ""}]
|
||||
this.response = {
|
||||
hasResult: false,
|
||||
code: -1,
|
||||
message: "",
|
||||
data: null,
|
||||
requestId: "",
|
||||
resultRows: []
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user