
简介这是一套基于ThinkPHP与uniapp开发的开源网约车、代驾、顺风车及货运多端小程序源码面向希望研究出行平台业务逻辑与双端小程序搭建的开发者可用于本地测试、代码学习与二次开发练习。压缩包共1276个文件约144.69MB以vue页面组件、js业务逻辑、json配置、wxml与wxss小程序模板、png图标资源为主另含scss样式、ts脚本及少量apk安装包覆盖乘客端、司机端与后台管理三大模块。乘客端支持地图选点叫车、司机车辆资料查看、一键求救与优惠券营销司机端内置高德导航、离线收费、自动与手动接单及路线规划后台涵盖会员分组、实名与车主认证、代驾订单、顺风车评价、货运车辆等管理功能。目前已有836人学习适合研究多端出行系统架构与接口设计的开发者参考。1. 从一份双端司机入驻包说起uniapp 网约车项目到底能不能跑起来前阵子有个做同城货运的朋友找我说他手上有个司机端入驻的需求想用 uniapp 一套代码同时出微信小程序和 App问我有没有现成的开源包能直接拆。我翻了一圈发现市面上打着「网约车源码」旗号的东西不少但真正把司机入驻、接单、货运/代驾/顺风车多业务线揉进一个 uniapp 双端包里的能跑通的不多。这份纯开源 uniapp 小程序包就是在这个背景下被我拆开的——它不是那种只给你几个静态页面的壳子而是把司机从注册、资质上传、审核状态流转到接单大厅的完整链路都铺了一遍同时兼容小程序和 App 两端编译。适合谁一是想快速搭一套司机侧入驻系统的团队二是拿它当 uniapp 多端适配的练手项目三是做货运、代驾、顺风车这类同城业务的产品经理想看看司机端到底该有哪些字段和状态机。下面我按自己实际拆包的顺序把能复现的部分一条条写出来。2. 拆包先看目录uniapp 双端司机入驻的工程结构怎么读拿到一个 uniapp 包别急着 npm install先把目录树拉出来看三遍。这份包的根目录结构是典型的 uniapp CLI 工程但它在 pages 层做了业务线拆分这是它和普通 demo 最大的区别。2.1 根目录关键文件与作用先看根目录我一般会重点盯这几个文件文件/目录作用拆包时注意manifest.json各端编译配置重点看 app-plus 和 mp-weixin 的权限声明pages.json路由与 tabBar司机端 tabBar 通常只有 3 到 4 个App.vue全局生命周期看登录态恢复逻辑写在哪main.js入口看 Vue 版本和全局挂载static/静态资源司机端图标、占位图、协议模板pages/业务页面按业务线分子目录components/公共组件接单卡片、状态标签、上传组件utils/工具函数请求封装、定位、格式化store/状态管理司机信息、订单列表、token这份包的 pages 目录下能看到 driver-join、driver-order、driver-cargo、driver-chauffeur 这类命名说明它把入驻、订单、货运、代驾分开了。顺风车相关页面通常挂在 driver-trip 或 driver-carpool 下。你拿到手第一件事是确认这些目录是不是都有实际内容有些包会留空目录充数。2.2 双端编译配置的差异点uniapp 最容易被低估的就是双端差异。这份包在 manifest.json 里对 app-plus 和 mp-weixin 分别做了配置我摘几个关键字段{ mp-weixin: { appid: , setting: { urlCheck: false, es6: true, postcss: true }, permission: { scope.userLocation: { desc: 用于获取司机当前位置 } }, requiredPrivateInfos: [getLocation, chooseLocation] }, app-plus: { modules: { Geolocation: {}, Camera: {}, Gallery: {} }, distribute: { android: { permissions: [ uses-permission android:name\android.permission.ACCESS_FINE_LOCATION\/, uses-permission android:name\android.permission.CAMERA\/ ] } } } }逻辑说明小程序端的定位权限走permission和requiredPrivateInfosApp 端走modules和原生权限声明。参数上urlCheck: false是开发阶段跳过域名校验用的上线前必须改回 true 并在小程序后台配好合法域名。App 端的 Camera 和 Gallery 模块是司机上传证件照必需的缺了会在真机上直接调不起相册。提示如果你只跑小程序端app-plus 那段可以先不动但要出 App 包Geolocation 模块不勾选定位接口会静默失败不报错但拿不到坐标这个坑我踩过。2.3 司机入驻页面的字段与状态机司机入驻不是一张表单就完事它背后是个状态机。这份包把入驻拆成了几个页面基础信息、证件上传、车辆信息、审核结果。字段层面常见的有姓名、手机号、身份证号、驾驶证、行驶证、车辆类型、车牌号。状态层面我梳理了一下它页面里出现的状态值pending提交后待审核reviewing审核中approved通过rejected驳回带驳回原因这几个状态决定了司机能不能进接单大厅。页面跳转逻辑一般是提交成功后进 reviewing 页轮询或手动刷新查状态approved 后跳转接单首页。这里有个细节驳回后要允许重新编辑并再次提交很多包只做了单向流程驳回就卡死这份包在 rejected 分支里留了重新提交入口算是完整。3. 跑起来的第一步环境、依赖与双端编译命令拆完结构下一步是让它跑起来。uniapp 项目跑不起来八成是环境或依赖版本对不上我按实际顺序写。3.1 环境准备与依赖安装先确认 Node 版本。uniapp CLI 工程对 Node 版本敏感我一般用 16.x 或 18.x20.x 有时会在编译小程序时出幺蛾子。装依赖# 确认 node 版本建议 16 或 18 node -v # 安装依赖用 npm 或 yarn 都行 npm install # 如果卡在某个包先清缓存再装 npm cache clean --force npm install逻辑说明npm install会拉取 package.json 里的依赖uniapp 项目常见依赖包括dcloudio/uni-app、dcloudio/uni-mp-weixin、dcloudio/uni-app-plus等。参数上没什么可调的但如果你公司内网有私有源记得先配 registry否则会卡在某个 scoped 包上。装完检查 node_modules 里dcloudio目录是否完整缺了对应端的包编译时会提示找不到平台。3.2 小程序端编译与开发者工具导入小程序端编译命令# 编译到微信小程序输出到 dist/dev/mp-weixin npm run dev:mp-weixin # 生产构建 npm run build:mp-weixin逻辑说明dev:mp-weixin是开发模式带热更新输出目录一般在dist/dev/mp-weixin。编译完成后打开微信开发者工具选择「导入项目」目录指向这个输出目录不是项目根目录。AppID 可以先用测试号但定位和上传相关能力在测试号下会受限。参数上如果你改了输出路径去 vue.config.js 或 manifest.json 里找outputDir配置。注意导入开发者工具后如果白屏先看控制台有没有报app.json找不到通常是 pages.json 里路径写错或 tabBar 图标缺失。图标路径必须是相对 static 的绝对路径写错一个就整个 tabBar 不渲染。3.3 App 端打包与真机调试App 端有两种跑法HBuilderX 云打包和 CLI 本地打包。这份包是 CLI 工程我一般先用 HBuilderX 打开根目录做真机运行确认逻辑没问题再云打包。# CLI 方式编译到 App 资源 npm run dev:app-plus # 输出目录 # dist/dev/app-plus逻辑说明dev:app-plus生成的是 App 资源包需要配合 HBuilderX 或原生基座运行。真机调试时把手机连上HBuilderX 里选「运行到手机或模拟器」它会自动安装基座并加载资源。参数上manifest.json 里的appid要填对云打包时证书和包名也要配。常见问题是 Android 9 以上默认禁止明文 HTTP如果你的接口是 http需要在 manifest 里开usesCleartextTraffic否则请求全挂。4. 司机入驻与接单链路接口封装、定位与状态流转的实操跑起来之后真正要改的是业务链路。这份包把司机入驻和接单串成了一条线我按数据流拆。4.1 请求封装与 token 管理uniapp 里请求一般封装在 utils/request.js。这份包的封装思路是拦截器加统一错误处理// utils/request.js const BASE_URL https://your-api.example.com function request(options) { const token uni.getStorageSync(driver_token) return new Promise((resolve, reject) { uni.request({ url: BASE_URL options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, Authorization: token ? Bearer ${token} : }, success: (res) { if (res.statusCode 401) { uni.removeStorageSync(driver_token) uni.reLaunch({ url: /pages/login/login }) return reject(new Error(登录过期)) } if (res.data.code ! 0) { uni.showToast({ title: res.data.msg, icon: none }) return reject(new Error(res.data.msg)) } resolve(res.data.data) }, fail: (err) reject(err) }) }) } export default request逻辑说明BASE_URL换成你自己的接口地址。Authorization头带 token401 时清 token 并跳登录这是司机端标配。参数上res.data.code ! 0是业务错误码约定不同后端可能用 200 或 1 表示成功按你后端改。注意uni.reLaunch会关掉所有页面避免用户返回时又进到需要登录的页。4.2 定位与城市选择司机端离不开定位。这份包在入驻页和接单大厅都调了定位// 获取当前位置 uni.getLocation({ type: gcj02, success: (res) { console.log(纬度, res.latitude, 经度, res.longitude) // 存到 store 或本地 uni.setStorageSync(driver_location, { lat: res.latitude, lng: res.longitude }) }, fail: (err) { console.error(定位失败, err) uni.showToast({ title: 请开启定位权限, icon: none }) } })逻辑说明type: gcj02是国测局坐标小程序和 App 都支持别用 wgs84否则地图偏移。参数上getLocation在小程序端需要requiredPrivateInfos声明App 端需要 Geolocation 模块。失败回调里要引导用户去设置页开权限光弹 toast 没用。常见坑是模拟器定位不准真机测试才靠谱。4.3 入驻状态轮询与接单大厅跳转提交入驻后页面要能查状态。这份包用的是定时轮询// 入驻状态查询 let timer null function startPolling() { timer setInterval(async () { const res await request({ url: /driver/audit/status }) if (res.status approved) { clearInterval(timer) uni.redirectTo({ url: /pages/driver-order/hall }) } else if (res.status rejected) { clearInterval(timer) uni.showModal({ title: 审核未通过, content: res.reason || 请修改后重新提交, showCancel: false }) } }, 5000) } // 页面卸载时清掉避免内存泄漏 onUnload(() { if (timer) clearInterval(timer) })逻辑说明setInterval每 5 秒查一次approved 跳接单大厅rejected 弹驳回原因。参数上轮询间隔别太短5 到 10 秒合适太短会被后端限流。onUnload里清定时器是必须的否则用户退出页面后定时器还在跑内存和请求都浪费。接单大厅的跳转用redirectTo而不是navigateTo避免用户返回时又回到审核页。5. 避坑与排查双端编译和司机入驻里最容易翻车的几件事这一章是我拆包过程中实际遇到的坑按现象、原因、解决写。5.1 小程序端定位接口报「getLocation 未声明」现象开发者工具里调uni.getLocation直接 fail提示getLocation:fail the api need to be declared in the requiredPrivateInfos field。原因微信从某个基础库版本起定位、选点等接口必须在 manifest 的requiredPrivateInfos里显式声明光配permission不够。解决在 manifest.json 的 mp-weixin 节点下加requiredPrivateInfos: [getLocation, chooseLocation]重新编译。如果还不行检查开发者工具的基础库版本调高到支持该字段的版本。5.2 App 端打包后接口全部请求失败现象真机装包后所有接口返回失败但小程序端正常。原因Android 9 及以上默认禁止明文 HTTP 请求如果你的接口是 http 开头系统直接拦截。解决要么把接口换成 https要么在 manifest.json 的 app-plus 里开usesCleartextTraffic: true。生产环境建议直接上 https明文传输司机证件信息风险太大。5.3 司机证件照上传后显示裂图现象上传成功但预览时图片裂开小程序端尤其明显。原因上传返回的是相对路径前端直接拿相对路径渲染小程序端没有域名前缀就加载不出来。解决上传接口返回的路径要么是完整 URL要么前端拼上 BASE_URL。检查 request 封装里有没有对图片路径做统一处理。另外小程序端图片域名要在后台配 downloadFile 合法域名否则真机加载失败。5.4 审核状态轮询导致页面卡死现象入驻审核页停留久了页面越来越卡最后点不动。原因定时器没清或者每次进入页面都新起一个定时器多个定时器叠加。解决在onUnload和onHide里都清定时器并且用一个全局变量存 timer避免重复创建。如果用了组件在组件beforeDestroy里也清一遍。5.5 双端 tabBar 图标在 App 端不显示现象小程序端 tabBar 正常App 端图标空白。原因App 端对 tabBar 图标的尺寸和格式更严格png 尺寸不对或路径用了网络地址都可能不显示。解决图标统一用本地 png尺寸按官方建议81x81 左右路径写/static/tabbar/xxx.png这种绝对路径。改完重新编译 App 资源别只刷新。6. 进阶把司机入驻包改造成多业务线可配置的接单系统拆到最后这份包最值钱的地方不是它现在能跑而是它的结构允许你往货运、代驾、顺风车多条线扩。我一般会做三件事把业务线抽成配置、把状态机抽成常量、把接口按业务线分模块。先抽业务线配置。在 utils 下建一个biz-config.js// utils/biz-config.js export const BIZ_LINES { cargo: { name: 货运, orderHall: /pages/driver-cargo/hall, needVehicle: true, vehicleTypes: [小面, 中面, 4.2米] }, chauffeur: { name: 代驾, orderHall: /pages/driver-chauffeur/hall, needVehicle: false, vehicleTypes: [] }, carpool: { name: 顺风车, orderHall: /pages/driver-trip/hall, needVehicle: true, vehicleTypes: [5座, 7座] } }逻辑说明BIZ_LINES把每条业务线的名称、接单大厅路径、是否需要车辆、可选车型都收进来。入驻页根据当前业务线动态渲染车辆信息模块接单大厅跳转也读这个配置。参数上needVehicle为 false 时代驾入驻就不显示车辆表单避免司机填一堆无关字段。这样加一条新业务线只改这个文件不用动页面逻辑。再抽状态机常量。建一个utils/order-status.jsexport const ORDER_STATUS { PENDING: { value: pending, label: 待接单, color: #f0ad4e }, ACCEPTED: { value: accepted, label: 已接单, color: #5cb85c }, ONGOING: { value: ongoing, label: 进行中, color: #0275d8 }, FINISHED: { value: finished, label: 已完成, color: #999 }, CANCELED: { value: canceled, label: 已取消, color: #d9534f } } export function getStatusLabel(value) { const item Object.values(ORDER_STATUS).find(s s.value value) return item ? item.label : 未知 }逻辑说明状态值和展示文案、颜色绑在一起页面里只调getStatusLabel不写死字符串。参数上颜色值按你 UI 规范改value要和后端返回的状态码对齐。这样后端改状态码前端只改这一处。最后是验证方法。改完配置后我一般跑一个最小验证切到代驾业务线确认入驻页不显示车辆表单提交后状态轮询正常approved 后跳到代驾接单大厅而不是货运大厅。再切到货运确认车型下拉是「小面、中面、4.2米」。两端都跑一遍小程序端重点看定位和图片App 端重点看权限和明文请求。这套流程走完基本就能确认改造没破坏原有链路。从那以后我每次拆 uniapp 双端包都强制先跑一遍「小程序定位 App 打包 状态轮询」这三件套任何一个环节报错就先停下来排查不往下写业务。这份包在这三件套上表现算稳的结构也留了扩展余地适合拿来当司机侧系统的起点。希望帮到你。本文还有配套的精品资源点击获取