From 9c2001bb140e12bd0d3a234c1e0467049cd8bb1d Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期三, 25 三月 2026 10:45:58 +0800
Subject: [PATCH] 标准成本导入页面

---
 src/views/costAccounting/standardCostImport/index.vue |  336 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 336 insertions(+), 0 deletions(-)

diff --git a/src/views/costAccounting/standardCostImport/index.vue b/src/views/costAccounting/standardCostImport/index.vue
new file mode 100644
index 0000000..4bfbb7f
--- /dev/null
+++ b/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: "鎸変骇鍝佹洿鏂颁汉宸ヤ笌璐圭敤鍙e緞",
+    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>

--
Gitblit v1.9.3