1061 lines
30 KiB
PHP
1061 lines
30 KiB
PHP
|
|
<?php
|
|||
|
|
/**
|
|||
|
|
* 归档页统计、时间、目标进度统计
|
|||
|
|
*
|
|||
|
|
* @package TimeProgressStats
|
|||
|
|
* @author 石头厝
|
|||
|
|
* @version 2.8.0
|
|||
|
|
* @link https://www.shitoucuo.com/
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
|
|||
|
|
|
|||
|
|
class TimeProgressStats_Plugin implements Typecho_Plugin_Interface
|
|||
|
|
{
|
|||
|
|
/**
|
|||
|
|
* 激活插件
|
|||
|
|
*/
|
|||
|
|
public static function activate()
|
|||
|
|
{
|
|||
|
|
Typecho_Plugin::factory('Widget_Archive')->header = array('TimeProgressStats_Plugin', 'header');
|
|||
|
|
Typecho_Plugin::factory('Widget_Archive')->footer = array('TimeProgressStats_Plugin', 'footer');
|
|||
|
|
return '插件已激活';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 禁用插件
|
|||
|
|
*/
|
|||
|
|
public static function deactivate()
|
|||
|
|
{
|
|||
|
|
return '插件已禁用';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 插件配置
|
|||
|
|
*/
|
|||
|
|
public static function config(Typecho_Widget_Helper_Form $form)
|
|||
|
|
{
|
|||
|
|
// 是否开启插件
|
|||
|
|
$enable = new Typecho_Widget_Helper_Form_Element_Radio('enable', array(
|
|||
|
|
'1' => '开启',
|
|||
|
|
'0' => '关闭'
|
|||
|
|
), '1', '是否开启插件', '启用或禁用时间进度统计功能');
|
|||
|
|
$form->addInput($enable);
|
|||
|
|
|
|||
|
|
// 博客建立日期
|
|||
|
|
$blog_start_date = new Typecho_Widget_Helper_Form_Element_Text('blog_start_date', null, date('Y-m-d'),
|
|||
|
|
_t('博客建立日期'), _t('设置博客建立的日期,用于计算运行天数,格式:YYYY-MM-DD'));
|
|||
|
|
$form->addInput($blog_start_date);
|
|||
|
|
|
|||
|
|
// 显示样式设置
|
|||
|
|
$style = new Typecho_Widget_Helper_Form_Element_Radio('style', array(
|
|||
|
|
'card' => '卡片样式',
|
|||
|
|
'simple' => '简洁样式',
|
|||
|
|
'modern' => '现代样式'
|
|||
|
|
), 'card', '显示样式', '选择统计信息的显示样式');
|
|||
|
|
$form->addInput($style);
|
|||
|
|
|
|||
|
|
// 更新速度设置
|
|||
|
|
$updateSpeed = new Typecho_Widget_Helper_Form_Element_Select('update_speed', array(
|
|||
|
|
'100' => '0.1秒(非常流畅)',
|
|||
|
|
'200' => '0.2秒(流畅)',
|
|||
|
|
'500' => '0.5秒(标准)',
|
|||
|
|
'1000' => '1秒(节能)'
|
|||
|
|
), '200', '更新速度', '设置实时更新的速度');
|
|||
|
|
$form->addInput($updateSpeed);
|
|||
|
|
|
|||
|
|
// 显示实时时钟
|
|||
|
|
$showClock = new Typecho_Widget_Helper_Form_Element_Radio('show_clock', array(
|
|||
|
|
'1' => '显示',
|
|||
|
|
'0' => '隐藏'
|
|||
|
|
), '1', '实时时钟', '是否显示实时时钟');
|
|||
|
|
$form->addInput($showClock);
|
|||
|
|
|
|||
|
|
// 今年文章目标
|
|||
|
|
$postGoal = new Typecho_Widget_Helper_Form_Element_Text('post_goal', null, '50',
|
|||
|
|
_t('今年文章目标'), _t('设置今年计划写的文章数量'));
|
|||
|
|
$form->addInput($postGoal);
|
|||
|
|
|
|||
|
|
// 今年字数目标
|
|||
|
|
$charGoal = new Typecho_Widget_Helper_Form_Element_Text('char_goal', null, '100000',
|
|||
|
|
_t('今年字数目标'), _t('设置今年计划写的总字数'));
|
|||
|
|
$form->addInput($charGoal);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 个人配置
|
|||
|
|
*/
|
|||
|
|
public static function personalConfig(Typecho_Widget_Helper_Form $form) {}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取统计数据
|
|||
|
|
*/
|
|||
|
|
public static function getStats()
|
|||
|
|
{
|
|||
|
|
$db = Typecho_Db::get();
|
|||
|
|
$currentYear = date('Y');
|
|||
|
|
$currentMonth = date('n');
|
|||
|
|
|
|||
|
|
// 今年文章
|
|||
|
|
$yearPosts = $db->fetchRow($db->select('COUNT(*) as total')
|
|||
|
|
->from('table.contents')
|
|||
|
|
->where('type = ?', 'post')
|
|||
|
|
->where('status = ?', 'publish')
|
|||
|
|
->where('YEAR(FROM_UNIXTIME(created)) = ?', $currentYear));
|
|||
|
|
|
|||
|
|
// 本月文章
|
|||
|
|
$monthPosts = $db->fetchRow($db->select('COUNT(*) as total')
|
|||
|
|
->from('table.contents')
|
|||
|
|
->where('type = ?', 'post')
|
|||
|
|
->where('status = ?', 'publish')
|
|||
|
|
->where('YEAR(FROM_UNIXTIME(created)) = ?', $currentYear)
|
|||
|
|
->where('MONTH(FROM_UNIXTIME(created)) = ?', $currentMonth));
|
|||
|
|
|
|||
|
|
// 本月字数
|
|||
|
|
$monthChars = $db->fetchRow($db->select('SUM(LENGTH(text)) as total')
|
|||
|
|
->from('table.contents')
|
|||
|
|
->where('type = ?', 'post')
|
|||
|
|
->where('status = ?', 'publish')
|
|||
|
|
->where('YEAR(FROM_UNIXTIME(created)) = ?', $currentYear)
|
|||
|
|
->where('MONTH(FROM_UNIXTIME(created)) = ?', $currentMonth));
|
|||
|
|
|
|||
|
|
// 标签总数
|
|||
|
|
$tags = $db->fetchRow($db->select('COUNT(*) as total')
|
|||
|
|
->from('table.metas')
|
|||
|
|
->where('type = ?', 'tag'));
|
|||
|
|
|
|||
|
|
// 分类总数
|
|||
|
|
$categories = $db->fetchRow($db->select('COUNT(*) as total')
|
|||
|
|
->from('table.metas')
|
|||
|
|
->where('type = ?', 'category'));
|
|||
|
|
|
|||
|
|
// 评论总数(已审核)
|
|||
|
|
$comments = $db->fetchRow($db->select('COUNT(*) as total')
|
|||
|
|
->from('table.comments')
|
|||
|
|
->where('status = ?', 'approved'));
|
|||
|
|
|
|||
|
|
// 文章总数
|
|||
|
|
$totalPosts = $db->fetchRow($db->select('COUNT(*) as total')
|
|||
|
|
->from('table.contents')
|
|||
|
|
->where('type = ?', 'post')
|
|||
|
|
->where('status = ?', 'publish'));
|
|||
|
|
|
|||
|
|
// 累计字数(全部)
|
|||
|
|
$totalChars = $db->fetchRow($db->select('SUM(LENGTH(text)) as total')
|
|||
|
|
->from('table.contents')
|
|||
|
|
->where('type = ?', 'post')
|
|||
|
|
->where('status = ?', 'publish'));
|
|||
|
|
|
|||
|
|
// 今年字数
|
|||
|
|
$yearChars = $db->fetchRow($db->select('SUM(LENGTH(text)) as total')
|
|||
|
|
->from('table.contents')
|
|||
|
|
->where('type = ?', 'post')
|
|||
|
|
->where('status = ?', 'publish')
|
|||
|
|
->where('YEAR(FROM_UNIXTIME(created)) = ?', $currentYear));
|
|||
|
|
|
|||
|
|
return array(
|
|||
|
|
'year_posts' => isset($yearPosts['total']) ? intval($yearPosts['total']) : 0,
|
|||
|
|
'month_posts' => isset($monthPosts['total']) ? intval($monthPosts['total']) : 0,
|
|||
|
|
'month_chars' => isset($monthChars['total']) ? intval($monthChars['total']) : 0,
|
|||
|
|
'total_tags' => isset($tags['total']) ? intval($tags['total']) : 0,
|
|||
|
|
'total_categories' => isset($categories['total']) ? intval($categories['total']) : 0,
|
|||
|
|
'total_comments' => isset($comments['total']) ? intval($comments['total']) : 0,
|
|||
|
|
'total_posts' => isset($totalPosts['total']) ? intval($totalPosts['total']) : 0,
|
|||
|
|
'total_chars' => isset($totalChars['total']) ? intval($totalChars['total']) : 0,
|
|||
|
|
'year_chars' => isset($yearChars['total']) ? intval($yearChars['total']) : 0
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取运行天数
|
|||
|
|
*/
|
|||
|
|
private static function getRunningDays($blogStartDate)
|
|||
|
|
{
|
|||
|
|
try {
|
|||
|
|
$startDate = new DateTime($blogStartDate);
|
|||
|
|
$today = new DateTime();
|
|||
|
|
$interval = $startDate->diff($today);
|
|||
|
|
return $interval->days + 1; // +1 包含今天
|
|||
|
|
} catch (Exception $e) {
|
|||
|
|
// 如果日期格式错误,使用默认值
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 格式化数字
|
|||
|
|
*/
|
|||
|
|
private static function formatNumber($number)
|
|||
|
|
{
|
|||
|
|
$number = intval($number);
|
|||
|
|
if ($number >= 100000000) {
|
|||
|
|
return round($number / 100000000, 2) . '亿';
|
|||
|
|
} elseif ($number >= 10000) {
|
|||
|
|
return round($number / 10000, 1) . '万';
|
|||
|
|
}
|
|||
|
|
return number_format($number);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 渲染统计数据
|
|||
|
|
*/
|
|||
|
|
public static function renderStats($config = null)
|
|||
|
|
{
|
|||
|
|
if (!$config) {
|
|||
|
|
$options = Typecho_Widget::widget('Widget_Options');
|
|||
|
|
$config = $options->plugin('TimeProgressStats');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查插件是否开启
|
|||
|
|
if (isset($config->enable) && $config->enable == '0') {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$stats = self::getStats();
|
|||
|
|
$year = date('Y');
|
|||
|
|
$hour = date('H');
|
|||
|
|
$minute = date('i');
|
|||
|
|
$second = date('s');
|
|||
|
|
|
|||
|
|
// 获取运行天数
|
|||
|
|
$runningDays = 0;
|
|||
|
|
if (isset($config->blog_start_date) && !empty($config->blog_start_date)) {
|
|||
|
|
$runningDays = self::getRunningDays($config->blog_start_date);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 时间计算
|
|||
|
|
$isLeapYear = (($year % 400 == 0) || ($year % 4 == 0 && $year % 100 != 0));
|
|||
|
|
$totalDays = $isLeapYear ? 366 : 365;
|
|||
|
|
$dayOfYear = date('z') + 1;
|
|||
|
|
$remainingDays = $totalDays - $dayOfYear;
|
|||
|
|
|
|||
|
|
// 进度计算
|
|||
|
|
$yearProgress = ($dayOfYear / $totalDays) * 100;
|
|||
|
|
$totalSecondsToday = $hour * 3600 + $minute * 60 + $second;
|
|||
|
|
$dayProgress = ($totalSecondsToday / 86400) * 100;
|
|||
|
|
|
|||
|
|
// 年度目标计算
|
|||
|
|
$postGoal = isset($config->post_goal) ? intval($config->post_goal) : 50;
|
|||
|
|
$charGoal = isset($config->char_goal) ? intval($config->char_goal) : 100000;
|
|||
|
|
|
|||
|
|
// 月度目标计算(年度目标除以12)
|
|||
|
|
$monthPostGoal = ceil($postGoal / 12);
|
|||
|
|
$monthCharGoal = ceil($charGoal / 12);
|
|||
|
|
|
|||
|
|
// 进度计算
|
|||
|
|
$postGoalProgress = $postGoal > 0 ? ($stats['year_posts'] / $postGoal) * 100 : 0;
|
|||
|
|
$charGoalProgress = $charGoal > 0 ? ($stats['year_chars'] / $charGoal) * 100 : 0;
|
|||
|
|
$monthPostGoalProgress = $monthPostGoal > 0 ? ($stats['month_posts'] / $monthPostGoal) * 100 : 0;
|
|||
|
|
$monthCharGoalProgress = $monthCharGoal > 0 ? ($stats['month_chars'] / $monthCharGoal) * 100 : 0;
|
|||
|
|
|
|||
|
|
// 格式化显示
|
|||
|
|
$charsFormatted = self::formatNumber($stats['total_chars']);
|
|||
|
|
$yearCharsFormatted = self::formatNumber($stats['year_chars']);
|
|||
|
|
$monthCharsFormatted = self::formatNumber($stats['month_chars']);
|
|||
|
|
|
|||
|
|
$styleClass = 'tps-card';
|
|||
|
|
if ($config && $config->style) {
|
|||
|
|
$styleClass = 'tps-' . $config->style;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$showClockClass = '';
|
|||
|
|
if ($config && isset($config->show_clock) && $config->show_clock == '1') {
|
|||
|
|
$showClockClass = 'tps-has-clock';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ob_start();
|
|||
|
|
?>
|
|||
|
|
<div class="time-progress-stats <?php echo $styleClass; ?> <?php echo $showClockClass; ?>" id="tps-container">
|
|||
|
|
|
|||
|
|
<div class="tps-header">
|
|||
|
|
<h3>🎯 实时数据</h3>
|
|||
|
|
<div class="tps-time" id="tps-time-display">
|
|||
|
|
<span class="tps-year"><?php echo $year; ?>年</span>
|
|||
|
|
<span class="tps-day">第<?php echo $dayOfYear; ?>天</span>
|
|||
|
|
<span class="tps-remaining">仅剩<?php echo $remainingDays; ?>天</span>
|
|||
|
|
<?php if ($config && isset($config->show_clock) && $config->show_clock == '1'): ?>
|
|||
|
|
<span id="tps-live-clock"><?php echo sprintf('%02d:%02d:%02d', $hour, $minute, $second); ?></span>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="tps-content">
|
|||
|
|
<!-- 新增:站点统计区 -->
|
|||
|
|
<div class="tps-stats-area">
|
|||
|
|
<div class="tps-stats-grid">
|
|||
|
|
<div class="tps-stat-item">
|
|||
|
|
<div class="tps-stat-title">运行天数</div>
|
|||
|
|
<div class="tps-stat-value"><?php echo $runningDays; ?>天</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-stat-item">
|
|||
|
|
<div class="tps-stat-title">分类数量</div>
|
|||
|
|
<div class="tps-stat-value"><?php echo $stats['total_categories']; ?>个</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-stat-item">
|
|||
|
|
<div class="tps-stat-title">标签总数</div>
|
|||
|
|
<div class="tps-stat-value"><?php echo $stats['total_tags']; ?>个</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-stat-item">
|
|||
|
|
<div class="tps-stat-title">文章总数</div>
|
|||
|
|
<div class="tps-stat-value"><?php echo $stats['total_posts']; ?>篇</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="tps-stat-item">
|
|||
|
|
<div class="tps-stat-title">评论总数</div>
|
|||
|
|
<div class="tps-stat-value"><?php echo $stats['total_comments']; ?>条</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-stat-item">
|
|||
|
|
<div class="tps-stat-title">累计字数</div>
|
|||
|
|
<div class="tps-stat-value"><?php echo $charsFormatted; ?>字</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 时间进度区 -->
|
|||
|
|
<div class="tps-progress-area">
|
|||
|
|
<div class="tps-progress-row">
|
|||
|
|
<div class="tps-progress-info">
|
|||
|
|
<span class="tps-progress-title">今年进度</span>
|
|||
|
|
<span class="tps-progress-percent" id="tps-year-percent"><?php echo number_format($yearProgress, 6); ?>%</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-progress-track">
|
|||
|
|
<div class="tps-progress-fill" id="tps-year-bar" style="width: <?php echo min($yearProgress, 100); ?>%"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="tps-progress-row">
|
|||
|
|
<div class="tps-progress-info">
|
|||
|
|
<span class="tps-progress-title">今日进度</span>
|
|||
|
|
<span class="tps-progress-percent" id="tps-day-percent"><?php echo number_format($dayProgress, 6); ?>%</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-progress-track">
|
|||
|
|
<div class="tps-progress-fill" id="tps-day-bar" style="width: <?php echo min($dayProgress, 100); ?>%"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 年度目标进度区 -->
|
|||
|
|
<div class="tps-goal-area">
|
|||
|
|
<div class="tps-goal-row">
|
|||
|
|
<div class="tps-goal-info">
|
|||
|
|
<span class="tps-goal-title">今年文章</span>
|
|||
|
|
<span class="tps-goal-status"><?php echo $stats['year_posts']; ?>篇 / <?php echo $postGoal; ?>篇</span>
|
|||
|
|
<span class="tps-goal-percent"><?php echo number_format($postGoalProgress, 1); ?>%</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-progress-track tps-goal-track">
|
|||
|
|
<div class="tps-goal-fill" style="width: <?php echo min($postGoalProgress, 100); ?>%"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="tps-goal-row">
|
|||
|
|
<div class="tps-goal-info">
|
|||
|
|
<span class="tps-goal-title">今年字数</span>
|
|||
|
|
<span class="tps-goal-status"><?php echo $yearCharsFormatted; ?> / <?php echo self::formatNumber($charGoal); ?></span>
|
|||
|
|
<span class="tps-goal-percent"><?php echo number_format($charGoalProgress, 1); ?>%</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-progress-track tps-goal-track">
|
|||
|
|
<div class="tps-goal-fill" style="width: <?php echo min($charGoalProgress, 100); ?>%"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 月度目标进度区 -->
|
|||
|
|
<div class="tps-month-goal-area">
|
|||
|
|
<div class="tps-month-goal-row">
|
|||
|
|
<div class="tps-month-goal-info">
|
|||
|
|
<span class="tps-month-goal-title">本月文章</span>
|
|||
|
|
<span class="tps-month-goal-status"><?php echo $stats['month_posts']; ?>篇 / <?php echo $monthPostGoal; ?>篇</span>
|
|||
|
|
<span class="tps-month-goal-percent"><?php echo number_format($monthPostGoalProgress, 1); ?>%</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-progress-track tps-month-goal-track">
|
|||
|
|
<div class="tps-month-goal-fill" style="width: <?php echo min($monthPostGoalProgress, 100); ?>%"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="tps-month-goal-row">
|
|||
|
|
<div class="tps-month-goal-info">
|
|||
|
|
<span class="tps-month-goal-title">本月字数</span>
|
|||
|
|
<span class="tps-month-goal-status"><?php echo $monthCharsFormatted; ?> / <?php echo self::formatNumber($monthCharGoal); ?></span>
|
|||
|
|
<span class="tps-month-goal-percent"><?php echo number_format($monthCharGoalProgress, 1); ?>%</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="tps-progress-track tps-month-goal-track">
|
|||
|
|
<div class="tps-month-goal-fill" style="width: <?php echo min($monthCharGoalProgress, 100); ?>%"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
// 时间进度实时更新系统 - 完善版
|
|||
|
|
(function() {
|
|||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
function initTimeProgress() {
|
|||
|
|
var container = document.getElementById('tps-container');
|
|||
|
|
if (!container) return;
|
|||
|
|
|
|||
|
|
// 核心更新函数
|
|||
|
|
function updateTimeProgress() {
|
|||
|
|
var now = new Date();
|
|||
|
|
var year = now.getFullYear();
|
|||
|
|
var hours = now.getHours();
|
|||
|
|
var minutes = now.getMinutes();
|
|||
|
|
var seconds = now.getSeconds();
|
|||
|
|
var milliseconds = now.getMilliseconds();
|
|||
|
|
|
|||
|
|
// 更新时钟
|
|||
|
|
var clock = document.getElementById('tps-live-clock');
|
|||
|
|
if (clock) {
|
|||
|
|
clock.textContent = padZero(hours) + ':' + padZero(minutes) + ':' + padZero(seconds);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 计算今年进度
|
|||
|
|
var startOfYear = new Date(year, 0, 1);
|
|||
|
|
var msPassed = now.getTime() - startOfYear.getTime();
|
|||
|
|
var daysPassed = msPassed / (1000 * 60 * 60 * 24);
|
|||
|
|
|
|||
|
|
var isLeapYear = (year % 400 === 0) || (year % 4 === 0 && year % 100 !== 0);
|
|||
|
|
var totalDays = isLeapYear ? 366 : 365;
|
|||
|
|
var yearProgress = (daysPassed / totalDays) * 100;
|
|||
|
|
|
|||
|
|
// 计算今天进度
|
|||
|
|
var msPassedToday = (hours * 3600 + minutes * 60 + seconds) * 1000 + milliseconds;
|
|||
|
|
var dayProgress = (msPassedToday / 86400000) * 100;
|
|||
|
|
|
|||
|
|
// 更新显示
|
|||
|
|
var yearPercent = document.getElementById('tps-year-percent');
|
|||
|
|
var dayPercent = document.getElementById('tps-day-percent');
|
|||
|
|
var yearBar = document.getElementById('tps-year-bar');
|
|||
|
|
var dayBar = document.getElementById('tps-day-bar');
|
|||
|
|
|
|||
|
|
if (yearPercent) yearPercent.textContent = yearProgress.toFixed(6) + '%';
|
|||
|
|
if (yearBar) yearBar.style.width = Math.min(yearProgress, 100) + '%';
|
|||
|
|
if (dayPercent) dayPercent.textContent = dayProgress.toFixed(6) + '%';
|
|||
|
|
if (dayBar) dayBar.style.width = Math.min(dayProgress, 100) + '%';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function padZero(num) {
|
|||
|
|
return (num < 10 ? '0' : '') + num;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 立即执行一次
|
|||
|
|
updateTimeProgress();
|
|||
|
|
|
|||
|
|
// 启动定时器
|
|||
|
|
setInterval(updateTimeProgress, 200);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 页面加载完成后初始化
|
|||
|
|
if (document.readyState === 'loading') {
|
|||
|
|
document.addEventListener('DOMContentLoaded', initTimeProgress);
|
|||
|
|
} else {
|
|||
|
|
initTimeProgress();
|
|||
|
|
}
|
|||
|
|
})();
|
|||
|
|
</script>
|
|||
|
|
<?php
|
|||
|
|
return ob_get_clean();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 头部样式
|
|||
|
|
*/
|
|||
|
|
public static function header()
|
|||
|
|
{
|
|||
|
|
?>
|
|||
|
|
<style>
|
|||
|
|
/* 时间进度统计组件深色模式适配 */
|
|||
|
|
.dark .time-stats-container,
|
|||
|
|
.dark div[class*="time-stats"],
|
|||
|
|
.dark div[class*="time-progress"] {
|
|||
|
|
background: rgb(10 12 25 / var(--tw-bg-opacity))!important;
|
|||
|
|
color: #e2e8f0 !important;
|
|||
|
|
border-color: rgba(255, 255, 255, 0.1) !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dark .time-stats-title,
|
|||
|
|
.dark h2[class*="time-stats"],
|
|||
|
|
.dark h3[class*="time-stats"] {
|
|||
|
|
color: #e2e8f0 !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dark .time-stat-item,
|
|||
|
|
.dark div[class*="stat-item"] {
|
|||
|
|
background: rgba(30, 35, 50, 0.8) !important;
|
|||
|
|
color: #cbd5e0 !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dark .time-progress-bar,
|
|||
|
|
.dark div[class*="progress-bar"] {
|
|||
|
|
background: rgba(255, 255, 255, 0.1) !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dark .time-progress-fill,
|
|||
|
|
.dark div[class*="progress-fill"] {
|
|||
|
|
background: linear-gradient(90deg, #f15a22, #ff8c42) !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dark .time-progress-value,
|
|||
|
|
.dark span[class*="progress-value"],
|
|||
|
|
.dark span[class*="stat-value"] {
|
|||
|
|
color: #cbd5e0 !important;
|
|||
|
|
}
|
|||
|
|
.dark .tps-month-goal-area,
|
|||
|
|
.dark .tps-progress-area,
|
|||
|
|
.dark .tps-goal-area,
|
|||
|
|
.dark .tps-stats-area {
|
|||
|
|
background-color: hsl(0 0% 15%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dark .time-stat-label,
|
|||
|
|
.dark span[class*="stat-label"] {
|
|||
|
|
color: #a0aec0 !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dark .time-stat-description,
|
|||
|
|
.dark p[class*="stat-description"] {
|
|||
|
|
color: #94a3b8 !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 通用深色模式文本颜色 */
|
|||
|
|
.dark .dark\\:text-gray-400 {
|
|||
|
|
color: #9ca3af !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dark .dark\\:text-neutral-300 {
|
|||
|
|
color: #d1d5db !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 基础容器 - 增加上边距 */
|
|||
|
|
.time-progress-stats {
|
|||
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|||
|
|
margin: 30px 0 20px 0;
|
|||
|
|
border-radius: 12px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-card {
|
|||
|
|
background: #eee;
|
|||
|
|
color: #666;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple {
|
|||
|
|
background: #ffffff;
|
|||
|
|
border: 1px solid #e1e8ed;
|
|||
|
|
color: #333;
|
|||
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern {
|
|||
|
|
background: linear-gradient(135deg, #141e30 0%, #243b55 100%);
|
|||
|
|
color: #fff;
|
|||
|
|
border: 1px solid #2c3e50;
|
|||
|
|
}
|
|||
|
|
.dark .tps-header{
|
|||
|
|
background: rgb(10 12 25 / var(--tw-bg-opacity));
|
|||
|
|
}
|
|||
|
|
.tps-header {
|
|||
|
|
padding: 18px 24px;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|||
|
|
background: #eee;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-header {
|
|||
|
|
border-bottom: 1px solid #e1e8ed;
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-header {
|
|||
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|||
|
|
background: rgba(0, 0, 0, 0.2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-header h3 {
|
|||
|
|
margin: 0;
|
|||
|
|
font-size: 1.5em;
|
|||
|
|
font-weight: 600;
|
|||
|
|
display: flex; /* 添加这行 */
|
|||
|
|
align-items: center; /* 添加这行 */
|
|||
|
|
gap: 8px; /* 添加这行,调整图标和文字间距 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#tps-time-display {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-family: 'Courier New', monospace;
|
|||
|
|
text-align: right;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-year,
|
|||
|
|
.tps-day,
|
|||
|
|
.tps-remaining {
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-remaining {
|
|||
|
|
color: #ff6b6b;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-remaining {
|
|||
|
|
color: #ff4757;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-remaining {
|
|||
|
|
color: #ff6b6b;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#tps-live-clock {
|
|||
|
|
color: #00ff88;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple #tps-live-clock {
|
|||
|
|
color: #1890ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern #tps-live-clock {
|
|||
|
|
color: #00c6ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-content {
|
|||
|
|
padding: 20px 20px 0px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 新增:站点统计区样式 */
|
|||
|
|
.tps-stats-area {
|
|||
|
|
margin-bottom: 25px;
|
|||
|
|
padding: 20px;
|
|||
|
|
background: #faf8f1;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.15);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-stats-area {
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
border: 1px solid #e1e8ed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-stats-area {
|
|||
|
|
background: rgba(255, 255, 255, 0.03);
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.05);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-stats-grid {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: repeat(3, 1fr);
|
|||
|
|
gap: 15px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-stat-item {
|
|||
|
|
padding: 15px;
|
|||
|
|
background:#eee;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
text-align: center;
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|||
|
|
transition: all 0.3s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-stat-item:hover {
|
|||
|
|
transform: translateY(-2px);
|
|||
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-stat-item {
|
|||
|
|
background: #ffffff;
|
|||
|
|
border: 1px solid #e1e8ed;
|
|||
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-stat-item:hover {
|
|||
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-stat-item {
|
|||
|
|
background: rgba(255, 255, 255, 0.05);
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|||
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.dark .tps-stat-title{color:#fff;}
|
|||
|
|
.tps-stat-title {
|
|||
|
|
font-size: 13px;
|
|||
|
|
opacity: 0.9;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
color: #666;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-stat-title {
|
|||
|
|
color: #666;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-stat-title {
|
|||
|
|
color: rgba(255, 255, 255, 0.8);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-stat-value {
|
|||
|
|
font-size: 18px;
|
|||
|
|
font-weight: bold;
|
|||
|
|
color: #f15a22;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-stat-value {
|
|||
|
|
color: #1890ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-stat-value {
|
|||
|
|
color: #00c6ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-progress-area {
|
|||
|
|
margin-bottom: 25px;
|
|||
|
|
padding: 20px;
|
|||
|
|
background: #faf8f1;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.15);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-progress-row:last-child {
|
|||
|
|
margin-bottom: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-progress-row {
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-progress-info {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-progress-title {
|
|||
|
|
font-size: 15px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 时间进度百分比颜色 - 与进度条颜色保持一致 */
|
|||
|
|
.tps-progress-percent {
|
|||
|
|
font-family: 'Courier New', monospace;
|
|||
|
|
font-size: 16px;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 卡片样式时间进度百分比颜色 */
|
|||
|
|
.tps-card .tps-progress-percent {
|
|||
|
|
color: #f15a22; /* 与进度条左侧颜色一致 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-progress-percent {
|
|||
|
|
color: #1890ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-progress-percent {
|
|||
|
|
color: #00c6ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-progress-track {
|
|||
|
|
height: 10px;
|
|||
|
|
background: rgba(255, 255, 255, 0.1);
|
|||
|
|
border-radius: 5px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
margin-bottom: 6px;
|
|||
|
|
position: relative;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-progress-track {
|
|||
|
|
background: #f0f0f0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-progress-track {
|
|||
|
|
background: rgba(255, 255, 255, 0.05);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-progress-fill {
|
|||
|
|
height: 100%;
|
|||
|
|
border-radius: 5px;
|
|||
|
|
transition: width 0.1s linear !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 时间进度条颜色 */
|
|||
|
|
.tps-card .tps-progress-fill {
|
|||
|
|
background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-progress-fill {
|
|||
|
|
background: linear-gradient(90deg, #1890ff 0%, #36cfc9 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-progress-fill {
|
|||
|
|
background: linear-gradient(90deg, #00c6ff 0%, #0072ff 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-progress-detail {
|
|||
|
|
font-size: 13px;
|
|||
|
|
opacity: 0.9;
|
|||
|
|
text-align: center;
|
|||
|
|
color: rgba(255, 255, 255, 0.8);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-progress-detail {
|
|||
|
|
color: #666;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-progress-detail {
|
|||
|
|
color: rgba(255, 255, 255, 0.7);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 年度目标区域样式 */
|
|||
|
|
.tps-goal-area {
|
|||
|
|
margin-bottom: 25px;
|
|||
|
|
padding: 20px;
|
|||
|
|
background: #faf8f1;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-goal-area {
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
border: 1px solid #e1e8ed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-goal-area {
|
|||
|
|
background: rgba(255, 255, 255, 0.03);
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.05);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-goal-row {
|
|||
|
|
margin-bottom: 15px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-goal-row:last-child {
|
|||
|
|
margin-bottom: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-goal-info {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-goal-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-goal-status {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
margin: 0 10px;
|
|||
|
|
font-family: 'Courier New', monospace;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 年度目标百分比颜色 - 与进度条颜色保持一致 */
|
|||
|
|
.tps-goal-percent {
|
|||
|
|
font-family: 'Courier New', monospace;
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: bold;
|
|||
|
|
min-width: 50px;
|
|||
|
|
text-align: right;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 卡片样式年度目标百分比颜色 */
|
|||
|
|
.tps-card .tps-goal-percent {
|
|||
|
|
color: #ffd166; /* 与进度条左侧颜色一致 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-goal-percent {
|
|||
|
|
color: #ffd166;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-goal-percent {
|
|||
|
|
color: #ffd166;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-goal-track {
|
|||
|
|
position: relative;
|
|||
|
|
overflow: visible;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-goal-fill {
|
|||
|
|
height: 100%;
|
|||
|
|
border-radius: 5px;
|
|||
|
|
background: linear-gradient(90deg, #ffd166 0%, #ff9e6d 100%);
|
|||
|
|
max-width: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-goal-fill {
|
|||
|
|
background: linear-gradient(90deg, #ffd166 0%, #ff9e6d 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-goal-fill {
|
|||
|
|
background: linear-gradient(90deg, #ffd166 0%, #ff9e6d 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 月度目标区域样式 */
|
|||
|
|
.tps-month-goal-area {
|
|||
|
|
margin-bottom: 25px;
|
|||
|
|
padding: 20px;
|
|||
|
|
background:#faf8f1;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-month-goal-area {
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
border: 1px solid #e1e8ed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-month-goal-area {
|
|||
|
|
background: rgba(255, 255, 255, 0.03);
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.05);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-month-goal-row {
|
|||
|
|
margin-bottom: 15px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-month-goal-row:last-child {
|
|||
|
|
margin-bottom: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-month-goal-info {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-month-goal-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-month-goal-status {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
margin: 0 10px;
|
|||
|
|
font-family: 'Courier New', monospace;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 月度目标百分比颜色 - 与进度条颜色保持一致(偏橙色) */
|
|||
|
|
.tps-month-goal-percent {
|
|||
|
|
font-family: 'Courier New', monospace;
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: bold;
|
|||
|
|
min-width: 50px;
|
|||
|
|
text-align: right;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 卡片样式月度目标百分比颜色 */
|
|||
|
|
.tps-card .tps-month-goal-percent {
|
|||
|
|
color: #ff9500; /* 橙色系 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-month-goal-percent {
|
|||
|
|
color: #ff9500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-month-goal-percent {
|
|||
|
|
color: #ff9500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-month-goal-track {
|
|||
|
|
position: relative;
|
|||
|
|
overflow: visible;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-month-goal-fill {
|
|||
|
|
height: 100%;
|
|||
|
|
border-radius: 5px;
|
|||
|
|
background: linear-gradient(90deg, #ffb347 0%, #ff9500 100%); /* 偏橙色的渐变 */
|
|||
|
|
max-width: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-simple .tps-month-goal-fill {
|
|||
|
|
background: linear-gradient(90deg, #ffb347 0%, #ff9500 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-modern .tps-month-goal-fill {
|
|||
|
|
background: linear-gradient(90deg, #ffb347 0%, #ff9500 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@media (max-width: 768px) {
|
|||
|
|
.time-progress-stats {
|
|||
|
|
margin: 25px 0 15px 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-stats-grid {
|
|||
|
|
grid-template-columns: repeat(2, 1fr);
|
|||
|
|
gap: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-header {
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
gap: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#tps-time-display {
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
gap: 8px;
|
|||
|
|
text-align: left;
|
|||
|
|
justify-content: flex-start;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-content,
|
|||
|
|
.tps-header {
|
|||
|
|
padding: 18px !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-goal-info {
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-goal-status {
|
|||
|
|
order: 3;
|
|||
|
|
width: 100%;
|
|||
|
|
text-align: center;
|
|||
|
|
margin: 5px 0 0 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-month-goal-info {
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tps-month-goal-status {
|
|||
|
|
order: 3;
|
|||
|
|
width: 100%;
|
|||
|
|
text-align: center;
|
|||
|
|
margin: 5px 0 0 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@media (max-width: 480px) {
|
|||
|
|
.tps-stats-grid {
|
|||
|
|
grid-template-columns: 1fr;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
<?php
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 底部脚本
|
|||
|
|
*/
|
|||
|
|
public static function footer()
|
|||
|
|
{
|
|||
|
|
// 空函数,JavaScript已内联在HTML中
|
|||
|
|
}
|
|||
|
|
}
|