mirror of
https://github.com/cedar2025/Xboard.git
synced 2025-02-14 20:48:12 -05:00
feat: add one-click update feature to admin panel
This commit is contained in:
parent
1b728fffc7
commit
39456923d3
28
app/Http/Controllers/V2/Admin/UpdateController.php
Normal file
28
app/Http/Controllers/V2/Admin/UpdateController.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V2\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\UpdateService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class UpdateController extends Controller
|
||||
{
|
||||
protected $updateService;
|
||||
|
||||
public function __construct(UpdateService $updateService)
|
||||
{
|
||||
$this->updateService = $updateService;
|
||||
}
|
||||
|
||||
public function checkUpdate()
|
||||
{
|
||||
return $this->success($this->updateService->checkForUpdates());
|
||||
}
|
||||
|
||||
public function executeUpdate()
|
||||
{
|
||||
$result = $this->updateService->executeUpdate();
|
||||
return $result['success'] ? $this->success($result) : $this->fail([500, $result['message']]);
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ use App\Http\Controllers\V2\Admin\KnowledgeController;
|
||||
use App\Http\Controllers\V2\Admin\PaymentController;
|
||||
use App\Http\Controllers\V2\Admin\SystemController;
|
||||
use App\Http\Controllers\V2\Admin\ThemeController;
|
||||
use App\Http\Controllers\V2\Admin\UpdateController;
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
@ -194,6 +195,14 @@ class AdminRoute
|
||||
$router->get('/getSystemLog', [SystemController::class, 'getSystemLog']);
|
||||
});
|
||||
|
||||
// Update
|
||||
$router->group([
|
||||
'prefix' => 'update'
|
||||
], function ($router) {
|
||||
$router->get('/check', [UpdateController::class, 'checkUpdate']);
|
||||
$router->post('/execute', [UpdateController::class, 'executeUpdate']);
|
||||
});
|
||||
|
||||
// Theme
|
||||
$router->group([
|
||||
'prefix' => 'theme'
|
||||
|
19
app/Providers/OctaneVersionProvider.php
Normal file
19
app/Providers/OctaneVersionProvider.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Services\UpdateService;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Octane\Events\WorkerStarting;
|
||||
|
||||
class OctaneVersionProvider extends ServiceProvider
|
||||
{
|
||||
public function boot(): void
|
||||
{
|
||||
if ($this->app->bound('octane')) {
|
||||
$this->app['events']->listen(WorkerStarting::class, function () {
|
||||
app(UpdateService::class)->updateVersionCache();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
439
app/Services/UpdateService.php
Normal file
439
app/Services/UpdateService.php
Normal file
@ -0,0 +1,439 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Utils\CacheKey;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class UpdateService
|
||||
{
|
||||
const UPDATE_CHECK_INTERVAL = 86400; // 24 hours
|
||||
const GITHUB_API_URL = 'https://api.github.com/repos/cedar2025/xboard/commits';
|
||||
const CACHE_UPDATE_INFO = 'UPDATE_INFO';
|
||||
const CACHE_LAST_CHECK = 'LAST_UPDATE_CHECK';
|
||||
const CACHE_UPDATE_LOCK = 'UPDATE_LOCK';
|
||||
const CACHE_VERSION = 'CURRENT_VERSION';
|
||||
const CACHE_VERSION_DATE = 'CURRENT_VERSION_DATE';
|
||||
|
||||
/**
|
||||
* Get current version from cache or generate new one
|
||||
*/
|
||||
public function getCurrentVersion(): string
|
||||
{
|
||||
$date = Cache::get(self::CACHE_VERSION_DATE, date('Ymd'));
|
||||
$hash = Cache::get(self::CACHE_VERSION, $this->getCurrentCommit());
|
||||
return $date . '-' . $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update version cache
|
||||
*/
|
||||
public function updateVersionCache(): void
|
||||
{
|
||||
try {
|
||||
$result = Process::run('git log -1 --format=%cd:%H --date=format:%Y%m%d');
|
||||
if ($result->successful()) {
|
||||
list($date, $hash) = explode(':', trim($result->output()));
|
||||
Cache::forever(self::CACHE_VERSION_DATE, $date);
|
||||
Cache::forever(self::CACHE_VERSION, substr($hash, 0, 7));
|
||||
Log::info('Version cache updated: ' . $date . '-' . substr($hash, 0, 7));
|
||||
return;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to get version with date: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
// Fallback
|
||||
Cache::forever(self::CACHE_VERSION_DATE, date('Ymd'));
|
||||
Cache::forever(self::CACHE_VERSION, $this->getCurrentCommit());
|
||||
Log::info('Version cache updated (fallback): ' . date('Ymd') . '-' . $this->getCurrentCommit());
|
||||
}
|
||||
|
||||
public function checkForUpdates(): array
|
||||
{
|
||||
try {
|
||||
// Get current version commit
|
||||
$currentCommit = $this->getCurrentCommit();
|
||||
if ($currentCommit === 'unknown') {
|
||||
// If unable to get current commit, try to get the first commit
|
||||
$currentCommit = $this->getFirstCommit();
|
||||
}
|
||||
|
||||
// Get local git logs
|
||||
$localLogs = $this->getLocalGitLogs();
|
||||
if (empty($localLogs)) {
|
||||
Log::error('Failed to get local git logs');
|
||||
return $this->getCachedUpdateInfo();
|
||||
}
|
||||
|
||||
// Get remote latest commits
|
||||
$response = Http::withHeaders([
|
||||
'Accept' => 'application/vnd.github.v3+json',
|
||||
'User-Agent' => 'XBoard-Update-Checker'
|
||||
])->get(self::GITHUB_API_URL . '?sha=master&per_page=50');
|
||||
|
||||
if ($response->successful()) {
|
||||
$commits = $response->json();
|
||||
$latestCommit = $this->formatCommitHash($commits[0]['sha']);
|
||||
|
||||
// Find current version position in commit history
|
||||
$currentIndex = -1;
|
||||
$updateLogs = [];
|
||||
$isLocalNewer = false;
|
||||
|
||||
// Check if local is newer than remote
|
||||
foreach ($localLogs as $localCommit) {
|
||||
$localHash = $this->formatCommitHash($localCommit['hash']);
|
||||
if ($localHash === $latestCommit) {
|
||||
break;
|
||||
}
|
||||
// If local commit not in remote, local version is newer
|
||||
$isLocalNewer = true;
|
||||
$updateLogs[] = [
|
||||
'version' => $localHash,
|
||||
'message' => $localCommit['message'],
|
||||
'author' => $localCommit['author'],
|
||||
'date' => $localCommit['date'],
|
||||
'is_local' => true
|
||||
];
|
||||
}
|
||||
|
||||
if (!$isLocalNewer) {
|
||||
// If local is not newer, check remote updates
|
||||
foreach ($commits as $index => $commit) {
|
||||
$shortSha = $this->formatCommitHash($commit['sha']);
|
||||
if ($shortSha === $currentCommit) {
|
||||
$currentIndex = $index;
|
||||
break;
|
||||
}
|
||||
// Collect update logs
|
||||
$updateLogs[] = [
|
||||
'version' => $shortSha,
|
||||
'message' => $commit['commit']['message'],
|
||||
'author' => $commit['commit']['author']['name'],
|
||||
'date' => $commit['commit']['author']['date'],
|
||||
'is_local' => false
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$hasUpdate = !$isLocalNewer && $currentIndex !== 0 && $currentIndex !== -1;
|
||||
|
||||
$updateInfo = [
|
||||
'has_update' => $hasUpdate,
|
||||
'is_local_newer' => $isLocalNewer,
|
||||
'latest_version' => $isLocalNewer ? $currentCommit : $latestCommit,
|
||||
'current_version' => $currentCommit,
|
||||
'update_logs' => $updateLogs,
|
||||
'download_url' => $commits[0]['html_url'] ?? '',
|
||||
'published_at' => $commits[0]['commit']['author']['date'] ?? '',
|
||||
'author' => $commits[0]['commit']['author']['name'] ?? '',
|
||||
];
|
||||
|
||||
// Cache check results
|
||||
$this->setLastCheckTime();
|
||||
Cache::put(self::CACHE_UPDATE_INFO, $updateInfo, now()->addHours(24));
|
||||
|
||||
return $updateInfo;
|
||||
}
|
||||
|
||||
return $this->getCachedUpdateInfo();
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Update check failed: ' . $e->getMessage());
|
||||
return $this->getCachedUpdateInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public function executeUpdate(): array
|
||||
{
|
||||
// Check for new version first
|
||||
$updateInfo = $this->checkForUpdates();
|
||||
if ($updateInfo['is_local_newer']) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => __('update.local_newer')
|
||||
];
|
||||
}
|
||||
if (!$updateInfo['has_update']) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => __('update.already_latest')
|
||||
];
|
||||
}
|
||||
|
||||
// Check for update lock
|
||||
if (Cache::get(self::CACHE_UPDATE_LOCK)) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => __('update.process_running')
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
// Set update lock
|
||||
Cache::put(self::CACHE_UPDATE_LOCK, true, now()->addMinutes(30));
|
||||
|
||||
// 1. Backup database
|
||||
$this->backupDatabase();
|
||||
|
||||
// 2. Pull latest code
|
||||
$result = $this->pullLatestCode();
|
||||
if (!$result['success']) {
|
||||
throw new \Exception($result['message']);
|
||||
}
|
||||
|
||||
// 3. Run database migrations
|
||||
$this->runMigrations();
|
||||
|
||||
// 4. Clear cache
|
||||
$this->clearCache();
|
||||
|
||||
// 5. Create update flag
|
||||
$this->createUpdateFlag();
|
||||
|
||||
// 6. Restart Octane if running
|
||||
$this->restartOctane();
|
||||
|
||||
// Remove update lock
|
||||
Cache::forget(self::CACHE_UPDATE_LOCK);
|
||||
|
||||
// Format update logs
|
||||
$logMessages = array_map(function($log) {
|
||||
return sprintf("- %s (%s): %s",
|
||||
$log['version'],
|
||||
date('Y-m-d H:i', strtotime($log['date'])),
|
||||
$log['message']
|
||||
);
|
||||
}, $updateInfo['update_logs']);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => __('update.success', [
|
||||
'from' => $updateInfo['current_version'],
|
||||
'to' => $updateInfo['latest_version']
|
||||
]),
|
||||
'version' => $updateInfo['latest_version'],
|
||||
'update_info' => [
|
||||
'from_version' => $updateInfo['current_version'],
|
||||
'to_version' => $updateInfo['latest_version'],
|
||||
'update_logs' => $logMessages,
|
||||
'author' => $updateInfo['author'],
|
||||
'published_at' => $updateInfo['published_at']
|
||||
]
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Update execution failed: ' . $e->getMessage());
|
||||
Cache::forget(self::CACHE_UPDATE_LOCK);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => __('update.failed', ['error' => $e->getMessage()])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCurrentCommit(): string
|
||||
{
|
||||
try {
|
||||
$result = Process::run('git rev-parse HEAD');
|
||||
$fullHash = trim($result->output());
|
||||
return $fullHash ? $this->formatCommitHash($fullHash) : 'unknown';
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to get current commit: ' . $e->getMessage());
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
protected function getFirstCommit(): string
|
||||
{
|
||||
try {
|
||||
// Get first commit hash
|
||||
$result = Process::run('git rev-list --max-parents=0 HEAD');
|
||||
$fullHash = trim($result->output());
|
||||
return $fullHash ? $this->formatCommitHash($fullHash) : 'unknown';
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to get first commit: ' . $e->getMessage());
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
protected function formatCommitHash(string $hash): string
|
||||
{
|
||||
// Use 7 characters for commit hash
|
||||
return substr($hash, 0, 7);
|
||||
}
|
||||
|
||||
protected function backupDatabase(): void
|
||||
{
|
||||
try {
|
||||
// Use existing backup command
|
||||
Process::run('php artisan backup:database');
|
||||
|
||||
if (!Process::result()->successful()) {
|
||||
throw new \Exception(__('update.backup_failed', ['error' => Process::result()->errorOutput()]));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Database backup failed: ' . $e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
protected function pullLatestCode(): array
|
||||
{
|
||||
try {
|
||||
// Get current project root directory
|
||||
$basePath = base_path();
|
||||
|
||||
// Ensure git configuration is correct
|
||||
Process::run(sprintf('git config --global --add safe.directory %s', $basePath));
|
||||
|
||||
// Pull latest code
|
||||
Process::run('git fetch origin master');
|
||||
Process::run('git reset --hard origin/master');
|
||||
|
||||
// Update dependencies
|
||||
Process::run('composer install --no-dev --optimize-autoloader');
|
||||
|
||||
// Update version cache after pulling new code
|
||||
$this->updateVersionCache();
|
||||
|
||||
return ['success' => true];
|
||||
} catch (\Exception $e) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => __('update.code_update_failed', ['error' => $e->getMessage()])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
protected function runMigrations(): void
|
||||
{
|
||||
try {
|
||||
Process::run('php artisan migrate --force');
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Migration failed: ' . $e->getMessage());
|
||||
throw new \Exception(__('update.migration_failed', ['error' => $e->getMessage()]));
|
||||
}
|
||||
}
|
||||
|
||||
protected function clearCache(): void
|
||||
{
|
||||
try {
|
||||
$commands = [
|
||||
'php artisan config:clear',
|
||||
'php artisan cache:clear',
|
||||
'php artisan view:clear',
|
||||
'php artisan route:clear'
|
||||
];
|
||||
|
||||
foreach ($commands as $command) {
|
||||
Process::run($command);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Cache clearing failed: ' . $e->getMessage());
|
||||
throw new \Exception(__('update.cache_clear_failed', ['error' => $e->getMessage()]));
|
||||
}
|
||||
}
|
||||
|
||||
protected function createUpdateFlag(): void
|
||||
{
|
||||
try {
|
||||
// Create update flag file for external script to detect and restart container
|
||||
$flagFile = storage_path('update_pending');
|
||||
File::put($flagFile, date('Y-m-d H:i:s'));
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to create update flag: ' . $e->getMessage());
|
||||
throw new \Exception(__('update.flag_create_failed', ['error' => $e->getMessage()]));
|
||||
}
|
||||
}
|
||||
|
||||
protected function restartOctane(): void
|
||||
{
|
||||
try {
|
||||
if (!config('octane.server')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check Octane running status
|
||||
$statusResult = Process::run('php artisan octane:status');
|
||||
if (!$statusResult->successful()) {
|
||||
Log::info('Octane is not running, skipping restart.');
|
||||
return;
|
||||
}
|
||||
|
||||
$output = $statusResult->output();
|
||||
if (str_contains($output, 'Octane server is running')) {
|
||||
Log::info('Restarting Octane server after update...');
|
||||
// Update version cache before restart
|
||||
$this->updateVersionCache();
|
||||
Process::run('php artisan octane:reload');
|
||||
Log::info('Octane server restarted successfully.');
|
||||
} else {
|
||||
Log::info('Octane is not running, skipping restart.');
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to restart Octane server: ' . $e->getMessage());
|
||||
// Non-fatal error, don't throw exception
|
||||
}
|
||||
}
|
||||
|
||||
public function getLastCheckTime()
|
||||
{
|
||||
return Cache::get(self::CACHE_LAST_CHECK, null);
|
||||
}
|
||||
|
||||
protected function setLastCheckTime(): void
|
||||
{
|
||||
Cache::put(self::CACHE_LAST_CHECK, now()->timestamp, now()->addDays(30));
|
||||
}
|
||||
|
||||
public function getCachedUpdateInfo(): array
|
||||
{
|
||||
return Cache::get(self::CACHE_UPDATE_INFO, [
|
||||
'has_update' => false,
|
||||
'latest_version' => $this->getCurrentCommit(),
|
||||
'current_version' => $this->getCurrentCommit(),
|
||||
'update_logs' => [],
|
||||
'download_url' => '',
|
||||
'published_at' => '',
|
||||
'author' => '',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getLocalGitLogs(int $limit = 50): array
|
||||
{
|
||||
try {
|
||||
// 获取本地git log
|
||||
$result = Process::run(
|
||||
sprintf('git log -%d --pretty=format:"%%H||%%s||%%an||%%ai"', $limit)
|
||||
);
|
||||
|
||||
if (!$result->successful()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$logs = [];
|
||||
$lines = explode("\n", trim($result->output()));
|
||||
foreach ($lines as $line) {
|
||||
$parts = explode('||', $line);
|
||||
if (count($parts) === 4) {
|
||||
$logs[] = [
|
||||
'hash' => $parts[0],
|
||||
'message' => $parts[1],
|
||||
'author' => $parts[2],
|
||||
'date' => $parts[3]
|
||||
];
|
||||
}
|
||||
}
|
||||
return $logs;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to get local git logs: ' . $e->getMessage());
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
@ -177,6 +177,7 @@ return [
|
||||
App\Providers\SettingServiceProvider::class,
|
||||
App\Providers\OctaneSchedulerProvider::class,
|
||||
App\Providers\PluginServiceProvider::class,
|
||||
App\Providers\OctaneVersionProvider::class,
|
||||
|
||||
],
|
||||
|
||||
|
2
public/assets/admin/assets/index.css
vendored
2
public/assets/admin/assets/index.css
vendored
File diff suppressed because one or more lines are too long
8
public/assets/admin/assets/index.js
vendored
8
public/assets/admin/assets/index.js
vendored
File diff suppressed because one or more lines are too long
180
public/assets/admin/assets/vendor.js
vendored
180
public/assets/admin/assets/vendor.js
vendored
File diff suppressed because one or more lines are too long
11
public/assets/admin/locales/en-US.js
vendored
11
public/assets/admin/locales/en-US.js
vendored
@ -874,6 +874,17 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
|
||||
"nextPage": "Next page",
|
||||
"lastPage": "Go to last page"
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"title": "System Update",
|
||||
"newVersion": "New Version Available",
|
||||
"currentVersion": "Current Version",
|
||||
"latestVersion": "Latest Version",
|
||||
"updateLater": "Update Later",
|
||||
"updateNow": "Update Now",
|
||||
"updating": "Updating...",
|
||||
"updateSuccess": "Update successful, system will restart shortly",
|
||||
"updateFailed": "Update failed, please try again later"
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
|
11
public/assets/admin/locales/ko-KR.js
vendored
11
public/assets/admin/locales/ko-KR.js
vendored
@ -870,6 +870,17 @@ window.XBOARD_TRANSLATIONS['ko-KR'] = {
|
||||
"nextPage": "다음 페이지",
|
||||
"lastPage": "마지막 페이지로 이동"
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"title": "시스템 업데이트",
|
||||
"newVersion": "새 버전 발견",
|
||||
"currentVersion": "현재 버전",
|
||||
"latestVersion": "최신 버전",
|
||||
"updateLater": "나중에 업데이트",
|
||||
"updateNow": "지금 업데이트",
|
||||
"updating": "업데이트 중...",
|
||||
"updateSuccess": "업데이트 성공, 시스템이 곧 재시작됩니다",
|
||||
"updateFailed": "업데이트 실패, 나중에 다시 시도해주세요"
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
|
11
public/assets/admin/locales/zh-CN.js
vendored
11
public/assets/admin/locales/zh-CN.js
vendored
@ -879,6 +879,17 @@ window.XBOARD_TRANSLATIONS['zh-CN'] = {
|
||||
"nextPage": "下一页",
|
||||
"lastPage": "跳转到最后一页"
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"title": "系统更新",
|
||||
"newVersion": "发现新版本",
|
||||
"currentVersion": "当前版本",
|
||||
"latestVersion": "最新版本",
|
||||
"updateLater": "稍后更新",
|
||||
"updateNow": "立即更新",
|
||||
"updating": "更新中...",
|
||||
"updateSuccess": "更新成功,系统将在稍后自动重启",
|
||||
"updateFailed": "更新失败,请稍后重试"
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
|
@ -119,5 +119,15 @@
|
||||
"Monthly": "Monthly",
|
||||
"Never": "Never",
|
||||
"First Day of Year": "First Day of Year",
|
||||
"Yearly": "Yearly"
|
||||
"Yearly": "Yearly",
|
||||
"update.local_newer": "Current version is newer than remote version, please commit your changes first",
|
||||
"update.already_latest": "Already on the latest version",
|
||||
"update.process_running": "Update process is already running",
|
||||
"update.success": "Update successful, from :from to :to, system will restart automatically later",
|
||||
"update.failed": "Update failed: :error",
|
||||
"update.backup_failed": "Database backup failed: :error",
|
||||
"update.code_update_failed": "Code update failed: :error",
|
||||
"update.migration_failed": "Database migration failed: :error",
|
||||
"update.cache_clear_failed": "Cache clearing failed: :error",
|
||||
"update.flag_create_failed": "Failed to create update flag: :error"
|
||||
}
|
||||
|
@ -119,5 +119,15 @@
|
||||
"Monthly": "按月",
|
||||
"Never": "不重置",
|
||||
"First Day of Year": "每年1月1日",
|
||||
"Yearly": "按年"
|
||||
"Yearly": "按年",
|
||||
"update.local_newer": "当前版本比远程版本更新,请先提交您的更改",
|
||||
"update.already_latest": "当前已经是最新版本",
|
||||
"update.process_running": "更新进程正在运行中",
|
||||
"update.success": "更新成功,从 :from 更新到 :to, 系统将在稍后自动重启",
|
||||
"update.failed": "更新失败: :error",
|
||||
"update.backup_failed": "数据库备份失败: :error",
|
||||
"update.code_update_failed": "代码更新失败: :error",
|
||||
"update.migration_failed": "数据库迁移失败: :error",
|
||||
"update.cache_clear_failed": "缓存清理失败: :error",
|
||||
"update.flag_create_failed": "创建更新标记失败: :error"
|
||||
}
|
||||
|
@ -119,5 +119,15 @@
|
||||
"Monthly": "按月",
|
||||
"Never": "不重置",
|
||||
"First Day of Year": "每年1月1日",
|
||||
"Yearly": "按年"
|
||||
"Yearly": "按年",
|
||||
"update.local_newer": "當前版本比遠程版本更新,請先提交您的更改",
|
||||
"update.already_latest": "當前已經是最新版本",
|
||||
"update.process_running": "更新進程正在運行中",
|
||||
"update.success": "更新成功,從 :from 更新到 :to, 系統將在稍後自動重啟",
|
||||
"update.failed": "更新失敗: :error",
|
||||
"update.backup_failed": "數據庫備份失敗: :error",
|
||||
"update.code_update_failed": "代碼更新失敗: :error",
|
||||
"update.migration_failed": "數據庫遷移失敗: :error",
|
||||
"update.cache_clear_failed": "緩存清理失敗: :error",
|
||||
"update.flag_create_failed": "創建更新標記失敗: :error"
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Services\ThemeService;
|
||||
use App\Services\UpdateService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@ -57,7 +58,7 @@ Route::get('/', function (Request $request) {
|
||||
$renderParams = [
|
||||
'title' => admin_setting('app_name', 'Xboard'),
|
||||
'theme' => $theme,
|
||||
'version' => config('app.version'),
|
||||
'version' => app(UpdateService::class)->getCurrentVersion(),
|
||||
'description' => admin_setting('app_description', 'Xboard is best'),
|
||||
'logo' => admin_setting('logo'),
|
||||
'theme_config' => $themeService->getConfig($theme)
|
||||
@ -80,7 +81,7 @@ Route::get('/' . admin_setting('secure_path', admin_setting('frontend_admin_path
|
||||
'theme_header' => admin_setting('frontend_theme_header', 'dark'),
|
||||
'theme_color' => admin_setting('frontend_theme_color', 'default'),
|
||||
'background_url' => admin_setting('frontend_background_url'),
|
||||
'version' => config('app.version'),
|
||||
'version' => app(UpdateService::class)->getCurrentVersion(),
|
||||
'logo' => admin_setting('logo'),
|
||||
'secure_path' => admin_setting('secure_path', admin_setting('frontend_admin_path', hash('crc32b', config('app.key'))))
|
||||
]);
|
||||
|
Loading…
Reference in New Issue
Block a user