feat 对接路由生成

This commit is contained in:
xxm
2022-10-13 17:35:05 +08:00
parent 8112891db2
commit bb79544e81
19 changed files with 139 additions and 117 deletions

View File

@@ -1,20 +1,17 @@
# 是否打开mock # 是否打开mock
VITE_USE_MOCK = true VITE_USE_MOCK=true
# 发布路径 # 发布路径
VITE_PUBLIC_PATH = / VITE_PUBLIC_PATH=/
# 跨域代理,您可以配置多个 ,请注意,没有换行符 # 跨域代理,您可以配置多个 ,请注意,没有换行符
VITE_PROXY = [["/api","http://localhost:9999"],["/upload","http://localhost:3300/upload"]] VITE_PROXY=[["/api","http://localhost:9999"],["/upload","http://localhost:3300/upload"]]
#VITE_PROXY = [["/api","http://localhost:9999"],["/upload","http://localhost:3300/upload"]]
# VITE_PROXY=[["/api","http://localhost:9999"]]
# 控制台不输出console # 控制台不输出console
VITE_DROP_CONSOLE = false VITE_DROP_CONSOLE=false
# 接口地址 # 接口地址
VITE_GLOB_API_URL=/api VITE_GLOB_API_URL=/api
#VITE_GLOB_API_URL=/basic-api
# 文件上传地址 # 文件上传地址
VITE_GLOB_UPLOAD_URL=/upload VITE_GLOB_UPLOAD_URL=/upload

View File

@@ -1,35 +1,33 @@
# Whether to open mock # 是否打开mock
VITE_USE_MOCK = true VITE_USE_MOCK=true
# public path # 发布路径
VITE_PUBLIC_PATH = / VITE_PUBLIC_PATH=/
# Delete console # 控制台不输出console
VITE_DROP_CONSOLE = true VITE_DROP_CONSOLE=true
# Whether to enable gzip or brotli compression # 是否启用gzip或brotli压缩可选: gzip | brotli |
# Optional: gzip | brotli | none # 无如果您需要多个表单,可以使用 '' 分隔
# If you need multiple forms, you can use `,` to separate VITE_BUILD_COMPRESS='none'
VITE_BUILD_COMPRESS = 'none'
# Whether to delete origin files when using compress, default false # 使用compress时是否删除origin文件默认为false
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE=false
# Basic interface address SPA # 接口地址
VITE_GLOB_API_URL=/basic-api VITE_GLOB_API_URL=/api
# File upload address optional # 文件上传地址
# It can be forwarded by nginx or write the actual address directly
VITE_GLOB_UPLOAD_URL=/upload VITE_GLOB_UPLOAD_URL=/upload
# Interface prefix # 接口前缀
VITE_GLOB_API_URL_PREFIX= VITE_GLOB_API_URL_PREFIX=
# Whether to enable image compression # Whether to enable image compression
VITE_USE_IMAGEMIN= true VITE_USE_IMAGEMIN=true
# use pwa # use pwa
VITE_USE_PWA = false VITE_USE_PWA=false
# Is it compatible with older browsers # Is it compatible with older browsers
VITE_LEGACY = false VITE_LEGACY = false

View File

@@ -1,14 +1,14 @@
import { defHttp } from '/@/utils/http/axios' import { defHttp } from '/@/utils/http/axios'
import { getMenuListResultModel } from './model/menuModel' import { getMenuListResultModel, MenuAndResource } from './model/menuModel'
import { Result } from '/#/axios'
enum Api { enum Api {
GetMenuList = '/getMenuList', GetMenuList = '/getMenuList',
} }
/** /**
* @description: Get user menu based on id * 获取菜单和权限码
*/ */
export const getPermissions = (clientCode: string) => {
export const getMenuList = () => { return defHttp.get<Result<MenuAndResource>>({ url: '/role/menu/getPermissions', params: { clientCode } })
return defHttp.get<getMenuListResultModel>({ url: Api.GetMenuList })
} }

View File

