approval-history-dialog.vue 5.95 KB
<template>
  <el-dialog 
    title="审批历史" 
    :visible.sync="visible" 
    :close-on-click-modal="false"
    class="NCC-dialog NCC-dialog_center" 
    width="900px"
    @close="handleClose"
  >
    <div class="history-content" v-loading="loading">
      <el-timeline v-if="historyList && historyList.length > 0">
        <el-timeline-item
          v-for="(item, index) in historyList"
          :key="index"
          :timestamp="formatDateTime(item.approvalTime)"
          placement="top"
          :type="getTimelineType(item.approvalResult)"
          :icon="getTimelineIcon(item.approvalResult)"
        >
          <el-card class="history-card">
            <div class="history-header">
              <div class="history-node-info">
                <span class="node-name">{{ item.nodeName || '无' }}</span>
                <el-tag size="small" type="info">第{{ item.nodeOrder }}节点</el-tag>
              </div>
              <el-tag 
                :type="getRecordType(item.approvalResult)"
                size="medium"
              >
                {{ item.approvalResult || '无' }}
              </el-tag>
            </div>
            <div class="history-body">
              <div class="history-item">
                <span class="history-label">审批人:</span>
                <span class="history-value">{{ item.approverName || '无' }}</span>
              </div>
              <div class="history-item" v-if="item.approvalOpinion">
                <span class="history-label">审批意见:</span>
                <span class="history-value">{{ item.approvalOpinion }}</span>
              </div>
              <div class="history-item" v-if="item.approvalTime">
                <span class="history-label">审批时间:</span>
                <span class="history-value">{{ formatDateTime(item.approvalTime) }}</span>
              </div>
            </div>
          </el-card>
        </el-timeline-item>
      </el-timeline>
      <el-empty v-else description="暂无审批历史" :image-size="120" />
    </div>
    <span slot="footer" class="dialog-footer">
      <el-button @click="visible = false">关 闭</el-button>
    </span>
  </el-dialog>
</template>

<script>
import request from '@/utils/request'

export default {
  name: 'ApprovalHistoryDialog',
  data() {
    return {
      visible: false,
      loading: false,
      historyList: []
    }
  },
  methods: {
    init(id) {
      this.visible = true
      this.loading = true
      this.historyList = []
      this.getHistory(id)
    },

    async getHistory(id) {
      try {
        const response = await request({
          url: `/api/Extend/LqReimbursementApplication/${id}/Actions/ApprovalHistory`,
          method: 'GET'
        })

        if (response.code === 200) {
          this.historyList = response.data || []
        } else {
          this.$message.error(response.msg || '获取审批历史失败')
          this.historyList = []
        }
      } catch (error) {
        console.error('获取审批历史失败:', error)
        this.$message.error('获取审批历史失败')
        this.historyList = []
      } finally {
        this.loading = false
      }
    },

    handleClose() {
      this.visible = false
      this.historyList = []
    },

    formatDateTime(dateTime) {
      if (!dateTime) return '无'
      // 如果是时间戳(数字),需要转换
      if (typeof dateTime === 'number') {
        const date = new Date(dateTime)
        const year = date.getFullYear()
        const month = String(date.getMonth() + 1).padStart(2, '0')
        const day = String(date.getDate()).padStart(2, '0')
        const hours = String(date.getHours()).padStart(2, '0')
        const minutes = String(date.getMinutes()).padStart(2, '0')
        const seconds = String(date.getSeconds()).padStart(2, '0')
        return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
      }
      // 如果是字符串,直接返回
      const date = new Date(dateTime)
      if (isNaN(date.getTime())) return dateTime
      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      const hours = String(date.getHours()).padStart(2, '0')
      const minutes = String(date.getMinutes()).padStart(2, '0')
      const seconds = String(date.getSeconds()).padStart(2, '0')
      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
    },

    getRecordType(result) {
      const typeMap = {
        '待审批': 'info',
        '通过': 'success',
        '不通过': 'danger',
        '退回': 'warning'
      }
      return typeMap[result] || ''
    },

    getTimelineType(result) {
      const typeMap = {
        '待审批': '',
        '通过': 'success',
        '不通过': 'danger',
        '退回': 'warning'
      }
      return typeMap[result] || ''
    },

    getTimelineIcon(result) {
      const iconMap = {
        '待审批': 'el-icon-time',
        '通过': 'el-icon-check',
        '不通过': 'el-icon-close',
        '退回': 'el-icon-back'
      }
      return iconMap[result] || 'el-icon-time'
    }
  }
}
</script>

<style lang="scss" scoped>
.history-content {
  //max-height: 70vh;
  overflow-y: auto;
  padding: 20px 0;
}

.history-card {
  margin-bottom: 8px;

  .history-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;

    .history-node-info {
      display: flex;
      align-items: center;
      gap: 8px;

      .node-name {
        font-weight: 600;
        color: #303133;
        font-size: 16px;
      }
    }
  }

  .history-body {
    .history-item {
      margin-bottom: 8px;
      display: flex;
      align-items: flex-start;

      &:last-child {
        margin-bottom: 0;
      }

      .history-label {
        min-width: 80px;
        color: #606266;
        font-weight: 500;
      }

      .history-value {
        color: #303133;
        flex: 1;
        word-break: break-all;
      }
    }
  }
}
</style>