Última atividade 2 months ago

友人帐页面新增延迟展示

Joe
php Bruto
1<?php
2
3/**
4 * 友链
5 *
6 * @package custom
7 *
8 **/
9
10if (!defined('__TYPECHO_ROOT_DIR__')) {
11 http_response_code(404);
12 exit;
13}
14$this->need('module/single/pjax.php');
15?>
16<!DOCTYPE html>
17<html lang="zh-CN">
18
19<head>
20 <?php $this->need('module/head.php') ?>
21 <link rel="stylesheet" href="<?= joe\theme_url('assets/css/joe.friend.css') ?>">
22 <style>
23 .status-tag {
24 position: absolute;
25 top: 0px;
26 right: 0px;
27 padding: 3px 8px;
28 border-radius: 0px 12px 0px 12px;
29 font-size: 12px;
30 color: white;
31 font-weight: bold;
32 transition: font-size 0.3s ease-out, width 0.3s ease-out, opacity 0.3s ease-out;
33 z-index: 1;
34 }
35 .joe_detail__friends-item:hover .status-tag {
36 font-size: 0px;
37 opacity: 0;
38 }
39 /* 固态颜色 */
40 .status-tag-green {
41 background-color: #005E00; /* 绿色 */
42 }
43 .status-tag-light-yellow {
44 background-color: #FED101; /* 浅黄色 */
45 }
46 .status-tag-dark-yellow {
47 background-color: #F0B606; /* 深黄色 */
48 }
49 .status-tag-red {
50 background-color: #B90000; /* 红色 */
51 }
52
53 /* 修改卡片样式,使用头像作为背景 */
54 .joe_detail__friends-item .contain {
55 position: relative;
56 overflow: hidden;
57 background: rgba(255, 255, 255, 0.1) !important;
58 backdrop-filter: blur(10px);
59 box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
60 border-radius: 12px;
61 transition: transform 0.3s ease, box-shadow 0.3s ease;
62 }
63
64 .joe_detail__friends-item .contain::before {
65 content: '';
66 position: absolute;
67 top: 0;
68 left: 0;
69 right: 0;
70 bottom: 0;
71 background-image: var(--bg-image);
72 background-size: cover;
73 background-position: center;
74 opacity: 0.5;
75 z-index: -1;
76 border-radius: 12px;
77 }
78
79 .joe_detail__friends-item .contain:hover {
80 transform: translateY(-5px);
81 box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
82 }
83
84 .joe_detail__friends-item .content {
85 position: relative;
86 z-index: 2;
87 }
88
89 .joe_detail__friends-item .title {
90 color: #fff;
91 text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
92 font-weight: bold;
93 }
94
95 .joe_detail__friends-item .desc {
96 color: rgba(255, 255, 255, 0.9);
97 text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
98 }
99
100 .joe_detail__friends-item .avatar {
101 border: 2px solid rgba(255, 255, 255, 0.8);
102 box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
103 }
104 </style>
105</head>
106
107<body>
108 <?php $this->need('module/header.php'); ?>
109 <div id="Joe">
110 <div class="joe_container">
111 <main class="joe_main">
112 <div class="joe_detail" data-cid="<?= $this->cid ?>">
113 <?php $this->need('module/single/batten.php'); ?>
114 <?php $this->need('module/single/article.php'); ?>
115 <?php
116 $friends = think\facade\Db::name('friends')->where('status', 1)->whereFindInSet('position', 'single')->order('order', 'desc')->select()->toArray();
117 ?>
118 <?php if (sizeof($friends) > 0 && ($this->options->JFriendsSpiderHide != 'on' || !joe\detectSpider())) : ?>
119 <style>
120 .joe_detail__article {
121 margin-bottom: 0px;
122 }
123 </style>
124 <ul class="joe_detail__friends">
125 <?php
126 if ($this->options->JFriends_shuffle == 'on') shuffle($friends);
127 foreach ($friends as $item) :
128 ?>
129 <li class="joe_detail__friends-item">
130 <a class="contain" href="<?= $item['url'] ?>" target="_blank" rel="<?= $item['rel'] ?>" referrer="unsafe-url" style="--bg-image: url('<?= $item['logo'] ?>')">
131 <span class="title"><?= $item['title'] ?></span>
132 <div class="content">
133 <div class="desc"><?= $item['description'] ?></div>
134 <img referrerpolicy="no-referrer" rel="noreferrer" width="40" height="40" class="avatar lazyload" onerror="Joe.avatarError(this)" src="<?= joe\getAvatarLazyload(); ?>" data-src="<?= $item['logo'] ?>" alt="<?= $item['title'] ?>" />
135 </div>
136 </a>
137 </li>
138 <?php endforeach; ?>
139 </ul>
140 <?php endif; ?>
141 <?php
142 if ($this->options->JFriends_Submit == 'on') $this->need('module/friends/submit.php');
143 ?>
144 <?php $this->need('module/single/handle.php'); ?>
145 <?php $this->need('module/single/copyright.php'); ?>
146 </div>
147 <?php $this->need('module/single/comment.php'); ?>
148 </main>
149 <?php joe\isPc() ? $this->need('module/aside.php') : null ?>
150 </div>
151 <?php $this->need('module/bottom.php'); ?>
152 </div>
153 <?php $this->need('module/footer.php') ?>
154 <script>
155 function addStatusTagsWithCache(jsonUrl) {
156 const cacheKey = "statusTagsData";
157 const cacheExpirationTime = 30 * 60 * 1000; // 半小时
158 function applyStatusTags(data) {
159 const linkStatus = data.link_status;
160 document.querySelectorAll('.joe_detail__friends-item').forEach(card => {
161 const linkAnchor = card.querySelector('a.contain');
162 if (!linkAnchor) return;
163 const link = linkAnchor.href.replace(/\/$/, '');
164 const statusTag = document.createElement('div');
165 statusTag.classList.add('status-tag');
166 let matched = false;
167 // 查找链接状态
168 const status = linkStatus.find(item => item.link.replace(/\/$/, '') === link);
169 if (status) {
170 let latencyText = '未知';
171 let className = 'status-tag-red'; // 默认红色
172 if (status.latency === -1) {
173 latencyText = '未知';
174 } else {
175 latencyText = status.latency.toFixed(2) + ' s';
176 if (status.latency <= 2) {
177 className = 'status-tag-green';
178 } else if (status.latency <= 5) {
179 className = 'status-tag-light-yellow';
180 } else if (status.latency <= 10) {
181 className = 'status-tag-dark-yellow';
182 }
183 }
184 statusTag.textContent = latencyText;
185 statusTag.classList.add(className);
186 matched = true;
187 }
188 if (matched) {
189 card.style.position = 'relative';
190 card.appendChild(statusTag);
191 }
192 });
193 }
194 function fetchDataAndUpdateUI() {
195 fetch(jsonUrl)
196 .then(response => response.json())
197 .then(data => {
198 applyStatusTags(data);
199 const cacheData = {
200 data: data,
201 timestamp: Date.now()
202 };
203 localStorage.setItem(cacheKey, JSON.stringify(cacheData));
204 })
205 .catch(error => console.error('Error fetching test-flink result.json:', error));
206 }
207 const cachedData = localStorage.getItem(cacheKey);
208 if (cachedData) {
209 const { data, timestamp } = JSON.parse(cachedData);
210 if (Date.now() - timestamp < cacheExpirationTime) {
211 applyStatusTags(data);
212 return;
213 }
214 }
215 fetchDataAndUpdateUI();
216 }
217 setTimeout(() => {
218 addStatusTagsWithCache('https://你的部署地址/result.json');
219 }, 0);
220 </script>
221</body>
222
223</html>