mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-14 12:20:27 +08:00
多处域名列表支持批量输入
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package acme
|
package acme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
@@ -25,7 +26,7 @@ func (this *UpdateTaskPopupAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
task := taskResp.AcmeTask
|
var task = taskResp.AcmeTask
|
||||||
if task == nil {
|
if task == nil {
|
||||||
this.NotFound("acmeTask", params.TaskId)
|
this.NotFound("acmeTask", params.TaskId)
|
||||||
return
|
return
|
||||||
@@ -74,7 +75,7 @@ func (this *UpdateTaskPopupAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
providerMaps := []maps.Map{}
|
var providerMaps = []maps.Map{}
|
||||||
for _, provider := range providersResp.DnsProviders {
|
for _, provider := range providersResp.DnsProviders {
|
||||||
providerMaps = append(providerMaps, maps.Map{
|
providerMaps = append(providerMaps, maps.Map{
|
||||||
"id": provider.Id,
|
"id": provider.Id,
|
||||||
@@ -93,7 +94,7 @@ func (this *UpdateTaskPopupAction) RunPost(params struct {
|
|||||||
AcmeUserId int64
|
AcmeUserId int64
|
||||||
DnsProviderId int64
|
DnsProviderId int64
|
||||||
DnsDomain string
|
DnsDomain string
|
||||||
Domains []string
|
DomainsJSON []byte
|
||||||
AutoRenew bool
|
AutoRenew bool
|
||||||
AuthURL string
|
AuthURL string
|
||||||
|
|
||||||
@@ -123,11 +124,20 @@ func (this *UpdateTaskPopupAction) RunPost(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(params.Domains) == 0 {
|
var domains = []string{}
|
||||||
|
if len(params.DomainsJSON) > 0 {
|
||||||
|
err := json.Unmarshal(params.DomainsJSON, &domains)
|
||||||
|
if err != nil {
|
||||||
|
this.Fail("解析域名数据失败:" + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(domains) == 0 {
|
||||||
this.Fail("请输入证书域名列表")
|
this.Fail("请输入证书域名列表")
|
||||||
}
|
}
|
||||||
realDomains := []string{}
|
var realDomains = []string{}
|
||||||
for _, domain := range params.Domains {
|
for _, domain := range domains {
|
||||||
domain = strings.ToLower(domain)
|
domain = strings.ToLower(domain)
|
||||||
if params.AuthType == "dns" {
|
if params.AuthType == "dns" {
|
||||||
if !strings.HasSuffix(domain, "."+dnsDomain) && domain != dnsDomain {
|
if !strings.HasSuffix(domain, "."+dnsDomain) && domain != dnsDomain {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// 域名列表
|
// 域名列表
|
||||||
Vue.component("domains-box", {
|
Vue.component("domains-box", {
|
||||||
props: ["v-domains", "name"],
|
props: ["v-domains", "name", "v-support-wildcard"],
|
||||||
data: function () {
|
data: function () {
|
||||||
let domains = this.vDomains
|
let domains = this.vDomains
|
||||||
if (domains == null) {
|
if (domains == null) {
|
||||||
@@ -11,11 +11,47 @@ Vue.component("domains-box", {
|
|||||||
if (this.name != null && typeof this.name == "string") {
|
if (this.name != null && typeof this.name == "string") {
|
||||||
realName = this.name
|
realName = this.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let supportWildcard = true
|
||||||
|
if (typeof this.vSupportWildcard == "boolean") {
|
||||||
|
supportWildcard = this.vSupportWildcard
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
domains: domains,
|
domains: domains,
|
||||||
|
|
||||||
|
mode: "single", // single | batch
|
||||||
|
batchDomains: "",
|
||||||
|
|
||||||
isAdding: false,
|
isAdding: false,
|
||||||
addingDomain: "",
|
addingDomain: "",
|
||||||
realName: realName
|
|
||||||
|
isEditing: false,
|
||||||
|
editingIndex: -1,
|
||||||
|
|
||||||
|
realName: realName,
|
||||||
|
supportWildcard: supportWildcard
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
vSupportWildcard: function (v) {
|
||||||
|
if (typeof v == "boolean") {
|
||||||
|
this.supportWildcard = v
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mode: function (mode) {
|
||||||
|
let that = this
|
||||||
|
setTimeout(function () {
|
||||||
|
if (mode == "single") {
|
||||||
|
if (that.$refs.addingDomain != null) {
|
||||||
|
that.$refs.addingDomain.focus()
|
||||||
|
}
|
||||||
|
} else if (mode == "batch") {
|
||||||
|
if (that.$refs.batchDomains != null) {
|
||||||
|
that.$refs.batchDomains.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -27,6 +63,11 @@ Vue.component("domains-box", {
|
|||||||
}, 100)
|
}, 100)
|
||||||
},
|
},
|
||||||
confirm: function () {
|
confirm: function () {
|
||||||
|
if (this.mode == "batch") {
|
||||||
|
this.confirmBatch()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let that = this
|
let that = this
|
||||||
|
|
||||||
// 删除其中的空格
|
// 删除其中的空格
|
||||||
@@ -39,8 +80,8 @@ Vue.component("domains-box", {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 基本校验
|
// 基本校验
|
||||||
|
if (this.supportWildcard) {
|
||||||
if (this.addingDomain[0] == "~") {
|
if (this.addingDomain[0] == "~") {
|
||||||
let expr = this.addingDomain.substring(1)
|
let expr = this.addingDomain.substring(1)
|
||||||
try {
|
try {
|
||||||
@@ -52,41 +93,142 @@ Vue.component("domains-box", {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (/[*~^]/.test(this.addingDomain)) {
|
||||||
|
teaweb.warn("当前只支持添加普通域名,域名中不能含有特殊符号", function () {
|
||||||
|
that.$refs.addingDomain.focus()
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isEditing && this.editingIndex >= 0) {
|
||||||
|
this.domains[this.editingIndex] = this.addingDomain
|
||||||
|
} else {
|
||||||
this.domains.push(this.addingDomain)
|
this.domains.push(this.addingDomain)
|
||||||
|
}
|
||||||
this.cancel()
|
this.cancel()
|
||||||
|
this.change()
|
||||||
|
},
|
||||||
|
confirmBatch: function () {
|
||||||
|
let domains = this.batchDomains.split("\n")
|
||||||
|
let realDomains = []
|
||||||
|
let that = this
|
||||||
|
let hasProblems = false
|
||||||
|
domains.forEach(function (domain) {
|
||||||
|
if (hasProblems) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (domain.length == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (that.supportWildcard) {
|
||||||
|
if (domain == "~") {
|
||||||
|
let expr = domain.substring(1)
|
||||||
|
try {
|
||||||
|
new RegExp(expr)
|
||||||
|
} catch (e) {
|
||||||
|
hasProblems = true
|
||||||
|
teaweb.warn("正则表达式错误:" + e.message, function () {
|
||||||
|
that.$refs.batchDomains.focus()
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (/[*~^]/.test(domain)) {
|
||||||
|
hasProblems = true
|
||||||
|
teaweb.warn("当前只支持添加普通域名,域名中不能含有特殊符号", function () {
|
||||||
|
that.$refs.batchDomains.focus()
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realDomains.push(domain)
|
||||||
|
})
|
||||||
|
if (hasProblems) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (realDomains.length == 0) {
|
||||||
|
teaweb.warn("请输入要添加的域名", function () {
|
||||||
|
that.$refs.batchDomains.focus()
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
realDomains.forEach(function (domain) {
|
||||||
|
that.domains.push(domain)
|
||||||
|
})
|
||||||
|
this.cancel()
|
||||||
|
this.change()
|
||||||
|
},
|
||||||
|
edit: function (index) {
|
||||||
|
this.addingDomain = this.domains[index]
|
||||||
|
this.isEditing = true
|
||||||
|
this.editingIndex = index
|
||||||
|
let that = this
|
||||||
|
setTimeout(function () {
|
||||||
|
that.$refs.addingDomain.focus()
|
||||||
|
}, 50)
|
||||||
},
|
},
|
||||||
remove: function (index) {
|
remove: function (index) {
|
||||||
this.domains.$remove(index)
|
this.domains.$remove(index)
|
||||||
|
this.change()
|
||||||
},
|
},
|
||||||
cancel: function () {
|
cancel: function () {
|
||||||
this.isAdding = false
|
this.isAdding = false
|
||||||
|
this.mode = "single"
|
||||||
|
this.batchDomains = ""
|
||||||
|
this.isEditing = false
|
||||||
|
this.editingIndex = -1
|
||||||
this.addingDomain = ""
|
this.addingDomain = ""
|
||||||
|
},
|
||||||
|
change: function () {
|
||||||
|
this.$emit("change", this.domains)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: `<div>
|
template: `<div>
|
||||||
<input type="hidden" :name="realName" :value="JSON.stringify(domains)"/>
|
<input type="hidden" :name="realName" :value="JSON.stringify(domains)"/>
|
||||||
<div v-if="domains.length > 0">
|
<div v-if="domains.length > 0">
|
||||||
<span class="ui label small basic" v-for="(domain, index) in domains">
|
<span class="ui label small basic" v-for="(domain, index) in domains" :class="{blue: index == editingIndex}">
|
||||||
<span v-if="domain.length > 0 && domain[0] == '~'" class="grey" style="font-style: normal">[正则]</span>
|
<span v-if="domain.length > 0 && domain[0] == '~'" class="grey" style="font-style: normal">[正则]</span>
|
||||||
<span v-if="domain.length > 0 && domain[0] == '.'" class="grey" style="font-style: normal">[后缀]</span>
|
<span v-if="domain.length > 0 && domain[0] == '.'" class="grey" style="font-style: normal">[后缀]</span>
|
||||||
<span v-if="domain.length > 0 && domain[0] == '*'" class="grey" style="font-style: normal">[泛域名]</span>
|
<span v-if="domain.length > 0 && domain[0] == '*'" class="grey" style="font-style: normal">[泛域名]</span>
|
||||||
{{domain}}
|
{{domain}}
|
||||||
|
<span v-if="!isAdding && !isEditing">
|
||||||
|
<a href="" title="修改" @click.prevent="edit(index)"><i class="icon pencil small"></i></a>
|
||||||
<a href="" title="删除" @click.prevent="remove(index)"><i class="icon remove small"></i></a>
|
<a href="" title="删除" @click.prevent="remove(index)"><i class="icon remove small"></i></a>
|
||||||
</span>
|
</span>
|
||||||
|
<span v-if="isAdding || isEditing">
|
||||||
|
<a class="disabled"><i class="icon pencil small"></i></a>
|
||||||
|
<a class="disabled"><i class="icon remove small"></i></a>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isAdding">
|
<div v-if="isAdding || isEditing">
|
||||||
<div class="ui fields">
|
<div class="ui fields">
|
||||||
|
<div class="ui field" v-if="isAdding">
|
||||||
|
<select class="ui dropdown" v-model="mode">
|
||||||
|
<option value="single">单个</option>
|
||||||
|
<option value="batch">批量</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="ui field">
|
<div class="ui field">
|
||||||
<input type="text" v-model="addingDomain" @keyup.enter="confirm()" @keypress.enter.prevent="1" ref="addingDomain" placeholder="*.xxx.com" size="30"/>
|
<div v-show="mode == 'single'">
|
||||||
|
<input type="text" v-model="addingDomain" @keyup.enter="confirm()" @keypress.enter.prevent="1" @keydown.esc="cancel()" ref="addingDomain" :placeholder="supportWildcard ? 'example.com、*.example.com' : 'example.com、www.example.com'" size="30" maxlength="100"/>
|
||||||
|
</div>
|
||||||
|
<div v-show="mode == 'batch'">
|
||||||
|
<textarea cols="30" v-model="batchDomains" placeholder="example1.com\nexample2.com\n每行一个域名" ref="batchDomains"></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui field">
|
<div class="ui field">
|
||||||
<button class="ui button tiny" type="button" @click.prevent="confirm">确定</button>
|
<button class="ui button tiny" type="button" @click.prevent="confirm">确定</button>
|
||||||
<a href="" title="取消" @click.prevent="cancel"><i class="icon remove small"></i></a>
|
<a href="" title="取消" @click.prevent="cancel"><i class="icon remove small"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="comment">支持普通域名(<code-label>example.com</code-label>)、泛域名(<code-label>*.example.com</code-label>)、域名后缀(以点号开头,如<code-label>.example.com</code-label>)和正则表达式(以波浪号开头,如<code-label>~.*.example.com</code-label>)。</p>
|
<p class="comment" v-if="supportWildcard">支持普通域名(<code-label>example.com</code-label>)、泛域名(<code-label>*.example.com</code-label>)、域名后缀(以点号开头,如<code-label>.example.com</code-label>)和正则表达式(以波浪号开头,如<code-label>~.*.example.com</code-label>)。</p>
|
||||||
|
<p class="comment" v-if="!supportWildcard">只支持普通域名(<code-label>example.com</code-label>、<code-label>www.example.com</code-label>)。</p>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 0.5em" v-if="!isAdding">
|
<div style="margin-top: 0.5em" v-if="!isAdding">
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ Vue.component("origin-list-box", {
|
|||||||
methods: {
|
methods: {
|
||||||
createPrimaryOrigin: function () {
|
createPrimaryOrigin: function () {
|
||||||
teaweb.popup("/servers/server/settings/origins/addPopup?originType=primary&" + this.vParams, {
|
teaweb.popup("/servers/server/settings/origins/addPopup?originType=primary&" + this.vParams, {
|
||||||
|
width: "45em",
|
||||||
height: "27em",
|
height: "27em",
|
||||||
callback: function (resp) {
|
callback: function (resp) {
|
||||||
teaweb.success("保存成功", function () {
|
teaweb.success("保存成功", function () {
|
||||||
@@ -19,6 +20,7 @@ Vue.component("origin-list-box", {
|
|||||||
},
|
},
|
||||||
createBackupOrigin: function () {
|
createBackupOrigin: function () {
|
||||||
teaweb.popup("/servers/server/settings/origins/addPopup?originType=backup&" + this.vParams, {
|
teaweb.popup("/servers/server/settings/origins/addPopup?originType=backup&" + this.vParams, {
|
||||||
|
width: "45em",
|
||||||
height: "27em",
|
height: "27em",
|
||||||
callback: function (resp) {
|
callback: function (resp) {
|
||||||
teaweb.success("保存成功", function () {
|
teaweb.success("保存成功", function () {
|
||||||
@@ -29,6 +31,7 @@ Vue.component("origin-list-box", {
|
|||||||
},
|
},
|
||||||
updateOrigin: function (originId, originType) {
|
updateOrigin: function (originId, originType) {
|
||||||
teaweb.popup("/servers/server/settings/origins/updatePopup?originType=" + originType + "&" + this.vParams + "&originId=" + originId, {
|
teaweb.popup("/servers/server/settings/origins/updatePopup?originType=" + originType + "&" + this.vParams + "&originId=" + originId, {
|
||||||
|
width: "45em",
|
||||||
height: "27em",
|
height: "27em",
|
||||||
callback: function (resp) {
|
callback: function (resp) {
|
||||||
teaweb.success("保存成功", function () {
|
teaweb.success("保存成功", function () {
|
||||||
|
|||||||
@@ -126,7 +126,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="title">证书域名列表 *</td>
|
<td class="title">证书域名列表 *</td>
|
||||||
<td>
|
<td>
|
||||||
<values-box name="" placeholder="域名" size="30" @change="changeDomains"></values-box>
|
<domains-box :v-support-wildcard="authType == 'dns'" @change="changeDomains"></domains-box>
|
||||||
<p class="comment">需要申请的证书中包含的域名列表<span v-if="authType == 'dns'">,所有域名必须是同一个顶级域名</span><span v-if="authType == 'http'">使用HTTP认证方式时,域名中不能含有通配符</span>。</p>
|
<p class="comment">需要申请的证书中包含的域名列表<span v-if="authType == 'dns'">,所有域名必须是同一个顶级域名</span><span v-if="authType == 'http'">使用HTTP认证方式时,域名中不能含有通配符</span>。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
<td>自动续期</td>
|
<td>自动续期</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox v-model="autoRenew"></checkbox>
|
<checkbox v-model="autoRenew"></checkbox>
|
||||||
<p class="comment">在免费证书临近到期之前,是否尝试自动续期。</p>
|
<p class="comment">选中后,表示在免费证书临近到期之前尝试自动续期。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
<div class="ui message blue" v-if="isRunning">有任务在执行中,可能需要的时间较长,请耐心等待。</div>
|
<div class="ui message blue" v-if="isRunning">有任务在执行中,可能需要的时间较长,请耐心等待。</div>
|
||||||
|
|
||||||
<table class="ui table selectable" v-if="tasks.length > 0">
|
<table class="ui table selectable celled" v-if="tasks.length > 0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ACME用户</th>
|
<th>ACME用户</th>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Tea.context(function () {
|
|||||||
|
|
||||||
this.updateTask = function (taskId) {
|
this.updateTask = function (taskId) {
|
||||||
teaweb.popup("/servers/certs/acme/updateTaskPopup?taskId=" + taskId, {
|
teaweb.popup("/servers/certs/acme/updateTaskPopup?taskId=" + taskId, {
|
||||||
|
width: "45em",
|
||||||
height: "26em",
|
height: "26em",
|
||||||
callback: function () {
|
callback: function () {
|
||||||
teaweb.success("保存成功,如果证书域名发生了改变,请重新执行生成新证书", function () {
|
teaweb.success("保存成功,如果证书域名发生了改变,请重新执行生成新证书", function () {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="title">证书域名列表 *</td>
|
<td class="title">证书域名列表 *</td>
|
||||||
<td>
|
<td>
|
||||||
<values-box name="domains" :values="task.domains" placeholder="域名" size="30"></values-box>
|
<domains-box name="domainsJSON" :v-domains="task.domains" :v-support-wildcard="task.authType == 'dns'"></domains-box>
|
||||||
<p class="comment">需要申请的证书中包含的域名列表<span v-if="task.authType == 'dns'">,所有域名必须是同一个顶级域名</span><span v-if="task.authType == 'http'">使用HTTP认证方式时,域名中不能含有通配符</span>。</p>
|
<p class="comment">需要申请的证书中包含的域名列表<span v-if="task.authType == 'dns'">,所有域名必须是同一个顶级域名</span><span v-if="task.authType == 'http'">使用HTTP认证方式时,域名中不能含有通配符</span>。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<td>自动续期</td>
|
<td>自动续期</td>
|
||||||
<td>
|
<td>
|
||||||
<checkbox name="autoRenew" v-model="task.autoRenew"></checkbox>
|
<checkbox name="autoRenew" v-model="task.autoRenew"></checkbox>
|
||||||
<p class="comment">在免费证书临近到期之前,是否尝试自动续期。</p>
|
<p class="comment">选中后,表示在免费证书临近到期之前尝试自动续期。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user