feat: support for parametrizing the base path #335 #836 #800

This commit is contained in:
shuai
2024-04-23 10:22:23 +08:00
17 changed files with 211 additions and 84 deletions
+3 -2
View File
@@ -1,4 +1,5 @@
TSC_COMPILE_ON_ERROR=true
ESLINT_NO_DEV_ERRORS=true
PUBLIC_URL = /
REACT_APP_API_URL = /
PUBLIC_URL=/
REACT_APP_API_URL=/
REACT_APP_BASE_URL=/test
+2 -1
View File
@@ -5,7 +5,7 @@
"homepage": "/",
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"build": "node ./scripts/env.js && react-app-rewired build",
"lint": "eslint . --cache --fix --ext .ts,.tsx",
"prettier": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}' --config ./.prettierrc.json",
"pre-install": "node ./scripts/preinstall.js && pnpm install",
@@ -76,6 +76,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"humps": "^2.0.1",
"husky": "^8.0.1",
"js-yaml": "^4.1.0",
"lint-staged": "^13.2.3",
"postcss": "^8.0.0",
"prettier": "^3.1.0",
+98 -33
View File
@@ -1,20 +1,3 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
lockfileVersion: '6.0'
settings:
@@ -200,6 +183,9 @@ importers:
husky:
specifier: ^8.0.1
version: 8.0.1
js-yaml:
specifier: ^4.1.0
version: 4.1.0
lint-staged:
specifier: ^13.2.3
version: 13.3.0
@@ -231,6 +217,64 @@ importers:
specifier: ^0.8.0
version: 0.8.0
src/plugins/captcha-basic:
devDependencies:
'@typescript-eslint/eslint-plugin':
specifier: ^6.0.0
version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.3.2)
'@typescript-eslint/parser':
specifier: ^6.0.0
version: 6.11.0(eslint@8.53.0)(typescript@5.3.2)
'@vitejs/plugin-react-swc':
specifier: ^3.3.2
version: 3.5.0(vite@4.5.0)
eslint:
specifier: ^8.45.0
version: 8.53.0
eslint-plugin-react-hooks:
specifier: ^4.6.0
version: 4.6.0(eslint@8.53.0)
eslint-plugin-react-refresh:
specifier: ^0.4.3
version: 0.4.5(eslint@8.53.0)
typescript:
specifier: ^5.0.2
version: 5.3.2
vite:
specifier: ^4.4.5
version: 4.5.0(@types/node@16.11.59)(sass@1.54.9)
src/plugins/captcha-google-v2:
dependencies:
react-google-recaptcha:
specifier: ^3.1.0
version: 3.1.0(react@18.2.0)
devDependencies:
'@typescript-eslint/eslint-plugin':
specifier: ^6.0.0
version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.3.2)
'@typescript-eslint/parser':
specifier: ^6.0.0
version: 6.11.0(eslint@8.53.0)(typescript@5.3.2)
'@vitejs/plugin-react-swc':
specifier: ^3.3.2
version: 3.5.0(vite@4.5.0)
eslint:
specifier: ^8.45.0
version: 8.53.0
eslint-plugin-react-hooks:
specifier: ^4.6.0
version: 4.6.0(eslint@8.53.0)
eslint-plugin-react-refresh:
specifier: ^0.4.3
version: 0.4.5(eslint@8.53.0)
typescript:
specifier: ^5.0.2
version: 5.3.2
vite:
specifier: ^4.4.5
version: 4.5.0(@types/node@16.11.59)(sass@1.54.9)
src/plugins/editor-chart:
dependencies:
mermaid:
@@ -3072,7 +3116,7 @@ packages:
resolution: {integrity: sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==}
dependencies:
'@types/estree': 1.0.0
'@types/json-schema': 7.0.13
'@types/json-schema': 7.0.15
/@types/eslint@8.56.2:
resolution: {integrity: sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==}
@@ -3149,12 +3193,8 @@ packages:
pretty-format: 27.5.1
dev: true
/@types/json-schema@7.0.13:
resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==}
/@types/json-schema@7.0.15:
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
dev: true
/@types/json5@0.0.29:
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
@@ -3594,7 +3634,7 @@ packages:
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
'@types/json-schema': 7.0.13
'@types/json-schema': 7.0.15
'@typescript-eslint/scope-manager': 5.38.0
'@typescript-eslint/types': 5.38.0
'@typescript-eslint/typescript-estree': 5.38.0(typescript@4.9.5)
@@ -3612,7 +3652,7 @@ packages:
eslint: ^7.0.0 || ^8.0.0
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
'@types/json-schema': 7.0.13
'@types/json-schema': 7.0.15
'@types/semver': 7.5.5
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/types': 6.11.0
@@ -3631,7 +3671,7 @@ packages:
eslint: ^7.0.0 || ^8.0.0
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
'@types/json-schema': 7.0.13
'@types/json-schema': 7.0.15
'@types/semver': 7.5.5
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/types': 6.11.0
@@ -3950,7 +3990,6 @@ packages:
resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: true
/acorn@8.8.0:
resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==}
@@ -6954,7 +6993,7 @@ packages:
optional: true
dependencies:
'@babel/code-frame': 7.18.6
'@types/json-schema': 7.0.13
'@types/json-schema': 7.0.15
chalk: 4.1.2
chokidar: 3.5.3
cosmiconfig: 6.0.0
@@ -7262,6 +7301,12 @@ packages:
resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==}
dev: false
/hoist-non-react-statics@3.3.2:
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
dependencies:
react-is: 16.13.1
dev: false
/hoopy@0.1.4:
resolution: {integrity: sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==}
engines: {node: '>= 6.0.0'}
@@ -8421,7 +8466,7 @@ packages:
optional: true
dependencies:
abab: 2.0.6
acorn: 8.10.0
acorn: 8.11.3
acorn-globals: 6.0.0
cssom: 0.4.4
cssstyle: 2.3.0
@@ -10282,6 +10327,16 @@ packages:
semver: 5.7.1
dev: true
/react-async-script@1.2.0(react@18.2.0):
resolution: {integrity: sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==}
peerDependencies:
react: '>=16.4.1'
dependencies:
hoist-non-react-statics: 3.3.2
prop-types: 15.8.1
react: 18.2.0
dev: false
/react-bootstrap@2.10.0(@types/react@18.0.20)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-87gRP69VAfeU2yKgp8RI3HvzhPNrnYIV2QNranYXataz3ef+k7OhvKGGdxQLQfUsQ2RTmlY66tn4pdFrZ94hNg==}
peerDependencies:
@@ -10366,6 +10421,16 @@ packages:
resolution: {integrity: sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==}
dev: false
/react-google-recaptcha@3.1.0(react@18.2.0):
resolution: {integrity: sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==}
peerDependencies:
react: '>=16.4.1'
dependencies:
prop-types: 15.8.1
react: 18.2.0
react-async-script: 1.2.0(react@18.2.0)
dev: false
/react-helmet-async@1.3.0(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==}
peerDependencies:
@@ -10947,7 +11012,7 @@ packages:
resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==}
engines: {node: '>= 8.9.0'}
dependencies:
'@types/json-schema': 7.0.13
'@types/json-schema': 7.0.15
ajv: 6.12.6
ajv-keywords: 3.5.2(ajv@6.12.6)
@@ -10955,7 +11020,7 @@ packages:
resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==}
engines: {node: '>= 8.9.0'}
dependencies:
'@types/json-schema': 7.0.13
'@types/json-schema': 7.0.15
ajv: 6.12.6
ajv-keywords: 3.5.2(ajv@6.12.6)
@@ -10963,7 +11028,7 @@ packages:
resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==}
engines: {node: '>= 10.13.0'}
dependencies:
'@types/json-schema': 7.0.13
'@types/json-schema': 7.0.15
ajv: 6.12.6
ajv-keywords: 3.5.2(ajv@6.12.6)
@@ -10980,7 +11045,7 @@ packages:
resolution: {integrity: sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==}
engines: {node: '>= 12.13.0'}
dependencies:
'@types/json-schema': 7.0.13
'@types/json-schema': 7.0.15
ajv: 8.11.0
ajv-formats: 2.1.1(ajv@8.11.0)
ajv-keywords: 5.1.0(ajv@8.11.0)
@@ -11713,7 +11778,7 @@ packages:
hasBin: true
dependencies:
'@jridgewell/source-map': 0.3.2
acorn: 8.10.0
acorn: 8.11.3
commander: 2.20.3
source-map-support: 0.5.21
+21
View File
@@ -0,0 +1,21 @@
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
const configFilePath = path.resolve(__dirname, '../../configs/config.yaml');
const envFilePath = path.resolve(__dirname, '../.env.production');
// Read config.yaml file
const config = yaml.load(fs.readFileSync(configFilePath, 'utf8'));
// Generate .env file content
let envContent = 'TSC_COMPILE_ON_ERROR=true\nESLINT_NO_DEV_ERRORS=true\n';
for (const key in config.ui) {
const value = config.ui[key];
envContent += `${key.toUpperCase()}=${value}\n`;
}
// Write .env file
fs.writeFileSync(envFilePath, envContent);
console.log(`Generated ${envFilePath}`);
+3 -1
View File
@@ -25,7 +25,9 @@ import '@/utils/pluginKit';
import routes from '@/router';
function App() {
const router = createBrowserRouter(routes);
const router = createBrowserRouter(routes, {
basename: process.env.REACT_APP_BASE_URL,
});
return <RouterProvider router={router} />;
}
+26 -23
View File
@@ -24,7 +24,6 @@ import {
Nav,
Form,
FormControl,
Button,
Col,
} from 'react-bootstrap';
import { useTranslation } from 'react-i18next';
@@ -175,24 +174,26 @@ const Header: FC = () => {
/>
) : (
<>
<Button
variant="link"
className={classnames('me-2', {
<Link
className={classnames('me-2 btn btn-link', {
'link-light': navbarStyle === 'theme-colored',
'link-primary': navbarStyle !== 'theme-colored',
})}
onClick={() => floppyNavigation.storageLoginRedirect()}
href={userCenter.getLoginUrl()}>
to={userCenter.getLoginUrl()}>
{t('btns.login')}
</Button>
</Link>
{loginSetting.allow_new_registrations && (
<Button
variant={
navbarStyle === 'theme-colored' ? 'light' : 'primary'
}
href={userCenter.getSignUpUrl()}>
<Link
className={classnames(
'btn',
navbarStyle === 'theme-colored'
? 'btn-light'
: 'btn-primary',
)}
to={userCenter.getSignUpUrl()}>
{t('btns.signup')}
</Button>
</Link>
)}
</>
)}
@@ -249,24 +250,26 @@ const Header: FC = () => {
</Nav>
) : (
<>
<Button
variant="link"
className={classnames('me-2', {
<Link
className={classnames('me-2 btn btn-link', {
'link-light': navbarStyle === 'theme-colored',
'link-primary': navbarStyle !== 'theme-colored',
})}
onClick={() => floppyNavigation.storageLoginRedirect()}
href={userCenter.getLoginUrl()}>
to={userCenter.getLoginUrl()}>
{t('btns.login')}
</Button>
</Link>
{loginSetting.allow_new_registrations && (
<Button
variant={
navbarStyle === 'theme-colored' ? 'light' : 'primary'
}
href={userCenter.getSignUpUrl()}>
<Link
className={classnames(
'btn',
navbarStyle === 'theme-colored'
? 'btn-light'
: 'btn-primary',
)}
to={userCenter.getSignUpUrl()}>
{t('btns.signup')}
</Button>
</Link>
)}
</>
)}
+6 -2
View File
@@ -20,6 +20,7 @@
import { FC, useEffect, useLayoutEffect } from 'react';
import { Helmet } from 'react-helmet-async';
import { REACT_BASE_PATH } from '@/router/alias';
import { brandingStore, pageTagStore, siteInfoStore } from '@/stores';
import { getCurrentLang } from '@/utils/localize';
@@ -76,7 +77,7 @@ const Index: FC = () => {
<link
rel="icon"
type="image/png"
href={favicon || square_icon || '/favicon.ico'}
href={favicon || square_icon || `${REACT_BASE_PATH}/favicon.ico`}
/>
<link rel="icon" type="image/png" sizes="192x192" href={square_icon} />
<link rel="apple-touch-icon" type="image/png" href={square_icon} />
@@ -84,7 +85,10 @@ const Index: FC = () => {
{keywords && <meta name="keywords" content={keywords} />}
{description && <meta name="description" content={description} />}
{doInsertCustomCSS && (
<link rel="stylesheet" href={`${process.env.PUBLIC_URL}/custom.css`} />
<link
rel="stylesheet"
href={`${process.env.PUBLIC_URL}${REACT_BASE_PATH}/custom.css`}
/>
)}
</Helmet>
);
+3 -2
View File
@@ -24,6 +24,7 @@ import { useTranslation } from 'react-i18next';
import { FacebookShareButton, TwitterShareButton } from 'next-share';
import copy from 'copy-to-clipboard';
import { BASE_ORIGIN } from '@/router/alias';
import { loggedUserInfoStore } from '@/stores';
interface IProps {
@@ -42,8 +43,8 @@ const Index: FC<IProps> = ({ type, qid, aid, title }) => {
const { t } = useTranslation();
let baseUrl =
type === 'question'
? `${window.location.origin}/questions/${qid}`
: `${window.location.origin}/questions/${qid}/${aid}`;
? `${BASE_ORIGIN}/questions/${qid}`
: `${BASE_ORIGIN}/questions/${qid}/${aid}`;
if (user.id) {
baseUrl = `${baseUrl}?shareUserId=${user.username}`;
}
+4 -4
View File
@@ -19,7 +19,7 @@
import { FC } from 'react';
import { Form, Table, Stack } from 'react-bootstrap';
import { useSearchParams } from 'react-router-dom';
import { useSearchParams, Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import classNames from 'classnames';
@@ -110,8 +110,8 @@ const Answers: FC = () => {
return (
<tr key={li.id}>
<td>
<a
href={pathFactory.answerLanding({
<Link
to={pathFactory.answerLanding({
questionId: li.question_id,
slugTitle: li.question_info.url_title,
answerId: li.id,
@@ -120,7 +120,7 @@ const Answers: FC = () => {
className="text-break text-wrap"
rel="noreferrer">
{li.question_info.title}
</a>
</Link>
{li.accepted === 2 && (
<Icon
name="check-circle-fill"
+3 -3
View File
@@ -109,13 +109,13 @@ const Questions: FC = () => {
return (
<tr key={li.id}>
<td>
<a
href={pathFactory.questionLanding(li.id, li.url_title)}
<Link
to={pathFactory.questionLanding(li.id, li.url_title)}
target="_blank"
className="text-break text-wrap"
rel="noreferrer">
{li.title}
</a>
</Link>
{li.accepted_answer_id > 0 && (
<Icon
name="check-circle-fill"
@@ -21,6 +21,7 @@ import { FC } from 'react';
import { Button } from 'react-bootstrap';
import { useTranslation, Trans } from 'react-i18next';
import { REACT_BASE_PATH } from '@/router/alias';
import Progress from '../Progress';
interface Props {
@@ -37,15 +38,18 @@ const Index: FC<Props> = ({ visible, siteUrl = '' }) => {
<p>
<Trans i18nKey="install.ready_description">
If you ever feel like changing more settings, visit
<a href={`${siteUrl}/users/login`}> admin section</a>; find it in the
site menu.
<a href={`${siteUrl}${REACT_BASE_PATH}/users/login`}>
{' '}
admin section
</a>
; find it in the site menu.
</Trans>
</p>
<p>{t('good_luck')}</p>
<div className="d-flex align-items-center justify-content-between">
<Progress step={5} />
<Button href={siteUrl}>{t('done')}</Button>
<Button href={`${siteUrl}${REACT_BASE_PATH}`}>{t('done')}</Button>
</div>
</div>
);
+2 -1
View File
@@ -31,6 +31,7 @@ import {
} from '@/services';
import { Storage, handleFormError, scrollToDocTop } from '@/utils';
import { CURRENT_LANG_STORAGE_KEY } from '@/common/constants';
import { BASE_ORIGIN } from '@/router/alias';
import {
FirstStep,
@@ -94,7 +95,7 @@ const Index: FC = () => {
errorMsg: '',
},
site_url: {
value: window.location.origin,
value: BASE_ORIGIN,
isInvalid: false,
errorMsg: '',
},
@@ -20,6 +20,7 @@
import { memo } from 'react';
import { Accordion, ListGroup } from 'react-bootstrap';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { Icon } from '@/components';
import { pathFactory } from '@/router/pathFactory';
@@ -45,10 +46,10 @@ const SearchQuestion = ({ similarQuestions }) => {
return (
<ListGroup.Item
action
as="a"
as={Link}
className="link-dark text-wrap text-break"
key={item.id}
href={pathFactory.questionLanding(item.id, item.url_title)}
to={pathFactory.questionLanding(item.id, item.url_title)}
target="_blank">
<span
className={`${
+4 -4
View File
@@ -19,7 +19,7 @@
import React, { useState, useRef, useEffect, useLayoutEffect } from 'react';
import { Row, Col, Form, Button, Card } from 'react-bootstrap';
import { useParams, useNavigate } from 'react-router-dom';
import { useParams, useNavigate, Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import dayjs from 'dayjs';
@@ -217,12 +217,12 @@ const Index = () => {
<h3 className="mb-4">{t('title')}</h3>
<Row>
<Col className="page-main flex-auto">
<a
href={pathFactory.questionLanding(qid, data?.question.url_title)}
<Link
to={pathFactory.questionLanding(qid, data?.question.url_title)}
target="_blank"
rel="noreferrer">
<h5 className="mb-3">{data?.question.title}</h5>
</a>
</Link>
<div className="question-content-wrap">
<div
+2 -2
View File
@@ -25,7 +25,7 @@ import { usePageTags } from '@/hooks';
import { logout } from '@/services';
import { loggedUserInfoStore } from '@/stores';
import Storage from '@/utils/storage';
import { RouteAlias } from '@/router/alias';
import { RouteAlias, BASE_ORIGIN } from '@/router/alias';
import { REDIRECT_PATH_STORAGE_KEY } from '@/common/constants';
const Index = () => {
@@ -43,7 +43,7 @@ const Index = () => {
const redirect =
Storage.get(REDIRECT_PATH_STORAGE_KEY) || RouteAlias.home;
Storage.remove(REDIRECT_PATH_STORAGE_KEY);
window.location.replace(`${window.location.origin}${redirect}`);
window.location.replace(`${BASE_ORIGIN}${redirect}`);
});
}
// auto height of container
+2
View File
@@ -16,6 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
export const REACT_BASE_PATH = process.env.REACT_APP_BASE_URL || '';
export const BASE_ORIGIN = `${window.location.origin}${REACT_BASE_PATH}`;
export const RouteAlias = {
home: '/',
+22 -1
View File
@@ -19,7 +19,7 @@
import type { NavigateFunction } from 'react-router-dom';
import { RouteAlias } from '@/router/alias';
import { RouteAlias, REACT_BASE_PATH } from '@/router/alias';
import Storage from '@/utils/storage';
import { REDIRECT_PATH_STORAGE_KEY } from '@/common/constants';
import { getLoginUrl } from '@/utils/userCenter';
@@ -133,10 +133,31 @@ const navigate = (to: string | number, config: NavigateConfig = {}) => {
handler = 'replace';
}
if (handler === 'href') {
if (
to.startsWith('/') &&
!to.startsWith('//') &&
!to.startsWith(REACT_BASE_PATH)
) {
to = `${REACT_BASE_PATH}${to}`;
}
window.location.href = to;
} else if (handler === 'replace') {
if (
to.startsWith('/') &&
!to.startsWith('//') &&
!to.startsWith(REACT_BASE_PATH)
) {
to = `${REACT_BASE_PATH}${to}`;
}
window.location.replace(to);
} else if (typeof handler === 'function') {
if (to === '/test') {
to = '/';
}
if (to !== '/test' && to.startsWith('/test')) {
to = to.replace('/test', '');
}
handler(to, config.options);
}
}