|
|
@@ -0,0 +1,194 @@
|
|
|
+<template>
|
|
|
+ <view class="price-card" v-if="hasAnyPrice">
|
|
|
+ <view class="card-header">
|
|
|
+ <view class="header-row">
|
|
|
+ <view class="header-dot"></view>
|
|
|
+ <text class="header-title">收费标准<text class="header-tip">(以场地设备实际功能为准)</text></text>
|
|
|
+ <view class="header-close" @click="emit('close')">
|
|
|
+ <text class="close-icon">✕</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="price-grid">
|
|
|
+ <view class="price-item" v-for="item in priceItems" :key="item.label">
|
|
|
+ <text class="price-label">{{ item.label }}</text>
|
|
|
+ <text class="price-value">{{ fmtYuanPerMin(item.value) }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="price-footer" v-if="amountMinLimit != null || prepayMoney != null">
|
|
|
+ <view class="footer-item" v-if="amountMinLimit != null && amountMinLimit > 0">
|
|
|
+ <text class="footer-label">最低消费</text>
|
|
|
+ <text class="footer-value">¥{{ (amountMinLimit / 100).toFixed(2) }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="footer-item" v-if="prepayMoney != null && prepayMoney > 0">
|
|
|
+ <text class="footer-label">单次上限</text>
|
|
|
+ <text class="footer-value">¥{{ (prepayMoney / 100).toFixed(2) }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts" name="PriceTable">
|
|
|
+import { computed } from "vue";
|
|
|
+
|
|
|
+const PRICE_LABELS: Record<string, string> = {
|
|
|
+ priceSpace: "场地费",
|
|
|
+ priceWater: "清水",
|
|
|
+ priceFoam: "泡沫",
|
|
|
+ priceCleaner: "吸尘",
|
|
|
+ priceTap: "洗手",
|
|
|
+ priceUserExt: "扩展项目",
|
|
|
+ priceCoat: "镀膜",
|
|
|
+ priceBlow: "吹气",
|
|
|
+};
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ price: {
|
|
|
+ type: Object,
|
|
|
+ default: null,
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+const emit = defineEmits(["close"]);
|
|
|
+
|
|
|
+const amountMinLimit = computed(() => props.price?.amountMinLimit);
|
|
|
+const prepayMoney = computed(() => props.price?.prepayMoney);
|
|
|
+
|
|
|
+const hasAnyPrice = computed(() => {
|
|
|
+ if (!props.price) return false;
|
|
|
+ return Object.keys(PRICE_LABELS).some((key) => props.price[key] != null);
|
|
|
+});
|
|
|
+
|
|
|
+const priceItems = computed(() => {
|
|
|
+ if (!props.price) return [];
|
|
|
+ return Object.entries(PRICE_LABELS)
|
|
|
+ .filter(([key]) => props.price[key] != null)
|
|
|
+ .map(([key, label]) => ({ label, value: props.price[key] }));
|
|
|
+});
|
|
|
+
|
|
|
+const fmtYuanPerMin = (fen: number) => {
|
|
|
+ if (fen == null) return "";
|
|
|
+ const yuan = fen / 100;
|
|
|
+ return yuan % 1 === 0 ? `¥${yuan}/分钟` : `¥${yuan.toFixed(2)}/分钟`;
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.price-card {
|
|
|
+ width: 580rpx;
|
|
|
+ max-height: 80vh;
|
|
|
+ background: $uni-bg-color-card;
|
|
|
+ border-radius: 24rpx;
|
|
|
+ overflow: hidden;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+
|
|
|
+ .card-header {
|
|
|
+ padding: 32rpx 32rpx 0;
|
|
|
+
|
|
|
+ .header-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-dot {
|
|
|
+ width: 10rpx;
|
|
|
+ height: 10rpx;
|
|
|
+ background: $uni-color-primary;
|
|
|
+ border-radius: 50%;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-title {
|
|
|
+ font-size: 30rpx;
|
|
|
+ font-weight: $uni-font-weight-semibold;
|
|
|
+ color: $uni-text-color-dark;
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-close {
|
|
|
+ width: 48rpx;
|
|
|
+ height: 48rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: $uni-bg-color-page;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ .close-icon {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: $uni-text-color-tertiary;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-tip {
|
|
|
+ font-size: 22rpx;
|
|
|
+ color: $uni-text-color-tertiary;
|
|
|
+ font-weight: $uni-font-weight-normal;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .price-grid {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ padding: 24rpx 32rpx 12rpx;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ .price-item {
|
|
|
+ width: 50%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 14rpx 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ &:nth-child(odd) {
|
|
|
+ padding-right: 20rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:nth-child(even) {
|
|
|
+ padding-left: 20rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .price-label {
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: $uni-text-color-hint;
|
|
|
+ }
|
|
|
+
|
|
|
+ .price-value {
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: $uni-color-primary;
|
|
|
+ font-weight: $uni-font-weight-semibold;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .price-footer {
|
|
|
+ display: flex;
|
|
|
+ gap: 32rpx;
|
|
|
+ padding: 16rpx 32rpx 32rpx;
|
|
|
+ border-top: 1rpx solid $uni-border-color-light;
|
|
|
+
|
|
|
+ .footer-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8rpx;
|
|
|
+
|
|
|
+ .footer-label {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: $uni-text-color-tertiary;
|
|
|
+ }
|
|
|
+
|
|
|
+ .footer-value {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: $uni-text-color-dark;
|
|
|
+ font-weight: $uni-font-weight-medium;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|