product-web/src/views/system/user/index.vue

480 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="meter-monitoring-page">
<!-- 卡片容器带悬浮阴影圆角优化 -->
<el-card class="page-card" shadow="hover">
<!-- 搜索表单时间选择 + 快捷按钮 -->
<el-form inline :model="searchForm" class="search-form">
<el-form-item label="账号:">
<el-input></el-input>
</el-form-item>
<el-form-item label="姓名:">
<el-input></el-input>
</el-form-item>
<el-form-item label="手机号:">
<el-input></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">查询</el-button>
</el-form-item>
<el-form-item style="margin-left: 16px; float: right">
<el-button plain @click="handleAdd">新增</el-button>
</el-form-item>
</el-form>
<!-- 电表数据表格带边框斑马纹 -->
<el-table
:data="tableData"
:header-cell-style="headerStyle"
border
stripe
class="meter-table"
>
<el-table-column
prop="userName"
label="账号/工号"
align="center"
></el-table-column>
<el-table-column
prop="name"
label="姓名"
align="center"
></el-table-column>
<el-table-column
prop="sex"
label="性别"
align="center"
></el-table-column>
<el-table-column
prop="phonenumber"
label="手机号码"
align="center"
></el-table-column>
<el-table-column
prop="createTime"
label="创建时间"
align="center"
></el-table-column>
<el-table-column label="状态" align="center" key="status">
<template #default="scope">
<el-switch
v-model="scope.row.status"
active-value="0"
inactive-value="1"
@change="handleStatusChange(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
width="180"
class-name="small-padding fixed-width"
>
<template #default="scope">
<el-tooltip
content="修改"
placement="top"
v-if="scope.row.userId !== 1"
>
<el-button
link
type="primary"
icon="Edit"
@click="handleUpdate(scope.row)"
></el-button>
</el-tooltip>
<el-tooltip
content="删除"
placement="top"
v-if="scope.row.userId !== 1"
>
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
></el-button>
</el-tooltip>
<el-tooltip
content="重置密码"
placement="top"
v-if="scope.row.userId !== 1"
>
<el-button
link
type="primary"
icon="Key"
@click="handleResetPwd(scope.row)"
></el-button>
</el-tooltip>
<el-tooltip
content="分配角色"
placement="top"
v-if="scope.row.userId !== 1"
>
<el-button
link
type="primary"
icon="CircleCheck"
@click="handleAuthRole(scope.row)"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-card>
<!-- 添加或修改用户配置对话框 -->
<el-dialog :title="title" v-model="open" width="600px">
<el-form :model="form" :rules="rules" ref="userRef" label-width="80px">
<el-row>
<el-col :span="12">
<el-form-item label="账号" prop="nickName">
<el-input
v-model="form.nickName"
placeholder="请输入用户昵称"
maxlength="30"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="form.phonenumber"
placeholder="请输入手机号码"
maxlength="11"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item
v-if="form.userId == undefined"
label="姓名"
prop="userName"
>
<el-input
v-model="form.userName"
placeholder="请输入用户名称"
maxlength="30"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
v-if="form.userId == undefined"
label="用户密码"
prop="password"
>
<el-input
v-model="form.password"
placeholder="请输入用户密码"
type="password"
maxlength="20"
show-password
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="用户性别">
<el-select v-model="form.sex" placeholder="请选择">
<el-option
v-for="dict in sys_user_sex"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in sys_normal_disable"
:key="dict.value"
:value="dict.value"
>{{ dict.label }}</el-radio
>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="角色">
<el-select v-model="form.roleIds" multiple placeholder="请选择">
<el-option
v-for="item in roleOptions"
:key="item.roleId"
:label="item.roleName"
:value="item.roleId"
:disabled="item.status == 1"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="备注">
<el-input
v-model="form.remark"
type="textarea"
placeholder="请输入内容"
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary">确 定</el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
const { proxy } = getCurrentInstance();
const router = useRouter();
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
phonenumber: undefined,
status: undefined,
deptId: undefined,
},
rules: {
userName: [
{ required: true, message: "用户名称不能为空", trigger: "blur" },
{
min: 2,
max: 20,
message: "用户名称长度必须介于 2 和 20 之间",
trigger: "blur",
},
],
nickName: [
{ required: true, message: "用户昵称不能为空", trigger: "blur" },
],
password: [
{ required: true, message: "用户密码不能为空", trigger: "blur" },
{
min: 5,
max: 20,
message: "用户密码长度必须介于 5 和 20 之间",
trigger: "blur",
},
{
pattern: /^[^<>"'|\\]+$/,
message: "不能包含非法字符:< > \" ' \\ |",
trigger: "blur",
},
],
email: [
{
type: "email",
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"],
},
],
phonenumber: [
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur",
},
],
},
});
const { queryParams, form, rules } = toRefs(data);
const total = ref(10);
const open = ref(false);
const title = ref("添加用户");
const searchForm = ref({
startTime: "", // 开始时间
endTime: "", // 结束时间
});
// 表头样式(清新浅蓝主题)
const headerStyle = {
backgroundColor: "#f0f9ff",
color: "#409eff",
fontWeight: "500",
};
/** 重置操作表单 */
function reset() {
form.value = {
userId: undefined,
deptId: undefined,
userName: undefined,
nickName: undefined,
password: undefined,
phonenumber: undefined,
email: undefined,
sex: undefined,
status: "0",
remark: undefined,
postIds: [],
roleIds: [],
};
}
/** 用户状态修改 */
function handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用";
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset();
open.value = true;
title.value = "修改用户";
const userId = row.userId || ids.value;
getUser(userId).then((response) => {
form.value = response.data;
postOptions.value = response.posts;
roleOptions.value = response.roles;
form.value.postIds = response.postIds;
form.value.roleIds = response.roleIds;
form.password = "";
});
}
/** 删除按钮操作 */
function handleDelete(row) {
// const userIds = row.userId || ids.value;
ElMessageBox.confirm("是否确认删除用户?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
ElMessage.success(`删除成功`);
});
}
/** 重置密码按钮操作 */
function handleResetPwd(row) {
proxy
.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return "不能包含非法字符:< > \" ' \\ |";
}
},
})
.then(({ value }) => {
resetUserPwd(row.userId, value).then((response) => {
proxy.$modal.msgSuccess("修改成功,新密码是:" + value);
});
})
.catch(() => {});
}
/** 跳转角色分配 */
function handleAuthRole(row) {
const userId = row.userId;
router.push("/system/user-auth/role/" + userId);
}
// 模拟电表数据(与原型一致)
const tableData = ref([
{
userName: "admin",
name: "张三",
sex: "男",
phonenumber: "123456789",
createTime: "2025-10-09",
status: true,
},
]);
// 点击"查询"按钮
const handleQuery = () => {
console.log("查询条件:", searchForm.value);
// 实际项目中,这里会调用接口,根据 startTime/endTime 筛选数据
// 示例tableData.value = 接口返回的筛选后数据
};
const handleAdd = () => {
open.value = true;
title.value = "添加用户";
};
const cancel = () => {
open.value = false;
};
const getList = () => {};
</script>
<style scoped>
/* 页面整体:浅灰蓝背景,清新柔和 */
.meter-monitoring-page {
padding: 20px;
background-color: #f8fafc;
}
/* 卡片样式:圆角 + 悬浮阴影,增强层次感 */
.page-card {
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}
/* 搜索表单:间距与对齐优化 */
.search-form {
margin-bottom: 20px;
align-items: center;
}
/* 日期选择器:宽度统一,视觉更整齐 */
.el-date-picker {
width: 220px;
}
/* 按钮:间距调整,避免拥挤 */
.el-button {
margin-right: 10px;
}
/* 表格宽度100%,充分利用空间 */
.meter-table {
width: 100%;
}
.pagination-container {
display: flex;
justify-content: flex-end;
}
</style>