Files
wireguard-dashboard/web/src/views/user/index.vue
2024-09-23 17:17:29 +08:00

414 lines
9.7 KiB
Vue

<template>
<AppPage>
<n-card
:segmented="{
content: true,
footer: 'soft'
}"
header-style="font-size: 15px"
:hoverable="true"
:bordered="false"
>
<template #header>
{{ $route.meta.title }}
</template>
<template #header-extra>
<n-button v-if="useUserStore().isAdmin === 1" size="small" type="info" @click="addUser()">添加</n-button>
<n-button style="margin-left: 5px" size="small" type="primary" @click="getUserList()">刷新</n-button>
</template>
<n-data-table
remote
ref="table"
:columns="tableColumns"
:data="tableData.data"
:pagination="paginate"
:paginate-single-page="false"
></n-data-table>
</n-card>
</AppPage>
<n-modal
v-model:show="showInfoModel"
transform-origin="center"
preset="card"
:title="infoFormModel.nickname || '个人资料'"
:bordered="false"
size="large"
style="width: 400px"
header-style="text-align: center"
>
<n-form
ref="infoFormRef"
:rules="infoFormRules"
:model="infoFormModel"
label-placement="left"
label-width="auto"
label-align="right"
require-mark-placement="left"
>
<n-form-item label="账号" path="account">
<n-input v-if="infoFormModel.id !== ''" disabled v-model:value="infoFormModel.account"></n-input>
<n-input v-else v-model:value="infoFormModel.account"></n-input>
</n-form-item>
<n-form-item v-if="infoFormModel.id === ''" label="密码" path="password">
<n-input type="password" v-model:value="infoFormModel.password"></n-input>
</n-form-item>
<n-form-item label="昵称" path="nickname">
<n-input v-model:value="infoFormModel.nickname"></n-input>
</n-form-item>
<n-form-item label="联系方式" path="contact">
<n-input v-model:value="infoFormModel.contact"></n-input>
</n-form-item>
<n-form-item label="管理员">
<n-space>
<n-radio
:checked="infoFormModel.isAdmin === 1"
value="1"
@change="infoFormModel.isAdmin = 1"
>
</n-radio>
<n-radio
:checked="infoFormModel.isAdmin === 0"
value="0"
@change="infoFormModel.isAdmin = 0"
>
</n-radio>
</n-space>
</n-form-item>
<n-form-item label="状态">
<n-space>
<n-radio
:checked="infoFormModel.status === 1"
value="1"
@change="infoFormModel.status = 1"
>
</n-radio>
<n-radio
:checked="infoFormModel.status === 0"
value="0"
@change="infoFormModel.status = 0"
>
</n-radio>
</n-space>
</n-form-item>
<n-button style="margin-left: 20%" type="primary" @click="SaveUser(infoFormModel)">确认</n-button>
</n-form>
</n-modal>
</template>
<script setup>
import AppPage from '@/components/page/AppPage.vue'
import api from '@/views/user/api'
import userApi from '@/api/user'
import { NAvatar,NTag,NButton } from 'naive-ui'
import { renderIcon } from '@/utils'
import { useUserStore } from '@/store'
import event from '@/utils/event/event'
const { $bus } = event();
const infoFormRef = ref()
// 用户信息model的展示控制
const showInfoModel = ref(false)
// 表单表头
const tableColumns = [
{
title: 'ID',
key: 'index',
align: 'center',
titleAlign: 'center',
render: (_, index) => {
return `${index + 1}`
}
},
{
title: '账号',
key: 'account',
align: 'center',
titleAlign: 'center'
},
{
title: '昵称',
key: 'nickname',
align: 'center',
titleAlign: 'center'
},
{
title: '头像',
key: 'avatar',
align: 'center',
titleAlign: 'center',
render: (row) => {
return h(NAvatar,{
src: row.avatar,
})
}
},
{
title: '联系方式',
key: 'contact',
align: 'center',
titleAlign: 'center'
},
{
title: '管理员',
key: 'isAdmin',
align: 'center',
titleAlign: 'center',
render: (row) => {
switch (row.isAdmin) {
case 1:
return h(NTag,{
type: 'info',
},{
default: () => '是'
})
case 0:
return h(NTag,{
type: 'success',
},{
default: () => '否'
})
}
}
},
{
title: '状态',
key: 'status',
align: 'center',
titleAlign: 'center',
render: (row) => {
switch (row.status) {
case 1:
return h(NTag,{
type: 'info',
},{
default: () => '启用'
})
case 0:
return h(NTag,{
type: 'success',
},{
default: () => '禁用'
})
}
}
},
{
title: '创建时间',
key: 'createdAt',
align: 'center',
titleAlign: 'center'
},
{
title: '更新时间',
key: 'updatedAt',
align: 'center',
titleAlign: 'center'
},
{
title: '操作',
key: 'action',
align: 'center',
titleAlign: 'center',
render: (row) => {
let components = [
h(NButton,{
size: 'small',
color: '#4389DA',
onClick: () => listBtn(row,"EDIT")
},{
icon: renderIcon('mingcute:edit-line', { size: 14 }),
}),
h(NButton,{
size: 'small',
style: 'margin-left: 5px',
color: '#0BE170',
onClick: () => listBtn(row,"RESET")
},{
icon: renderIcon('ic:baseline-lock-reset', { size: 14 }),
}),
h(NButton,{
size: 'small',
style: 'margin-left: 5px',
color: '#ED1518',
onClick: () => listBtn(row,"DELETE")
},{
icon: renderIcon('icon-park-outline:delete', { size: 14 }),
})
]
const currentLoginUser = useUserStore().localUserInfo
if (row.account === 'admin') {
components = []
}
if (currentLoginUser.isAdmin !== 1) {
components = []
}
if (currentLoginUser.id === row.id) {
components = []
}
return components
}
}
]
// 表单数据
const tableData = ref({
data: []
})
// 页码控件
const paginate = reactive({
page: 1,
pageSize: 10,
itemCount: 0,
onChange: (page) => {
paginate.page = page;
pageParam.current = page
pageParam.size = paginate.pageSize
getUserList()
}
})
// 用户信息的表单数据
const infoFormModel = ref({
id: '',
account: '',
password: '',
nickname: '',
avatar: '',
contact: '',
isAdmin: 0,
status: 1
})
// 页码参数
const pageParam = {
current: 1,
size: 10
}
// 个人信息表单验证规则
const infoFormRules = {
account: [
{ required: true, message: '账号不能为空', trigger: 'blur' },
{ min: 2, message: '账号长度最短2位', trigger: 'blur' },
{ max: 20, message: '账号长度最长20位', trigger: 'blur' }
],
password: [
{ min: 8, message: '密码至少8位', trigger: 'blur' },
{ max: 32, message: '密码最多32位', trigger: 'blur' }
],
nickname: [
{ required: true, message: '昵称不能为空', trigger: 'blur' }
],
isAdmin: [
{ required: true, message: '管理员不能为空', trigger: 'blur' }
],
status: [
{ required: true, message: '状态不能为空', trigger: 'blur' }
]
}
// 获取用户列表信息
async function getUserList() {
const res = await api.userList(pageParam)
if (res.data.code === 200) {
tableData.value.data = res.data.data.records;
paginate.itemCount = res.data.data.total;
}
}
// 列表操作按钮
async function listBtn(row,type) {
switch (type) {
case 'EDIT':
showInfoModel.value = true
infoFormModel.value.id = row.id;
infoFormModel.value.account = row.account;
infoFormModel.value.nickname = row.nickname;
infoFormModel.value.avatar = row.avatar;
infoFormModel.value.contact = row.contact;
infoFormModel.value.isAdmin = row.isAdmin;
infoFormModel.value.status = row.status;
break;
case 'RESET':
$dialog.confirm({
type: 'info',
title: '重置密码',
content: `是否重置用户:【${row.nickname}】的密码?`,
async confirm() {
const res = await api.resetPassword(row.id)
if (res.data.code === 200) {
$message.success("操作成功")
await getUserList()
}
},
})
break;
case 'DELETE':
$dialog.confirm({
type: 'warning',
title: '删除',
content: `是否删除用户:【${row.nickname}】?`,
async confirm() {
const res = await api.deleteUser(row.id)
if (res.data.code === 200) {
$message.success("操作成功")
await getUserList()
}
},
})
break;
}
}
// 新增/编辑用户
async function SaveUser(user) {
if (!user) {
showInfoModel.value = true
}
infoFormRef.value.validate(async (valid) => {
if (valid) {
return valid
}
const res = await userApi.addOrUpdateUser(user)
if (res.data.code === 200) {
await getUserList()
showInfoModel.value = false
}
})
}
// 添加用户
function addUser() {
infoFormModel.value = {
id: '',
account: '',
password: '',
nickname: '',
avatar: '',
contact: '',
isAdmin: 0,
status: 1
}
showInfoModel.value = true
}
$bus.on('refreshUserInfo',value => {
if (value) {
getUserList();
}
})
getUserList()
</script>
<style></style>