yyb
20 小时以前 9c2001bb140e12bd0d3a234c1e0467049cd8bb1d
标准成本导入页面
已添加1个文件
336 ■■■■■ 文件已修改
src/views/costAccounting/standardCostImport/index.vue 336 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/costAccounting/standardCostImport/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,336 @@
// æ ‡å‡†æˆæœ¬å¯¼å…¥
<template>
  <div class="standard-cost-ledger-page">
    <el-card shadow="never" class="query-card">
      <el-form :inline="true" :model="queryForm">
        <el-form-item label="导入月份">
          <el-date-picker
            v-model="queryForm.month"
            type="month"
            value-format="YYYY-MM"
            placeholder="选择月份"
            @change="handleQuery"
          />
        </el-form-item>
        <el-form-item label="批次号">
          <el-select
            v-model="queryForm.batchNo"
            clearable
            filterable
            placeholder="全部批次"
            style="width: 220px"
            @change="handleQuery"
          >
            <el-option
              v-for="item in batchOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery">查询</el-button>
          <el-button @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <el-card shadow="never" class="ledger-card">
      <template #header>
        <div class="card-header">
          <span>标准成本导入台账</span>
          <span class="meta">共 {{ filteredLedgerRows.length }} æ¡å¯¼å…¥è®°å½•</span>
        </div>
      </template>
      <el-table
        :data="filteredLedgerRows"
        border
        highlight-current-row
        @current-change="handleLedgerRowChange"
      >
        <el-table-column prop="month" label="月份" width="120" />
        <el-table-column prop="batchNo" label="批次号" width="180" />
        <el-table-column prop="importTime" label="导入时间" min-width="180" />
        <el-table-column prop="importUser" label="导入人" width="120" />
        <el-table-column prop="remark" label="备注" min-width="220" show-overflow-tooltip />
      </el-table>
    </el-card>
    <el-card shadow="never" class="matrix-card">
      <template #header>
        <div class="card-header">
          <span>标准成本明细({{ activeLedgerRow?.month || "-" }})</span>
          <span class="meta">批次:{{ activeLedgerRow?.batchNo || "-" }}</span>
        </div>
      </template>
      <el-table :data="matrixRows" border class="matrix-table" :row-class-name="getRowClassName">
        <el-table-column prop="itemName" label="项目名称" min-width="180" />
        <el-table-column
          v-for="column in productColumns"
          :key="column.key"
          :prop="column.key"
          :label="column.label"
          min-width="130"
          align="right"
        >
          <template #default="{ row }">
            {{ formatNumber(row[column.key]) }}
          </template>
        </el-table-column>
      </el-table>
    </el-card>
  </div>
