Browse Source

完成“关闭窗口不登出”

master
hejl 1 week ago
parent
commit
6c79b27667
  1. 71
      gofaster/app/dist/renderer/js/index.js
  2. 167
      gofaster/app/dist/renderer/src_renderer_views_Settings_vue.js
  3. 41
      gofaster/app/src/main/index.js
  4. 69
      gofaster/app/src/renderer/components/MainLayout.vue
  5. 26
      gofaster/app/src/renderer/views/Settings.vue

71
gofaster/app/dist/renderer/js/index.js vendored

@ -3280,9 +3280,7 @@ __webpack_require__.r(__webpack_exports__); @@ -3280,9 +3280,7 @@ __webpack_require__.r(__webpack_exports__);
router.push('/')
}
const handleLoginSuccess = async (response) => {
console.log('登录成功响应:', response)
const handleLoginSuccess = async (response) => {
// 检查响应数据结构 - 后端返回的是 { code: 200, message: "登录成功", data: { token: "...", user: {...} } }
const responseData = response.data || response
const token = responseData.token
@ -3306,7 +3304,7 @@ __webpack_require__.r(__webpack_exports__); @@ -3306,7 +3304,7 @@ __webpack_require__.r(__webpack_exports__);
try {
// 登录成功后,调用后端接口获取完整的用户信息
const userResponse = await _services_userService__WEBPACK_IMPORTED_MODULE_3__.userService.getCurrentUser(token)
console.log('获取到的完整用户信息:', userResponse)
if (userResponse.data) {
const userData = userResponse.data
@ -3339,8 +3337,7 @@ __webpack_require__.r(__webpack_exports__); @@ -3339,8 +3337,7 @@ __webpack_require__.r(__webpack_exports__);
}
localStorage.setItem('user', JSON.stringify(userForStorage))
console.log('更新后的用户信息:', currentUser)
console.log(`欢迎回来,${currentUser.name}`)
// 检查是否需要强制修改密码
if (userData.force_change_password) {
@ -3413,10 +3410,7 @@ __webpack_require__.r(__webpack_exports__); @@ -3413,10 +3410,7 @@ __webpack_require__.r(__webpack_exports__);
}
// 强制触发响应式更新
(0,vue__WEBPACK_IMPORTED_MODULE_0__.nextTick)(() => {
console.log('强制更新后的登录状态:', isLoggedIn.value)
console.log('强制更新后的用户信息:', currentUser)
})
(0,vue__WEBPACK_IMPORTED_MODULE_0__.nextTick)()
}
const handleShowMessage = (message) => {
@ -3470,7 +3464,6 @@ __webpack_require__.r(__webpack_exports__); @@ -3470,7 +3464,6 @@ __webpack_require__.r(__webpack_exports__);
const inactiveTime = (currentTime - lastActivityTime) / 1000 / 60 // 转换为分钟
if (inactiveTime >= sessionTimeoutMinutes.value) {
console.log('会话超时,自动退出登录')
showToastMessage('warning', '会话超时', '您的会话已超时,将自动退出登录')
// 延迟2秒后执行退出登录,让用户看到提示
@ -3494,7 +3487,6 @@ __webpack_require__.r(__webpack_exports__); @@ -3494,7 +3487,6 @@ __webpack_require__.r(__webpack_exports__);
if (!isLoggedIn.value) return
try {
console.log('开始执行退出登录')
// 获取token并尝试调用后端接口
const token = localStorage.getItem('token')
@ -3529,7 +3521,6 @@ __webpack_require__.r(__webpack_exports__); @@ -3529,7 +3521,6 @@ __webpack_require__.r(__webpack_exports__);
// 停止会话超时检测
stopSessionTimeoutCheck()
console.log('退出登录完成')
} catch (error) {
console.error('退出登录失败:', error)
}
@ -3537,14 +3528,42 @@ __webpack_require__.r(__webpack_exports__); @@ -3537,14 +3528,42 @@ __webpack_require__.r(__webpack_exports__);
// 处理应用关闭事件(主进程事件)
const handleAppWillClose = () => {
console.log('主进程 app-will-close 事件触发')
// 检查用户设置,如果选择"关闭窗口不登出",则不执行退出登录
try {
const userSettings = localStorage.getItem('gofaster-settings')
if (userSettings) {
const settings = JSON.parse(userSettings)
if (settings.keepLoginOnClose) {
return
}
}
} catch (error) {
console.error('读取用户设置失败:', error)
}
// 执行退出登录
performLogout()
}
// 处理页面卸载事件
const handleBeforeUnload = () => {
if (isLoggedIn.value) {
console.log('beforeunload 事件触发,执行退出登录')
// 检查用户设置,如果选择"关闭窗口不登出",则不执行退出登录
try {
const userSettings = localStorage.getItem('gofaster-settings')
if (userSettings) {
const settings = JSON.parse(userSettings)
if (settings.keepLoginOnClose) {
return
}
}
} catch (error) {
console.error('读取用户设置失败:', error)
}
// 执行退出登录
performLogout()
}
}
@ -3552,7 +3571,21 @@ __webpack_require__.r(__webpack_exports__); @@ -3552,7 +3571,21 @@ __webpack_require__.r(__webpack_exports__);
// 处理页面隐藏事件
const handleVisibilityChange = () => {
if (document.visibilityState === 'hidden' && isLoggedIn.value) {
console.log('页面隐藏,可能应用即将关闭,执行退出登录')
// 检查用户设置,如果选择"关闭窗口不登出",则不执行退出登录
try {
const userSettings = localStorage.getItem('gofaster-settings')
if (userSettings) {
const settings = JSON.parse(userSettings)
if (settings.keepLoginOnClose) {
return
}
}
} catch (error) {
console.error('读取用户设置失败:', error)
}
// 执行退出登录
performLogout()
}
}
@ -3718,22 +3751,18 @@ __webpack_require__.r(__webpack_exports__); @@ -3718,22 +3751,18 @@ __webpack_require__.r(__webpack_exports__);
// 1. 监听主进程应用关闭事件(主要方案)
if (window.electronAPI && window.electronAPI.onAppWillClose) {
console.log('注册主进程 app-will-close 事件监听器')
window.electronAPI.onAppWillClose(handleAppWillClose)
} else {
console.warn('electronAPI不可用,无法注册主进程应用关闭事件监听器')
}
// 2. 监听页面卸载事件(备用方案)
console.log('注册 beforeunload 事件监听器')
window.addEventListener('beforeunload', handleBeforeUnload)
// 3. 监听页面隐藏事件(额外备用方案)
console.log('注册 visibilitychange 事件监听器')
document.addEventListener('visibilitychange', handleVisibilityChange)
// 4. 监听窗口焦点丢失事件(Windows 特有,暂时只记录不执行退出)
console.log('注册 window blur 事件监听器')
window.addEventListener('blur', handleWindowBlur)
// 检查登录状态
@ -9061,7 +9090,7 @@ __webpack_require__.r(__webpack_exports__); @@ -9061,7 +9090,7 @@ __webpack_require__.r(__webpack_exports__);
/******/
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("d5031258c9bcadee")
/******/ __webpack_require__.h = () => ("8cd3ca376637cd04")
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */

167
gofaster/app/dist/renderer/src_renderer_views_Settings_vue.js vendored

@ -124,6 +124,15 @@ ___CSS_LOADER_EXPORT___.push([module.id, ` @@ -124,6 +124,15 @@ ___CSS_LOADER_EXPORT___.push([module.id, `
transform: translateX(26px);
}
/* 设置描述文字 */
.setting-description[data-v-a5c10072] {
font-size: 12px;
color: var(--text-secondary);
margin-top: 8px;
line-height: 1.4;
opacity: 0.8;
}
/* 操作按钮 */
.settings-actions[data-v-a5c10072] {
display: flex;
@ -236,7 +245,7 @@ __webpack_require__.r(__webpack_exports__); @@ -236,7 +245,7 @@ __webpack_require__.r(__webpack_exports__);
retryCount: 3,
// 用户设置
autoLogin: false,
keepLoginOnClose: false,
rememberPassword: false,
sessionTimeout: 30,
@ -333,7 +342,7 @@ __webpack_require__.r(__webpack_exports__); @@ -333,7 +342,7 @@ __webpack_require__.r(__webpack_exports__);
// 显示保存成功提示
showToastMessage('success', '保存成功', '用户设置已成功保存')
console.log('用户设置已保存')
} catch (error) {
console.error('保存用户设置失败:', error)
// 显示保存失败提示
@ -410,37 +419,36 @@ const _hoisted_11 = { class: "setting-item" } @@ -410,37 +419,36 @@ const _hoisted_11 = { class: "setting-item" }
const _hoisted_12 = { class: "toggle-switch" }
const _hoisted_13 = { class: "setting-item" }
const _hoisted_14 = { class: "toggle-switch" }
const _hoisted_15 = { class: "setting-item" }
const _hoisted_16 = { class: "settings-section" }
const _hoisted_17 = { class: "setting-item" }
const _hoisted_18 = { class: "toggle-switch" }
const _hoisted_19 = { class: "setting-item" }
const _hoisted_20 = { class: "toggle-switch" }
const _hoisted_21 = { class: "setting-item" }
const _hoisted_22 = { class: "settings-section" }
const _hoisted_15 = { class: "settings-section" }
const _hoisted_16 = { class: "setting-item" }
const _hoisted_17 = { class: "toggle-switch" }
const _hoisted_18 = { class: "setting-item" }
const _hoisted_19 = { class: "toggle-switch" }
const _hoisted_20 = { class: "setting-item" }
const _hoisted_21 = { class: "settings-section" }
const _hoisted_22 = { class: "setting-item" }
const _hoisted_23 = { class: "setting-item" }
const _hoisted_24 = { class: "setting-item" }
const _hoisted_25 = { class: "toggle-switch" }
const _hoisted_26 = { class: "setting-item" }
const _hoisted_27 = { class: "settings-actions" }
const _hoisted_28 = ["disabled"]
const _hoisted_29 = { key: 0 }
const _hoisted_30 = { key: 1 }
const _hoisted_31 = { key: 2 }
const _hoisted_24 = { class: "toggle-switch" }
const _hoisted_25 = { class: "setting-item" }
const _hoisted_26 = { class: "settings-actions" }
const _hoisted_27 = ["disabled"]
const _hoisted_28 = { key: 0 }
const _hoisted_29 = { key: 1 }
const _hoisted_30 = { key: 2 }
function render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_Toast = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Toast")
return ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_1, [
_cache[45] || (_cache[45] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", { class: "page-header" }, [
_cache[43] || (_cache[43] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", { class: "page-header" }, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h2", null, "用户设置")
], -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_2, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 个人偏好 "),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_3, [
_cache[23] || (_cache[23] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "个人偏好", -1 /* CACHED */)),
_cache[22] || (_cache[22] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "个人偏好", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_4, [
_cache[18] || (_cache[18] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "应用名称", -1 /* CACHED */)),
_cache[17] || (_cache[17] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "应用名称", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (($setup.settings.appName) = $event)),
type: "text",
@ -450,10 +458,10 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { @@ -450,10 +458,10 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_5, [
_cache[20] || (_cache[20] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "语言", -1 /* CACHED */)),
_cache[19] || (_cache[19] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "语言", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("select", {
"onUpdate:modelValue": _cache[1] || (_cache[1] = $event => (($setup.settings.language) = $event))
}, _cache[19] || (_cache[19] = [
}, _cache[18] || (_cache[18] = [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "zh-CN" }, "简体中文", -1 /* CACHED */),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "en-US" }, "English", -1 /* CACHED */)
]), 512 /* NEED_PATCH */), [
@ -461,11 +469,11 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { @@ -461,11 +469,11 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_6, [
_cache[22] || (_cache[22] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "主题", -1 /* CACHED */)),
_cache[21] || (_cache[21] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "主题", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("select", {
"onUpdate:modelValue": _cache[2] || (_cache[2] = $event => (($setup.settings.theme) = $event)),
onChange: _cache[3] || (_cache[3] = $event => ($setup.handleThemeChange($setup.settings.theme)))
}, _cache[21] || (_cache[21] = [
}, _cache[20] || (_cache[20] = [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "light" }, "浅色主题", -1 /* CACHED */),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "dark" }, "深色主题", -1 /* CACHED */),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "auto" }, "跟随系统", -1 /* CACHED */)
@ -476,9 +484,9 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { @@ -476,9 +484,9 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 应用设置 "),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_7, [
_cache[26] || (_cache[26] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "应用设置", -1 /* CACHED */)),
_cache[25] || (_cache[25] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "应用设置", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_8, [
_cache[24] || (_cache[24] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "请求超时时间 (秒)", -1 /* CACHED */)),
_cache[23] || (_cache[23] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "请求超时时间 (秒)", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[4] || (_cache[4] = $event => (($setup.settings.timeout) = $event)),
type: "number",
@ -489,7 +497,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { @@ -489,7 +497,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_9, [
_cache[25] || (_cache[25] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "自动重试次数", -1 /* CACHED */)),
_cache[24] || (_cache[24] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "自动重试次数", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[5] || (_cache[5] = $event => (($setup.settings.retryCount) = $event)),
type: "number",
@ -502,25 +510,25 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { @@ -502,25 +510,25 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 用户设置 "),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_10, [
_cache[32] || (_cache[32] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "用户设置", -1 /* CACHED */)),
_cache[30] || (_cache[30] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "用户设置", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_11, [
_cache[28] || (_cache[28] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "自动登录", -1 /* CACHED */)),
_cache[27] || (_cache[27] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "关闭窗口不登出", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_12, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[6] || (_cache[6] = $event => (($setup.settings.autoLogin) = $event)),
"onUpdate:modelValue": _cache[6] || (_cache[6] = $event => (($setup.settings.keepLoginOnClose) = $event)),
type: "checkbox",
id: "autoLogin"
id: "keepLoginOnClose"
}, null, 512 /* NEED_PATCH */), [
[vue__WEBPACK_IMPORTED_MODULE_0__.vModelCheckbox, $setup.settings.autoLogin]
[vue__WEBPACK_IMPORTED_MODULE_0__.vModelCheckbox, $setup.settings.keepLoginOnClose]
]),
_cache[27] || (_cache[27] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
for: "autoLogin",
_cache[26] || (_cache[26] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
for: "keepLoginOnClose",
class: "toggle-label"
}, null, -1 /* CACHED */))
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_13, [
_cache[30] || (_cache[30] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "记住密码", -1 /* CACHED */)),
_cache[29] || (_cache[29] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "记住密码", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_14, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[7] || (_cache[7] = $event => (($setup.settings.rememberPassword) = $event)),
@ -529,63 +537,52 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { @@ -529,63 +537,52 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
}, null, 512 /* NEED_PATCH */), [
[vue__WEBPACK_IMPORTED_MODULE_0__.vModelCheckbox, $setup.settings.rememberPassword]
]),
_cache[29] || (_cache[29] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
_cache[28] || (_cache[28] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
for: "rememberPassword",
class: "toggle-label"
}, null, -1 /* CACHED */))
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_15, [
_cache[31] || (_cache[31] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "会话超时时间 (分钟)", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[8] || (_cache[8] = $event => (($setup.settings.sessionTimeout) = $event)),
type: "number",
min: "15",
max: "1440"
}, null, 512 /* NEED_PATCH */), [
[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.settings.sessionTimeout]
])
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 通知偏好 "),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_16, [
_cache[38] || (_cache[38] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "通知偏好", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_17, [
_cache[34] || (_cache[34] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "桌面通知", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_18, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_15, [
_cache[36] || (_cache[36] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "通知偏好", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_16, [
_cache[32] || (_cache[32] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "桌面通知", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_17, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[9] || (_cache[9] = $event => (($setup.settings.desktopNotifications) = $event)),
"onUpdate:modelValue": _cache[8] || (_cache[8] = $event => (($setup.settings.desktopNotifications) = $event)),
type: "checkbox",
id: "desktopNotifications"
}, null, 512 /* NEED_PATCH */), [
[vue__WEBPACK_IMPORTED_MODULE_0__.vModelCheckbox, $setup.settings.desktopNotifications]
]),
_cache[33] || (_cache[33] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
_cache[31] || (_cache[31] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
for: "desktopNotifications",
class: "toggle-label"
}, null, -1 /* CACHED */))
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_19, [
_cache[36] || (_cache[36] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "声音提醒", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_20, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_18, [
_cache[34] || (_cache[34] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "声音提醒", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_19, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[10] || (_cache[10] = $event => (($setup.settings.soundNotifications) = $event)),
"onUpdate:modelValue": _cache[9] || (_cache[9] = $event => (($setup.settings.soundNotifications) = $event)),
type: "checkbox",
id: "soundNotifications"
}, null, 512 /* NEED_PATCH */), [
[vue__WEBPACK_IMPORTED_MODULE_0__.vModelCheckbox, $setup.settings.soundNotifications]
]),
_cache[35] || (_cache[35] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
_cache[33] || (_cache[33] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
for: "soundNotifications",
class: "toggle-label"
}, null, -1 /* CACHED */))
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_21, [
_cache[37] || (_cache[37] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "消息提醒间隔 (秒)", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_20, [
_cache[35] || (_cache[35] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "消息提醒间隔 (秒)", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[11] || (_cache[11] = $event => (($setup.settings.notificationInterval) = $event)),
"onUpdate:modelValue": _cache[10] || (_cache[10] = $event => (($setup.settings.notificationInterval) = $event)),
type: "number",
min: "5",
max: "300"
@ -595,12 +592,12 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { @@ -595,12 +592,12 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 数据管理 "),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_22, [
_cache[44] || (_cache[44] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "数据管理", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_23, [
_cache[39] || (_cache[39] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "数据缓存大小 (MB)", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_21, [
_cache[42] || (_cache[42] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "数据管理", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_22, [
_cache[37] || (_cache[37] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "数据缓存大小 (MB)", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[12] || (_cache[12] = $event => (($setup.settings.cacheSize) = $event)),
"onUpdate:modelValue": _cache[11] || (_cache[11] = $event => (($setup.settings.cacheSize) = $event)),
type: "number",
min: "50",
max: "1000"
@ -608,27 +605,27 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { @@ -608,27 +605,27 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.settings.cacheSize]
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_24, [
_cache[41] || (_cache[41] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "自动清理缓存", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_25, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_23, [
_cache[39] || (_cache[39] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "自动清理缓存", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_24, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", {
"onUpdate:modelValue": _cache[13] || (_cache[13] = $event => (($setup.settings.autoCleanCache) = $event)),
"onUpdate:modelValue": _cache[12] || (_cache[12] = $event => (($setup.settings.autoCleanCache) = $event)),
type: "checkbox",
id: "autoCleanCache"
}, null, 512 /* NEED_PATCH */), [
[vue__WEBPACK_IMPORTED_MODULE_0__.vModelCheckbox, $setup.settings.autoCleanCache]
]),
_cache[40] || (_cache[40] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
_cache[38] || (_cache[38] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", {
for: "autoCleanCache",
class: "toggle-label"
}, null, -1 /* CACHED */))
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_26, [
_cache[43] || (_cache[43] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "数据备份频率", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_25, [
_cache[41] || (_cache[41] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "数据备份频率", -1 /* CACHED */)),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("select", {
"onUpdate:modelValue": _cache[14] || (_cache[14] = $event => (($setup.settings.backupFrequency) = $event))
}, _cache[42] || (_cache[42] = [
"onUpdate:modelValue": _cache[13] || (_cache[13] = $event => (($setup.settings.backupFrequency) = $event))
}, _cache[40] || (_cache[40] = [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "daily" }, "每日", -1 /* CACHED */),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "weekly" }, "每周", -1 /* CACHED */),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "monthly" }, "每月", -1 /* CACHED */),
@ -639,28 +636,28 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { @@ -639,28 +636,28 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 操作按钮 "),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_27, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_26, [
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", {
class: "btn btn-secondary",
onClick: _cache[15] || (_cache[15] = (...args) => ($setup.resetSettings && $setup.resetSettings(...args)))
onClick: _cache[14] || (_cache[14] = (...args) => ($setup.resetSettings && $setup.resetSettings(...args)))
}, " 重置所有设置 "),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", {
class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["btn", $setup.saveButtonClass]),
onClick: _cache[16] || (_cache[16] = (...args) => ($setup.saveSettings && $setup.saveSettings(...args))),
onClick: _cache[15] || (_cache[15] = (...args) => ($setup.saveSettings && $setup.saveSettings(...args))),
disabled: !$setup.hasChanges || $setup.isSaving
}, [
($setup.isSaving)
? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_29, "保存中..."))
? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_28, "保存中..."))
: ($setup.hasChanges)
? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_30, "保存更改"))
: ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_31, "已保存"))
], 10 /* CLASS, PROPS */, _hoisted_28)
? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_29, "保存更改"))
: ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_30, "已保存"))
], 10 /* CLASS, PROPS */, _hoisted_27)
])
]),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" Toast 消息提示 "),
(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Toast, {
visible: $setup.showToast,
"onUpdate:visible": _cache[17] || (_cache[17] = $event => (($setup.showToast) = $event)),
"onUpdate:visible": _cache[16] || (_cache[16] = $event => (($setup.showToast) = $event)),
type: $setup.toastConfig.type,
title: $setup.toastConfig.title,
content: $setup.toastConfig.content,

41
gofaster/app/src/main/index.js

@ -13,7 +13,6 @@ process.env.LC_ALL = 'zh_CN.UTF-8' @@ -13,7 +13,6 @@ process.env.LC_ALL = 'zh_CN.UTF-8'
// 获取项目根目录绝对路径
const appRoot = path.resolve(__dirname, '../..')
console.log('Application root:', appRoot)
// 获取本地IP地址
function getLocalIPAddresses() {
@ -123,7 +122,6 @@ function initLogging() { @@ -123,7 +122,6 @@ function initLogging() {
originalWarn.apply(console, args)
}
console.log('日志系统已初始化,日志文件:', logFilePath)
} catch (error) {
console.error('初始化日志系统失败:', error)
}
@ -144,7 +142,6 @@ if (getIsDev() && !process.argv.includes('--watch')) { @@ -144,7 +142,6 @@ if (getIsDev() && !process.argv.includes('--watch')) {
/\.git|[\/\\]\./
]
});
console.log('Hot reload enabled');
} catch (error) {
console.log('Hot reload failed:', error.message);
}
@ -152,7 +149,6 @@ if (getIsDev() && !process.argv.includes('--watch')) { @@ -152,7 +149,6 @@ if (getIsDev() && !process.argv.includes('--watch')) {
// 监听文件变化(用于watch模式)
if (getIsDev() && process.argv.includes('--watch')) {
console.log('Watch mode enabled, monitoring file changes...');
// 监听dist目录变化
const distPath = path.join(appRoot, 'dist/renderer');
@ -168,7 +164,6 @@ if (getIsDev() && process.argv.includes('--watch')) { @@ -168,7 +164,6 @@ if (getIsDev() && process.argv.includes('--watch')) {
reloadTimeout = setTimeout(() => {
try {
console.log(`File changed: ${filename}, reloading page...`);
mainWindow.reload();
} catch (error) {
console.log('Page reload failed:', error.message);
@ -233,13 +228,11 @@ function createWindow() { @@ -233,13 +228,11 @@ function createWindow() {
mainWindow.setFullScreen(true)
}
console.log('Main window created');
// 开发环境下抑制安全警告
if (getIsDev()) {
mainWindow.webContents.on('did-frame-finish-load', () => {
// 移除有问题的JavaScript执行,避免IPC通信错误
console.log('Page loaded, DevTools ready');
// 简化JavaScript注入,避免序列化错误
mainWindow.webContents.executeJavaScript(`
@ -267,24 +260,14 @@ function createWindow() { @@ -267,24 +260,14 @@ function createWindow() {
originalError.apply(console, args);
};
console.log('Console warning suppression enabled');
`).catch(err => {
console.log('JavaScript injection failed:', err.message);
// 注入失败不影响应用运行
});
});
// 添加页面加载错误处理
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL) => {
console.log('Page load failed:', errorDescription);
// 可以在这里添加重试逻辑
});
// 添加渲染进程崩溃处理
mainWindow.webContents.on('render-process-gone', (event, details) => {
console.log('Render process gone:', details.reason);
// 可以在这里添加恢复逻辑
});
// 抑制Electron安全警告
mainWindow.webContents.on('console-message', (event, level, message, line, sourceId) => {
@ -307,16 +290,13 @@ function createWindow() { @@ -307,16 +290,13 @@ function createWindow() {
}
const loadPath = path.join(appRoot, 'dist/renderer/index.html')
console.log('Loading:', loadPath)
// 检查文件是否存在
if (!fs.existsSync(loadPath)) {
console.log('File not found, waiting for build completion...');
// 在watch模式下等待文件构建完成
if (getIsDev() && process.argv.includes('--watch')) {
const checkFile = () => {
if (fs.existsSync(loadPath)) {
console.log('Build completed, starting to load...');
loadMainWindow();
} else {
setTimeout(checkFile, 1000); // 每秒检查一次
@ -337,7 +317,6 @@ function createWindow() { @@ -337,7 +317,6 @@ function createWindow() {
function loadMainWindow() {
mainWindow.loadFile(loadPath).then(() => {
console.log('Page loaded successfully');
// 开发环境下打开开发者工具
if (getIsDev()) {
mainWindow.webContents.openDevTools()
@ -403,7 +382,6 @@ function createWindow() { @@ -403,7 +382,6 @@ function createWindow() {
// 窗口即将关闭事件(更早触发)
mainWindow.on('close', (event) => {
console.log('窗口即将关闭,发送退出登录事件')
// 立即发送事件,不等待
if (!mainWindow.isDestroyed()) {
mainWindow.webContents.send('app-will-close')
@ -425,10 +403,6 @@ function createWindow() { @@ -425,10 +403,6 @@ function createWindow() {
}
app.whenReady().then(() => {
console.log('Electron app ready');
// 输出开发环境状态
console.log('Development environment:', getIsDev());
// 初始化窗口状态管理器
windowStateManager = new WindowStateManager('main')
@ -630,17 +604,6 @@ app.on('window-all-closed', () => { @@ -630,17 +604,6 @@ app.on('window-all-closed', () => {
}
})
// 应用即将退出时的处理
app.on('before-quit', () => {
// 由于已经在窗口 close 事件中处理了退出登录,这里不需要再次调用 app.quit()
// 避免无限递归调用
console.log('应用即将退出,退出登录已在窗口关闭时处理')
})
// 应用退出时的处理
app.on('quit', () => {
console.log('应用退出,已通知渲染进程执行退出登录')
})
app.on('activate', () => {
if (mainWindow === null) createWindow()

69
gofaster/app/src/renderer/components/MainLayout.vue

@ -541,9 +541,7 @@ export default { @@ -541,9 +541,7 @@ export default {
router.push('/')
}
const handleLoginSuccess = async (response) => {
console.log('登录成功响应:', response)
const handleLoginSuccess = async (response) => {
// - { code: 200, message: "", data: { token: "...", user: {...} } }
const responseData = response.data || response
const token = responseData.token
@ -567,7 +565,7 @@ export default { @@ -567,7 +565,7 @@ export default {
try {
//
const userResponse = await userService.getCurrentUser(token)
console.log('获取到的完整用户信息:', userResponse)
if (userResponse.data) {
const userData = userResponse.data
@ -600,8 +598,7 @@ export default { @@ -600,8 +598,7 @@ export default {
}
localStorage.setItem('user', JSON.stringify(userForStorage))
console.log('更新后的用户信息:', currentUser)
console.log(`欢迎回来,${currentUser.name}`)
//
if (userData.force_change_password) {
@ -674,10 +671,7 @@ export default { @@ -674,10 +671,7 @@ export default {
}
//
nextTick(() => {
console.log('强制更新后的登录状态:', isLoggedIn.value)
console.log('强制更新后的用户信息:', currentUser)
})
nextTick()
}
const handleShowMessage = (message) => {
@ -731,7 +725,6 @@ export default { @@ -731,7 +725,6 @@ export default {
const inactiveTime = (currentTime - lastActivityTime) / 1000 / 60 //
if (inactiveTime >= sessionTimeoutMinutes.value) {
console.log('会话超时,自动退出登录')
showToastMessage('warning', '会话超时', '您的会话已超时,将自动退出登录')
// 2退
@ -755,7 +748,6 @@ export default { @@ -755,7 +748,6 @@ export default {
if (!isLoggedIn.value) return
try {
console.log('开始执行退出登录')
// token
const token = localStorage.getItem('token')
@ -790,7 +782,6 @@ export default { @@ -790,7 +782,6 @@ export default {
//
stopSessionTimeoutCheck()
console.log('退出登录完成')
} catch (error) {
console.error('退出登录失败:', error)
}
@ -798,14 +789,42 @@ export default { @@ -798,14 +789,42 @@ export default {
//
const handleAppWillClose = () => {
console.log('主进程 app-will-close 事件触发')
// ""退
try {
const userSettings = localStorage.getItem('gofaster-settings')
if (userSettings) {
const settings = JSON.parse(userSettings)
if (settings.keepLoginOnClose) {
return
}
}
} catch (error) {
console.error('读取用户设置失败:', error)
}
// 退
performLogout()
}
//
const handleBeforeUnload = () => {
if (isLoggedIn.value) {
console.log('beforeunload 事件触发,执行退出登录')
// ""退
try {
const userSettings = localStorage.getItem('gofaster-settings')
if (userSettings) {
const settings = JSON.parse(userSettings)
if (settings.keepLoginOnClose) {
return
}
}
} catch (error) {
console.error('读取用户设置失败:', error)
}
// 退
performLogout()
}
}
@ -813,7 +832,21 @@ export default { @@ -813,7 +832,21 @@ export default {
//
const handleVisibilityChange = () => {
if (document.visibilityState === 'hidden' && isLoggedIn.value) {
console.log('页面隐藏,可能应用即将关闭,执行退出登录')
// ""退
try {
const userSettings = localStorage.getItem('gofaster-settings')
if (userSettings) {
const settings = JSON.parse(userSettings)
if (settings.keepLoginOnClose) {
return
}
}
} catch (error) {
console.error('读取用户设置失败:', error)
}
// 退
performLogout()
}
}
@ -979,22 +1012,18 @@ export default { @@ -979,22 +1012,18 @@ export default {
// 1.
if (window.electronAPI && window.electronAPI.onAppWillClose) {
console.log('注册主进程 app-will-close 事件监听器')
window.electronAPI.onAppWillClose(handleAppWillClose)
} else {
console.warn('electronAPI不可用,无法注册主进程应用关闭事件监听器')
}
// 2.
console.log('注册 beforeunload 事件监听器')
window.addEventListener('beforeunload', handleBeforeUnload)
// 3.
console.log('注册 visibilitychange 事件监听器')
document.addEventListener('visibilitychange', handleVisibilityChange)
// 4. Windows 退
console.log('注册 window blur 事件监听器')
window.addEventListener('blur', handleWindowBlur)
//

26
gofaster/app/src/renderer/views/Settings.vue

@ -46,15 +46,16 @@ @@ -46,15 +46,16 @@
<div class="settings-section">
<h3>用户设置</h3>
<div class="setting-item">
<label>自动登录</label>
<label>关闭窗口不登出</label>
<div class="toggle-switch">
<input
v-model="settings.autoLogin"
v-model="settings.keepLoginOnClose"
type="checkbox"
id="autoLogin"
id="keepLoginOnClose"
/>
<label for="autoLogin" class="toggle-label"></label>
<label for="keepLoginOnClose" class="toggle-label"></label>
</div>
</div>
<div class="setting-item">
<label>记住密码</label>
@ -67,10 +68,6 @@ @@ -67,10 +68,6 @@
<label for="rememberPassword" class="toggle-label"></label>
</div>
</div>
<div class="setting-item">
<label>会话超时时间 (分钟)</label>
<input v-model="settings.sessionTimeout" type="number" min="15" max="1440" />
</div>
</div>
<!-- 通知偏好 -->
@ -185,7 +182,7 @@ export default { @@ -185,7 +182,7 @@ export default {
retryCount: 3,
//
autoLogin: false,
keepLoginOnClose: false,
rememberPassword: false,
sessionTimeout: 30,
@ -282,7 +279,7 @@ export default { @@ -282,7 +279,7 @@ export default {
//
showToastMessage('success', '保存成功', '用户设置已成功保存')
console.log('用户设置已保存')
} catch (error) {
console.error('保存用户设置失败:', error)
//
@ -448,6 +445,15 @@ export default { @@ -448,6 +445,15 @@ export default {
transform: translateX(26px);
}
/* 设置描述文字 */
.setting-description {
font-size: 12px;
color: var(--text-secondary);
margin-top: 8px;
line-height: 1.4;
opacity: 0.8;
}
/* 操作按钮 */
.settings-actions {
display: flex;

Loading…
Cancel
Save