HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

iOS上架App Store流程:账号选择、证书配置与审核被拒排查

做iOS开发这些年,最常被问的问题不是“这个功能怎么实现”,而是“App到底怎么上架”。身边不少开发者代码写得挺利索,一走到上架这步就开始卡壳——账号类型选错、证书懵圈、后台信息填完被打回来两次、上传报错看不懂,最后在审核门口耗掉一两周。我自己早期上架第一款App时也这样,踩过的坑加起来比写的代码还多。

这篇就专门聊iOS应用上架App Store的完整流程与技巧。从开发者账号、证书配置,到App Store Connect后台填写、上传测试,再到审核被拒后的应对策略,我会按实际操作顺序把整条链路拆开讲,同时把那些官方文档里不会明说、但实际非常关键的细节一并交代清楚。不管你是第一次上架的新手,还是已经上过架但被各种报错折磨过的老手,这篇应该都能帮上忙。

1. 上架前夜:账号类型、开发环境与最容易拖慢进度的门槛

很多人以为上架最难的是审核,其实在真正走到“提交审核”按钮之前,光是准备阶段就有好几个容易翻车的环节。我见过不止一个人卡在账号注册上,一卡就是好几天,所以这部分值得先花点时间理清楚。

1.1 开发者账号:个人、公司还是教育机构,到底怎么选

苹果开发者账号分三种:个人(Individual)、公司(Company)、教育机构(Educational Institution)。对于大部分开发者来说,面临的主要选择是个人还是公司。

个人账号299元/年,公司账号也是299元/年。这里有一个很多人不知道的点:苹果按年收取的费用对于个人和公司是一样的,但公司账号需要提供邓白氏编码(D-U-N-S Number)来验证企业信息。这个编码申请本身免费,但需要走一遍企业信息核验流程,通常要多花几天时间。

个人账号和公司账号在App Store上架能力上没有本质区别,都能正常上架。唯一实质性的差异是:公司账号的App可以显示公司名称,个人账号显示的则是个人姓名;另外,如果你的产品将来涉及企业签名分发,或者需要多人协作管理,公司账号的团队管理功能会更方便。

我的建议是:如果你是一个人独立开发,暂时没有公司主体,直接用个人账号完全没问题,不要为了显示“公司名”去挂靠或者临时注册公司,完全没有必要。等产品跑出来了,再升级或者换主体都来得及。

1.2 上架前必须完成的开发环境自检清单

正式开始上架操作前,先对照检查这几点,能省掉后面一大串问题:

Xcode版本更新到最新稳定版。上架用的构建版本必须用当代Xcode工具链打包,旧版本打出来的包可能会被直接拒绝。App Store审核特别在意构建工具版本,过老的Xcode提交会提示“SDK版本过低”。

确认你的Apple ID已经加入开发者计划。在“设置”App里能看到“开发者”入口,Xcode的Account设置里也能看到自己的Team信息。

准备一台能跑真机的设备。虽然纯模拟器也能开发,但涉及推送、相机、StoreKit等系统能力时,真机调试几乎是必须的。上架前至少要在真机上完整跑通一次主流程。

检查项目的Deployment Target是否合理。不要拍脑袋定最低版本,一定要结合你的目标用户群。通常建议参考当前主流系统版本分布,过低会白费适配成本,过高则会丢失用户。

工程的Bundle Identifier(后面简称Bundle ID)要提前确认好。这个ID一旦在开发者后台注册过,就是全局唯一的,后续替换代价很大,涉及推送服务、跨App登录、云同步等一堆配置。

这一套自检看起来琐碎,但每一条背后都有我见过的真实翻车案例。尤其是Bundle ID,不少开发者等到App都快写完了才想起来改,结果推送服务、App内购买、第三方登录全都得跟着改一遍,心态很容易崩。

2. 证书、Bundle ID与描述文件:苹果签名体系中三个易混概念的正解

iOS的签名体系对新手来说非常劝退。证书、标识符、描述文件这三个名词经常听着听着就混了。我试着用生活化的方式讲清楚,这套逻辑一旦通了,后面所有上架操作都会顺畅很多。

2.1 三者的职责划分:身份证、门牌号与通行证

Bundle ID相当于App的门牌号,它让系统能准确识别“你是哪个App”。苹果后台里注册的Bundle ID必须与Xcode工程里的Build Settings > Product Bundle Identifier完全一致,包括大小写。

证书(Certificates)相当于你的身份证,证明“这是经过验证的开发者发布的”。证书分为开发证书(Development)和分发证书(Distribution),上架用的是Apple Distribution类型的分发证书。

描述文件(Provisioning Profile)相当于通行证,它把证书、Bundle ID和允许运行的真机设备绑定在一起。上架用的描述文件叫App Store Connect类型的Distribution Profile。

这三者的关系可以这样理解:Bundle ID告诉系统你是谁,证书证明你确实是你说的那个人,描述文件则决定你这个身份在哪个App的哪个环境里可以合法使用。其中任何一个不匹配,编译阶段或者上传阶段就会直接报错。

2.2 在开发者后台和Xcode里的实际操作路径

现在的Xcode其实已经大大简化了这些操作。如果你的账号在Xcode里登录过,并且开启了Automatically manage signing,那么Xcode会自动帮你生成和匹配证书与描述文件。具体操作路径是:

打开Xcode工程,选中Target,进入Signing & Capabilities。

勾选“Automatically manage signing”。

Team选择你的开发者团队。

Bundle Identifier填好后,Xcode会自动在开发者后台为你注册这个App的标识符。

如果勾选自动管理签约后出现“No account with team ID”之类的问题,多半是开发者账号还没激活,或者该Apple ID没加入开发者计划。去开发者后台确认一下Membership状态即可。

不过有一点要注意:自动管理虽然省心,但在做App内购买(IAP)或者推送配置时,有些能力(如Push Notifications、In-App Purchase)是需要到后台手动开启App ID的Capabilities的。如果遇到“Capabilities无法添加”的情况,大概率是这一步漏了。

2.3 证书和描述文件过期的真实坑

签名体系里最常见的翻车点就是过期。开发证书有效期是一年,描述文件根据不同情况有效期不一,上架用的App Store Connect描述文件通常也是按年签发的。

我自己的习惯是:每次上架前,先到开发者后台的Certificates, Identifiers & Profiles页面看一眼证书到期时间。如果发现快到期了,提前几个月就重新生成一份。不要等到打包时才发现证书失效,那种“一切就绪但证书过期”的挫败感真的非常容易劝退人。

另外,描述文件过期后,Xcode在Archive时会提示“Provisioning profile doesn't include signing certificate”。看到这句话,第一反应应该是去看描述文件的有效期,而不是怀疑证书本身有问题。

3. App Store Connect后台:那些看着简单、填错就影响审核的细节

App Store Connect是苹果的后台管理系统,上架和审核相关的所有操作都在这里完成。很多人以为填后台信息是一件“随便填填就行”的事情,实际上这里面的细节非常多,而且直接关系到审核效率和过审率。

3.1 应用名称、副标题与关键词的取舍之道

App名称(Name)在后台的“App信息”页面填写,展示在App Store上的名称长度限制是30个字符。这里有个很重要的点:名称并不一定要和工程里的Bundle ID对应的产品名完全一致,你可以起一个更适合商店搜索习惯的名字。

副标题(Subtitle)是iOS 11之后引入的字段,最多30个字符,会展示在App Store首页卡片上。它和名称一起构成了App Store搜索结果里最重要的两个文本权重来源,写得好能显著提升转化率。

关键词(Keywords)最多100个字符,用英文逗号分隔。苹果明确禁止在关键词里重复品牌名、填充无关热词、或者使用其他App的名称。我见过不少人在这里堆了几十个词,结果被审核团队以“误导性元数据”驳回。关键词写法的正确姿势是:核心词靠前,优先组合词而不是单个词,不要带空格和标点。

3.2 截图与预览物料:尺寸、内容与本地化要求

App Store对截图的要求相当细致,6.7英寸、6.5英寸、5.5英寸、5.8英寸几个档位,按你App支持的设备类型,有些规格需要指定尺寸上传。截图必须真实反映App界面,不能使用未经标注的合成图或者隐藏功能的“演示模式”。

给到你的实操建议:优先准备6.7英寸(iPhone 15 Pro Max等设备)和6.5英寸的截图,这是App Store主要展示的尺寸。每张截图的第一个屏幕至关重要,它会直接出现在搜索结果和Today推荐里,所以第一张一定要放最核心的功能界面。

如果App支持多语言,后台的每个本地化语言版本都需要单独上传对应语言内容的截图。这一步经常被忽略,导致审核团队看到英文界面的截图与实际中文界面不符而被打回。

3.3 隐私政策、年龄分级与出口合规这些“隐形关卡”

App Store Connect后台里有几个非开发类字段,看着不起眼,实际审核权重很高。

隐私政策网址是必填项。如果你有产品,可以直接放产品隐私政策页;如果没有产品,也可以用托管服务的隐私政策模板页。这里一定要填真实有效的可访问地址,审核团队会真的打开看。最好避免用临时生成的短链,也不要放需要登录才能查看的页面。

年龄分级(Age Rating)在“App信息”页面的“年龄分级”区域填写。苹果提供了一套问卷式的选项,包括是否包含色情、暴力、赌博、酒精、药品等内容。不同游戏类型还有额外的分级问卷。这里要注意:问卷结果会自动映射到不同国家/地区的分级体系,填得太低容易有问题,填得太高则会限制流量。按照实际情况如实填写即可,不必刻意压级。

出口合规信息(Export Compliance)通常在提交构建版本时会出现,问你的App是否包含加密功能。如果你的App用了HTTPS、内置加密库或自定义加密逻辑,理论上就属于“使用加密”。实际填写的技巧是:只要你的App没有使用非标准加密算法,一般都可以选择“豁免”。HTTPS这种系统级加密不算需要申报的类型,选豁免就好。如果实在拿不准,建议选需要申报,然后等待审核团队进一步询问。

3.4 三种发布方式的区别:手动发布与自动发布

在App Store Connect后台“App信息”页面的“发布”部分,可以选择“自动发布”或“手动发布”。这个选择看似简单,但对上架节奏影响巨大。

选择自动发布的意思是,当审核通过后,App会自动在当天进入“可供销售”状态。选择手动发布则是审核通过后,App进入“等待发布”状态,需要你手动点击“发布此版本”按钮。

我的建议是:首次上架选自动发布,简化流程;后续版本更新,尤其是带来重大功能调整时,选手动发布,可以避开周末或节假日这种数据波动期,让你有更多控制空间。

4. 上传与测试:从Xcode Archive到TestFlight,中间的真实报错排查

后台信息填好后,就到了真正打包上传的环节。这一步对经验的依赖程度非常高,很多报错信息看起来吓人,实际上原因很单纯,一部分报错信息还非常具有误导性。

4.1 Archive、上传与构建版本的处理链路

在Xcode里,选择Any iOS Device(或者Generic iOS Device)作为编译目标,然后通过菜单Product > Archive打包。Archive完成后,Xcode会自动打开Organizer窗口,里面列出所有归档包。

点击右上角的“Distribute App”,选择“App Store Connect”选项,然后按向导走完。这里要特别注意,第一次分发时会询问是否包含Bitcode。现在苹果已经不强制要求Bitcode,保持默认关闭状态即可。后续几步会让你选择签名方式,确认使用自动签名的分发证书后,Xcode就会开始上传。

上传成功的标志:Organizer窗口中你的归档包状态变为“Uploaded”,同时App Store Connect后台的“构建版本”区域会按顺序出现在“TestFlight”或“审核”区域。构建版本从上传到后台出现通常有几分钟延迟,耐心等待,不要重复上传。

4.2 上传报错的几类真实原因与排查思路

上传阶段我遇到过的报错,归纳起来主要有三类:

第一类是网络层问题。错误信息常常是“The network connection was lost”或者“Your session has expired”。这类问题最常见的原因是网络直连不稳定。可以试试切换网络环境,或者退出 Xcode 账号重新登录,大多数都能解决。

第二类是证书问题。Xcode 弹窗提示“No accounts with iTunes Connect access”或者“Unable to process request”。遇到这种问题,去开发者后台确认分发证书是否有效,去 Xcode 的 Accounts 设置里确认账号是否加入了对应的 Team,两步检查通常就能定位。

第三类是“ITMS-90078”这类带有明确代码的报错。这类代码背后往往对应的是元数据缺失、缺少隐私政策、缺少必要权限描述等具体问题。建议直接在 App Store Connect 后台的“功能 → App 隐私”和“App 信息”里逐项检查。ITMS-90078 的常见原因是缺少“用途字符串”说明——也就是 Info.plist 里对应权限的 NS*UsageDescription。

4.3 TestFlight内测:上架前最应该利用的环节

构建版本上传成功后,第一站是 TestFlight。很多开发者直接跳过内测就把版本提交审核,这个习惯其实很亏。

TestFlight 可以让你邀请最多 100 名内部测试员和 10000 名外部测试员,在真机上先试用你的 App。这一步的价值不只是发现 Bug——很多时候,审核团队会先跑一遍你的 App,如果启动就崩、主流程走不通,那么任何元数据上的努力都白费了。至少自己用 TestFlight 安装一遍,跑通完整的注册、登录、支付、主要功能路径,再提交审核,能省掉至少两三天的往返沟通时间。

TestFlight 本身还有个常被忽略的细节:外部测试需要提交“测试说明”和“Beta 版 App 审核”,也就是 Beta App Review,这个审核通过后你的测试链接才能发给外部用户。首次配置时留出一天时间比较稳妥。

5. 审核被拒:常见理由、攻防策略与申诉的正确姿势

提交审核之后,等待一般是 1 到 3 天。苹果的审核时间波动很大,工作日上午提交往往比周五晚提交更快。审核被拒不是世界末日,被拒后怎么高效沟通、怎么修改再提,才是真正见经验的地方。

5.1 元数据类拒绝:占被拒比例最高的一种

元数据被拒在审核反馈里通常显示为“Guideline 2.3 - Performance - Accurate Metadata”。常见触发点包括:App 名称包含“免费”等营销词、截图与 App 实际功能不符、描述里声称支持某些实际上看不到的功能、关键词堆砌相关词汇。

这类拒绝一般不需要改代码,只需要在 App Store Connect 后台修改对应的元数据内容,然后重新提交审核即可。修改完记得在“App 信息”页面右下角点击“提交审核”,而不是以为保存就够了。

5.2 功能与隐私类拒绝:需要真正修改App的情况

功能类拒绝最常见的理由是:App 无法正常登录、需要付费才能体验完整功能但与描述不符、包含 UGC 内容却没有举报和屏蔽机制、崩溃或闪退。

隐私类拒绝在近年明显增多,常见的是:收集用户数据但没有清晰告知、隐私政策链接无法访问、使用了 API 但不满足“App 跟踪透明度”的要求。

收到这类拒绝时,不要急着重新提交。先在“解决方案中心”的线程里,用英文(或者其他审核人员使用的语言)清晰地回复你的处理方案,说明已做修改的细节和原因。回复后点“提交审核”即可,不用重新上传构建版本,除非你修改了代码。

5.3 加急审核与申诉:什么时候用、怎么用

如果你的App因为线上严重Bug需要紧急发布,或者审核超过预期时间且事态紧急,可以使用加急审核(Accelerated Review)。进入App Store Connect后,在“联系我们”页面选择“App Review”→“Request an expedited review”,并填写理由。

加急审核不是随便用的。滥用会被列入“不诚信名单”,后续所有审核都会被特殊对待。我个人的原则是:非紧急时刻绝不用加急,平时正常排队,一般2-3天足够。

如果被拒后你认为是苹果审核判断有误,可以在拒绝通知里选择“Appeal”提交申诉。申诉的关键是把该版本与上一个通过审核的版本差异说清楚,用简短的语言说明问题出在沟通误解而不是产品本身。申诉响应的速度通常比新提交审核要快,但成功率还是要看具体案例是否真的有争议。

5.4 审核期间你能做的几件事

等待审核的时候,不少人会反复刷新后台,这很正常,但没必要。更有价值的做法是:把App Store页面上的“宣传文本”(Promotional Text)提前写好,审核通过后第一时间发布;准备好发布当天的推广物料;如果App是订阅制,提前确认内购项目状态是“准备提交”还是“已批准”;同时可以开始准备第一个版本的用户反馈渠道。

审核结果出来后,不论通过与否,记得去后台看完整的“审核备注”。有时候审核团队会附上视频或截图,显示具体问题位置,这些信息可以根据反馈再次查阅。

6. 上架之后的更新节奏:版本迭代、审核周期与日常维护

App上架不是终点,而是一个新的起点。版本更新的审核节奏、发布时机的选择、日常维护的细节,都直接影响App的长期数据表现。

6.1 版本更新的审核周期与提交窗口

版本更新的审核周期通常比首发审核快,很多情况下1-2天就能过。但如果你选择在周五下午提交,大概率要等到下周一甚至周二才能过审,因为周末审核团队人手少。想要让新版本在周一早上发布的话,周五上午提交是比较理想的窗口。

另外注意:新版本上传的构建版本,必须使用当前的Xcode版本重新打包。不要试图复用旧构建版本,尤其是跨越了iOS系统大版本更新之后,复用老构建会有非常明显的兼容性和合规风险。

6.2 审核通过后的第一小时应该做什么

审核通过后,App并不会自动出现在所有用户面前,搜索结果收录和推荐位更新通常需要几小时到一天的时间。这个阶段可以做的事包括:更新宣传文本、确认内购项目状态、观察首批下载数据。

还有一个容易被忽略的操作:把审核通过的版本设置为“手动发布”时,通过后不会自动上线,而是停留在“等待发布”状态。如果你在后台发现新版本下方有“发布此版本”按钮,记得点击确认,否则App会一直处于未上架状态。

6.3 日常维护中最常被问到的几个坑

被问得最多的问题是:“我改了代码想更新,但忘了原来的证书在哪一台电脑上生成的。”这个问题在新电脑上尤其常见。实际解决办法是:在开发者后台重新生成证书,不需要找回旧私钥。因为分发证书和推送证书都可以重新创建,重新生成后旧的证书会失效,但基本不影响线上App的使用,除非你在用旧证书做推送服务。

另一个常见问题是:“为什么我的App在商店里搜不到?”原因通常有三种:搜索关键词没有覆盖到用户习惯的词汇(不是技术问题,是关键词策略问题);新上架App的搜索权重本来就很低,过几天会自然上升;或者该地区还没有完成发布。如果上架已经一整天并且状态是“可供销售”,那大概率就是关键词策略的问题,建议下一版本更新时调整关键词布局。

我自己走过一遍完整流程后,最大的感受是:上架这件事,流程本身并不复杂,真正需要花心思的是对细节的掌握程度。很多失败并不是因为产品差,而是因为某个字段填错、某个证书过期、某个权限说明没写清楚。把上面这些环节都梳理顺畅了,你大概率能比大多数人少折腾一半时间。

继续阅读 »

做iOS开发这些年,最常被问的问题不是“这个功能怎么实现”,而是“App到底怎么上架”。身边不少开发者代码写得挺利索,一走到上架这步就开始卡壳——账号类型选错、证书懵圈、后台信息填完被打回来两次、上传报错看不懂,最后在审核门口耗掉一两周。我自己早期上架第一款App时也这样,踩过的坑加起来比写的代码还多。

这篇就专门聊iOS应用上架App Store的完整流程与技巧。从开发者账号、证书配置,到App Store Connect后台填写、上传测试,再到审核被拒后的应对策略,我会按实际操作顺序把整条链路拆开讲,同时把那些官方文档里不会明说、但实际非常关键的细节一并交代清楚。不管你是第一次上架的新手,还是已经上过架但被各种报错折磨过的老手,这篇应该都能帮上忙。

1. 上架前夜:账号类型、开发环境与最容易拖慢进度的门槛

很多人以为上架最难的是审核,其实在真正走到“提交审核”按钮之前,光是准备阶段就有好几个容易翻车的环节。我见过不止一个人卡在账号注册上,一卡就是好几天,所以这部分值得先花点时间理清楚。

1.1 开发者账号:个人、公司还是教育机构,到底怎么选

苹果开发者账号分三种:个人(Individual)、公司(Company)、教育机构(Educational Institution)。对于大部分开发者来说,面临的主要选择是个人还是公司。

个人账号299元/年,公司账号也是299元/年。这里有一个很多人不知道的点:苹果按年收取的费用对于个人和公司是一样的,但公司账号需要提供邓白氏编码(D-U-N-S Number)来验证企业信息。这个编码申请本身免费,但需要走一遍企业信息核验流程,通常要多花几天时间。

个人账号和公司账号在App Store上架能力上没有本质区别,都能正常上架。唯一实质性的差异是:公司账号的App可以显示公司名称,个人账号显示的则是个人姓名;另外,如果你的产品将来涉及企业签名分发,或者需要多人协作管理,公司账号的团队管理功能会更方便。

我的建议是:如果你是一个人独立开发,暂时没有公司主体,直接用个人账号完全没问题,不要为了显示“公司名”去挂靠或者临时注册公司,完全没有必要。等产品跑出来了,再升级或者换主体都来得及。

1.2 上架前必须完成的开发环境自检清单

正式开始上架操作前,先对照检查这几点,能省掉后面一大串问题:

Xcode版本更新到最新稳定版。上架用的构建版本必须用当代Xcode工具链打包,旧版本打出来的包可能会被直接拒绝。App Store审核特别在意构建工具版本,过老的Xcode提交会提示“SDK版本过低”。

确认你的Apple ID已经加入开发者计划。在“设置”App里能看到“开发者”入口,Xcode的Account设置里也能看到自己的Team信息。

准备一台能跑真机的设备。虽然纯模拟器也能开发,但涉及推送、相机、StoreKit等系统能力时,真机调试几乎是必须的。上架前至少要在真机上完整跑通一次主流程。

检查项目的Deployment Target是否合理。不要拍脑袋定最低版本,一定要结合你的目标用户群。通常建议参考当前主流系统版本分布,过低会白费适配成本,过高则会丢失用户。

工程的Bundle Identifier(后面简称Bundle ID)要提前确认好。这个ID一旦在开发者后台注册过,就是全局唯一的,后续替换代价很大,涉及推送服务、跨App登录、云同步等一堆配置。

这一套自检看起来琐碎,但每一条背后都有我见过的真实翻车案例。尤其是Bundle ID,不少开发者等到App都快写完了才想起来改,结果推送服务、App内购买、第三方登录全都得跟着改一遍,心态很容易崩。

2. 证书、Bundle ID与描述文件:苹果签名体系中三个易混概念的正解

iOS的签名体系对新手来说非常劝退。证书、标识符、描述文件这三个名词经常听着听着就混了。我试着用生活化的方式讲清楚,这套逻辑一旦通了,后面所有上架操作都会顺畅很多。

2.1 三者的职责划分:身份证、门牌号与通行证

Bundle ID相当于App的门牌号,它让系统能准确识别“你是哪个App”。苹果后台里注册的Bundle ID必须与Xcode工程里的Build Settings > Product Bundle Identifier完全一致,包括大小写。

证书(Certificates)相当于你的身份证,证明“这是经过验证的开发者发布的”。证书分为开发证书(Development)和分发证书(Distribution),上架用的是Apple Distribution类型的分发证书。

描述文件(Provisioning Profile)相当于通行证,它把证书、Bundle ID和允许运行的真机设备绑定在一起。上架用的描述文件叫App Store Connect类型的Distribution Profile。

这三者的关系可以这样理解:Bundle ID告诉系统你是谁,证书证明你确实是你说的那个人,描述文件则决定你这个身份在哪个App的哪个环境里可以合法使用。其中任何一个不匹配,编译阶段或者上传阶段就会直接报错。

2.2 在开发者后台和Xcode里的实际操作路径

现在的Xcode其实已经大大简化了这些操作。如果你的账号在Xcode里登录过,并且开启了Automatically manage signing,那么Xcode会自动帮你生成和匹配证书与描述文件。具体操作路径是:

打开Xcode工程,选中Target,进入Signing & Capabilities。

勾选“Automatically manage signing”。

Team选择你的开发者团队。

Bundle Identifier填好后,Xcode会自动在开发者后台为你注册这个App的标识符。

如果勾选自动管理签约后出现“No account with team ID”之类的问题,多半是开发者账号还没激活,或者该Apple ID没加入开发者计划。去开发者后台确认一下Membership状态即可。

不过有一点要注意:自动管理虽然省心,但在做App内购买(IAP)或者推送配置时,有些能力(如Push Notifications、In-App Purchase)是需要到后台手动开启App ID的Capabilities的。如果遇到“Capabilities无法添加”的情况,大概率是这一步漏了。

2.3 证书和描述文件过期的真实坑

签名体系里最常见的翻车点就是过期。开发证书有效期是一年,描述文件根据不同情况有效期不一,上架用的App Store Connect描述文件通常也是按年签发的。

我自己的习惯是:每次上架前,先到开发者后台的Certificates, Identifiers & Profiles页面看一眼证书到期时间。如果发现快到期了,提前几个月就重新生成一份。不要等到打包时才发现证书失效,那种“一切就绪但证书过期”的挫败感真的非常容易劝退人。

另外,描述文件过期后,Xcode在Archive时会提示“Provisioning profile doesn't include signing certificate”。看到这句话,第一反应应该是去看描述文件的有效期,而不是怀疑证书本身有问题。

3. App Store Connect后台:那些看着简单、填错就影响审核的细节

App Store Connect是苹果的后台管理系统,上架和审核相关的所有操作都在这里完成。很多人以为填后台信息是一件“随便填填就行”的事情,实际上这里面的细节非常多,而且直接关系到审核效率和过审率。

3.1 应用名称、副标题与关键词的取舍之道

App名称(Name)在后台的“App信息”页面填写,展示在App Store上的名称长度限制是30个字符。这里有个很重要的点:名称并不一定要和工程里的Bundle ID对应的产品名完全一致,你可以起一个更适合商店搜索习惯的名字。

副标题(Subtitle)是iOS 11之后引入的字段,最多30个字符,会展示在App Store首页卡片上。它和名称一起构成了App Store搜索结果里最重要的两个文本权重来源,写得好能显著提升转化率。

关键词(Keywords)最多100个字符,用英文逗号分隔。苹果明确禁止在关键词里重复品牌名、填充无关热词、或者使用其他App的名称。我见过不少人在这里堆了几十个词,结果被审核团队以“误导性元数据”驳回。关键词写法的正确姿势是:核心词靠前,优先组合词而不是单个词,不要带空格和标点。

3.2 截图与预览物料:尺寸、内容与本地化要求

App Store对截图的要求相当细致,6.7英寸、6.5英寸、5.5英寸、5.8英寸几个档位,按你App支持的设备类型,有些规格需要指定尺寸上传。截图必须真实反映App界面,不能使用未经标注的合成图或者隐藏功能的“演示模式”。

给到你的实操建议:优先准备6.7英寸(iPhone 15 Pro Max等设备)和6.5英寸的截图,这是App Store主要展示的尺寸。每张截图的第一个屏幕至关重要,它会直接出现在搜索结果和Today推荐里,所以第一张一定要放最核心的功能界面。

如果App支持多语言,后台的每个本地化语言版本都需要单独上传对应语言内容的截图。这一步经常被忽略,导致审核团队看到英文界面的截图与实际中文界面不符而被打回。

3.3 隐私政策、年龄分级与出口合规这些“隐形关卡”

App Store Connect后台里有几个非开发类字段,看着不起眼,实际审核权重很高。

隐私政策网址是必填项。如果你有产品,可以直接放产品隐私政策页;如果没有产品,也可以用托管服务的隐私政策模板页。这里一定要填真实有效的可访问地址,审核团队会真的打开看。最好避免用临时生成的短链,也不要放需要登录才能查看的页面。

年龄分级(Age Rating)在“App信息”页面的“年龄分级”区域填写。苹果提供了一套问卷式的选项,包括是否包含色情、暴力、赌博、酒精、药品等内容。不同游戏类型还有额外的分级问卷。这里要注意:问卷结果会自动映射到不同国家/地区的分级体系,填得太低容易有问题,填得太高则会限制流量。按照实际情况如实填写即可,不必刻意压级。

出口合规信息(Export Compliance)通常在提交构建版本时会出现,问你的App是否包含加密功能。如果你的App用了HTTPS、内置加密库或自定义加密逻辑,理论上就属于“使用加密”。实际填写的技巧是:只要你的App没有使用非标准加密算法,一般都可以选择“豁免”。HTTPS这种系统级加密不算需要申报的类型,选豁免就好。如果实在拿不准,建议选需要申报,然后等待审核团队进一步询问。

3.4 三种发布方式的区别:手动发布与自动发布

在App Store Connect后台“App信息”页面的“发布”部分,可以选择“自动发布”或“手动发布”。这个选择看似简单,但对上架节奏影响巨大。

选择自动发布的意思是,当审核通过后,App会自动在当天进入“可供销售”状态。选择手动发布则是审核通过后,App进入“等待发布”状态,需要你手动点击“发布此版本”按钮。

我的建议是:首次上架选自动发布,简化流程;后续版本更新,尤其是带来重大功能调整时,选手动发布,可以避开周末或节假日这种数据波动期,让你有更多控制空间。

4. 上传与测试:从Xcode Archive到TestFlight,中间的真实报错排查

后台信息填好后,就到了真正打包上传的环节。这一步对经验的依赖程度非常高,很多报错信息看起来吓人,实际上原因很单纯,一部分报错信息还非常具有误导性。

4.1 Archive、上传与构建版本的处理链路

在Xcode里,选择Any iOS Device(或者Generic iOS Device)作为编译目标,然后通过菜单Product > Archive打包。Archive完成后,Xcode会自动打开Organizer窗口,里面列出所有归档包。

点击右上角的“Distribute App”,选择“App Store Connect”选项,然后按向导走完。这里要特别注意,第一次分发时会询问是否包含Bitcode。现在苹果已经不强制要求Bitcode,保持默认关闭状态即可。后续几步会让你选择签名方式,确认使用自动签名的分发证书后,Xcode就会开始上传。

上传成功的标志:Organizer窗口中你的归档包状态变为“Uploaded”,同时App Store Connect后台的“构建版本”区域会按顺序出现在“TestFlight”或“审核”区域。构建版本从上传到后台出现通常有几分钟延迟,耐心等待,不要重复上传。

4.2 上传报错的几类真实原因与排查思路

上传阶段我遇到过的报错,归纳起来主要有三类:

第一类是网络层问题。错误信息常常是“The network connection was lost”或者“Your session has expired”。这类问题最常见的原因是网络直连不稳定。可以试试切换网络环境,或者退出 Xcode 账号重新登录,大多数都能解决。

第二类是证书问题。Xcode 弹窗提示“No accounts with iTunes Connect access”或者“Unable to process request”。遇到这种问题,去开发者后台确认分发证书是否有效,去 Xcode 的 Accounts 设置里确认账号是否加入了对应的 Team,两步检查通常就能定位。

第三类是“ITMS-90078”这类带有明确代码的报错。这类代码背后往往对应的是元数据缺失、缺少隐私政策、缺少必要权限描述等具体问题。建议直接在 App Store Connect 后台的“功能 → App 隐私”和“App 信息”里逐项检查。ITMS-90078 的常见原因是缺少“用途字符串”说明——也就是 Info.plist 里对应权限的 NS*UsageDescription。

4.3 TestFlight内测:上架前最应该利用的环节

构建版本上传成功后,第一站是 TestFlight。很多开发者直接跳过内测就把版本提交审核,这个习惯其实很亏。

TestFlight 可以让你邀请最多 100 名内部测试员和 10000 名外部测试员,在真机上先试用你的 App。这一步的价值不只是发现 Bug——很多时候,审核团队会先跑一遍你的 App,如果启动就崩、主流程走不通,那么任何元数据上的努力都白费了。至少自己用 TestFlight 安装一遍,跑通完整的注册、登录、支付、主要功能路径,再提交审核,能省掉至少两三天的往返沟通时间。

TestFlight 本身还有个常被忽略的细节:外部测试需要提交“测试说明”和“Beta 版 App 审核”,也就是 Beta App Review,这个审核通过后你的测试链接才能发给外部用户。首次配置时留出一天时间比较稳妥。

5. 审核被拒:常见理由、攻防策略与申诉的正确姿势

提交审核之后,等待一般是 1 到 3 天。苹果的审核时间波动很大,工作日上午提交往往比周五晚提交更快。审核被拒不是世界末日,被拒后怎么高效沟通、怎么修改再提,才是真正见经验的地方。

5.1 元数据类拒绝:占被拒比例最高的一种

