<template>
  <div class="ezj-form-pane">
    <template v-if="form.hint">
      <div class="ezj-form-pane__hint" v-html="form.hint"></div>
    </template>
    <!-- 多个表单 -->
    <template v-if="form.hasAdd">
      <template v-if="isMultiple">
        <template v-for="(item, index) in model">
          <div class="ejz-form-pane_group" :key="index">
            <div class="remove" @click="handleRemove(index)">
              <i class="el-icon-close"></i>
            </div>
            <form-form
              :options="form.options"
              :model="item"
              :items="form.items"
              :hasButton="false"
              ref="form"
            ></form-form>
          </div>
        </template>
        <el-button @click="handleAdd">增加一项</el-button>
        <el-button type="primary" @click="handleSubmit">保存</el-button>
      </template>
    </template>

    <!-- 一个表单 -->
    <template v-else>
      <form-form
        :options="form.options"
        :model="model"
        :items="form.items"
        @onSubmit="onSubmit"
        :hasButton="form.hasButton"
        ref="form"
      ></form-form>
    </template>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  name: 'EzjFormPane',
  components: {},
  props: {
    title: String,
    get: Object,
    update: Object,
    form: {
      type: Object,
      default() {
        return {}
      }
    }
  },
  data() {
    let model =
      this.form.model ||
      (this.form.hasAdd ? [Object.assign({}, this.form.defaultModel)] : {})
    return {
      model
    }
  },
  computed: {
    isMultiple() {
      return Array.isArray(this.model)
    }
  },
  methods: {
    init() {
      this.get && this.getData()
    },
    // 获取
    getData() {
      let {
        action,
        headers = {},
        data = {},
        beforeRequest,
        callback
      } = this.get
      if (beforeRequest) {
        data = beforeRequest(data)
      }
      axios
        .get(action, { params: data, headers })
        .then(res => {
          let { data } = res
          // 默认数据设置
          if (this.form.hasAdd && Array.isArray(data) && !data.length) {
            data.push(Object.assign({}, this.form.defaultModel))
          }
          if (callback) {
            data = callback(data)
          }
          this.model = data
        })
        .catch(error => {
          if (error.response) {
            this.$emit('error', error.response.data)
          } else {
            throw error
          }
        })
    },
    // 更新
    updateData(formData) {
      let {
        action,
        headers = {},
        data = {},
        beforeRequest,
        callback
      } = this.update
      if (beforeRequest) {
        formData = beforeRequest(formData)
      }
      // 自定义数据和表单数据合并
      formData = Object.assign({}, formData, data)
      // 自定义header和默认header合并
      headers = Object.assign(
        { 'Content-Type': 'application/x-www-form-urlencoded' },
        headers
      )
      // 表单数据序列化
      if (headers['Content-Type'] === 'application/x-www-form-urlencoded') {
        let params = new URLSearchParams()
        for (let key in formData) {
          let value = formData[key]
          params.append(
            key,
            typeof value === 'object' ? JSON.stringify(value) : value
          )
        }
        formData = params
      }
      axios
        .post(action, formData, { headers })
        .then(res => {
          let { data } = res
          callback && callback(data)
          this.$emit('success', data)
        })
        .catch(error => {
          if (error.response) {
            this.$emit('error', error.response.data)
          } else {
            throw error
          }
        })
    },
    onSubmit(data) {
      this.updateData(data)
    },
    // 新增表单
    handleAdd() {
      this.model.push(Object.assign({}, this.form.defaultModel))
    },
    // 删除表单
    handleRemove(index) {
      this.model.splice(index, 1)
    },
    // 提交
    handleSubmit() {
      const formCompoents = this.$refs.form
      let allPromise = formCompoents.map(form => form.validate())
      Promise.all(allPromise).then(() => {
        this.updateData(this.model)
      })
    }
  },
  beforeMount() {
    this.init()
  }
}
</script>

<style lang="scss">
.ezj-form-pane__hint {
  margin-bottom: 20px;
}
.ejz-form-pane_group {
  position: relative;
  margin-bottom: 20px;
  padding: 15px;
  border: 2px solid #c41230;
  border-radius: 10px;

  .remove {
    position: absolute;
    top: -12px;
    right: -12px;
    z-index: 999;
    font-size: 20px;
    line-height: 24px;
    text-align: center;
    color: #fff;
    cursor: pointer;
    background-color: #c41230;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    overflow: hidden;
  }
}
</style>
