<template>
  <div
    v-if="permission !== 'n'"
    v-express
    :class="[
      'inputs',
      formInputsDisplay == 'block'
        ? 'ht-form-inputs__block'
        : 'ht-form-inputs__inline',
      company && inputWriteable ? 'has-company-box' : '',
      type == 'textarea' && permission != 'r' && isShowInput
        ? 'ht-textarea'
        : '',
      isMobile ? 'mobile-input-box' : '',
      numberType.includes(showCompanys) ? 'isFormat' : '',
    ]"
  >
    <input
      v-if="disabled && isValidate && !isSubCellReadOnly"
      v-model="inputVal"
      v-validate="inputValidate"
      type="hidden"
      :name="inputName"
      :data-vv-as="name"
    />
    <template>
      <template v-if="inputWriteable && isSubCellReadOnly">
        <input
          v-model="inputVal"
          v-validate="inputValidate"
          type="hidden"
          :name="inputName"
          :data-vv-as="name"
        />
        <div class="sub-table-cell-readonly" @click="handleCellClick">
          <span
            :style="{
              maxHeight: !textareaAutoHeight && textareaHeight + 'px',
              overflow: !textareaAutoHeight && 'auto',
            }"
          >
            {{ inputVal }}
          </span>
        </div>
      </template>
      <template v-else>
        <el-input
          v-if="isShowInput && !isMobile"
          ref="inputEle"
          v-model="inputVal"
          v-validate="inputValidate"
          :type="type"
          :size="inputSize"
          :style="inputWidth"
          :name="inputName"
          :data-vv-as="name"
          :placeholder="placeholder"
          :clearable="clearable"
          :show-password="showPassword"
          :autocomplete="autocomplete"
          :disabled="
            isDisabled ||
            (permission && permission === 'd') ||
            (permission_sub && permission_sub === 'd')
          "
          :readonly="readonly"
          :rows="rowsVal"
          :cols="colsVal"
          :min="min"
          :max="max"
          :autosize="autosize"
          :autofocus="autofocus"
          :resize="resize"
          :tabindex="tabindex"
          :prefix-icon="prefixIcon"
          :suffix-icon="suffixIcon"
          :minlength="minlength"
          :maxlength="maxlength"
          :show-word-limit="showWordLimit"
          @blur="handleBlur"
          @focus="handleFocus"
          @change="handleChange"
          @input="handleInput"
          @clear="handleClear"
        >
          <slot slot="prefix" name="prefix"></slot>
          <slot slot="suffix" name="suffix"></slot>
          <slot slot="prepend" name="prepend"></slot>
          <slot slot="append" name="append"></slot>
        </el-input>
        <template v-if="isMobile">
          <div
            v-if="isShowInput && type !== 'textarea' && !inputWriteable"
            class="mobile-no-permission"
          >
            {{ inputVal }}
          </div>
          <van-field
            v-else-if="isShowInput && type !== 'number'"
            v-model="inputVal"
            v-validate="inputValidate"
            class="mobile-input-field"
            :class="{
              'mobile-textarea-field': type === 'textarea',
              'mobile-scan-input': scanConfig,
            }"
            rows="2"
            :autosize="{ maxHeight: 100 }"
            :type="mobileType ? 'password' : type"
            :maxlength="maxlength"
            :placeholder="mobilePlaceholder(placeholder)"
            :disabled="
              isDisabled ||
              (permission && permission === 'd') ||
              (permission_sub && permission_sub === 'd')
            "
            :readonly="readonly"
            :show-word-limit="showWordLimit"
            :clearable="false"
            :left-icon="prefixIcon"
            :right-icon="suffixIcon"
            :name="inputName"
            :data-vv-as="name"
            @blur="handleBlur"
            @input="handleInput"
            @click-right-icon="handlePassword"
          >
            <template #right-icon>
              <i
                v-if="showPassword"
                class="mobile-input-field-right-icon"
                :class="mobileType ? 'icon-yincang' : 'icon-xianshi'"
              ></i>
            </template>
          </van-field>
          <BarScan
            v-if="scanConfig && inputWriteable"
            v-model="inputVal"
            :scan-config="scanConfig"
            :pos-right-in-title="type === 'textarea'"
          />
        </template>
        <template v-if="inputWriteable && type == 'number'">
          <div class="mobile-number-location">
            <div :class="isMobile ? 'mobile-number-wrap' : 'pcInputNumberWrap'">
              <inputNumber
                v-if="!isMobile"
                ref="inputEle"
                v-model="inputVal"
                v-validate="inputNumValidate"
                :type="type"
                :controls-position="controlsPosition"
                :controls="controls"
                :size="inputSize"
                :style="inputWidth"
                :name="inputName"
                :data-vv-as="name"
                :placeholder="placeholder"
                :clearable="clearable"
                :disabled="
                  disabled ||
                  (permission && permission === 'd') ||
                  (permission_sub && permission_sub === 'd')
                "
                :readonly="readonly"
                :min="min"
                :max="max"
                :show-companys="showCompanys"
                :step="step"
                :unit="unit"
                :step-strictly="stepStrictly"
                :precision="precision"
                :company="company"
                :thousands-number="thousandsNumber"
                :class="[
                  numberType.includes(showCompanys) &&
                  permission_sub == 'w' &&
                  !isShowText
                    ? 'haveNumMargin'
                    : '',
                ]"
                @blur="handleNumberBlur"
                @focus="handleFocus"
                @input="handleInput"
                @change="handleChange"
              >
                <template slot="exhibitText">
                  <div
                    v-if="
                      !hasErrorsVal &&
                      showCompanys === 'filtercurrency' &&
                      permission_sub == 'w'
                    "
                    v-show="!isNumber"
                    class="exhibitText isMobileExhibitText pc-exhibit-text"
                  >
                    {{ exhibitText }}
                  </div>
                </template>
              </inputNumber>
              <inputNumber
                v-else-if="isMobile && filterthousandBit"
                ref="inputEle"
                v-model="inputVal"
                v-validate="inputNumValidate"
                class="mobile-thousand-num"
                :type="type"
                :controls-position="controlsPosition"
                :controls="controls"
                :size="inputSize"
                :style="inputWidth"
                :name="inputName"
                :data-vv-as="name"
                :placeholder="placeholder"
                :clearable="clearable"
                :disabled="
                  disabled ||
                  (permission && permission === 'd') ||
                  (permission_sub && permission_sub === 'd')
                "
                :readonly="readonly"
                :min="min"
                :max="max"
                :show-companys="showCompanys"
                :step="step"
                :unit="unit"
                :step-strictly="stepStrictly"
                :precision="precision"
                :company="company"
                :thousands-number="thousandsNumber"
                :class="[
                  numberType.includes(showCompanys) &&
                  permission_sub == 'w' &&
                  !isShowText
                    ? 'haveNumMargin'
                    : '',
                ]"
                @blur="handleNumberBlur"
                @focus="handleFocus"
                @input="handleInput"
                @change="handleChange"
              ></inputNumber>
              <Stepper
                v-else
                ref="inputEle"
                v-model="inputVal"
                v-validate="inputNumValidate"
                :type="type"
                class="mobile-number-input"
                style="text-align: right"
                :step="step"
                :controls="controls"
                :disabled="
                  disabled ||
                  (permission && permission === 'd') ||
                  (permission_sub && permission_sub === 'd')
                "
                :placeholder="mobilePlaceholder(placeholder)"
                :max="maxValue"
                :min="minValue"
                :name="inputName"
                :data-vv-as="name"
                :is-mobile-search-num="isMobileSearchNum"
                :unit="unit"
                :class="[
                  controls ? 'show-button' : 'hidden-button',
                  disabledBtn ? 'disabledBtn' : '',
                ]"
                @blur="handleNumberBlur"
                @focus="handleFocus"
                @change="handleChange"
                @plus="handlePlus"
                @minus="handleMinus"
                @input="handleInput"
              />
            </div>
            <span v-if="company && isMobile && !filterthousandBit" class="unit">
              {{ company }}
            </span>
          </div>
          <div
            v-if="
              !hasErrorsVal &&
              exhibitText &&
              isMobile &&
              showCompanys === 'filtercurrency' &&
              permission_sub == 'w'
            "
            v-show="!isNumber"
            class="exhibitText isMobileExhibitText"
          >
            <div class="text">
              {{ exhibitText }}
            </div>
          </div>
        </template>
      </template>
    </template>

    <ht-field-tail
      v-if="isShowText"
      :field-name="inputName"
      :readonly="!inputWriteable"
      :input-value="readOnlyInputVal"
      :company="company"
      :decimal-length="precision"
      :precision="precision"
      :type="type"
      :filter-currency="filtercurrency"
      :filterthousand-bit="filterthousandBit"
      :show-companys="showCompanys"
      :hyperlink="hyperlink"
      :exhibit-text-number="exhibitTextNumber"
      @hasErrors="hasErrors"
    >
      <slot slot="prefix" name="prefix"></slot>
      <slot slot="suffix" name="suffix"></slot>
      <slot slot="prepend" name="prepend"></slot>
      <slot slot="append" name="append"></slot>
    </ht-field-tail>
  </div>
