From e1fc007a67b7e4de15ad7bbd68a61399a2fa0436 Mon Sep 17 00:00:00 2001 From: Timi Date: Thu, 20 Aug 2026 16:50:38 +0800 Subject: [PATCH] fix submit button position --- src/components/CustomerSelector.vue | 8 ---- src/pages/customer/CustomerEdit.vue | 62 ++++++++++++++++++++--------- src/pages/customer/CustomerList.vue | 24 +++++------ src/pages/event/EventRecordEdit.vue | 28 +++++++------ src/pages/home/QuickEntryPage.vue | 47 +++++++++++++++++----- 5 files changed, 107 insertions(+), 62 deletions(-) diff --git a/src/components/CustomerSelector.vue b/src/components/CustomerSelector.vue index a33bf40..c3b327a 100644 --- a/src/components/CustomerSelector.vue +++ b/src/components/CustomerSelector.vue @@ -30,7 +30,6 @@ :empty-text="loading ? '正在加载客户' : '未找到匹配客户'" @select="toggleCustomer" /> -
@@ -75,13 +74,6 @@ let searchToken = 0; let keywordTimer: number | undefined; const isMultiple = computed(() => props.selectionMode === "multiple"); -const loadStateText = computed(() => { - if (loading.value) { - return "正在加载更多"; - } - - return noMore.value ? `共 ${totalCount.value} 位客户` : "上拉加载更多"; -}); const popupVisible = computed({ get() { diff --git a/src/pages/customer/CustomerEdit.vue b/src/pages/customer/CustomerEdit.vue index 836838b..57519b2 100644 --- a/src/pages/customer/CustomerEdit.vue +++ b/src/pages/customer/CustomerEdit.vue @@ -147,18 +147,6 @@ accept="image/*" @change="handlePhotoSelected" > - - - 保存 - route.name === "CustomerCreate"); const savePermissionCode = computed(() => isCreateMode.value ? permissionCodes.customer.create : permissionCodes.customer.update); +const hasCustomerDeletePermission = computed(() => userStore.hasPermissions(permissionCodes.customer.delete)); const isGlobalManager = computed(() => userStore.hasRoles(gaoRoleCodes.globalManager)); let latestDecodedText = ""; @@ -457,6 +448,14 @@ async function loadDetail() { } } onMounted(loadDetail); + +onMounted(() => { + navBarStore.clearRight(); + if (userStore.hasPermissions(savePermissionCode.value)) { + navBarStore.setRightText("保存", "var(--td-brand-color)", doSubmit); + } +}); + watch(() => route.fullPath, loadDetail); // ---------- 年龄 ---------- @@ -524,6 +523,23 @@ function normalizeAttachmentType(attachType?: string): CustomerAttachmentType { return "PHOTO"; } +function validateCustomerPhotoList(): boolean { + if (hasCustomerDeletePermission.value) { + return true; + } + + const attachTypeSet = new Set(photoItemList.value.map(item => item.attachType)); + if (!attachTypeSet.has("PHOTO")) { + Toast.warning("请上传客户照片"); + return false; + } + if (!attachTypeSet.has("POINT_CARD")) { + Toast.warning("请上传积分卡照片"); + return false; + } + return true; +} + async function handlePhotoSelected(event: Event): Promise { const input = event.target as HTMLInputElement; const file = input.files?.[0]; @@ -552,10 +568,20 @@ async function handlePhotoSelected(event: Event): Promise { const isSubmitting = ref(false); async function doSubmit(): Promise { - if (!formData.storeId) { + if (isSubmitting.value) { + return; + } + if (!canSubmit.value) { + if (!formData.name?.trim()) { + Toast.warning("请填写姓名"); + return; + } Toast.warning("请选择门店"); return; } + if (!validateCustomerPhotoList()) { + return; + } isSubmitting.value = true; try { @@ -594,6 +620,10 @@ async function doSubmit(): Promise { } } +onUnmounted(() => { + navBarStore.clearRight(); +}); + function buildAttachmentList(): Attachment[] { return photoItemList.value.flatMap(item => { if (item.attachment) { @@ -660,12 +690,6 @@ function buildAttachmentList(): Attachment[] { display: none; } - .save { - left: 1rem; - right: 1rem; - bottom: calc(.75rem + env(safe-area-inset-bottom, 0)); - position: fixed; - } } :global(html.theme-dark) { diff --git a/src/pages/customer/CustomerList.vue b/src/pages/customer/CustomerList.vue index 1123a14..704f283 100644 --- a/src/pages/customer/CustomerList.vue +++ b/src/pages/customer/CustomerList.vue @@ -96,17 +96,6 @@ 导出 - - - 添加 - userStore.hasRoles(gaoRoleCodes.globalManager)); @@ -239,6 +230,13 @@ async function loadData(): Promise { onMounted(loadData); +onMounted(() => { + navBarStore.clearRight(); + if (userStore.hasPermissions(permissionCodes.customer.create)) { + navBarStore.setRightText("添加", "var(--td-brand-color)", toCreate); + } +}); + watch(keyword, async () => { window.clearTimeout(keywordTimer); keywordTimer = window.setTimeout(async () => { @@ -247,6 +245,7 @@ watch(keyword, async () => { }); onUnmounted(() => { + navBarStore.clearRight(); window.clearTimeout(keywordTimer); }); @@ -371,9 +370,6 @@ async function doExport(): Promise { flex: 1; } - .create { - flex: 2; - } } } diff --git a/src/pages/event/EventRecordEdit.vue b/src/pages/event/EventRecordEdit.vue index 5dcf7b3..d8afaf4 100644 --- a/src/pages/event/EventRecordEdit.vue +++ b/src/pages/event/EventRecordEdit.vue @@ -167,9 +167,6 @@ multiple @change="handleRecordPhotoSelected" > - - - ; @@ -590,9 +589,10 @@ const note = ref(""); const isSaving = ref(false); const editingRecord = ref(); -const canSubmit = computed(() => selectedCustomerList.value.some(item => !!item.id) && 0 < selectedEventIdList.value.length); - async function submitRecord(): Promise { + if (isSaving.value) { + return; + } if (!validateForm()) { return; } @@ -731,6 +731,17 @@ async function loadRecordForEdit(): Promise { onMounted(loadPageData); +onMounted(() => { + navBarStore.clearRight(); + if (userStore.hasPermissions(pageAccess.value)) { + navBarStore.setRightText(saveButtonText.value, "var(--td-brand-color)", submitRecord); + } +}); + +onUnmounted(() => { + navBarStore.clearRight(); +}); + watch(selectedEventIdList, async () => { await loadSourceValueRule(); }, { deep: true }); @@ -833,13 +844,6 @@ watch(customerCode, async (value) => { border-radius: 1rem; } - .save { - left: 1rem; - right: 1rem; - bottom: calc(.75rem + env(safe-area-inset-bottom, 0)); - position: fixed; - } - .file-input { display: none; } diff --git a/src/pages/home/QuickEntryPage.vue b/src/pages/home/QuickEntryPage.vue index 819d6d8..e3214e2 100644 --- a/src/pages/home/QuickEntryPage.vue +++ b/src/pages/home/QuickEntryPage.vue @@ -126,7 +126,6 @@ multiple @change="handleRecordPhotoSelected" > - 提交 userStore.hasPermissions(permissionCodes.customer.delete)); const eventList = ref([]); @@ -243,7 +244,6 @@ function validateNumberValueList(): boolean { const note = ref(""); const saving = ref(false); -const canSubmit = computed(() => !!inputCode.value && !!customerName.value.trim() && !customerPhotoUploading.value && !recordPhotoUploading.value); let latestDecodedText = ""; @@ -539,6 +539,23 @@ function normalizeCustomerAttachmentType(attachType?: string): CustomerAttachmen return "PHOTO"; } +function validateCustomerPhotoList(): boolean { + if (hasCustomerDeletePermission.value) { + return true; + } + + const attachTypeSet = new Set(customerPhotoItemList.value.map(item => item.attachType)); + if (!attachTypeSet.has("PHOTO")) { + showToast("请上传客户照片", "warning"); + return false; + } + if (!attachTypeSet.has("POINT_CARD")) { + showToast("请上传积分卡照片", "warning"); + return false; + } + return true; +} + async function handleCustomerPhotoSelected(event: Event): Promise { const input = event.target as HTMLInputElement; const file = input.files?.[0]; @@ -611,6 +628,13 @@ async function handleRecordPhotoSelected(event: Event): Promise { // ---------- 提交 ---------- async function saveRecord(): Promise { + if (saving.value) { + return; + } + if (customerPhotoUploading.value || recordPhotoUploading.value) { + showToast("照片正在上传,请稍候", "warning"); + return; + } const customerCode = validateForm(); if (!customerCode) { return; @@ -704,6 +728,9 @@ function validateForm(): string { showToast("请填写客户姓名", "warning"); return ""; } + if (!validateCustomerPhotoList()) { + return ""; + } if (!validateNumberValueList()) { return ""; } @@ -729,9 +756,17 @@ function showToast(message: string, theme: "success" | "warning" = "success"): v // ---------- 初始化 ---------- onMounted(async () => { + navBarStore.clearRight(); + if (userStore.hasPermissions(permissionCodes.eventRecord.create)) { + navBarStore.setRightText("保存", "var(--td-brand-color)", saveRecord); + } eventList.value = await EventAPI.listValid(); }); +onUnmounted(() => { + navBarStore.clearRight(); +}); + watch(selectedEventIdList, async () => { await loadSourceValueRule(); }, { deep: true }); @@ -797,12 +832,6 @@ watch(scanCode, (value) => { border-radius: 1rem; } - .save { - left: 1rem; - right: 1rem; - bottom: calc(.75rem + env(safe-area-inset-bottom, 0)); - position: fixed; - } } :global(html.theme-dark) {