This commit is contained in:
unknown
2026-02-04 20:27:13 +08:00
commit 3b042d1dad
9410 changed files with 1488147 additions and 0 deletions

View File

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

View File

@@ -0,0 +1,12 @@
<first-menu>
<menu-item href="/ns/domains">所有域名</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">解析记录({{domain.countRecords}})</menu-item>
<span class="item disabled">|</span>
<menu-item :href="'/ns/domains/update?domainId=' + domain.id" code="update">修改</menu-item>
<span class="item disabled">|</span>
<menu-item :href="'/ns/domains/healthCheck?domainId=' + domain.id" code="healthCheck">健康检查<span class="small green" v-if="domain.enableHealthCheck">(启用)</span><span></span></menu-item>
<menu-item :href="'/ns/domains/keys?domainId=' + domain.id" code="key">密钥({{domain.countKeys}})</menu-item>
<menu-item :href="'/ns/domains/tsig?domainId=' + domain.id" code="tsig">TSIG</menu-item>
</first-menu>

View File

@@ -0,0 +1,9 @@
<first-menu>
<menu-item href="/ns/domains/batch" :active="secondMenuItem == 'index'">添加域名</menu-item>
<menu-item href="/ns/domains/batch/deleteDomains" :active="secondMenuItem == 'deleteDomains'">删除域名</menu-item>
<menu-item href="/ns/domains/batch/createRecords" :active="secondMenuItem == 'createRecords'">添加解析</menu-item>
<menu-item href="/ns/domains/batch/updateRecords" :active="secondMenuItem == 'updateRecords'">修改解析</menu-item>
<menu-item href="/ns/domains/batch/deleteRecords" :active="secondMenuItem == 'deleteRecords'">删除解析</menu-item>
<menu-item href="/ns/domains/batch/enableRecords" :active="secondMenuItem == 'enableRecords'">启用/暂停解析</menu-item>
<menu-item href="/ns/domains/batch/importRecords" :active="secondMenuItem == 'importRecords'">混合添加解析</menu-item>
</first-menu>

View File

@@ -0,0 +1,42 @@
{$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 class="title">域名 *</td>
<td>
<textarea rows="15" name="names" placeholder="每行一个域名" ref="focus"></textarea>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<ns-user-selector></ns-user-selector>
<p class="comment">当前域名所属的平台用户。</p>
</td>
</tr>
<tr>
<td>解析记录 *</td>
<td>
<ns-create-records-table :v-types="types"></ns-create-records-table>
</td>
</tr>
<tr>
<td>删除原有同名记录</td>
<td>
<checkbox name="removeOld"></checkbox>
<p class="comment">选中后,在导入新的记录之前,先删除域名中的同名且同类型记录。</p>
</td>
</tr>
<tr>
<td>清空原有记录</td>
<td>
<checkbox name="removeAll"></checkbox>
<p class="comment">选中后,在导入新的记录之前,先清空域名中的所有记录。</p>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

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

View File

@@ -0,0 +1,22 @@
{$layout}
{$template "menu"}
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<table class="ui table selectable definition">
<tr>
<td class="title">域名 *</td>
<td>
<textarea name="names" rows="15" ref="focus" placeholder="每行一个域名"></textarea>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<ns-user-selector></ns-user-selector>
<p class="comment">当前域名所属的平台用户。</p>
</td>
</tr>
</table>
<submit-btn>批量删除</submit-btn>
</form>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("删除成功")
})

View File

@@ -0,0 +1,57 @@
{$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 class="title">域名 *</td>
<td>
<textarea rows="15" name="names" placeholder="每行一个域名" ref="focus"></textarea>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<ns-user-selector></ns-user-selector>
<p class="comment">当前域名所属的平台用户。</p>
</td>
</tr>
<tr>
<td>匹配条件</td>
<td>
<table class="ui table definition">
<tr>
<td class="title">记录名</td>
<td>
<input type="text" name="searchName"/>
<p class="comment">只有不为空时才生效。</p>
</td>
</tr>
<tr>
<td>记录值</td>
<td>
<input type="text" name="searchValue"/>
<p class="comment">只有不为空时才生效。</p>
</td>
</tr>
<tr>
<td>记录类型</td>
<td>
<select class="ui dropdown auto-width" name="searchType">
<option v-for="type in types" :value="type.type">{{type.type}}</option>
</select>
</td>
</tr>
<tr>
<td>线路</td>
<td>
<ns-routes-selector name="searchRouteCodes"></ns-routes-selector>
</td>
</tr>
</table>
</td>
</tr>
</table>
<submit-btn>批量删除</submit-btn>
</form>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("删除成功")
})

View File

