diff --git a/src/App.css b/src/App.css index 984044e..19f35b9 100644 --- a/src/App.css +++ b/src/App.css @@ -2,50 +2,53 @@ a.btn { text-decoration: none; } .btn { - color: white !important; - border-radius: .3em; - padding: .375em 0; + --btn-fg: #FFF; + color: var(--btn-fg) !important; + border-radius: .4em; + padding: .3em 0; line-height: 1.5em; - font-size: 1.1em; cursor: pointer; transition: filter .3s ease-out; width: 5em; text-align: center; font-size: 18px; + border: 1px solid transparent; } .btn:disabled { cursor: not-allowed; filter: grayscale(100%) opacity(.5); } .btn:active { - color: white !important; + color: var(--btn-fg) !important; } .btn:hover(:not(:disabled)) { filter: brightness(1.2); } -button.btn { - border: none; -} - .btn-primary { - background-color: #318ffb; + background-color: #0AF; } .btn-ok { background-color: #47c74c; } .btn-gray { - background-color: #d9d9d9; + background-color: #E8E8E8; + --btn-fg: #000; } .btn-sdu { background-color: #9D0004; } -.btn.btn-light { - background-color: #fcfafa; - color: #323232 !important; +.btn-light { + background-color: #fcfcfc; + --btn-fg: #333; } -.btn.btn-light:active { - color: #323232 !important; +.btn.btn-hollow { + background-color: transparent; + border: 1px solid #FFF; +} +.btn.btn-dark.btn-hollow { + border: 1px solid #AAA; + --btn-fg: #333; } .btn-circle { @@ -56,10 +59,34 @@ button.btn { box-shadow: 1px 1px 4px 0 #0003; } .btn-straight { - border-radius: .15em; + border-radius: .2em; 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, .user { height: 100%; @@ -75,6 +102,10 @@ button.btn { margin-left: 10px; } +b { + color: #9E0004; +} + .content { width: 1000px; margin: 0 auto; @@ -86,4 +117,12 @@ button.btn { width: calc(100% - 80px); margin: 0 40px; } +} + +/* modifying sweet alert */ +.expanded-msg { + padding: 50px 0; +} +.swal2-actions > .btn { + margin: 0 40px; } \ No newline at end of file diff --git a/src/App.js b/src/App.js index 62e5dcf..3480074 100644 --- a/src/App.js +++ b/src/App.js @@ -3,7 +3,7 @@ import { Redirect, Route, SingleRouter } from './components/SingleRouter/SingleR import { AppContainer } from './index/index'; import { UploadContainer } from './upload/upload'; import { LogInContainer } from './login/login'; -import { ReviewContainer } from './review/review'; +import { ReviewContainer } from './admin/review/review'; import { Component } from 'react'; import { UserContext } from './helper/Context'; @@ -28,7 +28,7 @@ class App extends Component { - + diff --git a/src/admin/review/review.css b/src/admin/review/review.css new file mode 100644 index 0000000..a1ab715 --- /dev/null +++ b/src/admin/review/review.css @@ -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; + } +} \ No newline at end of file diff --git a/src/admin/review/review.js b/src/admin/review/review.js new file mode 100644 index 0000000..944e376 --- /dev/null +++ b/src/admin/review/review.js @@ -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(`
确认${accepted ? '发布' : '不通过'}此条信息?
`)) 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 ( +
+
+
+ logo + +
+ +
+
+ { + this.state.fetchingPosts + ? ( +
+ +
正在加载审核列表...
+
+ ) + : ( + this.state.posts.length === 0 + ? ( +
暂时没有待审核的内容哦
+ ) + : ( +
+

{this.state.posts[this.state.reviewingNow].content}

+ + 待审核的配图 + +
+ + +
+
+ ) + ) + } +
+
+ ); + } +} \ No newline at end of file diff --git a/src/components/Spinner/Spinner.js b/src/components/Spinner/Spinner.js index 10c6ea7..963746d 100644 --- a/src/components/Spinner/Spinner.js +++ b/src/components/Spinner/Spinner.js @@ -1,17 +1,19 @@ import './spinner.css'; -export default function Spinner(props) { +export default function Spinner({ isGray }) { + let base = isGray ? '888' : 'FFF'; return (
- - - - - - - - + + + + + + + + +
); } \ No newline at end of file diff --git a/src/components/UploadUnit/upload.css b/src/components/UploadUnit/upload.css index 4017da3..dbdc8c8 100644 --- a/src/components/UploadUnit/upload.css +++ b/src/components/UploadUnit/upload.css @@ -91,6 +91,7 @@ justify-content: center; display: none; z-index: 1; + cursor: zoom-out; } .scaled-wrap.open { display: flex; diff --git a/src/components/UserControl/UserControl.js b/src/components/UserControl/UserControl.js index 064ad59..817409b 100644 --- a/src/components/UserControl/UserControl.js +++ b/src/components/UserControl/UserControl.js @@ -16,7 +16,11 @@ export default function UserControl(props) {
) : ( @@ -34,9 +38,9 @@ export default function UserControl(props) {
{userData.name || "加载中"}
{ (() => { - if (userData.role !== 2 && History.getHref().match(/^\/admin.*/)) + if (userData.role === 1 && History.getHref().match(/^\/admin.*/)) History.force('/'); - if (userData.role !== -1) return null; + if (userData.role !== -1 || !localStorage.getItem('jwt')) return null; get(apis.getProfile).then(({ data, status, networkStatus }) => { if (networkStatus !== 200) return; if (!status) return alert('获取用户信息失败:' + data + ',请稍候刷新再试'); diff --git a/src/helper/alert.js b/src/helper/alert.js index a56fdfc..7dca0bd 100644 --- a/src/helper/alert.js +++ b/src/helper/alert.js @@ -2,8 +2,8 @@ import Swal from 'sweetalert2'; const SelfSwal = Swal.mixin({ customClass: { - confirmButton: 'btn btn-primary', - cancelButton: 'btn btn-gray', + confirmButton: 'btn btn-primary btn-pill', + cancelButton: 'btn btn-dark btn-hollow btn-pill', }, buttonsStyling: false, }); @@ -23,7 +23,8 @@ export const failed = (content, afterRetry) => { html: content, showCancelButton: true, confirmButtonText: '重试', - cancelButtonText: '放弃' + cancelButtonText: '放弃', + icon: 'error' }) .then(result => result.isConfirmed ? afterRetry() : null) : SelfSwal.fire({ @@ -39,6 +40,16 @@ export const alert = (content) => { return SelfSwal.fire({ html: content, confirmButtonText: '了解', - icon: 'warning' + icon: 'info' }); } + +export const confirmWithClose = async (content) => { + return (await SelfSwal.fire({ + html: content, + confirmButtonText: '确定', + showCancelButton: true, + cancelButtonText: '取消', + showCloseButton: true, + })).isConfirmed; +} diff --git a/src/helper/apis.js b/src/helper/apis.js index d445380..d57654c 100644 --- a/src/helper/apis.js +++ b/src/helper/apis.js @@ -8,6 +8,6 @@ export const apis = { submitMessage: backEndBaseURL + "/post/submit", listEssence: backEndBaseURL + "/post/listPublished?page=1", - listAll: backEndBaseURL + "/admin/list", + listNotReviewed: backEndBaseURL + "/admin/list/1", setStatus: backEndBaseURL + "/admin/setStatus" }; \ No newline at end of file diff --git a/src/helper/axios.js b/src/helper/axios.js index 4ec6d36..dcf001d 100644 --- a/src/helper/axios.js +++ b/src/helper/axios.js @@ -11,7 +11,7 @@ export function get(url) { "Allow-Control-Allow-Origin": "*" } }), - () => ({ fn: get(url), identifier: 'get:' + url }) + { fn: () => get(url), identifier: 'get:' + url } ); } export function post(url, data) { @@ -22,7 +22,7 @@ export function post(url, data) { "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() { - waitToSend.forEach(retryFunc => retryFunc()); + let fns = waitToSend.map(item => item.fn); waitToSend.splice(0, waitToSend.length); + fns.forEach(fn => fn()); } \ No newline at end of file diff --git a/src/index/index.css b/src/index/index.css index 6fcdf0f..10db512 100644 --- a/src/index/index.css +++ b/src/index/index.css @@ -26,12 +26,6 @@ font-size: 18px; border-bottom: 1px solid #e6e6e6; } -.card-center { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; -} .card-body { padding: 10px; } diff --git a/src/index/index.js b/src/index/index.js index 2d181bf..cf18a5d 100644 --- a/src/index/index.js +++ b/src/index/index.js @@ -48,9 +48,9 @@ export class AppContainer extends Component {
{ this.state.fetchingEssential - ?
+ ?
: (this.state.essentialMessages.length === 0 - ? (
暂时没有精选留言
) + ? (
暂时没有精选留言
) : (
    {this.state.essentialMessages.map(msg => ( @@ -69,9 +69,9 @@ export class AppContainer extends Component {
    { this.state.fetchingEssential - ?
    + ?
    : (this.state.essentialImages.length === 0 - ? (
    暂时没有精选图片
    ) + ? (
    暂时没有精选图片
    ) : this.state.essentialImages.map(src => ( 精选图片 )) diff --git a/src/review/review.css b/src/review/review.css deleted file mode 100644 index e69de29..0000000 diff --git a/src/review/review.js b/src/review/review.js deleted file mode 100644 index b83b634..0000000 --- a/src/review/review.js +++ /dev/null @@ -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 ( -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -