码桶
发现社区成员的开源项目
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'); ?>