<template>
  <component
    :is="panelIsFlexLayout ? 'div' : 'el-col'"
    :class="[
      'search-field__container',
      panelIsFlexLayout ? 'search-field__container-flex' : '',
    ]"
    :style="containerStyle"
    :span="colSpanVal"
  >
    <div
      v-if="!hideLabel"
      :style="{ width: finalLabelWidth + 'px' }"
      class="field-label-panel"
      :class="{ 'is-align-right': isAlignRight, 'is-required': isRequired }"
    >
      <label v-if="label" v-ellipsis :title="label" class="search-field-label">
        {{ label }}
      </label>
    </div>
    <div
      :style="{ width: `calc(100% - ${inputDivJudgeWidth}px)` }"
      class="field-input-panel"
      :class="{ 'unset-width': isAlignRight }"
    >
      <template v-if="!hasDefaultSlot">
        <ht-input
          v-if="fieldType == 'text'"
          v-model="data"
          :placeholder="placeholder"
          :display-style="finalDisplayStyle"
          :prefix-icon="prefixIcon"
          :suffix-icon="suffixIcon"
          :custom-input-writeable="true"
          :type="type"
          @keydown.enter.native="textInputEnter"
        ></ht-input>
        <ht-date
          v-if="fieldType == 'date' || fieldType == 'datetime'"
          v-model="data"
          :type="fieldType"
          :value-format="valueFormat"
          :format="valueFormat"
          :placeholder="placeholder"
          :default-time="defaultTime"
          :display-style="finalDisplayStyle"
          :custom-input-writeable="true"
        />
        <ht-date-picker
          v-if="['datetimerange', 'daterange'].includes(fieldType)"
          v-model="data"
          :type="fieldType"
          :value-format="valueFormat"
          :unlink-panels="unlinkPanels"
          :picker-options="pickerOptions"
          :format="valueFormat"
          :custom-input-writeable="true"
        />
        <div v-if="fieldType == 'select'">
          <ht-select
            v-if="dialogConfig.choiceType == 'static'"
            v-model="data"
            :placeholder="placeholder"
            :options="dialogConfig.selectData"
            :props="props"
            :display-style="finalDisplayStyle"
            :custom-input-writeable="true"
          ></ht-select>
          <ht-select
            v-else
            v-model="data"
            :ganged="{
              alias: dialogConfig.customQuery.alias,
              valueBind: dialogConfig.customQuery.valueBind,
              noInit: '',
              labelBind: dialogConfig.customQuery.labelBind,
              gangedBind: '{}',
              bind: dialogConfig.bind,
            }"
            :multiple="false"
            :filterable="false"
            :allow-create="false"
            :selectlist="[]"
            :custom-input-writeable="true"
          ></ht-select>
        </div>
        <ht-custom-dialog
          v-if="fieldType == 'dialog'"
          v-model="data"
          :custdialog="customDialogConfig"
          :model-name="'customDialog'"
          permission="w"
          :custom-input-writeable="true"
        ></ht-custom-dialog>
        <ht-user-selector-input
          v-if="fieldType == 'user'"
          v-model="data"
          :select-current="dialogConfig.selectCurrent"
          :single="dialogConfig.isSingle"
          :append-to-body="true"
          :config="selectorConfig"
          :custom-input-writeable="true"
        />
        <ht-org-selector-input
          v-if="fieldType == 'org'"
          v-model="data"
          :select-current="dialogConfig.selectCurrent"
          :single="dialogConfig.isSingle"
          :append-to-body="true"
          :config="selectorConfig"
          :custom-input-writeable="true"
        />
        <ht-post-selector-input
          v-if="fieldType == 'post'"
          v-model="data"
          :append-to-body="true"
          :single="dialogConfig.isSingle"
          :config="selectorConfig"
          :custom-input-writeable="true"
        />
        <ht-role-selector-input
          v-if="fieldType == 'role'"
          v-model="data"
          :append-to-body="true"
          :single="dialogConfig.isSingle"
          :config="selectorConfig"
          :custom-input-writeable="true"
        />
        <ht-job-selector-input
          v-if="fieldType == 'job'"
          v-model="data"
          :append-to-body="true"
          :single="dialogConfig.isSingle"
          :config="selectorConfig"
          :custom-input-writeable="true"
        />
        <ht-dimension-selector-input
          v-if="fieldType == 'dem'"
          v-model="data"
          :append-to-body="true"
          :single="dialogConfig.isSingle"
          :config="selectorConfig"
          :custom-input-writeable="true"
        />
        <div v-if="fieldType == 'radio'">
          <ht-radio
            v-if="dialogConfig.choiceType == 'static'"
            v-model="data"
            :options="dialogConfig.selectData"
            :props="props"
            :display-style="finalDisplayStyle"
            :custom-input-writeable="true"
          ></ht-radio>
          <ht-radio
            v-else
            v-model="data"
            :ganged="{
              alias: dialogConfig.customQuery.alias,
              valueBind: dialogConfig.customQuery.valueBind,
              noInit: '',
              labelBind: dialogConfig.customQuery.labelBind,
              gangedBind: '{}',
              bind: dialogConfig.bind,
            }"
            :custom-input-writeable="true"
          ></ht-radio>
        </div>
        <div v-if="fieldType == 'checkbox'">
          <ht-checkbox
            v-if="dialogConfig.choiceType == 'static'"
            v-model="data"
            :options="dialogConfig.selectData"
            :props="props"
            :display-style="finalDisplayStyle"
            :custom-input-writeable="true"
          ></ht-checkbox>
          <ht-checkbox
            v-else
            v-model="data"
            :ganged="{
              alias: dialogConfig.customQuery.alias,
              valueBind: dialogConfig.customQuery.valueBind,
              noInit: '',
              labelBind: dialogConfig.customQuery.labelBind,
              gangedBind: '{}',
              bind: dialogConfig.bind,
            }"
            :custom-input-writeable="true"
          ></ht-checkbox>
        </div>
        <ht-dictionary
          v-if="fieldType == 'dictionary'"
          v-model="data"
          :dickey="dialogConfig.parameter.dic"
          :custom-input-writeable="true"
        />
      </template>
      <slot v-else></slot>
    </div>
  </component>
