diff --git a/ui/src/api/API_README.md b/ui/src/api/API_README.md index 28119a94ad4..a0e54d6ed52 100644 --- a/ui/src/api/API_README.md +++ b/ui/src/api/API_README.md @@ -56,6 +56,10 @@ Admin 与 Chat 分别维护请求客户端和业务接口。 `import WorkspaceApi from '@/api/admin/system/workspace'`;System 登录设置使用 `import AuthSettingApi from '@/api/admin/system/settings/auth-setting'`。 +系统登录设置的 `system_options` 仅用于登录方式选项,默认登录方式从已选 `login_methods` 中选择。 +保存仅提交 `login_methods`、`default_value`、`max_attempts`、`failed_attempts`、`lock_time`、 +`role_id`、`workspace_id` 和 `permission`,不透传查询响应中的选项或 `group_id`。 + ## 枚举与类型组织 `enums/state.ts` 的 `STATE_TYPES` 维护跨业务复用的任务状态,联合类型 `State` 定义在 @@ -155,8 +159,9 @@ API 枚举与类型统一在 `src/api` 范围内管理,相关规则由本文 `admin/system/chat-management/portal-setting.ts` 通过 Admin `/portal` 读取和局部保存门户配置, 公共类型维护在 `types/portal.ts`。JSON 用于访问开关和认证、跨域配置,门户名称与 Logo 使用 FormData;保存返回完整配置,页面以该返回值作为唯一数据来源。 -认证配置保留未编辑字段,仅提交后端读取的 `login_value`、`max_attempts`、`failed_attempts`、 -`lock_time`;跨域地址提交 `cross_domain_list` 数组,不另建 `cors_config`。 +认证设置的登录方式选项来自 `auth_config.system_options`,默认登录方式从草稿已选的 `login_value` +中选择。认证配置仅提交 `login_value`、`type`、`max_attempts`、`failed_attempts`、`lock_time`, +不透传查询响应中的选项;跨域地址提交 `cross_domain_list` 数组,不另建 `cors_config`。 ### 当前账号密码 diff --git a/ui/src/views/VIEW_README.md b/ui/src/views/VIEW_README.md index d4bd2b4eb71..fbd8e439393 100644 --- a/ui/src/views/VIEW_README.md +++ b/ui/src/views/VIEW_README.md @@ -368,7 +368,8 @@ View 负责路由、资源与模式、图加载、保存/发布/调试编排 查询失败展示重新加载入口,不展示默认开关;保存期间使用 loading 与 inert,失败保留已保存配置。 知识库或资源范围变化时重新查询;示例与地址来自响应,只读展示/复制,不在前端拼接。 - 门户设置已通过 Portal API 持久化,JSON 保存开关、认证及 `cross_domain_list`,FormData 保存名称/Logo。 - 成功以完整响应回显,保留现有编辑权限;认证选项来自 LoginSetting,跨域地址按行清理,取消不回写。 + 成功以完整响应回显,保留现有编辑权限;认证选项来自门户配置的 `auth_config.system_options`, + 默认登录方式仅展示草稿中已选的 `login_value`;跨域地址按行清理,取消不回写。 - 用户导入、改密、批量角色/配额流程留在各自业务目录;工作空间成员按用户联动角色行选择, 删除按 `user_relation_id` 去重,不按用户 ID 丢弃角色记录。 - 登录页使用 `formEl.validate` 回调和清晰的 LDAP/本地分支,不额外抽象或改写提交控制流程。 diff --git a/ui/src/views/system/chat-management/portal-setting/components/ButtonPortalAuthSetting.vue b/ui/src/views/system/chat-management/portal-setting/components/ButtonPortalAuthSetting.vue index a800b827871..36cd9fcadc3 100644 --- a/ui/src/views/system/chat-management/portal-setting/components/ButtonPortalAuthSetting.vue +++ b/ui/src/views/system/chat-management/portal-setting/components/ButtonPortalAuthSetting.vue @@ -2,43 +2,36 @@ import { computed, reactive, ref, useTemplateRef } from 'vue' import type { FormInstance, FormRules } from 'element-plus' import { LOGIN_METHOD } from '@/api/enums' -import type { LoginMethod, OptionItem, PortalSetting, PortalSettingPayload } from '@/api/types' -import { LOGIN_METHOD_LABELS } from '@/constants/auth' +import type { PortalAuthConfig, PortalSetting, PortalSettingPayload } from '@/api/types' const props = defineProps<{ disabled: boolean; setting: PortalSetting; saving: boolean; save: (payload: PortalSettingPayload) => Promise }>() -/* 可用登录方式与默认登录方式均取自后端返回的门户 auth_config */ -const authConfig = computed(() => props.setting.auth_config ?? {}) - -const loginMethodOptions = computed(() => { - const values = (authConfig.value.system_options ?? []).map((option) => option.value) - return values.length ? values : [LOGIN_METHOD.LOCAL] -}) - -const defaultLoginMethodOptions = computed[]>(() => { - const authTypes = authConfig.value.auth_types ?? [] - return authTypes.length ? authTypes : (authConfig.value.system_options ?? []) -}) +/* 登录方式选项来自 system_options,默认登录方式仅允许选择草稿中已选的 login_value */ +const loginMethodOptions = ref>([]) +const defaultLoginMethodOptions = computed(() => + loginMethodOptions.value.filter(({ value }) => authForm.login_value.some((loginMethod) => loginMethod === value)), +) const authVisible = ref(false) const enableAuthAfterSave = ref(false) const authFormRef = useTemplateRef('authFormRef') const authForm = reactive({ - loginMethods: [LOGIN_METHOD.LOCAL] as string[], - default_value: LOGIN_METHOD.LOCAL as string, - maxAttempts: 1, - failedAttempts: 5, - lockTime: 10, + login_value: [LOGIN_METHOD.LOCAL] as string[], + type: LOGIN_METHOD.LOCAL as string, + max_attempts: 1, + failed_attempts: 5, + lock_time: 10, }) + const authRules: FormRules = { - loginMethods: [{ type: 'array', required: true, min: 1, message: '请选择至少一种登录方式', trigger: 'change' }], - default_value: [{ required: true, message: '请选择默认登录方式', trigger: 'change' }], + login_value: [{ type: 'array', required: true, min: 1, message: '请选择至少一种登录方式', trigger: 'change' }], + type: [{ required: true, message: '请选择默认登录方式', trigger: 'change' }], } /* 登录方式变化时,确保默认登录方式仍为已启用的方式 */ function handleLoginMethodsChange(loginMethods: string[]) { - if (!loginMethods.includes(authForm.default_value)) { - authForm.default_value = loginMethods[0] ?? LOGIN_METHOD.LOCAL + if (!loginMethods.includes(authForm.type)) { + authForm.type = loginMethods[0] ?? '' } } @@ -47,16 +40,17 @@ function open(enableAfterSave = false) { if (props.disabled || props.saving) return enableAuthAfterSave.value = enableAfterSave - const config = authConfig.value + const config = props.setting.auth_config ?? {} + loginMethodOptions.value = config.system_options ?? [] const loginMethods = [...(config.login_value?.length ? config.login_value : [LOGIN_METHOD.LOCAL])] const defaultType = config.type ?? LOGIN_METHOD.LOCAL - const default_value = loginMethods.includes(defaultType) ? defaultType : loginMethods[0] ?? LOGIN_METHOD.LOCAL + const type = loginMethods.includes(defaultType) ? defaultType : (loginMethods[0] ?? LOGIN_METHOD.LOCAL) Object.assign(authForm, { - loginMethods, - default_value, - maxAttempts: config.max_attempts ?? 1, - failedAttempts: config.failed_attempts ?? 5, - lockTime: config.lock_time ?? 10, + login_value: loginMethods, + type, + max_attempts: config.max_attempts ?? 1, + failed_attempts: config.failed_attempts ?? 5, + lock_time: config.lock_time ?? 10, }) authVisible.value = true } @@ -68,16 +62,16 @@ function handleOpenAuthSetting() { function handleClosed() { enableAuthAfterSave.value = false Object.assign(authForm, { - loginMethods: [LOGIN_METHOD.LOCAL], - default_value: LOGIN_METHOD.LOCAL, - maxAttempts: 1, - failedAttempts: 5, - lockTime: 10, + login_value: [LOGIN_METHOD.LOCAL], + type: LOGIN_METHOD.LOCAL, + max_attempts: 1, + failed_attempts: 5, + lock_time: 10, }) authFormRef.value?.clearValidate() } -/* 保存认证配置,仅提交后端读取的字段并保留其余配置 */ +/* 保存认证配置,仅提交表单字段 */ function handleSaveAuthSetting() { if (props.disabled || props.saving) return @@ -87,12 +81,11 @@ function handleSaveAuthSetting() { .save({ ...(enableAuthAfterSave.value ? { enable_auth: true } : {}), auth_config: { - ...props.setting.auth_config, - login_value: [...authForm.loginMethods], - type: authForm.default_value, - max_attempts: authForm.maxAttempts, - failed_attempts: authForm.failedAttempts, - lock_time: authForm.lockTime, + login_value: [...authForm.login_value], + type: authForm.type, + max_attempts: authForm.max_attempts, + failed_attempts: authForm.failed_attempts, + lock_time: authForm.lock_time, }, }) .then(() => { @@ -119,15 +112,15 @@ defineExpose({ open }) require-asterisk-position="right" @submit.prevent > - - - + + + + {{ loginMethodOption.label }} + - - + +
登录失败 - + 次显示验证码
登录失败 - + 次,锁定账号 - + 分钟
diff --git a/ui/src/views/system/chat-management/portal-setting/index.vue b/ui/src/views/system/chat-management/portal-setting/index.vue index 0e7279d2de5..cbf8d351359 100644 --- a/ui/src/views/system/chat-management/portal-setting/index.vue +++ b/ui/src/views/system/chat-management/portal-setting/index.vue @@ -72,7 +72,7 @@ function handleAccessChange(field: AccessField, value: string | number | boolean return savePortalSetting({ [field]: Boolean(value) }) } -/* 认证配置保存,payload 已保留未编辑字段 */ +/* 认证配置保存 */ function savePortalAuthSetting(payload: PortalSettingPayload) { return savePortalSetting(payload) } diff --git a/ui/src/views/system/settings/authentication/components/LoginSetting.vue b/ui/src/views/system/settings/authentication/components/LoginSetting.vue index 1a883697ecb..64c70ac3be8 100644 --- a/ui/src/views/system/settings/authentication/components/LoginSetting.vue +++ b/ui/src/views/system/settings/authentication/components/LoginSetting.vue @@ -1,12 +1,12 @@