<template>
<div class="common-layout">
<el-container>
<el-header><span>餐饮后台管理系统</span><span @click="out">退出</span></el-header>
<el-container>
<el-aside width="200px">
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="vertical"
@select="handleSelect"
>
<div v-for="(item,index) in menu" :key="index">
<router-link :to="{path:item.router}" style="text-decoration: none;">
<el-menu-item :index="item.id" v-if="item.sub.length==0">
<template #title>
<el-icon><component :is="item.icon"></component></el-icon>
<span>{{item.title}}</span>
</template>
</el-menu-item>
</router-link>
<el-sub-menu v-if="item.sub.length > 0" :index="item.id" >
<template #title>
<el-icon>
<component :is="item.icon"></component>
</el-icon>
<span>{{item.title}}</span>
</template>
<div v-for="(items,indexs) in item.sub" :key="indexs" >
<el-menu-item :index="items.id" >{{items.title}}</el-menu-item>
</div>
</el-sub-menu>
</div>
</el-menu>
</el-aside>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import{Histogram,UserFilled,CreditCard,Bowl}from '@element-plus/icons-vue'
import{reactive,ref,onMounted} from 'vue'
import {useRouter} from 'vue-router'
export default{
components:{
Histogram,UserFilled,CreditCard,Bowl
},
setup(){
const router = useRouter()
const activeIndex=ref('1')
const handleSelect =(index)=>{
localStorage.setItem('index',JSON.stringify(index))
}
onMounted(()=>{
activeIndex.value = JSON.parse(localStorage.getItem('index'))
})
const out=()=>{
localStorage.clear()
router.push({name:'login'})
}
const array =[
{id:'1',
title:'数据分析',
router:'',
sub:[],
icon:Histogram
},
{id:'2',
title:'用户列表',
router:'user',
sub:[],
icon:UserFilled
},
{id:'3',
title:'菜品管理',
router:'',
sub:[],
icon:CreditCard
},
{id:'4',
title:'订单管理',
router:'order',
sub:[],
icon:Bowl
},
{id:'5',
title:'员工管理',
router:'',
icon:UserFilled,
sub:[
{
id:'5-1',
title:'员工数据',
router:'',
},
{
id:'5-2',
title:'其他页面',
router:'',
}
],
}
]
const menu =reactive(array)
return {menu,activeIndex,handleSelect,out}
}
}
</script>
<style>
span {
cursor: pointer;
}
.el-header{
background-color: #b3c0d1;
color: var(--el-text-color-primary);
text-align: center;
line-height: 60px;
display: flex;
justify-content: space-between;
}
.el-aside {
background-color: #d3dce6;
color: var(--el-text-color-primary);
text-align: center;
height: 1000px;
}
.el-main {
background-color: #e9eef3;
color: var(--el-text-color-primary);
text-align: center;
}
</style>
<template>
<div class="login">
<div class="login-input">
<h1>扫码点餐</h1>
<p>账号<el-input v-model="account" class="inputflex" placeholder="请输入账号" clearable /></p>
<p>密码<el-input v-model="password" class="inputflex" placeholder="请输入密码" show-password /></p>
<div @click="bian=bian=='登录'?'注册':'登录'">
<p>{{bian}}</p></div>
<div id="btn">
<el-button v-if="bian=='注册'" @click='register' :loading="load" class='btn' type="success">注册</el-button>
<el-button v-else class='btn' @click='signin' :loading="load" type="success">登录</el-button>
</div>
</div>
</div>
</template>
<script>
import {reactive,toRefs,getCurrentInstance} from 'vue'//getCurrentInstance获取全局方法
import { ElMessage } from 'element-plus'
import {useRouter} from 'vue-router'
export default{
setup(){
const router = useRouter()
const {proxy}=getCurrentInstance()
const user=reactive({
account:'',
password:'',
bian:'登录',
load:false
})
const register = async()=>{
user.load=true
try{
const obj= {account:user.account,password:user.password}
const res=await new proxy.$request(proxy.$urls.m().register,obj).modepost()//vue3没有this只有proxy
console.log(res)
if(res.status!=200){
new proxy.$tips(res.data.msg,'warning').msg()
}else{
user.bian="注册"}
user.load=false
}catch(e){
user.load=false
}
}
const signin= async()=>{
user.load=true
const obj={account:user.account,password:user.password}
try{
const res=await new proxy.$request(proxy.$urls.m().login,obj).modepost()//vue3没有this只有proxy
console.log(res)
if(res.status!=200){
new proxy.$tips(res.data.msg,'warning').msg()
}else{
localStorage.setItem('token',res.data.data.token)
router.push({name:'index'})
}
user.load=false
}catch(e){
user.load=false
}
}
return {...toRefs(user),register,signin}
}
}
</script>
<style>
@import url("../../../style/style.css");
</style>
<template>
<div >
<el-table :data="userarray" style="width: 100%">
<el-table-column prop="time" label="注册时间" min-width="100" align='center' />
<el-table-column prop="name" label="姓名" min-width="100" align='center'/>
<el-table-column prop="sex" label="性别" min-width="100" align='center'/>
<el-table-column prop="head" label="相片" min-width="100" align='center'>
<template #default="scope">
<el-image
style="width: 50px; height: 50px"
:src="scope.row.head"
fit='cover'
:preview-src-list="[scope.row.head]"
lazy
></el-image>
</template>
</el-table-column>
<el-table-column prop="position" label="职业" min-width="100" align='center'/>
</el-table>
<el-pagination background layout="prev, pager, next"
:total="total"
:hide-on-single-page='true'
:pager-count="5"
:page-size="10"
@current-change="currentchange"
>
</el-pagination>
</div>
</template>
<script>
import {onMounted,getCurrentInstance,reactive,toRefs}from'vue'
export default{
setup(){
const {proxy}=getCurrentInstance()
const datas=reactive({
userarray:[],
total:0,
page:0
})
onMounted(()=>{
userlist()
})
async function userlist(){
try{
const res = await new proxy.$request(proxy.$urls.m().pulluserlist + '?page=' + datas.page).modeget()
datas.userarray = res.data.data.result
datas.total = res.data.data.total
console.log(res)
}catch(e){
new proxy.$tips('服务器发生错误','error').mess_age()
}
}
const currentchange=(e)=>{
datas.page=e-1
userlist()
}
return {currentchange,...toRefs(datas)}
}
}
</script>
<style>
</style>
<template>
<div class="ordering" v-loading.fullscreen.lock="Loading">
<div class="heading">订单管理</div>
<div class="query-view">
<!-- 日期选择器 -->
<div class="quotation-query">
<div class="quotation-title">交易时间</div>
<div>
<el-date-picker
v-model="time"
type="daterange"
unlink-panels
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="YYYY-MM-DD"
>
</el-date-picker>
</div>
</div>
<!-- 下拉列表 -->
<div class="quotation-query">
<div class="quotation-title">桌号</div>
<div>
<el-select v-model="sevalue" placeholder="请选择桌号">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
</div>
<!-- 查询按钮 -->
<div class="quotation-query"><el-button type="success" @click="queryFun">查询</el-button></div>
</div>
<!-- 表格 -->
<div>
<el-table :data="table_data" style="width: 100%" >
<el-table-column prop="order_time" label="交易时间" align="center" min-width="100" />
<el-table-column prop="table_number" label="桌号" align="center" min-width="100" />
<el-table-column prop="number_of_diners" label="用餐人数" align="center" min-width="100" />
<el-table-column label="菜品详情" align="center" min-width="100">
<template #default="scope">
<el-button size="small" :loading="scope.$index == deta_load ? true : false" @click="detailed(scope.$index,scope.row._id)">详细菜单</el-button>
</template>
</el-table-column>
<el-table-column prop="sett_amount" align="center" label="交易金额" min-width="100" />
<el-table-column label="交易状态" align="center" min-width="100">
<template #default="scope">
<el-button size="small" v-if="scope.row.transac_status == 'success'" disabled type="danger">已结账</el-button>
<el-button size="small" v-else type="danger">未结账</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination background layout="prev, pager, next"
:total="total"
:hide-on-single-page="true"
@current-change="currentchange"
>
</el-pagination>
</div>
<!-- 弹窗 -->
<Dialog ref="dialog"></Dialog>
</div>
</template>
<script>
import {reactive,toRefs,onMounted,getCurrentInstance,ref} from 'vue'
import Dialog from './component/el-dialog.vue'
import qs from 'qs'
export default{
components:{Dialog},
setup(){
const {proxy} = getCurrentInstance()
const Loading = ref(true)
let dialog = ref()
const oper_data = reactive({
time:[],//选中的时间
sevalue:'',//选中的桌号
options:[],//桌号的数据
table_data:[],// 表格数据
page:0,//第一页的数据
total:0,//数据总得条数
deta_load:-1
})
// 请求数据
onMounted(()=>{
get_order()
})
async function get_order(){
const query = qs.stringify({
page:oper_data.page,
table_number:oper_data.sevalue,
order_time:JSON.stringify(oper_data.time)
})
try{
const TAB = new proxy.$request(proxy.$urls.m().gettable).modeget()
const ORDER = new proxy.$request(proxy.$urls.m().obtainorder + '?' + query).modeget()
const res = await Promise.all([TAB,ORDER])
console.log(TAB)
oper_data.options = res[0].data.data
oper_data.table_data = res[1].data.data.result
oper_data.total = res[1].data.data.total
Loading.value = false
}catch(e){
new proxy.$tips('服务器发生错误','error').mess_age()
}
}
// 分页触发事件
function currentchange(e){
oper_data.page = e - 1
get_order()
}
//点击详细菜单传值给子组件
const detailed = async(index,id)=>{
oper_data.deta_load = index
try{
const res = await new proxy.$request(proxy.$urls.m().vieworder + '?id=' + id).modeget()
dialog.value.popup(res.data.data)
oper_data.deta_load = -1
}catch(e){
oper_data.deta_load = -1
new proxy.$tips('服务器发生错误','error').mess_age()
}
}
// 查询
function queryFun(){
get_order()
}
return {...toRefs(oper_data),currentchange,detailed,dialog,queryFun,Loading}
}
}
</script>
<style scoped="scoped">
::v-deep .el-pagination.is-background .el-pager li:not(.disabled).active {
background-color: #00be06;
color: #fff;
}
</style>
<template>
<el-dialog
v-model="res.dialogVisible"
title="详细菜单"
width="500px"
center
custom-class="hei_dialog"
>
<div class="menu-padd" v-for="(item,index) in res.menu_data" :key='index'>
<div class="Menu-details menu-span">
<span>第{{res.menu_data.length - index}}次下单</span>
</div>
<div v-for="(item_menu,index_menu) in item.goods_list" :key="index_menu">
<div class="Menu-details menu-margin">
<span>{{item_menu.name}}</span>
<span v-if="item_menu.good_specs != ''">{{item_menu.good_specs}}</span>
<span>{{item_menu.quantity}}{{item_menu.unit}}</span>
</div>
</div>
</div>
</el-dialog>
</template>
<script>
import {reactive} from 'vue'
export default{
setup(){
const res = reactive({
dialogVisible:false,
menu_data:[]
})
// 被父组件调用的方法,并且携带值
function popup(val){
res.dialogVisible = true
res.menu_data = val
}
return{res,popup}
}
}
</script>
<style>
.hei_dialog{
height: 600px;
overflow-y: auto;
}
</style>
<template>
<div class="ordering" v-loading.fullscreen.lock="Loading">
<div class="heading">菜品管理</div>
<div class="button-view">
<router-link :to="{name:'upload'}">
<el-button type="success">添加菜品</el-button>
</router-link>
</div>
<div class="modify-button">
<el-table :data="dish_data" style="width: 100%" >
<el-table-column prop="time" label="创建时间" align="center" min-width="100" />
<el-table-column prop="category" label="类目" align="center" min-width="100" />
<el-table-column prop="name" label="菜品名称" align="center" min-width="100" />
<el-table-column label="商品图片" align="center" min-width="100">
<!-- 头像 -->
<template #default="scope">
<el-image
style="width: 40px; height: 40px"
:src="scope.row.image[0].url"
:preview-src-list="[scope.row.image[0].url]"
fit="cover"
:hide-on-click-modal="true"
lazy
></el-image>
</template>
</el-table-column>
<el-table-column prop="unitprice" align="center" label="价格" min-width="100" />
<el-table-column align="center" label="操作" min-width="100">
<template #default="scope">
<el-button size="small" type="primary" @click="Edit(scope.row)">编辑</el-button>
<el-button size="small" type="danger" v-if="scope.row.onsale" @click="offthe_Shelf(scope.row.name,scope.row._id,scope.$index)">下架</el-button>
<el-button size="small" type="danger" disabled v-else>已下架</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination background layout="prev, pager, next"
:total="total"
:hide-on-single-page="true"
@current-change="currentchange"
>
</el-pagination>
</div>
</div>
</template>
<script>
import {reactive,toRefs,onMounted,getCurrentInstance,ref} from 'vue'
import { ElMessageBox } from 'element-plus'
import {useRouter} from 'vue-router'
export default{
setup(){
const {proxy} = getCurrentInstance()
const Loading = ref(true)
const router = useRouter()
const oper_data = reactive({
page:0,
dish_data:[],
total:0
})
// 请求菜品数据
onMounted(()=>{
get_dishes()
})
async function get_dishes(){
try{
const res = await new proxy.$request(proxy.$urls.m().obtaindishes + '?page=' + oper_data.page).modeget()
console.log(res)
oper_data.dish_data = res.data.data.result
oper_data.total = res.data.data.total
Loading.value = false
}catch(e){
new proxy.$tips('服务器发生错误','error').mess_age()
}
}
// 下架菜品提示框
const offthe_Shelf = (name,id,index)=>{
console.log(name,id)
ElMessageBox.confirm(
`确定对 ${name} 下架吗?`,
'提示',
{confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning',center: true}
)
.then(res=>{
console.log('确定')
Shelf(id,index)
})
.catch(err=>{
console.log('取消')
})
}
// 下架菜品
async function Shelf(id,index){
try{
const res = await new proxy.$request(proxy.$urls.m().fromsale + '?id=' + id).modeget()
console.log(res)
oper_data.dish_data[index].onsale = false
}catch(e){
new proxy.$tips('服务器发生错误','error').mess_age()
}
}
// 编辑商品
const Edit = (scope)=>{
const val = JSON.stringify(scope)
router.push({name:'upload',params:{val}})
}
// 分页触发:作业
function currentchange(){
oper_data.page = e - 1
get_dishes()
}
return{...toRefs(oper_data),currentchange,offthe_Shelf,Edit,Loading}
}
}
</script>
<style scoped="scoped">
::v-deep .el-pagination.is-background .el-pager li:not(.disabled).active {
background-color: #00be06;
color: #fff;
}
</style>
<template>
<div class="ordering">
<el-breadcrumb :separator-icon="icon">
<el-breadcrumb-item :to="{ path: '/dishes' }">菜品管理</el-breadcrumb-item>
<el-breadcrumb-item>添加菜品</el-breadcrumb-item>
</el-breadcrumb>
<div class="content-view-ten">
<!-- 菜品类目 -->
<div class="image-view-title">
<div class="image-list">菜品类目</div>
<div>
<el-select v-model="catevalue" placeholder="请选择菜品类目">
<el-option
v-for="item in cate"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
</div>
<!-- 菜品民称 -->
<div class="image-view-title">
<div class="image-list">菜品名称</div>
<el-input v-model="name" placeholder="请输入菜品名称" clearable />
</div>
<!-- 菜品价格(元) -->
<div class="image-view-title">
<div class="image-list">菜品价格(元)</div>
<div class="opload-option">
<el-input type="number" v-model="unitprice" placeholder="请输入菜品价格" clearable />
<el-select v-model="compvalue" placeholder="请选择单位">
<el-option
v-for="item in company"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
<el-input v-if="compvalue == '自定义单位'" v-model="unit" placeholder="请输入自定义单位" clearable />
<div v-if="compvalue == '自定义单位'">
<el-button type="success" style="width: 100%; padding: 12px 20px;"
@click="Dishunit"
:loading="unitload"
>添加自定义单位</el-button>
</div>
</div>
</div>
<!-- 图片上传 -->
<div class="image-view-title">
<div class="image-list">菜品图片</div>
<div>
<el-upload
:action="img_url"
list-type="picture-card"
accept=".jpg,.png,.webp,.jpeg,.jfif"
:on-preview="onpreview"
:on-remove="onremove"
:on-success="onsuccess"
:on-error="onerror"
:on-progress="onprogress"
:before-upload="project"
:file-list="goodsimage"
:limit="1"
>
<el-icon><plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<img style="width: 100%;" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</div>
<!-- 提交 -->
<div class="sub-button">
<el-button type="success" :loading="subload" @click="Submit">提交</el-button>
</div>
</div>
</div>
</template>
<script>
import { ArrowRight,Plus } from '@element-plus/icons-vue'
import {shallowRef,reactive,toRefs,getCurrentInstance,toRaw,onMounted} from 'vue'
import {useRouter,useRoute} from 'vue-router'
export default{
components:{ArrowRight,Plus},
setup(){
const icon = shallowRef(ArrowRight)
const {proxy} = getCurrentInstance()
const img_url = proxy.$urls.m().uploadres
const jump_router = useRouter()//跳转页面
const router = useRoute()//接收值
const oper_data = reactive({
catevalue:'',//选中的菜品类目
name:'',//菜品名称
unitprice:'',//输入的价格
compvalue:'',//选中的单位
unit:'',//选中的自定义单位
cate:[],//菜品类目列表
company:[],//菜品单位列表
goodsimage:[],//上传接收的图片
dialogVisible:false,//是否展示大图
dialogImageUrl:'',//展开大图的图片连接
unitload:false,//自定义单位按钮loading
subload:false,//提交按钮loading
id:'',//该条菜品数据唯一标识_id
})
// 点击文件列表中已上传的文件时的钩子:点击展开大图时触发
const onpreview = (file)=>{
oper_data.dialogImageUrl = toRaw(file).url
oper_data.dialogVisible = true
}
// 文件列表移除文件时的钩子
const onremove = (file, fileList)=>{
oper_data.goodsimage = []
}
// 文件上传成功时的钩子
const onsuccess = (res, file, fileList)=>{
oper_data.goodsimage.push({url:res.data,uid:file.uid})
}
// 文件上传失败时的钩子
const onerror = (err, file, fileList)=>{
console.log(err, file, fileList)
}
// 文件上传时的钩子
const onprogress = (event, file, fileList)=>{}
// 上传文件之前的钩子
const project = (file)=>{}
// 获取菜品类目和单位
onMounted(()=>{
cate_unit()
})
async function cate_unit(){
try{
const CATE = new proxy.$request(proxy.$urls.m().obtaincate).modeget()
const UNIT = new proxy.$request(proxy.$urls.m().obtainunit).modeget()
const res = await Promise.all([CATE,UNIT])
console.log(res)
oper_data.cate = res[0].data.data
oper_data.company = res[1].data.data
oper_data.company.push({label: "自定义单位",unid: "980",value: "自定义单位",_id: "980"})
}catch(e){
//TODO handle the exception
}
}
// 添加自定义单位
const Dishunit = async()=>{
oper_data.unitload = true
const obj = {unit:oper_data.unit}
try{
const res = await new proxy.$request(proxy.$urls.m().dishunit,obj).modepost()
console.log(res)
if(res.status !=200){
new proxy.$tips(res.data.msg,'warning').mess_age()
}else{
new proxy.$tips(res.data.msg,'success').mess_age()
oper_data.compvalue = ''
oper_data.unit = ''
cate_unit()
}
oper_data.unitload = false
}catch(e){
oper_data.unitload = false
new proxy.$tips('服务器发生错误','error').mess_age()
}
}
// 提交上架菜品
const Submit = async()=>{
oper_data.subload = true
const {id,catevalue,name,unitprice,compvalue,goodsimage} = oper_data
const obj = {id,category:catevalue,name,unitprice,
unit:compvalue,image:goodsimage}
console.log(obj)
const URL = id == '' ? proxy.$urls.m().putdishes : proxy.$urls.m().editdishes
try{
const res = await new proxy.$request(URL,obj).modepost()
if(res.status != 200){
new proxy.$tips(res.data.msg,'warning').mess_age()
}else{
new proxy.$tips(res.data.msg,'success').mess_age()
jump_router.push({name:'dishes'})
}
oper_data.subload = false
}catch(e){
oper_data.subload = false
console.log(e)
}
}
// 接收编辑菜品传来的数据
const etid_data = router.params.val
if(etid_data != undefined){
const value = JSON.parse(etid_data)
const {category,name,unitprice,unit,image,_id} = value
oper_data.id = _id,
oper_data.catevalue = category,
oper_data.name = name,
oper_data.unitprice = JSON.stringify(unitprice),
oper_data.compvalue = unit,
oper_data.goodsimage = image
}
return{icon,...toRefs(oper_data),img_url,
onpreview,onremove,onsuccess,onerror,onprogress,
project,Dishunit,Submit
}
}
}
</script>
<style scoped="scoped">
.opload-option{
display: flex;
align-items: center;
justify-content: left;
}
.opload-option div{
width: 25% !important;
margin-right: 5px;
}
.el-button--success{width: 150px;}
</style>
小程序舒尔特方格源代码_我爱的昵称为什么都存在的博客-CSDN博客小程序舒尔特方格源代码,使用uniapp编写https://blog.csdn.net/weixin_50501118/article/details/125075453