1.海川开心-来票登记可以多选开票(多选时金额要加起来)
2.海川开心-采购台账添加一个附件操作
已添加1个文件
已修改3个文件
413 ■■■■ 文件已修改
src/views/procurementManagement/invoiceEntry/components/Modal.vue 320 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/invoiceEntry/index.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/fileList.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/index.vue 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/invoiceEntry/components/Modal.vue
@@ -10,7 +10,7 @@
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="采购合同号:" prop="purchaseLedgerNo">
            <el-input v-model="form.purchaseLedgerNo" disabled />
                        <el-input v-model="form.purchaseLedgerNo" disabled placeholder="多合同批量处理(具体合同号见产品列表)" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
@@ -33,7 +33,16 @@
            />
          </el-form-item>
        </el-col>
<!--                <el-col :span="12">-->
<!--                    <el-form-item label="项目名称:" prop="projectName">-->
<!--                        <el-input-->
<!--                            v-model="form.projectName"-->
<!--                            placeholder="自动填充"-->
<!--                            clearable-->
<!--                            disabled-->
<!--                        />-->
<!--                    </el-form-item>-->
<!--                </el-col>-->
        <el-col :span="12">
          <el-form-item label="发票号:" prop="invoiceNumber">
            <el-input
@@ -47,9 +56,8 @@
          <el-form-item label="发票金额(元):" prop="invoiceAmount">
            <el-input-number :step="0.01" :min="0" style="width: 100%"
              v-model="form.invoiceAmount"
              placeholder="自动填充"
                                                         placeholder="请输入发票金额"
              clearable
              :disabled="true"
            />
          </el-form-item>
        </el-col>
@@ -59,6 +67,7 @@
              v-model="form.issUer"
              placeholder="请输入"
              clearable
                            disabled
            />
          </el-form-item>
        </el-col>
@@ -102,47 +111,90 @@
                        />
                    </el-form-item>
                </el-col>
      </el-row>
      <el-form-item label="产品信息:"> </el-form-item>
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableData="form.productData"
                :summaryMethod="summarizeChildrenTable"
                :isShowSummary="true"
        height="auto"
            <el-table
                :data="form.productData"
                border
                show-summary
                :summary-method="summarizeChildrenTable"
      >
        <template #ticketsNumRef="{ row }">
          <el-input-number
            v-model="row.ticketsNum"
            placeholder="请输入"
            :min="0"
            :step="0.1"
                <el-table-column align="center" label="序号" type="index" width="60" />
                <el-table-column label="所属合同" prop="purchaseLedgerNo" width="200">
                    <template #default="{ row }">
                        <el-tag type="primary">{{ row.purchaseLedgerNo }}</el-tag>
                    </template>
                </el-table-column>
                <el-table-column label="产品大类" prop="productCategory" />
                <el-table-column label="规格型号" prop="specificationModel" width="150" />
                <el-table-column label="单位" prop="unit" width="70" />
                <el-table-column label="数量" prop="quantity" width="70" />
                <el-table-column label="税率(%)" prop="taxRate" width="80" />
                <el-table-column
                    label="含税单价(元)"
                    prop="taxInclusiveUnitPrice"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="含税总价(元)"
                    prop="taxInclusiveTotalPrice"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="不含税总价(元)"
                    prop="taxExclusiveTotalPrice"
                    :formatter="formattedNumber"
                />
                <el-table-column label="本次开票数" prop="ticketsNum" width="180">
                    <template #default="scope">
                        <el-input-number :step="0.1" :min="0" style="width: 100%"
                        :precision="2"
            clearable
            style="width: 100%"
            @change="invoiceNumBlur(row)"
                                                         v-model="scope.row.ticketsNum"
                                                         @change="invoiceNumBlur(scope.row)"
          />
        </template>
        <template #ticketsAmountRef="{ row }">
          <el-input-number
            v-model="row.ticketsAmount"
            placeholder="请输入"
            :min="0"
                </el-table-column>
                <el-table-column
                    label="本次开票金额(元)"
                    prop="ticketsAmount"
                    width="180"
                >
                    <template #default="scope">
                        <el-input-number :step="0.01" :min="0" style="width: 100%"
                        :precision="2"
            :step="0.1"
            clearable
            style="width: 100%"
            @change="invoiceAmountBlur(row)"
                                                         v-model="scope.row.ticketsAmount"
                                                         @change="invoiceAmountBlur(scope.row)"
          />
        </template>
      </PIMTable>
                </el-table-column>
                <el-table-column
                    label="未来票数"
                    prop="futureTickets"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="本次来票金额(元)"
                    prop="ticketsAmount"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="未来票数"
                    prop="futureTickets"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="未来票金额(元)"
                    prop="futureTicketsAmount"
                    :formatter="formattedNumber"
                />
            </el-table>
    </el-form>
    <template #footer>
            <el-button type="primary" :loading="modalLoading" @click="submitForm">
                {{ modalOptions.confirmText }}
                ç¡®è®¤
            </el-button>
      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
            <el-button @click="closeModal">取消</el-button>
    </template>
  </el-dialog>
