diff --git a/packages/core/handler/discuss.ts b/packages/core/handler/discuss.ts index 86b6089..7647760 100644 --- a/packages/core/handler/discuss.ts +++ b/packages/core/handler/discuss.ts @@ -1,7 +1,7 @@ import {perm} from '../declare/perm'; import {DefaultType} from '../declare/type'; import {Handler, Route} from '../handle'; -import {DiscussSchema, RespondProps, discuss} from '../model/discuss'; +import {DiscussSchema, RespondProps, discuss, DiscussListElementSchema} from '../model/discuss'; import {param} from '../utils/decorate'; import {token as tokenModel} from '../model/token'; import {CommentSchema, comment} from '../model/comment'; @@ -263,12 +263,25 @@ class DiscussHandler extends Handler { @param('page', DefaultType.Number) async postHotDiscussList(limit: string, page: string) { try { - // const requester = await tokenModel.stripId(token); + const data: DiscussListElementSchema[] = await discuss.getRecentHotDiscuss(parseInt(limit), parseInt(page)); + const respData: (DiscussListElementSchema & CommentSchemaExtra)[] = [] + + const count = await discuss.count(); + + for (const datum of data) { + const author = await user.getbyId(datum.author); + const respDatum: DiscussListElementSchema & CommentSchemaExtra = { + ...datum, + authorName: author.username, + authorAvatar: author.gravatarLink, + }; + respData.push(respDatum); + } - const data = await discuss.getRecentHotDiscuss(parseInt(limit), parseInt(page)); this.ctx.body = { status: 'success', - data, + count, + data: respData, }; } catch (err) { this.ctx.body = { diff --git a/packages/core/model/discuss.ts b/packages/core/model/discuss.ts index 5176ec3..5a3163f 100644 --- a/packages/core/model/discuss.ts +++ b/packages/core/model/discuss.ts @@ -29,6 +29,10 @@ export class RespondProps { type DiscussUpdatedSchema = Omit, 'did'>; +export type DiscussListElementSchema = Omit, 'responds'> & { + recentCommentCount: number; +}; + export class DiscussModel { async genDId() { const newID = (await db.getone('count', {type: 'discussId'}))?.count + 1 || 1; @@ -233,8 +237,8 @@ export class DiscussModel { ],); } - async getRecentHotDiscuss(limit: number, page: number): Promise { - return await db.aggregate('discuss', [ + async getRecentHotDiscuss(limit: number, page: number): Promise { + return await db.aggregate('discuss', [ {$match: {deleted: false}}, { $lookup: { @@ -264,6 +268,14 @@ export class DiscussModel { {$limit: limit}, ],); } + + async count(): Promise { + const count = await db.aggregate<{count: number}>('discuss', [ + {$match: {deleted: false}}, + {$count: 'count'}, + ],); + return count[0].count; + } } export const discuss = new DiscussModel(); diff --git a/packages/core/service/db.ts b/packages/core/service/db.ts index 93572bc..f55ad7f 100644 --- a/packages/core/service/db.ts +++ b/packages/core/service/db.ts @@ -78,11 +78,11 @@ class dbClass { return res; } - async aggregate(model: string, pipeline: object[], options: AggregateOptions = {}) { + async aggregate(model: string, pipeline: object[], options: AggregateOptions = {}) { const client = new MongoClient(this.url); const database = client.db(this.dbname); const coll = database.collection(model); - const res = await coll.aggregate(pipeline, options).toArray(); + const res = await coll.aggregate(pipeline, options).toArray(); client.close(); return res; } diff --git a/packages/ui/src/app.tsx b/packages/ui/src/app.tsx index 2a911ec..f5ea120 100644 --- a/packages/ui/src/app.tsx +++ b/packages/ui/src/app.tsx @@ -11,6 +11,7 @@ import * as Direct from './interfaces/interface'; import DiscussPage from './pages/discuss'; import './app.css'; import { DiscussCreatePage } from './pages/discussCreate'; +import DiscussListPage from './pages/discussList'; const myCache = createEmotionCache({ key: 'school-hub' }); @@ -83,6 +84,7 @@ function App() { }> } /> } /> + } /> } /> } /> diff --git a/packages/ui/src/handlers/discussHandler.ts b/packages/ui/src/handlers/discussHandler.ts index b2bb479..688da45 100644 --- a/packages/ui/src/handlers/discussHandler.ts +++ b/packages/ui/src/handlers/discussHandler.ts @@ -1,4 +1,4 @@ -import { fetch } from '../interfaces/data'; +import {fetch} from '../interfaces/data'; interface CreateProp { token: string; @@ -30,6 +30,12 @@ interface FetchRespondProp { did: number; } +interface FetchDiscussListProp { + limit: number; + page: number; + token: string; +} + interface Response { status: 'success' | 'error'; msg?: string; @@ -76,6 +82,15 @@ interface FetchRespondResponse extends Response { param?: string; } +interface FetchDiscussListResponse extends Response { + status: 'success' | 'error'; + msg?: string; + data?: DiscussListElementSchema[]; + count?: number; + type?: string; + param?: string; +} + export interface CommentSchema { cid: number; did: number; @@ -115,6 +130,23 @@ export interface DiscussSchema { parsedResponds: RespondProps[]; } +export interface DiscussListElementSchema { + did?: number; + author: number; + topic: string; + tags: Array; + title: string; + content: string; + createdTime: number; + lastModified: number; + official: boolean; + officialNotice: string; + authorName: string; + authorAvatar: string; + commentCount: number; + recentCommentCount: number; +} + interface InfoResponse extends Response { status: 'success' | 'error'; msg?: string; @@ -172,3 +204,8 @@ export async function handleFetchResponds(fetchRespondData: FetchRespondProp): P const data = await fetch('discuss', 'fetchResponds', fetchRespondData); return data; } + +export async function handleFetchDiscussList(fetchDiscussListData: FetchDiscussListProp): Promise { + const data = await fetch('discuss', 'hotDiscussList', fetchDiscussListData); + return data; +} \ No newline at end of file diff --git a/packages/ui/src/pages/discussList.tsx b/packages/ui/src/pages/discussList.tsx new file mode 100644 index 0000000..128c11b --- /dev/null +++ b/packages/ui/src/pages/discussList.tsx @@ -0,0 +1,150 @@ +import { + Alert, + Avatar, Badge, + Card, Center, + Container, + createStyles, Divider, Flex, Menu, Pagination, Popover, Space, Text, +} from '@mantine/core'; +import React, {useEffect, useState} from 'react'; +import {useParams} from 'react-router-dom'; +import { + DiscussListElementSchema, + fetchDiscussError, + handleFetchDiscussList, +} from '../handlers/discussHandler'; +import {NoStyleCard} from '../components/card'; +import moment from 'moment/moment'; +import {IconEye, IconInfoCircle, IconMessage} from '@tabler/icons-react'; + +const useStyles = createStyles((theme) => ({ + discussTitle: { + fontWeight: 600, + fontSize: 16, + } +})); + +function DiscussSingle({data}: { data: DiscussListElementSchema }) { + const {theme, classes} = useStyles(); + return ( + <> + { + window.location.href = `/discuss/${data.did}`; + }} + > + + + + +
+ + + {data.authorName} · {moment(data.createdTime * 1000).format('YYYY-MM-DD HH:mm:ss')} + + + + {data.title} + + + + + {data.commentCount} + + · + + + + + {data.commentCount} + +
+
+
+ + ) +} + +export default function DiscussListPage() { + const {theme, classes} = useStyles(); + + const [loaded, setLoaded] = useState(false); + const [status, setStatus] = useState(false); + const [errorMsg, setErrorMsg] = useState(''); + + const param = useParams(); + + const [discussList, setDiscussList] = useState([]); + const [discussCount, setDiscussCount] = useState(0); + + const [nowPage, setNowPage] = useState(1); + useEffect(() => { + handleFetchDiscussList({ + token: localStorage.getItem('token') || '', + limit: 5, + page: nowPage + }).then((response) => { + if (response.status === 'success') { + if (response.data) { + setDiscussList(response.data); + setDiscussCount(response.count || 0); + setLoaded(true); + setStatus(true); + } + } else { + setLoaded(true); + setStatus(false); + setErrorMsg(response.type ? fetchDiscussError[response.type] || '后端未知错误' : '后端未知错误'); + } + }); + }, [nowPage]); + + return ( + <> + + + } radius={0} title="欢迎来到 灌水区" color="blue"> + + 规定什么的都不重要的吧,随便灌水就好了( + + + + + {loaded ? ( + status ? ( + <> + + {discussList.map((element) => { + return ( + + ); + })} +
+
+ + ) : ( +
{errorMsg}
+ ) + ) : ( +
加载中……
+ )} +
+ + ); +}