Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
B
boyueCEnd
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
游洁
boyueCEnd
Commits
befc0b59
Commit
befc0b59
authored
Dec 09, 2025
by
罗超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
更新国际化,守卫,加载逻辑
parent
15c0667c
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
400 additions
and
171 deletions
+400
-171
index.html
index.html
+1
-1
package.json
package.json
+1
-1
App.vue
src/App.vue
+2
-5
OtaRequest.ts
src/api/OtaRequest.ts
+24
-1
LanguageSwitcher.vue
src/components/common/LanguageSwitcher.vue
+1
-1
AccordionGallery.vue
src/components/page-builder/AccordionGallery.vue
+1
-1
en.ts
src/i18n/locales/en.ts
+1
-0
vi.ts
src/i18n/locales/vi.ts
+1
-0
zh-CN.ts
src/i18n/locales/zh-CN.ts
+1
-0
zh-TW.ts
src/i18n/locales/zh-TW.ts
+1
-0
HeaderTopBar.vue
src/layouts/components/HeaderTopBar.vue
+2
-2
guards.ts
src/router/guards.ts
+15
-19
index.ts
src/router/index.ts
+22
-22
systemConfig.ts
src/stores/systemConfig.ts
+189
-56
router.d.ts
src/types/router.d.ts
+7
-0
pageTranslation.ts
src/utils/pageTranslation.ts
+54
-13
Login.vue
src/views/auth/Login.vue
+21
-16
header.vue
src/views/auth/components/header.vue
+2
-2
registerSuccess.vue
src/views/auth/components/registerSuccess.vue
+1
-1
forgePassword.vue
src/views/auth/forgePassword.vue
+2
-2
index.vue
src/views/home/index.vue
+28
-1
accountCenter.vue
src/views/personalCenter/accountCenter.vue
+4
-8
account.vue
src/views/personalCenter/accountPage/account.vue
+4
-4
editEmail.vue
src/views/personalCenter/accountPage/editEmail.vue
+2
-2
perForgePassword.vue
src/views/personalCenter/accountPage/perForgePassword.vue
+3
-3
resetPassword.vue
src/views/personalCenter/accountPage/resetPassword.vue
+2
-2
LeftView.vue
src/views/personalCenter/components/LeftView.vue
+2
-2
index.vue
src/views/personalCenter/index.vue
+6
-6
No files found.
index.html
View file @
befc0b59
...
...
@@ -7,7 +7,7 @@
<script
src=
"https://unpkg.com/vue@3/dist/vue.global.js"
></script>
<link
rel=
"stylesheet"
href=
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
>
<meta
http-equiv=
"Cross-Origin-Opener-Policy"
content=
"same-origin-allow-popups"
>
<title>
C-end
</title>
<title></title>
</head>
<body>
<div
id=
"app"
></div>
...
...
package.json
View file @
befc0b59
{
"name"
:
"
C-
end
"
,
"name"
:
"
boyuec
end
"
,
"version"
:
"0.0.1"
,
"private"
:
true
,
"type"
:
"module"
,
...
...
src/App.vue
View file @
befc0b59
<
script
setup
lang=
"ts"
>
import
{
RouterView
,
useRoute
}
from
'vue-router'
import
{
computed
,
watch
,
onMounted
,
ref
}
from
'vue'
import
{
watch
,
onMounted
}
from
'vue'
import
{
useI18n
}
from
'vue-i18n'
import
{
ConfigProvider
}
from
'@arco-design/web-vue'
import
LanguageSwitcher
from
'./components/common/LanguageSwitcher.vue'
import
{
configureArcoLocale
,
globalArcoLocale
}
from
'./i18n/arco'
import
{
useUserStore
}
from
'./stores/user'
import
{
useSystemConfigStore
}
from
'./stores/systemConfig'
import
{
loadThemeFromConfig
}
from
'./utils/themeUtils'
const
route
=
useRoute
()
const
{
t
,
locale
}
=
useI18n
()
const
useUser
=
useUserStore
()
const
systemConfigStore
=
useSystemConfigStore
()
// 监听语言变化,更新 Arco Design 国际化
...
...
@@ -28,7 +25,7 @@ watch(
()
=>
route
.
meta
.
title
,
(
title
)
=>
{
if
(
title
&&
typeof
title
===
'string'
)
{
document
.
title
=
`
${
t
(
title
)}
-
${
t
(
'common.systemName'
)
}
`
document
.
title
=
`
${
t
(
title
)}
-
${
systemConfigStore
.
config
?.
webSiteName
||
''
}
`
}
},
{ immediate: true }
...
...
src/api/OtaRequest.ts
View file @
befc0b59
...
...
@@ -22,10 +22,33 @@ const service = axios.create({
// 请求拦截器:自动加 token 或临时令牌
service
.
interceptors
.
request
.
use
(
config
=>
{
async
config
=>
{
const
userStore
=
useUserStore
();
const
token
=
userStore
.
getUserToken
;
const
systemConfigStore
=
useSystemConfigStore
();
// 如果是初始化接口本身,直接放行(避免循环等待)
const
isInitRequest
=
config
.
url
?.
includes
(
'/tenant-confing-by-domain'
)
// 等待初始化完成(如果是新用户且正在初始化)
// 对于有缓存的用户(isInitialized === true),不需要等待
if
(
!
isInitRequest
&&
!
systemConfigStore
.
isInitialized
)
{
// 如果正在初始化,等待完成(最多等待 5 秒,避免无限等待)
if
(
systemConfigStore
.
isLoading
&&
systemConfigStore
.
initPromise
)
{
try
{
await
Promise
.
race
([
systemConfigStore
.
initPromise
,
new
Promise
((
_
,
reject
)
=>
setTimeout
(()
=>
reject
(
new
Error
(
'Init timeout'
)),
5000
))
])
}
catch
(
error
)
{
// 初始化失败或超时,但继续请求(可能某些接口不需要 tenantId)
console
.
warn
(
'System config initialization failed or timeout, continuing request:'
,
error
)
}
}
// 如果未初始化且未开始初始化,不等待,直接继续
// tenantId 可能为空,但不会阻塞请求
}
if
(
systemConfigStore
.
groupId
>
0
)
{
config
.
headers
[
'x-user-group'
]
=
systemConfigStore
.
groupId
;
}
...
...
src/components/common/LanguageSwitcher.vue
View file @
befc0b59
...
...
@@ -97,7 +97,7 @@ const updatePageTitle = () => {
case
'/billing'
:
titleKey
=
'billing.title'
break
case
'/account'
:
case
'/
personalCenter/accountCenter/
account'
:
titleKey
=
'account.title'
break
}
...
...
src/components/page-builder/AccordionGallery.vue
View file @
befc0b59
...
...
@@ -73,7 +73,7 @@
type=
"primary"
@
click
.
stop=
"handleClick(item)"
>
查看更多
{{
$t
(
'common.more'
)
}}
</a-button>
</div>
</transition>
...
...
src/i18n/locales/en.ts
View file @
befc0b59
...
...
@@ -108,6 +108,7 @@ export default {
chinese
:
'简体中文'
,
english
:
'English'
,
systemName
:
'C-end'
,
more
:
'View More'
},
header
:
{
destinations
:
'Destinations'
,
...
...
src/i18n/locales/vi.ts
View file @
befc0b59
...
...
@@ -108,6 +108,7 @@ export default {
chinese
:
'简体中文'
,
english
:
'English'
,
systemName
:
'C-end'
,
more
:
'Xem thêm'
},
header
:
{
destinations
:
'Điểm đến'
,
...
...
src/i18n/locales/zh-CN.ts
View file @
befc0b59
...
...
@@ -108,6 +108,7 @@ export default {
chinese
:
'简体中文'
,
english
:
'English'
,
systemName
:
'C-end'
,
more
:
'查看更多'
},
header
:
{
destinations
:
'目的地'
,
...
...
src/i18n/locales/zh-TW.ts
View file @
befc0b59
...
...
@@ -108,6 +108,7 @@ export default {
chinese
:
'繁體中文'
,
english
:
'English'
,
systemName
:
'C-end'
,
more
:
'检索更多'
},
header
:
{
destinations
:
'目的地'
,
...
...
src/layouts/components/HeaderTopBar.vue
View file @
befc0b59
...
...
@@ -157,11 +157,11 @@ const handleGoLogin = () => {
}
const
handleGoProfile
=
()
=>
{
goPage
(
'/myOrder'
)
goPage
(
'/
personalCenter/
myOrder'
)
}
const
handleGoHome
=
()
=>
{
goPage
(
'/
home
'
)
goPage
(
'/'
)
}
<
/script
>
...
...
src/router/guards.ts
View file @
befc0b59
import
type
{
NavigationGuardNext
,
RouteLocationNormalized
}
from
'vue-router'
import
{
useUserStore
}
from
'@/stores/user'
// 白名单路由(不需要登录即可访问)
const
whiteList
=
[
'/login'
,
'/register'
,
'/forgePassword'
,
'/'
,
'/home'
]
const
whiteListRegex
=
[
/
\/
oa
\/
/
]
/**
* 路由权限守卫
* 通过路由 meta.requiresAuth 标识是否需要 token 验证
* 如果 requiresAuth 为 true,则检查用户是否已登录
*/
export
const
createPermissionGuard
=
(
to
:
RouteLocationNormalized
,
from
:
RouteLocationNormalized
,
_
from
:
RouteLocationNormalized
,
next
:
NavigationGuardNext
,
)
=>
{
const
userStore
=
useUserStore
()
// 检查是否是白名单路由
if
(
whiteList
.
includes
(
to
.
path
))
{
next
()
return
}
// 检查所有匹配的路由记录(包括父路由和子路由)是否需要认证
const
requiresAuth
=
to
.
matched
.
some
(
record
=>
record
.
meta
.
requiresAuth
===
true
)
// 检查是否是白名单正则路由
if
(
whiteListRegex
.
some
((
regex
)
=>
regex
.
test
(
to
.
path
)))
{
next
()
if
(
requiresAuth
&&
!
userStore
.
getUserToken
)
{
next
({
path
:
'/login'
,
query
:
{
redirect
:
to
.
fullPath
}
})
return
}
// 检查用户是否登录
// if (!userStore.getUserToken) {
// next('/login')
// return
// }
next
()
}
src/router/index.ts
View file @
befc0b59
...
...
@@ -7,69 +7,69 @@ const router = createRouter({
routes
:
[
{
path
:
'/'
,
redirect
:
'
/home
'
,
redirect
:
''
,
component
:
()
=>
import
(
'../layouts/HomeLayout.vue'
),
children
:
[
{
path
:
'/
home
'
,
path
:
'/'
,
name
:
'home'
,
meta
:
{
title
:
'page.home'
},
component
:
()
=>
import
(
'../views/home/index.vue'
)
},
{
path
:
'/personalCenter'
,
meta
:
{
title
:
"page.profile"
},
meta
:
{
title
:
"page.profile"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/index.vue'
),
children
:
[{
path
:
'
/
myOrder'
,
//我的订单
meta
:
{
title
:
"page.myOrder"
},
path
:
'myOrder'
,
//我的订单
meta
:
{
title
:
"page.myOrder"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/myOrder.vue'
)
},
{
path
:
'
/
systemMessage'
,
//系统消息
meta
:
{
title
:
"page.systemMessage"
},
path
:
'systemMessage'
,
//系统消息
meta
:
{
title
:
"page.systemMessage"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/systemMessage.vue'
)
},
{
path
:
'
/
myCollection'
,
//我的收藏
meta
:
{
title
:
"page.myCollection"
},
path
:
'myCollection'
,
//我的收藏
meta
:
{
title
:
"page.myCollection"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/myCollection.vue'
)
},
{
path
:
'
/
myCoupon'
,
//我的优惠券
meta
:
{
title
:
"page.coupon"
},
path
:
'myCoupon'
,
//我的优惠券
meta
:
{
title
:
"page.coupon"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/myCoupon.vue'
)
},
{
path
:
'
/
accountCenter'
,
//账号中心
meta
:
{
title
:
"page.accountCenter"
},
path
:
'accountCenter'
,
//账号中心
meta
:
{
title
:
"page.accountCenter"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/accountCenter.vue'
),
children
:
[
{
path
:
'
/
basicInfor'
,
//基础资料
meta
:
{
title
:
"page.basicInfor"
},
path
:
'basicInfor'
,
//基础资料
meta
:
{
title
:
"page.basicInfor"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/accountPage/basicInfor.vue'
)
},
{
path
:
'
/
account/:reType?'
,
//账户
meta
:
{
title
:
"page.account"
},
path
:
'account/:reType?'
,
//账户
meta
:
{
title
:
"page.account"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/accountPage/account.vue'
)
},
{
path
:
'
/
passengerList'
,
//乘客列表
meta
:
{
title
:
"page.passengerList"
},
path
:
'passengerList'
,
//乘客列表
meta
:
{
title
:
"page.passengerList"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/accountPage/passengerList.vue'
)
},
{
path
:
'
/
mailingAddressList'
,
//邮寄地址列表
meta
:
{
title
:
"page.mailingAddressList"
},
path
:
'mailingAddressList'
,
//邮寄地址列表
meta
:
{
title
:
"page.mailingAddressList"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/accountPage/mailingAddressList.vue'
)
},
]
},
{
path
:
'/distributionCenter'
,
//分销中心
meta
:
{
title
:
"page.distributionCenter"
},
meta
:
{
title
:
"page.distributionCenter"
,
requiresAuth
:
true
},
component
:
()
=>
import
(
'../views/personalCenter/distributionCenter.vue'
)
},
]
...
...
src/stores/systemConfig.ts
View file @
befc0b59
...
...
@@ -7,6 +7,22 @@ import { ResultMessage } from '@/utils/message'
import
router
from
'@/router'
import
ErpUserService
from
'@/services/ErpUserService'
import
{
ApiResult
}
from
'@/types/ApiResult'
import
SecureLS
from
'secure-ls'
import
type
{
StorageLike
}
from
'pinia-plugin-persistedstate'
const
ls
=
new
SecureLS
({
isCompression
:
false
,
encryptionSecret
:
'38c31684-d00d-30dc-82e0-fad9eec46d1c'
,
})
const
st
:
StorageLike
=
{
setItem
(
key
:
string
,
value
:
string
)
{
ls
.
set
(
key
,
value
)
},
getItem
(
key
:
string
):
string
|
null
{
return
ls
.
get
(
key
)
},
}
/**
* 系统配置 Store
...
...
@@ -36,6 +52,9 @@ export const useSystemConfigStore = defineStore('systemConfig', {
groupId
:
0
as
number
,
erpAdminUserId
:
0
as
number
,
// 初始化 Promise(用于等待初始化完成)
initPromise
:
null
as
Promise
<
void
>
|
null
,
}),
getters
:
{
/**
...
...
@@ -167,74 +186,112 @@ export const useSystemConfigStore = defineStore('systemConfig', {
}
},
/**
* 等待初始化完成
* 如果已经初始化,立即返回;如果正在初始化,等待完成;如果未初始化,返回 resolved Promise
*/
async
waitForInitialization
():
Promise
<
void
>
{
// 如果已经初始化,立即返回
if
(
this
.
isInitialized
)
{
return
}
// 如果正在初始化,等待现有的 Promise
if
(
this
.
initPromise
)
{
return
this
.
initPromise
}
// 如果未初始化且未开始初始化,返回 resolved Promise(调用者需要自己初始化)
return
Promise
.
resolve
()
},
/**
* 初始化系统配置
* 根据域名获取租户信息和平台配置
*/
async
initialize
(
domainName
?:
string
)
{
// 如果已经初始化过,直接返回
if
(
this
.
isInitialized
&&
!
domainName
)
{
async
initialize
(
domainName
?:
string
):
Promise
<
void
>
{
// 如果已经初始化过且没有指定新域名,直接返回
if
(
this
.
tenantId
&&
this
.
tenantId
.
length
>
0
&&
domainName
)
{
await
this
.
queryTenantInfoAsyncAsync
(
domainName
)
return
}
this
.
isLoading
=
true
this
.
loadError
=
null
// 如果正在初始化,等待现有的 Promise
if
(
this
.
initPromise
&&
this
.
isLoading
)
{
return
this
.
initPromise
}
// 创建新的初始化 Promise
this
.
initPromise
=
(
async
()
=>
{
this
.
isLoading
=
true
this
.
loadError
=
null
try
{
await
this
.
queryTenantInfoAsyncAsync
(
domainName
)
try
{
const
data
=
await
SystemConfigService
.
getTenantInfoByDomainAsync
(
domainName
)
// 保存租户信息
this
.
tenantId
=
data
.
tenantId
||
null
this
.
navs
=
data
.
navList
||
[]
this
.
domainName
=
data
.
config
?.
domainName
||
null
this
.
distributorId
=
data
.
distributorId
||
0
// 保存平台配置
this
.
platformConfig
=
data
.
platform
||
null
this
.
config
=
data
.
config
this
.
groupId
=
data
.
erpGroupId
// 如果有租户ID,加载代理商配置
if
(
this
.
tenantId
)
{
await
this
.
getGroupInfoAsync
(
this
.
groupId
)
try
{
const
partnerConfig
=
await
PartnerCenterConfigService
.
getConfigByTenantIdAsync
(
this
.
tenantId
)
this
.
partnerCenterConfig
=
partnerConfig
||
{
isEnabled
:
false
// 如果有租户ID,加载代理商配置
if
(
this
.
tenantId
)
{
await
this
.
getGroupInfoAsync
(
this
.
groupId
)
try
{
const
partnerConfig
=
await
PartnerCenterConfigService
.
getConfigByTenantIdAsync
(
this
.
tenantId
)
this
.
partnerCenterConfig
=
partnerConfig
||
{
isEnabled
:
false
}
}
catch
(
error
)
{
console
.
warn
(
'Failed to load partner center config:'
,
error
)
// 代理商配置加载失败不影响整体初始化,设置默认值
this
.
partnerCenterConfig
=
{
isEnabled
:
false
}
}
}
catch
(
error
)
{
console
.
warn
(
'Failed to load partner center config:'
,
error
)
// 代理商配置加载失败不影响整体初始化,设置默认值
this
.
partnerCenterConfig
=
{
isEnabled
:
false
}
// 如果有默认语言,应用到 i18n
if
(
this
.
platformConfig
?.
defaultLanguage
)
{
const
savedLocale
=
localStorage
.
getItem
(
'locale'
)
// 只有在用户没有手动设置过语言时,才使用默认语言
if
(
!
savedLocale
)
{
i18n
.
global
.
locale
.
value
=
this
.
platformConfig
.
defaultLanguage
as
any
localStorage
.
setItem
(
'locale'
,
this
.
platformConfig
.
defaultLanguage
)
}
}
}
// 如果有默认语言,应用到 i18n
if
(
this
.
platformConfig
?.
defaultLanguage
)
{
const
savedLocale
=
localStorage
.
getItem
(
'locale'
)
// 只有在用户没有手动设置过语言时,才使用默认语言
if
(
!
savedLocale
)
{
i18n
.
global
.
locale
.
value
=
this
.
platformConfig
.
defaultLanguage
as
any
localStorage
.
setItem
(
'locale'
,
this
.
platformConfig
.
defaultLanguage
)
// 更新网站图标
if
(
this
.
config
?.
favicon
)
{
this
.
updateFavicon
(
this
.
config
.
favicon
)
}
}
catch
(
error
)
{
this
.
loadError
=
error
as
Error
ResultMessage
.
Error
(
'Failed to initialize system config:'
+
error
)
router
.
push
(
'/login'
)
console
.
error
(
'Failed to initialize system config:'
,
error
)
throw
error
}
finally
{
this
.
isLoading
=
false
this
.
isInitialized
=
true
}
// 更新网站图标
if
(
this
.
config
?.
favicon
)
{
this
.
updateFavicon
(
this
.
config
.
favicon
)
}
this
.
isInitialized
=
true
}
catch
(
error
)
{
this
.
loadError
=
error
as
Error
ResultMessage
.
Error
(
'Failed to initialize system config:'
+
error
)
router
.
push
(
'/login'
)
console
.
error
(
'Failed to initialize system config:'
,
error
)
//throw error
}
finally
{
this
.
isLoading
=
false
}
})()
return
this
.
initPromise
},
async
queryTenantInfoAsyncAsync
(
domainName
?:
string
)
{
console
.
log
(
'enter in/queryTenantInfoAsyncAsync'
)
const
data
=
await
SystemConfigService
.
getTenantInfoByDomainAsync
(
domainName
)
// 保存租户信息
this
.
tenantId
=
data
.
tenantId
||
null
this
.
navs
=
data
.
navList
||
[]
this
.
domainName
=
data
.
config
?.
domainName
||
null
this
.
distributorId
=
data
.
distributorId
||
0
// 保存平台配置
this
.
platformConfig
=
data
.
platform
||
null
this
.
config
=
data
.
config
this
.
groupId
=
data
.
erpGroupId
},
/**
...
...
@@ -243,9 +300,81 @@ export const useSystemConfigStore = defineStore('systemConfig', {
*/
async
refresh
(
domainName
?:
string
)
{
this
.
isInitialized
=
false
this
.
initPromise
=
null
await
this
.
initialize
(
domainName
)
},
/**
* 部分更新配置字段
* 只更新指定的字段,不重新加载全部数据
*/
updateConfig
(
updates
:
{
tenantId
?:
string
|
null
domainName
?:
string
|
null
distributorId
?:
number
|
null
navs
?:
NavItemDto
[]
|
null
platformConfig
?:
Partial
<
PlatformConfigDto
>
|
null
partnerCenterConfig
?:
Partial
<
PartnerCenterConfigDto
>
|
null
config
?:
any
|
null
groupId
?:
number
erpAdminUserId
?:
number
})
{
if
(
updates
.
tenantId
!==
undefined
)
{
this
.
tenantId
=
updates
.
tenantId
}
if
(
updates
.
domainName
!==
undefined
)
{
this
.
domainName
=
updates
.
domainName
}
if
(
updates
.
distributorId
!==
undefined
)
{
this
.
distributorId
=
updates
.
distributorId
}
if
(
updates
.
navs
!==
undefined
)
{
this
.
navs
=
updates
.
navs
}
if
(
updates
.
platformConfig
!==
undefined
)
{
if
(
updates
.
platformConfig
===
null
)
{
this
.
platformConfig
=
null
}
else
if
(
this
.
platformConfig
)
{
this
.
platformConfig
=
{
...
this
.
platformConfig
,
...
updates
.
platformConfig
,
}
}
else
{
this
.
platformConfig
=
updates
.
platformConfig
as
PlatformConfigDto
}
}
if
(
updates
.
partnerCenterConfig
!==
undefined
)
{
if
(
updates
.
partnerCenterConfig
===
null
)
{
this
.
partnerCenterConfig
=
null
}
else
if
(
this
.
partnerCenterConfig
)
{
this
.
partnerCenterConfig
=
{
...
this
.
partnerCenterConfig
,
...
updates
.
partnerCenterConfig
,
}
}
else
{
this
.
partnerCenterConfig
=
updates
.
partnerCenterConfig
as
PartnerCenterConfigDto
}
}
if
(
updates
.
config
!==
undefined
)
{
if
(
updates
.
config
===
null
)
{
this
.
config
=
null
}
else
if
(
this
.
config
)
{
this
.
config
=
{
...
this
.
config
,
...
updates
.
config
,
}
}
else
{
this
.
config
=
updates
.
config
}
}
if
(
updates
.
groupId
!==
undefined
)
{
this
.
groupId
=
updates
.
groupId
}
if
(
updates
.
erpAdminUserId
!==
undefined
)
{
this
.
erpAdminUserId
=
updates
.
erpAdminUserId
}
},
/**
* 更新平台配置(本地状态)
*/
...
...
@@ -287,6 +416,10 @@ export const useSystemConfigStore = defineStore('systemConfig', {
this
.
isLoading
=
false
this
.
isInitialized
=
false
this
.
loadError
=
null
this
.
initPromise
=
null
},
}
},
persist
:
{
storage
:
st
,
},
})
\ No newline at end of file
src/types/router.d.ts
View file @
befc0b59
...
...
@@ -11,6 +11,13 @@ declare module 'vue-router' {
*/
title
?:
string
/**
* 是否需要 token 验证
* 如果为 true,访问该路由时需要检查用户是否已登录
* 如果未登录,将重定向到登录页
*/
requiresAuth
?:
boolean
/**
* 筛选器参数
* 用于存储页面级的筛选配置
...
...
src/utils/pageTranslation.ts
View file @
befc0b59
...
...
@@ -6,7 +6,7 @@
import
CryptoJS
from
'crypto-js'
import
type
{
ComponentNode
}
from
'@/types/pageBuilder'
import
{
isTranslatableField
}
from
'./i18nFieldMap'
import
type
{
TextToTranslateDto
,
TranslationItemDto
}
from
'@/types/
page-builder
/pageTranslation'
import
type
{
TextToTranslateDto
,
TranslationItemDto
}
from
'@/types/
translation
/pageTranslation'
/**
* 计算文本的 MD5 哈希值
...
...
@@ -38,13 +38,26 @@ function extractTextsRecursive(
if
(
Array
.
isArray
(
obj
))
{
obj
.
forEach
((
item
,
index
)
=>
{
const
result
=
extractTextsRecursive
(
item
,
componentType
,
`
${
fieldPath
}
[
${
index
}
]`
,
sourceLanguage
)
texts
.
push
(...
result
)
const
itemPath
=
`
${
fieldPath
}
[
${
index
}
]`
// 如果数组元素是字符串,且路径可翻译,直接提取
if
(
typeof
item
===
'string'
&&
item
.
trim
()
&&
isTranslatableField
(
componentType
,
itemPath
))
{
const
hash
=
calculateTextHash
(
item
)
texts
.
push
({
hash
,
text
:
item
,
fieldPath
:
itemPath
,
sourceLanguage
,
})
}
else
{
// 否则递归处理
const
result
=
extractTextsRecursive
(
item
,
componentType
,
itemPath
,
sourceLanguage
)
texts
.
push
(...
result
)
}
})
return
texts
}
...
...
@@ -142,9 +155,17 @@ export function collectTextHashes(components: ComponentNode[]): string[] {
if
(
obj
===
null
||
obj
===
undefined
)
return
if
(
Array
.
isArray
(
obj
))
{
obj
.
forEach
((
item
,
index
)
=>
collectFromObj
(
item
,
componentType
,
`
${
fieldPath
}
[
${
index
}
]`
)
)
obj
.
forEach
((
item
,
index
)
=>
{
const
itemPath
=
`
${
fieldPath
}
[
${
index
}
]`
// 如果数组元素是字符串,且路径可翻译,直接收集哈希
if
(
typeof
item
===
'string'
&&
item
.
trim
()
&&
isTranslatableField
(
componentType
,
itemPath
))
{
const
hash
=
calculateTextHash
(
item
)
hashes
.
add
(
hash
)
}
else
{
// 否则递归处理
collectFromObj
(
item
,
componentType
,
itemPath
)
}
})
return
}
...
...
@@ -203,8 +224,17 @@ export function collectTranslationsByHash(
// 数组:按索引对齐
if
(
Array
.
isArray
(
sourceNode
))
{
sourceNode
.
forEach
((
item
,
index
)
=>
{
const
itemPath
=
`
${
fieldPath
}
[
${
index
}
]`
const
tgt
=
Array
.
isArray
(
targetNode
)
?
targetNode
[
index
]
:
undefined
traversePair
(
item
,
tgt
,
componentType
,
`
${
fieldPath
}
[
${
index
}
]`
)
// 如果数组元素是字符串,且路径可翻译,直接收集
if
(
typeof
item
===
'string'
&&
item
.
trim
()
&&
isTranslatableField
(
componentType
,
itemPath
))
{
const
hash
=
calculateTextHash
(
item
)
const
text
=
typeof
tgt
===
'string'
?
tgt
:
item
result
.
push
({
hash
,
text
,
fieldPath
:
itemPath
})
}
else
{
// 否则递归处理
traversePair
(
item
,
tgt
,
componentType
,
itemPath
)
}
})
return
}
...
...
@@ -259,7 +289,18 @@ export function applyTranslations(
}
if
(
Array
.
isArray
(
obj
))
{
return
obj
.
map
(
item
=>
replaceTextRecursive
(
item
))
return
obj
.
map
(
item
=>
{
// 如果数组元素是字符串,检查是否需要替换
if
(
typeof
item
===
'string'
&&
item
.
trim
())
{
const
hash
=
calculateTextHash
(
item
)
const
translationItem
=
translations
[
hash
]
if
(
translationItem
&&
translationItem
.
text
)
{
return
translationItem
.
text
}
}
// 否则递归处理
return
replaceTextRecursive
(
item
)
})
}
if
(
typeof
obj
===
'object'
)
{
...
...
src/views/auth/Login.vue
View file @
befc0b59
...
...
@@ -117,14 +117,11 @@
<
script
setup
lang=
"ts"
>
import
{
ref
,
reactive
,
computed
,
onMounted
}
from
"vue"
;
import
{
useI18n
}
from
"vue-i18n"
;
import
{
useRouter
}
from
'vue-router'
import
{
useRouter
,
useRoute
}
from
'vue-router'
import
{
useUserStore
}
from
'@/stores/index'
import
{
useSystemConfigStore
}
from
'@/stores/index'
import
ErpUserService
from
'@/services/ErpUserService'
import
{
ApiResult
}
from
'@/types/ApiResult'
import
{
Message
}
from
'@arco-design/web-vue'
import
loginHeader
from
"./components/header.vue"
;
import
f
from
'@/assets/images/login/login_f.png'
import
G
from
'@/assets/images/login/login_G.png'
import
tel
from
'@/assets/images/login/login_tel.png'
import
line
from
'@/assets/images/login/login_line.png'
...
...
@@ -139,9 +136,25 @@ const systemConfigStore = useSystemConfigStore()
const
loading
=
ref
(
true
)
const
router
=
useRouter
()
const
route
=
useRoute
()
const
{
params
}
=
router
.
currentRoute
.
value
const
googleButtonContainer
=
ref
(
null
);
// 获取登录后的重定向路径
// 优先级:1. 路由 query 参数中的 redirect 2. localStorage 中的 forward 3. 默认首页
const
getRedirectPath
=
():
string
=>
{
const
queryRedirect
=
route
.
query
.
redirect
as
string
|
undefined
if
(
queryRedirect
)
{
return
queryRedirect
}
const
forward
=
localStorage
.
getItem
(
'forward'
)
if
(
forward
)
{
localStorage
.
removeItem
(
'forward'
)
return
forward
}
return
'/'
}
const
loginMsg
=
reactive
({
tenantId
:
systemConfigStore
.
tenantId
||
null
,
...
...
@@ -225,10 +238,8 @@ const useLineLogin = async(code:string) => {
if
(
response
.
status
==
'SUCCESS'
)
{
userStore
.
setLoginType
(
loginMsg
.
reType
||
0
)
Message
.
success
(
t
(
'login.loginSuccess'
))
const
forward
=
localStorage
.
getItem
(
'forward'
)
localStorage
.
removeItem
(
'forward'
)
router
.
push
({
path
:
forward
?
forward
:
'/'
,
path
:
getRedirectPath
()
,
})
}
else
if
(
response
.
status
==
'ERROR'
){
router
.
push
(
'/login'
)
...
...
@@ -254,10 +265,8 @@ const useWechatLogin = async(code:string) => {
if
(
response
.
status
==
'SUCCESS'
)
{
userStore
.
setLoginType
(
loginMsg
.
reType
||
0
)
Message
.
success
(
t
(
'login.loginSuccess'
))
const
forward
=
localStorage
.
getItem
(
'forward'
)
localStorage
.
removeItem
(
'forward'
)
router
.
push
({
path
:
forward
?
forward
:
'/'
,
path
:
getRedirectPath
()
,
})
}
else
if
(
response
.
status
==
'ERROR'
){
router
.
push
(
'/login'
)
...
...
@@ -360,10 +369,8 @@ const handleSignInSuccess = async (googleUser:any) => {
if
(
response
.
status
==
'SUCCESS'
)
{
userStore
.
setLoginType
(
loginMsg
.
reType
||
0
)
Message
.
success
(
t
(
'login.loginSuccess'
))
const
forward
=
localStorage
.
getItem
(
'forward'
)
localStorage
.
removeItem
(
'forward'
)
router
.
push
({
path
:
forward
?
forward
:
'/'
,
path
:
getRedirectPath
()
,
})
}
else
if
(
response
.
status
==
'ERROR'
){
router
.
push
(
'/login'
)
...
...
@@ -409,10 +416,8 @@ const handleLogin = async () => {
if
(
result
.
status
==
'SUCCESS'
)
{
userStore
.
setLoginType
(
loginMsg
.
reType
||
0
)
Message
.
success
(
t
(
'login.loginSuccess'
))
const
forward
=
localStorage
.
getItem
(
'forward'
)
localStorage
.
removeItem
(
'forward'
)
router
.
push
({
path
:
forward
?
forward
:
'/'
,
path
:
getRedirectPath
()
,
})
}
}
catch
(
error
:
any
)
{
...
...
src/views/auth/components/header.vue
View file @
befc0b59
<
template
>
<div
class=
"flex justify-between items-center"
>
<div
class=
"flex justify-center items-center cursor-pointer"
@
click=
"goHome('/
home
')"
>
@
click=
"goHome('/')"
>
<img
v-if=
"systemConfigStore.config?.logo"
:src=
"systemConfigStore.config.logo"
:alt=
"systemConfigStore.config.webSiteName"
...
...
@@ -14,7 +14,7 @@
</svg>
</div>
<div
class=
"flex items-center"
v-if=
"!currentStep||currentStep
<3
"
>
<div
class=
"flex items-center mr-[67px] cursor-pointer"
@
click=
"goHome('/
home
')"
>
<div
class=
"flex items-center mr-[67px] cursor-pointer"
@
click=
"goHome('/')"
>
<img
src=
"../../../assets/images/login/login-home.png"
class=
"h-[20px]"
...
...
src/views/auth/components/registerSuccess.vue
View file @
befc0b59
...
...
@@ -20,7 +20,7 @@
:loading=
"loading"
html-type=
"submit"
class=
"w-[222px] flex-1 font-medium !h-[46px] !rounded-[13px] !text-[#FFFFFF] !text-[16px]"
@
click=
"goHome('/
home
')"
@
click=
"goHome('/')"
>
{{
t
(
'login.backToHome'
)
}}
</a-button>
...
...
src/views/auth/forgePassword.vue
View file @
befc0b59
...
...
@@ -234,7 +234,7 @@ const goPage = (path:string) => {
router
.
push
(
path
)
return
}
router
.
push
(
'/basicInfor'
)
router
.
push
(
'/
personalCenter/accountCenter/
basicInfor'
)
}
// 验证邮箱是否可用
...
...
@@ -370,7 +370,7 @@ const handleSubmit = async () => {
Message
.
success
(
t
(
'login.resetSuccess'
))
// 延迟跳转到登录页
if
(
params
&&
params
.
email
){
router
.
push
(
'/basicInfor'
)
router
.
push
(
'/
personalCenter/accountCenter/
basicInfor'
)
}
else
{
router
.
push
(
'/login'
)
}
...
...
src/views/home/index.vue
View file @
befc0b59
...
...
@@ -15,11 +15,19 @@
const
pageData
=
ref
<
any
>
(
null
)
const
translatedPageData
=
ref
<
any
>
(
null
)
const
{
locale
}
=
useI18n
()
const
{
locale
,
t
}
=
useI18n
()
// 按目标语言缓存翻译结果,减少重复请求
const
translationsCache
=
new
Map
<
string
,
Record
<
string
,
any
>>
()
// 更新页面标题
function
updatePageTitle
(
pageDataValue
:
any
)
{
if
(
pageDataValue
?.
metadata
?.
pageTitle
)
{
const
pageTitle
=
pageDataValue
.
metadata
.
pageTitle
document
.
title
=
`
${
pageTitle
}
`
}
}
async
function
loadPageData
()
{
try
{
const
response
=
await
WebSitePageService
.
getHomePageAsync
({
...
...
@@ -31,6 +39,8 @@
if
(
response
.
pageDataList
&&
response
.
pageDataList
.
length
>
0
)
{
pageData
.
value
=
JSON
.
parse
(
response
.
pageDataList
[
0
].
plugData
as
string
)
await
applyI18nTranslations
()
// 更新页面标题
updatePageTitle
(
translatedPageData
.
value
||
pageData
.
value
)
}
}
catch
(
error
)
{
console
.
error
(
'加载首页数据失败:'
,
error
)
...
...
@@ -40,6 +50,7 @@
async
function
applyI18nTranslations
()
{
if
(
!
pageData
.
value
?.
components
)
{
translatedPageData
.
value
=
pageData
.
value
updatePageTitle
(
pageData
.
value
)
return
}
const
sourceLang
=
pageData
.
value
.
metadata
?.
sourceLanguage
||
'zh-CN'
...
...
@@ -48,6 +59,7 @@
// 同源语言直接用原数据
if
(
targetLang
===
sourceLang
)
{
translatedPageData
.
value
=
pageData
.
value
updatePageTitle
(
pageData
.
value
)
return
}
...
...
@@ -58,12 +70,14 @@
...
pageData
.
value
,
components
:
applyTranslations
(
pageData
.
value
.
components
,
cached
),
}
updatePageTitle
(
translatedPageData
.
value
)
return
}
const
hashes
=
collectTextHashes
(
pageData
.
value
.
components
)
if
(
!
hashes
.
length
)
{
translatedPageData
.
value
=
pageData
.
value
updatePageTitle
(
pageData
.
value
)
return
}
...
...
@@ -79,9 +93,11 @@
...
pageData
.
value
,
components
:
applyTranslations
(
pageData
.
value
.
components
,
translations
),
}
updatePageTitle
(
translatedPageData
.
value
)
}
catch
(
err
)
{
console
.
error
(
'加载翻译失败:'
,
err
)
translatedPageData
.
value
=
pageData
.
value
updatePageTitle
(
pageData
.
value
)
}
}
...
...
@@ -99,6 +115,17 @@
}
}
)
// 监听翻译后的页面数据变化,更新页面标题
watch
(
()
=>
translatedPageData
.
value
,
(
newData
)
=>
{
if
(
newData
)
{
updatePageTitle
(
newData
)
}
},
{
immediate
:
true
}
)
</
script
>
<
style
scoped
>
...
...
src/views/personalCenter/accountCenter.vue
View file @
befc0b59
...
...
@@ -22,10 +22,6 @@
import
{
ref
,
onMounted
,
computed
}
from
'vue'
import
{
useI18n
}
from
'vue-i18n'
import
{
useRouter
,
useRoute
}
from
'vue-router'
import
account
from
"./components/accountCenter/account.vue"
import
basicInfor
from
"./components/accountCenter/basicInfor.vue"
import
passengerList
from
"./components/accountCenter/passengerList.vue"
import
mailingAddressList
from
"./components/accountCenter/mailingAddressList.vue"
const
{
t
}
=
useI18n
();
const
router
=
useRouter
()
...
...
@@ -38,25 +34,25 @@ const TitleBars = [
{
label
:
t
(
'personal.basicInfo'
),
value
:
1
,
path
:
'/basicInfor'
,
path
:
'/
personalCenter/accountCenter/
basicInfor'
,
key
:
'basicInfor'
},
{
label
:
t
(
'personal.accountInfor'
),
value
:
2
,
path
:
'/account'
,
path
:
'/
personalCenter/accountCenter/
account'
,
key
:
'account'
},
{
label
:
t
(
'personal.commonPassenger'
),
value
:
3
,
path
:
'/passengerList'
,
path
:
'/p
ersonalCenter/accountCenter/p
assengerList'
,
key
:
'passengerList'
},
{
label
:
t
(
'personal.postAddress'
),
value
:
4
,
path
:
'/mailingAddressList'
,
path
:
'/
personalCenter/accountCenter/
mailingAddressList'
,
key
:
'mailingAddressList'
}
]
...
...
src/views/personalCenter/accountPage/account.vue
View file @
befc0b59
...
...
@@ -240,7 +240,7 @@ const loginWithLine = () => {
// https://www.oytour.com/#/login/2/3
console
.
log
(
openInfo
.
value
,
'----------'
)
// return
const
redirectUri
=
encodeURIComponent
(
openInfo
.
value
.
redirectUri
||
'http://localhost:8002/account/3'
);
// 替换为你的重定向 URI
const
redirectUri
=
encodeURIComponent
(
openInfo
.
value
.
redirectUri
||
'http://localhost:8002/
personalCenter/accountCenter/
account/3'
);
// 替换为你的重定向 URI
const
state
=
generateState
();
// 防止 CSRF 攻击,生成随机的 state 参数
// 构造 LINE 授权 URL
const
lineLoginUrl
=
`https://access.line.me/oauth2/v2.1/authorize?response_type=code&client_id=
${
channelId
}
&redirect_uri=
${
redirectUri
}
&state=
${
state
}
&scope=openid%20profile`
;
...
...
@@ -257,7 +257,7 @@ const useLineBind = async(code:string) => {
Message
.
success
(
t
(
'personal.bindWechatSuccess'
))
getPersonalInfor
()
}
else
if
(
response
.
status
==
'ERROR'
){
router
.
push
(
'/account'
)
router
.
push
(
'/
personalCenter/accountCenter/
account'
)
}
}
catch
(
error
:
any
)
{
Message
.
error
(
error
.
message
)
...
...
@@ -267,7 +267,7 @@ const useLineBind = async(code:string) => {
}
// 微信授权
const
loginWechat
=
()
=>
{
const
redirect_url
=
openInfo
.
value
.
redirectUri
||
'https://www.oytour.com/#/login/2'
||
'http://localhost:8002/account/2'
const
redirect_url
=
openInfo
.
value
.
redirectUri
||
'https://www.oytour.com/#/login/2'
||
'http://localhost:8002/
personalCenter/accountCenter/
account/2'
const
url
=
`https://open.weixin.qq.com/connect/qrconnect?appid=
${
openInfo
.
value
.
appId
}
&redirect_uri=
${
encodeURIComponent
(
redirect_url
)}
&response_type=code&scope=snsapi_login&state=
${
1
}
&wechat_redirect=
${
redirect_url
}
`
;
window
.
location
.
href
=
url
;
}
...
...
@@ -280,7 +280,7 @@ const useWechatBind = async(code:string) => {
Message
.
success
(
t
(
'personal.bindWechatSuccess'
))
getPersonalInfor
()
}
else
if
(
response
.
status
==
'ERROR'
){
router
.
push
(
'/account'
)
router
.
push
(
'/
personalCenter/accountCenter/
account'
)
}
}
catch
(
error
:
any
)
{
Message
.
error
(
error
.
message
)
...
...
src/views/personalCenter/accountPage/editEmail.vue
View file @
befc0b59
...
...
@@ -11,7 +11,7 @@
<a-form-item
field=
""
label=
""
class=
""
>
<div
class=
"flex justify-center relative"
>
<div
class=
"flex justify-center items-center absolute left-[-300px] top-[5px]"
@
click=
"goPage('/account')"
>
@
click=
"goPage('/
personalCenter/accountCenter/
account')"
>
<div
class=
"flex items-center justify-center cursor-pointer"
>
<icon-left
class=
"font-semibold"
size=
"20"
strokeLinejoin=
"miter"
/>
<span
class=
"text-base ml-[9px]"
>
{{
t
(
'personal.return'
)
}}
</span>
...
...
@@ -438,7 +438,7 @@ const handleSubmit = async () => {
if
(
params
&&
params
.
forward
){
goPage
(
`/${params.forward
}
`
)
}
else
{
goPage
(
'/account'
)
goPage
(
'/
personalCenter/accountCenter/
account'
)
}
}
}
catch
(
error
:
any
)
{
...
...
src/views/personalCenter/accountPage/perForgePassword.vue
View file @
befc0b59
...
...
@@ -11,7 +11,7 @@
<a-form-item
field=
""
label=
""
class=
""
>
<div
class=
"flex justify-center relative"
>
<div
class=
"flex justify-center items-center absolute left-[-300px] top-[5px]"
@
click=
"currentStep==1?goPage('/account'):handlePrevious()"
>
@
click=
"currentStep==1?goPage('/
personalCenter/accountCenter/
account'):handlePrevious()"
>
<div
class=
"flex items-center justify-center cursor-pointer"
>
<icon-left
class=
"font-semibold"
size=
"20"
strokeLinejoin=
"miter"
/>
<span
class=
"text-base ml-[9px]"
>
{{
currentStep
==
1
?
t
(
'personal.return'
):
t
(
'personal.returnStep'
)
}}
</span>
...
...
@@ -255,7 +255,7 @@ const goPage = (path:string) => {
router
.
push
(
path
)
return
}
router
.
push
(
'/account'
)
router
.
push
(
'/
personalCenter/accountCenter/
account'
)
}
// 验证邮箱是否可用
...
...
@@ -391,7 +391,7 @@ const handleSubmit = async () => {
Message
.
success
(
t
(
'login.resetSuccess'
))
// currentStep.value ++
// 延迟跳转
router
.
push
(
'/account'
)
router
.
push
(
'/
personalCenter/accountCenter/
account'
)
}
}
catch
(
error
:
any
)
{
Message
.
error
(
error
.
message
||
t
(
'login.resetFailed'
))
...
...
src/views/personalCenter/accountPage/resetPassword.vue
View file @
befc0b59
...
...
@@ -12,7 +12,7 @@
<a-form-item
field=
""
label=
""
class=
""
>
<div
class=
"flex justify-center relative"
>
<div
class=
"flex justify-center items-center absolute left-[-300px] top-[5px]"
@
click=
"goPage('/account')"
>
@
click=
"goPage('/
personalCenter/accountCenter/
account')"
>
<div
class=
"flex items-center justify-center cursor-pointer"
>
<icon-left
class=
"font-semibold"
size=
"20"
strokeLinejoin=
"miter"
/>
<span
class=
"text-base ml-[9px]"
>
{{
t
(
'personal.return'
)
}}
</span>
...
...
@@ -371,7 +371,7 @@ const handleSubmit = async () => {
if
(
response
){
Message
.
success
(
t
(
'login.resetSuccess'
))
// 延迟跳转到登录页
goPage
(
'/account'
)
goPage
(
'/
personalCenter/accountCenter/
account'
)
}
}
catch
(
error
:
any
)
{
Message
.
error
(
error
.
message
||
t
(
'login.resetFailed'
))
...
...
src/views/personalCenter/components/LeftView.vue
View file @
befc0b59
...
...
@@ -16,7 +16,7 @@
</div>
<div
class=
"mt-[13px] text-lg font-medium text-center truncate"
>
{{
userInfo
?.
name
||
''
}}
</div>
<div
class=
"flex justify-center items-center mt-[10px] cursor-pointer"
@
click=
"goPage('/basicInfor')"
>
@
click=
"goPage('/
personalCenter/accountCenter/
basicInfor')"
>
<span
v-if=
"!userInfo?.IsComplete"
class=
"LeftViewTisp w-[6px] h-[6px] rounded-full"
></span>
<span
class=
"LeftViewData ml-[5px] text-sm font-medium text-[#666]"
>
{{
t
(
'personal.completeProfile'
)
}}
...
...
@@ -109,7 +109,7 @@ const props = defineProps({
},
activeMenu
:
{
type
:
String
,
default
:
'/myOrder'
,
default
:
'/
personalCenter/
myOrder'
,
},
})
...
...
src/views/personalCenter/index.vue
View file @
befc0b59
...
...
@@ -28,7 +28,7 @@ const route = useRoute()
const
activeMenu
=
computed
(()
=>
{
const
path
=
route
.
path
const
menu
=
menuList
.
value
.
find
(
item
=>
path
.
startsWith
(
item
.
path
))
if
(
path
==
'/
account'
||
path
==
'/passengerList'
||
path
==
'
/mailingAddressList'
){
if
(
path
==
'/
personalCenter/accountCenter/account'
||
path
==
'/personalCenter/accountCenter/passengerList'
||
path
==
'/personalCenter/accountCenter
/mailingAddressList'
){
return
'basicInfor'
}
return
menu
?.
key
||
'myOrder'
...
...
@@ -38,28 +38,28 @@ const activeMenu = computed(() => {
const
menuList
=
ref
([
{
name
:
t
(
'personal.menu.myOrder'
),
path
:
'/myOrder'
,
path
:
'/
personalCenter/
myOrder'
,
key
:
'myOrder'
,
},
{
name
:
t
(
'personal.menu.systemMessage'
),
path
:
'/systemMessage'
,
path
:
'/
personalCenter/
systemMessage'
,
key
:
'systemMessage'
,
},
{
name
:
t
(
'personal.menu.myCollection'
),
path
:
'/myCollection'
,
path
:
'/
personalCenter/
myCollection'
,
key
:
'myCollection'
,
},
{
name
:
t
(
'personal.menu.coupon'
),
path
:
'/myCoupon'
,
path
:
'/
personalCenter/
myCoupon'
,
key
:
'myCoupon'
,
count
:
2
,
},
{
name
:
t
(
'personal.menu.accountCenter'
),
path
:
'/basicInfor'
,
path
:
'/
personalCenter/accountCenter/
basicInfor'
,
key
:
'basicInfor'
,
},
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment