<template>
  <view>
    <navbar-back :autoBack="false" titleWidth="800" :title="title" @leftClick="customBack">
      <view class="navbar-right" @click="navRightClick">
        <text>填写任务单</text>
        <u-icon color="" name="edit-pen" size="19"></u-icon>
      </view>
    </navbar-back>

    <u-row gutter="8">
      <u-col span="3">
        <up-tabs
          :current="activeAssayTypeIndex"
          :list="assayGroups"
          lineColor="#5ac725"
          :activeStyle="{
            fontWeight: 'bold',
            color: '#0055a2'
          }"
          :itemStyle="{
            height: '35px'
          }"
          @change="handleAssayTypeChange"
        ></up-tabs>
        <u-gap height="5" bg-color="#0055A2"></u-gap>
      </u-col>
      <u-col span="6">
        <view class="content-title-name">
          <view class="current-sample-code">{{ currentSampleData.sampleCode }}</view>
          <view>数据采集或录入</view>
        </view>
        <u-gap height="5" bg-color="#0055A2"></u-gap>
      </u-col>
      <u-col span="3">
        <u-dropdown style="height: 35px">
          <u-dropdown-item
            v-model="curParameterKey"
            :title="curParameterTitle"
            height="70vh"
            :options="fieldGroup"
            @change="parameterClassifyChange"
          ></u-dropdown-item>
        </u-dropdown>
        <u-gap height="5" bg-color="#0055A2"></u-gap>
      </u-col>
    </u-row>
    <u-row gutter="8" align="top">
      <u-col span="3">
        <scroll-view class="content-left-scroll" scroll-with-animation scroll-y :scroll-top="scrollTop">
          <view
            v-for="(sample, index) in sampleDataList"
            :key="index"
            class="u-tab-item"
            :class="currentSampleIndex === index ? 'u-tab-item-active' : ''"
            :data-current="index"
            @tap.stop="switchSample(index, false)"
          >
            <u-badge type="warning" :value="index + 1"></u-badge>
            <view class="ml20">
              <view>
                {{ sample.sampleCode }}
              </view>
              <view> {{ getDataSourceTypeShow(sample.dataSourceType) }}{{ sample.sampleName }} </view>
            </view>
          </view>
        </scroll-view>
        <u-button class="btn-operation" type="primary" @click="submitTask()">提交任务单</u-button>
      </u-col>
      <u-col span="6">
        <view class="field-name" v-html="selectedField.title" />
        <zzjc-num-keyboard
          ref="myKeyboard"
          v-show="selectedField.fillingWay == 'keyboard' && selectedField.type != 'select'"
          :numKeyboardParam="numKeyboardParam"
        ></zzjc-num-keyboard>
        <view v-if="selectedField.fillingWay == 'collect'" class="y-f">
          <view class="auncel" @click="selectAuncel">
            <view class="code">{{ currentAuncel.code }}</view>
            <view class="auncel-title"> 杯号：{{ currentCupNum }} </view>
            <view class="auncel-weight">
              <view class="weight">
                <view
                  :style="{ textAlign: !currentAuncel.isConnected ? 'center' : 'right' }"
                  :class="
                    currentAuncel.weightStable === 0
                      ? 'weight-data-yellow'
                      : currentAuncel.weightStable === 1
                      ? 'weight-data'
                      : 'weight-data-warning'
                  "
                >
                  {{ currentAuncel.weightData }}
                </view>
              </view>
              <view class="weight-unit">{{ currentAuncel.weightUnit }}</view>
            </view>
          </view>

          <u-button
            class="btn-operation"
            type="success"
            :disabled="confirmWeightDisabled"
            shape="circle"
            @click="saveAuncelData"
          >
            确认采集
          </u-button>
        </view>
        <view v-if="selectedField.fillingWay === 'input'" class="p8">
          <up-textarea v-model="inputValue" placeholder="请输入内容"></up-textarea>
          <view class="x-c mt20 pl100 pr100">
            <up-button @click="handleResetInputValue" style="width: 30%" :plain="true" text="清空"></up-button>
            <up-button
              @click="selectedField.value = inputValue"
              style="width: 30%"
              type="success"
              text="确认"
            ></up-button>
          </view>
        </view>
      </u-col>
      <u-col span="3">
        <view>
          <scroll-view class="content-right-scroll" scroll-y scroll-with-animation>
            <view>
              <!-- <template v-for="(fields, groupIndex) in fieldGroup" :key="'group_' + groupIndex"> -->
              <!-- <view> -->
              <!-- 组名 -->
              <!-- <view class="my-collapse" @click="fields.open = !fields.open">
                      <text class="title">{{ fields.title }}</text>
                      <u-icon :name="fields.open ? 'arrow-up' : 'arrow-down'"></u-icon>
                    </view>
                    <view
                      class="content"
                      :id="'elId' + groupIndex"
                      :style="{ height: fields.open ? collaHeights[groupIndex] + 'px' : '0' }"
                    > -->
              <up-collapse ref="collapseRef" :value="activeCollapses" :border="false">
                <template v-for="(fields, groupIndex) in currentGroup">
                  <up-collapse-item v-if="fields.label !== '全部'">
                    <template #title>
                      <text class="font-bold">{{ fields.label }}</text>
                    </template>
                    <template v-for="(field, fieldIndex) in fields.fields" :key="groupIndex + '-' + fieldIndex">
                      <view
                        class="form-item-my"
                        @click="fieldClick(field, groupIndex + '-' + fieldIndex)"
                        v-show="field.hidden != 1"
                        :class="{
                          'selected-field': groupFieldIndex === groupIndex + '-' + fieldIndex,
                          'disabled-field': !field.isEdit
                        }"
                      >
                        <view
                          :class="['label-my', { 'label-high-light': field.highlight == 1 }]"
                          v-html="field.title"
                        ></view>
                        <view class="content-my">
                          <!--
							    如果是select，渲染2个组件：1个input、1个picker.
							    field.valueText用于显示picker选中的文本
                  1，键盘输入，2、天平，3、自动计算，4、文本输入
							    -->
                          <!-- <u-input
                          border="bottom"
                          style="width: 120px"
                          v-if="field.fillingWay == 'input'"
                          v-model="field.value"
                          placeholder="请输入"
                        /> -->

                          <!-- <view v-if="field.type === 'select'" class="x-bc select-my" @click="field.showPicker = true">
                            <text v-if="field.valueText">{{ field.valueText }}</text>
                            <text v-else>请选择</text>
                            <u-icon name="arrow-down" size="20"></u-icon>
                          </view>
                          <u-picker
                            v-if="field.type === 'select'"
                            :show="field.showPicker"
                            :columns="[field.options]"
                            keyName="dictValue"
                            @cancel="field.showPicker = false"
                            @confirm="event => dicPickerConfirm(event, field)"
                          /> -->
                          <!--普通输入框 使用文本显示-->
                          <view class="content-my-text" v-if="field.dataType != 'select'">
                            <text v-if="!field.value" class="content-my-text-placeholder">{{
                              !field.fillingWay || field.fillingWay == 'calculate' ? '计算值' : '请输入'
                            }}</text>
                            <text
                              v-else
                              :class="['content-my-text-value', { 'field-high-light': field.highlight == 1 }]"
                              >{{ field.value }}</text
                            >
                          </view>
                        </view>
                      </view>
                      <view
                        v-if="field.validation"
                        class="fs12"
                        :class="field.validation?.promptType === 'warning' ? 'valid-warning' : 'valid-error'"
                        >{{ field.validation?.promptMsg }}</view
                      >
                    </template>
                  </up-collapse-item>
                </template>
              </up-collapse>
              <!-- </view>
                  </view> -->
              <!-- </template> -->
            </view>
          </scroll-view>
          <u-button class="btn-operation" type="success" @click="saveDetail()">保存样品数据</u-button>
        </view>
      </u-col>
    </u-row>
    <!--    天平选择-->
    <auncel-select-popup
      ref="auncelSelector"
      v-model:showAuncelSelector="showAuncelSelector"
      :previousAuncelId="currentAuncel.id"
      @doSelect="auncelDoSelect"
    ></auncel-select-popup>
  </view>
