新增充值商店配置管理功能:库存、临时优惠、售价、债券范围、上下架

This commit is contained in:
ypsdf1
2026-07-16 14:39:44 +08:00
parent 95630c7609
commit 6da7f58281
2 changed files with 397 additions and 0 deletions
+233
View File
@@ -34,6 +34,24 @@ function getAdminPlatformDB() {
return $pdo;
}
/**
* 确保充值商店配置表存在
*/
function ensureShopConfigsTable($db) {
$db->exec("CREATE TABLE IF NOT EXISTS shop_configs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
item_name TEXT NOT NULL DEFAULT '',
stock INTEGER NOT NULL DEFAULT -1,
temporary_offer TEXT NOT NULL DEFAULT '',
offer_expire TEXT NOT NULL DEFAULT '',
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
)");
}
// 检查管理员登录
if (!isAdminLoggedIn()) {
error('无权限访问', 403);
@@ -48,6 +66,9 @@ switch ($action) {
case 'detail':
handleOrderDetail();
break;
case 'shop_config':
handleShopConfig();
break;
case 'reconcile':
handleReconcile();
break;
@@ -387,3 +408,215 @@ function ensurePayOrdersTable($db) {
$db->exec("ALTER TABLE pay_orders ADD COLUMN submit_params TEXT");
}
}
/**
* 处理充值商店配置
*/
function handleShopConfig() {
$db = getOrdersDB();
ensureShopConfigsTable($db);
$method = getParam('method', 'list');
switch ($method) {
case 'list':
handleShopConfigList($db);
break;
case 'save':
handleShopConfigSave($db);
break;
case 'delete':
handleShopConfigDelete($db);
break;
case 'toggle':
handleShopConfigToggle($db);
break;
default:
error('未知操作');
}
}
/**
* 获取商店配置列表
*/
function handleShopConfigList($db) {
$stmt = $db->query("SELECT * FROM shop_configs ORDER BY id DESC");
$configs = [];
while ($row = $stmt->fetchArray(SQLITE3_ASSOC)) {
// 解析有效期
$expireInfo = parseExpireDate($row['offer_expire']);
$row['expire_valid'] = $expireInfo['valid'];
$row['expire_timestamp'] = $expireInfo['timestamp'];
$row['expire_display'] = $expireInfo['display'];
$configs[] = $row;
}
success($configs);
}
/**
* 保存商店配置(添加或编辑)
*/
function handleShopConfigSave($db) {
$id = getParam('id', 0);
$itemName = getParam('item_name', '');
$stock = getParam('stock', -1, 'intval');
$temporaryOffer = getParam('temporary_offer', '');
$offerExpire = getParam('offer_expire', '');
$price = getParam('price', 0, 'floatval');
$bondReward = getParam('bond_reward', '1-1');
$isActive = getParam('is_active', 1, 'intval');
// 验证库存
if ($stock < -1) {
error('库存不能小于-1');
}
// 验证售价
if ($price <= 0) {
error('售价必须大于0');
}
// 验证债券范围格式(支持盲盒范围,如"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
item_name = :name,
stock = :stock,
temporary_offer = :offer,
offer_expire = :expire,
price = :price,
bond_reward = :bond,
is_active = :active,
updated_at = :updated
WHERE id = :id");
$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->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(':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 ? '配置已更新' : '配置已添加');
}
/**
* 删除商店配置
*/
function handleShopConfigDelete($db) {
$id = getParam('id', 0, 'intval');
if ($id <= 0) {
error('无效的配置ID');
}
$stmt = $db->prepare("DELETE FROM shop_configs WHERE id = :id");
$stmt->bindValue(':id', $id, SQLITE3_INTEGER);
$stmt->execute();
if ($db->changes() > 0) {
success([], '配置已删除');
} else {
error('配置不存在');
}
}
/**
* 切换商店配置上下架状态
*/
function handleShopConfigToggle($db) {
$id = getParam('id', 0, 'intval');
if ($id <= 0) {
error('无效的配置ID');
}
$stmt = $db->prepare("UPDATE shop_configs SET is_active = CASE WHEN is_active = 1 THEN 0 ELSE 1 END, updated_at = :updated WHERE id = :id");
$stmt->bindValue(':id', $id, SQLITE3_INTEGER);
$stmt->bindValue(':updated', time(), SQLITE3_INTEGER);
$stmt->execute();
if ($db->changes() > 0) {
// 获取新状态
$check = $db->prepare("SELECT is_active FROM shop_configs WHERE id = :id");
$check->bindValue(':id', $id, SQLITE3_INTEGER);
$row = $check->execute()->fetchArray(SQLITE3_ASSOC);
$newStatus = $row ? $row['is_active'] : 0;
success(['is_active' => $newStatus], $newStatus ? '已上架' : '已下架');
} else {
error('配置不存在');
}
}
/**
* 解析有效期日期(支持yyyy-MM-dd和中文格式如"2026年7月16日")
*/
function parseExpireDate($expireStr) {
if (empty($expireStr)) {
return ['valid' => true, 'timestamp' => 0, 'display' => '长期有效'];
}
$expireStr = trim($expireStr);
// 尝试解析yyyy-MM-dd格式
if (preg_match('/^\d{4}-\d{1,2}-\d{1,2}$/', $expireStr)) {
$time = strtotime($expireStr . ' 23:59:59');
if ($time !== false) {
return [
'valid' => true,
'timestamp' => $time,
'display' => date('Y-m-d', $time) . ' 到期'
];
}
}
// 尝试解析中文格式(如"2026年7月16日")
if (preg_match('/(\d{4})年(\d{1,2})月(\d{1,2})日/', $expireStr, $matches)) {
$year = $matches[1];
$month = $matches[2];
$day = $matches[3];
$time = mktime(23, 59, 59, $month, $day, $year);
if ($time !== false) {
return [
'valid' => true,
'timestamp' => $time,
'display' => "{$year}-{$month}-{$day} 到期"
];
}
}
// 尝试使用strtotime解析其他格式
$time = strtotime($expireStr);
if ($time !== false && $time > time()) {
return [
'valid' => true,
'timestamp' => $time,
'display' => date('Y-m-d', $time) . ' 到期'
];
}
return ['valid' => false, 'timestamp' => 0, 'display' => '无效日期'];
}