Commit c91a0f1d by yzh

feat:系统管理接口接完

parent b323f506
......@@ -76,4 +76,5 @@ export const userApi = {
addUser: '/user/insert',
updateUser: '/user/update',
deleteUser: '/user/delete',
batchDelete: '/user/batchDelete',
} as const
\ No newline at end of file
......@@ -67,4 +67,13 @@ export function deleteUser(data: UserQueryParams) {
method: POST,
data
}) as unknown as Promise<ApiResponse>
}
// 批量删除用户
export function batchDeleteUser(data: UserQueryParams) {
return request({
url: userApi.batchDelete,
method: POST,
data
}) as unknown as Promise<ApiResponse>
}
\ No newline at end of file
......@@ -17,24 +17,43 @@
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { defineProps } from 'vue';
import { getUserList, addUser, deleteUser, updateUser, batchDeleteUser } from '@/api/user.ts'
const props = defineProps({
dialogVisible: {
type: Boolean,
default: false
},
mode: {
deleteMode: {
type: String,
default: '1'
default: '0'
},
id: {
type: Number,
default: '0'
},
ids: {
type: Array,
default: []
}
})
const emit = defineEmits(['update:dialogVisible', 'confirm'])
const emit = defineEmits(['update:dialogVisible', 'confirm', 'getUserList', 'update:deleteMode'])
const deleteDialogVisible = ref(props.dialogVisible)
const deleteMode = ref(props.deleteMode)
// 删除方法
const handleDelelte = () => {
emit('confirm')
deleteDialogVisible.value = false
const handleDelelte = async () => {
if (props.deleteMode == '1') {
await deleteUser({ id: props.id })
emit('getUserList')
deleteDialogVisible.value = false
}
else if (props.deleteMode == '2') {
console.log(props.ids);
await batchDeleteUser({ ids: props.ids })
emit('getUserList')
deleteDialogVisible.value = false
}
}
// 关闭弹窗的方法
const close = () => {
......@@ -52,4 +71,16 @@ watch(() => deleteDialogVisible.value,
emit('update:dialogVisible', newVal)
}
)
// 监听父组件传过来的值
watch(() => props.deleteMode,
(newVal) => {
deleteMode.value = newVal
}
)
// 监听组件内的值并向父组件更新
watch(() => deleteMode.value,
(newVal) => {
emit('update:deleteMode', newVal)
}
)
</script>
\ No newline at end of file
......@@ -107,4 +107,7 @@ export interface UserQueryParams {
password?: string
role?: number
status?: boolean
id?: number
ids?: any
}
\ No newline at end of file
......@@ -2,60 +2,51 @@
<el-dialog v-model="currentVisible" :title="currentMode === '1' ? '新增用户' : '编辑用户'" width="610" center align-center
@close="handleClose" draggable>
<div v-if="currentMode === '1'">
<el-form :inline="true" >
<el-form-item label="用户账号:">
<el-input v-model="addNickName" />
</el-form-item>
<el-form-item label="用户名称:" >
<el-input v-model="addUserName" />
</el-form-item>
</el-form>
<div class="m-t-4" />
<el-form :inline="true">
<el-form-item label="用户状态:">
<el-select v-model="userStatusValue" placeholder=" " style="width: 180px;">
<el-option v-for="item in userStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="用户密码:">
<el-input v-model="userPassword" />
</el-form-item>
</el-form>
<div class="m-t-4" />
<el-form :inline="true">
<el-form-item label="用户角色:">
<el-select v-model="userRoleValue" placeholder=" " style="width: 180px;">
<el-option v-for="item in userRoleOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
</div>
<div class="m-t-4">
<el-form :rules="firstFormRules" ref="firstRuleFormRef" :model="firstForm">
<el-form-item label="用户账号:" prop="userAccount">
<el-input v-model="firstForm.userAccount" />
</el-form-item>
<el-form-item label="用户名称:" prop="userName">
<el-input v-model="firstForm.userName" />
</el-form-item>
<el-form-item label="用户状态:">
<el-select v-model="userStatusValue" placeholder="请选择状态" style="width: 100%;">
<el-option v-for="item in userStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="用户密码:" prop="userPassword">
<el-input v-model="firstForm.userPassword" />
</el-form-item>
<el-form-item label="用户角色:">
<el-select v-model="userRoleValue" placeholder="请选择角色" style="width: 100%;">
<el-option v-for="item in userRoleOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
</div>
<div v-if="currentMode === '2'">
<el-form :inline="true" v-if="currentMode === '2'">
<el-form-item label="用户名称:" >
<el-input v-model="addNickName" />
</el-form-item>
<el-form-item label="用户角色:">
<el-select v-model="userRoleValue" placeholder=" " style="width: 180px;">
<el-option v-for="item in userRoleOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
<div class="m-t-4" />
<el-form :inline="true" v-if="currentMode === '2'">
<el-form-item label="用户状态:">
<el-select v-model="userStatusValue" placeholder=" " style="width: 180px;">
<el-option v-for="item in userStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="用户密码:">
<el-input v-model="userPassword" />
</el-form-item>
</el-form>
<el-form :inline="true" :rules="secondFormRules" ref="secondRuleFormRef" :model="secondForm">
<el-form-item label="用户名称:" prop="userName">
<el-input v-model="secondForm.userName" />
</el-form-item>
<el-form-item label="用户角色:">
<el-select v-model="userRoleValue" placeholder="请选择角色" style="width: 180px;">
<el-option v-for="item in userRoleOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-form>
<div class="m-t-4" />
<el-form :inline="true" :rules="editPasswordRules" ref="editPasswordFormRef" :model="editPasswordForm">
<el-form-item label="用户状态:">
<el-select v-model="userStatusValue" placeholder="请选择状态" style="width: 180px;">
<el-option v-for="item in userStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="用户密码:" prop="userPassword">
<el-input v-model="editPasswordForm.userPassword" placeholder="不修改请留空" />
</el-form-item>
</el-form>
</div>
<div class="m-t-4" />
<template #footer>
<div class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
......@@ -68,143 +59,182 @@
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { defineProps } from 'vue';
import { watch } from 'vue'
import { getUserList, addUser, deleteUser, updateUser } from '@/api/user.ts'
import { ref, watch } from 'vue'
import { defineProps, defineEmits } from 'vue';
import { addUser, updateUser } from '@/api/user.ts'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus';
// 定义表单数据结构(与rules对应)
const firstForm = ref({
userAccount: '', // 用户账号
userName: '', // 用户名称
userPassword: '' // 用户密码
})
const secondForm = ref({
userName: '' // 编辑模式的用户名称
})
const editPasswordForm = ref({
userPassword: '' // 编辑模式的密码
})
// 表单引用
const firstRuleFormRef = ref<FormInstance>()
const secondRuleFormRef = ref<FormInstance>()
const editPasswordFormRef = ref<FormInstance>()
// 新增模式验证规则
const firstFormRules = ref<FormRules>({
userAccount: [
{ required: true, message: '请输入用户账号', trigger: 'blur' },
{ type: 'string', min: 1, max: 20, message: '用户账号长度1-20字符', trigger: 'blur' },
{ pattern: /^[A-Za-z0-9]+$/, message: '只能包含英文字母或数字', trigger: 'blur' }
],
userName: [
{ required: true, message: '请输入用户名称', trigger: 'blur' },
{ type: 'string', min: 1, max: 20, message: '用户名称长度1-20字符', trigger: 'blur' },
],
userPassword: [
{ required: true, message: '请输入用户密码', trigger: 'blur' },
{ type: 'string', min: 6, max: 20, message: '密码长度6-20字符', trigger: 'blur' },
],
})
// 编辑模式验证规则(密码可选)
const secondFormRules = ref<FormRules>({
userName: [
{ required: true, message: '请输入用户名称', trigger: 'blur' },
{ type: 'string', min: 1, max: 20, message: '用户名称长度1-20字符', trigger: 'blur' },
],
})
const editPasswordRules = ref<FormRules>({
userPassword: [
{ type: 'string', min: 6, max: 20, message: '密码长度6-20字符', trigger: 'blur' },
],
})
// 状态选项(统一值类型,避免类型错误)
const userStatusValue = ref(true)
const userRoleValue = ref(1)
const userStatusOptions = [
{
value: true,
label: '启用'
},
{
value: '0',
label: '停用'
}
{ value: true, label: '启用' },
{ value: false, label: '停用' } // 与userStatusValue类型一致(boolean)
]
const userRoleOptions = [
{
value: false,
label: '管理员'
},
{
value: '0',
label: '普通用户'
}
{ value: false, label: '管理员' },
{ value: true, label: '普通用户' } // 统一值类型
]
// 属性定义
const props = defineProps({
dialogVisible: {
type: Boolean,
default: false
},
mode: {
type: String,
default: 'add'
},
nickName: {
type: String,
default: ''
},
userName: {
type: String,
default: ''
},
id: {
type: Number,
default: false
},
userPassword: {
type: String,
default: ''
},
userStatus: {
type: Boolean,
default: ''
},
userRole: {
type: Number,
default: ''
}
dialogVisible: { type: Boolean, default: false },
mode: { type: String, default: '1' },
nickName: { type: String, default: '' },
userName: { type: String, default: '' },
id: { type: Number, default: 0 },
userPassword: { type: String, default: '' },
userStatus: { type: Boolean, default: true },
userRole: { type: Number, default: false }
})
// 向父组件传递dialog值
const emit = defineEmits(['update:dialogVisible', 'confirm','getUserList'])
// 组件的状态
// 事件发射
const emit = defineEmits(['update:dialogVisible', 'getUserList'])
// 组件状态
const currentVisible = ref(props.dialogVisible)
const currentMode = ref(props.mode)
const addNickName = ref('')
const addUserName = ref('')
const userRemark = ref('')
const userPassword = ref('')
// 关闭的方法
// 关闭对话框
const handleClose = () => {
currentVisible.value = false
}
// 确定的方法
const handleConfirm = async () => {
if (currentMode.value === '1') {
await addUser({
nickname: addNickName.value,
username: addUserName.value,
password: userPassword.value,
role: userRoleValue.value,
status: userStatusValue.value
})
console.log(addUserName.value);
emit('getUserList')
} else if (currentMode.value === '2') {
// 确认操作
const handleConfirm = async () => {
try {
if (currentMode.value === '1') {
if (!firstRuleFormRef.value) {
return;
}
// 3. 使用Promise形式的validate(不传入回调),确保await生效
const valid = await firstRuleFormRef.value.validate();
if (valid) {
// 进入这里即197行附近逻辑
await addUser({
nickname: firstForm.value.userName, // 注意:根据实际接口字段调整
username: firstForm.value.userAccount,
password: firstForm.value.userPassword,
role: userRoleValue.value,
status: userStatusValue.value
});
ElMessage.success('新增成功');
emit('getUserList');
currentVisible.value = false;
}
} else if (currentMode.value === '2') {
// 编辑模式逻辑(略,可参考新增模式调整)
if (!secondRuleFormRef.value) return;
const valid = await secondRuleFormRef.value.validate();
if (valid) {
// 密码非空时验证密码
if (editPasswordForm.value.userPassword) {
if (!editPasswordFormRef.value) return;
const pwdValid = await editPasswordFormRef.value.validate();
if (!pwdValid) return;
}
await updateUser({
id: props.id,
nickname: secondForm.value.userName,
role: userRoleValue.value,
status: userStatusValue.value,
...(editPasswordForm.value.userPassword && { password: editPasswordForm.value.userPassword })
});
ElMessage.success('编辑成功');
emit('getUserList');
currentVisible.value = false;
}
}
} catch (error) {
console.error('操作失败:', error);
// 验证失败时Element会自动提示,无需额外处理
}
currentVisible.value = false
}
};
// 监听props变化,同步给组件内部
watch(() => props.dialogVisible,
(newVal) => {
currentVisible.value = newVal
}
)
// 监听属性同步
watch(() => props.dialogVisible, (newVal) => {
currentVisible.value = newVal
})
// 监听组件内部状态变化,同步给父组件,这样才能做到控制对话框组件的显隐
watch(() => currentVisible.value,
(newVal) => {
emit('update:dialogVisible', newVal)
}
)
watch(() => props.mode,
(newVal) => {
currentMode.value = newVal
}
)
watch(() => currentVisible.value, (newVal) => {
emit('update:dialogVisible', newVal)
})
watch(() => props.mode, (newVal) => {
currentMode.value = newVal
})
watch(
// 监听需要同步的 props 集合
[() => props.dialogVisible, () => props.mode, () => props.nickName, () => props.userPassword, () => props.userStatus, () => props.userRole],
// 任一值变化时执行
([newVisible, newMode, newNickName, newPwd, newStatus, newRole]) => {
if (newVisible && newMode === '2') {
addNickName.value = newNickName;
userPassword.value = newPwd;
userStatusValue.value = newStatus;
userRoleValue.value = newRole;
}
// 弹窗关闭时,清空表单
if (!newVisible) {
addNickName.value = '';
addUserName.value = '';
userPassword.value = '';
}
},
{ immediate: true }
[() => props.dialogVisible, () => props.mode, () => props.nickName, () => props.userPassword, () => props.userStatus, () => props.userRole],
([newVisible, newMode, newNickName, newPwd, newStatus, newRole]) => {
if (newVisible && newMode === '2') {
secondForm.value.userName = newNickName;
editPasswordForm.value.userPassword = newPwd || '';
userStatusValue.value = newStatus;
userRoleValue.value = newRole;
}
if (!newVisible) {
// 清空表单
firstForm.value = { userAccount: '', userName: '', userPassword: '' };
secondForm.value = { userName: '' };
editPasswordForm.value = { userPassword: '' };
}
},
{ immediate: true }
);
</script>
<style>
/* 修改弹窗样式 */
/* 保持原有样式 */
.el-dialog {
background: transparent;
background-image: url("@/assets/picture/dialog1.png");
......@@ -215,27 +245,26 @@ watch(
.el-dialog__title {
color: #ffffff;
}
.el-input__inner{
.el-input__inner {
color: #ffffff;
}
.el-select__wrapper{
background-color:#1d5484 ;
box-shadow: 0,0,0,0;
.el-select__wrapper {
background-color: #1d5484;
box-shadow: 0, 0, 0, 0;
border: none;
.el-select__placeholder{
.el-select__placeholder {
color: #ffffff;
}
}
}
/* 修改表单样式 */
.el-form {
.el-form-item__label {
color: #ffffff;
}
}
</style>
<style>
</style>
\ No newline at end of file
\ No newline at end of file
......@@ -6,18 +6,17 @@
<el-button type="primary" plain @click="openAddUserDialog">创建用户</el-button>
</el-form-item>
<el-form-item>
<el-button type="danger" plain @click="handleDelete">批量删除</el-button>
<el-button type="danger" plain @click="handleBatchDelete">批量删除</el-button>
</el-form-item>
</el-form>
</div>
<el-table :data="tableData" style="width: 100%" border :header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center' }" :row-style="{ height: '58px' }">
:cell-style="{ textAlign: 'center' }" :row-style="{ height: '58px' }"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="40" />
<el-table-column property="number" label="序号" width="55" type="index" />
<el-table-column property="username" label="用户账号" show-overflow-tooltip />
<el-table-column property="nickname" label="用户名称" show-overflow-tooltip />
<!-- <el-table-column property="userRemark" label="备注" show-overflow-tooltip /> -->
<!-- <el-table-column property="userPassword" label="用户密码" show-overflow-tooltip /> -->
<el-table-column property="create_time" label="创建时间" width="280" show-overflow-tooltip />
<el-table-column label="操作" width="220">
<template #default="scope">
......@@ -32,13 +31,15 @@
</el-table>
<div class="pagination w-full flex flex-row-reverse pr-4 m-t-4">
<Pagination :total="pageObj.total" v-model:page="pageObj.pageNo" v-model:limit="pageObj.pageSize"
@pagination="getData" />
@pagination="getUserListData" />
</div>
<!-- 删除弹窗组件 -->
<deleteDialog v-model:dialogVisible="showDeleteDialog" @mode="deleteMode" />
<deleteDialog v-model:dialogVisible="showDeleteDialog" @get-user-list="getUserListData"
:ids="userIds" v-model:deleteMode="deleteMode" />
<!-- 创建用户弹窗组件 -->
<addUserDialog v-model:dialogVisible="dialogVisible" :mode="mode" :nick-name="nickName" :user-name="userName" :id="userId"
:user-role="userRole" :user-status="userStatus" :user-password="userPassword" @get-user-list="getUserListData" />
<addUserDialog v-model:dialogVisible="dialogVisible" :mode="mode" :nick-name="nickName" :user-name="userName"
:id="userId" :user-role="userRole" :user-status="userStatus" :user-password="userPassword"
@get-user-list="getUserListData" />
</div>
</template>
......@@ -47,16 +48,17 @@ import { ref, onMounted } from 'vue'
import Pagination from '@/components/pagination/index.vue'
import deleteDialog from '@/components/Delete/index.vue'
import addUserDialog from './components/addUserDialog.vue'
import { getUserList, addUser, deleteUser, updateUser } from '@/api/user.ts'
import { getUserList, addUser, deleteUser, updateUser, batchDeleteUser } from '@/api/user.ts'
const userId = ref(0)
const userId = ref<any>([])
const userIds = ref<any>()
const nickName = ref('')
const userName = ref('')
const userRole = ref(0)
const userStatus = ref(true)
const userPassword = ref('')
const showDeleteDialog = ref(false)
const deleteMode = ref('2')
const deleteMode = ref('0')
const dialogVisible = ref(false)
const mode = ref('1')
const tableData = ref()
......@@ -73,33 +75,40 @@ const handleEdit = async (row: any) => {
userStatus.value = row.status
userPassword.value = row.password
dialogVisible.value = true
userId.value = row.id
// console.log(row);
}
const handleDelete = (row: any) => {
const handleDelete = async (row: any) => {
showDeleteDialog.value = true
deleteMode.value = '1'
userId.value = row.id
console.log(userId.value);
}
const getData = (number: number) => {
// console.log('getData');
console.log(number);
const handleBatchDelete = async () => {
deleteMode.value = '2'
showDeleteDialog.value = true
}
const handleDeleteConfirm = () => {
const handleSelectionChange = (data: any) => {
let array = []
for (let i = 0; i < data.length; i++) {
array.push(data[i].id)
}
userIds.value = array
}
const openAddUserDialog = () => {
mode.value = '1'
dialogVisible.value = true
}
const getUserListData = async () => {
const userList = await getUserList({
page: 1,
// page: 1,
size: 10
})
tableData.value = userList.data
console.log(tableData.value);
pageObj.value.total = tableData.value.length
console.log(tableData.value.length);
}
onMounted(async () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment