<!--
 * @Author: wlo_o
 * @Date: 2022-02-09 11:16:54
 * @LastEditors: Jone
 * @LastEditTime: 2022-07-04 15:56:50
 * @FilePath: /frontend/lib/components/MdSetForm.vue
 * @Description: 数据集表单 用于数据集新增、修改
 *
 * 为了降低操作难度，需要先保存（有主键）后才能对子集、标签分类
 *
 * Copyright (c) 2022 by 青岛百洋智能科技股份有限公司, All Rights Reserved.
-->
<template>
  <div class="oecp-md-set-form">
    <el-row
      v-if="showHeader||showGoBack"
      class="oecp-component-header"
    >
      <el-col :span="12">
        <template v-if="showGoBack">
          <el-page-header
            @back="goBack"
            title=''
          >
            <div slot="content">
              <template v-if="!!$slots.title">
                <slot name="title"></slot>
              </template>
              <div
                v-else-if="!!title"
                class="title-style"
              >{{title}}</div>
              <div v-else>&nbsp;</div>
            </div>
          </el-page-header>
        </template>
        <template v-else>
          <template v-if="!!$slots.title">
            <slot name="title"></slot>
          </template>
          <div v-else-if="!!title">{{title}}</div>
          <div v-else>&nbsp;</div>
        </template>
      </el-col>
      <el-col
        v-show="editable&&showSaveBtn"
        :span="12"
      >
        <el-row
          type="flex"
          justify="end"
        >
          <el-button
            v-oecp-auth:[{type}]="'setForm.save'"
            :loading="loading"
            class="addBtn"
            :icon="stateId?'el-icon-edit':'el-icon-plus'"
            @click="handleSave()"
            type="primary"
            size="medium"
          >
            {{submitBtnText}}
          </el-button>
        </el-row>
      </el-col>
      <el-divider
        v-if="showHeader||showGoBack"
        class="oecp-divider"
      />
    </el-row>
    <div
      v-loading="loading"
      class="mt20"
    >
      <el-row>
        <ele-form
          v-bind="formConfig"
          v-model="formData"
          ref="form"
        />
      </el-row>
      <el-row v-if="extFormConfig">
        <ele-form
          v-bind="extFormConfig"
          v-model="extData"
          ref="ext"
        />
      </el-row>
    </div>
    <el-row v-if="showSubset&&stateParentId==='0'">
      <md-set-subset-list
        :parentInfo="{...formData,id:stateId}"
        :editable="editable"
        :showAddSubset="stateParentId==='0'"
        :type="type"
        :disabled="!stateId"
        class="mt20"
      >
        <h4
          slot="title"
          class="tag-style"
        >该数据集包含的子集</h4>
      </md-set-subset-list>
    </el-row>
    <el-row v-if="showElement">
      <md-set-element-list
        :id="stateId"
        :type="type"
        :editable="editable"
        :showSubsetElement="stateParentId==='0'"
        :showAddModule="showAddModule"
        :showImport="false"
        :allowDelete="formData.isSys!='0'"
      >
        <h4
          slot="title"
          class="tag-style"
        >该数据集包含的数据元</h4>
      </md-set-element-list>
    </el-row>
    <el-row v-if="showCategory">
      <md-category
        :disabled="!editable||!stateId"
        :displayType="editable?'input':'tag'"
        :showExpand="true"
        :values="categoryIds"
        @click="handleTagClick"
        :type="type"
      >
        <h4
          class="tag-style"
          slot="title"
          style="margin: 0"
        >添加标签</h4>
      </md-category>
    </el-row>
  </div>
</template>
<script>
import { fetchApi } from '../common/apis'
import pick from 'lodash/pick'
import get from 'lodash/get'
import isObject from 'lodash/isObject'
import isArray from 'lodash/isArray'
import OptionsMixin from '../mixins/OptionsMixin'
import RouterMixin from '../mixins/RouterMixin'
import FormMixin from '../mixins/FormMixin'
import EventMixin from '../mixins/EventMixin'

