mirror of
https://github.com/A-Minos/nonebot-plugin-tetris-stats.git
synced 2026-03-05 05:36:54 +08:00
* 🚧 查数据图初版测试 Co-authored-by: C1ystal <m17687496044@163.com> Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com> * 🙈 添加一些 ignore 文件 * 🎨 格式化代码 * 🐛 修复格式化导致的样式爆炸 * 💄 优化曲线图观感 * 💄 将雷达图的指示器名称旋转显示 * 💄 查数据图第二版 Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com> * ✏️ 修复 typo * 💄 把用户头像文件的引用放到 html 里 * 💄 账户绑定图第一版 Co-authored-by: C1ystal <m17687496044@163.com> Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com> * 🚧 模板化测试 * ➕ 添加依赖 fastapi * ✨ 通过 FastAPI 提供静态文件 * ➕ 添加依赖 jinja2 * 💄 更新数据图模板 (#291) * feat(template): show actual value * feat(template): add user avatar * feat(template): fix radar * feat(style): fix name container width fixed caused display misplacement * feat(style): fix vs value wrap display * feat(template): make check data length in template * feat(template): update radar data * feat(jinja): update data * fix(template): fix typo * feat(style): prevent sign too long * feat(template): turn off echarts animation * chore(deps): add identicon.js * fix(template): fix typo * 🙈 更新.gitignore * 🏗️ 大部分重构为 flex 布局 --------- Co-authored-by: shoucandanghehe <wallfjjd@gmail.com> Co-authored-by: 呵呵です <51957264+shoucandanghehe@users.noreply.github.com> * ➕ 添加依赖 nonebot_plugin_userinfo * ✨ 通过 FastAPI 托管渲染后的模板 * ✨ 新增头像 api 使用 playwright 生成 * ✨ 修正模板资源文件引用路径 被托管后的正确路径 * 💄 将绑定图模板化 * 💄 重命名变量 * 🚚 重命名资源 * ✨ 使用 jinja2 渲染模板 * ✨ 使用 playwright 渲染网页 * 🩹 渲染模板时对 IO 进行一些额外处理 * ➕ 添加依赖 pillow * 🚚 修改托管页面的路由路径 * 💬 优化绑定图文案 * ✨ 新增获取自身网络位置的方法 * 🍱 更新 unknown.svg * ✨ 新增获取用户头像的方法 * ✨ 绑定消息使用图片回复 * ✨ 为 identicon api 添加缓存 * 🔥 删除旧文件 * 🚚 重命名模板 * 📄 添加字体 License * 🙈 更新.gitignore --------- Co-authored-by: C1ystal <m17687496044@163.com> Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com> Co-authored-by: 渣渣120 <WOSHIZHAZHA120@qq.com>
This commit is contained in:
352
nonebot_plugin_tetris_stats/templates/data.j2.html
Normal file
352
nonebot_plugin_tetris_stats/templates/data.j2.html
Normal file
@@ -0,0 +1,352 @@
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title></title>
|
||||
<link href="../../static/css/data.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="main-content">
|
||||
<span class="big-title">Account&Rankings</span>
|
||||
<div id="account-box">
|
||||
<div id="info-box">
|
||||
<div class="flex-gap"></div>
|
||||
<div class="box-shadow box-rounded-corners" id="user-info-box">
|
||||
<img id="user-avatar" src="{{user_avatar}}" />
|
||||
<div id="user-name">{{user_name}}</div>
|
||||
<div id="user-sign">“{{user_sign}}”</div>
|
||||
</div>
|
||||
<div class="flex-gap"></div>
|
||||
<div class="box-shadow box-rounded-corners" id="game-info-box">
|
||||
<div id="game-type-box">
|
||||
<img id="game-logo" src="../../static/static/logo/{{game_type}}.svg" />
|
||||
<span id="game-name">{{game_type}}</span>
|
||||
</div>
|
||||
<div id="game-info-dividing-line"></div>
|
||||
<div id="ranking-info-box">
|
||||
<span id="ranking-title">Ranking</span>
|
||||
<span id="ranking">{{ranking}}</span>
|
||||
<span id="rd">±{{rd}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-gap"></div>
|
||||
</div>
|
||||
<div class="chart-shadow box-rounded-corners" id="TR-curve-chart">
|
||||
<span id="TR-title">Tetra Rating (TR)</span>
|
||||
<img id="rank-icon" src="../../static/static/rank/{{rank}}.svg" />
|
||||
<span id="TR" style="display: flex; align-items: flex-end"
|
||||
>{{TR}}
|
||||
<p style="font-size: 30px; font-weight: 400; line-height: 47px">(#{{global_rank}})</p>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="big-title">Multiplayer Stats</span>
|
||||
<div id="multiplayer-box">
|
||||
<div class="flex-gap"></div>
|
||||
<div id="multiplayer-data-box">
|
||||
<div class="multiplayer-data small-data-box box-shadow box-rounded-corners" id="lpm-box">
|
||||
<span class="big-data-value" id="lpm-value">{{lpm}}</span>
|
||||
<span class="small-data-value" id="pps-value">{{pps}} pps</span>
|
||||
</div>
|
||||
<div class="multiplayer-data small-data-box box-shadow box-rounded-corners" id="apm-box">
|
||||
<span class="big-data-value" id="apm-value">{{apm}}</span>
|
||||
<span class="small-data-value" id="apl-value">x{{apl}}</span>
|
||||
</div>
|
||||
<div class="multiplayer-data small-data-box box-shadow box-rounded-corners" id="adpm-box">
|
||||
<span class="big-data-value" id="adpm-value">{{adpm}}</span>
|
||||
<span class="small-data-value" id="adpl-value">x{{adpl}}</span>
|
||||
<span class="small-data-value" id="vs-value">{{vs}} vs</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-gap"></div>
|
||||
<div class="chart-shadow box-rounded-corners" id="radar-chart"></div>
|
||||
<div class="flex-gap"></div>
|
||||
</div>
|
||||
<span class="big-title">Singleplayer Stats</span>
|
||||
<div id="singleplayer-box">
|
||||
<div class="flex-gap"></div>
|
||||
<div class="small-data-box box-shadow box-rounded-corners" id="sprint-box">
|
||||
<span class="big-data-value" id="sprint-value">{{sprint}}</span>
|
||||
</div>
|
||||
<div class="flex-gap"></div>
|
||||
<div class="small-data-box box-shadow box-rounded-corners" id="blitz-box">
|
||||
<span class="big-data-value" id="blitz-value">{{blitz}}</span>
|
||||
</div>
|
||||
<div class="flex-gap"></div>
|
||||
</div>
|
||||
<div id="footer">Powered by<br />Nonebot2 x nonebot-plugin-tetris-stats</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src="../../static/js/echarts.js"></script>
|
||||
|
||||
<script>
|
||||
var data = {{data}}
|
||||
|
||||
// 曲线图
|
||||
var lineChartDom = document.getElementById('TR-curve-chart');
|
||||
var lineChart = echarts.init(lineChartDom, null, { renderer: 'svg' });
|
||||
var option;
|
||||
|
||||
/** @type EChartsOption */
|
||||
option = {
|
||||
animation: false,
|
||||
grid: {
|
||||
left: '-5%',
|
||||
bottom: '17%',
|
||||
width: '90%',
|
||||
height: '70%',
|
||||
},
|
||||
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
minInterval: 3600 * 48 * 1000,
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: function (value, index) {
|
||||
var date = new Date(value);
|
||||
var lst;
|
||||
var ret;
|
||||
function format_date() {
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
})
|
||||
.format(date)
|
||||
.split('/');
|
||||
}
|
||||
switch (index) {
|
||||
case 0:
|
||||
case 6:
|
||||
ret = '';
|
||||
break;
|
||||
default:
|
||||
lst = format_date();
|
||||
if (index === 5) {
|
||||
ret = '{last_month|' + lst[0] + '}\n{last_day|' + lst[1] + '}';
|
||||
break;
|
||||
}
|
||||
ret = '{month|' + lst[0] + '}\n{day|' + lst[1] + '}';
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
rich: {
|
||||
month: {
|
||||
fontFamily: 'CabinetGrotesk-Variable',
|
||||
fontSize: 13,
|
||||
fontWeight: '400',
|
||||
color: 'rgba(255, 255, 255, 0.6)',
|
||||
},
|
||||
day: {
|
||||
fontFamily: 'CabinetGrotesk-Variable',
|
||||
fontSize: 20,
|
||||
fontWeight: '800',
|
||||
color: 'rgba(255, 255, 255, 0.6)',
|
||||
},
|
||||
last_month: {
|
||||
fontFamily: 'CabinetGrotesk-Variable',
|
||||
fontSize: 13,
|
||||
fontWeight: '400',
|
||||
color: '#373533',
|
||||
backgroundColor: '#FAFAFA',
|
||||
borderRadius: 6,
|
||||
padding: [-10, 0, 10, 0],
|
||||
width: 36,
|
||||
height: 37,
|
||||
lineHeight: 32,
|
||||
},
|
||||
last_day: {
|
||||
fontFamily: 'CabinetGrotesk-Variable',
|
||||
fontSize: 20,
|
||||
fontWeight: '800',
|
||||
color: '#373533',
|
||||
padding: [-18, 0, 0, 0],
|
||||
lineHeight: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
zlevel: 1,
|
||||
},
|
||||
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
interval: {{split_value}},
|
||||
position: 'right',
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
align: 'right',
|
||||
formatter: function (value, index) {
|
||||
return '{value|' + value.toLocaleString() + '}';
|
||||
},
|
||||
rich: {
|
||||
value: {
|
||||
fontFamily: 'CabinetGrotesk-Variable',
|
||||
fontSize: 15,
|
||||
fontWeight: '500',
|
||||
color: 'rgba(255, 255, 255, 0.6)',
|
||||
},
|
||||
},
|
||||
},
|
||||
offset: 70,
|
||||
max: {{value_max+offset}},
|
||||
min: {{value_min-offset}},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
// 10天的数据,最后一天只要第一条 (时间戳最少要多1ms)
|
||||
data: data,
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
symbol: function (value, params) {
|
||||
if (params.dataIndex === data.length - 1) {
|
||||
return 'image://../../static/static/data/point.svg';
|
||||
}
|
||||
return 'none';
|
||||
},
|
||||
symbolSize: 75,
|
||||
symbolOffset: [0.79, 0],
|
||||
lineStyle: {
|
||||
color: '#FAFAFA99',
|
||||
},
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(250, 250, 250, 0.3)',
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(250, 250, 250, 0)',
|
||||
},
|
||||
],
|
||||
global: false,
|
||||
},
|
||||
},
|
||||
markLine: {
|
||||
data: [
|
||||
{
|
||||
xAxis: 'max',
|
||||
y: 300,
|
||||
},
|
||||
],
|
||||
label: {
|
||||
show: false,
|
||||
},
|
||||
lineStyle: {
|
||||
color: '#FAFAFA',
|
||||
width: 3,
|
||||
type: 'dashed',
|
||||
cap: 'round',
|
||||
},
|
||||
symbol: 'none',
|
||||
animation: false,
|
||||
},
|
||||
z: 5,
|
||||
},
|
||||
],
|
||||
};
|
||||
option && lineChart.setOption(option);
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// 雷达图
|
||||
var radarChartDom = document.getElementById('radar-chart');
|
||||
var radarChart = echarts.init(radarChartDom, null, { renderer: 'svg' });
|
||||
var option;
|
||||
|
||||
option = {
|
||||
animation: false,
|
||||
radar: [
|
||||
{
|
||||
indicator: [
|
||||
{ name: 'PPS' },
|
||||
{ name: 'APP', nameRotate: 60 },
|
||||
{ name: 'DSPP', nameRotate: -60 },
|
||||
{ name: 'OR' },
|
||||
{ name: 'CI', nameRotate: 60 },
|
||||
{ name: 'GE', nameRotate: -60 },
|
||||
],
|
||||
center: ['50%', '50%'],
|
||||
radius: '65%',
|
||||
startAngle: 90,
|
||||
splitNumber: 4,
|
||||
shape: 'circle',
|
||||
silent: true,
|
||||
axisName: {
|
||||
color: '#FAFAFA',
|
||||
fontFamily: 'CabinetGrotesk-Variable',
|
||||
fontSize: 15,
|
||||
fontWeight: '800',
|
||||
},
|
||||
splitArea: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: 'rgba(250, 250, 250, 0.3)',
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
rotate: 0,
|
||||
margin: -1,
|
||||
fontFamily: 'CabinetGrotesk-Variable',
|
||||
fontSize: 7,
|
||||
fontWeight: '800',
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: 'rgba(250, 250, 250, 0.3)',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: 'radar',
|
||||
symbol: 'none',
|
||||
label: {
|
||||
show: true,
|
||||
},
|
||||
emphasis: {
|
||||
disabled: true,
|
||||
},
|
||||
lineStyle: {
|
||||
color: '#FAFAFA',
|
||||
width: 2.5,
|
||||
shadowBlur: 20,
|
||||
shadowColor: 'rgba(250, 250, 250, 1)',
|
||||
},
|
||||
areaStyle: {
|
||||
color: 'rgba(250, 250, 250, 0.45)',
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: [{{pps}}, {{app}}, {{dspp}}, {{OR}}, {{ci}}, {{ge}}],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
option && radarChart.setOption(option);
|
||||
</script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user