index.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <?php
  2. $blogs = DB::selectAll("select blogs.id, title, poster, post_time from important_blogs, blogs where is_hidden = 0 and important_blogs.blog_id = blogs.id order by level desc, important_blogs.blog_id desc limit 8");
  3. $topusers = DB::selectAll("select username, rating, qq, motto from user_info order by rating desc, username asc limit 12;");
  4. $topblogs = DB::selectAll("select id from blogs order by zan desc limit 10;");
  5. $songs_data = htmlspecialchars(json_encode(DB::selectAll("select * from songs;")), ENT_QUOTES, 'UTF-8');
  6. $submdata = DB::selectAll("select yearweek(submit_time, 1) as weeknr, date(submit_time - interval weekday(submit_time) day) as weekst, count(*) as cnt from submissions group by weeknr, weekst order by weekst;");
  7. $submjson = htmlspecialchars(json_encode($submdata), ENT_QUOTES, 'UTF-8');
  8. requireLib('flot');
  9. ?>
  10. <?php echoUOJPageHeader(UOJConfig::$data['profile']['oj-name-short']) ?>
  11. <div id="songs-data" data-songs='<?php echo $songs_data; ?>'></div>
  12. <div class="row shadow my-4 wyoj-topcard">
  13. <div class="card-body">
  14. <div class="row">
  15. <!-- <div class="col-xs-6 col-sm-4 col-md-3">
  16. <img class="media-object img-thumbnail" src="/images/logo.png" alt="Logo" />
  17. </div>-->
  18. <div class="col-sm-12 col-md-9">
  19. <table class="table table-sm">
  20. <!-- <thead>
  21. <tr>
  22. <th style="width:60%"><?= UOJLocale::get('announcements') ?></th>
  23. <th style="width:20%"></th>
  24. <th style="width:20%"></th>
  25. </tr>
  26. </thead>-->
  27. <tbody>
  28. <?php $now_cnt = 0; ?>
  29. <?php foreach ($blogs as $blog): ?>
  30. <?php
  31. $now_cnt++;
  32. $new_tag = '';
  33. if ((time() - strtotime($blog['post_time'])) / 3600 / 24 <= 7) {
  34. $new_tag = '<sup style="color:red">&nbsp;new</sup>';
  35. }
  36. ?>
  37. <tr>
  38. <td><a href="/blogs/<?= $blog['id'] ?>"><?= $blog['title'] ?></a><?= $new_tag ?></td>
  39. <td>by <?= getUserLink($blog['poster']) ?></td>
  40. <td><small><?= $blog['post_time'] ?></small></td>
  41. </tr>
  42. <?php endforeach ?>
  43. <?php for ($i = $now_cnt + 1; $i <= 8; $i++): ?>
  44. <tr><td colspan="233">&nbsp;</td></tr>
  45. <?php endfor ?>
  46. <tr><td class="text-right" colspan="233">
  47. <span>本歌曲由 </span><span id="recommender"></span><span> 推荐</span>
  48. </td></tr>
  49. <tr><td class="text-right" colspan="233">
  50. <a href="https://git.ryp.org.cn/wyoj/" class="text-info font-weight-bold">WyOJ 以及所有相关项目均为自由软件。</a>
  51. <a href="/announcements"><?= UOJLocale::get('all the announcements') ?></a>
  52. </td></tr>
  53. <tr>
  54. <td class="text-right" colspan="233">
  55. <span class="text-danger font-weight-bold">声明:本网站属个人非经营性网站,仅用于学习交流,无任何盈利目的,与任何组织无关</span>
  56. <a href="/certs-manage/songs">我要推歌</a>
  57. </td>
  58. </tr>
  59. </tbody>
  60. </table>
  61. </div>
  62. <div class="col-xs-6 col-sm-4 col-md-3">
  63. <div class="card" style="max-width:300px; width:100%; border-radius:0; ">
  64. <div class="image-frame" style="aspect-ratio:1/1; position:relative;">
  65. <img id="photo" src="" alt="" style="width:100%; height:100%; object-fit:cover; display:block; cursor:pointer; -webkit-tap-highlight-color:transparent;">
  66. </div>
  67. <div class="intro" style="padding:1.6rem 1.8rem 1.2rem; text-align:center; background:#ffffff;">
  68. <p id="name" style="font-size:1.0rem; font-weight:800; letter-spacing:1px; margin-bottom:0.5rem; line-height:1.2; margin-block:0;"></p>
  69. <p id="amb" style="font-size:0.7rem; font-weight:400; color:#4f5d69; margin-bottom:0.25rem; line-height:1.5; border-top:1px dashed #cdd9e3; padding-top:0.8rem; white-space:pre-wrap; margin-block:0;"></p>
  70. <p id="writer" style="font-size:0.7rem; font-weight:400; color:#4f5d69; margin-bottom:0.25rem; line-height:1.5; white-space:pre-wrap; margin-block:0;"></p>
  71. </div>
  72. <div class="button-wrapper" style="padding:0.2rem 1.8rem 2rem 1.8rem; background:#ffffff;">
  73. <style>
  74. #randomBtn{
  75. display: inline-flex;
  76. align-items: center;
  77. justify-content: center;
  78. gap: 0.6rem;
  79. width: 100%;
  80. background: #1f2f3b;
  81. color: white;
  82. padding: 0.7rem 0;
  83. cursor: pointer;
  84. transition: all 0.2s ease;
  85. letter-spacing: 0.5px;
  86. border: 1px solid rgba(255, 255, 255, 0.2);
  87. backdrop-filter: blur(4px);
  88. font-family: inherit;
  89. line-height: 1;
  90. }
  91. </style>
  92. <button id="randomBtn">换一首</button>
  93. </div>
  94. </div>
  95. <script>
  96. (function() {
  97. let dataDiv = document.getElementById('songs-data');
  98. let library = JSON.parse(dataDiv.dataset.songs);
  99. const photoImg = document.getElementById('photo');
  100. const nameEl = document.getElementById('name');
  101. const ambEl = document.getElementById('amb');
  102. const writerEl = document.getElementById('writer');
  103. const randomBtn = document.getElementById('randomBtn');
  104. const recommenderEl = document.getElementById('recommender');
  105. let lastIndex = -1;
  106. let currentMusicLink = library[0].musiclink;
  107. photoImg.addEventListener('mousedown', function(e) {
  108. this.style.opacity = '0.8';
  109. });
  110. photoImg.addEventListener('mouseup', function(e) {
  111. this.style.opacity = '';
  112. });
  113. photoImg.addEventListener('mouseleave', function(e) {
  114. this.style.opacity = '';
  115. });
  116. photoImg.addEventListener('touchstart', function(e) {
  117. this.style.opacity = '0.8';
  118. });
  119. photoImg.addEventListener('touchend', function(e) {
  120. this.style.opacity = '';
  121. });
  122. photoImg.addEventListener('touchcancel', function(e) {
  123. this.style.opacity = '';
  124. });
  125. function setBtnActive() {
  126. randomBtn.style.background = '#17242e';
  127. randomBtn.style.transform = 'scale(0.98)';
  128. randomBtn.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
  129. }
  130. function setBtnNormal() {
  131. randomBtn.style.background = '#1f2f3b';
  132. randomBtn.style.transform = 'scale(1)';
  133. randomBtn.style.boxShadow = 'none';
  134. }
  135. randomBtn.addEventListener('mousedown', setBtnActive);
  136. randomBtn.addEventListener('mouseup', setBtnNormal);
  137. randomBtn.addEventListener('mouseleave', setBtnNormal);
  138. randomBtn.addEventListener('touchstart', setBtnActive);
  139. randomBtn.addEventListener('touchend', setBtnNormal);
  140. randomBtn.addEventListener('touchcancel', setBtnNormal);
  141. photoImg.addEventListener('click', function() {
  142. if (currentMusicLink) {
  143. window.open(currentMusicLink, '_blank');
  144. }
  145. });
  146. function randmusic() {
  147. let randid = lastIndex;
  148. while (randid === lastIndex) {
  149. randid = Math.floor(Math.random() * library.length);
  150. }
  151. if (lastIndex == -1) randid = 3;
  152. lastIndex = randid;
  153. const ys = library[randid];
  154. photoImg.src = ys.cover;
  155. photoImg.alt = ys.name;
  156. nameEl.textContent = ys.name;
  157. ambEl.textContent = ys.album;
  158. writerEl.textContent = ys.writer;
  159. recommenderEl.textContent = ys.user;
  160. currentMusicLink = ys.click;
  161. }
  162. randmusic();
  163. randomBtn.addEventListener('click', function() {
  164. randmusic();
  165. });
  166. })();
  167. </script>
  168. </div>
  169. </div>
  170. </div>
  171. </div>
  172. <!--
  173. <div class="row shadow my-4 wyoj-topcard" id="recommender-zone">
  174. <div class="col-12 p-4">
  175. <h3>服务器信息</h3>
  176. <div id="submissions-data" data-submissions_data='<?= $submjson ?>'></div>
  177. <div style="position: relative; width: 100%; padding-top: 20%;">
  178. <div id="submissions-plot" class="w-100 h-100" style="position: absolute; top: 0; left: 0;"></div>
  179. </div>
  180. <div style="position: relative; width: 100%; padding-top: 20%;">
  181. <div id="storage-plot" class="w-100 h-100" style="position: absolute; top: 0; left: 0;"></div>
  182. </div>
  183. </div>
  184. </div>
  185. -->
  186. <div class="row shadow my-4 wyoj-topcard">
  187. <div class="col-12 p-4">
  188. <h3>博客广场</h3>
  189. </div>
  190. <?php
  191. foreach ($topblogs as $id) echo echoBlogCard(queryBlog($id['id']));
  192. ?>
  193. </div>
  194. <div class="row shadow my-4 wyoj-topcard">
  195. <div class="col-12 p-4">
  196. <h3>比赛排行榜</h3>
  197. </div>
  198. <?php foreach($topusers as $user): ?>
  199. <div class="col-md-3 mb-4">
  200. <div class="card h-100 p-3 text-center">
  201. <img class="uoj-avatar mx-auto mb-2" src=<?= "https://q.qlogo.cn/g?b=qq&nk=" . $user['qq'] . "&s=100" ?> alt="...">
  202. <span class="mb-2"><?= getUserLink($user['username']) ?></span>
  203. <span class="text-center text-bottom"><?= $user['motto'] ?></span>
  204. </div>
  205. </div>
  206. <?php endforeach ?>
  207. </div>
  208. <script>
  209. (function() {
  210. const submissions_data_raw = JSON.parse(document.getElementById('submissions-data').dataset.submissions_data);
  211. const submissions_data = submissions_data_raw.map(x => [Number(new Date(x['weekst'])), Number(x['cnt'])]);
  212. console.log(submissions_data);
  213. var dataset = [
  214. {
  215. label: "提交数",
  216. data: submissions_data,
  217. yaxis: 1,
  218. lines: { show: true },
  219. points: { show: true }
  220. },
  221. ];
  222. var options1 = {
  223. yaxes: [
  224. {
  225. position: "left",
  226. min: 0,
  227. max: 10000,
  228. axisLabelUseCanvas: true,
  229. axisLabelFontSizePixels: 12
  230. },
  231. {
  232. position: "right",
  233. min: 0,
  234. max: 10000,
  235. tickDecimals: 0,
  236. axisLabelUseCanvas: true,
  237. axisLabelFontSizePixels: 12
  238. }
  239. ],
  240. xais: {
  241. mode: 'time',
  242. timeformat: "%Y-%m-%d",
  243. minTickSize: [1, 'day']
  244. },
  245. grid: {
  246. hoverable: true,
  247. },
  248. legend: {
  249. position: "ne"
  250. }
  251. };
  252. $.plot($("#submissions-plot"), dataset, options1);
  253. }) ();
  254. </script>
  255. <?php echoUOJPageFooter() ?>