</template>
<script>
  import utils from '@/utils.js'
  import FormMath from '@/math.js'
  import HtFieldTail from '../../FieldTail/index'
  import permission from '@/mixins/permission.js'
  import inputName from '@/mixins/inputName.js'
  import form from '@/mixins/form.js'
  import mobileMode from '@/mixins/mobileMode.js'
  import tableFieldReadOnly from '@/mixins/tableFieldReadOnly.js'
  import inputNumber from './inputNumber.vue'
  import BarScan from './BarScan.vue'
  import _ from 'lodash'
  import Stepper from './vanStepper.js'
  export default {
    name: 'HtInput',
    components: {
      HtFieldTail,
      inputNumber,
      Stepper,
      BarScan,
    },
    mixins: [permission, inputName, form, mobileMode, tableFieldReadOnly],
    props: {
      value: [String, Number],
      controlsPosition: {
        type: String,
        default: '',
      },
      width: [String, Number],
      clearable: {
        type: Boolean,
        default: true,
      },
      showPassword: {
        type: Boolean,
        default: false,
      },
      autocomplete: {
        type: String,
        default: 'on',
      },
      mathExp: String,
      type: {
        type: String,
        default: 'text',
      },
      ctrlType: {
        type: String,
        default: '',
      },
      dateCalcExp: Object,
      readonly: {
        type: Boolean,
        default: false,
      },
      disabled: {
        type: Boolean,
        default: false,
      },
      min: Number,
      max: Number,
      step: {
        type: Number,
        default: 1,
      },
      stepStrictly: {
        type: Boolean,
        default: false,
      },
      precision: {
        type: Number,
      },
      cols: {
        type: Number,
        default: 60,
      },
      rows: {
        type: Number,
        default: 2,
      },
      autosize: {
        type: [Boolean, Object],
        default: false,
      },
      prefixIcon: String,
      suffixIcon: String,
      tabindex: String,
      minlength: {
        type: Number,
      },
      maxlength: {
        type: Number,
      },
      showWordLimit: {
        type: Boolean,
        default: false,
      },
      format: {
        type: Function,
      },
      formatWhenReadonly: {
        type: Boolean,
        default: true,
      },
      filterthousandBit: {
        type: Boolean,
        default: false,
      },
      filtercurrency: {
        type: Boolean,
        default: false,
      },
      configAttributes: Object,
      company: String,
      resize: {
        type: String,
      },

      showCompanys: {
        type: String,
        default: '',
      },

      controls: {
        type: [Boolean, String],
        default: true,
      },
      hyperlink: Object,
      isMobileSearchNum: {
        type: Boolean,
        default: false,
      },
      isValidate: {
        type: Boolean,
        default: false,
      },
      autofocus: {
        type: Boolean,
        default: false,
      },
      scanConfig: {
        type: String,
      },
      textareaHeight: {
        type: Number,
        default: 96,
      },
      textareaAutoHeight: {
        type: Boolean,
        default: false,
      },
    },
    data() {
      return {
        unwatchAry: [],
        morphing: false,
        hasErrorsVal: false,
        tempInputVal: null,
        isFocus: false,
        exhibitText: '',
        isNumber: true,
        numberPreBlur: false,
        cursorIndex: 0,
        unit: '',
        numberType: ['filtercurrency', 'filterthousandBit'],
        mobileType: this.showPassword,
      }
    },
    computed: {
      inputVal: {
        get() {
          // input为number时 输入框获取焦点时 自动清空输入框默认内容 简化用户操作

          if (this.isFocus && this.type === 'number' && this.value === 0) {
            return undefined
          }

          if (this.morphing && this.tempInputVal !== null) {
            return this.tempInputVal
          }
          if (utils.isEmpty(this.value)) {
            this.handleResized()
            return ''
          }
          this.handleResized()
          return this.value
        },
        set(val) {
          if (
            this.isFocus &&
            this.type === 'number' &&
            (val === undefined || Number(val) === 0)
          ) {
            this.morphing = false
            this.enterMorph(0)
            this.$emit('input', 0)
            return
          }

          // 格式化显示时不更新到value属性上
          // !this.morphing &&
          this.$emit('input', val)
          this.handleResized()
        },
      },
      colsVal: function () {
        return this.type == 'textarea' ? this.cols : null
      },
      rowsVal: function () {
        return this.type == 'textarea' ? this.rows : null
      },
      inputWidth: function () {
        let styleObj = {}
        this.width
          ? typeof this.width == 'string'
            ? (styleObj = { width: this.width })
            : (styleObj = { width: `${this.width}px` })
          : (styleObj = {})

        if (this.type && this.type === 'textarea' && !this.isMobile) {
          let tHeight = Number(this.textareaHeight) + 10 + 'px'
          this.textareaHeight && (styleObj['--textareaHeight'] = tHeight)
          styleObj['--textareaMinHeight'] = this.textareaAutoHeight
            ? this.textareaHeight
              ? tHeight
              : '74px'
            : '30px'
        }

        return styleObj
      },

      isShowText() {
        return !this.inputWriteable
          ? this.type === 'number'
            ? this.permission_sub !== 'n'
            : this.permission_sub !== 'n' && this.currentShowMode !== 'input'
          : true
      },
      isShowInput() {
        return (
          (this.inputWriteable || this.currentShowMode === 'input') &&
          this.type !== 'number'
        )
      },
      readOnlyInputVal() {
        return this.filterthousandBit ||
          this.filtercurrency ||
          this.showCompanys
          ? this.exhibitText
          : this.inputVal
      },
      disabledBtn() {
        return (
          Number(this.inputVal) >= this.maxValue ||
          Number(this.inputVal) <= this.minValue
        )
      },
      maxValue() {
        const max = Number(this.max)
        const { max_value: validateMaxValue } =
          this.getValidateMaxAndMinNumber()
        return validateMaxValue > max ? max : validateMaxValue
      },
      minValue() {
        const min = Number(this.min)
        const { min_value: validateMinValue } =
          this.getValidateMaxAndMinNumber()
        return validateMinValue > min ? validateMinValue : min
      },
      exhibitTextNumber() {
        if(this.filterthousandBit ||
          this.filtercurrency ||
          this.showCompanys){
          if (typeof this.inputVal === 'number' && this.precision !== undefined) {
            this.inputVal = this.inputVal.toFixed(this.precision)
          }
          return this.inputVal
        } else {
          return null
        }
      },
      thousandsNumber() {
        return this.filterthousandBit ? this.exhibitText : ''
      },
    },
    watch: {
      value: function (val) {
        if (this.morphing && this.tempInputVal !== null) {
          this.enterMorph()
        }
        this.formatterNumber(val)
        this.name && this.$validator.validate(this.inputName)
      },
      inputWriteable: function (newVal, oldVal) {
        if (newVal != oldVal) {
          if (!newVal) {
            // 只读时是否保持格式化显示
            this.formatWhenReadonly ? this.enterMorph() : this.exitMorph()
          } else {
            this.enterMorph()
          }
        }
      },
      inputVal: function (newVal, oldVal) {
        if (!newVal || newVal == '') {
          const _me = this
          const formVm = utils.getOnlineFormInstance(_me)
          this.initIdentity(_me, formVm)
        }
      },
    },
    created() {
      window.addEventListener('resize', () => this.handleResized())
    },
    mounted() {
      if (this.isMobile && this.type === 'textarea') {
        this.addMobileTopLabelClass()
      }
      const _me = this
      const exp = this.mathExp
      const formVm = utils.getOnlineFormInstance(_me)
      // 初始化流水号配置
      this.initIdentity(_me, formVm)
      // 数学运算表达式
      if (exp) {
        let elAttr = this.$vnode.data.model.expression
        if (this.modelExpression) {
          elAttr = this.modelExpression
        }
        const fields = FormMath.parseFuncexpField(exp)
        formVm.$on(elAttr, function (args) {
          if (args.hasOwnProperty('index')) {
            const { subScopeEl, index } = utils.getSubScopeElAndIndex(_me.$el)
            if (subScopeEl != null && index === null) {
              throw '要计算子表行数据的输入框不在包含data-subname属性的元素中.'
            }
            if (index == args.index) {
              _me.$emit('input', args.result)
            }
          } else {
            _me.$emit('input', args.result)
          }
        })

        fields.forEach((ele) => {
          if (formVm.watchMap.has(ele)) {
            let ary = formVm.watchMap.get(ele)
            ary.push({ target: elAttr, exp })
            formVm.watchMap.set(ele, ary.unique('target'))
          } else {
            formVm.watchMap.set(ele, [{ target: elAttr, exp }])
          }
        })
      }
      // 日期计算表达式
      if (this.dateCalcExp) {
        // 计算日期间隔
        let handleDateCalc = function (startVal, endVal) {
          _me.$emit(
            'input',
            utils.dateCalc(startVal, endVal, _me.dateCalcExp.diffType)
          )
        }
        // 获取是否在子表中每一行进行日期计算
        const { subScopeEl, index } = utils.getSubScopeElAndIndex(_me.$el)
        if (subScopeEl) {
          const startScope = utils.getSubInputScopeByModelExpression(
            subScopeEl,
            this.dateCalcExp.start
          )
          const endScope = utils.getSubInputScopeByModelExpression(
            subScopeEl,
            this.dateCalcExp.end
          )
          // 对于子表中某行的日期计算，需要找到日期控件对应的vm实例
          startScope.$watch(
            'inputVal',
            function (newVal, oldVal) {
              if (newVal !== oldVal) {
                handleDateCalc(startScope.value, endScope.value)
              }
            },
            { immediate: false }
          )
          endScope.$watch(
            'inputVal',
            function (newVal, oldVal) {
              if (newVal !== oldVal) {
                handleDateCalc(startScope.value, endScope.value)
              }
            },
            { immediate: false }
          )
        } else {
          let cb = function (newVal, oldVal) {
            if (newVal !== oldVal) {
              let startVal = utils.getValueByPath(
                formVm,
                _me.dateCalcExp.start,
                index
              )
              let endVal = utils.getValueByPath(
                formVm,
                _me.dateCalcExp.end,
                index
              )
              handleDateCalc(startVal, endVal)
            }
          }
          // 主表中的日期计算，在表单上通过v-model的表达式来监控值变更
          formVm.$watch(this.dateCalcExp.start, cb, { immediate: true })
          formVm.$watch(this.dateCalcExp.end, cb, { immediate: true })
        }
      }
      setTimeout(() => {
        this.enterMorph()
      }, 0)
      // 数字类型且配置了千分位或人民币大写
      // if (
      //   this.type == 'number' &&
      //   (this.filtercurrency || this.filterthousandBit || this.showCompanys)
      // ) {
      //   window.addEventListener('click', this.clickOther)
      // }
    },
    beforeDestroy() {
      window.removeEventListener('resize', () => this.handleResized())
      // if (
      //   this.type == 'number' &&
      //   (this.filtercurrency || this.filterthousandBit || this.showCompanys)
      // ) {
      //   window.removeEventListener('click', this.clickOther)
      // }
      let that = this
      let watcher =
        that._watchers && that._watchers.find((m) => m.expression == 'inputVal')
      if (watcher && watcher.cb) {
        // 单行文本销毁时，触发一次change事件，更新计算公式
        watcher.cb('0', that.inputVal, true)
      }
    },
    destroyed() {
      this.unwatchAry &&
        this.unwatchAry.forEach((unwatch) => {
          unwatch.call()
        })
    },
    methods: {
      handleResized() {
        setTimeout(() => {
          this.$nextTick(() => {
            if (
              !this.isMobile &&
              this.type === 'textarea' &&
              this.$refs.inputEle &&
              this.textareaAutoHeight
            ) {
              let dom = this.$refs.inputEle.$el.childNodes[0]
              if (dom && dom.scrollHeight > Number(this.textareaHeight)) {
                dom.style.height = 'inherit'
                dom.style.height = dom.scrollHeight + 10 + 'px'
              }
            }
          })
        }, 2000)
      },
      hasErrors(val) {
        this.hasErrorsVal = val
      },
      formatterNumber(val) {
        let inputVal = val || Number(val) === 0 ? val : this.value
        const ctrlTypeList = ['currency', 'number']
        if (this.filtercurrency) {
          if (ctrlTypeList.includes(this.ctrlType)) {
            this.exhibitText = FormMath.convertCurrency(inputVal)
          }
        }
        // 最后千分位
        else if (this.filterthousandBit) {
          if (ctrlTypeList.includes(this.ctrlType)) {
            this.$nextTick(() => {
              this.exhibitText = utils.thousandBit(inputVal)
            })
          }
        } // 货币
        else if (
          this.showCompanys &&
          !this.numberType.includes(this.showCompanys)
        ) {
          this.morphing = true
          this.unit = this.showCompanys
          if (ctrlTypeList.includes(this.ctrlType)) {
            if (utils.isEmpty(inputVal)) {
              this.$emit('input', 0)
            }
            this.$nextTick(() => {
              this.exhibitText = `${this.showCompanys}${inputVal}`
              this.isNumber = false
            })
          } else {
            this.tempInputVal = `${this.showCompanys}${inputVal}`
          }
        }
      },
      handleNumberBlur(event) {
        if (
          this.type == 'number' &&
          (this.filtercurrency || this.filterthousandBit || this.showCompanys)
        ) {
          this.numberPreBlur = true
          return
        }
        this.handleBlur(event)
      },
      clickOther(event) {
        setTimeout(() => {
          if (!this.numberPreBlur) {
            return
          }
          // 当外部点击事件触发时判断当前是否在点击el-input-number控件，是则不继续触发blur事件，否则才触发blur事件
          const path =
            event.path || (event.composedPath && event.composedPath())
          const result = path.some((p) => {
            return p.className && p.className.indexOf('el-input-number') > -1
          })
          if (!result) {
            this.handleBlur(event)
            this.numberPreBlur = false
          }
        }, 10)
      },
      exhibitFocus() {
        this.isNumber = true
        this.$nextTick(() => {
          if (this.isMobile && this.type == 'number') {
            this.$refs.inputEle.$refs.input.focus()
          } else {
            this.$refs.inputEle.focus()
          }
        })
      },
      handleBlur(event) {
        this.isFocus = false
        // 获取光标位置
        this.cursorIndex = event.srcElement.selectionStart
        this.enterMorph()
        this.$emit('blur', event)
      },
      handleFocus(event) {
        this.isFocus = true
        this.exitMorph()
        this.$emit('focus', event)
      },
      handleChange(val) {
        //显示
        if (!this.isNumber) {
          this.morphing = false
          this.enterMorph(val)
        }

        this.$emit('change', val)
      },
      handlePassword() {
        this.mobileType = !this.mobileType
      },
      handleInput(val) {
        this.$emit('input', val)
      },
      handleClear() {
        this.$emit('clear')
      },
      handleMinus() {
        this.$emit('Minus')
      },
      handlePlus() {
        this.$emit('Plus')
      },
      // 进入格式显示模式
      enterMorph(val) {
        let inputVal = val || Number(val) === 0 ? val : this.value
        // 只在text类型时格式化
        // 货币和数字时也格式化
        const ctrlTypeList = ['currency', 'number']

        if (
          this.morphing ||
          (this.type != 'text' && this.ctrlType !== 'number')
        ) {
          return
        }
        // 优先处理设定了format方法的情况
        if (this.format) {
          const result = this.format(inputVal)
          if (result && result.constructor == Promise) {
            result.then((resp) => {
              this.morphing = true
              this.tempInputVal = resp
            })
          } else if (result != null && result != undefined) {
            this.morphing = true
            this.tempInputVal = result
          }
        }
        // 其次人民币大写
        else if (this.filtercurrency) {
          this.morphing = true
          if (ctrlTypeList.includes(this.ctrlType)) {
            if (utils.isEmpty(inputVal)) {
              this.$emit('input', 0)
            }
            this.$nextTick(() => {
              this.exhibitText = utils.isEmpty(inputVal)
                ? FormMath.convertCurrency(0)
                : FormMath.convertCurrency(inputVal)
              this.isNumber = false
            })
          } else {
            this.tempInputVal = FormMath.convertCurrency(inputVal)
          }
        }
        // 最后千分位
        else if (this.filterthousandBit) {
          this.morphing = true
          if (ctrlTypeList.includes(this.ctrlType)) {
            if (utils.isEmpty(inputVal)) {
              this.$emit('input', 0)
            }
            this.$nextTick(() => {
              // 确保保留指定的小数位数
              let formattedVal = inputVal
              if (this.precision !== undefined) {
                formattedVal = Number(inputVal).toFixed(this.precision)
              }
              this.exhibitText = utils.thousandBit(formattedVal)
              this.isNumber = false
            })
          } else {
            // 确保保留指定的小数位数
            let formattedVal = inputVal
            if (this.precision !== undefined) {
              formattedVal = Number(inputVal).toFixed(this.precision)
            }
            this.tempInputVal = utils.thousandBit(formattedVal)
          }
        }
        // 货币
        else if (
          this.showCompanys &&
          !this.numberType.includes(this.showCompanys)
        ) {
          this.morphing = true
          this.unit = this.showCompanys
          if (ctrlTypeList.includes(this.ctrlType)) {
            if (utils.isEmpty(inputVal)) {
              this.$emit('input', 0)
            }
            this.$nextTick(() => {
              this.exhibitText = `${this.showCompanys}${inputVal}`
              this.isNumber = false
            })
          } else {
            this.tempInputVal = `${this.showCompanys}${inputVal}`
          }
        }
      },
      // 退出格式化显示模式
      exitMorph() {
        this.morphing = false
        // this.tempInputVal = null
      },
      // 如果当前输入框绑定了流水号，则将modelName记录到form的watchMap中，用于在复制数据时将流水号置空以便产生新的流水号。
      recordBindIdentityInWatchMap(pInst) {
        if (!pInst || !pInst.watchMap || !this.modelName) {
          return
        }
        let bindIdentityModelNameList = pInst.watchMap.get(
          'bindIdentityModelNameList'
        )
        if (
          bindIdentityModelNameList == null ||
          bindIdentityModelNameList == undefined
        ) {
          bindIdentityModelNameList = []
        }
        bindIdentityModelNameList.push(this.modelName)
        bindIdentityModelNameList = bindIdentityModelNameList.unique()
        pInst.watchMap.set(
          'bindIdentityModelNameList',
          bindIdentityModelNameList
        )
      },
      isDOMFixed(_me) {
        if (_me.$el.closest('table') && _me.$el.closest('table').parentNode) {
          return _me.$el
            .closest('table')
            .parentNode.classList.contains('el-table__fixed-body-wrapper')
        }
        return false
      },
      initIdentity(_me, pInst) {
        //检查流水号
        if (this.configAttributes && !this.isDOMFixed(_me)) {
          this.isEdit = !this.configAttributes.isInputEdit
          //判断是否绑定流水号
          if (this.configAttributes.bindIdentityAlias) {
            this.recordBindIdentityInWatchMap(pInst)
            this.isEdit = false
            if (this.value) return
            var alias = this.configAttributes.bindIdentityAlias
            this.$requestConfig.getNextIdByAlias(alias).then((res) => {
              if (res.state) {
                this.$emit('input', res.value)
                if (res.value) {
                  let matchOne
                  const matches = []
                  const regex = /\{([^\}]+)\}/g
                  while ((matchOne = regex.exec(res.value)) !== null) {
                    matches.push(matchOne)
                  }
                  let strValue = res.value
                  matches.forEach((match) => {
                    //判断流水号中是否表达式如{kjbt.csfjsc}
                    if (match) {
                      strValue = strValue.replace(match[0], '')
                      this.$emit('input', strValue)
                      // data 数据所在的 VueComponent
                      const runtimePInst =
                        utils.getRuntimeTemplateOnlineForm(this)
                      if (runtimePInst && match[1]) {
                        runtimePInst.$watch(
                          `data.${match[1]}`,
                          (newVal, oldVal) => {
                            if (newVal != oldVal) {
                              if (this.modelName === `data.${match[1]}`) {
                                this.$message.error(
                                  '流水号生成规则字段不能绑定流水号显示字段'
                                )
                              } else {
                                if (matches && matches.length == 1) {
                                  this.$emit(
                                    'input',
                                    res.value.replace(match[0], newVal)
                                  )
                                } else {
                                  let value = res.value
                                  matches.forEach((item) => {
                                    if (item && item[1]) {
                                      const valueChanged = utils.getValueByPath(
                                        runtimePInst,
                                        `data.${item[1]}`
                                      )
                                      value = value.replace(
                                        item[0],
                                        valueChanged
                                      )
                                    }
                                  })
                                  this.$emit('input', value)
                                }
                              }
                            }
                          },
                          { immediate: true }
                        )
                      }
                    }
                  })
                }
              } else {
                this.$message.error(res.message)
              }
            })
          }
          _me.$watch('inputVal', function () {
            pInst.$watch(
              'identityMap',
              function (newVal, oldVal) {
                if (newVal && newVal !== oldVal) {
                  for (const key in newVal) {
                    if (_me.modelName == key) {
                      let item = newVal[key]
                      utils.setValueByPath(
                        pInst,
                        item.key,
                        item.value.replace(item.expression, _me.value)
                      )
                    }
                  }
                }
              },
              { immediate: true }
            )
          })
        }
      },
      getValidateMaxAndMinNumber() {
        const inputNumValidateArray = this.inputNumValidate
          .toString()
          .split('|')
        let validateMap = new Map()
        inputNumValidateArray.forEach((i) => {
          const itemArray = i.split(':')
          !validateMap.has(itemArray[0]) &&
            validateMap.set(itemArray[0], Number(itemArray[1]))
        })
        let max_value = validateMap.get('max_value')
        let min_value = validateMap.get('min_value')
        return {
          max_value,
          min_value,
        }
      },
    },
  }
