yyb
20 小时以前 b6a007d417bf5eea80ec807d3f1201e220e5f651
销售和采购退货
已修改7个文件
670 ■■■■■ 文件已修改
src/api/procurementManagement/purchase_return_order.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/purchaseReturnOrder/New.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/purchaseReturnOrder/ProductList.vue 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/purchaseReturnOrder/index.vue 440 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/returnOrder/components/detailDia.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/returnOrder/components/formDia.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/returnOrder/index.vue 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/procurementManagement/purchase_return_order.js
@@ -19,6 +19,15 @@
    });
}
// 根据采购台账 ID 查询可退产品等信息
export function getPurchaseReturnOrderByPurchaseLedgerId(query) {
    return request({
        url: "/purchaseReturnOrders/getByPurchaseLedgerId",
        method: "get",
        params: query,
    });
}
// 查看详情
// purchaseReturnOrders/selectById/xxx
export function getPurchaseReturnOrderDetail(id) {
src/views/procurementManagement/purchaseReturnOrder/New.vue
@@ -227,10 +227,11 @@
              <span class="title-text">产品列表</span>
            </div>
            <el-button type="primary" size="small" style="margin-bottom: 20px" @click="isShowProductsModal = true" :disabled="!formState.purchaseLedgerId">添加产品</el-button>
            <el-table :data="formState.purchaseReturnOrderProductsDtos"
            <div class="product-table-scroll">
            <el-table class="product-table-inner"
                      :data="formState.purchaseReturnOrderProductsDtos"
                      border
                      max-height="400"
                      :scroll-y="true"
                      show-summary
                      :summary-method="summarizeChildrenTable">
              <el-table-column align="center"
@@ -240,6 +241,12 @@
                               label="序号"
                               type="index"
                               width="60" />
              <el-table-column label="入库单号"
                               prop="inboundBatches"
                               width="150" />
              <el-table-column label="批次号"
                               prop="batchNo"
                               width="150" />
              <el-table-column label="产品大类"
                               prop="productCategory" />
              <el-table-column label="规格型号"
@@ -248,10 +255,13 @@
                               prop="unit"
                               width="70" />
              <el-table-column label="数量"
                               prop="quantity"
                               prop="stockInNum"
                               width="100" />
                               <el-table-column label="可退货数量"
                               prop="availableQuality"
                               prop="unQuantity"
                               width="130" />
              <el-table-column label="已退货数量"
                               prop="totalReturnNum"
                               width="130" />
              <el-table-column label="退货数量"
                               prop="returnQuantity"
@@ -268,27 +278,27 @@
                            placeholder="请输入退货数量" />
                </template>
              </el-table-column>
              <el-table-column label="库存预警数量"
              <!-- <el-table-column label="库存预警数量"
                               prop="warnNum"
                               width="120"
                               show-overflow-tooltip />
              <el-table-column label="税率(%)"
                               prop="taxRate"
                               width="80" />
                               width="80" /> -->
              <el-table-column label="含税单价(元)"
                               prop="taxInclusiveUnitPrice"
                               :formatter="formattedNumber"
                               width="150" />
                               width="120" />
              <el-table-column label="退货总价(元)"
                               prop="taxInclusiveTotalPrice"
                               width="180">
                               width="120">
                <template #default="scope">
                  {{ formatAmount(getReturnTotal(scope.row)) || '--' }}
                </template>
              </el-table-column>
              <el-table-column label="是否质检"
                               prop="isChecked"
                               width="150">
                               width="100">
                <template #default="scope">
                  <el-tag :type="scope.row.isChecked ? 'success' : 'info'">
                    {{ scope.row.isChecked ? '是' : '否' }}
@@ -311,6 +321,7 @@
                </template>
              </el-table-column>
            </el-table>
            </div>
          </div>
        <div class="section-title">
@@ -408,9 +419,6 @@
import {getOptions, purchaseList} from "@/api/procurementManagement/procurementLedger.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
const ProductList = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/ProductList.vue"));
  import {
    productList,
  } from "@/api/procurementManagement/procurementLedger.js";
const props = defineProps({
  visible: {
    type: Boolean,
@@ -553,7 +561,7 @@
}
const getReturnQtyMax = (row) => {
  const max = Number(row?.availableQuality)
  const max = Number(row?.unQuantity)
  if (Number.isNaN(max) || max < 0) {
    return 0
  }
@@ -568,17 +576,17 @@
  return proxy.summarizeTable(
      param,
      [
        "quantity",
        "availableQuality",
        "stockInNum",
        "unQuantity",
        "returnQuantity",
        "taxInclusiveUnitPrice",
        "taxInclusiveTotalPrice",
        "taxExclusiveTotalPrice",
      ],
      {
        quantity: { noDecimal: true }, // 不保留小数
        stockInNum: { noDecimal: true }, // 不保留小数
        returnQuantity: { noDecimal: true }, // 不保留小数
        availableQuality: { noDecimal: true }, // 不保留小数
        unQuantity: { noDecimal: true }, // 不保留小数
      }
  );
};
@@ -660,20 +668,10 @@
  }
}
// 处理改变采购台账数据
const handleChangePurchaseLedgerId = async () => {
// 处理改变采购台账数据(不请求接口回显产品,产品仅在「添加产品」弹窗勾选后写入)
const handleChangePurchaseLedgerId = () => {
  resetFeeInfo()
  if (!formState.value.purchaseLedgerId) {
    formState.value.purchaseReturnOrderProductsDtos = []
    return
  }
  const res = await productList({ salesLedgerId: formState.value.purchaseLedgerId, type: 2 });
  formState.value.purchaseReturnOrderProductsDtos = res.data.map(item => ({
    ...item,
    returnQuantity: undefined,
    taxInclusiveTotalPrice: 0,
    salesLedgerProductId: item.id,
  }))
  syncTotalAmount()
}
@@ -691,7 +689,7 @@
    ...item,
    returnQuantity: undefined,
    taxInclusiveTotalPrice: 0,
    salesLedgerProductId: item.id,
    salesLedgerProductId: item.salesLedgerProductId ?? item.id,
  }));
  formState.value.purchaseReturnOrderProductsDtos.push(...newProducts);
  syncTotalAmount()
