diff --git a/.trae/documents/实现简约美观的登录页(Vue + Tailwind).md b/.trae/documents/实现简约美观的登录页(Vue + Tailwind).md new file mode 100644 index 0000000..de24a0a --- /dev/null +++ b/.trae/documents/实现简约美观的登录页(Vue + Tailwind).md @@ -0,0 +1,85 @@ +## 页面需求 + +* 输入:账号、密码;按钮:登录 + +* 交互:输入校验(必填、长度/格式)、回车提交、禁用按钮(加载中/校验失败)、错误提示、明文/密文切换 + +* 布局:简约卡片居中、品牌标题、副文、响应式(桌面)、浅色渐变背景 + +## 现状与集成点 + +* 已存在页面骨架:`src/views/login/index.vue`(中心卡片+标题,待补表单) + +* 路由:登录路由目前注释(`src/router/index.ts`),默认首页为 `/` 的 `BrowserLayout`(标签页界面) + +## 实现步骤 + +1. 表单与校验 + +* 在 `src/views/login/index.vue` 中添加账号/密码输入框与登录按钮 + +* 使用 `ref`/`reactive` 管理表单;规则: + + * 账号:必填、长度 4-32、允许邮箱/手机号/用户名(简单格式校验) + + * 密码:必填、长度 ≥ 6 + +* 按钮禁用条件:`!valid || loading` + +* 支持 `Enter` 键触发提交 + +* 密码框添加“显示/隐藏”切换 + +1. 反馈与跳转 + +* 登录过程显示 `loading`(按钮文案切换为“登录中…”) + +* 失败显示错误提示(红色文本);成功暂时跳转到 `/`(浏览器标签页界面) + +* 留出接口占位:`login(account, password)`(后续接入真实 API) + +1. 样式 + +* Tailwind 构建简约风格:卡片圆角阴影、输入框边框、聚焦效果、按钮主色(蓝色) + +* 响应式:移动端输入宽度 100%,桌面端 `max-w-md` 保持卡片紧凑 + +1. 路由接入 + +* 在 `src/router/index.ts` 增加登录路由:`/login` → `views/login/index.vue` + +* 暂不改默认首页;如需登录守卫,可后续将 `/login` 作为默认或在未认证时重定向到 `/login` + +## 代码改动概览(不执行,仅说明) + +* `src/views/login/index.vue` + + * 模板:两个输入框(账号、密码)、显示/隐藏密码按钮、登录按钮、错误提示区域 + + * 逻辑:`form`、`errors`、`validate()`、`onSubmit()`、`loading`、`togglePassword()`;成功后:`router.push('/')` + + * 样式:Tailwind 类名添加于容器/卡片/输入/按钮 + +* `src/router/index.ts` + + * 添加: + + ```ts + { path: '/login', name: 'Login', component: () => import('@/views/login/index.vue') } + ``` + +## 验证 + +* 输入为空时按钮禁用;填入合法后启用 + +* 按 `Enter` 能提交;失败提示文案显示;成功跳转到首页 + +* 移动端/桌面端居中显示良好 + +## 后续可选 + +* 接入真实认证 API(axios),保存 token(Pinia/LocalStorage),路由守卫控制访问 + +* 增加“记住我”、忘记密码、国际化 + +请确认以上方案,确认后我将直接补全 `index.vue` 表单与交互,并注册 `/login` 路由。 diff --git a/index.html b/index.html index a095539..5f37e43 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - 智念科技 AI + NIANXX { +const createTray = (app: Electron.App, win: Electron.BrowserWindow) => { let tray = new Tray(path.join(__dirname, '../public/favicon.ico')) tray.setToolTip('示例平台') // 鼠标放在托盘图标上的提示信息 diff --git a/src/controller/changeWindowSize.js b/src/controller/window-size-controll/index.ts similarity index 86% rename from src/controller/changeWindowSize.js rename to src/controller/window-size-controll/index.ts index 8029fcd..a5a4bec 100644 --- a/src/controller/changeWindowSize.js +++ b/src/controller/window-size-controll/index.ts @@ -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() }) diff --git a/src/main/ipc.ts b/src/ipc/index.ts similarity index 92% rename from src/main/ipc.ts rename to src/ipc/index.ts index c7a10f9..b9b9cf0 100644 --- a/src/main/ipc.ts +++ b/src/ipc/index.ts @@ -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)) diff --git a/src/main.ts b/src/main.ts index 3514daf..a5df7dc 100644 --- a/src/main.ts +++ b/src/main.ts @@ -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"; + diff --git a/src/router/index.ts b/src/router/index.ts index e33ec75..97ae176 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -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"), }, diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 0682c00..9f49452 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -8,25 +8,94 @@

- China Fellou Plus + NIANXX

您的隐私对我们很重要,我们确保您的数据是安全和保密的
-
+
+
+ + +

{{ errors.account }}

+
+
+ +
+ + +
+

{{ errors.password }}

+
+ +
- + diff --git a/tsconfig.base.json b/tsconfig.json similarity index 100% rename from tsconfig.base.json rename to tsconfig.json