</template>
<script>
  /* eslint-disable */
  import emitter from '@/mixins/emitter.js'
  import CustomQuery from '@/services/CustomQuery.js'

  export default {
    name: 'HtTableSearchField',
    componentName: 'HtTableSearchField',
    mixins: [emitter],
    props: {
      value: [String, Number, Boolean, Object, Array],
      defaultTime: {
        type: String,
        default: '00:00:00',
      },
      unlinkPanels: {
        type: Boolean,
        default: true,
      },
      isAlignRight: {
        type: Boolean,
        default: false,
      },
      //必填校验的星号
      isRequired: {
        type: Boolean,
        default: false,
      },
      span: {
        type: Number,
        default: 0,
      },
      prop: {
        type: String,
        required: true,
      },
      props: {
        type: Object,
        default: null,
      },
      operation: {
        type: String,
        default: 'LIKE',
        validator: (value) =>
          [
            'EQUAL',
            'EQUAL_IGNORE_CASE',
            'LESS',
            'GREAT',
            'LESS_EQUAL',
            'GREAT_EQUAL',
            'NOT_EQUAL',
            'LIKE',
            'LEFT_LIKE',
            'RIGHT_LIKE',
            'IS_NULL',
            'NOTNULL',
            'IN',
            'BETWEEN',
          ].indexOf(value) != -1,
      },
      relation: {
        type: String,
        default: 'AND',
        validator: (value) => ['AND', 'OR'].indexOf(value) != -1,
      },
      label: String,
      type: {
        type: String,
        default: 'text',
        validator: (value) =>
          [
            'text',
            'date',
            'number',
            'daterange',
            'datetimerange',
            'select',
          ].indexOf(value) != -1,
      },
      options: Array,
      placeholder: {
        type: String,
        default() {
          return `请输入${this.label}`
        },
      },
      valueFormat: {
        type: String,
        default: 'yyyy-MM-dd HH:mm:ss',
      },
      hideLabel: {
        type: Boolean,
        default: false,
      },
      labelWidth: {
        type: Number,
        default: 0,
      },
      width: {
        type: Number,
        default: 0,
      },
      prefixIcon: String,
      suffixIcon: String,
      displayStyle: String,
      enterToSearch: {
        type: Boolean,
        default: false,
      },
      config: String,
    },
    data() {
      return {
        marginWidth: 48,
        data: null,
        colspan: 8,
        panelDisplayStyle: null,
        panelLabelWidth: 105,
        panelIsFlexLayout: false, //面板是否流式布局
        pickerOptions: {
          shortcuts: [
            {
              text: '最近一周',
              onClick(picker) {
                const end = new Date()
                const start = new Date()
                start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
                picker.$emit('pick', [start, end])
              },
            },
            {
              text: '最近一个月',
              onClick(picker) {
                const end = new Date()
                const start = new Date()
                start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
                picker.$emit('pick', [start, end])
              },
            },
            {
              text: '最近三个月',
              onClick(picker) {
                const end = new Date()
                const start = new Date()
                start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
                picker.$emit('pick', [start, end])
              },
            },
          ],
        },
        fieldType: '',
        dialogConfig: {},
        selectOptions: [],
        customDialogConfig: {},
        selectorConfig: {},
      }
    },
    computed: {
      hasDefaultSlot() {
        return this.$slots.default && this.$slots.default.length > 0
      },
      colSpanVal() {
        return this.span > 0 ? this.span : this.colspan
      },
      finalLabelWidth() {
        return this.labelWidth > 0 ? this.labelWidth : this.panelLabelWidth
      },
      inputDivJudgeWidth() {
        return this.hideLabel
          ? 0
          : this.finalLabelWidth +
              (this.panelIsFlexLayout ? 0 : this.marginWidth)
      },
      containerStyle() {
        return this.width > 0 ? { width: `${this.width}px` } : ''
      },
      finalDisplayStyle() {
        const partDisplayStyle =
          this.span == 0
            ? this.displayStyle
            : this.displayStyle
            ? this.displayStyle
            : 'block'
        return partDisplayStyle || this.panelDisplayStyle
      },
    },
    watch: {
      data: function (newVal) {
        this.handleInputChange(newVal)
      },
      value: function (newVal) {
        this.handleInputChange(newVal)
      },
    },
    created() {
      this.$on('change-TableSearchField-data', (val) => {
        if (!this.hasDefaultSlot && this.prop == val.prop) {
          this.data = val.value
        }
      })
      this.$on('input-reset', () => {
        this.data = null
      })
      this.$on('panel-props', (m, n, o, d) => {
        this.panelLabelWidth = m
        this.colspan = n
        this.panelIsFlexLayout = o
        this.panelDisplayStyle = d
      })
      if (this.type) {
        this.fieldType = this.type
      }
      if (this.options) {
        this.selectOptions = this.options
      }
      //默认值
      this.value && this.$set(this, 'data', this.value)
      this.handDialog()
    },
    mounted() {
      // 挂载完成后，将本实例注册到高级搜索面板对应的搜索条件列表中
      this.dispatch('HtTableSearchPanel', 'field-loaded', [this])
      window.addEventListener('resize', this.handleResize())
    },
    beforeDestroy() {
      window.removeEventListener('resize', this.handleResize())
    },
    methods: {
      handleResize() {
        this.marginWidth = window.innerWidth > 1440 ? 48 : 24
      },
      handleInputChange(inputVal) {
        this.dispatch('HtTableSearchPanel', 'input-change', [
          {
            value: inputVal,
            operation: this.operation,
            relation: this.relation,
          },
          this.prop,
        ])
      },
      textInputEnter() {
        this.enterToSearch &&
          this.dispatch('HtTableSearchPanel', 'search', [this])
      },
      //处理对话框数据
      handDialog() {
        if (this.config) {
          this.dialogConfig = JSON.parse(this.config)
          this.fieldType = this.dialogConfig.type
          if (
            this.dialogConfig.type == 'select' ||
            this.dialogConfig.type == 'radio' ||
            this.dialogConfig.type == 'checkbox'
          ) {
            this.selectOptions = this.dialogConfig.selectData
            if (this.dialogConfig.choiceType == 'dynamic') {
              let customQuery = this.dialogConfig.customQuery
              let params = {}
              let dynamicOptions = []
              setTimeout(() => {
                CustomQuery.load(customQuery.alias, params).then((data) => {
                  if (data && data.length > 0) {
                    //去重防止重复值报错
                    const map = new Map()
                    const newArr = data.filter(
                      (key) =>
                        !map.has(key[customQuery.valueBind]) &&
                        map.set(key[customQuery.valueBind], 1)
                    )
                    newArr.forEach((item) => {
                      let value = item[customQuery.valueBind]
                      let name = item[customQuery.labelBind]
                      dynamicOptions.push({
                        key: value,
                        value: name,
                      })
                    })
                    this.selectOptions = dynamicOptions
                  }
                })
              }, 0)
            }
          } else if (this.dialogConfig.type == 'dialog') {
            //构建对话框所需格式
            let mappingConfig = []
            for (let key in this.dialogConfig.parameter) {
              if (this.dialogConfig.parameter[key]) {
                mappingConfig.push({
                  from: key,
                  target: [this.dialogConfig.parameter[key]],
                })
              }
            }
            let item = {
              name: this.dialogConfig.dialogConfig.btnName || '请选择',
              custDialog: {
                selectNum: 1,
                conditions: '',
                custQueryJson: '',
                alias: this.dialogConfig.dialogConfig.alias,
                mappingConf: mappingConfig,
                type: 'custDialog',
              },
              resultField: this.dialogConfig.dialogConfig.resultField,
              allowInput: false,
            }
            this.customDialogConfig = item
          }
          //把条件字段映射写入到model中,key是字段名称。所以映射关系不能重复，重复则覆盖
          if (this.dialogConfig.parameter) {
            for (let key in this.dialogConfig.parameter) {
              if (this.dialogConfig.parameter[key]) {
                this.$set(
                  this.selectorConfig,
                  key,
                  `selectorConfig.${this.dialogConfig.parameter[key]}`
                )
              }
            }
          }
        }
      },
    },
  }