export default {
  mixins: [OptionsMixin, RouterMixin, FormMixin, EventMixin],
  props: {
    parentId: { type: [String, null], default: null }, // 父级主键
    showSubset: { type: Boolean, default: false }, // 显示子集合
    showElement: { type: Boolean, default: false }, // 显示数据元
    showCategory: { type: Boolean, default: false }, // 显示分类标签
    showImport: { type: Boolean, default: false }, // 显示导入
    showAddModule: { type: Boolean, default: false }, // 子集显示添加模块
  },
  computed: {
    submitBtnText: function () {
      return '保存' // this.stateId ? '保存' : '保存'
    },
  },
  watch: {
    id(id) {
      this.stateId = id
    },
    stateId(id) {
      this.loadData()
    },
    parentId(id) {
      this.stateParentId = id
    },
  },
  data() {
    return {
      stateParentId: this.parentId,
    }
  },
  methods: {
    updateFormConfig() {
      let { stateParentId: parentId } = this
      let { defaultFormConfig } = this
      let bol = parentId === '0' || !parentId
      let formConfig = {
        ...defaultFormConfig,
        formDesc: {
          name: { type: 'input', label: '名称', required: true },
          code: { type: 'input', label: '编码', required: true, attrs: { readonly: true }, vif: data => !!data.id },
          internalCode: { type: 'input', label: '内部标识符', required: true, vif: () => this.type === '3' }, // 暂时不要内部标识符},
          sourceCode: { type: 'text', label: '来源标识符', attrs: { readonly: true }, vif: data => !!data.id, displayFormatter: v => (!v ? '——————' : v) },
          ...(bol ? { sourceFileName: { type: 'input', label: '来源文件名' }, sourceFileCode: { type: 'input', label: '来源文件编码' } } : {}),
          keyword: { type: 'input', label: '关键词' },
        },
        order: ['name', 'code', 'internalCode', 'sourceCode', ...(bol ? ['sourceFileCode', 'sourceFileName'] : []), 'keyword'],
      }
      let filterFormConfig =
        get(this, '$OecpMetaDataConfig.filterFormConfig') ||
        function (params) {
          return params
        }
      formConfig = filterFormConfig(formConfig, this.type)
      this.formConfig = formConfig
    },
    clearData() {
      this.formData = {}
      this.extData = {}
      this.extList = []
      this.categoryIds = []
      let mainform = get(this, '$refs.form')
      let extForm = get(this, '$refs.ext')
      mainform && mainform.resetForm() // 规避dom未初始化调用时报错
      extForm && extForm.resetForm() // 规避dom未初始化调用时报错
    },
    loadFormData() {
      let that = this
      return fetchApi
        .call(this, '/set/find', { id: this.stateId })
        .then(res => {
          that.formData = pick(res, ['id', ...Object.keys(this.formConfig.formDesc)])
          that.extList = get(res, 'ext') || []
          that.extData = that.extArray2FormData(that.extList, that.extFormConfig)
          that.stateParentId = res.parentId
          if (res.parentId !== '0') {
            that.updateFormConfig()
          }
        })
        .finally(() => {
          that.loading = false
        })
    },
    loadData() {
      let { stateId: id } = this
      this.clearData()
      if (!id) {
        return
      }
      if (this.loading) return
      this.loading = true
      this.loadFormData()
      this.showCategory && this.loadCategoryList()
    },
    // 扩展数据更新，将数据格式化成水平表格式  {"definition": "标识" } -> {"extName": "definition", "extValue": "标识"}
    // 注意：只处理模版配置中显示的字段。未在模版内配置的不显示
    formatExtData() {
      let { extData = {}, extList = [], extFormConfig } = this
      let newExtList = []
      // key: extName value: extRowData
      let extDataKv = extList.reduce((rs, o) => {
        return { ...rs, ...(o.extName && { [o.extName]: o }) }
      }, {})
      let keys = Object.keys(extFormConfig.formDesc || {}) // 只处理模版内配置的扩展字段
      keys.length &&
        keys.forEach(key => {
          let { type } = extFormConfig.formDesc[key]
          if (['text', 'button'].includes(type)) return // 排除掉静态文本和按钮控件
          let extValue = extData[key] === null || extData[key] === undefined ? '' : extData[key]
          if (isObject(extValue) || isArray(extValue)) {
            // 上传控件、多选控件等格式是数组或者复杂对象
            extValue = JSON.stringify(extValue)
          }
          newExtList.push({ ...extDataKv[key], extName: key, extValue }) // 合并数据。主要是合并主键
        })
      return newExtList
    },
    handleSave(val) {
      // 只有不是dialog的时候才去更新id
      let that = this
      let { formData, stateParentId: parentId, type } = this
      return new Promise(function (resolve, reject) {
        Promise.all([that.$refs.form.validate(), that.extFormConfig ? that.$refs.ext.validate() : Promise.resolve()]).then(
          () => {
            let ext = that.formatExtData()
            that.loading = true
            fetchApi
              .call(that, '/set/save', { ...formData, ...(parentId && { parentId }), ext, type })
              .then(function (res) {
                that.stateId = res.id
                if (val !== 'dialog') {
                  that.$OecpMetaDataEventBus.component.attrs = {
                    ...that.$OecpMetaDataEventBus.component.attrs,
                    id: res.id,
                    editable: true,
                    showSubset: true,
                    showElement: true,
                    showCategory: true,
                    showGoBack: true,
                  }
                }
                that.$message.success('保存成功')
                resolve(res)
              })
              .catch(err => {
                reject(err)
              })
              .finally(() => {
                that.loading = false
              })
          },
          err => {
            reject(err)
          },
        )
      })
    },
  },
  created() {
    this.stateId = this.id
    this.stateParentId = this.parentId
    this.updateFormConfig()
    this.loadData()
  },
}
</script>
<style scoped>
.mt20 {
  margin-top: 20px;
}
.oecp-divider {
  margin-top: 10px;
  margin-bottom: 0px;
  display: none;
}
.title-style {
  /* padding-top: 6px; */
  font-size: 18px;
  /* font-weight: 600; */
}
/* .oecp-component-header{
  position: -webkit-sticky;
  position: sticky;
  top: -20px;
  z-index: 999;
  background-color:#fff;
} */
.oecp-component-header {
  justify-content: center;
  align-items: center !important;
  display: flex;
}
.oecp-md-set-form {
  background: #fff;
  margin-top: 20px;
  padding: 20px;
  border-radius: 6px;
}
.addBtn {
  background: #2468f2;
  border-color: #2468f2;
  padding: 0 20px;
}
.addBtn:hover {
  background: #2469f2d6;
  border-color: #2469f2d6;
}
</style>
