Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

208 wiersze
8.3 KiB

  1. {% extends "./layout.html" %}
  2. {% block title %}控制台{% endblock %}
  3. {% block css %}
  4. <style>
  5. .stat-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:16px;}
  6. .stat-card{
  7. background:var(--white);border-radius:var(--radius);box-shadow:var(--shadow);
  8. padding:20px;display:flex;flex-wrap:wrap;align-items:flex-start;gap:14px;
  9. position:relative;overflow:hidden;transition:.2s;
  10. }
  11. .stat-card:hover{transform:translateY(-2px);box-shadow:0 4px 16px rgba(0,0,0,.1);}
  12. .stat-icon{
  13. width:48px;height:48px;border-radius:10px;display:flex;
  14. align-items:center;justify-content:center;flex-shrink:0;
  15. }
  16. .stat-icon svg{width:24px;height:24px;}
  17. .stat-info{flex:1;min-width:0;}
  18. .stat-value{font-size:26px;font-weight:700;color:var(--text);font-family:var(--font-en);line-height:1.2;}
  19. .stat-label{font-size:12px;color:var(--text-secondary);margin-top:4px;}
  20. .stat-footer{
  21. width:100%;padding-top:12px;margin-top:4px;border-top:1px solid var(--border-light);
  22. font-size:12px;color:var(--text-secondary);
  23. }
  24. .stat-up{color:var(--success);font-weight:500;}
  25. .stat-down{color:var(--danger);font-weight:500;}
  26. .dashboard-row{display:flex;gap:16px;}
  27. .shortcuts{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;}
  28. .shortcut-item{
  29. display:flex;flex-direction:column;align-items:center;gap:8px;
  30. padding:14px 8px;border-radius:var(--radius);transition:.15s;cursor:pointer;
  31. text-decoration:none;
  32. }
  33. .shortcut-item:hover{background:var(--bg);}
  34. .shortcut-icon{
  35. width:40px;height:40px;border-radius:10px;display:flex;
  36. align-items:center;justify-content:center;
  37. }
  38. .shortcut-icon svg{width:20px;height:20px;}
  39. .shortcut-item span{font-size:12px;color:var(--text-regular);}
  40. .todo-list{display:flex;flex-direction:column;gap:0;}
  41. .todo-item{
  42. display:flex;align-items:center;gap:10px;padding:10px 0;
  43. border-bottom:1px solid var(--border-light);font-size:13px;color:var(--text-regular);
  44. }
  45. .todo-item:last-child{border-bottom:none;}
  46. .todo-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;}
  47. .todo-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  48. @media(max-width:1200px){
  49. .stat-cards{grid-template-columns:repeat(2,1fr);}
  50. .dashboard-row{flex-direction:column;}
  51. .dashboard-row>div:last-child{width:100%;}
  52. }
  53. </style>
  54. {% endblock %}
  55. {% block content %}
  56. <!-- 统计卡片 -->
  57. <div class="stat-cards">
  58. <div class="stat-card">
  59. <div class="stat-icon" style="background:rgba(232,117,26,.1);color:var(--primary);">
  60. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
  61. </div>
  62. <div class="stat-info">
  63. <div class="stat-value">{{ stats.contentCount or 0 }}</div>
  64. <div class="stat-label">内容总数</div>
  65. </div>
  66. <div class="stat-footer"><span class="stat-up">↑ 12%</span> 较上月</div>
  67. </div>
  68. <div class="stat-card">
  69. <div class="stat-icon" style="background:rgba(230,162,60,.1);color:var(--warning);">
  70. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
  71. </div>
  72. <div class="stat-info">
  73. <div class="stat-value">{{ stats.pendingCount or 0 }}</div>
  74. <div class="stat-label">待审核</div>
  75. </div>
  76. <div class="stat-footer"><span class="stat-down">↓ 3</span> 较昨日</div>
  77. </div>
  78. <div class="stat-card">
  79. <div class="stat-icon" style="background:rgba(103,194,58,.1);color:var(--success);">
  80. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
  81. </div>
  82. <div class="stat-info">
  83. <div class="stat-value">{{ stats.visitCount or '0' }}</div>
  84. <div class="stat-label">本月访问</div>
  85. </div>
  86. <div class="stat-footer"><span class="stat-up">↑ 28%</span> 较上月</div>
  87. </div>
  88. <div class="stat-card">
  89. <div class="stat-icon" style="background:rgba(26,53,80,.1);color:var(--blue);">
  90. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
  91. </div>
  92. <div class="stat-info">
  93. <div class="stat-value">¥{{ stats.donationTotal or '0' }}</div>
  94. <div class="stat-label">累计捐赠</div>
  95. </div>
  96. <div class="stat-footer"><span class="stat-up">↑ 5.2%</span> 较上季</div>
  97. </div>
  98. </div>
  99. <!-- 下方两列 -->
  100. <div class="dashboard-row">
  101. <!-- 最近更新 -->
  102. <div class="card" style="flex:1;">
  103. <div class="card-header">
  104. <span class="card-title">最近更新</span>
  105. <button class="el-btn el-btn-sm">查看全部</button>
  106. </div>
  107. <table class="el-table">
  108. <thead>
  109. <tr>
  110. <th>标题</th>
  111. <th>栏目</th>
  112. <th>状态</th>
  113. <th>更新时间</th>
  114. </tr>
  115. </thead>
  116. <tbody>
  117. {% if recentList and recentList.length %}
  118. {% for item in recentList %}
  119. <tr>
  120. <td>{{ item.title }}</td>
  121. <td>{{ item.column_name }}</td>
  122. <td>
  123. {% if item.status == 1 %}
  124. <span class="el-tag el-tag-success">已发布</span>
  125. {% else %}
  126. <span class="el-tag el-tag-warning">待审核</span>
  127. {% endif %}
  128. </td>
  129. <td>{{ item.update_time }}</td>
  130. </tr>
  131. {% endfor %}
  132. {% else %}
  133. <tr>
  134. <td colspan="4" style="text-align:center;color:var(--text-secondary);">暂无数据</td>
  135. </tr>
  136. {% endif %}
  137. </tbody>
  138. </table>
  139. </div>
  140. <!-- 快捷操作 & 待办 -->
  141. <div style="width:320px;display:flex;flex-direction:column;gap:16px;">
  142. <!-- 快捷操作 -->
  143. <div class="card">
  144. <div class="card-header">
  145. <span class="card-title">快捷操作</span>
  146. </div>
  147. <div class="shortcuts">
  148. <a href="/admin/content/article-edit.html" class="shortcut-item">
  149. <div class="shortcut-icon" style="background:rgba(232,117,26,.1);color:var(--primary);">
  150. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
  151. </div>
  152. <span>发布文章</span>
  153. </a>
  154. <a href="/admin/content/image.html" class="shortcut-item">
  155. <div class="shortcut-icon" style="background:rgba(103,194,58,.1);color:var(--success);">
  156. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
  157. </div>
  158. <span>上传图片</span>
  159. </a>
  160. <a href="/admin/data/medicine.html" class="shortcut-item">
  161. <div class="shortcut-icon" style="background:rgba(26,53,80,.1);color:var(--blue);">
  162. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
  163. </div>
  164. <span>录入数据</span>
  165. </a>
  166. <a href="#" class="shortcut-item">
  167. <div class="shortcut-icon" style="background:rgba(230,162,60,.1);color:var(--warning);">
  168. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
  169. </div>
  170. <span>审核内容</span>
  171. </a>
  172. </div>
  173. </div>
  174. <!-- 待办事项 -->
  175. <div class="card">
  176. <div class="card-header">
  177. <span class="card-title">待办事项</span>
  178. </div>
  179. <div class="todo-list">
  180. {% if todoList and todoList.length %}
  181. {% for item in todoList %}
  182. <div class="todo-item">
  183. <span class="todo-dot" style="background:var(--warning);"></span>
  184. <span class="todo-text">{{ item.title }}</span>
  185. </div>
  186. {% endfor %}
  187. {% else %}
  188. <div class="todo-item">
  189. <span class="todo-dot" style="background:var(--success);"></span>
  190. <span class="todo-text">暂无待办事项</span>
  191. </div>
  192. {% endif %}
  193. </div>
  194. </div>
  195. </div>
  196. </div>
  197. {% endblock %}