<template>
  <el-container>
    <el-header height="220">
      <h3>构建部署列表</h3>
      <el-row style="margin-top: 10px">
        <el-select
          v-model="queryInfo.env"
          placeholder="环境"
          style="margin-left: 5px; width: 10%"
          @change="onSelectChange"
        >
          <el-option
            v-for="(item, index) in envList"
            :key="index"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <el-select
          v-model="queryInfo.appType"
          placeholder="类型"
          style="margin-left: 5px; width: 10%"
          @change="onSelectChange"
        >
          <el-option
            v-for="(item, index) in appTypeList"
            :key="index"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <el-input
          v-model="queryInfo.appId"
          style="margin :5px; width: 20%"
          clearable
          placeholder="输入应用名(回车搜索)"
          @clear="onClear"
          @keyup.enter.native="onSearch"
        />
        <!--        <el-button type="success" icon="el-icon-search" style="margin-left: 5px" @click="onSearch">查询</el-button>-->
        <el-button type="text" style="margin-left: 5px" @click="onRefresh">刷新</el-button>
        <el-button type="text" style="margin-left: 5px" @click="handleBuildTask">构建任务</el-button>
      </el-row>
    </el-header>
    <el-main>
      <el-table
        :data="dataList"
        border
        height="480"
        style="width: 100%"
      >
        <el-table-column
          fixed="left"
          label="No"
          type="index"
        />
        <el-table-column
          prop="appId"
          label="应用 ID"
        >
          <template slot-scope="scope">
            <el-button type="text" @click="handleAppDetail(scope.row)">
              {{ scope.row.appId }}
            </el-button>
          </template>
        </el-table-column>
        <el-table-column
          prop="repoBranch"
          label="分支"
        />
        <el-table-column
          prop="httpPort"
          label="监听端口"
        />
        <el-table-column
          prop="commitId"
          label="当前版本"
        />
        <el-table-column
          prop="commitTime"
          label="提交时间"
        />
        <el-table-column
          prop="buildTime"
          label="构建时间"
        />
        <el-table-column
          prop="buildResult"
          label="构建结果"
        >
          <template slot-scope="scope">
            <el-popover
              placement="bottom"
              title="构建进度"
              width="300"
              trigger="hover"
            >
              <el-steps
                :active="getCurrentStepIndex(scope.row.steps)"
                finish-status="success"
                direction="vertical"
                space="50px"
              >
                <el-step
                  v-for="step in scope.row.steps"
                  :key="step.stepName"
                  :title="step.stepName"
                  :description="getStepDesc(step)"
                  :status="getStepStatus(step.status)"
                />
              </el-steps>
              <el-button
                v-if="scope.row.buildResult.code !== 4"
                slot="reference"
                type="text"
                :style="{ color: scope.row.buildResult.color, fontWeight: 'bold' }"
              >
                <i v-if="scope.row.buildResult.code === 2" class="el-icon-loading" />
                {{ scope.row.buildResult.desc }}
              </el-button>
              <el-button
                v-else
                slot="reference"
                type="text"
                :style="{ color: scope.row.buildResult.color, fontWeight: 'bold' }"
                @click="handleBuildResult(scope.row)"
              >
                {{ scope.row.buildResult.desc }}
              </el-button>
            </el-popover>
          </template>
        </el-table-column>
        <el-table-column
          prop="buildBy"
          label="操作用户"
        />
        <el-table-column
          fixed="right"
          label="操作"
          width="280"
        >
          <template slot-scope="scope">
            <el-button
              style="margin-top: 5px; margin-left: 5px"
              size="mini"
              @click="handleUpdateApp(scope.$index, scope.row)"
            >更新</el-button>
            <el-button
              style="margin-top: 5px; margin-left: 5px"
              size="mini"
              @click="handleBuildApp(scope.$index, scope.row)"
            >构建</el-button>
            <el-button
              style="margin-top: 5px; margin-left: 5px"
              size="mini"
              @click="handleDeployList(scope.$index, scope.row)"
            >部署列表</el-button>
            <el-button
              style="margin-top: 5px; margin-left: 5px"
              size="mini"
              @click="handleBuildLog(scope.$index, scope.row)"
            >构建历史</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        background
        :small="screenWidth <= 768"
        layout="prev, pager, next"
        :page-size="pageSize"
        :current-page="currentPage"
        :total="totalSize"
        @current-change="handleCurrentChange"
        @prev-click="handleCurrentChange"
        @next-click="handleCurrentChange"
      />
    </el-main>

    <el-dialog
      title="构建任务"
      append-to-body
      :visible.sync="showTaskDialog"
      center
    >
      <template>
        <el-table
          :data="buildTaskList"
          border
          height="480"
          style="width: 100%"
        >
          <el-table-column
            prop="appId"
            label="应用"
          />
          <el-table-column
            prop="status"
            label="状态"
          />
          <el-table-column
            prop="waitTime"
            label="等待时间(秒)"
          />
          <el-table-column
            fixed="right"
            label="操作"
            width="280"
          >
            <template slot-scope="scope">
              <el-button
                style="margin-top: 5px; margin-left: 5px"
                size="mini"
                @click="cancelTask(scope.$index, scope.row)"
              >取消</el-button>
            </template>
          </el-table-column>
        </el-table>
      </template>
    </el-dialog>
    <el-dialog
      :title="deployDialogTitle"
      append-to-body
      :visible.sync="showDeployDialog"
      width="70%"
      center
    >
      <template>
        <el-table
          :data="deployList"
          border
          height="480"
          style="width: 100%"
        >
          <el-table-column
            fixed="left"
            label="No"
            type="index"
          />
          <el-table-column
            prop="machineIpv4"
            label="机器地址"
          />
          <el-table-column
            prop="machineStatus"
            label="机器状态"
          >
            <template slot-scope="scope">
              <el-button
                v-if="scope.row.machineStatus === 'Online'"
                type="text"
              >
                <span style="color: green">{{ scope.row.machineStatus }}</span>
              </el-button>
              <el-button
                v-else
                type="text"
              >
                <span style="color: red">{{ scope.row.machineStatus }}</span>
              </el-button>
            </template>
          </el-table-column>
          <el-table-column
            prop="commitId"
            label="当前版本"
          />
          <el-table-column
            prop="packagePath"
            label="包路径"
          />
          <el-table-column
            prop="deployBy"
            label="部署用户"
          />
          <el-table-column
            prop="deployTime"
            label="部署时间"
          />
          <el-table-column
            prop="deployResult"
            label="部署结果"
          >
            <template slot-scope="scope">
              <el-popover
                placement="bottom"
                title="部署进度"
                width="300"
                trigger="hover"
              >
                <el-steps
                  :active="getCurrentStepIndex(scope.row.steps)"
                  finish-status="success"
                  direction="vertical"
                  space="50px"
                >
                  <el-step
                    v-for="step in scope.row.steps"
                    :key="step.stepName"
                    :title="step.stepName"
                    :description="getStepDesc(step)"
                    :status="getStepStatus(step.status)"
                  />
                </el-steps>
                <el-button
                  slot="reference"
                  type="text"
                  :style="{ color: scope.row.deployResult.color, fontWeight: 'bold' }"
                >
                  <i v-if="scope.row.deployResult.code === 2" class="el-icon-loading" />
                  {{ scope.row.deployResult.desc }}
                </el-button>
              </el-popover>
            </template>
          </el-table-column>
          <el-table-column
            fixed="right"
            label="操作"
            width="280"
          >
            <template slot-scope="scope">
              <el-button
                style="margin-top: 5px; margin-left: 5px"
                size="mini"
                @click="handleDeployApp(scope.row)"
              >部署</el-button>
              <el-button
                style="margin-top: 5px; margin-left: 5px"
                size="mini"
                @click="handleDeployLog(scope.row)"
              >部署日志</el-button>
            </template>
          </el-table-column>
        </el-table>
      </template>
    </el-dialog>
    <el-dialog
      :title="buildLogDialogTitle"
      append-to-body
      :visible.sync="showBuildLogDialog"
      width="100%"
      center
    >
      <template>
        <el-table
          :data="dataList1"
          border
          height="480"
          style="width: 100%"
        >
          <el-table-column
            prop="branch"
            label="分支"
          />
          <el-table-column
            prop="commitId"
            label="版本 ID"
          />
          <el-table-column
            prop="buildTime"
            label="构建时间"
          />
          <el-table-column
            prop="buildResult"
            label="构建结果"
          >
            <template slot-scope="scope">
              <el-button
                v-if="scope.row.buildResult.code !== 4"
                slot="reference"
                type="text"
                :style="{ color: scope.row.buildResult.color, fontWeight: 'bold' }"
              >
                <i v-if="scope.row.buildResult.code === 2" class="el-icon-loading" />
                {{ scope.row.buildResult.desc }}
              </el-button>
              <el-button
                v-else
                slot="reference"
                type="text"
                :style="{ color: scope.row.buildResult.color, fontWeight: 'bold' }"
                @click="handleBuildResult(scope.row)"
              >
                {{ scope.row.buildResult.desc }}
              </el-button>
            </template>
          </el-table-column>
          <el-table-column
            prop="buildBy"
            label="部署用户"
          />
          <el-table-column
            prop="packagePath"
            label="包路径"
          />
          <el-table-column
            prop="commitId"
            label="构建配置快照"
          >
            <template slot-scope="scope">
              <el-button
                size="mini"
                type="success"
                @click="handleBuildConfig(scope.$index, scope.row)"
              >查看</el-button>
            </template>
          </el-table-column>
          <el-table-column
            prop="commitTime"
            label="构建耗时"
          >
            <template slot-scope="scope">
              <el-button
                size="mini"
                type="success"
                @click="handleBuildConsumed(scope.$index, scope.row)"
              >查看</el-button>
            </template>
          </el-table-column>
          <el-table-column
            fixed="right"
            label="操作"
            width="280"
          >
            <template slot-scope="scope">
              <el-button
                style="margin-top: 5px; margin-left: 5px"
                size="mini"
                @click="handleBuildLogFile(scope.row)"
              >日志</el-button>
              <el-button
                style="margin-top: 5px; margin-left: 5px"
                size="mini"
                @click="handleDeployBuild(scope.$index, scope.row)"
              >部署</el-button>
              <el-button
                style="margin-top: 5px; margin-left: 5px"
                size="mini"
                @click="handleBuildPackage(scope.$index, scope.row)"
              >下载</el-button>
              <el-button
                style="margin-top: 5px; margin-left: 5px"
                size="mini"
                @click="handleDeleteBuildLog(scope.$index, scope.row)"
              >删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
          background
          :small="screenWidth <= 768"
          layout="prev, pager, next"
          :page-size="pageSize1"
          :current-page="currentPage1"
          :total="totalSize1"
          @current-change="handleCurrentChange1"
          @prev-click="handleCurrentChange1"
          @next-click="handleCurrentChange1"
        />
      </template>
    </el-dialog>
    <el-dialog
      title="应用详情"
      append-to-body
      :visible.sync="showAppDialog"
      width="100%"
      center
    >
      <template>
      </template>
    </el-dialog>
    <el-dialog
      title="构建结果"
      append-to-body
      :visible.sync="showResultDialog"
      width="100%"
      center
    >
      <template>
        <span v-html="buildResult" />
      </template>
    </el-dialog>
    <el-dialog
      title="构建配置快照"
      append-to-body
      :visible.sync="showSnapshotDialog"
      center
    >
      <template>
        <div v-if="buildConfigSnapshot !== null">
          <h3>仓库配置</h3>
          <el-descriptions direction="vertical" :column="3" border>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-mobile-phone" />
                仓库认证
              </template>
              {{ buildConfigSnapshot.repoType }}
            </el-descriptions-item>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-location-outline" />
                认证名字
              </template>
              {{ buildConfigSnapshot.repoName }}
            </el-descriptions-item>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-tickets" />
                认证类型
              </template>
              {{ buildConfigSnapshot.repoAuthType }}
            </el-descriptions-item>
          </el-descriptions>
          <h3>编译配置</h3>
          <el-descriptions direction="vertical" :column="3" border>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-mobile-phone" />
                编译器类型
              </template>
              {{ buildConfigSnapshot.compileType }}
            </el-descriptions-item>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-location-outline" />
                编译名字
              </template>
              {{ buildConfigSnapshot.compileName }}
            </el-descriptions-item>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-tickets" />
                编译命令
              </template>
              {{ buildConfigSnapshot.compileScript }}
            </el-descriptions-item>
          </el-descriptions>
          <h3>打包配置</h3>
          <el-descriptions direction="vertical" :column="4" border>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-mobile-phone" />
                打包类型
              </template>
              {{ buildConfigSnapshot.packType }}
            </el-descriptions-item>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-location-outline" />
                打包名字
              </template>
              {{ buildConfigSnapshot.packName }}
            </el-descriptions-item>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-tickets" />
                打包路径
              </template>
              {{ buildConfigSnapshot.targetPath }}
            </el-descriptions-item>
            <el-descriptions-item>
              <template slot="label">
                <i class="el-icon-office-building" />
                Dockerfile
              </template>
              {{ buildConfigSnapshot.dockerfile }}
            </el-descriptions-item>
          </el-descriptions>
        </div>
      </template>
    </el-dialog>
    <el-dialog
      title="构建耗时"
      append-to-body
      :visible.sync="showConsumedDialog"
      center
    >
      <template>
        <div v-if="buildConsumed !== null" style="margin-bottom: 20px;">
          <el-row :gutter="20">
            <el-col :span="6">
              <el-statistic title="总构建耗时" :value="buildConsumed.totalDurationSeconds" suffix="秒" />
            </el-col>
            <el-col :span="18">
              <el-tag
                v-for="(time, name) in buildConsumed.stepDurations"
                :key="name"
                style="margin-right: 10px"
              >
                {{ name }}: {{ time }}s
              </el-tag>
            </el-col>
          </el-row>
        </div>
      </template>
    </el-dialog>
    <el-dialog
      title="构建日志"
      width="100%"
      append-to-body
      :visible.sync="showBuildLogFileDialog"
      center
    >
      <template>
        <div v-if="buildLogFile !== null" style="margin-bottom: 20px;">
          <span v-html="buildLogFile" />
        </div>
      </template>
    </el-dialog>
  </el-container>
