<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">
        <view class="content-title-name">
          <text>待化验样品</text>
        </view>
        <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">{{ currentSample.sampleCode }}</view>
          <view>数据采集或录入</view>
        </view>
        <u-gap height="5" bg-color="#0055A2"></u-gap>
      </u-col>
      <u-col span="3">
        <view class="content-title-name">
          <text>样品详情</text>
        </view>
        <u-gap height="5" bg-color="#0055A2"></u-gap>
      </u-col>
    </u-row>
    <u-row gutter="8" align="top">
      <u-col span="3">
        <u-dropdown>
          <u-dropdown-item
            v-model="curParameterClassify"
            :title="curParameterTitle"
            height="340px"
            :options="optionParameterClassify"
            @change="parameterClassifyChange"
          ></u-dropdown-item>
        </u-dropdown>
        <scroll-view class="content-left-scroll" scroll-with-animation scroll-y :scroll-top="scrollTop">
          <view
            v-for="(sample, index) in leftList"
            :key="index"
            class="u-tab-item"
            :class="[current.value === index ? 'u-tab-item-active' : '']"
            :data-current="index"
            @tap.stop="switchSample(index, false)"
          >
            <view class="pr5"> 【{{ sample.sort }}】 </view>
            <view>
              <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.value.name" />
        <zzjc-num-keyboard
          ref="myKeyboard"
          v-show="selectedField.value.fillingWay === '1' && selectedField.value.type !== 'select'"
          :numKeyboardParam="numKeyboardParam"
        ></zzjc-num-keyboard>
        <view v-if="selectedField.value.fillingWay === '2'" class="y-f">
          <view class="auncel" @click="selectAuncel">
            <view class="auncel-title"> {{ currentAuncel.code }}</view>
            <view class="auncel-weight">
              <view class="weight">
                <view
                  :style="{ textAlign: currentAuncel.isConnected != 1 ? '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"
            v-if="currentAuncel.code !== ''"
            type="success"
            :disabled="confirmWeightDisabled"
            shape="circle"
            @click="saveAuncelData"
          >
            确认采集
          </u-button>
        </view>
      </u-col>
      <u-col span="3">
        <view>
          <scroll-view class="content-right-scroll" scroll-y scroll-with-animation>
            <view>
              <u-form :model="curSample" ref="uForm" label-width="140">
                <template v-for="(fields, groupIndex) in fieldGroup" :key="'group_' + groupIndex">
                  <view v-if="curParameterKey.value === '' || curParameterKey.value === fields.title">
                    <!-- 组名 -->
                    <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' }"
                    >
                      <view
                        class="form-item-my"
                        v-for="(field, fieldIndex) in fields.fields"
                        @click="fieldClick(field, groupIndex + '-' + fieldIndex)"
                        :key="groupIndex + '-' + fieldIndex"
                        v-show="field.hidden !== 1 && field.hidden !== '1'"
                        :class="{ 'selected-field': selectedFieldIndex.value === groupIndex + '-' + fieldIndex }"
                      >
                        <view
                          :class="[
                            'label-my',
                            { 'label-high-light': field.highlight === 1 || field.highlight === '1' }
                          ]"
                          v-html="
                            field.name +
                            (typeof field.unit !== 'undefined' && field.unit !== null && field.unit !== ''
                              ? '(' + field.unit + ')'
                              : '')
                          "
                        ></view>
                        <view class="content-my">
                          <!--
							    如果是select，渲染2个组件：1个input、1个picker.
							    field.valueText用于显示picker选中的文本
							    -->
                          <u-input
                            style="width: 120px"
                            v-if="field.fillingWay === 4"
                            v-model="field.value"
                            :placeholder="field.placeholder"
                            type="text"
                          />

                          <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.type !== 'select' && field.fillingWay !== 4">
                            <text v-if="!field.value || field.value === ''" class="content-my-text-placeholder">{{
                              field.placeholder
                            }}</text>
                            <text
                              v-else
                              :class="[
                                'content-my-text-value',
                                { 'field-high-light': field.highlight === 1 || field.highlight === '1' }
                              ]"
                              >{{ field.value }}</text
                            >
                          </view>
                        </view>
                      </view>
                    </view>
                  </view>
                </template>
              </u-form>
            </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, onMounted } from 'vue'