@@ -0,0 +1,66 @@
{$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 class="title">域名 *</td>
<td>
<textarea rows="15" name="names" placeholder="每行一个域名" ref="focus"></textarea>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<ns-user-selector></ns-user-selector>
<p class="comment">当前域名所属的平台用户。</p>
</td>
</tr>
<tr>
<td>匹配条件</td>
<td>
<table class="ui table definition">
<tr>
<td class="title">记录名</td>
<td>
<input type="text" name="searchName"/>
<p class="comment">只有不为空时才生效。</p>
</td>
</tr>
<tr>
<td>记录值</td>
<td>
<input type="text" name="searchValue"/>
<p class="comment">只有不为空时才生效。</p>
</td>
</tr>
<tr>
<td>记录类型</td>
<td>
<select class="ui dropdown auto-width" name="searchType">
<option v-for="type in types" :value="type.type">{{type.type}}</option>
</select>
</td>
</tr>
<tr>
<td>线路</td>
<td>
<ns-routes-selector name="searchRouteCodes"></ns-routes-selector>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>修改状态为</td>
<td>
<select class="ui dropdown auto-width" name="isOn">
<option value="1">启用</option>
<option value="0">停用</option>
</select>
</td>
</tr>
</table>
<submit-btn>批量修改</submit-btn>
</form>

View File

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

View File

@@ -0,0 +1,24 @@
{$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 class="title">解析记录 *</td>
<td>
<textarea rows="15" name="records" placeholder="每行一个解析记录
example.com www A 192.168.1.100 600" ref="focus"></textarea>
<p class="comment">每行一个解析记录,格式:<code-label>域名 记录名 记录类型 记录值 TTL</code-label>,比如<code-label>example.com www A 192.168.1.100 600</code-label>,各项用空格隔开。</p>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<ns-user-selector></ns-user-selector>
<p class="comment">当前域名所属的平台用户。</p>
</td>
</tr>
</table>
<submit-btn>批量导入</submit-btn>
</form>

View File

@@ -0,0 +1,3 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("导入成功")
})

View File

