el-form封装

<template>
  <el-form
    ref="elform"
    :model="formData"
    :inline="inline"
    :label-width="formLabelWidth"
    :size="size"
    v-bind="$attrs"
    :rules="rules"
    v-on="$listeners"
    @submit.native.prevent
  >
    <!-- {{ notebookAndModuleInfo }} -->
    <!-- {{ formWidth }} -->
    <!-- {{ autoLayout }}
    {{ isAutoComputedColumns }}
    {{ Object.keys(formView).length }}
    {{ columns }}
    {{ itemcolumns }} -->
    <!-- {{ checkboxMultiple }} -->
    <!-- {{ formView }} -->
    <!-- {{ formData }} -->
    <!-- {{ rules }} -->
    <!-- {{ proxyMethods }} -->
    <!-- {{ tableRowIndex }} -->
    <!-- {{ groupCodeOptions }} -->
    <draggable
      :group="dragGroup"
      animation="300"
      :scroll="true"
      @end="dragEnd"
      ghostClass="ghost"
      :disabled="!draggable"
      :class="[layoutClass, hiddenLabelClass, labelPosition ? `el-form--label-${labelPosition}` : '', dragFormClass]"
      :style="styleObj"
    >
      <!-- :label="item.itemlabel" -->
      <template v-for="(item, key) in formView">
        <el-form-item
          v-if="
            item.showInEditForm ||
            (typeof item.hidden === 'function'
              ? !item.hidden({
                  item,
                  formView,
                  formData,
                  editTableRowIndex,
                  tableRowIndex
                })
              : !item.hidden &&
                !hiddenKeys.includes(item.prop || key) &&
                !hiddenTypes.includes(item.itemtype) &&
                item?.itemAttr != 'hidden')
          "
          v-show="(item.showInEditForm || item.show) ?? true"
          :key="item.key || key"
          :prop="item.prop || key"
          :show-message="item.showMessage"
          :item-key="key"
          :label-width="item.labelWidth"
          :label="$t(item.itemlabel) || item.itemlabel"
          :readonly="item.readonly"
          :class="[
            {
              selectedFormItem: selectedKey === key,
              hiddenLabelClass: item.hiddenLabel,
              itemIsDisabled:
                typeof item.itemDisabled === 'function'
                  ? item.itemDisabled({
                      item,
                      formView,
                      formData,
                      editTableRowIndex,
                      tableRowIndex
                    })
                  : item.itemDisabled,
              contentOverHidden: ['Table'].includes(item.itemtype) ? true : false
            },
            item.itemClassName
          ]"
          @click.native.stop="
            handleClickFormItem({
              key,
              item,
              formView,
              formData,
              editTableRowIndex,
              tableRowIndex
            })
          "
          :style="[setStyle(item, key), item.itemStyle]"
        >
          <!-- TODO注意key和prop,要考虑具体绑定的值和验证的值在一些场景是否会区分 -->

          <!--TODO需要插件语法支持,默认为 :clearable="item.clearable ?? true" -->
          <!-- <template slot="label" v-if="!item.hiddenLabel">
            {{ item.itemlabel }}
          </template> -->
          <template #label v-if="item.customFormLabel">
            <div>
              <span>{{ item.itemlabel }}</span>
              <el-tooltip :content="item.formLabelContent" placement="top">
                <i class="el-icon-question" style="color: #e6a23c; margin-left: 2px" v-if="item.formLabelContent"></i>
              </el-tooltip>
            </div>
          </template>
          <span slot="label" v-if="item.clickable">
            <span :class="item.clickable ? 'clickable' : ''">{{ $t(item.i18nkey || item.itemlabel) || ' ' }}</span>
          </span>
          <!-- ReadonlyInput类型仅仅用来展示,需要配合bindkey一起使用 -->
          <el-input
            v-if="item.itemtype === 'ReadonlyInput'"
            v-model="formData[item.bindkey]"
            v-bind="item"
            v-on="item"
            :placeholder="$t(item.placeholder || `${$t('请输入')} ${$t(item.label || item.itemlabel || '')}`)"
            :title="formData[item.bindkey] ?? ''"
          >
          </el-input>
          <el-input
            v-else-if="item.itemtype === 'Input'"
            :maxlength="item.verify && !item?.needMaxLength ? false : item.maxlength || 255"
            :show-word-limit="item.showWordLimit === false || !item.maxlength ? false : true"
            ref="formInput"
            :id="item?.ref || 'formInput'"
            v-model="formData[key]"
            v-bind="item"
            v-on="item"
            v-verify="item.verify"
            :clearable="item.clearable ?? true"
            :readonly="item?.readonly || item?.isReadonlyInputView"
            @clear="handleClear"
            @click.native="clickHandler(key, item)"
            @keyup.enter.native="keyupEnterHandler(key, item)"
            :placeholder="
              $t(
                item.placeholder ||
                  `${showPlaceholderPrefix ? $t('请输入') : ''} ${$t(item.label || item.itemlabel || '')}`
              )
            "
            :title="item.itemlabel && !item.itemlabel.includes('密码') && formData[key] ? formData[key] : ''"
            :class="item.showWordLimit === false || !item.maxlength ? '' : 'showWordLimitInput'"
          >
            <component :is="item.prefix" slot="prefix" v-if="item.prefix"></component>
            <component :is="item.suffix" slot="suffix" v-if="item.suffix"></component>
            <component
              :is="item.prepend"
              slot="prepend"
              v-if="item.prepend"
              v-bind="item.prependAttrs"
              v-on="item.prependListeners"
            ></component>
            <component :is="item.append" slot="append" v-if="item.append"></component>
            <template v-if="item.child">
              {{ typeof item.child === 'function' ? item.child({ key, formData, itemConfig: item }) : item.child }}
            </template>
            <template slot="append" v-if="item.appendTemplate">
              {{
                typeof item.appendTemplate === 'function'
                  ? item.appendTemplate({ key, formData, itemConfig: item })
                  : item.appendTemplate
              }}
            </template>
          </el-input>
          <el-input
            v-else-if="item.itemtype === 'Password'"
            v-model="formData[key]"
            type="password"
            autocomplete="new-password"
            :maxlength="item.verify ? false : item.maxlength || 255"
            :show-word-limit="item.showWordLimit === false || !item.maxlength ? false : true"
            :placeholder="$t(item.placeholder || `${$t('请输入')} ${$t(item.label || item.itemlabel || '')}`)"
          >
            <!--            <i style="cursor: pointer; line-height: 30px" slot="suffix" :class="iconClass" @click="showPwd(key)"></i>-->
          </el-input>
          <toggle-password v-else-if="item.itemtype === 'TogglePassword'" v-model="formData[key]" v-bind="item">
          </toggle-password>
          <el-button
            v-else-if="item.itemtype === 'Button'"
            v-bind="item"
            :menuCode="item.menuCode"
            :disabled="
              typeof item.disabled === 'function'
                ? item.disabled({
                    item,
                    formView,
                    formData,
                    editTableRowIndex,
                    tableRowIndex
                  })
                : item.disabled
            "
            @click="item.click({ key, tableRowIndex, tableColIndex, formData })"
          >
            {{
              typeof item.buttonText === 'function'
                ? item.buttonText({ key, tableRowIndex, tableColIndex, formData })
                : $t(item.buttonText)
            }}
          </el-button>
          <template v-else-if="item.itemtype === 'NativeFile'">
            <!-- <input type="file" @change="item.change && item.change($event)" class="nativeFile" /> -->
            <input
              ref="nativeFile"
              type="file"
              id="nativeFile"
              style="display: none"
              @change="nativeFileChange(item, $event)"
            />
            <input ref="nativeFileName" id="nativeFileName" readonly />
            <input
              type="button"
              :value="$t('选择文件')"
              style="border-radius: 2px; padding: 0 4px; margin-left: 6px"
              @click="nativeFileClick"
            />
          </template>

          <template v-else-if="item.itemtype === 'Autocomplete'">
            <el-autocomplete
              v-bind="item"
              v-on="item"
              v-model="formData[key]"
              :title="formData[key]"
              @select="changeAutoComplete()"
            >
              <template slot-scope="{ item }">
                <span>{{ item.label || item.value }}</span>
              </template>
            </el-autocomplete>
          </template>
          <template v-else-if="item.itemtype === 'CustomAutocomplete'">
            <customAutocomplete
              :formData="formData"
              :itemkey="key"
              :formItem="item"
              v-model="formData[key]"
              :title="formData[key]"
            >
            </customAutocomplete>
          </template>

          <el-input
            v-else-if="item.itemtype === 'SelectInput'"
            v-model="formData[key]"
            v-bind="item"
            v-on="item"
            v-verify="item.verify"
            clearable
            @clear="handleClear"
            :placeholder="$t(item.placeholder || `${$t('请输入')} ${$t(item.label || item.itemlabel || '')}`)"
            :title="formData[key]"
          >
            <!-- ReadonlyInput类型仅仅用来展示,需要配合bindkey一起使用 -->
            <template v-if="item.selectConfig.itemtype === 'ReadonlyInput'">
              <span :slot="item.selectConfig.slot || 'append'">{{ formData[item.selectConfig.bindkey] }}</span>
            </template>
            <template v-else>
              <el-select
                v-if="item.selectConfig"
                v-model="formData[item.selectConfig.prop]"
                :slot="item.selectConfig.slot || 'append'"
                :style="[{ minWidth: '80px' }, item.selectConfig.itemStyle]"
                :placeholder="$t('请选择')"
                v-bind="item.selectConfig"
                @clear="handleClear(item, key)"
                @change="handleChangeSelectInput(item.selectConfig, item.selectConfig.prop)"
              >
                <el-option
                  v-for="(selitem, index) in item.selectConfig.groupCode
                    ? groupCodeOptions[item.selectConfig.groupCode]
                    : item.selectConfig.options"
                  :key="index"
                  :label="selitem.label"
                  :value="selitem[item.selectConfig.bindValueField || 'value' || 'label']"
                  :disabled="selitem.disabled"
                  @click.native="handleSelect(selitem, key, item)"
                ></el-option>
              </el-select>
            </template>
          </el-input>

          <template v-else-if="item.itemtype === 'Select'">
            <div
              v-if="item.multiple"
              v-selectloadmore="item.infiniteScrollMethods ? item.infiniteScrollMethods : ''"
              style="width: 100%; display: grid"
            >
              <el-select
                v-model="checkboxMultiple[key]"
                v-bind="item"
                v-on="item"
                :collapse-tags="item.collapseTags ? true : false"
                ref="SelectMultiple"
                :placeholder="$t(item.placeholder || `${$t('请选择')} ${$t(item.label || item.itemlabel || '')}`)"
                :clearable="item.clearable ?? true"
                :filterable="item.filterable ?? true"
                :title="renderTitle('select', { key, item })"
                @clear="handleClear(item, key)"
              >
                <li
                  class="el-select-dropdown__item"
                  :class="{
                    selected: selmultiAll(key, 2),
                    optionBtnType: item.optionBtnType
                  }"
                  style="user-select: none"
                  v-if="item.multiple"
                  @click="selmultiAll(key, 1, item, item.groupCode ? groupCodeOptions[item.groupCode] : item.options)"
                >
                  <span>{{ selmultiAll(key, 2) ? $t('全不选') : $t('全选') }}</span>
                </li>
                <template v-if="item.slotTitle">
                  <li v-html="item.slotTitle" class="el-select-dropdown__item" style="user-select: none"></li>
                </template>
                <el-option
                  v-for="(selitem, index) in item.groupCode ? groupCodeOptions[item.groupCode] : item.options"
                  :key="selitem.value + index"
                  :label="selitem.label"
                  :value="selitem[item.bindValueField || 'value' || 'label']"
                  :disabled="selitem.disabled ?? (selitem.optionDisabled && selitem.optionDisabled(selitem))"
                  @click.native="
                    selectOptionsRow(
                      key,
                      selitem,
                      item,
                      item.groupCode ? groupCodeOptions[item.groupCode] : item.options
                    )
                  "
                >
                  <div v-if="item.slotHtml" v-html="item.slotHtml(selitem)"></div>
                </el-option>
              </el-select>
            </div>

            <div
              v-else
              v-selectloadmore="item.infiniteScrollMethods ? item.infiniteScrollMethods : ''"
              style="width: 100%; display: grid"
            >
              <el-select
                @focus="handleFocus(item, key)"
                :ref="'selectSingle' + key"
                v-model="formData[key]"
                v-bind="item"
                v-on="item"
                :placeholder="$t(item.placeholder || `${$t('请选择')} ${$t(item.label || item.itemlabel || '')}`)"
                :clearable="item.clearable ?? true"
                :filterable="item.filterable ?? true"
                :title="renderTitle('select', { key, item })"
                @clear="handleClear(item, key)"
                :bindKey="key"
                @filter-change="handleFilterChange"
                @visible-change="item.shouldInput ? selectFocus(key) : item.visibleChange"
              >
                <template v-if="item.slotTitle">
                  <li v-html="item.slotTitle" class="el-select-dropdown__item" style="user-select: none"></li>
                </template>
                <template v-if="item.customOption">
                  <li
                    :style="item.customOption.style || ''"
                    @click="item.customOption.click && item.customOption.click($refs['selectSingle' + key][0])"
                  >
                    <span> {{ item.customOption.label }} </span>
                  </li>
                  <el-option
                    v-if="
                      typeof item.options === 'function'
                        ? item.options(key, formData, formView) && item.options(key, formData, formView).length === 0
                        : item.options && item.options.length === 0
                    "
                    style="height: 0"
                    :value="''"
                    @click.native="selectOptionsRow(key, selitem, item)"
                  ></el-option>
                </template>

                <el-option
                  v-for="(selitem, index) in typeof item.options === 'function'
                    ? item.options(key, formData, formView)
                    : item.groupCode
                    ? groupCodeOptions[item.groupCode]
                    : item.options"
                  :key="key + index"
                  :optionData="selitem"
                  :filterVal="selectFilterObj[key]"
                  :customFilterMethod="item.customFilterMethod"
                  :label="selitem[item.bindLabelField || 'label' || 'value']"
                  :value="selitem[item.bindValueField || 'value' || 'label']"
                  :disabled="selitem.disabled"
                  @click.native="selectOptionsRow(key, selitem, item)"
                >
                  <span v-if="selitem.html" v-html="selitem.html"></span>
                  <div v-if="item.slotHtml" v-html="item.slotHtml(selitem)"></div>
                </el-option>
              </el-select>
            </div>
          </template>

          <!-- todo支持多选和下拉多选返回的值的类型,数组或者逗号隔开的字符串 -->
          <template v-else-if="item.itemtype === 'Checkbox'">
            <span
              v-if="item?.class === 'custom_check_box' || item?.class === 'custom_label'"
              :style="{ 'font-size': '12px', color: formData[key] ? 'red' : '' }"
              >{{ formData[key] ? $t('是') : $t('否') }}</span
            >
            <el-checkbox
              v-else
              v-model="formData[key]"
              v-bind="item"
              v-on="item"
              :title="formData[key]"
              :disabled="
                typeof item.disabled === 'function'
                  ? item.disabled({
                      item,
                      formView,
                      formData,
                      editTableRowIndex,
                      tableRowIndex
                    })
                  : item.disabled
              "
            >
              {{ item.label }}
            </el-checkbox>
          </template>
          <el-checkbox-group
            v-else-if="item.itemtype === 'CheckboxGroup'"
            v-model="checkboxMultiple[key]"
            v-bind="item"
            v-on="item"
            :title="formData[key]"
          >
            <template v-if="checkboxMultiple[key]">
              <el-checkbox
                v-for="(checkitem, checkboxindex) in item.options"
                :label="checkitem.value"
                :disabled="checkitem.disabled"
                :key="checkboxindex"
              >
                {{ checkitem.label }}
              </el-checkbox>
            </template>
          </el-checkbox-group>

          <el-radio-group
            v-else-if="item.itemtype === 'Radio'"
            v-model="formData[key]"
            v-bind="item"
            v-on="item"
            :title="formData[key]"
          >
            <el-radio
              v-for="(radioItem, index) in getSelectOptions(item, item.params)"
              :label="radioItem.value"
              :key="index"
            >
              {{ $t(radioItem.label) }}
            </el-radio>
          </el-radio-group>

          <el-switch
            v-else-if="item.itemtype === 'Switch'"
            v-model="formData[key]"
            v-bind="item"
            style="width: min-content"
            v-on="item"
            :title="formData[key]"
          ></el-switch>

          <el-date-picker
            v-else-if="item.itemtype === 'DatePicker'"
            :type="item.type || 'date'"
            :value-format="item.format || 'yyyy-MM-dd'"
            :placeholder="$t(item.placeholder) || $t('请选择日期')"
            :start-placeholder="$t('开始日期')"
            :end-placeholder="$t('结束日期')"
            v-model="formData[key]"
            v-bind="item"
            v-on="item"
            :title="formData[key]"
            :picker-options="item.pickerOptions ?? datePickerOptions"
            @clear="handleClear"
          ></el-date-picker>

          <el-date-picker
            v-else-if="item.itemtype === 'DateTimePicker'"
            :type="item.type || 'datetime'"
            :value-format="item.format || 'yyyy-MM-dd'"
            :placeholder="item.placeholder || $t('请选择日期')"
            v-model="formData[key]"
            v-bind="item"
            v-on="item"
            :title="formData[key]"
            :picker-options="item.pickerOptions ?? datePickerOptions"
            @clear="handleClear"
          ></el-date-picker>

          <el-time-picker
            v-else-if="item.itemtype === 'TimePicker'"
            :placeholder="item.placeholder || $t('请选择时间')"
            :value-format="item.format || 'HH:mm:ss'"
            v-model="formData[key]"
            v-bind="item"
            v-on="item"
            :title="formData[key]"
            @clear="handleClear"
          ></el-time-picker>

          <el-button-group v-else-if="item.itemtype === 'ButtonGroup'">
            <el-button
              v-for="(buttonItem, buttonIndex) in item.options"
              @click="formData[key] = buttonItem.value"
              :type="formData[key] == buttonItem.value ? item.checkedType || 'primary' : buttonItem.type"
              :key="buttonIndex"
              :title="formData[key]"
            >
              {{ buttonItem.label }}
            </el-button>
          </el-button-group>

          <el-dropdown v-else-if="item.itemtype === 'Dropdown'" v-bind="item" v-on="item">
            <span class="el-dropdown-link"> {{ item.text }}<i class="el-icon-arrow-down el-icon--right"></i> </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item v-for="dropdownItem in item.options" :key="dropdownItem.label || dropdownItem.value">
                {{ dropdownItem.label || dropdownItem.value }}
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>

          <el-input
            v-else-if="item.itemtype === 'Textarea'"
            type="textarea"
            show-word-limit
            :rows="item.rows || 3"
            v-model="formData[key]"
            v-bind="item"
            v-on="item"
            :title="formData[key]"
            :placeholder="$t(item.placeholder || `${$t('请输入')} ${$t(item.label || item.itemlabel || '')}`)"
          />

          <el-input-number
            v-else-if="item.itemtype === 'InputNumber' && !item.isNativeAction"
            v-model="formData[key]"
            v-bind="item"
            v-on="item"
            :title="formData[key]"
            @clear="handleClear"
            :max="item.max || 1000000000"
          ></el-input-number>
          <el-input-number
            v-else-if="item.itemtype === 'InputNumber' && item.isNativeAction"
            v-model="formData[key]"
            v-bind="item"
            :title="formData[key]"
            @input.native="item.input"
            :max="item.max || 1000000000"
            @clear="handleClear"
          ></el-input-number>

          <el-divider v-else-if="item.itemtype === 'Divider'" v-bind="item"
            ><span v-html="item.content"></span
          ></el-divider>

          <selectTree
            v-else-if="item.itemtype === 'SelectTree'"
            v-bind="item"
            v-on="item"
            :formData="formData"
            v-model="formData[key]"
            :data="item.groupCode ? getSelectOptions(item) : item.data"
          ></selectTree>
          <el-color-picker
            v-else-if="item.itemtype === 'ColorPicker'"
            v-bind="item"
            v-on="item"
            v-model="formData[key]"
          ></el-color-picker>
          <!-- <el-upload v-else-if="item.itemtype === 'Upload'" class="my-el-upload" v-bind="item" v-on="item">
            <span style="cursor:pointer" class="el-icon-upload2"></span>
            <div slot="tip" class="el-upload__tip" v-if="item.tip">{{ item.tip }}</div>
          </el-upload> -->
          <custom-file
            v-else-if="item.itemtype === 'CustomFile'"
            v-bind="item"
            v-on="item"
            v-model="formData[key]"
          ></custom-file>

          <upload-file
            v-else-if="item.itemtype === 'UploadFile'"
            v-bind="item"
            v-on="item"
            v-model="formData[key]"
          ></upload-file>

          <page-select
            v-else-if="item.itemtype === 'PageSelect'"
            style="width: 100%"
            v-bind="item"
            v-on="item"
            :modelval.sync="formData[key]"
            :formData="formData"
          ></page-select>

          <mingdu-form
            v-else-if="item.itemtype === 'SlotForm'"
            class="slotform"
            :form-data="item.formData ? formData[item.formData] : formData"
            :form-view="item.formView"
            v-bind="item.slotFormConfig"
            ref="SlotForm"
          ></mingdu-form>

          <template v-else-if="item.itemtype === 'Table'">
            <mingdu-table v-bind="item" :data="formData[key]" v-on="item" :ref="key + 'Mdtable'"></mingdu-table>
          </template>
          <!-- 配置选项 -->
          <template v-else-if="item.itemtype === 'ConfigOptions'">
            <config-options v-model="formData[key]"></config-options>
          </template>
          <template v-else-if="item.itemtype === 'TableConfigOptions'">
            <table-config-options v-model="formData[key]"></table-config-options>
          </template>
          <template v-else-if="item.itemtype === 'CustomElement'">
            <slot
              v-if="item.slotName"
              :name="item.slotName"
              :form-item="item"
              :form-data="formData"
              :prop-name="key"
            ></slot>
            <div
              v-else-if="item.html"
              v-html="
                typeof item.html === 'function'
                  ? item.html({
                      formItem: item,
                      formView,
                      formData,
                      propName: key
                    })
                  : item.html
              "
            ></div>
            <component
              :formItem="item"
              :formView="formView"
              :formData="formData"
              :propName="key"
              v-on="item.emitMethods"
              v-bind="item"
              :is="item.component"
              v-else-if="item.component"
            ></component>
            <component
              :scope="{ formItem: item, formView, formData, propName: key }"
              v-bind="item"
              :is="
                typeof item.render === 'function'
                  ? handleRendel(item.render, {
                      formItem: item,
                      formView,
                      formData,
                      propName: key
                    })
                  : item.render
              "
              v-else-if="item.render"
            ></component>
          </template>
          <el-input
            class="dialogSelect"
            v-else-if="item.itemtype === 'DialogSelect'"
            v-model="formData[`${key}_label`]"
            v-bind="item"
            v-on="item"
            @focus="openSelectDialog(item, key)"
            @input="inputDialogSelect($event, item, key)"
            id="dialogSelectInput"
            :placeholder="$t(item.placeholder || `${$t('请选择')} ${$t(item.label || item.itemlabel || '')}`)"
          >
            <el-button
              slot="append"
              icon="el-icon-circle-close"
              v-if="!item.required"
              @click="dialogSelectClear(item, key)"
            ></el-button>
            <el-button
              slot="append"
              icon="el-icon-folder-opened"
              v-if="item.shouldInput"
              @click="openSelectDialog(item, key, 'click')"
            ></el-button>
          </el-input>
          <!-- 仅显示文本 -->
          <span v-else-if="item.itemtype === 'Text'" :class="item.class || ''">{{
            item.formatter && typeof item.formatter === 'function'
              ? item.formatter(formData[key], {
                  formItem: item,
                  formView,
                  formData,
                  propName: key
                })
              : formData[key]
          }}</span>
          <span v-else>{{ formData[key] }}</span>
          <el-button
            v-if="selectedKey === key"
            @click.stop="deleteSelectedKeyEvent(key)"
            class="deleteSelectedKey"
            type="danger"
            icon="el-icon-delete"
          ></el-button>
        </el-form-item>
      </template>
      <slot name="rightContent"></slot>
      <!-- <el-button type="primary" style="width: 100px" v-if="formKey" @click="$saveFormView(formView, formKey)"
        >保存表单配置</el-button
      > -->
    </draggable>
    <!-- 选择用户 -->
    <SelectUser
      ref="refSelectUser"
      :defaultCheckedList="defaultCheckedUserList"
      @on-select="handleSelectUser"
    ></SelectUser>
    <!--    库位选择-->
    <location-select ref="locationSelect" @locationInfo="getLocationInfo"></location-select>
  </el-form>
