Initial commit (code only without large binaries)

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

View File

@@ -0,0 +1,4 @@
.chart-box {
height: 20em;
}
/*# sourceMappingURL=index.css.map */

View File

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

View File

@@ -0,0 +1,52 @@
{$layout}
{$template "/echarts"}
<p class="ui message warning" v-if="emailVerificationMessage.length > 0"><a href="/settings/email-verify">{{emailVerificationMessage}}</a></p>
<p class="ui message warning" v-if="mobileVerificationMessage.length > 0"><a href="/settings/mobile-verify">{{mobileVerificationMessage}}</a></p>
<p class="ui message warning" v-if="!isVerified">您的账号正在审核中,请耐心等待完成,暂时不能使用相关功能。</p>
<p class="ui message warning" v-if="!isIdentified"><a href="/settings/identity">实名认证</a>后才能使用相关功能。</p>
<div class="ui message loading" v-if="isLoading">
<div class="ui active inline loader small"></div> &nbsp; 数据加载中...
</div>
<columns-grid class="ui columns grid counter-chart" :class="{'three columns': !uiConfig.showTrafficCharts || !uiConfig.showBandwidthCharts, 'four columns': uiConfig.showTrafficCharts && uiConfig.showBandwidthCharts }" v-if="!isLoading">
<div class="ui column">
<h4>加速网站数量</h4>
<div class="value"><span>{{dashboard.countServers}}</span></div>
</div>
<div class="ui column" v-if="uiConfig.showTrafficCharts">
<h4>本月总流量</h4>
<div class="value"><span>{{dashboard.monthlyTrafficBytes}}</span>{{dashboard.monthlyTrafficBytesUnit}}</div>
</div>
<div class="ui column" v-if="uiConfig.showBandwidthCharts">
<h4>本月带宽峰值</h4>
<div class="value"><span>{{dashboard.monthlyPeekBandwidthBytes}}</span>{{dashboard.monthlyPeekBandwidthBytesUnit}}</div>
</div>
<div class="ui column with-border" v-if="uiConfig.showTrafficCharts">
<h4>今日流量</h4>
<div class="value"><span>{{dashboard.dailyTrafficBytes}}</span>{{dashboard.dailyTrafficBytesUnit}}</div>
</div>
<div class="ui column with-border" v-if="uiConfig.showBandwidthCharts">
<h4>今日带宽峰值</h4>
<div class="value"><span>{{dashboard.dailyPeekBandwidthBytes}}</span>{{dashboard.dailyPeekBandwidthBytesUnit}}</div>
</div>
</columns-grid>
<div v-if="uiConfig.showTrafficCharts && !isLoading">
<div class="ui divider"></div>
<h4>近 30 日流量趋势 <span>(单位:字节)</span></h4>
<div class="chart-box" id="daily-traffic-chart"></div>
</div>
<div v-if="uiConfig.showBandwidthCharts && !isLoading">
<div class="ui divider"></div>
<h4>近 30 日带宽趋势</h4>
<div class="chart-box" id="daily-peek-bandwidth-chart"></div>
</div>

View File

