Files
argon-theme/friend-links.php

1074 lines
60 KiB
PHP
Raw Normal View History

<?php
/**
* 友情链接页面
* @package Argon
*/
$wp_load_path = dirname(dirname(dirname(dirname(__FILE__)))) . '/wp-load.php';
if (!file_exists($wp_load_path)) $wp_load_path = $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php';
require_once($wp_load_path);
if (function_exists('argon_deduplicate_friend_links')) argon_deduplicate_friend_links();
// 权限检查
$is_admin = current_user_can('manage_options');
// AJAX 处理友链管理
if (isset($_POST['flink_action'])) {
header('Content-Type: application/json; charset=utf-8');
$response = array('success' => false, 'message' => '');
$action = sanitize_text_field($_POST['flink_action']);
// 以下操作需要管理员权限
if (!$is_admin) {
echo json_encode(array('success' => false, 'message' => '权限不足'));
exit;
}
if (!isset($_POST['flink_nonce']) || !wp_verify_nonce($_POST['flink_nonce'], 'argon_flink_manage')) {
echo json_encode(array('success' => false, 'message' => '安全验证失败'));
exit;
}
switch ($action) {
case 'add':
$id = argon_add_friend_link(array(
'name' => isset($_POST['name']) ? $_POST['name'] : '',
'display_name' => isset($_POST['display_name']) ? $_POST['display_name'] : '',
'url' => isset($_POST['url']) ? $_POST['url'] : '',
'avatar' => isset($_POST['avatar']) ? $_POST['avatar'] : '',
'description' => isset($_POST['description']) ? $_POST['description'] : '',
'auto_description' => isset($_POST['auto_description']) ? $_POST['auto_description'] : '',
'category' => isset($_POST['category']) ? $_POST['category'] : '',
'status' => 'approved'
));
$response = array('success' => $id !== false, 'id' => $id);
break;
case 'delete':
$id = isset($_POST['id']) ? sanitize_text_field($_POST['id']) : '';
$response = array('success' => argon_delete_friend_link($id));
break;
case 'approve':
$id = isset($_POST['id']) ? sanitize_text_field($_POST['id']) : '';
$result = argon_update_friend_link($id, array('status' => 'approved'));
if ($result) {
$link = argon_get_friend_link($id);
if ($link && !empty($link['email'])) {
$subject = sprintf('[%s] 您的友链申请已通过', get_bloginfo('name'));
$message = sprintf("您好!\n\n您申请的友链已通过审核。\n\n网站名称:%s\n网站地址:%s\n\n感谢您的支持!", $link['name'], $link['url']);
wp_mail($link['email'], $subject, $message);
}
}
$response = array('success' => $result);
break;
case 'reject':
$id = isset($_POST['id']) ? sanitize_text_field($_POST['id']) : '';
$response = array('success' => argon_delete_friend_link($id));
break;
case 'update':
$id = isset($_POST['id']) ? sanitize_text_field($_POST['id']) : '';
$data = array();
foreach (array('name', 'display_name', 'url', 'links_page', 'avatar', 'description', 'auto_description', 'category', 'hide_no_backlink', 'auto_approved') as $f) {
if (isset($_POST[$f])) $data[$f] = $_POST[$f];
}
$response = array('success' => argon_update_friend_link($id, $data));
break;
case 'get':
$id = isset($_POST['id']) ? sanitize_text_field($_POST['id']) : '';
$link = argon_get_friend_link($id);
$response = $link ? array('success' => true, 'data' => $link) : array('success' => false);
break;
case 'check_backlink':
$id = isset($_POST['id']) ? sanitize_text_field($_POST['id']) : '';
$link = argon_get_friend_link($id);
if ($link) {
$links_page = !empty($link['links_page']) ? $link['links_page'] : '';
$has_backlink = $links_page ? argon_check_backlink($links_page) : null;
$accessible = argon_check_site_accessible($link['url']);
argon_update_friend_link($id, array('has_backlink' => $has_backlink, 'accessible' => $accessible, 'last_check' => time()));
$response = array('success' => true, 'has_backlink' => $has_backlink, 'accessible' => $accessible, 'links_page' => $links_page);
}
break;
case 'check_all':
$links = argon_get_friend_links_raw('approved');
$results = array();
foreach ($links as $link) {
$links_page = !empty($link['links_page']) ? $link['links_page'] : '';
$has_backlink = $links_page ? argon_check_backlink($links_page) : null;
$accessible = argon_check_site_accessible($link['url']);
argon_update_friend_link($link['id'], array('has_backlink' => $has_backlink, 'accessible' => $accessible, 'last_check' => time()));
$results[$link['id']] = array('has_backlink' => $has_backlink, 'accessible' => $accessible);
}
$response = array('success' => true, 'results' => $results);
break;
case 'fetch_info':
$url = isset($_POST['url']) ? esc_url_raw($_POST['url']) : '';
if (empty($url)) {
$response = array('success' => false, 'message' => __('请输入网址', 'argon'));
} else {
$info = argon_fetch_site_info($url);
$response = array('success' => true, 'data' => $info);
}
break;
default:
$response = array('success' => false, 'message' => '未知操作');
}
echo json_encode($response);
exit;
}
// 处理访客申请
$apply_result = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['argon_link_apply'])) {
$apply_result = argon_handle_link_application_v3($_POST);
// PRG 模式:成功后重定向避免表单重复提交
if ($apply_result) {
$redirect_url = remove_query_arg(array('apply_success', 'apply_error'), $_SERVER['REQUEST_URI']);
if ($apply_result['success']) {
wp_redirect($redirect_url . (strpos($redirect_url, '?') !== false ? '&' : '?') . 'apply_success=1');
exit;
} else {
// 失败时保存错误信息到 session
if (!session_id()) session_start();
$_SESSION['flink_apply_error'] = $apply_result['message'];
wp_redirect($redirect_url . (strpos($redirect_url, '?') !== false ? '&' : '?') . 'apply_error=1');
exit;
}
}
}
// 从 URL 参数或 session 获取申请结果
if (isset($_GET['apply_success'])) {
$apply_result = array('success' => true, 'message' => __('申请已提交,请等待审核', 'argon'));
} elseif (isset($_GET['apply_error'])) {
if (!session_id()) session_start();
$error_msg = isset($_SESSION['flink_apply_error']) ? $_SESSION['flink_apply_error'] : __('申请失败', 'argon');
unset($_SESSION['flink_apply_error']);
$apply_result = array('success' => false, 'message' => $error_msg);
}
// 获取友链数据
$all_approved_links = argon_get_friend_links_raw('approved');
$pending_links = $is_admin ? argon_get_friend_links_raw('pending') : array();
$show_apply_form = get_option('argon_friend_link_allow_apply', 'true') === 'true';
$requirements = get_option('argon_friend_link_requirements', '');
$hide_no_backlink = get_option('argon_friend_link_hide_no_backlink', 'true') === 'true';
// 过滤友链:非管理员时根据设置隐藏未上友链/失效的
$visible_links = array();
foreach ($all_approved_links as $link) {
$show = true;
if (!$is_admin && $hide_no_backlink) {
// 未填写友链页面的永不隐藏
if (!empty($link['links_page'])) {
$link_hide = $link['hide_no_backlink'] ?? '';
if ($link_hide === 'hide' || ($link_hide !== 'show' && $hide_no_backlink)) {
if (isset($link['has_backlink']) && $link['has_backlink'] === false) $show = false;
if (isset($link['accessible']) && $link['accessible'] === false) $show = false;
}
}
}
if ($show) $visible_links[] = $link;
}
// 按分类分组
$links = array();
foreach ($visible_links as $link) {
$cat = !empty($link['category']) ? $link['category'] : '';
if (!isset($links[$cat])) $links[$cat] = array();
$links[$cat][] = $link;
}
$total_links = count($visible_links);
// 验证码设置(支持独立配置)
$flink_captcha_setting = get_option('argon_friend_link_captcha', 'global');
if ($flink_captcha_setting === 'global' || $flink_captcha_setting === 'same') {
// 使用全局设置
$global_captcha = get_option('argon_need_captcha', get_option('argon_comment_need_captcha', 'true'));
$captcha_enabled = ($global_captcha === 'true');
} elseif ($flink_captcha_setting === 'enabled') {
$captcha_enabled = true;
} else {
$captcha_enabled = false;
}
$captcha_type = get_option('argon_captcha_type', 'math');
get_header();
?>
<div class="page-information-card-container"></div>
<?php get_sidebar(); ?>
<div id="primary" class="content-area">
<style id="flinks-page-style">
/* 桌面端隐藏侧边栏 */
@media screen and (min-width: 901px) {
body.flinks-page #leftbar_part, body.flinks-page #leftbar { display: none !important; }
}
/* 移动端侧边栏支持 - 使用全局样式 */
@media screen and (max-width: 900px) {
body.flinks-page #leftbar {
display: block;
position: fixed;
background: var(--color-foreground);
top: 0;
left: -300px;
height: 100vh;
width: 280px;
padding: 0;
overflow-y: auto;
overflow-x: hidden;
z-index: 1002;
box-shadow: 0 15px 35px rgba(50, 50, 93, 0.1), 0 5px 15px rgba(0, 0, 0, 0.07) !important;
transition: left 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
html.leftbar-opened body.flinks-page #leftbar { left: 0px; }
body.flinks-page .leftbar-mobile-nav { display: flex; flex-direction: column; min-height: 100%; }
body.flinks-page .leftbar-desktop-content { display: none !important; }
/* 底部操作区固定在底部 */
body.flinks-page .leftbar-mobile-footer {
margin-top: auto;
position: sticky;
bottom: 0;
background: var(--color-foreground);
z-index: 10;
}
}
body.flinks-page #primary { width: 100% !important; max-width: 1000px !important; margin: 0 auto !important; float: none !important; }
body.flinks-page #content { margin-top: -50vh !important; }
.flinks-header-card { text-align: center; padding: 24px 24px 20px; background: transparent !important; box-shadow: none !important; }
.flinks-header-icon { width: 56px; height: 56px; margin: 0 auto 12px; background: var(--themecolor-gradient); border-radius: 14px; display: flex; align-items: center; justify-content: center; font-size: 24px; color: #fff; box-shadow: 0 4px 16px rgba(var(--themecolor-rgbstr), 0.25); }
.flinks-title { font-size: 22px; font-weight: 700; margin: 0 0 6px; color: var(--color-text-deeper); background: none !important; }
.flinks-title::before, .flinks-title::after { display: none !important; }
.flinks-subtitle { font-size: 13px; color: #888; margin: 0 0 12px; }
.flinks-stats { display: flex; justify-content: center; gap: 10px; }
.flinks-stat { display: inline-flex; align-items: center; gap: 5px; padding: 6px 14px; background: rgba(var(--themecolor-rgbstr), 0.1); border-radius: 16px; font-size: 12px; font-weight: 500; color: var(--themecolor); }
.flinks-welcome-text { font-size: 13px; color: #666; line-height: 1.6; margin-bottom: 12px; padding: 10px 14px; background: rgba(var(--themecolor-rgbstr), 0.05); border-radius: 8px; border-left: 3px solid var(--themecolor); }
.flinks-category-card { padding: 20px 24px; }
.flinks-category-header { display: flex; align-items: center; margin-bottom: 16px; padding-bottom: 12px; border-bottom: 2px solid rgba(var(--themecolor-rgbstr), 0.12); }
.flinks-category-title { font-size: 16px; font-weight: 600; margin: 0; color: var(--color-text-deeper); display: flex; align-items: center; gap: 8px; background: none !important; }
.flinks-category-title::before, .flinks-category-title::after { display: none !important; }
.flinks-category-title i { color: var(--themecolor); font-size: 14px; }
.flinks-category-count { margin-left: auto; font-size: 12px; font-weight: 500; color: var(--themecolor); background: rgba(var(--themecolor-rgbstr), 0.1); padding: 3px 12px; border-radius: 12px; }
.flinks-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.flink-card { display: flex; align-items: flex-start; gap: 14px; padding: 16px; background: var(--color-background); border-radius: var(--card-radius); text-decoration: none !important; color: inherit; border: 1px solid transparent; transition: border-color 0.2s, box-shadow 0.2s; min-height: 90px; position: relative; }
.flink-card:hover { border-color: rgba(var(--themecolor-rgbstr), 0.25); box-shadow: 0 4px 16px rgba(var(--themecolor-rgbstr), 0.1); }
.flink-card.editable { cursor: default; }
.flink-card .flink-edit-btn { position: absolute; top: 8px; right: 8px; width: 28px; height: 28px; border-radius: 6px; background: rgba(var(--themecolor-rgbstr), 0.1); color: var(--themecolor); border: none; cursor: pointer; display: none; align-items: center; justify-content: center; font-size: 12px; transition: background 0.2s; }
.flink-card:hover .flink-edit-btn { display: flex; }
.flink-card .flink-edit-btn:hover { background: rgba(var(--themecolor-rgbstr), 0.2); }
/* 状态标记 */
.flink-status-badge { position: absolute; top: 6px; right: 6px; font-size: 10px; padding: 2px 6px; border-radius: 4px; font-weight: 500; cursor: help; }
.flink-status-badge.no-backlink { background: #fef3c7; color: #d97706; }
.flink-status-badge.inaccessible { background: #fee2e2; color: #dc2626; }
.flink-status-badge.waf-blocked { background: #fce7f3; color: #db2777; }
.flink-status-badge.auto-approved { background: #d1fae5; color: #059669; cursor: pointer; }
.flink-card.editable .flink-status-badge { right: 40px; }
.flink-avatar { width: 52px; height: 52px; flex-shrink: 0; border-radius: 12px; background: var(--themecolor-gradient); display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 600; color: #fff; position: relative; overflow: hidden; box-shadow: 0 3px 10px rgba(var(--themecolor-rgbstr), 0.25); }
.flink-avatar::before { content: attr(data-letter); }
.flink-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 12px; }
.flink-info { flex: 1; min-width: 0; padding-top: 2px; }
.flink-name { font-size: 15px; font-weight: 600; color: var(--color-text-deeper); margin-bottom: 2px; display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.flink-name .main-name { }
.flink-name .sub-name { font-size: 12px; font-weight: 400; color: #999; }
.flink-verified { color: #22c55e; font-size: 12px; flex-shrink: 0; }
.flink-desc { font-size: 13px; color: #888; line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; margin-top: 4px; }
.flink-url { font-size: 12px; color: #aaa; margin-top: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.flinks-empty { padding: 60px 24px; text-align: center; }
.flinks-empty i { font-size: 48px; color: var(--color-border); margin-bottom: 16px; display: block; }
.flinks-empty p { font-size: 15px; color: #888; margin: 0; }
/* 申请区域 */
.flinks-apply-card { padding: 12px 18px; }
.flinks-apply-header { display: flex; align-items: center; justify-content: space-between; cursor: pointer; user-select: none; }
.flinks-apply-header:hover { opacity: 0.75; }
.flinks-apply-title { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; color: var(--themecolor); }
.flinks-apply-arrow { color: var(--themecolor); font-size: 12px; transition: transform 0.3s; }
.flinks-apply-arrow.open { transform: rotate(180deg); }
.flinks-apply-content { max-height: 0; overflow: hidden; transition: max-height 0.35s; }
.flinks-apply-content.open { max-height: 1200px; }
.flinks-requirements { background: rgba(var(--themecolor-rgbstr), 0.05); border-radius: var(--card-radius); padding: 10px 12px; margin: 10px 0 8px; border-left: 3px solid var(--themecolor); font-size: 13px; line-height: 1.5; }
.flinks-requirements p { margin: 0; }
.flinks-mysite-info { background: var(--color-background); border-radius: var(--card-radius); padding: 10px 12px; margin: 8px 0; }
.flinks-mysite-title { font-size: 12px; font-weight: 600; color: var(--themecolor); margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.flinks-mysite-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.flinks-mysite-item { background: var(--color-foreground); border-radius: calc(var(--card-radius) * 0.6); padding: 6px 10px; cursor: pointer; transition: background 0.2s; }
.flinks-mysite-item:hover { background: rgba(var(--themecolor-rgbstr), 0.08); }
.flinks-mysite-item label { display: block; font-size: 10px; color: #999; margin-bottom: 1px; text-transform: uppercase; pointer-events: none; }
.flinks-mysite-item span { font-size: 12px; color: var(--color-text-deeper); word-break: break-all; font-weight: 500; pointer-events: none; }
.flinks-form { margin-top: 8px; font-family: var(--font); }
.flinks-form .row { margin-left: -6px; margin-right: -6px; }
.flinks-form .row > [class*="col-"] { padding-left: 6px; padding-right: 6px; }
.flinks-form .form-group { margin-bottom: 8px; }
.flinks-form .form-control-label { font-size: 12px; font-weight: 600; margin-bottom: 3px; color: var(--color-text-deeper); display: block; font-family: var(--font); }
.flinks-form .form-control { border-radius: calc(var(--card-radius) * 0.6); border: 1px solid var(--color-border); padding: 7px 10px; font-size: 13px; font-family: var(--font); }
.flinks-form .form-control:focus { border-color: var(--themecolor); box-shadow: 0 0 0 2px rgba(var(--themecolor-rgbstr), 0.1); }
.flinks-form .char-count { font-size: 11px; color: #999; float: right; }
.flinks-submit { margin-top: 10px; text-align: center; }
.flinks-submit .btn { padding: 8px 24px; font-size: 13px; font-weight: 600; font-family: var(--font); }
/* 自动获取预览 */
.flinks-auto-preview { background: var(--color-background); border-radius: var(--card-radius); padding: 12px; margin: 10px 0; display: none; }
.flinks-auto-preview.show { display: block; }
.flinks-auto-preview-title { font-size: 12px; font-weight: 600; color: var(--themecolor); margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.flinks-auto-preview-content { display: flex; gap: 12px; align-items: flex-start; }
.flinks-auto-preview-avatar { width: 48px; height: 48px; border-radius: 10px; background: var(--color-border); flex-shrink: 0; overflow: hidden; }
.flinks-auto-preview-avatar img { width: 100%; height: 100%; object-fit: cover; }
.flinks-auto-preview-info { flex: 1; min-width: 0; }
.flinks-auto-preview-name { font-size: 14px; font-weight: 600; color: var(--color-text-deeper); }
.flinks-auto-preview-desc { font-size: 12px; color: #888; margin-top: 4px; }
/* 验证码 */
.flinks-captcha { margin-top: 10px; }
.flinks-captcha .input-group { max-width: 280px; }
.flinks-captcha-text { background: var(--color-background); font-family: monospace; font-size: 14px; letter-spacing: 2px; cursor: pointer; user-select: none; }
/* 管理面板 */
.flinks-admin-card { padding: 16px 20px; }
.flinks-admin-title { font-size: 15px; font-weight: 600; color: var(--themecolor); margin: 0 0 12px; display: flex; align-items: center; gap: 8px; }
.flinks-admin-section { margin-bottom: 16px; }
.flinks-admin-section:last-child { margin-bottom: 0; }
.flinks-admin-section h4 { font-size: 13px; font-weight: 600; color: var(--color-text-deeper); margin: 0 0 8px; display: flex; align-items: center; gap: 6px; }
.flinks-pending-item { display: flex; align-items: flex-start; gap: 12px; padding: 12px; background: #fffbeb; border: 1px solid #fcd34d; border-radius: var(--card-radius); margin-bottom: 8px; }
.flinks-pending-avatar { width: 40px; height: 40px; border-radius: 8px; background: var(--color-border); flex-shrink: 0; overflow: hidden; }
.flinks-pending-avatar img { width: 100%; height: 100%; object-fit: cover; }
.flinks-pending-info { flex: 1; min-width: 0; }
.flinks-pending-name { font-weight: 600; font-size: 14px; margin-bottom: 2px; }
.flinks-pending-name .sub-name { font-weight: 400; font-size: 12px; color: #888; margin-left: 6px; }
.flinks-pending-url { font-size: 12px; color: #666; margin-bottom: 4px; }
.flinks-pending-url a { color: var(--themecolor); }
.flinks-pending-desc { font-size: 12px; color: #888; }
.flinks-pending-actions { display: flex; gap: 6px; flex-shrink: 0; }
.flinks-pending-actions .btn { padding: 4px 12px; font-size: 12px; }
.flinks-add-form { background: var(--color-background); border-radius: var(--card-radius); padding: 14px; }
.flinks-add-form .form-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-bottom: 8px; }
.flinks-add-form .form-row.full { grid-template-columns: 1fr; }
.flinks-add-form label { font-size: 12px; font-weight: 500; color: var(--color-text-deeper); margin-bottom: 3px; display: block; }
.flinks-add-form input { width: 100%; padding: 6px 10px; font-size: 13px; border: 1px solid var(--color-border); border-radius: calc(var(--card-radius) * 0.6); font-family: var(--font); box-sizing: border-box; }
.flinks-add-form input:focus { border-color: var(--themecolor); outline: none; }
.flinks-add-form .input-with-btn { display: flex; gap: 6px; }
.flinks-add-form .input-with-btn input { flex: 1; min-width: 0; }
.flinks-add-form .input-with-btn .btn { flex-shrink: 0; padding: 6px 10px; font-size: 12px; }
.flinks-add-form .form-actions { margin-top: 10px; display: flex; gap: 8px; }
.flinks-add-form .form-actions .btn { display: inline-flex; align-items: center; justify-content: center; text-align: center; }
/* 编辑弹窗 */
.flink-modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 9998; display: none; align-items: center; justify-content: center; }
.flink-modal-overlay.show { display: flex; }
.flink-modal { background: var(--color-foreground); border-radius: var(--card-radius); padding: 20px; width: 90%; max-width: 500px; max-height: 90vh; overflow-y: auto; }
.flink-modal-title { font-size: 16px; font-weight: 600; margin-bottom: 16px; display: flex; align-items: center; justify-content: space-between; }
.flink-modal-close { background: none; border: none; font-size: 20px; cursor: pointer; color: #999; padding: 0; line-height: 1; }
.flink-modal .form-group { margin-bottom: 12px; }
.flink-modal .form-group label { font-size: 12px; font-weight: 600; color: var(--color-text-deeper); margin-bottom: 4px; display: block; }
.flink-modal .form-group input, .flink-modal .form-group select { width: 100%; padding: 8px 10px; font-size: 13px; border: 1px solid var(--color-border); border-radius: calc(var(--card-radius) * 0.6); font-family: var(--font); box-sizing: border-box; }
.flink-modal .form-group input:focus { border-color: var(--themecolor); outline: none; }
.flink-modal .form-actions { margin-top: 16px; display: flex; gap: 8px; justify-content: flex-end; flex-wrap: nowrap; }
.flink-modal .form-actions .btn { display: inline-flex; align-items: center; justify-content: center; text-align: center; min-width: auto; }
.flink-modal .btn-danger { background: #ef4444; border-color: #ef4444; }
.flink-modal .btn-danger:hover { background: #dc2626; border-color: #dc2626; }
.flink-modal .status-info { font-size: 12px; color: #888; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--color-border); }
.flink-modal .status-info .badge { font-size: 11px; padding: 2px 6px; border-radius: 4px; margin-left: 6px; }
.flink-modal .status-info .badge-warning { background: #fef3c7; color: #d97706; }
.flink-modal .status-info .badge-danger { background: #fee2e2; color: #dc2626; }
.flink-modal .status-info .badge-success { background: #d1fae5; color: #059669; }
@media (max-width: 768px) {
.flinks-grid { grid-template-columns: 1fr; }
.flinks-mysite-grid { grid-template-columns: 1fr; }
.flinks-add-form .form-row { grid-template-columns: 1fr; }
.flink-card { min-height: auto; }
}
html.darkmode .flink-card { background: rgba(255, 255, 255, 0.03); }
html.darkmode .flink-card:hover { background: rgba(255, 255, 255, 0.05); }
html.darkmode .flinks-pending-item { background: rgba(251, 191, 36, 0.1); border-color: rgba(251, 191, 36, 0.3); }
html.darkmode .flink-modal { background: var(--color-background); }
.flink-avatar[data-color="1"] { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }
.flink-avatar[data-color="2"] { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); }
.flink-avatar[data-color="3"] { background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); }
.flink-avatar[data-color="4"] { background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); }
.flink-avatar[data-color="5"] { background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); }
.flink-avatar[data-color="6"] { background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%); }
</style>
<script data-pjax>
(function() {
// 清理函数
function cleanupFlinksPage() {
document.body.classList.remove('flinks-page');
var s = document.getElementById('flinks-page-style');
if (s) s.remove();
}
// 先清理可能残留的状态(处理后退情况)
// 如果当前不是友链页面但有残留 class清理它
if (!document.getElementById('flinks-page-style')) {
document.body.classList.remove('flinks-page');
}
// 添加页面标识 class
document.body.classList.add('flinks-page');
// PJAX 离开时清理
if (typeof jQuery !== 'undefined') {
var $ = jQuery;
$(document).off('pjax:start.flinks pjax:popstate.flinks');
// 正常跳转离开
$(document).on('pjax:start.flinks', function() {
cleanupFlinksPage();
$(document).off('pjax:start.flinks pjax:popstate.flinks');
});
// 浏览器后退/前进
$(document).on('pjax:popstate.flinks', function() {
// 延迟检查,等 PJAX 完成内容替换
setTimeout(function() {
if (!document.getElementById('flinks-page-style')) {
document.body.classList.remove('flinks-page');
}
}, 50);
});
}
})();
</script>
<main id="main" class="site-main" role="main">
<?php
// 获取自定义标语
$flink_slogan = get_option('argon_friend_link_slogan', __('海内存知己,天涯若比邻', 'argon'));
$flink_welcome = get_option('argon_friend_link_welcome', __('欢迎与我交换友链!如果您的网站已添加本站链接,填写友链页面地址可自动通过审核。', 'argon'));
?>
<!-- 头部卡片 -->
<div class="flinks-header-card" style="margin-bottom: 16px;">
<div class="flinks-header-icon"><i class="fa fa-link"></i></div>
<h1 class="flinks-title"><?php _e('友情链接', 'argon'); ?></h1>
<p class="flinks-subtitle"><?php echo esc_html($flink_slogan); ?></p>
<div class="flinks-stats">
<div class="flinks-stat"><i class="fa fa-heart"></i><span><?php echo $total_links; ?> <?php _e('位朋友', 'argon'); ?></span></div>
<?php if (count($links) > 1) : ?>
<div class="flinks-stat"><i class="fa fa-folder-open"></i><span><?php echo count($links); ?> <?php _e('个分类', 'argon'); ?></span></div>
<?php endif; ?>
</div>
</div>
<!-- 管理面板(仅管理员可见) -->
<?php if ($is_admin) : ?>
<article class="post card shadow-sm bg-white border-0 flinks-admin-card" style="margin-bottom: 16px;" id="admin-panel">
<div class="flinks-admin-title"><i class="fa fa-cog"></i><?php _e('友链管理', 'argon'); ?> <button class="btn btn-sm btn-secondary" style="margin-left:auto;font-size:11px;" id="check-all-btn"><?php _e('检测所有友链', 'argon'); ?></button></div>
<?php if (!empty($pending_links)) : ?>
<div class="flinks-admin-section">
<h4><i class="fa fa-clock-o"></i> <?php _e('待审核', 'argon'); ?> (<?php echo count($pending_links); ?>)</h4>
<?php foreach ($pending_links as $link) :
$main_name = esc_html($link['name']);
$sub_name = !empty($link['display_name']) ? esc_html($link['display_name']) : '';
?>
<div class="flinks-pending-item" data-id="<?php echo esc_attr($link['id']); ?>">
<div class="flinks-pending-avatar">
<?php if (!empty($link['avatar'])) : ?><img src="<?php echo esc_url($link['avatar']); ?>" alt=""><?php endif; ?>
</div>
<div class="flinks-pending-info">
<div class="flinks-pending-name"><?php echo $main_name; ?><?php if ($sub_name) : ?><span class="sub-name"><?php echo $sub_name; ?></span><?php endif; ?></div>
<div class="flinks-pending-url"><a href="<?php echo esc_url($link['url']); ?>" target="_blank"><?php echo esc_html($link['url']); ?></a></div>
<?php if (!empty($link['description'])) : ?><div class="flinks-pending-desc"><?php echo esc_html($link['description']); ?></div><?php endif; ?>
</div>
<div class="flinks-pending-actions">
<button class="btn btn-sm btn-primary flink-approve" data-id="<?php echo esc_attr($link['id']); ?>"><?php _e('通过', 'argon'); ?></button>
<button class="btn btn-sm btn-secondary flink-reject" data-id="<?php echo esc_attr($link['id']); ?>"><?php _e('拒绝', 'argon'); ?></button>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<div class="flinks-admin-section">
<h4><i class="fa fa-plus"></i> <?php _e('添加友链', 'argon'); ?></h4>
<div class="flinks-add-form">
<div class="form-row">
<div>
<label><?php _e('网站地址', 'argon'); ?> *</label>
<div class="input-with-btn">
<input type="url" id="add-url" placeholder="https://example.com">
<button type="button" class="btn btn-secondary" id="fetch-info"><?php _e('获取', 'argon'); ?></button>
</div>
</div>
<div><label><?php _e('网站名称', 'argon'); ?> *</label><input type="text" id="add-name" placeholder="<?php _e('主标题', 'argon'); ?>"></div>
</div>
<div class="form-row">
<div><label><?php _e('副标题', 'argon'); ?></label><input type="text" id="add-display-name" placeholder="<?php _e('自动获取的标题', 'argon'); ?>"></div>
<div><label><?php _e('分类', 'argon'); ?></label><input type="text" id="add-category" placeholder="<?php _e('留空为默认', 'argon'); ?>"></div>
</div>
<div class="form-row">
<div><label><?php _e('头像', 'argon'); ?></label><input type="url" id="add-avatar" placeholder="<?php _e('自动获取', 'argon'); ?>"></div>
<div><label><?php _e('描述', 'argon'); ?></label><input type="text" id="add-desc" maxlength="100" placeholder="<?php _e('主描述', 'argon'); ?>"></div>
</div>
<div class="form-actions">
<button type="button" class="btn btn-primary" id="add-link-btn"><?php _e('添加', 'argon'); ?></button>
</div>
</div>
</div>
</article>
<?php endif; ?>
<!-- 友链列表 -->
<?php if (!empty($links)) : ?>
<?php $color_index = 0; foreach ($links as $category => $category_links) : ?>
<article class="post card shadow-sm bg-white border-0 flinks-category-card" style="margin-bottom: 16px;">
<div class="flinks-category-header">
<h2 class="flinks-category-title">
<i class="fa fa-<?php echo empty($category) ? 'star' : 'folder-open'; ?>"></i>
<?php echo empty($category) ? __('友情链接', 'argon') : esc_html($category); ?>
</h2>
<span class="flinks-category-count"><?php echo count($category_links); ?></span>
</div>
<div class="flinks-grid">
<?php foreach ($category_links as $link) :
$host = parse_url($link['url'], PHP_URL_HOST);
$main_name = $link['name'];
$sub_name = !empty($link['display_name']) ? $link['display_name'] : '';
$first_letter = mb_substr($main_name, 0, 1);
$color_index = ($color_index % 6) + 1;
$desc = !empty($link['description']) ? $link['description'] : (!empty($link['auto_description']) ? $link['auto_description'] : __('暂无描述', 'argon'));
// 状态检测
$has_backlink = isset($link['has_backlink']) ? $link['has_backlink'] : null;
$accessible = isset($link['accessible']) ? $link['accessible'] : null;
$blocked_by_waf = isset($link['blocked_by_waf']) ? $link['blocked_by_waf'] : false;
$error_reason = isset($link['error_reason']) ? $link['error_reason'] : '';
$auto_approved = !empty($link['auto_approved']);
$status_badge = '';
if ($is_admin) {
if ($blocked_by_waf) {
$status_badge = '<span class="flink-status-badge waf-blocked" title="' . esc_attr($error_reason) . '">' . __('WAF拦截', 'argon') . '</span>';
} elseif ($accessible === false) {
$title = $error_reason ? esc_attr($error_reason) : '';
$status_badge = '<span class="flink-status-badge inaccessible" title="' . $title . '">' . __('失效', 'argon') . '</span>';
} elseif ($has_backlink === false) {
$status_badge = '<span class="flink-status-badge no-backlink">' . __('未上链', 'argon') . '</span>';
} elseif ($auto_approved) {
$status_badge = '<span class="flink-status-badge auto-approved" data-id="' . esc_attr($link['id']) . '" onclick="event.preventDefault();event.stopPropagation();removeAutoTag(this)" title="' . __('点击移除标记', 'argon') . '">' . __('自动', 'argon') . '</span>';
}
}
?>
<a href="<?php echo esc_url($link['url']); ?>" class="flink-card <?php echo $is_admin ? 'editable' : ''; ?>" target="_blank" rel="noopener noreferrer" data-id="<?php echo esc_attr($link['id']); ?>">
<?php echo $status_badge; ?>
<?php if ($is_admin) : ?><button type="button" class="flink-edit-btn" onclick="event.preventDefault();event.stopPropagation();openEditModal('<?php echo esc_attr($link['id']); ?>')"><i class="fa fa-pencil"></i></button><?php endif; ?>
<div class="flink-avatar" data-letter="<?php echo esc_attr($first_letter); ?>" data-color="<?php echo $color_index; ?>">
<?php if (!empty($link['avatar'])) : ?><img src="<?php echo esc_url($link['avatar']); ?>" alt="" loading="lazy" onerror="this.style.display='none'"><?php endif; ?>
</div>
<div class="flink-info">
<div class="flink-name">
<span class="main-name"><?php echo esc_html($main_name); ?></span>
<?php if ($sub_name) : ?><span class="sub-name"><?php echo esc_html($sub_name); ?></span><?php endif; ?>
<?php if (!empty($link['verified'])) : ?><i class="fa fa-check-circle flink-verified"></i><?php endif; ?>
</div>
<div class="flink-desc"><?php echo esc_html($desc); ?></div>
<div class="flink-url"><i class="fa fa-link" style="margin-right:4px;font-size:10px;"></i><?php echo esc_html($host); ?></div>
</div>
</a>
<?php endforeach; ?>
</div>
</article>
<?php endforeach; ?>
<?php else : ?>
<article class="post card shadow-sm bg-white border-0 flinks-empty" style="margin-bottom: 16px;">
<i class="fa fa-inbox"></i>
<p><?php _e('暂无友情链接', 'argon'); ?></p>
</article>
<?php endif; ?>
<!-- 申请友链 -->
<?php if ($show_apply_form && !$is_admin) : ?>
<article class="post card shadow-sm bg-white border-0 flinks-apply-card" style="margin-bottom: 16px;" id="apply-section">
<div class="flinks-apply-header" onclick="toggleApplyForm()">
<div class="flinks-apply-title"><i class="fa fa-plus-circle"></i><span><?php _e('申请友链', 'argon'); ?></span></div>
<i class="fa fa-chevron-down flinks-apply-arrow <?php echo $apply_result ? 'open' : ''; ?>"></i>
</div>
<div class="flinks-apply-content <?php echo $apply_result ? 'open' : ''; ?>">
<?php if ($apply_result) : ?>
<div class="alert alert-<?php echo $apply_result['success'] ? 'success' : 'danger'; ?>" style="margin-top:10px;padding:8px 12px;font-size:13px;"><?php echo esc_html($apply_result['message']); ?></div>
<?php endif; ?>
<?php if (!empty($requirements)) : ?>
<div class="flinks-requirements"><?php echo wp_kses_post($requirements); ?></div>
<?php endif; ?>
<div class="flinks-welcome-text">
<?php echo wp_kses_post($flink_welcome); ?>
</div>
<div class="flinks-mysite-info">
<div class="flinks-mysite-title"><i class="fa fa-bookmark"></i><?php _e('本站信息(点击复制)', 'argon'); ?></div>
<div class="flinks-mysite-grid">
<div class="flinks-mysite-item" onclick="copyText('<?php echo esc_js(get_bloginfo('name')); ?>')"><label><?php _e('名称', 'argon'); ?></label><span><?php echo get_bloginfo('name'); ?></span></div>
<div class="flinks-mysite-item" onclick="copyText('<?php echo esc_js(home_url()); ?>')"><label><?php _e('地址', 'argon'); ?></label><span><?php echo home_url(); ?></span></div>
<div class="flinks-mysite-item" onclick="copyText('<?php echo esc_js(get_bloginfo('description')); ?>')"><label><?php _e('描述', 'argon'); ?></label><span><?php echo get_bloginfo('description') ?: '-'; ?></span></div>
</div>
</div>
<form method="post" action="<?php echo esc_url($_SERVER['REQUEST_URI']); ?>" class="flinks-form" id="apply-form">
<?php wp_nonce_field('argon_link_apply', 'argon_link_apply_nonce'); ?>
<input type="hidden" name="argon_link_apply" value="1">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="form-control-label"><?php _e('网站地址', 'argon'); ?> <span class="text-danger">*</span></label>
<input type="url" name="apply_url" id="apply-url" class="form-control" required placeholder="https://example.com">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="form-control-label"><?php _e('网站名称', 'argon'); ?></label>
<input type="text" name="apply_name" id="apply-name" class="form-control" placeholder="<?php _e('选填', 'argon'); ?>">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="form-control-label"><?php _e('网站图标', 'argon'); ?></label>
<input type="url" name="apply_avatar" id="apply-avatar" class="form-control" placeholder="<?php _e('选填', 'argon'); ?>">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="form-control-label"><?php _e('联系邮箱', 'argon'); ?></label>
<input type="email" name="apply_email" class="form-control" placeholder="<?php _e('选填', 'argon'); ?>">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="form-control-label"><?php _e('友链页面', 'argon'); ?> <small style="color:#4caf50;font-weight:normal;"><?php _e('填写可自动通过', 'argon'); ?></small></label>
<input type="url" name="apply_links_page" class="form-control" placeholder="<?php _e('您放置友链的页面地址', 'argon'); ?>">
</div>
</div>
<div class="col-12">
<div class="form-group">
<label class="form-control-label"><?php _e('网站描述', 'argon'); ?> <span class="char-count"><span id="desc-count">0</span>/100</span></label>
<textarea name="apply_description" id="apply-desc" class="form-control" maxlength="100" rows="2" placeholder="<?php _e('选填', 'argon'); ?>" oninput="document.getElementById('desc-count').textContent=this.value.length" style="resize:vertical;min-height:60px;"></textarea>
</div>
</div>
</div>
<!-- 验证码 -->
<?php if ($captcha_enabled) : ?>
<div class="flinks-captcha">
<?php if ($captcha_type === 'geetest') : ?>
<div id="flink-geetest-captcha"></div>
<input type="hidden" name="lot_number" id="flink-lot-number">
<input type="hidden" name="captcha_output" id="flink-captcha-output">
<input type="hidden" name="pass_token" id="flink-pass-token">
<input type="hidden" name="gen_time" id="flink-gen-time">
<?php else : ?>
<div class="input-group input-group-sm">
<input type="text" name="comment_captcha" id="flink-captcha-input" class="form-control" placeholder="<?php _e('验证码', 'argon'); ?>" required style="max-width:120px;">
<div class="input-group-append">
<span class="input-group-text flinks-captcha-text" id="flink-captcha-text" onclick="refreshCaptcha()" title="<?php _e('点击刷新', 'argon'); ?>"><?php echo get_comment_captcha(); ?></span>
</div>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="flinks-submit">
<button type="submit" class="btn btn-primary" id="apply-submit-btn"><i class="fa fa-paper-plane"></i> <?php _e('提交申请', 'argon'); ?></button>
</div>
</form>
</div>
</article>
<?php endif; ?>
<!-- 编辑弹窗 -->
<?php if ($is_admin) : ?>
<div class="flink-modal-overlay" id="edit-modal">
<div class="flink-modal">
<div class="flink-modal-title">
<span><i class="fa fa-pencil"></i> <?php _e('编辑友链', 'argon'); ?></span>
<button type="button" class="flink-modal-close" onclick="closeEditModal()">&times;</button>
</div>
<input type="hidden" id="edit-id">
<div class="form-group">
<label><?php _e('网站名称', 'argon'); ?> *</label>
<input type="text" id="edit-name" placeholder="<?php _e('主标题', 'argon'); ?>">
</div>
<div class="form-group">
<label><?php _e('副标题', 'argon'); ?></label>
<input type="text" id="edit-display-name" placeholder="<?php _e('自动获取的标题', 'argon'); ?>">
</div>
<div class="form-group">
<label><?php _e('网站地址', 'argon'); ?> *</label>
<input type="url" id="edit-url">
</div>
<div class="form-group">
<label><?php _e('友链页面', 'argon'); ?></label>
<input type="url" id="edit-links-page" placeholder="<?php _e('对方放置友链的页面地址', 'argon'); ?>">
</div>
<div class="form-group">
<label><?php _e('头像地址', 'argon'); ?></label>
<input type="url" id="edit-avatar">
</div>
<div class="form-group">
<label><?php _e('描述', 'argon'); ?></label>
<input type="text" id="edit-desc" maxlength="100">
</div>
<div class="form-group">
<label><?php _e('分类', 'argon'); ?></label>
<input type="text" id="edit-category">
</div>
<div class="form-group">
<label><?php _e('未上友链时', 'argon'); ?></label>
<select id="edit-hide-no-backlink">
<option value=""><?php _e('跟随全局设置', 'argon'); ?></option>
<option value="hide"><?php _e('隐藏', 'argon'); ?></option>
<option value="show"><?php _e('仍然显示', 'argon'); ?></option>
</select>
</div>
<div class="status-info" id="edit-status-info"></div>
<div class="form-actions">
<button type="button" class="btn btn-secondary" id="edit-fetch-btn"><?php _e('更新信息', 'argon'); ?></button>
<button type="button" class="btn btn-secondary" id="edit-check-btn"><?php _e('检测互链', 'argon'); ?></button>
<button type="button" class="btn btn-danger" id="edit-delete-btn"><?php _e('删除', 'argon'); ?></button>
<button type="button" class="btn btn-primary" id="edit-save-btn"><?php _e('保存', 'argon'); ?></button>
</div>
</div>
</div>
<?php endif; ?>
<script data-pjax>
function toggleApplyForm() {
var c = document.querySelector('.flinks-apply-content');
var a = document.querySelector('.flinks-apply-arrow');
if (c && a) { c.classList.toggle('open'); a.classList.toggle('open'); }
}
function copyText(t) {
navigator.clipboard ? navigator.clipboard.writeText(t).then(showCopyTip) : (function() {
var ta = document.createElement('textarea'); ta.value = t; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); showCopyTip();
})();
}
function showCopyTip() {
var tip = document.createElement('span');
tip.textContent = '<?php _e('已复制', 'argon'); ?>';
tip.style.cssText = 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(0,0,0,0.75);color:#fff;padding:10px 20px;border-radius:8px;font-size:14px;z-index:9999;';
document.body.appendChild(tip);
setTimeout(function() { tip.remove(); }, 1200);
}
// 刷新验证码
function refreshCaptcha() {
fetch('<?php echo admin_url('admin-ajax.php'); ?>?action=argon_get_captcha')
.then(function(r) { return r.json(); })
.then(function(res) {
if (res.captcha) {
document.getElementById('flink-captcha-text').textContent = res.captcha;
}
});
}
<?php if ($apply_result) : ?>
document.addEventListener('DOMContentLoaded', function() {
var s = document.getElementById('apply-section');
if (s) s.scrollIntoView({ behavior: 'smooth', block: 'center' });
// 清除 URL 中的申请结果参数
if (window.history && window.history.replaceState) {
var url = new URL(window.location.href);
url.searchParams.delete('apply_success');
url.searchParams.delete('apply_error');
window.history.replaceState({}, '', url.toString());
}
});
<?php endif; ?>
<?php if ($captcha_enabled && $captcha_type === 'geetest') : ?>
// 极验验证码
if (typeof initGeetest4 === 'function') {
initGeetest4({
captchaId: '<?php echo get_option('argon_geetest_captcha_id', ''); ?>',
product: 'bind'
}, function(captcha) {
captcha.appendTo('#flink-geetest-captcha');
document.getElementById('apply-submit-btn').addEventListener('click', function(e) {
e.preventDefault();
captcha.showCaptcha();
});
captcha.onSuccess(function() {
var result = captcha.getValidate();
document.getElementById('flink-lot-number').value = result.lot_number;
document.getElementById('flink-captcha-output').value = result.captcha_output;
document.getElementById('flink-pass-token').value = result.pass_token;
document.getElementById('flink-gen-time').value = result.gen_time;
document.getElementById('apply-form').submit();
});
});
}
<?php endif; ?>
<?php if ($is_admin) : ?>
(function() {
var nonce = '<?php echo wp_create_nonce('argon_flink_manage'); ?>';
var ajaxUrl = '<?php echo esc_url($_SERVER['REQUEST_URI']); ?>';
function flinkAction(action, data, callback) {
data.flink_action = action;
data.flink_nonce = nonce;
var fd = new FormData();
for (var k in data) fd.append(k, data[k]);
fetch(ajaxUrl, { method: 'POST', body: fd })
.then(function(r) { return r.json(); })
.then(callback)
.catch(function(e) { alert('<?php _e('操作失败', 'argon'); ?>'); });
}
// 移除自动审核标记
window.removeAutoTag = function(el) {
if (!confirm('<?php _e('确定移除自动审核标记?', 'argon'); ?>')) return;
var id = el.getAttribute('data-id');
flinkAction('update', { id: id, auto_approved: '' }, function(res) {
if (res.success) el.remove();
});
};
// 获取网站信息(服务器端)
document.getElementById('fetch-info')?.addEventListener('click', function() {
var url = document.getElementById('add-url').value.trim();
if (!url) return alert('<?php _e('请输入网址', 'argon'); ?>');
if (!/^https?:\/\//i.test(url)) url = 'https://' + url;
document.getElementById('add-url').value = url;
this.disabled = true; this.textContent = '...';
var btn = this;
flinkAction('fetch_info', { url: url }, function(res) {
btn.disabled = false; btn.textContent = '<?php _e('获取', 'argon'); ?>';
if (res.success && res.data) {
if (res.data.title) document.getElementById('add-display-name').value = res.data.title;
// 优先使用作者头像,没有才用 favicon
var avatar = res.data.author_avatar || res.data.favicon || '';
if (avatar) document.getElementById('add-avatar').value = avatar;
} else {
alert(res.message || '<?php _e('获取失败', 'argon'); ?>');
}
});
});
// 添加友链
document.getElementById('add-link-btn')?.addEventListener('click', function() {
var name = document.getElementById('add-name').value.trim();
var url = document.getElementById('add-url').value.trim();
if (!url) return alert('<?php _e('请填写网址', 'argon'); ?>');
if (!name) {
name = document.getElementById('add-display-name').value.trim();
if (!name) return alert('<?php _e('请填写名称', 'argon'); ?>');
}
this.disabled = true; this.textContent = '<?php _e('添加中...', 'argon'); ?>';
var btn = this;
flinkAction('add', {
name: name,
url: url,
display_name: document.getElementById('add-display-name').value.trim(),
avatar: document.getElementById('add-avatar').value.trim(),
description: document.getElementById('add-desc').value.trim(),
category: document.getElementById('add-category').value.trim()
}, function(res) {
if (res.success) location.reload();
else { btn.disabled = false; btn.textContent = '<?php _e('添加', 'argon'); ?>'; alert(res.message || '<?php _e('添加失败', 'argon'); ?>'); }
});
});
// 审核操作
document.querySelectorAll('.flink-approve').forEach(function(btn) {
btn.addEventListener('click', function() {
var id = this.dataset.id;
this.disabled = true;
flinkAction('approve', { id: id }, function(res) { if (res.success) location.reload(); });
});
});
document.querySelectorAll('.flink-reject').forEach(function(btn) {
btn.addEventListener('click', function() {
if (!confirm('<?php _e('确定拒绝?', 'argon'); ?>')) return;
var id = this.dataset.id;
this.disabled = true;
flinkAction('reject', { id: id }, function(res) { if (res.success) location.reload(); });
});
});
// 检测所有友链
document.getElementById('check-all-btn')?.addEventListener('click', function() {
if (!confirm('<?php _e('将检测所有友链的状态,可能需要一些时间,确定继续?', 'argon'); ?>')) return;
this.disabled = true; this.textContent = '<?php _e('检测中...', 'argon'); ?>';
flinkAction('check_all', {}, function(res) {
if (res.success) location.reload();
else alert('<?php _e('检测失败', 'argon'); ?>');
});
});
// 编辑弹窗
window.openEditModal = function(id) {
flinkAction('get', { id: id }, function(res) {
if (res.success && res.data) {
var link = res.data;
document.getElementById('edit-id').value = link.id;
document.getElementById('edit-name').value = link.name || '';
document.getElementById('edit-display-name').value = link.display_name || '';
document.getElementById('edit-url').value = link.url || '';
document.getElementById('edit-links-page').value = link.links_page || '';
document.getElementById('edit-avatar').value = link.avatar || '';
document.getElementById('edit-desc').value = link.description || '';
document.getElementById('edit-category').value = link.category || '';
document.getElementById('edit-hide-no-backlink').value = link.hide_no_backlink || '';
// 显示状态信息
var statusHtml = '';
if (link.last_check) {
var date = new Date(link.last_check * 1000);
statusHtml += '<?php _e('上次检测', 'argon'); ?>: ' + date.toLocaleString() + '<br>';
}
if (link.accessible === false) {
statusHtml += '<?php _e('网站状态', 'argon'); ?>: <span class="badge badge-danger"><?php _e('无法访问', 'argon'); ?></span><br>';
} else if (link.accessible === true) {
statusHtml += '<?php _e('网站状态', 'argon'); ?>: <span class="badge badge-success"><?php _e('正常', 'argon'); ?></span><br>';
}
if (link.has_backlink === false) {
statusHtml += '<?php _e('互链状态', 'argon'); ?>: <span class="badge badge-warning"><?php _e('未检测到本站链接', 'argon'); ?></span>';
} else if (link.has_backlink === true) {
statusHtml += '<?php _e('互链状态', 'argon'); ?>: <span class="badge badge-success"><?php _e('已上友链', 'argon'); ?></span>';
} else if (!link.links_page) {
statusHtml += '<?php _e('互链状态', 'argon'); ?>: <span class="badge badge-secondary"><?php _e('未填写友链页面', 'argon'); ?></span>';
}
document.getElementById('edit-status-info').innerHTML = statusHtml || '<?php _e('暂无检测记录', 'argon'); ?>';
document.getElementById('edit-modal').classList.add('show');
}
});
};
window.closeEditModal = function() {
document.getElementById('edit-modal').classList.remove('show');
};
document.getElementById('edit-modal')?.addEventListener('click', function(e) {
if (e.target === this) closeEditModal();
});
// 更新信息(从网站获取最新数据)
document.getElementById('edit-fetch-btn')?.addEventListener('click', function() {
var url = document.getElementById('edit-url').value.trim();
if (!url) return alert('<?php _e('请先填写网址', 'argon'); ?>');
if (!/^https?:\/\//i.test(url)) url = 'https://' + url;
this.disabled = true; this.textContent = '<?php _e('获取中...', 'argon'); ?>';
var btn = this;
flinkAction('fetch_info', { url: url }, function(res) {
btn.disabled = false; btn.textContent = '<?php _e('更新信息', 'argon'); ?>';
if (res.success && res.data) {
var displayName = document.getElementById('edit-display-name');
var avatar = document.getElementById('edit-avatar');
var desc = document.getElementById('edit-desc');
// 直接替换数据
if (res.data.title) displayName.value = res.data.title;
var newAvatar = res.data.author_avatar || res.data.favicon || '';
if (newAvatar) avatar.value = newAvatar;
if (res.data.description) desc.value = res.data.description;
// 显示获取结果
var statusInfo = document.getElementById('edit-status-info');
var infoHtml = '<div style="margin-top:10px;padding:10px;background:#e8f5e9;border-radius:6px;font-size:13px;">';
infoHtml += '<strong><?php _e('已更新', 'argon'); ?></strong>';
if (res.data.blocked_by_waf) {
infoHtml += ' <span style="color:#e91e63;">(<?php _e('被WAF拦截', 'argon'); ?>)</span>';
}
infoHtml += '</div>';
statusInfo.innerHTML = infoHtml;
} else {
alert(res.data?.error_reason || '<?php _e('获取失败', 'argon'); ?>');
}
});
});
// 检测互链
document.getElementById('edit-check-btn')?.addEventListener('click', function() {
var linksPage = document.getElementById('edit-links-page').value.trim();
if (!linksPage) {
return alert('<?php _e('请先填写对方的友链页面地址', 'argon'); ?>');
}
var id = document.getElementById('edit-id').value;
this.disabled = true; this.textContent = '<?php _e('检测中...', 'argon'); ?>';
var btn = this;
flinkAction('check_backlink', { id: id }, function(res) {
btn.disabled = false; btn.textContent = '<?php _e('检测互链', 'argon'); ?>';
if (res.success) {
openEditModal(id); // 刷新显示
}
});
});
// 保存编辑
document.getElementById('edit-save-btn')?.addEventListener('click', function() {
var id = document.getElementById('edit-id').value;
var name = document.getElementById('edit-name').value.trim();
var url = document.getElementById('edit-url').value.trim();
if (!name || !url) return alert('<?php _e('名称和网址不能为空', 'argon'); ?>');
this.disabled = true; this.textContent = '<?php _e('保存中...', 'argon'); ?>';
var btn = this;
flinkAction('update', {
id: id,
name: name,
display_name: document.getElementById('edit-display-name').value.trim(),
url: url,
links_page: document.getElementById('edit-links-page').value.trim(),
avatar: document.getElementById('edit-avatar').value.trim(),
description: document.getElementById('edit-desc').value.trim(),
category: document.getElementById('edit-category').value.trim(),
hide_no_backlink: document.getElementById('edit-hide-no-backlink').value
}, function(res) {
if (res.success) location.reload();
else { btn.disabled = false; btn.textContent = '<?php _e('保存', 'argon'); ?>'; alert('<?php _e('保存失败', 'argon'); ?>'); }
});
});
// 删除
document.getElementById('edit-delete-btn')?.addEventListener('click', function() {
if (!confirm('<?php _e('确定删除这个友链?', 'argon'); ?>')) return;
var id = document.getElementById('edit-id').value;
this.disabled = true; this.textContent = '<?php _e('删除中...', 'argon'); ?>';
flinkAction('delete', { id: id }, function(res) {
if (res.success) location.reload();
else alert('<?php _e('删除失败', 'argon'); ?>');
});
});
})();
<?php endif; ?>
</script>
<?php get_footer(); ?>