元数据被拒在审核反馈里通常显示为“Guideline 2.3 - Performance - Accurate Metadata”。常见触发点包括:App 名称包含“免费”等营销词、截图与 App 实际功能不符、描述里声称支持某些实际上看不到的功能、关键词堆砌相关词汇。

这类拒绝一般不需要改代码,只需要在 App Store Connect 后台修改对应的元数据内容,然后重新提交审核即可。修改完记得在“App 信息”页面右下角点击“提交审核”,而不是以为保存就够了。

5.2 功能与隐私类拒绝:需要真正修改App的情况

功能类拒绝最常见的理由是:App 无法正常登录、需要付费才能体验完整功能但与描述不符、包含 UGC 内容却没有举报和屏蔽机制、崩溃或闪退。

隐私类拒绝在近年明显增多,常见的是:收集用户数据但没有清晰告知、隐私政策链接无法访问、使用了 API 但不满足“App 跟踪透明度”的要求。

收到这类拒绝时,不要急着重新提交。先在“解决方案中心”的线程里,用英文(或者其他审核人员使用的语言)清晰地回复你的处理方案,说明已做修改的细节和原因。回复后点“提交审核”即可,不用重新上传构建版本,除非你修改了代码。

5.3 加急审核与申诉:什么时候用、怎么用

如果你的App因为线上严重Bug需要紧急发布,或者审核超过预期时间且事态紧急,可以使用加急审核(Accelerated Review)。进入App Store Connect后,在“联系我们”页面选择“App Review”→“Request an expedited review”,并填写理由。

加急审核不是随便用的。滥用会被列入“不诚信名单”,后续所有审核都会被特殊对待。我个人的原则是:非紧急时刻绝不用加急,平时正常排队,一般2-3天足够。

如果被拒后你认为是苹果审核判断有误,可以在拒绝通知里选择“Appeal”提交申诉。申诉的关键是把该版本与上一个通过审核的版本差异说清楚,用简短的语言说明问题出在沟通误解而不是产品本身。申诉响应的速度通常比新提交审核要快,但成功率还是要看具体案例是否真的有争议。

5.4 审核期间你能做的几件事

等待审核的时候,不少人会反复刷新后台,这很正常,但没必要。更有价值的做法是:把App Store页面上的“宣传文本”(Promotional Text)提前写好,审核通过后第一时间发布;准备好发布当天的推广物料;如果App是订阅制,提前确认内购项目状态是“准备提交”还是“已批准”;同时可以开始准备第一个版本的用户反馈渠道。

审核结果出来后,不论通过与否,记得去后台看完整的“审核备注”。有时候审核团队会附上视频或截图,显示具体问题位置,这些信息可以根据反馈再次查阅。

6. 上架之后的更新节奏:版本迭代、审核周期与日常维护

App上架不是终点,而是一个新的起点。版本更新的审核节奏、发布时机的选择、日常维护的细节,都直接影响App的长期数据表现。

6.1 版本更新的审核周期与提交窗口

版本更新的审核周期通常比首发审核快,很多情况下1-2天就能过。但如果你选择在周五下午提交,大概率要等到下周一甚至周二才能过审,因为周末审核团队人手少。想要让新版本在周一早上发布的话,周五上午提交是比较理想的窗口。

另外注意:新版本上传的构建版本,必须使用当前的Xcode版本重新打包。不要试图复用旧构建版本,尤其是跨越了iOS系统大版本更新之后,复用老构建会有非常明显的兼容性和合规风险。

6.2 审核通过后的第一小时应该做什么

审核通过后,App并不会自动出现在所有用户面前,搜索结果收录和推荐位更新通常需要几小时到一天的时间。这个阶段可以做的事包括:更新宣传文本、确认内购项目状态、观察首批下载数据。

还有一个容易被忽略的操作:把审核通过的版本设置为“手动发布”时,通过后不会自动上线,而是停留在“等待发布”状态。如果你在后台发现新版本下方有“发布此版本”按钮,记得点击确认,否则App会一直处于未上架状态。

6.3 日常维护中最常被问到的几个坑

被问得最多的问题是:“我改了代码想更新,但忘了原来的证书在哪一台电脑上生成的。”这个问题在新电脑上尤其常见。实际解决办法是:在开发者后台重新生成证书,不需要找回旧私钥。因为分发证书和推送证书都可以重新创建,重新生成后旧的证书会失效,但基本不影响线上App的使用,除非你在用旧证书做推送服务。

另一个常见问题是:“为什么我的App在商店里搜不到?”原因通常有三种:搜索关键词没有覆盖到用户习惯的词汇(不是技术问题,是关键词策略问题);新上架App的搜索权重本来就很低,过几天会自然上升;或者该地区还没有完成发布。如果上架已经一整天并且状态是“可供销售”,那大概率就是关键词策略的问题,建议下一版本更新时调整关键词布局。

我自己走过一遍完整流程后,最大的感受是:上架这件事,流程本身并不复杂,真正需要花心思的是对细节的掌握程度。很多失败并不是因为产品差,而是因为某个字段填错、某个证书过期、某个权限说明没写清楚。把上面这些环节都梳理顺畅了,你大概率能比大多数人少折腾一半时间。

收起阅读 »

举报涉嫌冒充 HBuilderX 官方下载渠道 分发捆绑恶意远控的安装包

官网 病毒

涉事网址:https://hbuilderx.app/cn/index.html

这个网站在搜索排名极度靠前 比官网还靠前

.10 月 10 日本人从上述页面下载 hbuilderx-win.zip。本机 Chrome 下载记录显示,下载链经过 1.startss-downloading.icu,最终文件地址为:
https://pub-6a90252f6d70443d960d6ac029dbd446.r2.dev/hbuilderx-win.zip

解压运行该安装包后,系统于当日 安装了 ScreenConnect 远程控制服务,服务名为 14.38.33135.0,程序隐藏在 C:\Program Files (x86)\Microsoft Visual C++ 2022\ScreenConnect.ClientService.exe,连接地址为 442.open-fast-ports.com:8041,启动参数带有 c=hbuilderx 标记。安装过程中也安装了正常的 HBuilderX,使捆绑远控不易被察觉。

.2026 年 10 月 14 日 09:07:29,该远控的事件日志记录执行远程命令;9 秒后,系统中出现恶意加载器 C:\ProgramData\Microsoft\Windows\Caches\4259B89A\RuntimeHost.exe。随后出现后台挖矿、恶意启动项、杀毒排除项,以及窃取浏览器 Cookie 和 Cursor 登录令牌的记录。显卡曾持续接近 100% 负载,温度达到约 82~83℃。
已保留的木马原始日志包含以下文字:

2026-10-14 09:09:55 | CursorHarvester: STEAL_CURSOR: 6 token(s) uploaded.  
2026-10-14 09:14:26 | CookieHarvester [immediate]: 113 cookies uploaded=True  
2026-10-14 09:44:01 | CookieHarvester [chrome (delayed)]: 3767 cookies uploaded=True

本人已保留浏览器下载来源记录、服务安装及远控执行事件日志、恶意程序日志和文件哈希。请求核查该网站及关联下载地址,阻断恶意安装包传播

继续阅读 »

涉事网址:https://hbuilderx.app/cn/index.html

这个网站在搜索排名极度靠前 比官网还靠前

.10 月 10 日本人从上述页面下载 hbuilderx-win.zip。本机 Chrome 下载记录显示,下载链经过 1.startss-downloading.icu,最终文件地址为:
https://pub-6a90252f6d70443d960d6ac029dbd446.r2.dev/hbuilderx-win.zip

解压运行该安装包后,系统于当日 安装了 ScreenConnect 远程控制服务,服务名为 14.38.33135.0,程序隐藏在 C:\Program Files (x86)\Microsoft Visual C++ 2022\ScreenConnect.ClientService.exe,连接地址为 442.open-fast-ports.com:8041,启动参数带有 c=hbuilderx 标记。安装过程中也安装了正常的 HBuilderX,使捆绑远控不易被察觉。

.2026 年 10 月 14 日 09:07:29,该远控的事件日志记录执行远程命令;9 秒后,系统中出现恶意加载器 C:\ProgramData\Microsoft\Windows\Caches\4259B89A\RuntimeHost.exe。随后出现后台挖矿、恶意启动项、杀毒排除项,以及窃取浏览器 Cookie 和 Cursor 登录令牌的记录。显卡曾持续接近 100% 负载,温度达到约 82~83℃。
已保留的木马原始日志包含以下文字:

2026-10-14 09:09:55 | CursorHarvester: STEAL_CURSOR: 6 token(s) uploaded.  
2026-10-14 09:14:26 | CookieHarvester [immediate]: 113 cookies uploaded=True  
2026-10-14 09:44:01 | CookieHarvester [chrome (delayed)]: 3767 cookies uploaded=True

本人已保留浏览器下载来源记录、服务安装及远控执行事件日志、恶意程序日志和文件哈希。请求核查该网站及关联下载地址,阻断恶意安装包传播

收起阅读 »

自动化测试,可能与不可用

自动化测试 HBuilderX

HBuilderX 官方自动化测试 CLI 连接与运行指南

文档定位

本文档总结 HBuilderX 官方自动化测试 CLI 在 Web 测试中的完整连接链路,重点说明以下问题:

  • CLI 在什么条件下可以连接正在运行的 HBuilderX;
  • HBuilderX 官方测试在什么条件下可以连接项目运行时;
  • 已运行的 Web 服务在什么条件下可以被复用;
  • 什么情况属于 CLI 连接失败、运行时连接失败、编译失败、测试失败或环境阻塞;
  • 如何用日志和官方 JSON 报告判断测试结果是否有效。

本文不依赖某个具体业务项目,不包含项目名称、业务页面、项目目录和本机用户信息。

结论摘要

官方 Web 自动化测试不是单一连接,而是连续的多阶段流程:

官方 CLI  
  │  
  ├── 连接 HBuilderX GUI 和官方 CLI 能力  
  │  
  ├── 打开或识别测试项目  
  │  
  ├── 启动或连接 Web 页面服务  
  │  
  ├── 连接页面对应的 Automator WebSocket 运行时  
  │  
  └── 执行测试并生成官方 JSON 报告

只有最后一阶段也得到有效报告,才能说明一次官方测试完整完成。

“CLI 能找到 HBuilderX”不等于“官方测试通过”;“页面能在浏览器中打开”也不等于“Automator 运行时可以连接”。

文档目录

01-连接链路与正式状态

说明 CLI、HBuilderX、Web 服务、Automator 和测试报告之间的关系,并定义“可正常执行”“失败”“阻塞”等正式状态。

02-验证环境与场景矩阵

记录本次实际验证环境,以及已经执行过的正向、负向和边界场景。

03-排查手册

提供从 CLI 连接到测试报告的逐步排查流程、日志关键词和常见误区。

04-验证记录模板

提供可以复制到其他机器或其他版本环境中的验证记录模板。

正式术语

本文尽量不使用“顺利”“不顺利”这类含义不明确的说法,统一使用以下术语:

术语 含义
CLI 连接成功 CLI 找到并成功调用目标 HBuilderX 的官方 CLI 能力
项目打开成功 CLI 的项目打开操作返回成功,HBuilderX 能识别目标项目
Web 服务启动成功 页面 HTTP 服务能够启动并返回页面资源
Automator 连接成功 测试运行时与页面内置的 Automator WebSocket 完成连接
测试执行通过 测试套件和测试用例实际运行,并且指定断言通过
测试环境阻塞 因工具、服务、端口、设备或权限问题,测试没有有效执行
测试脚本无效 测试文件没有正确解析、没有有效断言,或证据不能证明目标行为

如何使用本文档

遇到问题时建议按以下顺序阅读:

  1. 先阅读 01-连接链路与正式状态,确定问题处在哪一层;
  2. 再对照 02-验证环境与场景矩阵,确认当前环境属于哪种场景;
  3. 按 03-排查手册 检查日志、端口和报告;
  4. 使用 04-验证记录模板 记录版本、配置、证据和边界。

适用范围

本文主要针对:

  • HBuilderX 官方 Web 自动化测试;
  • uniapp.test web-chrome 测试入口;
  • uni-app x Web 编译服务;
  • Playwright Chromium 和 Automator WebSocket 运行时;
  • CLI 连接 HBuilderX、连接项目和判断官方测试结果。

本文不替代以下内容:

  • 业务页面测试用例设计;
  • Android 真机键盘、焦点和生命周期验收;
  • Tauri WebView、Rust 宿主和 SQLite 验收;
  • 生产环境部署或发布构建说明。

版本边界

本次验证使用的环境和结论见 02-验证环境与场景矩阵。HBuilderX、uni-app x 编译器或官方测试插件升级后,应重新记录版本并复测关键正向、负向场景。

官方参考资料

01. 连接链路与正式状态

1. 完整连接链路

官方 Web 自动化测试应拆成三个阶段。三个阶段的通过标准不同,不能用前一个阶段的结果替代后一个阶段的结果。

阶段一:CLI → HBuilderX  
阶段二:HBuilderX 官方测试 → Web/Automator 运行时  
阶段三:测试套件 → 有效测试报告

阶段一:CLI 连接 HBuilderX

该阶段确认测试入口能够找到并调用 HBuilderX。

主要检查:

  • HBuilderX GUI 是否正在运行;
  • CLI 是否找到可用的 cli.exe;
  • CLI 和 GUI 是否来自同一套 HBuilderX 安装;
  • CLI 是否能执行项目打开操作;
  • HBuilderX 官方测试插件是否被正确加载;
  • 官方测试命令是否真正开始运行。

阶段一通过,只能说明控制入口可用,不能说明页面运行时已经连接。

阶段二:官方测试连接 Web/Automator 运行时

该阶段确认浏览器页面和自动化运行时可以被测试执行器使用。

需要同时检查两条通道:

HTTP 通道:       CLI → h5.url → Web 页面  
Automator 通道:  CLI → WebSocket → 页面运行时

HTTP 通道负责页面和资源访问。Automator 通道负责页面对象查询、点击、输入、路由和断言等自动化操作。

页面能打开而 Automator 不能连接时,仍然不能执行有效的官方自动化测试。

阶段三:测试套件执行并生成有效报告

该阶段确认测试文件确实被解析、执行并产生可信证据。

至少需要确认:

  • 测试套件数量大于零;
  • 测试用例数量大于零;
  • 测试文件没有语法错误;
  • 没有运行时连接异常;
  • 断言结果符合预期;
  • 官方 JSON 报告已经生成。

如果 CLI 找到了 HBuilderX,但测试套件没有执行,不能报告为完整通过。

2. 三种连接结果必须分开描述

2.1 CLI 连接 HBuilderX 成功

表示:

  • HBuilderX GUI 已被检测到;
  • CLI 找到了对应的官方 CLI 程序;
  • 项目打开命令返回成功;
  • 官方测试插件开始处理测试命令。

这只是控制层连接成功。

2.2 Automator 运行时连接成功

表示:

  • 浏览器已经打开 h5.url 指向的页面;
  • 页面编译结果包含 Automator 连接配置;
  • CLI 使用的主机和端口能够访问页面运行时;
  • 日志出现 connected 或 program ready。

这才说明页面具备被官方自动化操作的条件。

2.3 测试报告有效

表示:

  • 测试文件已经被 Jest 正确解析;
  • 至少一个测试套件和一个测试用例实际执行;
  • 报告中的失败和运行异常数量符合预期;
  • 通过结果与测试动作和断言一致。

这才可以报告一次完整的官方测试通过。

3. 正常使用条件

3.1 CLI 连接 HBuilderX 的条件

要使 CLI 能够连接 HBuilderX,通常需要满足:

  1. HBuilderX GUI 正在运行;
  2. 使用的 CLI 与当前 HBuilderX 属于同一版本体系或同一安装目录;
  3. CLI 能够找到官方 CLI 程序;
  4. 项目路径有效,并且包含可被 HBuilderX 识别的 uni-app x 工程文件;
  5. HBuilderX 的测试插件已经安装并且没有被禁用;
  6. CLI 项目打开操作没有超时或异常退出。

3.2 官方测试连接运行时的条件

要使页面运行时可被官方测试连接,通常需要满足:

  1. 页面 HTTP 服务已经启动;
  2. h5.url 指向正确的页面地址;
  3. 页面编译时已经配置 Automator WebSocket;
  4. Automator 主机地址可以从测试进程访问;
  5. 页面使用的 Automator 端口与 CLI 使用的端口一致;
  6. 页面服务和 Automator 服务在测试期间保持运行。

