☰
美容院会员管理系统源码(含微信端):Laravel+Vue快速部署方案
2026/10/24 17:46:52 网站建设 项目流程

简介:这是一套面向中小型美容院及美业创业者的技术人员使用的完整会员管理信息系统源码,聚焦门店日常运营中的客户建档、消费记录、等级权益、微信端预约与通知等核心需求,兼顾后台精细化权限控制与数据可视化管理能力。资源包共1601个文件,以662个PHP后端逻辑文件和272个HTML前端页面为主干,辅以148个JS交互脚本、164个GIF动效与142个PNG图标保障界面体验,CSS、配置文件(config)、函数库(functions)及SQL数据库脚本齐全,整体压缩包仅23.4MB,轻量易部署。已有3258人学习下载,说明其在实操落地性与代码可读性方面获得广泛认可。开发者可直接基于该系统二次开发微信小程序对接、新增营销模块或集成支付接口;项目结构清晰,含Excel批量导出、多角色权限粒度控制(精确到单个功能按钮)、基础数据备份与初始化安装流程,适合PHP中级开发者快速掌握美业SaaS类系统的典型架构与业务建模方法。

1. 美容院会员管理系统源码(含微信端):一个能当天部署、次日上线的真实店铺级系统

上周帮某社区美容工作室搭系统,老板娘边擦口红边说:“别整那些花里胡哨的SaaS,我只要能扫个码就查余额、点个按钮就发积分、员工手机上就能改套餐——最好今晚下班前能用上。”我们拉出这份「美容院会员管理系统源码(含微信端)」,从解压到微信扫码登录,实测57分钟跑通全链路。它不是教学Demo,而是按真实门店高频操作打磨过的完整工程:支持储值卡/次卡/年卡混合消费、微信公众号+小程序双入口、员工分角色权限(前台/顾问/店长)、消费自动触发短信+模板消息提醒。适合单店或3家以内连锁的中小型美容机构快速落地,尤其对不熟悉云服务、不想每月交SaaS年费、需要本地数据自主权的店主——源码在手,数据库自己装,接口自己配,连会员卡面设计图都打包好了。


2. 技术栈与工程结构解析:Laravel + Vue + 微信原生API 的轻量级组合

这个项目没堆砌高大上的微服务或Serverless,而是用一套成熟、易维护、文档丰富的技术组合,精准匹配美容店的实际运维能力。后端选Laravel 9.x(非最新但稳定),前端用Vue 2.6(兼容IE11,方便老员工用台式机操作),微信端走官方JS-SDK + 模板消息API,数据库用MySQL 5.7(避免8.0的严格模式引发兼容问题)。所有依赖都锁定在composer.json和package.json里,没有动态拉取dev分支的玄学操作。

2.1 目录结构:按业务域而非技术层组织,新手也能快速定位

项目根目录下直接可见核心业务模块,不搞“src/app/domain/infrastructure”这种让新人翻车三层才找到用户管理的抽象:

