2026-01-02 16:17:24 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<PageContainer>
|
|
|
|
|
|
<PageHeader
|
|
|
|
|
|
title="LDAP 配置"
|
|
|
|
|
|
description="配置 LDAP 认证服务"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mt-6 space-y-6">
|
|
|
|
|
|
<CardSection
|
|
|
|
|
|
title="LDAP 服务器配置"
|
|
|
|
|
|
description="配置 LDAP 服务器连接参数"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #actions>
|
|
|
|
|
|
<div class="flex gap-2">
|
|
|
|
|
|
<Button
|
|
|
|
|
|
size="sm"
|
|
|
|
|
|
variant="outline"
|
|
|
|
|
|
:disabled="testLoading"
|
|
|
|
|
|
@click="handleTestConnection"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ testLoading ? '测试中...' : '测试连接' }}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
size="sm"
|
|
|
|
|
|
:disabled="saveLoading"
|
|
|
|
|
|
@click="handleSave"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ saveLoading ? '保存中...' : '保存' }}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
|
|
|
|
<div>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<Label
|
|
|
|
|
|
for="server-url"
|
|
|
|
|
|
class="block text-sm font-medium"
|
|
|
|
|
|
>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
服务器地址
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="server-url"
|
|
|
|
|
|
v-model="ldapConfig.server_url"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="ldap://ldap.example.com:389"
|
|
|
|
|
|
class="mt-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<p class="mt-1 text-xs text-muted-foreground">
|
|
|
|
|
|
格式: ldap://host:389 或 ldaps://host:636
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<Label
|
|
|
|
|
|
for="bind-dn"
|
|
|
|
|
|
class="block text-sm font-medium"
|
|
|
|
|
|
>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
绑定 DN
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="bind-dn"
|
|
|
|
|
|
v-model="ldapConfig.bind_dn"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="cn=admin,dc=example,dc=com"
|
|
|
|
|
|
class="mt-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<p class="mt-1 text-xs text-muted-foreground">
|
|
|
|
|
|
用于连接 LDAP 服务器的管理员 DN
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<Label
|
|
|
|
|
|
for="bind-password"
|
|
|
|
|
|
class="block text-sm font-medium"
|
|
|
|
|
|
>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
绑定密码
|
|
|
|
|
|
</Label>
|
2026-01-06 14:38:42 +08:00
|
|
|
|
<div class="relative mt-1">
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="bind-password"
|
|
|
|
|
|
v-model="ldapConfig.bind_password"
|
|
|
|
|
|
type="password"
|
|
|
|
|
|
:placeholder="hasPassword ? '已设置(留空保持不变)' : '请输入密码'"
|
|
|
|
|
|
:class="(hasPassword || ldapConfig.bind_password) ? 'pr-10' : ''"
|
|
|
|
|
|
autocomplete="new-password"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<button
|
|
|
|
|
|
v-if="hasPassword || ldapConfig.bind_password"
|
|
|
|
|
|
type="button"
|
|
|
|
|
|
class="absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded-full text-muted-foreground/60 hover:text-muted-foreground hover:bg-muted/50 transition-colors"
|
|
|
|
|
|
title="清除密码"
|
2026-01-07 14:55:07 +08:00
|
|
|
|
@click="handleClearPassword"
|
2026-01-06 14:38:42 +08:00
|
|
|
|
>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<svg
|
|
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
|
width="14"
|
|
|
|
|
|
height="14"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
stroke-linecap="round"
|
|
|
|
|
|
stroke-linejoin="round"
|
|
|
|
|
|
><line
|
|
|
|
|
|
x1="18"
|
|
|
|
|
|
y1="6"
|
|
|
|
|
|
x2="6"
|
|
|
|
|
|
y2="18"
|
|
|
|
|
|
/><line
|
|
|
|
|
|
x1="6"
|
|
|
|
|
|
y1="6"
|
|
|
|
|
|
x2="18"
|
|
|
|
|
|
y2="18"
|
|
|
|
|
|
/></svg>
|
2026-01-06 14:38:42 +08:00
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
<p class="mt-1 text-xs text-muted-foreground">
|
|
|
|
|
|
绑定账号的密码
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<Label
|
|
|
|
|
|
for="base-dn"
|
|
|
|
|
|
class="block text-sm font-medium"
|
|
|
|
|
|
>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
基础 DN
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="base-dn"
|
|
|
|
|
|
v-model="ldapConfig.base_dn"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="ou=users,dc=example,dc=com"
|
|
|
|
|
|
class="mt-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<p class="mt-1 text-xs text-muted-foreground">
|
|
|
|
|
|
用户搜索的基础 DN
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<Label
|
|
|
|
|
|
for="user-search-filter"
|
|
|
|
|
|
class="block text-sm font-medium"
|
|
|
|
|
|
>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
用户搜索过滤器
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="user-search-filter"
|
|
|
|
|
|
v-model="ldapConfig.user_search_filter"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="(uid={username})"
|
|
|
|
|
|
class="mt-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<p class="mt-1 text-xs text-muted-foreground">
|
|
|
|
|
|
{username} 会被替换为登录用户名
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<Label
|
|
|
|
|
|
for="username-attr"
|
|
|
|
|
|
class="block text-sm font-medium"
|
|
|
|
|
|
>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
用户名属性
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="username-attr"
|
|
|
|
|
|
v-model="ldapConfig.username_attr"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="uid"
|
|
|
|
|
|
class="mt-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<p class="mt-1 text-xs text-muted-foreground">
|
|
|
|
|
|
常用: uid (OpenLDAP), sAMAccountName (AD)
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<Label
|
|
|
|
|
|
for="email-attr"
|
|
|
|
|
|
class="block text-sm font-medium"
|
|
|
|
|
|
>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
邮箱属性
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="email-attr"
|
|
|
|
|
|
v-model="ldapConfig.email_attr"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="mail"
|
|
|
|
|
|
class="mt-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<Label
|
|
|
|
|
|
for="display-name-attr"
|
|
|
|
|
|
class="block text-sm font-medium"
|
|
|
|
|
|
>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
显示名称属性
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="display-name-attr"
|
|
|
|
|
|
v-model="ldapConfig.display_name_attr"
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="cn"
|
|
|
|
|
|
class="mt-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2026-01-04 16:27:02 +08:00
|
|
|
|
|
|
|
|
|
|
<div>
|
2026-01-07 14:55:07 +08:00
|
|
|
|
<Label
|
|
|
|
|
|
for="connect-timeout"
|
|
|
|
|
|
class="block text-sm font-medium"
|
|
|
|
|
|
>
|
2026-01-04 16:27:02 +08:00
|
|
|
|
连接超时 (秒)
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="connect-timeout"
|
|
|
|
|
|
v-model.number="ldapConfig.connect_timeout"
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
min="1"
|
|
|
|
|
|
max="60"
|
|
|
|
|
|
placeholder="10"
|
|
|
|
|
|
class="mt-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<p class="mt-1 text-xs text-muted-foreground">
|
2026-01-06 14:38:42 +08:00
|
|
|
|
单次 LDAP 操作超时时间 (1-60秒),跨国网络建议 15-30 秒
|
2026-01-04 16:27:02 +08:00
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
2026-01-02 16:17:24 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="mt-6 space-y-4">
|
|
|
|
|
|
<div class="flex items-center justify-between">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<Label class="text-sm font-medium">使用 STARTTLS</Label>
|
|
|
|
|
|
<p class="text-xs text-muted-foreground">
|
|
|
|
|
|
在非 SSL 连接上启用 TLS 加密
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
2026-01-06 14:38:42 +08:00
|
|
|
|
<Switch v-model="ldapConfig.use_starttls" />
|
2026-01-02 16:17:24 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="flex items-center justify-between">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<Label class="text-sm font-medium">启用 LDAP 认证</Label>
|
|
|
|
|
|
<p class="text-xs text-muted-foreground">
|
|
|
|
|
|
允许用户使用 LDAP 账号登录
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
2026-01-06 14:38:42 +08:00
|
|
|
|
<Switch v-model="ldapConfig.is_enabled" />
|
2026-01-02 16:17:24 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="flex items-center justify-between">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<Label class="text-sm font-medium">仅允许 LDAP 登录</Label>
|
|
|
|
|
|
<p class="text-xs text-muted-foreground">
|
|
|
|
|
|
禁用本地账号登录,仅允许 LDAP 认证
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
2026-01-06 14:38:42 +08:00
|
|
|
|
<Switch v-model="ldapConfig.is_exclusive" />
|
2026-01-02 16:17:24 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</CardSection>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</PageContainer>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import { ref, onMounted } from 'vue'
|
|
|
|
|
|
import { PageContainer, PageHeader, CardSection } from '@/components/layout'
|
2026-01-06 14:38:42 +08:00
|
|
|
|
import { Button, Input, Label, Switch } from '@/components/ui'
|
2026-01-02 16:17:24 +08:00
|
|
|
|
import { useToast } from '@/composables/useToast'
|
2026-01-04 11:18:28 +08:00
|
|
|
|
import { adminApi, type LdapConfigUpdateRequest } from '@/api/admin'
|
2026-01-02 16:17:24 +08:00
|
|
|
|
|
|
|
|
|
|
const { success, error } = useToast()
|
|
|
|
|
|
|
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
const saveLoading = ref(false)
|
|
|
|
|
|
const testLoading = ref(false)
|
|
|
|
|
|
const hasPassword = ref(false)
|
2026-01-06 14:38:42 +08:00
|
|
|
|
const clearPassword = ref(false) // 标记是否要清除密码
|
2026-01-02 16:17:24 +08:00
|
|
|
|
|
|
|
|
|
|
const ldapConfig = ref({
|
|
|
|
|
|
server_url: '',
|
|
|
|
|
|
bind_dn: '',
|
|
|
|
|
|
bind_password: '',
|
|
|
|
|
|
base_dn: '',
|
|
|
|
|
|
user_search_filter: '(uid={username})',
|
|
|
|
|
|
username_attr: 'uid',
|
|
|
|
|
|
email_attr: 'mail',
|
|
|
|
|
|
display_name_attr: 'cn',
|
|
|
|
|
|
is_enabled: false,
|
|
|
|
|
|
is_exclusive: false,
|
|
|
|
|
|
use_starttls: false,
|
2026-01-04 16:27:02 +08:00
|
|
|
|
connect_timeout: 10,
|
2026-01-02 16:17:24 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
await loadConfig()
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
async function loadConfig() {
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await adminApi.getLdapConfig()
|
|
|
|
|
|
ldapConfig.value = {
|
|
|
|
|
|
server_url: response.server_url || '',
|
|
|
|
|
|
bind_dn: response.bind_dn || '',
|
|
|
|
|
|
bind_password: '',
|
|
|
|
|
|
base_dn: response.base_dn || '',
|
|
|
|
|
|
user_search_filter: response.user_search_filter || '(uid={username})',
|
|
|
|
|
|
username_attr: response.username_attr || 'uid',
|
|
|
|
|
|
email_attr: response.email_attr || 'mail',
|
|
|
|
|
|
display_name_attr: response.display_name_attr || 'cn',
|
|
|
|
|
|
is_enabled: response.is_enabled || false,
|
|
|
|
|
|
is_exclusive: response.is_exclusive || false,
|
|
|
|
|
|
use_starttls: response.use_starttls || false,
|
2026-01-04 16:27:02 +08:00
|
|
|
|
connect_timeout: response.connect_timeout || 10,
|
2026-01-02 16:17:24 +08:00
|
|
|
|
}
|
2026-01-06 14:38:42 +08:00
|
|
|
|
hasPassword.value = !!response.has_bind_password
|
|
|
|
|
|
clearPassword.value = false
|
2026-01-02 16:17:24 +08:00
|
|
|
|
} catch (err) {
|
|
|
|
|
|
error('加载 LDAP 配置失败')
|
2026-01-06 14:38:42 +08:00
|
|
|
|
console.error('加载 LDAP 配置失败:', err)
|
2026-01-02 16:17:24 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function handleSave() {
|
|
|
|
|
|
saveLoading.value = true
|
|
|
|
|
|
try {
|
2026-01-04 11:18:28 +08:00
|
|
|
|
const payload: LdapConfigUpdateRequest = {
|
2026-01-02 16:17:24 +08:00
|
|
|
|
server_url: ldapConfig.value.server_url,
|
|
|
|
|
|
bind_dn: ldapConfig.value.bind_dn,
|
|
|
|
|
|
base_dn: ldapConfig.value.base_dn,
|
|
|
|
|
|
user_search_filter: ldapConfig.value.user_search_filter,
|
|
|
|
|
|
username_attr: ldapConfig.value.username_attr,
|
|
|
|
|
|
email_attr: ldapConfig.value.email_attr,
|
|
|
|
|
|
display_name_attr: ldapConfig.value.display_name_attr,
|
|
|
|
|
|
is_enabled: ldapConfig.value.is_enabled,
|
|
|
|
|
|
is_exclusive: ldapConfig.value.is_exclusive,
|
|
|
|
|
|
use_starttls: ldapConfig.value.use_starttls,
|
2026-01-04 16:27:02 +08:00
|
|
|
|
connect_timeout: ldapConfig.value.connect_timeout,
|
2026-01-02 16:17:24 +08:00
|
|
|
|
}
|
2026-01-06 14:38:42 +08:00
|
|
|
|
|
|
|
|
|
|
// 优先使用输入的新密码;否则如果标记清除则发送空字符串
|
|
|
|
|
|
let passwordAction: 'unchanged' | 'updated' | 'cleared' = 'unchanged'
|
|
|
|
|
|
if (ldapConfig.value.bind_password) {
|
|
|
|
|
|
payload.bind_password = ldapConfig.value.bind_password
|
|
|
|
|
|
passwordAction = 'updated'
|
|
|
|
|
|
} else if (clearPassword.value) {
|
|
|
|
|
|
payload.bind_password = ''
|
|
|
|
|
|
passwordAction = 'cleared'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-02 16:17:24 +08:00
|
|
|
|
await adminApi.updateLdapConfig(payload)
|
|
|
|
|
|
success('LDAP 配置保存成功')
|
2026-01-06 14:38:42 +08:00
|
|
|
|
|
|
|
|
|
|
if (passwordAction === 'cleared') {
|
|
|
|
|
|
hasPassword.value = false
|
|
|
|
|
|
clearPassword.value = false
|
|
|
|
|
|
} else if (passwordAction === 'updated') {
|
|
|
|
|
|
hasPassword.value = true
|
|
|
|
|
|
clearPassword.value = false
|
|
|
|
|
|
}
|
2026-01-02 16:17:24 +08:00
|
|
|
|
ldapConfig.value.bind_password = ''
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
error('保存 LDAP 配置失败')
|
2026-01-06 14:38:42 +08:00
|
|
|
|
console.error('保存 LDAP 配置失败:', err)
|
2026-01-02 16:17:24 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
saveLoading.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function handleTestConnection() {
|
2026-01-06 14:38:42 +08:00
|
|
|
|
if (clearPassword.value && !ldapConfig.value.bind_password) {
|
|
|
|
|
|
error('已标记清除绑定密码,请先保存或输入新的绑定密码再测试')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-02 16:17:24 +08:00
|
|
|
|
testLoading.value = true
|
|
|
|
|
|
try {
|
2026-01-04 16:27:02 +08:00
|
|
|
|
const payload: LdapConfigUpdateRequest = {
|
|
|
|
|
|
server_url: ldapConfig.value.server_url,
|
|
|
|
|
|
bind_dn: ldapConfig.value.bind_dn,
|
|
|
|
|
|
base_dn: ldapConfig.value.base_dn,
|
|
|
|
|
|
user_search_filter: ldapConfig.value.user_search_filter,
|
|
|
|
|
|
username_attr: ldapConfig.value.username_attr,
|
|
|
|
|
|
email_attr: ldapConfig.value.email_attr,
|
|
|
|
|
|
display_name_attr: ldapConfig.value.display_name_attr,
|
|
|
|
|
|
is_enabled: ldapConfig.value.is_enabled,
|
|
|
|
|
|
is_exclusive: ldapConfig.value.is_exclusive,
|
|
|
|
|
|
use_starttls: ldapConfig.value.use_starttls,
|
|
|
|
|
|
connect_timeout: ldapConfig.value.connect_timeout,
|
|
|
|
|
|
...(ldapConfig.value.bind_password && { bind_password: ldapConfig.value.bind_password }),
|
|
|
|
|
|
}
|
|
|
|
|
|
const response = await adminApi.testLdapConnection(payload)
|
2026-01-02 16:17:24 +08:00
|
|
|
|
if (response.success) {
|
|
|
|
|
|
success('LDAP 连接测试成功')
|
|
|
|
|
|
} else {
|
|
|
|
|
|
error(`LDAP 连接测试失败: ${response.message}`)
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
error('LDAP 连接测试失败')
|
2026-01-06 14:38:42 +08:00
|
|
|
|
console.error('LDAP 连接测试失败:', err)
|
2026-01-02 16:17:24 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
testLoading.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-06 14:38:42 +08:00
|
|
|
|
|
|
|
|
|
|
function handleClearPassword() {
|
|
|
|
|
|
// 如果有输入内容,先清空输入框
|
|
|
|
|
|
if (ldapConfig.value.bind_password) {
|
|
|
|
|
|
ldapConfig.value.bind_password = ''
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
// 标记要清除服务端密码(保存时生效)
|
|
|
|
|
|
if (hasPassword.value) {
|
|
|
|
|
|
clearPassword.value = true
|
|
|
|
|
|
hasPassword.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-02 16:17:24 +08:00
|
|
|
|
</script>
|