完成审核页面,对样式做大量微调(视觉的按钮好怪啊),但是目前发现了请求处理等待流程的bug
This commit is contained in:
父節點
a1386d8870
當前提交
b8f99f4e4c
73
src/App.css
73
src/App.css
@ -2,50 +2,53 @@ a.btn {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.btn {
|
.btn {
|
||||||
color: white !important;
|
--btn-fg: #FFF;
|
||||||
border-radius: .3em;
|
color: var(--btn-fg) !important;
|
||||||
padding: .375em 0;
|
border-radius: .4em;
|
||||||
|
padding: .3em 0;
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
font-size: 1.1em;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: filter .3s ease-out;
|
transition: filter .3s ease-out;
|
||||||
width: 5em;
|
width: 5em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
.btn:disabled {
|
.btn:disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
filter: grayscale(100%) opacity(.5);
|
filter: grayscale(100%) opacity(.5);
|
||||||
}
|
}
|
||||||
.btn:active {
|
.btn:active {
|
||||||
color: white !important;
|
color: var(--btn-fg) !important;
|
||||||
}
|
}
|
||||||
.btn:hover(:not(:disabled)) {
|
.btn:hover(:not(:disabled)) {
|
||||||
filter: brightness(1.2);
|
filter: brightness(1.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.btn {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
background-color: #318ffb;
|
background-color: #0AF;
|
||||||
}
|
}
|
||||||
.btn-ok {
|
.btn-ok {
|
||||||
background-color: #47c74c;
|
background-color: #47c74c;
|
||||||
}
|
}
|
||||||
.btn-gray {
|
.btn-gray {
|
||||||
background-color: #d9d9d9;
|
background-color: #E8E8E8;
|
||||||
|
--btn-fg: #000;
|
||||||
}
|
}
|
||||||
.btn-sdu {
|
.btn-sdu {
|
||||||
background-color: #9D0004;
|
background-color: #9D0004;
|
||||||
}
|
}
|
||||||
.btn.btn-light {
|
.btn-light {
|
||||||
background-color: #fcfafa;
|
background-color: #fcfcfc;
|
||||||
color: #323232 !important;
|
--btn-fg: #333;
|
||||||
}
|
}
|
||||||
.btn.btn-light:active {
|
.btn.btn-hollow {
|
||||||
color: #323232 !important;
|
background-color: transparent;
|
||||||
|
border: 1px solid #FFF;
|
||||||
|
}
|
||||||
|
.btn.btn-dark.btn-hollow {
|
||||||
|
border: 1px solid #AAA;
|
||||||
|
--btn-fg: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-circle {
|
.btn-circle {
|
||||||
@ -56,10 +59,34 @@ button.btn {
|
|||||||
box-shadow: 1px 1px 4px 0 #0003;
|
box-shadow: 1px 1px 4px 0 #0003;
|
||||||
}
|
}
|
||||||
.btn-straight {
|
.btn-straight {
|
||||||
border-radius: .15em;
|
border-radius: .2em;
|
||||||
width: 6em;
|
width: 6em;
|
||||||
}
|
}
|
||||||
|
.btn-pill {
|
||||||
|
border-radius: 1em;
|
||||||
|
padding: .15em 0;
|
||||||
|
width: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-center {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.col-center > .spinner {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner {
|
||||||
|
height: 80px;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 60px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #9D0004;
|
||||||
|
}
|
||||||
.sdu,
|
.sdu,
|
||||||
.user {
|
.user {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -75,6 +102,10 @@ button.btn {
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b {
|
||||||
|
color: #9E0004;
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 1000px;
|
width: 1000px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@ -86,4 +117,12 @@ button.btn {
|
|||||||
width: calc(100% - 80px);
|
width: calc(100% - 80px);
|
||||||
margin: 0 40px;
|
margin: 0 40px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* modifying sweet alert */
|
||||||
|
.expanded-msg {
|
||||||
|
padding: 50px 0;
|
||||||
|
}
|
||||||
|
.swal2-actions > .btn {
|
||||||
|
margin: 0 40px;
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ import { Redirect, Route, SingleRouter } from './components/SingleRouter/SingleR
|
|||||||
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';
|
||||||
import { ReviewContainer } from './review/review';
|
import { ReviewContainer } from './admin/review/review';
|
||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
import { UserContext } from './helper/Context';
|
import { UserContext } from './helper/Context';
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ class App extends Component {
|
|||||||
<Route path="/" component={AppContainer} />
|
<Route path="/" component={AppContainer} />
|
||||||
<Route path="/upload" component={UploadContainer} />
|
<Route path="/upload" component={UploadContainer} />
|
||||||
<Route path="/login" component={LogInContainer} />
|
<Route path="/login" component={LogInContainer} />
|
||||||
<Route path="/review" component={ReviewContainer} />
|
<Route path="/admin/review" component={ReviewContainer} />
|
||||||
<Route component={CheckLogIn} />
|
<Route component={CheckLogIn} />
|
||||||
</SingleRouter>
|
</SingleRouter>
|
||||||
</UserContext.Provider>
|
</UserContext.Provider>
|
||||||
|
40
src/admin/review/review.css
Normal file
40
src/admin/review/review.css
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
.review-content {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-content > p {
|
||||||
|
width: calc(100% - 300px);
|
||||||
|
}
|
||||||
|
.review-img {
|
||||||
|
margin: 40px 0;
|
||||||
|
display: block;
|
||||||
|
cursor: zoom-in;
|
||||||
|
}
|
||||||
|
.review-img > img {
|
||||||
|
/* max-height: 300px; */
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-btns {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-top: 1px solid #DDD;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 40px 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 840px) {
|
||||||
|
.review-img > img {
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
.review-content > p {
|
||||||
|
width: calc(100% - 100px);
|
||||||
|
}
|
||||||
|
.review-btns {
|
||||||
|
padding: 30px 50px;
|
||||||
|
}
|
||||||
|
}
|
108
src/admin/review/review.js
Normal file
108
src/admin/review/review.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import './review.css';
|
||||||
|
import { Component } from 'react';
|
||||||
|
import UserControl from '../../components/UserControl/UserControl';
|
||||||
|
import { images } from '../../resources.json';
|
||||||
|
import { get, post } from '../../helper/axios';
|
||||||
|
import { apis } from '../../helper/apis';
|
||||||
|
import { alert, confirmWithClose } from '../../helper/alert';
|
||||||
|
import { UserContext } from '../../helper/Context';
|
||||||
|
import Spinner from '../../components/Spinner/Spinner';
|
||||||
|
|
||||||
|
export class ReviewContainer extends Component {
|
||||||
|
static contextType = UserContext;
|
||||||
|
fetched = false;
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
posts: [],
|
||||||
|
fetchingPosts: false,
|
||||||
|
reviewingNow: 0,
|
||||||
|
actionPerforming: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.context.userData?.role === 2) this.fetchPosts();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
if (this.context.userData?.role === 2 && !this.fetched) this.fetchPosts();
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchPosts() {
|
||||||
|
this.fetched = true;
|
||||||
|
this.setState({ fetchingPosts: true });
|
||||||
|
get(apis.listNotReviewed).then(({ data, status, networkStatus }) => {
|
||||||
|
this.setState({ fetchingPosts: false });
|
||||||
|
if (networkStatus !== 200) return;
|
||||||
|
if (!status) return alert('拉取审核列表失败:' + data + ',请刷新重试');
|
||||||
|
|
||||||
|
this.setState({ posts: data });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async review(accepted) {
|
||||||
|
// 哇提示语怎么这么生硬啊
|
||||||
|
if (!await confirmWithClose(`<div class="expanded-msg">确认<b>${accepted ? '发布' : '不通过'}</b>此条信息?</div>`)) return;
|
||||||
|
const { posts, reviewingNow } = this.state;
|
||||||
|
const { id } = posts[reviewingNow];
|
||||||
|
this.setState({ actionPerforming: accepted ? 1 : 2 });
|
||||||
|
post(apis.setStatus, { id, status: accepted ? 2 : 3 }).then(({ data, status, networkStatus }) => {
|
||||||
|
this.setState({ actionPerforming: 0 });
|
||||||
|
if (networkStatus !== 200) return;
|
||||||
|
if (!status) return alert('提交审核失败:' + data + ',请稍后重试');
|
||||||
|
|
||||||
|
if (this.state.reviewingNow === this.state.posts.length - 1)
|
||||||
|
this.fetchPosts();
|
||||||
|
else
|
||||||
|
this.setState({ reviewingNow: this.state.reviewingNow + 1 });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="review-container">
|
||||||
|
<div className="banner">
|
||||||
|
<div className="sdu">
|
||||||
|
<img src={images.icon} className="sdu-logo" alt="logo" />
|
||||||
|
<img src={images.name} className="sdu-name" alt="" />
|
||||||
|
</div>
|
||||||
|
<UserControl />
|
||||||
|
</div>
|
||||||
|
<div className="content">
|
||||||
|
{
|
||||||
|
this.state.fetchingPosts
|
||||||
|
? (
|
||||||
|
<div className="col-center">
|
||||||
|
<Spinner isGray />
|
||||||
|
<div style={{ marginLeft: '10px' }}>正在加载审核列表...</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
this.state.posts.length === 0
|
||||||
|
? (
|
||||||
|
<div className="col-center">暂时没有待审核的内容哦</div>
|
||||||
|
)
|
||||||
|
: (
|
||||||
|
<div className="review-content">
|
||||||
|
<p>{this.state.posts[this.state.reviewingNow].content}</p>
|
||||||
|
<a className="review-img" href={this.state.posts[this.state.reviewingNow].image} target="_blank" rel="noreferrer">
|
||||||
|
<img src={this.state.posts[this.state.reviewingNow].image} alt="待审核的配图" />
|
||||||
|
</a>
|
||||||
|
<div className="review-btns">
|
||||||
|
<button className="btn btn-primary" onClick={() => this.review(true)} disabled={this.state.actionPerforming !== 0}>
|
||||||
|
{this.state.actionPerforming === 1 ? (<Spinner />) : '发布'}
|
||||||
|
</button>
|
||||||
|
<button className="btn btn-gray" onClick={() => this.review(false)} disabled={this.state.actionPerforming !== 0}>
|
||||||
|
{this.state.actionPerforming === 2 ? (<Spinner />) : '不通过'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,19 @@
|
|||||||
import './spinner.css';
|
import './spinner.css';
|
||||||
|
|
||||||
export default function Spinner(props) {
|
export default function Spinner({ isGray }) {
|
||||||
|
let base = isGray ? '888' : 'FFF';
|
||||||
return (
|
return (
|
||||||
<div className="spinner">
|
<div className="spinner">
|
||||||
<svg viewBox="0 0 1027 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 1027 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M101.725953 198.235466m48.271823-48.271823l0 0q48.271823-48.271823 96.543646 0l144.815469 144.815468q48.271823 48.271823 0 96.543646l0 0q-48.271823 48.271823-96.543646 0l-144.815469-144.815468q-48.271823-48.271823 0-96.543646Z" fill="#FFFD"></path>
|
<path d="M101.725953 198.235466m48.271823-48.271823l0 0q48.271823-48.271823 96.543646 0l144.815469 144.815468q48.271823 48.271823 0 96.543646l0 0q-48.271823 48.271823-96.543646 0l-144.815469-144.815468q-48.271823-48.271823 0-96.543646Z" fill={`#${base}D`}></path>
|
||||||
<path d="M341.367467 443.733333m0 68.266667l0 0q0 68.266667-68.266667 68.266667l-204.8 0q-68.266667 0-68.266667-68.266667l0 0q0-68.266667 68.266667-68.266667l204.8 0q68.266667 0 68.266667 68.266667Z" fill="#FFFC"></path>
|
<path d="M341.367467 443.733333m0 68.266667l0 0q0 68.266667-68.266667 68.266667l-204.8 0q-68.266667 0-68.266667-68.266667l0 0q0-68.266667 68.266667-68.266667l204.8 0q68.266667 0 68.266667 68.266667Z" fill={`#${base}C`}></path>
|
||||||
<path d="M343.085068 584.40542m48.271823 48.271823l0 0q48.271823 48.271823 0 96.543646l-144.815469 144.815468q-48.271823 48.271823-96.543646 0l0 0q-48.271823-48.271823 0-96.543646l144.815469-144.815468q48.271823-48.271823 96.543646 0Z" fill="#FFFB"></path>
|
<path d="M343.085068 584.40542m48.271823 48.271823l0 0q48.271823 48.271823 0 96.543646l-144.815469 144.815468q-48.271823 48.271823-96.543646 0l0 0q-48.271823-48.271823 0-96.543646l144.815469-144.815468q48.271823-48.271823 96.543646 0Z" fill={`#${base}B`}></path>
|
||||||
<path d="M443.767467 682.666667m68.266666 0l0 0q68.266667 0 68.266667 68.266666l0 204.8q0 68.266667-68.266667 68.266667l0 0q-68.266667 0-68.266666-68.266667l0-204.8q0-68.266667 68.266666-68.266666Z" fill="#FFFA"></path>
|
<path d="M443.767467 682.666667m68.266666 0l0 0q68.266667 0 68.266667 68.266666l0 204.8q0 68.266667-68.266667 68.266667l0 0q-68.266667 0-68.266666-68.266667l0-204.8q0-68.266667 68.266666-68.266666Z" fill={`#${base}A`}></path>
|
||||||
<path d="M584.439553 680.949066m48.271823-48.271823l0 0q48.271823-48.271823 96.543646 0l144.815469 144.815468q48.271823 48.271823 0 96.543646l0 0q-48.271823 48.271823-96.543646 0l-144.815469-144.815468q-48.271823-48.271823 0-96.543646Z" fill="#FFF9"></path>
|
<path d="M584.439553 680.949066m48.271823-48.271823l0 0q48.271823-48.271823 96.543646 0l144.815469 144.815468q48.271823 48.271823 0 96.543646l0 0q-48.271823 48.271823-96.543646 0l-144.815469-144.815468q-48.271823-48.271823 0-96.543646Z" fill={`#${base}9`}></path>
|
||||||
<path d="M1024.034133 443.733333m0 68.266667l0 0q0 68.266667-68.266666 68.266667l-204.8 0q-68.266667 0-68.266667-68.266667l0 0q0-68.266667 68.266667-68.266667l204.8 0q68.266667 0 68.266666 68.266667Z" fill="#FFF8"></path>
|
<path d="M1024.034133 443.733333m0 68.266667l0 0q0 68.266667-68.266666 68.266667l-204.8 0q-68.266667 0-68.266667-68.266667l0 0q0-68.266667 68.266667-68.266667l204.8 0q68.266667 0 68.266666 68.266667Z" fill={`#${base}8`}></path>
|
||||||
<path d="M825.798668 101.69182m48.271823 48.271823l0 0q48.271823 48.271823 0 96.543646l-144.815469 144.815468q-48.271823 48.271823-96.543646 0l0 0q-48.271823-48.271823 0-96.543646l144.815469-144.815468q48.271823-48.271823 96.543646 0Z" fill="#FFF7"></path>
|
<path d="M825.798668 101.69182m48.271823 48.271823l0 0q48.271823 48.271823 0 96.543646l-144.815469 144.815468q-48.271823 48.271823-96.543646 0l0 0q-48.271823-48.271823 0-96.543646l144.815469-144.815468q48.271823-48.271823 96.543646 0Z" fill={`#${base}7`}></path>
|
||||||
<path d="M443.767467 0m68.266666 0l0 0q68.266667 0 68.266667 68.266667l0 204.8q0 68.266667-68.266667 68.266666l0 0q-68.266667 0-68.266666-68.266666l0-204.8q0-68.266667 68.266666-68.266667Z" fill="#FFF6"></path></svg>
|
<path d="M443.767467 0m68.266666 0l0 0q68.266667 0 68.266667 68.266667l0 204.8q0 68.266667-68.266667 68.266666l0 0q-68.266667 0-68.266666-68.266666l0-204.8q0-68.266667 68.266666-68.266667Z" fill={`#${base}6`}></path>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -91,6 +91,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
display: none;
|
display: none;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
cursor: zoom-out;
|
||||||
}
|
}
|
||||||
.scaled-wrap.open {
|
.scaled-wrap.open {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -16,7 +16,11 @@ export default function UserControl(props) {
|
|||||||
<div className="user">
|
<div className="user">
|
||||||
<button
|
<button
|
||||||
className="btn btn-hollow btn-straight"
|
className="btn btn-hollow btn-straight"
|
||||||
onClick={() => setUserData({ role: -1, name: '' })}
|
onClick={() => {
|
||||||
|
localStorage.setItem('jwt', '');
|
||||||
|
setUserData({ role: -1, name: '' });
|
||||||
|
History.force('/login');
|
||||||
|
}}
|
||||||
>退出审核</button>
|
>退出审核</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@ -34,9 +38,9 @@ export default function UserControl(props) {
|
|||||||
<div className="user-name">{userData.name || "加载中"}</div>
|
<div className="user-name">{userData.name || "加载中"}</div>
|
||||||
{
|
{
|
||||||
(() => {
|
(() => {
|
||||||
if (userData.role !== 2 && History.getHref().match(/^\/admin.*/))
|
if (userData.role === 1 && History.getHref().match(/^\/admin.*/))
|
||||||
History.force('/');
|
History.force('/');
|
||||||
if (userData.role !== -1) return null;
|
if (userData.role !== -1 || !localStorage.getItem('jwt')) return null;
|
||||||
get(apis.getProfile).then(({ data, status, networkStatus }) => {
|
get(apis.getProfile).then(({ data, status, networkStatus }) => {
|
||||||
if (networkStatus !== 200) return;
|
if (networkStatus !== 200) return;
|
||||||
if (!status) return alert('获取用户信息失败:' + data + ',请稍候刷新再试');
|
if (!status) return alert('获取用户信息失败:' + data + ',请稍候刷新再试');
|
||||||
|
@ -2,8 +2,8 @@ import Swal from 'sweetalert2';
|
|||||||
|
|
||||||
const SelfSwal = Swal.mixin({
|
const SelfSwal = Swal.mixin({
|
||||||
customClass: {
|
customClass: {
|
||||||
confirmButton: 'btn btn-primary',
|
confirmButton: 'btn btn-primary btn-pill',
|
||||||
cancelButton: 'btn btn-gray',
|
cancelButton: 'btn btn-dark btn-hollow btn-pill',
|
||||||
},
|
},
|
||||||
buttonsStyling: false,
|
buttonsStyling: false,
|
||||||
});
|
});
|
||||||
@ -23,7 +23,8 @@ export const failed = (content, afterRetry) => {
|
|||||||
html: content,
|
html: content,
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
confirmButtonText: '重试',
|
confirmButtonText: '重试',
|
||||||
cancelButtonText: '放弃'
|
cancelButtonText: '放弃',
|
||||||
|
icon: 'error'
|
||||||
})
|
})
|
||||||
.then(result => result.isConfirmed ? afterRetry() : null) :
|
.then(result => result.isConfirmed ? afterRetry() : null) :
|
||||||
SelfSwal.fire({
|
SelfSwal.fire({
|
||||||
@ -39,6 +40,16 @@ export const alert = (content) => {
|
|||||||
return SelfSwal.fire({
|
return SelfSwal.fire({
|
||||||
html: content,
|
html: content,
|
||||||
confirmButtonText: '了解',
|
confirmButtonText: '了解',
|
||||||
icon: 'warning'
|
icon: 'info'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const confirmWithClose = async (content) => {
|
||||||
|
return (await SelfSwal.fire({
|
||||||
|
html: content,
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
showCancelButton: true,
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
showCloseButton: true,
|
||||||
|
})).isConfirmed;
|
||||||
|
}
|
||||||
|
@ -8,6 +8,6 @@ export const apis = {
|
|||||||
submitMessage: backEndBaseURL + "/post/submit",
|
submitMessage: backEndBaseURL + "/post/submit",
|
||||||
listEssence: backEndBaseURL + "/post/listPublished?page=1",
|
listEssence: backEndBaseURL + "/post/listPublished?page=1",
|
||||||
|
|
||||||
listAll: backEndBaseURL + "/admin/list",
|
listNotReviewed: backEndBaseURL + "/admin/list/1",
|
||||||
setStatus: backEndBaseURL + "/admin/setStatus"
|
setStatus: backEndBaseURL + "/admin/setStatus"
|
||||||
};
|
};
|
@ -11,7 +11,7 @@ export function get(url) {
|
|||||||
"Allow-Control-Allow-Origin": "*"
|
"Allow-Control-Allow-Origin": "*"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
() => ({ fn: get(url), identifier: 'get:' + url })
|
{ fn: () => get(url), identifier: 'get:' + url }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export function post(url, data) {
|
export function post(url, data) {
|
||||||
@ -22,7 +22,7 @@ export function post(url, data) {
|
|||||||
"Allow-Control-Allow-Origin": "*"
|
"Allow-Control-Allow-Origin": "*"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
() => ({ fn: post(url, data), identifier: 'post:' + url + ' ' + JSON.stringify(data) })
|
{ fn: () => post(url, data), identifier: 'post:' + url + ' ' + JSON.stringify(data) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +63,7 @@ async function send(xhr, retryConf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function flushWaitList() {
|
function flushWaitList() {
|
||||||
waitToSend.forEach(retryFunc => retryFunc());
|
let fns = waitToSend.map(item => item.fn);
|
||||||
waitToSend.splice(0, waitToSend.length);
|
waitToSend.splice(0, waitToSend.length);
|
||||||
|
fns.forEach(fn => fn());
|
||||||
}
|
}
|
@ -26,12 +26,6 @@
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
border-bottom: 1px solid #e6e6e6;
|
border-bottom: 1px solid #e6e6e6;
|
||||||
}
|
}
|
||||||
.card-center {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.card-body {
|
.card-body {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,9 @@ export class AppContainer extends Component {
|
|||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
{
|
{
|
||||||
this.state.fetchingEssential
|
this.state.fetchingEssential
|
||||||
? <div className="card-center"><Spinner /></div>
|
? <div className="col-center"><Spinner isGray /></div>
|
||||||
: (this.state.essentialMessages.length === 0
|
: (this.state.essentialMessages.length === 0
|
||||||
? (<div className="card-center">暂时没有精选留言</div>)
|
? (<div className="col-center">暂时没有精选留言</div>)
|
||||||
: (
|
: (
|
||||||
<ul className="message-list">
|
<ul className="message-list">
|
||||||
{this.state.essentialMessages.map(msg => (
|
{this.state.essentialMessages.map(msg => (
|
||||||
@ -69,9 +69,9 @@ export class AppContainer extends Component {
|
|||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
{
|
{
|
||||||
this.state.fetchingEssential
|
this.state.fetchingEssential
|
||||||
? <div className="card-center"><Spinner /></div>
|
? <div className="col-center"><Spinner isGray /></div>
|
||||||
: (this.state.essentialImages.length === 0
|
: (this.state.essentialImages.length === 0
|
||||||
? (<div className="card-center">暂时没有精选图片</div>)
|
? (<div className="col-center">暂时没有精选图片</div>)
|
||||||
: this.state.essentialImages.map(src => (
|
: this.state.essentialImages.map(src => (
|
||||||
<img src={src} alt="精选图片" />
|
<img src={src} alt="精选图片" />
|
||||||
))
|
))
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
import { Component } from 'react';
|
|
||||||
import './review.css';
|
|
||||||
|
|
||||||
export class ReviewContainer extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
rating: 0,
|
|
||||||
comment: '',
|
|
||||||
showComment: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick(e) {
|
|
||||||
this.setState({
|
|
||||||
showComment: !this.state.showComment,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChange(e) {
|
|
||||||
this.setState({
|
|
||||||
rating: e.target.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCommentChange(e) {
|
|
||||||
this.setState({
|
|
||||||
comment: e.target.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="review">
|
|
||||||
<div className="rating">
|
|
||||||
<div className="star-rating">
|
|
||||||
<div className="star" />
|
|
||||||
<div className="star" />
|
|
||||||
<div className="star" />
|
|
||||||
<div className="star" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="comment">
|
|
||||||
<textarea
|
|
||||||
className="comment-input"
|
|
||||||
value={this.state.comment}
|
|
||||||
onChange={this.handleCommentChange.bind(this)}
|
|
||||||
/>
|
|
||||||
<div className="comment-button">
|
|
||||||
<button onClick={this.handleClick.bind(this)}>
|
|
||||||
Comment
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +1,3 @@
|
|||||||
.banner {
|
|
||||||
height: 80px;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 10px 80px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: #9D0004;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-box {
|
.message-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
|
@ -40,7 +40,6 @@ export class UploadContainer extends Component {
|
|||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
if (this.state.submitting && (!this.state.file || this.state.url !== "")) {
|
if (this.state.submitting && (!this.state.file || this.state.url !== "")) {
|
||||||
// upload using axios
|
|
||||||
post(apis.submitMessage, { content: this.state.msg, image: this.state.url })
|
post(apis.submitMessage, { content: this.state.msg, image: this.state.url })
|
||||||
.then(({ data, status, networkStatus }) => {
|
.then(({ data, status, networkStatus }) => {
|
||||||
if (networkStatus !== 200) return;
|
if (networkStatus !== 200) return;
|
||||||
|
載入中…
x
新增問題並參考
Block a user