query('SELECT `key`, `value`, updated_at FROM settings ORDER BY `key`'); AuditService::log($adminId, 'settings.list', 'settings'); Json::ok(['items' => $stmt->fetchAll()]); } public function set(int $adminId): void { $body = Json::readBody(); $key = (string)($body['key'] ?? ''); $value = (string)($body['value'] ?? ''); if ($key === '') { Json::fail('bad_request', 'key 必填', 400); } $stmt = Db::pdo()->prepare( 'INSERT INTO settings (`key`, `value`, updated_at) VALUES (:k, :v, :ts) ' . 'ON DUPLICATE KEY UPDATE `value`=VALUES(`value`), updated_at=VALUES(updated_at)' ); $stmt->execute(['k' => $key, 'v' => $value, 'ts' => date('Y-m-d H:i:s')]); AuditService::log($adminId, 'settings.set', 'setting:' . $key, ['value' => $value]); if (in_array($key, SettingsConfigLoader::PAYMENT_KEYS, true)) { PaymentConfig::reloadRuntime(); } Json::ok(['key' => $key]); } public function setBatch(int $adminId): void { $body = Json::readBody(); $items = $body['items'] ?? null; if (!is_array($items) || $items === []) { Json::fail('bad_request', 'items 须为非空数组', 400); } $pdo = Db::pdo(); $stmt = $pdo->prepare( 'INSERT INTO settings (`key`, `value`, updated_at) VALUES (:k, :v, :ts) ' . 'ON DUPLICATE KEY UPDATE `value`=VALUES(`value`), updated_at=VALUES(updated_at)' ); $saved = []; $now = date('Y-m-d H:i:s'); foreach ($items as $item) { if (!is_array($item)) { continue; } $key = trim((string)($item['key'] ?? '')); if ($key === '') { continue; } $value = (string)($item['value'] ?? ''); $stmt->execute(['k' => $key, 'v' => $value, 'ts' => $now]); $saved[] = $key; } if ($saved === []) { Json::fail('bad_request', '无有效配置项', 400); } AuditService::log($adminId, 'settings.set_batch', 'settings', ['keys' => $saved]); if (array_intersect($saved, SettingsConfigLoader::PAYMENT_KEYS) !== []) { PaymentConfig::reloadRuntime(); } Json::ok(['keys' => $saved]); } }