项目详情页test
This commit is contained in:
parent
5b4dbe4908
commit
7817cc451f
|
|
@ -1,6 +1,6 @@
|
|||
// import app from './src/App'
|
||||
import app from './src/App'
|
||||
// import users from './src/forge/users/Index';
|
||||
// import Detail from "./src/forge/Main/Detail";
|
||||
import Detail from "./src/forge/Main/Detail";
|
||||
// import Information from "./src/forge/Information/index"
|
||||
// import NewsDetail from './src/forge/Information/Pages/newsDetail';
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ export default [
|
|||
{
|
||||
key:"detail",
|
||||
path: "/:owner/:projectsId",
|
||||
// component: app,
|
||||
component: app,
|
||||
}
|
||||
];
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ export const deepRoutes = [
|
|||
{
|
||||
key: "detail",
|
||||
path: "/:owner/:projectsId",
|
||||
// component: Detail,
|
||||
component: Detail,
|
||||
},
|
||||
{
|
||||
key: "owner",
|
||||
|
|
|
|||
|
|
@ -159,12 +159,13 @@ const serverConfig = {
|
|||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: {
|
||||
publicPath,
|
||||
},
|
||||
},
|
||||
'isomorphic-style-loader',
|
||||
// {
|
||||
// loader: MiniCssExtractPlugin.loader,
|
||||
// options: {
|
||||
// publicPath,
|
||||
// },
|
||||
// },
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
|
|
|
|||
|
|
@ -11450,7 +11450,7 @@
|
|||
},
|
||||
"isomorphic-style-loader": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/isomorphic-style-loader/-/isomorphic-style-loader-5.3.2.tgz",
|
||||
"resolved": "https://registry.npmjs.org/isomorphic-style-loader/-/isomorphic-style-loader-5.3.2.tgz",
|
||||
"integrity": "sha512-5mwHrN2xK5zsKBxSUYF7iDhoU9Kpcpfgn0lFOP0SKk3aKwkl26zi6kh+KDrekjlLzNbYsFnn8o1yWaB3OflVXQ==",
|
||||
"requires": {
|
||||
"hoist-non-react-statics": "^3.0.0",
|
||||
|
|
@ -21603,13 +21603,15 @@
|
|||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
|
|
@ -21618,7 +21620,8 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.6.0",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ app.use('/build', express.static('build'));
|
|||
const options = (target) => {
|
||||
return {
|
||||
target: target,
|
||||
changeOrigin: false, // 允许在请求头中更改主机
|
||||
changeOrigin: true, // 允许在请求头中更改主机
|
||||
timeout: 30000,
|
||||
onProxyRes: (proxyRes, req, res) => {
|
||||
// 代理成功后输出日志
|
||||
|
|
|
|||
102
server/render.js
102
server/render.js
|
|
@ -1,23 +1,27 @@
|
|||
// import React from "react";
|
||||
// import {renderToString} from "react-dom/server";
|
||||
import React from "react";
|
||||
import {renderToString} from "react-dom/server";
|
||||
import {StaticRouter, matchPath} from "react-router-dom";
|
||||
// import {renderRoutes} from "react-router-config";
|
||||
import StyleContext from 'isomorphic-style-loader/StyleContext'
|
||||
import {renderRoutes} from "react-router-config";
|
||||
|
||||
import Routes, { deepRoutes, specialRoute } from "../Routes";
|
||||
// import { Provider } from "react-redux";
|
||||
// import { serverStore } from "../src/redux/stores/configureStore";
|
||||
import { Provider } from "react-redux";
|
||||
import { serverStore } from "../src/redux/stores/configureStore";
|
||||
// import App from "../src/App";
|
||||
// import { Route } from 'react-router-dom';
|
||||
// import { setDefaultMeta } from '../src/common/UrlTool'
|
||||
import { setDefaultMeta } from '../src/common/UrlTool'
|
||||
import Logger from "./log";
|
||||
import { changeHead } from './setHead'
|
||||
|
||||
const css = new Set() // 这个必须在路由函数里面,在外面的话,就会累加出现之前的css
|
||||
const insertCss = (...styles) => styles.forEach(style => css.add(style._getCss()));
|
||||
|
||||
export const render = async (req,res)=>{
|
||||
let _route = null,
|
||||
_match = null;
|
||||
// Logger.info(`${req.url} UA:${req.headers['user-agent']}`)
|
||||
Logger.info(`${req.url} UA:${req.headers['user-agent']}`)
|
||||
|
||||
// let store = serverStore();
|
||||
let store = serverStore();
|
||||
|
||||
function matchSubRoutes(routes, url) {
|
||||
for (const route of routes) {
|
||||
|
|
@ -50,6 +54,44 @@ export const render = async (req,res)=>{
|
|||
code: 200,
|
||||
};
|
||||
|
||||
|
||||
if (_route && _route.component && _route.component.preFetch) {
|
||||
context = await _route.component.preFetch({
|
||||
store,
|
||||
match: _match,
|
||||
query: req.path,
|
||||
});
|
||||
}
|
||||
|
||||
const content = renderToString((
|
||||
<Provider store={store}>
|
||||
<StaticRouter location={req.path} context={context}>
|
||||
<StyleContext.Provider value={{insertCss}}>
|
||||
{renderRoutes(Routes)}
|
||||
{/* <Route path='/:owner/:projectsId' exact component={App}></Route> */}
|
||||
</StyleContext.Provider>
|
||||
</StaticRouter>
|
||||
</Provider>
|
||||
))
|
||||
|
||||
if (!content) {
|
||||
// 未匹配到详情页恢复默认header
|
||||
setDefaultMeta()
|
||||
} else {
|
||||
// 匹配到服务端渲染页面注入state
|
||||
let script = domObj.window.document.getElementById('initState')
|
||||
if (!script) {
|
||||
script = domObj.window.document.createElement('script')
|
||||
script.setAttribute('id', 'initState')
|
||||
}
|
||||
script.textContent = `window.__initState__ = ${ JSON.stringify(store.getState()) }`
|
||||
const styleNode = domObj.window.document.createElement('style')
|
||||
styleNode.type = 'text/css'
|
||||
styleNode.innerHTML = `${ [...css].join('') }`
|
||||
domObj.window.document.head.appendChild(script);
|
||||
domObj.window.document.head.appendChild(styleNode);
|
||||
}
|
||||
|
||||
if (_route && !specialRoute.includes(_match.url && _match.url.replace('/', ''))) {
|
||||
Logger.info(`matchRoot: ${ _match.url }`)
|
||||
await changeHead(_route, _match.params)
|
||||
|
|
@ -58,51 +100,13 @@ export const render = async (req,res)=>{
|
|||
}
|
||||
|
||||
|
||||
// if (_route && _route.component && _route.component.preFetch) {
|
||||
// context = await _route.component.preFetch({
|
||||
// store,
|
||||
// match: _match,
|
||||
// query: req.path,
|
||||
// });
|
||||
// }
|
||||
|
||||
// 暂时不开放ssr,只修改head
|
||||
// const content = renderToString((
|
||||
// <Provider store={store}>
|
||||
// <StaticRouter location={req.path} context={context}>
|
||||
// {renderRoutes(Routes)}
|
||||
// {/* <Route path='/:owner/:projectsId' exact component={App}></Route> */}
|
||||
// </StaticRouter>
|
||||
// </Provider>
|
||||
// ))
|
||||
|
||||
// 暂时不开放ssr,只修改head
|
||||
// if (!content) {
|
||||
// // 未匹配到详情页恢复默认header
|
||||
// setDefaultMeta()
|
||||
// } else {
|
||||
// // 匹配到服务端渲染页面注入state
|
||||
// let script = domObj.window.document.getElementById('initState')
|
||||
// if (!script) {
|
||||
// script = domObj.window.document.createElement('script')
|
||||
// script.setAttribute('id', 'initState')
|
||||
// }
|
||||
// script.textContent = `window.__initState__ = ${ JSON.stringify(store.getState()) }`
|
||||
|
||||
// domObj.window.document.head.appendChild(script);
|
||||
// }
|
||||
|
||||
|
||||
let html = domObj.serialize()
|
||||
|
||||
const prepHTML=(data,rootString)=>{
|
||||
// 暂时不开放ssr,只修改head
|
||||
// data=data.replace('<div id="root" class="page -layout-v -fit widthunit"></div>',`<div id="root" class="page -layout-v -fit widthunit">${rootString}</div>`);
|
||||
data=data.replace('<div id="root" class="page -layout-v -fit widthunit"></div>',`<div id="root" class="page -layout-v -fit widthunit">${rootString}</div>`);
|
||||
return data;
|
||||
}
|
||||
// 暂时不开放ssr,只修改head
|
||||
// res.send(prepHTML(html, content))
|
||||
res.send(prepHTML(html, ''))
|
||||
res.send(prepHTML(html, content))
|
||||
|
||||
// store = null
|
||||
store = null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,15 +6,15 @@ export const changeHead = async ({ key }, params) => {
|
|||
let res
|
||||
let data
|
||||
switch (key) {
|
||||
case 'detail':
|
||||
res = await getProjectDetailFunc(params.owner, params.projectsId);
|
||||
data = res.data
|
||||
if (data && data.status === 1) {
|
||||
let keyWords=`${params.owner},${params.projectsId}${ data.topics.length > 0 && ','}${ data.topics.length > 0 && data.topics.map(item => item.name).join(',') }`;
|
||||
let title= `${params.owner}/${params.projectsId}${data.description?':'+data.description:''}`;
|
||||
setSeoMeta(keyWords,title,data.description || '',`/${params.owner}/${params.projectsId}`,params.owner,params.projectsId);
|
||||
}
|
||||
break;
|
||||
// case 'detail':
|
||||
// res = await getProjectDetailFunc(params.owner, params.projectsId);
|
||||
// data = res.data
|
||||
// if (data && data.status === 1) {
|
||||
// let keyWords=`${params.owner},${params.projectsId}${ data.topics.length > 0 && ','}${ data.topics.length > 0 && data.topics.map(item => item.name).join(',') }`;
|
||||
// let title= `${params.owner}/${params.projectsId}${data.description?':'+data.description:''}`;
|
||||
// setSeoMeta(keyWords,title,data.description || '',`/${params.owner}/${params.projectsId}`,params.owner,params.projectsId);
|
||||
// }
|
||||
// break;
|
||||
case 'zoneNews':
|
||||
res = await getNewsDetail(params.id)
|
||||
data = res.data.data
|
||||
|
|
@ -33,7 +33,7 @@ export const changeHead = async ({ key }, params) => {
|
|||
res = await getOwnerInfo(params.owner);
|
||||
data = res.data
|
||||
const name = data.nickname || data.username
|
||||
if (data && data.status === 1) {
|
||||
if (data && data.name) {
|
||||
setSeoMeta(`${name}`, name, data.description || '', `/${params.owner}`)
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
18
src/App.js
18
src/App.js
|
|
@ -23,6 +23,8 @@ import SiderBarHelp from './glcc/siderBarHelp';
|
|||
import { SnackbarHOC, configShareForCustom } from 'educoder';
|
||||
import { initAxiosInterceptors } from './AppConfig'
|
||||
import cookie from 'react-cookies';
|
||||
import InfosIndex from './forge/users/Index'
|
||||
import OrganizeIndex from './forge/Team/Index'
|
||||
|
||||
window.marked = marked;
|
||||
const theme = createMuiTheme({
|
||||
|
|
@ -74,15 +76,15 @@ const http500 = Loadable({
|
|||
loader: () => import('./modules/500/http500'),
|
||||
loading: Loading,
|
||||
})
|
||||
const InfosIndex = Loadable({
|
||||
loader: () => import('./forge/users/Index'),
|
||||
loading: Loading,
|
||||
})
|
||||
// const InfosIndex = Loadable({
|
||||
// loader: () => import('./forge/users/Index'),
|
||||
// loading: Loading,
|
||||
// })
|
||||
// 组织
|
||||
const OrganizeIndex = Loadable({
|
||||
loader: () => import('./forge/Team/Index'),
|
||||
loading: Loading,
|
||||
})
|
||||
// const OrganizeIndex = Loadable({
|
||||
// loader: () => import('./forge/Team/Index'),
|
||||
// loading: Loading,
|
||||
// })
|
||||
|
||||
const Search = Loadable({
|
||||
loader: () => import('./modules/search/'),
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
import './index.scss';
|
||||
import React, { useState } from 'react';
|
||||
import { Form, Button, Input } from 'antd';
|
||||
import QuillForEditor from '../../quillForEditor';
|
||||
// import QuillForEditor from '../../quillForEditor';
|
||||
const FormItem = Form.Item;
|
||||
|
||||
function CommentForm(props) {
|
||||
|
|
@ -116,7 +116,7 @@ function CommentForm(props) {
|
|||
)
|
||||
}
|
||||
|
||||
<QuillForEditor
|
||||
{/* <QuillForEditor
|
||||
imgAttrs={{ width: '60px', height: '30px' }}
|
||||
wrapStyle={{
|
||||
height: showQuill ? 'auto' : '0px',
|
||||
|
|
@ -131,7 +131,7 @@ function CommentForm(props) {
|
|||
value={ctx}
|
||||
showUploadImage={handleShowImage}
|
||||
onContentChange={handleContentChange}
|
||||
/>
|
||||
/> */}
|
||||
</FormItem>
|
||||
<FormItem style={{ textAlign: 'right', display: showQuill ? 'block' : 'none' }}>
|
||||
<Button onClick={handleCancle}>取消</Button>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export { default as ActionBtn } from './course/ActionBtn'
|
|||
|
||||
export { default as MarkdownToHtml } from './components/markdown/MarkdownToHtml'
|
||||
|
||||
export { default as QuillForEditor } from './quillForEditor'
|
||||
// export { default as QuillForEditor } from './quillForEditor'
|
||||
|
||||
export { default as Clappr } from './components/media/Clappr'
|
||||
export { default as AliyunUploader } from './components/media/AliyunUploader'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import './index.scss'
|
||||
import 'quill/dist/quill.core.css' // 核心样式
|
||||
import 'quill/dist/quill.snow.css' // 有工具栏
|
||||
import 'quill/dist/quill.bubble.css' // 无工具栏
|
||||
// import 'quill/dist/quill.core.css' // 核心样式
|
||||
// import 'quill/dist/quill.snow.css' // 有工具栏
|
||||
// import 'quill/dist/quill.bubble.css' // 无工具栏
|
||||
import './font.css'
|
||||
import React, { useState, useRef, useEffect } from 'react'
|
||||
import Quill from 'quill'
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import axios from 'axios';
|
|||
import Path from './CoderDepotPath';
|
||||
import Catalogue from './CoderDepotCatalogue';
|
||||
import ReadMe from './CoderDepotReadme';
|
||||
import CoderRootFileDetail from './CoderRootFileDetail';
|
||||
// import CoderRootFileDetail from './CoderRootFileDetail';
|
||||
import './Index.scss';
|
||||
import Releases from '../Component/Releases';
|
||||
import Contributors from '../Component/Contributors';
|
||||
|
|
@ -571,18 +571,18 @@ function CoderDepot(props){
|
|||
})
|
||||
}
|
||||
{
|
||||
fileInfo &&
|
||||
<CoderRootFileDetail
|
||||
{...props}
|
||||
detail={fileInfo}
|
||||
readOnly={readOnly}
|
||||
md={mdFlag}
|
||||
onEdit={onEdit}
|
||||
currentBranch={branchName || defaultBranch}
|
||||
branch={branchName || defaultBranch}
|
||||
type={projectDetail.type}
|
||||
treeValuePath={treeValuePath}
|
||||
></CoderRootFileDetail>
|
||||
// fileInfo &&
|
||||
// <CoderRootFileDetail
|
||||
// {...props}
|
||||
// detail={fileInfo}
|
||||
// readOnly={readOnly}
|
||||
// md={mdFlag}
|
||||
// onEdit={onEdit}
|
||||
// currentBranch={branchName || defaultBranch}
|
||||
// branch={branchName || defaultBranch}
|
||||
// type={projectDetail.type}
|
||||
// treeValuePath={treeValuePath}
|
||||
// ></CoderRootFileDetail>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ import types from '../../redux/actions/actionTypes'
|
|||
import { getProjectFunc, getProjectDetailFunc } from '../../services/project'
|
||||
import '../css/index.scss'
|
||||
import './list.scss';
|
||||
import styles from './list.scss'
|
||||
import styles1 from '../css/index.scss'
|
||||
import withStyles from 'isomorphic-style-loader/withStyles';
|
||||
|
||||
|
||||
import Loadable from 'react-loadable';
|
||||
|
|
@ -980,7 +983,7 @@ Detail.preFetch = ({ store, match, query }) => {
|
|||
});
|
||||
};
|
||||
|
||||
export default withRouter(connect(
|
||||
export default withRouter(withStyles(styles, styles1)(connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(Detail));
|
||||
)(Detail)));
|
||||
10
src/index.js
10
src/index.js
|
|
@ -9,13 +9,17 @@ import { configureUrlQuery } from 'react-url-query';
|
|||
import history from './history';
|
||||
import configureStore from './redux/stores/configureStore';
|
||||
import { Provider } from 'react-redux';
|
||||
import StyleContext from 'isomorphic-style-loader/StyleContext'
|
||||
|
||||
configureUrlQuery({ history });
|
||||
const store = configureStore();
|
||||
|
||||
window.__useKindEditor = false;
|
||||
|
||||
|
||||
const insertCss = (...styles) => {
|
||||
const removeCss = styles.map(style => style._insertCss && style._insertCss());
|
||||
return () => removeCss.forEach(dispose => dispose && dispose())
|
||||
}
|
||||
|
||||
const render = (Component) => {
|
||||
ReactDOM.hydrate(
|
||||
|
|
@ -24,7 +28,9 @@ const render = (Component) => {
|
|||
<Provider store={store}>
|
||||
|
||||
<BrowserRouter basename='/'>
|
||||
<Route path='/' component={App}></Route>
|
||||
<StyleContext.Provider value={{insertCss}}>
|
||||
<Route path='/' component={App}></Route>
|
||||
</StyleContext.Provider>
|
||||
</BrowserRouter>
|
||||
</Provider>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue