简介一份面向微信小程序开发学习者的线上儿童摄影店小程序完整项目适用于计算机相关专业学生的毕设、课程设计或初期项目演示。项目围绕儿童摄影门店场景实现商品与服务的分类展示、店面环境介绍、预约与信息浏览等模块代码结构清晰包含前后端交互逻辑与页面配置文件。资源共533个文件以js逻辑脚本、wxml页面结构、wxss样式、json配置及png图片素材为主另有docx使用手册和md说明文件压缩包约4.73MB整体轻量易部署。源码内封装了数据库工具类、页面辅助函数与表单校验等通用模块适合在已有基础上二次扩展。目前已有58人浏览学习适合对小程序开发有一定基础、希望参考真实业务案例的读者。配套文档覆盖安装运行指引、功能说明及界面截图可帮助快速跑通项目并为答辩或课设提供完整演示素材。1. 为什么一家儿童摄影店需要自己的小程序儿童摄影店有个绕不开的尴尬客片就是最好的商品但又不敢把客片全量丢到美团点评上——价格被平台压到底客片还会被同行直接截图当样片。所以越来越多的店主开始找微信小程序-线上儿童摄影店小程序这类带完整源代码的模板把套餐商品、店面环境全塞进一个微信里直接打开的小程序。客人从朋友圈点进来就能看环境、看客片、填预约不靠第三方平台抽佣数据也握在自己手里。这套方案对店主是一个能反复更新的宣传页对开发者是一个可直接二次开发的微信小程序项目实例原生框架加源代码、文档说明、功能截图、使用手册四件套改图片换价格就能给下一家店交付。2. 源码包拆解四类交付物分工页面目录与数据文件先摸清拿到项目包的第一件事不是急着打开微信开发者工具而是先把压缩包拆开看清里面到底有什么。这类标题里承诺了源代码、文档说明、功能截图、使用手册四样东西它们的读者和用途完全不一样源代码是给开发者改的文档说明是部署阶段的路线图功能截图是验收清单使用手册是最后交到店主手里的操作指南。四者分不清后面大概率会出现“代码跑通但店主不会用”或者“页面改完了跟截图对不上”的返工。2.1 页面目录儿童摄影店的六个页面和它们的职责一个小程序项目的骨架全在 app.json 的 pages 数组里。儿童摄影店模板一般会拆出六个页面首页、套餐列表、套餐详情、店面环境、预约、我的预约。首页串起整个店的卖点套餐列表负责商品转化详情页是说服用户下单的主力店面环境页解决信任问题预约页是转化收口我的预约让用户回访时能看到自己的记录。{ pages: [ pages/index/index, pages/product/product, pages/detail/detail, pages/environment/environment, pages/appointment/appointment, pages/mine/mine ], window: { navigationBarTitleText: XX儿童摄影, navigationBarBackgroundColor: #FFF8F0, navigationBarTextStyle: black } }pages 数组里排第一位的页面就是小程序启动时第一个打开的页面所以 index 必须放第一项。新增页面不能只建文件夹必须手动在 app.json 里注册否则开发者工具直接报错 page not found。window 节点里配置的是全局导航栏样式摄影店这类面向宝妈群体的店铺导航栏一般用暖色底加深色字比默认的白底黑字更有辨识度。六个页面之间的跳转关系也有约定列表页跳详情页用 wx.navigateTo详情页返回用 wx.navigateBack首页跳店面环境同样用 wx.navigateTo。模板里如果用 wx.redirectTo 跳主页返回链会断真机上体验很差这是拿到代码后要检查的第一处。2.2 四类交付物怎么对账源代码、文档、截图、手册各看什么源代码是交付的核心。文档说明要重点看三块环境要求、部署步骤、配置项。环境要求一般写的是微信开发者工具的版本号和基础库版本先对照自己的工具版本版本太老会跑不起来太新可能触发模板没适配的 API 变更。部署步骤里如果出现“申请 AppID”“配置合法域名”“上传体验版”这三步说明文档是完整的缺任何一步上线时都会卡住。功能截图的作用是验收对照。我一般会把截图按页面名归档改完代码以后逐页对比轮播图个数对不对、套餐卡片的文案排版是否一致、预约表单字段有没有少。要留个心眼截图和源码很可能不是同一版本遇到截图与代码行为不一致时一律以源码为准截图只当参考。使用手册是四件套里唯一写给非技术读者看的。合格的店铺使用手册应该包含怎么在小程序后台换轮播图、怎么改套餐价格、怎么查预约记录、怎么联系开发方。如果手册里全是 npm install、git clone 这种命令那它写错了对象——店主需要的是操作截图加按钮位置描述不是命令行。交付物读者核心用途最容易犯的错源代码开发者二次开发与部署让店主直接打开源码文档说明开发者环境与部署指引跳过文档直接跑环境问题返工功能截图开发者/验收人页面验收对照截图版本和源码不一致仍当真使用手册店主/运营自主更新内容把手册写成命令行教程2.3 店铺数据文件套餐、轮播图、门店信息都收敛在一个 JS 里模板为了让你改起来省事通常会做一个数据文件把店铺名、电话、地址、营业时间、轮播图、套餐列表集中放在一起。这个设计是刻意的运营人员只需要维护一个文件就能更新整个小程序的展示内容不需要动任何页面代码。// data/store.js 店铺基础数据 module.exports { storeName: XX儿童摄影, phone: 13800000000, address: XX市XX区XX路XX号, businessHours: 09:00 - 20:00, banners: [ /images/banners/banner-1.jpg, /images/banners/banner-2.jpg, /images/banners/banner-3.jpg ], packages: [ { id: pkg_100, name: 新生儿上门照, price: 999, originalPrice: 1399, cover: /images/packages/newborn.jpg, features: [上门拍摄, 精修12张, 底片全送] } ] }注意这里所有的图片路径都是相对项目根目录的写法以 / 开头。微信小程序里不能用本地磁盘绝对路径也不能在 JS 里 require 一张图片文件图片必须放在项目目录内通过相对路径引用。price 和 originalPrice 建议存数字而不是字符串后面做价格计算、划线价的展示逻辑时不用再 parseInt少一类类型转换的 bug。数据文件里套餐的 id 是页面跳转和预约记录关联的关键字段不要用中文名当 id也不要留空。模板里如果看到用数组下标当 id 的做法建议改成稳定的字符串 id——下标会随着运营删改套餐而漂移预约记录一旦关联错套餐售后解释成本很高。3. 在微信开发者工具里跑通模板AppID、导入、数据替换三步走对这个标题感兴趣的读者多数不是来看概念的而是想快点看到这个小程序长什么样、能不能改。这一章就把跑通的路径讲完从注册 AppID 到把 Demo 数据换成真实店铺数据三步走完模板就能以你的店的名义在模拟器里运行。3.1 注册 AppID 与导入项目测试号和正式号的取舍微信小程序开发必须有一个 AppID 才能真机预览和发布。在微信公众平台注册小程序账号主体类型选企业或个体工商户完成后在“开发管理-开发设置”里能看到自己的 AppID。模板项目打开时开发者工具会问你要 AppID这里可以填自己的也可以选“测试号”。我的建议是直接用正式 AppID。测试号能本地预览但上传代码、真机调试、调用 wx.request 请求线上接口都会受限等你改完数据再回来换 AppID还得重新检查一遍所有配置纯属给自己挖坑。换 AppID 不是改 project.config.json 里一个字段就完事页面里如果有写死的 appid 引用也要一并换。导入项目的路径选源码包解压后的根目录也就是包含 app.json 的那一层。工具会识别出这是原生小程序项目并生成 project.config.json。如果导入时报“非小程序项目目录”多半是路径选深了一层选到了 pages 或者其他子目录。3.2 微信小程序项目配置三件套appid、urlCheck、基础库版本导入后打开 project.config.json重点看三个配置。appid 确认是你的正式 AppIDsetting.urlCheck 决定开发时要不要校验合法域名libVersion 或工具详情里的调试基础库版本决定了模板里用到的高版本 API 能不能跑。{ appid: wx1234567890abcdef, projectname: children-photo-store, setting: { urlCheck: false, es6: true, minified: true } }urlCheck 是开发期的后悔药。把它设为 false意味着本地开发时微信不检查请求域名是否在后台白名单里接口随便请求方便调通逻辑。但发布前必须改回 true——否则真机上用户看到的是一排 request:fail而你在开发者工具里永远复现不了因为工具默认帮你跳过了校验。es6 必须开模板代码里大概率用了箭头函数、模板字符串、async/await不开会直接在编译阶段报语法错。minified 是压缩代码上线前开着能省一点包体。补充一个常见翻车点修改 project.config.json 后开发者工具有时不会热重载配置。改完以后手动点“编译”或者重启工具否则你改的 appid 看起来改了实际上编译用的还是缓存里那一份。3.3 替换店铺数据三处必改和两处可留跑通之后就是往模板里填自己的内容。按照交付顺序有三处是必须改的两处可以暂时留着。必改的app.json 里的 navigationBarTitleText把它从 Demo 店名改成真实店名data/store.js 里的门店基础信息包括电话、地址、营业时间images 目录下的图片文件套餐封面、轮播图、店面环境图全部换成实拍图。这里特别提醒换图时保持主文件名不变直接覆盖同名文件是最省事的做法。# 图片替换的目录约定以 project 根目录为基准 # 轮播图 - images/banners/建议 750x400 像素单张 300KB # 套餐封面 - images/packages/建议 750x750 正方形 # 店面环境 - images/store/建议 1280 宽单张 400KB # 替换后重新编译模拟器有缓存点“编译”而不是“刷新”提示换了文件名就要同步改数据文件里的路径漏一处就是一个裂图。保持同名覆盖能避开这类低级故障。两处可以先留着套餐文案的句式结构比如“精修12张”“底片全送”这种卖点列表的写法用你自己的产品替换内容即可结构不需要重写预约表单的字段设计家长姓名、手机号、宝宝月龄、日期、时段这套字段对绝大多数儿童摄影店都适用急着上线就别动它等跑起来再按需增删。数据替换完先在模拟器里完整走一遍首页轮播、套餐详情、店面环境、预约提交。走完这一遍模板的本地运行就算验收了。真机预览时记得把开发者工具的“不校验合法域名”关掉用真实网络环境再测一遍避免把开发期的便利带到生产环境。4. 三个核心功能怎么落代码套餐页、环境页、预约页的参数与实现这一章进入代码层面。儿童摄影店小程序的核心业务就三块把套餐和服务讲清楚把门店环境秀出来把有意向的客户变成预约记录。对应到模板里就是三个页面每一块的实现都有几个参数是必须吃透的。4.1 套餐列表页lazy-load、widthFix 和图片防裂兜底儿童摄影店的图片密度比普通电商还高详情页挂十几张客片很正常。原生 image 组件的默认行为是进入页面立即加载所有图片网络差的时候低端安卓机直接白屏这不是玄学是图片并发请求把 WebView 压垮了。处理手法就三招lazy-load 让图片滚动到视口附近再加载modewidthFix 让高度按图片比例自动撑开避免布局抖动每个 image 加 binderror 做兜底图片文件损坏或路径错了时换占位图。!-- pages/product/product.wxml 套餐列表项 -- view classpkg-card wx:for{{packages}} wx:keyid image classpkg-cover src{{item.cover}} modewidthFix lazy-load >// pages/product/product.js Page({ data: { packages: [] }, onLoad() { const store require(../../data/store) this.setData({ packages: store.packages }) }, onImgError(e) { const idx e.currentTarget.dataset.index this.setData({ [packages[ idx ].cover]: /images/placeholder.jpg }) } })这里有个容易犯的错binderror 事件里直接改 e.currentTarget.src 是不会生效的image 组件的 src 是数据驱动的必须 setData 回来。上面代码用>!-- pages/environment/environment.wxml -- swiper indicator-dots indicator-colorrgba(255,255,255,0.4) indicator-active-color#FF8A65 autoplay interval4000 duration500 circular swiper-item wx:for{{envImages}} wx:key*this image src{{item}} modeaspectFill lazy-load / /swiper-item /swiperindicator-dots 是底部的小圆点指示器颜色要跟页面的主色调搭配默认灰色在深色照片上几乎看不见。modeaspectFill 会把图片等比缩放并居中裁剪填满整个容器适合轮播图如果换成 aspectFit图是完整显示了但上下会露出黑边店面环境这种满屏展示的场景不建议用。environment 页的数据源同样建议收敛到 data/store.js 里店主自己传图时会方便很多。图片体积是店面环境页最容易爆的点手机拍的现场照片一张五六兆直接塞进项目小程序主包 2MB 限制先把你卡住。我一般会在传图前统一压一遍宽度压到 1280JPEG 质量 70%单张控制在 300KB 到 400KB。压缩工具随意关键是建立习惯——每次运营给图都先压再进包不然轮播图加载慢家长划两下没看到图就退出了转化链直接断在信任环节。4.3 预约表单手机号校验、picker 日期与 wx.request 提交预约页是全项目转化率最高的一页也是最容易出 bug 的一页。表单字段模板里基本定好了家长姓名、手机号、宝宝月龄、预约日期、预约时段、备注。手机号校验是重灾区只做空判断等于没做后台会收到一堆“138”开头的脏数据。// pages/appointment/appointment.js Page({ data: { phone: , dateIndex: 0, dates: [2026-03-01, 2026-03-02, 2026-03-03], timeSlots: [上午 09:00-12:00, 下午 14:00-17:00], submitted: false }, onPhoneInput(e) { this.setData({ phone: e.detail.value }) }, submit() { const phone this.data.phone.trim() if (!/^1[3-9]\d{9}$/.test(phone)) { wx.showToast({ title: 请填写正确的手机号, icon: none }) return } wx.showLoading({ title: 提交中 }) wx.request({ url: https://your-domain.com/api/appointment, method: POST, data: { phone, date: this.data.dates[this.data.dateIndex], slot: this.data.timeSlots[this.data.slotIndex] }, success: (res) { wx.hideLoading() if (res.statusCode 200) { this.setData({ submitted: true }) } else { wx.showToast({ title: 提交失败请稍后重试, icon: none }) } }, fail: () { wx.hideLoading() wx.showToast({ title: 网络异常请检查网络, icon: none }) } }) } })正则 ^1[3-9]\d{9}$ 是目前最常用的手机号校验规则覆盖 13 到 19 号段它校验的是“是不是 11 位手机号”而不是“这个号码存在不存在”后者需要短信验证码模板一般不涉及。日期选择我用 picker 加索引数组不用 input typedate因为原生 date 组件在 iOS 和安卓上的弹层样式不一样模板要兼容两端picker 最稳。注意wx.request 的 success 只表示“请求有响应”404、500 也会走 successfail 只在网络层彻底失败时触发。所以业务成功与否要看 statusCode 是不是 200。如果模板没有后端只是把预约记录存到本地缓存把提交逻辑换成 wx.setStorageSync 即可但同样要保留表单校验这一步脏数据存进本地也一样麻烦。另外这类店铺模板一般不带在线支付儿童摄影是到店服务预约后到店选片付款是行业常态不用为了支付卡住上线。如果以后要接微信支付需要企业主体并通过微信支付类目审核个体户主体基本做不了这条要提前跟店主讲清楚。生产环境建议把 wx.request 再封装一层到 utils/request.js统一处理 baseURL、statusCode 和错误提示预约页只关心业务字段模板自带的裸请求封装不复杂但收益很直接。5. 上线前后要排查的 5 个高发坑图片域名、刘海屏、肖像权、接口校验与日期排序下面五条不是从文档里抄出来的是这类店铺小程序交付时最容易反复出现的问题。每一条都按“现象、原因、解决”来写可以直接当排查清单用。5.1 真机加载不出图片http 协议与 downloadFile 域名白名单现象模拟器里图片一切正常点了真机预览套餐图和店面图一片空白页面结构还在就是图不显示。原因常见两种。其一图片地址还是 http:// 开头微信真机环境强制要求 https直接拦截其二模板如果走了 wx.downloadFile 下载图片再展示图片域名没在小程序后台配 downloadFile 合法域名下载阶段就直接 fail自然没有图片可显示。开发者工具默认跳过校验所以模拟器里看不出来。解决把所有图片资源换成 https并在微信公众平台“开发管理-服务器域名”里把图片所在域名加到 downloadFile 合法域名。注意这个列表只填域名不带 https:// 前缀也不带路径域名还得完成备案。图片请求走的是 downloadFile 域名而不是 request 域名这两个列表经常被人搞混。5.2 iPhone 刘海屏顶栏遮挡用胶囊按钮反推微信小程序导航栏高度现象安卓上页面正常iPhone 上自定义导航栏和右上角的胶囊按钮重叠页面内容有一部分被状态栏和刘海挡住。原因模板里导航栏高度写死了常见的是 padding-top: 64px。这个值在 iPhone 8 以下的机型够用但刘海屏机型的 statusBarHeight 更高胶囊按钮的位置也随机型变化写死必然翻车。解决动态计算。用 wx.getSystemInfoSync 拿状态栏高度用 wx.getMenuButtonBoundingClientRect 拿胶囊按钮的位置和尺寸两者相减再换算就能得到当前机型真正的导航栏占位高度。// utils/menu.js 导航栏占位高度计算 function getNavHeight() { const sys wx.getSystemInfoSync() const menu wx.getMenuButtonBoundingClientRect() const statusBarHeight sys.statusBarHeight || 20 const navBarHeight (menu.top - statusBarHeight) * 2 menu.height return { statusBarHeight, navBarHeight } } module.exports { getNavHeight }这段代码的意义在于它每次启动时读取真机真实参数而不是依赖一份机型适配表。模板如果用了自定义导航栏这一处是优先级最高的修改项。微信小程序顶部导航栏高度这个话题在社区里被反复问就是因为每个新机型都可能再次打破旧的经验值。新版基础库推荐用 wx.getWindowInfo但 getSystemInfoSync 在现有模板里仍然通用兼容性最好。5.3 儿童肖像权客片不是想放就能放现象小程序上线后收到侵权投诉或提交审核时被打回理由大多是“页面使用的人物图片无法确认已获得授权”。原因儿童摄影店的客片拍的是真实客户的孩子肖像权归监护人所有。平台审核虽然不会逐张查验但一旦肖像权人主张权利轻则封页面重则下架这是这类项目特有的合规风险跟代码质量无关。解决拍摄协议里单独加一条“客户同意门店在宣传物料与小程序中使用其肖像”让监护人在拍摄前签字确认。交付时要跟店主当面确认这条已经落实。另外小程序发布前要在“用户隐私保护指引”里声明收集的信息类型预约表单收集了姓名、手机号、宝宝月龄属于个人信息不声明会被审核打回。这是血泪经验别等被投诉了才补。5.4 开发者工具通、真机全失败request 合法域名的三类配置现象预约表单在开发者工具里提交成功真机上一直转圈最后报 request:fail url not in domain list。原因开发者工具默认勾选了“不校验合法域名”本地怎么请求都通但真机强制校验。报错信息已经说得很明白——url 不在域名列表里。解决在小程序后台分别配置三类域名列表request 合法域名管 wx.requestuploadFile 合法域名管 wx.uploadFiledownloadFile 合法域名管 wx.downloadFile。这不是一个列表通吃三个列表独立生效。域名不能带端口默认 443 除外不能是 IP 地址必须 https 且备案。改完域名配置后真机上一般要等一两分钟生效不要刚改完就急着下结论“配置没用”。5.5 预约记录排序乱把日期时间存成时间戳现象“我的预约”列表里2 月 9 日的记录排在了 2 月 14 日后面同一天的时段也是乱的。原因模板把预约日期和时段拼成字符串存储比如 2026-02-14 加 上午。字符串排序按字典序2026-02-9 会排在 2026-02-14 前面因为字符 9 大于 1。数字和字符混排时这类问题特别隐蔽跨月还能蒙混过关跨年必现。解决存储时用时间戳而不是字符串。预约日期加时段先拼成 2026-02-14 10:00再用 Date.parse 转成时间戳存入展示时再格式化成用户能读的文本。如果后端接口返回的已经是字符串前端先转时间戳再排序不要拿原始字符串直接 sort。顺带注意 iOS 上 new Date(2026-02-14 10:00) 可能解析失败建议把空格换成 T即 2026-02-14T10:00兼容性和可读性都好一些。6. 进阶改造把模板项目换成你自己的骨架6.1 抽出组件套餐卡片只维护一份模板的套餐卡片通常在三处重复出现首页推荐位、套餐列表页、详情页相关推荐。改一次样式要动三个页面漏一个就样式不统一。我一般拿到代码后第一件事是把这种重复块抽成 Component。// components/pkg-card/pkg-card.json { component: true }// components/pkg-card/pkg-card.js Component({ properties: { pkg: { type: Object, value: {} } }, methods: { onTap() { wx.navigateTo({ url: /pages/detail/detail?id this.data.pkg.id }) } } })组件化之后套餐卡片的样式、跳转逻辑都收敛到一个文件里。新增字段时在 properties 里声明页面引用处只需要传入 pkg 对象。有朋友会问要不要干脆用 uniapp 开发一版跨端。单店展示加预约这类场景原生模板的改造成本远低于迁移跨端框架不必为了技术上的完整去动已经跑通的代码。6.2 品牌色收敛改主题不翻全页面模板默认的暖橙色适合大部分儿童摄影店但如果店主要求品牌色别去每个 wxml 里逐个改 class。WXSS 支持 CSS 自定义属性把主色调、辅助色收敛到 app.wxss 的 page 选择器里之后改主题只动一个文件。最后说一个交付习惯每次做完这类店铺小程序我都会让店主拿着使用手册自己走一遍“换轮播图、改套餐价格”的操作我在旁边只看不动手。能独立走完项目才算真正交付走不顺的地方就是手册要补的内容。代码总有下一个版本但店主学会自己更新内容你的售后工单能少一大半。这一条经验比任何组件封装都值钱希望帮到你。本文还有配套的精品资源点击获取