bar
This commit is contained in:
+8
-1
@@ -4,6 +4,7 @@ import { NumberBall } from "@/components/number-ball"
|
|||||||
import { SettingsPanel } from "@/components/settings"
|
import { SettingsPanel } from "@/components/settings"
|
||||||
import { ResultPanel } from "@/components/result"
|
import { ResultPanel } from "@/components/result"
|
||||||
import { SingleModePanel } from "@/components/single-panel"
|
import { SingleModePanel } from "@/components/single-panel"
|
||||||
|
import { TitleBar } from "@/components/title-bar"
|
||||||
import { useRollCallLogic } from "@/components/logic"
|
import { useRollCallLogic } from "@/components/logic"
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
@@ -11,7 +12,12 @@ export default function Page() {
|
|||||||
const isSingleMode = state.mode === "single"
|
const isSingleMode = state.mode === "single"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen w-full bg-[#ffffff] text-[#16191f] font-mono flex flex-col lg:flex-row overflow-hidden">
|
<div className="h-screen w-full bg-[#0f141a] text-[#16191f] font-mono flex flex-col overflow-hidden">
|
||||||
|
{/* Custom title bar */}
|
||||||
|
<TitleBar />
|
||||||
|
|
||||||
|
{/* Main content */}
|
||||||
|
<div className="flex-1 bg-[#ffffff] flex flex-col lg:flex-row overflow-hidden">
|
||||||
|
|
||||||
{/* Left sidebar — config (fixed width, full height) */}
|
{/* Left sidebar — config (fixed width, full height) */}
|
||||||
<aside className="w-full lg:w-72 flex-shrink-0 border-b lg:border-b-0 lg:border-r border-[#e2e6ea] bg-[#f7f8fa] overflow-y-auto scrollbar-thin">
|
<aside className="w-full lg:w-72 flex-shrink-0 border-b lg:border-b-0 lg:border-r border-[#e2e6ea] bg-[#f7f8fa] overflow-y-auto scrollbar-thin">
|
||||||
@@ -125,5 +131,6 @@ export default function Page() {
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-8
@@ -91,14 +91,23 @@ export interface RollCallActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const COLORS = [
|
export const COLORS = [
|
||||||
"#0f141a", // 黑色
|
"#d92d20",
|
||||||
"#d92d20", // 红色
|
"#0070f3",
|
||||||
"#0070f3", // 蓝色
|
"#6d6df6",
|
||||||
"#6d6df6", // 紫色
|
"#00b8d9",
|
||||||
"#00b8d9", // 青色
|
"#36b37e",
|
||||||
"#36b37e", // 绿色
|
"#ff991f",
|
||||||
"#ff991f", // 橙色
|
"#8754ad",
|
||||||
"#8754ad", // 深紫
|
"#e63946",
|
||||||
|
"#457b9d",
|
||||||
|
"#2a9d8f",
|
||||||
|
"#f4a261",
|
||||||
|
"#264653",
|
||||||
|
"#9d4edd",
|
||||||
|
"#fb5607",
|
||||||
|
"#06d6a0",
|
||||||
|
"#118ab2",
|
||||||
|
"#ffd166",
|
||||||
]
|
]
|
||||||
|
|
||||||
export function useRollCallLogic(): [RollCallState, RollCallActions] {
|
export function useRollCallLogic(): [RollCallState, RollCallActions] {
|
||||||
|
|||||||
@@ -101,13 +101,6 @@ export function SettingsPanel({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-0">
|
<div className="flex flex-col gap-0">
|
||||||
|
|
||||||
{/* Title */}
|
|
||||||
<div className="flex items-center gap-2 mb-6">
|
|
||||||
<span className="w-2 h-2 bg-[#0f141a] flex-shrink-0" />
|
|
||||||
<span className="text-sm tracking-[0.2em] uppercase text-[#16191f] leading-none">ROLL CALL</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Mode selector */}
|
{/* Mode selector */}
|
||||||
<div className="flex gap-2 mb-6">
|
<div className="flex gap-2 mb-6">
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||||
|
|
||||||
|
export function TitleBar() {
|
||||||
|
const handleMinimize = async () => {
|
||||||
|
const window = getCurrentWindow()
|
||||||
|
await window.minimize()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMaximize = async () => {
|
||||||
|
const window = getCurrentWindow()
|
||||||
|
const isMaximized = await window.isMaximized()
|
||||||
|
if (isMaximized) {
|
||||||
|
await window.unmaximize()
|
||||||
|
} else {
|
||||||
|
await window.maximize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClose = async () => {
|
||||||
|
const window = getCurrentWindow()
|
||||||
|
await window.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="h-10 bg-[#ffffff] flex items-center justify-between px-4 select-none border-b border-[#e2e6ea]"
|
||||||
|
style={{
|
||||||
|
WebkitAppRegion: 'drag'
|
||||||
|
} as React.CSSProperties}
|
||||||
|
>
|
||||||
|
{/* Left: App title */}
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="w-2 h-2 bg-[#0f141a] flex-shrink-0" />
|
||||||
|
<span className="text-xs tracking-[0.2em] uppercase text-[#0f141a] leading-none font-mono">
|
||||||
|
ROLL CALL
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right: Window controls */}
|
||||||
|
<div
|
||||||
|
className="flex gap-1"
|
||||||
|
style={{ WebkitAppRegion: 'no-drag' } as React.CSSProperties}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
onClick={handleMinimize}
|
||||||
|
className="w-8 h-8 flex items-center justify-center text-[#8a95a1] hover:text-[#0f141a] hover:bg-[#f1f3f5] transition-colors"
|
||||||
|
title="最小化"
|
||||||
|
>
|
||||||
|
<svg width="10" height="10" viewBox="0 0 10 10" fill="currentColor">
|
||||||
|
<line x1="1" y1="5" x2="9" y2="5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleMaximize}
|
||||||
|
className="w-8 h-8 flex items-center justify-center text-[#8a95a1] hover:text-[#0f141a] hover:bg-[#f1f3f5] transition-colors"
|
||||||
|
title="最大化"
|
||||||
|
>
|
||||||
|
<svg width="10" height="10" viewBox="0 0 10 10" fill="currentColor">
|
||||||
|
<rect x="1" y="1" width="8" height="8" stroke="currentColor" strokeWidth="1.5" fill="none"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleClose}
|
||||||
|
className="w-8 h-8 flex items-center justify-center text-[#8a95a1] hover:text-[#ffffff] hover:bg-[#d92d20] transition-colors"
|
||||||
|
title="关闭"
|
||||||
|
>
|
||||||
|
<svg width="10" height="10" viewBox="0 0 10 10" fill="currentColor">
|
||||||
|
<line x1="2" y1="2" x2="8" y2="8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
|
||||||
|
<line x1="8" y1="2" x2="2" y2="8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
Generated
+11
@@ -9,6 +9,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@base-ui/react": "^1.5.0",
|
"@base-ui/react": "^1.5.0",
|
||||||
|
"@tauri-apps/api": "^2.11.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^1.16.0",
|
"lucide-react": "^1.16.0",
|
||||||
@@ -1852,6 +1853,16 @@
|
|||||||
"tailwindcss": "4.3.1"
|
"tailwindcss": "4.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tauri-apps/api": {
|
||||||
|
"version": "2.11.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@tauri-apps/api/-/api-2.11.0.tgz",
|
||||||
|
"integrity": "sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA==",
|
||||||
|
"license": "Apache-2.0 OR MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/tauri"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tauri-apps/cli": {
|
"node_modules/@tauri-apps/cli": {
|
||||||
"version": "2.11.2",
|
"version": "2.11.2",
|
||||||
"resolved": "https://registry.npmmirror.com/@tauri-apps/cli/-/cli-2.11.2.tgz",
|
"resolved": "https://registry.npmmirror.com/@tauri-apps/cli/-/cli-2.11.2.tgz",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@base-ui/react": "^1.5.0",
|
"@base-ui/react": "^1.5.0",
|
||||||
|
"@tauri-apps/api": "^2.11.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^1.16.0",
|
"lucide-react": "^1.16.0",
|
||||||
|
|||||||
@@ -6,6 +6,13 @@
|
|||||||
"main"
|
"main"
|
||||||
],
|
],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"core:default"
|
"core:window:allow-minimize",
|
||||||
|
"core:window:allow-is-minimized",
|
||||||
|
"core:window:allow-maximize",
|
||||||
|
"core:window:allow-is-maximized",
|
||||||
|
"core:window:allow-unmaximize",
|
||||||
|
"core:window:allow-unminimize",
|
||||||
|
"core:window:allow-close",
|
||||||
|
"core:window:allow-start-dragging"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@
|
|||||||
"width": 1204,
|
"width": 1204,
|
||||||
"height": 685,
|
"height": 685,
|
||||||
"resizable": true,
|
"resizable": true,
|
||||||
"fullscreen": false
|
"fullscreen": false,
|
||||||
|
"decorations": false,
|
||||||
|
"transparent": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"security": {
|
"security": {
|
||||||
@@ -29,13 +31,6 @@
|
|||||||
"icon": [
|
"icon": [
|
||||||
"icons/icon.ico"
|
"icons/icon.ico"
|
||||||
],
|
],
|
||||||
"windows": {
|
|
||||||
"webviewInstallMode": {
|
|
||||||
"type": "fixedRuntime",
|
|
||||||
"path": "./webview2/"
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"android": {
|
"android": {
|
||||||
"debugApplicationIdSuffix": ".debug"
|
"debugApplicationIdSuffix": ".debug"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user