Initial commit (code only without large binaries)
This commit is contained in:
56
EdgeUser/web/views/@default/servers/server/log/history.html
Normal file
56
EdgeUser/web/views/@default/servers/server/log/history.html
Normal file
@@ -0,0 +1,56 @@
|
||||
{$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}
|
||||
|
||||
{$template "/left_menu"}
|
||||
|
||||
<div class="right-box">
|
||||
{$ if eq .featureIsOn false }
|
||||
<server-feature-required></server-feature-required>
|
||||
{$ else }
|
||||
<first-menu>
|
||||
<menu-item :href="path + '?serverId=' + serverId + '&day=' + day" :active="hasError == 0">所有日志</menu-item>
|
||||
<menu-item :href="path + '?serverId=' + serverId + '&day=' + day + '&hasError=1'" :active="hasError > 0">错误日志</menu-item>
|
||||
<div class="item right">
|
||||
<form method="get" class="ui form small" :action="path" autocomplete="off">
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<div class="ui fields inline">
|
||||
<div class="ui field">
|
||||
<input type="text" name="day" maxlength="10" placeholder="选择日期" style="width:7.8em" id="day-input" v-model="day"/>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<button class="ui button small" type="submit">查找</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</first-menu>
|
||||
<form method="get" class="ui form small" :action="path" autocomplete="off">
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<http-access-log-search-box :v-ip="ip" :v-domain="domain" :v-keyword="keyword" :v-cluster-id="clusterId" :v-node-id="nodeId"></http-access-log-search-box>
|
||||
</form>
|
||||
<p class="comment" v-if="accessLogs.length == 0">暂时还没有访问日志。</p>
|
||||
|
||||
<table class="ui table selectable" v-if="accessLogs.length > 0">
|
||||
<!-- 这里之所以需要添加 :key,是因为要不然不会刷新显示 -->
|
||||
<tr v-for="accessLog in accessLogs" :key="accessLog.requestId">
|
||||
<td><http-access-log-box :v-access-log="accessLog"></http-access-log-box></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div v-if="accessLogs.length > 0">
|
||||
<a :href="path + '?serverId=' + serverId + '&requestId=' + lastRequestId + '&day=' + day + '&hasError=' + hasError+'&ip='+ip+'&domain='+domain+'&keyword='+keyword+'&clusterId='+clusterId+'&nodeId='+nodeId" v-if="hasPrev">上一页</a>
|
||||
<span v-else class="disabled">上一页</span>
|
||||
<span class="disabled"> | </span>
|
||||
<a :href="path + '?serverId=' + serverId + '&requestId=' + nextRequestId + '&day=' + day + '&hasError=' + hasError+'&ip='+ip+'&domain='+domain+'&keyword='+keyword+'&clusterId='+clusterId+'&nodeId='+nodeId" v-if="hasMore">下一页</a>
|
||||
<span v-else class="disabled">下一页</span>
|
||||
</div>
|
||||
{$end}
|
||||
</div>
|
||||
21
EdgeUser/web/views/@default/servers/server/log/history.js
Normal file
21
EdgeUser/web/views/@default/servers/server/log/history.js
Normal file
@@ -0,0 +1,21 @@
|
||||
Tea.context(function () {
|
||||
this.$delay(function () {
|
||||
let that = this
|
||||
if (this.featureIsOn) {
|
||||
teaweb.datepicker("day-input", function (day) {
|
||||
that.day = day
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let that = this
|
||||
if (this.featureIsOn) {
|
||||
this.accessLogs.forEach(function (accessLog) {
|
||||
if (typeof (that.regions[accessLog.remoteAddr]) == "string") {
|
||||
accessLog.region = that.regions[accessLog.remoteAddr]
|
||||
} else {
|
||||
accessLog.region = ""
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
20
EdgeUser/web/views/@default/servers/server/log/index.html
Normal file
20
EdgeUser/web/views/@default/servers/server/log/index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
{$layout}
|
||||
|
||||
{$template "/left_menu"}
|
||||
<div class="right-box">
|
||||
{$ if eq .featureIsOn false }
|
||||
<server-feature-required></server-feature-required>
|
||||
{$ else }
|
||||
<form method="get" class="ui form small" :action="path" autocomplete="off">
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<http-access-log-search-box :v-ip="ip" :v-domain="domain" :v-keyword="keyword" :v-cluster-id="clusterId" :v-node-id="nodeId"></http-access-log-search-box>
|
||||
</form>
|
||||
<p class="comment" v-if="isLoaded && accessLogs.length == 0">今天暂时还没有访问日志。</p>
|
||||
<table class="ui table selectable" v-if="accessLogs.length > 0">
|
||||
<!-- 这里之所以需要添加 :key,是因为要不然不会刷新显示 -->
|
||||
<tr v-for="accessLog in accessLogs" :key="accessLog.requestId">
|
||||
<td><http-access-log-box :v-access-log="accessLog"></http-access-log-box></td>
|
||||
</tr>
|
||||
</table>
|
||||
{$end}
|
||||
</div>
|
||||
61
EdgeUser/web/views/@default/servers/server/log/index.js
Normal file
61
EdgeUser/web/views/@default/servers/server/log/index.js
Normal file
@@ -0,0 +1,61 @@
|
||||
Tea.context(function () {
|
||||
this.$delay(function () {
|
||||
this.load()
|
||||
})
|
||||
|
||||
this.hasMore = false
|
||||
this.accessLogs = []
|
||||
this.isLoaded = false
|
||||
|
||||
this.load = function () {
|
||||
// 如果有弹窗时,暂时不更新
|
||||
if (teaweb.hasPopup()) {
|
||||
this.$delay(function () {
|
||||
this.load()
|
||||
}, 5000)
|
||||
return
|
||||
}
|
||||
|
||||
this.$post("$")
|
||||
.params({
|
||||
serverId: this.serverId,
|
||||
requestId: this.requestId,
|
||||
keyword: this.keyword,
|
||||
ip: this.ip,
|
||||
domain: this.domain,
|
||||
clusterId: this.clusterId,
|
||||
nodeId: this.nodeId
|
||||
})
|
||||
.success(function (resp) {
|
||||
this.accessLogs = resp.data.accessLogs.concat(this.accessLogs)
|
||||
|
||||
// 添加区域信息
|
||||
this.accessLogs.forEach(function (accessLog) {
|
||||
if (typeof (resp.data.regions[accessLog.remoteAddr]) == "string") {
|
||||
accessLog.region = resp.data.regions[accessLog.remoteAddr]
|
||||
} else {
|
||||
accessLog.region = ""
|
||||
}
|
||||
})
|
||||
|
||||
let max = 100
|
||||
if (this.accessLogs.length > max) {
|
||||
this.accessLogs = this.accessLogs.slice(0, max)
|
||||
}
|
||||
this.hasMore = resp.data.hasMore
|
||||
this.requestId = resp.data.requestId
|
||||
})
|
||||
.done(function () {
|
||||
if (!this.isLoaded) {
|
||||
this.$delay(function () {
|
||||
this.isLoaded = true
|
||||
})
|
||||
}
|
||||
|
||||
// 自动刷新
|
||||
this.$delay(function () {
|
||||
this.load()
|
||||
}, 5000)
|
||||
})
|
||||
}
|
||||
})
|
||||
33
EdgeUser/web/views/@default/servers/server/log/today.html
Normal file
33
EdgeUser/web/views/@default/servers/server/log/today.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{$layout}
|
||||
|
||||
{$template "/left_menu"}
|
||||
<div class="right-box">
|
||||
{$ if eq .featureIsOn false }
|
||||
<server-feature-required></server-feature-required>
|
||||
{$ else }
|
||||
<first-menu>
|
||||
<menu-item :href="path + '?serverId=' + serverId" :active="hasError == 0">所有日志</menu-item>
|
||||
<menu-item :href="path + '?serverId=' + serverId + '&hasError=1'" :active="hasError > 0">错误日志</menu-item>
|
||||
</first-menu>
|
||||
|
||||
<form method="get" class="ui form small" :action="path" autocomplete="off">
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<http-access-log-search-box :v-ip="ip" :v-domain="domain" :v-keyword="keyword" :v-cluster-id="clusterId" :v-node-id="nodeId"></http-access-log-search-box>
|
||||
</form>
|
||||
<p class="comment" v-if="accessLogs.length == 0">今天暂时还没有访问日志。</p>
|
||||
<table class="ui table selectable" v-if="accessLogs.length > 0">
|
||||
<!-- 这里之所以需要添加 :key,是因为要不然不会刷新显示 -->
|
||||
<tr v-for="accessLog in accessLogs" :key="accessLog.requestId">
|
||||
<td><http-access-log-box :v-access-log="accessLog"></http-access-log-box></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div v-if="accessLogs.length > 0">
|
||||
<a :href="path + '?serverId=' + serverId + '&requestId=' + lastRequestId + '&hasError=' + hasError+'&ip='+ip+'&domain='+domain+'&keyword='+keyword+'&clusterId='+clusterId+'&nodeId='+nodeId" v-if="hasPrev">上一页</a>
|
||||
<span v-else class="disabled">上一页</span>
|
||||
<span class="disabled"> | </span>
|
||||
<a :href="path + '?serverId=' + serverId + '&requestId=' + nextRequestId + '&hasError=' + hasError+'&ip='+ip+'&domain='+domain+'&keyword='+keyword+'&clusterId='+clusterId+'&nodeId='+nodeId" v-if="hasMore">下一页</a>
|
||||
<span v-else class="disabled">下一页</span>
|
||||
</div>
|
||||
{$end}
|
||||
</div>
|
||||
12
EdgeUser/web/views/@default/servers/server/log/today.js
Normal file
12
EdgeUser/web/views/@default/servers/server/log/today.js
Normal file
@@ -0,0 +1,12 @@
|
||||
Tea.context(function () {
|
||||
let that = this
|
||||
if (this.featureIsOn) {
|
||||
this.accessLogs.forEach(function (accessLog) {
|
||||
if (typeof (that.regions[accessLog.remoteAddr]) == "string") {
|
||||
accessLog.region = that.regions[accessLog.remoteAddr]
|
||||
} else {
|
||||
accessLog.region = ""
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
table td {
|
||||
word-break: break-all;
|
||||
}
|
||||
table td.title {
|
||||
width: 12em !important;
|
||||
}
|
||||
/*# sourceMappingURL=viewPopup.css.map */
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["viewPopup.less"],"names":[],"mappings":"AAAA,KAAM;EACL,qBAAA;;AAGD,KAAM,GAAE;EACP,sBAAA","file":"viewPopup.css"}
|
||||
150
EdgeUser/web/views/@default/servers/server/log/viewPopup.html
Normal file
150
EdgeUser/web/views/@default/servers/server/log/viewPopup.html
Normal file
@@ -0,0 +1,150 @@
|
||||
{$layout "layout_popup"}
|
||||
{$template "/code_editor"}
|
||||
|
||||
<div class="ui menu tabular tiny">
|
||||
<a class="item" :class="{active: tab == 'summary'}" @click.prevent="switchTab('summary')">综合信息</a>
|
||||
<a class="item" :class="{active: tab == 'response'}" @click.prevent="switchTab('response')">响应数据(Response)</a>
|
||||
<a class="item" :class="{active: tab == 'request'}" @click.prevent="switchTab('request')">请求数据(Request)</a>
|
||||
<a class="item" :class="{active: tab == 'cookie'}" @click.prevent="switchTab('cookie')">Cookie</a>
|
||||
<a class="item" :class="{active: tab == 'client'}" @click.prevent="switchTab('client')">终端信息</a>
|
||||
</div>
|
||||
|
||||
<div v-if="tab == 'summary'">
|
||||
<table class="ui table selectable small">
|
||||
<tr>
|
||||
<td style="width: 50%">请求概要<em>(Request)</em>:{{accessLog.request}}</td>
|
||||
<td>请求URI<em>(RequestURI)</em>:{{accessLog.requestURI}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>请求方法<em>(RequestMethod)</em>:{{accessLog.requestMethod}}</td>
|
||||
<td>主机地址<em>(Host)</em>:{{accessLog.host}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>请求来源<em>(Referer)</em>:
|
||||
<span v-if="accessLog.referer != null && accessLog.referer.length > 0">{{accessLog.referer}}</span>
|
||||
<span v-else>-</span>
|
||||
</td>
|
||||
<td>终端地址<em>(RemoteAddr:RemotePort)</em>:{{accessLog.remoteAddr}}:{{accessLog.remotePort}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>终端信息<em>(UserAgent)</em>:
|
||||
<span v-if="accessLog.userAgent != null && accessLog.userAgent.length > 0">{{accessLog.userAgent}}</span>
|
||||
<span v-else>-</span>
|
||||
</td>
|
||||
<td>协议<em>(Proto)</em>:{{accessLog.proto}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>状态<em>(StatusMessage)</em>:<span :class="{red:accessLog.status>=400, green:accessLog.status<400}">{{accessLog.status}} {{accessLog.statusMessage}} <span v-if="accessLog.originStatus >= 400 || (accessLog.originStatus > 0 && accessLog.originStatus != accessLog.status)" class="grey small">(源站{{accessLog.originStatus}})</span></span></span></td>
|
||||
<td>文件类型<em>(ContentType)</em>:
|
||||
<span v-if="accessLog.contentType != null && accessLog.contentType.length > 0">{{accessLog.contentType}}</span>
|
||||
<span v-else>-</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>下行流量<em>(BytesSent)</em>:{{accessLog.bytesSent}}</td>
|
||||
<td>源站地址:
|
||||
<span v-if="accessLog.originAddress != null && accessLog.originAddress">{{accessLog.originAddress}}</span>
|
||||
<span v-else class="disabled">未访问源站</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ISO8601时间:{{accessLog.timeISO8601}}</td>
|
||||
<td>本地时间<em>(TimeLocal)</em>:{{accessLog.timeLocal}}</td>
|
||||
</tr>
|
||||
<tr v-if="wafInfo != null">
|
||||
<td class="color-border">WAF策略:{{wafInfo.policy.name}}</td>
|
||||
<td>WAF规则分组:
|
||||
<span v-if="wafInfo.group != null">{{wafInfo.group.name}}</span>
|
||||
<span v-else>-</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="wafInfo != null && wafInfo.set != null">
|
||||
<td class="color-border">WAF规则集:{{wafInfo.set.name}}</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr v-if="accessLog.errors != null && accessLog.errors.length > 0">
|
||||
<td colspan="2">
|
||||
<div v-for="error in accessLog.errors">
|
||||
<span class="red">{{error}}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div v-if="tab == 'response'">
|
||||
<table class="ui table definition selectable small">
|
||||
<tr>
|
||||
<td class="title">Status</td>
|
||||
<td>{{accessLog.status}} {{accessLog.statusMessage}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="ui table definition selectable small" v-if="responseHeaders.length > 0">
|
||||
<tbody v-for="header in responseHeaders">
|
||||
<tr v-for="value in header.values">
|
||||
<td class="title">
|
||||
<span v-if="header.isGeneral">{{header.name}}</span>
|
||||
<span style="font-style: italic" v-else>{{header.name}}</span>
|
||||
</td>
|
||||
<td>{{value}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div v-if="tab == 'request'">
|
||||
<table class="ui table definition selectable small">
|
||||
<tbody v-for="header in requestHeaders">
|
||||
<tr v-for="value in header.values">
|
||||
<td class="title">
|
||||
<span v-if="header.isGeneral">{{header.name}}</span>
|
||||
<span style="font-style: italic" v-else>{{header.name}}</span>
|
||||
</td>
|
||||
<td>{{value}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody v-if="requestBody.length > 0">
|
||||
<tr>
|
||||
<td colspan="2">请求内容:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<source-code-box :type="requestContentType" width="0" height="200">{{requestBody}}</source-code-box>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div v-if="tab == 'cookie'">
|
||||
<p class="comment" v-if="cookies.length == 0">暂时没有Cookie数据。</p>
|
||||
<div v-else>
|
||||
<table class="ui table definition selectable small">
|
||||
<tr v-for="cookie in cookies">
|
||||
<td class="title">{{cookie.name}}</td>
|
||||
<td>{{cookie.value}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="tab == 'client'">
|
||||
<table class="ui table definition selectable small">
|
||||
<tr>
|
||||
<td class="title">综合信息<em>(UserAgent)</em></td>
|
||||
<td>{{accessLog.userAgent}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IP</td>
|
||||
<td>{{accessLog.remoteAddr}}</td>
|
||||
</tr>
|
||||
<tr v-if="region != null">
|
||||
<td>区域</td>
|
||||
<td>{{region.full}}</td>
|
||||
</tr>
|
||||
<tr v-if="region != null && region.isp != null && region.isp.length > 0">
|
||||
<td>ISP</td>
|
||||
<td>{{region.isp}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
73
EdgeUser/web/views/@default/servers/server/log/viewPopup.js
Normal file
73
EdgeUser/web/views/@default/servers/server/log/viewPopup.js
Normal file
@@ -0,0 +1,73 @@
|
||||
Tea.context(function () {
|
||||
this.tab = "summary"
|
||||
|
||||
this.switchTab = function (tab) {
|
||||
this.tab = tab
|
||||
}
|
||||
|
||||
// 请求Header
|
||||
this.requestHeaders = []
|
||||
if (this.accessLog.header != null) {
|
||||
for (let k in this.accessLog.header) {
|
||||
let v = this.accessLog.header[k]
|
||||
if (typeof (v) != "object") {
|
||||
continue
|
||||
}
|
||||
this.requestHeaders.push({
|
||||
name: k,
|
||||
values: v.values,
|
||||
isGeneral: !k.startsWith("X-")
|
||||
})
|
||||
}
|
||||
}
|
||||
this.requestHeaders.sort(function (v1, v2) {
|
||||
return (v1.name < v2.name) ? -1 : 1
|
||||
})
|
||||
|
||||
// 响应Header
|
||||
this.responseHeaders = []
|
||||
|
||||
if (this.accessLog.sentHeader != null) {
|
||||
for (let k in this.accessLog.sentHeader) {
|
||||
let v = this.accessLog.sentHeader[k]
|
||||
if (typeof (v) != "object") {
|
||||
continue
|
||||
}
|
||||
this.responseHeaders.push({
|
||||
name: k,
|
||||
values: v.values,
|
||||
isGeneral: !k.startsWith("X-")
|
||||
})
|
||||
}
|
||||
}
|
||||
this.responseHeaders.sort(function (v1, v2) {
|
||||
return (v1.name < v2.name) ? -1 : 1
|
||||
})
|
||||
|
||||
// Cookie
|
||||
this.cookies = []
|
||||
if (this.accessLog.cookie != null) {
|
||||
for (let k in this.accessLog.cookie) {
|
||||
let v = this.accessLog.cookie[k]
|
||||
if (typeof (v) != "string") {
|
||||
continue
|
||||
}
|
||||
this.cookies.push({
|
||||
name: k,
|
||||
value: v
|
||||
})
|
||||
}
|
||||
}
|
||||
this.cookies.sort(function (v1, v2) {
|
||||
if (v1.name.startsWith("_")) {
|
||||
if (v2.name.startsWith("_")) {
|
||||
return (v1.name < v2.name) ? -1 : 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
if (v2.name.startsWith("_")) {
|
||||
return 1
|
||||
}
|
||||
return (v1.name.toUpperCase() < v2.name.toUpperCase()) ? -1 : 1
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
table td {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
table td.title {
|
||||
width: 12em !important;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<first-menu>
|
||||
<menu-item href="/servers">网站列表</menu-item>
|
||||
<span class="item disabled">|</span>
|
||||
<menu-item :href="'/servers/server/settings/dns?serverId=' + server.id">"{{server.name}}"设置</menu-item>
|
||||
<span class="disabled item">»</span>
|
||||
<a class="item active" v-if="leftMenuActiveItem != null" :href="leftMenuActiveItem.url">"{{leftMenuActiveItem.name}}"设置</a>
|
||||
<span class="disabled item" v-if="leftMenuActiveItem != null && leftMenuActiveItem.configCode != null && leftMenuActiveItem.configCode.length > 0">|</span>
|
||||
<server-config-copy-link :v-server-id="server.id" :v-config-code="leftMenuActiveItem.configCode" v-if="leftMenuActiveItem != null && leftMenuActiveItem.configCode != null && leftMenuActiveItem.configCode.length > 0"></server-config-copy-link>
|
||||
</first-menu>
|
||||
@@ -0,0 +1,203 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>创建鉴权方式</h3>
|
||||
<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>
|
||||
<input type="text" name="name" maxlength="50" ref="focus"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>鉴权类型 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="type" v-model="type" @change="changeType">
|
||||
<option value="">[鉴权类型]</option>
|
||||
<option v-for="authType in authTypes" :value="authType.code">{{authType.name}}</option>
|
||||
</select>
|
||||
<p class="comment" v-html="authDescription"></p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- TypeA -->
|
||||
<tbody v-show="type == 'typeA'">
|
||||
<tr>
|
||||
<td>鉴权密钥 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="40" name="typeASecret" v-model="typeASecret" autocomplete="off"/>
|
||||
<p class="comment">只能包含字母、数字,长度不超过40。<a href="" @click.prevent="generateTypeASecret()">[随机生成]</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>签名参数 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="30" name="typeASignParamName" value="sign" v-model="typeASignParamName" @input="changeTypeASignParamName"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>有效时间</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" maxlength="8" name="typeALife" value="30" style="width: 7em"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">链接有效时间。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- TypeB -->
|
||||
<tbody v-show="type == 'typeB'">
|
||||
<tr>
|
||||
<td>鉴权密钥 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="40" name="typeBSecret" v-model="typeBSecret" autocomplete="off"/>
|
||||
<p class="comment">只能包含字母、数字,长度不超过40。<a href="" @click.prevent="generateTypeBSecret()">[随机生成]</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>有效时间</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" maxlength="8" name="typeBLife" value="30" style="width: 7em"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">链接有效时间。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- TypeC -->
|
||||
<tbody v-show="type == 'typeC'">
|
||||
<tr>
|
||||
<td>鉴权密钥 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="40" name="typeCSecret" v-model="typeCSecret" autocomplete="off"/>
|
||||
<p class="comment">只能包含字母、数字,长度不超过40。<a href="" @click.prevent="generateTypeCSecret()">[随机生成]</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>有效时间</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" maxlength="8" name="typeCLife" value="30" style="width: 7em"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">链接有效时间。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- TypeD -->
|
||||
<tbody v-show="type == 'typeD'">
|
||||
<tr>
|
||||
<td>鉴权密钥 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="40" name="typeDSecret" v-model="typeDSecret" autocomplete="off"/>
|
||||
<p class="comment">只能包含字母、数字,长度不超过40。<a href="" @click.prevent="generateTypeDSecret()">[随机生成]</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>签名参数 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="30" name="typeDSignParamName" value="sign" v-model="typeDSignParamName" @input="changeTypeDSignParamName"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>时间戳参数 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="30" name="typeDTimestampParamName" value="t" v-model="typeDTimestampParamName" @input="changeTypeDTimestampParamName"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>有效时间</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" maxlength="8" name="typeDLife" value="30" style="width: 7em"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">链接有效时间。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- BasicAuth -->
|
||||
<tbody v-show="type == 'basicAuth'">
|
||||
<tr>
|
||||
<td>用户 *</td>
|
||||
<td>
|
||||
<http-auth-basic-auth-user-box></http-auth-basic-auth-user-box>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<a href="" @click.prevent="showMoreBasicAuthOptions()">更多基本认证选项<i class="ui icon angle" :class="{up: moreBasicAuthOptionsVisible, down: !moreBasicAuthOptionsVisible}"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="moreBasicAuthOptionsVisible">
|
||||
<td>认证领域名<em>(Realm)</em></td>
|
||||
<td>
|
||||
<input type="text" name="basicAuthRealm" value="" maxlength="100"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="moreBasicAuthOptionsVisible">
|
||||
<td>字符集</td>
|
||||
<td>
|
||||
<input type="text" name="basicAuthCharset" style="width: 6em" maxlength="50"/>
|
||||
<p class="comment">类似于<code-label>UTF-8</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- SubRequest -->
|
||||
<tbody v-show="type == 'subRequest'">
|
||||
<tr>
|
||||
<td>子请求URL *</td>
|
||||
<td>
|
||||
<input type="text" name="subRequestURL" maxlength="1024"/>
|
||||
<p class="comment">可以是一个完整的URL,也可以是一个路径。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>请求方法</td>
|
||||
<td>
|
||||
<radio name="subRequestFollowRequest" :v-value="1" v-model="subRequestFollowRequest">同当前请求一致</radio>
|
||||
<radio name="subRequestFollowRequest" :v-value="0" v-model="subRequestFollowRequest">自定义</radio>
|
||||
<div style="margin-top: 0.8em" v-show="subRequestFollowRequest == 0">
|
||||
<div class="ui divider"></div>
|
||||
<select class="ui dropdown auto-width" name="subRequestMethod">
|
||||
<option value="POST">POST</option>
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="HEAD">HEAD</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>限定文件扩展名</td>
|
||||
<td>
|
||||
<values-box name="exts"></values-box>
|
||||
<p class="comment">如果不为空,则表示只有这些扩展名的文件才需要鉴权;扩展名需要包含点符号(.),比如<code-label>.png</code-label></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>限定域名</td>
|
||||
<td>
|
||||
<domains-box></domains-box>
|
||||
<p class="comment">如果不为空,则表示只有这些域名的文件才需要鉴权。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,100 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyPopup
|
||||
|
||||
this.type = ""
|
||||
this.authDescription = ""
|
||||
this.rawDescription = ""
|
||||
|
||||
this.changeType = function () {
|
||||
let that = this
|
||||
let authType = this.authTypes.$find(function (k, v) {
|
||||
return v.code == that.type
|
||||
})
|
||||
if (authType != null) {
|
||||
this.authDescription = authType.description
|
||||
this.rawDescription = authType.description
|
||||
} else {
|
||||
this.authDescription = ""
|
||||
this.rawDescription = ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TypeA
|
||||
*/
|
||||
this.typeASecret = ""
|
||||
this.typeASignParamName = "sign"
|
||||
|
||||
this.generateTypeASecret = function () {
|
||||
this.$post(".random")
|
||||
.success(function (resp) {
|
||||
this.typeASecret = resp.data.random
|
||||
})
|
||||
}
|
||||
|
||||
this.changeTypeASignParamName = function () {
|
||||
this.authDescription = this.rawDescription.replace("sign=", this.typeASignParamName + "=")
|
||||
}
|
||||
|
||||
/**
|
||||
* TypeB
|
||||
*/
|
||||
this.typeBSecret = ""
|
||||
|
||||
this.generateTypeBSecret = function () {
|
||||
this.$post(".random")
|
||||
.success(function (resp) {
|
||||
this.typeBSecret = resp.data.random
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* TypeC
|
||||
*/
|
||||
this.typeCSecret = ""
|
||||
|
||||
this.generateTypeCSecret = function () {
|
||||
this.$post(".random")
|
||||
.success(function (resp) {
|
||||
this.typeCSecret = resp.data.random
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* TypeD
|
||||
*/
|
||||
this.typeDSecret = ""
|
||||
this.typeDSignParamName = "sign"
|
||||
this.typeDTimestampParamName = "t"
|
||||
|
||||
this.generateTypeDSecret = function () {
|
||||
this.$post(".random")
|
||||
.success(function (resp) {
|
||||
this.typeDSecret = resp.data.random
|
||||
})
|
||||
}
|
||||
|
||||
this.changeTypeDSignParamName = function () {
|
||||
this.authDescription = this.rawDescription.replace("sign=", this.typeDSignParamName + "=")
|
||||
this.authDescription = this.authDescription.replace("t=", this.typeDTimestampParamName + "=")
|
||||
}
|
||||
|
||||
this.changeTypeDTimestampParamName = function () {
|
||||
this.authDescription = this.rawDescription.replace("sign=", this.typeDSignParamName + "=")
|
||||
this.authDescription = this.authDescription.replace("t=", this.typeDTimestampParamName + "=")
|
||||
}
|
||||
|
||||
/**
|
||||
* 基本认证
|
||||
*/
|
||||
this.moreBasicAuthOptionsVisible = false
|
||||
|
||||
this.showMoreBasicAuthOptions = function () {
|
||||
this.moreBasicAuthOptionsVisible = !this.moreBasicAuthOptionsVisible
|
||||
}
|
||||
|
||||
/**
|
||||
* 子请求
|
||||
*/
|
||||
this.subRequestFollowRequest = 1
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success" ref="authForm">
|
||||
<input type="hidden" name="webId" :value="webId">
|
||||
<http-auth-config-box :v-auth-config="authConfig" @change="changeMethods"></http-auth-config-box>
|
||||
<submit-btn @ref=""></submit-btn>
|
||||
</form>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,10 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
|
||||
this.changeMethods = function (config) {
|
||||
Tea.action("$")
|
||||
.form(this.$refs.authForm)
|
||||
.post()
|
||||
teaweb.successRefresh("保存成功")
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,206 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>修改鉴权方式</h3>
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="policyId" :value="policy.id"/>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">名称 *</td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="50" ref="focus" v-model="policy.name"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>鉴权类型 *</td>
|
||||
<td>
|
||||
{{policy.typeName}}
|
||||
<p class="comment" v-html="authDescription"></p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- TypeA -->
|
||||
<tbody v-show="type == 'typeA'">
|
||||
<tr>
|
||||
<td>鉴权密钥 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="40" name="typeASecret" v-model="typeASecret" autocomplete="off"/>
|
||||
<p class="comment">只能包含字母、数字,长度不超过40。<a href="" @click.prevent="generateTypeASecret()">[随机生成]</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>签名参数 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="30" name="typeASignParamName" value="sign" v-model="typeASignParamName" @input="changeTypeASignParamName"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>有效时间</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" maxlength="8" name="typeALife" value="30" style="width: 7em" v-model="policy.params.life"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">链接有效时间。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- TypeB -->
|
||||
<tbody v-show="type == 'typeB'">
|
||||
<tr>
|
||||
<td>鉴权密钥 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="40" name="typeBSecret" v-model="typeBSecret" autocomplete="off"/>
|
||||
<p class="comment">只能包含字母、数字,长度不超过40。<a href="" @click.prevent="generateTypeBSecret()">[随机生成]</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>有效时间</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" maxlength="8" name="typeBLife" value="30" style="width: 7em" v-model="policy.params.life"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">链接有效时间。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- TypeC -->
|
||||
<tbody v-show="type == 'typeC'">
|
||||
<tr>
|
||||
<td>鉴权密钥 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="40" name="typeCSecret" v-model="typeCSecret" autocomplete="off"/>
|
||||
<p class="comment">只能包含字母、数字,长度不超过40。<a href="" @click.prevent="generateTypeCSecret()">[随机生成]</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>有效时间</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" maxlength="8" name="typeCLife" value="30" style="width: 7em" v-model="policy.params.life"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">链接有效时间。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- TypeD -->
|
||||
<tbody v-show="type == 'typeD'">
|
||||
<tr>
|
||||
<td>鉴权密钥 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="40" name="typeDSecret" v-model="typeDSecret" autocomplete="off"/>
|
||||
<p class="comment">只能包含字母、数字,长度不超过40。<a href="" @click.prevent="generateTypeDSecret()">[随机生成]</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>签名参数 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="30" name="typeDSignParamName" value="sign" v-model="typeDSignParamName" @input="changeTypeDSignParamName"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>时间戳参数 *</td>
|
||||
<td>
|
||||
<input type="text" maxlength="30" name="typeDTimestampParamName" value="t" v-model="typeDTimestampParamName" @input="changeTypeDTimestampParamName"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>有效时间</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" maxlength="8" name="typeDLife" value="30" style="width: 7em" v-model="policy.params.life"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">链接有效时间。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- BasicAuth -->
|
||||
<tbody v-show="type == 'basicAuth'">
|
||||
<tr>
|
||||
<td>用户 *</td>
|
||||
<td>
|
||||
<http-auth-basic-auth-user-box :v-users="policy.params.users"></http-auth-basic-auth-user-box>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<a href="" @click.prevent="showMoreBasicAuthOptions()">更多基本认证选项<i class="ui icon angle" :class="{up: moreBasicAuthOptionsVisible, down: !moreBasicAuthOptionsVisible}"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="moreBasicAuthOptionsVisible">
|
||||
<td>认证领域名<em>(Realm)</em></td>
|
||||
<td>
|
||||
<input type="text" name="basicAuthRealm" value="" maxlength="100" v-model="policy.params.realm"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="moreBasicAuthOptionsVisible">
|
||||
<td>字符集</td>
|
||||
<td>
|
||||
<input type="text" name="basicAuthCharset" style="width: 6em" v-model="policy.params.charset" maxlength="50"/>
|
||||
<p class="comment">类似于<code-label>utf-8</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- SubRequest -->
|
||||
<tbody v-show="type == 'subRequest'">
|
||||
<tr>
|
||||
<td>子请求URL *</td>
|
||||
<td>
|
||||
<input type="text" name="subRequestURL" maxlength="1024" v-model="policy.params.url"/>
|
||||
<p class="comment">可以是一个完整的URL,也可以是一个路径。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>请求方法</td>
|
||||
<td>
|
||||
<radio name="subRequestFollowRequest" :v-value="1" v-model="subRequestFollowRequest">同当前请求一致</radio>
|
||||
<radio name="subRequestFollowRequest" :v-value="0" v-model="subRequestFollowRequest">自定义</radio>
|
||||
<div style="margin-top: 0.8em" v-show="subRequestFollowRequest == 0">
|
||||
<div class="ui divider"></div>
|
||||
<select class="ui dropdown auto-width" name="subRequestMethod" v-model="policy.params.method">
|
||||
<option value="">[请选择]</option>
|
||||
<option value="POST">POST</option>
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="HEAD">HEAD</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>限定文件扩展名</td>
|
||||
<td>
|
||||
<values-box name="exts" :v-values="policy.params.exts"></values-box>
|
||||
<p class="comment">如果不为空,则表示只有这些扩展名的文件才需要鉴权;扩展名需要包含点符号(.),比如<code-label>.png</code-label></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>限定域名</td>
|
||||
<td>
|
||||
<domains-box :v-domains="policy.params.domains"></domains-box>
|
||||
<p class="comment">如果不为空,则表示只有这些域名的文件才需要鉴权。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>启用当前鉴权</td>
|
||||
<td><checkbox name="isOn" value="1" v-model="policy.isOn"></checkbox></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,131 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyPopup
|
||||
|
||||
this.type = this.policy.type
|
||||
this.authDescription = ""
|
||||
this.rawDescription = ""
|
||||
|
||||
this.$delay(function () {
|
||||
this.changeType()
|
||||
})
|
||||
|
||||
this.changeType = function () {
|
||||
let that = this
|
||||
let authType = this.authTypes.$find(function (k, v) {
|
||||
return v.code == that.type
|
||||
})
|
||||
if (authType != null) {
|
||||
this.policy.typeName = authType.name
|
||||
this.authDescription = authType.description
|
||||
this.rawDescription = authType.description
|
||||
} else {
|
||||
this.authDescription = ""
|
||||
this.rawDescription = ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TypeA
|
||||
*/
|
||||
this.typeASecret = ""
|
||||
this.typeASignParamName = "sign"
|
||||
|
||||
if (this.policy.type == "typeA") {
|
||||
this.typeASecret = this.policy.params.secret
|
||||
this.typeASignParamName = this.policy.params.signParamName
|
||||
this.$delay(function () {
|
||||
this.changeTypeASignParamName()
|
||||
})
|
||||
}
|
||||
|
||||
this.generateTypeASecret = function () {
|
||||
this.$post(".random")
|
||||
.success(function (resp) {
|
||||
this.typeASecret = resp.data.random
|
||||
})
|
||||
}
|
||||
|
||||
this.changeTypeASignParamName = function () {
|
||||
this.authDescription = this.rawDescription.replace("sign=", this.typeASignParamName + "=")
|
||||
}
|
||||
|
||||
/**
|
||||
* TypeB
|
||||
*/
|
||||
this.typeBSecret = ""
|
||||
|
||||
if (this.policy.type == "typeB") {
|
||||
this.typeBSecret = this.policy.params.secret
|
||||
}
|
||||
|
||||
this.generateTypeBSecret = function () {
|
||||
this.$post(".random")
|
||||
.success(function (resp) {
|
||||
this.typeBSecret = resp.data.random
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* TypeC
|
||||
*/
|
||||
this.typeCSecret = ""
|
||||
|
||||
if (this.policy.type == "typeC") {
|
||||
this.typeCSecret = this.policy.params.secret
|
||||
}
|
||||
|
||||
this.generateTypeCSecret = function () {
|
||||
this.$post(".random")
|
||||
.success(function (resp) {
|
||||
this.typeCSecret = resp.data.random
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* TypeD
|
||||
*/
|
||||
this.typeDSecret = ""
|
||||
this.typeDSignParamName = "sign"
|
||||
this.typeDTimestampParamName = "t"
|
||||
|
||||
if (this.policy.type == "typeD") {
|
||||
this.typeDSecret = this.policy.params.secret
|
||||
this.typeDSignParamName = this.policy.params.signParamName
|
||||
this.typeDTimestampParamName = this.policy.params.timestampParamName
|
||||
this.$delay(function () {
|
||||
this.changeTypeDSignParamName()
|
||||
this.changeTypeDTimestampParamName()
|
||||
})
|
||||
}
|
||||
|
||||
this.generateTypeDSecret = function () {
|
||||
this.$post(".random")
|
||||
.success(function (resp) {
|
||||
this.typeDSecret = resp.data.random
|
||||
})
|
||||
}
|
||||
|
||||
this.changeTypeDSignParamName = function () {
|
||||
this.authDescription = this.rawDescription.replace("sign=", this.typeDSignParamName + "=")
|
||||
this.authDescription = this.authDescription.replace("t=", this.typeDTimestampParamName + "=")
|
||||
}
|
||||
|
||||
this.changeTypeDTimestampParamName = function () {
|
||||
this.authDescription = this.rawDescription.replace("sign=", this.typeDSignParamName + "=")
|
||||
this.authDescription = this.authDescription.replace("t=", this.typeDTimestampParamName + "=")
|
||||
}
|
||||
|
||||
/**
|
||||
* 基本鉴权
|
||||
*/
|
||||
this.moreBasicAuthOptionsVisible = false
|
||||
|
||||
this.showMoreBasicAuthOptions = function () {
|
||||
this.moreBasicAuthOptionsVisible = !this.moreBasicAuthOptionsVisible
|
||||
}
|
||||
|
||||
/**
|
||||
* 子请求
|
||||
*/
|
||||
this.subRequestFollowRequest = (this.policy.params.method != null && this.policy.params.method.length > 0) ? 0 : 1
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success" v-show="featureIsOn">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<http-access-log-config-box
|
||||
:v-access-log-config="accessLogConfig"
|
||||
:v-fields="fields"
|
||||
:v-default-field-codes="defaultFieldCodes"
|
||||
:v-access-log-policies="accessLogPolicies"></http-access-log-config-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
|
||||
<server-feature-required v-if="!featureIsOn"></server-feature-required>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
14
EdgeUser/web/views/@default/servers/server/settings/cache/createPopup.html
vendored
Normal file
14
EdgeUser/web/views/@default/servers/server/settings/cache/createPopup.html
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3 v-if="!isReverse && cacheRef == null">添加缓存条件</h3>
|
||||
<h3 v-if="!isReverse && cacheRef != null">修改缓存条件</h3>
|
||||
<h3 v-if="isReverse && cacheRef == null">添加不缓存条件</h3>
|
||||
<h3 v-if="isReverse && cacheRef != null">修改不缓存条件</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<table class="ui table definition selectable">
|
||||
<tbody is="http-cache-ref-box" :v-cache-ref="cacheRef" :v-is-reverse="isReverse"></tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
<p class="comment" v-if="isReverse">如果请求满足当前添加的条件,则不缓存。</p>
|
||||
</form>
|
||||
9
EdgeUser/web/views/@default/servers/server/settings/cache/createPopup.js
vendored
Normal file
9
EdgeUser/web/views/@default/servers/server/settings/cache/createPopup.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyPopup
|
||||
this.cacheRef = null
|
||||
|
||||
if (window.parent.UPDATING_CACHE_REF != null) {
|
||||
this.cacheRef = window.parent.UPDATING_CACHE_REF
|
||||
this.isReverse = this.cacheRef.isReverse
|
||||
}
|
||||
})
|
||||
11
EdgeUser/web/views/@default/servers/server/settings/cache/index.html
vendored
Normal file
11
EdgeUser/web/views/@default/servers/server/settings/cache/index.html
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<http-cache-config-box :v-cache-config="cacheConfig" :v-web-id="webId" :v-cache-policy="cachePolicy"></http-cache-config-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
3
EdgeUser/web/views/@default/servers/server/settings/cache/index.js
vendored
Normal file
3
EdgeUser/web/views/@default/servers/server/settings/cache/index.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,18 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<http-cc-config-box :v-cc-config="ccConfig"></http-cc-config-box>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,11 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<http-charsets-box :v-usual-charsets="usualCharsets" :v-all-charsets="allCharsets" :v-charset-config="charsetConfig"></http-charsets-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<form method="post" class="ui form" data-tea-success="success" data-tea-action="$">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<input type="hidden" name="gzipId" :value="gzipConfig.id"/>
|
||||
|
||||
<http-gzip-box :v-gzip-ref="gzipRef" :v-gzip-config="gzipConfig"></http-gzip-box>
|
||||
|
||||
<div class="margin"></div>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<div v-if="hasGroupConfig">
|
||||
<div class="margin"></div>
|
||||
<warning-message>由于已经在当前<a :href="groupSettingURL">网站分组</a>中进行了对应的配置,在这里的配置将不会生效。</warning-message>
|
||||
</div>
|
||||
|
||||
<div :class="{'opacity-mask': hasGroupConfig}">
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
|
||||
<http-compression-config-box :v-compression-config="compressionConfig"></http-compression-config-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,43 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3 v-if="!isUpdating">添加子条件</h3>
|
||||
<h3 v-if="isUpdating">修改子条件</h3>
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">选择条件类型</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="condType" v-model="condType" @change="changeCondType">
|
||||
<option v-for="c in components" :value="c.type">{{c.name}}</option>
|
||||
</select>
|
||||
{$ range .components}
|
||||
<p class="comment" v-if="condType == '{$ .Type}'">{$ .Description}</p>
|
||||
{$ end}
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="condType != 'params'">
|
||||
<td>{{paramsTitle}}</td>
|
||||
<td>
|
||||
{$ range .components}
|
||||
{$if not (eq .Type "params") }
|
||||
<{$ .Component} v-if="condType == '{$ .Type}'" :v-cond="cond" ref="component"></{$ .Component}>
|
||||
{$end}
|
||||
{$ end}
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="paramsCaseInsensitive">
|
||||
<td>不区分大小写</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" v-model="isCaseInsensitive" @change="changeCaseInsensitive"/>
|
||||
<label></label>
|
||||
</div>
|
||||
<p class="comment">选中后表示对比时忽略参数值的大小写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 变量相关 -->
|
||||
<tbody is="http-cond-params" :v-cond="cond" v-if="condType == 'params'"></tbody>
|
||||
</table>
|
||||
<submit-btn>确定</submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,55 @@
|
||||
Tea.context(function () {
|
||||
this.isUpdating = false
|
||||
this.cond = null
|
||||
this.paramsTitle = ""
|
||||
this.paramsCaseInsensitive = false
|
||||
this.isCaseInsensitive = false
|
||||
|
||||
this.success = NotifyPopup
|
||||
this.condType = (this.components.length > 0) ? this.components[0].type : ""
|
||||
|
||||
// 是否正在修改
|
||||
if (window.parent.UPDATING_COND != null) {
|
||||
this.isUpdating = true
|
||||
this.condType = window.parent.UPDATING_COND.type
|
||||
this.cond = window.parent.UPDATING_COND
|
||||
if (typeof (this.cond.isCaseInsensitive) == "boolean") {
|
||||
this.isCaseInsensitive = this.cond.isCaseInsensitive
|
||||
}
|
||||
}
|
||||
|
||||
this.changeCondType = function () {
|
||||
let that = this
|
||||
let c = this.components.$find(function (k, v) {
|
||||
return v.type == that.condType
|
||||
})
|
||||
if (c == null || c.paramsTitle.length == 0) {
|
||||
that.paramsTitle = "条件参数"
|
||||
that.paramsCaseInsensitive = false
|
||||
} else {
|
||||
that.paramsTitle = c.paramsTitle
|
||||
if (typeof (c.caseInsensitive) != "undefined") {
|
||||
that.paramsCaseInsensitive = c.caseInsensitive
|
||||
that.$delay(function () {
|
||||
that.changeCaseInsensitive()
|
||||
})
|
||||
} else {
|
||||
that.paramsCaseInsensitive = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.$delay(function () {
|
||||
this.changeCondType()
|
||||
})
|
||||
|
||||
this.changeCaseInsensitive = function () {
|
||||
let componentRef = this.$refs.component
|
||||
if (componentRef == null) {
|
||||
return
|
||||
}
|
||||
if (typeof (componentRef.changeCaseInsensitive) == "function") {
|
||||
componentRef.changeCaseInsensitive(this.isCaseInsensitive)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,59 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3 v-if="!isUpdating">添加条件分组</h3>
|
||||
<h3 v-if="isUpdating">修改条件分组</h3>
|
||||
<form method="post" class="ui form" data-tea-success="success" data-tea-action="$">
|
||||
<input type="hidden" name="condGroupJSON" :value="JSON.stringify(group)"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">子条件列表</td>
|
||||
<td style="word-break: break-all">
|
||||
<div v-if="group.conds.length > 0">
|
||||
<var v-for="(cond, index) in group.conds" style="font-style: normal;display: inline-block; margin-bottom:0.5em">
|
||||
<span class="ui label small">
|
||||
<var v-if="cond.type.length == 0 || cond.type == 'params'" style="font-style: normal">{{cond.param}} <var>{{cond.operator}}</var></var>
|
||||
<var v-if="cond.type.length > 0 && cond.type != 'params'" style="font-style: normal">{{typeName(cond)}}: </var>
|
||||
{{cond.value}}
|
||||
<sup v-if="cond.isCaseInsensitive" title="不区分大小写"><i class="icon info small"></i></sup>
|
||||
<a href="" title="修改" @click.prevent="updateCond(index, cond)"><i class="icon pencil small"></i></a> <a href="" title="删除" @click.prevent="removeCond(index)"><i class="icon remove"></i></a> </span>
|
||||
<var v-if="index < group.conds.length - 1"> {{group.connector}} </var>
|
||||
</var>
|
||||
<div class="ui divider"></div>
|
||||
</div>
|
||||
<button class="ui button tiny" type="button" @click.prevent="addCond()">+</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>子条件之间关系</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" v-model="group.connector">
|
||||
<option value="and">和</option>
|
||||
<option value="or">或</option>
|
||||
</select>
|
||||
<p class="comment" v-if="group.connector == 'and'">必须满足所有条件才能成立。</p>
|
||||
<p class="comment" v-if="group.connector == 'or'">只要满足其中一个条件即可成立。</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="3" v-model="group.description" maxlength="100"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>启用当前分组</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" v-model="group.isOn"/>
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn>确定</submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,72 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyPopup
|
||||
|
||||
this.group = {
|
||||
connector: "and", // 默认为and,更符合用户的直觉
|
||||
description: "",
|
||||
isReverse: false,
|
||||
conds: [],
|
||||
isOn: true
|
||||
}
|
||||
|
||||
this.isUpdating = false
|
||||
|
||||
// 是否在修改
|
||||
this.$delay(function () {
|
||||
if (window.parent.UPDATING_COND_GROUP != null) {
|
||||
this.group = window.parent.UPDATING_COND_GROUP
|
||||
this.isUpdating = true
|
||||
} else if (this.group.conds.length == 0) {
|
||||
// 如果尚未有条件,则自动弹出添加界面
|
||||
this.addCond()
|
||||
}
|
||||
})
|
||||
|
||||
// 条件类型名称
|
||||
this.typeName = function (cond) {
|
||||
let c = this.components.$find(function (k, v) {
|
||||
return v.type == cond.type
|
||||
})
|
||||
if (c != null) {
|
||||
return c.name;
|
||||
}
|
||||
return cond.param + " " + cond.operator
|
||||
}
|
||||
|
||||
// 添加条件
|
||||
this.addCond = function () {
|
||||
window.UPDATING_COND = null
|
||||
|
||||
let that = this
|
||||
|
||||
teaweb.popup("/servers/server/settings/conds/addCondPopup", {
|
||||
width: "32em",
|
||||
height: "22em",
|
||||
callback: function (resp) {
|
||||
that.group.conds.push(resp.data.cond)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 删除条件
|
||||
this.removeCond = function (condIndex) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除此条件?", function () {
|
||||
that.group.conds.$remove(condIndex)
|
||||
})
|
||||
}
|
||||
|
||||
// 修改条件
|
||||
this.updateCond = function (condIndex, cond) {
|
||||
window.UPDATING_COND = cond
|
||||
let that = this
|
||||
|
||||
teaweb.popup("/servers/server/settings/conds/addCondPopup", {
|
||||
width: "32em",
|
||||
height: "22em",
|
||||
callback: function (resp) {
|
||||
Vue.set(that.group.conds, condIndex, resp.data.cond)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
.checkboxes .checkbox {
|
||||
width: 8em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
/*# sourceMappingURL=index.css.map */
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA,WACC;EACC,UAAA;EACA,oBAAA","file":"index.css"}
|
||||
@@ -0,0 +1,75 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>批量复制配置</h3>
|
||||
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success" data-tea-done="done" data-tea-before="before">
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<input type="hidden" name="configCode" :value="configCode"/>
|
||||
<input type="hidden" name="targetsJSON" :value="JSON.stringify(targets)"/>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="title">将当前配置复制到</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" v-model="targetType" @change="changeTargetType">
|
||||
<option value="">[选择目标]</option>
|
||||
<option v-for="option in targetOptions" :value="option.code">{{option.name}}</option>
|
||||
</select>
|
||||
<p class="comment" v-if="configCode == 'waf'">目前只能同步WAF设置的启用和停用,不能复制规则、IP名单等。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- WAF特殊选项 -->
|
||||
<tbody v-show="configCode == 'waf'">
|
||||
<tr>
|
||||
<td>同时拷贝国家/地区/省份封禁</td>
|
||||
<td>
|
||||
<checkbox name="wafCopyRegions"></checkbox>
|
||||
<p class="comment">WAF设置专有选项。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 选择分组 -->
|
||||
<tbody v-show="targetType == 'group'">
|
||||
<tr v-show="userId > 0">
|
||||
<td>分组</td>
|
||||
<td>
|
||||
<div class="checkboxes">
|
||||
<checkbox v-for="userGroup in userGroups" :v-value="userGroup.id" @input="changeGroupId(userGroup.id)">{{userGroup.name}}</checkbox>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 选择网站 -->
|
||||
<tbody v-show="targetType == 'server'">
|
||||
<tr>
|
||||
<td>网站</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 网站数量 -->
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>目标网站数量</td>
|
||||
<td>
|
||||
<span v-if="countServers < 0">-</span>
|
||||
<span v-else><strong>{{countServers}}个</strong></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="countServers > 0">
|
||||
<td>提醒</td>
|
||||
<td><span class="red">此操作无法撤销,请谨慎确认!</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<submit-btn v-show="!isRequesting">确认复制</submit-btn>
|
||||
<button class="ui button disabled" type="button" v-show="isRequesting">正在复制...</button>
|
||||
</form>
|
||||
@@ -0,0 +1,51 @@
|
||||
Tea.context(function () {
|
||||
this.targetType = ""
|
||||
this.countServers = -1
|
||||
|
||||
this.targets = []
|
||||
|
||||
this.reloadCountServers = function () {
|
||||
this.countServers = -1
|
||||
this.$post(".countServers")
|
||||
.params({
|
||||
"targets": this.targets
|
||||
})
|
||||
.success(function (resp) {
|
||||
this.countServers = resp.data.countServers
|
||||
})
|
||||
}
|
||||
|
||||
this.changeTargetType = function () {
|
||||
this.targets = []
|
||||
this.countServers = -1
|
||||
if (this.targetType.match(/^(user):/)) {
|
||||
this.targets = [this.targetType]
|
||||
this.reloadCountServers()
|
||||
}
|
||||
}
|
||||
|
||||
let groupIds = []
|
||||
this.changeGroupId = function (groupId) {
|
||||
if (groupIds.$contains(groupId)) {
|
||||
groupIds.$removeValue(groupId)
|
||||
} else {
|
||||
groupIds.push(groupId)
|
||||
}
|
||||
if (groupIds.length > 0) {
|
||||
this.targets = ["groups:" + groupIds.join(",")]
|
||||
this.reloadCountServers()
|
||||
} else {
|
||||
this.targets = []
|
||||
this.countServers = -1
|
||||
}
|
||||
}
|
||||
|
||||
this.isRequesting = false
|
||||
this.before = function () {
|
||||
this.isRequesting = true
|
||||
}
|
||||
|
||||
this.done = function () {
|
||||
this.isRequesting = false
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
.checkboxes {
|
||||
.checkbox {
|
||||
width: 8em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">当前网站CNAME</td>
|
||||
<td>
|
||||
<span id="cname-text">{{dnsName}}.<span v-if="dnsDomain.length > 0">{{dnsDomain}}.</span><span v-else>根域名</span></span> <copy-to-clipboard :v-target="'cname-text'"></copy-to-clipboard>
|
||||
<p class="comment">你需要为你的每个<a :href="'/servers/server/settings/serverNames?serverId=' + serverId">网站域名</a>设置一个CNAME解析,值为上面内容。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -0,0 +1,19 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">网站分组</td>
|
||||
<td>
|
||||
<server-group-selector :v-groups="groups"></server-group-selector>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,16 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>添加需要删除的报头</h3>
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="headerPolicyId" :value="headerPolicyId"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">报头名称<em>(Name)</em></td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="100" ref="focus" v-model="headerName"/>
|
||||
<p class="comment"><http-header-assistant :v-type="type" :v-value="headerName" @select="selectHeader"></http-header-assistant>请注意报头名称的大小写,如无特殊需求,报头名称的格式通常为<code-label>Xxx</code-label>或者<code-label>Xxx-Yyy</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,7 @@
|
||||
Tea.context(function () {
|
||||
this.headerName = ""
|
||||
|
||||
this.selectHeader = function (headerName) {
|
||||
this.headerName = headerName
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,16 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>添加非标报头</h3>
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="headerPolicyId" :value="headerPolicyId"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">报头名称<em>(Name)</em></td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="100" ref="focus" v-model="headerName"/>
|
||||
<p class="comment">比如<code-label>hello_world</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,7 @@
|
||||
Tea.context(function () {
|
||||
this.headerName = ""
|
||||
|
||||
this.selectHeader = function (headerName) {
|
||||
this.headerName = headerName
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,72 @@
|
||||
{$layout "layout_popup"}
|
||||
<h3 v-if="type == 'request'">添加自定义请求报头</h3>
|
||||
<h3 v-if="type == 'response'">添加自定义响应报头</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="headerPolicyId" :value="headerPolicyId"/>
|
||||
<input type="hidden" name="type" :value="type"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">报头名称<em>(Name)</em> *</td>
|
||||
<td>
|
||||
<input type="text" name="name" value="" maxlength="200" placeholder="类似于Server、Content-Type之类" ref="focus" v-model="headerName" autocomplete="off"/>
|
||||
<p class="comment"><http-header-assistant :v-type="type" :v-value="headerName" @select="selectHeader"></http-header-assistant>请注意报头名称的大小写,如无特殊需求,报头名称的格式通常为<code-label>Xxx</code-label>或者<code-label>Xxx-Yyy</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>值<em>(Value)</em></td>
|
||||
<td>
|
||||
<input type="text" name="value" maxlength="500"/>
|
||||
<p class="comment">可以包含请求变量。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator>更多选项</more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr v-show="type == 'response'">
|
||||
<td>支持的状态码</td>
|
||||
<td>
|
||||
<http-status-box></http-status-box>
|
||||
<p class="comment">不填表示支持所有的状态码。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>支持的请求方法</td>
|
||||
<td><http-methods-box></http-methods-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>支持的域名</td>
|
||||
<td><domains-box></domains-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>只附加不替换</td>
|
||||
<td>
|
||||
<checkbox name="shouldAppend"></checkbox>
|
||||
<p class="comment">选中后表示如果已经存在同名的报头,则只会附加在原有的报头之后,不会覆盖。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="type == 'response'">
|
||||
<td>不在跳转时启用</td>
|
||||
<td>
|
||||
<checkbox name="disableRedirect"></checkbox>
|
||||
<p class="comment">选中后表示在30X跳转时不启用当前报头。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">启用内容替换</td>
|
||||
<td>
|
||||
<checkbox name="shouldReplace" v-model="shouldReplace"></checkbox>
|
||||
<p class="comment">可以替换原有报头中的内容。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="shouldReplace">
|
||||
<td class="color-border">替换内容</td>
|
||||
<td>
|
||||
<http-header-replace-values></http-header-replace-values>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,8 @@
|
||||
Tea.context(function () {
|
||||
this.shouldReplace = false
|
||||
this.headerName = ""
|
||||
|
||||
this.selectHeader = function (headerName) {
|
||||
this.headerName = headerName
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<http-header-policy-box
|
||||
:v-request-header-policy="requestHeaderPolicy"
|
||||
:v-response-header-policy="responseHeaderPolicy"
|
||||
:v-params="'serverId=' + serverId"
|
||||
:v-has-group-request-config="hasGroupRequestConfig"
|
||||
:v-has-group-response-config="hasGroupResponseConfig"
|
||||
:v-group-setting-url="groupSettingURL"></http-header-policy-box>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>CORS跨域设置</h3>
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="headerPolicyId" :value="headerPolicyId"/>
|
||||
<http-cors-header-config-box v-model="cors"></http-cors-header-config-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,73 @@
|
||||
{$layout "layout_popup"}
|
||||
<h3 v-if="type == 'request'">修改自定义请求报头</h3>
|
||||
<h3 v-if="type == 'response'">修改自定义响应报头</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="headerPolicyId" :value="headerPolicyId"/>
|
||||
<input type="hidden" name="headerId" :value="headerId"/>
|
||||
<input type="hidden" name="type" :value="type"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">报头名称<em>(Name)</em> *</td>
|
||||
<td>
|
||||
<input type="text" name="name" value="" v-model="headerConfig.name" maxlength="200" placeholder="类似于Server、Content-Type之类" ref="focus"/>
|
||||
<p class="comment"><http-header-assistant :v-type="type" :v-value="headerConfig.name" @select="selectHeader"></http-header-assistant>请注意报头名称的大小写,如无特殊需求,报头名称的格式通常为<code-label>Xxx</code-label>或者<code-label>Xxx-Yyy</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>值<em>(Value)</em></td>
|
||||
<td>
|
||||
<input type="text" name="value" v-model="headerConfig.value" maxlength="500"/>
|
||||
<p class="comment">可以包含请求变量。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator>更多选项</more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr v-show="type == 'response'">
|
||||
<td>支持的状态码</td>
|
||||
<td>
|
||||
<http-status-box :v-status-list="statusList"></http-status-box>
|
||||
<p class="comment">不填表示支持所有的状态码。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>支持的请求方法</td>
|
||||
<td><http-methods-box :v-methods="headerConfig.methods"></http-methods-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>支持的域名</td>
|
||||
<td><domains-box :v-domains="headerConfig.domains"></domains-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>只附加不替换</td>
|
||||
<td>
|
||||
<checkbox name="shouldAppend" v-model="headerConfig.shouldAppend"></checkbox>
|
||||
<p class="comment">选中后表示如果已经存在同名的报头,则只会附加在原有的报头之后,不会覆盖。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="type == 'response'">
|
||||
<td>不在跳转时启用</td>
|
||||
<td>
|
||||
<checkbox name="disableRedirect" v-model="headerConfig.disableRedirect"></checkbox>
|
||||
<p class="comment">选中后表示在30X跳转时不启用当前报头。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">启用内容替换</td>
|
||||
<td>
|
||||
<checkbox name="shouldReplace" v-model="shouldReplace"></checkbox>
|
||||
<p class="comment">可以替换原有报头中的内容。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="shouldReplace">
|
||||
<td class="color-border">替换内容</td>
|
||||
<td>
|
||||
<http-header-replace-values :v-replace-values="headerConfig.replaceValues"></http-header-replace-values>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,11 @@
|
||||
Tea.context(function () {
|
||||
this.shouldReplace = this.headerConfig.shouldReplace
|
||||
this.statusList = []
|
||||
if (this.headerConfig.status != null && this.headerConfig.status.codes != null) {
|
||||
this.statusList = this.headerConfig.status.codes
|
||||
}
|
||||
|
||||
this.selectHeader = function (headerName) {
|
||||
this.headerConfig.name = headerName
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,31 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<input type="hidden" name="serverType" :value="serverType"/>
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">启用HTTP</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="isOn" value="1" v-model="httpConfig.isOn"/>
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tbody v-show="httpConfig.isOn">
|
||||
<tr>
|
||||
<td>自动跳转到HTTPS</td>
|
||||
<td>
|
||||
<http-redirect-to-https-box :v-redirect-to-https-config="redirectToHTTPSConfig"></http-redirect-to-https-box>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,38 @@
|
||||
{$layout}
|
||||
|
||||
{$var "header"}
|
||||
<script src="/servers/certs/datajs" type="text/javascript"></script>
|
||||
<script src="/js/sortable.min.js" type="text/javascript"></script>
|
||||
{$end}
|
||||
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<p class="comment">提醒:HTTP/2、证书等信息修改后,可能需要清空浏览器缓存后才能浏览效果。</p>
|
||||
|
||||
<div v-if="httpsConfig.isOn && (missingCertServerNames || []).length > 0" class="ui message warning">
|
||||
警告:当前网站绑定的以下域名尚未配置证书,将无法通过HTTPS协议访问:{{missingCertServerNames.join("、")}} 。
|
||||
</div>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<input type="hidden" name="serverType" :value="serverType"/>
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">启用HTTPS</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="isOn" value="1" v-model="httpsConfig.isOn"/>
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- SSL配置 -->
|
||||
<ssl-config-box :v-ssl-policy="httpsConfig.sslPolicy" :v-protocol="'https'" v-show="httpsConfig.isOn" :v-server-id="serverId" :v-support-http3="httpsConfig.supportsHTTP3 && http3FeatureEnabled"></ssl-config-box>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,43 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>申请免费证书</h3>
|
||||
<form method="post" class="ui form" data-tea-success="success" data-tea-action="$" data-tea-timeout="300" data-tea-before="beforeSubmit" data-tea-fail="fail">
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">证书包含的域名 *</td>
|
||||
<td>
|
||||
<span v-if="serverNames.length == 0" class="disabled">还没有需要申请证书的域名,暂时不能申请。</span>
|
||||
<div v-if="serverNames.length > 0">
|
||||
<div v-for="(serverName, index) in serverNames" class="ui tiny basic label">
|
||||
<input type="hidden" name="serverNames" :value="serverName"/>
|
||||
{{serverName}}
|
||||
<a href="" title="删除" @click.prevent="remove(index)"><i class="icon remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>证书用户 *</td>
|
||||
<td>
|
||||
<div v-if="users.length > 0">
|
||||
<select class="ui dropdown auto-width" name="userId" v-model="userId">
|
||||
<option value="0">[请选择]</option>
|
||||
<option v-for="user in users" :value="user.id">{{user.email}}{{user.description}}</option>>
|
||||
</select>
|
||||
<p class="comment">用来申请证书的用户。</p>
|
||||
</div>
|
||||
|
||||
<div v-if="users.length == 0">
|
||||
<input type="text" name="userEmail" maxlength="100" placeholder="用户E-mail" ref="focus"/>
|
||||
<p class="comment">用来申请证书的用户邮箱,可以任意填写,只要格式正确即可。</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn v-if="!isRequesting">提交</submit-btn>
|
||||
<button class="ui button" type="button" v-if="isRequesting">处理中...</button>
|
||||
</form>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
Tea.context(function () {
|
||||
this.isRequesting = false
|
||||
this.userId = 0
|
||||
|
||||
this.remove = function (index) {
|
||||
this.serverNames.$remove(index)
|
||||
}
|
||||
|
||||
this.beforeSubmit = function () {
|
||||
this.isRequesting = true
|
||||
}
|
||||
|
||||
this.fail = function (resp) {
|
||||
this.isRequesting = false
|
||||
teaweb.warn(resp.message)
|
||||
if (resp.data.acmeUser != null) {
|
||||
this.users.push({
|
||||
id: resp.data.acmeUser.id,
|
||||
email: resp.data.acmeUser.email,
|
||||
description: ""
|
||||
})
|
||||
this.userId = resp.data.acmeUser.id
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
<first-menu>
|
||||
<menu-item code="hls" :href="'.hls?serverId=' + server.id">启用HLS加密配置</menu-item>
|
||||
</first-menu>
|
||||
@@ -0,0 +1,14 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<form class="ui form" data-tea-success="success" data-tea-action="$">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
|
||||
<http-hls-config-box v-model="hlsConfig"></http-hls-config-box>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<div v-if="hasGroupConfig">
|
||||
<div class="margin"></div>
|
||||
<warning-message>由于已经在当前<a :href="groupSettingURL">网站分组</a>中进行了对应的配置,在这里的配置将不会生效。</warning-message>
|
||||
</div>
|
||||
|
||||
<div :class="{'opacity-mask': hasGroupConfig}">
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
|
||||
<http-encryption-config-box :v-encryption-config="encryptionConfig"></http-encryption-config-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,119 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>添加源站</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="reverseProxyId" :value="reverseProxyId"/>
|
||||
<input type="hidden" name="originType" :value="originType"/>
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">源站协议</td>
|
||||
<td>
|
||||
<!-- HTTP -->
|
||||
<select class="ui dropdown auto-width" name="protocol" v-model="protocol" v-if="serverType == 'httpProxy' || serverType == 'httpWeb'" @change="changeProtocol">
|
||||
<option value="http">HTTP</option>
|
||||
<option value="https">HTTPS</option>
|
||||
|
||||
<!-- 对象存储 -->
|
||||
<optgroup label="对象存储" v-if="ossTypes.length > 0"></optgroup>
|
||||
<option v-for="ossType in ossTypes" :value="ossType.code">{{ossType.name}}</option>
|
||||
</select>
|
||||
|
||||
<!-- TCP -->
|
||||
<select class="ui dropdown auto-width" name="protocol" v-model="protocol" v-if="serverType == 'tcpProxy'">
|
||||
<option value="tcp">TCP</option>
|
||||
<option value="tls">TLS</option>
|
||||
</select>
|
||||
|
||||
<!-- UDP -->
|
||||
<select class="ui dropdown auto-width" name="protocol" v-model="protocol" v-if="serverType == 'udpProxy'">
|
||||
<option value="udp">UDP</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 普通源站 -->
|
||||
<tr v-show="!isOSS">
|
||||
<td class="title">源站地址 *</td>
|
||||
<td>
|
||||
<div class="ui input left labeled">
|
||||
<span class="ui label">{{protocol.toLowerCase()}}://</span>
|
||||
<input type="text" name="addr" ref="focus" v-model="addr" @input="changeAddr" @change="detectHTTPS"/>
|
||||
</div>
|
||||
<p class="comment" style="padding-bottom: 0; margin-bottom: 0" v-if="addrError.length == 0 && adviceHTTPS && protocol == 'http'"><span class="red">系统检测到当前源站有HTTPS协议可用,是否切换到HTTPS协议?</span> <a href="" @click.prevent="switchToHTTPS">[点此切换]</a></p>
|
||||
<p class="comment"><span class="red" v-if="addrError.length > 0">{{addrError}}</span>
|
||||
源站服务器地址,通常是一个IP(或域名)加端口,80和443端口可以省略<span v-if="serverType == 'httpProxy'">,不需要加 http:// 或 https://</span>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="(isHTTP || protocol == 'tls') && !isOSS">
|
||||
<td>回源主机名</td>
|
||||
<td>
|
||||
<input type="text" name="host" placeholder="比如example.com" maxlength="100"/>
|
||||
<p class="comment">可选项。请求源站时的Host,用于设置访问源站的站点域名<span v-if="isHTTP">,自定义Host内容中支持请求变量</span>;如果用户访问的域名和源站域名不一致,请务必设置为源站域名。</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- OSS -->
|
||||
{$ .ossForm}
|
||||
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr v-if="protocol == 'https' || protocol == 'tls'">
|
||||
<td>{{protocol.toUpperCase()}}证书</td>
|
||||
<td>
|
||||
<ssl-certs-box :v-single-mode="true" :v-view-size="'mini'" :v-description="'可以选择连接源站使用的证书;除非源站有特殊需求,否则不需要添加。'"></ssl-certs-box>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="protocol != 'udp'">
|
||||
<td>专属域名</td>
|
||||
<td>
|
||||
<domains-box></domains-box>
|
||||
<p class="comment">默认不需要填写,表示支持所有域名。如果填写了专属域名,表示这些源站只会在所列的专属域名被访问时才生效。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="!isOSS">
|
||||
<td>端口跟随</td>
|
||||
<td>
|
||||
<checkbox name="followPort"></checkbox>
|
||||
<p class="comment">选中后表示源站的端口保持和用户访问的服务端口保持一致;此时的源站地址中的端口号可以任意填写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="!isOSS && protocol == 'https'">
|
||||
<td>支持HTTP/2</td>
|
||||
<td>
|
||||
<checkbox name="http2Enabled"></checkbox>
|
||||
<p class="comment">选中后,表示源站支持HTTP/2协议。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>权重</td>
|
||||
<td>
|
||||
<input type="text" name="weight" maxlength="4" value="10" style="width:5em"/>
|
||||
<p class="comment">数字越大,代表分配的请求比例越多。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>名称</td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="100"/>
|
||||
<p class="comment">给当前源站起一个容易识别的名称。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>备注</td>
|
||||
<td>
|
||||
<textarea name="description" rows="3" maxlength="100"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>启用当前源站</td>
|
||||
<td>
|
||||
<checkbox name="isOn" :value="true"></checkbox>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,96 @@
|
||||
Tea.context(function () {
|
||||
this.addr = ""
|
||||
this.protocol = ""
|
||||
this.isOSS = false
|
||||
|
||||
this.addrError = ""
|
||||
|
||||
if (this.isHTTP) {
|
||||
this.protocol = "http"
|
||||
} else if (this.serverType == "tcpProxy") {
|
||||
this.protocol = "tcp"
|
||||
} else if (this.serverType == "udpProxy") {
|
||||
this.protocol = "udp"
|
||||
}
|
||||
|
||||
this.changeProtocol = function () {
|
||||
this.isOSS = this.protocol.startsWith("oss:")
|
||||
|
||||
if (this.protocol == "http") {
|
||||
this.detectHTTPS()
|
||||
} else {
|
||||
this.adviceHTTPS = false
|
||||
}
|
||||
|
||||
this.checkPort()
|
||||
}
|
||||
|
||||
this.changeAddr = function () {
|
||||
this.adviceHTTPS = false
|
||||
|
||||
if (this.serverType == "httpProxy") {
|
||||
if (this.addr.startsWith("http://")) {
|
||||
this.protocol = "http"
|
||||
} else if (this.addr.startsWith("https://")) {
|
||||
this.protocol = "https"
|
||||
}
|
||||
}
|
||||
|
||||
this.checkPort()
|
||||
}
|
||||
|
||||
this.checkPort = function () {
|
||||
this.addrError = ""
|
||||
|
||||
// HTTP
|
||||
if (this.protocol == "http") {
|
||||
if (this.addr.endsWith(":443")) {
|
||||
this.addrError = "443通常是HTTPS协议端口,请确认源站协议选择是否正确。"
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPS
|
||||
if (this.protocol == "https") {
|
||||
if (this.addr.endsWith(":80")) {
|
||||
this.addrError = "80通常是HTTP协议端口,请确认源站协议选择是否正确。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.adviceHTTPS = false
|
||||
var isDetectingHTTPS = false
|
||||
this.detectHTTPS = function () {
|
||||
if (isDetectingHTTPS) {
|
||||
return
|
||||
}
|
||||
isDetectingHTTPS = true
|
||||
|
||||
this.adviceHTTPS = false
|
||||
if (this.protocol == "http") {
|
||||
this.$post(".detectHTTPS")
|
||||
.params({
|
||||
addr: this.addr
|
||||
})
|
||||
.success(function (resp) {
|
||||
this.adviceHTTPS = resp.data.isOk
|
||||
if (resp.data.isOk) {
|
||||
this.addr = resp.data.addr
|
||||
}
|
||||
})
|
||||
.done(function () {
|
||||
isDetectingHTTPS = false
|
||||
})
|
||||
} else {
|
||||
isDetectingHTTPS = false
|
||||
}
|
||||
}
|
||||
|
||||
this.switchToHTTPS = function () {
|
||||
this.adviceHTTPS = false
|
||||
this.protocol = "https"
|
||||
|
||||
if (this.addr.endsWith(":80")) {
|
||||
this.addr = this.addr.substring(0, this.addr.length - (":80").length)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,194 @@
|
||||
|
||||
|
||||
<!-- 腾讯云COS -->
|
||||
<tbody v-if="protocol == 'oss:tencentCOS'">
|
||||
<tr>
|
||||
<td>密钥ID *<br/><em>(Secret Id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="tencentCOSSecretId" maxlength="100"/>
|
||||
<p class="comment">访问存储桶需要的密钥ID。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>密钥Key *<br/><em>(Secret Key)</em></td>
|
||||
<td>
|
||||
<input type="text" name="tencentCOSSecretKey" maxlength="100"/>
|
||||
<p class="comment">访问存储桶需要的密钥Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>所属区域代号 *</td>
|
||||
<td>
|
||||
<input type="text" name="tencentCOSRegion" maxlength="100"/>
|
||||
<p class="comment">COS服务所属区域代号,类似于<code-label>ap-beijing</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 阿里云OSS -->
|
||||
<tbody v-if="protocol == 'oss:aliyunOSS'">
|
||||
<tr>
|
||||
<td>密钥ID *<br/><em>(AccessKey Id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="aliyunOSSAccessKeyId" maxlength="100"/>
|
||||
<p class="comment">访问存储空间需要的密钥ID。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>密钥Key *<br/><em>(AccessKey Secret)</em></td>
|
||||
<td>
|
||||
<input type="text" name="aliyunOSSAccessKeySecret" maxlength="100"/>
|
||||
<p class="comment">访问存储空间需要的密钥Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>地域节点 *</td>
|
||||
<td>
|
||||
<input type="text" name="aliyunOSSEndpoint" maxlength="100"/>
|
||||
<p class="comment">地域节点域名(Endpoint),类似于<code-label>oss-cn-shanghai.aliyuncs.com</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 华为云 -->
|
||||
<tbody v-if="protocol == 'oss:huaweiOBS'">
|
||||
<tr>
|
||||
<td>密钥ID *<br/><em>(AccessKey Id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="huaweiOBSAccessKeyId" maxlength="100"/>
|
||||
<p class="comment">访问存储桶需要的密钥ID。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>密钥Key *<br/><em>(AccessKey Secret)</em></td>
|
||||
<td>
|
||||
<input type="text" name="huaweiOBSAccessKeySecret" maxlength="100"/>
|
||||
<p class="comment">访问存储桶需要的密钥Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域Endpoint *</td>
|
||||
<td>
|
||||
<div class="ui input left labeled">
|
||||
<span class="ui label">https://</span>
|
||||
<input type="text" name="huaweiOBSEndpoint" maxlength="100"/>
|
||||
</div>
|
||||
<p class="comment">区域Endpoint域名,类似于<code-label>obs.cn-north-4.myhuaweicloud.com</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 百度云 -->
|
||||
<tbody v-if="protocol == 'oss:baiduBOS'">
|
||||
<tr>
|
||||
<td>Access Key *</td>
|
||||
<td>
|
||||
<input type="text" name="baiduBOSAccessKey" maxlength="100"/>
|
||||
<p class="comment">访问Bucket需要的Access Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secret Key *</td>
|
||||
<td>
|
||||
<input type="text" name="baiduBOSSecretKey" maxlength="100"/>
|
||||
<p class="comment">访问存储桶需要的Secret Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域Endpoint *</td>
|
||||
<td>
|
||||
<div class="ui input left labeled">
|
||||
<span class="ui label">https://</span>
|
||||
<input type="text" name="baiduBOSEndpoint" maxlength="100"/>
|
||||
</div>
|
||||
<p class="comment">区域Endpoint域名,类似于<code-label>bj.bcebos.com</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 七牛云 -->
|
||||
<tbody v-if="protocol == 'oss:qiniuKodo'">
|
||||
<tr>
|
||||
<td>AccessKey *<br/><em>(AK)</em></td>
|
||||
<td>
|
||||
<input type="text" name="qiniuKodoAccessKey" maxlength="100"/>
|
||||
<p class="comment">访问存储空间需要的AccessKey。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SecretKey *<br/><em>(SK)</em></td>
|
||||
<td>
|
||||
<input type="text" name="qiniuKodoSecretKey" maxlength="100"/>
|
||||
<p class="comment">访问存储空间需要的SecretKey。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>访问域名 *</td>
|
||||
<td>
|
||||
<div class="ui fields">
|
||||
<div class="ui field">
|
||||
<select class="ui dropdown" name="qiniuKodoProtocol">
|
||||
<option value="http">http://</option>
|
||||
<option value="https">https://</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<input type="text" name="qiniuKodoDomain" placeholder="比如 example.com" style="width: 20em"/>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>访问控制</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="qiniuKodoIsPublic">
|
||||
<option value="0">私有</option>
|
||||
<option value="1">公开</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Amazon S3 -->
|
||||
<tbody v-if="protocol == 'oss:amazonS3' || protocol == 'oss:b2'">
|
||||
<tr>
|
||||
<td>密钥ID *<br/><em>(AK)</em></td>
|
||||
<td>
|
||||
<input type="text" name="amazonS3AccessKeyId" maxlength="100"/>
|
||||
<p class="comment">访问存储桶需要的密钥ID。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>密钥Key *<br/><em>(SK)</em></td>
|
||||
<td>
|
||||
<input type="text" name="amazonS3AccessKeySecret" maxlength="100"/>
|
||||
<p class="comment">访问存储桶需要的密钥Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域代号 *<br/><em>(Region)</em></td>
|
||||
<td>
|
||||
<input type="text" name="amazonS3Region" maxlength="100"/>
|
||||
<p class="comment">所属区域代号,类似于<code-label>us-east-2</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Endpoint <span v-if="protocol != 'oss:amazonS3'">*</span></td>
|
||||
<td>
|
||||
<input type="text" name="amazonS3Endpoint" maxlength="100"/>
|
||||
<p class="comment">Endpoint域名或URL,只有非AWS应用时才需要填写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Endpoint中存储桶访问样式</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="bucketAddressStyle">
|
||||
<option value="path">路径</option>
|
||||
<option value="domain">子域名</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 存储桶名称 -->
|
||||
<tbody v-for="ossType in ossTypes" v-if="protocol == ossType.code" is="http-oss-bucket-params" :v-params="ossBucketParams" :name="ossType.bucketOptionName"></tbody>
|
||||
@@ -0,0 +1,119 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>修改源站</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="reverseProxyId" :value="reverseProxyId"/>
|
||||
<input type="hidden" name="originType" :value="originType"/>
|
||||
<input type="hidden" name="originId" :value="originId"/>
|
||||
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">源站协议</td>
|
||||
<td>
|
||||
<!-- HTTP -->
|
||||
<select class="ui dropdown auto-width" name="protocol" v-model="origin.protocol" v-if="serverType == 'httpProxy' || serverType == 'httpWeb'" @change="changeProtocol">
|
||||
<option value="http">HTTP</option>
|
||||
<option value="https">HTTPS</option>
|
||||
|
||||
<!-- 对象存储 -->
|
||||
<optgroup label="对象存储" v-if="ossTypes.length > 0"></optgroup>
|
||||
<option v-for="ossType in ossTypes" :value="ossType.code">{{ossType.name}}</option>
|
||||
</select>
|
||||
|
||||
<!-- TCP -->
|
||||
<select class="ui dropdown auto-width" name="protocol" v-model="origin.protocol" v-if="serverType == 'tcpProxy'">
|
||||
<option value="tcp">TCP</option>
|
||||
<option value="tls">TLS</option>
|
||||
</select>
|
||||
|
||||
<!-- UDP -->
|
||||
<select class="ui dropdown auto-width" name="protocol" v-model="origin.protocol" v-if="serverType == 'udpProxy'">
|
||||
<option value="udp">UDP</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 普通源站 -->
|
||||
<tr v-show="!isOSS">
|
||||
<td class="title">源站地址</td>
|
||||
<td>
|
||||
<div class="ui input left labeled">
|
||||
<span class="ui label">{{origin.protocol.toLowerCase()}}://</span>
|
||||
<input type="text" name="addr" ref="focus" v-model="origin.addr" @input="changeAddr"/>
|
||||
</div>
|
||||
<p class="comment"><span class="red" v-if="addrError.length > 0">{{addrError}}</span>源站服务器地址,通常是一个IP(或域名)加端口,80和443端口可以省略<span v-if="serverType == 'httpProxy'">,不需要加 http:// 或 https://</span>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="(isHTTP || origin.protocol == 'tls') && !isOSS">
|
||||
<td>回源主机名</td>
|
||||
<td>
|
||||
<input type="text" name="host" v-model="origin.host" placeholder="比如example.com" maxlength="100"/>
|
||||
<p class="comment">可选项。请求源站时的Host,用于设置访问源站的站点域名<span v-if="isHTTP">,自定义Host内容中支持请求变量</span>;如果用户访问的域名和源站域名不一致,请务必设置为源站域名。</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- OSS -->
|
||||
{$ .ossForm}
|
||||
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr v-if="origin.protocol == 'https' || origin.protocol == 'tls'">
|
||||
<td>{{origin.protocol.toUpperCase()}}证书</td>
|
||||
<td>
|
||||
<ssl-certs-box :v-single-mode="true" :v-cert="origin.cert" :v-view-size="'mini'" :v-description="'可以选择连接源站使用的证书;除非源站有特殊需求,否则不需要添加。'"></ssl-certs-box>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="origin.protocol != 'udp'">
|
||||
<td>专属域名</td>
|
||||
<td>
|
||||
<domains-box :v-domains="origin.domains"></domains-box>
|
||||
<p class="comment">默认不需要填写,表示支持所有域名。如果填写了专属域名,表示这些源站只会在所列的专属域名被访问时才生效。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="!isOSS">
|
||||
<td>端口跟随</td>
|
||||
<td>
|
||||
<checkbox name="followPort" v-model="origin.followPort"></checkbox>
|
||||
<p class="comment">选中后表示源站的端口保持和用户访问的服务端口保持一致;此时的源站地址中的端口号可以任意填写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="!isOSS && origin.protocol == 'https'">
|
||||
<td>支持HTTP/2</td>
|
||||
<td>
|
||||
<checkbox name="http2Enabled" v-model="origin.http2Enabled"></checkbox>
|
||||
<p class="comment">选中后,表示源站支持HTTP/2协议。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>权重</td>
|
||||
<td>
|
||||
<input type="text" name="weight" maxlength="4" v-model="origin.weight" style="width:5em"/>
|
||||
<p class="comment">数字越大,代表分配的请求比例越多。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>名称</td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="100" v-model="origin.name"/>
|
||||
<p class="comment">给当前源站起一个容易识别的名称。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>备注</td>
|
||||
<td>
|
||||
<textarea name="description" rows="3" maxlength="100" v-model="origin.description"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>启用当前源站</td>
|
||||
<td>
|
||||
<checkbox name="isOn" :value="origin.isOn"></checkbox>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,44 @@
|
||||
Tea.context(function () {
|
||||
this.addrError = ""
|
||||
this.isOSS = this.origin != null && this.origin.protocol != null && this.origin.protocol.startsWith("oss:")
|
||||
|
||||
this.$delay(function () {
|
||||
this.checkPort()
|
||||
})
|
||||
|
||||
this.changeProtocol = function () {
|
||||
this.isOSS = this.origin.protocol.startsWith("oss:")
|
||||
|
||||
this.checkPort()
|
||||
}
|
||||
|
||||
this.changeAddr = function () {
|
||||
if (this.serverType == "httpProxy") {
|
||||
if (this.origin.addr.startsWith("http://")) {
|
||||
this.origin.protocol = "http"
|
||||
} else if (this.origin.addr.startsWith("https://")) {
|
||||
this.origin.protocol = "https"
|
||||
}
|
||||
}
|
||||
|
||||
this.checkPort()
|
||||
}
|
||||
|
||||
this.checkPort = function () {
|
||||
this.addrError = ""
|
||||
|
||||
// HTTP
|
||||
if (this.origin.protocol == "http") {
|
||||
if (this.origin.addr.endsWith(":443")) {
|
||||
this.addrError = "443通常是HTTPS协议端口,请确认源站协议选择是否正确。"
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPS
|
||||
if (this.origin.protocol == "https") {
|
||||
if (this.origin.addr.endsWith(":80")) {
|
||||
this.addrError = "80通常是HTTP协议端口,请确认源站协议选择是否正确。"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,192 @@
|
||||
<!-- 腾讯云COS -->
|
||||
<tbody v-if="origin.protocol == 'oss:tencentCOS'">
|
||||
<tr>
|
||||
<td>密钥ID *<br/><em>(Secret Id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="tencentCOSSecretId" maxlength="100" v-model="origin.oss.options.secretId"/>
|
||||
<p class="comment">访问存储桶需要的密钥ID。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>密钥Key *<br/><em>(Secret Key)</em></td>
|
||||
<td>
|
||||
<input type="text" name="tencentCOSSecretKey" maxlength="100" v-model="origin.oss.options.secretKey"/>
|
||||
<p class="comment">访问存储桶需要的密钥Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>所属区域代号 *</td>
|
||||
<td>
|
||||
<input type="text" name="tencentCOSRegion" maxlength="100" v-model="origin.oss.options.region"/>
|
||||
<p class="comment">COS服务所属区域代号,类似于<code-label>ap-beijing</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 阿里云OSS -->
|
||||
<tbody v-if="origin.protocol == 'oss:aliyunOSS'">
|
||||
<tr>
|
||||
<td>密钥ID *<br/><em>(AccessKey Id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="aliyunOSSAccessKeyId" maxlength="100" v-model="origin.oss.options.accessKeyId"/>
|
||||
<p class="comment">访问存储空间需要的密钥ID。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>密钥Key *<br/><em>(AccessKey Secret)</em></td>
|
||||
<td>
|
||||
<input type="text" name="aliyunOSSAccessKeySecret" maxlength="100" v-model="origin.oss.options.accessKeySecret"/>
|
||||
<p class="comment">访问存储空间需要的密钥Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>地域节点 *</td>
|
||||
<td>
|
||||
<input type="text" name="aliyunOSSEndpoint" maxlength="100" v-model="origin.oss.options.endpoint"/>
|
||||
<p class="comment">地域节点域名(Endpoint),类似于<code-label>oss-cn-shanghai.aliyuncs.com</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 华为云 -->
|
||||
<tbody v-if="origin.protocol == 'oss:huaweiOBS'">
|
||||
<tr>
|
||||
<td>密钥ID *<br/><em>(AccessKey Id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="huaweiOBSAccessKeyId" maxlength="100" v-model="origin.oss.options.accessKeyId"/>
|
||||
<p class="comment">访问存储桶需要的密钥ID。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>密钥Key *<br/><em>(AccessKey Secret)</em></td>
|
||||
<td>
|
||||
<input type="text" name="huaweiOBSAccessKeySecret" maxlength="100" v-model="origin.oss.options.accessKeySecret"/>
|
||||
<p class="comment">访问存储桶需要的密钥Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域Endpoint *</td>
|
||||
<td>
|
||||
<div class="ui input left labeled">
|
||||
<span class="ui label">https://</span>
|
||||
<input type="text" name="huaweiOBSEndpoint" maxlength="100" v-model="origin.oss.options.endpoint"/>
|
||||
</div>
|
||||
<p class="comment">区域Endpoint域名,类似于<code-label>obs.cn-north-4.myhuaweicloud.com</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 百度云 -->
|
||||
<tbody v-if="origin.protocol == 'oss:baiduBOS'">
|
||||
<tr>
|
||||
<td>Access Key *</td>
|
||||
<td>
|
||||
<input type="text" name="baiduBOSAccessKey" maxlength="100" v-model="origin.oss.options.accessKey"/>
|
||||
<p class="comment">访问Bucket需要的Access Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secret Key *</td>
|
||||
<td>
|
||||
<input type="text" name="baiduBOSSecretKey" maxlength="100" v-model="origin.oss.options.secretKey"/>
|
||||
<p class="comment">访问存储桶需要的Secret Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域Endpoint *</td>
|
||||
<td>
|
||||
<div class="ui input left labeled">
|
||||
<span class="ui label">https://</span>
|
||||
<input type="text" name="baiduBOSEndpoint" maxlength="100" v-model="origin.oss.options.endpoint"/>
|
||||
</div>
|
||||
<p class="comment">区域Endpoint域名,类似于<code-label>bj.bcebos.com</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 七牛云 -->
|
||||
<tbody v-if="origin.protocol == 'oss:qiniuKodo'">
|
||||
<tr>
|
||||
<td>AccessKey *<br/><em>(AccessKey)</em></td>
|
||||
<td>
|
||||
<input type="text" name="qiniuKodoAccessKey" maxlength="100" v-model="origin.oss.options.accessKey"/>
|
||||
<p class="comment">访问存储空间需要的密钥ID。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SecretKey *<br/><em>(SecretKey)</em></td>
|
||||
<td>
|
||||
<input type="text" name="qiniuKodoSecretKey" maxlength="100" v-model="origin.oss.options.secretKey"/>
|
||||
<p class="comment">访问存储空间需要的密钥Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>域名</td>
|
||||
<td>
|
||||
<div class="ui fields">
|
||||
<div class="ui field">
|
||||
<select class="ui dropdown" name="qiniuKodoProtocol" v-model="origin.oss.options.protocol">
|
||||
<option value="http">http://</option>
|
||||
<option value="https">https://</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<input type="text" name="qiniuKodoDomain" v-model="origin.oss.options.domain" style="width: 20em"/>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>访问控制</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="qiniuKodoIsPublic" v-model="origin.oss.options.isPublic">
|
||||
<option :value="false">私有</option>
|
||||
<option :value="true">公开</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Amazon S3 -->
|
||||
<tbody v-if="origin.protocol == 'oss:amazonS3' || origin.protocol == 'oss:b2'">
|
||||
<tr>
|
||||
<td>密钥ID *<br/><em>(AK)</em></td>
|
||||
<td>
|
||||
<input type="text" name="amazonS3AccessKeyId" maxlength="100" v-model="origin.oss.options.accessKeyId"/>
|
||||
<p class="comment">访问存储桶需要的密钥ID。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>密钥Key *<br/><em>(SK)</em></td>
|
||||
<td>
|
||||
<input type="text" name="amazonS3AccessKeySecret" maxlength="100" v-model="origin.oss.options.accessKeySecret"/>
|
||||
<p class="comment">访问存储桶需要的密钥Key。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域代号 *<br/><em>(Region)</em></td>
|
||||
<td>
|
||||
<input type="text" name="amazonS3Region" maxlength="100" v-model="origin.oss.options.region"/>
|
||||
<p class="comment">所属区域代号,类似于<code-label>us-east-2</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Endpoint<span v-if="origin.protocol != 'oss:amazonS3'">*</span></td>
|
||||
<td>
|
||||
<input type="text" name="amazonS3Endpoint" maxlength="100" v-model="origin.oss.options.endpoint"/>
|
||||
<p class="comment">Endpoint域名,只有非AWS应用时才需要填写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Endpoint中存储桶访问样式</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="bucketAddressStyle" v-model="origin.oss.options.bucketAddressStyle">
|
||||
<option value="path">路径</option>
|
||||
<option value="domain">子域名</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 存储桶名称 -->
|
||||
<tbody v-for="ossType in ossTypes" v-if="origin.protocol == ossType.code" is="http-oss-bucket-params" :v-params="ossBucketParams" :name="ossType.bucketOptionName" :v-oss-config="origin.oss"></tbody>
|
||||
@@ -0,0 +1,66 @@
|
||||
{$layout "layout_popup"}
|
||||
<h3>添加自定义页面</h3>
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="exceptURLPatternsJSON" :value="JSON.stringify(exceptURLPatterns)"/>
|
||||
<input type="hidden" name="onlyURLPatternsJSON" :value="JSON.stringify(onlyURLPatterns)"/>
|
||||
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">响应状态码 *</td>
|
||||
<td>
|
||||
<input type="text" name="status" size="3" placeholder="状态码" maxlength="3" style="width:5.2em" ref="focus"/>
|
||||
<p class="comment">匹配的响应状态码,比如404,或者50x。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>内容类型 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="bodyType" v-model="bodyType">
|
||||
<option v-for="bodyType in bodyTypes" :value="bodyType.code">{{bodyType.name}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="bodyType == 'html'">
|
||||
<td>显示页面HTML *</td>
|
||||
<td>
|
||||
<textarea name="body" ref="htmlBody"></textarea>
|
||||
<p class="comment"><a href="" @click.prevent="addHTMLTemplate">[使用模板]</a>。填写页面的HTML内容,支持请求变量。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="bodyType == 'url'">
|
||||
<td>显示页面URL *</td>
|
||||
<td>
|
||||
<input type="text" name="url" maxlength="500" placeholder="类似于 https://example.com/page.html"/>
|
||||
<p class="comment">将从此URL中读取内容。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="bodyType == 'redirectURL'">
|
||||
<td>跳转到URL *</td>
|
||||
<td>
|
||||
<input type="text" name="url" maxlength="500" placeholder="类似于 https://example.com/page.html"/>
|
||||
<p class="comment">将会跳转到此URL,支持使用变量。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>例外URL <tip-icon content="对这些URL将不做任何限制。"></tip-icon></td>
|
||||
<td><url-patterns-box v-model="exceptURLPatterns"></url-patterns-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>限制URL <tip-icon content="只对这些URL做限制。"></tip-icon></td>
|
||||
<td><url-patterns-box v-model="onlyURLPatterns"></url-patterns-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>新状态码</td>
|
||||
<td>
|
||||
<input type="text" name="newStatus" size="3" placeholder="状态码" maxlength="3" style="width:5.2em"/>
|
||||
<p class="comment">可以用来修改响应的状态码,不填表示不改变原有状态码。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,29 @@
|
||||
Tea.context(function () {
|
||||
this.bodyType = this.bodyTypes[0].code
|
||||
|
||||
this.addHTMLTemplate = function () {
|
||||
this.$refs.htmlBody.value = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
\t<title>\${status} \${statusMessage}</title>
|
||||
\t<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
\t<style>
|
||||
\t\taddress { line-height: 1.8; }
|
||||
\t</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>\${status} \${statusMessage}</h1>
|
||||
<p><!-- 内容 --></p>
|
||||
|
||||
<address>Connection: \${remoteAddr} (Client) -> \${serverAddr} (Server)</address>
|
||||
<address>Request ID: \${requestId}</address>
|
||||
|
||||
</body>
|
||||
</html>`
|
||||
}
|
||||
|
||||
|
||||
this.exceptURLPatterns = []
|
||||
this.onlyURLPatterns = []
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<http-pages-and-shutdown-box :v-pages="pages" :v-shutdown-config="shutdownConfig" :v-enable-global-pages="enableGlobalPages"></http-pages-and-shutdown-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,66 @@
|
||||
{$layout "layout_popup"}
|
||||
<h3>修改自定义页面</h3>
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="pageId" :value="pageConfig.id"/>
|
||||
<input type="hidden" name="exceptURLPatternsJSON" :value="JSON.stringify(pageConfig.exceptURLPatterns)"/>
|
||||
<input type="hidden" name="onlyURLPatternsJSON" :value="JSON.stringify(pageConfig.onlyURLPatterns)"/>
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">响应状态码 *</td>
|
||||
<td>
|
||||
<input type="text" name="status" size="3" placeholder="状态码" maxlength="3" style="width:5.2em" ref="focus" v-model="pageConfig.status"/>
|
||||
<p class="comment">匹配的响应状态码,比如404,或者50x。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>内容类型 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="bodyType" v-model="bodyType">
|
||||
<option v-for="bodyType in bodyTypes" :value="bodyType.code">{{bodyType.name}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="bodyType == 'html'">
|
||||
<td>显示页面HTML *</td>
|
||||
<td>
|
||||
<textarea name="body" ref="htmlBody" v-model="pageConfig.body"></textarea>
|
||||
<p class="comment"><a href="" @click.prevent="addHTMLTemplate">[使用模板]</a>。填写页面的HTML内容,支持请求变量。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="bodyType == 'url'">
|
||||
<td>显示页面URL *</td>
|
||||
<td>
|
||||
<input type="text" name="url" maxlength="500" placeholder="类似于 https://example.com/page.html" v-model="pageConfig.url"/>
|
||||
<p class="comment">将从此URL中读取内容。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="bodyType == 'redirectURL'">
|
||||
<td>跳转到URL *</td>
|
||||
<td>
|
||||
<input type="text" name="url" maxlength="500" placeholder="类似于 https://example.com/page.html" v-model="pageConfig.url"/>
|
||||
<p class="comment">将会跳转到此URL,支持使用变量。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>例外URL <tip-icon content="对这些URL将不做任何限制。"></tip-icon></td>
|
||||
<td><url-patterns-box v-model="pageConfig.exceptURLPatterns"></url-patterns-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>限制URL <tip-icon content="只对这些URL做限制。"></tip-icon></td>
|
||||
<td><url-patterns-box v-model="pageConfig.onlyURLPatterns"></url-patterns-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>新状态码</td>
|
||||
<td>
|
||||
<input type="text" name="newStatus" size="3" placeholder="状态码" maxlength="3" style="width:5.2em" v-model="newStatus"/>
|
||||
<p class="comment">可以用来修改响应的状态码,不填表示不改变原有状态码。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,32 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyPopup
|
||||
|
||||
this.bodyType = this.pageConfig.bodyType
|
||||
|
||||
this.newStatus = ""
|
||||
if (this.pageConfig.newStatus > 0) {
|
||||
this.newStatus = this.pageConfig.newStatus
|
||||
}
|
||||
|
||||
this.addHTMLTemplate = function () {
|
||||
this.$refs.htmlBody.value = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
\t<title>\${status} \${statusMessage}</title>
|
||||
\t<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
\t<style>
|
||||
\t\taddress { line-height: 1.8; }
|
||||
\t</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>\${status} \${statusMessage}</h1>
|
||||
<p><!-- 内容 --></p>
|
||||
|
||||
<address>Connection: \${remoteAddr} (Client) -> \${serverAddr} (Server)</address>
|
||||
<address>Request ID: \${requestId}</address>
|
||||
|
||||
</body>
|
||||
</html>`
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,76 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<form class="ui form" data-tea-success="success" data-tea-action="$">
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">当前绑定套餐</td>
|
||||
<td>
|
||||
<span v-if="userPlan.id == 0" class="disabled">暂时还没有绑定套餐。
|
||||
<a href="" @click.prevent="update()" v-if="!isUpdating">[修改]</a>
|
||||
<a href="" @click.prevent="update()" v-if="isUpdating">[取消修改]</a>
|
||||
</span>
|
||||
<div v-else>
|
||||
{{userPlan.plan.name}}<span v-if="userPlan.name.length > 0">-{{userPlan.name}}</span> (到期时间:{{userPlan.dayTo}})
|
||||
<a href="" @click.prevent="update()" v-if="!isUpdating">[修改]</a>
|
||||
<a href="" @click.prevent="update()" v-if="isUpdating">[取消修改]</a>
|
||||
<p class="comment" v-if="userPlan.isExpired"><a href="/plans"><span class="red">[已过期,请及时续费]</span></a></p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 注意:必须使用v-if -->
|
||||
<tr v-if="isUpdating">
|
||||
<td>新套餐 *</td>
|
||||
<td>
|
||||
<input type="hidden" name="isChanged" value="1"/>
|
||||
<span v-if="userPlans.length == 0" class="disabled">当前还没有可以使用的套餐。</span>
|
||||
<div v-else>
|
||||
<select class="ui dropdown auto-width" name="userPlanId" v-model="newUserPlanId" @change="changeUserPlan">
|
||||
<option value="0">[不使用套餐]</option>
|
||||
<option v-for="userPlan in userPlans" :value="userPlan.id">{{userPlan.name}}({{userPlan.dayTo}})</option>
|
||||
</select>
|
||||
<p class="comment" v-if="newUserPlanId > 0 && newUserPlanId == userPlan.id">当前正在使用的套餐。</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="isUpdating && newUserPlan != null">
|
||||
<td>所选套餐限制</td>
|
||||
<td>
|
||||
<div v-if="newUserPlan != null && newUserPlanDescription.length > 0">
|
||||
{{newUserPlanDescription}}
|
||||
</div>
|
||||
<div v-else><span class="disabled">没有限制</span></div>
|
||||
|
||||
<div v-if="newUserPlanLimit.length > 0 && newUserPlanId != userPlan.id">
|
||||
<span class="red">{{newUserPlanLimit}}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tbody v-if="!isUpdating && hasTrafficLimit">
|
||||
<tr v-if="userPlan.plan.trafficLimit.dailySize != null && userPlan.plan.trafficLimit.dailySize.count > 0">
|
||||
<td>套餐日流量限制</td>
|
||||
<td>
|
||||
<size-capacity-view :v-value="userPlan.plan.trafficLimit.dailySize"></size-capacity-view>
|
||||
<p class="comment">当天流量:{{trafficDailyFormat}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="userPlan.plan.trafficLimit.monthlySize != null && userPlan.plan.trafficLimit.monthlySize.count > 0">
|
||||
<td>套餐月流量限制</td>
|
||||
<td>
|
||||
<size-capacity-view :v-value="userPlan.plan.trafficLimit.monthlySize"></size-capacity-view>
|
||||
<p class="comment">当月流量:{{trafficMonthlyFormat}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<submit-btn v-show="newUserPlanLimit.length == 0 && newUserPlanId != userPlan.id"></submit-btn>
|
||||
<button class="ui button disabled" type="button" v-if="newUserPlanLimit.length > 0 || newUserPlanId == userPlan.id">保存</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,69 @@
|
||||
Tea.context(function () {
|
||||
this.isUpdating = false
|
||||
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
|
||||
this.update = function () {
|
||||
this.isUpdating = !this.isUpdating
|
||||
}
|
||||
|
||||
this.newUserPlanId = 0
|
||||
this.newUserPlan = null
|
||||
this.newUserPlanDescription = ""
|
||||
this.newUserPlanLimit = ""
|
||||
|
||||
let changePlanRequestId = ""
|
||||
|
||||
this.changeUserPlan = function () {
|
||||
this.newUserPlan = null
|
||||
this.newUserPlanDescription = ""
|
||||
this.newUserPlanLimit = ""
|
||||
if (this.newUserPlanId == 0) {
|
||||
return
|
||||
}
|
||||
let that = this
|
||||
this.newUserPlan = this.userPlans.find(function (v) {
|
||||
return v.id == that.newUserPlanId
|
||||
})
|
||||
if (this.newUserPlan != null) {
|
||||
changePlanRequestId = Math.random().toString()
|
||||
var requestId = changePlanRequestId
|
||||
|
||||
this.$post(".data")
|
||||
.params({
|
||||
serverId: this.serverId,
|
||||
userPlanId: this.newUserPlanId
|
||||
})
|
||||
.success(function (resp) {
|
||||
// check request
|
||||
if (requestId != changePlanRequestId) {
|
||||
return
|
||||
}
|
||||
|
||||
let quotaInfo = resp.data
|
||||
let descriptionItems = []
|
||||
if (quotaInfo.servers.max > 0) {
|
||||
descriptionItems.push("网站数限制:" + quotaInfo.servers.current + "+1/" + quotaInfo.servers.max)
|
||||
if (!quotaInfo.servers.isValid) {
|
||||
this.newUserPlanLimit = "已绑定网站数超出当前套餐限制"
|
||||
}
|
||||
}
|
||||
if (quotaInfo.allServerNames.max > 0) {
|
||||
descriptionItems.push("域名数限制:" + quotaInfo.allServerNames.current + "+" + quotaInfo.serverNames.current + "/" + quotaInfo.allServerNames.max)
|
||||
if (!quotaInfo.allServerNames.isValid) {
|
||||
this.newUserPlanLimit = "已绑定域名数超出当前套餐限制"
|
||||
}
|
||||
}
|
||||
if (quotaInfo.serverNames.max > 0) {
|
||||
descriptionItems.push("单网站域名数限制:+" + quotaInfo.serverNames.current + "/" + quotaInfo.serverNames.max)
|
||||
if (!quotaInfo.serverNames.isValid) {
|
||||
this.newUserPlanLimit = "当前网站域名数超出当前套餐限制"
|
||||
}
|
||||
}
|
||||
if (descriptionItems.length > 0) {
|
||||
this.newUserPlanDescription = descriptionItems.join(";") + "。"
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,187 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3 v-if="isCreating">添加URL跳转</h3>
|
||||
<h3 v-if="!isCreating">修改URL跳转</h3>
|
||||
|
||||
{$if .featureIsOn}
|
||||
<form class="ui form" data-tea-success="success" data-tea-action="$">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="matchPrefix" :value="redirect.matchPrefix ? 1 : 0"/>
|
||||
<input type="hidden" name="matchRegexp" :value="redirect.matchRegexp ? 1 : 0"/>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">跳转类型</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="type" v-model="redirect.type">
|
||||
<option value="url">URL跳转</option>
|
||||
<option value="domain">域名跳转</option>
|
||||
<option value="port">端口跳转</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- URL跳转 -->
|
||||
<tbody v-show="redirect.type == 'url'">
|
||||
<tr>
|
||||
<td class="color-border">跳转前URL *</td>
|
||||
<td>
|
||||
<input type="text" name="beforeURL" placeholder="比如 http://www.url1.com" v-model="redirect.beforeURL" ref="focus"/>
|
||||
<p class="comment">需要填写完整的URL,包括<code-label>http://</code-label>或者<code-label>https://</code-label>,如果有非默认端口,也需要带上端口号。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">匹配模式 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="mode" v-model="mode">
|
||||
<option value="equal">精准匹配</option>
|
||||
<option value="matchPrefix">匹配前缀</option>
|
||||
<option value="matchRegexp">正则匹配</option>
|
||||
</select>
|
||||
<p class="comment" v-if="mode == 'equal'">精准匹配跳转前的URL,即只有访问完全一样的URL才会跳转。</p>
|
||||
<p class="comment" v-if="mode == 'matchPrefix'">只要访问的URL头部部分包含跳转前URL,即可跳转。</p>
|
||||
<p class="comment" v-if="mode == 'matchRegexp'">可以在跳转前URL中使用正则表达式,然后可以在跳转后URL中使用正则表达式中括号的变量,比如<code-label>${1}</code-label>、<code-label>${2}</code-label>分别表示第一个和第二个括号内的变量值。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">跳转后URL *</td>
|
||||
<td>
|
||||
<input type="text" name="afterURL" placeholder="比如 https://www.url2.cn" v-model="redirect.afterURL"/>
|
||||
<p class="comment">需要填写完整的URL,包括<code-label>http://</code-label>或者<code-label>https://</code-label>,如果有非默认端口,也需要带上端口号。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="mode == 'matchPrefix'">
|
||||
<td class="color-border">是否保留URL路径参数</td>
|
||||
<td>
|
||||
<checkbox name="keepRequestURI" value="1" v-model="redirect.keepRequestURI"></checkbox>
|
||||
<p class="comment">选中后,则跳转之后,保留跳转之前的URL路径和参数。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="mode == 'equal' || mode == 'matchRegexp'">
|
||||
<td class="color-border">是否保留请求参数</td>
|
||||
<td>
|
||||
<checkbox name="keepArgs" value="1" v-model="redirect.keepArgs"></checkbox>
|
||||
<p class="comment">选中后,则跳转之后,保留跳转之前的URL上的参数(即问号之后的部分)。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 域名跳转 -->
|
||||
<tbody v-show="redirect.type == 'domain'">
|
||||
<tr>
|
||||
<td class="color-border">所有域名都跳转</td>
|
||||
<td>
|
||||
<checkbox name="domainsAll" v-model="redirect.domainsAll"></checkbox>
|
||||
<p class="comment">选中后,表示所有域名都会跳转(只要跳转前后域名不同);不选中后可以指定域名跳转。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="!redirect.domainsAll">
|
||||
<td class="color-border">指定跳转前域名</td>
|
||||
<td>
|
||||
<domains-box name="domainsBeforeJSON" :v-domains="redirect.domainsBefore"></domains-box>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">忽略跳转前端口</td>
|
||||
<td>
|
||||
<checkbox name="domainBeforeIgnorePorts" v-model="redirect.domainBeforeIgnorePorts"></checkbox>
|
||||
<p class="comment">选中后,表示忽略跳转前域名端口,只要域名匹配时就跳转;如不选中,则表示只有域名和端口同时匹配时才会跳转。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">跳转后域名 *</td>
|
||||
<td>
|
||||
<input type="text" name="domainAfter" maxlength="100" v-model="redirect.domainAfter" placeholder="比如example.com"/>
|
||||
<p class="comment">这里填写的是网址中的域名部分,不需要添加<code-label>https://</code-label>部分。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">跳转后协议</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="domainAfterScheme" v-model="redirect.domainAfterScheme">
|
||||
<option value="">保持</option>
|
||||
<option value="https">HTTPS</option>
|
||||
<option value="http">HTTP</option>
|
||||
</select>
|
||||
<p class="comment">跳转后的URL的协议。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 端口跳转 -->
|
||||
<tbody v-show="redirect.type == 'port'">
|
||||
<tr>
|
||||
<td class="color-border">所有端口都跳转</td>
|
||||
<td>
|
||||
<checkbox name="portsAll" v-model="redirect.portsAll"></checkbox>
|
||||
<p class="comment">选中后,表示所有端口都会跳转(只要跳转前后端口不同);不选中后可以指定端口跳转。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="!redirect.portsAll">
|
||||
<td class="color-border">指定跳转前端口</td>
|
||||
<td>
|
||||
<values-box placeholder="单个端口 或 端口1-端口2" name="portsBefore" :v-values="redirect.portsBefore"></values-box>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">跳转后端口 *</td>
|
||||
<td>
|
||||
<input type="text" name="portAfter" maxlength="5" v-model="redirect.portAfter" style="width: 5em"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">跳转后协议</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="portAfterScheme" v-model="redirect.portAfterScheme">
|
||||
<option value="">保持</option>
|
||||
<option value="https">HTTPS</option>
|
||||
<option value="http">HTTP</option>
|
||||
</select>
|
||||
<p class="comment">跳转后的URL的协议。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tr>
|
||||
<td>跳转状态码</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="status" v-model="redirect.status">
|
||||
<option value="0">[默认]</option>
|
||||
<option v-for="status in statusList" :value="status.code">{{status.code}} - {{status.text}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>例外域名</td>
|
||||
<td>
|
||||
<domains-box name="exceptDomainsJSON" :v-domains="redirect.exceptDomains"></domains-box>
|
||||
<p class="comment">这些域名<strong>不</strong>执行跳转。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>仅限域名</td>
|
||||
<td>
|
||||
<domains-box name="onlyDomainsJSON" :v-domains="redirect.onlyDomains"></domains-box>
|
||||
<p class="comment">只有这些域名执行跳转。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>匹配条件</td>
|
||||
<td><http-request-conds-box :v-conds="redirect.conds" @change="changeConds"></http-request-conds-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>启用当前跳转</td>
|
||||
<td><checkbox name="isOn" value="1" v-model="redirect.isOn"></checkbox></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
@@ -0,0 +1,63 @@
|
||||
Tea.context(function () {
|
||||
this.isCreating = true
|
||||
if (window.parent.UPDATING_REDIRECT != null) {
|
||||
this.isCreating = false
|
||||
this.redirect = window.parent.UPDATING_REDIRECT
|
||||
if (this.redirect.type == null || this.redirect.type.length == 0) {
|
||||
this.redirect.type = "url"
|
||||
}
|
||||
} else {
|
||||
this.redirect = {
|
||||
type: "url",
|
||||
status: 0,
|
||||
beforeURL: "",
|
||||
afterURL: "",
|
||||
matchPrefix: false,
|
||||
matchRegexp: false,
|
||||
keepRequestURI: false,
|
||||
keepArgs: true,
|
||||
conds: null,
|
||||
isOn: true,
|
||||
|
||||
domainsAll: false,
|
||||
domainBefore: [],
|
||||
domainBeforeIgnorePorts: true,
|
||||
domainAfter: "",
|
||||
domainAfterScheme: "",
|
||||
|
||||
portsAll: false,
|
||||
portsBefore: [],
|
||||
portAfter: 0,
|
||||
portAfterScheme: ""
|
||||
}
|
||||
}
|
||||
|
||||
this.mode = ""
|
||||
if (this.redirect.matchPrefix) {
|
||||
this.mode = "matchPrefix"
|
||||
} else if (this.redirect.matchRegexp) {
|
||||
this.mode = "matchRegexp"
|
||||
} else {
|
||||
this.mode = "equal"
|
||||
}
|
||||
|
||||
this.$delay(function () {
|
||||
let that = this
|
||||
this.$watch("mode", function (v) {
|
||||
if (v == "matchPrefix") {
|
||||
that.redirect.matchPrefix = true
|
||||
that.redirect.matchRegexp = false
|
||||
} else if (v == "matchRegexp") {
|
||||
that.redirect.matchPrefix = false
|
||||
that.redirect.matchRegexp = true
|
||||
} else {
|
||||
that.redirect.matchPrefix = false
|
||||
that.redirect.matchRegexp = false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
this.changeConds = function (conds) {
|
||||
this.redirect.conds = conds
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<form class="ui form" method="post" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<http-host-redirect-box :v-redirects="redirects" @change="change"></http-host-redirect-box>
|
||||
</form>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
Tea.context(function () {
|
||||
this.change = function (values) {
|
||||
this.$post("$")
|
||||
.params({
|
||||
webId: this.webId,
|
||||
hostRedirectsJSON: JSON.stringify(values)
|
||||
})
|
||||
.success(function () {
|
||||
teaweb.successToast("保存成功", null, function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,18 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
|
||||
<http-referers-config-box :v-referers-config="referersConfig"></http-referers-config-box>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
<div v-if="hasGroupConfig">
|
||||
<div class="margin"></div>
|
||||
<warning-message>由于已经在当前<a :href="groupSettingURL">网站分组</a>中进行了对应的配置,在这里的配置将不会生效。</warning-message>
|
||||
</div>
|
||||
|
||||
<div :class="{'opacity-mask': hasGroupConfig}">
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
|
||||
<http-remote-addr-config-box :v-remote-addr-config="remoteAddrConfig"></http-remote-addr-config-box>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<div v-if="hasGroupConfig">
|
||||
<div class="margin"></div>
|
||||
<warning-message>由于已经在当前<a :href="groupSettingURL">网站分组</a>中进行了对应的配置,在这里的配置将不会生效。</warning-message>
|
||||
</div>
|
||||
<div :class="{'opacity-mask': hasGroupConfig}">
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<http-request-limit-config-box :v-request-limit-config="requestLimitConfig"></http-request-limit-config-box>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
{$template "/code_editor"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$if .featureIsOn}
|
||||
<div v-if="hasGroupConfig">
|
||||
<div class="margin"></div>
|
||||
<warning-message>由于已经在当前<a :href="groupSettingURL">网站分组</a>中进行了对应的配置,在这里的配置将不会生效。</warning-message>
|
||||
</div>
|
||||
<div :class="{'opacity-mask': hasGroupConfig}">
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<http-request-scripts-config-box :v-request-scripts-config="requestScriptsConfig" :v-auditing-status="auditingStatus"></http-request-scripts-config-box>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
<first-menu>
|
||||
<menu-item :href="'/servers/server/settings/reverseProxy?serverId=' + serverId" code="index">源站列表</menu-item>
|
||||
<menu-item :href="'/servers/server/settings/reverseProxy/scheduling?serverId=' + serverId" code="scheduling">调度算法</menu-item>
|
||||
<menu-item :href="'/servers/server/settings/reverseProxy/setting?serverId=' + serverId" code="setting">更多设置</menu-item>
|
||||
</first-menu>
|
||||
@@ -0,0 +1,16 @@
|
||||
{$layout}
|
||||
{$template "../settings_menu"}
|
||||
{$template "/left_menu_with_menu"}
|
||||
|
||||
<div class="right-box with-menu">
|
||||
{$template "menu"}
|
||||
|
||||
<div v-if="!reverseProxyRef.isOn">
|
||||
<div class="margin"></div>
|
||||
<p class="ui message warning">当前CDN服务没有开启,可以通过点击 <a :href="'/servers/server/settings/reverseProxy/setting?serverId=' + serverId">[更多设置]</a> 开启 。</p>
|
||||
</div>
|
||||
|
||||
<origin-list-box :v-primary-origins="primaryOrigins" :v-backup-origins="backupOrigins"
|
||||
:v-server-type="serverType"
|
||||
:v-params="'type=server&serverId=' + serverId + '&reverseProxyId=' + reverseProxyConfig.id"></origin-list-box>
|
||||
</div>
|
||||
@@ -0,0 +1,8 @@
|
||||
{$layout}
|
||||
{$template "/left_menu"}
|
||||
|
||||
<div class="right-box">
|
||||
{$template "menu"}
|
||||
|
||||
<origin-scheduling-view-box :v-scheduling="scheduling" :v-params="'type=server&serverId=' + serverId + '&reverseProxyId=' + reverseProxyId"></origin-scheduling-view-box>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
{$layout}
|
||||
{$template "/left_menu"}
|
||||
|
||||
<div class="right-box">
|
||||
{$template "menu"}
|
||||
|
||||
<div class="margin"></div>
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<input type="hidden" name="reverseProxyRefJSON" :value="JSON.stringify(reverseProxyRef)"/>
|
||||
<reverse-proxy-box :v-reverse-proxy-ref="reverseProxyRef" :v-reverse-proxy-config="reverseProxyConfig" :v-family="serverFamily"></reverse-proxy-box>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -0,0 +1,60 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>修改调度算法</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="dataType" :value="dataType"/>
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<input type="hidden" name="reverseProxyId" :value="reverseProxyId"/>
|
||||
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">选择调度算法</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="type" v-model="selectedType"
|
||||
@change="changeSchedulingType()">
|
||||
<option v-for="schedulingType in schedulingTypes"
|
||||
:value="schedulingType.code">{{schedulingType.name}}</option>
|
||||
</select>
|
||||
<p class="comment">{{schedulingTypeDescription}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="selectedType == 'hash'">
|
||||
<td>
|
||||
Key
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="hashKey" v-model="hashKey" maxlength="500"/>
|
||||
<p class="comment">用来计算Hash的字符串,其中可以使用变量。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="selectedType == 'hash'">
|
||||
<td>常用变量</td>
|
||||
<td>
|
||||
<select class="ui dropdown" style="width:12em" v-model="hashVar" @change="changeHashVar()">
|
||||
<option></option>
|
||||
<option value="${remoteAddr}">客户端IP</option>
|
||||
<option value="${host}${requestURI}">请求URL</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="selectedType == 'sticky'">
|
||||
<td>参数类型</td>
|
||||
<td>
|
||||
<select class="ui dropdown" style="width:12em" name="stickyType" v-model="stickyType">
|
||||
<option value="cookie">Cookie</option>
|
||||
<option value="header">HTTP Header</option>
|
||||
<option value="argument">URL参数</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="selectedType == 'sticky'">
|
||||
<td>参数名</td>
|
||||
<td>
|
||||
<input type="text" name="stickyParam" v-model="stickyParam" maxlength="50"/>
|
||||
<p class="comment">记录或指定源站的参数名,只能是英文字母和数字的组合,不允许有下划线(因为在HTTP Header中下划线是不标准的)</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
@@ -0,0 +1,39 @@
|
||||
Tea.context(function () {
|
||||
var that = this;
|
||||
|
||||
this.success = NotifyPopup
|
||||
|
||||
this.selectedType = this.scheduling.code;
|
||||
this.schedulingTypeDescription = null;
|
||||
|
||||
this.changeSchedulingType = function () {
|
||||
this.schedulingTypeDescription = this.schedulingTypes.$find(function (k, v) {
|
||||
return v.code == that.selectedType;
|
||||
}).description;
|
||||
};
|
||||
this.changeSchedulingType();
|
||||
|
||||
// hash
|
||||
this.hashKey = "";
|
||||
this.hashVar = "";
|
||||
if (this.scheduling.code == "hash") {
|
||||
this.hashKey = this.scheduling.options.key;
|
||||
} else {
|
||||
this.hashKey = "${remoteAddr}";
|
||||
}
|
||||
|
||||
this.changeHashVar = function () {
|
||||
if (this.hashVar.length > 0) {
|
||||
this.hashKey = this.hashVar;
|
||||
}
|
||||
};
|
||||
|
||||
// sticky
|
||||
if (this.scheduling.code == "sticky") {
|
||||
this.stickyType = this.scheduling.options.type;
|
||||
this.stickyParam = this.scheduling.options.param;
|
||||
} else {
|
||||
this.stickyType = "cookie";
|
||||
this.stickyParam = "Origin";
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>创建重写规则</h3>
|
||||
{$if .featureIsOn}
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="webId" :value="webId"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">匹配规则 *</td>
|
||||
<td>
|
||||
<input type="text" name="pattern" maxlength="500" placeholder="比如 /post/(.+)" ref="focus"/>
|
||||
<p class="comment">需要符合正则表达式规范,<a href="https://goedge.cn/docs/Appendix/Regexp/Index.md" target="_blank">正则表达式语法 »</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>目标URL *</td>
|
||||
<td>
|
||||
<input type="text" name="replace" placeholder="比如 /post/${1}.html" maxlength="500"/>
|
||||
<p class="comment">URL中可以包含一些<a href="https://goedge.cn/docs/Server/Variables.md" target="_blank">内置的变量</a>,并且可以用<code-label>${1}</code-label>、<code-label>${2}</code-label>等变量形式表示在匹配规则中匹配的第N个括号里的内容,也可以是一个完整的URL,比如:http://example.com/hello。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>转发方式</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="mode" v-model="rewriteRule.mode">
|
||||
<option value="proxy">隐式</option>
|
||||
<option value="redirect">显式</option>
|
||||
</select>
|
||||
<p class="comment">隐式表示不在客户端显示重写后的URL;显式表示在客户端跳转URL,将会显示重写后的URL。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>匹配条件</td>
|
||||
<td><http-request-conds-box></http-request-conds-box></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr v-show="rewriteRule.mode == 'redirect'">
|
||||
<td>跳转状态码</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="redirectStatus" v-model="rewriteRule.redirectStatus">
|
||||
<option v-for="status in statusOptions" :value="status.code">{{status.code}} {{status.text}}</option>
|
||||
</select>
|
||||
<p class="comment">通常使用默认的307即可。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="rewriteRule.mode == 'proxy'">
|
||||
<td>代理主机名</td>
|
||||
<td>
|
||||
<input type="text" name="proxyHost" placeholder="比如 example.com" maxlength="100"/>
|
||||
<p class="comment">如果转发的方式为隐式而且目标URL为不同的域名时需要用到此选项,用于修改被代理服务接收到的域名,默认和客户端请求的主机名一致,通常不必填写,支持<a href="https://goedge.cn/docs/Server/Variables.md" target="_blank">请求变量</a>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>是否保留URL参数</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="withQuery" value="1" checked="checked"/>
|
||||
<label></label>
|
||||
</div>
|
||||
<p class="comment">选中此选项,将会把用户输入的URL中的参数部分转发到目标URL上。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>是否终止往下匹配</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="isBreak" value="1"/>
|
||||
<label></label>
|
||||
</div>
|
||||
<p class="comment">如果选中了此选项,一旦匹配成功,不会继续匹配其他的重写规则或路由规则。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>启用当前重写规则</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="isOn" value="1" checked="checked"/>
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
{$else}
|
||||
<server-feature-required></server-feature-required>
|
||||
{$end}
|
||||
@@ -0,0 +1,15 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyPopup
|
||||
|
||||
this.rewriteRule = {
|
||||
mode: "proxy",
|
||||
redirectStatus: 307
|
||||
}
|
||||
this.statusOptions = [
|
||||
{"code": 301, "text": "Moved Permanently"},
|
||||
{"code": 308, "text": "Permanent Redirect"},
|
||||
{"code": 302, "text": "Found"},
|
||||
{"code": 303, "text": "See Other"},
|
||||
{"code": 307, "text": "Temporary Redirect"}
|
||||
]
|
||||
})
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user