在许多电子商务网站中,用户经常需要根据自己的喜好定制产品。本文将介绍如何使用 Vue 构建一个交互式披萨定制界面,允许用户选择披萨的大小、外皮、浇头和配料,并实时更新总价。
此 Vue 组件提供了以下功能:
npm install vue vue-router echarts-for-vue v-calendar vue3-baidu-map-gl @wangeditor/editor-for-vue
<template>
<div class="bg-gray-100">
<!-- 导航栏 -->
<div class="flex items-center justify-between p-4 border-b border-gray-200">
<a-back-top />
<div class="text-lg font-semibold">Detail</div>
<a-button type="link" icon={<MessageOutlined />} />
</div>
<!-- 披萨图片 -->
<div class="flex items-center justify-center">
<img
class="w-48 h-48 rounded-full object-cover"
src="https://source.unsplash.com/random/400x400"
alt="Pizza"
/>
</div>
<!-- 披萨信息 -->
<div class="p-4">
<h2 class="text-2xl font-semibold">Margherita with Tomatoes</h2>
<div class="flex items-center mt-2">
<a-rate allow-half value={3} disabled />
<span class="ml-2 text-sm text-gray-500">3.5</span>
</div>
<div class="mt-4">
<p class="text-gray-500">
Mauris eu erat quis ante bibendum eleifend. Curabitur egestas sapien sit amet porta sagittis. In semper nibh ac ipsum tempor egestas.
</p>
</div>
<!-- 披萨定制选项 -->
<div class="mt-4">
<div class="text-lg font-semibold">Size</div>
<div class="flex items-center mt-2">
<a-radio-group v-model="size" class="mr-4">
<a-radio value="small">Small</a-radio>
<a-radio value="medium">Medium</a-radio>
<a-radio value="large">Large</a-radio>
</a-radio-group>
<div class="text-sm text-gray-500">
<span v-if="size === 'small'">320g</span>
<span v-else-if="size === 'medium'">830g</span>
<span v-else>1200g</span>
</div>
</div>
</div>
<div class="mt-4">
<div class="text-lg font-semibold">Crust</div>
<div class="flex items-center mt-2">
<a-radio-group v-model="crust" class="mr-4">
<a-radio value="standard">Standard</a-radio>
<a-radio value="garlicRoasted">Garlic Roasted</a-radio>
<a-radio value="cheeseBurst">Cheese Burst</a-radio>
</a-radio-group>
</div>
</div>
<div class="mt-4">
<div class="text-lg font-semibold">Toppings</div>
<div class="flex items-center mt-2">
<a-checkbox-group v-model="toppings">
<a-checkbox value="standard">Standard</a-checkbox>
<a-checkbox value="extraCheese">Extra Cheese</a-checkbox>
<a-checkbox value="extraSpice">Extra Spice</a-checkbox>
</a-checkbox-group>
</div>
</div>
<!-- 总价 -->
<div class="mt-4">
<div class="flex items-center justify-between">
<div class="text-lg font-semibold">TOTAL</div>
<div class="text-lg font-semibold">$14.90</div>
</div>
</div>
<!-- 添加到购物车按钮 -->
<div class="mt-4">
<a-button type="primary" block>Add To Cart</a-button>
</div>
</div>
<!-- 选项卡 -->
<a-tabs class="mt-4">
<a-tab-pane tab="Home" key="1">
<template #tab-content>
<div class="p-4">
<a-list
:dataSource="listData"
renderItem="{ item }"
>
<a-list-item>
<a-skeleton avatar title={false} paragraph={{ rows: 1 }} />
</a-list-item>
</a-list>
</div>
</template>
</a-tab-pane>
<a-tab-pane tab="Menu" key="2">
<template #tab-content>
<div class="p-4">
<a-list
:dataSource="listData"
renderItem="{ item }"
>
<a-list-item>
<a-skeleton avatar title={false} paragraph={{ rows: 1 }} />
</a-list-item>
</a-list>
</div>
</template>
</a-tab-pane>
<a-tab-pane tab="Cart" key="3">
<template #tab-content>
<div class="p-4">
<a-list
:dataSource="listData"
renderItem="{ item }"
>
<a-list-item>
<a-skeleton avatar title={false} paragraph={{ rows: 1 }} />
</a-list-item>
</a-list>
</div>
</template>
</a-tab-pane>
<a-tab-pane tab="More" key="4">
<template #tab-content>
<div class="p-4">
<a-list
:dataSource="listData"
renderItem="{ item }"
>
<a-list-item>
<a-skeleton avatar title={false} paragraph={{ rows: 1 }} />
</a-list-item>
</a-list>
</div>
</template>
</a-tab-pane>
</a-tabs>
</div>
</template>
<script lang="tsx" setup>
import * as echarts from 'echarts';
import { h } from "vue";
import { createComponent } from 'echarts-for-vue';
import { Calendar } from 'v-calendar';
import { BMap } from 'vue3-baidu-map-gl';
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { onBeforeUnmount, ref, shallowRef } from 'vue';
const ECharts = createComponent({echarts, h});
const listData = Array.from({ length: 10 }).map((_, i) => ({
id: i,
title: `item ${i}`,
description: `description of item ${i}`,
}));
const size = ref('medium');
const crust = ref('standard');
const toppings = ref(['standard']);
const editorConfig = ref({
placeholder: '请输入内容...'
});
const editor = shallowRef();
const handleEditorCreated = (editorInstance) => {
// Attach the editor instance to the ref
editor.value = editorInstance;
console.log("editor.value", editor.value, editorInstance)
};
onBeforeUnmount(() => {
// Destroy the editor instance before the component is unmounted
editor.value.destroy();
editor.value = null;
});
</script>
.bg-gray-100 {
background-color: #f5f5f5;
}
.text-lg {
font-size: