<template>
  <div class="leave-apply-page" v-loading="loading || quotaLoading">
    <div v-if="!flowBoxMode" class="page-head">
      <div>
        <div class="page-title">{{ currentSceneConfig.title }}</div>
        <div class="page-tip">{{ currentSceneConfig.tip }}</div>
      </div>
      <div class="page-actions">
        <el-button @click="handleBack">返回</el-button>
        <el-button type="warning" :loading="submitLoading && submitType === 'save'"
          @click="handleSubmit('save')">保存草稿</el-button>
        <el-button type="primary" :loading="submitLoading && submitType === 'submit'"
          @click="handleSubmit('submit')">提交申请</el-button>
      </div>
    </div>

    <el-alert v-if="!flowBoxMode && !dataForm.flowId" class="head-alert" type="warning" :closable="false"
      title="当前页面未携带 flowId，请从流程入口进入，或在地址后追加 ?flowId=流程ID 再提交。" show-icon />

    <div v-if="showSummaryPanel" class="summary-panel">
      <div class="summary-head">
        <div class="summary-title">{{ currentSceneConfig.summaryTitle }}</div>
        <el-button v-if="canFillMaxDays" type="text" @click="fillMaxDays">按可用上限填入天数</el-button>
      </div>
      <el-row :gutter="16">
        <el-col v-for="item in summaryCards" :key="item.key" :xs="24" :sm="12" :md="6">
          <div class="summary-card" :class="{ active: item.active }">
            <div class="summary-label">{{ item.label }}</div>
            <div class="summary-value">{{ item.value }}</div>
            <div v-if="item.desc" class="summary-desc">{{ item.desc }}</div>
          </div>
        </el-col>
      </el-row>
      <div v-if="leaveTypeSummaryText" class="summary-helper">{{ leaveTypeSummaryText }}</div>
    </div>

    <el-card shadow="never" class="form-card">
      <div slot="header" class="card-head">
        <span>申请信息</span>
        <span class="bill-no">单据号：{{ dataForm.billNo || '生成中...' }}</span>
      </div>
      <el-form ref="dataForm" :model="dataForm" :rules="dataRule" label-width="100px" :disabled="setting.readonly">
        <el-row :gutter="16">
          <el-col :span="12">
            <el-form-item label="流程标题" prop="flowTitle">
              <el-input v-model.trim="dataForm.flowTitle" maxlength="50" placeholder="请输入流程标题" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="紧急程度" prop="flowUrgent">
              <el-select v-model="dataForm.flowUrgent" placeholder="请选择紧急程度">
                <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 :span="12">
            <el-form-item label="申请人员">
              <el-input :value="dataForm.applyUser || '无'" readonly />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="申请日期">
              <el-date-picker v-model="dataForm.applyDate" type="date" value-format="timestamp" format="yyyy-MM-dd"
                readonly :editable="false" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="申请部门">
              <el-input :value="dataForm.applyDept || '无'" readonly />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="申请职位">
              <el-input :value="dataForm.applyPost || '无'" readonly />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item :label="currentSceneConfig.leaveTypeLabel" prop="leaveType">
              <el-radio-group v-model="dataForm.leaveType" @change="handleLeaveTypeChange">
                <el-radio v-for="item in leaveTypeOptions" :key="item.value" :label="item.value">{{ item.label
                }}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col v-if="isPaidScene && dataForm.leaveType === '丧假'" :span="24">
            <el-form-item label="丧假关系" prop="funeralRelationType">
              <el-radio-group v-model="dataForm.funeralRelationType">
                <el-radio :label="1">直系亲属</el-radio>
                <el-radio :label="2">非直系亲属</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="请假原因" prop="leaveReason">
              <el-input v-model.trim="dataForm.leaveReason" type="textarea" :rows="3" maxlength="300" show-word-limit
                :placeholder="currentSceneConfig.reasonPlaceholder" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="开始日期" prop="leaveStartTime">
              <el-date-picker v-model="leaveStartDateTs" type="date" value-format="timestamp" format="yyyy-MM-dd"
                :editable="false" placeholder="请选择开始日期" @change="recomputeLeaveRangeFromNaturalDay" />
            </el-form-item>
          </el-col>
          <el-col v-if="needsHalfPeriod" :span="12">
            <el-form-item label="半天为">
              <el-radio-group v-model="dayHalfPeriod" @change="recomputeLeaveRangeFromNaturalDay">
                <el-radio label="am">上午</el-radio>
                <el-radio label="pm">下午</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="结束时间">
              <el-input :value="leaveEndTimeDisplay" readonly placeholder="根据开始日期与请假天数自动计算" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <div v-if="isPaidScene" class="form-helper">带薪休假仅支持整天；请在下方下拉中选择 1～当前类型可用上限 的天数。</div>
            <div v-else-if="isRestScene" class="form-helper">应休请先选整数天；若有半天拆分额度，可勾选「再加半天」；含半天时请选择上/下午。</div>
            <div v-else-if="isPersonalScene" class="form-helper">事假、病假请在下方下拉中选择 1～10 天整数天；1 天按自然日 24 小时计。</div>
            <div v-else class="form-helper">1 天按自然日 24 小时计；请假天数支持整数或 0.5，含半天时请选择上/下午。</div>
          </el-col>
          <el-col :span="12">
            <el-form-item v-if="isPaidScene" label="请假天数" prop="leaveDayCount">
              <el-select v-model="dataForm.leaveDayCount" placeholder="请选择请假天数" clearable filterable
                @change="recomputeLeaveRangeFromNaturalDay">
                <el-option v-for="n in paidLeaveDaySelectOptions" :key="n" :label="`${n} 天`" :value="String(n)" />
              </el-select>
            </el-form-item>
            <el-form-item v-else-if="isRestScene" label="请假天数" prop="leaveDayCount">
              <div class="rest-days-admin">
                <el-select v-model.number="restFullDays" placeholder="整数天" class="rest-days-admin__full"
                  @change="syncRestLeaveDayToForm">
                  <el-option v-for="n in restFullDaySelectOptions" :key="n" :label="n === 0 ? '0 天（与半天组合）' : `${n} 天`"
                    :value="n" />
                </el-select>
                <el-checkbox v-if="restCanOfferHalfDay" v-model="restAddHalfDay" class="rest-days-admin__half"
                  :disabled="!restHalfChoiceEnabled" @change="syncRestLeaveDayToForm">再加半天</el-checkbox>
              </div>
            </el-form-item>
            <el-form-item v-else-if="isPersonalScene" label="请假天数" prop="leaveDayCount">
              <el-select v-model="dataForm.leaveDayCount" placeholder="请选择请假天数" clearable filterable
                @change="recomputeLeaveRangeFromNaturalDay">
                <el-option v-for="n in personalLeaveDaySelectOptions" :key="n" :label="`${n} 天`" :value="String(n)" />
              </el-select>
            </el-form-item>
            <el-form-item v-else label="请假天数" prop="leaveDayCount">
              <el-input v-model.trim="dataForm.leaveDayCount" placeholder="请输入请假天数"
                @input="recomputeLeaveRangeFromNaturalDay" @blur="recomputeLeaveRangeFromNaturalDay">
                <template slot="append">天</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="请假小时" prop="leaveHour">
              <el-input v-model.trim="dataForm.leaveHour" placeholder="请输入请假小时">
                <template slot="append">小时</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="相关附件" prop="fileJson">
              <NCC-UploadFz v-model="fileList" type="workFlow" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import { BillNumber } from '@/api/system/billRule'