3.3 测试结果有效的条件

要把结果报告为通过,还需要满足:

  1. 测试文件可以解析;
  2. 测试套件实际启动;
  3. 测试用例数量大于零;
  4. 测试动作确实通过官方自动化 API 执行;
  5. 官方 JSON 报告已经生成;
  6. 没有把环境阻塞或脚本无效误判为通过。

4. 不正常使用的典型情况

4.1 HBuilderX 没有运行

CLI 无法连接 GUI 控制入口。此时不应把问题归类为业务页面测试失败,应记录为环境阻塞。

4.2 CLI 找到的 HBuilderX 与当前 GUI 不一致

可能出现以下问题:

  • CLI 使用了另一套 HBuilderX 的 cli.exe;
  • 编译器版本与测试插件版本不匹配;
  • CLI 打开的项目和 GUI 当前项目不是同一个实例;
  • 测试配置被不同版本的插件以不同方式修改。

排查时应记录 GUI 版本、CLI 路径、CLI 输出版本和编译器版本。

4.3 CLI 可以连接 HBuilderX,但项目打不开

这表示控制入口可用,但项目识别或项目路径存在问题。应单独记录项目打开失败,不要直接归类为 Automator 失败。

4.4 CLI 可以连接 HBuilderX,但 Automator 连接失败

这通常表示阶段一通过、阶段二失败。常见原因包括:

  • h5.url 指向普通 HTTP 服务;
  • 页面没有注入 Automator 地址;
  • 页面和 CLI 使用不同的 Automator 端口;
  • Automator 主机地址不可达;
  • 页面服务已经重启,CLI 仍连接旧端点。

4.5 Automator 已连接,但测试脚本没有有效执行

这通常是阶段三问题,常见原因包括:

  • 测试文件语法错误;
  • 测试范围没有包含目标文件;
  • 测试文件没有有效用例;
  • 断言或页面入口本身有问题;
  • 报告生成失败。

5. Web 服务复用在完整链路中的位置

“复用已经运行的 Web 服务”只是阶段二的一种运行方式,不是 CLI 连接 HBuilderX 的全部定义。

5.1 CLI 自行编译

CLI 负责启动 Web 编译服务和 Automator 运行时。这种方式中,CLI 的服务生命周期最清晰,适合先验证工具链本身。

5.2 复用带 Automator 的已有服务

已有服务必须同时提供:

  • 页面 HTTP 地址;
  • 页面编译时注入的 Automator WebSocket 地址;
  • CLI 可以访问的主机和端口。

5.3 复用普通 GUI Web 服务

普通 GUI Web 服务可以成功返回页面,但如果没有 Automator 端点,不能直接作为官方自动化测试服务复用。

6. 正式状态定义

建议统一使用以下状态,避免“可用”“不顺利”等表达产生歧义。

状态 正式含义 是否可以报告为通过
passed 指定连接检查和测试用例均已实际执行并通过 可以,但仅限已覆盖范围
failed 测试已经执行,但连接、代码或断言实际失败 不可以
blocked 因 HBuilderX、服务、端口、权限或工具链问题,测试没有有效执行 不可以
incomplete 测试能够运行,但覆盖范围或必要验证尚未完成 不可以作为完整通过
test-invalid 测试脚本没有有效执行,或证据不能证明目标行为 不可以

7. 结论表达示例

正确表达

CLI 已成功连接 HBuilderX,项目打开操作返回成功;但 Automator 运行时未完成连接,因此本次 Web 自动化测试记录为 failed,不能报告为完整通过。

页面 HTTP 服务访问正常,Automator WebSocket 端口与 CLI 配置一致,测试报告包含一个通过套件和一个通过用例,因此该复用场景在本次环境中验证通过。

HBuilderX GUI 未运行,CLI 测试入口未能建立,测试没有有效执行,因此记录为 blocked。

不建议表达

  • “HBuilderX 可以用,所以测试可以用”;
  • “页面能打开,所以自动化通过”;
  • “CLI 启动了,所以测试已经完成”;
  • “没有看到错误,所以应该通过”;
  • “compile:false 就会自动复用开发服务”。

02. 验证环境与场景矩阵

1. 本次验证环境

本节记录实际验证环境,帮助读者判断版本差异。文档不记录具体业务项目名称、项目目录和用户信息。

1.1 工具链

  • 操作系统:Windows 桌面环境;
  • 命令行环境:PowerShell;
  • HBuilderX 安装目录:D:\App\HBuilderX;对外分享时可替换为 <HBuilderX-root>;
  • HBuilderX 官方 CLI:<HBuilderX-root>\cli.exe;本次验证对应 D:\App\HBuilderX\cli.exe;
  • HBuilderX 内置 Node.js:由 <HBuilderX-root>\plugins\node\node.exe 提供;
  • HBuilderX:5.31.2026093020-alpha;
  • HBuilderX 官方自动化测试 CLI:命令行输出版本 5.4.0;
  • uni-app x 编译器:5.31,VDOM 模式;
  • 测试平台:web-chrome;
  • 浏览器驱动:Playwright Chromium;
  • 浏览器模式:无头模式;
  • 页面测试视口:官方运行时默认移动端视口。

1.2 HBuilderX 和 CLI 状态

本次运行入口要求 HBuilderX GUI 已经启动。测试脚本先检查 HBuilderX 进程,再解析与当前安装对应的 cli.exe。

CLI 执行项目打开操作后,再调用官方 Web 自动化测试命令。已实际观察到项目打开命令返回成功,说明控制入口阶段可以建立。

1.3 Web 服务状态

本次验证使用了两类服务:

普通 GUI Web 服务

  • 页面地址示例:http://127.0.0.1:5173/;
  • HTTP 请求可以得到成功响应;
  • 进程参数为普通 uni-app x Web 启动方式;
  • 未发现 --auto-port 或 --auto-host;
  • /main 响应中未发现可供测试运行时使用的 Automator 端点。

带 Automator 地址的独立 Web 服务

  • 页面地址示例:http://127.0.0.1:5174/;
  • Automator 主机:127.0.0.1;
  • Automator 端口示例:9538;
  • 服务启动时明确注入 Automator 地址;
  • 用于验证“官方 CLI 复用带 Automator 端点的已有服务”。

1.4 环境边界

本次矩阵只验证 Web 自动化测试连接链路,不包含:

  • Android 真机或模拟器自动化;
  • Tauri WebView 和 Rust 宿主;
  • 数据库读写和业务数据验收;
  • 完整业务页面覆盖;
  • 远程机器、局域网和跨主机防火墙验证。

2. 场景矩阵

下表覆盖了判断核心连接条件所需的关键正向和负向场景。它不是所有配置组合的穷举。

编号 场景 阶段一:CLI → HBuilderX 阶段二:Web/Automator 阶段三:测试报告 结果
A CLI 自行编译并启动 Web 服务 成功 成功 有效通过报告 可正常执行
B 复用带 Automator 的已有服务 成功 页面地址和端口匹配,连接成功 1 个冒烟用例通过 可以复用
C 复用普通 GUI Web 服务 成功 页面可访问,但 Automator 连接失败 运行时异常或无有效用例 不能复用
D 已有服务端口与 CLI 端口不一致 成功 Failed to connect to runtime 测试未有效开始 连接失败
E compile:false、无 h5.url、绑定地址无效 成功 CLI 自行编译时 EADDRNOTAVAIL 未生成有效报告 环境阻塞
F compile:false、无 h5.url、本机地址有效 成功 CLI 仍尝试自行编译,未复用 GUI 服务 超时或无有效报告 环境阻塞
G 检查 GUI 服务是否自带 Automator 成功 当前 GUI 服务未发现端点 不适用 普通 Web 服务

3. 各场景说明

3.1 场景 A:CLI 自行编译并启动

该场景中,官方 CLI 自己启动编译器和 Automator 运行时。

验证重点:

  • 主机地址可以被当前机器绑定;
  • 编译服务可以启动;
  • CLI 能够打开页面;
  • Automator 运行时能够连接;
  • 测试报告中存在实际执行的测试用例。

该场景可以证明官方 CLI 自己管理整条链路时能够工作,但不能证明普通 GUI 服务可以被复用。

3.2 场景 B:复用带 Automator 的已有服务

该场景中,先启动页面服务,并在编译时注入 Automator 地址,再让官方 CLI 使用相同的页面地址和 Automator 端口。

成功条件:

页面地址:       http://127.0.0.1:5174/  
页面 Automator: 127.0.0.1:9538  
CLI Automator:   127.0.0.1:9538

本次验证中,运行日志出现了 Automator 连接和 program ready,并且冒烟用例通过。这证明“已有服务复用”本身是可行的,但前提是服务已经具备 Automator 能力。

3.3 场景 C:复用普通 GUI Web 服务

该场景中,页面地址可以访问,但服务只提供普通 HTTP/Vite 能力,没有对应 Automator 端点。

实际表现:

  • 浏览器上下文可以创建;
  • 页面 URL 可以被访问;
  • 运行时连接阶段失败;
  • 出现 Failed to connect to runtime;
  • 测试套件可能没有真正执行。

这说明页面服务可访问和官方自动化可用是两个独立条件。

3.4 场景 D:端口不一致

已有页面服务在编译时使用 Automator 端口 9538,而 CLI 运行时使用动态分配的 9539。

两个进程可能都处于运行状态,但它们不会自动建立同一个 Automator 会话,最终表现为运行时连接失败。

3.5 场景 E:无效绑定地址

在 compile:false 且没有 h5.url 的配置下,CLI 仍尝试启动自己的编译服务。如果 Automator 主机被设置为当前机器不存在的地址,编译器会在监听阶段报:

EADDRNOTAVAIL: address not available

这属于服务启动失败,不属于测试用例断言失败。

3.6 场景 F:compile:false 但没有 h5.url

将绑定地址改为 127.0.0.1 后,CLI 仍尝试启动自己的编译服务。由于 GUI 已占用默认页面端口,CLI 改用其他页面端口,但没有自动复用 GUI 服务,最终测试没有有效完成。

该结果说明:

compile:false 不是“自动查找并复用已有 Web 服务”的充分条件。

3.7 场景 G:检查 GUI 服务是否自带 Automator

本次检查包括:

  • 查看 Web 服务进程启动参数;
  • 查看页面入口响应;
  • 检查页面和日志中是否存在 Automator 地址;
  • 检查对应 Automator 端口是否监听。

当前 GUI 服务是普通 Web 编译服务,没有发现官方自动化复用所需的 Automator 端点。

4. 环境与结论的边界

4.1 已确认的事实

  • 当前版本的官方 CLI 可以连接正在运行的 HBuilderX;
  • CLI 可以执行项目打开操作;
  • CLI 可以自行编译并运行 Web 自动化测试;
  • 带匹配 Automator 地址的已有服务可以被复用;
  • 普通 HTTP/Vite 服务不能仅凭页面地址被复用;
  • Automator 端口不一致会导致运行时连接失败;
  • compile:false 不足以单独决定复用哪一个已有服务;
  • 无效主机地址会导致编译服务启动失败。

4.2 尚未穷举的组合

以下内容没有在本次矩阵中全部穷举:

  • 其他 HBuilderX 版本的 CLI 与 GUI 组合;
  • 不同操作系统下的网络绑定行为;
  • 局域网地址和远程测试机之间的连接;
  • GUI 中可能新增的 Automator 服务启动选项;
  • 所有 compile、h5.url、主机、端口排列组合;
  • 完整业务页面和多页面测试。

因此,本文应使用“在本次验证环境中确认”这样的表述,不应宣称已经验证了所有版本和所有配置。

5. 复现记录最少应包含的环境信息

  • 操作系统和命令行环境;
  • HBuilderX 版本;
  • 官方 CLI 输出版本;
  • uni-app x 编译器版本和渲染模式;
  • 测试平台和浏览器驱动;
  • HBuilderX GUI 是否正在运行;
  • CLI 实际使用的路径;
  • 项目打开结果;
  • 页面 HTTP 地址和端口;
  • Automator 主机和端口;
  • compile、h5.url 和自定义环境变量;
  • 测试报告路径和套件/用例统计;
  • 未覆盖的场景和环境限制。

03. 排查手册

1. 排查原则

排查时不要直接从业务断言开始。应按官方测试的实际连接顺序逐层确认:

HBuilderX GUI  
  ↓  
CLI 程序  
  ↓  
项目打开  
  ↓  
Web 页面服务  
  ↓  
Automator WebSocket  
  ↓  
测试套件  
  ↓  
官方 JSON 报告

前一层没有通过时,不要用后一层的现象解释问题。

2. 第一步:确认 HBuilderX GUI

需要确认:

  • HBuilderX 窗口或进程确实正在运行;
  • 没有停留在启动失败、更新未完成或插件加载失败状态;
  • 当前 HBuilderX 是期望使用的版本;
  • 目标项目已经被 HBuilderX 识别。

如果 HBuilderX 没有运行,CLI 通常不能依靠测试命令自行替代 GUI 控制入口。应记录为 blocked,不要报告为业务测试失败。

3. 第二步:确认 CLI 来源

记录 CLI 实际使用的完整路径和输出版本。

重点检查:

  • CLI 是否来自当前 HBuilderX 安装目录;
  • 是否存在多个 HBuilderX 安装;
  • 环境变量是否把 CLI 指向了旧安装;
  • CLI 调用的内置 Node、编译器和测试插件是否属于同一套安装。

如果 GUI 和 CLI 不是同一版本体系,首先应排除工具链混用问题。

4. 第三步:确认项目打开

CLI 项目打开操作成功,只能证明项目控制入口可用。

需要记录:

  • 项目路径是否存在;
  • 项目是否包含有效的 uni-app x 工程文件;
  • CLI 项目打开命令的退出码;
  • 是否出现“项目未打开”“项目不存在”或超时;
  • HBuilderX 是否切换到目标项目。

项目打开失败时,不要继续修改页面测试断言。应先解决工程识别或 CLI 连接问题。

5. 第四步:确认测试配置

至少检查以下配置:

5.1 compile

确认是否让官方 CLI 自己编译,还是准备复用已有服务。

不要把以下两种含义混为一谈:

  • compile:false:不应简单解释为“自动连接任意已运行服务”;
  • h5.url:只指定页面访问地址,不自动为页面添加 Automator 能力。

5.2 h5.url

如果要复用已有 Web 服务,应确认:

  • 地址指向当前实际运行的页面服务;
  • 协议、主机、端口和路径都正确;
  • 该页面服务在测试期间不会被切换或重启。

5.3 Automator 主机和端口

确认页面编译时使用的 Automator 主机、页面实际连接的端口,以及 CLI 测试运行时使用的端口。

推荐把三者记录在同一张表中:

位置 主机 端口
页面编译配置 127.0.0.1 9538
页面实际运行时 127.0.0.1 9538
CLI 测试运行时 127.0.0.1 9538

页面端口和 Automator 端口可以不同,但页面和 CLI 的 Automator 端点必须指向同一个运行时。

6. 第五步:确认 HTTP 页面服务

先验证页面 HTTP 地址,再验证 Automator。

PowerShell 示例:

Invoke-WebRequest -UseBasicParsing -Uri 'http://127.0.0.1:<web-port>/'

页面请求失败时,检查:

  • Web 服务是否已经启动;
  • 页面端口是否被其他进程占用;
  • 服务是否绑定到正确主机;
  • 服务是否在测试过程中退出;
  • CLI 日志是否显示了实际使用的 URL。

页面 HTTP 检查成功后,仍必须继续检查 Automator 端点。

7. 第六步:确认 Automator 运行时

重点查看官方测试日志中的以下信息:

automator:launcher  
automator:runtime  
connected  
program ready  
Failed to connect to runtime

7.1 出现 connected 或 program ready

说明 Automator 运行时已经建立连接,可以继续判断测试脚本和页面行为。

7.2 出现 Failed to connect to runtime

优先检查:

  1. 页面是否只是普通 HTTP 服务;
  2. 页面是否注入了 Automator 地址;
  3. 页面和 CLI 的 Automator 端口是否一致;
  4. Automator 主机是否可访问;
  5. 页面服务是否在测试前已经重启;
  6. CLI 是否连接到了旧端口或动态分配的新端口。

该错误通常不是业务用例断言失败。

7.3 出现 EADDRNOTAVAIL

说明服务尝试绑定当前机器无法使用的主机地址。应先检查主机配置和网络接口,不要先修改测试脚本。

