<template>
  <div class="fullheight">
    <el-dialog width="55%" top="6vh" title="连接管理" class="sp-manager__dialog" :visible.sync="dialogVisible"
      v-if="dialogVisible" :before-close="beforeCloseDialog" append-to-body :close-on-click-modal="false">
      <el-form v-form data-vv-scope="PortalConnectionManagerForm" :disabled="formData.initFlag == 1">
        <ht-form-item label="所属分类" label-width="140px">
          <EipSysTypeSelector placeholder="所属分类" cat-id="15" v-model="formData.typeName"
            :sys-type-id.sync="formData.typeId" :validate="{ required: true }" />
        </ht-form-item>
        <ht-form-item label="连接名称" label-width="140px">
          <ht-input v-model="formData.name" autocomplete="off" :validate="{ required: true }" placeholder="请输入名称"
            :maxlength="50" :showWordLimit="true"></ht-input>
        </ht-form-item>
        <ht-form-item label="连接别名" label-width="140px">
          <ht-input v-model="formData.alias" v-pinyin="formData.name" :disabled="formData.id ? true : false"
            autocomplete="off" :validate="{
              required: true,
              isExist: '${form}/form/form/v1/checkKey?key=',
              regex: {
                exp: '^[a-zA-Z][a-zA-Z0-9_]*$',
                message: '只能输入字母、数字、下划线，且以字母开头'
              }
            }" :maxlength="50" :showWordLimit="true" placeholder="请输入别名"></ht-input>
        </ht-form-item>
        <ht-form-item label="启用状态" label-width="140px">
          <el-switch active-value="1" inactive-value="0" v-model="formData.status"></el-switch>
        </ht-form-item>
        <ht-form-item label="连接类型" label-width="140px">
          <ht-select v-model="formData.connectionType" :options="options" :validate="{ required: true }"
            placeholder="请选择连接类型" />
        </ht-form-item>
        <div v-if="formData.connectionType == 'dataSource'">
          <ht-form-item label="数据源类型" label-width="140px" class="dataSource-item-bottom dataSource-input-width">
            <ht-select v-model="sourceProp.dbType" :options="dbTypeList" :props="{ key: 'value', value: 'value' }"
              :validate="{ required: true }" @change="currentSel" />
          </ht-form-item>
          <ht-form-item label="数据源" label-width="140px" class="dataSource-item-bottom dataSource-input-width">
            <ht-select v-model="dsId" :options="sysDataSourceDefs" :props="{ key: 'id', value: 'name' }"
              :validate="{ required: true }" @change="settingSel" />
          </ht-form-item>
          <ht-form-item v-for="(item, index) in sourceProp.settingJson" :key="item.comment" v-show="
            sourceProp.settingJson.length > 0 && !isExpand ? index < 4 : true
          " :label="item.comment" label-width="140px" class="dataSource-item-bottom dataSource-input-width">
            <ht-input v-model="item.value" :validate="{ required: true }" :placeholder="'请输入' + item.comment" :disabled="
              (item.name == 'password' ||
                item.name == 'connectionProperties') &&
              isEncrypt === 1
            ">
            </ht-input>
            ({{ item.type }})
            <div v-if="item.name == 'password'">
              <el-switch v-model="isEncrypt" active-color="#13ce66" inactive-color="#ff4949" :active-value="1"
                :inactive-value="0" active-text="加密" inactive-text="不加密" @change="encrypt(item)">
              </el-switch>
            </div>
          </ht-form-item>
          <div style="text-align: center;" v-if="sourceProp.settingJson.length > 0">
            <el-button size="mini" @click="isExpand = !isExpand" :icon="isExpand ? 'icon-expand' : 'icon-hide'" circle
              :title="isExpand ? '收起' : '展开'"></el-button>
          </div>
        </div>
        <div v-if="formData.connectionType == 'restful'">
          <ht-form-item label="基础地址" label-width="140px" class="dataSource-item-bottom dataSource-input-width">
            <ht-input v-model="formData.restfulManage.baseUrl" :validate="{ required: true }" placeholder="请输入基础地址">
            </ht-input>
          </ht-form-item>
        </div>
      </el-form>
      <div slot="footer" style="text-align: right">
        <el-button @click="beforeCloseDialog">{{
          $t('eip.common.cancel')
        }}</el-button>
        <el-button v-if="formData.connectionType == 'dataSource' && !formData.initFlag" @click="checkConnection()"
          type="primary">测试连接</el-button>
        <ht-submit-button v-if="!formData.initFlag" url="${portal}/portal/portalConnectionManager/v1/save" :model="formData"
          :request-method="saveMethod" scope-name="PortalConnectionManagerForm" @before-save-data="beforeSaveData"
          @after-save-data="afterSaveData" :loading="loadBtning">{{ $t('eip.common.save') }}</ht-submit-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import sys from '@/api/portal.js'
