MySQL 设计说明
-/misc/mysql-query-design.md
+/docs/mysql-query-design.md
加载中...
diff --git a/.dockerignore b/.dockerignore
index c08fd8a..2afb830 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,5 +1,6 @@
.git
.DS_Store
+delivery/.env
__pycache__
*.pyc
*.pyo
diff --git a/.github/workflows/daily-sync-upstream.yml b/.github/workflows/daily-sync-upstream.yml
deleted file mode 100644
index 47c4398..0000000
--- a/.github/workflows/daily-sync-upstream.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-name: Daily Upstream Sync
-
-on:
- workflow_dispatch:
- schedule:
- - cron: "0 1 * * *"
-
-permissions:
- contents: write
-
-jobs:
- sync:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: "3.11"
-
- - name: Capture upstream commit
- id: upstream
- run: |
- echo "commit=$(git ls-remote https://github.com/KHwang9883/MobileModels.git refs/heads/master | awk '{print $1}')" >> "$GITHUB_OUTPUT"
-
- - name: Sync upstream raw data
- run: |
- python3 tools/sync_upstream_mobilemodels.py --build-index --export-mysql-seed
-
- - name: Commit changes
- env:
- UPSTREAM_COMMIT: ${{ steps.upstream.outputs.commit }}
- run: |
- git config user.name "github-actions[bot]"
- git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- git add brands misc README.md README_en.md CHANGELOG.md CHANGELOG_en.md LICENSE.txt dist/device_index.json dist/mobilemodels_mysql_seed.sql
- if git diff --cached --quiet; then
- echo "No upstream changes to commit."
- exit 0
- fi
- git commit -m "chore: sync upstream raw data ${UPSTREAM_COMMIT::7}"
-
- - name: Push changes
- run: git push
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..be47843
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.DS_Store
+.env
diff --git a/README.md b/README.md
index 49fb41a..34c6506 100644
--- a/README.md
+++ b/README.md
@@ -1,157 +1,37 @@
-# 手机品牌型号汇总
+# MobileModels Workspace
-[](https://github.com/KHwang9883/MobileModels/issues)
-[](https://github.com/KHwang9883/MobileModels/pulls)
-[](https://github.com/KHwang9883/MobileModels)
-[](https://github.com/KHwang9883/MobileModels)
-[](https://creativecommons.org/licenses/by-nc-sa/4.0/)
+当前仓库按两层结构组织:
-汇总各厂商上市的手机型号与对应的传播名。
+- `workspace/`
+ - 工作空间
+ - 存放上游原始数据、补充资料和历史变更文件
+- `delivery/`
+ - 交付物
+ - 存放可直接运行的 Docker Compose 项目、Web 页面、MySQL schema 和交付文档
-[English](README_en.md)
+## 使用方式
-## Web UI
-
-项目内置了设备查询与数据管理页面,统一通过 `docker compose` 启动:
+进入交付目录启动:
```bash
+cd delivery
docker compose up --build -d
```
-打开:
+页面入口:
- `http://127.0.0.1:8123/web/device_query.html`
- `http://127.0.0.1:8123/web/brand_management.html`
+- `http://127.0.0.1:8123/web/device_query.html?view=docs`
-MySQL 也会一并启动:
+## 目录说明
-- host: `127.0.0.1`
-- port: `3306`
-- database: `mobilemodels`
-- reader user: `mobilemodels_reader`
+```text
+workspace/ 原始数据与工作空间
+delivery/ 可交付运行物
+```
-如需自定义 MySQL 账号密码,可先复制 `.env.example` 为 `.env` 后再启动。
-原始数据、索引和 MySQL seed 运行时持久化在 Docker volume 中,不再回写本地工作区。
+更多交付说明见:
-更多说明参见 [web/README.md](web/README.md)。
-
-- ✅ 包含
-- ⏹ 仅部分包含
-- ❌ 不包含
-
-| 名称 | 品牌 | 汇总范围 | codename | 海外机型 | 备注 |
-| :-: | :-: | :-: | :-: | :-: | :-: |
-| [360shouji](brands/360shouji.md) | 360 手机 | 全部 360/奇酷手机 | ❌ | ❌ | -- |
-| [apple_all](brands/apple_all.md) | Apple | 全部 iPhone/iPad/iPod touch/Apple Watch/Apple TV/Apple Vision | ✅ | ✅ | -- |
-| [apple_all_en](brands/apple_all_en.md) | Apple | 全部 iPhone/iPad/iPod touch/Apple Watch/Apple TV/Apple Vision | ✅ | ✅ | 英文版 |
-| [apple_cn](brands/apple_cn.md) | Apple | 全部国行 iPhone/iPad/iPod touch/Apple Watch/Apple Vision | ✅ | ❌ | -- |
-| [asus_cn](brands/asus_cn.md) | 华硕 (ASUS) | ROG Phone 等 | ✅ | ❌ | -- |
-| [asus_en](brands/asus_en.md) | 华硕 (ASUS) | ROG Phone/Zenfone | ✅ | ✅ | 英文版 |
-| [blackshark](brands/blackshark.md) | 黑鲨 (Black Shark) | 全部机型 | ✅ | ✅ | -- |
-| [blackshark_en](brands/blackshark_en.md) | 黑鲨 (Black Shark) | 全部机型 | ✅ | ✅ | 英文版 |
-| [coolpad](brands/coolpad.md) | 酷派 (Coolpad) | 酷派近年智能手机机型 | ❌ | ❌ | -- |
-| [google](brands/google.md) | Google | Google Pixel 手机/平板/手表 | ✅ | ✅ | 英文版 |
-| [honor_cn](brands/honor_cn.md) | 荣耀 (HONOR) | 荣耀手机/平板/笔记本电脑/智慧屏/穿戴设备,仅包含国行型号 | ⏹ | ❌ | -- |
-| [honor_global_en](brands/honor_global_en.md)| 荣耀 (HONOR) | 荣耀手机/平板,仅包含海外型号 | ⏹ | ✅ | 英文版 |
-| [huawei_cn](brands/huawei_cn.md) | 华为 (HUAWEI) | 华为 Mate/Pura/nova/G/麦芒/畅享系列、平板电脑、MateBook、智慧屏及穿戴设备,仅包含国行型号 | ⏹ | ❌ | [其他早期型号参阅此处](misc/early-huawei-models.md) |
-| [huawei_global_en](brands/huawei_global_en.md)| 华为 (HUAWEI) | 华为 Mate/Pura/nova/Y 系列及平板电脑,仅包含海外型号 | ⏹ | ⏹ | 英文版 |
-| [lenovo_cn](brands/lenovo_cn.md) | 联想 (Lenovo) | 联想品牌 2017 年起上市的机型、ZUK 全部机型 | ✅ | ❌ | -- |
-| [letv](brands/letv.md) | 乐视 (Letv) | 全部手机机型 | ❌ | ❌ | 不包含电视产品 |
-| [meizu](brands/meizu.md) | 魅族 (MEIZU) | 全部机型 | ✅ | ✅ | -- |
-| [meizu_en](brands/meizu_en.md) | 魅族 (MEIZU) | 全部机型 | ✅ | ✅ | 英文版 |
-| [mitv_cn](brands/mitv_cn.md) | 小米 (Xiaomi) | 全部国行小米/Redmi 电视、机顶盒 | ❌ | ❌ | -- |
-| [mitv_global_en](brands/mitv_global_en.md) | 小米 (Xiaomi) | 全部小米/Redmi 电视、机顶盒、智能电视棒,仅包含海外型号 | ❌ | ✅ | 英文版 |
-| [motorola_cn](brands/motorola_cn.md) | 摩托罗拉 (Motorola) | 2015 年起上市的机型 | ✅ | ❌ | -- |
-| [nokia_cn](brands/nokia_cn.md) | 诺基亚 (Nokia) | 2017 年起由 HMD Global 制造的智能手机机型 | ✅ | ❌ | -- |
-| [nothing](brands/nothing.md) | Nothing | 全部机型 | ✅ | ✅ | 英文版 |
-| [nubia](brands/nubia.md) | 努比亚 (nubia) | 全部机型 | ❌ | ⏹ | -- |
-| [oneplus](brands/oneplus.md) | 一加 (OnePlus) | 全部机型 | ✅ | ✅ | -- |
-| [oneplus_en](brands/oneplus_en.md) | 一加 (OnePlus) | 全部机型 | ✅ | ✅ | 英文版 |
-| [oppo_cn](brands/oppo_cn.md) | OPPO | 2018 年起新型号命名方式的国行机型 | ⏹ | ❌ | -- |
-| [oppo_global_en](brands/oppo_global_en.md) | OPPO | 2018 年起上市的海外机型 | ⏹ | ⏹ | 英文版 |
-| [realme_cn](brands/realme_cn.md) | 真我 (realme) | 全部国行机型 | ⏹ | ❌ | -- |
-| [realme_global_en](brands/realme_global_en.md) | 真我 (realme) | 全部海外机型 | ⏹ | ✅ | 英文版 |
-| [samsung_cn](brands/samsung_cn.md) | 三星 (Samsung) | Galaxy S/Note/A/Z/M/C/J/On/Tab/心系天下系列及个别其他机型,仅包含国行型号 | ✅ | ❌ | [其他早期型号参阅此处](misc/early-samsung-models.md) |
-| [samsung_global_en](brands/samsung_global_en.md) | 三星 (Samsung) | Galaxy S/Note/A/Z/M/F 系列,2019 年起上市的机型 | ✅ | ⏹ | 英文版 |
-| [smartisan](brands/smartisan.md) | 坚果 (Smartisan) | 全部机型 | ✅ | ❌ | -- |
-| [sony](brands/sony.md) | 索尼 (SONY) | 2015 年起上市的机型 | ✅ | ✅ | 英文版 |
-| [sony_cn](brands/sony_cn.md) | 索尼 (SONY) | 2015 年起上市的国行机型 | ✅ | ❌ | -- |
-| [vivo_cn](brands/vivo_cn.md) | vivo | 2018 年起新型号命名方式的国行机型 | ✅ | ❌ | -- |
-| [vivo_global_en](brands/vivo_global_en.md) | vivo | 2019 年起上市的海外机型 | ⏹ | ⏹ | 英文版 |
-| [xiaomi](brands/xiaomi.md) | 小米 (Xiaomi) | 小米/REDMI/POCO 手机 & 平板等 | ✅ | ✅ | -- |
-| [xiaomi_cn](brands/xiaomi_cn.md) | 小米 (Xiaomi) | 小米/REDMI 手机 & 平板等 | ✅ | ✅ | 英文版 |
-| [xiaomi_en](brands/xiaomi_en.md) | 小米 (Xiaomi) | 小米/REDMI/POCO 手机 & 平板等 | ✅ | ✅ | 英文版 |
-| [xiaomi-wear](brands/xiaomi-wear.md) | 小米 (Xiaomi) | 小米/Redmi 手表、手环、TWS 等穿戴设备 | ⏹ | ✅ | TWS 不包含外包型号;暂不含儿童手表型号 |
-| [zhixuan](brands/zhixuan.md) | 华为智选 | U-MAGIC 优畅享/电信麦芒/NZONE/Hi nova/雷鸟 FFALCON/TD Tech/WIKO | ⏹ | ❌ | -- |
-| [zte_cn](brands/zte_cn.md) | 中兴 (ZTE) | 2017 年起上市的机型 | ❌ | ❌ | -- |
-
-## 更新日志
-
-参见 [CHANGELOG.md](CHANGELOG.md)
-
-## 许可
-
-
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
-
-## 项目历史
-
-### 2024 年 3 月
-- 将本项目 csv 及脚本迁移至 [此 repo](https://github.com/KHwang9883/MobileModels-csv),使用 GitHub Actions 自动更新。
-
-### 2022 年 4 月
-- 新增 [各大 Android 厂商 BL 解锁/内核开源情况](https://github.com/KHwang9883/bootloader-kernel-source) 汇总(已停更)。
-
-### 2021 年 12 月
-- 新增 [各品牌型号命名规则](misc/naming-rules.md) 汇总。
-
-### 2019 年 7 月
-- 文档版停止维护。
-
-### 2019 年 4 月
-- 文档版迁移至 GitHub 直链下载。
-- 新增英文版。
-
-### 2019 年 3 月
-- 文档版迁移至微云。
-
-### 2018 年 11 月
-- 项目同步至 GitHub。
-
-### 2018 年 7 月
-- 由于小米社区帖子失效,「手机品牌型号汇总」项目公开发布,提供文档版百度网盘下载。
-
-### 2016 年 3 月
-- 小米手机型号汇总发布至 [小米社区](http://bbs.xiaomi.cn/t-12641411)(帖子已失效)。
-
-### 2016 年 2 月
-- 我开始汇总一些国内手机品牌的型号,「手机品牌型号汇总」的雏形诞生。
-
-[](https://starchart.cc/KHwang9883/MobileModels)
-
-## 参考资料
-
-- [电信设备终端网](http://zd.taf.org.cn)
-- [产品认证证书查询](http://webdata.cqccms.com.cn/webdata/query/CCCCerti.do)
-- [工业和信息化部政务服务平台](https://ythzxfw.miit.gov.cn/resultQuery)
-- [产品库-中国电信天翼终端信息平台](http://surfing.tydevice.com/)
-- [Google Play 支持的设备](http://storage.googleapis.com/play_public/supported_devices.html)
-- [Wi-Fi Alliance](https://www.wi-fi.org)
-- [Bluetooth Launch Studio](https://launchstudio.bluetooth.com/Listings/Search)
-- [Xiaomi Firmware Updater](https://xiaomifirmwareupdater.com/)
-- [Huawei Open Source Release Center](https://consumer.huawei.com/en/opensource/)
-- [ReaMEIZU](https://reameizu.com/)
-- [The Apple Wiki](https://theapplewiki.com/)
-- [ipsw.me](https://ipsw.me)
-- [XDA Developers](https://www.xda-developers.com)
-- [Huawei Firmware Database](https://pro-teammt.ru/en/online-firmware-database-ru/)
-- [XSMS IMEI 数据库](http://xsms.com.ua/phone/imei/all/1)
-- [Android Dumps](https://dumps.tadiphone.dev/dumps)
-- [Lenovo Android タブレット一覧](https://idomizu.dev/archives/20150)
-
-以及各品牌官网、论坛、微博等,恕不一一列出
-
-## 联系方式
-
-如有相关问题,请 [提交 Issue](https://github.com/KHwang9883/MobileModels/issues)。如有错误或缺漏,欢迎提交 PR。
-
-其他平台同名(@KHwang9883),但不一定回复本 repo 相关问题。
+- [delivery/README.md](delivery/README.md)
+- [delivery/docs/README.md](delivery/docs/README.md)
diff --git a/README_en.md b/README_en.md
index a7f5f4d..d341b0b 100644
--- a/README_en.md
+++ b/README_en.md
@@ -1,85 +1,30 @@
-# Mobile Models
+# MobileModels Workspace
-[](https://github.com/KHwang9883/MobileModels/issues)
-[](https://github.com/KHwang9883/MobileModels/pulls)
-[](https://github.com/KHwang9883/MobileModels)
-[](https://github.com/KHwang9883/MobileModels)
-[](https://creativecommons.org/licenses/by-nc-sa/4.0/)
+This repository is organized into two layers:
-Collecting device names, models and internal codenames.
+- `workspace/`
+ - source workspace
+ - upstream raw data, notes, and historical files
+- `delivery/`
+ - delivery artifact
+ - a ready-to-run Docker Compose project with web UI, MySQL schema, and docs
-[Issue submission](https://github.com/KHwang9883/MobileModels/issues) and [Pull Requests](https://github.com/KHwang9883/MobileModels/pulls) are welcomed if you find mistakes.
+## Usage
-## Web UI
-
-The project ships with device query and data management pages and now runs through `docker compose`:
+Run from the delivery directory:
```bash
+cd delivery
docker compose up --build -d
```
-Open:
+Entry pages:
- `http://127.0.0.1:8123/web/device_query.html`
- `http://127.0.0.1:8123/web/brand_management.html`
+- `http://127.0.0.1:8123/web/device_query.html?view=docs`
-MySQL is started together with the stack:
+More delivery details:
-- host: `127.0.0.1`
-- port: `3306`
-- database: `mobilemodels`
-- reader user: `mobilemodels_reader`
-
-If you want custom MySQL credentials, copy `.env.example` to `.env` before startup.
-Raw source data, rebuilt indexes, and MySQL seed files are persisted in Docker volumes instead of being written back to the local workspace at runtime.
-
-More details: [web/README.md](web/README.md)
-
-Unlisted brands usually not include international models.
-
-| Name | Brand | Range |
-| :-: | :-: | :-: |
-| [apple_all_en](brands/apple_all_en.md) | Apple | iPhone, iPad, iPod touch, Apple Watch, Apple TV and Apple Vision |
-| [asus_en](brands/asus_en.md) | ASUS | ROG Phone, Zenfone |
-| [blackshark_en](brands/blackshark_en.md) | Black Shark | All models |
-| [google](brands/google.md) | Google | Google Pixel phones, tablets & watch |
-| [honor_global_en](brands/honor_global_en.md) | HONOR | All international models |
-| [huawei_global_en](brands/huawei_global_en.md) | HUAWEI | HUAWEI Mate, Pura, nova & Y series, MediaPad & MatePad series |
-| [meizu_en](brands/meizu_en.md) | Meizu | All models |
-| [mitv_global_en](brands/mitv_global_en.md) | Xiaomi | All international/Indian Xiaomi & Redmi TV models (excluding Chinese models) |
-| [nothing](brands/nothing.md) | Nothing | All models |
-| [oneplus_en](brands/oneplus_en.md) | OnePlus | All models |
-| [oppo_global_en](brands/oppo_global_en.md) | OPPO | International models since 2018 |
-| [samsung_global_en](brands/samsung_global_en.md) | Samsung | International models since 2019 |
-| [sony](brands/sony.md) | Sony | All models since 2015 |
-| [realme_global_en](brands/realme_global_en.md) | realme | All international models |
-| [vivo_global_en](brands/vivo_global_en.md) | vivo | International models since 2019 |
-| [xiaomi_en](xiaomi_en.md) | Xiaomi | Xiaomi/Redmi/POCO phones & tablets |
-
-## Changelog
-
-[CHANGELOG_en.md](CHANGELOG_en.md)
-
-## References
-
-- [TENAA](http://zd.taf.org.cn)
-- [CQCCMS](http://webdata.cqccms.com.cn/webdata/query/CCCCerti.do)
-- [MIIT](https://ythzxfw.miit.gov.cn/resultQuery)
-- [China Telecom Tianyi Devices](http://surfing.tydevice.com/)
-- [Google Play Supported Devices](http://storage.googleapis.com/play_public/supported_devices.html)
-- [Wi-Fi Alliance](https://www.wi-fi.org)
-- [Bluetooth Launch Studio](https://launchstudio.bluetooth.com/Listings/Search)
-- [Xiaomi Firmware Updater](https://xiaomifirmwareupdater.com/)
-- [Huawei Open Source Release Center](https://consumer.huawei.com/en/opensource/)
-- [ReaMEIZU](https://reameizu.com/)
-- [The Apple Wiki](https://theapplewiki.com/)
-- [ipsw.me](https://ipsw.me)
-- [XDA Developers](https://www.xda-developers.com)
-- [Huawei Firmware Database](https://pro-teammt.ru/en/online-firmware-database-ru/)
-- [XSMS IMEI Database](http://xsms.com.ua/phone/imei/all/1)
-- [Android Dumps](https://dumps.tadiphone.dev/dumps)
-- [Lenovo Android タブレット一覧](https://idomizu.dev/archives/20150)
-
-## License
-
-
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
+- [delivery/README.md](delivery/README.md)
+- [delivery/docs/README.md](delivery/docs/README.md)
diff --git a/.env.example b/delivery/.env.example
similarity index 100%
rename from .env.example
rename to delivery/.env.example
diff --git a/Dockerfile b/delivery/Dockerfile
similarity index 78%
rename from Dockerfile
rename to delivery/Dockerfile
index b009f63..e97ff9f 100644
--- a/Dockerfile
+++ b/delivery/Dockerfile
@@ -9,7 +9,10 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends git ca-certificates default-mysql-client \
&& rm -rf /var/lib/apt/lists/*
-COPY . /app
+COPY workspace /app/workspace
+COPY delivery /app/delivery
+
+WORKDIR /app/delivery
EXPOSE 8123
diff --git a/delivery/README.md b/delivery/README.md
new file mode 100644
index 0000000..0aade4c
--- /dev/null
+++ b/delivery/README.md
@@ -0,0 +1,98 @@
+# 手机品牌型号汇总
+[](https://creativecommons.org/licenses/by-nc-sa/4.0/)
+
+这是交付目录,提供可直接运行的 Docker Compose 项目。
+
+项目目标:
+
+- 提供可直接交付的设备查询与数据管理系统
+- 通过容器内流程同步上游原始 git 数据
+- 在容器内重建索引并刷新 MySQL
+- 形成可独立部署的交付包
+
+[English](README_en.md)
+
+## 运行方式
+
+在当前目录执行:
+
+```bash
+docker compose up --build -d
+```
+
+打开:
+
+- `http://127.0.0.1:8123/web/device_query.html`
+- `http://127.0.0.1:8123/web/brand_management.html`
+
+MySQL 也会一并启动:
+
+- host: `127.0.0.1`
+- port: `3306`
+- database: `mobilemodels`
+- reader user: `mobilemodels_reader`
+
+如需自定义 MySQL 账号密码,可先复制 `.env.example` 为 `.env` 后再启动。
+
+## 结构说明
+
+```text
+dist/ 构建产物与 MySQL seed
+docs/ 交付文档
+sql/ MySQL schema
+tools/ 容器内构建与同步脚本
+web/ 页面与静态资源
+```
+
+上游原始数据不放在本目录,而是从仓库根目录下的 `workspace/` 读取。
+
+容器启动后会自动完成:
+
+- 初始化 `workspace/` 与 `dist/` 的运行期数据目录
+- 从 `workspace/brands` 构建设备索引
+- 导出 MySQL seed
+- 加载 MySQL schema 与 seed
+- 启动 Web 页面与 API
+
+更多说明参见:
+
+- [docs/README.md](docs/README.md)
+- [docs/web-ui.md](docs/web-ui.md)
+- [docs/mysql-query-design.md](docs/mysql-query-design.md)
+- [docs/device-mapper.md](docs/device-mapper.md)
+## 工作空间
+
+原始数据与补充资料位于仓库根目录下的 `workspace/`:
+
+- `../workspace/brands`
+- `../workspace/misc`
+- `../workspace/CHANGELOG.md`
+- `../workspace/CHANGELOG_en.md`
+
+### 2016 年 3 月
+- 小米手机型号汇总发布至 [小米社区](http://bbs.xiaomi.cn/t-12641411)(帖子已失效)。
+
+### 2016 年 2 月
+- 我开始汇总一些国内手机品牌的型号,「手机品牌型号汇总」的雏形诞生。
+
+## 参考资料
+
+- [电信设备终端网](http://zd.taf.org.cn)
+- [产品认证证书查询](http://webdata.cqccms.com.cn/webdata/query/CCCCerti.do)
+- [工业和信息化部政务服务平台](https://ythzxfw.miit.gov.cn/resultQuery)
+- [产品库-中国电信天翼终端信息平台](http://surfing.tydevice.com/)
+- [Google Play 支持的设备](http://storage.googleapis.com/play_public/supported_devices.html)
+- [Wi-Fi Alliance](https://www.wi-fi.org)
+- [Bluetooth Launch Studio](https://launchstudio.bluetooth.com/Listings/Search)
+- [Xiaomi Firmware Updater](https://xiaomifirmwareupdater.com/)
+- [Huawei Open Source Release Center](https://consumer.huawei.com/en/opensource/)
+- [ReaMEIZU](https://reameizu.com/)
+- [The Apple Wiki](https://theapplewiki.com/)
+- [ipsw.me](https://ipsw.me)
+- [XDA Developers](https://www.xda-developers.com)
+- [Huawei Firmware Database](https://pro-teammt.ru/en/online-firmware-database-ru/)
+- [XSMS IMEI 数据库](http://xsms.com.ua/phone/imei/all/1)
+- [Android Dumps](https://dumps.tadiphone.dev/dumps)
+- [Lenovo Android タブレット一覧](https://idomizu.dev/archives/20150)
+
+以及各品牌官网、论坛、微博等,恕不一一列出
diff --git a/delivery/README_en.md b/delivery/README_en.md
new file mode 100644
index 0000000..7b80f0c
--- /dev/null
+++ b/delivery/README_en.md
@@ -0,0 +1,61 @@
+# Mobile Models
+[](https://creativecommons.org/licenses/by-nc-sa/4.0/)
+
+This is the delivery directory and contains the ready-to-run Docker Compose project.
+
+Project goals:
+
+- provide a ready-to-deliver device query system
+- sync upstream raw git data inside containers
+- rebuild index and refresh MySQL inside containers
+- keep deployment content independent from workspace files
+
+## Run
+
+The project ships with device query and data management pages and now runs through `docker compose`:
+
+```bash
+docker compose up --build -d
+```
+
+Open:
+
+- `http://127.0.0.1:8123/web/device_query.html`
+- `http://127.0.0.1:8123/web/brand_management.html`
+
+MySQL is started together with the stack:
+
+- host: `127.0.0.1`
+- port: `3306`
+- database: `mobilemodels`
+- reader user: `mobilemodels_reader`
+
+If you want custom MySQL credentials, copy `.env.example` to `.env` before startup.
+
+## Structure
+
+```text
+dist/ build outputs and MySQL seed
+docs/ delivery docs
+sql/ MySQL schema
+tools/ container-side build and sync scripts
+web/ delivered web pages
+```
+
+Raw source files are read from the repository root `workspace/` directory.
+
+More details:
+
+- [docs/README.md](docs/README.md)
+- [docs/web-ui.md](docs/web-ui.md)
+- [docs/mysql-query-design.md](docs/mysql-query-design.md)
+- [docs/device-mapper.md](docs/device-mapper.md)
+
+## Workspace
+
+Raw data and historical files live under the repository root `workspace/`:
+
+- `../workspace/brands`
+- `../workspace/misc`
+- `../workspace/CHANGELOG.md`
+- `../workspace/CHANGELOG_en.md`
diff --git a/dist/device_index.json b/delivery/dist/device_index.json
similarity index 100%
rename from dist/device_index.json
rename to delivery/dist/device_index.json
diff --git a/dist/mobilemodels_mysql_seed.sql b/delivery/dist/mobilemodels_mysql_seed.sql
similarity index 100%
rename from dist/mobilemodels_mysql_seed.sql
rename to delivery/dist/mobilemodels_mysql_seed.sql
diff --git a/docker-compose.yml b/delivery/docker-compose.yml
similarity index 94%
rename from docker-compose.yml
rename to delivery/docker-compose.yml
index 4dd3c33..daf7858 100644
--- a/docker-compose.yml
+++ b/delivery/docker-compose.yml
@@ -23,10 +23,10 @@ services:
mobilemodels:
build:
- context: .
- dockerfile: Dockerfile
+ context: ..
+ dockerfile: delivery/Dockerfile
container_name: mobilemodels-web
- working_dir: /app
+ working_dir: /app/delivery
environment:
MOBILEMODELS_DATA_ROOT: /data
MYSQL_HOST: mysql
diff --git a/delivery/docs/README.md b/delivery/docs/README.md
new file mode 100644
index 0000000..24ac2c8
--- /dev/null
+++ b/delivery/docs/README.md
@@ -0,0 +1,18 @@
+# 项目文档
+
+交付版文档统一收敛到本目录,便于部署、培训和对外交付。
+
+## 文档索引
+
+- [部署与使用说明](web-ui.md)
+- [MySQL 设计说明](mysql-query-design.md)
+- [索引构建与设备映射说明](device-mapper.md)
+
+## 目录说明
+
+- `web-ui.md`
+ - Docker Compose 启动、页面入口、MySQL 连接和管理能力说明
+- `mysql-query-design.md`
+ - 主表设计、兼容视图、推荐查询方式
+- `device-mapper.md`
+ - `dist/device_index.json` 构建方式与索引字段说明
diff --git a/delivery/docs/device-mapper.md b/delivery/docs/device-mapper.md
new file mode 100644
index 0000000..174e536
--- /dev/null
+++ b/delivery/docs/device-mapper.md
@@ -0,0 +1,57 @@
+# Device Mapper Usage
+
+This tool builds a cross-platform lookup index from `workspace/brands/*.md`.
+
+## 1) Build index
+
+```bash
+python3 tools/device_mapper.py build
+```
+
+Output file: `dist/device_index.json`
+
+## 2) Query from command line
+
+```bash
+python3 tools/device_mapper.py find --name 'iPhone14,5' --brand Apple
+python3 tools/device_mapper.py find --name 'M2102J2SC' --brand Xiaomi
+python3 tools/device_mapper.py find --name 'L55M5-AD' --brand Xiaomi
+```
+
+## 3) JSON structure
+
+- `records`: normalized device records
+ - `device_name`: standard marketing name
+ - `brand`: normalized brand
+ - `manufacturer_brand`: manufacturer-level brand
+ - `market_brand`: market sub-brand
+ - `device_type`: `phone | tablet | wear | tv | other`
+ - `aliases`: all searchable aliases
+- `lookup`: normalized alias -> candidate `record.id[]`
+- `brand_aliases`: normalized brand aliases to filter by app-provided brand
+- `brand_management`: brand governance metadata
+
+## 4) App-side integration
+
+1. Load `dist/device_index.json` into memory.
+2. Normalize input `name` and optional `brand`.
+3. Use `lookup[normalized_name]` to fetch candidate records.
+4. Normalize brand via `brand_management`.
+5. Filter records by normalized manufacturer or market brand when needed.
+6. Return first candidate or all candidates.
+
+Normalization rule:
+
+- lower-case
+- keep only `[0-9a-z\u4e00-\u9fff]`
+- remove spaces, hyphens, underscores and punctuation
+
+## 5) Device type mapping
+
+Supported categories:
+
+- `phone`
+- `tablet`
+- `wear`
+- `tv`
+- `other`
diff --git a/delivery/docs/mysql-query-design.md b/delivery/docs/mysql-query-design.md
new file mode 100644
index 0000000..aa7cc44
--- /dev/null
+++ b/delivery/docs/mysql-query-design.md
@@ -0,0 +1,142 @@
+# MySQL 设计说明
+
+本文档说明交付版 MobileModels 的 MySQL 数据组织方式、兼容层设计与推荐查询方式。
+
+## 设计目标
+
+- 所有设备标识都能落到 MySQL 查询
+- 支持第三方直接查库,保证查询速度
+- 保留兼容旧结构的访问方式
+- 页面侧和 SQL 接入侧统一使用同一份设备数据
+
+## 主表
+
+主推物理表:
+
+```sql
+mobilemodels.mm_device_catalog
+```
+
+主表整合了设备型号、品牌、厂商、来源、别名归一化结果和兼容字段,适合作为统一查询入口。
+
+### 关键字段
+
+- `model`
+- `record_id`
+- `alias_norm`
+- `device_name`
+- `brand`
+- `manufacturer_brand`
+- `parent_brand`
+- `market_brand`
+- `device_type`
+- `source_file`
+- `section`
+- `source_rank`
+- `source_weight`
+- `code`
+- `code_alias`
+- `ver_name`
+
+## 推荐查询方式
+
+### 1. 第三方直接查主表
+
+推荐按 `alias_norm` 等值查询:
+
+```sql
+SELECT
+ model,
+ record_id,
+ alias_norm,
+ device_name,
+ brand,
+ manufacturer_brand,
+ parent_brand,
+ market_brand,
+ device_type,
+ source_file,
+ section,
+ source_rank,
+ source_weight,
+ code,
+ code_alias,
+ ver_name
+FROM mobilemodels.mm_device_catalog
+WHERE alias_norm = ?
+ORDER BY source_rank ASC, record_id ASC
+LIMIT 20;
+```
+
+### 2. 页面 SQL 查询
+
+页面的 `SQL 查询` tab 也是基于这张主表。
+
+查询流程:
+
+1. 接收客户端原始上报值
+2. 服务端归一化为 `alias_norm`
+3. 按主表等值查询
+4. 返回结果列表、执行 SQL 和 JSON 输出
+
+## 兼容视图
+
+为了兼容旧系统,当前仍保留以下视图:
+
+```sql
+mobilemodels.mm_device_lookup
+mobilemodels.mm_device_record
+mobilemodels.models
+python_services_test.models
+```
+
+其中旧结构 `python_services_test.models` 主要用于兼容既有查询逻辑,不再作为主推接入方式。
+
+## 兼容旧结构查询示例
+
+```sql
+SELECT
+ model,
+ dtype,
+ brand,
+ brand_title,
+ code,
+ code_alias,
+ model_name,
+ ver_name
+FROM python_services_test.models
+WHERE model = ?
+LIMIT 20;
+```
+
+## 归一化规则
+
+`alias_norm` 统一按以下规则生成:
+
+- 全部转小写
+- 仅保留 `[0-9a-z中文]`
+- 去掉空格、横线、下划线和其他标点
+
+示例:
+
+```text
+SM-G9980 -> smg9980
+iPhone14,2 -> iphone142
+NOH-AL00 -> nohal00
+```
+
+## 数据来源
+
+主表和索引数据均由以下流程生成:
+
+1. 同步上游原始 markdown 数据
+2. 解析 `workspace/brands/*.md`
+3. 构建 `dist/device_index.json`
+4. 导出 `dist/mobilemodels_mysql_seed.sql`
+5. 加载 MySQL schema 与 seed
+
+## 交付建议
+
+- 第三方新接入优先使用 `mm_device_catalog`
+- 页面联调和数据库联调使用同一套原始数据与归一化规则
+- 生产环境务必替换默认数据库密码
diff --git a/delivery/docs/web-ui.md b/delivery/docs/web-ui.md
new file mode 100644
index 0000000..c2f1778
--- /dev/null
+++ b/delivery/docs/web-ui.md
@@ -0,0 +1,101 @@
+# Web UI
+
+## 启动方式
+
+在 `delivery/` 目录执行:
+
+```bash
+docker compose up --build -d
+```
+
+如需自定义环境变量:
+
+```bash
+cp .env.example .env
+```
+
+停止服务:
+
+```bash
+docker compose down
+```
+
+重置 MySQL 和运行期数据:
+
+```bash
+docker compose down -v
+```
+
+## 页面入口
+
+- `http://127.0.0.1:8123/web/device_query.html`:设备查询
+- `http://127.0.0.1:8123/web/brand_management.html`:数据管理
+- `http://127.0.0.1:8123/web/device_query.html?view=docs`:相关文档
+
+整个功能栈统一运行在 Docker Compose 中,不再依赖本地 Python 或本地 MySQL。
+
+原始数据工作空间位于仓库根目录下的 `workspace/`,交付物位于 `delivery/`。
+
+## 启动后自动完成的动作
+
+- 从 `workspace/brands` 构建设备索引
+- 生成 `dist/device_index.json`
+- 导出 MySQL seed 文件
+- 加载 MySQL schema 与 seed 数据
+- 启动 Web 页面与 API 服务
+
+## MySQL 默认连接
+
+- Host: `127.0.0.1`
+- Port: `3306`
+- Database: `mobilemodels`
+- Reader User: `mobilemodels_reader`
+
+如需自定义账号密码,请使用 `.env` 覆盖默认值。
+
+## 设备查询
+
+页面顶部统一提供三个导航入口:
+
+- `设备查询`
+- `数据管理`
+- `相关文档`
+
+设备查询页顶部包含两个页内 tab:
+
+- `SQL 查询`
+- `索引查询`
+
+### SQL 查询
+
+- 直接调用 Compose 内 API 查询 MySQL 主表 `mobilemodels.mm_device_catalog`
+- 服务端先将输入归一化为 `alias_norm`
+- 页面展示实际执行的 SQL、返回结果和 JSON
+- 页面同时展示只读连接信息,便于第三方联调
+
+### 索引查询
+
+- 基于 `dist/device_index.json` 内存索引进行快速识别
+- 适合前端联调、接口对比和结果核验
+
+### 平台输入建议
+
+- Android / iOS / HarmonyOS:直接使用客户端原始上报的 `model_raw`
+- 输入框会根据所选平台自动提供示例值
+- 未输入时,系统会使用当前平台的默认示例值发起查询
+
+## 数据管理
+
+数据管理页支持:
+
+- 品牌列表管理
+- 品牌与厂商关系管理
+- 品牌同义词管理
+- 数据来源优先级管理
+- 原始数据同步
+- 索引数据查看与重新加载
+
+## 说明
+
+- 原始数据、索引和 MySQL seed 运行时持久化在 Docker volume 中,不回写本地工作区
+- 交付环境建议覆盖默认的 `MYSQL_ROOT_PASSWORD` 和 `MYSQL_READER_PASSWORD`
diff --git a/sql/mobilemodels_mysql_schema.sql b/delivery/sql/mobilemodels_mysql_schema.sql
similarity index 100%
rename from sql/mobilemodels_mysql_schema.sql
rename to delivery/sql/mobilemodels_mysql_schema.sql
diff --git a/tools/container_start.sh b/delivery/tools/container_start.sh
similarity index 92%
rename from tools/container_start.sh
rename to delivery/tools/container_start.sh
index 3eeb330..c9f23ac 100644
--- a/tools/container_start.sh
+++ b/delivery/tools/container_start.sh
@@ -1,7 +1,7 @@
#!/bin/sh
set -eu
-cd /app
+cd /app/delivery
sh tools/init_runtime_data.sh
diff --git a/tools/device_mapper.py b/delivery/tools/device_mapper.py
similarity index 99%
rename from tools/device_mapper.py
rename to delivery/tools/device_mapper.py
index df4b93d..27259ac 100644
--- a/tools/device_mapper.py
+++ b/delivery/tools/device_mapper.py
@@ -12,6 +12,8 @@ from datetime import date
from pathlib import Path
from typing import Dict, Iterable, List, Optional, Set
+from project_layout import DELIVERY_ROOT, WORKSPACE_ROOT
+
ENTRY_RE = re.compile(r"^\*\*(.+?)\*\*\s*$")
VARIANT_RE = re.compile(r"^\s*((?:`[^`]+`\s*)+):\s*(.+?)\s*$")
BACKTICK_RE = re.compile(r"`([^`]+)`")
@@ -714,8 +716,8 @@ def main() -> None:
parser.add_argument(
"--repo-root",
type=Path,
- default=Path(__file__).resolve().parents[1],
- help="Path to MobileModels repository root",
+ default=WORKSPACE_ROOT,
+ help="Path to workspace root",
)
subparsers = parser.add_subparsers(dest="command", required=True)
@@ -741,7 +743,7 @@ def main() -> None:
if args.command == "build":
output_path: Path = args.output
if not output_path.is_absolute():
- output_path = args.repo_root / output_path
+ output_path = DELIVERY_ROOT / output_path
export_index(records, output_path)
print(f"Built index: {output_path}")
print(f"Total records: {len(records)}")
diff --git a/tools/export_mysql_seed.py b/delivery/tools/export_mysql_seed.py
similarity index 98%
rename from tools/export_mysql_seed.py
rename to delivery/tools/export_mysql_seed.py
index 5f1d02e..f3a81bb 100644
--- a/tools/export_mysql_seed.py
+++ b/delivery/tools/export_mysql_seed.py
@@ -16,9 +16,9 @@ from device_mapper import (
normalize_text,
resolve_parent_brand,
)
+from project_layout import DELIVERY_ROOT, WORKSPACE_ROOT
-REPO_ROOT = Path(__file__).resolve().parent.parent
LEGACY_CODE_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9,._/+\\-]{1,63}$")
@@ -185,8 +185,8 @@ def parse_args() -> argparse.Namespace:
parser.add_argument(
"--repo-root",
type=Path,
- default=REPO_ROOT,
- help="Path to MobileModels repository root",
+ default=WORKSPACE_ROOT,
+ help="Path to workspace root",
)
parser.add_argument(
"--output",
@@ -200,7 +200,7 @@ def parse_args() -> argparse.Namespace:
def main() -> int:
args = parse_args()
repo_root = args.repo_root.resolve()
- output_path = args.output if args.output.is_absolute() else repo_root / args.output
+ output_path = args.output if args.output.is_absolute() else DELIVERY_ROOT / args.output
records = build_records(repo_root)
device_record_count = len(records)
diff --git a/tools/init_runtime_data.sh b/delivery/tools/init_runtime_data.sh
similarity index 92%
rename from tools/init_runtime_data.sh
rename to delivery/tools/init_runtime_data.sh
index 66e30a5..509f6e6 100644
--- a/tools/init_runtime_data.sh
+++ b/delivery/tools/init_runtime_data.sh
@@ -60,14 +60,8 @@ init_path() {
}
for rel_path in \
- brands \
- misc \
- dist \
- README.md \
- README_en.md \
- CHANGELOG.md \
- CHANGELOG_en.md \
- LICENSE.txt
+ workspace \
+ delivery/dist
do
init_path "$rel_path"
done
diff --git a/tools/load_mysql_seed.py b/delivery/tools/load_mysql_seed.py
similarity index 97%
rename from tools/load_mysql_seed.py
rename to delivery/tools/load_mysql_seed.py
index c6eabc9..9c71034 100644
--- a/tools/load_mysql_seed.py
+++ b/delivery/tools/load_mysql_seed.py
@@ -10,8 +10,7 @@ import sys
import time
from pathlib import Path
-
-REPO_ROOT = Path(__file__).resolve().parent.parent
+from project_layout import DELIVERY_ROOT
def mysql_env(password: str) -> dict[str, str]:
@@ -131,8 +130,8 @@ def parse_args() -> argparse.Namespace:
def main() -> int:
args = parse_args()
- schema_path = args.schema if args.schema.is_absolute() else REPO_ROOT / args.schema
- seed_path = args.seed if args.seed.is_absolute() else REPO_ROOT / args.seed
+ schema_path = args.schema if args.schema.is_absolute() else DELIVERY_ROOT / args.schema
+ seed_path = args.seed if args.seed.is_absolute() else DELIVERY_ROOT / args.seed
wait_for_mysql(args.user, args.password, args.host, args.port, args.wait_timeout)
diff --git a/delivery/tools/project_layout.py b/delivery/tools/project_layout.py
new file mode 100644
index 0000000..a785688
--- /dev/null
+++ b/delivery/tools/project_layout.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+"""Shared path helpers for the workspace/delivery project layout."""
+
+from __future__ import annotations
+
+from pathlib import Path
+
+
+DELIVERY_ROOT = Path(__file__).resolve().parent.parent
+PROJECT_ROOT = DELIVERY_ROOT.parent
+WORKSPACE_ROOT = PROJECT_ROOT / "workspace"
diff --git a/tools/sync_upstream_mobilemodels.py b/delivery/tools/sync_upstream_mobilemodels.py
similarity index 89%
rename from tools/sync_upstream_mobilemodels.py
rename to delivery/tools/sync_upstream_mobilemodels.py
index 7815227..56adcd3 100644
--- a/tools/sync_upstream_mobilemodels.py
+++ b/delivery/tools/sync_upstream_mobilemodels.py
@@ -11,15 +11,13 @@ import sys
import tempfile
from pathlib import Path
+from project_layout import DELIVERY_ROOT, PROJECT_ROOT, WORKSPACE_ROOT
-REPO_ROOT = Path(__file__).resolve().parent.parent
DEFAULT_REPO_URL = "https://github.com/KHwang9883/MobileModels.git"
DEFAULT_BRANCH = "master"
SYNC_PATHS = [
"brands",
"misc",
- "README.md",
- "README_en.md",
"CHANGELOG.md",
"CHANGELOG_en.md",
"LICENSE.txt",
@@ -27,7 +25,7 @@ SYNC_PATHS = [
def run(cmd: list[str], cwd: Path | None = None) -> None:
- subprocess.run(cmd, cwd=cwd or REPO_ROOT, check=True)
+ subprocess.run(cmd, cwd=cwd or PROJECT_ROOT, check=True)
def remove_path(path: Path) -> None:
@@ -59,7 +57,7 @@ def sync_path(src: Path, dst: Path) -> None:
def sync_selected_paths(upstream_root: Path) -> None:
for relative_path in SYNC_PATHS:
src = upstream_root / relative_path
- dst = REPO_ROOT / relative_path
+ dst = WORKSPACE_ROOT / relative_path
if not src.exists():
raise FileNotFoundError(f"Missing upstream path: {relative_path}")
sync_path(src, dst)
@@ -69,7 +67,9 @@ def build_index(output_path: str) -> None:
run(
[
sys.executable,
- str(REPO_ROOT / "tools/device_mapper.py"),
+ str(DELIVERY_ROOT / "tools/device_mapper.py"),
+ "--repo-root",
+ str(WORKSPACE_ROOT),
"build",
"--output",
output_path,
@@ -81,9 +81,11 @@ def export_mysql_seed(output_path: str) -> None:
run(
[
sys.executable,
- str(REPO_ROOT / "tools/export_mysql_seed.py"),
+ str(DELIVERY_ROOT / "tools/export_mysql_seed.py"),
"--output",
output_path,
+ "--repo-root",
+ str(WORKSPACE_ROOT),
]
)
@@ -92,7 +94,7 @@ def load_mysql_seed(seed_path: str) -> None:
run(
[
sys.executable,
- str(REPO_ROOT / "tools/load_mysql_seed.py"),
+ str(DELIVERY_ROOT / "tools/load_mysql_seed.py"),
"--seed",
seed_path,
]
diff --git a/tools/web_server.py b/delivery/tools/web_server.py
similarity index 92%
rename from tools/web_server.py
rename to delivery/tools/web_server.py
index 2d42086..f2863c7 100644
--- a/tools/web_server.py
+++ b/delivery/tools/web_server.py
@@ -14,13 +14,14 @@ from http import HTTPStatus
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
-from sync_upstream_mobilemodels import DEFAULT_BRANCH, DEFAULT_REPO_URL, REPO_ROOT
+from project_layout import DELIVERY_ROOT, PROJECT_ROOT, WORKSPACE_ROOT
+from sync_upstream_mobilemodels import DEFAULT_BRANCH, DEFAULT_REPO_URL
-SYNC_SCRIPT = REPO_ROOT / "tools/sync_upstream_mobilemodels.py"
-INDEX_PATH = REPO_ROOT / "dist/device_index.json"
-MYSQL_SEED_PATH = REPO_ROOT / "dist/mobilemodels_mysql_seed.sql"
-MYSQL_LOADER = REPO_ROOT / "tools/load_mysql_seed.py"
+SYNC_SCRIPT = DELIVERY_ROOT / "tools/sync_upstream_mobilemodels.py"
+INDEX_PATH = DELIVERY_ROOT / "dist/device_index.json"
+MYSQL_SEED_PATH = DELIVERY_ROOT / "dist/mobilemodels_mysql_seed.sql"
+MYSQL_LOADER = DELIVERY_ROOT / "tools/load_mysql_seed.py"
DATA_ROOT = Path(os.environ.get("MOBILEMODELS_DATA_ROOT", "/data"))
SYNC_METADATA_PATH = DATA_ROOT / "state/sync_status.json"
SYNC_LOCK = threading.Lock()
@@ -30,7 +31,7 @@ NORMALIZE_RE = re.compile(r"[^0-9a-z\u4e00-\u9fff]+")
def run_command(args: list[str]) -> subprocess.CompletedProcess[str]:
return subprocess.run(
args,
- cwd=REPO_ROOT,
+ cwd=PROJECT_ROOT,
text=True,
capture_output=True,
check=False,
@@ -192,15 +193,17 @@ def get_status_payload() -> dict[str, object]:
return {
"supports_upstream_sync": True,
"storage_mode": "docker_volume",
- "repo_root": str(REPO_ROOT),
+ "project_root": str(PROJECT_ROOT),
+ "workspace_root": str(WORKSPACE_ROOT),
+ "delivery_root": str(DELIVERY_ROOT),
"data_root": str(DATA_ROOT),
"upstream_repo_url": DEFAULT_REPO_URL,
"upstream_branch": DEFAULT_BRANCH,
"last_sync_time": sync_metadata.get("last_sync_time"),
"last_upstream_commit": sync_metadata.get("last_upstream_commit"),
- "index_file": str(INDEX_PATH.relative_to(REPO_ROOT)),
+ "index_file": str(INDEX_PATH.relative_to(DELIVERY_ROOT)),
"index_mtime": index_mtime,
- "mysql_seed_file": str(MYSQL_SEED_PATH.relative_to(REPO_ROOT)),
+ "mysql_seed_file": str(MYSQL_SEED_PATH.relative_to(DELIVERY_ROOT)),
"mysql_seed_mtime": mysql_seed_mtime,
"mysql_host": mysql_host,
"mysql_port": mysql_port,
@@ -240,18 +243,20 @@ def run_upstream_sync() -> dict[str, object]:
payload = {
"storage_mode": "docker_volume",
- "repo_root": str(REPO_ROOT),
+ "project_root": str(PROJECT_ROOT),
+ "workspace_root": str(WORKSPACE_ROOT),
+ "delivery_root": str(DELIVERY_ROOT),
"data_root": str(DATA_ROOT),
"upstream_repo_url": DEFAULT_REPO_URL,
"upstream_branch": DEFAULT_BRANCH,
"upstream_commit": upstream_commit,
"last_sync_time": datetime.now().isoformat(timespec="seconds"),
"last_upstream_commit": upstream_commit,
- "index_file": str(INDEX_PATH.relative_to(REPO_ROOT)),
+ "index_file": str(INDEX_PATH.relative_to(DELIVERY_ROOT)),
"index_mtime": datetime.fromtimestamp(INDEX_PATH.stat().st_mtime).isoformat(timespec="seconds")
if INDEX_PATH.exists()
else None,
- "mysql_seed_file": str(MYSQL_SEED_PATH.relative_to(REPO_ROOT)),
+ "mysql_seed_file": str(MYSQL_SEED_PATH.relative_to(DELIVERY_ROOT)),
"mysql_seed_mtime": datetime.fromtimestamp(MYSQL_SEED_PATH.stat().st_mtime).isoformat(timespec="seconds")
if MYSQL_SEED_PATH.exists()
else None,
@@ -270,7 +275,7 @@ def run_upstream_sync() -> dict[str, object]:
class MobileModelsHandler(SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
- super().__init__(*args, directory=str(REPO_ROOT), **kwargs)
+ super().__init__(*args, directory=str(DELIVERY_ROOT), **kwargs)
def guess_type(self, path: str) -> str:
content_type = super().guess_type(path)
diff --git a/web/brand_management.html b/delivery/web/brand_management.html
similarity index 99%
rename from web/brand_management.html
rename to delivery/web/brand_management.html
index ecdaee7..104474c 100644
--- a/web/brand_management.html
+++ b/delivery/web/brand_management.html
@@ -518,7 +518,9 @@
const lines = [];
if (fallbackTitle) lines.push(fallbackTitle);
if (data.data_root) lines.push(`数据目录: ${data.data_root}`);
- if (data.repo_root) lines.push(`应用目录: ${data.repo_root}`);
+ if (data.project_root) lines.push(`项目目录: ${data.project_root}`);
+ if (data.workspace_root) lines.push(`工作空间目录: ${data.workspace_root}`);
+ if (data.delivery_root) lines.push(`交付目录: ${data.delivery_root}`);
if (data.storage_mode) lines.push(`存储模式: ${data.storage_mode}`);
if (data.upstream_repo_url) lines.push(`上游仓库: ${data.upstream_repo_url}`);
if (data.upstream_branch) lines.push(`上游分支: ${data.upstream_branch}`);
diff --git a/web/device_query.html b/delivery/web/device_query.html
similarity index 99%
rename from web/device_query.html
rename to delivery/web/device_query.html
index 559aa5c..b3bced6 100644
--- a/web/device_query.html
+++ b/delivery/web/device_query.html
@@ -694,15 +694,15 @@
这里统一整理页面调试、MySQL 接入和兼容查询相关说明,直接在当前页面查看,不再跳转到单独页面。
/misc/mysql-query-design.md
+/docs/mysql-query-design.md
加载中...