sen
1 天以前 5abcde36961125cbf436f91b8c17610a6b5f8308
ui/admin-ui3/src/views/tms/generationCost/index.vue
@@ -72,8 +72,9 @@
                </el-select>
              </el-descriptions-item>
              <el-descriptions-item label="是否存在应付报价">
                <span :style="{ color: row.isCZYF == 0 ? 'red' : '' }">{{ row.isCZYF == 0 ? '否' : row.isCZYF == 1 ? '是' :
                  ''}}</span>
                <span :style="{ color: row.isCZYF == 0 ? 'red' : '' }">{{ row.isCZYF == 0 ? '否' : row.isCZYF == 1 ? '是'
                  :
                  '' }}</span>
              </el-descriptions-item>
              <el-descriptions-item label="计费金额">
@@ -83,7 +84,7 @@
              <el-descriptions-item label="币制">
                <el-radio-group v-model="row.yfCurrency">
                  <el-radio v-for="dict in sys_currency" :key="dict.value" :label="dict.value">{{ dict.label
                    }}</el-radio>
                  }}</el-radio>
                </el-radio-group>
              </el-descriptions-item>
              <el-descriptions-item label="计费数量">
@@ -99,15 +100,32 @@
      <div v-if="active === 'tab2'">
        <h2>实报实销费用</h2>
        <avue-form v-model="boxForm" ref="boxFormRef" :option="boxFormOption">
          <template #voucherUrl="{ row }">
            <el-upload class="upload-demo" ref="uploadRef" :limit="1" drag :action="urlApi + '/common/upload2'" multiple
              :show-file-list="true" :on-success="(res) => handleUploadAfter(res, row)"
              :on-exceed="(files) => handleExceed(files, row)">
              <el-icon class="el-icon--upload"><upload-filled /></el-icon>
              <div class="el-upload__text">
                点击或将图片拖拽到此区域上传
              </div>
            </el-upload>
          </template>
        </avue-form>
        <avue-crud :option="boxTableOption" :data="boxTableData">
        <avue-crud :option="boxTableOption" :data="boxTableData" @selection-change="boxSelectionChange">
          <template #menu-left>
            <el-button type="danger" plain icon="Delete"
              :disabled="!(boxSelectionList.length === 1 && boxSelectionList[0]?.status === 0)"
              @click="handleBatchBoxDel">
              作废
            </el-button>
          </template>
          <template #isYF="{ row }">
            <el-checkbox v-model="row.isYF" :true-value="1" :false-value="0"
            <el-checkbox v-model="row.isYF" :disabled="row.status == 1" :true-value="1" :false-value="0"
              @change="(e: number) => isYFChange(e, row)"></el-checkbox>
          </template>
          <template #yfServiceProviderId="{ row }">
            <el-select v-model="row.yfServiceProviderIdType" placeholder="请选择服务商"
            <el-select :disabled="row.status == 1" v-model="row.yfServiceProviderIdType" placeholder="请选择服务商"
              @change="(e: any) => ysServiceProviderChange(e, row)" :filterable="true">
              <el-option v-for="item in serviceProviderList"
                :key="item.serviceProviderId + '_' + item.serviceProviderType" :label="item.serviceProviderName"
@@ -115,10 +133,11 @@
            </el-select>
          </template>
          <template #yfPrice="{ row }">
            <el-input v-model="row.yfPrice" :min="1" type="number" placeholder="请输入金额"></el-input>
            <el-input :disabled="row.status == 1" v-model="row.yfPrice" :min="1" type="number"
              placeholder="请输入金额"></el-input>
          </template>
          <template #yfCurrency="{ row }">
            <el-radio-group v-model="row.yfCurrency">
            <el-radio-group v-model="row.yfCurrency" :disabled="row.status == 1">
              <el-radio v-for="dict in sys_currency" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
            </el-radio-group>
          </template>
