<template>
  <sd-form
    v-if="formData.pageFormData"
    ref="form"
    :read-only="formMode"
    :init-values="formData.pageFormData.pageFieldInfos"
    :form-relations="sdGet(formData, 'pageFormData.attr?.formRelations')"
  >
    <template v-slot="scope">
      <h3 v-if="!portalPrefix" :class="$style.title">
        <portal-target :name="portalInternalPrefix + 'title'" slim> </portal-target>
      </h3>
      <!--
          @slot 详情表单内容
          @binding {object} model 整个表单的数据，可用于 v-model 绑定
          @binding {object} fields 后台返回的字段定义
          @binding {string} pageId 当前显示详情页使用的pageId，可以为不同pageId画不同的表单
          @binding {object} formData 当前显示详情页的整个formData（8.1.0.24新增）
        -->
      <slot :model="scope.model" :fields="scope.fields" :pageId="pageId" :formData="formData" />
      <portal :to="(portalPrefix || portalInternalPrefix) + 'buttons'">
        <sd-form-buttons :buttons="btns" :reverse-btns="!!portalPrefix" @btnClick="btnClick" />
      </portal>
      <portal :to="(portalPrefix || portalInternalPrefix) + 'title'">
        <span>{{ formData.pageTitle }}</span>
      </portal>
      <a-form-model-item v-if="!portalPrefix" :class="$style.buttons">
        <portal-target :name="portalInternalPrefix + 'buttons'" slim> </portal-target>
      </a-form-model-item>
    </template>
  </sd-form>
  <div v-else :class="$style.loading">
    <portal :to="(portalPrefix || portalInternalPrefix) + 'title'">
      <span>正在加载…</span>
    </portal>
    <a-spin />
    <portal :to="(portalPrefix || portalInternalPrefix) + 'buttons'">
      <sd-form-buttons
        :class="$style.btns"
        :buttons="[{ buttonId: 'loading-placeholder', buttonName: '' }]"
      />
    </portal>
  </div>
</template>

<script>
import { Modal } from 'ant-design-vue'
import axios from '@/common/services/axios-instance'
import errorUtil from '@/common/services/error-util'
import logUtil from '@/common/services/log-util'
import sdFormButtons from './sd-form/sd-form-buttons'
import sdFormPublicMethodsNew from './sd-form/sd-form-public-methods-new'
import components from './_import-components/sd-detail-form-import'

/**
 * <p>查看、编辑、新建一条记录。一般情况下不需要单独使用它，因为 SdDataTableEx 已经包含了这部分功能。</p>
 * <p>该组件需要配合固定格式的接口实现</p>
 * <ul>
 * <li>获取详情 <pre>api/framework/v1/page/wp/${pageId}?id={beanId}</pre></li>
 * <li>保存数据 <pre>api/framework/v1/page/handleData</pre></li>
 * </ul>
 * @displayName SdDetailForm 详情表单
 */
