personnel-report-dialog.vue 7.39 KB
<template>
  <el-dialog
    :visible.sync="visibleProxy"
    :show-close="false"
    width="920px"
    :close-on-click-modal="false"
    custom-class="personnel-report-dialog"
    append-to-body
    @open="handleOpen"
  >
    <div class="dialog-inner">
      <div class="dialog-header">
        <div class="dialog-title-wrap">
          <div class="dialog-title">人事填报</div>
          <div class="dialog-subtitle">{{ currentStoreName }} · 仅提交记录,不修改主档</div>
        </div>
        <span class="dialog-close" @click="visibleProxy = false"><i class="el-icon-close"></i></span>
      </div>

      <div class="dialog-body" v-loading="optionsLoading">
        <div class="entry-cards">
          <div
            class="entry-card"
            :class="{ 'entry-card--active': activeTab === 'transfer' }"
            @click="activeTab = 'transfer'"
          >
            <div class="entry-card-icon entry-card-icon--transfer">
              <i class="el-icon-sort"></i>
            </div>
            <div class="entry-card-body">
              <div class="entry-card-title">调动填报</div>
              <div class="entry-card-desc">员工调店申请</div>
            </div>
          </div>
          <div
            class="entry-card"
            :class="{ 'entry-card--active': activeTab === 'resignation' }"
            @click="activeTab = 'resignation'"
          >
            <div class="entry-card-icon entry-card-icon--resignation">
              <i class="el-icon-document-remove"></i>
            </div>
            <div class="entry-card-body">
              <div class="entry-card-title">离职填报</div>
              <div class="entry-card-desc">员工离职申请</div>
            </div>
          </div>
        </div>

        <el-card class="content-card" shadow="never">
          <el-tabs v-model="activeTab" class="report-tabs">
            <el-tab-pane label="调动填报" name="transfer">
              <transfer-report-form
                v-if="activeTab === 'transfer'"
                :options="formOptions"
                @success="handleSubmitSuccess"
              />
            </el-tab-pane>
            <el-tab-pane label="离职填报" name="resignation">
              <resignation-report-form
                v-if="activeTab === 'resignation'"
                :options="formOptions"
                @success="handleSubmitSuccess"
              />
            </el-tab-pane>
          </el-tabs>
        </el-card>
      </div>
    </div>
  </el-dialog>
</template>

<script>
import { getPersonnelReportFormOptions } from '@/api/lqPersonnelReport'
import TransferReportForm from '@/views/personnel-report/components/transfer-report-form.vue'
import ResignationReportForm from '@/views/personnel-report/components/resignation-report-form.vue'

export default {
  name: 'PersonnelReportDialog',
  components: {
    TransferReportForm,
    ResignationReportForm
  },
  props: {
    visible: { type: Boolean, default: false },
    initialTab: { type: String, default: 'transfer' }
  },
  data() {
    return {
      activeTab: 'transfer',
      optionsLoading: false,
      formOptions: {
        sourceOrganizeId: '',
        sourceOrganizeName: '',
        sourceMdid: '',
        sourceMdName: '',
        employees: [],
        targetStores: []
      }
    }
  },
  computed: {
    visibleProxy: {
      get() { return this.visible },
      set(v) { this.$emit('update:visible', v) }
    },
    currentStoreName() {
      const info = (this.$store && this.$store.getters && this.$store.getters.storeInfo) || {}
      return info.storeName || this.formOptions.sourceMdName || localStorage.getItem('store_current_store_name') || '当前门店'
    }
  },
  methods: {
    handleOpen() {
      this.activeTab = this.initialTab === 'resignation' ? 'resignation' : 'transfer'
      this.loadFormOptions()
    },
    loadFormOptions() {
      this.optionsLoading = true
      getPersonnelReportFormOptions({}).then(res => {
        const data = res.data || {}
        this.formOptions = {
          sourceOrganizeId: data.sourceOrganizeId || '',
          sourceOrganizeName: data.sourceOrganizeName || '',
          sourceMdid: data.sourceMdid || '',
          sourceMdName: data.sourceMdName || '',
          employees: data.employees || data.employeeOptions || [],
          targetStores: data.targetStores || data.targetStoreOptions || []
        }
      }).catch(() => {
        this.formOptions = {
          sourceOrganizeId: '',
          sourceOrganizeName: '',
          sourceMdid: localStorage.getItem('store_current_store_id') || '',
          sourceMdName: localStorage.getItem('store_current_store_name') || '当前门店',
          employees: [],
          targetStores: []
        }
      }).finally(() => {
        this.optionsLoading = false
      })
    },
    handleSubmitSuccess() {
      // 提交成功后保留在弹窗内,表单组件内已清空
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep .personnel-report-dialog {
  border-radius: 20px;
  padding: 0;
  background: radial-gradient(circle at 10% 20%, #eef2ff 0, #eef2ff 26%, #fdf2ff 60%, #fff7ed 100%);
  box-shadow: 0 24px 48px rgba(15, 23, 42, 0.18), 0 0 0 1px rgba(255, 255, 255, 0.9);
  .el-dialog__header { display: none; }
  .el-dialog__body { padding: 0; }
}

.dialog-inner {
  display: flex;
  flex-direction: column;
  max-height: 88vh;
}

.dialog-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 18px 22px 0;
  padding: 10px 14px;
  border-radius: 14px;
  background: rgba(219, 234, 254, 0.96);
}

.dialog-title-wrap {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.dialog-title {
  font-size: 17px;
  font-weight: 600;
  color: #0f172a;
}

.dialog-subtitle {
  font-size: 12px;
  color: #64748b;
}

.dialog-close {
  cursor: pointer;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  color: #64748b;

  &:hover {
    background: rgba(0, 0, 0, 0.06);
    color: #0f172a;
  }
}

.dialog-body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 16px 22px 22px;
}

.entry-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 16px;
}

.entry-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.88);
  border: 1px solid rgba(148, 163, 184, 0.28);
  cursor: pointer;
  transition: all 0.2s ease;
}

.entry-card:hover {
  border-color: rgba(59, 130, 246, 0.45);
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06);
}

.entry-card--active {
  border-color: #3b82f6;
  background: #fff;
  box-shadow: 0 10px 28px rgba(59, 130, 246, 0.12);
}

.entry-card-icon {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 20px;
  flex-shrink: 0;
}

.entry-card-icon--transfer {
  background: linear-gradient(135deg, #0ea5e9, #0284c7);
}

.entry-card-icon--resignation {
  background: linear-gradient(135deg, #f97316, #ef4444);
}

.entry-card-title {
  font-size: 16px;
  font-weight: 600;
  color: #0f172a;
}

.entry-card-desc {
  margin-top: 2px;
  font-size: 12px;
  color: #64748b;
}

.content-card {
  border-radius: 14px;
  border: none;
}

.report-tabs {
  ::v-deep .el-tabs__header {
    margin-bottom: 18px;
  }
}

@media (max-width: 768px) {
  .entry-cards {
    grid-template-columns: 1fr;
  }
}
</style>