fixed 维护一下项目结构
This commit is contained in:
1 parent
c7acf03b4a
commit
6ad43b2c08
87 files changed
+6864
-11017
No files matched your search
@@ -1,48 +0,0 @@
|
||||
{{ define "main" }}
|
||||
<div id="pjax-container">
|
||||
<div class="post-content" itemprop="articleBody" uk-scrollspy="target: > *; cls: uk-animation-slide-bottom-small; delay: 100">
|
||||
{{ .Content }}
|
||||
|
||||
{{ $sectionCount := 0 }}
|
||||
|
||||
<!-- Heatmap Section -->
|
||||
{{ if site.Params.about.enableheatmap }}
|
||||
{{ $sectionCount = add $sectionCount 1 }}
|
||||
<div style="margin-top: 40px;">
|
||||
<div class="section-title">{{ printf "%02d" $sectionCount }} / 热力图 (Hot Map)</div>
|
||||
{{ partial "heatmap.html" . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<!-- Skills Section -->
|
||||
{{ if site.Params.about.enableskills }}
|
||||
{{ $sectionCount = add $sectionCount 1 }}
|
||||
<div style="margin-top: 40px;">
|
||||
<div class="section-title">{{ printf "%02d" $sectionCount }} / 技能栈 (System Ops)</div>
|
||||
{{ partial "skills.html" . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<!-- Album Section -->
|
||||
{{ if site.Params.about.enablealbum }}
|
||||
{{ $sectionCount = add $sectionCount 1 }}
|
||||
<div style="margin-top: 40px;">
|
||||
<div class="section-title">{{ printf "%02d" $sectionCount }} / 光影 (Album)</div>
|
||||
<div class="album-content" uk-scrollspy="target: > .album-item; cls: uk-animation-slide-bottom-small; delay: 100">
|
||||
{{ range site.Data.album }}
|
||||
<div class="album-item">
|
||||
<div class="album-img-box">
|
||||
<img src="{{ .image }}" loading="lazy">
|
||||
{{ if .date }}<span class="album-date-badge">{{ .date }}</span>{{ end }}
|
||||
<div class="album-info">
|
||||
<span class="album-title">{{ .title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -1,50 +0,0 @@
|
||||
{{ define "main" }}
|
||||
<div id="pjax-container">
|
||||
<div class="post-content" style="list-style-type: none;" uk-scrollspy="target: .link-title; cls: uk-animation-slide-left-small; delay: 50; repeat: true">
|
||||
{{ $currentYear := 0 }}
|
||||
{{ $currentMonth := 0 }}
|
||||
|
||||
{{/* 过滤文章:类型为 post 且 status 不为 hidden */}}
|
||||
{{ $pages := where (where .Site.RegularPages "Type" "post") "Params.status" "ne" "hidden" }}
|
||||
|
||||
{{ range $pages }}
|
||||
{{ $year := .Date.Year }}
|
||||
{{ $month := .Date.Month }}
|
||||
|
||||
{{ if ne $year $currentYear }}
|
||||
{{ if ne $currentYear 0 }}
|
||||
</div> {{/* Close last month of previous year */}}
|
||||
{{ end }}
|
||||
<div class="link-title a-title">
|
||||
<span>{{ $year }}</span>
|
||||
</div>
|
||||
{{ $currentYear = $year }}
|
||||
{{ $currentMonth = 0 }}
|
||||
{{ end }}
|
||||
|
||||
{{ if ne $month $currentMonth }}
|
||||
{{ if ne $currentMonth 0 }}
|
||||
</div> <!-- Close previous month -->
|
||||
{{ end }}
|
||||
<h3 class="diy-h3" data-toggle="collapse" uk-scrollspy="cls: uk-animation-fade; delay: 100"
|
||||
data-target="#collapse{{ $year }}{{ printf "%02d" $month }}" aria-expanded="false"
|
||||
aria-controls="collapse{{ $year }}{{ printf "%02d" $month }}">
|
||||
|
||||
{{ $month | printf "%02d" }}月
|
||||
</h3>
|
||||
<div class="collapse" id="collapse{{ $year }}{{ printf "%02d" $month }}" uk-scrollspy="target: > li; cls: uk-animation-slide-right-small; delay: 100">
|
||||
{{ $currentMonth = $month }}
|
||||
{{ end }}
|
||||
|
||||
<li data-date="{{ $year }}{{ printf "%02d" $month }}{{ .Date.Day }}">
|
||||
<span class="articles_date_time">{{ .Date.Format "01/02" }}</span>
|
||||
<a class="a-archives" href="{{ .Permalink }}">{{ .Title }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
|
||||
{{ if ne $currentMonth 0 }}
|
||||
</div> <!-- Close last month -->
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -1,607 +0,0 @@
|
||||
{{ define "main" }}
|
||||
<div id="pjax-container">
|
||||
<div class="post-content" itemprop="articleBody">
|
||||
{{ .Content }}
|
||||
<div id="friend-circle-container" class="friend-circle-list">
|
||||
<div class="loading-container">
|
||||
<div class="loading-spinner"></div>
|
||||
<p>正在探索朋友们的新动态...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Container Layout */
|
||||
.friend-circle-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px; /* Tighter gap to make cards wider */
|
||||
margin-top: 20px;
|
||||
padding: 0; /* Remove padding to maximize width */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Mobile Layout */
|
||||
@media (max-width: 768px) {
|
||||
.friend-circle-list {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Card Style - Refined based on User Request */
|
||||
.fc-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
height: 160px;
|
||||
justify-content: space-between;
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
/* Enhanced Glassmorphism for non-mobile */
|
||||
backdrop-filter: blur(12px) saturate(120%);
|
||||
-webkit-backdrop-filter: blur(12px) saturate(120%);
|
||||
border: 1px solid #111827;
|
||||
box-shadow: none;
|
||||
transition:
|
||||
transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),
|
||||
box-shadow 0.3s ease,
|
||||
background-color 0.3s ease,
|
||||
border-color 0.3s ease;
|
||||
will-change: transform;
|
||||
text-decoration: none;
|
||||
transform: translateZ(0); /* Enable GPU acceleration */
|
||||
overflow: hidden; /* 防止背景图溢出 */
|
||||
}
|
||||
|
||||
/* Mobile Optimization: Remove expensive effects */
|
||||
@media (max-width: 767px) {
|
||||
.fc-item {
|
||||
backdrop-filter: none !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
background: rgba(255, 255, 255, 0.8); /* Higher opacity fallback */
|
||||
}
|
||||
[data-theme="dark"] .fc-item {
|
||||
background: rgba(30, 30, 30, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
.friend-circle-list a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Light Mode Override - if theme is light, keep it readable but consistent layout */
|
||||
/* Assuming the user wants the dark look as shown in the reference, we prioritize that feel
|
||||
or make it adapt. Let's make it adapt but keep the structure. */
|
||||
:root {
|
||||
/* --fc-bg: rgba(255, 255, 255, 0.8); */
|
||||
--fc-text: #333;
|
||||
--fc-meta-bg: rgba(0, 0, 0, 0.05);
|
||||
/* --fc-border: rgba(0, 0, 0, 0.05); */
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
/* --fc-bg: rgba(35, 35, 35, 0.8); */
|
||||
--fc-text: #fff;
|
||||
--fc-meta-bg: rgba(255, 255, 255, 0.1);
|
||||
/* --fc-border: rgba(255, 255, 255, 0.1); */
|
||||
}
|
||||
|
||||
/*
|
||||
.fc-item {
|
||||
background: var(--fc-bg);
|
||||
border-color: var(--fc-border);
|
||||
}
|
||||
*/
|
||||
|
||||
/* UK Style Animation & Hover */
|
||||
/* 优化后的 hover 效果 */
|
||||
.fc-item:hover {
|
||||
/* 位移+缩放:微调数值,更克制不夸张 */
|
||||
transform: translateY(-6px) scale(1.015);
|
||||
/* 阴影:分层阴影,更有立体感(主阴影+柔和光晕) */
|
||||
box-shadow:
|
||||
0 12px 28px rgba(0, 0, 0, 0.1),
|
||||
/* 主阴影:缩小范围,降低不透明度 */ 0 2px 8px rgba(0, 0, 0, 0.06); /* 次级光晕:增加柔和感 */
|
||||
/* 背景:轻微提亮,保留通透感 */
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
/* 边框:轻微加亮,避免纯黑太突兀 */
|
||||
border-color: #1a1a1a;
|
||||
/* 层级:保持原有值 */
|
||||
z-index: 10;
|
||||
/* 光标:交互提示 */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 可选:点击回弹效果,增强交互反馈 */
|
||||
.fc-item:active {
|
||||
transform: translateY(-3px) scale(1.005);
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
/* Top: Title */
|
||||
.fc-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: var(--fc-text);
|
||||
text-decoration: none;
|
||||
line-height: 1.4;
|
||||
z-index: 2;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
margin-right: 60px; /* Space for the image */
|
||||
}
|
||||
|
||||
.fc-item:hover .fc-title {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
/* Background Image (Decorative) */
|
||||
.fc-bg-image {
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
bottom: -20px;
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
opacity: 0.15;
|
||||
transition: all 0.5s ease;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
filter: grayscale(20%);
|
||||
}
|
||||
|
||||
.fc-item:hover .fc-bg-image {
|
||||
opacity: 0.3;
|
||||
transform: scale(1.1) rotate(deg);
|
||||
filter: grayscale(0%);
|
||||
}
|
||||
|
||||
/* Bottom Row: Author Pill & Date */
|
||||
.fc-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Author Pill */
|
||||
.fc-author-pill {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--fc-meta-bg);
|
||||
padding: 4px 10px 4px 4px;
|
||||
border-radius: 20px;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.fc-item:hover .fc-author-pill {
|
||||
background: rgba(52, 152, 219, 0.1);
|
||||
}
|
||||
|
||||
.fc-avatar {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
margin-right: 8px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.fc-author-name {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--fc-text);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* Date */
|
||||
.fc-date {
|
||||
font-size: 12px;
|
||||
color: var(--fc-text);
|
||||
opacity: 0.6;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fc-date i {
|
||||
margin-right: 4px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* FontAwesome fallback if not available, simple calendar icon via CSS or Unicode */
|
||||
.fc-icon-calendar::before {
|
||||
content: "\f133";
|
||||
font-family: "Font Awesome 5 Free", "FontAwesome";
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
/* Loading Animation */
|
||||
.loading-container {
|
||||
grid-column: 1 / -1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 60px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid rgba(127, 127, 127, 0.2);
|
||||
border-radius: 50%;
|
||||
border-top-color: #3498db;
|
||||
animation: spin 1s ease-in-out infinite;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
/* Dark Mode Specific Adjustments to match the reference exactly */
|
||||
[data-theme="dark"] .fc-item {
|
||||
background: rgba(
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
0.65
|
||||
); /* More transparent for glass effect */
|
||||
box-shadow: none;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .fc-author-pill {
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .fc-bg-image {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .fc-item:hover {
|
||||
background: rgba(60, 60, 60, 0.85);
|
||||
border-color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .fc-item:hover .fc-title {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Removed unused fadeInUp to keep clean, utilizing ukFadeInUp instead */
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
/* Load More Button */
|
||||
.fc-load-more-btn {
|
||||
grid-column: 1 / -1;
|
||||
padding: 5px 30px;
|
||||
margin: 30px auto 10px;
|
||||
background: #000; /* Black background */
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 30px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.fc-load-more-btn:hover {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .fc-load-more-btn {
|
||||
background: #000;
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .fc-load-more-btn:hover {
|
||||
background: #222;
|
||||
}
|
||||
|
||||
/* Artalk Dark Mode Adjustment */
|
||||
[data-theme="dark"] .artalk .atk-main-editor {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
||||
}
|
||||
|
||||
/* Friend Circle Tooltip Card */
|
||||
.fc-tooltip {
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
width: 300px;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transform: scale(0.95) translateY(10px);
|
||||
transition: opacity 0.2s ease, transform 0.2s ease;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
display: none; /* Hidden by default */
|
||||
}
|
||||
|
||||
.fc-tooltip.is-visible {
|
||||
opacity: 1;
|
||||
transform: scale(1) translateY(0);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.fc-tooltip-title {
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
font-size: 15px;
|
||||
color: #000;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.05);
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.fc-tooltip-content {
|
||||
color: #555;
|
||||
text-align: justify;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 6; /* Limit lines */
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .fc-tooltip {
|
||||
background: rgba(35, 35, 35, 0.95);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .fc-tooltip-title {
|
||||
color: #fff;
|
||||
border-bottom-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .fc-tooltip-content {
|
||||
color: #ccc;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="fc-tooltip" class="fc-tooltip">
|
||||
<div class="fc-tooltip-title"></div>
|
||||
<div class="fc-tooltip-content"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 使用全局对象管理友圈逻辑
|
||||
window.FriendCircle = {
|
||||
allPosts: [],
|
||||
currentIndex: 0,
|
||||
BATCH_SIZE: 10,
|
||||
|
||||
timeAgo: function (dateStr) {
|
||||
const date = new Date(dateStr);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}`;
|
||||
},
|
||||
|
||||
renderPosts: function (posts) {
|
||||
const container = document.getElementById("friend-circle-container");
|
||||
if (!container) return;
|
||||
|
||||
const existingBtn = document.getElementById("fc-load-more-btn");
|
||||
if (existingBtn) existingBtn.remove();
|
||||
|
||||
let html = "";
|
||||
posts.forEach((post, index) => {
|
||||
const dateStr = this.timeAgo(post.date);
|
||||
// 背景图固定使用头像,以获得一致的装饰效果
|
||||
const bgImageSrc = post.avatar;
|
||||
// Escape quotes for data attribute
|
||||
const description = post.description ? post.description.replace(/"/g, '"') : '';
|
||||
|
||||
// Calculate delay for staggered animation
|
||||
const delay = index * 100;
|
||||
|
||||
html += `
|
||||
<a href="${post.link}" target="_blank" class="fc-item" data-desc="${description}" data-title="${post.title}" uk-scrollspy="cls: uk-animation-slide-bottom-small; delay: ${delay}">
|
||||
<div class="fc-title" title="${post.title}">${post.title}</div>
|
||||
<img src="${bgImageSrc}" class="fc-bg-image" loading="lazy" onerror="this.style.opacity=0">
|
||||
<div class="fc-bottom">
|
||||
<div class="fc-author-pill">
|
||||
<img src="${post.avatar}" class="fc-avatar" loading="lazy" onerror="this.src='https://cravatar.cn/avatar/default?s=50'">
|
||||
<span class="fc-author-name">${post.author}</span>
|
||||
</div>
|
||||
<div class="fc-date">
|
||||
<i class="ri-calendar-line"></i> ${dateStr}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
`;
|
||||
});
|
||||
|
||||
container.insertAdjacentHTML("beforeend", html);
|
||||
|
||||
if (this.currentIndex < this.allPosts.length) {
|
||||
const btn = document.createElement("button");
|
||||
btn.id = "fc-load-more-btn";
|
||||
btn.className = "fc-load-more-btn";
|
||||
btn.innerText = "加载更多";
|
||||
btn.onclick = () => this.loadMore();
|
||||
container.appendChild(btn);
|
||||
} else {
|
||||
if (window.fcUpdateTime) {
|
||||
const footer = document.createElement("div");
|
||||
footer.style.cssText =
|
||||
"grid-column: 1 / -1; text-align: center; margin-top: 20px; font-size: 12px; color: #999; opacity: 0.6;";
|
||||
footer.innerText = `最近更新: ${window.fcUpdateTime}`;
|
||||
container.appendChild(footer);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
loadMore: function () {
|
||||
const nextBatch = this.allPosts.slice(
|
||||
this.currentIndex,
|
||||
this.currentIndex + this.BATCH_SIZE,
|
||||
);
|
||||
this.currentIndex += this.BATCH_SIZE;
|
||||
// 使用 requestAnimationFrame 优化渲染性能
|
||||
requestAnimationFrame(() => {
|
||||
this.renderPosts(nextBatch);
|
||||
});
|
||||
},
|
||||
|
||||
initTooltip: function() {
|
||||
if (this.tooltipInitialized) return;
|
||||
this.tooltipInitialized = true;
|
||||
|
||||
const tooltip = document.getElementById('fc-tooltip');
|
||||
const titleEl = tooltip.querySelector('.fc-tooltip-title');
|
||||
const contentEl = tooltip.querySelector('.fc-tooltip-content');
|
||||
const container = document.getElementById('friend-circle-container');
|
||||
|
||||
if (!tooltip || !container) return;
|
||||
|
||||
// Move tooltip to body to prevent clipping by overflow:hidden or transforms
|
||||
if (tooltip.parentNode !== document.body) {
|
||||
document.body.appendChild(tooltip);
|
||||
}
|
||||
|
||||
// Cleanup tooltip when navigating away (PJAX)
|
||||
const cleanup = () => {
|
||||
if (tooltip && tooltip.parentNode === document.body) {
|
||||
tooltip.remove();
|
||||
}
|
||||
document.removeEventListener('pjax:send', cleanup);
|
||||
};
|
||||
document.addEventListener('pjax:send', cleanup);
|
||||
|
||||
const updateTooltip = (e) => {
|
||||
// Disable tooltip on mobile devices
|
||||
if (window.innerWidth <= 768) return;
|
||||
|
||||
const item = e.target.closest('.fc-item');
|
||||
if (item) {
|
||||
const desc = item.getAttribute('data-desc');
|
||||
const title = item.getAttribute('data-title');
|
||||
|
||||
if (desc) {
|
||||
titleEl.innerText = title;
|
||||
contentEl.innerText = desc;
|
||||
tooltip.classList.add('is-visible');
|
||||
|
||||
const tooltipWidth = tooltip.offsetWidth;
|
||||
const tooltipHeight = tooltip.offsetHeight;
|
||||
const winWidth = window.innerWidth;
|
||||
const winHeight = window.innerHeight;
|
||||
const gap = 15; // Gap between cursor and tooltip
|
||||
|
||||
let left = e.clientX + gap;
|
||||
let top = e.clientY + gap;
|
||||
|
||||
// Horizontal Logic
|
||||
if (left + tooltipWidth > winWidth - gap) {
|
||||
// Flip to left
|
||||
left = e.clientX - tooltipWidth - gap;
|
||||
|
||||
// If flipping makes it go off-screen to the left (e.g. wide tooltip, cursor near left)
|
||||
if (left < gap) {
|
||||
// Clamp to left edge
|
||||
left = gap;
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical Logic
|
||||
if (top + tooltipHeight > winHeight - gap) {
|
||||
// Flip to top
|
||||
top = e.clientY - tooltipHeight - gap;
|
||||
|
||||
// If flipping makes it go off-screen to the top
|
||||
if (top < gap) {
|
||||
// Clamp to top edge
|
||||
top = gap;
|
||||
}
|
||||
}
|
||||
|
||||
tooltip.style.left = `${left}px`;
|
||||
tooltip.style.top = `${top}px`;
|
||||
} else {
|
||||
tooltip.classList.remove('is-visible');
|
||||
}
|
||||
} else {
|
||||
tooltip.classList.remove('is-visible');
|
||||
}
|
||||
};
|
||||
|
||||
container.addEventListener('mousemove', updateTooltip);
|
||||
container.addEventListener('mouseleave', () => {
|
||||
tooltip.classList.remove('is-visible');
|
||||
});
|
||||
},
|
||||
|
||||
init: function () {
|
||||
const container = document.getElementById("friend-circle-container");
|
||||
if (!container) return;
|
||||
|
||||
this.initTooltip();
|
||||
|
||||
// 防止重复初始化导致掉帧
|
||||
if (this.isFetching) return;
|
||||
this.isFetching = true;
|
||||
|
||||
fetch("/json/friend_circle_data.json?t=" + new Date().getTime())
|
||||
.then((res) => {
|
||||
if (!res.ok) throw new Error("Network response was not ok");
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => {
|
||||
if (!data.posts || data.posts.length === 0) {
|
||||
container.innerHTML =
|
||||
'<div class="empty" style="grid-column: 1/-1; text-align:center; padding:20px;">暂无动态</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
this.allPosts = data.posts;
|
||||
window.fcUpdateTime = new Date(data.updated).toLocaleString();
|
||||
this.currentIndex = 0;
|
||||
container.innerHTML = "";
|
||||
this.loadMore();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Friend Circle Error:", err);
|
||||
container.innerHTML =
|
||||
'<div class="error" style="grid-column: 1/-1; text-align:center; padding:20px; color:#d9534f;">加载失败,请稍后刷新重试</div>';
|
||||
})
|
||||
.finally(() => {
|
||||
this.isFetching = false;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// 移除多余的 pjax:complete 监听,因为脚本在 PJAX 容器内,每次导航都会重新执行
|
||||
// 避免了重复触发 init 导致的性能问题
|
||||
|
||||
// 立即执行初始化
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", () =>
|
||||
window.FriendCircle.init(),
|
||||
);
|
||||
} else {
|
||||
window.FriendCircle.init();
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -1,22 +0,0 @@
|
||||
{{ define "main" }}
|
||||
<div id="pjax-container" uk-scrollspy="target: > #szh,hr,h2,p; cls: uk-animation-slide-bottom-small; delay: 0">
|
||||
<!-- 用于 Pjax 获取当前文章 ID -->
|
||||
<div id="data-pid" style="display:none;">{{ .RelPermalink }}</div>
|
||||
<div class="post-content" itemprop="articleBody" uk-scrollspy="target: > #szh; cls: uk-animation-slide-bottom-small; delay: 0">
|
||||
{{ .Content }}
|
||||
<div id="szh" onclick="copySzhContent()" style="cursor: pointer;" title="点击复制">
|
||||
- 名称:{{ .Site.Params.message_info.name | default .Site.Params.artalk.site }}<br>
|
||||
- 简介:{{ .Site.Params.message_info.description | default .Site.Params.author.description }}<br>
|
||||
- 链接:{{ .Site.Params.message_info.url | default .Site.BaseURL }}<br>
|
||||
- 图标:{{ .Site.Params.message_info.icon | default .Site.Params.author.avatar }}
|
||||
</div>
|
||||
</div>
|
||||
<hr class="uk-divider-icon">
|
||||
<div class="comments-area">
|
||||
<!-- 评论区内容 -->
|
||||
{{ partial "artalk.html" . }}
|
||||
<!-- 评论区内容结束 -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -1,64 +0,0 @@
|
||||
{{ define "main" }}
|
||||
<div id="pjax-container">
|
||||
<article>
|
||||
<div class="recent-posts section">
|
||||
<!-- Searchable Header Container -->
|
||||
<div class="searchable-header-container">
|
||||
<h2 class="section-header normal-mode" id="essay-header" onclick="toggleSearchMode(true)" uk-scrollspy="cls: uk-animation-slide-left-small; delay: 200">
|
||||
随笔<i class="ri-quill-pen-line"></i>
|
||||
<span class="search-hint">点击随笔,开始搜索</span>
|
||||
</h2>
|
||||
<div class="search-mode" id="search-container" style="display: none;">
|
||||
<div class="search-input-group">
|
||||
<i class="ri-search-line search-icon"></i>
|
||||
<input type="text" id="inline-search-input" placeholder="搜索文章..." autocomplete="off">
|
||||
<i class="ri-close-line close-icon" onclick="toggleSearchMode(false)"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div id="inline-search-results" class="search-dropdown"></div>
|
||||
</div>
|
||||
|
||||
<div class="posts" uk-scrollspy="target: > .post; cls: uk-animation-slide-bottom-small; delay: 100">
|
||||
<!-- 使用 sort 对文章按 Weight 排序 -->
|
||||
{{ $posts := sort (where (where .Site.RegularPages "Type" "post") "Params.status" "ne" "hidden")
|
||||
"Weight" }}
|
||||
{{ $paginator := .Paginate $posts }}
|
||||
|
||||
{{ range $paginator.Pages }}
|
||||
<div class="post">
|
||||
<div class="time">{{ .Date.Format "January 2, 2006" }}</div>
|
||||
<a href="{{ .Permalink }}">{{ .Title }}</a>
|
||||
|
||||
<!-- 计算每篇文章的发布时间与当前时间的差值 -->
|
||||
{{ $publishDate := .Date }}
|
||||
{{ $currentTime := now }}
|
||||
{{ $timeDiff := div (sub $currentTime.Unix $publishDate.Unix) 3600 }}
|
||||
|
||||
<!-- 判断发布时间是否小于 24 小时,并且没有 weight 属性 -->
|
||||
{{ if and (lt $timeDiff 24) (not .Params.weight) }}
|
||||
<span class="new-post-message"></span>
|
||||
{{ end }}
|
||||
<!-- 判断发布时间和 weight 属性 -->
|
||||
{{ if .Params.weight }}
|
||||
<!-- 如果有 weight 属性,添加 pushpin 图标 -->
|
||||
<img src="/image/zd_top.png" alt="" srcset="" style="width: 19px;position: relative;bottom: 2px;right: 3px;box-shadow: 0 0px 0px rgba(0, 0, 0, 0.2);cursor: pointer;transform: 1s;">
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<ul class="pagination">
|
||||
<li class="page-item page-next">
|
||||
{{ if $paginator.HasNext }}
|
||||
<a class="next" title="下一页" href="{{ $paginator.Next.URL }}">下一页</a>
|
||||
{{ end }}
|
||||
</li>
|
||||
<li class="page-item page-previous">
|
||||
{{ if $paginator.HasPrev }}
|
||||
<a class="prev" title="上一页" href="{{ $paginator.Prev.URL }}">上一页</a>
|
||||
{{ end }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -1,8 +0,0 @@
|
||||
{{ define "main" }}
|
||||
<div id="pjax-container">
|
||||
<div class="post-content" itemprop="articleBody" uk-scrollspy="target: > .cf-friends; cls: uk-animation-scale-up; delay: 150">
|
||||
{{ partial "link_items.html" . }}
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -1,84 +0,0 @@
|
||||
{{ define "main" }}
|
||||
<div id="pjax-container">
|
||||
<style>
|
||||
.links ul>li {
|
||||
position: relative;
|
||||
padding-left: 1.75em;
|
||||
}
|
||||
|
||||
.links a {
|
||||
color: var(--link-color-light);
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.links li {
|
||||
margin-top: .5em;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
.links ul>li:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: #d1d5db;
|
||||
border-radius: 50%;
|
||||
width: .375em;
|
||||
height: .375em;
|
||||
top: .6875em;
|
||||
left: .25em;
|
||||
}
|
||||
|
||||
.url-name {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.url-name::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: 12px;
|
||||
bottom: 3px;
|
||||
left: -4px;
|
||||
z-index: -1;
|
||||
background-color: #5d5d5d;
|
||||
opacity: .3;
|
||||
transform: skew(-35deg);
|
||||
transition: opacity .2s ease;
|
||||
border-radius: 3px 8px 10px 6px;
|
||||
transition: 0.1s ease background-color;
|
||||
width: 112%;
|
||||
/* 宽度根据a标签的内容动态变化 */
|
||||
}
|
||||
|
||||
.url-name:hover::before {
|
||||
opacity: 0.5;
|
||||
/* 鼠标悬浮时可以改变不透明度 */
|
||||
}
|
||||
|
||||
[data-theme="dark"] .links a {
|
||||
color: var(--link-color-dark);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .url-name::before {
|
||||
background-color: #e5e7eb;
|
||||
opacity: 0.18;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .url-name:hover::before {
|
||||
opacity: 0.35;
|
||||
}
|
||||
</style>
|
||||
<div class="post-content" itemprop="articleBody">
|
||||
<div class="links">
|
||||
<ul id="links-list" uk-scrollspy="target: > li; cls: uk-animation-slide-bottom-small; delay: 50">
|
||||
<!-- 静态生成的内容作为 SEO 兜底或构建时数据 -->
|
||||
{{ range site.Data.links.blogs }}
|
||||
<li><a href="{{ .url }}" class="url-name" target="_blank">{{ .name }}</a><span style="margin-left: 13px;">{{ .description }}</span></li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 移除动态加载脚本,仅保留静态生成内容 -->
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -1,30 +0,0 @@
|
||||
{{ define "main" }}
|
||||
<div id="pjax-container">
|
||||
<div class="post-content" itemprop="articleBody">
|
||||
<div id="links-container" class="items" uk-scrollspy="target: > .item-box; cls: uk-animation-slide-bottom-small; delay: 100">
|
||||
<!-- 静态生成的内容作为 SEO 兜底或构建时数据 -->
|
||||
{{ range site.Data.links.blogs }}
|
||||
<div class="item-box">
|
||||
<div class="website-img">
|
||||
<img src="https://s0.wp.com/mshots/v1/{{ .url }}?w=800&h=600" alt="{{ .name }}">
|
||||
</div>
|
||||
<div class="link-info">
|
||||
<div class="link-avatar">
|
||||
<img src="{{ .image }}" alt="{{ .name }}">
|
||||
</div>
|
||||
<div class="link-des">
|
||||
<div class="link-name">{{ .name }}</div>
|
||||
<div class="link-des" style="color: #64748B;">{{ .description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="{{ .url }}">
|
||||
<div class="website-go-button">逛一逛</div>
|
||||
</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
<!-- 移除动态加载脚本,仅保留静态生成内容 -->
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -1,274 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, viewport-fit=cover">
|
||||
<meta name="fragment" content="!">
|
||||
<script>
|
||||
(function() {
|
||||
var theme = localStorage.getItem('theme');
|
||||
if (!theme) {
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
theme = 'dark';
|
||||
} else {
|
||||
theme = 'light';
|
||||
}
|
||||
}
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
})();
|
||||
</script>
|
||||
<title>即将离开{{ site.Title }}</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg-color: #f3f4f6;
|
||||
--card-bg: #ffffff;
|
||||
--text-primary: #111827;
|
||||
--text-secondary: #4b5563;
|
||||
--text-tertiary: #9ca3af;
|
||||
--accent-color: #000000;
|
||||
--accent-hover: #333333;
|
||||
--accent-text: #ffffff;
|
||||
--code-bg: #f9fafb;
|
||||
--code-text: #6b7280;
|
||||
--border-color: #e5e7eb;
|
||||
--shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--bg-color: #0f172a;
|
||||
--card-bg: #1e293b;
|
||||
--text-primary: #f3f4f6;
|
||||
--text-secondary: #9ca3af;
|
||||
--text-tertiary: #6b7280;
|
||||
--accent-color: #3b82f6;
|
||||
--accent-hover: #2563eb;
|
||||
--accent-text: #ffffff;
|
||||
--code-bg: #020617;
|
||||
--code-text: #94a3b8;
|
||||
--border-color: #334155;
|
||||
--shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5), 0 8px 10px -6px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--bg-color);
|
||||
margin: 0;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
color: var(--text-primary);
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: var(--card-bg);
|
||||
border-radius: 24px;
|
||||
padding: 40px 32px;
|
||||
box-shadow: var(--shadow);
|
||||
text-align: center;
|
||||
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 0 auto 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--code-bg);
|
||||
border-radius: 50%;
|
||||
overflow: hidden; /* 确保图片不溢出圆角 */
|
||||
}
|
||||
|
||||
.card-icon img {
|
||||
width: 100%; /* 宽度铺满 */
|
||||
height: 100%; /* 高度铺满 */
|
||||
object-fit: cover; /* 裁剪图片以填充容器,保持纵横比 */
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
margin: 0 0 12px;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
color: var(--text-secondary);
|
||||
margin: 0 0 32px;
|
||||
}
|
||||
|
||||
.link-preview {
|
||||
background: var(--code-bg);
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--border-color);
|
||||
margin-bottom: 32px;
|
||||
text-align: left;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
transition: background-color 0.3s ease, border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.link-icon {
|
||||
flex-shrink: 0;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
.link-url {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 13px;
|
||||
color: var(--code-text);
|
||||
word-break: break-all;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 14px 24px;
|
||||
background-color: var(--accent-color);
|
||||
color: var(--accent-text);
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, transform 0.1s ease;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: var(--accent-hover);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 40px;
|
||||
font-size: 13px;
|
||||
color: var(--text-tertiary);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dashed var(--text-tertiary);
|
||||
padding-bottom: 2px;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
color: var(--text-secondary);
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
/* Animation */
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.card {
|
||||
animation: fadeIn 0.5s ease-out forwards;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="card">
|
||||
<div class="card-icon">
|
||||
<img src="{{ .Site.Params.author.avatar }}" alt="Icon">
|
||||
</div>
|
||||
<h1 class="card-title">即将离开{{ site.Title }}</h1>
|
||||
<p class="card-desc">
|
||||
您正在尝试访问一个外部链接。请注意,外部网站可能包含未知的安全风险,请确保您信任该站点。
|
||||
</p>
|
||||
|
||||
<div class="link-preview" onclick="copyLink()" title="点击复制链接" style="cursor: pointer;">
|
||||
<div class="link-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
|
||||
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div id="target-url" class="link-url">正在解析目标地址...</div>
|
||||
</div>
|
||||
|
||||
<a id="continue-btn" href="#" class="btn">继续访问</a>
|
||||
|
||||
<div class="footer">
|
||||
<p>© {{ now.Year }} {{ site.Title }} · <a href="https://beian.miit.gov.cn/" target="_blank">鄂ICP备2022015735号-1</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 解析 URL 参数
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const encodedTarget = params.get('target');
|
||||
let targetUrl = '';
|
||||
|
||||
try {
|
||||
if (encodedTarget) {
|
||||
targetUrl = atob(encodedTarget); // Base64 解码
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解码失败', e);
|
||||
}
|
||||
|
||||
const urlElement = document.getElementById('target-url');
|
||||
const btnElement = document.getElementById('continue-btn');
|
||||
|
||||
if (targetUrl) {
|
||||
urlElement.textContent = targetUrl;
|
||||
btnElement.href = targetUrl;
|
||||
} else {
|
||||
urlElement.textContent = '无效的目标链接';
|
||||
btnElement.classList.add('disabled');
|
||||
btnElement.style.opacity = '0.5';
|
||||
btnElement.style.pointerEvents = 'none';
|
||||
btnElement.textContent = '无法继续';
|
||||
}
|
||||
|
||||
// 复制链接功能
|
||||
function copyLink() {
|
||||
if (!targetUrl) return;
|
||||
navigator.clipboard.writeText(targetUrl).then(() => {
|
||||
const originalText = urlElement.textContent;
|
||||
urlElement.textContent = '已复制到剪贴板';
|
||||
setTimeout(() => {
|
||||
urlElement.textContent = originalText;
|
||||
}, 2000);
|
||||
}).catch(err => {
|
||||
console.error('复制失败', err);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user