1. 卡片式展示站点数据

2. 增加随机选项,可以自行选择是否随机顺序显示,默认按上传量由大到小排序,同时支持列表,饼图
This commit is contained in:
ngfchl
2022-11-29 14:01:46 +08:00
parent 80d1d8bc91
commit 6976640622
2 changed files with 221 additions and 36 deletions

View File

@@ -563,7 +563,69 @@ def download_tasks():
def site_status_api(request):
my_site_list = MySite.objects.all()
# my_site_list = MySite.objects.all()
# uploaded = 0
# downloaded = 0
# seeding = 0
# seeding_size = 0
# status_list = []
# now = datetime.now()
# for my_site in my_site_list:
# site_info = my_site.sitestatus_set.order_by('-pk').first()
# if not site_info:
# continue
# downloaded += site_info.downloaded
# uploaded += site_info.uploaded
# seeding += my_site.seed
# seeding_size += site_info.seed_vol
# weeks = (now - my_site.time_join).days // 7
# days = (now - my_site.time_join).days % 7
# site_info = {
# 'name': my_site.site.name,
# 'icon': my_site.site.logo,
# 'class': my_site.my_level,
# 'invite': my_site.invitation,
# 'sp_hour': my_site.sp_hour,
# 'seeding': my_site.seed,
# 'time_join': f'{weeks}周 {days}天',
# 'hr': my_site.my_hr,
# 'mail': my_site.mail,
# 'sp': site_info.my_sp,
# 'bonus': site_info.my_bonus,
# # 'uploaded': FileSizeConvert.parse_2_file_size(site_info.uploaded),
# # 'downloaded': FileSizeConvert.parse_2_file_size(site_info.downloaded),
# # 'seeding_size': FileSizeConvert.parse_2_file_size(site_info.seed_vol),
# 'uploaded': site_info.uploaded,
# 'downloaded': site_info.downloaded,
# 'seeding_size': site_info.seed_vol,
# }
# status_list.append(site_info)
# # 按上传量排序
# # status_list.sort(key=lambda x: x['uploaded'], reverse=False)
# # sorted(status_list, key=lambda x: x['uploaded'])
# # 随机乱序
# random.shuffle(status_list)
# total_data = {
# # 'uploaded': FileSizeConvert.parse_2_file_size(uploaded),
# # 'downloaded': FileSizeConvert.parse_2_file_size(downloaded),
# # 'seeding_size': FileSizeConvert.parse_2_file_size(seeding_size),
# 'uploaded': uploaded,
# 'downloaded': downloaded,
# 'seeding_size': seeding_size,
# 'seeding': seeding,
# 'ratio': round(uploaded / downloaded, 3),
# }
# return render(request, 'auto_pt/status.html')
return JsonResponse(data=CommonResponse.success(
data=get_status()
).to_dict(), safe=False)
def get_status(ids: list = None):
if ids is None:
my_site_list = MySite.objects.all()
else:
my_site_list = MySite.objects.filter(pk__in=ids).all()
uploaded = 0
downloaded = 0
seeding = 0
@@ -583,11 +645,16 @@ def site_status_api(request):
site_info = {
'name': my_site.site.name,
'icon': my_site.site.logo,
'url': my_site.site.url,
'class': my_site.my_level,
'invite': my_site.invitation,
'sp_hour': my_site.sp_hour,
'sp_hour_full': '{:.2%}'.format(
float(my_site.sp_hour) / my_site.site.sp_full) if my_site.site.sp_full != 0 else 0,
'seeding': my_site.seed,
'time_join': f'{weeks}{days}',
'leeching': my_site.leech,
'weeks': f'{weeks}{days}',
'time_join': my_site.time_join,
'hr': my_site.my_hr,
'mail': my_site.mail,
'sp': site_info.my_sp,
@@ -601,10 +668,10 @@ def site_status_api(request):
}
status_list.append(site_info)
# 按上传量排序
# status_list.sort(key=lambda x: x['uploaded'], reverse=False)
status_list.sort(key=lambda x: x['uploaded'], reverse=False)
# sorted(status_list, key=lambda x: x['uploaded'])
# 随机乱序
random.shuffle(status_list)
# random.shuffle(status_list)
total_data = {
# 'uploaded': FileSizeConvert.parse_2_file_size(uploaded),
# 'downloaded': FileSizeConvert.parse_2_file_size(downloaded),
@@ -616,13 +683,18 @@ def site_status_api(request):
'ratio': round(uploaded / downloaded, 3),
}
# return render(request, 'auto_pt/status.html')
return JsonResponse(data=CommonResponse.success(
data={
'total_data': total_data, 'status_list': status_list
}
).to_dict(), safe=False)
return {
'total_data': total_data,
'status_list': status_list
}
@login_required
def site_status(request):
return render(request, 'auto_pt/status.html')
def user_data(request):
my_site_list = MySite.objects.all()
return render(request, 'auto_pt/userdata.html')

View File

@@ -13,8 +13,7 @@
}
.box-card {
background-color: #130f2c;
color: #ffefef;
{#background-color: rgba(88, 200, 233, 80%);#}{#color: #ffefef;#}
}
.chart-button {
@@ -27,7 +26,7 @@
<div id="status">
<el-card class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<span>数据总量</span>
<span>站点数据</span>
<span>
<el-button type="warning" size="mini" class="chart-button"
@@ -36,24 +35,111 @@
@click="setBar">柱状图</el-button>
<el-button type="primary" size="mini" class="chart-button"
@click="setPie">饼图</el-button>
<el-switch
class="chart-button"
v-model="begInvite"
active-color="#13ce66"
inactive-text="求药模式"
inactive-color="#ff4949">
</el-switch>
<el-switch
class="chart-button"
v-model="showLegend"
active-color="#13ce66"
inactive-text="图例"
inactive-color="#ff4949">
</el-switch>
<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>
{# <el-switch#}
{# class="chart-button"#}
{# v-model="begInvite"#}
{# active-color="#13ce66"#}
{# inactive-text="求药模式"#}
{# inactive-color="#ff4949">#}
{# </el-switch>#}
{# <el-switch#}
{# class="chart-button"#}
{# v-model="showLegend"#}
{# active-color="#13ce66"#}
{# inactive-text="图例"#}
{# inactive-color="#ff4949">#}
{# </el-switch>#}
{# <el-switch#}
{# class="chart-button"#}
{# v-model="shuffle"#}
{# active-color="#13ce66"#}
{# inactive-text="随机"#}
{# inactive-color="#ff4949">#}
{# </el-switch>#}
</span>
</div>
<div class="body">
<charts ref="charts" style="height: 700px;" :option="option"></charts>
<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">
<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" title="用户等级"></i>
<br v-if="site.hr == 0">
<i class="el-icon-postcard" v-text="site.invite" title="邀请"></i>
<i class="el-icon-date" v-text="' ' + site.weeks"
: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>
{# <span v-text="site.class" title="用户等级"></span>#}
{# <span v-text="site.invite" title="邀请"></span>#}
{# <el-button style="float: right; padding: 3px 0" type="text">更新</el-button>#}
</div>
<div class="text item" style="font-size: 13px;text-align: center;">
<div>
<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>
<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>
<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>
<el-divider>实时数据</el-divider>
{# <div v-text="site.hr.length >0 ? site.hr : 0" style="text-align: center"#}
{# title="H&R"></div>#}
{# <el-divider>H&R</el-divider>#}
</div>
</el-card>
</el-col>
</el-row>
</div>
</div>
</el-card>
</div>
@@ -77,6 +163,10 @@
return size + ' ' + unitArr[index];
}
function shuffle() {
return Math.random() > 0.5 ? -1 : 1;
}
const vm = new Vue({
el: '#status',
data() {
@@ -87,6 +177,8 @@
begInvite: false,
showLogo: false,
showLegend: false,
showList: false,
shuffle: false,
}
},
beforeMount() {
@@ -109,6 +201,7 @@
methods: {
setChartOption(option) {
this.option = option
this.showList = false
this.$refs.charts.chart.clear()
this.$refs.charts.chart.setOption(this.option)
window.addEventListener("resize", () => {
@@ -117,12 +210,29 @@
}
})
},
setCard() {
if (this.chart) {
this.$refs.charts.chart.clear()
}
if (this.shuffle) {
this.ptData.status_list.sort(shuffle)
} else {
this.ptData.status_list.sort((a, b) => {
return b.uploaded - a.uploaded
})
}
this.showList = true
},
setPie() {
let uploadedList = []
let siteList = []
let ptData = this.ptData
let begInvite = !this.begInvite
ptData.status_list.forEach((site, index) => {
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,
@@ -143,20 +253,20 @@
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: '#969696',
color: 'orange',
fontWeight: 'bold',
fontFamily: '黑体',
fontSize: '16',
lineHeight: 32,
},
left: '5%',
top: '10%',
top: '2%',
},
tooltip: {
show: true,
//formatter: function (params) {
// return params.name + '\t' + renderSize(params.data.value)
//}
formatter: function (params) {
return params.name + '\t' + renderSize(params.data.value)
},
valueFormatter: function (value) {
return renderSize(value)
}
@@ -176,6 +286,8 @@
{#type: 'scroll',#}
{#top: 'bottom',#}
right: '2%',
top: '5%',
bottom: '5%',
orient: 'vertical',
data: [],
},
@@ -190,9 +302,9 @@
},
series: [
{
name: 'PT数据展示',
name: '站点数据',
type: 'pie',
bottom: '7%',
bottom: '2%',
radius: '55%',
{#visualDimension: 1,#}
center: ['45%', '50%'],
@@ -420,7 +532,8 @@
console.log(res.data.data)
{#this.ptData = res.data.data#}
this.ptData = res.data.data
this.setPie()
{#this.setPie()#}
this.setCard()
} else {
this.loading = false
this.$message({