import { Info, Create, Update, QuotaSummary } from '@/api/workFlow/workFlowForm'
import { computeLeaveRangeNaturalDay } from '@/utils/leave-calendar-range'

const REST_SCENE = 'rest'
const PERSONAL_SCENE = 'personal'
const PAID_SCENE = 'paid'

const createDefaultForm = () => ({
  id: '',
  flowId: '',
  billNo: '',
  flowTitle: '',
  flowUrgent: 1,
  applyUser: '',
  applyDate: '',
  applyDept: '',
  applyPost: '',
  leaveType: '',
  leaveReason: '',
  funeralRelationType: 1,
  leaveStartTime: '',
  leaveEndTime: '',
  leaveDayCount: '',
  leaveHour: '',
  fileJson: ''
})

export default {
  name: 'LeaveApplyPage',
  props: {
    scene: {
      type: String,
      default: REST_SCENE
    }
  },
  data() {
    const checkLeaveRangeComputed = (rule, value, callback) => {
      if (!this.leaveStartDateTs) return callback(new Error('请选择开始日期'))
      const days = Number(this.dataForm.leaveDayCount || 0)
      if (!days || days <= 0) {
        if (this.isPaidScene) return callback(new Error('请选择请假天数'))
        if (this.isRestScene) return callback(new Error('请选择请假天数（整数天，必要时勾选再加半天）'))
        if (this.isPersonalScene) return callback(new Error('请选择请假天数'))
        return callback(new Error('请输入请假天数'))
      }
      if (this.isPaidScene) {
        if (Math.floor(days) !== days) return callback(new Error('带薪休假仅可选择整天'))
      } else if (this.isPersonalScene) {
        if (Math.floor(days) !== days || days < 1 || days > 10) {
          return callback(new Error('请选择 1～10 天整数天'))
        }
      } else if (Math.round(days * 2) !== days * 2) {
        return callback(new Error('请假天数必须是整数或 0.5 的倍数'))
      }
      if (!this.dataForm.leaveStartTime || !this.dataForm.leaveEndTime) {
        return callback(new Error('请确认开始日期与请假天数，系统将自动计算起止时刻'))
      }
      callback()
    }
    const checkLeaveDayCount = (rule, value, callback) => {
      if (value === '' || value === null || value === undefined) {
        if (this.isPaidScene) return callback(new Error('请选择请假天数'))
        if (this.isRestScene) return callback(new Error('请选择请假天数（整数天，必要时勾选再加半天）'))
        if (this.isPersonalScene) return callback(new Error('请选择请假天数'))
        return callback(new Error('请输入请假天数'))
      }
      const num = Number(value)
      if (!num || num <= 0) return callback(new Error('请假天数必须大于 0'))
      if (this.isPaidScene) {
        if (Math.floor(num) !== num) return callback(new Error('带薪休假仅可选择整天'))
        const max = this.paidLeaveMaxInteger
        if (max <= 0) return callback(new Error('当前假期类型暂无可选天数'))
        if (num > max) return callback(new Error(`最多可选 ${max} 天`))
        return callback()
      }
      if (this.isRestScene) {
        if (Math.round(num * 2) !== num * 2) return callback(new Error('请假天数必须是整数或 0.5 天'))
        const max = this.restMaxAvailableDays
        if (num > max) return callback(new Error(`最多可申请 ${this.formatNumber(max)} 天`))
        const splitNeed = num - Math.floor(num)
        if (splitNeed > this.restRemainingHalfSplit + 1e-9) {
          return callback(new Error('半天拆分额度不足'))
        }
        return callback()
      }
      if (this.isPersonalScene) {
        if (Math.floor(num) !== num) return callback(new Error('事假、病假须选择整数天'))
        if (num < 1 || num > 10) return callback(new Error('事假、病假可选择 1～10 天'))
        return callback()
      }
      if (Math.round(num * 2) !== num * 2) return callback(new Error('请假天数必须是整数或 0.5 的倍数'))
      callback()
    }
    const checkLeaveHour = (rule, value, callback) => {
      if (value === '' || value === null || value === undefined) return callback(new Error(rule.message))
      const num = Number(value)
      if (!num || num <= 0) return callback(new Error('请假小时必须大于 0'))
      if (this.isPaidScene || this.isPersonalScene) {
        if (Math.floor(num) !== num) return callback(new Error('请假小时须为整数'))
        return callback()
      }
      if (Math.round(num * 2) !== num * 2) return callback(new Error('请假小时必须是整数或 0.5 的倍数'))
      callback()
    }
    const checkFuneralRelationType = (rule, value, callback) => {
      if (!this.isPaidScene || this.dataForm.leaveType !== '丧假') return callback()
      if (![1, 2].includes(Number(value))) return callback(new Error('请选择丧假关系'))
      callback()
    }
    return {
      loading: false,
      quotaLoading: false,
      submitLoading: false,
      submitType: '',
      applicantName: '',
      fileList: [],
      quotaSummary: null,
      flowBoxMode: false,
      setting: {},
      leaveStartDateTs: '',
      dayHalfPeriod: 'am',
      restFullDays: 0,
      restAddHalfDay: false,
      flowUrgentOptions: [
        { value: 1, label: '普通' },
        { value: 2, label: '重要' },
        { value: 3, label: '紧急' }
      ],
      sceneConfigMap: {
        [REST_SCENE]: {
          title: '休假申请',
          tip: '当前页用于发起每月应休天数的休假申请。',
          summaryTitle: '本月休假额度',
          leaveTypeLabel: '休假类别',
          reasonPlaceholder: '请输入休假原因',
          defaultLeaveType: '休假',
          leaveTypeOptions: [{ value: '休假', label: '休假' }]
        },
        [PERSONAL_SCENE]: {
          title: '事假申请',
          tip: '当前页用于发起事假、病假申请。',
          summaryTitle: '请假说明',
          leaveTypeLabel: '请假类别',
          reasonPlaceholder: '请输入事假/病假原因',
          defaultLeaveType: '事假',
          leaveTypeOptions: [
            { value: '事假', label: '事假' },
            { value: '病假', label: '病假' }
          ]
        },
        [PAID_SCENE]: {
          title: '带薪休假',
          tip: '当前页用于发起婚假、丧假、年假、产假申请。',
          summaryTitle: '带薪休假额度',
          leaveTypeLabel: '带薪休假类别',
          reasonPlaceholder: '请输入带薪休假原因',
          defaultLeaveType: '婚假',
          leaveTypeOptions: [
            { value: '婚假', label: '婚假' },
            { value: '丧假', label: '丧假' },
            { value: '年假', label: '年假' },
            { value: '产假', label: '产假' }
          ]
        }
      },
      dataForm: createDefaultForm(),
      dataRule: {
        flowTitle: [{ required: true, message: '请输入流程标题', trigger: 'blur' }],
        flowUrgent: [{ required: true, message: '请选择紧急程度', trigger: 'change' }],
        leaveType: [{ required: true, message: '请选择请假类别', trigger: 'change' }],
        leaveReason: [{ required: true, message: '请输入请假原因', trigger: 'blur' }],
        funeralRelationType: [{ validator: checkFuneralRelationType, trigger: 'change' }],
        leaveStartTime: [{ validator: checkLeaveRangeComputed, trigger: 'change' }],
        leaveDayCount: [{ validator: checkLeaveDayCount, trigger: 'change' }],
        leaveHour: [{ validator: checkLeaveHour, message: '请输入请假小时', trigger: 'blur' }]
      }
    }
  },
  computed: {
    ...mapGetters(['userInfo']),
    currentSceneConfig() {
      return this.sceneConfigMap[this.scene] || this.sceneConfigMap[REST_SCENE]
    },
    isRestScene() {
      return this.scene === REST_SCENE
    },
    isPersonalScene() {
      return this.scene === PERSONAL_SCENE
    },
    isPaidScene() {
      return this.scene === PAID_SCENE
    },
    showSummaryPanel() {
      return this.isRestScene || this.isPaidScene
    },
    restQuota() {
      var q = this.quotaSummary || {}
      var r = q.rest || q.Rest
      if (!r || typeof r !== 'object') return {}
      return {
        ...r,
        workedDaysThisMonth: r.workedDaysThisMonth != null ? r.workedDaysThisMonth : (r.WorkedDaysThisMonth != null ? r.WorkedDaysThisMonth : 0),
        restUnlockCycle: r.restUnlockCycle != null ? r.restUnlockCycle : (r.RestUnlockCycle != null ? r.RestUnlockCycle : 0),
        unlockedRestDays: r.unlockedRestDays != null ? r.unlockedRestDays : (r.UnlockedRestDays != null ? r.UnlockedRestDays : 0),
        availableRestDays: r.availableRestDays != null ? r.availableRestDays : (r.AvailableRestDays != null ? r.AvailableRestDays : 0)
      }
    },
    paidQuota() {
      const q = this.quotaSummary || {}
      const paid = q.paid || q.Paid
      if (!paid || typeof paid !== 'object') {
        return { marriage: {}, funeral: {}, annual: {}, maternity: {}, extraLeaves: [] }
      }
      const m = paid.marriage || paid.Marriage || {}
      const f = paid.funeral || paid.Funeral || {}
      const a = paid.annual || paid.Annual || {}
      const mat = paid.maternity || paid.Maternity || {}
      const exRaw = paid.extraLeaves || paid.ExtraLeaves
      let exArr = []
      if (Array.isArray(exRaw)) exArr = exRaw
      else if (exRaw && typeof exRaw === 'object') exArr = Object.values(exRaw)
      var extraLeaves = exArr.map(function (x, idx) {
        return {
          id: x.id || x.Id || ('extra-' + idx),
          leaveName: String(x.leaveName || x.LeaveName || '').trim(),
          grantYear: x.grantYear != null ? x.grantYear : x.GrantYear,
          extraDays: Number(x.extraDays != null ? x.extraDays : (x.ExtraDays != null ? x.ExtraDays : 0))
        }
      }).filter(function (x) { return x.leaveName })
      return {
        marriage: {
          matched: m.matched != null ? m.matched : m.Matched,
          maxDays: Number(m.maxDays != null ? m.maxDays : (m.MaxDays != null ? m.MaxDays : 0))
        },
        funeral: {
          matched: f.matched != null ? f.matched : f.Matched,
          directRelativeDays: Number(f.directRelativeDays != null ? f.directRelativeDays : (f.DirectRelativeDays != null ? f.DirectRelativeDays : 0)),
          indirectRelativeDays: Number(f.indirectRelativeDays != null ? f.indirectRelativeDays : (f.IndirectRelativeDays != null ? f.IndirectRelativeDays : 0))
        },
        annual: {
          matched: a.matched != null ? a.matched : a.Matched,
          totalDays: Number(a.totalDays != null ? a.totalDays : (a.TotalDays != null ? a.TotalDays : 0)),
          usedDays: Number(a.usedDays != null ? a.usedDays : (a.UsedDays != null ? a.UsedDays : 0)),
          remainingDays: Number(a.remainingDays != null ? a.remainingDays : (a.RemainingDays != null ? a.RemainingDays : 0))
        },
        maternity: {
          matched: mat.matched != null ? mat.matched : mat.Matched,
          maxDays: Number(mat.maxDays != null ? mat.maxDays : (mat.MaxDays != null ? mat.MaxDays : 0))
        },
        extraLeaves: extraLeaves
      }
    },
    extraLeaveList() {
      return Array.isArray(this.paidQuota.extraLeaves) ? this.paidQuota.extraLeaves : []
    },
    leaveTypeOptions() {
      const baseOptions = this.currentSceneConfig.leaveTypeOptions || []
      if (!this.isPaidScene || !this.extraLeaveList.length) return baseOptions
      const extraOptions = this.extraLeaveList.map(item => {
        const nm = String(item.leaveName || '').trim()
        const gy = item.grantYear
        const label = nm && gy != null && gy !== '' ? `${nm}（${gy}年）` : nm
        return { value: nm, label }
      })
      return [...baseOptions, ...extraOptions]
    },
    summaryCards() {
      if (this.isRestScene) {
        const rest = this.restQuota
        const unlockEnabled = rest.restUnlockCycle > 0
        const remainValue = unlockEnabled ? (rest.availableRestDays || 0) : (rest.remainingRestDays || 0)
        const remainDesc = unlockEnabled ? `已解锁 ${rest.unlockedRestDays || 0} 天` : '天'
        const cards = [
          { key: 'total', label: '本月应休', value: this.formatNumber(rest.monthlyRestDays || 0), desc: '天' },
          { key: 'used', label: '已申请', value: this.formatNumber(rest.usedRestDays || 0), desc: '天' },
          { key: 'remain', label: '剩余可休', value: this.formatNumber(remainValue), desc: remainDesc, active: true },
          { key: 'split', label: '半天额度', value: this.formatNumber(rest.remainingHalfDaySplitDays || 0), desc: `还能拆 ${rest.remainingHalfDaySelections || 0} 次半天` }
        ]
        if (unlockEnabled) {
          cards.push({
            key: 'worked',
            label: '本月已上班',
            value: `${rest.workedDaysThisMonth || 0} 天`,
            desc: `每${rest.restUnlockCycle}天解锁1天`
          })
        }
        return cards
      }
      if (this.isPersonalScene) {
        return [
          { key: 'personal', label: '可申请类型', value: '事假 / 病假', desc: '1～10 天可选', active: true }
        ]
      }
      const extraTotalDays = this.extraLeaveList.reduce((sum, item) => sum + Number(item.extraDays || 0), 0)
      const sel = String(this.dataForm.leaveType || '').trim()
      const extraTypeSelected = this.extraLeaveList.some(item => String(item.leaveName || '').trim() === sel)
      return [
        { key: 'marriage', label: '婚假', value: `${this.formatNumber((this.paidQuota.marriage || {}).maxDays || 0)} 天`, active: this.dataForm.leaveType === '婚假' },
        { key: 'funeral', label: '丧假', value: `${this.formatNumber((this.paidQuota.funeral || {}).directRelativeDays || 0)} / ${this.formatNumber((this.paidQuota.funeral || {}).indirectRelativeDays || 0)} 天`, desc: '直系 / 非直系', active: this.dataForm.leaveType === '丧假' },
        { key: 'annual', label: '年假剩余', value: `${this.formatNumber((this.paidQuota.annual || {}).remainingDays || 0)} 天`, desc: `总额 ${this.formatNumber((this.paidQuota.annual || {}).totalDays || 0)} 天`, active: this.dataForm.leaveType === '年假' },
        { key: 'maternity', label: '产假', value: `${this.formatNumber((this.paidQuota.maternity || {}).maxDays || 0)} 天`, desc: '按后台规则', active: this.dataForm.leaveType === '产假' },
        { key: 'extra', label: '额外假期总额', value: `${this.formatNumber(extraTotalDays)} 天`, active: extraTypeSelected }
      ]
    },
    leaveTypeSummaryText() {
      if (this.isRestScene) {
        const rest = this.restQuota
        if (!rest.attendanceGroupBound) return '当前用户还未绑定考勤分组，暂时无法计算本月休假额度。'
        if (rest.restUnlockCycle > 0) {
          const worked = rest.workedDaysThisMonth || 0
          const cycle = rest.restUnlockCycle
          const unlocked = rest.unlockedRestDays || 0
          const available = rest.availableRestDays || 0
          const daysInCurrentCycle = worked % cycle
          const nextNeed = daysInCurrentCycle === 0 ? cycle : cycle - daysInCurrentCycle
          const canUnlockMore = unlocked < (rest.monthlyRestDays || 0)
          let text = `本月已上班 ${worked} 天，已解锁 ${unlocked} 天应休，当前可申请 ${available} 天。`
          if (canUnlockMore && nextNeed > 0) {
            text += `再上满 ${nextNeed} 天可再解锁 1 天。`
          }
          return text
        }
        return `当前分组【${rest.attendanceGroupName || '未命名分组'}】本月还可休 ${this.formatNumber(rest.remainingRestDays || 0)} 天；其中还能拆分半天 ${this.formatNumber(rest.remainingHalfDaySplitDays || 0)} 天。`
      }
      if (this.isPersonalScene) return '事假、病假不限制后台额度；请假天数请在下拉中选择 1～10 天整数天；1 天按自然日 24 小时计。'
      if (this.dataForm.leaveType === '婚假') {
        const maxDays = Number((this.paidQuota.marriage || {}).maxDays || 0)
        return maxDays > 0 ? `按当前司龄规则，本次婚假最多可请 ${this.formatNumber(maxDays)} 天。` : '当前未匹配到婚假规则，请先联系管理员维护规则。'
      }
      if (this.dataForm.leaveType === '丧假') {
        const funeral = this.paidQuota.funeral || {}
        const currentDays = Number(Number(this.dataForm.funeralRelationType) === 1 ? funeral.directRelativeDays : funeral.indirectRelativeDays) || 0
        return `当前丧假规则：直系亲属 ${this.formatNumber(funeral.directRelativeDays || 0)} 天，非直系亲属 ${this.formatNumber(funeral.indirectRelativeDays || 0)} 天；当前选择最多可请 ${this.formatNumber(currentDays)} 天。`
      }
      if (this.dataForm.leaveType === '年假') {
        const annual = this.paidQuota.annual || {}
        return `本年年假总额 ${this.formatNumber(annual.totalDays || 0)} 天，已申请 ${this.formatNumber(annual.usedDays || 0)} 天，剩余 ${this.formatNumber(annual.remainingDays || 0)} 天。`
      }
      if (this.dataForm.leaveType === '产假') {
        const maternity = this.paidQuota.maternity || {}
        return Number(maternity.maxDays || 0) > 0 ? `按当前司龄规则，本次产假最多可请 ${this.formatNumber(maternity.maxDays || 0)} 天。` : '当前未匹配到产假规则，请先联系管理员维护规则。'
      }
      const matchedExtraLeave = this.extraLeaveList.find(item => String(item.leaveName || '').trim() === String(this.dataForm.leaveType || '').trim())
      if (matchedExtraLeave) {
        return `当前额外假期【${matchedExtraLeave.leaveName}】最多可请 ${this.formatNumber(matchedExtraLeave.extraDays || 0)} 天。`
      }
      return ''
    },
    selectedLeaveMaxDays() {
      if (this.isRestScene) {
        const rest = this.restQuota
        return rest.restUnlockCycle > 0
          ? Number(rest.availableRestDays || 0)
          : Number(rest.remainingRestDays || 0)
      }
      if (!this.isPaidScene) return null
      if (this.dataForm.leaveType === '婚假') return Number((this.paidQuota.marriage || {}).maxDays || 0)
      if (this.dataForm.leaveType === '丧假') return Number(Number(this.dataForm.funeralRelationType) === 1 ? (this.paidQuota.funeral || {}).directRelativeDays || 0 : (this.paidQuota.funeral || {}).indirectRelativeDays || 0)
      if (this.dataForm.leaveType === '年假') return Number((this.paidQuota.annual || {}).remainingDays || 0)
      if (this.dataForm.leaveType === '产假') return Number((this.paidQuota.maternity || {}).maxDays || 0)
      const matchedExtraLeave = this.extraLeaveList.find(item => String(item.leaveName || '').trim() === String(this.dataForm.leaveType || '').trim())
      if (matchedExtraLeave) return Number(matchedExtraLeave.extraDays || 0)
      return null
    },
    canFillMaxDays() {
      if (this.isPaidScene) return false
      return this.selectedLeaveMaxDays !== null && this.selectedLeaveMaxDays > 0
    },
    paidLeaveMaxInteger() {
      if (!this.isPaidScene) return 0
      const raw = Number(this.selectedLeaveMaxDays)
      if (this.selectedLeaveMaxDays === null || this.selectedLeaveMaxDays === undefined || Number.isNaN(raw)) {
        return 0
      }
      return Math.max(0, Math.floor(raw))
    },
    paidLeaveDaySelectOptions() {
      const max = this.paidLeaveMaxInteger
      if (!this.isPaidScene || max <= 0) return []
      return Array.from({ length: max }, (_, i) => i + 1)
    },
    /** 事假/病假：固定 1～10 天 */
    personalLeaveDaySelectOptions() {
      if (!this.isPersonalScene) return []
      return Array.from({ length: 10 }, (_, i) => i + 1)
    },
    restMaxAvailableDays() {
      if (!this.isRestScene) return 0
      return Number(this.selectedLeaveMaxDays || 0)
    },
    restRemainingHalfSplit() {
      if (!this.isRestScene) return 0
      return Number(this.restQuota.remainingHalfDaySplitDays || 0)
    },
    restCanOfferHalfDay() {
      return this.isRestScene && this.restRemainingHalfSplit >= 0.5
    },
    restFullDayMax() {
      return Math.max(0, Math.floor(this.restMaxAvailableDays))
    },
    restFullDaySelectOptions() {
      if (!this.isRestScene) return []
      const m = this.restFullDayMax
      return Array.from({ length: m + 1 }, (_, i) => i)
    },
    restHalfChoiceEnabled() {
      if (!this.restCanOfferHalfDay) return false
      return this.restFullDays + 0.5 <= this.restMaxAvailableDays + 1e-9
    },
    restAddHalfDayRequired() {
      return this.isRestScene && this.restMaxAvailableDays > 0 && this.restFullDays === 0 && this.restHalfChoiceEnabled
    },
    needsHalfPeriod() {
      if (this.isPaidScene || this.isPersonalScene) return false
      const d = Number(this.dataForm.leaveDayCount || 0)
      if (!d || Math.round(d * 2) !== d * 2) return false
      return Math.round(d * 2) % 2 === 1
    },
    leaveEndTimeDisplay() {
      const raw = this.dataForm.leaveEndTime
      if (raw === '' || raw == null) return ''
      const t = Number(raw)
      if (Number.isNaN(t) || !t) return ''
      const d = new Date(t)
      if (Number.isNaN(d.getTime())) return ''
      const y = d.getFullYear()
      const m = `${d.getMonth() + 1}`.padStart(2, '0')
      const day = `${d.getDate()}`.padStart(2, '0')
      const hh = `${d.getHours()}`.padStart(2, '0')
      const mm = `${d.getMinutes()}`.padStart(2, '0')
      return `${y}-${m}-${day} ${hh}:${mm}`
    }
  },
  created() {
    if (!this.flowBoxMode) this.initializePage()
  },
  watch: {
    '$route.query': {
      deep: true,
      handler() {
        if (!this.flowBoxMode) this.initializePage()
      }
    },
    'dataForm.leaveType'(value) {
      if (value === '丧假' && ![1, 2].includes(Number(this.dataForm.funeralRelationType))) {
        this.dataForm.funeralRelationType = 1
      }
      if (value !== '丧假') this.dataForm.funeralRelationType = 1
      if (this.isPaidScene || this.isPersonalScene) {
        this.dataForm.leaveDayCount = ''
        this.$nextTick(() => this.recomputeLeaveRangeFromNaturalDay())
      }
      this.refreshFlowTitle()
    },
    'dataForm.funeralRelationType'() {
      if (!this.isPaidScene || this.dataForm.leaveType !== '丧假') return
      this.dataForm.leaveDayCount = ''
      this.$nextTick(() => this.recomputeLeaveRangeFromNaturalDay())
    },
    restCanOfferHalfDay(val) {
      if (!val && this.isRestScene) {
        this.restAddHalfDay = false
        this.syncRestLeaveDayToForm()
      }
    }
  },
  methods: {
    init(data) {
      this.flowBoxMode = true
      this.setting = data || {}
      this.leaveStartDateTs = ''
      this.dayHalfPeriod = 'am'
      this.restFullDays = 0
      this.restAddHalfDay = false
      this.dataForm = createDefaultForm()
      this.dataForm.id = data.id || ''
      this.dataForm.flowId = data.flowId || ''
      this.dataForm.leaveType = this.currentSceneConfig.defaultLeaveType
      this.$nextTick(() => {
        if (this.$refs.dataForm) this.$refs.dataForm.resetFields()
        this.fileList = []
        this.quotaSummary = null
        this.fillApplicantInfo()
        var done = () => {
          this.loadQuotaSummary().then(() => {
            if (this.isPaidScene) {
              this.clampPaidLeaveDayForScene()
            } else if (this.isRestScene) {
              this.applyRestUiFromLeaveDayCount()
            } else if (this.isPersonalScene) {
              this.clampPersonalLeaveDayForScene()
            }
            this.recomputeLeaveRangeFromNaturalDay()
            this.$emit('setPageLoad')
          })
        }
        if (data.id) {
          Info('leaveApply', data.id).then((res) => {
            this.dataForm = Object.assign(createDefaultForm(), res.data || {})
            if (!this.dataForm.flowId && data.flowId) this.dataForm.flowId = data.flowId
            if (this.dataForm.fileJson) {
              try { this.fileList = JSON.parse(this.dataForm.fileJson) } catch (e) { this.fileList = [] }
            }
            this.syncLeaveStartDateFromStoredTimes()
            done()
          }).catch(() => { done() })
        } else {
          BillNumber('WF_LeaveApplyNo').then((res) => {
            this.dataForm.billNo = (res && res.data) || ''
            done()
          }).catch(() => { done() })
        }
      })
    },
    dataFormSubmit(eventType) {
      this.$refs.dataForm.validate((valid) => {
        if (!valid) return
        // 流程待办里点「通过/拒绝」时，额度接口是当前登录人（如 admin）的，与申请人无关，不能据此拦截
        const skipBizForApproval = this.flowBoxMode && (eventType === 'audit' || eventType === 'reject')
        if (!skipBizForApproval) {
          var error = this.validateBusinessRule()
          if (error) {
            this.$message.error(error)
            return
          }
        }
        var payload = Object.assign({}, this.dataForm, {
          flowUrgent: Number(this.dataForm.flowUrgent || 1),
          funeralRelationType: this.dataForm.leaveType === '丧假' ? Number(this.dataForm.funeralRelationType || 0) : null,
          leaveReason: (this.dataForm.leaveReason || '').trim(),
          fileJson: this.fileList && this.fileList.length ? JSON.stringify(this.fileList) : ''
        })
        this.$emit('eventReciver', payload, eventType)
      })
    },
    async initializePage() {
      const { id = '', flowId = '' } = this.$route.query || {}
      const currentKey = `${this.scene}_${id}_${flowId}`
      if (this._pageInitKey === currentKey) return
      this._pageInitKey = currentKey
      this.loading = true
      this.fileList = []
      this.quotaSummary = null
      this.leaveStartDateTs = ''
      this.dayHalfPeriod = 'am'
      this.restFullDays = 0
      this.restAddHalfDay = false
      this.dataForm = createDefaultForm()
      this.dataForm.flowId = flowId || ''
      this.dataForm.leaveType = this.currentSceneConfig.defaultLeaveType
      this.fillApplicantInfo()
      try {
        await Promise.all([this.loadQuotaSummary(), id ? this.loadInfo(id) : this.loadBillNo()])
      } finally {
        this.loading = false
        if (this.isRestScene) {
          this.applyRestUiFromLeaveDayCount()
        } else if (this.isPersonalScene) {
          this.clampPersonalLeaveDayForScene()
        }
        this.recomputeLeaveRangeFromNaturalDay()
      }
    },
    fillApplicantInfo() {
      const name = this.userInfo.userName || this.userInfo.realName || '当前用户'
      const account = this.userInfo.userAccount || ''
      this.applicantName = name
      this.dataForm.applyUser = account ? `${name}/${account}` : name
      this.dataForm.applyDate = new Date().getTime()
      this.dataForm.applyDept = this.userInfo.organizeName || ''
      this.dataForm.applyPost = this.getPositionText()
      this.refreshFlowTitle()
    },
    getPositionText() {
      const positions = this.userInfo.positionIds
      if (!Array.isArray(positions) || !positions.length) return this.userInfo.positionName || ''
      return positions.map(item => item && item.name).filter(Boolean).join('、')
    },
    refreshFlowTitle() {
      if (!this.applicantName || this.dataForm.id) return
      const leaveType = this.dataForm.leaveType || this.currentSceneConfig.title
      this.dataForm.flowTitle = `${this.applicantName}的${leaveType}申请`
    },
    async loadBillNo() {
      const res = await BillNumber('WF_LeaveApplyNo')
      this.dataForm.billNo = (res && res.data) || ''
    },
    async loadInfo(id) {
      const res = await Info('leaveApply', id)
      this.dataForm = Object.assign(createDefaultForm(), res.data || {})
      if (!this.dataForm.flowId && this.$route.query.flowId) this.dataForm.flowId = this.$route.query.flowId
      if (this.dataForm.fileJson) {
        try {
          this.fileList = JSON.parse(this.dataForm.fileJson)
        } catch (e) {
          this.fileList = []
        }
      }
      this.syncLeaveStartDateFromStoredTimes()
      if (this.isPaidScene) {
        this.clampPaidLeaveDayForScene()
      } else if (this.isPersonalScene) {
        this.clampPersonalLeaveDayForScene()
      }
    },
    async loadQuotaSummary() {
      this.quotaLoading = true
      try {
        const res = await QuotaSummary()
        this.quotaSummary = (res && res.data) || {}
      } finally {
        this.quotaLoading = false
      }
    },
    handleLeaveTypeChange(value) {
      this.dataForm.leaveType = value
      this.$nextTick(() => {
        this.$refs.dataForm && this.$refs.dataForm.clearValidate('funeralRelationType')
      })
    },
    tsToYmd(ts) {
      if (ts === '' || ts == null) return ''
      const d = new Date(Number(ts))
      if (Number.isNaN(d.getTime())) return ''
      const y = d.getFullYear()
      const m = `${d.getMonth() + 1}`.padStart(2, '0')
      const day = `${d.getDate()}`.padStart(2, '0')
      return `${y}-${m}-${day}`
    },
    parseLocalYmdHmsToTs(str) {
      if (!str) return ''
      const d = new Date(String(str).replace(/-/g, '/'))
      if (Number.isNaN(d.getTime())) return ''
      return d.getTime()
    },
    syncLeaveStartDateFromStoredTimes() {
      if (!this.dataForm.leaveStartTime) {
        this.leaveStartDateTs = ''
        return
      }
      const t = Number(this.dataForm.leaveStartTime)
      if (!t || Number.isNaN(t)) {
        this.leaveStartDateTs = ''
        return
      }
      const orig = new Date(t)
      const mid = new Date(orig.getFullYear(), orig.getMonth(), orig.getDate())
      this.leaveStartDateTs = mid.getTime()
      this.dayHalfPeriod = this.isPaidScene ? 'am' : (orig.getHours() >= 12 ? 'pm' : 'am')
    },
    /** 带薪假编辑加载时：非整数天或超上限时收敛为合法整天 */
    clampPaidLeaveDayForScene() {
      if (!this.isPaidScene) return
      const max = this.paidLeaveMaxInteger
      if (max <= 0) {
        this.dataForm.leaveDayCount = ''
        return
      }
      const d = Number(this.dataForm.leaveDayCount || 0)
      if (!d) return
      let n = Math.floor(d)
      if (n < 1) n = 1
      if (n > max) n = max
      if (Math.floor(d) !== d || d > max || d < 1) {
        this.dataForm.leaveDayCount = String(n)
      }
    },
    /** 事假/病假编辑加载时：收敛为 1～10 整数天 */
    clampPersonalLeaveDayForScene() {
      if (!this.isPersonalScene) return
      const d = Number(this.dataForm.leaveDayCount || 0)
      if (!d) return
      let n = Math.floor(d)
      if (n < 1) n = 1
      if (n > 10) n = 10
      if (Math.floor(d) !== d || d > 10 || d < 1) {
        this.dataForm.leaveDayCount = String(n)
      }
    },
    recomputeLeaveRangeFromNaturalDay() {
      const days = Number(this.dataForm.leaveDayCount || 0)
      const daysInvalid = !days || days <= 0
        || (this.isPaidScene ? Math.floor(days) !== days
          : this.isPersonalScene ? (Math.floor(days) !== days || days < 1 || days > 10)
            : Math.round(days * 2) !== days * 2)
      if (!this.leaveStartDateTs || daysInvalid) {
        this.dataForm.leaveStartTime = ''
        this.dataForm.leaveEndTime = ''
        this.dataForm.leaveHour = ''
        return
      }
      const startDateStr = this.tsToYmd(this.leaveStartDateTs)
      if (!startDateStr) {
        this.dataForm.leaveStartTime = ''
        this.dataForm.leaveEndTime = ''
        this.dataForm.leaveHour = ''
        return
      }
      const { leaveStartTime, leaveEndTime, leaveHour } = computeLeaveRangeNaturalDay(
        startDateStr,
        days,
        this.dayHalfPeriod
      )
      this.dataForm.leaveStartTime = this.parseLocalYmdHmsToTs(leaveStartTime)
      this.dataForm.leaveEndTime = this.parseLocalYmdHmsToTs(leaveEndTime)
      this.dataForm.leaveHour = leaveHour
      this.$nextTick(() => {
        if (this.$refs.dataForm) this.$refs.dataForm.validateField('leaveStartTime')
      })
    },
    formatNumber(value) {
      const num = Number(value || 0)
      return Number.isInteger(num) ? String(num) : num.toFixed(1)
    },
    fillMaxDays() {
      if (this.isRestScene) {
        this.fillMaxRestDays()
        return
      }
      const maxDays = Number(this.selectedLeaveMaxDays || 0)
      if (maxDays <= 0) return
      this.dataForm.leaveDayCount = this.formatNumber(maxDays)
      this.$nextTick(() => this.recomputeLeaveRangeFromNaturalDay())
    },
    fillMaxRestDays() {
      const max = this.restMaxAvailableDays
      const split = this.restRemainingHalfSplit
      const opts = this.restFullDaySelectOptions
      if (!opts.length) return
      const bestFull = Math.floor(max)
      const full = opts.indexOf(bestFull) >= 0 ? bestFull : opts[opts.length - 1]
      this.restFullDays = full
      this.restAddHalfDay = split >= 0.5 && full + 0.5 <= max + 1e-9
      if (!this.restHalfChoiceEnabled) this.restAddHalfDay = false
      this.syncRestLeaveDayToForm()
    },
    syncRestLeaveDayToForm() {
      if (!this.isRestScene) return
      if (this.restFullDays > this.restFullDayMax) this.restFullDays = this.restFullDayMax
      if (!this.restCanOfferHalfDay) this.restAddHalfDay = false
      if (this.restAddHalfDay && !this.restHalfChoiceEnabled) this.restAddHalfDay = false
      const full = this.restFullDays
      const total = full + (this.restAddHalfDay ? 0.5 : 0)
      if (total <= 0) {
        this.dataForm.leaveDayCount = ''
        this.recomputeLeaveRangeFromNaturalDay()
        return
      }
      if (total > this.restMaxAvailableDays + 1e-9) {
        this.dataForm.leaveDayCount = ''
        this.recomputeLeaveRangeFromNaturalDay()
        return
      }
      const splitNeed = total - Math.floor(total)
      if (splitNeed > this.restRemainingHalfSplit + 1e-9) {
        this.dataForm.leaveDayCount = ''
        this.recomputeLeaveRangeFromNaturalDay()
        return
      }
      this.dataForm.leaveDayCount = total % 1 === 0 ? String(total) : String(total.toFixed(1))
      this.recomputeLeaveRangeFromNaturalDay()
      this.$nextTick(() => {
        if (this.$refs.dataForm) {
          this.$refs.dataForm.validateField('leaveDayCount')
          this.$refs.dataForm.validateField('leaveStartTime')
        }
      })
    },
    applyRestUiFromLeaveDayCount() {
      if (!this.isRestScene) return
      const d = Number(this.dataForm.leaveDayCount || 0)
      if (!d || d <= 0) {
        this.restFullDays = 0
        this.restAddHalfDay = false
        this.syncRestLeaveDayToForm()
        return
      }
      const cap = this.restFullDayMax
      let full = Math.min(Math.floor(d), cap)
      let half = d - Math.floor(d) >= 0.5
      this.restFullDays = full
      if (!this.restCanOfferHalfDay) half = false
      if (half && full + 0.5 > this.restMaxAvailableDays + 1e-9) half = false
      this.restAddHalfDay = half
      this.syncRestLeaveDayToForm()
    },
    getRequestDays() {
      return Number(this.dataForm.leaveDayCount || 0)
    },
    getHalfDaySplitDays(days) {
      const value = Number(days || 0)
      return value - Math.floor(value)
    },
    validateRestScene(requestDays) {
      if (!this.restFullDaySelectOptions.length) return '当前暂无可选应休天数'
      if (this.restAddHalfDayRequired && !this.restAddHalfDay) {
        return '请选择「再加半天」或改选大于 0 的整数天'
      }
      const rest = this.restQuota
      if (!rest.attendanceGroupBound) return '当前用户未绑定考勤分组，无法提交休假申请'
      const maxDays = rest.restUnlockCycle > 0
        ? Number(rest.availableRestDays || 0)
        : Number(rest.remainingRestDays || 0)
      if (requestDays > maxDays) return `当前可申请 ${this.formatNumber(maxDays)} 天`
      const splitDays = this.getHalfDaySplitDays(requestDays)
      const remainSplitDays = Number(rest.remainingHalfDaySplitDays || 0)
      if (splitDays > remainSplitDays) return `本月可拆分半天额度剩余 ${this.formatNumber(remainSplitDays)} 天`
      return ''
    },
    validatePaidScene(requestDays) {
      if (Math.floor(requestDays) !== requestDays) return '带薪休假仅可选择整天'
      if (this.dataForm.leaveType === '婚假') {
        const maxDays = Math.floor(Number((this.paidQuota.marriage || {}).maxDays || 0))
        if (maxDays <= 0) return '当前未匹配到婚假规则，暂不能提交婚假申请'
        if (requestDays > maxDays) return `婚假最多可请 ${this.formatNumber(maxDays)} 天`
        return ''
      }
      if (this.dataForm.leaveType === '丧假') {
        const funeral = this.paidQuota.funeral || {}
        const maxDays = Math.floor(Number(Number(this.dataForm.funeralRelationType) === 1 ? funeral.directRelativeDays || 0 : funeral.indirectRelativeDays || 0))
        if (maxDays <= 0) return '当前未匹配到丧假规则，暂不能提交丧假申请'
        if (requestDays > maxDays) return `当前选择的丧假最多可请 ${this.formatNumber(maxDays)} 天`
        return ''
      }
      if (this.dataForm.leaveType === '年假') {
        const remainDays = Math.floor(Number((this.paidQuota.annual || {}).remainingDays || 0))
        if (remainDays <= 0) return '当前年假剩余天数为 0，暂不能提交年假申请'
        if (requestDays > remainDays) return `当前年假剩余 ${this.formatNumber(remainDays)} 天`
        return ''
      }
      if (this.dataForm.leaveType === '产假') {
        const maxDays = Math.floor(Number((this.paidQuota.maternity || {}).maxDays || 0))
        if (maxDays <= 0) return '当前未匹配到产假规则，暂不能提交产假申请'
        if (requestDays > maxDays) return `产假最多可请 ${this.formatNumber(maxDays)} 天`
        return ''
      }
      const matchedExtraLeave = this.extraLeaveList.find(item => String(item.leaveName || '').trim() === String(this.dataForm.leaveType || '').trim())
      if (matchedExtraLeave) {
        const maxDays = Math.floor(Number(matchedExtraLeave.extraDays || 0))
        if (maxDays <= 0) return `当前额外假期【${matchedExtraLeave.leaveName}】可用天数为 0`
        if (requestDays > maxDays) return `额外假期【${matchedExtraLeave.leaveName}】最多可请 ${this.formatNumber(maxDays)} 天`
        return ''
      }
      return '请选择有效的带薪假类型'
    },
    validateBusinessRule() {
      if (!this.dataForm.flowId) return '缺少流程ID，无法提交，请从流程入口进入页面'
      const requestDays = this.getRequestDays()
      if (!requestDays || requestDays <= 0) return '请假天数必须大于 0'
      if (this.isPaidScene) {
        if (Math.floor(requestDays) !== requestDays) return '带薪休假仅可选择整天'
      } else if (this.isPersonalScene) {
        if (Math.floor(requestDays) !== requestDays) return '事假、病假须选择整数天'
        if (requestDays < 1 || requestDays > 10) return '事假、病假可选择 1～10 天'
      } else if (Math.round(requestDays * 2) !== requestDays * 2) {
        return '请假天数必须是整数或 0.5 的倍数'
      }
      if (this.isRestScene) return this.validateRestScene(requestDays)
      if (this.isPaidScene) return this.validatePaidScene(requestDays)
      return ''
    },
    handleSubmit(type) {
      this.submitType = type
      this.$refs.dataForm.validate(valid => {
        if (!valid) return
        const error = this.validateBusinessRule()
        if (error) {
          this.$message.error(error)
          return
        }
        if (type === 'submit') {
          this.$confirm('确认提交当前申请吗？', '提示', { type: 'warning' })
            .then(() => this.handleRequest(type))
            .catch(() => { })
          return
        }
        this.handleRequest(type)
      })
    },
    async handleRequest(type) {
      this.submitLoading = true
      try {
        const payload = Object.assign({}, this.dataForm, {
          flowUrgent: Number(this.dataForm.flowUrgent || 1),
          funeralRelationType: this.dataForm.leaveType === '丧假' ? Number(this.dataForm.funeralRelationType || 0) : null,
          leaveReason: (this.dataForm.leaveReason || '').trim(),
          fileJson: this.fileList && this.fileList.length ? JSON.stringify(this.fileList) : '',
          status: type === 'submit' ? 0 : 1
        })
        if (!payload.id) delete payload.id
        const requestMethod = payload.id ? Update : Create
        const res = await requestMethod('leaveApply', payload)
        this.$message.success((res && res.msg) || (type === 'submit' ? '提交成功' : '保存成功'))
        this.goAfterSuccess()
      } finally {
        this.submitLoading = false
      }
    },
    goAfterSuccess() {
      this.$router.push({ path: '/workFlow/flowLaunch' })
    },
    handleBack() {
      if (window.history.length > 1) {
        this.$router.back()
        return
      }
      this.$router.push({ path: '/workFlow/flowLaunch' })
    }
  }
}
</script>

