sen
2025-08-18 d8c563d7ce8e4541d614d5d6a889aa7b0c136adc
ui/admin-ui3/src/views/cwgl/dispatchOrder/index.vue
@@ -1,37 +1,51 @@
<template>
  <basicContainer>
    <avue-crud
        :option="option"
        :table-loading="pageF.loading"
        :data="tableData"
        :page="page"
        :permission="permissionList"
        :before-open="beforeOpen"
        v-model="form"
        ref="crudRef"
        @row-update="rowUpdate"
        @row-save="rowSave"
        @refresh-change="refreshChange"
        @row-del="rowDel"
        @search-change="searchChange"
        @search-reset="searchReset"
        @selection-change="selectionChange"
        @current-change="currentChange"
        @size-change="sizeChange"
        @on-load="onLoad"
    >
    <avue-crud :option="option" :table-loading="pageF.loading" :data="tableData" :page="page"
      :permission="permissionList" :before-open="beforeOpen" v-model="form" ref="crudRef" @row-update="rowUpdate"
      @row-save="rowSave" @refresh-change="refreshChange" @row-del="rowDel" @search-change="searchChange"
      @search-reset="searchReset" @selection-change="selectionChange" @current-change="currentChange"   v-model:search="queryParams"
      @size-change="sizeChange" @on-load="onLoad">
      <template #menu-left>
        <el-button
            type="warning"
            plain
            icon="Download"
            @click="handleExport"
            v-hasPermi="['cwgl:dispatchOrder:export']"
        >导出
        <el-button type="warning" plain icon="Download" @click="handleExport"
          v-hasPermi="['cwgl:dispatchOrder:export']">导出
        </el-button>
        <el-button type="success" plain icon="Download" @click="handleExport2"
          v-hasPermi="['cwgl:dispatchOrder:export']">生成台账报表
        </el-button>
      </template>
      <template #menu="{ size, row, index }">
        <el-link class="link-btn" type="primary" :underline="false" plain :size="size" icon="View"
          @click="handleFy(row)" v-hasPermi="['cwgl:dispatchOrder:query']"> 查看费用
        </el-link>
        <el-link class="link-btn" type="primary" :underline="false" plain icon="View" @click="handleFj(row)"
          v-hasPermi="['cwgl:dispatchOrder:query']"> 查看附件
        </el-link>
      </template>
    </avue-crud>
    <el-dialog title="查看费用" v-model="open1" class="avue-dialog avue-dialog--top" width="60%">
      <avue-crud :option="itemTableOption1" :data="itemTableData1" :table-loading="itemTableLoading1">
      </avue-crud>
    </el-dialog>
    <el-dialog title="查看附件" v-model="open2" class="avue-dialog avue-dialog--top" width="60%">
      <avue-crud :option="itemTableOption2" :data="itemTableData2" :page="pageAttachment"
        :table-loading="itemTableLoading2" @current-change="handleAttachmentCurrentChange"
        @size-change="handleAttachmentSizeChange">
        <template #imageUrl="{ row }">
          <el-image :src="row.imageUrl" style="width: 100px; height: 100px" fit="cover"
            :preview-src-list="[row.imageUrl]" :preview-teleported="true" hide-on-click-modal
            class="attachment-image" />
        </template>
      </avue-crud>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" v-if="itemTableData2.length>0" @click="downPZ">下载附件</el-button>
        </div>
      </template>
    </el-dialog>
  </basicContainer>
