码桶

发现社区成员的开源项目

飞扬 / LB_Down 公开
main
LB_Down/category.php
category.php13.3 KB
<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;

$currentCatMid = 0;
if ($this->is('category')) {
    if (isset($this->mid)) {
        $currentCatMid = intval($this->mid);
    }

    if (!$currentCatMid) {
        $slug = $this->getArchiveSlug();
        if ($slug) {
            try {
                $db = \Typecho\Db::get();
                $row = $db->fetchRow($db->select('mid')->from('table.metas')
                    ->where('type = ?', 'category')->where('slug = ?', $slug)->limit(1));
                if ($row) {
                    $currentCatMid = intval($row['mid']);
                }
            } catch (\Exception $e) {
                $currentCatMid = 0;
            }
        }
    }
}

$filterCatsConfig = trim($this->options->filterCats ?? '');
$showFilterBar = true;
if ($filterCatsConfig !== '') {
    $filterCatIds = array_map('intval', array_filter(explode(',', $filterCatsConfig)));
    $showFilterBar = in_array($currentCatMid, $filterCatIds);
}

$viewMode = '';
if ($showFilterBar) {
    if (isset($_GET['view']) && in_array($_GET['view'], ['list', 'card'], true)) {
        $viewMode = $_GET['view'];
    }
    if (!$viewMode && isset($_COOKIE['lb_view']) && in_array($_COOKIE['lb_view'], ['list', 'card'], true)) {
        $viewMode = $_COOKIE['lb_view'];
    }
}
if ($viewMode) {
    setcookie('lb_view', $viewMode, time() + 86400 * 30, '/');
    $listStyle = $viewMode;
} else {
    $listStyle = $this->options->listStyle ?? 'list';
}
$isCardStyle = ($listStyle === 'card');

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

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

$hasFilter = $showFilterBar && ($filterLicense || $filterLang || $filterSort !== 'date');

