WP资源网插件教程:后台插件样式美化二次元版

 

<?php
/**
 * Plugin Name: Xd News List 二次元美化完整版
 * Plugin URI:
 * Description: WordPress资源列表插件,二次元动漫风后台、分栏卡片布局不拥挤、自定义HTML/CSS模板、支持文章/子比社区帖子、自定义模板变量、广告管理
 * Version: 2.06
 * Author: Dev
 * License: GPL2
 */

if (!defined('ABSPATH')) exit;

// ===================== 全局默认配置 =====================
$default_base_options = [
    'active_template'   => 'template1',
    'media_type'        => 'image',
    'banner_img'        => 'https://g.gtimg.cn/music/photo_new/T057XD001003CoPL62IyR9q.png',
    'banner_video'      => '',
    'banner_url'        => '',
    'show_privilege'    => '1',
    'posts_per_page'    => 38,
    'cat_ids'           => '',
    'exclude_pids'      => '',
    'only_sticky'       => '0',
    'stat_hours'        => 24,
    'data_source'       => 'post',
    'forum_ids'         => '',
    'forum_status'      => 'publish',
    'forum_exclude'     => '',
    'site_tip_text'     => '本站资源仅供学习,禁止商用',
    'copyright_text'    => '©2026 二次元资源站 版权所有'
];

$default_link_options = [
    'link1_text' => '商务合作',
    'link1_url'  => '',
    'link2_text' => '二次元交流群',
    'link2_url'  => '',
    'link3_text' => '资源求稿通道',
    'link3_url'  => ''
];

$default_ad_options = [
    'ad_switch'   => '1',
    'ad_mode'     => 'top',
    'ad_interval' => 3
];

$default_ad_list = [];

// ===================== 内置系统模板 =====================
function xd_news_get_system_templates(){
    return [
        'template1' => [
            'name' => '模板1:原版小刀左右分栏',
            'css'  => '',
            'html' => '
<div class="xd-news-wrap template1">
    <div class="index-news">
        <div class="index-news-tool left">
            {{banner_html}}
            <div class="index-news-tool-container">
                {{link_bar}}
                {{privilege_html}}
            </div>
        </div>
        <div class="index-news-article right">
            <div class="title">最近更新<font>+{{today_count}}</font></div>
            <div class="news-article_container" id="newslist">
                {{item_list}}
            </div>
            {{pagination}}
        </div>
    </div>
</div>
'
        ],
        'template2' => [
            'name' => '模板2:简约单列表',
            'css'  => '
.template2 {
    padding: 12px;
    border: 1px solid #eee;
    border-radius: 8px;
    background: #fff;
}
.template2 .title {
    font-size: 16px;
    font-weight: bold;
    margin-bottom: 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid #eee;
}
.template2 .page {
    margin-top: 15px;
    display: flex;
    gap: 10px;
    justify-content: center;
}
.template2 .page div {
    padding: 5px 16px;
    border: 1px solid #ddd;
    border-radius: 4px;
    cursor: pointer;
}
.template2 ul.page-item {
    list-style: none;
    padding: 0;
    margin: 0;
}
.template2 .item-post {
    padding: 8px 10px;
    margin: 4px 0;
    border-bottom: 1px solid #f5f5f5;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.template2 .item-ad {
    padding: 8px 10px;
    margin: 6px 0;
    background: #f8f8f8;
    border-radius: 6px;
}
.template2 .link-footer {
    margin-top: 16px;
    padding-top: 10px;
    border-top: 1px solid #eee;
    font-size: 13px;
}
',
            'html' => '
<div class="xd-news-wrap template2">
    <div class="title">最近更新 <span style="color:#f30;">+{{today_count}}</span></div>
    <div class="news-article_container" id="newslist">
        {{item_list}}
    </div>
    {{pagination}}
    <div class="link-footer">{{link_bar}}</div>
</div>
'
        ]
    ];
}

// ===================== 配置读取函数 =====================
function xd_news_get_all_templates(){
    $system = xd_news_get_system_templates();
    $user_tpl = get_option('xd_news_user_templates', []);
    return array_merge($system, $user_tpl);
}

function xd_get_base_options(){
    global $default_base_options;
    $opts = get_option('xd_news_base_options');
    return is_array($opts) ? array_merge($default_base_options, $opts) : $default_base_options;
}
function xd_get_link_options(){
    global $default_link_options;
    $opts = get_option('xd_news_link_options');
    return is_array($opts) ? array_merge($default_link_options, $opts) : $default_link_options;
}
function xd_get_ad_options(){
    global $default_ad_options;
    $opts = get_option('xd_news_ad_options');
    return is_array($opts) ? array_merge($default_ad_options, $opts) : $default_ad_options;
}
function xd_get_ad_list(){
    global $default_ad_list;
    $ads = get_option('xd_news_ad_list');
    return is_array($ads) ? $ads : $default_ad_list;
}

// ===================== 注册配置项 =====================
function xd_news_register_setting(){
    global $default_base_options, $default_link_options, $default_ad_options, $default_ad_list;
    register_setting('xd_base_group', 'xd_news_base_options', [
        'sanitize_callback' => 'xd_news_sanitize_base',
        'default' => $default_base_options
    ]);
    register_setting('xd_link_group', 'xd_news_link_options', [
        'sanitize_callback' => 'xd_news_sanitize_link',
        'default' => $default_link_options
    ]);
    register_setting('xd_ad_set_group', 'xd_news_ad_options', [
        'sanitize_callback' => 'xd_news_sanitize_ad_set',
        'default' => $default_ad_options
    ]);
    register_setting('xd_news_ad_group', 'xd_news_ad_list', [
        'sanitize_callback' => 'xd_news_sanitize_ad_list',
        'default' => $default_ad_list
    ]);
    register_setting('xd_tpl_group', 'xd_news_user_templates');
}
add_action('admin_init', 'xd_news_register_setting');