</template>
@@ -43,16 +57,17 @@
  exportDispatchOrder,
  getDispatchOrder,
  listDispatchOrder,
  updateDispatchOrder
  updateDispatchOrder, cwglDispatchOrderItem, cwglDispatchOrderattAchment, exportDispatchOrder2, downloadFJ
} from "@/api/cwgl/dispatchOrder";
import useCurrentInstance from "@/utils/useCurrentInstance";
import {computed, reactive, ref, toRefs} from "vue";
import {PagesInterface, PageQueryInterface} from "@/utils/globalInterface";
import {usePagePlus} from "@/hooks/usePagePlus";
import {hasPermission} from "@/utils/permissionUtils";
import {useTableColumnWidth} from "@/hooks/useAvueTableWidths";
import { computed, reactive, ref, toRefs } from "vue";
import { PagesInterface, PageQueryInterface } from "@/utils/globalInterface";
import { usePagePlus } from "@/hooks/usePagePlus";
import { hasPermission } from "@/utils/permissionUtils";
import {blobValidate} from "@/utils/ruoyi";
import {saveAs} from "file-saver";
const {proxy} = useCurrentInstance();
const { proxy } = useCurrentInstance();
const crudRef = ref();
const permissionList = computed(() => {
@@ -72,20 +87,36 @@
    total: 0,
    currentPage: 1,
  },
  pageAttachment: <PagesInterface>{
    pageSize: 10,
    total: 0,
    currentPage: 1,
  },
  selectionList: [],
  itemTableData1: [],
  itemTableData2: [],
  open1: false,
  open2: false,
  itemTableLoading1: false,
  itemTableLoading2: false,
})
const {queryParams, form, page, selectionList} = toRefs(data);
const { queryParams, form, page, selectionList, itemTableData1, itemTableData2, open1, open2, itemTableLoading1, itemTableLoading2,
  pageAttachment
} = toRefs(data);
const option = ref({
  pageKey: 'DispatchOrder',
  rowKey: 'id',
  addBtn:false,
  editBtn:false,
  delBtn:false,
  viewBtn:false,
  selection:false,
  addBtn: false,
  editBtn: false,
  delBtn: false,
  viewBtn: false,
  selection: false,
  searchSpan: 5,
  searchLabelWidth: 100,
  column: {
    dispatchNo: {
      label: '调度单号',search:true,width: 120,
      fixed: 'left',
      label: '调度单号', search: true, minWidth: 180,
      rules: [
        {
          required: true,
@@ -94,83 +125,86 @@
      ],
    },
    transportMode: {
      label: '运输方式',width: 120,
      label: '运输方式', width: 120,
    },
    productName: {
      label: '服务产品名称',width: 120,
      label: '服务产品名称', width: 120, showOverflowTooltip: true
    },
    customerName: {
      label: '客户名称', search: true, width: 200, showOverflowTooltip: true
    },
    carrierName: {
      label: '承运商',search:true,width: 120,
      label: '承运商', search: true, width: 200, showOverflowTooltip: true
    },
    departureLocationName: {
      label: '出发地名称',width: 120,
      label: '出发地名称', width: 210, showOverflowTooltip: true
    },
    arrivalLocationName: {
      label: '目的地名称',width: 120,
      label: '目的地名称', width: 200, showOverflowTooltip: true
    },
    licensePlateNumber: {
      label: '车牌',search:true,width: 120,
      label: '车牌', search: true, width: 120,
    },
    vehiclePlateId: {
      label: '车板号',width: 120,
      label: '车板号', width: 120,
    },
    mainDriverName: {
      label: '主驾驶员',width: 120,
    },
    assistantDriverName: {
      label: '副驾驶员',width: 120,
    },
    pointNum: {
      label: '提送货点数',width: 120,
    },
    quantity: {
      label: '件数',width: 120,
    },
    actualDepartureTime: {
      label: '实际出发时间',width: 180,
    },
    actualDepartureTimeRange: {
      label: '实际出发时间',display: false,search: true, searchRange: true, type: 'date',
      format: 'YYYY-MM-DD',hide: true,searchSpan: 6,searchLabelWidth: 110,
      valueFormat: 'YYYY-MM-DD',
    },
    requiredArrivalTime: {
      label: '要求到达时间',width: 180,
    },
    requiredArrivalTimeRange: {
      label: '要求到达时间',display: false,search: true, searchRange: true, type: 'date',
      format: 'YYYY-MM-DD',hide: true,searchSpan: 6,searchLabelWidth: 110,
      valueFormat: 'YYYY-MM-DD',
    },
    actualArrivalTime: {
      label: '实际到达时间',width: 180,
    },
    actualArrivalTimeRange: {
      label: '要求到达时间',display: false,search: true, searchRange: true, type: 'date',
      format: 'YYYY-MM-DD',hide: true,searchSpan: 6,searchLabelWidth: 110,
      valueFormat: 'YYYY-MM-DD',
    },
    beReturn: {
      label: '是否回程',dataType:'string',width: 100,
      type: 'select', dicUrl: '/system/dict/data/type/dispatch_order_status',
    },
    dispatchQuantity: {
      label: '实发件数',width: 100,
    },
    dispatchWeight: {
      label: '实发重量',width: 100,
    },
    dispatchVolume: {
      label: '实发体积(立方)',width: 100,
    },
    status: {
      label: '状态',search: true,dataType:'string',width: 100,
      type: 'select', dicUrl: '/system/dict/data/type/dispatch_order_status',
    },
    remark: {
      label: '备注',width: 120,
      type: 'textarea', minRows: 3, maxRows: 5,
    },
    // mainDriverName: {
    //   label: '主驾驶员', width: 120,
    // },
    // assistantDriverName: {
    //   label: '副驾驶员', width: 120,
    // },
    // pointNum: {
    //   label: '提送货点数', width: 120,
    // },
    // quantity: {
    //   label: '件数', width: 120,
    // },
    // actualDepartureTime: {
    //   label: '实际出发时间', width: 180,
    // },
    // actualDepartureTimeRange: {
    //   label: '实际出发时间', display: false, search: true, searchRange: true, type: 'date',
    //   format: 'YYYY-MM-DD', hide: true, searchSpan: 5, searchLabelWidth: 120,
    //   valueFormat: 'YYYY-MM-DD',
    // },
    // requiredArrivalTime: {
    //   label: '要求到达时间', width: 180,
    // },
    // requiredArrivalTimeRange: {
    //   label: '要求到达时间', display: false, search: true, searchRange: true, type: 'date',
    //   format: 'YYYY-MM-DD', hide: true, searchSpan: 5, searchLabelWidth: 120,
    //   valueFormat: 'YYYY-MM-DD',
    // },
    // actualArrivalTime: {
    //   label: '实际到达时间', width: 180,
    // },
    // actualArrivalTimeRange: {
    //   label: '要求到达时间', display: false, search: true, searchRange: true, type: 'date',
    //   format: 'YYYY-MM-DD', hide: true, searchSpan: 5, searchLabelWidth: 120,
    //   valueFormat: 'YYYY-MM-DD',
    // },
    // beReturn: {
    //   label: '是否回程', dataType: 'string', width: 100,
    //   type: 'select', dicUrl: '/system/dict/data/type/dispatch_order_status',
    // },
    // dispatchQuantity: {
    //   label: '实发件数', width: 100,
    // },
    // dispatchWeight: {
    //   label: '实发重量', width: 100,
    // },
    // dispatchVolume: {
    //   label: '实发体积(立方)', width: 160,
    // },
    // status: {
    //   label: '状态', search: true, dataType: 'string', width: 100,
    //   type: 'select', dicUrl: '/system/dict/data/type/dispatch_order_status',
    // },
    // remark: {
    //   label: '备注', width: 120,
    //   type: 'textarea', minRows: 3, maxRows: 5,
    // },
    // createBy: {
    //   label: '创建人',
    // },
@@ -183,9 +217,9 @@
    // updateTime: {
    //   label: '修改时间',
    // },
    isDeleted: {
      label: '是否删除(0-否,1-是)',
    },
    // isDeleted: {
    //   label: '是否删除(0-否,1-是)',
    // },
  }
})
@@ -221,17 +255,162 @@
  handleUpdateFunc: () => {
    crudRef.value.rowEdit(selectionList.value[0]);
  },
  getBeginListFunc(params:any = {}){
    params = proxy.addDateRangeNew(params, params?.actualDepartureTimeRange, 'actualDepartureTime') || {};
    params = proxy.addDateRangeNew(params, params?.requiredArrivalTimeRange, 'requiredArrivalTime') || {};
    params = proxy.addDateRangeNew(params, params?.actualArrivalTimeRange, 'actualArrivalTime') || {};
    return params;
  getBeginListFunc() {
    queryParams.value = proxy.addDateRangeNew(queryParams.value, queryParams.value?.actualDepartureTimeRange, 'actualDepartureTime') || {};
    queryParams.value = proxy.addDateRangeNew(queryParams.value, queryParams.value?.requiredArrivalTimeRange, 'requiredArrivalTime') || {};
    queryParams.value = proxy.addDateRangeNew(queryParams.value, queryParams.value?.actualArrivalTimeRange, 'actualArrivalTime') || {};
  },
  handleSelectionChangeFunc: (selection: any) => {
    selectionList.value = selection;
  }
})
useTableColumnWidth(option.value, crudRef); // 使用 Hook 管理列宽
const itemTableOption1 = ref({
  addBtn: false,
  selection: false,
  menu: false,
  header: false,
  column: {
    feeItem: {
      label: '费用类型', minWidth: 180, fixed: 'left'
    },
    receivableFee: {
      label: '应收费用', minWidth: 180,
    },
    receivableFeeCurrency: {
      label: '应收币制类型', minWidth: 180,
    },
    actualFee: {
      label: '应付费用', minWidth: 180,
    },
    actualFeeCurrency: {
      label: '应付费用币制类型', minWidth: 180,
    },
    isSettlement: {
      label: '是否可付款', dataType: 'string', minWidth: 180,
      type: 'select',
      dicUrl: '/system/dict/data/type/sys_whether_type',
    },
  }
})
const itemTableOption2 = ref({
  addBtn: false,
  selection: false,
  menu: false,
  header: false,
  column: {
    feeItem: {
      label: '费用类型', minWidth: 180, fixed: 'left'
    },
    account: {
      label: '金额', minWidth: 180,
    },
    currency: {
      label: '币值', minWidth: 180,
    },
    imageUrl: {
      label: '图片',
      prop: 'img',
      dataType: 'string',
      type: 'img'
    },
  }
})
const handleFy = (row: DispatchOrderI) => {
  cwglDispatchOrderItem({ no: row.dispatchNo }).then((res: any) => {
    if (res.code == 200) {
      itemTableData1.value = res.data || [];
      open1.value = true;
    }
  })
}
const pangeIshow = ref(false);
const handleFj = (row: DispatchOrderI) => {
   pageAttachment.value  ={
    pageSize: 10,
    pageNum: 1,
    no:row.dispatchNo
  }
  pangeIshow.value = true;
  cwglDispatchOrderattAchment(pageAttachment.value).then((res: any) => {
    if (res.code == 200) {
      itemTableData2.value = res.rows || [];
      pageAttachment.value.total = res.total || 0;
      open2.value = true;
    }
  })
}
// 处理附件分页页码变化
const handleAttachmentCurrentChange = (currentPage: number) => {
  pageAttachment.value.pageNum = currentPage;
  loadAttachmentData();
}
// 处理附件分页大小变化
const handleAttachmentSizeChange = (pageSize: number) => {
  pageAttachment.value.pageSize = pageSize;
  // pageAttachment.value.currentPage = 1; // 重置到第一页
  loadAttachmentData();
}
// 加载附件数据的函数
const loadAttachmentData = () => {
  itemTableLoading2.value = true;
  cwglDispatchOrderattAchment({
    no: pageAttachment.value.no,
    pageNum:  pageAttachment.value.pageNum,
    pageSize: pageAttachment.value.pageSize
  }).then((res: any) => {
    if (res.code == 200) {
      itemTableData2.value = res.rows || [];
      pageAttachment.value.total = res.total || 0;
    }
    itemTableLoading2.value = false;
  }).catch(() => {
    itemTableLoading2.value = false;
  });
}
// 附件表格加载事件
const attachmentChange = () => {
  // loadAttachmentData();
}
const handleExport2 =()=>{
  queryParams.value = proxy.addDateRangeNew(queryParams.value, queryParams.value?.actualDepartureTimeRange, 'actualDepartureTime') || {};
  queryParams.value = proxy.addDateRangeNew(queryParams.value, queryParams.value?.requiredArrivalTimeRange, 'requiredArrivalTime') || {};
  queryParams.value = proxy.addDateRangeNew(queryParams.value, queryParams.value?.actualArrivalTimeRange, 'actualArrivalTime') || {};
  exportDispatchOrder2(queryParams.value);
}
const downPZ =()=>{
  downloadFJ({no:pageAttachment.value.no}).then(res=>{
    console.log(res)
      const blob = new Blob([res])
    console.log(blob)
      saveAs(blob, decodeURI(pageAttachment.value.no+"附件.pdf"))
  })
}
</script>
<style lang="scss" scoped>
.avue-dialog .el-dialog__body {
  padding: 20px 20px;
  flex: 1;
  overflow: scroll;
}
.attachment-image {
  .el-image__preview {
    z-index: 9999 !important;
  }
}
</style>