diff --git a/backend/managerRoutes.js b/backend/managerRoutes.js index df1e066..abdf0a7 100644 --- a/backend/managerRoutes.js +++ b/backend/managerRoutes.js @@ -392,7 +392,6 @@ export default function () { } const wantXlsx = String(req.query.format || 'csv').toLowerCase() === 'xlsx' - const wantTxt = String(req.query.format || '').toLowerCase() === 'txt' let workerIdClause = '' let departmentClause = '' @@ -523,39 +522,6 @@ export default function () { byWorkerForXlsx.set(`${w.username}||${w.full_name}||${w.department}`, perWorkerRows) } - // ===== TXT branch ===== - if (wantTxt) { - const lines = [] - for (const wId in workByDay) { - const w = workByDay[wId] - const seen = new Set() - for (const day of Object.keys(w.days).sort()) { - const events = w.days[day].slice().sort((a, b) => a.time - b.time) - for (const e of events) { - const code = e.type === 'clock_in' ? '1' : '0' - const date = ymdInTZ(e.time, TZ) - const timeStr = new Intl.DateTimeFormat('en-GB', { - timeZone: TZ, - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - hour12: false, - }).format(e.time) - const line = `${w.username},"${code}","${date} ${timeStr}";"${w.full_name}"` - if (!seen.has(line)) { - seen.add(line) - lines.push(line) - } - } - } - } - res.set('X-Export-TZ', TZ) - res.header('Content-Type', 'text/plain') - .attachment(`attendance_${startDate}_to_${endDate}.txt`) - .send(lines.join('\n')) - return - } - // ===== XLSX branch: grouped header + per-day summary sheet ===== if (wantXlsx) { const wb = new ExcelJS.Workbook() diff --git a/src/components/PersonnelManagement.vue b/src/components/PersonnelManagement.vue index e5a4df6..284f332 100644 --- a/src/components/PersonnelManagement.vue +++ b/src/components/PersonnelManagement.vue @@ -95,13 +95,6 @@ {{ exportLoading ? $t('exporting') : $t('exportAll') }} -
- -
@@ -478,7 +471,6 @@ const confirmMessage = ref(''); const isConfirmModalVisible = ref(false); const exportFilters = ref({ startDate: '', endDate: '' }); const exportLoading = ref(false); -const txtExportLoading = ref(false); const showClearDeviceConfirm = ref(false); const showDeleteConfirm = ref(false); const departments = ref([]); @@ -770,39 +762,6 @@ const exportWorkHours = async () => { } }; -const exportTxt = async () => { - const toast = useToast(); - txtExportLoading.value = true; - const { startDate, endDate } = exportFilters.value; - const workerIds = selectedWorkerIds.value.join(','); - let exportUrl = `${import.meta.env.VITE_API_BASE_URL}/api/managers/attendance-records/export?format=txt&startDate=${startDate}&endDate=${endDate}&workerIds=${workerIds}`; - if (selectedDepartment.value) { - exportUrl += `&department=${encodeURIComponent(selectedDepartment.value)}`; - } - try { - const response = await fetch(exportUrl, { - headers: { - Authorization: `Bearer ${sessionStorage.getItem('token')}`, - 'X-User-Timezone': getUserTimezone(), - }, - }); - if (!response.ok) throw new Error('Network response was not ok.'); - const blob = await response.blob(); - const url = window.URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = `attendance_${startDate}_to_${endDate}.txt`; - document.body.appendChild(a); - a.click(); - a.remove(); - window.URL.revokeObjectURL(url); - } catch (_err) { - toast.showToast('Export TXT failed.', 'error'); - } finally { - txtExportLoading.value = false; - } -}; - onMounted(() => { fetchDepartments(); const savedSearchState = sessionStorage.getItem('personnelSearchState');