<template>
  <app-dialog
    v-model="visible"
    :hide-footer="disabled"
    :loading="loading"
    :title="title"
    append-to-body
    class="detail-dialog"
    width="60%"
    @cancel="onCancel"
    @confirm="onConfirm"
  >
    <el-form ref="form" :model="form" :rules="rules" label-width="130px">
      <el-divider content-position="left"><i class="el-icon-document" style="color: rgb(24, 144, 255)" /><span
        class="divider-top">采集任务</span></el-divider>
      <div class="form-content">
        <el-row :gutter="20" type="flex">
          <app-filter-item :span="12" label="任务名称" prop="jobName">
            <el-input v-model="form.jobName" :disabled="disabled" clearable placeholder="请输入" />
          </app-filter-item>
          <app-filter-item :span="12" label="任务类别" prop="jobType">
            <el-radio-group v-model="form.jobType" :disabled="disabled">
              <el-radio-button v-for="item in jobTypes" :key="item.value" :label="item.value">
                {{ item.name }}
              </el-radio-button>
            </el-radio-group>
          </app-filter-item>
        </el-row>
        <el-row :gutter="20" type="flex">
          <app-filter-item :span="12" label="数据资源表" prop="dataResourcesName">
            <el-input v-model="form.dataResourcesName" :disabled="disabled" placeholder="请输入" read-only
                      @focus="handleTable">
              <i slot="suffix" class="el-input__icon el-icon-search" />
            </el-input>
          </app-filter-item>
        </el-row>
        <el-row :gutter="20" type="flex">
          <app-filter-item :span="24" label="执行参数配置" prop="jobParam">
            <el-input v-model="form.jobParam" :disabled="disabled" placeholder="请输入" read-only @focus="handleParam">
              <i slot="suffix" class="el-input__icon el-icon-setting" />
            </el-input>
          </app-filter-item>
        </el-row>
        <el-row v-if="form.jobType === 1" :gutter="20" type="flex">
          <app-filter-item :span="24" label="Cron表达式" prop="jobCron">
            <el-input v-model="form.jobCron" :disabled="disabled" :rows="2" clearable placeholder="请输入"
                      type="textarea" />
          </app-filter-item>
        </el-row>

        <el-row :gutter="20" type="flex">
          <app-filter-item :span="24" label="任务描述" prop="jobContent">
            <el-input v-model="form.jobContent" :disabled="disabled" :rows="2" clearable placeholder="请输入"
                      type="textarea" />
          </app-filter-item>
        </el-row>
      </div>
      <el-divider content-position="left">
        <i class="el-icon-document" style="color: rgb(24, 144, 255)" />
        <span class="divider-top">shell服务器信息</span>
      </el-divider>
      <div class="form-content">
        <el-row :gutter="20" type="flex">
          <app-filter-item :span="12" label="服务器地址" prop="remoteIp">
            <el-input v-model="form.remoteIp" :disabled="disabled" clearable placeholder="请输入服务器地址" />
            <i class="el-icon-info" style="color: rgb(24, 144, 255)" /> 格式为IP+端口，如:127.0.0.1:22
          </app-filter-item>
          <app-filter-item :span="12" label="账号" prop="remoteName">
            <el-input v-model="form.remoteName" :disabled="disabled" clearable placeholder="请输入账号" />
          </app-filter-item>
        </el-row>
        <el-row :gutter="20" type="flex">
          <app-filter-item :span="12" label="密码" prop="remotePwd">
            <el-input v-model="form.remotePwd" :disabled="disabled" clearable placeholder="请输入密码" show-password
                      type="password" />
          </app-filter-item>
          <app-filter-item :span="12" label="执行方式" prop="jobMode">
            <el-radio-group v-model="form.jobMode" :disabled="disabled">
              <el-radio-button v-for="item in jobModes" :key="item.value" :label="item.value">
                {{ item.name }}
              </el-radio-button>
            </el-radio-group>
          </app-filter-item>
        </el-row>
        <el-row :gutter="20" type="flex">
          <app-filter-item :span="24" label="shell命令" prop="command">
            <code-editor v-model="form.command" :full-screen="true" language="shell" placeholder="请输入shell命令"
                         style="min-height: 100px" />
          </app-filter-item>
        </el-row>
        <el-row :gutter="20" type="flex">
          <app-filter-item :span="12" label="shell脚本" prop="shellFile">
            <el-upload
              ref="uploadShell"
              :action="uploadUrl"
              :auto-upload="false"
              :before-upload="beforeUpload"
              :file-list="form.shellFile"
              :limit="1"
              :multiple="false"
              :on-change="changeUpload"
              :on-exceed="handleExceed"
              :on-remove="handleRemove"
              :show-file-list="true"
              accept=".sh"
            >
              <el-button slot="trigger" size="small" type="primary">文件上传</el-button>
              <span style="color: #e6a23c; margin-left: 6px">
                <i class="el-icon-warning" style="margin-right: 6px" />
                <span>shell命令和shell脚本文件至少填写一个！</span>
              </span>
            </el-upload>
          </app-filter-item>
        </el-row>
      </div>
    </el-form>
    <param-dialog v-model="paramsDialogVisible" :data="dialogData" @confirm="onConfirmJson" />
    <table-select-dialog v-model="tableDialogVisible" :data="taskData" @change="onConfirmTable" />
  </app-dialog>