</template>

<script setup>
import { ref, reactive, computed, nextTick, watch, getCurrentInstance } from 'vue'
import { onLoad, onBackPress, onShow, onHide, onUnload } from '@dcloudio/uni-app'
import request from '@/nx/request'
import {
  calcAnalysisValue,
  handleRoundFiveNumber,
  calcRowAnalysisValue,
  math,
  groupByField,
  validateElementRange
} from '@/nx/helper/calcAnalysisValue'
import { number } from 'mathjs'
import AuncelSelectPopup from '@/components/sample/auncel-select-popup.vue'
import { getTenantId } from '@/defaultBaseUrl'
import { useScreenOrientation } from '@/nx/hooks/useScreenOrientation'
import nx from '@/nx'
import { getDataSourceTypeShow } from '../common'
import tools from '@/nx/utils/tools'

const { proxy } = getCurrentInstance()

// 响应式数据定义
const taskId = ref('')
const elId = nx.$helper.uuid()
const scrollTop = ref(0) //tab标题的滚动条位置
const menuHeight = ref(0) // 左边菜单的高度
const menuItemHeight = ref(0) // 左边菜单item的高度
const weightDataIsToZero = ref(false) //重量数据是否归零
const currentSampleIndex = ref(0) // 预设当前项的值
let sampleDataList = ref([])
const title = ref('')
const numKeyboardParam = reactive({
  decimal: '-1' //数字键盘小数位数，-1为不限制
})
const showAuncelSelector = ref(false) //显示天平选择框
const currentAuncel = ref({
  id: '',
  name: '',
  code: '',
  weightStable: 0,
  weightData: '请选天平',
  weightUnit: ''
})
let selectedField = ref({})
const groupFieldIndex = ref('') //分组的索引
const curSample = ref({})
const curParameterTitle = ref('选择字段分类')
const curParameterKey = ref('all')
const conAssayTaskId = ref('')
const busSubCSampleId = ref('')
let fieldGroup = ref([])
const collaHeights = ref([])
const cupNumKey = '杯号'
const inputValue = ref('')

function handleResetInputValue() {
  inputValue.value = ''
}
// refs
const myKeyboard = ref(null)
const auncelSelector = ref(null)

