7 天以前 63afcf7bd6eff23e4feee8b6d12053bd8e78abb8
src/views/customerService/feedbackRegistration/components/formDia.vue
@@ -1,89 +1,72 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
    <el-dialog v-model="dialogFormVisible"
        title="新增售后单"
        width="90%"
        @close="closeDia"
    >
               @close="closeDia">
      <div>
        <span class="descriptions">基础资料</span>
        <el-form
            :model="form"
        <el-form :model="form"
            label-width="140px"
            label-position="top"
            :rules="rules"
            ref="formRef"
        >
                 ref="formRef">
          <el-row :gutter="30">
            <el-col :span="4">
              <el-form-item label="客户名称:" prop="customerName">
                <el-select
                    v-model="form.customerName"
              <el-form-item label="客户名称:"
                            prop="customerName">
                <el-select v-model="form.customerName"
                    filterable
                    @change="customerNameChange"
                >
                  <el-option
                      v-for="item in customerNameOptions"
                           @change="customerNameChange">
                  <el-option v-for="item in customerNameOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                  />
                             :value="item.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="售后类型:" prop="serviceType">
                <el-select
                    v-model="form.serviceType"
                    filterable
                >
                  <el-option
                      v-for="dict in serviceTypeOptions"
              <el-form-item label="售后类型:"
                            prop="serviceType">
                <el-select v-model="form.serviceType"
                           filterable>
                  <el-option v-for="dict in serviceTypeOptions"
                      :key="dict.value"
                      :label="dict.label"
                      :value="dict.value"
                  />
                             :value="dict.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="关联销售单号:" prop="salesContractNo">
                <el-select
                    v-model="form.salesContractNo"
              <el-form-item label="关联销售单号:"
                            prop="salesContractNo">
                <el-select v-model="form.salesContractNo"
                    @change="associatedSalesOrderNumberChange"
                    filterable
                >
                  <el-option
                      v-for="item in associatedSalesOrderNumberOptions"
                           filterable>
                  <el-option v-for="item in associatedSalesOrderNumberOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                  />
                             :value="item.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="紧急程度:" prop="urgency">
                <el-select
                    v-model="form.urgency"
                    filterable
                >
                  <el-option
                      v-for="dict in urgencyOptions"
              <el-form-item label="紧急程度:"
                            prop="urgency">
                <el-select v-model="form.urgency"
                           filterable>
                  <el-option v-for="dict in urgencyOptions"
                      :key="dict.value"
                      :label="dict.label"
                      :value="dict.value"
                  />
                             :value="dict.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="问题描述:" prop="proDesc">
                <el-input
                    v-model="form.proDesc"
                    placeholder="请输入问题描述"
                />
              <el-form-item label="问题描述:"
                            prop="proDesc">
                <el-input v-model="form.proDesc"
                          placeholder="请输入问题描述" />
              </el-form-item>
            </el-col>
          </el-row>
@@ -92,27 +75,25 @@
          <div style="padding-top: 20px">
            <div style="display: flex; justify-content: space-between">
              <span class="descriptions">关联产品</span>
            <el-button
              type="primary"
            <el-button type="primary"
              style="margin-right: 12px; margin-bottom: 10px"
              @click="isShowProductSelectDialog = true"
            >
                       @click="isShowProductSelectDialog = true">
              选择产品
            </el-button>
            </div>
            <PIMTable
                :isShowPagination="false"
          <PIMTable :isShowPagination="false"
                rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
            >
                    :tableData="tableData">
              <template #approveStatus="{ row }">
                <el-tag :type="getApproveStatusType(row)" size="small">
              <el-tag :type="getApproveStatusType(row)"
                      size="small">
                  {{ getApproveStatusText(row) }}
                </el-tag>
              </template>
              <template #shippingStatus="{ row }">
                <el-tag :type="getShippingStatusType(row)" size="small">
              <el-tag :type="getShippingStatusType(row)"
                      size="small">
                  {{ getShippingStatusText(row) }}
                </el-tag>
              </template>
@@ -121,18 +102,17 @@
      </div>
         <template #footer>
            <div class="dialog-footer">
               <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button type="primary"
                     @click="submitForm">确认</el-button>
               <el-button @click="closeDia">取消</el-button>
            </div>
         </template>
    </el-dialog>
    <!-- 选择产品弹窗 -->
    <ProductSelectDialog
      v-model="isShowProductSelectDialog"
    <ProductSelectDialog v-model="isShowProductSelectDialog"
      :products="currentSalesOrderProducts"
      :selected-ids="currentSelectedProductIds"
      @confirm="handleSelectProducts"
    />
                         @confirm="handleSelectProducts" />
  </div>
</template>
@@ -141,14 +121,19 @@
import ProductSelectDialog from "./ProductSelectDialog.vue";
import useUserStore from "@/store/modules/user.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import {afterSalesServiceAdd, afterSalesServiceUpdate, getAllCustomerList, getSalesLedger } from "@/api/customerService/index.js";
  import {
    afterSalesServiceAdd,
    afterSalesServiceUpdate,
    getAllCustomerList,
    getSalesLedger,
  } from "@/api/customerService/index.js";
import { getCurrentDate } from "@/utils/index.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
  const { proxy } = getCurrentInstance();
  const emit = defineEmits(["close"]);
const dialogFormVisible = ref(false);
const operationType = ref('')
const formRef = ref(null)
const customerNameOptions = ref([])
  const operationType = ref("");
  const formRef = ref(null);
  const customerNameOptions = ref([]);
const userStore = useUserStore();
const data = reactive({
@@ -161,26 +146,30 @@
    customerId: null,
    salesContractNo: "",
    proDesc: "",
    customerName: ""
      customerName: "",
   },
   rules: {
    customerName: [{required: true, message: "请选择客户名称", trigger: "change"}],
    serviceType: [{required: true, message: "请选择售后类型", trigger: "change"}],
      customerName: [
        { required: true, message: "请选择客户名称", trigger: "change" },
      ],
      serviceType: [
        { required: true, message: "请选择售后类型", trigger: "change" },
      ],
    urgency: [{required: true, message: "请选择紧急程度", trigger: "change"}],
      feedbackDate: [{required: true, message: "请选择", trigger: "change"}],
   }
})
    },
  });
// 自定义校验函数:判断是否需要校验售后编号
const { form, rules } = toRefs(data);
const userList = ref([])
  const userList = ref([]);
const formatCurrency = (val) => {
  if (val === null || val === undefined || val === '') return '-'
  const num = Number(val)
  return Number.isFinite(num) ? num.toFixed(2) : '-'
}
  const formatCurrency = val => {
    if (val === null || val === undefined || val === "") return "-";
    const num = Number(val);
    return Number.isFinite(num) ? num.toFixed(2) : "-";
  };
const { post_sale_waiting_list, degree_of_urgency } = proxy.useDict(
  "post_sale_waiting_list",
@@ -190,31 +179,38 @@
const serviceTypeOptions = computed(() => post_sale_waiting_list?.value || []);
const urgencyOptions = computed(() => degree_of_urgency?.value || []);
const getProductRowId = (row) => {
  return row?.id ?? row?.productModelId ?? row?.modelId ?? `${row?.productCategory || row?.productName || ""}-${row?.specificationModel || row?.model || ""}-${row?.unit || ""}`
}
  const getProductRowId = row => {
    return (
      row?.id ??
      row?.productModelId ??
      row?.modelId ??
      `${row?.productCategory || row?.productName || ""}-${
        row?.specificationModel || row?.model || ""
      }-${row?.unit || ""}`
    );
  };
const normalizeProductRow = (row) => {
  const normalizeProductRow = row => {
  return {
    ...row,
    id: getProductRowId(row),
    productCategory: row?.productCategory ?? row?.productName ?? '',
    specificationModel: row?.specificationModel ?? row?.model ?? '',
    unit: row?.unit ?? '',
      productCategory: row?.productCategory ?? row?.productName ?? "",
      specificationModel: row?.specificationModel ?? row?.model ?? "",
      unit: row?.unit ?? "",
    approveStatus: row?.approveStatus ?? null,
    shippingStatus: row?.shippingStatus ?? '',
    expressCompany: row?.expressCompany ?? '',
    expressNumber: row?.expressNumber ?? '',
    shippingCarNumber: row?.shippingCarNumber ?? '',
    shippingDate: row?.shippingDate ?? '',
      shippingStatus: row?.shippingStatus ?? "",
      expressCompany: row?.expressCompany ?? "",
      expressNumber: row?.expressNumber ?? "",
      shippingCarNumber: row?.shippingCarNumber ?? "",
      shippingDate: row?.shippingDate ?? "",
    quantity: row?.quantity ?? 0,
    taxRate: row?.taxRate ?? 0,
    taxInclusiveUnitPrice: row?.taxInclusiveUnitPrice ?? 0,
    taxInclusiveTotalPrice: row?.taxInclusiveTotalPrice ?? 0,
    taxExclusiveTotalPrice: row?.taxExclusiveTotalPrice ?? 0,
    noQuantity: row?.noQuantity ?? 0,
  }
}
    };
  };
const tableColumn = ref([
  { label: "产品大类", prop: "productCategory" },
@@ -237,7 +233,12 @@
  },
  { label: "快递公司", prop: "expressCompany", width: 140 },
  { label: "快递单号", prop: "expressNumber", width: 160 },
  { label: "发货车牌", prop: "shippingCarNumber", minWidth: 100, align: "center" },
    {
      label: "发货车牌",
      prop: "shippingCarNumber",
      minWidth: 100,
      align: "center",
    },
  { label: "发货日期", prop: "shippingDate", minWidth: 100, align: "center" },
  { label: "数量", prop: "quantity", width: 100 },
  { label: "税率(%)", prop: "taxRate", width: 100 },
@@ -263,52 +264,57 @@
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: 'right',
      fixed: "right",
    operation: [
      {
        name: "删除",
        type: "text",
        clickFun: (row) => {
          tableData.value = tableData.value.filter(i => getProductRowId(i) !== getProductRowId(row))
          clickFun: row => {
            tableData.value = tableData.value.filter(
              i => getProductRowId(i) !== getProductRowId(row)
            );
        },
      },
    ],
  },
])
const tableData = ref([])
  ]);
  const tableData = ref([]);
// 选择产品弹窗
const isShowProductSelectDialog = ref(false)
const handleSelectProducts = (rows) => {
  if (!Array.isArray(rows)) return
  const existingIds = new Set(tableData.value.map(i => String(getProductRowId(i))))
  const isShowProductSelectDialog = ref(false);
  const handleSelectProducts = rows => {
    if (!Array.isArray(rows)) return;
    const existingIds = new Set(
      tableData.value.map(i => String(getProductRowId(i)))
    );
  const mapped = rows
    .map(normalizeProductRow)
    .filter(r => !existingIds.has(String(getProductRowId(r))))
  tableData.value = tableData.value.concat(mapped)
}
      .filter(r => !existingIds.has(String(getProductRowId(r))));
    tableData.value = tableData.value.concat(mapped);
  };
const currentSelectedProductIds = computed(() => {
  return tableData.value.map(item => getProductRowId(item)).filter(item => item !== undefined && item !== null && item !== '')
})
    return tableData.value
      .map(item => getProductRowId(item))
      .filter(item => item !== undefined && item !== null && item !== "");
  });
const associatedSalesOrderNumberChange = () => {
  const opt = associatedSalesOrderNumberOptions.value.find(
    (item) => item.value === form.value.salesContractNo
  )
  tableData.value = (opt?.productData || []).map(normalizeProductRow)
  form.value.salesLedgerId = opt?.id || null
}
      item => item.value === form.value.salesContractNo
    );
    tableData.value = (opt?.productData || []).map(normalizeProductRow);
    form.value.salesLedgerId = opt?.id || null;
  };
const associatedSalesOrderNumberOptions = ref([])
  const associatedSalesOrderNumberOptions = ref([]);
const currentSalesOrderProducts = computed(() => {
  const opt = associatedSalesOrderNumberOptions.value.find(
    (item) => item.value === form.value.salesContractNo
  )
  return (opt?.productData || []).map(normalizeProductRow)
})
      item => item.value === form.value.salesContractNo
    );
    return (opt?.productData || []).map(normalizeProductRow);
  });
const customerNameChange = (val) => {
  const customerNameChange = val => {
  form.value.salesContractNo = "";
  form.value.salesLedgerId = null;
  tableData.value = [];
@@ -320,74 +326,77 @@
    form.value.customerId = null;
  }
  getSalesLedger({
    customerName: form.value.customerName
      customerName: form.value.customerName,
  }).then(res => {
    if(res.code === 200){
      associatedSalesOrderNumberOptions.value = res.data.records.map(item => ({
        label: item.salesContractNo,
        value: item.salesContractNo,
        productData:item.productData,
        id: item.id
      }))
          id: item.id,
        }));
    }
  })
}
    });
  };
