论坛首页改版、增加分论坛列表页

This commit is contained in:
谢思 2026-07-23 11:24:58 +08:00
parent 5b1d0016c1
commit fe17dac74f
29 changed files with 751 additions and 455 deletions

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2340181 */
src: url('iconfont.woff2?t=1778741577467') format('woff2'),
url('iconfont.woff?t=1778741577467') format('woff'),
url('iconfont.ttf?t=1778741577467') format('truetype');
src: url('iconfont.woff2?t=1784688510240') format('woff2'),
url('iconfont.woff?t=1784688510240') format('woff'),
url('iconfont.ttf?t=1784688510240') format('truetype');
}
.iconfont {
@ -13,10 +13,94 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-xiala5:before {
.icon-zhinengti:before {
content: "\ea0f";
}
.icon-a-fabu1:before {
content: "\ea0d";
}
.icon-a-search-ai6c9d7b621:before {
content: "\ea0e";
}
.icon-remenhuati:before {
content: "\e9df";
}
.icon-chengguolingyu:before {
content: "\ea09";
}
.icon-chengguoleixing:before {
content: "\ea0a";
}
.icon-chengguolaiyuan:before {
content: "\ea0b";
}
.icon-zhinengzhushou:before {
content: "\ea08";
}
.icon-shine-search:before {
content: "\ea07";
}
.icon-zuojiantou3:before {
content: "\ea05";
}
.icon-youjiantou2:before {
content: "\ea06";
}
.icon-fanhuagongju:before {
content: "\ea02";
}
.icon-jingxuanxiangmu1:before {
content: "\ea03";
}
.icon-gengduo2:before {
content: "\ea04";
}
.icon-shengwuyiyao:before {
content: "\e9f5";
}
.icon-youjiantou1:before {
content: "\e9fa";
}
.icon-zuojiantou2:before {
content: "\e9fd";
}
.icon-daqihaiyanghuanjing:before {
content: "\e9fe";
}
.icon-tianwendiliwuli:before {
content: "\e9ff";
}
.icon-xinnengyuanxincailiao:before {
content: "\ea00";
}
.icon-gongyeshejizhizao:before {
content: "\ea01";
}
.icon-tiezi:before {
content: "\e9f4";
}
.icon-yulan:before {
content: "\e9f1";
}

File diff suppressed because one or more lines are too long

View File

@ -6,12 +6,159 @@
"description": "",
"glyphs": [
{
"icon_id": "47540662",
"name": "下拉",
"font_class": "xiala5",
"icon_id": "48129347",
"name": "智能体",
"font_class": "zhinengti",
"unicode": "ea0f",
"unicode_decimal": 59919
},
{
"icon_id": "48114624",
"name": "发布 (1)",
"font_class": "a-fabu1",
"unicode": "ea0d",
"unicode_decimal": 59917
},
{
"icon_id": "48114623",
"name": "search-ai.6c9d7b62 (1)",
"font_class": "a-search-ai6c9d7b621",
"unicode": "ea0e",
"unicode_decimal": 59918
},
{
"icon_id": "48114629",
"name": "热门话题",
"font_class": "remenhuati",
"unicode": "e9df",
"unicode_decimal": 59871
},
{
"icon_id": "47969738",
"name": "成果领域",
"font_class": "chengguolingyu",
"unicode": "ea09",
"unicode_decimal": 59913
},
{
"icon_id": "47969739",
"name": "成果类型",
"font_class": "chengguoleixing",
"unicode": "ea0a",
"unicode_decimal": 59914
},
{
"icon_id": "47969740",
"name": "成果来源",
"font_class": "chengguolaiyuan",
"unicode": "ea0b",
"unicode_decimal": 59915
},
{
"icon_id": "45990748",
"name": "智能助手",
"font_class": "zhinengzhushou",
"unicode": "ea08",
"unicode_decimal": 59912
},
{
"icon_id": "47826921",
"name": "shine-search",
"font_class": "shine-search",
"unicode": "ea07",
"unicode_decimal": 59911
},
{
"icon_id": "47798947",
"name": "左箭头",
"font_class": "zuojiantou3",
"unicode": "ea05",
"unicode_decimal": 59909
},
{
"icon_id": "47798946",
"name": "右箭头",
"font_class": "youjiantou2",
"unicode": "ea06",
"unicode_decimal": 59910
},
{
"icon_id": "47778051",
"name": "泛化工具",
"font_class": "fanhuagongju",
"unicode": "ea02",
"unicode_decimal": 59906
},
{
"icon_id": "47778050",
"name": "精选项目",
"font_class": "jingxuanxiangmu1",
"unicode": "ea03",
"unicode_decimal": 59907
},
{
"icon_id": "47778049",
"name": "更多",
"font_class": "gengduo2",
"unicode": "ea04",
"unicode_decimal": 59908
},
{
"icon_id": "47778058",
"name": "生物医药",
"font_class": "shengwuyiyao",
"unicode": "e9f5",
"unicode_decimal": 59893
},
{
"icon_id": "47778057",
"name": "右箭头",
"font_class": "youjiantou1",
"unicode": "e9fa",
"unicode_decimal": 59898
},
{
"icon_id": "47778056",
"name": "左箭头",
"font_class": "zuojiantou2",
"unicode": "e9fd",
"unicode_decimal": 59901
},
{
"icon_id": "47778052",
"name": "大气海洋环境",
"font_class": "daqihaiyanghuanjing",
"unicode": "e9fe",
"unicode_decimal": 59902
},
{
"icon_id": "47778055",
"name": "天文地理物理",
"font_class": "tianwendiliwuli",
"unicode": "e9ff",
"unicode_decimal": 59903
},
{
"icon_id": "47778054",
"name": "新能源新材料",
"font_class": "xinnengyuanxincailiao",
"unicode": "ea00",
"unicode_decimal": 59904
},
{
"icon_id": "47778053",
"name": "工业设计制造",
"font_class": "gongyeshejizhizao",
"unicode": "ea01",
"unicode_decimal": 59905
},
{
"icon_id": "47756092",
"name": "帖子",
"font_class": "tiezi",
"unicode": "e9f4",
"unicode_decimal": 59892
},
{
"icon_id": "47540661",
"name": "预览",

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -123,4 +123,11 @@ export function deleteUserForums(id,is_apply) {
is_apply
}
});
}
}
export async function getForumHead(id) {
return fetch({
url: `/api/memos/forum_memos_head/${id}.json`,
method: 'get',
});
}

View File

@ -154,8 +154,6 @@ function detail(props) {
}
})
}}>{memo.is_fine ? "取消推荐" : "推荐"}</a>
<a onClick={()=>{setVisible(1)}}>删除</a>
</Fragment>}
{(memo.is_current_user || banned_permission) && <Fragment>
@ -167,6 +165,8 @@ function detail(props) {
setVisible(apply_destroy ? 3 : 2)
}}>{apply_destroy ? "撤销申请" : "申请删帖"}</a>
</Fragment>}
{banned_permission && <a onClick={()=>{setVisible(1)}}>删除</a>}
</div>
}
>

View File

@ -5,6 +5,7 @@ import { Divider, Form, Input, Cascader, Select, Breadcrumb, Upload, Button, Ico
import RichEditor from '../../forge/Component/RichEditor';
import UploadImage from '../../forge/Team/Component/UploadImage';
import { httpUrl } from "../fetch";
import cookie from 'react-cookies';
const { Option } = Select;
function EditForum(props) {
@ -198,7 +199,7 @@ function EditForum(props) {
</Form.Item>
<Form.Item label="上传附件">
{getFieldDecorator('attachments')(
<Upload.Dragger action={`${httpUrl}/api/attachments.json`} beforeUpload={beforeUpload} onChange={changeFileList} fileList={fileList}>
<Upload.Dragger action={`${httpUrl}/api/attachments.json`} beforeUpload={beforeUpload} onChange={changeFileList} fileList={fileList} withCredentials={true} headers={{ Authorization: cookie.load("autologin_trustie") }}>
<p className="ant-upload-drag-icon">
<Icon type="inbox" />
</p>
@ -210,7 +211,7 @@ function EditForum(props) {
<Button
className="mr20"
onClick={() => {
history.push("/forums");
history.go(-1);
}}
>
返回

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 204 KiB

BIN
src/forums/image/bk3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
src/forums/image/bk4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 KiB

BIN
src/forums/image/icon17.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/forums/image/icon18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1000 B

BIN
src/forums/image/icon19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

After

Width:  |  Height:  |  Size: 707 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -15,6 +15,10 @@ const List = Loadable({
loader : () => import("./list"),
loading: Loading,
})
const ListById = Loadable({
loader : () => import("./list/listById"),
loading: Loading,
})
const Editor = Loadable({
loader : () => import("./edit"),
loading: Loading,
@ -29,6 +33,12 @@ function SoftBot(props){
<Editor {...props} {...p} />
)}
></Route>
<Route
path="/forums/theme/:id"
render={(p) => (
<ListById {...props} {...p} />
)}
></Route>
<Route
path="/forums/:id/edit"
render={(p) => (

View File

@ -0,0 +1,65 @@
import React from "react";
import { Link } from "react-router-dom";
import { Divider, Input, Pagination, Tag } from "antd";
import Nodata from "../../forge/Nodata";
import icon5 from '../image/icon5.png';
import icon6 from '../image/icon6.png';
import icon10 from '../image/icon10.png';
import icon17 from '../image/icon17.png';
import './index.scss';
function ForumList({title="最新帖子", forumList, LIMIT, page, setPage, total, onSearch, onSort, sortBy}){
const sortImg1 = {
0: require('../image/icon7.png'),
1: require('../image/icon8.png'),
2: require('../image/icon9.png'),
}
return <div className="flex1 pb30">
<div className="df forums_header">
<img src={icon17} width={24}/>
<span className="font-22 font-bd ml8 mr30">{title}</span>
<Input.Search placeholder="输入名称关键字" className="forums_search" allowClear onSearch={(value)=>{onSearch(value)}}/>
<a onClick={()=>{onSort("published_at")}} className={`${sortBy === "published_at" ? 'active' : ''}`}>最新</a>
<Divider type="vertical" />
<a onClick={()=>{onSort("replies_count")}} className={`${sortBy === "replies_count" ? 'active' : ''}`}>最热</a>
</div>
<div className="forums-list4-box pt5">
{forumList.map((item, index) => {
const orderIndex = index+LIMIT*(page-1)
return <div className="forums-list4-item">
<div className="pr80 AlignCenter">
{orderIndex < 3 ? <img src={sortImg1[orderIndex]} width={24} className="mr10"/> : <span className="font-bd font-20 mr10">{orderIndex + 1}</span>}
<Link to={`/forums/${item.id}`} className="forums-list4-item-link task-hide font-22 mr10">
{item.subject}
</Link>
{item.sticky && <Tag color="#d06d3c">置顶</Tag>}
{item.is_original && <Tag color="#7e41f1">原创</Tag>}
{item.is_fine && <Tag color="#2E89FF">精华</Tag>}
<i className="iconfont icon-jiantou21 font-16"></i>
</div>
<div className="opacity8 mt15 forums-list4-item-bottom">
<img src={item.image_url} alt="" className="user-img" />
{item.username}
<span className="ml10">{item.published_time}</span>
<Divider type="vertical" />
<img src={icon5} width={14} className="mb3 mr5" />
{item.praises_count}
<img src={icon6} width={14} className="mb3 mr5 ml10" />
{item.replies_count}
</div>
{/* <span className="viewed_count">
<img src={icon10} width={11} className="mb3 mr5 viewed_count-icon" />
{item.viewed_count}
</span> */}
</div>
})}
{forumList.length === 0 && (
<Nodata _html="暂无数据" />
)}
<Pagination pageSize={LIMIT} total={total} hideOnSinglePage={true} showQuickJumper current={page} onChange={(page) => { setPage(page) }} className='edu-txt-right mt30 black_active_Pagination pr25' />
</div>
</div>
}
export default ForumList;

View File

@ -1,253 +1,217 @@
import React, { useEffect, useState } from "react";
import './index.scss';
import { Button, Carousel, Divider, Pagination, Tag } from "antd";
import { getForumsById, getForumSections, getForumsList } from "../api";
import { httpUrl } from "../fetch";
import { getForumSections, getForumsList } from "../api";
import { Link } from "react-router-dom";
import icon5 from '../image/icon5.png';
import icon6 from '../image/icon6.png';
import icon10 from '../image/icon10.png';
import img1 from '../image/img1.png';
import img2 from '../image/img2.png';
import img3 from '../image/img3.png';
import img4 from '../image/img4.png';
import Nodata from "../../forge/Nodata";
import { forumSectionId } from "../static";
import { rollingButton } from "../../components/button";
import { HoverUnderline } from "../../components/title";
import { rollingButton, slidingArrowButton } from "../../components/button";
import ForumList from "./forumList";
function List(props) {
const {mygetHelmetapi, location, current_user} = props;
const {mygetHelmetapi, current_user, showLoginDialog} = props;
const {common} = mygetHelmetapi || {};
const {forums: forumsDoMain} = common || {};
const tagNameByState = location && location.state && location.state.name;
const [forumsList, setForumsList] = useState([]);
const [forumsImgList, setForumsImgList] = useState([]);
const [hottestForumsList, setHottestForumsList] = useState([]);
//
const [forumTag, setForumTag] = useState([]);
//
const [forumTagDetail, setForumTagDetail] = useState(undefined);
//
const LIMIT = 10;
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [forumListByTag, setForumListByTag] = useState([]);
const [recommendList, setRecommendList] = useState([]);
// active
const [activeId, setActiveId] = useState(0);
const [activeId, setActiveId] = useState(null);
//
const [isInitialized, setIsInitialized] = useState(false);
const [search, setSearch] = useState()
const [sort, setSort] = useState("published_at")
//
const autoPlayTimerRef = React.useRef(null);
//
const isHoveringRef = React.useRef(false);
// id
const hoveringIdRef = React.useRef(null);
// forumTag
const forumTagRef = React.useRef([]);
const sortImg1 = {
0: require('../image/icon7.png'),
1: require('../image/icon8.png'),
2: require('../image/icon9.png'),
}
const sortImg2 = {
0: require('../image/icon2.png'),
1: require('../image/icon3.png'),
2: require('../image/icon4.png'),
}
const forumsImg = {
0: img1,
1: img2,
2: img3,
3: img4
}
function init(updatedTags){
const tagByState = updatedTags.filter(i=>i.title.includes(tagNameByState))
setForumTagDetail(tagByState && !!tagByState.length ? tagByState[0] : updatedTags[0]);
if (tagByState && !!tagByState.length) {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
const el = document.getElementById('forums-list3-id')
if (el) {
el.scrollIntoView({ behavior: 'smooth' })
}
})
})
//
const startAutoPlay = () => {
stopAutoPlay();
autoPlayTimerRef.current = setInterval(() => {
//
if (isHoveringRef.current) return;
// 使forumTagRefforumTag
const currentTags = forumTagRef.current;
if (!currentTags || currentTags.length === 0) return;
setActiveId(prevId => {
const currentIndex = currentTags.findIndex(t => t.id === prevId);
const nextIndex = (currentIndex + 1) % currentTags.length;
const nextTag = currentTags[nextIndex];
if (nextTag) {
return nextTag.id;
}
return prevId;
});
}, 3000); // 3
};
//
const stopAutoPlay = () => {
if (autoPlayTimerRef.current) {
clearInterval(autoPlayTimerRef.current);
autoPlayTimerRef.current = null;
}
}
};
//
const handleMouseEnter = (tag) => {
isHoveringRef.current = true;
hoveringIdRef.current = tag.id;
stopAutoPlay();
setActiveId(tag.id);
};
//
const handleMouseLeave = () => {
isHoveringRef.current = false;
hoveringIdRef.current = null;
startAutoPlay();
};
useEffect(() => {
document.title = '论坛交流';
getForumsList({
page: 1,
limit: 6,
sort: 'published_at',
homepage_show: true
}).then(res => {
if (res) {
setForumsList(res.memos || []);
const imageList = res.memos.filter(item=>!!item.memo_image_info)
setForumsImgList(imageList)
setHottestForumsList(res.hottest_memos || []);
}
})
getForumSections(forumSectionId).then(res => {
if (res && res.recommend_forum_sections) {
//
const childrenTags = res.recommend_forum_sections;
setForumTag(childrenTags);
init(childrenTags)
//
// const fetchEssencePosts = async (tag) => {
// try {
// const essenceRes = await getForumsById(tag.id, {
// page: 1,
// limit: 1,
// sort: 'published_at',
// select_type: 'is_fine',
// });
// return {
// ...tag,
// essencePosts: essenceRes?.memos || []
// };
// } catch (err) {
// return {
// ...tag,
// essencePosts: []
// };
// }
// };
// // 使 Promise.all
// Promise.all(childrenTags.map(fetchEssencePosts))
// .then(updatedTags => {
// setForumTag(updatedTags);
// if (updatedTags.length > 0) {
// init(updatedTags)
// }
// })
// .catch(error => {
// //
// setForumTag(childrenTags);
// if (childrenTags.length > 0) {
// init(childrenTags)
// }
// });
forumTagRef.current = childrenTags;
const firstTag = childrenTags && !!childrenTags.length ? childrenTags[0] : childrenTags[0];
if (firstTag) {
setActiveId(firstTag.id);
}
setIsInitialized(true);
}
})
}, [])
// forumTag
useEffect(() => {
if (forumTagDetail && forumTagDetail.id) {
// const forums = forumTagDetail.essencePosts[0] || {}
getForumsById(forumTagDetail.id, {
page: page,
limit: LIMIT,
sort: 'published_at',
select_type: 'all',
// hide_id: forums.id
}).then(res => {
if (res) {
setForumListByTag(res.memos || []);
setTotal(res.memos_count);
}
})
if (forumTag.length > 0 && isInitialized) {
forumTagRef.current = forumTag;
startAutoPlay();
}
}, [forumTagDetail && forumTagDetail.id, page])
return () => {
stopAutoPlay();
};
}, [forumTag.length, isInitialized])
useEffect(()=>{
getForumsList({
page: page,
limit: LIMIT,
sort: sort,
search: search,
}).then(res => {
if (res) {
setTotal(res.memos_count);
setForumsList(res.memos || []);
setHottestForumsList(res.hottest_memos || []);
setRecommendList(res.recommend_memos || []);
}
})
}, [page, sort, search])
return (
<div className="forums-list-box">
<div className="forums-banner-box">
<div className="width1600 center">
<div className="font-60 font-bd forums-banner-title1 mb10"><span>论坛交流·</span><span className="carousel-text">开始思想的</span><span className="carousel-text">联接与互动</span></div>
<div className="font-18 mb35 forums-banner-title2">需求反馈 技术交流 创意分享</div>
<div className="font-60 font-bd forums-banner-title1 mb10"><span>论坛交流·</span><span className="carousel-text">解锁头脑风暴</span></div>
<div className="font-18 mb35 forums-banner-title2">开源动态社区前言新闻速递开启开源新视野</div>
{forumsDoMain && rollingButton({href: current_user && current_user.login ? `/forums/add` : `/login?go_page=/forums/add`, name: '发布帖子', hoverName: '发布帖子', classname: "add-forums"})}
</div>
<div className="width1600 df pt50 forums-hot-list">
{forumsImgList && !!forumsImgList.length && <Carousel autoplay className='forums-list-left-Carousel' beforeChange={(_, nextId)=>{setActiveId(nextId)}}>
{forumsImgList.map((item, index)=>{
return <img src={httpUrl + item.memo_image_info.url} alt=''key={index}/>
})}
</Carousel>}
<div className="forums-list1">
{forumsList.map((item, index) => (
<div className={`font-18 forums-list-item ${activeId === index ? 'forums-list-item-active' : ''}`} key={index}>
<span className="forums-subject AlignCenter">
<Link className="task-hide" to={`/forums/${item.id}`}>{item.subject}</Link>
{index === 0 && <Tag color="#df2659" className="mr0">NEW</Tag>}
{item.is_original && <Tag color="#7e41f1">原创</Tag>}
</span>
</div>
))}
</div>
{/* 热门回答 */}
<div className="hot-forums-list flex1 ml20">
<div className="font-22 hot-forums-list-header">
<img src={require('../image/icon1.png')} alt="" width={24} className="mr8 mb3"/>
热门回答
</div>
<div className="forums-list2">
{hottestForumsList.slice(0,5).map((item, index) => (
<div className="font-18 forums-list-item" key={index}>
<span className="forums-subject AlignCenter">
{index < 3 ? <img src={sortImg2[index]} width={22} className="mr5"/> : <span className="ml5 mr10">{index + 1}</span>}
<Link className="task-hide" to={`/forums/${item.id}`}>{item.subject}</Link>
</span>
</div>
))}
</div>
</div>
</div>
</div>
<div className="forums-list3-box" id="forums-list3-box">
<div className="font-40 font-bd center mb40">精华论坛</div>
<div className="width1600 pb100" id="forums-list3-id">
<div className="width1600 df pt30 forums-hot-list">
{/* 四个板块 */}
<div className="team highlight-list teamShow">
{forumTag.map((item, index) => {
const isSelected = forumTagDetail && forumTagDetail.id === item.id;
const forums = item.essencePosts && item.essencePosts[0] || {};
const isSelected = activeId === item.id;
return (
<li className={`highlight-card ${isSelected ? "hovered":""}`} onClick={()=>{setForumTagDetail(item); setPage(1)}}>
<img src={forumsImg[index]} alt="" className="mb30" width={37}/>
<div className='t-title'><span dangerouslySetInnerHTML={{ __html: item.title }}></span></div>
<div className="t-desc" dangerouslySetInnerHTML={{ __html: item.description }}></div>
<li
className={`highlight-card ${isSelected ? "hovered":""}`}
onMouseEnter={() => handleMouseEnter(item)}
onMouseLeave={handleMouseLeave}
style={{ cursor: 'pointer' }}
>
<a href={`/forums/theme/${item.id}`}>
<div className='t-title'><span dangerouslySetInnerHTML={{ __html: item.title }}></span></div>
<div className="highlight-card-bottom">
查看更多
<i className="iconfont icon-arrright font-24 line-normal"></i>
</div>
</a>
</li>
)
})}
</div>
{/* 板块对应的帖子列表 */}
<div className="forums-list4-box mt40">
{forumListByTag.map((item, index) => {
const orderIndex = index+LIMIT*(page-1)
return <div className="forums-list4-item">
<div className="pr80 AlignCenter">
{orderIndex < 3 ? <img src={sortImg1[orderIndex]} width={24} className="mr10"/> : <span className="font-bd font-20 mr10">{orderIndex + 1}</span>}
<Link to={`/forums/${item.id}`} className="forums-list4-item-link task-hide">
<HoverUnderline classname="font-22 task-hide">
{item.subject}
</HoverUnderline>
</Link>
{item.sticky && <Tag color="#d06d3c">置顶</Tag>}
{item.is_original && <Tag color="#7e41f1">原创</Tag>}
{item.is_fine && <Tag color="#2E89FF">精华</Tag>}
</div>
<div className="opacity8 mt15">
<img src={item.image_url} alt="" className="user-img" />
{item.username}
<span className="ml10">{item.published_time}</span>
<Divider type="vertical" />
<img src={icon5} width={14} className="mb3 mr5" />
{item.praises_count}
<img src={icon6} width={14} className="mb3 mr5 ml10" />
{item.replies_count}
</div>
{/* <span className="viewed_count">
<img src={icon10} width={11} className="mb3 mr5 viewed_count-icon" />
{item.viewed_count}
</span> */}
</div>
</div>
<div className="forums-list3-box" id="forums-list3-box">
<div className="width1600 pb100 df forums-list3-content" id="forums-list3-id">
{/* 帖子列表 */}
<ForumList forumList={forumsList} LIMIT={LIMIT} page={page} setPage={setPage} total={total} onSearch={setSearch} onSort={setSort} sortBy={sort}/>
<div className="forums-list3-right">
<a className="add_forum" href={`/forums/add`} onClick={(e)=>{
if(current_user && !current_user.login){
e.stopPropagation();
e.preventDefault();
showLoginDialog("/forums/add");
}
}}><i className="iconfont icon-a-fabu1 font-16 mr5"></i>写点什么</a>
<div className="hot-forums-list mt20 mb20">
<div className="font-22 hot-forums-list-header">
<img src={require('../image/icon1.png')} alt="" width={24} className="mr8 mb3"/>
热门话题
</div>
})}
{forumListByTag.length === 0 && (
<Nodata _html="暂无数据" />
)}
<Pagination pageSize={LIMIT} total={total} hideOnSinglePage={true} current={page} onChange={(page) => { setPage(page) }} className='edu-txt-right mt30' />
<div className="forums-list2">
{hottestForumsList && hottestForumsList.length > 0 ? hottestForumsList.map((item, index) => (
<div className="font-18 forums-list-item" key={index}>
<span className="forums-subject AlignCenter">
{index < 3 ? <img src={sortImg2[index]} width={22} className="mr5"/> : <span className="ml5 mr10">{index + 1}</span>}
<Link className="task-hide" to={`/forums/${item.id}`}>{item.subject}</Link>
</span>
</div>
)) : <Nodata _html="暂无数据" small/>}
</div>
</div>
<div className="hot-forums-list">
<div className="font-22 hot-forums-list-header">
<img src={require('../image/icon18.png')} alt="" width={24} className="mr8 mb3"/>
版主推荐
</div>
<div className="forums-list2">
{recommendList && recommendList.length > 0 ? recommendList.map((item, index) => (
<div className="font-18 forums-list-item" key={index}>
<span className="forums-subject AlignCenter">
<span className="ml5 mr10">{index + 1}</span>
<Link className="task-hide" to={`/forums/${item.id}`}>{item.subject}</Link>
</span>
</div>
)) : <Nodata _html="暂无数据" small/>}
</div>
</div>
</div>
</div>
</div>

View File

@ -4,23 +4,27 @@
color: #091221;
background-color: #f1f6fd;
font-family: "alibabaReg";
background-image: url('../image/banner.png');
background-size: 100% 100%;
.ant-tag {
line-height: 16px;
padding: 0 3px;
margin-left: 10px;
margin-right: 0px;
&+.ant-tag {
margin-left: 6px;
}
}
.font-bd{
font-weight: normal;
font-family: "alibaba";
}
}
.forums-banner-box {
background-image: url('../image/banner.png');
background-size: 100% 100%;
padding: 70px 0 145px;
padding: 70px 0 120px;
.forums-banner-title1 {
font-family: 'DouyinSansBold';
@ -49,14 +53,7 @@
}
.carousel-text {
background-image: linear-gradient(313.07deg, #d62ece 0%, #1664ff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
&:nth-of-type(2) {
background-image: linear-gradient(313.07deg, #1664ff 0%, #06050e 100%);
}
color: #2149d4;
}
.forums-banner-title2 {
@ -69,7 +66,7 @@
width: 168px;
height: 60px;
border-radius: 30px;
border: 4px solid #CCD3E8;
border: 4px solid #E2D5DC;
line-height: 52px;
position: relative;
--offsetTop: 26px;
@ -82,30 +79,11 @@
}
}
.ant-carousel {
width: 48.3%;
border-radius: 15px 0px 0px 15px;
overflow: hidden;
}
.forums-list-left-Carousel {
img {
height: 392px;
object-fit: cover;
}
}
.forums-list1 {
width: 23.4%;
background-color: #ffffff;
border-radius: 0px 15px 15px 0px;
padding: 10px 15px;
}
}
.hot-forums-list {
background-color: #ffffff;
border-radius: 8px;
border-radius: 15px;
box-shadow: 0px 0px 10px rgba(35, 44, 121, 0.07);
}
@ -139,15 +117,14 @@
}
}
.forums-list-item:not(:last-of-type):not(.forums-list-item-active) {
.forums-list-item:not(:last-of-type) {
.forums-subject {
border-bottom: 1px dashed rgba(130, 132, 164, 0.4);
}
}
.forums-list-item:hover,
.forums-list-item-active {
.forums-list-item:hover {
background-image: linear-gradient(180deg, #f7f9fd00 0%, #f7f9fd 100%);
border-radius: 4px;
font-weight: bold;
@ -162,13 +139,13 @@
}
.hot-forums-list-header {
padding: 12px 25px 10px 25px;
padding: 12px 16px 10px 16px;
background-image: url('../image/bk2.png');
background-size: 100% 100%;
}
.forums-list2 {
padding: 0 25px 12px 25px;
padding: 0 16px 12px 16px;
}
.forums-hot-list {
@ -176,17 +153,49 @@
--offsetTop: 56px;
animation: itemUp .4s ease-in-out 1.36s forwards, bgOpacity .4s linear 1.36s reverse backwards;
}
}
.forums-list3-box {
padding: 60px 0 60px;
background-image: linear-gradient(179.88deg, #ffffff 0%, rgba(255, 255, 255, 0.62) 16.1%, rgba(255, 255, 255, 0) 100%);
border-radius: 40px;
position: relative;
--offsetTop: 116px;
--top: -60px;
animation: itemUp .4s ease-in-out 1.56s forwards, bgOpacity .4s linear 1.56s reverse backwards;
.forums-list3-content {
gap: 20px;
&>div.flex1{
background-color: white;
border-radius: 0px 0px 15px 15px;
}
}
.forums-list3-right{
width: 26.5%;
flex-shrink: 0;
}
}
a.add_forum, a.add_forum:link{
display: block;
height:48px;
line-height: 48px;
background:#091221;
border-radius:15px;
color:#ffffff;
font-size:18px;
text-align: center;
&:hover{
opacity: 0.8;
}
}
.forums-list4-box {
background-color: #ffffff;
border-radius: 0 0 15px 15px;
.user-img {
width: 24px;
height: 24px;
@ -195,124 +204,38 @@
margin-right: 10px;
}
.forums-section-box {
gap: 20px;
}
.forums-section-item-box {
border-radius: 15px;
border: 2px solid transparent;
box-shadow: 0px 3px 6px rgba(22, 100, 255, 0.02);
.forums-list4-item {
padding: 25px 30px 0 25px;
position: relative;
&.active {
border-color: #2149d4;
&::before {
width: 106%;
height: 110%;
content: '';
position: absolute;
background-color: rgb(33 72 212 / 20%);
top: -5%;
left: -3%;
border-radius: 15px;
&:hover{
background:#f7f9fd;
border-radius:10px;
.forums-list4-item-link{
font-family: "alibaba";
}
&::after {
content: "";
position: absolute;
top: 105%;
left: 50%;
transform: translateX(-50%);
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid rgb(33 72 212 / 20%);
}
}
&:nth-of-type(3) .forums-section-item {
background-image: url('../image/forums3.png');
background-size: 100% 100%;
}
&:nth-of-type(2) .forums-section-item {
background-image: url('../image/forums2.png');
background-size: 100% 100%;
}
&:nth-of-type(4) .forums-section-item {
background-image: url('../image/forums4.png');
background-size: 100% 100%;
}
}
.forums-section-item {
position: relative;
cursor: pointer;
border-radius: 15px;
background-image: url('../image/forums1.png');
background-size: 100% 100%;
.memo_image_info {
width: 100%;
height: auto;
object-fit: cover;
border-radius: 15px 15px 0 0;
transition: transform .4s cubic-bezier(.25, .46, .45, .94);
}
.memo_image_info_box {
margin: 15px;
overflow: hidden;
border-radius: 15px;
}
.forums-section-item-content {
// background-color: white;
border-radius: 15px;
overflow: hidden;
}
.icon-jiantou3 {
display: none;
}
&:hover {
.icon-jiantou3 {
// color:#2149d4;
// display: inline-block;
.ant-tag {
display: none;
}
a {
// color:#2149d4;
}
.memo_image_info {
transform: scale(1.05);
}
}
a:hover {
color: #2149d4;
.icon-jiantou3 {
.icon-jiantou21{
display: inline-block;
}
.forums-list4-item-link{
color: #091221;
}
}
}
}
.forums-list4-box {
background-color: #ffffff;
border-radius: 15px;
padding: 25px 30px;
.forums-list4-item-bottom{
border-bottom: 1px dashed rgba(130, 132, 164, 0.4);
padding-bottom: 25px;
}
.forums-list4-item {
position: relative;
border-bottom: 1px dashed rgba(130, 132, 164, 0.4);
padding-bottom: 12px;
margin-bottom: 20px;
.icon-jiantou21{
display: none;
}
}
.viewed_count {
@ -332,22 +255,11 @@
animation: fire 1s ease-in-out infinite;
}
}
.forums-list4-item-link {
&:hover {
.hover-underline {
padding-right: 30px;
}
&~.ant-tag {
display: none;
}
}
}
}
.team {
display: flex;
gap: 20px;
margin-top: 40px;
width: 100%;
padding-left: 0px;
@ -361,103 +273,70 @@
}
li {
height: 280px;
height: 260px;
padding: 30px 30px 34px 30px;
box-sizing: border-box;
border-radius: 15px;
flex: 1 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 0;
margin-right: 20px;
transition: 0.2s;
text-align: left;
position: relative;
transition-duration: 1s;
cursor: pointer;
background-size: 100% 100%;
&>span {
margin-bottom: auto;
font-size: 18px;
}
&::after {
position: absolute;
width: 100%;
height: 100%;
content: "";
right: 0;
top: 0;
background-position: right bottom;
background-repeat: no-repeat;
background-size: 100% 100%;
border-radius: 15px;
transition-duration: 1s;
}
border-radius: 15px;
&:nth-child(1) {
background-image: url("../image/image13.png");
&::after {
background-image: url("../image/image9.png");
width: 100%;
background-image: url("../image/image5.png");
.t-title{
background:linear-gradient(94.98deg,#ffffff 3.87%,#ffffff 83.9%,#eca2b9 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
}
&:nth-child(2) {
background-image: url("../image/image6.png");
&::after {
background-image: url("../image/image10.png");
width: 100%;
.t-title{
background:linear-gradient(92.24deg,#ffffff 2.21%,#ffffff 86.8%,#87e1e8 99.78%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
}
&:nth-child(3) {
background-image: url("../image/image7.png");
&::after {
background-image: url("../image/image11.png");
width: 100%;
.t-title{
background:linear-gradient(97.88deg,#ffffff 3.83%,#ffffff 83.89%,#eca2b9 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
}
&:nth-child(4) {
background-image: url("../image/image8.png");
&::after {
background-image: url("../image/image12.png");
width: 100%;
.t-title{
background:linear-gradient(94.26deg,#ffffff 2.16%,#ffffff 81.2%,#9cd8f8 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
}
&.hovered {
color: white;
background-image: url("../image/image5.png");
.t-title span{
font-size: 26px;
line-height: 32px;
}
}
// &:hover{
// .t-title span{
// font-size: 26px;
// }
// }
&:last-child {
margin-right: 0px;
}
&.hovered, &:hover {
flex: 2 1;
&:nth-child(1)::after {
width: 50%;
transform: translateY(-24px);
.highlight-card-bottom{
font-family: "alibaba";
}
&:not(:nth-child(1))::after {
width: 70%;
.iconfont {
display: inline-block;
animation: arrow-move 1.2s ease-in-out infinite;
}
}
@ -467,30 +346,84 @@
span {
display: block;
font-size: 18px;
line-height: 30px;
font-size: 28px;
line-height: 36px;
font-family: "alibabaBold";
}
}
.t-desc {
font-size: 14px;
line-height: 22px;
text-align: left;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
font-family: alibabaPuhuiR;
-webkit-line-clamp: 2;
opacity: 0.8;
.highlight-card-bottom{
position: absolute;
left: 0px;
bottom: 10px;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 25px;
color: white;
font-size:20px;
}
}
}
.t-time {
font-size: 15px;
text-align: left;
.forums_header{
background-image: url('../image/bk3.png');
background-size: 100% 100%;
align-items: center;
padding: 11px 30px;
.forums_search{
width: 320px;
margin-right: auto;
.ant-input{
border: none;
border-radius:18px;
height: 36px;
padding-left: 16px;
}
.ant-input-search-icon{
position: relative;
width: 15px;
svg{
display: none;
}
&::before{
content: "\ea0e";
font-family: iconfont;
position: absolute;
display: inline-block;
color: #191919;
left: 0px;
font-size: 16px;
}
}
}
a{
color:#8284a4;
font-size:15px;
&.active{
color: #2149d4;
}
}
}
.forumListById_box{
background-image: url('../image/bk4.png');
background-size: 100% 100%;
padding-bottom: 100px;
min-height: 89vh;
a.add_forum{
padding: 0 18px;
border-radius:24px;
margin-left: auto;
}
.ant-pagination{
padding-bottom: 40px;
}
}

View File

@ -0,0 +1,84 @@
import React, { useEffect, useState, useMemo } from "react";
import { Breadcrumb } from "antd";
import { Link } from "react-router-dom";
import icon19 from '../image/icon19.png';
import { getForumHead, getForumsById } from "../api";
import ForumList from "./forumList";
import './index.scss';
function forumListById(props){
const LIMIT = 10;
const { match: { params: { id } }, current_user, showLoginDialog } = props;
const [detail, setDetail] = useState({});
const [forumsList, setForumsList] = useState([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [search, setSearch] = useState()
const [sort, setSort] = useState("published_at")
const {forum_section={}, bread_crumb} = detail || {};
const {forum_tag} = bread_crumb || {};
// forum_tag children_bread_crumb ID
const getTagIds = (tag) => {
if (!tag) return [];
const ids = [tag.id];
if (tag.children_bread_crumb && tag.children_bread_crumb.id) {
ids.push(...getTagIds(tag.children_bread_crumb));
}
return ids;
};
const tagIdsStr = useMemo(() => getTagIds(forum_tag).join(','), [forum_tag]);
useEffect(()=>{
if(!id) return
getForumHead(id).then(res=>{
setDetail(res || {});
document.title = `${res && res.forum_section && res.forum_section.title}-论坛交流`;
})
}, [id])
useEffect(()=>{
if(!id) return
getForumsById(id, {
page: page,
limit: LIMIT,
sort: sort,
select_type: 'all',
search: search
}).then(res => {
if (res) {
setForumsList(res.memos || []);
setTotal(res.memos_count);
}
})
}, [id, page, sort, search])
return <div className="forumListById_box">
<div className="width1600 pt25 pb20">
<Link to="/forums" className="opacity7">论坛交流<i className="iconfont icon-youjiantou font-12 ml5 mr5"></i></Link>
{forum_section.title}详情
</div>
<div className="width1600 df" style={{alignItems: 'center'}}>
<img src={icon19} width={48} className="mr25"/>
<div>
<div className="font-bd font-24">{forum_section.title}</div>
<div className="opacity8 font-15">{forum_section.description}</div>
</div>
<a className="add_forum" href={`/forums/add?sec=${tagIdsStr}`} onClick={(e)=>{
if(current_user && !current_user.login){
e.stopPropagation();
e.preventDefault();
showLoginDialog(`/forums/add?sec=${tagIdsStr}`);
}
}}><i className="iconfont icon-a-fabu1 font-16 mr5"></i>写点什么</a>
</div>
{/* 板块对应的帖子列表 */}
<div className="width1600 df mt30">
<ForumList title="全部帖子" forumList={forumsList} LIMIT={LIMIT} page={page} setPage={setPage} total={total} onSearch={setSearch} onSort={setSort} sortBy={sort}/>
</div>
</div>
}
export default forumListById;

View File

@ -315,10 +315,11 @@ i.color-orange05:hover {
color:#fff !important;
}
}
.ant-pagination-item:hover, .ant-pagination-item:focus, .ant-pagination-item:active, .ant-pagination-next:hover .ant-pagination-item-link, .ant-pagination-prev:hover .ant-pagination-item-link{
border-color:#091221;
a, i{
li, li:hover, li:focus, li:active{
border-color:#091221 !important;
a, i, a.ant-pagination-item-link i{
color:#091221;
border-color:#091221 !important;
}
}
.ant-pagination-options-quick-jumper input:hover{