gaoluyang
23 小时以前 8b1b73b297451d87e2ebf8c1bcb05c64f108127c
银川
1.销售退货选择销售订单逻辑修改
已修改12个文件
424 ■■■■ 文件已修改
src/api/erp/sale/order/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/components/select-dialog.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/components/select.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/return/modules/form.vue 138 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/return/modules/item-form.vue 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/md/item/components/select-dialog.vue 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/md/item/components/select.vue 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/workorder/modules/form.vue 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/returnsales/data.ts 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/returnsales/modules/form.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/returnsales/modules/line-form.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/wls/returnsales/modules/line-list.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/erp/sale/order/index.ts
@@ -55,6 +55,7 @@
    stockCount?: number; // 库存数量(显示字段)
    needProduction?: number; // 是否需要生产:0-不需要,1-需要
    mpsId?: number; // MPS编号
    batchCode?: string; // 批次号
  }
}
src/views/erp/sale/order/components/select-dialog.vue
@@ -17,6 +17,7 @@
const open = ref(false);
const multiple = ref(true);
const outStatus = ref<number | undefined>(undefined);
const status = ref<number | undefined>(undefined);
const selectedRows = ref<ErpSaleOrderApi.SaleOrder[]>([]);
const preSelectedIds = ref<number[]>([]);
@@ -117,6 +118,7 @@
          return await getSaleOrderPage({
            pageNo: page.currentPage,
            pageSize: page.pageSize,
            outStatus: outStatus.value,
            status: status.value,
            ...formValues,
          });
@@ -149,10 +151,11 @@
/** 打开销售订单选择弹窗 */
async function openModal(
  selectedIds?: number[],
  options?: { multiple?: boolean; status?: number },
  options?: { multiple?: boolean; outStatus?: number; status?: number },
) {
  open.value = true;
  multiple.value = options?.multiple ?? true;
  outStatus.value = options?.outStatus;
  status.value = options?.status;
  preSelectedIds.value = selectedIds || [];
  await nextTick();
src/views/erp/sale/order/components/select.vue
@@ -18,6 +18,7 @@
    allowClear?: boolean;
    disabled?: boolean;
    modelValue?: number;
    outStatus?: number;
    placeholder?: string;
    status?: number;
  }>(),
@@ -25,6 +26,7 @@
    allowClear: true,
    disabled: false,
    modelValue: undefined,
    outStatus: undefined,
    placeholder: '请选择销售订单',
    status: undefined,
  },
