简介:这是一套可用于二次开发与学习参考的微信小程序源码,面向前端开发者、小程序爱好者及WIFI营销系统研究者,聚焦于WiFi热点管理、分销推广与流量主变现等实际业务场景。资源包含完整前后端代码,共1832个文件,以1487个PHP后端逻辑文件为核心,辅以71个PNG图标资源、38个JS交互脚本、25个JSON配置、23个CSS样式文件及少量SQL数据库脚本和Dockerfile等运维支持文件,整体压缩包仅8.23MB,结构紧凑、模块清晰。目前已有909人学习下载,反映出较强的技术关注度与实践需求。读者可直接部署运行独立版WIFI大师小程序,快速掌握后台分页管理、平台统计看板、WiFi码双版本导出、公告图标化展示、插件中心集成等实用功能实现逻辑,并深入理解含AmazeUI、Layer、UMEditor、FullCalendar等主流前端组件的小程序管理后台架构设计。
1. 新版WIFI大师v4.47小程序源码:一套可二次开发的轻量级WiFi分销系统前端工程,适合快速搭建带流量主、支持独立部署的微信小程序管理界面
你有没有遇到过这样的场景:客户要一个能扫码连WiFi、带后台统计、还能挂广告变现的小程序,但又不想从零写Vue或Taro?或者你手头有个现成的WiFi热点运营项目,急需一套能直接改样式、加字段、对接自己后端的前端架子?这套网传的「新版WIFI大师v4.47小程序源码」就是冲着这个需求来的——它不是黑盒App,而是一份结构清晰、模块分离、已接入微信原生API(如wx.scanCode、wx.showModal)、内置流量主广告位(ad-unit-id占位符明确)、且支持脱离官方平台独立运行的完整小程序前端工程。它不依赖云开发,所有接口走标准HTTPS请求;不绑定特定云服务商,你换自己的Nginx+Node.js后端只需改3个配置项;甚至“清除缓存”“导出WiFi码”这些高频操作都已封装成可复用函数。适合有基础前端能力的开发者做定制化交付,也适合教学场景下带学生拆解真实商业小程序的路由组织、状态管理与广告集成逻辑。注意:源码未附后端,也未提供数据库设计,它定位是「前端交付包」,不是开箱即用的SaaS系统。
2. 源码结构解析与核心模块定位:从10个CSS文件看工程分层逻辑与可修改边界
这套源码虽小,但结构上明显遵循了「表现层隔离 + 功能模块解耦」的设计思路。我们先不急着跑起来,而是打开根目录,用树状结构理清它的物理组织:
├── app.js # 小程序全局逻辑入口,含onLaunch、onShow及全局数据初始化 ├── app.json # 页面路由配置、窗口样式、tabBar定义(含“首页”“我的”“统计”三栏) ├── project.config.json # 微信开发者工具项目配置(appid已脱敏为占位符) ├── sitemap.json # 搜索引擎收录配置(默认关闭) ├── pages/ # 所有页面目录 │ ├── index/ # 首页:扫码连网、热点列表、广告位 │ ├── my/ # 我的页面:账号信息、分销设置、收益明细 │ ├── admin/ # 后台管理页(需权限控制):公告管理、插件中心、统计看板 │ └── ... # 其他功能页(如WiFi码生成、导出页) ├── components/ # 自定义组件:ad-banner(广告组件)、wifi-card(热点卡片)、stat-chart(统计图表) ├── utils/ # 工具函数:request.js(统一封装wx.request)、storage.js(本地缓存增强)、qrcode.js(生成WiFi二维码) ├── static/ # 静态资源:图标、字体、默认图片 └── style/ # 样式体系(重点!) ├── amazeui.min.css # Amaze UI框架精简版(栅格、按钮、表单基础样式) ├── layer.css # 弹层组件样式(用于提示框、确认弹窗) ├── fullcalendar.min.css # 日历控件样式(用于“平台统计”中的时间筛选) ├── umeditor.css # 富文本编辑器样式(用于公告编辑) └── app.css # 项目主样式:覆盖Amaze UI、定义主题色、重写组件默认行为提示:
app.css是你唯一需要长期维护的样式文件。其他.min.css均为第三方库压缩版,修改它们等于放弃后续升级能力。app.css里已用CSS变量定义了主色(--primary-color: #1aad19)、背景色(--bg-color: #f5f5f5),改这两个值就能快速换肤。
2.1 为什么选Amaze UI而非WeUI或Vant Weapp?
这不是技术怀旧,而是业务权衡。WeUI偏重微信原生感,但缺少分页表格、日历、富文本等后台管理刚需组件;Vant Weapp体积大(gzip后超300KB),对WiFi类工具小程序属于冗余。而Amaze UI v2.8的精简版(amazeui.min.css仅86KB)提供了:
am-list+am-pagination:支撑后台“板块列表分页”需求(对应更新项#1);am-calendar:配合fullcalendar.min.css实现平台统计的时间维度筛选;am-modal+layer.css:组合出符合国内用户习惯的确认弹窗(比原生wx.showModal更可控)。
实际开发中,某导师在带学生做模拟项目X时,就要求必须用Amaze UI实现“公告管理页”,理由很实在:学生能在2小时内理解其栅格系统并完成响应式布局,而Vant的slot透传和props嵌套会让新手卡在调试上。
2.2 流量主广告位的3种植入方式与替换路径
源码中广告并非硬编码,而是通过3层抽象实现灵活替换:
- 组件层:
components/ad-banner/ad-banner.js封装了广告加载逻辑,暴露adUnitId属性; - 页面层:在
pages/index/index.wxml中调用<ad-banner ad-unit-id="adunit-xxx"></ad-banner>; - 配置层:
utils/config.js中定义AD_CONFIG = { home: 'adunit-xxx', my: 'adunit-yyy' }。
你要做的只是:
- 在微信公众号后台开通流量主,获取你的
adunit-xxxxxx; - 修改
utils/config.js里的对应键值; - 确保
app.json中"permission"字段已声明"scope.advertisements": {"desc": "用于展示广告"}。
注意:
ad-unit-id必须是字符串类型,不能带空格或特殊字符。若填错,真机调试时控制台会报[Ad] ad unit id is invalid,但开发工具里可能静默失败。
2.3 “独立运行版”的技术实质:如何绕过微信后台审核直接部署
所谓“独立运行”,指该小程序不依赖微信小程序管理后台的云开发环境或插件市场,所有静态资源可托管在任意HTTP服务器(Nginx/Apache),动态接口由你自己的后端提供。关键证据在utils/request.js:
// utils/request.js const BASE_URL = 'https://your-api-domain.com/api'; // ← 这里就是你改的地方! function request(options) { return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + options.url, method: options.method || 'GET', data: options.data || {}, header: { 'Content-Type': 'application/json', 'Authorization': wx.getStorageSync('token') || '' // 支持token鉴权 }, success: (res) => { if (res.statusCode === 200) resolve(res.data); else reject(new Error(`HTTP ${res.statusCode}`)); }, fail: reject }); }); }只要把BASE_URL指向你自己的域名,并确保该域名已在微信后台配置为“request合法域名”,它就能完全脱离微信生态独立运转。某公司曾用此方案将WiFi小程序嵌入自有APP的WebView中,仅需改一行BASE_URL并注入wx对象模拟器。
3. 关键功能实操:从扫码连网到WiFi码导出,5步跑通核心业务流
现在我们动手验证这套源码是否真能用。以下步骤基于微信开发者工具(Stable 1.06.2308010)实测,全程无需真机,但需开启“不校验合法域名”。
3.1 初始化与环境配置:3分钟完成本地启动
- 下载源码解压后,打开微信开发者工具,选择「小程序项目」→「从本地文件夹导入」;
- 在
project.config.json中确认appid字段为占位符(如"wx1234567890abcdef"),不要填你的真实appid,否则无法预览; - 修改
utils/config.js中的API_BASE_URL为你本地后端地址(如http://localhost:3000/api); - 启动本地Mock服务(推荐使用
json-server):
# 安装 npm install -g json-server # 创建mock数据(db.json) { "hotspots": [ { "id": 1, "name": "咖啡馆WiFi", "ssid": "cafe-wifi", "password": "12345678", "status": "online" } ], "announcements": [ { "id": 1, "title": "系统升级通知", "content": "本周五晚22:00维护", "icon": "icon-bell" } ] } # 启动服务 json-server --watch db.json --port 3000- 点击开发者工具「编译」按钮,看到首页正常渲染即成功。
逻辑说明:
json-server在此扮演后端角色,返回符合源码预期的数据结构。pages/index/index.js中onLoad会调用getHotspots(),该方法最终执行request({url: '/hotspots'}),从而拉取Mock数据。这是验证接口层是否通畅的第一步。
3.2 扫码连网功能:如何让手机真正连上WiFi?
源码中扫码逻辑位于pages/index/index.js的scanWiFiCode方法:
scanWiFiCode() { wx.scanCode({ onlyFromCamera: true, success: (res) => { // res.result 格式示例:WIFI:T:WPA;S:cafe-wifi;P:12345678;; const wifiInfo = this.parseWiFiQR(res.result); if (wifiInfo) { wx.addPhoneContact({ firstName: wifiInfo.ssid, description: `密码:${wifiInfo.password}`, success: () => wx.showToast({ title: '已保存,点击即可连接' }) }); } else { wx.showToast({ title: '二维码格式错误', icon: 'none' }); } } }); }, parseWiFiQR(qrStr) { const match = qrStr.match(/WIFI:T:(\w+);S:([^;]+);P:([^;]+);/); return match ? { ssid: match[2], password: match[3], type: match[1] } : null; }这段代码的关键在于:它不直接调用wx.connectWifi(因该API需用户手动授权且兼容性差),而是生成联系人卡片,引导用户点击保存后手动连接。这是当前最稳定、兼容iOS/Android的方案。测试时,用另一台手机生成WiFi二维码(格式:WIFI:T:WPA;S:your_ssid;P:your_password;;),对准摄像头扫描即可触发保存。
3.3 后台管理页权限控制:如何限制非管理员访问/admin页面?
源码中pages/admin/index.js开头有段硬编码判断:
onLoad() { const userInfo = wx.getStorageSync('userInfo'); if (!userInfo || userInfo.role !== 'admin') { wx.showToast({ title: '无权限访问', icon: 'none' }); setTimeout(() => wx.navigateBack(), 1500); } }这意味着你需要:
- 在登录流程中(
pages/login/login.js),将用户角色写入wx.setStorageSync('userInfo', { role: 'admin' }); - 或在
app.js的onLaunch中,通过wx.checkSession校验登录态后动态设置。
参数说明:
role字段值必须为字符串'admin',大小写敏感。若你后端返回的是is_admin: true,需在存储前转换:{ role: res.data.is_admin ? 'admin' : 'user' }。
3.4 WiFi码导出功能:体验版与正式版的区别在哪?
更新项#5提到“可选择版本(体验版或正式版)”,其实现逻辑在pages/admin/export/index.js:
exportWiFiCode() { const version = this.data.version; // 'trial' or 'release' const ssid = this.data.ssid; const password = this.data.password; // 体验版:生成带水印的二维码,且SSID末尾加"-trial" const finalSSID = version === 'trial' ? `${ssid}-trial` : ssid; // 调用utils/qrcode.js生成base64图片 const qrcodeBase64 = generateQRCode( `WIFI:T:WPA;S:${finalSSID};P:${password};;`, { width: 300, height: 300, watermark: version === 'trial' } ); this.setData({ qrcode: qrcodeBase64 }); }导出时,体验版二维码会在右下角叠加半透明文字“体验版”,且SSID自动追加-trial后缀,避免误连。正式版则无水印、无后缀。这个细节体现了作者对交付场景的理解——客户试用时不想影响真实网络。
3.5 平台统计看板:如何接入你自己的数据?
pages/admin/stat/index.js中,统计图表数据来自/api/stat/platform接口。源码使用echarts-for-weixin(已打包进static/echarts.js),但初始化逻辑极简:
initChart() { const query = wx.createSelectorQuery(); query.select('#chart').fields({ node: true, size: true }).exec((res) => { const canvas = res[0].node; const rect = res[0].node.getBoundingClientRect(); const dpr = wx.getSystemInfoSync().pixelRatio; const ctx = canvas.getContext('2d'); ctx.scale(dpr, dpr); const chart = echarts.init(canvas, null, { renderer: 'canvas', devicePixelRatio: dpr }); chart.setOption(this.getOption()); // getOption()返回ECharts配置 }); }你只需重写getOption()方法,返回符合ECharts 4.x规范的配置对象。例如按日活统计:
getOption() { return { tooltip: { trigger: 'axis' }, xAxis: { type: 'category', data: ['周一','周二','周三'] }, yAxis: { type: 'value' }, series: [{ name: '日活', type: 'line', data: [120, 200, 150] }] }; }注意:
echarts-for-weixin不支持dataset或geo等高级特性,但足够应付WiFi类项目的常规统计需求。
4. 避坑指南:5个真实踩过的坑与血泪解决方案
这套源码虽小,但在实际部署中仍有不少隐蔽雷区。以下是我在某高校实验室带学生做模拟项目X时,连续3天调试才定位的典型问题,按「现象 → 原因 → 解决」整理:
4.1 现象:真机扫码后白屏,开发工具却正常
原因:app.js中onLaunch调用了wx.getSystemInfoSync()获取设备信息,但部分低端Android机型(如Android 6.0)该API同步调用会阻塞渲染线程,导致页面白屏。
解决:将同步调用改为异步,并加try-catch兜底:
// ❌ 错误写法 const systemInfo = wx.getSystemInfoSync(); // ✅ 正确写法 wx.getSystemInfo({ success: (res) => { app.globalData.systemInfo = res; }, fail: () => { app.globalData.systemInfo = { platform: 'unknown', pixelRatio: 1 }; } });4.2 现象:后台公告列表图标不显示,只显示方块
原因:style/app.css中图标字体路径写死为/static/fonts/iconfont.woff,但源码包里实际字体文件在static/fonts/iconfont.ttf,且未提供WOFF格式。
解决:
- 将
static/fonts/iconfont.ttf重命名为iconfont.woff; - 或修改
app.css中@font-face的src属性,指向.ttf文件:
@font-face { font-family: 'iconfont'; src: url('/static/fonts/iconfont.ttf') format('truetype'); }4.3 现象:“清除缓存”按钮点击无反应,控制台无报错
原因:pages/admin/index.js中clearCache方法调用了wx.clearStorage(),但未处理Promise返回值,且缺少catch。当用户拒绝授权时,Promise被reject但未捕获,导致后续逻辑中断。
解决:补全Promise链并提示用户:
clearCache() { wx.clearStorage() .then(() => { wx.showToast({ title: '缓存已清空' }); this.setData({ cacheSize: 0 }); }) .catch((err) => { wx.showToast({ title: '清除失败,请检查授权', icon: 'none' }); console.error('clearStorage error:', err); }); }4.4 现象:流量主广告在iOS真机上不展示,安卓正常
原因:iOS微信客户端对广告组件有更严格的校验,要求ad-unit-id必须与当前小程序的AppID在同一个微信公众号主体下绑定。源码中ad-unit-id为占位符,未做环境判断。
解决:在components/ad-banner/ad-banner.js中增加平台判断:
const systemInfo = wx.getSystemInfoSync(); const isIOS = /ios/i.test(systemInfo.system); Component({ properties: { adUnitId: { type: String, value: isIOS ? 'adunit-ios-real-id' : 'adunit-android-real-id' } } });4.5 现象:上传小程序至微信后台时提示“代码包大小超过2MB”
原因:static/目录下存在未压缩的原始图片(如logo.png为5MB),且project.config.json未开启代码压缩。
解决:
- 用TinyPNG批量压缩
static/下所有图片; - 在开发者工具「详情」→「本地设置」中勾选「代码压缩」;
- 删除
node_modules/(源码本就不该包含它,但网传包里意外混入)。
最终包体积可从2.8MB降至1.3MB,满足微信2MB限制。
5. 进阶技巧:3个让交付更稳、迭代更快的实战习惯
做完基础功能验证,真正决定项目成败的是交付质量和后续维护效率。这里分享我在多个WiFi类项目中沉淀下来的3个具体技巧,每个都经过真实场景检验。
5.1 接口Mock自动化:用Postman Collection一键生成json-server数据
每次改接口字段都要手动编辑db.json?太低效。我习惯用Postman导出Collection为JSON,再用脚本转成json-server可识别的格式。例如,你有一个/api/hotspots接口返回:
{ "data": [ { "id": 1, "name": "咖啡馆", "ssid": "cafe", "password": "123" } ], "total": 1 }Postman导出的Collection里,response.body是完整JSON。我写了个Python脚本(gen-mock.py)自动提取data数组并写入db.json:
import json import sys # 读取Postman导出的collection.json with open(sys.argv[1], 'r', encoding='utf-8') as f: collection = json.load(f) # 提取第一个请求的响应体 responses = collection['item'][0]['event'][0]['script']['exec'] # 实际中需解析JS代码,此处简化为假设已知data结构 mock_data = { "hotspots": [ { "id": 1, "name": "咖啡馆", "ssid": "cafe", "password": "123", "status": "online" } ] } with open('db.json', 'w', encoding='utf-8') as f: json.dump(mock_data, f, ensure_ascii=False, indent=2)运行python gen-mock.py collection.json,立刻生成可用Mock数据。从此接口联调不再卡在“等后端给数据”。
5.2 样式变更原子化:用CSS Custom Properties管理主题色与断点
app.css里大量使用#1aad19这种硬编码色值,一旦要换主题,得全局搜索替换。我强制团队改用CSS变量:
:root { --primary-color: #1aad19; --primary-color-dark: #0a8b0a; --bg-color: #f5f5f5; --breakpoint-sm: 576px; --breakpoint-md: 768px; } .am-btn-primary { background-color: var(--primary-color); border-color: var(--primary-color-dark); } @media (max-width: var(--breakpoint-sm)) { .am-list-item { padding: 10px; } }这样,换主题只需改:root里的变量值,所有组件自动响应。更重要的是,它让app.css变成一份“配置文档”,而非“魔法代码”。
5.3 版本发布防呆:用Git Hooks校验app.json与project.config.json一致性
交付前最怕app.json里写了"debug": true,结果发到线上。我用pre-commit钩子自动检查:
# .husky/pre-commit #!/bin/sh set -e # 检查app.json是否含debug字段 if grep -q '"debug": *true' app.json; then echo "❌ 错误:app.json中存在debug: true,请设为false" exit 1 fi # 检查project.config.json的appid是否为占位符 if ! grep -q '"appid": *"wx[0-9a-f]\{16\}"' project.config.json; then echo "❌ 错误:project.config.json的appid未设为占位符(如wx1234567890abcdef)" exit 1 fi每次git commit前自动执行,杜绝人为失误。某公司因此避免了一次线上白屏事故——因debug: true导致console.log在生产环境暴露出敏感API地址。
从那以后我每次新建小程序项目,都强制走一遍这三步:用Postman生成Mock、用CSS变量管样式、用Git Hooks卡发布。不是为了炫技,而是让交付像拧螺丝一样确定——拧紧了,就不会松。希望帮到你。
本文还有配套的精品资源,点击获取