LoongPanel-Asp/web/components/UserPage/UserPageAddUser.vue

220 lines
5.5 KiB
Vue

<script setup lang="ts">
import {watchDebounced} from '@vueuse/core'
import * as Yup from "yup";
import {useToast} from "vue-toastification";
import type {UserInfoListType} from "~/types/UserType";
const toast = useToast()
const avatarImgUrl = ref("")
const errors = ref<string[]>([]);
const props=defineProps({
closeBack: {
type: Function,
default: () => {}
}
})
//随机生成密码
const randomPassword = () => {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+';
let password = '';
for (let i = 0; i < 24; i++) {
password += chars.charAt(Math.floor(Math.random() * chars.length));
}
return password
}
const form = reactive({
fullName: '',
userName: '',
position: '',
email: 'examp@examp.com',
phone: '1888888888',
password: randomPassword().toString(),
role: 'user',
});
const schema = Yup.object().shape({
fullName: Yup.string().required('请输入姓名'),
userName: Yup.string().required('请输入用户名').matches(/^[A-Za-z0-9_]+$/,"用户名必须为英文,且只能包含英文字母、数字和下划线"),
position: Yup.string().required('请输入职位'),
email: Yup.string().email('请输入正确的邮箱').required('请输入邮箱'),
phone: Yup.string().required('请输入手机号'),
password: Yup.string().required('请输入密码').min(6, '密码至少需要6个字符')
.matches(/(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$%^&*()_+])[0-9a-zA-Z!@#$%^&*()_+]{6,}/, '密码必须包含字母、数字和至少一个特殊字符'),
role: Yup.string().required('请选择权限'),
});
watchDebounced(
() => form.userName,
() => {
avatarImgUrl.value = `https://api.multiavatar.com/${form.userName}.svg`
},
{debounce: 2000, maxWait: 4000},
)
const handleSubmit = async () => {
try {
// 验证表单
await schema.validate(form, {abortEarly: false});
errors.value = []; // 清空错误信息
// 执行创建用户的逻辑
$fetch('Api/Account/Register', {
method: "POST",
body: form,
headers:{
"Authorization": "Bearer " + useCookie("token").value
},
baseURL:useRuntimeConfig().public.baseUrl
}).then(res => {
toast.success(res)
//调用copy
const { text, copy, copied, isSupported } = useClipboard({
source: JSON.stringify(form),
copiedDuring: 2000,
})
if(!isSupported.value){
toast.error('浏览器不支持复制')
setTimeout(()=>{
props.closeBack()
return
},2000)
}
copy()
toast.success('账号已复制到剪贴板')
//检查是否拷贝成功
if (!copied.value) {
toast.error('复制失败')
}
setTimeout(()=>{
props.closeBack()
},2000)
}).catch(
err => {
toast.error(err)
}
)
} catch (error) {
// 处理验证错误
if (error instanceof Yup.ValidationError) {
errors.value = error.inner.map(e =>{
toast.error(e.message)
return e.message
} );
}
}
};
</script>
<template>
<div class="create-user-layout">
<Avatar size="xlarge" shape="circle" class="avatar" :image="avatarImgUrl"/>
<div class="header">
<Icon name="User" :stroke-width="2" :size="32"></Icon>
<h2>创建新的账户</h2>
</div>
<form class="form" @submit.prevent="handleSubmit">
<div>
<input placeholder="用户名" type="text" v-model="form.userName"/>
<input placeholder="姓名" type="text" v-model="form.fullName"/>
</div>
<div>
<input placeholder="职位" type="text" v-model="form.position"/>
<select v-model="form.role">>
<option value="user">普通运维人员</option>
<option value="admin">管理员</option>
</select>
</div>
<input placeholder="邮箱" type="email" v-model="form.email"/>
<input placeholder="手机号" type="text" v-model="form.phone"/>
<input placeholder="密码" type="text" v-model="form.password"/>
<div class="active">
<button @click.prevent="closeBack()">取消</button>
<button type="submit">创建</button>
</div>
</form>
</div>
</template>
<style scoped lang="scss">
@import "base";
.create-user-layout {
background: $light-bg-color;
width: 400px;
min-height: 600px;
border-radius: $radius;
position: relative;
display: flex;
align-items: center;
gap: $gap*4;
flex-direction: column;
padding: $padding*6 $padding*2 $padding*2;
box-shadow: 0 0 10px rgba($light-bg-color, .4);
}
.avatar {
position: absolute;
top: -50px;
box-shadow: 0 0 10px rgba($light-bg-color, .4);
left: 50%;
transform: translateX(-50%);
width: 120px;
height: 120px;
background: #2F3F53;
color: #fff;
}
.header {
display: flex;
align-items: center;
gap: $gap;
}
.form {
display: flex;
flex-direction: column;
width: 100%;
gap: $gap;
div {
display: flex;
gap: $gap;
align-items: center;
input, select {
flex: 1;
width: 100%;
}
}
input, select {
border: 2px solid rgb(212, 217, 221);
padding: $padding;
border-radius: $radius;
height: 60px;
}
}
.active{
display: flex;
width: 100%;
padding-top:$gap*2;
button {
flex: 1;
height: 60px;
border: 2px solid rgb(212, 217, 221);
border-radius: $radius;
background: $primary-color;
color:#fff;
font-size: 16px;
&:first-child {
background: unset;
color: rgb(212, 217, 221);
&:hover {
border-color: $light-text-color;
color: $light-text-color;
}
}
}
}
</style>