</template>
<script>
import { formItemRules } from './js/form-rules.js'
import mixin from '../mixins/commonUi.js'
import draggable from 'vuedraggable'
import ConfigOptions from './basicComponent/config-options.vue'
import TableConfigOptions from './basicComponent/table-config-options.vue'
import { cloneDeep } from 'lodash'
import selectTree from './basicComponent/selectTree'
import CustomFile from '@/components/customFileUpload/index.vue'
import uploadFile from '@/components/uploadFile'
import PageSelect from './basicComponent/pageSelect.vue'
import customAutocomplete from './basicComponent/myCustomAutocomplete.vue'
import togglePassword from './basicComponent/myPassword.vue'
// import { createRulesBasicPage } from '@/util/validate';
import { optionsConfigs } from '@/common/getBasicDate.js'
import { nanoid } from 'nanoid'
import i18n from '@/lang'
import { mapGetters } from 'vuex'

function validateEmpty(message = '') {
  return function (rule, value, callback) {
    // console.log('validate Empty= >', value)
    typeof value === 'string' && value !== '' && value.trim() === ''
      ? callback(message || i18n.t('请勿全部输入空格'))
      : callback()
  }
}

const validatorRange = function ({ type = 'text', min = 0, max = 0, data = {}, required = false }) {
  const { itemtype, value, options } = data

  // 判断表单项是否必填
  if (required === false && (value === '' || value === undefined)) {
    return { success: true }
  }

  if (itemtype === 'Select') {
    // const option = (options ?? []).find((item) => item.value === value)
    // const len = `${option?.label ?? ''}`.length
    // if (len < min || len > max) {
    //   const message = `请选择长度【${min}~${max}】的数据`
    //   return { success: false, message }
    // } else {
    //   return { success: true }
    // }
    return { success: true }
  } else if (itemtype === 'Input' || itemtype === 'SelectInput') {
    if (type === 'text') {
      const len = `${value ?? ''}`.length
      if (len >= min && len <= max) {
        return { success: true }
      } else {
        const message = `请输入长度【${min}~${max}】的字符`
        return { success: false, message }
      }
    } else if (type === 'number') {
      const nValue = Number(value)
      if (isNaN(nValue)) {
        return { success: false, message: i18n.t('请输入正确的数字') }
      } else if (value !== '' && value !== '0' && /^[0]+$/.test(nValue)) {
        return { success: false, message: i18n.t('请勿输入全为0的数字') }
      } else if (nValue >= min && nValue <= max) {
        return { success: true }
      } else {
        const message = i18n.t('请输入范围【{0}~{1}】的{2}', [min, max, '数字'])
        return { success: false, message }
      }
    }
  } else {
    return { success: true }
  }
}

export default {
  inheritAttrs: false,
  name: 'MdForm',
  mixins: [mixin],
  components: {
    draggable,
    ConfigOptions,
    TableConfigOptions,
    selectTree,
    CustomFile,
    PageSelect,
    uploadFile,
    customAutocomplete,
    SelectUser: () => import('@/components/selectUser'),
    locationSelect: () => import('@/components/locationSelect'),
    togglePassword
  },
  props: {
    /**
     * 表单绑定的值
     *@param {paraName}
     */
    formData: {
      type: Object,
      default: () => ({})
    },
    // 用于查询条件时,去掉值为undefined null 和空字符串的数据
    searchData: {
      type: Object,
      default: () => ({})
    },
    // 表单是否可拖动
    draggable: {
      type: Boolean,
      default: false
    },
    // 拖动时的group名
    dragGroup: {
      type: String,
      default: ''
    },
    formKey: {
      type: String,
      default: ''
    },
    isUpdateCustomLabel: {
      type: Boolean,
      default: true
    },
    formView: {
      type: Object,
      default: () => ({})
    },
    inline: {
      type: Boolean,
      default: false
    },
    size: {
      type: String,
      default: 'small'
    },
    // label的宽度
    labelWidth: {
      type: [String, Number],
      default: '104px'
    },
    layoutClass: {
      // 可维护多种备选布局方式
      type: String,
      default: 'default-layout'
    },
    labelPosition: {
      // left right top
      type: String,
      default: 'right'
    },
    formColumns: {
      // 默认共12列,
      type: Number,
      default: 12
    },
    columns: {
      // 默认每个表单组件所占的列数,
      type: Number,
      default: 12
    },
    updateClearValidate: {
      // 默认更新view会校验表单
      type: Boolean,
      default: true
    },
    isAutoComputedColumns: {
      // 是否自动计算columns
      type: Boolean,
      default: true
    },
    // 是否自适应布局
    autoLayout: {
      type: Boolean,
      default: false
    },
    formItemMinWidth: {
      // form-item的最小宽度
      type: Number,
      default: 0
    },
    selectedKey: {
      type: [Number, String],
      default: ''
    },
    // 设置表单可拖动时的样式名
    dragFormClass: {
      type: String,
      default: ''
    },
    // 隐藏表单的所有label
    hiddenLabel: {
      type: Boolean,
      default: false
    },
    // 隐藏某些 form-item
    hiddenKeys: {
      type: Array,
      default: () => []
    },
    // 隐藏某些类型的表单
    hiddenTypes: {
      type: Array,

      default: () => []
    },
    // 列间距
    columnGap: {
      type: [Number, String],
      default: 6
    },
    // 行间距
    rowGap: {
      type: [Number, String],
      default: 16
    },
    editTableRowIndex: {
      // 当用于表格中的单元格的表单的时候的编辑行的索引
      type: [Number, String],
      default: -1
    },
    tableRowIndex: {
      // 当用于表格中的单元格的表单的时候的行索引
      type: [Number, String],
      default: -1
    },
    tableColIndex: {
      // 当用于表格中的单元格的表单的时候的行索引
      type: [Number, String],
      default: -1
    },
    editFormType: {
      // left right top
      type: Number,
      default: 1
    },
    showPlaceholderPrefix: {
      //placeholder前缀
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      refsName: 'elform',
      proxyMethodsArr: ['validate', 'validateField', 'resetFields', 'clearValidate'],
      checkboxMultiple: {}, // 代理多选框组数据
      formWidth: null,
      rules: {},
      formDataBackup: {},
      focusElement: null,
      selectAuto: true,
      selectOptions: {}, // 记录选择框的选项的行数据
      groupCodeOptions: {}, // 存储groupCode对应的options选项,可以直接通过groupCodeOptions['groupCode']渠道缓存的选项值
      selectFilterObj: {},
      datePickerOptions: {
        disabledDate(time) {
          return (
            time.getTime() <= new Date('1900-01-01 00:00:00').getTime() ||
            time.getTime() >= new Date('2073-12-30 23:59:59').getTime()
          )
        }
      },
      defaultCheckedUserList: [], // 已选择的用户
      currentFocusData: {} //记住当前操作数据
    }
  },
  inject: {
    notebookAndModuleInfo: {
      default: {}
    }
  },
  watch: {
    autoLayout: {
      handler(val) {
        // window.removeEventListener('resize', this.onResize)
        // console.log('%c 第372行', 'color:red;font-size:2em')
        // console.log(val)

        if (val) {
          // this.$nextTick(() => {
          // window.addEventListener('resize', this.onResize)
          // this.onResize()
          // })
        }
      },
      immediate: true
    }
  },
  created() {
    // this.rewriteEventMethods()
  },
  beforeMount() {
    this.initConfig()
  },
  mounted() {
    // console.log('%c 第839行 mounted', 'color:red;font-size:2em')
    // console.log(this.formView)
    this.$watch(
      () => {
        return this.formView
      },
      async () => {
        if (!this.formView) {
          return
        }
        console.log('表单json变化')
        await this.queryGroupCodeOptions().then(async (res) => {
          this.initFormItemConfig()
          this.initConfig()
          await this.rewriteEventMethods()
        })
      },
      { deep: true, immediate: true }
    )
    this.$watch(
      () => {
        return this.formData
      },
      (val) => {
        let changeField = null
        let searchData = {}
        Object.keys(this.formData).forEach((i) => {
          let v = this.formData[i]
          if (
            this.formView &&
            this.formView[i] &&
            (this.formView[i].type === 'Number' || this.formView[i].verify === 'integer')
          ) {
            const nVal = isNaN(Number(v)) || Number(v) === 0 ? '' : Number(v)
            this.$set(this.formData, i, nVal)
          }
          if (this.formView && this.formView[i]) {
            // console.log('2222', this.editFormType)
            //修改的时候调接口查询对应中文名
            if (
              this.formView[i].itemtype === 'DialogSelect' &&
              (this.formView[i].dialogType === 'selectUser' || this.formView[i].dialogType === 'selectLocation') &&
              this.editFormType == 2 &&
              !this.formView[i].shouldInput
            ) {
              if (this.formData.hasOwnProperty(i)) {
                if (!isNaN(this.formData[i])) {
                  //数字类型 为userid
                  this.$request.getUserInfoListById([this.formData[i]]).then((res) => {
                    let data = res?.data
                    this.$set(this.formData, i + '_label', data[this.formData[i]])
                  })
                } else {
                  if (this.formView[i].dialogType === 'selectLocation') {
                    this.$set(
                      this.formData,
                      i + '_label',
                      this.formData[this.formView[i]['linkSetField']] ||
                        this.formData[this.formView[i]['labelShowField']] ||
                        this.formData[i]
                    )
                  } else {
                    this.$set(this.formData, i + '_label', this.formData[i])
                  }
                }
              }
            }
          }
          if (v !== undefined && v !== null && v !== '' && !(Array.isArray(v) && v.length === 0)) {
            searchData[i] = v
          }
          if ((v || this.formDataBackup[i]) && JSON.stringify(v) !== JSON.stringify(this.formDataBackup[i])) {
            changeField = i
          }
        })
        this.$emit('update:searchData', searchData)
        // 不用失焦而是立即执行的input类型
        let inputTypes = ['Radio']
        if (
          document.activeElement &&
          document.activeElement !== document.body &&
          !this.focusElement &&
          !inputTypes.includes(this.formView[changeField]?.itemtype)
        ) {
          if (this.$refs.elform.$el.contains(document.activeElement)) {
            this.focusElement = document.activeElement
            this.focusElement.addEventListener('blur', this.elementBlur) // 只能监听部分类型的失去焦点事件,一些类型的数据改变应当立即抛出时间
          }
        } else {
          let types = ['Switch', 'DatePicker', 'DateTimePicker'].concat(inputTypes)

          if (changeField && types.includes(this.formView[changeField]?.itemtype)) {
            this.elementBlur()
          }
        }
        this.formDataBackup = cloneDeep(val)
        // if (this.notebookAndModuleInfo?.formUsedToExperimentNotebook) {
        // 	// 当表单用于实验记录页面的时候,监听数据变化,在离开实验记录页面的时候保存数据
        // 	this.$store.commit('record/SET_VALUECHANGE', true)
        // }
      },
      { deep: true, immediate: true }
    )

    if (this.autoLayout) {
      window.addEventListener('resize', this.onResize)
      this.onResize()
    }
    if (this.draggable) {
      document.addEventListener('click', this.documentClick)
    }
  },
  directives: {
    selectloadmore: {
      bind(el, binding) {
        if (binding.value) {
          const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
          SELECTWRAP_DOM.addEventListener('scroll', function () {
            const CONDITION = this.scrollHeight - this.scrollTop <= this.clientHeight
            if (CONDITION) {
              binding.value()
            }
          })
        }
      }
    }
  },
  methods: {
    findForm(el) {
      if (el.parentNode.tagName === 'FORM') {
        return el.parentNode
      } else {
        return this.findForm(el.parentNode)
      }
    },
    initConfig() {
      try {
        if (!this.isUpdateCustomLabel) {
          return
        }
        // console.log('formKey', this.formKey)
        let tarConfig = (this.sysFormConfig || {})[this.formKey] // 获取当前模块配置

        console.log('tarConfig', tarConfig)
        if (tarConfig) {
          for (let key in this.formView) {
            let configView = tarConfig[key]
            if (!configView) continue
            if (configView.itemCustomLabel) {
              this.formView[key].itemlabel = configView.itemCustomLabel
            }
            if (configView.itemAttr === 'required') {
              this.$set(this.formView[key], 'required', true)
            }
            if (configView.itemAttr === 'disabled') {
              this.formView[key].disabled = true
            }
            if (configView.itemAttr === 'readonly') {
              this.formView[key].readonly = true
            }
            if (configView.itemAttr === 'hidden') {
              this.formView[key].show = false
            }
            if (configView.itemAttr === 'normal') {
              this.$set(this.formView[key], 'required', false)
            }
            if (configView?.itemAttr != 'hidden') {
              if (this.formView[key].hasOwnProperty('itemAttr')) {
                delete this.formView[key].itemAttr
              }
              // this.$set(this.formView[key], 'itemAttr', '')
            }
          }
        }
      } catch {}
    },
    nativeFileClick() {
      this.$refs.nativeFile[0].click()
    },
    nativeFileChange(item, e) {
      this.$refs.nativeFileName[0].value = e.target.files[0].name
      item.change && item.change(e)
    },
    inputDialogSelect(e, item, key) {
      if (item.dialogType === 'selectUser') {
        this.$set(this.formData, key, e)
      }
    },
    openSelectDialog(data, key, type = 'focus') {
      this.currentFocusData = Object.assign({}, data, { key: key }) //记住当前操作数据
      if (data.dialogType === 'selectUser') {
        //选择用户组件
        if (type === 'focus' && data.shouldInput) return
        let dataList = Number(this.formData[key]) ? [Number(this.formData[key])].map((item) => ({ userId: item })) : []
        this.defaultCheckedUserList = this.formData.hasOwnProperty(key) ? dataList : []
        console.log('this.defaultCheckedUserList', this.defaultCheckedUserList)
        this.$refs.refSelectUser.show()
        //手动失焦,为了解决键盘输入还是会输入值在输入框中
        if (type === 'focus') {
          let formInput = document.getElementById('dialogSelectInput')
          formInput && formInput.blur()
        }
      } else if (data.dialogType === 'selectLocation') {
        if (type === 'focus' && data.shouldInput) return
        this.$refs.locationSelect.show()
      }
    },
    dialogSelectClear(data, key) {
      this.currentFocusData = Object.assign({}, data, { key: key }) //记住当前操作数据
      const item = this.currentFocusData
      if (data.dialogType === 'selectUser' || data.dialogType === 'selectLocation') {
        this.$set(this.formData, key, '')
        this.$set(this.formData, `${key}_label`, '')
        if (item.linkSetField) {
          // 需要关联的设置的值
          if (typeof item.linkSetField === 'string') {
            this.$set(this.formData, item.linkSetField, '')
          }
          if (typeof item.linkSetField === 'object') {
            // console.log('%c 第1228行', 'color: red; font-size: 2em')
            // console.log(item)
            this.$set(this.formData, item.linkSetField.setField, '')
          }

          if (Array.isArray(item.linkSetField)) {
            item.linkSetField.forEach((oItem) => {
              this.$set(this.formData, oItem.setField, '')
            })
          }
        }
        //选择用户组件
        item.change && item.change('')
        console.log('formData', this.formData)
      }
    },
    handleSelectUser(user = {}) {
      const item = this.currentFocusData
      let row = {
        label: user.userName,
        value: user.id,
        account: user.account,
        userCode: user.userCode,
        info: user
      }
      let value = row[item['bindValueField'] || 'value' || 'label']
      let key = item.key
      this.$set(this.formData, key, value)
      console.log('row, ', row)
      this.$set(this.formData, `${key}_label`, row.label)
      console.log('formDatahandleSelectUser', this.formData)
      if (item.linkSetField) {
        // 需要关联的设置的值
        if (typeof item.linkSetField === 'string') {
          this.$set(this.formData, item.linkSetField, row[item.linkSetFieldBindKey] || row.label)
        }
        if (typeof item.linkSetField === 'object') {
          // console.log('%c 第1228行', 'color: red; font-size: 2em')
          // console.log(item)
          this.$set(this.formData, item.linkSetField.setField, row[item.linkSetField.bindField] || row.label)
        }

        if (Array.isArray(item.linkSetField)) {
          item.linkSetField.forEach((oItem) => {
            this.$set(this.formData, oItem.setField, row[oItem.bindField])
          })
        }
      }
      item.afterSelect &&
        item.afterSelect({
          value: this.formData[key],
          key,
          formView: this.formView,
          formData: this.formData,
          selectOption: row
        })
    },
    getLocationInfo(data) {
      if (!data) return
      // console.log('getLocationInfo-data---------', data)
      const item = this.currentFocusData
      let row = {
        label: data.name,
        showName: data.name,
        value: data.id,
        info: data
      }
      let value = row[item['bindValueField'] || 'value' || 'label']
      // console.log('item', item, row, value)
      let key = item.key
      this.$set(this.formData, key, value)
      this.$set(this.formData, `${key}_label`, row.label)
      if (item.linkSetField) {
        // 需要关联的设置的值
        if (typeof item.linkSetField === 'string') {
          this.$set(this.formData, item.linkSetField, row.label)
        }
        if (typeof item.linkSetField === 'object') {
          // console.log('%c 第1228行', 'color: red; font-size: 2em')
          // console.log(item)
          this.$set(this.formData, item.linkSetField.setField, row[item.linkSetField.bindField] || row.label)
        }

        if (Array.isArray(item.linkSetField)) {
          item.linkSetField.forEach((oItem) => {
            this.$set(this.formData, oItem.setField, row[oItem.bindField])
          })
        }
      }
      if (item.recordSelectedRowInfo) {
        this.$set(this.formData, item.recordSelectedRowInfo, row)
      }
      item.afterSelect &&
        item.afterSelect({
          value: this.formData[key],
          key,
          formView: this.formView,
          formData: this.formData,
          selectOption: row
        })
    },
    renderTitle(type = '', data = {}) {
      // console.log('render title =>', type, data)
      let title = ''
      if (type === 'select') {
        const { key, item } = data
        const array = (item.groupCode ? this.groupCodeOptions[item.groupCode] : item.options) ?? []
        const options = typeof item.options === 'function' ? item.options(key, this.formData, this.formView) : array

        if (Array.isArray(options)) {
          const value = this.formData[key]
          const values = Array.isArray(value) ? value : [value]
          const matched = options.filter((e) => values.includes(e.value))
          title = matched.map((e) => e?.label ?? '').join('、')
        }
      }

      return title
    },
    handleFilterChange(filter, key) {
      this.$set(this.selectFilterObj, key, filter)
    },
    /**
     * formItem 点击时触发
     * @param { String } key formItem对应的key值
     * @param { Object } item formItem对应的项目
     * @param { Object } formView formView数据
     * @param { Object } formData formData数据
     */
    handleClickFormItem({ key, item, formView, formData }) {
      // console.log(key, item, formView, formData)
      this.draggable ? this.updateSelectedKey(key) : null

      if (item.clickable) {
        this.$emit('itemClick', { key, item, formView, formData })
      }
    },
    changeAutoComplete() {
      // console.log('changeAutoComplete')
      // 选中后让输入框失焦,不然下拉的数据可能还在
      document.body.click()
    },
    clickHandler(key, item) {
      typeof item.click === 'function' && item.click(key, item)
    },
    keyupEnterHandler(key, item) {
      typeof item.enterSearch === 'function' && item.enterSearch(item)

      this.$emit('enter', { key, itemData: item })
    },
    keydownHandler(e, key, item) {
      if (item.type === 'number') {
        let keyCode = e.keyCode
        if (keyCode === 69) {
          //数字类型输入框禁止输入e
          e.returnValue = false
          return false
        }
        return true
      }
    },
    handleClear(item, key) {
      console.log('🚀 ~ file: index.vue:932 ~ handleClear ~ item, key:', item, key)
      if (item && key) {
        item.clear && item.clear(item, this.formData[key], this.formData)
      }
      this.$nextTick(() => {
        this.elementBlur()
      })
    },
    handleChangeSelectInput(item, key) {
      if (item && key) {
        item.change && item.change(item, this.formData[key], this.formData)
      }
    },
    handleFocus(item, key) {
      if (item && key && item?.readonly) {
        let select = this.$refs['selectSingle' + key][0]
        select.blur()
      }
    },
    /**
     * Select 目前的选中值,选中值发生变化时触发
     * @param { Object } selitem
     * @param { String } key
     * @param { Object } item
     */
    handleSelect(selitem, key, item) {
      // console.log(selitem, key, item)
      const afterSelect = item.afterSelect ?? item.selectConfig.afterSelect ?? undefined
      if (typeof afterSelect === 'function') {
        afterSelect({
          value: this.formData[key],
          key,
          formView: this.formView,
          formData: this.formData,
          selectOption: selitem
        })
      }
    },
    elementBlur() {
      this.$emit('on-form-data-change', this.formData)
      if (this.focusElement) {
        this.focusElement.removeEventListener('blur', this.elementBlur)
        this.focusElement = null
      }
    },
    queryGroupCodeOptions() {
      return new Promise(async (resolve, reject) => {
        // 开始批量查询字典值
        const existOptionsConfigKeys = Object.keys(optionsConfigs)
        let groupCodeKeys = []
        const object = this.formView
        for (const key in object) {
          if (Object.hasOwnProperty.call(object, key)) {
            const item = object[key]
            const groupCode = item?.groupCode ?? item?.selectConfig?.groupCode ?? undefined
            if (groupCode) {
              // console.log('query =>', key, groupCode, isDictCode, this.groupCodeOptions)
              const isDictCode = !existOptionsConfigKeys.includes(groupCode) // 判断是否为维护的字典项数据
              if (isDictCode && !this.groupCodeOptions[groupCode]) {
                groupCodeKeys.push(groupCode)
              }
              if (!isDictCode && item?.selectConfig?.groupCode && !this.groupCodeOptions[groupCode]) {
                //selectInput下拉是本地数据的
                await this.setSelectOptions(groupCode, {}, {})
              }
            }
          }
        }
        // console.log(this.formView, existOptionsConfigKeys, groupCodeKeys)
        if (groupCodeKeys.length > 0) {
          const params = {
            dictCodes: groupCodeKeys,
            uuid: nanoid() // 随机字符串,无实义
          }

          let labelProp = localStorage.getItem('language') === 'en_US' ? 'dictItemNameEn' : 'dictItemName'
          const res = await this.$request.apiDictQueryListByCodes(params)
          const data = res?.data ?? {}
          for (const key in data) {
            if (groupCodeKeys.includes(key)) {
              const list = (data[key] || []).map((i) => {
                return {
                  label: i[labelProp],
                  value: i.dictItemCode
                }
              })
              this.$set(this.groupCodeOptions, key, list)
            }
          }
        }
        // 结束批量查询字典值
        resolve(this.groupCodeOptions)
      })
    },
    async initFormItemConfig() {
      // await this.queryGroupCodeOptions()

      let rules = {}

      for (let [key, item] of Object.entries(this.formView)) {
        // console.log('%c 第798行', 'color:red;font-size:2em')
        // console.log(key, item.groupCode, item.params)
        // if (item.watch) {
        //   this.setFieldWatch(key, item)
        // }
        if (item.groupCode && item.params && item.groupCode in optionsConfigs) {
          // 对于在本地维护的带参数的groupCode需要在params变化的时候重新查询
          this.$set(this.groupCodeOptions, item.groupCode, '')
        }
        // 多选框的值代理
        if (item.itemtype === 'CheckboxGroup') {
          this.setCheckboxMultiple(key)
        }
        if (item.itemtype === 'Select' && item.multiple) {
          this.setCheckboxMultiple(key)
        }
        if (item.itemtype === 'Select' && item.groupCode) {
          // console.log('%c 第722行', 'color:red;font-size:2em')
          // console.log(item)

          if (!this.groupCodeOptions[item.groupCode]) {
            await this.setSelectOptions(item.groupCode, item.params, item)
          }
        }

        if (item.deepBindSeparator) {
          this.setDeepBindValue(key, item.deepBindSeparator)
        }
        if (item.itemtype === 'SlotForm' && item.formData) {
          // console.log(item.formData)
          this.$set(this.formData, item.formData, this.formData[item.formData] || {})
        }
        // 设置选项的默认值
        if ('defaultValue' in item && (this.formData[key] === null || this.formData[key] === undefined)) {
          this.$set(
            this.formData,
            key,
            typeof item.defaultValue === 'function' ? item.defaultValue() : cloneDeep(item.defaultValue)
          )
        }

        // 设置表单的验证
        if (item.rules) {
          if (typeof item.rules === 'function') {
            rules[key] = item.rules({ formData: this.formData })
          } else {
            rules[key] = item.rules
          }
        } else {
          rules[key] = []
        }

        if (item.rulesType) {
          // 数组或者逗号隔开的字符串
          let rulesfields = Array.isArray(item.rulesType)
            ? item.rulesType
            : typeof item.rulesType === 'string'
            ? item.rulesType.split(',')
            : []
          let addrules = []
          rulesfields.forEach((i) => {
            addrules.push(formItemRules[i])
          })

          rules[key] = [...rules[key], ...addrules]
        }

        if (item.required) {
          // if (typeof(item.required) === 'boolean') { //仅输入框控制不为空
          rules[key] = [
            ...rules[key],
            item.itemtype === 'CheckboxGroup' || (item.itemtype === 'Select' && item.multiple)
              ? {
                  validator: (rule, value, callback) => {
                    let nVal = this.checkboxMultiple[key] || []
                    nVal.length > 0 ? callback() : callback(new Error(this.$t('请选择')))
                  },
                  required: true,
                  message: `${this.$t('请选择')}${this.$t(item.itemlabel) ?? ''}`,
                  trigger: 'change'
                }
              : {
                  required: true,
                  message: `${this.$t(item.itemlabel) || ''}  ${this.$t('不能为空')}`,
                  // pattern: '[^ \x22]+',
                  trigger: item.trigger || (['Input', 'InputNumber'].includes(item.itemtype) ? 'blur' : 'change')
                }
          ]
          // } else { //其他情况
          //   rules[key] = [
          //     ...rules[key]
          //   ].concat(createRulesBasicPage(item.required))
          // }
        } else {
          this.$nextTick(() => {
            this.$refs.elform && this.$refs.elform.clearValidate()
          })
        }

        if (item?.selectConfig?.required === true) {
          rules[key].push({
            validator: (rule, value, callback) => {
              let nVal = this.formData[item?.selectConfig?.prop]
              nVal ? callback() : callback(new Error(this.$t('请选择')))
            },
            message: `${this.$t('请选择')}${item?.selectConfig?.itemlabel ?? ''}`,
            trigger: item?.selectConfig?.trigger || 'change'
          })
        }

        // 判断输入框是否开启空格校验,默认开启校验
        if (
          item.itemtype === 'Input' ||
          item.itemtype === 'Textarea' ||
          (item.itemtype === 'CustomElement' && item?.customElementType === 'Input')
        ) {
          if (item.validateSpace !== false) {
            const message = item.validateSpaceMsg ?? `${item.itemlabel || ''}${this.$t('不能全为空格')}`
            const validator = {
              key: 'validateEmpty',
              validator: validateEmpty.call(this, message),
              trigger: 'blur'
            }

            if (Array.isArray(rules[key])) {
              const ruleKeys = rules[key].map((e) => e.key)
              const isExist = ruleKeys.includes('validateEmpty')
              if (!isExist) {
                rules[key].push(validator)
              }
            }
          }
        }

        // 判断是否传入 validateRange
        const itemtype = item.itemtype ?? ''
        if (Array.isArray(item.validateRange) && itemtype !== '') {
          const range = item.validateRange ?? []
          const type = range[0] ?? 'text'
          const first = isNaN(Number(range[1])) ? 0 : Number(range[1])
          const second = isNaN(Number(range[2])) ? 0 : Number(range[2])
          const [min = 0, max = 0] = [Math.min(first, second), Math.max(first, second)]

          const validateRangeKey = 'validateRange-' + key
          const validator = {
            key: validateRangeKey,
            validator: (rule, value, callback) => {
              const params = {
                type,
                key,
                data: { itemtype, value, options: item.options ?? [] },
                min,
                max,
                required: item.required ?? false
              }
              const { success, message } = validatorRange(params) ?? {}
              success ? callback() : callback(new Error(message))
            },
            trigger: 'change'
          }
          if (Array.isArray(rules[key])) {
            const ruleKeys = rules[key].map((e) => e.key)
            const isExist = ruleKeys.includes(validateRangeKey)
            if (!isExist) {
              rules[key].push(cloneDeep(validator))
            }
          } else {
            rules[key] = [cloneDeep(validator)]
          }
        }
      }
      this.rules = rules
      this.$nextTick(() => {
        if (this.updateClearValidate) {
          this.$refs.elform && this.$refs.elform.clearValidate()
        }
      })
      this.$emit('update:formView', this.formView)
    },
    selectFocus(key) {
      //  console.log('%c 第681行','color:red;font-size:2em');
      //  console.log(key)
      //  console.log('%c 第684行','color:red;font-size:2em');
      //  console.log(this.selectAuto)

      if (this.formView[key].shouldInput) {
        if (this.selectAuto) {
          setTimeout(() => {
            let ref = this.$refs['selectSingle' + key][0]
            if (ref) {
              console.log('%c 第687行', 'color:red;font-size:2em')
              console.log(this.formData[key])
              ref.$el.querySelector('input').value = this.formData[key] ?? ''
              ref.$el.querySelector('input').addEventListener('blur', () => {
                this.$set(this.formData, key, ref.$el.querySelector('input').value ?? '')
              })
            }
          }, 0)
        }
        this.selectAuto = !this.selectAuto
      }
    },
    /**
     *解析方法有几个形参,如果不需要额外的参数就不用重新方法
     *@param {paraName}
     */
    getFuncParameters(func) {
      if (typeof func === 'function') {
        var mathes = /[^(]+\(([^)]*)?\)/gm.exec(Function.prototype.toString.call(func))
        if (mathes[1]) {
          var args = mathes[1].replace(/[^,\w]*/g, '').split(',')
          return args
        }
      }
    },
    /**
     *重写element的组件的事件方法,使可以使用其他参数。如change:(val,{key,formView,formData})=>{}
     *@param {paraName}
     */
    rewriteEventMethods(type = 'install') {
      // console.log('%c 第472行', 'color:red;font-size:2em')
      // console.log(4545)
      const methodsArr = ['blur', 'focus', 'change', 'input', 'clear', 'visible-change', 'remove-tag', 'select']
      for (let [key, item] of Object.entries(this.formView)) {
        methodsArr.forEach((method) => {
          if (method in item && typeof item[method] === 'function' && item.type !== 'file') {
            if (this.getFuncParameters(item[method])?.length > 1) {
              if (item[method].toString() !== this.formItemValueChange(item[method], key).toString()) {
                item[method] = type === 'install' ? this.formItemValueChange(item[method], key) : null
              }
            }
          }
        })
        // if (!item.options && type === 'install') {
        //   this.$set(item, 'options', item.options || [])
        // }
      }
    },
    selectOptionsRow(key, row, item, allOptions) {
      // console.log('%c 第844行', 'color:red;font-size:2em')
      // console.log(key, row,item)
      this.$set(this.selectOptions, key, row)
      this.$emit('onItemSelect', this.selectOptions)
      this.$nextTick(() => {
        if (item.linkSetField) {
          // 需要关联的设置的值
          if (typeof item.linkSetField === 'string') {
            this.$set(this.formData, item.linkSetField, row[item.linkSetFieldBindKey] || row.label)
          }
          if (typeof item.linkSetField === 'object') {
            // console.log('%c 第1228行', 'color: red; font-size: 2em')
            // console.log(item)
            this.$set(this.formData, item.linkSetField.setField, row[item.linkSetField.bindField] || row.label)
          }

          if (Array.isArray(item.linkSetField)) {
            item.linkSetField.forEach((oItem) => {
              this.$set(this.formData, oItem.setField, row[oItem.bindField])
            })
          }
        }
        item.afterSelect &&
          item.afterSelect({
            value: this.formData[key],
            key,
            formView: this.formView,
            formData: this.formData,
            selectOption: row,
            allOptions
          })
      })
    },
    formItemValueChange(func, key) {
      // console.log('func', func)
      // console.log('key', key)
      // console.log('111')
      return () =>
        func(this.formData[key], {
          key,
          formView: this.formView,
          formData: this.formData,
          $index: this.tableRowIndex,
          selectOptions: this.selectOptions
        })
    },
    getAttr(e, name) {
      return e.target.attributes[name].value
    },
    documentClick() {
      this.updateKey()
    },
    updateKey(val) {
      this.$emit('update:selectedKey', val)
    },
    updateSelectedKey(key) {
      this.updateKey(this.selectedKey === key ? '' : key)
    },
    deleteSelectedKeyEvent(key) {
      this.$emit('deleteSelectedKey', key)
    },
    setStyle(item, key) {
      if (this.isDefaultLayout) {
        let style = { 'min-width': this.formItemMinWidth + 'px' }
        if (this.draggable) {
          // style = { ...style, resize: 'both', overflow: 'auto', border: '1px dotted' }
        }
        if (item.itemlabelStyle) {
          this.$nextTick(() => {
            if (this.$refs.elform) {
              let label = this.$refs.elform.$el.querySelector(`[item-key="${key}"]`).querySelector(`[for="${key}"]`)
              Object.keys(item.itemlabelStyle).forEach((name) => {
                label.style[name] = item.itemlabelStyle[name]
              })
            }
          })
        }
        if (item.itemcontentStyle) {
          this.$nextTick(() => {
            if (this.$refs.elform) {
              let label = this.$refs.elform.$el
                .querySelector(`[item-key="${key}"]`)
                .querySelector('.el-form-item__content')
              Object.keys(item.itemcontentStyle).forEach((name) => {
                label.style[name] = item.itemcontentStyle[name]
              })
            }
          })
        }

        if (item.fillRow) {
          return { 'grid-column-start': `span ${this.formColumns}`, ...style }
        }

        if (item.itemtype === 'SlotForm') {
          style['margin-bottom'] = 0
          style['grid-template-columns'] = '0 1fr'
        }

        if (item.order !== undefined) {
          style['order'] = item.order
        }

        let hasSpan = item.span && item.span >= 0 && item.span <= this.formColumns
        let hasRowspan = item.rowspan && item.rowspan > 1

        if (hasSpan || hasRowspan) {
          let spanstyle = {
            'grid-column-start':
              item.span <= 1 ? `span ${Math.max(item.span * this.formColumns, this.itemcolumns)}` : `span ${item.span}`
          }
          let rowstyle = {
            'grid-row-start': `span ${item.rowspan}`
          }
          if (hasSpan && hasRowspan) {
            return { ...spanstyle, ...rowstyle, ...style }
          }
          if (hasSpan && !hasRowspan) {
            return { ...spanstyle, ...style }
          }
          return { ...rowstyle, ...style }
        }

        return { 'grid-column-start': `span ${this.itemcolumns}`, ...style }
      }
    },
    // 设置下拉选项的值,如果直接设置在formView上会触发循环监听,所以代理一下这些值
    setSelectOptions(code, params, item) {
      // mustAssociated 必须要传参数才能查询的
      if (item.mustAssociated) {
        params = params && typeof params === 'function' ? params({ formData: this.formData }) : params
        if (!params || (params && Object.values(params).filter((i) => !!i).length === 0)) {
          this.$set(this.groupCodeOptions, code, '')
          return
        }
      }

      // console.log('query code =>', code, params, this.groupCodeOptions, this.groupCodeOptions[code])
      if (this.groupCodeOptions[code]) {
        return
      }
      return new Promise((resolve, reject) => {
        this.$commonMethods
          .getSelectData(code, params)
          .then((res) => {
            this.$set(this.groupCodeOptions, code, res || [])
            resolve(res || [])
          })
          .catch((err) => {
            this.$set(this.groupCodeOptions, code, [])
            resolve([])
          })
      })
    },
    setCheckboxMultiple(i) {
      // 代理多选的值,使可以直接返回指定类型的值,数组或者以逗号分割的字符串
      // if (this.formView[i].defaultValue) {
      //   this.$set(this.formData, i, this.formView[i].defaultValue)
      // }
      const isStringType = this.formView[i]['valueType'] && this.formView[i]['valueType'].toLowerCase() === 'string'
      this.$watch(
        function () {
          return this.formData[i]
        },
        function (newval) {
          this.$set(this.checkboxMultiple, i, newval ? (isStringType ? newval.toString().split(',') : newval) : [])
        },
        {
          immediate: true
        }
      )

      this.$watch(
        function () {
          return this.checkboxMultiple[i]
        },
        function (newval) {
          let val = isStringType ? this.checkboxMultiple[i].toString() : newval
          this.$set(this.formData, i, val)
        }
      )
    },
    /**
     * 点击全选操作
     *@param {type} 1执行全选反选操作 2 返回是否已全选的Boolean值
     */
    selmultiAll(key, type = 1, item, allOptions) {
      // console.log('%c 第1385行', 'color: red; font-size: 2em')
      // console.log(key, type, item, allOptions)
      // todo 需要处理allow-create的场景
      if (!this.formView[key].options && !this.formView[key].groupCode) return
      let linkSetField = this.formView[key].linkSetField
      let bindValueField = this.formView[key].bindValueField || 'value' || 'label'
      const arr = (this.formView[key].options || this.groupCodeOptions[this.formView[key].groupCode] || []).map(
        (i) => i[bindValueField]
      )
      const labelArr = (this.formView[key].options || this.groupCodeOptions[this.formView[key].groupCode] || []).map(
        (i) => i.label
      )
      const isStringType = this.formView[key]['valueType'] && this.formView[key]['valueType'].toLowerCase() === 'string'
      const selectedAll = isStringType
        ? this.formData[key] === arr.join(',')
        : this.formData[key]?.length === arr.length
      if (type === 1) {
        this.$set(this.formData, key, selectedAll ? (isStringType ? '' : []) : isStringType ? arr.toString() : arr)
        if (linkSetField) {
          this.$set(
            this.formData,
            linkSetField,
            selectedAll ? (isStringType ? '' : []) : isStringType ? labelArr.toString() : labelArr
          )
        }

        this.$refs.SelectMultiple && this.$refs.SelectMultiple[0]?.emitChange(this.formData[key])
        item.afterSelect &&
          item.afterSelect({
            value: this.formData[key],
            key,
            formView: this.formView,
            formData: this.formData,
            selectOption: {},
            allOptions
          })
      } else {
        return selectedAll
      }
    },
    onResize() {
      let resize = () => {
        if (!this.$refs.elform || !this.$refs.elform.$el) return
        const formWidth = window.getComputedStyle(this.$refs.elform.$el, null).getPropertyValue('width')
        this.formWidth = parseInt(formWidth)
      }
      const timer = setTimeout(() => {
        resize()
        clearTimeout(timer)
      }, 500)
    },
    dragEnd() {
      this.updateKey()
      let keysOrder = []
      this.$nextTick(() => {
        const elArr = this.$refs.elform.$el.querySelectorAll(`[item-key]`)
        for (let el of elArr) {
          keysOrder.push(el.getAttribute('item-key'))
        }
        this.$emit('keyOrderChange', keysOrder)
      })
    },
    setDeepBindValue(key, deepBindSeparator) {
      let arr = key.split(deepBindSeparator)
      if (arr.length > 0) {
        this.$watch(
          () => {
            return this.formData[key]
          },
          (val) => {
            // console.log(val)
            if (val === undefined || val === null) return
            let obj = {}
            for (let i = arr.length - 1; i >= 0; i--) {
              let field = arr[i]
              if (i === arr.length - 1) {
                obj = { [field]: val }
              } else if (i > 0) {
                obj = { [field]: obj }
              } else {
                // this.formData[field] = obj
                if (!this.formData[field] || (this.formData[field] && this.formData[field] !== obj)) {
                  this.$set(this.formData, field, obj)
                }
              }
            }
            // console.log(obj)
            // console.log(this.formData)
          },
          { immediate: true }
        )

        this.$watch(
          () => {
            // console.log(this.formData.hasOwnProperty(f))
            let f = arr[0]
            if (!this.formData.hasOwnProperty(f)) {
              this.$set(this.formData, f, {})
            }
            // console.log(this.formData.hasOwnProperty(f))
            return this.formData[f]
          },
          (val) => {
            // console.log(val)
            if (val === undefined || val === null) return
            let newval = val
            for (let i = 1; i < arr.length; i++) {
              let field = arr[i]
              if (newval) {
                newval = newval[field]
              }
            }
            // console.log(newval)
            if (newval !== this.formData[key]) {
              this.$set(this.formData, key, newval)
            }
          },
          { deep: true }
        )
      }
    },
    validate() {
      return new Promise((provide, reject) => {
        this.$refs['elform'].validate((valid) => {
          console.log(valid)
          provide(valid)
        })
      })
    },
    validateForm() {
      return new Promise((resolve, reject) => {
        this.$refs['elform'].validate(async (valid, error) => {
          // console.log('validateForm =>', valid, error)
          if (valid) {
            let flag = true
            if (this.$refs['SlotForm']) {
              for await (let deepForm of this.$refs['SlotForm']) {
                await deepForm.$refs['elform'].validate((valid2) => {
                  if (!valid2) {
                    flag = false
                  }
                })
              }
              resolve(flag)
            } else {
              resolve(true)
            }
          } else {
            resolve(false)
          }
        })
      })
    },
    getSelectOptions(item) {
      // 需要优化取值次数
      // console.log('%c 第1223行', 'color:red;font-size:2em')
      // console.log(item.groupCode, this.groupCodeOptions, this.groupCodeOptions[item.groupCode])
      // console.log(item)
      if (item.groupCode) {
        if (!this.groupCodeOptions[item.groupCode]) {
          this.setSelectOptions(item.groupCode, item.params, item).then((res) => {
            // setTimeout(() => {
            //   this.getSelectOptions(item)
            // }, 500)
          })
        } else {
          return this.groupCodeOptions[item.groupCode]
        }
      } else {
        return item.options
      }
    },
    resetForm() {
      this.$refs.elform.resetFields()
    },
    clearValidate() {
      this.$refs.elform.clearValidate()
    },
    setFieldWatch(key, item) {
      // 如果在里面执行了给formView 设置值,将导致死循环
      this.$watch(
        () => {
          return this.formData[key]
        },
        (val) => {
          item.watch({ value: val, formData: this.formData })
        },
        { immediate: true, deep: true }
      )
    }
  },

  computed: {
    // getLabelAlign() {
    //   return { 'label-position-top': this.labelPosition === 'top' }
    // },
    ...mapGetters(['sysFormConfig']),
    formLabelWidth() {
      return this.labelPosition === 'top' ? '' : parseInt(this.labelWidth) + 'px'
    },
    hiddenLabelClass() {
      return {
        hiddenLabelClass: parseInt(this.labelWidth) === 0 || this.hiddenLabel
      }
    },
    // rules() {
    // return Object.keys(this.formView).reduce((prev, curr) => {
    //   let item = this.formView[curr]
    //   const requiredRules = {
    //     required: true,
    //     message: `${item.itemlabel || ''}不能为空`,
    //     trigger: 'blur'
    //   }
    //   if (item.rules && item.rules.length > 0) {
    //     prev[curr] = [...prev[curr], ...item.rules]
    //   } else {
    //     prev[curr] = []
    //   }

    //   if (item.required) {
    //     // if (item.rules && item.rules.length > 0) {
    //     prev[curr] = [...prev[curr], requiredRules]
    //     // } else {
    //     //   // 需要根据类型判断提示内容
    //     //   prev[curr] = [requiredRules]
    //     // }
    //   } else {
    //     // this.$refs.elform?.clearValidate(curr)//需要loader支持这种语法
    //     this.$refs.elform && this.$refs.elform.clearValidate(curr)
    //   }

    //   return prev
    // }, {})

    // },
    isDefaultLayout() {
      return this.layoutClass === 'default-layout'
    },
    styleObj() {
      // grid-template-columns: repeat(auto-fill, 320px);
      if (!this.isDefaultLayout) return
      let style = {
        'grid-template-columns': `repeat(${this.formColumns},1fr)`
      }
      const columnGap = this.$attrs['columnGap'] ?? this.columnGap
      const rowGap = this.$attrs['rowGap'] ?? this.rowGap
      if (columnGap) {
        style['column-gap'] = columnGap + 'px'
      }
      if (rowGap) {
        style['row-gap'] = rowGap + 'px'
      }

      return style
    },
    itemcolumns: {
      get() {
        if (!this.isDefaultLayout) return
        if (this.autoLayout) {
          let columnsNum = this.formColumns / this.columns
          if (this.formWidth && this.formWidth < columnsNum * this.formItemMinWidth) {
            return this.formColumns / Math.floor(this.formWidth / this.formItemMinWidth)
          } else {
            return this.columns
          }
        }
        // console.log('%c 第1646行', 'color: red; font-size: 2em')
        // console.log(this.isAutoComputedColumns && this.columns === 12)
        // 如果自动分配columuns,那么表单元素小于等于4个,默认一行一列,否则一行两列
        if (this.isAutoComputedColumns && this.columns === 12) {
          return Object.keys(this.formView).filter((i) => !this.formView[i].hidden).length > 4 ? 6 : 12
        }
        return this.columns
      },
      set(val) {
        // this.$emit('update:columns', val)
      }
    }
  },
  beforeUpdate() {
    // label 文字超出后换行并修改行高
    // let el = this.$refs.elform && this.$refs.elform.$el
    // if (el) {
    //   for (let [key, item] of Object.entries(this.formView)) {
    //     if (item.itemlabel && item.itemlabel.length > 4) {
    //       let label = el.querySelector(`[item-key="${key}"]`)?.querySelector(`[for="${key}"]`)
    //       if (label && label.scrollWidth > label.clientWidth) {
    //         console.log(item.itemlabel)
    //         label.style['line-height'] = '16px'
    //         label.style['white-space'] = 'break-spaces'
    //         label.style['ovferflow'] = 'hidden'
    //       }
    //     }
    //   }
    // }
  },
  updated() {
    // label 文字超出后换行并修改行高
    let el = this.$refs.elform && this.$refs.elform.$el
    if (el) {
      for (let [key, item] of Object.entries(this.formView)) {
        if (item.itemlabel && item.itemlabel.length > 4) {
          let label = el.querySelector(`[item-key="${key}"]`)?.querySelector(`[for="${key}"]`)
          if (label && label.scrollWidth > label.clientWidth) {
            // console.log(item.itemlabel)
            label.style['line-height'] = '16px'
            label.style['white-space'] = 'break-spaces'
            label.style['overflow'] = 'hidden'
          }
        }
      }
    }
  },
  beforeDestroy() {
    this.rewriteEventMethods('uninstall')
    window.removeEventListener('resize', this.onResize)
    document.removeEventListener('click', this.documentClick)
    if (this.focusElement) {
      this.focusElement.removeEventListener('blur', this.elementBlur)
    }
    this.focusElement = null
  }
}
</script>
<style lang="scss" scoped>
.default-layout {
  display: grid;
  column-gap: 3px;
  row-gap: 6px;
  // grid-template-columns: repeat(12, 1fr);
  > .el-form-item {
    display: grid;
    grid-template-columns: auto auto 1fr;
    grid-auto-flow: column dense;
    margin-bottom: 0px;
    // min-width: 250px;
    // grid-column: span 3;
    ::v-deep .el-form-item__label {
      // line-height: 16px;
      // display: grid;
      // align-items: center;
      // grid-auto-flow: column;
      // justify-content: end;
      white-space: nowrap;
      overflow: hidden;
      padding-right: 6px;
      // white-space: pre-wrap;
      // word-wrap: break-word;
      // line-height: 1;
      // display: flex;
      // justify-content: flex-end;
      // align-items: center;
      // text-overflow: ellipsis;
    }
    ::v-deep .el-input__inner {
      padding: 0 6px;
    }
    ::v-deep .el-icon-date {
      display: none !important;
    }

    ::v-deep .el-form-item__content {
      height: max-content;
      margin-left: 0px !important;
      // .el-select,
      // .el-date-editor {
      //   width: 100%;
      // }
      > div {
        width: 100%;
      }
      .el-input--small .el-input__icon {
        line-height: 30px;
      }
      .el-date-editor .el-range-separator {
        padding: 0;
      }
      .el-date-editor .el-icon-date {
        display: none !important;
      }
      .el-date-editor .el-icon-time {
        display: none !important;
      }
    }
  }
  &.el-form--label-top {
    column-gap: 6px;
    ::v-deep > .el-form-item {
      display: grid;
      grid-template-columns: 1fr;
      grid-template-rows: auto auto 1fr auto;
      grid-auto-flow: row dense;
      margin-bottom: 14px;
      .el-form-item__label {
        justify-content: flex-start;
        text-align: left;
        padding: 0;
      }
    }
  }
  &.el-form--label-left {
    column-gap: 6px;
  }
}

