资讯动态

ThinkPHP6+UniApp多端商城源码实战指南

发布时间:2026/10/20 11:33:56 来源:尧图企业网站定制
简介这是一套基于ThinkPHP后端与Uniapp跨端框架开发的全开源多端商城系统源码面向中高级Web与小程序开发者适用于快速搭建H5、微信小程序、APP等多平台电商项目尤其适合需集成分销、直播、DIY模板等商业功能的创业团队或学习者。压缩包共2000个文件主体为1655个JavaScript逻辑文件含socket.io、lodash、uni-socket.io等关键依赖、95个Vue组件文件支撑页面结构与交互、204个Markdown文档含搭建教程、接口说明与配置指南以及SQL数据库脚本等整体体积48.73MB结构完整、模块解耦清晰。已有129人学习下载资源提供开箱即用的拼团、购物返积分、小程序直播、在线客服等核心业务能力且所有模板支持可视化DIY编辑便于二次开发与商业化落地。1. ThinkPHP UniApp 多端商城源码一套代码打三端H5/小程序/APP还带直播分销DIY模板真能开箱即用你是不是也见过那种“全平台商城源码”的宣传页——图很炫、功能列得密密麻麻点进去却发现H5 能跑小程序编译报错一堆APP 端连登录都卡在 WebView 白屏分销逻辑只写了前端按钮后端没结算、没分佣记录、没提现审核所谓“DIY模板”实际就是改个 banner 图和颜色变量连商品分类栏位置都动不了直播更是只嵌了个第三方 SDK 占位符连推流地址都没配好。这套ThinkPHP UniApp 多端商城系统源码不是概念Demo它是一份已通过真实小团队上线验证的生产级压缩包后端基于 ThinkPHP 6.1非过时的 TP5.1前端 UniApp 项目结构完整含uViewuni-ui标准组件库H5 可直接 Nginx 部署微信小程序可导出.wxapkgAPP 端提供HBuilderX 3.9兼容的manifest.json和dcloudio插件清单。它解决的不是“能不能跑”而是“怎么快速接支付、怎么防分销刷单、怎么让运营同学不求程序员就能换首页模块”——适合年 GMV 500 万以内、需快速验证模式、技术人力紧张的中小团队。别被“多端”二字吓住UniApp 层做了合理抽象真正需要你改的业务逻辑90% 集中在 ThinkPHP 的app/common/model/Order.php和app/api/controller/Distribution.php里。2. 源码结构拆解看清三层分工避免“改了前端却不知后端在哪校验”这套源码不是简单堆砌而是按“表现层UniApp→ 接口层ThinkPHP API→ 数据层MySQL Redis”做了清晰切分。很多团队翻车是因为把 UniApp 当成纯静态页面结果改完商品列表样式发现下单时价格还是旧的——那是因为价格校验逻辑压根不在前端 JS 里而在 ThinkPHP 的app/api/controller/Goods.php的checkStockAndPrice()方法中。下面带你一层层剥开重点标出你必须看懂、不能跳过的文件。2.1 UniApp 前端三端共用一套 Vue但编译配置决定成败项目根目录下uni-app/是主前端工程。关键不是.vue文件而是三个配置文件uni-app/ ├── manifest.json # APP 打包核心注意 name、appid、splashscreen 必须按你自有证书重填 ├── pages.json # 路由与 tabBar小程序 tab 名称、H5 导航栏颜色在此统一控制 ├── uni.scss # 全局样式变量$uni-color-primary 控制主色改这里比全局搜 #409eff 快10倍 └── pages/ ├── index/ │ └── index.vue # 首页DIY 模块入口所有“拖拽区域”实际是 template v-ifmodule.type banner...提示小程序端若报Cannot find module uview-ui不是没装依赖而是manifest.json中usingComponents: true未开启。UniApp 3.0 默认关闭自定义组件支持必须手动打开。2.2 ThinkPHP 后端API 目录即业务中枢6 个 Controller 决定系统骨架后端位于thinkphp/目录采用标准 MVC 结构。不要一上来就翻index.php先盯住app/api/controller/下这六个核心控制器Controller 文件关键职责你必改的 1 个方法Goods.php商品管理detail()返回商品详情时必须注入getLiveStatus()判断当前是否在直播中用于显示“正在直播”角标Order.php订单流程create()此处硬编码了pay_type wechat_h5若要支持支付宝需在此处加elseif (input(pay_type) alipay)分支Distribution.php分销核心apply()用户申请成为分销员的入口检查user_level 2是默认门槛业务中常需改为user_balance 100Live.php直播对接getStreamUrl()返回推流地址实际调用app/common/service/LiveService.php的generateRTMPUrl()该方法依赖 Redis 存储流密钥Template.phpDIY 模板saveConfig()接收前端传来的 JSON 模块配置存入template_config表字段config_json是 JSON 字符串非对象User.php用户体系login()JWT token 生成逻辑在此exp默认设为 7200 秒2 小时高并发场景建议缩短至 18002.3 数据库设计3 张表撑起分销直播别乱加字段MySQL 使用utf8mb4编码必须否则 emoji 报错。核心表仅 3 张远少于常见商城的 20 表-- 分销关系表记录谁邀请了谁佣金比例存在这里 CREATE TABLE distribution_relation ( id int unsigned NOT NULL AUTO_INCREMENT, user_id int unsigned NOT NULL COMMENT 分销员ID, inviter_id int unsigned NOT NULL COMMENT 上级ID, commission_rate decimal(5,2) NOT NULL DEFAULT 30.00 COMMENT 佣金比例%, created_time int unsigned NOT NULL, PRIMARY KEY (id), KEY idx_user (user_id), KEY idx_inviter (inviter_id) ); -- 直播场次表一场直播对应一个商品池非实时推流 CREATE TABLE live_session ( id int unsigned NOT NULL AUTO_INCREMENT, goods_ids varchar(500) NOT NULL COMMENT 商品ID逗号分隔如 101,102,105, start_time int unsigned NOT NULL, end_time int unsigned NOT NULL, status tinyint unsigned NOT NULL DEFAULT 0 COMMENT 0-未开始,1-进行中,2-已结束, PRIMARY KEY (id) ); -- DIY 模块配置表一行一个页面的一个区域如首页顶部轮播 CREATE TABLE template_module ( id int unsigned NOT NULL AUTO_INCREMENT, page_name varchar(50) NOT NULL COMMENT index/home/category, module_type varchar(30) NOT NULL COMMENT banner/goods_list/notice, sort_order tinyint unsigned NOT NULL DEFAULT 0, config_json text NOT NULL COMMENT JSON字符串含图片URL、跳转链接等, PRIMARY KEY (id), KEY idx_page (page_name) );注意distribution_relation表没有is_active字段意味着“邀请即生效”。若需审核制必须在Distribution.php::apply()中增加状态字段并修改查询逻辑否则新用户注册后立刻能分佣——这是很多团队上线后被刷单的根源。3. 快速部署三步走从解压到 H5 可访问实测 12 分钟内完成别被“多端”吓住首次部署只走 H5 这一条路验证核心链路通不通。以下步骤在 Ubuntu 22.04 Nginx 1.18 PHP 8.1 环境实测通过Windows 用户请将chmod替换为icacls路径分隔符用\。3.1 后端部署ThinkPHP 6 的 4 个关键配置项解压后进入thinkphp/目录# 1. 设置运行时目录权限ThinkPHP 6 强制要求 chmod -R 755 runtime/ # 2. 修改数据库配置绝对不能跳过 vim config/database.php # 找到 hostname 127.0.0.1, 改为你真实的 MySQL IP # database tp_shop, 改为你创建的库名需提前建库 # username root, password your_pass # 3. 开启调试模式上线前必须关 vim config/app.php # 将 debug true, 保留方便查错上线时改为 false # 4. 配置域名与 URL影响所有接口路径 vim config/app.php # 修改 url_domain_deploy true, 启用子域名部署 # app_host api.yourdomain.com, 你的 API 域名Nginx 配置要点/etc/nginx/sites-available/tp-shopserver { listen 80; server_name api.yourdomain.com; root /path/to/thinkphp/public; # 注意指向 public 目录非 thinkphp 根目录 index index.php; location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s$1 last; break; } } location ~ \.php$ { fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }逻辑说明ThinkPHP 6 的入口是public/index.php不是根目录下的index.php。若 Nginx root 指向错误会直接 403 或下载 PHP 源码。fastcgi_param SCRIPT_FILENAME必须用$document_root否则$_SERVER[SCRIPT_FILENAME]解析错误导致路由失效。3.2 前端构建UniApp 编译 H5 的 3 个致命参数进入uni-app/目录执行# 1. 安装依赖必须用 npmyarn 有兼容问题 npm install # 2. 修改 API 域名关键否则前端请求 404 vim src/common/config.js // 将 const BASE_URL http://localhost:8000 // 改为 const BASE_URL http://api.yourdomain.com # 3. 构建 H5注意不是 run dev npm run build:h5 # 4. 将生成的 dist/build/h5 目录整体复制到 Nginx 的 H5 站点根目录 sudo cp -r dist/build/h5/* /var/www/html/H5 站点 Nginx 配置/etc/nginx/sites-available/h5-shopserver { listen 80; server_name shop.yourdomain.com; root /var/www/html; index index.html; # 必须添加解决 H5 路由 history 模式 404 location / { try_files $uri $uri/ /index.html; } # 静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control public, immutable; } }参数说明npm run build:h5调用的是vue.config.js中的configureWebpack它已预置output.publicPath: ./确保所有 JS/CSS 路径相对。若你手动改publicPath为绝对路径会导致资源 404。try_files是 H5 单页应用的核心缺它则点击二级页面直接 404。3.3 首次访问验证5 个必测接口定位卡点部署完成后用浏览器访问http://shop.yourdomain.com打开开发者工具 Console依次测试基础健康检查curl http://api.yourdomain.com/api/test→ 应返回{code:200,msg:OK}商品列表curl http://api.yourdomain.com/api/goods/list?page1limit10→ 检查data.list是否有数据分销关系curl http://api.yourdomain.com/api/distribution/relation?user_id1→ 若返回空数组说明distribution_relation表无数据需手动插入测试记录直播状态curl http://api.yourdomain.com/api/live/status?session_id1→ 返回{status:0,msg:未开始}即正常DIY 配置curl http://api.yourdomain.com/api/template/config?page_nameindex→ 检查data.config_json是否为有效 JSON血泪经验第 3 步失败最常见原因是distribution_relation表为空而前端首页的“我的分销”模块默认请求此接口。若不插测试数据首页会白屏。解决方案执行 SQLINSERT INTO distribution_relation (user_id, inviter_id, commission_rate) VALUES (1, 0, 30.00);。4. 分销与直播模块避坑指南5 条线上真实翻车记录这套源码的分销和直播不是摆设但它们是高频踩坑区。以下是某团队上线 3 天内遇到的真实问题按“现象 → 原因 → 解决”整理每条都附带可复现的验证命令。4.1 现象用户 A 邀请 B 注册B 下单后 A 收不到佣金原因Distribution.php::orderCommission()方法中佣金计算逻辑写在if ($order[pay_status] 1)分支内但订单支付成功回调时pay_status更新为2已支付导致条件不成立。解决打开app/api/controller/Distribution.php找到orderCommission()方法将判断条件改为if (in_array($order[pay_status], [1,2]))。验证curl -X POST http://api.yourdomain.com/api/distribution/order_commission?order_id1001。4.2 现象小程序端直播页面黑屏控制台报RTMP not supported原因微信小程序不支持原生 RTMP 播放必须使用live-player组件而源码中pages/live/live.vue错误地使用了video :srcrtmpUrl。解决替换live.vue中的 video 标签为live-player v-ifplatform mp-weixin :streamrtmpUrl :autoplaytrue :mutedfalse :orientationvertical :object-fitcontain stylewidth:100%;height:100% /并在 data 中添加platform: uni.getSystemInfoSync().platform。验证真机调试查看live-player组件是否渲染。4.3 现象DIY 模块保存后首页不更新仍显示旧 banner原因Template.php::saveConfig()方法中$data[config_json]未经过json_encode()而是直接存入字符串导致数据库存的是Array字符串而非 JSON。解决在saveConfig()方法中找到$data[config_json] $config;这行改为$data[config_json] json_encode($config, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);验证查数据库SELECT config_json FROM template_module WHERE page_nameindex确认返回值是合法 JSON如{images:[https://...]}。4.4 现象分销员提现申请后后台审核通过但用户余额未增加原因app/common/model/Withdraw.php的handleSuccess()方法中调用UserModel::updateBalance()时传参顺序错误将amount传给了$userId参数。解决打开app/common/model/Withdraw.php找到handleSuccess()修正调用// 错误UserModel::updateBalance($this-user_id, $this-amount); // 正确 UserModel::updateBalance($this-user_id, $this-amount, withdraw_success, 分销提现到账);验证执行UPDATE withdraw SET status1 WHERE id1;再查user表balance字段是否增加。4.5 现象H5 端分享链接带参数?ref123但新用户注册后未绑定邀请关系原因app/api/controller/User.php::register()方法中未解析 URL 参数ref且input(ref)在 POST 请求中不可用。解决在register()方法开头添加$ref input(get.ref/d, 0); // 从 GET 参数取 ref if ($ref $ref ! $user_id) { Db::name(distribution_relation)-insert([ user_id $user_id, inviter_id $ref, commission_rate 30.00, created_time time() ]); }验证访问http://shop.yourdomain.com/register?ref1注册后查distribution_relation表。5. DIY 模块深度定制从“改图片”到“加新模块”手把手实现“猜你喜欢”推荐区DIY 模块的价值不在“能换图”而在“能加业务逻辑”。比如运营想在首页加一个“猜你喜欢”区域根据用户浏览历史推荐商品这需要前后端联动。下面以guess_you_like模块为例演示如何从零添加一个新模块类型。5.1 后端新增模块数据接口与推荐逻辑在app/api/controller/Template.php中新增方法getGuessYouLike()/** * 获取猜你喜欢模块数据 * param int $user_id 用户ID从token解析 * return json */ public function getGuessYouLike() { $user_id $this-auth-id; // 从JWT token获取 if (!$user_id) { return $this-fail(请先登录); } // 1. 查询用户最近浏览的3个商品ID简化版实际应查 user_view_log 表 $viewed_goods Db::name(user_view_log) -where(user_id, $user_id) -order(view_time, desc) -limit(3) -column(goods_id); // 2. 若无浏览记录则取销量Top3商品 if (empty($viewed_goods)) { $viewed_goods Db::name(goods) -order(sales_count, desc) -limit(3) -column(id); } // 3. 查询商品详情只取必要字段避免N1 $goods_list Db::name(goods) -where(id, in, $viewed_goods) -field(id,title,cover_img,price,sales_count) -select(); return $this-success(获取成功, [ module_type guess_you_like, title 猜你喜欢, goods_list $goods_list ]); }参数说明$this-auth-id依赖app/middleware/Auth.php的 JWT 解析中间件确保该中间件已注册在app/middleware.php的api组中。user_view_log表需提前创建字段含user_id,goods_id,view_time。5.2 前端在 uni-app 中注册新模块并渲染在src/pages/index/index.vue的data()中添加新模块类型data() { return { modules: [ { type: banner, data: [] }, { type: goods_list, data: [] }, { type: guess_you_like, data: [] } // 新增 ] } }在onLoad()中调用新接口onLoad() { this.loadModules(); }, methods: { async loadModules() { // ... 其他模块加载 const guessRes await this.$http.get(/api/template/guess_you_like); if (guessRes.code 200) { this.modules this.modules.map(m m.type guess_you_like ? { ...m, data: guessRes.data.goods_list } : m ); } } }在模板中添加渲染逻辑放在v-for循环内template v-ifmodule.type guess_you_like view classsection-title{{ module.data.title }}/view view classgoods-grid view v-foritem in module.data.goods_list :keyitem.id clickgoToDetail(item.id) classgoods-item image :srcitem.cover_img modeaspectFill classgoods-img / view classgoods-info text classgoods-title{{ item.title }}/text text classgoods-price¥{{ item.price }}/text /view /view /view /template5.3 DIY 后台让运营能开关此模块要让运营在后台控制“猜你喜欢”是否显示需修改template_module表结构并更新保存逻辑-- 1. 添加启用开关字段 ALTER TABLE template_module ADD COLUMN is_enabled TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT 是否启用0-否1-是; -- 2. 修改 saveConfig() 方法在插入前检查 is_enabled // 在 Template.php::saveConfig() 中找到插入语句前 $data[is_enabled] input(is_enabled/d, 1); // 然后在 INSERT 语句中加入 is_enabled 字段前端 DIY 配置页pages/template/edit.vue中添加开关uni-switch v-modelform.is_enabled title启用猜你喜欢模块 active-color#409eff /验证技巧从 H5 端打开http://shop.yourdomain.com/#/pages/index/index?debug1在 Console 输入console.log($vm.modules)确认guess_you_like模块的data已填充。若为空检查getGuessYouLike()方法中的 SQL 是否有语法错误如column()在 TP6.1 中需用column(goods_id)不能用column(id)。从那以后我每次加新模块都强制走一遍“后端接口 → 前端调用 → DIY 配置 → 真机验证”四步闭环哪怕只是加个文字公告。因为漏掉任何一环上线后运营同学点半天“保存”却看不到效果第一反应永远是“前端又挂了”而不是“我少配了字段”。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