简介这是一份基于Uniapp开发的微商个人相册多端小程序源码面向需要快速搭建个人相册类小程序的开发者解决相册内容展示、分类管理与图片维护等常见需求。资源共228个文件、9.35MB以js、vue、json、wxml、wxss等前端逻辑与页面文件为主辅以png/jpg图片资源和sql数据脚本结构清晰。功能上首页相册分页展示列表页支持分类的增改与排序每个分类下可挂多个相册相册内图片支持小图/大图切换长按图片可删除或设为封面同时支持相册分享、管理员登录和联系客服等能力。已有294人学习下载。源码只需用HBuilderX导入修改小程序AppID及Uni-app应用标识即可调试发布既适合微商相册、个人作品展示等实际场景落地也可作为Uniapp多端项目开发的完整参考。1. Uniapp 开发的微商个人相册为什么值得单独做一套而不是套模板微商卖货的日常本质上是在朋友圈和微信对话里反复发图、发视频、发文案。个人相册不是朋友圈它承担的是「货架 内容沉淀 信任背书」三重角色客户点进来要能快速分类浏览、按标签找款、看实拍细节甚至直接联系下单。把这个场景做成小程序比公众号图文和 H5 都更顺手因为入口浅、分享方便、加载快。而用 Uniapp 来写核心诉求只有两个字多端。同一套源码编译成微信小程序、支付宝小程序、H5甚至打包成 Android/iOS App微商代理团队经常需要同时覆盖微信和支付宝两端Uniapp 是目前这种场景下投入产出比最高的方案没有之一。但要注意市面上的微商相册小程序源码不少真正能跑起来、能改、能上架的却不多。问题通常出在图片加载策略、多端 API 差异处理、以及分包的体积控制上。这篇就顺着 Uniapp 的语法和多端编译机制把一套完整的微商个人相册小程序源码拆开讲透从架构设计到具体代码实现再到打包发布和排错技巧全部落到可执行层面。2. 多端架构从零搭建Uniapp 项目结构与微商相册的关键目录划分2.1 为什么微商相册小程序特别看重页面结构和分包策略微商相册的内容形态很固定分类相册、商品详情、联系页、个人主页。但图片数量非常大代理商可能一次上传几百张实拍图这种场景下小程序的启动速度和页面切换流畅度直接决定客户会不会继续往下翻。Uniapp 打包成微信小程序时主包大小限制是 2MB整个小程序不能超过 20MB所以源码里的静态资源管理和分包配置决定了这款相册源码能不能真正落地运营。一个常见的做法是把商品详情页、图片预览页、联系页这三个核心业务页面放在主包把分类管理、素材上传、数据统计这些低频管理页面放到分包。因为客户浏览相册时访问的是主包里的页面启动时只需要加载主包首屏速度明显更快。而代理商自己管理和上传素材时多等一会儿分包加载是无感知的。2.2 源码目录结构按多端和业务维度双向拆分用 Uniapp 写源码目录结构是项目的骨架。微商相册小程序的推荐结构长这样├── pages // 主包页面 │ ├── index // 相册首页瀑布流展示 │ ├── category // 分类相册列表页 │ ├── detail // 单组相册详情图片九宫格/大图预览 │ └── contact // 联系页展示二维码/微信号/手机号 ├── pages_manage // 分包管理端页面 │ ├── upload // 图片上传与编辑 │ ├── classify // 分类管理新增/排序/隐藏 │ └── stats // 访问数据统计 ├── static // 静态资源logo、占位图、iconfont ├── components // 自定义组件 │ ├── img-lazy // 图片懒加载组件 │ └── tab-bar // 自定义底部导航 ├── utils // 工具函数 │ ├── request.js // 封装 uni.request兼容多端 │ ├── oss.js // 阿里云 OSS 直传签名逻辑 │ └── share.js // 分享参数统一处理 ├── store // Vuex 状态管理用户信息、分类缓存 ├── App.vue ├── main.js └── manifest.json // 多端配置appid、权限声明、SDK配置分包配置写在pages.json里这是 Uniapp 和原生小程序写法最接近的地方。核心区别在于Uniapp 的pages.json同时控制页面路由和导航栏样式而且是多端通用的。下面这段配置把管理端放进了分包同时给主包页面配置了微信小程序的自定义导航栏高度兼容{ pages: [ { path: pages/index/index, style: { navigationStyle: custom, enablePullDownRefresh: true } }, { path: pages/detail/detail, style: { navigationBarTitleText: 相册详情 } } ], subPackages: [ { root: pages_manage, pages: [ { path: upload, style: { navigationBarTitleText: 上传素材 } } ] } ], preloadRule: { pages/index/index: { network: all, packages: [pages_manage] } } }这里的preloadRule是微信小程序特有的分包预加载配置含义是客户进入相册首页后空闲时间就提前加载管理分包。因为pages_manage里的上传页面对应的是代理商自己的操作但预加载可以让代理商后续点击上传时秒开。2.3 manifest.json 的多端适配appid、权限和 SDK 差一个都不能上架Uniapp 的跨端能力不是自动的需要配置manifest.json。微商相册小程序涉及的核心配置有以下几项配置项微信小程序支付宝小程序H5应用标识mp-weixin.appidmp-alipay.appid无图片上传域名downloadFile合法域名my.uploadFile白名单无跨域限制需 CORS用户授权uni.loginuni.getUserProfilemy.getAuthCode无分享能力uni.share需配置onShareAppMessagemy.showSharePanelWeb 分享这里容易踩坑的地方在域名白名单。微信小程序要求所有请求和下载域名为 HTTPS 且在后台配置过白名单支付宝小程序则要求my.uploadFile的目标域名也必须在支付宝开放平台后台配置。用源码时不要直接搜代码里的域名然后本地跑先确认你的后端接口域名和 OSS 域名是否已经在对应平台完成配置。3. 相册核心功能与源码实现从图片懒加载到多端兼容3.1 瀑布流相册的图片加载方案微商相册的首页是展示核心图片多且尺寸不一直接image标签渲染会白屏很久。关键在两点懒加载和图片裁剪参数。Uniapp 的image组件自带lazy-load属性但它的生效条件是页面滚动到图片附近才加载基础库较低的微信版本上表现不稳定。另一个做法是自封装一个图片懒加载组件配合IntersectionObserver在 H5 和 App 端做兼容。下面这段是components/img-lazy/img-lazy.vue的核心代码用 Uniapp 的uni.createIntersectionObserver实现多端兼容的懒加载template view classimg-lazy-wrap image v-ifisShow :srcrealSrc :modemode clickpreview(realSrc) / view v-else classimg-lazy-placeholder text加载中/text /view /view /template script export default { name: ImgLazy, props: { src: { type: String, required: true }, mode: { type: String, default: aspectFill } }, data() { return { isShow: false, realSrc: } }, mounted() { // 微信小程序和 App 端使用 IntersectionObserver // H5 端因为兼容性问题直接设为已显示更稳 // #ifndef H5 this.createObserver() // #endif // #ifdef H5 this.isShow true this.realSrc this.src // #endif }, methods: { createObserver() { const observer uni.createIntersectionObserver(this) observer.relativeToViewport({ bottom: 50 }).observe(.img-lazy-wrap, (res) { if (res.intersectionRatio 0 !this.isShow) { this.isShow true this.realSrc this.src observer.disconnect() } }) }, preview(src) { const urls this.previewList || [src] uni.previewImage({ current: src, urls }) } } } /scriptcreateIntersectionObserver是微信小程序原生的能力Uniapp 把它封装成了uni.createIntersectionObserver。这里有个细节relativeToViewport({ bottom: 50 })表示视口底部向下偏移 50px 后进入这个范围的元素才触发加载相当于给图片加了一个预加载缓冲区用户还没滑到图片就已经开始加载了滚动时无白屏感。#ifdef和#ifndef就是 Uniapp 的条件编译注释小程序的写法在 H5 端可能会报错所以做了分端处理。3.2 图片压缩和缩略图策略实拍图不能直接拿原图渲染微商相册的痛点在于实拍图一张就 3~6MB如果直接渲染微信小程序的image组件会崩溃iOS 上也会出现内存警告。更现实的问题是流量成本客户用 4G 看相册一张 5MB 的图加载 10 秒这体验根本留不住人。所以源码里一定会有图片处理服务器的配置最常见的是阿里云 OSS 搭配图片处理参数。假设存储路径为https://your-bucket.oss-cn-hangzhou.aliyuncs.com/goods/2024/xxx.jpg渲染缩略图时在 URL 后面追加?x-oss-processimage/resize,w_400,limit_0/quality,q_70这个参数的含义是将图片等比缩放到宽度 400px不会放大原图同时压缩到 70% 质量。在列表页用w_400在详情页大图预览时用w_1200。但uni.previewImage打开大图时传入的 URL 必须是原图 URL否则客户保存下来的图片是压缩过的不利于二次传播。代码里对这种情况的处理是src存原图 URL展示时动态拼接缩略图参数。看这段utils/oss.js的代码// utils/oss.js export function getThumbUrl(url, width 400) { // 兼容不同 OSS 服务商的裁剪参数 // 阿里云 OSS 直接拼 x-oss-process // 腾讯云 COS 用 imageMogr2需判断域名 if (!url) return if (url.indexOf(aliyuncs.com) -1) { return ${url}?x-oss-processimage/resize,w_${width},limit_0/quality,q_70 } if (url.indexOf(myqcloud.com) -1) { return ${url}?imageMogr2/thumbnail/!${width}p/quality/70 } return url }拼缩略图 URL 是最推荐的方案原因图片文件本身不用额外复制存储CDN 节点直接处理并缓存加载速度比单独传缩略图文件更快。唯一要注意的坑是limit_0它的作用是「只缩小不放大」不加这个参数的话如果图片本身小于 400pxOSS 会把图放大导致实拍细节模糊。3.3 多端分享机制微信好友分享与 App 端打开的区别微商相册的获客路径主要靠分享而且分享的不只是小程序名片更多是「某一组商品相册」的详情页。不同端的分享 API 不同但 Uniapp 中统一用onShareAppMessage来处理// pages/detail/detail.vue import { getThumbUrl } from /utils/oss.js export default { data() { return { albumId: , cover: , title: } }, onLoad(options) { // 深链参数从分享卡片点进来的场景 if (options.albumId) { this.albumId options.albumId this.fetchAlbumDetail() } }, onShareAppMessage() { // 微商场景分享出去必须带分销或客户标识 // 统一用 query 参数携带方便统计哪个客户带来的流量 return { title: this.title || 最新实拍相册, path: /pages/detail/detail?albumId${this.albumId}inviter${this.inviter}, imageUrl: this.cover } } }onShareAppMessage在微信小程序和 App 端都生效。一个容易忽略的细节是imageUrl必须是 HTTPS 地址如果封面图是本地临时路径微信会直接分享失败建议用getThumbUrl(cover, 600)生成分享卡片缩略图。另外inviter参数是微商体系的常见玩法通过分享卡片进入的客户后续下单时要把这个参数作为佣金归属的依据这套逻辑在源码里一般会在 App.vue 的onLaunch里捕获。3.4 分类相册的数据结构和 Vuex 缓存分类相册通常是一级大分类美妆、穿搭、生活日用品每个大类下挂多组实拍相册。数据结构设计要同时考虑扩展性和渲染效率// store/index.js 中的 Vuex 模块 const state { // 分类列表缓存后减少重复请求 categories: [], // 每个分类下相册的本地缓存key 为 categoryId categoryAlbums: {} } const actions { async fetchCategories({ commit }) { // 首次进入加载分类后续走缓存 // 在微商运营场景中分类会频繁调整所以缓存时间不宜过长 const cached uni.getStorageSync(categories) if (cached) { commit(SET_CATEGORIES, cached) } const res await uni.request({ url: ${BASE_URL}/api/category/list }) commit(SET_CATEGORIES, res.data.data) uni.setStorageSync(categories, res.data.data) } }分类和相册列表的缓存策略要区分开分类变动频率低可以埋uni.setStorageSync持久化缓存相册列表变动频繁新增实拍图就要刷新建议只做内存缓存不落盘否则客户看到的是旧图对微商来说是致命的信任损失。4. 从源码到上架Uniapp 打包多端小程序与安卓 iOS 的完整参数4.1 微信小程序打包流程与运行机制拿到源码以后第一步不是改代码而是确认manifest.json里的appid是否占位符。Uniapp 项目通过 HBuilderX 导入后在manifest.json的可视化配置界面里选择「微信小程序配置」填入你在微信公众平台申请的小程序 AppID。打包时有两种方式HBuilderX 菜单栏「运行」-「运行到小程序模拟器」-「微信开发者工具」这种是开发调试模式改动代码自动热更新「发行」-「小程序-微信」这种才是生产构建会对代码做压缩和分包整理体积更小发行构建完成后HBuilderX 会在项目目录下生成dist/build/mp-weixin文件夹。这个文件夹才是真正的小程序源码需要导出后在微信开发者工具中打开上传代码然后去微信公众平台提交审核。manifest.json中一个容易被忽略的项是mp-weixin.usingComponents如果项目里用了自定义组件必须确认微信小程序后台的「本地设置」勾选了「将 JS 编译成 ES5」否则老机型上会出现白屏问题。4.2 App 端打包与原生插件兼容问题Uniapp 打包 App 有两种形式云打包和离线打包。云打包在 HBuilderX 里直接操作不需要本地安装 Android SDK免费版可以打测试包正式上架的包建议用自定义基座否则热更新能力和原生插件的调试会受限。很多微商相册源码会用到一个原生插件图片保存到系统相册。uni.saveImageToPhotosAlbum在微信小程序上是微信自带的 API但是在 App 端如果系统版本是 Android 10 及以上需要申请访问外部存储权限。Uniapp 打包 App 时使用的社区原生插件通常已经自带权限声明你只需在manifest.json的App常用其它设置里确认app-plus: { distribute: { android: { permissions: [ uses-permission android:name\android.permission.WRITE_EXTERNAL_STORAGE\/, uses-permission android:name\android.permission.READ_EXTERNAL_STORAGE\/ ] } } }注意Android 13 及以上WRITE_EXTERNAL_STORAGE权限不再授予替代方案是用系统相册的MediaStore能力Uniapp 的uni.saveImageToPhotosAlbum已经封装了这个兼容逻辑。如果你的项目源码较旧可能需要升级对应的原生插件版本。4.3 多端差异处理条件编译的实战写法Uniapp 最大的坑在于同一个页面在微信小程序里正常到 App 端就白屏或者到 H5 端样式错乱。原因往往是用了某个端独有的 API 或样式属性。多端兼容的正规做法是在源码里使用条件编译注释而不是在页面里写if (uni.getSystemInfoSync().platform ios)来判断。典型的例子是导航栏高度的处理。微商相册首页为了视觉效果通常使用自定义导航栏navigationStyle: custom此时需要获取状态栏高度但各端返回的字段名不同// utils/system.js export function getStatusBarHeight() { const systemInfo uni.getSystemInfoSync() // 微信小程序statusBarHeight 直接返回 // App 端 iOSstatusBarHeight 返回的是逻辑像素需要换算 // H5 端部分浏览器没有 statusBarHeight需降级处理 // #ifdef H5 return 0 // #endif // #ifdef MP-WEIXIN return systemInfo.statusBarHeight || 20 // #endif // #ifdef APP-PLUS return plus.navigator.getStatusbarHeight() // #endif }#ifdef和#ifndef是 Uniapp 的预处理注释编译时 Uniapp 会根据当前编译目标自动裁剪代码。这种写法不属于哪一份官方文档独有的而是多端项目里通用的工程化做法经过编译后最终代码里只会保留对应端的逻辑。4.4 多端上线前必须检查的权限和域名配置清单微商相册类小程序在提审前以下内容每一项都要排查否则大概率被拒检查项说明常见驳回原因downloadFile合法域名图片加载域名必须加入后台图片加载是image组件直接显示不用配置但uni.downloadFile需要uploadFile合法域名代理商上传图片的接口域名没有配置时 IOS 端能跑Android 端直接报url not in domain list用户隐私保护指引涉及相机、相册、位置权限必须声明微商相册需要访问相册权限不声明直接拒分享按钮可用性分享出去的页面必须能正常打开常见问题是分享页面的path参数拼错导致白屏「修改刚进入的加载页面」这个搜索词在源码开发里通常指的是启动页或首页的onLoad逻辑。微商相册源码中进入首页时如果有登录态校验之类的逻辑很慢。常见的优化做法是把onLoad里非关键的数据请求改为onReady再执行首页和数据接口并行请求避免串行等待。5. 多端发布后避坑与性能优化验证源码是否可用的 3 个技巧5.1 用微信开发者工具自带的「真机调试」替代预览微商相册的真实使用场景是客户在微信里聊天随手点开和开发者工具里的表现完全不同。开发完成后不要只在模拟器里点一遍就收工。正确做法在微信开发者工具里选择「真机调试 2.0」这个模式下不是扫码预览而是把调试器挂在真机上可以在电脑上看到真机端的console输出和 Network 请求状态。重点排查三个场景4G 网络下首页图片是否能正常加载而不是只在 WiFi 下测试分享出去的页面对方打开时能否正确读取options参数因为微信可能对分享链接做编码处理安卓低端机上瀑布流滚动是否卡顿如果卡顿优先检查是不是图片用了原图5.2 检查分包体积与主包大小的数值底线5.2.1 主包体积超限的系统化排查方法HBuilderX 发行后微信开发者工具里「详情」面板会直接显示主包和分包的大小。如果主包超过 2MB按以下顺序排查这几个步骤是排障系统里最常用的执行路径第一步在开发者工具的「代码依赖分析」面板中查看主包各文件的体积排行先定位体积占比最大的文件是页面代码还是vendor.js。这个面板是微信开发者工具自带的静态分析能力不需要导入额外插件。第二步如果vendor.js超过 500KB说明源码里把整个第三方库通过import引入了主包。典型的误用是import * as qs from query-string这类全量引入微商相册场景只需用 URL 参数拼接完全可以用uni.$emit或原生encodeURIComponent替代删掉整个依赖体积直接降下来。第三步检查static目录下是否有位图图片或旧版设计稿残留。开发者经常在调试时往static里临时放了几张test.png忘了删这种文件不会被打包器压缩会原样进包。排查方法是打开dist/build/mp-weixin目录按文件大小排序超过 200KB 的图片单独确认用途没有引用关系的直接清理。如果以上三步做完仍然超限唯一的出路是把更多页面移入分包。移动的实现方式是把pages.json里对应页面的path删掉在subPackages中重新声明页面代码本身不用改路径因为内部引用用的是相对路径。5.2.2 分包体积超限的差异化处理分包没有 2MB 的硬限制但微信小程序整体包体主包 全部分包不能超过 20MB。微商相册源码中分包超限的主要原因往往是「上传素材页面」把本地图片转成了base64缓存在页面里。这在调试时方便但会残留大量无用的 base64 变量微信开发者工具的「代码依赖分析」不会显示这些字符串难度更大。处理办法是检查pages_manage/upload页面里是否有const tempFile data:image/jpeg;base64,...这样的文件级常量有的话直接改成。同时确认store里没有把uni.chooseImage返回的临时文件路径持久化到 Vuex临时路径的格式在小程序端是一个wxfile://开头的本地地址没有任何持久化价值。5.3 用 uni-app 的官方 CLI 模式排查编译告警很多人拿到第三方的源码后直接用 HBuilderX 打开就改这样确实能看到报错但看不到编译告警。正确姿势是用命令行在项目根目录执行下面的命令对比不同编译目标下的告警输出# 微信小程序编译 npx uni build -p mp-weixin # 支付宝小程序编译 npx uni build -p mp-alipay # H5 端编译 npx uni build -p h5执行后观察输出的警告信息[plugin:vite:resolve]这类告警表示某个模块在对应平台找不到Sass 编译警告表示样式兼容性有问题。微商相册源码里最常见的告警是Some packages use a deprecated API造成这个告警的原因是源码里用了uni.getSystemInfoSync但没有捕获异常这个 API 在部分系统上会返回空对象。替换方式是把调用处包一层let systemInfo {} try { systemInfo uni.getSystemInfoSync() } catch (e) { systemInfo { platform: , statusBarHeight: 20 } }5.4 热重载失效时的应急手段清除缓存重新构建开发时改动pages.json或manifest.jsonHBuilderX 经常出现热重载不生效的情况页面样式改了但显示没变。这个问题的根因是 HBuilderX 内置的编译缓存它只对vue文件和js文件的增量变更敏感配置文件变更不会触发增量编译。遇到这种情况不要反复改代码试直接操作以下两步在 HBuilderX 中「运行」菜单选择「重新运行到小程序模拟器」而不是「刷新」「刷新」不会清理运行时缓存手动删除项目根目录下的unpackage/dist目录这个目录是编译产物删掉后重新构建一定会全量编译注意unpackage目录应该加入.gitignore不要让编译产物混入源码版本管理否则团队协作时经常出现两个人改完代码提交了大量dist文件冲突的情况。这些动态生成的资源不具备合并价值Diff 出来的内容无法人工审阅只会污染提交历史。最后说一个关于 Uniapp 版本选择的实际经验微商相册这类以微信小程序为主战场的项目如果源码基础比较旧用的是 Vue 2 语法优先确认 HBuilderX 版本在 3.x 以上低于 3.0 的版本构建出来的包无法通过微信最新基础库的审核Vue 3 版本的项目编译产物依赖vitejs/plugin-vue微信开发者工具里首次打开时会在「本地设置」中弹出「将 JS 编译成 ES6」的选项必须勾选否则会报SyntaxError: Unexpected token ?之类的错误这是老版本工具链的典型编译产物兼容性问题不是源码本身的问题在manifest.json里把vueVersion明确写成3不要留空不写留空会导致 HBuilderX 按 Vue 2 编译部分组件如script setup语法直接报错而且报错信息不具备可读性如果是极简场景或者你需要快速改造成自己品牌的小程序从 Vue 2 版本改起是更快的路径如果要在此基础上做视频号关联、直播带货这类扩展功能Vue 3 的生态兼容性更好比如短视频相关插件对新版基础库的支持更积极本文还有配套的精品资源点击获取