<style lang="scss" scoped>
.leave-apply-page {
  padding: 20px;
}

.page-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 16px;
  gap: 16px;
}

.page-title {
  font-size: 22px;
  font-weight: 600;
  color: #303133;
}

.page-tip {
  margin-top: 6px;
  color: #606266;
  line-height: 1.6;
}

.page-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.head-alert {
  margin-bottom: 16px;
}

.summary-panel,
.form-card {
  margin-bottom: 16px;
}

.summary-panel {
  background: #fff;
  border-radius: 4px;
  padding: 16px;
}

.summary-head,
.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.summary-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.summary-card {
  min-height: 110px;
  margin-bottom: 16px;
  padding: 16px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  background: #fafafa;
}

.summary-card.active {
  border-color: #67c23a;
  background: #f0f9eb;
}

.summary-label {
  color: #909399;
  font-size: 13px;
}

.summary-value {
  margin-top: 8px;
  font-size: 24px;
  font-weight: 600;
  color: #303133;
}

.summary-desc,
.summary-helper,
.form-helper,
.bill-no {
  color: #606266;
  line-height: 1.6;
}

.summary-desc {
  margin-top: 8px;
}

.summary-helper {
  margin-top: 4px;
}

.form-helper {
  margin: -4px 0 16px;
  font-size: 12px;
}

.bill-no {
  font-size: 13px;
}

.rest-days-admin {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.rest-days-admin__full {
  min-width: 160px;
}
</style>
