Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
050075d9c8 |
81
frontend/src/page/share/component/nav-bar.tsx
Normal file
81
frontend/src/page/share/component/nav-bar.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import React, {useEffect, useState} from 'react';
|
||||||
|
import {createUseStyles} from 'react-jss';
|
||||||
|
|
||||||
|
const useStyle = createUseStyles({
|
||||||
|
nav: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
padding: '0 24px',
|
||||||
|
height: '48px',
|
||||||
|
backgroundColor: '#2c9678',
|
||||||
|
boxShadow: '0 2px 6px rgba(0,0,0,0.15)',
|
||||||
|
flexShrink: 0,
|
||||||
|
},
|
||||||
|
brand: {
|
||||||
|
color: 'white',
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: '18px',
|
||||||
|
letterSpacing: '1px',
|
||||||
|
textDecoration: 'none',
|
||||||
|
},
|
||||||
|
links: {
|
||||||
|
display: 'flex',
|
||||||
|
gap: '8px',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
color: 'rgba(255,255,255,0.9)',
|
||||||
|
fontSize: '13px',
|
||||||
|
textDecoration: 'none',
|
||||||
|
padding: '5px 12px',
|
||||||
|
borderRadius: '4px',
|
||||||
|
transition: 'background-color 0.2s',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(255,255,255,0.2)',
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
divider: {
|
||||||
|
color: 'rgba(255,255,255,0.4)',
|
||||||
|
fontSize: '13px',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const NavBar: React.FC = () => {
|
||||||
|
const style = useStyle();
|
||||||
|
const [isAdmin, setIsAdmin] = useState(false);
|
||||||
|
const [hasTokenPerm, setHasTokenPerm] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch('/api/uauth/me').then(async res => {
|
||||||
|
if (res.ok) {
|
||||||
|
const json = await res.json();
|
||||||
|
const perms: string[] = json.data?.permissions ?? [];
|
||||||
|
setIsAdmin(perms.includes('user_manage'));
|
||||||
|
setHasTokenPerm(perms.includes('token_manage'));
|
||||||
|
}
|
||||||
|
}).catch(() => {});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const showLinks = isAdmin || hasTokenPerm;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className={style.nav}>
|
||||||
|
<a href="/share" className={style.brand}>UShare</a>
|
||||||
|
{showLinks && (
|
||||||
|
<div className={style.links}>
|
||||||
|
{hasTokenPerm && (
|
||||||
|
<a href="/self" className={style.link}>个人中心</a>
|
||||||
|
)}
|
||||||
|
{isAdmin && hasTokenPerm && (
|
||||||
|
<span className={style.divider}>|</span>
|
||||||
|
)}
|
||||||
|
{isAdmin && (
|
||||||
|
<a href="/admin" className={style.link}>管理控制台</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import {createUseStyles} from "react-jss";
|
import {createUseStyles} from "react-jss";
|
||||||
import {UButton} from "../../../component/button/u-button.tsx";
|
import {UButton} from "../../../component/button/u-button.tsx";
|
||||||
import React, {useEffect, useState} from "react";
|
import React, {useState} from "react";
|
||||||
import {useStore} from "../../../store/share.ts";
|
import {useStore} from "../../../store/share.ts";
|
||||||
import {message} from "../../../hook/message/u-message.tsx";
|
import {message} from "../../../hook/message/u-message.tsx";
|
||||||
import {useFileUpload} from "../../../api/upload.ts";
|
import {useFileUpload} from "../../../api/upload.ts";
|
||||||
@@ -60,22 +60,6 @@ const useUploadStyle = createUseStyles({
|
|||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
'&:hover': {}
|
'&:hover': {}
|
||||||
},
|
},
|
||||||
adminLink: {
|
|
||||||
display: 'block',
|
|
||||||
textAlign: 'center',
|
|
||||||
marginTop: '16px',
|
|
||||||
color: '#2c9678',
|
|
||||||
fontSize: '12px',
|
|
||||||
textDecoration: 'none',
|
|
||||||
opacity: 0.8,
|
|
||||||
'&:hover': {opacity: 1, textDecoration: 'underline'},
|
|
||||||
},
|
|
||||||
navLinks: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'center',
|
|
||||||
gap: '16px',
|
|
||||||
marginTop: '16px',
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const useShowStyle = createUseStyles({
|
const useShowStyle = createUseStyles({
|
||||||
@@ -195,22 +179,9 @@ const PanelLeftUpload: React.FC<{ set_code: (code:string) => void }> = ({set_cod
|
|||||||
const style = useUploadStyle()
|
const style = useUploadStyle()
|
||||||
const {file, setFile} = useStore()
|
const {file, setFile} = useStore()
|
||||||
const {uploadFile, progress, loading} = useFileUpload();
|
const {uploadFile, progress, loading} = useFileUpload();
|
||||||
const [isAdmin, setIsAdmin] = useState(false);
|
|
||||||
const [hasTokenPerm, setHasTokenPerm] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetch('/api/uauth/me').then(async res => {
|
|
||||||
if (res.ok) {
|
|
||||||
const json = await res.json();
|
|
||||||
const perms: string[] = json.data?.permissions ?? [];
|
|
||||||
setIsAdmin(perms.includes('user_manage'));
|
|
||||||
setHasTokenPerm(perms.includes('token_manage'));
|
|
||||||
}
|
|
||||||
}).catch(() => {});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
function onFileSelect() {
|
function onFileSelect() {
|
||||||
// @ts-ignore
|
// @ts-expect-error no types for direct DOM query
|
||||||
document.querySelector('#real-file-input').click();
|
document.querySelector('#real-file-input').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,12 +225,6 @@ const PanelLeftUpload: React.FC<{ set_code: (code:string) => void }> = ({set_cod
|
|||||||
<div className={style.name}>{file.name}</div>
|
<div className={style.name}>{file.name}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{isAdmin && (
|
|
||||||
<a href="/admin" className={style.adminLink}>管理控制台</a>
|
|
||||||
)}
|
|
||||||
{hasTokenPerm && (
|
|
||||||
<a href="/self" className={style.adminLink}>个人中心 / API Token</a>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -278,7 +243,6 @@ const PanelLeftShow: React.FC<{ code: string; set_code: (code: string) => void }
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.container}>
|
<div className={classes.container}>
|
||||||
|
|
||||||
<div className={classes.form}>
|
<div className={classes.form}>
|
||||||
<button
|
<button
|
||||||
className={classes.closeButton}
|
className={classes.closeButton}
|
||||||
|
|||||||
@@ -2,17 +2,23 @@ import {createUseStyles} from 'react-jss'
|
|||||||
import {PanelLeft} from "./component/panel-left.tsx";
|
import {PanelLeft} from "./component/panel-left.tsx";
|
||||||
import {PanelRight} from "./component/panel-right.tsx";
|
import {PanelRight} from "./component/panel-right.tsx";
|
||||||
import {PanelMid} from "./component/panel-mid.tsx";
|
import {PanelMid} from "./component/panel-mid.tsx";
|
||||||
|
import {NavBar} from "./component/nav-bar.tsx";
|
||||||
|
|
||||||
const useStyle = createUseStyles({
|
const useStyle = createUseStyles({
|
||||||
"@global": {
|
"@global": {
|
||||||
margin: 0,
|
margin: 0,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
},
|
},
|
||||||
|
wrapper: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
height: '100vh',
|
||||||
|
},
|
||||||
container: {
|
container: {
|
||||||
margin: 0,
|
flex: 1,
|
||||||
height: "100vh",
|
|
||||||
display: "grid",
|
display: "grid",
|
||||||
gridTemplateColumns: "40% 20% 40%",
|
gridTemplateColumns: "40% 20% 40%",
|
||||||
|
overflow: 'hidden',
|
||||||
|
|
||||||
"@media (max-width: 768px)": {
|
"@media (max-width: 768px)": {
|
||||||
gridTemplateColumns: "100%",
|
gridTemplateColumns: "100%",
|
||||||
@@ -24,9 +30,14 @@ const useStyle = createUseStyles({
|
|||||||
|
|
||||||
export const FileSharing = () => {
|
export const FileSharing = () => {
|
||||||
const style = useStyle()
|
const style = useStyle()
|
||||||
return <div className={style.container}>
|
return (
|
||||||
|
<div className={style.wrapper}>
|
||||||
|
<NavBar />
|
||||||
|
<div className={style.container}>
|
||||||
<PanelLeft />
|
<PanelLeft />
|
||||||
<PanelMid />
|
<PanelMid />
|
||||||
<PanelRight/>
|
<PanelRight />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user