<template>
  <app-dialog v-model="visible" :loading="loading" :title="title" append-to-body class="detail-dialog" fullscreen @cancel="onCancel" @confirm="onConfirm">
    <div class="page-view border-radius-5 h-100 bg-white pa-11 flex-col">
      <div class="mb-10 flex flex-gap-10">
        <el-button type="primary" @click="addAttrRows">
          <el-tooltip class="item" content="按F2可快速添加字段" effect="dark" placement="top">
            <i class="icon-question" style="margin-right: 8px" />
          </el-tooltip>
          添加字段
        </el-button>
        <el-popover v-if="!published" v-model="uploadVisible" placement="bottom" trigger="hover">
          <p>请先下载模板，填写完成后上传</p>
          <div class="text-c flex-row-c">
            <el-button class="mr-10" type="primary" plain @click="download">下载模板</el-button>
            <el-upload
              ref="upload"
              :action="actionUrl"
              :before-upload="beforeUpload"
              :data="importData"
              :headers="headers"
              :multiple="false"
              :on-error="handleError"
              :on-success="handleSuccess"
              :show-file-list="false"
            >
              <el-button size="mini" type="warning" plain>导入字段</el-button>
            </el-upload>
          </div>
          <el-button slot="reference" :loading="uploadLoading" class="ml-10" icon="el-icon-upload2" type="primary"> 导入字段 </el-button>
        </el-popover>
      </div>
      <div class="table__body_wrapper">
        <el-form ref="form" :model="form" :rule="fieldsRules" class="h-100 w-100" size="medium">
          <el-table ref="attrTableScrollbarHeight" v-loading="tableLoading" :data="form.attrData" border height="100%" style="width: 100%">
            <el-table-column align="center" fixed="left" label="序号" type="index" width="50" />
            <el-table-column align="center" fixed="left" label="名称" min-width="160" resizable>
              <template v-slot="{ row, $index }">
                <el-form-item :prop="`attrData.${$index}.name`" :rules="fieldsRules.name">
                  <el-input v-model="row.name" placeholder="请输入" />
                </el-form-item>
              </template>
            </el-table-column>
            <el-table-column align="center" fixed="left" label="编码" min-width="160" resizable>
              <template v-slot="{ row, $index }">
                <el-form-item :prop="`attrData.${$index}.code`" :rules="fieldsRules.code">
                  <el-input v-model="row.code" placeholder="请输入" />
                </el-form-item>
              </template>
            </el-table-column>
            <el-table-column align="center" label="描述" min-width="180" resizable>
              <template v-slot="{ row, $index }">
                <el-form-item :prop="`attrData.${$index}.desc`" :rules="fieldsRules.desc">
                  <el-input v-model="row.desc" placeholder="请输入" />
                </el-form-item>
              </template>
            </el-table-column>
            <!-- <el-table-column align="center" label="UI组件" min-width="120" resizable>
              <template v-slot="{ row, $index }">
                <el-form-item :prop="`attrData.${$index}.uiComCode`" :rules="fieldsRules.uiComCode">
                  <el-select v-model="row.uiComCode" placeholder="请选择" @change="(val) => changeUIType(val, row, $index)">
                    <el-option v-for="item in getDictionaryByCode('UIzjlx')" :key="item.value" :label="item.name" :value="item.value" />
                  </el-select>
                </el-form-item>
              </template>
            </el-table-column> -->
            <el-table-column align="center" label="数据类型" resizable>
              <el-table-column align="center" label="类型" min-width="120" resizable>
                <template v-slot="{ row, $index }">
                  <el-form-item :prop="`attrData.${$index}.dataType`" :rules="fieldsRules.dataType">
                    <el-select
                      v-model="row.dataType"
                      :disabled="published && !!row.id"
                      placeholder="请选择"
                      @change="(val) => changeDataType(val, row, $index)"
                    >
                      <el-option v-for="item in getDictionaryByCode('hjzdlx')" :key="item.value" :label="item.name" :value="item.value" />
                    </el-select>
                  </el-form-item>
                </template>
              </el-table-column>
              <el-table-column align="center" label="字段长度" min-width="100" resizable>
                <template v-slot="{ row, $index }">
                  <el-form-item v-if="row.dataType !== 'datetime'" :prop="`attrData.${$index}.attrLength`" :rules="fieldsRules.attrLength">
                    <el-input v-model.number="row.attrLength" placeholder="请输入" type="number" />
                  </el-form-item>
                </template>
              </el-table-column>
            </el-table-column>
            <el-table-column align="center" label="属性字段值" resizable>
              <el-table-column align="center" label="字段值类别" min-width="140" resizable>
                <template v-slot="{ row, $index }">
                  <el-form-item :prop="`attrData.${$index}.fieldValueType`" :rules="fieldsRules.fieldValueType">
                    <el-select v-model="row.fieldValueType" placeholder="请选择" @change="(val) => changeFieldValueType(val, row, $index)">
                      <el-option v-for="item in getDictionaryByCode('zdzlb')" :key="item.value" :label="item.name" :value="item.value" />
                    </el-select>
                  </el-form-item>
                </template>
              </el-table-column>
              <el-table-column align="center" label="字段值" min-width="180" resizable>
                <template v-slot="{ row, $index }">
                  <el-form-item
                    v-if="row.dataType !== 'datetime' && row.fieldValueType !== '1'"
                    :prop="`attrData.${$index}.dimensionId`"
                    :rules="fieldsRules.dimensionId"
                  >
                    <el-input v-model="row.dimensionId" placeholder="请点击选择" readonly @focus="handleSearchDict(row, $index)">
                      <i slot="suffix" class="el-input__icon el-icon-search" />
                    </el-input>
                  </el-form-item>
                </template>
              </el-table-column>
            </el-table-column>
            <el-table-column align="center" fixed="right" label="操作" width="100">
              <template v-slot="{ row, $index }">
                <el-dropdown
                  v-if="form.attrData.length > 0"
                  size="mini"
                  split-button
                  @click="handleDelete({ command: 'del', index: $index, row }, published)"
                  @command="handleCommand"
                >
                  <i v-if="published && row.id" class="el-icon-sort" />
                  <i v-else class="el-icon-delete-solid" />
                  <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item :command="{ command: 'up', row, index: $index }" :disabled="$index == 0 ? true : false">
                      上升
                      <i class="el-icon-arrow-up" />
                    </el-dropdown-item>
                    <el-dropdown-item :command="{ command: 'down', row, index: $index }" :disabled="$index == form.attrData.length - 1 ? true : false">
                      下降
                      <i class="el-icon-arrow-down" />
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </el-dropdown>
                <!-- <el-button v-else class="el-icon-delete-solid" disabled plain size="mini" /> -->
              </template>
            </el-table-column>
          </el-table>
        </el-form>
        <enum-dict-dialog v-model="dialogVisibleEnum" @change="(val) => changeDict(val, 'code')" />
        <multi-dict-dialog v-model="dialogVisibleMulti" @change="(val) => changeDict(val, 'key')" />
      </div>
    </div>
  </app-dialog>
