投票平台 · 独立安装向导

本向导独立于日常管理端;全部接口受服务端交付的入口凭据与“未完成”状态双重门控,安装完成后服务端将拒绝再次初始化。口令与密钥只写入服务器文件,不回显、不落日志。

① 环境检查

检查运行环境、配置目录可写性与当前安装状态(入口凭据由服务端核验;每个接口仍各自复核,页面不保存任何凭据)。
尚未检查

入口交付自检(只读)

这一段只回答“本次的初始化入口是怎么交付的、还差什么”,不写入任何进度记录,也不显示任何凭据内容。
尚未自检

② 数据库连接与配置

数据库服务(PostgreSQL 本身、端口与监听地址)由负责人自行安装与管理,本向导不安装数据库服务。这一步只做三件事:填写连接参数 → 验证连接 → 保存应用所需的数据库配置; 结构迁移(建表与改表)是同一步里单独的一次动作,只有它跑完才点亮本步进度——所以“连接成功”既不表示还要向导去装一个数据库,也不表示表结构已经建好。 角色要求:一个能登录、且对业务库有建表权限的普通角色即可,无需 PostgreSQL 超级用户;但“无需超级用户”不等于“无需任何权限”—— “执行结构迁移”要求该角色在业务库上具有 CREATE(“验证连接”会报出当前角色与这项权限); 最后那颗「可选:库不存在时才创建」平时不用碰:库已由你或 1Panel 建好时它无事可做,只有目标库确实还不存在时才会创建那一个库(需要 CREATEDB 权限;没有它就请 DBA 预先建库并把属主交给这个角色)。 向导不提供任何裸 SQL 或 Shell 能力,从不执行 GRANT/REVOKE,也绝不删除任何数据库;验证不通过时一个配置字节都不写。
尚未操作

③ 初始管理员

「检查是否已存在」看的是当前连接的那个数据库里的 admins 表(结果里会写明库名与迁移台账条数):它不看业务数据、不建库、也不涉及数据库服务本身。 空白数据库首次初始化得到的就是“还没有管理员、请创建”,这是正常流程;若这里报“连迁移台账都没有”,意思是第 ② 步的结构迁移还没执行,回到第 ② 步点「执行结构迁移」即可,不是初始化失败。 库里已有管理员时向导拒绝重复创建(不覆盖、也不重置任何口令),但“库里已有管理员记录”本身既不代表初始化完成,也不代表其口令可用——这时走「使用已有管理员」那条正常路径:见下方检查结果后出现的口令校验。公开注册产生的是普通用户,永远不会获得管理员权限。
尚未操作

④ 微信登录配置

可暂时跳过:跳过会作为服务端记录保存(刷新后仍是“已跳过:未配置”,不会被伪装成已配置),未配置时用户端会明确显示“待配置”,不影响继续安装。
这一项填的是回调基址:只填域名时,本步会把它补成 https://你的域名/api/auth/wechat/callback 再写进配置——那是服务端唯一一条真的会拿 code 换身份、签发会话并把你送回登录页的路由。基址填成一个具体路径(例如反向代理自己的回调路径)时按原样保留。但用户端站点自己的路径不算:把 https://你的域名/v/<短码> 这类地址交进来,本步会拒绝并说明原因——那条路径是用户端页面,不是回调路由,换码与签发会话一次都不会执行。微信后台里登记的授权回调地址要和写进配置的这一条一致,保存后本步的返回会原样告诉你最终地址。
尚未操作

⑤ 微信支付配置

默认按凭据自动判定:下面的凭据全部齐备且可加载时服务端写入 wechat,任一项缺失就写入 disabled 并在结果里列出缺哪几项(只列配置项名,不回显内容)。 选“启用真实微信支付”时任何一项不通过都会拒绝启用;选“暂不启用”则直接写 disabled。任何情况都不会自动落到模拟支付,模拟与真实在数据上按支付渠道来源分开记录。私钥仅写入服务器 secrets 目录(0600),不回显。
尚未操作

⑥ 配置验证