@@ -210,7 +229,7 @@
  updateTmsDispatchOrder,
  generateTmsDispatchOrder, initGenerate, initYSGenerate,
  ysGenerateTmsDispatchOrder, initYFGenerate, yfGenerateTmsDispatchOrder,
  getServiceProvider, checkCloseOrder, closeOrder
  getServiceProvider, checkCloseOrder, closeOrder, tmsFinanceDetail
} from "@/api/tms/tmsDispatchOrder";
import useCurrentInstance from "@/utils/useCurrentInstance";
import { computed, onMounted, reactive, ref, toRefs, watch, getCurrentInstance, nextTick } from "vue";
@@ -227,6 +246,7 @@
import { listTmsLoadingServiceProvider } from "@/api/tms/tmsLoadingServiceProvider";
import { selectPaymentTmsQuotePlan } from "@/api/tms/tmsQuotePlan";
import { addTmsQuoteFee, listTmsQuoteFee, pushTmsQuoteFee } from "@/api/tms/tmsQuoteFee";
import { status } from "nprogress";
@@ -253,6 +273,8 @@
};
const data = reactive({
  form: <TmsDispatchOrderI>{},
  selectionList2: <any>[],
  boxSelectionList: <any>[],
  queryParams: <TmsDispatchOrderI & PageQueryInterface>{},
  page: <PagesInterface>{
    pageSize: 10,
@@ -270,7 +292,6 @@
  open: false,
  open2: false,
  goodsTableData: <any>[],
  selectionList2: <any>[],
  goodsForm: <any>{},
  open3: false,
  actualForm: <any>{},
@@ -283,7 +304,7 @@
})
const {
  queryParams, form, page, selectionList,
  boxTableData, optionType, open, open5,
  boxTableData, optionType, open, open5, boxSelectionList,
  boxFormOption, boxForm, boxTableOption, boxItemTableOption, selectionList2, isCustoms, isLoad, active, quotationItems, serviceProviderList
} = toRefs(data);
const option = ref({
@@ -808,7 +829,7 @@
      display: true,
    },
    voucherUrl: {
      label: '行程凭证',
      label: '行程凭证3',
      display: true,
      span: 24, dataType: 'string',
      type: 'upload',
@@ -861,8 +882,8 @@
      display: true,
      accept: 'string', dataType: 'string',
      type: 'upload',
      action: '/common/upload2',
      // action: '/common/upload2',
      slot: true,
    },
    remark: {
      label: '备注', span: 24,
@@ -881,7 +902,8 @@
const financeTableOption = ref({
  menu: false,
  addBtn: false,
  header: false, selection: false,
  header: true,
  selection: true,
  title: '历史垫付费用',
  column: {
    dataSource: {
@@ -952,9 +974,12 @@
    yfCurrency: {
      label: '应付币制',
      display: true,
    }
    },
    status: {
      label: '状态',
      display: true,
      type: 'select', dicUrl: '/system/dict/data/type/sys_cancel_word', dataType: 'string',
    },
  }
})
@@ -1198,50 +1223,48 @@
    console.log(pageF.single)
  },
  getBeginListFunc: (params = {}) => {
    // 1. 日期转换
    let newParams = <any>{ ...params };
    if (newParams) {
      // 1. 定义日期字段映射 (数组名 : 接口需要的前缀)
      // 这样写的好处是:如果你有多个日期,直接在这里添加一行即可
      const dateMap = {
        createTimeRange: 'createTime',
        updateTimeRange: 'updateTime',
        confirmTimeRange: 'confirmTime',
        okTimeRange: 'okTime',
    // 1. 使用浅拷贝,不影响原始查询对象
    // 关键点:从原始 queryParams.value 取值,确保分页时依然能拿到数组
    let newParams = { ...queryParams.value, ...params };
      };
    // 2. 定义日期字段映射 (数组名 : 接口需要的前缀)
    const dateMap = {
      createTimeRange: 'createTime',
      updateTimeRange: 'updateTime',
      confirmTimeRange: 'confirmTime',
      okTimeRange: 'okTime',
    };
      // 2. 遍历处理日期
      Object.keys(dateMap).forEach(arrayKey => {
        const prefix = dateMap[arrayKey];
        const range = newParams[arrayKey];
    // 3. 遍历处理日期
    Object.keys(dateMap).forEach(arrayKey => {
      const prefix = dateMap[arrayKey];
      const range = newParams[arrayKey];
        if (Array.isArray(range) && range.length > 0) {
          // 赋值 Begin 和 End
          newParams[`${prefix}Begin`] = range[0];
          newParams[`${prefix}End`] = range[1];
        }
      if (Array.isArray(range) && range.length === 2) {
        // 赋值接口需要的 Begin 和 End
        newParams[`${prefix}Begin`] = range[0];
        newParams[`${prefix}End`] = range[1];
      }
        // 【核心改动】:无论是否有值,处理完后都把原始的 Array 字段删掉
        // 这样请求里就不会出现 confirmTimeRangeArray: [...]
        delete newParams[arrayKey];
      });
      // 只在给接口的参数中删除数组,不影响页面显示的 queryParams
      delete newParams[arrayKey];
    });
      // 3. 通用清洗:删除所有空字符串、null 或 undefined 的其他字段
      Object.keys(newParams).forEach(key => {
        const val = newParams[key];
        if (val === '' || val === null || val === undefined) {
          delete newParams[key];
        }
      });
    // 4. 清洗参数:过滤空值
    const finalParams = {};
    Object.keys(newParams).forEach(key => {
      const val = newParams[key];
      if (val !== '' && val !== null && val !== undefined) {
        finalParams[key] = val;
      }
    });
    } else {
      newParams = {};
    }
    console.log('发送给接口的最终参数:', finalParams);
    return newParams;
    // 【核心修改】:直接返回,不要赋值给 queryParams.value
    return finalParams;
  },
})
@@ -1261,7 +1284,6 @@
const submitForm = () => {
  if (active.value === 'tab1') {
    console.log()
    pushTmsQuoteFee({
      ...form.value,
      quoteFeeItems: selectionList2.value
@@ -1278,6 +1300,7 @@
    if (Array.isArray(boxForm.value.feeVoucherUrl)) {
      boxForm.value.feeVoucherUrl = boxForm.value.feeVoucherUrl.toString();
    }
    boxForm.value.rowItems = boxTableData.value;
    saveTmsFinanceDetail(boxForm.value).then(res => {
      ElMessage({
@@ -1285,6 +1308,7 @@
        type: 'success'
      })
      boxFormRef.value?.resetFields();
      uploadRef.value?.clearFiles();
      getTab2Data();
    })
  }
@@ -1329,7 +1353,6 @@
  const quotePlanItemRes2 = await listTmsQuoteItem({ quotePlanId: form.value.quotePlanId, pageNum: 1, pageSize: 999 });
  let list = quotePlanItemRes2.rows || [];
  let quotePlanItemRes = await getDicts("sys_quotation_items");
  console.log(quotePlanItemRes)
  let items = quotePlanItemRes.data || [];
  let res = await listTmsQuoteFee({ dispatchId: form.value.id, pageNum: 1, pageSize: 999 });
  let rowsData = res.rows || [];
@@ -1457,7 +1480,6 @@
  if (value == 1) {
    let find: any = quotationItems.value.find((item: any) => item.dictLabel === row.feeType);
    if (find) {
      console.log(find, "find")
      let opt = find.remark;
      row.serviceProviderType = opt;
      if (opt == 0) {
@@ -1548,7 +1570,6 @@
      let receivableAmountHKD = items.filter((cItem: any) => cItem.currency == 'HKD').reduce((pre: any, cur: any) => {
        return pre + Number(cur.registerAmount)
      }, 0);
      console.log(receivableAmountRMB, receivableAmountHKD)
      item.receivableAmountRMB = receivableAmountRMB;
      item.receivableAmountHKD = receivableAmountHKD;
@@ -1630,7 +1651,6 @@
}
const submitForm5 = () => {
  boxFormRef.value.validate((valid: boolean, done: any) => {
    console.log(valid)
    if (valid) {
      boxForm.value.id = form.value.id;
      closeOrder(boxForm.value).then(res => {
@@ -1644,4 +1664,69 @@
    }
  })
}
const uploadRef = ref<any>()
const urlApi = ref(import.meta.env.VITE_APP_BASE_API)
// 在 script 部分修改 handleUploadAfter 函数
const handleUploadAfter = (res: any, row: any) => {
  if (res.code === 200) {
    // 确保 res.data.url 存在
    const url = res.data?.url || res.url;
    if (url) {
      boxForm.value.feeVoucherUrl = url
    } else {
      ElMessage.error('未获取到上传文件 URL');
    }
  } else {
    ElMessage.error(res.msg || '上传失败');
  }
};
// 同时修改 handleExceed 函数
const handleExceed = (files: any, row: any) => {
  if (!row) {
    ElMessage.error('行数据为空');
    return;
  }
  uploadRef.value?.clearFiles();
  const file = files[0];
  uploadRef.value?.handleStart(file);
  uploadRef.value?.submit();
};
const boxSelectionChange = (selection: any[]) => {
  boxSelectionList.value = selection;
}
/**
 * 批量作废费用明细
 */
const handleBatchBoxDel = () => {
  if (boxSelectionList.value.length === 0) {
    ElMessage.warning('请选择要作废的费用明细');
    return;
  }
  ElMessageBox.confirm(`确认要作废选中的 ${boxSelectionList.value.length} 条费用明细吗?`, '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // 从 boxTableData 中移除选中的项
    // const ids = boxSelectionList.value.map((item: any) => item.id).join(',');
    let data = {
      id: boxSelectionList.value[0].id,
      status: 1
    }
    tmsFinanceDetail(data).then(res => {
      ElMessage.success('作废成功');
      getTab2Data(); // 刷新数据
    }).catch(err => {
      ElMessage.error('作废失败');
    });
    // ElMessage.success('作废成功');
    // boxSelectionList.value = []; // 清空选择
  }).catch(() => {
    // 取消操作
  });
}
</script>