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