diff --git a/pc-fe/.umirc.ts b/pc-fe/.umirc.ts index ee7bcb6..e301eb6 100644 --- a/pc-fe/.umirc.ts +++ b/pc-fe/.umirc.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'umi'; import { Platform, Arch } from '@umijs/plugin-electron'; +const path = require('path'); +const rootdir = path.join(__dirname, "."); export default defineConfig({ npmClient: 'yarn', @@ -13,29 +15,39 @@ export default defineConfig({ mfsu: false, hash: true, styles: ['src/global.less'], + alias: { + "@": path.resolve(rootdir, "src"), + "@assets": path.resolve(rootdir, "src/assets"), + "@components": path.resolve(rootdir, "src/components"), + "@utils": path.resolve(rootdir, "src/utils"), + }, // 路由配置 routes: [ - { - path: '/login', - component: '@/pages/login', - }, + // { + // path: '/', + // component: '@/pages/welcome', + // }, + // { + // path: '/login', + // component: '@/pages/login', + // }, { path: '/', component: '@/pages/components/Layout/index', routes: [ { - path: '/images', - component: '@/pages/images', + path: '/welcome', + component: '@/pages/welcome', }, { - path: '/profile', - component: '@/pages/profile', + path: '/login', + component: '@/pages/login', + }, + { + path: '/', + redirect: '/welcome', }, ], }, - { - path: '/', - redirect: '@/pages/login', - }, ], }); diff --git a/pc-fe/package-lock.json b/pc-fe/package-lock.json index c4afe6c..f4f3bd1 100644 --- a/pc-fe/package-lock.json +++ b/pc-fe/package-lock.json @@ -1,16 +1,17 @@ { - "name": "@umijs/electron-template", - "version": "1.0.2", + "name": "vdi-manager", + "version": "1.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@umijs/electron-template", - "version": "1.0.2", + "name": "vdi-manager", + "version": "1.0.5", "hasInstallScript": true, "dependencies": { "@ant-design/icons": "^6.0.0", "antd": "^5.26.6", + "axios": "^1.11.0", "umi": "^4.0.42" }, "devDependencies": { @@ -7352,7 +7353,6 @@ "version": "0.4.0", "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, "license": "MIT" }, "node_modules/at-least-node": { @@ -7426,6 +7426,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.11.0", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmmirror.com/babel-jest/-/babel-jest-29.7.0.tgz", @@ -8528,7 +8539,6 @@ "version": "1.0.8", "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -9479,7 +9489,6 @@ "version": "1.0.0", "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -11359,6 +11368,26 @@ "license": "ISC", "peer": true }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmmirror.com/for-each/-/for-each-0.3.5.tgz", @@ -11481,7 +11510,6 @@ "version": "4.0.4", "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz", "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -16648,6 +16676,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz", diff --git a/pc-fe/package.json b/pc-fe/package.json index d4e7b42..8c0a012 100644 --- a/pc-fe/package.json +++ b/pc-fe/package.json @@ -18,6 +18,7 @@ "dependencies": { "@ant-design/icons": "^6.0.0", "antd": "^5.26.6", + "axios": "^1.11.0", "umi": "^4.0.42" }, "devDependencies": { diff --git a/pc-fe/src/assets/welcome-icon.jpg b/pc-fe/src/assets/welcome-icon.jpg new file mode 100644 index 0000000..234edef Binary files /dev/null and b/pc-fe/src/assets/welcome-icon.jpg differ diff --git a/pc-fe/src/main/config.ts b/pc-fe/src/main/config.ts new file mode 100644 index 0000000..73e270b --- /dev/null +++ b/pc-fe/src/main/config.ts @@ -0,0 +1,15 @@ +import { BrowserWindowConstructorOptions } from "electron"; +export default{ + browserWindow:{ + kiosk: true, + frame: false, + titleBarStyle: 'hidden', + autoHideMenuBar: true, + // 禁止调整窗口大小 + resizable: false, + // 禁止最大化和最小化按钮 + maximizable: false, + minimizable: false, + closable: false, + } as BrowserWindowConstructorOptions, +} \ No newline at end of file diff --git a/pc-fe/src/main/index.ts b/pc-fe/src/main/index.ts index fd77ed7..7a60796 100644 --- a/pc-fe/src/main/index.ts +++ b/pc-fe/src/main/index.ts @@ -1 +1 @@ -// getBrowserWindowRuntime().webContents.openDevTools(); +getBrowserWindowRuntime().webContents.openDevTools(); diff --git a/pc-fe/src/main/ipc/platform.ts b/pc-fe/src/main/ipc/platform.ts index c8c8bec..d41f784 100644 --- a/pc-fe/src/main/ipc/platform.ts +++ b/pc-fe/src/main/ipc/platform.ts @@ -1,5 +1,23 @@ -import { ipcMain } from 'electron'; +import { ipcMain,app } from 'electron'; +const window = getBrowserWindowRuntime(); + +// 监听渲染进程发送的消息 ipcMain.handle('getPlatform', () => { return `hi, i'm from ${process.platform}`; }); + +// 窗口控制:最小化,退出全屏 +ipcMain.on('close-app', () => { + app.quit(); +}); + +ipcMain.on('minimize-app', () => { + window?.minimize(); +}); + +ipcMain.on('exit-kiosk', () => { + if (window) { + window.setFullScreen(false); + } +}); \ No newline at end of file diff --git a/pc-fe/src/main/preload.ts b/pc-fe/src/main/preload.ts index fe8a235..1042f48 100644 --- a/pc-fe/src/main/preload.ts +++ b/pc-fe/src/main/preload.ts @@ -1,7 +1,31 @@ import { contextBridge, ipcRenderer } from 'electron'; -contextBridge.exposeInMainWorld('$api', { +// 页面调用的方法 +contextBridge.exposeInMainWorld('electronAPI', { getPlatform: async () => { return await ipcRenderer.invoke('getPlatform'); }, + closeApp: () => ipcRenderer.send('close-app'), + minimizeApp: () => ipcRenderer.send('minimize-app'), + exitKiosk: () => ipcRenderer.send('exit-kiosk'), + // 事件监听 + onMainProcessMessage: (callback: (data: string) => void) => { + ipcRenderer.on('main-process-message', (_, data) => callback(data)); + }, + on(...args: Parameters) { + const [channel, listener] = args + return ipcRenderer.on(channel, (event, ...args) => listener(event, ...args)) + }, + off(...args: Parameters) { + const [channel, ...omit] = args + return ipcRenderer.off(channel, ...omit) + }, + send(...args: Parameters) { + const [channel, ...omit] = args + return ipcRenderer.send(channel, ...omit) + }, + invoke(...args: Parameters) { + const [channel, ...omit] = args + return ipcRenderer.invoke(channel, ...omit) + } }); diff --git a/pc-fe/src/pages/components/Layout/index.less b/pc-fe/src/pages/components/Layout/index.less index aec72f7..50d4abe 100644 --- a/pc-fe/src/pages/components/Layout/index.less +++ b/pc-fe/src/pages/components/Layout/index.less @@ -1,64 +1,9 @@ .main-layout { - min-height: 100vh; - } + min-height: 100vh; +} + - .main-sider { - .logo { - height: 64px; - display: flex; - align-items: center; - justify-content: center; - color: white; - font-size: 18px; - font-weight: bold; - border-bottom: 1px solid #303030; - } - } - - .main-header { - background: #fff; - padding: 0 24px; - display: flex; - align-items: center; - justify-content: space-between; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); - - .trigger { - font-size: 18px; - color: #666; - - &:hover { - color: #1890ff; - } - } - - .header-right { - display: flex; - align-items: center; - gap: 16px; - - .welcome-text { - color: #666; - font-size: 14px; - } - - .user-avatar { - cursor: pointer; - background: #1890ff; - - &:hover { - opacity: 0.8; - } - } - } - } - - .main-content { - // margin: 24px; - // padding: 24px; - background: #fff; - border-radius: 8px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); - min-height: calc(100vh - 112px); - } +.main-content { + min-height: 100vh; +} \ No newline at end of file diff --git a/pc-fe/src/pages/components/Layout/index.tsx b/pc-fe/src/pages/components/Layout/index.tsx index cc509f3..fbecb4c 100644 --- a/pc-fe/src/pages/components/Layout/index.tsx +++ b/pc-fe/src/pages/components/Layout/index.tsx @@ -1,34 +1,33 @@ import React, { useState, useEffect } from 'react'; -import { Layout, Menu, Button, Avatar, Dropdown, message } from 'antd'; -import { - AppstoreOutlined, - UserOutlined, - LogoutOutlined, - MenuFoldOutlined, - MenuUnfoldOutlined, -} from '@ant-design/icons'; +import { Layout, message } from 'antd'; import { history, useLocation, Outlet } from 'umi'; import './index.less'; const { Header, Sider, Content } = Layout; const MainLayout: React.FC = () => { - const [collapsed, setCollapsed] = useState(false); const [username, setUsername] = useState(''); const location = useLocation(); + // useEffect(() => { + // // 检查登录状态 + // const isLoggedIn = localStorage.getItem('isLoggedIn'); + // const currentUsername = localStorage.getItem('username'); + + // if (!isLoggedIn) { + // message.error('请先登录!'); + // history.push('/login'); + // return; + // } + + // setUsername(currentUsername || ''); + // }, []); + useEffect(() => { - // 检查登录状态 - const isLoggedIn = localStorage.getItem('isLoggedIn'); - const currentUsername = localStorage.getItem('username'); - - if (!isLoggedIn) { - message.error('请先登录!'); - history.push('/login'); - return; - } - - setUsername(currentUsername || ''); + // TODO: 第一次来:判断是否配置ip/DHCP、服务ip绑定终端 绑定:直接到版本更新页面 未绑定:到配置ip/DHCP页面 + setTimeout(() => { + history.push('/login'); + },9000) }, []); const handleMenuClick = (key: string) => { @@ -43,73 +42,11 @@ const MainLayout: React.FC = () => { history.push('/login'); }; - const userMenu = ( - - } onClick={() => history.push('/profile')}> - 个人资料 - - - } onClick={handleLogout}> - 退出登录 - - - ); - - // 根据当前路径确定选中的菜单项 - const getSelectedKey = () => { - const path = location.pathname; - if (path === '/images') return 'images'; - if (path === '/profile') return 'profile'; - return 'images'; // 默认选中镜像列表 - }; - return ( - -
- {!collapsed && VDI 系统} -
- handleMenuClick(key)} - > - }> - 镜像列表 - - }> - 我的 - - -
- - -
-
- - - - -
+ + +
); }; diff --git a/pc-fe/src/pages/login/index.tsx b/pc-fe/src/pages/login/index.tsx index 450b8e8..4cb530b 100644 --- a/pc-fe/src/pages/login/index.tsx +++ b/pc-fe/src/pages/login/index.tsx @@ -33,6 +33,24 @@ const LoginPage: React.FC = () => { } }; + const closeApp = () => { + if (window.electronAPI) { + window.electronAPI.closeApp(); + } + }; + + const minimizeApp = () => { + if (window.electronAPI) { + window.electronAPI.minimizeApp(); + } + }; + + const exitKioskMode = () => { + if (window.electronAPI) { + window.electronAPI.exitKiosk(); + } + }; + return (
@@ -74,7 +92,11 @@ const LoginPage: React.FC = () => { - +
+ + + +

提示:用户名 admin,密码 123456

diff --git a/pc-fe/src/pages/welcome/index.less b/pc-fe/src/pages/welcome/index.less new file mode 100644 index 0000000..2657624 --- /dev/null +++ b/pc-fe/src/pages/welcome/index.less @@ -0,0 +1,84 @@ +.welcomeCon{ + width: 100vw; + height: 100vh; + background-color: rgba(0, 9, 51, 1); + background-size: 100% 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + .showTextCon{ + display: flex; + flex-direction: column; + justify-self: center; + align-items: center; + .name{ + height: 80px; + margin-bottom: 20px; + font-size: 36px; + color: #e5e5e5; + display: flex; + .welcomeIcon{ + height: 66px; + width: 70px; + margin-right: 20px; + } + .textCon{ + height: 120px; + display: flex; + flex-direction: column; + justify-content: space-between; + .text{ + display: flex; + flex-direction: column; + .nameText{ + font-size: 28px; + } + } + .loadingCon{ + width: 96px; + height: 12px; + display: flex; + justify-content: space-between; + align-items: center; + .dot { + width: 10px; + height: 10px; + border-radius: 50%; + background-color: rgba(255, 255, 255, 0.3); + display: flex; + justify-content: space-between; + animation: loading 1.5s infinite ease-in-out; + } + + .dot:nth-child(1) { + animation-delay: -0.32s; + } + + .dot:nth-child(2) { + animation-delay: -0.16s; + } + + @keyframes loading { + 0%, 100% { + background-color: rgba(255, 255, 255, 0.3); + transform: scale(0.6); + } + 25% { + background-color: rgba(255, 255, 255, 0.6); + transform: scale(0.8); + } + 50% { + background-color: rgba(255, 255, 255, 1); + transform: scale(1); + } + 75% { + background-color: rgba(255, 255, 255, 0.6); + transform: scale(0.8); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/pc-fe/src/pages/welcome/index.tsx b/pc-fe/src/pages/welcome/index.tsx new file mode 100644 index 0000000..998967a --- /dev/null +++ b/pc-fe/src/pages/welcome/index.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import styles from './index.less'; +import WelcomeIcon from '../../assets/welcome-icon.jpg' + +const Welcome = () => { + return ( +
+
+
+ +
+
+ 紫光汇智 + UNISSENSE +
+
+
+
+
+
+
+
+ +
+
+ ); +} + +export default Welcome; diff --git a/pc-fe/src/services/test.js b/pc-fe/src/services/test.js new file mode 100644 index 0000000..9968492 --- /dev/null +++ b/pc-fe/src/services/test.js @@ -0,0 +1,20 @@ +import axios from '@/utils/axios'; + +export const BASE_URL = '/api/v1/test'; + +export const getPageConfig = async () => { + const res = await axios({ + url: `${BASE_URL}/page-config/1`, + method: 'GET', + }); + return res; +}; + +export const getTruckList = async (params) => { + const res = await axios({ + url: `${BASE_URL}/listCarInfo`, + method: 'POST', + data: params, + }); + return res; +}; diff --git a/pc-fe/src/utils/axios/index.ts b/pc-fe/src/utils/axios/index.ts new file mode 100644 index 0000000..b8bd154 --- /dev/null +++ b/pc-fe/src/utils/axios/index.ts @@ -0,0 +1,52 @@ +import axios from 'axios'; +import { message } from 'antd'; + +const HTTP_CODE_SUCCESS = '0000000000'; + +function getCookie(name: string): string { + let arr; + const reg = new RegExp(`(^| )${name}=([^;]*)(;|$)`); + if ((arr = document.cookie.match(reg))) return decodeURIComponent(arr[2]); + return ''; +} + +// headers +function getHeaders(headers = {}) { + // const userCode = getCookie('usercode') || 'admin'; + // const userName = getCookie('username') || 'admin'; + return { + 'Content-Type': 'application/json', + // Authorization: encodeURIComponent(`username:${userName}&usercode:${userCode}`), + // User: encodeURIComponent(`username:${userName}&usercode:${userCode}`), + ...headers, + }; +} + +const instance = axios.create({ + timeout: 30000, +}); + +instance.interceptors.request.use(config => { + const _headers = getHeaders(); + config.headers = { ..._headers, ...config.headers }; + if (config.method === 'get' && config.params) { + config.params.t = +new Date; + } + return config; +}, error => { + return Promise.reject(error); +}); + +instance.interceptors.response.use(res => { + if (res?.data?.error_code === HTTP_CODE_SUCCESS) { + res.data.hzApiStatu = true; + } + return res.data; +}, rej => { + if (!rej?.config?.$refusedDefaultDealError && rej?.response?.data?.message) { + message.error(rej.response.data.message); + } + return Promise.reject(rej.response); +}); + +export default instance; diff --git a/pc-fe/typings.d.ts b/pc-fe/typings.d.ts index 9101d14..bc5f0c8 100644 --- a/pc-fe/typings.d.ts +++ b/pc-fe/typings.d.ts @@ -2,6 +2,6 @@ import 'umi/typings'; declare global { interface Window { - $api: any; + electronAPI: any; } }