// ===================== 数据清洗过滤 =====================
function xd_news_sanitize_base($input){
    global $default_base_options;
    $out = [];
    $tpl_list = array_keys(xd_news_get_all_templates());
    $out['active_template'] = in_array($input['active_template'], $tpl_list) ? $input['active_template'] : 'template1';
    $out['media_type'] = $input['media_type'] === 'video' ? 'video' : 'image';
    $out['banner_img'] = esc_url_raw($input['banner_img']);
    $out['banner_video'] = esc_url_raw($input['banner_video']);
    $out['banner_url'] = esc_url_raw($input['banner_url']);
    $out['show_privilege'] = $input['show_privilege'] === '1' ? '1' : '0';
    $out['posts_per_page'] = max(1, absint($input['posts_per_page']));
    $out['cat_ids'] = sanitize_text_field($input['cat_ids']);
    $out['exclude_pids'] = sanitize_text_field($input['exclude_pids']);
    $out['only_sticky'] = $input['only_sticky'] === '1' ? '1' : '0';
    $out['stat_hours'] = max(1, absint($input['stat_hours']));
    $out['data_source'] = $input['data_source'] === 'forum' ? 'forum' : 'post';
    $out['forum_ids'] = sanitize_text_field($input['forum_ids']);
    $out['forum_status'] = sanitize_text_field($input['forum_status']);
    $out['forum_exclude'] = sanitize_text_field($input['forum_exclude']);
    $out['site_tip_text'] = sanitize_text_field($input['site_tip_text']);
    $out['copyright_text'] = sanitize_text_field($input['copyright_text']);
    return $out;
}
function xd_news_sanitize_link($input){
    global $default_link_options;
    $out = [];
    $out['link1_text'] = sanitize_text_field($input['link1_text']);
    $out['link1_url'] = esc_url_raw($input['link1_url']);
    $out['link2_text'] = sanitize_text_field($input['link2_text']);
    $out['link2_url'] = esc_url_raw($input['link2_url']);
    $out['link3_text'] = sanitize_text_field($input['link3_text']);
    $out['link3_url'] = esc_url_raw($input['link3_url']);
    return $out;
}
function xd_news_sanitize_ad_set($input){
    global $default_ad_options;
    $out = [];
    $out['ad_switch'] = $input['ad_switch'] === '1' ? '1' : '0';
    $out['ad_mode'] = $input['ad_mode'] === 'split' ? 'split' : 'top';
    $out['ad_interval'] = max(1, absint($input['ad_interval']));
    return $out;
}
function xd_news_sanitize_ad_list($input){
    if (!is_array($input)) return [];
    $clean = [];
    foreach ($input as $ad) {
        if (empty($ad['text'])) continue;
        $clean[] = [
            'link' => esc_url_raw($ad['link']),
            'text' => sanitize_text_field($ad['text']),
            'color' => sanitize_hex_color($ad['color']) ?: '#32cd99'
        ];
    }
    return $clean;
}

// ===================== 后台菜单与资源 =====================
function xd_news_add_menu(){
    add_options_page(
        'Xd‑News 二次元配置面板',
        'Xd‑二次元列表配置',
        'manage_options',
        'xd‑news‑config',
        'xd_news_admin_page'
    );
}
add_action('admin_menu', 'xd_news_add_menu');
function xd_enqueue_admin_media(){
    wp_enqueue_media();
}
add_action('admin_enqueue_scripts', 'xd_enqueue_admin_media');

