重构 monorepo 并完善网页端订阅与首页体验
- 迁移为 frontend-web、frontend-electron、backend-web 与 docker 部署结构 - 网页端:订阅门禁二次弹窗、套餐/支付组件化、顶栏分组对齐 - 首页:最近文件与模板库布局优化,缩略图对齐,下载与删除操作 - 新增管理后台、支付与云端文件 API,更新 README 与项目规范 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Bootstrap: 配置加载、自动加载、生产环境禁止回退 example 配置。
|
||||
*/
|
||||
|
||||
if (defined('SOON_BOOTSTRAPPED')) {
|
||||
return;
|
||||
}
|
||||
define('SOON_BOOTSTRAPPED', true);
|
||||
|
||||
define('SOON_API_ROOT', __DIR__);
|
||||
define('SOON_SERVER_ROOT', dirname(__DIR__));
|
||||
|
||||
$configDir = SOON_SERVER_ROOT . '/config';
|
||||
$localConfig = $configDir . '/local.php';
|
||||
$exampleConfig = $configDir . '/local.php.example';
|
||||
$hostConfig = null;
|
||||
if (isset($_SERVER['HTTP_HOST'])) {
|
||||
$slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $_SERVER['HTTP_HOST']));
|
||||
$candidate = $configDir . '/config.' . $slug . '.php';
|
||||
if (is_file($candidate)) {
|
||||
$hostConfig = $candidate;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_file($localConfig)) {
|
||||
$config = require $localConfig;
|
||||
} elseif ($hostConfig !== null) {
|
||||
$config = require $hostConfig;
|
||||
} else {
|
||||
$allowExample = PHP_SAPI === 'cli' || getenv('SOON_ALLOW_EXAMPLE_CONFIG') === '1';
|
||||
if ($allowExample && is_file($exampleConfig)) {
|
||||
$config = require $exampleConfig;
|
||||
} else {
|
||||
http_response_code(500);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode([
|
||||
'error' => 'config_missing',
|
||||
'message' => '未找到 backend-web/config/local.php,请先写入生产配置。',
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($config)) {
|
||||
http_response_code(500);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode(['error' => 'config_invalid'], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($config['app']) || !is_array($config['app'])) {
|
||||
$config['app'] = [];
|
||||
}
|
||||
if (!isset($config['app']['env'])) {
|
||||
$config['app']['env'] = 'production';
|
||||
}
|
||||
if (!isset($config['app']['debug'])) {
|
||||
$config['app']['debug'] = false;
|
||||
}
|
||||
|
||||
if ($config['app']['debug']) {
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
} else {
|
||||
ini_set('display_errors', '0');
|
||||
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
|
||||
}
|
||||
|
||||
date_default_timezone_set($config['app']['timezone'] ?? 'Asia/Shanghai');
|
||||
|
||||
spl_autoload_register(static function (string $class): void {
|
||||
$prefixes = [
|
||||
'Soon\\Api\\' => SOON_API_ROOT . '/',
|
||||
'Soon\\Admin\\' => SOON_API_ROOT . '/',
|
||||
];
|
||||
foreach ($prefixes as $prefix => $baseDir) {
|
||||
if (strpos($class, $prefix) !== 0) {
|
||||
continue;
|
||||
}
|
||||
$relative = substr($class, strlen($prefix));
|
||||
$path = $baseDir . str_replace('\\', '/', $relative) . '.php';
|
||||
if (is_file($path)) {
|
||||
require $path;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
require SOON_API_ROOT . '/Core/Config.php';
|
||||
\Soon\Api\Core\Config::init($config);
|
||||
require SOON_API_ROOT . '/Services/PaymentConfigLoader.php';
|
||||
\Soon\Api\Services\PaymentConfigLoader::merge($config);
|
||||
\Soon\Api\Core\Config::init($config);
|
||||
Reference in New Issue
Block a user