Files
gao-customer-h5/src/pages/store/StoreEdit.vue
T
2026-09-15 13:13:39 +08:00

220 lines
5.7 KiB
Vue

<template>
<div v-can="savePermissionCode" class="store-edit">
<t-form class="form" label-align="left" v-entrance-transition>
<t-form-item v-if="!isStoreManagerScope" label="编码">
<t-input v-model.trim="formData.code" placeholder="门店编码" borderless />
</t-form-item>
<t-form-item label="名称">
<t-input v-model.trim="formData.name" placeholder="门店名称" borderless />
</t-form-item>
<t-form-item v-if="!isStoreManagerScope" label="启用" content-align="right">
<t-switch v-model="formData.status" :custom-value="['ACTIVE', 'INACTIVE']" />
</t-form-item>
<t-form-item label="电话">
<t-input v-model.trim="formData.telephone" type="tel" placeholder="联系电话" borderless />
</t-form-item>
<t-form-item label="地址">
<t-input v-model.trim="formData.address" placeholder="门店地址" borderless />
</t-form-item>
<t-form-item label="备注">
<t-textarea v-model.trim="formData.remark" class="textarea" placeholder="备注" autosize borderless />
</t-form-item>
</t-form>
<t-cell-group v-if="!isCreateMode" theme="card" v-entrance-transition="70">
<t-cell
title="营业日管理"
note="配置营业或休息日期"
arrow
@click="router.push(`/management/stores/${routeId}/business-days`)"
/>
<t-cell
title="自动休息日"
description="全天无任何登记记录时自动判定为休息日,休息日不视为中断连续登记事件"
>
<template #right-icon>
<t-switch v-model="formData.autoClosedDay" />
</template>
</t-cell>
</t-cell-group>
<t-button
v-if="!isCreateMode && !isStoreManagerScope"
v-can="permissionCodes.store.delete"
class="cell-button"
theme="danger"
:loading="isRemoving"
content="删除"
v-entrance-transition="140"
@click="confirmRemoveStore"
/>
<store-remove-dialog
v-model:visible="removeDialogVisible"
:store="formData"
:loading="isRemoving"
@confirm="removeConfirmedStore"
/>
</div>
</template>
<script setup lang="ts">
import { useUserStore } from "timi-web-api";
import StoreAPI from "@/api/StoreAPI";
import StoreRemoveDialog from "@/components/StoreRemoveDialog.vue";
import { useCurrentStoreStore } from "@/store/currentStoreStore";
import { useNavBarStore } from "@/store/navBarStore";
import type { Store, StoreStatus } from "@/types/Store";
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
import { Message } from "@/utils/message.ts";
defineOptions({
name: "StoreEdit"
});
const route = useRoute();
const router = useRouter();
const navBarStore = useNavBarStore();
const userStore = useUserStore();
const currentStoreStore = useCurrentStoreStore();
const routeId = computed(() => String(route.params.id || ""));
const isStoreManagerScope = computed(() => userStore.hasRoles(gaoRoleCodes.storeManager) && !userStore.hasRoles(gaoRoleCodes.globalManager));
// ---------- 路由权限 ----------
const isCreateMode = computed(() => !routeId.value);
const savePermissionCode = computed(() => isCreateMode.value ? permissionCodes.store.create : permissionCodes.store.update);
// ---------- 表单 ----------
const isSaving = ref(false);
const isRemoving = ref(false);
const removeDialogVisible = ref(false);
const formData = reactive({
id: "",
code: "",
name: "",
status: "ACTIVE" as StoreStatus,
telephone: "",
address: "",
remark: "",
autoClosedDay: true
});
async function doSave(): Promise<void> {
if (!validateForm()) {
return;
}
isSaving.value = true;
try {
if (isCreateMode.value) {
await StoreAPI.create(formData);
} else {
await StoreAPI.update(formData);
await refreshCurrentStore();
}
Message.success("门店已保存");
if (userStore.hasPermissions(permissionCodes.store.create)) {
await router.replace("/management/stores");
} else {
await router.replace("/store");
}
} finally {
isSaving.value = false;
}
}
async function refreshCurrentStore(): Promise<void> {
if (formData.id !== currentStoreStore.currentStoreId) {
return;
}
await currentStoreStore.refreshCurrentStore(formData.id);
}
function validateForm(): boolean {
if (!isStoreManagerScope.value && !formData.code) {
Message.warning("请填写门店编码");
return false;
}
if (!formData.name) {
Message.warning("请填写门店名称");
return false;
}
return true;
}
onMounted(async () => {
if (userStore.hasPermissions(savePermissionCode.value)) {
navBarStore.setRightText("保存", "var(--td-brand-color)", doSave);
}
try {
if (!routeId.value) {
return;
}
const current = await StoreAPI.detail(routeId.value);
Object.assign(formData, current);
} catch {
Message.error("门店数据加载失败");
}
});
onUnmounted(() => navBarStore.clearRight());
// ---------- 删除 ----------
async function confirmRemoveStore(): Promise<void> {
if (!formData.id || isRemoving.value) {
return;
}
removeDialogVisible.value = true;
}
function closeRemoveDialog(): void {
removeDialogVisible.value = false;
}
async function removeConfirmedStore(store: Store): Promise<void> {
if (!store.id || isRemoving.value) {
return;
}
closeRemoveDialog();
await removeStore(store.id);
}
async function removeStore(id: string): Promise<void> {
if (isRemoving.value) {
return;
}
isRemoving.value = true;
try {
await StoreAPI.remove(id);
Message.success("门店已删除");
await router.replace("/management/stores");
} finally {
isRemoving.value = false;
}
}
</script>
<style scoped lang="less">
.store-edit {
gap: 1rem;
padding: calc(var(--app-nav-height) + 1rem) 0 calc(1rem + env(safe-area-inset-bottom, 0)) 0;
display: flex;
flex-direction: column;
.form {
border-radius: .75rem;
}
.textarea {
width: 100%;
}
.links {
margin: 1rem 0;
}
}
</style>