From e20b0b607daec82be35bb4b665e258e43396fde6 Mon Sep 17 00:00:00 2001 From: "DESKTOP-HR0JS52\\jun" Date: Fri, 30 Sep 2022 23:19:25 +0800 Subject: [PATCH 1/2] windowBox base --- .stylelintrc.js | 6 +++ package-lock.json | 5 -- package.json | 2 +- src/common/style/vars.scss | 4 ++ src/common/utils/getId.ts | 10 ++++ .../Window/WindowBox/Header/index.module.scss | 47 +++++++++++++++++++ .../Desktop/Window/WindowBox/Header/index.tsx | 27 +++++++++++ .../Window/WindowBox/index.module.scss | 47 +++++++++++++++++++ src/pages/Desktop/Window/WindowBox/index.tsx | 33 +++++++++++++ src/pages/Desktop/Window/WindowContext.ts | 14 ++++++ src/pages/Desktop/Window/index.module.scss | 0 src/pages/Desktop/Window/index.tsx | 35 ++++++++++++++ src/pages/Desktop/index.tsx | 5 ++ src/store/windowSlice.ts | 14 +++++- 14 files changed, 242 insertions(+), 7 deletions(-) create mode 100644 src/common/utils/getId.ts create mode 100644 src/pages/Desktop/Window/WindowBox/Header/index.module.scss create mode 100644 src/pages/Desktop/Window/WindowBox/Header/index.tsx create mode 100644 src/pages/Desktop/Window/WindowBox/index.module.scss create mode 100644 src/pages/Desktop/Window/WindowBox/index.tsx create mode 100644 src/pages/Desktop/Window/WindowContext.ts create mode 100644 src/pages/Desktop/Window/index.module.scss create mode 100644 src/pages/Desktop/Window/index.tsx diff --git a/.stylelintrc.js b/.stylelintrc.js index fa95536..38d5535 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -10,6 +10,12 @@ module.exports = { rules: { 'no-empty-source': null, 'selector-class-pattern': '^[a-z][a-zA-Z0-9]+$', + 'selector-pseudo-class-no-unknown': [ + true, + { + ignorePseudoClasses: ['global'] + } + ], 'color-function-notation': 'legacy', 'alpha-value-notation': 'number', // 属性的排序 diff --git a/package-lock.json b/package-lock.json index 55bd3e7..64e79c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4512,11 +4512,6 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, - "classname": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/classname/-/classname-0.0.0.tgz", - "integrity": "sha512-kkhsspEJdUW+VhuvNzb2sQf0KbafDPfd36dB1qf03Uu42dWZwMQzaQuyNkaRr5ir0ZiAN0+TlH/EOOfwb/aaXg==" - }, "classnames": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", diff --git a/package.json b/package.json index c57020e..d689d9a 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "@ant-design/icons": "^4.7.0", "antd": "^4.23.2", "axios": "^0.27.2", - "classname": "0.0.0", + "classnames": "^2.3.2", "lodash": "^4.17.21", "react-router-dom": "^6.4.0", "zustand": "^4.1.1" diff --git a/src/common/style/vars.scss b/src/common/style/vars.scss index 5de36de..3f8811f 100644 --- a/src/common/style/vars.scss +++ b/src/common/style/vars.scss @@ -5,6 +5,10 @@ $desk-background2: rgba(255, 255, 255, 0.1); $hover-background1: rgba(255, 255, 255, 0.25); +$window-border-color: #555; +$window-header-height: 32px; +$window-background: #303030; + $border-color1: #eee; $scrollbar-thumb1: #999; diff --git a/src/common/utils/getId.ts b/src/common/utils/getId.ts new file mode 100644 index 0000000..b552dbd --- /dev/null +++ b/src/common/utils/getId.ts @@ -0,0 +1,10 @@ +import { customAlphabet } from 'nanoid' + +const getId = () => { + const dictionary = + '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + const nanoid = customAlphabet(dictionary) + return nanoid() +} + +export default getId() diff --git a/src/pages/Desktop/Window/WindowBox/Header/index.module.scss b/src/pages/Desktop/Window/WindowBox/Header/index.module.scss new file mode 100644 index 0000000..0408401 --- /dev/null +++ b/src/pages/Desktop/Window/WindowBox/Header/index.module.scss @@ -0,0 +1,47 @@ +.headerBox { + display: flex; + flex-direction: row; + border-bottom: 1px solid $window-border-color; + width: 100%; + height: $window-header-height; +} + +.title { + flex-grow: 1; + line-height: 30px; + padding-left: 15px; + font-size: 12px; + user-select: none; + cursor: all-scroll; +} + +.tools { + display: flex; + flex-direction: row; +} + +.tool { + display: flex; + justify-content: center; + align-items: center; + width: 46px; + cursor: pointer; + + &:hover { + background-color: $desk-background2; + } +} + +.full { + :global { + svg { + font-size: 11px; + } + } +} + +.close { + &:hover { + background-color: rgb(232, 17, 35) !important; + } +} diff --git a/src/pages/Desktop/Window/WindowBox/Header/index.tsx b/src/pages/Desktop/Window/WindowBox/Header/index.tsx new file mode 100644 index 0000000..2626408 --- /dev/null +++ b/src/pages/Desktop/Window/WindowBox/Header/index.tsx @@ -0,0 +1,27 @@ +import React from 'react' +import { MinusOutlined, CloseOutlined, BorderOutlined } from '@ant-design/icons' +import classnames from 'classnames' +import styles from './index.module.scss' +import WindowContext from '@/pages/Desktop/Window/WindowContext' + +const Header: React.FC = () => { + const { window } = React.useContext(WindowContext) + return ( +
+
{window.title}
+
+
+ +
+
+ +
+
+ +
+
+
+ ) +} + +export default Header diff --git a/src/pages/Desktop/Window/WindowBox/index.module.scss b/src/pages/Desktop/Window/WindowBox/index.module.scss new file mode 100644 index 0000000..193b38b --- /dev/null +++ b/src/pages/Desktop/Window/WindowBox/index.module.scss @@ -0,0 +1,47 @@ +$drag: 8px; +$shift: -6px; + +.windowBox { + position: absolute; + border: 1px solid $window-border-color; + border-radius: 3px; + background-color: $window-background; +} + +.main { + position: relative; + width: 100%; + height: 100%; +} + +.content { + width: 100%; + height: calc(100% - #{$window-header-height}); +} + +.dragRight { + position: absolute; + top: 32px; + right: $shift; + width: $drag; + height: calc(100% - #{$drag + $shift} - 32px); + cursor: e-resize; +} + +.dragBottom { + position: absolute; + bottom: $shift; + left: 0; + width: calc(100% - #{$drag + $shift}); + height: $drag; + cursor: s-resize; +} + +.dragRightBottom { + position: absolute; + right: $shift; + bottom: $shift; + width: $drag; + height: $drag; + cursor: se-resize; +} diff --git a/src/pages/Desktop/Window/WindowBox/index.tsx b/src/pages/Desktop/Window/WindowBox/index.tsx new file mode 100644 index 0000000..18f0737 --- /dev/null +++ b/src/pages/Desktop/Window/WindowBox/index.tsx @@ -0,0 +1,33 @@ +import React from 'react' +import WindowContext from '../WindowContext' +import styles from './index.module.scss' +import Header from './Header' + +interface Props { + children: React.ReactNode +} + +const WindowBox: React.FC = props => { + const { window } = React.useContext(WindowContext) + return ( +
+
+
+
{props.children}
+
+
+
+
+
+ ) +} + +export default WindowBox diff --git a/src/pages/Desktop/Window/WindowContext.ts b/src/pages/Desktop/Window/WindowContext.ts new file mode 100644 index 0000000..9b68e1b --- /dev/null +++ b/src/pages/Desktop/Window/WindowContext.ts @@ -0,0 +1,14 @@ +import React from 'react' +import type { Window } from '@/store/windowSlice' + +export interface WindowContextType { + window: Window + id: string + index: number +} + +export default React.createContext({ + window: {} as Window, + id: '', + index: 0 +}) diff --git a/src/pages/Desktop/Window/index.module.scss b/src/pages/Desktop/Window/index.module.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/Desktop/Window/index.tsx b/src/pages/Desktop/Window/index.tsx new file mode 100644 index 0000000..ca98239 --- /dev/null +++ b/src/pages/Desktop/Window/index.tsx @@ -0,0 +1,35 @@ +import React from 'react' +import styles from './index.module.scss' +import WindowContext from './WindowContext' +import type { Window as WindowType } from '@/store/windowSlice' +import WindowBox from './WindowBox' + +interface Props { + window: WindowType + index: number +} + +const Window: React.FC = () => { + const { window } = React.useContext(WindowContext) + return ( + +
+
+ ) +} + +const WindowWithContext: React.FC = props => { + const { window, index } = props + return ( + + + + ) +} + +export default WindowWithContext diff --git a/src/pages/Desktop/index.tsx b/src/pages/Desktop/index.tsx index 5f44cb2..a5ded9c 100644 --- a/src/pages/Desktop/index.tsx +++ b/src/pages/Desktop/index.tsx @@ -5,12 +5,17 @@ import StartToolsBar from './StartToolsBar' import styles from './index.module.scss' import StartMenu from './StartMenu' import Mask from './Mask' +import Window from '@/pages/Desktop/Window' const Desktop: React.FC = () => { const showStartMenu = useStore((state: MyState) => state.showStartMenu) + const windowList = useStore((state: MyState) => state.windowList) return (
+ {windowList.map((window, index) => ( + + ))} {showStartMenu && } {showStartMenu && } diff --git a/src/store/windowSlice.ts b/src/store/windowSlice.ts index 3b37108..92d7236 100644 --- a/src/store/windowSlice.ts +++ b/src/store/windowSlice.ts @@ -1,6 +1,17 @@ import { StoreApi } from 'zustand' import { MyState } from './index' import _ from 'lodash' +import getId from '@utils/getId' + +const win = { + id: getId(), + width: 800, + height: 800, + top: 200, + left: 100, + zIndex: 1, + title: '窗口标题名称' +} export interface Window { id: string @@ -9,6 +20,7 @@ export interface Window { top: number left: number zIndex: number + title: string } export interface WindowSlice { @@ -22,7 +34,7 @@ const windowListSlice = ( set: StoreApi['setState'], get: StoreApi['getState'] ) => ({ - windowList: [], // 窗口列表 + windowList: [win], // 窗口列表 setWindowList: (windowList: Window[]) => { // 设置窗口列表 set(prev => ({ windowList: windowList })) -- Gitee From b89181157170c8c46b13ae7efd28476bfe5dba67 Mon Sep 17 00:00:00 2001 From: "DESKTOP-HR0JS52\\jun" Date: Sat, 1 Oct 2022 17:55:50 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20window=20=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/constants/index.ts | 8 +++ src/common/style/vars.scss | 5 ++ src/common/utils/getId.ts | 5 +- .../Desktop/StartToolsBar/index.module.scss | 2 +- .../Window/WindowBox/Header/index.module.scss | 8 +++ .../Desktop/Window/WindowBox/Header/index.tsx | 38 +++++++++--- src/pages/Desktop/Window/WindowBox/index.tsx | 25 +++++--- src/pages/Desktop/index.module.scss | 1 + src/react-app-env.d.ts | 5 ++ src/store/windowSlice.ts | 58 +++++++++++++++---- 10 files changed, 123 insertions(+), 32 deletions(-) create mode 100644 src/common/constants/index.ts diff --git a/src/common/constants/index.ts b/src/common/constants/index.ts new file mode 100644 index 0000000..3778d64 --- /dev/null +++ b/src/common/constants/index.ts @@ -0,0 +1,8 @@ +// 窗口状态常量 +const WINDOW_STATUS = { + NORMAL: 0, // 正常 + MIN: 1, // 最小化 + MAX: 2 // 最大化 +} + +export { WINDOW_STATUS } diff --git a/src/common/style/vars.scss b/src/common/style/vars.scss index 3f8811f..ba6a337 100644 --- a/src/common/style/vars.scss +++ b/src/common/style/vars.scss @@ -13,6 +13,11 @@ $border-color1: #eee; $scrollbar-thumb1: #999; +$start-tools-bar-height: 48px; + $start-menu-width: 600px; $start-menu-height: 550px; +:export { + startToolsBarHeight: $start-tools-bar-height +} diff --git a/src/common/utils/getId.ts b/src/common/utils/getId.ts index b552dbd..68e50ae 100644 --- a/src/common/utils/getId.ts +++ b/src/common/utils/getId.ts @@ -1,10 +1,9 @@ import { customAlphabet } from 'nanoid' -const getId = () => { +const getId = (size = 32) => { const dictionary = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' - const nanoid = customAlphabet(dictionary) - return nanoid() + return customAlphabet(dictionary, size) } export default getId() diff --git a/src/pages/Desktop/StartToolsBar/index.module.scss b/src/pages/Desktop/StartToolsBar/index.module.scss index 5c41d66..48c89fd 100644 --- a/src/pages/Desktop/StartToolsBar/index.module.scss +++ b/src/pages/Desktop/StartToolsBar/index.module.scss @@ -4,7 +4,7 @@ left: 0; z-index: 9999; width: 100%; - height: 48px; + height: $start-tools-bar-height; background: $desk-background1; backdrop-filter: saturate(3) blur(20px); } diff --git a/src/pages/Desktop/Window/WindowBox/Header/index.module.scss b/src/pages/Desktop/Window/WindowBox/Header/index.module.scss index 0408401..65bdcb8 100644 --- a/src/pages/Desktop/Window/WindowBox/Header/index.module.scss +++ b/src/pages/Desktop/Window/WindowBox/Header/index.module.scss @@ -40,6 +40,14 @@ } } +.normal { + :global { + svg { + font-size: 13px; + } + } +} + .close { &:hover { background-color: rgb(232, 17, 35) !important; diff --git a/src/pages/Desktop/Window/WindowBox/Header/index.tsx b/src/pages/Desktop/Window/WindowBox/Header/index.tsx index 2626408..5a99592 100644 --- a/src/pages/Desktop/Window/WindowBox/Header/index.tsx +++ b/src/pages/Desktop/Window/WindowBox/Header/index.tsx @@ -1,22 +1,46 @@ import React from 'react' -import { MinusOutlined, CloseOutlined, BorderOutlined } from '@ant-design/icons' +import { + MinusOutlined, + CloseOutlined, + BorderOutlined, + BlockOutlined +} from '@ant-design/icons' import classnames from 'classnames' import styles from './index.module.scss' import WindowContext from '@/pages/Desktop/Window/WindowContext' +import useStore, { MyState } from '@/store' +import { WINDOW_STATUS } from '@/common/constants' const Header: React.FC = () => { - const { window } = React.useContext(WindowContext) + const { window, id: windowId } = React.useContext(WindowContext) + const editWindowStatus = useStore((state: MyState) => state.setWindowStatus) + const closeWindow = useStore((state: MyState) => state.closeWindow) return (
{window.title}
-
+
editWindowStatus(WINDOW_STATUS.MIN, windowId)}>
-
- -
-
+ {window.status === WINDOW_STATUS.NORMAL && ( +
editWindowStatus(WINDOW_STATUS.MAX, windowId)}> + +
+ )} + {window.status === WINDOW_STATUS.MAX && ( +
editWindowStatus(WINDOW_STATUS.NORMAL, windowId)}> + +
+ )} +
closeWindow(windowId)}>
diff --git a/src/pages/Desktop/Window/WindowBox/index.tsx b/src/pages/Desktop/Window/WindowBox/index.tsx index 18f0737..2c60118 100644 --- a/src/pages/Desktop/Window/WindowBox/index.tsx +++ b/src/pages/Desktop/Window/WindowBox/index.tsx @@ -2,6 +2,8 @@ import React from 'react' import WindowContext from '../WindowContext' import styles from './index.module.scss' import Header from './Header' +import { WINDOW_STATUS } from '@/common/constants' +import vars from '@/common/style/vars.scss' interface Props { children: React.ReactNode @@ -9,16 +11,21 @@ interface Props { const WindowBox: React.FC = props => { const { window } = React.useContext(WindowContext) + const windowStyle = React.useMemo(() => { + const cssStyle = { ...window.style } + if (window.status === WINDOW_STATUS.MAX) { + cssStyle.left = 0 + cssStyle.top = 0 + cssStyle.width = '100%' + cssStyle.height = `calc(100% - ${vars.startToolsBarHeight})` + } + if (window.status === WINDOW_STATUS.MIN) { + cssStyle.display = 'none' + } + return cssStyle + }, [window.style, window.status]) return ( -
+
{props.children}
diff --git a/src/pages/Desktop/index.module.scss b/src/pages/Desktop/index.module.scss index 67d5478..b821bc8 100644 --- a/src/pages/Desktop/index.module.scss +++ b/src/pages/Desktop/index.module.scss @@ -2,4 +2,5 @@ position: relative; width: 100%; height: 100%; + overflow: hidden; } diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts index 9a973e4..3d25540 100644 --- a/src/react-app-env.d.ts +++ b/src/react-app-env.d.ts @@ -60,6 +60,11 @@ declare module '*.module.css' { export default classes } +declare module '*.scss' { + const classes: { readonly [key: string]: string } + export default classes +} + declare module '*.module.scss' { const classes: { readonly [key: string]: string } export default classes diff --git a/src/store/windowSlice.ts b/src/store/windowSlice.ts index 92d7236..35de82b 100644 --- a/src/store/windowSlice.ts +++ b/src/store/windowSlice.ts @@ -5,28 +5,40 @@ import getId from '@utils/getId' const win = { id: getId(), - width: 800, - height: 800, - top: 200, - left: 100, - zIndex: 1, - title: '窗口标题名称' + title: '窗口标题名称', + status: 0, + style: { + display: 'block', + width: 800, + height: 800, + top: 200, + left: 100, + zIndex: 1 + } } export interface Window { id: string - width: number - height: number + title: string + status: number + style: WindowStyle +} + +export interface WindowStyle { + display: string + width: number | string + height: number | string top: number left: number zIndex: number - title: string } export interface WindowSlice { windowList: Window[] setWindowList: (windowList: Window[]) => void - editWindow: (window: Window, index: number) => void + editWindow: (window: Window, id: string) => void + setWindowStatus: (status: number, id: string) => void + closeWindow: (id: string) => void closeWindowAll: () => void } @@ -39,11 +51,33 @@ const windowListSlice = ( // 设置窗口列表 set(prev => ({ windowList: windowList })) }, - editWindow: (window: Window, index: number) => { + editWindow: (window: Window, id: string) => { // 窗口属性编辑 set(({ windowList }) => { const list = _.cloneDeep(windowList) - list[index] = window + const windowIndex = list.findIndex(row => row.id === id) + list[windowIndex] = window + return { + windowList: list + } + }) + }, + setWindowStatus: (status: number, id: string) => { + set(({ windowList }) => { + const list = _.cloneDeep(windowList) + const windowIndex = list.findIndex(row => row.id === id) + const window = list[windowIndex] + window.status = status + return { + windowList: list + } + }) + }, + closeWindow: (id: string) => { + set(({ windowList }) => { + const list = _.cloneDeep(windowList) + const windowIndex = list.findIndex(row => row.id === id) + list.splice(windowIndex, 1) return { windowList: list } -- Gitee