// 计算属性
const confirmWeightDisabled = computed(() => {
  if (
    currentSampleData.value.sampleCode &&
    currentAuncel.value.weightStable === 1 &&
    Number(currentAuncel.value.weightData) > 0
  ) {
    return false
  }
  return true
})

const userInfo = computed(() => nx.$store('user').userInfo)

// 方法定义
const getDomHeight = async () => {
  await nextTick() // 等待 DOM 更新完成
  collaHeights.value = []
  if (fieldGroup.value.length) {
    fieldGroup.value.forEach((item, index) => {
      proxy.$u.getRect('#elId' + index).then(res => {
        collaHeights.value.push(res.height)
      })
    })
  }
}

//返回上一页
const customBack = () => {
  uni.redirectTo({
    url: '/pages/analysis/sample/sample-work-list'
  })
}

const navRightClick = () => {
  let url = '/pages/analysis/sample/sample-work-edit-task'
  url += '?currentTaskId=' + taskId.value
  uni.navigateTo({
    url: url
  })
}

const parameterClassifyChange = v => {
  curParameterKey.value = v
  curParameterTitle.value = currentGroup.value[0].label
  groupFieldIndex.value = ''
  selectedField.value = {}
  collapseRef.value.init()
  autoNextField()
}

const fieldClick = (field, key) => {
  if (!field.isEdit) return
  if (field.fillingWay === 'input') {
    inputValue.value = field.value
  }
  selectedField.value = field
  groupFieldIndex.value = key
  if (myKeyboard.value) {
    myKeyboard.value.clearNum()
  }
  //判断小数位数
  let decimalPosition = field.decimalPosition
  if (decimalPosition == null || decimalPosition < -1) decimalPosition = -1
  numKeyboardParam.decimal = decimalPosition
  if (field.fillingWay == 'collect') {
    listenDeviceData()
  } else {
    closeDeviceListener()
  }
}

//自动切换到下一个字段
const autoNextField = () => {
  let groupIndex = 0
  let fieldIndex = 0
  if (typeof groupFieldIndex.value === 'undefined' || groupFieldIndex.value === '') groupFieldIndex.value = '0-'
  const indexV = groupFieldIndex.value.split('-')
  groupIndex = number(indexV[0])
  fieldIndex = indexV[1] === '' ? -1 : number(indexV[1])
  const group = currentGroup.value[groupIndex]
  const fields = group.fields
  if (fields.length > fieldIndex + 1) {
    //切换到下一个字段
    const key = groupIndex + '-' + (fieldIndex + 1)
    fieldClick(fields[fieldIndex + 1], key)
  }
}

//自动切换到下一个样品
const autoNextSample = () => {
  if (sampleDataList.value.length <= currentSampleIndex.value + 1) return
  const index = currentSampleIndex.value + 1
  switchSample(index, true)
}

//手动切换样品
const switchSample = async (index, autoFlag) => {
  // if (!autoFlag) {
  //   const shouldContinue = await tools.showPromiseModal(
  //     '提示',
  //     `请确认样品【${currentSampleData.value.sampleCode}】数据已经保存，是否继续？`
  //   )
  //   if (!shouldContinue) {
  //     return // 用户点了取消，直接退出
  //   }
  // }
  //重置天平归0
  weightDataIsToZero.value = false
  if (index === currentSampleIndex.value) return
  currentSampleIndex.value = index
  // 如果为0，意味着尚未初始化
  if (menuHeight.value === 0 || menuItemHeight.value === 0) {
    const rect = await getElRect('u-tab-item')
    menuItemHeight.value = rect.height
  }
  // 将菜单菜单活动item垂直居中
  scrollTop.value = index * menuItemHeight.value + menuItemHeight.value / 2 - menuHeight.value / 2 - 50
  uni.showLoading({ title: '加载中...' })
  setValueToField()
  autoGenerateCupNum()
  setTimeout(() => {
    uni.hideLoading()
  }, 500)
}

// 获取一个目标元素的高度
const getElRect = (elClass, maxRetry = 50) => {
  return new Promise((resolve, reject) => {
    let retryCount = 0
    const execQuery = () => {
      uni
        .createSelectorQuery()
        .in(proxy)
        .select('.' + elClass)
        .fields({ size: true, rect: true })
        .exec(res => {
          const result = res[0] // exec 返回数组，取第一个
          if (result) {
            resolve(result)
          } else if (retryCount < maxRetry) {
            retryCount++
            setTimeout(execQuery, 10)
          } else {
            reject(new Error(`无法获取元素 .${elClass} 的尺寸，已重试 ${maxRetry} 次`))
          }
        })
    }

    execQuery()
  })
}

//读取样品明细字段
const getDetailFieldsAndStatus = autoSelectNextField => {
  const taskDetailId = currentSampleData.value.id
  //读取回收率配置
  loadConRecoveryList()
  conAssayTaskId.value = res.additionalProperties.conAssayTaskId
  busSubCSampleId.value = res.additionalProperties.busSubCSampleId
  const detail = res.additionalProperties.taskDetail
  //处理硫值、硫量：未保存过的数据，读取接口返回的硫值、硫量
  loadSValue(detail)
  calAndCheck()
}

