zhangwencui
11 小时以前 4be9b07e00bea78ae394aec67062b4db9895b565
src/views/basicData/product/ProductSelectDialog.vue
@@ -1,39 +1,72 @@
<template>
  <el-dialog v-model="visible" title="选择产品" width="900px" destroy-on-close :close-on-click-modal="false">
    <el-form :inline="true" :model="query" class="mb-2">
      <el-form-item label="产品大类">
        <el-input v-model="query.productName" placeholder="输入产品大类" clearable @keyup.enter="onSearch" />
  <el-dialog v-model="visible"
             title="选择产品"
             width="900px"
             destroy-on-close
             :close-on-click-modal="false">
    <el-form :inline="true"
             :model="query"
             class="mb-2">
      <el-form-item label="规格">
        <el-input v-model="query.specification"
                  placeholder="输入规格"
                  clearable
                  @keyup.enter="onSearch" />
      </el-form-item>
      <el-form-item label="型号名称">
        <el-input v-model="query.model" placeholder="输入型号名称" clearable @keyup.enter="onSearch" />
      <el-form-item label="物料编码">
        <el-input v-model="query.materialCode"
                  placeholder="输入物料编码"
                  clearable
                  @keyup.enter="onSearch" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSearch">搜索</el-button>
        <el-button type="primary"
                   @click="onSearch">搜索</el-button>
        <el-button @click="onReset">重置</el-button>
      </el-form-item>
    </el-form>
    <!-- 列表 -->
    <el-table ref="tableRef" v-loading="loading" :data="tableData" height="420" highlight-current-row row-key="id"
      @selection-change="handleSelectionChange" @select="handleSelect">
      <el-table-column type="selection" width="55" />
      <el-table-column type="index" label="序号" width="60" />
      <el-table-column prop="productName" label="产品大类" min-width="160" />
      <el-table-column prop="model" label="型号名称" min-width="200" />
      <el-table-column prop="unit" label="单位" min-width="160" />
    <el-table ref="tableRef"
              v-loading="loading"
              :data="tableData"
              height="420"
              highlight-current-row
              row-key="skuId"
              @selection-change="handleSelectionChange"
              @select="handleSelect">
      <el-table-column type="selection"
                       width="55" />
      <el-table-column type="index"
                       label="序号"
                       width="60" />
      <el-table-column prop="materialName"
                       label="产品名称"
                       min-width="160" />
      <el-table-column prop="materialCode"
                       label="物料编码"
                       min-width="200" />
      <el-table-column prop="specification"
                       label="规格"
                       min-width="200" />
      <el-table-column prop="baseUnit"
                       label="单位"
                       min-width="160" />
    </el-table>
    <div class="mt-3 flex justify-end">
      <el-pagination background layout="total, sizes, prev, pager, next, jumper" :total="total"
        v-model:page-size="page.pageSize" v-model:current-page="page.pageNum" :page-sizes="[10, 20, 50, 100]"
        @size-change="onPageChange" @current-change="onPageChange" />
      <el-pagination background
                     layout="total, sizes, prev, pager, next, jumper"
                     :total="total"
                     v-model:page-size="page.pageSize"
                     v-model:current-page="page.pageNum"
                     :page-sizes="[10, 20, 50, 100]"
                     @size-change="onPageChange"
                     @current-change="onPageChange" />
    </div>
    <template #footer>
      <el-button @click="close()">取消</el-button>
      <el-button type="primary" :disabled="multipleSelection.length === 0" @click="onConfirm">
      <el-button type="primary"
                 :disabled="multipleSelection.length === 0"
                 @click="onConfirm">
        确定
      </el-button>
    </template>
@@ -41,140 +74,147 @@
</template>
<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch, nextTick } from "vue";
import { ElMessage } from "element-plus";
import { productModelList } from '@/api/basicData/productModel'
  import { computed, onMounted, reactive, ref, watch, nextTick } from "vue";
  import { ElMessage } from "element-plus";
  import { modelListPage } from "@/api/basicData/newProduct";
export type ProductRow = {
  id: number;
  productName: string;
  model: string;
  unit?: string;
};
  export type ProductRow = {
    skuId: number;
    specification: string;
    materialCode: string;
    baseUnit?: string;
    materialName?: string;
  };
const props = defineProps<{
  modelValue: boolean;
  single?: boolean; // 是否只能选择一个,默认false(可选择多个)
}>();
  const props = defineProps<{
    modelValue: boolean;
    single?: boolean; // 是否只能选择一个,默认false(可选择多个)
  }>();
const emit = defineEmits(['update:modelValue', 'confirm']);
  const emit = defineEmits(["update:modelValue", "confirm"]);
const visible = computed({
  get: () => props.modelValue,
  set: (v) => emit("update:modelValue", v),
});
  const visible = computed({
    get: () => props.modelValue,
    set: v => emit("update:modelValue", v),
  });
const query = reactive({
  productName: "",
  model: "",
});
  const query = reactive({
    specification: "",
    materialCode: "",
  });
const page = reactive({
  pageNum: 1,
  pageSize: 10,
});
  const page = reactive({
    pageNum: 1,
    pageSize: 10,
  });
