From 23fc9eb0f2a9d3822cf21894ff25f551751f7d4e Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 28 五月 2026 21:37:57 +0800
Subject: [PATCH] Revert "feat: 合并"

---
 src/views/collaborativeApproval/attendanceManagement/index.vue | 1244 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,244 insertions(+), 0 deletions(-)

diff --git a/src/views/collaborativeApproval/attendanceManagement/index.vue b/src/views/collaborativeApproval/attendanceManagement/index.vue
new file mode 100644
index 0000000..1f5f956
--- /dev/null
+++ b/src/views/collaborativeApproval/attendanceManagement/index.vue
@@ -0,0 +1,1244 @@
+<template>
+  <div class="app-container">
+    <el-tabs v-model="activeTab" type="border-card">
+      <!-- 鍋囨湡璁剧疆 -->
+      <el-tab-pane label="鍋囨湡璁剧疆" name="holiday">
+        <div class="tab-content">
+          <el-button type="primary" @click="openDialog('holiday', 'add')">鏂板鍋囨湡</el-button>
+
+          <el-table :data="holidayData" border style="width: 100%; margin-top: 20px;">
+            <el-table-column prop="name" label="鍋囨湡鍚嶇О" />
+            <el-table-column prop="type" label="鍋囨湡绫诲瀷">
+              <template #default="scope">
+                <el-tag :type="getTagType(scope.row.type)">{{ getTypeLabel(scope.row.type) }}</el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column prop="startDate" label="寮�濮嬫棩鏈�"  />
+            <el-table-column prop="endDate" label="缁撴潫鏃ユ湡"  />
+            <el-table-column prop="days" label="澶╂暟"  align="center" />
+            <el-table-column prop="status" label="鐘舵��" >
+              <template #default="scope">
+                <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
+                  {{ scope.row.status === 'active' ? '鍚敤' : '鍋滅敤' }}
+                </el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column label="鎿嶄綔" fixed="right">
+              <template #default="scope">
+                <el-button type="primary" size="small" @click="openDialog('holiday', 'edit', scope.row)">缂栬緫</el-button>
+                <el-button type="danger" size="small" @click="deleteItem('holiday', scope.row)">鍒犻櫎</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </el-tab-pane>
+
+      <!-- 骞村亣璁剧疆 -->
+      <el-tab-pane label="骞村亣璁剧疆" name="annual">
+        <div class="tab-content">
+          <el-button type="primary" @click="openDialog('annual', 'add')">鏂板骞村亣瑙勫垯</el-button>
+
+          <el-table :data="annualData" border style="width: 100%; margin-top: 20px;">
+            <el-table-column prop="employeeType" label="鍛樺伐绫诲瀷">
+              <template #default="scope">
+                <el-tag :type="getTagType(scope.row.employeeType)">{{ getTypeLabel(scope.row.employeeType) }}</el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column prop="workYears" label="宸ヤ綔骞撮檺" />
+            <el-table-column prop="annualDays" label="骞村亣澶╂暟" align="center" />
+            <el-table-column prop="maxCarryOver" label="鏈�澶х粨杞ぉ鏁�" align="center" />
+            <el-table-column prop="status" label="鐘舵��">
+              <template #default="scope">
+                <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
+                  {{ scope.row.status === 'active' ? '鍚敤' : '鍋滅敤' }}
+                </el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column label="鎿嶄綔" fixed="right">
+              <template #default="scope">
+                <el-button type="primary" size="small" @click="openDialog('annual', 'edit', scope.row)">缂栬緫</el-button>
+                <el-button type="danger" size="small" @click="deleteItem('annual', scope.row)">鍒犻櫎</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </el-tab-pane>
+
+      <!-- 鍔犵彮璁剧疆 -->
+      <el-tab-pane label="鍔犵彮璁剧疆" name="overtime">
+        <div class="tab-content">
+          <el-button type="primary" @click="openDialog('overtime', 'add')">鏂板鍔犵彮瑙勫垯</el-button>
+
+          <el-table :data="overtimeData" border style="width: 100%; margin-top: 20px;">
+            <el-table-column prop="name" label="瑙勫垯鍚嶇О" />
+            <el-table-column prop="type" label="鍔犵彮绫诲瀷" >
+              <template #default="scope">
+                <el-tag :type="getTagType(scope.row.type)">{{ getTypeLabel(scope.row.type) }}</el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column prop="startTime" label="寮�濮嬫椂闂�"  />
+            <el-table-column prop="endTime" label="缁撴潫鏃堕棿"  />
+            <el-table-column prop="rate" label="鍊嶇巼" align="center" />
+            <el-table-column prop="status" label="鐘舵��" >
+              <template #default="scope">
+                <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
+                  {{ scope.row.status === 'active' ? '鍚敤' : '鍋滅敤' }}
+                </el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column label="鎿嶄綔" fixed="right">
+              <template #default="scope">
+                <el-button type="primary" size="small" @click="openDialog('overtime', 'edit', scope.row)">缂栬緫</el-button>
+                <el-button type="danger" size="small" @click="deleteItem('overtime', scope.row)">鍒犻櫎</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </el-tab-pane>
+
+      <!-- 涓婄彮鏃堕棿璁剧疆 -->
+      <el-tab-pane label="涓婄彮鏃堕棿璁剧疆" name="worktime">
+        <div class="tab-content">
+          <el-button type="primary" @click="openDialog('worktime', 'add')">鏂板鏃堕棿娈�</el-button>
+
+          <el-table :data="worktimeData" border style="width: 100%; margin-top: 20px;">
+            <el-table-column prop="name" label="鏃堕棿娈靛悕绉�"  />
+            <el-table-column prop="startTime" label="涓婄彮鏃堕棿"/>
+            <el-table-column prop="endTime" label="涓嬬彮鏃堕棿" />
+            <el-table-column prop="flexibleStart" label="寮规�т笂鐝�">
+              <template #default="scope">
+                <el-tag :type="scope.row.flexibleStart === 'true' ? 'success' : 'info'">
+                  {{ scope.row.flexibleStart === 'true' ? '鏄�' : '鍚�' }}
+                </el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column prop="flexibleMinutes" label="寮规�ф椂闂�(鍒嗛挓)" width="120" align="center" />
+            <el-table-column prop="status" label="鐘舵��" >
+              <template #default="scope">
+                <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
+                  {{ scope.row.status === 'active' ? '鍚敤' : '鍋滅敤' }}
+                </el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column label="鎿嶄綔" fixed="right">
+              <template #default="scope">
+                <el-button type="primary" size="small" @click="openDialog('worktime', 'edit', scope.row)">缂栬緫</el-button>
+                <el-button type="danger" size="small" @click="deleteItem('worktime', scope.row)">鍒犻櫎</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </el-tab-pane>
+
+      <!-- 鎵撳崱璁板綍 -->
+      <el-tab-pane label="鎵撳崱璁板綍" name="attendance">
+        <div class="tab-content">
+          <div style="margin-bottom: 20px;">
+            <el-date-picker
+              v-model="attendanceDate"
+              type="date"
+              placeholder="閫夋嫨鏃ユ湡"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              style="margin-right: 10px;"
+              @change="filterAttendanceData"
+            />
+            <el-select
+              v-model="attendanceStatus"
+              placeholder="閫夋嫨鐘舵��"
+              style="width: 120px; margin-right: 10px;"
+              @change="filterAttendanceData"
+            >
+              <el-option label="鍏ㄩ儴" value="" />
+              <el-option label="姝e父" value="normal" />
+              <el-option label="杩熷埌" value="late" />
+              <el-option label="鏃╅��" value="early" />
+              <el-option label="缂哄嫟" value="absent" />
+            </el-select>
+            <el-button type="primary" @click="exportAttendance">瀵煎嚭璁板綍</el-button>
+          </div>
+
+          <el-table :data="filteredAttendanceData" border style="width: 100%;">
+            <el-table-column prop="employeeName" label="鍛樺伐濮撳悕" width="120" />
+            <el-table-column prop="department" label="閮ㄩ棬" width="120" />
+            <el-table-column prop="date" label="鏃ユ湡" width="120" />
+            <el-table-column prop="clockInTime" label="涓婄彮鎵撳崱" width="120" />
+            <el-table-column prop="clockOutTime" label="涓嬬彮鎵撳崱" width="120" />
+            <el-table-column prop="workHours" label="宸ヤ綔鏃堕暱" width="100" align="center" />
+            <el-table-column prop="status" label="鐘舵��" width="100" align="center">
+              <template #default="scope">
+                <el-tag :type="getAttendanceTagType(scope.row.status)">{{ getAttendanceStatusLabel(scope.row.status) }}</el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column prop="location" label="鎵撳崱鍦扮偣" width="150" />
+            <el-table-column prop="remark" label="澶囨敞" min-width="150" />
+          </el-table>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+
+    <!-- 閫氱敤寮圭獥 -->
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px">
+      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="鍚嶇О" prop="name" v-if="currentType !== 'annual'">
+          <el-input v-model="form.name" placeholder="璇疯緭鍏ュ悕绉�" />
+        </el-form-item>
+
+        <el-form-item label="绫诲瀷" prop="type" v-if="currentType === 'holiday' || currentType === 'overtime'">
+          <el-select v-model="form.type" placeholder="璇烽�夋嫨绫诲瀷" style="width: 100%">
+            <el-option
+              v-for="option in getTypeOptions()"
+              :key="option.value"
+              :label="option.label"
+              :value="option.value"
+            />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="鍛樺伐绫诲瀷" prop="employeeType" v-if="currentType === 'annual'">
+          <el-select v-model="form.employeeType" placeholder="璇烽�夋嫨鍛樺伐绫诲瀷" style="width: 100%">
+            <!-- <el-option label="姝e紡鍛樺伐" value="regular" />
+            <el-option label="璇曠敤鏈熷憳宸�" value="probation" />
+            <el-option label="瀹炰範鐢�" value="intern" /> -->
+            <el-option
+              v-for="option in getTypeOptions()"
+              :key="option.value"
+              :label="option.label"
+              :value="option.value"
+            />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="宸ヤ綔骞撮檺" prop="workYears" v-if="currentType === 'annual'">
+          <el-input v-model="form.workYears" placeholder="濡傦細1-3骞淬��3-5骞寸瓑" />
+        </el-form-item>
+
+        <el-form-item label="骞村亣澶╂暟" prop="annualDays" v-if="currentType === 'annual'">
+          <el-input-number v-model="form.annualDays" :min="0" :max="365" style="width: 100%" />
+        </el-form-item>
+
+        <el-form-item label="鏈�澶х粨杞ぉ鏁�" prop="maxCarryOver" v-if="currentType === 'annual'">
+          <el-input-number v-model="form.maxCarryOver" :min="0" :max="30" style="width: 100%" />
+        </el-form-item>
+
+                          <el-form-item label="鏃ユ湡鑼冨洿" prop="dateRange" v-if="currentType === 'holiday'">
+           <el-date-picker
+             v-model="form.dateRange"
+             type="daterange"
+             range-separator="鑷�"
+             start-placeholder="寮�濮嬫棩鏈�"
+             end-placeholder="缁撴潫鏃ユ湡"
+             style="width: 100%"
+             @change="calculateDays"
+           />
+         </el-form-item>
+
+        <el-form-item label="澶╂暟" prop="days" v-if="currentType === 'holiday'">
+          <el-input-number v-model="form.days" :min="0" style="width: 100%" />
+        </el-form-item>
+
+                 <el-form-item label="寮�濮嬫椂闂�" prop="startTime" v-if="currentType === 'overtime'">
+           <el-time-picker
+             v-model="form.startTime"
+             placeholder="寮�濮嬫椂闂�"
+             format="HH:mm"
+             value-format="HH:mm"
+             style="width: 100%"
+             @change="validateTimeField('startTime')"
+           />
+         </el-form-item>
+
+         <el-form-item label="缁撴潫鏃堕棿" prop="endTime" v-if="currentType === 'overtime'">
+           <el-time-picker
+             v-model="form.endTime"
+             placeholder="缁撴潫鏃堕棿"
+             format="HH:mm"
+             value-format="HH:mm"
+             style="width: 100%"
+             @change="validateTimeField('endTime')"
+           />
+         </el-form-item>
+
+        <el-form-item label="鍊嶇巼" prop="rate" v-if="currentType === 'overtime'">
+          <el-input-number v-model="form.rate" :min="1" :max="3" :step="0.5" style="width: 100%" />
+        </el-form-item>
+
+                 <el-form-item label="涓婄彮鏃堕棿" prop="workStartTime" v-if="currentType === 'worktime'">
+           <el-time-picker
+             v-model="form.workStartTime"
+             placeholder="涓婄彮鏃堕棿"
+             format="HH:mm"
+             value-format="HH:mm"
+             style="width: 100%"
+             @change="validateTimeField('workStartTime')"
+           />
+         </el-form-item>
+
+         <el-form-item label="涓嬬彮鏃堕棿" prop="workEndTime" v-if="currentType === 'worktime'">
+           <el-time-picker
+             v-model="form.workEndTime"
+             placeholder="涓嬬彮鏃堕棿"
+             format="HH:mm"
+             value-format="HH:mm"
+             style="width: 100%"
+             @change="validateTimeField('workEndTime')"
+           />
+         </el-form-item>
+
+        <el-form-item label="寮规�т笂鐝�" prop="flexibleStart" v-if="currentType === 'worktime'">
+          <el-switch v-model="form.flexibleStart" />
+        </el-form-item>
+
+        <el-form-item label="寮规�ф椂闂�(鍒嗛挓)" prop="flexibleMinutes" v-if="currentType === 'worktime' && form.flexibleStart">
+          <el-input-number v-model="form.flexibleMinutes" :min="0" :max="120" style="width: 100%" />
+        </el-form-item>
+
+        <el-form-item label="鐘舵��" prop="status">
+           <el-radio-group v-model="form.status">
+             <el-radio value="active">鍚敤</el-radio>
+             <el-radio value="inactive">鍋滅敤</el-radio>
+           </el-radio-group>
+         </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button type="primary" @click="submitForm">纭畾</el-button>
+          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, onUnmounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { listHolidaySettings, addHolidaySettings, updateHolidaySettings, delHolidaySettings, listAnnualLeaveSettingList, addAnnualLeaveSetting, updateAnnualLeaveSetting, delAnnualLeaveSetting, listOvertimeSettingList, addOvertimeSetting, updateOvertimeSetting, delOvertimeSetting, listWorkingHoursSettingList, addWorkingHoursSetting, updateWorkingHoursSetting, delWorkingHoursSetting } from '@/api/collaborativeApproval/attendanceManagement.js'
+
+// 褰撳墠婵�娲荤殑鏍囩椤�
+const activeTab = ref('holiday')
+
+// 寮圭獥鐩稿叧
+const dialogVisible = ref(false)
+const dialogTitle = ref('')
+const currentType = ref('')
+const currentAction = ref('')
+const currentEditId = ref('')
+const formRef = ref()
+const page = {
+    current: 1,
+    size: 20,
+    total: 0,
+  }
+const holidayData = ref([])
+const annualData = ref([])
+const overtimeData = ref([])
+const worktimeData = ref([])
+
+// 鎵撳崱璁板綍鐩稿叧鏁版嵁
+const attendanceData = ref([])
+const filteredAttendanceData = ref([])
+const attendanceDate = ref('')
+const attendanceStatus = ref('')
+
+// 琛ㄥ崟鏁版嵁
+const form = reactive({
+  name: '',
+  type: '',
+  dateRange: [],
+  startDate: '',
+  endDate: '',
+  days: 0,
+  employeeType: '',
+  workYears: '',
+  annualDays: 0,
+  maxCarryOver: 0,
+  startTime: '', // 鍔犵彮寮�濮嬫椂闂�
+  endTime: '',   // 鍔犵彮缁撴潫鏃堕棿
+  workStartTime: '', // 涓婄彮鏃堕棿
+  workEndTime: '',   // 涓嬬彮鏃堕棿
+  rate: 1.5,
+  flexibleStart: false,
+  flexibleMinutes: 30,
+  status: 'active'
+})
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const rules = {
+  name: [{ required: true, message: '璇疯緭鍏ュ悕绉�', trigger: 'blur' }],
+  type: [{ required: true, message: '璇烽�夋嫨绫诲瀷', trigger: 'change' }],
+  dateRange: [{ required: true, message: '璇烽�夋嫨鏃ユ湡鑼冨洿', trigger: 'change' }],
+  days: [{ required: true, message: '璇疯緭鍏ュぉ鏁�', trigger: 'blur' }],
+  employeeType: [{ required: true, message: '璇烽�夋嫨鍛樺伐绫诲瀷', trigger: 'change' }],
+  workYears: [{ required: true, message: '璇疯緭鍏ュ伐浣滃勾闄�', trigger: 'blur' }],
+  annualDays: [{ required: true, message: '璇疯緭鍏ュ勾鍋囧ぉ鏁�', trigger: 'blur' }],
+  maxCarryOver: [{ required: true, message: '璇疯緭鍏ユ渶澶х粨杞ぉ鏁�', trigger: 'blur' }],
+  startTime: [{
+    required: true,
+    message: '璇烽�夋嫨寮�濮嬫椂闂�',
+    trigger: 'change',
+    validator: (rule, value, callback) => {
+      if (!value) {
+        callback(new Error('璇烽�夋嫨寮�濮嬫椂闂�'))
+      } else {
+        callback()
+      }
+    }
+  }],
+  endTime: [{
+    required: true,
+    message: '璇烽�夋嫨缁撴潫鏃堕棿',
+    trigger: 'change',
+    validator: (rule, value, callback) => {
+      if (!value) {
+        callback(new Error('璇烽�夋嫨缁撴潫鏃堕棿'))
+      } else {
+        callback()
+      }
+    }
+  }],
+  workStartTime: [{
+    required: true,
+    message: '璇烽�夋嫨涓婄彮鏃堕棿',
+    trigger: 'change',
+    validator: (rule, value, callback) => {
+      if (!value) {
+        callback(new Error('璇烽�夋嫨涓婄彮鏃堕棿'))
+      } else {
+        callback()
+      }
+    }
+  }],
+  workEndTime: [{
+    required: true,
+    message: '璇烽�夋嫨涓嬬彮鏃堕棿',
+    trigger: 'change',
+    validator: (rule, value, callback) => {
+      if (!value) {
+        callback(new Error('璇烽�夋嫨涓嬬彮鏃堕棿'))
+      } else {
+        callback()
+      }
+    }
+  }],
+  rate: [{ required: true, message: '璇疯緭鍏ュ�嶇巼', trigger: 'blur' }]
+}
+// 宸ュ叿鍑芥暟
+const getTagType = (type) => {
+  const tagMap = {
+    legal: 'success', adjustment: 'warning', special: 'info', company: 'primary',
+    weekday: 'primary', weekend: 'warning', holiday: 'danger', night: 'info',
+    regular: 'success', probation: 'info', intern: 'danger'
+  }
+  return tagMap[type] || 'info'
+}
+
+const getTypeLabel = (type) => {
+  const labelMap = {
+    legal: '娉曞畾鑺傚亣鏃�', adjustment: '璋冧紤鏃�', special: '鐗规畩鍋囨湡', company: '鍏徃鍋囨湡',
+    weekday: '宸ヤ綔鏃ュ姞鐝�', weekend: '鍛ㄦ湯鍔犵彮', holiday: '鑺傚亣鏃ュ姞鐝�', night: '娣卞鍔犵彮',
+    regular: '姝e紡鍛樺伐', probation: '璇曠敤鏈熷憳宸�', intern: '瀹炰範鐢�'
+  }
+  return labelMap[type] || type
+}
+
+// 鎵撳崱璁板綍鐩稿叧宸ュ叿鍑芥暟
+const getAttendanceTagType = (status) => {
+  const tagMap = {
+    normal: 'success',
+    late: 'warning', 
+    early: 'warning',
+    absent: 'danger'
+  }
+  return tagMap[status] || 'info'
+}
+
+const getAttendanceStatusLabel = (status) => {
+  const labelMap = {
+    normal: '姝e父',
+    late: '杩熷埌',
+    early: '鏃╅��', 
+    absent: '缂哄嫟'
+  }
+  return labelMap[status] || status
+}
+
+const getTypeOptions = () => {
+  if (currentType.value === 'holiday') {
+    return [
+      { label: '娉曞畾鑺傚亣鏃�', value: 'legal' },
+      { label: '璋冧紤鏃�', value: 'adjustment' },
+      { label: '鐗规畩鍋囨湡', value: 'special' },
+      { label: '鍏徃鍋囨湡', value: 'company' }
+    ]
+  } else if (currentType.value === 'overtime') {
+    return [
+      { label: '宸ヤ綔鏃ュ姞鐝�', value: 'weekday' },
+      { label: '鍛ㄦ湯鍔犵彮', value: 'weekend' },
+      { label: '鑺傚亣鏃ュ姞鐝�', value: 'holiday' },
+      { label: '娣卞鍔犵彮', value: 'night' }
+    ]
+  } else if (currentType.value === 'annual') {
+    return [
+      { label: '姝e紡鍛樺伐', value: 'regular' },
+      { label: '璇曠敤鏈熷憳宸�', value: 'probation' },
+      { label: '瀹炰範鐢�', value: 'intern' }
+    ]
+  }
+  return []
+}
+
+// 璁$畻鍋囨湡澶╂暟
+const calculateDays = () => {
+  try {
+    if (form.dateRange && form.dateRange.length === 2 && form.dateRange[0] && form.dateRange[1]) {
+      const start = new Date(form.dateRange[0])
+      const end = new Date(form.dateRange[1])
+      form.startDate = start.toISOString().split('T')[0]
+      form.endDate = end.toISOString().split('T')[0]
+
+      if (isNaN(start.getTime()) || isNaN(end.getTime())) {
+        console.warn('鏃犳晥鐨勬棩鏈熸牸寮�')
+        return
+      }
+
+      const diffTime = Math.abs(end - start)
+      const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1
+      form.days = diffDays
+    }
+  } catch (error) {
+    console.error('璁$畻澶╂暟澶辫触:', error)
+  }
+}
+
+// 楠岃瘉鏃堕棿鏍煎紡
+// const validateTime = (time) => {
+//   if (!time) return ''
+//   if (typeof time === 'string') return time
+//   if (time instanceof Date) {
+//     return time.toTimeString().slice(0, 5)
+//   }
+//   return ''
+// }
+
+// 楠岃瘉鏃堕棿瀛楁
+const validateTimeField = (fieldName) => {
+  try {
+    const value = form[fieldName]
+    if (value && typeof value === 'object' && value.hour !== undefined) {
+      // 濡傛灉鏄椂闂村璞★紝杞崲涓哄瓧绗︿覆鏍煎紡
+      const hours = value.hour.toString().padStart(2, '0')
+      const minutes = value.minute.toString().padStart(2, '0')
+      form[fieldName] = `${hours}:${minutes}`
+    }
+  } catch (error) {
+    console.error(`楠岃瘉鏃堕棿瀛楁 ${fieldName} 澶辫触:`, error)
+    form[fieldName] = ''
+  }
+}
+
+// 鎵撳紑寮圭獥
+const openDialog = (type, action, row = null) => {
+  try {
+    currentType.value = type
+    currentAction.value = action
+
+    if (action === 'add') {
+      dialogTitle.value = `鏂板${getTypeName(type)}`
+      currentEditId.value = ''
+      resetForm()
+    } else if (action === 'edit' && row) {
+      dialogTitle.value = `缂栬緫${getTypeName(type)}`
+      currentEditId.value = row.id
+      fillForm(row)
+    }
+
+    dialogVisible.value = true
+  } catch (error) {
+    console.error('鎵撳紑寮圭獥澶辫触:', error)
+    ElMessage.error('鎵撳紑寮圭獥澶辫触锛岃閲嶈瘯')
+  }
+}
+
+const getTypeName = (type) => {
+  const nameMap = {
+    holiday: '鍋囨湡',
+    annual: '骞村亣瑙勫垯',
+    overtime: '鍔犵彮瑙勫垯',
+    worktime: '鏃堕棿娈�'
+  }
+  return nameMap[type] || ''
+}
+
+const resetForm = () => {
+  Object.assign(form, {
+    name: '',
+    type: '',
+    dateRange: [],
+    startDate: '',
+    endDate: '',
+    days: 0,
+    employeeType: '',
+    workYears: '',
+    annualDays: 0,
+    maxCarryOver: 0,
+    startTime: '',
+    endTime: '',
+    workStartTime: '',
+    workEndTime: '',
+    rate: 1.5,
+    flexibleStart: false,
+    flexibleMinutes: 30,
+    status: 'active'
+  })
+}
+
+const fillForm = (row) => {
+  if (currentType.value === 'holiday') {
+    Object.assign(form, {
+      name: row.name,
+      type: row.type,
+      dateRange: [new Date(row.startDate), new Date(row.endDate)],
+      startDate: row.startDate,
+      endDate: row.endDate,
+      days: row.days,
+      status: row.status
+    })
+  } else if (currentType.value === 'annual') {
+    Object.assign(form, {
+      employeeType: row.employeeType,
+      workYears: row.workYears,
+      annualDays: row.annualDays,
+      maxCarryOver: row.maxCarryOver,
+      status: row.status
+    })
+  } else if (currentType.value === 'overtime') {
+    Object.assign(form, {
+      name: row.name,
+      type: row.type,
+      startTime: row.startTime || '',
+      endTime: row.endTime || '',
+      rate: row.rate,
+      status: row.status
+    })
+  } else if (currentType.value === 'worktime') {
+    Object.assign(form, {
+      name: row.name,
+      workStartTime: row.startTime || '',
+      workEndTime: row.endTime || '',
+      flexibleStart: row.flexibleStart,
+      flexibleMinutes: row.flexibleMinutes,
+      status: row.status
+    })
+  }
+}
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+  try {
+    if (!formRef.value) {
+      ElMessage.error('琛ㄥ崟寮曠敤涓嶅瓨鍦�')
+      return
+    }
+
+    await formRef.value.validate()
+
+    if (currentAction.value === 'add') {
+      addItem()
+    } else if (currentAction.value === 'edit') {
+      editItem()
+    }
+
+    dialogVisible.value = false
+    ElMessage.success('鎿嶄綔鎴愬姛')
+  } catch (error) {
+    console.error('琛ㄥ崟楠岃瘉澶辫触:', error)
+    ElMessage.error('琛ㄥ崟楠岃瘉澶辫触锛岃妫�鏌ヨ緭鍏�')
+  }
+}
+
+const addItem = () => {
+
+  if (currentType.value === 'holiday') {
+    const params = {
+      name: form.name,
+      type: form.type,
+      startDate: form.startDate,
+      endDate: form.endDate,
+      days: form.days,
+      status: form.status
+    }
+    addHolidaySettings(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("娣诲姞鎴愬姛");
+        // dialogVisible.value = false;
+        getHolidaySettingsList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+  } else if (currentType.value === 'annual') {
+    // annualData.value.push(newItem)
+    const params = {
+      employeeType: form.employeeType,
+      workYears: form.workYears,
+      annualDays: form.annualDays,
+      maxCarryOver: form.maxCarryOver,
+      status: form.status
+    }
+    addAnnualLeaveSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("娣诲姞鎴愬姛");
+        // dialogVisible.value = false;
+        getAnnualLeaveSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+  } else if (currentType.value === 'overtime') {
+    const params = {
+      name: form.name,
+      type: form.type,
+      startTime: form.startTime || '',
+      endTime: form.endTime || '',
+      rate: form.rate,
+      status: form.status
+    }
+    addOvertimeSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("娣诲姞鎴愬姛");
+        // dialogVisible.value = false;
+        getOvertimeSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+    // newItem.startTime = form.startTime || ''
+    // newItem.endTime = form.endTime || ''
+    // overtimeData.value.push(newItem)
+  } else if (currentType.value === 'worktime') {
+    const params = {
+      name: form.name,
+      startTime: form.workStartTime || '',
+      endTime: form.workEndTime || '',
+      flexibleStart: form.flexibleStart,
+      flexibleMinutes: form.flexibleMinutes,
+      status: form.status
+    }
+    addWorkingHoursSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("娣诲姞鎴愬姛");
+        getWorkingHoursSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+    // newItem.startTime = form.workStartTime || ''
+    // newItem.endTime = form.workEndTime || ''
+    // worktimeData.value.push(newItem)
+  }
+}
+
+const editItem = () => {
+  let dataArray
+  let index
+
+  if (currentType.value === 'holiday') {
+    const params = {
+      id: currentEditId.value,
+      name: form.name,
+      type: form.type,
+      startDate: form.dateRange[0].toISOString().split('T')[0],
+      endDate: form.dateRange[1].toISOString().split('T')[0],
+      days: form.days,
+      status: form.status
+    }
+    updateHolidaySettings(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鏇存柊鎴愬姛");
+        // dialogVisible.value = false;
+        getHolidaySettingsList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+  } else if (currentType.value === 'annual') {
+    const params = {
+      id: currentEditId.value,
+      employeeType: form.employeeType,
+      workYears: form.workYears,
+      annualDays: form.annualDays,
+      maxCarryOver: form.maxCarryOver,
+      status: form.status
+    }
+    updateAnnualLeaveSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鏇存柊鎴愬姛");
+        getAnnualLeaveSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+  } else if (currentType.value === 'overtime') {
+    const params = {
+      id: currentEditId.value,
+      name: form.name,
+      type: form.type,
+      startTime: form.startTime || '',
+      endTime: form.endTime || '',
+      rate: form.rate,
+      status: form.status
+    }
+    updateOvertimeSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鏇存柊鎴愬姛");
+        getOvertimeSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+
+    // dataArray = overtimeData.value
+    // index = dataArray.findIndex(item => item.id === currentEditId.value)
+    // if (index > -1) {
+    //   dataArray[index] = {
+    //     ...dataArray[index],
+    //     name: form.name,
+    //     type: form.type,
+    //     startTime: form.startTime || '',
+    //     endTime: form.endTime || '',
+    //     rate: form.rate,
+    //     status: form.status
+    //   }
+    // }
+  } else if (currentType.value === 'worktime') {
+    const params = {
+      id: currentEditId.value,
+      name: form.name,
+      startTime: form.workStartTime || '',
+      endTime: form.workEndTime || '',
+      flexibleStart: form.flexibleStart,
+      flexibleMinutes: form.flexibleMinutes,
+      status: form.status
+    }
+    updateWorkingHoursSetting(params).then(res => {
+      if(res.code == 200){
+        ElMessage.success("鏇存柊鎴愬姛");
+        getWorkingHoursSettingList()
+      }
+    }).catch(err => {
+      ElMessage.error(err.msg);
+    })
+    // dataArray = worktimeData.value
+    // index = dataArray.findIndex(item => item.id === currentEditId.value)
+    // if (index > -1) {
+    //   dataArray[index] = {
+    //     ...dataArray[index],
+    //     name: form.name,
+    //     startTime: form.workStartTime || '',
+    //     endTime: form.workEndTime || '',
+    //     flexibleStart: form.flexibleStart,
+    //     flexibleMinutes: form.flexibleMinutes,
+    //     status: form.status
+    //   }
+    // }
+  }
+}
+
+// 鎵撳崱璁板綍杩囨护鍔熻兘
+const filterAttendanceData = () => {
+  let filtered = attendanceData.value
+  
+  // 鎸夋棩鏈熻繃婊�
+  if (attendanceDate.value) {
+    filtered = filtered.filter(item => item.date === attendanceDate.value)
+  }
+  
+  // 鎸夌姸鎬佽繃婊�
+  if (attendanceStatus.value) {
+    filtered = filtered.filter(item => item.status === attendanceStatus.value)
+  }
+  
+  filteredAttendanceData.value = filtered
+}
+
+// 瀵煎嚭鎵撳崱璁板綍
+const exportAttendance = () => {
+  ElMessage.success('瀵煎嚭鍔熻兘寮�鍙戜腑...')
+}
+
+// 鍒濆鍖栨墦鍗¤褰曞亣鏁版嵁
+const initAttendanceData = () => {
+  const mockData = [
+    {
+      id: 1,
+      employeeName: '闄堝織寮�',
+      department: '鎶�鏈儴',
+      date: '2025-08-15',
+      clockInTime: '09:00:00',
+      clockOutTime: '18:00:00',
+      workHours: '8.0h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 2,
+      employeeName: '鏉庨洩姊�',
+      department: '甯傚満閮�',
+      date: '2025-08-16',
+       clockInTime: '08:58:00',
+       clockOutTime: '18:05:00',
+       workHours: '8.12h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 3,
+       employeeName: '鐜嬪缓鍗�',
+       department: '浜轰簨閮�',
+       date: '2025-08-16',
+       clockInTime: '09:02:00',
+       clockOutTime: '18:00:00',
+       workHours: '7.97h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 4,
+       employeeName: '璧垫檽涓�',
+       department: '璐㈠姟閮�',
+       date: '2025-09-02',
+       clockInTime: '08:55:00',
+       clockOutTime: '18:10:00',
+       workHours: '8.25h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 5,
+       employeeName: '寮犲浗搴�',
+       department: '鎶�鏈儴',
+       date: '2025-09-02',
+       clockInTime: '09:00:00',
+       clockOutTime: '18:30:00',
+       workHours: '8.5h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: '鍔犵彮'
+     },
+     {
+       id: 6,
+       employeeName: '鍒樻槑杈�',
+       department: '杩愯惀閮�',
+       date: '2025-09-03',
+       clockInTime: '09:05:00',
+       clockOutTime: '18:00:00',
+       workHours: '7.92h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 7,
+       employeeName: '瀛欎附鍗�',
+       department: '璁捐閮�',
+       date: '2025-09-03',
+       clockInTime: '08:59:00',
+       clockOutTime: '18:02:00',
+       workHours: '8.05h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 8,
+       employeeName: '鍛ㄥ缓鍐�',
+       department: '閿�鍞儴',
+       date: '2025-09-04',
+       clockInTime: '09:15:00',
+       clockOutTime: '18:00:00',
+       workHours: '7.75h',
+       status: 'late',
+       location: '鍏徃鎬婚儴',
+       remark: '浜ら�氬牭濉�'
+     },
+     {
+       id: 9,
+       employeeName: '鍚村皬鑺�',
+       department: '瀹㈡湇閮�',
+       date: '2025-09-04',
+       clockInTime: '09:01:00',
+       clockOutTime: '18:00:00',
+       workHours: '7.98h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 10,
+       employeeName: '椹枃鏉�',
+       department: '鎶�鏈儴',
+       date: '2025-09-05',
+       clockInTime: '08:57:00',
+       clockOutTime: '17:30:00',
+       workHours: '7.55h',
+       status: 'early',
+       location: '鍏徃鎬婚儴',
+       remark: '鏈夋�ヤ簨鎻愬墠绂诲紑'
+     },
+     {
+       id: 11,
+       employeeName: '鏋楁檽涓�',
+       department: '琛屾斂閮�',
+       date: '2025-09-05',
+       clockInTime: '09:03:00',
+       clockOutTime: '18:08:00',
+       workHours: '8.08h',
+       status: 'normal',
+       location: '鍏徃鎬婚儴',
+       remark: ''
+     },
+     {
+       id: 12,
+       employeeName: '榛勭編鐜�',
+       department: '璐㈠姟閮�',
+       date: '2025-09-06',
+       clockInTime: '',
+       clockOutTime: '',
+       workHours: '0h',
+       status: 'absent',
+       location: '',
+       remark: '璇风梾鍋�'
+     },
+    {
+      id: 13,
+      employeeName: '閮戞捣娑�',
+      department: '甯傚満閮�',
+      date: '2025-08-14',
+      clockInTime: '09:00:00',
+      clockOutTime: '18:00:00',
+      workHours: '8.0h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 14,
+      employeeName: '璋附濞�',
+      department: '浜轰簨閮�',
+      date: '2025-08-20',
+      clockInTime: '08:58:00',
+      clockOutTime: '18:03:00',
+      workHours: '8.08h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 15,
+      employeeName: '浣曞織浼�',
+      department: '鎶�鏈儴',
+      date: '2025-08-21',
+      clockInTime: '09:10:00',
+      clockOutTime: '18:00:00',
+      workHours: '7.83h',
+      status: 'late',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 16,
+      employeeName: '璁搁泤鑺�',
+      department: '璁捐閮�',
+      date: '2025-08-22',
+      clockInTime: '09:01:00',
+      clockOutTime: '18:00:00',
+      workHours: '7.98h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 17,
+      employeeName: '閭撳缓骞�',
+      department: '杩愯惀閮�',
+      date: '2025-09-10',
+      clockInTime: '08:59:00',
+      clockOutTime: '18:05:00',
+      workHours: '8.1h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    },
+    {
+      id: 18,
+      employeeName: '鏇惧皬绾�',
+      department: '瀹㈡湇閮�',
+      date: '2025-09-11',
+      clockInTime: '09:02:00',
+      clockOutTime: '18:00:00',
+      workHours: '7.97h',
+      status: 'normal',
+      location: '鍏徃鎬婚儴',
+      remark: ''
+    }
+  ]
+  
+  attendanceData.value = mockData
+  filteredAttendanceData.value = mockData
+}
+
+// 鍒犻櫎椤圭洰
+const deleteItem = (type, row) => {
+  ElMessageBox.confirm('纭畾瑕佸垹闄よ繖涓」鐩悧锛�', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    let ids = [];
+    let dataArray
+    if (type === 'holiday') {
+      ids.push(row.id)
+      delHolidaySettings(ids).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鍒犻櫎鎴愬姛");
+          ids = []
+          getHolidaySettingsList()
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
+    }
+    else if (type === 'annual') {
+      ids.push(row.id)
+      delAnnualLeaveSetting(ids).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鍒犻櫎鎴愬姛");
+          ids = []
+          getAnnualLeaveSettingList()
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
+    }
+    else if (type === 'overtime') {
+      ids.push(row.id)
+      delOvertimeSetting(ids).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鍒犻櫎鎴愬姛");
+          ids = []
+          getOvertimeSettingList()
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
+    }
+    else if (type === 'worktime') {
+      ids.push(row.id)
+      delWorkingHoursSetting(ids).then(res => {
+        if(res.code == 200){
+          ElMessage.success("鍒犻櫎鎴愬姛");
+          ids = []
+          getWorkingHoursSettingList()
+        }
+      }).catch(err => {
+        ElMessage.error(err.msg);
+      })
+    }
+
+    // const index = dataArray.findIndex(item => item.id === row.id)
+    // if (index > -1) {
+    //   dataArray.splice(index, 1)
+    //   ElMessage.success('鍒犻櫎鎴愬姛')
+    // }
+  })
+}
+// 鑾峰彇鍋囨湡璁剧疆鍒楄〃
+const getHolidaySettingsList = () => {
+  // tableLoading.value = true;
+  listHolidaySettings({...page.value})
+  .then(res => {
+    // tableLoading.value = false;
+    holidayData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+    // tableLoading.value = false;
+  })
+};
+// 鑾峰彇骞村亣瑙勫垯鍒楄〃
+const getAnnualLeaveSettingList = () => {
+
+  listAnnualLeaveSettingList({...page.value})
+  .then(res => {
+    // console.log(res.data)
+    annualData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+  })
+};
+// 鑾峰彇鍔犵彮瑙勫垯鍒楄〃
+const getOvertimeSettingList = () => {
+
+  listOvertimeSettingList({...page.value})
+  .then(res => {
+    // console.log(res.data)
+    overtimeData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+  })
+};
+// 鑾峰彇宸ヤ綔鏃堕棿瑙勫垯鍒楄〃
+const getWorkingHoursSettingList = () => {
+
+  listWorkingHoursSettingList({...page.value})
+  .then(res => {
+    // console.log(res.data)
+    worktimeData.value = res.data.records
+    page.total = res.data.total;
+  }).catch(err => {
+  })
+};
+onMounted(() => {
+  getHolidaySettingsList()
+  getAnnualLeaveSettingList()
+  getOvertimeSettingList()
+  getWorkingHoursSettingList()
+  initAttendanceData()
+  console.log('鑰冨嫟绠$悊椤甸潰鍔犺浇瀹屾垚')
+})
+
+onUnmounted(() => {
+  // 娓呯悊宸ヤ綔
+  dialogVisible.value = false
+  currentType.value = ''
+  currentAction.value = ''
+  currentEditId.value = ''
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.tab-content {
+  padding: 20px 0;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+:deep(.el-tabs__content) {
+  padding: 20px;
+}
+
+:deep(.el-form-item) {
+  margin-bottom: 20px;
+}
+</style>

--
Gitblit v1.9.3