const checkLoadSValue = () => {
  const vKey = 'sRange'
  const vF = getFieldByKey(vKey)
  if (vF === null) return false
  const v = vF.value
  if (v === null || v === '') return true
  try {
    if (v === 0 || number(v) === 0) return true
  } catch (e) {}
  return false
}

//读取硫值、硫量
const loadSValue = detail => {
  let flag = checkLoadSValue()
  if (!flag) return
  const vKey = 'sValue'
  const rKey = 'sRange'
  const vF = getFieldByKey(vKey)
  if (vF !== null) {
    vF.value = detail.svalue
  }
  const rF = getFieldByKey(rKey)
  if (rF !== null) {
    rF.value = detail.srange
  }
}

const getFieldByKey = key => {
  const group = fieldGroup.value
  let field = null
  for (let g of group) {
    for (let f of g.fields) {
      const dicKey = f.dicKey
      if (dicKey && dicKey === key) {
        field = f
        break
      }
    }
  }
  return field
}

//按公式计算值，并检查原数据与计算后的数据是否一致
const calAndCheck = () => {
  //提取原本数值
  const oldVal = fitUpValues()
  calcAnalysisValue(fieldGroup.value)
  if (checkDataNew(oldVal)) return
  const newVal = fitUpValues(oldVal)
  //检查是否一致
  let modifyFlag = false
  for (const o in oldVal) {
    let old = oldVal[o]
    if (old === null) old = 0
    //判断是否number
    try {
      if (number(old) !== number(newVal[o])) {
        modifyFlag = true
      }
    } catch (e) {
      if (old !== newVal[o]) modifyFlag = true
    }
  }
  if (modifyFlag)
    uni.showToast({
      title: '数据有修改，请检查所有样品，并重新保存！',
      duration: 2000,
      icon: 'error'
    })
}

//检查是否是新数据
const checkDataNew = data => {
  for (const o in data) {
    if (data[o] !== null && data[o] !== '0') return false
  }
  return true
}

//组装表单值，用于数据比对
const fitUpValues = () => {
  const val = {}
  for (const g of fieldGroup.value) {
    for (const f of g.fields) {
      const detailId = f.detailId
      if (!detailId) continue
      val[detailId] = f.value
    }
  }
  return val
}

const clearFieldVal = () => {
  uni.showModal({
    title: '提示',
    content: '清空当前字段的值，是否继续？',
    cancelColor: '#0055A2',
    confirmColor: '#0055A2',
    success: res => {
      if (res.cancel) {
        return
      }
      selectedField.value.value = ''
      //重新计算
      calcAnalysisValue(fieldGroup.value)
    }
  })
}

//自动填写筛上杯号
const autoFillBhUp = val => {
  const bh = Number(val) + 1
  for (const g of fieldGroup.value) {
    for (const f of g.fields) {
      if (f.dicKey && f.dicKey === 'bh_up') {
        f.value = bh + ''
        return
      }
    }
  }
}

