Compare commits
10 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
87bc88600e | |
|
|
6409ad6940 | |
|
|
5aae70e4c7 | |
|
|
811bdc3d10 | |
|
|
406f0dc51e | |
|
|
fe17dac74f | |
|
|
5b1d0016c1 | |
|
|
3ebc2f6ee4 | |
|
|
18cc06a4ae | |
|
|
1dcaf6a291 |
|
|
@ -56,4 +56,4 @@ export const deepRoutes = [
|
||||||
]
|
]
|
||||||
|
|
||||||
// 不进行组织或个人判断
|
// 不进行组织或个人判断
|
||||||
export const specialRoute = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot","zone", "undefined", "admins", "oauth", "competitions", "hiagent","sf", "development", "governance"]
|
export const specialRoute = ["ossRepo", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot","zone", "undefined", "admins", "oauth", "competitions", "hiagent","sf", "development", "governance","explore"]
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 2340181 */
|
font-family: "iconfont"; /* Project id 2340181 */
|
||||||
src: url('iconfont.woff2?t=1778741577467') format('woff2'),
|
src: url('iconfont.woff2?t=1784688510240') format('woff2'),
|
||||||
url('iconfont.woff?t=1778741577467') format('woff'),
|
url('iconfont.woff?t=1784688510240') format('woff'),
|
||||||
url('iconfont.ttf?t=1778741577467') format('truetype');
|
url('iconfont.ttf?t=1784688510240') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
|
|
@ -13,10 +13,94 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-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";
|
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 {
|
.icon-yulan:before {
|
||||||
content: "\e9f1";
|
content: "\e9f1";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,159 @@
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
{
|
{
|
||||||
"icon_id": "47540662",
|
"icon_id": "48129347",
|
||||||
"name": "下拉",
|
"name": "智能体",
|
||||||
"font_class": "xiala5",
|
"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": "e9df",
|
||||||
"unicode_decimal": 59871
|
"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",
|
"icon_id": "47540661",
|
||||||
"name": "预览",
|
"name": "预览",
|
||||||
|
|
|
||||||
20
src/App.js
|
|
@ -236,6 +236,11 @@ const GovernanceIframe = Loadable({
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const OssRepoIframe = Loadable({
|
||||||
|
loader: () => import("./forge/ossRepoIframe"),
|
||||||
|
loading: Loading,
|
||||||
|
});
|
||||||
|
|
||||||
const Forums = Loadable({
|
const Forums = Loadable({
|
||||||
loader: () => import("./forums"),
|
loader: () => import("./forums"),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
|
|
@ -252,7 +257,7 @@ const AI = Loadable({
|
||||||
});
|
});
|
||||||
|
|
||||||
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
|
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
|
||||||
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot","zone", "hiagent","sf", "development", "governance", "forums", "news", "exploreStore", "factory", "zoneAdmin", "ai"];
|
const keyWord = ["ossRepo", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder", "glcc","bindlogin", "softbot","zone", "hiagent","sf", "development", "governance", "explore","forums", "news", "exploreStore", "factory", "zoneAdmin", "ai"];
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|
@ -636,7 +641,7 @@ class App extends Component {
|
||||||
<Route path="/search" component={Search} mygetHelmetapi={mygetHelmetapi} />
|
<Route path="/search" component={Search} mygetHelmetapi={mygetHelmetapi} />
|
||||||
|
|
||||||
{/* 项目标签列表页 */}
|
{/* 项目标签列表页 */}
|
||||||
<Route path="/explore/topic/:id/:name" component={Topic} mygetHelmetapi={mygetHelmetapi} />
|
<Route path="/ossRepo/topic/:id/:name" component={Topic} mygetHelmetapi={mygetHelmetapi} />
|
||||||
|
|
||||||
<Route path={"/:OIdentifier/enterprise"}
|
<Route path={"/:OIdentifier/enterprise"}
|
||||||
render={
|
render={
|
||||||
|
|
@ -723,7 +728,7 @@ class App extends Component {
|
||||||
<Projects {...this.props} {...props} />
|
<Projects {...this.props} {...props} />
|
||||||
)}
|
)}
|
||||||
></Route>
|
></Route>
|
||||||
<Route exact path="/explore"
|
<Route exact path="/ossRepo"
|
||||||
render={
|
render={
|
||||||
(props) => (
|
(props) => (
|
||||||
<Projects {...this.props} {...props} {...this.state}/>
|
<Projects {...this.props} {...props} {...this.state}/>
|
||||||
|
|
@ -745,6 +750,15 @@ class App extends Component {
|
||||||
}>
|
}>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path={"/explore"}
|
||||||
|
render={
|
||||||
|
(props) => {
|
||||||
|
return (<OssRepoIframe {...this.props} {...props} {...this.state} />)
|
||||||
|
}
|
||||||
|
}>
|
||||||
|
</Route>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={"/factory"}
|
path={"/factory"}
|
||||||
render={
|
render={
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import fetch from './fetch';
|
||||||
|
import fetchLogin from './fetchLogin';
|
||||||
|
|
||||||
|
/**智能体分类列表***/
|
||||||
|
export function getAgentTypeList(params) {
|
||||||
|
return fetch({
|
||||||
|
url: `/console-api/home-page/agent-square/get-bot-type-list`,
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**智能体列表***/
|
||||||
|
export function getAgentList(params) {
|
||||||
|
return fetch({
|
||||||
|
url: `/console-api/home-page/agent-square/get-bot-page-by-type`,
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**智能体登录***/
|
||||||
|
export function agentLogin(data) {
|
||||||
|
return fetchLogin({
|
||||||
|
url: `/api/login/oauth/access_token`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { withRouter } from "react-router";
|
||||||
|
import { httpUrl } from '../../ai/fetch';
|
||||||
|
import cookie from 'react-cookies';
|
||||||
|
import { aiAgentLogin } from "../../forge/Information/api";
|
||||||
|
import { agentLogin } from "../api";
|
||||||
|
|
||||||
|
function Agent(props) {
|
||||||
|
const { match, current_user, history, showLoginDialog } = props;
|
||||||
|
const { id } = match.params;
|
||||||
|
const { login } = current_user || {};
|
||||||
|
const [iframeUrl, setIframeUrl] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = "智能体-AI资源";
|
||||||
|
checkLoginAndGetIframeUrl();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 检查登录状态并获取iframe URL
|
||||||
|
const checkLoginAndGetIframeUrl = async () => {
|
||||||
|
try {
|
||||||
|
// 判断用户是否登录
|
||||||
|
if (!login) {
|
||||||
|
history.push(`/login?go_page=/ai/agents/${id}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已登录,检查Cookie中agent是否有值
|
||||||
|
const agentCookie = cookie.load('agent');
|
||||||
|
let currentTokenData = null;
|
||||||
|
|
||||||
|
if (!agentCookie) {
|
||||||
|
// Cookie中agent没有值,调用登录接口
|
||||||
|
const res = await agentLogin({
|
||||||
|
grant_type: 'password',
|
||||||
|
client_id: '4b25ca036879216a020a',
|
||||||
|
username: 'hnxjy',
|
||||||
|
password: '123456',
|
||||||
|
scope: 'profile'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res && res.data && res.data) {
|
||||||
|
const { access_token, expires_in } = res.data;
|
||||||
|
// 用当前时间 + expires_in(秒)计算过期时间
|
||||||
|
const expiryDate = new Date(Date.now() + (expires_in) * 1000);
|
||||||
|
|
||||||
|
// 将完整的token数据存储在agent Cookie中
|
||||||
|
currentTokenData = access_token;
|
||||||
|
cookie.save('agent', currentTokenData, { expires: expiryDate, path: '/' });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Cookie中有值,从Cookie获取保存的token数据
|
||||||
|
currentTokenData = agentCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取iframe URL(带上token参数)
|
||||||
|
const url = getIframeUrl(id, currentTokenData);
|
||||||
|
setIframeUrl(url);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('检查登录状态失败:', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 构建iframe URL,将token作为URL参数传递
|
||||||
|
const getIframeUrl = (agentId, accessToken) => {
|
||||||
|
if (!httpUrl || !agentId) return '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const urlObj = new URL(httpUrl);
|
||||||
|
const baseOrigin = `${urlObj.protocol}//${urlObj.host}`;
|
||||||
|
let url = `${baseOrigin}/chat/${agentId}`;
|
||||||
|
|
||||||
|
// 如果有token,添加到URL参数中
|
||||||
|
if (accessToken) {
|
||||||
|
const separator = url.includes('?') ? '&' : '?';
|
||||||
|
url += `${separator}token=${encodeURIComponent(accessToken)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
} catch (e) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="agent-container" style={{ width: '100%', height: '100vh', overflow: 'hidden' }}>
|
||||||
|
{iframeUrl ? (
|
||||||
|
<iframe
|
||||||
|
src={iframeUrl}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
border: 'none',
|
||||||
|
}}
|
||||||
|
allow="clipboard-read; clipboard-write"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
|
||||||
|
加载中...
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(Agent);
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
import { message , notification } from 'antd';
|
||||||
|
import cookie from 'react-cookies';
|
||||||
|
|
||||||
|
function beforeFetch(actionUrl){
|
||||||
|
if (window.location.href.indexOf('localhost') < 0) {
|
||||||
|
axios.defaults.withCredentials = true;
|
||||||
|
}
|
||||||
|
const config = {
|
||||||
|
// headers:{Authorization:"Bearer eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjo0NCwidXNlcl9rZXkiOiI3NWY3MmJmYmE2NGU4N2U3NWVjNWMwZDk2OThkMDFiN2EyODE0YjYwIiwidXNlcm5hbWUiOiJpbm5vdiJ9.IviAyZQjPFc4rT3ejAKfJYx3_QgS78RCKHx1XS-A4uI_mrc7_l6wK76HVIoPCEvP0Qimzyc6dpeVW4cE2fILZw"},
|
||||||
|
baseURL: actionUrl,
|
||||||
|
timeout: 1800000, // 请求超时时间
|
||||||
|
}
|
||||||
|
|
||||||
|
const service = axios.create(config);
|
||||||
|
|
||||||
|
service.interceptors.request.use(request => {
|
||||||
|
// let deptId = sessionStorage.getItem('deptId')
|
||||||
|
// request.headers.Authorization = cookie.load('autologin_trustie')
|
||||||
|
// if (deptId) {
|
||||||
|
// // 用于权限区分
|
||||||
|
// request.headers['Dept-Id'] = deptId
|
||||||
|
// }
|
||||||
|
return request
|
||||||
|
})
|
||||||
|
|
||||||
|
service.interceptors.response.use(
|
||||||
|
response => {
|
||||||
|
const res = response||{};
|
||||||
|
if(res && res.data && res.data.code === 404){
|
||||||
|
message.error("错误链接!");
|
||||||
|
window.location.href = '/nopage';
|
||||||
|
return Promise.reject('error');
|
||||||
|
}else if(res && res.data && res.data.code === 500){
|
||||||
|
message.error(res.data.msg);
|
||||||
|
return Promise.reject('error');
|
||||||
|
}else{
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log(error);
|
||||||
|
// notification.open({
|
||||||
|
// message: "提示",
|
||||||
|
// description: error.message,
|
||||||
|
// });
|
||||||
|
// return Promise.reject(error);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
let settings = localStorage.chromesetting&& localStorage.chromesetting !=="undefined"&& JSON.parse(localStorage.chromesetting);
|
||||||
|
// 根据当前IP判断使用哪个zone配置
|
||||||
|
const isSpecificIP = window.location.hostname.startsWith('27.');
|
||||||
|
// let actionUrl = settings && (isSpecificIP ? settings.common.zone : settings.common.zone_local) + '/zoneAdmin/api';
|
||||||
|
|
||||||
|
let actionUrl = settings && settings.common && settings.common.agent
|
||||||
|
const service = beforeFetch(actionUrl);
|
||||||
|
export const httpUrl = actionUrl;
|
||||||
|
export default service;
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
import { message , notification } from 'antd';
|
||||||
|
import cookie from 'react-cookies';
|
||||||
|
|
||||||
|
function beforeFetch(actionUrl){
|
||||||
|
if (window.location.href.indexOf('localhost') < 0) {
|
||||||
|
axios.defaults.withCredentials = true;
|
||||||
|
}
|
||||||
|
const config = {
|
||||||
|
// headers:{Authorization:"Bearer eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjo0NCwidXNlcl9rZXkiOiI3NWY3MmJmYmE2NGU4N2U3NWVjNWMwZDk2OThkMDFiN2EyODE0YjYwIiwidXNlcm5hbWUiOiJpbm5vdiJ9.IviAyZQjPFc4rT3ejAKfJYx3_QgS78RCKHx1XS-A4uI_mrc7_l6wK76HVIoPCEvP0Qimzyc6dpeVW4cE2fILZw"},
|
||||||
|
baseURL: actionUrl,
|
||||||
|
timeout: 1800000, // 请求超时时间
|
||||||
|
}
|
||||||
|
|
||||||
|
const service = axios.create(config);
|
||||||
|
|
||||||
|
service.interceptors.request.use(request => {
|
||||||
|
// let deptId = sessionStorage.getItem('deptId')
|
||||||
|
// request.headers.Authorization = cookie.load('autologin_trustie')
|
||||||
|
// if (deptId) {
|
||||||
|
// // 用于权限区分
|
||||||
|
// request.headers['Dept-Id'] = deptId
|
||||||
|
// }
|
||||||
|
return request
|
||||||
|
})
|
||||||
|
|
||||||
|
service.interceptors.response.use(
|
||||||
|
response => {
|
||||||
|
const res = response||{};
|
||||||
|
if(res && res.data && res.data.code === 404){
|
||||||
|
message.error("错误链接!");
|
||||||
|
window.location.href = '/nopage';
|
||||||
|
return Promise.reject('error');
|
||||||
|
}else if(res && res.data && res.data.code === 500){
|
||||||
|
message.error(res.data.msg);
|
||||||
|
return Promise.reject('error');
|
||||||
|
}else{
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log(error);
|
||||||
|
// notification.open({
|
||||||
|
// message: "提示",
|
||||||
|
// description: error.message,
|
||||||
|
// });
|
||||||
|
// return Promise.reject(error);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
let settings = localStorage.chromesetting&& localStorage.chromesetting !=="undefined"&& JSON.parse(localStorage.chromesetting);
|
||||||
|
// 根据当前IP判断使用哪个zone配置
|
||||||
|
const isSpecificIP = window.location.hostname.startsWith('27.');
|
||||||
|
// let actionUrl = settings && (isSpecificIP ? settings.common.zone : settings.common.zone_local) + '/zoneAdmin/api';
|
||||||
|
|
||||||
|
let actionUrl = settings && settings.common && settings.common.agent_login;
|
||||||
|
|
||||||
|
const service = beforeFetch(actionUrl);
|
||||||
|
export const httpUrl = actionUrl;
|
||||||
|
export default service;
|
||||||
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 113 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
|
@ -25,6 +25,10 @@ const MyResources = Loadable({
|
||||||
loader: () => import("./my-resources"),
|
loader: () => import("./my-resources"),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
const Agents = Loadable({
|
||||||
|
loader: () => import("./detail/agent"),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
|
||||||
function AI(props) {
|
function AI(props) {
|
||||||
const { current_user: { login } } = props
|
const { current_user: { login } } = props
|
||||||
|
|
@ -56,6 +60,12 @@ function AI(props) {
|
||||||
|
|
||||||
return <div className="ai_resouce_page">
|
return <div className="ai_resouce_page">
|
||||||
<Switch {...props}>
|
<Switch {...props}>
|
||||||
|
<Route
|
||||||
|
path="/ai/agents/:id"
|
||||||
|
render={(p) => (
|
||||||
|
<Agents {...props} {...p} aiZoneInfo={aiZoneInfo} roleByZone={roleByZone}/>
|
||||||
|
)}
|
||||||
|
></Route>
|
||||||
<Route
|
<Route
|
||||||
path="/ai/:type/my"
|
path="/ai/:type/my"
|
||||||
render={(p) => (
|
render={(p) => (
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,126 @@
|
||||||
import { Fragment, useEffect, useState } from "react";
|
import { Fragment, useEffect, useState } from "react";
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
|
// 预置智能体 Mock 数据(从预置12个智能体.md 提炼)
|
||||||
|
const agentMockCate = [
|
||||||
|
{ id: "work", name: "工作" },
|
||||||
|
{ id: "study", name: "学习" },
|
||||||
|
{ id: "writing", name: "写作" },
|
||||||
|
{ id: "programming", name: "编程" },
|
||||||
|
{ id: "life", name: "生活" },
|
||||||
|
{ id: "health", name: "健康" }
|
||||||
|
];
|
||||||
|
|
||||||
|
const agentMockList = [
|
||||||
|
// 工作类
|
||||||
|
{
|
||||||
|
id: "meeting-minutes",
|
||||||
|
name: "会议纪要助手",
|
||||||
|
image: "",
|
||||||
|
desc: "专注于会议纪要的整理与提炼,帮助用户快速生成结构清晰、重点突出的会议纪要。",
|
||||||
|
cate: "work"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "project-management",
|
||||||
|
name: "项目管理助手",
|
||||||
|
image: "",
|
||||||
|
desc: "协助项目管理者进行任务拆解、进度跟踪、风险识别与资源协调,提升项目管理效率。",
|
||||||
|
cate: "work"
|
||||||
|
},
|
||||||
|
// 学习类
|
||||||
|
{
|
||||||
|
id: "knowledge-combination",
|
||||||
|
name: "知识梳理助手",
|
||||||
|
image: "",
|
||||||
|
desc: "帮助用户将零散的知识点系统化整理,构建知识框架,提升学习效率与记忆效果。",
|
||||||
|
cate: "study"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "training-planning",
|
||||||
|
name: "培训规划助手",
|
||||||
|
image: "",
|
||||||
|
desc: "根据岗位需求与员工能力现状,协助制定科学合理的培训计划与课程体系。",
|
||||||
|
cate: "study"
|
||||||
|
},
|
||||||
|
// 写作类
|
||||||
|
{
|
||||||
|
id: "official-writing",
|
||||||
|
name: "公文写作助手",
|
||||||
|
image: "",
|
||||||
|
desc: "专注于各类公文的撰写与润色,确保格式规范、用语准确、逻辑严密。",
|
||||||
|
cate: "writing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "report-writing",
|
||||||
|
name: "报告撰写助手",
|
||||||
|
image: "",
|
||||||
|
desc: "协助用户撰写各类工作报告、调研报告、总结报告,提升报告的专业性与可读性。",
|
||||||
|
cate: "writing"
|
||||||
|
},
|
||||||
|
// 编程类
|
||||||
|
{
|
||||||
|
id: "code-review",
|
||||||
|
name: "代码审查助手",
|
||||||
|
image: "",
|
||||||
|
desc: "协助开发人员进行代码审查,发现潜在问题,提升代码质量与可维护性。",
|
||||||
|
cate: "programming"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "tech-documentation",
|
||||||
|
name: "技术文档助手",
|
||||||
|
image: "",
|
||||||
|
desc: "协助技术人员撰写 API 文档、系统设计文档、操作手册等技术文档,确保文档清晰准确。",
|
||||||
|
cate: "programming"
|
||||||
|
},
|
||||||
|
// 生活类
|
||||||
|
{
|
||||||
|
id: "schedule-planning",
|
||||||
|
name: "日程规划助手",
|
||||||
|
image: "",
|
||||||
|
desc: "协助用户合理安排日常工作与生活日程,提升时间利用效率,平衡工作与生活。",
|
||||||
|
cate: "life"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "meeting-arrangement",
|
||||||
|
name: "会议安排助手",
|
||||||
|
image: "",
|
||||||
|
desc: "协助用户高效安排会议时间、协调与会人员、准备会议材料,减少会议组织成本。",
|
||||||
|
cate: "life"
|
||||||
|
},
|
||||||
|
// 健康类
|
||||||
|
{
|
||||||
|
id: "schedule-management",
|
||||||
|
name: "作息管理助手",
|
||||||
|
image: "",
|
||||||
|
desc: "协助用户建立科学的作息规律,提供睡眠改善建议与作息调整方案,促进身心健康。",
|
||||||
|
cate: "health"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "exercise-planning",
|
||||||
|
name: "运动计划助手",
|
||||||
|
image: "",
|
||||||
|
desc: "根据用户的身体状况与运动目标,协助制定科学合理的运动计划,促进身体健康。",
|
||||||
|
cate: "health"
|
||||||
|
}
|
||||||
|
];
|
||||||
import { aiResouceType, aiResouceTypeKey, iconByCateIndex, iconByCateName } from "../static";
|
import { aiResouceType, aiResouceTypeKey, iconByCateIndex, iconByCateName } from "../static";
|
||||||
import icon1 from '../image/icon1.png';
|
import icon1 from '../image/icon1.png';
|
||||||
import icon2 from '../image/icon2.png';
|
import icon2 from '../image/icon2.png';
|
||||||
import icon3 from '../image/icon3.png';
|
import icon3 from '../image/icon3.png';
|
||||||
import icon5 from '../image/icon5.png';
|
import icon5 from '../image/icon5.png';
|
||||||
import icon6 from '../image/icon6.png';
|
import icon6 from '../image/icon6.png';
|
||||||
import { Divider, Input, Pagination } from "antd";
|
import { Divider, Input, Pagination, Spin } from "antd";
|
||||||
import ActionItem from "../../factory/resource/components/ActionItem";
|
import ActionItem from "../../factory/resource/components/ActionItem";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { getAISourceList, getProjectsLists, getProjectsTypeLists, getSourceZoneList } from "../../forge/Information/api";
|
import { getAISourceList, getProjectsLists, getProjectsTypeLists, getSourceZoneList } from "../../forge/Information/api";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import Nodata from "../../forge/Nodata";
|
import Nodata from "../../forge/Nodata";
|
||||||
|
import { getAgentList, getAgentTypeList } from "../api";
|
||||||
|
import { httpUrl } from "../fetch";
|
||||||
|
|
||||||
function List(props) {
|
function List(props) {
|
||||||
const { match: { params }, history, aiZoneInfo, current_user } = props || {};
|
|
||||||
|
const { match: { params }, history, aiZoneInfo, current_user, showLoginDialog } = props || {};
|
||||||
const type = params.type || aiResouceType[0].key
|
const type = params.type || aiResouceType[0].key
|
||||||
const [activeCategory, setActiveCategory] = useState();
|
const [activeCategory, setActiveCategory] = useState();
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
|
|
@ -22,25 +128,58 @@ function List(props) {
|
||||||
const [cate, setCate] = useState([]);
|
const [cate, setCate] = useState([]);
|
||||||
const [list, setList] = useState();
|
const [list, setList] = useState();
|
||||||
const [search, setSearch] = useState();
|
const [search, setSearch] = useState();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const limit = 12;
|
||||||
const { id: aiZoneId } = aiZoneInfo || {}
|
const { id: aiZoneId } = aiZoneInfo || {}
|
||||||
const typeDetail = type && aiResouceType.find(i => i.key === type);
|
const aiTypeInList = [
|
||||||
|
...aiResouceType,
|
||||||
|
{ key: "agents", name: "智能体", icon: "icon-zhinengti", intro: "驱动行业数智化", desc: "矩阵覆盖全场景需求,极速响应精准输出,低成本释放 AI 算力,赋能每一项任务。", createIntro: "上传您的智能体文件" }
|
||||||
|
]
|
||||||
|
const typeDetail = type && aiTypeInList.find(i => i.key === type);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = `AI资源广场`;
|
document.title = `AI资源广场`;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// 获取分类列表:agents 类型不依赖 aiZoneId,单独处理避免重复请求
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setActiveCategory(undefined);
|
if (type === "agents") {
|
||||||
|
if(!httpUrl){
|
||||||
|
setCate(agentMockCate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getAgentTypeList().then(res => {
|
||||||
|
if (res && res.data && res.data.data) {
|
||||||
|
const data = res.data.data
|
||||||
|
setCate(data.map(item=>{
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
name: item.typeName,
|
||||||
|
id: item.typeKey
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [type])
|
||||||
|
|
||||||
|
// 其他类型需要 aiZoneId,当 aiZoneId 变化时获取分类
|
||||||
|
useEffect(() => {
|
||||||
|
if (type === "agents") return; // agents 类型已在上方的 useEffect 中处理
|
||||||
|
|
||||||
|
if (!aiZoneId) return;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "codes":
|
case "codes":
|
||||||
aiZoneId && getProjectsTypeLists(aiZoneId).then(res => {
|
getProjectsTypeLists(aiZoneId).then(res => {
|
||||||
if (res && res.data && res.data.rows) {
|
if (res && res.data && res.data.rows) {
|
||||||
setCate(res.data.rows);
|
setCate(res.data.rows);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
aiZoneId && getSourceZoneList(aiZoneId, {
|
getSourceZoneList(aiZoneId, {
|
||||||
domainCategory: aiResouceTypeKey[type]
|
domainCategory: aiResouceTypeKey[type]
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res && res.data && res.data.rows) {
|
if (res && res.data && res.data.rows) {
|
||||||
|
|
@ -52,22 +191,70 @@ function List(props) {
|
||||||
}, [type, aiZoneId])
|
}, [type, aiZoneId])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(!aiZoneId) return
|
if (type === "agents") {
|
||||||
|
setLoading(true);
|
||||||
|
if(!httpUrl){
|
||||||
|
let filteredList = [...agentMockList];
|
||||||
|
if (activeCategory) {
|
||||||
|
filteredList = filteredList.filter(item => item.cate === activeCategory);
|
||||||
|
}
|
||||||
|
if (search) {
|
||||||
|
filteredList = filteredList.filter(item =>
|
||||||
|
item.name.toLowerCase().includes(search.toLowerCase()) ||
|
||||||
|
item.desc.toLowerCase().includes(search.toLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const start = (page - 1) * limit;
|
||||||
|
setList(filteredList.slice(start, start + limit));
|
||||||
|
setTotal(filteredList.length);
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getAgentList({
|
||||||
|
page: page,
|
||||||
|
pageSize: limit,
|
||||||
|
search: search,
|
||||||
|
type: activeCategory
|
||||||
|
}).then(res => {
|
||||||
|
if (res && res.data && res.data.data) {
|
||||||
|
const data = res.data.data;
|
||||||
|
setList(data.pageData.map(row => {
|
||||||
|
const { botId, botCoverUrl, botName, botDesc } = row;
|
||||||
|
return {
|
||||||
|
id: botId,
|
||||||
|
name: botName,
|
||||||
|
image: botCoverUrl,
|
||||||
|
desc: botDesc,
|
||||||
|
}}
|
||||||
|
));
|
||||||
|
setTotal(data.totalCount);
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [type, activeCategory, page, search])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (type === "agents" || !aiZoneId) return
|
||||||
|
setLoading(true);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "codes":
|
case "codes":
|
||||||
getProjectsLists(aiZoneId, {
|
getProjectsLists(aiZoneId, {
|
||||||
pageNum: page,
|
pageNum: page,
|
||||||
pageSize: 10,
|
pageSize: limit,
|
||||||
projectTypeId: activeCategory,
|
projectTypeId: activeCategory,
|
||||||
name: search
|
name: search
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res && res.data && res.data.rows) {
|
if (res && res.data && res.data.rows) {
|
||||||
setList(res.data.rows.map(row => {
|
setList(res.data.rows.map(row => {
|
||||||
const { projectProperties, id } = row;
|
const { projectProperties, id } = row;
|
||||||
|
const imageUrl = projectProperties.authorImageUrl.split(':4000/') && projectProperties.authorImageUrl.split(':4000/')[1]
|
||||||
|
const authorImageUrl = imageUrl ? `${window.location.origin}/${imageUrl}` : projectProperties.authorImageUrl
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
name: projectProperties.fromOwner === "AI-RESOURCE" ? projectProperties.name.split("/").pop() : projectProperties.name,
|
name: projectProperties.fromOwner === "AI-RESOURCE" ? projectProperties.name.split("/").pop() : projectProperties.name,
|
||||||
image: projectProperties.authorImageUrl,
|
image: authorImageUrl,
|
||||||
isNew: false,
|
isNew: false,
|
||||||
url: projectProperties.fullName,
|
url: projectProperties.fullName,
|
||||||
desc: projectProperties.description,
|
desc: projectProperties.description,
|
||||||
|
|
@ -79,13 +266,15 @@ function List(props) {
|
||||||
}))
|
}))
|
||||||
setTotal(res.data.total)
|
setTotal(res.data.total)
|
||||||
}
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
setLoading(false);
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
getAISourceList(aiZoneId, {
|
getAISourceList(aiZoneId, {
|
||||||
domainId: activeCategory,
|
domainId: activeCategory,
|
||||||
pageNum: page,
|
pageNum: page,
|
||||||
pageSize: 10,
|
pageSize: limit,
|
||||||
name: search,
|
name: search,
|
||||||
resourceCategory: aiResouceTypeKey[type]
|
resourceCategory: aiResouceTypeKey[type]
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
|
|
@ -105,6 +294,8 @@ function List(props) {
|
||||||
}))
|
}))
|
||||||
setTotal(res.data.total)
|
setTotal(res.data.total)
|
||||||
}
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
setLoading(false);
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -147,9 +338,10 @@ function List(props) {
|
||||||
面向开发者提供可信、合规、高效的 AI 资产分发中心。涵盖百亿级模型权重库、千万量级专业数据集、托管代码仓及<br />智能skill中心。实现从资源检索、安全审计到业务集成的一体化研发生态。
|
面向开发者提供可信、合规、高效的 AI 资产分发中心。涵盖百亿级模型权重库、千万量级专业数据集、托管代码仓及<br />智能skill中心。实现从资源检索、安全审计到业务集成的一体化研发生态。
|
||||||
</div>
|
</div>
|
||||||
<div className="ai_home_banner_tabs">
|
<div className="ai_home_banner_tabs">
|
||||||
{aiResouceType.map((item) => (
|
{aiTypeInList.map((item) => (
|
||||||
<Link
|
<Link
|
||||||
to={`/ai/${item.key}`}
|
to={`/ai/${item.key}`}
|
||||||
|
onClick={()=>{setActiveCategory(undefined); setList([])}}
|
||||||
key={item.key}
|
key={item.key}
|
||||||
className={`ai_home_banner_tab font-15 pointer ${type === item.key ? 'active' : ''}`}
|
className={`ai_home_banner_tab font-15 pointer ${type === item.key ? 'active' : ''}`}
|
||||||
>
|
>
|
||||||
|
|
@ -174,7 +366,7 @@ function List(props) {
|
||||||
className={`ai_home_sidebar_item mb30 ${!activeCategory ? 'active' : ''}`}
|
className={`ai_home_sidebar_item mb30 ${!activeCategory ? 'active' : ''}`}
|
||||||
onClick={() => setActiveCategory(undefined)}
|
onClick={() => setActiveCategory(undefined)}
|
||||||
>
|
>
|
||||||
<i className={`${!activeCategory ? "iconfont icon-remenmoxing-2" : "iconfont-color icon-colorremenmoxing-1"} font-14 mr10`}></i>
|
{type !== "agents" && <i className={`${!activeCategory ? "iconfont icon-remenmoxing-2" : "iconfont-color icon-colorremenmoxing-1"} font-14 mr10`}></i>}
|
||||||
全部
|
全部
|
||||||
</li>
|
</li>
|
||||||
{cate.map((category, index) => {
|
{cate.map((category, index) => {
|
||||||
|
|
@ -184,7 +376,7 @@ function List(props) {
|
||||||
className={`ai_home_sidebar_item mb30 ${activeCategory === category.id ? 'active' : ''}`}
|
className={`ai_home_sidebar_item mb30 ${activeCategory === category.id ? 'active' : ''}`}
|
||||||
onClick={() => setActiveCategory(category.id)}
|
onClick={() => setActiveCategory(category.id)}
|
||||||
>
|
>
|
||||||
<i className={`${icons[Number(activeCategory === category.id)]} font-14 mr10`}></i>
|
{type !== "agents" && <i className={`${icons[Number(activeCategory === category.id)]} font-14 mr10`}></i>}
|
||||||
{category.name}
|
{category.name}
|
||||||
</li>
|
</li>
|
||||||
})}
|
})}
|
||||||
|
|
@ -196,54 +388,65 @@ function List(props) {
|
||||||
{/* 搜索和操作栏 */}
|
{/* 搜索和操作栏 */}
|
||||||
<div className="ai_home_toolbar">
|
<div className="ai_home_toolbar">
|
||||||
<Input.Search className="ai_home_search flex1" placeholder={`输入关键词搜索您想要的${typeDetail.name}(共${total}个)`} enterButton={<i className="iconfont icon-sousuo5 font-15"></i>} onSearch={(value) => { setPage(1); setSearch(value) }} />
|
<Input.Search className="ai_home_search flex1" placeholder={`输入关键词搜索您想要的${typeDetail.name}(共${total}个)`} enterButton={<i className="iconfont icon-sousuo5 font-15"></i>} onSearch={(value) => { setPage(1); setSearch(value) }} />
|
||||||
{current_user && current_user.login && <div className="">
|
{current_user && current_user.login && type !== "agents" && <div className="">
|
||||||
<a className="btn-outline font-bd mr10" href={`/ai/${type}/create`}> 新建 </a>
|
<a className="btn-outline font-bd mr10" href={`/ai/${type}/create`}> 新建 </a>
|
||||||
<a className="btn-outline font-bd ai_home_action_my" href={`/ai/${type}/my`}>我的{typeDetail.name}<i className="iconfont icon-arrright ml5"></i></a>
|
<a className="btn-outline font-bd ai_home_action_my" href={`/ai/${type}/my`}>我的{typeDetail.name}<i className="iconfont icon-arrright ml5"></i></a>
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 模型列表 */}
|
{/* 模型列表 */}
|
||||||
{list && !!list.length ? <div className={`ai_home_list ${type}_pattern`}>
|
<Spin spinning={loading}>
|
||||||
{list.map((model) => (
|
{list && !!list.length ? <div className={`ai_home_list ${type}_pattern`}>
|
||||||
<ActionItem key={model.id} className="ai_home_card" padding="1px" borderRadius="12px">
|
{list.map((model) => (
|
||||||
<div>
|
<ActionItem key={`${type}-${model.id}`} className="ai_home_card" padding="1px" borderRadius="12px">
|
||||||
<div className="df-center">
|
{type === "agents" ? <div>
|
||||||
{model.image && <img src={model.image} width={38} className="mr15" style={{ borderRadius: '8px' }} />}
|
<div className="df">
|
||||||
{model.icon && type !== "skills" && <i className={`iconfont ${model.icon} font-30 mr15`}></i>}
|
<img src={model.image ? model.image : require(`../image/${model.id}.png`).default} width={46} className="mr15" style={{ borderRadius: '8px' }} />
|
||||||
<div className="flex1 task-hide mr10" style={{ minHeight: '40px' }}>
|
<span className="font-18 font-bd task-hide">{model.name}</span>
|
||||||
<div className="font-16 font-bd">{model.name}{model.isNew && <i className="iconfont-color icon-colora-zuixin1 font-20 ml10"></i>}</div>
|
|
||||||
{model.desc && <div className="color3f4">{model.desc}</div>}
|
|
||||||
</div>
|
</div>
|
||||||
<a className="btn-black arrowRight" href={type === "codes" ? `/${model.url}` : `/ai/${type}/${model.id}`}>查看<i className="iconfont icon-arrright"></i></a>
|
<div className="color3f4 mt15 task-hide-2" style={{minHeight: 56}}>{model.desc}</div>
|
||||||
</div>
|
<div className="btn-Box">
|
||||||
{type === "skills" ? <div className="df-center skills_bottom color828">
|
{httpUrl ? <a className="btn-black" href={`/ai/${type}/${model.id}`} onClick={(e) => { if (!current_user || !current_user.login) { e.preventDefault(); e.stopPropagation(); showLoginDialog(); } }}>立即使用</a> : <a className="unClickBtn">暂未开放</a>}
|
||||||
<img src={icon6} width={18} />
|
</div>
|
||||||
<span className="mrat ml10 color091 font-13">{model.domainName}</span>
|
</div>:<div>
|
||||||
{aiCard(model)}
|
<div className="df-center">
|
||||||
</div> : <Fragment>
|
{model.image && <img src={model.image} width={38} className="mr15" style={{ borderRadius: '8px' }} />}
|
||||||
{type === "codes" ? <div className="mt15"></div> : <Divider dashed />}
|
{model.icon && type !== "skills" && <i className={`iconfont ${model.icon} font-30 mr15`}></i>}
|
||||||
<div className="df-center color828">
|
<div className="flex1 task-hide mr10" style={{minHeight: '40px'}}>
|
||||||
|
<div className="font-16 font-bd">{model.name}{model.isNew && <i className="iconfont-color icon-colora-zuixin1 font-20 ml10"></i>}</div>
|
||||||
|
{model.desc && <div className="color3f4">{model.desc}</div>}
|
||||||
|
</div>
|
||||||
|
<a className="btn-black arrowRight" href={type === "codes" ? `/${model.url}` : `/ai/${type}/${model.id}`}>查看<i className="iconfont icon-arrright"></i></a>
|
||||||
|
</div>
|
||||||
|
{type === "skills" ? <div className="df-center skills_bottom color828">
|
||||||
|
<img src={icon6} width={18} />
|
||||||
|
<span className="mrat ml10 color091 font-13">{model.domainName}</span>
|
||||||
{aiCard(model)}
|
{aiCard(model)}
|
||||||
{type === "codes" ? <div className="df-center mlat">
|
</div> : <Fragment>
|
||||||
{model.language && !!model.language.length && <Fragment>
|
{type === "codes" ? <div className="mt15"></div> : <Divider dashed />}
|
||||||
<img src={icon5} className="mr8 mt1" width={18} />
|
<div className="df-center color828">
|
||||||
{model.language.map((topic, index) => {
|
{aiCard(model)}
|
||||||
return <Fragment>
|
{type === "codes" ? <div className="df-center mlat">
|
||||||
<span className="color091">{topic}</span>
|
{model.language && !!model.language.length && <Fragment>
|
||||||
{index < model.language.length - 1 && <Divider type="vertical" style={{ height: '7px' }} className="mt5" />}
|
<img src={icon5} className="mr8 mt1" width={18} />
|
||||||
</Fragment>
|
{model.language.map((topic, index) => {
|
||||||
})}
|
return <Fragment>
|
||||||
</Fragment>}
|
<span className="color091">{topic}</span>
|
||||||
</div> : <span className="ai_home_card_tag mlat">{model.domainName}</span>}
|
{index < model.language.length - 1 && <Divider type="vertical" style={{ height: '7px' }} className="mt5" />}
|
||||||
</div>
|
</Fragment>
|
||||||
</Fragment>}
|
})}
|
||||||
</div>
|
</Fragment>}
|
||||||
</ActionItem>
|
</div> : <span className="ai_home_card_tag mlat">{model.domainName}</span>}
|
||||||
))}
|
</div>
|
||||||
</div> : <div className="pt80"><Nodata _html="暂无数据"/></div>}
|
</Fragment>}
|
||||||
|
</div>}
|
||||||
|
</ActionItem>
|
||||||
|
))}
|
||||||
|
</div> : <div className="pt80"><Nodata _html="暂无数据"/></div>}
|
||||||
|
</Spin>
|
||||||
|
|
||||||
{/* 分页 */}
|
{/* 分页 */}
|
||||||
<Pagination className="edu-txt-right ai_list_Pagination mb70 black_active_Pagination" current={page} onChange={(p) => { setPage(p) }} pageSize={10} total={total} showQuickJumper hideOnSinglePage />
|
<Pagination className="edu-txt-right ai_list_Pagination mb70 black_active_Pagination" current={page} onChange={(p) => { setPage(p) }} pageSize={limit} total={total} showQuickJumper hideOnSinglePage />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -222,6 +222,42 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.agents_pattern{
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
.ai_home_card{
|
||||||
|
position: relative;
|
||||||
|
.action-item_content{
|
||||||
|
padding: 27px 36px;
|
||||||
|
background-image: url('../image/card_bk3.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
.btn-Box{
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 17px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btn-Box{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.btn-black{
|
||||||
|
padding: 4px 48px 4px 48px;
|
||||||
|
}
|
||||||
|
.unClickBtn{
|
||||||
|
padding: 8px 47px 8px 47px;
|
||||||
|
background:#9ea2a8;
|
||||||
|
border-radius:10px;
|
||||||
|
color:#ffffff;
|
||||||
|
font-size:15px;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 卡片
|
// 卡片
|
||||||
.ai_home_card {
|
.ai_home_card {
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,8 @@ function Index(props) {
|
||||||
<div className="tools-info">
|
<div className="tools-info">
|
||||||
<div>
|
<div>
|
||||||
<span>{detail.downloadCount}</span>
|
<span>{detail.downloadCount}</span>
|
||||||
<span>下载量{admin && <Button className='downloadUser' onClick={handleOpenDownloadUserModal}>查看下载用户</Button>}</span>
|
<span>下载量</span>
|
||||||
|
{/* {admin && <Button className='downloadUser' onClick={handleOpenDownloadUserModal}>查看下载用户</Button>} */}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>{totalFileSize || (detail.fileList && detail.fileList[0] ? detail.fileList[0].fileSizeInfo : 0)}</span>
|
<span>{totalFileSize || (detail.fileList && detail.fileList[0] ? detail.fileList[0].fileSizeInfo : 0)}</span>
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,13 @@ function Index(props) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 按 createTime 降序排序,最新的版本排在最上面
|
||||||
|
historyVersions.sort((a, b) => {
|
||||||
|
const timeA = a.createTime ? new Date(a.createTime).getTime() : 0;
|
||||||
|
const timeB = b.createTime ? new Date(b.createTime).getTime() : 0;
|
||||||
|
return timeB - timeA;
|
||||||
|
});
|
||||||
|
|
||||||
return { currentVersions, historyVersions };
|
return { currentVersions, historyVersions };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ class NewHeader extends Component {
|
||||||
//退出账号时清除登录页面的下次自动登录(用户再次打开登录页面时下次自动登录框不勾选)
|
//退出账号时清除登录页面的下次自动登录(用户再次打开登录页面时下次自动登录框不勾选)
|
||||||
cookie.remove("autologin");
|
cookie.remove("autologin");
|
||||||
cookie.remove("login");
|
cookie.remove("login");
|
||||||
|
cookie.remove("agent");
|
||||||
//退出账号
|
//退出账号
|
||||||
var url = `/accounts/logout.json`;
|
var url = `/accounts/logout.json`;
|
||||||
axios.get((url)).then((result) => {
|
axios.get((url)).then((result) => {
|
||||||
|
|
@ -349,7 +350,7 @@ class NewHeader extends Component {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "开源软件仓库",
|
"name": "开源软件仓库",
|
||||||
"link": "/explore",
|
"link": "/ossRepo",
|
||||||
"index": "2",
|
"index": "2",
|
||||||
"hidden": false
|
"hidden": false
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class Index extends Component {
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/explore"
|
path="/ossRepo"
|
||||||
render={(props) => (
|
render={(props) => (
|
||||||
<ProjectHome {...this.props} {...props} />
|
<ProjectHome {...this.props} {...props} />
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -650,4 +650,13 @@ export function getAIProjectStatistics(params){
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params
|
params
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**AI智能体登录***/
|
||||||
|
export function aiAgentLogin(data) {
|
||||||
|
return fetch({
|
||||||
|
url: `/auth/aiAgent/login`,
|
||||||
|
method: 'POST',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,6 @@ import { Base64 } from 'js-base64';
|
||||||
import { setProject, setProjectDetail, setProjectEntries, setProjectMenuList, setProjectReadMe } from '../../redux/actions/server';
|
import { setProject, setProjectDetail, setProjectEntries, setProjectMenuList, setProjectReadMe } from '../../redux/actions/server';
|
||||||
import actions from '../../redux/actions';
|
import actions from '../../redux/actions';
|
||||||
import types from '../../redux/actions/actionTypes'
|
import types from '../../redux/actions/actionTypes'
|
||||||
import { getProjectFunc, getProjectDetailFunc } from '../../services/project'
|
|
||||||
import '../css/index.scss'
|
import '../css/index.scss'
|
||||||
import './list.scss';
|
import './list.scss';
|
||||||
import '../../modules/courses/css/Courses.css'
|
import '../../modules/courses/css/Courses.css'
|
||||||
|
|
@ -252,7 +251,7 @@ class Detail extends Component {
|
||||||
let propsParam = this.props.match.params;
|
let propsParam = this.props.match.params;
|
||||||
if (prevState && this.props && (prevParam.projectsId !== propsParam.projectsId || prevParam.owner !== propsParam.owner)) {
|
if (prevState && this.props && (prevParam.projectsId !== propsParam.projectsId || prevParam.owner !== propsParam.owner)) {
|
||||||
const { projectsId, owner } = this.props.match.params;
|
const { projectsId, owner } = this.props.match.params;
|
||||||
const data = await getProjectFunc(owner, projectsId);
|
const data = await this.getProjectFunc(owner, projectsId);
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
this.getProject(data.data)
|
this.getProject(data.data)
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +275,7 @@ class Detail extends Component {
|
||||||
async componentWillMount() {
|
async componentWillMount() {
|
||||||
const { projectsId, owner } = this.props.match.params;
|
const { projectsId, owner } = this.props.match.params;
|
||||||
if (!this.props.projectBase) {
|
if (!this.props.projectBase) {
|
||||||
const data = await getProjectFunc(owner, projectsId);
|
const data = await this.getProjectFunc(owner, projectsId);
|
||||||
if (data && data.data) {
|
if (data && data.data) {
|
||||||
this.getProject(data.data)
|
this.getProject(data.data)
|
||||||
}
|
}
|
||||||
|
|
@ -314,17 +313,11 @@ class Detail extends Component {
|
||||||
mirror_status:data.mirror_status || 0
|
mirror_status:data.mirror_status || 0
|
||||||
})
|
})
|
||||||
this.getBanner(this.props.projectMenu)
|
this.getBanner(this.props.projectMenu)
|
||||||
let projectdata
|
|
||||||
if (this.props.defaultDetail) {
|
if (this.props.defaultDetail) {
|
||||||
projectdata = this.props.defaultDetail
|
projectdata = this.props.defaultDetail
|
||||||
} else {
|
|
||||||
const res = await getProjectDetailFunc(owner, projectsId, !window.location.host);
|
|
||||||
if (res && res.status === 200) {
|
|
||||||
projectdata = res.data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (projectdata) {
|
|
||||||
this.getDetail(projectdata)
|
this.getDetail(projectdata)
|
||||||
|
} else {
|
||||||
|
this.getDetail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -468,6 +461,11 @@ class Detail extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProjectFunc = async (owner, projectsId)=>{
|
||||||
|
const url = `/${owner}/${projectsId}/simple.json`;
|
||||||
|
return axios.get(url);
|
||||||
|
}
|
||||||
|
|
||||||
// 获取动态导航栏菜单
|
// 获取动态导航栏菜单
|
||||||
async getBanner(data) {
|
async getBanner(data) {
|
||||||
const { projectsId, owner } = this.props.match.params;
|
const { projectsId, owner } = this.props.match.params;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
|
||||||
|
import loadingGIf from "./Images/loading.gif";
|
||||||
|
function OssRepo(props) {
|
||||||
|
const {current_user, mygetHelmetapi} = props;
|
||||||
|
const {admin, user_id} = current_user || {}
|
||||||
|
const {common} = mygetHelmetapi || {};
|
||||||
|
const {ossRepo="http://27.122.114.160:3001"} = common || {};
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
document.title = '开源软件仓库';
|
||||||
|
// document.body.style.background = '#fff';
|
||||||
|
return () => {
|
||||||
|
document.body.style.background = '';
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const url = `${ossRepo}/?uid=${user_id === 2 ? undefined : user_id}`
|
||||||
|
// const url = "http://localhost:3007/"
|
||||||
|
|
||||||
|
return <div className="" style={{border: "none"}}>
|
||||||
|
{loading && <div className="center" style={{minHeight: '60vh', marginTop: '30vh'}}>
|
||||||
|
<img src={loadingGIf} width={250}/>
|
||||||
|
<div className="font-16" style={{position: 'relative', top: '-40px', color: '#091221', opacity: '0.6'}}>加载中,请耐心等待</div>
|
||||||
|
</div>}
|
||||||
|
<iframe title={`ossRepoIframe`} src={url} id={`ossRepoIframe`} frameBorder="0" name={`ossRepoIframe`} width="100%" style={{height: '100vh', border: 'none'}} onLoad={()=>{setLoading(false)}}></iframe>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TPMIndexHOC(OssRepo);
|
||||||
|
|
@ -124,7 +124,8 @@ function ProjectHomePage(props) {
|
||||||
page: page,
|
page: page,
|
||||||
topic_id: topicId,
|
topic_id: topicId,
|
||||||
sort_by: cateID ? undefined : "praises_count",
|
sort_by: cateID ? undefined : "praises_count",
|
||||||
language_id: undefined
|
language_id: undefined,
|
||||||
|
exclude_forked: true
|
||||||
};
|
};
|
||||||
if (cateID === 39 && topicId) {
|
if (cateID === 39 && topicId) {
|
||||||
// 三方组件,topicId要作为language_id参数进行查询,查询maven、python、npm的语言仓库列表
|
// 三方组件,topicId要作为language_id参数进行查询,查询maven、python、npm的语言仓库列表
|
||||||
|
|
|
||||||
|
|
@ -123,4 +123,11 @@ export function deleteUserForums(id,is_apply) {
|
||||||
is_apply
|
is_apply
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getForumHead(id) {
|
||||||
|
return fetch({
|
||||||
|
url: `/api/memos/forum_memos_head/${id}.json`,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -154,8 +154,6 @@ function detail(props) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}}>{memo.is_fine ? "取消推荐" : "推荐"}</a>
|
}}>{memo.is_fine ? "取消推荐" : "推荐"}</a>
|
||||||
|
|
||||||
<a onClick={()=>{setVisible(1)}}>删除</a>
|
|
||||||
</Fragment>}
|
</Fragment>}
|
||||||
|
|
||||||
{(memo.is_current_user || banned_permission) && <Fragment>
|
{(memo.is_current_user || banned_permission) && <Fragment>
|
||||||
|
|
@ -167,6 +165,8 @@ function detail(props) {
|
||||||
setVisible(apply_destroy ? 3 : 2)
|
setVisible(apply_destroy ? 3 : 2)
|
||||||
}}>{apply_destroy ? "撤销申请" : "申请删帖"}</a>
|
}}>{apply_destroy ? "撤销申请" : "申请删帖"}</a>
|
||||||
</Fragment>}
|
</Fragment>}
|
||||||
|
|
||||||
|
{banned_permission && <a onClick={()=>{setVisible(1)}}>删除</a>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { Divider, Form, Input, Cascader, Select, Breadcrumb, Upload, Button, Ico
|
||||||
import RichEditor from '../../forge/Component/RichEditor';
|
import RichEditor from '../../forge/Component/RichEditor';
|
||||||
import UploadImage from '../../forge/Team/Component/UploadImage';
|
import UploadImage from '../../forge/Team/Component/UploadImage';
|
||||||
import { httpUrl } from "../fetch";
|
import { httpUrl } from "../fetch";
|
||||||
|
import cookie from 'react-cookies';
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
function EditForum(props) {
|
function EditForum(props) {
|
||||||
|
|
@ -198,7 +199,7 @@ function EditForum(props) {
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="上传附件">
|
<Form.Item label="上传附件">
|
||||||
{getFieldDecorator('attachments')(
|
{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">
|
<p className="ant-upload-drag-icon">
|
||||||
<Icon type="inbox" />
|
<Icon type="inbox" />
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -210,7 +211,7 @@ function EditForum(props) {
|
||||||
<Button
|
<Button
|
||||||
className="mr20"
|
className="mr20"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
history.push("/forums");
|
history.go(-1);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
返回
|
返回
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 771 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1000 B |
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 596 KiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 707 KiB |
|
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
|
@ -15,6 +15,10 @@ const List = Loadable({
|
||||||
loader : () => import("./list"),
|
loader : () => import("./list"),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
const ListById = Loadable({
|
||||||
|
loader : () => import("./list/listById"),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
const Editor = Loadable({
|
const Editor = Loadable({
|
||||||
loader : () => import("./edit"),
|
loader : () => import("./edit"),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
|
|
@ -29,6 +33,12 @@ function SoftBot(props){
|
||||||
<Editor {...props} {...p} />
|
<Editor {...props} {...p} />
|
||||||
)}
|
)}
|
||||||
></Route>
|
></Route>
|
||||||
|
<Route
|
||||||
|
path="/forums/theme/:id"
|
||||||
|
render={(p) => (
|
||||||
|
<ListById {...props} {...p} />
|
||||||
|
)}
|
||||||
|
></Route>
|
||||||
<Route
|
<Route
|
||||||
path="/forums/:id/edit"
|
path="/forums/:id/edit"
|
||||||
render={(p) => (
|
render={(p) => (
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
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);
|
||||||
|
const imageUrl = item.image_url.split(':4000/') && item.image_url.split(':4000/')[1]
|
||||||
|
const authorImageUrl = imageUrl ? `${window.location.origin}/${imageUrl}` : item.image_url
|
||||||
|
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={authorImageUrl} 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;
|
||||||
|
|
@ -1,253 +1,228 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
import { Button, Carousel, Divider, Pagination, Tag } from "antd";
|
import { getForumSections, getForumsList } from "../api";
|
||||||
import { getForumsById, getForumSections, getForumsList } from "../api";
|
|
||||||
import { httpUrl } from "../fetch";
|
|
||||||
import { Link } from "react-router-dom";
|
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 Nodata from "../../forge/Nodata";
|
||||||
import { forumSectionId } from "../static";
|
import { forumSectionId } from "../static";
|
||||||
import { rollingButton } from "../../components/button";
|
import { rollingButton, slidingArrowButton } from "../../components/button";
|
||||||
import { HoverUnderline } from "../../components/title";
|
import ForumList from "./forumList";
|
||||||
|
|
||||||
function List(props) {
|
function List(props) {
|
||||||
const {mygetHelmetapi, location, current_user} = props;
|
const {mygetHelmetapi, current_user, showLoginDialog} = props;
|
||||||
const {common} = mygetHelmetapi || {};
|
const {common} = mygetHelmetapi || {};
|
||||||
const {forums: forumsDoMain} = common || {};
|
const {forums: forumsDoMain} = common || {};
|
||||||
const tagNameByState = location && location.state && location.state.name;
|
|
||||||
const [forumsList, setForumsList] = useState([]);
|
const [forumsList, setForumsList] = useState([]);
|
||||||
const [forumsImgList, setForumsImgList] = useState([]);
|
|
||||||
const [hottestForumsList, setHottestForumsList] = useState([]);
|
const [hottestForumsList, setHottestForumsList] = useState([]);
|
||||||
// 板块信息
|
// 板块信息
|
||||||
const [forumTag, setForumTag] = useState([]);
|
const [forumTag, setForumTag] = useState([]);
|
||||||
// 选中的板块详情
|
|
||||||
const [forumTagDetail, setForumTagDetail] = useState(undefined);
|
|
||||||
// 选中的板块对应的帖子列表
|
// 选中的板块对应的帖子列表
|
||||||
const LIMIT = 10;
|
const LIMIT = 10;
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [forumListByTag, setForumListByTag] = useState([]);
|
const [recommendList, setRecommendList] = useState([]);
|
||||||
// 轮播的active
|
// 轮播的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 = {
|
const sortImg2 = {
|
||||||
0: require('../image/icon2.png'),
|
0: require('../image/icon2.png'),
|
||||||
1: require('../image/icon3.png'),
|
1: require('../image/icon3.png'),
|
||||||
2: require('../image/icon4.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))
|
const startAutoPlay = () => {
|
||||||
setForumTagDetail(tagByState && !!tagByState.length ? tagByState[0] : updatedTags[0]);
|
stopAutoPlay();
|
||||||
if (tagByState && !!tagByState.length) {
|
autoPlayTimerRef.current = setInterval(() => {
|
||||||
requestAnimationFrame(() => {
|
// 如果正在悬停,不切换
|
||||||
requestAnimationFrame(() => {
|
if (isHoveringRef.current) return;
|
||||||
const el = document.getElementById('forums-list3-id')
|
|
||||||
if (el) {
|
// 使用forumTagRef获取最新的forumTag
|
||||||
el.scrollIntoView({ behavior: 'smooth' })
|
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(() => {
|
useEffect(() => {
|
||||||
document.title = '论坛交流';
|
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 => {
|
getForumSections(forumSectionId).then(res => {
|
||||||
if (res && res.recommend_forum_sections) {
|
if (res && res.recommend_forum_sections) {
|
||||||
// 获取所有子板块
|
// 获取所有子板块
|
||||||
const childrenTags = res.recommend_forum_sections;
|
const childrenTags = res.recommend_forum_sections;
|
||||||
setForumTag(childrenTags);
|
setForumTag(childrenTags);
|
||||||
init(childrenTags)
|
forumTagRef.current = childrenTags;
|
||||||
|
const firstTag = childrenTags && !!childrenTags.length ? childrenTags[0] : childrenTags[0];
|
||||||
// 并发请求所有板块的精华帖子
|
if (firstTag) {
|
||||||
// const fetchEssencePosts = async (tag) => {
|
setActiveId(firstTag.id);
|
||||||
// try {
|
}
|
||||||
// const essenceRes = await getForumsById(tag.id, {
|
setIsInitialized(true);
|
||||||
// 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)
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// 当forumTag更新且已初始化后,启动自动轮播
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (forumTagDetail && forumTagDetail.id) {
|
if (forumTag.length > 0 && isInitialized) {
|
||||||
// const forums = forumTagDetail.essencePosts[0] || {}
|
forumTagRef.current = forumTag;
|
||||||
getForumsById(forumTagDetail.id, {
|
startAutoPlay();
|
||||||
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);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}, [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 (
|
return (
|
||||||
<div className="forums-list-box">
|
<div className="forums-list-box">
|
||||||
<div className="forums-banner-box">
|
<div className="forums-banner-box">
|
||||||
<div className="width1600 center">
|
<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-60 font-bd forums-banner-title1 mb10">
|
||||||
<div className="font-18 mb35 forums-banner-title2">需求反馈 技术交流 创意分享</div>
|
<span>论坛交流·</span>
|
||||||
{forumsDoMain && rollingButton({href: current_user && current_user.login ? `/forums/add` : `/login?go_page=/forums/add`, name: '发布帖子', hoverName: '发布帖子', classname: "add-forums"})}
|
<span className="carousel-text">解锁头脑风暴</span>
|
||||||
</div>
|
<span className="eyes">
|
||||||
<div className="width1600 df pt50 forums-hot-list">
|
<svg viewBox="0 0 50 32" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-full h-full overflow-visible">
|
||||||
{forumsImgList && !!forumsImgList.length && <Carousel autoplay className='forums-list-left-Carousel' beforeChange={(_, nextId)=>{setActiveId(nextId)}}>
|
<rect class="animate-eye-left-white" width="18.67" height="23.44" rx="10.72" fill="#ffffff00" stroke="#000" stroke-width="1.5"></rect>
|
||||||
{forumsImgList.map((item, index)=>{
|
<rect class="animate-eye-right-white" width="18.67" height="23.44" rx="10.72" fill="#ffffff00" stroke="#000" stroke-width="1.5"></rect>
|
||||||
return <img src={httpUrl + item.memo_image_info.url} alt=''key={index}/>
|
<circle class="animate-eye-right-pupil" r="5.395" fill="#000"></circle>
|
||||||
})}
|
<circle class="animate-eye-left-pupil" r="5.49" fill="#000"></circle>
|
||||||
</Carousel>}
|
</svg>
|
||||||
<div className="forums-list1">
|
</span>
|
||||||
{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 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 font-18"})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="width1600 df pt30 forums-hot-list">
|
||||||
<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="team highlight-list teamShow">
|
<div className="team highlight-list teamShow">
|
||||||
{forumTag.map((item, index) => {
|
{forumTag.map((item, index) => {
|
||||||
const isSelected = forumTagDetail && forumTagDetail.id === item.id;
|
const isSelected = activeId === item.id;
|
||||||
const forums = item.essencePosts && item.essencePosts[0] || {};
|
|
||||||
return (
|
return (
|
||||||
<li className={`highlight-card ${isSelected ? "hovered":""}`} onClick={()=>{setForumTagDetail(item); setPage(1)}}>
|
<li
|
||||||
<img src={forumsImg[index]} alt="" className="mb30" width={37}/>
|
className={`highlight-card ${isSelected ? "hovered":""}`}
|
||||||
<div className='t-title'><span dangerouslySetInnerHTML={{ __html: item.title }}></span></div>
|
onMouseEnter={() => handleMouseEnter(item)}
|
||||||
<div className="t-desc" dangerouslySetInnerHTML={{ __html: item.description }}></div>
|
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>
|
</li>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{/* 板块对应的帖子列表 */}
|
</div>
|
||||||
<div className="forums-list4-box mt40">
|
</div>
|
||||||
{forumListByTag.map((item, index) => {
|
<div className="forums-list3-box" id="forums-list3-box">
|
||||||
const orderIndex = index+LIMIT*(page-1)
|
<div className="width1600 pb100 df forums-list3-content" id="forums-list3-id">
|
||||||
return <div className="forums-list4-item">
|
{/* 帖子列表 */}
|
||||||
<div className="pr80 AlignCenter">
|
<ForumList forumList={forumsList} LIMIT={LIMIT} page={page} setPage={setPage} total={total} onSearch={setSearch} onSort={setSort} sortBy={sort}/>
|
||||||
{orderIndex < 3 ? <img src={sortImg1[orderIndex]} width={24} className="mr10"/> : <span className="font-bd font-20 mr10">{orderIndex + 1}</span>}
|
<div className="forums-list3-right">
|
||||||
<Link to={`/forums/${item.id}`} className="forums-list4-item-link task-hide">
|
<a className="add_forum" href={`/forums/add`} onClick={(e)=>{
|
||||||
<HoverUnderline classname="font-22 task-hide">
|
if(current_user && !current_user.login){
|
||||||
{item.subject}
|
e.stopPropagation();
|
||||||
</HoverUnderline>
|
e.preventDefault();
|
||||||
</Link>
|
showLoginDialog("/forums/add");
|
||||||
{item.sticky && <Tag color="#d06d3c">置顶</Tag>}
|
}
|
||||||
{item.is_original && <Tag color="#7e41f1">原创</Tag>}
|
}}><i className="iconfont icon-a-fabu1 font-16 mr5"></i>写点什么</a>
|
||||||
{item.is_fine && <Tag color="#2E89FF">精华</Tag>}
|
<div className="hot-forums-list mt20 mb20">
|
||||||
</div>
|
<div className="font-22 hot-forums-list-header">
|
||||||
<div className="opacity8 mt15">
|
<img src={require('../image/icon1.png')} alt="" width={24} className="mr8 mb3"/>
|
||||||
<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-list2">
|
||||||
{forumListByTag.length === 0 && (
|
{hottestForumsList && hottestForumsList.length > 0 ? hottestForumsList.map((item, index) => (
|
||||||
<Nodata _html="暂无数据" />
|
<div className="font-18 forums-list-item" key={index}>
|
||||||
)}
|
<span className="forums-subject AlignCenter">
|
||||||
<Pagination pageSize={LIMIT} total={total} hideOnSinglePage={true} current={page} onChange={(page) => { setPage(page) }} className='edu-txt-right mt30' />
|
{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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,27 +4,32 @@
|
||||||
color: #091221;
|
color: #091221;
|
||||||
background-color: #f1f6fd;
|
background-color: #f1f6fd;
|
||||||
font-family: "alibabaReg";
|
font-family: "alibabaReg";
|
||||||
|
background-image: url('../image/banner.png');
|
||||||
|
background-size: 100% 100%;
|
||||||
|
|
||||||
.ant-tag {
|
.ant-tag {
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
margin-left: 10px;
|
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
|
|
||||||
&+.ant-tag {
|
&+.ant-tag {
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.font-bd{
|
||||||
|
font-weight: normal;
|
||||||
|
font-family: "alibaba";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.forums-banner-box {
|
.forums-banner-box {
|
||||||
background-image: url('../image/banner.png');
|
padding: 70px 0 120px;
|
||||||
background-size: 100% 100%;
|
|
||||||
padding: 70px 0 145px;
|
|
||||||
|
|
||||||
.forums-banner-title1 {
|
.forums-banner-title1 {
|
||||||
font-family: 'DouyinSansBold';
|
font-family: 'DouyinSansBold';
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
&>:first-child {
|
&>:first-child {
|
||||||
--duration: 200ms;
|
--duration: 200ms;
|
||||||
|
|
@ -39,6 +44,7 @@
|
||||||
&>:nth-child(3) {
|
&>:nth-child(3) {
|
||||||
--duration: 200ms;
|
--duration: 200ms;
|
||||||
--delay: 600ms;
|
--delay: 600ms;
|
||||||
|
--top: -16px
|
||||||
}
|
}
|
||||||
|
|
||||||
&>* {
|
&>* {
|
||||||
|
|
@ -46,17 +52,27 @@
|
||||||
--offsetTop: 56px;
|
--offsetTop: 56px;
|
||||||
animation: itemUp var(--duration) ease-in-out var(--delay) forwards, bgOpacity var(--duration) linear var(--delay) reverse backwards
|
animation: itemUp var(--duration) ease-in-out var(--delay) forwards, bgOpacity var(--duration) linear var(--delay) reverse backwards
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.eyes{
|
||||||
|
width: 77px;
|
||||||
|
display: inline-block;
|
||||||
|
.animate-eye-right-white {
|
||||||
|
animation: 3s cubic-bezier(.4,0,.2,1) infinite eyeRightWhite
|
||||||
|
}
|
||||||
|
.animate-eye-left-white {
|
||||||
|
animation: 3s cubic-bezier(.4,0,.2,1) infinite eyeLeftWhite
|
||||||
|
}
|
||||||
|
.animate-eye-right-pupil {
|
||||||
|
animation: 3s cubic-bezier(.4,0,.2,1) infinite eyeRightPupil
|
||||||
|
}
|
||||||
|
.animate-eye-left-pupil {
|
||||||
|
animation: 3s cubic-bezier(.4,0,.2,1) infinite eyeLeftPupil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-text {
|
.carousel-text {
|
||||||
background-image: linear-gradient(313.07deg, #d62ece 0%, #1664ff 100%);
|
color: #2149d4;
|
||||||
-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%);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.forums-banner-title2 {
|
.forums-banner-title2 {
|
||||||
|
|
@ -69,7 +85,7 @@
|
||||||
width: 168px;
|
width: 168px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
border: 4px solid #CCD3E8;
|
border: 4px solid #E2D5DC;
|
||||||
line-height: 52px;
|
line-height: 52px;
|
||||||
position: relative;
|
position: relative;
|
||||||
--offsetTop: 26px;
|
--offsetTop: 26px;
|
||||||
|
|
@ -82,30 +98,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 {
|
.hot-forums-list {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-radius: 8px;
|
border-radius: 15px;
|
||||||
box-shadow: 0px 0px 10px rgba(35, 44, 121, 0.07);
|
box-shadow: 0px 0px 10px rgba(35, 44, 121, 0.07);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,15 +136,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.forums-list-item:not(:last-of-type):not(.forums-list-item-active) {
|
.forums-list-item:not(:last-of-type) {
|
||||||
.forums-subject {
|
.forums-subject {
|
||||||
border-bottom: 1px dashed rgba(130, 132, 164, 0.4);
|
border-bottom: 1px dashed rgba(130, 132, 164, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.forums-list-item:hover,
|
.forums-list-item:hover {
|
||||||
.forums-list-item-active {
|
|
||||||
background-image: linear-gradient(180deg, #f7f9fd00 0%, #f7f9fd 100%);
|
background-image: linear-gradient(180deg, #f7f9fd00 0%, #f7f9fd 100%);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
@ -162,13 +158,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.hot-forums-list-header {
|
.hot-forums-list-header {
|
||||||
padding: 12px 25px 10px 25px;
|
padding: 12px 16px 10px 16px;
|
||||||
background-image: url('../image/bk2.png');
|
background-image: url('../image/bk2.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.forums-list2 {
|
.forums-list2 {
|
||||||
padding: 0 25px 12px 25px;
|
padding: 0 16px 12px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.forums-hot-list {
|
.forums-hot-list {
|
||||||
|
|
@ -176,17 +172,49 @@
|
||||||
--offsetTop: 56px;
|
--offsetTop: 56px;
|
||||||
animation: itemUp .4s ease-in-out 1.36s forwards, bgOpacity .4s linear 1.36s reverse backwards;
|
animation: itemUp .4s ease-in-out 1.36s forwards, bgOpacity .4s linear 1.36s reverse backwards;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.forums-list3-box {
|
.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;
|
position: relative;
|
||||||
--offsetTop: 116px;
|
--offsetTop: 116px;
|
||||||
--top: -60px;
|
--top: -60px;
|
||||||
animation: itemUp .4s ease-in-out 1.56s forwards, bgOpacity .4s linear 1.56s reverse backwards;
|
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 {
|
.user-img {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
@ -195,124 +223,38 @@
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.forums-section-box {
|
.forums-list4-item {
|
||||||
gap: 20px;
|
padding: 25px 30px 0 25px;
|
||||||
}
|
|
||||||
|
|
||||||
.forums-section-item-box {
|
|
||||||
border-radius: 15px;
|
|
||||||
border: 2px solid transparent;
|
|
||||||
box-shadow: 0px 3px 6px rgba(22, 100, 255, 0.02);
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&.active {
|
&:hover{
|
||||||
border-color: #2149d4;
|
background:#f7f9fd;
|
||||||
|
border-radius:10px;
|
||||||
&::before {
|
.forums-list4-item-link{
|
||||||
width: 106%;
|
font-family: "alibaba";
|
||||||
height: 110%;
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
background-color: rgb(33 72 212 / 20%);
|
|
||||||
top: -5%;
|
|
||||||
left: -3%;
|
|
||||||
border-radius: 15px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
.ant-tag {
|
||||||
content: "";
|
display: none;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
.icon-jiantou21{
|
||||||
// color:#2149d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memo_image_info {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: #2149d4;
|
|
||||||
|
|
||||||
.icon-jiantou3 {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.forums-list4-item-link{
|
||||||
|
color: #091221;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.forums-list4-box {
|
.forums-list4-item-bottom{
|
||||||
background-color: #ffffff;
|
border-bottom: 1px dashed rgba(130, 132, 164, 0.4);
|
||||||
border-radius: 15px;
|
padding-bottom: 25px;
|
||||||
padding: 25px 30px;
|
}
|
||||||
|
|
||||||
.forums-list4-item {
|
.icon-jiantou21{
|
||||||
position: relative;
|
display: none;
|
||||||
border-bottom: 1px dashed rgba(130, 132, 164, 0.4);
|
}
|
||||||
padding-bottom: 12px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewed_count {
|
.viewed_count {
|
||||||
|
|
@ -332,22 +274,11 @@
|
||||||
animation: fire 1s ease-in-out infinite;
|
animation: fire 1s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.forums-list4-item-link {
|
|
||||||
&:hover {
|
|
||||||
.hover-underline {
|
|
||||||
padding-right: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&~.ant-tag {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.team {
|
.team {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-left: 0px;
|
padding-left: 0px;
|
||||||
|
|
@ -361,103 +292,70 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
height: 280px;
|
height: 260px;
|
||||||
padding: 30px 30px 34px 30px;
|
padding: 30px 30px 34px 30px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 15px;
|
|
||||||
flex: 1 1;
|
flex: 1 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
width: 0;
|
width: 0;
|
||||||
margin-right: 20px;
|
|
||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
text-align: left;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
transition-duration: 1s;
|
transition-duration: 1s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
|
border-radius: 15px;
|
||||||
&>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;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(1) {
|
&:nth-child(1) {
|
||||||
background-image: url("../image/image13.png");
|
background-image: url("../image/image5.png");
|
||||||
|
.t-title{
|
||||||
&::after {
|
background:linear-gradient(94.98deg,#ffffff 3.87%,#ffffff 83.9%,#eca2b9 100%);
|
||||||
background-image: url("../image/image9.png");
|
-webkit-background-clip: text;
|
||||||
width: 100%;
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(2) {
|
&:nth-child(2) {
|
||||||
background-image: url("../image/image6.png");
|
background-image: url("../image/image6.png");
|
||||||
|
.t-title{
|
||||||
&::after {
|
background:linear-gradient(92.24deg,#ffffff 2.21%,#ffffff 86.8%,#87e1e8 99.78%);
|
||||||
background-image: url("../image/image10.png");
|
-webkit-background-clip: text;
|
||||||
width: 100%;
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(3) {
|
&:nth-child(3) {
|
||||||
background-image: url("../image/image7.png");
|
background-image: url("../image/image7.png");
|
||||||
|
.t-title{
|
||||||
&::after {
|
background:linear-gradient(97.88deg,#ffffff 3.83%,#ffffff 83.89%,#eca2b9 100%);
|
||||||
background-image: url("../image/image11.png");
|
-webkit-background-clip: text;
|
||||||
width: 100%;
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(4) {
|
&:nth-child(4) {
|
||||||
background-image: url("../image/image8.png");
|
background-image: url("../image/image8.png");
|
||||||
|
.t-title{
|
||||||
&::after {
|
background:linear-gradient(94.26deg,#ffffff 2.16%,#ffffff 81.2%,#9cd8f8 100%);
|
||||||
background-image: url("../image/image12.png");
|
-webkit-background-clip: text;
|
||||||
width: 100%;
|
-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 {
|
&.hovered, &:hover {
|
||||||
flex: 2 1;
|
transform: translateY(-24px);
|
||||||
|
.highlight-card-bottom{
|
||||||
&:nth-child(1)::after {
|
font-family: "alibaba";
|
||||||
width: 50%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(:nth-child(1))::after {
|
.iconfont {
|
||||||
width: 70%;
|
display: inline-block;
|
||||||
|
animation: arrow-move 1.2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -467,30 +365,84 @@
|
||||||
|
|
||||||
span {
|
span {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 18px;
|
font-size: 28px;
|
||||||
line-height: 30px;
|
line-height: 36px;
|
||||||
font-family: "alibabaBold";
|
font-family: "alibabaBold";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.t-desc {
|
.highlight-card-bottom{
|
||||||
font-size: 14px;
|
position: absolute;
|
||||||
line-height: 22px;
|
left: 0px;
|
||||||
text-align: left;
|
bottom: 10px;
|
||||||
word-break: break-all;
|
width: 100%;
|
||||||
overflow: hidden;
|
display: flex;
|
||||||
text-overflow: ellipsis;
|
justify-content: space-between;
|
||||||
display: -webkit-box;
|
align-items: center;
|
||||||
-webkit-box-orient: vertical;
|
padding: 0 25px;
|
||||||
font-family: alibabaPuhuiR;
|
color: white;
|
||||||
-webkit-line-clamp: 2;
|
font-size:20px;
|
||||||
opacity: 0.8;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.t-time {
|
.forums_header{
|
||||||
font-size: 15px;
|
background-image: url('../image/bk3.png');
|
||||||
text-align: left;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -519,4 +471,49 @@
|
||||||
100% {
|
100% {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eyeRightWhite {
|
||||||
|
0%,to {
|
||||||
|
transform: translate(27.22px,1px)
|
||||||
|
}
|
||||||
|
33%,66% {
|
||||||
|
transform: translate(24.22px,3px)
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: translate(24.22px,1px)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes eyeLeftWhite {
|
||||||
|
0%,to {
|
||||||
|
transform: translate(6.59px,4.94px)
|
||||||
|
}
|
||||||
|
33%,66% {
|
||||||
|
transform: translate(3.59px,6.94px)
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: translate(3.59px,4.94px)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes eyeRightPupil {
|
||||||
|
0%,to {
|
||||||
|
transform: translate(38.745px,12.895px)
|
||||||
|
}
|
||||||
|
33%,66% {
|
||||||
|
transform: translate(31.745px,16.895px)
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: translate(31.745px,10.895px)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes eyeLeftPupil {
|
||||||
|
0%,to {
|
||||||
|
transform: translate(18.16px,17.11px)
|
||||||
|
}
|
||||||
|
33%,66% {
|
||||||
|
transform: translate(11.16px,21.11px)
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: translate(11.16px,15.11px)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -315,10 +315,11 @@ i.color-orange05:hover {
|
||||||
color:#fff !important;
|
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{
|
li, li:hover, li:focus, li:active{
|
||||||
border-color:#091221;
|
border-color:#091221 !important;
|
||||||
a, i{
|
a, i, a.ant-pagination-item-link i{
|
||||||
color:#091221;
|
color:#091221;
|
||||||
|
border-color:#091221 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ant-pagination-options-quick-jumper input:hover{
|
.ant-pagination-options-quick-jumper input:hover{
|
||||||
|
|
|
||||||