import { onLoad, onBackPress, onShow, onHide, onUnload } from '@dcloudio/uni-app'
import request from '@/nx/request'
import { calcAnalysisValue } 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 text from '@/uview-plus/components/u-text/text'

// 响应式数据定义
const elId = nx.$helper.uuid()
const scrollTop = ref(0) //tab标题的滚动条位置
const current = ref(0) // 预设当前项的值
const menuHeight = ref(0) // 左边菜单的高度
const menuItemHeight = ref(0) // 左边菜单item的高度
const orderGenBH = ref(true) //顺序生成杯号
const weightDataIsToZero = ref(false) //重量数据是否归零
const currentSample = ref({}) //当前样品
const currentTaskNo = ref('') //当前任务指派单号
const currentTaskId = ref('') //当前任务指派单id
const currentTaskType = ref('') //当前任务类型
const title = ref('')
const numKeyboardParam = reactive({
  decimal: '-1' //数字键盘小数位数，-1为不限制
})
const showAuncelSelector = ref(false) //显示天平选择框
const currentAuncel = reactive({
  id: '',
  name: '',
  code: '',
  weightStable: 0,
  weightData: '请选天平',
  weightUnit: ''
})
const selectedField = ref({})
const selectedFieldIndex = ref('')
const leftList = ref([])
const curSample = ref({})
const showDicPicker = ref(false)
const curParameterTitle = ref('选择字段分类')
const curParameterKey = ref('')
const curParameterClassify = ref('')
const conAssayTaskId = ref('')
const busSubCSampleId = ref('')
const optionParameterClassify = ref([])
const paramFieldApiRet = ref([])
const fieldGroup = ref([])
const collaHeights = ref([])

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

const checkCupNumReadonly = computed(() => {
  if (!currentAuncel.value || currentAuncel.value.id === '') return true
  return false
})

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

