| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- <template>
- <el-dialog v-model="visible" title="物流信息" width="650px" @close="handleClose">
- <div class="logistics-container">
- <div class="section-title">单号查询</div>
- <el-select v-model="selectedLogistics" placeholder="请选择物流单号" @change="handleLogisticNoChange" style="width: 100%">
- <el-option
- v-for="item in logisticsList"
- :key="item.id"
- :label="`${item.logisticNo || item.deliverCode},${getDictLabel(deliver_method, item.deliverMethod)}`"
- :value="item.logisticNo || item.deliverCode"
- />
- </el-select>
- <div class="section-title" style="margin-top: 20px">物流信息</div>
- <div class="timeline-container">
- <el-timeline>
- <el-timeline-item v-for="(item, index) in logisticsTrack" :key="index" :timestamp="item.time" placement="top" color="#409EFF">
- <div class="track-number">{{ item.trackingNo }}</div>
- <div class="track-content">{{ item.content }}</div>
- <div v-if="item.imagesUrl" class="timeline-images">
- <div class="image-label">签收图片:</div>
- <div class="image-list">
- <el-image
- v-for="(url, imgIndex) in item.imagesUrl.split(',')"
- :key="imgIndex"
- :src="url"
- :preview-src-list="item.imagesUrl.split(',')"
- :initial-index="imgIndex"
- fit="cover"
- class="sign-image"
- >
- <template #error>
- <div class="image-error">
- <el-icon><Picture /></el-icon>
- </div>
- </template>
- </el-image>
- </div>
- </div>
- </el-timeline-item>
- </el-timeline>
- </div>
- </div>
- </el-dialog>
- </template>
- <script setup lang="ts">
- import { ref, watch } from 'vue';
- const { proxy } = getCurrentInstance() as ComponentInternalInstance;
- const { deliver_method } = toRefs<any>(proxy?.useDict('deliver_method'));
- import { selectOrderDeliverByOrderId, queryTrack, listOrderStatusLog } from '@/api/pc/enterprise/order';
- import { Picture } from '@element-plus/icons-vue';
- interface TrackItem {
- time: string;
- trackingNo: string;
- content: string;
- imagesUrl: string;
- }
- const props = defineProps<{
- modelValue: boolean;
- orderId?: string | number;
- }>();
- const emit = defineEmits(['update:modelValue']);
- const visible = ref(false);
- const selectedLogistics = ref('');
- const logisticsList = ref<any[]>([]);
- const logisticsTrack = ref<TrackItem[]>([]);
- const getDictLabel = (dictOptions: any[], value: string) => {
- if (!dictOptions || !value) return value;
- const dict = dictOptions.find((item) => item.value === value);
- return dict ? dict.label : value;
- };
- watch(
- () => props.modelValue,
- (val) => {
- visible.value = val;
- if (val && props.orderId) {
- loadLogisticsData();
- }
- }
- );
- watch(visible, (val) => {
- emit('update:modelValue', val);
- });
- // watch(selectedLogistics, (val) => {
- // if (val) {
- // loadTrackData(val);
- // }
- // });
- const loadLogisticsData = async () => {
- if (!props.orderId) return;
- try {
- const res = await selectOrderDeliverByOrderId({ orderId: props.orderId });
- logisticsList.value = res.rows || [];
- if (logisticsList.value.length > 0) {
- selectedLogistics.value = logisticsList.value[0].logisticNo || logisticsList.value[0].deliverCode;
- handleLogisticNoChange(selectedLogistics.value);
- }
- } catch (error) {
- console.error('获取物流单号失败:', error);
- }
- };
- const handleLogisticNoChange = async (logisticNo: string) => {
- const selected = logisticsList.value.find((item) => item.logisticNo === logisticNo);
- try {
- if (selected) {
- const res = await queryTrack({ logisticNo: logisticNo, id: selected.id });
- // 1. 兼容处理:有些接口返回在 res.data,有些可能直接是 res
- const dataList = res.data || [];
- if (Array.isArray(dataList) && dataList.length > 0) {
- logisticsTrack.value = dataList.map((item: any) => {
- // 2. 核心修复:精准匹配时间字段
- // 顺丰用 'time',韵达用 'ftime'。
- // 优先取 ftime (韵达标准),如果没有则取 time (顺丰标准)
- const displayTime = item.ftime || item.time || item.acceptTime || '';
- return {
- time: displayTime,
- // 3. 建议:保留原始状态字段,方便后续筛选(如"已签收")
- content: item.context || item.content || '',
- // 4. 建议:如果有地址字段,也可以映射进来,没有则保持订单号
- trackingNo: item.location || (selected.orderCode ? `${selected.orderCode}` : ''),
- imagesUrl: ''
- };
- });
- }
- } else {
- await listOrderStatusLog({
- orderId: props.orderId,
- logisticNos: selectedLogistics.value,
- pageNum: 1,
- pageSize: 100
- }).then((res) => {
- if (res && res.code == 200) {
- logisticsTrack.value = res.rows.map((item: any) => {
- return {
- time: item.createTime,
- trackingNo: item.orderCode ? `${item.orderCode}` : '',
- content: item.statusName,
- imagesUrl: item.imagesUrl
- };
- });
- } else {
- logisticsTrack.value = [
- {
- time: (selected as any).createTime || '',
- trackingNo: selected.orderCode ? `${selected.orderCode}` : '',
- content: '已下单',
- imagesUrl: ''
- }
- ];
- }
- });
- }
- } catch (error) {
- console.error('查询物流轨迹失败:', error);
- logisticsTrack.value = [];
- }
- };
- // const loadTrackData = async (logisticsId: string | number) => {
- // const selectedItem = logisticsList.value.find((item) => item.id === logisticsId);
- // try {
- // if (selectedItem) {
- // const res = await queryTrack({ logisticNo: selectedItem.logisticNo });
- // // 1. 兼容处理:有些接口返回在 res.data,有些可能直接是 res
- // const dataList = res.data || [];
- // if (Array.isArray(dataList) && dataList.length > 0) {
- // logisticsTrack.value = dataList.map((item: any) => {
- // // 2. 核心修复:精准匹配时间字段
- // // 顺丰用 'time',韵达用 'ftime'。
- // // 优先取 ftime (韵达标准),如果没有则取 time (顺丰标准)
- // const displayTime = item.ftime || item.time || item.acceptTime || '';
- // return {
- // time: displayTime,
- // // 3. 建议:保留原始状态字段,方便后续筛选(如“已签收”)
- // content: item.context || item.content || '',
- // // 4. 建议:如果有地址字段,也可以映射进来,没有则保持订单号
- // trackingNo: selectedItem.orderCode ? `${selectedItem.orderCode}` : ''
- // };
- // });
- // }
- // } else {
- // await listOrderStatusLog({
- // orderId: props.orderId,
- // logisticNos: selectedLogistics.value,
- // pageNum: 1,
- // pageSize: 100
- // }).then((res) => {
- // if (res && res.code == 200) {
- // logisticsTrack.value = res.rows.map((item: any) => {
- // return {
- // time: item.createTime,
- // trackingNo: item.orderCode ? `${item.orderCode}` : '',
- // content: item.statusName
- // };
- // });
- // } else {
- // logisticsTrack.value = [
- // {
- // time: (selectedItem as any).createTime || '',
- // trackingNo: selectedItem.orderCode ? `${selectedItem.orderCode}` : '',
- // content: '已下单'
- // }
- // ];
- // }
- // });
- // }
- // } catch (error) {
- // console.error('查询物流轨迹失败:', error);
- // logisticsTrack.value = [];
- // }
- // };
- const handleClose = () => {
- visible.value = false;
- };
- </script>
- <style scoped lang="scss">
- .logistics-container {
- .section-title {
- font-size: 14px;
- font-weight: 500;
- color: #333;
- margin-bottom: 12px;
- }
- .timeline-container {
- max-height: 500px;
- overflow-y: auto;
- padding-right: 10px;
- :deep(.el-timeline) {
- padding-left: 0;
- }
- :deep(.el-timeline-item__timestamp) {
- font-size: 12px;
- color: #999;
- margin-bottom: 4px;
- }
- .track-number {
- font-size: 12px;
- color: #666;
- margin-bottom: 4px;
- }
- .track-content {
- font-size: 13px;
- color: #333;
- line-height: 1.6;
- }
- .timeline-images {
- margin-top: 8px;
- padding-top: 8px;
- border-top: 1px dashed #dcdfe6;
- .image-label {
- font-size: 13px;
- color: #909399;
- margin-bottom: 6px;
- }
- .image-list {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
- .sign-image {
- width: 60px;
- height: 60px;
- border-radius: 4px;
- border: 1px solid #dcdfe6;
- cursor: pointer;
- .image-error {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: #f5f7fa;
- color: #c0c4cc;
- }
- }
- }
- }
- }
- }
- </style>
|