Implement comprehensive user management functionality with API integration
This commit is contained in:
parent
bb1acb50c1
commit
fb5ad57dc1
5
.env
5
.env
@ -19,4 +19,7 @@ VITE_BUILD_GZIP=false
|
||||
VITE_BUILD_BROTLI=false
|
||||
|
||||
# 是否删除 console
|
||||
VITE_DROP_CONSOLE=true
|
||||
VITE_DROP_CONSOLE=true
|
||||
|
||||
# 后端 API 的基础 URL
|
||||
VITE_API_BASE_URL=http://localhost:3000
|
||||
@ -0,0 +1,52 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 获取用户列表
|
||||
* @returns {Promise} 返回用户列表数据
|
||||
*/
|
||||
export function getUserList() {
|
||||
return request.get('/api/users')
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增用户
|
||||
* @param {Object} data - 用户数据
|
||||
* @param {string} data.username - 用户名(必选)
|
||||
* @param {string} data.password - 密码(必选)
|
||||
* @param {string} data.role_id - 角色ID(必选)
|
||||
* @param {string} [data.real_name] - 真实姓名(可选)
|
||||
* @param {string} [data.email] - 邮箱(可选)
|
||||
* @param {string} [data.phone] - 手机号(可选)
|
||||
* @param {string} [data.status] - 状态(可选)
|
||||
* @param {string} [data.expire_time] - 过期时间(可选)
|
||||
* @returns {Promise} 返回创建结果
|
||||
*/
|
||||
export function createUser(data) {
|
||||
return request.post('/api/users', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑用户
|
||||
* @param {string|number} id - 用户ID
|
||||
* @param {Object} data - 用户数据
|
||||
* @param {string} [data.real_name] - 真实姓名(可选)
|
||||
* @param {string} [data.email] - 邮箱(可选)
|
||||
* @param {string} [data.phone] - 手机号(可选)
|
||||
* @param {string} [data.role_id] - 角色ID(可选)
|
||||
* @param {string} [data.status] - 状态(可选)
|
||||
* @param {string} [data.expire_time] - 过期时间(可选)
|
||||
* @param {string} [data.password] - 新密码(可选)
|
||||
* @returns {Promise} 返回更新结果
|
||||
*/
|
||||
export function updateUser(id, data) {
|
||||
return request.put(`/api/users/${id}`, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
* @param {string|number} id - 用户ID
|
||||
* @returns {Promise} 返回删除结果
|
||||
*/
|
||||
export function deleteUser(id) {
|
||||
return request.delete(`/api/users/${id}`)
|
||||
}
|
||||
@ -1,11 +1,30 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { login as loginApi, logout as logoutApi } from '@/api/login'
|
||||
|
||||
// 安全的 JSON 解析函数
|
||||
const safeJSONParse = (str, defaultValue = null) => {
|
||||
if (!str || str === 'undefined' || str === 'null') {
|
||||
return defaultValue
|
||||
}
|
||||
try {
|
||||
return JSON.parse(str)
|
||||
} catch (error) {
|
||||
console.warn('JSON解析错误,使用默认值:', error)
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
export const useUserStore = defineStore('user', {
|
||||
state: () => ({
|
||||
token: localStorage.getItem('token'),
|
||||
userInfo: JSON.parse(localStorage.getItem('userInfo')) || null
|
||||
}),
|
||||
state: () => {
|
||||
// 从 localStorage 获取数据
|
||||
const token = localStorage.getItem('token')
|
||||
const userInfoStr = localStorage.getItem('userInfo')
|
||||
|
||||
return {
|
||||
token: token || null,
|
||||
userInfo: safeJSONParse(userInfoStr)
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
// 登录
|
||||
|
||||
68
src/utils/format.js
Normal file
68
src/utils/format.js
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 格式化日期时间
|
||||
* @param {string|number|Date} time 需要格式化的时间
|
||||
* @param {string} [format='YYYY-MM-DD HH:mm:ss'] 格式化的格式
|
||||
* @returns {string} 格式化后的时间字符串
|
||||
*/
|
||||
export function formatDateTime(time, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||
if (!time) return '';
|
||||
|
||||
const date = new Date(time);
|
||||
|
||||
if (isNaN(date.getTime())) return '';
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||
|
||||
return format
|
||||
.replace('YYYY', year)
|
||||
.replace('MM', month)
|
||||
.replace('DD', day)
|
||||
.replace('HH', hours)
|
||||
.replace('mm', minutes)
|
||||
.replace('ss', seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期
|
||||
* @param {string|number|Date} time 需要格式化的时间
|
||||
* @returns {string} 格式化后的日期字符串 YYYY-MM-DD
|
||||
*/
|
||||
export function formatDate(time) {
|
||||
return formatDateTime(time, 'YYYY-MM-DD');
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间为相对时间
|
||||
* @param {string|number|Date} time 需要格式化的时间
|
||||
* @returns {string} 相对时间描述
|
||||
*/
|
||||
export function formatRelativeTime(time) {
|
||||
if (!time) return '';
|
||||
|
||||
const date = new Date(time);
|
||||
if (isNaN(date.getTime())) return '';
|
||||
|
||||
const now = new Date();
|
||||
const diff = now - date;
|
||||
const seconds = Math.floor(diff / 1000);
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const hours = Math.floor(minutes / 60);
|
||||
const days = Math.floor(hours / 24);
|
||||
|
||||
if (days > 30) {
|
||||
return formatDateTime(time);
|
||||
} else if (days > 0) {
|
||||
return `${days}天前`;
|
||||
} else if (hours > 0) {
|
||||
return `${hours}小时前`;
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes}分钟前`;
|
||||
} else {
|
||||
return '刚刚';
|
||||
}
|
||||
}
|
||||
@ -38,31 +38,9 @@ service.interceptors.response.use(
|
||||
(response) => {
|
||||
const res = response.data
|
||||
|
||||
// 模拟API响应
|
||||
if (response.config.url.includes('/api/users/')) {
|
||||
// 模拟登录接口
|
||||
if (response.config.url.includes('/login')) {
|
||||
return {
|
||||
token: 'demo-token',
|
||||
userInfo: {
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
role: '管理员',
|
||||
email: 'admin@example.com',
|
||||
status: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 模拟退出登录接口
|
||||
if (response.config.url.includes('/logout')) {
|
||||
return { message: '退出成功' }
|
||||
}
|
||||
}
|
||||
|
||||
// 如果响应成功
|
||||
if (res.code === 200 || res.code === undefined) {
|
||||
return res.data || res
|
||||
if (res.success) {
|
||||
return res
|
||||
}
|
||||
|
||||
// 处理特定错误码
|
||||
@ -74,7 +52,8 @@ service.interceptors.response.use(
|
||||
ElMessage.error('没有权限访问该资源')
|
||||
break
|
||||
case 500:
|
||||
ElMessage.error('服务器错误,请稍后重试')
|
||||
console.error('服务器错误详情:', res)
|
||||
ElMessage.error(res.message || '服务器错误,请稍后重试')
|
||||
break
|
||||
default:
|
||||
ElMessage.error(res.message || '请求失败')
|
||||
@ -83,7 +62,18 @@ service.interceptors.response.use(
|
||||
return Promise.reject(new Error(res.message || '请求失败'))
|
||||
},
|
||||
(error) => {
|
||||
console.error('响应错误:', error)
|
||||
console.error('响应错误详情:', {
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
data: error.response?.data,
|
||||
headers: error.response?.headers,
|
||||
config: {
|
||||
url: error.config?.url,
|
||||
method: error.config?.method,
|
||||
headers: error.config?.headers,
|
||||
params: error.config?.params
|
||||
}
|
||||
})
|
||||
|
||||
// 处理网络错误
|
||||
if (!error.response) {
|
||||
|
||||
@ -4,38 +4,6 @@ import * as echarts from "echarts";
|
||||
import { ElMessageBox, ElMessage } from "element-plus";
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
|
||||
interface AnalysisReport {
|
||||
id: number;
|
||||
title: string;
|
||||
type: "species" | "environment"; // 分析类型:物种/环境
|
||||
timeRange: {
|
||||
// 分析时间范围
|
||||
start: string;
|
||||
end: string;
|
||||
};
|
||||
dataSource: {
|
||||
// 数据来源
|
||||
type: string;
|
||||
points: string[]; // 监测点位
|
||||
}[];
|
||||
analysis: {
|
||||
summary: string; // 分析总结
|
||||
trends: {
|
||||
// 趋势分析
|
||||
indicator: string; // 指标
|
||||
trend: string; // 变化趋势
|
||||
data: any[]; // 数据
|
||||
}[];
|
||||
abnormal: {
|
||||
// 异常分析
|
||||
type: string;
|
||||
description: string;
|
||||
level: string;
|
||||
}[];
|
||||
};
|
||||
recommendations: string[]; // 建议措施
|
||||
}
|
||||
|
||||
// 示例数据
|
||||
const tableData = ref([
|
||||
{
|
||||
|
||||
@ -1,32 +1,260 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { getUserList, createUser, updateUser, deleteUser } from "@/api/user";
|
||||
import { formatDateTime } from "@/utils/format";
|
||||
|
||||
const tableData = ref([
|
||||
{
|
||||
id: 1,
|
||||
username: "admin",
|
||||
role: "超级管理员",
|
||||
email: "admin@example.com",
|
||||
status: true,
|
||||
createTime: "2024-03-20",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
username: "manager",
|
||||
role: "管理人员",
|
||||
email: "manager@example.com",
|
||||
status: true,
|
||||
createTime: "2024-03-20",
|
||||
},
|
||||
]);
|
||||
const tableData = ref([]);
|
||||
const allData = ref([]); // 保存所有数据
|
||||
const loading = ref(false);
|
||||
const total = ref(0);
|
||||
|
||||
// 查询参数
|
||||
const queryParams = ref({
|
||||
username: '',
|
||||
role: '',
|
||||
status: ''
|
||||
});
|
||||
|
||||
// 过滤后的数据
|
||||
const filteredData = computed(() => {
|
||||
return allData.value.filter(item => {
|
||||
// 用户名搜索
|
||||
if (queryParams.value.username &&
|
||||
!item.real_name.toLowerCase().includes(queryParams.value.username.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 角色搜索
|
||||
if (queryParams.value.role &&
|
||||
item.role.name !== queryParams.value.role) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 状态搜索
|
||||
if (queryParams.value.status !== '' &&
|
||||
item.status !== queryParams.value.status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}).sort((a, b) => a.id - b.id); // 按ID升序排序
|
||||
});
|
||||
|
||||
// 获取用户列表
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await getUserList();
|
||||
|
||||
if (res.success) {
|
||||
allData.value = res.data.list; // 保存所有数据
|
||||
tableData.value = filteredData.value; // 显示过滤后的数据
|
||||
total.value = filteredData.value.length;
|
||||
} else {
|
||||
ElMessage.error(res.message || '获取用户列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.response) {
|
||||
ElMessage.error(error.response.data.message || '获取用户列表失败');
|
||||
} else if (error.request) {
|
||||
ElMessage.error('网络错误,请检查网络连接');
|
||||
} else {
|
||||
ElMessage.error(error.message || '获取用户列表失败');
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 处理查询
|
||||
const handleQuery = () => {
|
||||
tableData.value = filteredData.value;
|
||||
total.value = filteredData.value.length;
|
||||
};
|
||||
|
||||
// 重置查询
|
||||
const resetQuery = () => {
|
||||
queryParams.value = {
|
||||
username: '',
|
||||
role: '',
|
||||
status: ''
|
||||
};
|
||||
tableData.value = allData.value;
|
||||
total.value = allData.value.length;
|
||||
};
|
||||
|
||||
// 新增/编辑对话框
|
||||
const dialogVisible = ref(false);
|
||||
const dialogTitle = ref('新增用户');
|
||||
const formData = ref({
|
||||
username: '',
|
||||
password: '',
|
||||
role_id: undefined,
|
||||
real_name: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
status: 1,
|
||||
expire_time: undefined
|
||||
});
|
||||
|
||||
// 表单规则
|
||||
const rules = {
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 6, max: 30, message: '长度在 6 到 30 个字符', trigger: 'blur' },
|
||||
{
|
||||
pattern: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,30}$/,
|
||||
message: '密码必须包含字母和数字',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
role_id: [
|
||||
{ required: true, message: '请选择角色', trigger: 'change' }
|
||||
],
|
||||
email: [
|
||||
{
|
||||
pattern: /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/,
|
||||
message: '请输入正确的邮箱格式',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
phone: [
|
||||
{
|
||||
pattern: /^1[3-9]\d{9}$/,
|
||||
message: '请输入正确的手机号格式',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const formRef = ref(null);
|
||||
const isEdit = ref(false);
|
||||
const editId = ref(null);
|
||||
|
||||
// 打开新增对话框
|
||||
const handleAdd = () => {
|
||||
dialogTitle.value = '新增用户';
|
||||
isEdit.value = false;
|
||||
editId.value = null;
|
||||
formData.value = {
|
||||
username: '',
|
||||
password: '',
|
||||
role_id: undefined,
|
||||
real_name: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
status: 1,
|
||||
expire_time: undefined
|
||||
};
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
// 打开编辑对话框
|
||||
const handleEdit = (row) => {
|
||||
console.log("编辑用户:", row);
|
||||
dialogTitle.value = '编辑用户';
|
||||
isEdit.value = true;
|
||||
editId.value = row.id;
|
||||
formData.value = {
|
||||
real_name: row.real_name || '',
|
||||
email: row.email || '',
|
||||
phone: row.phone || '',
|
||||
role_id: row.role.id.toString(),
|
||||
status: row.status.toString(),
|
||||
expire_time: row.expire_time || '',
|
||||
password: '' // 编辑时密码为可选
|
||||
};
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
const handleDelete = (row) => {
|
||||
console.log("删除用户:", row);
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
|
||||
const submitData = { ...formData.value };
|
||||
|
||||
// 处理数据格式
|
||||
if (submitData.status) {
|
||||
submitData.status = parseInt(submitData.status); // 转换为数字
|
||||
}
|
||||
if (submitData.role_id) {
|
||||
submitData.role_id = parseInt(submitData.role_id); // 转换为数字
|
||||
}
|
||||
// 如果过期时间为空,则不提交该字段
|
||||
if (!submitData.expire_time) {
|
||||
delete submitData.expire_time;
|
||||
}
|
||||
|
||||
console.log('提交的数据:', submitData); // 打印提交的数据
|
||||
|
||||
if (isEdit.value) {
|
||||
// 编辑时,如果密码为空,则不提交密码字段
|
||||
if (!submitData.password) {
|
||||
delete submitData.password;
|
||||
}
|
||||
await updateUser(editId.value, submitData);
|
||||
ElMessage.success('编辑成功');
|
||||
} else {
|
||||
await createUser(submitData);
|
||||
ElMessage.success('添加成功');
|
||||
}
|
||||
|
||||
dialogVisible.value = false;
|
||||
getList(); // 刷新列表
|
||||
} catch (error) {
|
||||
console.error('表单提交错误:', error);
|
||||
if (error.response) {
|
||||
console.error('错误响应数据:', error.response.data);
|
||||
ElMessage.error(error.response.data.message || '提交失败,请检查表单数据');
|
||||
} else if (error.request) {
|
||||
ElMessage.error('网络错误,请检查网络连接');
|
||||
} else {
|
||||
ElMessage.error(error.message || '操作失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 删除用户
|
||||
const handleDelete = (row) => {
|
||||
ElMessageBox.confirm(
|
||||
'确认删除该用户吗?',
|
||||
'警告',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
).then(async () => {
|
||||
try {
|
||||
await deleteUser(row.id);
|
||||
ElMessage.success('删除成功');
|
||||
getList(); // 刷新列表
|
||||
} catch (error) {
|
||||
ElMessage.error(error.message || '删除失败');
|
||||
}
|
||||
}).catch(() => {
|
||||
// 取消删除
|
||||
});
|
||||
};
|
||||
|
||||
// 角色选项
|
||||
const roleOptions = [
|
||||
{ label: '超级管理员', value: '1' },
|
||||
{ label: '管理人员', value: '2' },
|
||||
{ label: '普通用户', value: '3' }
|
||||
];
|
||||
|
||||
// 页面加载时获取列表
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -35,14 +263,50 @@ const handleDelete = (row) => {
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>用户管理</span>
|
||||
<el-button type="primary">新增用户</el-button>
|
||||
<el-button type="primary" @click="handleAdd">新增用户</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="tableData" style="width: 100%">
|
||||
<!-- 搜索表单 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" class="search-form">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input
|
||||
v-model="queryParams.username"
|
||||
placeholder="请输入用户名"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色" prop="role">
|
||||
<el-select v-model="queryParams.role" placeholder="请选择角色" clearable>
|
||||
<el-option
|
||||
v-for="item in roleOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
|
||||
<el-option :value="1" label="启用" />
|
||||
<el-option :value="0" label="禁用" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="tableData"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="id" label="ID" width="80" />
|
||||
<el-table-column prop="username" label="用户名" width="120" />
|
||||
<el-table-column prop="role" label="角色" width="120" />
|
||||
<el-table-column prop="real_name" label="用户名" width="120" />
|
||||
<el-table-column prop="role.name" label="角色" width="120" />
|
||||
<el-table-column prop="email" label="邮箱" />
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
@ -51,19 +315,116 @@ const handleDelete = (row) => {
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="180" />
|
||||
<el-table-column prop="updated_at" label="创建时间" width="180">
|
||||
<template #default="{ row }">
|
||||
{{ formatDateTime(row.updated_at) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" size="small" @click="handleEdit(row)">
|
||||
<el-button type="primary" link @click="handleEdit(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button type="danger" size="small" @click="handleDelete(row)">
|
||||
<el-button type="danger" link @click="handleDelete(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
:size="'small'"
|
||||
:total="total"
|
||||
:default-current-page="1"
|
||||
:default-page-size="10"
|
||||
layout="total, prev, pager, next"
|
||||
:disabled="true"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑对话框 -->
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="500px"
|
||||
@close="dialogVisible = false"
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="isEdit ? {
|
||||
...rules,
|
||||
password: [] // 编辑模式下移除密码验证规则
|
||||
} : rules"
|
||||
label-width="100px"
|
||||
class="user-form"
|
||||
>
|
||||
<el-form-item label="用户名" prop="username" v-if="!isEdit">
|
||||
<el-input v-model="formData.username" placeholder="请输入用户名" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="isEdit ? '新密码' : '密码'"
|
||||
prop="password"
|
||||
>
|
||||
<el-input
|
||||
v-model="formData.password"
|
||||
type="password"
|
||||
show-password
|
||||
:placeholder="isEdit ? '不修改请留空' : '请输入密码'"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色" prop="role_id">
|
||||
<el-select v-model="formData.role_id" placeholder="请选择角色" class="w-full">
|
||||
<el-option
|
||||
v-for="item in roleOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="真实姓名" prop="real_name">
|
||||
<el-input
|
||||
v-model="formData.real_name"
|
||||
placeholder="请输入真实姓名"
|
||||
maxlength="50"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="formData.email" placeholder="请输入邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="phone">
|
||||
<el-input v-model="formData.phone" placeholder="请输入手机号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio :value="'1'">启用</el-radio>
|
||||
<el-radio :value="'0'">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="过期时间" prop="expire_time">
|
||||
<el-date-picker
|
||||
v-model="formData.expire_time"
|
||||
type="datetime"
|
||||
placeholder="请选择过期时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
class="w-full"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -96,6 +457,25 @@ const handleDelete = (row) => {
|
||||
}
|
||||
}
|
||||
|
||||
.search-form {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 16px;
|
||||
|
||||
:deep(.el-input),
|
||||
:deep(.el-select) {
|
||||
width: 240px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
th.el-table__cell {
|
||||
background-color: #fafafa;
|
||||
@ -111,4 +491,23 @@ const handleDelete = (row) => {
|
||||
.el-tag {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.user-form {
|
||||
.el-form-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
text-align: right;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 20px 40px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user