CONDO Owner Desk
CONDO Owner Desk 是一套面向酒店公寓运营团队的业主年度住宿权益管理系统。它把业主账户、房型规则、入住使用记录和年度剩余权益集中在一个工作台中,并由后端统一计算房晚、扣减倍率和余额,避免浏览器直接修改权威数据。
当前版本由原生 Web 前端、TypeScript/Fastify API 和 PostgreSQL 数据层组成,可通过 Docker 部署,也可使用 Mock API 或本地历史审计快照进行演示。
主要功能
- 受保护的运营人员登录、12 小时 HttpOnly 会话和主动退出。
- Dashboard 展示业主房间数、剩余权益、已用权益、房型分布与月度使用情况。
- 按编号、业主、房号、单元号、会员号和房型查询业主账户。
- 查询、筛选和分页浏览使用记录及业主详情。
- 新增使用记录时预览扣减结果;Night、倍率、Use 和 Balance 最终由后端计算。
- 删除使用记录时通过事务恢复账户余额。
- 英语、简体中文和泰语界面切换。
- 支持 PostgreSQL 持久化模式、完整历史快照预览模式和内置原型数据模式。
系统架构
flowchart LR
Browser[浏览器<br/>HTML / CSS / JavaScript]
Nginx[Nginx<br/>静态资源与 /api 反向代理]
API[Fastify API<br/>认证、校验、业务事务]
DB[(PostgreSQL<br/>booking_test / condon)]
Browser --> Nginx
Nginx --> API
API --> DB
- 前端没有打包步骤,可直接由任意静态 Web 服务器托管。
- Docker 模式下,浏览器只访问 Nginx;
/api/*被同源代理到后端,后端端口不对外发布。 - PostgreSQL 不包含在
docker-compose.yml中,后端连接现有的booking_test数据库,并且只使用隔离的condonschema。 - 浏览器不接触数据库凭据,也不直接连接 PostgreSQL。
快速体验
前置条件
- Node.js 24 或更高版本。
- Python 3(仅用于下面的本地静态文件服务;也可换成其他静态服务器)。
使用内置原型数据
这是全新克隆仓库后最容易复现的方式,不需要 PostgreSQL,也不会写入真实数据。
在第一个终端启动本地认证 Mock API:
node tests/mock-api-server.mjs
在第二个终端从仓库根目录启动前端:
python3 -m http.server 4173 --bind 127.0.0.1
打开 http://127.0.0.1:4173/?mode=demo,使用本地开发账号登录:
Username: wyndhamcondon
Password: wyndhamcondon
?mode=demo 使用前端内置的 190 条原型账户;登录由 Mock API 完成。演示期间新增或删除的数据只保存在当前进程内存中,进程重启后恢复初始状态。
默认账号只用于本地开发和演示。任何共享或生产环境都必须通过环境变量更换密码。
运行模式
1. PostgreSQL 持久化模式
前端默认运行在 API 模式。后端需要可访问且已经应用 condon 迁移的 booking_test 数据库。
cd backend
npm ci
cp .env.example .env
编辑 .env 中的数据库连接和认证信息,然后在 zsh/bash 中加载环境变量并启动后端:
set -a
source .env
set +a
npm run dev
另开终端,在仓库根目录启动前端:
python3 -m http.server 4173 --bind 127.0.0.1
打开 http://127.0.0.1:4173。前端会连接当前主机的 3000 端口,并在认证成功后加载数据库中的业主、使用记录和 Dashboard 聚合数据。
数据库迁移、导入和只读部署验证需要额外的运维步骤,详见 后端说明 和 Docker 部署说明。
2. 完整历史快照预览
历史预览不连接 PostgreSQL,提供与正式 API 相同的认证和业务接口。但预览所需的审计 JSON 含业务数据,位于 Git 忽略目录,不会随仓库克隆或推送。
只有已安全取得该批次材料时才可使用此模式。默认目录为:
.planning/data_import_audit/import_batch_2026_07_31
也可以通过 CONDO_IMPORT_SNAPSHOT_DIR 指向外部安全目录。准备好材料后执行:
cd backend
npm ci
npm run build
npm run preview:history:check
npm run preview:history
再从仓库根目录启动 4173 端口的前端并打开默认 URL。快照写入只存在内存中,预览进程停止后即丢失。
当前脚本校验的历史基线为:388 个业主账户、157 条使用记录、2026 年已使用 438 个权益晚、剩余 5,394 个权益晚。
3. Docker 部署
复制生产环境示例文件:
cp deploy/.env.production.example .env
至少填写 DB_HOST、DB_USER、DB_PASSWORD 和 AUTH_PASSWORD。如果不是通过 http://localhost:8080 访问,还要把 CORS_ORIGINS 改为浏览器实际访问的完整 Origin;HTTPS 环境应设置 AUTH_COOKIE_SECURE=true。
docker compose build
docker compose up -d
默认访问地址为 http://localhost:8080。停止服务:
docker compose down
部署拓扑、迁移命令和连接输入格式见 Docker 部署说明。
核心业务规则
每个业主房号独立拥有年度权益期间,当前默认年度新增为 15 晚,可包含上一年度结转。一次使用的权威计算为:
Night = Check-out - Check-in
Multiplier = max(1, Used Tier - Purchased Tier + 1)
Use = Night × Multiplier
Balance After = Balance Before - Use
房型分级如下:
| Tier | 房型 |
|---|---|
| 1 | RM1、RM2、RM3、RM4、UG1、UG2 |
| 2 | SU1、SU2、SU6 |
| 3 | SU3 |
AC2 不进入自动分级;购买房型或使用房型涉及 AC2 时,运营人员必须选择 1–3 的人工倍率,后端再次校验。
使用记录创建和删除、权益流水及当前余额在 PostgreSQL 事务中同步更新。系统拒绝余额不足、日期无效、跨权益年度、房型规则不符和幂等键冲突等请求。完整表结构和规则见 后端数据模型。
API 概览
除三个 /auth/* 接口和 CORS 预检外,其他接口(包括 /docs)都要求有效的 condon_session Cookie。
| Method | Path | 说明 |
|---|---|---|
| POST | /auth/login |
登录并创建会话 |
| GET | /auth/session |
查询当前会话 |
| POST | /auth/logout |
注销当前会话 |
| GET | /health |
检查数据库、schema 和迁移版本 |
| GET | /room-types |
获取房型与倍率规则元数据 |
| GET | /owner-accounts |
搜索和分页查询业主账户 |
| GET | /owner-accounts/:id |
查询业主账户详情与年度余额 |
| GET | /usage-records |
查询使用记录 |
| POST | /usage-records |
事务性新增使用记录并扣减余额 |
| DELETE | /usage-records/:id |
事务性删除使用记录并恢复余额 |
| GET | /dashboard |
查询年度 Dashboard 聚合 |
后端运行时可通过 /docs 查看 OpenAPI UI。请求字段、返回模型和数据库函数详见 后端说明。
主要配置
后端本地配置模板为 backend/.env.example,Docker 配置模板为 deploy/.env.production.example。
| 变量 | 默认值/要求 | 用途 |
|---|---|---|
API_HOST |
127.0.0.1 |
后端监听地址 |
API_PORT |
3000 |
后端监听端口 |
CORS_ORIGINS |
本地 4173 Origin |
允许携带 Cookie 的前端来源,逗号分隔 |
AUTH_USERNAME |
本地默认 wyndhamcondon |
运营登录名 |
AUTH_PASSWORD |
生产必须设置 | 运营登录密码 |
AUTH_SESSION_TTL_HOURS |
12 |
会话有效期,允许 1–168 小时 |
AUTH_COOKIE_SECURE |
生产默认 true |
是否只通过 HTTPS 发送 Cookie |
DB_HOST / DB_USER / DB_PASSWORD |
必填 | PostgreSQL 连接信息 |
DB_NAME |
必须为 booking_test |
防止误连其他数据库 |
DB_SSL |
false |
是否启用数据库 SSL |
CONDO_API_BASE_URL |
Docker 默认 /api |
前端 API 根地址 |
CONDO_DEFAULT_MODE |
api |
前端默认数据模式 |
CONDO_PERIOD_YEAR |
当前 UTC 年 | Dashboard 与账户权益年度 |
应用不会自动读取 .env 文件;本地运行需要先把其中的值导出到当前 shell。不要提交真实环境文件或凭据。
目录结构
.
├── index.html / styles.css / app.js # 原生前端界面与交互
├── api-client.js / runtime-config.js # API 客户端与前端运行时配置
├── owners-data.js # demo 模式原型数据
├── backend/
│ ├── src/ # Fastify API、认证、仓储和配置
│ ├── migrations/ # condon schema SQL 迁移
│ ├── scripts/ # 迁移、导入、冒烟和部署验证工具
│ └── tests/ # 后端单元与仓储测试
├── tests/ # 前端 Node 测试和 Mock API
├── deploy/ # Nginx 与 Docker 运行时配置
├── docker-compose.yml # 前后端容器编排
├── backend-data-model.md # 数据模型与业务规则规格
└── DOCKER_DEPLOYMENT.md # Docker 运维说明
业主账户.md 和 使用记录.md 是历史业务资料摘要,含个人与运营数据。共享、复制或导出前请遵循适用的数据保护要求。
开发与验证
前端测试:
node --test tests/*.test.mjs
后端检查:
cd backend
npm ci
npm run typecheck
npm test
npm run build
npm run db:check-migrations
需要真实数据库的命令包括 db:inventory、db:migrate:up、db:verify、db:verify-import 和 db:test-integration。其中 db:test-integration 只允许针对空的测试 schema 执行,不能用于已导入业务数据的环境。
安全与当前边界
- 生产环境必须更换默认登录凭据,并通过 Secret Manager 或运行时环境变量注入数据库密码。
- 会话令牌只通过 HttpOnly Cookie 发送,服务端只保存其 SHA-256 键;当前会话存储在后端内存中,后端重启后所有会话失效。
- 后端日志对 Cookie、认证信息和数据库密码做脱敏处理。
- 当前版本是单一运营账号模型,尚未实现多用户身份、角色权限和持久化会话。
- 当前不支持人工余额调整或跨权益年度入住。
- 数据库回滚属于显式运维操作;业务数据导入后不要执行迁移回滚。