feat(账号管理): 新增账号管理模块及相关功能
- 添加账号管理API接口 - 实现账号列表、添加/编辑、删除、启用/禁用功能 - 新增账号管理路由和页面 - 添加账号类型用户权限处理 - 密码输入框增加类型保护 - 实现账号管理相关组件和样式
This commit is contained in:
parent
80f428d694
commit
ca6621bbda
|
|
@ -0,0 +1,37 @@
|
||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
// 获取账号列表
|
||||||
|
export const getAccounts = (params: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/jnh/accounts/page',
|
||||||
|
method: 'post',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加账号
|
||||||
|
export const addOrUpdate = (params: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/jnh/accounts/addOrUpdate',
|
||||||
|
method: 'post',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除账号
|
||||||
|
export const deleteAccount = (params: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/jnh/accounts/remove',
|
||||||
|
method: 'post',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 账号启用/禁用
|
||||||
|
export const updateStatus = (params: any) => {
|
||||||
|
return request({
|
||||||
|
url: '/jnh/accounts/status',
|
||||||
|
method: 'post',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -62,6 +62,21 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
||||||
icon: 'iconfont ele-Edit',
|
icon: 'iconfont ele-Edit',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/jindex',
|
||||||
|
name: 'jindex',
|
||||||
|
component: () => import('/@/views/pages/jnh/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '账号管理',
|
||||||
|
isLink: '',
|
||||||
|
isHide: false,
|
||||||
|
isKeepAlive: true,
|
||||||
|
isAffix: true,
|
||||||
|
isIframe: false,
|
||||||
|
roles: ['jnh'],
|
||||||
|
icon: 'ele-Edit',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/index',
|
path: '/index',
|
||||||
name: 'index',
|
name: 'index',
|
||||||
|
|
@ -74,7 +89,7 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
|
||||||
isAffix: true,
|
isAffix: true,
|
||||||
isIframe: false,
|
isIframe: false,
|
||||||
roles: ['admin', 'common', 'secondCommon'],
|
roles: ['admin', 'common', 'secondCommon'],
|
||||||
icon: 'iconfont ele-Edit',
|
icon: 'ele-Edit',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -32,16 +32,19 @@ export const useUserInfo = defineStore('userInfo', {
|
||||||
async getApiUserInfo() {
|
async getApiUserInfo() {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let rolesLocal = ''
|
let rolesLocal = '';
|
||||||
if (Local.get('userInfoLocal').userType == '00') {
|
if (Local.get('userInfoLocal').userType == '00') {
|
||||||
Cookies.set('userName', 'common')
|
Cookies.set('userName', 'common');
|
||||||
rolesLocal = 'common'
|
rolesLocal = 'common';
|
||||||
} else if (Local.get('userInfoLocal').userType == '02') {
|
} else if (Local.get('userInfoLocal').userType == '02') {
|
||||||
Cookies.set('userName', 'secondCommon')
|
Cookies.set('userName', 'secondCommon');
|
||||||
rolesLocal = 'secondCommon'
|
rolesLocal = 'secondCommon';
|
||||||
|
} else if (Local.get('userInfoLocal').userType == 'jnh') {
|
||||||
|
Cookies.set('userName', 'jnh');
|
||||||
|
rolesLocal = 'jnh';
|
||||||
} else {
|
} else {
|
||||||
Cookies.set('userName', 'admin')
|
Cookies.set('userName', 'admin');
|
||||||
rolesLocal = 'admin'
|
rolesLocal = 'admin';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 模拟数据,请求接口时,记得删除多余代码及对应依赖的引入
|
// 模拟数据,请求接口时,记得删除多余代码及对应依赖的引入
|
||||||
|
|
@ -56,6 +59,7 @@ export const useUserInfo = defineStore('userInfo', {
|
||||||
// test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
|
// test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
|
||||||
let testRoles: Array<string> = ['common'];
|
let testRoles: Array<string> = ['common'];
|
||||||
let secondCommonRoles: Array<string> = ['secondCommon'];
|
let secondCommonRoles: Array<string> = ['secondCommon'];
|
||||||
|
let jnhRoles: Array<string> = ['jnh'];
|
||||||
// test 按钮权限标识
|
// test 按钮权限标识
|
||||||
let testAuthBtnList: Array<string> = ['btn.add', 'btn.link'];
|
let testAuthBtnList: Array<string> = ['btn.add', 'btn.link'];
|
||||||
// 不同用户模拟不同的用户权限
|
// 不同用户模拟不同的用户权限
|
||||||
|
|
@ -65,12 +69,14 @@ export const useUserInfo = defineStore('userInfo', {
|
||||||
} else if (rolesLocal == 'secondCommon') {
|
} else if (rolesLocal == 'secondCommon') {
|
||||||
defaultRoles = secondCommonRoles;
|
defaultRoles = secondCommonRoles;
|
||||||
defaultAuthBtnList = testAuthBtnList;
|
defaultAuthBtnList = testAuthBtnList;
|
||||||
|
} else if (rolesLocal == 'jnh') {
|
||||||
|
defaultRoles = jnhRoles;
|
||||||
|
defaultAuthBtnList = testAuthBtnList;
|
||||||
} else {
|
} else {
|
||||||
defaultRoles = testRoles;
|
defaultRoles = testRoles;
|
||||||
defaultAuthBtnList = testAuthBtnList;
|
defaultAuthBtnList = testAuthBtnList;
|
||||||
}
|
}
|
||||||
console.log("🚀 ~ getApiUserInfo ~ rolesLocal:", rolesLocal)
|
console.log('🚀 ~ getApiUserInfo ~ rolesLocal:', rolesLocal);
|
||||||
|
|
||||||
|
|
||||||
// 用户信息模拟数据
|
// 用户信息模拟数据
|
||||||
const userInfos = {
|
const userInfos = {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item class="login-animation1">
|
<el-form-item class="login-animation1">
|
||||||
<el-input text class="code_input" placeholder="请输入密码" v-model="state.ruleForm.captcha" clearable>
|
<el-input text class="code_input" type="password" placeholder="请输入密码" v-model="state.ruleForm.captcha" clearable>
|
||||||
<!-- <template #append>
|
<!-- <template #append>
|
||||||
<view @click="doSendCode">
|
<view @click="doSendCode">
|
||||||
<text v-if="!isSendCode" class="sendcode">发送验证码</text>
|
<text v-if="!isSendCode" class="sendcode">发送验证码</text>
|
||||||
|
|
@ -189,6 +189,8 @@ const signInSuccess = (isNoPower: boolean | undefined) => {
|
||||||
|
|
||||||
// 移动端逻辑
|
// 移动端逻辑
|
||||||
router.push('/richeditMobile');
|
router.push('/richeditMobile');
|
||||||
|
} else if (Session.get('userInfoLocal').userType == 'jnh') {
|
||||||
|
router.push('/jindex');
|
||||||
} else {
|
} else {
|
||||||
// PC端逻辑
|
// PC端逻辑
|
||||||
if (route.query?.redirect && route.query?.redirect != '/richeditMobile') {
|
if (route.query?.redirect && route.query?.redirect != '/richeditMobile') {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
<template>
|
||||||
|
<div class="index">
|
||||||
|
<el-dialog v-model="dialogTableVisible" :title="form.id ? '账号编辑' : '账号创建'" width="600" @closed="closeDialog">
|
||||||
|
<el-form :model="form" label-width="auto" :rules="rules" ref="ruleFormRef">
|
||||||
|
<el-form-item label="姓名" prop="name">
|
||||||
|
<el-input v-model="form.name" placeholder="请输入姓名" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="部门名称" prop="department">
|
||||||
|
<el-input v-model="form.department" placeholder="请输入部门名称" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="手机号码" prop="mobile">
|
||||||
|
<el-input v-model="form.mobile" placeholder="请输入手机号码" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="close">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submit()"> 确认 </el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="loginIndex">
|
||||||
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
|
import { NextLoading } from '/@/utils/loading';
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
|
import { addOrUpdate } from '/@/api/jnh';
|
||||||
|
|
||||||
|
const emit = defineEmits(['close']);
|
||||||
|
const rules = reactive({
|
||||||
|
name: [{ required: true, message: '必须填写姓名', trigger: 'blur' }],
|
||||||
|
mobile: [{ required: true, message: '必须填写手机号码', trigger: 'blur' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = ref({});
|
||||||
|
const dialogTableVisible = ref(false);
|
||||||
|
|
||||||
|
function open(data) {
|
||||||
|
console.log('🚀 ~ open ~ data:', data);
|
||||||
|
dialogTableVisible.value = true;
|
||||||
|
if (data) {
|
||||||
|
form.value = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function close() {
|
||||||
|
dialogTableVisible.value = false;
|
||||||
|
emit('close');
|
||||||
|
}
|
||||||
|
const ruleFormRef = ref(null);
|
||||||
|
async function submit() {
|
||||||
|
await ruleFormRef.value.validate();
|
||||||
|
|
||||||
|
addOrUpdate(form.value).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success('操作成功');
|
||||||
|
close();
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '操作失败');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面加载时
|
||||||
|
onMounted(() => {
|
||||||
|
NextLoading.done();
|
||||||
|
});
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
close,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
<template>
|
||||||
|
<div class="index">
|
||||||
|
<div class="form">
|
||||||
|
<div class="form_button">
|
||||||
|
<el-button type="primary" icon="Plus" @click="addOpen">创建</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form class="form_content">
|
||||||
|
<el-form-item label="手机号" prop="mobile">
|
||||||
|
<el-input v-model="form.mobile" placeholder="输入手机号进行搜索" class="input">
|
||||||
|
<template #append>
|
||||||
|
<el-button icon="Search" @click="getData" />
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="部门" prop="department">
|
||||||
|
<el-input v-model="form.department" placeholder="输入部门进行搜索" class="input">
|
||||||
|
<template #append>
|
||||||
|
<el-button icon="Search" @click="seagetDatarch" />
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="账号状态" prop="status">
|
||||||
|
<el-select v-model="form.status" placeholder="请选择账号状态" class="input" @change="getData">
|
||||||
|
<el-option label="禁用" :value="0" />
|
||||||
|
<el-option label="启用" :value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<tableComponents :tableData="tableData">
|
||||||
|
<el-table-column prop="name" label="姓名" align="center" />
|
||||||
|
<el-table-column prop="mobile" label="手机号" align="center" />
|
||||||
|
<el-table-column prop="createTime" label="创建时间" align="center" />
|
||||||
|
<el-table-column prop="updateTime" label="更新时间" align="center" />
|
||||||
|
<el-table-column prop="status" label="账号状态" align="center" />
|
||||||
|
<el-table-column label="操作" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="text" @click="addOpen(scope.row)">编辑</el-button>
|
||||||
|
<el-button type="text" @click="doDeleteAccount(scope.row)">删除</el-button>
|
||||||
|
<el-button type="text" v-if="scope.row.status == 0" @click="doUpdateStatus(scope.row)">启用</el-button>
|
||||||
|
<el-button type="text" v-else @click="doUpdateStatus(scope.row)">禁用</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</tableComponents>
|
||||||
|
|
||||||
|
<addDialog ref="addDialogRef" @close="getData"></addDialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="loginIndex">
|
||||||
|
import { onMounted, ref, reactive } from 'vue';
|
||||||
|
import { NextLoading } from '/@/utils/loading';
|
||||||
|
import { getAccounts, deleteAccount, updateStatus } from '/@/api/jnh';
|
||||||
|
import tableComponents from '/@/components/tableComponents/index.vue';
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
|
import addDialog from '/@/views/pages/jnh/add.vue';
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
keyword: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const tableData = reactive({
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
name: 'string',
|
||||||
|
mobile: 'string',
|
||||||
|
createTime: 'string',
|
||||||
|
updateTime: 'string',
|
||||||
|
status: '0',
|
||||||
|
department: 'sdfa',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'string',
|
||||||
|
mobile: 'string',
|
||||||
|
createTime: 'string',
|
||||||
|
updateTime: 'string',
|
||||||
|
status: '1',
|
||||||
|
department: 'sdfa',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
total: 0,
|
||||||
|
page: 1,
|
||||||
|
size: 20,
|
||||||
|
});
|
||||||
|
|
||||||
|
const addDialogRef = ref(addDialog);
|
||||||
|
// 新增弹窗打开
|
||||||
|
function addOpen(data) {
|
||||||
|
addDialogRef.value.open(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getData() {
|
||||||
|
let { code, data } = await getAccounts({
|
||||||
|
page: tableData.page,
|
||||||
|
size: tableData.size,
|
||||||
|
...form,
|
||||||
|
});
|
||||||
|
if (code == 200) {
|
||||||
|
tableData.data = data.list;
|
||||||
|
tableData.total = data.total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doDeleteAccount(row) {
|
||||||
|
let { code, data } = await deleteAccount({
|
||||||
|
id: row.id,
|
||||||
|
});
|
||||||
|
if (code == 200) {
|
||||||
|
ElMessage.success('删除成功');
|
||||||
|
getData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doUpdateStatus(row) {
|
||||||
|
let { code, data } = await updateStatus({
|
||||||
|
id: row.id,
|
||||||
|
status: row.status == 0 ? 1 : 0,
|
||||||
|
});
|
||||||
|
if (code == 200) {
|
||||||
|
ElMessage.success('操作成功');
|
||||||
|
getData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面加载时
|
||||||
|
onMounted(() => {
|
||||||
|
NextLoading.done();
|
||||||
|
|
||||||
|
getData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.index {
|
||||||
|
background-color: white;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
|
||||||
|
.input {
|
||||||
|
min-width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form_content {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item--large) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item--label-right .el-form-item__label) {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #3e3e3e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue