Add centralized API client with axios interceptors, remove vue-axios
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
33
src/api/auth.js
Normal file
33
src/api/auth.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import axios from 'axios';
|
||||
import { getCookie, setCookie, setCookieWithoutExpiration } from '@/utils/cookieUtil.js';
|
||||
|
||||
/**
|
||||
* Refresh the access token using the refresh token cookie.
|
||||
* Uses plain axios (not apiClient) to avoid interceptor loops.
|
||||
* @returns {Promise<string>} The new access token.
|
||||
*/
|
||||
export async function refreshTokenAndGetNew() {
|
||||
const api = '/api/oauth/token';
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
};
|
||||
const data = {
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: getCookie('luciaRefreshToken'),
|
||||
};
|
||||
|
||||
const response = await axios.post(api, data, config);
|
||||
const newAccessToken = response.data.access_token;
|
||||
const newRefreshToken = response.data.refresh_token;
|
||||
|
||||
setCookieWithoutExpiration('luciaToken', newAccessToken);
|
||||
// Expire in ~6 months
|
||||
const expiredMs = new Date();
|
||||
expiredMs.setMonth(expiredMs.getMonth() + 6);
|
||||
const days = Math.ceil((expiredMs.getTime() - Date.now()) / (24 * 60 * 60 * 1000));
|
||||
setCookie('luciaRefreshToken', newRefreshToken, days);
|
||||
|
||||
return newAccessToken;
|
||||
}
|
||||
78
src/api/client.js
Normal file
78
src/api/client.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import axios from 'axios';
|
||||
import { getCookie, deleteCookie } from '@/utils/cookieUtil.js';
|
||||
|
||||
const apiClient = axios.create();
|
||||
|
||||
// Request interceptor: automatically attach Authorization header
|
||||
apiClient.interceptors.request.use((config) => {
|
||||
const token = getCookie('luciaToken');
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
||||
// Response interceptor: handle 401 by attempting token refresh
|
||||
let isRefreshing = false;
|
||||
let pendingRequests = [];
|
||||
|
||||
function onRefreshSuccess(newToken) {
|
||||
pendingRequests.forEach((cb) => cb(newToken));
|
||||
pendingRequests = [];
|
||||
}
|
||||
|
||||
function onRefreshFailure(error) {
|
||||
pendingRequests.forEach((cb) => cb(null, error));
|
||||
pendingRequests = [];
|
||||
}
|
||||
|
||||
apiClient.interceptors.response.use(
|
||||
(response) => response,
|
||||
async (error) => {
|
||||
const originalRequest = error.config;
|
||||
|
||||
// Only attempt refresh on 401, and not for auth endpoints or already-retried requests
|
||||
if (
|
||||
error.response?.status !== 401 ||
|
||||
originalRequest._retried ||
|
||||
originalRequest.url === '/api/oauth/token'
|
||||
) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
if (isRefreshing) {
|
||||
// Queue this request until the refresh completes
|
||||
return new Promise((resolve, reject) => {
|
||||
pendingRequests.push((newToken, err) => {
|
||||
if (err) return reject(err);
|
||||
originalRequest.headers.Authorization = `Bearer ${newToken}`;
|
||||
originalRequest._retried = true;
|
||||
resolve(apiClient(originalRequest));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
isRefreshing = true;
|
||||
originalRequest._retried = true;
|
||||
|
||||
try {
|
||||
// Dynamic import to avoid circular dependency with login store
|
||||
const { refreshTokenAndGetNew } = await import('@/api/auth.js');
|
||||
const newToken = await refreshTokenAndGetNew();
|
||||
isRefreshing = false;
|
||||
onRefreshSuccess(newToken);
|
||||
originalRequest.headers.Authorization = `Bearer ${newToken}`;
|
||||
return apiClient(originalRequest);
|
||||
} catch (refreshError) {
|
||||
isRefreshing = false;
|
||||
onRefreshFailure(refreshError);
|
||||
|
||||
// Refresh failed: clear auth and redirect to login
|
||||
deleteCookie('luciaToken');
|
||||
window.location.href = '/login';
|
||||
return Promise.reject(refreshError);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default apiClient;
|
||||
@@ -3,8 +3,6 @@ import { createApp, markRaw } from "vue";
|
||||
import App from "./App.vue";
|
||||
import router from "./router";
|
||||
import pinia from '@/stores/main.js';
|
||||
import axios from 'axios';
|
||||
import VueAxios from 'vue-axios';
|
||||
import moment from 'moment';
|
||||
import mitt from 'mitt';
|
||||
import ToastPlugin from 'vue-toast-notification';
|
||||
@@ -49,15 +47,9 @@ import ContextMenu from 'primevue/contextmenu';
|
||||
const emitter = mitt();
|
||||
const app = createApp(App);
|
||||
|
||||
// 將 Axios 實例添加到 Vue 的應用實例中
|
||||
app.config.globalProperties.$http = axios;
|
||||
app.$http = axios; // 將 $http 添加到 Vue 實例中
|
||||
// Pinia Set
|
||||
pinia.use(({ store }) => {
|
||||
store.$router = markRaw(router);
|
||||
store.$axios = markRaw(axios);
|
||||
store.$toast = markRaw(ToastPlugin);
|
||||
store.$http = app.$http;
|
||||
});
|
||||
|
||||
// can use `this.$moment` in Vue.js
|
||||
@@ -72,7 +64,6 @@ cytoscape.use( popper((ref) => ref) );
|
||||
|
||||
app.use(pinia);
|
||||
app.use(router);
|
||||
app.use(VueAxios, axios);
|
||||
app.use(VueSweetalert2);
|
||||
app.use(ToastPlugin, { // use `this.$toast` in Vue.js
|
||||
position: 'bottom',
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
import router from "@/router/index";
|
||||
import loadingStore from '@/stores/loading.js';
|
||||
import {useToast} from 'vue-toast-notification';
|
||||
import 'vue-toast-notification/dist/theme-sugar.css';
|
||||
import axios from "axios";
|
||||
import { deleteCookie } from "@/utils/cookieUtil.js";
|
||||
|
||||
// Delay loading and toast
|
||||
const delay = (s = 0) => new Promise((resolve, reject) => setTimeout(resolve, s));
|
||||
|
||||
/**
|
||||
* API catch error function
|
||||
* @param {object} Error 後端 ERROR
|
||||
* API catch error function.
|
||||
* 401 errors are handled by the axios response interceptor in api/client.js.
|
||||
* @param {object} error 後端 ERROR
|
||||
* @param {string} toastMessage Toast 的提示文字
|
||||
* @returns {string} Error HTTP Status
|
||||
*/
|
||||
export default async function apiError(error, toastMessage) {
|
||||
if(error.request?.status === 401) {
|
||||
delete axios.defaults.headers.common["Authorization"];
|
||||
deleteCookie("luciaToken");
|
||||
return router.push('/login');
|
||||
}
|
||||
const loading = loadingStore();
|
||||
const $toast = useToast();
|
||||
await delay();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import apiClient from '@/api/client.js';
|
||||
import apiError from '@/module/apiError';
|
||||
import piniaLoginStore from '@/stores/login';
|
||||
import { JUST_CREATE_ACCOUNT_HOT_DURATION_MINS } from '@/constants/constants';
|
||||
@@ -87,7 +88,7 @@ export default defineStore('acctMgmtStore', {
|
||||
async getAllUserAccounts() {
|
||||
const apiGetUserList = `/api/users`;
|
||||
try {
|
||||
const response = await this.$axios.get(apiGetUserList);
|
||||
const response = await apiClient.get(apiGetUserList);
|
||||
const customizedResponseData = await this.customizeAllUserList(response.data);
|
||||
this.allUserAccoutList = await this.moveCurrentLoginUserToFirstRow(customizedResponseData);
|
||||
} catch (error) {
|
||||
@@ -135,7 +136,7 @@ export default defineStore('acctMgmtStore', {
|
||||
const apiCreateAccount = `/api/users`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.post(apiCreateAccount, userToCreate);
|
||||
const response = await apiClient.post(apiCreateAccount, userToCreate);
|
||||
if (response.status === 200) {
|
||||
this.isOneAccountJustCreate = true;
|
||||
this.justCreateUsername = userToCreate.username;
|
||||
@@ -154,7 +155,7 @@ export default defineStore('acctMgmtStore', {
|
||||
const apiDelete = `/api/users/${userToDelete}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.delete(apiDelete);
|
||||
const response = await apiClient.delete(apiDelete);
|
||||
return response.status === 200;
|
||||
} catch (error) {
|
||||
apiError(error, 'Failed to delete the account.');
|
||||
@@ -170,7 +171,7 @@ export default defineStore('acctMgmtStore', {
|
||||
const apiEdit = `/api/users/${userToEdit}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.put(apiEdit, {
|
||||
const response = await apiClient.put(apiEdit, {
|
||||
username: editDetail.newUsername ? editDetail.newUsername : editDetail.username,
|
||||
password: editDetail.password,
|
||||
name: editDetail.name,
|
||||
@@ -186,7 +187,7 @@ export default defineStore('acctMgmtStore', {
|
||||
const apiEdit = `/api/users/${userToEdit}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.put(apiEdit, {
|
||||
const response = await apiClient.put(apiEdit, {
|
||||
username: userToEdit,
|
||||
name: newName,
|
||||
is_active: this.currentViewingUser.is_active,
|
||||
@@ -202,7 +203,7 @@ export default defineStore('acctMgmtStore', {
|
||||
const apiEdit = `/api/users/${userToEdit}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.put(apiEdit, {
|
||||
const response = await apiClient.put(apiEdit, {
|
||||
username: userToEdit,
|
||||
name: this.currentViewingUser.name,
|
||||
password: newPwd,
|
||||
@@ -223,7 +224,7 @@ export default defineStore('acctMgmtStore', {
|
||||
const apiAddRole = `/api/users/${usernameToEdit}/roles/${roleCode}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.put(apiAddRole);
|
||||
const response = await apiClient.put(apiAddRole);
|
||||
return response.status === 200;
|
||||
} catch (error) {
|
||||
apiError(error, 'Failed to add role to the account.');
|
||||
@@ -238,7 +239,7 @@ export default defineStore('acctMgmtStore', {
|
||||
const apiDeleteRole = `/api/users/${usernameToEdit}/roles/${roleCode}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.delete(apiDeleteRole);
|
||||
const response = await apiClient.delete(apiDeleteRole);
|
||||
return response.status === 200;
|
||||
} catch (error) {
|
||||
apiError(error, 'Failed to delete a role frome the account.');
|
||||
@@ -252,7 +253,7 @@ export default defineStore('acctMgmtStore', {
|
||||
async getUserDetail(uniqueUsername: string): Promise<boolean> {
|
||||
const apiUserDetail = `/api/users/${uniqueUsername}`;
|
||||
try {
|
||||
const response = await this.$axios.get(apiUserDetail);
|
||||
const response = await apiClient.get(apiUserDetail);
|
||||
this.currentViewingUser = response.data;
|
||||
this.currentViewingUser.is_admin = response.data.roles.some(role => role.code === 'admin');
|
||||
return response.status === 200;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { defineStore } from "pinia";
|
||||
import moment from "moment";
|
||||
import apiClient from "@/api/client.js";
|
||||
import apiError from '@/module/apiError.js';
|
||||
import { Decimal } from 'decimal.js';
|
||||
|
||||
@@ -136,7 +137,7 @@ export default defineStore('allMapDataStore', {
|
||||
else api = `/api/logs/${logId}/discover`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allProcessMap = response.data.process_map;
|
||||
this.allBpmn = response.data.bpmn;
|
||||
this.allStats = response.data.stats;
|
||||
@@ -163,10 +164,10 @@ export default defineStore('allMapDataStore', {
|
||||
|
||||
try {
|
||||
let baseResponse;
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allTrace = response.data;
|
||||
if(baseLogId) {
|
||||
baseResponse = await this.$axios.get(baseApi);
|
||||
baseResponse = await apiClient.get(baseApi);
|
||||
this.allBaseTrace = baseResponse.data;
|
||||
}
|
||||
} catch(error) {
|
||||
@@ -190,7 +191,7 @@ export default defineStore('allMapDataStore', {
|
||||
else api = `/api/logs/${logId}/traces/${traceId}?start=${start}&page_size=20`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allTraceTaskSeq = response.data.task_seq;
|
||||
this.allCase = response.data.cases;
|
||||
this.allCase.forEach(c => {
|
||||
@@ -229,7 +230,7 @@ export default defineStore('allMapDataStore', {
|
||||
const api = `/api/logs/${logId}/traces/${traceId}?start=${start}&page_size=20`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allBaseTraceTaskSeq = response.data.task_seq;
|
||||
this.allBaseCase = response.data.cases;
|
||||
this.allBaseCase.forEach(c => {
|
||||
@@ -266,7 +267,7 @@ export default defineStore('allMapDataStore', {
|
||||
const api = `/api/filters/params?log_id=${logId}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allFilterTask = response.data.tasks;
|
||||
this.allFilterStartToEnd = response.data.sources;
|
||||
this.allFilterEndToStart = response.data.sinks;
|
||||
@@ -294,7 +295,7 @@ export default defineStore('allMapDataStore', {
|
||||
const api = `/api/filters/has-result?log_id=${logId}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.post(api, this.postRuleData)
|
||||
const response = await apiClient.post(api, this.postRuleData)
|
||||
this.hasResultRule = response.data.result;
|
||||
} catch(error) {
|
||||
apiError(error, 'Failed to load the Has Result.');
|
||||
@@ -308,7 +309,7 @@ export default defineStore('allMapDataStore', {
|
||||
const api = `/api/temp-filters?log_id=${logId}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.post(api, this.postRuleData)
|
||||
const response = await apiClient.post(api, this.postRuleData)
|
||||
this.tempFilterId = response.data.id;
|
||||
} catch(error) {
|
||||
apiError(error, 'Failed to add the Temporary Filters.');
|
||||
@@ -327,7 +328,7 @@ export default defineStore('allMapDataStore', {
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await this.$axios.post(api, createFilterObj);
|
||||
const response = await apiClient.post(api, createFilterObj);
|
||||
this.createFilterId = response.data.id;
|
||||
this.tempFilterId = null;
|
||||
}catch(error) {
|
||||
@@ -343,7 +344,7 @@ export default defineStore('allMapDataStore', {
|
||||
|
||||
if(createFilterId){
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.temporaryData = response.data.rules;
|
||||
this.logId = response.data.log.id;
|
||||
this.filterName = response.data.name;
|
||||
@@ -362,7 +363,7 @@ export default defineStore('allMapDataStore', {
|
||||
const data = this.postRuleData;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.put(api, data);
|
||||
const response = await apiClient.put(api, data);
|
||||
this.isUpdateFilter = response.status === 200;
|
||||
this.tempFilterId = null;
|
||||
}catch(error) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { defineStore } from "pinia";
|
||||
import apiClient from "@/api/client.js";
|
||||
import apiError from '@/module/apiError.js';
|
||||
|
||||
export default defineStore('compareStore', {
|
||||
@@ -21,7 +22,7 @@ export default defineStore('compareStore', {
|
||||
const api = `/api/compare?datasets=${encodeURIComponent(queryString)}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allCompareDashboardData = response.data;
|
||||
} catch(error) {
|
||||
apiError(error, 'Failed to load the Compare.');
|
||||
@@ -44,7 +45,7 @@ export default defineStore('compareStore', {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
|
||||
return response.data.stats;
|
||||
} catch(error) {
|
||||
@@ -58,7 +59,7 @@ export default defineStore('compareStore', {
|
||||
async getFileName(id) {
|
||||
id = Number(id)
|
||||
try {
|
||||
const response = await this.$axios.get('/api/files');
|
||||
const response = await apiClient.get('/api/files');
|
||||
const file = response.data.find(i => i.id === id);
|
||||
|
||||
if(file) return file.name;
|
||||
|
||||
@@ -2,6 +2,7 @@ import { defineStore } from "pinia";
|
||||
import moment from "moment";
|
||||
import { Decimal } from 'decimal.js';
|
||||
import abbreviateNumber from '@/module/abbreviateNumber.js';
|
||||
import apiClient from "@/api/client.js";
|
||||
import apiError from '@/module/apiError.js';
|
||||
|
||||
export default defineStore('conformanceStore', {
|
||||
@@ -201,7 +202,7 @@ export default defineStore('conformanceStore', {
|
||||
api = `/api/log-checks/params?log_id=${logId}`;
|
||||
}
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allConformanceTask = response.data.tasks;
|
||||
this.allCfmSeqStart = response.data.sources;
|
||||
this.allCfmSeqEnd = response.data.sinks;
|
||||
@@ -230,7 +231,7 @@ export default defineStore('conformanceStore', {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.post(api, data);
|
||||
const response = await apiClient.post(api, data);
|
||||
if(filterId !== null) {
|
||||
this.conformanceFilterTempCheckId = response.data.id;
|
||||
}
|
||||
@@ -266,7 +267,7 @@ export default defineStore('conformanceStore', {
|
||||
api = `/api/log-checks/${logCreateCheckId}`;
|
||||
}
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
if(!getRouteFile) {
|
||||
this.allConformanceTempReportData = response.data
|
||||
} else {
|
||||
@@ -302,7 +303,7 @@ export default defineStore('conformanceStore', {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allIssueTraces = response.data.traces;
|
||||
} catch(error) {
|
||||
apiError(error, 'Failed to Get the detail of a temporary log conformance issue.');
|
||||
@@ -336,7 +337,7 @@ export default defineStore('conformanceStore', {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allTaskSeq = response.data.task_seq;
|
||||
this.allCases = response.data.cases;
|
||||
return response.data.cases;
|
||||
@@ -366,7 +367,7 @@ export default defineStore('conformanceStore', {
|
||||
else if(logCreateCheckId !== null) api = `/api/log-checks/${logCreateCheckId}/loops/${loopNo}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allLoopTraces = response.data.traces;
|
||||
} catch(error) {
|
||||
apiError(error, 'Failed to Get the detail of a temporary log conformance loop.');
|
||||
@@ -392,7 +393,7 @@ export default defineStore('conformanceStore', {
|
||||
else if(logCreateCheckId !== null) api = `/api/log-checks/${logCreateCheckId}/loops/${loopNo}/traces/${traceId}?start=${start}&page_size=20`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allLoopTaskSeq = response.data.task_seq;
|
||||
this.allLoopCases = response.data.cases;
|
||||
return response.data.cases;
|
||||
@@ -422,7 +423,7 @@ export default defineStore('conformanceStore', {
|
||||
else api = `/api/log-checks?log_id=${logId}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.post(api, data);
|
||||
const response = await apiClient.post(api, data);
|
||||
if(filterId !== null) {
|
||||
this.conformanceFilterCreateCheckId = response.data.id;
|
||||
this.conformanceFilterTempCheckId = null;
|
||||
@@ -449,7 +450,7 @@ export default defineStore('conformanceStore', {
|
||||
else if(logCreateCheckId !== null) api = `/api/log-checks/${logCreateCheckId}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.put(api, data);
|
||||
const response = await apiClient.put(api, data);
|
||||
this.isUpdateConformance = response.status === 200;
|
||||
this.conformanceLogTempCheckId = null;
|
||||
this.conformanceFilterTempCheckId = null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from "pinia";
|
||||
import axios from "axios";
|
||||
import apiClient from "@/api/client.js";
|
||||
import moment from 'moment';
|
||||
import apiError from '@/module/apiError.js';
|
||||
import Swal from 'sweetalert2';
|
||||
@@ -66,7 +66,7 @@ export default defineStore('filesStore', {
|
||||
let parentLog = '';
|
||||
|
||||
try {
|
||||
const response = await axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
|
||||
this.allEventFiles = response.data;
|
||||
this.allEventFiles.forEach(o => {
|
||||
@@ -119,7 +119,7 @@ export default defineStore('filesStore', {
|
||||
|
||||
uploadloader(); // 進度條
|
||||
try {
|
||||
const response = await axios.post(api, fromData, config);
|
||||
const response = await apiClient.post(api, fromData, config);
|
||||
|
||||
this.uploadId = response.data.id;
|
||||
this.$router.push({name: 'Upload'});
|
||||
@@ -145,7 +145,7 @@ export default defineStore('filesStore', {
|
||||
const api = `/api/logs/csv-uploads/${uploadId}`;
|
||||
|
||||
try {
|
||||
const response = await axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allUploadDetail = response.data.preview;
|
||||
} catch(error) {
|
||||
apiError(error, 'Failed to get upload detail.');
|
||||
@@ -161,7 +161,7 @@ export default defineStore('filesStore', {
|
||||
|
||||
uploadloader(); // 進度條
|
||||
try {
|
||||
const response = await axios.post(api, data);
|
||||
const response = await apiClient.post(api, data);
|
||||
|
||||
this.uploadLogId = await response.data.id;
|
||||
await Swal.close(); // 關閉進度條
|
||||
@@ -211,7 +211,7 @@ export default defineStore('filesStore', {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
await axios.put(api, data);
|
||||
await apiClient.put(api, data);
|
||||
this.uploadFileName = null;
|
||||
await this.fetchAllFiles();
|
||||
} catch(error) {
|
||||
@@ -241,7 +241,7 @@ export default defineStore('filesStore', {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
const response = await axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allDependentsData = response.data;
|
||||
} catch(error) {
|
||||
apiError(error, 'Failed to get Dependents of the files.');
|
||||
@@ -276,7 +276,7 @@ export default defineStore('filesStore', {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
await axios.delete(api);
|
||||
await apiClient.delete(api);
|
||||
await this.fetchAllFiles();
|
||||
await deleteSuccess();
|
||||
} catch(error) {
|
||||
@@ -296,7 +296,7 @@ export default defineStore('filesStore', {
|
||||
loading.isLoading = true;
|
||||
api = `/api/deletion/${id}`;
|
||||
try {
|
||||
await axios.delete(api);
|
||||
await apiClient.delete(api);
|
||||
} catch(error) {
|
||||
apiError(error, 'Failed to Remove a Deletion Record.')
|
||||
} finally {
|
||||
@@ -329,7 +329,7 @@ export default defineStore('filesStore', {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const response = await axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
const csvData = response.data;
|
||||
const blob = new Blob([csvData], { type: 'text/csv' });
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { defineStore } from "pinia";
|
||||
import axios from 'axios';
|
||||
import apiClient from '@/api/client.js';
|
||||
import apiError from '@/module/apiError.js';
|
||||
import { deleteCookie, setCookie, setCookieWithoutExpiration, getCookie } from "../utils/cookieUtil";
|
||||
|
||||
@@ -51,7 +52,7 @@ export default defineStore('loginStore', {
|
||||
window.location.href = decodedUrl;
|
||||
} else {
|
||||
this.$router.push('/files');
|
||||
}
|
||||
}
|
||||
} catch(error) {
|
||||
this.isInvalid = true;
|
||||
};
|
||||
@@ -78,8 +79,6 @@ export default defineStore('loginStore', {
|
||||
|
||||
setCookieWithoutExpiration("luciaToken", newAccessToken);
|
||||
setCookie("luciaRefreshToken", newRefreshToken, Math.ceil((this.expired - Date.now()) / (24 * 60 * 60 * 1000)));
|
||||
|
||||
axios.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`;
|
||||
}
|
||||
} catch(error) {
|
||||
// 若refresh token 失敗則導向至登入頁面
|
||||
@@ -91,7 +90,6 @@ export default defineStore('loginStore', {
|
||||
* Logout, token expired
|
||||
*/
|
||||
logOut() {
|
||||
delete axios.defaults.headers.common["Authorization"];
|
||||
deleteCookie("luciaToken");
|
||||
|
||||
this.isLoggedIn = false;
|
||||
@@ -106,7 +104,7 @@ export default defineStore('loginStore', {
|
||||
const api = '/api/my-account';
|
||||
|
||||
try {
|
||||
const response = await axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
|
||||
this.userData = response.data;
|
||||
} catch(error) {
|
||||
@@ -120,7 +118,7 @@ export default defineStore('loginStore', {
|
||||
const api = '/api/my-account';
|
||||
|
||||
try {
|
||||
await axios.get(api);
|
||||
await apiClient.get(api);
|
||||
} catch(error) {
|
||||
this.$router.push('/login');
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { defineStore } from "pinia";
|
||||
import apiClient from "@/api/client.js";
|
||||
import apiError from '@/module/apiError.js';
|
||||
|
||||
export default defineStore('performanceStore', {
|
||||
@@ -36,7 +37,7 @@ export default defineStore('performanceStore', {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
const response = await apiClient.get(api);
|
||||
this.allPerformanceData = response.data;
|
||||
} catch(error) {
|
||||
apiError(error, 'Failed to load the Performance.');
|
||||
|
||||
8
src/types/shims-vue.d.ts
vendored
8
src/types/shims-vue.d.ts
vendored
@@ -4,11 +4,3 @@ declare module '*.vue' {
|
||||
const component: DefineComponent<{}, {}, any>;
|
||||
export default component;
|
||||
}
|
||||
|
||||
declare module 'vue/types/vue' {
|
||||
import { AxiosInstance } from 'axios';
|
||||
interface Vue {
|
||||
$axios: AxiosInstance;
|
||||
}
|
||||
}
|
||||
|
||||
7
src/types/store.d.ts
vendored
7
src/types/store.d.ts
vendored
@@ -1,7 +1,8 @@
|
||||
import { AxiosInstance } from 'axios';
|
||||
import 'pinia';
|
||||
import { Router } from 'vue-router';
|
||||
|
||||
declare module 'pinia' {
|
||||
export interface PiniaCustomProperties {
|
||||
$axios: AxiosInstance;
|
||||
$router: Router;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
8
src/types/vue-axios.d.ts
vendored
8
src/types/vue-axios.d.ts
vendored
@@ -1,7 +1 @@
|
||||
import { AxiosInstance } from 'axios';
|
||||
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
$axios: AxiosInstance;
|
||||
}
|
||||
}
|
||||
// vue-axios type declarations removed — API client is used directly
|
||||
|
||||
14
src/types/vue.d.ts
vendored
14
src/types/vue.d.ts
vendored
@@ -1,15 +1 @@
|
||||
import { AxiosInstance } from 'axios';
|
||||
import { App } from 'vue';
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$http: AxiosInstance;
|
||||
}
|
||||
}
|
||||
|
||||
// 將類型擴展到 Vue 應用實例
|
||||
declare module 'vue' {
|
||||
interface App {
|
||||
$http: AxiosInstance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,8 +56,6 @@
|
||||
import { onBeforeMount, computed, } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useRoute } from 'vue-router';
|
||||
import axios from 'axios';
|
||||
import { getCookie } from "@/utils/cookieUtil.js";
|
||||
import LoadingStore from '@/stores/loading.js';
|
||||
import AllMapDataStore from '@/stores/allMapData.js';
|
||||
import ConformanceStore from '@/stores/conformance.js';
|
||||
@@ -519,10 +517,6 @@
|
||||
|
||||
if (isCheckPage) {
|
||||
const conformanceStore = ConformanceStore();
|
||||
// Save token in Headers.
|
||||
const token = getCookie('luciaToken');
|
||||
|
||||
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||
switch (to.params.type) {
|
||||
case 'log':
|
||||
conformanceStore.conformanceLogCreateCheckId = to.params.fileId;
|
||||
|
||||
@@ -9,13 +9,11 @@
|
||||
</template>
|
||||
<script>
|
||||
import { storeToRefs } from 'pinia';
|
||||
import axios from 'axios';
|
||||
import LoadingStore from '@/stores/loading.js';
|
||||
import ConformanceStore from '@/stores/conformance.js';
|
||||
import StatusBar from '@/components/Discover/StatusBar.vue';
|
||||
import ConformanceResults from '@/components/Discover/Conformance/ConformanceResults.vue';
|
||||
import ConformanceSidebar from '@/components/Discover/Conformance/ConformanceSidebar.vue';
|
||||
import { getCookie } from "@/utils/cookieUtil.js";
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
@@ -99,10 +97,6 @@ export default {
|
||||
// ([^;]*):捕獲 "luciaToken" 的值,直到遇到下一個分號或字符串結尾。
|
||||
// .*$:匹配剩餘的字符,確保完整的提取。
|
||||
// |^.*$:在找不到 "luciaToken" 的情況下,匹配整個字符串。
|
||||
// 實際應用
|
||||
const token = getCookie('luciaToken');
|
||||
|
||||
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||
switch (to.params.type) {
|
||||
case 'log':
|
||||
conformanceStore.setConformanceLogCreateCheckId(to.params.fileId);
|
||||
|
||||
@@ -64,8 +64,6 @@
|
||||
import { onBeforeMount, computed, } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useRoute } from 'vue-router';
|
||||
import axios from 'axios';
|
||||
import { getCookie } from "@/utils/cookieUtil.js";
|
||||
import LoadingStore from '@/stores/loading.js';
|
||||
import AllMapDataStore from '@/stores/allMapData.js';
|
||||
import ConformanceStore from '@/stores/conformance.js';
|
||||
@@ -537,10 +535,6 @@ export default {
|
||||
|
||||
if (isCheckPage) {
|
||||
const conformanceStore = ConformanceStore();
|
||||
// Save token in Headers.
|
||||
const token = getCookie('luciaToken');
|
||||
|
||||
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||
switch (to.params.type) {
|
||||
case 'log':
|
||||
conformanceStore.conformanceLogCreateCheckId = to.params.fileId;
|
||||
|
||||
@@ -137,7 +137,6 @@
|
||||
</template>
|
||||
<script>
|
||||
import { storeToRefs, mapActions, } from 'pinia';
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
import LoadingStore from '@/stores/loading.js';
|
||||
import PerformanceStore from '@/stores/performance.js';
|
||||
@@ -152,7 +151,6 @@ import { simpleTimeLabel, followTimeLabel,
|
||||
} from '@/module/timeLabel.js';
|
||||
import FreqChart from './FreqChart.vue';
|
||||
import { PRIME_VUE_TICKS_LIMIT } from '../../../constants/constants.js';
|
||||
import { getCookie } from "@/utils/cookieUtil.js";
|
||||
|
||||
const primeVueTicksLimit = PRIME_VUE_TICKS_LIMIT;
|
||||
|
||||
@@ -921,10 +919,6 @@ export default {
|
||||
|
||||
if (isCheckPage) {
|
||||
const conformanceStore = ConformanceStore();
|
||||
// Save token in Headers.
|
||||
const token = getCookie('luciaToken');
|
||||
|
||||
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||
switch (to.params.type) {
|
||||
case 'log':
|
||||
conformanceStore.conformanceLogCreateCheckId = to.params.fileId;
|
||||
|
||||
@@ -85,11 +85,6 @@ export default {
|
||||
'refreshToken',
|
||||
],),
|
||||
},
|
||||
created() {
|
||||
// Save token in Headers.
|
||||
const token = getCookie('luciaToken');
|
||||
this.$http.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||
},
|
||||
// 重新整理畫面以及第一次進入網頁時,beforeRouteEnter這個hook會被執行,然而beforeRouteUpdate不會被執行
|
||||
// PSEUDOCODE
|
||||
// if (not logged in) {
|
||||
|
||||
Reference in New Issue
Block a user