BatchDeleteDialog.vue 6 KB
<template>
  <el-dialog title="批量删除考勤数据" :visible.sync="visible" width="480px" custom-class="batch-delete-attendance-dialog"
    :close-on-click-modal="false" @close="close">
    <div class="batch-delete-body">
      <div class="batch-delete-intro">
        <i class="el-icon-warning-outline intro-icon" />
        <div class="intro-text">
          <p class="intro-title">按月份清空考勤汇总</p>
          <p class="intro-desc">将删除所选月份下全部汇总记录(含 Excel 导入与打卡同步),删除后无法恢复。</p>
        </div>
      </div>

      <el-form :model="form" label-width="88px" label-position="right" :rules="rules" ref="form"
        class="batch-delete-form" @submit.native.prevent>
        <el-form-item label="删除月份" prop="statMonth">
          <el-date-picker v-model="form.statMonth" type="month" value-format="yyyy-MM" format="yyyy年MM月"
            placeholder="请选择要删除的月份" style="width: 100%" :picker-options="pickerOptions" clearable
            @change="onMonthChange" />
        </el-form-item>
      </el-form>

      <div v-if="selectedLabel" class="batch-delete-target">
        <div class="target-label">即将删除范围</div>
        <div class="target-value">
          <i class="el-icon-date" />
          <span>{{ selectedLabel }}</span>
        </div>
        <div class="target-hint">该月所有员工的考勤汇总数据将被永久删除</div>
      </div>

      <el-alert class="batch-delete-alert" title="操作不可撤销" type="warning" description="建议在删除前先导出模板备份,或确认该月数据已不再需要。"
        show-icon :closable="false" />
    </div>

    <div slot="footer" class="dialog-footer">
      <el-button @click="close">取消</el-button>
      <el-button type="danger" icon="el-icon-delete" :disabled="!form.statMonth" :loading="deleting"
        @click="confirmDelete">
        确定删除
      </el-button>
    </div>
  </el-dialog>
</template>

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

export default {
  name: 'BatchDeleteDialog',
  data() {
    const now = new Date()
    const minYear = now.getFullYear() - 5
    const maxYear = now.getFullYear() + 1
    return {
      visible: false,
      deleting: false,
      form: {
        statMonth: null,
        year: null,
        month: null
      },
      rules: {
        statMonth: [
          { required: true, message: '请选择删除月份', trigger: 'change' }
        ]
      },
      pickerOptions: {
        disabledDate(date) {
          const y = date.getFullYear()
          return y < minYear || y > maxYear
        }
      }
    }
  },
  computed: {
    selectedLabel() {
      if (!this.form.year || !this.form.month) return ''
      return `${this.form.year}年${this.form.month}月`
    }
  },
  methods: {
    init(defaultMonth) {
      this.visible = true
      this.resetForm(defaultMonth)
    },
    resetForm(defaultMonth) {
      this.deleting = false
      this.form.statMonth = defaultMonth || null
      this.syncYearMonthFromStatMonth()
      this.$nextTick(() => {
        if (this.$refs.form) {
          this.$refs.form.clearValidate()
        }
      })
    },
    onMonthChange(val) {
      this.form.statMonth = val || null
      this.syncYearMonthFromStatMonth()
    },
    syncYearMonthFromStatMonth() {
      if (!this.form.statMonth) {
        this.form.year = null
        this.form.month = null
        return
      }
      const parts = this.form.statMonth.split('-')
      this.form.year = parseInt(parts[0], 10)
      this.form.month = parseInt(parts[1], 10)
    },
    confirmDelete() {
      this.$refs.form.validate((valid) => {
        if (!valid) return
        this.$confirm(
          `确定删除 ${this.selectedLabel} 的全部考勤汇总数据吗?此操作不可恢复!`,
          '确认删除',
          {
            confirmButtonText: '确定删除',
            cancelButtonText: '取消',
            type: 'warning'
          }
        ).then(() => {
          this.performDelete()
        }).catch(() => { })
      })
    },
    performDelete() {
      this.deleting = true
      request({
        url: `/api/Extend/lqattendancesummary/DeleteByMonth/${this.form.year}/${this.form.month}`,
        method: 'DELETE'
      }).then(res => {
        this.deleting = false
        if (res.code === 200) {
          this.$message.success(res.msg || '删除成功')
          this.close()
          this.$emit('refresh', true)
        } else {
          this.$message.error(res.msg || '删除失败')
        }
      }).catch(err => {
        this.deleting = false
        this.$message.error('删除失败,请重试')
        console.error('删除失败:', err)
      })
    },
    close() {
      this.visible = false
      this.resetForm()
    }
  }
}
</script>

<style lang="scss" scoped>
.batch-delete-body {
  padding: 4px 0 0;
}

.batch-delete-intro {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  margin-bottom: 20px;
  background: #fdf6ec;
  border: 1px solid #faecd8;
  border-radius: 8px;

  .intro-icon {
    flex-shrink: 0;
    font-size: 22px;
    color: #e6a23c;
    margin-top: 2px;
  }

  .intro-title {
    margin: 0 0 6px;
    font-size: 14px;
    font-weight: 600;
    color: #303133;
    line-height: 1.4;
  }

  .intro-desc {
    margin: 0;
    font-size: 13px;
    color: #606266;
    line-height: 1.5;
  }
}

.batch-delete-form {
  margin-bottom: 16px;
}

.batch-delete-target {
  padding: 14px 16px;
  margin-bottom: 16px;
  background: #f5f7fa;
  border-radius: 8px;
  border: 1px solid #ebeef5;

  .target-label {
    font-size: 12px;
    color: #909399;
    margin-bottom: 8px;
  }

  .target-value {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 18px;
    font-weight: 600;
    color: #f56c6c;
    line-height: 1.4;

    i {
      font-size: 18px;
    }
  }

  .target-hint {
    margin-top: 8px;
    font-size: 12px;
    color: #909399;
    line-height: 1.4;
  }
}

.batch-delete-alert {
  border-radius: 8px;
}

.dialog-footer {
  text-align: right;
}
</style>