fix event record

This commit is contained in:
Timi
2026-08-07 19:39:48 +08:00
parent 16fa5fdd36
commit 45ea8b46aa
9 changed files with 205 additions and 53 deletions
+15 -9
View File
@@ -254,9 +254,9 @@ async function applyIntroducer(code: string): Promise<void> {
const matched = await CustomerAPI.findByCode(code); const matched = await CustomerAPI.findByCode(code);
if (!matched?.id) { if (!matched?.id) {
formData.introducerCustomerId = ""; formData.introducerCustomerId = "";
formData.introducerCustomer = undefined;
introducerCustomerId.value = ""; introducerCustomerId.value = "";
scannerVisible.value = false; scannerVisible.value = false;
scannerVisible.value = false;
Toast.warning(`未匹配到 ${code} 编码介绍人,请选择或扫码已有客户`); Toast.warning(`未匹配到 ${code} 编码介绍人,请选择或扫码已有客户`);
return; return;
} }
@@ -267,8 +267,9 @@ async function applyIntroducer(code: string): Promise<void> {
} }
async function handleIntroducerChange(id: string): Promise<void> { async function handleIntroducerChange(id: string): Promise<void> {
const customer = await CustomerAPI.findById(id); const customer = id ? await CustomerAPI.findById(id) : undefined;
introducerCustomerId.value = customer!.id!; introducerCustomerId.value = customer?.id || "";
formData.introducerCustomerId = customer?.id || "";
formData.introducerCustomer = customer; formData.introducerCustomer = customer;
} }
@@ -349,7 +350,7 @@ async function loadDetail() {
Object.assign(formData, customer); Object.assign(formData, customer);
formData.storeId = customer.storeId || formData.storeId; formData.storeId = customer.storeId || formData.storeId;
selectedAreas.value = normalizeBodyAreaValue(customer.conditioningPart); selectedAreas.value = normalizeBodyAreaValue(customer.conditioningPart);
introducerCustomerId.value = customer.introducerCustomer?.id || ""; introducerCustomerId.value = customer.introducerCustomerId || customer.introducerCustomer?.id || "";
} catch (err) { } catch (err) {
console.warn("客户详情加载失败", err); console.warn("客户详情加载失败", err);
Toast.error("客户详情加载失败"); Toast.error("客户详情加载失败");
@@ -411,18 +412,23 @@ async function doSubmit(): Promise<void> {
isSubmitting.value = true; isSubmitting.value = true;
try { try {
formData.conditioningPart = selectedAreas.value; const payload: Customer = { ...formData };
formData.attachmentList = photoTempFileId.value ? [{ payload.conditioningPart = selectedAreas.value;
payload.introducerCustomerId = introducerCustomerId.value || "";
payload.attachmentList = photoTempFileId.value ? [{
attachType: "PHOTO", attachType: "PHOTO",
tempFileId: photoTempFileId.value tempFileId: photoTempFileId.value
}] : undefined; }] : undefined;
delete payload.introducerCustomer;
if (isCreateMode.value) { if (isCreateMode.value) {
const id = await CustomerAPI.create(formData); await CustomerAPI.create(payload);
Toast.success("创建成功"); Toast.success("创建成功");
await router.replace(`/management/customers/${id}`); const redirect = String(route.query.redirect || "");
await router.replace(redirect || "/management/customers");
return;
} else { } else {
await CustomerAPI.update(formData); await CustomerAPI.update(payload);
Toast.success("保存成功"); Toast.success("保存成功");
const redirect = String(route.query.redirect || ""); const redirect = String(route.query.redirect || "");
if (redirect) { if (redirect) {
+15 -1
View File
@@ -1,6 +1,11 @@
<template> <template>
<div v-can="permissionCodes.eventRecord.read" class="registration-record-detail"> <div v-can="permissionCodes.eventRecord.read" class="registration-record-detail">
<customer-profile-card v-if="record?.customer" class="customer-profile" :customer="record.customer" /> <customer-profile-card
v-if="record?.customer"
class="customer-profile"
:customer="record.customer"
@click="toCustomerDetail"
/>
<t-cell-group v-if="record" title="登记信息" theme="card"> <t-cell-group v-if="record" title="登记信息" theme="card">
<t-cell title="登记事件" :note="record.event?.name || '未知事件'" /> <t-cell title="登记事件" :note="record.event?.name || '未知事件'" />
<t-cell title="登记时间" :note="record.registeredAt ? Time.toPassedDateTime(record.registeredAt) : '-'" /> <t-cell title="登记时间" :note="record.registeredAt ? Time.toPassedDateTime(record.registeredAt) : '-'" />
@@ -80,6 +85,15 @@ async function toEdit(): Promise<void> {
await router.push(`/management/registration-event-records/${recordId}/edit`); await router.push(`/management/registration-event-records/${recordId}/edit`);
} }
async function toCustomerDetail(): Promise<void> {
const customerId = record.value?.customer?.id;
if (!customerId) {
return;
}
await router.push(`/management/customers/${customerId}`);
}
watch(() => route.params.id, async () => { watch(() => route.params.id, async () => {
await loadRecord(); await loadRecord();
}, { immediate: true }); }, { immediate: true });
+2 -2
View File
@@ -432,8 +432,8 @@ function openRegisteredAtPicker(): void {
registeredAtPickerVisible.value = true; registeredAtPickerVisible.value = true;
} }
function confirmRegisteredAt(): void { function confirmRegisteredAt(value?: string | number): void {
registeredAtText.value = registeredAtDraftText.value; registeredAtText.value = String(value || registeredAtDraftText.value);
registeredAtPickerVisible.value = false; registeredAtPickerVisible.value = false;
} }
+67 -14
View File
@@ -63,7 +63,7 @@
class="cell" class="cell"
:title="getRecordEventName(item)" :title="getRecordEventName(item)"
:description="getRecordCustomerName(item)" :description="getRecordCustomerName(item)"
:note="item.registeredAt ? Time.toPassedDateTime(item.registeredAt) : '-'" :note="item.registeredAt ? Time.toDateTime(item.registeredAt) : '-'"
arrow arrow
hover hover
@click="toDetail(item.id || '')" @click="toDetail(item.id || '')"
@@ -131,12 +131,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { DialogPlugin, Toast, type DropdownValue } from "tdesign-mobile-vue"; import { DialogPlugin, Toast, type DropdownValue } from "tdesign-mobile-vue";
import { AttachmentAPI, Time, Toolkit, type PageResult, useUserStore } from "timi-web"; import { Time, Toolkit, type PageResult, useUserStore } from "timi-web";
import EventAPI from "@/api/EventAPI"; import EventAPI from "@/api/EventAPI";
import EventRecordAPI from "@/api/EventRecordAPI"; import EventRecordAPI from "@/api/EventRecordAPI";
import { useNavBarStore } from "@/store/navBarStore"; import { useNavBarStore } from "@/store/navBarStore";
import type { EventItem } from "@/types/EventItem"; import type { EventItem } from "@/types/EventItem";
import type { EventRecordListItemView, EventRecordPage } from "@/types/EventRecord"; import type { EventRecordListItemView, EventRecordPage } from "@/types/EventRecord";
import { getCustomerPhotoURL } from "@/utils/customer";
import { permissionCodes } from "@/utils/permission"; import { permissionCodes } from "@/utils/permission";
type DateFilterType = "today" | "yesterday" | "beforeYesterday" | "lastWeek" | "all" | "custom"; type DateFilterType = "today" | "yesterday" | "beforeYesterday" | "lastWeek" | "all" | "custom";
@@ -146,6 +147,7 @@ defineOptions({
}); });
const pageSize = 20; const pageSize = 20;
const route = useRoute();
const router = useRouter(); const router = useRouter();
const navBarStore = useNavBarStore(); const navBarStore = useNavBarStore();
const userStore = useUserStore(); const userStore = useUserStore();
@@ -160,9 +162,9 @@ const dateOptions: Array<{ label: string; value: DateFilterType }> = [
// ---------- 筛选 ---------- // ---------- 筛选 ----------
const keyword = ref(""); const keyword = ref(getQueryText("keyword"));
const dateFilterType = ref<DateFilterType>("today"); const dateFilterType = ref<DateFilterType>(parseDateFilterType(route.query.dateType));
const dateRange = ref(buildPresetRange("today")); const dateRange = ref(parseDateRange(dateFilterType.value));
const actionFilter = ref<string[]>([]); const actionFilter = ref<string[]>([]);
const eventList = ref<EventItem[]>([]); const eventList = ref<EventItem[]>([]);
const startVisible = ref(false); const startVisible = ref(false);
@@ -204,6 +206,7 @@ watch(keyword, () => {
} }
window.clearTimeout(keywordTimer); window.clearTimeout(keywordTimer);
keywordTimer = window.setTimeout(async () => { keywordTimer = window.setTimeout(async () => {
await replaceFilterQuery();
await reloadRecords(); await reloadRecords();
}, 300); }, 300);
}); });
@@ -212,6 +215,7 @@ watch(actionFilter, async () => {
if (!initialized) { if (!initialized) {
return; return;
} }
await replaceFilterQuery();
await reloadRecords(); await reloadRecords();
}); });
@@ -225,6 +229,7 @@ watch(dateRange, async (value) => {
return; return;
} }
await replaceFilterQuery();
await reloadRecords(); await reloadRecords();
}, { deep: true }); }, { deep: true });
@@ -299,7 +304,10 @@ const deletingId = ref("");
async function loadActions(): Promise<void> { async function loadActions(): Promise<void> {
eventList.value = await EventAPI.listValid(); eventList.value = await EventAPI.listValid();
actionFilter.value = eventList.value.map(item => item.id).filter((item): item is string => Boolean(item)); const eventIdList = parseEventIdList(route.query.eventIds);
actionFilter.value = eventIdList.length
? eventIdList
: eventList.value.map(item => item.id).filter((item): item is string => Boolean(item));
} }
async function selectDateFilter(type: DropdownValue): Promise<void> { async function selectDateFilter(type: DropdownValue): Promise<void> {
@@ -310,7 +318,10 @@ async function selectDateFilter(type: DropdownValue): Promise<void> {
dateFilterType.value = String(type) as DateFilterType; dateFilterType.value = String(type) as DateFilterType;
if (dateFilterType.value !== "custom") { if (dateFilterType.value !== "custom") {
dateRange.value = buildPresetRange(dateFilterType.value); dateRange.value = buildPresetRange(dateFilterType.value);
await replaceFilterQuery();
await reloadRecords(); await reloadRecords();
} else {
await replaceFilterQuery();
} }
} }
@@ -336,7 +347,10 @@ async function toDetail(id: string): Promise<void> {
if (!id) { if (!id) {
return; return;
} }
await router.push(`/management/registration-event-records/${id}`); await router.push({
path: `/management/registration-event-records/${id}`,
query: buildFilterQuery()
});
} }
async function toCreate(): Promise<void> { async function toCreate(): Promise<void> {
@@ -385,22 +399,19 @@ async function removeRecord(id: string): Promise<void> {
// ---------- 格式化 ---------- // ---------- 格式化 ----------
function getRecordEventName(record: EventRecordListItemView): string { function getRecordEventName(record: EventRecordListItemView): string {
return record.eventName || "未知事件"; return record.event?.name || "未知事件";
} }
function getRecordCustomerName(record: EventRecordListItemView): string { function getRecordCustomerName(record: EventRecordListItemView): string {
return record.customerName || "未知客户"; return record.customer?.name || "未知客户";
} }
function getRecordPhotoURL(record: EventRecordListItemView): string { function getRecordPhotoURL(record: EventRecordListItemView): string {
if (!record.customerPhotoAttachmentId) { return getCustomerPhotoURL(record.customer);
return "";
}
return AttachmentAPI.getReadURL(record.customerPhotoAttachmentId);
} }
function getRecordCustomerInitial(record: EventRecordListItemView): string { function getRecordCustomerInitial(record: EventRecordListItemView): string {
return (record.customerName || "客").slice(0, 1); return getRecordCustomerName(record).slice(0, 1);
} }
function buildRangeReq(): Omit<EventRecordPage, "index" | "size"> { function buildRangeReq(): Omit<EventRecordPage, "index" | "size"> {
@@ -414,6 +425,48 @@ function buildRangeReq(): Omit<EventRecordPage, "index" | "size"> {
}; };
} }
function getQueryText(key: string): string {
const value = route.query[key];
return Array.isArray(value) ? String(value[0] || "") : String(value || "");
}
function parseDateFilterType(value: unknown): DateFilterType {
const text = Array.isArray(value) ? String(value[0] || "") : String(value || "");
return dateOptions.some(item => item.value === text) ? text as DateFilterType : "today";
}
function parseDateRange(type: DateFilterType): [string, string] {
if (type !== "custom") {
return buildPresetRange(type);
}
const beginAt = getQueryText("beginAt");
const endAt = getQueryText("endAt");
return [beginAt, endAt];
}
function parseEventIdList(value: unknown): string[] {
const text = Array.isArray(value) ? String(value[0] || "") : String(value || "");
return text.split(",").map(item => item.trim()).filter(Boolean);
}
function buildFilterQuery(): Record<string, string> {
return {
keyword: keyword.value.trim(),
dateType: dateFilterType.value,
beginAt: dateRange.value[0] || "",
endAt: dateRange.value[1] || "",
eventIds: actionFilter.value.join(",")
};
}
async function replaceFilterQuery(): Promise<void> {
await router.replace({
name: "EventRecordList",
query: buildFilterQuery()
});
}
function buildPresetRange(type: Exclude<DateFilterType, "custom">): [string, string] { function buildPresetRange(type: Exclude<DateFilterType, "custom">): [string, string] {
if (type === "all") { if (type === "all") {
return ["", ""]; return ["", ""];
@@ -61,7 +61,7 @@
<div class="actions"> <div class="actions">
<t-button <t-button
v-if="editingId" v-if="editingId"
v-can="permissionCodes.store.delete" v-can="deletePermissionCode"
class="action" class="action"
theme="danger" theme="danger"
variant="outline" variant="outline"
@@ -82,16 +82,19 @@
<script setup lang="ts"> <script setup lang="ts">
import { DialogPlugin, Toast, type CalendarProps, type TDate } from "tdesign-mobile-vue"; import { DialogPlugin, Toast, type CalendarProps, type TDate } from "tdesign-mobile-vue";
import { useUserStore } from "timi-web";
import StoreAPI from "@/api/StoreAPI"; import StoreAPI from "@/api/StoreAPI";
import type { Store, StoreBusinessDay, StoreBusinessDayOpenStatus } from "@/types/Store"; import type { Store, StoreBusinessDay, StoreBusinessDayOpenStatus } from "@/types/Store";
import { permissionCodes } from "@/utils/permission"; import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
defineOptions({ defineOptions({
name: "StoreBusinessDayCalendar" name: "StoreBusinessDayCalendar"
}); });
const route = useRoute(); const route = useRoute();
const userStore = useUserStore();
const storeId = computed(() => String(route.params.id || "")); const storeId = computed(() => String(route.params.id || ""));
const isStoreManagerScope = computed(() => userStore.hasRoles(gaoRoleCodes.storeManager) && !userStore.hasRoles(gaoRoleCodes.globalManager));
// ---------- 门店信息 ---------- // ---------- 门店信息 ----------
@@ -176,7 +179,14 @@ const formModel = reactive({
openStatus: "OPEN" as StoreBusinessDayOpenStatus, openStatus: "OPEN" as StoreBusinessDayOpenStatus,
reason: "正常休息" reason: "正常休息"
}); });
const savePermissionCode = computed(() => editingId.value ? permissionCodes.store.update : permissionCodes.store.create); const savePermissionCode = computed(() => {
if (isStoreManagerScope.value) {
return permissionCodes.store.update;
}
return editingId.value ? permissionCodes.store.update : permissionCodes.store.create;
});
const deletePermissionCode = computed(() => isStoreManagerScope.value ? permissionCodes.store.update : permissionCodes.store.delete);
function openDayEditor(day?: StoreBusinessDay, dateValue = toDateValue(new Date())): void { function openDayEditor(day?: StoreBusinessDay, dateValue = toDateValue(new Date())): void {
editingId.value = day?.id || ""; editingId.value = day?.id || "";
+36 -16
View File
@@ -1,13 +1,13 @@
<template> <template>
<div v-can="savePermissionCode" class="store-edit"> <div v-can="savePermissionCode" class="store-edit">
<t-form class="form" label-align="left"> <t-form class="form" label-align="left">
<t-form-item label="编码"> <t-form-item v-if="!isStoreManagerScope" label="编码">
<t-input v-model.trim="formModel.code" placeholder="门店编码" borderless /> <t-input v-model.trim="formModel.code" placeholder="门店编码" borderless />
</t-form-item> </t-form-item>
<t-form-item label="名称"> <t-form-item label="名称">
<t-input v-model.trim="formModel.name" placeholder="门店名称" borderless /> <t-input v-model.trim="formModel.name" placeholder="门店名称" borderless />
</t-form-item> </t-form-item>
<t-form-item label="启用" content-align="right"> <t-form-item v-if="!isStoreManagerScope" label="启用" content-align="right">
<t-switch v-model="formModel.status" :custom-value="['ACTIVE', 'INACTIVE']" /> <t-switch v-model="formModel.status" :custom-value="['ACTIVE', 'INACTIVE']" />
</t-form-item> </t-form-item>
<t-form-item label="电话"> <t-form-item label="电话">
@@ -25,7 +25,7 @@
</t-cell-group> </t-cell-group>
<div class="actions"> <div class="actions">
<t-button <t-button
v-if="!isCreateMode" v-if="!isCreateMode && !isStoreManagerScope"
v-can="permissionCodes.store.delete" v-can="permissionCodes.store.delete"
class="action" class="action"
theme="danger" theme="danger"
@@ -44,9 +44,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { DialogPlugin, Toast } from "tdesign-mobile-vue"; import { DialogPlugin, Toast } from "tdesign-mobile-vue";
import { useUserStore } from "timi-web";
import StoreAPI from "@/api/StoreAPI"; import StoreAPI from "@/api/StoreAPI";
import type { Store, StoreStatus } from "@/types/Store"; import type { Store, StoreStatus } from "@/types/Store";
import { permissionCodes } from "@/utils/permission"; import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
defineOptions({ defineOptions({
name: "StoreEdit" name: "StoreEdit"
@@ -54,7 +55,9 @@ defineOptions({
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const userStore = useUserStore();
const routeId = computed(() => String(route.params.id || "")); const routeId = computed(() => String(route.params.id || ""));
const isStoreManagerScope = computed(() => userStore.hasRoles(gaoRoleCodes.storeManager) && !userStore.hasRoles(gaoRoleCodes.globalManager));
// ---------- 路由权限 ---------- // ---------- 路由权限 ----------
@@ -105,7 +108,34 @@ async function saveStore(): Promise<void> {
isSaving.value = true; isSaving.value = true;
try { try {
const store: Store = { const store = buildStorePayload();
if (isCreateMode.value) {
await StoreAPI.create(store);
} else {
await StoreAPI.update(store);
}
Toast.success("门店已保存");
if (isStoreManagerScope.value) {
return;
}
await router.replace("/management/stores");
} finally {
isSaving.value = false;
}
}
function buildStorePayload(): Store {
if (isStoreManagerScope.value) {
return {
id: formModel.id || undefined,
name: formModel.name,
telephone: formModel.telephone || undefined,
address: formModel.address || undefined,
remark: formModel.remark || undefined
};
}
return {
id: formModel.id || undefined, id: formModel.id || undefined,
code: formModel.code, code: formModel.code,
name: formModel.name, name: formModel.name,
@@ -115,20 +145,10 @@ async function saveStore(): Promise<void> {
remark: formModel.remark || undefined, remark: formModel.remark || undefined,
sort: sortValue.value sort: sortValue.value
}; };
if (isCreateMode.value) {
await StoreAPI.create(store);
} else {
await StoreAPI.update(store);
}
Toast.success("门店已保存");
await router.replace("/management/stores");
} finally {
isSaving.value = false;
}
} }
function validateForm(): boolean { function validateForm(): boolean {
if (!formModel.code) { if (!isStoreManagerScope.value && !formModel.code) {
Toast.warning("请填写门店编码"); Toast.warning("请填写门店编码");
return false; return false;
} }
+23 -4
View File
@@ -48,7 +48,7 @@
:title="item.title" :title="item.title"
arrow arrow
hover hover
@click="go(item.path)" @click="go(item)"
> >
<template #leftIcon> <template #leftIcon>
<t-icon :name="item.icon" size="1.75rem" /> <t-icon :name="item.icon" size="1.75rem" />
@@ -87,6 +87,7 @@ type MenuItem = {
path: string; path: string;
title: string; title: string;
visible: boolean; visible: boolean;
action?: "store";
}; };
type MenuGroup = { type MenuGroup = {
@@ -108,6 +109,7 @@ const currentUserAvatar = computed(() => buildUserAvatar(currentUser.value));
const canSelectStore = computed(() => userStore.hasRoles(gaoRoleCodes.globalManager)); const canSelectStore = computed(() => userStore.hasRoles(gaoRoleCodes.globalManager));
const canLoadLoginStore = computed(() => userStore.hasRoles([gaoRoleCodes.storeManager, gaoRoleCodes.employee], "or")); const canLoadLoginStore = computed(() => userStore.hasRoles([gaoRoleCodes.storeManager, gaoRoleCodes.employee], "or"));
const canViewStore = computed(() => canSelectStore.value || canLoadLoginStore.value); const canViewStore = computed(() => canSelectStore.value || canLoadLoginStore.value);
const canManageStore = computed(() => userStore.hasRoles([gaoRoleCodes.globalManager, gaoRoleCodes.storeManager], "or"));
const canManagePermission = computed(() => ( const canManagePermission = computed(() => (
userStore.hasRoles(coreRoleCodes.admin) || userStore.hasRoles(coreRoleCodes.userRoleAdmin) userStore.hasRoles(coreRoleCodes.admin) || userStore.hasRoles(coreRoleCodes.userRoleAdmin)
) && userStore.hasPermissions([ ) && userStore.hasPermissions([
@@ -166,7 +168,8 @@ const menuGroupList = computed<MenuGroup[]>(() => [
icon: "shop", icon: "shop",
path: "/management/stores", path: "/management/stores",
title: "门店管理", title: "门店管理",
visible: canSelectStore.value && userStore.hasPermissions(permissionCodes.store.read) action: "store",
visible: canManageStore.value && userStore.hasPermissions(permissionCodes.store.read)
}, },
{ {
icon: "usergroup", icon: "usergroup",
@@ -235,8 +238,24 @@ function buildUserAvatar(user?: UserAvatarSource): string {
return UserAPI.getAvatarURL(user) || buildFallbackAvatar(currentUser.value?.name, "#0f766e"); return UserAPI.getAvatarURL(user) || buildFallbackAvatar(currentUser.value?.name, "#0f766e");
} }
async function go(path: string): Promise<void> { async function go(item: MenuItem | string): Promise<void> {
await router.push(path); if (typeof item === "string") {
await router.push(item);
return;
}
if (item.action === "store" && !canSelectStore.value) {
const store = await currentStoreStore.loadLoginStore();
if (!store?.id) {
Toast.warning("未绑定所属门店");
return;
}
await router.push(`/management/stores/${store.id}`);
return;
}
await router.push(item.path);
} }
onMounted(async () => { onMounted(async () => {
+33 -2
View File
@@ -1,4 +1,4 @@
import { createRouter, createWebHistory } from "vue-router"; import { createRouter, createWebHistory, type RouteLocationNormalized } from "vue-router";
import RootLayout from "@/layout/RootLayout.vue"; import RootLayout from "@/layout/RootLayout.vue";
import MainLayout from "@/layout/MainLayout.vue"; import MainLayout from "@/layout/MainLayout.vue";
import Login from "@/pages/Login.vue"; import Login from "@/pages/Login.vue";
@@ -9,7 +9,9 @@ import permissionRoutes from "@/router/routes/permissionRoutes";
import registrationRoutes from "@/router/routes/registrationRoutes"; import registrationRoutes from "@/router/routes/registrationRoutes";
import tabRoutes from "@/router/routes/tabRoutes"; import tabRoutes from "@/router/routes/tabRoutes";
import userRoutes from "@/router/routes/userRoutes"; import userRoutes from "@/router/routes/userRoutes";
import { useCurrentStoreStore } from "@/store/currentStoreStore";
import { useGlobalUIStore } from "@/store/globalUI"; import { useGlobalUIStore } from "@/store/globalUI";
import { gaoRoleCodes } from "@/utils/permission";
import { useUserStore } from "timi-web"; import { useUserStore } from "timi-web";
const detailRoutes = [ const detailRoutes = [
@@ -80,7 +82,7 @@ const router = createRouter({
] ]
}); });
router.beforeEach((to) => { router.beforeEach(async (to) => {
const userStore = useUserStore(); const userStore = useUserStore();
if (to.path === "/login") { if (to.path === "/login") {
return userStore.isLogged() ? "/management" : true; return userStore.isLogged() ? "/management" : true;
@@ -95,9 +97,38 @@ router.beforeEach((to) => {
}; };
} }
const storeAccessRedirect = await resolveStoreAccessRedirect(to);
if (storeAccessRedirect) {
return storeAccessRedirect;
}
return true; return true;
}); });
async function resolveStoreAccessRedirect(to: RouteLocationNormalized): Promise<string | undefined> {
const userStore = useUserStore();
if (!userStore.hasRoles(gaoRoleCodes.storeManager) || userStore.hasRoles(gaoRoleCodes.globalManager)) {
return undefined;
}
const storeRouteNameList = ["StoreList", "StoreCreate", "StoreSort", "StoreEdit", "StoreBusinessDayCalendar"];
if (!storeRouteNameList.includes(String(to.name || ""))) {
return undefined;
}
const currentStoreStore = useCurrentStoreStore();
const store = await currentStoreStore.loadLoginStore();
if (!store?.id) {
return "/management";
}
if (to.name === "StoreEdit" || to.name === "StoreBusinessDayCalendar") {
return String(to.params.id || "") === store.id ? undefined : `/management/stores/${store.id}`;
}
return `/management/stores/${store.id}`;
}
router.afterEach((to) => { router.afterEach((to) => {
const globalUIStore = useGlobalUIStore(); const globalUIStore = useGlobalUIStore();
const isDarkMode = globalUIStore.themeMode === "dark"; const isDarkMode = globalUIStore.themeMode === "dark";
+2 -3
View File
@@ -22,10 +22,9 @@ export type EventRecord = {
export type EventRecordListItemView = { export type EventRecordListItemView = {
id?: string; id?: string;
customerId?: string; customerId?: string;
customerName?: string; customer?: Customer;
customerPhotoAttachmentId?: string;
eventId?: string; eventId?: string;
eventName?: string; event?: EventItem;
registeredAt?: number; registeredAt?: number;
}; };