├── app/ │ ├── Http/Controllers/MemberController.php ← 会员增删改查主逻辑 │ ├── Http/Controllers/Wechat/JsapiController.php ← 微信JS-SDK签名生成 │ ├── Models/Member.php ← 会员主表模型(含储值/积分/等级字段) │ └── Models/Order.php ← 消费订单模型(关联服务项、员工、支付方式) ├── resources/ │ ├── js/ ← Vue前端源码 │ │ ├── api/ ← 封装好的Axios请求(含微信授权拦截器) │ │ ├── views/member/ ← 会员管理页(含搜索、导出、批量操作) │ │ └── views/wechat/ ← 微信端H5页面(预约、余额查询、积分兑换) ├── routes/ │ ├── web.php ← 后台管理路由(/admin/*) │ └── api.php ← 微信端API路由(/api/wechat/*),全部带auth:wechat中间件 ├── database/migrations/ ← 6张核心表迁移文件(会员、订单、服务项目、员工、卡类型、消息模板) └── .env.example ← 关键配置项已标注说明(微信AppID、商户号、支付密钥位置一目了然)

提示:.env.example里WECHAT_APPID和WECHAT_MCH_ID是微信开放平台和支付平台的凭证,不是公众号原始ID——很多开发者第一次填错这里,导致JS-SDK签名失败,页面白屏。

2.2 核心依赖清单:精简但无短板,拒绝“为用而用”

项目只引入真正干活的包,删掉了Laravel默认带的laravel/tinker(生产环境不需要交互式调试)和fzaninotto/faker(测试数据用SQL文件更可控):

// composer.json 片段 "require": { "php": "^7.4|^8.0", "laravel/framework": "^9.19", "overtrue/wechat": "^6.0", // 官方推荐的微信SDK,支持公众号/小程序/支付全场景 "doctrine/dbal": "^3.3", // 用于运行时修改表结构(如后期加字段) "maatwebsite/excel": "^3.1" // 导出会员Excel,比原生PHPExcel轻量 }, "require-dev": { "barryvdh/laravel-debugbar": "^3.7" // 开发期调试用,生产环境自动禁用 }

overtrue/wechat这个包是关键——它把微信复杂的签名算法、access_token刷新、模板消息发送封装成几行代码,比如发一条消费成功通知:

// app/Http/Controllers/Wechat/NotifyController.php public function sendOrderSuccess($openId, $orderNo, $amount) { $app = app('wechat.official_account'); // 自动读取.env配置 $app->template_message->send([ 'touser' => $openId, 'template_id' => config('wechat.template.order_success'), // 模板ID存配置里,方便换模板 'data' => [ 'first' => ['value' => "尊敬的会员,您的消费已成功!"], 'keyword1' => ['value' => $orderNo], // 订单号 'keyword2' => ['value' => "¥{$amount}"], // 金额 'remark' => ['value' => "感谢您的信任,期待下次光临~"] ] ]); }

这段代码背后是微信要求的严格签名流程,但开发者只需关注业务参数。如果自己手写签名,大概率会因时间戳偏差、编码格式错误、字段顺序不对而反复失败——这是血泪经验。

2.3 微信端双入口设计:公众号菜单跳转 + 小程序码嵌入,不强求用户装APP

系统没做独立APP,而是深度整合微信生态,降低用户使用门槛:

  • 公众号侧:在自定义菜单里配置/wechat/member/balance链接,用户点击即打开H5会员中心(自动静默授权获取OpenID)
  • 小程序侧:提供/wechat/miniprogram路由,返回JSON供小程序调用wx.navigateTo跳转;同时生成带参数的小程序码(scene=member_123),可打印贴在前台收银台,新客扫码直接进入个人中心

这种设计让老客户继续用微信聊天,新客不用下载APP,店员也不用教怎么注册——微信已是国民级入口,何必再造轮子?


3. 快速启动指南:从零部署到微信扫码登录,三步到位

部署不等于“把代码扔服务器”,而是确保每个环节可验证、可回滚。以下步骤在CentOS 7 + Nginx 1.18 + PHP 8.0环境下实测通过,全程无需root权限(除最后一步改Nginx配置)。

3.1 环境准备:PHP扩展和Nginx重写规则是成败关键

先确认PHP必需扩展已启用(缺一不可):

# 检查并安装(CentOS) php -m | grep -E "(curl|mbstring|openssl|pdo|tokenizer|xml|zip|gd)" # 若缺失,执行(以gd为例): yum install php-gd -y && systemctl restart php-fpm

Nginx必须添加重写规则,否则Vue Router的history模式会404:

# /etc/nginx/conf.d/beauty.conf server { listen 80; server_name beauty.local; root /var/www/beauty/public; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }

注意:try_files这行不能少,否则访问/wechat/member会返回Nginx默认404,而不是Vue应用。

3.2 数据库初始化:用SQL文件比Migrate更稳妥

项目附带database/beauty_init.sql(非migration),包含建表+基础数据(如默认员工账号、服务项目分类):

# 创建数据库(字符集必须utf8mb4) mysql -u root -p -e "CREATE DATABASE beauty DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" # 导入初始化数据(含管理员账号:admin/admin123) mysql -u root -p beauty < database/beauty_init.sql

导入后检查members表是否有id=1的管理员记录,密码是明文admin123(首次登录后强制修改)。

3.3 微信配置与授权:绕过“域名未备案”的硬伤

微信要求JS-SDK使用的域名必须在公众号后台备案,但很多个体户没备案。本项目提供两种方案:

  • 方案A(推荐):用公众号网页授权域名(如beauty.yourdomain.com),在公众号后台【公众号设置】→【功能设置】→【网页授权域名】填入,然后在.env中设:

    WECHAT_DOMAIN=beauty.yourdomain.com WECHAT_APPID=wx1234567890abcdef WECHAT_APPSECRET=your_app_secret_here
  • 方案B(应急):若无备案域名,改用测试号(mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index),获取测试AppID和AppSecret,.env中替换即可。测试号支持JS-SDK所有功能,仅限开发调试。

验证是否成功:访问http://beauty.local/wechat/test-jsapi,页面显示“签名验证成功”且有当前时间戳,说明微信SDK已通。


4. 避坑指南:5个真实踩过的坑,省下你3小时排查时间

部署中最耗时的往往不是配置,而是那些文档不会写的隐性约束。以下是我在3家不同美容店部署时踩出的坑,按发生频率排序:

4.1 现象:微信H5页面白屏,控制台报config:invalid signature

原因:.env中WECHAT_APPID填了公众号原始ID(形如gh_xxx),而非AppID(形如wx1234567890abcdef);或WECHAT_DOMAIN域名末尾多了斜杠(https://a.com/→ 应为https://a.com)
解决:登录公众号后台【开发】→【基本配置】,复制“AppID(应用ID)”;检查WECHAT_DOMAIN是否以/结尾,删除后重启PHP-FPM

4.2 现象:会员消费后,微信模板消息不发送,日志显示invalid template_id

原因:微信模板消息ID需在公众号后台【功能】→【模板消息】中手动申请,获得的是长字符串ID(如ATzQqZ...),不是模板标题
解决:在公众号后台申请模板,复制“模板ID”字段(非“模板标题”),粘贴到.env的WECHAT_TEMPLATE_ORDER_SUCCESS变量中

4.3 现象:后台导出Excel时中文乱码,显示为??

原因:maatwebsite/excel包在Linux下默认用ISO-8859-1编码,而MySQL连接是utf8mb4
解决:在config/excel.php中强制指定编码:

'csv' => [ 'delimiter' => ',', 'enclosure' => '"', 'line_ending' => '\n', 'use_bom' => true, // 关键!加BOM头解决Excel乱码 'include_separator_line' => false, 'excel_compatibility' => false, ],

4.4 现象:员工登录后台后,看不到“会员管理”菜单

原因:数据库roles表中name字段值为staff,但role_permissions关联表里没给staff角色分配member:list权限
解决:执行SQL补全权限:

INSERT INTO role_permissions (role_id, permission_id) SELECT r.id, p.id FROM roles r, permissions p WHERE r.name = 'staff' AND p.name = 'member:list';

4.5 现象:微信支付回调/api/wechat/pay/notify返回{"error":"Invalid request"}

原因:微信支付回调地址必须是https,但本地开发用http;或WECHAT_MCH_KEY(商户API密钥)长度不足32位(微信要求32位随机字符串)
解决:开发期用ngrok生成https隧道;WECHAT_MCH_KEY用openssl rand -base64 24 | tr -d "=+/" | cut -c1-32生成32位密钥


5. 核心模块拆解:会员储值与消费的完整链路实现

会员系统的核心不是CRUD,而是资金流闭环。本项目把“储值→消费→扣减→积分→记录”压缩在MemberController@consume一个方法里,逻辑清晰可追溯。

5.1 储值卡消费的原子操作:事务内完成5件事

当店员在后台选择“张女士-面部护理”,输入金额298,系统执行:

// app/Http/Controllers/MemberController.php public function consume(Request $request) { DB::transaction(function () use ($request) { $member = Member::lockForUpdate()->findOrFail($request->member_id); // 加行锁防并发超扣 // 1. 检查余额是否足够(储值卡优先,次卡次之) if ($member->balance < $request->amount && !$member->has_valid_service_card($request->service_id)) { throw new Exception('余额不足且无有效次卡'); } // 2. 扣减储值余额(若够) if ($member->balance >= $request->amount) { $member->decrement('balance', $request->amount); } else { // 3. 否则消耗次卡(查最近一张未过期、未用完的次卡) $card = $member->cards() ->where('type', 'times') ->where('remaining_times', '>', 0) ->where('expires_at', '>=', now()) ->orderBy('created_at', 'desc') ->first(); if (!$card) throw new Exception('无可用次卡'); $card->decrement('remaining_times'); } // 4. 记录消费订单(含员工ID、服务ID、支付方式) $order = Order::create([ 'member_id' => $member->id, 'employee_id' => auth()->id(), 'service_id' => $request->service_id, 'amount' => $request->amount, 'payment_method' => $request->payment_method, // cash/alipay/wechat ]); // 5. 发放积分(按消费额1:1,满200再送10) $points = $request->amount; if ($request->amount >= 200) $points += 10; $member->increment('points', $points); // 触发微信通知(异步队列更佳,此处简化) $this->notifyWechat($member->open_id, $order->order_no, $request->amount); }); }

这段代码的关键在于DB::transaction包裹全部操作,确保资金安全。如果第4步创建订单失败,前面的余额扣减和次卡消耗会自动回滚——这是美容店最怕的“钱扣了但没记账”。

5.2 积分体系设计:可配置的多级规则,不止于“1元=1分”

积分不是简单乘法,而是支持运营策略的规则引擎。配置存在config/points.php:

return [ 'rules' => [ 'default' => [ 'ratio' => 1, // 1元=1分 'min_amount' => 0, ], 'vip' => [ 'ratio' => 1.5, // VIP会员1.5倍 'min_amount' => 500, ], 'holiday' => [ 'ratio' => 2, // 节假日双倍(需配合日历API) 'date_range' => ['2023-12-24', '2024-01-01'], ], ], 'exchange_rate' => 100, // 100分=1元(用于抵扣) ];

消费时调用PointsCalculator::calculate($member, $amount),自动匹配规则。这样店长在节日活动时,只需改配置文件,不用动代码。

5.3 微信端余额查询:免登录的静默授权方案

用户扫前台二维码,无需关注公众号或输入手机号,直接看到余额:

// resources/js/api/wechat.js export function getMemberBalance() { return axios.get('/api/wechat/member/balance', { headers: { 'X-WX-SIGNATURE': localStorage.getItem('wx_signature') || '' // 签名存在localStorage } }) } // 页面mounted时自动获取 mounted() { this.$wechat.getSignature().then(signature => { localStorage.setItem('wx_signature', signature); this.fetchBalance(); // 此时请求带签名,后端验证后返回余额 }); }

后端验证逻辑在app/Http/Middleware/WechatAuth.php,用overtrue/wechat的validateSignature()方法校验,通过后从$_GET['code']换取OpenID,再查库——整个过程用户无感。


6. 二次开发实战:如何为系统增加“生日月双倍积分”功能

这是美容店老板提得最多的需求之一。改造不涉及架构调整,只需3个文件改动,15分钟可上线。

6.1 第一步:扩展会员模型,增加生日月份判断

在app/Models/Member.php中添加辅助方法:

// app/Models/Member.php public function isBirthdayMonth() { if (!$this->birthday) return false; return $this->birthday->month === now()->month; // Carbon实例,直接比月份 }

6.2 第二步:修改积分计算逻辑,注入生日规则

编辑app/Services/PointsCalculator.php(若不存在则新建):

<?php namespace App\Services; use App\Models\Member; use Illuminate\Support\Facades\Config; class PointsCalculator { public static function calculate(Member $member, float $amount): int { $base = (int) $amount; // 原有VIP规则 if ($member->is_vip && $amount >= 500) { $base = (int) ($amount * 1.5); } // 新增:生日月双倍 if ($member->isBirthdayMonth()) { $base *= 2; } // 节假日规则(原有逻辑) $holidayRules = Config::get('points.rules.holiday', []); if (!empty($holidayRules['date_range']) && now()->between($holidayRules['date_range'][0], $holidayRules['date_range'][1])) { $base *= $holidayRules['ratio']; } return $base; } }

6.3 第三步:在消费逻辑中调用新计算器

回到MemberController@consume,替换原来的积分发放代码:

// 替换原代码中的 $member->increment('points', $points); use App\Services\PointsCalculator; $points = PointsCalculator::calculate($member, $request->amount); $member->increment('points', $points);

6.4 验证与上线:用真实数据跑一遍

  • 验证:用测试会员(生日为本月)消费100元,检查members.points是否增加200;
  • 灰度:先在后台“员工管理”中将店长账号设为is_vip=1,再用其手机号注册会员,生日设为本月,让店长自己试;
  • 上线:git add . && git commit -m "feat: add birthday month double points",推送后git pull,无需重启服务。

从那以后我每次接到“节日活动”“会员等级”“限时折扣”这类需求,都先看config/下有没有对应配置文件,再查app/Services/里有没有可插拔的计算器类——把业务规则从控制器里抽出来,才是可持续迭代的开始。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询