Initial commit (code only without large binaries)

This commit is contained in:
robin
2026-02-15 18:58:44 +08:00
commit 35df75498f
9442 changed files with 1495866 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
<first-menu>
<menu-item href="/servers">网站列表</menu-item>
<span class="item disabled">|</span>
<menu-item :href="'/servers/server/settings?serverId=' + server.id" :active="leftMenuActiveItem == null">"{{server.name}}"设置</menu-item>
<span class="disabled item">&raquo;</span>
<a class="item active" v-if="leftMenuActiveItem != null" :href="leftMenuActiveItem.url">"{{leftMenuActiveItem.name}}"设置</a>
<span class="disabled item" v-if="leftMenuActiveItem != null">|</span>
<more-items-angle
:v-data-url="'/servers/nearby?serverId=' + server.id"
:v-url="'/servers/server/settings?serverId=${serverId}'"></more-items-angle>
<span class="disabled item" style="font-size: 0.8em" v-if="leftMenuActiveItem != null && leftMenuActiveItem.configCode != null && leftMenuActiveItem.configCode.length > 0 && teaIsPlus">|</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 && teaIsPlus"></server-config-copy-link>
</first-menu>

View File

@@ -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> &nbsp; &nbsp;
<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>

View File

@@ -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
})

View File

@@ -0,0 +1,11 @@
{$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" 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>
</div>

View File

@@ -0,0 +1,10 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
this.changeMethods = function (config) {
Tea.action("$")
.form(this.$refs.authForm)
.post()
teaweb.successRefresh("保存成功")
}
})

View File

@@ -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> &nbsp; &nbsp;
<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>

View File

@@ -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
})

View File

@@ -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 method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<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"></http-access-log-config-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,5 @@
<first-menu>
<menu-item :href="'.?serverId=' + serverId" code="index">设置</menu-item>
<menu-item :href="'.purge?serverId=' + serverId" code="purge">刷新</menu-item>
<menu-item :href="'.fetch?serverId=' + serverId" code="fetch">预热</menu-item>
</first-menu>

View File

@@ -0,0 +1,13 @@
{$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>
<p class="comment" v-if="isReverse">如果请求满足当前添加的条件,则不缓存。</p>
<submit-btn>确定</submit-btn>
</form>

View 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
}
})

View File

@@ -0,0 +1,41 @@
{$layout}
{$template "../settings_menu"}
{$template "/left_menu_with_menu"}
<div class="right-box with-menu">
{$template "menu"}
<div class="margin"></div>
<div v-show="webConfig.cache == null || !webConfig.cache.isOn">
<p class="comment">没有开启缓存,暂时无法预热缓存。</p>
</div>
<div v-show="webConfig.cache != null && webConfig.cache.isOn">
<p class="comment">可以在这里批量预热一组URL。</p>
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="3600">
<input type="hidden" name="serverId" :value="serverId"/>
<input type="hidden" name="webId" :value="webId"/>
<table class="ui table definition selectable">
<tr>
<td>URL列表</td>
<td>
<textarea name="keys" rows="10" ref="focus"></textarea>
<p class="comment">每行一个URL。</p>
</td>
</tr>
<tr>
<td class="title">操作结果</td>
<td>
<div v-if="isRequesting">数据发送中...</div>
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
<div v-for="failKey in failKeys">
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
</div>
</div>
</td>
</tr>
</table>
<submit-btn v-if="!isRequesting">提交</submit-btn>
</form>
</div>
</div>

View File

@@ -0,0 +1,32 @@
Tea.context(function () {
this.isRequesting = false
this.isOk = false
this.message = ""
this.failKeys = []
this.before = function () {
this.isRequesting = true
this.isOk = false
this.message = ""
this.failKeys = []
}
this.success = function (resp) {
this.isOk = true
let f = NotifyReloadSuccess("任务提交成功")
f()
}
this.fail = function (resp) {
this.message = resp.message
if (resp.data.failKeys != null) {
this.failKeys = resp.data.failKeys
}
}
this.done = function () {
this.isRequesting = false
}
});

View File

