diff --git a/Routes.js b/Routes.js index 9b4b58f06..98db25f6d 100644 --- a/Routes.js +++ b/Routes.js @@ -1,8 +1,8 @@ import app from './src/App' -import users from './src/forge/users/Index'; -import Detail from "./src/forge/Main/Detail"; -import Information from "./src/forge/Information/index" -import NewsDetail from './src/forge/Information/Pages/newsDetail'; +// import users from './src/forge/users/Index'; +// import Detail from "./src/forge/Main/Detail"; +// import Information from "./src/forge/Information/index" +// import NewsDetail from './src/forge/Information/Pages/newsDetail'; export default [ { @@ -26,16 +26,16 @@ export const deepRoutes = [ { key: "zoneNews", path: "/zone/:deptId/newdetail/:id", - component: NewsDetail + // component: NewsDetail }, { key: "zone", path: "/zone/:deptId", - component: Information + // component: Information }, { key: "detail", path: "/:owner/:projectsId", - component: Detail, + // component: Detail, } ] \ No newline at end of file diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js index 712ddd82c..9756df5bb 100644 --- a/config/webpack.config.dev.js +++ b/config/webpack.config.dev.js @@ -17,6 +17,13 @@ const paths = require("./paths"); const publicPath = "/"; const env = getClientEnvironment("/","development"); +const process = require('process'); + +process.on('uncaughtException', function (err) { + // 开发时,websocket proxy 会因服务重新部署而报错中断本地 server,这里拦截一下 + console.log('拦截未处理异常:', err); +}); + module.exports = { optimization: { splitChunks: { diff --git a/package-lock.json b/package-lock.json index ab299564c..812eec9a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -235,7 +235,7 @@ }, "@babel/helper-annotate-as-pure": { "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", "requires": { "@babel/types": "^7.22.5" @@ -243,7 +243,7 @@ }, "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "resolved": "https://registry.npmmirror.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", "requires": { "@babel/types": "^7.22.15" @@ -1456,7 +1456,7 @@ }, "core-js": { "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", "dev": true }, @@ -1480,7 +1480,7 @@ }, "regenerator-runtime": { "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true } @@ -1497,7 +1497,7 @@ "dependencies": { "core-js": { "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" } } @@ -21603,15 +21603,13 @@ "version": "2.1.1", "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "optional": true + "dev": 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" } @@ -21620,8 +21618,7 @@ "version": "3.0.0", "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "optional": true + "dev": true }, "readdirp": { "version": "3.6.0", diff --git a/package.json b/package.json index 6c5cf27f8..edb79a525 100644 --- a/package.json +++ b/package.json @@ -157,8 +157,8 @@ "analyze": "npm run build -- --stats && webpack-bundle-analyzer build/bundle-stats.json", "analyz": "NODE_ENV=production npm_config_report=true npm run build", "dev": "npm-run-all --parallel dev:**", - "dev:server": "cross-env NODE_ENV=production nodemon --exec babel-node \"./buildserver/bundle.js\" --watch config --watch server", - "dev:build:server": "cross-env NODE_ENV=production webpack --config config/webpack.server.js", + "dev:server": "cross-env NODE_ENV=dev nodemon --exec babel-node \"./buildserver/bundle.js\" --watch config --watch server", + "dev:build:server": "cross-env NODE_ENV=dev webpack --config config/webpack.server.js", "pm2": "pm2 start pm2.json" }, "jest": { diff --git a/server/render.js b/server/render.js index 1e778d31b..7b7caf6e9 100644 --- a/server/render.js +++ b/server/render.js @@ -10,11 +10,12 @@ import App from "../src/App"; import { Route } from 'react-router-dom'; import { setDefaultMeta } from '../src/common/UrlTool' import Logger from "./log"; +import { changeHead } from './setHead' 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(); @@ -57,39 +58,47 @@ export const render = async (req,res)=>{ query: req.path, }); } - - const content = renderToString(( - - - {renderRoutes(Routes)} - {/* */} - - - )) - - 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); + if (_route) { + await changeHead(_route, _match.params) } + // 暂时不开放ssr,只修改head + // const content = renderToString(( + // + // + // {renderRoutes(Routes)} + // {/* */} + // + // + // )) + + // 暂时不开放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)=>{ - data=data.replace('
',`
${rootString}
`); + // 暂时不开放ssr,只修改head + // data=data.replace('
',`
${rootString}
`); return data; } - res.send(prepHTML(html, content)) + // 暂时不开放ssr,只修改head + // res.send(prepHTML(html, content)) + res.send(prepHTML(html, '')) store = null } diff --git a/server/setHead.js b/server/setHead.js new file mode 100644 index 000000000..d8f804a73 --- /dev/null +++ b/server/setHead.js @@ -0,0 +1,35 @@ +// 兜底方案,先改head +import { setDefaultMeta, setSeoMeta } from '../src/common/UrlTool' +import { getProjectDetailFunc, getMainInfos, getNewsDetail } from '../src/services/project' + +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 !== 404) { + let keyWords=`${params.owner},${params.projectsId},${data.author && data.author.name}`; + 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 + if (data) { + setSeoMeta(`${data.name}`, data.name, data.subTitle || '', `/zone/${params.deptId}/newdetail/${ params.id }`) + } + break; + case 'zone': + res = await getMainInfos(params.deptId); + data = res.data.data + if (data) { + setSeoMeta(`${data.name}`, data.name, data.subTitle || '', `/zone/${params.deptId}`) + } + break; + default: + break; + } +} diff --git a/src/AppConfig.js b/src/AppConfig.js index 1b161c5ac..dab676aca 100644 --- a/src/AppConfig.js +++ b/src/AppConfig.js @@ -18,14 +18,14 @@ function locationurl(list) { // TODO 开发期多个身份切换 let debugType = "" if (isDev) { - // const _search = window.location.search; - // let parsed = {}; - // if (_search) { - // parsed = queryString.parse(_search); - // } - // debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' : - // window.location.search.indexOf('debug=s') !== -1 ? 'student' : - // window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin' + const _search = window.location.search; + let parsed = {}; + if (_search) { + parsed = queryString.parse(_search); + } + debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' : + window.location.search.indexOf('debug=s') !== -1 ? 'student' : + window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin' } window._debugType = debugType; export function initAxiosInterceptors(props) { diff --git a/src/common/UrlTool.js b/src/common/UrlTool.js index ca5f963e1..1b1f645c9 100644 --- a/src/common/UrlTool.js +++ b/src/common/UrlTool.js @@ -360,7 +360,7 @@ export function setSeoMeta(keyWords, title, description, url, owner, projectId) document.querySelector(`meta[property='og:url']`).content = origin + url; document.querySelector(`meta[property='og:description']`).content = description + ' | GitLink'; document.querySelector(`meta[property='og:image:alt']`).content = description + ' | GitLink'; - document.querySelector('meta[name="Keywords"]').content= `${ keyWords },${ keyWords ? '' : 'GitLink, git, 开源, 代码托管, 项目管理, 版本控制, 代码分享, 项目协作, 协同开发平台' }` ; + document.querySelector('meta[name="Keywords"]').content= `${ keyWords }${ keyWords ? '' : 'GitLink, git, 开源, 代码托管, 项目管理, 版本控制, 代码分享, 项目协作, 协同开发平台' }` ; document.querySelector(`meta[name='description']`).content = description + ' | GitLink'; document.querySelector(`meta[name='go-import']`).content = host + url + ' git ' + origin + url; document.querySelector(`meta[name='octolytics-dimension-user_login']`).content = owner; diff --git a/src/forge/Information/Pages/newsDetail.jsx b/src/forge/Information/Pages/newsDetail.jsx index 825ba12cf..f17e1ebb0 100644 --- a/src/forge/Information/Pages/newsDetail.jsx +++ b/src/forge/Information/Pages/newsDetail.jsx @@ -8,7 +8,7 @@ import { isPhone } from 'educoder'; import { tempConfig } from '../tempInfo'; import Acce from '../Component/mobile/accessory'; import { addMeta, setSeoMeta } from 'educoder'; -// import CommentList from '../Component/comments/list' +import CommentList from '../Component/comments/list' import { connect } from 'react-redux'; import { withRouter } from "react-router"; import { setZoneDetail, setNewsDetail } from '../../../redux/actions/server'; @@ -23,9 +23,6 @@ function NewsDetail(props){ const [ commentReload, setCommentReload] = useState(undefined); const temp = props.temp; const zonedetail = props.zoneDetail || props.data; - if (__SERVER__ && detail) { - setMeta() - } useEffect(()=>{ let initialContent = undefined; @@ -50,7 +47,7 @@ function NewsDetail(props){ } if (zonedetail) { document.title= zonedetail.mainTitle; - setSeoMeta(`${zonedetail.name},`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}`) + setSeoMeta(`${zonedetail.name},`, zonedetail.name, zonedetail.subTitle, `/zone/${deptId}/newdetail/${ id }`) } } },[zonedetail,detail]) diff --git a/src/forge/Main/CoderDepot.jsx b/src/forge/Main/CoderDepot.jsx index 1ca7a0f81..5e7cf22cb 100644 --- a/src/forge/Main/CoderDepot.jsx +++ b/src/forge/Main/CoderDepot.jsx @@ -109,7 +109,7 @@ function CoderDepot(props){ useEffect(()=>{ // 设置网页标题 - if(projectDetail){ + if(projectDetail && projectDetail.project_identifier){ const { author, name, description, default_branch} = projectDetail; if(branchName && branchName !== default_branch){ // 处于某分支/标签 diff --git a/src/forge/Main/Detail.js b/src/forge/Main/Detail.js index a2e8b0fba..e1a513541 100644 --- a/src/forge/Main/Detail.js +++ b/src/forge/Main/Detail.js @@ -310,7 +310,10 @@ class Detail extends Component { if (this.props.defaultDetail) { projectdata = this.props.defaultDetail } else { - projectdata = await getProjectDetailFunc(owner, projectsId, !window.location.host).data; + const res = await getProjectDetailFunc(owner, projectsId, !window.location.host); + if (res.status === 200) { + projectdata = res.data + } } if (projectdata) { this.getDetail(projectdata) diff --git a/src/services/project.js b/src/services/project.js index aaa89b608..e9c30c58d 100644 --- a/src/services/project.js +++ b/src/services/project.js @@ -1,8 +1,15 @@ import axios from 'axios'; import { url, zoneUrl } from '../ssrUrl'; -const baseUrl = `${url}/api` -const baseZoneUrl = `${zoneUrl}/api` +let baseUrl = `${url}/api` +let baseZoneUrl = `${zoneUrl}/api` + +if (__CLIENT__) { + let settings = localStorage.chromesetting&&JSON.parse(localStorage.chromesetting); + baseUrl = settings && settings.common.main_site_url + '/api'; + baseZoneUrl = settings && settings.common.zone + '/api'; +} + // export async function getProjectFunc (owner, projectsId) { diff --git a/src/ssrUrl.js b/src/ssrUrl.js index f614ee107..4bf99bf81 100644 --- a/src/ssrUrl.js +++ b/src/ssrUrl.js @@ -1,3 +1,7 @@ -export const url = process.env.NODE_ENV === 'production' ? 'https://www.gitlink.org.cn' : 'http://172.20.32.202:4000' -export const zoneUrl = process.env.NODE_ENV === 'production' ? 'https://gateway.gitlink.org.cn' : 'http://172.20.32.202:4000' -export const host = process.env.NODE_ENV === 'production' ? 'www.gitlink.org.cn' : '172.20.32.202:4000' \ No newline at end of file +export const url = process.env.NODE_ENV === 'production' ? 'https://www.gitlink.org.cn' : 'https://testforgeplus.trustie.net' +export const zoneUrl = process.env.NODE_ENV === 'production' ? 'https://gateway.gitlink.org.cn' : 'https://testgetway.trustie.net' +export const host = process.env.NODE_ENV === 'production' ? 'www.gitlink.org.cn' : 'testforgeplus.trustie.net' + +// export const url = process.env.NODE_ENV === 'production' ? 'https://www.gitlink.org.cn' : '' +// export const zoneUrl = process.env.NODE_ENV === 'production' ? 'https://gateway.gitlink.org.cn' : '' +// export const host = process.env.NODE_ENV === 'production' ? 'www.gitlink.org.cn' : '' \ No newline at end of file