@@ -717,7 +715,7 @@
  // 逐行校验退货数量:任意一行未填/非法/超限都不允许提交
  const invalidRowIndex = productList.findIndex((item) => {
    const qty = Number(item.returnQuantity)
    const maxQty = Number(item.availableQuality)
    const maxQty = Number(item.unQuantity)
    if (item.returnQuantity === null || item.returnQuantity === undefined || item.returnQuantity === "") {
      return true
@@ -738,7 +736,15 @@
  proxy.$refs["formRef"].validate(valid => {
    if (valid) {
      createPurchaseReturnOrder(formState.value).then(res => {
      console.log(productList)
      const submitPayload = {
        ...formState.value,
        purchaseReturnOrderProductsDtos: productList.map((row) => ({
          ...row,
          stockInRecordId: row.id,
        })),
      }
      createPurchaseReturnOrder(submitPayload).then(res => {
        // 关闭模态框
        isShow.value = false;
        // 告知父组件已完成
@@ -785,4 +791,13 @@
  border-radius: 50%;
  margin-right: 8px;
}
.product-table-scroll {
  width: 100%;
  overflow-x: auto;
}
.product-table-inner {
  min-width: 1280px;
}
</style>
src/views/procurementManagement/purchaseReturnOrder/ProductList.vue
@@ -6,9 +6,10 @@
        width="1200"
        @close="closeModal"
    >
      <div class="table_list">
      <div class="table_list" v-loading="tableLoading">
        <el-table :data="tableData"
                  border
                  row-key="id"
                  @selection-change="handleChangeSelection">
          <el-table-column align="center"
                           type="selection"
@@ -17,6 +18,12 @@
                           label="序号"
                           type="index"
                           width="60" />
                           <el-table-column label="入库单号"
                               prop="inboundBatches"
                               width="150" />
              <el-table-column label="批次号"
                               prop="batchNo"
                               width="150" />
          <el-table-column label="产品大类"
                           prop="productCategory" />
          <el-table-column label="规格型号"
@@ -25,27 +32,33 @@
                           prop="unit"
                           width="70" />
          <el-table-column label="数量"
                           prop="quantity"
                           prop="stockInNum"
                           width="70" />
          <el-table-column label="库存预警数量"
          <el-table-column label="可退货数量"
                           prop="unQuantity"
                           width="130" />
          <el-table-column label="已退货数量"
                           prop="totalReturnNum"
                           width="130" />
          <!-- <el-table-column label="库存预警数量"
                           prop="warnNum"
                           width="120"
                           show-overflow-tooltip />
          <el-table-column label="税率(%)"
                           prop="taxRate"
                           width="80" />
                           width="80" /> -->
          <el-table-column label="含税单价(元)"
                           prop="taxInclusiveUnitPrice"
                           :formatter="formattedNumber"
                           width="150" />
          <el-table-column label="含税总价(元)"
          <!-- <el-table-column label="含税总价(元)"
                           prop="taxInclusiveTotalPrice"
                           :formatter="formattedNumber"
                           width="150" />
          <el-table-column label="不含税总价(元)"
                           prop="taxExclusiveTotalPrice"
                           :formatter="formattedNumber"
                           width="150" />
                           width="150" /> -->
          <el-table-column label="是否质检"
                           prop="isChecked"
                           width="150">
@@ -56,8 +69,6 @@
            </template>
          </el-table-column>
        </el-table>
        <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
                    :page="page.current" :limit="page.size" @pagination="paginationChange" />
      </div>
      <template #footer>
@@ -71,8 +82,8 @@
</template>
<script setup>
import {computed, reactive, ref, onMounted} from "vue";
import {productList} from "@/api/procurementManagement/procurementLedger.js";
import {computed, ref, onMounted} from "vue";
import {getPurchaseReturnOrderByPurchaseLedgerId} from "@/api/procurementManagement/purchase_return_order.js";
import {ElMessage} from "element-plus";
const props = defineProps({
@@ -82,7 +93,7 @@
  },
  purchaseLedgerId: {
    type: Number,
    type: [Number, String],
    required: true,
  }
});
@@ -101,31 +112,50 @@
const tableData = ref([])
const selectedRows = ref([])
const tableLoading = ref(false)
const page = reactive({
  current: 1,
  size: 100,
})
const total = ref(0)
const formattedNumber = (row, column, cellValue) => {
  return parseFloat(cellValue).toFixed(2);
};
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList()
}
const handleChangeSelection = (val) => {
  selectedRows.value = val;
}
/** 与 New.vue 中采购台账变更时解析 getByPurchaseLedgerId 的规则一致 */
const parseProductRowsFromLedgerResponse = (res) => {
  const payload = res?.data
  let list = []
  if (Array.isArray(payload)) {
    list = payload
  } else if (payload && typeof payload === 'object') {
    const nested =
      payload.purchaseReturnOrderProductsDtos ||
      payload.purchaseReturnOrderProductsDetailVoList
    list = Array.isArray(nested) ? nested : []
    if (list.length && list[0]?.salesLedgerProduct) {
      list = list.map((item) => ({ ...item, ...item.salesLedgerProduct }))
    }
  }
  return list
}
const fetchData = () => {
  tableLoading.value = true;
  productList({salesLedgerId: props.purchaseLedgerId, type: 2}).then((res) => {
    tableData.value = res.data;
  }).finally(() => {
    tableLoading.value = false;
  if (props.purchaseLedgerId === undefined || props.purchaseLedgerId === null || props.purchaseLedgerId === '') {
    tableData.value = []
    return
  }
  tableLoading.value = true
  getPurchaseReturnOrderByPurchaseLedgerId({
    purchaseLedgerId: props.purchaseLedgerId,
  })
    .then((res) => {
      const list = parseProductRowsFromLedgerResponse(res)
      tableData.value = list
    })
    .catch(() => {
      tableData.value = []
    })
    .finally(() => {
      tableLoading.value = false
  })
}
src/views/procurementManagement/purchaseReturnOrder/index.vue
@@ -1,24 +1,26 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <el-form :model="searchForm"
               :inline="true">
      <el-form :model="searchForm" :inline="true">
        <el-form-item label="退料单号:">
          <el-input v-model="searchForm.no"
          <el-input
            v-model="searchForm.no"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    @change="handleQuery" />
            @change="handleQuery"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary"
                     @click="handleQuery"> 搜索 </el-button>
          <el-button type="primary" @click="handleQuery"> 搜索 </el-button>
        </el-form-item>
      </el-form>
      <div>
        <el-button type="primary" @click="isShowNewModal = true">新增</el-button>
        <el-button type="primary" @click="isShowNewModal = true"
          >新增</el-button
        >
      </div>
    </div>
@@ -35,14 +37,25 @@
        @pagination="paginationChange"
      >
        <template #operation="{ row }">
          <el-button link type="primary" size="small" style="color: #67C23A" @click="handleDetail(row)">详情</el-button>
          <el-button link size="small" @click="handleDelete(row)">删除</el-button>
          <el-button
            link
            type="primary"
            size="small"
            style="color: #67c23a"
            @click="handleDetail(row)"
            >详情</el-button
          >
          <el-button link size="small" @click="handleDelete(row)"
            >删除</el-button
          >
        </template>
      </PIMTable>
    </div>
    <new v-if="isShowNewModal"
    <new
      v-if="isShowNewModal"
         v-model:visible="isShowNewModal"
         @completed="handleQuery" />
      @completed="handleQuery"
    />
    <el-dialog
      v-model="detailVisible"
@@ -52,21 +65,51 @@
    >
      <div v-loading="detailLoading">
        <el-descriptions :column="3" border>
          <el-descriptions-item label="退料单号">{{ detailData.no || '--' }}</el-descriptions-item>
          <el-descriptions-item label="退货方式">{{ getReturnTypeLabel(detailData.returnType) }}</el-descriptions-item>
          <el-descriptions-item label="供应商名称">{{ detailData.supplierName || '--' }}</el-descriptions-item>
          <el-descriptions-item label="项目阶段">{{ getProjectPhaseLabel(detailData.projectPhase) }}</el-descriptions-item>
          <el-descriptions-item label="关联单号">{{ detailData.purchaseContractNumber || '--' }}</el-descriptions-item>
          <el-descriptions-item label="制作日期">{{ detailData.preparedAt || '--' }}</el-descriptions-item>
          <el-descriptions-item label="制单人">{{ detailData.preparedUserName || '--' }}</el-descriptions-item>
          <el-descriptions-item label="退料人">{{ detailData.returnUserName || '--' }}</el-descriptions-item>
          <el-descriptions-item label="整单折扣额">{{ formatAmount(detailData.totalDiscountAmount) }}</el-descriptions-item>
          <el-descriptions-item label="整单折扣率">{{ detailData.totalDiscountRate ?? '--' }}</el-descriptions-item>
          <el-descriptions-item label="成交金额">{{ formatAmount(detailData.totalAmount) }}</el-descriptions-item>
          <el-descriptions-item label="创建人">{{ detailData.createUserName || '--' }}</el-descriptions-item>
          <el-descriptions-item label="创建时间">{{ detailData.createTime || '--' }}</el-descriptions-item>
          <el-descriptions-item label="最近更新时间">{{ detailData.updateTime || '--' }}</el-descriptions-item>
          <el-descriptions-item label="备注" :span="3">{{ detailData.remark || '--' }}</el-descriptions-item>
          <el-descriptions-item label="退料单号">{{
            detailData.no || "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="退货方式">{{
            getReturnTypeLabel(detailData.returnType)
          }}</el-descriptions-item>
          <el-descriptions-item label="供应商名称">{{
            detailData.supplierName || "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="项目阶段">{{
            getProjectPhaseLabel(detailData.projectPhase)
          }}</el-descriptions-item>
          <el-descriptions-item label="关联的采购订单号">{{
            detailData.purchaseContractNumber || "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="制作日期">{{
            detailData.preparedAt || "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="制单人">{{
            detailData.preparedUserName || "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="退料人">{{
            detailData.returnUserName || "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="整单折扣额">{{
            formatAmount(detailData.totalDiscountAmount)
          }}</el-descriptions-item>
          <el-descriptions-item label="整单折扣率">{{
            detailData.totalDiscountRate ?? "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="成交金额">{{
            formatAmount(detailData.totalAmount)
          }}</el-descriptions-item>
          <el-descriptions-item label="创建人">{{
            detailData.createUserName || "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="创建时间">{{
            detailData.createTime || "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="最近更新时间">{{
            detailData.updateTime || "--"
          }}</el-descriptions-item>
          <el-descriptions-item label="备注" :span="3">{{
            detailData.remark || "--"
          }}</el-descriptions-item>
        </el-descriptions>
        <el-divider content-position="left">产品列表</el-divider>
@@ -77,27 +120,72 @@
          max-height="420"
          style="width: 100%"
        >
          <el-table-column align="center" label="序号" type="index" width="60" />
          <el-table-column label="产品大类" prop="productCategory" min-width="120" show-overflow-tooltip />
          <el-table-column label="规格型号" prop="specificationModel" min-width="140" show-overflow-tooltip />
          <el-table-column
            align="center"
            label="序号"
            type="index"
            width="60"
          />
          <el-table-column label="入库单号" prop="inboundBatches" width="150" />
          <el-table-column label="批次号" prop="batchNo" width="150" />
          <el-table-column
            label="产品大类"
            prop="productCategory"
            min-width="120"
            show-overflow-tooltip
          />
          <el-table-column
            label="规格型号"
            prop="specificationModel"
            min-width="140"
            show-overflow-tooltip
          />
          <el-table-column label="单位" prop="unit" width="80" />
          <el-table-column label="数量" prop="quantity" width="80" />
          <el-table-column label="退货数量" prop="returnQuantity" width="100" />
          <el-table-column label="库存预警数量" prop="warnNum" width="120" />
          <el-table-column label="税率(%)" prop="taxRate" width="90" />
          <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" width="130">
            <template #default="scope">{{ formatAmount(scope.row.taxInclusiveUnitPrice) }}</template>
          <el-table-column label="数量" prop="stockInNum" width="80" />
          <el-table-column label="可退货数量"
                           prop="unQuantity"
                           width="100" />
          <el-table-column label="已退货数量"
                           prop="totalReturnNum"
                           width="100" />
          <!-- <el-table-column label="库存预警数量" prop="warnNum" width="120" /> -->
          <!-- <el-table-column label="税率(%)" prop="taxRate" width="90" /> -->
          <el-table-column
            label="含税单价(元)"
            prop="taxInclusiveUnitPrice"
            width="130"
          >
            <template #default="scope">{{
              formatAmount(scope.row.taxInclusiveUnitPrice)
            }}</template>
          </el-table-column>
          <el-table-column label="退货总价(元)" prop="taxInclusiveTotalPrice" width="130">
            <template #default="scope">{{ formatAmount(scope.row.taxInclusiveTotalPrice) }}</template>
          <!-- <el-table-column
            label="退货总价(元)"
            prop="taxInclusiveTotalPrice"
            width="130"
          >
            <template #default="scope">{{
              formatAmount(scope.row.taxInclusiveTotalPrice)
            }}</template>
          </el-table-column>
          <el-table-column label="不退货总价(元)" prop="taxExclusiveTotalPrice" width="140">
            <template #default="scope">{{ formatAmount(scope.row.taxExclusiveTotalPrice) }}</template>
          </el-table-column>
          <el-table-column label="是否质检" prop="isChecked" width="100" align="center">
          <el-table-column
            label="不退货总价(元)"
            prop="taxExclusiveTotalPrice"
            width="140"
          >
            <template #default="scope">{{
              formatAmount(scope.row.taxExclusiveTotalPrice)
            }}</template>
          </el-table-column> -->
          <el-table-column
            label="是否质检"
            prop="isChecked"
            width="100"
            align="center"
          >
            <template #default="scope">
              <el-tag :type="scope.row.isChecked ? 'success' : 'info'">
                {{ scope.row.isChecked ? '是' : '否' }}
                {{ scope.row.isChecked ? "是" : "否" }}
              </el-tag>
            </template>
          </el-table-column>
@@ -111,111 +199,127 @@
</template>
<script setup>
import PIMTable from '@/components/PIMTable/PIMTable.vue'
import { ref, reactive, toRefs, onMounted, defineAsyncComponent, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
import {findPurchaseReturnOrderListPage, getPurchaseReturnOrderDetail, deletePurchaseReturnOrder} from "@/api/procurementManagement/purchase_return_order.js";
const New = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/New.vue"));
const tableData = ref([])
const selectedRows = ref([])
const tableLoading = ref(false)
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import {
  ref,
  reactive,
  toRefs,
  onMounted,
  defineAsyncComponent,
  getCurrentInstance,
} from "vue";
const { proxy } = getCurrentInstance();
import {
  findPurchaseReturnOrderListPage,
  getPurchaseReturnOrderDetail,
  deletePurchaseReturnOrder,
} from "@/api/procurementManagement/purchase_return_order.js";
const New = defineAsyncComponent(() =>
  import("@/views/procurementManagement/purchaseReturnOrder/New.vue")
);
const tableData = ref([]);
const selectedRows = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
  total: 0,
})
const detailVisible = ref(false)
const detailLoading = ref(false)
const detailData = ref({})
const detailProducts = ref([])
});
const detailVisible = ref(false);
const detailLoading = ref(false);
const detailData = ref({});
const detailProducts = ref([]);
// 是否显示新增弹框
const isShowNewModal = ref(false)
const isShowNewModal = ref(false);
const returnTypeOptions = [
  { label: '退货退款', value: 0 },
  { label: '拒收', value: 1 },
]
  { label: "退货退款", value: 0 },
  { label: "拒收", value: 1 },
];
const projectPhaseOptions = [
  { label: '立项', value: 0 },
  { label: '设计', value: 1 },
  { label: '采购', value: 2 },
  { label: '生产', value: 3 },
  { label: '出货', value: 4 },
]
  { label: "立项", value: 0 },
  { label: "设计", value: 1 },
  { label: "采购", value: 2 },
  { label: "生产", value: 3 },
  { label: "出货", value: 4 },
];
const tableColumn = ref([
  {
    label: '退料单号',
    prop: 'no',
    label: "退料单号",
    prop: "no",
  },
  {
    label: '退货方式',
    prop: 'returnType',
    formatData: (val) => returnTypeOptions.find(item => item.value === val)?.label || '--',
    label: "退货方式",
    prop: "returnType",
    formatData: (val) =>
      returnTypeOptions.find((item) => item.value === val)?.label || "--",
  },
  {
    label: '供应商名称',
    prop: 'supplierName',
    label: "供应商名称",
    prop: "supplierName",
    width: 180,
  },
  {
    label: '项目阶段',
    prop: 'projectPhase',
    label: "项目阶段",
    prop: "projectPhase",
    width: 100,
    formatData: (val) => projectPhaseOptions.find(item => String(item.value) === String(val))?.label || '--',
    formatData: (val) =>
      projectPhaseOptions.find((item) => String(item.value) === String(val))
        ?.label || "--",
  },
  {
    label: '关联单号',
    prop: 'purchaseContractNumber',
    label: "关联的采购订单号",
    prop: "purchaseContractNumber",
    width: 160,
  },
  {
    label: '制作日期',
    prop: 'preparedAt',
    label: "制作日期",
    prop: "preparedAt",
    width: 130,
  },
  {
    label: '制单人',
    prop: 'preparedUserName',
    label: "制单人",
    prop: "preparedUserName",
    width: 110,
  },
  {
    label: '退料人',
    prop: 'returnUserName',
    label: "退料人",
    prop: "returnUserName",
    width: 110,
  },
  {
    label: '整单折扣额',
    prop: 'totalDiscountAmount',
    label: "整单折扣额",
    prop: "totalDiscountAmount",
    width: 120,
  },
  {
    label: '整单折扣率',
    prop: 'totalDiscountRate',
    label: "整单折扣率",
    prop: "totalDiscountRate",
    width: 120,
  },
  {
    label: '成交金额',
    prop: 'totalAmount',
    label: "成交金额",
    prop: "totalAmount",
    width: 120,
  },
  {
    label: '创建人',
    prop: 'createUserName',
    label: "创建人",
    prop: "createUserName",
    width: 110,
  },
  {
    label: '创建时间',
    prop: 'createTime',
    label: "创建时间",
    prop: "createTime",
    width: 170,
  },
  {
    label: '最近更新时间',
    prop: 'updateTime',
    label: "最近更新时间",
    prop: "updateTime",
    width: 170,
  },
  {
    label: '备注',
    prop: 'remark',
    label: "备注",
    prop: "remark",
    width: 180,
  },
  {
@@ -228,117 +332,135 @@
      {
                name: "详情",
                type: "text",
                clickFun: row => {handleDetail(row);},
        clickFun: (row) => {
          handleDetail(row);
        },
            },
      {
        name: "删除",
        clickFun: row => {handleDelete(row)},
        clickFun: (row) => {
          handleDelete(row);
        },
      },
  ],
  },
])
]);
const data = reactive({
  searchForm: {
    no: '',
  }
})
const { searchForm } = toRefs(data)
    no: "",
  },
});
const { searchForm } = toRefs(data);
// 查询列表
/** 搜索按钮操作 */
const handleQuery = () => {
  page.current = 1
  getList()
}
  page.current = 1;
  getList();
};
// 删除操作
const handleDelete = (row) => {
  console.log('删除行数据:', row)
  proxy?.$modal?.confirm('确定要删除吗?删除将无法恢复').then(() => {
  console.log("删除行数据:", row);
  proxy?.$modal
    ?.confirm("确定要删除吗?删除将无法恢复")
    .then(() => {
    // 这里调用删除接口,传入 row.id
    deletePurchaseReturnOrder(row.id).then(() => {
      deletePurchaseReturnOrder(row.id)
        .then(() => {
      proxy?.$modal?.msgSuccess?.("删除成功");
      getList()
    }).catch(() => {
      proxy?.$modal?.msgError?.('删除失败')
          getList();
    })
  }).catch(() => {
        .catch(() => {
          proxy?.$modal?.msgError?.("删除失败");
        });
    })
    .catch(() => {
    // 取消删除
    proxy?.$modal?.msgInfo?.('已取消删除')
  })
}
      proxy?.$modal?.msgInfo?.("已取消删除");
    });
};
// 查看详情
const handleDetail = (row) => {
  if (!row?.id) {
    proxy?.$modal?.msgWarning?.('未获取到单据ID')
    return
    proxy?.$modal?.msgWarning?.("未获取到单据ID");
    return;
  }
  detailVisible.value = true
  detailLoading.value = true
  getPurchaseReturnOrderDetail(row.id).then(res => {
    const payload = res?.data || {}
    detailData.value = payload
  detailVisible.value = true;
  detailLoading.value = true;
  getPurchaseReturnOrderDetail(row.id)
    .then((res) => {
      const payload = res?.data || {};
      detailData.value = payload;
    // 拼接连个对象成一个对象,方便展示 item 和 item.salesLedgerProduct 里的字段
    detailProducts.value =
      payload.purchaseReturnOrderProductsDetailVoList.map(item => ({ ...item, ...item.salesLedgerProduct })) ||
      []
  }).catch(() => {
    proxy?.$modal?.msgError?.('获取详情失败')
  }).finally(() => {
    detailLoading.value = false
        payload.purchaseReturnOrderProductsDetailVoList.map((item) => ({
          ...item,
          ...item.salesLedgerProduct,
        })) || [];
  })
}
    .catch(() => {
      proxy?.$modal?.msgError?.("获取详情失败");
    })
    .finally(() => {
      detailLoading.value = false;
    });
};
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList()
}
  getList();
};
const getList = () => {
  tableLoading.value = true
  findPurchaseReturnOrderListPage({ ...searchForm.value, ...page }).then(res => {
    tableLoading.value = false
    tableData.value = res.data.records
    page.total = res.data.total
  }).catch(() => {
    tableLoading.value = false
  tableLoading.value = true;
  findPurchaseReturnOrderListPage({ ...searchForm.value, ...page })
    .then((res) => {
      tableLoading.value = false;
      tableData.value = res.data.records;
      page.total = res.data.total;
  })
}
    .catch(() => {
      tableLoading.value = false;
    });
};
// 表格选择数据
const handleSelectionChange = (selection) => {
  // 过滤掉子数据
  selectedRows.value = selection.filter(item => item.id);
}
  selectedRows.value = selection.filter((item) => item.id);
};
const getReturnTypeLabel = (value) => {
  return returnTypeOptions.find(item => String(item.value) === String(value))?.label || '--'
}
  return (
    returnTypeOptions.find((item) => String(item.value) === String(value))
      ?.label || "--"
  );
};
const getProjectPhaseLabel = (value) => {
  return projectPhaseOptions.find(item => String(item.value) === String(value))?.label || '--'
}
  return (
    projectPhaseOptions.find((item) => String(item.value) === String(value))
      ?.label || "--"
  );
};
const formatAmount = (value) => {
  if (value === null || value === undefined || value === '') {
    return '--'
  if (value === null || value === undefined || value === "") {
    return "--";
  }
  const num = Number(value)
  const num = Number(value);
  if (Number.isNaN(num)) {
    return value
    return value;
  }
  return num.toFixed(2)
}
  return num.toFixed(2);
};
onMounted(() => {
  getList()
})
  getList();
});
</script>
<style scoped>
.table_list {
src/views/salesManagement/returnOrder/components/detailDia.vue
@@ -10,8 +10,8 @@
        <el-descriptions-item label="客户名称">{{ detail.customerName }}</el-descriptions-item>
        <el-descriptions-item label="销售单号">{{ detail.salesContractNo }}</el-descriptions-item>
        <el-descriptions-item label="业务员">{{ detail.salesman }}</el-descriptions-item>
        <el-descriptions-item label="关联出库单号">{{ detail.shippingNo }}</el-descriptions-item>
        <el-descriptions-item label="项目名称">{{ detail.projectName }}</el-descriptions-item>
        <el-descriptions-item label="关联发货单号">{{ detail.shippingNo }}</el-descriptions-item>
        <!-- <el-descriptions-item label="项目名称">{{ detail.projectName }}</el-descriptions-item> -->
        <el-descriptions-item label="制单人">{{ detail.maker }}</el-descriptions-item>
        <el-descriptions-item label="制单时间">{{ detail.makeTime }}</el-descriptions-item>
        <el-descriptions-item label="退货原因">{{ detail.returnReason }}</el-descriptions-item>
@@ -42,10 +42,12 @@
const availableProducts = ref([]);
const tableColumn = [
  {align: "center", label: "产品大类", prop: "productCategory"},
  {align: "center", label: "规格型号", prop: "specificationModel"},
  {align: "center", label: "出库单号", prop: "outboundBatches"},
  {align: "center", label: "批次号", prop: "batchNo"},
  {align: "center", label: "产品大类", prop: "productName"},
  {align: "center", label: "规格型号", prop: "model"},
  {align: "center", label: "单位", prop: "unit", width: 80},
  {align: "center", label: "总数量", prop: "quantity", width: 120},
  {align: "center", label: "总数量", prop: "stockOutNum", width: 120},
  {align: "center", label: "已退货数量", prop: "totalReturnNum", width: 120},
  {align: "center", label: "未退货数量", prop: "unQuantity", width: 120},
  {align: "center", label: "退货数量", prop: "returnQuantity", width: 120},
src/views/salesManagement/returnOrder/components/formDia.vue
@@ -145,10 +145,12 @@
        row-key="id"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" prop="outboundBatches" label="出库单号" />
        <el-table-column align="center" prop="batchNo" label="批次号" />
        <el-table-column align="center" prop="productCategory" label="产品大类" />
        <el-table-column align="center" prop="specificationModel" label="规格型号" />
        <el-table-column align="center" prop="unit" label="单位" />
        <el-table-column align="center" prop="quantity" label="总数量" />
        <el-table-column align="center" prop="stockOutNum" label="总数量" />
        <el-table-column align="center" prop="unQuantity" label="未退货数量" />
        <el-table-column align="center" label="已退货数量">
          <template #default="{ row }">{{ calcAlreadyReturned(row) }}</template>
@@ -208,17 +210,19 @@
const { form, rules } = toRefs(data);
const calcAlreadyReturned = (row) => {
  const total = Number(row?.quantity ?? row?.totalQuantity ?? row?.totalReturnNum ?? 0);
  const total = Number(row?.stockOutNum ?? row?.totalQuantity ?? row?.totalReturnNum ?? 0);
  const un = Number(row?.unQuantity ?? 0);
  if (!Number.isFinite(total) || !Number.isFinite(un)) return 0;
  return Math.max(total - un, 0);
};
const tableColumn = ref([
  {align: "center", label: "出库单号", prop: "outboundBatches" },
  {align: "center", label: "批次号", prop: "batchNo" },
  {align: "center", label: "产品大类", prop: "productCategory" },
  {align: "center", label: "规格型号", prop: "specificationModel" },
  {align: "center", label: "单位", prop: "unit", width: 80 },
  {align: "center", label: "总数量", prop: "quantity", width: 120 },
  {align: "center", label: "总数量", prop: "stockOutNum", width: 120 },
  {align: "center", label: "已退货数量", prop: "totalReturnNum", width: 120 },
  {align: "center", label: "未退货数量", prop: "unQuantity", width: 120 },
  {align: "center", label: "退货数量", prop: "returnQuantity", dataType: "slot", slot: "returnQuantity", width: 120 },
@@ -320,7 +324,7 @@
  proxy.$refs["formRef"].validate(valid => {
    if (!valid) return;
    const returnSaleProducts = (tableData.value || []).map(el => ({
      returnSaleLedgerProductId: el.returnSaleLedgerProductId ?? el.id,
      stockOutRecordId: el.returnSaleLedgerProductId ?? el.id,
      productModelId: el.productModelId,
      unit: el.unit,
      num: Number(el.num ?? el.returnQuantity ?? 0),
@@ -419,8 +423,8 @@
    // If backend returns project info, set it
    if (res.data.projectId) form.value.projectId = res.data.projectId;
    
    // Store available products for selection
    availableProducts.value = res.data.productDtoData || [];
    availableProducts.value =
      res.data.shippingProductVoList || [];
    if (clearTable) tableData.value = [];
  }
};
@@ -457,9 +461,9 @@
};
const calculateRowAmount = (row) => {
  const quantity = Number(row.returnQuantity || 0);
  const stockOutNum = Number(row.returnQuantity || 0);
  const price = Number(row.price || 0);
  row.amount = (quantity * price).toFixed(2);
  row.amount = (stockOutNum * price).toFixed(2);
};
const calculateTotalRefund = () => {
@@ -514,7 +518,7 @@
        productName: product.productName,
        specificationModel: product.specificationModel,
        unit: product.unit,
        quantity: product.quantity,
        stockOutNum: product.stockOutNum,
        totalReturnNum: product.totalReturnNum,
        unQuantity: product.unQuantity
      });
src/views/salesManagement/returnOrder/index.vue
@@ -11,8 +11,8 @@
                <el-form-item label="销售单号">
                    <el-input v-model="searchForm.salesContractNo" placeholder="销售单号" clearable />
                </el-form-item>
                <el-form-item label="关联出库单号">
                    <el-input v-model="searchForm.shippingNo" placeholder="关联出库单号" clearable />
                <el-form-item label="关联发货单号">
                    <el-input v-model="searchForm.shippingNo" placeholder="关联发货单号" clearable />
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="handleQuery">搜索</el-button>
@@ -112,22 +112,22 @@
]);
const defaultColumns = [
  { label: "退货单号", prop: "returnNo", width: 160 },
  { label: "单据状态", prop: "status", width: 90, dataType: "slot", slot: "status" },
  { label: "制单时间", prop: "makeTime", width: 170 },
  { label: "客户名称", prop: "customerName", width: 220 },
  { label: "销售单号", prop: "salesContractNo", width: 160 },
  { label: "业务员", prop: "salesman", width: 120 },
  { label: "关联出库单号", prop: "shippingNo", width: 170 },
  { label: "项目名称", prop: "projectName", width: 180 },
  { label: "制单人", prop: "maker", width: 120 },
  { label: "退货单号", prop: "returnNo", minWidth: 160 },
  { label: "单据状态", prop: "status", minWidth: 90, dataType: "slot", slot: "status" },
  { label: "制单时间", prop: "makeTime", minWidth: 170 },
  { label: "客户名称", prop: "customerName", minWidth: 220 },
  { label: "销售单号", prop: "salesContractNo", minWidth: 160 },
  { label: "业务员", prop: "salesman", minWidth: 120 },
  { label: "关联发货单号", prop: "shippingNo", minWidth: 170 },
  { label: "项目名称", prop: "projectName", minWidth: 180 },
  { label: "制单人", prop: "maker", minWidth: 120 },
  {
    label: "操作",
    prop: "operation",
    dataType: "action",
    align: "center",
    fixed: "right",
    width: 240,
    minWidth: 240,
    operation: [
      { name: "编辑", disabled: (row) => row.status !== 0, type: "text", clickFun: (row) => openForm("edit", row) },
      { name: "退款处理", disabled: (row) => row.status !== 0, type: "text", clickFun: (row) => handleRowHandle(row) },