</script>
<style lang="scss" scoped>
  .search-field__container {
    margin-bottom: 16px;
    height: 32px;
    display: inline-flex;
    align-items: center;
  }

  .search-field__container-flex {
    margin-right: 10px;
    float: left;
  }

  .field-label-panel,
  .field-input-panel {
    display: inline-block;
  }
  .field-label-panel {
    text-align: right;
    padding-right: 12px;
  }
  .is-align-right {
    text-align: right;
    width: unset !important;
  }
  .unset-width {
    width: unset !important;
    max-width: unset !important;
    margin-right: 20px;
  }
  .field-input-panel {
    max-width: 500px;
    ::v-deep .search-item {
      width: 100%;
    }
    ::v-deep.inputs.ht-form-inputs__inline {
      width: 100%;
    }
  }

  .field-input-panel > .inputs {
    display: block;
  }

  .field-input-panel > .inputs ::v-deep .el-input__inner {
    border-radius: 0;
  }

  .search-field-label {
    display: inline-block;
    max-width: calc(100% - 10px);
    line-height: 110%;
    font-size: 14px;
    &::after {
      content: ':';
    }
  }
  ::v-deep .el-date-editor.el-input {
    width: 100%;
  }
  ::v-deep {
    .el-date-editor--daterange,
    .el-date-editor--datetimerange {
      width: 100% !important;
    }
    .el-radio-group,
    .el-checkbox-group {
      padding: 4px 0;
      width: 100%;
      text-align: left;
    }
  }
</style>
