2.1 版本文件

This commit is contained in:
2026-08-14 10:55:06 +08:00
commit a3434ec620
67 changed files with 12559 additions and 0 deletions
+143
View File
@@ -0,0 +1,143 @@
<?php
// 商品详情 + 加入购物车
require __DIR__ . '/includes/init.php';
$pageTitle = __('product.detail');
$id = (int) ($_GET['id'] ?? 0);
$stmt = db()->prepare('SELECT * FROM ' . tn('products') . ' WHERE id = ? AND status = 1');
$stmt->execute([$id]);
$product = $stmt->fetch();
if (!$product) {
header('Location: index.php');
exit;
}
// 当前登录用户是否已购买该商品,并取最新发货 / 商品信息
$hasBought = false;
$purchase = null;
if ($user = currentUser()) {
$bstmt = db()->prepare(
'SELECT 1 FROM ' . tn('orders') . ' o
INNER JOIN ' . tn('order_items') . ' oi ON oi.order_id = o.id
WHERE o.user_id = ? AND oi.product_id = ? AND o.status IN ("paid","shipped","completed") LIMIT 1'
);
$bstmt->execute([$user['id'], $id]);
$hasBought = (bool) $bstmt->fetchColumn();
$pstmt = db()->prepare(
'SELECT d.* FROM ' . tn('order_deliveries') . ' d
INNER JOIN ' . tn('orders') . ' o ON o.id = d.order_id
INNER JOIN ' . tn('order_items') . ' oi ON oi.order_id = o.id
WHERE o.user_id = ? AND oi.product_id = ? AND o.status IN ("paid","shipped","completed")
ORDER BY d.id DESC LIMIT 1'
);
$pstmt->execute([$user['id'], $id]);
$purchase = $pstmt->fetch();
}
$err = $ok = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add'])) {
verifyCsrf();
$qty = max(1, (int) ($_POST['qty'] ?? 1));
if ($product['stock'] <= 0) {
$err = __('product_page.err_out_of_stock');
} elseif ($qty > $product['stock']) {
$err = str_replace('{max}', $product['stock'], __('product_page.err_low_stock'));
} else {
if (!isset($_SESSION['cart'])) $_SESSION['cart'] = [];
$cur = (int) ($_SESSION['cart'][$id] ?? 0);
$_SESSION['cart'][$id] = $cur + $qty;
header('Location: cart.php');
exit;
}
}
require 'includes/header.php';
?>
<section class="section">
<a href="index.php" class="back-link"><i class="fas fa-arrow-left"></i> <?= __('product_page.back_list') ?></a>
<div class="product-detail">
<div class="pd-media">
<?php if (!empty($product['image'])): ?>
<img src="<?= h($product['image']) ?>" alt="<?= h($product['name']) ?>">
<?php else: ?>
<i class="fas <?= h($product['icon']) ?>"></i>
<?php endif; ?>
</div>
<div class="pd-info">
<span class="pc-cat"><?= h($product['category']) ?></span>
<h1 class="pd-name"><?= h($product['name']) ?></h1>
<?php if (!empty($product['points_price'])): ?>
<div class="pd-price"><?= __('product_page.points_price_label') ?><strong><?= (int) $product['points_price'] ?></strong><?= __('product_page.points_suffix') ?></div>
<?php else: ?>
<div class="pd-price"><?= __('product_page.cash_price_label') ?></div>
<?php endif; ?>
<div class="pd-stock"><?= __('product_page.stock_label') ?><?= (int) $product['stock'] ?><?= __('product_page.stock_unit') ?></div>
<?php if (!empty($product['period_days'])): ?>
<div class="pd-period"><i class="fas fa-clock"></i> <?= __('product_page.period_label') ?><?= periodLabel($product['period_days']) ?></div>
<?php endif; ?>
<p class="pd-desc"><?= nl2br(h($product['description'] ?? '')) ?></p>
<?php if ($err): ?><p class="form-err"><?= h($err) ?></p><?php endif; ?>
<?php if ($product['stock'] > 0): ?>
<form method="post" action="" class="pd-buy">
<?= csrfField() ?>
<label><?= __('product_page.qty_label') ?>
<input type="number" name="qty" value="1" min="1" max="<?= (int)$product['stock'] ?>" class="qty-input">
</label>
<button type="submit" name="add" class="btn btn-primary"><i class="fas fa-cart-plus"></i> <?= __('product_page.add_cart_btn') ?></button>
</form>
<?php else: ?>
<p class="sold-out"><?= __('product_page.sold_out') ?></p>
<?php endif; ?>
</div>
</div>
</section>
<?php if ($hasBought): ?>
<section class="section">
<div class="pd-purchased">
<div class="pp-head">
<i class="fas fa-check-circle"></i>
<span class="pp-title"><?= __('product_page.purchased_title') ?></span>
<button type="button" class="btn btn-ghost btn-sm" id="ppToggle"><?= __('product_page.purchased_toggle') ?></button>
</div>
<div class="pp-detail" id="ppDetail" style="display:none;">
<?php if ($purchase): ?>
<div class="od-line"><?= __('status') ?><span class="badge-<?= !empty($purchase['activated']) ? 'on' : 'off' ?>"><?= !empty($purchase['activated']) ? __('product_page.purchased_activated') : __('product_page.purchased_not_activated') ?></span></div>
<?php if ($purchase['product_info'] !== ''): ?>
<div class="od-line od-info-block"><?= __('product_page.purchased_product_info') ?><?= nl2br(h($purchase['product_info'])) ?></div>
<?php endif; ?>
<?php if ($purchase['server_ip'] !== '' || $purchase['conn_addr'] !== '' || $purchase['login_user'] !== '' || $purchase['login_pass'] !== ''): ?>
<div class="od-line"><?= __('product_page.server_ip') ?><?= h($purchase['server_ip']) ?: __('product_page.none_value') ?></div>
<div class="od-line"><?= __('product_page.conn_addr') ?><?= h($purchase['conn_addr']) ?: __('product_page.none_value') ?></div>
<div class="od-line"><?= __('product_page.login_user') ?><?= h($purchase['login_user']) ?: __('product_page.none_value') ?></div>
<div class="od-line"><?= __('product_page.login_pass') ?>
<span class="secret" data-secret="<?= h($purchase['login_pass']) ?>"><?= $purchase['login_pass'] !== '' ? str_repeat('●', max(6, mb_strlen($purchase['login_pass']))) : __('product_page.none_value') ?></span>
<?php if ($purchase['login_pass'] !== ''): ?><button type="button" class="mini-btn reveal-btn"><?= __('product_page.reveal_btn') ?></button><?php endif; ?>
</div>
<?php endif; ?>
<?php if ($purchase['remark'] !== ''): ?>
<div class="od-line"><?= __('product_page.remark_label') ?><?= nl2br(h($purchase['remark'])) ?></div>
<?php endif; ?>
<?php else: ?>
<p class="muted"><?= __('product_page.pending_delivery') ?></p>
<?php endif; ?>
</div>
</div>
</section>
<script>
(function () {
var btn = document.getElementById('ppToggle');
var box = document.getElementById('ppDetail');
if (!btn || !box) return;
btn.addEventListener('click', function () {
var open = box.style.display === 'none';
box.style.display = open ? 'block' : 'none';
btn.textContent = open ? '<?= __('product_page.purchased_toggle_close') ?>' : '<?= __('product_page.purchased_toggle') ?>';
});
})();
</script>
<?php endif; ?>
<?php require 'includes/footer.php'; ?>