@@ -0,0 +1,21 @@
{$layout}
{$template "../settings_menu"}
{$template "/left_menu_with_menu"}
<div class="right-box with-menu">
{$template "menu"}
<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"/>
<http-cache-config-box :v-cache-config="cacheConfig" :v-cache-policy="cachePolicy" :v-web-id="webId"></http-cache-config-box>
<submit-btn></submit-btn>
<p class="comment">修改条件设置后请记得保存。</p>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,53 @@
{$layout}
{$template "../settings_menu"}
{$template "/left_menu_with_menu"}
<div class="right-box with-menu">
{$template "menu"}
<div class="margin"></div>
<div v-show="webConfig.cache == null || !webConfig.cache.isOn">
<p class="comment">没有开启缓存,不需要刷新。</p>
</div>
<div v-show="webConfig.cache != null && webConfig.cache.isOn">
<p class="comment">可以在这里批量刷新一组URL缓存。</p>
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="300">
<input type="hidden" name="serverId" :value="serverId"/>
<input type="hidden" name="webId" :value="webId"/>
<table class="ui table definition selectable">
<tr>
<td class="title">URL类型</td>
<td>
<radio name="keyType" :v-value="'key'" v-model="keyType">URL</radio> &nbsp;
<radio name="keyType" :v-value="'prefix'" v-model="keyType">目录</radio>
</td>
</tr>
<tr>
<td>
<span v-if="keyType == 'key'">URL</span>
<span v-if="keyType == 'prefix'">目录</span>
</td>
<td>
<textarea name="keys" rows="10" ref="keysBox"></textarea>
<p class="comment" v-if="keyType == 'key'">每行一个URL比如<code-label>https://example.com/hello/world.html</code-label></p>
<p class="comment" v-if="keyType == 'prefix'">每行一个URL目录比如<code-label>https://example.com/hello/</code-label>;如果只填写域名部分,表示清理全站,比如<code-label>https://example.com/</code-label></p>
</td>
</tr>
<tr>
<td>操作结果</td>
<td>
<div v-if="isRequesting">数据发送中...</div>
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
<div v-for="failKey in failKeys">
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
</div>
</div>
</td>
</tr>
</table>
<submit-btn v-if="!isRequesting">提交</submit-btn>
</form>
</div>
</div>

View File

@@ -0,0 +1,43 @@
Tea.context(function () {
this.isRequesting = false
this.isOk = false
this.message = ""
this.failKeys = []
this.$delay(function () {
this.$refs.keysBox.focus()
this.$watch("keyType", function () {
this.$refs.keysBox.focus()
})
})
this.before = function () {
this.isRequesting = true
this.isOk = false
this.message = ""
this.failKeys = []
}
this.success = function () {
this.isOk = true
let f = NotifyReloadSuccess("任务提交成功")
f()
}
this.fail = function (resp) {
this.message = resp.message
if (resp.data.failKeys != null) {
this.failKeys = resp.data.failKeys
}
}
this.done = function () {
this.isRequesting = false
}
/**
* 操作类型
*/
this.keyType = "key" // key | prefix
})

View File

@@ -0,0 +1,14 @@
{$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"/>
<csrf-token></csrf-token>
<http-cc-config-box :v-cc-config="ccConfig"></http-cc-config-box>
<submit-btn></submit-btn>
</form>
</div>

View File

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

View File

@@ -0,0 +1,18 @@
{$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 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>
</div>

View File

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

View File

@@ -0,0 +1,16 @@
{$layout}
{$template "../settings_menu"}
{$template "/left_menu_with_menu"}
<div class="right-box with-menu">
<div class="margin"></div>
<div :class="{'opacity-mask': hasGroupConfig}">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="webId" :value="webId"/>
<http-common-config-box :v-common-config="commonConfig"></http-common-config-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -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>

View File

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

View File

@@ -0,0 +1,20 @@
{$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-compression-config-box :v-compression-config="compressionConfig"></http-compression-config-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -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>

View File

@@ -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)
}
}
})

View File

@@ -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> &nbsp;
<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}} &nbsp;</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>

View File

@@ -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)
}
})
}
})

View File

@@ -0,0 +1,5 @@
.checkboxes .checkbox {
width: 8em;
margin-bottom: 0.5em;
}
/*# sourceMappingURL=index.css.map */

View File

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

View File

@@ -0,0 +1,107 @@
{$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>
<tr>
<td>管理员创建的分组</td>
<td>
<div class="checkboxes">
<checkbox v-for="adminGroup in adminGroups" :v-value="adminGroup.id" @input="changeGroupId(adminGroup.id)">{{adminGroup.name}}</checkbox>
</div>
</td>
</tr>
</tbody>
<!-- 选择用户 -->
<tbody v-show="targetType == 'user'">
<tr>
<td>选择用户</td>
<td>
<user-selector @change="changeUser"></user-selector>
</td>
</tr>
</tbody>
<!-- 选择集群 -->
<tbody v-show="targetType == 'cluster'">
<tr>
<td>选择集群</td>
<td>
<node-cluster-combo-box @change="changeCluster"></node-cluster-combo-box>
</td>
</tr>
</tbody>
<!-- 选择网站 -->
<tbody v-show="targetType == 'server'">
<tr>
<td>当前用户下网站</td>
<td></td>
</tr>
<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>

View File

@@ -0,0 +1,71 @@
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|cluster):/)) {
this.targets = [this.targetType]
this.reloadCountServers()
}
}
this.changeUser = function (userId) {
if (typeof userId == "number" && userId > 0) {
this.targets = ["user:" + userId]
this.reloadCountServers()
} else {
this.targets = []
this.countServers = -1
}
}
this.changeCluster = function (clusterId) {
if (typeof clusterId == "number" && clusterId > 0) {
this.targets = ["cluster:" + clusterId]
this.reloadCountServers()
} else {
this.targets = []
this.countServers = -1
}
}
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
}
})

