增加请求的全局拦截添加token,增加下载文件日志的封装函数

This commit is contained in:
593415420 2025-06-19 17:59:36 +08:00 committed by Lyn Lee
parent 867b73bb5a
commit bf6ef5bae2
11 changed files with 163 additions and 38 deletions

View File

@ -1,5 +1,5 @@
<template>
<v-dialog v-model="showDialog" persistent :width="400">
<v-dialog v-model="showDialog" persistent :width="450">
<panel :title="titleText" :icon="mdiConnection" card-class="the-connection-dialog" :margin-bottom="false">
<v-card-text v-if="connectingFailed" class="pt-5">
<connection-status :moonraker="false" />

View File

@ -72,23 +72,15 @@
</v-snackbar>
<emergency-stop-dialog :show-dialog="showEmergencyStopDialog" @close="showEmergencyStopDialog = false" />
<v-dialog v-model="dialog" max-width="290">
<v-card color="white" style="color: black;">
<v-card-title class="headings">
Prompt
</v-card-title>
<v-card-text style="color: black;">
Are you sure you want to log out?
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn text style="color: black;" @click="dialog = false">
NO
</v-btn>
<v-btn text style="color: black;" @click="goLogot">
YES
</v-btn>
</v-card-actions>
</v-card>
<v-card color="#1e1e1e">
<v-card-title class="headings">logout</v-card-title>
<v-card-text style="color:#FFF">Are you sure you want to log out?</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn text style="color: #E53935" @click="dialog = false">NO</v-btn>
<v-btn text style="color: #43a047" @click="goLogot">YES</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
@ -249,17 +241,15 @@ export default class TheTopbar extends Mixins(BaseMixin, ThemeMixin) {
this.naviDrawer = this.$vuetify.breakpoint.lgAndUp
}
}
dialog: boolean = false;
dialog: boolean = false
goLogot() {
this.dialog = false;
this.$services.post('/access/logout').then((response) => {
localStorage.removeItem('token');
this.$toast.success('logout successful', {
position: 'top'
});
window.location.reload();
});
this.$socket.emitAndWait('access.logout').then(({ res }) => {
localStorage.removeItem('token')
this.$toast.success('logout successful', { position: 'top' })
window.location.reload()
})
}
btnEmergencyStop() {

View File

@ -253,7 +253,8 @@ export default class GcodefilesPanelTableRowFile extends Mixins(BaseMixin, Contr
const filename = this.currentPath + '/' + this.item.filename
const href = this.apiUrl + '/server/files/gcodes' + escapePath(filename)
window.open(href)
// window.open(href)
this.$getDownloadZip(href,filename)
}
editFile() {

View File

@ -156,7 +156,8 @@ export default class KlippyStatePanel extends Mixins(BaseMixin) {
if ('href' in event.target.attributes) href = event.target.attributes.href.value
if ('href' in event.target.parentElement.attributes) href = event.target.parentElement.attributes.href.value
window.open(href)
// window.open(href)
this.$getDownloadLog(href)
}
powerOn() {

View File

@ -1033,8 +1033,10 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin, ThemeMixin) {
downloadFile() {
const filename = this.absolutePath + '/' + this.contextMenu.item.filename
const href = `${this.apiUrl}/server/files${escapePath(filename)}`
window.open(href)
// const href = `${this.apiUrl}/server/files${escapePath(filename)}`
// window.open(href)
const href = `/server/files${escapePath(filename)}`
this.$getDownloadZip(href,filename)
}
async downloadSelectedFiles() {

View File

@ -61,7 +61,8 @@ export default class LogfilesPanel extends Mixins(BaseMixin) {
if ('href' in event.target.attributes) href = event.target.attributes.href.value
if ('href' in event.target.parentElement.attributes) href = event.target.parentElement.attributes.href.value
window.open(href)
// window.open(href)
this.$getDownloadLog(href)
}
}
</script>

View File

@ -268,9 +268,12 @@ export default class StatusPanelGcodefilesEntry extends Mixins(BaseMixin, Contro
}
downloadFile() {
const href = this.apiUrl + '/server/files/gcodes/' + escapePath(this.item.filename)
// const href = this.apiUrl + '/server/files/gcodes/' + escapePath(this.item.filename)
window.open(href)
// window.open(href)
const href = '/server/files/gcodes/' + escapePath(this.item.filename)
this.$getDownloadZip(href)
}
renameFile() {

View File

@ -40,8 +40,11 @@ import { defaultMode } from './store/variables'
import axios from 'axios'
import services from '@/utils/services'
import { getDownloadLog,getDownloadZip} from '@/utils/tool'
Vue.prototype.$services = services
Vue.prototype.$getDownloadLog = getDownloadLog
Vue.prototype.$getDownloadZip = getDownloadZip
Vue.config.productionTip = false
@ -55,6 +58,47 @@ Vue.use(VueToast, {
duration: 3000,
})
axios.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token && !config.headers.Authorization) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, error => {
return Promise.reject(error);
});
const originalFetch = window.fetch;
window.fetch = async function (url, options: RequestInit = {}) {
try {
const token = localStorage.getItem('token');
if (token) {
if (!options.headers) {
options.headers = new Headers();
}
if (options.headers instanceof Headers) {
options.headers.set('Authorization', `Bearer ${token}`);
} else if (typeof options.headers === 'object' && !Array.isArray(options.headers)) {
(options.headers as Record<string, string>)['Authorization'] = `Bearer ${token}`;
} else {
const newHeaders = new Headers();
if (Array.isArray(options.headers)) {
options.headers.forEach(([key, value]) => newHeaders.set(key, value));
} else {
Object.entries(options.headers as Record<string, string>).forEach(([key, value]) => newHeaders.set(key, value));
}
newHeaders.set('Authorization', `Bearer ${token}`);
options.headers = newHeaders;
}
}
const response = await originalFetch.call(window, url, options);
return response;
} catch (error) {
console.error('Fetch error:', error);
return Promise.reject(error);
}
};
const isSafari = navigator.userAgent.includes('Safari') && navigator.userAgent.search('Chrome') === -1
const isTouch = 'ontouchstart' in window || (navigator.maxTouchPoints > 0 && navigator.maxTouchPoints !== 256)
Vue.use(OverlayScrollbarsPlugin, {

View File

@ -12,6 +12,7 @@ import i18n from '@/plugins/i18n'
import { hiddenDirectories, validGcodeExtensions } from '@/store/variables'
import axios, { AxiosProgressEvent } from 'axios'
import { BatchMessage } from '@/plugins/webSocketClient'
import { getDownloadZip } from '@/utils/tool'
export const actions: ActionTree<FileState, RootState> = {
reset({ commit }) {
@ -362,7 +363,10 @@ export const actions: ActionTree<FileState, RootState> = {
downloadZip({ rootGetters }, payload) {
const apiUrl = rootGetters['socket/getUrl']
const url = `${apiUrl}/server/files/${payload.destination.root}/${encodeURI(payload.destination.path)}`
window.open(url)
const urls = `/server/files/${payload.destination.root}/${encodeURI(payload.destination.path)}`
console.log(`获取下载的url`, urls);
getDownloadZip(urls);
},
rolloverLog(_, payload) {

View File

@ -28,7 +28,7 @@ export const actions: ActionTree<ServerState, RootState> = {
version: rootState.packageVersion,
type: 'web',
url: 'https://github.com/mainsail-crew/mainsail',
...(token ? { access_token: token }: {})
...(token ? { access_token: token } : {})
})
commit('setConnectionId', connection.connection_id)
} catch (e: any) {
@ -36,7 +36,7 @@ export const actions: ActionTree<ServerState, RootState> = {
this.dispatch('socket/setConnectionFailed', e.message)
}
if (e.code === 400) { localStorage.removeItem("token"); window.location.reload() }
if (e.code === 400||e.message=='JWT Expired') { localStorage.removeItem("token"); window.location.reload() }
Vue.prototype.$toast.error(e.message, { position: 'top' });
window.console.error('Error while identifying client: ' + e.message)
return

79
src/utils/tool.ts Normal file
View File

@ -0,0 +1,79 @@
import service from './services';
export const getDownloadLog = async (url: string): Promise<void> => {
try {
const response = await service.get(url);
if (response) {
let urls = JSON.stringify(response.data)
const blob = new Blob([JSON.parse(urls)], { type: 'text/plain' });
const objectUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = objectUrl;
let time = getDateTime()
link.download = `${time}.log`;
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(objectUrl);
document.body.removeChild(link);
}
} catch (error) {
if (error instanceof Error) {
console.error(error.message);
} else {
console.error(error);
}
}
};
export const getDownloadZip = async (url: string, filename?: string): Promise<void> => {
try {
const response = await service.get(url, { responseType: 'blob' });
if (response) {
let type = 'application/zip'
if (filename) {
let index = filename.lastIndexOf('.')
if (index !== -1) {
type = 'application/' + filename.substring(index + 1)
}
}
const blob = new Blob([response.data], { type: type });
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
if (filename) {
link.setAttribute('download', filename);
} else {
let time = getDateTime()
link.setAttribute('download', `${time}`);
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(downloadUrl);
}
} catch (error) {
if (error instanceof Error) {
console.error(error.message);
} else {
console.error(error);
}
}
}
//获取当前时间
function getDateTime() {
let date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
let hour = date.getHours();
let minute = date.getMinutes();
let second = date.getSeconds();
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}