重构 monorepo 并完善网页端订阅与首页体验

- 迁移为 frontend-web、frontend-electron、backend-web 与 docker 部署结构
- 网页端:订阅门禁二次弹窗、套餐/支付组件化、顶栏分组对齐
- 首页:最近文件与模板库布局优化,缩略图对齐,下载与删除操作
- 新增管理后台、支付与云端文件 API,更新 README 与项目规范

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
24kycj
2026-06-08 18:17:39 +08:00
parent 5814b7bc0e
commit 88c6ce8ccc
511 changed files with 189528 additions and 22804 deletions
+97
View File
@@ -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);