<template>
  <div class="app-container">
    <el-card shadow="never">
      <el-form ref="queryForm" :model="queryParams" size="small" :inline="true">
        <el-form-item>
          <template slot="label">{{ tmT("queryQuoteDate") }}</template>
          <el-date-picker
            v-model="queryDateRange"
            type="daterange"
            value-format="yyyy-MM-dd"
            :range-separator="'-'"
            :start-placeholder="tmT('queryDateRangePh')"
            :end-placeholder="tmT('queryDateRangeEndPh')"
            clearable
            style="width: 240px"
          />
        </el-form-item>
        <el-form-item prop="tradeMarketId">
          <template slot="label">{{ tmT("queryTradeMarket") }}</template>
          <el-select v-model="queryParams.tradeMarketId" :placeholder="tmCommon('pleaseSelect')" clearable filterable style="width: 180px">
            <el-option v-for="item in tradeMarketOptions" :key="item.id" :label="item.marketName" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item prop="queryCountyCode">
          <template slot="label">{{ tmT("queryOrigin") }}</template>
          <region-cascader
            :province-code.sync="queryRegion.provinceCode"
            :province-name.sync="queryRegion.provinceName"
            :city-code.sync="queryRegion.cityCode"
            :city-name.sync="queryRegion.cityName"
            :county-code.sync="queryRegion.countyCode"
            :county-name.sync="queryRegion.countyName"
            :placeholder="tmCommon('pleaseSelect')"
            style="width: 220px; display: inline-block"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">{{ tmCommon("search") }}</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">{{ tmCommon("reset") }}</el-button>
          <el-button
            v-hasPermi="['tradeMarket:marketQuote:add']"
            type="primary"
            plain
            icon="el-icon-plus"
            size="mini"
            @click="handleAdd"
          >{{ tmCommon("add") }}</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <br />

    <el-card shadow="never">
      <el-table v-loading="loading" :data="tableList" border>
        <el-table-column :label="tmT('colQuoteDate')" prop="quoteDate" align="center" width="110" fixed="left" />
        <el-table-column :label="tmT('colOrigin')" align="center" min-width="140" :show-overflow-tooltip="true">
          <template slot-scope="scope">
            <span>{{ formatOrigin(scope.row) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tmT('colTradeMarket')" prop="tradeMarketName" align="center" min-width="120" :show-overflow-tooltip="true" />
        <el-table-column :label="tmT('colCattleGender')" align="center" width="90">
          <template slot-scope="scope">
            <span>{{ labelEnum("cattleGender", scope.row.cattleGender, scope.row.cattleGenderName) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tmT('colWeightGrade')" align="center" width="100">
          <template slot-scope="scope">
            <span>{{ labelEnum("weightGrade", scope.row.weightGrade, scope.row.weightGradeName) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tmT('colPriceRange')" align="center" min-width="130">
          <template slot-scope="scope">
            <span>{{ formatPriceRange(scope.row) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tmT('colAvgPrice')" align="center" width="100">
          <template slot-scope="scope">
            <span>{{ formatAvgPrice(scope.row) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tmT('colSupplyStatus')" align="center" width="100">
          <template slot-scope="scope">
            <span>{{ labelEnum("supplyStatus", scope.row.supplyStatus, scope.row.supplyStatusName) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tmCommon('colOp')" align="center" class-name="small-padding fixed-width" width="180" fixed="right">
          <template slot-scope="scope">
            <el-button v-hasPermi="['tradeMarket:marketQuote:query']" type="text" size="mini" @click="handleView(scope.row)">{{ tmCommon("view") }}</el-button>
            <el-button v-hasPermi="['tradeMarket:marketQuote:edit']" type="text" size="mini" @click="handleEdit(scope.row)">{{ tmCommon("edit") }}</el-button>
            <el-button v-hasPermi="['tradeMarket:marketQuote:remove']" type="text" size="mini" @click="handleDelete(scope.row)">{{ tmCommon("delete") }}</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="total > 0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getList"
      />
    </el-card>

    <el-dialog :title="dialogTitle" :visible.sync="open" width="960px" append-to-body @close="cancel">
      <el-form :key="formKey" ref="form" :model="form" label-width="130px">
        <el-row :gutter="16">
          <el-col :span="12">
            <el-form-item prop="quoteDate" :rules="formRules.quoteDate">
              <template slot="label">{{ tmT("formQuoteDate") }}</template>
              <el-date-picker
                v-model="form.quoteDate"
                type="date"
                value-format="yyyy-MM-dd"
                :placeholder="tmCommon('pleaseSelect')"
                style="width: 100%"
                @change="onPriceChange"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="tradeMarketId" :rules="formRules.tradeMarketId">
              <template slot="label">{{ tmT("formTradeMarket") }}</template>
              <el-select v-model="form.tradeMarketId" :placeholder="tmCommon('pleaseSelect')" filterable style="width: 100%">
                <el-option v-for="item in tradeMarketOptions" :key="item.id" :label="item.marketName" :value="item.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item prop="regionCodes" :rules="formRules.regionCodes">
              <template slot="label">{{ tmT("formOrigin") }}</template>
              <region-cascader
                :province-code.sync="form.provinceCode"
                :province-name.sync="form.provinceName"
                :city-code.sync="form.cityCode"
                :city-name.sync="form.cityName"
                :county-code.sync="form.countyCode"
                :county-name.sync="form.countyName"
                :placeholder="tmCommon('pleaseSelect')"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="cattleGender" :rules="formRules.cattleGender">
              <template slot="label">{{ tmT("formCattleGender") }}</template>
              <el-select v-model="form.cattleGender" :placeholder="tmCommon('pleaseSelect')" style="width: 100%">
                <el-option v-for="item in cattleGenderOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="weightGrade">
              <template slot="label">{{ tmT("formWeightGrade") }}</template>
              <el-select v-model="form.weightGrade" :placeholder="tmCommon('pleaseSelect')" clearable style="width: 100%">
                <el-option v-for="item in weightGradeOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="growthStage">
              <template slot="label">{{ tmT("formGrowthStage") }}</template>
              <el-select v-model="form.growthStage" :placeholder="tmCommon('pleaseSelect')" clearable style="width: 100%">
                <el-option v-for="item in growthStageOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="ageMonthGrade">
              <template slot="label">{{ tmT("formAgeMonthGrade") }}</template>
              <el-select v-model="form.ageMonthGrade" :placeholder="tmCommon('pleaseSelect')" clearable style="width: 100%">
                <el-option v-for="item in ageMonthGradeOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="fatGrade">
              <template slot="label">{{ tmT("formFatGrade") }}</template>
              <el-select v-model="form.fatGrade" :placeholder="tmCommon('pleaseSelect')" clearable style="width: 100%">
                <el-option v-for="item in fatGradeOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item prop="supplyStatus" :rules="formRules.supplyStatus">
              <template slot="label">{{ tmT("formSupplyStatus") }}</template>
              <el-select v-model="form.supplyStatus" :placeholder="tmCommon('pleaseSelect')" style="width: 100%">
                <el-option v-for="item in supplyStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="priceMin" :rules="formRules.priceMin">
              <template slot="label">{{ tmT("formPriceMin") }}</template>
              <el-input v-model="form.priceMin" :placeholder="tmT('phPrice')" @input="onPriceChange" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="priceMax" :rules="formRules.priceMax">
              <template slot="label">{{ tmT("formPriceMax") }}</template>
              <el-input v-model="form.priceMax" :placeholder="tmT('phPrice')" @input="onPriceChange" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="priceUnit" :rules="formRules.priceUnit">
              <template slot="label">{{ tmT("formPriceUnit") }}</template>
              <el-select v-model="form.priceUnit" :placeholder="tmCommon('pleaseSelect')" style="width: 100%" @change="onPriceChange">
                <el-option v-for="item in priceUnitOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('formAvgPrice')">
              <el-input :value="displayAvgPrice" disabled>
                <template slot="append">{{ priceUnitLabel(form.priceUnit) }}</template>
              </el-input>
              <div class="el-form-item__tip" style="line-height: 1.4">{{ tmT("tipAvgAuto") }}</div>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item prop="changeFactors" :rules="formRules.changeFactors">
              <template slot="label">{{ tmT("formChangeFactors") }}</template>
              <el-checkbox-group v-model="form.changeFactors">
                <el-checkbox v-for="item in changeFactorOptions" :key="item.value" :label="item.value">{{ item.label }}</el-checkbox>
              </el-checkbox-group>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="probRise" :rules="formRules.probRise">
              <template slot="label">{{ tmT("formProbRise") }}</template>
              <el-input v-model="form.probRise" :placeholder="tmT('phPrice')">
                <template slot="append">{{ tmT("probUnit") }}</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="probFlat" :rules="formRules.probFlat">
              <template slot="label">{{ tmT("formProbFlat") }}</template>
              <el-input v-model="form.probFlat" :placeholder="tmT('phPrice')">
                <template slot="append">{{ tmT("probUnit") }}</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item prop="probFall" :rules="formRules.probFall">
              <template slot="label">{{ tmT("formProbFall") }}</template>
              <el-input v-model="form.probFall" :placeholder="tmT('phPrice')">
                <template slot="append">{{ tmT("probUnit") }}</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item prop="outboundAdvice" :rules="formRules.outboundAdvice">
              <template slot="label">{{ tmT("formOutboundAdvice") }}</template>
              <el-input v-model="form.outboundAdvice" type="textarea" :rows="3" :placeholder="tmT('phOutboundAdvice')" maxlength="500" show-word-limit />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">{{ tmCommon("ok") }}</el-button>
        <el-button @click="cancel">{{ tmCommon("cancel") }}</el-button>
      </div>
    </el-dialog>

    <el-dialog :title="tmCommon('viewTitle')" :visible.sync="viewOpen" width="960px" append-to-body>
      <el-form label-width="130px" size="small">
        <el-row :gutter="16">
          <el-col :span="12">
            <el-form-item :label="tmT('formQuoteDate')">
              <span>{{ viewRow.quoteDate || dash }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('formTradeMarket')">
              <span>{{ viewRow.tradeMarketName || dash }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="tmT('formOrigin')">
              <span>{{ formatOrigin(viewRow) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('formCattleGender')">
              <span>{{ labelEnum("cattleGender", viewRow.cattleGender, viewRow.cattleGenderName) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('formWeightGrade')">
              <span>{{ labelEnum("weightGrade", viewRow.weightGrade, viewRow.weightGradeName) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('formGrowthStage')">
              <span>{{ labelEnum("growthStage", viewRow.growthStage, viewRow.growthStageName) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('formAgeMonthGrade')">
              <span>{{ labelEnum("ageMonthGrade", viewRow.ageMonthGrade, viewRow.ageMonthGradeName) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('formFatGrade')">
              <span>{{ labelEnum("fatGrade", viewRow.fatGrade, viewRow.fatGradeName) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('formSupplyStatus')">
              <span>{{ labelEnum("supplyStatus", viewRow.supplyStatus, viewRow.supplyStatusName) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('colPriceRange')">
              <span>{{ formatPriceRange(viewRow) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('formAvgPrice')">
              <span>{{ formatAvgPrice(viewRow) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="tmT('viewChangeFactors')">
              <span>{{ viewChangeFactorText }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="tmT('viewProb')">
              <span>{{ formatProbView(viewRow) }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="tmT('formOutboundAdvice')">
              <span class="pre-wrap">{{ viewRow.outboundAdvice || dash }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('viewCreateBy')">
              <span>{{ viewRow.createBy || dash }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('viewCreateTime')">
              <span>{{ viewRow.createTime ? parseTime(viewRow.createTime) : dash }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('viewUpdateBy')">
              <span>{{ viewRow.updateBy || dash }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item :label="tmT('viewUpdateTime')">
              <span>{{ viewRow.updateTime ? parseTime(viewRow.updateTime) : dash }}</span>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button v-hasPermi="['tradeMarket:marketQuote:edit']" type="primary" plain @click="openEditFromView">{{ tmCommon("edit") }}</el-button>
        <el-button v-hasPermi="['tradeMarket:marketQuote:remove']" type="danger" plain @click="handleDelete(viewRow)">{{ tmCommon("delete") }}</el-button>
        <el-button @click="viewOpen = false">{{ tmCommon("close") }}</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import tradeMarketLocaleMixin from "@/mixins/tradeMarketLocaleMixin"
import RegionCascader from "@/components/RegionCascader/index.vue"
import {
  listMarketQuote,
  getMarketQuote,
  addMarketQuote,
  updateMarketQuote,
  delMarketQuote,
  listTradeMarketOptions
} from "@/api/tradeMarket/marketQuote"

const PROB_SUM_TOLERANCE = 0.01
const OUTBOUND_MAX = 500

function formatYmd(d) {
  const y = d.getFullYear()
  const m = String(d.getMonth() + 1).padStart(2, "0")
  const day = String(d.getDate()).padStart(2, "0")
  return `${y}-${m}-${day}`
}

function yesterdayYmd() {
  const d = new Date()
  d.setDate(d.getDate() - 1)
  return formatYmd(d)
}

function todayYmd() {
  return formatYmd(new Date())
}

function createEmptyForm() {
  return {
    id: undefined,
    quoteDate: yesterdayYmd(),
    provinceCode: undefined,
    provinceName: undefined,
    cityCode: undefined,
    cityName: undefined,
    countyCode: undefined,
    countyName: undefined,
    tradeMarketId: undefined,
    cattleGender: 1,
    weightGrade: undefined,
    growthStage: undefined,
    ageMonthGrade: undefined,
    fatGrade: undefined,
    priceMin: undefined,
    priceMax: undefined,
    priceUnit: 2,
    supplyStatus: undefined,
    changeFactors: [],
    probRise: undefined,
    probFlat: undefined,
    probFall: undefined,
    outboundAdvice: undefined
  }
}

function parseChangeFactors(val) {
  if (val == null || val === "") {
    return []
  }
  if (Array.isArray(val)) {
    return val.map((n) => Number(n)).filter((n) => !isNaN(n) && n > 0)
  }
  return String(val)
    .split(",")
    .map((s) => Number(s.trim()))
    .filter((n) => !isNaN(n) && n > 0)
}

/** 详情/列表：优先 changeFactorList，与后端 MarketDailyQuoteLabelResolver 一致 */
function resolveChangeFactorsFromApi(data) {
  if (!data) {
    return []
  }
  if (data.changeFactorList && data.changeFactorList.length) {
    return parseChangeFactors(data.changeFactorList)
  }
  return parseChangeFactors(data.changeFactors)
}

export default {
  name: "TradeMarketMarketQuote",
  components: { RegionCascader },
  mixins: [tradeMarketLocaleMixin],
  data() {
    return {
      tmNs: "marketQuote",
      loading: false,
      open: false,
      viewOpen: false,
      viewRow: {},
      dialogEdit: false,
      formKey: 0,
      total: 0,
      tableList: [],
      tradeMarketOptions: [],
      queryDateRange: [],
      queryRegion: {
        provinceCode: undefined,
        provinceName: undefined,
        cityCode: undefined,
        cityName: undefined,
        countyCode: undefined,
        countyName: undefined
      },
      queryParams: {
        pageNum: 1,
        pageSize: 20,
        tradeMarketId: undefined,
        countyCode: undefined
      },
      form: createEmptyForm()
    }
  },
  computed: {
    dash() {
      return this.$t("tradeMarket.status.dash")
    },
    dialogTitle() {
      return this.dialogEdit ? this.tmT("dialogEdit") : this.tmT("dialogAdd")
    },
    cattleGenderOptions() {
      return [1, 2, 3].map((v) => ({ value: v, label: this.tmT("cattleGender" + v) }))
    },
    weightGradeOptions() {
      return [1, 2, 3, 4, 5, 6, 7].map((v) => ({ value: v, label: this.tmT("weightGrade" + v) }))
    },
    growthStageOptions() {
      return [1, 2, 3].map((v) => ({ value: v, label: this.tmT("growthStage" + v) }))
    },
    ageMonthGradeOptions() {
      return [1, 2, 3, 4, 5, 6, 7].map((v) => ({ value: v, label: this.tmT("ageMonthGrade" + v) }))
    },
    fatGradeOptions() {
      return [1, 2, 3, 4].map((v) => ({ value: v, label: this.tmT("fatGrade" + v) }))
    },
    priceUnitOptions() {
      return [1, 2].map((v) => ({ value: v, label: this.tmT("priceUnit" + v) }))
    },
    supplyStatusOptions() {
      return [1, 2, 3].map((v) => ({ value: v, label: this.tmT("supplyStatus" + v) }))
    },
    changeFactorOptions() {
      return [1, 2, 3, 4, 5, 6, 7, 8].map((v) => ({ value: v, label: this.tmT("changeFactor" + v) }))
    },
    displayAvgPrice() {
      const min = Number(this.form.priceMin)
      const max = Number(this.form.priceMax)
      if (!min || !max || min <= 0 || max <= 0 || min > max) {
        return ""
      }
      return ((min + max) / 2).toFixed(2)
    },
    viewChangeFactorText() {
      if (this.viewRow.changeFactorNames) {
        return this.viewRow.changeFactorNames
      }
      const codes = resolveChangeFactorsFromApi(this.viewRow)
      if (!codes.length) {
        return this.dash
      }
      return codes.map((c) => this.tmT("changeFactor" + c)).join("、")
    },
    formRules() {
      return {
        quoteDate: [
          { required: true, message: this.tmT("ruleQuoteDateRequired"), trigger: "change" },
          { validator: this.validateQuoteDate, trigger: "change" }
        ],
        regionCodes: [{ validator: this.validateRegion, trigger: "change" }],
        tradeMarketId: [{ required: true, message: this.tmT("ruleTradeMarketRequired"), trigger: "change" }],
        cattleGender: [{ required: true, message: this.tmT("ruleCattleGenderRequired"), trigger: "change" }],
        priceMin: [
          { required: true, message: this.tmT("rulePriceMinRequired"), trigger: "blur" },
          { validator: this.validatePriceMin, trigger: "blur" }
        ],
        priceMax: [
          { required: true, message: this.tmT("rulePriceMaxRequired"), trigger: "blur" },
          { validator: this.validatePriceMax, trigger: "blur" }
        ],
        priceUnit: [{ required: true, message: this.tmT("rulePriceUnitRequired"), trigger: "change" }],
        supplyStatus: [{ required: true, message: this.tmT("ruleSupplyStatusRequired"), trigger: "change" }],
        changeFactors: [{ validator: this.validateChangeFactors, trigger: "change" }],
        probRise: [{ validator: this.validateProbField, trigger: "blur" }],
        probFlat: [{ validator: this.validateProbField, trigger: "blur" }],
        probFall: [{ validator: this.validateProbField, trigger: "blur" }],
        outboundAdvice: [
          { required: true, message: this.tmT("ruleOutboundRequired"), trigger: "blur" },
          { validator: this.validateOutbound, trigger: "blur" }
        ]
      }
    }
  },
  watch: {
    "queryRegion.countyCode"(val) {
      this.queryParams.countyCode = val || undefined
    }
  },
  created() {
    this.loadTradeMarketOptions()
    this.getList()
  },
  methods: {
    labelEnum(prefix, val, nameFromApi) {
      if (nameFromApi) {
        return nameFromApi
      }
      if (val == null || val === "") {
        return this.dash
      }
      return this.tmT(prefix + val) || val
    },
    priceUnitLabel(unit) {
      if (unit == null || unit === "") {
        return ""
      }
      return this.tmT("priceUnit" + unit) || ""
    },
    formatOrigin(row) {
      if (!row) {
        return this.dash
      }
      const parts = [row.provinceName, row.cityName, row.countyName].filter(Boolean)
      return parts.length ? parts.join("") : this.dash
    },
    formatPriceRange(row) {
      if (!row || row.priceMin == null || row.priceMax == null) {
        return this.dash
      }
      const unit = row.priceUnitName || this.priceUnitLabel(row.priceUnit)
      return `${row.priceMin}～${row.priceMax} ${unit}`.trim()
    },
    formatAvgPrice(row) {
      if (!row || row.avgPrice == null) {
        return this.dash
      }
      const unit = row.priceUnitName || this.priceUnitLabel(row.priceUnit)
      return `${row.avgPrice} ${unit}`.trim()
    },
    formatProbView(row) {
      if (!row) {
        return this.dash
      }
      return `看涨 ${row.probRise || 0}% / 看平 ${row.probFlat || 0}% / 看跌 ${row.probFall || 0}%`
    },
    calcAvgNumber() {
      const min = Number(this.form.priceMin)
      const max = Number(this.form.priceMax)
      if (!min || !max || min <= 0 || max <= 0 || min > max) {
        return null
      }
      return Number(((min + max) / 2).toFixed(2))
    },
    onPriceChange() {
      // 触发均价展示更新（computed displayAvgPrice）
    },
    validateQuoteDate(rule, value, callback) {
      if (!value) {
        callback()
        return
      }
      if (value > todayYmd()) {
        callback(new Error(this.tmT("ruleQuoteDateFuture")))
        return
      }
      callback()
    },
    validateRegion(rule, value, callback) {
      if (!this.form.provinceCode || !this.form.cityCode || !this.form.countyCode) {
        callback(new Error(this.tmT("ruleRegionRequired")))
        return
      }
      callback()
    },
    validatePriceMin(rule, value, callback) {
      const n = Number(value)
      if (!value || isNaN(n) || n <= 0) {
        callback(new Error(this.tmT("rulePricePositive")))
        return
      }
      callback()
    },
    validatePriceMax(rule, value, callback) {
      const n = Number(value)
      if (!value || isNaN(n) || n <= 0) {
        callback(new Error(this.tmT("rulePricePositive")))
        return
      }
      const min = Number(this.form.priceMin)
      if (!isNaN(min) && min > n) {
        callback(new Error(this.tmT("rulePriceOrder")))
        return
      }
      callback()
    },
    validateChangeFactors(rule, value, callback) {
      if (!this.form.changeFactors || !this.form.changeFactors.length) {
        callback(new Error(this.tmT("ruleChangeFactorsRequired")))
        return
      }
      callback()
    },
    validateProbField(rule, value, callback) {
      const rise = Number(this.form.probRise)
      const flat = Number(this.form.probFlat)
      const fall = Number(this.form.probFall)
      if ([this.form.probRise, this.form.probFlat, this.form.probFall].some((v) => v === "" || v == null)) {
        callback(new Error(this.tmT("ruleProbRequired")))
        return
      }
      if ([rise, flat, fall].some((n) => isNaN(n) || n <= 0 || n > 100)) {
        callback(new Error(this.tmT("ruleProbRequired")))
        return
      }
      const sum = rise + flat + fall
      if (Math.abs(sum - 100) > PROB_SUM_TOLERANCE) {
        callback(new Error(this.tmT("ruleProbSum")))
        return
      }
      callback()
    },
    validateOutbound(rule, value, callback) {
      const v = value != null ? String(value).trim() : ""
      if (!v) {
        callback(new Error(this.tmT("ruleOutboundRequired")))
        return
      }
      if (v.length > OUTBOUND_MAX) {
        callback(new Error(this.tmT("ruleOutboundLen")))
        return
      }
      callback()
    },
    loadTradeMarketOptions() {
      listTradeMarketOptions()
        .then((res) => {
          this.tradeMarketOptions = res.data || res.rows || []
        })
        .catch(() => {
          this.tradeMarketOptions = []
        })
    },
    buildListParams() {
      const params = {
        pageNum: this.queryParams.pageNum,
        pageSize: this.queryParams.pageSize,
        tradeMarketId: this.queryParams.tradeMarketId,
        countyCode: this.queryParams.countyCode
      }
      if (this.queryDateRange && this.queryDateRange.length === 2) {
        params.beginQuoteDate = this.queryDateRange[0]
        params.endQuoteDate = this.queryDateRange[1]
      }
      return params
    },
    getList() {
      this.loading = true
      listMarketQuote(this.buildListParams())
        .then((res) => {
          this.tableList = res.rows || []
          this.total = res.total != null ? res.total : 0
        })
        .finally(() => {
          this.loading = false
        })
    },
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    resetQuery() {
      this.queryDateRange = []
      this.queryParams.tradeMarketId = undefined
      this.queryParams.countyCode = undefined
      this.queryRegion = {
        provinceCode: undefined,
        provinceName: undefined,
        cityCode: undefined,
        cityName: undefined,
        countyCode: undefined,
        countyName: undefined
      }
      this.resetForm("queryForm")
      this.handleQuery()
    },
    resetFormModel() {
      this.form = createEmptyForm()
    },
    fillFormFromData(data) {
      this.form = Object.assign(createEmptyForm(), {
        id: data.id,
        quoteDate: data.quoteDate,
        provinceCode: data.provinceCode,
        provinceName: data.provinceName,
        cityCode: data.cityCode,
        cityName: data.cityName,
        countyCode: data.countyCode,
        countyName: data.countyName,
        tradeMarketId: data.tradeMarketId,
        cattleGender: data.cattleGender != null ? data.cattleGender : 1,
        weightGrade: data.weightGrade,
        growthStage: data.growthStage,
        ageMonthGrade: data.ageMonthGrade,
        fatGrade: data.fatGrade,
        priceMin: data.priceMin != null ? String(data.priceMin) : undefined,
        priceMax: data.priceMax != null ? String(data.priceMax) : undefined,
        priceUnit: data.priceUnit != null ? data.priceUnit : 2,
        supplyStatus: data.supplyStatus,
        changeFactors: resolveChangeFactorsFromApi(data),
        probRise: data.probRise != null ? String(data.probRise) : undefined,
        probFlat: data.probFlat != null ? String(data.probFlat) : undefined,
        probFall: data.probFall != null ? String(data.probFall) : undefined,
        outboundAdvice: data.outboundAdvice
      })
    },
    buildPayload() {
      const avg = this.calcAvgNumber()
      return {
        quoteDate: this.form.quoteDate,
        provinceCode: this.form.provinceCode,
        provinceName: this.form.provinceName,
        cityCode: this.form.cityCode,
        cityName: this.form.cityName,
        countyCode: this.form.countyCode,
        countyName: this.form.countyName,
        tradeMarketId: this.form.tradeMarketId,
        cattleGender: this.form.cattleGender,
        weightGrade: this.form.weightGrade || null,
        growthStage: this.form.growthStage || null,
        ageMonthGrade: this.form.ageMonthGrade || null,
        fatGrade: this.form.fatGrade || null,
        priceMin: Number(this.form.priceMin),
        priceMax: Number(this.form.priceMax),
        priceUnit: this.form.priceUnit,
        avgPrice: avg,
        supplyStatus: this.form.supplyStatus,
        changeFactorList: [...this.form.changeFactors].sort((a, b) => a - b),
        probRise: Number(this.form.probRise),
        probFlat: Number(this.form.probFlat),
        probFall: Number(this.form.probFall),
        outboundAdvice: String(this.form.outboundAdvice).trim()
      }
    },
    handleAdd() {
      this.formKey += 1
      this.resetFormModel()
      this.dialogEdit = false
      this.open = true
      this.$nextTick(() => {
        if (this.$refs.form) {
          this.$refs.form.clearValidate()
        }
      })
    },
    handleEdit(row) {
      getMarketQuote(row.id).then((res) => {
        const data = res.data || {}
        this.formKey += 1
        this.dialogEdit = true
        this.fillFormFromData(data)
        this.open = true
        this.viewOpen = false
        this.$nextTick(() => {
          if (this.$refs.form) {
            this.$refs.form.clearValidate()
          }
        })
      })
    },
    openEditFromView() {
      this.handleEdit(this.viewRow)
    },
    handleView(row) {
      getMarketQuote(row.id).then((res) => {
        this.viewRow = res.data || {}
        this.viewOpen = true
      })
    },
    handleDelete(row) {
      const date = row.quoteDate || ""
      const market = row.tradeMarketName || row.tradeMarketId || ""
      this.$modal
        .confirm(this.tmT("confirmDelete", { date: date, market: market }))
        .then(() => delMarketQuote(row.id))
        .then(() => {
          this.$modal.msgSuccess(this.tmCommon("msgDelOk"))
          this.viewOpen = false
          this.getList()
        })
        .catch(() => {})
    },
    submitForm() {
      this.$refs.form.validate((valid) => {
        if (!valid) {
          return
        }
        const avg = this.calcAvgNumber()
        if (avg == null) {
          this.$modal.msgError(this.tmT("rulePriceOrder"))
          return
        }
        const payload = this.buildPayload()
        if (this.dialogEdit) {
          payload.id = this.form.id
          updateMarketQuote(payload).then(() => {
            this.$modal.msgSuccess(this.tmCommon("msgModOk"))
            this.open = false
            this.getList()
          })
        } else {
          addMarketQuote(payload).then(() => {
            this.$modal.msgSuccess(this.tmCommon("msgAddOk"))
            this.open = false
            this.getList()
          })
        }
      })
    },
    cancel() {
      this.open = false
      this.resetFormModel()
    }
  }
}
</script>

<style scoped>
.pre-wrap {
  white-space: pre-wrap;
  word-break: break-word;
}
</style>
