debug
This commit is contained in:
@@ -7,6 +7,7 @@ use app\admin\controller\Index;
|
||||
use app\admin\controller\Domain;
|
||||
use app\admin\controller\SeoSupply;
|
||||
use app\admin\controller\Novel;
|
||||
use app\admin\controller\ServerNode;
|
||||
use app\admin\controller\Site;
|
||||
use app\admin\controller\SystemConfig;
|
||||
use app\admin\controller\Video;
|
||||
@@ -32,6 +33,9 @@ Route::group("/system", function () {
|
||||
Route::post("/config/save", [SystemConfig::class, "saveSystemConfig"])->name("SystemConfig@saveSystemConfig");
|
||||
Route::post("/config/seo-ai-rules/reset", [SystemConfig::class, "resetSeoAiRules"])->name("SystemConfig@resetSeoAiRules");
|
||||
Route::get("/storage/file", [SystemConfig::class, "previewStorageFile"])->name("SystemConfig@previewStorageFile");
|
||||
Route::get("/node/list", [ServerNode::class, "getServerNodeList"])->name("ServerNode@getServerNodeList");
|
||||
Route::post("/node/save", [ServerNode::class, "saveServerNode"])->name("ServerNode@saveServerNode");
|
||||
Route::post("/node/del", [ServerNode::class, "delServerNode"])->name("ServerNode@delServerNode");
|
||||
|
||||
Route::get("/cjpz/list", [SystemConfig::class, "getCaiJiPeiZhiList"])->name("SystemConfig@getCaiJiPeiZhiList");
|
||||
Route::post("/cjpz/save", [SystemConfig::class, "saveCaiJiPeiZhi"])->name("SystemConfig@saveCaiJiPeiZhi");
|
||||
|
||||
210
code/app/admin/controller/ServerNode.php
Normal file
210
code/app/admin/controller/ServerNode.php
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\BaseController;
|
||||
use app\model\AdminUserModel;
|
||||
use app\model\ServerNodeModel;
|
||||
use app\Request;
|
||||
use think\Response;
|
||||
|
||||
class ServerNode extends BaseController
|
||||
{
|
||||
/**
|
||||
* 前端服务器节点列表
|
||||
*/
|
||||
public function getServerNodeList(Request $Request, ?AdminUserModel $AdminUserModel): Response
|
||||
{
|
||||
$arrData = [
|
||||
'page' => (int)$Request->get('page', 1),
|
||||
'limit' => (int)$Request->get('limit', 10),
|
||||
'key' => trim((string)$Request->get('key', '')),
|
||||
];
|
||||
|
||||
$this->validate($arrData, [
|
||||
'page' => 'require|number',
|
||||
'limit' => 'require|number',
|
||||
]);
|
||||
|
||||
$ServerNodeModel = ServerNodeModel::alias('sn')
|
||||
->order('sn.sn_status', 'desc')
|
||||
->order('sn.updated_at', 'desc')
|
||||
->order('sn.sn_id', 'desc');
|
||||
|
||||
if ($arrData['key'] !== '') {
|
||||
$strKey = $arrData['key'];
|
||||
$ServerNodeModel->where(function ($query) use ($strKey) {
|
||||
$query->whereOr([
|
||||
['sn.sn_name', 'like', '%' . $strKey . '%'],
|
||||
['sn.sn_code', 'like', '%' . $strKey . '%'],
|
||||
['sn.sn_host', 'like', '%' . $strKey . '%'],
|
||||
['sn.sn_username', 'like', '%' . $strKey . '%'],
|
||||
['sn.sn_region', 'like', '%' . $strKey . '%'],
|
||||
['sn.sn_purpose', 'like', '%' . $strKey . '%'],
|
||||
['sn.sn_project_dir', 'like', '%' . $strKey . '%'],
|
||||
['sn.sn_log_dir', 'like', '%' . $strKey . '%'],
|
||||
['sn.sn_nginx_dir', 'like', '%' . $strKey . '%'],
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
$Paginate = $ServerNodeModel->paginate([
|
||||
'list_rows' => $arrData['limit'],
|
||||
'page' => $arrData['page'],
|
||||
]);
|
||||
|
||||
$arrItems = [];
|
||||
foreach ($Paginate->items() as $arrItem) {
|
||||
$arrItems[] = $this->serializeServerNodeRow($arrItem);
|
||||
}
|
||||
|
||||
return $this->success([
|
||||
'items' => $arrItems,
|
||||
'total' => $Paginate->total(),
|
||||
'current_page' => $Paginate->currentPage(),
|
||||
'total_pages' => $Paginate->lastPage(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前端服务器节点
|
||||
*/
|
||||
public function saveServerNode(Request $Request, ?AdminUserModel $AdminUserModel): Response
|
||||
{
|
||||
$arrData = [
|
||||
'sn_id' => $Request->post('sn_id'),
|
||||
'sn_name' => trim((string)$Request->post('sn_name', '')),
|
||||
'sn_code' => $this->normalizeNullableString($Request->post('sn_code')),
|
||||
'sn_host' => trim((string)$Request->post('sn_host', '')),
|
||||
'sn_port' => (int)$Request->post('sn_port', 22),
|
||||
'sn_username' => trim((string)$Request->post('sn_username', '')),
|
||||
'sn_auth_type' => trim((string)$Request->post('sn_auth_type', 'password')),
|
||||
'sn_password' => trim((string)$Request->post('sn_password', '')),
|
||||
'sn_private_key' => trim((string)$Request->post('sn_private_key', '')),
|
||||
'sn_passphrase' => trim((string)$Request->post('sn_passphrase', '')),
|
||||
'sn_region' => $this->normalizeNullableString($Request->post('sn_region')),
|
||||
'sn_purpose' => $this->normalizeNullableString($Request->post('sn_purpose')),
|
||||
'sn_project_dir' => $this->normalizeNullableString($Request->post('sn_project_dir')),
|
||||
'sn_log_dir' => $this->normalizeNullableString($Request->post('sn_log_dir')),
|
||||
'sn_nginx_dir' => $this->normalizeNullableString($Request->post('sn_nginx_dir')),
|
||||
'sn_note' => $this->normalizeNullableString($Request->post('sn_note')),
|
||||
'sn_status' => (int)$Request->post('sn_status', 1),
|
||||
];
|
||||
|
||||
$this->validate($arrData, [
|
||||
'sn_name' => 'require|max:255',
|
||||
'sn_host' => 'require|max:255',
|
||||
'sn_port' => 'require|number|between:1,65535',
|
||||
'sn_username' => 'require|max:100',
|
||||
'sn_auth_type' => 'require|in:password,private_key',
|
||||
'sn_status' => 'require|in:0,1',
|
||||
]);
|
||||
|
||||
$boolIsCreate = empty($arrData['sn_id']);
|
||||
if ($boolIsCreate) {
|
||||
$ServerNodeModel = new ServerNodeModel();
|
||||
} else {
|
||||
$ServerNodeModel = ServerNodeModel::where('sn_id', (int)$arrData['sn_id'])->find();
|
||||
if (empty($ServerNodeModel)) {
|
||||
return $this->error('9993', '服务器节点不存在');
|
||||
}
|
||||
}
|
||||
|
||||
if ($arrData['sn_code'] !== null) {
|
||||
$DuplicateModel = ServerNodeModel::where('sn_code', $arrData['sn_code']);
|
||||
if (!$boolIsCreate) {
|
||||
$DuplicateModel->where('sn_id', '<>', (int)$arrData['sn_id']);
|
||||
}
|
||||
if ($DuplicateModel->find() !== null) {
|
||||
return $this->error('9993', '节点编码已存在,请更换后重试');
|
||||
}
|
||||
}
|
||||
|
||||
$strCurrentAuthType = trim((string)($ServerNodeModel->sn_auth_type ?? ''));
|
||||
$boolHasExistingPassword = trim((string)($ServerNodeModel->sn_password ?? '')) !== '';
|
||||
$boolHasExistingPrivateKey = trim((string)($ServerNodeModel->sn_private_key ?? '')) !== '';
|
||||
|
||||
if ($arrData['sn_auth_type'] === 'password') {
|
||||
if ($arrData['sn_password'] === '') {
|
||||
if ($boolIsCreate || $strCurrentAuthType !== 'password' || !$boolHasExistingPassword) {
|
||||
return $this->error('9993', '当前登录方式为密码,请填写 SSH 密码');
|
||||
}
|
||||
unset($arrData['sn_password']);
|
||||
}
|
||||
|
||||
$arrData['sn_private_key'] = '';
|
||||
$arrData['sn_passphrase'] = '';
|
||||
} else {
|
||||
if ($arrData['sn_private_key'] === '') {
|
||||
if ($boolIsCreate || $strCurrentAuthType !== 'private_key' || !$boolHasExistingPrivateKey) {
|
||||
return $this->error('9993', '当前登录方式为私钥,请填写 SSH 私钥');
|
||||
}
|
||||
unset($arrData['sn_private_key']);
|
||||
if ($arrData['sn_passphrase'] === '') {
|
||||
unset($arrData['sn_passphrase']);
|
||||
}
|
||||
}
|
||||
|
||||
$arrData['sn_password'] = '';
|
||||
}
|
||||
|
||||
$ServerNodeModel->fill($arrData);
|
||||
$ServerNodeModel->save();
|
||||
|
||||
return $this->success([
|
||||
'sn_id' => (int)$ServerNodeModel->sn_id,
|
||||
], $boolIsCreate ? '服务器节点新增成功' : '服务器节点保存成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除前端服务器节点
|
||||
*/
|
||||
public function delServerNode(Request $Request, ?AdminUserModel $AdminUserModel): Response
|
||||
{
|
||||
$arrData = [
|
||||
'sn_id' => trim((string)$Request->post('sn_id', '')),
|
||||
];
|
||||
|
||||
$this->validate($arrData, [
|
||||
'sn_id' => 'require',
|
||||
]);
|
||||
|
||||
$arrIds = array_values(array_unique(array_filter(array_map('intval', explode(',', $arrData['sn_id'])), static function (int $intId): bool {
|
||||
return $intId > 0;
|
||||
})));
|
||||
|
||||
if ($arrIds === []) {
|
||||
return $this->error('9993', '未识别到可删除的服务器节点');
|
||||
}
|
||||
|
||||
ServerNodeModel::whereIn('sn_id', $arrIds)->delete();
|
||||
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 屏蔽列表接口里的敏感 SSH 凭证,只返回配置状态。
|
||||
*/
|
||||
protected function serializeServerNodeRow($arrItem): array
|
||||
{
|
||||
$arrRow = is_array($arrItem) ? $arrItem : $arrItem->toArray();
|
||||
$arrRow['sn_port'] = (int)($arrRow['sn_port'] ?? 22);
|
||||
$arrRow['sn_status'] = (int)($arrRow['sn_status'] ?? 1);
|
||||
$arrRow['sn_password_configured'] = trim((string)($arrRow['sn_password'] ?? '')) !== '';
|
||||
$arrRow['sn_private_key_configured'] = trim((string)($arrRow['sn_private_key'] ?? '')) !== '';
|
||||
$arrRow['sn_passphrase_configured'] = trim((string)($arrRow['sn_passphrase'] ?? '')) !== '';
|
||||
|
||||
unset($arrRow['sn_password'], $arrRow['sn_private_key'], $arrRow['sn_passphrase']);
|
||||
|
||||
return $arrRow;
|
||||
}
|
||||
|
||||
protected function normalizeNullableString($value): ?string
|
||||
{
|
||||
$strValue = trim((string)$value);
|
||||
|
||||
return $strValue === '' ? null : $strValue;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ class DomainExternalSeoSnapshotAnalysisHelper
|
||||
|
||||
$arrProviders = [];
|
||||
$arrHosts = [];
|
||||
$arrLatestIndexByHost = [];
|
||||
$arrLatestSignalsByHost = [];
|
||||
$intKeywordSnapshots = (int)SeoExternalSnapshotModel::where('metric_date', '>=', $strStartDate)
|
||||
->where('scope', 'keyword')
|
||||
->count();
|
||||
@@ -28,9 +28,10 @@ class DomainExternalSeoSnapshotAnalysisHelper
|
||||
self::eachSnapshotRow(
|
||||
SeoExternalSnapshotModel::where('metric_date', '>=', $strStartDate)
|
||||
->where('scope', 'host'),
|
||||
['id', 'provider', 'host', 'scope', 'metric_date', 'status', 'indexed_status', 'baidu_pc_ip_range', 'baidu_mobile_ip_range', 'pc_keyword_count', 'mobile_keyword_count', 'queried_at'],
|
||||
static function (array $arrItem) use (&$arrProviders, &$arrHosts, &$arrLatestIndexByHost, &$strLatestMetricDate): void {
|
||||
['id', 'provider', 'snapshot_type', 'host', 'scope', 'metric_date', 'status', 'indexed_status', 'result_count_text', 'baidu_pc_ip_range', 'baidu_mobile_ip_range', 'pc_keyword_count', 'mobile_keyword_count', 'queried_at'],
|
||||
static function (array $arrItem) use (&$arrProviders, &$arrHosts, &$arrLatestSignalsByHost, &$strLatestMetricDate): void {
|
||||
$strProvider = trim((string)($arrItem['provider'] ?? ''));
|
||||
$strSnapshotType = trim((string)($arrItem['snapshot_type'] ?? ''));
|
||||
$strHost = trim((string)($arrItem['host'] ?? ''));
|
||||
$strMetricDate = trim((string)($arrItem['metric_date'] ?? ''));
|
||||
$strStatus = trim((string)($arrItem['status'] ?? ''));
|
||||
@@ -48,34 +49,33 @@ class DomainExternalSeoSnapshotAnalysisHelper
|
||||
}
|
||||
|
||||
if ($strHost !== '') {
|
||||
$strHostKey = $strHost;
|
||||
$arrCurrent = $arrLatestIndexByHost[$strHostKey] ?? null;
|
||||
$boolShouldReplace = false;
|
||||
if (!$arrCurrent) {
|
||||
$boolShouldReplace = true;
|
||||
} else {
|
||||
$strCurrentDate = (string)($arrCurrent['metric_date'] ?? '');
|
||||
$intCurrentQueriedAt = (int)($arrCurrent['queried_at'] ?? 0);
|
||||
if (strcmp($strCurrentDate, $strMetricDate) < 0) {
|
||||
$boolShouldReplace = true;
|
||||
} elseif ($strCurrentDate === $strMetricDate && $intCurrentQueriedAt < $intQueriedAt) {
|
||||
$boolShouldReplace = true;
|
||||
}
|
||||
$arrCandidate = [
|
||||
'host' => $strHost,
|
||||
'provider' => $strProvider,
|
||||
'snapshot_type' => $strSnapshotType,
|
||||
'metric_date' => $strMetricDate,
|
||||
'queried_at' => $intQueriedAt,
|
||||
'status' => $strStatus,
|
||||
'indexed_status' => $strIndexedStatus,
|
||||
'result_count_text' => trim((string)($arrItem['result_count_text'] ?? '')),
|
||||
'baidu_pc_ip_range' => trim((string)($arrItem['baidu_pc_ip_range'] ?? '')),
|
||||
'baidu_mobile_ip_range' => trim((string)($arrItem['baidu_mobile_ip_range'] ?? '')),
|
||||
'pc_keyword_count' => (int)($arrItem['pc_keyword_count'] ?? 0),
|
||||
'mobile_keyword_count' => (int)($arrItem['mobile_keyword_count'] ?? 0),
|
||||
];
|
||||
|
||||
if (self::shouldReplaceSnapshot($arrLatestSignalsByHost[$strHost]['display'] ?? null, $strMetricDate, $intQueriedAt)) {
|
||||
$arrLatestSignalsByHost[$strHost]['display'] = $arrCandidate;
|
||||
}
|
||||
|
||||
if ($boolShouldReplace) {
|
||||
$arrLatestIndexByHost[$strHostKey] = [
|
||||
'host' => $strHost,
|
||||
'provider' => $strProvider,
|
||||
'metric_date' => $strMetricDate,
|
||||
'queried_at' => $intQueriedAt,
|
||||
'status' => $strStatus,
|
||||
'indexed_status' => $strIndexedStatus,
|
||||
'baidu_pc_ip_range' => trim((string)($arrItem['baidu_pc_ip_range'] ?? '')),
|
||||
'baidu_mobile_ip_range' => trim((string)($arrItem['baidu_mobile_ip_range'] ?? '')),
|
||||
'pc_keyword_count' => (int)($arrItem['pc_keyword_count'] ?? 0),
|
||||
'mobile_keyword_count' => (int)($arrItem['mobile_keyword_count'] ?? 0),
|
||||
];
|
||||
if ($strSnapshotType === 'site_query'
|
||||
&& self::shouldReplaceSnapshot($arrLatestSignalsByHost[$strHost]['index'] ?? null, $strMetricDate, $intQueriedAt)) {
|
||||
$arrLatestSignalsByHost[$strHost]['index'] = $arrCandidate;
|
||||
}
|
||||
|
||||
if ($strSnapshotType === 'aizhan_summary'
|
||||
&& self::shouldReplaceSnapshot($arrLatestSignalsByHost[$strHost]['keyword'] ?? null, $strMetricDate, $intQueriedAt)) {
|
||||
$arrLatestSignalsByHost[$strHost]['keyword'] = $arrCandidate;
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -85,13 +85,44 @@ class DomainExternalSeoSnapshotAnalysisHelper
|
||||
$intIndexedLikeCount = 0;
|
||||
$intKeywordReadyCount = 0;
|
||||
$intTrafficReadyCount = 0;
|
||||
$arrHostRows = array_values($arrLatestIndexByHost);
|
||||
$arrHostRows = [];
|
||||
|
||||
foreach ($arrLatestSignalsByHost as $strHost => $arrSignals) {
|
||||
$arrDisplay = (array)($arrSignals['display'] ?? []);
|
||||
$arrIndex = (array)($arrSignals['index'] ?? []);
|
||||
$arrKeyword = (array)($arrSignals['keyword'] ?? []);
|
||||
$arrProvidersForHost = [];
|
||||
|
||||
foreach ([$arrIndex, $arrKeyword, $arrDisplay] as $arrSignalRow) {
|
||||
$strSignalProvider = trim((string)($arrSignalRow['provider'] ?? ''));
|
||||
if ($strSignalProvider !== '') {
|
||||
$arrProvidersForHost[$strSignalProvider] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$arrHostRows[] = [
|
||||
'host' => $strHost,
|
||||
'provider' => implode(',', array_keys($arrProvidersForHost)),
|
||||
'index_provider' => (string)($arrIndex['provider'] ?? ''),
|
||||
'keyword_provider' => (string)($arrKeyword['provider'] ?? ''),
|
||||
'metric_date' => max((string)($arrDisplay['metric_date'] ?? ''), (string)($arrIndex['metric_date'] ?? ''), (string)($arrKeyword['metric_date'] ?? '')),
|
||||
'queried_at' => max((int)($arrDisplay['queried_at'] ?? 0), (int)($arrIndex['queried_at'] ?? 0), (int)($arrKeyword['queried_at'] ?? 0)),
|
||||
'status' => (string)($arrDisplay['status'] ?? ''),
|
||||
'indexed_status' => (string)($arrIndex['indexed_status'] ?? ''),
|
||||
'result_count_text' => (string)($arrIndex['result_count_text'] ?? ''),
|
||||
'baidu_pc_ip_range' => (string)($arrKeyword['baidu_pc_ip_range'] ?? ''),
|
||||
'baidu_mobile_ip_range' => (string)($arrKeyword['baidu_mobile_ip_range'] ?? ''),
|
||||
'pc_keyword_count' => (int)($arrKeyword['pc_keyword_count'] ?? 0),
|
||||
'mobile_keyword_count' => (int)($arrKeyword['mobile_keyword_count'] ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($arrHostRows as &$arrRow) {
|
||||
$boolIndexedLike = (string)($arrRow['indexed_status'] ?? '') === 'indexed_like';
|
||||
$boolIndexedLike = self::normalizeIndexState($arrRow) === 'indexed_like';
|
||||
$boolKeywordReady = (int)($arrRow['pc_keyword_count'] ?? 0) > 0 || (int)($arrRow['mobile_keyword_count'] ?? 0) > 0;
|
||||
$boolTrafficReady = !self::isZeroRange((string)($arrRow['baidu_pc_ip_range'] ?? ''))
|
||||
|| !self::isZeroRange((string)($arrRow['baidu_mobile_ip_range'] ?? ''));
|
||||
$arrRow['indexed_like'] = $boolIndexedLike;
|
||||
$arrRow['keyword_ready'] = $boolKeywordReady;
|
||||
$arrRow['traffic_ready'] = $boolTrafficReady;
|
||||
|
||||
@@ -113,6 +144,11 @@ class DomainExternalSeoSnapshotAnalysisHelper
|
||||
if ($intLeftKeyword !== $intRightKeyword) {
|
||||
return $intRightKeyword <=> $intLeftKeyword;
|
||||
}
|
||||
$intLeftIndexed = !empty($arrLeft['indexed_like']) ? 1 : 0;
|
||||
$intRightIndexed = !empty($arrRight['indexed_like']) ? 1 : 0;
|
||||
if ($intLeftIndexed !== $intRightIndexed) {
|
||||
return $intRightIndexed <=> $intLeftIndexed;
|
||||
}
|
||||
return strcmp((string)($arrLeft['host'] ?? ''), (string)($arrRight['host'] ?? ''));
|
||||
});
|
||||
|
||||
@@ -402,6 +438,19 @@ class DomainExternalSeoSnapshotAnalysisHelper
|
||||
return $strRange === '' || $strRange === '0 ~ 0' || $strRange === '0~0';
|
||||
}
|
||||
|
||||
protected static function shouldReplaceSnapshot(?array $arrCurrent, string $strMetricDate, int $intQueriedAt): bool
|
||||
{
|
||||
if (!$arrCurrent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$strCurrentDate = (string)($arrCurrent['metric_date'] ?? '');
|
||||
$intCurrentQueriedAt = (int)($arrCurrent['queried_at'] ?? 0);
|
||||
|
||||
return strcmp($strCurrentDate, $strMetricDate) < 0
|
||||
|| ($strCurrentDate === $strMetricDate && $intCurrentQueriedAt < $intQueriedAt);
|
||||
}
|
||||
|
||||
protected static function normalizeIndexState(array $arrRow): string
|
||||
{
|
||||
$strIndexedStatus = trim((string)($arrRow['indexed_status'] ?? ''));
|
||||
|
||||
@@ -27,14 +27,6 @@ class JsBuilder
|
||||
@mkdir($targetDir, 0755, true);
|
||||
}
|
||||
|
||||
// 输出文件名(域名专属缓存)
|
||||
$targetFile = $targetDir . "{$staticHash}.js";
|
||||
|
||||
// 如果已经生成过,直接返回
|
||||
if (file_exists($targetFile)) {
|
||||
return "/static/js/compiled/{$staticHash}.js";
|
||||
}
|
||||
|
||||
// 你可以像 CSS 一样在这里挂一个“全站基础 JS”
|
||||
// 注意:如果没有这个文件,就别写入,否则会被 skip
|
||||
$listJs = [
|
||||
@@ -46,9 +38,46 @@ class JsBuilder
|
||||
$finalJsFiles = array_merge($listJs, $jsFiles);
|
||||
$finalJsFiles = array_values(array_unique(array_filter($finalJsFiles)));
|
||||
|
||||
$signatureParts = [
|
||||
'static_hash' => $staticHash,
|
||||
'dom_prefix' => $domPrefix,
|
||||
'builder' => is_file(__FILE__) ? sha1_file(__FILE__) : (string)@filemtime(__FILE__),
|
||||
'files' => [],
|
||||
];
|
||||
|
||||
// 如果 compiled 已存在且比所有源文件都新,直接返回;否则自动重建。
|
||||
$intLatestSourceTime = @filemtime(__FILE__) ?: 0;
|
||||
foreach ($finalJsFiles as $file) {
|
||||
$file = ltrim((string)$file, '/');
|
||||
$path = $baseDir . $file;
|
||||
if (is_file($path)) {
|
||||
$intLatestSourceTime = max($intLatestSourceTime, (int)@filemtime($path));
|
||||
$signatureParts['files'][] = [
|
||||
'file' => $file,
|
||||
'mtime' => (int)@filemtime($path),
|
||||
'size' => (int)@filesize($path),
|
||||
'sha1' => sha1_file($path),
|
||||
];
|
||||
} else {
|
||||
$signatureParts['files'][] = [
|
||||
'file' => $file,
|
||||
'missing' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 前端代理的静态缓存按 path 命中,query version 无法兜底;文件名必须跟随源码变化。
|
||||
$sourceHash = substr(sha1((string)json_encode($signatureParts, JSON_UNESCAPED_SLASHES)), 0, 10);
|
||||
$targetName = "{$staticHash}-{$sourceHash}.js";
|
||||
$targetFile = $targetDir . $targetName;
|
||||
|
||||
if (file_exists($targetFile) && (int)@filemtime($targetFile) >= $intLatestSourceTime) {
|
||||
return "/static/js/compiled/{$targetName}";
|
||||
}
|
||||
|
||||
// 合并 JS 文件内容
|
||||
$allJs = "";
|
||||
$allJs .= "/*! compiled: {$staticHash}.js */\n";
|
||||
$allJs .= "/*! compiled: {$targetName} */\n";
|
||||
$allJs .= "(function(){\n'use strict';\n";
|
||||
|
||||
foreach ($finalJsFiles as $file) {
|
||||
@@ -82,6 +111,6 @@ class JsBuilder
|
||||
file_put_contents($targetFile, $allJs);
|
||||
|
||||
// 返回前端可访问路径
|
||||
return "/static/js/compiled/{$staticHash}.js";
|
||||
return "/static/js/compiled/{$targetName}";
|
||||
}
|
||||
}
|
||||
|
||||
18
code/app/model/ServerNodeModel.php
Normal file
18
code/app/model/ServerNodeModel.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\model;
|
||||
|
||||
/**
|
||||
* 前端服务器节点模型
|
||||
*
|
||||
* @mixin \think\Model
|
||||
*/
|
||||
class ServerNodeModel extends BaseModel
|
||||
{
|
||||
protected $name = 'server_node';
|
||||
protected $pk = 'sn_id';
|
||||
protected $createTime = 'created_at';
|
||||
protected $updateTime = 'updated_at';
|
||||
}
|
||||
Reference in New Issue
Block a user