import req from '@/request.js'
import portal from '@/api/portal.js'
const EipSysTypeSelector = () =>
  import('@/components/selector/EipSysTypeSelector.vue')
export default {
  components: {
    EipSysTypeSelector
  },
  data() {
    return {
      isExpand: false,
      dialogVisible: false,
      formData: {
        typeId: '',
        typeName: '',
        name: '',
        alias: '',
        connectionType: '',
        status: '1',
        dataSource: {},
        restfulManage: {
          baseUrl: ''
        }
      },
      options: [
        { key: 'dataSource', value: '数据源' },
        { key: 'restful', value: 'restful接口' }
      ],
      dbType: null,
      dbTypeList: [
        {
          value: 'mysql',
          driverName: 'com.mysql.cj.jdbc.Driver',
          url:
            'jdbc:mysql://主机:3306/数据库名?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull',
          validationquery: 'select 1 from dual'
        },
        {
          value: 'oracle',
          driverName: 'oracle.jdbc.OracleDriver',
          url: 'jdbc:oracle:thin:@主机:1521:数据库实例',
          validationquery: 'select 1 from dual'
        },
        {
          //人大金仓
          value: 'kingbase',
          driverName: 'com.kingbase8.Driver',
          url: 'jdbc:kingbase8://主机:54321/数据库名',
          validationquery: 'select 1 from dual'
        },
        {
          value: 'pgsql',
          driverName: 'org.postgresql.Driver',
          url: 'jdbc:postgresql://主机:5432/数据库名',
          validationquery: 'select 1'
        },
        {
          value: 'dm8',
          driverName: 'dm.jdbc.driver.DmDriver',
          url: 'jdbc:dm://192.168.1.120:5236/EIP725_DM',
          validationquery: 'select 1 from dual'
        },
        {
          value: 'mssql2012',
          driverName: 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
          url: 'jdbc:sqlserver://主机:1433;databaseName=数据库名;',
          validationquery: 'select 1'
        },
        {
          value: 'mssql2008',
          driverName: 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
          url: 'jdbc:sqlserver://主机:1433;databaseName=数据库名;',
          validationquery: 'select 1'
        },
      ],
      sysDataSourceDefs: [],
      dsId: '',
      sourceProp: {
        settingJson: [],
        initOnStart: false,
        enabled: null,
        dbType: '',
        classPath: '',
        initMethod: '',
        closeMethod: '',
        name: '',
        alias: '',
        id: ''
      },
      newSourceProp: {},
      sysDataSourceRow: {},
      dataSourcesInBean: [], //数据源池
      systemList: [], //外部系统列表
      saveMethod: 'POST',
      isEncrypt: 0,
      loadBtning: false
    }
  },
  watch: {
    dsId: function (newVal, oldVal) {
      if (!newVal) {
        this.sourceProp.settingJson = []
      }
    }
  },
  mounted() {
    this.getDataSourcesList()
    this.getDataSourceDef()
    this.loadSystemList()
    this.$validator = this.$root.$validator
  },
  methods: {
    //鼠标选中行改变复选框
    rowClick(row, column, event) {
      this.$refs.dataSourceTable.$refs.htTable.toggleRowSelection(row)
    },
    getDataSourceDef() {
      req
        .get(window.context.portal + '/sys/sysDataSourceDef/v1/getAll')
        .then(resp => {
          this.sysDataSourceDefs = resp.data
        })
    },
    encrypt(item) {
      if (this.isEncrypt === 1) {
        if (!item.value) {
          this.$message.warning('请输入密码!')
          this.isEncrypt = 0
          return
        }
        this.$http
          .post(window.context.portal + '/base/tools/v1/encryptDbPassword', {
            password: item.value
          })
          .then(res => {
            if (this.dsId != '1') {
              this.$message.error('不支持密码加密')
              this.isEncrypt = 0
              return
            }
            if (!res.data.state) {
              this.$message.error('加密失败')
              return
            }
            item.value = res.data.value.password
            let publicKey = {
              name: 'connectionProperties',
              comment: '公钥',
              type: 'java.lang.String',
              baseAttr: '1',
              default: '',
              value:
                'config.decrypt=true;config.decrypt.key=' +
                res.data.value.publicKey
            }
            this.sourceProp.settingJson.splice(
              this.sourceProp.settingJson.findIndex(
                item => item.name === 'connectionProperties'
              ),
              1
            )
            this.sourceProp.settingJson.splice(
              this.sourceProp.settingJson.findIndex(
                item => item.name === 'password'
              ) + 1,
              0,
              publicKey
            )
          })
      } else {
        item.value = ''
        let index = this.sourceProp.settingJson.findIndex(
          item => item.name === 'connectionProperties'
        )
        if (index > 0) {
          this.sourceProp.settingJson.splice(index, 1)
        }
      }
    },
    checkConnection() {

      if (this.sourceProp.settingJson.length == 0) {
        this.$message.error('连接失败')
        return
      }
      var newSourceProp = {}
      Object.assign(newSourceProp, this.sourceProp)
      newSourceProp.name = this.formData.name
      newSourceProp.settingJson = JSON.stringify(newSourceProp.settingJson)
      sys.checkConnection(newSourceProp).then(
        data => {
          if (data.state) {
            this.$message.success(data.message)
          }
        },
        error => {
          this.$message.error(error || '连接失败')
        }
      )
    },
    currentSel(val, data) {
      var list = data.value
      for (var i in this.dbTypeList) {
        var d = this.dbTypeList[i]
        if (d.value != val) continue
        for (var i = 0; i < this.sourceProp.settingJson.length; i++) {
          var attr = this.sourceProp.settingJson[i]
          if (attr.name.toLowerCase().indexOf('url') != -1) {
            attr.value = d.url
          } else if (attr.name.toLowerCase().indexOf('driver') != -1) {
            attr.value = d.driverName
          } else if (attr.name.toLowerCase().indexOf('validationquery') != -1) {
            attr.value = d.validationquery
          }
        }
      }
    },
    settingSel(dsId, data) {
      if (data && data.settingJson) {
        this.sourceProp.settingJson = JSON.parse(
          data.settingJson.replace(/[\\]/g, '')
        )
        //改变了数据池id，那么需要输入的属性也变了
        for (var i = 0; i < this.sysDataSourceDefs.length; i++) {
          var def = this.sysDataSourceDefs[i]
          if (def.id != dsId) continue
          var settingJson = JSON.parse(def.settingJson.replace(/[\\]/g, ''))
          this.sourceProp.classPath = def.classPath
          this.sourceProp.initMethod = def.initMethod
          this.sourceProp.closeMethod = def.closeMethod
          //处理配置的初始化值
          this.sourceProp.settingJson = []
          settingJson.forEach(obj => {
            obj.value = obj['default']
            this.sourceProp.settingJson.push(obj)
          })
        }

        //选择了数据源类型 就替换数据源中的连接地址和驱动
        for (var i in this.dbTypeList) {
          var d = this.dbTypeList[i]
          if (d.value != this.sourceProp.dbType) continue
          for (var i = 0; i < this.sourceProp.settingJson.length; i++) {
            var attr = this.sourceProp.settingJson[i]
            if (attr.name.toLowerCase().indexOf('url') != -1) {
              attr.value = d.url
            } else if (attr.name.toLowerCase().indexOf('driver') != -1) {
              attr.value = d.driverName
            } else if (
              attr.name.toLowerCase().indexOf('validationquery') != -1
            ) {
              attr.value = d.validationquery
            }
          }
        }
        //数据源配置别名跟这里的别名一致
        for (var i = 0; i < this.sourceProp.settingJson.length; i++) {
          var attr = this.sourceProp.settingJson[i]
          if (attr.name.toLowerCase().indexOf('alias') != -1) {
            attr.value = attr.alias
          }
        }
      }
    },
    handleSelectOptions(query) {
      let _me = this
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          _me.dbType = _me.dbTypeList
          resolve()
        }, 1000)
      })
    },
    judgeIsEncrypt(settingJson) {
      let index = settingJson.findIndex(
        item => item.name === 'connectionProperties'
      )
      if (index > 0) {
        this.isEncrypt = 1
      } else {
        this.isEncrypt = 0
      }
    },
    getDataSourcesList() {
      req
        .get(window.context.portal + '/sys/sysDataSource/v1/getDataSources')
        .then(resp => {
          this.dataSourcesInBean = resp.data
        })
    },
    loadSystemList() {
      req
        .get(window.context.portal + '/portalBizSystem/v1/getList')
        .then(resp => {
          if (resp && resp.data) {
            this.systemList = resp.data.map(item => {
              let m = { key: item.id, value: item.sysName }
              return { ...m }
            })
          }
        })
    },
    showDialog(id) {
      this.loadBtning = false
      if (id) {
        this.$http
          .get('${portal}/portal/portalConnectionManager/v1/getDetail?id=' + id)
          .then(resp => {
            this.formData = resp.data.value
            if (this.formData.connectionType == 'dataSource') {
              this.formData.restfulManage = {}
              this.formData.restfulManage.baseUrl = ''
              let data = this.formData.dataSource
              this.sourceProp = data
              this.sourceProp.settingJson = JSON.parse(data.settingJson)
              this.oldAlias = this.sourceProp.alias
              //判断是否已经加密
              this.judgeIsEncrypt(this.sourceProp.settingJson)
              for (let i = 0; i < this.sysDataSourceDefs.length; i++) {
                let item = this.sysDataSourceDefs[i]
                if (item.classPath == this.sourceProp.classPath) {
                  this.dsId = item.id
                  break
                }
              }
            }
            this.dialogVisible = true
          })
      } else {
        this.formData = {
          typeId: '',
          typeName: '',
          name: '',
          alias: '',
          connectionType: '',
          status: '1',
          dataSource: {},
          restfulManage: {
            baseUrl: ''
          }
        }
        this.dialogVisible = true
      }
    },
    beforeCloseDialog() {
      this.dsId = ''
        ; (this.sourceProp = {
          settingJson: [],
          initOnStart: false,
          enabled: null,
          dbType: '',
          classPath: '',
          initMethod: '',
          closeMethod: '',
          name: '',
          alias: '',
          id: ''
        }),
          (this.dialogVisible = false)
    },
    beforeSaveData() {
      if (this.formData.connectionType == 'dataSource') {
        this.newSourceProp = {}
        //克隆一个新对象以免影响页面数据动态绑定上了
        Object.assign(this.newSourceProp, this.sourceProp)
        this.newSourceProp.settingJson = JSON.stringify(
          this.newSourceProp.settingJson
        )
        this.formData.dataSource = this.newSourceProp
        this.loadBtning = true
      }
    },
    afterSaveData() {
      setTimeout(() => {
        this.$emit('reloadList', '')
        this.beforeCloseDialog()
      }, 0)
    }
  }
}
</script>

<style lang="scss" scoped>
.sp-manager__dialog /deep/ .el-dialog>.el-dialog__body {
  stheight: calc(100% - 170px);
}

.dataSource-input-width .inputs {
  width: 100%;
}
</style>