@@ -14,3 +14,18 @@ export interface RouteItem {
* @description: Get menu return value * @description: Get menu return value
*/ */
export type getMenuListResultModel = RouteItem[] export type getMenuListResultModel = RouteItem[]
/**
* 用户菜单及资源权限返回类
*/
export interface MenuAndResource {
// 权限码
resourcePerms: Array<string>
// 菜单
menus: Array<PermMenu>
}
/**
* 权限菜单
*/
export interface PermMenu {}

View File

@@ -41,6 +41,7 @@ export function usePermission() {
* @param id * @param id
*/ */
async function resume() { async function resume() {
console.log('重置和重新获得权限资源信息')
const tabStore = useMultipleTabStore() const tabStore = useMultipleTabStore()
tabStore.clearCacheTabs() tabStore.clearCacheTabs()
resetRouter() resetRouter()

View File

@@ -1,13 +1,11 @@
<template> <template>
<Footer :class="prefixCls" v-if="getShowLayoutFooter" ref="footerRef"> <Footer :class="prefixCls" v-if="getShowLayoutFooter" ref="footerRef">
<div :class="`${prefixCls}__links`"> <!-- <div :class="`${prefixCls}__links`">-->
<a @click="openWindow(SITE_URL)">{{ t('layout.footer.onlinePreview') }}</a> <!-- <a @click="openWindow(SITE_URL)">{{ t('layout.footer.onlinePreview') }}</a>-->
<!-- <GithubFilled @click="openWindow(GITHUB_URL)" :class="`${prefixCls}__github`" />-->
<GithubFilled @click="openWindow(GITHUB_URL)" :class="`${prefixCls}__github`" /> <!-- <a @click="openWindow(DOC_URL)">{{ t('layout.footer.onlineDocument') }}</a>-->
<!-- </div>-->
<a @click="openWindow(DOC_URL)">{{ t('layout.footer.onlineDocument') }}</a> <div>Copyright &copy;2020 Bootx出品</div>
</div>
<div>Copyright &copy;2021 Bootx</div>
</Footer> </Footer>
</template> </template>

View File

@@ -46,7 +46,7 @@ function createPageGuard(router: Router) {
}) })
} }
// Used to handle page loading status // 用于处理页面加载状态
function createPageLoadingGuard(router: Router) { function createPageLoadingGuard(router: Router) {
const userStore = useUserStoreWithOut() const userStore = useUserStoreWithOut()
const appStore = useAppStoreWithOut() const appStore = useAppStoreWithOut()

View File

@@ -32,16 +32,15 @@ export function createParamMenuGuard(router: Router) {
next() next()
}) })
} }
const getPermissionMode = () => { const getPermissionMode = () => {
const appStore = useAppStoreWithOut() const appStore = useAppStoreWithOut()
return appStore.getProjectConfig.permissionMode return appStore.getProjectConfig.permissionMode
} }
// 后端模式
const isBackMode = () => { const isBackMode = () => {
return getPermissionMode() === PermissionModeEnum.BACK return getPermissionMode() === PermissionModeEnum.BACK
} }
// 路由映射
const isRouteMappingMode = () => { const isRouteMappingMode = () => {
return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING
} }

View File

