云贝餐饮连锁V3扫码点餐小程序全开源系统:重塑餐饮数字化体验
云贝餐饮连锁V3扫码点餐小程序全开源系统**是一款专为连锁餐饮品牌设计的数字化转型工具。该系统以扫码点餐为核心功能,覆盖堂食、外卖、自提等多种场景,支持多门店数据统一管理,同时提供完整的开源代码,满足企业个性化开发需求
一、云贝餐饮连锁V3系统概述:全开源扫码点餐新标杆
1.1 什么是云贝餐饮连锁V3扫码点餐系统?
**云贝餐饮连锁V3扫码点餐小程序全开源系统**是一款专为连锁餐饮品牌设计的数字化转型工具。该系统以扫码点餐为核心功能,覆盖堂食、外卖、自提等多种场景,支持多门店数据统一管理,同时提供完整的开源代码,满足企业个性化开发需求。
1.2 全开源系统的核心优势
- **自主可控**:100%开放源代码,企业可自由修改功能模块
- **多端适配**:兼容微信小程序、支付宝及H5页面
- **连锁管理**:总部后台统一管控菜品、订单、会员数据
- **成本节约**:无需支付年费,一次部署终身使用
二、云贝V3扫码点餐系统核心功能解析
2.1 智能化扫码点餐流程
通过**云贝餐饮连锁V3扫码点餐小程序**,顾客只需扫描桌台二维码,即可完成:
1. 实时菜单浏览(含图片/视频展示)
2. 多人同步点餐与合并支付
3. 特殊需求备注(如忌口、辣度调节)
4. 后厨自动分单打印
2.2 连锁餐饮管理闭环
多门店管理后台系统为连锁品牌提供:
- **中央厨房管控**:配方标准化与原料损耗分析
- **动态价格策略**:不同区域门店差异化定价
- **会员通存通兑**:跨店消费积分累计
- **大数据看板**:热销菜品排行、客流量预测
2.3 全开源技术架构亮点
| 模块 | 技术方案 | 扩展性 |
|-------|---------|--------|
| 前端 | UniApp跨端框架 | 支持编译至6大平台 |
| 后端 | SpringBoot微服务 | 可对接ERP/CRM系统 |
| 数据库 | MySQL集群+Redis缓存 | 支撑10万级并发 |
| 部署 | Docker容器化 | 快速扩容降本50% |

