<template>
  <div class="product-machine-add">
    <div class="header">
      <el-button type="text" @click="handleBack">返回</el-button>
      <h2 class="title">创建商品</h2>
    </div>

    <!-- <el-alert
      class="notice-alert"
      type="warning"
      show-icon
      :closable="false"
      title="新增商品必须在 M2pool 有挖矿算力记录才能添加出租"
      description="建议稳定在 M2pool 矿池挖矿 24 小时之后，再创建该商品"
    /> -->

    <el-card shadow="never" class="form-card">
      <el-form
        ref="machineForm"
        :model="form"
        :rules="rules"
        label-width="160px"
        size="small"
      >
        <el-form-item label="矿机种类">
          <el-radio-group
            v-model="form.machineCategory"
            @change="handleMachineCategoryChange"
          >
            <el-radio label="ASIC">ASIC</el-radio>
            <el-radio label="GPU">GPU</el-radio>
          </el-radio-group>
        </el-form-item>
        <!-- GPU 引导内容 -->
        <div v-if="form.machineCategory === 'GPU'" class="gpu-guide-section">
          <el-card shadow="never" class="gpu-guide-card">
            <div class="gpu-guide-content">
              <div class="gpu-guide-title">注意事项：</div>
              <ol class="gpu-guide-list">
                <li>
                  GPU商品需先点击下方按钮，下载并在GPU所在主机启动客户端，在下载包中会有启动客户端的操作指引文档
                </li>
                <li>
                  成功在GPU主机启动客户端后，GPU信息会自行添加至商品列表中，点击下方前往商品列表按钮可以前往该页面
                </li>
                <li>
                  客户端和您的卖家账号绑定，如果您需要在本卖家账号<span v-if="userEmail"> ({{ userEmail }})</span>添加多个GPU商品，可通过下列两种方法实现：<br />
                  方法一：点击下方下载客户端按钮，将下载好的完整客户端包复制到不同的GPU主机并且启动，启动后客户端所在主机的GPU数据会自动添加到商品列表中
                  (推荐) <br />
                  方法二：在不同的客户端主机登陆您的卖家账号，进入本页面，点击下载对应操作系统客户端，成功启动客户端后也可自动添加GPU数据到商品列表中
                </li>
                <li>目前只支持NVIDIA系列GPU</li>
              </ol>
              <div class="gpu-guide-buttons">
                <el-button type="primary" @click="handleDownloadClient('windows')"
                  >Windows 客户端下载</el-button
                >
                <el-button type="primary" @click="handleDownloadClient('linux')"
                  >Linux 客户端下载</el-button
                >
                <el-button type="success" @click="handleGpuClientStarted"
                  >前往商品列表</el-button
                >
              </div>
            </div>
          </el-card>
        </div>
        <!-- ASIC：币种/算法/理论算力/单位 同行，支持多行动态增删 -->
        <el-form-item
          v-if="form.machineCategory === 'ASIC'"
          label="币种/算法/算力/单位"
          prop="coinAndAlgoList"
          :required="true"
        >
          <div class="coin-algo-rows">
            <div
              class="coin-algo-line"
              v-for="(row, idx) in form.coinAndAlgoList"
              :key="idx"
            >
              <el-select
                v-model="row.coin"
                placeholder="请选择币种"
                class="coin-input"
                @change="handleCoinChange(idx, $event)"
                :loading="loadingCoins"
                filterable
                clearable
              >
                <el-option
                  v-for="coin in coinOptions"
                  :key="coin"
                  :label="coin"
                  :value="coin"
                />
              </el-select>
              <el-select
                v-model="row.algorithm"
                placeholder="请选择算法"
                class="algo-input"
                :loading="loadingAlgos[idx]"
                :disabled="!row.coin"
                filterable
                clearable
              >
                <el-option
                  v-for="algo in (algoOptionsMap[row.coin] || [])"
                  :key="algo"
                  :label="algo"
                  :value="algo"
                />
              </el-select>
              <el-input
                v-model="row.theoryPower"
                placeholder="理论算力"
                inputmode="decimal"
                class="power-input"
                @input="handleCoinRowTheoryInput(idx)"
              />
              <el-select
                v-model="row.unit"
                placeholder="单位"
                class="unit-select"
                @change="handleCoinRowUnitChange(idx, $event)"
              >
                <el-option label="KH/S" value="KH/S" />
                <el-option label="MH/S" value="MH/S" />
                <el-option label="GH/S" value="GH/S" />
                <el-option label="TH/S" value="TH/S" />
                <el-option label="PH/S" value="PH/S" />
              </el-select>
              <el-button
                class="op-btn"
                type="primary"
                icon="el-icon-plus"
                circle
                @click="handleAddCoinAlgoRow"
                :aria-label="'新增一行'"
              />
              <el-button
                v-if="form.coinAndAlgoList.length > 1"
                class="op-btn"
                icon="el-icon-minus"
                circle
                @click="handleRemoveCoinAlgoRow(idx)"
                :aria-label="'删除该行'"
              />
            </div>
          </div>
        </el-form-item>

        <el-form-item v-if="form.machineCategory === 'ASIC'" label="矿机型号" prop="type" :required="true">
          <el-input
            style="width: 50%"
            v-model="form.type"
            placeholder="示例：龍珠"
            :maxlength="20"
            @input="handleTypeInput"
          />
        </el-form-item>
        <!-- 理论算力与单位已合并到上面的同行多行输入 -->
        <el-form-item v-if="form.machineCategory === 'ASIC'" label="最大租赁天数" prop="maxLeaseDays">
          <el-input
            v-model="form.maxLeaseDays"
            placeholder="1-365"
            inputmode="numeric"
            @input="handleNumeric('maxLeaseDays')"
            style="width: 50%"
          >
            <template slot="append">天</template>
          </el-input>
        </el-form-item>
        <el-form-item v-if="form.machineCategory === 'ASIC'" label="功耗" prop="powerDissipation">
          <el-input
            v-model="form.powerDissipation"
            inputmode="decimal"
            @input="handleNumeric('powerDissipation')"
            style="width: 50%"
          >
            <template slot="append">kw/h</template>
          </el-input>
        </el-form-item>

        <el-form-item
          v-if="form.machineCategory === 'ASIC'"
          label="统一售价"
          :prop="payTypeDefs && payTypeDefs.length ? 'costMap' : 'cost'"
          :required="true"
        >
          <span slot="label">统一售价</span>
          <!-- 若商品定义了多个结算币种，则按链-币种动态生成多个售价输入；否则回退为旧的 USDT 单价 -->
          <div v-if="payTypeDefs && payTypeDefs.length" class="cost-multi">
            <div v-for="pt in payTypeDefs" :key="pt.key" class="cost-item">
              <el-input
                v-model="form.costMap[pt.key]"
                placeholder="请输入价格"
                inputmode="decimal"
                @input="(val) => handleCostMapInput(pt.key, val)"
                style="width: 50%"
              >
                <template slot="append">{{ pt.label }}</template>
              </el-input>
            </div>
          </div>
          <el-input
            v-else
            v-model="form.cost"
            placeholder="请输入成本（USDT）"
            inputmode="decimal"
            @input="handleNumeric('cost')"
            style="width: 50%"
          >
            <template slot="append">USDT</template>
          </el-input>
        </el-form-item>

        <!-- 出售机器数量（统一使用，GPU 仅作引导不在本页提交） -->
        <el-form-item
          v-if="form.machineCategory === 'ASIC'"
          label="出售机器数量(台)"
          prop="sellCount"
          :required="true"
        >
          <el-input
            v-model="form.sellCount"
            placeholder="0 - 9999"
            inputmode="numeric"
            style="width: 50%"
            @input="handleSellCountInput"
            @blur="handleSellCountBlur"
          />
        </el-form-item>
      </el-form>
    </el-card>

    <div v-if="form.machineCategory === 'ASIC'" class="actions">
      <el-button @click="handleBack">取消</el-button>
      <el-button type="primary" :loading="saving" @click="handleSave"
        >确认创建</el-button
      >
    </div>

    <!-- 上架确认弹窗 -->
    <el-dialog
      title="请确认上架信息"
      :visible.sync="confirmVisible"
      width="560px"
    >
      <div style="text-align: left; line-height: 1.9">
        <div>
          币种：<b>{{ confirmData.coin }}</b>
        </div>
        <div>
          算法：<b>{{ confirmData.algorithm }}</b>
        </div>
        <div>
          最大租赁天数：<b>{{ confirmData.maxLeaseDays || "-" }}</b>
        </div>
        <div>
          出售机器数量：<b>{{ confirmData.saleNumbers || "-" }}</b>
        </div>
        <div style="margin-top: 8px">售价：</div>
        <el-table
          :data="confirmData.priceList"
          border
          size="mini"
          style="width: 100%"
        >
          <el-table-column prop="chain" label="链" width="120" />
          <el-table-column prop="coin" label="币种" width="120" />
          <el-table-column label="价格">
            <template slot-scope="scope">
              {{ scope.row.price }}
            </template>
          </el-table-column>
        </el-table>
        <p style="color: #666; margin-top: 12px">
          请仔细确认以上参数无误后提交。
        </p>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="confirmVisible = false">取消</el-button>
        <el-button type="primary" :loading="saving" @click="doSubmit"
          >确认提交</el-button
        >
      </span>
    </el-dialog>
  </div>
</template>

<script>
import {
  addSingleOrBatchMachine,
  downloadClient,
  addAsicMachine,getSupportCoin,getSupportAlgo
} from "../../api/machine";
import { getPayTypes } from "../../api/products";
import request from "../../utils/request";
export default {
  name: "AccountProductMachineAdd",
  data() {
    return {
      form: {
        productId: Number(this.$route.query.productId) || null,
        coin: this.$route.query.coin || "",
        productName: this.$route.query.name || "",
        /** 矿机种类：ASIC 或 GPU，默认 ASIC */
        machineCategory: "ASIC",
        /** 出售机器数量（仅 ASIC 模式使用） */
        sellCount: "",
        /** ASIC：币种/算法/理论算力/单位 行编辑（最多10行） */
        coinAndAlgoList: [
          { coin: "", algorithm: "", theoryPower: "", unit: "TH/S" },
        ],
        powerDissipation: null,
        type: "",
        cost: "",
        costMap: {}, // { 'CHAIN-COIN': '123.45' }
        maxLeaseDays: "",
      },
      confirmVisible: false,
      confirmData: {
        coin: "",
        algorithm: "",
        maxLeaseDays: "",
        saleNumbers: "",
        priceList: [],
      },
      rules: {
        productName: [
          { required: true, message: "商品名称不能为空", trigger: "change" },
        ],
        type: [
          { required: true, message: "矿机型号不能为空", trigger: "blur" },
          {
            validator: (rule, value, callback) => {
              const s = String(value || "");
              // 不允许全是空格
              if (s && s.trim().length === 0) {
                callback(new Error("矿机型号不能全是空格"));
                return;
              }
              callback();
            },
            trigger: "blur",
          },
        ],
        coinAndAlgoList: [
          {
            validator: (rule, value, callback) =>
              this.validateCoinAlgoRows(rule, value, callback),
            trigger: "blur",
          },
        ],
        sellCount: [
          {
            validator: (rule, value, callback) => {
              if (this.form.machineCategory !== "ASIC") {
                callback();
                return;
              }
              const raw = String(value ?? "");
              if (raw === "") {
                callback(new Error("请输入出售机器数量"));
                return;
              }
              if (!/^\d{1,4}$/.test(raw)) {
                callback(new Error("请输入 0-9999 的整数"));
                return;
              }
              const n = Number(raw);
              if (!Number.isInteger(n) || n < 0 || n > 9999) {
                callback(new Error("范围需在 0-9999"));
                return;
              }
              callback();
            },
            trigger: "blur",
          },
        ],
        powerDissipation: [
          { required: true, message: "功耗不能为空", trigger: "blur" },
          {
            validator: (rule, value, callback) => {
              const str = String(value || "");
              if (!str) {
                callback(new Error("功耗不能为空"));
                return;
              }
              const pattern = /^\d{1,6}(\.\d{1,4})?$/;
              if (!pattern.test(str)) {
                callback(new Error("功耗整数最多6位，小数最多4位"));
                return;
              }
              if (Number(str) <= 0) {
                callback(new Error("功耗必须大于0"));
                return;
              }
              callback();
            },
            trigger: "blur",
          },
        ],
        cost: [
          {
            validator(rule, value, callback) {
              // 若为多结算币种模式，跳过此校验（统一售价由每种币种的输入框承担）
              if (
                Array.isArray(this.payTypeDefs) &&
                this.payTypeDefs.length > 0
              ) {
                callback();
                return;
              }
              const str = String(value || "");
              if (!str) {
                callback(new Error("请填写机器成本（USDT）"));
                return;
              }
              const pattern = /^\d{1,12}(\.\d{1,2})?$/;
              if (!pattern.test(str)) {
                callback(new Error("成本整数最多12位，小数最多2位"));
                return;
              }
              if (Number(str) <= 0) {
                callback(new Error("成本必须大于 0"));
                return;
              }
              callback();
            },
            trigger: "blur",
          },
        ],
        maxLeaseDays: [
          { required: true, message: "请填写最大租赁天数", trigger: "blur" },
          {
            validator: (rule, value, callback) => {
              const raw = String(value ?? "");
              if (!raw) {
                callback(new Error("请填写最大租赁天数"));
                return;
              }
              if (!/^\d{1,3}$/.test(raw)) {
                callback(new Error("仅允许整数，范围 1-365"));
                return;
              }
              const n = Number(raw);
              if (!Number.isInteger(n) || n < 1 || n > 365) {
                callback(new Error("范围需在 1-365 天"));
                return;
              }
              callback();
            },
            trigger: "blur",
          },
        ],
      },
      miners: [
        // {
        //           "user": "lx_888",
        //           "miner": null,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "lx999",
        //           "miner": null,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "lx88",
        //           "miner": null,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "lx6666",
        //           "miner": null,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "lx_999",
        //           "miner": null,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "Lx_6966",
        //           "miner": null,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "LX_666",
        //           "miner": null,
        //           "coin": "nexa"
        //       },
      ],
      minersLoading: false,
      selectedMiner: "", // 格式 user|coin
      machineOptions: [
        // {
        //           "user": "lx_888",
        //           "miner": `iusfhufhu`,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "lx999",
        //           "miner": `iusfhufhu2`,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "lx88",
        //           "miner": `iusfhufhu3`,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "lx6666",
        //           "miner": `iusfhufhu4`,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "lx_999",
        //           "miner": `iusfhufhu5`,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "Lx_6966",
        //           "miner": `iusfhufhu6`,
        //           "coin": "nexa"
        //       },
        //       {
        //           "user": "LX_666",
        //           "miner": `iusfhufhu7`,
        //           "coin": "nexa"
        //       },
      ],
      machinesLoading: false,
      selectedMachines: [],
      selectedMachineRows: [],
      saving: false,
      lastCostBaseline: 0,
      lastCostMapBaseline: {}, // { key: number }
      lastTypeBaseline: "",
      lastMaxLeaseDaysBaseline: 0,
      lastPowerDissipationBaseline: 0,
      lastTheoryPowerBaseline: 0,
      lastUnitBaseline: "TH/S",
      /** GPU 引导弹窗可见性 */
      gpuDialogVisible: false,
      /** GPU 客户端下载地址（可通过环境变量配置：VUE_APP_GPU_CLIENT_URL） */
      clientDownloadUrl: process.env.VUE_APP_GPU_CLIENT_URL || "",
      /** 是否点击过下载客户端（用于控制“已启动客户端”按钮禁用态） */
      hasDownloadedClient: false,
      /** 支持的支付方式定义（用于动态渲染统一售价输入组） */
      payTypeDefs: [],
      /** 币种选项列表 */
      coinOptions: [],
      /** 算法选项映射 { coin: [algo1, algo2, ...] } */
      algoOptionsMap: {},
      /** 加载币种状态 */
      loadingCoins: false,
      /** 加载算法状态映射 { index: boolean } */
      loadingAlgos: {},
      params: {
        cost: 353400,
        powerDissipation: 0.01,
        theoryPower: 1000,
        type: "",
        unit: "TH/S",
        productId: 1,
        productMachineURDVos: [
          {
            user: "lx_888",
            miner: "iusfhufhu",
            price: 353400,
            type: "",
            state: 0,
          },
          {
            user: "lx_888",
            miner: "iusfhufhu2",
            price: 353400,
            type: "",
            state: 0,
          },
        ],
      },
      userEmail:"",
    };
  },
  created() {
    this.initPayTypesFromRoute();
    this.lastTypeBaseline = this.form.type;
    // 绑定基于组件实例的校验器，避免 this 丢失
    if (this.rules && this.rules.cost) {
      this.$set(this.rules, "cost", [
        { validator: this.validateCost, trigger: "blur" },
      ]);
    }
    // 多币种价格专用校验
    this.$set(this.rules, "costMap", [
      { validator: this.validateCostMap, trigger: "blur" },
    ]);

    this.getPayTypes();
    this.loadSupportCoins();

    this.userEmail = JSON.parse(localStorage.getItem("leasEmail")) || "";
  },
  methods: {
    /** ASIC 行校验：币种/算法/理论算力/单位 */
    validateCoinAlgoRows(rule, value, callback) {
      try {
        const rows = Array.isArray(this.form.coinAndAlgoList)
          ? this.form.coinAndAlgoList
          : [];
        if (!rows.length) {
          callback(new Error("请至少添加一行币种/算法/算力/单位"));
          return;
        }
        const powerPattern = /^\d{1,6}(\.\d{1,4})?$/;
        for (let i = 0; i < rows.length; i += 1) {
          const r = rows[i] || {};
          const coin = String(r.coin || "").trim();
          const algo = String(r.algorithm || "").trim();
          const power = String(r.theoryPower || "").trim();
          const unit = String(r.unit || "").trim();
          if (!coin) {
            callback(new Error(`第 ${i + 1} 行：请选择币种`));
            return;
          }
          if (!algo) {
            callback(new Error(`第 ${i + 1} 行：请选择算法`));
            return;
          }
          if (!power || !powerPattern.test(power) || Number(power) <= 0) {
            callback(
              new Error(
                `第 ${i + 1} 行：理论算力需大于0，整数最多6位，小数最多4位`
              )
            );
            return;
          }
          if (!unit) {
            callback(new Error(`第 ${i + 1} 行：请选择算力单位`));
            return;
          }
        }
        callback();
      } catch (e) {
        callback(new Error("请检查币种/算法/算力/单位填写"));
      }
    },
    /**
     * 加载支持的币种列表
     */
    async loadSupportCoins() {
      this.loadingCoins = true;
      try {
        const res = await getSupportCoin();
        if (res && (res.code === 0 || res.code === 200)) {
          const data = res.data || [];
          // 处理返回的数据，可能是数组或对象
          if (Array.isArray(data)) {
            this.coinOptions = data.map(item => {
              // 如果是对象，取 coin 字段；如果是字符串，直接使用
              return typeof item === 'string' ? item : (item.coin || item.name || item);
            }).filter(Boolean);
          } else if (data && typeof data === 'object') {
            // 如果是对象，尝试提取币种列表
            this.coinOptions = Object.keys(data).map(key => {
              const item = data[key];
              return typeof item === 'string' ? item : (item.coin || item.name || key);
            }).filter(Boolean);
          }
          // 去重并排序
          this.coinOptions = [...new Set(this.coinOptions)].sort();
        }
      } catch (e) {
        console.error("加载币种列表失败", e);
        this.$message.error("加载币种列表失败，请稍后重试");
      } finally {
        this.loadingCoins = false;
      }
    },
    /**
     * 币种选择变化处理
     * @param {number} index - 行索引
     * @param {string} coin - 选择的币种
     */
    async handleCoinChange(index, coin) {
      // 清空当前行的算法选择
      this.$set(this.form.coinAndAlgoList[index], "algorithm", "");
      // 如果选择了币种，加载对应的算法列表
      if (coin) {
        await this.loadAlgorithmsForCoin(coin, index);
      }
    },
    /**
     * 加载指定币种支持的算法列表
     * @param {string} coin - 币种名称
     * @param {number} index - 行索引（用于显示加载状态）
     */
    async loadAlgorithmsForCoin(coin, index) {
      if (!coin) return;
      
      // 如果已经加载过该币种的算法，直接返回
      if (this.algoOptionsMap[coin] && this.algoOptionsMap[coin].length > 0) {
        return;
      }

      // 设置加载状态
      this.$set(this.loadingAlgos, index, true);
      
      try {
        const res = await getSupportAlgo(coin);
        if (res && (res.code === 0 || res.code === 200)) {
          const data = res.data || [];
          let algorithms = [];
          
          // 处理返回的数据，可能是数组或对象
          if (Array.isArray(data)) {
            algorithms = data.map(item => {
              // 如果是对象，取 algorithm 或 algo 字段；如果是字符串，直接使用
              return typeof item === 'string' ? item : (item.algorithm || item.algo || item.name || item);
            }).filter(Boolean);
          } else if (data && typeof data === 'object') {
            // 如果是对象，尝试提取算法列表
            algorithms = Object.keys(data).map(key => {
              const item = data[key];
              return typeof item === 'string' ? item : (item.algorithm || item.algo || item.name || key);
            }).filter(Boolean);
          }
          
          // 去重并排序，保存到映射中
          this.$set(this.algoOptionsMap, coin, [...new Set(algorithms)].sort());
        }
      } catch (e) {
        console.error(`加载币种 ${coin} 的算法列表失败`, e);
        this.$message.error(`加载算法列表失败，请稍后重试`);
        // 设置空数组，避免重复请求
        this.$set(this.algoOptionsMap, coin, []);
      } finally {
        this.$set(this.loadingAlgos, index, false);
      }
    },
    /** 行：理论算力输入限制（6整数4小数） */
    handleCoinRowTheoryInput(index) {
      let v = String(this.form.coinAndAlgoList[index].theoryPower ?? "");
      v = v.replace(/[^0-9.]/g, "");
      const firstDot = v.indexOf(".");
      if (firstDot !== -1) {
        v = v.slice(0, firstDot + 1) + v.slice(firstDot + 1).replace(/\./g, "");
      }
      const endsWithDot = v.endsWith(".");
      const parts = v.split(".");
      let intPart = parts[0] || "";
      let decPart = parts[1] || "";
      if (intPart.length > 6) intPart = intPart.slice(0, 6);
      if (decPart) decPart = decPart.slice(0, 4);
      v = decPart.length
        ? `${intPart}.${decPart}`
        : endsWithDot
        ? `${intPart}.`
        : intPart;
      this.$set(this.form.coinAndAlgoList[index], "theoryPower", v);
    },
    /** 行：单位变更 */
    handleCoinRowUnitChange(index, value) {
      this.$set(this.form.coinAndAlgoList[index], "unit", value);
    },
    /** 新增一行 */
    handleAddCoinAlgoRow() {
      if (this.form.coinAndAlgoList.length >= 10) {
        this.$message.warning("最多添加 10 行");
        return;
      }
      const last = this.form.coinAndAlgoList[
        this.form.coinAndAlgoList.length - 1
      ] || { unit: "TH/S" };
      const newIndex = this.form.coinAndAlgoList.length;
      this.form.coinAndAlgoList.push({
        coin: "",
        algorithm: "",
        theoryPower: "",
        unit: last.unit || "TH/S",
      });
      // 初始化新行的加载状态
      this.$set(this.loadingAlgos, newIndex, false);
    },
    /** 删除一行 */
    handleRemoveCoinAlgoRow(index) {
      if (this.form.coinAndAlgoList.length <= 1) return;
      this.form.coinAndAlgoList.splice(index, 1);
    },
    /** 从多行聚合 coin CSV */
    buildCoinCsvFromRows() {
      const set = new Set();
      const rows = Array.isArray(this.form.coinAndAlgoList)
        ? this.form.coinAndAlgoList
        : [];
      rows.forEach((r) => {
        const token = String(r.coin || "")
          .split(/[,\s，、]+/)
          .map((s) => s.trim().toUpperCase())
          .filter(Boolean);
        token.forEach((t) => set.add(t));
      });
      return Array.from(set).join(",");
    },
    /** 从多行聚合 algorithm CSV */
    buildAlgoCsvFromRows() {
      const set = new Set();
      const rows = Array.isArray(this.form.coinAndAlgoList)
        ? this.form.coinAndAlgoList
        : [];
      rows.forEach((r) => {
        const token = String(r.algorithm || "")
          .split(/[,\s，、]+/)
          .map((s) => s.trim().toUpperCase())
          .filter(Boolean);
        token.forEach((t) => set.add(t));
      });
      return Array.from(set).join(",");
    },
    /** 实时过滤币种输入中的中文字符（仅保留英文/数字/分隔符） */
    handleCoinsInput() {
      let v = String(this.form.coinsInput || "");
      // 去除中文
      v = v.replace(/[\u4e00-\u9fa5]/g, "");
      this.form.coinsInput = v;
    },
    /** 实时过滤算法输入中的中文字符（仅保留英文/数字/连字符/分隔符） */
    handleAlgorithmsInput() {
      let v = String(this.form.algorithmsInput || "");
      v = v.replace(/[\u4e00-\u9fa5]/g, "");
      this.form.algorithmsInput = v;
    },
    /** 将输入按中英文逗号、空格分割，去空，统一英文逗号连接；可选：统一大写 */
    normalizeCsv(input, upper = true) {
      const arr = String(input || "")
        .split(/[,\s，、]+/)
        .map((s) => s.trim())
        .filter(Boolean);
      const list = upper ? arr.map((s) => s.toUpperCase()) : arr;
      return list.join(",");
    },
    /** 从 payTypeDefs 与 costMap 生成价格列表 */
    buildPriceList() {
      const list = [];
      const defs = Array.isArray(this.payTypeDefs) ? this.payTypeDefs : [];
      defs.forEach((d) => {
        const key = d.key;
        const priceRaw = this.form.costMap ? this.form.costMap[key] : "";
        const priceNum = Number(priceRaw);
        // 允许为空/非数字则不加入
        if (!Number.isFinite(priceNum) || priceNum <= 0) return;
        list.push({
          chain: d.chain,
          coin: d.coin,
          price: priceNum,
        });
      });
      return list;
    },
    async getPayTypes() {
      try {
        const res = await getPayTypes();
        // 期望结构：{ code:200, data:[ { payChain, payCoin, payCoinImage } ] }
        if (res && (res.code === 0 || res.code === 200)) {
          const list = Array.isArray(res.data) ? res.data : [];
          const defs = [];
          const seen = new Set();
          list.forEach((it) => {
            const chain = String(
              it && it.payChain ? it.payChain : ""
            ).toUpperCase();
            const coin = String(
              it && it.payCoin ? it.payCoin : ""
            ).toUpperCase();
            if (!chain && !coin) return;
            const key = [chain, coin].filter(Boolean).join("-");
            if (seen.has(key)) return;
            seen.add(key);
            defs.push({
              chain,
              coin,
              key,
              label: key,
              image: it && it.payCoinImage ? String(it.payCoinImage) : "",
            });
          });
          // 根据接口结果渲染“统一售价”输入组
          this.payTypeDefs = defs;
          const nextCostMap = {};
          this.payTypeDefs.forEach((d) => {
            // 保留已输入的数值；否则置空
            nextCostMap[d.key] =
              (this.form.costMap && this.form.costMap[d.key]) || "";
          });
          this.form.costMap = nextCostMap;
        }
      } catch (e) {
        // 忽略错误，维持当前 payTypeDefs
      }
    },
    /**
     * ASIC 模式：出售机器数量输入，仅允许 0-9999 的整数
     */
    handleSellCountInput() {
      let v = String(this.form.sellCount ?? "");
      // 仅数字
      v = v.replace(/\D/g, "");
      // 限制最多4位
      if (v.length > 4) v = v.slice(0, 4);
      // 限制最大 9999
      if (v) {
        const n = Number(v);
        if (n > 9999) v = "9999";
      }
      this.form.sellCount = v;
    },
    handleSellCountBlur() {
      const raw = String(this.form.sellCount ?? "");
      if (raw === "") return;
      const n = Number(raw);
      if (!Number.isInteger(n) || n < 0 || n > 9999) {
        this.$message.warning("出售机器数量需为 0-9999 的整数");
        this.form.sellCount = "";
      }
    },
    /**
     * 矿机种类变更
     * @param {string} val
     */
    handleMachineCategoryChange(val) {
      // GPU 引导内容已直接显示在页面上，无需弹窗
    },
    /**
     * 下载 GPU 客户端
     */
    handleDownloadClient(types) {
      // 走后端接口下载客户端程序

      let userEmail = JSON.parse(localStorage.getItem("leasEmail"));
      if (!userEmail) {
        // 弹出确认框，用户确认后跳转到外部网站
        this.$confirm("获取用户信息失败，请重新进入网站？", "提示", {
          confirmButtonText: "确认",
          cancelButtonText: "取消",
          type: "warning",
        })
          .then(() => {
            // 用户点击确认，跳转到外部网站
            window.open("https://test.m2pool.com/", "_blank");
          })
          .catch(() => {
            // 用户点击取消，不执行任何操作
          });
        return;
      }
      console.log(userEmail, "userEmail");

      this.downloadUrl = ` ${request.defaults.baseURL}/lease/user/downloadClient?userEmail=${userEmail}&type=${types}`;
      let a = document.createElement(`a`);
      a.href = this.downloadUrl;
      a.click();
    },
    /**
     * GPU 客户端已启动：跳转至商品列表
     */
    handleGpuClientStarted() {
      // 跳转到“个人中心-商品列表”页面
      this.$router.push("/account/products");
    },
    /** 统一售价校验：多结算币种时跳过，单价时按 USDT 校验 */
    validateCost(rule, value, callback) {
      // 多支付方式：逐个校验 costMap
      if (Array.isArray(this.payTypeDefs) && this.payTypeDefs.length > 0) {
        return this.validateCostMap(rule, value, callback);
      }
      const str = String(value || "");
      if (!str) {
        callback(new Error("请填写机器成本（USDT）"));
        return;
      }
      const pattern = /^\d{1,12}(\.\d{1,2})?$/;
      if (!pattern.test(str)) {
        callback(new Error("成本整数最多12位，小数最多2位"));
        return;
      }
      if (Number(str) <= 0) {
        callback(new Error("成本必须大于 0"));
        return;
      }
      callback();
    },
    // 多支付方式下的价格校验：要求每个支付方式都需填写有效价格
    validateCostMap(rule, value, callback) {
      try {
        const defs = Array.isArray(this.payTypeDefs) ? this.payTypeDefs : [];
        if (!defs.length) {
          callback();
          return;
        }
        const pattern = /^\d{1,12}(\.\d{1,2})?$/;
        for (let i = 0; i < defs.length; i += 1) {
          const d = defs[i];
          const key = d.key;
          const v =
            this.form && this.form.costMap
              ? String(this.form.costMap[key] || "")
              : "";
          if (!v) {
            callback(new Error(`请填写 ${d.label} 的价格`));
            return;
          }
          if (!pattern.test(v)) {
            callback(new Error(`${d.label} 价格整数最多12位，小数最多2位`));
            return;
          }
          if (Number(v) <= 0) {
            callback(new Error(`${d.label} 价格必须大于0`));
            return;
          }
        }
        callback();
      } catch (e) {
        callback(new Error("价格填写有误，请检查"));
      }
    },
    /** 解析路由参数中的支付方式，生成标准定义 */
    initPayTypesFromRoute() {
      this.payTypeDefs = [];
      try {
        const raw = this.$route.query.payTypes;
        if (!raw) return;
        const arr = JSON.parse(decodeURIComponent(raw));
        if (!Array.isArray(arr)) return;
        const defs = [];
        arr.forEach((it) => {
          const chain = String(it && it.chain ? it.chain : "").toUpperCase();
          const coin = String(it && it.coin ? it.coin : "").toUpperCase();
          if (!chain && !coin) return;
          const key = [chain, coin].filter(Boolean).join("-");
          const label = key;
          defs.push({ chain, coin, key, label });
        });
        // 去重
        const map = new Map();
        defs.forEach((d) => {
          if (!map.has(d.key)) map.set(d.key, d);
        });
        this.payTypeDefs = Array.from(map.values());
        // 初始化统一售价映射
        const initCostMap = {};
        this.payTypeDefs.forEach((d) => {
          initCostMap[d.key] = "";
        });
        this.form.costMap = initCostMap;
        this.lastCostMapBaseline = { ...initCostMap };
      } catch (e) {
        this.payTypeDefs = [];
      }
    },
    handleBack() {
      this.$router.back();
    },
    handleNumeric(key) {
      // 仅允许数字和一个小数点
      let v = String(this.form[key] ?? "");
      // 清理非法字符
      v = v.replace(/[^0-9.]/g, "");
      // 保留第一个小数点
      const firstDot = v.indexOf(".");
      if (firstDot !== -1) {
        v = v.slice(0, firstDot + 1) + v.slice(firstDot + 1).replace(/\./g, "");
      }
      const endsWithDot = v.endsWith(".");
      if (key === "cost") {
        // 成本：整数最多12位，小数最多2位
        const parts = v.split(".");
        let intPart = parts[0] || "";
        let decPart = parts[1] || "";
        if (intPart.length > 12) {
          intPart = intPart.slice(0, 12);
        }
        if (decPart) {
          decPart = decPart.slice(0, 2);
        }
        v = decPart.length
          ? `${intPart}.${decPart}`
          : endsWithDot
          ? `${intPart}.`
          : intPart;
      } else if (key === "powerDissipation" || key === "theoryPower") {
        // 功耗/理论算力：整数最多6位，小数最多4位
        const parts = v.split(".");
        let intPart = parts[0] || "";
        let decPart = parts[1] || "";
        if (intPart.length > 6) {
          intPart = intPart.slice(0, 6);
        }
        if (decPart) {
          decPart = decPart.slice(0, 4);
        }
        v = decPart.length
          ? `${intPart}.${decPart}`
          : endsWithDot
          ? `${intPart}.`
          : intPart;
      } else if (key === "maxLeaseDays") {
        // 最大租赁天数：仅整数，范围 1-365，输入阶段限制为最多3位数字
        v = v.replace(/\D/g, "");
        if (v.length > 3) v = v.slice(0, 3);
        this.form[key] = v;
        this.syncMaxLeaseDaysToRows();
        return;
      } else {
        // 其他：最多6位小数（保持原有逻辑）
        if (firstDot !== -1) {
          const [intPart, decPart] = v.split(".");
          v = intPart + "." + (decPart ? decPart.slice(0, 6) : "");
        }
      }
      this.form[key] = v;
    },
    /** 顶部多结算币种统一售价输入 */
    handleCostMapInput(key, val) {
      // 价格输入：整数最多12位，小数最多2位；允许尾随小数点
      let v = String(val ?? this.form.costMap[key] ?? "");
      v = v.replace(/[^0-9.]/g, "");
      const firstDot = v.indexOf(".");
      if (firstDot !== -1) {
        v = v.slice(0, firstDot + 1) + v.slice(firstDot + 1).replace(/\./g, "");
      }
      const endsWithDot = v.endsWith(".");
      const parts = v.split(".");
      let intPart = parts[0] || "";
      let decPart = parts[1] || "";
      if (intPart.length > 12) intPart = intPart.slice(0, 12);
      if (decPart) decPart = decPart.slice(0, 2);
      v = decPart.length
        ? `${intPart}.${decPart}`
        : endsWithDot
        ? `${intPart}.`
        : intPart;
      this.$set(this.form.costMap, key, v);
    },
    /**
     * 顶部矿机型号输入：限制20字符
     */
    handleTypeInput() {
      if (typeof this.form.type === "string" && this.form.type.length > 20) {
        this.form.type = this.form.type.slice(0, 20);
      }
    },
    syncCostToRows() {
      const newCost = Number(this.form.cost);
      if (!Number.isFinite(newCost)) {
        return;
      }
      const oldBaseline = this.lastCostBaseline;
      this.selectedMachineRows = this.selectedMachineRows.map((row) => {
        const priceNum = Number(row.price);
        if (!Number.isFinite(priceNum) || priceNum === oldBaseline) {
          return { ...row, price: newCost };
        }
        return row;
      });
      this.lastCostBaseline = newCost;
    },
    updateMachineType() {
      // 仅记录最近一次外层输入，避免无用同步逻辑
      this.lastTypeBaseline = this.form.type;
    },
    /**
     * 行内功耗输入（限制：整数最多6位，小数最多4位）
     */
    handleRowPowerDissipationInput(index) {
      let v = String(this.selectedMachineRows[index].powerDissipation ?? "");
      v = v.replace(/[^0-9.]/g, "");
      const firstDot = v.indexOf(".");
      if (firstDot !== -1) {
        v = v.slice(0, firstDot + 1) + v.slice(firstDot + 1).replace(/\./g, "");
      }
      const endsWithDot = v.endsWith(".");
      const parts = v.split(".");
      let intPart = parts[0] || "";
      let decPart = parts[1] || "";
      if (intPart.length > 6) intPart = intPart.slice(0, 6);
      if (decPart) decPart = decPart.slice(0, 4);
      v = decPart.length
        ? `${intPart}.${decPart}`
        : endsWithDot
        ? `${intPart}.`
        : intPart;
      this.$set(this.selectedMachineRows[index], "powerDissipation", v);
    },
    /**
     * 行内功耗校验
     */
    handleRowPowerDissipationBlur(index) {
      const raw = String(
        this.selectedMachineRows[index].powerDissipation ?? ""
      );
      const pattern = /^\d{1,6}(\.\d{1,4})?$/;
      if (!raw || Number(raw) <= 0 || !pattern.test(raw)) {
        this.$message.warning("功耗需大于0，整数最多6位，小数最多4位");
        this.$set(this.selectedMachineRows[index], "powerDissipation", "");
      }
    },
    /**
     * 行内理论算力输入（限制：整数最多6位，小数最多4位）
     */
    handleRowTheoryPowerInput(index) {
      let v = String(this.selectedMachineRows[index].theoryPower ?? "");
      v = v.replace(/[^0-9.]/g, "");
      const firstDot = v.indexOf(".");
      if (firstDot !== -1) {
        v = v.slice(0, firstDot + 1) + v.slice(firstDot + 1).replace(/\./g, "");
      }
      const endsWithDot = v.endsWith(".");
      const parts = v.split(".");
      let intPart = parts[0] || "";
      let decPart = parts[1] || "";
      if (intPart.length > 6) intPart = intPart.slice(0, 6);
      if (decPart) decPart = decPart.slice(0, 4);
      v = decPart.length
        ? `${intPart}.${decPart}`
        : endsWithDot
        ? `${intPart}.`
        : intPart;
      this.$set(this.selectedMachineRows[index], "theoryPower", v);
    },
    /**
     * 行内理论算力校验
     */
    handleRowTheoryPowerBlur(index) {
      const raw = String(this.selectedMachineRows[index].theoryPower ?? "");
      const pattern = /^\d{1,6}(\.\d{1,4})?$/;
      if (!raw || Number(raw) <= 0 || !pattern.test(raw)) {
        this.$message.warning("理论算力需大于0，整数最多6位，小数最多4位");
        this.$set(this.selectedMachineRows[index], "theoryPower", "");
      }
    },
    /**
     * 行内单位变更
     */
    handleRowUnitChange(index, value) {
      this.$set(this.selectedMachineRows[index], "unit", value);
    },
    syncMaxLeaseDaysToRows() {
      const raw = this.form.maxLeaseDays;
      const n = Number(raw);
      if (!Number.isInteger(n)) return;
      const oldBaseline = this.lastMaxLeaseDaysBaseline;
      this.selectedMachineRows = this.selectedMachineRows.map((row) => {
        const rowNum = Number(row.maxLeaseDays);
        if (!Number.isInteger(rowNum) || rowNum === oldBaseline) {
          return { ...row, maxLeaseDays: n };
        }
        return row;
      });
      this.lastMaxLeaseDaysBaseline = n;
    },
    handleRowMaxLeaseDaysInput(index) {
      let v = String(this.selectedMachineRows[index].maxLeaseDays ?? "");
      v = v.replace(/\D/g, "");
      if (v.length > 3) v = v.slice(0, 3);
      this.$set(this.selectedMachineRows[index], "maxLeaseDays", v);
    },
    handleRowMaxLeaseDaysBlur(index) {
      const raw = String(this.selectedMachineRows[index].maxLeaseDays ?? "");
      if (!/^\d{1,3}$/.test(raw)) {
        this.$message.warning("最大租赁天数需为 1-365 的整数");
        this.$set(this.selectedMachineRows[index], "maxLeaseDays", "");
        return;
      }
      const n = Number(raw);
      if (!Number.isInteger(n) || n < 1 || n > 365) {
        this.$message.warning("最大租赁天数需为 1-365 的整数");
        this.$set(this.selectedMachineRows[index], "maxLeaseDays", "");
      }
    },
    handleRowPriceInput(index) {
      // 价格输入：整数最多12位，小数最多2位；允许尾随小数点
      let v = String(this.selectedMachineRows[index].price ?? "");
      v = v.replace(/[^0-9.]/g, "");
      const firstDot = v.indexOf(".");
      if (firstDot !== -1) {
        v = v.slice(0, firstDot + 1) + v.slice(firstDot + 1).replace(/\./g, "");
      }
      const endsWithDot = v.endsWith(".");
      const parts = v.split(".");
      let intPart = parts[0] || "";
      let decPart = parts[1] || "";
      if (intPart.length > 12) {
        intPart = intPart.slice(0, 12);
      }
      if (decPart) {
        decPart = decPart.slice(0, 2);
      }
      v = decPart.length
        ? `${intPart}.${decPart}`
        : endsWithDot
        ? `${intPart}.`
        : intPart;
      this.$set(this.selectedMachineRows[index], "price", v);
    },
    /** 行内多结算币种价格输入 */
    handleRowPriceMapInput(index, key) {
      // 价格输入：整数最多12位，小数最多2位；允许尾随小数点
      const row = this.selectedMachineRows[index];
      const map = { ...(row.priceMap || {}) };
      let v = String(map[key] ?? "");
      v = v.replace(/[^0-9.]/g, "");
      const firstDot = v.indexOf(".");
      if (firstDot !== -1) {
        v = v.slice(0, firstDot + 1) + v.slice(firstDot + 1).replace(/\./g, "");
      }
      const endsWithDot = v.endsWith(".");
      const parts = v.split(".");
      let intPart = parts[0] || "";
      let decPart = parts[1] || "";
      if (intPart.length > 12) intPart = intPart.slice(0, 12);
      if (decPart) decPart = decPart.slice(0, 2);
      v = decPart.length
        ? `${intPart}.${decPart}`
        : endsWithDot
        ? `${intPart}.`
        : intPart;
      map[key] = v;
      this.$set(this.selectedMachineRows[index], "priceMap", map);
    },
    handleRowPriceMapBlur(index, key) {
      const row = this.selectedMachineRows[index];
      const raw = String((row.priceMap && row.priceMap[key]) ?? "");
      const pattern = /^\d{1,12}(\.\d{1,2})?$/;
      if (!raw || Number(raw) <= 0 || !pattern.test(raw)) {
        this.$message.warning("价格必须大于0，整数最多12位，小数最多2位");
        const map = { ...(row.priceMap || {}) };
        map[key] = "";
        this.$set(this.selectedMachineRows[index], "priceMap", map);
      }
    },
    handleRowPriceBlur(index) {
      const raw = String(this.selectedMachineRows[index].price ?? "");
      const pattern = /^\d{1,12}(\.\d{1,2})?$/;
      if (!raw || Number(raw) <= 0 || !pattern.test(raw)) {
        this.$message.warning("价格必须大于0，整数最多12位，小数最多2位");
        this.$set(this.selectedMachineRows[index], "price", "");
      }
    },
    handleRowTypeInput(index) {
      // 处理矿机型号输入
      const raw = String(this.selectedMachineRows[index].type || "");
      const v = raw.length > 20 ? raw.slice(0, 20) : raw;
      this.$set(this.selectedMachineRows[index], "type", v);
    },
    handleRowTypeBlur(index) {
      const raw = this.selectedMachineRows[index].type;
      const isOnlySpaces = (v) =>
        typeof v === "string" && v.length > 0 && v.trim().length === 0;
      if (isOnlySpaces(raw)) {
        this.$message.warning("矿机型号不能全是空格");
        this.$set(this.selectedMachineRows[index], "type", "");
      }
    },
    handleToggleState(index) {
      // 切换上下架状态：0上架，1下架
      const currentState = this.selectedMachineRows[index].state;
      this.$set(
        this.selectedMachineRows[index],
        "state",
        currentState === 0 ? 1 : 0
      );
    },
    async fetchMiners() {
      this.minersLoading = true;
      try {
        // 按商品币种筛选挖矿账户
        const res = await getUserMinersList({ coin: this.form.coin || "" });
        const data = res?.data;
        let list = [];
        if (Array.isArray(data)) {
          list = data;
        } else if (data && typeof data === "object") {
          // 现在的结构是 { coin: [ { user, coin }, ... ], coin2: [...] }
          Object.keys(data).forEach((coinKey) => {
            const arr = Array.isArray(data[coinKey]) ? data[coinKey] : [];
            arr.forEach((item) => {
              if (item && item.user && item.coin) {
                list.push({
                  user: item.user,
                  coin: item.coin,
                  miner: item.miner || null,
                });
              }
            });
          });
        } else if (data && data.additionalProperties1) {
          list = [data.additionalProperties1];
        }

        // 如页面带了 product coin，则仅展示该币种的账户
        if (this.form.coin) {
          list = list.filter((i) => i.coin === this.form.coin);
        }
        this.miners = list;
      } catch (e) {
        console.error("获取挖矿账户失败", e);
      } finally {
        this.minersLoading = false;
      }
    },
    async handleMinerChange(val) {
      this.selectedMachines = [];
      if (!val) {
        this.machineOptions = [];
        return;
      }
      const [user, coin] = val.split("|");
      this.machinesLoading = true;
      try {
        // 按照API文档要求，传递 userMinerVo 对象
        const userMinerVo = {
          coin: coin,
          user: user,
        };
        const res = await getUserMachineList(userMinerVo);
        const data = res?.data || [];
        this.machineOptions = Array.isArray(data) ? data : [];

        // 调试信息
        console.log("选择挖矿账户:", { user, coin });
        console.log("获取机器列表响应:", res);
        console.log("机器列表数据:", this.machineOptions);
      } catch (e) {
        console.error("获取机器列表失败", e);
      } finally {
        this.machinesLoading = false;
      }
    },
    async handleSave() {
      // 表单校验（除矿机型号外其他必填）
      try {
        const ok = await this.$refs.machineForm.validate();
        if (!ok) {
          return;
        }
      } catch (e) {
        return;
      }
      // if (!this.form.productId) {
      //   this.$message.warning('缺少商品ID')
      //   return
      // }
      // 现在统一按出售数量提交（GPU 模式不在本页提交）
      {
        // ASIC：校验出售机器数量（允许 0-9999；为 0 则提示）
        const raw = String(this.form.sellCount ?? "");
        if (raw === "") {
          this.$message.warning("请输入出售机器数量");
          return;
        }
        const n = Number(raw);
        if (!Number.isInteger(n) || n < 0 || n > 9999) {
          this.$message.warning("出售机器数量需为 0-9999 的整数");
          return;
        }
        if (n === 0) {
          this.$message.warning("出售机器数量为 0，无需提交");
          return;
        }
      }
      // 校验：矿机型号不可全空格（允许为空或包含空格的正常文本）
      const isOnlySpaces = (v) =>
        typeof v === "string" && v.length > 0 && v.trim().length === 0;
      if (isOnlySpaces(this.form.type)) {
        this.$message.warning("矿机型号不能全是空格");
        return;
      }
      const invalidTypeRowIndex = this.selectedMachineRows.findIndex((r) =>
        isOnlySpaces(r.type)
      );
      if (invalidTypeRowIndex !== -1) {
        this.$message.warning("存在行的矿机型号全是空格，请修正后再试");
        return;
      }
      // 统一售价与最大租赁天数已在表单级校验中处理，无需逐机校验
      // 组装确认数据并弹框
      const coinStr = this.buildCoinCsvFromRows();
      const algoStr = this.buildAlgoCsvFromRows();
      this.confirmData = {
        coin: coinStr || "-",
        algorithm: algoStr || "-",
        maxLeaseDays: this.form.maxLeaseDays,
        saleNumbers: this.form.sellCount,
        priceList: this.buildPriceList(),
      };
      this.confirmVisible = true;
    },
    async doSubmit() {
      this.saving = true;
      try {
        // 统一售卖新增接口参数
        const list = (this.form.coinAndAlgoList || []).map((r) => ({
          coin: String(r.coin || "")
            .toUpperCase()
            .trim(),
          algorithm: String(r.algorithm || "")
            .toUpperCase()
            .trim(),
          theoryPower: Number(r.theoryPower) || 0,
          unit: r.unit,
        }));
        const payload = {
          // 逗号分隔（中英文逗号都兼容），统一为英文逗号并大写
          coinAndAlgoList: list,
          maxLeaseDays: Number(this.form.maxLeaseDays) || 0,
          name: this.form.type,
          powerDissipation: Number(this.form.powerDissipation) || 0,
          saleNumbers: Number(this.form.sellCount) || 0,
          priceList: this.buildPriceList(),
        };
        // 过滤空价目
        payload.priceList = (payload.priceList || []).filter(
          (p) => Number(p.price) > 0
        );

        console.log(payload, "请求参数");

        const res = await addAsicMachine(payload);
        if (res && (res.code === 0 || res.code === 200)) {
          this.$message({
            message: "创建成功",
            duration: 3000,
            showClose: true,
            type: "success",
          });
          this.confirmVisible = false;
          this.$router.push("/account/products");
        }
      } catch (e) {
        console.error("创建商品失败", e);
        console.log("创建失败");
      } finally {
        this.saving = false;
      }
    },
  },
};
</script>