// ===================== 二次元美化后台页面完整代码 =====================
function xd_news_admin_page(){
    $base_opts = xd_get_base_options();
    $link_opts = xd_get_link_options();
    $ad_set = xd_get_ad_options();
    $ad_list = xd_get_ad_list();
    $has_forum = post_type_exists('forum_post');
    $all_tpl = xd_news_get_all_templates();
    $system_tpl = xd_news_get_system_templates();
    $user_tpl = get_option('xd_news_user_templates', []);

    // 保存自定义模板
    if(isset($_POST['save_custom_tpl']) && wp_verify_nonce($_POST['xd_tpl_nonce'], 'xd_tpl_action')){
        $tpl_id = sanitize_text_field($_POST['tpl_id']);
        $tpl_name = sanitize_text_field($_POST['tpl_name']);
        $tpl_css = stripslashes($_POST['tpl_css']);
        $tpl_html = stripslashes($_POST['tpl_html']);
        $user_tpl[$tpl_id] = ['name' => $tpl_name, 'css' => $tpl_css, 'html' => $tpl_html];
        update_option('xd_news_user_templates', $user_tpl);
        echo '<div class="notice notice-success anime-notice-success"><p>🌸 自定义模板保存成功!</p></div>';
    }
    // 删除模板
    if(isset($_GET['del_tpl'])){
        $del_id = sanitize_text_field($_GET['del_tpl']);
        if(!isset($system_tpl[$del_id]) && isset($user_tpl[$del_id])){
            unset($user_tpl[$del_id]);
            update_option('xd_news_user_templates', $user_tpl);
            echo '<div class="notice notice-success anime-notice-success"><p>🌸 模板已删除</p></div>';
        }
    }
    $edit_id = isset($_GET['edit_tpl']) ? sanitize_text_field($_GET['edit_tpl']) : '';
    $edit_data = $edit_id && isset($all_tpl[$edit_id]) ? $all_tpl[$edit_id] : ['name'=>'','css'=>'','html'=>''];
    ?>
    <style>
        .wrap {background: linear-gradient(135deg, #fff5fb 0%, #f0f8ff 100%);padding:20px;border-radius:16px;}
        .wrap h2 {color:#9340b7;font-size:26px;font-weight:bold;text-shadow:0 0 6px #ffc0e8;display:flex;align-items:center;gap:10px;}
        .wrap h2::before {content:"🌸";font-size:30px;}
        .anime-notice-success {border-left:5px solid #ff88bb;background:#fff0f8;border-radius:10px;box-shadow:0 2px 12px #ffd8ec;}
        .notice-warning {border-left:5px solid #9168d8;background:#f8f0ff;border-radius:10px;box-shadow:0 2px 12px #e8d8ff;}
        .xd-tab-nav {display:flex;gap:8px;margin:20px 0;border-bottom:none;flex-wrap:wrap;}
        .xd-tab-btn {padding:10px 22px;border:none;border-radius:999px;background:linear-gradient(135deg,#e8c8ff,#ffd8ef);color:#622080;font-weight:500;cursor:pointer;transition:all 0.3s ease;box-shadow:0 2px 8px #e0c0f0;}
        .xd-tab-btn.active {background:linear-gradient(135deg,#b878e8,#ff88bb);color:#fff;box-shadow:0 3px 14px #d090e8;transform:translateY(-2px);}
        .xd-tab-btn:hover {transform:translateY(-2px);}
        .xd-tab-content {display:none;}
        .anime-card {background:#fff;border-radius:18px;padding:24px;margin-bottom:24px;box-shadow:0 4px 18px rgba(180,120,230,0.12);border:1px solid #f0e0ff;}
        .anime-card-title {font-size:18px;font-weight:bold;color:#9340b7;margin:0 0 18px 0;padding-bottom:10px;border-bottom:2px dashed #e8ccff;display:flex;align-items:center;gap:8px;}
        .anime-card-title::before {content:"✨";}
        .form-table {margin:0;}
        .form-table th {width:240px;color:#703090;font-weight:500;padding:14px 10px;}
        .form-table td {padding:14px 10px;}
        .regular-text,input[type="url"],input[type="number"] {border:1px solid #e0c8f0;border-radius:12px;padding:10px 14px;width:100%;max-width:600px;background:#fcfaff;transition:0.2s;}
        .regular-text:focus,input[type="url"]:focus,input[type="number"]:focus {outline:none;border-color:#b878e8;box-shadow:0 0 0 3px rgba(184,120,232,0.18);}
        textarea {border:1px solid #e0c8f0;border-radius:12px;padding:12px 16px;background:#fcfaff;width:100%;}
        .tpl-code-box {background:#2a2438 !important;color:#e8e0ff !important;font-family:Consolas,monospace;}
        select {border:1px solid #e0c8f0;border-radius:12px;padding:10px 14px;background:#fcfaff;min-width:320px;}
        .button,.button-primary {border-radius:999px !important;padding:8px 20px !important;border:none !important;box-shadow:0 2px 10px rgba(184,120,232,0.2);}
        .button-primary {background:linear-gradient(135deg,#b878e8,#ff88bb) !important;color:#fff !important;}
        .button {background:#f0e8ff !important;color:#703090 !important;}
        .tpl-wrap {display:grid;grid-template-columns:300px 1fr;gap:24px;}
        .tpl-list-box {background:#fcfaff;border-radius:16px;padding:18px;border:1px dashed #e0c8f0;}
        .tpl-list-box h4 {color:#9340b7;margin-top:0;}
        .tpl-list-box li {padding:6px 0;}
        .tpl-list-box a {color:#b858c8;}
        .tpl-list-box a[href*="del_tpl"] {color:#e05088;}
        .ad-item {background:#fcfaff;border-radius:14px;padding:16px;margin:12px 0;border:1px dashed #f0d8f8;}
        .description {color:#9060b0;font-size:13px;margin-top:6px;}
        @media (max-width:1200px){.tpl-wrap {grid-template-columns:1fr;}}
    </style>
    <div class="wrap">
        <h2>Xd二次元资源列表|可视化模板配置面板</h2>
        <?php if ($base_opts['data_source'] === 'forum' && !$has_forum): ?>
        <div class="notice notice-warning"><p>⚠️ 未检测到子比社区 forum_post 帖子类型,请开启社区圈子功能,否则前台无板块数据。</p></div>
        <?php endif; ?>
        <div class="xd-tab-nav">
            <button class="xd-tab-btn active" data-tab="tab-base">基础全局设置</button>
            <button class="xd-tab-btn" data-tab="tab-tpl">🎨 自定义模板管理</button>
            <button class="xd-tab-btn" data-tab="tab-link">底部链接配置</button>
            <button class="xd-tab-btn" data-tab="tab-ad">广告系统管理</button>
        </div>
        <!-- 基础设置标签页 -->
        <div class="xd-tab-content" id="tab-base">
            <form method="post" action="options.php">
                <?php settings_fields('xd_base_group'); ?>
                <div class="anime-card">
                    <h3 class="anime-card-title">启用模板选择</h3>
                    <table class="form-table">
                        <tr>
                            <th>当前前端展示模板</th>
                            <td>
                                <select name="xd_news_base_options[active_template]">
                                    <?php foreach ($all_tpl as $tid => $tpl): ?>
                                    <option value="<?php echo esc_attr($tid); ?>" <?php selected($base_opts['active_template'], $tid); ?>>
                                        <?php echo esc_html($tpl['name']); ?>
                                    </option>
                                    <?php endforeach; ?>
                                </select>
                                <p class="description">新增/修改模板请切换到「自定义模板管理」标签页。</p>
                            </td>
                        </tr>
                    </table>
                </div>
                <div class="anime-card">
                    <h3 class="anime-card-title">内容数据源设置</h3>
                    <table class="form-table">
                        <tr>
                            <th>读取内容来源</th>
                            <td>
                                <label><input type="radio" name="xd_news_base_options[data_source]" value="post" <?php checked($base_opts['data_source'], 'post'); ?>> WordPress普通文章</label>
                                &nbsp;&nbsp;&nbsp;
                                <label><input type="radio" name="xd_news_base_options[data_source]" value="forum" <?php checked($base_opts['data_source'], 'forum'); ?>> 子比社区帖子 forum_post</label>
                            </td>
                        </tr>
                    </table>
                </div>
                <div class="anime-card">
                    <h3 class="anime-card-title">轮播图 & 特权模块</h3>
                    <table class="form-table">
                        <tr>
                            <th>轮播媒体类型</th>
                            <td>
                                <label><input type="radio" name="xd_news_base_options[media_type]" value="image" <?php checked($base_opts['media_type'], 'image'); ?>> 图片轮播</label>
                                &nbsp;&nbsp;&nbsp;
                                <label><input type="radio" name="xd_news_base_options[media_type]" value="video" <?php checked($base_opts['media_type'], 'video'); ?>> MP4视频轮播</label>
                            </td>
                        </tr>
                        <tr class="row-image">
                            <th>轮播图地址</th>
                            <td>
                                <input type="text" id="banner_img" name="xd_news_base_options[banner_img]" value="<?php echo esc_attr($base_opts['banner_img']); ?>" class="regular-text">
                                <input type="button" class="button xd-upload-img" value="选择图片">
                                <p><img id="preview_img" src="<?php echo esc_attr($base_opts['banner_img']); ?>" style="max-width:300px;margin-top:10px;border-radius:12px;"></p>
                            </td>
                        </tr>
                        <tr class="row-video" style="display:none;">
                            <th>轮播视频地址</th>
                            <td>
                                <input type="text" id="banner_video" name="xd_news_base_options[banner_video]" value="<?php echo esc_attr($base_opts['banner_video']); ?>" class="regular-text">
                                <input type="button" class="button xd-upload-video" value="上传视频">
                                <?php if (!empty($base_opts['banner_video'])): ?>
                                <p style="margin-top:10px;"><video style="max-width:300px;border-radius:12px;" controls src="<?php echo esc_attr($base_opts['banner_video']); ?>"></video></p>
                                <?php endif; ?>
                            </td>
                        </tr>
                        <tr>
                            <th>轮播跳转链接</th>
                            <td><input type="url" name="xd_news_base_options[banner_url]" value="<?php echo esc_attr($base_opts['banner_url']); ?>" class="regular-text"></td>
                        </tr>
                        <tr>
                            <th>右侧特权模块开关</th>
                            <td>
                                <label><input type="radio" name="xd_news_base_options[show_privilege]" value="1" <?php checked($base_opts['show_privilege'], '1'); ?>> 开启</label>
                                &nbsp;&nbsp;&nbsp;
                                <label><input type="radio" name="xd_news_base_options[show_privilege]" value="0" <?php checked($base_opts['show_privilege'], '0'); ?>> 关闭</label>
                            </td>
                        </tr>
                    </table>
                </div>
                <div class="anime-card">
                    <h3 class="anime-card-title">内容筛选过滤</h3>
                    <table class="form-table">
                        <tr><th colspan="2" style="color:#b858c8;font-weight:bold;">WordPress文章筛选</th></tr>
                        <tr><th>读取分类ID(逗号分隔)</th><td><input type="text" name="xd_news_base_options[cat_ids]" value="<?php echo esc_attr($base_opts['cat_ids']); ?>" class="regular-text" placeholder="1,2,10"></td></tr>
                        <tr><th>排除文章ID</th><td><input type="text" name="xd_news_base_options[exclude_pids]" value="<?php echo esc_attr($base_opts['exclude_pids']); ?>" class="regular-text" placeholder="5,12"></td></tr>
                        <tr>
                            <th>仅展示置顶文章</th>
                            <td>
                                <label><input type="radio" name="xd_news_base_options[only_sticky]" value="1" <?php checked($base_opts['only_sticky'], '1'); ?>> 开启</label>
                                &nbsp;&nbsp;&nbsp;
                                <label><input type="radio" name="xd_news_base_options[only_sticky]" value="0" <?php checked($base_opts['only_sticky'], '0'); ?>> 关闭</label>
                            </td>
                        </tr>
                        <tr><th colspan="2" style="color:#b858c8;font-weight:bold;margin-top:10px;">子比社区帖子筛选 plate_id</th></tr>
                        <tr><th>指定板块 plate_id</th><td><input type="text" name="xd_news_base_options[forum_ids]" value="<?php echo esc_attr($base_opts['forum_ids']); ?>" class="regular-text" placeholder="3,7,9"></td></tr>
                        <tr>
                            <th>帖子读取状态</th>
                            <td>
                                <select name="xd_news_base_options[forum_status]">
                                    <option value="publish" <?php selected($base_opts['forum_status'], 'publish'); ?>>正常发布帖子</option>
                                    <option value="pending" <?php selected($base_opts['forum_status'], 'pending'); ?>>待审核帖子</option>
                                    <option value="trash" <?php selected($base_opts['forum_status'], 'trash'); ?>>回收站</option>
                                </select>
                            </td>
                        </tr>
                        <tr><th>排除帖子ID</th><td><input type="text" name="xd_news_base_options[forum_exclude]" value="<?php echo esc_attr($base_opts['forum_exclude']); ?>" class="regular-text" placeholder="18,22"></td></tr>
                    </table>
                </div>
                <div class="anime-card">
                    <h3 class="anime-card-title">分页、统计与自定义变量</h3>
                    <table class="form-table">
                        <tr><th>统计更新小时数</th><td><input type="number" min="1" name="xd_news_base_options[stat_hours]" value="<?php echo esc_attr($base_opts['stat_hours']); ?>"> 小时内更新内容标记为红色日期</td></tr>
                        <tr><th>单页展示条数(广告+内容)</th><td><input type="number" min="1" name="xd_news_base_options[posts_per_page]" value="<?php echo esc_attr($base_opts['posts_per_page']); ?>"> 超出自动分到下一页</td></tr>
                        <tr><th colspan="2" style="color:#b858c8;font-weight:bold;margin-top:10px;">模板自定义变量</th></tr>
                        <tr><th>站点提示文字 {{site_tip}}</th><td><input type="text" name="xd_news_base_options[site_tip_text]" value="<?php echo esc_attr($base_opts['site_tip_text']); ?>" class="regular-text"></td></tr>
                        <tr><th>底部版权文字 {{copyright}}</th><td><input type="text" name="xd_news_base_options[copyright_text]" value="<?php echo esc_attr($base_opts['copyright_text']); ?>" class="regular-text"></td></tr>
                    </table>
                </div>
                <?php submit_button('🌸 保存全部基础设置'); ?>
            </form>
        </div>
        <!-- 模板管理标签页 -->
        <div class="xd-tab-content" id="tab-tpl" style="display:none;">
            <div class="anime-card">
                <h3 class="anime-card-title">自定义模板编辑器|粘贴HTML+CSS即可生成新样式</h3>
                <div class="tpl-wrap">
                    <div class="tpl-list-box">
                        <h4>全部模板列表</h4>
                        <ul style="padding-left:15px;">
                            <?php foreach ($all_tpl as $tid => $tpl): ?>
                            <li>
                                <?php echo esc_html($tpl['name']); ?>
                                <a href="?page=xd-news-config&edit_tpl=<?php echo esc_attr($tid); ?>">编辑</a>
                                <?php if (!isset($system_tpl[$tid])): ?>
                                <a href="?page=xd-news-config&del_tpl=<?php echo esc_attr($tid); ?>" onclick="return confirm('确定删除该自定义模板?')">删除</a>
                                <?php endif; ?>
                            </li>
                            <?php endforeach; ?>
                        </ul>
                        <hr style="border-color:#e0d8f8;">
                        <a href="?page=xd-news-config&edit_tpl=new" class="button button-primary" style="margin-top:10px;">➕ 新增自定义模板</a>
                    </div>
                    <div>
                        <?php $form_tid = $edit_id ?: uniqid('user_tpl_'); ?>
                        <form method="post">
                            <?php wp_nonce_field('xd_tpl_action', 'xd_tpl_nonce'); ?>
                            <input type="hidden" name="save_custom_tpl" value="1">
                            <input type="hidden" name="tpl_id" value="<?php echo esc_attr($form_tid); ?>">
                            <table class="form-table">
                                <tr><th>模板展示名称</th><td><input type="text" name="tpl_name" value="<?php echo esc_attr($edit_data['name']); ?>" class="regular-text" required placeholder="例如:二次元卡片资源模板"></td></tr>
                                <tr>
                                    <th>独立自定义CSS样式</th>
                                    <td>
                                        <textarea name="tpl_css" rows="8" class="tpl-code-box"><?php echo esc_textarea($edit_data['css']); ?></textarea>
                                        <p class="description">仅作用于当前模板,无需添加 &lt;style&gt; 标签。</p>
                                    </td>
                                </tr>
                                <tr>
                                    <th>HTML结构代码(支持变量)</th>
                                    <td>
                                        <textarea name="tpl_html" rows="14" class="tpl-code-box" required><?php echo esc_textarea($edit_data['html']); ?></textarea>
                                        <p class="description">可用变量:{{today_count}} {{banner_html}} {{privilege_html}} {{link_bar}} {{item_list}} {{pagination}} {{site_tip}} {{copyright}}</p>
                                    </td>
                                </tr>
                            </table>
                            <?php submit_button('💜 保存模板代码'); ?>
                        </form>
                    </div>
                </div>
            </div>
        </div>
        <!-- 底部链接标签页 -->
        <div class="xd-tab-content" id="tab-link" style="display:none;">
            <div class="anime-card">
                <h3 class="anime-card-title">底部文字链接配置</h3>
                <form method="post" action="options.php">
                    <?php settings_fields('xd_link_group'); ?>
                    <table class="form-table">
                        <tr><th>链接1显示文字</th><td><input type="text" name="xd_news_link_options[link1_text]" value="<?php echo esc_attr($link_opts['link1_text']); ?>" class="regular-text"></td></tr>
                        <tr><th>链接1跳转地址(可留空)</th><td><input type="text" name="xd_news_link_options[link1_url]" value="<?php echo esc_attr($link_opts['link1_url']); ?>" class="regular-text"></td></tr>
                        <tr><th>链接2显示文字</th><td><input type="text" name="xd_news_link_options[link2_text]" value="<?php echo esc_attr($link_opts['link2_text']); ?>" class="regular-text"></td></tr>
                        <tr><th>链接2跳转地址(可留空)</th><td><input type="text" name="xd_news_link_options[link2_url]" value="<?php echo esc_attr($link_opts['link2_url']); ?>" class="regular-text"></td></tr>
                        <tr><th>链接3显示文字</th><td><input type="text" name="xd_news_link_options[link3_text]" value="<?php echo esc_attr($link_opts['link3_text']); ?>" class="regular-text"></td></tr>
                        <tr><th>链接3跳转地址(可留空)</th><td><input type="text" name="xd_news_link_options[link3_url]" value="<?php echo esc_attr($link_opts['link3_url']); ?>" class="regular-text"></td></tr>
                    </table>
                    <?php submit_button('🌸 保存链接设置'); ?>
                </form>
            </div>
        </div>
        <!-- 广告管理标签页 -->
        <div class="xd-tab-content" id="tab-ad" style="display:none;">
            <div class="anime-card">
                <h3 class="anime-card-title">广告全局控制</h3>
                <form method="post" action="options.php">
                    <?php settings_fields('xd_ad_set_group'); ?>
                    <table class="form-table">
                        <tr>
                            <th>广告总开关</th>
                            <td>
                                <label><input type="radio" name="xd_news_ad_options[ad_switch]" value="1" <?php checked($ad_set['ad_switch'], '1'); ?>> 开启广告展示</label>
                                &nbsp;&nbsp;&nbsp;
                                <label><input type="radio" name="xd_news_ad_options[ad_switch]" value="0" <?php checked($ad_set['ad_switch'], '0'); ?>> 完全关闭广告</label>
                            </td>
                        </tr>
                        <tr>
                            <th>广告展示模式</th>
                            <td>
                                <label><input type="radio" name="xd_news_ad_options[ad_mode]" value="top" <?php checked($ad_set['ad_mode'], 'top'); ?>> 全部置顶顶部</label>
                                &nbsp;&nbsp;&nbsp;
                                <label><input type="radio" name="xd_news_ad_options[ad_mode]" value="split" <?php checked($ad_set['ad_mode'], 'split'); ?>> 间隔穿插内容中间</label>
                            </td>
                        </tr>
                        <tr><th>每多少条内容插入广告</th><td><input type="number" min="1" name="xd_news_ad_options[ad_interval]" value="<?php echo esc_attr($ad_set['ad_interval']); ?>"></td></tr>
                    </table>
                    <?php submit_button('🌸 保存广告全局设置'); ?>
                </form>
            </div>
            <div class="anime-card">
                <h3 class="anime-card-title">自定义广告条目</h3>
                <form method="post" action="options.php" id="ad-form">
                    <?php settings_fields('xd_news_ad_group'); ?>
                    <table class="form-table" id="ad-table">
                        <?php if (!empty($ad_list)): foreach ($ad_list as $idx => $ad): ?>
                        <tr class="ad-item">
                            <th>广告 #<?php echo $idx + 1; ?></th>
                            <td>
                                <div style="margin:8px 0;">
                                    <label>跳转链接(可空):</label>
                                    <input type="url" name="xd_news_ad_list[<?php echo $idx; ?>][link]" value="<?php echo esc_attr($ad['link']); ?>" class="regular-text">
                                </div>
                                <div style="margin:8px 0;">
                                    <label>广告文字:</label>
                                    <input type="text" name="xd_news_ad_list[<?php echo $idx; ?>][text]" value="<?php echo esc_attr($ad['text']); ?>" class="regular-text" required>
                                </div>
                                <div style="margin:8px 0;display:flex;align-items:center;gap:10px;">
                                    <label>文字颜色:</label>
                                    <input type="color" name="xd_news_ad_list[<?php echo $idx; ?>][color]" value="<?php echo esc_attr($ad['color']); ?>">
                                    <button type="button" class="button del-ad">删除本条广告</button>
                                </div>
                            </td>
                        </tr>
                        <?php endforeach; endif; ?>
                    </table>
                    <div style="margin-top:10px;display:flex;gap:12px;align-items:center;">
                        <button type="button" class="button button-primary" id="add-ad">➕ 新增一条广告</button>
                        <?php submit_button('💜 保存全部广告条目', 'primary', 'submit', false); ?>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <script>
    jQuery(function($){
        $('.xd-tab-btn').click(function(){
            const tabId = $(this).data('tab');
            $('.xd-tab-btn').removeClass('active');
            $(this).addClass('active');
            $('.xd-tab-content').hide();
            $('#' + tabId).show();
        });
        function toggleMediaRow(){
            const type = $('input[name="xd_news_base_options[media_type]"]:checked').val();
            $('.row-image').toggle(type === 'image');
            $('.row-video').toggle(type === 'video');
        }
        toggleMediaRow();
        $('input[name="xd_news_base_options[media_type]"]').change(toggleMediaRow);
        let frameImg;
        $('.xd-upload-img').click(function(){
            if (frameImg) return frameImg.open();
            frameImg = wp.media({title: '选择轮播图片', multiple: false, library: {type: 'image'}});
            frameImg.on('select', function(){
                const a = frameImg.state().get('selection').first().toJSON();
                $('#banner_img').val(a.url);
                $('#preview_img').attr('src', a.url);
            });
            frameImg.open();
        });
        let frameVideo;
        $('.xd-upload-video').click(function(){
            if (frameVideo) return frameVideo.open();
            frameVideo = wp.media({title: '上传MP4视频', multiple: false, library: {type: 'video'}});
            frameVideo.on('select', function(){
                const a = frameVideo.state().get('selection').first().toJSON();
                $('#banner_video').val(a.url);
                location.reload();
            });
            frameVideo.open();
        });
        let adIdx = <?php echo count($ad_list); ?>;
        $('#add-ad').click(function(){
            const html = `<tr class="ad-item"><th>广告#${adIdx+1}</th><td><div style="margin:8px 0;"><label>跳转链接(可空):</label><input type="url" name="xd_news_ad_list[${adIdx}][link]" class="regular-text"></div><div style="margin:8px 0;"><label>广告文字:</label><input type="text" name="xd_news_ad_list[${adIdx}][text]" class="regular-text" required></div><div style="margin:8px 0;display:flex;align-items:center;gap:10px;"><label>文字颜色:</label><input type="color" name="xd_news_ad_list[${adIdx}][color]" value="#ff88bb"><button type="button" class="button del-ad">删除本条广告</button></div></td></tr>`;
            $('#ad-table').append(html);
            adIdx++;
        });
        $(document).on('click', '.del-ad', function(){
            $(this).closest('.ad-item').remove();
        });
    });
    </script>
    <?php
}

// ===================== 前端静态资源加载 =====================
function xd_news_load_assets(){
    $plugin_url = plugin_dir_url(__FILE__);
    wp_enqueue_style('layui-css', $plugin_url . 'assets/layui.css');
    wp_enqueue_style('xd-common', $plugin_url . 'assets/common.css', ['layui-css']);
    wp_enqueue_style('xd-shuangyi', $plugin_url . 'assets/shuangyi.css', ['xd-common']);
    wp_enqueue_style('xd-index', $plugin_url . 'assets/index.css', ['xd-shuangyi']);
    wp_enqueue_script('layui-js', $plugin_url . 'assets/layui.js', ['jquery'], '', true);
    wp_enqueue_script('xd-news-js', $plugin_url . 'assets/script.js', ['jquery','layui-js'], '', true);
}

// ===================== 核心渲染函数(完整无截断) =====================
function xd_news_render_html(){
    $base_opts = xd_get_base_options();
    $link_opts = xd_get_link_options();
    $ad_set = xd_get_ad_options();
    $ads_raw = xd_get_ad_list();
    $posts_per_page = $base_opts['posts_per_page'];
    $data_source = $base_opts['data_source'];
    $active_tpl_id = $base_opts['active_template'];
    $all_tpl = xd_news_get_all_templates();
    $tpl_info = isset($all_tpl[$active_tpl_id]) ? $all_tpl[$active_tpl_id] : xd_news_get_system_templates()['template1'];

    $content_raw = [];
    $stat_seconds = $base_opts['stat_hours'] * 3600;
    $time_limit = current_time('timestamp') - $stat_seconds;
    $today_count = 0;
    $site_tip = $base_opts['site_tip_text'];
    $copyright = $base_opts['copyright_text'];

    // 查询普通文章
    if ($data_source === 'post') {
        $query_args = [
            'post_type' => 'post',
            'posts_per_page' => 999,
            'orderby' => 'modified',
            'order' => 'DESC',
            'post_status' => 'publish',
            'no_found_rows' => true,
            'update_post_meta_cache' => false,
            'update_post_term_cache' => false,
        ];
        if (!empty($base_opts['cat_ids'])) $query_args['category__in'] = array_map('intval', explode(',', $base_opts['cat_ids']));
        if (!empty($base_opts['exclude_pids'])) $query_args['post__not_in'] = array_map('intval', explode(',', $base_opts['exclude_pids']));
        if ($base_opts['only_sticky'] === '1') {
            $sticky = get_option('sticky_posts');
            if (!empty($sticky)) $query_args['post__in'] = $sticky;
        }
        $wp_query = new WP_Query($query_args);
        if ($wp_query->have_posts()) {
            while ($wp_query->have_posts()) {
                $wp_query->the_post();
                $p = $wp_query->post;
                $mod_t = strtotime($p->post_modified);
                $content_raw[] = $p;
                if ($mod_t >= $time_limit) $today_count++;
            }
        }
        wp_reset_postdata();
    } else {
        // 查询子比社区帖子
        $forum_args = [
            'post_type' => 'forum_post',
            'posts_per_page' => 999,
            'orderby' => 'modified',
            'order' => 'DESC',
            'post_status' => $base_opts['forum_status'],
            'ignore_sticky_posts' => true,
            'no_found_rows' => true,
            'update_post_meta_cache' => false,
            'update_post_term_cache' => false,
        ];
        if (!empty($base_opts['forum_ids'])) {
            $f_ids = array_map('intval', explode(',', $base_opts['forum_ids']));
            $forum_args['meta_query'][] = ['key'=>'plate_id','value'=>$f_ids,'compare'=>'IN','type'=>'NUMERIC'];
        }
        if (!empty($base_opts['forum_exclude'])) $forum_args['post__not_in'] = array_map('intval', explode(',', $base_opts['forum_exclude']));
        $forum_query = new WP_Query($forum_args);
        if ($forum_query->have_posts()) {
            while ($forum_query->have_posts()) {
                $forum_query->the_post();
                $p = $forum_query->post;
                $mod_t = strtotime($p->post_modified);
                $content_raw[] = $p;
                if ($mod_t >= $time_limit) $today_count++;
            }
        }
        wp_reset_postdata();
    }

    // 按修改时间倒序排序
    usort($content_raw, function ($a, $b) {
        $ta = strtotime($a->post_modified);
        $tb = strtotime($b->post_modified);
        return $tb - $ta;
    });

    // 广告拼接逻辑
    $ads = [];
    if ($ad_set['ad_switch'] === '1') $ads = $ads_raw;
    $full_list = [];
    if ($ad_set['ad_mode'] === 'top') {
        foreach ($ads as $ad) $full_list[] = ['type' => 'ad', 'data' => $ad];
        foreach ($content_raw as $item) $full_list[] = ['type' => 'post', 'data' => $item];
    } else {
        $line = 0; $ad_idx = 0;
        foreach ($content_raw as $item) {
            $full_list[] = ['type' => 'post', 'data' => $item];
            $line++;
            if ($line >= $ad_set['ad_interval'] && $ad_idx < count($ads)) {
                $full_list[] = ['type' => 'ad', 'data' => $ads[$ad_idx]];
                $ad_idx++; $line = 0;
            }
        }
        for ($i = $ad_idx; $i < count($ads); $i++) $full_list[] = ['type' => 'ad', 'data' => $ads[$i]];
    }

    $chunks_all = array_chunk($full_list, $posts_per_page);
    $chunks = array_slice($chunks_all, 0, 4);
    $totalPage = count($chunks);

    // 轮播HTML生成
    ob_start();
    if ($base_opts['media_type'] === 'image'):
    ?>
    <div class="dad addd layui-carousel" id="test1" lay-anim="fade" style="width: 390px; height: 300px;">
        <a href="<?php echo esc_url($base_opts['banner_url']); ?>" rel="nofollow" target="_blank">
            <img src="<?php echo esc_attr($base_opts['banner_img']); ?>" width="100%" height="100%" >
        </a>
    </div>
    <?php else: ?>
    <div style="width:390px;height:300px;overflow:hidden;border-radius:4px;">
        <video width="390" height="300" muted autoplay loop playsinline style="object-fit:cover;display:block;">
            <source src="<?php echo esc_attr($base_opts['banner_video']); ?>" type="video/mp4">
        </video>
    </div>
    <?php endif;
    $banner_html = ob_get_clean();

    // 特权模块HTML
    ob_start();
    if ($base_opts['show_privilege'] === '1'):
    ?>
    <fieldset>
        <legend>本站特权</legend>
    </fieldset>
    <ul class="tequan">
        <li class="clearfix">
            <div><i style="background-position: center -389px;"></i><span>简洁好看</span></div>
            <div class="liright"><i style="background-position: center -360px;"></i><span>按时更新</span></div>
        </li>
        <li class="clearfix">
            <div><i style="background-position: center -101px;"></i><span>少量广告</span></div>
            <div class="liright"><i style="background-position: center -263px;"></i><span>资源丰富</span></div>
        </li>
    </ul>
    <?php endif;
    $privilege_html = ob_get_clean();

    // 底部链接栏
    ob_start();
    $link_arr = [];
    if (!empty($link_opts['link1_text'])) $link_arr[] = ['t' => $link_opts['link1_text'], 'u' => $link_opts['link1_url']];
    if (!empty($link_opts['link2_text'])) $link_arr[] = ['t' => $link_opts['link2_text'], 'u' => $link_opts['link2_url']];
    if (!empty($link_opts['link3_text'])) $link_arr[] = ['t' => $link_opts['link3_text'], 'u' => $link_opts['link3_url']];
    foreach ($link_arr as $l):
        if (!empty($l['u'])) echo '<a href="' . esc_attr($l['u']) . '" class="noad" target="_blank">' . esc_html($l['t']) . '</a>';
        else echo '<span class="noad">' . esc_html($l['t']) . '</span>';
    endforeach;
    $link_bar = ob_get_clean();

    // 列表循环HTML
    ob_start();
    foreach ($chunks as $pageIndex => $items):
    ?>
    <ul class="page-item" style="<?php echo $pageIndex === 0 ? 'display:block' : 'display:none' ?>">
        <?php foreach ($items as $item): ?>
            <?php if ($item['type'] === 'ad'):
                $ad = $item['data'];
            ?>
            <li class="item-ad addd">
                <a href="<?php echo esc_url($ad['link']) ?>" rel="nofollow" target="_blank">
                    <font style="color:<?php echo esc_attr($ad['color']) ?>"><?php echo esc_html($ad['text']) ?></font>
                </a>
                <span class="myad">广告</span>
            </li>
            <?php else:
                $p = $item['data'];
                $mod_t = strtotime($p->post_modified);
                $is_new = $mod_t >= $time_limit;
                $color = $is_new ? '#ff0000' : '#999999';
                $date_show = date('m-d', $mod_t);
            ?>
            <li class="item-post new">
                <a href="<?php echo get_permalink($p->ID); ?>" title="<?php echo esc_attr($p->post_title); ?>">
                    <?php echo esc_html($p->post_title); ?>
                </a>
                <span style="color:<?php echo $color; ?>"><?php echo $date_show; ?></span>
            </li>
            <?php endif; ?>
        <?php endforeach; ?>
    </ul>
    <?php endforeach;
    $item_list = ob_get_clean();

    // 分页HTML
    ob_start();
    if ($totalPage > 1):
    ?>
    <div class="page layui-clear" data-nowpage="1" data-totalpage="<?php echo $totalPage ?>">
        <div class="top" id="last">上一页</div>
        <b class="cfx"></b>
        <div class="bottom" id="next">下一页</div>
    </div>
    <?php endif;
    $pagination = ob_get_clean();

    // 变量替换映射
    $replace_map = [
        '{{today_count}}'   => $today_count,
        '{{banner_html}}'   => $banner_html,
        '{{privilege_html}}' => $privilege_html,
        '{{link_bar}}'      => $link_bar,
        '{{item_list}}'     => $item_list,
        '{{pagination}}'    => $pagination,
        '{{site_tip}}'      => $site_tip,
        '{{copyright}}'     => $copyright
    ];
    $tpl_html = $tpl_info['html'];
    $tpl_css = trim($tpl_info['css']);
    foreach ($replace_map as $k => $v) {
        $tpl_html = str_replace($k, $v, $tpl_html);
    }
    ob_start();
    if (!empty($tpl_css)) echo '<style>' . $tpl_css . '</style>';
    echo $tpl_html;
    return ob_get_clean();
}

// ===================== 短代码调用 =====================
function xd_news_shortcode($atts){
    xd_news_load_assets();
    return xd_news_render_html();
}
add_shortcode('xd_news_list', 'xd_news_shortcode');

// ===================== 侧边栏小工具完整类 =====================
class Xd_News_Widget extends WP_Widget
{
    public function __construct(){
        parent::__construct(
            'xd_news_widget',
            'Xd-News二次元资源列表',
            [
                'description' => '自定义HTML/CSS模板资源列表,支持子比社区板块筛选、广告分页'
            ]
        );
    }
    // 后台小工具表单
    public function form($instance){
        echo '<p>所有配置请到 【设置 > Xd‑二次元列表配置】 面板统一修改</p>';
    }
    // 前台输出小工具
    public function widget($args, $instance){
        xd_news_load_assets();
        echo $args['before_widget'];
        echo xd_news_render_html();
        echo $args['after_widget'];
    }
}
// 注册侧边栏小工具
function xd_news_register_widget(){
    register_widget('Xd_News_Widget');
}
add_action('widgets_init', 'xd_news_register_widget');

使用说明

  1. 新建文件,粘贴全部代码,保存为 xd-news-list.php;
  2. 上传到网站插件目录 /wp-content/plugins/xd-news-list/;
  3. WP 后台插件页面启用;
  4. 后台「设置」菜单出现【Xd‑二次元列表配置】,分 4 大独立卡片分区,二次元粉紫渐变风格;
  5. 支持自定义 HTML/CSS 模板、后台新增变量、广告管理、文章 / 子比帖子双数据源;
  6. 调用方式:页面插入短代码
    商务合作加入QQ群我想求资源
    本站特权
    • 简洁好看
      持续更新
    • 无冗余广告
      资源丰富
    最近更新+1
    上一页
    / 外观 – 小工具拖拽挂件。
© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容