@@ -84,7 +86,11 @@
  const selectedIds = (
    props.modelValue === null ? [] : [props.modelValue]
  ) as number[];
  dialogRef.value?.open(selectedIds, { multiple: false, status: props.status });
  dialogRef.value?.open(selectedIds, {
    multiple: false,
    outStatus: props.outStatus,
    status: props.status,
  });
}
function handleSelected(rows: ErpSaleOrderApi.SaleOrder[]) {
src/views/erp/sale/return/modules/form.vue
@@ -13,6 +13,7 @@
import { useVbenForm } from '#/adapter/form';
import { getAccountSimpleList } from '#/api/erp/finance/account';
import { getSaleOrderItemListByOrderId, getSaleOrderPage } from '#/api/erp/sale/order';
import {
  createSaleReturn,
  getSaleReturn,
@@ -48,6 +49,7 @@
});
const formType = ref<FormType>('create'); // 表单类型:'create' | 'edit' | 'detail'
const itemFormRef = ref<InstanceType<typeof ItemForm>>();
const orderItems = ref<ErpSaleOrderApi.SaleOrderItem[]>([]);
const getTitle = computed(() => {
  if (formType.value === 'create') {
@@ -113,7 +115,7 @@
}
/** 选择销售订单 */
function handleUpdateOrder(order: ErpSaleOrderApi.SaleOrder) {
async function handleUpdateOrder(order: ErpSaleOrderApi.SaleOrder) {
  formData.value = {
    ...formData.value,
    orderId: order.id,
@@ -123,16 +125,34 @@
    remark: order.remark!,
    discountPercent: order.discountPercent!,
  };
  // 将订单项设置到退货单项
  order.items!.forEach((item: any) => {
    item.totalCount = item.count;
    item.count = item.totalCount - item.returnCount;
    item.orderItemId = item.id;
    item.id = undefined;
  });
  formData.value.items = order.items!.filter(
    (item) => item.count && item.count > 0,
  ) as ErpSaleReturnApi.SaleReturnItem[];
  // 加载关联销售订单的物料列表
  const items = await getSaleOrderItemListByOrderId(order.id!);
  orderItems.value = items;
  // 将订单项转换为退货单项(仅保留可退货数量 > 0 的项)
  const returnItems: ErpSaleReturnApi.SaleReturnItem[] = [];
  for (const item of items) {
    const returnCount = (item as { returnCount?: number }).returnCount ?? 0;
    const remainingCount = (item.count ?? 0) - returnCount;
    if (remainingCount <= 0) continue;
    returnItems.push({
      orderItemId: item.id,
      productId: item.productId,
      productName: item.productName || '',
      productPrice: item.productPrice || 0,
      productUnitId: item.productUnitId,
      productUnitName: item.productUnitName,
      productBarCode: item.productBarCode,
      totalCount: item.count,
      count: remainingCount,
      taxPercent: item.taxPercent || 0,
      remark: item.remark || '',
      totalProductPrice: 0,
      taxPrice: 0,
      totalPrice: 0,
    });
  }
  formData.value.items = returnItems;
  formApi.setValues(formData.value, false);
}
@@ -171,14 +191,72 @@
  async onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      formData.value = {} as ErpSaleReturnApi.SaleReturn;
      orderItems.value = [];
      return;
    }
    // 加载数据
    const data = modalApi.getData<{ formType: FormType; id?: number }>();
    formType.value = data.formType;
    const modalData = modalApi.getData<{ formType: FormType; id?: number }>();
    formType.value = modalData.formType;
    // 编辑/详情模式:先加载数据,再更新 schema,确保渲染时 orderNo 已就绪
    if (modalData?.id) {
      modalApi.lock();
      try {
        const apiData = await getSaleReturn(modalData.id);
        const raw = apiData as Record<string, unknown>;
        // 提取订单号(尝试多种可能的字段名 / 嵌套结构)
        const getOrderNo = (): string => {
          if (raw.orderNo) return raw.orderNo as string;
          if (raw.salesOrderCode) return raw.salesOrderCode as string;
          if (raw.salesOrderNo) return raw.salesOrderNo as string;
          const so = raw.salesOrder as Record<string, unknown> | undefined;
          if (so?.no) return so.no as string;
          const o = raw.order as Record<string, unknown> | undefined;
          if (o?.no) return o.no as string;
          return '';
        };
        // 提取订单ID(尝试多种可能的字段名 / 嵌套结构)
        const getOrderId = (): number | undefined => {
          if (raw.orderId) return raw.orderId as number;
          if (raw.salesOrderId) return raw.salesOrderId as number;
          const so = raw.salesOrder as Record<string, unknown> | undefined;
          if (so?.id) return so.id as number;
          const o = raw.order as Record<string, unknown> | undefined;
          if (o?.id) return o.id as number;
          return undefined;
        };
        let orderNo = getOrderNo();
        let orderId = getOrderId();
        // 如果有订单号但没有订单ID,通过订单号反查订单ID
        if (orderNo && !orderId) {
          const orderPage = await getSaleOrderPage({
            pageNo: 1,
            pageSize: 1,
            no: orderNo,
          } as Record<string, unknown> as never);
          const list = (orderPage as Record<string, unknown>)?.list as Array<Record<string, unknown>> | undefined;
          if (list?.length) {
            orderId = list[0].id as number;
          }
        }
        formData.value = { ...apiData, orderNo, orderId };
        if (orderId) {
          orderItems.value = await getSaleOrderItemListByOrderId(orderId);
        }
      } finally {
        modalApi.unlock();
      }
    }
    // 数据就绪后再更新 schema 和设置表单值
    formApi.setDisabled(formType.value === 'detail');
    formApi.updateSchema(useFormSchema(formType.value));
    if (!data || !data.id) {
    if (!modalData?.id) {
      // 新增时,默认选中账户
      const accountList = await getAccountSimpleList();
      const defaultAccount = accountList.find((item) => item.defaultStatus);
@@ -187,23 +265,17 @@
      }
      return;
    }
    modalApi.lock();
    try {
      formData.value = await getSaleReturn(data.id);
      // 设置到 values
      await formApi.setValues(formData.value, false);
      if (formData.value?.attachmentList?.length) {
        const blobIds = formData.value.attachmentList.map((item) => ({
          uid: String(item.id),
          name: item.name || '',
          url: item.url || '',
          status: 'done',
          id: item.id,
        }));
        await formApi.setFieldValue('blobIds', blobIds);
      }
    } finally {
      modalApi.unlock();
    await formApi.setValues(formData.value, false);
    if (formData.value?.attachmentList?.length) {
      const blobIds = formData.value.attachmentList.map((item) => ({
        uid: String(item.id),
        name: item.name || '',
        url: item.url || '',
        status: 'done',
        id: item.id,
      }));
      await formApi.setFieldValue('blobIds', blobIds);
    }
  },
});
@@ -224,6 +296,7 @@
          :disabled="formType === 'detail'"
          :discount-percent="formData?.discountPercent ?? 0"
          :other-price="formData?.otherPrice ?? 0"
          :order-items="orderItems"
          @update:items="handleUpdateItems"
          @update:discount-price="handleUpdateDiscountPrice"
          @update:other-price="handleUpdateOtherPrice"
