diff --git a/deploy/README.md b/deploy/README.md index af5865c..dca9d3e 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1,6 +1,6 @@ # 一键部署脚本 -在本机运行一条命令,自动完成「打包源码 → 上传服务器 → 构建 → 重启进程」。 +在本机运行一条命令,自动完成「本地构建(可选)→ 打包 → 上传服务器 → 重启进程」。 服务器上**不需要安装任何东西**,它复用的就是你已经能用的 SSH。 @@ -82,7 +82,7 @@ type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh root@你的服务器 "mkdir -p ~ === yelaymaths_api (server API) === [1/5] Building locally: pnpm prisma:generate && pnpm build [2/5] Packing yelaymaths_api - 100.8 KB (src, prisma, tools, package.json, ...) + 160 KB (dist, prisma, package.json, pnpm-lock.yaml, pnpm-workspace.yaml) [3/5] Uploading to /www/wwwroot/yelaymaths/yelaymaths_api/api [4/5] Running on server __DEPLOY_DONE__ @@ -121,10 +121,11 @@ All done in 12.0s 脚本用的是**白名单**,只有列在 `DeployPaths` 里的路径会被打包。所以这些东西**结构上不可能**被传上去: - `.env` / `.env.local`(服务器上的配置不会被覆盖) -- `node_modules/`(依赖在服务器上装) -- `dist/`、`.next/`(构建产物在服务器上生成) +- `node_modules/` +- 白名单之外的源码目录 -服务端实际约 100 KB,管理端约 25 KB。 +Windows 版配置(`deploy.config.ps1`)已经在**本机构建、只传产物**:服务端传 `dist` + `prisma`(约 160 KB), +管理端传 `.next` + `next.config.ts`(约 540 KB,73 MB 的构建缓存已排除),服务器不再执行编译,部署完自动重启并探活。 --- diff --git a/deploy/deploy.config.example.ps1 b/deploy/deploy.config.example.ps1 index 85234d8..042c479 100644 --- a/deploy/deploy.config.example.ps1 +++ b/deploy/deploy.config.example.ps1 @@ -23,27 +23,38 @@ $Config = @{ NginxBin = '/www/server/nginx/sbin/nginx' # ---- yelaymaths_api ---- + # The build runs on your machine; the server only receives build output. Api = @{ Key = 'api' Label = 'yelaymaths_api (server API)' LocalPath = 'yelaymaths_api' RemotePath = '/www/wwwroot/yelaymaths/yelaymaths_api' + # Build output only. 'prisma' carries the schema + migrations so you can still run + # `pnpm prisma:migrate` on the server. Source (src / tools / tsconfig …) is never uploaded. DeployPaths = @( - 'src', 'prisma', 'tools', - 'package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml', - 'tsconfig.json', 'tsconfig.build.json', 'nest-cli.json', - '.env.example' + 'dist', 'prisma', + 'package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml' ) - InstallCmd = 'pnpm install --frozen-lockfile' - BuildCmd = 'pnpm build' + # Compile locally so the server never spends CPU on a build. + LocalBuildCmd = 'pnpm prisma:generate && pnpm build' + # Opt-in via -WithInstall. The server's global pnpm is 8.x and cannot read our + # v9+ lockfile, so npx fetches a matching pnpm into its cache instead. + InstallCmd = 'npx --yes pnpm@10.27.0 install --frozen-lockfile' + # Already built locally — do not rebuild on the server. + BuildCmd = '' + # Directories to delete on the server before unpacking, so files removed locally do + # not linger. Leave empty ('@()') when the build output is fully overwritten. + CleanPaths = @() - # Restart command. Run `pm2 list` on the server to find the process name. - # Leave empty ('') if you restart the process some other way. - RestartCmd = 'pm2 restart yelaymaths-api' - # Start command. Used when killing the old process is not enough - # (BT Panel does not bring it back automatically). setsid + nohup keeps - # the process alive after the SSH session ends. Leave empty to skip. + # Restart command: kills the old process so the new build is picked up + # (Node reads code into memory at startup — uploading alone changes nothing). + # If PM2 / systemd already keeps it running, use e.g. 'pm2 restart yelaymaths-api' + # and leave StartCmd empty (''). + RestartCmd = 'pkill -f "dist/main.js" || true' + # Start command. BT Panel does not bring the process back after it is killed, + # so we start it ourselves; setsid + nohup keeps it alive after the SSH session ends. # `node` resolves through the NodeBin PATH exported by the remote script. + # Leave empty ('') to skip. StartCmd = 'setsid nohup node dist/main.js >> /www/wwwlogs/yelaymaths-api.out.log 2>&1 < /dev/null &' # Probe after start. The deploy fails if this URL does not answer in 30s. HealthUrl = 'http://127.0.0.1:3002/healthz' @@ -53,19 +64,30 @@ $Config = @{ # NOTE: NEXT_PUBLIC_* values are inlined at build time, so .env.local must already # exist on the server before the first deploy. It is never uploaded (it is gitignored # and not in the whitelist). + # As with the API, the build runs on your machine and only output is uploaded. Admin = @{ Key = 'admin' Label = 'yelaymaths_admin (admin console)' LocalPath = 'yelaymaths_admin' RemotePath = '/www/wwwroot/yelaymaths/yelaymaths_admin' + # Build output only: `next start` needs .next and next.config.ts at runtime. DeployPaths = @( - 'src', - 'package.json', 'pnpm-lock.yaml', - 'tsconfig.json', 'next.config.ts', 'postcss.config.mjs' + '.next', + 'package.json', 'pnpm-lock.yaml', 'next.config.ts' ) - InstallCmd = 'pnpm install --frozen-lockfile' - BuildCmd = 'pnpm build' - RestartCmd = 'pm2 restart yelaymaths-admin' + # ~73 MB of build cache inside .next is not needed at runtime. + ExcludePaths = @('.next/cache', '.next/diagnostics', '.next/trace', '.next/types') + # Next serves pre-rendered pages straight from .next/cache instead of reading the files + # on disk, so a stale cache means "deployed and restarted, page unchanged". + CleanPaths = @('.next/cache') + # Same as the API: built locally, never rebuilt on the server. + LocalBuildCmd = 'pnpm build' + InstallCmd = 'npx --yes pnpm@10.27.0 install --frozen-lockfile' + BuildCmd = '' + # next start reads pages into memory as well — restart or the old build keeps serving. + # 'next-server' is its process name. + RestartCmd = 'pkill -f "next-server" || true' + # Kill first, then bring it back up ourselves; no BT Panel click needed. StartCmd = 'setsid nohup node node_modules/next/dist/bin/next start -p 3001 >> /www/wwwlogs/yelaymaths-admin.out.log 2>&1 < /dev/null &' HealthUrl = 'http://127.0.0.1:3001/' } diff --git a/yelaymaths_admin/src/app/(admin)/orders/page.tsx b/yelaymaths_admin/src/app/(admin)/orders/page.tsx index ac54976..b6fe0e9 100644 --- a/yelaymaths_admin/src/app/(admin)/orders/page.tsx +++ b/yelaymaths_admin/src/app/(admin)/orders/page.tsx @@ -8,7 +8,8 @@ import { Button, Card, Empty, Input, Notice, Select } from '@/components/ui'; interface OrderRow { id: number; - out_trade_no: string; + /** 后台主动发放 / 回收没有支付单号,服务端返回 null */ + out_trade_no: string | null; wx_order_id: string | null; status: number; amount_fen: number; @@ -140,6 +141,8 @@ export default function OrdersPage() { { value: 2, label: '已开通' }, { value: 3, label: '已退款' }, { value: 4, label: '已关闭' }, + { value: 5, label: '后台主动发放' }, + { value: 6, label: '后台主动回收' }, ]} />