1
This commit is contained in:
278
app/App.vue
Normal file
278
app/App.vue
Normal file
@@ -0,0 +1,278 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<header class="header">
|
||||
<div class="header-left">
|
||||
<h1>Boss - 远程监听服务 <span style="font-size: 0.7em; opacity: 0.8;">v{{ currentVersion }}</span></h1>
|
||||
<div class="status-indicator">
|
||||
<span :class="statusDotClass"></span>
|
||||
<span>{{ isConnected ? '已连接' : '未连接' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<!-- 登录页面不显示 UserMenu -->
|
||||
<UserMenu v-if="showSidebar" />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="main-content">
|
||||
<!-- 左侧菜单 - 登录页面不显示 -->
|
||||
<Sidebar v-if="showSidebar" />
|
||||
|
||||
<!-- 内容区域 - 使用 router-view 切换页面 -->
|
||||
<div class="content-area" :class="{ 'full-width': !showSidebar }">
|
||||
<router-view />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 更新弹窗 - 使用 store 管理状态 -->
|
||||
<UpdateDialog />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Sidebar from './components/Sidebar.vue';
|
||||
import UpdateDialog from './components/UpdateDialog.vue';
|
||||
import UserMenu from './components/UserMenu.vue';
|
||||
|
||||
// 导入 Vuex helpers
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
// 导入 Mixins
|
||||
import logMixin from './mixins/logMixin.js';
|
||||
import authMixin from './mixins/authMixin.js';
|
||||
import mqttMixin from './mixins/mqttMixin.js';
|
||||
import taskMixin from './mixins/taskMixin.js';
|
||||
import systemInfoMixin from './mixins/systemInfoMixin.js';
|
||||
import platformMixin from './mixins/platformMixin.js';
|
||||
import qrCodeMixin from './mixins/qrCodeMixin.js';
|
||||
import updateMixin from './mixins/updateMixin.js';
|
||||
import eventListenerMixin from './mixins/eventListenerMixin.js';
|
||||
|
||||
// Vue 应用主组件逻辑
|
||||
export default {
|
||||
name: 'App',
|
||||
mixins: [
|
||||
logMixin,
|
||||
authMixin,
|
||||
mqttMixin,
|
||||
taskMixin,
|
||||
systemInfoMixin,
|
||||
platformMixin,
|
||||
qrCodeMixin,
|
||||
updateMixin,
|
||||
eventListenerMixin
|
||||
],
|
||||
components: {
|
||||
Sidebar,
|
||||
UpdateDialog,
|
||||
UserMenu
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 应用启动时间(用于计算运行时间)
|
||||
startTime: Date.now(),
|
||||
|
||||
// 应用加载状态
|
||||
isLoading: true,
|
||||
|
||||
// 浏览器窗口状态
|
||||
browserWindowVisible: false
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
// beforeDestroy 已在 taskMixin 中定义
|
||||
|
||||
watch: {
|
||||
// 监听登录状态变化
|
||||
isLoggedIn(newVal, oldVal) {
|
||||
// 未登录时自动跳转到登录页面
|
||||
if (!newVal && this.$route.name !== 'Login') {
|
||||
this.$router.push('/login');
|
||||
}
|
||||
|
||||
// 登录状态从 false 变为 true 时,检查 MQTT 状态(连接由主进程自动处理)
|
||||
if (newVal && !oldVal) {
|
||||
// 延迟一下,确保 store 中的 snCode 已经更新
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
// MQTT 连接由主进程自动处理,这里只检查状态
|
||||
if (this.checkMQTTStatus) {
|
||||
this.checkMQTTStatus();
|
||||
}
|
||||
// 开始获取任务状态
|
||||
if (this.startTaskStatusUpdate) {
|
||||
this.startTaskStatusUpdate();
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async init() {
|
||||
try {
|
||||
// 先隐藏加载屏幕,避免一直显示
|
||||
this.hideLoadingScreen();
|
||||
|
||||
if (window.electronAPI && window.electronAPI.invoke) {
|
||||
const result = await window.electronAPI.invoke('system:get-version');
|
||||
if (result && result.success && result.version) {
|
||||
this.currentVersion = result.version;
|
||||
this.addLog('info', `当前版本: v${this.currentVersion}`);
|
||||
} else if (window.appInfo && window.appInfo.version) {
|
||||
this.currentVersion = window.appInfo.version;
|
||||
}
|
||||
} else if (window.appInfo && window.appInfo.version) {
|
||||
this.currentVersion = window.appInfo.version;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取版本号失败:', error);
|
||||
if (window.appInfo && window.appInfo.version) {
|
||||
this.$store.commit('app/SET_VERSION', window.appInfo.version);
|
||||
}
|
||||
}
|
||||
|
||||
this.setupEventListeners();
|
||||
await this.loadSavedConfig();
|
||||
|
||||
// 加载投递配置到 store
|
||||
if (this.$store && this.$store.dispatch) {
|
||||
await this.$store.dispatch('delivery/loadDeliveryConfig');
|
||||
}
|
||||
|
||||
this.startSystemInfoUpdate();
|
||||
|
||||
// 尝试自动登录
|
||||
const autoLoginSuccess = await this.tryAutoLogin();
|
||||
|
||||
// 如果已登录,开始获取任务状态
|
||||
if (this.$store.state.auth.isLoggedIn) {
|
||||
this.startTaskStatusUpdate();
|
||||
|
||||
// 检查 MQTT 连接状态
|
||||
this.checkMQTTStatus();
|
||||
} else if (!autoLoginSuccess) {
|
||||
// 未登录时,自动跳转到登录页面
|
||||
this.$router.push('/login');
|
||||
}
|
||||
},
|
||||
|
||||
hideLoadingScreen() {
|
||||
setTimeout(() => {
|
||||
const loadingScreen = document.getElementById('loading-screen');
|
||||
const app = document.getElementById('app');
|
||||
|
||||
if (loadingScreen) {
|
||||
loadingScreen.classList.add('hidden');
|
||||
setTimeout(() => {
|
||||
if (loadingScreen.parentNode) {
|
||||
loadingScreen.remove();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
if (app) {
|
||||
app.style.display = 'block';
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
}, 500);
|
||||
},
|
||||
|
||||
// setupEventListeners 已在 eventListenerMixin 中定义
|
||||
// loadSavedConfig, checkActivationStatus, userLogin, tryAutoLogin 已在 authMixin 中定义
|
||||
// startTaskStatusUpdate, updateCurrentTask, onTaskStatusUpdate 已在 taskMixin 中定义
|
||||
|
||||
// connectMQTT, disconnectMQTT, onMQTTConnected, onMQTTDisconnected, onMQTTMessage, onMQTTStatusChange 已在 mqttMixin 中定义
|
||||
// handleMenuChange, handleUpdateDeliveryConfig, handleLoginFromPage, handleLoginFromDialog 已不需要,使用路由和组件内部处理
|
||||
|
||||
/**
|
||||
* 检查 MQTT 连接状态,如果未连接则尝试重新连接
|
||||
*/
|
||||
async checkMQTTStatus() {
|
||||
try {
|
||||
if (!window.electronAPI || !window.electronAPI.invoke) {
|
||||
console.warn('[App] electronAPI 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取当前 MQTT 状态
|
||||
const status = await window.electronAPI.invoke('mqtt:status');
|
||||
console.log('[App] MQTT 状态查询结果:', status);
|
||||
|
||||
if (status && status.isConnected) {
|
||||
// 如果已经连接,更新状态
|
||||
if (this.$store) {
|
||||
this.$store.dispatch('mqtt/setConnected', true);
|
||||
console.log('[App] MQTT 状态已更新为已连接');
|
||||
}
|
||||
} else {
|
||||
// 如果未连接,尝试重新连接(需要 snCode)
|
||||
const snCode = this.$store?.state?.auth?.snCode;
|
||||
if (snCode) {
|
||||
console.log('[App] MQTT 未连接,尝试重新连接...');
|
||||
try {
|
||||
await window.electronAPI.invoke('mqtt:connect', snCode);
|
||||
console.log('[App] MQTT 重新连接成功');
|
||||
if (this.$store) {
|
||||
this.$store.dispatch('mqtt/setConnected', true);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[App] MQTT 重新连接失败:', error);
|
||||
if (this.$store) {
|
||||
this.$store.dispatch('mqtt/setConnected', false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn('[App] 无法重新连接 MQTT: 缺少 snCode');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[App] 检查 MQTT 状态失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState('app', ['currentVersion']),
|
||||
...mapState('mqtt', ['isConnected']),
|
||||
...mapState('auth', ['isLoggedIn', 'userName', 'snCode', 'deviceId', 'remainingDays', 'phone']),
|
||||
// 根据路由 meta 决定是否显示侧边栏,默认为 true
|
||||
showSidebar() {
|
||||
return this.$route.meta.showSidebar !== false;
|
||||
},
|
||||
statusDotClass() {
|
||||
return {
|
||||
'status-dot': true,
|
||||
'connected': this.isConnected
|
||||
};
|
||||
}
|
||||
// logEntries 已在 logMixin 中定义
|
||||
}
|
||||
|
||||
// snCode watch 已在 authMixin 中定义
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
// 登录页面时,内容区域不需要背景和padding
|
||||
.content-area.full-width {
|
||||
// 当侧边栏隐藏时,登录页面应该有特殊样式
|
||||
&.login-page {
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user