mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
feat: Custom sorting function style
This commit is contained in:
parent
d8d15c8902
commit
f7b3cc9ae0
|
|
@ -1,34 +1,31 @@
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
|
|
||||||
|
|
||||||
export const SORT_TYPES = {
|
export const SORT_TYPES = {
|
||||||
CREATE_TIME_ASC: 'createTime-asc',
|
CREATE_TIME_ASC: 'createTime-asc',
|
||||||
CREATE_TIME_DESC: 'createTime-desc',
|
CREATE_TIME_DESC: 'createTime-desc',
|
||||||
NAME_ASC: 'name-asc',
|
NAME_ASC: 'name-asc',
|
||||||
NAME_DESC: 'name-desc',
|
NAME_DESC: 'name-desc',
|
||||||
CUSTOM: 'custom'
|
CUSTOM: 'custom',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type SortType = typeof SORT_TYPES[keyof typeof SORT_TYPES]
|
export type SortType = (typeof SORT_TYPES)[keyof typeof SORT_TYPES]
|
||||||
|
|
||||||
export const SORT_MENU_CONFIG = [
|
export const SORT_MENU_CONFIG = [
|
||||||
{
|
{
|
||||||
title: 'time',
|
title: 'time',
|
||||||
items: [
|
items: [
|
||||||
{ label: t('components.folder.ascTime', '按创建时间升序'), value: SORT_TYPES.CREATE_TIME_ASC},
|
{ label: t('components.folder.ascTime'), value: SORT_TYPES.CREATE_TIME_ASC },
|
||||||
{ label: t('components.folder.descTime', '按创建时间降序'), value: SORT_TYPES.CREATE_TIME_DESC },
|
{ label: t('components.folder.descTime'), value: SORT_TYPES.CREATE_TIME_DESC },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'name',
|
title: 'name',
|
||||||
items: [
|
items: [
|
||||||
{ label: t('components.folder.ascName', '按名称升序'), value: SORT_TYPES.NAME_ASC },
|
{ label: t('components.folder.ascName'), value: SORT_TYPES.NAME_ASC },
|
||||||
{ label: t('components.folder.descName', '按名称降序'), value: SORT_TYPES.NAME_DESC },
|
{ label: t('components.folder.descName'), value: SORT_TYPES.NAME_DESC },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
items: [
|
items: [{ label: t('components.folder.sortDrop'), value: SORT_TYPES.CUSTOM }],
|
||||||
{ label: t('components.folder.custom', '按用户拖拽排序'), value: SORT_TYPES.CUSTOM },
|
},
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
@ -1,27 +1,29 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="folder-tree">
|
<div class="folder-tree">
|
||||||
<div class="flex ml-4 p-8 pb-0 items-start">
|
<div class="flex ml-4 p-8 pb-0">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="filterText"
|
v-model="filterText"
|
||||||
:placeholder="$t('common.search')"
|
:placeholder="$t('common.search')"
|
||||||
prefix-icon="Search"
|
prefix-icon="Search"
|
||||||
clearable
|
clearable
|
||||||
class="flex-[5]"
|
|
||||||
/>
|
/>
|
||||||
<el-dropdown trigger="click" :teleported="false" @command="switchSortMethod">
|
<el-dropdown trigger="click" :teleported="false" @command="switchSortMethod">
|
||||||
<el-button class="flex-1 ml-4">
|
<el-button class="ml-4">
|
||||||
<el-icon><Operation /></el-icon>
|
<el-icon><Operation /></el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu class="w-180">
|
||||||
<template v-for="(group, index) in SORT_MENU_CONFIG" :key="index">
|
<template v-for="(group, index) in SORT_MENU_CONFIG" :key="index">
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
v-for="obj in group.items"
|
v-for="obj in group.items"
|
||||||
:key="obj.value"
|
:key="obj.value"
|
||||||
:command="obj.value"
|
:command="obj.value"
|
||||||
class="mr-2"
|
:class="`${currentSort === obj.value ? 'active' : ''} flex-between`"
|
||||||
>
|
>
|
||||||
{{ obj.label }}
|
<span>
|
||||||
|
{{ obj.label }}
|
||||||
|
</span>
|
||||||
|
|
||||||
<el-icon v-if="currentSort === obj.value" class="ml-4">
|
<el-icon v-if="currentSort === obj.value" class="ml-4">
|
||||||
<Check />
|
<Check />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
|
|
@ -272,7 +274,7 @@ function addOrderToTree(nodes: any, parentId: string): Node[] {
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
let positions = getPositions(parentId)
|
const positions = getPositions(parentId)
|
||||||
let needSave = false
|
let needSave = false
|
||||||
|
|
||||||
nodes.forEach((node: any) => {
|
nodes.forEach((node: any) => {
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,6 @@ const noMore = computed(
|
||||||
props.size > 0 && props.size === props.total && props.total > props.page_size && !props.loading,
|
props.size > 0 && props.size === props.total && props.total > props.page_size && !props.loading,
|
||||||
)
|
)
|
||||||
const disabledScroll = computed(() => props.size > 0 && (props.loading || noMore.value))
|
const disabledScroll = computed(() => props.size > 0 && (props.loading || noMore.value))
|
||||||
console.log(props.size)
|
|
||||||
console.log(props.total)
|
|
||||||
console.log(props.page_size)
|
|
||||||
function loadData() {
|
function loadData() {
|
||||||
if (props.total > props.page_size) {
|
if (props.total > props.page_size) {
|
||||||
current.value += 1
|
current.value += 1
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu style="width: 180px">
|
<el-dropdown-menu class="w-180">
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
v-for="(lang, index) in langList"
|
v-for="(lang, index) in langList"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<el-col :xs="24" :sm="24" :md="14" :lg="14" :xl="14" class="right-container flex-center">
|
<el-col :xs="24" :sm="24" :md="14" :lg="14" :xl="14" class="right-container flex-center">
|
||||||
<el-dropdown trigger="click" type="primary" class="lang" v-if="lang">
|
<el-dropdown trigger="click" type="primary" class="lang" v-if="lang">
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu style="width: 180px">
|
<el-dropdown-menu class="w-180">
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
v-for="(lang, index) in langList"
|
v-for="(lang, index) in langList"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,10 @@ export default {
|
||||||
folderNamePlaceholder: 'Please enter a name',
|
folderNamePlaceholder: 'Please enter a name',
|
||||||
requiredMessage: 'Please select a folder',
|
requiredMessage: 'Please select a folder',
|
||||||
deleteConfirmMessage: 'Folders with resources will be deleted, please be cautious.',
|
deleteConfirmMessage: 'Folders with resources will be deleted, please be cautious.',
|
||||||
|
ascTime: 'Sort by creation time ascending',
|
||||||
|
descTime: 'Sort by creation time descending',
|
||||||
|
ascName: 'Sort by name ascending',
|
||||||
|
descName: 'Sort by name descending',
|
||||||
|
custom: 'Sort by user drag-and-drop',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,10 @@ export default {
|
||||||
folderNamePlaceholder: '请输入名称',
|
folderNamePlaceholder: '请输入名称',
|
||||||
requiredMessage: '请选择文件夹',
|
requiredMessage: '请选择文件夹',
|
||||||
deleteConfirmMessage: '文件夹下的资源会被删除,请谨慎操作。',
|
deleteConfirmMessage: '文件夹下的资源会被删除,请谨慎操作。',
|
||||||
|
ascTime: '按创建时间升序',
|
||||||
|
descTime: '按创建时间降序',
|
||||||
|
ascName: '按名称升序',
|
||||||
|
descName: '按名称降序',
|
||||||
|
sortDrop: '按用户拖拽排序',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,10 @@ export default {
|
||||||
folderNamePlaceholder: '請輸入名稱',
|
folderNamePlaceholder: '請輸入名稱',
|
||||||
requiredMessage: '請選擇文件夾',
|
requiredMessage: '請選擇文件夾',
|
||||||
deleteConfirmMessage: '文件夹下的資源會被刪除,請謹慎操作。',
|
deleteConfirmMessage: '文件夹下的資源會被刪除,請謹慎操作。',
|
||||||
|
ascTime: '按創建時間升序',
|
||||||
|
descTime: '按創建時間降序',
|
||||||
|
ascName: '按名稱升序',
|
||||||
|
descName: '按名稱降序',
|
||||||
|
sortDrop: '按用戶拖拽排序',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,9 @@ h5 {
|
||||||
.w-120 {
|
.w-120 {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
|
.w-180 {
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
.w-240 {
|
.w-240 {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,9 +150,9 @@
|
||||||
<div class="mb-16">
|
<div class="mb-16">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="history_day"
|
v-model="history_day"
|
||||||
class="mr-12"
|
class="mr-12 w-180"
|
||||||
@change="changeDayHandle"
|
@change="changeDayHandle"
|
||||||
style="width: 180px"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in dayOptions"
|
v-for="item in dayOptions"
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@
|
||||||
style="height: 120px"
|
style="height: 120px"
|
||||||
@submitDialog="submitNoReferencesPromptDialog"
|
@submitDialog="submitNoReferencesPromptDialog"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('views.application.form.roleSettings.placeholder', {
|
$t('views.application.form.prompt.placeholder', {
|
||||||
data: '{data}',
|
data: '{data}',
|
||||||
question: '{question}',
|
question: '{question}',
|
||||||
})
|
})
|
||||||
|
|
@ -288,7 +288,7 @@
|
||||||
style="height: 150px"
|
style="height: 150px"
|
||||||
@submitDialog="submitPromptDialog"
|
@submitDialog="submitPromptDialog"
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('views.application.form.roleSettings.placeholder', {
|
$t('views.application.form.prompt.placeholder', {
|
||||||
data: '{data}',
|
data: '{data}',
|
||||||
question: '{question}',
|
question: '{question}',
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,8 @@
|
||||||
</div>
|
</div>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="history_day"
|
v-model="history_day"
|
||||||
class="ml-12"
|
class="ml-12 w-180"
|
||||||
@change="changeDayHandle"
|
@change="changeDayHandle"
|
||||||
style="width: 180px"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in dayOptions"
|
v-for="item in dayOptions"
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,13 @@
|
||||||
<div class="authentication-setting__main main-calc-height">
|
<div class="authentication-setting__main main-calc-height">
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<div class="form-container p-24" v-loading="loading">
|
<div class="form-container p-24" v-loading="loading">
|
||||||
<el-form ref="authFormRef" :model="form" label-position="top"
|
<el-form
|
||||||
require-asterisk-position="right" @submit.prevent>
|
ref="authFormRef"
|
||||||
|
:model="form"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
@submit.prevent
|
||||||
|
>
|
||||||
<!-- 登录方式选择框 -->
|
<!-- 登录方式选择框 -->
|
||||||
<el-form-item
|
<el-form-item
|
||||||
:label="$t('views.system.default_login')"
|
:label="$t('views.system.default_login')"
|
||||||
|
|
@ -17,8 +22,11 @@
|
||||||
prop="default_value"
|
prop="default_value"
|
||||||
style="padding-top: 16px"
|
style="padding-top: 16px"
|
||||||
>
|
>
|
||||||
<el-radio-group v-model="form.default_value" class="radio-group"
|
<el-radio-group
|
||||||
style="margin-left: 10px;">
|
v-model="form.default_value"
|
||||||
|
class="radio-group"
|
||||||
|
style="margin-left: 10px"
|
||||||
|
>
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="method in loginMethods"
|
v-for="method in loginMethods"
|
||||||
:key="method.value"
|
:key="method.value"
|
||||||
|
|
@ -41,13 +49,13 @@
|
||||||
]"
|
]"
|
||||||
prop="max_attempts"
|
prop="max_attempts"
|
||||||
>
|
>
|
||||||
<el-row :gutter="16" style="margin-left: 10px;">
|
<el-row :gutter="16" style="margin-left: 10px">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<span style="font-size: 13px;">
|
<span style="font-size: 13px">
|
||||||
{{ $t('views.system.loginFailed') }}
|
{{ $t('views.system.loginFailed') }}
|
||||||
</span>
|
</span>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
style="margin-left: 8px;"
|
style="margin-left: 8px"
|
||||||
v-model="form.max_attempts"
|
v-model="form.max_attempts"
|
||||||
:min="-1"
|
:min="-1"
|
||||||
:max="10"
|
:max="10"
|
||||||
|
|
@ -55,20 +63,20 @@
|
||||||
controls-position="right"
|
controls-position="right"
|
||||||
@change="onMaxAttemptsChange"
|
@change="onMaxAttemptsChange"
|
||||||
/>
|
/>
|
||||||
<span style="margin-left: 8px; font-size: 13px;">
|
<span style="margin-left: 8px; font-size: 13px">
|
||||||
{{ $t('views.system.loginFailedMessage') }}
|
{{ $t('views.system.loginFailedMessage') }}
|
||||||
</span>
|
</span>
|
||||||
<span style="margin-left: 8px; color: #909399; font-size: 12px;">
|
<span style="margin-left: 8px; color: #909399; font-size: 12px">
|
||||||
({{ $t('views.system.display_codeTip') }})
|
({{ $t('views.system.display_codeTip') }})
|
||||||
</span>
|
</span>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="24" style="margin-top: 8px;">
|
<el-col :span="24" style="margin-top: 8px">
|
||||||
<span style="font-size: 13px;">
|
<span style="font-size: 13px">
|
||||||
{{ $t('views.system.loginFailed') }}
|
{{ $t('views.system.loginFailed') }}
|
||||||
</span>
|
</span>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
style="margin-left: 8px;"
|
style="margin-left: 8px"
|
||||||
v-model="form.failed_attempts"
|
v-model="form.failed_attempts"
|
||||||
:min="-1"
|
:min="-1"
|
||||||
:max="10"
|
:max="10"
|
||||||
|
|
@ -76,42 +84,42 @@
|
||||||
controls-position="right"
|
controls-position="right"
|
||||||
@change="onFailedAttemptsChange"
|
@change="onFailedAttemptsChange"
|
||||||
/>
|
/>
|
||||||
<span style="margin-left: 8px; font-size: 13px;">
|
<span style="margin-left: 8px; font-size: 13px">
|
||||||
{{ $t('views.system.failedTip') }}
|
{{ $t('views.system.failedTip') }}
|
||||||
</span>
|
</span>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
style="margin-left: 8px;"
|
style="margin-left: 8px"
|
||||||
v-model="form.lock_time"
|
v-model="form.lock_time"
|
||||||
:min="1"
|
:min="1"
|
||||||
:step="1"
|
:step="1"
|
||||||
controls-position="right"
|
controls-position="right"
|
||||||
/>
|
/>
|
||||||
<span style="margin-left: 8px; font-size: 13px;">
|
<span style="margin-left: 8px; font-size: 13px">
|
||||||
{{ $t('views.system.minute') }}
|
{{ $t('views.system.minute') }}
|
||||||
</span>
|
</span>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
:label="$t('views.system.third_party_user_default_role')"
|
:label="$t('views.system.third_party_user_default_role')"
|
||||||
:rules="[
|
:rules="[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: $t('views.system.thirdPartyUserDefaultRoleRequired'),
|
message: $t('views.system.thirdPartyUserDefaultRoleRequired'),
|
||||||
trigger: 'change',
|
trigger: 'change',
|
||||||
},
|
},
|
||||||
]">
|
]"
|
||||||
<el-row :gutter="16" style="margin-left: 10px;">
|
>
|
||||||
|
<el-row :gutter="16" style="margin-left: 10px">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<div style="display: flex; align-items: center; gap: 8px; min-width: 0;">
|
<div style="display: flex; align-items: center; gap: 8px; min-width: 0">
|
||||||
<span style="font-size: 13px; white-space: nowrap;">
|
<span style="font-size: 13px; white-space: nowrap">
|
||||||
{{ $t('views.role.member.role') }}
|
{{ $t('views.role.member.role') }}
|
||||||
</span>
|
</span>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="form.role_id"
|
v-model="form.role_id"
|
||||||
:placeholder="`${$t('common.selectPlaceholder')}${$t('views.role.member.role')}`"
|
:placeholder="`${$t('common.selectPlaceholder')}${$t('views.role.member.role')}`"
|
||||||
style="flex: 1; min-width: 180px;"
|
style="flex: 1; min-width: 180px"
|
||||||
@change="handleRoleChange"
|
@change="handleRoleChange"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
|
|
@ -119,20 +127,19 @@
|
||||||
:key="role.id"
|
:key="role.id"
|
||||||
:label="role.name"
|
:label="role.name"
|
||||||
:value="role.id"
|
:value="role.id"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12" v-if="user.isEE() && showWorkspaceSelector">
|
<el-col :span="12" v-if="user.isEE() && showWorkspaceSelector">
|
||||||
<div style="display: flex; align-items: center; gap: 8px; min-width: 0;">
|
<div style="display: flex; align-items: center; gap: 8px; min-width: 0">
|
||||||
<span style="font-size: 13px; white-space: nowrap;">
|
<span style="font-size: 13px; white-space: nowrap">
|
||||||
{{ $t('views.role.member.workspace') }}
|
{{ $t('views.role.member.workspace') }}
|
||||||
</span>
|
</span>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="form.workspace_id"
|
v-model="form.workspace_id"
|
||||||
:placeholder="`${$t('common.selectPlaceholder')}${$t('views.role.member.workspace')}`"
|
:placeholder="`${$t('common.selectPlaceholder')}${$t('views.role.member.workspace')}`"
|
||||||
style="flex: 1; min-width: 180px;"
|
style="flex: 1; min-width: 180px"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="workspace in workspaceOptions"
|
v-for="workspace in workspaceOptions"
|
||||||
|
|
@ -144,21 +151,20 @@
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div style="margin-top:16px;">
|
<div style="margin-top: 16px">
|
||||||
<span
|
<span
|
||||||
v-hasPermission="
|
v-hasPermission="
|
||||||
new ComplexPermission([RoleConst.ADMIN], [PermissionConst.LOGIN_AUTH_EDIT], [], 'OR')
|
new ComplexPermission([RoleConst.ADMIN], [PermissionConst.LOGIN_AUTH_EDIT], [], 'OR')
|
||||||
"
|
"
|
||||||
class="mr-12"
|
class="mr-12"
|
||||||
>
|
>
|
||||||
<!-- 直接调用 submit,不传参 -->
|
<!-- 直接调用 submit,不传参 -->
|
||||||
<el-button @click="submit" type="primary" :disabled="loading">
|
<el-button @click="submit" type="primary" :disabled="loading">
|
||||||
{{ $t('common.save') }}
|
{{ $t('common.save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
|
@ -166,20 +172,20 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, onMounted, computed} from "vue";
|
import { ref, onMounted, computed } from 'vue'
|
||||||
import {ComplexPermission} from "@/utils/permission/type";
|
import { ComplexPermission } from '@/utils/permission/type'
|
||||||
import {PermissionConst, RoleConst} from "@/utils/permission/data";
|
import { PermissionConst, RoleConst } from '@/utils/permission/data'
|
||||||
import type {FormInstance} from 'element-plus';
|
import type { FormInstance } from 'element-plus'
|
||||||
import {t} from "@/locales";
|
import { t } from '@/locales'
|
||||||
import authApi from "@/api/system-settings/auth-setting.ts";
|
import authApi from '@/api/system-settings/auth-setting.ts'
|
||||||
import {MsgSuccess} from "@/utils/message.ts";
|
import { MsgSuccess } from '@/utils/message.ts'
|
||||||
import WorkspaceApi from "@/api/workspace/workspace.ts";
|
import WorkspaceApi from '@/api/workspace/workspace.ts'
|
||||||
import useStore from "@/stores";
|
import useStore from '@/stores'
|
||||||
|
|
||||||
const loginMethods = ref<Array<{ label: string; value: string }>>([]);
|
const loginMethods = ref<Array<{ label: string; value: string }>>([])
|
||||||
const loading = ref(false);
|
const loading = ref(false)
|
||||||
// 明确允许 null,避免未挂载时访问出错
|
// 明确允许 null,避免未挂载时访问出错
|
||||||
const authFormRef = ref<FormInstance | null>(null);
|
const authFormRef = ref<FormInstance | null>(null)
|
||||||
|
|
||||||
const form = ref<any>({
|
const form = ref<any>({
|
||||||
default_value: 'LOCAL',
|
default_value: 'LOCAL',
|
||||||
|
|
@ -192,35 +198,35 @@ const form = ref<any>({
|
||||||
|
|
||||||
const normalizeInputValue = (val: number | null): number => {
|
const normalizeInputValue = (val: number | null): number => {
|
||||||
// 若输入为空或无法转换为有效数字,默认设为 1
|
// 若输入为空或无法转换为有效数字,默认设为 1
|
||||||
let normalizedVal = typeof val === 'number' ? Math.trunc(val) : NaN;
|
let normalizedVal = typeof val === 'number' ? Math.trunc(val) : NaN
|
||||||
if (!Number.isFinite(normalizedVal)) {
|
if (!Number.isFinite(normalizedVal)) {
|
||||||
normalizedVal = 1;
|
normalizedVal = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (normalizedVal === 0) {
|
if (normalizedVal === 0) {
|
||||||
normalizedVal = 1;
|
normalizedVal = 1
|
||||||
} else if (normalizedVal < -1) {
|
} else if (normalizedVal < -1) {
|
||||||
normalizedVal = -1;
|
normalizedVal = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
return normalizedVal;
|
return normalizedVal
|
||||||
};
|
}
|
||||||
|
|
||||||
const onFailedAttemptsChange = (val: number | null) => {
|
const onFailedAttemptsChange = (val: number | null) => {
|
||||||
form.value.failed_attempts = normalizeInputValue(val);
|
form.value.failed_attempts = normalizeInputValue(val)
|
||||||
};
|
}
|
||||||
|
|
||||||
const onMaxAttemptsChange = (val: number | null) => {
|
const onMaxAttemptsChange = (val: number | null) => {
|
||||||
form.value.max_attempts = normalizeInputValue(val);
|
form.value.max_attempts = normalizeInputValue(val)
|
||||||
};
|
}
|
||||||
|
|
||||||
// 提交:使用 authFormRef.value.validate() 的 Promise 风格,并保证 loading 在 finally 中恢复
|
// 提交:使用 authFormRef.value.validate() 的 Promise 风格,并保证 loading 在 finally 中恢复
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
const formRef = authFormRef.value;
|
const formRef = authFormRef.value
|
||||||
if (!formRef) return;
|
if (!formRef) return
|
||||||
try {
|
try {
|
||||||
await formRef.validate();
|
await formRef.validate()
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
const params = {
|
const params = {
|
||||||
default_value: form.value.default_value,
|
default_value: form.value.default_value,
|
||||||
max_attempts: form.value.max_attempts,
|
max_attempts: form.value.max_attempts,
|
||||||
|
|
@ -228,85 +234,92 @@ const submit = async () => {
|
||||||
lock_time: form.value.lock_time,
|
lock_time: form.value.lock_time,
|
||||||
role_id: form.value.role_id,
|
role_id: form.value.role_id,
|
||||||
workspace_id: form.value.workspace_id,
|
workspace_id: form.value.workspace_id,
|
||||||
};
|
}
|
||||||
await authApi.putLoginSetting(params);
|
await authApi.putLoginSetting(params)
|
||||||
MsgSuccess(t('common.saveSuccess'));
|
MsgSuccess(t('common.saveSuccess'))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// 验证或请求失败:按需处理,避免未捕获异常
|
// 验证或请求失败:按需处理,避免未捕获异常
|
||||||
// console.error(err);
|
// console.error(err);
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const roleOptions = ref<Array<{ id: string; name: string, type?: string }>>([]);
|
const roleOptions = ref<Array<{ id: string; name: string; type?: string }>>([])
|
||||||
const workspaceOptions = ref<Array<{ id: string; name: string }>>([]);
|
const workspaceOptions = ref<Array<{ id: string; name: string }>>([])
|
||||||
const {user} = useStore();
|
const { user } = useStore()
|
||||||
const selectedRoleType = ref<string>(''); // 存储选中角色类型,用于控制 workspace 显示
|
const selectedRoleType = ref<string>('') // 存储选中角色类型,用于控制 workspace 显示
|
||||||
const showWorkspaceSelector = computed(() => selectedRoleType.value !== 'ADMIN');
|
const showWorkspaceSelector = computed(() => selectedRoleType.value !== 'ADMIN')
|
||||||
|
|
||||||
// 当角色变更时更新 selectedRoleType
|
// 当角色变更时更新 selectedRoleType
|
||||||
const handleRoleChange = (roleId: string) => {
|
const handleRoleChange = (roleId: string) => {
|
||||||
const selectedRole = roleOptions.value.find(role => role.id === roleId);
|
const selectedRole = roleOptions.value.find((role) => role.id === roleId)
|
||||||
selectedRoleType.value = selectedRole?.type || '';
|
selectedRoleType.value = selectedRole?.type || ''
|
||||||
};
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const isEE = typeof user?.isEE === 'function' ? user.isEE() : false;
|
const isEE = typeof user?.isEE === 'function' ? user.isEE() : false
|
||||||
|
|
||||||
// 并行请求:角色列表 + 登录设置;若为 EE 同时请求 workspace 列表
|
// 并行请求:角色列表 + 登录设置;若为 EE 同时请求 workspace 列表
|
||||||
const roleP = WorkspaceApi.getWorkspaceRoleList().then(r => r).catch(() => ({data: []}));
|
const roleP = WorkspaceApi.getWorkspaceRoleList()
|
||||||
const settingP = authApi.getLoginSetting().then(r => r).catch(() => ({data: {}}));
|
.then((r) => r)
|
||||||
const tasks: Promise<any>[] = [roleP, settingP];
|
.catch(() => ({ data: [] }))
|
||||||
|
const settingP = authApi
|
||||||
|
.getLoginSetting()
|
||||||
|
.then((r) => r)
|
||||||
|
.catch(() => ({ data: {} }))
|
||||||
|
const tasks: Promise<any>[] = [roleP, settingP]
|
||||||
if (isEE) {
|
if (isEE) {
|
||||||
tasks.push(WorkspaceApi.getWorkspaceList().then(r => r).catch(() => ({data: []})));
|
tasks.push(
|
||||||
|
WorkspaceApi.getWorkspaceList()
|
||||||
|
.then((r) => r)
|
||||||
|
.catch(() => ({ data: [] })),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await Promise.all(tasks);
|
const results = await Promise.all(tasks)
|
||||||
const roleRes = results[0] ?? {data: []};
|
const roleRes = results[0] ?? { data: [] }
|
||||||
const settingRes = results[1] ?? {data: {}};
|
const settingRes = results[1] ?? { data: {} }
|
||||||
const workspaceRes = isEE ? results[2] ?? {data: []} : null;
|
const workspaceRes = isEE ? (results[2] ?? { data: [] }) : null
|
||||||
|
|
||||||
// 处理角色列表(尽早回显)
|
// 处理角色列表(尽早回显)
|
||||||
const rolesData = Array.isArray(roleRes?.data) ? roleRes.data : [];
|
const rolesData = Array.isArray(roleRes?.data) ? roleRes.data : []
|
||||||
roleOptions.value = rolesData.map((item: any) => ({
|
roleOptions.value = rolesData.map((item: any) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
type: item.type
|
type: item.type,
|
||||||
}));
|
}))
|
||||||
|
|
||||||
// 处理 setting(合并默认值,避免访问未定义)
|
// 处理 setting(合并默认值,避免访问未定义)
|
||||||
const data = settingRes?.data ?? {};
|
const data = settingRes?.data ?? {}
|
||||||
form.value = {
|
form.value = {
|
||||||
...form.value,
|
...form.value,
|
||||||
...data,
|
...data,
|
||||||
failed_attempts: data.failed_attempts ?? form.value.failed_attempts ?? 5,
|
failed_attempts: data.failed_attempts ?? form.value.failed_attempts ?? 5,
|
||||||
lock_time: data.lock_time ?? form.value.lock_time ?? 10,
|
lock_time: data.lock_time ?? form.value.lock_time ?? 10,
|
||||||
role_id: data.role_id ?? form.value.role_id ?? 'USER',
|
role_id: data.role_id ?? form.value.role_id ?? 'USER',
|
||||||
workspace_id: data.workspace_id ?? form.value.workspace_id ?? 'default'
|
workspace_id: data.workspace_id ?? form.value.workspace_id ?? 'default',
|
||||||
};
|
}
|
||||||
loginMethods.value = Array.isArray(data.auth_types) ? data.auth_types : [];
|
loginMethods.value = Array.isArray(data.auth_types) ? data.auth_types : []
|
||||||
|
|
||||||
// 处理 workspace 列表(如果需要)
|
// 处理 workspace 列表(如果需要)
|
||||||
if (isEE && workspaceRes) {
|
if (isEE && workspaceRes) {
|
||||||
const wks = Array.isArray(workspaceRes.data) ? workspaceRes.data : [];
|
const wks = Array.isArray(workspaceRes.data) ? workspaceRes.data : []
|
||||||
workspaceOptions.value = wks.map((item: any) => ({id: item.id, name: item.name}));
|
workspaceOptions.value = wks.map((item: any) => ({ id: item.id, name: item.name }))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化 selectedRoleType(基于当前回显的 role_id 与已加载的 roleOptions)
|
// 初始化 selectedRoleType(基于当前回显的 role_id 与已加载的 roleOptions)
|
||||||
const initRole = roleOptions.value.find(r => r.id === form.value.role_id);
|
const initRole = roleOptions.value.find((r) => r.id === form.value.role_id)
|
||||||
selectedRoleType.value = initRole?.type || '';
|
selectedRoleType.value = initRole?.type || ''
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// overall error, 保持默认回显
|
// overall error, 保持默认回显
|
||||||
// console.error(e);
|
// console.error(e);
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,8 @@
|
||||||
<div>
|
<div>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="history_day"
|
v-model="history_day"
|
||||||
class="mr-12"
|
class="mr-12 w-180"
|
||||||
@change="changeDayHandle"
|
@change="changeDayHandle"
|
||||||
style="width: 180px"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in dayOptions"
|
v-for="item in dayOptions"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue