店铺管理-》员工管理增加权限设置

This commit is contained in:
YeMingfei666 2025-02-19 11:27:46 +08:00
parent 00ffce98c7
commit 0758aef0fb
15 changed files with 1843 additions and 1526 deletions

View File

@ -6,11 +6,8 @@ VITE_APP_BASE_API=/dev-api
# 接口地址
# VITE_APP_API_URL=https://admintestpapi.sxczgkj.cn/ # 线上
VITE_APP_API_URL=https://tapi.cashier.sxczgkj.cn/ # 正式
# VITE_APP_API_URL=https://api.youlai.tech # 线上
# VITE_APP_API_URL=http://localhost:8989 # 本地
# WebSocket 端点(不配置则关闭),线上 ws://api.youlai.tech/ws ,本地 ws://localhost:8989/ws
VITE_APP_WS_ENDPOINT=wss://sockets.sxczgkj.com/wss

View File

@ -4,3 +4,14 @@ VITE_APP_BASE_API = '/prod-api'
# WebSocket端点(可选)
#VITE_APP_WS_ENDPOINT=wss://api.youlai.tech/ws
# 接口地址
VITE_APP_API_URL=https://tapi.cashier.sxczgkj.cn/ # 正式
# WebSocket 端点(不配置则关闭),线上 ws://api.youlai.tech/ws ,本地 ws://localhost:8989/ws
VITE_APP_WS_ENDPOINT=wss://sockets.sxczgkj.com/wss
# 启用 Mock 服务
VITE_MOCK_DEV_SERVER=false

View File

@ -4,14 +4,14 @@ const baseURL = Account_BaseUrl + "/admin";
const ShopStaffApi = {
// 获取店铺权限列表
getshopPermission() {
return request<any>({
return request<any, PermissionResonpseResponse>({
url: `${baseURL}/shopPermission`,
method: "get",
});
},
// 获取员工对应的权限id
getPermission(id: number | string) {
return request<any>({
return request<any, string[]>({
url: `${baseURL}/shopStaff/permission`,
method: "get",
params: { id }
@ -20,3 +20,56 @@ const ShopStaffApi = {
};
export default ShopStaffApi;
/**
*
*
* CzgResult«List«ShopPermission»»
*/
export interface PermissionResonpseResponse {
code?: number | null;
data?: ShopPermission[] | null;
msg?: null | string;
[property: string]: any;
}
/**
*
*
* ShopPermission
*/
export interface ShopPermission {
children?: ShopPermission[] | null;
/**
* code
*/
code?: null | string;
createTime?: null | string;
id: string;
/**
*
*/
isImportant?: number | null;
/**
*
*/
label?: null | string;
/**
*
*/
level?: number | null;
/**
* ID
*/
parentId?: number | null;
/**
*
*/
sort?: number | null;
/**
* staff
*/
type?: null | string;
updateTime?: null | string;
[property: string]: any;
}

View File

@ -0,0 +1,78 @@
import request from "@/utils/request";
import { Account_BaseUrl } from "@/api/config";
const baseURL = Account_BaseUrl + "/admin/shopArea";
const ShopStaffApi = {
getList(params: getListRequest) {
return request<any>({
url: `${baseURL}`,
method: "get",
params
});
},
add(data: addRequest) {
return request<any>({
url: `${baseURL}`,
method: "post",
data
});
},
edit(data: editRequest) {
return request<any>({
url: `${baseURL}`,
method: "put",
data
});
},
delete(id: string | number) {
return request<any>({
url: `${baseURL}`,
method: "delete",
data: { id }
});
},
};
export default ShopStaffApi;
export interface getListRequest {
/**
*
*/
name?: string;
page?: string;
size?: string;
[property: string]: any;
}
/**
* ShopAreaEditDTO
*/
export interface editRequest {
/**
* id
*/
id: number | null;
/**
*
*/
name?: null | string;
/**
*
*/
sort?: number | null;
[property: string]: any;
}
/**
* ShopAreaAddDTO
*/
export interface addRequest {
/**
*
*/
name: null | string;
/**
*
*/
sort?: number | null;
[property: string]: any;
}

View File

@ -1,9 +1,20 @@
<template>
<!-- drawer -->
<template v-if="modalConfig.component === 'drawer'">
<el-drawer v-model="modalVisible" :append-to-body="true" v-bind="modalConfig.drawer" @close="handleCloseModal">
<el-drawer
v-model="modalVisible"
:append-to-body="true"
v-bind="modalConfig.drawer"
@close="handleCloseModal"
>
<!-- 表单 -->
<el-form ref="formRef" label-width="auto" v-bind="modalConfig.form" :model="formData" :rules="formRules">
<el-form
ref="formRef"
label-width="auto"
v-bind="modalConfig.form"
:model="formData"
:rules="formRules"
>
<el-row :gutter="20">
<template v-for="item in formItems" :key="item.prop">
<template v-if="item.type === 'title'">
@ -15,7 +26,12 @@
<template v-if="item.tips" #label>
<span>
{{ item.label }}
<el-tooltip placement="bottom" effect="light" :content="item.tips" :raw-content="true">
<el-tooltip
placement="bottom"
effect="light"
:content="item.tips"
:raw-content="true"
>
<el-icon style="vertical-align: -0.15em" size="16">
<QuestionFilled />
</el-icon>
@ -90,13 +106,20 @@
</template>
<!-- 自定义 -->
<template v-else-if="item.type === 'custom'">
<slot :name="item.slotName ?? item.prop" :prop="item.prop" :formData="formData" :attrs="item.attrs" />
<slot
:name="item.slotName ?? item.prop"
:prop="item.prop"
:formData="formData"
:attrs="item.attrs"
/>
</template>
</el-form-item>
</el-col>
</template>
</el-row>
</el-form>
<!-- 表单底部插槽 -->
<slot name="formFooter" />
<!-- 弹窗底部操作按钮 -->
<template #footer>
<div v-if="!formDisable">
@ -111,13 +134,26 @@
</template>
<!-- dialog -->
<template v-else>
<el-dialog v-model="modalVisible" :align-center="true" :append-to-body="true" width="70vw"
v-bind="modalConfig.dialog" style="padding-right: 0" @close="handleCloseModal">
<el-dialog
v-model="modalVisible"
:align-center="true"
:append-to-body="true"
width="70vw"
v-bind="modalConfig.dialog"
style="padding-right: 0"
@close="handleCloseModal"
>
<!-- 滚动 -->
<el-scrollbar max-height="60vh">
<!-- 表单 -->
<el-form ref="formRef" label-width="auto" v-bind="modalConfig.form"
style="padding-right: var(--el-dialog-padding-primary)" :model="formData" :rules="formRules">
<el-form
ref="formRef"
label-width="auto"
v-bind="modalConfig.form"
style="padding-right: var(--el-dialog-padding-primary)"
:model="formData"
:rules="formRules"
>
<el-row :gutter="20">
<template v-for="item in formItems" :key="item.prop">
<template v-if="item.type === 'title'">
@ -131,7 +167,12 @@
<template v-if="item.tips" #label>
<span>
{{ item.label }}
<el-tooltip placement="bottom" effect="light" :content="item.tips" :raw-content="true">
<el-tooltip
placement="bottom"
effect="light"
:content="item.tips"
:raw-content="true"
>
<el-icon style="vertical-align: -0.15em" size="16">
<QuestionFilled />
</el-icon>
@ -140,7 +181,11 @@
</template>
<!-- Input 输入框 -->
<template v-if="item.type === 'input' || item.type === undefined">
<el-input v-model="formData[item.prop]" v-bind="item.attrs" :disabled="item.disabled" />
<el-input
v-model="formData[item.prop]"
v-bind="item.attrs"
:disabled="item.disabled"
/>
</template>
<!-- textarea 输入框 -->
<template v-else-if="item.type === 'textarea'">
@ -207,8 +252,12 @@
</template>
<!-- 自定义 -->
<template v-else-if="item.type === 'custom'">
<slot :name="item.slotName ?? item.prop" :prop="item.prop" :formData="formData"
:attrs="item.attrs" />
<slot
:name="item.slotName ?? item.prop"
:prop="item.prop"
:formData="formData"
:attrs="item.attrs"
/>
</template>
</el-form-item>
</el-col>
@ -216,6 +265,8 @@
</el-row>
</el-form>
</el-scrollbar>
<!-- 表单底部插槽 -->
<slot name="formFooter" />
<!-- 弹窗底部操作按钮 -->
<template #footer>
<div style="padding-right: var(--el-dialog-padding-primary)">
@ -370,7 +421,14 @@ function handleDisabled(disable: boolean) {
}
//
defineExpose({ setModalVisible, getFormData, setFormData, setFormItemData, handleDisabled, handleClose });
defineExpose({
setModalVisible,
getFormData,
setFormData,
setFormItemData,
handleDisabled,
handleClose,
});
</script>
<style lang="scss" scoped>

View File

@ -11,7 +11,6 @@ const Layout = () => import("@/layout/index.vue");
export const usePermissionStore = defineStore("permission", () => {
// 储所有路由,包括静态路由和动态路由
const routes = ref<RouteRecordRaw[]>(constantRoutes);
console.log(router);
// 混合模式左侧菜单路由
const mixedLayoutLeftRoutes = ref<RouteRecordRaw[]>([]);
// 路由是否加载完成

View File

@ -15,7 +15,6 @@ const service = axios.create({
// 请求拦截器
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
console.log(config);
const accessToken = getToken();
// 如果 Authorization 设置为 no-auth则不携带 Token用于登录、刷新 Token 等接口
if (config.headers.Authorization !== "no-auth" && accessToken) {

View File

@ -1,4 +1,3 @@
class WebSocketManager {
private client: WebSocket | null = null;
private connected: boolean = false;
@ -35,6 +34,11 @@ class WebSocketManager {
};
this.client.onerror = (error) => {
console.error("WebSocket 发生错误:", error);
ElNotification({
title: "提示",
message: "WebSocket 发生错误",
type: "error",
});
};
this.client.onmessage = (event) => {
const message = event.data;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
<el-radio-button :value="1">员工</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item prop="merchantName" v-if="state.loginForm.loginType == 'staff'">
<el-form-item prop="merchantName" v-if="state.loginForm.loginType == 1">
<el-input
v-model="state.loginForm.merchantName"
type="text"
@ -145,7 +145,7 @@ function getCookie() {
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
code: "",
merchantName: "",
loginType: "merchant",
loginType: 0,
};
}

View File

@ -1 +1,52 @@
<template>11</template>
<template>
<div v-for="(item, index) in list" :key="index">
<h4 class="title">
{{ item.label }}
</h4>
<div v-if="item.children" class="flex gap-10">
<el-checkbox-group v-model="model[index]">
<el-checkbox
v-for="(child, childIndex) in item.children"
:key="childIndex"
:value="child.id"
:label="child.label"
:style="returnStyle(child)"
></el-checkbox>
</el-checkbox-group>
</div>
</div>
</template>
<script setup>
const props = defineProps({
list: {
type: Array,
default: () => [],
},
});
const model = defineModel({ type: Array, default: () => [] });
const importantPer = ["允许收款", "允许打折", "允许修改会员余额", "允许沽清"];
function returnStyle(child) {
if (importantPer.includes(child.label)) {
return "color:red";
}
}
for (const item in props.list) {
console.log(item);
model[item] = [];
}
function getFormData() {
return formData;
}
defineExpose({
getFormData,
});
</script>
<style scoped >
.title {
text-align: left;
}
</style>

View File

@ -144,12 +144,7 @@ const modalConfig: IModalConfig<addRequest> = {
sm: 12,
},
},
{
label: "员工权限设置",
prop: "",
type: "title",
slotName: "title",
},
{
label: "是否允许管理端登录",
prop: "isManage",
@ -170,6 +165,20 @@ const modalConfig: IModalConfig<addRequest> = {
],
initialValue: 1,
},
{
label: "员工权限设置",
prop: "",
type: "title",
slotName: "title",
},
{
type: 'custom',
prop: 'permission',
slotName: 'permission',
label: '',
hidden: true
}
],
};

View File

@ -27,7 +27,7 @@ const modalConfig: IModalConfig<editRequest> = {
{
label: "角色",
prop: "roleId",
rules: [{ required: true, message: "请选择角色", trigger: "blur" }],
rules: [{ required: false, message: "请选择角色", trigger: "blur" }],
type: "select",
attrs: {
placeholder: "请选择角色",
@ -54,7 +54,7 @@ const modalConfig: IModalConfig<editRequest> = {
{
label: "员工编号",
prop: "code",
rules: [{ required: true, message: "请输入员工编号", trigger: "blur" }],
rules: [{ required: false, message: "请输入员工编号", trigger: "blur" }],
type: "input",
attrs: {
placeholder: "请输入员工编号",
@ -68,7 +68,7 @@ const modalConfig: IModalConfig<editRequest> = {
label: "手机号",
prop: "phone",
rules: [{
required: true,
required: false,
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur",
@ -85,7 +85,7 @@ const modalConfig: IModalConfig<editRequest> = {
{
label: "登录账号",
prop: "accountName",
rules: [{ required: true, message: "请输入登录账号", trigger: "blur" }],
rules: [{ required: false, message: "请输入登录账号", trigger: "blur" }],
type: "input",
attrs: {
placeholder: "请输入登录账号",
@ -98,7 +98,7 @@ const modalConfig: IModalConfig<editRequest> = {
{
label: "登录密码",
prop: "accountPwd",
rules: [{ required: true, message: "请输入登录密码", trigger: "blur" }],
rules: [{ required: false, message: "请输入登录密码", trigger: "blur" }],
type: "input",
attrs: {
placeholder: "请输入登录密码",
@ -144,12 +144,6 @@ const modalConfig: IModalConfig<editRequest> = {
sm: 12,
},
},
{
label: "员工权限设置",
prop: "",
type: "title",
slotName: "title",
},
{
label: "是否允许管理端登录",
prop: "isManage",
@ -170,6 +164,12 @@ const modalConfig: IModalConfig<editRequest> = {
],
initialValue: 1,
},
{
label: "员工权限设置",
prop: "",
type: "title",
slotName: "title",
},
],
};

View File

@ -43,8 +43,12 @@
<!-- 新增 -->
<page-modal ref="addModalRef" :modal-config="addModalConfig" @submit-click="handleSubmitClick">
<template #permission="scope">
<selectPermission></selectPermission>
<template #formFooter>
<selectPermission
v-model="selPermissionList"
:list="permissionList"
ref="refSelectPermission"
></selectPermission>
</template>
</page-modal>
@ -54,8 +58,12 @@
:modal-config="editModalConfig"
@submit-click="handleSubmitClick"
>
<template #permission="scope">
<selectPermission></selectPermission>
<template #formFooter>
<selectPermission
v-model="selPermissionList"
:list="permissionList"
ref="refSelectPermission"
></selectPermission>
</template>
</page-modal>
</div>
@ -71,9 +79,10 @@ import searchConfig from "./config/search";
import { returnOptionsLabel } from "./config/config";
import RoleApi, { type SysRole } from "@/api/account/role";
import ShopStaffApi from "@/api/account/shopStaff";
import permissionApi from "@/api/account/permission";
import permissionApi, { type ShopPermission } from "@/api/account/permission";
import selectPermission from "./components/select-permission.vue";
permissionApi.getshopPermission();
const refSelectPermission = ref();
const {
searchRef,
contentRef,
@ -89,9 +98,36 @@ const {
handleFilterChange,
} = usePage();
//
let permissionList = ref<ShopPermission[]>([]);
//
let selPermissionList = ref<string[]>([]);
//
async function init() {
//
const oldAddSubmitFunc = addModalConfig.formAction;
addModalConfig.formAction = (data) => {
return oldAddSubmitFunc({
...data,
shopPermissionIds: selPermissionList.value.reduce((pre: string[], cur: string) => {
return pre.concat(cur);
}, [] as string[]),
});
};
//
const oldeditSubmitFunc = editModalConfig.formAction;
editModalConfig.formAction = (data) => {
return oldeditSubmitFunc({
...data,
shopPermissionIds: selPermissionList.value.reduce((pre: string[], cur: string) => {
return pre.concat(cur);
}, [] as string[]),
});
};
const res = await RoleApi.getList({ page: 1, size: 100 });
const permission = await permissionApi.getshopPermission();
permissionList.value = Array.isArray(permission) ? permission : [];
const roleArr = res.records.map((item: SysRole) => {
return {
...item,
@ -106,12 +142,33 @@ init();
//
async function handleAddClick() {
selPermissionList.value = [];
addModalRef.value?.setModalVisible();
}
//
async function handleEditClick(row: IObject) {
selPermissionList.value = [];
editModalRef.value?.handleDisabled(false);
editModalRef.value?.setModalVisible();
//
const perselArr = await permissionApi.getPermission(row.id);
for (let id of perselArr) {
for (let index in permissionList.value) {
const item = permissionList.value[index];
if (item.children) {
for (let child of item.children) {
if (child.id != null && child.id == id) {
if (selPermissionList.value[index]) {
selPermissionList.value[index].push(id);
} else {
selPermissionList.value[index] = [id];
}
}
}
}
}
}
console.log(selPermissionList.value);
// id
await ShopStaffApi.get(row.id).then((res) => {
console.log(res);