7.4 页面端口被占用

如果日志显示 Web 服务自动换到其他页面端口,应确认:

  • h5.url 是否仍然指向旧端口;
  • 页面编译结果中的 Automator 地址是否仍然有效;
  • CLI 是否真的连接了新服务;
  • 是否因此误把端口变化当成页面测试失败。

8. 第七步:确认测试套件真正执行

Automator 连接成功后,还要确认 Jest 测试本身有效。

重点检查:

  • 测试文件是否被纳入 testMatch;
  • 测试文件是否可以被 Babel/Jest 解析;
  • 测试套件数量是否大于零;
  • 测试用例数量是否大于零;
  • 测试是否在 beforeAll 或页面启动阶段失败;
  • 页面断言是否真正执行。

如果日志显示:

Tests: 0 total

则不能把这次运行报告为功能通过。

如果出现 JavaScript 语法错误,应记录为 test-invalid 或测试脚本失败,而不是 Automator 连接成功。

9. 第八步:确认官方 JSON 报告

官方 JSON 报告是判断测试是否有效的重要证据。至少检查:

  • 报告文件是否生成;
  • numTotalTestSuites 是否大于零;
  • numTotalTests 是否大于零;
  • numRuntimeErrorTestSuites 是否为零;
  • numFailedTestSuites 是否为零;
  • numFailedTests 是否为零;
  • success 字段与详细统计是否一致。

建议不要只看终端最后一行,也不要只看退出码。退出码、日志和 JSON 报告需要相互印证。

10. 错误现象与处理方向

错误现象 优先判断 不应直接判断为
未检测到 HBuilderX GUI 或 CLI 环境阻塞 页面业务失败
项目打开失败 项目路径或 HBuilderX 识别问题 Automator 断言失败
EADDRNOTAVAIL 绑定主机地址无效 测试用例失败
Failed to connect to runtime Automator 地址、端口或注入缺失 页面 HTTP 不可访问
页面可打开但测试为 0 测试范围、脚本或运行时问题 功能通过
JavaScript 语法错误 测试脚本无效 Web 服务连接失败
生成报告但包含运行异常 测试没有完整通过 仅凭 success 字段通过
超时且没有有效报告 环境阻塞或进程未完成握手 业务断言失败

11. 常见误区

11.1 CLI 已启动,不代表 HBuilderX 已连接

CLI 进程启动只能说明命令被调用。还需要确认 HBuilderX 检测、项目打开和官方测试插件初始化结果。

11.2 HBuilderX 已连接,不代表页面运行时已连接

控制层和运行时是两个阶段。必须继续查看 Automator 日志。

11.3 页面可访问,不代表页面可自动化

普通 HTTP/Vite 服务可能没有 Automator WebSocket。

11.4 compile:false 不保证复用服务

没有 h5.url 或没有匹配的 Automator 端点时,CLI 可能自行启动编译服务,或者最终无法完成运行时连接。

11.5 动态端口不应未经确认直接使用

页面编译时注入的端口、CLI 运行时端口和页面实际连接端口必须一致。只看到 CLI 分配了端口,不代表页面已经同步使用该端口。

11.6 一个冒烟用例通过不等于完整验收通过

冒烟用例只能证明连接链路和该用例覆盖的行为。完整应用验收仍需独立的测试矩阵和必要的平台验证。

12. 推荐的最小排查命令

以下命令仅用于说明检查顺序,实际路径和端口应替换为当前环境值:

# 检查页面 HTTP 服务  
Invoke-WebRequest -UseBasicParsing -Uri 'http://127.0.0.1:<web-port>/'  

# 检查 Automator 端口  
Test-NetConnection -ComputerName 127.0.0.1 -Port <automator-port>  

# 使用 HBuilderX 官方 CLI 打开项目  
<hbuilderx-cli> project open --path <project-root>  

# 执行官方 Web 自动化测试  
<hbuilderx-cli> uniapp.test web-chrome --project <project-root>

如果当前 PowerShell 或 HBuilderX 版本不支持某个检查命令,应记录替代命令和实际输出,不要把未执行的检查写成通过。

13. 清理和恢复

测试工具可能临时修改测试范围、环境配置或生成报告文件。测试结束后应确认:

  • 仅保留用户明确需要的配置变化;
  • 临时测试文件已经清理;
  • 临时编译进程已经退出;
  • HBuilderX 原有 Web 服务没有被误停;
  • 失败证据、日志和 JSON 报告按需要保留;
  • 配置文件差异经过审查。

14. 排查结论模板

可以使用以下格式记录一次结果:

HBuilderX GUI:已运行 / 未运行  
CLI 连接:成功 / 失败  
项目打开:成功 / 失败  
页面 HTTP 服务:可访问 / 不可访问  
Automator 运行时:已连接 / 未连接  
测试套件:已执行 / 未执行  
官方 JSON 报告:有效 / 缺失 / 内容不完整  
最终状态:passed / failed / blocked / incomplete / test-invalid  
根因:  
证据:  
未覆盖范围:
继续阅读 »

HBuilderX 官方自动化测试 CLI 连接与运行指南

文档定位

本文档总结 HBuilderX 官方自动化测试 CLI 在 Web 测试中的完整连接链路,重点说明以下问题:

  • CLI 在什么条件下可以连接正在运行的 HBuilderX;
  • HBuilderX 官方测试在什么条件下可以连接项目运行时;
  • 已运行的 Web 服务在什么条件下可以被复用;
  • 什么情况属于 CLI 连接失败、运行时连接失败、编译失败、测试失败或环境阻塞;
  • 如何用日志和官方 JSON 报告判断测试结果是否有效。

本文不依赖某个具体业务项目,不包含项目名称、业务页面、项目目录和本机用户信息。

结论摘要

官方 Web 自动化测试不是单一连接,而是连续的多阶段流程:

官方 CLI  
  │  
  ├── 连接 HBuilderX GUI 和官方 CLI 能力  
  │  
  ├── 打开或识别测试项目  
  │  
  ├── 启动或连接 Web 页面服务  
  │  
  ├── 连接页面对应的 Automator WebSocket 运行时  
  │  
  └── 执行测试并生成官方 JSON 报告

只有最后一阶段也得到有效报告,才能说明一次官方测试完整完成。

“CLI 能找到 HBuilderX”不等于“官方测试通过”;“页面能在浏览器中打开”也不等于“Automator 运行时可以连接”。

文档目录

01-连接链路与正式状态

说明 CLI、HBuilderX、Web 服务、Automator 和测试报告之间的关系,并定义“可正常执行”“失败”“阻塞”等正式状态。

02-验证环境与场景矩阵

记录本次实际验证环境,以及已经执行过的正向、负向和边界场景。

03-排查手册

提供从 CLI 连接到测试报告的逐步排查流程、日志关键词和常见误区。

04-验证记录模板

提供可以复制到其他机器或其他版本环境中的验证记录模板。

正式术语

本文尽量不使用“顺利”“不顺利”这类含义不明确的说法,统一使用以下术语:

术语 含义
CLI 连接成功 CLI 找到并成功调用目标 HBuilderX 的官方 CLI 能力
项目打开成功 CLI 的项目打开操作返回成功,HBuilderX 能识别目标项目
Web 服务启动成功 页面 HTTP 服务能够启动并返回页面资源
Automator 连接成功 测试运行时与页面内置的 Automator WebSocket 完成连接
测试执行通过 测试套件和测试用例实际运行,并且指定断言通过
测试环境阻塞 因工具、服务、端口、设备或权限问题,测试没有有效执行
测试脚本无效 测试文件没有正确解析、没有有效断言,或证据不能证明目标行为

如何使用本文档

遇到问题时建议按以下顺序阅读:

  1. 先阅读 01-连接链路与正式状态,确定问题处在哪一层;
  2. 再对照 02-验证环境与场景矩阵,确认当前环境属于哪种场景;
  3. 按 03-排查手册 检查日志、端口和报告;
  4. 使用 04-验证记录模板 记录版本、配置、证据和边界。

适用范围

本文主要针对:

  • HBuilderX 官方 Web 自动化测试;
  • uniapp.test web-chrome 测试入口;
  • uni-app x Web 编译服务;
  • Playwright Chromium 和 Automator WebSocket 运行时;
  • CLI 连接 HBuilderX、连接项目和判断官方测试结果。

本文不替代以下内容:

  • 业务页面测试用例设计;
  • Android 真机键盘、焦点和生命周期验收;
  • Tauri WebView、Rust 宿主和 SQLite 验收;
  • 生产环境部署或发布构建说明。

版本边界

本次验证使用的环境和结论见 02-验证环境与场景矩阵。HBuilderX、uni-app x 编译器或官方测试插件升级后,应重新记录版本并复测关键正向、负向场景。

官方参考资料

01. 连接链路与正式状态

1. 完整连接链路

官方 Web 自动化测试应拆成三个阶段。三个阶段的通过标准不同,不能用前一个阶段的结果替代后一个阶段的结果。

阶段一:CLI → HBuilderX  
阶段二:HBuilderX 官方测试 → Web/Automator 运行时  
阶段三:测试套件 → 有效测试报告

阶段一:CLI 连接 HBuilderX

该阶段确认测试入口能够找到并调用 HBuilderX。

主要检查:

  • HBuilderX GUI 是否正在运行;
  • CLI 是否找到可用的 cli.exe;
  • CLI 和 GUI 是否来自同一套 HBuilderX 安装;
  • CLI 是否能执行项目打开操作;
  • HBuilderX 官方测试插件是否被正确加载;
  • 官方测试命令是否真正开始运行。

阶段一通过,只能说明控制入口可用,不能说明页面运行时已经连接。

阶段二:官方测试连接 Web/Automator 运行时

该阶段确认浏览器页面和自动化运行时可以被测试执行器使用。

需要同时检查两条通道:

HTTP 通道:       CLI → h5.url → Web 页面  
Automator 通道:  CLI → WebSocket → 页面运行时

HTTP 通道负责页面和资源访问。Automator 通道负责页面对象查询、点击、输入、路由和断言等自动化操作。

页面能打开而 Automator 不能连接时,仍然不能执行有效的官方自动化测试。

阶段三:测试套件执行并生成有效报告

该阶段确认测试文件确实被解析、执行并产生可信证据。

至少需要确认:

  • 测试套件数量大于零;
  • 测试用例数量大于零;
  • 测试文件没有语法错误;
  • 没有运行时连接异常;
  • 断言结果符合预期;
  • 官方 JSON 报告已经生成。

如果 CLI 找到了 HBuilderX,但测试套件没有执行,不能报告为完整通过。

2. 三种连接结果必须分开描述

2.1 CLI 连接 HBuilderX 成功

表示:

  • HBuilderX GUI 已被检测到;
  • CLI 找到了对应的官方 CLI 程序;
  • 项目打开命令返回成功;
  • 官方测试插件开始处理测试命令。

这只是控制层连接成功。

2.2 Automator 运行时连接成功

表示:

  • 浏览器已经打开 h5.url 指向的页面;
  • 页面编译结果包含 Automator 连接配置;
  • CLI 使用的主机和端口能够访问页面运行时;
  • 日志出现 connected 或 program ready。

这才说明页面具备被官方自动化操作的条件。

2.3 测试报告有效

表示:

  • 测试文件已经被 Jest 正确解析;
  • 至少一个测试套件和一个测试用例实际执行;
  • 报告中的失败和运行异常数量符合预期;
  • 通过结果与测试动作和断言一致。

这才可以报告一次完整的官方测试通过。

3. 正常使用条件

3.1 CLI 连接 HBuilderX 的条件

要使 CLI 能够连接 HBuilderX,通常需要满足:

  1. HBuilderX GUI 正在运行;
  2. 使用的 CLI 与当前 HBuilderX 属于同一版本体系或同一安装目录;
  3. CLI 能够找到官方 CLI 程序;
  4. 项目路径有效,并且包含可被 HBuilderX 识别的 uni-app x 工程文件;
  5. HBuilderX 的测试插件已经安装并且没有被禁用;
  6. CLI 项目打开操作没有超时或异常退出。

3.2 官方测试连接运行时的条件

要使页面运行时可被官方测试连接,通常需要满足:

  1. 页面 HTTP 服务已经启动;
  2. h5.url 指向正确的页面地址;
  3. 页面编译时已经配置 Automator WebSocket;
  4. Automator 主机地址可以从测试进程访问;
  5. 页面使用的 Automator 端口与 CLI 使用的端口一致;
  6. 页面服务和 Automator 服务在测试期间保持运行。

3.3 测试结果有效的条件

要把结果报告为通过,还需要满足:

  1. 测试文件可以解析;
  2. 测试套件实际启动;
  3. 测试用例数量大于零;
  4. 测试动作确实通过官方自动化 API 执行;
  5. 官方 JSON 报告已经生成;
  6. 没有把环境阻塞或脚本无效误判为通过。

4. 不正常使用的典型情况

4.1 HBuilderX 没有运行

CLI 无法连接 GUI 控制入口。此时不应把问题归类为业务页面测试失败,应记录为环境阻塞。

4.2 CLI 找到的 HBuilderX 与当前 GUI 不一致

可能出现以下问题:

  • CLI 使用了另一套 HBuilderX 的 cli.exe;
  • 编译器版本与测试插件版本不匹配;
  • CLI 打开的项目和 GUI 当前项目不是同一个实例;
  • 测试配置被不同版本的插件以不同方式修改。

排查时应记录 GUI 版本、CLI 路径、CLI 输出版本和编译器版本。

4.3 CLI 可以连接 HBuilderX,但项目打不开

这表示控制入口可用,但项目识别或项目路径存在问题。应单独记录项目打开失败,不要直接归类为 Automator 失败。

4.4 CLI 可以连接 HBuilderX,但 Automator 连接失败

这通常表示阶段一通过、阶段二失败。常见原因包括:

  • h5.url 指向普通 HTTP 服务;
  • 页面没有注入 Automator 地址;
  • 页面和 CLI 使用不同的 Automator 端口;
  • Automator 主机地址不可达;
  • 页面服务已经重启,CLI 仍连接旧端点。

4.5 Automator 已连接,但测试脚本没有有效执行

这通常是阶段三问题,常见原因包括:

  • 测试文件语法错误;
  • 测试范围没有包含目标文件;
  • 测试文件没有有效用例;
  • 断言或页面入口本身有问题;
  • 报告生成失败。

5. Web 服务复用在完整链路中的位置

“复用已经运行的 Web 服务”只是阶段二的一种运行方式,不是 CLI 连接 HBuilderX 的全部定义。

5.1 CLI 自行编译

CLI 负责启动 Web 编译服务和 Automator 运行时。这种方式中,CLI 的服务生命周期最清晰,适合先验证工具链本身。

5.2 复用带 Automator 的已有服务

已有服务必须同时提供:

  • 页面 HTTP 地址;
  • 页面编译时注入的 Automator WebSocket 地址;
  • CLI 可以访问的主机和端口。

5.3 复用普通 GUI Web 服务

普通 GUI Web 服务可以成功返回页面,但如果没有 Automator 端点,不能直接作为官方自动化测试服务复用。

6. 正式状态定义

建议统一使用以下状态,避免“可用”“不顺利”等表达产生歧义。

状态 正式含义 是否可以报告为通过
passed 指定连接检查和测试用例均已实际执行并通过 可以,但仅限已覆盖范围
failed 测试已经执行,但连接、代码或断言实际失败 不可以
blocked 因 HBuilderX、服务、端口、权限或工具链问题,测试没有有效执行 不可以
incomplete 测试能够运行,但覆盖范围或必要验证尚未完成 不可以作为完整通过
test-invalid 测试脚本没有有效执行,或证据不能证明目标行为 不可以

7. 结论表达示例

正确表达

CLI 已成功连接 HBuilderX,项目打开操作返回成功;但 Automator 运行时未完成连接,因此本次 Web 自动化测试记录为 failed,不能报告为完整通过。

页面 HTTP 服务访问正常,Automator WebSocket 端口与 CLI 配置一致,测试报告包含一个通过套件和一个通过用例,因此该复用场景在本次环境中验证通过。

HBuilderX GUI 未运行,CLI 测试入口未能建立,测试没有有效执行,因此记录为 blocked。

不建议表达

  • “HBuilderX 可以用,所以测试可以用”;
  • “页面能打开,所以自动化通过”;
  • “CLI 启动了,所以测试已经完成”;
  • “没有看到错误,所以应该通过”;
  • “compile:false 就会自动复用开发服务”。