</template>

<script>
import {
  buildApp,
  cancelBuildTask, deleteBuildLog, deployApp, getBuildConfigSnapshot, getBuildConsumed,
  getBuildDeployList, getBuildLogFile,
  getBuildLogList, getBuildPackageUrl, getBuildResult,
  getBuildTaskList,
  getDeployList,
  getEnvList,
  updateApp
} from '@/api/devops'

export default {
  name: 'BuildDeploy',
  data() {
    return {
      envList: [],
      appTypeList: [],
      queryInfo: {
        env: 'test',
        appType: '',
        appId: '',
        pn: 1
      },
      // 屏幕宽度, 为了控制分页条的大小
      screenWidth: document.body.clientWidth,
      currentPage: 1,
      pageSize: 10,
      totalSize: 0,
      dataList: [],
      // **********************************************************************
      showTaskDialog: null,
      buildTaskList: [],
      // **********************************************************************
      buildLogDialogTitle: '',
      showBuildLogDialog: false,
      queryInfo1: {
        appId: '',
        pn: 1
      },
      currentPage1: 1,
      pageSize1: 10,
      totalSize1: 0,
      dataList1: [],
      showAppDialog: false,
      showResultDialog: false,
      buildResult: null,
      showSnapshotDialog: false,
      buildConfigSnapshot: null,
      showConsumedDialog: false,
      buildConsumed: null,
      showBuildLogFileDialog: false,
      buildLogFile: null,
      // **********************************************************************
      deployDialogTitle: '',
      showDeployDialog: false,
      deployList: [],
      deployForm: {
        appId: null,
        buildLogId: null,
        machineId: null
      }
    }
  },
  created() {
    getEnvList().then(resp => {
      if (resp.code === 0) {
        this.queryInfo.env = resp.data.userEnv
        this.queryInfo.appType = resp.data.userAppType
        this.envList = resp.data.envList
        this.appTypeList = resp.data.appTypeList

        const env = this.$route.query.env
        if (env !== undefined && env !== null) {
          this.queryInfo.env = env
        }
        const appType = this.$route.query.appType
        if (appType !== undefined && appType !== null) {
          this.queryInfo.appType = appType
        }
        const pageNumber = this.$route.query.pn
        if (pageNumber !== undefined && pageNumber !== null) {
          this.currentPage = parseInt(pageNumber)
          this.queryInfo.pn = parseInt(pageNumber)
        }

        this.getData()
      } else {
        this.$message.error(resp.msg)
      }
    }).catch(error => {
      this.$message.error(error.message)
    })

    document.title = '构建部署'
  },
  methods: {
    handleCurrentChange(pageNumber) {
      this.queryInfo.pn = pageNumber
      this.$router.push({
        path: '/bg/app/bd',
        query: this.queryInfo
      })
      this.getData()
      // 回到顶部
      scrollTo(0, 0)
    },
    getData() {
      this.dataList = []
      getBuildDeployList(this.queryInfo).then(resp => {
        if (resp.code === 0) {
          const respData = resp.data
          this.dataList = respData.list
          this.totalSize = respData.totalSize
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleBuildTask() {
      this.showTaskDialog = true
      getBuildTaskList().then(resp => {
        if (resp.code === 0) {
          this.buildTaskList = resp.data
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    cancelTask(index, row) {
      const formData = new FormData()
      formData.append('appId', row.appId)
      cancelBuildTask(formData).then(resp => {
        this.$message.info(resp.msg)
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleBuildLog(index, row) {
      this.queryInfo1.appId = row.appId
      this.queryInfo1.pn = 1
      getBuildLogList(this.queryInfo1).then(resp => {
        if (resp.code === 0) {
          const respData = resp.data
          this.dataList1 = respData.list
          this.totalSize1 = respData.totalSize
          this.buildLogDialogTitle = row.appId + ' 的构建历史列表'
          this.showBuildLogDialog = true
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleCurrentChange1(pageNumber) {
      this.queryInfo1.pn = pageNumber
      getBuildLogList(this.queryInfo1).then(resp => {
        if (resp.code === 0) {
          const respData = resp.data
          this.dataList1 = respData.list
          this.totalSize1 = respData.totalSize
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleAppDetail(row) {
      this.$message.info('get ' + row.appId + ' detail')
      const queryInfo = {}
      queryInfo.appId = row.appId
      this.showAppDialog = true
    },
    handleBuildResult(row) {
      const queryInfo = {}
      queryInfo.buildLogId = row.buildLogId
      getBuildResult(queryInfo).then(resp => {
        if (resp.code === 0) {
          this.buildResult = resp.data
          this.showResultDialog = true
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleBuildConfig(index, row) {
      const queryInfo = {}
      queryInfo.buildLogId = row.buildLogId
      getBuildConfigSnapshot(queryInfo).then(resp => {
        if (resp.code === 0) {
          this.buildConfigSnapshot = resp.data
          this.showSnapshotDialog = true
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleBuildConsumed(index, row) {
      const queryInfo = {}
      queryInfo.buildLogId = row.buildLogId
      getBuildConsumed(queryInfo).then(resp => {
        if (resp.code === 0) {
          this.buildConsumed = resp.data
          this.showConsumedDialog = true
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleBuildPackage(index, row) {
      const queryInfo = {}
      queryInfo.buildLogId = row.buildLogId
      getBuildPackageUrl(queryInfo).then(resp => {
        if (resp.code === 0) {
          this.$message.info(resp.data)
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleBuildLogFile(row) {
      const queryInfo = {}
      queryInfo.buildLogId = row.buildLogId
      getBuildLogFile(queryInfo).then(resp => {
        if (resp.code === 0) {
          this.buildLogFile = resp.data
          this.showBuildLogFileDialog = true
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleDeployBuild(index, row) {
      const formData = new FormData()
      formData.append('buildLogId', row.buildLogId)
      formData.append('machineId', '')
      deployApp(formData).then(resp => {
        this.$message.info(resp.msg)
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleDeleteBuildLog(index, row) {
      const formData = new FormData()
      formData.append('buildLogId', row.buildLogId)
      deleteBuildLog(formData).then(resp => {
        this.$message.info(resp.msg)
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleUpdateApp(index, row) {
      const formData = new FormData()
      formData.append('appId', row.appId)
      updateApp(formData).then(resp => {
        this.getData()
        this.$message.info(resp.msg)
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleBuildApp(index, row) {
      const formData = new FormData()
      formData.append('appId', row.appId)
      buildApp(formData).then(resp => {
        this.getData()
        this.$message.info(resp.msg)
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleDeployList(index, row) {
      if (row.buildLogId === undefined) {
        this.$message.error('应用尚未构建')
        return
      }

      const queryInfo = {}
      queryInfo.appId = row.appId
      this.deployForm.appId = row.appId
      this.deployForm.buildLogId = row.buildLogId
      getDeployList(queryInfo).then(resp => {
        if (resp.code === 0) {
          this.deployList = resp.data
          this.deployDialogTitle = row.appId + ' 的部署列表'
          this.showDeployDialog = true
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleDeployApp(row) {
      const formData = new FormData()
      formData.append('buildLogId', this.deployForm.buildLogId)
      formData.append('machineId', row.machineId)
      deployApp(formData).then(resp => {
        this.$message.info(resp.msg)

        const queryInfo = {}
        queryInfo.appId = this.deployForm.appId
        getDeployList(queryInfo).then(resp => {
          if (resp.code === 0) {
            this.deployList = resp.data
          }
        })
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleDeployLog(row) {
      this.$message.info('get deploy log')
    },
    onClear() {
      this.getData()
    },
    onSearch() {
      this.getData()
    },
    onRefresh() {
      this.queryInfo.appId = ''
      this.getData()
    },
    onSelectChange() {
      this.currentPage = 1
      this.queryInfo.pn = 1
      this.$router.push({
        path: '/bg/app/bd',
        query: this.queryInfo
      })
      this.getData()
    },
    /**
     * 获取当前激活步骤的索引
     * @param {Array} steps 步骤列表
     * @returns {Number} 索引值
     */
    getCurrentStepIndex(steps) {
      if (!steps || steps.length === 0) return 0
      // 找到第一个状态不是 SUCCESS 的步骤索引
      const index = steps.findIndex(step => step.status !== 'SUCCESS')
      // 如果全部都成功了，返回 steps.length 使进度条全绿
      return index === -1 ? steps.length : index
    },

    /**
     * 获取步骤描述信息
     * @param {Object} step 步骤对象
     */
    getStepDesc(step) {
      if (step.status === 'RUNNING') {
        return '正在执行...'
      }
      if (step.status === 'FAILURE' && step.errorMsg) {
        // 如果报错，显示错误摘要（截取前30个字符防止气泡框撑爆）
        return step.errorMsg.length > 30
          ? step.errorMsg.substring(0, 30) + '...'
          : step.errorMsg
      }
      if (step.status === 'SUCCESS' && step.endTime && step.startTime) {
        // 计算耗时（可选）
        const duration = (new Date(step.endTime) - new Date(step.startTime)) / 1000
        return `耗时: ${duration.toFixed(1)}s`
      }
      return ''
    },

    /**
     * 映射后端状态到 el-step 的 status 属性
     * el-step status 可选值: wait / process / finish / error / success
     * @param {String} backendStatus 后端传来的状态串
     */
    getStepStatus(backendStatus) {
      const statusMap = {
        'PENDING': 'wait',
        'RUNNING': 'process',
        'SUCCESS': 'success',
        'FAILED': 'error',
        'SKIPPED': 'wait'
      }
      return statusMap[backendStatus] || 'wait'
    }
  }
}
</script>

<style>
</style>
