<template>
  <span :class="{'print-read-label': printRead}">
    <template v-if="widget.type == 'blank'">
      <div :style="{width: isTable ? '100%' : widget.options.width}">
        <slot :name="widget.model" :model="dataModels"></slot>
      </div>
    </template>

    <template v-if="widget.type == 'component'">
      <div :style="{width: isTable ? '100%' : widget.options.width}">
        <component :is="`component-${widget.key}-${key}`" :key="key" v-model="dataModel"
                   :ref="'fm-'+widget.model"></component>
      </div>
    </template>

    <template v-if="widget.type == 'custom'">
      <div :style="{width: isTable ? '100%' : widget.options.width}">
        <component
          :is="widget.el"
          v-model="dataModel"
          :width="widget.options.width"
          :height="widget.options.height"
          :placeholder="widget.options.placeholder"
          :readonly="widget.options.readonly"
          :disabled="elementDisabled"
          :editable="widget.options.editable"
          :clearable="widget.options.clearable"
          :ref="'fm-'+widget.model"
          :print-read="printRead"
          v-bind="{...widget.options.customProps, ...extendProps}"
          v-on="dynamicEvents"
        ></component>
      </div>
    </template>

    <template v-if="widget.type == 'input'">
      <template v-if="printRead">
        <span>{{ dataModel }}</span>
      </template>
      <template v-else>
        <el-input
          v-if="widget.options.dataTypeCheck && (widget.options.dataType == 'number' || widget.options.dataType == 'integer' || widget.options.dataType == 'float')"
          type="number"
          v-model.number="dataModel"
          :disabled="elementDisabled"
          :placeholder="widget.options.placeholder"
          :show-password="widget.options.showPassword"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :ref="'fm-'+widget.model"
          :clearable="widget.options.clearable"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          v-bind="{...widget.options.customProps, ...extendProps}"
        ></el-input>
        <el-input
          v-else
          :type="widget.options.dataTypeCheck ? widget.options.dataType : 'text'"
          v-model="dataModel"
          :disabled="elementDisabled"
          :placeholder="widget.options.placeholder"
          :show-password="widget.options.showPassword"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :ref="'fm-'+widget.model"
          :clearable="widget.options.clearable"
          :maxlength="widget.options.maxlength"
          :show-word-limit="widget.options.showWordLimit"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          v-bind="{...widget.options.customProps, ...extendProps}"
        ></el-input>
      </template>

    </template>

    <template v-if="widget.type == 'textarea'">
      <template v-if="printRead">
        <pre>{{ dataModel }}</pre>
      </template>
      <template v-else>
        <el-input type="textarea" :rows="widget.options.rows"
                  v-model="dataModel"
                  :disabled="elementDisabled"
                  :placeholder="widget.options.placeholder"
                  :style="{width: isTable ? '100%' : widget.options.width}"
                  :ref="'fm-'+widget.model"
                  :clearable="widget.options.clearable"
                  :maxlength="widget.options.maxlength"
                  :show-word-limit="widget.options.showWordLimit"
                  :autosize="widget.options.autosize"
                  @focus="handleOnFocus"
                  @blur="handleOnBlur"
                  v-bind="{...widget.options.customProps, ...extendProps}"
        ></el-input>
      </template>
    </template>

    <template v-if="widget.type == 'number'">
      <template v-if="printRead">
        <span>{{ typeof dataModel == 'number' ? dataModel.toFixed(widget.options.precision) : dataModel }}</span>
      </template>
      <template v-else>
        <el-input-number
          v-model="dataModel"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :step="widget.options.step"
          :disabled="elementDisabled"
          :min="widget.options.min"
          :max="widget.options.max"
          :controls-position="widget.options.controlsPosition"
          :precision="widget.options.precision"
          :controls="widget.options.controls"
          :ref="'fm-'+widget.model"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          v-bind="{...widget.options.customProps, ...extendProps}"
        ></el-input-number>
      </template>
    </template>

    <template v-if="widget.type == 'radio'">
      <template v-if="printRead">
        <template v-if="widget.options.remote">
          {{
            remoteOptions.find(item => item.value == dataModel)
            && remoteOptions.find(item => item.value == dataModel).label
          }}
        </template>
        <template v-else>
          {{
            widget.options.showLabel ?
              (remoteOptions.find(item => item.value == dataModel) && remoteOptions.find(item => item.value == dataModel).label) :
              dataModel
          }}
        </template>
      </template>
      <template v-else>
        <el-radio-group v-model="dataModel"
                        :style="{width: isTable ? '100%' : widget.options.width}"
                        :disabled="elementDisabled"
                        :ref="'fm-'+widget.model"
                        v-bind="{...widget.options.customProps, ...extendProps}"
        >
          <el-radio
            :style="{display: widget.options.inline ? 'inline-block' : 'block'}"
            :label="item.value" v-for="(item, index) in remoteOptions" :key="index"
          >
            <template v-if="widget.options.remote">{{ item.label }}</template>
            <template v-else>{{ widget.options.showLabel ? item.label : item.value }}</template>
          </el-radio>
        </el-radio-group>
      </template>
    </template>

    <template v-if="widget.type == 'checkbox'">
      <template v-if="printRead">
        <template v-if="widget.options.remote">
          {{
            dataModel.map(dm =>
              remoteOptions.find(item => item.value == dm)
              && remoteOptions.find(item => item.value == dm).label
            ).join('、')

          }}
        </template>
        <template v-else>
          {{
            widget.options.showLabel ?
              dataModel.map(dm => remoteOptions.find(item => item.value == dm) && remoteOptions.find(item => item.value == dm).label).join('、') :
              dataModel.join('、')
          }}
        </template>
      </template>
      <template v-else>
        <el-checkbox-group v-model="dataModel"
                           :style="{width: isTable ? '100%' : widget.options.width}"
                           :disabled="elementDisabled"
                           :ref="'fm-'+widget.model"
                           v-bind="{...widget.options.customProps, ...extendProps}"
        >
          <el-checkbox

            :style="{display: widget.options.inline ? 'inline-block' : 'block'}"
            :label="item.value" v-for="(item, index) in remoteOptions" :key="index"
          >
            <template v-if="widget.options.remote">{{ item.label }}</template>
            <template v-else>{{ widget.options.showLabel ? item.label : item.value }}</template>
          </el-checkbox>
        </el-checkbox-group>
      </template>
    </template>

    <template v-if="widget.type == 'time'">
      <template v-if="printRead">
        {{ dataModel }}
      </template>
      <template v-else>
        <el-time-picker
          v-model="dataModel"
          :is-range="widget.options.isRange"
          :placeholder="widget.options.placeholder"
          :start-placeholder="widget.options.startPlaceholder"
          :end-placeholder="widget.options.endPlaceholder"
          :readonly="widget.options.readonly"
          :disabled="elementDisabled"
          :editable="widget.options.editable"
          :clearable="widget.options.clearable"
          :arrowControl="widget.options.arrowControl"
          :value-format="widget.options.format"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :ref="'fm-'+widget.model"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          v-bind="{...widget.options.customProps, ...extendProps}"
        >
        </el-time-picker>
      </template>
    </template>

    <template v-if="widget.type=='date'">
      <template v-if="printRead">
        {{
          widget.options.type == 'dates' ?
            dataModel?.join('、') :
            typeof dataModel == 'object' ? dataModel.join(' ~ ') : dataModel
        }}
      </template>
      <template v-else>
        <el-date-picker
          v-model="dataModel"
          :type="widget.options.type"
          :placeholder="widget.options.placeholder"
          :start-placeholder="widget.options.startPlaceholder"
          :end-placeholder="widget.options.endPlaceholder"
          :readonly="widget.options.readonly"
          :disabled="elementDisabled"
          :editable="widget.options.editable"
          :clearable="widget.options.clearable"
          :value-format="widget.options.timestamp ? 'timestamp' : widget.options.format"
          :format="widget.options.format"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :ref="'fm-'+widget.model"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          v-bind="{...widget.options.customProps, ...extendProps}"
        >
        </el-date-picker>
      </template>
    </template>
<!--    <template v-if="widget.type=='takeLeaveDate'">-->
<!--      <template v-if="printRead">-->
<!--        {{-->
<!--          widget.options.type == 'dates' ?-->
<!--            dataModel?.join('、') :-->
<!--            typeof dataModel == 'object' ? dataModel.join(' ~ ') : dataModel-->
<!--        }}-->
<!--      </template>-->
<!--      <template v-else>-->
<!--        <el-date-picker-->
<!--          v-model="dataModel"-->
<!--          :type="widget.options.type"-->
<!--          :placeholder="widget.options.placeholder"-->
<!--          :start-placeholder="widget.options.startPlaceholder"-->
<!--          :end-placeholder="widget.options.endPlaceholder"-->
<!--          :readonly="widget.options.readonly"-->
<!--          :disabled="elementDisabled"-->
<!--          :editable="widget.options.editable"-->
<!--          :clearable="widget.options.clearable"-->
<!--          :value-format="widget.options.timestamp ? 'timestamp' : widget.options.format"-->
<!--          :format="widget.options.format"-->
<!--          :style="{width: isTable ? '100%' : widget.options.width}"-->
<!--          :ref="'fm-'+widget.model"-->
<!--          @focus="handleOnFocus"-->
<!--          @blur="handleOnBlur"-->
<!--          v-bind="{...widget.options.customProps, ...extendProps}"-->
<!--        >-->
<!--        </el-date-picker>-->
<!--      </template>-->
<!--    </template>-->

    <template v-if="widget.type =='rate'">
      <template v-if="printRead">
        {{ dataModel }}
      </template>
      <template v-else>
        <el-rate v-model="dataModel"
                 :max="widget.options.max"
                 :disabled="elementDisabled"
                 :allow-half="widget.options.allowHalf"
                 :show-score="widget.options.showScore"
                 :ref="'fm-'+widget.model"
                 :style="{width: isTable ? '100%' : widget.options.width, display: 'inline-block'}"
                 v-bind="{...widget.options.customProps, ...extendProps}"
        ></el-rate>
      </template>
    </template>

    <template v-if="widget.type == 'color'">
      <template v-if="printRead">
        {{ dataModel }}
      </template>
      <template v-else>
        <el-color-picker
          v-model="dataModel"
          :disabled="elementDisabled"
          :show-alpha="widget.options.showAlpha"
          :ref="'fm-'+widget.model"
          :style="{width: isTable ? '100%' : widget.options.width}"
          v-bind="{...widget.options.customProps, ...extendProps}"
        ></el-color-picker>
      </template>
    </template>

    <template v-if="widget.type == 'select'">
      <template v-if="printRead">
        <template v-if="widget.options.remote">
          {{
            typeof dataModel == 'object' ?
              (dataModel.map(dm => remoteOptions.find(item => item.value == dm)
                && remoteOptions.find(item => item.value == dm).label).join('、'))
              : (remoteOptions.find(item => item.value == dataModel)
                && remoteOptions.find(item => item.value == dataModel).label)
          }}
        </template>
        <template v-else>
          {{
            widget.options.showLabel ?
              (
                typeof dataModel == 'object' ?
                  dataModel.map(dm => remoteOptions.find(item => item.value == dm) && remoteOptions.find(item => item.value == dm).label).join('、')
                  : (remoteOptions.find(item => item.value == dataModel) && remoteOptions.find(item => item.value == dataModel).label)
              ) :
              typeof dataModel == 'object' ? dataModel.join('、') : dataModel
          }}
        </template>
      </template>
      <template v-else>
        <el-select
          v-model="dataModel"
          :disabled="elementDisabled"
          :multiple="widget.options.multiple"
          :clearable="widget.options.clearable"
          :placeholder="widget.options.placeholder"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :filterable="widget.options.filterable"
          :ref="'fm-'+widget.model"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          v-bind="{...widget.options.customProps, ...extendProps}"
        >
          <el-option v-for="item in remoteOptions" :key="item.value" :value="item.value"
                     :label="widget.options.showLabel || widget.options.remote?item.label:item.value"></el-option>
        </el-select>
      </template>
    </template>
     <template v-if="widget.type == 'deptSelect'">
      <template v-if="printRead">
        <template v-if="widget.options.remote">
          {{
            typeof dataModel == 'object' ?
              (dataModel.map(dm => remoteOptions.find(item => item.value == dm)
                && remoteOptions.find(item => item.value == dm).label).join('、'))
              : (remoteOptions.find(item => item.value == dataModel)
                && remoteOptions.find(item => item.value == dataModel).label)
          }}
        </template>
        <template v-else>
          {{
            widget.options.showLabel ?
              (
                typeof dataModel == 'object' ?
                  dataModel.map(dm => remoteOptions.find(item => item.value == dm) && remoteOptions.find(item => item.value == dm).label).join('、')
                  : (remoteOptions.find(item => item.value == dataModel) && remoteOptions.find(item => item.value == dataModel).label)
              ) :
              typeof dataModel == 'object' ? dataModel.join('、') : dataModel
          }}
        </template>
      </template>
      <template v-else>
        <el-select
          v-model="dataModel"
          :disabled="elementDisabled"
          :multiple="widget.options.multiple"
          :clearable="widget.options.clearable"
          :placeholder="widget.options.placeholder"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :filterable="widget.options.filterable"
          :ref="'fm-'+widget.model"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          v-bind="{...widget.options.customProps, ...extendProps}"
        >
          <el-option v-for="item in remoteOptions" :key="item.value" :value="item.value"
                     :label="widget.options.showLabel || widget.options.remote?item.label:item.value"></el-option>
        </el-select>
      </template>
    </template>

     <template v-if="widget.type == 'userSelect'">
      <template v-if="printRead">
        <template v-if="widget.options.remote">
          {{
            typeof dataModel == 'object' ?
              (dataModel.map(dm => remoteOptions.find(item => item.value == dm)
                && remoteOptions.find(item => item.value == dm).label).join('、'))
              : (remoteOptions.find(item => item.value == dataModel)
                && remoteOptions.find(item => item.value == dataModel).label)
          }}
        </template>
        <template v-else>
          {{
            widget.options.showLabel ?
              (
                typeof dataModel == 'object' ?
                  dataModel.map(dm => remoteOptions.find(item => item.value == dm) && remoteOptions.find(item => item.value == dm).label).join('、')
                  : (remoteOptions.find(item => item.value == dataModel) && remoteOptions.find(item => item.value == dataModel).label)
              ) :
              typeof dataModel == 'object' ? dataModel.join('、') : dataModel
          }}
        </template>
      </template>
      <template v-else>
        <el-select
          v-model="dataModel"
          :disabled="elementDisabled"
          :multiple="widget.options.multiple"
          :clearable="widget.options.clearable"
          :placeholder="widget.options.placeholder"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :filterable="widget.options.filterable"
          :ref="'fm-'+widget.model"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          v-bind="{...widget.options.customProps, ...extendProps}"
        >
          <el-option v-for="item in remoteOptions" :key="item.value" :value="item.value"
                     :label="widget.options.showLabel || widget.options.remote?item.label:item.value"></el-option>
        </el-select>
      </template>
    </template>

    <template v-if="widget.type=='switch'">
      <template v-if="printRead">
        {{ dataModel }}
      </template>
      <template v-else>
        <el-switch
          v-model="dataModel"
          :disabled="elementDisabled"
          :ref="'fm-'+widget.model"
          :style="{width: isTable ? '100%' : widget.options.width}"
          v-bind="{...widget.options.customProps, ...extendProps}"
        >
        </el-switch>
      </template>
    </template>

    <template v-if="widget.type=='slider'">
      <template v-if="printRead">
        {{ dataModel }}
      </template>
      <template v-else>
        <el-slider
          v-model="dataModel"
          :min="widget.options.min"
          :max="widget.options.max"
          :disabled="elementDisabled"
          :step="widget.options.step"
          :show-input="widget.options.showInput"
          :range="widget.options.range"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :ref="'fm-'+widget.model"
          v-bind="{...widget.options.customProps, ...extendProps}"
        ></el-slider>
      </template>
    </template>

    <template v-if="widget.type=='imgupload'">
      <fm-upload
        v-model="dataModel"
        :disabled="elementDisabled"
        :readonly="widget.options.readonly || printRead"
        :style="{'width': isTable ? '100%' : widget.options.width}"
        :width="widget.options.size.width"
        :height="widget.options.size.height"
        :token="remoteToken"
        :domain="widget.options.domain"
        :multiple="widget.options.multiple"
        :limit="widget.options.limit"
        :is-qiniu="widget.options.isQiniu"
        :is-delete="widget.options.isDelete"
        :min="widget.options.min"
        :is-edit="widget.options.isEdit"
        :action="widget.options.action"
        :headers="widget.options.headers || []"
        :ref="'fm-'+widget.model"
        :withCredentials="widget.options.withCredentials"
        :print-read="printRead"
        @on-upload-success="handleOnUploadSuccess"
        @on-upload-error="handleOnUploadError"
        @on-upload-remove="handleOnUploadRemove"
        @on-upload-progress="handleOnUploadProgress"
        :on-select="handleOnUploadSelect"
      >
      </fm-upload>
    </template>

    <template v-if="widget.type == 'editor'">
      <template v-if="printRead">
        <div v-html="dataModel" class="ql-editor"></div>
      </template>
      <template v-else>
        <fm-editor
          v-model="dataModel"
          :sty="{width: isTable ? '100%' : widget.options.width, cursor: (elementDisabled) ? 'no-drop' : '', backgroundColor: (elementDisabled) ? '#F5F7FA' : ''}"
          :toolbar="widget.options.customToolbar"
          :disabled="elementDisabled"
          :readonly="true"
          :ref="'fm-'+widget.model"
        >
        </fm-editor>
      </template>
    </template>

    <template v-if="widget.type == 'cascader'">
      <template v-if="printRead">
        <template v-if="widget.options.remote">
          {{
            widget.options.multiple ?
              dataModel.map(dm => getCascaderText([...dm], remoteOptions).join(' / ')).join('、')
              : getCascaderText([...dataModel], remoteOptions).join(' / ')
          }}
        </template>
        <template v-else>
          {{
            widget.options.multiple ?
              dataModel.map(dm => getCascaderText([...dm], remoteOptions).join(' / ')).join('、')
              : getCascaderText([...dataModel], remoteOptions).join(' / ')
          }}
        </template>
      </template>
      <template v-else>
        <el-cascader
          v-model="dataModel"
          :disabled="elementDisabled"
          :clearable="widget.options.clearable"
          :placeholder="widget.options.placeholder"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :options="remoteOptions"
          @change="onCascaderChange"
          :ref="'fm-'+widget.model"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          :props="{multiple: widget.options.multiple, checkStrictly: widget.options.checkStrictly, ...(extendProps.props ?? {})}"
          collapse-tags
          :filterable="widget.options.filterable"
          v-bind="{...widget.options.customProps, ...extendProps}"
        >
        </el-cascader>
      </template>
    </template>
    <template v-if="widget.type == 'deptAndUserCascader'">
      <template v-if="printRead">
        <template v-if="widget.options.remote">
          {{
            widget.options.multiple ?
              dataModel.map(dm => getCascaderText([...dm], remoteOptions).join(' / ')).join('、')
              : getCascaderText([...dataModel], remoteOptions).join(' / ')
          }}
        </template>
        <template v-else>
          {{
            widget.options.multiple ?
              dataModel.map(dm => getCascaderText([...dm], remoteOptions).join(' / ')).join('、')
              : getCascaderText([...dataModel], remoteOptions).join(' / ')
          }}
        </template>
      </template>
      <template v-else>
        <el-cascader
          v-model="dataModel"
          :disabled="elementDisabled"
          :clearable="widget.options.clearable"
          :placeholder="widget.options.placeholder"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :options="remoteOptions"
          @change="onCascaderChange"
          :ref="'fm-'+widget.model"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          :props="{multiple: widget.options.multiple, checkStrictly: widget.options.checkStrictly, ...(extendProps.props ?? {})}"
          collapse-tags
          :filterable="widget.options.filterable"
          v-bind="{...widget.options.customProps, ...extendProps}"
        >
        </el-cascader>
      </template>
    </template>
    <template v-if="widget.type == 'deptCascader'">
      <template v-if="printRead">
        <template v-if="widget.options.remote">
          {{
            widget.options.multiple ?
              dataModel.map(dm => getCascaderText([...dm], remoteOptions).join(' / ')).join('、')
              : getCascaderText([...dataModel], remoteOptions).join(' / ')
          }}
        </template>
        <template v-else>
          {{
            widget.options.multiple ?
              dataModel.map(dm => getCascaderText([...dm], remoteOptions).join(' / ')).join('、')
              : getCascaderText([...dataModel], remoteOptions).join(' / ')
          }}
        </template>
      </template>
      <template v-else>
        <el-cascader
          v-model="dataModel"
          :disabled="elementDisabled"
          :clearable="widget.options.clearable"
          :placeholder="widget.options.placeholder"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :options="remoteOptions"
          @change="onCascaderChange"
          :ref="'fm-'+widget.model"
          @focus="handleOnFocus"
          @blur="handleOnBlur"
          :props="{multiple: widget.options.multiple, checkStrictly: widget.options.checkStrictly, ...(extendProps.props ?? {})}"
          collapse-tags
          :filterable="widget.options.filterable"
          v-bind="{...widget.options.customProps, ...extendProps}"
        >
        </el-cascader>
      </template>
    </template>

    <template v-if="widget.type == 'text'">
      <span :ref="'fm-'+widget.model"
            :style="{width: isTable ? '100%' : (widget.options.width || '100%'), display: 'inline-block'}">{{ dataModel }}</span>
    </template>

    <template v-if="widget.type == 'html'">
      <span v-html="dataModel" :ref="'fm-'+widget.model"
            :style="{width: isTable ? '100%' : (widget.options.width || '100%'), display: 'inline-block'}"></span>
    </template>

    <template v-if="widget.type == 'table'">
      <fm-form-table
        v-model="dataModel"
        :columns="widget.tableColumns"
        :models="dataModels"
        :remote="remote"
        :blanks="blanks"
        :disableddata="elementDisabled || printRead"
        :rules="rules"
        :name="widget.model"
        :remote-option="remoteOption"
        :ref="'fm-'+widget.model"
        :preview="preview"
        :platform="platform"
        :data-source-value="dataSourceValue"
        :event-function="eventFunction"
        :widget="widget"
        :print-read="printRead"
        :paging="widget.options.paging"
        :page-size="widget.options.pageSize"
        :container-key="containerKey"
        :is-delete="widget.options.isDelete ?? true"
        :is-add="widget.options.isAdd ?? true"
        :show-control="widget.options.showControl ?? true"
        :is-dialog="isDialog"
        :dialog-name="dialogName"
        :is-group="isGroup"
        :group="group"
        :field-node="fieldNode"
      >
        <template v-slot:[blank.name]="scope" v-for="blank in blanks">
          <slot :name="blank.name" :model="scope.model"></slot>
        </template>
      </fm-form-table>
    </template>

    <template v-if="widget.type == 'subform'">
      <fm-sub-form
        v-model="dataModel"
        :list="widget.list"
        :models="dataModels"
        :remote="remote"
        :blanks="blanks"
        :disableddata="elementDisabled || printRead"
        :rules="rules"
        :name="widget.model"
        :remote-option="remoteOption"
        :ref="'fm-'+widget.model"
        :preview="preview"
        :platform="platform"
        :data-source-value="dataSourceValue"
        :event-function="eventFunction"
        :widget="widget"
        :print-read="printRead"
        :paging="widget.options.paging"
        :page-size="widget.options.pageSize"
        :show-control="widget.options.showControl"
        :is-delete="widget.options.isDelete ?? true"
        :is-add="widget.options.isAdd ?? true"
        :is-dialog="isDialog"
        :dialog-name="dialogName"
        :is-group="isGroup"
        :group="group"
        :field-node="fieldNode"
        :container-key="containerKey"
      >
        <template v-slot:[blank.name]="scope" v-for="blank in blanks">
          <slot :name="blank.name" :model="scope.model"></slot>
        </template>
      </fm-sub-form>
    </template>

    <template v-if="widget.type == 'group'">
      <fm-group
        v-model="dataModel"
        :rules="rules"
        :element="widget"
        :remote="remote"
        :blanks="blanks"
        :edit="!elementDisabled"
        :remote-option="remoteOption"
        :platform="platform"
        :preview="preview"
        :container-key="containerKey"
        :data-source-value="dataSourceValue"
        :event-function="eventFunction"
        :print-read="printRead"
        :ref="'fm-'+widget.model"
        :is-group="isGroup"
        :group="group"
        :field-node="fieldNode"
      >
        <template v-slot:[blank.name]="scope" v-for="blank in blanks">
          <slot :name="blank.name" :model="scope.model"></slot>
        </template>
      </fm-group>
    </template>

    <template v-if="widget.type == 'fileupload'">
      <fm-file-upload
        v-model="dataModel"
        :disabled="elementDisabled"
        :style="{'width': isTable ? '100%' : widget.options.width}"
        :token="remoteToken"
        :domain="widget.options.domain"
        :multiple="widget.options.multiple"
        :limit="widget.options.limit"
        :is-qiniu="widget.options.isQiniu"
        :min="widget.options.min"
        :action="widget.options.action"
        :headers="widget.options.headers || []"
        :ref="'fm-'+widget.model"
        :withCredentials="widget.options.withCredentials"
        :print-read="printRead"
        :accept="widget.options.accept"
        @on-upload-success="handleOnUploadSuccess"
        @on-upload-error="handleOnUploadError"
        @on-upload-remove="handleOnUploadRemove"
        @on-upload-progress="handleOnUploadProgress"
        :on-select="handleOnUploadSelect"
      >
      </fm-file-upload>
    </template>

    <template v-if="widget.type == 'button'">
      <el-button
        :disabled="elementDisabled"
        :type="widget.options.buttonType"
        :plain="widget.options.buttonPlain"
        :round="widget.options.buttonRound"
        :circle="widget.options.buttonCircle"
        :style="{width: widget.options.width, 'vertical-align': 'top'}"
        :ref="'fm-'+widget.model"
        @click="handleOnClick"
        v-bind="{...widget.options.customProps, ...extendProps}"
      >{{ widget.options.buttonName }}
      </el-button>
    </template>

    <template v-if="widget.type == 'link'">
      <el-link
        :disabled="elementDisabled"
        :type="widget.options.linkType"
        :underline="widget.options.underline"
        :href="widget.options.href"
        :target="widget.options.blank ? '_blank' : '_self'"
        :ref="'fm-'+widget.model"
        @click="handleOnClick"
        v-bind="{...widget.options.customProps, ...extendProps}"
      >
        {{ widget.options.linkName }}
      </el-link>
    </template>

    <template v-if="widget.type == 'steps'">
      <el-steps :active="dataModel"
                :ref="'fm-'+widget.model"
                :space="widget.options.space"
                :direction="widget.options.direction"
                :process-status="widget.options.processStatus"
                :finish-status="widget.options.finishStatus"
                :align-center="widget.options.alignCenter"
                :simple="widget.options.simple"
                :style="{'line-height': 'normal'}"
                v-bind="{...widget.options.customProps, ...extendProps}"
      >
        <el-step
          :title="item.title"
          :description="item.description"
          v-for="(item, index) in remoteOptions" :key="index"></el-step>
      </el-steps>
    </template>

    <template v-if="widget.type == 'pagination'">
      <template v-if="printRead">
        Page {{ dataModel }}
      </template>
      <template v-else>
        <el-pagination
          :current-page.sync="dataModel"
          :page-size="widget.options.pageSize"
          :pager-count="widget.options.pagerCount"
          :disabled="widget.options.disabled"
          :background="widget.options.background"
          layout="total, prev, pager, next"
          :total="widget.options.total"
          :ref="'fm-'+widget.model"
          v-bind="{...widget.options.customProps, ...extendProps}"
        />
      </template>
    </template>

    <template v-if="widget.type == 'transfer'">
      <template v-if="printRead">
        <template v-if="widget.options.remote">
          {{
            dataModel.map(dm => widget.options.remoteOptions.find(item =>
              item[widget.options.props.key] == dm)?.[widget.options.props.label]).join('、')
          }}
        </template>
        <template v-else>
          {{
            dataModel.map(dm => remoteOptions.find(item =>
              item[propsTransfer.key] == dm)?.[propsTransfer.label]).join('、')
          }}
        </template>
      </template>
      <template v-else>
        <el-transfer
          :value="dataModel"
          :disabled="elementDisabled"
          :data="remoteOptions"
          :filterable="widget.options.filterable"
          :props="propsTransfer"
          :titles="widget.options.titles"
          :style="{width: isTable ? '100%' : widget.options.width}"
          :ref="'fm-'+widget.model"
          @change="handleTransferChange"
          v-bind="{...widget.options.customProps, ...extendProps}"
        ></el-transfer>
      </template>
    </template>
  </span>