const checkBh = () => {
  //检查杯号
  let hasHb = true
  for (const g of fieldGroup.value) {
    for (const f of g.fields) {
      if (f.title && f.title.indexOf(cupNumKey) >= 0) {
        if (typeof f.value === 'undefined' || f.value === null || f.value === '') hasHb = false
      }
    }
  }
  if (!hasHb) {
    nx.$helper.showToast({
      title: '杯号不能为空，请填写杯号！'
    })
    return false
  }
  return true
}
const checkRange = async () => {
  for (const g of fieldGroup.value) {
    for (const f of g.fields) {
      if (f.validation) {
        if (f.validation.promptType === 'error') {
          nx.$helper.showToast({
            title: '存在范围校验错误，请修正后再保存！',
            icon: 'error',
            duration: 2000
          })
          return false
        }
        if (f.validation.promptType === 'warning') {
          const confirm = await tools.showPromiseModal('提示', '检测到范围警告，是否继续保存？')
          return confirm
        }
      }
    }
  }
  return true // 无问题，通过
}
const saveAuncelData = () => {
  //保存数据
  if (!weightDataIsToZero.value) {
    nx.$helper.showToast({
      title: '天平必须先回零！'
    })
    return
  }
  //获取当前重量
  let weight = currentAuncel.value.weightData

  selectedField.value.value = weight
  const curFieldDicKey = selectedField.dicKey
  let upDownFlag = ''
  if (curFieldDicKey && curFieldDicKey !== '' && curFieldDicKey.indexOf('_') > 0) {
    upDownFlag = curFieldDicKey.substring(curFieldDicKey.lastIndexOf('_') + 1)
  }

  //这里不修改weightDataIsToZero，在切换样品是修改
  // weightDataIsToZero.value = false;

  //保存天平编号、天平名称、称重时间。支持筛上、筛下
  if (curFieldDicKey && curFieldDicKey.indexOf('sampleWeight') >= 0) {
    let auncelNoFieldKey = 'auncelNo'
    let measureTimeFieldKey = 'measureTime'
    if (upDownFlag && upDownFlag !== '') {
      auncelNoFieldKey += '_' + upDownFlag
      measureTimeFieldKey += '_' + upDownFlag
    }
    const auncelNoField = getFieldByKey(auncelNoFieldKey)
    if (auncelNoField !== null) {
      auncelNoField.value = currentAuncel.value.code
    }
    const measureTimeField = getFieldByKey(measureTimeFieldKey)
    if (measureTimeField !== null) {
      measureTimeField.value = nx.$dayjs().format('YYYY-MM-DD HH:mm:ss')
    }
  }
  //指派单明细上的称重时间
  curSample.value.measureTime = nx.$dayjs().format('YYYY-MM-DD HH:mm:ss')
  //计算
  try {
    calcAnalysisValue(fieldGroup.value)
  } catch (e) {
    console.error(e)
  }

  //自动跳转下一个字段
  setTimeout(() => {
    autoNextField()
    weightDataIsToZero.value = false
  }, 100)
}
let dynamicFormData = reactive({})
const saveDetail = async () => {
  //检查杯号
  if (!checkBh()) return
  // 检查范围校验
  if (!(await checkRange())) return
  setValueToSample()
  let params = {
    businessAssayTaskId: taskId.value
  }

  // 如果是空白样和标样就需要根据配置信息来计算质控样、分析样
  if (activeAssayTypeKey.value === 'kby' || activeAssayTypeKey.value === 'by') {
    // 处理其他页签的输入变化
    const configInfomation = currentAssayType.value.configQCSampleMethodInfo
    const row = currentSampleData.value
    configInfomation.forEach(item => {
      const sourceKey = item.source
      const sourceValue = row[sourceKey]
      if (sourceValue !== undefined) {
        if (item.calcMethod === 'calculateAverageValue') {
          item.value = calcAverageValue(sourceKey, currentAssayType.value.tableData)
        } else {
          item.value = handleRoundFiveNumber(row[sourceKey].value, row.decimalPosition)
        }
        // 如果处理后的值不为空，重新赋值该字段到其他样品类型下的样品上，并触发每一个样品的计算
        if (item.value !== null) {
          dynamicFormData[item.target] = item.value
          updateTableDataByConfigFields()
        }
      }
    })
    params.formValue = JSON.stringify(dynamicFormData)
    params.assayTaskAnalysisDataList = assayGroups.value.map(item => ({
      datas: item.tableData,
      analysisType: item.value
    }))
  } else {
    const datas = currentSampleData.value
    params.assayTaskAnalysisDataList = [{ datas: [datas], analysisType: activeAssayTypeKey.value }]
  }

  await nx.$api.assayTask.saveBatchSmpleAndQcAnalysis(params)
  // getSampleAnalysisByTaskId()
  autoNextSample()
}
// 计算表格列平均值
function calcAverageValue(fieldIndex, tableData) {
  const rows = tableData.map(row => row[fieldIndex])
  const decimalPosition = rows[0].decimalPosition
  const values = rows.map(row => Number(row.value))
  if (values.some(item => item == null)) return null
  return handleRoundFiveNumber(math.mean(values), decimalPosition)
}

// 表格数据更新后重新计算
function updateTableDataByConfigFields() {
  let needCalcTabs = []
  needCalcTabs = assayGroups.value.filter(t => t.value !== 'by' && t.value !== 'kby')
  if (needCalcTabs.length === 0) return
  for (const key in dynamicFormData) {
    for (const tab of needCalcTabs) {
      const columnObj = tab.columns.find(c => {
        if (c.formula) {
          let FromKey = c.formula.split(':')
          return FromKey[1] === key
        }
        return false
      })
      if (!columnObj) continue
      tab.tableData.forEach(row => {
        // 赋值配置列参与计算
        row[columnObj.fieldIndex].value = dynamicFormData[key]
        calcRowAnalysisValue(row, columnObj, tab.columns)
      })
    }
  }
}

// 把字段值保存回样品数据中
function setValueToSample() {
  let fields = fieldGroup.value.flatMap(item => item.fields)
  fields.forEach(item => {
    if (
      currentSampleData.value.hasOwnProperty(item.fieldIndex) &&
      nx.$test.object(currentSampleData.value[item.fieldIndex])
    ) {
      currentSampleData.value[item.fieldIndex].value = item.value
    }
  })
}

//提交任务单
const submitTask = () => {
  const params = {
    businessAssayTaskId: taskId.value
  }
  const msg = '请确认所有样品数据都已保存，然后再提交指派单！是否继续？'
  uni.showModal({
    title: '提示',
    content: msg,
    cancelColor: '#0055A2',
    confirmColor: '#0055A2',
    success: res => {
      if (res.cancel) return

      nx.$api.assayTask.submitTask(params).then(res => {
        uni.navigateTo({
          url: '/pages/analysis/sample/sample-report-search'
        })
      })
    }
  })
}

//自动生成杯号（仅顺序称重）：第一杯：手填，后续杯 = 上一杯 + 1
const autoGenerateCupNum = () => {
  let cupNum = 0
  let currentIndex = currentSampleIndex.value
  //第一杯
  if (currentIndex === 0) return
  //取上一个样品的杯号
  const sample = sampleDataList.value[currentIndex - 1]
  cupNum = sample[cupNumFieldIndex.value].value
  //杯号赋值到当前样品
  putCupNum(Number(cupNum) + 1, currentIndex, Number(cupNum))
}