// 方法定义
const getDomHeight = () => {
  collaHeights.value = []
  nextTick(() => {
    if (fieldGroup.value.length) {
      fieldGroup.value.forEach((item, index) => {
        nx.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 += '?currentTaskNo=' + currentTaskNo.value
  uni.navigateTo({
    url: url
  })
}

const parameterClassifyChange = (v, a) => {
  const groupIndex = ref(0)
  curParameterKey.value = v
  optionParameterClassify.value.forEach((item, index) => {
    if (item.value === v) {
      groupIndex.value = index
      curParameterTitle.value = item.label
    }
  })
  if (v === '') groupIndex.value = 0
  if (groupIndex.value > 0) groupIndex.value--
  //自动选中字段
  selectedFieldIndex.value = groupIndex.value + '-'
  autoNextField()
}

const fieldClick = (field, key) => {
  try {
    myKeyboard.value.clearNum()
  } catch (e) {
    console.error(e)
  }
  if (field.fillingWay === 4) return
  selectedField.value = field
  selectedFieldIndex.value = key
  //判断小数位数
  let dataType = field.dataType
  if (dataType == null || dataType < -1) dataType = -1
  numKeyboardParam.decimal = dataType
  if (field.fillingWay === 2) {
    listenDeviceData()
  } else {
    closeDeviceListener()
  }
}

//自动切换到下一个字段
const autoNextField = () => {
  //selectedFieldIndex是groupIndex-fieldIndex
  let groupIndex = 0
  let fieldIndex = 0
  if (typeof selectedFieldIndex.value === 'undefined' || selectedFieldIndex.value === '')
    selectedFieldIndex.value = '0-'
  const indexV = selectedFieldIndex.value.split('-')
  groupIndex = number(indexV[0])
  fieldIndex = indexV[1] === '' ? -1 : number(indexV[1])
  const group = fieldGroup.value[groupIndex]
  const fields = group.fields
  if (fields.length > fieldIndex + 1) {
    //如果下一个字段是计算，不自动切换
    const fillingWay = fields[fieldIndex + 1].fillingWay || ''
    if (fillingWay === '3') return
    //切换到下一个字段
    const key = groupIndex + '-' + (fieldIndex + 1)
    fieldClick(fields[fieldIndex + 1], key)
  }
}

//自动切换到下一个样品
const autoNextSample = () => {
  //仅在顺序称重时自动切换
  // if (!orderWeighChecked.value)
  //   return;
  if (leftList.value.length <= current.value + 1) return
  const index = current.value + 1
  switchSample(index, true)
}

//手动切换样品
const switchSample = async (index, autoFlag) => {
  //重置天平归0
  weightDataIsToZero.value = false
  //清空数字键盘数据
  myKeyboard.value.clearNum()
  if (index === current.value) return
  // if (orderWeighChecked.value && !autoFlag) return;//顺序称重不允许选中
  current.value = index
  // 如果为0，意味着尚未初始化
  if (menuHeight.value === 0 || menuItemHeight.value === 0) {
    // await getElRect('menu-scroll-view', 'menuHeight');
    await getElRect('u-tab-item', 'menuItemHeight')
  }
  // 将菜单菜单活动item垂直居中
  scrollTop.value = index * menuItemHeight.value + menuItemHeight.value / 2 - menuHeight.value / 2 - 50
  //修改当前选中的selectedFieldIndex
  if (typeof selectedFieldIndex.value !== 'undefined' && selectedFieldIndex.value.indexOf('-') > 0) {
    selectedFieldIndex.value = selectedFieldIndex.value.split('-')[0] + '-'
  }
  currentSample.value = leftList.value[index]
  //读取样品明细字段
  getDetailFieldsAndStatus(true)
}

// 获取一个目标元素的高度
const getElRect = (elClass, dataVal) => {
  return new Promise((resolve, reject) => {
    const query = uni.createSelectorQuery().in(this)
    query
      .select('.' + elClass)
      .fields({ size: true }, res => {
        // 如果节点尚未生成，res值为null，循环调用执行
        if (!res) {
          setTimeout(() => {
            getElRect(elClass)
          }, 10)
          return
        }
        this[dataVal] = res.height
      })
      .exec()
  })
}

//读取样品明细字段
const getDetailFieldsAndStatus = autoSelectNextField => {
  const taskDetailId = currentSample.value.id
  //读取回收率配置
  loadConRecoveryList()
  //查询字段
  nx.$api.assayTask.queryFieldsByTaskDetail({ taskDetailId: taskDetailId }).then(res => {
    fieldGroup.value = []
    if (!res.success) {
      nx.$helper.showToast({
        title: res.message
      })
      return
    }
    //处理“填写&计算”字段：如果后台存了值，则不自动计算
    const groupList = res.result
    for (const g of groupList) {
      g.open = true
      for (const f of g.fields) {
        if (f.fillingWay === '1' && f.value != null && f.value !== '') {
          f.valueTypeManual = '1'
        }
      }
    }
    fieldGroup.value = groupList
    const arr = [
      {
        label: '全部',
        value: ''
      }
    ]
    for (const g of fieldGroup.value) {
      const title = g.title
      const o = {
        label: title,
        value: title
      }
      arr.push(o)
    }
    // 计算样品详情高度
    getDomHeight()
    optionParameterClassify.value = arr //字段分类
    conAssayTaskId.value = res.additionalProperties.conAssayTaskId
    busSubCSampleId.value = res.additionalProperties.busSubCSampleId
    const detail = res.additionalProperties.taskDetail
    //处理硫值、硫量：未保存过的数据，读取接口返回的硫值、硫量
    loadSValue(detail)
    //自动生成杯号
    autoGenerateCupNum()
    //自动选择下一个字段
    if (autoSelectNextField) autoNextField()
    //按公式计算值，并检查原数据与计算后的数据是否一致
    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 = ''
      selectedField.value.valueTypeManual = '0'
      //重新计算
      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.dicKey && f.dicKey.indexOf('bh_') >= 0) {
        if (typeof f.value === 'undefined' || f.value === null || f.value === '') hasHb = false
      }
    }
  }
  if (!hasHb) {
    nx.$helper.showToast({
      title: '杯号不能为空，请填写杯号！'
    })
    return false
  }
  return true
}

const saveAuncelData = () => {
  //检查杯号
  if (!checkBh()) return
  //保存数据
  if (!weightDataIsToZero.value) {
    nx.$helper.showToast({
      title: '天平必须先回零！'
    })
    return
  }
  //获取当前重量
  let weight = currentAuncel.weightData

  selectedField.value.value = weight
  const curFieldDicKey = selectedField.value.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.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()
  }, 100)
}

const checkSubmit = () => {
  //检查必填字段
  let fieldNames = ''
  for (const g of fieldGroup.value) {
    for (const f of g.fields) {
      let name = f.shortName
      if (name === null || name === '') name = f.name
      if (f.allowNull === 1 || f.allowNull === '1') continue
      if (f.value === null || f.value === '') {
        fieldNames += name + '，'
      }
    }
  }
  if (fieldNames !== '') {
    nx.$helper.showToast({
      title: '请填写必填字段：' + fieldNames
    })
    return false
  }
  //检查不能为0的字段
  fieldNames = ''
  for (const g of fieldGroup.value) {
    for (const f of g.fields) {
      let name = f.shortName
      if (name === null || name === '') name = f.name
      //检查不可为0的数据
      if (f.notZero === 1 || f.notZero === '1') {
        if (f.value === null || f.value === '' || number(f.value) === 0) {
          fieldNames += name + '，'
        }
      }
    }
  }
  if (fieldNames !== '') {
    nx.$helper.showToast({
      title: '这几个值不能为0，请检查：' + fieldNames
    })
    return false
  }

  return true
}

const saveDetail = () => {
  //检查杯号
  if (!checkBh()) return
  const valueList = []
  let cupNum = 0
  let detailId = currentSample.value.id
  for (const g of fieldGroup.value) {
    for (const f of g.fields) {
      if (f.dicKey === 'bh' || f.dicKey === 'bh_up') cupNum = f.value
      valueList.push({
        id: f.detailId,
        type: f.pOrE,
        value: f.value,
        name: f.name,
        dataType: f.dataType
      })
    }
  }
  const data = {
    busSubCSampleId: busSubCSampleId.value,
    conAssayTaskId: conAssayTaskId.value,
    measureTime: curSample.value.measureTime,
    elementParamValueList: valueList,
    busAssayTaskDetailId: detailId
  }
  if (typeof cupNum !== 'undefined' && cupNum !== null && cupNum !== '' && cupNum !== 0 && cupNum !== '0') {
    //提交杯号，保存到后台
    data.cupNum = cupNum
    //标记当前杯号
    markCurCupNum(cupNum)
  }
  nx.$api.assayTask.saveDetailValue(data).then(res => {
    //如果仅保存，在这里触发切换
    setTimeout(() => {
      autoNextSample()
    }, 1000)
  })
}

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

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

//自动生成杯号（仅顺序称重）：第一杯：手填，后续杯 = 上一杯 + 1
const autoGenerateCupNum = () => {
  if (!orderGenBH.value) return
  let cupNum = 0

  let current = current.value
  if (typeof current === 'undefined' || current === null) current = 0
  //第一杯
  if (current === 0) {
    cupNum = 1
    putCupNum(cupNum)
    return
  }
  //取上一个样品的杯号
  const sample = leftList.value[current - 1]
  cupNum = sample.cupNum
  if (typeof cupNum === 'undefined' || cupNum === null || cupNum === '') return
  //杯号赋值到当前样品
  putCupNum(Number(cupNum) + 1, current, Number(cupNum))
}

const markCurCupNum = cupNum => {
  currentSample.value.cupNum = cupNum
}

const putCupNum = (cupNum, sampleIndex, lastCupNum) => {
  if (typeof sampleIndex === 'undefined' || sampleIndex === null) sampleIndex = 0
  const cupNumKey = 'bh'
  for (const fields of fieldGroup.value) {
    if (typeof fields === 'undefined') continue
    //杯号
    for (const field of fields.fields) {
      if (field.dicKey === cupNumKey) {
        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
        }
      }
    }
  }
  return false
}

const loadConRecoveryList = () => {
  const conBaseSampleId = currentSample.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)
    })
}

