|
@@ -0,0 +1,184 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="panel">
|
|
|
|
|
+ <div class="toolbar">
|
|
|
|
|
+ <el-button type="primary" @click="openCreate">新建用户</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-table :data="list" v-loading="loading" stripe>
|
|
|
|
|
+ <el-table-column prop="username" label="账号" min-width="120" />
|
|
|
|
|
+ <el-table-column prop="displayName" label="显示名" min-width="120" />
|
|
|
|
|
+ <el-table-column prop="roleName" label="角色" min-width="120" />
|
|
|
|
|
+ <el-table-column label="状态" width="100">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-tag :type="row.status === '0' ? 'success' : 'info'" size="small">
|
|
|
|
|
+ {{ row.status === '0' ? '启用' : '停用' }}
|
|
|
|
|
+ </el-tag>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column label="操作" min-width="260" fixed="right">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <el-button link type="primary" @click="openEdit(row)">编辑</el-button>
|
|
|
|
|
+ <el-button link type="primary" @click="toggleStatus(row)">
|
|
|
|
|
+ {{ row.status === '0' ? '停用' : '启用' }}
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ <el-button link type="primary" @click="openReset(row)">重置密码</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog v-model="editVisible" :title="editingId ? '编辑用户' : '新建用户'" width="480px">
|
|
|
|
|
+ <el-form :model="form" label-position="top">
|
|
|
|
|
+ <el-form-item label="账号" v-if="!editingId">
|
|
|
|
|
+ <el-input v-model="form.username" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="密码" v-if="!editingId">
|
|
|
|
|
+ <el-input v-model="form.password" type="password" show-password />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="显示名">
|
|
|
|
|
+ <el-input v-model="form.displayName" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="角色">
|
|
|
|
|
+ <el-select v-model="form.roleId" style="width: 100%">
|
|
|
|
|
+ <el-option v-for="r in roles" :key="r.id" :label="r.roleName" :value="r.id" />
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <el-button @click="editVisible = false">取消</el-button>
|
|
|
|
|
+ <el-button type="primary" :loading="saving" @click="saveUser">确定</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog v-model="pwdVisible" title="重置密码" width="420px">
|
|
|
|
|
+ <el-form label-position="top">
|
|
|
|
|
+ <el-form-item label="新密码">
|
|
|
|
|
+ <el-input v-model="newPassword" type="password" show-password />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <el-button @click="pwdVisible = false">取消</el-button>
|
|
|
|
|
+ <el-button type="primary" :loading="saving" @click="savePassword">确定</el-button>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+ import { onMounted, reactive, ref } from 'vue'
|
|
|
|
|
+ import { ElMessage } from 'element-plus'
|
|
|
|
|
+ import {
|
|
|
|
|
+ createUser,
|
|
|
|
|
+ fetchRoles,
|
|
|
|
|
+ fetchUsers,
|
|
|
|
|
+ resetUserPassword,
|
|
|
|
|
+ updateUser
|
|
|
|
|
+ } from '@/api/admin'
|
|
|
|
|
+
|
|
|
|
|
+ const loading = ref(false)
|
|
|
|
|
+ const saving = ref(false)
|
|
|
|
|
+ const list = ref<any[]>([])
|
|
|
|
|
+ const roles = ref<any[]>([])
|
|
|
|
|
+ const editVisible = ref(false)
|
|
|
|
|
+ const pwdVisible = ref(false)
|
|
|
|
|
+ const editingId = ref('')
|
|
|
|
|
+ const resetId = ref('')
|
|
|
|
|
+ const newPassword = ref('')
|
|
|
|
|
+ const form = reactive({
|
|
|
|
|
+ username: '',
|
|
|
|
|
+ password: '',
|
|
|
|
|
+ displayName: '',
|
|
|
|
|
+ roleId: ''
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ async function load() {
|
|
|
|
|
+ loading.value = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ const [u, r]: any[] = await Promise.all([fetchUsers(), fetchRoles()])
|
|
|
|
|
+ list.value = u.data || []
|
|
|
|
|
+ roles.value = r.data || []
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ loading.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function openCreate() {
|
|
|
|
|
+ editingId.value = ''
|
|
|
|
|
+ Object.assign(form, { username: '', password: '', displayName: '', roleId: roles.value[0]?.id || '' })
|
|
|
|
|
+ editVisible.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function openEdit(row: any) {
|
|
|
|
|
+ editingId.value = row.id
|
|
|
|
|
+ Object.assign(form, {
|
|
|
|
|
+ username: row.username,
|
|
|
|
|
+ password: '',
|
|
|
|
|
+ displayName: row.displayName,
|
|
|
|
|
+ roleId: row.roleId
|
|
|
|
|
+ })
|
|
|
|
|
+ editVisible.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function openReset(row: any) {
|
|
|
|
|
+ resetId.value = row.id
|
|
|
|
|
+ newPassword.value = ''
|
|
|
|
|
+ pwdVisible.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async function saveUser() {
|
|
|
|
|
+ saving.value = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (editingId.value) {
|
|
|
|
|
+ await updateUser(editingId.value, {
|
|
|
|
|
+ displayName: form.displayName,
|
|
|
|
|
+ roleId: form.roleId
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await createUser({
|
|
|
|
|
+ username: form.username,
|
|
|
|
|
+ password: form.password,
|
|
|
|
|
+ displayName: form.displayName,
|
|
|
|
|
+ roleId: form.roleId
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ ElMessage.success('已保存')
|
|
|
|
|
+ editVisible.value = false
|
|
|
|
|
+ load()
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ saving.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async function toggleStatus(row: any) {
|
|
|
|
|
+ const status = row.status === '0' ? '1' : '0'
|
|
|
|
|
+ await updateUser(row.id, { status })
|
|
|
|
|
+ ElMessage.success(status === '0' ? '已启用' : '已停用')
|
|
|
|
|
+ load()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async function savePassword() {
|
|
|
|
|
+ if (!newPassword.value) {
|
|
|
|
|
+ ElMessage.warning('请输入新密码')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ saving.value = true
|
|
|
|
|
+ try {
|
|
|
|
|
+ await resetUserPassword(resetId.value, newPassword.value)
|
|
|
|
|
+ ElMessage.success('密码已重置')
|
|
|
|
|
+ pwdVisible.value = false
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ saving.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onMounted(load)
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+ .panel {
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+ }
|
|
|
|
|
+ .toolbar {
|
|
|
|
|
+ margin-bottom: 14px;
|
|
|
|
|
+ }
|
|
|
|
|
+</style>
|