@@ -0,0 +1,35 @@
{$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>
<textarea rows="15" name="names" placeholder="每行一个域名" ref="namesInput"></textarea>
</td>
</tr>
<tr>
<td class="title">所属集群 *</td>
<td>
<ns-cluster-selector></ns-cluster-selector>
<p class="comment">需要部署域名服务的集群。</p>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<ns-user-selector @change="changeUserId"></ns-user-selector>
<p class="comment">当前域名所属的平台用户。</p>
</td>
</tr>
<tr v-if="hasGroups">
<td>所属分组</td>
<td>
<ns-domain-group-selector ref="groupSelector"></ns-domain-group-selector>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,24 @@
Tea.context(function () {
this.$delay(function () {
this.$refs.namesInput.focus()
this.changeUserId(0)
})
this.success = NotifyReloadSuccess("保存成功")
this.hasGroups = false
this.changeUserId = function (userId) {
this.$post("/ns/domains/groups/options")
.params({
userId: userId
})
.success(function (resp) {
this.hasGroups = resp.data.groups.length > 0
if (this.hasGroups) {
this.$delay(function () {
this.$refs.groupSelector.reload(userId)
})
}
})
}
})

View File

@@ -0,0 +1,92 @@
{$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 class="title">域名 *</td>
<td>
<textarea rows="15" name="names" placeholder="每行一个域名" ref="focus"></textarea>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<ns-user-selector></ns-user-selector>
<p class="comment">当前域名所属的平台用户。</p>
</td>
</tr>
<tr>
<td>匹配条件</td>
<td>
<table class="ui table definition">
<tr>
<td class="title">记录名</td>
<td>
<input type="text" name="searchName"/>
<p class="comment">只有不为空时才生效。</p>
</td>
</tr>
<tr>
<td>记录值</td>
<td>
<input type="text" name="searchValue"/>
<p class="comment">只有不为空时才生效。</p>
</td>
</tr>
<tr>
<td>记录类型</td>
<td>
<select class="ui dropdown auto-width" name="searchType">
<option v-for="type in types" :value="type.type">{{type.type}}</option>
</select>
</td>
</tr>
<tr>
<td>线路</td>
<td>
<ns-routes-selector name="searchRouteCodes"></ns-routes-selector>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>修改后的记录</td>
<td>
<table class="ui table definition">
<tr>
<td class="title">记录名</td>
<td>
<input type="text" name="newName"/>
<p class="comment">只有不为空时才生效。</p>
</td>
</tr>
<tr>
<td>记录值</td>
<td>
<input type="text" name="newValue"/>
<p class="comment">只有不为空时才生效。</p>
</td>
</tr>
<tr>
<td>记录类型</td>
<td>
<select class="ui dropdown auto-width" name="newType">
<option v-for="type in types" :value="type.type">{{type.type}}</option>
</select>
</td>
</tr>
<tr>
<td>线路</td>
<td>
<ns-routes-selector name="newRouteCodes"></ns-routes-selector>
</td>
</tr>
</table>
</td>
</tr>
</table>
<submit-btn>批量修改</submit-btn>
</form>

View File

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

View File

@@ -0,0 +1,63 @@
{$layout}
{$template "menu"}
<div v-if="countClusters == 0">
<not-found-box>
暂时还没有集群,请先 <a href="/ns/clusters/create">创建集群</a>
</not-found-box>
</div>
<div v-show="countClusters > 0">
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="addingType" :value="addingType"/>
<table class="ui table definition selectable">
<tr>
<td>域名 *</td>
<td>
<!-- 单个添加 -->
<div v-show="addingType == 'one'">
<input type="text" name="name" maxlength="255" ref="nameInput" placeholder="单个域名"/>
<p class="comment">
<a href="" @click.prevent="setAddingType('batch')">[批量添加]</a>
</p>
</div>
<!-- 批量添加 -->
<div v-show="addingType == 'batch'">
<textarea rows="10" name="names" placeholder="每行一个域名" ref="namesInput"></textarea>
<p class="comment">
<a href="" @click.prevent="setAddingType('one')">[单个添加]</a>
</p>
</div>
</td>
</tr>
<tr>
<td class="title">所属集群 *</td>
<td>
<ns-cluster-selector></ns-cluster-selector>
<p class="comment">需要部署域名服务的集群。</p>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>所属用户</td>
<td>
<ns-user-selector @change="changeUserId"></ns-user-selector>
<p class="comment">当前域名所属的平台用户。</p>
</td>
</tr>
<tr v-if="hasGroups">
<td>所属分组</td>
<td>
<ns-domain-group-selector ref="groupSelector"></ns-domain-group-selector>
</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,42 @@
Tea.context(function () {
this.addingType = "one"
this.$delay(function () {
this.$refs.nameInput.focus()
this.changeUserId(0)
})
this.success = NotifySuccess("保存成功", "/ns/domains")
this.setAddingType = function (addingType) {
this.addingType = addingType
switch (addingType) {
case "one":
this.$delay(function () {
this.$refs.nameInput.focus()
})
break
case "batch":
this.$delay(function () {
this.$refs.namesInput.focus()
})
break
}
}
this.hasGroups = false
this.changeUserId = function (userId) {
this.$post("/ns/domains/groups/options")
.params({
userId: userId
})
.success(function (resp) {
this.hasGroups = resp.data.groups.length > 0
if (this.hasGroups) {
this.$delay(function () {
this.$refs.groupSelector.reload(userId)
})
}
})
}
})

View File

@@ -0,0 +1,41 @@
{$layout}
{$template "../menu_domain"}
<table class="ui table definition selectable">
<tr>
<td class="title">域名</td>
<td>{{domain.name}}</td>
</tr>
<tr>
<td>状态</td>
<td>
<span v-if="!domain.isOn" class="red">已停用</span>
<span v-if="domain.isOn" :class="{green:domain.status == 'verified', red:domain.status == 'rejected' || domain.status == 'forbidden'}">{{domain.statusName}}</span>
&nbsp; &nbsp; <a href="" @click.prevent="updateDomainStatus(domain.id)" v-if="domain.isOn"><span class="small">[修改状态]</span></a>
</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>
<tr>
<td>所属分组</td>
<td>
<div v-if="domain.groups.length > 0">
<a :href="'/ns/domains?userId=' + group.userId + '&groupId=' + group.id" class="ui label small basic" v-for="group in domain.groups">{{group.name}}</a>
</div>
<span v-else class="disabled">暂时没有分组</span>
</td>
</tr>
</table>

View File

@@ -0,0 +1,9 @@
Tea.context(function () {
this.updateDomainStatus = function (domainId) {
teaweb.popup("/ns/domains/domain/updateStatusPopup?domainId=" + domainId, {
callback: function () {
teaweb.successRefresh("保存成功")
}
})
}
})

View File

@@ -0,0 +1,21 @@
{$layout "layout_popup"}
<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>{{domain.name}}</td>
</tr>
<tr>
<td>状态 *</td>
<td>
<select class="ui dropdown auto-width" name="status" v-model="domain.status">
<option v-for="status in statusList" :value="status.code">{{status.name}}</option>
</select>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,15 @@
{$layout "layout_popup"}
<h3>创建分组</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<table class="ui table selectable definition">
<tr>
<td class="title">分组名称 *</td>
<td>
<input type="text" name="name" maxlength="100" ref="focus"/>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,22 @@
{$layout "layout_popup"}
<h3>修改分组</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="groupId" :value="group.id"/>
<table class="ui table selectable definition">
<tr>
<td class="title">分组名称 *</td>
<td>
<input type="text" name="name" maxlength="100" ref="focus" v-model="group.name"/>
</td>
</tr>
<tr>
<td>启用</td>
<td>
<checkbox name="isOn" v-model="group.isOn"></checkbox>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,31 @@
{$layout}
<first-menu>
<menu-item href="/ns/domains/groups" active="true">分组列表</menu-item>
<span class="item disabled">|</span>
<menu-item @click.prevent="createGroup">[创建分组]</menu-item>
</first-menu>
<not-found-box v-if="groups.length == 0">暂时还没有分组。</not-found-box>
<table class="ui table selectable celled" v-if="groups.length > 0">
<thead>
<tr>
<th>分组名称</th>
<th class="width6">状态</th>
<th class="two op">操作</th>
</tr>
</thead>
<tr v-for="group in groups">
<td>
<a href="" @click.prevent="updateGroup(group.id)">{{group.name}} <i class="icon expand small"></i></a>
</td>
<td>
<label-on :v-is-on="group.isOn"></label-on>
</td>
<td>
<a href="" @click.prevent="updateGroup(group.id)">修改</a> &nbsp;
<a href="" @click.prevent="deleteGroup(group.id)">删除</a>
</td>
</tr>
</table>

View File

@@ -0,0 +1,30 @@
Tea.context(function () {
this.createGroup = function () {
teaweb.popup("/ns/domains/groups/createPopup", {
callback: function () {
teaweb.successRefresh("保存成功")
}
})
}
this.updateGroup = function (groupId) {
teaweb.popup("/ns/domains/groups/group/updatePopup?groupId=" + groupId, {
callback: function () {
teaweb.successRefresh("保存成功")
}
})
}
this.deleteGroup = function (groupId) {
let that = this
teaweb.confirm("确定要删除此分组吗?", function () {
that.$post("/ns/domains/groups/group/delete")
.params({
groupId: groupId
})
.success(function () {
teaweb.successRefresh("删除成功")
})
})
}
})

View File

@@ -0,0 +1,14 @@
{$layout}
{$template "menu_domain"}
<p class="ui message warning" v-if="!canUpdate">当前用户没有权限修改健康检查设置,请检查用户所属套餐。</p>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="domainId" :value="domainId"/>
<ns-records-health-check-config-box v-model="config"></ns-records-health-check-config-box>
<submit-btn :class="{disabled: !canUpdate}"></submit-btn>
</form>

View File

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

View File

@@ -0,0 +1,98 @@
{$layout}
{$template "menu"}
<div class="margin"></div>
<div v-if="countClusters == 0">
<not-found-box>
暂时还没有集群,请先 <a href="/ns/clusters/create">创建集群</a>
</not-found-box>
</div>
<div v-if="countClusters > 0">
<form class="ui form" method="get" action="/ns/domains" v-show="!hasSelectedDomains">
<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" @change="changeUserId"></ns-user-selector>
</div>
<div class="ui field" v-if="hasGroups">
<ns-domain-group-selector :v-domain-group-id="groupId" ref="groupSelector"></ns-domain-group-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>
&nbsp;
<a :href="Tea.url('.')" v-if="clusterId > 0 || userId > 0 || groupId > 0 || keyword.length > 0">[清除条件]</a>
</div>
</div>
</form>
<form class="ui form" v-show="hasSelectedDomains">
<div class="ui fields inline">
<div class="ui field">
<button class="ui button basic" type="button" @click.prevent="deleteDomains">批量删除选中域名</button>
</div>
<div class="ui field">
<button class="ui button basic" type="button" @click.prevent="cancelDomains">取消</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 style="width: 1em">
<checkbox v-model="selectedAll"></checkbox>
</th>
<th>域名</th>
<th class="four wide">集群</th>
<th class="four wide">用户</th>
<th class="width5">状态</th>
<th class="two op">操作</th>
</tr>
</thead>
<tr v-for="domain in domains">
<td>
<checkbox ref="domainCheckbox" :v-value="domain.id" :checked="selectedAll ? 'checked' : ''"
@input="changeSelectedDomains" :status="domain.status"></checkbox>
</td>
<td>
<a :href="'/ns/domains/records?domainId=' + domain.id"><keyword :v-word="keyword">{{domain.name}}</keyword></a>
<div v-if="domain.groups.length > 0">
<a v-for="group in domain.groups" :href="'/ns/domains?userId=' + group.userId + '&groupId=' + group.id"><grey-label :key="group.id">{{group.name}}</grey-label></a>
</div>
</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>
<a :href="'/ns/domains/domain?domainId=' + domain.id">
<span v-if="!domain.isOn" class="red">已停用</span>
<span v-if="domain.isOn" :class="{green:domain.status == 'verified', red:domain.status == 'rejected' || domain.status == 'forbidden', grey:domain.status == 'none'}">{{domain.statusName}}</span>
</a>
</td>
<td>
<a :href="'/ns/domains/records?domainId=' + domain.id">详情</a> &nbsp; <a href="" @click.prevent="deleteDomain(domain.id)">删除</a>
</td>
</tr>
</table>
<page-box></page-box>
</div>

View File

@@ -0,0 +1,119 @@
Tea.context(function () {
this.$delay(function () {
this.changeUserId(this.userId)
})
this.deleteDomain = function (domainId) {
let that = this
teaweb.confirm("确定要删除此域名吗?", function () {
that.$post("/ns/domains/delete")
.params({
domainId: domainId
})
.success(function () {
teaweb.reload()
})
})
}
this.hasGroups = false
this.changeUserId = function (userId) {
this.$post("/ns/domains/groups/options")
.params({
userId: userId
})
.success(function (resp) {
this.hasGroups = resp.data.groups.length > 0
if (this.hasGroups) {
this.$delay(function () {
this.$refs.groupSelector.reload(userId)
})
}
})
}
/**
* 批量操作
*/
this.selectedAll = false
this.hasSelectedDomains = false
this.hasVerifyingDomains = false
this.$delay(function () {
let that = this
this.$watch("selectedAll", function (b) {
let checkboxes = that.$refs.domainCheckbox
if (checkboxes != null) {
checkboxes.forEach(function (checkbox) {
if (b) {
checkbox.check()
that.hasSelectedDomains = true
let status = checkbox.$el.getAttribute("status")
if (status == "none") {
that.hasVerifyingDomains = true
}
} else {
checkbox.uncheck()
that.hasSelectedDomains = false
}
})
}
})
})
this.changeSelectedDomains = function () {
if (this.$refs == null) {
return
}
let checkboxes = this.$refs.domainCheckbox
if (checkboxes != null) {
let hasSelectedDomains = false
let hasVerifyingDomains = false
checkboxes.forEach(function (checkbox) {
if (checkbox.isChecked()) {
hasSelectedDomains = true
let status = checkbox.$el.getAttribute("status")
if (status == "none") {
hasVerifyingDomains = true
}
}
})
this.hasSelectedDomains = hasSelectedDomains
this.hasVerifyingDomains = hasVerifyingDomains
return
}
}
this.cancelDomains = function () {
let checkboxes = this.$refs.domainCheckbox
checkboxes.forEach(function (checkbox) {
checkbox.uncheck()
})
this.selectedAll = false
this.hasSelectedDomains = false
this.hasVerifyingDomains = false
}
this.deleteDomains = function () {
let checkboxes = this.$refs.domainCheckbox
let domainIds = []
checkboxes.forEach(function (checkbox) {
if (checkbox.isChecked()) {
let domainId = checkbox.vValue
if (typeof domainId == "number") {
domainIds.push(domainId)
}
}
})
let that = this
teaweb.confirm("确定要删除选中的域名吗?", function () {
that.$post(".deletePage")
.params({
domainIds: domainIds
})
.success(function () {
teaweb.successRefresh("删除成功")
})
})
}
})

View File

@@ -0,0 +1,40 @@
{$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="domainId"/>
<table class="ui table definition selectable">
<tr>
<td class="title">密钥名称 *</td>
<td>
<input type="text" name="name" ref="focus"/>
</td>
</tr>
<tr>
<td>算法 *</td>
<td>
<select class="ui dropdown auto-width" name="algo">
<option value="">[选择算法]</option>
<option v-for="algo in algorithms" :value="algo.code">{{algo.name}}</option>
</select>
</td>
</tr>
<tr>
<td>密码 *</td>
<td>
<div style="margin-bottom: 1em">
<radio name="secretType" value="clear" :v-value="'clear'" v-model="secretType">明文密码</radio>
&nbsp; &nbsp;
<radio name="secretType" value="base64" :v-value="'base64'" v-model="secretType">Base64密码</radio>
</div>
<textarea name="secret" maxlength="256" v-model="secret" rows="3"></textarea>
<p class="comment" v-if="secretType == 'clear'">客户端需要将明文转换为BASE64使用。</p>
<div style="margin-top: 1em">
<a href="" @click.prevent="generateSecret">[随机生成]</a>
</div>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,20 @@
Tea.context(function () {
this.secretType = "clear"
this.secret = ""
this.$delay(function () {
this.$watch("secretType", function () {
this.secret = ""
})
})
this.generateSecret = function () {
this.$post(".generateSecret")
.params({
secretType: this.secretType
})
.success(function (resp) {
this.secret = resp.data.secret
})
}
})

View File

@@ -0,0 +1,38 @@
{$layout}
{$template "../menu_domain"}
<second-menu>
<menu-item @click.prevent="createKey">[创建密钥]</menu-item>
</second-menu>
<tip-message-box>这里的密钥可以用于TSIG通讯校验。</tip-message-box>
<p class="comment" v-if="keys.length == 0">暂时还没有密钥。</p>
<table class="ui table celled selectable" v-if="keys.length > 0">
<thead>
<tr>
<th class="three wide">密钥名称</th>
<th class="three wide">算法</th>
<th>密码</th>
<th class="two wide">密码类型</th>
<th class="two wide">状态</th>
<th class="two op">操作</th>
</tr>
</thead>
<tr v-for="key in keys">
<td>{{key.name}}</td>
<td>{{key.algoName}}</td>
<td>{{key.secret}}</td>
<td>{{key.secretTypeName}}</td>
<td>
<label-on :v-is-on="key.isOn"></label-on>
</td>
<td>
<a href="" @click.prevent="updateKey(key.id)">修改</a> &nbsp;
<a href="" @click.prevent="deleteKey(key.id)">删除</a>
</td>
</tr>
</table>
<div class="page" v-html="page"></div>

View File

@@ -0,0 +1,31 @@
Tea.context(function () {
this.createKey = function () {
teaweb.popup(Tea.url(".createPopup?domainId=" + this.domain.id), {
height: "24em",
callback: function () {
teaweb.successRefresh("保存成功")
}
})
}
this.updateKey = function (keyId) {
teaweb.popup(Tea.url(".updatePopup?keyId=" + keyId), {
height: "27em",
callback: function () {
teaweb.successRefresh("保存成功")
}
})
}
this.deleteKey = function (keyId) {
teaweb.confirm("确定要删除这个密钥吗?", function () {
this.$post(".delete")
.params({
keyId: keyId
})
.success(function () {
teaweb.successRefresh("删除成功")
})
})
}
})

View File

@@ -0,0 +1,46 @@
{$layout "layout_popup"}
<h3>修改密钥</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="keyId" :value="key.id"/>
<table class="ui table definition selectable">
<tr>
<td class="title">密钥名称 *</td>
<td>
<input type="text" name="name" ref="focus" v-model="key.name"/>
</td>
</tr>
<tr>
<td>算法 *</td>
<td>
<select class="ui dropdown auto-width" name="algo" v-model="key.algo">
<option value="">[选择算法]</option>
<option v-for="algo in algorithms" :value="algo.code">{{algo.name}}</option>
</select>
</td>
</tr>
<tr>
<td>密码 *</td>
<td>
<div style="margin-bottom: 1em">
<radio name="secretType" value="clear" :v-value="'clear'" v-model="secretType">明文密码</radio>
&nbsp; &nbsp;
<radio name="secretType" value="base64" :v-value="'base64'" v-model="secretType">Base64密码</radio>
</div>
<textarea name="secret" maxlength="256" v-model="secret" rows="3"></textarea>
<p class="comment" v-if="secretType == 'clear'">客户端需要将明文转换为BASE64使用。</p>
<div style="margin-top: 1em">
<a href="" @click.prevent="generateSecret">[随机生成]</a>
</div>
</td>
</tr>
<tr>
<td>启用</td>
<td>
<checkbox name="isOn" v-model="key.isOn"></checkbox>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,20 @@
Tea.context(function () {
this.secretType = this.key.secretType
this.secret = this.key.secret
this.$delay(function () {
this.$watch("secretType", function () {
this.secret = ""
})
})
this.generateSecret = function () {
this.$post(".generateSecret")
.params({
secretType: this.secretType
})
.success(function (resp) {
this.secret = resp.data.secret
})
}
})

View File

@@ -0,0 +1,125 @@
{$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"/>
<input type="hidden" name="addingType" :value="addingType"/>
<table class="ui table definition selectable">
<tr>
<td class="title">记录名</td>
<td>
<!-- 单个添加 -->
<div v-if="addingType == 'one'">
<div class="ui input right labeled">
<input type="text" name="name" ref="nameInput" v-model="name" @input="changeName" style="width: 16em"/>
<span class="ui label">.{{domain.name}}</span>
</div>
<p class="comment">
<span class="red" v-if="nameWarning">请确认使用非标准记录名(标准记录名只能包含小写字母、数字、中划线-、下划线_的组合</span>
<a href="" @click.prevent="setAddingType('batch')">[批量添加]</a>
</p>
</div>
<!-- 批量添加 -->
<div v-if="addingType == 'batch'">
<textarea name="names" rows="10" placeholder="每行一个,不需要加顶级域名" ref="namesInput"></textarea>
<p class="comment"><a href="" @click.prevent="setAddingType('one')">[单个添加]</a></p>
</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="512"/>
</td>
</tr>
<!-- MX -->
<tr v-show="type == 'MX'">
<td class="color-border">MX优先级</td>
<td>
<input type="text" name="mxPriority" value="10" maxlength="5" size="5" style="width: 6em"/>
<p class="comment">数字越小越优先最高为0。</p>
</td>
</tr>
<!-- SRV -->
<tr v-show="type == 'SRV'">
<td class="color-border">SRV端口 *</td>
<td>
<input type="text" name="srvPort" value="" maxlength="5" size="5" style="width: 6em"/>
</td>
</tr>
<tr v-show="type == 'SRV'">
<td class="color-border">SRV优先级</td>
<td>
<input type="text" name="srvPriority" value="10" maxlength="5" size="5" style="width: 6em"/>
</td>
</tr>
<tr v-show="type == 'SRV'">
<td class="color-border">SRV权重</td>
<td>
<input type="text" name="srvWeight" value="10" maxlength="5" size="5" style="width: 6em"/>
</td>
</tr>
<!-- CAA -->
<tr v-show="type == 'CAA'">
<td class="color-border">CAA等级</td>
<td>
<input type="text" name="caaFlag" value="0" maxlength="3" size="5" style="width: 4em"/>
<p class="comment">取值在0到128之间。</p>
</td>
</tr>
<tr v-show="type == 'CAA'">
<td class="color-border">CAA标签</td>
<td>
<select class="ui dropdown auto-width" name="caaTag">
<option value="issue">issue</option>
<option value="issuewild">issuewild</option>
<option value="iodef">iodef</option>
</select>
</td>
</tr>
<tr>
<td>TTL</td>
<td>
<div class="ui input right labeled">
<input type="text" name="ttl" maxlength="10" style="width: 6em" v-model="ttl"/>
<span class="ui label"></span>
</div>
</td>
</tr>
<tr>
<td>线路</td>
<td>
<ns-routes-selector></ns-routes-selector>
</td>
</tr>
<tr>
<td>权重</td>
<td>
<input type="text" name="weight" style="width: 6em" maxlength="6" value="0"/>
<p class="comment">不大于0的权重将当做10处理。</p>
</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,44 @@
Tea.context(function () {
this.name = ""
this.type = "A"
this.typeDescription = ""
this.ttl = 600
this.nameWarning = false
this.changeName = function () {
this.nameWarning = this.name.length > 0 && !this.name.match(/^[0-9a-z_@*-.]+$/)
}
this.changeType = function () {
let that = this
this.types.forEach(function (v) {
if (v.type == that.type) {
that.typeDescription = v.description
}
})
}
this.changeType()
// 单个添加或者批量添加
this.addingType = "one"
this.$delay(function () {
this.$refs.nameInput.focus()
})
this.setAddingType = function (addingType) {
this.addingType = addingType
this.$delay(function () {
switch (addingType) {
case "one":
this.$refs.nameInput.focus()
break
case "batch":
this.$refs.namesInput.focus()
break
}
})
}
})

View File

@@ -0,0 +1,21 @@
{$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>
<span v-if="record.name.length > 0">{{record.name}}</span><span v-else class="disabled">[空]</span>.{{domain.name}}. {{record.type}} {{record.value}}
</td>
</tr>
</table>
<ns-record-health-check-config-box v-model="record.healthCheckConfig" :v-parent-config="domain.healthCheckConfig"></ns-record-health-check-config-box>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,21 @@
table thead th span {
font-weight: normal;
font-size: 0.8em;
}
table td.health-check-status-box {
text-align: center!important;
}
table td.health-check-status-box a {
display: none;
}
table td.health-check-status-box span.status {
display: none;
font-size: 0.8em;
}
table td.health-check-status-box:hover a {
display: inline;
}
table td.health-check-status-box:hover span.status {
display: inline;
}
/*# sourceMappingURL=index.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA,KACC,MACC,GACC;EACC,mBAAA;EACA,gBAAA;;AALJ,KAUC,GAAE;EACD,4BAAA;;AAXF,KAUC,GAAE,wBAGD;EACC,aAAA;;AAdH,KAUC,GAAE,wBAOD,KAAI;EACH,aAAA;EACA,gBAAA;;AAnBH,KAuBC,GAAE,wBAAwB,MACzB;EACC,eAAA;;AAzBH,KAuBC,GAAE,wBAAwB,MAKzB,KAAI;EACH,eAAA","file":"index.css"}

View File

@@ -0,0 +1,95 @@
{$layout}
{$template "../menu_domain"}
<second-menu>
<menu-item @click.prevent="createRecord">[创建记录]</menu-item>
</second-menu>
<form class="ui form" method="get" action="/ns/domains/records" ref="recordsSearchForm">
<input type="hidden" name="domainId" :value="domain.id"/>
<div class="ui fields inline">
<div class="ui field">
<select class="ui dropdown" name="type" v-model="type">
<option value="">[记录类型]</option>
<option v-for="t in types" :value="t.type">{{t.type}}</option>
</select>
</div>
<div class="ui field">
<ns-route-selector :v-route-code="routeCode"></ns-route-selector>
</div>
<div class="ui field">
<input type="text" placeholder="记录名、备注..." name="keyword" v-model="keyword" style="width: 20em"/>
</div>
<div class="ui field">
<button type="submit" class="ui button">搜索</button>
</div>
</div>
</form>
<p class="comment" v-if="records.length == 0">暂时还没有记录。</p>
<div v-if="enableNameSearch || enableValueSearch" style="margin-top: 1em">
<a href="" v-if="enableNameSearch" class="ui label basic small blue" style="font-weight: normal" @click.prevent="searchWithName(searchingKeyword)">使用name:"{{searchingKeyword}}"精确搜索</a>
<a href="" v-if="enableValueSearch" class="ui label basic small blue" style="font-weight: normal" @click.prevent="searchWithValue(searchingKeyword)">使用value:"{{searchingKeyword}}"精确搜索</a>
</div>
<table class="ui table selectable celled" v-if="records.length > 0">
<thead>
<tr>
<th class="two wide">记录名 <sort-arrow name="nameOrder"></sort-arrow>
<br/><span>&nbsp;</span>
</th>
<th class="two wide">记录类型 <sort-arrow name="typeOrder"></sort-arrow><br/><span>&nbsp;</span></th>
<th>记录值<br/><span>&nbsp;</span></th>
<th class="two wide">TTL <sort-arrow name="ttlOrder"></sort-arrow><br/><span>&nbsp;</span></th>
<th class="two wide">线路<br/><span>&nbsp;</span></th>
<th style="width: 8em; text-align: center" v-show="domainHealthCheckIsOn">健康检查 <sort-arrow name="upOrder"></sort-arrow><br/><span>&nbsp;</span></th>
<th class="two wide">解析次数<br/><span class="grey">当前小时内</span></th>
<th class="width6">状态<br/><span>&nbsp;</span></th>
<th class="two op">操作<br/><span>&nbsp;</span></th>
</tr>
</thead>
<tr v-for="record in records">
<td><keyword :v-word="keyword">{{record.name}} &nbsp;</keyword>
<div v-if="(record.description != null && record.description.length > 0) || record.weight > 0 || (record.type == 'MX')">
<span class="grey small" v-if="record.description != null && record.description.length > 0"><keyword :v-word="keyword">{{record.description}}</keyword></span>
<span class="grey small" v-if="record.weight > 0">权重:{{record.weight}}</span>
<span class="grey small" v-if="record.type == 'MX'">优先级:{{record.mxPriority}}</span>
</div>
</td>
<td>{{record.type}}</td>
<td><keyword :v-word="keyword">{{record.value}}</keyword></td>
<td>{{formatTTL(record.ttl)}}</td>
<td>
<div v-for="route in record.routes" style="margin-top: 0.3em; margin-bottom: 0.3em">
<span class="ui label basic text tiny">{{route.name}}</span>
</div>
</td>
<td v-show="domainHealthCheckIsOn" class="health-check-status-box">
<div v-if="record.type == 'A' || record.type == 'AAAA'">
<span v-if="record.healthCheck.isOn">
<span v-if="record.isUp" title="在线"><i class="icon green circle small"></i><span class="status green">在线</span></span>
<span v-if="!record.isUp" title="离线"><i class="icon red circle small"></i><span class="status red">离线</span></span>
</span>
<span v-else class="disabled">
<i class="icon circle small"></i>
</span>
<br/>
<a href="" style="font-size: 0.9em; margin-top: 0.12em" @click.prevent="updateRecordHealthCheck(record.id)">[设置]</a>
<span v-if="!record.isUp">&nbsp; <a href="" @click.prevent="upRecord(record)">[上线]</a></span>
</div>
</td>
<td>
<a href="" @click.prevent="showStat(record.id)" title="查看统计"><i class="icon chart area small"></i></a>
<span v-if="record.stat.countRequests > 0">{{record.stat.countRequestsFormat}}</span>
<span v-else class="disabled">-</span>
</td>
<td><label-on :v-is-on="record.isOn"></label-on></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,97 @@
Tea.context(function () {
this.createRecord = function () {
teaweb.popup(".createPopup?domainId=" + this.domain.id, {
height: "35em",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
})
}
this.updateRecord = function (recordId) {
teaweb.popup(".updatePopup?recordId=" + recordId, {
height: "35em",
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.searchWithName = function (keyword) {
this.keyword = "name:\"" + keyword + "\""
this.$delay(function () {
this.$refs.recordsSearchForm.submit()
})
}
this.searchWithValue = function (keyword) {
this.keyword = "value:\"" + keyword + "\""
this.$delay(function () {
this.$refs.recordsSearchForm.submit()
})
}
this.showStat = function (recordId) {
teaweb.popup(".statPopup?recordId=" + recordId, {
})
}
this.updateRecordHealthCheck = function (recordId) {
teaweb.popup(".healthCheckPopup?recordId=" + recordId, {
height: "26em",
callback: function () {
teaweb.success("设置成功", function () {
teaweb.reload()
})
}
})
}
this.upRecord = function (record) {
record.isUp = true
this.$post(".updateUp")
.params({
recordId: record.id
})
.success(function () {
teaweb.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,33 @@
table {
thead {
th {
span {
font-weight: normal;
font-size: 0.8em;
}
}
}
td.health-check-status-box {
text-align: center!important;
a {
display: none;
}
span.status {
display: none;
font-size: 0.8em;
}
}
td.health-check-status-box:hover {
a {
display: inline;
}
span.status {
display: inline;
}
}
}

View File

@@ -0,0 +1,4 @@
#stat-chart {
height: 18em;
}
/*# sourceMappingURL=statPopup.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["statPopup.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"statPopup.css"}

View File

@@ -0,0 +1,6 @@
{$layout "layout_popup"}
{$template "/echarts"}
<h3>记录"{{record.name}}"解析量统计 <span v-for="routeName in record.routeNames" class="ui label basic tiny">{{routeName}}</span></h3>
<div id="stat-chart"></div>

View File

@@ -0,0 +1,32 @@
Tea.context(function () {
this.$delay(function () {
this.reloadChart()
})
this.reloadChart = function () {
let axis = teaweb.countAxis(this.stats, function (stat){
return stat.countRequests
})
teaweb.renderLineChart({
id: "stat-chart",
name: "解析量统计",
values: this.stats,
x: function (stat) {
return stat.hour.substring(8)
},
tooltip: function (args, stats) {
let index = args.dataIndex
let year = stats[index].hour.substring(0, 4)
let month = stats[index].hour.substring(4, 6)
let day = stats[index].hour.substring(6, 8)
let hour = stats[index].hour.substring(8, 10)
return year + "-" + month + "-" + day + " " + hour + "时<br/>解析次数:" + teaweb.formatNumber(stats[index].countRequests)
},
value: function (stat) {
return stat.countRequests/axis.divider
},
axis: axis
})
}
})

View File

@@ -0,0 +1,3 @@
#stat-chart {
height: 18em;
}

View File

@@ -0,0 +1,123 @@
{$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"/>
<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" style="width: 16em"/>
<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="512" v-model="record.value"/>
</td>
</tr>
<!-- MX -->
<tr v-show="type == 'MX'">
<td class="color-border">MX优先级</td>
<td>
<input type="text" name="mxPriority" value="10" v-model="record.mxPriority" maxlength="5" size="5" style="width: 6em"/>
<p class="comment">数字越小越优先最高为0。</p>
</td>
</tr>
<!-- SRV -->
<tr v-show="type == 'SRV'">
<td class="color-border">SRV端口 *</td>
<td>
<input type="text" name="srvPort" value="" maxlength="5" size="5" style="width: 6em" v-model="record.srvPort"/>
</td>
</tr>
<tr v-show="type == 'SRV'">
<td class="color-border">SRV优先级</td>
<td>
<input type="text" name="srvPriority" value="10" maxlength="5" size="5" style="width: 6em" v-model="record.srvPriority"/>
</td>
</tr>
<tr v-show="type == 'SRV'">
<td class="color-border">SRV权重</td>
<td>
<input type="text" name="srvWeight" value="10" maxlength="5" size="5" style="width: 6em" v-model="record.srvWeight"/>
</td>
</tr>
<!-- CAA -->
<tr v-show="type == 'CAA'">
<td class="color-border">CAA等级</td>
<td>
<input type="text" name="caaFlag" value="0" maxlength="3" size="5" style="width: 4em" v-model="record.caaFlag"/>
<p class="comment">取值在0到128之间。</p>
</td>
</tr>
<tr v-show="type == 'CAA'">
<td class="color-border">CAA标签</td>
<td>
<select class="ui dropdown auto-width" name="caaTag" v-model="record.caaTag">
<option value="issue">issue</option>
<option value="issuewild">issuewild</option>
<option value="iodef">iodef</option>
</select>
</td>
</tr>
<tr>
<td>TTL</td>
<td>
<div class="ui input right labeled">
<input type="text" name="ttl" maxlength="10" style="width: 6em" v-model="record.ttl"/>
<span class="ui label"></span>
</div>
</td>
</tr>
<tr>
<td>线路</td>
<td>
<ns-routes-selector :v-routes="record.routes"></ns-routes-selector>
</td>
</tr>
<tr>
<td>权重</td>
<td>
<input type="text" name="weight" style="width: 6em" maxlength="6" v-model="record.weight"/>
<p class="comment">不大于0的权重将当做10处理。</p>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>备注</td>
<td>
<textarea rows="2" name="description" v-model="record.description"></textarea>
</td>
</tr>
<tr>
<td>启用</td>
<td>
<checkbox name="isOn" v-model="record.isOn"></checkbox>
</td>
</tr>
</tbody>
</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,16 @@
{$layout}
{$template "menu_domain"}
<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">启用TSIG *</td>
<td>
<checkbox name="isOn" v-model="tsig.isOn"></checkbox>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

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

View File

@@ -0,0 +1,53 @@
{$layout}
{$template "menu_domain"}
<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>
{{domain.name}}
</td>
</tr>
<tr>
<td class="title">所属集群 *</td>
<td>
<ns-cluster-selector :v-cluster-id="domain.clusterId"></ns-cluster-selector>
<p class="comment">需要部署域名服务的集群。</p>
</td>
</tr>
<tr v-show="dnsHosts != null && dnsHosts.length > 0">
<td>DNS服务器</td>
<td>
<span v-for="host in dnsHosts" class="ui basic small label">{{host}}</span>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>所属用户</td>
<td>
<ns-user-selector :v-user-id="domain.userId" @change="changeUserId"></ns-user-selector>
<p class="comment">当前域名所属的平台用户。</p>
</td>
</tr>
<tr v-if="hasGroups">
<td>所属分组</td>
<td>
<ns-domain-group-selector :v-domain-group-id="domain.groupId" ref="groupSelector"></ns-domain-group-selector>
</td>
</tr>
<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,23 @@
Tea.context(function () {
this.$delay(function() {
this.changeUserId(this.domain.userId)
})
this.success = NotifySuccess("保存成功", "/ns/domains/domain?domainId=" + this.domain.id)
this.hasGroups = false
this.changeUserId = function (userId) {
this.$post("/ns/domains/groups/options")
.params({
userId: userId
})
.success(function (resp) {
this.hasGroups = resp.data.groups.length > 0
if (this.hasGroups) {
this.$delay(function () {
this.$refs.groupSelector.reload(userId)
})
}
})
}
})