if ($hasFilter && $currentCatMid) {
    $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;

    $sql = "SELECT c.* FROM {$q}{$prefix}contents{$q} c";
    $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 = " WHERE c.status = 'publish' AND c.type = 'post' AND m.type = 'category' AND m.mid = {$currentCatMid}";
    $orderby = '';
    $groupby = " GROUP BY c.cid";

    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');

$catPermalink = '';
if ($currentCatMid) {
    $catWidget = \Widget\Metas\Category\Rows::alloc();
    while ($catWidget->next()) {
        if ($catWidget->mid == $currentCatMid) {
            $catPermalink = $catWidget->url;
            break;
        }
    }
}
$filterBase = $catPermalink ?: $this->options->siteUrl;
?>

<div class="content-area">

    
    <?php if ($showFilterBar): ?>
    <div class="filter-bar">
        <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 = ['lang' => $filterLang, 'sort' => $filterSort];
                    if ($viewMode) $licParams['view'] = $viewMode;
                    if ($val) $licParams['license'] = $val;
                    $licLink = $filterBase . '?' . 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 = ['license' => $filterLicense, 'sort' => $filterSort];
                    if ($viewMode) $langParams['view'] = $viewMode;
                    if ($val) $langParams['lang'] = $val;
                    $langLink = $filterBase . '?' . 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 = ['license' => $filterLicense, 'lang' => $filterLang];
                    if ($viewMode) $sortParams['view'] = $viewMode;
                    if ($val !== 'date') $sortParams['sort'] = $val;
                    $sortLink = $filterBase . '?' . 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 class="filter-row">
            <span class="filter-label">视图:</span>
            <div class="filter-links">
                <?php
                $viewParams = ['license' => $filterLicense, 'lang' => $filterLang, 'sort' => $filterSort];
                $cardViewLink = $filterBase . '?' . http_build_query(array_merge($viewParams, ['view' => 'card']));
                $listViewLink = $filterBase . '?' . http_build_query(array_merge($viewParams, ['view' => 'list']));
                ?>
                <a href="<?php echo $cardViewLink; ?>" class="filter-link <?php if ($isCardStyle) echo 'active'; ?>">卡片</a>
                <a href="<?php echo $listViewLink; ?>" class="filter-link <?php if (!$isCardStyle) echo 'active'; ?>">列表</a>
            </div>
        </div>
    </div>
    <?php endif; ?>

    
    <?php if ($isCardStyle): ?>
    <ul class="resource-grid">
        <?php
        $gridIndex = 0;
        if ($hasFilter):
            if ($filteredPosts):
                $postWidget = \Widget\Contents\Post\Recent::alloc();
                foreach ($filteredPosts as $post):
                    $postWidget->reset();
                    $postWidget->push($post);
                    lb_resource_card_grid($postWidget, $gridIndex);
                    $gridIndex++;
                endforeach;
            endif;
        else:
            if ($this->have()):
                while ($this->next()):
                    lb_resource_card_grid($this, $gridIndex);
                    $gridIndex++;
                endwhile;
            endif;
        endif;
        ?>
    </ul>
    <?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 if ($hasFilter ? ($total > 0) : $this->have()): ?>
        <?php
        $paginationType = trim($this->options->paginationType ?? 'pager');
        $isScrollLoad = ($paginationType === 'scroll');
        if ($isScrollLoad):
            $scrollTotalPages = $hasFilter ? ceil($total / $pageSize) : ceil($this->getTotal() / $pageSize);
            $loadUrl = $this->options->siteUrl . '?lb_action=lb_more_posts&cat=' . $currentCatMid
                     . '&license=' . urlencode($filterLicense)
                     . '&lang=' . urlencode($filterLang)
                     . '&sort=' . urlencode($filterSort)
                     . '&view=' . ($isCardStyle ? 'card' : 'list');
        ?>
        <div class="scroll-load-wrap">
            <div class="scroll-load-more" id="scroll-more" data-url="<?php echo htmlspecialchars($loadUrl); ?>" data-pages="<?php echo max(1, $scrollTotalPages); ?>" data-page="1" data-initialized="0">
                加载更多…
            </div>
        </div>
        <?php else: ?>
        <nav class="pagination" aria-label="分页导航">
            <?php if ($hasFilter): ?>
                <?php
                $totalPages = ceil($total / $pageSize);
                if ($totalPages > 1):
                    $allParams = [];
                    if ($filterLicense) $allParams['license'] = $filterLicense;
                    if ($filterLang) $allParams['lang'] = $filterLang;
                    if ($filterSort !== 'date') $allParams['sort'] = $filterSort;
                    if ($viewMode) $allParams['view'] = $viewMode;
                    $pageUrl = $filterBase . '?' . http_build_query($allParams);
                ?>
                    <div class="pagination-inner">
                        <?php if ($page > 1): ?>
                            <a class="prev" href="<?php echo $pageUrl . '&page=' . ($page - 1); ?>">上一页</a>
                        <?php endif; ?>
                        <?php for ($i = 1; $i <= $totalPages; $i++): ?>
                            <?php if ($i == $page): ?>
                                <span class="current"><?php echo $i; ?></span>
                            <?php else: ?>
                                <a href="<?php echo $pageUrl . '&page=' . $i; ?>"><?php echo $i; ?></a>
                            <?php endif; ?>
                        <?php endfor; ?>
                        <?php if ($page < $totalPages): ?>
                            <a class="next" href="<?php echo $pageUrl . '&page=' . ($page + 1); ?>">下一页</a>
                        <?php endif; ?>
                    </div>
                <?php endif; ?>
            <?php else: ?>
                <?php $this->pageNav('上一页', '下一页', 3, '...', [
                    'wrapTag' => 'div',
                    'wrapClass' => 'pagination-inner',
                    'itemTag' => 'a',
                    'textTag' => 'span',
                    'currentClass' => 'current',
                    'prevClass' => 'prev',
                    'nextClass' => 'next'
                ]); ?>
            <?php endif; ?>
        </nav>
        <?php endif; ?>
    <?php endif; ?>
</div>

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