This commit is contained in:
YeMingfei666 2025-02-24 14:55:26 +08:00
commit 31fe0ba0bb
27 changed files with 891 additions and 17585 deletions

View File

@ -1,13 +1,13 @@
# 代理前缀
VITE_APP_BASE_API = '/prod-api'
# WebSocket端点(可选)
#VITE_APP_WS_ENDPOINT=wss://api.youlai.tech/ws
# 接口地址
VITE_APP_BASE_API = 'https://tapi.cashier.sxczgkj.cn/'
VITE_APP_API_URL=https://tapi.cashier.sxczgkj.cn/ # 正式
# WebSocket 端点(不配置则关闭),线上 ws://api.youlai.tech/ws ,本地 ws://localhost:8989/ws

View File

@ -125,3 +125,35 @@ server {
执行 `pnpm run commit` 唤起 git commit 交互,根据提示完成信息的输入和选择。
![](https://foruda.gitee.com/images/1687755823165218215/c1705416_716974.png)
新版银收客后台管理系统web端
<https://tapi.cashier.sxczgkj.cn/>
admin
12345
可测试功能:
1.店铺管理
店铺管理
角色管理
员工列表
2.系统管理
系统参数
角色管理
菜单管理
小程序页面
版本管理
3.激活码
激活码列表
商品分组
4.线上店铺
店铺装修
5.经营工具
台桌管理
6.应用中心
营销中心
霸王餐
7.商品管理
常用单位
商品分类
商品规格
8.用户管理
用户列表

View File

@ -18,7 +18,7 @@ const MenuApi = {
});
},
get(id: string) {
return request<any, MenuVO>({
return request<any, SysMenu>({
url: `${baseURL}/detail`,
method: "get",
params: { id }
@ -103,101 +103,59 @@ export interface addRequest {
/**
*
*/
activeMenu?: string;
activeMenu?: null | string;
/**
*
*/
cache?: number;
cache: number | string;
/**
*
*/
component?: string;
component: number | string;
/**
*
*/
hidden?: number;
hidden: number | string;
/**
*
*/
icon?: string;
icon: string;
/**
*
*/
iFrame?: number;
iFrame: number | string;
/**
*
*/
menuSort?: number;
menuSort: number;
/**
*
*/
name: string;
/**
*
*/
path?: string;
path: number | string;
/**
*
*/
permission?: string;
permission?: null | string;
/**
*
*/
pid?: number;
title: string;
pid?: number | string;
title: string | string;
/**
* 0 1 2
*/
type: number | null;
type: number | string;
[property: string]: any;
}
/**
* MenuEditDTO
*/
export interface editRequest {
/**
* 0 1 2
*/
type: number;
/**
*
*/
activeMenu?: string;
/**
*
*/
cache?: number;
/**
*
*/
component?: string;
/**
*
*/
hidden?: number;
/**
*
*/
icon?: string;
export interface editRequest extends addRequest {
id: number | string;
/**
*
*/
iFrame?: number;
/**
*
*/
menuSort?: number;
/**
*
*/
path?: string;
/**
*
*/
permission?: string;
/**
*
*/
pid: number | string | null;
title: string;
[property: string]: any;
}
/**
@ -305,4 +263,94 @@ export interface MenuVO {
*/
updateTime?: string;
[property: string]: any;
}
/**
*
*
* CzgResult«SysMenu»
*/
export interface SysMenu {
/**
*
*/
activeMenu?: null | string;
/**
*
*/
cache?: boolean | null;
/**
*
*/
component?: null | string;
/**
*
*/
createBy?: null | string;
/**
*
*/
createTime?: null | string;
/**
*
*/
hidden?: boolean | null;
/**
*
*/
icon?: null | string;
/**
*
*/
iFrame?: boolean | null;
/**
* 使 01
*/
isShop?: number | null;
/**
* ID
*/
menuId?: number | null;
/**
*
*/
menuSort?: number | null;
/**
*
*/
name?: null | string;
/**
*
*/
path?: null | string;
/**
*
*/
permission?: null | string;
/**
* ID
*/
pid?: number | null;
/**
*
*/
subCount?: number | null;
/**
*
*/
title?: null | string;
/**
* 0 1 3
*/
type?: number | null;
/**
*
*/
updateBy?: null | string;
/**
*
*/
updateTime?: null | string;
[property: string]: any;
}

View File

@ -24,9 +24,23 @@ const ShopApi = {
data,
});
},
get(params: getRequest) {
return request<any, ShopInfo>({
url: `${baseURL}/detail`,
method: "get",
params
});
}
};
export default ShopApi;
export interface getRequest {
/**
* id
*/
id?: string | number;
[property: string]: any;
}
/**
* ShopInfoEditDTO
@ -58,3 +72,202 @@ export interface PageQuery {
status?: number;
[property: string]: any;
}
/**
* ShopInfo
*/
export interface ShopInfo {
/**
*
*/
address?: null | string;
/**
*
*/
article?: null | string;
/**
*
*/
backImg?: null | string;
/**
*
*/
bindAccount?: null | string;
/**
*
*/
bookingSms?: null | string;
/**
* ()
*/
businessEndDay?: null | string;
/**
* ()
*/
businessStartDay?: null | string;
/**
*
*/
businessTime?: null | string;
/**
*
*/
chainName?: null | string;
/**
*
*/
cities?: null | string;
/**
* all- vip-
*/
consumeColony?: null | string;
/**
*
*/
contactName?: null | string;
/**
*
*/
coverImg?: null | string;
createTime?: null | string;
/**
*
*/
detail?: null | string;
/**
* /
*/
districts?: null | string;
/**
* dine-in take-out
*/
eatModel?: null | string;
/**
*
*/
expireTime?: null | string;
/**
*
*/
frontImg?: null | string;
/**
* 使 sys_user id
*/
id?: number | null;
/**
*
*/
isAccountPay?: number | null;
/**
* 1 0
*/
isCustomAmount?: number | null;
/**
* 1 0
*/
isMemberInPwd?: number | null;
/**
* 01
*/
isMemberPrice?: number | null;
/**
* 退 1 0
*/
isMemberReturnPwd?: number | null;
/**
* 退 1 0
*/
isReturnPwd?: number | null;
/**
* 01
*/
isTableFee?: number | null;
/**
*
*/
lat?: null | string;
/**
*
*/
lng?: null | string;
/**
* logo
*/
logo?: null | string;
/**
* id
*/
mainId?: number | null;
/**
* 0 1 2
*/
onSale?: number | null;
/**
*
*/
operationPwd?: null | string;
/**
*
*/
paymentQrcode?: null | string;
/**
*
*/
phone?: null | string;
/**
* trial试用版release正式
*/
profiles?: null | string;
/**
*
*/
provinces?: null | string;
registerType?: null | string;
/**
*
*/
sdType?: null | string;
/**
*
*/
shopName?: null | string;
/**
*
*/
shopQrcode?: null | string;
/**
* --only --chain--join type
*/
shopType?: null | string;
/**
* ()
*/
smallQrcode?: null | string;
/**
* -1 0-1
*/
status?: number | null;
/**
*
*/
subTitle?: null | string;
/**
*
*/
tableFee?: number | null;
/**
*
*/
tag?: null | string;
/**
*
*/
taxAmount?: null | string;
/**
* 0 1, 1 0
*/
tubeType?: number | null;
updateTime?: null | string;
[property: string]: any;
}

View File

@ -126,7 +126,7 @@ export const constantRoutes: RouteRecordRaw[] = [
},
{
path: "role",
component: () => import("@/views/shop/role.vue"),
component: () => import("@/views/admim/system/role/index.vue"),
name: "shopRole",
meta: {
title: "角色管理",

View File

@ -3,6 +3,7 @@ import { usePermissionStoreHook } from "@/store/modules/permission";
import { useDictStoreHook } from "@/store/modules/dict";
import AuthAPI, { type loginRequest } from "@/api/account/login";
import ShopApi from "@/api/account/shop";
import UserAPI, { type UserInfo } from "@/api/system/user";
import { setToken, setRefreshToken, getRefreshToken, clearToken } from "@/utils/auth";
@ -12,7 +13,9 @@ export const useUserStore = defineStore("user", () => {
const promissionList = useStorage<string[]>("promissionList", [] as string[]);
localStorage.setItem("shopId", "" + userInfo.value.shopId);
if (userInfo.value.shopId) {
getUserInfo()
}
/**
*
*
@ -43,15 +46,16 @@ export const useUserStore = defineStore("user", () => {
*/
function getUserInfo() {
return new Promise<UserInfo>((resolve, reject) => {
UserAPI.getInfo(userInfo.value.shopId)
ShopApi.get({ id: userInfo.value.shopId })
.then((data) => {
if (!data) {
reject("Verification failed, please Login again.");
return;
}
localStorage.setItem("shopId", "" + userInfo.value.shopId);
Object.assign(userInfo.value, { ...data });
resolve(data);
console.log("获取用户信息", data);
Object.assign(userInfo.value, { ...data, roles: [], promissionList: [], shopId: userInfo.value.shopId });
resolve(userInfo.value);
})
.catch((error) => {
reject(error);

View File

@ -58,19 +58,17 @@ class WebSocketManager {
this.client.onopen = () => {
this.connected = true;
console.log("WebSocket 连接已建立");
ElNotification.success('WebSocket 连接已建立')
// ElNotification.success('WebSocket 连接已建立')
this.sendMessage(this.initParams)
};
this.client.onclose = () => {
if (!this.connected) {
ElMessageBox.alert('WebSocket 连接已断开', 'Title', {
// if you want to disable its autofocus
// autofocus: false,
confirmButtonText: '立即重连',
callback: () => {
this.sendMessage(this.initParams)
},
})
// ElMessageBox.alert('WebSocket 连接已断开', 'Title', {
// confirmButtonText: '立即重连',
// callback: () => {
// this.sendMessage(this.initParams)
// },
// })
}
this.connected = false;
console.log("WebSocket 连接已断开");
@ -78,19 +76,17 @@ class WebSocketManager {
};
this.client.onerror = (error) => {
console.error("WebSocket 发生错误:", error);
ElNotification({
title: "提示",
message: "WebSocket 发生错误",
type: "error",
});
ElMessageBox.alert('WebSocket 发生错误', 'Title', {
// if you want to disable its autofocus
// autofocus: false,
confirmButtonText: '立即重连',
callback: () => {
this.sendMessage(this.initParams)
},
})
// ElNotification({
// title: "提示",
// message: "WebSocket 发生错误",
// type: "error",
// });
// ElMessageBox.alert('WebSocket 发生错误', 'Title', {
// confirmButtonText: '立即重连',
// callback: () => {
// this.sendMessage(this.initParams)
// },
// })
};
this.client.onmessage = (event) => {
const message = event.data;

View File

@ -162,9 +162,14 @@
<el-radio :value="2">接口</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="formData.iFrame == 1" label="外链地址" prop="path">
<el-input v-model="formData.path" placeholder="请输入外链完整路径" />
<el-form-item label="是否外链" prop="path">
<el-switch
v-model="formData.iFrame"
:active-value="1"
:inactive-value="0"
active-text="是"
inactive-text="否"
/>
</el-form-item>
<el-form-item v-if="formData.type == MenuTypeEnum.MENU" prop="name">
@ -237,8 +242,8 @@
<el-form-item v-if="formData.type === MenuTypeEnum.MENU" label="缓存页面">
<el-radio-group v-model="formData.cache">
<el-radio :value="1">开启</el-radio>
<el-radio :value="0">关闭</el-radio>
<el-radio :value="true">开启</el-radio>
<el-radio :value="false">关闭</el-radio>
</el-radio-group>
</el-form-item>
@ -265,9 +270,9 @@
<icon-select v-model="formData.icon" />
</el-form-item>
<el-form-item v-if="formData.type == MenuTypeEnum.MENU" label="跳转路由">
<!-- <el-form-item v-if="formData.type == MenuTypeEnum.MENU" label="跳转路由">
<el-input v-model="formData.redirect" placeholder="跳转路由" />
</el-form-item>
</el-form-item> -->
</el-form>
<template #footer>
@ -286,7 +291,7 @@ defineOptions({
inheritAttrs: false,
});
import MenuAPI, { getListRequest, editRequest, addRequest, MenuVO } from "@/api/account/menu";
import MenuAPI, { getListRequest, MenuVO, editRequest } from "@/api/account/menu";
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
const queryFormRef = ref();
@ -305,21 +310,22 @@ const menuTableData = ref<MenuVO[]>([]);
//
const menuOptions = ref<OptionType[]>([]);
//
{
}
const initialeditRequestData = ref<editRequest>({
id: "",
pid: "",
pid: "0",
hidden: 0,
menuSort: 1,
type: 0, //
alwaysShow: 0,
cache: 1,
params: [],
alwaysShow: false,
cache: 0,
title: "",
icon: "",
iFrame: 0,
permission: "",
path: "",
component: "",
name: "",
});
//
const formData = ref({ ...initialeditRequestData.value });
@ -393,19 +399,26 @@ function handleOpenDialog(pid?: string, menuId?: string) {
dialog.title = "编辑菜单";
MenuAPI.get(menuId).then((data) => {
console.log(data);
initialeditRequestData.value = {
...data,
};
data.iFrame;
formData.value = {
...data,
id: data.id || "",
pid: data.pid || "0",
cache: data.cache ? 1 : 0,
hidden: data.hidden ? 1 : 0,
pid: !pid ? "0" : data.pid,
component: data.component || "",
icon: data.icon || "",
iFrame: data.iFrame ? 1 : 0,
menuSort: data.menuSort ?? 0, // Ensure menuSort is always a number
name: data.name || "", // Ensure name is always a string
path: data.path || "", // Ensure path is always a string
title: data.title || "", // Ensure title is always a string
type: data.type ?? 0, // Ensure type is always a number
};
});
} else {
dialog.title = "新增菜单";
formData.value.pid = pid?.toString();
formData.value.pid = pid ? pid : "0";
}
});
}
@ -438,7 +451,7 @@ function handleSubmit() {
...formData.value,
cache: formData.value.cache ? 1 : 0,
hidden: formData.value.hidden ? 1 : 0,
pid: formData.value.pid == 0 ? null : formData.value.pid,
pid: formData.value.pid == 0 ? undefined : String(formData.value.pid),
};
if (menuId) {
//
@ -496,17 +509,19 @@ function resetForm() {
editRequestRef.value.clearValidate();
formData.value = {
id: "",
pid: "",
pid: "0",
hidden: 0,
menuSort: 1,
type: 0, //
alwaysShow: 0,
cache: 1,
params: [],
alwaysShow: false,
cache: 0,
title: "",
icon: "",
iFrame: 0,
permission: "",
path: "",
component: "",
name: "",
};
}

View File

@ -94,7 +94,7 @@ function returnMenu(menu) {
}
//
async function getMenuPermOptions() {
let arr = await MenuAPI.getList();
let arr = await MenuAPI.getRoutes();
menuPermOptions.value = returnMenu(arr);
}
getMenuPermOptions();

View File

@ -383,7 +383,7 @@ function returnMenu(menu) {
//
async function getMenuPermOptions() {
let arr = await MenuAPI.getList({});
let arr = await MenuAPI.getRoutes();
menuPermOptions.value = returnMenu(arr);
}
getMenuPermOptions();

View File

@ -181,7 +181,7 @@ function handleLogin() {
userStore
.login(user)
.then(async (res) => {
// await userStore.getUserInfo();
await userStore.getUserInfo();
const { path, queryParams } = parseRedirect();
console.log(res, "Denglv返回");
router.push({ path: path, query: queryParams });

View File

@ -402,6 +402,16 @@ function show(obj) {
console.log(obj);
state.form = { ...obj };
}
for (let key in state.rules) {
if (key === "accountName") {
if (obj.id) {
state.rules[key][0].required = false;
} else {
state.rules[key][0].required = true;
}
}
}
console.log(state.rules);
}
function close() {
state.dialogVisible = false;

View File

@ -1,12 +1,13 @@
<template>
<div class="simple-Keyboard-number">
<div class="carts">
<div class="keybord-box">
<div class="box_status">
<slot name="input">
<span> {{ number }}</span>
<span>{{ number }}</span>
</slot>
</div>
<div class="number_list_box">
<slot name="tips"></slot>
<div class="number_list_box" v-if="!disabled">
<div class="yd-keyboard">
<div class="mini-number-box1">
<div class="mini-number">
@ -27,14 +28,10 @@
</div>
<div class="key-line">
<div class="key" @click="clearFunction">
<slot name="clear"> </slot>
<slot name="clear"></slot>
</div>
<div class="key" @click="keyboradAdd('0')">0</div>
<div
class="key"
style="font-size: 31px"
@click="keyboradReduce"
>
<div class="key" style="font-size: 31px" @click="keyboradReduce">
<svg
t="1723453480343"
class="icon"
@ -63,74 +60,91 @@
</div>
</div>
</template>
<script>
export default {
props: {
isCanEmpty: {
type: Boolean,
default: false,
},
maxTips: {
type: String,
default: "输入值超范围",
},
showConfirm: {
type: Boolean,
default: false,
},
max: {
type: Number,
default: Infinity,
},
value: {
type: [String, Number],
default: 0,
},
<script setup>
const props = defineProps({
isCanEmpty: {
type: Boolean,
default: false,
},
data() {
return {
number: 0,
};
maxTips: {
type: String,
default: "输入值超范围",
},
watch: {
value(newval) {
this.number = newval;
},
number(newval) {
this.$emit("input", newval);
},
showConfirm: {
type: Boolean,
default: false,
},
methods: {
clearFunction() {
this.$emit("clear", this.number);
},
keyboradAdd(n) {
if (Number(this.number) == 0) {
return (this.number = n);
}
const newval = this.number + n;
if (newval > this.max) {
return this.$message( this.maxTips);
}
this.number = newval;
},
keyboradReduce() {
if (this.number.length <= 1) {
return (this.number = this.isCanEmpty ? "" : "0");
}
this.number = `${this.number}`.substring(0, this.number.length - 1);
},
keyboradConfirm() {
this.$emit("confirm", this.number);
},
disabled: {
type: Boolean,
default: false,
},
mounted() {
this.number = `${this.value}`;
max: {
type: [Number, String],
default: Infinity,
},
};
value: {
type: [String, Number],
default: 0,
},
//
isFloat: {
type: Boolean,
default: false,
},
});
let number = ref(0);
watch(
() => props.value,
(newval) => {
number.value = newval;
}
);
const emits = defineEmits(["input", "confirm"]);
watch(
() => number.value,
(newval) => {
emits("input", newval);
}
);
function clearFunction() {
if (props.isFloat) {
return keyboradAdd(".");
}
}
function keyboradAdd(n) {
if (n == "." && `${number.value}`.includes(".")) {
return;
}
if (Number(number.value) == 0) {
if (n == ".") {
return (number.value = 0 + n);
}
}
const newval = number.value + n;
if (newval * 1 > props.max * 1) {
return ElMessage.error(this.maxTips);
}
number.value = newval;
}
function keyboradReduce() {
if (number.value.length <= 1) {
return (number.value = props.isCanEmpty ? "" : "0");
}
number.value = `${number.value}`.substring(0, number.value.length - 1);
}
function keyboradConfirm() {
this.$emit("confirm", number.value);
}
onMounted(() => {
number.value = `${props.value}`;
});
</script>
<style lang="scss" scoped>
<style lang="scss" scoped>
.yd-keyboard {
justify-content: center;
margin-bottom: 20px;
@ -159,9 +173,11 @@ export default {
border-radius: 0;
margin-left: 0;
}
.mini-number-box1 .mini-number .key:hover {
background-color: #dcdfe6;
}
.mini-number-box1 .mini-number .key:not(:last-child) {
border-right: 1px solid #dcdfe6;
}
@ -224,6 +240,7 @@ export default {
-ms-user-select: none;
user-select: none;
}
.simple-Keyboard-number,
.simple-Keyboard-weight {
min-width: 410px;
@ -231,6 +248,7 @@ export default {
border-radius: 4px;
overflow: hidden;
}
.submit {
width: 366px;
height: 44px;
@ -249,6 +267,7 @@ export default {
margin-bottom: 40px;
cursor: pointer;
}
.disabled-box {
position: absolute;
inset: 0;
@ -258,21 +277,21 @@ export default {
bottom: 0;
}
.carts {
.keybord-box {
flex-direction: column;
background: #fff;
height: 100%;
}
.carts .title,
.carts {
.keybord-box .title,
.keybord-box {
display: flex;
align-items: center;
width: 100%;
}
.carts .title {
.keybord-box .title {
justify-content: space-between;
height: 64px;
border-bottom: 1px solid #ebebeb;
@ -280,24 +299,23 @@ export default {
padding-top: 30px;
}
.carts .title .left {
.keybord-box .title .left {
font-family: PingFangSC-Medium;
font-weight: 500;
font-size: 18px;
color: #000;
}
.carts .title .right {
.keybord-box .title .right {
font-size: 14.4px;
cursor: pointer;
}
.carts .box_status {
.keybord-box .box_status {
margin-bottom: 20px;
width: 370px;
height: 58px;
background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
@ -313,7 +331,7 @@ export default {
text-align: center;
}
.carts .box_status span {
.keybord-box .box_status span {
padding: 0 5px;
}
</style>

View File

@ -0,0 +1,336 @@
<template>
<div class="select_desk">
<el-dialog width="410px" title="套餐" v-model="show">
<div class="select_desk_dialog u-p-b-20">
<key-board isCanEmpty v-model="number" isFloat @clear="clear">
<template #clear>
<div>.</div>
</template>
<template #input>
<div class="u-font-14 u-row-between u-flex w-full u-text-left">
<div class="">
<div>单价</div>
<div class="u-m-t-10">
<el-tag type="primary" size="medium">{{ price }}/{{ item.unitName }}</el-tag>
</div>
</div>
<div>
<div class="u-font-14">重量</div>
<div class="u-m-t-10">
<el-input
placeholder="请输入重量"
v-model="number"
@input="inputNumber"
@change="inputChange"
@focus="inputFocus"
@blur="inputBlur"
:type="focus ? 'number' : 'text'"
>
<template #append>
{{ item.unitName }}
</template>
</el-input>
</div>
</div>
</div>
</template>
</key-board>
<div class="price u-text-left w-full"> {{ allPrice }}</div>
<div class="confirm_btns u-flex u-m-t-20">
<el-button style="width: 100%" type="primary" size="medium" @click="confirm">
确定
</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
<script setup>
import keyBoard from "./keyboard.vue";
const props = defineProps({
payMoney: {
type: [Number, String],
default: 0,
},
isShowVipPrice: {
type: Boolean,
default: false,
},
});
const state = reactive({
guazhangRen: "",
number: "",
show: false,
hasOpen: false,
loading: false,
tips: "",
focus: false,
data: {},
item: "",
});
const { guazhangRen, number, show, hasOpen, loading, tips, focus, data, item } = toRefs(state);
const price = computed(() => {
if (!item.value) {
return 0;
}
return item.value.lowPrice;
});
const allPrice = computed(() => {
return (price.value * number.value).toFixed(2);
});
function inputFocus() {
focus.value = true;
}
function inputBlur() {
focus.value = false;
}
function inputNumber(e) {
console.log(e);
}
function inputChange(e) {
console.log(e);
}
function clear(e) {
console.log(e);
number.value = "";
item.value = "";
}
const emits = defineEmits(["confirm"]);
function confirm() {
if (number.value * 1 <= 0) {
return ElMessage.error("请输入重量");
}
emits("confirm", item.value, (number.value * 1).toFixed(2));
close();
}
function open(item) {
console.log(item);
item.value = item;
show.value = true;
}
function close() {
show.valuie = false;
number.value = "";
item.value = "";
}
defineExpose({
open,
close,
});
</script>
<style lang="scss" scoped>
::v-deep.el-button {
padding: 12px 20px;
}
::v-deep .carts .box_status {
border: none;
}
::v-deep .select_desk_dialog .el-input__inner {
// border: none;
}
::v-deep .el-input__inner::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
::v-deep .el-input__inner::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
::v-deep .el-button--success {
border-color: #22bf64;
background-color: #22bf64;
}
.select_desk .btn {
height: 34px;
}
.tags {
font-size: 16px;
&.using {
color: rgb(234, 64, 37);
}
&.wait {
color: rgb(252, 236, 79);
}
&.idle {
color: rgb(137, 234, 71);
}
&.closed {
color: rgb(221, 221, 221);
filter: grayscale(1);
}
}
::v-deep .inputs .el-input__inner {
border-color: transparent !important;
color: rgba(0, 0, 0, 0.8);
letter-spacing: 1.25px;
font-size: 20px;
}
.select_desk .select_desk_dialog {
display: flex;
flex-direction: column;
align-items: center;
}
.select_desk .select_desk_dialog .nav {
width: 286px;
height: 38px;
background: #dcf0e8;
justify-content: space-around;
}
.select_desk .select_desk_dialog .nav .li,
.select_desk .select_desk_dialog .nav {
border-radius: 4px;
display: flex;
align-items: center;
}
.select_desk .select_desk_dialog .nav .li {
width: 140px;
height: 34px;
color: #0fc161;
justify-content: center;
font-size: 14px;
cursor: pointer;
}
.select_desk .select_desk_dialog .nav .lion {
background: #0fc161;
color: #fff;
}
.select_desk .select_desk_dialog .inputs {
width: 370px;
line-height: 54px;
margin-top: 24px;
height: 54px;
margin-bottom: 20px;
background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
color: rgba(0, 0, 0, 0.8);
letter-spacing: 1.25px;
text-align: center;
font-size: 20px;
position: relative;
}
.price {
font-size: 18px;
text-align: left;
color: rgb(255, 81, 82);
font-weight: 600;
}
.select_desk .select_desk_dialog .inputs .close {
color: #aaa;
position: absolute;
right: 10px;
height: 30px;
width: 30px;
line-height: 30px;
top: 50%;
margin-top: -15px;
cursor: pointer;
}
.guazhangren {
padding: 12px 10px;
border: 1px solid #dcdfe6;
border-radius: 4px;
margin-top: 20px;
min-height: 58px;
color: #999;
cursor: pointer;
.name {
color: #3f9eff;
}
}
.select_desk .select_desk_dialog .keyboard {
display: flex;
flex-wrap: wrap;
width: 100%;
margin-top: 20px;
margin-bottom: 10px;
border-right: 1px solid #dcdfe6;
border-bottom: 1px solid #dcdfe6;
}
.select_desk .select_desk_dialog .keyboard .li {
height: 60px;
width: 33.333%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: #212121;
cursor: pointer;
user-select: none;
border-left: 1px solid #dcdfe6;
border-top: 1px solid #dcdfe6;
transition: all 0.1s;
}
.select_desk .select_desk_dialog .keyboard .li:hover {
background: #dcdfe6;
}
.select_desk .select_desk_dialog .keyboard .li .icon {
font-size: 1.3em;
}
.select_desk .select_desk_dialog .keyboard .confirm {
height: 140px;
background: #ff9f2e;
position: absolute;
bottom: 0;
right: 0;
border-right: none;
}
.select_desk .select_desk_dialog .keyboard .confirm:hover {
background: #f88502;
}
.confirm_btns {
display: flex;
justify-content: space-between;
width: 100%;
}
.confirm_btns .el-button {
width: 175px;
}
</style>

View File

@ -134,11 +134,18 @@
</div>
</div>
<!-- 多规格选择确认 -->
<dialogGoodsSel ref="refSelSku" @confirm="skuSelConfirm"></dialogGoodsSel>
<!-- 备注 -->
<note ref="refNote" @confirm="noteConfirm"></note>
<!-- 打包数量 -->
<pack ref="refPack" @confirm="packConfirm"></pack>
<!-- 临时菜 -->
<addLingShiCai ref="refAddLingShiCai" @confirm="addLingShiCaiConfirm"></addLingShiCai>
<!-- 改价 -->
<changePrice ref="refChangePrice" @confirm="changePriceConfirm"></changePrice>
<!-- 称重商品 -->
<changeWeight ref="refChangeWeight" @confirm="changeWeightConfirm"></changeWeight>
</div>
</template>
<script setup>
@ -146,6 +153,7 @@ import Controls from "./components/control.vue";
import note from "./components/note.vue";
import pack from "./components/pack.vue";
import changePrice from "./components/popup-cart-changePrice.vue";
import changeWeight from "./components/popup-weight-goods.vue";
import addLingShiCai from "./components/popup-linshiCai.vue";
import GoodsItem from "./components/goods-item.vue";
import dialogGoodsSel from "./components/dialog-goods-sel.vue";
@ -155,6 +163,13 @@ import productApi from "@/api/product/index";
import tableApi from "@/api/account/table";
import $status from "@/views/tool/table/status.js";
//
const refChangeWeight = ref();
function changeWeightConfirm(e) {}
function showWeight(item) {
refChangeWeight.value.open(item);
}
//
const tableSearchText = ref("");
const tableList = ref([]);
@ -307,10 +322,17 @@ function goodsClick(item) {
product_name: "",
remark: "",
});
return;
}
//
if (item.type == "sku") {
refSelSku.value.open(item);
return;
}
//
if (item.type == "weight") {
showWeight(item);
return;
}
}

View File

@ -1,270 +0,0 @@
<template>
<div class="select_desk">
<el-dialog width="410px" title="就餐人数" :visible.sync="show">
<div class="select_desk_dialog u-p-b-20">
<key-board
isCanEmpty
v-model="number"
@clear="clear"
:max="max"
:maxTips=" '最多'+max+'位'"
>
<div slot="clear">清空</div>
<div slot="input" class="u-p-l-20 u-p-r-20 u-flex w-full">
<el-input
placeholder="请输入就餐人数"
v-model="number"
@input="inputNumber"
@change="inputChange"
type="number"
>
<template slot="append"></template>
</el-input>
</div>
</key-board>
<div class="confirm_btns">
<el-button size="medium" @click="close">取消</el-button>
<el-button type="primary" size="medium" @click="confirm"
>确定</el-button
>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import keyBoard from "../keyboard.vue";
export default {
components: { keyBoard },
props:{
max:{
type:Number,
default:99
}
},
data() {
return {
number: "",
show: false,
hasOpen: false,
loading: false,
};
},
watch: {
number(newval) {
if (newval >this.max) {
this.number = this.max;
this.$message("最多只能选择"+this.max+"位就餐人数");
}
// 使
const regex = /^[1-9]\d*$/;
//
if (!regex.test(newval)) {
this.number = newval.substring(0, newval.length - 1);
}
},
},
methods: {
inputNumber(e) {},
inputChange(e) {},
clear(e) {
console.log(e);
this.number = "";
},
confirm() {
if (this.number >this.max) {
return this.$message("最多只能选择"+this.max+"位就餐人数");
}
if (!this.number) {
return this.$message("请选择就餐人数");
}
console.log(this.number)
this.$emit("confirm", this.number);
this.close();
},
open(number) {
this.number = number || "";
this.show = true;
},
close() {
this.show = false;
this.number = "";
},
},
mounted() {},
};
</script>
<style lang="scss" scoped>
::v-deep.el-button {
padding: 12px 20px;
}
::v-deep .el-input__inner::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
::v-deep .el-input__inner::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
::v-deep .el-button--success {
border-color: #22bf64;
background-color: #22bf64;
}
.select_desk .btn {
height: 34px;
}
.tags {
font-size: 16px;
&.using {
color: rgb(234, 64, 37);
}
&.wait {
color: rgb(252, 236, 79);
}
&.idle {
color: rgb(137, 234, 71);
}
&.closed {
color: rgb(221, 221, 221);
filter: grayscale(1);
}
}
::v-deep .inputs .el-input__inner {
border-color: transparent !important;
color: rgba(0, 0, 0, 0.8);
letter-spacing: 1.25px;
font-size: 20px;
}
.select_desk .select_desk_dialog {
display: flex;
flex-direction: column;
align-items: center;
}
.select_desk .select_desk_dialog .nav {
width: 286px;
height: 38px;
background: #dcf0e8;
justify-content: space-around;
}
.select_desk .select_desk_dialog .nav .li,
.select_desk .select_desk_dialog .nav {
border-radius: 4px;
display: flex;
align-items: center;
}
.select_desk .select_desk_dialog .nav .li {
width: 140px;
height: 34px;
color: #0fc161;
justify-content: center;
font-size: 14px;
cursor: pointer;
}
.select_desk .select_desk_dialog .nav .lion {
background: #0fc161;
color: #fff;
}
.select_desk .select_desk_dialog .inputs {
width: 370px;
line-height: 54px;
margin-top: 24px;
height: 54px;
margin-bottom: 20px;
background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
color: rgba(0, 0, 0, 0.8);
letter-spacing: 1.25px;
text-align: center;
font-size: 20px;
position: relative;
}
.select_desk .select_desk_dialog .inputs .close {
color: #aaa;
position: absolute;
right: 10px;
height: 30px;
width: 30px;
line-height: 30px;
top: 50%;
margin-top: -15px;
cursor: pointer;
}
.select_desk .select_desk_dialog .keyboard {
display: flex;
flex-wrap: wrap;
width: 100%;
margin-top: 20px;
margin-bottom: 10px;
border-right: 1px solid #dcdfe6;
border-bottom: 1px solid #dcdfe6;
}
.select_desk .select_desk_dialog .keyboard .li {
height: 60px;
width: 33.333%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: #212121;
cursor: pointer;
user-select: none;
border-left: 1px solid #dcdfe6;
border-top: 1px solid #dcdfe6;
transition: all 0.1s;
}
.select_desk .select_desk_dialog .keyboard .li:hover {
background: #dcdfe6;
}
.select_desk .select_desk_dialog .keyboard .li .icon {
font-size: 1.3em;
}
.select_desk .select_desk_dialog .keyboard .confirm {
height: 140px;
background: #ff9f2e;
position: absolute;
bottom: 0;
right: 0;
border-right: none;
}
.select_desk .select_desk_dialog .keyboard .confirm:hover {
background: #f88502;
}
.confirm_btns {
display: flex;
justify-content: space-between;
width: 100%;
}
.confirm_btns .el-button {
width: 175px;
}
</style>

View File

@ -1,289 +0,0 @@
<template>
<el-dialog title="选择用户" width="850px" :visible.sync="show">
<div class="app-container">
<div class="head-container">
<el-form :model="query" inline>
<el-form-item label="">
<el-input
v-model="query.name"
placeholder="请输入昵称或手机号"
></el-input>
</el-form-item>
<!-- <el-form-item label="是否为会员">
<el-select v-model="query.isVip" placeholder="是否是会员">
<el-option value="" label="全部"></el-option>
<el-option :value="1" label="是"></el-option>
<el-option :value="0" label="否"></el-option>
</el-select>
</el-form-item> -->
<el-form-item>
<div class="flex gap-20">
<el-button type="primary" @click="getTableData" size="medium"
>搜索</el-button
>
<!-- <el-button @click="resetHandle" size="medium">重置</el-button> -->
<el-button @click="noChooseUser" size="medium"
>不选择用户</el-button
>
<!-- <el-button @click="resetHandle" size="medium">新建用户</el-button> -->
</div>
</el-form-item>
</el-form>
</div>
<!-- <div class="head-container">
<el-button type="primary" icon="el-icon-plus" @click="$refs.addActive.show()">
添加活动
</el-button>
</div> -->
<div class="head-container">
<el-table :data="tableData.data" v-loading="tableData.loading" @cell-click="cellClick">
<el-table-column label="ID" prop="id"></el-table-column>
<el-table-column label="用户" prop="headImg" width="200px">
<template v-slot="scope">
<div class="user_info">
<el-image
:src="scope.row.headImg"
style="width: 40px; height: 40px; flex-shrink: 0"
>
<div slot="error" class="image-slot">
<i class="el-icon-user"></i>
</div>
</el-image>
<span class="name">{{ scope.row.nickName }}</span>
</div>
</template>
</el-table-column>
<el-table-column
label="手机号"
prop="telephone"
width="160"
></el-table-column>
<!-- <el-table-column label="性别" prop="sex">
<template v-slot="scope">
<el-tag type="priamry">{{ scope.row.sex || "未知" }}</el-tag>
</template>
</el-table-column> -->
<el-table-column label="会员" prop="isVip">
<template v-slot="scope">
<el-tag type="warning" v-if="scope.row.isVip"
>会员等级{{ scope.row.isVip }}</el-tag
>
<span v-else></span>
</template>
</el-table-column>
<el-table-column label="余额" prop="amount"></el-table-column>
<el-table-column label="积分" prop="totalScore"></el-table-column>
<el-table-column label="操作" width="90" fixed="right">
<template v-slot="scope">
<el-button type="primary" size="mini" @click="choose(scope.row)">选择</el-button>
<!-- <el-button type="text" @click="charge(scope.row)">充值</el-button> -->
</template>
</el-table-column>
</el-table>
</div>
<div class="head-container">
<el-pagination
:total="tableData.total"
:current-page="tableData.page + 1"
:page-size="tableData.size"
@size-change="sizeChange"
@current-change="paginationChange"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
</div>
</div>
</el-dialog>
</template>
<script>
import { queryAllShopUser, queryAllShopInfo } from "@/api/shop";
import dayjs from "dayjs";
let cacheData = {};
export default {
data() {
return {
show: false,
query: {
name: "",
},
shopInfo: {
balanceTotal: 0,
userTotal: 0,
chageTotal: 0,
},
tableData: {
data: [],
page: 0,
size: 10,
loading: false,
total: 0,
},
};
},
filters: {
timeFilter(s) {
return dayjs(s).format("YYYY-MM-DD HH:mm:ss");
},
},
mounted() {
// this.getTableData();
},
methods: {
cellClick(user){
console.log(user)
this.$emit("chooseUser",user)
this.close()
},
noChooseUser(){
this.$emit("chooseUser",null)
this.close()
},
choose(user) {
this.$emit("chooseUser",user)
this.close()
},
charge(user) {
console.log(user);
},
close(){
this.show = false;
},
open() {
this.getTableData();
this.show = true;
},
toPage(type) {
const pages = {
charge: "charge_list",
cost: "cost_list",
};
this.$router.push({
name: pages[type],
});
console.log(pages[type]);
},
//
async getShopInfo() {
try {
const res = await queryAllShopInfo(this.query);
this.shopInfo = res;
} catch (error) {
console.log(error);
}
},
sizeChange() {
this.tableData.page = 0;
this.getTableData();
},
//
async statusChange(e, row) {
try {
this.tableData.loading = true;
const data = { ...row };
data.status = e;
await modityActivate(data);
this.getTableData();
} catch (error) {
console.log(error);
this.tableData.loading = false;
}
},
//
resetHandle() {
this.query.name = "";
this.getTableData();
},
//
paginationChange(e) {
this.tableData.page = e - 1;
this.getTableData();
},
//
async getTableData() {
this.tableData.loading = true;
try {
const res = await queryAllShopUser({
...this.query,
size: this.tableData.size,
page: this.tableData.page + 1,
});
this.tableData.loading = false;
this.tableData.data = res.content;
this.tableData.total = res.totalElements;
} catch (error) {
console.log(error);
}
},
},
};
</script>
<style scoped lang="scss">
.user_info {
display: flex;
align-items: center;
.name {
margin-left: 10px;
}
}
::v-deep .el-input--small .el-input__inner{
height: 36px;
line-height: 36px;
}
::v-deep .image-slot {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #efefef;
font-size: 20px;
color: #999;
}
.card {
background-color: #f5f5f5;
padding: 0 14px;
.title {
font-size: 22px;
padding-top: 14px;
}
.row {
display: flex;
padding: 20px 0;
.item {
flex: 1;
.t {
text-align: center;
color: #555;
}
.n {
color: #000;
font-size: 20px;
font-weight: bold;
padding-top: 6px;
text-align: center;
}
}
}
}
.flex{
display: flex;
align-items: center;
}
.gap-20{
gap: 20px;
}
</style>

View File

@ -1,69 +0,0 @@
<template>
<el-dialog title="下载桌码" width="400px" :visible.sync="dialogVisible" @open="reset">
<el-form ref="form" :model="form" label-position="left">
<el-form-item label="下载数量">
<el-input-number v-model="form.number" :min="1" :max="500"></el-input-number>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" :loading="loading" @click="onSubmitHandle"> </el-button>
</span>
</el-dialog>
</template>
<script>
import { downloadFile } from "@/utils/index";
import { downloadTableCode } from '@/api/table'
export default {
props: {
total: {
type: [Number, String],
default: 1
}
},
data() {
return {
dialogVisible: false,
loading: false,
form: {
number: 1
},
resetForm: ''
}
},
mounted() {
this.resetForm = { ...this.form }
},
methods: {
async onSubmitHandle() {
try {
this.loading = true
const file = await downloadTableCode({
count: this.form.number,
shopId: localStorage.getItem('shopId')
})
this.loading = false
this.dialogVisible = false
this.$message.success('下载成功')
downloadFile(file, "桌码", "zip");
} catch (error) {
this.loading = false
console.log(error);
}
},
show(obj) {
this.dialogVisible = true
// if (obj && obj.id) {
// this.form = JSON.parse(JSON.stringify(obj))
// }
},
close() {
this.dialogVisible = false
},
reset() {
this.form = { ...this.resetForm }
}
}
}
</script>

View File

@ -1,339 +0,0 @@
<template>
<el-dialog width="330px" :title="title" :visible.sync="show">
<div class="simple-Keyboard-number">
<div class="carts">
<div class="pad-14">
<div class="box_status">
<span class="sym"></span>
<el-input v-model="number" type="text" @input="numberInput"></el-input>
<!-- <span class="inputs" :contenteditable="true" @input="numberInput" type="text" >{{ number }}</span> -->
</div>
</div>
<div class="number_list_box">
<div class="yd-keyboard">
<div class="mini-number-box1">
<div class="mini-number">
<div class="key-line">
<div class="key" @click="keyboradAdd('1')">1</div>
<div class="key" @click="keyboradAdd('2')">2</div>
<div class="key" @click="keyboradAdd('3')">3</div>
<div
class="key"
style="font-size: 31px"
@click="keyboradReduce"
>
<svg
t="1723453480343"
class="icon"
viewBox="0 0 1664 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1467"
width="32"
height="32"
>
<path
d="M1526.08 1.6H459.84L41.28 416c-53.76 53.248-53.76 139.52 0 192.64l418.624 414.592v-0.064h1066.176a136.96 136.96 0 0 0 137.6-136.256V137.792a136.96 136.96 0 0 0-137.6-136.192z m-331.392 631.168c26.816 26.624 26.816 69.76 0 96.384-26.88 26.56-70.4 26.56-97.28 0l-121.28-120.128-123.328 122.112a69.76 69.76 0 0 1-97.92 0 68.096 68.096 0 0 1 0-96.96L878.208 512l-121.28-120.064a67.648 67.648 0 0 1 0-96.32c26.88-26.624 70.4-26.624 97.28 0l121.216 120.064 122.24-120.96a69.696 69.696 0 0 1 97.92 0 68.032 68.032 0 0 1 0 96.96l-122.24 120.96 121.344 120.064z"
fill="#333333"
p-id="1468"
></path>
</svg>
</div>
</div>
<div class="key-line">
<div class="key" @click="keyboradAdd('4')">4</div>
<div class="key" @click="keyboradAdd('5')">5</div>
<div class="key" @click="keyboradAdd('6')">6</div>
<div class="key" @click="keyboradAdd('clear')">清空</div>
</div>
<div class="key-line">
<div class="key" @click="keyboradAdd('7')">7</div>
<div class="key" @click="keyboradAdd('8')">8</div>
<div class="key" @click="keyboradAdd('9')">9</div>
<div class="key"></div>
</div>
<div class="key-line">
<div class="key" @click="keyboradAdd('.')">.</div>
<div class="key" @click="keyboradAdd('0')">0</div>
<div class="key" @click="keyboradAdd('00')">00</div>
<div class="key"></div>
</div>
<div class="confirm key" @click="confirm">确认</div>
</div>
</div>
</div>
</div>
<!-- <div class="submit" @click="keyboradConfirm">确认</div> -->
</div>
</div>
</el-dialog>
</template>
<script>
export default {
props: {
title: {
type: String,
default: "支付",
},
value: {
type: [String, Number],
default: 0,
},
},
data() {
return {
number: '0',
show:false
};
},
watch: {
number(newval) {
this.$emit("input", newval);
},
},
methods: {
confirm(){
},
open(){
this.show=true
},
close(){
this.show=false
},
numberInput(val){
console.log(val)
this.number=`${Number(val)}`
},
keyboradAdd(n) {
if (n === "clear") {
return (this.number = '0');
}
if(n==='.'){
return this.number += this.number.includes('.')?'' : '.'
}
if (`${this.number}`.length<=1&&Number(this.number)===0) {
return (this.number = n);
}
this.number += n;
},
keyboradReduce() {
if (this.number.length <= 1) {
return (this.number = this.isCanEmpty ? "" : "0");
}
this.number = this.number.substring(0, this.number.length - 1);
},
keyboradConfirm() {
this.$emit("confirm", this.number);
},
},
mounted() {
this.number = `${this.value}`;
},
};
</script>
<style lang="scss" scoped>
.pad-14 {
padding: 14px;
width: 100%;
}
::v-deep .el-dialog__body {
padding: 0;
}
::v-deep .el-input__inner::-webkit-outer-spin-button{
-webkit-appearance: none;
margin: 0;
}
::v-deep .el-input__inner::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
::v-deep .el-input__inner {
-moz-appearance: textfield;
}
.number_list_box,
.yd-keyboard,
.mini-number,
.mini-number-box1,
.key-line {
width: 100%;
}
.yd-keyboard {
justify-content: center;
}
.mini-number-box1 .mini-number,
.yd-keyboard {
display: flex;
position: relative;
flex-direction: column;
}
.mini-number-box1 .mini-number {
border-top: 1px solid #dcdfe6;
}
.mini-number-box2 {
display: flex;
justify-content: center;
}
.mini-number-box2 .function-button {
display: flex;
flex-direction: column;
}
.key,
.key-line {
display: flex;
justify-content: center;
}
.key {
width: 25%;
height: 70px;
box-sizing: border-box;
background: #fff;
align-items: center;
font-family: PingFangSC-Regular;
font-weight: 400;
font-size: 24px;
color: #212121;
text-align: center;
line-height: 34px;
cursor: pointer;
user-select: none;
}
.key:hover {
background-color: #dcdfe6;
}
.key:not(:last-child) {
border-right: 1px solid #dcdfe6;
}
.key-line:not(:last-child) {
border-bottom: 1px solid #dcdfe6;
}
.confirm {
height: 142px;
width: 25%;
background: #22bf64;
color: #fff;
position: absolute;
bottom: 0;
right: 0;
border-right: none;
}
.confirm:hover {
background: rgba(34, 191, 100, 0.8666666666666667);
}
.simple-Keyboard-number,
.simple-Keyboard-weight {
background: #fff;
border-radius: 4px;
overflow: hidden;
}
.submit {
width: 366px;
height: 44px;
background: #22bf64;
border-radius: 2px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
color: #fff;
font-family: PingFangSC-Regular;
font-weight: 400;
margin-bottom: 40px;
cursor: pointer;
}
.disabled-box {
position: absolute;
inset: 0;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.carts {
flex-direction: column;
background: #fff;
height: 100%;
}
.carts .title,
.carts {
display: flex;
align-items: center;
width: 100%;
}
.carts .title {
justify-content: space-between;
height: 64px;
border-bottom: 1px solid #ebebeb;
padding: 20px;
padding-top: 30px;
}
.carts .title .left {
font-family: PingFangSC-Medium;
font-weight: 500;
font-size: 18px;
color: #000;
}
.carts .title .right {
font-size: 14.4px;
cursor: pointer;
}
.box_status {
box-sizing: border-box;
width: 100%;
background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
padding: 14px;
align-items: flex-end;
font-family: MicrosoftYaHei;
font-size: 20px;
color: rgba(0, 0, 0, 0.8);
letter-spacing: 1.25px;
.sym {
font-size: 24px;
color: #212121;
width: 30px;
margin-bottom: 3px;
}
.inputs {
font-size: 28px;
color: #212121;
outline: none;
line-height: 37px;
border: none;
max-width: 250px;
}
}
::v-deep .el-input--small .el-input__inner{
font-size: 28px;
color: #212121;
outline: none;
line-height: 37px;
border: none;
max-width: 250px;
padding-left: 0;
}
.carts .box_status span {
padding: 0 5px;
}
</style>

View File

@ -1,76 +0,0 @@
<template>
<div>
<div class="title">选择支付方式</div>
<div class="btn_group">
<div class="price_select">
<div class="pay_btns">
<el-button
size="medium"
@click="changeSel(item)"
v-for="(item, index) in list"
:key="index"
:type="sel === item.payType ? 'primary' : ''"
>
{{ item.payName }}
</el-button>
<!-- <el-button size="medium"> 余额支付 </el-button>
<el-button size="medium"> 现金支付 </el-button>
<el-button size="medium"> 挂账 </el-button> -->
</div>
</div>
</div>
</div>
</template>
<script>
import { $getPayType } from "@/api/table";
export default {
props: {
value: {
type: [String, Number],
default: '',
},
},
data() {
return {
list: [],
sel: "",
};
},
watch: {
sel(newval) {
console.log(newval);
this.$emit("input", newval);
},
},
methods: {
changeSel(item) {
this.sel = item.payType;
this.$emit("itemClick", item);
},
async init() {
const res = await $getPayType();
this.list = res.filter(v=>v.isDisplay);
console.log(res[0]);
this.sel = this.sel ? this.sel : res[0].payType;
},
},
mounted() {
this.init();
},
};
</script>
<style lang="scss" scoped>
.title {
font-size: 18px;
color: #000;
font-weight: 600;
padding: 20px 0;
}
.pay_btns .el-button {
margin-left: 0;
margin-right: 10px;
margin-bottom: 10px;
}
</style>

View File

@ -1,269 +0,0 @@
<template>
<el-dialog
title="预约"
:visible.sync="dialogVisible"
width="500px"
@close="reset"
>
<el-form
ref="form"
:model="form"
:rules="rules"
label-width="120px"
label-position="left"
>
<el-form-item label="预约日期" prop="bookingDate">
<!-- <el-date-picker
v-model="form.bookingDate"
type="date"
value-format="yyyy-MM-dd"
:picker-options="pickerOptions"
placeholder="选择预约日期"
style="width: 200px;margin-right: 10px;"
@change="getShopTableList"
/> -->
<el-radio-group
v-model="form.bookingDate"
class="date"
@change="getShopTableList"
>
<el-radio-button
v-for="(item) in dateList"
:key="item.date"
:label="item.date"
>
<div style="font-size: 12px;margin-bottom: 4px;">{{ item.label }} / {{ item.date.substring(8,10) }}</div>
<div style="font-size: 12px;"> {{ item.day }}</div>
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="预约类型" prop="bookingType">
<el-radio-group v-model="form.bookingType" @change="getShopTableList">
<el-radio-button label="lunch">午餐</el-radio-button>
<el-radio-button label="dinner">晚餐</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="就餐时间" prop="bookingTime">
<el-time-picker
v-model="form.bookingTime"
value-format="HH:mm:ss"
placeholder="选择时间"
style="width: 100%;"
/>
</el-form-item>
<el-form-item label="预约桌台" prop="shopTableId">
<el-select v-model="form.shopTableId" placeholder="请选择" style="width: 100%;">
<el-option
v-for="item in shopTableList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="用餐人数" prop="dinerNum">
<el-input-number v-model="form.dinerNum" :min="1" controls-position="right" style="width: 100%;"/>
</el-form-item>
<el-form-item label="订餐人" prop="bookingPerson">
<el-input v-model="form.bookingPerson" style="width: 200px;margin-right: 10px;" placeholder="请输入联系人姓名" />
<el-radio-group v-model="form.gender">
<el-radio-button label="1">先生</el-radio-button>
<el-radio-button label="2">女士</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="联系电话" prop="phoneNumber">
<el-input v-model="form.phoneNumber" oninput="value= value.replace(/[^0-9]/g, '')" maxlength="11" placeholder="请输入联系电话" />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button
type="primary"
:loading="loading"
@click="onSubmitHandle"
> </el-button>
</span>
</el-dialog>
</template>
<script>
import { getShopTableList, makeShopTable } from '@/api/table'
import dayjs from 'dayjs'
export default {
data() {
return {
dialogVisible: false,
resetForm: '',
loading: false,
pickerOptions: {
disabledDate(time) {
return time.getTime() < Date.now() - 8.64e7 // 8.64e71
}
},
dateList: [
{ label: '今', day: '', date: '' },
{ label: '明', day: '', date: '' },
{ label: '后', day: '', date: '' }
],
shopTableList: [],
form: {
bookingDate: '',
bookingType: 'lunch',
shopTableId: null,
dinerNum: 1,
bookingPerson: '',
phoneNumber: '',
gender: '1',
bookingTime: '',
diningType: '普通用餐',
focus: '0',
receiveMarketingSms: '0'
},
rules: {
shopTableId: [
{
required: true,
message: '请选择预约桌台',
trigger: ['blur']
}
],
dinerNum: [
{
required: true,
message: '请选择用餐人数',
trigger: ['blur']
}
],
phoneNumber: [
{
required: true,
message: '请输入联系方式',
trigger: ['blur']
}
],
bookingPerson: [
{
required: true,
message: '请输入订餐人姓名',
trigger: ['blur']
}
],
bookingTime: [
{
required: true,
message: '请选择用餐时间',
trigger: ['change']
}
]
}
}
},
mounted() {
this.resetForm = { ...this.form }
},
methods: {
getWeekdays() {
const today = new Date()
const tomorrow = new Date(today)
const dayAfterTomorrow = new Date(today)
//
tomorrow.setDate(today.getDate() + 1)
dayAfterTomorrow.setDate(today.getDate() + 2)
//
const getDayOfWeek = (date) => {
const days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
return days[date.getDay()]
}
//
const todayWeekday = getDayOfWeek(today)
const tomorrowWeekday = getDayOfWeek(tomorrow)
const dayAfterTomorrowWeekday = getDayOfWeek(dayAfterTomorrow)
this.dateList[0].day = todayWeekday
this.dateList[1].day = tomorrowWeekday
this.dateList[2].day = dayAfterTomorrowWeekday
this.dateList[0].date = dayjs(today).format('YYYY-MM-DD')
this.dateList[1].date = dayjs(tomorrow).format('YYYY-MM-DD')
this.dateList[2].date = dayjs(dayAfterTomorrow).format('YYYY-MM-DD')
this.form.bookingDate = this.dateList[0].date
},
/**
* 获取桌台数据
*/
async getShopTableList() {
this.form.shopTableId = null
const params = {
bookingDate: this.form.bookingDate,
bookingType: this.form.bookingType
}
const res = await getShopTableList(params)
this.shopTableList = res
console.log(res)
},
onSubmitHandle() {
this.$refs.form.validate(async(valid) => {
if (valid) {
this.loading = true
try {
const bookingTime = this.form.bookingDate + ' ' + this.form.bookingTime
const params = {
...this.form,
shopId: localStorage.getItem('shopId')
}
params.bookingTime = bookingTime
const res = await makeShopTable(params)
this.$emit('success', res)
this.close()
this.$notify({
title: '成功',
message: `预约成功`,
type: 'success'
})
this.loading = false
} catch (error) {
this.loading = false
console.log(error)
}
}
})
},
show(obj) {
this.dialogVisible = true
if (obj && obj.id) {
this.form = JSON.parse(JSON.stringify(obj))
}
this.getShopTableList()
this.getWeekdays()
},
close() {
this.dialogVisible = false
},
reset() {
this.form = { ...this.resetForm }
}
}
}
</script>
<style scoped lang="scss">
.date{
::v-deep .el-form-item__content{
// height: 36px;
// display: flex;
// justify-content: space-between;
}
::v-deep .el-radio-button{
height: 100%;
}
::v-deep .el-radio-button__inner{
padding: 4px 20px;
height: 100%;
}
}
</style>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,141 +0,0 @@
<template>
<el-dialog :title="form.id ? '编辑台桌' : '添加台桌'" :visible.sync="dialogVisible" @open="tbShopAreaGet" @close="reset">
<el-form ref="form" :model="form" :rules="rules" label-width="120px" label-position="left">
<el-form-item label="选择区域" prop="areaId">
<el-select v-model="form.areaId" placeholder="请选择区域">
<el-option :label="item.name" :value="item.id" v-for="item in areaList" :key="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="台桌状态" prop="status" v-if="form.id">
<el-select v-model="form.status" placeholder="请选择台桌状态">
<el-option :label="item.label" :value="item.value" v-for="item in status" :key="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="台桌名称">
<el-input v-model="form.name" placeholder="请输入台桌名称"></el-input>
</el-form-item>
<el-form-item label="客座数">
<el-input-number v-model="form.maxCapacity" :min="0" controls-position="right"></el-input-number>
</el-form-item>
<el-form-item label="清台管理">
<el-radio-group v-model="form.autoClear">
<el-radio-button :label="0">手动清台</el-radio-button>
<el-radio-button :label="1">自动清台</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="网络预定开关">
<el-switch v-model="form.isPredate" :active-value="1" :inactive-value="2"></el-switch>
</el-form-item>
<el-form-item label="类型">
<el-radio-group v-model="form.type">
<el-radio-button :label="0">低消</el-radio-button>
<el-radio-button :label="2">计时</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="最低消费" v-if="form.type == 0">
<el-input-number v-model="form.amount" :min="0" controls-position="right"></el-input-number>
</el-form-item>
<el-form-item label="每小时收费" v-if="form.type == 2">
<el-input-number v-model="form.perhour" :min="0" controls-position="right"></el-input-number>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" :loading="loading" @click="onSubmitHandle"> </el-button>
</span>
</el-dialog>
</template>
<script>
import { tbShopTable, tbShopAreaGet } from '@/api/table'
import $status from "../status.js";
export default {
data() {
return {
dialogVisible: false,
resetForm: '',
loading: false,
status:[],
form: {
id: '',
name: '',
areaId: '',
maxCapacity: 0,
isPredate: 1,
type: 2,
perhour: 0,
amount: 0,
autoClear: 1,
},
rules: {
areaId: [
{
required: true,
message: '请选择区域',
trigger: 'blur'
}
]
},
areaList: []
}
},
mounted() {
this.resetForm = { ...this.form }
this.status = Object.keys($status).map(key =>{
return {...$status[key],value:key}
});
},
methods: {
onSubmitHandle() {
this.$refs.form.validate(async valid => {
if (valid) {
this.loading = true
try {
let res = await tbShopTable({
...this.form,
qrcode:this.form.tableId,
shopId: localStorage.getItem('shopId')
}, this.form.id ? 'put' : 'post')
this.$emit('success', res)
this.close()
this.$notify({
title: '成功',
message: `${this.form.id ? '编辑' : '添加'}成功`,
type: 'success'
});
this.loading = false
} catch (error) {
this.loading = false
console.log(error)
}
}
})
},
show(obj) {
this.dialogVisible = true
if (obj && obj.id) {
this.form = JSON.parse(JSON.stringify(obj))
}
},
close() {
this.dialogVisible = false
},
reset() {
this.form = { ...this.resetForm }
},
//
async tbShopAreaGet() {
try {
const { content } = await tbShopAreaGet({
shopId: localStorage.getItem('shopId')
})
this.areaList = content
} catch (error) {
console.log(error);
}
}
}
}
</script>

View File

@ -25,7 +25,7 @@
"allowJs": true,
//
"types": ["node", "vite/client", "element-plus/global", "vuemap"]
"types": ["node", "vite/client", "element-plus/global"]
},
"include": [