实现基本的域名、记录管理

This commit is contained in:
GoEdgeLab
2021-05-27 17:09:53 +08:00
parent 04db86a919
commit c0c80f32c9
48 changed files with 1386 additions and 9 deletions

View File

@@ -0,0 +1,5 @@
<first-menu>
<menu-item href="/ns" code="index">域名列表</menu-item>
<menu-item href="/ns/domains/create" code="create">添加域名</menu-item>
</first-menu>
<div class="margin"></div>

View File

@@ -0,0 +1,5 @@
pre.log-box {
margin: 0;
padding: 0;
}
/*# sourceMappingURL=index.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA,GAAG;EACF,SAAA;EACA,UAAA","file":"index.css"}

View File

@@ -0,0 +1,62 @@
{$layout}
{$var "header"}
<!-- datepicker -->
<script type="text/javascript" src="/js/moment.min.js"></script>
<script type="text/javascript" src="/js/pikaday.js"></script>
<link rel="stylesheet" href="/js/pikaday.css"/>
<link rel="stylesheet" href="/js/pikaday.theme.css"/>
<link rel="stylesheet" href="/js/pikaday.triangle.css"/>
{$end}
<div class="margin"></div>
<form method="get" action="/ns/clusters/logs" class="ui form" autocomplete="off">
<div class="ui fields inline">
<div class="ui field">
<input type="text" name="dayFrom" placeholder="开始日期" v-model="dayFrom" value="" style="width:8em" id="day-from-picker"/>
</div>
<div class="ui field">
<input type="text" name="dayTo" placeholder="结束日期" v-model="dayTo" value="" style="width:8em" id="day-to-picker"/>
</div>
<div class="ui field">
<select class="ui dropdown" name="level" v-model="level">
<option value="">[级别]</option>
<option value="error">错误</option>
<option value="warning">警告</option>
<option value="info">信息</option>
</select>
</div>
<div class="ui field">
<input type="text" name="keyword" style="width:10em" v-model="keyword" placeholder="关键词"/>
</div>
<div class="ui field">
<button type="submit" class="ui button">查询</button>
</div>
<div class="ui field" v-if="dayFrom.length > 0 || dayTo.length > 0 || keyword.length > 0 || level.length > 0">
<a href="/ns/clusters/logs">[清除条件]</a>
</div>
</div>
</form>
<p class="comment" v-if="logs.length == 0">暂时还没有日志。</p>
<table class="ui table selectable celled" v-if="logs.length > 0">
<thead>
<tr>
<th>集群</th>
<th>节点</th>
<th>信息</th>
</tr>
</thead>
<tr v-for="log in logs">
<td nowrap=""><link-icon :href="'/ns/clusters/cluster?clusterId=' + log.node.cluster.id">{{log.node.cluster.name}}</link-icon></td>
<td nowrap=""><link-icon :href="'/ns/clusters/cluster/node?clusterId=' + log.node.cluster.id + '&nodeId=' + log.node.id">{{log.node.name}}</link-icon></td>
<td>
<pre class="log-box"><span :class="{red:log.level == 'error', orange:log.level == 'warning'}"><span v-if="!log.isToday">[{{log.createdTime}}]</span><strong v-if="log.isToday">[{{log.createdTime}}]</strong>[{{log.tag}}]{{log.description}}</span> &nbsp; <span v-if="log.count > 0" class="ui label tiny" :class="{red:log.level == 'error', orange:log.level == 'warning'}">共{{log.count}}条</span></pre>
</td>
</tr>
</table>
<div class="page" v-html="page"></div>

View File

@@ -0,0 +1,6 @@
Tea.context(function () {
this.$delay(function () {
teaweb.datepicker("day-from-picker")
teaweb.datepicker("day-to-picker")
})
})

View File

@@ -0,0 +1,4 @@
pre.log-box {
margin: 0;
padding: 0;
}

View File

@@ -0,0 +1,7 @@
<first-menu>
<menu-item href="/ns">所有域名</menu-item>
<span class="item disabled">|</span>
<menu-item :href="'/ns/domains/domain?domainId=' + domain.id" code="index">详情<span class="grey small">{{domain.name}}</span></menu-item>
<menu-item :href="'/ns/domains/records?domainId=' + domain.id" code="record">记录</menu-item>
<menu-item :href="'/ns/domains/update?domainId=' + domain.id" code="update">修改</menu-item>
</first-menu>

View File

@@ -0,0 +1,27 @@
{$layout}
{$template "../menu"}
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<table class="ui table definition selectable">
<tr>
<td>域名 *</td>
<td>
<input type="text" name="name" maxlength="255" ref="focus"/>
</td>
</tr>
<tr>
<td class="title">所属集群 *</td>
<td>
<ns-cluster-selector></ns-cluster-selector>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<ns-user-selector></ns-user-selector>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifySuccess("保存成功", "/ns")
})

View File

@@ -0,0 +1,30 @@
{$layout}
{$template "domain_menu"}
<table class="ui table definition selectable">
<tr>
<td class="title">域名</td>
<td>{{domain.name}}</td>
</tr>
<tr>
<td>状态</td>
<td>
<label-on :v-is-on="domain.isOn"></label-on>
</td>
</tr>
<tr>
<td>所属集群</td>
<td>
{{domain.cluster.name}}<link-icon :href="'/ns/clusters/cluster?clusterId=' + domain.cluster.id"></link-icon>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<span v-if="domain.user != null">
{{domain.user.fullname}} ({{domain.user.username}})
</span>
<span v-else class="disabled">-</span>
</td>
</tr>
</table>

View File

@@ -0,0 +1,48 @@
{$layout "layout_popup"}
<h3>创建记录</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="domainId" :value="domain.id"/>
<table class="ui table definition selectable">
<tr>
<td class="title">记录名</td>
<td>
<div class="ui input right labeled">
<input type="text" name="name" ref="focus"/>
<span class="ui label">.{{domain.name}}</span>
</div>
</td>
</tr>
<tr>
<td>记录类型</td>
<td>
<select class="ui dropdown auto-width" name="type" v-model="type" @change="changeType">
<option v-for="t in types" :value="t.type">{{t.type}}</option>
</select>
<p class="comment">{{typeDescription}}</p>
</td>
</tr>
<tr>
<td>记录值</td>
<td>
<input type="text" name="value" maxlength="1024"/>
</td>
</tr>
<tr>
<td>TTL</td>
<td>
<select class="ui dropdown auto-width" name="ttl">
<option v-for="v in ttlValues" :value="v.value">{{v.name}}</option>
</select>
</td>
</tr>
<tr>
<td>备注</td>
<td>
<textarea rows="2" name="description"></textarea>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,15 @@
Tea.context(function () {
this.type = "A"
this.typeDescription = ""
this.changeType = function () {
let that = this
this.types.forEach(function (v) {
if (v.type == that.type) {
that.typeDescription = v.description
}
})
}
this.changeType()
})

View File

@@ -0,0 +1,37 @@
{$layout}
{$template "../domain_menu"}
<second-menu>
<menu-item @click.prevent="createRecord">[创建记录]</menu-item>
</second-menu>
<p class="comment" v-if="records.length == 0">暂时还没有记录。</p>
<table class="ui table selectable celled" v-if="records.length > 0">
<thead>
<tr>
<th>记录名</th>
<th>记录类型</th>
<th>记录值</th>
<th>TTL</th>
<th>线路</th>
<th>备注</th>
<th class="two op">操作</th>
</tr>
</thead>
<tr v-for="record in records">
<td>{{record.name}}</td>
<td>{{record.type}}</td>
<td>{{record.value}}</td>
<td>{{formatTTL(record.ttl)}}</td>
<td>
<span class="ui label basic text tiny" v-for="route in record.routes">{{route.name}}</span>
</td>
<td>{{record.description}}</td>
<td>
<a href="" @click.prevent="updateRecord(record.id)">修改</a> &nbsp;
<a href="" @click.prevent="deleteRecord(record.id)">删除</a>
</td>
</tr>
</table>
<div class="page" v-html="page"></div>

View File

@@ -0,0 +1,50 @@
Tea.context(function () {
this.createRecord = function () {
teaweb.popup("/ns/domains/records/createPopup?domainId=" + this.domain.id, {
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
})
}
this.updateRecord = function (recordId) {
teaweb.popup("/ns/domains/records/updatePopup?recordId=" + recordId, {
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
})
}
this.deleteRecord = function (recordId) {
let that = this
teaweb.confirm("确定要删除此记录吗?", function () {
that.$post(".delete")
.params({
recordId: recordId
})
.success(function () {
teaweb.reload()
})
})
}
this.formatTTL = function (ttl) {
if (ttl % 86400 == 0) {
let days = ttl / 86400
return days + "天"
}
if (ttl % 3600 == 0) {
let hours = ttl / 3600
return hours + "小时"
}
if (ttl % 60 == 0) {
let minutes = ttl / 60
return minutes + "分钟"
}
return ttl + "秒"
}
})

View File

@@ -0,0 +1,48 @@
{$layout "layout_popup"}
<h3>创建记录</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="recordId" :value="record.id"/>
<table class="ui table definition selectable">
<tr>
<td class="title">记录名</td>
<td>
<div class="ui input right labeled">
<input type="text" name="name" ref="focus" v-model="record.name"/>
<span class="ui label">.{{domain.name}}</span>
</div>
</td>
</tr>
<tr>
<td>记录类型</td>
<td>
<select class="ui dropdown auto-width" name="type" v-model="type" @change="changeType">
<option v-for="t in types" :value="t.type">{{t.type}}</option>
</select>
<p class="comment">{{typeDescription}}</p>
</td>
</tr>
<tr>
<td>记录值</td>
<td>
<input type="text" name="value" maxlength="1024" v-model="record.value"/>
</td>
</tr>
<tr>
<td>TTL</td>
<td>
<select class="ui dropdown auto-width" name="ttl" v-model="record.ttl">
<option v-for="v in ttlValues" :value="v.value">{{v.name}}</option>
</select>
</td>
</tr>
<tr>
<td>备注</td>
<td>
<textarea rows="2" name="description" v-model="record.description"></textarea>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,15 @@
Tea.context(function () {
this.type = this.record.type
this.typeDescription = ""
this.changeType = function () {
let that = this
this.types.forEach(function (v) {
if (v.type == that.type) {
that.typeDescription = v.description
}
})
}
this.changeType()
})

View File

@@ -0,0 +1,39 @@
{$layout}
{$template "domain_menu"}
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="domainId" :value="domain.id"/>
<table class="ui table definition selectable">
<tr>
<td>域名 *</td>
<td>
<input type="text" name="name" maxlength="255" ref="focus" v-model="domain.name"/>
</td>
</tr>
<tr>
<td class="title">所属集群 *</td>
<td>
<ns-cluster-selector :v-cluster-id="domain.clusterId"></ns-cluster-selector>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<ns-user-selector :v-user-id="domain.userId"></ns-user-selector>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>是否启用</td>
<td>
<checkbox name="isOn" value="1" v-model="domain.isOn"></checkbox>
</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifySuccess("保存成功", "/ns/domains/domain?domainId=" + this.domain.id)
})

View File

@@ -1 +1,61 @@
{$layout}
{$template "menu"}
<div v-if="countClusters == 0">
<not-found-box>
暂时还没有集群,请先 <a href="/ns/clusters">创建集群</a>
</not-found-box>
</div>
<div v-if="countClusters > 0">
<form class="ui form" method="get" action="/ns">
<div class="ui fields inline">
<div class="ui field">
<ns-cluster-selector :v-cluster-id="clusterId"></ns-cluster-selector>
</div>
<div class="ui field">
<ns-user-selector :v-user-id="userId"></ns-user-selector>
</div>
<div class="ui field">
<input type="text" name="keyword" v-model="keyword" placeholder="域名、备注..."/>
</div>
<div class="ui field">
<button class="ui button" type="submit">搜索</button>
</div>
</div>
</form>
<div v-if="domains.length == 0">
<div class="margin"></div>
<p class="comment">暂时还没有域名。</p>
</div>
<!-- 域名列表 -->
<table class="ui table selectable celled" v-if="domains.length > 0">
<thead>
<tr>
<th>域名</th>
<th>集群</th>
<th>用户</th>
<th class="two wide">状态</th>
<th class="two op">操作</th>
</tr>
</thead>
<tr v-for="domain in domains">
<td>{{domain.name}}</td>
<td>
{{domain.cluster.name}}<link-icon :href="'/ns/clusters/cluster?clusterId=' + domain.cluster.id"></link-icon>
</td>
<td>
<span v-if="domain.user != null">
{{domain.user.fullname}} ({{domain.user.username}})
</span>
<span v-else class="disabled">-</span>
</td>
<td><label-on :v-is-on="domain.isOn"></label-on></td>
<td>
<a :href="'/ns/domains/domain?domainId=' + domain.id">详情</a> &nbsp; <a href="" @click.prevent="deleteDomain(domain.id)">删除</a>
</td>
</tr>
</table>
</div>

View File

@@ -0,0 +1,14 @@
Tea.context(function () {
this.deleteDomain = function (domainId) {
let that = this
teaweb.confirm("确定要删除此域名吗?", function () {
that.$post("/ns/domains/delete")
.params({
domainId: domainId
})
.success(function () {
teaweb.reload()
})
})
}
})