index.vue 9.6 KB
<template>
  <div class="flow-form" v-loading="loading">
    <div class="com-title">
      <h1>补卡申请</h1>
      <span class="number">单据号:{{ dataForm.billNo }}</span>
    </div>
    <el-form ref="dataForm" :model="dataForm" :rules="dataRule" label-width="110px" :disabled="setting.readonly">
      <el-row>
        <el-col v-if="judgeShow('flowTitle')" :span="12">
          <el-form-item label="流程标题" prop="flowTitle">
            <el-input v-model="dataForm.flowTitle" placeholder="流程标题" :disabled="judgeWrite('flowTitle')" />
          </el-form-item>
        </el-col>
        <el-col v-if="judgeShow('flowUrgent')" :span="12">
          <el-form-item label="紧急程度" prop="flowUrgent">
            <el-select v-model="dataForm.flowUrgent" placeholder="选择紧急程度" :disabled="judgeWrite('flowUrgent')">
              <el-option v-for="item in flowUrgentOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col v-if="judgeShow('applyUser')" :span="12">
          <el-form-item label="申请人员" prop="applyUser">
            <el-input v-model="dataForm.applyUser" readonly :disabled="judgeWrite('applyUser')" />
          </el-form-item>
        </el-col>
        <el-col v-if="judgeShow('applyDate')" :span="12">
          <el-form-item label="申请日期" prop="applyDate">
            <el-date-picker v-model="dataForm.applyDate" type="date" value-format="timestamp" format="yyyy-MM-dd"
              :editable="false" readonly :disabled="judgeWrite('applyDate')" />
          </el-form-item>
        </el-col>
        <el-col v-if="judgeShow('applyDept')" :span="12">
          <el-form-item label="申请部门" prop="applyDept">
            <el-input v-model="dataForm.applyDept" readonly :disabled="judgeWrite('applyDept')" />
          </el-form-item>
        </el-col>
        <el-col v-if="judgeShow('applyPost')" :span="12">
          <el-form-item label="申请职位" prop="applyPost">
            <el-input v-model="dataForm.applyPost" readonly :disabled="judgeWrite('applyPost')" />
          </el-form-item>
        </el-col>
        <el-col v-if="judgeShow('punchTargetsJson')" :span="24">
          <el-form-item label="补卡日期">
            <span class="el-text-muted">近 3 个自然日(不含当日)未打满卡的日期;勾选需补的上班/下班卡(可同时选)。审批通过后按考勤组标准时间写入。</span>
            <el-table v-loading="candidateLoading" :data="punchRows" border size="small"
              style="width:100%;margin-top:8px;">
              <el-table-column prop="date" label="日期" width="120" />
              <el-table-column prop="statusText" label="当前状态" min-width="100" />
              <el-table-column label="补上班卡" width="100" align="center">
                <template slot-scope="scope">
                  <el-checkbox v-model="scope.row._in" :disabled="setting.readonly || !scope.row.missingPunchIn" />
                </template>
              </el-table-column>
              <el-table-column label="补下班卡" width="100" align="center">
                <template slot-scope="scope">
                  <el-checkbox v-model="scope.row._out" :disabled="setting.readonly || !scope.row.missingPunchOut" />
                </template>
              </el-table-column>
            </el-table>
          </el-form-item>
        </el-col>
        <el-col v-if="judgeShow('applyReason')" :span="24">
          <el-form-item label="补卡原因" prop="applyReason">
            <el-input v-model="dataForm.applyReason" type="textarea" :rows="3" placeholder="请说明补卡原因"
              :disabled="judgeWrite('applyReason')" />
          </el-form-item>
        </el-col>
        <el-col v-if="judgeShow('fileJson')" :span="24">
          <el-form-item label="相关附件" prop="fileJson">
            <NCC-UploadFz v-model="fileList" type="workFlow" :disabled="judgeWrite('fileJson')" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

<script>
import comMixin from '../../workFlowForm/mixin'
import { Info, Create, Update } from '@/api/workFlow/workFlowForm'
import { getPunchApplyCandidates } from '@/api/extend/attendanceRecord'