@@ -0,0 +1,181 @@
Tea.context(function () {
this.splitFormat = function (format) {
let result = format.match(/^([0-9.]+)([a-zA-Z]+)$/)
return [result[1], result[2]]
}
this.isLoading = true
this.dashboard = {}
this.$delay(function () {
this.$post("$")
.success(function (resp) {
this.isLoading = false
for (let k in resp.data) {
this[k] = resp.data[k]
}
let bandwidthUnit = this.uiConfig.bandwidthUnit
if (bandwidthUnit == null || bandwidthUnit.length == 0) {
bandwidthUnit = "bit"
}
if (bandwidthUnit == "bit") {
this.dashboard.monthlyPeekBandwidthBytes = this.dashboard.monthlyPeekBandwidthBytes.replace("B", "b")
this.dashboard.dailyPeekBandwidthBytes = this.dashboard.dailyPeekBandwidthBytes.replace("B", "b")
}
{
let pieces = this.splitFormat(this.dashboard.monthlyTrafficBytes)
this.dashboard.monthlyTrafficBytes = pieces[0]
this.dashboard.monthlyTrafficBytesUnit = pieces[1]
}
{
let pieces = this.splitFormat(this.dashboard.monthlyPeekBandwidthBytes)
this.dashboard.monthlyPeekBandwidthBytes = pieces[0]
this.dashboard.monthlyPeekBandwidthBytesUnit = pieces[1]
}
{
let pieces = this.splitFormat(this.dashboard.dailyTrafficBytes)
this.dashboard.dailyTrafficBytes = pieces[0]
this.dashboard.dailyTrafficBytesUnit = pieces[1]
}
{
let pieces = this.splitFormat(this.dashboard.dailyPeekBandwidthBytes)
this.dashboard.dailyPeekBandwidthBytes = pieces[0]
this.dashboard.dailyPeekBandwidthBytesUnit = pieces[1]
}
this.$delay(function () {
this.reloadDailyTrafficChart()
this.reloadDailyPeekBandwidthChart()
})
})
})
this.reloadDailyTrafficChart = function () {
let bandwidthUnit = this.uiConfig.bandwidthUnit
if (!this.uiConfig.showTrafficCharts) {
return
}
let stats = this.dailyTrafficStats
let hasCacheInfo = false
let axis = teaweb.bytesAxis(stats, function (stat) {
if (stat.cachedBytes != null) {
hasCacheInfo = true
}
return stat.bytes
})
let series = []
if (hasCacheInfo) {
series = [
{
name: name,
type: "line",
data: stats.map(function (stat) {
return stat.cachedBytes / axis.divider
}),
itemStyle: {
color: "rgba(97,160,168,0.2)"
},
areaStyle: {
//color: "#61A0A8"
},
smooth: true
}
]
}
teaweb.renderLineChart({
id: "daily-traffic-chart",
values: stats,
axis: axis,
x: function (stat) {
return stat.day
},
value: function (stat) {
return stat.bytes / axis.divider
},
tooltip: function (args, values) {
let index = args.dataIndex
let hasCacheInfo = (stats[index].cachedBytes != null)
let cachedRatio = 0
if (hasCacheInfo) {
cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100
}
let tooltip = values[index].day + "<br/>流量:" + teaweb.formatBytes(values[index].bytes)
if (hasCacheInfo) {
tooltip += "<br/>缓存流量:" + teaweb.formatBytes(values[index].cachedBytes)
tooltip += "<br/>缓存命中率:" + cachedRatio + "%"
}
return tooltip
},
series: series
})
}
this.reloadDailyPeekBandwidthChart = function () {
let bandwidthUnit = this.uiConfig.bandwidthUnit
if (!this.uiConfig.showBandwidthCharts) {
return
}
let stats = this.dailyPeekBandwidthStats
let axis = teaweb.bitsAxis(stats, function (stat) {
let value = stat.bytes
if (bandwidthUnit == "bit") {
value *= 8
}
return value
})
teaweb.renderLineChart({
id: "daily-peek-bandwidth-chart",
values: stats,
axis: axis,
x: function (stat) {
return stat.day
},
value: function (stat) {
let value = stat.bytes
if (bandwidthUnit == "bit") {
value *= 8
}
return value / axis.divider
},
tooltip: function (args, values) {
if (args.componentType == "markLine") {
return args.name
}
let index = args.dataIndex
let value = values[index].bytes
if (bandwidthUnit == "bit") {
value *= 8
}
return values[index].day + "<br/>峰值带宽:" + teaweb.formatBits(value)
},
left: 30,
right: 40,
markLine: {
precision: 4,
data: [{
name: this.bandwidthPercentile + "th",
yAxis: this.bandwidthPercentileBits / axis.divider
}],
symbol: "none",
lineStyle: {
color: teaweb.chartColor("red")
}
}
})
}
})

View File

@@ -0,0 +1,3 @@
.chart-box {
height: 20em;
}

View File

@@ -0,0 +1,9 @@
.ui.message .icon {
position: absolute;
right: 1em;
top: 1.8em;
}
.chart-box {
height: 14em;
}
/*# sourceMappingURL=ns.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["ns.less"],"names":[],"mappings":"AAAA,GAAG,QACF;EACC,kBAAA;EACA,UAAA;EACA,UAAA;;AAIF;EACC,YAAA","file":"ns.css"}

View File

@@ -0,0 +1,29 @@
{$layout}
{$template "/echarts"}
<div class="ui four columns grid counter-chart">
<div class="ui column">
<h4>域名<link-icon href="/ns/domains"></link-icon></h4>
<div class="value"><span>{{board.countDomains}}</span></div>
</div>
<div class="ui column">
<h4>记录<link-icon href="/ns/domains"></link-icon></h4>
<div class="value"><span>{{board.countRecords}}</span></div>
</div>
<div class="ui column">
<h4>线路<link-icon href="/ns/routes"></link-icon></h4>
<div class="value"><span>{{board.countRoutes}}</span></div>
</div>
<div class="ui column with-border">
<h4>套餐<link-icon href="/ns/plans"></link-icon></h4>
<div class="value"><span>{{board.countNodes}}</span>
<span v-if="board.planName.length > 0">{{board.planName}}</span>
<span v-if="board.planName.length == 0">未购套餐</span>
</div>
</div>
</div>
<!-- 域名排行 -->
<h4>域名访问排行 <span>24小时</span></h4>
<div class="chart-box" id="top-domains-chart"></div>
<div class="ui divider"></div>

View File

@@ -0,0 +1,31 @@
Tea.context(function () {
this.$delay(function () {
this.reloadTopDomainsChart()
})
// 域名排行
this.reloadTopDomainsChart = function () {
let that = this
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.domainName
},
tooltip: function (args, stats) {
return stats[args.dataIndex].domainName + "<br/>请求数:" + " " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + "<br/>流量:" + teaweb.formatBytes(stats[args.dataIndex].bytes)
},
value: function (v) {
return v.countRequests / axis.divider;
},
axis: axis,
click: function (args, stats) {
window.location = "/ns/domains/domain?domainId=" + stats[args.dataIndex].domainId
}
})
}
})

View File

@@ -0,0 +1,11 @@
.ui.message {
.icon {
position: absolute;
right: 1em;
top: 1.8em;
}
}
.chart-box {
height: 14em;
}