feat(库存/明细账): 明细账真实导出、库存报表合并出入库、按采购订单号搜索

- 科目明细账“导出”由提示改为真实导出 CSV
- 库存报表日报/月报合并出库明细,修正日期范围与来源字典
- 库存管理、库存报表支持按采购订单号筛选

Co-Authored-By: Claude Code <noreply@anthropic.com>
已修改3个文件
105 ■■■■■ 文件已修改
src/views/financialManagement/voucher/detailLedger.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/Record.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockReport/index.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/voucher/detailLedger.vue
@@ -76,6 +76,7 @@
<script setup>
import { ref, reactive, onMounted, computed, watch, nextTick } from "vue";
import { ElMessage } from "element-plus";
import { saveAs } from "file-saver";
import { listAccountSubject } from "@/api/financialManagement/accountSubject";
import { getDetailLedger } from "@/api/financialManagement/ledger";
@@ -236,7 +237,36 @@
  ElMessage.info("打印功能");
};
const csvCell = (value) => {
  const text = value === undefined || value === null ? "" : String(value);
  return `"${text.replace(/"/g, '""').replace(/\r?\n/g, " ")}"`;
};
const handleOut = () => {
  if (!currentSubject.value) {
    ElMessage.warning("请先选择会计科目");
    return;
  }
  if (dataList.value.length === 0) {
    ElMessage.warning("当前没有可导出的数据");
    return;
  }
  const header = ["日期", "凭证字号", "摘要", "借方", "贷方", "方向", "余额"];
  const rows = dataList.value.map((row) => [
    row.date || "",
    row.voucherNo || "",
    row.summary || "",
    Number(row.debit || 0).toFixed(2),
    Number(row.credit || 0).toFixed(2),
    row.direction || "",
    Math.abs(Number(row.balance || 0)).toFixed(2),
  ]);
  const content = [header, ...rows].map((line) => line.map(csvCell).join(",")).join("\r\n");
  // 带 BOM,避免 Excel 打开中文乱码
  const blob = new Blob(["\ufeff" + content], { type: "text/csv;charset=utf-8;" });
  const period = [filters.startMonth, filters.endMonth].filter(Boolean).join("_");
  const name = `明细账_${currentSubject.value.code}_${currentSubject.value.name}${period ? `_${period}` : ""}.csv`;
  saveAs(blob, name);
  ElMessage.success("导出成功");
};
src/views/inventoryManagement/stockManagement/Record.vue
@@ -32,6 +32,15 @@
                        clearable />
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item label="采购订单号"
                          prop="purchaseOrderNo">
              <el-input v-model="searchForm.purchaseOrderNo"
                        style="width: 240px"
                        placeholder="请输入"
                        clearable />
            </el-form-item>
          </el-col>
          <!-- 按钮 -->
          <el-col :span="4">
            <el-form-item>
@@ -215,6 +224,7 @@
      productName: "",
      model: "",
      batchNo: "",
      purchaseOrderNo: "",
      topParentProductId: props.productId,
    },
  });
src/views/inventoryManagement/stockReport/index.vue
@@ -41,6 +41,11 @@
                        format="YYYY-MM-DD"
                        value-format="YYYY-MM-DD"
                        style="width: 240px;" />
        <span class="search_title ml10">采购订单号:</span>
        <el-input v-model="searchForm.purchaseOrderNo"
                  placeholder="请输入采购订单号"
                  clearable
                  style="width: 180px;" />
        <el-button type="primary"
                   @click="onSearch"
                   style="margin-left: 10px">
@@ -148,16 +153,30 @@
                           label="序号"
                           type="index"
                           width="60" />
          <el-table-column label="入库时间"
          <el-table-column label="时间"
                           prop="createTime"
                           width="200"
                           show-overflow-tooltip
                           v-if="searchForm.reportType !== 'inout'" />
          <el-table-column label="入库批次"
                           prop="inboundBatches"
          <el-table-column label="方向"
                           width="80"
                           align="center"
                           v-if="searchForm.reportType !== 'inout'">
            <template #default="scope">
              <el-tag :type="scope.row.direction === 'out' ? 'warning' : 'success'"
                      size="small">
                {{ scope.row.direction === 'out' ? '出库' : '入库' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="单据批次"
                           width="180"
                           show-overflow-tooltip
                           v-if="searchForm.reportType !== 'inout'" />
                           v-if="searchForm.reportType !== 'inout'">
            <template #default="scope">
              {{ scope.row.direction === 'out' ? scope.row.outboundBatches : scope.row.inboundBatches }}
            </template>
          </el-table-column>
          <el-table-column label="批号"
                           prop="batchNo"
                           width="180"
@@ -179,12 +198,25 @@
          <el-table-column label="入库数量"
                           prop="stockInNum"
                           align="center"
                           v-else />
                           v-else>
            <template #default="scope">
              {{ scope.row.direction === 'out' ? '-' : scope.row.stockInNum }}
            </template>
          </el-table-column>
          <el-table-column label="出库数量"
                           prop="totalStockOut"
                           width="100"
                           align="center"
                           v-if="searchForm.reportType === 'inout'" />
          <el-table-column label="出库数量"
                           prop="stockOutNum"
                           width="100"
                           align="center"
                           v-else>
            <template #default="scope">
              {{ scope.row.direction === 'out' ? scope.row.stockOutNum : '-' }}
            </template>
          </el-table-column>
          <el-table-column label="现在库存"
                           prop="currentStock"
                           align="center" />
@@ -193,10 +225,10 @@
                           v-if="searchForm.reportType !== 'inout'"
                           show-overflow-tooltip>
            <template #default="scope">
              {{ getRecordType(scope.row.recordType) }}
              {{ getRecordType(scope.row) }}
            </template>
          </el-table-column>
          <el-table-column label="入库人"
          <el-table-column label="经手人"
                           prop="createBy"
                           width="80"
                           v-if="searchForm.reportType !== 'inout'"
@@ -223,6 +255,7 @@
  } from "@/api/inventoryManagement/stockInventory.js";
  import {
    findAllQualifiedStockInRecordTypeOptions,
    findAllQualifiedStockOutRecordTypeOptions,
    // findAllUnQualifiedStockInRecordTypeOptions,
  } from "@/api/basicData/enum.js";
@@ -237,6 +270,7 @@
    singleDate: "",
    dateRange: [],
    monthRange: [],
    purchaseOrderNo: "",
  });
  const reportData = ref({
@@ -253,12 +287,14 @@
  const total = ref(0);
  const stockRecordTypeOptions = ref([]);
  const stockOutRecordTypeOptions = ref([]);
  const getRecordType = recordType => {
    return (
      stockRecordTypeOptions.value.find(item => item.value === recordType)
        ?.label || ""
    );
  const getRecordType = row => {
    const options =
      row.direction === "out"
        ? stockOutRecordTypeOptions.value
        : stockRecordTypeOptions.value;
    return options.find(item => item.value === row.recordType)?.label || "";
  };
  // 获取来源类型选项
@@ -271,6 +307,9 @@
      //     ...res.data,
      //   ];
      // });
    });
    findAllQualifiedStockOutRecordTypeOptions().then(res => {
      stockOutRecordTypeOptions.value = res.data;
    });
  };
@@ -404,6 +443,7 @@
      endMonth: "",
      startDate: "",
      endDate: "",
      purchaseOrderNo: searchForm.purchaseOrderNo,
    };
    if (searchForm.reportType === "daily") {
@@ -425,6 +465,7 @@
    searchForm.singleDate = "";
    searchForm.dateRange = [];
    searchForm.monthRange = [];
    searchForm.purchaseOrderNo = "";
    reportData.value = {
      summary: null,
      chartData: null,