const putCupNum = (cupNum, sampleIndex, lastCupNum) => {
  for (const fields of fieldGroup.value) {
    if (typeof fields === 'undefined') continue
    //杯号
    for (const field of fields.fields) {
      if (field.fieldIndex === cupNumFieldIndex.value) {
        if (typeof field.value === 'undefined' || field.value === null || field.value === '') {
          field.value = cupNum
          return true
        }
      }
    }
  }
  //处理筛上筛下
  // if (lastCupNum && lastCupNum === sampleIndex) {
  //   //上一个杯号 == 默认杯号
  //   cupNum = sampleIndex * 2 + 1
  // }
  // for (const fields of fieldGroup.value) {
  //   if (typeof fields === 'undefined') continue
  //   //杯号-筛下
  //   for (const field of fields.fields) {
  //     if (field.dicKey === cupNumKey + '_down') {
  //       if (typeof field.value === 'undefined' || field.value === null || field.value === '') {
  //         field.value = cupNum
  //         cupNum++
  //         break
  //       }
  //     }
  //   }
  //   //杯号-筛上
  //   for (const field of fields.fields) {
  //     if (field.dicKey === cupNumKey + '_up') {
  //       if (typeof field.value === 'undefined' || field.value === null || field.value === '') {
  //         field.value = cupNum
  //         return true
  //       }
  //     }
  //   }
  // }
}

const loadConRecoveryList = () => {
  const conBaseSampleId = currentSampleData.value.conBaseSampleId
  const rParam = {
    pageNo: 1,
    pageSize: -1,
    conBaseSampleId: conBaseSampleId
  }
  const storageKey = 'ConRecoveryRateList'
  nx.$api.assayTask
    .queryConRecoveryRateList(rParam)
    .then(res => {
      const result = res.result
      if (typeof result === 'undefined' || result === null || !result) {
        uni.setStorage(storageKey, [])
        return
      }
      const records = result.records
      if (!records || records.length === 0) {
        uni.setStorage(storageKey, [])
        return
      }
      uni.setStorageSync(storageKey, records)
    })
    .catch(err => {
      console.error(err)
    })
}

// 分析样品组
let assayGroups = ref([])
const activeAssayTypeKey = ref('')
const activeAssayTypeIndex = ref(0)
//元素结果范围
let conRangeElementAnalysisList = ref([])
// 杯号fieldIndex
const cupNumFieldIndex = ref('')
const currentAssayType = computed(() => {
  return assayGroups.value.find(item => item.value === activeAssayTypeKey.value)
})
// 当前样品数据
const currentSampleData = computed(() => {
  if (sampleDataList.value.length > 0) {
    return sampleDataList.value[currentSampleIndex.value]
  }
  return {}
})
watch(
  () => currentAssayType.value,
  () => {
    sampleDataList.value = currentAssayType.value.tableData
    fieldGroup.value = groupByField(currentAssayType.value.columns, cupNumFieldIndex)

    setValueToField()
    // getDomHeight()
    activeCollapses.value = fieldGroup.value.map((_, index) => index)
  }
)
const currentCupNum = computed(() => {
  for (const item of fieldGroup.value) {
    const field = item.fields.find(field => field.fieldIndex === cupNumFieldIndex.value)
    if (field) {
      return field.value
    }
  }
  return null
})
const currentGroup = computed(() => {
  if (!currentAssayType.value || curParameterKey.value === 'all') {
    return fieldGroup.value
  } else {
    return fieldGroup.value.filter(g => g.value === curParameterKey.value)
  }
})
watch(
  () => currentGroup.value,
  () => {
    fieldGroup.value.forEach(item => {
      item.fields.forEach(field => {
        const validation = validateElementRange(
          field.fieldIndex,
          currentSampleData.value,
          conRangeElementAnalysisList.value
        )
        field.validation = validation
      })
    })
  }
)
const collapseRef = ref()
const activeCollapses = ref([])
function handleAssayTypeChange({ index, value }) {
  activeAssayTypeKey.value = value
  activeAssayTypeIndex.value = index
  currentSampleIndex.value = 0
  groupFieldIndex.value = ''
  selectedField.value = {}
  curParameterKey.value = 'all'
  curParameterTitle.value = '选择字段分类'
  collapseRef.value.init()
}
// 获取任务数据
async function getSampleAnalysisByTaskId() {
  const { assayTaskAnalysisDataList, configAssayMethodProjectRangeList, businessAssayTasNo, formValue } =
    await nx.$api.assayTask.batchSampleAndQcAnalysisByTaskId(taskId.value)
  title.value = '样品分析-任务单编号：' + businessAssayTasNo
  // 处理分析数据

  assayGroups.value = assayTaskAnalysisDataList.map(group => {
    // 必须深拷贝 datas！防止多个表格共享引用
    const tableData = JSON.parse(JSON.stringify(group.datas || []))
    const columns = group.columns.filter(item => item.paramNo) || []

    return {
      value: group.analysisType,
      name: group.analysisName,
      columns,
      tableData,
      configQCSampleMethodInfo: group.configQCSampleMethod?.configInfomation
        ? JSON.parse(group.configQCSampleMethod['configInfomation'])['set']
        : []
    }
  })
  dynamicFormData = formValue ? JSON.parse(formValue) : {}
  // 默认激活第一个 类型
  if (!activeAssayTypeKey.value) {
    activeAssayTypeKey.value = assayGroups.value.length > 0 ? assayGroups.value[0].value : ''
  }
  conRangeElementAnalysisList.value = configAssayMethodProjectRangeList || []
}
// 设置字段值
function setValueToField() {
  for (const group of fieldGroup.value) {
    group.fields.forEach(field => {
      let value = getFieldValue(field)
      field.value = value
    })
  }
}
function getFieldValue(field) {
  const fieldValue = currentSampleData.value[field.fieldIndex]?.value
  if (fieldValue) {
    return fieldValue
  } else {
    return ''
  }
}