View File

@@ -0,0 +1,6 @@
.checkboxes {
.checkbox {
width: 8em;
margin-bottom: 0.5em;
}
}

View File

@@ -0,0 +1,28 @@
{$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">当前网站CNAME</td>
<td>
<span id="cname-text">{{dnsName}}.<span v-if="dnsDomain.length > 0">{{dnsDomain}}</span><span v-else>根域名</span></span> &nbsp; <copy-to-clipboard :v-target="'cname-text'"></copy-to-clipboard> &nbsp;<a href="" @click.prevent="regenerateCNAME()" style="font-size: 0.8em">[重新生成]</a> &nbsp; <a href="" @click.prevent="updateCNAME()" style="font-size: 0.8em">[手动修改]</a>
<p class="comment">你需要为你的每个<a :href="'/servers/server/settings/serverNames?serverId=' + serverId">网站域名</a>设置一个CNAME解析值为上面内容。</p>
<p v-if="dnsDomain.length == 0"><span class="red">你尚未为当前网站所在集群指定CNAME根域名可以在 <a :href="'/clusters/cluster/settings/dns?clusterId=' + server.clusterId" target="_blank">[这里]</a> 修改。</span></p>
</td>
</tr>
<tr>
<td>支持任意域名CNAME</td>
<td>
<checkbox name="supportCNAME" v-model="supportCNAME"></checkbox>
<p class="comment">选中后表示允许任意域名使用此服务的CNAME直接访问此服务。需要节点服务器可以正确解析DNS记录。在严格匹配域名时才会生效。此选项可能导致安全问题请谨慎开启。</p>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,22 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
this.regenerateCNAME = function () {
let serverId = this.serverId
teaweb.confirm("确定要重新生成此服务的CNAME吗", function () {
this.$post(".regenerateCNAME")
.params({
serverId: serverId
})
.refresh()
})
}
this.updateCNAME = function () {
teaweb.popup("/servers/server/settings/dns/updateCNAMEPopup?serverId=" + this.serverId, {
callback: function () {
teaweb.successRefresh("保存成功")
}
})
}
})

View File

@@ -0,0 +1,20 @@
{$layout "layout_popup"}
<h3>修改服务CNAME</h3>
<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 definition selectable">
<tr>
<td class="title">CNAME *</td>
<td>
<input type="text" name="dnsName" maxlength="30" v-model="dnsName"/>
<p class="comment">英文字母、数字的组合最长30个字符。</p>
</td>
</tr>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,78 @@
{$layout "layout_popup"}
<h3>添加Fastcgi服务</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="paramsJSON" :value="JSON.stringify(params)"/>
<table class="ui table definition selectable">
<tr>
<td class="title">Fastcgi地址</td>
<td>
<input type="text" name="address" placeholder="比如 127.0.0.1:9000" maxlength="100" style="width:14em" ref="focus"/>
</td>
</tr>
<tr>
<td>自定义参数集</td>
<td>
<div v-for="(param, index) in params">
<div class="ui field" style="margin:0" v-if="param.nameZh.length > 0"><label>{{param.nameZh}}</label></div>
<div class="ui fields inline" >
<div class="ui field">
<input type="text" name="paramNames" placeholder="参数名" v-model="param.name" style="width:12em" />
</div>
<div class="ui field">
<input type="text" name="paramValues" placeholder="参数值" v-model="param.value" style="width:16em"/>
</div>
<div class="ui field" style="padding:0">
<a href="" title="删除" @click.prevent="removeParam(index)"><i class="ui icon remove"></i> </a>
</div>
</div>
</div>
<p class="comment" v-if="params.length > 0">可以在参数值中使用一些变量<a href="https://goedge.cn/docs/Server/Variables.md" target="_blank">点这里查看</a></p>
<button class="ui button tiny" type="button" @click.prevent="addParam()">+</button>
</td>
</tr>
<tr>
<td colspan="2">
<more-options-indicator></more-options-indicator>
</td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>读取超时时间</td>
<td>
<div class="ui right labeled input" style="width:7em">
<input type="number" name="readTimeout" maxlength="10" placeholder="比如 30"/>
<span class="ui basic label"></span>
</div>
</td>
</tr>
<tr>
<td>连接池尺寸</td>
<td>
<input type="text" name="poolSize" value="0" maxlength="4" style="width:7em"/>
<p class="comment">0表示不限制通常可以设置为CPU数量的两倍</p>
</td>
</tr>
<tr>
<td>PATH_INFO匹配</td>
<td>
<input type="text" name="pathInfoPattern" maxlength="100"/>
<p class="comment">匹配PATH_INFO的正则表达式用括号表示匹配的内容如果只有一个匹配括号表示第一个括号为${fastcgi.pathInfo}值;如果有两个或两个以上的匹配括号,则第一个表示匹配的是${fastcgi.filename},第二个匹配的是${fastcgi.pathInfo},比如(\w+\.php)(.+)$。</p>
</td>
</tr>
<tr>
<td>启用当前Fastcgi</td>
<td>
<checkbox name="isOn" value="1" checked="checked"></checkbox>
</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,29 @@
Tea.context(function () {
this.params = [
{
"name": "DOCUMENT_ROOT",
"value": "",
"nameZh": "文档目录"
},
{
"name": "SCRIPT_FILENAME",
"value": "",
"nameZh": "脚本文件"
}
]
this.addParam = function () {
this.params.push({
"name": "",
"value": "",
"nameZh": ""
})
this.$delay(function () {
this.$find("form input[name='paramNames']").last().focus()
})
}
this.removeParam = function (index) {
this.params.$remove(index)
}
})

