Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-vue-admin
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-vue-admin
Commits
913c22c8
提交
913c22c8
authored
6月 27, 2021
作者:
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(menu): the route is automatically mapped to the menu
上级
327d71b8
显示空白字符变更
内嵌
并排
正在显示
40 个修改的文件
包含
121 行增加
和
851 行删除
+121
-851
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+8
-0
appEnum.ts
src/enums/appEnum.ts
+2
-0
usePermission.ts
src/hooks/web/usePermission.ts
+4
-4
index.vue
src/layouts/default/feature/index.vue
+2
-2
index.ts
src/router/guard/index.ts
+4
-4
permissionGuard.ts
src/router/guard/permissionGuard.ts
+4
-4
routeHelper.ts
src/router/helper/routeHelper.ts
+2
-0
index.ts
src/router/menus/index.ts
+38
-13
about.ts
src/router/menus/modules/about.ts
+0
-11
dashboard.ts
src/router/menus/modules/dashboard.ts
+0
-22
charts.ts
src/router/menus/modules/demo/charts.ts
+0
-45
comp.ts
src/router/menus/modules/demo/comp.ts
+0
-279
excel.ts
src/router/menus/modules/demo/excel.ts
+0
-29
feat.ts
src/router/menus/modules/demo/feat.ts
+0
-130
flow.ts
src/router/menus/modules/demo/flow.ts
+0
-17
iframe.ts
src/router/menus/modules/demo/iframe.ts
+0
-25
level.ts
src/router/menus/modules/demo/level.ts
+0
-37
page.ts
src/router/menus/modules/demo/page.ts
+0
-121
permission.ts
src/router/menus/modules/demo/permission.ts
+0
-49
setup.ts
src/router/menus/modules/demo/setup.ts
+0
-14
system.ts
src/router/menus/modules/demo/system.ts
+0
-34
basic.ts
src/router/routes/basic.ts
+2
-0
about.ts
src/router/routes/modules/about.ts
+2
-0
dashboard.ts
src/router/routes/modules/dashboard.ts
+1
-0
charts.ts
src/router/routes/modules/demo/charts.ts
+1
-0
comp.ts
src/router/routes/modules/demo/comp.ts
+1
-0
feat.ts
src/router/routes/modules/demo/feat.ts
+1
-0
flow.ts
src/router/routes/modules/demo/flow.ts
+1
-0
iframe.ts
src/router/routes/modules/demo/iframe.ts
+1
-0
level.ts
src/router/routes/modules/demo/level.ts
+1
-0
page.ts
src/router/routes/modules/demo/page.ts
+1
-0
permission.ts
src/router/routes/modules/demo/permission.ts
+1
-0
setup.ts
src/router/routes/modules/demo/setup.ts
+2
-0
system.ts
src/router/routes/modules/demo/system.ts
+2
-0
projectSetting.ts
src/settings/projectSetting.ts
+1
-1
app.ts
src/store/modules/app.ts
+1
-1
permission.ts
src/store/modules/permission.ts
+34
-6
user.ts
src/store/modules/user.ts
+1
-1
checkStatus.ts
src/utils/http/axios/checkStatus.ts
+2
-2
vue-router.d.ts
types/vue-router.d.ts
+1
-0
没有找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
913c22c8
## Wip
### ⚡ Performance Improvements
-
**Icon**
移除 Icon 组件全局注册,防止特定情况下热更新问题
### ✨ Features
-
**Menu**
新增
`permissionMode=PermissionModeEnum.ROUTE_MAPPING`
模式
-
项目默认改为该模式,删除原有菜单文件
-
如果之前已经写好了菜单,可以更改为
`PermissionModeEnum.ROLE`
模式即可
## 2.5.1(2021-06-26)
### ⚡ Performance Improvements
...
...
src/enums/appEnum.ts
浏览文件 @
913c22c8
...
...
@@ -33,6 +33,8 @@ export enum PermissionModeEnum {
ROLE
=
'ROLE'
,
// black
BACK
=
'BACK'
,
// route mapping
ROUTE_MAPPING
=
'ROUTE_MAPPING'
,
}
// Route switching animation
...
...
src/hooks/web/usePermission.ts
浏览文件 @
913c22c8
...
...
@@ -31,7 +31,7 @@ export function usePermission() {
appStore
.
setProjectConfig
({
permissionMode
:
projectSetting
.
permissionMode
===
PermissionModeEnum
.
BACK
?
PermissionModeEnum
.
RO
LE
?
PermissionModeEnum
.
RO
UTE_MAPPING
:
PermissionModeEnum
.
BACK
,
});
location
.
reload
();
...
...
@@ -59,7 +59,7 @@ export function usePermission() {
function
hasPermission
(
value
?:
RoleEnum
|
RoleEnum
[]
|
string
|
string
[],
def
=
true
):
boolean
{
const
permMode
=
projectSetting
.
permissionMode
;
if
(
PermissionModeEnum
.
RO
LE
===
permMode
)
{
if
(
PermissionModeEnum
.
RO
UTE_MAPPING
===
permMode
)
{
// Visible by default
if
(
!
value
)
{
return
def
;
...
...
@@ -89,9 +89,9 @@ export function usePermission() {
* @param roles
*/
async
function
changeRole
(
roles
:
RoleEnum
|
RoleEnum
[]):
Promise
<
void
>
{
if
(
projectSetting
.
permissionMode
!==
PermissionModeEnum
.
RO
LE
)
{
if
(
projectSetting
.
permissionMode
!==
PermissionModeEnum
.
RO
UTE_MAPPING
)
{
throw
new
Error
(
'Please switch PermissionModeEnum to RO
LE
mode in the configuration to operate!'
'Please switch PermissionModeEnum to RO
UTE_MAPPING
mode in the configuration to operate!'
);
}
...
...
src/layouts/default/feature/index.vue
浏览文件 @
913c22c8
...
...
@@ -5,7 +5,7 @@
import
{
useRootSetting
}
from
'/@/hooks/setting/useRootSetting'
;
import
{
useHeaderSetting
}
from
'/@/hooks/setting/useHeaderSetting'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useUserStoreWi
d
thOut
}
from
'/@/store/modules/user'
;
import
{
useUserStoreWithOut
}
from
'/@/store/modules/user'
;
import
{
SettingButtonPositionEnum
}
from
'/@/enums/appEnum'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
...
...
@@ -22,7 +22,7 @@
setup
()
{
const
{
getUseOpenBackTop
,
getShowSettingButton
,
getSettingButtonPosition
,
getFullContent
}
=
useRootSetting
();
const
userStore
=
useUserStoreWi
d
thOut
();
const
userStore
=
useUserStoreWithOut
();
const
{
prefixCls
}
=
useDesign
(
'setting-drawer-fearure'
);
const
{
getShowHeader
}
=
useHeaderSetting
();
...
...
src/router/guard/index.ts
浏览文件 @
913c22c8
import
type
{
Router
,
RouteLocationNormalized
}
from
'vue-router'
;
import
{
useAppStoreWi
d
thOut
}
from
'/@/store/modules/app'
;
import
{
useUserStoreWi
d
thOut
}
from
'/@/store/modules/user'
;
import
{
useAppStoreWithOut
}
from
'/@/store/modules/app'
;
import
{
useUserStoreWithOut
}
from
'/@/store/modules/user'
;
import
{
useTransitionSetting
}
from
'/@/hooks/setting/useTransitionSetting'
;
import
{
AxiosCanceler
}
from
'/@/utils/http/axios/axiosCancel'
;
import
{
Modal
,
notification
}
from
'ant-design-vue'
;
...
...
@@ -46,8 +46,8 @@ function createPageGuard(router: Router) {
// Used to handle page loading status
function
createPageLoadingGuard
(
router
:
Router
)
{
const
userStore
=
useUserStoreWi
d
thOut
();
const
appStore
=
useAppStoreWi
d
thOut
();
const
userStore
=
useUserStoreWithOut
();
const
appStore
=
useAppStoreWithOut
();
const
{
getOpenPageLoading
}
=
useTransitionSetting
();
router
.
beforeEach
(
async
(
to
)
=>
{
if
(
!
userStore
.
getToken
)
{
...
...
src/router/guard/permissionGuard.ts
浏览文件 @
913c22c8
import
type
{
Router
,
RouteRecordRaw
}
from
'vue-router'
;
import
{
usePermissionStoreWi
d
thOut
}
from
'/@/store/modules/permission'
;
import
{
usePermissionStoreWithOut
}
from
'/@/store/modules/permission'
;
import
{
PageEnum
}
from
'/@/enums/pageEnum'
;
import
{
useUserStoreWi
d
thOut
}
from
'/@/store/modules/user'
;
import
{
useUserStoreWithOut
}
from
'/@/store/modules/user'
;
import
{
PAGE_NOT_FOUND_ROUTE
}
from
'/@/router/routes/basic'
;
...
...
@@ -12,8 +12,8 @@ const LOGIN_PATH = PageEnum.BASE_LOGIN;
const
whitePathList
:
PageEnum
[]
=
[
LOGIN_PATH
];
export
function
createPermissionGuard
(
router
:
Router
)
{
const
userStore
=
useUserStoreWi
d
thOut
();
const
permissionStore
=
usePermissionStoreWi
d
thOut
();
const
userStore
=
useUserStoreWithOut
();
const
permissionStore
=
usePermissionStoreWithOut
();
router
.
beforeEach
(
async
(
to
,
from
,
next
)
=>
{
// Jump to the 404 page after processing the login
if
(
from
.
path
===
LOGIN_PATH
&&
to
.
name
===
PAGE_NOT_FOUND_ROUTE
.
name
)
{
...
...
src/router/helper/routeHelper.ts
浏览文件 @
913c22c8
...
...
@@ -65,6 +65,8 @@ function dynamicImport(
// Turn background objects into routing objects
export
function
transformObjToRoute
<
T
=
AppRouteModule
>
(
routeList
:
AppRouteModule
[]):
T
[]
{
console
.
log
(
routeList
);
routeList
.
forEach
((
route
)
=>
{
const
component
=
route
.
component
as
string
;
if
(
component
)
{
...
...
src/router/menus/index.ts
浏览文件 @
913c22c8
import
type
{
Menu
,
MenuModule
}
from
'/@/router/types'
;
import
type
{
RouteRecordNormalized
}
from
'vue-router'
;
import
{
useAppStoreWi
d
thOut
}
from
'/@/store/modules/app'
;
import
{
useAppStoreWithOut
}
from
'/@/store/modules/app'
;
import
{
usePermissionStore
}
from
'/@/store/modules/permission'
;
import
{
transformMenuModule
,
getAllParentPath
}
from
'/@/router/helper/menuHelper'
;
import
{
filter
}
from
'/@/utils/helper/treeHelper'
;
...
...
@@ -23,9 +23,21 @@ Object.keys(modules).forEach((key) => {
// ===========================
// ==========Helper===========
// ===========================
const
getPermissionMode
=
()
=>
{
const
appStore
=
useAppStoreWithOut
();
return
appStore
.
getProjectConfig
.
permissionMode
;
};
const
isBackMode
=
()
=>
{
const
appStore
=
useAppStoreWidthOut
();
return
appStore
.
getProjectConfig
.
permissionMode
===
PermissionModeEnum
.
BACK
;
return
getPermissionMode
()
===
PermissionModeEnum
.
BACK
;
};
const
isRouteMappingMode
=
()
=>
{
return
getPermissionMode
()
===
PermissionModeEnum
.
ROUTE_MAPPING
;
};
const
isRoleMode
=
()
=>
{
return
getPermissionMode
()
===
PermissionModeEnum
.
ROLE
;
};
const
staticMenus
:
Menu
[]
=
[];
...
...
@@ -41,40 +53,53 @@ const staticMenus: Menu[] = [];
async
function
getAsyncMenus
()
{
const
permissionStore
=
usePermissionStore
();
return
!
isBackMode
()
?
staticMenus
:
permissionStore
.
getBackMenuList
;
if
(
isBackMode
())
{
return
permissionStore
.
getBackMenuList
;
}
if
(
isRouteMappingMode
())
{
return
permissionStore
.
getFrontMenuList
.
filter
((
item
)
=>
!
item
.
hideMenu
);
}
return
staticMenus
;
}
export
const
getMenus
=
async
():
Promise
<
Menu
[]
>
=>
{
const
menus
=
await
getAsyncMenus
();
if
(
isRoleMode
())
{
const
routes
=
router
.
getRoutes
();
return
!
isBackMode
()
?
filter
(
menus
,
basicFilter
(
routes
))
:
menus
;
return
filter
(
menus
,
basicFilter
(
routes
));
}
return
menus
;
};
export
async
function
getCurrentParentPath
(
currentPath
:
string
)
{
const
menus
=
await
getAsyncMenus
();
const
allParentPath
=
await
getAllParentPath
(
menus
,
currentPath
);
return
allParentPath
?.[
0
];
}
// Get the level 1 menu, delete children
export
async
function
getShallowMenus
():
Promise
<
Menu
[]
>
{
const
menus
=
await
getAsyncMenus
();
const
routes
=
router
.
getRoutes
();
const
shallowMenuList
=
menus
.
map
((
item
)
=>
({
...
item
,
children
:
undefined
}));
return
!
isBackMode
()
?
shallowMenuList
.
filter
(
basicFilter
(
routes
))
:
shallowMenuList
;
if
(
isRoleMode
())
{
const
routes
=
router
.
getRoutes
();
return
shallowMenuList
.
filter
(
basicFilter
(
routes
));
}
return
shallowMenuList
;
}
// Get the children of the menu
export
async
function
getChildrenMenus
(
parentPath
:
string
)
{
const
menus
=
await
getMenus
();
const
parent
=
menus
.
find
((
item
)
=>
item
.
path
===
parentPath
);
if
(
!
parent
||
!
parent
.
children
||
!!
parent
?.
meta
?.
hideChildrenInMenu
)
return
[]
as
Menu
[];
if
(
!
parent
||
!
parent
.
children
||
!!
parent
?.
meta
?.
hideChildrenInMenu
)
{
return
[]
as
Menu
[];
}
if
(
isRoleMode
())
{
const
routes
=
router
.
getRoutes
();
return
!
isBackMode
()
?
filter
(
parent
.
children
,
basicFilter
(
routes
))
:
parent
.
children
;
return
filter
(
parent
.
children
,
basicFilter
(
routes
));
}
return
parent
.
children
;
}
function
basicFilter
(
routes
:
RouteRecordNormalized
[])
{
...
...
src/router/menus/modules/about.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
about
:
MenuModule
=
{
orderNo
:
100000
,
menu
:
{
path
:
'/about/index'
,
name
:
t
(
'routes.dashboard.about'
),
},
};
export
default
about
;
src/router/menus/modules/dashboard.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
10
,
menu
:
{
name
:
t
(
'routes.dashboard.dashboard'
),
path
:
'/dashboard'
,
children
:
[
{
path
:
'analysis'
,
name
:
t
(
'routes.dashboard.analysis'
),
},
{
path
:
'workbench'
,
name
:
t
(
'routes.dashboard.workbench'
),
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/charts.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
500
,
menu
:
{
name
:
t
(
'routes.demo.charts.charts'
),
path
:
'/charts'
,
children
:
[
{
path
:
'aMap'
,
name
:
t
(
'routes.demo.charts.aMap'
),
},
{
path
:
'baiduMap'
,
name
:
t
(
'routes.demo.charts.baiduMap'
),
},
{
path
:
'googleMap'
,
name
:
t
(
'routes.demo.charts.googleMap'
),
},
{
path
:
'echarts'
,
name
:
'Echarts'
,
children
:
[
{
path
:
'map'
,
name
:
t
(
'routes.demo.charts.map'
),
},
{
path
:
'line'
,
name
:
t
(
'routes.demo.charts.line'
),
},
{
path
:
'pie'
,
name
:
t
(
'routes.demo.charts.pie'
),
},
],
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/comp.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
30
,
menu
:
{
name
:
t
(
'routes.demo.comp.comp'
),
path
:
'/comp'
,
tag
:
{
dot
:
true
},
children
:
[
{
path
:
'basic'
,
name
:
t
(
'routes.demo.comp.basic'
),
},
{
path
:
'form'
,
name
:
t
(
'routes.demo.form.form'
),
children
:
[
{
path
:
'basic'
,
name
:
t
(
'routes.demo.form.basic'
),
},
{
path
:
'useForm'
,
name
:
t
(
'routes.demo.form.useForm'
),
},
{
path
:
'refForm'
,
name
:
t
(
'routes.demo.form.refForm'
),
},
{
path
:
'advancedForm'
,
name
:
t
(
'routes.demo.form.advancedForm'
),
},
{
path
:
'ruleForm'
,
name
:
t
(
'routes.demo.form.ruleForm'
),
},
{
path
:
'dynamicForm'
,
name
:
t
(
'routes.demo.form.dynamicForm'
),
},
{
path
:
'customerForm'
,
name
:
t
(
'routes.demo.form.customerForm'
),
},
{
path
:
'appendForm'
,
name
:
t
(
'routes.demo.form.appendForm'
),
},
],
},
{
path
:
'table'
,
name
:
t
(
'routes.demo.table.table'
),
children
:
[
{
path
:
'basic'
,
name
:
t
(
'routes.demo.table.basic'
),
},
{
path
:
'treeTable'
,
name
:
t
(
'routes.demo.table.treeTable'
),
},
{
path
:
'fetchTable'
,
name
:
t
(
'routes.demo.table.fetchTable'
),
},
{
path
:
'fixedColumn'
,
name
:
t
(
'routes.demo.table.fixedColumn'
),
},
{
path
:
'customerCell'
,
name
:
t
(
'routes.demo.table.customerCell'
),
},
{
path
:
'formTable'
,
name
:
t
(
'routes.demo.table.formTable'
),
},
{
path
:
'useTable'
,
name
:
t
(
'routes.demo.table.useTable'
),
},
{
path
:
'refTable'
,
name
:
t
(
'routes.demo.table.refTable'
),
},
{
path
:
'multipleHeader'
,
name
:
t
(
'routes.demo.table.multipleHeader'
),
},
{
path
:
'mergeHeader'
,
name
:
t
(
'routes.demo.table.mergeHeader'
),
},
{
path
:
'expandTable'
,
name
:
t
(
'routes.demo.table.expandTable'
),
},
{
path
:
'fixedHeight'
,
name
:
t
(
'routes.demo.table.fixedHeight'
),
},
{
path
:
'footerTable'
,
name
:
t
(
'routes.demo.table.footerTable'
),
},
{
path
:
'editCellTable'
,
name
:
t
(
'routes.demo.table.editCellTable'
),
},
{
path
:
'editRowTable'
,
name
:
t
(
'routes.demo.table.editRowTable'
),
},
{
path
:
'authColumn'
,
name
:
t
(
'routes.demo.table.authColumn'
),
},
],
},
{
path
:
'cropper'
,
name
:
t
(
'routes.demo.comp.cropperImage'
),
tag
:
{
content
:
'new'
,
},
},
{
path
:
'countTo'
,
name
:
t
(
'routes.demo.comp.countTo'
),
},
{
path
:
'timestamp'
,
name
:
t
(
'routes.demo.comp.time'
),
},
{
path
:
'transition'
,
name
:
t
(
'routes.demo.comp.transition'
),
},
{
path
:
'modal'
,
name
:
t
(
'routes.demo.comp.modal'
),
},
{
path
:
'drawer'
,
name
:
t
(
'routes.demo.comp.drawer'
),
},
{
path
:
'desc'
,
name
:
t
(
'routes.demo.comp.desc'
),
},
{
path
:
'qrcode'
,
name
:
t
(
'routes.demo.comp.qrcode'
),
},
{
path
:
'strength-meter'
,
name
:
t
(
'routes.demo.comp.strength'
),
},
{
path
:
'upload'
,
name
:
t
(
'routes.demo.comp.upload'
),
},
{
path
:
'loading'
,
name
:
t
(
'routes.demo.comp.loading'
),
},
{
path
:
'tree'
,
name
:
t
(
'routes.demo.comp.tree'
),
children
:
[
{
path
:
'basic'
,
name
:
t
(
'routes.demo.comp.treeBasic'
),
},
{
path
:
'editTree'
,
name
:
t
(
'routes.demo.comp.editTree'
),
},
{
path
:
'actionTree'
,
name
:
t
(
'routes.demo.comp.actionTree'
),
},
],
},
{
name
:
t
(
'routes.demo.editor.editor'
),
path
:
'editor'
,
children
:
[
{
path
:
'json'
,
name
:
t
(
'routes.demo.editor.jsonEditor'
),
},
{
path
:
'markdown'
,
name
:
t
(
'routes.demo.editor.markdown'
),
children
:
[
{
path
:
'index'
,
name
:
t
(
'routes.demo.editor.tinymceBasic'
),
},
{
path
:
'editor'
,
name
:
t
(
'routes.demo.editor.tinymceForm'
),
},
],
},
{
path
:
'tinymce'
,
name
:
t
(
'routes.demo.editor.tinymce'
),
children
:
[
{
path
:
'index'
,
name
:
t
(
'routes.demo.editor.tinymceBasic'
),
},
{
path
:
'editor'
,
name
:
t
(
'routes.demo.editor.tinymceForm'
),
},
],
},
],
},
{
path
:
'scroll'
,
name
:
t
(
'routes.demo.comp.scroll'
),
children
:
[
{
path
:
'basic'
,
name
:
t
(
'routes.demo.comp.scrollBasic'
),
},
{
path
:
'action'
,
name
:
t
(
'routes.demo.comp.scrollAction'
),
},
{
path
:
'virtualScroll'
,
name
:
t
(
'routes.demo.comp.virtualScroll'
),
},
],
},
{
path
:
'lazy'
,
name
:
t
(
'routes.demo.comp.lazy'
),
children
:
[
{
path
:
'basic'
,
name
:
t
(
'routes.demo.comp.lazyBasic'
),
},
{
path
:
'transition'
,
name
:
t
(
'routes.demo.comp.lazyTransition'
),
},
],
},
{
path
:
'verify'
,
name
:
t
(
'routes.demo.comp.verify'
),
children
:
[
{
path
:
'drag'
,
name
:
t
(
'routes.demo.comp.verifyDrag'
),
},
{
path
:
'rotate'
,
name
:
t
(
'routes.demo.comp.verifyRotate'
),
},
],
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/excel.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
500
,
menu
:
{
name
:
t
(
'routes.demo.excel.excel'
),
path
:
'/excel'
,
children
:
[
{
path
:
'customExport'
,
name
:
t
(
'routes.demo.excel.customExport'
),
},
{
path
:
'jsonExport'
,
name
:
t
(
'routes.demo.excel.jsonExport'
),
},
{
path
:
'arrayExport'
,
name
:
t
(
'routes.demo.excel.arrayExport'
),
},
{
path
:
'importExcel'
,
name
:
t
(
'routes.demo.excel.importExcel'
),
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/feat.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
19
,
menu
:
{
name
:
t
(
'routes.demo.feat.feat'
),
path
:
'/feat'
,
children
:
[
{
path
:
'icon'
,
name
:
t
(
'routes.demo.feat.icon'
),
},
{
path
:
'ws'
,
name
:
t
(
'routes.demo.feat.ws'
),
},
{
name
:
t
(
'routes.demo.feat.sessionTimeout'
),
path
:
'session-timeout'
,
},
{
path
:
'tabs'
,
name
:
t
(
'routes.demo.feat.tabs'
),
},
{
path
:
'context-menu'
,
name
:
t
(
'routes.demo.feat.contextMenu'
),
},
{
path
:
'download'
,
name
:
t
(
'routes.demo.feat.download'
),
},
{
path
:
'print'
,
name
:
t
(
'routes.demo.feat.print'
),
},
{
path
:
'click-out-side'
,
name
:
t
(
'routes.demo.feat.clickOutSide'
),
},
{
path
:
'img-preview'
,
name
:
t
(
'routes.demo.feat.imgPreview'
),
},
{
path
:
'copy'
,
name
:
t
(
'routes.demo.feat.copy'
),
},
{
path
:
'msg'
,
name
:
t
(
'routes.demo.feat.msg'
),
},
{
path
:
'watermark'
,
name
:
t
(
'routes.demo.feat.watermark'
),
},
{
path
:
'ripple'
,
name
:
t
(
'routes.demo.feat.ripple'
),
},
{
path
:
'full-screen'
,
name
:
t
(
'routes.demo.feat.fullScreen'
),
},
{
path
:
'error-log'
,
name
:
t
(
'routes.demo.feat.errorLog'
),
},
{
name
:
t
(
'routes.demo.excel.excel'
),
path
:
'excel'
,
children
:
[
{
path
:
'customExport'
,
name
:
t
(
'routes.demo.excel.customExport'
),
},
{
path
:
'jsonExport'
,
name
:
t
(
'routes.demo.excel.jsonExport'
),
},
{
path
:
'arrayExport'
,
name
:
t
(
'routes.demo.excel.arrayExport'
),
},
{
path
:
'importExcel'
,
name
:
t
(
'routes.demo.excel.importExcel'
),
},
],
},
{
name
:
t
(
'routes.demo.feat.breadcrumb'
),
path
:
'breadcrumb'
,
children
:
[
// {
// path: 'flat',
// name: t('routes.demo.feat.breadcrumbFlat'),
// },
// {
// path: 'flatDetail',
// name: t('routes.demo.feat.breadcrumbFlatDetail'),
// },
{
path
:
'children'
,
name
:
t
(
'routes.demo.feat.breadcrumbChildren'
),
},
],
},
{
path
:
'testTab'
,
name
:
t
(
'routes.demo.feat.tab'
),
children
:
[
{
path
:
'id1'
,
name
:
t
(
'routes.demo.feat.tab1'
),
},
{
path
:
'id2'
,
name
:
t
(
'routes.demo.feat.tab2'
),
},
],
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/flow.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
5000
,
menu
:
{
name
:
t
(
'routes.demo.flow.name'
),
path
:
'/flow'
,
children
:
[
{
path
:
'flowChart'
,
name
:
t
(
'routes.demo.flow.flowChart'
),
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/iframe.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
1000
,
menu
:
{
name
:
t
(
'routes.demo.iframe.frame'
),
path
:
'/frame'
,
children
:
[
{
path
:
'doc'
,
name
:
t
(
'routes.demo.iframe.doc'
),
},
{
path
:
'antv'
,
name
:
t
(
'routes.demo.iframe.antv'
),
},
{
path
:
'https://vvbin.cn/doc-next/'
,
name
:
t
(
'routes.demo.iframe.docExternal'
),
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/level.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
2000
,
menu
:
{
name
:
t
(
'routes.demo.level.level'
),
path
:
'/level'
,
children
:
[
{
path
:
'menu1'
,
name
:
'Menu1'
,
children
:
[
{
path
:
'menu1-1'
,
name
:
'Menu1-1'
,
children
:
[
{
path
:
'menu1-1-1'
,
name
:
'Menu1-1-1'
,
},
],
},
{
path
:
'menu1-2'
,
name
:
'Menu1-2'
,
},
],
},
{
path
:
'menu2'
,
name
:
'Menu2'
,
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/page.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
20
,
menu
:
{
name
:
t
(
'routes.demo.page.page'
),
path
:
'/page-demo'
,
children
:
[
{
path
:
'form'
,
name
:
t
(
'routes.demo.page.form'
),
children
:
[
{
path
:
'basic'
,
name
:
t
(
'routes.demo.page.formBasic'
),
},
{
path
:
'step'
,
name
:
t
(
'routes.demo.page.formStep'
),
},
{
path
:
'high'
,
name
:
t
(
'routes.demo.page.formHigh'
),
},
],
},
{
path
:
'desc'
,
name
:
t
(
'routes.demo.page.desc'
),
children
:
[
{
path
:
'basic'
,
name
:
t
(
'routes.demo.page.descBasic'
),
},
{
path
:
'high'
,
name
:
t
(
'routes.demo.page.descHigh'
),
},
],
},
{
path
:
'result'
,
name
:
t
(
'routes.demo.page.result'
),
children
:
[
{
path
:
'success'
,
name
:
t
(
'routes.demo.page.resultSuccess'
),
},
{
path
:
'fail'
,
name
:
t
(
'routes.demo.page.resultFail'
),
},
],
},
{
path
:
'exception'
,
name
:
t
(
'routes.demo.page.exception'
),
children
:
[
{
path
:
'403'
,
name
:
t
(
'403'
),
},
{
path
:
'404'
,
name
:
t
(
'404'
),
},
{
path
:
'500'
,
name
:
t
(
'500'
),
},
{
path
:
'net-work-error'
,
name
:
t
(
'routes.demo.page.netWorkError'
),
},
{
path
:
'not-data'
,
name
:
t
(
'routes.demo.page.notData'
),
},
],
},
{
path
:
'account'
,
name
:
t
(
'routes.demo.page.account'
),
children
:
[
{
path
:
'center'
,
name
:
t
(
'routes.demo.page.accountCenter'
),
},
{
path
:
'setting'
,
name
:
t
(
'routes.demo.page.accountSetting'
),
},
],
},
{
path
:
'list'
,
name
:
t
(
'routes.demo.page.list'
),
children
:
[
{
path
:
'basic'
,
name
:
t
(
'routes.demo.page.listBasic'
),
},
{
path
:
'card'
,
name
:
t
(
'routes.demo.page.listCard'
),
},
{
path
:
'search'
,
name
:
t
(
'routes.demo.page.listSearch'
),
},
],
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/permission.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
15
,
menu
:
{
name
:
t
(
'routes.demo.permission.permission'
),
path
:
'/permission'
,
children
:
[
{
path
:
'front'
,
name
:
t
(
'routes.demo.permission.front'
),
children
:
[
{
path
:
'page'
,
name
:
t
(
'routes.demo.permission.frontPage'
),
},
{
path
:
'btn'
,
name
:
t
(
'routes.demo.permission.frontBtn'
),
},
{
path
:
'auth-pageA'
,
name
:
t
(
'routes.demo.permission.frontTestA'
),
},
{
path
:
'auth-pageB'
,
name
:
t
(
'routes.demo.permission.frontTestB'
),
},
],
},
{
path
:
'back'
,
name
:
t
(
'routes.demo.permission.back'
),
children
:
[
{
path
:
'page'
,
name
:
t
(
'routes.demo.permission.backPage'
),
},
{
path
:
'btn'
,
name
:
t
(
'routes.demo.permission.backBtn'
),
},
],
},
],
},
};
export
default
menu
;
src/router/menus/modules/demo/setup.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
setup
:
MenuModule
=
{
orderNo
:
90000
,
menu
:
{
path
:
'/setup/index'
,
name
:
t
(
'routes.demo.setup.page'
),
tag
:
{
content
:
'new'
,
},
},
};
export
default
setup
;
src/router/menus/modules/demo/system.ts
deleted
100644 → 0
浏览文件 @
327d71b8
import
type
{
MenuModule
}
from
'/@/router/types'
;
import
{
t
}
from
'/@/hooks/web/useI18n'
;
const
menu
:
MenuModule
=
{
orderNo
:
2000
,
menu
:
{
name
:
t
(
'routes.demo.system.moduleName'
),
path
:
'/system'
,
children
:
[
{
path
:
'account'
,
name
:
t
(
'routes.demo.system.account'
),
},
{
path
:
'role'
,
name
:
t
(
'routes.demo.system.role'
),
},
{
path
:
'menu'
,
name
:
t
(
'routes.demo.system.menu'
),
},
{
path
:
'dept'
,
name
:
t
(
'routes.demo.system.dept'
),
},
{
path
:
'changePassword'
,
name
:
t
(
'routes.demo.system.password'
),
},
],
},
};
export
default
menu
;
src/router/routes/basic.ts
浏览文件 @
913c22c8
...
...
@@ -10,6 +10,7 @@ export const PAGE_NOT_FOUND_ROUTE: AppRouteRecordRaw = {
meta
:
{
title
:
'ErrorPage'
,
hideBreadcrumb
:
true
,
hideMenu
:
true
,
},
children
:
[
{
...
...
@@ -31,6 +32,7 @@ export const REDIRECT_ROUTE: AppRouteRecordRaw = {
meta
:
{
title
:
REDIRECT_NAME
,
hideBreadcrumb
:
true
,
hideMenu
:
true
,
},
children
:
[
{
...
...
src/router/routes/modules/about.ts
浏览文件 @
913c22c8
...
...
@@ -9,8 +9,10 @@ const dashboard: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/about/index'
,
meta
:
{
hideChildrenInMenu
:
true
,
icon
:
'simple-icons:about-dot-me'
,
title
:
t
(
'routes.dashboard.about'
),
orderNo
:
100000
,
},
children
:
[
{
...
...
src/router/routes/modules/dashboard.ts
浏览文件 @
913c22c8
...
...
@@ -9,6 +9,7 @@ const dashboard: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/dashboard/analysis'
,
meta
:
{
orderNo
:
10
,
icon
:
'ion:grid-outline'
,
title
:
t
(
'routes.dashboard.dashboard'
),
},
...
...
src/router/routes/modules/demo/charts.ts
浏览文件 @
913c22c8
...
...
@@ -9,6 +9,7 @@ const charts: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/charts/echarts/map'
,
meta
:
{
orderNo
:
500
,
icon
:
'ion:bar-chart-outline'
,
title
:
t
(
'routes.demo.charts.charts'
),
},
...
...
src/router/routes/modules/demo/comp.ts
浏览文件 @
913c22c8
...
...
@@ -9,6 +9,7 @@ const comp: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/comp/basic'
,
meta
:
{
orderNo
:
30
,
icon
:
'ion:layers-outline'
,
title
:
t
(
'routes.demo.comp.comp'
),
},
...
...
src/router/routes/modules/demo/feat.ts
浏览文件 @
913c22c8
...
...
@@ -9,6 +9,7 @@ const feat: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/feat/icon'
,
meta
:
{
orderNo
:
19
,
icon
:
'ion:git-compare-outline'
,
title
:
t
(
'routes.demo.feat.feat'
),
},
...
...
src/router/routes/modules/demo/flow.ts
浏览文件 @
913c22c8
...
...
@@ -9,6 +9,7 @@ const charts: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/flow/flowChart'
,
meta
:
{
orderNo
:
5000
,
icon
:
'tabler:chart-dots'
,
title
:
t
(
'routes.demo.flow.name'
),
},
...
...
src/router/routes/modules/demo/iframe.ts
浏览文件 @
913c22c8
...
...
@@ -10,6 +10,7 @@ const iframe: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/frame/doc'
,
meta
:
{
orderNo
:
1000
,
icon
:
'ion:tv-outline'
,
title
:
t
(
'routes.demo.iframe.frame'
),
},
...
...
src/router/routes/modules/demo/level.ts
浏览文件 @
913c22c8
...
...
@@ -9,6 +9,7 @@ const permission: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/level/menu1/menu1-1/menu1-1-1'
,
meta
:
{
orderNo
:
2000
,
icon
:
'ion:menu-outline'
,
title
:
t
(
'routes.demo.level.level'
),
},
...
...
src/router/routes/modules/demo/page.ts
浏览文件 @
913c22c8
...
...
@@ -12,6 +12,7 @@ const page: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/page-demo/form/basic'
,
meta
:
{
orderNo
:
20
,
icon
:
'ion:aperture-outline'
,
title
:
t
(
'routes.demo.page.page'
),
},
...
...
src/router/routes/modules/demo/permission.ts
浏览文件 @
913c22c8
...
...
@@ -10,6 +10,7 @@ const permission: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/permission/front/page'
,
meta
:
{
orderNo
:
15
,
icon
:
'ion:key-outline'
,
title
:
t
(
'routes.demo.permission.permission'
),
},
...
...
src/router/routes/modules/demo/setup.ts
浏览文件 @
913c22c8
...
...
@@ -9,6 +9,8 @@ const setup: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/setup/index'
,
meta
:
{
orderNo
:
90000
,
hideChildrenInMenu
:
true
,
icon
:
'simple-icons:about-dot-me'
,
title
:
t
(
'routes.demo.setup.page'
),
},
...
...
src/router/routes/modules/demo/system.ts
浏览文件 @
913c22c8
...
...
@@ -9,6 +9,7 @@ const system: AppRouteModule = {
component
:
LAYOUT
,
redirect
:
'/system/account'
,
meta
:
{
orderNo
:
2000
,
icon
:
'ion:settings-outline'
,
title
:
t
(
'routes.demo.system.moduleName'
),
},
...
...
@@ -26,6 +27,7 @@ const system: AppRouteModule = {
path
:
'account_detail/:id'
,
name
:
'AccountDetail'
,
meta
:
{
hideMenu
:
true
,
title
:
t
(
'routes.demo.system.account_detail'
),
ignoreKeepAlive
:
true
,
showMenu
:
false
,
...
...
src/settings/projectSetting.ts
浏览文件 @
913c22c8
...
...
@@ -24,7 +24,7 @@ const setting: ProjectConfig = {
settingButtonPosition
:
SettingButtonPositionEnum
.
AUTO
,
// Permission mode
permissionMode
:
PermissionModeEnum
.
RO
LE
,
permissionMode
:
PermissionModeEnum
.
RO
UTE_MAPPING
,
// Permission-related cache is stored in sessionStorage or localStorage
permissionCacheType
:
CacheTypeEnum
.
LOCAL
,
...
...
src/store/modules/app.ts
浏览文件 @
913c22c8
...
...
@@ -103,6 +103,6 @@ export const useAppStore = defineStore({
});
// Need to be used outside the setup
export
function
useAppStoreWi
d
thOut
()
{
export
function
useAppStoreWithOut
()
{
return
useAppStore
(
store
);
}
src/store/modules/permission.ts
浏览文件 @
913c22c8
...
...
@@ -4,7 +4,7 @@ import { defineStore } from 'pinia';
import
{
store
}
from
'/@/store'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
import
{
useUserStore
}
from
'./user'
;
import
{
useAppStoreWi
d
thOut
}
from
'./app'
;
import
{
useAppStoreWithOut
}
from
'./app'
;
import
{
toRaw
}
from
'vue'
;
import
{
transformObjToRoute
,
flatMultiLevelRoutes
}
from
'/@/router/helper/routeHelper'
;
import
{
transformRouteToMenu
}
from
'/@/router/helper/menuHelper'
;
...
...
@@ -32,6 +32,7 @@ interface PermissionState {
lastBuildMenuTime
:
number
;
// Backstage menu list
backMenuList
:
Menu
[];
frontMenuList
:
Menu
[];
}
export
const
usePermissionStore
=
defineStore
({
id
:
'app-permission'
,
...
...
@@ -43,6 +44,8 @@ export const usePermissionStore = defineStore({
lastBuildMenuTime
:
0
,
// Backstage menu list
backMenuList
:
[],
// menu List
frontMenuList
:
[],
}),
getters
:
{
getPermCodeList
():
string
[]
|
number
[]
{
...
...
@@ -51,6 +54,9 @@ export const usePermissionStore = defineStore({
getBackMenuList
():
Menu
[]
{
return
this
.
backMenuList
;
},
getFrontMenuList
():
Menu
[]
{
return
this
.
frontMenuList
;
},
getLastBuildMenuTime
():
number
{
return
this
.
lastBuildMenuTime
;
},
...
...
@@ -68,6 +74,10 @@ export const usePermissionStore = defineStore({
list
?.
length
>
0
&&
this
.
setLastBuildMenuTime
();
},
setFrontMenuList
(
list
:
Menu
[])
{
this
.
frontMenuList
=
list
;
},
setLastBuildMenuTime
()
{
this
.
lastBuildMenuTime
=
new
Date
().
getTime
();
},
...
...
@@ -88,25 +98,41 @@ export const usePermissionStore = defineStore({
async
buildRoutesAction
():
Promise
<
AppRouteRecordRaw
[]
>
{
const
{
t
}
=
useI18n
();
const
userStore
=
useUserStore
();
const
appStore
=
useAppStoreWi
d
thOut
();
const
appStore
=
useAppStoreWithOut
();
let
routes
:
AppRouteRecordRaw
[]
=
[];
const
roleList
=
toRaw
(
userStore
.
getRoleList
)
||
[];
const
{
permissionMode
=
projectSetting
.
permissionMode
}
=
appStore
.
getProjectConfig
;
// role permissions
if
(
permissionMode
===
PermissionModeEnum
.
ROLE
)
{
const
routeFilter
=
(
route
:
AppRouteRecordRaw
)
=>
{
const
{
meta
}
=
route
;
const
{
roles
}
=
meta
||
{};
if
(
!
roles
)
return
true
;
return
roleList
.
some
((
role
)
=>
roles
.
includes
(
role
));
};
switch
(
permissionMode
)
{
case
PermissionModeEnum
.
ROLE
:
routes
=
filter
(
asyncRoutes
,
routeFilter
);
routes
=
routes
.
filter
(
routeFilter
);
// Convert multi-level routing to level 2 routing
routes
=
flatMultiLevelRoutes
(
routes
);
break
;
case
PermissionModeEnum
.
ROUTE_MAPPING
:
routes
=
filter
(
asyncRoutes
,
routeFilter
);
routes
=
routes
.
filter
(
routeFilter
);
const
menuList
=
transformRouteToMenu
(
asyncRoutes
);
menuList
.
sort
((
a
,
b
)
=>
{
return
(
a
.
meta
?.
orderNo
||
0
)
-
(
b
.
meta
?.
orderNo
||
0
);
});
this
.
setFrontMenuList
(
menuList
);
// Convert multi-level routing to level 2 routing
routes
=
flatMultiLevelRoutes
(
routes
);
break
;
// If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below
}
else
if
(
permissionMode
===
PermissionModeEnum
.
BACK
)
{
case
PermissionModeEnum
.
BACK
:
const
{
createMessage
}
=
useMessage
();
createMessage
.
loading
({
...
...
@@ -133,7 +159,9 @@ export const usePermissionStore = defineStore({
routeList
=
flatMultiLevelRoutes
(
routeList
);
routes
=
[
PAGE_NOT_FOUND_ROUTE
,
...
routeList
];
break
;
}
routes
.
push
(
ERROR_LOG_ROUTE
);
return
routes
;
},
...
...
@@ -141,6 +169,6 @@ export const usePermissionStore = defineStore({
});
// Need to be used outside the setup
export
function
usePermissionStoreWi
d
thOut
()
{
export
function
usePermissionStoreWithOut
()
{
return
usePermissionStore
(
store
);
}
src/store/modules/user.ts
浏览文件 @
913c22c8
...
...
@@ -128,6 +128,6 @@ export const useUserStore = defineStore({
});
// Need to be used outside the setup
export
function
useUserStoreWi
d
thOut
()
{
export
function
useUserStoreWithOut
()
{
return
useUserStore
(
store
);
}
src/utils/http/axios/checkStatus.ts
浏览文件 @
913c22c8
...
...
@@ -3,7 +3,7 @@ import { useMessage } from '/@/hooks/web/useMessage';
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
// import router from '/@/router';
// import { PageEnum } from '/@/enums/pageEnum';
import
{
useUserStoreWi
d
thOut
}
from
'/@/store/modules/user'
;
import
{
useUserStoreWithOut
}
from
'/@/store/modules/user'
;
import
projectSetting
from
'/@/settings/projectSetting'
;
import
{
SessionTimeoutProcessingEnum
}
from
'/@/enums/appEnum'
;
...
...
@@ -17,7 +17,7 @@ export function checkStatus(
errorMessageMode
:
ErrorMessageMode
=
'message'
):
void
{
const
{
t
}
=
useI18n
();
const
userStore
=
useUserStoreWi
d
thOut
();
const
userStore
=
useUserStoreWithOut
();
let
errMessage
=
''
;
switch
(
status
)
{
...
...
types/vue-router.d.ts
浏览文件 @
913c22c8
...
...
@@ -2,6 +2,7 @@ export {};
declare
module
'vue-router'
{
interface
RouteMeta
extends
Record
<
string
|
number
|
symbol
,
unknown
>
{
orderNo
?:
number
;
// title
title
:
string
;
// Whether to ignore permissions
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论