|
|
@@ -0,0 +1,163 @@
|
|
|
+<template>
|
|
|
+ <ele-modal :width="800" v-model="visible" title="发货" @closed="handleClosed">
|
|
|
+ <div class="delivery-container" v-loading="loading">
|
|
|
+ <div class="section-title font-bold mb-3">填写包裹信息</div>
|
|
|
+ <div class="packages-list">
|
|
|
+ <div v-for="(pkg, index) in expressList" :key="index" class="package-item flex items-start gap-3 mb-4">
|
|
|
+ <el-input v-model="pkg.waybillCode" placeholder="请输入物流单号" class="w-64" clearable />
|
|
|
+ <dict-data code="shop_order_express_name" v-model="pkg.expressName" type="select" placeholder="请选择快递公司"
|
|
|
+ class="w-48" />
|
|
|
+ <el-button v-if="expressList.length > 1" type="danger" link @click="removePackage(index)"
|
|
|
+ class="mt-1">删除</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-button @click="addPackage" plain class="mb-4">
|
|
|
+ <el-icon class="mr-1">
|
|
|
+ <Plus />
|
|
|
+ </el-icon> 添加包裹
|
|
|
+ </el-button>
|
|
|
+ <div class="text-xs text-gray-400 mb-4">如需拆分为多个包裹发货,请先添加包裹</div>
|
|
|
+
|
|
|
+ <div class="order-info-card mb-4 border border-gray-200 rounded">
|
|
|
+ <div class="receiver-info bg-gray-50 p-3 text-sm text-gray-700 border-b border-gray-200">
|
|
|
+ {{ orderData.receiverName }}, {{ formatPhone(orderData.receiverMobile) }}, {{
|
|
|
+ orderData.receiverProvince }}{{ orderData.receiverCity }}{{ orderData.receiverCounty }}{{
|
|
|
+ orderData.receiverAddress }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="order-id-bar bg-blue-50 p-2 text-sm text-gray-700 border-b border-gray-200 flex justify-between items-center">
|
|
|
+ <div>
|
|
|
+ 订单号:{{ orderData.orderId }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="product-list p-3">
|
|
|
+ <div v-for="(product, idx) in orderData.detailList" :key="idx"
|
|
|
+ class="product-item flex items-center mb-3 last:mb-0">
|
|
|
+ <el-image :src="product.cover" class="w-12 h-12 rounded mr-3 flex-shrink-0" fit="cover" />
|
|
|
+ <div class="flex-1 min-w-0 mr-4">
|
|
|
+ <div class="text-sm font-medium truncate">{{ product.bookName }} {{ product.isbn }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="w-20 text-center text-sm text-gray-500">¥ {{ product.price }}</div>
|
|
|
+ <div class="w-16 text-center text-sm text-red-500">{{ product.num }}件</div>
|
|
|
+ <div class="w-24 text-center text-sm text-gray-500">待发货</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="visible = false">返回</el-button>
|
|
|
+ <el-button type="primary" @click="handleSubmit" :loading="submitLoading">发货</el-button>
|
|
|
+ </template>
|
|
|
+ </ele-modal>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+ import { ref, reactive } from 'vue';
|
|
|
+ import { Plus } from '@element-plus/icons-vue';
|
|
|
+ import { EleMessage } from 'ele-admin-plus/es';
|
|
|
+ import request from '@/utils/request';
|
|
|
+ import { formatPhone } from '@/utils/common';
|
|
|
+
|
|
|
+ const visible = ref(false);
|
|
|
+ const loading = ref(false);
|
|
|
+ const submitLoading = ref(false);
|
|
|
+ const orderData = ref({});
|
|
|
+ const expressList = ref([
|
|
|
+ { waybillCode: '', expressName: '' }
|
|
|
+ ]);
|
|
|
+
|
|
|
+ const emit = defineEmits(['success']);
|
|
|
+
|
|
|
+ const open = (order) => {
|
|
|
+ orderData.value = order;
|
|
|
+ expressList.value = [{ waybillCode: '', expressName: '' }];
|
|
|
+ visible.value = true;
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleClosed = () => {
|
|
|
+ orderData.value = {};
|
|
|
+ expressList.value = [{ waybillCode: '', expressName: '' }];
|
|
|
+ };
|
|
|
+
|
|
|
+ const addPackage = () => {
|
|
|
+ expressList.value.push({ waybillCode: '', expressName: '' });
|
|
|
+ };
|
|
|
+
|
|
|
+ const removePackage = (index) => {
|
|
|
+ expressList.value.splice(index, 1);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSubmit = () => {
|
|
|
+ // Validate
|
|
|
+ const validList = expressList.value.filter(item => item.waybillCode && item.expressName);
|
|
|
+ if (validList.length === 0) {
|
|
|
+ EleMessage.warning('请至少填写一个完整的包裹信息(物流单号和快递公司)');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let i = 0; i < expressList.length; i++) {
|
|
|
+ const item = expressList.value[i];
|
|
|
+ if ((item.waybillCode && !item.expressName) || (!item.waybillCode && item.expressName)) {
|
|
|
+ EleMessage.warning(`第 ${i + 1} 个包裹信息不完整`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ submitLoading.value = true;
|
|
|
+ request.post('/shop/shopOrder/sendPackage', {
|
|
|
+ orderId: orderData.value.orderId,
|
|
|
+ expressList: validList
|
|
|
+ }).then(res => {
|
|
|
+ if (res.data.code === 200) {
|
|
|
+ EleMessage.success('发货成功');
|
|
|
+ visible.value = false;
|
|
|
+ emit('success');
|
|
|
+ } else {
|
|
|
+ EleMessage.error(res.data.msg || '发货失败');
|
|
|
+ }
|
|
|
+ }).catch(e => {
|
|
|
+ console.error(e);
|
|
|
+ EleMessage.error('网络错误');
|
|
|
+ }).finally(() => {
|
|
|
+ submitLoading.value = false;
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ defineExpose({ open });
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+ .border-gray-200 {
|
|
|
+ border-color: #ebeef5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .bg-gray-50 {
|
|
|
+ background-color: #f9fafc;
|
|
|
+ }
|
|
|
+
|
|
|
+ .bg-blue-50 {
|
|
|
+ background-color: #ecf5ff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .text-gray-700 {
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+
|
|
|
+ .text-gray-500 {
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+
|
|
|
+ .text-gray-400 {
|
|
|
+ color: #c0c4cc;
|
|
|
+ }
|
|
|
+
|
|
|
+ .text-red-500 {
|
|
|
+ color: #f56c6c;
|
|
|
+ }
|
|
|
+</style>
|