feat: 接入真实登录鉴权流程
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
type RoleOption,
|
||||
type StoreOption
|
||||
} from "@/api/access";
|
||||
import { hasPerms } from "@/utils/auth";
|
||||
|
||||
import Plus from "~icons/ep/plus";
|
||||
import Search from "~icons/ep/search";
|
||||
@@ -41,6 +42,13 @@ type EmployeeFormState = EmployeePayload & {
|
||||
|
||||
/** 员工手机号按中国大陆手机号做前端第一层校验,最终唯一性仍由后端保证。 */
|
||||
const phonePattern = /^1[3-9]\d{9}$/;
|
||||
const bindableRoleCodes = new Set([
|
||||
"store_manager",
|
||||
"cashier",
|
||||
"kitchen",
|
||||
"part_time",
|
||||
"admin"
|
||||
]);
|
||||
const tableLoading = ref(false);
|
||||
const catalogLoading = ref(false);
|
||||
const submitLoading = ref(false);
|
||||
@@ -99,6 +107,8 @@ const inactiveCount = computed(
|
||||
() => employees.value.filter(item => item.status === "INACTIVE").length
|
||||
);
|
||||
const dialogTitle = computed(() => (form.id ? "编辑员工" : "新增员工"));
|
||||
const canManageEmployees = computed(() => hasPerms("employee:manage"));
|
||||
const canViewAllEmployees = computed(() => hasPerms("employee:view:all"));
|
||||
|
||||
function getErrorMessage(error: unknown, fallback: string) {
|
||||
const message = (
|
||||
@@ -147,14 +157,22 @@ function buildPayload(): EmployeePayload {
|
||||
|
||||
/** 门店和角色是员工表单的基础字典,打开弹窗前必须先加载。 */
|
||||
async function fetchCatalog() {
|
||||
const shouldLoadStores =
|
||||
canViewAllEmployees.value || canManageEmployees.value;
|
||||
const shouldLoadRoles = canManageEmployees.value;
|
||||
|
||||
if (!shouldLoadStores && !shouldLoadRoles) return;
|
||||
|
||||
catalogLoading.value = true;
|
||||
try {
|
||||
const [storeResult, roleResult] = await Promise.all([
|
||||
listStores(),
|
||||
listRoles()
|
||||
shouldLoadStores ? listStores() : Promise.resolve({ data: [] }),
|
||||
shouldLoadRoles ? listRoles() : Promise.resolve({ data: [] })
|
||||
]);
|
||||
stores.value = storeResult.data;
|
||||
roles.value = roleResult.data;
|
||||
roles.value = roleResult.data.filter(role =>
|
||||
bindableRoleCodes.has(role.code)
|
||||
);
|
||||
} catch (error) {
|
||||
ElMessage.error(getErrorMessage(error, "加载门店和角色选项失败"));
|
||||
} finally {
|
||||
@@ -209,12 +227,14 @@ function handleSizeChange(pageSize: number) {
|
||||
}
|
||||
|
||||
function openCreateDialog() {
|
||||
if (!canManageEmployees.value) return;
|
||||
resetFormState();
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
/** 编辑前重新拉详情,确保角色绑定不是来自列表摘要的过期数据。 */
|
||||
async function openEditDialog(row: Employee) {
|
||||
if (!canManageEmployees.value) return;
|
||||
try {
|
||||
const result = await getEmployee(row.id);
|
||||
const employee = result.data;
|
||||
@@ -235,6 +255,7 @@ async function openEditDialog(row: Employee) {
|
||||
}
|
||||
|
||||
async function submitForm() {
|
||||
if (!canManageEmployees.value) return;
|
||||
await formRef.value?.validate();
|
||||
submitLoading.value = true;
|
||||
|
||||
@@ -259,6 +280,7 @@ async function submitForm() {
|
||||
}
|
||||
|
||||
async function toggleStatus(row: Employee) {
|
||||
if (!canManageEmployees.value) return;
|
||||
const nextStatus: EmployeeStatus =
|
||||
row.status === "ACTIVE" ? "INACTIVE" : "ACTIVE";
|
||||
const action = nextStatus === "ACTIVE" ? "启用" : "停用";
|
||||
@@ -284,6 +306,7 @@ async function toggleStatus(row: Employee) {
|
||||
}
|
||||
|
||||
async function removeEmployee(row: Employee) {
|
||||
if (!canManageEmployees.value) return;
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`删除后员工「${row.name}」会被软删除并停用,确认继续?`,
|
||||
@@ -321,7 +344,12 @@ onMounted(async () => {
|
||||
<p class="eyebrow">门店员工权限管理</p>
|
||||
<h1>员工管理</h1>
|
||||
</div>
|
||||
<el-button type="primary" :icon="Plus" @click="openCreateDialog">
|
||||
<el-button
|
||||
v-if="canManageEmployees"
|
||||
type="primary"
|
||||
:icon="Plus"
|
||||
@click="openCreateDialog"
|
||||
>
|
||||
新增员工
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -347,6 +375,7 @@ onMounted(async () => {
|
||||
|
||||
<div class="toolbar">
|
||||
<el-select
|
||||
v-if="canViewAllEmployees"
|
||||
v-model="query.storeId"
|
||||
clearable
|
||||
filterable
|
||||
@@ -440,7 +469,12 @@ onMounted(async () => {
|
||||
{{ formatTime(row.updatedAt) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" fixed="right">
|
||||
<el-table-column
|
||||
v-if="canManageEmployees"
|
||||
label="操作"
|
||||
width="260"
|
||||
fixed="right"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
link
|
||||
|
||||
Reference in New Issue
Block a user