const apiRequest = async url => {
  return request({
    url: url,
    method: 'GET'
  })
}

//读取字段里的API选项
const loadFieldApiData = async fieldGroups => {
  for (const fields of fieldGroups) {
    for (const field of fields.fields) {
      const api = field.api
      const type = field.type
      if (type === 'select' && api && api !== '') {
        //读取API选项
        try {
          const res = await apiRequest(api)
          const data = res
          field.options = data
          field.rangeKey = 'displayName'
        } catch (e) {}
      }
    }
  }
}

/*
 * 选择器组件确认事件
 * event： 事件默认参数
 * field： 当前字段
 * 处理逻辑：
 *   field.value = 选中的值
 *   field.valueText = 选中的文本
 * */
const dicPickerConfirm = (event, field) => {
  const checked = event.value[0]
  const displayName = checked.displayName
  const value = checked.dictValue
  const extField1 = checked.extField1
  field.value = value
  field.valueText = value

  const relatedFieldNo = '8'
  //查找并处理关联字段
  for (const fieldGroup of fieldGroup.value) {
    for (const field of fieldGroup.fields) {
      if (field.paramNo === relatedFieldNo) {
        field.value = extField1
        break
      }
    }
  }
  //触发计算公式
  calcAnalysisValue(fieldGroup.value)
}
// 天平监听
const listenDeviceData = () => {
  //监听websocket返回来的数据
  //设备数据
  uni.$on('deviceData', res => {
    switch (res.deviceType) {
      case 'balance':
        if (currentAuncel.value.id === res.deviceId) {
          currentAuncel.value.weightData = res.weightData
          currentAuncel.value.weightUnit = res.weightUnit
          currentAuncel.value.weightStable = res.weightStable
          currentAuncel.value.isConnected = true
          if (Number(res.weightData) === 0) {
            weightDataIsToZero.value = true
          }
        }
        break
      default:
        break
    }
  })
  //设备状态
  uni.$on('deviceStatus', res => {
    if (currentAuncel.value.id === res.deviceId) {
      if (res.connected === 0) {
        currentAuncel.value.weightStable = 0
        currentAuncel.value.weightData = '天平断开'
        currentAuncel.value.weightUnit = ''
      }
    }
    currentAuncel.value.isConnected = res.connected
  })
  //控制设备状态
  uni.$on('controlDevice', res => {
    if (currentAuncel.value.id === res.deviceId) {
      currentAuncel.value.id = ''
      currentAuncel.value.name = ''
      currentAuncel.value.code = ''
      currentAuncel.value.weightStable = 0
      currentAuncel.value.weightData = '请选天平'
      currentAuncel.value.weightUnit = ''
    }
  })
  //连接断开
  uni.$on('connClose', res => {
    //重置
    currentAuncel.value.weightData = ''
    currentAuncel.value.weightUnit = ''
    currentAuncel.value.weightStable = 0
    currentAuncel.value.controlUserName = ''
    currentAuncel.value.isConnected = false
  })
}
const closeDeviceListener = () => {
  uni.$off('deviceData')
  uni.$off('deviceStatus')
  uni.$off('controlDevice')
  uni.$off('connClose')
}
const loadDevice = () => {
  //注册websocket
  let regData = {
    msgId: nx.$helper.uuid(),
    cmd: 'register',
    clientType: 'caaClient',
    data: {
      userId: userInfo.value.id,
      tenantId: getTenantId(),
      userRealName: userInfo.value.realname
    }
  }
  nx.$measure.setRegData(JSON.stringify(regData))
  nx.$measure.open()
}

// 键盘监听
const listenNumKeyboard = () => {
  //键盘监听
  uni.$on('keyboardOK', res => {
    if (res === null) {
      clearFieldVal()
      return
    }
    //自动补全小数位数
    const decimalPosition = selectedField.value.decimalPosition || 0
    let val = res.val
    selectedField.value.value = handleRoundFiveNumber(val, decimalPosition)
    const dicKey = selectedField.value.dicKey
    if (dicKey && dicKey === 'bh_down') {
      autoFillBhUp(val)
    }
    calcAnalysisValue(fieldGroup.value)
    //自动跳转下一个字段
    setTimeout(() => {
      autoNextField()
    }, 60)
  })
}
const closeNumKeyBoardListener = () => {
  uni.$off('keyboardOK')
}

const closeDeviceLink = () => {
  const deviceId = currentAuncel.value.id
  releaseDeviceControl(deviceId)
}

