码桶

发现社区成员的开源项目

飞扬 / LB_Down 公开
main
LB_Down/index.php
index.php17.8 KB
<?php
/**
 * LB Down - 专业下载站主题
 *
 * @package LB Down
 * @author 小野
 * @version 1.0.0
 * @link https://lb5.net
 */

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

$listStyle = $this->options->listStyle ?? 'list';
$isCardStyle = ($listStyle === 'card');

$filterCategory = isset($_GET['category']) ? trim($_GET['category']) : '';
$filterLicense = isset($_GET['license']) ? trim($_GET['license']) : '';
$filterLang = isset($_GET['lang']) ? trim($_GET['lang']) : '';
$filterSort = isset($_GET['sort']) ? trim($_GET['sort']) : 'date';

$filterQuery = [];
if ($filterLicense) $filterQuery['license'] = $filterLicense;
if ($filterLang) $filterQuery['lang'] = $filterLang;
if ($filterSort) $filterQuery['sort'] = $filterSort;
$filterBase = $this->options->siteUrl . '?' . http_build_query($filterQuery);

$pageSize = intval($this->options->pageSize ?: 20);
$this->parameter->setDefault(['pageSize' => $pageSize]);

$db = Typecho\Db::get();
$prefix = $db->getPrefix();
$adapter = $db->getAdapterName();
$isMysql = (strpos($adapter, 'Mysql') !== false || strpos($adapter, 'Pdo_Mysql') !== false);
$q = $isMysql ? '`' : '"';
$page = isset($this->request->page) ? intval($this->request->page) : 1;
$offset = ($page - 1) * $pageSize;

$hasFilter = $filterCategory || $filterLicense || $filterLang || $filterSort !== 'date';

if ($hasFilter) {

    $sql = "SELECT c.* FROM {$q}{$prefix}contents{$q} c";
    $where = " WHERE c.status = 'publish' AND c.type = 'post'";
    $joins = '';
    $orderby = '';
    $groupby = " GROUP BY c.cid";

    if ($filterCategory) {
        $joins .= " INNER JOIN {$q}{$prefix}relationships{$q} r ON c.cid = r.cid";
        $joins .= " INNER JOIN {$q}{$prefix}metas{$q} m ON r.mid = m.mid";
        $where .= " AND m.type = 'category' AND m.slug = '{$filterCategory}'";
    }

    if ($filterLicense) {
        $joins .= " INNER JOIN {$q}{$prefix}fields{$q} fl ON c.cid = fl.cid AND fl.name = 'license'";
        $where .= " AND fl.str_value = '{$filterLicense}'";
    }

    if ($filterLang) {
        $joins .= " INNER JOIN {$q}{$prefix}fields{$q} flang ON c.cid = flang.cid AND flang.name = 'language'";
        $where .= " AND flang.str_value = '{$filterLang}'";
    }

    switch ($filterSort) {
        case 'hot':
            $joins .= " LEFT JOIN {$q}{$prefix}fields{$q} fdc ON c.cid = fdc.cid AND fdc.name = 'downloadCount'";
            $orderby = " ORDER BY CAST(COALESCE(fdc.str_value, '0') AS UNSIGNED) DESC, c.created DESC";
            break;
        case 'rating':
            $joins .= " LEFT JOIN {$q}{$prefix}lb_ratings{$q} frt ON c.cid = frt.cid";
            $orderby = " ORDER BY AVG(frt.rating) DESC, c.created DESC";
            break;
        default:
            $orderby = " ORDER BY c.created DESC";
    }

    $fullSql = $sql . $joins . $where . $groupby . $orderby . " LIMIT {$pageSize} OFFSET {$offset}";
    $filteredPosts = $db->fetchAll($fullSql);

    $countSql = "SELECT COUNT(DISTINCT c.cid) AS total FROM {$q}{$prefix}contents{$q} c" . $joins . $where;
    $total = $db->fetchObject($countSql)->total;
} else {
    $filteredPosts = null;
    $total = 0;
}

$this->need('header.php');
?>