::v-deep.el-form-item.contentOverHidden {
  .el-form-item__content {
    overflow: hidden;
  }
}

.tableForm {
  ::v-deep .el-form-item__label {
    padding-right: 0 !important;
  }

  ::v-deep .el-form-item {
    align-items: center;
  }
}
.hiddenLabelClass {
  ::v-deep > .el-form-item__label {
    color: transparent;
    height: 0 !important;
    padding: 0;
    // transform: translateX(-8px);
    // position: absolute;
    width: 0 !important;
  }
}
.slotform {
}
.ghost {
  // border: 1px solid #409eff;
  box-shadow: 0px 0px 3px 3px orange !important;
  border-radius: 2px;
}
.selectedFormItem {
  box-shadow: 0px 0px 3px 3px #409eff;
  border-radius: 2px;
}

.deleteSelectedKey {
  position: absolute;
  right: 0;
  top: 0;
  z-index: 9999;
}

.el-select-dropdown__item.optionBtnType {
  display: inline-flex;
  & ~ li {
    display: inline-flex;
  }
}
.el-input.is-disabled .el-input__inner {
  color: #666;
}
::v-deep .el-input.is-disabled .el-input-group__append {
  pointer-events: none;
}

::v-deep .el-input .el-input__suffix {
  display: flex;
  align-items: center;
}