把“生产可运行”的几件事一次原子写定:缺失的会话密钥自动生成强随机值、对外地址、下面的部署范围,以及微信登录的启停。本步不会摘掉引导开关——“安装结束”这个宣告只由第 ⑦ 步的服务端复验给出,因此中途退出后仍可用同一命令重启续装。校验不通过时不写入任何文件。图片一律以站内相对地址落库,用户端与管理端各按自己访问 API 的地址显示:本步不需要填写任何图片地址前缀,也不需要填写跨域来源。
选“仅内网”请填你实际要用的那个地址(例如 http://192.168.1.20:3000),不要编一个 https 域名:换台机器它就解析不到。图片不落任何地址前缀(存的是站内相对路径),因此这一项只影响用户端入口,不影响图片能不能显示。这一档还决定下面那份用户端入口清单里能否出现 http://内网地址:选“公网”时 http 条目在本步会被整批拒绝,压根成不了分享链接候选。要让内网 http 与公网 https 两条入口共存就选“仅内网”——公网 https 条目在这一档同样合法,这不是放松校验,只是把私有网段的 http 一并放进允许集合。
停用之后:本进程不会构造任何真实微信授权,用户端如实显示“微信登录未启用”,投票身份判定不再把微信算作可用来源,真实微信支付也不能再回落使用登录的 AppID——如果支付正靠这条回落,本步会先拒绝这组选择、一个字都不写,请先到第 ⑤ 步补一个独立的支付 AppID。写完的配置要重启 API 进程才生效:本进程用的是启动时读入的那一份,本步不会让它当场改口径。
本安装包的路由是用户端在站点根 /、管理端在 /login(同一地址按路径分开)。这一行填用户端规范入口的站点根(https://你的域名),不要追加 /vote 或其他路径前缀:微信授权完成后会回到 <站点根>/login?success=1,而 /vote 下没有用户端页面。接口仍在站点根的 /api/…,安装向导那条给操作者点击的入口地址也取这一行的站点根(https://你的域名/api/install)。
没有正式域名、也没有启用微信登录时这里留空即可:本步照样完成全部必要校验并写入生产口径配置,第 ⑦ 步也不要求它。这一行承担的是「用户端规范入口」这一件事:微信授权完成后的 302 回到它,管理端分享链接的主入口候选也取它,安装向导那条可点击入口取它的站点根部分。等真正启用微信登录(第 ④ 步配置凭据、本步把开关选回“启用”)时再回到这里填真实可达地址就行。 留空同时会把配置里遗留的开发默认值或本机地址(形如 http://localhost:5173)清掉——那不是对外地址,留着会被严格校验按“不能指向本机地址”拒绝,而这一页别无清除入口。 两条约束一条没松:选“公网”就必须是可解析的 https 真实域名;微信登录处于启用状态时这一行变成必填,且不能是本机地址。
管理端生成投票分享链接时读的就是这一份清单,它不需要在建包时写进前端产物:入口地址是部署期事实,同一份产物换成内网 IP 或正式域名访问都应给出正确链接。 分享链接默认跟随你此刻打开管理端所用的地址(同主机且同协议的清单条目优先;没有这样的条目时直接用当前地址 + 用户端站点根 /),所以清单为空也能生成链接——这条清单的作用是补充“固定的、跨域的”用户端入口,不是“没配就不能分享”。 多条目时取哪一条有固定顺序:先跟随你此刻打开管理端用的那个地址(同主机且同协议的那条候选);当前地址是内网地址时优先于站点基础地址;当前地址是公网地址且没有同主机候选时,才退到上面的站点基础地址。 想同时用内网 IP 与内网域名两种方式访问、并希望两种方式都优先生成对应的链接,两种方式各自打开管理端即可,不要求先把另一种写法配进清单;清单里也可以把两种写法各列一条(如 http://192.168.1.20,http://vote.internal)。系统不推断 DNS 别名,也不做 IP 与域名互换:要让两种写法各自生成对应链接,就把它们各列一条。 上面那行“站点基础地址 APP_BASE_URL”只是单一规范/跨域入口:从内网入口打开管理端时它只做兜底,不会顶掉当前内网入口。它不会让管理端自动认出、自动多出其它内网入口——“有哪些用户端入口”这个事实只由 USER_APP_URLS 这一行承载。 留空表示本次不改这一行:第 ⑦ 步会不带参数复验同一个方法,把留空当成“清除”会连带抹掉你早已配好的清单。 本机地址(localhost/127.*)不能当入口,任一条不合格本步一个字都不写、原文件逐字节不变。 本安装包的用户端与后台共用一个地址、只靠路径分开(后台是 http://内网地址/login、用户端是 http://内网地址/),所以这一行写纯站点根(http://内网地址),不要追加 /vote:当前路由没有那个前缀,协议与主机该判的一条没少。 但这一行的每一条都要与该用户端站点的实际路径和产物构建形态一致(见下面那段):写成 /toupiao 这类没人为它服务的前缀,链接格式全对、打开的却是后台或白屏。 这一行同样要重启 API 进程才生效:本进程用的是启动时读入的那一份。
上面两行写的路径必须与用户端产物里的资源前缀一致,它不是本步能改成的东西:产物里的引用是构建期烧进去的(apps/web/vite.config.ts 按 VITE_WEB_BASE 三态决定:没写或显式写 / 都落站点根、显式写前缀按该前缀构建,形态非法直接拒绝构建)。本安装包是站点根形态:两行写纯站点根(https://你的域名),产物按 / 构建(npm run build:web 缺省即是,或显式 VITE_WEB_BASE=/)。
本包自带的 first-entry.ts 只提供 / 的用户端与 /login 的管理端,不再为 /vote/ 提供用户端页面;把这两行写成 /vote,链接格式可能全对,打开却会落到管理端外壳或 404。
配错的表现是白屏或打开错页面而不是报错,本步无法替你核实——它读的是配置,产物里的那份前缀不在本进程能看到的范围里,靠猜只会把不确定包装成确定。可核实的方法:解包看 apps/web/dist/index.html 里 src= 是 /assets/… 还是 /vote/assets/…,或在新窗口打开一条分享链接看得到的是投票页还是空白页;对不上就按站点根形态重新构建,改配置不会让一份产物同时满足两种形态。
尚未校验

⑦ 完成验收

服务端复验(迁移无待执行 + 管理员来源明确 + 配置在无引导开关下也能严格通过)后,同一步里把配置文件的生产口径写定并写入完成标记;任一步失败都不会留下半提交状态,原命令重启即可继续。完成后本向导立即失效;管理端接口要等按部署方式重启进程(systemd / 1Panel 自动拉起,前台演练重跑同一条启动命令)后才开放——当前进程内存里仍是引导期读入的旧会话密钥,配置里第 ⑥ 步生成的强随机密钥必须重启才会加载,因此这一步不靠人工改任何配置。管理员来源只认服务端记录(第 ③ 步创建过、或「使用已有管理员」校验通过),页面自己的勾选状态不构成来源;库里有一行管理员这件事本身永远不算来源。
尚未判定管理员来源:请先回到第 ③ 步检查或创建管理员。
尚未完成