const loading = ref(false);
const tableData = ref<ProductRow[]>([]);
const total = ref(0);
const multipleSelection = ref<ProductRow[]>([]);
const tableRef = ref();
  const loading = ref(false);
  const tableData = ref<ProductRow[]>([]);
  const total = ref(0);
  const multipleSelection = ref<ProductRow[]>([]);
  const tableRef = ref();
function close() {
  visible.value = false;
}
const handleSelectionChange = (val: ProductRow[]) => {
  if (props.single && val.length > 1) {
    // 如果限制为单个选择,只保留最后一个选中的
    const lastSelected = val[val.length - 1];
    multipleSelection.value = [lastSelected];
    // 清空表格选中状态,然后重新选中最后一个
    nextTick(() => {
      if (tableRef.value) {
        tableRef.value.clearSelection();
        tableRef.value.toggleRowSelection(lastSelected, true);
      }
    });
  } else {
    multipleSelection.value = val;
  function close() {
    visible.value = false;
  }
}
// 处理单个选择
const handleSelect = (selection: ProductRow[], row: ProductRow) => {
  if (props.single) {
    // 如果限制为单个,清空其他选择,只保留当前行
    if (selection.includes(row)) {
      // 选中当前行时,清空其他选中
      multipleSelection.value = [row];
  const handleSelectionChange = (val: ProductRow[]) => {
    if (props.single && val.length > 1) {
      // 如果限制为单个选择,只保留最后一个选中的
      const lastSelected = val[val.length - 1];
      multipleSelection.value = [lastSelected];
      // 清空表格选中状态,然后重新选中最后一个
      nextTick(() => {
        if (tableRef.value) {
          tableData.value.forEach((item) => {
            if (item.id !== row.id) {
              tableRef.value.toggleRowSelection(item, false);
            }
          });
          tableRef.value.clearSelection();
          tableRef.value.toggleRowSelection(lastSelected, true);
        }
      });
    } else {
      multipleSelection.value = val;
    }
  };
  // 处理单个选择
  const handleSelect = (selection: ProductRow[], row: ProductRow) => {
    if (props.single) {
      // 如果限制为单个,清空其他选择,只保留当前行
      if (selection.includes(row)) {
        // 选中当前行时,清空其他选中
        multipleSelection.value = [row];
        nextTick(() => {
          if (tableRef.value) {
            tableData.value.forEach(item => {
              if (item.skuId !== row.skuId) {
                tableRef.value.toggleRowSelection(item, false);
              }
            });
          }
        });
      }
    }
  };
  function onSearch() {
    page.pageNum = 1;
    loadData();
  }
  function onReset() {
    query.specification = "";
    query.materialCode = "";
    page.pageNum = 1;
    loadData();
  }
  function onPageChange() {
    loadData();
  }
  function onConfirm() {
    if (multipleSelection.value.length === 0) {
      ElMessage.warning("请选择一条产品");
      return;
    }
    if (props.single && multipleSelection.value.length > 1) {
      ElMessage.warning("只能选择一个产品");
      return;
    }
    emit(
      "confirm",
      props.single ? [multipleSelection.value[0]] : multipleSelection.value
    );
    close();
  }
  async function loadData() {
    loading.value = true;
    try {
      multipleSelection.value = []; // 翻页/搜索后清空选择更符合预期
      const res: any = await modelListPage({
        specification: query.specification.trim(),
        materialCode: query.materialCode.trim(),
        current: page.pageNum,
        size: page.pageSize,
      });
      tableData.value = res.data.records;
      total.value = res.data.total;
    } finally {
      loading.value = false;
    }
  }
}
function onSearch() {
  page.pageNum = 1;
  loadData();
}
  // 监听弹窗打开,重置选择
  watch(
    () => props.modelValue,
    visible => {
      if (visible) {
        multipleSelection.value = [];
      }
    }
  );
function onReset() {
  query.productName = "";
  query.model = "";
  page.pageNum = 1;
  loadData();
}
function onPageChange() {
  loadData();
}
function onConfirm() {
  if (multipleSelection.value.length === 0) {
    ElMessage.warning("请选择一条产品");
    return;
  }
  if (props.single && multipleSelection.value.length > 1) {
    ElMessage.warning("只能选择一个产品");
    return;
  }
  emit("confirm", props.single ? [multipleSelection.value[0]] : multipleSelection.value);
  close();
}
async function loadData() {
  loading.value = true;
  try {
    multipleSelection.value = []; // 翻页/搜索后清空选择更符合预期
    const res: any = await productModelList({
      productName: query.productName.trim(),
      model: query.model.trim(),
      current: page.pageNum,
      size: page.pageSize,
    });
    tableData.value = res.records;
    total.value = res.total;
  } finally {
    loading.value = false;
  }
}
// 监听弹窗打开,重置选择
watch(() => props.modelValue, (visible) => {
  if (visible) {
    multipleSelection.value = [];
  }
});
onMounted(() => {
  loadData()
})
  onMounted(() => {
    loadData();
  });
</script>