// ::v-deep .my-el-upload {
//   display: flex;
//   width: 100px;
//   align-items: center;
//   flex-direction: row-reverse;
//   .el-upload-list {
//     line-height: auto;
//     margin-top: 0px;
//     max-width: 125px;
//   }
//   .el-upload-list__item {
//     margin-top: 0px;
//   }
//   .el-upload-list__item-name {
//     margin-right: 4px;
//   }
// }
.itemIsDisabled {
  cursor: not-allowed;
  ::v-deep * {
    pointer-events: none;
    color: #606266;
  }
  ::v-deep .el-form-item__content input {
    background-color: #f5f7fa;
    border-color: #e4e7ed;
    color: #c0c4cc;
    cursor: not-allowed;
  }
}

//.el-form-item[readonly] {
//  pointer-events: none;
//}

.formInLuckysheet {
  // display: grid;
  column-gap: 0px;
  row-gap: 0px;
  // grid-template-columns: repeat(12, 1fr);
  > .el-form-item {
    display: grid;
    // grid-template-columns: auto auto 1fr;
    grid-template-columns: 0 1fr;
    grid-auto-flow: column dense;
    margin-bottom: 0px;

    ::v-deep .el-form-item__label {
      white-space: nowrap;
      overflow: auto;
      padding-right: 0px;
    }
    ::v-deep .el-input__inner {
      padding: 0 3px;
      border: none;
      height: 28px;
      line-height: 28px;
      width: 100%;
    }

    ::v-deep .el-icon-date {
      display: none !important;
    }
    ::v-deep .el-icon-time {
      display: none !important;
    }
    ::v-deep .el-form-item__content {
      line-height: 24px;
      margin-left: 0px !important;
      background: #fff;
      overflow: hidden;
      > div {
        width: 100%;
      }
      .el-input__suffix {
        margin-right: -6px;
      }
      .el-input--small .el-input__icon {
        // line-height: 20px;
      }
      .el-date-editor .el-range-separator {
        padding: 0;
      }
    }
  }
  // &.el-form--label-top {
  //   column-gap: 6px;
  //   ::v-deep > .el-form-item {
  //     display: grid;
  //     grid-template-columns: 1fr;
  //     grid-template-rows: auto auto 1fr auto;
  //     grid-auto-flow: row dense;
  //     margin-bottom: 14px;
  //     .el-form-item__label {
  //       text-align: left;
  //       padding: 0;
  //     }
  //   }
  // }
  // &.el-form--label-left {
  //   column-gap: 6px;
  // }
}

.dialogSelect {
  /deep/.el-input-group__append {
    padding: 0 5px !important;
  }
}
</style>
<style lang="scss">
.el-select-dropdown.el-popper.is-multiple {
  max-width: 400px;
}
.el-autocomplete-suggestion {
  min-width: 250px;
}

.clickable {
  color: #017aff;
}
</style>

posted @ 2024-09-24 14:13  一bottle陈  阅读(15)  评论(0编辑  收藏  举报