export default {
  name: 'AttendancePunchApplyForm',
  mixins: [comMixin],
  data() {
    return {
      billEnCode: 'WF_AttendancePunchApplyNo',
      formApiKey: 'attendancePunchApply',
      candidateLoading: false,
      punchRows: [],
      dataForm: {
        id: '',
        flowId: '',
        billNo: '',
        flowTitle: '',
        flowUrgent: 1,
        applyUser: '',
        applyDate: '',
        applyDept: '',
        applyPost: '',
        punchTargetsJson: '[]',
        applyReason: '',
        fileJson: '',
        description: ''
      },
      dataRule: {
        flowTitle: [{ required: true, message: '流程标题不能为空', trigger: 'blur' }],
        flowUrgent: [{ required: true, message: '紧急程度不能为空', trigger: 'change' }],
        applyReason: [{ required: true, message: '补卡原因不能为空', trigger: 'blur' }]
      }
    }
  },
  methods: {
    syncPunchJson() {
      const arr = (this.punchRows || []).filter(r => r._in || r._out).map(r => ({
        date: r.date,
        punchIn: !!r._in,
        punchOut: !!r._out
      }))
      this.dataForm.punchTargetsJson = JSON.stringify(arr)
    },
    selfInit() {
      this.dataForm.applyDate = new Date().getTime()
      this.dataForm.flowTitle = this.userInfo.userName + '的补卡申请'
      this.dataForm.applyUser = this.userInfo.userName + '/' + this.userInfo.userAccount
      this.dataForm.applyDept = this.userInfo.organizeName
      if (this.userInfo.positionIds && this.userInfo.positionIds.length) {
        this.dataForm.applyPost = this.userInfo.positionIds.map(o => o.name).join(',')
      }
      this.loadPunchCandidates('[]')
    },
    loadPunchCandidates(savedPunchJson) {
      this.candidateLoading = true
      const saved = savedPunchJson !== undefined ? savedPunchJson : (this.dataForm.punchTargetsJson || '[]')
      let parsed = []
      try {
        parsed = JSON.parse(saved || '[]') || []
      } catch (e) {
        parsed = []
      }
      const readonly = !!(this.setting && this.setting.readonly)
      return getPunchApplyCandidates({}).then(res => {
        const list = res.data || []
        this.punchRows = list.map(x => ({
          date: x.date,
          statusText: x.statusText,
          missingPunchIn: x.missingPunchIn,
          missingPunchOut: x.missingPunchOut,
          _in: false,
          _out: false
        }))
        if (parsed.length) {
          parsed.forEach(p => {
            if (!p || !p.date) return
            const row = this.punchRows.find(r => r.date === p.date)
            if (row) {
              if (readonly) {
                row._in = !!p.punchIn
                row._out = !!p.punchOut
              } else {
                row._in = !!p.punchIn && row.missingPunchIn
                row._out = !!p.punchOut && row.missingPunchOut
              }
            }
          })
        }
        // 已保存的日期若已超出「当前近 3 日候选」窗口(如历史单回看),仍展示申请时勾选的补卡日
        const seen = new Set(this.punchRows.map(r => r.date))
        parsed.forEach(p => {
          if (!p || !p.date || seen.has(p.date)) return
          if (!p.punchIn && !p.punchOut) return
          seen.add(p.date)
          this.punchRows.push({
            date: p.date,
            statusText: '申请已选日期',
            missingPunchIn: !!p.punchIn,
            missingPunchOut: !!p.punchOut,
            _in: !!p.punchIn,
            _out: !!p.punchOut
          })
        })
        this.punchRows.sort((a, b) => String(b.date).localeCompare(String(a.date)))
        this.syncPunchJson()
      }).finally(() => {
        this.candidateLoading = false
      })
    },
    selfGetInfo() {
      Info(this.formApiKey, this.setting.id).then(res => {
        this.dataForm = res.data
        if (res.data.fileJson) {
          this.fileList = JSON.parse(res.data.fileJson)
        }
        const savedJson = this.dataForm.punchTargetsJson
        this.loadPunchCandidates(savedJson).then(() => {
          this.$emit('setPageLoad')
        })
      })
    },
    exist() {
      this.syncPunchJson()
      const ok = (this.punchRows || []).some(r => r._in || r._out)
      if (!ok) {
        this.$message.warning('请至少勾选一天的上班卡或下班卡')
        return false
      }
      return true
    },
    selfSubmit() {
      this.syncPunchJson()
      this.dataForm.status = this.eventType === 'submit' ? 0 : 1
      if (this.eventType === 'save') return this.selfHandleRequest()
      this.$confirm('确定提交补卡申请?审批通过后将按考勤组标准时间自动写入打卡。', '提示', { type: 'warning' }).then(() => {
        this.selfHandleRequest()
      }).catch(() => { })
    },
    selfHandleRequest() {
      this.syncPunchJson()
      if (!this.dataForm.id) delete this.dataForm.id
      if (this.eventType === 'save') this.$emit('setLoad', true)
      const formMethod = this.dataForm.id ? Update : Create
      formMethod(this.formApiKey, this.dataForm).then(res => {
        this.$message({
          message: res.msg, type: 'success', duration: 1500, onClose: () => {
            if (this.eventType === 'save') this.$emit('setLoad', false)
            this.$emit('close', true)
          }
        })
      }).catch(() => {
        if (this.eventType === 'save') this.$emit('setLoad', false)
      })
    }
  }
}
</script>

<style scoped>
.el-text-muted {
  color: #909399;
  font-size: 12px;
}
</style>