// リストコンポーネント Alpine.data('auditHistoryList', () => ({ historyData: [], isLoading: false, hasData: false, searchExecuted: false, // ページネーション currentPage: 1, lastPage: 1, perPage: 50, total: 0, // 現在の検索条件 currentSearchParams: {}, currentTab: 'all', // エクスポート isExporting: false, initializeList() { // 検索実行イベントリスナー this.$el.addEventListener('search-executed', (event) => { this.currentSearchParams = event.detail; this.currentPage = 1; this.searchExecuted = true; this.loadData(); }); // 検索リセットイベントリスナー this.$el.addEventListener('search-reset', () => { this.resetData(); }); // タブ変更イベントリスナー this.$el.addEventListener('tab-changed', (event) => { if (this.searchExecuted) { this.currentTab = event.detail; this.currentPage = 1; this.loadData(); } }); }, async loadData() { this.isLoading = true; try { const searchEndpoint = this.getSearchEndpoint(); const params = { ...this.currentSearchParams, page: this.currentPage, per_page: this.perPage }; const response = await fetch(searchEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }, body: JSON.stringify(params) }); if (!response.ok) { throw new Error('検索エラーが発生しました。'); } const data = await response.json(); if (data.success) { this.historyData = data.data.data || []; this.updatePagination(data.data.pagination); this.hasData = this.historyData.length > 0; this.updateTabCounts(data.data); } else { throw new Error(data.message || '検索に失敗しました。'); } } catch (error) { console.error('Search error:', error); alert('検索中にエラーが発生しました: ' + error.message); this.historyData = []; this.hasData = false; } finally { this.isLoading = false; } }, getSearchEndpoint() { const endpoints = { 'all': '{{ route("audit-history.search.integrated") }}', 'activity': '{{ route("audit-history.search.activity") }}', 'audit': '{{ route("audit-history.search.audit") }}' }; return endpoints[this.currentTab] || endpoints['all']; }, updatePagination(pagination) { this.currentPage = pagination.current_page; this.lastPage = pagination.last_page; this.perPage = pagination.per_page; this.total = pagination.total; }, updateTabCounts(data) { // タブ別件数更新のイベントを発火 this.$dispatch('update-tab-counts', { all: data.total || 0, activity: data.activity_count || 0, audit: data.audit_count || 0 }); }, changePage(page) { if (page >= 1 && page <= this.lastPage && page !== this.currentPage) { this.currentPage = page; this.loadData(); } }, resetData() { this.historyData = []; this.hasData = false; this.searchExecuted = false; this.currentPage = 1; this.lastPage = 1; this.total = 0; }, // 表示用メソッド getRowNumber(index) { return ((this.currentPage - 1) * this.perPage) + index + 1; }, formatDateTime(datetime) { if (!datetime) return '-'; return new Date(datetime).toLocaleString('ja-JP', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }); }, getEventAction(record) { if (record.history_type === 'audit') { const eventNames = { 'created': '新規作成', 'updated': '更新', 'deleted': '削除', 'restored': '復元' }; return eventNames[record.event] || record.event || '-'; } else { return record.action_type || record.description || '-'; } }, getTarget(record) { if (record.history_type === 'audit') { return record.auditable_display_name || this.getTableName(record.auditable_type) || '-'; } else { return record.menu_name || '-'; } }, getTableName(modelType) { // 設定ファイルから全マッピングを取得(PHP側で生成) const tableNames = @json(config('model_names', [])); return tableNames[modelType] || (modelType ? modelType.split('\\').pop() : ''); }, getUserName(record) { return (record.user_family_name || '') + ' ' + (record.user_given_name || '') || 'システム'; }, getPaginationInfo() { if (this.total === 0) return '0件'; const from = ((this.currentPage - 1) * this.perPage) + 1; const to = Math.min(this.currentPage * this.perPage, this.total); return `${from} - ${to}件 / ${this.total}件中`; }, showDetailModal(record) { this.$dispatch('show-detail-modal', record); }, showSessionHistory(sessionId) { this.$dispatch('show-session-history', sessionId); }, async startExport() { if (this.isExporting) return; this.isExporting = true; try { const params = { ...this.currentSearchParams, export_type: this.currentTab }; const response = await fetch('{{ route("audit-history.export.start") }}', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }, body: JSON.stringify(params) }); if (!response.ok) { throw new Error('エクスポートの開始に失敗しました。'); } const data = await response.json(); if (data.success) { this.$dispatch('export-started', { jobId: data.data.job_id, recordCount: data.data.record_count }); } else { throw new Error(data.message || 'エクスポートの開始に失敗しました。'); } } catch (error) { console.error('Export start error:', error); alert('エクスポート開始中にエラーが発生しました: ' + error.message); } finally { this.isExporting = false; } } }));