1.4.5.2
This commit is contained in:
18
EdgeAdmin/web/views/@default/servers/server/boards/index.css
Normal file
18
EdgeAdmin/web/views/@default/servers/server/boards/index.css
Normal file
@@ -0,0 +1,18 @@
|
||||
.chart-box {
|
||||
height: 14em;
|
||||
}
|
||||
.traffic-map-box {
|
||||
height: 16em;
|
||||
}
|
||||
.traffic-map-box div::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
h4 span {
|
||||
font-size: 0.8em;
|
||||
color: grey;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
.menu .item span.small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
/*# sourceMappingURL=index.css.map */
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,YAAA;;AAGD;EACC,YAAA;;AADD,gBAGC,IAAG;EACF,UAAA;;AAIF,EACC;EACC,gBAAA;EACA,WAAA;EACA,8BAAA;;AAIF,KACC,MAAM,KAAI;EACT,gBAAA","file":"index.css"}
|
||||
122
EdgeAdmin/web/views/@default/servers/server/boards/index.html
Normal file
122
EdgeAdmin/web/views/@default/servers/server/boards/index.html
Normal file
@@ -0,0 +1,122 @@
|
||||
{$layout}
|
||||
|
||||
{$var "header"}
|
||||
<!-- world map -->
|
||||
<script type="text/javascript" src="/js/echarts/echarts.min.js"></script>
|
||||
<script type="text/javascript" src="/js/world.js"></script>
|
||||
<script type="text/javascript" src="/js/world-countries-map.js"></script>
|
||||
{$end}
|
||||
|
||||
<first-menu>
|
||||
<menu-item href="/servers">网站列表</menu-item>
|
||||
<span class="item disabled">|</span>
|
||||
<menu-item :href="'/servers/server?serverId=' + server.id" active="true">"{{server.name}}"看板</menu-item>
|
||||
<span class="disabled item">|</span>
|
||||
<more-items-angle
|
||||
:v-data-url="'/servers/nearby?serverId=' + server.id"
|
||||
:v-url="'/servers/server/boards?serverId=${serverId}'"></more-items-angle>
|
||||
</first-menu>
|
||||
|
||||
<!-- 加载中 -->
|
||||
<div style="margin-top: 0.8em">
|
||||
<div class="ui message loading" v-if="isLoading">
|
||||
<div class="ui active inline loader small"></div> 数据加载中...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 总体统计 -->
|
||||
<columns-grid v-if="!isLoading">
|
||||
<div class="ui column">
|
||||
<h4>上月峰值带宽</h4>
|
||||
<div class="value"><bits-var :v-bits="lastMonthlyPeekBandwidthBits"></bits-var></div>
|
||||
</div>
|
||||
<div class="ui column">
|
||||
<h4>当月峰值带宽</h4>
|
||||
<div class="value"><bits-var :v-bits="monthlyPeekBandwidthBits"></bits-var></div>
|
||||
</div>
|
||||
<div class="ui column">
|
||||
<h4>当天峰值带宽</h4>
|
||||
<div class="value"><bits-var :v-bits="dailyPeekBandwidthBits"></bits-var></div>
|
||||
</div>
|
||||
<div class="ui column">
|
||||
<h4>当前峰值带宽</h4>
|
||||
<div class="value"><bits-var :v-bits="minutelyPeekBandwidthBits"></bits-var></div>
|
||||
</div>
|
||||
<div class="ui column">
|
||||
<h4>当天独立IP</h4>
|
||||
<div class="value">
|
||||
<span v-if="dailyCountIPs > 0">{{dailyCountIPsFormat}}</span>
|
||||
<span v-else class="disabled">尚无数据</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui column">
|
||||
<h4>当天流量</h4>
|
||||
<div class="value"><bytes-var :v-bytes="dailyTrafficBytes"></bytes-var></div>
|
||||
</div>
|
||||
</columns-grid>
|
||||
|
||||
<chart-columns-grid>
|
||||
<div class="ui column">
|
||||
<!-- 流量地图 -->
|
||||
<div v-if="!isLoading">
|
||||
<traffic-map-box :v-stats="topCountryStats"></traffic-map-box>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui column">
|
||||
<!-- 带宽图表 -->
|
||||
<div class="ui menu text blue" v-show="!isLoading">
|
||||
<a href="" class="item" :class="{active: bandwidthTab == 'minutely'}" @click.prevent="selectBandwidthTab('minutely')">最近带宽<span class="small grey">(比特)</span></a>
|
||||
<a href="" class="item" :class="{active: bandwidthTab == 'hourly'}" @click.prevent="selectBandwidthTab('hourly')">按小时带宽<span class="small grey">(比特)</span></a>
|
||||
<a href="" class="item" :class="{active: bandwidthTab == 'daily'}" @click.prevent="selectBandwidthTab('daily')">按天带宽<span class="small grey">(比特)</span></a>
|
||||
<a :href="'/servers/traffic-stats?serverId=' + server.id" class="item right">更多</a>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
<div class="chart-box" id="bandwidth-chart"></div>
|
||||
</div>
|
||||
|
||||
<div class="ui column">
|
||||
<!-- 流量图表 -->
|
||||
<div class="ui menu text blue" v-show="!isLoading">
|
||||
<a href="" class="item" :class="{active: trafficTab == 'hourly'}" @click.prevent="selectTrafficTab('hourly')">24小时流量趋势</a>
|
||||
<a href="" class="item" :class="{active: trafficTab == 'daily'}" @click.prevent="selectTrafficTab('daily')">15天流量趋势</a>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
|
||||
<!-- 按小时统计流量 -->
|
||||
<div class="chart-box" id="hourly-traffic-chart" v-show="trafficTab == 'hourly'"></div>
|
||||
|
||||
<!-- 按日统计流量 -->
|
||||
<div class="chart-box" id="daily-traffic-chart" v-show="trafficTab == 'daily'"></div>
|
||||
</div>
|
||||
|
||||
<div class="ui column">
|
||||
<div class="ui menu text blue" v-show="!isLoading">
|
||||
<a href="" class="item" :class="{active: requestsTab == 'hourly'}" @click.prevent="selectRequestsTab('hourly')">24小时访问量趋势</a>
|
||||
<a href="" class="item" :class="{active: requestsTab == 'daily'}" @click.prevent="selectRequestsTab('daily')">15天访问量趋势</a>
|
||||
</div>
|
||||
<div class="ui divider"></div>
|
||||
|
||||
<!-- 按小时统计访问量 -->
|
||||
<div class="chart-box" id="hourly-requests-chart" v-show="requestsTab == 'hourly'"></div>
|
||||
|
||||
<!-- 按日统计访问量 -->
|
||||
<div class="chart-box" id="daily-requests-chart" v-show="requestsTab == 'daily'"></div>
|
||||
</div>
|
||||
|
||||
<div class="ui column">
|
||||
<!-- 域名排行 -->
|
||||
<h4 v-show="!isLoading">域名访问排行 <span>(24小时)</span></h4>
|
||||
<div class="ui divider"></div>
|
||||
<div class="chart-box" id="top-domains-chart"><loading-message>数据加载中...</loading-message></div>
|
||||
</div>
|
||||
|
||||
<!-- 指标 -->
|
||||
<metric-chart v-for="chart in metricCharts"
|
||||
:key="chart.id"
|
||||
:v-chart="chart.chart"
|
||||
:v-stats="chart.stats"
|
||||
:v-item="chart.item"
|
||||
:v-column="true">
|
||||
</metric-chart>
|
||||
</chart-columns-grid>
|
||||
498
EdgeAdmin/web/views/@default/servers/server/boards/index.js
Normal file
498
EdgeAdmin/web/views/@default/servers/server/boards/index.js
Normal file
@@ -0,0 +1,498 @@
|
||||
Tea.context(function () {
|
||||
this.isLoading = true
|
||||
this.metricCharts = []
|
||||
|
||||
this.formatBytes = teaweb.formatBytes
|
||||
this.dailyCountIPsFormat = "0"
|
||||
|
||||
|
||||
/**
|
||||
* 流量统计
|
||||
*/
|
||||
this.trafficTab = "hourly"
|
||||
|
||||
this.$delay(function () {
|
||||
this.load()
|
||||
})
|
||||
|
||||
this.load = function () {
|
||||
this.$post("$")
|
||||
.params({
|
||||
serverId: this.server.id
|
||||
})
|
||||
.success(function (resp) {
|
||||
for (let k in resp.data) {
|
||||
this[k] = resp.data[k]
|
||||
}
|
||||
this.isLoading = false
|
||||
|
||||
if (this.dailyCountIPs > 0) {
|
||||
this.dailyCountIPsFormat = teaweb.formatNumber(this.dailyCountIPs)
|
||||
}
|
||||
|
||||
this.$delay(function () {
|
||||
this.reloadMinutelyBandwidthChart()
|
||||
this.reloadHourlyTrafficChart()
|
||||
this.reloadHourlyRequestsChart()
|
||||
})
|
||||
|
||||
// 域名统计
|
||||
this.$post(".domainStats")
|
||||
.params({
|
||||
serverId: this.server.id
|
||||
})
|
||||
.success(function (resp) {
|
||||
for (let k in resp.data) {
|
||||
this[k] = resp.data[k]
|
||||
}
|
||||
this.reloadTopDomainsChart()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.bandwidthTab = "minutely"
|
||||
this.hourlyBandwidthStats = []
|
||||
this.dailyBandwidthStats = []
|
||||
|
||||
this.selectBandwidthTab = function (tab) {
|
||||
this.bandwidthTab = tab
|
||||
switch (tab) {
|
||||
case "minutely":
|
||||
this.reloadMinutelyBandwidthChart()
|
||||
break
|
||||
case "hourly":
|
||||
this.$post(".hourlyBandwidth")
|
||||
.params({
|
||||
serverId: this.serverId
|
||||
})
|
||||
.success(function (response) {
|
||||
this.hourlyBandwidthStats = response.data.stats
|
||||
this.reloadHourlyBandwidthChart(response.data.percentile, response.data.percentileBits)
|
||||
})
|
||||
break
|
||||
case "daily":
|
||||
this.$post(".dailyBandwidth")
|
||||
.params({
|
||||
serverId: this.serverId
|
||||
})
|
||||
.success(function (response) {
|
||||
this.dailyBandwidthStats = response.data.stats
|
||||
this.reloadDailyBandwidthChart(response.data.percentile, response.data.percentileBits)
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
this.reloadMinutelyBandwidthChart = function () {
|
||||
let axis = teaweb.bitsAxis(this.bandwidthStats, function (stat) {
|
||||
return stat.bits
|
||||
})
|
||||
teaweb.renderLineChart({
|
||||
id: "bandwidth-chart",
|
||||
values: this.bandwidthStats,
|
||||
axis: axis,
|
||||
x: function (stat) {
|
||||
return stat.timeAt
|
||||
},
|
||||
value: function (stat) {
|
||||
return stat.bits / axis.divider
|
||||
},
|
||||
tooltip: function (args, values) {
|
||||
if (args.componentType == "markLine") {
|
||||
return args.name
|
||||
}
|
||||
let index = args.dataIndex
|
||||
let day = values[index].day
|
||||
return day.substr(0, 4) + "-" + day.substr(4, 2) + "-" + day.substr(6, 2) + " " + values[index].timeAt + "<br/>峰值带宽:" + teaweb.formatBits(values[index].bits)
|
||||
},
|
||||
markLine: {
|
||||
precision: 4,
|
||||
data: [{
|
||||
name: this.bandwidthPercentile + "th",
|
||||
yAxis: this.bandwidthPercentileBits/axis.divider
|
||||
}],
|
||||
symbol: "none",
|
||||
lineStyle: {
|
||||
color: teaweb.chartColor("red")
|
||||
}
|
||||
},
|
||||
left: 30,
|
||||
right: 40
|
||||
})
|
||||
}
|
||||
|
||||
this.reloadHourlyBandwidthChart = function (percentile, percentileBits) {
|
||||
let axis = teaweb.bitsAxis(this.hourlyBandwidthStats, function (stat) {
|
||||
return stat.bits
|
||||
})
|
||||
teaweb.renderLineChart({
|
||||
id: "bandwidth-chart",
|
||||
values: this.hourlyBandwidthStats,
|
||||
axis: axis,
|
||||
x: function (stat) {
|
||||
return stat.hour
|
||||
},
|
||||
value: function (stat) {
|
||||
return stat.bits / axis.divider
|
||||
},
|
||||
tooltip: function (args, values) {
|
||||
if (args.componentType == "markLine") {
|
||||
return args.name
|
||||
}
|
||||
let index = args.dataIndex
|
||||
let day = values[index].day
|
||||
return day.substr(0, 4) + "-" + day.substr(4, 2) + "-" + day.substr(6, 2) + " " + values[index].hour + "时<br/>峰值带宽:" + teaweb.formatBits(values[index].bits)
|
||||
},
|
||||
markLine: {
|
||||
precision: 4,
|
||||
data: [{
|
||||
name: percentile + "th",
|
||||
yAxis: percentileBits/axis.divider
|
||||
}],
|
||||
symbol: "none",
|
||||
lineStyle: {
|
||||
color: teaweb.chartColor("red")
|
||||
}
|
||||
},
|
||||
left: 30,
|
||||
right: 40
|
||||
})
|
||||
}
|
||||
|
||||
this.reloadDailyBandwidthChart = function (percentile, percentileBits) {
|
||||
let axis = teaweb.bitsAxis(this.dailyBandwidthStats, function (stat) {
|
||||
return stat.bits
|
||||
})
|
||||
teaweb.renderLineChart({
|
||||
id: "bandwidth-chart",
|
||||
values: this.dailyBandwidthStats,
|
||||
axis: axis,
|
||||
x: function (stat) {
|
||||
let day = stat.day
|
||||
return day.substr(4, 2) + "-" + day.substr(6, 2)
|
||||
},
|
||||
value: function (stat) {
|
||||
return stat.bits / axis.divider
|
||||
},
|
||||
tooltip: function (args, values) {
|
||||
if (args.componentType == "markLine") {
|
||||
return args.name
|
||||
}
|
||||
let index = args.dataIndex
|
||||
let day = values[index].day
|
||||
return day.substr(0, 4) + "-" + day.substr(4, 2) + "-" + day.substr(6, 2) + "<br/>峰值带宽:" + teaweb.formatBits(values[index].bits)
|
||||
},
|
||||
markLine: {
|
||||
precision: 4,
|
||||
data: [{
|
||||
name: percentile + "th",
|
||||
yAxis: percentileBits/axis.divider
|
||||
}],
|
||||
symbol: "none",
|
||||
lineStyle: {
|
||||
color: teaweb.chartColor("red")
|
||||
}
|
||||
},
|
||||
left: 30,
|
||||
right: 40
|
||||
})
|
||||
}
|
||||
|
||||
this.selectTrafficTab = function (tab) {
|
||||
this.trafficTab = tab
|
||||
if (tab == "hourly") {
|
||||
this.$delay(function () {
|
||||
this.reloadHourlyTrafficChart()
|
||||
})
|
||||
} else if (tab == "daily") {
|
||||
this.$delay(function () {
|
||||
this.reloadDailyTrafficChart()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.reloadHourlyTrafficChart = function () {
|
||||
let stats = this.hourlyStats
|
||||
this.reloadTrafficChart("hourly-traffic-chart", "流量统计", stats, function (args) {
|
||||
let index = args.dataIndex
|
||||
let cachedRatio = 0
|
||||
let attackRatio = 0
|
||||
if (stats[index].bytes > 0) {
|
||||
cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100
|
||||
attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100
|
||||
}
|
||||
|
||||
return stats[index].day + " " + stats[index].hour + "时<br/>总流量:" + teaweb.formatBytes(stats[index].bytes) + "<br/>缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "<br/>缓存命中率:" + cachedRatio + "%<br/>拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "<br/>拦截比例:" + attackRatio + "%"
|
||||
})
|
||||
}
|
||||
|
||||
this.reloadDailyTrafficChart = function () {
|
||||
let stats = this.dailyStats
|
||||
this.reloadTrafficChart("daily-traffic-chart", "流量统计", stats, function (args) {
|
||||
let index = args.dataIndex
|
||||
let cachedRatio = 0
|
||||
let attackRatio = 0
|
||||
if (stats[index].bytes > 0) {
|
||||
cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100
|
||||
attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100
|
||||
}
|
||||
|
||||
return stats[index].day + "<br/>总流量:" + teaweb.formatBytes(stats[index].bytes) + "<br/>缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "<br/>缓存命中率:" + cachedRatio + "%<br/>拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "<br/>拦截比例:" + attackRatio + "%"
|
||||
})
|
||||
}
|
||||
|
||||
this.reloadTrafficChart = function (chartId, name, stats, tooltipFunc) {
|
||||
let chartBox = document.getElementById(chartId)
|
||||
if (chartBox == null) {
|
||||
return
|
||||
}
|
||||
|
||||
let axis = teaweb.bytesAxis(stats, function (v) {
|
||||
return Math.max(v.bytes, v.cachedBytes)
|
||||
})
|
||||
|
||||
let chart = teaweb.initChart(chartBox)
|
||||
let option = {
|
||||
xAxis: {
|
||||
data: stats.map(function (v) {
|
||||
if (v.hour != null) {
|
||||
return v.hour
|
||||
}
|
||||
return v.day
|
||||
})
|
||||
},
|
||||
yAxis: {
|
||||
axisLabel: {
|
||||
formatter: function (value) {
|
||||
return value + axis.unit
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: "item",
|
||||
formatter: tooltipFunc
|
||||
},
|
||||
grid: {
|
||||
left: 50,
|
||||
top: 40,
|
||||
right: 20,
|
||||
bottom: 20
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "流量",
|
||||
type: "line",
|
||||
data: stats.map(function (v) {
|
||||
return v.bytes / axis.divider
|
||||
}),
|
||||
itemStyle: {
|
||||
color: teaweb.DefaultChartColor
|
||||
},
|
||||
areaStyle: {
|
||||
color: teaweb.DefaultChartColor
|
||||
},
|
||||
smooth: true
|
||||
},
|
||||
{
|
||||
name: "缓存流量",
|
||||
type: "line",
|
||||
data: stats.map(function (v) {
|
||||
return v.cachedBytes / axis.divider
|
||||
}),
|
||||
itemStyle: {
|
||||
color: "#61A0A8"
|
||||
},
|
||||
areaStyle: {
|
||||
color: "#61A0A8"
|
||||
},
|
||||
smooth: true
|
||||
},
|
||||
{
|
||||
name: "攻击流量",
|
||||
type: "line",
|
||||
data: stats.map(function (v) {
|
||||
return v.attackBytes / axis.divider;
|
||||
}),
|
||||
itemStyle: {
|
||||
color: "#F39494"
|
||||
},
|
||||
areaStyle: {
|
||||
color: "#F39494"
|
||||
},
|
||||
smooth: true
|
||||
}
|
||||
],
|
||||
legend: {
|
||||
data: ["流量", "缓存流量", "攻击流量"]
|
||||
},
|
||||
animation: true
|
||||
}
|
||||
chart.setOption(option)
|
||||
chart.resize()
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求数统计
|
||||
*/
|
||||
this.requestsTab = "hourly"
|
||||
|
||||
this.selectRequestsTab = function (tab) {
|
||||
this.requestsTab = tab
|
||||
if (tab == "hourly") {
|
||||
this.$delay(function () {
|
||||
this.reloadHourlyRequestsChart()
|
||||
})
|
||||
} else if (tab == "daily") {
|
||||
this.$delay(function () {
|
||||
this.reloadDailyRequestsChart()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
this.reloadHourlyRequestsChart = function () {
|
||||
let stats = this.hourlyStats
|
||||
this.reloadRequestsChart("hourly-requests-chart", "请求数统计", stats, function (args) {
|
||||
let index = args.dataIndex
|
||||
let cachedRatio = 0
|
||||
let attackRatio = 0
|
||||
if (stats[index].countRequests > 0) {
|
||||
cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100
|
||||
attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100
|
||||
}
|
||||
|
||||
return stats[index].day + " " + stats[index].hour + "时<br/>总请求数:" + teaweb.formatNumber(stats[index].countRequests) + "<br/>缓存请求数:" + teaweb.formatNumber(stats[index].countCachedRequests) + "<br/>缓存命中率:" + cachedRatio + "%<br/>拦截攻击数:" + teaweb.formatNumber(stats[index].countAttackRequests) + "<br/>拦截比例:" + attackRatio + "%"
|
||||
})
|
||||
}
|
||||
|
||||
this.reloadDailyRequestsChart = function () {
|
||||
let stats = this.dailyStats
|
||||
this.reloadRequestsChart("daily-requests-chart", "请求数统计", stats, function (args) {
|
||||
let index = args.dataIndex
|
||||
let cachedRatio = 0
|
||||
let attackRatio = 0
|
||||
if (stats[index].countRequests > 0) {
|
||||
cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100
|
||||
attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100
|
||||
}
|
||||
|
||||
return stats[index].day + "<br/>总请求数:" + teaweb.formatNumber(stats[index].countRequests) + "<br/>缓存请求数:" + teaweb.formatNumber(stats[index].countCachedRequests) + "<br/>缓存命中率:" + cachedRatio + "%<br/>拦截攻击数:" + teaweb.formatNumber(stats[index].countAttackRequests) + "<br/>拦截比例:" + attackRatio + "%"
|
||||
})
|
||||
}
|
||||
|
||||
this.reloadRequestsChart = function (chartId, name, stats, tooltipFunc) {
|
||||
let chartBox = document.getElementById(chartId)
|
||||
if (chartBox == null) {
|
||||
return
|
||||
}
|
||||
|
||||
let axis = teaweb.countAxis(stats, function (v) {
|
||||
return Math.max(v.countRequests, v.countCachedRequests)
|
||||
})
|
||||
|
||||
let chart = teaweb.initChart(chartBox)
|
||||
let option = {
|
||||
xAxis: {
|
||||
data: stats.map(function (v) {
|
||||
if (v.hour != null) {
|
||||
return v.hour
|
||||
}
|
||||
if (v.day != null) {
|
||||
return v.day
|
||||
}
|
||||
return ""
|
||||
})
|
||||
},
|
||||
yAxis: {
|
||||
axisLabel: {
|
||||
formatter: function (value) {
|
||||
return value + axis.unit
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: "item",
|
||||
formatter: tooltipFunc
|
||||
},
|
||||
grid: {
|
||||
left: 50,
|
||||
top: 40,
|
||||
right: 20,
|
||||
bottom: 20
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "请求数",
|
||||
type: "line",
|
||||
data: stats.map(function (v) {
|
||||
return v.countRequests / axis.divider
|
||||
}),
|
||||
itemStyle: {
|
||||
color: teaweb.DefaultChartColor
|
||||
},
|
||||
areaStyle: {
|
||||
color: teaweb.DefaultChartColor
|
||||
},
|
||||
smooth: true
|
||||
},
|
||||
{
|
||||
name: "缓存请求数",
|
||||
type: "line",
|
||||
data: stats.map(function (v) {
|
||||
return v.countCachedRequests / axis.divider
|
||||
}),
|
||||
itemStyle: {
|
||||
color: "#61A0A8"
|
||||
},
|
||||
areaStyle: {
|
||||
color: "#61A0A8"
|
||||
},
|
||||
smooth: true
|
||||
},
|
||||
{
|
||||
name: "攻击请求数",
|
||||
type: "line",
|
||||
data: stats.map(function (v) {
|
||||
return v.countAttackRequests / axis.divider;
|
||||
}),
|
||||
itemStyle: {
|
||||
color: "#F39494"
|
||||
},
|
||||
areaStyle: {
|
||||
color: "#F39494"
|
||||
},
|
||||
smooth: true
|
||||
}
|
||||
],
|
||||
legend: {
|
||||
data: ["请求数", "缓存请求数", "攻击请求数"]
|
||||
},
|
||||
animation: true
|
||||
}
|
||||
chart.setOption(option)
|
||||
chart.resize()
|
||||
}
|
||||
|
||||
// 域名排行
|
||||
this.reloadTopDomainsChart = function () {
|
||||
let axis = teaweb.countAxis(this.topDomainStats, function (v) {
|
||||
return v.countRequests
|
||||
})
|
||||
teaweb.renderBarChart({
|
||||
id: "top-domains-chart",
|
||||
name: "域名",
|
||||
values: this.topDomainStats,
|
||||
x: function (v) {
|
||||
return v.domain
|
||||
},
|
||||
tooltip: function (args, stats) {
|
||||
return stats[args.dataIndex].domain + "<br/>请求数:" + " " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + "<br/>流量:" + teaweb.formatBytes(stats[args.dataIndex].bytes)
|
||||
},
|
||||
value: function (v) {
|
||||
return v.countRequests / axis.divider;
|
||||
},
|
||||
axis: axis
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
.chart-box {
|
||||
height: 14em;
|
||||
}
|
||||
|
||||
.traffic-map-box {
|
||||
height: 16em;
|
||||
|
||||
div::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
span {
|
||||
font-size: 0.8em;
|
||||
color: grey;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
.item span.small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
.delete-box {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.delete-box button {
|
||||
width: 20em!important;
|
||||
}
|
||||
/*# sourceMappingURL=index.css.map */
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,eAAA;;AADD,WAGC;EACC,qBAAA","file":"index.css"}
|
||||
@@ -0,0 +1,15 @@
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<menu-item href="/servers">网站列表</menu-item>
|
||||
<span class="item disabled">|</span>
|
||||
<menu-item :href="'/servers/server/delete?serverId=' + server.id" active="true">"{{server.name}}"删除</menu-item>
|
||||
<span class="disabled item">|</span>
|
||||
<more-items-angle
|
||||
:v-data-url="'/servers/nearby?serverId=' + server.id"
|
||||
:v-url="'/servers/server/delete?serverId=${serverId}'"></more-items-angle>
|
||||
</first-menu>
|
||||
|
||||
<div class="delete-box">
|
||||
<button class="ui button red large fluid" type="button" @click.prevent="deleteServer(serverId)">删除当前网站</button>
|
||||
</div>
|
||||
15
EdgeAdmin/web/views/@default/servers/server/delete/index.js
Normal file
15
EdgeAdmin/web/views/@default/servers/server/delete/index.js
Normal file
@@ -0,0 +1,15 @@
|
||||
Tea.context(function () {
|
||||
this.deleteServer = function (serverId) {
|
||||
teaweb.confirm("html:确定要删除当前网站吗?<br/>请慎重操作,删除后无法恢复!", function () {
|
||||
this.$post("$")
|
||||
.params({
|
||||
"serverId": serverId
|
||||
})
|
||||
.success(function () {
|
||||
teaweb.success("删除成功", function () {
|
||||
window.location = "/servers"
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
.delete-box {
|
||||
margin-top: 1em;
|
||||
|
||||
button {
|
||||
width: 20em!important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
undefined
|
||||
5
EdgeAdmin/web/views/@default/servers/server/index.html
Normal file
5
EdgeAdmin/web/views/@default/servers/server/index.html
Normal file
@@ -0,0 +1,5 @@
|
||||
{$layout}
|
||||
{$template "/left_menu"}
|
||||
|
||||
<div class="right-box">
|
||||
</div>
|
||||
72
EdgeAdmin/web/views/@default/servers/server/log/history.html
Normal file
72
EdgeAdmin/web/views/@default/servers/server/log/history.html
Normal file
@@ -0,0 +1,72 @@
|
||||
{$template "/datepicker"}
|
||||
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<menu-item href="/servers">网站列表</menu-item>
|
||||
<span class="item disabled">|</span>
|
||||
<menu-item :href="'/servers/server/log?serverId=' + server.id" active="true">"{{server.name}}"日志</menu-item>
|
||||
<span class="disabled item">|</span>
|
||||
<more-items-angle
|
||||
:v-data-url="'/servers/nearby?serverId=' + server.id"
|
||||
:v-url="'/servers/server/log?serverId=${serverId}'"></more-items-angle>
|
||||
</first-menu>
|
||||
|
||||
{$template "/left_menu_with_menu"}
|
||||
<div class="right-box with-menu">
|
||||
<!-- 集群设置提醒 -->
|
||||
<div v-if="!clusterAccessLogIsOn">
|
||||
<div class="margin"></div>
|
||||
<warning-message>当前集群已经设置不允许网站记录访问日志,可以在"集群设置" -- "网站设置"中修改此选项。</warning-message>
|
||||
</div>
|
||||
|
||||
<!-- 网站设置提醒 -->
|
||||
<div v-if="!serverAccessLogIsOn">
|
||||
<div class="margin"></div>
|
||||
<warning-message>当前网站尚未启用访问日志,可以在 <a :href="'/servers/server/settings/accessLog?serverId=' + serverId">[这里]</a> 修改。</warning-message>
|
||||
</div>
|
||||
|
||||
<first-menu>
|
||||
<menu-item :href="buildLogUrl('')" :active="hasError == 0 && hasWAF == 0">所有日志</menu-item>
|
||||
<menu-item :href="buildLogUrl('hasError=1')" :active="hasError > 0">错误日志</menu-item>
|
||||
<menu-item :href="buildLogUrl('hasWAF=1')" :active="hasWAF > 0">WAF日志</menu-item>
|
||||
</first-menu>
|
||||
|
||||
<form method="get" class="ui form small" :action="path">
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<input type="hidden" name="hasError" :value="hasError"/>
|
||||
<input type="hidden" name="hasWAF" :value="hasWAF"/>
|
||||
<http-access-log-search-box :v-ip="ip" :v-domain="domain" :v-keyword="keyword" :v-cluster-id="clusterId" :v-node-id="nodeId">
|
||||
<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">
|
||||
<div class="ui right labeled input">
|
||||
<input type="text" name="hour" maxlength="2" style="width: 3.5em" v-model="hour"/>
|
||||
<span class="ui label">时</span>
|
||||
</div>
|
||||
</div>
|
||||
</http-access-log-search-box>
|
||||
</form>
|
||||
|
||||
<!-- 分区 -->
|
||||
<http-access-log-partitions-box :v-day="day" :v-partition="partition" :v-query="currentQuery"></http-access-log-partitions-box>
|
||||
|
||||
<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" :v-keyword="keyword"></http-access-log-box></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div v-if="accessLogs.length > 0">
|
||||
<a :href="buildLogUrl('requestId=' + lastRequestId + '&hasError=' + hasError + '&hasWAF=' + hasWAF + '&partition=' + partition)" v-if="hasPrev">上一页</a>
|
||||
<span v-else class="disabled">上一页</span>
|
||||
<span class="disabled"> | </span>
|
||||
<a :href="buildLogUrl('requestId=' + nextRequestId + '&hasError=' + hasError + '&hasWAF=' + hasWAF + '&partition=' + partition)" v-if="hasMore">下一页</a>
|
||||
<span v-else class="disabled">下一页</span>
|
||||
<page-size-selector></page-size-selector>
|
||||
</div>
|
||||
</div>
|
||||
82
EdgeAdmin/web/views/@default/servers/server/log/history.js
Normal file
82
EdgeAdmin/web/views/@default/servers/server/log/history.js
Normal file
@@ -0,0 +1,82 @@
|
||||
Tea.context(function () {
|
||||
this.$delay(function () {
|
||||
let that = this
|
||||
teaweb.datepicker("day-input", function (day) {
|
||||
that.day = day
|
||||
})
|
||||
})
|
||||
|
||||
let that = this
|
||||
this.accessLogs.forEach(function (accessLog) {
|
||||
if (typeof (that.regions[accessLog.remoteAddr]) == "string") {
|
||||
accessLog.region = that.regions[accessLog.remoteAddr]
|
||||
} else {
|
||||
accessLog.region = ""
|
||||
}
|
||||
if (accessLog.firewallRuleSetId > 0 && typeof (that.wafInfos[accessLog.firewallRuleSetId]) == "object") {
|
||||
accessLog.wafInfo = that.wafInfos[accessLog.firewallRuleSetId]
|
||||
} else {
|
||||
accessLog.wafInfo = null
|
||||
}
|
||||
})
|
||||
|
||||
this.query = function (args) {
|
||||
// 初始化时页面尚未设置Vue变量,所以使用全局的变量获取
|
||||
let that = TEA.ACTION.data
|
||||
|
||||
if (that.serverId == null) {
|
||||
that.serverId = 0
|
||||
}
|
||||
if (that.keyword == null) {
|
||||
that.keyword = ""
|
||||
}
|
||||
if (that.ip == null) {
|
||||
that.ip = ""
|
||||
}
|
||||
if (that.domain == null) {
|
||||
that.domain = ""
|
||||
}
|
||||
if (that.pageSize == null) {
|
||||
that.pageSize = ""
|
||||
}
|
||||
if (that.day == null) {
|
||||
that.day = ""
|
||||
}
|
||||
if (that.hour == null) {
|
||||
that.hour = ""
|
||||
}
|
||||
let query = 'serverId=' + that.serverId + '&day=' + that.day + '&keyword=' + encodeURIComponent(that.keyword) + '&ip=' + that.ip + '&domain=' + that.domain + '&hour=' + that.hour + '&pageSize=' + that.pageSize
|
||||
if (args != null && args.length > 0) {
|
||||
query += "&" + args
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
this.allQuery = function () {
|
||||
if (this.query == null) {
|
||||
// 尚未初始化完成
|
||||
return
|
||||
}
|
||||
let query = this.query()
|
||||
if (this.hasError == 1) {
|
||||
query += "&hasError=1"
|
||||
}
|
||||
if (this.hasWAF == 1) {
|
||||
query += "&hasWAF=1"
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
this.currentQuery = this.allQuery()
|
||||
|
||||
// 构建日志URL
|
||||
this.buildLogUrl = function (args) {
|
||||
// 使用全局数据,确保在模板中也能正确访问
|
||||
let that = TEA.ACTION.data
|
||||
let query = this.query()
|
||||
if (args != null && args.length > 0) {
|
||||
query += "&" + args
|
||||
}
|
||||
return (that.path || this.path || "") + "?" + query
|
||||
}
|
||||
})
|
||||
40
EdgeAdmin/web/views/@default/servers/server/log/index.html
Normal file
40
EdgeAdmin/web/views/@default/servers/server/log/index.html
Normal file
@@ -0,0 +1,40 @@
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<menu-item href="/servers">网站列表</menu-item>
|
||||
<span class="item disabled">|</span>
|
||||
<menu-item :href="'/servers/server/log?serverId=' + server.id" active="true">"{{server.name}}"日志</menu-item>
|
||||
<span class="disabled item">|</span>
|
||||
<more-items-angle
|
||||
:v-data-url="'/servers/nearby?serverId=' + server.id"
|
||||
:v-url="'/servers/server/log?serverId=${serverId}'"></more-items-angle>
|
||||
</first-menu>
|
||||
|
||||
{$template "/left_menu_with_menu"}
|
||||
<div class="right-box with-menu">
|
||||
<!-- 集群设置提醒 -->
|
||||
<div v-if="!clusterAccessLogIsOn">
|
||||
<div class="margin"></div>
|
||||
<warning-message>当前集群已经设置不允许网站记录访问日志,可以在"集群设置" -- "网站设置"中修改此选项。</warning-message>
|
||||
</div>
|
||||
|
||||
<!-- 网站设置提醒 -->
|
||||
<div v-if="!serverAccessLogIsOn">
|
||||
<div class="margin"></div>
|
||||
<warning-message>当前网站尚未启用访问日志,可以在 <a :href="'/servers/server/settings/accessLog?serverId=' + serverId">[这里]</a> 修改。</warning-message>
|
||||
</div>
|
||||
|
||||
<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" :v-keyword="keyword"></http-access-log-box></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
82
EdgeAdmin/web/views/@default/servers/server/log/index.js
Normal file
82
EdgeAdmin/web/views/@default/servers/server/log/index.js
Normal file
@@ -0,0 +1,82 @@
|
||||
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)
|
||||
|
||||
// 添加区域信息
|
||||
let that = this
|
||||
this.accessLogs.forEach(function (accessLog) {
|
||||
that.formatTime(accessLog)
|
||||
if (typeof (resp.data.regions[accessLog.remoteAddr]) == "string") {
|
||||
accessLog.region = resp.data.regions[accessLog.remoteAddr]
|
||||
} else {
|
||||
accessLog.region = ""
|
||||
}
|
||||
if (accessLog.firewallRuleSetId > 0 && typeof (resp.data.wafInfos[accessLog.firewallRuleSetId]) == "object") {
|
||||
accessLog.wafInfo = resp.data.wafInfos[accessLog.firewallRuleSetId]
|
||||
} else {
|
||||
accessLog.wafInfo = null
|
||||
}
|
||||
})
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
this.formatTime = function (accessLog) {
|
||||
let elapsedSeconds = Math.ceil(new Date().getTime() / 1000) - accessLog.timestamp
|
||||
if (elapsedSeconds >= 0) {
|
||||
if (elapsedSeconds < 60) {
|
||||
accessLog.humanTime = elapsedSeconds + "秒前"
|
||||
} else if (elapsedSeconds < 3600) {
|
||||
accessLog.humanTime = Math.ceil(elapsedSeconds / 60) + "分钟前"
|
||||
} else if (elapsedSeconds < 3600 * 24) {
|
||||
accessLog.humanTime = Math.ceil(elapsedSeconds / 3600) + "小时前"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
60
EdgeAdmin/web/views/@default/servers/server/log/today.html
Normal file
60
EdgeAdmin/web/views/@default/servers/server/log/today.html
Normal file
@@ -0,0 +1,60 @@
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<menu-item href="/servers">网站列表</menu-item>
|
||||
<span class="item disabled">|</span>
|
||||
<menu-item :href="'/servers/server/log?serverId=' + server.id" active="true">"{{server.name}}"日志</menu-item>
|
||||
<span class="disabled item">|</span>
|
||||
<more-items-angle
|
||||
:v-data-url="'/servers/nearby?serverId=' + server.id"
|
||||
:v-url="'/servers/server/log?serverId=${serverId}'"></more-items-angle>
|
||||
</first-menu>
|
||||
|
||||
{$template "/left_menu_with_menu"}
|
||||
<div class="right-box with-menu">
|
||||
<!-- 集群设置提醒 -->
|
||||
<div v-if="!clusterAccessLogIsOn">
|
||||
<div class="margin"></div>
|
||||
<warning-message>当前集群已经设置不允许网站记录访问日志,可以在"集群设置" -- "网站设置"中修改此选项。</warning-message>
|
||||
</div>
|
||||
|
||||
<!-- 网站设置提醒 -->
|
||||
<div v-if="!serverAccessLogIsOn">
|
||||
<div class="margin"></div>
|
||||
<warning-message>当前网站尚未启用访问日志,可以在 <a :href="'/servers/server/settings/accessLog?serverId=' + serverId">[这里]</a> 修改。</warning-message>
|
||||
</div>
|
||||
|
||||
<first-menu>
|
||||
<menu-item :href="buildLogUrl('')" :active="hasError == 0 && hasWAF == 0">所有日志</menu-item>
|
||||
<menu-item :href="buildLogUrl('hasError=1')" :active="hasError > 0">错误日志</menu-item>
|
||||
<menu-item :href="buildLogUrl('hasWAF=1')" :active="hasWAF > 0">WAF日志</menu-item>
|
||||
</first-menu>
|
||||
|
||||
<form method="get" class="ui form small" :action="path">
|
||||
<input type="hidden" name="serverId" :value="serverId"/>
|
||||
<input type="hidden" name="hasError" :value="hasError"/>
|
||||
<input type="hidden" name="hasWAF" :value="hasWAF"/>
|
||||
<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>
|
||||
|
||||
<!-- 分区 -->
|
||||
<http-access-log-partitions-box :v-day="day" :v-partition="partition" :v-query="currentQuery"></http-access-log-partitions-box>
|
||||
|
||||
<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" :v-keyword="keyword"></http-access-log-box></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div v-if="accessLogs.length > 0">
|
||||
<a :href="buildLogUrl('requestId=' + lastRequestId + '&hasError=' + hasError + '&hasWAF=' + hasWAF + '&partition=' + partition)" v-if="hasPrev">上一页</a>
|
||||
<span v-else class="disabled">上一页</span>
|
||||
<span class="disabled"> | </span>
|
||||
<a :href="buildLogUrl('requestId=' + nextRequestId + '&hasError=' + hasError + '&hasWAF=' + hasWAF + '&partition=' + partition)" v-if="hasMore">下一页</a>
|
||||
<span v-else class="disabled">下一页</span>
|
||||
<page-size-selector></page-size-selector>
|
||||
</div>
|
||||
</div>
|
||||
69
EdgeAdmin/web/views/@default/servers/server/log/today.js
Normal file
69
EdgeAdmin/web/views/@default/servers/server/log/today.js
Normal file
@@ -0,0 +1,69 @@
|
||||
Tea.context(function () {
|
||||
let that = this
|
||||
this.accessLogs.forEach(function (accessLog) {
|
||||
if (typeof (that.regions[accessLog.remoteAddr]) == "string") {
|
||||
accessLog.region = that.regions[accessLog.remoteAddr]
|
||||
} else {
|
||||
accessLog.region = ""
|
||||
}
|
||||
if (accessLog.firewallRuleSetId > 0 && typeof (that.wafInfos[accessLog.firewallRuleSetId]) == "object") {
|
||||
accessLog.wafInfo = that.wafInfos[accessLog.firewallRuleSetId]
|
||||
} else {
|
||||
accessLog.wafInfo = null
|
||||
}
|
||||
})
|
||||
|
||||
this.query = function (args) {
|
||||
// 初始化时页面尚未设置Vue变量,所以使用全局的变量获取
|
||||
let that = TEA.ACTION.data
|
||||
|
||||
if (that.serverId == null) {
|
||||
that.serverId = 0
|
||||
}
|
||||
if (that.keyword == null) {
|
||||
that.keyword = ""
|
||||
}
|
||||
if (that.ip == null) {
|
||||
that.ip = ""
|
||||
}
|
||||
if (that.domain == null) {
|
||||
that.domain = ""
|
||||
}
|
||||
if (that.pageSize == null) {
|
||||
that.pageSize = ""
|
||||
}
|
||||
let query = 'serverId=' + that.serverId + '&keyword=' + encodeURIComponent(that.keyword) + '&ip=' + that.ip + '&domain=' + that.domain + '&pageSize=' + that.pageSize
|
||||
if (args != null && args.length > 0) {
|
||||
query += "&" + args
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
this.allQuery = function () {
|
||||
if (this.query == null) {
|
||||
// 尚未初始化完成
|
||||
return
|
||||
}
|
||||
let query = this.query()
|
||||
if (this.hasError == 1) {
|
||||
query += "&hasError=1"
|
||||
}
|
||||
if (this.hasWAF == 1) {
|
||||
query += "&hasWAF=1"
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
this.currentQuery = this.allQuery()
|
||||
|
||||
// 构建日志URL
|
||||
this.buildLogUrl = function (args) {
|
||||
// 使用全局数据,确保在模板中也能正确访问
|
||||
let that = TEA.ACTION.data
|
||||
let query = this.query()
|
||||
if (args != null && args.length > 0) {
|
||||
query += "&" + args
|
||||
}
|
||||
return (that.path || this.path || "") + "?" + query
|
||||
}
|
||||
})
|
||||
@@ -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"}
|
||||
160
EdgeAdmin/web/views/@default/servers/server/log/viewPopup.html
Normal file
160
EdgeAdmin/web/views/@default/servers/server/log/viewPopup.html
Normal file
@@ -0,0 +1,160 @@
|
||||
{$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>请求ID:{{accessLog.requestId}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>请求方法<em>(RequestMethod)</em>:{{accessLog.requestMethod}}</td>
|
||||
<td>请求URI<em>(RequestURI)</em>:{{accessLog.requestURI}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>主机地址<em>(Host)</em>:{{accessLog.host}}</td>
|
||||
<td>终端地址<em>(RemoteAddr:RemotePort)</em>:{{accessLog.remoteAddr}}:{{accessLog.remotePort}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>请求来源<em>(Referer)</em>:
|
||||
<span v-if="accessLog.referer != null && accessLog.referer.length > 0">{{accessLog.referer}}</span>
|
||||
<span v-else class="disabled">[没有设置]</span>
|
||||
</td>
|
||||
<td>终端信息<em>(UserAgent)</em>:
|
||||
<span v-if="accessLog.userAgent != null && accessLog.userAgent.length > 0">{{accessLog.userAgent}}</span>
|
||||
<span v-else class="disabled">[没有设置]</span>
|
||||
</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></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>:
|
||||
<span v-if="accessLog.bytesSent != null">{{accessLog.bytesSent}}
|
||||
<span v-if="accessLog.bytesSent > 0" class="grey small">({{teaweb.formatBytes(accessLog.bytesSent)}})</span>
|
||||
</span>
|
||||
<span v-else class="disabled">0</span>
|
||||
</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规则集:
|
||||
<a :href="'/servers/components/waf/group?firewallPolicyId=' + accessLog.firewallPolicyId + '&type=inbound&groupId=' + accessLog.firewallRuleGroupId+ '#set' + accessLog.firewallRuleSetId" v-if="wafInfo.policy.serverId == 0" target="_parent">{{wafInfo.set.name}}</a>
|
||||
<a :href="'/servers/server/settings/waf/group?serverId=' + accessLog.serverId + '&firewallPolicyId=' + accessLog.firewallPolicyId + '&type=inbound&groupId=' + accessLog.firewallRuleGroupId + '#set' + accessLog.firewallRuleSetId" target="_parent" v-if="wafInfo.policy.serverId > 0">{{wafInfo.set.name}}</a> </td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr v-if="accessLog.errors != null && accessLog.errors.length > 0">
|
||||
<td colspan="2">
|
||||
<div v-for="error in accessLog.errors">
|
||||
<pre><span class="red">{{error}}</span></pre>
|
||||
</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>
|
||||
<span v-if="accessLog.userAgent != null && accessLog.userAgent.length > 0">{{accessLog.userAgent}}</span>
|
||||
<span class="disabled" v-else>[没有设置]</span>
|
||||
</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>
|
||||
74
EdgeAdmin/web/views/@default/servers/server/log/viewPopup.js
Normal file
74
EdgeAdmin/web/views/@default/servers/server/log/viewPopup.js
Normal file
@@ -0,0 +1,74 @@
|
||||
Tea.context(function () {
|
||||
this.tab = "summary"
|
||||
this.teaweb= teaweb
|
||||
|
||||
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,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">»</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>
|
||||
@@ -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,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>
|
||||
@@ -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,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>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
5
EdgeAdmin/web/views/@default/servers/server/settings/cache/@menu.html
vendored
Normal file
5
EdgeAdmin/web/views/@default/servers/server/settings/cache/@menu.html
vendored
Normal 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>
|
||||
13
EdgeAdmin/web/views/@default/servers/server/settings/cache/createPopup.html
vendored
Normal file
13
EdgeAdmin/web/views/@default/servers/server/settings/cache/createPopup.html
vendored
Normal 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>
|
||||
9
EdgeAdmin/web/views/@default/servers/server/settings/cache/createPopup.js
vendored
Normal file
9
EdgeAdmin/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
|
||||
}
|
||||
})
|
||||
41
EdgeAdmin/web/views/@default/servers/server/settings/cache/fetch.html
vendored
Normal file
41
EdgeAdmin/web/views/@default/servers/server/settings/cache/fetch.html
vendored
Normal 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>
|
||||
32
EdgeAdmin/web/views/@default/servers/server/settings/cache/fetch.js
vendored
Normal file
32
EdgeAdmin/web/views/@default/servers/server/settings/cache/fetch.js
vendored
Normal 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
|
||||
}
|
||||
});
|
||||
21
EdgeAdmin/web/views/@default/servers/server/settings/cache/index.html
vendored
Normal file
21
EdgeAdmin/web/views/@default/servers/server/settings/cache/index.html
vendored
Normal 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>
|
||||
3
EdgeAdmin/web/views/@default/servers/server/settings/cache/index.js
vendored
Normal file
3
EdgeAdmin/web/views/@default/servers/server/settings/cache/index.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
53
EdgeAdmin/web/views/@default/servers/server/settings/cache/purge.html
vendored
Normal file
53
EdgeAdmin/web/views/@default/servers/server/settings/cache/purge.html
vendored
Normal 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>
|
||||
<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>
|
||||
43
EdgeAdmin/web/views/@default/servers/server/settings/cache/purge.js
vendored
Normal file
43
EdgeAdmin/web/views/@default/servers/server/settings/cache/purge.js
vendored
Normal 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
|
||||
})
|
||||
@@ -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>
|
||||
@@ -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">
|
||||
<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>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -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>
|
||||
@@ -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,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>
|
||||
@@ -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,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>
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
.checkboxes {
|
||||
.checkbox {
|
||||
width: 8em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
@@ -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> <copy-to-clipboard :v-target="'cname-text'"></copy-to-clipboard> <a href="" @click.prevent="regenerateCNAME()" style="font-size: 0.8em">[重新生成]</a> <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>
|
||||
@@ -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("保存成功")
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
@@ -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>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -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>
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
@@ -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,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>
|
||||
@@ -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,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>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -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>
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
})
|
||||
101
EdgeAdmin/web/views/@default/servers/server/settings/index.html
Normal file
101
EdgeAdmin/web/views/@default/servers/server/settings/index.html
Normal 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> <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>
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
@@ -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>
|
||||
@@ -0,0 +1,7 @@
|
||||
<first-menu>
|
||||
<menu-item :href="'/servers/server/settings/locations?serverId=' + serverId">« 返回网站设置</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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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,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>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
17
EdgeAdmin/web/views/@default/servers/server/settings/locations/cache/index.html
vendored
Normal file
17
EdgeAdmin/web/views/@default/servers/server/settings/locations/cache/index.html
vendored
Normal 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>
|
||||
3
EdgeAdmin/web/views/@default/servers/server/settings/locations/cache/index.js
vendored
Normal file
3
EdgeAdmin/web/views/@default/servers/server/settings/locations/cache/index.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
@@ -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>
|
||||
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyReloadSuccess("保存成功")
|
||||
})
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user