</template>
@@ -175,6 +227,7 @@
  purchaseLedgerNo: undefined, // é‡‡è´­åˆåŒå·
  salesContractNo: undefined, // é”€å”®åˆåŒå·
  supplierName: undefined, // ä¾›åº”商名称
    projectName: undefined, // é¡¹ç›®åç§°
  invoiceNumber: undefined, // å‘票号
  invoiceAmount: undefined, // å‘票金额(元)
  issUerId: userStore.id, // å½•入人
@@ -185,6 +238,8 @@
  productData: [], // è¡¨æ ¼
  tempFileIds: [], // æ–‡ä»¶
});
const selectedContracts = ref([]); // å­˜å‚¨é€‰ä¸­çš„合同数据
const rules = ref({
  invoiceNumber: [
@@ -294,26 +349,89 @@
        width: 200,
  },
];
const getTableData = async (type, id) => {
const formattedNumber = (row, column, cellValue) => {
    if (cellValue == 0) {
        return parseFloat(cellValue).toFixed(2);
    }
    if (cellValue) {
        return parseFloat(cellValue).toFixed(2);
    } else {
        return cellValue;
    }
};
const getTableData = async (type, selectedRows) => {
  if (type == "add") {
    const { data } = await getPurchaseNoById({ id });
    form.purchaseLedgerNo = data.purchaseContractNumber;
    form.invoiceAmount = data.invoiceAmount;
    form.invoiceNumber = data.invoiceNumber;
    form.entryDate = data.entryDate;
    form.salesContractNoId = data.salesContractNoId;
        // æ£€æŸ¥æ‰€æœ‰é€‰æ‹©çš„合同是否具有相同的供应商名称
        const firstRow = selectedRows[0];
        const isSameSupplier = selectedRows.every(row =>
            row.supplierName === firstRow.supplierName
        );
    const { data: infoData } = await getInfo({ id });
    form.salesContractNo = infoData.salesContractNo;
    form.supplierName = infoData.supplierName;
    form.productData = infoData.productData;
        if (!isSameSupplier) {
            proxy.$modal.msgError("请选择相同供应商名称的合同");
            return;
        }
        // å…è®¸ä¸åŒçš„采购合同号批量处理,无需检查重复
        // æ¸…空表单数据
        Object.keys(form).forEach(key => {
            if (key !== 'productData') {
                form[key] = undefined;
            }
        });
        form.productData = [];
        // åŠ è½½æ‰€æœ‰é€‰ä¸­åˆåŒçš„äº§å“æ•°æ®
        const promises = selectedRows.map(row =>
            getInfo({ id: row.id })
        );
        Promise.all(promises).then(results => {
            // åˆå¹¶æ‰€æœ‰åˆåŒçš„产品数据,并为每个产品添加对应的合同信息
            const allProductData = [];
            results.forEach((result, index) => {
                const contract = selectedRows[index];
                const contractId = contract.id;
                if (result.data && result.data.productData) {
                    result.data.productData.forEach(item => {
                        allProductData.push({
                            ...item,
                            id: contractId, // æ˜Žç¡®è®¾ç½®åˆåŒID
                            purchaseLedgerNo: contract.purchaseContractNumber, // æ·»åŠ é‡‡è´­åˆåŒå·
                            supplierName: contract.supplierName, // æ·»åŠ ä¾›åº”å•†åç§°
                            projectName: contract.projectName // æ·»åŠ é¡¹ç›®åç§°
                        });
                    });
                }
            });
            // è®¾ç½®è¡¨å•数据(使用第一个合同的基本信息,采购合同号留空)
            form.purchaseLedgerNo = ""; // é‡‡è´­åˆåŒå·ç•™ç©ºï¼Œå› ä¸ºä¼šåœ¨äº§å“è¡¨æ ¼ä¸­åˆ†åˆ«æ˜¾ç¤º
            form.invoiceAmount = 0;
            form.invoiceNumber = "";
            form.entryDate = dayjs().format("YYYY-MM-DD");
            form.enterDate = dayjs().format("YYYY-MM-DD");
            form.salesContractNo = results[0].data.salesContractNo;
            form.projectName = results[0].data.projectName;
            form.supplierName = results[0].data.supplierName;
            // ä¿ç•™å½•入人信息
            form.issUerId = userStore.id;
            form.issUer = userStore.nickName;
            form.productData = allProductData;
            // å­˜å‚¨é€‰ä¸­çš„合同数据
            selectedContracts.value = selectedRows;
        });
  } else if (type == "edit") {
        const id = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows;
    const data = await getPurchaseById({ id, type: 2 });
    form.purchaseLedgerNo = data.purchaseContractNumber;
    form.invoiceAmount = data.invoiceAmount;
    form.invoiceNumber = data.invoiceNumber;
    form.salesContractNo = data.salesContractNo;
        form.projectName = data.projectName;
    form.supplierName = data.supplierName;
    form.entryDate = data.entryDate;
    form.productData = data.productData;
@@ -382,10 +500,23 @@
  form.invoiceAmount = invoiceAmountTotal.toFixed(2);
};
const open = (type, eid) => {
  openModal();
  getTableData(type, eid);
  id.value = eid;
const open = async (type, selectedRows) => {
    visible.value = true;
    // å¦‚果是批量操作,设置标题
    if (Array.isArray(selectedRows) && selectedRows.length > 1) {
        modalOptions.title = `批量新增 (${selectedRows.length}条)`;
    } else {
        modalOptions.title = type == "add" ? "新增" : "编辑";
    }
    // å¦‚果是单个操作,获取id
    if (!Array.isArray(selectedRows) || selectedRows.length === 1) {
        const idValue = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows;
        id.value = idValue;
    }
    await getTableData(type, selectedRows);
};
const uploadSuccess = (response) => {
@@ -404,31 +535,96 @@
};
const submitForm = () => {
  formRef.value.validate(async (valid, fields) => {
    proxy.$refs["formRef"].validate((valid) => {
    if (valid) {
      // modalLoading.value = true;
      const { code } = await addOrUpdateRegistration({
        purchaseLedgerId: id.value,
        purchaseContractNumber: form.purchaseLedgerNo,
            // å¦‚果是批量操作,将所有合同的数据放在一个数组里,只调用一次接口
            if (selectedContracts.value.length > 1) {
                // åˆ›å»ºåŒ…含所有合同数据的数组
                const batchData = selectedContracts.value.map(contract => {
                    // ç­›é€‰å‡ºå±žäºŽå½“前合同的产品数据
                    const contractProductData = form.productData.filter(item =>
                        item.id === contract.id
                    );
                    // ä¸ºæ¯ä¸ªé‡‡è´­åˆåŒåˆ›å»ºç‹¬ç«‹çš„对象
                    return {
                        // åŸºç¡€è¡¨å•数据
        invoiceNumber: form.invoiceNumber,
        invoiceAmount: form.invoiceAmount,
        salesContractNo: form.salesContractNo,
        productData: form.productData,
        issueDate: form.entryDate,
                        entryDate: form.entryDate,
                        enterDate: form.enterDate,
        issUerId: form.issUerId, // å½•入人id
        issUer: form.issUer, // å½•入人
        salesContractNoId: form.salesContractNoId,
        supplierName: form.supplierName,
        tempFileIds: form.tempFileIds,
        enterDate: form.enterDate,
        type: 4,
                        // åˆåŒå®žé™…信息
                        purchaseLedgerId: contract.id, // ä½¿ç”¨id作为字段名,值为purchaseLedgerId
                        purchaseContractNumber: contract.purchaseContractNumber, // ä½¿ç”¨å®žé™…的采购合同号
                        salesContractNo: contract.salesContractNo, // ä½¿ç”¨å®žé™…的销售合同号
                        supplierName: contract.supplierName, // ä½¿ç”¨å®žé™…的供应商名称
                        projectName: contract.projectName, // ä½¿ç”¨å®žé™…的项目名称
                        // äº§å“æ•°æ®
                        productData: proxy.HaveJson(contractProductData),
                        // æ‰¹é‡æ ‡è¯†
                        isBatch: true,
                        type: 4
                    };
      });
                // åªè°ƒç”¨ä¸€æ¬¡æŽ¥å£ï¼Œä¼ é€’包含所有合同数据的数组
                modalLoading.value = true;
                addOrUpdateRegistration(batchData).then((res) => {
      modalLoading.value = false;
      if (code == 200) {
                    if (res.code === 200) {
                        proxy.$modal.msgSuccess("批量登记成功");
        closeAndRefresh();
      }
    } else {
                }).catch(() => {
      modalLoading.value = false;
                    proxy.$modal.msgError("批量登记失败");
                });
            } else {
                // å•个合同提交逻辑
                const singleContract = selectedContracts.value[0];
                const singleForm = {
                    // åŸºç¡€è¡¨å•数据
                    invoiceNumber: form.invoiceNumber,
                    invoiceAmount: form.invoiceAmount,
                    entryDate: form.entryDate,
                    enterDate: form.enterDate,
                    issUerId: form.issUerId, // å½•入人id
                    issUer: form.issUer, // å½•入人
                    tempFileIds: form.tempFileIds,
                    // åˆåŒå®žé™…信息
                    purchaseLedgerId: singleContract.id, // ä½¿ç”¨id作为字段名,值为purchaseLedgerId
                    purchaseContractNumber: singleContract.purchaseContractNumber, // ä½¿ç”¨å®žé™…的采购合同号
                    salesContractNo: singleContract.salesContractNo, // ä½¿ç”¨å®žé™…的销售合同号
                    supplierName: singleContract.supplierName, // ä½¿ç”¨å®žé™…的供应商名称
                    projectName: singleContract.projectName, // ä½¿ç”¨å®žé™…的项目名称
                    // äº§å“æ•°æ®
                    productData: proxy.HaveJson(form.productData),
                    // æ‰¹é‡æ ‡è¯†
                    isBatch: false,
                    type: 4
                };
                modalLoading.value = true;
                addOrUpdateRegistration(singleForm).then((res) => {
                    modalLoading.value = false;
                    if (res.code === 200) {
                        proxy.$modal.msgSuccess("登记成功");
                        closeAndRefresh();
                    }
                }).catch(() => {
                    modalLoading.value = false;
                    proxy.$modal.msgError("登记失败");
                });
            }
    }
  });
};
src/views/procurementManagement/invoiceEntry/index.vue
@@ -186,11 +186,11 @@
};
const handleAdd = (type) => {
  if (selectedRows.value.length !== 1) {
    proxy.$modal.msgWarning("请先选中一条数据");
    if (selectedRows.value.length < 1) {
        proxy.$modal.msgWarning("请至少选中一条数据");
    return;
  }
  modalRef.value.open(type, selectedRows.value[0].id);
    modalRef.value.open(type, selectedRows.value);
};
const handleEdit = (type, id) => {
src/views/procurementManagement/procurementLedger/fileList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
<template>
  <el-dialog v-model="dialogVisible" title="附件" width="40%" :before-close="handleClose">
    <el-table :data="tableData" border height="40vh">
      <el-table-column label="附件名称" prop="name" min-width="400" show-overflow-tooltip />
      <el-table-column fixed="right" label="操作" width="150" align="center">
        <template #default="scope">
          <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">下载</el-button>
          <el-button link type="primary" size="small" @click="lookFile(scope.row)">预览</el-button>
          <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-dialog>
  <filePreview ref="filePreviewRef" />
</template>
<script setup>
import { ref } from 'vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import filePreview from '@/components/filePreview/index.vue'
import { delCommonFile } from '@/api/publicApi/commonFile.js'
const dialogVisible = ref(false)
const tableData = ref([])
const { proxy } = getCurrentInstance();
const filePreviewRef = ref()
const handleClose = () => {
  dialogVisible.value = false
}
const open = (list) => {
  dialogVisible.value = true
  tableData.value = list
}
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
}
const lookFile = (row) => {
  filePreviewRef.value.open(row.url)
}
// åˆ é™¤é™„ä»¶
const handleDelete = (row) => {
  ElMessageBox.confirm(`确认删除附件"${row.name}"吗?`, '删除确认', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    delCommonFile([row.id]).then(() => {
      ElMessage.success('删除成功')
      // ä»Žåˆ—表中移除已删除的附件
      const index = tableData.value.findIndex(item => item.id === row.id)
      if (index !== -1) {
        tableData.value.splice(index, 1)
      }
    }).catch(() => {
      ElMessage.error('删除失败')
    })
  }).catch(() => {
    proxy.$modal.msg('已取消删除')
  })
}
defineExpose({
  open
})
</script>
<style></style>
src/views/procurementManagement/procurementLedger/index.vue
@@ -99,12 +99,10 @@
        <el-table-column
          label="销售合同号"
          prop="salesContractNo"
          width="200"
          show-overflow-tooltip
        />
        <el-table-column
          label="供应商名称"
          width="240"
          prop="supplierName"
          show-overflow-tooltip
        />
@@ -124,7 +122,7 @@
        <el-table-column
          label="录入人"
          prop="recorderName"
           width="100"
           width="120"
          show-overflow-tooltip
        />
        <el-table-column
@@ -136,7 +134,7 @@
        <el-table-column
          fixed="right"
          label="操作"
          min-width="150"
          width="180"
          align="center"
        >
          <template #default="scope">
@@ -153,6 +151,13 @@
              size="small"
              @click="showQRCode(scope.row)"
              >生成二维码</el-button
            >
            <el-button
              link
              type="primary"
              size="small"
              @click="downLoadFile(scope.row)"
              >附件</el-button
            >
          </template>
@@ -757,6 +762,7 @@
        </div>
      </template>
    </el-dialog>
        <FileList ref="fileListRef" />
  </div>
</template>
@@ -767,6 +773,7 @@
import { Search } from "@element-plus/icons-vue";
import { ElMessageBox } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
import FileList from "./fileList.vue";
import {
  getSalesLedgerWithProducts,
  addOrUpdateSalesLedgerProduct,
@@ -1384,6 +1391,11 @@
  }
};
const fileListRef = ref(null)
const downLoadFile = (row) => {
    fileListRef.value.open(row.salesLedgerFiles)
}
// æ˜¾ç¤ºäºŒç»´ç 
const showQRCode = async (row) => {
  try {