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 @@
-
+
diff --git a/src/components/TheTopbar.vue b/src/components/TheTopbar.vue
index 69df0d65..184ba80d 100644
--- a/src/components/TheTopbar.vue
+++ b/src/components/TheTopbar.vue
@@ -72,23 +72,15 @@
-
-
- Prompt
-
-
- Are you sure you want to log out?
-
-
-
-
- NO
-
-
- YES
-
-
-
+
+ logout
+ Are you sure you want to log out?
+
+
+ NO
+ YES
+
+
@@ -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}`;
+}
+
+