</template>
<script setup>
import { computed, ref } from "vue";
const getCurrentMonth = () => {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, "0");
  return `${year}-${month}`;
};
const queryForm = ref({
  month: getCurrentMonth(),
  batchNo: "",
});
const ledgerRows = ref([
  {
    id: 1,
    month: "2026-01",
    batchNo: "SC-202601-001",
    importTime: "2026-01-05 09:18:22",
    importUser: "王会计",
    remark: "月初标准成本导入",
    matrix: buildMatrixData(),
  },
  {
    id: 2,
    month: "2026-02",
    batchNo: "SC-202602-001",
    importTime: "2026-02-03 10:08:16",
    importUser: "李会计",
    remark: "按产品更新人工与费用口径",
    matrix: buildMatrixData({
      yieldA35: 1050,
      yieldA50: 920,
      yieldBoard: 840,
      directMaterialA35: 12.4,
      directMaterialA50: 11.9,
      directMaterialBoard: 9.2,
    }),
  },
  {
    id: 3,
    month: "2026-03",
    batchNo: "SC-202603-001",
    importTime: "2026-03-04 14:32:09",
    importUser: "王会计",
    remark: "按月导入标准成本",
    matrix: buildMatrixData({
      yieldA35: 1100,
      yieldA50: 960,
      yieldBoard: 900,
      directMaterialA35: 12.9,
      directMaterialA50: 12.1,
      directMaterialBoard: 9.6,
    }),
  },
]);
const activeLedgerId = ref(ledgerRows.value[0]?.id || null);
const batchOptions = computed(() => {
  return ledgerRows.value.map((row) => ({
    label: `${row.batchNo}(${row.month})`,
    value: row.batchNo,
  }));
});
const filteredLedgerRows = computed(() => {
  return ledgerRows.value.filter((row) => {
    const byMonth = !queryForm.value.month || row.month === queryForm.value.month;
    const byBatch = !queryForm.value.batchNo || row.batchNo === queryForm.value.batchNo;
    return byMonth && byBatch;
  });
});
const activeLedgerRow = computed(() => {
  const list = filteredLedgerRows.value;
  const target = list.find((row) => row.id === activeLedgerId.value);
  return target || list[0] || null;
});
const matrixRows = computed(() => activeLedgerRow.value?.matrix || []);
const productColumns = [
  { key: "a35", label: "加气块-A3.5" },
  { key: "a50", label: "加气块-A5.0" },
  { key: "board", label: "板材" },
  { key: "total", label: "综合" },
];
function buildMatrixData(override = {}) {
  const yieldA35 = override.yieldA35 ?? 980;
  const yieldA50 = override.yieldA50 ?? 860;
  const yieldBoard = override.yieldBoard ?? 800;
  const directMaterialA35 = override.directMaterialA35 ?? 12.6;
  const directMaterialA50 = override.directMaterialA50 ?? 11.7;
  const directMaterialBoard = override.directMaterialBoard ?? 9.1;
  const manufacturingA35 = 3.2;
  const manufacturingA50 = 3.5;
  const manufacturingBoard = 2.8;
  const mgmtA35 = 1.4;
  const mgmtA50 = 1.2;
  const mgmtBoard = 1.0;
  const salesA35 = 0.9;
  const salesA50 = 0.8;
  const salesBoard = 0.7;
  const financeA35 = 0.4;
  const financeA50 = 0.3;
  const financeBoard = 0.2;
  const offSeasonA35 = 1.1;
  const offSeasonA50 = 1.0;
  const offSeasonBoard = 0.8;
  const subtotalA35 = directMaterialA35 + manufacturingA35;
  const subtotalA50 = directMaterialA50 + manufacturingA50;
  const subtotalBoard = directMaterialBoard + manufacturingBoard;
  const totalA35 = subtotalA35 + mgmtA35 + salesA35 + financeA35 + offSeasonA35;
  const totalA50 = subtotalA50 + mgmtA50 + salesA50 + financeA50 + offSeasonA50;
  const totalBoard = subtotalBoard + mgmtBoard + salesBoard + financeBoard + offSeasonBoard;
  return [
    {
      itemName: "产量",
      a35: yieldA35,
      a50: yieldA50,
      board: yieldBoard,
      total: yieldA35 + yieldA50 + yieldBoard,
    },
    {
      itemName: "直接材料单方成本",
      a35: directMaterialA35,
      a50: directMaterialA50,
      board: directMaterialBoard,
      total: (directMaterialA35 + directMaterialA50 + directMaterialBoard) / 3,
    },
    {
      itemName: "制造费用",
      a35: manufacturingA35,
      a50: manufacturingA50,
      board: manufacturingBoard,
      total: (manufacturingA35 + manufacturingA50 + manufacturingBoard) / 3,
    },
    {
      itemName: "生产成本小计",
      a35: subtotalA35,
      a50: subtotalA50,
      board: subtotalBoard,
      total: (subtotalA35 + subtotalA50 + subtotalBoard) / 3,
      isSubtotal: true,
    },
    {
      itemName: "管理费用",
      a35: mgmtA35,
      a50: mgmtA50,
      board: mgmtBoard,
      total: (mgmtA35 + mgmtA50 + mgmtBoard) / 3,
    },
    {
      itemName: "销售费用",
      a35: salesA35,
      a50: salesA50,
      board: salesBoard,
      total: (salesA35 + salesA50 + salesBoard) / 3,
    },
    {
      itemName: "财务费用",
      a35: financeA35,
      a50: financeA50,
      board: financeBoard,
      total: (financeA35 + financeA50 + financeBoard) / 3,
    },
    {
      itemName: "淡季费用-生产成本",
      a35: offSeasonA35,
      a50: offSeasonA50,
      board: offSeasonBoard,
      total: (offSeasonA35 + offSeasonA50 + offSeasonBoard) / 3,
    },
    {
      itemName: "合计",
      a35: totalA35,
      a50: totalA50,
      board: totalBoard,
      total: (totalA35 + totalA50 + totalBoard) / 3,
    },
  ];
}
function handleQuery() {
  if (filteredLedgerRows.value.length > 0) {
    activeLedgerId.value = filteredLedgerRows.value[0].id;
    return;
  }
  activeLedgerId.value = null;
}
function handleReset() {
  queryForm.value.month = getCurrentMonth();
  queryForm.value.batchNo = "";
  handleQuery();
}
function handleLedgerRowChange(row) {
  if (!row) return;
  activeLedgerId.value = row.id;
}
function getRowClassName({ row }) {
  return row.isSubtotal ? "is-subtotal-row" : "";
}
function formatNumber(value) {
  if (typeof value !== "number") return "-";
  if (Number.isInteger(value)) return value.toLocaleString("zh-CN");
  return value.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
</script>
<style scoped>
.standard-cost-ledger-page {
  padding: 16px;
  background: #f6f8fa;
  min-height: calc(100vh - 100px);
}
.query-card,
.ledger-card,
.matrix-card {
  margin-bottom: 16px;
}
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 16px;
  font-weight: 600;
}
.meta {
  font-size: 13px;
  color: #909399;
  font-weight: 400;
}
.matrix-table :deep(.is-subtotal-row td) {
  background: #fff200 !important;
}
</style>