@@ -232,6 +305,7 @@
      </template>
      <template #orderNo>
        <SaleOrderSelect
          :key="formData?.orderNo ?? 'empty'"
          :order-no="formData?.orderNo"
          @update:order="handleUpdateOrder"
        />
src/views/erp/sale/return/modules/item-form.vue
@@ -1,5 +1,6 @@
<script lang="ts" setup>
import type { MdmItemApi } from '#/api/mdm/item';
import type { ErpSaleOrderApi } from '#/api/erp/sale/order';
import type { ErpSaleReturnApi } from '#/api/erp/sale/return';
import { computed, nextTick, onMounted, ref, watch } from 'vue';
@@ -24,6 +25,7 @@
  disabled?: boolean;
  discountPercent?: number;
  otherPrice?: number;
  orderItems?: ErpSaleOrderApi.SaleOrderItem[];
}
const props = withDefaults(defineProps<Props>(), {
@@ -31,6 +33,7 @@
  disabled: false,
  discountPercent: 0,
  otherPrice: 0,
  orderItems: () => [],
});
const emit = defineEmits([
@@ -141,6 +144,57 @@
  emit('update:items', [...tableData.value]);
}
/** 处理新增物料行 */
function handleAdd() {
  const newRow: ErpSaleReturnApi.SaleReturnItem = {
    seq: Date.now(),
    productId: undefined,
    productName: '',
    productPrice: 0,
    productUnitId: undefined,
    productUnitName: '',
    count: 0,
    totalProductPrice: 0,
    taxPercent: 0,
    taxPrice: 0,
    totalPrice: 0,
    remark: '',
  };
  tableData.value.push(newRow);
  emit('update:items', [...tableData.value]);
}
/** 处理产品变更:优先从关联订单物料中填充,兜底从全部物料中查找 */
function handleProductChange(row: ErpSaleReturnApi.SaleReturnItem) {
  // 优先从关联订单的物料中查找
  const orderItem = props.orderItems.find(
    (item) => item.productId === row.productId,
  );
  if (orderItem) {
    row.productName = orderItem.productName;
    row.productPrice = orderItem.productPrice ?? 0;
    row.productUnitId = orderItem.productUnitId;
    row.productUnitName = orderItem.productUnitName;
    row.productBarCode = orderItem.productBarCode;
    row.taxPercent = orderItem.taxPercent ?? 0;
    row.count = row.count || 1;
    handleRowChange(row);
    return;
  }
  // 兜底:从全部物料中查找
  const product = productOptions.value.find((item) => item.id === row.productId);
  if (product) {
    row.productName = product.name || '';
    row.productPrice = product.salesPrice ?? 0;
    row.productUnitId = product.unitMeasureId;
    row.productUnitName = product.unitMeasureName;
    row.productBarCode = product.barCode;
    row.taxPercent = 0;
    row.count = row.count || 1;
    handleRowChange(row);
  }
}
/** 处理仓库变更 */
async function handleWarehouseChange(row: ErpSaleReturnApi.SaleReturnItem) {
  const stockCount = await getWarehouseStockCount({
@@ -177,6 +231,9 @@
  for (let i = 0; i < tableData.value.length; i++) {
    const item = tableData.value[i];
    if (item) {
      if (!item.productId) {
        throw new Error(`第 ${i + 1} 行:产品不能为空`);
      }
      if (!item.warehouseId) {
        throw new Error(`第 ${i + 1} 行:仓库不能为空`);
      }
@@ -215,13 +272,14 @@
    </template>
    <template #productId="{ row }">
      <Select
        disabled
        :disabled="disabled"
        v-model:value="row.productId"
        :options="productOptions"
        :field-names="{ label: 'name', value: 'id' }"
        :options="orderItems?.length ? orderItems : productOptions"
        :field-names="orderItems?.length ? { label: 'productName', value: 'productId' } : { label: 'name', value: 'id' }"
        class="w-full"
        placeholder="请选择产品"
        show-search
        @change="handleProductChange(row)"
      />
    </template>
    <template #count="{ row }">
@@ -291,6 +349,17 @@
          </div>
        </div>
      </div>
      <TableAction
        v-if="!disabled"
        class="mt-2 flex justify-center"
        :actions="[
          {
            label: '添加退货产品',
            type: 'default',
            onClick: handleAdd,
          },
        ]"
      />
    </template>
  </Grid>
</template>
src/views/mes/md/item/components/select-dialog.vue
@@ -26,6 +26,7 @@
  const selectedRows = ref<MesMdItemApi.Item[]>([]); // 已选物料列表
  const selectedItemTypeId = ref<number>(); // 当前筛选分类编号
  const preSelectedIds = ref<number[]>([]); // 预选物料编号列表
  const productIds = ref<number[]>([]); // 限定可选的物料编号列表(为空则不限制)
  const typeTreeRef = ref<InstanceType<typeof MdItemTypeTree>>(); // 物料分类树
  /** 获取当前表格数据 */
@@ -130,13 +131,20 @@
      proxyConfig: {
        ajax: {
          query: async ({ page }, formValues) => {
            return await getItemPage({
            const params: Record<string, unknown> = {
              pageNo: page.currentPage,
              pageSize: page.pageSize,
              ...formValues,
              itemTypeId: selectedItemTypeId.value,
              status: CommonStatusEnum.ENABLE,
            });
            };
            // 限定可选物料范围
            if (productIds.value.length > 0) {
              params.pageSize = 1000;
              params.ids = productIds.value.join(',');
            }
            const result = await getItemPage(params as never);
            return result;
          },
        },
      },
@@ -173,11 +181,12 @@
  /** 打开物料选择弹窗 */
  async function openModal(
    selectedIds?: number[],
    options?: { multiple?: boolean }
    options?: { multiple?: boolean; productIds?: number[] }
  ) {
    open.value = true;
    multiple.value = options?.multiple ?? true;
    preSelectedIds.value = selectedIds || [];
    productIds.value = options?.productIds || [];
    await nextTick();
    gridApi.setGridOptions({
      columns: useItemSelectGridColumns(multiple.value),
src/views/mes/md/item/components/select.vue
@@ -19,12 +19,14 @@
    disabled?: boolean;
    modelValue?: number;
    placeholder?: string;
    productIds?: number[];
  }>(),
  {
    allowClear: true,
    disabled: false,
    modelValue: undefined,
    placeholder: '请选择产品物料',
    productIds: () => [],
  },
);
const emit = defineEmits<{
@@ -86,7 +88,10 @@
  const selectedIds = (
    props.modelValue === null ? [] : [props.modelValue]
  ) as number[];
  dialogRef.value?.open(selectedIds, { multiple: false });
  dialogRef.value?.open(selectedIds, {
    multiple: false,
    productIds: props.productIds,
  });
}
/** 回填选中的物料 */
src/views/mes/pro/workorder/modules/form.vue
@@ -99,19 +99,17 @@
  });
  /** 重新挂载 schema 并按表单态控制底部按钮 */
  const mainActionText = computed(() => {
    if (isConfirm.value) return '确认';
    if (isFinish.value) return '完成';
    return '提交';
  });
  const showMainBtn = computed(() => isEditable.value || isConfirm.value || isFinish.value);
  function applySchema() {
    formApi.setState({ schema: useFormSchema(formType.value, formApi) });
    const showBtn = isEditable.value || isConfirm.value || isFinish.value;
    modalApi.setState({
      showConfirmButton: showBtn,
      confirmText: isConfirm.value || canConfirm.value
        ? '确认'
        : isFinish.value
          ? '完成'
          : isCreateMode.value
            ? '新增'
            : '保存',
    });
    modalApi.setState({ showCancelButton: false, showConfirmButton: false });
  }
  /** 仅保存(不改变状态) */
@@ -353,14 +351,26 @@
      </Tabs>
    </template>
    <template #prepend-footer>
      <Button v-if="canConfirm"
              @click="handleSave">
        保存
      </Button>
      <Button v-if="formType === 'detail' && formData?.id"
              @click="handleBarcode">
        查看条码
      </Button>
      <div class="flex flex-auto items-center">
        <Button v-if="showMainBtn"
                type="primary"
                @click="modalApi.onConfirm()">
          {{ mainActionText }}
        </Button>
      </div>
    </template>
    <template #append-footer>
      <div class="flex gap-2">
        <Button v-if="canConfirm"
                @click="handleSave">
          保存修改
        </Button>
        <Button v-if="formType === 'detail' && formData?.id"
                @click="handleBarcode">
          查看条码
        </Button>
        <Button @click="modalApi.close()">取消</Button>
      </div>
    </template>
  </Modal>
  <BarcodeDetail ref="barcodeDetailRef" />
src/views/wls/returnsales/data.ts
@@ -1,3 +1,4 @@
import type { ErpSaleOrderApi } from '#/api/erp/sale/order';
import type { VbenFormApi, VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MesWmReturnSalesApi } from '#/api/mes/wm/returnsales';
@@ -35,6 +36,7 @@
export function useFormSchema(
  formType: FormType,
  formApi?: VbenFormApi,
  onOrderChange?: (item: Record<string, unknown> | undefined) => void,
): VbenFormSchema[] {
  return [
    {
@@ -100,6 +102,7 @@
      label: '销售订单号',
      component: markRaw(ErpSaleOrderSelect),
      componentProps: {
        outStatus: 3,
        placeholder: '请选择销售订单',
        onChange: (item: any) => {
          if (formApi) {
@@ -108,6 +111,7 @@
              formApi.setFieldValue('clientId', item.customerId);
            }
          }
          onOrderChange?.(item);
        },
      },
      rules: 'selectRequired',
@@ -342,15 +346,31 @@
export function useLineFormSchema(
  clientId?: number,
  salesOrderCode?: string,
  items?: ErpSaleOrderApi.SaleOrderItem[],
  onItemChange?: (item: ErpSaleOrderApi.SaleOrderItem | undefined) => void,
): VbenFormSchema[] {
  const hasItems = items && items.length > 0;
  return [
    {
      fieldName: 'itemId',
      label: '物料',
      component: markRaw(MdItemSelect),
      componentProps: {
        placeholder: '请选择物料',
      },
      component: hasItems ? 'Select' : markRaw(MdItemSelect),
      componentProps: hasItems
        ? {
            placeholder: '请选择物料',
            options: items.map((item) => ({
              label: `${item.productName || ''}(${item.productBarCode || ''})`,
              value: item.productId,
            })),
            onChange: (value: number | undefined) => {
              const selected = items.find((i) => i.productId === value);
              onItemChange?.(selected);
            },
          }
        : {
            placeholder: '请选择物料',
            productIds: [],
          },
      rules: 'selectRequired',
    },
    {
@@ -363,6 +383,30 @@
        placeholder: '请输入退货数量',
        precision: 2,
      },
      dependencies: {
        triggerFields: ['itemId'],
        componentProps: (values) => {
          const selected = items?.find((i) => i.productId === values.itemId);
          return {
            class: '!w-full',
            max: selected?.count ?? undefined,
            min: 0,
            placeholder: '请输入退货数量',
            precision: 2,
          };
        },
        rules: (values) => {
          const selected = items?.find((i) => i.productId === values.itemId);
          const max = selected?.count;
          if (max !== undefined && max !== null) {
            return z
              .number({ message: '请输入退货数量' })
              .min(0)
              .max(max, `可退货数量不能超过 ${max}`);
          }
          return z.number({ message: '请输入退货数量' }).min(0);
        },
      },
      rules: 'required',
    },
    {
@@ -371,6 +415,7 @@
      component: markRaw(WmBatchSelect),
      componentProps: {
        clientId,
        disabled: true,
        placeholder: '请选择批次',
        salesOrderCode,
      },
@@ -378,6 +423,7 @@
        triggerFields: ['itemId'],
        componentProps: (values) => ({
          clientId,
          disabled: true,
          itemId: values.itemId,
          placeholder: '请选择批次',
          salesOrderCode,
src/views/wls/returnsales/modules/form.vue
@@ -19,6 +19,9 @@
  submitReturnSales,
  updateReturnSales,
} from '#/api/mes/wm/returnsales';
import type { ErpSaleOrderApi } from '#/api/erp/sale/order';
import { getSaleOrder, getSaleOrderPage } from '#/api/erp/sale/order';
import { $t } from '#/locales';
import { useFormSchema } from '../data';
@@ -28,6 +31,7 @@
const formType = ref<FormType>('create');
const formData = ref<MesWmReturnSalesApi.ReturnSales>();
const originalSnapshot = ref(''); // 表单原始数据快照,用于提交时跳过未变更的保存请求
const saleOrderItems = ref<ErpSaleOrderApi.SaleOrderItem[]>([]); // 当前销售订单的物料行
const isEditable = computed(() =>
  // 是否为编辑模式(可保存)
  ['create', 'update'].includes(formType.value),
@@ -169,13 +173,38 @@
    // 加载数据
    const data = modalApi.getData<{ formType: FormType; id?: number }>();
    formType.value = data.formType;
    formApi.setState({ schema: useFormSchema(formType.value, formApi) });
    formApi.setState({
      schema: useFormSchema(formType.value, formApi, (item) => {
        if (item?.id) {
          getSaleOrder(item.id as number).then((order) => {
            saleOrderItems.value = (order as ErpSaleOrderApi.SaleOrder)?.items || [];
          });
        } else {
          saleOrderItems.value = [];
        }
      }),
    });
    formApi.setDisabled(!isEditable.value);
    modalApi.setState({ showConfirmButton: isEditable.value });
    if (data?.id) {
      modalApi.lock();
      try {
        formData.value = await getReturnSales(data.id);
        // 通过销售订单号反查订单ID,确保 ErpSaleOrderSelect 能正确回显
        if (formData.value?.salesOrderCode && !formData.value.saleOrderId) {
          const orderPage = await getSaleOrderPage({
            pageNo: 1,
            pageSize: 1,
            no: formData.value.salesOrderCode,
          } as Record<string, unknown> as never);
          const list = (orderPage as Record<string, unknown>)?.list as Array<Record<string, unknown>> | undefined;
          if (list?.length) {
            const orderId = list[0].id as number;
            (formData.value as Record<string, unknown>).saleOrderId = orderId;
            const order = await getSaleOrder(orderId);
            saleOrderItems.value = order?.items || [];
          }
        }
        // 设置到 values
        await formApi.setValues(formData.value);
      } finally {
@@ -198,6 +227,7 @@
          :client-id="formData.clientId"
          :form-type="formType"
          :return-id="formData.id"
          :sale-order-items="saleOrderItems"
          :sales-order-code="formData.salesOrderCode"
        />
      </div>
src/views/wls/returnsales/modules/line-form.vue
@@ -1,4 +1,5 @@
<script lang="ts" setup>
import type { ErpSaleOrderApi } from '#/api/erp/sale/order';
import type { MesWmReturnSalesLineApi } from '#/api/mes/wm/returnsales/line';
import { computed, ref } from 'vue';
@@ -8,6 +9,7 @@
import { message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { getBatchPage } from '#/api/mes/wm/batch';
import {
  createReturnSalesLine,
  getReturnSalesLine,
@@ -20,6 +22,7 @@
const emit = defineEmits(['success']);
const formData = ref<MesWmReturnSalesLineApi.ReturnSalesLine>();
const returnId = ref<number>(); // 所属退货单编号
const maxQuantity = ref<number>(); // 当前选中物料可退货的最大数量
const getTitle = computed(() => {
  return formData.value?.id
@@ -73,12 +76,38 @@
    const data = modalApi.getData<{
      clientId?: number;
      id?: number;
      items?: ErpSaleOrderApi.SaleOrderItem[];
      returnId: number;
      salesOrderCode?: string;
    }>();
    returnId.value = data.returnId;
    maxQuantity.value = undefined;
    formApi.setState({
      schema: useLineFormSchema(data.clientId, data.salesOrderCode),
      schema: useLineFormSchema(
        data.clientId,
        data.salesOrderCode,
        data.items || [],
        async (item) => {
          maxQuantity.value = item?.count;
          // 重置批次
          await formApi.setFieldValue('batchId', undefined);
          if (item?.batchCode) {
            try {
              const batchPage = await getBatchPage({
                code: item.batchCode,
                pageNo: 1,
                pageSize: 1,
              });
              const batchList = batchPage?.list;
              if (batchList?.length) {
                await formApi.setFieldValue('batchId', batchList[0].id);
              }
            } catch {
              // 查询失败时忽略
            }
          }
        },
      ),
    });
    if (!data.id) {
      return;
@@ -98,5 +127,11 @@
<template>
  <Modal :title="getTitle" class="w-3/5">
    <Form class="mx-4" />
    <div
      v-if="maxQuantity !== undefined"
      class="mx-4 mt-2 text-sm text-blue-600"
    >
      当前物料可退货数量:<span class="font-bold">{{ maxQuantity }}</span>
    </div>
  </Modal>
</template>
src/views/wls/returnsales/modules/line-list.vue
@@ -1,6 +1,7 @@
<script lang="ts" setup>
import type { FormType } from '../data';
import type { ErpSaleOrderApi } from '#/api/erp/sale/order';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MesWmReturnSalesDetailApi } from '#/api/mes/wm/returnsales/detail';
import type { MesWmReturnSalesLineApi } from '#/api/mes/wm/returnsales/line';
@@ -29,6 +30,7 @@
  clientId?: number;
  formType: FormType;
  returnId: number;
  saleOrderItems?: ErpSaleOrderApi.SaleOrderItem[];
  salesOrderCode?: string;
}>();
@@ -64,6 +66,7 @@
  lineFormModalApi
    .setData({
      clientId: props.clientId,
      items: props.saleOrderItems,
      returnId: props.returnId,
      salesOrderCode: props.salesOrderCode,
    })
@@ -76,6 +79,7 @@
    .setData({
      clientId: props.clientId,
      id: row.id,
      items: props.saleOrderItems,
      returnId: props.returnId,
      salesOrderCode: props.salesOrderCode,
    })