做这个“基于Android的招投标信息系统”的项目,前后折腾了大概三个月。起初是帮一家做招标代理业务的客户做内部工具,他们原来全靠PC端和邮件来回传标书,业务员出差在外经常错过报名截止时间,老板催进度也只能靠电话问。后来聊着聊着就决定直接做一个移动端信息系统,把招标公告发布、投标报名、标书上传下载、开标结果公示这些核心环节全部搬到Android手机上。做完之后复盘,发现这个项目虽然不算什么高深技术,但胜在业务流程完整、涉及的角色多、数据状态变化复杂,特别适合作为移动端信息化项目的典型样本。
这篇文章就把整个项目的设计和实现过程拆开来讲,包括我为什么选这套技术方案、每个核心模块是怎么落地实现的、数据库怎么设计、踩过哪些坑、遇到问题怎么排查。如果你是做Android开发想了解业务系统怎么设计,或者正打算给自己公司做一套类似的招投标管理工具,这篇文章应该能给你一个比较完整的参考。
1. 项目定位:移动招投标系统到底要解决什么问题
1.1 传统招投标流程的真实痛点
先别急着写代码,得说清楚这个系统是给谁用的、解决什么问题。招投标行业的业务链条其实很清晰:招标人发布招标公告,投标人根据公告要求报名、下载标书文件,在截止时间前提交投标文件,然后由评标委员会评审,最后公示中标结果。
这套流程在线下操作有四个很明显的问题。
第一个是信息传递慢。公告发出去之后,投标人往往是靠业务员口口相传或者反复刷新网页才知道有新项目。我接触过不少投标企业的业务员,手机里存着十几个招标平台的网址,每天上班第一件事就是挨个翻一遍,翻完还要判断哪些项目跟自己的公司资质匹配,效率非常低。
第二个是时间节点容易漏。投标报名有截止时间,标书递交有截止时间,保证金缴纳也有截止时间。错过一个节点,前面所有准备工作全部作废。用纸质流转或者邮件沟通,这些时间节点靠人脑去记,出错的概率非常高。
第三个是文件管理混乱。一份标书动辄几十上百页,电子版、纸质版、盖章版、PDF版、Word版,版本一多就分不清哪个是最终版。再加上标书文件动辄几十MB,用邮件发经常被拒收,用U盘拷又要人肉送。
第四个是过程不够透明。投标人想知道自己的标书有没有被收到、审核状态到哪一步了、有没有中标,传统方式只能打电话去问,一问还未必能问到准信。
1.2 移动端切入的独特价值
为什么选Android移动端来做这套系统,而不是继续做Web系统?最直接的原因是使用场景决定了终端形态。招标代理机构的业务员常年在外跑项目,投标企业的负责人也经常在工地、厂区、外地办事处之间往返,他们最需要的是掏出手机就能看到“今天有哪些项目在报名”“我参与的项目状态有没有变化”。
移动端的价值不只是“把网页塞进手机”。手机有推送能力,可以在报名截止前主动提醒业务员;手机有拍照和扫描能力,现场拿到纸质文件可以直接拍照存档;手机有GPS定位能力,可以记录开标现场的签到位置。这些是PC网页端天然不具备的。
当然,移动端也不是万能的。标书文件通常很大,手机上编辑和评审标书并不现实,所以我的定位是:Android端做信息查询、流程办理和提醒通知,PC端做文件编辑和后台管理。两端功能互补,不搞大而全。
1.3 用户角色与核心流程梳理
动工之前,先把用户角色理清楚。这套系统我划分了三类角色:
- 招标代理机构人员(管理员):负责发布招标公告、审核投标报名、上传标书文件、录入开标记录、发布中标公示。
- 投标企业人员(业务员):负责浏览公告、在线报名、下载标书、上传投标文件、查看项目进度和中标结果。
- 系统管理员:负责账号管理、角色分配、数据维护和系统配置。
核心业务流程我用一句话概括:公告发布 -> 投标人报名 -> 代理审核 -> 标书下载 -> 投标准备 -> 递交投标文件 -> 开标评标 -> 结果公示。整个系统的数据模型和功能模块,全部围绕这条主线展开。
这里有一个设计上的取舍需要说清楚:很多类似系统会把“在线支付保证金”也做进去,但我没有做。原因是支付涉及到金融合规、第三方支付对接和资金监管,项目周期和复杂度会成倍上升。我更倾向于在系统里管理“保证金缴纳状态”——代理机构在线下确认到账之后,在系统里把状态改成“已缴纳”,业务员手机端实时可见。这个取舍,既解决了信息透明度问题,又规避了支付合规风险。
2. 技术选型与总体架构设计
2.1 客户端技术栈选型与理由
技术选型没有追求新潮,我的原则是:团队熟、生态稳、资料多。最终客户端定的方案是:
- 开发语言:Kotlin + Java 混编。新写的业务代码用Kotlin,老一些的工具类保留Java。
- 网络层:Retrofit 2 + OkHttp 3,配合RxJava做异步回调。
- 图片加载:Glide,主要是加载公告附件里的图片和证书扫描件。
- 数据库:客户端本地用Room,服务端用MySQL。
- 架构模式:MVVM,用Jetpack的ViewModel + LiveData管理UI数据。
- 消息推送:极光推送(或类似第三方推送SDK)。
- 文件下载:OkHttp的DownloadListener + 自写的断点续传逻辑。
没有用现在很火的Jetpack Compose,主要原因是项目启动时团队对Compose还不够熟,而且系统里有大量表单页面和列表页面,使用成熟的RecyclerView + XML布局开发效率更高,踩坑成本更低。
2.2 服务端接口设计概览
服务端采用RESTful风格,返回统一JSON格式。整个系统接口按业务模块拆分,大致包括:
- 认证模块:登录、登出、修改密码、刷新Token。
- 公告模块:公告列表、公告详情、公告搜索、公告置顶状态。
- 报名模块:提交报名、报名状态查询、报名审核、取消报名。
- 文件模块:文件上传、文件下载、断点续传、文件列表。
- 项目模块:项目归档、进度查询、开标记录、中标公示。
- 消息模块:消息列表、已读标记、推送设置。
这里有一个坑要提前说:招投标业务的数据状态特别多,比如一个报名记录就有“草稿”“已提交”“待审核”“已通过”“已驳回”“已取消”六种状态。后端接口如果只是单纯地传状态码,客户端很容易出现“状态显示不一致”的问题。所以我在设计接口时做了一件事:所有涉及状态变化的接口,返回体里除了最新的状态码,还附带一个状态描述文字和时间戳,客户端直接展示,不需要自己再映射一套文案。
2.3 端到端通信与数据同步策略
招投标业务有一个特点:强实时性要求不高,但对数据一致性要求很高。开标结果这种关键信息,晚几分钟展示可以接受,但绝对不能出现“两个手机看到不同的中标结果”。
基于这个特点,我采用的策略是:普通业务数据走接口轮询 + 关键状态走消息推送。客户端在进入某个页面时主动请求最新数据,同时后台监听推送消息,收到推送后刷新对应页面或弹出提醒。比如报名审核通过、中标结果公示这种关键节点,服务端会主动推一条消息到客户端,客户端收到后自动拉取最新数据并更新UI。
这种“推送唤醒 + 主动拉取”的方式,比纯轮询省电省流量,比纯推送可靠。因为推送通道偶尔会丢消息,如果客户端完全依赖推送,状态就不同步了;而如果进入页面时强制拉一次接口,即使推送丢了,用户刷新页面也能拿到最新状态。
3. 核心功能模块的设计与实现
3.1 登录模块与基于Token的认证机制
登录模块是整个系统的入口,难点不在登录本身,而在权限控制和会话保持。我没有用传统的Session-Cookie方案,而是用了Token机制:客户端登录成功后,服务端返回一个AccessToken和一个RefreshToken,AccessToken有效期设为2小时,RefreshToken有效期设为7天。
客户端在内存中保存AccessToken,在本地加密存储中保存RefreshToken。每次请求时在Header里带上AccessToken,服务端拦截器校验通过才放行。AccessToken过期后,客户端自动用RefreshToken换取新的AccessToken,用户无感知地续期。
Token刷新这块有个细节很容易被忽略:多个请求并发时如果同时发现Token过期,不能每个请求都去刷新Token,否则会导致RefreshToken被反复使用而失效。我的做法是维护一个“刷新锁”——只有一个请求能发起刷新,其他请求进入等待队列,刷新完成后再统一重放。这个逻辑说起来简单,但实现时如果不加锁,线上就会偶发“登录状态突然失效,需要重新登录”的投诉。
登录页面上还做了一个实用功能:记住账号 + 快速登录。用SharedPreferences保存账号名,密码不落盘,Token过期时自动走刷新流程,尽量避免用户频繁输入密码。
3.2 招标公告模块:列表分页、搜索与缓存
招标公告是系统里访问量最大的模块,也是用户每天打开App第一个看到的界面。公告列表我实现了一个组合式的筛选条件:项目类型、地区、发布时间范围、报名截止状态、关键字搜索。
列表采用分页加载,每页20条,上拉加载更多。这里要特别说一下分页参数的设计。我用的不是传统的pageNum/pageSize,而是lastId + pageSize的方式:服务端按照时间倒序返回公告,客户端传最后一个公告的ID,服务端返回该ID之前的数据。这种方式的优势在于,用户下拉刷新后,列表新增的公告不会导致页码错乱,也不会出现重复数据。只要服务端各条公告的ID单调递增,翻页就不会乱。
公告详情页展示完整的招标信息,包括项目简介、资格要求、报名截止时间、招标代理机构联系方式等。详情页的数据我做了两级缓存:内存缓存 + Room缓存。已经看过的公告详情,弱网环境或离线状态下依然可以查看,这对经常跑外勤的业务员非常实用。
还有个容易被忽略但很影响体验的功能:报名截止时间的倒计时展示。详情页顶部用醒目颜色展示“距离报名截止还有XX天XX小时”,时间从服务器时间实时校准。这个功能需求很简单,但配套要解决一个技术点:客户端不能用手机本地时间做倒计时,因为用户改系统时间会导致倒计时不准。我的做法是登录时获取服务器时间,计算手机本地时间与服务端时间的偏移量,所有倒计时都基于这个校准后的时间。
3.3 投标报名模块:状态机设计与表单校验
报名模块是整个系统里业务逻辑最复杂的模块。一个投标人要报名,需要提交企业资质文件、项目负责人信息、授权委托书等多类材料,还要经过代理机构人工审核。
报名表单我设计了动态字段加载:客户端启动时从服务端拉取当前项目的报名表单模板,根据模板动态渲染表单控件。这样做的原因是,不同项目的资质要求不一样,有的项目需要安全生产许可证,有的项目需要特定行业资质,客户端如果写死表单,那么每次业务调整都要发版App,不现实。
报名提交后进入状态机流转:已提交 -> 待审核 -> 已通过 / 已驳回。被驳回时,服务端会附带驳回原因,客户端展示驳回原因并允许用户修改后重新提交。
这里有一个很关键的细节判断:重新提交时,用户已经填过的表单不能清空。我采用的做法是:本地保存表单填写草稿,重新提交时自动回填上一次的填写内容,只让用户修改被驳回的字段。这个功能开发量不大,但对用户好感度提升非常明显。
报名审核的实时提醒也很重要。我在服务端集成了Push消息推送,审核通过或驳回时,系统自动给投标人推送消息。用户点击消息后,直接跳转到该项目的报名详情页,不用重新去找项目。
3.4 标书文件的上传下载与断点续传
标书文件是整个系统体量最大的数据。一份标书电子版平均在30MB到80MB之间,上传下载的体验直接决定了用户对这个系统的评价。
上传方面,我实现了分片上传:客户端将文件按照每片2MB的大小切分,逐片上传到服务端,全部上传完成后服务端合并。单片上传失败时自动重试3次,已经传过的分片不重复上传。手机上网络不稳定,经常传一半断掉,没有分片上传的话,一个80MB的文件看到“传了70%突然失败重新来”,用户心态直接爆炸。
下载方面,我实现了断点续传。核心思路是:下载前先请求服务端获取文件大小,本地数据库记录已下载的字节数;每次下载时带上Range: bytes=已下载字节数-的请求头,服务端从指定位置继续传输。
还要解决一个文件下载后的打开问题。手机上收到一个标书PDF,用户点击要能直接打开预览。项目里集成了开源PDF预览组件,并兼容常见的doc、docx格式——doc文件先调用系统的文件打开方式,如果系统没有对应应用,就引导用户下载WPS等办公软件打开。
文件存储路径我统一放在getExternalFilesDir()目录下,按项目ID建子目录。这里有个经验:千万不要把文件下载到公共存储目录(比如Download目录),否则在Android 10及以上版本会遇到分区存储的权限限制,而且卸载App后残留的垃圾文件也不好清理。
3.5 开标记录与中标公示
开标评标环节,移动端做的事情相对轻量:代理机构在开标现场用手机记录开标时间、录入唱标价格、拍摄开标现场照片,实时上传到系统。投标人通过App实时查看开标进度和报价记录,不用到现场也能掌握进展。
中标公示模块,投标人登录后可以在“我的项目”里看到自己参与项目的公示状态。公示信息包括中标候选人名单、中标金额、公示期截止时间。公示期内,用户可以在App上提交异议反馈,反馈内容直接进入代理机构后台处理流程。
这个模块上线后效果最明显的一个功能是:中标结果一旦公示,App自动推送消息给所有参与投标的业务员,业务员再也不用时不时刷网页看结果了。光是这一条,客户方的项目经理就说“业务员终于能在下班后安心陪孩子了”。
4. 本地数据设计与网络层封装
4.1 客户端Room数据库表结构设计
客户端用Room做离线缓存和本地数据管理,表结构设计围绕两个原则:一是缓存服务端列表数据,二是存储用户的操作草稿。
核心表包括:
tb_user:用户表,存用户ID、角色、姓名、企业名称、Token。tb_notice_cache:公告缓存表,存公告列表数据、分页游标、缓存时间。tb_project_follow:关注项目表,存用户关注的项目ID、关注时间。tb_draft:草稿表,存报名表单草稿、留言草稿等。tb_download_record:下载记录表,存文件下载进度、本地路径。
这里有一个设计经验:公告缓存表不要直接存整个JSON字符串,那样做虽然简单,但查询和更新很不方便。我是在客户端把JSON解析成实体类后,逐字段存到表的列里,然后用Room的@Query支持按标题搜索、按时间排序。这样在公告列表页做“本地搜索”时,可以直接查询数据库,不需要网络请求。
4.2 Retrofit网络层封装与统一异常处理
网络层是整个客户端最核心的基础设施,我做了三层封装。
第一层是Retrofit的Service接口定义,每个接口对应一个业务方法,返回Observable<T>或者协程的suspend函数。
第二层是统一的Repository仓库层,负责调用Service接口、解析响应数据、处理缓存逻辑。业务模块的ViewModel只和Repository打交道,不知道数据是来自网络还是本地缓存。
第三层是网络状态和异常处理。我封装了一个ApiResponse包装类,所有接口返回的数据都包一层,包含code、message、data三个字段。网络请求失败时的处理逻辑集中在BaseViewModel里,根据异常类型统一提示:网络不通提示“请检查网络连接”,超时提示“请求超时,请稍后重试”,服务器错误提示“服务暂时不可用”。业务代码里不需要到处写try-catch。
4.3 接口数据一致性校验
招投标系统对数据准确性要求很高,我在设计接口时还加了一层“数据指纹”校验。具体来说,公告、项目详情、报名状态这类关键数据,服务端在返回时除了业务字段,还带一个dataVersion(版本号)。客户端每次拿到数据,先比对版本号,如果版本号变了说明数据有更新,即使内容相同也要刷新;如果版本号没变,则可以放心使用缓存。
这个机制在解决“多端数据一致性”上特别有效。举个例子:代理机构的操作员在PC端把报名状态从“待审核”改成了“已通过”,服务端的dataVersion自动加1。投标人的Android端收到推送后刷新数据,发现版本号不一致,就知道状态变了,立即更新UI。如果没有这个版本号,客户端单纯比对字段内容,有些情况下因为内容恰好相同,容易出现“数据没变”的误判。
5. 关键难点:权限安全、大文件与性能优化
5.1 权限校验与业务数据安全
招投标数据属于敏感商业数据,权限安全这块不能马虎。除了登录Token校验,我在服务端还做了接口级权限控制:每个接口都声明了允许访问的角色,比如“发布公告”接口只允许招标代理机构和系统管理员调用,投标人调用直接返回403。
客户端的权限控制主要做两件事:一是按角色隐藏功能入口,业务员看不到“发布公告”按钮,代理人员看不到“投标报名”入口;二是对已下载的标书文件做加密存储。标书加密我用的AES对称加密,密钥存在Android的KeyStore里,这样即使手机root了,别人拿到存储文件也解不开内容。
这里有一个常见的做法值得说明:不应该只在客户端做权限隐藏,那只是“看起来没权限”,真正要防的是越权调用接口。所以客户端隐藏入口只是提升用户体验,最终的权限管控一定要在服务端做。我在项目里反复强调这一点,因为很多初学Android的开发者容易犯“前端隐藏了就安全了”的错。
5.2 大文件分片上传的进度与稳定性
前面提到分片上传,这里把实现细节拆一下。分片上传的整体流程是:
- 客户端请求“初始化上传任务”接口,传入文件名、文件大小、MD5,服务端返回一个
uploadId。 - 客户端按每片2MB切分文件,逐片上传。每个分片请求带上
uploadId、chunkIndex、chunkContent。 - 所有分片传完后,客户端请求“合并文件”接口,服务端把所有分片拼接成完整文件,并做MD5校验。
- 如果第2步中某个分片失败,客户端只重传该分片。App退出后再进来,先查询服务端已收到的分片列表,从下一个分片继续传。
这个方案在弱网环境的实测表现很好。有一个真实场景:客户在贵州某工地用4G网络上传一份60MB的标书,全程大概6分钟,断网两次,每次都是断网后自动续传,没有重新上传。
分片上传还有一个好处,是秒传能力。如果服务端发现某个文件在数据库里已有相同MD5记录,表示之前有人传过同一个文件,直接返回文件已存在,客户端跳过上传。这个功能在客户实用中减少了至少30%的重复标书上传。
5.3 Android性能优化:列表卡顿与包体积控制
招投标系统的列表页比较多,公告列表、项目列表、消息列表,每个列表项里都有图片预览、状态标签、时间倒计时等元素。RecyclerView卡顿是这类页面最容易出现的问题,我主要做了三件事来优化。
第一,图片统一用Glide加载并做尺寸压缩,列表缩略图统一加载480像素宽度的图,点击查看原图时才加载大图。第二,列表项的倒计时用Handler驱动,但只在可见的第一个和第二个列表项里启动计时器,滑动时立即停掉之前的计时器,避免多个倒计时同时跑导致CPU占用过高。第三,数据列表用DiffUtil做差异化刷新,而不是整个列表刷新,减少不必要的UI重绘。
包体积方面,考虑到业务员手机配置参差不齐,我对APK做了精简。最终包体从46MB压到31MB,做法是启用资源瘦身、移除无用的语言包、用WebP替换大部分PNG图片。一个31MB的安装包,在4G网络下下载也就十几秒,用户安装意愿会高很多。
优化过程中有一个细节很值得分享:招投标系统中经常要用到企业资质证书的扫描件,这些图片分辨率极高,加载时如果不做采样压缩,直接加载原图会导致OutOfMemory。我封装了一个Bitmap工具类,按ImageView的显示尺寸做采样率计算,统一走inSampleSize,实测OOM率从优化前的3.7%降到了0.1%以下。
6. 实战总结:踩过的坑与排查技巧
6.1 状态不同步问题:推送丢失导致界面滞后
项目上线初期,遇到一个典型问题:代理机构在PC端审核通过了报名,但投标人手机上没有立即显示“已通过”。用户在App里反复下拉刷新才看到结果。
排查后发现,原因有两个。一个是推送SDK在部分国产手机上进程被杀掉,消息无法准时到达;另一个是服务端推送回调失败后没有补偿机制,单纯依赖推送通道。
解决思路做了两层保障:第一,App前台运行时,收到推送后立即拉取详情接口刷新;第二,App从后台回到前台时,对所有“进行中”的项目主动做一次批量状态同步。同时在服务端加了推送回调失败的补偿逻辑,推送失败后半小时内自动重推,重推不超过3次。这套机制上线后,状态滞后投诉量明显减少。顺便说一句,如果不用第三方SDK、自己维护推送长连接,成本会高不少,小团队建议直接选成熟的推送服务。
6.2 文件下载失败与断点续传异常排查
有用户反馈,在下载标书时,进度到99%卡住不动,或者提示下载失败重新开始。排查时先看服务端日志,发现这类问题集中在“服务端返回了206 Partial Content,但客户端校验文件总大小时不一致”的场景。
原因是部分代理机构的服务器之前配置过代理,反向代理在转发大文件请求时,默认把Range头丢掉了,导致服务端返回200全量数据,客户端按偏移量拼接文件时出现错位。解决办法是要求代理服务器的配置必须透传Range头,同时客户端在下载时增加“文件长度校验”:如果下载到的字节数和预期不符,直接判失败并重试,而不是继续拼接,避免生成一个损坏的文件。
6.3 内存泄漏排查:单例持有页面Context
开发中遇到过一次比较隐蔽的内存泄漏。公告详情页频繁打开关闭后,内存占用一直涨,用Android Studio的Profiler一查,发现是图片加载库的一个全局单例持有Activity引用了。具体原因是Glide在初始化时传入的Context是Activity的,而不是Application的。
修复方法很简单:Glide初始化时只用Application的Context,所有加载请求通过View的getContext()间接获取上下文。这个坑其实在官方文档里写了,但很多人不仔细看。在这里提醒一下,凡是初始化第三库,凡是长得像全局单例的东西,一律用ApplicationContext,不要图方便直接传Activity。
6.4 常见问题速查表
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
| 登录后很快提示登录失效 | AccessToken过期、RefreshToken刷新逻辑冲突 | 检查并发刷新锁;检查RefreshToken是否被多次使用 |
| 公告列表翻页出现重复数据 | 分页游标使用了pageNum而非lastId,新增数据导致偏移 | 改用lastId分页,并确保ID递增 |
| 报名表单提交后数据丢失 | 服务端表单模板更新,客户端缓存了旧模板 | 提交前校验模板版本号,不一致时强制刷新 |
| 标书下载到一半失败 | 服务端反代丢失Range头 | 检查服务端代理配置;客户端增加文件长度校验 |
| 倒计时时间不准 | 使用手机本地时间 | 登录时校准服务器时间差 |
| 推送收不到 | 国产ROM后台杀进程、推送通道中断 | 增加前台轮询兜底;后台返回时主动同步 |
| 列表滚动掉帧 | 图片加载过重、倒计时Handler未及时停止 | Glide缩略图、Handler按需启停、DiffUtil |
排查这个问题,我的经验是不要上来就改代码,先看日志和抓包,确认是客户端问题、服务端问题,还是网络链路问题。招投标系统的业务链路长,从App到服务端到数据库再到推送通道,任何一环出问题都会表现成“用户看到的现象不对”。养成“先定位分层、再动手修复”的习惯,能节省大量时间。
7. 扩展方向与个人经验谈
7.1 这套系统后续还能怎么演进
项目上线稳定运行之后,其实还有几个方向可以继续做深。
第一个是加入电子签章能力。投标文件在手机上直接完成盖章和签署,这会是移动招投标的一个刚需,但涉及第三方CA证书集成,合规要求高。
第二个是智能推荐。根据投标企业的行业分类、资质等级和历史投标记录,系统自动推荐匹配的招标公告。比如某家企业有建筑一级资质,最近投过两个市政项目,系统就能优先推荐市政类的招标公告。
第三个是数据分析报表。在管理端增加投标数据分析模块,比如“每季度各类项目投标数量趋势”“各投标企业活跃度排行”等。这些功能用现有数据就能做,但对客户的管理决策帮助很大。
第四个是适配平板和折叠屏。很多评标现场会用到平板展示标书内容,当前的界面在平板上只是简单地拉伸放大,体验一般。如果针对平板做双栏布局,更符合商务场景的使用习惯。
7.2 我做这个项目的一些体会
做完这套系统,最深的体会有三点。
第一个体会是,业务系统的难度不在技术,而在业务理解。如果对招投标流程不熟悉,做出来的功能很可能“每个按钮都有,但用起来总觉得哪里不对”。我在项目初期花了两周时间跟随客户方的业务员跑现场,观察他们怎么获取公告、怎么整理标书、怎么追进度。这些一手资料比网上搜索到的业务流程描述有用得多。
第二个体会是,不要为了技术而技术。刚开始我想在项目里引入微服务架构、引入Kotlin协程Flow、引入DataBinding等一堆新技术,后来冷静下来,评估团队能力和项目规模,果断砍掉大部分,只留下了真正能解决问题的技术。系统稳定上线比技术炫酷更能赢得客户信任。
第三个体会是,移动端业务系统一定要重视“弱网环境测试”。招投标业务的用户经常在工地、厂区、偏远地区办公,信号差是常态。我的测试清单里专门有一项:在电梯里、在地下室、在移动信号只有一格的地方,把核心流程完整走一遍。很多问题都是在这些场景下暴露出来的。
如果你正好要做一个类似的移动端业务系统,我建议你先把流程图画清楚、把角色权限梳理明白,再动手写代码。技术上没有太难的点,稳扎稳打,一定能做出来。这套系统的完整代码和文档我放在了自己的服务器上,虽然不能公开,但你在过程中遇到的任何具体技术问题,欢迎随时交流,我尽量把你需要的踩坑细节都讲透。