View 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-fastcgi-box :v-fastcgi-ref="fastcgiRef" :v-fastcgi-configs="fastcgiConfigs"></http-fastcgi-box>
<submit-btn></submit-btn>
</form>
</div>

View File

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

View File

@@ -0,0 +1,79 @@
{$layout "layout_popup"}
<h3>修改Fastcgi服务</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="fastcgiId" :value="fastcgi.id"/>
<input type="hidden" name="paramsJSON" :value="JSON.stringify(params)"/>
<table class="ui table definition selectable">
<tr>
<td class="title">Fastcgi地址</td>
<td>
<input type="text" name="address" placeholder="比如 127.0.0.1:9000" maxlength="100" style="width:14em" ref="focus" v-model="fastcgi.address"/>
</td>
</tr>
<tr>
<td>自定义参数集</td>
<td>
<div v-for="(param, index) in params">
<div class="ui field" style="margin:0" v-if="param.nameZh != null && param.nameZh.length > 0"><label>{{param.nameZh}}</label></div>
<div class="ui fields inline" >
<div class="ui field">
<input type="text" name="paramNames" placeholder="参数名" v-model="param.name" style="width:12em" />
</div>
<div class="ui field">
<input type="text" name="paramValues" placeholder="参数值" v-model="param.value" style="width:16em"/>
</div>
<div class="ui field" style="padding:0">
<a href="" title="删除" @click.prevent="removeParam(index)"><i class="ui icon remove"></i> </a>
</div>
</div>
</div>
<p class="comment" v-if="params.length > 0">可以在参数值中使用一些变量<a href="https://goedge.cn/docs/Server/Variables.md" target="_blank">点这里查看</a></p>
<button class="ui button tiny" type="button" @click.prevent="addParam()">+</button>
</td>
</tr>
<tr>
<td colspan="2">
<more-options-indicator></more-options-indicator>
</td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>读取超时时间</td>
<td>
<div class="ui right labeled input" style="width:7em">
<input type="number" name="readTimeout" maxlength="10" placeholder="比如 30" v-model="fastcgi.readTimeout.count"/>
<span class="ui basic label"></span>
</div>
</td>
</tr>
<tr>
<td>连接池尺寸</td>
<td>
<input type="text" name="poolSize" value="0" maxlength="4" style="width:7em" v-model="fastcgi.poolSize"/>
<p class="comment">0表示不限制通常可以设置为CPU数量的两倍</p>
</td>
</tr>
<tr>
<td>PATH_INFO匹配</td>
<td>
<input type="text" name="pathInfoPattern" maxlength="100" v-model="fastcgi.pathInfoPattern"/>
<p class="comment">匹配PATH_INFO的正则表达式用括号表示匹配的内容如果只有一个匹配括号表示第一个括号为${fastcgi.pathInfo}值;如果有两个或两个以上的匹配括号,则第一个表示匹配的是${fastcgi.filename},第二个匹配的是${fastcgi.pathInfo},比如(\w+\.php)(.+)$。</p>
</td>
</tr>
<tr>
<td>启用当前Fastcgi</td>
<td>
<checkbox name="isOn" value="1" v-model="fastcgi.isOn"></checkbox>
</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>
</form>

View File