<style scoped>
.product-machine-add {
  padding: 8px;
}
.header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}
.title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}
.notice-alert {
  margin-bottom: 12px;
}
.notice-alert :deep(.el-alert__content) {
  text-align: left;
}
.notice-alert :deep(.el-alert__title),
.notice-alert :deep(.el-alert__description) {
  text-align: left;
}
.label-help {
  margin-left: 4px;
  color: #909399;
  cursor: help;
}
.form-card {
  margin-bottom: 12px;
}
.actions {
  text-align: left;
}

/* 统一左对齐，控件宽度 50% */
.product-machine-add :deep(.el-form-item__content) {
  justify-content: flex-start;
}
/* .product-machine-add :deep(.el-input),
.product-machine-add :deep(.el-select),
.product-machine-add :deep(.el-textarea) {
  width: 50%;
} */
.product-machine-add :deep(.el-input-group__append) {
  background: #f5f7fa;
  color: #606266;
  border-left: 1px solid #dcdfe6;
}

::v-deep .el-form-item__content {
  text-align: left;
  padding-left: 18px !important;
}

/* 多结算币种价格输入的布局优化 */
.cost-multi {
  display: grid;
  gap: 8px;
}
.cost-item {
  display: flex;
  align-items: center;
}
.price-multi {
  display: grid;
  gap: 8px;
}
.price-items {
  display: grid;
  gap: 8px;
}
/* 让 链-币种 附加区同宽、居中显示，整体对齐 */
.price-item :deep(.el-input-group__append),
.cost-item :deep(.el-input-group__append) {
  width: 110px;
  min-width: 110px;
  text-align: center;
  padding: 0 8px;
  background: #f8fafc;
  color: #606266;
}
/* 缩小输入高度并保持垂直居中 */
.price-item :deep(.el-input__inner),
.cost-item :deep(.el-input__inner) {
  height: 30px;
  line-height: 30px;
}
/* 让组内附加区高度与输入一致 */
.price-item :deep(.el-input-group__append),
.cost-item :deep(.el-input-group__append) {
  height: 30px;
  line-height: 30px;
}
/* 略微收紧间距，让整体更紧凑 */
.price-multi {
  gap: 6px;
}
.price-items {
  gap: 6px;
}
.cost-multi {
  gap: 6px;
}
/* ASIC 币种/算法/算力/单位 多行 */
.coin-algo-rows {
  display: grid;
  gap: 8px;
  width: 100%;
}
.coin-algo-line {
  display: flex;
  align-items: center;
  gap: 8px;
}
.coin-algo-line .coin-input {
  width: 18%;
  min-width: 140px;
}
.coin-algo-line .algo-input {
  width: 24%;
  min-width: 160px;
}
.coin-algo-line .power-input {
  width: 20%;
  min-width: 140px;
}
.coin-algo-line .unit-select {
  width: 16%;
  min-width: 120px;
}
.coin-algo-line .op-btn {
  flex: 0 0 auto;
}
/* GPU 引导区域样式 */
.gpu-guide-section {
  margin-bottom: 12px;
  margin-left: 86px;
}
.gpu-guide-card {
  padding: 20px;
  background: #f9fafb;
   width: 85%;
}
.gpu-guide-content {
  text-align: left;
  line-height: 1.7;
  font-size: 15px;
  color: #555;
}
.gpu-guide-title {
  margin-bottom: 8px;
  font-weight: 600;
  font-size: 16px;
  color: #333;
}
.gpu-guide-list {
  padding-left: 18px;
  margin: 0;
  font-size: 15px;
  line-height: 1.8;
}
.gpu-guide-list li {
  margin-bottom: 8px;
}
.gpu-guide-list li:last-child {
  margin-bottom: 0;
}
.gpu-guide-buttons {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
}
</style>