<div class="content-area">
    
    <?php
    $recEnabled = intval($this->options->recEnable ?? 1);
    $recommendPosts = $recEnabled ? lb_get_recommend_posts() : [];
    if ($recommendPosts):
        $recWidget = \Widget\Contents\Post\Recent::alloc();
    ?>
    <section class="recommend-section">
        <div class="container">
        <div class="recommend-swiper">
            <div class="swiper-container" id="recSwiper">
                <div class="swiper-wrapper">
                    <?php foreach ($recommendPosts as $idx => $post):
                        $recWidget->reset();
                        $recWidget->push($post);
                        $thumb = lb_get_thumb($recWidget);
                        $postFields = isset($post['fields']) ? $post['fields'] : (object)[];
                        $version = $postFields->version ?? '';
                        $fileSize = $postFields->fileSize ?? '';
                    ?>
                    <div class="swiper-slide" data-idx="<?php echo $idx; ?>">
                        <div class="rec-slide-inner">
                            <div class="rec-thumb">
                                <img src="<?php echo htmlspecialchars($thumb); ?>" alt="<?php $recWidget->title(); ?>" loading="lazy">
                            </div>
                            <div class="rec-info">
                                <h3 class="rec-title"><?php $recWidget->title(); ?></h3>
                                <?php if ($version): ?>
                                    <div class="rec-version"><?php echo htmlspecialchars($version); ?></div>
                                <?php endif; ?>
                                <div class="rec-meta">
                                    <span><?php $recWidget->date('Y.m.d'); ?></span>
                                    <?php if ($fileSize): ?>
                                        <span class="rec-sep">|</span>
                                        <span><?php echo htmlspecialchars($fileSize); ?></span>
                                    <?php endif; ?>
                                </div>
                                <a href="<?php $recWidget->permalink(); ?>" class="rec-download-btn">
                                    <span style="--i:0">立</span><span style="--i:1">即</span><span style="--i:2">下</span><span style="--i:3">载</span>
                                </a>
                            </div>
                        </div>
                    </div>
                    <?php endforeach; ?>
                </div>
                <div class="swiper-button-prev rec-prev">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
                        <polyline points="15 18 9 12 15 6"></polyline>
                    </svg>
                </div>
                <div class="swiper-button-next rec-next">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
                        <polyline points="9 18 15 12 9 6"></polyline>
                    </svg>
                </div>
            </div>
            <div class="rec-list-box">
                <div class="rec-list">
                    <ul class="rec-carousel">
                        <?php foreach ($recommendPosts as $idx => $post):
                            $recWidget->reset();
                            $recWidget->push($post);
                            $thumb = lb_get_thumb($recWidget);
                            $postFields = isset($post['fields']) ? $post['fields'] : (object)[];
                            $postVersion = $postFields->version ?? '';
                        ?>
                        <li class="rec-item" data-idx="<?php echo $idx; ?>" data-url="<?php $recWidget->permalink(); ?>">
                            <div class="liner">
                                <div class="rec-item-img">
                                    <img src="<?php echo htmlspecialchars($thumb); ?>" alt="<?php $recWidget->title(); ?>">
                                </div>
                                <p class="rec-item-title"><?php $recWidget->title(); ?> <?php echo htmlspecialchars($postVersion); ?></p>
                            </div>
                            <div class="rec-item-normal">
                                <div class="rec-item-img">
                                    <img src="<?php echo htmlspecialchars($thumb); ?>" alt="<?php $recWidget->title(); ?>">
                                </div>
                                <p class="rec-item-title"><?php $recWidget->title(); ?> <?php echo htmlspecialchars($postVersion); ?></p>
                            </div>
                        </li>
                        <?php endforeach; ?>
                    </ul>
                </div>
            </div>
        </div>
        </div>
    </section>
    <?php endif; ?>

    
    <?php $filterEnabled = intval($this->options->filterEnable ?? 1); if ($filterEnabled): ?>
    <div class="filter-bar">
        <div class="filter-row">
            <span class="filter-label">分类:</span>
            <div class="filter-links">
                <?php
                $catUrl = $this->options->siteUrl . '?' . http_build_query(array_merge($filterQuery, ['category' => '']));
                $catUrl = rtrim($catUrl, '?&');
                ?>
                <a href="<?php echo $catUrl; ?>" class="filter-link <?php if (!$filterCategory) echo 'active'; ?>">全部</a>
                <?php
                $categories = \Widget\Metas\Category\Rows::alloc();
                while ($categories->next()):
                    $catParams = $filterQuery;
                    $catParams['category'] = $categories->slug;
                    $catLink = $this->options->siteUrl . '?' . http_build_query($catParams);
                    $isCurrent = $filterCategory === $categories->slug;
                ?>
                    <a href="<?php echo $catLink; ?>" class="filter-link <?php if ($isCurrent) echo 'active'; ?>">
                        <?php $categories->name(); ?>
                    </a>
                <?php endwhile; ?>
            </div>
        </div>

        <div class="filter-row">
            <span class="filter-label">授权:</span>
            <div class="filter-links">
                <?php
                $licenses = ['' => '全部', 'free' => '免费', 'vip' => 'VIP免费', 'paid' => '付费', 'trial' => '试用', 'open' => '开源'];
                foreach ($licenses as $val => $label):
                    $licParams = ['category' => $filterCategory, 'lang' => $filterLang, 'sort' => $filterSort];
                    if ($val) $licParams['license'] = $val;
                    $licLink = $this->options->siteUrl . '?' . http_build_query($licParams);
                    $isActive = $filterLicense === $val;
                ?>
                    <a href="<?php echo $licLink; ?>" class="filter-link <?php if ($isActive) echo 'active'; ?>"><?php echo $label; ?></a>
                <?php endforeach; ?>
            </div>
        </div>

        <div class="filter-row">
            <span class="filter-label">语言:</span>
            <div class="filter-links">
                <?php
                $langs = ['' => '全部', 'zh-CN' => '简体中文', 'zh-TW' => '繁体中文', 'en' => '英文', 'multi' => '多语言'];
                foreach ($langs as $val => $label):
                    $langParams = ['category' => $filterCategory, 'license' => $filterLicense, 'sort' => $filterSort];
                    if ($val) $langParams['lang'] = $val;
                    $langLink = $this->options->siteUrl . '?' . http_build_query($langParams);
                    $isActive = $filterLang === $val;
                ?>
                    <a href="<?php echo $langLink; ?>" class="filter-link <?php if ($isActive) echo 'active'; ?>"><?php echo $label; ?></a>
                <?php endforeach; ?>
            </div>
        </div>

        <div class="filter-row">
            <span class="filter-label">排序:</span>
            <div class="filter-links">
                <?php
                $sorts = ['date' => '最新', 'hot' => '最热', 'rating' => '评分最高'];
                foreach ($sorts as $val => $label):
                    $sortParams = ['category' => $filterCategory, 'license' => $filterLicense, 'lang' => $filterLang];
                    if ($val !== 'date') $sortParams['sort'] = $val;
                    $sortLink = $this->options->siteUrl . '?' . http_build_query($sortParams);
                    $isActive = $filterSort === $val;
                ?>
                    <a href="<?php echo $sortLink; ?>" class="filter-link <?php if ($isActive) echo 'active'; ?>"><?php echo $label; ?></a>
                <?php endforeach; ?>
            </div>
        </div>
    </div>
    <?php endif; ?>

    
    <?php
    $newestCats = trim($this->options->newestCats ?? '');
    $newestCols = max(1, intval($this->options->newestCols ?? 4));
    $newestRows = max(1, intval($this->options->newestRows ?? 3));
    $newestLimit = $newestCols * $newestRows;
    $newestLimited = false;
    $firstCatUrl = '';
    if ($newestCats):
        $catIds = array_filter(array_map('intval', explode(',', $newestCats)));
        if ($catIds):
    $newestLimited = $isCardStyle && !empty($catIds);
    ?>
    <div class="newest-section">
        <h2 class="newest-title">最新更新</h2>
        <div class="newest-cats">
            <?php foreach ($catIds as $idx => $cid): ?>
                <?php
                    $cat = \Widget\Metas\Category\Rows::alloc();
                    $catName = '';
                    $catUrl = '';
                    while ($cat->next()):
                        if ($cat->mid == $cid):
                            $catName = $cat->name;
                            $catUrl = $cat->url;
                            break;
                        endif;
                    endwhile;
                    if (!$catName) continue;
                    if ($idx === 0) $firstCatUrl = $catUrl;
                ?>
                <a href="<?php echo htmlspecialchars($catUrl ?: 'javascript:;'); ?>" data-cat-mid="<?php echo $cid; ?>" class="newest-cat-item <?php if ($idx === 0) echo 'active'; ?>"><?php echo htmlspecialchars($catName); ?></a>
            <?php endforeach; ?>
        </div>
    </div>
    <?php endif; endif; ?>

    
    <?php if ($isCardStyle): ?>
    <ul class="resource-grid" style="--grid-cols: <?php echo $newestCols; ?>;">
        <?php
        $gridIndex = 0;
        if ($hasFilter):
            if ($filteredPosts):
                $postWidget = \Widget\Contents\Post\Recent::alloc();
                foreach ($filteredPosts as $post):
                    if ($newestLimited && $gridIndex >= $newestLimit) break;
                    $postWidget->reset();
                    $postWidget->push($post);
                    lb_resource_card_grid($postWidget, $gridIndex);
                    $gridIndex++;
                endforeach;
            endif;
        else:
            if ($this->have()):
                while ($this->next() && (!$newestLimited || $gridIndex < $newestLimit)):
                    lb_resource_card_grid($this, $gridIndex);
                    $gridIndex++;
                endwhile;
            endif;
        endif;
        ?>
    </ul>
    <?php if ($newestLimited): ?>
    <div class="newest-more-wrap">
        <a class="newest-more" href="<?php echo htmlspecialchars($firstCatUrl ?: $this->options->siteUrl); ?>" data-default-url="<?php echo htmlspecialchars($firstCatUrl ?: $this->options->siteUrl); ?>">更多资源<span class="newest-more-arrow">›</span></a>
    </div>
    <?php endif; ?>
    <?php else: ?>
    <div class="resource-list">
        <?php $listIndex = 0; ?>
        <?php if ($hasFilter): ?>
            <?php if ($filteredPosts): ?>
                <?php
                $postWidget = \Widget\Contents\Post\Recent::alloc();
                foreach ($filteredPosts as $post):
                    $postWidget->reset();
                    $postWidget->push($post);
                ?>
                    <?php lb_resource_card($postWidget, $listIndex++); ?>
                <?php endforeach; ?>
            <?php else: ?>
                <div class="no-results">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <circle cx="11" cy="11" r="8"/>
                        <line x1="21" y1="21" x2="16.65" y2="16.65"/>
                    </svg>
                    <p>没有找到相关资源</p>
                </div>
            <?php endif; ?>
        <?php else: ?>
            <?php if ($this->have()): ?>
                <?php while ($this->next()): ?>
                    <?php lb_resource_card($this, $listIndex++); ?>
                <?php endwhile; ?>
            <?php else: ?>
                <div class="no-results">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <circle cx="11" cy="11" r="8"/>
                        <line x1="21" y1="21" x2="16.65" y2="16.65"/>
                    </svg>
                    <p>没有找到相关资源</p>
                </div>
            <?php endif; ?>
        <?php endif; ?>
    </div>
    <?php endif; ?>

    
    <?php
    $rankCatsConfig = trim($this->options->downloadRankCats ?? '');
    if ($rankCatsConfig):
        $rankCatIds = array_filter(array_map('intval', explode(',', $rankCatsConfig)));
        if ($rankCatIds):
            $rankPosts = lb_get_rank_posts($rankCatIds, 14);
            if ($rankPosts):
                $rankWidget = \Widget\Contents\Post\Recent::alloc();
    ?>
    <div class="rank-section">
        <h2 class="rank-title">下载榜单</h2>
        <ul class="rank-list">
            <?php foreach ($rankPosts as $rkPost):
                $rankWidget->reset();
                $rankWidget->push($rkPost);
                $rkThumb = lb_get_thumb($rankWidget);
            ?>
            <li class="rank-item">
                <a href="<?php $rankWidget->permalink(); ?>" title="<?php $rankWidget->title(); ?>">
                    <span class="rank-img">
                        <img src="<?php echo htmlspecialchars($rkThumb); ?>" alt="<?php $rankWidget->title(); ?>" loading="lazy" onerror="this.src='<?php echo lb_theme_url('assets/img/placeholder.svg'); ?>'">
                    </span>
                    <span class="rank-name"><?php $rankWidget->title(); ?></span>
                </a>
            </li>
            <?php endforeach; ?>
        </ul>
    </div>
    <?php endif; endif; endif; ?>

    <div class="cat-empty" style="display:none;">该分类暂无资源</div>
</div>

<?php if (!$this->is('index')): ?>
<?php $this->need('sidebar.php'); ?>
<?php endif; ?>

<?php $this->need('footer.php'); ?>