Convert all store files from JavaScript to TypeScript

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 14:47:57 +08:00
parent 90048d0505
commit a619be7881
65 changed files with 2031 additions and 5066 deletions

347
src/stores/files.ts Normal file
View File

@@ -0,0 +1,347 @@
import { defineStore } from "pinia";
import apiClient from "@/api/client.js";
import moment from 'moment';
import apiError from '@/module/apiError.js';
import Swal from 'sweetalert2';
import { uploadFailedFirst, uploadFailedSecond, uploadloader, uploadSuccess, deleteSuccess } from '@/module/alertModal.js';
import { useLoadingStore } from '@/stores/loading';
export const useFilesStore = defineStore('filesStore', {
state: () => ({
allEventFiles: [
{
parentLog: '',
fileType: '',
ownerName: '',
}
],
switchFilesTagData: {
ALL: ['Log', 'Filter', 'Rule', 'Design'],
DISCOVER: ['Log', 'Filter', 'Rule'],
COMPARE: ['Log','Filter'],
DESIGN: ['Log', 'Design'],
},
filesTag: 'ALL',
httpStatus: 200,
uploadId: null,
allUploadDetail: null,
uploadLogId: null,
uploadFileName: null,
allDependentsData: null,
}),
getters: {
/**
* Get allFiles and switch files tag
*/
allFiles: state => {
let result = state.allEventFiles;
const data = state.switchFilesTagData;
const filesTag = state.filesTag;
result = result.filter(file => data[filesTag].includes(file.fileType));
return result;
},
/**
* Get upload preview
*/
uploadDetail: state => {
return state.allUploadDetail;
},
/**
* Get dependents of files data
*/
dependentsData: state => {
return state.allDependentsData;
}
},
actions: {
/**
* Fetch All Files api
*/
async fetchAllFiles() {
const api = '/api/files';
let icon = '';
let fileType = '';
let parentLog = '';
try {
const response = await apiClient.get(api);
this.allEventFiles = response.data;
this.allEventFiles.forEach(o => {
switch (o.type) {
case 'log':
icon = 'work_history';
fileType = 'Log';
parentLog = o.name;
break;
case 'filter':
icon = 'tornado';
fileType = 'Filter';
parentLog = o.parent.name;
break;
case 'log-check':
case 'filter-check':
icon = 'local_police';
fileType = 'Rule';
parentLog = o.parent.name;
break;
case 'design':
icon = 'shape_line';
break;
}
o.icon = icon;
o.parentLog = parentLog;
o.fileType = fileType;
o.ownerName = o.owner.name;
o.updated_base = o.updated_at;
o.accessed_base = o.accessed_at;
o.updated_at = moment(o.updated_at).utcOffset('+08:00').format('YYYY-MM-DD HH:mm');
o.accessed_at = o.accessed_at ? moment(o.accessed_at).utcOffset('+08:00').format('YYYY-MM-DD HH:mm') : null;
});
} catch(error) {
apiError(error, 'Failed to load the files.');
};
},
/**
* Uploads a CSV log file. 第一階段上傳
* @param {Object} fromData 傳給後端的 Data
*/
async upload(fromData) {
const api = '/api/logs/csv-uploads';
const config = {
data: true,
headers: {
'Content-Type': 'multipart/form-data',
},
};
uploadloader(); // 進度條
try {
const response = await apiClient.post(api, fromData, config);
this.uploadId = response.data.id;
this.$router.push({name: 'Upload'});
Swal.close(); // 關閉進度條
} catch(error) {
if(error.response.status === 422) {
// msg: 'not in UTF-8' | 'insufficient columns' | 'the csv file is empty' | 'the filename does not ends with .csv'
// type: 'encoding' | 'insufficient_columns' | 'empty' | 'name_suffix'
const detail = error.response.data.detail;
uploadFailedFirst(detail[0].type, detail[0].msg, detail[0].loc[2]);
} else {
Swal.close(); // 關閉進度條
apiError(error, 'Failed to upload the files.');
}
}
},
/**
* Fetch upload detail
*/
async getUploadDetail() {
const uploadId = this.uploadId;
const api = `/api/logs/csv-uploads/${uploadId}`;
try {
const response = await apiClient.get(api);
this.allUploadDetail = response.data.preview;
} catch(error) {
apiError(error, 'Failed to get upload detail.');
}
},
/**
* Add a Log from an Uploaded CSV Log File. 第二階段上傳
* @param {Object} data 傳給後端的 Data
*/
async uploadLog(data) {
const uploadId = this.uploadId;
const api = `/api/logs/csv-uploads/${uploadId}`;
uploadloader(); // 進度條
try {
const response = await apiClient.post(api, data);
this.uploadLogId = await response.data.id;
await Swal.close(); // 關閉進度條
await this.rename(); // 改檔名
await uploadSuccess();
this.$router.push({name: 'Files'});
} catch(error) {
if(error.response.status === 422) {
const detail = [...error.response.data.detail];
uploadFailedSecond(detail);
} else {
Swal.close(); // 關閉進度條
apiError(error, 'Failed to upload the log files.');
}
}
},
/**
* Rename a Log
* @param { string } type log | filter | log-check | filter-check傳入以上任一個。
* @param { number } id 檔案 ID
* @param { string } name file's name
*/
async rename(type, id, fileName) {
// 先判斷有沒有 uploadLogId有就設定 id 和 type再判斷檔案型別。
if(this.uploadId && this.uploadFileName) {
type = 'log';
id = this.uploadLogId;
fileName = this.uploadFileName;
}
let api;
const data = {"name": fileName};
switch (type) {
case 'log':
api = `/api/logs/${id}/name`;
break;
case 'filter':
api = `/api/filters/${id}/name`;
break;
case 'log-check':
api = `/api/log-checks/${id}/name`;
break;
case 'filter-check':
api = `/api/filter-checks/${id}/name`;
break;
}
try {
await apiClient.put(api, data);
this.uploadFileName = null;
await this.fetchAllFiles();
} catch(error) {
apiError(error, 'Failed to rename.');
}
},
/**
* Get the Dependents of the files
* @param { string } type log | filter | log-check | filter-check
* @param { number } id 檔案 ID
*/
async getDependents(type, id) {
let api;
switch (type) {
case 'log':
api = `/api/logs/${id}/dependents`;
break;
case 'filter':
api = `/api/filters/${id}/dependents`;
break;
case 'log-check':
api = `/api/log-checks/${id}/dependents`;
break;
case 'filter-check':
api = `/api/filter-checks/${id}/dependents`;
break;
}
try {
const response = await apiClient.get(api);
this.allDependentsData = response.data;
} catch(error) {
apiError(error, 'Failed to get Dependents of the files.');
}
},
/**
* Delete file
* @param { string } type log | filter | log-check | filter-check
* @param { number } id 檔案 ID
*/
async deleteFile(type, id) {
let api;
if(id === null || id === undefined || isNaN(id)) {
console.error('Delete File API Error: invalid id');
return;
};
const loading = useLoadingStore();
loading.isLoading = true;
switch (type) {
case 'log':
api = `/api/logs/${id}`;
break;
case 'filter':
api = `/api/filters/${id}`;
break;
case 'log-check':
api = `/api/log-checks/${id}`;
break;
case 'filter-check':
api = `/api/filter-checks/${id}`;
break;
}
try {
await apiClient.delete(api);
await this.fetchAllFiles();
await deleteSuccess();
} catch(error) {
apiError(error, 'Failed to delete.');
} finally {
loading.isLoading = false;
}
},
/**
* Remove a Deletion Record真刪除被 Admin 或被其他帳號刪除的檔案
* @param {number} id 檔案 ID
*/
async deletionRecord(id) {
let api = '';
const loading = useLoadingStore();
loading.isLoading = true;
api = `/api/deletion/${id}`;
try {
await apiClient.delete(api);
} catch(error) {
apiError(error, 'Failed to Remove a Deletion Record.')
} finally {
loading.isLoading = false;
}
},
/**
* Download file as CSV
* @param { string } type log | filter | log-check | filter-check
* @param { number } id 檔案 ID
* @param { string } fileName file's name
*/
async downloadFileCSV(type, id, fileName) {
let api;
switch (type) {
case 'log':
api = `/api/logs/${id}/csv`;
break;
case 'filter':
api = `/api/filters/${id}/csv`;
break;
// case 'log-check':
// api = `/api/log-checks/${id}/csv`;
// break;
// case 'filter-check':
// api = `/api/filter-checks/${id}/csv`;
// break;
default:
return;
}
try {
const response = await apiClient.get(api);
const csvData = response.data;
const blob = new Blob([csvData], { type: 'text/csv' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `${fileName}.csv`;
link.click();
window.URL.revokeObjectURL(url);
} catch(error) {
apiError(error, 'Failed to delete.');
}
},
},
})