<template>
  <div :class="['bom-details-page', { 'bom-details-page--embed': isEmbedMode }]">
    <!-- 嵌入抽屉：概览统计 -->
    <div v-if="isEmbedMode" class="bom-summary">
      <div class="bom-summary__hero">
        <div class="bom-summary__icon">
          <i class="el-icon-s-grid"></i>
        </div>
        <div class="bom-summary__meta">
          <span class="bom-summary__label">生产令号</span>
          <span class="bom-summary__order">{{ embedOrderNo || '—' }}</span>
          <span v-if="embedOrderName" class="bom-summary__name">{{ embedOrderName }}</span>
        </div>
      </div>
      <div class="bom-summary__stats">
        <div class="bom-stat-card">
          <span class="bom-stat-card__num">{{ bomStats.parentCount }}</span>
          <span class="bom-stat-card__txt">总成</span>
        </div>
        <div class="bom-stat-card">
          <span class="bom-stat-card__num">{{ bomStats.childCount }}</span>
          <span class="bom-stat-card__txt">明细</span>
        </div>
        <div class="bom-stat-card bom-stat-card--ok">
          <span class="bom-stat-card__num">{{ bomStats.existsCount }}</span>
          <span class="bom-stat-card__txt">已存在</span>
        </div>
        <div class="bom-stat-card bom-stat-card--warn">
          <span class="bom-stat-card__num">{{ bomStats.missingCount }}</span>
          <span class="bom-stat-card__txt">未建档</span>
        </div>
      </div>
    </div>

    <!-- 搜索区 -->
    <el-form
      :model="queryParams"
      ref="queryForm"
      size="small"
      :inline="true"
      v-show="showSearch"
      :label-width="isEmbedMode ? '72px' : '68px'"
      class="bom-search"
    >
      <el-form-item label="图号" prop="partNumber">
        <el-input v-model="queryParams.partNumber" placeholder="子项图号" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item label="父级图号" prop="fnumber">
        <el-input v-model="queryParams.fnumber" placeholder="父项图号" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item label="名称" prop="name">
        <el-input v-model="queryParams.name" placeholder="子项名称" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item v-if="!isEmbedMode" label="数量" prop="quantity">
        <el-input v-model="queryParams.quantity" placeholder="子项分子" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item v-if="!isEmbedMode" label="材料" prop="material">
        <el-input v-model="queryParams.material" placeholder="材料" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item v-if="!isEmbedMode" label="是否存在" prop="unitWeight">
        <el-select v-model="queryParams.unitWeight" placeholder="全部" clearable style="width: 100px">
          <el-option label="是" value="是" />
          <el-option label="否" value="否" />
        </el-select>
      </el-form-item>
      <el-form-item v-if="!isEmbedMode" label="生产令号" prop="totalWeight">
        <el-input v-model="queryParams.totalWeight" placeholder="生产令号" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item v-if="!isEmbedMode" label="备注" prop="remarks">
        <el-input v-model="queryParams.remarks" placeholder="备注" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <!-- 工具栏 -->
    <el-row :gutter="10" class="mb8 bom-toolbar">
      <el-col :span="1.5">
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:details:add']">新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['system:details:remove']">删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['system:details:export']">导出</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['system:details:import']">导入</el-button>
      </el-col>
      <el-col :span="3">
        <el-input v-model="groupName" placeholder="请输入上传分组" size="mini" clearable />
      </el-col>
      <el-col :span="1.5">
        <el-button type="info" plain icon="el-icon-upload2" size="mini" @click="updateFBMaterial" v-hasPermi="['system:details:updateFBMaterial']">更新物料清单</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="primary" plain icon="el-icon-view" size="mini" @click="getBomUploadStatus" v-hasPermi="['system:details:viewGetBomUploadStatus']">查看BOM上传状态</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button size="mini" icon="el-icon-arrow-down" :disabled="!detailsList.length" @click="expandAllRows">全部展开</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button size="mini" icon="el-icon-arrow-up" :disabled="!detailsList.length" @click="collapseAllRows">全部收起</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
    </el-row>

    <!-- BOM 树形表格 -->
    <div class="bom-table-wrap">
      <el-table
        ref="bomTable"
        v-loading="loading"
        row-key="id"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
        :data="detailsList"
        border
        stripe
        size="small"
        class="bom-tree-table"
        :header-cell-style="tableHeaderStyle"
        empty-text="暂无 BOM 明细数据"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="46" align="center" fixed="left" />
        <el-table-column label="物料编码" min-width="220" show-overflow-tooltip fixed="left" class-name="bom-code-column">
          <template slot-scope="scope">
            <div class="bom-code-cell">
              <span :class="['bom-code-text', { 'bom-code-text--assembly': isParentRow(scope.row) }]">
                {{ rowMaterialCode(scope.row) }}
              </span>
              <span
                v-if="isParentRow(scope.row) && scope.row.children && scope.row.children.length"
                class="bom-code-count"
              >{{ scope.row.children.length }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="物料名称" min-width="200" show-overflow-tooltip fixed="left" class-name="bom-name-column">
          <template slot-scope="scope">
            <span :class="['bom-name-text', { 'bom-name-text--assembly': isParentRow(scope.row) }]">
              {{ rowMaterialName(scope.row) }}
            </span>
          </template>
        </el-table-column>
        <el-table-column v-if="!isEmbedMode" label="生产令号" align="center" prop="totalWeight" min-width="110" show-overflow-tooltip />
        <el-table-column label="用量" width="80" align="center">
          <template slot-scope="scope">
            <span v-if="!isParentRow(scope.row)" class="bom-qty">{{ formatQuantity(scope.row) }}</span>
            <span v-else class="bom-cell-empty">—</span>
          </template>
        </el-table-column>
        <el-table-column v-if="showPartdiagramColumns" label="部件编码" align="left" min-width="120" show-overflow-tooltip>
          <template slot-scope="scope">
            <span v-if="!isParentRow(scope.row)" class="bom-code-text">{{ rowField(scope.row, 'partdiagramCode') }}</span>
            <span v-else class="bom-cell-empty">—</span>
          </template>
        </el-table-column>
        <el-table-column v-if="showPartdiagramColumns" label="部件名称" align="left" min-width="120" show-overflow-tooltip>
          <template slot-scope="scope">
            <span v-if="!isParentRow(scope.row)" class="bom-name-text">{{ rowField(scope.row, 'partdiagramName') }}</span>
            <span v-else class="bom-cell-empty">—</span>
          </template>
        </el-table-column>
        <el-table-column label="属性" width="72" align="center">
          <template slot-scope="scope">
            <el-tag v-if="scope.row.stats" size="mini" :type="statsTagType(scope.row.stats)" effect="plain" class="bom-stats-tag">
              {{ scope.row.stats }}
            </el-tag>
            <span v-else class="bom-cell-empty">—</span>
          </template>
        </el-table-column>
        <el-table-column label="材料" align="center" min-width="90" show-overflow-tooltip>
          <template slot-scope="scope">{{ rowField(scope.row, 'material') }}</template>
        </el-table-column>
        <el-table-column v-if="showWareHouseColumn" label="单位" align="center" width="72" show-overflow-tooltip>
          <template slot-scope="scope">{{ rowField(scope.row, 'wareHouse') }}</template>
        </el-table-column>
        <el-table-column v-if="showWeightColumn" label="单重" width="72" align="right">
          <template slot-scope="scope">{{ formatSingleWeight(scope.row) }}</template>
        </el-table-column>
        <el-table-column v-if="showBomTypeColumn" label="BOM类型" align="center" width="88" show-overflow-tooltip>
          <template slot-scope="scope">{{ rowField(scope.row, 'bomType') }}</template>
        </el-table-column>
        <el-table-column v-if="showImportanceColumn" label="重要程度" align="center" width="88" show-overflow-tooltip>
          <template slot-scope="scope">{{ rowField(scope.row, 'stateImportance') }}</template>
        </el-table-column>
        <el-table-column label="是否存在" width="88" align="center">
          <template slot-scope="scope">
            <span v-if="!scope.row.unitWeight" class="bom-cell-empty">—</span>
            <span v-else :class="['bom-exists', scope.row.unitWeight === '是' ? 'bom-exists--yes' : 'bom-exists--no']">
              <i :class="scope.row.unitWeight === '是' ? 'el-icon-circle-check' : 'el-icon-warning-outline'"></i>
              {{ scope.row.unitWeight }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="备注" align="left" min-width="120" show-overflow-tooltip>
          <template slot-scope="scope">{{ rowField(scope.row, 'remarks') }}</template>
        </el-table-column>
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width bom-op-column" width="200" fixed="right">
          <template slot-scope="scope">
            <el-button size="mini" type="text" @click="handAddSon(scope.row)" icon="el-icon-plus">添加子集</el-button>
            <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:material:edit']">修改</el-button>
            <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:details:remove']">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      :pageSizes="[50, 100, 1000, 5000]"
      @pagination="getList"
    />

    <!-- 添加或修改 bom 明细对话框 -->
    <el-dialog :title="title" :visible.sync="open" width="520px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="88px">
        <el-form-item label="生产令号" prop="totalWeight">
          <el-input v-model="form.totalWeight" placeholder="生产令号" :disabled="isDisabled" />
        </el-form-item>
        <el-form-item label="父级图号" prop="fnumber">
          <el-input v-model="form.fnumber" placeholder="父级图号" :disabled="isDisabled" />
        </el-form-item>
        <el-form-item label="父级名称" prop="fname">
          <el-input v-model="form.fname" placeholder="父级名称" :disabled="isDisabled" />
        </el-form-item>
        <el-form-item label="子项图号" prop="partNumber">
          <el-input v-model="form.partNumber" placeholder="请输入图号" />
        </el-form-item>
        <el-form-item label="子项名称" prop="name">
          <el-input v-model="form.name" placeholder="请输入名称" />
        </el-form-item>
        <el-form-item label="属性" prop="stats">
          <el-select v-model="form.stats" placeholder="请选择属性" style="width: 100%">
            <el-option label="自制" value="自制" />
            <el-option label="委外" value="委外" />
            <el-option label="外购" value="外购" />
          </el-select>
        </el-form-item>
        <el-form-item label="子项分子" prop="quantity">
          <el-input v-model="form.quantity" placeholder="分子" />
        </el-form-item>
        <el-form-item label="子项分母" prop="denominator">
          <el-input v-model="form.denominator" placeholder="分母" />
        </el-form-item>
        <el-form-item label="材料" prop="material">
          <el-input v-model="form.material" placeholder="请输入材料" />
        </el-form-item>
        <el-form-item label="是否存在" prop="unitWeight">
          <el-select v-model="form.unitWeight" placeholder="请选择" style="width: 100%">
            <el-option label="是" value="是" />
            <el-option label="否" value="否" />
          </el-select>
        </el-form-item>
        <el-form-item label="备注" prop="remarks">
          <el-input v-model="form.remarks" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>

    <!-- 导入对话框 -->
    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
      <el-upload
        ref="upload"
        :limit="1"
        accept=".xlsx, .xls"
        :headers="upload.headers"
        :action="upload.url + '?updateSupport=' + upload.updateSupport"
        :disabled="upload.isUploading"
        :on-progress="handleFileUploadProgress"
        :on-success="handleFileSuccess"
        :auto-upload="false"
        drag
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <div class="el-upload__tip text-center" slot="tip">
          <div class="el-upload__tip" slot="tip">
            <el-checkbox v-model="upload.updateSupport" />
            是否更新已经存在的物料数据
          </div>
          <span>仅允许导入 xls、xlsx 格式文件。</span>
          <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
        </div>
      </el-upload>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitFileForm">确 定</el-button>
        <el-button @click="upload.open = false">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { listDetails, getDetails, delDetails, addDetails, updateDetails, updateFBl, viewGetBomUploadStatus } from "@/api/system/details";
import { getToken } from "@/utils/auth";

export default {
  name: "Details",
  props: {
    params: {
      type: Object,
      default: null,
    },
  },
  data() {
    return {
      isDisabled: false,
      buttonLoading: false,
      loading: true,
      ids: [],
      selectedRows: [],
      fnumbers: [],
      single: true,
      multiple: true,
      showSearch: true,
      total: 0,
      detailsList: [],
      title: "",
      open: false,
      queryParams: {
        pageNum: 1,
        pageSize: 1000,
        partNumber: undefined,
        fname: undefined,
        fnumber: undefined,
        fName: undefined,
        fNumber: undefined,
        name: undefined,
        stats: undefined,
        quantity: undefined,
        denominator: undefined,
        material: undefined,
        unitWeight: undefined,
        totalWeight: undefined,
        remarks: undefined,
      },
      form: {},
      upload: {
        open: false,
        title: "",
        isUploading: false,
        updateSupport: 0,
        headers: { Authorization: "Bearer " + getToken() },
        url: process.env.VUE_APP_BASE_API + "/system/details/importData",
      },
      rules: {},
      groupName: "",
    };
  },
  computed: {
    isEmbedMode() {
      return !!(this.params && this.params.productionOrderNo);
    },
    embedOrderNo() {
      return (this.params && this.params.productionOrderNo) || this.queryParams.totalWeight || "";
    },
    embedOrderName() {
      return (this.params && this.params.productionName) || "";
    },
    tableHeaderStyle() {
      return {
        background: "#eef2f7",
        color: "#1a2942",
        fontWeight: "600",
        fontSize: "12px",
        borderBottom: "2px solid #c9a227",
      };
    },
    bomStats() {
      let parentCount = 0;
      let childCount = 0;
      let existsCount = 0;
      let missingCount = 0;
      const walk = (rows) => {
        if (!Array.isArray(rows)) return;
        rows.forEach((row) => {
          if (this.isParentRow(row)) {
            parentCount += 1;
          } else {
            childCount += 1;
            if (row.unitWeight === "是") existsCount += 1;
            else if (row.unitWeight === "否") missingCount += 1;
          }
          if (row.children && row.children.length) {
            walk(row.children);
          }
        });
      };
      walk(this.detailsList);
      return { parentCount, childCount, existsCount, missingCount };
    },
    flatBomRows() {
      const result = [];
      const walk = (rows) => {
        if (!Array.isArray(rows)) return;
        rows.forEach((row) => {
          result.push(row);
          if (row.children && row.children.length) walk(row.children);
        });
      };
      walk(this.detailsList);
      return result;
    },
    showPartdiagramColumns() {
      return this.hasFieldData(["partdiagramCode", "partdiagramName"]);
    },
    showWareHouseColumn() {
      return this.hasFieldData(["wareHouse"]);
    },
    showWeightColumn() {
      return this.flatBomRows.some((row) => row.danZhong != null || row.singleWeghit != null);
    },
    showBomTypeColumn() {
      return this.hasFieldData(["bomType"]);
    },
    showImportanceColumn() {
      return this.hasFieldData(["stateImportance"]);
    },
  },
  created() {
    this.queryParams.totalWeight = "";
    if (this.params && this.params.productionOrderNo) {
      this.queryParams.totalWeight = this.params.productionOrderNo;
      this.showSearch = false;
    }
    this.getList();
  },
  methods: {
    isParentRow(row) {
      return !!(row && row.children && row.children.length);
    },
    expandAllRows() {
      const table = this.$refs.bomTable;
      if (!table) return;
      this.detailsList.forEach((row) => {
        table.toggleRowExpansion(row, true);
      });
    },
    collapseAllRows() {
      const table = this.$refs.bomTable;
      if (!table) return;
      this.detailsList.forEach((row) => {
        table.toggleRowExpansion(row, false);
      });
    },
    hasFieldData(keys) {
      return this.flatBomRows.some((row) => {
        return keys.some((key) => {
          const val = row[key];
          return val !== undefined && val !== null && val !== "";
        });
      });
    },
    /** 取字段原始值（接口用，空则返回 ''，不用展示占位符 —） */
    rowFieldValue(row, ...keys) {
      if (!row) return "";
      for (const key of keys) {
        const val = row[key];
        if (val !== undefined && val !== null && val !== "") {
          return String(val).trim();
        }
      }
      return "";
    },
    /** 总成行：当前行 → 子行 依次取字段（展示与上传共用） */
    pickAssemblyField(row, ...keys) {
      if (!row) return "";
      let val = this.rowFieldValue(row, ...keys);
      if (val) return val;
      if (row.children && row.children.length) {
        for (const child of row.children) {
          val = this.rowFieldValue(child, ...keys);
          if (val) return val;
        }
      }
      if (row.parentCodeAndName) {
        const idx = row.parentCodeAndName.lastIndexOf("_");
        if (idx >= 0 && keys.some((k) => k === "fnumber" || k === "fNumber")) {
          const tail = row.parentCodeAndName.slice(idx + 1).trim();
          if (tail && tail !== "null") return tail;
        }
      }
      return "";
    },
    findParentRow(rows, targetRow) {
      if (!rows || !targetRow || targetRow.id == null) return null;
      for (const row of rows) {
        if (row.children && row.children.length) {
          if (row.children.some((child) => child.id == targetRow.id)) return row;
          const found = this.findParentRow(row.children, targetRow);
          if (found) return found;
        }
      }
      return null;
    },
    /** 更新物料清单：取父级 fnumber/fname/totalWeight，字段与后端 BomDetails 一致 */
    buildFbUploadPayload(row) {
      if (!row) return null;
      const parent = this.isParentRow(row) ? row : this.findParentRow(this.detailsList, row);
      const src = parent || row;
      const fnumber = String(src.fnumber || src.fNumber || row.fnumber || row.fNumber || "").trim();
      const fname = String(src.fname || src.fName || row.fname || row.fName || "").trim();
      const totalWeight = String(
        row.totalWeight || src.totalWeight || this.queryParams.totalWeight || ""
      ).trim();
      return {
        fnumber,
        fname,
        totalWeight,
        groupName: this.groupName.trim(),
      };
    },
    /** 解析行上的生产令号（totalWeight 字段） */
    resolveTotalWeight(row) {
      const pageOrderNo = this.queryParams.totalWeight;
      if (!row) return pageOrderNo || "";
      // 总成行优先从子行取令号（子行 totalWeight 为生产令号）
      if (this.isParentRow(row) && row.children && row.children.length) {
        for (const child of row.children) {
          if (child.totalWeight) return child.totalWeight;
        }
      }
      if (row.totalWeight) return row.totalWeight;
      return pageOrderNo || "";
    },
    rowField(row, ...keys) {
      if (!row) return "—";
      for (const key of keys) {
        const val = row[key];
        if (val !== undefined && val !== null && val !== "") {
          return val;
        }
      }
      return "—";
    },
    rowMaterialCode(row) {
      if (this.isParentRow(row)) {
        const code = this.rowFieldValue(row, "fnumber", "fNumber");
        return code || "—";
      }
      const code = this.rowFieldValue(row, "partNumber");
      return code || "—";
    },
    rowMaterialName(row) {
      if (this.isParentRow(row)) {
        const name = this.pickAssemblyField(row, "fname", "fName");
        return name || "—";
      }
      const name = this.rowFieldValue(row, "name");
      return name || "—";
    },
    formatQuantity(row) {
      const num = row.quantity;
      const den = row.denominator;
      if (num == null && den == null) return "—";
      // 早期数据：分子为空、分母为 1 时，按 1/1 展示
      const displayNum = num != null ? num : (den != null ? 1 : "—");
      const displayDen = den != null ? den : "—";
      return displayNum + "/" + displayDen;
    },
    formatNumber(val) {
      if (val == null || val === "") return "—";
      return val;
    },
    formatSingleWeight(row) {
      if (this.isParentRow(row)) {
        return this.formatNumber(row.danZhong);
      }
      const val = row.singleWeghit != null ? row.singleWeghit : row.danZhong;
      return this.formatNumber(val);
    },
    statsTagType(stats) {
      const map = { 自制: "success", 委外: "warning", 外购: "info" };
      return map[stats] || "";
    },
    buildQueryParams() {
      const params = { ...this.queryParams };
      if (!params.fNumber && params.fnumber) {
        params.fNumber = params.fnumber;
      }
      if (!params.fName && params.fname) {
        params.fName = params.fname;
      }
      return params;
    },
    normalizeFormFields(form) {
      const payload = { ...form };
      if (!payload.fNumber && payload.fnumber) {
        payload.fNumber = payload.fnumber;
      }
      if (!payload.fName && payload.fname) {
        payload.fName = payload.fname;
      }
      if (payload.fnumber == null && payload.fNumber != null) {
        payload.fnumber = payload.fNumber;
      }
      if (payload.fname == null && payload.fName != null) {
        payload.fname = payload.fName;
      }
      return payload;
    },
    getList() {
      this.loading = true;
      listDetails(this.buildQueryParams())
        .then((response) => {
          this.detailsList = response.rows || [];
          this.total = response.total || 0;
        })
        .finally(() => {
          this.loading = false;
        });
    },
    handleImport() {
      this.upload.title = "明细导入";
      this.upload.open = true;
    },
    importTemplate() {
      this.download("system/details/importTemplate", {}, "details_template_" + new Date().getTime() + ".xlsx");
    },
    handleFileUploadProgress() {
      this.upload.isUploading = true;
    },
    handleFileSuccess(response) {
      this.upload.open = false;
      this.upload.isUploading = false;
      this.$refs.upload.clearFiles();
      this.$alert(
        "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>",
        "导入结果",
        { dangerouslyUseHTMLString: true }
      );
      this.getList();
    },
    submitFileForm() {
      this.$refs.upload.submit();
    },
    cancel() {
      this.open = false;
      this.reset();
    },
    reset() {
      this.form = {
        id: undefined,
        fnumber: undefined,
        fname: undefined,
        fNumber: undefined,
        fName: undefined,
        partNumber: undefined,
        name: undefined,
        stats: undefined,
        quantity: undefined,
        denominator: undefined,
        material: undefined,
        unitWeight: undefined,
        totalWeight: undefined,
        remarks: undefined,
      };
      this.resetForm("form");
    },
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    resetQuery() {
      const lockedOrder = this.isEmbedMode ? this.queryParams.totalWeight : undefined;
      this.resetForm("queryForm");
      if (lockedOrder) {
        this.queryParams.totalWeight = lockedOrder;
      }
      this.handleQuery();
    },
    handleSelectionChange(selection) {
      this.selectedRows = selection || [];
      this.ids = this.selectedRows.map((item) => item.id);
      this.fnumbers = this.selectedRows.map((item) => item.fnumber || item.fNumber || "");
      this.single = this.selectedRows.length !== 1;
      this.multiple = !this.selectedRows.length;
    },
    handleAdd() {
      this.reset();
      this.isDisabled = false;
      this.open = true;
      this.title = "添加bom明细";
    },
    updateFBMaterial() {
      this.loading = true;
      if (!this.selectedRows || this.selectedRows.length === 0) {
        this.$modal.msgError("请先选择要上传的行!");
        this.loading = false;
        return;
      }
      if (!this.groupName || !this.groupName.trim()) {
        this.$modal.msgError("请填写上传分组!");
        this.loading = false;
        return;
      }
      const seen = {};
      const selectedData = [];
      this.selectedRows.forEach((row) => {
        const payload = this.buildFbUploadPayload(row);
        if (!payload) return;
        const key = [payload.fnumber, payload.fname, payload.totalWeight].join("|");
        if (seen[key]) return;
        seen[key] = true;
        selectedData.push(payload);
      });
      if (!selectedData.length) {
        this.$modal.msgError("未生成上传数据，请重新选择!");
        this.loading = false;
        return;
      }
      if (selectedData.some((row) => !row.totalWeight)) {
        this.$modal.msgError("生产令号(totalWeight)不能为空!");
        this.loading = false;
        return;
      }
      updateFBl(selectedData)
        .then((response) => {
          const list = Array.isArray(response.data) ? response.data : [];
          this.resNotice(list.length, response.msg);
        })
        .catch((error) => {
          console.error("更新BOM失败:", error);
          this.$modal.msgError("更新BOM失败，请重试!");
        })
        .finally(() => {
          this.loading = false;
        });
    },
    findRowById(rows, id) {
      for (const row of rows || []) {
        if (row.id === id) return row;
        if (row.children) {
          const found = this.findRowById(row.children, id);
          if (found) return found;
        }
      }
      return {};
    },
    getBomUploadStatus() {
      this.loading = true;
      this.reset();
      if (!this.ids || this.ids.length === 0) {
        this.$modal.msgError("请先选择要查询的行!");
        this.loading = false;
        return;
      }
      const firstSelectedItem = this.findRowById(this.detailsList, this.ids[0]);
      const rooteProdet = this.resolveTotalWeight(firstSelectedItem);
      if (!rooteProdet) {
        this.$modal.msgError("未获取到生产令号(totalWeight)，请检查选中行或查询条件!");
        this.loading = false;
        return;
      }
      viewGetBomUploadStatus(rooteProdet)
        .then((response) => {
          const bomData = response.data;
          if (bomData && bomData.items) {
            this.showBomUploadStatus(bomData.items);
          } else {
            this.$modal.msgWarning("未获取到BOM上传状态数据");
          }
        })
        .catch(() => {
          this.$modal.msgError("获取BOM上传状态失败，请重试!");
        })
        .finally(() => {
          this.loading = false;
        });
    },
    showBomUploadStatus(items) {
      if (!items || items.length === 0) {
        this.$modal.msgWarning("暂无BOM上传状态数据");
        return;
      }
      const successCount = items.filter((item) => item.code === "200").length;
      const existCount = items.filter((item) => item.code === "100").length;
      const failedCount = items.filter((item) => item.code === "300").length;
      const totalCount = items.length;
      let content = `
        <div style="margin-bottom: 15px; padding: 10px; background-color: #f5f7fa; border-radius: 4px;">
          <div><strong>项目编码:</strong> ${(items[0] && items[0].projectCode) || "未知"}</div>
          <div><strong>总计:</strong> ${totalCount} 条</div>
          <div><strong>成功上传:</strong> <span style="color: green;">${successCount}</span> 条</div>
          <div><strong>已存在:</strong> <span style="color: blue;">${existCount}</span> 条</div>
          <div><strong>上传失败:</strong> <span style="color: red;">${failedCount}</span> 条</div>
        </div>
        <div style="max-height: 400px; overflow-y: auto;">
      `;
      items.forEach((item, index) => {
        let statusColor, statusText, backgroundColor;
        switch (item.code) {
          case "100":
            statusColor = "blue";
            statusText = "已存在";
            backgroundColor = "#f0f8ff";
            break;
          case "200":
            statusColor = "green";
            statusText = "成功上传";
            backgroundColor = "#f0f9ff";
            break;
          case "300":
            statusColor = "red";
            statusText = "上传失败";
            backgroundColor = "#fef2f2";
            break;
          default:
            statusColor = "gray";
            statusText = "未知状态";
            backgroundColor = "#f5f5f5";
        }
        content += `
          <div style="margin-bottom: 10px; padding: 8px; border: 1px solid #e4e7ed; border-radius: 4px; background-color: ${backgroundColor};">
            <div><strong>序号:</strong> ${index + 1}</div>
            <div><strong>物料编码:</strong> ${item.materialCode || "无"}</div>
            <div><strong>状态码:</strong> <span style="color: ${statusColor}; font-weight: bold;">${item.code}</span></div>
            <div><strong>上传状态:</strong> <span style="color: ${statusColor}; font-weight: bold;">${statusText}</span></div>
            <div><strong>说明:</strong> ${item.reason || "无"}</div>
          </div>
        `;
      });
      content += "</div>";
      this.$alert(content, "BOM上传状态", {
        dangerouslyUseHTMLString: true,
        confirmButtonText: "确定",
        customClass: "bom-upload-status-dialog",
      });
    },
    resNotice(successCount, msg) {
      const count = Number(successCount) || 0;
      const tip = msg ? `${msg}，处理条数：${count}` : `成功上传的条数：${count}`;
      this.$alert(tip, "成功信息", {
        confirmButtonText: "确定",
      });
    },
    handAddSon(row) {
      this.reset();
      this.isDisabled = true;
      this.open = true;
      this.title = "添加子集";
      if (row.partNumber == null && row.name == null) {
        this.form.fnumber = this.rowField(row, "fnumber", "fNumber");
        this.form.fname = this.rowField(row, "fname", "fName");
      } else {
        this.form.fnumber = row.partNumber;
        this.form.fname = row.name;
      }
      this.form.fNumber = this.form.fnumber;
      this.form.fName = this.form.fname;
      this.form.totalWeight = this.resolveTotalWeight(row);
    },
    handleUpdate(row) {
      this.loading = true;
      this.reset();
      const id = row.id || this.ids;
      getDetails(id)
        .then((response) => {
          this.form = this.normalizeFormFields(response.data || {});
          this.open = true;
          this.title = "修改bom明细";
        })
        .finally(() => {
          this.loading = false;
        });
    },
    submitForm() {
      this.$refs["form"].validate((valid) => {
        if (!valid) return;
        this.buttonLoading = true;
        const payload = this.normalizeFormFields(this.form);
        const action = payload.id != null ? updateDetails(payload) : addDetails(payload);
        action
          .then(() => {
            this.$modal.msgSuccess(this.form.id != null ? "修改成功" : "新增成功");
            this.open = false;
            this.getList();
          })
          .finally(() => {
            this.buttonLoading = false;
          });
      });
    },
    handleDelete(row) {
      const ids = row.id || this.ids;
      this.$modal
        .confirm('是否确认删除bom明细编号为"' + ids + '"的数据项？')
        .then(() => {
          this.loading = true;
          return delDetails(ids);
        })
        .then(() => {
          this.getList();
          this.$modal.msgSuccess("删除成功");
        })
        .catch(() => {})
        .finally(() => {
          this.loading = false;
        });
    },
    handleExport() {
      this.download("system/details/export", this.buildQueryParams(), "details_" + new Date().getTime() + ".xlsx");
    },
  },
};
</script>

<style scoped>
.bom-details-page {
  --bom-ink: #1a2942;
  --bom-ink-muted: #5c6b7f;
  --bom-accent: #c9a227;
  --bom-steel: #2c5282;
  --bom-border: #dce3ec;
  --bom-surface: #ffffff;
  --bom-bg: #f4f6f9;
  --bom-ok: #1e7e4a;
  --bom-warn: #c0392b;
  --bom-radius: 10px;
  height: 100%;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.bom-details-page--embed {
  background: var(--bom-bg);
  padding: 0;
}

.bom-summary {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: stretch;
  padding: 16px 20px;
  background: linear-gradient(135deg, #f8fafc 0%, #eef2f7 100%);
  border-bottom: 1px solid var(--bom-border);
  flex-shrink: 0;
}

.bom-summary__hero {
  display: flex;
  align-items: center;
  gap: 14px;
}

.bom-summary__icon {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: linear-gradient(145deg, var(--bom-steel), #1a2942);
  color: var(--bom-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  box-shadow: 0 4px 12px rgba(26, 41, 66, 0.18);
}

.bom-summary__label {
  display: block;
  font-size: 11px;
  color: var(--bom-ink-muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 2px;
}

.bom-summary__order {
  display: block;
  font-size: 18px;
  font-weight: 700;
  color: var(--bom-ink);
  letter-spacing: 0.02em;
}

.bom-summary__name {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  color: var(--bom-ink-muted);
}

.bom-summary__stats {
  display: flex;
  gap: 10px;
  align-items: stretch;
}

.bom-stat-card {
  min-width: 72px;
  padding: 10px 14px;
  border-radius: var(--bom-radius);
  background: var(--bom-surface);
  border: 1px solid var(--bom-border);
  text-align: center;
  box-shadow: 0 1px 4px rgba(26, 41, 66, 0.05);
}

.bom-stat-card__num {
  display: block;
  font-size: 22px;
  font-weight: 700;
  color: var(--bom-steel);
  line-height: 1.1;
}

.bom-stat-card__txt {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--bom-ink-muted);
}

.bom-stat-card--ok .bom-stat-card__num {
  color: var(--bom-ok);
}

.bom-stat-card--warn .bom-stat-card__num {
  color: var(--bom-warn);
}

.bom-search {
  flex-shrink: 0;
  padding: 12px 20px 0;
  background: var(--bom-surface);
  border-bottom: 1px solid var(--bom-border);
}

.bom-details-page--embed .bom-search {
  background: transparent;
}

.bom-toolbar {
  flex-shrink: 0;
  padding: 0 4px;
}

.bom-op-column .el-button + .el-button {
  margin-left: 0;
}

.bom-tree-table >>> .bom-op-column .cell {
  white-space: normal;
  line-height: 1.6;
}

.bom-table-wrap {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 12px 16px 20px;
}

.bom-details-page--embed .bom-table-wrap {
  padding: 12px 16px 16px;
}

.bom-tree-table {
  width: 100%;
  border-radius: var(--bom-radius);
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(26, 41, 66, 0.06);
}

.bom-code-cell {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
}

.bom-code-text {
  font-family: "Consolas", "SF Mono", "DengXian", monospace;
  font-size: 12px;
  font-weight: 500;
  color: #3d5a80;
  line-height: 1.4;
}

.bom-code-text--assembly {
  font-size: 13px;
  font-weight: 700;
  color: var(--bom-ink);
}

.bom-name-text {
  font-size: 13px;
  color: var(--bom-ink-muted);
  line-height: 1.4;
}

.bom-name-text--assembly {
  font-size: 13px;
  font-weight: 600;
  color: var(--bom-ink);
}

.bom-code-count {
  flex-shrink: 0;
  min-width: 20px;
  height: 18px;
  padding: 0 6px;
  border-radius: 9px;
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
  text-align: center;
  color: var(--bom-steel);
  background: rgba(44, 82, 130, 0.1);
}

.bom-tree-table >>> .bom-code-column .cell,
.bom-tree-table >>> .bom-name-column .cell {
  line-height: 1.4;
}

.bom-cell-empty {
  color: #b0bac5;
}

.bom-qty {
  font-family: "Consolas", "SF Mono", monospace;
  font-weight: 600;
  color: var(--bom-ink);
  background: rgba(201, 162, 39, 0.1);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 12px;
}

.bom-stats-tag {
  border-radius: 4px;
  font-weight: 600;
}

.bom-exists {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
}

.bom-exists--yes {
  color: var(--bom-ok);
}

.bom-exists--no {
  color: var(--bom-warn);
}

.bom-tree-table >>> .el-table__row--level-0 > td {
  background: rgba(238, 242, 247, 0.65) !important;
  border-top: 1px solid rgba(44, 82, 130, 0.12);
}

.bom-tree-table >>> .el-table__row--level-0:hover > td {
  background: rgba(226, 234, 244, 0.9) !important;
}

.bom-tree-table >>> .el-table__row--level-1 > td {
  background: #fff !important;
}

.bom-tree-table >>> .el-table__indent {
  padding-left: 6px !important;
}

.bom-tree-table >>> .el-table__placeholder {
  width: 12px;
}

@media (max-width: 900px) {
  .bom-summary {
    grid-template-columns: 1fr;
  }
  .bom-summary__stats {
    flex-wrap: wrap;
  }
}
</style>