export default {
  name: 'SdDetailForm',
  components: {
    sdFormButtons,
    ...components,
  },
  mixins: [sdFormPublicMethodsNew],
  props: {
    /**
     * framework/v1/page/wp 接口中的 pageId
     */
    pageId: {
      type: String,
      required: true,
    },
    /**
     * framework/v1/page/wp 接口中的记录id，不传此参数就是新建
     */
    recordId: {
      type: [String, Number],
      default: undefined,
    },
    /**
     * framework/v1/page/wp 接口中的 extParams
     * @since 8.1.0.29
     */
    extParams: {
      type: Object,
      default: undefined,
    },
        /**
     * 整个表单是否只读
     */
    readOnly: {
      type: Boolean,
      default: null,
    },
    /**
     * @ignore
     */
    portalPrefix: {
      type: String,
      default: undefined,
    },
  },
  data() {
    return {
      portalInternalPrefix: this._uid + 'detail-',
      formData: {},
      dataWhenLoad: [],
    }
  },
  computed: {
    btns() {
      return this.formData.operationButtons.length > 0
        ? this.formData.operationButtons
        : [{ buttonId: 'close', buttonName: '退出' }]
    },
    formMode() {
      // 是否只读根据 上游组件设置 及 后端接口返回的mode 字段综合判断
      const readonly =
        this.readOnly != null
          ? this.readOnly
          : this.formData.mode !== undefined
          ? this.formData.mode !== 'EDIT'
          : this.formData.pageFormData.mode !== undefined
          ? this.formData.pageFormData.mode !== 'EDIT'
          : false

      return readonly
    },
  },
  watch: {
    recordId() {
      this.getData()
    },
  },
  created() {
    this.getData()
  },
  methods: {
    getData() {
      this.formData = {}
      var mode = this.$root.$route.query.mode
      axios({
        url: 'api/framework/v1/page/wp/' + this.pageId,
        method: 'post',
        data: {
          id: typeof this.recordId === 'number' ? this.recordId + '' : this.recordId,
          // 新建时，传extParams，用于设置默认值
          extParams: !this.recordId && this.extParams ? JSON.stringify(this.extParams) : undefined,
		  mode: mode,
        },
      }).then((res) => {
        this.formData = res.data
        this.initDataWhenLoad(res.data)
      })
    },
    btnClick(evt, btn) {
      // 内部按钮状态，等待外部的actionBtnClick事件返回的结果
      evt.waitUntil(
        new Promise((resolve, reject) => {
          this.sdEmit('actionBtnClick', btn)
            .then((evtInner) => {
              if (evtInner.defaultPrevented) {
                // actionBtnClick阻止了默认的行为，返回
                return
              }
              switch (btn.buttonId) {
                case 'save':
                  return this.saveBtnClick()
                case 'close':
                  /**
                   * 点击关闭按钮时触发
                   */
                  this.$emit('close')
                  break
                default:
                  break
              }
            })
            // 最终通知内部按钮，所有处理已完成
            .finally(resolve)
        })
      )

      return

      // 为了生成文档
      /**
       * 操作按钮点击时触发
       *
       * @property {event} evt 事件对象，可以用来取消默认操作等
       * @property {object} btn 点击的按钮
       */
      this.$emit('actionBtnClick', evt, btn) // eslint-disable-line no-unreachable
    },
    /**
     * 保存表单（仅处理保存请求，不做校验和错误提示）
     * @returns {Promise}
     * @since 8.0.7
     * @public
     */
    save() {
      try {
        this.saveDetailFormModifyLog()
      } catch (e) {}
      const data = {
        eventId: 'save',
        inputs: this.$refs.form.getBackendValues(),
        pageFlowId: this.formData.attrs.pageflowId,
        pagePath: this.formData.attrs.pagePath,
      }
      return axios({
        url: 'api/framework/v1/page/handleData',
        method: 'post',
        data,
      })
    },
    /**
     * 模拟点击保存按钮（包含校验和错误提示）
     * @returns {Promise}
     * @since 8.0.7
     * @public
     */
    saveBtnClick() {
      return this.$refs.form
        .validateFields()
        .then(() => {
          return this.save()
            .then((res) => {
              /**
               * 数据保存成功后触发
               */
              this.$emit('saved', res.data)
            })
            .catch((err) => {
              Modal.error({
                title: '保存失败',
                content: errorUtil.getMessage(err) || '保存失败',
              })
            })
        })
        .catch(() => {})
    },
    initDataWhenLoad(formData) {
      if (formData.pageFormData.beanId !== undefined) {
        var pageFieldInfos = formData.pageFormData.pageFieldInfos
        for (var i = 0; i < pageFieldInfos.length; i++) {
          var item = {}
          item.name = pageFieldInfos[i].name
          item.value = pageFieldInfos[i].value
          // 数据字典
          if (pageFieldInfos[i].attr && pageFieldInfos[i].attr.controlType === 'DictType') {
            item.value = pageFieldInfos[i].attr.displayValue
            item.controlType = pageFieldInfos[i].attr.controlType
            item.selectListItem = pageFieldInfos[i].attr.selectListItem
          }
          // 附件
          if (pageFieldInfos[i].attr && pageFieldInfos[i].attr.controlType === 'AttachmentType') {
            item.value = this.getAttachmentsValue(pageFieldInfos[i].attr.attachments)
            item.controlType = pageFieldInfos[i].attr.controlType
            var tmpObj = JSON.parse(pageFieldInfos[i].value)
            item.groupCode = tmpObj.value
          }
          // 选择机构
          if (pageFieldInfos[i].attr && pageFieldInfos[i].attr.controlType === 'GroupSelectType') {
            item.value = this.getSelectGroupOrUserNames(pageFieldInfos[i].value)
            item.controlType = pageFieldInfos[i].attr.controlType
          }
          this.dataWhenLoad.push(item)
        }
      }
    },
    resetWatchField() {
      // 根据前端当前字段内容重置监控，用于异步保存后页面不重新刷新的情况，避免重复识别为修改
      const dataWhenSave = this.$refs.form.getBackendValues()

      for (var i = 0; i < dataWhenSave.length; i++) {
        const key = dataWhenSave[i].name
        const dataWhenLoadItem = this.getDataWhenLoadItem(key)
        if (dataWhenLoadItem !== undefined) {
          let dataWhenSaveValue = dataWhenSave[i].value
          // 数据字典
          if (dataWhenLoadItem.controlType && dataWhenLoadItem.controlType === 'DictType') {
            dataWhenSaveValue = this.getDictLabel(
              dataWhenLoadItem.selectListItem,
              dataWhenSaveValue
            )
          }
          // 附件
          if (dataWhenLoadItem.controlType && dataWhenLoadItem.controlType === 'AttachmentType') {
            var attachments = this.$refs.form.getFieldValue(key)
            dataWhenSaveValue = this.getAttachmentsValue(attachments)
          }
          // 选择机构
          if (dataWhenLoadItem.controlType && dataWhenLoadItem.controlType === 'GroupSelectType') {
            dataWhenSaveValue = this.getSelectGroupOrUserNames(dataWhenSaveValue)
          }

          dataWhenLoadItem.value = dataWhenSaveValue
        }
      }
    },
    saveDetailFormModifyLog() {
      if (JSON.stringify(this.dataWhenLoad) !== '[]') {
        var dataWhenSave = this.$refs.form.getBackendValues()
        var modifyLogData = []
        for (var i = 0; i < dataWhenSave.length; i++) {
          var key = dataWhenSave[i].name
          var dataWhenLoadItem = this.getDataWhenLoadItem(key)
          if (dataWhenLoadItem !== undefined) {
            var dataWhenSaveValue = dataWhenSave[i].value
            // 数据字典
            if (
              Object.prototype.hasOwnProperty.call(dataWhenLoadItem, 'controlType') &&
              dataWhenLoadItem.controlType === 'DictType'
            ) {
              dataWhenSaveValue = this.getDictLabel(
                dataWhenLoadItem.selectListItem,
                dataWhenSaveValue
              )
            }
            // 附件
            if (
              Object.prototype.hasOwnProperty.call(dataWhenLoadItem, 'controlType') &&
              dataWhenLoadItem.controlType === 'AttachmentType'
            ) {
              var attachments = this.$refs.form.getFieldValue(key)
              dataWhenSaveValue = this.getAttachmentsValue(attachments)
            }
            // 选择机构
            if (
              Object.prototype.hasOwnProperty.call(dataWhenLoadItem, 'controlType') &&
              dataWhenLoadItem.controlType === 'GroupSelectType'
            ) {
              dataWhenSaveValue = this.getSelectGroupOrUserNames(dataWhenSaveValue)
            }

            if (dataWhenLoadItem.value !== dataWhenSaveValue) {
              modifyLogData.push({
                key: key,
                oldVal: dataWhenLoadItem.value,
                newVal: dataWhenSaveValue,
              })
            }
          }
        }
        // 扩展点--在子组件自定义修改modifyLogData中的元素
        this.$emit('modifyLogCustomData', modifyLogData)

        if (JSON.stringify(modifyLogData) !== '[]') {
          return axios({
            url: 'api/xcoa-mobile/v1/iamdetailformmodifylog/saveDetailFormModifyLog',
            method: 'post',
            data: {
              beanId: this.recordId,
              formId: this.formData.pageFormData.formId,
              pageId: this.pageId,
              jsonStr: JSON.stringify(modifyLogData),
            },
          })
        }
      }
    },
    getDataWhenLoadItem(key) {
      var item
      for (var i = 0; i < this.dataWhenLoad.length; i++) {
        if (this.dataWhenLoad[i].name === key) {
          item = this.dataWhenLoad[i]
        }
      }
      return item
    },
    getDictLabel(selectListItem, value) {
      var labels = []
      if (value !== undefined && value !== '') {
        var tmpArr = value.split(',')
        for (var i = 0; i < selectListItem.length; i++) {
          if (tmpArr.indexOf(selectListItem[i].value) !== -1) {
            labels.push(selectListItem[i].label)
          }
        }
      }
      return labels.join(',')
    },
    getAttachmentsValue(attachments) {
      var value = []
      for (var i = 0; i < attachments.length; i++) {
        value.push(attachments[i].name)
      }
      return value.join('，')
    },
    getSelectGroupOrUserNames(jsonStr) {
      var names = []
      if (jsonStr !== undefined && jsonStr !== '' && jsonStr !== null) {
        var tmpArr = JSON.parse(jsonStr)
        for (var j = 0; j < tmpArr.length; j++) {
          names.push(tmpArr[j].name)
        }
      }
      return names.join(',')
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.btns {
  :global(.sd-form-btns-loading-placeholder) {
    visibility: hidden;
  }
}
.title {
  text-align: center;
}
.loading {
  margin: 70px;
  text-align: center;
}
.buttons {
  :global .ant-form-item-control-wrapper {
    margin-left: 25%;
    .ant-btn + .ant-btn {
      margin-left: 8px;
    }
  }
}
</style>