</template>

<script>
import dialogMixin from '@/mixins/dialog.js';
import utils from '@/hotent-ui-util.js';
import enumDictDialog from './enumDictDialog.vue';
import multiDictDialog from './multiDictDialog.vue';
import { getDictionaryByCode } from '@/utils/dictionary.js';
import API from '@/api/business/dataDWCatalog';
import { mapState } from 'vuex';

export default {
  name: 'FieldsManage',
  components: {
    enumDictDialog,
    multiDictDialog,
  },
  mixins: [dialogMixin],
  props: [],
  data() {
    var checkey = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('字段编码不能为空'));
      } else {
        if (this.form.attrData.filter((item) => item.code === value).length > 1) {
          callback(new Error('字段编码不能重复!'));
        } else {
          callback();
        }
      }
    };
    return {
      fieldsRules: {
        name: [
          {
            required: true,
            message: '字段名称不能为空',
            trigger: 'blur',
          },
        ],
        code: [
          {
            required: true,
            message: '字段编码不能为空',
            trigger: 'blur',
          },
          {
            pattern: /^[a-zA-Z][a-zA-Z0-9_]*$/,
            message: '以字母开头的字母、数字、下划线组合',
            trigger: ['change', 'blur'],
          },
          { validator: checkey, trigger: 'blur' },
        ],
      },
      form: { attrData: [] },
      importData: { tableId: '' },
      dialogVisibleEnum: false,
      dialogVisibleMulti: false,
      currentRow: null,
      index: null,
      tabelData: null,
      tableLoading: false,
      uploadLoading: false,
      uploadVisible: false,
      published: false,
    };
  },
  mounted() {
    document.onkeydown = () => {
      if (this.form.attrData) {
        const key = window.event.keyCode;
        if (key == 113) {
          // == 83 && event.ctrlKey
          this.addAttrRows();
          setTimeout(() => {
            this.$refs.attrTableScrollbarHeight.bodyWrapper.scrollTop = this.$refs.attrTableScrollbarHeight.bodyWrapper.scrollHeight;
          }, 500);
        }
      }
    };
  },
  computed: {
    actionUrl: (_) => `${window.context.portal}/biz/dataResource/dwField/v1/importFile`,
    ...mapState({
      headers: (state) => ({
        Authorization: `Bearer ${state.login.currentUser.token}`,
      }),
    }),
  },

  beforeDestroy() {},
  methods: {
    initData(data) {
      this.tabelData = data;
      this.importData.tableId = data.id;
      this.published = this.tabelData.deployed === '1';
      this.getFieldsByTable();
    },
    async getFieldsByTable() {
      this.tableLoading = true;
      try {
        const { fieldList = [] } = await API.queryFieldsByTableId(this.tabelData.id);
        if (fieldList.length) {
          fieldList.forEach((item) => {
            if (item.fieldValueType) {
              item.fieldValueType = item.fieldValueType.toString();
            }
          });
          this.form.attrData = fieldList.filter((item) => item.fieldType === '2');
          this.form.attrData.sort((a, b) => a.sn - b.sn);
        } else {
          this.form.attrData = [];
        }
      } catch (err) {
        this.$message.warning(err || '资源项字段查询失败！');
      } finally {
        this.tableLoading = false;
      }
    },
    getDictionaryByCode,
    changeDict(data, key) {
      this.currentRow.dimensionId = data[key];
      this.form.attrData.splice(this.index, 1, this.currentRow);
    },
    // 新增字段
    addAttrRows() {
      const last = this.form.attrData[this.form.attrData.length - 1];
      const sn = last && last.sn ? last.sn + 1 : 1;
      const row = {
        tableId: this.tabelData.id,
        code: '',
        name: '',
        desc: '',
        fieldType: '2',
        isInitFiled: 'N',
        isPk: '0',
        isRequired: '0',
        uiComCode: 'input',
        dataType: 'varchar',
        defaultValue: '',
        format: '',
        fieldValueType: '1',
        dimensionId: '',
        unit: '',
        attrLength: 200,
        decimalLen: 0,
        isEncrypt: '0',
        isEdit: '0',
        isDesensitize: '0',
        index: this.form.attrData.length + 1,
      };
      sn ? (row.sn = sn) : null;
      this.form.attrData.splice(this.form.attrData.length, 0, row);
    },

    changeFieldValueType(val, row, index) {
      row.dimensionId = '';
      row.fieldValueType = val;
      this.form.attrData.splice(index, 1, row);
    },

    // UI类型切换设置默认值
    changeUIType(val, row, index) {
      if (!this.published && !row.id) {
        row.dataType = 'varchar';
      }
      row.format = '';
      row.fieldValueType = '1';
      if (val === 'date') {
        if (!this.published && !row.id) {
          row.dataType = 'date'; // 发布后UI和数据类型不关联
        }
        row.format = 'yyyy-MM-dd';
      } else if (val === 'datetime') {
        if (!this.published && !row.id) {
          row.dataType = 'datetime'; // 发布后UI和数据类型不关联
        }
        row.format = 'yyyy-MM-dd HH:mm:ss';
      } else if (val === 'select' || val === 'checkbox' || val === 'radio') {
        row.fieldValueType = '2';
      }
      this.form.attrData.splice(index, 1, row);
    },

    // 数据类型切换设置默认值
    changeDataType(val, row, index) {
      row.attrLength = 0;
      row.decimalLen = 0;
      row.format = '';
      row.fieldValueType = '1';
      row.dimensionId = '';
      if (val === 'date') {
        row.format = 'yyyy-MM-dd';
      } else if (val === 'datetime') {
        row.format = 'yyyy-MM-dd HH:mm:ss';
      } else if (val === 'varchar') {
        row.attrLength = 200;
      } else if (val === 'number') {
        row.attrLength = 10;
        row.decimalLen = 2;
      }
      this.form.attrData.splice(index, 1, row);
    },

    // 选择字典
    handleSearchDict(row, $index) {
      // if (this.published && row.id) {
      //   return;
      // }
      this.currentRow = row;
      this.index = $index;
      if (row.fieldValueType === '2') {
        this.dialogVisibleEnum = true;
      } else if (row.fieldValueType === '3') {
        this.dialogVisibleMulti = true;
      }
    },

    handleDelete(param, deployed) {
      if (deployed && param.row.id) return;
      this.handleCommand(param);
    },

    handleCommand(param) {
      switch (param.command) {
        case 'del':
          this.deleteAttrRows(param.row, param.index);
          break;
        case 'up':
          this.attrUp(param.row, param.index);
          break;
        case 'down':
          this.attrDown(param.row, param.index);
          break;
        default:
          break;
      }
    },

    async isDel(row, index) {
      try {
        const { state, message } = await API.deleteField(row.id);
        if (state) {
          this.form.attrData.splice(index, 1);
          this.$message.success('字段删除成功');
        }
      } catch (err) {
        this.$message.warning(err || '操作失败');
      } finally {
        this.loading = false;
      }
    },

    // 删除字段
    deleteAttrRows(row, index) {
      if (this.published && row.id) {
        return;
      }

      if (row.isInitFiled === 'Y') {
        this.$message.warning('该字段为初始字段，不可删除！');
        return;
      }

      this.$confirm(`此操作将删除字段（${row.name}）, 是否继续?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(async () => {
          if (row.id) {
            this.isDel(row, index);
          } else {
            this.form.attrData.splice(index, 1);
            this.$message.success('字段删除成功');
          }
        })
        .catch(() => {});
    },

    attrUp(row, index) {
      // if (this.published && row.id) {
      //   return;
      // }

      this.form.attrData[index].index = this.form.attrData[index].index - 1;
      this.form.attrData[index].sn = this.form.attrData[index - 1].sn;
      this.form.attrData[index - 1].index = this.form.attrData[index - 1].index + 1;
      this.form.attrData[index - 1].sn = this.form.attrData[index - 1].sn + 1;
      this.form.attrData = utils.arrayMove(this.form.attrData, row, 'up');
    },
    attrDown(row, index) {
      // if (this.published && row.id) {
      //   return;
      // }

      this.form.attrData[index].index = this.form.attrData[index].index + 1;
      this.form.attrData[index].sn = this.form.attrData[index].sn + 1;
      this.form.attrData[index + 1].index = this.form.attrData[index + 1].index - 1;
      this.form.attrData[index + 1].sn = this.form.attrData[index].sn - 1;
      this.form.attrData = utils.arrayMove(this.form.attrData, row, 'down');
    },

    onCancel() {
      this.visible = false;
    },
    onConfirm() {
      this.loading = true;
      this.$refs.form.validate(async (valid, object) => {
        if (valid) {
          console.log(this.form.attrData);
          try {
            let QUERYAPI;
            if (this.published) {
              QUERYAPI = API.saveOrUpdateFields;
            } else {
              QUERYAPI = API.saveFields;
            }
            const { state, message } = await QUERYAPI(this.form.attrData);
            if (state) {
              this.$message.success('字段保存成功');
              this.$emit('confirm');
              this.visible = false;
            } else {
              this.$message.warning(message || '操作失败');
            }
          } catch (err) {
            this.$message.warning(err || '操作失败');
          } finally {
            this.loading = false;
          }
        } else {
          this.$message.warning(`有${Object.keys(object).length}个字段未通过校验，请正确填写表单。`);
          this.loading = false;
        }
      });
    },
    download() {
      const fileType2 = '数据明细层动态表字段清单.xlsx';
      const fileType1 = '数据明细层物理表字段清单.xlsx';
      let fileType;

      if (this.tabelData.tableClass === '1') {
        fileType = fileType1;
      } else {
        fileType = fileType2;
      }
      var a = document.createElement('a');
      a.href = window.context.download + fileType;
      a.download = fileType; // 设置下载文件文件名
      a.style.display = 'none';
      document.body.appendChild(a);
      a.click();
      a.remove();
    },
    //  导入文件上传前
    beforeUpload(file) {
      return new Promise((resolve, reject) => {
        this.uploadLoading = true;
        const { size, name } = file;
        this.$confirm(`请确认是否导入 “${name}” ？`, '提示', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning',
        })
          .then((_) => {
            let passedOrNot = true; // 是否通过验证
            const typeRegular = /\.(xls|xlsx)$/i;
            const verification = [
              {
                condition: !typeRegular.test(name),
                result: () => this.$message.error('只能上传xls或xlsx文件类型'),
              },
            ];
            verification.forEach((item) => {
              if (item.condition) {
                item.result();
                passedOrNot = false;
                this.uploadLoading = false;
              }
            });

            passedOrNot ? resolve() : reject();
          })
          .catch((_) => {
            reject();
            this.uploadLoading = false;
            this.$message.warning('已取消上传');
          });
      });
    },

    // 导入文件上传成功
    async handleSuccess(res) {
      if (res.state) {
        this.$message.success('导入成功');
        this.uploadLoading = false;
        await this.getFieldsByTable();
      } else {
        this.$message.error(res.message);
      }
    },

    // 导入文件上传失败
    handleError(err) {
      if (err) {
        let errData = err.toString().replace('Error:', '');
        errData = JSON.parse(errData);
        this.$message.error(errData.message || '导入失败，请重试');
      } else {
        this.$message.error('导入失败，请重试');
      }
      this.uploadLoading = false;
    },
  },
};
</script>

<style lang="scss" scoped>
@import '@/assets/css/element-variables.scss';

.table__body_wrapper {
  flex: 1;
  height: calc(100% - 45px);
}

::v-deep .el-table td.el-table__cell {
  padding: 0;
}

::v-deep .el-form-item {
  margin: 18px 0;
}
</style>
