Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
center-book
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
center-book
Commits
bfe4669f
提交
bfe4669f
authored
7月 17, 2026
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor: serve admin app from admin subpath
上级
265c9f40
显示空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
80 行增加
和
79 行删除
+80
-79
.env
apps/admin/.env
+4
-6
.env.development
apps/admin/.env.development
+4
-6
index.html
apps/admin/index.html
+1
-1
package.json
apps/admin/package.json
+1
-1
main.jsx
apps/admin/src/main.jsx
+1
-1
adminPaths.js
apps/admin/src/utils/adminPaths.js
+14
-0
adminPaths.test.js
apps/admin/src/utils/adminPaths.test.js
+24
-0
axios.js
apps/admin/src/utils/axios.js
+6
-4
request.js
apps/admin/src/utils/request.js
+8
-6
vite.config.js
apps/admin/vite.config.js
+17
-54
没有找到文件。
apps/admin/.env
浏览文件 @
bfe4669f
VITE_API_URL = https://zijingebook.ezijing.com/api
VITE_API_PREFIX = /api
# VITE_API_WEBSOCKET_URL = wss://zijingebook.ezijing.com
VITE_API_WEBSOCKET_URL = wss://zijingebook.ezijing.com/ws
VITE_API_URL=https://zijingebook.ezijing.com/api/admin
VITE_API_PREFIX=/api/admin
VITE_ADMIN_API_TARGET=http://127.0.0.1:7419
VITE_API_WEBSOCKET_URL=wss://zijingebook.ezijing.com/ws
apps/admin/.env.development
浏览文件 @
bfe4669f
VITE_API_URL = https://zijingebook.ezijing.com/api
VITE_API_PREFIX = /api
# VITE_API_WEBSOCKET_URL = wss://zijingebook.ezijing.com
VITE_API_WEBSOCKET_URL = wss://zijingebook.ezijing.com/ws
VITE_API_URL=https://zijingebook.ezijing.com/api/admin
VITE_API_PREFIX=/api/admin
VITE_ADMIN_API_TARGET=http://127.0.0.1:7419
VITE_API_WEBSOCKET_URL=wss://zijingebook.ezijing.com/ws
apps/admin/index.html
浏览文件 @
bfe4669f
...
...
@@ -8,7 +8,7 @@
</head>
<body>
<div
id=
"root"
></div>
<script
src=
"
/formula-editor/dist/formula-editor.min.js"
></script>
<script
src=
"
%BASE_URL%formula-editor/dist/formula-editor.min.js"
></script>
<script
type=
"module"
src=
"/src/main.jsx"
></script>
</body>
</html>
apps/admin/package.json
浏览文件 @
bfe4669f
...
...
@@ -9,7 +9,7 @@
"build:dev"
:
"vite build --mode development"
,
"preview"
:
"vite preview"
,
"lint"
:
"eslint --ext .js,.jsx,.ts,.tsx --fix --ignore-path .gitignore ./src"
,
"test"
:
"node --test src/store/storage-import.test.mjs"
"test"
:
"node --test src/store/storage-import.test.mjs
src/utils/*.test.js
"
},
"dependencies"
:
{
"@ant-design/icons"
:
"^5.4.0"
,
...
...
apps/admin/src/main.jsx
浏览文件 @
bfe4669f
...
...
@@ -18,7 +18,7 @@ createRoot(document.getElementById('root')).render(
<
PersistGate
loading=
{
null
}
persistor=
{
persistor
}
>
<
ConfigProvider
locale=
{
zhCN
}
theme=
{
{
token
:
{
colorPrimary
:
'#ab1941'
}
}
}
>
<
App
>
<
BrowserRouter
>
<
BrowserRouter
basename=
"/admin"
>
<
MyApp
/>
</
BrowserRouter
>
</
App
>
...
...
apps/admin/src/utils/adminPaths.js
0 → 100644
浏览文件 @
bfe4669f
export
const
ADMIN_BASE_PATH
=
'/admin'
export
const
ADMIN_LOGIN_PATH
=
`
${
ADMIN_BASE_PATH
}
/login`
export
function
normalizeAdminApiPath
(
url
=
''
)
{
if
(
url
===
'/api/admin'
)
return
'/'
if
(
url
.
startsWith
(
'/api/admin/'
))
return
url
.
slice
(
'/api/admin'
.
length
)
if
(
url
===
'/api'
)
return
'/'
if
(
url
.
startsWith
(
'/api/'
))
return
url
.
slice
(
'/api'
.
length
)
return
url
}
export
function
stripAdminGatewayPrefix
(
url
=
''
)
{
return
url
.
replace
(
'/api/admin'
,
''
)
}
apps/admin/src/utils/adminPaths.test.js
0 → 100644
浏览文件 @
bfe4669f
import
test
from
'node:test'
import
assert
from
'node:assert/strict'
import
{
ADMIN_LOGIN_PATH
,
normalizeAdminApiPath
,
stripAdminGatewayPrefix
,
}
from
'./adminPaths.js'
test
(
'admin login stays under the admin base path'
,
()
=>
{
assert
.
equal
(
ADMIN_LOGIN_PATH
,
'/admin/login'
)
})
test
(
'legacy /api requests are normalized for the admin gateway'
,
()
=>
{
assert
.
equal
(
normalizeAdminApiPath
(
'/api/admin/user/login'
),
'/user/login'
)
assert
.
equal
(
normalizeAdminApiPath
(
'/api/user/login'
),
'/user/login'
)
assert
.
equal
(
normalizeAdminApiPath
(
'/user/login'
),
'/user/login'
)
})
test
(
'gateway prefix is removed before backend signature calculation'
,
()
=>
{
assert
.
equal
(
stripAdminGatewayPrefix
(
'https://zijingebook.ezijing.com/api/admin/user/login'
),
'https://zijingebook.ezijing.com/user/login'
)
})
apps/admin/src/utils/axios.js
浏览文件 @
bfe4669f
...
...
@@ -2,6 +2,7 @@ import axios from 'axios'
import
md5
from
'js-md5'
import
qs
from
'qs'
import
{
Modal
,
notification
}
from
'antd'
import
{
ADMIN_LOGIN_PATH
,
normalizeAdminApiPath
}
from
'@/utils/adminPaths.js'
// import { sm4 as Sm4js } from 'evit-gm-crypt'
// const sm4 = new Sm4js({
...
...
@@ -20,7 +21,7 @@ function showLoginModal() {
title
:
'登录状态已过期,请重新登录'
,
onOk
()
{
localStorage
.
removeItem
(
'kiwi.gpt.token'
)
location
.
href
=
'/login'
location
.
href
=
ADMIN_LOGIN_PATH
},
})
}
...
...
@@ -31,14 +32,15 @@ function alphabeticalSort(a, b) {
}
const
httpRequest
=
axios
.
create
({
// baseURL: import.meta.env.VITE_API_PREFIX,
// timeout: 60000,
baseURL
:
import
.
meta
.
env
.
VITE_API_PREFIX
,
withCredentials
:
true
,
})
// 请求拦截器
httpRequest
.
interceptors
.
request
.
use
(
(
config
)
=>
{
config
.
url
=
normalizeAdminApiPath
(
config
.
url
)
const
token
=
getToken
()
// 应用设置
const
appId
=
'TzEU5jPk2tu80266'
...
...
@@ -85,7 +87,7 @@ httpRequest.interceptors.response.use(
(
response
)
=>
{
const
{
data
}
=
response
if
(
data
.
code
===
401
||
data
.
code
===
403
)
{
if
(
location
.
pathname
!==
'/login'
)
{
if
(
location
.
pathname
!==
ADMIN_LOGIN_PATH
)
{
showLoginModal
()
}
return
Promise
.
reject
(
data
)
...
...
apps/admin/src/utils/request.js
浏览文件 @
bfe4669f
...
...
@@ -4,6 +4,7 @@ import { message, Modal, notification } from 'antd'
import
md5
from
'js-md5'
import
{
get
}
from
'lodash-es'
import
{
sortObjASCII
}
from
'@/utils/common.js'
import
{
ADMIN_LOGIN_PATH
,
normalizeAdminApiPath
,
stripAdminGatewayPrefix
}
from
'@/utils/adminPaths.js'
import
qs
from
'qs'
// import { sm4 as Sm4js } from 'evit-gm-crypt'
...
...
@@ -38,6 +39,8 @@ function getToken() {
// 请求拦截器
axios
.
interceptors
.
request
.
use
(
(
config
)
=>
{
config
.
url
=
normalizeAdminApiPath
(
config
.
url
)
// 登录流程控制中,根据本地是否存在token判断用户的登录情况
// 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token
// 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码
...
...
@@ -68,8 +71,7 @@ axios.interceptors.request.use(
if
(
config
.
url
.
indexOf
(
'.tiangong.cn'
)
>
-
1
)
{
s
=
config
.
url
}
else
{
s
=
import
.
meta
.
env
.
VITE_API_URL
+
config
.
url
s
=
s
.
replace
(
'/api'
,
''
)
s
=
stripAdminGatewayPrefix
(
import
.
meta
.
env
.
VITE_API_URL
+
config
.
url
)
}
signData
.
url
=
decodeURIComponent
(
s
)
// signData.url = 'http: //zijing.com/index.php/user/user/getList'
...
...
@@ -130,7 +132,7 @@ axios.interceptors.response.use(
if
(
code
===
401
||
code
===
403
)
{
if
(
!
axios
.
errorNotified
)
{
axios
.
errorNotified
=
true
// 添加标志,表示通知已经弹出
if
(
pathname
===
'/login'
)
{
if
(
pathname
===
ADMIN_LOGIN_PATH
)
{
return
}
Modal
.
warning
({
...
...
@@ -138,7 +140,7 @@ axios.interceptors.response.use(
// content: '请重新登录',
onOk
()
{
localStorage
.
removeItem
(
'kiwi.gpt.token'
)
window
.
location
.
pathname
=
'/login'
window
.
location
.
pathname
=
ADMIN_LOGIN_PATH
},
})
cancelPending
(
response
.
config
)
// 取消后续请求
...
...
@@ -163,7 +165,7 @@ axios.interceptors.response.use(
content
:
'请重新登录'
,
onOk
()
{
localStorage
.
removeItem
(
'kiwi.gpt.token'
)
window
.
location
.
href
=
'/login'
window
.
location
.
href
=
ADMIN_LOGIN_PATH
},
})
}
...
...
@@ -178,7 +180,7 @@ axios.interceptors.response.use(
content
:
'请重新登录'
,
onOk
()
{
localStorage
.
removeItem
(
'kiwi.gpt.token'
)
window
.
location
.
href
=
'/login'
window
.
location
.
href
=
ADMIN_LOGIN_PATH
},
})
}
...
...
apps/admin/vite.config.js
浏览文件 @
bfe4669f
import
{
fileURLToPath
,
URL
}
from
'node:url'
import
{
defineConfig
}
from
'vite'
import
{
defineConfig
,
loadEnv
}
from
'vite'
import
react
from
'@vitejs/plugin-react'
import
mkcert
from
'vite-plugin-mkcert'
// https://vitejs.dev/config/
export
default
defineConfig
(()
=>
{
export
default
defineConfig
(({
mode
})
=>
{
const
env
=
loadEnv
(
mode
,
process
.
cwd
(),
''
)
const
adminApiTarget
=
env
.
VITE_ADMIN_API_TARGET
||
'http://127.0.0.1:7419'
return
{
base
:
'/admin/'
,
plugins
:
[
react
(),
mkcert
()],
server
:
{
open
:
true
,
open
:
'/admin/'
,
host
:
'dev.ezijing.com'
,
port
:
5174
,
strictPort
:
true
,
proxy
:
{
// '/api/tiangong': {
// target: 'https://api.singularity-ai.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/tiangong/, ''),
// },
// '/api/deepseek': {
// target: 'https://api.deepseek.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/deepseek/, ''),
// },
// '/api/qwen': {
// target: 'https://dashscope.aliyuncs.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/qwen/, ''),
// },
// '/api/qianfan': {
// target: 'https://aip.baidubce.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/qianfan/, ''),
// },
// '/api/wenku': {
// target: 'https://wenchain.baidu.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/wenku/, '/'),
// },
// '/api/qianfan': {
// target: 'https://qianfan.baidubce.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/qianfan/, ''),
// },
// '/api/volcano': {
// target: 'https://ark.cn-beijing.volces.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/volcano/, ''),
// },
// '/api/xiling': {
// target: 'https://open.xiling.baidu.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/xiling/, ''),
// },
// '/api/volcano_file': {
// target: 'https://ark-content-generation-cn-beijing.tos-cn-beijing.volces.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/volcano_file/, ''),
// },
'/api'
:
{
// target: 'http://localhost:7419',
target
:
'https://zijingebook.ezijing.com'
,
'/api/admin'
:
{
target
:
adminApiTarget
,
changeOrigin
:
true
,
secure
:
false
,
rewrite
:
path
=>
path
.
replace
(
/^
\/
api
\/
admin/
,
''
),
},
},
},
build
:
{
outDir
:
'../../dist/admin'
,
emptyOutDir
:
true
,
},
resolve
:
{
alias
:
{
...
...
@@ -72,9 +37,7 @@ export default defineConfig(() => {
},
css
:
{
preprocessorOptions
:
{
less
:
{
javascriptEnabled
:
true
,
},
less
:
{
javascriptEnabled
:
true
},
},
},
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论