ZN
14 小时以前 2307a3125c23ad79ee92306603a418085cee194d
src/views/customerService/feedbackRegistration/components/formDia.vue
@@ -2,70 +2,118 @@
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        title="售后登记"
        width="70%"
        title="新增售后单"
        width="90%"
        @close="closeDia"
    >
         <el-form
            :model="form"
            label-width="140px"
            label-position="top"
            :rules="rules"
            ref="formRef"
         >
            <el-row :gutter="30">
               <el-col :span="12">
                  <el-form-item label="反馈时间:" prop="feedbackDate">
                     <el-date-picker
                        style="width: 100%"
                        v-model="form.feedbackDate"
                        value-format="YYYY-MM-DD"
                        format="YYYY-MM-DD"
                        type="date"
                        placeholder="请选择"
                        clearable
                     />
                  </el-form-item>
               </el-col>
               <el-col :span="12">
                  <el-form-item label="登记人:" prop="checkUserId">
                     <el-select
                        v-model="form.checkUserId"
                        placeholder="请选择"
                        clearable
                     >
                        <el-option
                           v-for="item in userList"
                           :key="item.userId"
                           :label="item.nickName"
                           :value="item.userId"
                        ></el-option>
                     </el-select>
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="12">
                  <el-form-item label="客户名称:" prop="customerName">
                     <el-input
                        v-model="form.customerName"
                        placeholder="请输入"
                        clearable
                     />
                  </el-form-item>
               </el-col>
               <el-col :span="12">
                  <el-form-item label="问题描述:" prop="proDesc">
                     <el-input
                        v-model="form.proDesc"
                        placeholder="请输入"
                        clearable
                        type="textarea"
                     />
                  </el-form-item>
               </el-col>
            </el-row>
         </el-form>
      <div>
        <span class="descriptions">基础资料</span>
        <el-form
            :model="form"
            label-width="140px"
            label-position="top"
            :rules="rules"
            ref="formRef"
        >
          <el-row :gutter="30">
            <el-col :span="4">
              <el-form-item label="客户名称:" prop="customerName">
                <el-select
                    v-model="form.customerName"
                    filterable
                    @change="customerNameChange"
                >
                  <el-option
                      v-for="item in customerNameOptions"
                      :key="item.value"
                      :label="item.label"
                      :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"
                      :key="dict.value"
                      :label="dict.label"
                      :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"
                    @change="associatedSalesOrderNumberChange"
                    filterable
                >
                  <el-option
                      v-for="item in associatedSalesOrderNumberOptions"
                      :key="item.value"
                      :label="item.label"
                      :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"
                      :key="dict.value"
                      :label="dict.label"
                      :value="dict.value"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="问题描述:" prop="disRes">
                <el-input
                    v-model="form.disRes"
                    placeholder="请输入问题描述"
                />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
        <hr>
          <div style="padding-top: 20px">
            <div style="display: flex; justify-content: space-between">
              <span class="descriptions">关联产品</span>
            <el-button
              type="primary"
              style="margin-right: 12px; margin-bottom: 10px"
              @click="isShowProductSelectDialog = true"
            >
              选择产品
            </el-button>
            </div>
            <PIMTable
                :isShowPagination="false"
                rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
            >
              <template #shippingStatus="{ row }">
                <el-tag :type="getShippingStatusType(row)" size="small">
                  {{ getShippingStatusText(row) }}
                </el-tag>
              </template>
            </PIMTable>
          </div>
      </div>
         <template #footer>
            <div class="dialog-footer">
               <el-button type="primary" @click="submitForm">确认</el-button>
@@ -73,63 +121,286 @@
            </div>
         </template>
    </el-dialog>
    <!-- 选择产品弹窗 -->
    <ProductSelectDialog
      v-model="isShowProductSelectDialog"
      :products="currentSalesOrderProducts"
      :selected-ids="currentSelectedProductIds"
      @confirm="handleSelectProducts"
    />
  </div>
