Merge branch 'ymf' of e.coding.net:g-cphe0354/cashier/cashier-web into gyq

This commit is contained in:
gyq 2025-07-01 09:59:30 +08:00
commit ceaf5fd2d5
9 changed files with 341 additions and 80 deletions

View File

@ -9,6 +9,12 @@ const MenuApi = {
method: "get",
});
},
getCashMenus() {
return request<any, CashMenu[]>({
url: `${baseURL}/list/cash`,
method: "get",
});
},
/**获取所有菜单 */
getList(data: getListRequest) {
return request<any, MenuVO[]>({
@ -48,6 +54,13 @@ const MenuApi = {
};
export default MenuApi;
export interface CashMenu {
component?: null | string;
menuId: number;
name: null | string;
path?: null | string;
[property: string]: any;
}
/** RouteVO路由对象 */
export interface RouteVO {

View File

@ -33,11 +33,11 @@ const RoleApi = {
});
},
// 获取角色对应的菜单id
getMenu(id: number) {
getMenu(id: number, type: number = 0) {
return request<any, any[]>({
url: `${baseURL}/menu`,
method: "get",
params: { id },
params: { id, type },
});
},
};

98
src/data/menus.ts Normal file
View File

@ -0,0 +1,98 @@
//收银机菜单列表
export const casher_windows_menus = [
{
title: '销售汇总',
icon: '/static/indexImg/PAGE_SALES_SUMMARY.svg',
pageUrl: 'PAGES_SALES_SUMMARY'
},
{
title: '代客下单',
icon: '/static/indexImg/icon-substitute-ordering.svg',
pageUrl: 'PAGES_CREATE_ORDER',
},
{
title: '桌台',
icon: '/static/indexImg/icon-table.svg',
pageUrl: 'PAGES_TABLE'
},
{
title: '商品管理',
icon: '/static/indexImg/icon-product-control.svg',
pageUrl: 'PAGES_PRODUCT'
},
{
title: '分组管理',
icon: '/static/indexImg/goods-group.svg',
pageUrl: 'PAGES_GOODS_GROUP'
},
{
title: '分类管理',
icon: '/static/indexImg/icon-category.svg',
pageUrl: 'PAGES_CATEGORY'
},
{
title: '会员管理',
icon: '/static/indexImg/icon-user.svg',
pageUrl: 'PAGES_USER_CONTROL'
},
{
title: '员工管理',
icon: '/static/indexImg/icon-staff.svg',
pageUrl: 'PAGES_STAFF'
},
{
title: '耗材管理',
icon: '/static/indexImg/PAGE_SALES_SUMMARY.svg',
pageUrl: 'PAGES_SALES_CONSUMABLES'
},
{
title: '订单管理',
icon: '/static/indexImg/icon-order.svg',
pageUrl: 'PAGES_ORDER_INDEX'
},
{
title: '设备管理',
icon: '/static/indexImg/icon-printer.svg',
pageUrl: 'PAGES_PRINTER_INDEX'
},
{
title: '交班',
icon: '/static/indexImg/icon-work.svg',
pageUrl: 'PAGES_WORK_INDEX'
},
{
title: '排队',
icon: '/static/indexImg/icon-line-up.svg',
pageUrl: 'PAGES_LINE_UP'
},
{
title: '霸王餐',
icon: '/static/indexImg/icon-bwc.svg',
pageUrl: 'PAGES_BWC'
},
{
title: '优惠券',
icon: '/static/coupon/icon_coupon.svg',
pageUrl: 'PAGES_COUPON_INDEX'
},
{
title: '订阅通知',
icon: '/static/indexImg/icon-notification.svg',
pageUrl: 'PAGES_NOTIFICATION_INDEX'
},
{
title: '挂账管理',
icon: '/static/indexImg/icon_credit.svg',
pageUrl: 'PAGES_CREDIT_BUYER_INDEX'
},
{
title: '核销管理',
icon: '/static/indexImg/pagewriteoff.svg',
pageUrl: 'PAGES_WEITEOFF'
},
{
title: '退出登录',
icon: '/static/indexImg/icon-login-out.svg',
pageUrl: 'PAGES_LOGIN',
}
]

View File

@ -22,6 +22,11 @@ export const useCartsStore = defineStore("carts", () => {
let dinnerType = ref<string>('dine-in');
//就餐模式 先付 后付
const isPayBefore = computed(() => {
return shopUser.userInfo.registerType == 'before' ? true : false;
});
//是否启用会员价
const useVipPrice = computed(() => {
@ -776,7 +781,7 @@ export const useCartsStore = defineStore("carts", () => {
changeTable,
rotTable,
getGoods,
setGoodsMap
setGoodsMap, isPayBefore
};
});

View File

@ -233,6 +233,49 @@
</el-input>
</el-form-item>
<el-form-item label="小程序路径" prop="miniPath">
<el-input v-model="formData.miniPath" placeholder="pages/index/index" />
</el-form-item>
<el-form-item label="小程序组件" prop="miniComponent">
<el-input v-model="formData.miniComponent" placeholder="小程序组件名称" />
</el-form-item>
<el-form-item label="小程序图标">
<single-image-upload
style="width: 100px; height: 100px"
v-model="formData.miniIcon"
></single-image-upload>
</el-form-item>
<el-form-item label="接口路径" prop="miniPage">
<div class="w-full">
<div>
<el-button @click="apiInfoPush" icon="plus" type="primary">添加</el-button>
</div>
<div class="u-flex u-m-t-10" v-for="(item, index) in formData.apiInfo" :key="index">
<el-form-item label="请求方式" label-position="left">
<el-select v-model="item.method" style="width: 100px">
<el-option
v-for="(item, index) in apiMethodOptions"
:key="index"
:value="item.value"
>
{{ item.label }}
</el-option>
</el-select>
</el-form-item>
<el-form-item label="接口地址" style="flex: 1">
<el-input v-model="item.url" placeholder="支持通配符*和?" />
</el-form-item>
<el-icon
style="margin-left: 10px"
size="20"
color="#F56c6c"
@click="formData.apiInfo.splice(index, 1)"
>
<RemoveFilled />
</el-icon>
</div>
</div>
</el-form-item>
<el-form-item v-if="formData.type !== MenuTypeEnum.BUTTON" prop="hidden" label="显示状态">
<el-radio-group v-model="formData.hidden">
<el-radio :value="1">隐藏</el-radio>
@ -302,7 +345,19 @@ const dialog = reactive({
title: "新增菜单",
visible: false,
});
const apiMethodOptions = ref([
{ value: "All", label: "All" },
{ value: "GET", label: "GET" },
{ value: "POST", label: "POST" },
{ value: "PUT", label: "PUT" },
{ value: "DELETE", label: "DELETE" },
]);
function apiInfoPush() {
if (!formData.value.apiInfo) {
formData.value.apiInfo = [];
}
formData.value.apiInfo.push({ method: "All", url: "" });
}
//
const queryParams = reactive<getListRequest>({});
//
@ -326,6 +381,10 @@ const initialeditRequestData = ref<editRequest>({
path: "",
component: "",
name: "",
miniPath: "",
miniComponent: "",
miniIcon: "",
apiInfo: [],
});
//
const formData = ref({ ...initialeditRequestData.value });
@ -414,6 +473,7 @@ function handleOpenDialog(pid?: string, menuId?: 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
apiInfo: data.apiInfo ? JSON.parse(data.apiInfo) : [],
};
});
} else {

View File

@ -108,10 +108,10 @@
<el-form-item label="描述" prop="description">
<el-input type="textarea" v-model="formData.description" placeholder="描述" />
</el-form-item>
<el-form-item label="菜单分配" prop="menuIdList">
<el-alert title="角色菜单请点击角色列表的分配菜单按钮编辑" type="success" effect="dark" />
<!-- <el-form-item label="菜单分配" prop="menuIdList">
<menuSelect ref="refmenuSelect" v-model="formData.menuIdList"></menuSelect>
</el-form-item>
</el-form-item> -->
</el-form>
<template #footer>
@ -123,58 +123,90 @@
</el-dialog>
<!-- 分配菜单弹窗 -->
<el-drawer
v-model="assignPermDialogVisible"
:title="'【' + checkedRole.name + '】菜单分配'"
size="500"
>
<div class="flex-x-between">
<el-input v-model="permKeywords" clearable class="w-[150px]" placeholder="菜单菜单名称">
<template #prefix>
<Search />
<el-drawer v-model="assignPermDialogVisible" size="500">
<template #header>
<div>
<div>
<h3>
{{ "【" + checkedRole.name + "】菜单分配" }}
</h3>
</div>
<div>
<el-form-item label="平台类型">
<el-radio-group v-model="platformType" @change="handlePlatformTypeChange">
<el-radio :value="0">管理端</el-radio>
<el-radio :value="1">收银机</el-radio>
</el-radio-group>
</el-form-item>
</div>
<div class="flex-x-between">
<el-input v-model="permKeywords" clearable class="w-[150px]" placeholder="菜单菜单名称">
<template #prefix>
<Search />
</template>
</el-input>
<div class="flex-center ml-5">
<el-button type="primary" size="small" plain @click="togglePermTree">
<template #icon>
<Switch />
</template>
{{ isExpanded ? "收缩" : "展开" }}
</el-button>
<el-checkbox
v-model="parentChildLinked"
class="ml-5"
@change="handleparentChildLinkedChange"
>
父子联动
</el-checkbox>
<el-tooltip placement="bottom">
<template #content>
如果只需勾选菜单菜单不需要勾选子菜单或者按钮菜单请关闭父子联动
</template>
<el-icon class="ml-1 color-[--el-color-primary] inline-block cursor-pointer">
<QuestionFilled />
</el-icon>
</el-tooltip>
</div>
</div>
</div>
</template>
<div class="u-relative" style="overflow-x: hidden">
<el-tree
ref="permTreeRef"
node-key="value"
show-checkbox
:data="menuPermOptions"
:default-checked-keys="adminMenuIdList"
:filter-node-method="handlePermFilter"
:default-expand-all="true"
:check-strictly="!parentChildLinked"
class="mt-5"
>
<template #default="{ data }">
{{ data.label }}
</template>
</el-input>
<div class="flex-center ml-5">
<el-button type="primary" size="small" plain @click="togglePermTree">
<template #icon>
<Switch />
</template>
{{ isExpanded ? "收缩" : "展开" }}
</el-button>
<el-checkbox
v-model="parentChildLinked"
class="ml-5"
@change="handleparentChildLinkedChange"
>
父子联动
</el-checkbox>
<el-tooltip placement="bottom">
<template #content>
如果只需勾选菜单菜单不需要勾选子菜单或者按钮菜单请关闭父子联动
</template>
<el-icon class="ml-1 color-[--el-color-primary] inline-block cursor-pointer">
<QuestionFilled />
</el-icon>
</el-tooltip>
</el-tree>
<div
class="cashMenuIdList"
:style="{
transform: `translateX(${(platformType == 1 ? 0 : 1) * 100}%)`,
}"
>
<el-checkbox-group v-model="cashMenuIdList">
<el-checkbox
v-for="(item, index) in casher_windows_menus"
:key="index"
:value="item.menuId"
>
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<el-tree
ref="permTreeRef"
node-key="value"
show-checkbox
:data="menuPermOptions"
:filter-node-method="handlePermFilter"
:default-expand-all="true"
:check-strictly="!parentChildLinked"
class="mt-5"
>
<template #default="{ data }">
{{ data.label }}
</template>
</el-tree>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleAssignPermSubmit"> </el-button>
@ -191,11 +223,11 @@ defineOptions({
inheritAttrs: false,
});
import { useUserStore } from "@/store/modules/user";
// import { casher_windows_menus } from "@/data/menus";
const shopUser = useUserStore();
import menuSelect from "./components/menus.vue";
import RoleApi, { SysRole, addRequest, getListRequest } from "@/api/account/role";
import MenuAPI, { type RouteVO } from "@/api/account/menu";
import MenuAPI, { type RouteVO, CashMenu } from "@/api/account/menu";
const queryFormRef = ref();
const addRequestRef = ref();
@ -221,6 +253,7 @@ const menuPermOptions = ref<RouteVO[]>([]);
const dialog = reactive({
title: "",
visible: false,
row: {},
});
//
const formData = reactive<addRequest>({
@ -232,7 +265,7 @@ const formData = reactive<addRequest>({
menuIdList: [],
description: "",
});
const cashMenuIdList = ref<number[]>([]);
const rules = reactive({
name: [{ required: true, message: "请输入角色名称", trigger: "blur" }],
level: [{ required: false, message: "请输入角色等级", trigger: "blur" }],
@ -251,6 +284,14 @@ const isExpanded = ref(true);
const parentChildLinked = ref(false);
const platformType = ref(0);
function handlePlatformTypeChange(e: string | number | boolean | undefined) {
const value = Number(e); // Ensure the value is cast to a number
console.log("handlePlatformTypeChange");
platformType.value = value;
handleOpenAssignPermDialog(dialog.row);
}
//
function handleQuery() {
loading.value = true;
@ -281,10 +322,11 @@ function handleSelectionChange(selection: any) {
//
async function handleOpenDialog(row: SysRole) {
dialog.visible = true;
dialog.row = row;
if (row && row.id) {
dialog.title = "修改角色";
//
const data = await RoleApi.getMenu(row.id);
const data = await RoleApi.getMenu(row.id, platformType.value);
console.log(data);
Object.assign(formData, row);
formData.menuIdList = data;
@ -329,9 +371,9 @@ function handleSubmit() {
//
function handleCloseDialog() {
addRequestRef.value.resetFields();
addRequestRef.value.clearValidate();
refmenuSelect.value.reset();
addRequestRef.value?.resetFields();
addRequestRef.value?.clearValidate();
refmenuSelect.value?.reset();
formData.id = undefined;
formData.sort = 1;
formData.status = 1;
@ -383,6 +425,13 @@ function returnMenu(menu) {
});
}
const casher_windows_menus = ref<CashMenu[]>([]);
//
async function getCashMenus() {
const res = await MenuAPI.getCashMenus();
console.log(res);
casher_windows_menus.value = res;
}
//
async function getMenuPermOptions() {
let arr =
@ -390,27 +439,43 @@ async function getMenuPermOptions() {
menuPermOptions.value = returnMenu(arr);
}
getMenuPermOptions();
getCashMenus();
const adminMenuIdList = ref<number[]>([]);
//
async function handleOpenAssignPermDialog(row: SysRole) {
const roleId = row.id;
dialog.row = row;
if (roleId) {
assignPermDialogVisible.value = true;
loading.value = true;
checkedRole.value.id = roleId;
checkedRole.value.name = row.name as string;
//
RoleApi.getMenu(roleId)
.then((data) => {
const checkedMenuIds = data;
checkedMenuIds.forEach((menuId) => permTreeRef.value!.setChecked(menuId, true, false));
})
.finally(() => {
loading.value = false;
});
getMenuIds(roleId);
}
}
//
function getMenuIds(roleId: number) {
roleId = roleId ? roleId : dialog.row.id;
if (!roleId) {
return;
}
RoleApi.getMenu(roleId, platformType.value)
.then((data) => {
if (platformType.value == 0) {
const checkedMenuIds = data;
adminMenuIdList.value = data;
// checkedMenuIds.forEach((menuId) => permTreeRef.value!.setChecked(menuId, true, false));
}
if (platformType.value == 1) {
cashMenuIdList.value = data;
}
})
.finally(() => {
loading.value = false;
});
}
//
function handleAssignPermSubmit() {
@ -422,7 +487,13 @@ function handleAssignPermSubmit() {
.map((node: any) => node.value);
loading.value = true;
RoleApi.update(roleId, { name, menuIdList: checkedMenuIds })
RoleApi.update(roleId, {
name,
adminMenuIdList: checkedMenuIds,
cashMenuIdList: cashMenuIdList.value.filter((id) =>
casher_windows_menus.value.find((v) => v.menuId == id)
),
})
.then(() => {
ElMessage.success("分配菜单成功");
assignPermDialogVisible.value = false;
@ -470,6 +541,9 @@ watch(
(val) => {
if (!val) {
permTreeRef.value.setCheckedKeys([]);
platformType.value = 0;
cashMenuIdList.value = [];
adminMenuIdList.value = [];
}
}
);
@ -493,3 +567,14 @@ onMounted(() => {
handleQuery();
});
</script>
<style scoped lang="scss">
.cashMenuIdList {
position: absolute;
box-sizing: border-box;
padding: var(--el-drawer-padding-primary);
inset: 0;
background-color: #fff;
z-index: 2;
transition: all 0.3s ease-in-out;
}
</style>

View File

@ -29,7 +29,7 @@ const contentConfig: IContentConfig = {
// // return OrderApi.edit(data);
// },
pk: "id",
toolbar: ["add"],
toolbar: [],
defaultToolbar: ["refresh", "filter", "search"],
cols: [
{ type: "selection", width: 50, align: "center" },

View File

@ -44,7 +44,7 @@
<!-- 新增 -->
<page-modal ref="addModalRef" :modal-config="addModalConfig" @submit-click="handleSubmitClick">
<template #formFooter>
<h3 style="color: rgb(63, 158, 255)">收银机权限设置</h3>
<!-- <h3 style="color: rgb(63, 158, 255)">收银机权限设置</h3>
<div>
<el-checkbox-group v-model="addPagePathIdList">
<el-checkbox
@ -57,7 +57,7 @@
</div>
<h3 style="color: rgb(63, 158, 255)">员工权限设置</h3>
<selectPermission v-model="addSelPermissionList" :list="permissionList"></selectPermission>
<selectPermission v-model="addSelPermissionList" :list="permissionList"></selectPermission> -->
</template>
</page-modal>
@ -67,7 +67,7 @@
:modal-config="editModalConfig"
@submit-click="handleSubmitClick"
>
<template #formFooter>
<!-- <template #formFooter>
<h3 style="color: rgb(63, 158, 255)">收银机权限设置</h3>
<div>
<el-checkbox-group v-model="editPagePathIdList">
@ -82,7 +82,7 @@
<h3 style="color: rgb(63, 158, 255)">员工权限设置</h3>
<selectPermission v-model="selPermissionList" :list="permissionList"></selectPermission>
</template>
</template> -->
</page-modal>
<!-- 修改密码 -->

View File

@ -45,7 +45,7 @@
<div class="head-container">
<div v-loading="loading" class="table_list">
<div v-for="item in tableList" :key="item.id" class="item"
:style="{ 'background-color': status[item.status].type }">
:style="{ 'background-color': status[item.status] ? status[item.status].type : '' }">
<div class="new-top flex u-row-between">
<div class="u-flex u-flex-1 u-p-r-10">
<span class="name u-line-1" style="max-width: 50px">