资讯动态

Windows 下 QGC 4.2.x Android 交叉编译环境搭建与避坑

发布时间:2026/9/30 3:34:35 来源:尧图企业网站定制
1. 为什么这套组合必须把版本钉死在 Windows 上折腾QGCQGroundControl4.2.x的 Android 版本最让人抓狂的从来不是代码本身而是版本。你可能已经见过那个很典型的报错cannot mix incompatible Qt library (5.15.3) with this library (5.15.2)这句话几乎是所有 Android 交叉编译踩坑者的入场券。它的意思很直白你的程序在运行时同时加载了两个不同小版本的 Qt 动态库5.15.2 和 5.15.3 在 ABI 上并不保证兼容于是进程直接崩掉。Qt 5.15.2和QGC 4.2.x之所以被绑在一起根本原因在这里。1.1 Qt 5.15.2 在开源链条上的特殊位置Qt 5.15 是 Qt 5 系列的最后一个长期支持分支而 5.15.2 是官方给出完整离线安装包、且仍然按开源许可分发的最后一个版本。再往后走5.15.3 及更新的补丁版本主要面向商业许可用户开源使用者要么走在线安装器的社区版通道要么干脆自己从源码编译。这就形成了一个很尴尬的局面绝大多数基于 Qt 5.15 的开源项目文档默认你手上装的是 5.15.2。QGC 4.2.x 的构建说明也是按这个版本写的官方给出的 Windows 构建文档里直接点名了 5.15.2。这个背景带来两个现实影响。第一你从各种渠道拿到的安装包不一定都是 5.15.2 的完整离线包可能是在线安装器拉下来的 5.15.3也可能是某个第三方软件自带的 Qt 运行时。第二一旦机器上存在多份 Qt环境变量 PATH 里谁在前面就决定了编译期和运行期加载哪一份冲突几乎不可避免。1.2 QGC 4.2.x 的依赖链长什么样QGC 不是一个纯 Qt 应用它在 Android 侧还要往下一层走Qt 的 Android 套件负责把 C 代码编译成针对 ARM 的本地库再由Android SDK 的 Gradle 构建系统打包成 APK中间还要经过 NDK 完成工具链交叉编译。整条链路大致是这样C 源码 → qmake 生成 Makefile → MinGW 宿主工具链驱动 Android Clang 交叉编译器 → 生成各 ABI 的.so.so与 Java 胶水层 → Gradle 调用 SDK 工具 → 合并资源、签名 → 输出.apk部署 → adb 推送到设备 → 运行时加载 Qt 的 Android 运行时库每一个环节都有自己的版本约束NDK 太新或太老Qt 预编译的本地库会链接失败JDK 版本和 Gradle 版本对不上打包阶段会直接报 Java 版本错误build-tools 版本过新老版本 Android Gradle 插件识别不了。这也是为什么这份环境搭建看起来步骤很多但每一步都不能省。1.3 适合谁来参考这份记录如果你符合下面任意一种情况这套流程基本可以直接照搬手里有 QGC 4.2.x 的源码需要出 Android 定制包准备做地面站二次开发需要改包名、改图标、改默认链路单纯想验证 Qt 5.15.2 在 Windows 上做 Android 交叉编译是否顺畅。整个过程对磁盘空间的要求不低Qt 全套加 Android 组件、SDK、NDK 装完30GB 是很正常的占用C 盘紧张的话提前规划到数据盘。我的建议是在动手之前先决定好目录规划。后面所有步骤都建立在路径不含中文、不含空格、尽量短这个前提上。我见过太多因为用户名是中文、或者把 SDK 放在我的文档下面导致 Gradle 报路径错误的案例排查起来非常浪费时间。2. 工具链选型与版本对照环境搭建的质量八成取决于选型阶段有没有把版本关系理顺。下面这份对照不是随便拍的每一条都对应实际操作中会遇到的硬约束。2.1 JDK、Gradle 与 Android Gradle 插件的三方约束Android 打包阶段由 Gradle 驱动而 Gradle 本身跑在 JVM 上所以 JDK 版本是第一道门槛。Qt 5.15.2 自带的 Android 构建模板使用的是较早期的 Gradle 与 Android Gradle 插件版本JDK 选得太新会直接报错。常见搭配关系是Gradle 版本支持的 JDK 范围备注5.xJDK 8 ~ 11老工程最常见稳定性好6.xJDK 8 ~ 13QGC 4.2.x 附近常见7.xJDK 8 ~ 17新工程才会用实操建议是优先装 JDK 8。原因不是 JDK 8 有多先进而是 Qt 5.15.2 那套构建脚本在 JDK 8 下几乎不会出幺蛾子。装 JDK 11 也能用但你需要额外确认工程里的 Gradle Wrapper 版本是否在 6.0 以上。至于 JDK 17 及以上我不建议在这套组合里尝试报错信息往往指向 Gradle 内部排查成本很高。JDK 的安装路径同样要留意。安装到C:\Program Files\Java\...不会有问题但如果你装的是某些集成包路径里带空格Gradle 在拼接命令行时可能被截断。稳妥做法是装到D:\Dev\jdk8这类短路径下。2.2 Android SDK 与 NDK 的版本钉死策略NDK 是这套环境里最容易踩雷的一环。Qt 5.15.2 的 Android 预编译库是用特定版本的 NDK 构建的混用其他版本会在链接阶段报符号找不到或者编译能过但运行时崩溃。针对 Qt 5.15.2推荐使用 r21e它对应的版本号是21.4.7075529如果你手上只有 r20b也能跑通大部分场景但不建议再往新版本走。SDK 侧的三个组件同样要选版本platform-tools包含 adb尽量用新版本因为旧版 adb 在部分新机型上会出现设备列表解析异常platforms;android-29编译目标平台29 是这套组合最稳的选择build-tools;29.0.2打包工具链和上面的平台版本保持同代不选最新版本的逻辑很实在Android Gradle 插件版本是固定的它对 build-tools 的接受范围有限。你装个 34.0.0 的 build-tools老插件可能连目录都找不到打包直接中断。2.3 目录规划与环境变量预演在真正开始安装前先把目录结构想清楚。我习惯这样规划D:\Dev\ Qt\5.15.2\ # Qt 安装目录安装器会自动补 mingw81_64、android 等子目录 jdk8\ # JDK Android\Sdk\ # ANDROID_SDK_ROOT Android\Sdk\ndk\21.4.7075529\ work\qgroundcontrol\ # 源码目录环境变量需要提前明确三类JAVA_HOME指向 JDK 根目录ANDROID_SDK_ROOT指向 SDK 根目录PATH 里追加SDK\platform-tools让 adb 全局可用。ANDROID_NDK_ROOT现在更多是历史遗留变量Qt Creator 4.13 会自己在 SDK 目录下搜索 ndk 文件夹但设上不会有副作用。注意不要同时设置ANDROID_HOME和ANDROID_SDK_ROOT且指向不同目录某些工具会因此产生歧义。统一用ANDROID_SDK_ROOT就够了。还有一个容易被忽略的点Qt Creator 会继承系统 PATH。如果你的 PATH 里存在另一个 Qt 的 bin 目录编译过程中调用的 moc、uic、rcc 可能是另一个版本的工具生成的文件与 5.15.2 的库不匹配就会出现开头提到的那类版本混用报错。后面我会讲怎么在 Qt Creator 里隔离构建环境。3. 从零安装 Qt 5.15.2 与 Android 组件这一段是整篇的核心操作区我把顺序安排成先装大件、再装小件、最后做校验这样出问题时排查范围小。3.1 离线安装包的获取与组件勾选Qt 5.15.2 的离线安装包放在官方归档目录里文件名形如qt-opensource-windows-x86-5.15.2.exe体积在 3GB 上下。下载和安装过程需要登录 Qt 账号这是官方流程提前注册好即可。下载的时候建议用支持断点续传的方式大文件中断重来很浪费时间。安装过程中组件树里要勾选的东西得看仔细因为默认勾选并不包含 AndroidQt 5.15.2 → MinGW 8.1.0 64-bit这个必须勾。它是宿主工具链Windows 上给 Android 目标做交叉编译时moc、uic、rcc 这些宿主工具都来自它。别用 MSVC 当宿主Qt 提供的预编译宿主工具是 MinGW 构建的混用会出现二进制不兼容。Qt 5.15.2 → Android → Android ARMv7真机 32 位 ARM兼容性最广Qt 5.15.2 → Android → Android ARM64_v8a现在的主流64 位包体积更大但性能更好Qt 5.15.2 → Android → Android x86只在模拟器上需要不做模拟器调试可以不装Developer and Designer Tools → Qt Creator安装器自带保持默认勾选这里有个坑值得提前说Android 组件的选择直接影响你能产出哪些 ABI 的 APK。只勾 ARMv7 的话64 位设备装上去虽然也能跑系统支持 32 位兼容但在部分纯 64 位系统上会直接拒绝安装。QGC 作为地面站实际使用场景里 64 位平板不少所以我一般 ARMV7 和 ARM64_v8a 都装。3.2 JDK 与 Android 命令行工具的落地JDK 装完之后验证方式很简单开一个 cmd 敲java -version输出里能看到版本号并且JAVA_HOME已经在系统变量里配好这一步就算过了。注意java -version输出的是 JDK 版本而不是 JRE 版本如果你只装了 JREGradle 会因为找不到javac直接报错这个区分点很多人会忽略。Android SDK 侧现在官方推荐用command-line tools而不是早期的 SDK Manager 图形界面。下载commandline-tools-windows压缩包解压到D:\Dev\Android\Sdk\cmdline-tools\latest\目录结构要保证bin\sdkmanager.bat存在。然后执行sdkmanager.bat --sdk_rootD:\Dev\Android\Sdk platform-tools platforms;android-29 build-tools;29.0.2 ndk;21.4.7075529这条命令一次把四样东西装齐好处是 NDK 的版本由 SDK 仓库统一管理不会出现你手上下载的 NDK 版本号对不上的情况。第一次执行会提示接受许可协议一路y确认即可。装完之后可以用sdkmanager --list_installed复核一遍确认ndk;21.4.7075529确实在列表里。注意新版 command-line tools 把工具放在cmdline-tools\latest\bin而 Qt 5.15.2 自带的 Qt Creator 4.13 在自检 Android 环境时习惯去SDK\tools\bin下面找 sdkmanager。如果自检一直提示找不到工具把cmdline-tools\latest\里的内容整体复制一份到SDK\tools\下让老路径也能命中问题基本就解决了。3.3 环境变量的最终形态把这一节单独拎出来讲是因为环境变量在这个项目里承担了两件事让命令行工具能找到彼此以及让 Qt Creator 的自检逻辑通过。最终系统变量应该是这个形态JAVA_HOME D:\Dev\jdk8 ANDROID_SDK_ROOT D:\Dev\Android\Sdk PATH 追加 %JAVA_HOME%\bin D:\Dev\Android\Sdk\platform-tools D:\Dev\Qt\5.15.2\mingw81_64\binPATH 里加 Qt 的 mingw81_64\bin 是为了命令行直接能跑 qmake但这也埋下了一个隐患如果你的机器上还装过其他版本的 Qt并且它的 bin 也在 PATH 里谁在前面谁生效。我的做法是把 Qt 的 bin 放在这一堆的最后面日常用命令行时靠绝对路径调用避免误用。配完之后重启终端逐条验证java -version、adb version、qmake -v。特别是qmake -v输出里应该明确写着Using Qt version 5.15.2如果显示别的版本号说明 PATH 里有别的 Qt 抢在了前面这时候就得回头清理。4. Qt Creator 中打通 Android 设备链Qt Creator 识别 Android 工具链的入口在工具 → 选项 → 设备 → Android。这个页面看起来简单实际上自检逻辑相当严格任何一个路径不对都会红字提示。4.1 三个路径的填写与自检触发页面里要填三样东西JDK 位置、Android SDK 位置、Android NDK 位置。填写顺序无所谓但填完之后一定要点应用或确定触发自检。自检通过后页面下方会显示一个汇总信息包含 SDK 版本、NDK 版本、可用的 ABI 列表。自检结果里最需要关注的是ABI 列表。如果你在 Qt 安装阶段勾了 ARMv7 和 ARM64_v8a这里就应该同时看到armeabi-v7a和arm64-v8a。只看到一个说明对应的 Qt Android 组件没装上回去补装。这一步常见的失败原因和对应处理报错提示实际原因处理方式找不到 sdkmanagercmdline-tools 目录结构不匹配复制到SDK\tools\NDK 版本不受支持NDK 版本过新或过老换成 21.4.7075529找不到 JavaJAVA_HOME 指向 JRE重装完整 JDKABI 列表为空Qt Android 组件未安装用维护工具补装4.2 Kit 的生成与默认选择Android 环境自检通过之后Qt Creator 会自动在构建套件Kit页面里生成对应的条目名字类似Android Qt 5.15.2 Clang (arm64-v8a)。这里有一个很关键的细节Android Kit 的宿主编译器应该显示为 MinGW 8.1.0 64-bit而不是 MSVC。如果你看到的是 MSVC说明安装时没勾 MinGW 组件或者宿主编译器被手工改过需要改回来。Kit 生成之后我习惯做两件微调。一是把构建目录单独指到一个短路径下比如D:\build\qgc-android避免和源码目录混在一起。二是把默认构建类型设为 Release因为 Debug 版的 Android 包体积巨大而且 QGC 在 Debug 模式下性能会明显下降测实时链路时容易误判是程序问题。4.3 隔离构建环境掐死版本混用前面提到的 Qt 库版本混用问题最有效的解法就在 Kit 配置里。打开 Kit 的构建环境一栏默认是使用系统环境也就是继承系统 PATH。把它改成手动编辑然后把 PATH 精简成只包含D:\Dev\Qt\5.15.2\mingw81_64\bin D:\Dev\jdk8\bin D:\Dev\Android\Sdk\platform-tools %SystemRoot%\system32这个操作的目的是确保 qmake、moc、uic 一定来自 5.15.2。我见过有人电脑上装了三个版本的 Qt编译时一切正常运行桌面版工具时突然报cannot mix incompatible Qt library最后查出来是系统 PATH 里另一个 Qt 的 bin 排在前面。花十分钟做这个隔离能省掉后面几小时的排查。4.4 设备连接与调试通道验证Android 设备和 PC 之间的通道靠 adb。设备打开开发者选项和 USB 调试后连上电脑命令行执行adb devices正常应该看到一串设备号和device状态。如果显示unauthorized需要在设备屏幕上确认授权弹窗显示offline通常是数据线或者驱动问题换线比换驱动更常见。有一类报错很隐蔽Failed to parse output of adb devices。这个基本可以确定是 platform-tools 版本太旧adb 输出的格式和 Qt Creator 的解析器不匹配。解决办法就是用 sdkmanager 把 platform-tools 升到较新版本注意只升这一个组件不要顺手把 build-tools 也升了。通道验证完之后可以顺手跑一次adb logcat确认能看到设备日志输出。后面 APK 装上去之后所有运行时错误都要靠 logcat 来定位提前确认它能用很关键。5. 拉取 QGC 4.2.x 并完成首次构建到了这一步环境本身已经通了接下来是把工程跑起来。5.1 源码获取与分支、子模块处理QGC 的仓库用 Git 管理克隆的时候要注意分支。4.2.x 属于稳定分支对应的分支名形如Stable_V4.2。完整流程是git clone https://github.com/mavlink/qgroundcontrol.git cd qgroundcontrol git checkout Stable_V4.2 git submodule update --init --recursive子模块这一步绝对不能省。QGC 依赖多个第三方库和 mavlink 相关模块它们以 submodule 形式挂载。如果只克隆主仓库不拉子模块编译时会报大量头文件找不到。而且子模块拉取本身是递归的网络不好的时候容易中途失败失败后重新执行同一条命令即可Git 会跳过已经拉好的部分。如果后续需要切换分支或者更新代码记得再次执行git submodule update --init --recursive否则子模块会停留在旧版本产生一些看起来毫无道理的编译错误。5.2 OpenSSL 运行时库的准备QGC 在通信层会用到 OpenSSLAndroid 平台没有系统自带的可用实现需要把针对 Android ABI 编译好的libcrypto.so和libssl.so提供给打包流程。这一步的具体做法是准备对应 ABI 的so文件通过工程里的ANDROID_EXTRA_LIBS机制附加进 APK并保证 ABI 目录名与目标一致armeabi-v7a对应 ARMv7arm64-v8a对应 ARM64。ABI 目录名必须严格对齐这一条踩过坑的人印象都很深。你把 64 位的so放进armeabi-v7a目录构建过程不会报错但装到 32 位设备上启动就崩logcat 里会看到dlopen failed: is 64-bit instead of 32-bit这类信息。QGC 仓库的构建说明里给出了具体的库文件放置位置和命名要求以你拉下来的那个分支的官方说明为准因为不同小版本之间这块结构会有调整。5.3 用 Qt Creator 打开工程并配置构建QGC 用的是 qmake 工程体系根目录下的.pro文件就是入口。用 Qt Creator 直接打开这个.pro然后在配置界面里勾选 Android Kit。首次解析工程时 Qt Creator 会跑一次 qmake这一步如果报错基本都和环境变量、Kit 配置有关和源码本身无关。构建前建议再做三件事。第一把构建目录设成独立短路径。第二确认构建类型为 Release。第三检查 Kit 的构建环境是否为前面精简过的那个版本。做完之后点构建第一次编译会很久十几分钟到半小时都算正常毕竟 QGC 的代码量不小加上要过一遍 Android 的交叉编译工具链。编译过程中会看到宿主工具被反复调用会看到 NDK 的 clang 在编译各个.cpp最后进入 Gradle 阶段。Gradle 阶段是最容易卡住的地方因为它需要下载依赖包。网络条件一般的情况下可以把工程的 Gradle 配置指向国内公共 Maven 镜像比如阿里云提供的那个公共仓库速度会有明显改善。这是常规的构建加速手段配置位置在 Gradle 的仓库声明里把mavenCentral()和google()前面插入镜像地址即可。5.4 产出 APK 与真机安装构建成功之后APK 会出现在构建目录的一层子目录里路径形如build\android-build\build\outputs\apk\release\。Debug 版和 Release 版的路径略有差别看目录里哪个存在就知道用的哪种。签名方面Debug 构建用自动生成的调试证书Release 构建需要你自己准备 keystoreQt Creator 的 Android 配置页面里可以指定 keystore 路径、别名和密码。安装到设备上用一条命令就够adb install -r qgroundcontrol.apk-r表示覆盖安装保留数据。装完之后手动点开图标如果出现闪退立刻抓日志adb logcat -s QGC:V AndroidRuntime:E libc:F把AndroidRuntime和libc两个标签加上绝大多数闪退原因都能在这两类日志里直接看到。缺库会报dlopen failedABI 不匹配会明确写出位数冲突Qt 版本问题则往往出现在libc相关的段里。5.5 改包名、改图标这类定制需求做二次开发的人绕不开这个需求。包名决定了设备上能否和应用商店版本共存图标和应用名决定用户看到的样子。包名相关的配置分散在.pro和 Android 工程目录下的清单文件里改的时候必须两处同步只改一处会导致构建出来的包名和你预期的不一致。具体文件位置以你拉下来的分支结构为准通常在工程根目录下有一个专门存放 Android 平台相关的目录。改完之后建议先卸载旧版本再安装避免签名不一致导致的安装失败。签名不一致时报错信息是INSTALL_FAILED_UPDATE_INCOMPATIBLE看到这条直接adb uninstall 包名再重装别在签名上纠缠。6. 报错速查与排查思路这一节把整个流程里最常遇到的几类问题集中整理方便出问题时对着查。6.1 版本冲突类问题现象根本原因解决思路cannot mix incompatible Qt library运行时加载了非 5.15.2 的 Qt 库清理 PATH检查依赖加载路径编译报符号未定义NDK 版本与 Qt 预编译库不匹配换回 21.4.7075529Java 版本不兼容JDK 与 Gradle 版本跨度过大降到 JDK 8 或 11找不到 build-tools 目录build-tools 版本过新钉到 29.0.2关于第一条排查手法值得单独说如果被构建出来的桌面端工具或者调试程序报这个错最直接的办法是用依赖查看工具打开可执行文件看它实际加载的 Qt5Core 来自哪个目录。路径指向的目录不是你的 5.15.2 安装路径就说明有另一份 Qt 在抢。找到它之后要么从 PATH 里移除要么在构建环境里覆盖。6.2 路径与权限类问题路径问题在 Windows 上出现的频率远超想象。用户名是中文、工程放在桌面、目录名带空格这三类都会引发问题。表现各有不同有的是 qmake 报找不到文件有的是 Gradle 报非法字符还有的是编译能过但打包时资源路径匹配不上。处理方式只有一个全部挪到纯英文短路径下。另一类是文件占用。编译过程中如果 Qt Creator 崩溃过可能残留了正在运行的qmake.exe或者mingw32-make.exe进程再次编译时会报无法写入目标文件。任务管理器里把这些残留进程结束掉就行。这个现象在反复编译失败后特别常见容易误判成工程配置错误。6.3 构建缓存与依赖下载类问题编译失败重新开始时如果上一次失败发生在 Gradle 阶段Qt Creator 有时会保留部分缓存导致新一次构建直接跳过某些步骤问题看起来修好了其实是没重跑。遇到这种情况清理构建目录再全量编译一次更可靠删掉build\android-build\build目录重新构建。依赖下载失败通常表现为超时或者校验不通过。Gradle 的依赖缓存在用户目录下的.gradle\caches里如果某个包下载了一半损坏了后续会一直失败。删掉对应的缓存目录重新拉比反复重试有效得多。把仓库地址换成国内公共镜像也能从根上减少这类问题。6.4 三个独家避坑技巧技巧一先只出 ARM64 包验证流程再出多 ABI 包。多 ABI 构建会同时编译多套本地库出错时很难判断是哪个 ABI 的问题。先用单一 ABI 跑通全流程确认 APK 能装能跑再打开多 ABI 选项。技巧二给 Qt Creator 的构建日志开详细输出。构建失败时默认日志往往只显示了最后一行汇总错误看不到真正的原因。把构建输出的详细程度调高能看到具体的调用命令定位问题快很多。技巧三把 NDK 的路径写死进工程配置。有些情况下 Qt Creator 会去猜 NDK 位置猜错时编译期报错非常难懂。在 Kit 的构建环境里显式声明 NDK 根目录变量能避免这类莫名其妙的失败。7. 长期维护与几件值得提前做的事环境搭完能跑通只是开始真正要长期用下去还有几件事情值得提前安排。7.1 多 Qt 版本的共存策略如果你后续还要做桌面端开发机器上迟早会有多个 Qt 版本。我的经验是不要依赖系统 PATH 来切换改成靠 Qt Creator 的 Kit 隔离。每个 Kit 内置自己的构建环境互不影响。命令行侧则用一个批处理脚本临时设置环境变量用完即走不要往系统变量里塞一堆版本相关的路径。至于 Qt 5.15.2 的安装留一份完整副本别删。有些依赖库的源码在归档服务器上不保证长期可访问本地留档比什么都实在。7.2 环境快照与文档化这套环境搭一次要花不少时间配好之后建议做两件事一是把关键版本号记进工程根目录的一份说明文件里包括 Qt 版本、NDK 版本、JDK 版本、build-tools 版本、QGC 分支名。二是考虑给系统盘做一次快照或者至少把 Qt 和 SDK 目录压缩备份。换机器、重装系统的时候有这份记录和备份恢复时间能从一天缩短到一小时。7.3 关于构建速度的一点实测体会同一台机器上Android 构建耗时的主要瓶颈在两块C 编译和 Gradle 打包。前者可以靠并行编译缓解Qt Creator 的构建参数里可以加-j提高并发数但并发开太高反而会因为内存不足触发 MinGW 工具崩溃我一般设成 CPU 核心数的六到八成。后者主要受网络影响依赖已经缓存到本地之后重复构建的 Gradle 阶段只需要十几秒。另外一个小细节QGC 的源码改动如果只涉及 QML 和资源文件增量构建会快很多因为不需要重新编译全部 C。所以在开发阶段改界面的时候尽量别顺手动 C 头文件那会触发大面积重编。7.4 真机与模拟器的取舍模拟器调试在前期验证阶段挺方便不需要插设备但它的 ARM 兼容层在跑 QGC 这种图形和数据吞吐都重的应用时帧率和响应都跟不上容易让你误判性能问题。我的习惯是功能验证用模拟器看能不能起来性能相关的测试一律上真机。真机型号尽量选系统版本较新的Android 12 及以上对文件访问权限收得更紧早期版本上能跑的路径写法在新系统上可能直接读不到早暴露比晚暴露好。最后再补一句实际操作中的体会这套环境里最花时间的从来不是安装而是找错。把版本关系画成一张表贴在工程文档里把每一处路径写进配置文件而不是靠环境变量传递后续换人接手或者自己隔几个月回来重看省掉的都是成小时的时间。环境搭好那一刻的顺利其实是从第一分钟就规划出来的。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