</template>
<script setup>
import {ref} from "vue";
import { ref, reactive, toRefs, getCurrentInstance, computed } from "vue";
import ProductSelectDialog from "./ProductSelectDialog.vue";
import useUserStore from "@/store/modules/user.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import {afterSalesServiceAdd, afterSalesServiceUpdate} 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 dialogFormVisible = ref(false);
const operationType = ref('')
const formRef = ref(null)
const customerNameOptions = ref([])
const userStore = useUserStore();
const data = reactive({
   form: {
      feedbackDate: "",
      checkUserId: "",
      customerName: "",
      proDesc: "",
    topic: "",
    serviceType: "",
    urgency: "",
    salesLedgerId: null,
    productModelIds: "",
    customerId: null,
    salesContractNo: "",
    disRes: "",
    customerName: ""
   },
   rules: {
    customerName: [{required: true, message: "请选择客户名称", trigger: "change"}],
    serviceType: [{required: true, message: "请选择售后类型", trigger: "change"}],
    urgency: [{required: true, message: "请选择紧急程度", trigger: "change"}],
      feedbackDate: [{required: true, message: "请选择", trigger: "change"}],
      checkUserId: [{required: true, message: "请选择", trigger: "change"}],
      customerName: [{required: true, message: "请输入", trigger: "blur"}],
      proDesc: [{required: true, message: "请输入", trigger: "blur"}],
   }
})
// 自定义校验函数:判断是否需要校验售后编号
const { form, rules } = toRefs(data);
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 { post_sale_waiting_list, degree_of_urgency } = proxy.useDict(
  "post_sale_waiting_list",
  "degree_of_urgency"
);
const serviceTypeOptions = computed(() => post_sale_waiting_list?.value || []);
const urgencyOptions = computed(() => degree_of_urgency?.value || []);
const tableColumn = ref([
  { label: "产品大类", prop: "productCategory" },
  { label: "规格型号", prop: "specificationModel" },
  { label: "单位", prop: "unit" },
  {
    label: "产品状态",
    prop: "approveStatus",
    width: 100,
    align: "center",
    dataType: "tag",
    formatData: (v) => (v === 1 ? "充足" : "不足"),
    formatType: (v) => (v === 1 ? "success" : "danger"),
  },
  {
    label: "发货状态",
    align: "center",
    width: 140,
    dataType: "slot",
    slot: "shippingStatus",
  },
  { label: "快递公司", prop: "expressCompany", width: 140 },
  { label: "快递单号", prop: "expressNumber", width: 160 },
  { label: "发货车牌", prop: "shippingCarNumber", minWidth: 100, align: "center" },
  { label: "发货日期", prop: "shippingDate", minWidth: 100, align: "center" },
  { label: "数量", prop: "quantity", width: 100 },
  { label: "税率(%)", prop: "taxRate", width: 100 },
  {
    label: "含税单价(元)",
    prop: "taxInclusiveUnitPrice",
    width: 160,
    formatData: formatCurrency,
  },
  {
    label: "含税总价(元)",
    prop: "taxInclusiveTotalPrice",
    width: 160,
    formatData: formatCurrency,
  },
  {
    label: "不含税总价(元)",
    prop: "taxExclusiveTotalPrice",
    width: 160,
    formatData: formatCurrency,
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: 'right',
    operation: [
      {
        name: "删除",
        type: "text",
        clickFun: (row) => {
          tableData.value = tableData.value.filter(i => i.id !== row.id)
        },
      },
    ],
  },
])
const tableData = ref([])
// 选择产品弹窗
const isShowProductSelectDialog = ref(false)
const handleSelectProducts = (rows) => {
  if (!Array.isArray(rows)) return
  const existingIds = new Set(tableData.value.map(i => i.id))
  const mapped = rows
    .filter(r => !existingIds.has(r.id))
    .map(r => ({
      id: r.id,
      productCategory: r.productName,
      specificationModel: r.model,
      unit: r.unit || '',
      approveStatus: null,
      shippingStatus: '',
      expressCompany: '',
      expressNumber: '',
      shippingCarNumber: '',
      shippingDate: '',
      quantity: 0,
      taxRate: 0,
      taxInclusiveUnitPrice: 0,
      taxInclusiveTotalPrice: 0,
      taxExclusiveTotalPrice: 0,
    }))
  tableData.value = tableData.value.concat(mapped)
}
const currentSelectedProductIds = computed(() => {
  return tableData.value.map(item => item.id)
})
const associatedSalesOrderNumberChange = () => {
  const opt = associatedSalesOrderNumberOptions.value.find(
    (item) => item.value === form.value.salesContractNo
  )
  tableData.value = opt?.productData || []
  form.value.salesLedgerId = opt?.id || null
}
const associatedSalesOrderNumberOptions = ref([])
const currentSalesOrderProducts = computed(() => {
  const opt = associatedSalesOrderNumberOptions.value.find(
    (item) => item.value === form.value.salesContractNo
  )
  return opt?.productData || []
})
const customerNameChange = (val) => {
  const opt = customerNameOptions.value.find(item => item.value === val);
  if (opt) {
    form.value.customerId = opt.id;
  }
  getSalesLedger({
    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
      }))
    }
  })
}
const getShippingStatusText = (row) => {
  if (!row) return '待发货'
  if (row.shippingDate || row.shippingCarNumber) {
    return '已发货'
  }
  const status = row.shippingStatus
  if (status === null || status === undefined || status === '') {
    return '待发货'
  }
  const map = {
    '待发货': '待发货',
    '待审核': '待审核',
    '审核中': '审核中',
    '审核拒绝': '审核拒绝',
    '审核通过': '审核通过',
    '已发货': '已发货'
  }
  return map[String(status).trim()] || '待发货'
}
const getShippingStatusType = (row) => {
  if (!row) return 'info'
  if (row.shippingDate || row.shippingCarNumber) {
    return 'success'
  }
  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'
}
// 打开弹框
const openDialog = (type, row) => {
const openDialog =async (type, row) => {
  // 请求多个接口,获取数据
  let res = await getAllCustomerList();
  if(res.records){
    customerNameOptions.value = res.records.map(item => ({
      label: item.customerName,
      value: item.customerName,
      id: item.id
    }));
  }
  operationType.value = type;
  dialogFormVisible.value = true;
   form.value = {}
   proxy.resetForm("formRef");
   form.value.checkUserId = userStore.id;
   form.value.feedbackDate = getCurrentDate();
  // 新增时清空已选关联产品
  if (type === "add") {
    tableData.value = []
  }
   userListNoPageByTenantId().then((res) => {
      userList.value = res.data;
   });
   if (type === "edit") {
      form.value = {...row}
    if (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 => ({
          label: item.salesContractNo,
          value: item.salesContractNo,
          productData: item.productData,
          id: item.id
        }))
      }
    }
    console.log(form.value)
   }
}
// const setName = (code) => {
//    const index = userList.value.findIndex(item => item.deviceModel === code);
//    if (index > -1) {
//       console.log(userList)
//       form.value.name = userList.value[index].deviceName;
//    }
// }
const submitForm = () => {
   proxy.$refs["formRef"].validate(valid => {
      if (valid) {
      // 匹配产品型号IDs
      form.value.productModelIds = tableData.value.map(item => item.id).join(",")
         if (operationType.value === "add") {
            afterSalesServiceAdd(form.value).then(response => {
               proxy.$modal.msgSuccess("新增成功")
@@ -155,6 +426,25 @@
});
</script>
<style scoped>
<style scoped lang="scss">
.descriptions {
  margin-bottom: 20px;
  display: inline-block;
  font-size: 1rem;
  font-weight: 600;
  padding-left: 12px;
  position: relative;
}
</style>
.descriptions::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 1rem;
  background-color: #002FA7; /* Element 默认红色 */
  border-radius: 2px;
}
</style>