From bf6ef5bae2e8e889862ce1a238c411dbef192f5e Mon Sep 17 00:00:00 2001 From: 593415420 <131138394+593415420@users.noreply.github.com> Date: Thu, 19 Jun 2025 17:59:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AF=B7=E6=B1=82=E7=9A=84?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E6=8B=A6=E6=88=AA=E6=B7=BB=E5=8A=A0token,?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=8B=E8=BD=BD=E6=96=87=E4=BB=B6=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E7=9A=84=E5=B0=81=E8=A3=85=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TheConnectingDialog.vue | 2 +- src/components/TheTopbar.vue | 44 ++++------- .../GcodefilesPanelTableRowFile.vue | 3 +- src/components/panels/KlippyStatePanel.vue | 3 +- .../panels/Machine/ConfigFilesPanel.vue | 6 +- .../LogfilesPanel/LogfilesPanelGenericLog.vue | 3 +- .../panels/Status/GcodefilesEntry.vue | 7 +- src/main.ts | 44 +++++++++++ src/store/files/actions.ts | 6 +- src/store/server/actions.ts | 4 +- src/utils/tool.ts | 79 +++++++++++++++++++ 11 files changed, 163 insertions(+), 38 deletions(-) create mode 100644 src/utils/tool.ts diff --git a/src/components/TheConnectingDialog.vue b/src/components/TheConnectingDialog.vue index 7e17812e..8e5cd82b 100644 --- a/src/components/TheConnectingDialog.vue +++ b/src/components/TheConnectingDialog.vue @@ -1,5 +1,5 @@ @@ -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() { diff --git a/src/components/panels/Gcodefiles/GcodefilesPanelTableRowFile.vue b/src/components/panels/Gcodefiles/GcodefilesPanelTableRowFile.vue index 6fc5a43c..36310686 100644 --- a/src/components/panels/Gcodefiles/GcodefilesPanelTableRowFile.vue +++ b/src/components/panels/Gcodefiles/GcodefilesPanelTableRowFile.vue @@ -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() { diff --git a/src/components/panels/KlippyStatePanel.vue b/src/components/panels/KlippyStatePanel.vue index 48607c81..00bfd362 100644 --- a/src/components/panels/KlippyStatePanel.vue +++ b/src/components/panels/KlippyStatePanel.vue @@ -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() { diff --git a/src/components/panels/Machine/ConfigFilesPanel.vue b/src/components/panels/Machine/ConfigFilesPanel.vue index 59cba3f5..b90090e9 100644 --- a/src/components/panels/Machine/ConfigFilesPanel.vue +++ b/src/components/panels/Machine/ConfigFilesPanel.vue @@ -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() { diff --git a/src/components/panels/Machine/LogfilesPanel/LogfilesPanelGenericLog.vue b/src/components/panels/Machine/LogfilesPanel/LogfilesPanelGenericLog.vue index 48970335..d759a265 100644 --- a/src/components/panels/Machine/LogfilesPanel/LogfilesPanelGenericLog.vue +++ b/src/components/panels/Machine/LogfilesPanel/LogfilesPanelGenericLog.vue @@ -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) } } diff --git a/src/components/panels/Status/GcodefilesEntry.vue b/src/components/panels/Status/GcodefilesEntry.vue index b2f6caa3..be47a944 100644 --- a/src/components/panels/Status/GcodefilesEntry.vue +++ b/src/components/panels/Status/GcodefilesEntry.vue @@ -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() { diff --git a/src/main.ts b/src/main.ts index 537fc9f6..c7fd6686 100644 --- a/src/main.ts +++ b/src/main.ts @@ -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)['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).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, { diff --git a/src/store/files/actions.ts b/src/store/files/actions.ts index 032e98e2..71679abd 100644 --- a/src/store/files/actions.ts +++ b/src/store/files/actions.ts @@ -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 = { reset({ commit }) { @@ -362,7 +363,10 @@ export const actions: ActionTree = { 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) { diff --git a/src/store/server/actions.ts b/src/store/server/actions.ts index 08ee3e57..303acee1 100644 --- a/src/store/server/actions.ts +++ b/src/store/server/actions.ts @@ -28,7 +28,7 @@ export const actions: ActionTree = { 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 = { 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 diff --git a/src/utils/tool.ts b/src/utils/tool.ts new file mode 100644 index 00000000..fc1b035b --- /dev/null +++ b/src/utils/tool.ts @@ -0,0 +1,79 @@ + +import service from './services'; + + +export const getDownloadLog = async (url: string): Promise => { + 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 => { + 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}`; +} + +