<template>
|
<div class="container mx-auto px-4 py-8 max-w-6xl">
|
<h1 class="text-2xl font-bold mb-6">填写并核对订单信息</h1>
|
|
<!-- 收货人信息 -->
|
<div class="bg-white p-6 rounded-lg shadow-sm mb-4">
|
<div class="flex justify-between items-center mb-4">
|
<h2 class="text-lg font-medium">收货人信息</h2>
|
<el-button type="primary" link @click="showAddressDialog = true">新增收货地址</el-button>
|
</div>
|
|
<el-skeleton :loading="loading.addresses" :rows="3" animated>
|
<template #default>
|
<el-radio-group v-model="selectedAddress" class="w-full">
|
<el-radio
|
v-for="address in addresses"
|
:key="address.id"
|
:label="address.id"
|
class="!flex p-4 border rounded-lg mb-2 hover:bg-gray-50"
|
>
|
<div class="flex-1">
|
<div class="flex items-center gap-4">
|
<span class="font-medium">{{ address.name }} {{ address.city }}</span>
|
<span class="text-gray-600">{{ address.phone }}</span>
|
<el-tag size="small" type="success" v-if="address.isDefault">默认地址</el-tag>
|
</div>
|
<div class="text-gray-600 mt-1">{{ address.fullAddress }}</div>
|
</div>
|
</el-radio>
|
</el-radio-group>
|
</template>
|
</el-skeleton>
|
</div>
|
|
<!-- 支付方式 -->
|
<div class="bg-white p-6 rounded-lg shadow-sm mb-4">
|
<h2 class="text-lg font-medium mb-4">支付方式</h2>
|
<el-radio-group v-model="paymentMethod">
|
<el-radio label="online" class="mr-6">在线支付</el-radio>
|
<!-- <el-radio label="cod">货到付款</el-radio> -->
|
</el-radio-group>
|
</div>
|
|
<!-- 送货清单 -->
|
<div class="bg-white p-6 rounded-lg shadow-sm mb-4">
|
<div class="flex justify-between items-center mb-4">
|
<h2 class="text-lg font-medium">送货清单</h2>
|
<div class="flex items-center gap-4">
|
<el-tooltip content="价格说明">
|
<el-icon><InfoFilled /></el-icon>
|
</el-tooltip>
|
<!-- <el-link type="primary" @click="goToCart">返回修改购物车</el-link> -->
|
</div>
|
</div>
|
|
<div class="bg-blue-50 p-4 rounded-lg mb-4">
|
<div class="flex justify-between mb-4">
|
<div class="flex gap-4">
|
<span>配送方式:</span>
|
<el-radio-group v-model="deliveryMethod">
|
<el-radio label="jd">顺丰快递</el-radio>
|
<el-radio label="self">申通快递</el-radio>
|
<el-radio label="self">圆通快递</el-radio>
|
<el-radio label="self">邮政快递</el-radio>
|
</el-radio-group>
|
</div>
|
<!-- <el-link type="primary" @click="showDeliveryDialog = true">修改</el-link> -->
|
</div>
|
<div class="text-gray-600">配送时间:{{ deliveryTime }}</div>
|
</div>
|
|
<!-- 商品列表 -->
|
<el-skeleton :loading="loading.products" :rows="2" animated>
|
<template #default>
|
<div v-for="product in products" :key="product.id" class="border-t py-4">
|
<div class="text-gray-600 mb-4">商家:{{ product.shopName }}</div>
|
<div class="flex gap-4">
|
<el-image :src="product.image" style="width: 80px; height: 80px" fit="cover" :preview-src-list="[product.image]">
|
<template #error>
|
<div class="image-slot">
|
<el-icon><Picture /></el-icon>
|
</div>
|
</template>
|
</el-image>
|
<div class="flex-1">
|
<div class="flex justify-between">
|
<div>
|
<div class="font-medium">{{ product.name }}</div>
|
<div class="text-gray-500 mt-1">厂商:{{ product.specs }}</div>
|
</div>
|
<div class="text-right">
|
<div class="text-red-500">¥{{ product.price.toFixed(2) }}</div>
|
<div class="text-gray-600">x{{ product.quantity }}</div>
|
<div>{{ product.stock > 0 ? '有货' : '无货' }}</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
</el-skeleton>
|
</div>
|
|
<!-- 发票信息 -->
|
<div class="bg-white p-6 rounded-lg shadow-sm mb-4">
|
<div class="flex justify-between items-center">
|
<h2 class="text-lg font-medium">发票信息</h2>
|
<el-tooltip content="开企业抬头发票需要填写纳税人识别号,以免影响报销">
|
<el-icon><InfoFilled /></el-icon>
|
</el-tooltip>
|
</div>
|
<div class="mt-4">
|
<el-form
|
v-if="invoice.type === 'company'"
|
ref="invoiceForm"
|
:model="invoice"
|
|
label-width="120px"
|
class="mt-4"
|
>
|
<el-form-item label="单位名称" prop="companyName">
|
<el-input v-model="invoice.companyName" placeholder="请输入单位名称"></el-input>
|
</el-form-item>
|
|
<el-form-item label="纳税人识别号" prop="taxNumber">
|
<el-input v-model="invoice.taxNumber" placeholder="请输入纳税人识别号"></el-input>
|
</el-form-item>
|
|
<div class="text-gray-500 text-sm mt-2">
|
<el-icon class="mr-1"><InfoFilled /></el-icon>
|
发票将在订单完成后自动开具并发送至订单中的邮箱
|
</div>
|
</el-form>
|
</div>
|
</div>
|
|
<!-- 优惠/礼品卡 -->
|
<div class="bg-white p-6 rounded-lg shadow-sm mb-4">
|
<el-collapse v-model="activeCollapse">
|
<el-collapse-item title="使用优惠/礼品卡/抵用" name="coupons">
|
<el-skeleton :loading="loading.coupons" :rows="2" animated>
|
<template #default>
|
<div class="p-4" v-if="coupons.length">
|
<div v-for="coupon in coupons" :key="coupon.id" class="mb-2">
|
<el-checkbox v-model="coupon.selected"> {{ coupon.name }} - 优惠{{ coupon.amount }}元 </el-checkbox>
|
</div>
|
</div>
|
<div class="p-4" v-else>暂无可用优惠</div>
|
</template>
|
</el-skeleton>
|
</el-collapse-item>
|
</el-collapse>
|
</div>
|
|
<!-- 订单金额 -->
|
<div class="bg-white p-6 rounded-lg shadow-sm">
|
<div class="flex justify-end text-right">
|
<div>
|
<div class="flex justify-between gap-8 mb-2">
|
<span>商品总额:</span>
|
<span>¥{{ orderAmount.subtotal.toFixed(2) }}</span>
|
</div>
|
<div class="flex justify-between gap-8 mb-2">
|
<span>运费:</span>
|
<span>¥{{ orderAmount.shipping.toFixed(2) }}</span>
|
</div>
|
<div class="flex justify-between gap-8 mb-2" v-if="orderAmount.discount > 0">
|
<span>优惠金额:</span>
|
<span class="text-red-500">-¥{{ orderAmount.discount.toFixed(2) }}</span>
|
</div>
|
<div class="flex justify-between gap-8 text-lg font-medium text-red-500">
|
<span>应付总额:</span>
|
<span>¥{{ orderAmount.total.toFixed(2) }}</span>
|
</div>
|
<div class="text-gray-500 text-sm mt-2">寄送至:{{ selectedAddressText }}</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 提交订单按钮 -->
|
<div class="flex justify-end mt-6">
|
<el-button type="success" size="large" :loading="loading.submit" @click="submitOrder"> 提交订单 </el-button>
|
</div>
|
</div>
|
|
<!-- 新增地址对话框 -->
|
<el-dialog v-model="showAddressDialog" title="新增收货地址" width="500px">
|
<el-form :model="newAddress" :rules="addressRules" ref="addressForm">
|
<el-form-item label="收货人" prop="name">
|
<el-input v-model="newAddress.name" />
|
</el-form-item>
|
<el-form-item label="手机号码" prop="phone">
|
<el-input v-model="newAddress.phone" />
|
</el-form-item>
|
<el-form-item label="所在地区" prop="region">
|
<el-cascader v-model="newAddress.region" :options="regionOptions" placeholder="请选择所在地区" />
|
</el-form-item>
|
<el-form-item label="详细地址" prop="address">
|
<el-input v-model="newAddress.address" type="textarea" :rows="2" />
|
</el-form-item>
|
<el-form-item>
|
<el-checkbox v-model="newAddress.isDefault">设为默认地址</el-checkbox>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button @click="showAddressDialog = false">取消</el-button>
|
<el-button type="primary" @click="saveAddress" :loading="loading.saveAddress"> 保存 </el-button>
|
</span>
|
</template>
|
</el-dialog>
|
|
<!-- 发票信息对话框 -->
|
<el-dialog v-model="showInvoiceDialog" title="发票信息" width="500px">
|
<el-form :model="invoice" :rules="invoiceRules" ref="invoiceForm">
|
<el-form-item label="发票类型" prop="type">
|
<el-radio-group v-model="invoice.type">
|
<el-radio label="personal">个人</el-radio>
|
<el-radio label="company">单位</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
<template v-if="invoice.type === 'company'">
|
<el-form-item label="单位名称" prop="companyName">
|
<el-input v-model="invoice.companyName" />
|
</el-form-item>
|
<el-form-item label="税号" prop="taxNumber">
|
<el-input v-model="invoice.taxNumber" />
|
</el-form-item>
|
</template>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button @click="showInvoiceDialog = false">取消</el-button>
|
<el-button type="primary" @click="saveInvoice" :loading="loading.saveInvoice"> 确定 </el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</template>
|
|
<script setup lang="ts">
|
import { ref, computed, onMounted } from 'vue';
|
import { useRouter } from 'vue-router';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { InfoFilled, Picture } from '@element-plus/icons-vue';
|
import { SERVE_URL } from '@/constants';
|
import type { FormInstance } from 'element-plus';
|
|
const router = useRouter();
|
|
// 加载状态
|
const loading = ref({
|
addresses: false,
|
products: false,
|
coupons: false,
|
submit: false,
|
saveAddress: false,
|
saveInvoice: false,
|
});
|
|
// 地址相关
|
const addresses = ref([
|
{
|
id: 1,
|
name: '义维流体科技有限公司',
|
city: '上海',
|
phone: '189****7818',
|
fullAddress: '上海 闵行区 江月路 999号',
|
isDefault: true,
|
},
|
]);
|
|
const selectedAddress = ref(1);
|
const showAddressDialog = ref(false);
|
const showDeliveryDialog = ref(false);
|
const addressForm = ref<FormInstance>();
|
const newAddress = ref({
|
name: '',
|
phone: '',
|
region: [],
|
address: '',
|
isDefault: false,
|
});
|
|
// 地区选项数据
|
const regionOptions = ref([
|
{
|
value: 'shanghai',
|
label: '上海',
|
children: [
|
{
|
value: 'minhang',
|
label: '闵行区',
|
children: [
|
{
|
value: 'pujiang',
|
label: '江月路',
|
},
|
],
|
},
|
],
|
},
|
]);
|
|
const addressRules = {
|
name: [{ required: true, message: '请输入收货人姓名', trigger: 'blur' }],
|
phone: [
|
{ required: true, message: '请输入手机号码', trigger: 'blur' },
|
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' },
|
],
|
region: [{ required: true, message: '请选择所在地区', trigger: 'change' }],
|
address: [{ required: true, message: '请输入详细地址', trigger: 'blur' }],
|
};
|
|
// 支付和配送方式
|
const paymentMethod = ref('online');
|
const deliveryMethod = ref('jd');
|
const deliveryTime = ref('预计三天后送达');
|
|
// 商品相关
|
const products = ref([]);
|
|
// 发票相关
|
const showInvoiceDialog = ref(false);
|
const invoiceForm = ref<FormInstance>();
|
const invoice = ref({
|
type: 'company',
|
companyName: '',
|
taxNumber: '',
|
});
|
const invoiceRules = {
|
companyName: [{ required: true, message: '请输入单位名称', trigger: 'blur' }],
|
taxNumber: [{ required: true, message: '请输入税号', trigger: 'blur' }],
|
};
|
|
// 优惠券相关
|
const activeCollapse = ref(['']);
|
const coupons = ref([
|
{
|
id: 1,
|
name: '新人专享券',
|
amount: 5,
|
selected: false,
|
},
|
{
|
id: 2,
|
name: '满30减3元券',
|
amount: 3,
|
selected: false,
|
},
|
]);
|
|
// 订单金额计算
|
const orderAmount = computed(() => {
|
const subtotal = products.value.reduce((sum, product) => {
|
return sum + product.price * product.quantity;
|
}, 0);
|
|
const discount = coupons.value.filter((coupon) => coupon.selected).reduce((sum, coupon) => sum + coupon.amount, 0);
|
|
return {
|
subtotal,
|
shipping: 0,
|
discount,
|
total: subtotal - discount,
|
};
|
});
|
|
onMounted(() => {
|
// 从localStorage获取产品信息
|
const savedProduct = localStorage.getItem('currentProduct');
|
if (savedProduct) {
|
const productData = JSON.parse(savedProduct);
|
|
// 合并默认值和保存的产品数据
|
let productItem = {
|
id: productData.Id,
|
name: productData.ModelType,
|
applicationCode: productData.RecordNumber,
|
price: productData.Price,
|
image: `${SERVE_URL}${productData.PhysicalPicturePath}`,
|
quantity: 1,
|
stock: 999,
|
shopName: productData.Model,
|
specs: productData.CompanyName,
|
certificatePath: `${SERVE_URL}${productData.CertificatePath}`,
|
brand: productData.CompanyName,
|
model: productData.Model,
|
power: '详询厂家',
|
voltage: '详询厂家',
|
speed: '详询厂家',
|
protection: '详询厂家',
|
detailImages: [`${SERVE_URL}${productData.PhysicalPicturePath}`],
|
specifications: {
|
产品型号: productData.Model,
|
生产企业: productData.CompanyName,
|
备案编号: productData.RecordNumber,
|
备案时间: productData.RecordTime,
|
能效等级: `${productData.EnergyEfficiencyClass}级`,
|
},
|
};
|
console.log(productItem);
|
products.value.push(productItem);
|
}
|
});
|
|
// 选中地址文本
|
const selectedAddressText = computed(() => {
|
const address = addresses.value.find((addr) => addr.id === selectedAddress.value);
|
if (!address) return '';
|
return `${address.fullAddress} 收货人:${address.name} ${address.phone}`;
|
});
|
|
// 保存地址
|
const saveAddress = async () => {
|
if (!addressForm.value) return;
|
|
await addressForm.value.validate(async (valid) => {
|
if (valid) {
|
loading.value.saveAddress = true;
|
try {
|
// 模拟保存地址
|
const newAddr = {
|
id: addresses.value.length + 1,
|
name: newAddress.value.name,
|
city: newAddress.value.region[0],
|
phone: newAddress.value.phone,
|
fullAddress: `${newAddress.value.region.join(' ')} ${newAddress.value.address}`,
|
isDefault: newAddress.value.isDefault,
|
};
|
|
addresses.value.push(newAddr);
|
showAddressDialog.value = false;
|
ElMessage.success('地址保存成功');
|
|
// 如果设为默认地址,更新其他地址的默认状态
|
if (newAddr.isDefault) {
|
addresses.value.forEach((addr) => {
|
if (addr.id !== newAddr.id) {
|
addr.isDefault = false;
|
}
|
});
|
}
|
} catch (error) {
|
ElMessage.error('保存地址失败');
|
} finally {
|
loading.value.saveAddress = false;
|
}
|
}
|
});
|
};
|
|
// 保存发票信息
|
const saveInvoice = async () => {
|
if (invoice.value.type === 'none' || !invoiceForm.value) {
|
showInvoiceDialog.value = false;
|
return;
|
}
|
|
await invoiceForm.value.validate(async (valid) => {
|
if (valid) {
|
loading.value.saveInvoice = true;
|
try {
|
// 模拟保存发票信息
|
showInvoiceDialog.value = false;
|
ElMessage.success('发票信息保存成功');
|
} finally {
|
loading.value.saveInvoice = false;
|
}
|
}
|
});
|
};
|
|
// 提交订单
|
const submitOrder = async () => {
|
// 表单验证
|
if (!selectedAddress.value) {
|
ElMessage.warning('请选择收货地址');
|
return;
|
}
|
|
try {
|
loading.value.submit = true;
|
|
// 确认提交
|
await ElMessageBox.confirm(`确认提交订单?应付金额:¥${orderAmount.value.total.toFixed(2)}`, '提交订单', {
|
confirmButtonText: '确认',
|
cancelButtonText: '取消',
|
type: 'warning',
|
});
|
|
// 模拟订单提交
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
const orderId = Math.floor(Math.random() * 1000000);
|
ElMessage.success('订单提交成功');
|
|
// 根据支付方式跳转
|
if (paymentMethod.value === 'online') {
|
router.push(`/payment?orderId=${orderId}`);
|
} else {
|
router.push(`/order/success?orderId=${orderId}`);
|
}
|
} catch (error) {
|
if (error === 'cancel') return;
|
ElMessage.error('提交订单失败');
|
} finally {
|
loading.value.submit = false;
|
}
|
};
|
|
// 返回购物车
|
const goToCart = () => {
|
router.push('/cart');
|
};
|
</script>
|
|
<style scoped>
|
:deep(.el-radio__input.is-checked + .el-radio__label) {
|
color: inherit;
|
}
|
|
.image-slot {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
width: 100%;
|
height: 100%;
|
background: #f5f7fa;
|
color: #909399;
|
}
|
</style>
|