diff --git a/.gitignore b/.gitignore index 7dc2675b..f9f34c89 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ # 临时文件 *.tmp *.temp +/tmp # 日志文件 *.log diff --git a/src/views/hard/hard-coffee-log/index.vue b/src/views/hard/hard-coffee-log/index.vue index e61b757c..b26293e4 100644 --- a/src/views/hard/hard-coffee-log/index.vue +++ b/src/views/hard/hard-coffee-log/index.vue @@ -40,57 +40,101 @@ style="float: right" @queryTable="getDataList(false)"> - + - - + - + - - - - - - - - + - + - - - + + + +
+ +
{{ payloadDialog.raw }}
+
+ +
+ + diff --git a/src/views/hard/hard-coffee-order/index.vue b/src/views/hard/hard-coffee-order/index.vue index de639be0..b3031a0c 100644 --- a/src/views/hard/hard-coffee-order/index.vue +++ b/src/views/hard/hard-coffee-order/index.vue @@ -3,8 +3,8 @@
+ :loading="Boolean(state.loading)" :search-text="$t('common.queryBtn')" + :reset-text="$t('common.resetBtn')" @search="getDataList(false)" @reset="resetQuery"> @@ -35,90 +35,260 @@ style="float: right" @queryTable="getDataList(false)">
- - - - - - - - - - - - - - - - + + - + - + - + + + + + + + + + + + + + + + + - + -
+
+
+ + +
@@ -130,8 +300,12 @@ import { useDict } from "/@/hooks/dict" /** 咖啡机生命周期时间线组件,详情抽屉内复用。 */ const HardCoffeeLog = defineAsyncComponent(() => import("../components/hard-coffee-log.vue")) +/** 后台退款弹窗,复用硬件订单页的售后退款流程,按本地订单id操作。 */ +const AdminRefundDialog = defineAsyncComponent(() => import("../hard-order/components/admin-refund-dialog/index.vue")) +const adminRefundDialogRef = ref() + // 定义查询字典 -const { hard_order_status } = useDict("hard_order_status") +const { hard_order_status, hard_pay_type } = useDict("hard_order_status", "hard_pay_type") const route = useRoute() @@ -153,6 +327,13 @@ const detailVisible = ref(false) const detailLoading = ref(false) const coffeeDetail = reactive<{ order?: Record }>({}) +/** 无平台账号的支付用户(userId 为空或 -1)按散客展示。 */ +function hasOrderUser(row?: Record | null) { + return Boolean(row) && row!.userId && row!.userId != -1 +} + +const hasDetailUser = computed(() => hasOrderUser(coffeeDetail.order)) + /** 金额单位为分,换算为两位小数元展示。 */ function formatPrice(price: unknown): string { if (price === null || price === undefined || price === "") return "-" @@ -161,18 +342,50 @@ function formatPrice(price: unknown): string { return (fen / 100).toFixed(2) } +async function loadDetail(id: string) { + const { data } = await hardCoffeeApi.fetchOrderDetail(id) + coffeeDetail.order = data?.order || {} +} + async function openDetail(row: any) { detailVisible.value = true detailLoading.value = true coffeeDetail.order = undefined try { - const { data } = await hardCoffeeApi.fetchOrderDetail(String(row.id)) - coffeeDetail.order = data?.order || {} + await loadDetail(String(row.id)) } finally { detailLoading.value = false } } +/** 与硬件订单页退款入口保持一致的前置条件:已实际支付、未退完且支付方式支持原路退款。 */ +function canRefund(row?: Record | null) { + if (!row || !row.orderId) return false + // 未支付订单的 payPrice 是创建时预填的应付金额,必须以支付时间存在为已支付依据 + if (!row.payTime) return false + const payPrice = Number(row.payPrice) + const refundPrice = Number(row.refundPrice ?? 0) + return Number.isFinite(payPrice) && payPrice > 0 + && refundPrice < payPrice + && !["5", "6", "8"].includes(String(row.payType ?? "")) +} + +function openRefund(row: any) { + adminRefundDialogRef.value?.openDialog(String(row.orderId)) +} + +/** 退款成功后刷新列表;详情抽屉打开时同步重取详情。 */ +async function handleRefundRefresh() { + getDataList(false) + if (detailVisible.value && coffeeDetail.order?.id) { + try { + await loadDetail(String(coffeeDetail.order.id)) + } catch (e) { + console.error(e) + } + } +} + // 清空搜索条件 const resetQuery = () => { // 保留从设备详情带入的设备过滤 @@ -186,3 +399,57 @@ onMounted(() => { getDataList() }) + + diff --git a/src/views/hard/hard-manager/coffee-machine-section.vue b/src/views/hard/hard-manager/coffee-machine-section.vue index 92d5a423..6eaa9e0d 100644 --- a/src/views/hard/hard-manager/coffee-machine-section.vue +++ b/src/views/hard/hard-manager/coffee-machine-section.vue @@ -1,7 +1,6 @@