//释放设备控制
const releaseDeviceControl = deviceId => {
  if (!deviceId || deviceId === '') return
  let controlDevice = {
    msgId: deviceId,
    cmd: 'controlDevice',
    clientType: 'caaClient',
    data: {
      deviceId: deviceId,
      isControl: false,
      controlRealName: userInfo.value.nickname
    }
  }
  //发送控制数据
  nx.$measure.send(JSON.stringify(controlDevice))
}

// 天平选择
const selectAuncel = () => {
  showAuncelSelector.value = true
}
// 天平选择回调
const auncelDoSelect = res => {
  const data = res.data
  if (data) {
    currentAuncel.value.id = data.deviceId
    currentAuncel.value.name = data.deviceName
    currentAuncel.value.code = data.deviceCode
  }
}

// 生命周期
const { lockOrientation } = useScreenOrientation()

onLoad(param => {
  lockOrientation('landscape')
  if (param.currentTaskId) {
    taskId.value = param.currentTaskId
    getSampleAnalysisByTaskId()
  }
  loadFieldApiData(fieldGroup.value)
  listenNumKeyboard()
})

onShow(() => {
  loadDevice()
  listenDeviceData()
})

onHide(() => {
  closeDeviceListener()
})

onUnload(() => {
  closeDeviceLink()
  closeDeviceListener()
  closeNumKeyBoardListener()
})

onBackPress(() => {
  customBack()
  return true
})
</script>

<style lang="scss" scoped>
/* 原始样式保留不变 */
.navbar-right {
  font-size: 16px;
  color: #fff;
  display: flex;
}

.content-title-name {
  font-size: 18px;
  font-weight: 300;
  padding: 4px 0;
  display: flex;
  justify-content: center;
}

.current-sample-code {
  font-weight: bold;
  margin-right: 20px;
}

.form-item-my {
  display: flex;
  align-items: center;
  min-height: 35px;
  font-size: 13px;
  border-bottom: 1px solid #dcdcdc;
}
.selected-field {
  background-color: #bada55;
}
.disabled-field {
  background-color: #eee;
}
.label-my {
  flex: 5;
}

.label-high-light {
  color: #000;
  font-weight: 600;
  font-size: 1.2em;
}

.field-high-light {
  color: #000;
  font-weight: 600;
  font-size: 1.2em;
}

.label-my sub {
  font-size: 0.6em;
  vertical-align: sub;
}

.content-my {
  flex: 2;
  text-align: right;
  padding-right: 4px;
  .select-my {
    color: #303133;
    font-size: 15px;
    padding: 6px 8px;
    border: 1px solid #dcdcdc;
    border-radius: 5px;
  }
}

.content-my-text-value {
  color: rgb(48, 49, 51);
}
.content-my-text-placeholder {
  color: #c0c4cc;
}
.content-left-scroll {
  height: 68vh;
}
.content-right-scroll {
  height: 68vh;
}
.valid-warning {
  color: orange;
}
.valid-error {
  color: red;
}

.u-tab-item {
  display: flex;
  align-items: center;
  font-size: 16px;
  color: #444;
  padding: 4px 8px;
  box-sizing: border-box;
  border-bottom: 2px dotted #444;
}

.u-tab-item-active {
  color: #0055a2;
  font-weight: 600;
}

.btn-operation {
  width: 80%;
  font-size: 18px;
  margin-top: 10px;
}

.auncel {
  width: 90%;
  height: 55vh;
  background-image: url(/static/images/auncel.png);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-position: center;
  display: flex;
  flex-direction: column;
  position: relative;
  .code {
    position: absolute;
    top: 10px;
    left: 50px;
  }
}

.auncel-title {
  flex: 3;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  font-size: 32px;
}

.auncel-weight {
  flex: 2.5;
  display: flex;
  align-items: center;
  padding-bottom: 20px;
  box-sizing: border-box;
  position: relative;
}

.weight {
  font-size: 42px;
  width: 100%;
  padding: 0 60px;
}

.weight-data {
  color: #4cd964;
  font-family: zzjc-lcd;
}

.weight-data-yellow {
  color: #ffff00;
  font-family: zzjc-lcd;
}

.weight-data-warning {
  color: #ff3333;
  font-family: zzjc-lcd;
}

.weight-unit {
  position: absolute;
  right: 30px;
  color: #ffffff;
  font-size: 32px;
}
@media (max-width: 700px) {
  .auncel {
    height: 45vh;
  }
  .auncel-title {
    font-size: 20px;
  }
  .auncel-weight {
    padding-bottom: 15px;
  }
  .weight {
    font-size: 26px;
  }
  .weight-unit {
    font-size: 20px;
  }
}

.field-name {
  font-size: 26px;
  padding: 8px;
}

.my-collapse {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 5px 10px 5px 0;
  .title {
    font-weight: bold;
  }
}
.content {
  overflow: hidden;
  padding-right: 10px;
  transition: height 100ms;
}

@media (max-width: 700px) {
  .content-left-scroll {
    height: 45vh;
  }
  .content-right-scroll {
    height: 55vh;
  }
  .field-name {
    font-size: 16px;
  }
}
</style>