</template>

<script>
import dialogMixin from '@/mixins/dialog.js'
import {getDictionaryByCode} from '@/utils/dictionary.js'
import paramDialog from './paramDialog.vue'
import tableSelectDialog from './tableSelectDialog.vue'
import API from '@/api/business/schedulerDW'
import codeEditor from '@/components/codeEditor/index.vue'

export default {
  name: 'ShellDialog',
  components: {paramDialog, tableSelectDialog, codeEditor},
  mixins: [dialogMixin],
  props: {
    mode: {
      type: Number
    }
  },
  data() {
    return {
      form: {
        jobName: '',
        tableId: '',
        dataResourcesName: '',
        jobStatus: 'NONE',
        jobTaskMode: 3,
        jobTaskType: 3,
        jobType: 1,
        jobParam: '',
        remoteIp: '',
        remoteName: '',
        remotePwd: '',
        jobMode: 'local',
        command: '',
        shellFile: []
      },
      rules: {
        jobName: [{required: true, message: '任务名称不能为空'}],
        dataResourcesName: [{required: true, message: '数据资源表不能为空'}],
        // jobParam: [{ required: true, message: '执行参数配置不能为空' }],
        jobClass: [{required: true, message: '执行类路径不能为空'}],
        jobCron: [{required: true, message: 'Cron表达式不能为空'}],
        'schedulerOds.sourceAlias': [{required: true, message: '汇聚层数据库数据源别名'}],
        sourceTempTable: [{required: true, message: '源头数据库中间表名不能为空'}],
        targetAlias: [{required: true, message: 'ODS库数据源别名不能为空'}],
        remoteIp: [
          {
            required: true,
            message: '服务器地址不能为空'
          },
          {
            message: '请正确填写服务器地址',
            pattern: /^((25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d):([0-9]{1,4}|[1-5][0-9]{4}|6[0-5]{2}[0-3][0-5]{2})$/
          }
        ],
        remoteName: [{required: true, message: '账号不能为空'}],
        remotePwd: [{required: true, message: '密码不能为空'}],
        shellFile: [{validator: this.validateAtLeastOneField, trigger: 'change'}],
        command: [{validator: this.validateAtLeastOneField, trigger: 'change'}]
      },
      jobTypes: [
        {
          value: 1,
          name: '定时任务'
        },
        {
          value: 2,
          name: '非定时任务'
        }
      ],
      jobModes: [
        {
          value: 'local',
          name: '本地'
        },
        {
          value: 'remote',
          name: '远程'
        }
      ],
      loading: false,
      paramsDialogVisible: false,
      dialogData: {},
      tableDialogVisible: false,
      taskData: {},
      resourceList: [],
      disabled: false,
      uploadUrl: ''
    }
  },
  mounted() {
  },
  methods: {
    getDictionaryByCode,
    /**
     * @description: dialog每次显示时触发的init方法
     * @param {*} data 传入data
     * @return {*}
     */
    async initData(data) {
      const orgForm = this.$options.data().form

      if (data?.id) {
        var param = new FormData()
        param.append('id', data.id)
        const {
          schedulerShell: {remoteIp, remoteName, remotePwd, command, shellName, shellPath, jobMode, ...restShell},
          ...jobData
        } = await API.getSchedulerJob(param)
        this.form = {
          remoteIp,
          remoteName,
          remotePwd,
          command,
          jobMode,
          schedulerShell: {shellName, shellPath, ...restShell},
          shellFile: shellPath
            ? [
              {
                url: shellPath,
                name: shellName
              }
            ]
            : [],
          ...jobData
        }
      } else {
        this.form = {...orgForm}
      }
      this.form.jobTaskMode = this.mode
      this.disabled = this.form.jobStatus === 'NORMAL'
      console.log(this.form)
      this.$nextTick(() => {
        this.$refs.form && this.$refs.form.clearValidate()
      })
    },
    // 参数配置
    handleParam() {
      if (this.disabled) {
        return
      }
      this.paramsDialogVisible = true
      this.dialogData = {data: this.form.jobParam}
    },
    onConfirmJson(data) {
      this.form.jobParam = data
    },
    // 选择table
    handleTable() {
      if (this.disabled) {
        return
      }
      this.tableDialogVisible = true
      this.taskData = {data: this.form.tableId}
    },
    onConfirmTable(data) {
      this.form.tableId = data.id || ''
      this.form.dataResourcesName = data.name || ''
    },
    handleCheckClass() {
      if (this.form.jobClass) {
        API.validClass(this.form.jobClass)
          .then((res) => {
            if (res.state) {
              this.$message.success('验证成功！')
            }
          })
          .catch((err) => {
            this.$message.warning(err || '验证失败！')
          })
      } else {
        this.$message.warning('请输入执行类路径')
      }
    },
    onCancel() {
      this.visible = false
      this.loading = false
      this.$refs.form.resetFields()
    },
    validateAtLeastOneField(rule, value, callback) {
      if (this.form.shellFile.length > 0 || this.form.command) {
        callback()
      } else {
        callback(new Error('shell命令和shell脚本文件至少填写一个！'))
      }
    },
    onConfirm() {
      this.loading = true
      this.$refs.form.validate(async (valid, object) => {
        if (valid) {
          try {
            let APIMethod
            if (this.form?.id) {
              APIMethod = API.editSchedulerJob
            } else {
              APIMethod = API.addSchedulerJob
            }
            var param = new FormData()

            const {
              shellFile,
              schedulerShell,
              remoteIp = '',
              remoteName = '',
              remotePwd = '',
              jobMode = '',
              command = '',
              ...rest
            } = this.form
            const jobJson = {
              schedulerShell: {
                remoteIp,
                remoteName,
                remotePwd,
                jobMode,
                command, ...schedulerShell
              }, ...rest
            }

            param.append('jobJson', JSON.stringify(jobJson))
            if (shellFile.length > 0) param.append('files', shellFile[0]?.raw || '')

            const {state, message} = await APIMethod(param)
            if (state) {
              this.$message.success(`${this.form?.id ? '编辑' : '新增'}数据任务成功`)
              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
        }
      })
    },
    beforeUpload(file) {
      const isRightType = file.name.endsWith('.sh')
      if (!isRightType) {
        this.$message.error('只能上传.sh文件')
        return false
      }
    },
    changeUpload(file, fileList) {
      this.$set(this.form, 'shellFile', fileList)
    },
    handleRemove(file, fileList) {
      this.$set(this.form, 'shellFile', fileList)
    },
    handleExceed() {
      this.$message.error('只能上传1个文件')
    }
  }
}
</script>

<style lang="scss" scoped>
.form-content {
  width: 96%;
  margin: 0 auto;
}
</style>