02. 验证环境与场景矩阵

1. 本次验证环境

本节记录实际验证环境,帮助读者判断版本差异。文档不记录具体业务项目名称、项目目录和用户信息。

1.1 工具链

  • 操作系统:Windows 桌面环境;
  • 命令行环境:PowerShell;
  • HBuilderX 安装目录:D:\App\HBuilderX;对外分享时可替换为 <HBuilderX-root>;
  • HBuilderX 官方 CLI:<HBuilderX-root>\cli.exe;本次验证对应 D:\App\HBuilderX\cli.exe;
  • HBuilderX 内置 Node.js:由 <HBuilderX-root>\plugins\node\node.exe 提供;
  • HBuilderX:5.31.2026093020-alpha;
  • HBuilderX 官方自动化测试 CLI:命令行输出版本 5.4.0;
  • uni-app x 编译器:5.31,VDOM 模式;
  • 测试平台:web-chrome;
  • 浏览器驱动:Playwright Chromium;
  • 浏览器模式:无头模式;
  • 页面测试视口:官方运行时默认移动端视口。

1.2 HBuilderX 和 CLI 状态

本次运行入口要求 HBuilderX GUI 已经启动。测试脚本先检查 HBuilderX 进程,再解析与当前安装对应的 cli.exe。

CLI 执行项目打开操作后,再调用官方 Web 自动化测试命令。已实际观察到项目打开命令返回成功,说明控制入口阶段可以建立。

1.3 Web 服务状态

本次验证使用了两类服务:

普通 GUI Web 服务

  • 页面地址示例:http://127.0.0.1:5173/;
  • HTTP 请求可以得到成功响应;
  • 进程参数为普通 uni-app x Web 启动方式;
  • 未发现 --auto-port 或 --auto-host;
  • /main 响应中未发现可供测试运行时使用的 Automator 端点。

带 Automator 地址的独立 Web 服务

  • 页面地址示例:http://127.0.0.1:5174/;
  • Automator 主机:127.0.0.1;
  • Automator 端口示例:9538;
  • 服务启动时明确注入 Automator 地址;
  • 用于验证“官方 CLI 复用带 Automator 端点的已有服务”。

1.4 环境边界

本次矩阵只验证 Web 自动化测试连接链路,不包含:

  • Android 真机或模拟器自动化;
  • Tauri WebView 和 Rust 宿主;
  • 数据库读写和业务数据验收;
  • 完整业务页面覆盖;
  • 远程机器、局域网和跨主机防火墙验证。

2. 场景矩阵

下表覆盖了判断核心连接条件所需的关键正向和负向场景。它不是所有配置组合的穷举。

编号 场景 阶段一:CLI → HBuilderX 阶段二:Web/Automator 阶段三:测试报告 结果
A CLI 自行编译并启动 Web 服务 成功 成功 有效通过报告 可正常执行
B 复用带 Automator 的已有服务 成功 页面地址和端口匹配,连接成功 1 个冒烟用例通过 可以复用
C 复用普通 GUI Web 服务 成功 页面可访问,但 Automator 连接失败 运行时异常或无有效用例 不能复用
D 已有服务端口与 CLI 端口不一致 成功 Failed to connect to runtime 测试未有效开始 连接失败
E compile:false、无 h5.url、绑定地址无效 成功 CLI 自行编译时 EADDRNOTAVAIL 未生成有效报告 环境阻塞
F compile:false、无 h5.url、本机地址有效 成功 CLI 仍尝试自行编译,未复用 GUI 服务 超时或无有效报告 环境阻塞
G 检查 GUI 服务是否自带 Automator 成功 当前 GUI 服务未发现端点 不适用 普通 Web 服务

3. 各场景说明

3.1 场景 A:CLI 自行编译并启动

该场景中,官方 CLI 自己启动编译器和 Automator 运行时。

验证重点:

  • 主机地址可以被当前机器绑定;
  • 编译服务可以启动;
  • CLI 能够打开页面;
  • Automator 运行时能够连接;
  • 测试报告中存在实际执行的测试用例。

该场景可以证明官方 CLI 自己管理整条链路时能够工作,但不能证明普通 GUI 服务可以被复用。

3.2 场景 B:复用带 Automator 的已有服务

该场景中,先启动页面服务,并在编译时注入 Automator 地址,再让官方 CLI 使用相同的页面地址和 Automator 端口。

成功条件:

页面地址:       http://127.0.0.1:5174/  
页面 Automator: 127.0.0.1:9538  
CLI Automator:   127.0.0.1:9538

本次验证中,运行日志出现了 Automator 连接和 program ready,并且冒烟用例通过。这证明“已有服务复用”本身是可行的,但前提是服务已经具备 Automator 能力。

3.3 场景 C:复用普通 GUI Web 服务

该场景中,页面地址可以访问,但服务只提供普通 HTTP/Vite 能力,没有对应 Automator 端点。

实际表现:

  • 浏览器上下文可以创建;
  • 页面 URL 可以被访问;
  • 运行时连接阶段失败;
  • 出现 Failed to connect to runtime;
  • 测试套件可能没有真正执行。

这说明页面服务可访问和官方自动化可用是两个独立条件。

3.4 场景 D:端口不一致

已有页面服务在编译时使用 Automator 端口 9538,而 CLI 运行时使用动态分配的 9539。

两个进程可能都处于运行状态,但它们不会自动建立同一个 Automator 会话,最终表现为运行时连接失败。

3.5 场景 E:无效绑定地址

在 compile:false 且没有 h5.url 的配置下,CLI 仍尝试启动自己的编译服务。如果 Automator 主机被设置为当前机器不存在的地址,编译器会在监听阶段报:

EADDRNOTAVAIL: address not available

这属于服务启动失败,不属于测试用例断言失败。

3.6 场景 F:compile:false 但没有 h5.url

将绑定地址改为 127.0.0.1 后,CLI 仍尝试启动自己的编译服务。由于 GUI 已占用默认页面端口,CLI 改用其他页面端口,但没有自动复用 GUI 服务,最终测试没有有效完成。

该结果说明:

compile:false 不是“自动查找并复用已有 Web 服务”的充分条件。

3.7 场景 G:检查 GUI 服务是否自带 Automator

本次检查包括:

  • 查看 Web 服务进程启动参数;
  • 查看页面入口响应;
  • 检查页面和日志中是否存在 Automator 地址;
  • 检查对应 Automator 端口是否监听。

当前 GUI 服务是普通 Web 编译服务,没有发现官方自动化复用所需的 Automator 端点。

4. 环境与结论的边界

4.1 已确认的事实

  • 当前版本的官方 CLI 可以连接正在运行的 HBuilderX;
  • CLI 可以执行项目打开操作;
  • CLI 可以自行编译并运行 Web 自动化测试;
  • 带匹配 Automator 地址的已有服务可以被复用;
  • 普通 HTTP/Vite 服务不能仅凭页面地址被复用;
  • Automator 端口不一致会导致运行时连接失败;
  • compile:false 不足以单独决定复用哪一个已有服务;
  • 无效主机地址会导致编译服务启动失败。

4.2 尚未穷举的组合

以下内容没有在本次矩阵中全部穷举:

  • 其他 HBuilderX 版本的 CLI 与 GUI 组合;
  • 不同操作系统下的网络绑定行为;
  • 局域网地址和远程测试机之间的连接;
  • GUI 中可能新增的 Automator 服务启动选项;
  • 所有 compile、h5.url、主机、端口排列组合;
  • 完整业务页面和多页面测试。

因此,本文应使用“在本次验证环境中确认”这样的表述,不应宣称已经验证了所有版本和所有配置。

5. 复现记录最少应包含的环境信息

  • 操作系统和命令行环境;
  • HBuilderX 版本;
  • 官方 CLI 输出版本;
  • uni-app x 编译器版本和渲染模式;
  • 测试平台和浏览器驱动;
  • HBuilderX GUI 是否正在运行;
  • CLI 实际使用的路径;
  • 项目打开结果;
  • 页面 HTTP 地址和端口;
  • Automator 主机和端口;
  • compile、h5.url 和自定义环境变量;
  • 测试报告路径和套件/用例统计;
  • 未覆盖的场景和环境限制。

03. 排查手册

1. 排查原则

排查时不要直接从业务断言开始。应按官方测试的实际连接顺序逐层确认:

HBuilderX GUI  
  ↓  
CLI 程序  
  ↓  
项目打开  
  ↓  
Web 页面服务  
  ↓  
Automator WebSocket  
  ↓  
测试套件  
  ↓  
官方 JSON 报告

前一层没有通过时,不要用后一层的现象解释问题。

2. 第一步:确认 HBuilderX GUI

需要确认:

  • HBuilderX 窗口或进程确实正在运行;
  • 没有停留在启动失败、更新未完成或插件加载失败状态;
  • 当前 HBuilderX 是期望使用的版本;
  • 目标项目已经被 HBuilderX 识别。

如果 HBuilderX 没有运行,CLI 通常不能依靠测试命令自行替代 GUI 控制入口。应记录为 blocked,不要报告为业务测试失败。

3. 第二步:确认 CLI 来源

记录 CLI 实际使用的完整路径和输出版本。

重点检查:

  • CLI 是否来自当前 HBuilderX 安装目录;
  • 是否存在多个 HBuilderX 安装;
  • 环境变量是否把 CLI 指向了旧安装;
  • CLI 调用的内置 Node、编译器和测试插件是否属于同一套安装。

如果 GUI 和 CLI 不是同一版本体系,首先应排除工具链混用问题。

4. 第三步:确认项目打开

CLI 项目打开操作成功,只能证明项目控制入口可用。

需要记录:

  • 项目路径是否存在;
  • 项目是否包含有效的 uni-app x 工程文件;
  • CLI 项目打开命令的退出码;
  • 是否出现“项目未打开”“项目不存在”或超时;
  • HBuilderX 是否切换到目标项目。

项目打开失败时,不要继续修改页面测试断言。应先解决工程识别或 CLI 连接问题。

5. 第四步:确认测试配置

至少检查以下配置:

5.1 compile

确认是否让官方 CLI 自己编译,还是准备复用已有服务。

不要把以下两种含义混为一谈:

  • compile:false:不应简单解释为“自动连接任意已运行服务”;
  • h5.url:只指定页面访问地址,不自动为页面添加 Automator 能力。

5.2 h5.url

如果要复用已有 Web 服务,应确认:

  • 地址指向当前实际运行的页面服务;
  • 协议、主机、端口和路径都正确;
  • 该页面服务在测试期间不会被切换或重启。

5.3 Automator 主机和端口

确认页面编译时使用的 Automator 主机、页面实际连接的端口,以及 CLI 测试运行时使用的端口。

推荐把三者记录在同一张表中:

位置 主机 端口
页面编译配置 127.0.0.1 9538
页面实际运行时 127.0.0.1 9538
CLI 测试运行时 127.0.0.1 9538

页面端口和 Automator 端口可以不同,但页面和 CLI 的 Automator 端点必须指向同一个运行时。

6. 第五步:确认 HTTP 页面服务

先验证页面 HTTP 地址,再验证 Automator。

PowerShell 示例:

Invoke-WebRequest -UseBasicParsing -Uri 'http://127.0.0.1:<web-port>/'

页面请求失败时,检查:

  • Web 服务是否已经启动;
  • 页面端口是否被其他进程占用;
  • 服务是否绑定到正确主机;
  • 服务是否在测试过程中退出;
  • CLI 日志是否显示了实际使用的 URL。

页面 HTTP 检查成功后,仍必须继续检查 Automator 端点。

7. 第六步:确认 Automator 运行时

重点查看官方测试日志中的以下信息:

automator:launcher  
automator:runtime  
connected  
program ready  
Failed to connect to runtime

7.1 出现 connected 或 program ready

说明 Automator 运行时已经建立连接,可以继续判断测试脚本和页面行为。

7.2 出现 Failed to connect to runtime

优先检查:

  1. 页面是否只是普通 HTTP 服务;
  2. 页面是否注入了 Automator 地址;
  3. 页面和 CLI 的 Automator 端口是否一致;
  4. Automator 主机是否可访问;
  5. 页面服务是否在测试前已经重启;
  6. CLI 是否连接到了旧端口或动态分配的新端口。

该错误通常不是业务用例断言失败。

7.3 出现 EADDRNOTAVAIL

说明服务尝试绑定当前机器无法使用的主机地址。应先检查主机配置和网络接口,不要先修改测试脚本。

7.4 页面端口被占用

如果日志显示 Web 服务自动换到其他页面端口,应确认:

  • h5.url 是否仍然指向旧端口;
  • 页面编译结果中的 Automator 地址是否仍然有效;
  • CLI 是否真的连接了新服务;
  • 是否因此误把端口变化当成页面测试失败。

8. 第七步:确认测试套件真正执行

Automator 连接成功后,还要确认 Jest 测试本身有效。

重点检查:

  • 测试文件是否被纳入 testMatch;
  • 测试文件是否可以被 Babel/Jest 解析;
  • 测试套件数量是否大于零;
  • 测试用例数量是否大于零;
  • 测试是否在 beforeAll 或页面启动阶段失败;
  • 页面断言是否真正执行。

如果日志显示:

Tests: 0 total

则不能把这次运行报告为功能通过。

如果出现 JavaScript 语法错误,应记录为 test-invalid 或测试脚本失败,而不是 Automator 连接成功。

9. 第八步:确认官方 JSON 报告

官方 JSON 报告是判断测试是否有效的重要证据。至少检查:

  • 报告文件是否生成;
  • numTotalTestSuites 是否大于零;
  • numTotalTests 是否大于零;
  • numRuntimeErrorTestSuites 是否为零;
  • numFailedTestSuites 是否为零;
  • numFailedTests 是否为零;
  • success 字段与详细统计是否一致。

建议不要只看终端最后一行,也不要只看退出码。退出码、日志和 JSON 报告需要相互印证。

10. 错误现象与处理方向

错误现象 优先判断 不应直接判断为
未检测到 HBuilderX GUI 或 CLI 环境阻塞 页面业务失败
项目打开失败 项目路径或 HBuilderX 识别问题 Automator 断言失败
EADDRNOTAVAIL 绑定主机地址无效 测试用例失败
Failed to connect to runtime Automator 地址、端口或注入缺失 页面 HTTP 不可访问
页面可打开但测试为 0 测试范围、脚本或运行时问题 功能通过
JavaScript 语法错误 测试脚本无效 Web 服务连接失败
生成报告但包含运行异常 测试没有完整通过 仅凭 success 字段通过
超时且没有有效报告 环境阻塞或进程未完成握手 业务断言失败

11. 常见误区

11.1 CLI 已启动,不代表 HBuilderX 已连接

CLI 进程启动只能说明命令被调用。还需要确认 HBuilderX 检测、项目打开和官方测试插件初始化结果。

11.2 HBuilderX 已连接,不代表页面运行时已连接

控制层和运行时是两个阶段。必须继续查看 Automator 日志。

11.3 页面可访问,不代表页面可自动化

普通 HTTP/Vite 服务可能没有 Automator WebSocket。

11.4 compile:false 不保证复用服务

没有 h5.url 或没有匹配的 Automator 端点时,CLI 可能自行启动编译服务,或者最终无法完成运行时连接。

11.5 动态端口不应未经确认直接使用

页面编译时注入的端口、CLI 运行时端口和页面实际连接端口必须一致。只看到 CLI 分配了端口,不代表页面已经同步使用该端口。

11.6 一个冒烟用例通过不等于完整验收通过

冒烟用例只能证明连接链路和该用例覆盖的行为。完整应用验收仍需独立的测试矩阵和必要的平台验证。

12. 推荐的最小排查命令

以下命令仅用于说明检查顺序,实际路径和端口应替换为当前环境值:

# 检查页面 HTTP 服务  
Invoke-WebRequest -UseBasicParsing -Uri 'http://127.0.0.1:<web-port>/'  

# 检查 Automator 端口  
Test-NetConnection -ComputerName 127.0.0.1 -Port <automator-port>  

# 使用 HBuilderX 官方 CLI 打开项目  
<hbuilderx-cli> project open --path <project-root>  

# 执行官方 Web 自动化测试  
<hbuilderx-cli> uniapp.test web-chrome --project <project-root>

如果当前 PowerShell 或 HBuilderX 版本不支持某个检查命令,应记录替代命令和实际输出,不要把未执行的检查写成通过。

