<template>
  <div class="app-container">
    <el-card shadow="never">
      <el-form ref="queryForm" :model="queryParams" size="small" :inline="true">
        <el-form-item prop="trainingTopic">
          <template slot="label">{{ tsT("queryTrainingTopic") }}</template>
          <el-input
            v-model="queryParams.trainingTopic"
            :placeholder="tsT('queryTrainingTopicPh')"
            clearable
            style="width: 220px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item prop="trainingDateRange">
          <template slot="label">{{ tsT("queryTrainingDate") }}</template>
          <el-date-picker
            v-model="queryParams.trainingDateRange"
            type="daterange"
            value-format="yyyy-MM-dd"
            :range-separator="tsT('trainingRangeSeparator')"
            :start-placeholder="tsT('trainingRangeStartPh')"
            :end-placeholder="tsT('trainingRangeEndPh')"
            style="width: 260px"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">{{ tsCommon("search") }}</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">{{ tsCommon("reset") }}</el-button>
          <el-button
            v-hasPermi="['techService:practicalTraining:add']"
            type="primary"
            plain
            icon="el-icon-plus"
            size="mini"
            @click="handleAdd"
          >{{ tsCommon("add") }}</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <br />

    <el-card shadow="never">
      <el-table v-loading="loading" :data="tableList" border>
        <el-table-column :label="tsT('colTrainingTopic')" prop="trainingTopic" align="center" min-width="120" :show-overflow-tooltip="true" />
        <el-table-column :label="tsT('colTrainingTime')" align="center" width="160">
          <template slot-scope="scope">
            <span>{{ scope.row.trainingTime ? parseTime(scope.row.trainingTime) : dash }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tsT('colPlannedHeadCount')" align="center" width="100">
          <template slot-scope="scope">
            <span>{{ formatHeadCount(scope.row.plannedHeadCount) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tsT('colTrainingLocation')" prop="trainingLocation" align="center" min-width="120" :show-overflow-tooltip="true" />
        <el-table-column :label="tsT('colRegStart')" align="center" width="160">
          <template slot-scope="scope">
            <span>{{ scope.row.registrationStartTime ? parseTime(scope.row.registrationStartTime) : dash }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tsT('colRegEnd')" align="center" width="160">
          <template slot-scope="scope">
            <span>{{ scope.row.registrationEndTime ? parseTime(scope.row.registrationEndTime) : dash }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tsT('colPublishDate')" align="center" width="110">
          <template slot-scope="scope">
            <span>{{ publishDateText(scope.row) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tsT('colEnrollStatus')" align="center" width="100">
          <template slot-scope="scope">
            <el-tag :type="enrollTagType(scope.row.enrollStatus)" size="small">{{ enrollStatusLabel(scope.row) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column :label="tsT('colActualEnrolled')" align="center" width="110">
          <template slot-scope="scope">
            <span>{{ formatActualEnrolled(scope.row.actualEnrolledCount) }}</span>
          </template>
        </el-table-column>
        <el-table-column :label="tsCommon('colOp')" align="center" class-name="small-padding fixed-width" width="260" fixed="right">
          <template slot-scope="scope">
            <el-button
              v-hasPermi="['techService:practicalTraining:query']"
              type="text"
              size="mini"
              @click="handleView(scope.row)"
            >{{ tsCommon("view") }}</el-button>
            <el-button
              v-hasPermi="['techService:practicalTraining:publish']"
              v-if="canPublish(scope.row)"
              type="text"
              size="mini"
              @click="handlePublish(scope.row)"
            >{{ tsCommon("publish") }}</el-button>
            <el-button
              v-hasPermi="['techService:practicalTraining:edit']"
              v-if="canEdit(scope.row)"
              type="text"
              size="mini"
              @click="handleEdit(scope.row)"
            >{{ tsCommon("edit") }}</el-button>
            <el-button
              v-hasPermi="['techService:practicalTraining:offline']"
              v-if="canOffline(scope.row)"
              type="text"
              size="mini"
              @click="handleOffline(scope.row)"
            >{{ tsCommon("offline") }}</el-button>
            <el-button
              v-hasPermi="['techService:practicalTraining:remove']"
              v-if="canDelete(scope.row)"
              type="text"
              size="mini"
              @click="handleDelete(scope.row)"
            >{{ tsCommon("delete") }}</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="total > 0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getList"
      />
    </el-card>

    <el-dialog :title="dialogTitle" :visible.sync="open" width="550px" append-to-body @close="cancel">
      <el-form :key="formKey" ref="form" :model="form" label-width="130px">
        <el-form-item prop="trainingTopic" :rules="formRules.trainingTopic">
          <template slot="label">{{ tsT("formTrainingTopic") }}</template>
          <el-input v-model="form.trainingTopic" :placeholder="tsT('phTrainingTopic')" maxlength="20" show-word-limit />
        </el-form-item>
        <el-form-item prop="trainingTime" :rules="formRules.trainingTime">
          <template slot="label">{{ tsT("formTrainingTime") }}</template>
          <el-date-picker
            v-model="form.trainingTime"
            type="datetime"
            value-format="yyyy-MM-dd HH:mm:ss"
            :placeholder="tsCommon('pleaseInput')"
            style="width: 100%"
            @change="touchTimeChainValidate"
          />
        </el-form-item>
        <el-form-item prop="trainingIntro" :rules="formRules.trainingIntro">
          <template slot="label">{{ tsT("formTrainingIntro") }}</template>
          <el-input
            v-model="form.trainingIntro"
            type="textarea"
            :rows="3"
            :placeholder="tsT('phTrainingIntro')"
            maxlength="500"
            show-word-limit
          />
        </el-form-item>
       <el-form-item prop="plannedHeadCount" :rules="formRules.plannedHeadCount">
              <template slot="label">{{ tsT("formPlannedHeadCount") }}</template>
              <el-input-number v-model="form.plannedHeadCount" :min="1" :max="999999" :step="1" controls-position="right" style="width: 100%" />
            </el-form-item>
      
            <el-form-item prop="trainingLocation" :rules="formRules.trainingLocation">
              <template slot="label">{{ tsT("formTrainingLocation") }}</template>
              <el-input v-model="form.trainingLocation"  type="textarea" :rows="2" :placeholder="tsT('phTrainingLocation')" maxlength="200" show-word-limit />
            </el-form-item>
        
        <el-form-item prop="expectedOutcome">
          <template slot="label">{{ tsT("formExpectedOutcome") }}</template>
          <el-input v-model="form.expectedOutcome" type="textarea" :rows="2" :placeholder="tsT('phExpectedOutcome')" />
        </el-form-item>
        <el-form-item prop="registrationStartTime" :rules="formRules.registrationStartTime">
              <template slot="label">{{ tsT("formRegStart") }}</template>
              <el-date-picker
                v-model="form.registrationStartTime"
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                :placeholder="tsCommon('pleaseInput')"
                style="width: 100%"
                @change="touchTimeChainValidate"
              />
            </el-form-item>
             <el-form-item prop="registrationEndTime" :rules="formRules.registrationEndTime">
              <template slot="label">{{ tsT("formRegEnd") }}</template>
              <el-date-picker
                v-model="form.registrationEndTime"
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                :placeholder="tsCommon('pleaseInput')"
                style="width: 100%"
                @change="touchTimeChainValidate"
              />
            </el-form-item>
        <el-form-item prop="coverFilePath">
          <template slot="label">{{ tsT("formCover") }}</template>
          <el-upload
            list-type="picture-card"
            :class="{ hide: hideCoverUpload }"
            :action="uploadAction"
            :headers="uploadHeaders"
            :before-upload="beforeCoverUpload"
            :on-success="handleCoverUploadSuccess"
            :on-error="handleUploadHttpError"
            :on-remove="handleCoverRemove"
            :limit="1"
            :file-list="coverFileList"
          >
            <i class="el-icon-plus" />
          </el-upload>
          <div class="el-upload__tip">{{ tsCommon("tipCover") }}</div>
        </el-form-item>
        <el-form-item prop="remark" :rules="formRules.remark">
          <template slot="label">{{ tsT("formRemark") }}</template>
          <el-input v-model="form.remark" type="textarea" :rows="2" :placeholder="tsT('phRemark')" maxlength="500" show-word-limit />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button
          v-if="!dialogEdit"
          v-hasPermi="['techService:practicalTraining:publish']"
          type="warning"
          @click="submitForm(true)"
        >{{ tsT("btnSaveAndPublish") }}</el-button>
        <el-button type="primary" @click="submitForm(false)">{{ tsCommon("ok") }}</el-button>
        <el-button @click="cancel">{{ tsCommon("cancel") }}</el-button>
      </div>
    </el-dialog>

    <el-dialog :title="tsCommon('viewTitle')" :visible.sync="viewOpen" width="760px" append-to-body>
      <el-form label-width="130px" size="small">
        <el-form-item :label="tsT('formTrainingTopic')">
          <span>{{ viewRow.trainingTopic || dash }}</span>
        </el-form-item>
        <el-form-item :label="tsT('formTrainingTime')">
          <span>{{ viewRow.trainingTime ? parseTime(viewRow.trainingTime) : dash }}</span>
        </el-form-item>
        <el-form-item :label="tsT('formTrainingIntro')">
          <span class="pt-pre">{{ viewRow.trainingIntro || dash }}</span>
        </el-form-item>
        <el-form-item :label="tsT('formPlannedHeadCount')">
          <span>{{ formatHeadCount(viewRow.plannedHeadCount) }}</span>
        </el-form-item>
        <el-form-item :label="tsT('formTrainingLocation')">
          <span>{{ viewRow.trainingLocation || dash }}</span>
        </el-form-item>
        <el-form-item :label="tsT('formExpectedOutcome')">
          <span class="pt-pre">{{ viewRow.expectedOutcome || dash }}</span>
        </el-form-item>
        <el-form-item :label="tsT('formRegStart')">
          <span>{{ viewRow.registrationStartTime ? parseTime(viewRow.registrationStartTime) : dash }}</span>
        </el-form-item>
        <el-form-item :label="tsT('formRegEnd')">
          <span>{{ viewRow.registrationEndTime ? parseTime(viewRow.registrationEndTime) : dash }}</span>
        </el-form-item>
        <el-form-item v-if="viewRow.coverFileUrl" :label="tsT('formCover')">
          <el-image :src="viewRow.coverFileUrl" fit="contain" style="max-width: 200px; max-height: 120px" />
        </el-form-item>
        <el-form-item :label="tsT('viewPublishStatus')">
          <span>{{ publishStatusText(viewRow.publishStatus) }}</span>
        </el-form-item>
        <el-form-item :label="tsT('colPublishDate')">
          <span>{{ publishDateText(viewRow) }}</span>
        </el-form-item>
        <el-form-item :label="tsT('viewEnrollStatus')">
          <el-tag :type="enrollTagType(viewRow.enrollStatus)" size="small">{{ enrollStatusLabel(viewRow) }}</el-tag>
        </el-form-item>
        <el-form-item :label="tsT('viewActualEnrolled')">
          <span>{{ formatActualEnrolled(viewRow.actualEnrolledCount) }}</span>
        </el-form-item>
        <el-form-item :label="tsT('formRemark')">
          <span>{{ viewRow.remark || dash }}</span>
        </el-form-item>
        <el-form-item :label="tsT('viewCreateBy')">
          <span>{{ viewRow.createBy || dash }}</span>
        </el-form-item>
        <el-form-item :label="tsT('viewUpdateBy')">
          <span>{{ viewRow.updateBy || dash }}</span>
        </el-form-item>
        <el-form-item :label="tsT('viewUpdateTime')">
          <span>{{ viewRow.updateTime ? parseTime(viewRow.updateTime) : dash }}</span>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button
          v-hasPermi="['techService:practicalTraining:publish']"
          v-if="canPublish(viewRow)"
          type="warning"
          @click="handlePublish(viewRow)"
        >{{ tsCommon("publish") }}</el-button>
        <el-button
          v-hasPermi="['techService:practicalTraining:offline']"
          v-if="canOffline(viewRow)"
          type="warning"
          plain
          @click="handleOffline(viewRow)"
        >{{ tsCommon("offline") }}</el-button>
        <el-button
          v-hasPermi="['techService:practicalTraining:edit']"
          v-if="canEdit(viewRow)"
          type="primary"
          plain
          @click="openEditFromView"
        >{{ tsCommon("edit") }}</el-button>
        <el-button
          v-hasPermi="['techService:practicalTraining:remove']"
          v-if="canDelete(viewRow)"
          type="danger"
          plain
          @click="handleDelete(viewRow)"
        >{{ tsCommon("delete") }}</el-button>
        <el-button @click="viewOpen = false">{{ tsCommon("close") }}</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getToken } from "@/utils/auth"
import techServiceLocaleMixin from "@/mixins/techServiceLocaleMixin"
import {
  listPracticalTraining,
  getPracticalTraining,
  addPracticalTraining,
  updatePracticalTraining,
  delPracticalTraining,
  publishPracticalTraining,
  offlinePracticalTraining
} from "@/api/techService/practicalTraining"

const PUBLISH_STATUS = { UNPUBLISHED: 0, PUBLISHED: 1 }
const ENROLL_STATUS = { NOT_STARTED: 1, ENROLLING: 2, FULL: 3, CLOSED: 4 }

export default {
  name: "PracticalTraining",
  mixins: [techServiceLocaleMixin],
  data() {
    return {
      tsNs: "practicalTraining",
      loading: false,
      open: false,
      viewOpen: false,
      viewRow: {},
      dialogEdit: false,
      formKey: 0,
      total: 0,
      tableList: [],
      queryParams: {
        pageNum: 1,
        pageSize: 20,
        trainingTopic: undefined,
        trainingDateRange: null
      },
      form: {},
      coverFileExts: ["jpg", "jpeg", "png"]
    }
  },
  computed: {
    dash() {
      return this.$t("techService.status.dash")
    },
    dialogTitle() {
      return this.dialogEdit ? this.tsT("dialogEdit") : this.tsT("dialogAdd")
    },
    formRules() {
      return {
        trainingTopic: [
          { required: true, message: this.tsT("ruleTrainingTopicRequired"), trigger: "blur" },
          { validator: this.validateTrainingTopic, trigger: "blur" }
        ],
        trainingTime: [
          { required: true, message: this.tsT("ruleTrainingTimeRequired"), trigger: "change" },
          { validator: this.validateTimeChain, trigger: "change" }
        ],
        trainingIntro: [
          { required: true, message: this.tsT("ruleTrainingIntroRequired"), trigger: "blur" },
          { validator: this.validateTrainingIntro, trigger: "blur" }
        ],
        plannedHeadCount: [
          { required: true, message: this.tsT("rulePlannedHeadRequired"), trigger: "change" },
          { validator: this.validatePlannedHeadCount, trigger: "change" }
        ],
        trainingLocation: [
          { required: true, message: this.tsT("ruleLocationRequired"), trigger: "blur" },
          { validator: this.validateTrainingLocation, trigger: "blur" }
        ],
        registrationStartTime: [
          { required: true, message: this.tsT("ruleRegStartRequired"), trigger: "change" },
          { validator: this.validateTimeChain, trigger: "change" }
        ],
        registrationEndTime: [
          { required: true, message: this.tsT("ruleRegEndRequired"), trigger: "change" },
          { validator: this.validateTimeChain, trigger: "change" }
        ],
        remark: [{ validator: this.validateRemark, trigger: "blur" }]
      }
    },
    uploadAction() {
      return process.env.VUE_APP_BASE_API + "/common/upload"
    },
    uploadHeaders() {
      return { Authorization: "Bearer " + getToken() }
    },
    coverFileList() {
      if (!this.form.coverFileUrl) {
        return []
      }
      return [{ name: "cover", url: this.form.coverFileUrl }]
    },
    hideCoverUpload() {
      return !!(this.form.coverFilePath || this.form.coverFileUrl)
    }
  },
  created() {
    this.getList()
  },
  methods: {
    parseTs(s) {
      if (!s) {
        return NaN
      }
      return new Date(String(s).replace(/-/g, "/")).getTime()
    },
    isTimeChainValid() {
      const start = this.parseTs(this.form.registrationStartTime)
      const end = this.parseTs(this.form.registrationEndTime)
      const train = this.parseTs(this.form.trainingTime)
      if (isNaN(start) || isNaN(end) || isNaN(train)) {
        return true
      }
      return start < end && end < train
    },
    validateTimeChain(rule, value, callback) {
      if (!this.form.registrationStartTime || !this.form.registrationEndTime || !this.form.trainingTime) {
        callback()
        return
      }
      if (!this.isTimeChainValid()) {
        callback(new Error(this.tsT("ruleTimeChain")))
        return
      }
      callback()
    },
    touchTimeChainValidate() {
      this.$nextTick(() => {
        if (!this.$refs.form) {
          return
        }
        ;["registrationStartTime", "registrationEndTime", "trainingTime"].forEach((prop) => {
          this.$refs.form.validateField(prop, () => {})
        })
      })
    },
    validateTrainingTopic(rule, value, callback) {
      const text = value != null ? String(value).trim() : ""
      if (!text) {
        callback(new Error(this.tsT("ruleTrainingTopicRequired")))
        return
      }
      if (text.length > 20) {
        callback(new Error(this.tsT("ruleTrainingTopicLen")))
        return
      }
      callback()
    },
    validateTrainingIntro(rule, value, callback) {
      const text = value != null ? String(value).trim() : ""
      if (!text) {
        callback(new Error(this.tsT("ruleTrainingIntroRequired")))
        return
      }
      if (text.length > 500) {
        callback(new Error(this.tsT("ruleTrainingIntroLen")))
        return
      }
      callback()
    },
    validatePlannedHeadCount(rule, value, callback) {
      const n = Number(value)
      if (!Number.isInteger(n) || n < 1) {
        callback(new Error(this.tsT("rulePlannedHeadPositive")))
        return
      }
      callback()
    },
    validateTrainingLocation(rule, value, callback) {
      const text = value != null ? String(value).trim() : ""
      if (!text) {
        callback(new Error(this.tsT("ruleLocationRequired")))
        return
      }
      if (text.length > 200) {
        callback(new Error(this.tsT("ruleLocationLen")))
        return
      }
      callback()
    },
    validateRemark(rule, value, callback) {
      if (value != null && String(value).length > 500) {
        callback(new Error(this.tsT("ruleRemarkLen")))
        return
      }
      callback()
    },
    defaultDateTime() {
      return this.parseTime(new Date(), "{y}-{m}-{d} {h}:{i}:{s}")
    },
    formatHeadCount(n) {
      if (n == null || n === "") {
        return this.dash
      }
      return `${n}${this.tsT("unitPerson")}`
    },
    formatActualEnrolled(n) {
      if (n == null || n === "") {
        return `0${this.tsT("unitPerson")}`
      }
      return `${n}${this.tsT("unitPerson")}`
    },
    publishDateText(row) {
      if (!row || row.publishStatus !== PUBLISH_STATUS.PUBLISHED || !row.publishTime) {
        return this.dash
      }
      return this.parseTime(row.publishTime, "{y}-{m}-{d}")
    },
    enrollStatusLabel(row) {
      if (row && row.enrollStatusName) {
        return row.enrollStatusName
      }
      const map = {
        [ENROLL_STATUS.NOT_STARTED]: this.$t("techService.enrollStatus.notStarted"),
        [ENROLL_STATUS.ENROLLING]: this.$t("techService.enrollStatus.enrolling"),
        [ENROLL_STATUS.FULL]: this.$t("techService.enrollStatus.full"),
        [ENROLL_STATUS.CLOSED]: this.$t("techService.enrollStatus.closed")
      }
      return map[row.enrollStatus] || this.dash
    },
    enrollTagType(status) {
      if (status === ENROLL_STATUS.ENROLLING) {
        return "success"
      }
      if (status === ENROLL_STATUS.FULL) {
        return "warning"
      }
      if (status === ENROLL_STATUS.CLOSED) {
        return "info"
      }
      return ""
    },
    canEdit(row) {
      return row && row.publishStatus === PUBLISH_STATUS.UNPUBLISHED
    },
    canPublish(row) {
      return row && row.publishStatus === PUBLISH_STATUS.UNPUBLISHED
    },
    canDelete(row) {
      return row && row.publishStatus === PUBLISH_STATUS.UNPUBLISHED
    },
    canOffline(row) {
      if (!row || row.publishStatus !== PUBLISH_STATUS.PUBLISHED) {
        return false
      }
      if (row.canOffline === true) {
        return true
      }
      if (row.canOffline === false) {
        return false
      }
      if (!row.registrationStartTime) {
        return false
      }
      return Date.now() < this.parseTs(row.registrationStartTime)
    },
    buildListQuery() {
      const q = {
        pageNum: this.queryParams.pageNum,
        pageSize: this.queryParams.pageSize,
        trainingTopic: this.queryParams.trainingTopic
      }
      const range = this.queryParams.trainingDateRange
      if (range && range.length === 2) {
        if (range[0] > range[1]) {
          this.$modal.msgError(this.tsT("ruleTrainingDateInvalid"))
          return null
        }
        q.startDate = range[0]
        q.endDate = range[1]
      }
      return q
    },
    getList() {
      const q = this.buildListQuery()
      if (!q) {
        return
      }
      this.loading = true
      listPracticalTraining(q)
        .then((res) => {
          this.tableList = res.rows || []
          this.total = res.total != null ? res.total : 0
        })
        .finally(() => {
          this.loading = false
        })
    },
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    resetQuery() {
      this.queryParams.trainingTopic = undefined
      this.queryParams.trainingDateRange = null
      this.resetForm("queryForm")
      this.handleQuery()
    },
    resetFormModel() {
      this.form = {
        id: undefined,
        trainingTopic: undefined,
        trainingTime: undefined,
        trainingIntro: undefined,
        plannedHeadCount: undefined,
        trainingLocation: undefined,
        expectedOutcome: undefined,
        registrationStartTime: undefined,
        registrationEndTime: undefined,
        coverFileUrl: undefined,
        coverFilePath: undefined,
        remark: undefined
      }
    },
    fillFormFromData(data) {
      this.form = {
        id: data.id,
        trainingTopic: data.trainingTopic,
        trainingTime: data.trainingTime,
        trainingIntro: data.trainingIntro,
        plannedHeadCount: data.plannedHeadCount,
        trainingLocation: data.trainingLocation,
        expectedOutcome: data.expectedOutcome,
        registrationStartTime: data.registrationStartTime,
        registrationEndTime: data.registrationEndTime,
        coverFileUrl: data.coverFileUrl,
        coverFilePath: data.coverFilePath,
        remark: data.remark
      }
    },
    buildPayload() {
      return {
        trainingTopic: this.form.trainingTopic != null ? String(this.form.trainingTopic).trim() : undefined,
        trainingTime: this.form.trainingTime,
        trainingIntro: this.form.trainingIntro != null ? String(this.form.trainingIntro).trim() : undefined,
        plannedHeadCount: this.form.plannedHeadCount,
        trainingLocation: this.form.trainingLocation != null ? String(this.form.trainingLocation).trim() : undefined,
        expectedOutcome: this.form.expectedOutcome,
        registrationStartTime: this.form.registrationStartTime,
        registrationEndTime: this.form.registrationEndTime,
        coverFileUrl: this.form.coverFileUrl,
        coverFilePath: this.form.coverFilePath,
        remark: this.form.remark
      }
    },
    handleAdd() {
      this.formKey += 1
      this.resetFormModel()
      this.form.trainingTime = this.defaultDateTime()
      this.dialogEdit = false
      this.open = true
      this.$nextTick(() => {
        if (this.$refs.form) {
          this.$refs.form.clearValidate()
        }
      })
    },
    handleEdit(row) {
      if (!this.canEdit(row)) {
        this.$modal.msgWarning(this.tsT("msgPublishedCannotEdit"))
        return
      }
      getPracticalTraining(row.id).then((res) => {
        const data = res.data || {}
        if (data.publishStatus === PUBLISH_STATUS.PUBLISHED) {
          this.$modal.msgWarning(this.tsT("msgPublishedCannotEdit"))
          return
        }
        this.formKey += 1
        this.dialogEdit = true
        this.fillFormFromData(data)
        this.open = true
        this.viewOpen = false
        this.$nextTick(() => {
          if (this.$refs.form) {
            this.$refs.form.clearValidate()
          }
        })
      })
    },
    openEditFromView() {
      this.handleEdit(this.viewRow)
    },
    handleView(row) {
      getPracticalTraining(row.id).then((res) => {
        this.viewRow = res.data || {}
        this.viewOpen = true
      })
    },
    handleDelete(row) {
      this.$modal
        .confirm(this.tsT("confirmDelete", { id: row.id }))
        .then(() => delPracticalTraining(row.id))
        .then(() => {
          this.$modal.msgSuccess(this.tsCommon("msgDelOk"))
          this.viewOpen = false
          this.getList()
        })
        .catch(() => {})
    },
    handlePublish(row) {
      this.$modal
        .confirm(this.tsT("confirmPublish"))
        .then(() => publishPracticalTraining(row.id))
        .then(() => {
          this.$modal.msgSuccess(this.tsCommon("msgPubOk"))
          this.viewOpen = false
          this.open = false
          this.getList()
        })
        .catch(() => {})
    },
    handleOffline(row) {
      if (!this.canOffline(row)) {
        this.$modal.msgWarning(this.tsT("msgOfflineNotAllowed"))
        return
      }
      this.$modal
        .confirm(this.tsT("confirmOffline"))
        .then(() => offlinePracticalTraining(row.id))
        .then(() => {
          this.$modal.msgSuccess(this.tsCommon("msgOffOk"))
          this.viewOpen = false
          this.getList()
        })
        .catch(() => {})
    },
    extOf(fileName) {
      if (!fileName || fileName.lastIndexOf(".") < 0) {
        return ""
      }
      return fileName.slice(fileName.lastIndexOf(".") + 1).toLowerCase()
    },
    beforeCoverUpload(file) {
      const ext = this.extOf(file.name)
      if (!this.coverFileExts.includes(ext)) {
        this.$modal.msgError(this.tsCommon("errCoverFmt"))
        return false
      }
      if (file.name.includes(",")) {
        this.$modal.msgError(this.tsCommon("errComma"))
        return false
      }
      if (file.size / 1024 / 1024 >= 10) {
        this.$modal.msgError(this.tsCommon("errCoverMb"))
        return false
      }
      this.$modal.loading(this.tsCommon("uploadingImg"))
      return true
    },
    handleUploadHttpError() {
      this.$modal.closeLoading()
      this.$modal.msgError(this.tsCommon("errUploadRetry"))
    },
    handleCoverUploadSuccess(res) {
      this.$modal.closeLoading()
      if (res.code === 200) {
        this.form.coverFileUrl = res.url
        this.form.coverFilePath = res.fileName
      } else {
        this.$modal.msgError(res.msg || this.tsCommon("errUploadFail"))
      }
    },
    handleCoverRemove() {
      this.form.coverFileUrl = undefined
      this.form.coverFilePath = undefined
    },
    submitForm(saveAndPublish) {
      this.$refs.form.validate((valid) => {
        if (!valid) {
          return
        }
        if (!this.isTimeChainValid()) {
          this.$modal.msgError(this.tsT("ruleTimeChain"))
          return
        }
        const payload = this.buildPayload()
        if (this.dialogEdit) {
          payload.id = this.form.id
          updatePracticalTraining(payload).then(() => {
            this.$modal.msgSuccess(this.tsCommon("msgModOk"))
            this.open = false
            this.getList()
          })
        } else {
          if (saveAndPublish) {
            payload.saveAndPublish = true
          }
          addPracticalTraining(payload).then(() => {
            this.$modal.msgSuccess(saveAndPublish ? this.tsCommon("msgPubOk") : this.tsCommon("msgAddOk"))
            this.open = false
            this.getList()
          })
        }
      })
    },
    cancel() {
      this.open = false
      this.resetFormModel()
    }
  }
}
</script>

<style scoped>
.pt-pre {
  white-space: pre-wrap;
  word-break: break-word;
}
.hide ::v-deep .el-upload--picture-card {
  display: none;
}
</style>
