diff --git a/src/api/ConsumptionRecordAPI.ts b/src/api/ConsumptionRecordAPI.ts new file mode 100644 index 0000000..41e875b --- /dev/null +++ b/src/api/ConsumptionRecordAPI.ts @@ -0,0 +1,11 @@ +import { axios } from "timi-web-api"; +import type { ConsumptionRecordPage, ConsumptionRecordPageResult } from "@/types/ConsumptionRecord"; +import { withCurrentStoreId } from "@/utils/store"; + +const BASE_URI = "/gao/customer/consumption-record"; + +async function list(page: ConsumptionRecordPage): Promise { + return await axios.post(`${BASE_URI}/list`, withCurrentStoreId(page)); +} + +export default { list }; diff --git a/src/pages/event/EventRecordDetail.vue b/src/pages/event/EventRecordDetail.vue index 651a84e..1fd96b1 100644 --- a/src/pages/event/EventRecordDetail.vue +++ b/src/pages/event/EventRecordDetail.vue @@ -112,7 +112,7 @@ import type { PhotoItem } from "@/types/Photo"; import type { PointLedgerChangeType } from "@/types/Point"; import { getAttachmentReadURL } from "@/utils/attachment"; import { buildEventOptionSelectionMap } from "@/utils/eventOption"; -import { getEventBizTypeText, isPackagePurchaseEvent } from "@/utils/event"; +import { getEventBizTypeText, isRetiredEvent } from "@/utils/event"; import { getErrorMessage } from "@/utils/error"; import { formatEventNumberValue } from "@/utils/eventValue"; import { Message } from "@/utils/message"; @@ -135,10 +135,10 @@ const isVerifying = ref(false); const isDeleting = ref(false); const verifyDialogVisible = ref(false); -const isPackagePurchaseRecord = computed(() => isPackagePurchaseEvent(record.value?.event)); -const canUpdateRecord = computed(() => !!record.value && !isPackagePurchaseRecord.value && userStore.hasPermissions(permissionCodes.eventRecord.update)); -const canVerifyRecord = computed(() => !!record.value && !isPackagePurchaseRecord.value && userStore.hasPermissions(permissionCodes.eventRecord.verify)); -const canDeleteRecord = computed(() => !!record.value && !isPackagePurchaseRecord.value && userStore.hasPermissions(permissionCodes.eventRecord.delete)); +const isRetiredRecord = computed(() => isRetiredEvent(record.value?.event)); +const canUpdateRecord = computed(() => !!record.value && !isRetiredRecord.value && userStore.hasPermissions(permissionCodes.eventRecord.update)); +const canVerifyRecord = computed(() => !!record.value && !isRetiredRecord.value && userStore.hasPermissions(permissionCodes.eventRecord.verify)); +const canDeleteRecord = computed(() => !!record.value && !isRetiredRecord.value && userStore.hasPermissions(permissionCodes.eventRecord.delete)); const canReadEvent = computed(() => userStore.hasPermissions(permissionCodes.event.read)); const recordPhotoItemList = computed(() => (record.value?.attachmentList || []) .filter(item => !!item.id) @@ -152,7 +152,7 @@ const recordPhotoList = computed(() => recordPhotoItemList.value.map(item => ite async function submitPhotoItems(photoItems: PhotoItem[]): Promise { const currentRecord = record.value; - if (!currentRecord?.id || isPackagePurchaseRecord.value) { + if (!currentRecord?.id || isRetiredRecord.value) { throw new Error("登记记录不存在"); } @@ -263,7 +263,7 @@ async function confirmVerifyRecord(): Promise { async function submitVerifyRecord(record: EventRecord, attachmentList: Attachment[]): Promise { const id = record.id; - if (!id || isPackagePurchaseRecord.value) { + if (!id || isRetiredRecord.value) { throw new Error("登记事件记录不存在"); } @@ -316,7 +316,7 @@ function confirmRemoveRecord(): void { } async function removeRecord(id: string): Promise { - if (isDeleting.value || isPackagePurchaseRecord.value) { + if (isDeleting.value || isRetiredRecord.value) { return; } diff --git a/src/pages/salesOrder/ConsumptionRecordList.vue b/src/pages/salesOrder/ConsumptionRecordList.vue new file mode 100644 index 0000000..3e25dd3 --- /dev/null +++ b/src/pages/salesOrder/ConsumptionRecordList.vue @@ -0,0 +1,323 @@ + + + + + diff --git a/src/pages/tabs/ProductTab.vue b/src/pages/tabs/ProductTab.vue index 22afca9..02c2824 100644 --- a/src/pages/tabs/ProductTab.vue +++ b/src/pages/tabs/ProductTab.vue @@ -99,6 +99,12 @@ const menuGroupList = computed(() => [ path: "/management/order-fulfillments", title: "统一履约", visible: userStore.hasPermissions(permissionCodes.orderFulfillment.read) + }, + { + icon: "money", + path: "/management/consumption-records", + title: "消费记录", + visible: userStore.hasPermissions(permissionCodes.salesOrder.read) } ] }, diff --git a/src/router/routes/salesOrderRoutes.ts b/src/router/routes/salesOrderRoutes.ts index 7542df0..96993a7 100644 --- a/src/router/routes/salesOrderRoutes.ts +++ b/src/router/routes/salesOrderRoutes.ts @@ -9,6 +9,7 @@ import SalesOrderCancel from "@/pages/salesOrder/SalesOrderCancel.vue"; import FundRecordList from "@/pages/salesOrder/FundRecordList.vue"; import FundRecordDetail from "@/pages/salesOrder/FundRecordDetail.vue"; import FundRecordRevoke from "@/pages/salesOrder/FundRecordRevoke.vue"; +import ConsumptionRecordList from "@/pages/salesOrder/ConsumptionRecordList.vue"; function meta(title: string, depth = 3, background = "#F5F5F8"): RouteRecordRaw["meta"] { return { depth, navBarVisible: true, navBarCanBack: true, navBarTitle: title, tabBarVisible: false, bodyBackground: background, darkBodyBackground: "#10161f" }; @@ -16,6 +17,7 @@ function meta(title: string, depth = 3, background = "#F5F5F8"): RouteRecordRaw[ export default [ { path: "/management/sales-orders", name: "SalesOrderList", component: SalesOrderList, meta: meta("销售订单") }, + { path: "/management/consumption-records", name: "ConsumptionRecordList", component: ConsumptionRecordList, meta: meta("消费记录") }, { path: "/management/sales-orders/create", name: "SalesOrderCreate", diff --git a/src/types/ConsumptionRecord.ts b/src/types/ConsumptionRecord.ts new file mode 100644 index 0000000..d49c808 --- /dev/null +++ b/src/types/ConsumptionRecord.ts @@ -0,0 +1,43 @@ +import type { Model, PageResult } from "timi-web-api"; +import type { Customer } from "@/types/Customer"; +import type { GaoSalesOrderType } from "@/types/SalesOrder"; + +export type ConsumptionRecordSourceType = "LEGACY_EVENT" | "SALES_ORDER"; +export type ConsumptionRecordStatus = "ACTIVE" | "REVOKED"; + +export type ConsumptionRecord = { + storeId?: string; + customerId?: string; + sourceType?: ConsumptionRecordSourceType; + sourceId?: string; + salesOrderId?: string; + orderType?: GaoSalesOrderType; + amount?: number; + effectiveAt?: number; + status?: ConsumptionRecordStatus; + revokedAt?: number; + revokeReason?: string | null; + sourcePayload?: { + eventId?: string; + eventName?: string; + eventRecordId?: string; + migrationBatch?: string; + registeredAt?: number; + }; + customer?: Customer; +} & Model; + +export type ConsumptionRecordPage = { + storeId?: string; + customerId?: string; + sourceType?: ConsumptionRecordSourceType; + status?: ConsumptionRecordStatus; + beginAt?: number; + endAt?: number; + index: number; + size: number; +}; + +export type ConsumptionRecordPageResult = PageResult & { + amountTotal?: number; +};