{% extends "base.html" %} {% block title %}控制台 - Amrita Dashboard{% endblock
%} {% block extra_css %}
<style>
  .stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 20px;
    margin-bottom: 30px;
  }

  .stat-card {
    background: white;
    border-radius: 10px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
    padding: 20px;
    display: flex;
    align-items: center;
    transition: transform 0.3s, box-shadow 0.3s;
  }

  .stat-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
  }

  .stat-icon {
    width: 50px;
    height: 50px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 15px;
    font-size: 24px;
  }

  .stat-icon.blue {
    background: rgba(138, 43, 226, 0.1);
    color: var(--primary-color);
  }

  .stat-icon.green {
    background: rgba(46, 204, 113, 0.1);
    color: #2ecc71;
  }

  .stat-icon.orange {
    background: rgba(243, 156, 18, 0.1);
    color: #f39c12;
  }

  .stat-icon.purple {
    background: rgba(155, 89, 182, 0.1);
    color: #9b59b6;
  }

  .stat-info h3 {
    font-size: 24px;
    margin-bottom: 5px;
  }

  .stat-info p {
    color: #777;
    font-size: 14px;
  }

  .charts-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 20px;
    margin-bottom: 30px;
  }

  .chart-card {
    background: white;
    border-radius: 10px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
    padding: 20px;
  }

  .chart-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
  }

  .chart-title {
    font-size: 18px;
    font-weight: 600;
  }

  .chart-actions button {
    background: none;
    border: none;
    color: #777;
    cursor: pointer;
    margin-left: 10px;
    padding: 5px;
    border-radius: 4px;
    transition: background 0.3s;
  }

  .chart-actions button:hover {
    background: #f0f0f0;
  }

  .chart-container {
    height: 300px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f8f9fa;
    border-radius: 8px;
  }

  .chart-placeholder {
    text-align: center;
    color: #777;
  }

  .chart-placeholder i {
    font-size: 48px;
    margin-bottom: 15px;
    color: #ddd;
  }

  .recent-activity {
    background: white;
    border-radius: 10px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
    padding: 20px;
  }

  .activity-list {
    list-style: none;
  }

  .activity-item {
    display: flex;
    padding: 15px 0;
    border-bottom: 1px solid #eee;
  }

  .activity-item:last-child {
    border-bottom: none;
  }

  .activity-icon {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 15px;
    flex-shrink: 0;
  }

  .activity-icon.yellow {
    background: rgba(243, 156, 18, 0.1);
    color: #f39c12;
  }
  .activity-icon.purple {
    background: rgba(155, 89, 182, 0.1);
    color: #9b59b6;
  }
  .activity-icon.red {
    background: rgba(231, 76, 60, 0.1);
    color: #e74c3c;
  }
  .activity-icon.blue {
    background: rgba(52, 152, 219, 0.1);
    color: #3498db;
  }

  .activity-icon.green {
    background: rgba(46, 204, 113, 0.1);
    color: #2ecc71;
  }

  .activity-icon.orange {
    background: rgba(243, 156, 18, 0.1);
    color: #f39c12;
  }

  .activity-content {
    flex: 1;
  }

  .activity-title {
    font-weight: 500;
    margin-bottom: 5px;
  }

  .activity-desc {
    color: #777;
    font-size: 14px;
    margin-bottom: 5px;
  }

  .activity-time {
    color: #aaa;
    font-size: 12px;
  }

  /* 响应式设计 */
  @media (max-width: 768px) {
    .charts-grid {
      grid-template-columns: 1fr;
    }

    .stats-grid {
      grid-template-columns: 1fr;
    }

    .stat-card {
      flex-direction: row;
    }
  }

  @media (max-width: 480px) {
    .stats-grid {
      grid-template-columns: 1fr;
    }
  }

  /* 桌面端横向排列优化 */
  @media (min-width: 769px) {
    .stats-grid {
      grid-template-columns: repeat(4, 1fr);
    }
  }

  /* 图表容器 */
  .chart-canvas-container {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .chart-canvas {
    max-width: 100%;
    max-height: 100%;
  }
</style>
{% endblock %} {% block content %}
<div class="stats-grid">
  <div class="stat-card">
    <div class="stat-icon blue">
      <i class="fas fa-robot"></i>
    </div>
    <div class="stat-info">
      <h3>{{ loaded_plugins }}</h3>
      <p>已加载插件</p>
    </div>
  </div>
  <div class="stat-card">
    <div class="stat-icon green">
      <i class="fas fa-users"></i>
    </div>
    <div class="stat-info">
      <h3>{{bot_connected}}</h3>
      <p>Bot已连接</p>
    </div>
  </div>
  <div class="stat-card">
    <div class="stat-icon orange">
      <i class="fas fa-comments"></i>
    </div>
    <div class="stat-info">
      <h3>{{total_message}}</h3>
      <p>今日消息</p>
    </div>
  </div>
  <div class="stat-card">
    <div class="stat-icon purple">
      <i class="fas fa-microchip"></i>
    </div>
    <div class="stat-info">
      <h3>{{health}}</h3>
      <p>系统健康</p>
    </div>
  </div>
</div>

<div class="charts-grid">
  <div class="chart-card">
    <div class="chart-header">
      <div class="chart-title">消息统计</div>
      <div class="chart-actions">
        <button><i class="fas fa-sync"></i></button>
        <button><i class="fas fa-cog"></i></button>
      </div>
    </div>
    <div class="chart-container">
      <div class="chart-canvas-container">
        <canvas id="messagesChart" class="chart-canvas"></canvas>
      </div>
    </div>
  </div>
  <div class="chart-card">
    <div class="chart-header">
      <div class="chart-title">收发图表</div>
      <div class="chart-actions">
        <button><i class="fas fa-sync"></i></button>
      </div>
    </div>
    <div class="chart-container">
      <div class="chart-canvas-container">
        <canvas id="botMsgStatusChart" class="chart-canvas"></canvas>
      </div>
    </div>
  </div>
</div>

<div class="recent-activity">
  <div class="chart-header">
    <div class="chart-title">最近活动</div>
  </div>
  <ul class="activity-list">
    {% for activity in recent_activity %}
    <li class="activity-item">
      <div class="activity-icon {{activity.icon_color}}">
        <i class="fas fa-{{activity.icon}}"></i>
      </div>
      <div class="activity-content">
        <div class="activity-title">{{activity.title}}</div>
        <div class="activity-desc">{{activity.desc}}</div>
        <div class="activity-time">{{activity.time}}</div>
      </div>
    </li>
    {% endfor %}
  </ul>
</div>
{% endblock %} {% block scripts %}
<script>
  const urlParams = new URLSearchParams(window.location.search);
  if (urlParams.get('warn') === 'weak_password') {
                  Swal.fire({
                      icon: 'warning',
                      title: '密码强度不足',
                      text: '请尽快更换密码！',
                  });
              }

  // 全局变量存储图表实例
  let messagesChart;
  let botMsgStatusChart;

  // 页面加载完成后初始化图表
  document.addEventListener('DOMContentLoaded', function() {
      // 初始化图表
      initCharts();

      // 绑定按钮事件
      bindButtonEvents();
  });

  // 初始化图表函数
  function initCharts() {
      // 消息统计图表
      const messagesCtx = document.getElementById('messagesChart').getContext('2d');
      messagesChart = new Chart(messagesCtx, {
          type: 'line',
          data: {
              labels: {{ message_stats.labels | tojson }},
              datasets: [{
                  label: '消息数量',
                  data: {{ message_stats.data | tojson }},
                  borderColor: 'rgb(138, 43, 226)',
                  backgroundColor: 'rgba(138, 43, 226, 0.2)',
                  tension: 0.1
              }]
          },
          options: {
              responsive: true,
              maintainAspectRatio: false,
              scales: {
                  y: {
                      beginAtZero: true
                  }
              }
          }
      });

      // 系统状态图表
      const msgIOStatusCtx = document.getElementById('botMsgStatusChart').getContext('2d');
      botMsgStatusChart = new Chart(msgIOStatusCtx, {
          type: 'doughnut',
          data: {
              labels: {{ msg_io_status.labels | tojson }},
              datasets: [{
                  label: '消息收发状态',
                  data: {{ msg_io_status.data | tojson }},
                  backgroundColor: [
                      'rgb(138, 43, 226)',
                      'rgb(46, 204, 113)',
                  ],
                  hoverOffset: 4
              }]
          },
          options: {
              responsive: true,
              maintainAspectRatio: false
          }
      });
  }

  // 绑定按钮事件
  function bindButtonEvents() {
      // 为所有刷新按钮绑定事件
      document.querySelectorAll('.fa-sync').forEach(button => {
          button.addEventListener('click', function() {
              const chartCard = this.closest('.chart-card');
              const chartTitle = chartCard.querySelector('.chart-title').textContent;

              // 显示刷新提示
              Swal.fire({
                  title: '刷新中...',
                  text: `正在刷新${chartTitle}数据`,
                  allowOutsideClick: false,
                  didOpen: () => {
                      Swal.showLoading();
                  }
              });

              // 获取真实数据并更新图表
              refreshChartData(chartTitle)
                  .then(() => {
                      Swal.close();
                      Swal.fire({
                          title: '刷新成功',
                          text: `${chartTitle}数据已更新`,
                          icon: 'success',
                          timer: 1500,
                          showConfirmButton: false
                      });
                  })
                  .catch(() => {
                      Swal.close();
                      Swal.fire({
                          title: '刷新失败',
                          text: `无法获取${chartTitle}数据`,
                          icon: 'error',
                          timer: 1500,
                          showConfirmButton: false
                      });
                  });
          });
      });

      // 为所有设置按钮绑定事件
      document.querySelectorAll('.fa-cog').forEach(button => {
          button.addEventListener('click', function() {
              const chartCard = this.closest('.chart-card');
              const chartTitle = chartCard.querySelector('.chart-title').textContent;

              // 显示设置对话框
              Swal.fire({
                  title: `${chartTitle}设置`,
                  html: `
                      <div style="text-align: left;">
                          <p>图表设置选项：</p>
                          <div>
                              <input type="checkbox" id="showLegend" checked>
                              <label for="showLegend">显示图例</label>
                          </div>
                          <div>
                              <input type="checkbox" id="animateChart" checked>
                              <label for="animateChart">启用动画</label>
                          </div>
                          <div>
                              <label for="chartColor">图表颜色：</label>
                              <select id="chartColor">
                                  <option value="default">默认</option>
                                  <option value="blue">蓝色</option>
                                  <option value="green">绿色</option>
                                  <option value="orange">橙色</option>
                              </select>
                          </div>
                      </div>
                  `,
                  showCancelButton: true,
                  confirmButtonText: '应用',
                  cancelButtonText: '取消'
              }).then((result) => {
                  if (result.isConfirmed) {
                      Swal.fire({
                          title: '设置已保存',
                          text: `已更新${chartTitle}的设置`,
                          icon: 'success',
                          timer: 1500,
                          showConfirmButton: false
                      });
                  }
              });
          });
      });
  }

  // 刷新图表数据函数 - 使用API获取真实数据
  async function refreshChartData(chartTitle) {
      try {
          if (chartTitle === '消息统计') {
              // 从API获取消息统计数据
              const response = await fetch('/api/chart/messages');
              const data = await response.json();

              // 更新图表数据
              messagesChart.data.labels = data.labels;
              messagesChart.data.datasets[0].data = data.data;
              messagesChart.update();
          } else if (chartTitle === '收发图表') {
              // 从API获取系统状态数据
              const response = await fetch('/api/chart/today-usage');
              const data = await response.json();

              // 更新图表数据
              botMsgStatusChart.data.labels = data.labels;
              botMsgStatusChart.data.datasets[0].data = data.data;
              botMsgStatusChart.update();
          }
      } catch (error) {
          console.error('获取图表数据失败:', error);
          throw error;
      }
  }
</script>
{% endblock %}
