添加了修改头像功能,顺便重新设计了用户组件
This commit is contained in:
		
							
								
								
									
										13
									
								
								src/App.js
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/App.js
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | |||||||
| import './App.css'; | import './App.css'; | ||||||
| import { Redirect, Route, SingleRouter } from './components/SingleRouter/SingleRouter'; | import { Route, SingleRouter } from './components/SingleRouter/SingleRouter'; | ||||||
| import { AppContainer } from './index/index'; | import { AppContainer } from './index/index'; | ||||||
| import { UploadContainer } from './upload/upload'; | import { UploadContainer } from './upload/upload'; | ||||||
| import { LogInContainer } from './login/login'; | import { LogInContainer } from './login/login'; | ||||||
| @@ -12,13 +12,13 @@ class App extends Component { | |||||||
|     super(props); |     super(props); | ||||||
|     this.state = { |     this.state = { | ||||||
|       name: '', |       name: '', | ||||||
|       role: -1 |       role: 0 | ||||||
|     }; |     }; | ||||||
|     this.setUserData = this.setUserData.bind(this); |     this.setUserData = this.setUserData.bind(this); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   setUserData({ name, role }) { |   setUserData({ name, role, avatar }) { | ||||||
|     this.setState({ name, role }); |     this.setState({ name, role, avatar }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   render() { |   render() { | ||||||
| @@ -29,15 +29,10 @@ class App extends Component { | |||||||
|           <Route path="/upload" component={UploadContainer} /> |           <Route path="/upload" component={UploadContainer} /> | ||||||
|           <Route path="/login" component={LogInContainer} /> |           <Route path="/login" component={LogInContainer} /> | ||||||
|           <Route path="/admin/review" component={ReviewContainer} /> |           <Route path="/admin/review" component={ReviewContainer} /> | ||||||
|           <Route component={CheckLogIn} /> |  | ||||||
|         </SingleRouter> |         </SingleRouter> | ||||||
|       </UserContext.Provider> |       </UserContext.Provider> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| function CheckLogIn() { |  | ||||||
|   return localStorage.getItem('jwt') ? null : <Redirect from={/^\/.*/} to="/login" />; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export default App; | export default App; | ||||||
|   | |||||||
| @@ -67,7 +67,7 @@ export class ReviewContainer extends Component { | |||||||
|             <img src={images.icon} className="sdu-logo" alt="logo" /> |             <img src={images.icon} className="sdu-logo" alt="logo" /> | ||||||
|             <img src={images.name} className="sdu-name" alt="" /> |             <img src={images.name} className="sdu-name" alt="" /> | ||||||
|           </div> |           </div> | ||||||
|           <UserControl /> |           <UserControl pageAuthLevel={2} /> | ||||||
|         </div> |         </div> | ||||||
|         <div className="content"> |         <div className="content"> | ||||||
|           { |           { | ||||||
|   | |||||||
							
								
								
									
										122
									
								
								src/components/AvatarUnit/AvatarUnit.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/components/AvatarUnit/AvatarUnit.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | |||||||
|  | .user-avatar { | ||||||
|  |   width: 40px; | ||||||
|  |   height: 40px; | ||||||
|  |   position: relative; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .user-avatar > img { | ||||||
|  |   border-radius: 50%; | ||||||
|  |   width: 100%; | ||||||
|  |   height: 100%; | ||||||
|  |   cursor: pointer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .user-avatar-edit { | ||||||
|  |   border-radius: 8px; | ||||||
|  |   background-color: #f7f7f7; | ||||||
|  |   border: 1px solid #e5e5e5; | ||||||
|  |   width: 160px; | ||||||
|  |   height: 26px; | ||||||
|  |   position: absolute; | ||||||
|  |   margin-top: 10px; | ||||||
|  |   left: -60px; | ||||||
|  |   filter: opacity(0); | ||||||
|  |   transition-property: width, height, filter; | ||||||
|  |   transition-duration: .3s; | ||||||
|  |   transition-timing-function: ease-out; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .user-avatar-edit > .pointer { | ||||||
|  |   position: absolute; | ||||||
|  |   width: 20px; | ||||||
|  |   height: 10px; | ||||||
|  |   top: -10px; | ||||||
|  |   left: 70px; | ||||||
|  | } | ||||||
|  | .user-avatar-edit > .pointer > svg { | ||||||
|  |   position: absolute; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .user-avatar-edit-tip { | ||||||
|  |   width: 160px; | ||||||
|  |   height: 26px; | ||||||
|  |   line-height: 26px; | ||||||
|  |   padding-left: 5px; | ||||||
|  |   box-sizing: border-box; | ||||||
|  |   z-index: 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .user-avatar-edit.expand { | ||||||
|  |   width: 160px; | ||||||
|  |   height: 160px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .user-avatar-edit-tip, | ||||||
|  | .avatar-upload > * { | ||||||
|  |   position: absolute; | ||||||
|  |   filter: opacity(0); | ||||||
|  |   transition: filter .3s ease-out; | ||||||
|  | } | ||||||
|  | .user-avatar-edit-tip.show, | ||||||
|  | .avatar-upload > .show, | ||||||
|  | .user-avatar-edit.show { | ||||||
|  |   filter: opacity(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .user-avatar-edit-content { | ||||||
|  |   overflow: hidden; | ||||||
|  |   height: 100%; | ||||||
|  | } | ||||||
|  | .avatar-upload { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   align-items: center; | ||||||
|  |   height: 160px; | ||||||
|  | } | ||||||
|  | .avatar-upload .upload-unit-progress.show { | ||||||
|  |   z-index: 2; | ||||||
|  | } | ||||||
|  | .avatar-upload .upload-unit-progress > .progress-detail { | ||||||
|  |   color: black; | ||||||
|  | } | ||||||
|  | .upload-unit-progress > .icon { | ||||||
|  |   width: 40px; | ||||||
|  |   height: 40px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .avatar-preview { | ||||||
|  |   width: 160px; | ||||||
|  |   height: 160px; | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   align-items: center; | ||||||
|  |   background-size: cover; | ||||||
|  |   background-position: center; | ||||||
|  | } | ||||||
|  | .avatar-preview.show { | ||||||
|  |   z-index: 1; | ||||||
|  | } | ||||||
|  | .avatar-preview > .upload-btns { | ||||||
|  |   margin: 0; | ||||||
|  |   bottom: 10px; | ||||||
|  |   position: absolute; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .btn-close { | ||||||
|  |   position: absolute; | ||||||
|  |   right: 3px; | ||||||
|  |   top: 3px; | ||||||
|  |   z-index: 2; | ||||||
|  |   width: 20px; | ||||||
|  |   height: 20px; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   align-items: center; | ||||||
|  |   background-color: #e5e5e5bb; | ||||||
|  |   border-radius: 4px; | ||||||
|  |   backdrop-filter: blur(10px); | ||||||
|  | } | ||||||
|  | .btn-close > svg { | ||||||
|  |   width: 16px; | ||||||
|  |   height: 16px; | ||||||
|  | } | ||||||
							
								
								
									
										135
									
								
								src/components/AvatarUnit/AvatarUnit.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/components/AvatarUnit/AvatarUnit.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,135 @@ | |||||||
|  | import { useState, useCallback, useRef } from "react"; | ||||||
|  | import Spinner from '../Spinner/Spinner'; | ||||||
|  | import './AvatarUnit.css'; | ||||||
|  | import { multiFormPost } from '../../helper/axios'; | ||||||
|  | import { alert } from '../../helper/alert'; | ||||||
|  | import { apis } from "../../helper/apis"; | ||||||
|  |  | ||||||
|  | export default function AvatarUnit({ avatar, onChangeAvatar, showTip }) { | ||||||
|  |   const [showBubble, setShowBubble] = useState(showTip); | ||||||
|  |   const [showUpload, setShowUpload] = useState(false); | ||||||
|  |   const [loading, setLoading] = useState(false); | ||||||
|  |   const [loaded, setLoaded] = useState(false); | ||||||
|  |   const [uploading, setUploading] = useState(false); | ||||||
|  |   const [uploaded, setUploaded] = useState(false); | ||||||
|  |   const [dataURL, setDataURL] = useState(null); | ||||||
|  |   const [file, setFile] = useState(null); | ||||||
|  |  | ||||||
|  |   const inputRef = useRef(null); | ||||||
|  |  | ||||||
|  |   // useEffect(() => { | ||||||
|  |   //   setShowBubble(!localStorage.getItem("avatarTipShown")); | ||||||
|  |   //   localStorage.setItem("avatarTipShown", true); | ||||||
|  |   // }, []); | ||||||
|  |  | ||||||
|  |   const handleClose = () => { | ||||||
|  |     setShowBubble(false); | ||||||
|  |     setShowUpload(false); | ||||||
|  |     setLoading(false); | ||||||
|  |     setLoaded(false); | ||||||
|  |     setUploading(false); | ||||||
|  |     setUploaded(false); | ||||||
|  |     setFile(null); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   const handleFileChange = useCallback(file => { | ||||||
|  |     if (file) { | ||||||
|  |       if (!["image/jpeg", "image/png", "image/gif"].includes(file.type)) { | ||||||
|  |         alert('请不要上传jpg、png、gif格式以外的文件!'); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       setLoading(true); | ||||||
|  |       setFile(file); | ||||||
|  |       const reader = new FileReader(); | ||||||
|  |       reader.onload = () => { | ||||||
|  |         setDataURL(reader.result); | ||||||
|  |         if (inputRef.current) { | ||||||
|  |           inputRef.current.value = ""; | ||||||
|  |         } | ||||||
|  |         setLoaded(true); | ||||||
|  |         setLoading(false); | ||||||
|  |       }; | ||||||
|  |       reader.readAsDataURL(file); | ||||||
|  |     } | ||||||
|  |   }, []); | ||||||
|  |  | ||||||
|  |   const handleCancel = useCallback(() => { | ||||||
|  |     setLoaded(false); | ||||||
|  |     setFile(null); | ||||||
|  |   }, []); | ||||||
|  |  | ||||||
|  |   const handleUpload = useCallback(() => { | ||||||
|  |     if (file) { | ||||||
|  |       setUploading(true); | ||||||
|  |       const formData = new FormData(); | ||||||
|  |       formData.append("image", file); | ||||||
|  |       multiFormPost(apis.uploadAvatar, formData).then(data => { | ||||||
|  |         if (data.networkStatus === 200 && data.status) { | ||||||
|  |           setUploaded(true); | ||||||
|  |           setUploading(false); | ||||||
|  |           setTimeout(() => { | ||||||
|  |             handleClose(); | ||||||
|  |             onChangeAvatar(data.data); | ||||||
|  |           }, 800); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |           alert(data.data); | ||||||
|  |           setUploading(false); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   }, [file, onChangeAvatar]); | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|  |     <div className="user-avatar"> | ||||||
|  |       <img src={avatar} alt="user avatar" onClick={() => { | ||||||
|  |         setShowBubble(true); | ||||||
|  |         setShowUpload(true); | ||||||
|  |       }} /> | ||||||
|  |       <div className={"user-avatar-edit" + (showUpload ? ' expand' : '') + (showBubble ? ' show' : '')}> | ||||||
|  |         <div className="pointer"> | ||||||
|  |           <svg viewBox="0 0 20 10"> | ||||||
|  |             <path stroke="#e5e5e5" d="M0.112042+10.4465C1.43209+10.4306+4.24584+9.35904+5.0218+8.01502L6.77358+4.98086L8.52535+1.94671C9.30131+0.602693+10.5594+0.602693+11.3354+1.94671L13.0871+4.98086L14.8389+8.01502C15.6149+9.35904+18.4986+10.4864+20.0163+10.4757" fill="#f7f7f7"/> | ||||||
|  |           </svg> | ||||||
|  |         </div> | ||||||
|  |         <button className="btn btn-close" onClick={handleClose}> | ||||||
|  |           <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M597.333333 512l284.444445 284.444444c2.929778 3.328 2.929778 22.357333 0 28.444445l-56.888889 56.888889c-6.087111 2.929778-25.116444 2.929778-28.444445 0L512 597.333333 227.555556 881.777778c-3.328 2.929778-22.328889 2.929778-28.444445 0l-56.888889-56.888889c-2.929778-6.087111-2.929778-25.116444 0-28.444445l284.444445-284.444444L142.222222 227.555556c-2.929778-3.328-2.929778-22.328889 0-28.444445l56.888889-56.888889c6.115556-2.929778 25.116444-2.929778 28.444445 0l284.444444 284.444445L796.444444 142.222222c3.328-2.929778 22.357333-2.929778 28.444445 0l56.888889 56.888889c2.929778 6.115556 2.929778 25.116444 0 28.444445L597.333333 512z" fill="#4a4a4a"></path></svg> | ||||||
|  |         </button> | ||||||
|  |         <div className="user-avatar-edit-content"> | ||||||
|  |           <span className={'user-avatar-edit-tip' + (showBubble && !showUpload ? ' show' : '')}>点击图标修改头像</span> | ||||||
|  |           <div className="avatar-upload"> | ||||||
|  |             <div className={"upload-unit-progress" + (uploaded ? ' show' : '')}> | ||||||
|  |               <div className="icon"> | ||||||
|  |                 <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M939.717 106.665l-304.049 324.529-78.769 85.071-225.28 240.246-123.668-115.003-129.182-121.305-78.769 84.283 129.969 121.305 33.083 31.508 129.969 121.305 44.111 40.96 304.049-324.529 78.769-85.071 304.049-324.529-84.283-78.769z" fill="#47c74c"></path></svg> | ||||||
|  |               </div> | ||||||
|  |               <div className="progress-detail"> | ||||||
|  |                 上传成功 | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div className={"upload-unit-progress" + (loading || uploading ? ' show' : '')}> | ||||||
|  |               <Spinner isGray /> | ||||||
|  |               <div className="progress-detail"> | ||||||
|  |                 {loading ? '加载中' : uploading ? '上传中' : ''} | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div className={"avatar-preview" + (loaded && !uploading && !uploaded ? ' show' : '')} style={{ backgroundImage: `url(${dataURL})` }}> | ||||||
|  |               <div className="upload-btns"> | ||||||
|  |                 <button className="btn btn-circle btn-ok" onClick={handleUpload}> | ||||||
|  |                   <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M939.717 106.665l-304.049 324.529-78.769 85.071-225.28 240.246-123.668-115.003-129.182-121.305-78.769 84.283 129.969 121.305 33.083 31.508 129.969 121.305 44.111 40.96 304.049-324.529 78.769-85.071 304.049-324.529-84.283-78.769z" fill="#ffffff"></path></svg> | ||||||
|  |                 </button> | ||||||
|  |                 <button className="btn btn-circle btn-gray" onClick={handleCancel}> | ||||||
|  |                   <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M597.333333 512l284.444445 284.444444c2.929778 3.328 2.929778 22.357333 0 28.444445l-56.888889 56.888889c-6.087111 2.929778-25.116444 2.929778-28.444445 0L512 597.333333 227.555556 881.777778c-3.328 2.929778-22.328889 2.929778-28.444445 0l-56.888889-56.888889c-2.929778-6.087111-2.929778-25.116444 0-28.444445l284.444445-284.444444L142.222222 227.555556c-2.929778-3.328-2.929778-22.328889 0-28.444445l56.888889-56.888889c6.115556-2.929778 25.116444-2.929778 28.444445 0l284.444444 284.444445L796.444444 142.222222c3.328-2.929778 22.357333-2.929778 28.444445 0l56.888889 56.888889c2.929778 6.115556 2.929778 25.116444 0 28.444445L597.333333 512z" fill="#4a4a4a"></path></svg> | ||||||
|  |                 </button> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div className={"upload-image-btn" + (showUpload && !file ? ' show' : '')}> | ||||||
|  |               <input type="file" accept="image/*" multiple={false} onChange={e => handleFileChange(e.target.files[0])} ref={inputRef} /> | ||||||
|  |               <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 54"><path d="M60.342,102.091l5.331-8a2.249,2.249,0,0,1,1.872-1h18a2.246,2.246,0,0,1,1.872,1l5.332,8h7.094a6.72,6.72,0,0,1,6.7,6.7v31.6a6.722,6.722,0,0,1-6.7,6.7h-46.6a6.722,6.722,0,0,1-6.7-6.7v-31.6a6.72,6.72,0,0,1,6.7-6.7h7.094Zm5.407,0H87.341l-3-4.5H68.751l-3,4.5Zm10.8,35.25a12.75,12.75,0,1,0-12.75-12.75A12.764,12.764,0,0,0,76.545,137.341Zm0-21a8.25,8.25,0,1,1-8.25,8.25A8.261,8.261,0,0,1,76.545,116.341Z" transform="translate(-46.546 -93.091)" fill="#8A8A8A"/></svg> | ||||||
|  |               <div className="upload-image-btn-text">添加图片</div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   ); | ||||||
|  | } | ||||||
| @@ -56,6 +56,8 @@ | |||||||
|   color: white; |   color: white; | ||||||
|   font-size: 16px; |   font-size: 16px; | ||||||
|   margin-top: 10px; |   margin-top: 10px; | ||||||
|  |   width: 100px; | ||||||
|  |   text-align: center; | ||||||
| } | } | ||||||
| .progress-circle { | .progress-circle { | ||||||
|   width: 50px; |   width: 50px; | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | import { useEffect, useContext, Fragment } from 'react'; | ||||||
|  |  | ||||||
| import './userControl.css'; | import './userControl.css'; | ||||||
| import { images } from '../../resources.json'; | import { images } from '../../resources.json'; | ||||||
| import { UserContext } from '../../helper/Context'; | import { UserContext } from '../../helper/Context'; | ||||||
| @@ -6,56 +8,89 @@ import { get } from '../../helper/axios'; | |||||||
| import { apis } from '../../helper/apis'; | import { apis } from '../../helper/apis'; | ||||||
| import { alert } from '../../helper/alert'; | import { alert } from '../../helper/alert'; | ||||||
| import History from '../../helper/history'; | import History from '../../helper/history'; | ||||||
|  | import AvatarUnit from '../AvatarUnit/AvatarUnit'; | ||||||
|  |  | ||||||
|  | const exitContent = ['登录', '退出', '退出审核']; | ||||||
|  | // page level: 0: everyone, 1: login needed, 2: admin only | ||||||
|  | export default function UserControl({ pageAuthLevel, buttonOnly }) { | ||||||
|  |   const { userData, setUserData } = useContext(UserContext); | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (userData.role === -1) return; | ||||||
|  |     if (userData.role === 0 && localStorage.getItem('jwt')) { | ||||||
|  |       // 没有用户信息,但是有登录信息 | ||||||
|  |       setUserData({ role: -1, name: '加载中' }); | ||||||
|  |       get(apis.getProfile).then(({ data, status, networkStatus }) => { | ||||||
|  |         if (networkStatus !== 200) return; | ||||||
|  |         if (!status) return alert('获取用户信息失败:' + data + ',请稍候刷新再试'); | ||||||
|  |         setUserData({ | ||||||
|  |           name: data.realName, | ||||||
|  |           role: data.role, | ||||||
|  |           avatar: data.avatar, | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (userData.role < pageAuthLevel) { | ||||||
|  |       // 用户权限不足,依照页面权限跳转 | ||||||
|  |       if (userData.role === 1) { | ||||||
|  |         History.force('/'); | ||||||
|  |         alert('您没有权限访问该页面,退出登录后可以使用有权限的账号登录'); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       History.force('/login'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   }, [pageAuthLevel, setUserData, userData]); | ||||||
|  |  | ||||||
| export default function UserControl(props) { |  | ||||||
|   return ( |   return ( | ||||||
|     <UserContext.Consumer> |     <UserContext.Consumer> | ||||||
|       {({ userData, setUserData }) => ( |       {({ userData, setUserData }) => ( | ||||||
|         userData.role === 2 |         <div className="user"> | ||||||
|         ? ( |           {buttonOnly || ( | ||||||
|           <div className="user"> |             <Fragment> | ||||||
|             <button |               { | ||||||
|               className="btn btn-hollow btn-straight" |                 userData.role === -1 | ||||||
|               onClick={() => { |                 ? ( | ||||||
|                 localStorage.setItem('jwt', ''); |                   <Spinner isGray /> | ||||||
|                 setUserData({ role: -1, name: '' }); |                 ) | ||||||
|                 History.force('/login'); |                 : userData.role > 0 && ( | ||||||
|               }} |                   <AvatarUnit | ||||||
|             >退出审核</button> |                     avatar={userData.avatar || images.avatar} | ||||||
|           </div> |                     onChangeAvatar={url => setUserData({ ...userData, avatar: url })} | ||||||
|         ) |                     showTip={!userData.avatar} | ||||||
|         : ( |                   /> | ||||||
|           <div className="user"> |                 ) | ||||||
|             { |               } | ||||||
|               userData.role === -1 |               { | ||||||
|               ? ( |                 userData.role !== 0 && ( | ||||||
|                 <Spinner /> |                   <div className="user-name">{userData.name}</div> | ||||||
|               ) |                 ) | ||||||
|               : ( |               } | ||||||
|                 <div className="user-avatar"> |             </Fragment> | ||||||
|                   <img src={images.avatar} alt="user avatar" /> |           )} | ||||||
|                 </div> |           { | ||||||
|               ) |             userData.role === pageAuthLevel | ||||||
|             } |             ? ( | ||||||
|             <div className="user-name">{userData.name || "加载中"}</div> |               <button | ||||||
|             { |                 className="btn btn-hollow btn-straight" | ||||||
|               (() => { |                 onClick={() => { | ||||||
|                 if (userData.role === 1 && History.getHref().match(/^\/admin.*/)) |                   localStorage.setItem('jwt', ''); | ||||||
|                   History.force('/'); |                   setUserData({ role: 0, name: '' }); | ||||||
|                 if (userData.role !== -1 || !localStorage.getItem('jwt')) return null; |                   History.force('/login'); | ||||||
|                 get(apis.getProfile).then(({ data, status, networkStatus }) => { |                 }} | ||||||
|                   if (networkStatus !== 200) return; |               >{exitContent[pageAuthLevel]}</button> | ||||||
|                   if (!status) return alert('获取用户信息失败:' + data + ',请稍候刷新再试'); |             ) | ||||||
|                   setUserData({ |             : userData.role === 2 && ( | ||||||
|                     name: data.realName, |               <button | ||||||
|                     role: data.role |                 className="btn btn-hollow btn-straight" | ||||||
|                   }); |                 onClick={() => { | ||||||
|                 }); |                   History.push('/admin/review'); | ||||||
|                 return null; |                 }} | ||||||
|               })() |               >进入审核</button> | ||||||
|             } |             ) | ||||||
|           </div> |           } | ||||||
|         ) |         </div> | ||||||
|       )} |       )} | ||||||
|     </UserContext.Consumer> |     </UserContext.Consumer> | ||||||
|   ); |   ); | ||||||
|   | |||||||
| @@ -4,16 +4,5 @@ | |||||||
|   height: 50px; |   height: 50px; | ||||||
|   line-height: 50px; |   line-height: 50px; | ||||||
|   color: white; |   color: white; | ||||||
|   margin-left: 10px; |   margin: 0 10px; | ||||||
| } | } | ||||||
|  |  | ||||||
| .user-avatar { |  | ||||||
|   width: 40px; |  | ||||||
|   height: 40px; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .user-avatar > img { |  | ||||||
|   border-radius: 50%; |  | ||||||
|   width: 100%; |  | ||||||
|   height: 100%; |  | ||||||
| } |  | ||||||
| @@ -4,6 +4,7 @@ export const apis = { | |||||||
|  |  | ||||||
|   login: backEndBaseURL + "/user/login", |   login: backEndBaseURL + "/user/login", | ||||||
|   getProfile: backEndBaseURL + "/user/me", |   getProfile: backEndBaseURL + "/user/me", | ||||||
|  |   uploadAvatar: backEndBaseURL + "/user/uploadAvatar", | ||||||
|  |  | ||||||
|   submitMessage: backEndBaseURL + "/post/submit", |   submitMessage: backEndBaseURL + "/post/submit", | ||||||
|   listEssence: backEndBaseURL + "/post/listPublished?page=1", |   listEssence: backEndBaseURL + "/post/listPublished?page=1", | ||||||
|   | |||||||
| @@ -31,6 +31,20 @@ export function post(url, data, evoker) { | |||||||
|     } |     } | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  | export function multiFormPost(url, data, evoker) { | ||||||
|  |   return send( | ||||||
|  |     axios.post(url, data, { | ||||||
|  |       headers: { | ||||||
|  |         Authorization: localStorage.getItem('jwt'), | ||||||
|  |         "Allow-Control-Allow-Origin": "*" | ||||||
|  |       } | ||||||
|  |     }), | ||||||
|  |     { | ||||||
|  |       fetcher: () => multiFormPost(url, data, evoker), | ||||||
|  |       identifier: 'mfPost:' + url + (evoker ? `@${evoker}` : '') | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  |  | ||||||
| const waitToSend = []; | const waitToSend = []; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| .poster { | .poster { | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   height: 400px; |   height: 400px; | ||||||
|   background-color: #80010a; |   background-color: #84000B; | ||||||
|   display: flex; |   display: flex; | ||||||
|   flex-direction: column; |   flex-direction: column; | ||||||
|   align-items: center; |   align-items: center; | ||||||
| @@ -10,10 +10,15 @@ | |||||||
| .img-poster { | .img-poster { | ||||||
|   height: 100%; |   height: 100%; | ||||||
| } | } | ||||||
| .btn-partIn { | .index-btns { | ||||||
|   position: absolute; |   position: absolute; | ||||||
|   right: 40px; |   right: 40px; | ||||||
|   bottom: 20px; |   bottom: 20px; | ||||||
|  |   display: flex; | ||||||
|  |   height: 40px; | ||||||
|  | } | ||||||
|  | .index-btns > .user { | ||||||
|  |   margin-right: 10px; | ||||||
| } | } | ||||||
| /* 这里的卡片和分栏结构就比较接近bootstrap了,可惜视觉做的太古板,如果愿意的话改成Material Design就更好了 */ | /* 这里的卡片和分栏结构就比较接近bootstrap了,可惜视觉做的太古板,如果愿意的话改成Material Design就更好了 */ | ||||||
| .split-lg > .card { | .split-lg > .card { | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| import { Component } from 'react'; | import { Component } from 'react'; | ||||||
| import { Link } from '../components/SingleRouter/SingleRouter'; | import { Link } from '../components/SingleRouter/SingleRouter'; | ||||||
| import Spinner from '../components/Spinner/Spinner'; | import Spinner from '../components/Spinner/Spinner'; | ||||||
|  | import UserControl from '../components/UserControl/UserControl'; | ||||||
| import { alert } from '../helper/alert'; | import { alert } from '../helper/alert'; | ||||||
| import { apis } from '../helper/apis'; | import { apis } from '../helper/apis'; | ||||||
| import { get } from '../helper/axios'; | import { get } from '../helper/axios'; | ||||||
| @@ -38,7 +39,10 @@ export class AppContainer extends Component { | |||||||
|       <div className="index-container"> |       <div className="index-container"> | ||||||
|         <div className="poster"> |         <div className="poster"> | ||||||
|           <img src={images.poster} className="img-poster" alt="海报" /> |           <img src={images.poster} className="img-poster" alt="海报" /> | ||||||
|           <Link to="/upload" className="btn btn-light btn-straight btn-partIn">点击参加</Link> |           <div className='index-btns'> | ||||||
|  |             <UserControl pageAuthLevel={1} buttonOnly /> | ||||||
|  |             <Link to="/upload" className="btn btn-light btn-straight btn-partIn">点击参加</Link> | ||||||
|  |           </div> | ||||||
|         </div> |         </div> | ||||||
|         <div className="content split-lg"> |         <div className="content split-lg"> | ||||||
|           <div className="card"> |           <div className="card"> | ||||||
|   | |||||||
| @@ -63,7 +63,7 @@ export class UploadContainer extends Component { | |||||||
|             <img src={images.icon} className="sdu-logo" alt="logo" /> |             <img src={images.icon} className="sdu-logo" alt="logo" /> | ||||||
|             <img src={images.name} className="sdu-name" alt="" /> |             <img src={images.name} className="sdu-name" alt="" /> | ||||||
|           </div> |           </div> | ||||||
|           <UserControl /> |           <UserControl pageAuthLevel={1} /> | ||||||
|         </div> |         </div> | ||||||
|         <div className="content"> |         <div className="content"> | ||||||
|           <div className="message-box"> |           <div className="message-box"> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user