@@ -0,0 +1,33 @@
Tea.context(function () {
this.params = this.fastcgi.params
if (this.params == null) {
this.params = []
} else {
this.params.forEach(function (v) {
switch (v.name) {
case "DOCUMENT_ROOT":
v.nameZh = "文档目录"
break;
case "SCRIPT_FILENAME":
v.nameZh = "脚本文件"
break
}
})
}
this.addParam = function () {
this.params.push({
"name": "",
"value": "",
"nameZh": ""
})
this.$delay(function () {
this.$find("form input[name='paramNames']").last().focus()
})
}
this.removeParam = function (index) {
this.params.$remove(index)
}
})

View File

@@ -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>

View File

@@ -0,0 +1,7 @@
Tea.context(function () {
this.headerName = ""
this.selectHeader = function (headerName) {
this.headerName = headerName
}
})

View File

@@ -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>

View File

@@ -0,0 +1,7 @@
Tea.context(function () {
this.headerName = ""
this.selectHeader = function (headerName) {
this.headerName = headerName
}
})

View File

@@ -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>

View File

@@ -0,0 +1,8 @@
Tea.context(function () {
this.shouldReplace = false
this.headerName = ""
this.selectHeader = function (headerName) {
this.headerName = headerName
}
})

View File

@@ -0,0 +1,14 @@
{$layout}
{$template "../settings_menu"}
{$template "/left_menu_with_menu"}
<div class="right-box with-menu">
<div class="margin"></div>
<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>
</div>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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
}
})

View File

@@ -0,0 +1,39 @@
{$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 class="title">绑定端口 *</td>
<td>
<span class="red" v-if="httpConfig.isOn && (httpConfig.addresses == null || httpConfig.addresses.length == 0)">还没有添加端口绑定会导致HTTP服务无法访问。</span>
<network-addresses-box :v-server-type="serverType" :v-addresses="httpConfig.addresses" :v-protocol="'http'"></network-addresses-box>
<p class="comment"><span v-if="conflictingPorts.length > 0" class="red">配置错误:<span v-for="(port, index) in conflictingPorts">{{port}}<span v-if="index != conflictingPorts.length - 1"></span></span><span v-if="conflictingPorts.length > 1"></span>端口同HTTPS设置的端口冲突请删除HTTP或HTTPS中的相关端口。</span></p>
</td>
</tr>
<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>

View File

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

View File

@@ -0,0 +1,48 @@
{$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 != null" 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>
<tbody v-show="httpsConfig.isOn">
<tr>
<td class="title">绑定端口 *</td>
<td>
<span class="red" v-if="httpsConfig.isOn && (httpsConfig.addresses == null || httpsConfig.addresses.length == 0)">还没有添加端口绑定会导致HTTPS服务无法访问。</span>
<network-addresses-box :v-server-type="serverType" :v-addresses="httpsConfig.addresses" :v-protocol="'https'"></network-addresses-box>
<p class="comment"><span v-if="conflictingPorts.length > 0" class="red">配置错误:<span v-for="(port, index) in conflictingPorts">{{port}}<span v-if="index != conflictingPorts.length - 1"></span></span><span v-if="conflictingPorts.length > 1"></span>端口同HTTP设置的端口冲突请删除HTTP或HTTPS中的相关端口。</span></p>
</td>
</tr>
</tbody>
</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"></ssl-config-box>
<submit-btn></submit-btn>
</form>
</div>

View File

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

View File

@@ -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>

View File

@@ -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
}
}
})

View File

