no message
This commit is contained in:
@@ -137,17 +137,23 @@ cd D:\www\sport-era
|
|||||||
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net
|
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net
|
||||||
```
|
```
|
||||||
|
|
||||||
全量模式默认只打包以下目录:
|
全量模式默认以仓库根目录为源,只打包以下三个子目录:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
server/app
|
server/
|
||||||
server/config
|
uniapp/
|
||||||
server/extend
|
admin/
|
||||||
server/public/dongqiudi-crawler
|
|
||||||
server/route
|
|
||||||
```
|
```
|
||||||
|
|
||||||
默认会排除运行态或较大目录,例如 `.env`、`vendor`、`runtime`、`public/uploads`、`public/admin`、`public/mobile`、爬虫 `data/logs/venv`。如确实需要包含,可追加参数:
|
也就是说,远端 `RemoteDir` 下最终会形成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<RemoteDir>/server
|
||||||
|
<RemoteDir>/uniapp
|
||||||
|
<RemoteDir>/admin
|
||||||
|
```
|
||||||
|
|
||||||
|
默认会排除运行态或较大目录,例如 `server/.env`、`server/vendor`、`server/runtime`、`server/public/uploads`、`server/public/admin`、`server/public/mobile`、爬虫 `data/logs/venv`,以及 `uniapp/node_modules`、`uniapp/dist`、`admin/node_modules`、`admin/dist`。如确实需要包含,可追加参数:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
--include-env
|
--include-env
|
||||||
@@ -197,11 +203,11 @@ cd D:\www\sport-era
|
|||||||
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -AutoIncremental -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun
|
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -AutoIncremental -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun
|
||||||
```
|
```
|
||||||
|
|
||||||
脚本会在打包和上传前先检查 `server` 工作区;如果 `server` 内存在未提交、删除或未跟踪文件,会先自动提交这些变更,再继续计算增量范围。可以通过 `-AutoCommitMessage "提交说明"` 自定义这次自动提交的说明。若存在合并冲突,需要先手动解决。
|
脚本会在打包和上传前先检查默认打包范围(`server` + `uniapp` + `admin`);如果这些目录内存在未提交、删除或未跟踪文件,会先自动提交这些变更,再继续计算增量范围。可以通过 `-AutoCommitMessage "提交说明"` 自定义这次自动提交的说明。若存在合并冲突,需要先手动解决。
|
||||||
|
|
||||||
注意:自动增量只包含指定提交范围内已经提交到 Git 的差异,不会包含工作区未提交文件。需要指定任意起止提交时,继续使用 `-From <old_commit> -To <new_commit>`。
|
注意:自动增量只包含指定提交范围内已经提交到 Git 的差异,不会包含工作区未提交文件。需要指定任意起止提交时,继续使用 `-From <old_commit> -To <new_commit>`。
|
||||||
|
|
||||||
如果当前根目录 Git 只把 `server` 记录为 gitlink/submodule,且本机没有 `server/.git` 子仓库元数据,脚本无法拿到 `server` 内部的文件级差异;此时会自动降级为打包当前工作区默认的 5 个 server 目录,保证可以继续发布。
|
如果当前根目录 Git 只把 `server`、`uniapp` 或 `admin` 记录为 gitlink/submodule,脚本无法拿到对应目录内部的文件级差异;此时会把该目录从当前工作区按源码目录补进增量包,保证可以继续发布。
|
||||||
|
|
||||||
### 只演练不上传
|
### 只演练不上传
|
||||||
|
|
||||||
@@ -225,14 +231,34 @@ cd D:\www\sport-era
|
|||||||
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net -PostInstall "php think optimize:clear"
|
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net -PostInstall "php think optimize:clear"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 发布 uniapp 源码到服务器并在服务器构建
|
||||||
|
|
||||||
|
默认发布命令会把 `server/`、`uniapp/` 和 `admin/` 一起同步到远端根目录;如果需要在服务器端构建 `uniapp`,建议在远端根目录执行构建,再把 H5 产物写回同一套代码下的 `server/public/mobile`:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd D:\www\sport-era
|
||||||
|
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 `
|
||||||
|
-Sudo `
|
||||||
|
-RemoteDir /www/wwwroot/test-server.sbnews.net `
|
||||||
|
-UniappReleasePath ../server/public/mobile `
|
||||||
|
-PostInstall "cd uniapp && npm install && npm run build:h5"
|
||||||
|
```
|
||||||
|
|
||||||
|
说明:
|
||||||
|
|
||||||
|
- `-RemoteDir` 指向服务器上的项目根目录,解压后里面会同时有 `server/`、`uniapp/` 和 `admin/`。
|
||||||
|
- `-UniappReleasePath` 会通过环境变量 `UNIAPP_RELEASE_PATH` 传给 `uniapp/scripts/release.mjs`;这里传 `../server/public/mobile`,是因为构建命令会先 `cd uniapp`,再把 H5 产物回写到兄弟目录 `server/public/mobile`。
|
||||||
|
- 服务器需要预先安装 `node >= 18.19.0` 和 `npm`,否则 `npm install` / `npm run build:h5` 无法执行。
|
||||||
|
|
||||||
### 常见问题
|
### 常见问题
|
||||||
|
|
||||||
1. `ssh: Could not resolve hostname sbnews`:检查 Windows 的 `C:\Users\Administrator\.ssh\config` 是否存在 `Host sbnews`,或直接用 `-HostName <服务器IP>`。
|
1. `ssh: Could not resolve hostname sbnews`:检查 Windows 的 `C:\Users\Administrator\.ssh\config` 是否存在 `Host sbnews`,或直接用 `-HostName <服务器IP>`。
|
||||||
2. PowerShell 禁止执行脚本:使用示例中的 `-ExecutionPolicy Bypass -File`,或以管理员身份调整当前用户执行策略。
|
2. PowerShell 禁止执行脚本:使用示例中的 `-ExecutionPolicy Bypass -File`,或以管理员身份调整当前用户执行策略。
|
||||||
3. `tar: Cannot utime` 或 `Cannot change mode`:远端目录权限不足,请加 `-Sudo`。脚本会使用 `sudo tar` 覆盖解压,并默认跳过还原 owner/permission,减少权限冲突。
|
3. `tar: Cannot utime` 或 `Cannot change mode`:远端目录权限不足,请加 `-Sudo`。脚本会使用 `sudo tar` 覆盖解压,并默认跳过还原 owner/permission,减少权限冲突。
|
||||||
4. 增量发布提示 commit 无效:确认 commit id 属于当前根目录 Git 可识别的历史。
|
4. 增量发布提示 commit 无效:确认 commit id 属于当前根目录 Git 可识别的历史。
|
||||||
5. `server is tracked as a root gitlink`:脚本检测到根 Git 只记录了 `server` 指针,无法做文件级增量,会自动改为打包当前工作区默认 5 个 server 目录。
|
5. `root gitlink include paths will be copied from working tree`:脚本检测到默认发布范围里仍有 gitlink/submodule 目录,会把这些目录从当前工作区源码补进增量包。
|
||||||
6. 仍需使用 Bash 兼容版时,可继续运行 `bash ./scripts/deploy-server.sh ...`。
|
6. 仍需使用 Bash 兼容版时,可继续运行 `bash ./scripts/deploy-server.sh ...`。
|
||||||
|
7. 服务器运行 `uniapp` 报 `node: command not found` 或 `npm: command not found`:先在服务器安装 Node.js 18.19+ 与 npm,再执行 `-SourceDir uniapp` 的发布命令。
|
||||||
|
|
||||||
<a href="https://www.likeshop.cn"></a><br>
|
<a href="https://www.likeshop.cn"></a><br>
|
||||||
<a href="https://www.likeshop.cn"></a><br>
|
<a href="https://www.likeshop.cn"></a><br>
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
INSERT INTO `la_system_menu` (`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
|
||||||
|
SELECT COALESCE((SELECT `pid` FROM `la_system_menu` WHERE `perms` = 'community.communityComment/lists' LIMIT 1), 200), 'C', '评论账号', '', 0, 'community.commentAccount/lists', 'comment_account', 'community/account/index', '', '', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM `la_system_menu`
|
||||||
|
WHERE `perms` = 'community.commentAccount/lists'
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `la_system_role_menu` (`role_id`, `menu_id`)
|
||||||
|
SELECT 1, (SELECT id FROM `la_system_menu` WHERE `perms` = 'community.commentAccount/lists' LIMIT 1)
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM `la_system_role_menu` rm
|
||||||
|
JOIN `la_system_menu` m ON m.id = rm.menu_id
|
||||||
|
WHERE m.perms = 'community.commentAccount/lists'
|
||||||
|
);
|
||||||
+210
-50
@@ -1,8 +1,9 @@
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[string]$SourceDir = "server",
|
[string]$SourceDir = ".",
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$RemoteDir,
|
[string]$RemoteDir,
|
||||||
|
[string]$UniappReleasePath = "",
|
||||||
[string]$HostName = "sbnews",
|
[string]$HostName = "sbnews",
|
||||||
[string]$SshBin = "ssh.exe",
|
[string]$SshBin = "ssh.exe",
|
||||||
[switch]$AutoIncremental,
|
[switch]$AutoIncremental,
|
||||||
@@ -181,7 +182,9 @@ function Start-ProcessWithInputText {
|
|||||||
|
|
||||||
$inputFile = [System.IO.Path]::GetTempFileName()
|
$inputFile = [System.IO.Path]::GetTempFileName()
|
||||||
try {
|
try {
|
||||||
[System.IO.File]::WriteAllText($inputFile, $InputText, $Utf8NoBom)
|
# Remote shells like `bash -s` choke on Windows CRLF in stdin scripts.
|
||||||
|
$normalizedInputText = $InputText.Replace("`r`n", "`n").Replace("`r", "`n")
|
||||||
|
[System.IO.File]::WriteAllText($inputFile, $normalizedInputText, $Utf8NoBom)
|
||||||
Start-ProcessWithInputFile -FilePath $FilePath -Arguments $Arguments -InputFile $inputFile
|
Start-ProcessWithInputFile -FilePath $FilePath -Arguments $Arguments -InputFile $inputFile
|
||||||
} finally {
|
} finally {
|
||||||
Remove-Item -LiteralPath $inputFile -Force -ErrorAction SilentlyContinue
|
Remove-Item -LiteralPath $inputFile -Force -ErrorAction SilentlyContinue
|
||||||
@@ -195,13 +198,123 @@ function Remove-IfExists {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Test-IsRepoRootDeploy {
|
||||||
|
return ($SourceDir -eq "." -or [string]::IsNullOrWhiteSpace($SourceDir))
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-SourceLabel {
|
||||||
|
if (Test-IsRepoRootDeploy) {
|
||||||
|
return "repo-root"
|
||||||
|
}
|
||||||
|
return $SourceDir
|
||||||
|
}
|
||||||
|
|
||||||
function Get-DeployPathspec {
|
function Get-DeployPathspec {
|
||||||
|
if (Test-IsRepoRootDeploy) {
|
||||||
|
return @($FullIncludePaths)
|
||||||
|
}
|
||||||
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
|
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
|
||||||
return @(".")
|
return @(".")
|
||||||
}
|
}
|
||||||
return @($GitPathPrefix)
|
return @($GitPathPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-FullIncludePaths {
|
||||||
|
switch ($SourceDir.ToLowerInvariant()) {
|
||||||
|
"." {
|
||||||
|
return @("server", "uniapp", "admin", "docker")
|
||||||
|
}
|
||||||
|
"server" {
|
||||||
|
return @("app", "config", "extend", "public", "route")
|
||||||
|
}
|
||||||
|
"uniapp" {
|
||||||
|
return @(".")
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
return @(".")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-ArchiveExcludePatterns {
|
||||||
|
$patterns = @(
|
||||||
|
".git",
|
||||||
|
".idea",
|
||||||
|
".vscode",
|
||||||
|
".tmp",
|
||||||
|
".hbuilderx",
|
||||||
|
".gitignore",
|
||||||
|
"*.log",
|
||||||
|
"release-*.zip",
|
||||||
|
"*.zip",
|
||||||
|
"__pycache__",
|
||||||
|
"*.pyc",
|
||||||
|
"node_modules",
|
||||||
|
"dist"
|
||||||
|
)
|
||||||
|
|
||||||
|
switch ($SourceDir.ToLowerInvariant()) {
|
||||||
|
"." {
|
||||||
|
$patterns += @("uniapp/node_modules", "uniapp/dist", "admin/node_modules", "admin/dist")
|
||||||
|
if (-not $IncludeEnv) {
|
||||||
|
$patterns += "server/.env"
|
||||||
|
}
|
||||||
|
if (-not $IncludeVendor) {
|
||||||
|
$patterns += "server/vendor"
|
||||||
|
}
|
||||||
|
if (-not $IncludeRuntime) {
|
||||||
|
$patterns += "server/runtime"
|
||||||
|
}
|
||||||
|
if (-not $IncludeUploads) {
|
||||||
|
$patterns += "server/public/uploads"
|
||||||
|
}
|
||||||
|
if (-not $IncludePublicBuilds) {
|
||||||
|
$patterns += @("server/public/admin", "server/public/mobile")
|
||||||
|
}
|
||||||
|
if (-not $IncludeCrawlerData) {
|
||||||
|
$patterns += @(
|
||||||
|
"server/public/dongqiudi-crawler/data",
|
||||||
|
"server/public/dongqiudi-crawler/logs",
|
||||||
|
"server/public/dongqiudi-crawler/venv",
|
||||||
|
"server/public/dongqiudi-crawler/__pycache__"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"server" {
|
||||||
|
if (-not $IncludeEnv) {
|
||||||
|
$patterns += ".env"
|
||||||
|
}
|
||||||
|
if (-not $IncludeVendor) {
|
||||||
|
$patterns += "vendor"
|
||||||
|
}
|
||||||
|
if (-not $IncludeRuntime) {
|
||||||
|
$patterns += "runtime"
|
||||||
|
}
|
||||||
|
if (-not $IncludeUploads) {
|
||||||
|
$patterns += "public/uploads"
|
||||||
|
}
|
||||||
|
if (-not $IncludePublicBuilds) {
|
||||||
|
$patterns += @("public/admin", "public/mobile")
|
||||||
|
}
|
||||||
|
if (-not $IncludeCrawlerData) {
|
||||||
|
$patterns += @(
|
||||||
|
"public/dongqiudi-crawler/data",
|
||||||
|
"public/dongqiudi-crawler/logs",
|
||||||
|
"public/dongqiudi-crawler/venv",
|
||||||
|
"public/dongqiudi-crawler/__pycache__"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"uniapp" {
|
||||||
|
if (-not $IncludeEnv) {
|
||||||
|
$patterns += ".env"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return @($patterns)
|
||||||
|
}
|
||||||
|
|
||||||
function Commit-SourceChangesIfNeeded {
|
function Commit-SourceChangesIfNeeded {
|
||||||
param(
|
param(
|
||||||
[string]$Repository,
|
[string]$Repository,
|
||||||
@@ -220,12 +333,12 @@ function Commit-SourceChangesIfNeeded {
|
|||||||
|
|
||||||
$unmerged = @($statusLines | Where-Object { $_ -match "^(DD|AU|UD|UA|DU|AA|UU)" })
|
$unmerged = @($statusLines | Where-Object { $_ -match "^(DD|AU|UD|UA|DU|AA|UU)" })
|
||||||
if ($unmerged.Count -gt 0) {
|
if ($unmerged.Count -gt 0) {
|
||||||
Write-DeployLog "unmerged changes detected under ${SourceDir}:"
|
Write-DeployLog "unmerged changes detected under $(Get-SourceLabel):"
|
||||||
$unmerged | Select-Object -First 20 | ForEach-Object { Write-Host " $_" }
|
$unmerged | Select-Object -First 20 | ForEach-Object { Write-Host " $_" }
|
||||||
Fail "resolve merge conflicts under $SourceDir before deploy"
|
Fail "resolve merge conflicts under $(Get-SourceLabel) before deploy"
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-DeployLog "uncommitted changes detected under $SourceDir; auto committing before deploy:"
|
Write-DeployLog "uncommitted changes detected under $(Get-SourceLabel); auto committing before deploy:"
|
||||||
$maxDisplay = 80
|
$maxDisplay = 80
|
||||||
$statusLines | Select-Object -First $maxDisplay | ForEach-Object { Write-Host " $_" }
|
$statusLines | Select-Object -First $maxDisplay | ForEach-Object { Write-Host " $_" }
|
||||||
if ($statusLines.Count -gt $maxDisplay) {
|
if ($statusLines.Count -gt $maxDisplay) {
|
||||||
@@ -234,9 +347,18 @@ function Commit-SourceChangesIfNeeded {
|
|||||||
|
|
||||||
Invoke-Native "git" (@("-C", $Repository, "add", "-A", "--") + $Pathspec)
|
Invoke-Native "git" (@("-C", $Repository, "add", "-A", "--") + $Pathspec)
|
||||||
|
|
||||||
|
& git -C $Repository diff --cached --quiet -- $Pathspec
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
Write-DeployLog "no committable root changes detected after git add; continue with current working tree payload"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ($LASTEXITCODE -ne 1) {
|
||||||
|
Fail "git diff --cached failed"
|
||||||
|
}
|
||||||
|
|
||||||
$commitMessage = $AutoCommitMessage
|
$commitMessage = $AutoCommitMessage
|
||||||
if ([string]::IsNullOrWhiteSpace($commitMessage)) {
|
if ([string]::IsNullOrWhiteSpace($commitMessage)) {
|
||||||
$commitMessage = "deploy: auto commit $SourceDir changes $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
$commitMessage = "deploy: auto commit $(Get-SourceLabel) changes $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||||||
}
|
}
|
||||||
|
|
||||||
Invoke-Native "git" (@("-C", $Repository, "commit", "-m", $commitMessage, "--") + $Pathspec)
|
Invoke-Native "git" (@("-C", $Repository, "commit", "-m", $commitMessage, "--") + $Pathspec)
|
||||||
@@ -244,55 +366,42 @@ function Commit-SourceChangesIfNeeded {
|
|||||||
Write-DeployLog "auto commit created: $newCommit"
|
Write-DeployLog "auto commit created: $newCommit"
|
||||||
}
|
}
|
||||||
|
|
||||||
function Copy-FullPayload {
|
function Copy-WorkingTreePayloadPaths {
|
||||||
Write-DeployLog "building full payload from current working tree: $SourceDir"
|
param(
|
||||||
Write-DeployLog "full include paths: $($FullIncludePaths -join ' ')"
|
[string[]]$IncludePaths,
|
||||||
|
[string]$Reason
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($IncludePaths.Count -eq 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-DeployLog $Reason
|
||||||
|
Write-DeployLog "working tree include paths: $($IncludePaths -join ' ')"
|
||||||
|
|
||||||
$payloadTar = Join-Path $WorkDir "payload-copy.tar"
|
$payloadTar = Join-Path $WorkDir "payload-copy.tar"
|
||||||
$tarArgs = @(
|
$tarArgs = @(
|
||||||
"-cf", $payloadTar,
|
"-cf", $payloadTar,
|
||||||
"-C", $SourceAbs,
|
"-C", $SourceAbs
|
||||||
"--exclude=.git",
|
|
||||||
"--exclude=.idea",
|
|
||||||
"--exclude=.vscode",
|
|
||||||
"--exclude=.tmp",
|
|
||||||
"--exclude=.gitignore",
|
|
||||||
"--exclude=*.log",
|
|
||||||
"--exclude=release-*.zip",
|
|
||||||
"--exclude=*.zip",
|
|
||||||
"--exclude=__pycache__",
|
|
||||||
"--exclude=*.pyc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (-not $IncludeEnv) {
|
foreach ($pattern in (Get-ArchiveExcludePatterns)) {
|
||||||
$tarArgs += "--exclude=.env"
|
if (-not [string]::IsNullOrWhiteSpace($pattern)) {
|
||||||
|
$tarArgs += "--exclude=$pattern"
|
||||||
}
|
}
|
||||||
if (-not $IncludeVendor) {
|
|
||||||
$tarArgs += "--exclude=vendor"
|
|
||||||
}
|
|
||||||
if (-not $IncludeRuntime) {
|
|
||||||
$tarArgs += "--exclude=runtime"
|
|
||||||
}
|
|
||||||
if (-not $IncludeUploads) {
|
|
||||||
$tarArgs += "--exclude=public/uploads"
|
|
||||||
}
|
|
||||||
if (-not $IncludePublicBuilds) {
|
|
||||||
$tarArgs += @("--exclude=public/admin", "--exclude=public/mobile")
|
|
||||||
}
|
|
||||||
if (-not $IncludeCrawlerData) {
|
|
||||||
$tarArgs += @(
|
|
||||||
"--exclude=public/dongqiudi-crawler/data",
|
|
||||||
"--exclude=public/dongqiudi-crawler/logs",
|
|
||||||
"--exclude=public/dongqiudi-crawler/venv",
|
|
||||||
"--exclude=public/dongqiudi-crawler/__pycache__"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$tarArgs += $FullIncludePaths
|
$tarArgs += $IncludePaths
|
||||||
Invoke-Native "tar" $tarArgs
|
Invoke-Native "tar" $tarArgs
|
||||||
Invoke-Native "tar" @("-xf", $payloadTar, "-C", $PayloadDir)
|
Invoke-Native "tar" @("-xf", $payloadTar, "-C", $PayloadDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Copy-FullPayload {
|
||||||
|
Copy-WorkingTreePayloadPaths `
|
||||||
|
-IncludePaths $FullIncludePaths `
|
||||||
|
-Reason "building full payload from current working tree: $(Get-SourceLabel)"
|
||||||
|
}
|
||||||
|
|
||||||
function Strip-SourcePrefix {
|
function Strip-SourcePrefix {
|
||||||
param([string]$Path)
|
param([string]$Path)
|
||||||
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
|
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
|
||||||
@@ -308,6 +417,9 @@ function Strip-SourcePrefix {
|
|||||||
function Test-DeployIncludedPath {
|
function Test-DeployIncludedPath {
|
||||||
param([string]$RelativePath)
|
param([string]$RelativePath)
|
||||||
foreach ($include in $FullIncludePaths) {
|
foreach ($include in $FullIncludePaths) {
|
||||||
|
if ($include -eq ".") {
|
||||||
|
return $true
|
||||||
|
}
|
||||||
if ($RelativePath -eq $include -or $RelativePath.StartsWith("$include/")) {
|
if ($RelativePath -eq $include -or $RelativePath.StartsWith("$include/")) {
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
@@ -315,6 +427,25 @@ function Test-DeployIncludedPath {
|
|||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-RootGitLinkIncludePaths {
|
||||||
|
if (-not (Test-IsRepoRootDeploy)) {
|
||||||
|
return @()
|
||||||
|
}
|
||||||
|
|
||||||
|
$lsFiles = @(& git -C $RepoRoot ls-files -s -- $FullIncludePaths)
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Fail "git ls-files failed"
|
||||||
|
}
|
||||||
|
|
||||||
|
return @(
|
||||||
|
$lsFiles |
|
||||||
|
Where-Object { $_ -match "^160000\s+\S+\s+\d+\t(.+)$" } |
|
||||||
|
ForEach-Object { $Matches[1] } |
|
||||||
|
Where-Object { Test-DeployIncludedPath $_ } |
|
||||||
|
Sort-Object -Unique
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function Test-UnderSourceDir {
|
function Test-UnderSourceDir {
|
||||||
param([string]$GitPath)
|
param([string]$GitPath)
|
||||||
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
|
if ([string]::IsNullOrEmpty($GitPathPrefix)) {
|
||||||
@@ -401,6 +532,11 @@ function Build-IncrementalPayload {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$rootGitLinkPayloadPaths = @()
|
||||||
|
if (Test-IsRepoRootDeploy) {
|
||||||
|
$rootGitLinkPayloadPaths = @($RootGitLinkIncludePaths)
|
||||||
|
}
|
||||||
|
|
||||||
$diffArgs = @("-C", $GitCwd, "diff", "--name-status", "--find-renames", $FromCommit, $ToCommit)
|
$diffArgs = @("-C", $GitCwd, "diff", "--name-status", "--find-renames", $FromCommit, $ToCommit)
|
||||||
if (-not [string]::IsNullOrEmpty($GitPathPrefix)) {
|
if (-not [string]::IsNullOrEmpty($GitPathPrefix)) {
|
||||||
$diffArgs += @("--", $GitPathPrefix)
|
$diffArgs += @("--", $GitPathPrefix)
|
||||||
@@ -448,11 +584,15 @@ function Build-IncrementalPayload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$script:ChangedDisplayPaths = @($script:ChangedDisplayPaths | Sort-Object -Unique)
|
|
||||||
$script:DeletedDisplayPaths = @($script:DeletedDisplayPaths | Sort-Object -Unique)
|
$script:DeletedDisplayPaths = @($script:DeletedDisplayPaths | Sort-Object -Unique)
|
||||||
$changedGitPaths = @($changedGitPaths | Sort-Object -Unique)
|
$changedGitPaths = @($changedGitPaths | Sort-Object -Unique)
|
||||||
|
|
||||||
if ($changedGitPaths.Count -eq 0 -and $script:DeletedDisplayPaths.Count -eq 0) {
|
if ($rootGitLinkPayloadPaths.Count -gt 0) {
|
||||||
|
$script:ChangedDisplayPaths += @($rootGitLinkPayloadPaths | ForEach-Object { "$_/" })
|
||||||
|
}
|
||||||
|
$script:ChangedDisplayPaths = @($script:ChangedDisplayPaths | Sort-Object -Unique)
|
||||||
|
|
||||||
|
if ($changedGitPaths.Count -eq 0 -and $script:DeletedDisplayPaths.Count -eq 0 -and $rootGitLinkPayloadPaths.Count -eq 0) {
|
||||||
Write-DeployLog "no changed files detected between $FromCommit and $ToCommit under $SourceDir"
|
Write-DeployLog "no changed files detected between $FromCommit and $ToCommit under $SourceDir"
|
||||||
$script:NoChanges = $true
|
$script:NoChanges = $true
|
||||||
return
|
return
|
||||||
@@ -477,11 +617,18 @@ function Build-IncrementalPayload {
|
|||||||
Get-ChildItem -LiteralPath $extractSource -Force | Copy-Item -Destination $PayloadDir -Recurse -Force
|
Get-ChildItem -LiteralPath $extractSource -Force | Copy-Item -Destination $PayloadDir -Recurse -Force
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($rootGitLinkPayloadPaths.Count -gt 0) {
|
||||||
|
Copy-WorkingTreePayloadPaths `
|
||||||
|
-IncludePaths $rootGitLinkPayloadPaths `
|
||||||
|
-Reason "building working tree payload for root gitlink include paths"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$SourceDir = Normalize-DeployDir $SourceDir
|
$SourceDir = Normalize-DeployDir $SourceDir
|
||||||
$RemoteDir = Normalize-DeployDir $RemoteDir
|
$RemoteDir = Normalize-DeployDir $RemoteDir
|
||||||
$RemoteTmp = Normalize-DeployDir $RemoteTmp
|
$RemoteTmp = Normalize-DeployDir $RemoteTmp
|
||||||
|
$SourceLabel = Get-SourceLabel
|
||||||
|
|
||||||
if ($AutoIncremental -and ($From -or $To)) {
|
if ($AutoIncremental -and ($From -or $To)) {
|
||||||
Fail "-AutoIncremental cannot be used with -From/-To"
|
Fail "-AutoIncremental cannot be used with -From/-To"
|
||||||
@@ -519,7 +666,7 @@ if (-not (Test-Path -LiteralPath $SourceAbs -PathType Container)) {
|
|||||||
Fail "source directory not found: $SourceDir"
|
Fail "source directory not found: $SourceDir"
|
||||||
}
|
}
|
||||||
|
|
||||||
$FullIncludePaths = @("app", "config", "extend", "public", "route")
|
$FullIncludePaths = @(Get-FullIncludePaths)
|
||||||
$GitCwd = $RepoRoot
|
$GitCwd = $RepoRoot
|
||||||
$GitPathPrefix = $SourceDir
|
$GitPathPrefix = $SourceDir
|
||||||
$SourceIsGitRepo = $false
|
$SourceIsGitRepo = $false
|
||||||
@@ -543,6 +690,10 @@ if (-not $SourceIsGitRepo -and ($lsFiles | Where-Object { $_ -match "^160000\s"
|
|||||||
}
|
}
|
||||||
|
|
||||||
$DeployPathspec = @(Get-DeployPathspec)
|
$DeployPathspec = @(Get-DeployPathspec)
|
||||||
|
$RootGitLinkIncludePaths = @(Get-RootGitLinkIncludePaths)
|
||||||
|
if ($RootGitLinkIncludePaths.Count -gt 0) {
|
||||||
|
Write-DeployLog "root gitlink include paths will be copied from working tree: $($RootGitLinkIncludePaths -join ' ')"
|
||||||
|
}
|
||||||
Commit-SourceChangesIfNeeded -Repository $GitCwd -Pathspec $DeployPathspec
|
Commit-SourceChangesIfNeeded -Repository $GitCwd -Pathspec $DeployPathspec
|
||||||
|
|
||||||
if ($Mode -eq "incremental") {
|
if ($Mode -eq "incremental") {
|
||||||
@@ -564,7 +715,7 @@ $WorkDir = Join-Path $TempRoot ("deploy-server-" + [System.Guid]::NewGuid().ToSt
|
|||||||
$PackageRoot = Join-Path $WorkDir "package"
|
$PackageRoot = Join-Path $WorkDir "package"
|
||||||
$PayloadDir = Join-Path $PackageRoot "payload"
|
$PayloadDir = Join-Path $PackageRoot "payload"
|
||||||
$ExtractDir = Join-Path $WorkDir "extract"
|
$ExtractDir = Join-Path $WorkDir "extract"
|
||||||
$ArchivePath = Join-Path $WorkDir ("{0}-{1}.tar.gz" -f ($SourceDir -replace "[\\/]", "-"), $Mode)
|
$ArchivePath = Join-Path $WorkDir ("{0}-{1}.tar.gz" -f $SourceLabel, $Mode)
|
||||||
$DeletedPathsFile = Join-Path $PackageRoot ".deleted-paths.txt"
|
$DeletedPathsFile = Join-Path $PackageRoot ".deleted-paths.txt"
|
||||||
$DeployInfoFile = Join-Path $PackageRoot ".deploy-info.txt"
|
$DeployInfoFile = Join-Path $PackageRoot ".deploy-info.txt"
|
||||||
$script:ChangedDisplayPaths = @()
|
$script:ChangedDisplayPaths = @()
|
||||||
@@ -588,9 +739,10 @@ try {
|
|||||||
|
|
||||||
$deployInfo = @(
|
$deployInfo = @(
|
||||||
"mode=$Mode",
|
"mode=$Mode",
|
||||||
"source_dir=$SourceDir",
|
"source_dir=$SourceLabel",
|
||||||
"host=$HostName",
|
"host=$HostName",
|
||||||
"remote_dir=$RemoteDir",
|
"remote_dir=$RemoteDir",
|
||||||
|
"uniapp_release_path=$UniappReleasePath",
|
||||||
"built_at=$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
"built_at=$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||||||
)
|
)
|
||||||
if ($Mode -eq "incremental") {
|
if ($Mode -eq "incremental") {
|
||||||
@@ -619,8 +771,8 @@ try {
|
|||||||
|
|
||||||
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||||||
$pidValue = $PID
|
$pidValue = $PID
|
||||||
$remoteWorkDir = "$RemoteTmp/$($SourceDir -replace '[\\/]', '-')-deploy-$timestamp-$pidValue"
|
$remoteWorkDir = "$RemoteTmp/$SourceLabel-deploy-$timestamp-$pidValue"
|
||||||
$remoteArchive = "$RemoteTmp/$($SourceDir -replace '[\\/]', '-')-$Mode-$timestamp.tar.gz"
|
$remoteArchive = "$RemoteTmp/$SourceLabel-$Mode-$timestamp.tar.gz"
|
||||||
|
|
||||||
$remoteTmpQ = ConvertTo-RemoteSingleQuoted $RemoteTmp
|
$remoteTmpQ = ConvertTo-RemoteSingleQuoted $RemoteTmp
|
||||||
$remoteArchiveQ = ConvertTo-RemoteSingleQuoted $remoteArchive
|
$remoteArchiveQ = ConvertTo-RemoteSingleQuoted $remoteArchive
|
||||||
@@ -640,6 +792,7 @@ try {
|
|||||||
"REMOTE_DIR=$(ConvertTo-RemoteSingleQuoted $RemoteDir)",
|
"REMOTE_DIR=$(ConvertTo-RemoteSingleQuoted $RemoteDir)",
|
||||||
"REMOTE_ARCHIVE=$(ConvertTo-RemoteSingleQuoted $remoteArchive)",
|
"REMOTE_ARCHIVE=$(ConvertTo-RemoteSingleQuoted $remoteArchive)",
|
||||||
"REMOTE_WORK_DIR=$(ConvertTo-RemoteSingleQuoted $remoteWorkDir)",
|
"REMOTE_WORK_DIR=$(ConvertTo-RemoteSingleQuoted $remoteWorkDir)",
|
||||||
|
"UNIAPP_RELEASE_PATH=$(ConvertTo-RemoteSingleQuoted $UniappReleasePath)",
|
||||||
"KEEP_REMOTE_TEMP='$keepRemoteTempValue'",
|
"KEEP_REMOTE_TEMP='$keepRemoteTempValue'",
|
||||||
"POST_INSTALL_B64='$postInstallB64'",
|
"POST_INSTALL_B64='$postInstallB64'",
|
||||||
"USE_SUDO='$useSudoValue'",
|
"USE_SUDO='$useSudoValue'",
|
||||||
@@ -762,8 +915,15 @@ if [[ -n "${POST_INSTALL_B64:-}" ]]; then
|
|||||||
remote_log "run post-install command"
|
remote_log "run post-install command"
|
||||||
POST_INSTALL_CMD="$(printf '%s' "$POST_INSTALL_B64" | base64 -d)"
|
POST_INSTALL_CMD="$(printf '%s' "$POST_INSTALL_B64" | base64 -d)"
|
||||||
cd "$REMOTE_DIR"
|
cd "$REMOTE_DIR"
|
||||||
|
if [[ -n "${UNIAPP_RELEASE_PATH:-}" ]]; then
|
||||||
|
export UNIAPP_RELEASE_PATH
|
||||||
|
fi
|
||||||
if [[ "${USE_SUDO:-0}" == "1" ]]; then
|
if [[ "${USE_SUDO:-0}" == "1" ]]; then
|
||||||
|
if [[ -n "${UNIAPP_RELEASE_PATH:-}" ]]; then
|
||||||
|
sudo env UNIAPP_RELEASE_PATH="$UNIAPP_RELEASE_PATH" bash -lc "$POST_INSTALL_CMD"
|
||||||
|
else
|
||||||
sudo bash -lc "$POST_INSTALL_CMD"
|
sudo bash -lc "$POST_INSTALL_CMD"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
bash -lc "$POST_INSTALL_CMD"
|
bash -lc "$POST_INSTALL_CMD"
|
||||||
fi
|
fi
|
||||||
@@ -782,7 +942,7 @@ remote_log "remote install finished"
|
|||||||
|
|
||||||
Write-DeployLog "deploy finished"
|
Write-DeployLog "deploy finished"
|
||||||
Write-DeployLog "mode: $Mode"
|
Write-DeployLog "mode: $Mode"
|
||||||
Write-DeployLog "source: $SourceDir"
|
Write-DeployLog "source: $SourceLabel"
|
||||||
Write-DeployLog "remote: ${HostName}:$RemoteDir"
|
Write-DeployLog "remote: ${HostName}:$RemoteDir"
|
||||||
} finally {
|
} finally {
|
||||||
if ($WorkDir -and (Test-Path -LiteralPath $WorkDir)) {
|
if ($WorkDir -and (Test-Path -LiteralPath $WorkDir)) {
|
||||||
|
|||||||
@@ -13,6 +13,81 @@
|
|||||||
|
|
||||||
## 一、已完成事项
|
## 一、已完成事项
|
||||||
|
|
||||||
|
### 68. 默认部署切换为根目录同时上传 server、uniapp 与 admin
|
||||||
|
|
||||||
|
- 状态:已完成 - 时间:2026-06-12
|
||||||
|
|
||||||
|
完成内容:
|
||||||
|
- `scripts/deploy-server.ps1` 默认 `SourceDir` 改为仓库根目录 `.`,不再先发 `server` 再补发前端目录,而是直接以根目录为源打一个包。
|
||||||
|
- 根目录默认只包含 `server/`、`uniapp/` 与 `admin/` 三个子目录,因此远端 `RemoteDir` 下会直接形成三套源码目录,方便后续按 `server/public`、`uniapp`、`admin` 分别配置 Nginx 和构建流程。
|
||||||
|
- 根目录模式下,排除规则已同步切到子目录路径:会继续默认排除 `server/.env`、`server/vendor`、`server/runtime`、`server/public/uploads`、`server/public/admin`、`server/public/mobile`、crawler 大文件目录,以及 `uniapp/node_modules`、`uniapp/dist`、`admin/node_modules`、`admin/dist`。
|
||||||
|
- 默认增量发布也切到根目录范围,`-AutoIncremental` / `-AutoIncrementalCommits` / `-From` / `-To` 会同时跟踪 `server`、`uniapp` 与 `admin` 的 Git 变更和删除文件。
|
||||||
|
- 若根仓库里某个默认目录仍是 gitlink/submodule 记录,脚本会把该目录从当前工作区按源码目录补进增量包,避免 `admin` 这类目录在转换期间漏传。
|
||||||
|
- `README.md` 已同步更新根目录发布、远端目录结构以及在远端根目录内执行 `cd uniapp && npm install && npm run build:h5` 的示例。
|
||||||
|
|
||||||
|
涉及模块:
|
||||||
|
- `scripts/deploy-server.ps1`
|
||||||
|
- `README.md`
|
||||||
|
|
||||||
|
验证记录:
|
||||||
|
- 已在临时最小 Git 仓库执行默认 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -DryRun -RemoteDir /tmp/test`,修改前日志只出现 `server` 打包,确认红灯。
|
||||||
|
- 修改后已在临时最小 Git 仓库执行默认 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -DryRun -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /tmp/test`,日志已同时出现 `server/app/ok.txt`、`uniapp/src/App.vue` 与 `admin/src/main.ts` 的增量变更,确认根目录模式能同时覆盖三套源码。
|
||||||
|
- 已补跑 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -SourceDir server -DryRun -RemoteDir /tmp/test`,确认显式单独发布 `server` 的老用法仍可继续使用。
|
||||||
|
- 已在真实仓库执行 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -DryRun -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /www/wwwroot/test-server.sbnews.net`,日志出现 `root gitlink include paths will be copied from working tree: admin` 与 `+ admin/`,确认 `admin` 仍是 gitlink 记录时也会被补进增量包。
|
||||||
|
- 已在真实仓库执行默认全量 DryRun,日志显示 `working tree include paths: server uniapp admin`,确认全量包也会同时包含三套源码。
|
||||||
|
|
||||||
|
### 67. 部署脚本支持发布 uniapp 源码到服务器
|
||||||
|
|
||||||
|
- 状态:已完成 - 时间:2026-06-12
|
||||||
|
|
||||||
|
完成内容:
|
||||||
|
- `scripts/deploy-server.ps1` 现在支持 `-SourceDir uniapp`,可将 `uniapp` 源码按独立目录发布到服务器,不再只支持 `server` 后端目录。
|
||||||
|
- `uniapp` 全量打包默认改为包含整个源码目录,并排除 `node_modules`、`dist`、`.hbuilderx` 等不应上传的本地构建/IDE 目录;增量发布也可正确识别 `uniapp` 目录下的 Git 变更与删除文件。
|
||||||
|
- 部署脚本新增 `-UniappReleasePath`,会在远端执行 `-PostInstall` 时通过环境变量 `UNIAPP_RELEASE_PATH` 传给 `uniapp/scripts/release.mjs`,让服务器构建 `npm run build:h5` 后可把 H5 产物直接写入指定站点的 `public/mobile`。
|
||||||
|
- `uniapp/scripts/release.mjs` 新增 `UNIAPP_RELEASE_PATH` 覆盖能力,本地构建仍默认输出到 `../server/public/mobile`,服务端构建时则可改写到测试站真实目录。
|
||||||
|
- `README.md` 已补充“发布 uniapp 源码到服务器并在服务器构建”的标准命令示例与 Node.js 版本要求。
|
||||||
|
|
||||||
|
涉及模块:
|
||||||
|
- `scripts/deploy-server.ps1`
|
||||||
|
- `uniapp/scripts/release.mjs`
|
||||||
|
- `README.md`
|
||||||
|
|
||||||
|
验证记录:
|
||||||
|
- 已先执行 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -SourceDir uniapp -RemoteDir /tmp/sport-era-uniapp -DryRun`,修改前失败,确认原脚本不支持 `uniapp` 目录打包。
|
||||||
|
- 修改后已执行 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -SourceDir uniapp -RemoteDir /tmp/sport-era-uniapp -DryRun`,全量打包演练通过。
|
||||||
|
- 已执行 `git diff --check -- scripts/deploy-server.ps1 uniapp/scripts/release.mjs README.md 业务进度管理.md`,未发现空白错误。
|
||||||
|
- 已通过 SSH 检查测试服当前缺少 `node` / `npm`,因此本次仅验证到“源码可发布 + 远端构建命令已就绪”,尚未在测试服实际执行 `npm install` / `npm run build:h5`。
|
||||||
|
|
||||||
|
### 66. 管理端评论账号列表与统一评论列表
|
||||||
|
|
||||||
|
- 状态:已完成 - 时间:2026-06-12
|
||||||
|
|
||||||
|
完成内容:
|
||||||
|
- 管理端新增“评论账号”后台契约与页面,后端 `community.commentAccount/lists` 仅筛选 `ai_comment_*` 虚拟评论账号,返回账号、昵称、人设标签、禁用状态、资讯评论数、社区评论数和总评论数。
|
||||||
|
- 现有“社区评论管理”升级为统一评论列表,不再只看社区帖子评论;现在同一页面可同时查看资讯评论与社区评论,并按评论类型、虚拟/真实评论、状态、目标 ID、关键词筛选。
|
||||||
|
- 统一评论列表后端通过合并 `la_article_comment` 与 `la_community_comment` 输出统一字段:`comment_type`、`source_type_desc`、`target_id`、`target_title`、`target_summary`、`target_owner_nickname`、`account`、`is_virtual`、`user_type_desc`、`status` 等。
|
||||||
|
- 评论审核与删除逻辑已扩展到两类评论:资讯评论操作 `la_article_comment.is_show` 与 `la_article.comment_count`,社区评论操作 `la_community_comment.status` 与 `la_community_post.comment_count`。
|
||||||
|
- 新增菜单 SQL `docs/sql/insert_menu_comment_account.sql`,用于把“评论账号”挂到现有“社区管理”菜单下;统一评论列表继续复用原有 `community.communityComment/lists` 菜单入口。
|
||||||
|
|
||||||
|
涉及模块:
|
||||||
|
- `server/app/adminapi/controller/community/CommunityCommentController.php`
|
||||||
|
- `server/app/adminapi/lists/community/CommunityCommentLists.php`
|
||||||
|
- `server/app/adminapi/logic/community/CommunityCommentLogic.php`
|
||||||
|
- `server/app/adminapi/validate/community/CommunityCommentValidate.php`
|
||||||
|
- `server/app/adminapi/controller/community/CommentAccountController.php`
|
||||||
|
- `server/app/adminapi/lists/community/CommentAccountLists.php`
|
||||||
|
- `admin/src/api/community.ts`
|
||||||
|
- `admin/src/views/community/comment/index.vue`
|
||||||
|
- `admin/src/views/community/account/index.vue`
|
||||||
|
- `docs/sql/insert_menu_comment_account.sql`
|
||||||
|
- `qa/backend/test_comment_admin_static.php`
|
||||||
|
|
||||||
|
验证记录:
|
||||||
|
- 已先执行 `php qa/backend/test_comment_admin_static.php`,新增文件前失败,提示缺少 `admin/src/views/community/account/index.vue`。
|
||||||
|
- 修改后已执行 `php qa/backend/test_comment_admin_static.php`,静态检查通过。
|
||||||
|
- 已执行 `php -l` 检查 `CommunityCommentController.php`、`CommunityCommentLogic.php`、`CommunityCommentLists.php`、`CommunityCommentValidate.php`、`CommentAccountController.php`、`CommentAccountLists.php`,语法检查通过。
|
||||||
|
- 已在 `admin` 目录执行 `npm run build`,构建通过并刷新 `server/public/admin` 产物。
|
||||||
|
|
||||||
### 65. Docker AI评论调度接入帖子与资讯
|
### 65. Docker AI评论调度接入帖子与资讯
|
||||||
|
|
||||||
- 状态:已完成 - 时间:2026-06-12
|
- 状态:已完成 - 时间:2026-06-12
|
||||||
@@ -613,6 +688,7 @@
|
|||||||
- 排查 `scripts/deploy-server.ps1` 全量部署测试服时报 `tar: Cannot change mode ... Operation not permitted`,确认 SSH 用户 `ubuntu` 仅通过 `www` 组拥有目标目录写权限,并不是目录 owner,GNU tar 覆盖解包目录项时会尝试 `chmod` 已有目录导致失败。
|
- 排查 `scripts/deploy-server.ps1` 全量部署测试服时报 `tar: Cannot change mode ... Operation not permitted`,确认 SSH 用户 `ubuntu` 仅通过 `www` 组拥有目标目录写权限,并不是目录 owner,GNU tar 覆盖解包目录项时会尝试 `chmod` 已有目录导致失败。
|
||||||
- 远端安装 payload 改为优先使用 `rsync -r --links --no-perms --no-owner --no-group`,不保留 owner/group/perms;远端无 rsync 时回退为 `find + mkdir/cp/ln` 逐文件复制,避免对已有目录执行 chmod。
|
- 远端安装 payload 改为优先使用 `rsync -r --links --no-perms --no-owner --no-group`,不保留 owner/group/perms;远端无 rsync 时回退为 `find + mkdir/cp/ln` 逐文件复制,避免对已有目录执行 chmod。
|
||||||
- 修复通过 `ssh bash -s` 下发远端 Bash 文本时可能写入 UTF-8 BOM 的问题,改为用 `UTF8 No BOM` 字节流写入 stdin,避免 `set -euo pipefail` 失效导致部署“假成功”。
|
- 修复通过 `ssh bash -s` 下发远端 Bash 文本时可能写入 UTF-8 BOM 的问题,改为用 `UTF8 No BOM` 字节流写入 stdin,避免 `set -euo pipefail` 失效导致部署“假成功”。
|
||||||
|
- 2026-06-12 再次排查测试服增量部署时报 `invalid option namepefail`,根因是远端 Bash 脚本 stdin 保留了 Windows `CRLF`,导致 `set -euo pipefail` 被识别成 `pipefail\r` 非法选项;现已在写入 stdin 前统一转换为 `LF`。
|
||||||
- 保留当前全量部署包含整个 `public` 目录的变更,解决包含更多已有目录后触发的部署失败。
|
- 保留当前全量部署包含整个 `public` 目录的变更,解决包含更多已有目录后触发的部署失败。
|
||||||
|
|
||||||
涉及模块:
|
涉及模块:
|
||||||
|
|||||||
Reference in New Issue
Block a user