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) {