基于 HarmonyOS NEXT 的校园全场景分寝与共治平台。 一句话定位:把选择权交还给学生,让合拍的人先相聚。
本项目是一套结构完整、可直接导入 DevEco Studio 构建运行的 ArkTS 工程,核心的「三级匹配引擎」是真实可跑的算法,鸿蒙特性以「真实 API + 单设备可演示封装」两种方式落地(见 真实 API vs 演示封装)。
| 项 | 值 |
|---|---|
| 平台 | HarmonyOS NEXT |
| SDK | 6.1.1(24)(target / compatible 一致),runtimeOS: HarmonyOS |
| 语言 | ArkTS(Stage 模型 + 声明式 UI) |
| 包名 | com.example.myapplication |
| 版本 | 1.0.0(versionCode 1000000) |
| 设备 | phone |
| 许可 | MIT |
打开 web/index.html —— 一个零依赖的单文件网页演示版,涵盖全部 5 个页面与契合度五维雷达图,双击即可在浏览器中体验完整交互流程。
网页版是早期的 UI / 交互验证原型,用于没有鸿蒙环境时预览;真正的原生实现在
entry/与application/模块。
- 安装 DevEco Studio 6.1+(需包含 HarmonyOS SDK
6.1.1(24))。 File → Open选择本仓库根目录。- 等待
oh_modules自动同步完成。 - 连接鸿蒙模拟器或真机,在工具栏选择模块(
entry或application任选其一)后点击 Run。
体验路径:
首页 → ① 智能画像采集(可改文字重新解析意图)
→ ② 匹配广场(选 3 位伙伴,凑满 4 人成寝)
→ ③ 虚拟宿舍(一拉即合,改熄灯/充值看全舍同步)
→ ④ 换寝市场(看室友匿名画像与兼容度)
→ ⑤ 分寝结果公示(五维图 + 逐对扣分明细)
cd <仓库目录>
# 构建(产物为未签名 HAP,模拟器可直接安装)
& "<DevEco 安装目录>\tools\node\node.exe" `
"<DevEco 安装目录>\tools\hvigor\bin\hvigorw.js" `
--mode module -p module=entry@default -p product=default `
-p requiredDeviceType=phone assembleHap --analyze=normal --parallel --incremental --daemon
# 产物路径
# entry\build\default\outputs\default\entry-default-unsigned.hap安装与启动(需先启动模拟器):
$hdc = "<SDK 目录>\default\openharmony\toolchains\hdc.exe"
& $hdc list targets # 确认设备,如 127.0.0.1:5555
& $hdc -t 127.0.0.1:5555 install entry\build\default\outputs\default\entry-default-unsigned.hap
& $hdc -t 127.0.0.1:5555 shell aa start -b com.example.myapplication -a EntryAbility
# 验证运行状态(应显示 state #FOREGROUND)
& $hdc -t 127.0.0.1:5555 shell aa dump -l鸿蒙应用只能上架华为应用市场,服务端则需要自己准备一台服务器。
server/ 目录即为配套后端,与端侧共用同一套匹配算法与隐私红线。
- 技术栈:Node.js 22 + TypeScript + Express + SQLite
(数据层用 Node 内置
node:sqlite,零原生依赖,Windows / Docker 免编译) - 已实现:认证鉴权、生活画像、匹配推荐、自主组队与系统兜底聚合、 虚拟宿舍(乐观锁 + SSE 实时同步)、换寝市场、万能卡片数据接口
- 隐私红线:敏感字段(需下铺 / 打呼噜 / 健康备注)服务端无对应列, 请求一旦携带即返回 422 并列出被拒字段
一键启动:
cd server
cp .env.example .env # 务必修改 JWT_SECRET
docker compose up -d --build
curl http://localhost:3000/health完整文档见 server/README.md: API 清单、环境变量、鸿蒙端接入示例、Nginx 反代 SSE 配置与常见问题。
.
├─ AppScope/app.json5 # 应用级配置(包名 / 版本 / 图标)
├─ build-profile.json5 # 工程构建配置(products / modules)
├─ oh-package.json5 # 依赖声明
├─ hvigorfile.ts # 构建脚本入口
├─ LICENSE # MIT
├─ README.md
├─ docs/screenshot-index.jpeg # 首页实机截图
├─ web/index.html # 单文件网页演示版
│
├─ entry/ # ★ 鸿蒙主模块(推荐构建此模块)
│ ├─ build-profile.json5
│ └─ src/main/
│ ├─ module.json5 # Ability / Form / 页面路由
│ ├─ resources/
│ │ ├─ base/element/ # string.json / color.json / float.json
│ │ ├─ base/media/ # startIcon / layered_image
│ │ ├─ base/profile/ # main_pages.json / form_config.json / backup_config.json
│ │ └─ dark/element/color.json # 深色模式配色
│ └─ ets/
│ ├─ entryability/EntryAbility.ets # 应用入口(Stage 模型)
│ ├─ entrybackupability/EntryBackupAbility.ets
│ ├─ entryformability/EntryFormAbility.ets # 万能卡片能力(Form Kit)
│ ├─ widget/DormWidget.ets # 桌面万能卡片 UI
│ ├─ model/
│ │ ├─ types.ets # 数据模型(画像 / 房间 / 评分)
│ │ ├─ MockData.ets # 模拟新生数据(12 人,覆盖各类冲突)
│ │ └─ MatchEngine.ets # ★ 三级智能匹配引擎(核心算法)
│ ├─ utils/
│ │ ├─ IntentParser.ets # 端侧意图抽取(语音/文字 → 标签)
│ │ ├─ DormSync.ets # 分布式宿舍状态同步(封装 + 模拟)
│ │ ├─ storage.ets # 端侧沙箱存储(@kit.ArkData)
│ │ └─ session.ets # 跨页面运行期会话单例
│ ├─ components/
│ │ ├─ CompatRadar.ets # 契合度五维图(Canvas 绘制)
│ │ └─ DormCard.ets # 匿名候选卡片
│ └─ pages/
│ ├─ Index.ets # 首页(五大场景入口)
│ ├─ ProfileInput.ets # ① 智能画像采集
│ ├─ MatchSquare.ets # ② 匹配广场(自主组队)
│ ├─ VirtualDorm.ets # ③ 虚拟宿舍(超级终端)
│ ├─ ExchangeMarket.ets # ④ 换寝市场
│ └─ Result.ets # ⑤ 分寝结果公示
│
├─ application/ # 鸿蒙模块(内容与 entry 一致,历史原因保留)
└─ TongPin/ # 早期工程快照(含初版 README.md)
关于
entry与application两个模块:二者同为entry类型、代码内容一致,任选其一即可构建运行。这是开发过程中 DevEco 新建默认模板模块所留下的冗余,为保留历史记录未做删减。若你 fork 后想精简,删掉其中一个模块并从build-profile.json5的modules中移除对应条目即可。
| 作品描述 | 落地代码 |
|---|---|
| 三级匹配引擎(硬约束 / 软评分 / 自主组队) | model/MatchEngine.ets |
| 端侧 AI 意图框架(语音/文字 → 标签) | utils/IntentParser.ets |
| 隐私红线(端侧沙箱,绝不上云) | utils/storage.ets(@kit.ArkData preferences) |
| 超级终端虚拟宿舍 + 状态秒级同步 | utils/DormSync.ets + pages/VirtualDorm.ets |
| 匹配广场 / 可视化换寝市场 | pages/MatchSquare.ets / pages/ExchangeMarket.ets |
| 契合度五维图 + 扣分明细(算法透明) | components/CompatRadar.ets + pages/Result.ets |
| 万能卡片(Form Kit) | entryformability/EntryFormAbility.ets + widget/DormWidget.ets + form_config.json |
| ArkTS + Stage 模型声明式开发 | 全量 /pages,EntryAbility.ets |
算法全部在端侧完成(纯 ArkTS),无需联网调用云端模型。
第一级 · 硬约束红线
- 性别第一优先级:楼栋初始化即绑定男/女属性,跨性别伙伴永远不可见(
MatchEngine.filterHard)。 - 下铺刚需:身体原因需下铺设为不可逾越的硬性条件(
MatchEngine.satisfyLowerBunk)。
第二级 · 软约束加权评分(0~100)
| 冲突项 | 扣分规则 |
|---|---|
| 作息 | 睡眠时间差 > 2h 直接 -40(最高权重);否则每差 1h -8 |
| 空调 | 每差 1℃(一档)-15 |
| 卫生 | 档位差 ≥ 3 视为极端不匹配 -30;否则每档 -8 |
| 噪音 × 游戏 | 一方外放 + 另一方敏感 ⇒ -30 |
| 双向折磨 | 双方都敏感且都外放 ⇒ 额外 -30 |
- 兼容度 > 80 视为「物以类聚」优先推荐(
RECOMMEND_THRESHOLD)。 - 兼容度 ≥ 60 且 < 80 为
mid,< 60 为low(CandidateLevel)。
第三级 · 自主组队 + 兜底聚合(去中心化分配)
- 学生在匹配广场对匿名伙伴双向邀约,本人 + 3 人 = 4 人成寝即锁定房间。
- 超时未完成组队的人群,由
MatchEngine.fallbackAssign按兼容度贪心聚合成 4 人组,并保证同性别。 - 组内同时给出平均兼容度与最差两两兼容度(底线保障),避免"平均好看、个别人难受"。
算法透明:结果页会逐对列出扣分明细(作息-40,空调-15…),拒绝黑箱。
敏感字段(needLowerBunk 需下铺、snore 打呼噜、illness 健康备注)仅存于端侧沙箱,不进匹配网络、不展示给陌生人。候选卡片只暴露匿名标签(作息时段 / 空调温度 / 耳机习惯 / 卫生档位),展示名为「同学A/B/C」。
| 能力 | 实现方式 |
|---|---|
| ArkTS / Stage 模型 / 声明式 UI | ✅ 真实鸿蒙 API |
端侧存储(@kit.ArkData preferences) |
✅ 真实鸿蒙 API |
万能卡片(@kit.FormKit) |
✅ 真实鸿蒙 API |
数据备份(BackupExtensionAbility) |
✅ 真实鸿蒙 API |
| 意图抽取(Intent Framework) | 🟡 关键词轻量实现,真实场景替换为官方意图框架 |
| 分布式同步(Distributed Data Kit) | 🟡 DormSync 以内存事件总线 + 注释锚点模拟,真实场景替换为 distributedData KVStore |
| 超级终端一拉即合 / 跨端流转 / 实况窗 | 🟡 以按钮 + 状态广播演示交互,真实能力需调用对应 Kit |
工程刻意把「分布式 / 超级终端」做成接口稳定、注释清晰的封装层,方便在无多设备的单模拟器环境下演示,拿到真机或多设备后可替换为官方 SDK,上层业务代码无需改动。
本工程在 SDK 6.1.1(24) 的严格 ArkTS 子集下 0 error 通过编译。踩过的坑与对应写法,对同版本开发者有参考价值:
| 约束 | 错误写法 | 正确写法 |
|---|---|---|
| 自定义组件必须对象字面量调用 | Header('标题') |
Header({ title: '标题' }) |
| 禁止展开运算符 | { ...a, ...patch }、[...arr, x] |
mergeProfile(a, patch)、arr.concat([x]) |
| 禁止解构声明 | const { avg, min } = gs |
const avg = gs.avg; const min = gs.min; |
Object.assign 受限(arkts-limited-stdlib) |
Object.assign({}, a, b) |
显式逐字段拷贝(storage.ets 提供 cloneProfile / mergeProfile) |
对象字面量需对应声明类型(arkts-no-untyped-obj-literals) |
const d: Record<string,string> = {...} |
interface CardFormData {...} 再 const d: CardFormData = {...} |
| 组件成员不得与内置属性同名 | onClick: () => void |
改名 onTap |
| struct 引用需先定义(无前置声明) | DormCard 中用后文定义的 Tag |
Tag 定义在 DormCard 之前 |
| 可选属性初始化器 | onInvite?: (id:string)=>void = undefined |
onInvite?: (id:string)=>void,调用处 if (x !== undefined) x(...) |
裸 .align() 不可挂自定义组件 |
Card({...}){...}.align(Alignment.Center) |
去掉(容器自身已 width('100%')) |
该 SDK 版本的
build-profile.json5不支持通过arkOptions.strictMode关闭严格模式(会触发 schema 校验错误),必须按上表逐项改写代码。
web/—— 单文件网页演示版(零依赖,双击打开)。docs/—— 实机截图等文档素材。TongPin/—— 早期工程快照,保留初版README.md,仅供对照,构建时不需要。
- 接入校园一卡通 / 门禁(手机·手表碰一碰开门)
- 班会课选寝结果
Continuation跨端流转至鸿蒙智慧屏民主表决 - 匹配进度 / 换寝审批
Live View实况窗悬浮 - 用真实
distributedDataKVStore 替换DormSync模拟层 - 复用至职场合租、兴趣社团组队等泛社交场景
MIT © 2026 weekomen
欢迎 Issue 与 PR。若这个项目对你有帮助,点个 ⭐ 就是最大的鼓励。
