Files
pricing.tootaio.com/app/components/eventOrder/OrderSummary.vue
xiaomai a5ac00baa1 feat(pricing): introduce real-time budget estimator
This commit introduces a real-time budget estimator for event services. A new summary sidebar now displays a live,
itemized breakdown of costs as the user selects options in the order form.

Key changes include:
- A new `OrderSummary` component to display the price breakdown and total.
- Comprehensive pricing logic implemented in the `useEventOrder` composable.
- A responsive two-column layout on the main page to accommodate the summary.
- UI/UX improvements across the form, including clearer labels and subtle transition animations for conditional fields.
2025-10-16 21:14:44 +08:00

78 lines
2.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<UCard class="lg:sticky lg:top-24">
<template #header>
<div class="flex items-center justify-between">
<h2 class="text-xl font-bold">预算估算</h2>
<UBadge color="primary" variant="soft">实时</UBadge>
</div>
<p class="text-muted text-sm">基于所选服务动态计算</p>
</template>
<div class="space-y-3">
<div v-if="items.length === 0" class="text-muted text-sm">
当前未选择任何可计价项目
</div>
<div v-else class="space-y-3">
<div
v-for="(it, idx) in items"
:key="idx"
class="flex items-start justify-between gap-3 border-b border-[--ui-border] pb-2"
>
<div>
<div class="font-medium">{{ it.label }}</div>
<div v-if="it.note" class="text-muted text-xs">{{ it.note }}</div>
</div>
<div class="font-semibold">{{ money.format(it.amount) }}</div>
</div>
</div>
</div>
<template #footer>
<div class="flex items-center justify-between">
<div class="text-lg font-bold">合计</div>
<div class="text-2xl font-extrabold tracking-tight">
{{ money.format(total) }}
</div>
</div>
<div class="mt-3 flex items-center gap-2">
<UButton
color="primary"
size="lg"
block
:disabled="total === 0"
icon="lucide:send"
@click="onRequestQuote"
>
获取详细报价
</UButton>
</div>
<UAlert
class="mt-3"
title="说明"
color="neutral"
variant="subtle"
description="该预算为参考价,具体以需求细化及工期排期为准。"
/>
</template>
</UCard>
</template>
<script lang="ts" setup>
const { priceBreakdown, estimatedTotal, money } = useEventOrder();
const items = computed(() => priceBreakdown.value);
const total = computed(() => estimatedTotal.value);
function onRequestQuote() {
// Placeholder interaction (no backend). Could open mailto or copy summary.
const lines = items.value.map(
(i) =>
`${i.label}${money.format(i.amount)}${i.note ? `${i.note}` : ""}`
);
const text = `预算合计:${money.format(total.value)}\n\n` + lines.join("\n");
if (navigator?.clipboard) navigator.clipboard.writeText(text).catch(() => {});
}
</script>
<style></style>