ZN
2026-03-21 f3cec0341563c2c0dd4f5df609d0689c6c450bfc
src/views/procurementManagement/purchaseReturnOrder/index.vue
@@ -23,37 +23,97 @@
    </div>
    <div class="table_list">
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" :row-key="row => row.id" style="width: 100%" height="calc(100vh - 18.5em)">
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="退料单号" prop="no" show-overflow-tooltip />
        <el-table-column label="退货方式" prop="returnType" show-overflow-tooltip />
        <el-table-column label="供应商名称" prop="supplierName" show-overflow-tooltip />
        <el-table-column label="关联单号" prop="purchaseContractNumber" show-overflow-tooltip />
        <el-table-column label="退料人" prop="returnUserName" show-overflow-tooltip />
        <el-table-column label="备注" prop="remark"  show-overflow-tooltip />
        <el-table-column label="创建人" prop="createUserName"  show-overflow-tooltip />
        <el-table-column label="创建时间" prop="createTime" show-overflow-tooltip />
        <el-table-column label="最近更新时间" prop="updateTime" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="60" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" style="color: #67C23A">详情</el-button>
          </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" />
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :tableLoading="tableLoading"
        :isSelection="true"
        :page="page"
        :height="'calc(100vh - 18.5em)'"
        @selection-change="handleSelectionChange"
        @pagination="paginationChange"
      >
        <template #operation="{ row }">
          <el-button link type="primary" size="small" style="color: #67C23A" @click="handleDetail(row)">详情</el-button>
        </template>
      </PIMTable>
    </div>
    <new v-if="isShowNewModal"
         v-model:visible="isShowNewModal"
         @completed="handleQuery" />
    <el-dialog
      v-model="detailVisible"
      title="采购退货详情"
      width="1200"
      destroy-on-close
    >
      <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>
        <el-divider content-position="left">产品列表</el-divider>
        <el-table
          :data="detailProducts"
          border
          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 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>
          <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">
            <template #default="scope">
              <el-tag :type="scope.row.isChecked ? 'success' : 'info'">
                {{ scope.row.isChecked ? '是' : '否' }}
              </el-tag>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <template #footer>
        <el-button @click="detailVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
import { ref, reactive, toRefs, onMounted } from 'vue'
import {findPurchaseReturnOrderListPage} from "@/api/procurementManagement/purchase_return_order.js";
import PIMTable from '@/components/PIMTable/PIMTable.vue'
import { ref, reactive, toRefs, onMounted, defineAsyncComponent, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
import {findPurchaseReturnOrderListPage, getPurchaseReturnOrderDetail} from "@/api/procurementManagement/purchase_return_order.js";
const New = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/New.vue"));
const tableData = ref([])
const selectedRows = ref([])
@@ -61,10 +121,111 @@
const page = reactive({
  current: 1,
  size: 100,
  total: 0,
})
const total = ref(0)
const detailVisible = ref(false)
const detailLoading = ref(false)
const detailData = ref({})
const detailProducts = ref([])
// 是否显示新增弹框
const isShowNewModal = ref(false)
const returnTypeOptions = [
  { label: '退货退款', value: 0 },
  { label: '拒收', value: 1 },
]
const projectPhaseOptions = [
  { label: '立项', value: 0 },
  { label: '设计', value: 1 },
  { label: '采购', value: 2 },
  { label: '生产', value: 3 },
  { label: '出货', value: 4 },
]
const tableColumn = ref([
  {
    label: '退料单号',
    prop: 'no',
  },
  {
    label: '退货方式',
    prop: 'returnType',
    formatData: (val) => returnTypeOptions.find(item => item.value === val)?.label || '--',
  },
  {
    label: '供应商名称',
    prop: 'supplierName',
    width: 180,
  },
  {
    label: '项目阶段',
    prop: 'projectPhase',
    width: 100,
    formatData: (val) => projectPhaseOptions.find(item => String(item.value) === String(val))?.label || '--',
  },
  {
    label: '关联单号',
    prop: 'purchaseContractNumber',
    width: 160,
  },
  {
    label: '制作日期',
    prop: 'preparedAt',
    width: 130,
  },
  {
    label: '制单人',
    prop: 'preparedUserName',
    width: 110,
  },
  {
    label: '退料人',
    prop: 'returnUserName',
    width: 110,
  },
  {
    label: '整单折扣额',
    prop: 'totalDiscountAmount',
    width: 120,
  },
  {
    label: '整单折扣率',
    prop: 'totalDiscountRate',
    width: 120,
  },
  {
    label: '成交金额',
    prop: 'totalAmount',
    width: 120,
  },
  {
    label: '创建人',
    prop: 'createUserName',
    width: 110,
  },
  {
    label: '创建时间',
    prop: 'createTime',
    width: 170,
  },
  {
    label: '最近更新时间',
    prop: 'updateTime',
    width: 170,
  },
  {
    label: '备注',
    prop: 'remark',
    width: 180,
  },
  {
    fixed: 'right',
    label: '操作',
    dataType: 'slot',
    slot: 'operation',
    width: 100,
    align: 'center',
  },
])
const data = reactive({
  searchForm: {
    no: '',
@@ -79,6 +240,30 @@
  getList()
}
const handleDetail = (row) => {
  if (!row?.id) {
    proxy?.$modal?.msgWarning('未获取到单据ID')
    return
  }
  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
  })
}
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
@@ -90,7 +275,7 @@
  findPurchaseReturnOrderListPage({ ...searchForm.value, ...page }).then(res => {
    tableLoading.value = false
    tableData.value = res.data.records
    total.value = res.data.total
    page.total = res.data.total
  }).catch(() => {
    tableLoading.value = false
  })
@@ -102,6 +287,25 @@
  selectedRows.value = selection.filter(item => item.id);
}
const getReturnTypeLabel = (value) => {
  return returnTypeOptions.find(item => String(item.value) === String(value))?.label || '--'
}
const getProjectPhaseLabel = (value) => {
  return projectPhaseOptions.find(item => String(item.value) === String(value))?.label || '--'
}
const formatAmount = (value) => {
  if (value === null || value === undefined || value === '') {
    return '--'
  }
  const num = Number(value)
  if (Number.isNaN(num)) {
    return value
  }
  return num.toFixed(2)
}
onMounted(() => {
  getList()
})