From 74e50a2b307269ff17b3dc2a40a6a5a850153d67 Mon Sep 17 00:00:00 2001 From: yuanzhen869 Date: Thu, 19 Mar 2026 13:00:40 +0800 Subject: [PATCH] refactor: split workspace and delivery layout --- .dockerignore | 1 + .github/workflows/daily-sync-upstream.yml | 49 --- .gitignore | 2 + README.md | 162 +------- README_en.md | 87 +--- .env.example => delivery/.env.example | 0 Dockerfile => delivery/Dockerfile | 5 +- delivery/README.md | 98 +++++ delivery/README_en.md | 61 +++ {dist => delivery/dist}/device_index.json | 0 .../dist}/mobilemodels_mysql_seed.sql | 0 .../docker-compose.yml | 6 +- delivery/docs/README.md | 18 + delivery/docs/device-mapper.md | 57 +++ delivery/docs/mysql-query-design.md | 142 +++++++ delivery/docs/web-ui.md | 101 +++++ .../sql}/mobilemodels_mysql_schema.sql | 0 {tools => delivery/tools}/container_start.sh | 2 +- {tools => delivery/tools}/device_mapper.py | 8 +- .../tools}/export_mysql_seed.py | 8 +- .../tools}/init_runtime_data.sh | 10 +- {tools => delivery/tools}/load_mysql_seed.py | 7 +- delivery/tools/project_layout.py | 11 + .../tools}/sync_upstream_mobilemodels.py | 18 +- {tools => delivery/tools}/web_server.py | 31 +- {web => delivery/web}/brand_management.html | 4 +- {web => delivery/web}/device_query.html | 8 +- {web => delivery/web}/doc_viewer.html | 10 +- misc/mysql-query-design.md | 372 ------------------ tools/DEVICE_MAPPER_USAGE.md | 66 ---- web/README.md | 140 ------- CHANGELOG.md => workspace/CHANGELOG.md | 0 CHANGELOG_en.md => workspace/CHANGELOG_en.md | 0 LICENSE.txt => workspace/LICENSE.txt | 0 {brands => workspace/brands}/360shouji.md | 0 {brands => workspace/brands}/apple_all.md | 0 {brands => workspace/brands}/apple_all_en.md | 0 {brands => workspace/brands}/apple_cn.md | 0 {brands => workspace/brands}/asus_cn.md | 0 {brands => workspace/brands}/asus_en.md | 0 {brands => workspace/brands}/blackshark.md | 0 {brands => workspace/brands}/blackshark_en.md | 0 {brands => workspace/brands}/coolpad.md | 0 {brands => workspace/brands}/google.md | 0 {brands => workspace/brands}/honor_cn.md | 0 .../brands}/honor_global_en.md | 0 {brands => workspace/brands}/huawei_cn.md | 0 .../brands}/huawei_global_en.md | 0 {brands => workspace/brands}/lenovo_cn.md | 0 {brands => workspace/brands}/letv.md | 0 {brands => workspace/brands}/meizu.md | 0 {brands => workspace/brands}/meizu_en.md | 0 {brands => workspace/brands}/mitv_cn.md | 0 .../brands}/mitv_global_en.md | 0 {brands => workspace/brands}/motorola_cn.md | 0 {brands => workspace/brands}/nokia_cn.md | 0 {brands => workspace/brands}/nothing.md | 0 {brands => workspace/brands}/nubia.md | 0 {brands => workspace/brands}/oneplus.md | 0 {brands => workspace/brands}/oneplus_en.md | 0 {brands => workspace/brands}/oppo_cn.md | 0 .../brands}/oppo_global_en.md | 0 {brands => workspace/brands}/realme_cn.md | 0 .../brands}/realme_global_en.md | 0 {brands => workspace/brands}/samsung_cn.md | 0 .../brands}/samsung_global_en.md | 0 {brands => workspace/brands}/smartisan.md | 0 {brands => workspace/brands}/sony.md | 0 {brands => workspace/brands}/sony_cn.md | 0 {brands => workspace/brands}/vivo_cn.md | 0 .../brands}/vivo_global_en.md | 4 +- {brands => workspace/brands}/xiaomi-wear.md | 0 {brands => workspace/brands}/xiaomi.md | 0 {brands => workspace/brands}/xiaomi_cn.md | 0 {brands => workspace/brands}/xiaomi_en.md | 0 {brands => workspace/brands}/zhixuan.md | 0 {brands => workspace/brands}/zte_cn.md | 0 .../misc}/bootloader-kernel-source.md | 0 .../misc}/early-huawei-models.md | 0 .../misc}/early-samsung-models.md | 0 {misc => workspace/misc}/naming-rules.md | 0 ...ral-xiaomi-codenames-unreleased-devices.md | 0 .../misc}/xiaomi-book-internal-names.md | 0 83 files changed, 592 insertions(+), 896 deletions(-) delete mode 100644 .github/workflows/daily-sync-upstream.yml create mode 100644 .gitignore rename .env.example => delivery/.env.example (100%) rename Dockerfile => delivery/Dockerfile (78%) create mode 100644 delivery/README.md create mode 100644 delivery/README_en.md rename {dist => delivery/dist}/device_index.json (100%) rename {dist => delivery/dist}/mobilemodels_mysql_seed.sql (100%) rename docker-compose.yml => delivery/docker-compose.yml (94%) create mode 100644 delivery/docs/README.md create mode 100644 delivery/docs/device-mapper.md create mode 100644 delivery/docs/mysql-query-design.md create mode 100644 delivery/docs/web-ui.md rename {sql => delivery/sql}/mobilemodels_mysql_schema.sql (100%) rename {tools => delivery/tools}/container_start.sh (92%) rename {tools => delivery/tools}/device_mapper.py (99%) rename {tools => delivery/tools}/export_mysql_seed.py (98%) rename {tools => delivery/tools}/init_runtime_data.sh (92%) rename {tools => delivery/tools}/load_mysql_seed.py (97%) create mode 100644 delivery/tools/project_layout.py rename {tools => delivery/tools}/sync_upstream_mobilemodels.py (89%) rename {tools => delivery/tools}/web_server.py (92%) rename {web => delivery/web}/brand_management.html (99%) rename {web => delivery/web}/device_query.html (99%) rename {web => delivery/web}/doc_viewer.html (92%) delete mode 100644 misc/mysql-query-design.md delete mode 100644 tools/DEVICE_MAPPER_USAGE.md delete mode 100644 web/README.md rename CHANGELOG.md => workspace/CHANGELOG.md (100%) rename CHANGELOG_en.md => workspace/CHANGELOG_en.md (100%) rename LICENSE.txt => workspace/LICENSE.txt (100%) rename {brands => workspace/brands}/360shouji.md (100%) rename {brands => workspace/brands}/apple_all.md (100%) rename {brands => workspace/brands}/apple_all_en.md (100%) rename {brands => workspace/brands}/apple_cn.md (100%) rename {brands => workspace/brands}/asus_cn.md (100%) rename {brands => workspace/brands}/asus_en.md (100%) rename {brands => workspace/brands}/blackshark.md (100%) rename {brands => workspace/brands}/blackshark_en.md (100%) rename {brands => workspace/brands}/coolpad.md (100%) rename {brands => workspace/brands}/google.md (100%) rename {brands => workspace/brands}/honor_cn.md (100%) rename {brands => workspace/brands}/honor_global_en.md (100%) rename {brands => workspace/brands}/huawei_cn.md (100%) rename {brands => workspace/brands}/huawei_global_en.md (100%) rename {brands => workspace/brands}/lenovo_cn.md (100%) rename {brands => workspace/brands}/letv.md (100%) rename {brands => workspace/brands}/meizu.md (100%) rename {brands => workspace/brands}/meizu_en.md (100%) rename {brands => workspace/brands}/mitv_cn.md (100%) rename {brands => workspace/brands}/mitv_global_en.md (100%) rename {brands => workspace/brands}/motorola_cn.md (100%) rename {brands => workspace/brands}/nokia_cn.md (100%) rename {brands => workspace/brands}/nothing.md (100%) rename {brands => workspace/brands}/nubia.md (100%) rename {brands => workspace/brands}/oneplus.md (100%) rename {brands => workspace/brands}/oneplus_en.md (100%) rename {brands => workspace/brands}/oppo_cn.md (100%) rename {brands => workspace/brands}/oppo_global_en.md (100%) rename {brands => workspace/brands}/realme_cn.md (100%) rename {brands => workspace/brands}/realme_global_en.md (100%) rename {brands => workspace/brands}/samsung_cn.md (100%) rename {brands => workspace/brands}/samsung_global_en.md (100%) rename {brands => workspace/brands}/smartisan.md (100%) rename {brands => workspace/brands}/sony.md (100%) rename {brands => workspace/brands}/sony_cn.md (100%) rename {brands => workspace/brands}/vivo_cn.md (100%) rename {brands => workspace/brands}/vivo_global_en.md (99%) rename {brands => workspace/brands}/xiaomi-wear.md (100%) rename {brands => workspace/brands}/xiaomi.md (100%) rename {brands => workspace/brands}/xiaomi_cn.md (100%) rename {brands => workspace/brands}/xiaomi_en.md (100%) rename {brands => workspace/brands}/zhixuan.md (100%) rename {brands => workspace/brands}/zte_cn.md (100%) rename {misc => workspace/misc}/bootloader-kernel-source.md (100%) rename {misc => workspace/misc}/early-huawei-models.md (100%) rename {misc => workspace/misc}/early-samsung-models.md (100%) rename {misc => workspace/misc}/naming-rules.md (100%) rename {misc => workspace/misc}/several-xiaomi-codenames-unreleased-devices.md (100%) rename {misc => workspace/misc}/xiaomi-book-internal-names.md (100%) 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 -[![issues](https://img.shields.io/github/issues/KHwang9883/MobileModels?color=green)](https://github.com/KHwang9883/MobileModels/issues) -[![prs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/KHwang9883/MobileModels/pulls) -[![stars](https://img.shields.io/github/stars/KHwang9883/MobileModels.svg?color=yellow)](https://github.com/KHwang9883/MobileModels) -[![forks](https://img.shields.io/github/forks/KHwang9883/MobileModels.svg?color=orange)](https://github.com/KHwang9883/MobileModels) -[![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg)](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 月 -- 我开始汇总一些国内手机品牌的型号,「手机品牌型号汇总」的雏形诞生。 - -[![Stargazers over time](https://starchart.cc/KHwang9883/MobileModels.svg)](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 -[![issues](https://img.shields.io/github/issues/KHwang9883/MobileModels?color=green)](https://github.com/KHwang9883/MobileModels/issues) -[![prs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/KHwang9883/MobileModels/pulls) -[![stars](https://img.shields.io/github/stars/KHwang9883/MobileModels.svg?color=yellow)](https://github.com/KHwang9883/MobileModels) -[![forks](https://img.shields.io/github/forks/KHwang9883/MobileModels.svg?color=orange)](https://github.com/KHwang9883/MobileModels) -[![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg)](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 - -Creative Commons 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 @@ +# 手机品牌型号汇总 +[![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg)](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 +[![License: CC BY-NC-SA 4.0](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg)](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 接入和兼容查询相关说明,直接在当前页面查看,不再跳转到单独页面。

MySQL 设计说明

-

/misc/mysql-query-design.md

+

/docs/mysql-query-design.md

加载中...
@@ -1880,7 +1880,7 @@ LIMIT 20; syncReportPlatformUI(); syncSqlPlatformUI(); loadReadonlyInfo(); - loadDocInPanel("/misc/mysql-query-design.md", "MySQL 设计说明"); + loadDocInPanel("/docs/mysql-query-design.md", "MySQL 设计说明"); loadIndexFromPath(); diff --git a/web/doc_viewer.html b/delivery/web/doc_viewer.html similarity index 92% rename from web/doc_viewer.html rename to delivery/web/doc_viewer.html index 27f84e0..48c8a65 100644 --- a/web/doc_viewer.html +++ b/delivery/web/doc_viewer.html @@ -126,8 +126,8 @@

文档查看

正在加载文档...

- MySQL 设计说明 - Web 使用说明 + MySQL 设计说明 + Web 使用说明 项目 README
@@ -139,14 +139,14 @@