13. 清理和恢复

测试工具可能临时修改测试范围、环境配置或生成报告文件。测试结束后应确认:

  • 仅保留用户明确需要的配置变化;
  • 临时测试文件已经清理;
  • 临时编译进程已经退出;
  • HBuilderX 原有 Web 服务没有被误停;
  • 失败证据、日志和 JSON 报告按需要保留;
  • 配置文件差异经过审查。

14. 排查结论模板

可以使用以下格式记录一次结果:

HBuilderX GUI:已运行 / 未运行  
CLI 连接:成功 / 失败  
项目打开:成功 / 失败  
页面 HTTP 服务:可访问 / 不可访问  
Automator 运行时:已连接 / 未连接  
测试套件:已执行 / 未执行  
官方 JSON 报告:有效 / 缺失 / 内容不完整  
最终状态:passed / failed / blocked / incomplete / test-invalid  
根因:  
证据:  
未覆盖范围:
收起阅读 »

运行到浏览器报错: Network: unavailable

Network: unavailable 是 vue-cli 的 default-gateway 模块调用已被新版 Windows 移除的 wmic 命令失败,导致 prepareURLs.js 里 lanUrlForTerminal 保留了默认字面量 chalk.gray('unavailable'),再被 HBuilderX 原样转发到控制台。

修复:public 显式指定局域网访问地址,修复新版 Windows(无 wmic)下 default-gateway 探测失败、控制台显示 Network: unavailable 的问题;getLocalIPv4() 自动取本机私有网段 IP,换网络无需手改。

const os = require('os');

// 获取本机局域网 IPv4(优先 192.168.x / 10.x / 172.16-31.x,排除 169.254.x 链路本地地址)
function getLocalIPv4 () {
const nets = os.networkInterfaces()
const list = []
Object.keys(nets).forEach(name => {
(nets[name] || []).forEach(net => {
if (net.family === 'IPv4' && !net.internal) list.push(net.address)
})
})
const isPrivate = ip => /^10[.]|^172.[.]|^192[.]168[.]/.test(ip)
return list.find(isPrivate) || ''
}

const localIP = getLocalIPv4()
const devPort = 9001

devServer: {
proxy: proxyOption,
port: devPort, // 你的端口号
// 修复新版 Windows(无 wmic)下 default-gateway 探测失败导致控制台显示 Network: unavailable
// 显式指定局域网地址后,控制台会显示 http://<本机IP>:9001/
public: localIP ? ${localIP}:${devPort} : undefined,
},

继续阅读 »

Network: unavailable 是 vue-cli 的 default-gateway 模块调用已被新版 Windows 移除的 wmic 命令失败,导致 prepareURLs.js 里 lanUrlForTerminal 保留了默认字面量 chalk.gray('unavailable'),再被 HBuilderX 原样转发到控制台。

修复:public 显式指定局域网访问地址,修复新版 Windows(无 wmic)下 default-gateway 探测失败、控制台显示 Network: unavailable 的问题;getLocalIPv4() 自动取本机私有网段 IP,换网络无需手改。

const os = require('os');

// 获取本机局域网 IPv4(优先 192.168.x / 10.x / 172.16-31.x,排除 169.254.x 链路本地地址)
function getLocalIPv4 () {
const nets = os.networkInterfaces()
const list = []
Object.keys(nets).forEach(name => {
(nets[name] || []).forEach(net => {
if (net.family === 'IPv4' && !net.internal) list.push(net.address)
})
})
const isPrivate = ip => /^10[.]|^172.[.]|^192[.]168[.]/.test(ip)
return list.find(isPrivate) || ''
}

const localIP = getLocalIPv4()
const devPort = 9001

devServer: {
proxy: proxyOption,
port: devPort, // 你的端口号
// 修复新版 Windows(无 wmic)下 default-gateway 探测失败导致控制台显示 Network: unavailable
// 显式指定局域网地址后,控制台会显示 http://<本机IP>:9001/
public: localIP ? ${localIP}:${devPort} : undefined,
},

收起阅读 »

HBuilderX 5.26 鸿蒙生成本地安装包以后,打包成APP白屏问题

目前问题已解决,因为 /Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-app-vite/dist/plugins/template.js 这份文件中在打包的时候copy[uni-app-view.umd.js ]这份js没加判断,导致鸿蒙的包里面copy进去的也是安卓/iOS里面300+kb的,而不是鸿蒙里面800+kb的。我在template.js 中增加了判断```javascript outputDir = process.env.UNI_OUTPUT_DIR; if (renderer !== 'native') { // 鸿蒙用 uni-app-harmony 的 view 运行时(约 800KB+), // 安卓/iOS 仍用 uni-app-plus(约 300KB+) const viewPkg = process.env.UNI_PLATFORM === 'app-harmony' ? '@dcloudio/uni-app-harmony/dist/uni-app-view.umd.js' '@dcloudio/uni-app-plus/dist/uni-app-view.umd.js'; fs_extra_1.default.copySync((0, uni_cli_shared_1.resolveBuiltIn)(viewPkg), path_1.default.resolve(outputDir, 'uni-app-view.umd.js'), {
overwrite: true,
});
} ```
继续阅读 »
目前问题已解决,因为 /Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli-vite/node_modules/@dcloudio/uni-app-vite/dist/plugins/template.js 这份文件中在打包的时候copy[uni-app-view.umd.js ]这份js没加判断,导致鸿蒙的包里面copy进去的也是安卓/iOS里面300+kb的,而不是鸿蒙里面800+kb的。我在template.js 中增加了判断```javascript outputDir = process.env.UNI_OUTPUT_DIR; if (renderer !== 'native') { // 鸿蒙用 uni-app-harmony 的 view 运行时(约 800KB+), // 安卓/iOS 仍用 uni-app-plus(约 300KB+) const viewPkg = process.env.UNI_PLATFORM === 'app-harmony' ? '@dcloudio/uni-app-harmony/dist/uni-app-view.umd.js' '@dcloudio/uni-app-plus/dist/uni-app-view.umd.js'; fs_extra_1.default.copySync((0, uni_cli_shared_1.resolveBuiltIn)(viewPkg), path_1.default.resolve(outputDir, 'uni-app-view.umd.js'), {
overwrite: true,
});
} ``` 收起阅读 »

HBuilderX 云打包上传 iOS IPA 报错 90085,执行 xcode-select --install 后解决

解决 HBuilderX iOS 云打包上传 Transporter 报错 90085 的方法:

我之前使用 HBuilderX 5.07 打包 iOS IPA,通过 Mac 上的 Transporter 上传 App Store Connect 时,遇到了这个错误:

No architectures in the binary. Lipo failed to detect any architectures in the bundle executable. (90085)

一开始检查了 IPA 主程序,确认主程序是 arm64 架构,Transporter 也已经是 1.4.5,但仍然无法正常上传。

最后解决方法:

打开 Mac 终端。

执行命令:

xcode-select --install

按照系统提示安装 Xcode Command Line Tools。
安装完成后,重新使用 Transporter 上传原来的 IPA。

我这边实测,安装完成后重新上传就可以了!

如果你也遇到了同样的 90085 架构错误,可以先尝试这个方法,不一定需要先修改项目代码、反复重新打包或逐个检查 Framework。

说明:这是我自己的实测结果,不保证所有开发环境都适用。如果安装后仍然报错,再继续检查打包产物和上传环境。

补充说明:

我使用的 Transporter 已经是 1.4.5,检查 IPA 主程序后确认是 arm64 架构,但仍然出现 90085 错误。

后来在 Mac 终端执行 xcode-select --install,按照系统提示安装 Xcode Command Line Tools。安装完成后,重新使用 Transporter 上传 IPA,之前的 90085 错误就没有再出现,上传进入了 Apple 处理阶段。

目前这是我自己实测有效的方法,分享给遇到相同问题的开发者参考。不同电脑环境可能存在差异,如果此方法无效,还需要进一步排查。

继续阅读 »

解决 HBuilderX iOS 云打包上传 Transporter 报错 90085 的方法:

我之前使用 HBuilderX 5.07 打包 iOS IPA,通过 Mac 上的 Transporter 上传 App Store Connect 时,遇到了这个错误:

No architectures in the binary. Lipo failed to detect any architectures in the bundle executable. (90085)

一开始检查了 IPA 主程序,确认主程序是 arm64 架构,Transporter 也已经是 1.4.5,但仍然无法正常上传。

最后解决方法:

打开 Mac 终端。

执行命令:

xcode-select --install

按照系统提示安装 Xcode Command Line Tools。
安装完成后,重新使用 Transporter 上传原来的 IPA。

我这边实测,安装完成后重新上传就可以了!

如果你也遇到了同样的 90085 架构错误,可以先尝试这个方法,不一定需要先修改项目代码、反复重新打包或逐个检查 Framework。

说明:这是我自己的实测结果,不保证所有开发环境都适用。如果安装后仍然报错,再继续检查打包产物和上传环境。

补充说明:

我使用的 Transporter 已经是 1.4.5,检查 IPA 主程序后确认是 arm64 架构,但仍然出现 90085 错误。

后来在 Mac 终端执行 xcode-select --install,按照系统提示安装 Xcode Command Line Tools。安装完成后,重新使用 Transporter 上传 IPA,之前的 90085 错误就没有再出现,上传进入了 Apple 处理阶段。

目前这是我自己实测有效的方法,分享给遇到相同问题的开发者参考。不同电脑环境可能存在差异,如果此方法无效,还需要进一步排查。

收起阅读 »

仿信件助理开源小程序给监狱或看守所写信寄信明信片商城带完整管理后台小程序

仿信件助理开源小程序给监狱或看守所写信寄信明信片商城带完整管理后台小程序
QQ:348818683

仿信件助理开源小程序给监狱或看守所写信寄信明信片商城带完整管理后台小程序
QQ:348818683

谷歌上架被拒android.permission.READ_MEDIA_IMAGES和android.permission.READ_MEDIA_VIDEO

GooglePlay

时隔两年再次因为这两个权限被拒,我的APP中从未使用过照片和视频功能,至今也不知道什么原因导致打包后出现android.permission.READ_MEDIA_IMAGES和android.permission.READ_MEDIA_VIDEO
我的解决过程:
1、强制移除权限不生效,excludePermissions中已经声明了这两个权限,但android studio打开打包好的apk在AndroidManifest.xml中依然存在这两个权限,后来问了豆老师要同时移除 READ_EXTERNAL_STORAGE,如下配置后,成功移除READ_MEDIA_IMAGES和READ_MEDIA_VIDEO这两个权限

"app-plus": {  
    "distribute": {  
        "android": {  
            "excludePermissions": [  
                "<uses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\"/>",  
                "<uses-permission android:name=\"android.permission.READ_MEDIA_VIDEO\"/>",  
                "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",  
                "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>"  
            ]  
        }  
    }  
}  

2、权限移除后谷歌审核依然被拒,拒绝的原因一样还是说使用了“照片和视频权限”,搜索发现谷歌被拒后要停用/移除存在问题的所有发布轨道(如生产、开放测试或封闭测试),我被拒是有一个开放测试轨道未停用,停用后审核就通过了。在问题详情里可以查看有问题的app bundle

继续阅读 »

时隔两年再次因为这两个权限被拒,我的APP中从未使用过照片和视频功能,至今也不知道什么原因导致打包后出现android.permission.READ_MEDIA_IMAGES和android.permission.READ_MEDIA_VIDEO
我的解决过程:
1、强制移除权限不生效,excludePermissions中已经声明了这两个权限,但android studio打开打包好的apk在AndroidManifest.xml中依然存在这两个权限,后来问了豆老师要同时移除 READ_EXTERNAL_STORAGE,如下配置后,成功移除READ_MEDIA_IMAGES和READ_MEDIA_VIDEO这两个权限

"app-plus": {  
    "distribute": {  
        "android": {  
            "excludePermissions": [  
                "<uses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\"/>",  
                "<uses-permission android:name=\"android.permission.READ_MEDIA_VIDEO\"/>",  
                "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",  
                "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>"  
            ]  
        }  
    }  
}  

2、权限移除后谷歌审核依然被拒,拒绝的原因一样还是说使用了“照片和视频权限”,搜索发现谷歌被拒后要停用/移除存在问题的所有发布轨道(如生产、开放测试或封闭测试),我被拒是有一个开放测试轨道未停用,停用后审核就通过了。在问题详情里可以查看有问题的app bundle

收起阅读 »

5.26版本:uni-app x, 运行到自定义基座, 提示【编译器版本号5.24和自定义基座版本号5.26不一致】的说明

自定义基座 uni-app-x

5.26版本:uni-app x, 运行到自定义基座, 提示【编译器版本号5.24和自定义基座版本号5.26不一致】的说明

解决方案:直接升级

9月18日,上午出现【编译器版本号5.24和自定义基座版本号5.26不一致】问题。
9月18日晚,19: 30, 重新发布5.26版本,大家直接升级即可。

如果不想升级,可以通过以下方案解决。

HBuilderX插件安装目录,plugins/uniappx-vapor-launcher/base/version.txt 文件,改成以下内容。然后重启hx:

hbuilderx_version=5.26  

android_version=5.26.101163  

iphone_version=5.26.100892

说明

给大家造成不好的体验,万分抱歉,后续我们将加强质量管理。

继续阅读 »

5.26版本:uni-app x, 运行到自定义基座, 提示【编译器版本号5.24和自定义基座版本号5.26不一致】的说明

解决方案:直接升级

9月18日,上午出现【编译器版本号5.24和自定义基座版本号5.26不一致】问题。
9月18日晚,19: 30, 重新发布5.26版本,大家直接升级即可。

如果不想升级,可以通过以下方案解决。

HBuilderX插件安装目录,plugins/uniappx-vapor-launcher/base/version.txt 文件,改成以下内容。然后重启hx:

hbuilderx_version=5.26  

android_version=5.26.101163  

iphone_version=5.26.100892

说明

给大家造成不好的体验,万分抱歉,后续我们将加强质量管理。

收起阅读 »

在线教育知识付费直播源码免费下载|UniApp 多端可用

uniapp

仓库地址 https://gitee.com/tuzhi-open/tuzhi-mobile-open

凸知(Tuzhi) 是一套完整的知识付费解决方案,支持私有化部署,覆盖课程售卖、直播授课、圈子社区、考试测评、分销营销、实物商品等完整业务场景,提供管理后台、移动端(H5 / 微信小程序)、PC 学员端等多端入口,帮助个人 IP、教培机构与品牌商家搭建自有卖课平台。

凸知移动端 是一款基于 uni-app(Vue 2) TDesign 开发的知识付费移动端前端,支持 H5 / 微信小程序 多端编译(不支持 App 打包)。覆盖课程点播、直播、专栏、圈子社区、订单支付(前端交互)、优惠券、余额红包、考试答题等完整学习场景。

系统演示:

端 演示地址 账号 密码
后台 https://tuzhi.mutouweb.com/admin.php admin 123456
移动端(用户) https://tuzhi.mutouweb.com 13222222222 123456
PC 端(用户) https://tuzhi.mutouweb.com/pc/#/ 13222222222 123456

一、功能特性

  • 终端覆盖:电脑端 / 微信公众号(H5)/ 微信小程序多端学习
  • 课程内容:图文 / 视频 / 音频 / 专栏售卖,支持试看试听、课件资料与内容保护
  • 互动教学:练习 / 考试测评 / 题库 / 试卷库 / 证书 / 表单 / 圈子社区
  • 直播能力:直播授课 / 伪直播 / 回放 / 直播带货 / 送礼物 / 发红包
  • 营销增长:分销推广 / 优惠券 / 每日签到 / 积分商城 / 付费会员卡 / 组合商品 / 卡密兑换
  • 实物商品:商品管理 / 多规格 SKU / 限购设置 / 售后退换
  • 交易支付:购物车 / 订单管理 / 余额支付 / 微信支付 / 支付宝支付
  • 用户数据:用户管理 / 订阅记录 / 学习分析 / 交易分析 / 订单管理
  • 系统安全:页面 DIY 装修 / 云存储 / 短信与消息推送 / 管理员权限 / 版权保护(跑马灯 / 防录屏)

界面预览:

二、系统架构

凸知是一套完整的知识付费系统,由四个部分组成:

部分 技术栈 说明 源码开放
后端服务 ThinkPHP 5.0 FastAdmin MySQL 接口服务,承载支付、直播、分销等全部业务逻辑 购买授权
移动端(本仓库) uni-app(Vue 2) TDesign H5 / 微信小程序学员端(不支持 App 打包) 开源
管理后台 Vue 3 Arco Design 管理员 / 讲师运营后台 购买授权
PC 学员端 Vue 3 Arco Design 电脑端学员学习页面 购买授权

凸知终端技术结构:

整体调用链路:移动端 / PC 学员端 / 管理后台 → 后端接口服务({code, msg, data} 协议)→ MySQL 数据库。

本仓库仅开源移动端前端源码;如需后端服务或管理后台等其余端的源码,需购买商业授权获取,详见「十一、使用许可」与授权价格。

三、技术栈

分类 技术 说明
跨端框架 uni-app(Vue 2.x) vue-cli 工程,一套代码编译 H5 / 微信小程序等多端(不支持 App 打包)
开发语言 JavaScript(Vue 2 语法) Sass 页面按 xxx.vue js.vue css.css 三文件拆分,样式用 CSS 规则
UI 组件库 TDesign(@tdesign/uniapp) 全局主题样式,小程序端内置构建适配补丁(scripts/)
uView(本地 components/uview-ui) 列表 / 弹窗 / 表单等通用组件
自研 components/tz/ 音频 / 视频 / 媒体编辑 / 上传 / 文件预览等 45 业务组件
qiun-data-charts 图表可视化
状态管理 Vuex 3 全局登录态 / 用户信息等
国际化 vue-i18n 8 内置 zh-CN / US 多语言
网络请求 flyio 自封装 $api $api('module.action') 点分路由,统一鉴权 / 错误处理 / 401 跳转
音视频播放 阿里云播放器 Aliplayer(H5,本地化资源)、hls.js / flv.js 直播与点播,支持倍速 / 弹幕 / 水印等组件
微信能力 jweixin-module 微信登录 / 分享 JS-SDK 封装
构建工具 @vue/cli 5 webpack 由 @dcloudio/vue-cli-plugin-uni 驱动多端编译
测试 Jest 多端单元测试(npm run test:*)

四、快速开始

环境要求:Node.js >= 14(建议 16/18)、npm

# ① 安装依赖  
npm install  

# ② H5 开发(默认不启用 Mock,对接真实后端;如需 Mock 见「Mock 数据」)  
npm run dev:h5

浏览器访问 http://localhost:8080 即可看到完整页面效果。

微信小程序编译:

# ③ 小程序开发模式(监听编译,产物在 dist/dev/mp-weixin)  
npm run dev:mp-weixin  

# ④ 小程序生产构建(内置 TDesign 适配补丁,产物在 dist/build/mp-weixin)  
npm run build:mp-weixin

用微信开发者工具「导入项目」选择对应产物目录(开发选 dist/dev/mp-weixin,生产选 dist/build/mp-weixin),并在 src/manifest.json 中替换为自己的 appid。

对接真实后端:

  1. 修改 src/siteinfo.js 中的 siteroot 为你的后端地址;
  2. 在 src/common/request/api_list.js 中核对接口地址与 {code, msg, data} 协议;
  3. 微信小程序构建需在 src/manifest.json 中替换为自己的 appid。

五、构建

目标 命令
H5 npm run build:h5
微信小程序 npm run build:mp-weixin

小程序构建内置 TDesign 适配补丁(scripts/),构建成功后产物在 dist/build/ 下。

⚠️ 注意:当前版本不支持 App 打包,仅支持 H5 与微信小程序两个平台。

六、Mock 数据

  • H5 开发模式(NODE_ENV=development)默认关闭,全部走真实后端接口;
  • 开启方式:将 src/static/config.js 的 enableMock 改为 true(显式设置优先级最高),或通过 uni.setStorageSync('enableMock', true) / 环境变量 MOCK_ENABLE 切换;
  • 覆盖 200 接口,fixture 位于 src/mock/data/,按 module/action 路由镜像;
  • 未覆盖的接口自动透传真实网络并输出提示;
  • Mock 数据由仓库内 mock-crawler 工具采集真实后端响应生成,发布前已做敏感字段脱敏(token/openid/手机号等)。

七、目录结构

src/  
├── pages/        页面(index 主包   public/app/user/order/course 五个分包,约 100  页面)  
│   ├── index/        首页(主包唯一页面,tabBar 入口)  
│   ├── launch/       启动页(加载与参数透传跳转,未在 pages.json 注册)  
│   ├── public/       公共分包:登录 / 注册 / 找回密码 / 协议 / 搜索 / 消息 / 结果页等  
│   ├── app/          业务功能分包:活动 / 圈子 / 考试 / 优惠券 / 积分 / 签到 / 证书 / 分销 / 直播带货等  
│   ├── user/         用户分包:个人中心 / 资产 / 余额 / 地址 / 收藏 / 学习记录 / 订阅 / 红包等  
│   ├── order/        订单分包:订单列表 / 详情 / 提交 / 评价 / 售后 / 物流等  
│   ├── course/       课程分包:课程详情 / 分类 / 专栏 / 小组 / 直播等  
│   └── template/     页面模板(新建页面的三文件拆分参考,未在 pages.json 注册)  
├── components/   组件(tz/ 自研组件库、uview-ui、qiun-data-charts、视频播放器等)  
├── common/       公共层  
│   ├── request/  接口封装($api 点分路由、统一鉴权/错误处理)  
│   ├── utils/    工具(路由映射、支付、直播、OSS 签名等)  
│   ├── order/    订单状态处理  
│   └── wechat/   微信登录/分享 SDK 封装  
├── mock/         Mock 数据(H5 开发模式默认关闭,开启方式见「六、Mock 数据」)  
├── static/       静态资源  
├── pages.json    页面路由与分包配置  
└── manifest.json 应用配置(appid 等)

八、开发约定

  • 页面采用 xxx.vue js.vue css.css 三文件拆分(<script src="./js.vue"> @import "./css.css"),逻辑与样式分离;
  • 接口调用统一走 this.$api('module.action', data),登录态、401 跳转、错误提示由拦截器统一处理;
  • 业务组件优先复用 components/tz/ 自研组件库;
  • 提交信息遵循 Conventional Commits(feat: / fix: / chore:)。

九、相关链接

名称 链接
使用文档 https://wood-soft.feishu.cn/wiki/KKLkwOPBHiButJkTluTcoXKenjh
功能列表 https://wood-soft.feishu.cn/wiki/YGFYw0k8PiJDWxketgHcBNKNnxe
授权价格 https://www.tuzhi.ltd/index/pricing/version.html
功能演示 https://www.tuzhi.ltd/index/demo/index.html

十、软件安全

安全问题请通过 Issue(需注明"安全")或邮件私下报告给项目维护团队,请勿在公开渠道描述可利用的漏洞细节。我们将在确认后尽快修复并同步发布。

十一、使用许可

  • 本软件遵循 凸知开源协议 V1.0(非商业用途免费,商业用途需购买商业授权),详见 LICENSE;
  • 第三方组件许可声明见 THIRD-PARTY-NOTICES.md(发布前请核对);
继续阅读 »

仓库地址 https://gitee.com/tuzhi-open/tuzhi-mobile-open

凸知(Tuzhi) 是一套完整的知识付费解决方案,支持私有化部署,覆盖课程售卖、直播授课、圈子社区、考试测评、分销营销、实物商品等完整业务场景,提供管理后台、移动端(H5 / 微信小程序)、PC 学员端等多端入口,帮助个人 IP、教培机构与品牌商家搭建自有卖课平台。

凸知移动端 是一款基于 uni-app(Vue 2) TDesign 开发的知识付费移动端前端,支持 H5 / 微信小程序 多端编译(不支持 App 打包)。覆盖课程点播、直播、专栏、圈子社区、订单支付(前端交互)、优惠券、余额红包、考试答题等完整学习场景。

系统演示:

端 演示地址 账号 密码
后台 https://tuzhi.mutouweb.com/admin.php admin 123456
移动端(用户) https://tuzhi.mutouweb.com 13222222222 123456
PC 端(用户) https://tuzhi.mutouweb.com/pc/#/ 13222222222 123456

一、功能特性

  • 终端覆盖:电脑端 / 微信公众号(H5)/ 微信小程序多端学习
  • 课程内容:图文 / 视频 / 音频 / 专栏售卖,支持试看试听、课件资料与内容保护
  • 互动教学:练习 / 考试测评 / 题库 / 试卷库 / 证书 / 表单 / 圈子社区
  • 直播能力:直播授课 / 伪直播 / 回放 / 直播带货 / 送礼物 / 发红包
  • 营销增长:分销推广 / 优惠券 / 每日签到 / 积分商城 / 付费会员卡 / 组合商品 / 卡密兑换
  • 实物商品:商品管理 / 多规格 SKU / 限购设置 / 售后退换
  • 交易支付:购物车 / 订单管理 / 余额支付 / 微信支付 / 支付宝支付
  • 用户数据:用户管理 / 订阅记录 / 学习分析 / 交易分析 / 订单管理
  • 系统安全:页面 DIY 装修 / 云存储 / 短信与消息推送 / 管理员权限 / 版权保护(跑马灯 / 防录屏)

界面预览:

二、系统架构

凸知是一套完整的知识付费系统,由四个部分组成:

部分 技术栈 说明 源码开放
后端服务 ThinkPHP 5.0 FastAdmin MySQL 接口服务,承载支付、直播、分销等全部业务逻辑 购买授权
移动端(本仓库) uni-app(Vue 2) TDesign H5 / 微信小程序学员端(不支持 App 打包) 开源
管理后台 Vue 3 Arco Design 管理员 / 讲师运营后台 购买授权
PC 学员端 Vue 3 Arco Design 电脑端学员学习页面 购买授权

凸知终端技术结构:

整体调用链路:移动端 / PC 学员端 / 管理后台 → 后端接口服务({code, msg, data} 协议)→ MySQL 数据库。

本仓库仅开源移动端前端源码;如需后端服务或管理后台等其余端的源码,需购买商业授权获取,详见「十一、使用许可」与授权价格。

三、技术栈

分类 技术 说明
跨端框架 uni-app(Vue 2.x) vue-cli 工程,一套代码编译 H5 / 微信小程序等多端(不支持 App 打包)
开发语言 JavaScript(Vue 2 语法) Sass 页面按 xxx.vue js.vue css.css 三文件拆分,样式用 CSS 规则
UI 组件库 TDesign(@tdesign/uniapp) 全局主题样式,小程序端内置构建适配补丁(scripts/)
uView(本地 components/uview-ui) 列表 / 弹窗 / 表单等通用组件
自研 components/tz/ 音频 / 视频 / 媒体编辑 / 上传 / 文件预览等 45 业务组件
qiun-data-charts 图表可视化
状态管理 Vuex 3 全局登录态 / 用户信息等
国际化 vue-i18n 8 内置 zh-CN / US 多语言
网络请求 flyio 自封装 $api $api('module.action') 点分路由,统一鉴权 / 错误处理 / 401 跳转
音视频播放 阿里云播放器 Aliplayer(H5,本地化资源)、hls.js / flv.js 直播与点播,支持倍速 / 弹幕 / 水印等组件
微信能力 jweixin-module 微信登录 / 分享 JS-SDK 封装
构建工具 @vue/cli 5 webpack 由 @dcloudio/vue-cli-plugin-uni 驱动多端编译
测试 Jest 多端单元测试(npm run test:*)

四、快速开始

环境要求:Node.js >= 14(建议 16/18)、npm

# ① 安装依赖  
npm install  

# ② H5 开发(默认不启用 Mock,对接真实后端;如需 Mock 见「Mock 数据」)  
npm run dev:h5

浏览器访问 http://localhost:8080 即可看到完整页面效果。

微信小程序编译:

# ③ 小程序开发模式(监听编译,产物在 dist/dev/mp-weixin)  
npm run dev:mp-weixin  

# ④ 小程序生产构建(内置 TDesign 适配补丁,产物在 dist/build/mp-weixin)  
npm run build:mp-weixin

用微信开发者工具「导入项目」选择对应产物目录(开发选 dist/dev/mp-weixin,生产选 dist/build/mp-weixin),并在 src/manifest.json 中替换为自己的 appid。

对接真实后端:

  1. 修改 src/siteinfo.js 中的 siteroot 为你的后端地址;
  2. 在 src/common/request/api_list.js 中核对接口地址与 {code, msg, data} 协议;
  3. 微信小程序构建需在 src/manifest.json 中替换为自己的 appid。

五、构建

目标 命令
H5 npm run build:h5
微信小程序 npm run build:mp-weixin

小程序构建内置 TDesign 适配补丁(scripts/),构建成功后产物在 dist/build/ 下。

⚠️ 注意:当前版本不支持 App 打包,仅支持 H5 与微信小程序两个平台。

六、Mock 数据

  • H5 开发模式(NODE_ENV=development)默认关闭,全部走真实后端接口;
  • 开启方式:将 src/static/config.js 的 enableMock 改为 true(显式设置优先级最高),或通过 uni.setStorageSync('enableMock', true) / 环境变量 MOCK_ENABLE 切换;
  • 覆盖 200 接口,fixture 位于 src/mock/data/,按 module/action 路由镜像;
  • 未覆盖的接口自动透传真实网络并输出提示;
  • Mock 数据由仓库内 mock-crawler 工具采集真实后端响应生成,发布前已做敏感字段脱敏(token/openid/手机号等)。

七、目录结构

src/  
├── pages/        页面(index 主包   public/app/user/order/course 五个分包,约 100  页面)  
│   ├── index/        首页(主包唯一页面,tabBar 入口)  
│   ├── launch/       启动页(加载与参数透传跳转,未在 pages.json 注册)  
│   ├── public/       公共分包:登录 / 注册 / 找回密码 / 协议 / 搜索 / 消息 / 结果页等  
│   ├── app/          业务功能分包:活动 / 圈子 / 考试 / 优惠券 / 积分 / 签到 / 证书 / 分销 / 直播带货等  
│   ├── user/         用户分包:个人中心 / 资产 / 余额 / 地址 / 收藏 / 学习记录 / 订阅 / 红包等  
│   ├── order/        订单分包:订单列表 / 详情 / 提交 / 评价 / 售后 / 物流等  
│   ├── course/       课程分包:课程详情 / 分类 / 专栏 / 小组 / 直播等  
│   └── template/     页面模板(新建页面的三文件拆分参考,未在 pages.json 注册)  
├── components/   组件(tz/ 自研组件库、uview-ui、qiun-data-charts、视频播放器等)  
├── common/       公共层  
│   ├── request/  接口封装($api 点分路由、统一鉴权/错误处理)  
│   ├── utils/    工具(路由映射、支付、直播、OSS 签名等)  
│   ├── order/    订单状态处理  
│   └── wechat/   微信登录/分享 SDK 封装  
├── mock/         Mock 数据(H5 开发模式默认关闭,开启方式见「六、Mock 数据」)  
├── static/       静态资源  
├── pages.json    页面路由与分包配置  
└── manifest.json 应用配置(appid 等)

八、开发约定

  • 页面采用 xxx.vue js.vue css.css 三文件拆分(<script src="./js.vue"> @import "./css.css"),逻辑与样式分离;
  • 接口调用统一走 this.$api('module.action', data),登录态、401 跳转、错误提示由拦截器统一处理;
  • 业务组件优先复用 components/tz/ 自研组件库;
  • 提交信息遵循 Conventional Commits(feat: / fix: / chore:)。

九、相关链接

名称 链接
使用文档 https://wood-soft.feishu.cn/wiki/KKLkwOPBHiButJkTluTcoXKenjh
功能列表 https://wood-soft.feishu.cn/wiki/YGFYw0k8PiJDWxketgHcBNKNnxe
授权价格 https://www.tuzhi.ltd/index/pricing/version.html
功能演示 https://www.tuzhi.ltd/index/demo/index.html

十、软件安全

安全问题请通过 Issue(需注明"安全")或邮件私下报告给项目维护团队,请勿在公开渠道描述可利用的漏洞细节。我们将在确认后尽快修复并同步发布。

十一、使用许可

  • 本软件遵循 凸知开源协议 V1.0(非商业用途免费,商业用途需购买商业授权),详见 LICENSE;
  • 第三方组件许可声明见 THIRD-PARTY-NOTICES.md(发布前请核对);
收起阅读 »

这20块独立打包费,算是喂狗了。

App打包

排除20分钟,使用独立打包,还是等了接近20分钟。。

排除20分钟,使用独立打包,还是等了接近20分钟。。