</script>
<style lang="scss" scoped>
  .ht-textarea div[aria-invalid='true'].el-textarea,
  div[aria-invalid='true'] ::v-deep .el-input__inner,
  div[aria-invalid='true'] ::v-deep .el-input__inner:focus,
  div[aria-invalid='true'] + .exhibit ::v-deep .el-input__inner,
  div[aria-invalid='true'] + .exhibit ::v-deep .el-input__inner:focus {
    border-color: #f56c6c;
  }

  ::v-deep div[aria-invalid='true'].van-field {
    border: none;
  }
  div[aria-invalid='true'] ::v-deep .el-textarea__inner,
  div[aria-invalid='true'] ::v-deep .el-textarea__inner:focus {
    border-color: #f56c6c;
  }
  div[aria-invalid='true'] + .exhibitText {
    display: none !important;
  }

  .inputs {
    ::v-deep {
      .el-input-number {
        width: 100%;
      }
    }
  }
  .has-company-box {
    ::v-deep.field-tail__wrap {
      .el-form-item__error {
        min-width: 200px;
      }
      position: absolute;
    }
  }
  .mobile-input-box {
    justify-content: flex-end;
    .mobile-no-permission {
      padding: 8px 0 8px 12px;
      color: #c8c9cc;
    }
  }
  .exhibit {
    width: calc(100% - 30px);
  }
  .ht-textarea {
    box-sizing: border-box;
    border-radius: 4px;
    &:focus {
      border-color: #409eff;
    }
    &.mobile-input-box {
      border: none;
      border-radius: 0;
    }
    ::v-deep .el-textarea {
      border: 1px solid #dcdfe6;
      width: calc(100% - 2px);
    }
  }
  ::v-deep .el-textarea__inner {
    border: none;
    height: var(--textareaHeight);
    min-height: var(--textareaMinHeight) !important;
  }
  ::v-deep .mobile-number-input {
    .van-stepper__plus {
      border-radius: 50%;
      background: #409eff;
      color: #fff;
      width: 22px;
      height: 22px;
      &::before {
        height: 2px;
      }
      &::after {
        width: 2px;
      }
    }
    .van-stepper__minus {
      border-radius: 50%;
      background: #409eff;
      color: #fff;
      width: 22px;
      height: 22px;
      &::before {
        height: 2px;
      }
    }
    .van-stepper__input {
      width: 60px;
      background: none;
    }
  }

  ::v-deep .disabledBtn {
    .van-stepper__plus,
    .van-stepper__minus {
      background: #e6e6e6 !important;
    }
  }
  ::v-deep {
    .mobile-input-field {
      padding: 0;
      &::after {
        border: none;
      }
      .van-field__control {
        text-align: right;
      }
      &.mobile-textarea-field {
        .van-field__control {
          text-align: left;
        }
      }
      &.mobile-scan-input {
        display: inline-block;
        width: calc(100% - 50px);
      }

      .mobile-input-field-right-icon {
      }
    }

    .rightAlign {
      .el-input__inner {
        text-align: right;
      }
    }
    .centerAlign {
      .el-input__inner {
        text-align: center;
      }
    }
    .leftAlign {
      .el-input__inner {
        text-align: left;
      }
    }
  }
  .hidden-button {
    display: flex;
    align-items: center;
    ::v-deep {
      .van-stepper__plus,
      .van-stepper__minus {
        display: none !important;
      }
      .van-stepper__input {
        width: calc(100% - 5px);
        text-align: right;
      }
    }
  }

  .exhibitText {
    display: block;
    height: auto;
    line-height: 12px;
    font-size: 12px;
    text-align: right;
    // position: absolute;
    top: calc(100% - 0px);
    right: 0;
    white-space: nowrap;
    margin-top: 4px;
  }
  .isMobileExhibitText {
    top: 85%;
    .text {
      display: inline-block;
      text-align: right;
    }
  }
  .pc-exhibit-text {
    text-align: center;
  }
  .pcInputNumberWrap {
    position: relative;
    width: 100%;
    .pcExhibitText {
      left: 50%;
      right: auto;
      transform: translate(-50%, 0);
    }
    ::v-deep.is-controls-right {
      height: 32px;
    }
    .pc-exhibit-text {
      width: calc(100% - 32px);
    }
  }
  .mobile-number-location {
    display: flex;
    justify-content: flex-end;
    width: 100%;
  }
  .mobile-number-wrap {
    ::v-deep {
      .mobile-thousand-num {
        .el-input__inner {
          border: none;
          padding: 0;
          text-align: right;
        }
      }
    }
  }

  .unit {
    margin-left: 8px;
    white-space: nowrap;
    display: flex;
    justify-content: center;
    align-items: center;
  }
</style>