超管后台setup.js
const name = process['env']['VUE_' + 'APP_' + 'GITHUB_' + 'USER_' + 'NAME']
const noTest = name !== 'test'
const noEmpty = name !== 'undefined'
const dev = process['env']['NODE_' + 'ENV'] === 'dev' + 'elop' + 'ment'
// 加载雪碧图
// import '@/icon'
// 加载全局样式样式
import './styles/public.css'
import '../src/styles/public.css'
export function setupVab(app) {
if ((noTest && noEmpty) || dev) {
// 加载背景
// const Themes = require.context('./styles/background', false, /\.scss$/)
// Themes.keys().map(Themes)
// 加载插件
const Plugins = require.context('./plugins', true, /\.js$/)
Plugins.keys().forEach((key) => Plugins(key).setup(app))
}
}
叫号取餐manifest.jason
{
"name" : "叫号大屏",
"appid" : "__UNI__3E8A075",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* 模块配置 */
"modules" : {},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios打包配置 */
"ios" : {
"dSYMs" : false,
"idfa" : false
},
/* SDK配置 */
"sdkConfigs" : {
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* 快应用特有相关 */
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "wx17ed5fca3bdf53e0",
"setting" : {
"urlCheck" : false,
"minified" : true
},
"usingComponents" : true,
"permission" : {
"scope.userLocation" : {
"desc" : "你的位置信息将用于小程序位置接口的效果展示"
}
},
"requiredPrivateInfos" : [ "getLocation", "chooseLocation" ],
"requiredBackgroundModes" : [ "audio" ],
"lazyCodeLoading" : "requiredComponents"
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2"
}
商家端index.css
page {
height: 100%;
font-size: 28rpx;
color: #333;
background: #F5F5F5;
}
view,
scroll-view,
swiper,
movable-view,
icon,
text,
progress,
button,
checkbox,
form,
input,
label,
picker,
picker-view,
radio,
slider,
switch,
textarea,
navigator,
audio,
image,
video,
map,
canvas,
contact-button {
box-sizing: border-box;
}
button {
position: relative;
display: block;
margin-left: auto;
margin-right: auto;
padding-left: 14px;
padding-right: 14px;
font-size: 18px;
}
::-webkit-scrollbar {
display: none;
}
button::after {
border: none;
}
.uni-page-head {
z-index: 9999 !important;
}
.container {
width: 100%;
height: auto;
}
.p-a {
position: absolute;
}
.p-r {
position: relative;
}
.p-f {
position: fixed;
}
/*底部导航样式*/
.navbar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 115rpx;
background: #fff;
color: #555;
z-index: 2001;
border-top: 1rpx solid rgba(0, 0, 0, 0.1);
}
.navbargator {
height: 100%;
width: 1%;
}
.navbar-view {
width: 100%;
height: 100%;
}
.navbar .navbar-icon {
width: 36rpx;
height: 36rpx;
}
.navbar .navbar-text {
font-size: 22rpx;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-top: 8rpx;
}
/*+-*/
.reducecon {
height: 60rpx;
overflow: hidden;
transition: all 0.3s linear;
opacity: 0;
/* width:0; */
transform: rotate(180deg);
transform: translateX(50rpx);
}
.reducecon.active {
opacity: 1;
min-width: 105rpx;
transform: rotate(0);
}
.cartc {
width: 60rpx;
height: 60rpx;
}
.cartggc {
height: 60rpx;
}
.cartadd {
background: #C2C2C2;
position: relative;
width: 50rpx;
height: 50rpx;
border-radius: 50%;
padding: 0;
margin: 0;
}
.cartadd::after {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
content: "";
height: 5rpx;
width: 20rpx;
background: #fff;
display: block;
border-radius: 10rpx;
}
.cartadd::before {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
content: "";
height: 20rpx;
width: 5rpx;
background: #fff;
display: block;
border-radius: 10rpx;
}
.cartdec {
background: #fff;
position: relative;
width: 50rpx;
height: 50rpx;
border-radius: 50%;
padding: 0;
border: 2rpx solid #C2C2C2;
margin: 0;
}
.cartdecab {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
height: 5rpx;
width: 18rpx;
background: #fff;
display: block;
border-radius: 10rpx;
}
.tac {
text-align: center;
}
.tal {
text-align: left;
}
.tar {
text-align: right;
}
.bb1 {
border-bottom: 1px solid #f6f6f6;
}
.bd1 {
border-bottom: 3rpx dotted #e5e5e5;
}
.bt1 {
border-top: 3rpx dotted #e5e5e5;
}
li {
list-style: none;
}
/*flex布局*/
.dfa {
display: flex;
align-items: center;
}
.dfac {
display: flex;
justify-content: space-around;
align-items: center;
}
.dfbc {
display: flex;
justify-content: space-between;
align-items: center;
}
.flex {
display: -webkit-box;
display: -webkit-flex;
display: flex;
}
.f-row {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-flex-direction: row;
flex-direction: row;
}
.f-col {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
flex-direction: column;
}
.f-c {
display: flex;
align-items: center;
}
/*占比*/
.f-g-0 {
min-width: 0;
flex-grow: 0;
flex-shrink: 0;
}
.f-g-1 {
min-width: 0;
flex-grow: 1;
flex-shrink: 1;
}
.f-1 {
flex: 1;
min-width: 0;
}
.f-s-1 {
flex-shrink: 1;
}
.f-s-0 {
flex-shrink: 0;
}
.f-b-25 {
flex-basis: 25%;
}
/*居中*/
.f-c {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.f-c-c {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.f-x-c {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.f-y-c {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
-ms-grid-row-align: center;
align-items: center;
}
.f-c-xc {
display: flex;
flex-direction: column;
justify-content: center;
}
.f-c-ac {
display: flex;
flex-direction: column;
align-items: center;
}
/*wrap*/
.f-w {
flex-wrap: wrap;
}
.f-raw {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
}
.f-nw {
flex-wrap: nowrap;
}
.b0 {
bottom: 0;
}
/*end*/
.f-e {
display: flex;
align-items: center;
justify-content: flex-end;
}
.f-c-e {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.f-e-c {
display: flex;
justify-content: flex-end;
flex-direction: column;
}
.f-s {
display: flex;
align-items: flex-start;
}
.f-s-ac {
display: flex;
align-items: flex-start;
align-items: center;
}
.f-c-s {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.f-y-e {
display: flex;
align-items: flex-end;
}
.f-x-e {
display: flex;
justify-content: flex-end;
}
.f-x-c {
display: flex;
justify-content: flex-end;
align-items: center;
}
.f-sh {
display: flex;
align-items: stretch;
}
/*space-betwee*/
.f-bt {
display: flex;
justify-content: space-between;
}
.f-x-bt {
display: flex;
justify-content: space-between;
align-items: center;
}
.f-e-bt {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.f-s-bt {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.f-y-bt {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.f-x-ad {
display: flex;
justify-content: space-around;
}
.f-x-c-sa {
display: flex;
align-items: center;
justify-content: space-around;
}
.f-y-ad {
display: flex;
flex-direction: column;
justify-content: space-around;
}
/**/
.f-a-b {
align-items: baseline;
}
.f-c-b {
display: flex;
justify-content: center;
align-items: baseline;
}
.f-y-t {
display: flex;
align-items: flex-start;
}
/* 宽度样式 */
.w100 {
width: 100%;
}
.w50 {
width: 50%;
}
.w45 {
width: 45%;
}
.w20 {
width: 20%;
}
.w30 {
width: 30%;
}
.w33 {
width: 33.33%;
}
.w70 {
width: 70%;
}
.w75 {
width: 75%;
}
.w80 {
width: 80%;
}
.h100 {
height: 100%;
}
.mh100 {
min-height: 100%;
}
.mvh100 {
min-height: 100vh;
}
.h0 {
height: 0;
}
.wh {
width: 100%;
height: 100%;
}
.w100v {
width: 100vw;
}
.h100v {
height: 100vh;
}
/* 字体大小 */
.f10 {
font-size: 20rpx;
}
.f11 {
font-size: 22rpx;
}
.f12 {
font-size: 24rpx;
}
.f13 {
font-size: 26rpx;
}
.f14 {
font-size: 28rpx;
}
.f15 {
font-size: 30rpx;
}
.f16 {
font-size: 32rpx;
}
.f17 {
font-size: 34rpx;
}
.f18 {
font-size: 36rpx;
}
.f20 {
font-size: 40rpx;
}
.f22 {
font-size: 44rpx;
}
.f24 {
font-size: 48rpx;
}
.f26 {
font-size: 52rpx;
}
.f28 {
font-size: 56rpx;
}
.f30 {
font-size: 60rpx;
}
.f32 {
font-size: 64rpx;
}
.f34 {
font-size: 68rpx;
}
.f40 {
font-size: 80rpx;
}
.f70 {
font-size: 140rpx;
}
/* 字体是否加粗 */
.wei {
font-weight: bold;
}
.nowei {
font-weight: normal;
}
.wei4 {
font-weight: 400;
}
.wei5 {
font-weight: 500;
}
.wei6 {
font-weight: 600;
}
/*border-radius*/
.bs4{
border-radius: 8rpx;
}
.bs20 {
border-radius: 40rpx;
overflow: hidden;
}
.bs5 {
border-radius: 10rpx;
overflow: hidden;
}
.bs6 {
border-radius: 12rpx;
overflow: hidden;
}
.bs10 {
border-radius: 20rpx;
overflow: hidden;
}
.bs15 {
border-radius: 30rpx;
overflow: hidden;
}
.bs30 {
border-radius: 60rpx;
overflow: hidden;
}
.bsf {
border-radius: 50%;
overflow: hidden;
}
.o-h {
overflow: hidden;
}
.o-x-s {
overflow-x: scroll;
}
.o-x-s::-webkit-scrollbar {
display: none;
}
.o-y-s {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.o-a {
overflow: auto;
}
.o-v {
overflow: visible;
}
/* 文字颜色 */
.cl {
color: #3d3d3d;
}
.fc {
color: #3d3d3d;
font-weight: 600;
}
.c9 {
color: #999;
}
.c7 {
color: #777;
}
.c6 {
color: #666;
}
.c5 {
color: #555;
}
.c3 {
color: #333;
}
.c0 {
color: #000;
}
.cf {
color: #fff;
}
.cd {
color: #ddd;
}
.ce {
color: #eee;
}
.cef {
color: #efefef;
}
.cb {
color: #bbb;
}
.crb {
color: #FA463D;
}
.cf7 {
color: #fead77;
}
.cfa {
color: #ff4d3a;
}
.cf5f {
color: #FF5F2F;
}
.cf5 {
color: #ef585e;
}
.ce5 {
color: #e5e5e5;
}
.cf70 {
color: #FF7F00;
}
.c8 {
color: #888;
}
.cb2 {
color: #b2b2b2;
}
.cf2 {
color: #f2f2f2;
}
.cd3 {
color: #d3d3d3;
}
/* 背景为白色 */
.bf {
background: #fff;
}
.bfa {
background: #fafafa;
}
.bf5 {
background: #f5f5f5;
}
.bf6 {
background: #f6f6f6;
}
.bf7 {
background: #f7f7f7;
}
.bf8 {
background-color: #f8f8f8;
}
.bec {
background-color: #ECECEC;
}
.bfc {
background: #FAFBFC;
}
.be {
background: #eee;
}
.bf6 {
background: #F6F6F6;
}
.bf9 {
background: #f9f9f9;
}
.bd6 {
background: #D6D6D6;
}
.bdd {
background: #DDDDDD;
}
.b3 {
background: #333;
}
.b9 {
background: #999;
}
.bg0 {
background: #000;
}
.b05 {
background-color: rgba(0, 0, 0, 0.5);
}
.bt {
background: transparent;
}
.br {
background: #f00;
}
.bfbf {
background: #fbf1e5;
}
.bf5f {
background: #FF5F2F;
}
.bf25 {
background: #ff0025;
}
.bb {
background: #2d95ff;
}
.bg {
background: #15c42d;
}
.by {
background: #ffb71c;
}
.be6 {
background: #EFF3F6;
}
.bf2f {
background: #f2f2f2;
}
.b00 {
background: #07C160;
}
.bef {
background: #EF371F;
}
.bf0a {
background: #FF5B0A;
}
.b-l-f4ee {
background: linear-gradient(90deg, #f83144 0%, #ed4e6e 300%);
}
.b-l-f0f0 {
background: linear-gradient(to right, #ff8200, #fd5b00);
}
.b-l-fdf3 {
background: linear-gradient(to right, #f8c10d, #ff9503);
}
.b89d{
background: #F8F9FD;
}
.t-o-e {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.t-d-l {
text-decoration: line-through;
}
.l-h1 {
line-height: 1;
}
.mlr5{
margin: 0 10rpx;
}
.m02 {
margin: 0 20rpx;
}
.mt5 {
margin-top: 10rpx;
}
.mt10 {
margin-top: 20rpx;
}
.mt15 {
margin-top: 30rpx;
}
.mt20 {
margin-top: 40rpx;
}
.mt30 {
margin-top: 60rpx;
}
.mt35 {
margin-top: 70rpx;
}
.mt50 {
margin-top: 100rpx;
}
.mt80 {
margin-top: 160rpx;
}
.mb5 {
margin-bottom: 10rpx;
}
.mb10 {
margin-bottom: 20rpx;
}
.mb12 {
margin-bottom: 24rpx;
}
.mb15 {
margin-bottom: 30rpx;
}
.mb20 {
margin-bottom: 40rpx;
}
.mb30 {
margin-bottom: 60rpx;
}
.mr4 {
margin-right: 8rpx;
}
.mr5 {
margin-right: 10rpx;
}
.mr10 {
margin-right: 20rpx;
}
.mr15 {
margin-right: 30rpx;
}
.ml5 {
margin-left: 10rpx;
}
.ml7 {
margin-left: 14rpx;
}
.ml10 {
margin-left: 20rpx;
}
.ml20 {
margin-left: 40rpx;
}
.ml30 {
margin-left: 60rpx;
}
.ml45 {
margin-left: 90rpx;
}
.p2 {
padding: 20rpx;
}
.p5 {
padding: 10rpx;
}
.p10 {
padding: 20rpx;
}
.p20 {
padding: 40rpx;
}
.p15 {
padding: 30rpx;
}
.p20 {
padding: 40rpx;
}
.pb10 {
padding-bottom: 20rpx;
}
.pb15 {
padding-bottom: 30rpx;
}
.pb70 {
padding-bottom: 70rpx;
}
.pb40 {
padding-bottom: 80rpx;
}
.pb46 {
padding-bottom: 92rpx;
}
.pb60 {
padding-bottom: 120rpx;
}
.pb80 {
padding-bottom: 160rpx;
}
.pt5 {
padding-top: 10rpx;
}
.pt10 {
padding-top: 20rpx
}
.pt15 {
padding-top: 30rpx;
}
.pt50 {
padding-top: 100rpx;
}
.pl5 {
padding-left: 10rpx;
}
.pl10 {
padding-left: 20rpx;
}
.pl20 {
padding-left: 40rpx;
}
.pl30 {
padding-left: 60rpx;
}
.pl40 {
padding-left: 80rpx;
}
.pl50 {
padding-left: 100rpx;
}
.pl80 {
padding-left: 160rpx;
}
.pr5 {
padding-right: 10rpx;
}
.pr10 {
padding-right: 20rpx;
}
.pr15 {
padding-right: 30rpx;
}
.pr20 {
padding-right: 40rpx;
}
.p-0-5 {
padding: 0 10rpx;
}
.p-0-10 {
padding: 0 20rpx;
}
.p-0-20 {
padding: 0 40rpx;
}
.p-5-0 {
padding: 10rpx 0;
}
.p-5-8 {
padding: 10rpx 16rpx;
}
.p-5-10 {
padding: 10rpx 20rpx;
}
.p-5-15 {
padding: 10rpx 30rpx;
}
.p-5-20 {
padding: 10rpx 40rpx;
}
.p-5-25 {
padding: 10rpx 50rpx;
}
.p-10-0 {
padding: 20rpx 0;
}
.p-10-13 {
padding: 20rpx 26rpx;
}
.p-10-15 {
padding: 20rpx 30rpx;
}
.p-10-20 {
padding: 20rpx 40rpx;
}
.p-15-13 {
padding: 30rpx 26rpx;
}
.p-15-20 {
padding: 26rpx 40rpx;
}
.p-15-0 {
padding: 30rpx 0;
}
.p-15-10 {
padding: 30rpx 20rpx;
}
.p-20-0 {
padding: 40rpx 0;
}
.p-20-15 {
padding: 40rpx 30rpx;
}
.p-25-0 {
padding: 50rpx 0;
}
.p-30-0 {
padding: 60rpx 0;
}
.p-30-20 {
padding: 60rpx 40rpx;
}
.p-35-0 {
padding: 70rpx 0;
}
.p-40-0 {
padding: 80rpx 0;
}
.p-45-0 {
padding: 90rpx 0;
}
.p-50-0 {
padding: 100rpx 0;
}
收银台main.js
import App from './App'
import store from './store'
import request from '@/common/request';
import api from '@/api';
// import dLoading from '@/uni_modules/d-loading/components/d-loading/d-loading.vue'
// #ifndef VUE3
import Vue from 'vue'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
store,
...App
})
import uView from '@/uni_modules/uview-ui'
Vue.use(uView)
Vue.prototype.beg = request
Vue.prototype.api = api
// Vue.component('dLoading',dLoading)
app.$mount()
// #endif
// #ifdef VUE3
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
// #endif
小程序index.js
import Vue from 'vue'
import Vuex from 'vuex'
import util from '../common/core/util';
import api from '../common/api';
import utils from '@/common/utils.js'
import { aliAuthCode } from "@/common/wechat-util.js"
Vue.use(Vuex)
import dndc from './dndc'
const store = new Vuex.Store({
state: {
system: {
custom: {
live: '',
takeOut: '',
integral: '',
balance: '',
informationTitle: '',
hbfh: '',
hbmc: '',
inStore: '',
},
powerList: {},
},
user: {},
mobile: uni.getStorageSync('userTel'),
token: '',
isLogin: false,
noLogin: false,
isIpx: false,
scarList: {
out: {
data: []
},
fast: {
data: []
},
ins: {
data: []
},
},
sjxx: {},
sjgood: {},
ingood: {},
layout: {
index: {},
user: {},
nav: {},
copywriting: {},
defaultImg: {},
firing: {},
loadingImg: {},
style: {},
copyright: {},
notice: [],
orderCollect: {},
goodStyle: {},
},
config: {
hasKp: false,
storeBasicSetting: {},
orderSetting: {},
integralSettingcustomTxt: '',
growthSettingcustomTxt: '',
zfbSettingapp_id: '',
basicSetting: {},
storageVal: {},
vipset: {},
storageset: {},
integralSetting: {},
personPayOrderConfig: {},
inStoreOrderConfig:{},
birthdayGift: {},
shopInfo: {},
},
adList:{
index: {},
orderInfo: {},
user: {},
},
},
mutations: {
setUser(state, data) {
uni.setStorageSync('userId', data.id)
data.integral = data.integral || 0
data.balance = data.balance || 0
state.user = data
if (data.mobile) state.isLogin = true
// console.log('setUsersetUsersetUser', data, state.isLogin)
},
setNoLogin(state, data) {
state.noLogin = true
},
setMobile(state, data) {
uni.setStorageSync('userTel', data)
state.mobile = data
},
setToken(state, data) {
// console.log('token', data)
uni.setStorageSync('token', data)
// // #ifdef H5
// window.sessionStorage.setItem('token', data)
// // #endif
state.token = data
},
setSystem(state, data) {
state.system = data
},
setScarList(state, data) {
// console.log('setScarList', data, state.scarList)
if (!data.key) {
state.scarList['out'] = data.data
} else {
state.scarList[data.key] = data.data
}
},
setInCar(state, data) {
state.scarList['ins'] = data.data
},
setSjxx(state, data) {
state.sjxx = data
// uni.setStorageSync('storeId', data.id)
},
setGoods(state, {
params,
data
}) {
if(params.dType == "ins"){
state.ingood = data
}else{
state.sjgood = data
}
},
setLayout(state, {
params,
data
}) {
state.layout[params] = data
// console.log(params,data)
},
setConfig(state, {
params,
data
}) {
state.config[params] = data
},
setadList(state, {
params,
data
}) {
state.adList[params] = data
},
},
getters: {
},
actions: {
async getSystem({
commit,
state
}, params = {}) {
// console.log('state', state, params)
if (!state.system.color || params.get) {
let res = {};
state.isIpx = util.getSb().model.search('iPhone X') != -1 || util.getSb().model.search(
'iPhone 1') != -1 || util
.getSb().model.search('iPhone1') != -1
}
},
async checkBindTel({
commit,
rootState
}, params) {
return new Promise((reslove, reject) => {
if (!rootState.user.userTel) {
uni.showModal({
title: '提示',
content: '请先绑定手机号',
confirmText: '前往绑定',
cancelText: '暂不绑定',
success: res => {
if (res.confirm) {
uni.navigateTo({
url: '/pages/my/login/index',
});
}
}
});
} else {
reslove()
}
})
},
async getLoginInfo({
commit,
state
}, params = {}) {
if (state.user.id) {
return
} else {
return await new Promise(async (resolve, reject) => {
let siteInfo = getApp().globalData.siteInfo
// #ifndef H5
// util.showLoading()
uni.login({
success: async (lres) => {
let res = await util.request({
'url': api.login,
method: 'post',
// mask: 1,
data: {
code: lres.code
}
})
if (res.code == 200) {
if (res?.data?.token) {
if (res.data.session_key) {
getApp().globalData.session_key = res.data
.session_key
}
commit('setToken', res.data.token)
if (res.data && res.data.userInfo) {
commit('setUser', res.data.userInfo)
resolve()
} else {
let resu = await util.request({
'url': api.profix,
data: {}
})
commit('setUser', resu.data)
resolve()
}
}
if (res?.data?.openid) {
getApp().globalData.session_key = res.data
.session_key
getApp().globalData.openid = res.data
.openid
getApp().globalData.unionid = res.data
.unionid
console.log('游客', res.data)
if (res && res.data) {
let openid = res.data.openid,
unionid = res.data.unionid ? res.data
.unionid : ''
let rest = await util.request({
'url': api.wrg,
method: 'post',
data: {
avatar: '',
nickname: `用户_${util.sj()}`,
mobile: '',
openid,
unionid,
}
}).then(async (rest) => {
console.log('rest', rest)
resolve()
rest.data && commit(
'setToken', rest
.data.token)
rest.data && commit(
'setUser', rest.data
.userInfo)
}).catch((e) => {
console.log(e)
})
} else {
uni.showModal({
title: '温馨提示',
content: '请重新进入小程序',
showCancel: false
});
return;
}
} else {
// console.log('已登录', res)
}
} else {
reject()
util.modal('小程序秘钥配置')
}
},
fail: (err) => {
console.log('失败', err)
if (err.errMsg.indexOf('permission') > -1) {
resolve()
}
reject(err)
}
})
// #endif
// #ifdef H5
if (api.platform == 'wechat') {
console.log('%c api.platform ',
'color: white; background-color: #ff55ff', api.platform, uni.getStorageSync('token'))
if (!getApp().globalData.siteInfo.isDev) {
let link = window.location.href,params = utils.getUrlParams(link)
console.log('%c params ', 'color: white; background-color: #ff0000',params)
if(!uni.getStorageSync('token')){
window.location.href = `${getApp().globalData.siteInfo.siteroot}/wechat/${params.uniacid}?refererUrl=${btoa(window.location.href)}`
}
if (!state.user.id && uni.getStorageSync('token')) {
let {
data
} = await util.request({
url: api.profix
})
data && commit('setUser', data)
resolve()
}
if (uni.getStorageSync('token')) return;
return
if (params.code && uni.getStorageSync('bdCode')) {
window.sessionStorage.setItem('wcode', params.code)
}
if (!state.user.id && uni.getStorageSync('token')) {
let {
data
} = await util.request({
'url': api.profix
})
data && commit('setUser', data)
resolve()
}
if (process.env.NODE_ENV === 'development' && params.token) {
commit('setToken', params.token)
let {
data
} = await util.request({
'url': api.profix
})
data && commit('setUser', data)
resolve()
}
if (uni.getStorageSync('token')) return;
if (state.user && state.user.unionid && !uni.getStorageSync(
'token')) return;
if (params.code && window.sessionStorage.getItem('wcode')) {
console.log(params, link)
let rest = await util.request({
'url': api.wcl,
method: 'post',
data: {
code: window.sessionStorage.getItem('wcode') ||
params.code
}
}).then(async (rest) => {
if (rest.data.token) {
commit('setToken', rest.data.token)
// util.message('登录成功', 1, 1000)
commit('setUser', rest.data.userInfo)
resolve()
uni.removeStorageSync('bdCode')
} else if (!rest.data.id && rest.data.openid) {
commit('setUser', rest.data)
uni.removeStorageSync('bdCode')
// uni.navigateTo({
// url: '/pages/other/register',
// });
resolve()
} else {
util.showLoading()
let {
data
} = await util.request({
'url': api.wau,
mask: 1,
data: {
refererUrl: link
}
})
// window.location.href = `${data.split('&')[0]}`
window.location.href = data;
}
}).catch((error) => {
console.log('error', error)
this.loading = false
})
}
}
}else if (api.platform == 'alih5'){
console.log('%c api.platform ','color: white; background-color: #ff55ff', api.platform, uni.getStorageSync('token'))
let ress = await util.request({
'url': api.cMap,
method: 'POST',
ct: 1,
data: {
idents: ['zfbSetting.app_id']
},
})
if (ress) {
commit('setConfig', {
params:'zfbSettingapp_id',
data: ress.data['zfbSetting.app_id']
})
let code = await aliAuthCode()
console.log('code',code)
let res = await util.request({
'url': api.login,
method: 'post',
// mask: 1,
data: {
code: code.authCode
}
})
if (res.code == 200) {
if (res?.data?.token) {
commit('setToken', res.data.token)
if (res.data && res.data.userInfo) {
commit('setUser', res.data.userInfo)
resolve()
} else {
let resu = await util.request({
'url': api.profix,
data: {}
})
commit('setUser', resu.data)
resolve()
}
}
} else {
reject()
util.modal('支付宝秘钥配置')
}
}
} else {
console.log('%c api.platform ','color: white; background-color: #ff55ff', api.platform)
// commit('setUser', {
// id: "1",
// userId: '1',
// openId: "123",
// userName: "测试",
// userTel: "13823515936",
// portrait: ""
// })
// commit('setToken', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3YzLmJreWNtcy5jb20vY2hhbm5lbEFwaS93ZWNoYXQvbG9naW4iLCJpYXQiOjE3MDEwNTEzNTcsImV4cCI6MTcwMjM0NzM1NywibmJmIjoxNzAxMDUxMzU3LCJqdGkiOiJSQVEyMEpyYWhiSVdqZHhDIiwic3ViIjo0NTY4LCJwcnYiOiI4NjY1YWU5Nzc1Y2YyNmY2YjhlNDk2Zjg2ZmE1MzZkNjhkZDcxODE4In0.ymfMqsS9sTE3BwqPy8ctEEXeWbBKzOxZFmjP4MDKNkA')
// commit('setUser', {
// id: 4568,
// nickname: "从前慢",
// mobile: "13823515936",
// })
resolve()
if (api.platform == 'h5') {
return uni.showModal({
title: '提示',
content: '请在微信内打开',
showCancel: false
})
}
}
// #endif
})
}
},
async refreshUser({
commit,
state
}, params) {
// console.log(params)
// return
let {
data
} = await util.request({
'url': params.get ? api.profix : api.xgyh,
method: params.get ? 'GET' : 'POST',
mask: params.nomask ? 0 : 1,
data: params
})
if (params.now) {
data && commit('setUser', data)
} else {
setTimeout(() => {
data && commit('setUser', data)
}, 200);
}
return data
},
async loginBind({
commit,
state
}, params) {
let res = await util.request({
'url': api.bind,
method: 'POST',
mask: 1,
data: params
})
res && commit('setUser', res.data)
return res
},
async clearMycar({
dispatch,
commit,
state
}, params) {
let res = await util.request({
'url': api.qkgwc,
method: 'DELETE',
mask: 1,
data: params
})
// if (res) {
// dispatch('getMycar', {
// // key: params.key,
// storeId: params.storeId,
// })
// }
res && commit('setScarList', {
key: params.key,
data: {
goodsList:[],
goodsCount: 0
}
})
},
async getMycar({
commit,
state
}, params) {
let res = await util.request({
'url': api.wdgwc,
mask: params.mask,
data: params
})
res && commit('setScarList', {
key: params.key,
data: res.data
})
// console.log('index.js,getMycar', params, state.scarList)
},
async supdCar({
dispatch,
commit,
state
}, params) {
let res = await util.request({
'url': api.xggwc,
ct: 1,
method: 'POST',
// mask: 1,
data: params
})
// console.log('index.js,SaveShopCar', params, res)
if (res) {
commit('setScarList', {
key: params.key,
data: res.data.cart
})
return +res.data.count
// dispatch('getMycar', {
// // key: params.key,
// // userId: params.userId,
// // item: params.item,
// storeId: params.storeId,
// lat: params.lat,
// lng: params.lng,
// })
// console.log(this)
}
// console.log('index.js,supdCar', params)
},
async getInCar({
commit,
state
}, params) {
let res = await util.request({
'url': api.ingwc,
mask: params.mask,
data: params
})
res && commit('setInCar', {
key: params.key,
data: res.data
})
},
async supInCar({
dispatch,
commit,
state
}, params) {
let res = await util.request({
'url': api.ingwc,
ct: 1,
method: 'POST',
data: params
})
if (res) {
commit('setInCar', {
data: res.data.cart
})
return +res.data.count
}
},
async clearIncar({
dispatch,
commit,
state
}, params) {
let res = await util.request({
'url': api.inqkgwc,
method: 'DELETE',
mask: 1,
data: params
})
res && commit('setInCar', {
data: {
goodsList:[],
goodsCount: 0
}
})
},
async getSjxx({
commit,
state
}, params) {
let {
data
} = await util.request({
'url': `${api.dplb}/${params.storeId}`,
data:{
lat: params.lat,
lng: params.lng,
}
})
commit('setSjxx', data)
return data
},
async getGoods({
commit,
state
}, params) {
let {
data
} = await util.request({
'url': params.dType == 'ins' ? api.ingoods : api.goods,
data: params
})
commit('setGoods', {data,params,})
return data
},
async getLayout({
commit,
state
}, params = {
page: 'index',
id: '1',
}) {
state.isIpx = util.getSb().model.search('iPhone X') != -1 || util.getSb().model.search(
'iPhone 1') != -1 || util.getSb().model.search('iPhone1') != -1
for (let k in state.layout) {
if (state.layout[k].isget && params.rf!=1) {
return
}
}
let res = await util.request({
url: api.layout,
data: params
})
// console.timeEnd('getLayout')
if (res) {
for (let k in res.data) {
commit('setLayout', {
params:k,
data: {
isget: true,
...res.data[k],
}
})
}
}
},
async getAd({
commit,
state
}, params) {
for (let k in state.adList) {
if (state.adList[k].isget && !params) {
return
}
}
let res = await util.request({
'url': api.gglb,
data: params
})
if (res) {
for (let k in res.data) {
commit('setadList', {
params:k,
data: {
isget: true,
...res.data[k],
}
})
}
}
},
async getConfig({
commit,
state
}, params) {
if (params.ident) {
for (let k of params.ident) {
let nkey = k.replace(/\./g, "")
if (state.config[nkey].isget) {
return
}
}
let res = await util.request({
'url': api.cMap,
method: 'POST',
ct: 1,
data: {
idents: params.ident,
lat: params.lat,
lng: params.lng,
},
})
if (res) {
for (let k of params.ident) {
if(k.indexOf('.')>-1){
let nkey = k.replace(/\./g, "")
commit('setConfig', {
params:nkey,
data: res.data[k]
})
}else{
commit('setConfig', {
params: k,
data: {
isget: true,
...res.data[k]
}
})
}
}
if(res.data.shopInfo){
commit('setConfig', {
params:'shopInfo',
data: res.data.shopInfo
})
}
}
}else {
commit('setConfig', {
params:params.key,
data: params.data,
})
}
},
},
modules: {
dndc,
}
})
export default store
业务后台jsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}
装修后台vite.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import Icons from "unplugin-icons/vite";
import IconsResolver from "unplugin-icons/resolver";
import inject from '@rollup/plugin-inject';
export default defineConfig({
base: "./",
plugins: [
vue(),
inject({
$: "jquery",
jQuery: "jquery",
"windows.jQuery": "jquery"
}),
AutoImport({
include: [
/\.[tj]sx?$/,
/\.vue$/,
/\.vue\?vue/,
/\.md$/,
],
dts: true,
imports: ["vue", "vue-router"],
resolvers: [
ElementPlusResolver(),
IconsResolver({
prefix: "Icon",
}),
],
}),
Components({
dts: true,
resolvers: [
ElementPlusResolver(),
IconsResolver({
enabledCollections: ["ep"],
}),
],
}),
Icons({
autoInstall: true,
}),
],
resolve: {
alias: {
"@": resolve("src"),
},
},
build: {
assetsDir: 'static',
rollupOptions: {
input: {
index: resolve(__dirname, 'index.html'),
},
output: {
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/name-[hash].[ext]'
}
}
},
server: {
host: "0.0.0.0",
port: 10086,
open: true,
},
proxy: {
},
});
三、为什么选择全开源系统?
3.1 对比SaaS平台的显著优势
传统SaaS点餐系统存在**年费高昂**、**数据隔离**、**功能僵化**三大痛点,而**云贝餐饮连锁V3全开源系统**提供:
- **零年费终身授权**:节省年均3-8万元支出
- **数据私有化部署**:保障商业信息安全
- **深度定制开发**:根据品牌调性修改UI/UX
3.2 典型应用场景案例
场景1:快餐连锁店
某中式快餐品牌接入系统后:
- 点餐耗时从5分钟缩短至1.2分钟
- 人力成本降低40%(减少3名前台人员)
- 会员复购率提升27%
场景2:火锅连锁集团
通过自定义开发实现:
- 智能锅底推荐算法
- AR菜品立体展示
- 桌边服务呼叫系统
四、如何快速部署云贝V3系统?
4.1 基础环境要求
| 项目 | 最低配置 | 推荐配置 |
|-------|---------|----------|
| 服务器 | 2核4G | 4核8G集群 |
| 带宽 | 5Mbps | 10Mbps+CDN |
| 存储 | 100GB | 500GB SSD |
4.2 六步落地指南
1. 源码下载与环境检测
2. 数据库初始化配置
3. 支付接口对接(微信/支付宝/银联)
4. 门店信息批量导入
5. 员工权限分级设置
6. 压力测试与灰度发布
---
五、行业影响与未来演进
5.1 推动餐饮业数字化转型
据统计,采用**云贝扫码点餐小程序全开源系统**的商户:
- 平均翻台率提升15%-22%
- 纸质菜单成本年节省超8000元
- 顾客满意度达92.3%
**结语**
云贝餐饮连锁V3扫码点餐小程序全开源系统正在重新定义餐饮服务标准,其开源性、灵活性、高性价比特性,使其成为连锁餐饮企业数字化转型的首选方案。立即获取源码,开启您的智慧餐饮新时代!
更多推荐




所有评论(0)