156 行
5.2 KiB
Vue
156 行
5.2 KiB
Vue
<template>
|
||
<div>
|
||
<div class="page-header">
|
||
<h2>子账号管理</h2>
|
||
<el-button type="primary" @click="openCreate">
|
||
<el-icon><Plus /></el-icon> 创建子账号
|
||
</el-button>
|
||
</div>
|
||
|
||
<el-table :data="accounts" v-loading="loading">
|
||
<el-table-column prop="username" label="用户名" />
|
||
<el-table-column prop="nickname" label="昵称" />
|
||
<el-table-column prop="email" label="邮箱" />
|
||
<el-table-column prop="status" label="状态">
|
||
<template #default="{ row }">
|
||
<el-tag :type="row.status === 'ACTIVE' ? 'success' : 'danger'">
|
||
{{ row.status === 'ACTIVE' ? '正常' : '禁用' }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="120">
|
||
<template #default="{ row }">
|
||
<el-button link type="danger" @click="handleDisable(row.id)">禁用</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<!-- 创建子账号:先验证邮箱 -->
|
||
<el-dialog v-model="showDialog" :title="step === 0 ? '验证邮箱' : '创建子账号'" width="480px">
|
||
<template v-if="step === 0">
|
||
<p style="color:#666;margin-bottom:16px">首次创建子账号需验证主账号邮箱,24小时内有效。</p>
|
||
<el-form label-position="top">
|
||
<el-form-item label="主账号邮箱">
|
||
<div class="code-row">
|
||
<el-input v-model="verifyEmail" placeholder="邮箱" style="flex:1" />
|
||
<el-button :disabled="countdown > 0" @click="sendVerifyCode">
|
||
{{ countdown > 0 ? `${countdown}s` : '获取验证码' }}
|
||
</el-button>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="验证码">
|
||
<el-input v-model="verifyCode" placeholder="6位验证码" />
|
||
</el-form-item>
|
||
</el-form>
|
||
</template>
|
||
|
||
<template v-else>
|
||
<el-form ref="createFormRef" :model="createForm" label-position="top">
|
||
<el-form-item label="用户名" :rules="[{required:true, min:3}]">
|
||
<el-input v-model="createForm.username" />
|
||
</el-form-item>
|
||
<el-form-item label="昵称" :rules="[{required:true}]">
|
||
<el-input v-model="createForm.nickname" />
|
||
</el-form-item>
|
||
<el-form-item label="密码">
|
||
<div class="code-row">
|
||
<el-input v-model="createForm.password" show-password style="flex:1" />
|
||
<el-button @click="genPassword">随机生成</el-button>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="邮箱(选填)">
|
||
<el-input v-model="createForm.email" />
|
||
</el-form-item>
|
||
</el-form>
|
||
</template>
|
||
|
||
<template #footer>
|
||
<el-button @click="showDialog = false">取消</el-button>
|
||
<el-button v-if="step === 0" type="primary" @click="handleVerify">确认验证</el-button>
|
||
<el-button v-else type="primary" :loading="creating" @click="handleCreate">创建</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, reactive, onMounted } from 'vue'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import { accountApi, type SubAccount } from '@/api/account'
|
||
|
||
const accounts = ref<SubAccount[]>([])
|
||
const loading = ref(false)
|
||
const showDialog = ref(false)
|
||
const step = ref(0)
|
||
const verifyEmail = ref('')
|
||
const verifyCode = ref('')
|
||
const countdown = ref(0)
|
||
const creating = ref(false)
|
||
const createForm = reactive({ username: '', nickname: '', password: '', email: '' })
|
||
|
||
async function loadAccounts() {
|
||
loading.value = true
|
||
try {
|
||
const res = await accountApi.list()
|
||
accounts.value = res.data.data
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
async function openCreate() {
|
||
step.value = 0
|
||
showDialog.value = true
|
||
}
|
||
|
||
async function sendVerifyCode() {
|
||
if (!verifyEmail.value) { ElMessage.warning('请输入邮箱'); return }
|
||
await accountApi.sendVerifyCode(verifyEmail.value)
|
||
ElMessage.success('验证码已发送')
|
||
countdown.value = 60
|
||
const t = setInterval(() => { if (--countdown.value <= 0) clearInterval(t) }, 1000)
|
||
}
|
||
|
||
async function handleVerify() {
|
||
await accountApi.verifyEmail(verifyEmail.value, verifyCode.value)
|
||
ElMessage.success('验证成功')
|
||
step.value = 1
|
||
}
|
||
|
||
async function genPassword() {
|
||
const res = await accountApi.generatePassword()
|
||
createForm.password = res.data.data.password
|
||
}
|
||
|
||
async function handleCreate() {
|
||
creating.value = true
|
||
try {
|
||
await accountApi.create({
|
||
username: createForm.username,
|
||
nickname: createForm.nickname,
|
||
password: createForm.password,
|
||
email: createForm.email || undefined,
|
||
})
|
||
showDialog.value = false
|
||
ElMessage.success('子账号创建成功')
|
||
loadAccounts()
|
||
} finally {
|
||
creating.value = false
|
||
}
|
||
}
|
||
|
||
async function handleDisable(id: string) {
|
||
await ElMessageBox.confirm('确定禁用此子账号?', '警告', { type: 'warning' })
|
||
await accountApi.disable(id)
|
||
ElMessage.success('已禁用')
|
||
loadAccounts()
|
||
}
|
||
|
||
onMounted(loadAccounts)
|
||
</script>
|
||
|
||
<style scoped>
|
||
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
|
||
.code-row { display: flex; gap: 8px; width: 100%; }
|
||
</style>
|