Files
ptools/templates/auto_pt/status.html
2022-11-30 02:30:46 +08:00

549 lines
23 KiB
HTML

{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
{% include 'admin/includes/css-part.html' %}
<style>
body {
background-color: #2f4155;
background-image: url("{% static 'img/leaf.png' %}");
opacity: 0.95;
}
.info-card {
background-color: rgba(227, 229, 229, 0.6);
border: 2px solid skyblue;
}
.info-card .el-card__header {
background-color: rgba(122, 246, 173, 0.2);
border-bottom: 2px solid skyblue;
}
.info-card .el-card__header a {
color: orangered;
}
.chart-button {
float: right;
margin-right: 5px;
}
</style>
</head>
<body>
<div id="status">
<el-card class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<span>站点数据</span>
<span>
<el-button type="warning" size="mini" class="chart-button"
@click="setTree">矩形树图</el-button>
<el-button type="success" size="mini" class="chart-button"
@click="setBar">柱状图</el-button>
<el-button type="primary" size="mini" class="chart-button"
@click="setPie">饼图</el-button>
<el-button type="info" size="mini" class="chart-button"
@click="setCard">列表</el-button>
<div class="chart-button">
<el-checkbox border fill="#E6A23C" size="mini" v-model="begInvite" label="求药模式"></el-checkbox>
<el-checkbox border fill="#E6A23C" size="mini" v-model="showLegend" label="图例"></el-checkbox>
<el-checkbox border fill="#E6A23C" size="mini" v-model="shuffle" label="随机"></el-checkbox>
</div>
</span>
</div>
<div class="body">
<charts v-if="!showList" ref="charts" style="height: 700px;" :option="option"></charts>
<div v-if="showList">
<el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" style="margin-bottom: 10px;"
v-for="site in ptData.status_list">
<el-card class="box-card info-card">
<div slot="header" class="clearfix">
<div style="float: left;text-align: center;margin-top: -5px;font-size: 14px;height: 32px;">
<img :src="site.icon"
style="width: 16px;border-radius: 50%;margin-bottom: -5px;">
<br>
<a :href="site.url" target="blank" style="margin-top: -5px;">
<div class="el-badge item">
<span v-text="site.name">{}</span>
<sup class="el-badge__content is-fixed" v-if="site.mail > 0"
v-text="site.mail">{}</sup>
</div>
</a>
</div>
&nbsp;
<span style="font-size: 12px;float: right;">
<i class="el-icon-user-solid" v-text="' ' + site.class" style="color: indianred"
title="用户等级"></i>
<br v-if="site.hr == 0">
<i class="el-icon-postcard" v-text="' ' + site.invite" style="color: #003366"
title="邀请"></i>
<i class="el-icon-date" v-text="' ' + site.weeks" style="color: darkgreen"
:title="'加入时间:' + site.time_join"></i>
<br v-if="site.hr != 0">
<i class="el-icon-warning" style="color: orangered" v-if="site.hr!=0" title="H&R"
v-text="' ' + site.hr"></i>
</span>
</div>
<div class="text item" style="font-size: 13px;text-align: right;">
<div>
<span style="float: left;font-weight: bold;color: #3b5769;">数据量:</span>
<i class="el-icon-upload2" style="color: green" title="上传量"
v-text="' ' + renderSize(site.uploaded)"></i> /
<i class="el-icon-download" style="color: indianred" title="下载量"
v-text="' ' + renderSize(site.downloaded)"></i>
<i class="el-icon-share" style="color: saddlebrown" title="分享率"
v-text="' ' + (site.uploaded / site.downloaded).toFixed(2)"></i>
</div>
<el-divider></el-divider>
<div>
<span style="float: left;line-height: 36px;font-weight: bold;color: #3b5769;">魔力/积分:</span>
<i class="el-icon-magic-stick"
v-text="' ' + site.sp + ' / ' + site.bonus"
style="color: orange" title="魔力/积分"></i>
<br>
<i class="el-icon-lollipop" v-text="' ' + site.sp_hour + ' / ' + site.sp_hour_full"
style="color: coral" title="时魔"></i>
</div>
<el-divider></el-divider>
<div>
<span style="float: left;font-weight: bold;color: #3b5769;">实时数据:</span>
<i class="el-icon-upload" title="做种量"
v-text="' ' + renderSize(site.seeding_size)"></i> /
<i class="el-icon-top" style="color: green" title="做种数量"
v-text="' ' + site.seeding"></i> /
<i class="el-icon-bottom" style="color: saddlebrown" title="正在下载"
v-text="' ' + site.leeching"></i>
</div>
</div>
</el-card>
</el-col>
</el-row>
</div>
</div>
</el-card>
</div>
{% include 'admin/includes/js-part.html' %}
<script src="{% static 'admin/simpleui-x/js/axios.min.js' %}"></script>
<script src="{% static 'js/echarts.min.js' %}"></script>
<script src="{% static 'js/echarts-component.js' %}"></script>
<script>
function renderSize(value) {
if (null == value || value == '') {
return 0;
}
var unitArr = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
var index = 0;
var srcsize = parseFloat(value);
index = Math.floor(Math.log(srcsize) / Math.log(1024));
var size = srcsize / Math.pow(1024, index);
size = size.toFixed(2);//保留的小数位数
return size + ' ' + unitArr[index];
}
function shuffle() {
return Math.random() > 0.5 ? -1 : 1;
}
const vm = new Vue({
el: '#status',
data() {
return {
chart: {},
ptData: {},
option: {},
begInvite: false,
showLogo: false,
showLegend: false,
showList: false,
shuffle: false,
}
},
beforeMount() {
},
mounted() {
this.chart = this.$refs.charts.chart
this.getData()
},
watch: {
obj: {
option(newValue, oldValue) {
// option发生变化时自动重新渲染
this.chart.setOption(newValue)
},
// immediate: true,
deep: true,
}
},
methods: {
setChartOption(option) {
this.option = option
this.showList = false
this.$refs.charts.chart.clear()
this.$refs.charts.chart.setOption(this.option)
window.addEventListener("resize", () => {
if (this.$refs.charts.chart) {
this.$refs.charts.chart.resize()
}
})
},
shuffleList() {
if (this.shuffle) {
this.ptData.status_list.sort(() => {
return Math.random() > 0.5 ? -1 : 1
})
} else {
this.ptData.status_list.sort((a, b) => {
if (b.mail == a.mail) {
return b.uploaded - a.uploaded
}
return b.mail - a.mail
})
}
},
setCard() {
if (this.chart) {
this.$refs.charts.chart.clear()
}
//乱序
this.shuffleList()
this.showList = true
},
setPie() {
let uploadedList = []
let siteList = []
let ptData = this.ptData
let begInvite = !this.begInvite
let status_list = ptData.status_list
if (this.shuffle) {
status_list.sort(shuffle)
}
status_list.forEach((site, index) => {
uploadedList.push({
'value': site.uploaded,
'path': 'uploaded/' + site.name,
'name': site.name
})
//downloadedList.push({
// 'value': site.downloaded,
// 'path': 'downloaded/' + site.name,
// 'name': site.name
//})
siteList.push({
name: site.name,
icon: begInvite ? `image://${site.icon}` : 'roundRect'
})
})
let option = {
title: {
text: 'PT站点数据',
subtext: `上传量:${renderSize(ptData.total_data.uploaded)}\n做种量:${renderSize(ptData.total_data.seeding_size)}\n下载量:${renderSize(ptData.total_data.downloaded)}\n分享率:${ptData.total_data.ratio}`,
subtextStyle: {
color: 'orange',
fontWeight: 'bold',
fontFamily: '黑体',
fontSize: '16',
lineHeight: 32,
},
left: '5%',
top: '2%',
},
tooltip: {
show: true,
formatter: function (params) {
return params.name + '\t' + renderSize(params.data.value)
},
valueFormatter: function (value) {
return renderSize(value)
}
},
color: [
'#f66c73',
'#f68645',
'#7af6ad',
'#f4d55f',
'#488ff6',
'#0fba8d',
'#8a47dc',
'#d677f6',
],
legend: {
show: this.showLegend,
{#type: 'scroll',#}
{#top: 'bottom',#}
right: '2%',
top: '5%',
bottom: '5%',
orient: 'vertical',
data: [],
},
toolbox: {
show: true,
feature: {
mark: {show: true},
{#dataView: {show: true, readOnly: false},#}
{#restore: {show: true},#}
saveAsImage: {show: true}
}
},
series: [
{
name: '站点数据',
type: 'pie',
bottom: '2%',
radius: '55%',
{#visualDimension: 1,#}
center: ['45%', '50%'],
roseType: '',
label: {
show: true,
formatter: function (params) {
{#return params.name + ' \t ' + renderSize(params.data.value)#}
return `${begInvite ? params.name : ''} \t ${renderSize(params.data.value)}`
},
itemHeight: 12,
itemWidth: 20
},
itemStyle: {
borderRadius: 7
},
data: [
{value: 40, name: 'rose 1'},
{value: 38, name: 'rose 2'},
{value: 32, name: 'rose 3'},
{value: 30, name: 'rose 4'},
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
option.series[0].data = uploadedList
option.legend.data = siteList
this.setChartOption(option)
},
setTree() {
let ptData = this.ptData
let begInvite = !this.begInvite
let uploadedList = []
let downloadedList = []
ptData.status_list.forEach((site, index) => {
uploadedList.push({
'value': site.uploaded,
'path': 'uploaded/' + site.name,
'name': `${site.name}\t${renderSize(site.uploaded)}`
})
downloadedList.push({
'value': site.downloaded,
'path': 'downloaded/' + site.name,
'name': `${site.name}\t${renderSize(site.downloaded)}`
})
})
let option = {
backgroundColor: '#130f2c',
title: {
text: 'PT站点数据',
subtext: `上传量:${renderSize(ptData.total_data.uploaded)}\t做种量:${renderSize(ptData.total_data.seeding_size)}\t下载量:${renderSize(ptData.total_data.downloaded)}\t分享率:${ptData.total_data.ratio}`,
subtextStyle: {
color: '#969696',
fontWeight: 'bold',
fontFamily: '黑体',
fontSize: '16',
lineHeight: 32,
},
left: '10%',
},
tooltip: {
show: true,
//formatter: function (params) {
// return params.name + '\t' + renderSize(params.data.value)
//}
valueFormatter: function (value) {
return renderSize(value)
}
},
color: [
'#f66c73',
'#f68645',
'#7af6ad',
'#f4d55f',
'#488ff6',
'#0fba8d',
'#8a47dc',
'#d677f6',
'#130f2c',
'#2f4155',
],
toolbox: {
show: true,
feature: {
mark: {show: true},
saveAsImage: {show: true}
}
},
series: [
{
type: 'treemap',
name: '数据汇总',
colorMappingBy: 'index',
{#colorSaturation: [0.9, 0.9],#}
label: {
show: true,
formatter: function (params) {
{#return params.name + '\t' + renderSize(params.data.value)#}
return `${begInvite ? params.name : ''} \t ${renderSize(params.data.value)}`
}
},
data: [
{
name: '上传',
value: 0,
}
]
}
]
}
/**
console.log(this.treeOption.series[0].data)
this.treeOption.series[0].data.push({
name: '总下载',
value: ptData.total_data.downloaded,
})
let treeData = this.treeOption.series[0].data[0]
treeData.value = ptData.total_data.uploaded
treeData.children = dataList
**/
option.series[0].data.push({
name: `总上传\t${renderSize(ptData.total_data.uploaded)}`,
value: ptData.total_data.uploaded,
path: "uploaded",
children: uploadedList
}, {
name: `总下载\t${renderSize(ptData.total_data.downloaded)}`,
value: ptData.total_data.downloaded,
path: "downloaded",
children: downloadedList
})
{#this.treeOption.series[0].data.push()#}
{#this.$refs.charts.chart.setOption(treeOption)#}
this.setChartOption(option)
},
setBar() {
let option = {
title: {
text: 'PT数据聚合图'
},
color: [
'skyblue',
'orange'
],
tooltip: {
trigger: 'axis',
show: true,
axisPointer: {
type: 'shadow'
},
valueFormatter: function (value) {
return renderSize(value)
}
},
legend: {
show: this.showLegend
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: []
},
yAxis: {
type: 'value',
axisLabel: {
formatter: function (value, index) {
return renderSize(value);
}
},
label: {
formatter: function (value, index) {
return renderSize(value);
}
},
boundaryGap: [0, 0.01]
},
series: []
};
let ptData = this.ptData
let uploadedList = []
let downloadedList = []
let siteList = []
{#uploadedList.push(ptData.total_data.uploaded)#}
{#downloadedList.push(ptData.total_data.downloaded)#}
{#siteList.push('总量')#}
ptData.status_list.forEach((site, index) => {
downloadedList.push(site.downloaded)
uploadedList.push(site.uploaded)
siteList.push(site.name)
})
let uploaded = {
name: '上传量',
type: 'bar',
stack: 'Ad',
data: uploadedList
}
let downloaded = {
name: '下载量',
type: 'bar',
stack: 'Ad',
data: downloadedList
}
option.series.push(downloaded, uploaded)
option.xAxis.data = siteList
this.setChartOption(option)
},
getData() {
axios.get(
"{% url "site_status_api" %}"
).then(res => {
console.log('获取数据列表成功', res.data)
if (res.data.code === 0) {
console.log(res.data.data)
{#this.ptData = res.data.data#}
this.ptData = res.data.data
{#this.setPie()#}
this.setCard()
} else {
this.loading = false
this.$message({
type: 'warning',
message: '获取数据列表失败!'
});
}
}).catch(res => {
console.log('获取数据列表失败', res)
this.$message({
type: 'warning',
message: '获取数据列表失败!' + res
});
})
}
}
});
</script>
</body>
</html>