</template>

<script>
import FmUpload from './Upload'
import FmFormTable from './FormTable'
import FmFileUpload from './Upload/file'
import FmEditor from './Editor'
import FmSubForm from './SubForm/index.vue'
import FmGroup from './GenerateGroup.vue'
import Vue from 'vue'
import {EventBus} from '../util/event-bus'
import {executeExpression, extractExpression, isExpression} from '../util/expression'
import _ from 'lodash'

export default {
  name: 'generate-element-item',
  components: {
    FmUpload,
    FmFormTable,
    FmFileUpload,
    FmEditor,
    FmSubForm,
    FmGroup
  },
  props: ['widget', 'value', 'models', 'remote', 'isTable', 'blanks', 'disabled', 'edit',
    'remoteOption', 'rules', 'platform', 'preview', 'dataSourceValue', 'eventFunction',
    'rowIndex', 'tableName', 'printRead', 'isMobile', 'isSubform', 'subName',
    'isDialog', 'dialogName', 'group', 'fieldNode', 'containerKey', 'isGroup'],
  data() {
    return {
      dataModel: this.value,
      dataModels: this.models,
      key: new Date().getTime(),
      modelName: this.widget.model,
      remoteOptions: [],
      dynamicEvents: this.handleOnDynamicEvent(),
      propsTransfer: {key: 'key', label: 'label'},
      generateDisabled: undefined,
      remoteToken: ''
    }
  },
  computed: {
    elementDisabled() {
      let currentDisabled = this.widget.options.disabled

      if (isExpression(this.widget.options.disabled)) {
        currentDisabled = executeExpression(extractExpression(this.widget.options.disabled), this.currentOptions, this.formContext)
      }

      if (typeof this.generateDisabled === 'boolean') {
        return !this.edit || this.generateDisabled
      } else {
        return !this.edit || Boolean(currentDisabled)
      }
    },
    currentOptions() {
      if (this.isTable || this.isSubform) {
        return {
          value: this.dataModel,
          fieldNode: this.fieldNode,
          currentRef: this.$refs['fm-' + this.widget.model],
          rowIndex: this.rowIndex,
          row: _.cloneDeep(this.models),
          field: this.widget.model,
          group: this.group
        }
      } else {
        return {
          value: this.dataModel,
          fieldNode: this.fieldNode,
          currentRef: this.$refs['fm-' + this.widget.model],
          field: this.widget.model,
          group: this.group
        }
      }
    },
    extendProps() {
      let obj = {}

      this.widget.options.extendProps && Object.keys(this.widget.options.extendProps).forEach(key => {
        let value = this.widget.options.extendProps[key]

        if (!isExpression(value)) {
          obj[key] = value
        } else {
          obj[key] = executeExpression(extractExpression(value), this.currentOptions, this.formContext)
        }
      })

      return obj
    },
    groupNode() {
      return this.group ? this.group + '.' + this.widget.model : this.widget.model
    }
  },
 async created() {
    if (!this.widget.options.remote) {
      if (this.widget.type == 'steps') {
        this.loadOptions(this.widget.options.steps)
      } else if (this.widget.type == 'transfer') {
        this.loadOptions(this.widget.options.data)
      } else {
        this.loadOptions(this.widget.options.options)
      }
    }
    if (this.widget.options.remote
      && (Object.keys(this.widget.options).indexOf('remoteType') >= 0 ? this.widget.options.remoteType == 'func' : true)
      && this.remote[this.widget.options.remoteFunc]) {

      this.remote[this.widget.options.remoteFunc]((data) => {
        this.loadOptions(data)
      })
    }
    if (this.widget.options.remote
      && this.widget.options.remoteType == 'option'
      && this.remoteOption[this.widget.options.remoteOption]) {

      this.loadOptions(this.remoteOption[this.widget.options.remoteOption])
    }
    if (this.widget.options.remote
      && this.widget.options.remoteType == 'datasource'
      && this.dataSourceValue) {

      let options = this.getDataSourceOptions()

      options && options.value && this.loadOptions(options.value)
    }
    if (this.widget.options.remote && this.widget.options.remoteType == 'fx') {
      let options = executeExpression(this.widget.options.remoteFx, {}, this.formContext)

      options && this.loadOptions(options)
    }
    if ((this.widget.type === 'imgupload' || this.widget.type === 'fileupload') && this.widget.options.isQiniu) {

      this.loadUploadConfig()
    }
    if (this.widget.type == 'component') {

      const _pthis = this

      Vue.component(`component-${this.widget.key}-${this.key}`, {
        template: `${this.widget.options.template}`,
        props: ['value'],
        data: () => ({
          dataModel: this.value,
          formState: this.formContext
        }),
        watch: {
          dataModel(val) {

            if (this.ui == 'antd') {
              EventBus.$emit('on-field-change', this.$attrs.id, val)
            } else {
              this.$emit('input', val)
            }
          },
          value(val) {
            this.dataModel = val
          }
        },
        methods: {
          triggerEvent(eventName, arg) {
            if (_pthis.eventScriptConfig()) {
              let currentEventScript = _pthis.eventScriptConfig().find(item => item.name == eventName)

              if (currentEventScript) {
                _pthis.eventFunction[currentEventScript.key]({
                  ..._pthis.currentOptions,
                  $eventArgs: arg
                })
              }
            }
          }
        }
      })
    }
  },
  inject: ['generateComponentInstance', 'deleteComponentInstance', 'eventScriptConfig', 'dynamicValueData', 'formContext', 'sendRequest'],
  mounted() {
    this.generateComponentInstance && this.generateComponentInstance(
      this.fieldNode,
      this.$refs['fm-' + this.widget.model]
    )

    this.handleOnMounted()
  },
  beforeDestroy() {

    this.deleteComponentInstance && this.deleteComponentInstance(this.fieldNode)
  },
  methods: {
    handleTest(...args) {
      console.log('test', args)
    },
    handleOnDynamicEvent() {
      let currentEvents = {}

      for (let i in this.widget.events) {
        console.log('i', i)

        let funcKey = this.widget.events[i]

        funcKey && (
          currentEvents[i] = this.callbackDynamicFunc(funcKey)
        )
      }

      return currentEvents
    },
    callbackDynamicFunc(funcKey) {
      let callback = (...arg) => {
        this.eventFunction[funcKey]({
          ...this.currentOptions,
          $eventArgs: arg
        })
      }
      return callback
    },
    refreshOptionData(args) {
      return new Promise((resolve, reject) => {
        if (this.widget.options.remote && this.widget.options.remoteType === 'fx' && this.widget.options.remoteFx) {
          let value = executeExpression(this.widget.options.remoteFx, this.currentOptions, this.formContext)

          if (value !== null) {
            this.loadOptions(value)
          }

          resolve(value)
        }

        if (this.widget.options.remote && this.widget.options.remoteType === 'datasource' && this.widget.options.remoteDataSource) {
          let curArgs = typeof this.widget.options.remoteArgs === 'string' ? {} : {...this.widget.options.remoteArgs}

          for (let key in curArgs) {
            if (isExpression(curArgs[key])) {
              curArgs[key] = executeExpression(extractExpression(curArgs[key]), this.currentOptions, this.formContext)
            }
          }

          if (args && typeof args === 'object') {
            curArgs = {...curArgs, ...args}
          }

          let key = this.group ? this.group + '.' + this.widget.model + '.' + this.widget.options.remoteDataSource
            : this.widget.model + '.' + this.widget.options.remoteDataSource

          let sourceValue = this.dataSourceValue.find(item => item.key === key && _.isEqual(item.args, curArgs))

          if (sourceValue) {
            this.loadOptions(sourceValue.value)

            resolve(sourceValue.value)
          } else {
            console.log('====sendRequest')
            this.sendRequest(this.widget.options.remoteDataSource, curArgs).then(resData => {
              this.loadOptions(resData)

              resolve(resData)
            }).catch(e => {
              reject(e)
            })
          }
        }
      })
    },
    loadOptions(data) {
      console.log(data,this.widget.type);
      if (!Array.isArray(data)) return
      this.remoteOptions = data.map(item => {

        if (this.widget.options.props.children && this.widget.options.props.children.length && Object.keys(item).includes(this.widget.options.props.children)) {
          return {
            value: item[this.widget.options.props.value],
            label: item[this.widget.options.props.label],
            children: this.processRemoteProps(item[this.widget.options.props.children], this.widget.options.props)
          }
        } else {
          if (this.widget.type == 'steps') {
            return {
              title: item[this.widget.options.props.title] + '',
              description: item[this.widget.options.props.description]
            }
          } else if (this.widget.type == 'transfer') {
            return {
              key: item[this.widget.options.props.key],
              label: item[this.widget.options.props.label]
            }
          } else {
            return {
              value: item[this.widget.options.props.value],
              label: item[this.widget.options.props.label]
            }
          }
        }

      })
    },
    getOptions() {
      console.log(1111, '=======', this.remoteOptions);
      return JSON.parse(JSON.stringify(this.remoteOptions))
    },
    processRemoteProps(children, props) {
      if (children && children.length) {
        return children.map(item => {
          if (this.processRemoteProps(item[props.children], props).length) {
            return {
              value: item[props.value],
              label: item[props.label],
              children: this.processRemoteProps(item[props.children], props)
            }
          } else {
            return {
              value: item[props.value],
              label: item[props.label],
            }
          }
        })
      } else {
        return []
      }
    },
    onCascaderChange(value) {
      console.log(value)
      if (value) {
        this.$nextTick(() => {
          this.$parent && this.$parent.clearValidate()
          this.$parent && this.$parent.$parent && this.$parent.$parent.$refs.generateFormItem && this.$parent.$parent.$refs.generateFormItem.clearValidate()
        })
      }
    },
    handleTransferChange(value) {
      this.dataModel = value
    },
    getCascaderText(value, options, texts = []) {
      if (value.length >= 1) {
        let currentOpt = options?.find(opt => opt.value == value[0])
        if (currentOpt) {
          texts.push(currentOpt.label)
        }
        value.splice(0, 1)
        return this.getCascaderText(value, currentOpt?.children, texts)
      } else if (value.length == 0) {
        return texts
      }
    },
    loadUploadConfig() {
      if (this.widget.options.tokenType === 'func') {
        !this.widget.options.token && this.remote[this.widget.options.tokenFunc]((data) => {
          this.remoteToken = data
        })
      } else if (this.widget.options.tokenType === 'fx') {
        let token = executeExpression(this.widget.options.tokenFx, this.currentOptions, this.formContext)

        token && (this.remoteToken = token)
      } else {
        if (this.dataSourceValue) {
          let token = this.getDataSourceOptions('tokenDataSource')

          token && token.value && (this.remoteToken = token.value)
        }
      }
    },
    handleOnMounted() {
      this.execFunction('onMounted', {})
    },
    handleOnClick() {
      this.execFunction('onClick', {})
    },
    handleOnFocus() {
      this.execFunction('onFocus', {})
    },
    handleOnBlur() {
      this.execFunction('onBlur', {})
    },
    handleOnUploadSelect(file) {
      return this.execFunction('onSelect', {file: file})
    },
    handleOnUploadSuccess(file) {
      this.execFunction('onUploadSuccess', {file: file})
    },
    handleOnUploadError(file) {
      this.execFunction('onUploadError', {file: file})
    },
    handleOnUploadProgress(file) {
      this.execFunction('onUploadProgress', {file: file})
    },
    handleOnUploadRemove(file) {
      this.execFunction('onRemove', {file: file})
    },
    execFunction(method, arg) {
      if (this.widget.events && this.widget.events[method]) {
        let funcKey = this.widget.events[method]

        return this.eventFunction[funcKey]({
          ...this.currentOptions,
          ...arg,
        })
      }
    },
    getDataSourceOptions(remoteName = 'remoteDataSource') {
      let key = this.group ? this.group + '.' + this.widget.model + '.' + this.widget.options[remoteName]
        : this.widget.model + '.' + this.widget.options[remoteName]
      return this.dataSourceValue.find(item => item.key === key)
    },
    disabledElement(disabled) {
      this.generateDisabled = disabled
    }
  },
  watch: {
    value(val) {
      this.dataModel = val
    },

    dataModel(val, oldValue) {
      if (JSON.stringify(val) != JSON.stringify(oldValue)) {
        this.$emit('input', val)
      }
    },
    'remoteOption': {
      deep: true,
      handler: function (val) {
        if (Object.keys(this.remoteOption).indexOf(this.widget.options.remoteOption) >= 0
          && this.widget.options.remote
          && this.widget.options.remoteType == 'option'
        ) {
          this.loadOptions(this.remoteOption[this.widget.options.remoteOption])
        }
      }
    },
    'dataSourceValue': {
      deep: true,
      handler: function (val) {

        if (this.dataSourceValue) {
          let options = this.getDataSourceOptions()

          options && options.value && this.loadOptions(options.value)
        }

        if ((this.widget.type === 'imgupload' || this.widget.type === 'fileupload') && this.widget.options.isQiniu) {

          this.loadUploadConfig()
        }
      }
    }
  }
}
</script>