@@ -0,0 +1,101 @@
{$layout}
{$template "settings_menu"}
{$template "/left_menu_with_menu"}
<div class="right-box with-menu">
<div v-if="server.trafficLimitStatus != null">
<div class="ui margin"></div>
<warning-message>
<server-traffic-limit-status-viewer v-model="server.trafficLimitStatus"></server-traffic-limit-status-viewer>
</warning-message>
</div>
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="serverId" :value="server.id"/>
<table class="ui table selectable definition">
<tr>
<td>所属用户</td>
<td>
<span v-if="user != null">{{user.fullname}} <span class="small">{{user.username}}</span><link-icon :href="'/users/user?userId=' + user.id"></link-icon></span>
<div v-if="user == null">
<div v-show="!userSelectorVisible">
<span class="disabled">没有指定用户</span> &nbsp; <a href="" @click.prevent="showUserSelector">[指定用户]</a>
</div>
<div v-show="userSelectorVisible">
<user-selector style="display:inline-block"></user-selector>
<p class="comment"><span class="red">此操作同时会将与当前网站相关联的证书等数据自动修改为此用户所属。</span></p>
</div>
</div>
</td>
</tr>
<tr>
<td class="title">网站名称 *</td>
<td>
<input type="text" name="name" maxlength="60" ref="focus" v-model="server.name"/>
</td>
</tr>
<tr v-if="plans.length > 0">
<td>选择套餐</td>
<td>
<select class="ui dropdown auto-width" name="userPlanId" v-model="userPlanId">
<option value="0">[选择套餐]</option>
<option v-for="plan in plans" :value="plan.id">{{plan.name}}{{plan.dayTo}}</option>
</select>
</td>
</tr>
<tr v-if="plans.length == 0 && teaIsPlus">
<td>选择套餐</td>
<td>当前网站所属用户没有可用套餐。</td>
</tr>
<tr>
<td :class="{'color-border':server.clusterId != oldClusterId}">部署的集群 *</td>
<td>
<select class="ui dropdown auto-width" name="clusterId" v-model="server.clusterId" >
<option v-for="cluster in clusters" :value="cluster.id">{{cluster.name}}</option>
</select>
</td>
</tr>
<tr v-show="server.clusterId != oldClusterId">
<td class="color-border">是否保留原集群配置</td>
<td>
<checkbox name="keepOldConfigs" checked="checked"></checkbox>
<p class="comment">选中表示在先前的集群节点上仍然保留当前网站的配置,直至节点配置全部刷新时才会删除;不选中,则表示立即删除原集群上关于当前网站的配置。</p>
</td>
</tr>
<tr>
<td>网站类型 *</td>
<td>
{{typeName}}
</td>
</tr>
<tr>
<td>选择分组</td>
<td>
<server-group-selector :v-groups="server.groups"></server-group-selector>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>描述</td>
<td>
<textarea name="description" rows="3" v-model="server.description"></textarea>
</td>
</tr>
<tr>
<td>启用当前网站</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="isOn" value="1" v-model="server.isOn"/>
<label></label>
</div>
<p class="comment">可以使用此选项整体关闭当前网站。</p>
</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,43 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
/**
* 用户相关
*/
this.userSelectorVisible = false
this.showUserSelector = function () {
this.userSelectorVisible = !this.userSelectorVisible
}
this.userId = 0
this.plans = []
this.userPlanId = 0
this.oldClusterId = this.server.clusterId
if (this.userPlan != null) {
this.userPlanId = this.userPlan.id
}
this.changeUserId = function (v) {
this.userId = v
if (this.userId == 0) {
this.plans = []
return
}
this.$post("/servers/users/plans")
.params({
userId: this.userId,
serverId: this.serverId
})
.success(function (resp) {
this.plans = resp.data.plans
})
}
if (this.user != null) {
this.changeUserId(this.user.id)
}
})

View File

@@ -0,0 +1,9 @@
<div class="margin"></div>
<div class="left-box tiny">
<div class="ui menu text blue vertical tiny">
<a class="item" v-for="item in tinyLeftMenuItems" :href="item.url" :class="{active:item.isActive, separator:item.name == '-', on:item.isOn, off:item.isOff||item.isImportant}">
<i class="icon play tiny" :style="{'visibility':item.isActive ? 'visible' : 'hidden'}"></i><span v-if="item.name != '-'">{{item.name}}<var v-if="item.isOff"></var><var v-if="item.isImportant"></var></span>
</a>
</div>
</div>

View File

@@ -0,0 +1,7 @@
<first-menu>
<menu-item :href="'/servers/server/settings/locations?serverId=' + serverId">&laquo; 返回网站设置</menu-item>
<span class="item disabled" style="padding-left:0;padding-right:0">|</span>
<menu-item :href="'/servers/server/settings/locations?serverId=' + serverId">路由规则</menu-item>
<raquo-item></raquo-item>
<menu-item :href="'/servers/server/settings/locations/location?serverId=' + serverId + '&locationId=' + locationId" :active="true">{{locationConfig.pattern}}</menu-item>
</first-menu>

View File

@@ -0,0 +1,4 @@
<first-menu>
<menu-item :href="'/servers/server/settings/locations?serverId=' + serverId" code="index">列表</menu-item>
<menu-item :href="'/servers/server/settings/locations/create?serverId=' + serverId" code="create">创建</menu-item>
</first-menu>

View File

@@ -0,0 +1,16 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<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" :v-is-location="true"
@change="changeMethods"></http-auth-config-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

@@ -0,0 +1,10 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
this.changeMethods = function (config) {
Tea.action("$")
.form(this.$refs.authForm)
.post()
teaweb.successRefresh("保存成功")
}
})

View File