const getAssayTaskDetail = taskNo => {
  leftList.value = []
  nx.$api.assayTask
    .getAssayTaskDetailListByTaskNo({ taskNo: taskNo })
    .then(res => {
      let dataList = res.result
      dataList.forEach((item, index) => {
        leftList.value.push(item)
      })
      if (leftList.value.length === 0) {
        return
      }
      current.value = 0
      currentSample.value = leftList.value[0]
      getDetailFieldsAndStatus(true)
    })
    .catch(err => {
      console.error(err)
    })
}

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.id === res.deviceId) {
          currentAuncel.weightData = res.weightData
          currentAuncel.weightUnit = res.weightUnit
          currentAuncel.weightStable = res.weightStable
          currentAuncel.isConnected = 1
          if (Number(res.weightData) === 0) {
            weightDataIsToZero.value = true
          }
        }
        break
      default:
        break
    }
  })
  //设备状态
  uni.$on('deviceStatus', res => {
    if (currentAuncel.id === res.deviceId) {
      if (res.connected === 0) {
        currentAuncel.weightStable = 0
        currentAuncel.weightData = '天平断开'
        currentAuncel.weightUnit = ''
      }
    }
    currentAuncel.isConnected = res.connected
  })
  //控制设备状态
  uni.$on('controlDevice', res => {
    if (currentAuncel.id === res.deviceId) {
      currentAuncel.id = ''
      currentAuncel.name = ''
      currentAuncel.code = ''
      currentAuncel.weightStable = 0
      currentAuncel.weightData = '请选天平'
      currentAuncel.weightUnit = ''
    }
  })
  //连接断开
  uni.$on('connClose', res => {
    //重置
    currentAuncel.weightData = ''
    currentAuncel.weightUnit = ''
    currentAuncel.weightStable = 0
    currentAuncel.controlUserName = ''
    currentAuncel.isConnected = 0
  })
}
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 dataType = selectedField.value.dataType || 0
    let val = res.val
    //判断val小数位，如果小于设定位数，则补全
    if (dataType > 0) {
      if (val === '') val = '0'
      if (typeof val === 'number') val += ''
      let dotLen = 0
      if (val.indexOf('.') > 0) dotLen = val.length - val.indexOf('.') - 1
      else val += '.'
      while (dotLen < dataType) {
        dotLen++
        val += '0'
      }
    }
    selectedField.value.value = val
    selectedField.value.valueTypeManual = '1' //标记为手动值，不参与计算
    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.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 getDataSourceTypeShow = val => {
  if (val === 2) return '【筛上】'
  if (val === 3) return '【筛下】'
  return ''
}
// 天平选择
const selectAuncel = () => {
  showAuncelSelector.value = true
}
// 天平选择回调
const auncelDoSelect = res => {
  const data = res.data
  if (data) {
    currentAuncel.id = data.deviceId
    currentAuncel.name = data.deviceName
    currentAuncel.code = data.deviceCode
  }
}
// refs
const myKeyboard = ref(null)
const auncelSelector = ref(null)

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

onLoad(param => {
  lockOrientation('landscape')
  if (param.currentTaskNo) {
    currentTaskNo.value = param.currentTaskNo
    currentTaskType.value = param.currentTaskType
  }
  title.value = '样品分析-任务指派单：' + param.currentTaskNo
  getAssayTaskDetail(currentTaskNo.value)
  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;
  margin-bottom: 10px;
  height: 35px;
  font-size: 13px;
}
.selected-field {
  background-color: #bada55;
}
.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;
  .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: 60vh;
}
.content-right-scroll {
  height: 68vh;
}

.u-tab-item {
  display: flex;
  align-items: center;
  justify-content: space-around;
  font-size: 16px;
  color: #444;
  font-weight: 400;
  padding: 4px 0;
  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;
}

.auncel-title {
  flex: 3;
  display: flex;
  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>
