gaoluyang
2 天以前 100e814e0b699ef8973bc4ca9c47e3800c77356f
销售报价-产品和规格型号改成选择下拉框
已修改4个文件
257 ■■■■ 文件已修改
src/views/procurementManagement/procurementLedger/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/invoiceLedger/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesQuotation/index.vue 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/index.vue
@@ -828,12 +828,9 @@
    purchaseContractNumber: "", // 采购合同编号
    salesContractNo: "", // 销售合同编号
    projectName: "", // 项目名称
    entryDate: [
      dayjs().format("YYYY-MM-DD"),
      dayjs().add(1, "day").format("YYYY-MM-DD"),
    ], // 录入日期
    entryDateStart: dayjs().format("YYYY-MM-DD"),
    entryDateEnd: dayjs().add(1, "day").format("YYYY-MM-DD"),
    entryDate: null, // 录入日期
    entryDateStart: undefined,
    entryDateEnd: undefined,
  },
  form: {
    purchaseContractNumber: "",
src/views/salesManagement/invoiceLedger/index.vue
@@ -185,12 +185,9 @@
  searchForm: {
    searchText: "",
    status: false,
    invoiceDate: [
      dayjs().startOf("month").format("YYYY-MM-DD"),
      dayjs().endOf("month").format("YYYY-MM-DD"),
    ],
    invoiceDateStart: dayjs().startOf("month").format("YYYY-MM-DD"),
    invoiceDateEnd: dayjs().endOf("month").format("YYYY-MM-DD"),
    invoiceDate: null,
    invoiceDateStart: undefined,
    invoiceDateEnd: undefined,
    createTimeStart: "", // 录入日期
  },
  form: {
src/views/salesManagement/salesLedger/index.vue
@@ -505,12 +505,9 @@
    customerContractNo: "", // 客户合同编号
    salesContractNo: "", // 销售合同编号
    projectName: "", // 项目名称
    entryDate: [
      dayjs().format("YYYY-MM-DD"),
      dayjs().add(1, "day").format("YYYY-MM-DD"),
    ], // 录入日期
    entryDateStart: dayjs().format("YYYY-MM-DD"),
    entryDateEnd: dayjs().add(1, "day").format("YYYY-MM-DD"),
    entryDate: null, // 录入日期
    entryDateStart: undefined,
    entryDateEnd: undefined,
  },
  form: {
    salesContractNo: "",
src/views/salesManagement/salesQuotation/index.vue
@@ -154,7 +154,14 @@
            </el-col>
            <el-col :span="12">
              <el-form-item label="交货期" prop="deliveryPeriod">
                <el-input v-model="form.deliveryPeriod" placeholder="请输入交货期" />
                <el-date-picker
                  v-model="form.deliveryPeriod"
                  type="date"
                  placeholder="选择交货期"
                  style="width: 100%"
                  format="YYYY-MM-DD"
                  value-format="YYYY-MM-DD"
                />
              </el-form-item>
            </el-col>
          </el-row>
@@ -171,12 +178,33 @@
          <el-table :data="form.products" border style="width: 100%">
            <el-table-column prop="product" label="产品名称" width="200">
              <template #default="scope">
                <el-input v-model="scope.row.product" placeholder="请输入产品名称" />
                                <el-tree-select
                                    v-model="scope.row.productId"
                                    placeholder="请选择"
                                    clearable
                                    check-strictly
                                    @change="getModels($event, scope.row)"
                                    :data="productOptions"
                                    :render-after-expand="false"
                                    style="width: 100%"
                                />
              </template>
            </el-table-column>
            <el-table-column prop="specification" label="规格型号" width="150">
              <template #default="scope">
                <el-input v-model="scope.row.specification" placeholder="规格型号" />
                                <el-select
                                    v-model="scope.row.specificationId"
                                    placeholder="请选择"
                                    clearable
                                    @change="getProductModel($event, scope.row)"
                                >
                                    <el-option
                                        v-for="item in modelOptions"
                                        :key="item.id"
                                        :label="item.model"
                                        :value="item.id"
                                    />
                                </el-select>
              </template>
            </el-table-column>
            <el-table-column prop="quantity" label="数量">
@@ -313,13 +341,14 @@
</template>
<script setup>
import { ref, reactive, computed,onMounted  } from 'vue'
import { ref, reactive, computed, onMounted, markRaw, shallowRef } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search } from '@element-plus/icons-vue'
// import Pagination from '@/components/PIMTable/Pagination.vue'
import Pagination from '@/components/PIMTable/Pagination.vue'
import {getQuotationList,addQuotation,updateQuotation,deleteQuotation} from '@/api/salesManagement/salesQuotation.js'
import {userListNoPage} from "@/api/system/user.js";
import {customerList} from "@/api/salesManagement/salesLedger.js";
import {modelList, productTreeList} from "@/api/basicData/product.js";
// 响应式数据
const loading = ref(false)
@@ -330,11 +359,12 @@
})
const quotationList = ref([])
const productOptions = ref([]);
const modelOptions = ref([]);
const pagination = reactive({
  total: 3,
  currentPage: 1,
  pageSize: 10
  pageSize: 100
})
const dialogVisible = ref(false)
@@ -365,7 +395,7 @@
  quotationDate: [{ required: true, message: '请选择报价日期', trigger: 'change' }],
  validDate: [{ required: true, message: '请选择有效期', trigger: 'change' }],
  paymentMethod: [{ required: true, message: '请选择付款方式', trigger: 'change' }],
  deliveryPeriod: [{ required: true, message: '请输入交货期', trigger: 'blur' }]
  deliveryPeriod: [{ required: true, message: '请选择交货期', trigger: 'change' }]
}
const userList = ref([]);
const customerOption = ref([]);
@@ -413,14 +443,123 @@
  resetForm()
  dialogVisible.value = true
    let userLists = await userListNoPage();
    userList.value = userLists.data;
    // 只复制需要的字段,避免将组件引用放入响应式对象
    userList.value = (userLists.data || []).map(item => ({
    userId: item.userId,
    nickName: item.nickName || '',
    userName: item.userName || ''
  }));
    getProductOptions();
    customerList().then((res) => {
        customerOption.value = res;
        // 只复制需要的字段,避免将组件引用放入响应式对象
        customerOption.value = (Array.isArray(res) ? res : []).map(item => ({
      id: item.id,
      customerName: item.customerName || '',
      taxpayerIdentificationNumber: item.taxpayerIdentificationNumber || ''
    }))
    });
}
const getProductOptions = () => {
    productTreeList().then((res) => {
        productOptions.value = convertIdToValue(res);
    });
};
function convertIdToValue(data) {
    return data.map((item) => {
        const { id, children, ...rest } = item;
        const newItem = {
            ...rest,
            value: id, // 将 id 改为 value
        };
        if (children && children.length > 0) {
            newItem.children = convertIdToValue(children);
        }
        return newItem;
    });
}
const getModels = (value, row) => {
    if (!row) return;
    // 如果清空选择,则清空相关字段
    if (!value) {
        row.productId = '';
        row.product = '';
        modelOptions.value = [];
        row.specificationId = '';
        row.specification = '';
        row.unit = '';
        return;
    }
    // 更新 productId(v-model 已经自动更新,这里确保一致性)
    row.productId = value;
    // 找到对应的 label 并赋值给 row.product
    const label = findNodeById(productOptions.value, value);
    if (label) {
        row.product = label;
    }
    // 获取规格型号列表
    modelList({ id: value }).then((res) => {
        modelOptions.value = res || [];
    });
};
const getProductModel = (value, row) => {
    if (!row) return;
    // 如果清空选择,则清空相关字段
    if (!value) {
        row.specificationId = '';
        row.specification = '';
        row.unit = '';
        return;
    }
    // 更新 specificationId(v-model 已经自动更新,这里确保一致性)
    row.specificationId = value;
    const index = modelOptions.value.findIndex((item) => item.id === value);
    if (index !== -1) {
        row.specification = modelOptions.value[index].model;
        row.unit = modelOptions.value[index].unit;
    } else {
        row.specification = '';
        row.unit = '';
    }
};
const findNodeById = (nodes, productId) => {
    for (let i = 0; i < nodes.length; i++) {
        if (nodes[i].value === productId) {
            return nodes[i].label; // 找到节点,返回 label
        }
        if (nodes[i].children && nodes[i].children.length > 0) {
            const foundLabel = findNodeById(nodes[i].children, productId);
            if (foundLabel) {
                return foundLabel; // 在子节点中找到,返回 label
            }
        }
    }
    return null; // 没有找到节点,返回null
};
const handleView = (row) => {
  currentQuotation.value = row
  // 只复制需要的字段,避免将组件引用放入响应式对象
  currentQuotation.value = {
    quotationNo: row.quotationNo || '',
    customer: row.customer || '',
    salesperson: row.salesperson || '',
    quotationDate: row.quotationDate || '',
    validDate: row.validDate || '',
    paymentMethod: row.paymentMethod || '',
    deliveryPeriod: row.deliveryPeriod || '',
    status: row.status || '',
    remark: row.remark || '',
    products: row.products ? row.products.map(product => ({
      productId: product.productId || '',
      product: product.product || product.productName || '',
      specificationId: product.specificationId || '',
      specification: product.specification || '',
      quantity: product.quantity || 0,
      unit: product.unit || '',
      unitPrice: product.unitPrice || 0,
      amount: product.amount || 0
    })) : [],
    totalAmount: row.totalAmount || 0
  }
  viewDialogVisible.value = true
}
@@ -428,7 +567,32 @@
  dialogTitle.value = '编辑报价'
  isEdit.value = true
  editId.value = row.id
  Object.assign(form, row)
  // 只复制需要的字段,避免将组件引用放入响应式对象
  form.quotationNo = row.quotationNo || ''
  form.customer = row.customer || ''
  form.salesperson = row.salesperson || ''
  form.quotationDate = row.quotationDate || ''
  form.validDate = row.validDate || ''
  form.paymentMethod = row.paymentMethod || ''
  form.deliveryPeriod = row.deliveryPeriod || ''
  form.status = row.status || '草稿'
  form.remark = row.remark || ''
  form.products = row.products ? row.products.map(product => ({
    productId: product.productId || '',
    product: product.product || product.productName || '',
    specificationId: product.specificationId || '',
    specification: product.specification || '',
    quantity: product.quantity || 0,
    unit: product.unit || '',
    unitPrice: product.unitPrice || 0,
    amount: product.amount || 0
  })) : []
  form.subtotal = row.subtotal || 0
  form.freight = row.freight || 0
  form.otherFee = row.otherFee || 0
  form.discountRate = row.discountRate || 0
  form.discountAmount = row.discountAmount || 0
  form.totalAmount = row.totalAmount || 0
  dialogVisible.value = true
}
@@ -475,7 +639,10 @@
const addProduct = () => {
  form.products.push({
    productId: '',
    product: '',
    productName: '',
    specificationId: '',
    specification: '',
    quantity: 1,
    unit: '',
@@ -570,12 +737,45 @@
  getQuotationList(params).then(res=>{
    // console.log(res)
    if(res.code===200){
      quotationList.value = res.data.records
      // 只复制需要的字段,避免将组件引用或其他对象放入响应式对象
      quotationList.value = (res.data.records || []).map(item => ({
        id: item.id,
        quotationNo: item.quotationNo || '',
        customer: item.customer || '',
        salesperson: item.salesperson || '',
        quotationDate: item.quotationDate || '',
        validDate: item.validDate || '',
        paymentMethod: item.paymentMethod || '',
        deliveryPeriod: item.deliveryPeriod || '',
        status: item.status || '草稿',
        remark: item.remark || '',
        products: item.products ? item.products.map(product => ({
          productId: product.productId || '',
          product: product.product || product.productName || '',
          specificationId: product.specificationId || '',
          specification: product.specification || '',
          quantity: product.quantity || 0,
          unit: product.unit || '',
          unitPrice: product.unitPrice || 0,
          amount: product.amount || 0
        })) : [],
        subtotal: item.subtotal || 0,
        freight: item.freight || 0,
        otherFee: item.otherFee || 0,
        discountRate: item.discountRate || 0,
        discountAmount: item.discountAmount || 0,
        totalAmount: item.totalAmount || 0
      }))
      pagination.total = res.data.total
    }
  })
    customerList().then((res) => {
        customerOption.value = res;
        // 只复制需要的字段,避免将组件引用放入响应式对象
        customerOption.value = (Array.isArray(res) ? res : []).map(item => ({
      id: item.id,
      customerName: item.customerName || '',
      taxpayerIdentificationNumber: item.taxpayerIdentificationNumber || ''
    }))
    });
}