addOrderStatusLogDrawer.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <template>
  2. <!-- 订单状态日志抽屉 -->
  3. <el-drawer v-model="drawerVisible" title="变更物流状态" size="38%" :destroy-on-close="true" :close-on-click-modal="true">
  4. <div class="status-log-container">
  5. <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
  6. <el-form-item label="物流单号" prop="logisticNos">
  7. <el-input v-model="form.logisticNos" disabled />
  8. </el-form-item>
  9. <el-form-item label="包裹单号" prop="packageNo">
  10. <el-input v-model="form.packageNo" disabled />
  11. </el-form-item>
  12. <el-form-item label="所在状态" prop="statusName">
  13. <el-select v-model="form.statusName" placeholder="请选择状态" style="width: 100%" @change="handleStatusChange">
  14. <el-option
  15. v-for="item in statusOptions"
  16. :key="item.value"
  17. :label="item.label"
  18. :value="item.value"
  19. :disabled="isStatusDisabled(item.value)"
  20. />
  21. </el-select>
  22. </el-form-item>
  23. <el-form-item label="送货人" prop="shipper">
  24. <el-input v-model="form.shipper" disabled />
  25. </el-form-item>
  26. <el-form-item label="操作时间" prop="operateTime">
  27. <el-date-picker v-model="form.operateTime" type="date" placeholder="请选择操作时间" style="width: 100%" />
  28. </el-form-item>
  29. <el-form-item label="快递员手机号" prop="courierPhone">
  30. <el-input v-model="form.courierPhone" disabled />
  31. </el-form-item>
  32. <el-form-item label="上传图片" prop="images" v-if="form.statusName === '已签收'">
  33. <ImageUpload v-model="form.images" :limit="3" />
  34. </el-form-item>
  35. </el-form>
  36. </div>
  37. <template #footer>
  38. <div class="drawer-footer">
  39. <el-button @click="closeDrawer">取消</el-button>
  40. <el-button type="primary" @click="handleSubmit" :loading="submitLoading">保存</el-button>
  41. </div>
  42. </template>
  43. </el-drawer>
  44. </template>
  45. <script setup name="AddOrderStatusLogDrawer" lang="ts">
  46. import { ref, reactive } from 'vue';
  47. import { ElMessage } from 'element-plus';
  48. import { addOrderStatusLog } from '@/api/order/orderStatusLog';
  49. import ImageUpload from '@/components/ImageUpload/index.vue';
  50. const drawerVisible = ref(false);
  51. const submitLoading = ref(false);
  52. const formRef = ref<any>(null);
  53. // 表单数据
  54. const form = reactive({
  55. orderNo: '',
  56. orderId: undefined as string | number | undefined,
  57. customerNo: '',
  58. customerId: undefined as string | number | undefined,
  59. deliverMethod: '0',
  60. statusName: '',
  61. logisticNos: '',
  62. packageNo: '',
  63. shipper: '',
  64. operateTime: '',
  65. courierPhone: '',
  66. images: '',
  67. status: '0'
  68. });
  69. // 状态顺序定义
  70. const statusOrder = ['已下单', '已揽件', '运输中', '派件中', '已签收'];
  71. // 当前订单状态
  72. const currentStatus = ref('');
  73. // 状态选项
  74. const statusOptions = [
  75. { label: '已下单', value: '已下单' },
  76. { label: '已揽件', value: '已揽件' },
  77. { label: '运输中', value: '运输中' },
  78. { label: '派件中', value: '派件中' },
  79. { label: '已签收', value: '已签收' }
  80. ];
  81. const rules = {
  82. statusName: [{ required: true, message: '请选择状态名称', trigger: 'change' }],
  83. images: [
  84. {
  85. validator: (_rule: any, _value: any, callback: any) => {
  86. if (form.statusName === '已签收' && !form.images) {
  87. ElMessage.warning('已签收状态必须上传签收图片');
  88. callback(new Error('已签收状态必须上传签收图片'));
  89. } else {
  90. callback();
  91. }
  92. },
  93. trigger: 'change'
  94. }
  95. ]
  96. };
  97. // 打开抽屉
  98. const openDrawer = (orderData?: any, currentOrderStatus?: string) => {
  99. if (orderData) {
  100. form.orderNo = orderData.orderNo || '';
  101. form.orderId = orderData.orderId || '';
  102. form.shipper = orderData.deliverMan || '';
  103. form.courierPhone = orderData.phone || '';
  104. form.packageNo = orderData.deliverCode || '';
  105. form.logisticNos = orderData.deliverCode || '';
  106. form.customerNo = orderData.customerNo || '';
  107. form.customerId = orderData.customerId;
  108. form.operateTime = orderData.createTime || '';
  109. form.deliverMethod = orderData.deliverMethod || '0';
  110. form.statusName = currentOrderStatus || '';
  111. form.images = orderData.images || '';
  112. currentStatus.value = currentOrderStatus || '';
  113. }
  114. drawerVisible.value = true;
  115. };
  116. // 关闭抽屉
  117. const closeDrawer = () => {
  118. drawerVisible.value = false;
  119. resetForm();
  120. };
  121. // 判断是否禁用某个状态选项
  122. const isStatusDisabled = (statusValue: string) => {
  123. if (!currentStatus.value) return false;
  124. const currentIndex = statusOrder.indexOf(currentStatus.value);
  125. const targetIndex = statusOrder.indexOf(statusValue);
  126. // 如果目标状态在当前状态之前(索引更小),则禁用
  127. return targetIndex < currentIndex;
  128. };
  129. // 重置表单
  130. const resetForm = () => {
  131. form.statusName = '';
  132. form.logisticNos = '';
  133. form.packageNo = '';
  134. form.orderId = undefined;
  135. form.shipper = '';
  136. form.operateTime = '';
  137. form.courierPhone = '';
  138. form.images = '';
  139. currentStatus.value = '';
  140. };
  141. // 状态变化处理
  142. const handleStatusChange = () => {
  143. // 当状态变化时,如果不是已签收,清空图片
  144. if (form.statusName !== '已签收') {
  145. form.images = '';
  146. }
  147. };
  148. const handleSubmit = async () => {
  149. await formRef.value?.validate();
  150. submitLoading.value = true;
  151. try {
  152. await addOrderStatusLog(form);
  153. ElMessage.success('保存成功');
  154. closeDrawer();
  155. } catch (error) {
  156. console.error('保存失败:', error);
  157. ElMessage.error('保存失败');
  158. } finally {
  159. submitLoading.value = false;
  160. }
  161. };
  162. // 暴露方法给父组件
  163. defineExpose({
  164. openDrawer
  165. });
  166. </script>
  167. <style scoped>
  168. .status-log-container {
  169. padding: 20px;
  170. }
  171. .drawer-footer {
  172. display: flex;
  173. justify-content: flex-end;
  174. gap: 12px;
  175. }
  176. </style>