@@ -0,0 +1,20 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<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-is-location="true"></http-access-log-config-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,17 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<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-cache-policy="cachePolicy" :v-is-location="true"></http-cache-config-box>
<submit-btn></submit-btn>
<p class="comment">修改条件设置后请记得保存。</p>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,18 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<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" :v-is-location="true"></http-cc-config-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,17 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<div class="margin"></div>
<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" :v-is-location="true"></http-charsets-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,21 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<div class="margin"></div>
<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" :v-is-location="true"></http-gzip-box>
<div class="margin"></div>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,21 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<div class="margin"></div>
<form method="post" class="ui form" data-tea-success="success" data-tea-action="$">
<csrf-token></csrf-token>
<input type="hidden" name="webId" :value="webId"/>
<http-compression-config-box :v-compression-config="compressionConfig" :v-is-location="true"></http-compression-config-box>
<div class="margin"></div>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,91 @@
{$layout}
{$template "../settings_menu"}
{$template "/left_menu_with_menu"}
<div class="right-box with-menu">
{$template "menu"}
<div class="margin"></div>
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<table class="ui table selectable definition">
<tr>
<td>路径匹配规则 *</td>
<td>
<input type="text" name="pattern" maxlength="500" ref="focus"/>
<p class="comment">路径通常以斜杠(/)开头,比如/hello。如果匹配类型是正则表达式匹配则可以是一个正则表达式</p>
</td>
</tr>
<tr>
<td>匹配类型</td>
<td>
<select class="ui dropdown auto-width" name="patternType" v-model="type" @change="changePatternType(type)">
<option v-for="patternType in patternTypes" :value="patternType.type">{{patternType.name}}</option>
</select>
<p class="comment" v-if="selectedType != null" v-html="selectedType.description"></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 class="title">名称</td>
<td>
<input type="text" name="name" maxlength="100"/>
<p class="comment">可以用来说明此规则用途。。</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>
<td>专属域名</td>
<td>
<domains-box></domains-box>
<p class="comment">默认不需要填写,表示支持所有域名。如果填写了专属域名,表示当前路由规则只会在所列的专属域名被访问时才生效。</p>
</td>
</tr>
<tr>
<td>不区分大小写</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="isCaseInsensitive" value="1"/>
<label></label>
</div>
<p class="comment">选中表示匹配规则中的路径中的英文字母不区分大小写。</p>
</td>
</tr>
<tr>
<td>反向匹配</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="isReverse" value="1"/>
<label></label>
</div>
<p class="comment">选中表示匹配所有<strong>不符合规则</strong>的路径。</p>
</td>
</tr>
<tr>
<td>描述</td>
<td>
<textarea rows="3" name="description" maxlength="200"></textarea>
</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>
</form>
</div>

View File

@@ -0,0 +1,13 @@
Tea.context(function () {
this.success = NotifySuccess("添加成功", "/servers/server/settings/locations?serverId=" + this.serverId)
this.type = 1
this.selectedType = this.patternTypes[0]
this.changePatternType = function (type) {
this.selectedType = this.patternTypes.$find(function (k, v) {
return v.type == type;
})
}
})

View File

@@ -0,0 +1,15 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<http-fastcgi-box :v-fastcgi-ref="fastcgiRef" :v-fastcgi-configs="fastcgiConfigs" :v-is-location="true"></http-fastcgi-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,22 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<div class="margin"></div>
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<http-header-policy-box
:v-request-header-policy="requestHeaderPolicy"
:v-request-header-ref="requestHeaderRef"
:v-response-header-policy="responseHeaderPolicy"
:v-response-header-ref="responseHeaderRef"
:v-params="'serverId=' + serverId"
:v-is-location="true"></http-header-policy-box>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,16 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="webId" :value="webId"/>
<http-redirect-to-https-box :v-redirect-to-https-config="redirectToHTTPSConfig" :v-is-location="true"></http-redirect-to-https-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1 @@
undefined

View File

@@ -0,0 +1,45 @@
{$layout}
{$var "header"}
<script type="text/javascript" src="/js/sortable.min.js"></script>
{$end}
{$template "../settings_menu"}
{$template "/left_menu_with_menu"}
<div class="right-box with-menu">
{$template "menu"}
<p class="comment" v-if="locations.length == 0">暂时还没有路由规则。</p>
<table class="ui table selectable celled" v-if="locations.length > 0" id="sortable-table">
<thead>
<tr>
<th style="width:1em"></th>
<th>匹配规则</th>
<th class="two wide">匹配类型</th>
<th class="two wide">状态</th>
<th class="two op">操作</th>
</tr>
</thead>
<tbody v-for="location in locations" :v-id="location.id">
<tr>
<td><i class="icon bars grey handle"></i></td>
<td>
<a :href="'/servers/server/settings/locations/location?serverId=' + serverId + '&locationId=' + location.id">{{location.pattern}}</a>
<http-location-labels :v-location-config="location" :v-server-id="serverId"></http-location-labels>
</td>
<td>{{location.patternTypeName}}</td>
<td>
<label-on :v-is-on="location.isOn"></label-on>
</td>
<td>
<a :href="'/servers/server/settings/locations/location?serverId=' + serverId + '&locationId=' + location.id">详情</a> &nbsp;
<a href="" @click.prevent="deleteLocation(location.id)">删除</a> &nbsp;
<!--<a :href="'/servers/server/settings/locations/create?serverId=' + serverId + '&webId=' + webId + '&parentId=' + location.id" title="添加子规则">+</a>-->
</td>
</tr>
</tbody>
</table>
<p class="comment" v-if="locations.length > 0">拖动左侧的<i class="icon bars grey"></i>图标可以对路由规则进行排序。</p>
</div>

View File

@@ -0,0 +1,48 @@
Tea.context(function () {
this.$delay(function () {
this.sort()
}, 1000)
// 删除路由规则
this.deleteLocation = function (locationId) {
teaweb.confirm("确定要删除此路由规则吗?", function () {
this.$post(".delete")
.params({
webId: this.webId,
locationId: locationId
})
.refresh()
})
}
// 排序
this.sort = function () {
if (this.locations.length == 0) {
return
}
let box = this.$find("#sortable-table")[0]
let that = this
Sortable.create(box, {
draggable: "tbody",
handle: ".icon.handle",
onStart: function () {
},
onUpdate: function (event) {
let rows = box.querySelectorAll("tbody")
let locationIds = []
rows.forEach(function (row) {
locationIds.push(parseInt(row.getAttribute("v-id")))
})
that.$post(".sort")
.params({
webId: that.webId,
locationIds: locationIds
})
.success(function () {
teaweb.success("保存成功")
})
}
})
}
})

View File

@@ -0,0 +1,103 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="locationId" :value="locationConfig.id"/>
<table class="ui table selectable definition">
<tr>
<td>路径匹配规则 *</td>
<td>
<input type="text" name="pattern" v-model="pattern" maxlength="500" ref="focus"/>
<p class="comment">路径通常以斜杠(/)开头,比如/hello。如果匹配类型是正则表达式匹配则可以是一个正则表达式</p>
</td>
</tr>
<tr>
<td>匹配类型</td>
<td>
<select class="ui dropdown auto-width" name="patternType" v-model="type" @change="changePatternType(type)">
<option v-for="patternType in patternTypes" :value="patternType.type">{{patternType.name}}</option>
</select>
<p class="comment" v-if="selectedType != null" v-html="selectedType.description"></p>
</td>
</tr>
<tr>
<td>终止往下匹配</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="isBreak" value="1" v-model="locationConfig.isBreak"/>
<label></label>
</div>
<p class="comment">如果选中了此选项,一旦匹配成功,不会继续匹配其他的路由规则。</p>
</td>
</tr>
<tr>
<td class="title">名称</td>
<td>
<input type="text" name="name" maxlength="100" v-model="locationConfig.name"/>
<p class="comment">可以用来说明此规则用途。。</p>
</td>
</tr>
<tr>
<td>匹配条件</td>
<td>
<http-request-conds-box :v-conds="conds"></http-request-conds-box>
</td>
</tr>
<tr>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>专属域名</td>
<td>
<domains-box :v-domains="domains"></domains-box>
<p class="comment">默认不需要填写,表示支持所有域名。如果填写了专属域名,表示当前路由规则只会在所列的专属域名被访问时才生效。</p>
</td>
</tr>
<tr>
<tr>
<td>不区分大小写</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="isCaseInsensitive" value="1" v-model="isCaseInsensitive"/>
<label></label>
</div>
<p class="comment">选中表示匹配规则中的路径中的英文字母不区分大小写。</p>
</td>
</tr>
<tr>
<td>反向匹配</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="isReverse" value="1" v-model="isReverse"/>
<label></label>
</div>
<p class="comment">选中表示匹配所有<strong>不符合规则</strong>的路径。</p>
</td>
</tr>
<tr>
<td>描述</td>
<td>
<textarea rows="3" name="description" maxlength="200" v-model="locationConfig.description"></textarea>
</td>
</tr>
<tr>
<td>启用当前路由规则</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="isOn" v-model="locationConfig.isOn"/>
<label></label>
</div>
</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

@@ -0,0 +1,15 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
this.$delay(function () {
this.changePatternType(this.type)
})
this.selectedType = null
this.changePatternType = function (type) {
this.selectedType = this.patternTypes.$find(function (k, v) {
return v.type == type;
})
}
})

View File

@@ -0,0 +1,3 @@
<first-menu>
<menu-item code="hls" :href="'.hls?serverId=' + server.id">启用HLS加密配置</menu-item>
</first-menu>

View File

@@ -0,0 +1,18 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<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" :v-is-location="true"></http-hls-config-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

View File

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

View File

@@ -0,0 +1,18 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "../location_menu"}
{$template "../left_menu"}
<div class="right-box tiny">
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
<input type="hidden" name="webId" :value="webId"/>
<http-optimization-config-box :v-optimization-config="optimizationConfig" :v-is-location="true"></http-optimization-config-box>
<submit-btn></submit-btn>
</form>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More