@@ -15,6 +15,10 @@ const ROOT_PATH = RootRoute.path
const whitePathList: PageEnum[] = [LOGIN_PATH] const whitePathList: PageEnum[] = [LOGIN_PATH]
/**
* 路由守卫
* @param router
*/
export function createPermissionGuard(router: Router) { export function createPermissionGuard(router: Router) {
const userStore = useUserStoreWithOut() const userStore = useUserStoreWithOut()
const permissionStore = usePermissionStoreWithOut() const permissionStore = usePermissionStoreWithOut()
@@ -22,6 +26,7 @@ export function createPermissionGuard(router: Router) {
if ( if (
from.path === ROOT_PATH && from.path === ROOT_PATH &&
to.path === PageEnum.BASE_HOME && to.path === PageEnum.BASE_HOME &&
// TODO 没有用户首页配置这个字段
userStore.getUserInfo.homePath && userStore.getUserInfo.homePath &&
userStore.getUserInfo.homePath !== PageEnum.BASE_HOME userStore.getUserInfo.homePath !== PageEnum.BASE_HOME
) { ) {
@@ -94,7 +99,8 @@ export function createPermissionGuard(router: Router) {
next() next()
return return
} }
console.log(`路由守卫`)
// 重载菜单
const routes = await permissionStore.buildRoutesAction() const routes = await permissionStore.buildRoutesAction()
routes.forEach((route) => { routes.forEach((route) => {

View File

@@ -41,7 +41,9 @@ export function transformMenuModule(menuModule: MenuModule): Menu {
return menuList[0] return menuList[0]
} }
// 将路由转换成菜单 /**
* 将路由转换成菜单
*/
export function transformRouteToMenu(routeModList: AppRouteModule[], routerMapping = false) { export function transformRouteToMenu(routeModList: AppRouteModule[], routerMapping = false) {
// 借助 lodash 深拷贝 // 借助 lodash 深拷贝
const cloneRouteModList = cloneDeep(routeModList) const cloneRouteModList = cloneDeep(routeModList)

View File

@@ -64,8 +64,9 @@ function dynamicImport(dynamicViewsModules: Record<string, () => Promise<Recorda
} }
} }
// Turn background objects into routing objects /**
// 将背景对象变成路由对象 * 将后端对象变成路由对象
*/
export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] { export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] {
routeList.forEach((route) => { routeList.forEach((route) => {
const component = route.component as string const component = route.component as string

View File

@@ -25,7 +25,7 @@ export const router = createRouter({
scrollBehavior: () => ({ left: 0, top: 0 }), scrollBehavior: () => ({ left: 0, top: 0 }),
}) })
// reset router // 重置路由
export function resetRouter() { export function resetRouter() {
router.getRoutes().forEach((route) => { router.getRoutes().forEach((route) => {
const { name } = route const { name } = route

View File

@@ -1,4 +1,4 @@
// Used to configure the general configuration of some components without modifying the components // 用于配置某些组件的通用配置,而无需修改组件
import type { SorterResult } from '../components/Table' import type { SorterResult } from '../components/Table'

View File

@@ -12,95 +12,94 @@ import {
import { SIDE_BAR_BG_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST } from './designSetting' import { SIDE_BAR_BG_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST } from './designSetting'
import { primaryColor } from '../../build/config/themeConfig' import { primaryColor } from '../../build/config/themeConfig'
// ! You need to clear the browser cache after the change // ! 更改后需要清除浏览器缓存
const setting: ProjectConfig = { const setting: ProjectConfig = {
// Whether to show the configuration button // 是否显示配置按钮
showSettingButton: true, showSettingButton: true,
// Whether to show the theme switch button // 是否显示主题切换按钮
showDarkModeToggle: true, showDarkModeToggle: true,
// `Settings` button position // `Settings` 按钮位置
settingButtonPosition: SettingButtonPositionEnum.AUTO, settingButtonPosition: SettingButtonPositionEnum.AUTO,
// Permission mode // 权限模式
permissionMode: PermissionModeEnum.ROUTE_MAPPING, permissionMode: PermissionModeEnum.BACK,
// Permission-related cache is stored in sessionStorage or localStorage // 权限相关缓存存储在sessionStoragelocalStorage
permissionCacheType: CacheTypeEnum.LOCAL, permissionCacheType: CacheTypeEnum.LOCAL,
// Session timeout processing // 会话超时处理
sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP, sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP,
// color // 颜色
themeColor: primaryColor, themeColor: primaryColor,
// Website gray mode, open for possible mourning dates // 灰度迷失
grayMode: false, grayMode: false,
// Color Weakness Mode // 色日模式
colorWeak: false, colorWeak: false,
// Whether to cancel the menu, the top, the multi-tab page display, for possible embedded in other systems // 是否取消菜单,顶部,多选项卡页面显示,对于可能嵌入其他系统
fullContent: false, fullContent: false,
// content mode // 内容模式
contentMode: ContentEnum.FULL, contentMode: ContentEnum.FULL,
// Whether to display the logo // 是否显示Logo
showLogo: true, showLogo: true,
// Whether to show footer // 是否显示页脚
showFooter: false, showFooter: false,
// Header configuration // 页头设置
headerSetting: { headerSetting: {
// header bg color // 背景颜色
bgColor: HEADER_PRESET_BG_COLOR_LIST[0], bgColor: HEADER_PRESET_BG_COLOR_LIST[0],
// Fixed at the top // 固定在顶部
fixed: true, fixed: true,
// Whether to show top // 是否显示
show: true, show: true,
// theme // 主题
theme: ThemeEnum.LIGHT, theme: ThemeEnum.LIGHT,
// Whether to enable the lock screen function // 是否启用锁屏功能
useLockPage: true, useLockPage: true,
// Whether to show the full screen button // 是否显示全屏按钮
showFullScreen: true, showFullScreen: true,
// Whether to show the document button // 是否显示文档按钮
showDoc: true, showDoc: true,
// Whether to show the notification button // 是否显示通知按钮
showNotice: true, showNotice: true,
// Whether to display the menu search // 是否显示搜索按钮
showSearch: true, showSearch: true,
}, },
// Menu configuration // 菜单配置
menuSetting: { menuSetting: {
// sidebar menu bg color // 背景颜色
bgColor: SIDE_BAR_BG_COLOR_LIST[0], bgColor: SIDE_BAR_BG_COLOR_LIST[0],
// Whether to fix the left menu // 是否固定
fixed: true, fixed: true,
// Menu collapse // Menu collapse
collapsed: false, collapsed: false,
// When sider hide because of the responsive layout // 当sider因为响应式布局而隐藏时
siderHidden: false, siderHidden: false,
// Whether to display the menu name when folding the menu // 折叠菜单时是否显示菜单名称
collapsedShowTitle: false, collapsedShowTitle: false,
// Whether it can be dragged // 是否可以拖动仅限于左侧菜单的打开,鼠标在菜单的右侧有一个拖动条
// Only limited to the opening of the left menu, the mouse has a drag bar on the right side of the menu
canDrag: false, canDrag: false,
// Whether to show no dom // Whether to show no dom 是否不显示dom
show: true, show: true,
// Whether to show dom // Whether to show dom 是否隐藏
hidden: false, hidden: false,
// Menu width // Menu width 宽度
menuWidth: 210, menuWidth: 210,
// Menu mode // Menu mode 模式
mode: MenuModeEnum.INLINE, mode: MenuModeEnum.INLINE,
// Menu type // Menu 类型
type: MenuTypeEnum.SIDEBAR, type: MenuTypeEnum.SIDEBAR,
// Menu theme // Menu 主题
theme: ThemeEnum.DARK, theme: ThemeEnum.DARK,
// Split menu // Split menu
split: false, split: false,

View File

@@ -78,6 +78,7 @@ export const useAppStore = defineStore({
}, },
async resetAllState() { async resetAllState() {
console.log('重置所有状态')
resetRouter() resetRouter()
Persistent.clearAll() Persistent.clearAll()
}, },

View File

@@ -18,7 +18,7 @@ import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'
import { filter } from '/@/utils/helper/treeHelper' import { filter } from '/@/utils/helper/treeHelper'
import { getMenuList } from '/@/api/sys/menu' import { getMenuList, getPermissions } from "/@/api/sys/menu";
import { getPermCode } from '/@/api/sys/user' import { getPermCode } from '/@/api/sys/user'
import { useMessage } from '/@/hooks/web/useMessage' import { useMessage } from '/@/hooks/web/useMessage'
@@ -103,14 +103,22 @@ export const usePermissionStore = defineStore({
this.backMenuList = [] this.backMenuList = []
this.lastBuildMenuTime = 0 this.lastBuildMenuTime = 0
}, },
async changePermissionCode() { /**
const codeList = await getPermCode() * 权限码和菜单更新
this.setPermCodeList(codeList) */
async changeMenuAndPermCode() {
const {
data: { menus, resourcePerms },
} = await getPermissions('admin')
console.log(menus)
// this.setBackMenuList(menus)
this.setPermCodeList(resourcePerms)
}, },
// 构建路由 /**
* 构建路由
*/
async buildRoutesAction(): Promise<AppRouteRecordRaw[]> { async buildRoutesAction(): Promise<AppRouteRecordRaw[]> {
const { t } = useI18n()
const userStore = useUserStore() const userStore = useUserStore()
const appStore = useAppStoreWithOut() const appStore = useAppStoreWithOut()
@@ -141,7 +149,8 @@ export const usePermissionStore = defineStore({
* */ * */
const patchHomeAffix = (routes: AppRouteRecordRaw[]) => { const patchHomeAffix = (routes: AppRouteRecordRaw[]) => {
if (!routes || routes.length === 0) return if (!routes || routes.length === 0) return
let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME // let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME
let homePath: string = PageEnum.BASE_HOME
function patcher(routes: AppRouteRecordRaw[], parentPath = '') { function patcher(routes: AppRouteRecordRaw[], parentPath = '') {
if (parentPath) parentPath = parentPath + '/' if (parentPath) parentPath = parentPath + '/'
@@ -180,7 +189,7 @@ export const usePermissionStore = defineStore({
routes = flatMultiLevelRoutes(routes) routes = flatMultiLevelRoutes(routes)
break break
// 路由映射, 默认进入该case // 路由映射, 默认进入该case(不用了)
case PermissionModeEnum.ROUTE_MAPPING: case PermissionModeEnum.ROUTE_MAPPING:
// 对非一级路由进行过滤 // 对非一级路由进行过滤
routes = filter(asyncRoutes, routeFilter) routes = filter(asyncRoutes, routeFilter)
@@ -196,7 +205,6 @@ export const usePermissionStore = defineStore({
menuList.sort((a, b) => { menuList.sort((a, b) => {
return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0) return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0)
}) })
// 设置菜单列表 // 设置菜单列表
this.setFrontMenuList(menuList) this.setFrontMenuList(menuList)
@@ -205,38 +213,34 @@ export const usePermissionStore = defineStore({
routes = flatMultiLevelRoutes(routes) routes = flatMultiLevelRoutes(routes)
break break
// If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below // 后端控制 现在在用的方案
// 如果确定不需要做后台动态权限,请在下方评论整个判断
case PermissionModeEnum.BACK: case PermissionModeEnum.BACK:
const { createMessage } = useMessage() const { createMessage } = useMessage()
createMessage.loading({ createMessage.loading({
content: t('sys.app.menuLoading'), content: '菜单加载中...',
duration: 1, duration: 1,
}) })
// !Simulate to obtain permission codes from the background,
// 模拟从后台获取权限码,
// this function may only need to be executed once, and the actual project can be put at the right time by itself
// 这个功能可能只需要执行一次,实际项目可以自己放在合适的时间
let routeList: AppRouteRecordRaw[] = [] let routeList: AppRouteRecordRaw[] = []
// 获取菜单和权限码
try { try {
await this.changePermissionCode() await this.changeMenuAndPermCode()
routeList = (await getMenuList()) as AppRouteRecordRaw[] // 获取菜单列表
routeList = this.backMenuList as any
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} }
// Dynamically introduce components
// 动态引入组件 // 动态引入组件
console.log(routeList)
routeList = transformObjToRoute(routeList) routeList = transformObjToRoute(routeList)
// Background routing to menu structure
// 后台路由到菜单结构 // 后台路由到菜单结构
const backMenuList = transformRouteToMenu(routeList) const backMenuList = transformRouteToMenu(routeList)
this.setBackMenuList(backMenuList) this.setBackMenuList(backMenuList)
// remove meta.ignoreRoute item
// 删除 meta.ignoreRoute 项 // 删除 meta.ignoreRoute 项
routeList = filter(routeList, routeRemoveIgnoreFilter) routeList = filter(routeList, routeRemoveIgnoreFilter)
routeList = routeList.filter(routeRemoveIgnoreFilter) routeList = routeList.filter(routeRemoveIgnoreFilter)

View File

@@ -107,12 +107,13 @@ export const useUserStore = defineStore({
this.setSessionTimeout(false) this.setSessionTimeout(false)
} else { } else {
const permissionStore = usePermissionStore() const permissionStore = usePermissionStore()
console.log(permissionStore)
if (!permissionStore.isDynamicAddedRoute) { if (!permissionStore.isDynamicAddedRoute) {
// 构建路由
const routes = await permissionStore.buildRoutesAction() const routes = await permissionStore.buildRoutesAction()
routes.forEach((route) => { routes.forEach((route) => {
router.addRoute(route as unknown as RouteRecordRaw) router.addRoute(route as unknown as RouteRecordRaw)
}) })
// 404路由
router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw) router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw)
permissionStore.setDynamicAddedRoute(true) permissionStore.setDynamicAddedRoute(true)
} }

View File

@@ -10,13 +10,13 @@
<a-spin :spinning="confirmLoading"> <a-spin :spinning="confirmLoading">
<a-form class="small-from-item" ref="formRef" :label-col="labelCol" :wrapper-col="wrapperCol"> <a-form class="small-from-item" ref="formRef" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item label="主键" :hidden="true"> <a-form-item label="主键" :hidden="true">
<Input v-model:value="form.id" :disabled="showable" /> <a-input v-model:value="form.id" :disabled="showable" />
</a-form-item> </a-form-item>
<a-form-item label="编码" v-bind="validateInfos.code" name="code"> <a-form-item label="编码" v-bind="validateInfos.code" name="code">
<Input v-model:value="form.code" :disabled="showable" @blur="validate('code')" placeholder="请输入编码" /> <a-input v-model:value="form.code" :disabled="showable" @blur="validate('code')" placeholder="请输入编码" />
</a-form-item> </a-form-item>
<a-form-item label="名称" v-bind="validateInfos.name" name="name"> <a-form-item label="名称" v-bind="validateInfos.name" name="name">
<Input v-model:value="form.name" :disabled="showable" @blur="validate('name')" placeholder="请输入名称" /> <a-input v-model:value="form.name" :disabled="showable" @blur="validate('name')" placeholder="请输入名称" />
</a-form-item> </a-form-item>
<a-form-item label="启用状态" v-bind="validateInfos.enable" name="enable"> <a-form-item label="启用状态" v-bind="validateInfos.enable" name="enable">
<a-switch checked-children="" un-checked-children="" v-model:checked="form.enable" :disabled="showable || form.system" /> <a-switch checked-children="" un-checked-children="" v-model:checked="form.enable" :disabled="showable || form.system" />

View File

@@ -10,13 +10,13 @@
<a-spin :spinning="confirmLoading"> <a-spin :spinning="confirmLoading">
<a-form class="small-from-item" ref="formRef" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol"> <a-form class="small-from-item" ref="formRef" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item label="主键" name="id" :hidden="true"> <a-form-item label="主键" name="id" :hidden="true">
<Input v-model:value="form.id" :disabled="showable" /> <a-input v-model:value="form.id" :disabled="showable" />
</a-form-item> </a-form-item>
<a-form-item label="编码" name="code"> <a-form-item label="编码" name="code">
<Input v-model:value="form.code" :disabled="showable" placeholder="请输入登录方式编码" /> <a-input v-model:value="form.code" :disabled="showable" placeholder="请输入登录方式编码" />
</a-form-item> </a-form-item>
<a-form-item label="名称" name="name"> <a-form-item label="名称" name="name">
<Input v-model:value="form.name" :disabled="showable" placeholder="请输入登录方式名称" /> <a-input v-model:value="form.name" :disabled="showable" placeholder="请输入登录方式名称" />
</a-form-item> </a-form-item>
<a-form-item label="类型" name="type"> <a-form-item label="类型" name="type">
<a-radio-group v-model:value="form.type" button-style="solid"> <a-radio-group v-model:value="form.type" button-style="solid">
@@ -35,7 +35,7 @@
<a-switch checked-children="" un-checked-children="" v-model:checked="form.captcha" :disabled="showable" /> <a-switch checked-children="" un-checked-children="" v-model:checked="form.captcha" :disabled="showable" />
</a-form-item> </a-form-item>
<a-form-item label="超时时间(分钟)" name="timeout"> <a-form-item label="超时时间(分钟)" name="timeout">
<Input-number <a-input-number
v-model:value="form.timeout" v-model:value="form.timeout"
:disabled="showable" :disabled="showable"
:precision="0" :precision="0"
@@ -45,7 +45,7 @@
/> />
</a-form-item> </a-form-item>
<a-form-item label="密码可错误次数" name="pwdErrNum" v-show="form.type === PASSWORD"> <a-form-item label="密码可错误次数" name="pwdErrNum" v-show="form.type === PASSWORD">
<Input-number <a-input-number
v-model:value="form.pwdErrNum" v-model:value="form.pwdErrNum"
:disabled="showable" :disabled="showable"
:min="-1" :min="-1"