| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- <template>
- <!-- 订单状态日志抽屉 -->
- <el-drawer v-model="drawerVisible" title="变更物流状态" size="38%" :destroy-on-close="true" :close-on-click-modal="true">
- <div class="status-log-container">
- <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
- <el-form-item label="物流单号" prop="logisticNos">
- <el-input v-model="form.logisticNos" disabled />
- </el-form-item>
- <el-form-item label="包裹单号" prop="packageNo">
- <el-input v-model="form.packageNo" disabled />
- </el-form-item>
- <el-form-item label="所在状态" prop="statusName">
- <el-select v-model="form.statusName" placeholder="请选择状态" style="width: 100%" @change="handleStatusChange">
- <el-option
- v-for="item in statusOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- :disabled="isStatusDisabled(item.value)"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="发货人" prop="shipper">
- <el-input v-model="form.shipper" disabled />
- </el-form-item>
- <el-form-item label="操作时间" prop="operateTime">
- <el-date-picker v-model="form.operateTime" type="date" placeholder="请选择操作时间" style="width: 100%" />
- </el-form-item>
- <el-form-item label="快递员手机号" prop="courierPhone">
- <el-input v-model="form.courierPhone" disabled />
- </el-form-item>
- <el-form-item label="上传图片" prop="images" v-if="form.statusName === '已签收'">
- <div class="image-selector-wrapper">
- <!-- 修改点 1: 使用 !selectedImages.length 替代 length === 0,并确保样式一致 -->
- <div
- v-if="!selectedImages || selectedImages.length === 0"
- class="upload-box"
- @click="showFileSelector = true"
- style="
- width: 150px;
- height: 150px;
- border: 2px dashed #d9d9d9;
- border-radius: 4px;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- transition: all 0.3s;
- "
- >
- <div style="text-align: center; color: #8c939d">
- <el-icon :size="40" style="margin-bottom: 8px">
- <Plus />
- </el-icon>
- <div style="font-size: 14px">点击上传</div>
- </div>
- </div>
- <!-- 修改点 2: 列表渲染区域 -->
- <div v-else class="selected-images-list">
- <div
- v-for="(img, index) in selectedImages"
- :key="img.url || index"
- style="position: relative; display: inline-block; margin: 0 8px 8px 0"
- >
- <!-- 确保 img.url 存在才渲染,防止报错 -->
- <el-image
- v-if="img.url"
- :src="img.url"
- style="width: 150px; height: 150px"
- fit="cover"
- :preview-src-list="selectedImages.filter((i) => i.url).map((i) => i.url)"
- />
- <el-button
- type="danger"
- :icon="Delete"
- circle
- size="small"
- style="position: absolute; top: 5px; right: 5px; z-index: 10"
- @click="removeImage(index)"
- />
- </div>
- <!-- 修改点 3: 如果未满 3 张,显示“继续添加”按钮 -->
- <div
- v-if="selectedImages.length < 3"
- class="upload-box-more"
- @click="showFileSelector = true"
- style="
- width: 150px;
- height: 150px;
- border: 2px dashed #d9d9d9;
- border-radius: 4px;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- transition: all 0.3s;
- vertical-align: top;
- background-color: #f5f7fa; /* 加个背景色区分 */
- "
- >
- <el-icon :size="30" color="#8c939d">
- <Plus />
- </el-icon>
- </div>
- </div>
- </div>
- </el-form-item>
- <!-- 文件选择器 -->
- <FileSelector v-model="showFileSelector" :multiple="true" :allowed-types="[1]" title="选择图片" @confirm="handleImagesSelected" />
- </el-form>
- </div>
- <template #footer>
- <div class="drawer-footer">
- <el-button @click="closeDrawer">取消</el-button>
- <el-button type="primary" @click="handleSubmit" :loading="submitLoading">保存</el-button>
- </div>
- </template>
- </el-drawer>
- </template>
- <script setup name="AddOrderStatusLogDrawer" lang="ts">
- import { ref, reactive } from 'vue';
- import { ElMessage } from 'element-plus';
- import { Plus, Delete } from '@element-plus/icons-vue';
- import { addOrderStatusLog } from '@/api/order/orderStatusLog';
- import FileSelector from '@/components/FileSelector/index.vue';
- const drawerVisible = ref(false);
- const submitLoading = ref(false);
- const formRef = ref<any>(null);
- const showFileSelector = ref(false);
- const selectedImages = ref<any[]>([]);
- // 表单数据
- const form = reactive({
- orderNo: '',
- orderId: undefined as string | number | undefined,
- customerNo: '',
- customerId: undefined as string | number | undefined,
- deliverMethod: '0',
- statusName: '',
- logisticNos: '',
- packageNo: '',
- shipper: '',
- operateTime: '',
- courierPhone: '',
- images: '',
- status: '0'
- });
- // 状态顺序定义
- const statusOrder = ['已下单', '已揽件', '运输中', '派件中', '已签收'];
- // 当前订单状态
- const currentStatus = ref('');
- // 状态选项
- const statusOptions = [
- { label: '已下单', value: '已下单' },
- { label: '已揽件', value: '已揽件' },
- { label: '运输中', value: '运输中' },
- { label: '派件中', value: '派件中' },
- { label: '已签收', value: '已签收' }
- ];
- const rules = {
- statusName: [{ required: true, message: '请选择状态名称', trigger: 'change' }]
- };
- // 打开抽屉
- const openDrawer = (orderData?: any, currentOrderStatus?: string) => {
- if (orderData) {
- form.orderNo = orderData.orderNo || '';
- form.orderId = orderData.orderId || '';
- form.shipper = orderData.deliverMan || '';
- form.courierPhone = orderData.phone || '';
- form.packageNo = orderData.deliverCode || '';
- form.logisticNos = orderData.deliverCode || '';
- form.customerNo = orderData.customerNo || '';
- form.customerId = orderData.customerId;
- form.operateTime = orderData.createTime || '';
- form.deliverMethod = orderData.deliverMethod || '0';
- form.statusName = currentOrderStatus || '';
- form.images = orderData.images || '';
- selectedImages.value = [];
- if (form.images) {
- const urls = form.images.split(',');
- selectedImages.value = urls.filter((u) => u && u.trim()).map((u) => ({ url: u.trim(), name: 'Image' }));
- }
- currentStatus.value = currentOrderStatus || '';
- }
- drawerVisible.value = true;
- };
- // 关闭抽屉
- const closeDrawer = () => {
- drawerVisible.value = false;
- resetForm();
- };
- // 判断是否禁用某个状态选项
- const isStatusDisabled = (statusValue: string) => {
- if (!currentStatus.value) return false;
- const currentIndex = statusOrder.indexOf(currentStatus.value);
- const targetIndex = statusOrder.indexOf(statusValue);
- // 如果目标状态在当前状态之前(索引更小),则禁用
- return targetIndex < currentIndex;
- };
- // 重置表单
- const resetForm = () => {
- form.statusName = '';
- form.logisticNos = '';
- form.packageNo = '';
- form.orderId = undefined;
- form.shipper = '';
- form.operateTime = '';
- form.courierPhone = '';
- form.images = '';
- selectedImages.value = [];
- showFileSelector.value = false;
- currentStatus.value = '';
- };
- // 处理选择的图片 (优化健壮性)
- const handleImagesSelected = (files: any[]) => {
- if (!files || files.length === 0) {
- showFileSelector.value = false;
- return;
- }
- const remainingSlots = 3 - selectedImages.value.length;
- if (remainingSlots <= 0) {
- ElMessage.warning('最多上传 3 张图片');
- showFileSelector.value = false;
- return;
- }
- const filesToAdd = files.slice(0, remainingSlots);
- // 映射为标准格式 { url, name }
- const newItems = filesToAdd
- .map((f) => ({
- url: f.fileUrl || f.url || f.path, // 兼容多种返回字段
- name: f.fileName || 'Image'
- }))
- .filter((item) => item.url); // 过滤掉没有 url 的无效项
- if (newItems.length > 0) {
- // 重新赋值数组以触发视图更新
- selectedImages.value = [...selectedImages.value, ...newItems];
- form.images = selectedImages.value.map((img) => img.url).join(',');
- }
- showFileSelector.value = false;
- };
- // 移除已选择的图片
- const removeImage = (index: number) => {
- selectedImages.value.splice(index, 1);
- form.images = selectedImages.value.map((img) => img.url).join(',');
- };
- // 状态变化处理
- const handleStatusChange = () => {
- // 当状态变化时,如果不是已签收,清空图片
- if (form.statusName !== '已签收') {
- form.images = '';
- selectedImages.value = [];
- }
- };
- const handleSubmit = async () => {
- await formRef.value?.validate();
- submitLoading.value = true;
- try {
- await addOrderStatusLog(form);
- ElMessage.success('保存成功');
- closeDrawer();
- } catch (error) {
- console.error('保存失败:', error);
- ElMessage.error('保存失败');
- } finally {
- submitLoading.value = false;
- }
- };
- // 暴露方法给父组件
- defineExpose({
- openDrawer
- });
- </script>
- <style scoped>
- .status-log-container {
- padding: 20px;
- }
- .drawer-footer {
- display: flex;
- justify-content: flex-end;
- gap: 12px;
- }
- </style>
|