为【微浸】主题适配友链自助提交插件
编辑
93
2025-07-11
由于目前主题未适配 友链自助提交插件 故自己动手适配一下,通过代码注入减少后期修改
JS
通过拦截重写
.link-main-banner-btn.mt-10按钮逻辑实现。其他页面位置需要自己查找替换e.target.closest('.link-main-banner-btn.mt-10')按钮类,同时下面代码做了判断只处理/links页面
微浸主题提供 自定义JavaScript代码 直接复制下面代码。也可以用Halo官方的接口:设置 -> 代码注入 需要使用 <script></script> 包裹。
// 动态添加友链对话框
function insertCustomModal() {
if (document.getElementById('link-submit-modal')) return; // 避免重复添加
//添加提交窗口
const modalHTML = `
<div id="link-submit-modal">
<div>
<h2>🔗提交友链</h2>
<div class="modal-tip">
<p style="margin: 0;">⚠️<b>重要提示:</b> 在您申请之前,希望您已仔细阅读过<b>友链规则</b>,这将加快审核流程!</p>
</div>
<div id="link-submit-form-scroll-area">
<form id="link-submit-form" onsubmit="submitLinkForm(event)">
<div class="input-group">
<h3>基础信息</h3>
<input name="displayName" placeholder="博客名称" required><br>
<input name="url" placeholder="博客链接 (以 http:// 或 https:// 开头)" required><br>
<input name="logo" placeholder="Logo 图片链接" required><br>
<select name="groupName" id="link-groups">
<option value="">加载友链分组中...</option>
</select><br>
</div>
<div class="input-group">
<h3>联系与描述</h3>
<input name="email" placeholder="您的邮箱 (可选,用于审核联系)" type="email"><br>
<input name="rssUrl" placeholder="RSS 订阅链接 (选填)" type="url"><br>
<textarea name="description" placeholder="一句话描述您的博客 (不超过50字)"></textarea><br>
</div>
</form>
</div>
<div class="modal-buttons">
<div class="radio-group">
<label>
<input type="radio" name="type" value="add" checked> 添加
</label>
<label>
<input type="radio" name="type" value="update"> 更新
</label>
</div>
<div class="action-buttons">
<button type="button" id="link-submit-cancel" onclick="closeCustomModal()">取消</button>
<button type="submit" form="link-submit-form">提交</button>
</div>
</div>
</div>
</div>`;
document.body.insertAdjacentHTML('beforeend', modalHTML);
//添加toast
const toastHTML = `<div id="custom-toast"></div>`;
document.body.insertAdjacentHTML('beforeend', toastHTML);
}
/*
* 显示toast
* type success , error
*/
function showToast(message, type = 'info', duration = 3000) {
const toast = document.getElementById('custom-toast');
if (!toast) return; // 如果元素不存在则不执行
toast.textContent = message; // 设置消息文本
toast.className = ''; // 重置所有类名,清除之前的状态
toast.classList.add(type); // 添加消息类型类('success', 'error', 'info')
toast.classList.add('show'); // 添加 'show' 类以显示并触发动画
// 在指定时间后隐藏toast
setTimeout(() => {
toast.classList.remove('show');
}, duration);
}
// 打开对话框
function openCustomModal() {
insertCustomModal();
const modal = document.getElementById('link-submit-modal');
modal.style.display = 'flex';
loadLinkGroups();
}
// 关闭对话框
function closeCustomModal() {
const modal = document.getElementById('link-submit-modal');
modal.style.display = 'none';
}
// 加载友链分组
function loadLinkGroups() {
fetch('/apis/anonymous.link.submit.kunkunyu.com/v1alpha1/linkgroups')
.then(res => res.json())
.then(data => {
const select = document.getElementById('link-groups');
select.innerHTML = '';
data.forEach(group => {
const opt = document.createElement('option');
opt.value = group.groupName;
opt.textContent = group.displayName;
select.appendChild(opt);
});
})
.catch(err => {
console.error('加载分组失败', err);
document.getElementById('link-groups').innerHTML = '<option>加载失败</option>';
});
}
// 提交友链
function submitLinkForm(e) {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const json = {};
formData.forEach((value, key) => json[key] = value);
// 手动获取 type 单选框的选中值
const selectedTypeRadio = document.querySelector('input[name="type"]:checked');
if (selectedTypeRadio)
json.type = selectedTypeRadio.value;
else
json.type = 'add';//默认
fetch('/apis/anonymous.link.submit.kunkunyu.com/v1alpha1/linksubmits/-/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(json)
})
.then(res => res.json())
.then(result => {
if (result.status) {
showToast('⚠️ ' + result.detail, 'error');
return;
}
showToast('🎉 提交成功,请等待审核!', 'success');
closeCustomModal();
})
.catch(err => {
console.error('提交失败', err);
showToast('⚠️ 提交失败,请稍后再试', 'error');
});
}
// 拦截主题原有的申请按钮逻辑
if (/^\/links(\/|$)/.test(window.location.pathname)) {
document.addEventListener('click', function (e) {
if (e.target.closest('.link-main-banner-btn.mt-10')) {
e.stopImmediatePropagation();
e.preventDefault();
openCustomModal();
}
}, true);
}
else {
console.log('🚫 非 /links 页面,不绑定');
}CSS
微浸主题提供 自定义css代码 直接复制下面代码即可。也可以用Halo官方的接口:设置 -> 代码注入 需要使用 <style></style> 包裹。
/*************************Toast********************************/
#custom-toast {
position: fixed; /* 固定定位在视口中 */
top: 20px; /* 距离顶部 20px */
left: 50%; /* 水平居中 */
transform: translateX(-50%); /* 精确水平居中 */
background-color: #333;
color: #fff;
padding: 10px 16px;
border-radius: 6px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
z-index: 10000; /* 确保在模态框之上 */
opacity: 0; /* 默认隐藏 */
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out; /* 淡入淡出动画 */
pointer-events: none; /* 允许点击穿透,当隐藏时不阻挡下方元素 */
min-width: 200px;
text-align: center;
}
#custom-toast.show {
opacity: 1; /* 显示时完全不透明 */
transform: translateX(-50%) translateY(0); /* 保持居中并取消Y轴位移(如果有) */
}
#custom-toast.success {
background-color: #4caf50; /* 成功消息的背景色 (绿色) */
}
#custom-toast.error {
background-color: #EF5350; /* 错误消息的背景色 (红色) */
}
/*************************友链申请CSS********************************/
/*原插件自带按钮*/
button[title="提交友链"] {
display: none !important;
}
/* 模态框背景遮罩 */
#link-submit-modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
z-index: 9999;
justify-content: center;
align-items: center;
}
/* 模态框内容容器 - 负责整体布局 */
#link-submit-modal>div {
background: #fff;
padding: 20px;
/* 整体内边距 */
border-radius: 8px;
max-width: 450px;
width: 90%;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
position: relative;
display: flex;
/* 使用 Flexbox 进行内部布局 */
flex-direction: column;
/* 垂直排列子元素 */
max-height: 85vh;
/* 限制整体高度 */
box-sizing: border-box;
}
/* 标题 */
#link-submit-modal h2 {
margin-top: 0;
margin-bottom: 20px;
/* 增加底部间距,让标题更突出 */
font-size: 22px;
/* 略微增大字体 */
color: #333;
text-align: center;
/* 确保居中 */
}
/* 可滚动表单内容区 */
#link-submit-form-scroll-area {
flex-grow: 1;
/* 占据剩余空间 */
/* 垂直滚动条 - 针对不同浏览器做兼容性处理 */
overflow-y: auto;
-webkit-overflow-scrolling: touch;
/* 针对iOS平滑滚动 */
scrollbar-width: thin;
/* Firefox 滚动条样式 */
scrollbar-color: #ccc #f0f0f0;
/* Firefox 滚动条颜色 */
/* Webkit (Chrome, Safari) 滚动条样式 */
&::-webkit-scrollbar {
width: 8px;
}
&::-webkit-scrollbar-track {
background: #f0f0f0;
border-radius: 10px;
}
&::-webkit-scrollbar-thumb {
background-color: #ccc;
border-radius: 10px;
border: 2px solid #f0f0f0;
}
&::-webkit-scrollbar-thumb:hover {
background-color: #999;
}
padding-right: 10px;
/* 为滚动条留出空间,避免内容被遮挡 */
margin-right: -10px;
/* 抵消 padding-right,让内容对齐 */
}
/* 表单输入框及选择框 */
#link-submit-form input,
#link-submit-form textarea,
#link-submit-form select {
width: calc(100% - 16px);
/* 适应内边距 */
margin-bottom: 10px;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
box-sizing: border-box;
}
#link-submit-form input:focus,
#link-submit-form textarea:focus,
#link-submit-form select:focus {
border-color: #358bff;
outline: none;
}
#link-submit-form textarea {
resize: vertical;
min-height: 60px;
}
/* 按钮容器 (现在独立于滚动区) */
.modal-buttons {
display: flex;
justify-content: space-between;
/* 单选框组在左,按钮在右 */
gap: 8px;
margin-top: 15px;
/* 与上方内容保持距离 */
flex-shrink: 0;
/* 防止按钮区域收缩 */
}
/* 单选框组的容器 */
.radio-group {
display: flex;
align-items: center;
gap: 15px;
/* 单选框之间的间距 */
}
.radio-group label {
display: flex;
align-items: center;
font-size: 14px;
color: #555;
cursor: pointer;
}
.radio-group input[type="radio"] {
margin-right: 5px;
/* 单选框和文本之间的间距 */
width: auto;
/* 恢复默认宽度,不被100%覆盖 */
margin-bottom: 0;
/* 消除底部间距 */
}
/* 按钮的通用样式 */
.modal-buttons button {
padding: 8px 15px;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
background: #eee;
/* 默认一个浅色背景 */
color: #333;
/* 默认一个深色文本 */
}
/* 提交按钮的特定样式 */
.modal-buttons button[type="submit"] {
background: #358bff;
color: #fff;
}
.modal-buttons button[type="submit"]:hover {
background: #2a72e8;
}
/* 取消按钮的特定样式 */
#link-submit-cancel {
margin-right:5px;
background: #eee;
color: #333;
}
#link-submit-cancel:hover {
background: #ddd;
}
/* 提示样式 */
.modal-tip {
background: #e6f7ff;
border-left: 4px solid #358bff;
padding: 10px 15px;
margin-bottom: 20px;
font-size: 13px;
color: #333;
border-radius: 4px;
line-height: 1.5;
flex-shrink: 0;
}
/* 输入分组样式 */
.input-group {
border: 1px solid #eee;
padding: 15px;
margin-bottom: 20px;
border-radius: 6px;
background-color: #fcfcfc;
}
.input-group h3 {
margin-top: 0;
margin-bottom: 10px;
font-size: 16px;
color: #358bff;
border-bottom: 1px dashed #eee;
padding-bottom: 5px;
}
.input-group input,
.input-group textarea,
.input-group select {
margin-bottom: 8px;
}效果
可以看到能正常添加和更新:


- 1
- 1
-
分享