feat(ui): 支持外部邮箱启用解绑与账号管理删除功能,发布V2.12.0部署包
Some checks are pending
Security Checks / security (push) Waiting to run
Some checks are pending
Security Checks / security (push) Waiting to run
This commit is contained in:
parent
583b9e88b7
commit
d2fe1f8304
@ -139,6 +139,11 @@ export async function packageRelease(selectedTargets = targets, { workspace = ro
|
||||
const legacyArchive = path.join(releaseRoot, legacyArchiveName)
|
||||
try { await copyFile(archive, legacyArchive) } catch (e) {}
|
||||
}
|
||||
// 同步复制到 out 根目录,满足直接从 out 目录引用的部署习惯
|
||||
try {
|
||||
await copyFile(archive, path.join(outputRoot, archiveName))
|
||||
await copyFile(archive, path.join(outputRoot, legacyArchiveName))
|
||||
} catch (e) {}
|
||||
await rename(stagedReceipt, receipt)
|
||||
await rename(staging, directory)
|
||||
releases.push({ target, directory, archive, receipt })
|
||||
|
||||
@ -1401,4 +1401,19 @@
|
||||
max-width: none !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.external-item-actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.external-item-actions :deep(.el-button) {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@ -337,7 +337,28 @@ export function usePage() {
|
||||
notify('外部安全邮箱绑定成功', 'success')
|
||||
}
|
||||
|
||||
const disableExternalEmail = async item => {
|
||||
const rebindExternalEmail = (item) => {
|
||||
openExternalEmailDialog()
|
||||
}
|
||||
|
||||
const deleteExternalEmail = async item => {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定彻底删除/解绑安全邮箱 ${item.email} 吗?解绑后将移除该邮箱记录。`, '删除外部邮箱', {
|
||||
type: 'warning',
|
||||
confirmButtonText: '确定删除',
|
||||
cancelButtonText: '取消'
|
||||
})
|
||||
const res = await http.post('/api/v1/security/external-email/delete', { id: item.id })
|
||||
if (res.errorNo !== 0) throw new Error(res.errorMsg || '删除外部邮箱失败')
|
||||
await loadSecurityData()
|
||||
await globalStatus.refresh()
|
||||
notify('外部安全邮箱已删除', 'success')
|
||||
} catch (error) {
|
||||
if (error !== 'cancel' && error !== 'close') notify(error?.message || '删除外部邮箱失败')
|
||||
}
|
||||
}
|
||||
|
||||
const disableExternalEmail = async item => {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定停用 ${item.email} 吗?停用后不能用于登录验证和恢复。`, '停用外部邮箱', { type: 'warning' })
|
||||
const res = await http.post('/api/v1/security/external-email/disable', { id: item.id })
|
||||
@ -451,6 +472,6 @@ export function usePage() {
|
||||
externalDialogVisible, ruleForm, rules, submit, registerCredential, renameCredential, revokeCredential,
|
||||
saveSecurityQuestion, generateRecoveryCodes, revealRecoveryCodes, saveRecoveryCodes, revokeRecoveryCodes, openExternalEmailDialog,
|
||||
handleExternalEmailBound,
|
||||
disableExternalEmail, formatTime,
|
||||
rebindExternalEmail, deleteExternalEmail, disableExternalEmail, formatTime,
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +136,11 @@
|
||||
<div v-if="externalEmails.length" v-loading="externalListLoading" class="external-list">
|
||||
<div v-for="item in externalEmails" :key="item.id" class="external-item">
|
||||
<div><strong>{{ item.email }}</strong><span>{{ item.type === 'primary' ? '主要邮箱' : '备用邮箱' }}</span><el-tag size="small" :type="item.status === 'verified' ? 'success' : 'warning'">{{ item.status === 'verified' ? '已验证' : item.status === 'pending' ? '待验证' : '已停用' }}</el-tag></div>
|
||||
<el-button v-if="item.status !== 'disabled'" type="danger" plain size="small" @click="disableExternalEmail(item)">停用</el-button>
|
||||
<div class="external-item-actions">
|
||||
<el-button v-if="item.status === 'disabled'" type="primary" plain size="small" @click="rebindExternalEmail(item)">启用</el-button>
|
||||
<el-button v-else type="warning" plain size="small" @click="disableExternalEmail(item)">停用</el-button>
|
||||
<el-button type="danger" plain size="small" @click="deleteExternalEmail(item)">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else v-loading="externalListLoading" description="暂无外部安全邮箱" />
|
||||
|
||||
@ -4,7 +4,7 @@ import lang from '../../../i18n/i18n';
|
||||
|
||||
import {http} from "@/utils/axios";
|
||||
|
||||
import {ElNotification} from "element-plus";
|
||||
import {ElNotification, ElMessageBox} from "element-plus";
|
||||
|
||||
import {Plus} from "@element-plus/icons-vue";
|
||||
|
||||
@ -283,7 +283,41 @@ export function usePage() {
|
||||
|
||||
reflushList()
|
||||
|
||||
return {
|
||||
const canDeleteUser = user => {
|
||||
return canEditUser(user) && !isSameUser(user, globalStatus.userInfos)
|
||||
}
|
||||
|
||||
const handleDeleteUser = async user => {
|
||||
if (!canDeleteUser(user)) {
|
||||
ElNotification({ type: 'error', message: '无法删除该用户' })
|
||||
return
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定彻底删除用户 "${user.Account}" 吗?此操作将永久清理该用户的所有关联配置、安全密钥与绑定数据,且不可逆!`,
|
||||
'删除用户警告',
|
||||
{
|
||||
type: 'warning',
|
||||
confirmButtonText: '确定删除',
|
||||
cancelButtonText: '取消',
|
||||
confirmButtonClass: 'el-button--danger'
|
||||
}
|
||||
)
|
||||
const res = await http.post('/api/v1/user/delete', { id: user.ID, account: user.Account })
|
||||
if (res.errorNo !== 0) {
|
||||
throw new Error(res.errorMsg || '删除用户失败')
|
||||
}
|
||||
ElNotification({ type: 'success', message: `用户 ${user.Account} 已删除` })
|
||||
await reflushList()
|
||||
await globalStatus.refresh()
|
||||
} catch (error) {
|
||||
if (error !== 'cancel' && error !== 'close') {
|
||||
ElNotification({ type: 'error', message: error?.message || '删除用户失败' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
reactive,
|
||||
ref,
|
||||
lang,
|
||||
@ -320,6 +354,8 @@ export function usePage() {
|
||||
handleEdit,
|
||||
canEditUser,
|
||||
createUser,
|
||||
canDeleteUser,
|
||||
handleDeleteUser,
|
||||
submit,
|
||||
roleMeta,
|
||||
recoveryCodeMeta,
|
||||
@ -331,4 +367,4 @@ export function usePage() {
|
||||
export {
|
||||
Plus,
|
||||
roleMeta
|
||||
}
|
||||
}
|
||||
@ -84,7 +84,7 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="right" :width="canManageMembership ? 126 : 68">
|
||||
<el-table-column label="操作" align="right" :width="canManageMembership ? 186 : 126">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
size="small"
|
||||
@ -97,6 +97,17 @@
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
text
|
||||
bg
|
||||
@click="handleDeleteUser(scope.row)"
|
||||
:disabled="!canDeleteUser(scope.row)"
|
||||
class="action-btn"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
<el-button v-if="canManageMembership" size="small" text :disabled="groupSaving" @click="editMembership(scope.row)">分组</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user