diff --git a/admin.php b/admin.php
index 25343eb..e6a254f 100644
--- a/admin.php
+++ b/admin.php
@@ -3540,6 +3540,7 @@ async function loadShopConfig(el) {
@@ -3593,6 +3594,18 @@ function showShopConfigForm(config) {
document.getElementById('scfOffer').value = config ? (config.temporary_offer||'') : '';
document.getElementById('scfExpire').value = config ? (config.offer_expire||'') : '';
document.getElementById('scfPrice').value = config ? config.price : '';
+ // 优惠后价格:如果原价<1认为是折扣,否则是直接价格
+ if (config && config.discount_price > 0) {
+ const ratio = config.discount_price / (config.price || 1);
+ // 如果是整数倍(如原价10,优惠价5),显示折扣形式
+ if (ratio < 1 && ratio > 0) {
+ document.getElementById('scfDiscountPrice').value = ratio;
+ } else {
+ document.getElementById('scfDiscountPrice').value = config.discount_price;
+ }
+ } else {
+ document.getElementById('scfDiscountPrice').value = '';
+ }
document.getElementById('scfBond').value = config ? config.bond_reward : '1-1';
document.getElementById('scfActive').value = config ? config.is_active : 1;
document.getElementById('shopConfigFormOverlay').classList.add('show');
@@ -3630,6 +3643,7 @@ async function saveShopConfig() {
const offer = document.getElementById('scfOffer').value.trim();
const expire = document.getElementById('scfExpire').value.trim();
const price = parseFloat(document.getElementById('scfPrice').value) || 0;
+ const discountPriceRaw = document.getElementById('scfDiscountPrice').value.trim();
const bond = document.getElementById('scfBond').value.trim();
const active = parseInt(document.getElementById('scfActive').value) || 1;
@@ -3651,6 +3665,7 @@ async function saveShopConfig() {
temporary_offer: offer,
offer_expire: expire,
price: price,
+ discount_price: discountPriceRaw,
bond_reward: bond,
is_active: active
});
diff --git a/api/pay.php b/api/pay.php
index a643c24..9030291 100644
--- a/api/pay.php
+++ b/api/pay.php
@@ -315,7 +315,12 @@ function createOrder($token, $productId = 0) {
error('商品已售罄');
}
- $money = number_format($product['price'], 2, '.', '');
+ // 使用折扣价格(如果有)
+ $actualPrice = $product['price'];
+ if (isset($product['discount_price']) && $product['discount_price'] > 0) {
+ $actualPrice = $product['discount_price'];
+ }
+ $money = number_format($actualPrice, 2, '.', '');
$name = $product['item_name'];
// 解析债券范围
@@ -952,10 +957,21 @@ function getShopProducts() {
temporary_offer TEXT NOT NULL DEFAULT '',
offer_expire TEXT NOT NULL DEFAULT '',
price REAL NOT NULL DEFAULT 0,
+ discount_price REAL NOT NULL DEFAULT 0,
bond_reward TEXT NOT NULL DEFAULT '1-1',
is_active INTEGER NOT NULL DEFAULT 1,
- created_at INTEGER NOT NULL DEFAULT 0
+ created_at INTEGER NOT NULL DEFAULT 0,
+ updated_at INTEGER NOT NULL DEFAULT 0
)");
+ // 兼容旧表:检查并添加discount_price字段
+ $hasCol = false;
+ $cols = $db->query("PRAGMA table_info(shop_configs)");
+ while ($col = $cols->fetchArray(SQLITE3_ASSOC)) {
+ if ($col['name'] === 'discount_price') { $hasCol = true; break; }
+ }
+ if (!$hasCol) {
+ $db->exec("ALTER TABLE shop_configs ADD COLUMN discount_price REAL NOT NULL DEFAULT 0");
+ }
// 查询上架商品(is_active=1)
$stmt = $db->query("SELECT * FROM shop_configs WHERE is_active = 1 ORDER BY id ASC");
@@ -976,6 +992,12 @@ function getShopProducts() {
// 解析有效期
$expireInfo = parseExpireDate($row['offer_expire']);
+ // 计算实际显示价格(如果有折扣价格且折扣价格>0)
+ $displayPrice = $row['price'];
+ if (isset($row['discount_price']) && $row['discount_price'] > 0) {
+ $displayPrice = $row['discount_price'];
+ }
+
$products[] = [
'id' => $row['id'],
'item_name' => $row['item_name'],
@@ -985,6 +1007,8 @@ function getShopProducts() {
'expire_valid' => $expireInfo['valid'],
'expire_display' => $expireInfo['display'],
'price' => $row['price'],
+ 'discount_price' => $row['discount_price'] ?? 0,
+ 'display_price' => $displayPrice,
'bond_reward' => $bondReward,
'bond_min' => $bondMin,
'bond_max' => $bondMax,
diff --git a/api/recharge_orders_api.php b/api/recharge_orders_api.php
index be714e2..520ec9f 100644
--- a/api/recharge_orders_api.php
+++ b/api/recharge_orders_api.php
@@ -45,11 +45,21 @@ function ensureShopConfigsTable($db) {
temporary_offer TEXT NOT NULL DEFAULT '',
offer_expire TEXT NOT NULL DEFAULT '',
price REAL NOT NULL DEFAULT 0,
+ discount_price REAL NOT NULL DEFAULT 0,
bond_reward TEXT NOT NULL DEFAULT '1-1',
is_active INTEGER NOT NULL DEFAULT 1,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0
)");
+ // 兼容旧表:检查并添加discount_price字段
+ $hasCol = false;
+ $cols = $db->query("PRAGMA table_info(shop_configs)");
+ while ($col = $cols->fetchArray(SQLITE3_ASSOC)) {
+ if ($col['name'] === 'discount_price') { $hasCol = true; break; }
+ }
+ if (!$hasCol) {
+ $db->exec("ALTER TABLE shop_configs ADD COLUMN discount_price REAL NOT NULL DEFAULT 0");
+ }
}
// 检查管理员登录
@@ -463,40 +473,63 @@ function handleShopConfigSave($db) {
$temporaryOffer = getParam('temporary_offer', '');
$offerExpire = getParam('offer_expire', '');
$price = floatval(getParam('price', 0));
+ $discountPriceRaw = getParam('discount_price', '0');
$bondReward = getParam('bond_reward', '1-1');
$isActive = intval(getParam('is_active', 1));
-
+
// 验证库存
if ($stock < -1) {
error('库存不能小于-1');
}
-
+
// 验证售价
if ($price <= 0) {
error('售价必须大于0');
}
-
+
+ // 解析优惠后价格
+ // 支持两种格式:
+ // 1. 直接价格(如 1、2、1.5)→ 直接使用
+ // 2. 折扣(如 0.9、0.8)→ 计算 原价 × 折扣
+ $discountPrice = 0;
+ $discountPriceRaw = trim($discountPriceRaw);
+ if ($discountPriceRaw !== '' && $discountPriceRaw !== '0') {
+ $discountValue = floatval($discountPriceRaw);
+ if ($discountValue <= 0) {
+ error('优惠后价格必须大于0');
+ }
+ // 判断是直接价格还是折扣(<1的数认为是折扣)
+ if ($discountValue < 1) {
+ // 折扣:原价 × 折扣
+ $discountPrice = round($price * $discountValue, 2);
+ } else {
+ // 直接价格
+ $discountPrice = round($discountValue, 2);
+ }
+ }
+
// 验证债券范围格式(支持盲盒范围,如"1-10")
if (!preg_match('/^\d+(-\d+)?$/', $bondReward)) {
error('债券范围格式错误,应为数字或范围如"1-10"');
}
-
+
// 解析并验证有效期
$expireInfo = parseExpireDate($offerExpire);
if ($offerExpire && !$expireInfo['valid']) {
error('有效期格式错误,请使用yyyy-MM-dd或中文格式如"2026年7月16日"');
}
-
+
$now = time();
-
+
if ($id > 0) {
// 编辑
- $stmt = $db->prepare("UPDATE shop_configs SET
+ $stmt = $db->prepare("UPDATE shop_configs SET
item_name = :name,
stock = :stock,
temporary_offer = :offer,
offer_expire = :expire,
price = :price,
+ discount_price = :discount_price,
bond_reward = :bond,
is_active = :active,
updated_at = :updated
@@ -504,25 +537,26 @@ function handleShopConfigSave($db) {
$stmt->bindValue(':id', $id, SQLITE3_INTEGER);
} else {
// 添加
- $stmt = $db->prepare("INSERT INTO shop_configs
- (item_name, stock, temporary_offer, offer_expire, price, bond_reward, is_active, created_at, updated_at)
- VALUES (:name, :stock, :offer, :expire, :price, :bond, :active, :created, :updated)");
+ $stmt = $db->prepare("INSERT INTO shop_configs
+ (item_name, stock, temporary_offer, offer_expire, price, discount_price, bond_reward, is_active, created_at, updated_at)
+ VALUES (:name, :stock, :offer, :expire, :price, :discount_price, :bond, :active, :created, :updated)");
$stmt->bindValue(':created', $now, SQLITE3_INTEGER);
}
-
+
$stmt->bindValue(':name', $itemName, SQLITE3_TEXT);
$stmt->bindValue(':stock', $stock, SQLITE3_INTEGER);
$stmt->bindValue(':offer', $temporaryOffer, SQLITE3_TEXT);
$stmt->bindValue(':expire', $offerExpire, SQLITE3_TEXT);
$stmt->bindValue(':price', $price, SQLITE3_FLOAT);
+ $stmt->bindValue(':discount_price', $discountPrice, SQLITE3_FLOAT);
$stmt->bindValue(':bond', $bondReward, SQLITE3_TEXT);
$stmt->bindValue(':active', $isActive, SQLITE3_INTEGER);
$stmt->bindValue(':updated', $now, SQLITE3_INTEGER);
-
+
$stmt->execute();
-
+
$savedId = $id > 0 ? $id : $db->lastInsertRowID();
- success(['id' => $savedId], $id > 0 ? '配置已更新' : '配置已添加');
+ success(['id' => $savedId, 'discount_price' => $discountPrice], $id > 0 ? '配置已更新' : '配置已添加');
}
/**
diff --git a/player.php b/player.php
index 157c94c..f915963 100644
--- a/player.php
+++ b/player.php
@@ -1218,14 +1218,22 @@ if ($currentVersion !== $BUILD_VERSION) {
// ★ 盲盒随机语录
const quoteText = isBlindBox ? `
${blindBoxQuotes[Math.floor(Math.random() * blindBoxQuotes.length)]}
` : '';
+ // 计算显示价格(折扣价格优先)
+ const displayPrice = product.discount_price > 0 ? product.discount_price : product.price;
+ const hasDiscount = product.discount_price > 0 && product.discount_price < product.price;
+
html += `
-
+
${product.item_name}
${stockText}
-
+
+
¥${displayPrice}
+ ${hasDiscount ? `
原价 ¥${product.price}
` : ''}
+
支付金额
+
→ ${bondDisplay}
${offerText}