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 {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 {message} from "../../../hook/message/u-message.tsx";
|
||||
import {useFileUpload} from "../../../api/upload.ts";
|
||||
@@ -60,22 +60,6 @@ const useUploadStyle = createUseStyles({
|
||||
cursor: 'pointer',
|
||||
'&: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({
|
||||
@@ -195,22 +179,9 @@ const PanelLeftUpload: React.FC<{ set_code: (code:string) => void }> = ({set_cod
|
||||
const style = useUploadStyle()
|
||||
const {file, setFile} = useStore()
|
||||
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() {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error no types for direct DOM query
|
||||
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>
|
||||
}
|
||||
{isAdmin && (
|
||||
<a href="/admin" className={style.adminLink}>管理控制台</a>
|
||||
)}
|
||||
{hasTokenPerm && (
|
||||
<a href="/self" className={style.adminLink}>个人中心 / API Token</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -278,7 +243,6 @@ const PanelLeftShow: React.FC<{ code: string; set_code: (code: string) => void }
|
||||
|
||||
return (
|
||||
<div className={classes.container}>
|
||||
|
||||
<div className={classes.form}>
|
||||
<button
|
||||
className={classes.closeButton}
|
||||
|
||||
@@ -2,17 +2,23 @@ import {createUseStyles} from 'react-jss'
|
||||
import {PanelLeft} from "./component/panel-left.tsx";
|
||||
import {PanelRight} from "./component/panel-right.tsx";
|
||||
import {PanelMid} from "./component/panel-mid.tsx";
|
||||
import {NavBar} from "./component/nav-bar.tsx";
|
||||
|
||||
const useStyle = createUseStyles({
|
||||
"@global": {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
},
|
||||
wrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100vh',
|
||||
},
|
||||
container: {
|
||||
margin: 0,
|
||||
height: "100vh",
|
||||
flex: 1,
|
||||
display: "grid",
|
||||
gridTemplateColumns: "40% 20% 40%",
|
||||
overflow: 'hidden',
|
||||
|
||||
"@media (max-width: 768px)": {
|
||||
gridTemplateColumns: "100%",
|
||||
@@ -24,9 +30,14 @@ const useStyle = createUseStyles({
|
||||
|
||||
export const FileSharing = () => {
|
||||
const style = useStyle()
|
||||
return <div className={style.container}>
|
||||
return (
|
||||
<div className={style.wrapper}>
|
||||
<NavBar />
|
||||
<div className={style.container}>
|
||||
<PanelLeft />
|
||||
<PanelMid />
|
||||
<PanelRight />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user