const getApproveStatusText = (row) => {
  if (!row) return '不足'
  if (row.approveStatus === 1 && (!row.shippingDate || !row.shippingCarNumber)) {
    return '充足'
  const getApproveStatusText = row => {
    if (!row) return "不足";
    if (
      row.approveStatus === 1 &&
      (!row.shippingDate || !row.shippingCarNumber)
    ) {
      return "充足";
  }
  if (row.approveStatus === 0 && (row.shippingDate || row.shippingCarNumber)) {
    return '已出库'
      return "已出库";
  }
  return '不足'
}
    return "不足";
  };
const getApproveStatusType = (row) => {
  const statusText = getApproveStatusText(row)
  return statusText === '不足' ? 'danger' : 'success'
}
  const getApproveStatusType = row => {
    const statusText = getApproveStatusText(row);
    return statusText === "不足" ? "danger" : "success";
  };
const getShippingStatusText = (row) => {
  if (!row) return '待发货'
  const getShippingStatusText = row => {
    if (!row) return "待发货";
  if (row.shippingDate || row.shippingCarNumber) {
    return '已发货'
      return "已发货";
  }
  const status = row.shippingStatus
  if (status === null || status === undefined || status === '') {
    return '待发货'
    const status = row.shippingStatus;
    if (status === null || status === undefined || status === "") {
      return "待发货";
  }
  const map = {
    '待发货': '待发货',
    '待审核': '待审核',
    '审核中': '审核中',
    '审核拒绝': '审核拒绝',
    '审核通过': '审核通过',
    '已发货': '已发货'
  }
  return map[String(status).trim()] || '待发货'
}
      待发货: "待发货",
      待审核: "待审核",
      审核中: "审核中",
      审核拒绝: "审核拒绝",
      审核通过: "审核通过",
      已发货: "已发货",
    };
    return map[String(status).trim()] || "待发货";
  };
const getShippingStatusType = (row) => {
  if (!row) return 'info'
  const getShippingStatusType = row => {
    if (!row) return "info";
  if (row.shippingDate || row.shippingCarNumber) {
    return 'success'
      return "success";
  }
  const status = row.shippingStatus
  if (status === null || status === undefined || status === '') {
    return 'info'
    const status = row.shippingStatus;
    if (status === null || status === undefined || status === "") {
      return "info";
  }
  const map = {
    '待发货': 'info',
    '待审核': 'warning',
    '审核中': 'warning',
    '审核拒绝': 'danger',
    '审核通过': 'success',
    '已发货': 'success'
  }
  return map[String(status).trim()] || 'info'
}
      待发货: "info",
      待审核: "warning",
      审核中: "warning",
      审核拒绝: "danger",
      审核通过: "success",
      已发货: "success",
    };
    return map[String(status).trim()] || "info";
  };
// 打开弹框
const openDialog =async (type, row) => {
@@ -397,69 +406,77 @@
  size: 1000,
  total: 0,
  });
  if(res.records){
    customerNameOptions.value = res.records.map(item => ({
    console.log(res, "res");
    if (res.data.records) {
      customerNameOptions.value = res.data.records.map(item => ({
      label: item.customerName,
      value: item.customerName,
      id: item.id
        id: item.id,
    }));
    } else {
  }
  operationType.value = type;
  dialogFormVisible.value = true;
   form.value = {}
    form.value = {};
   proxy.resetForm("formRef");
   form.value.checkUserId = userStore.id;
   form.value.feedbackDate = getCurrentDate();
  // 新增时清空已选关联产品
  if (type === "add") {
    tableData.value = []
      tableData.value = [];
  }
   userListNoPageByTenantId().then((res) => {
    userListNoPageByTenantId().then(res => {
      userList.value = res.data;
   });
   if (type === "edit") {
      form.value = {...row}
      form.value = { ...row };
    if (form.value.customerName) {
      const res = await getSalesLedger({ customerName: form.value.customerName })
        const res = await getSalesLedger({
          customerName: form.value.customerName,
        });
      if (res?.code === 200) {
        console.log(res)
        associatedSalesOrderNumberOptions.value = (res.data?.records || []).map(item => ({
          console.log(res);
          associatedSalesOrderNumberOptions.value = (res.data?.records || []).map(
            item => ({
          label: item.salesContractNo,
          value: item.salesContractNo,
          productData: item.productData,
          id: item.id
        }))
              id: item.id,
            })
          );
      }
    }
    console.log(form.value)
      console.log(form.value);
   }
}
  };
const submitForm = () => {
   proxy.$refs["formRef"].validate(valid => {
      if (valid) {
      // 匹配产品型号IDs
      form.value.productModelIds = tableData.value.map(item => item.id).join(",")
        form.value.productModelIds = tableData.value
          .map(item => item.id)
          .join(",");
         if (operationType.value === "add") {
            afterSalesServiceAdd(form.value).then(response => {
               proxy.$modal.msgSuccess("新增成功")
               closeDia()
            })
            proxy.$modal.msgSuccess("新增成功");
            closeDia();
          });
         } else {
            afterSalesServiceUpdate(form.value).then(response => {
               proxy.$modal.msgSuccess("修改成功")
               closeDia()
            })
            proxy.$modal.msgSuccess("修改成功");
            closeDia();
          });
         }
      }
   })
}
    });
  };
// 关闭弹框
const closeDia = () => {
   proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  emit('close')
    emit("close");
};
defineExpose({
  openDialog,
@@ -484,7 +501,7 @@
  transform: translateY(-50%);
  width: 4px;
  height: 1rem;
  background-color: #002FA7; /* Element 默认红色 */
    background-color: #002fa7; /* Element 默认红色 */
  border-radius: 2px;
}
</style>