feat: 调整项目结构

This commit is contained in:
duanshuwen
2025-11-16 16:27:36 +08:00
parent 7760d2f1ed
commit c990ad7bbc
10 changed files with 179 additions and 22 deletions

View File

@@ -47,6 +47,7 @@ export class TabManager {
this.win.removeBrowserView(view)
this.activeId = null
}
// @ts-ignore
view.webContents.destroy()
this.views.delete(tabId)
this.win.webContents.send('tab-closed', { tabId })

View File

@@ -2,7 +2,7 @@
import { Tray, Menu } from 'electron'
import path from 'path'
const createTray = (app, win) => {
const createTray = (app: Electron.App, win: Electron.BrowserWindow) => {
let tray = new Tray(path.join(__dirname, '../public/favicon.ico'))
tray.setToolTip('示例平台') // 鼠标放在托盘图标上的提示信息

View File

@@ -4,17 +4,17 @@ import { ipcMain, BrowserWindow } from 'electron'
ipcMain.on('window-min', (event) => {
const webContent = event.sender
const win = BrowserWindow.fromWebContents(webContent)
win.minimize()
win?.minimize()
})
// 最大化
ipcMain.on('window-max', (event) => {
const webContent = event.sender
const win = BrowserWindow.fromWebContents(webContent)
if (win.isMaximized()) {
if (win?.isMaximized()) {
win.unmaximize()
} else {
win.maximize()
win?.maximize()
}
})
@@ -22,5 +22,5 @@ ipcMain.on('window-max', (event) => {
ipcMain.on('window-close', (event) => {
const webContent = event.sender
const win = BrowserWindow.fromWebContents(webContent)
win.close()
win?.close()
})

View File

@@ -1,5 +1,5 @@
import { ipcMain } from 'electron'
import { TabManager } from './tab-manager'
import { TabManager } from '../controller/tab-manager'
export const registerTabIpc = (tabs: TabManager) => {
ipcMain.handle('tab:create', (_e, url?: string) => tabs.create(url))

View File

@@ -1,8 +1,9 @@
import { app, BrowserWindow, ipcMain, shell } from "electron";
import path from "node:path";
import started from "electron-squirrel-startup";
import { TabManager } from './main/tab-manager'
import { registerTabIpc } from './main/ipc'
import { TabManager } from './controller/tab-manager'
import { registerTabIpc } from './ipc'
import "./controller/window-size-controll";
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (started) {
@@ -16,8 +17,8 @@ const createWindow = () => {
width: 900,
height: 670,
autoHideMenuBar: true,
frame: false,
windowButtonVisibility: false,
// frame: false,
// windowButtonVisibility: false,
resizable: true,
maximizable: true,
minimizable: true,
@@ -47,6 +48,7 @@ const createWindow = () => {
});
// and load the index.html of the app.
// @ts-ignore
if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL);
} else {
@@ -88,4 +90,4 @@ app.on("activate", () => {
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.
import "./controller/changeWindowSize.js";

View File

@@ -1,13 +1,13 @@
import { createRouter, createWebHistory } from "vue-router";
const routes = [
// {
// path: "/",
// name: "Login",
// component: () => import("@/views/login/index.vue"),
// },
{
path: "/",
name: "Login",
component: () => import("@/views/login/index.vue"),
},
{
path: "/browser",
name: "Browser",
component: () => import("@/views/browser/BrowserLayout.vue"),
},

View File

@@ -8,25 +8,94 @@
<!-- Logo和标题 -->
<div class="text-center mb-8">
<h1 class="text-2xl font-bold text-gray-900 mb-2">
China Fellou Plus
NIANXX
</h1>
<div class="text-sm text-gray-600">
您的隐私对我们很重要我们确保您的数据是安全和保密的
</div>
</div>
<div class="login flex items-start justify-center"></div>
<div class="space-y-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">账号</label>
<input
class="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-indigo-400"
type="text"
v-model.trim="form.account"
placeholder="请输入账号"
@keyup.enter="onSubmit"
/>
<p v-if="errors.account" class="mt-1 text-xs text-red-500">{{ errors.account }}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">密码</label>
<div class="flex items-center gap-2">
<input
class="flex-1 px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-indigo-400"
:type="showPwd ? 'text' : 'password'"
v-model.trim="form.password"
placeholder="请输入密码"
@keyup.enter="onSubmit"
/>
<button
class="px-3 py-2 text-sm border rounded bg-gray-100 hover:bg-gray-200"
@click="togglePassword"
>{{ showPwd ? '隐藏' : '显示' }}</button>
</div>
<p v-if="errors.password" class="mt-1 text-xs text-red-500">{{ errors.password }}</p>
</div>
<button
class="w-full py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700 disabled:bg-indigo-300"
:disabled="!valid || loading"
@click="onSubmit"
>{{ loading ? '登录中…' : '登录' }}</button>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
import { ref, reactive } from "vue";
import { useRouter } from "vue-router";
// 路由实例
const router = useRouter();
const form = reactive({ account: "", password: "" });
const errors = reactive<{ account?: string; password?: string }>({});
const loading = ref(false);
const showPwd = ref(false);
const validate = () => {
errors.account = undefined;
errors.password = undefined;
if (!form.account) errors.account = "请输入账号";
else if (form.account.length < 4 || form.account.length > 32) errors.account = "账号长度需在 4-32 之间";
if (!form.password) errors.password = "请输入密码";
else if (form.password.length < 6) errors.password = "密码长度不少于 6 位";
return !errors.account && !errors.password;
};
const valid = ref(false);
const recalc = () => {
valid.value = validate();
};
const togglePassword = () => {
showPwd.value = !showPwd.value;
};
const onSubmit = async () => {
recalc();
if (!valid.value || loading.value) return;
loading.value = true;
try {
await new Promise((r) => setTimeout(r, 600));
router.push("/");
} finally {
loading.value = false;
}
};
</script>
<style scoped lang="scss"></style>
<style scoped></style>