res: 角色管理modal抽取,优化用户管理modal实现

This commit is contained in:
zy7y
2022-09-19 00:08:10 +08:00
parent b6d8c034ad
commit 9b16af74ea
11 changed files with 6162 additions and 456 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,7 @@ defineProps({
</template> </template>
<style scoped> <style scoped>
.v-md-editor-preview /deep/ .github-markdown-body { :deep(.github-markdown-body) {
padding: 5px 20px !important; padding: 5px 20px !important;
margin: 0px !important; margin: 0px !important;
} }

View File

@@ -38,17 +38,14 @@ const emits = defineEmits(['createClick', 'updateClick', 'deleteClick'])
// 事件 // 事件
const createEvent = () => { const createEvent = () => {
console.log('点击了 table组件 新增 -> 向父组件传递')
emits('createClick') emits('createClick')
} }
const updateEvent = (record) => { const updateEvent = (record) => {
console.log('点击了 table组件 更新 -> 向父组件传递', record)
emits('updateClick', record) emits('updateClick', record)
} }
const deleteEvent = (record) => { const deleteEvent = (record) => {
console.log('点击了 table组件 删除-> 向父组件传递', record)
emits('deleteClick', record) emits('deleteClick', record)
} }
@@ -68,7 +65,7 @@ const expand = tableTree()
</template> </template>
<a-table <a-table
:columns="columns" :columns="columns"
:scroll="{ y: 'calc(100vh - 300px)' }" :scroll="{ y: 'calc(100vh - 420px)' }"
:data-source="dataSource" :data-source="dataSource"
:pagination="pagination" :pagination="pagination"
:row-key="(record) => record.id" :row-key="(record) => record.id"

View File

@@ -16,13 +16,7 @@ const routes = [
name: 'main', name: 'main',
path: '/main', path: '/main',
meta: { title: '主页' }, meta: { title: '主页' },
component: () => import('@/views/main/main.vue'), component: () => import('@/views/main/main.vue')
children: [
{
path: '/demo',
component: () => import('@/views/main/demo.vue')
}
]
}, },
{ {
path: '/:pathMatch(.*)*', path: '/:pathMatch(.*)*',

View File

@@ -18,6 +18,8 @@ export const userStore = defineStore(
const isLoading = ref(false) const isLoading = ref(false)
const isPush = ref(false)
// getter // getter
const accessToken = computed(() => 'Bearer ' + token.value) const accessToken = computed(() => 'Bearer ' + token.value)
@@ -83,6 +85,7 @@ export const userStore = defineStore(
} }
return { return {
isPush,
token, token,
accessToken, accessToken,
userInfo, userInfo,

View File

@@ -1,50 +0,0 @@
<script setup>
import { ref } from 'vue'
import UserModal from './system/user/user-modal.vue'
import { getRoles } from '@/service/role'
const isShow = ref(false)
const title = ref()
const type = ref()
const roleOptions = ref([])
getRoles({ limit: 100 }).then((res) => {
roleOptions.value = res.data.items.map((e) => ({ label: e.name, value: e.id }))
})
const add = () => {
isShow.value = !isShow.value
title.value = '新增用户'
}
const put = () => {
console.log('put')
}
const ok = (formRef) => {
formRef.value.validateFields().then(() => {})
}
const cancel = () => {
console.log('cancel')
isShow.value = !isShow.value
}
</script>
<template>
<div>
demo
<a-button @click="add">新增</a-button>
<a-button @click="put">更新</a-button>
<UserModal
:modal-title="title"
:modal-type="type"
:show-modal="isShow"
:role-options="roleOptions"
@modal-ok="ok"
@modal-cancel="cancel"
></UserModal>
</div>
</template>
<style scoped></style>

View File

@@ -0,0 +1,151 @@
<script setup>
import { ref, reactive, watch } from 'vue'
import { message } from 'ant-design-vue'
import { rules, treeFieldNames } from './conf'
import { addRole, putRole } from '@/service/role'
import { getMenus as getRoleMenu } from '@/service/user'
import { getMenus } from '@/service/menu'
import { userStore } from '@/stores/user'
const props = defineProps({
modalTitle: {
// modal 右上角显示的title
type: String
},
modalType: {
// create or update
type: String,
default: 'create'
}
})
const showModal = ref(false)
const formRef = ref()
const roleForm = reactive({
name: '',
remark: '',
menus: []
})
// 记录修改角色的ID
const userId = ref()
// menu数据
const treeData = ref()
const treeRef = ref()
watch(showModal, async (newValue) => {
if (newValue) {
const res = await getMenus()
treeData.value = res.data
}
})
// 记录选中的子节点
const checkedKeys = ref([])
// 展开的节点
const expandedKeys = ref([])
// 选中事件
const check = (checkedKeys, e) => {
roleForm.menus = [...e.halfCheckedKeys, ...checkedKeys]
}
// 获取当前角色 实际上传是 用的menus 和 展示在tree中的选中menus
const getCurrentMenu = (record) => {
let allMenus = []
let checkMenus = []
getRoleMenu(record.id).then((res) => {
function _mids(menus) {
for (const menu of menus) {
allMenus.push(menu.id)
if (menu.children) {
_mids(menu.children)
} else {
checkMenus.push(menu.id)
}
}
}
_mids(res.data)
})
return { allMenus, checkMenus }
}
// 编辑角色时调用
const openModal = (record) => {
showModal.value = true
const { allMenus, checkMenus } = getCurrentMenu(record)
userId.value = record.id
roleForm.name = record.name
roleForm.remark = record.remark
checkedKeys.value = checkMenus
roleForm.menus = allMenus
}
// 新增成功 和关闭modal时重置数据
const resetData = () => {
formRef.value.resetFields()
checkedKeys.value = []
expandedKeys.value = []
}
const onOk = () => {
formRef.value.validateFields().then(async () => {
// 表单验证通过
let res
if (props.modalType === 'create') {
res = await addRole(roleForm)
} else {
res = await putRole(userId.value, roleForm)
}
message.success(res.msg)
resetData()
showModal.value = false
userStore().isPush = true
})
}
const onCancel = () => {
resetData()
}
defineExpose({ showModal, openModal })
</script>
<template>
<div class="modal">
<a-modal
v-model:visible="showModal"
:title="modalTitle"
ok-text="确认"
cancel-text="取消"
@ok="onOk"
@cancel="onCancel"
>
<a-form ref="formRef" :model="roleForm" :rules="rules">
<a-form-item name="name" label="名称">
<a-input v-model:value="roleForm.name" />
</a-form-item>
<a-form-item name="remark" label="描述">
<a-input v-model:value="roleForm.remark" />
</a-form-item>
<a-form-item name="menus" label="菜单">
<a-tree
ref="treeRef"
checkable
:tree-data="treeData"
:fieldNames="treeFieldNames"
@check="check"
v-model:checkedKeys="checkedKeys"
v-model:expandedKeys="expandedKeys"
>
</a-tree>
</a-form-item>
</a-form>
</a-modal>
</div>
</template>
<style scoped></style>

View File

@@ -1,13 +1,22 @@
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, onMounted, toRefs } from 'vue'
import Table from '@/components/table/table.vue' import Table from '@/components/table/table.vue'
import { getRoles, queryRole, delRole, putRole, addRole } from '@/service/role' import { getRoles, queryRole, delRole } from '@/service/role'
import { getMenus } from '@/service/menu' import { columns } from './conf'
import { columns, rules, treeFieldNames } from './conf'
import { message } from 'ant-design-vue'
import { getMenus as getRoleMenu } from '@/service/user'
import RoleSearch from './role-search.vue' import RoleSearch from './role-search.vue'
import RoleModal from './role-modal.vue'
import { userStore } from '@/stores/user'
const store = userStore()
store.$subscribe((mutation, state) => {
if (state.isPush) {
getPageData()
state.isPush = false
}
})
/**查询表单响应式数据 */ /**查询表单响应式数据 */
@@ -71,134 +80,27 @@ const delClick = (record) => {
getPageData() getPageData()
} }
/**新增角色 */ // 新增
const addVisible = ref(false)
const formRef = ref(null) const modalRef = ref()
const newRoleForm = reactive({ const modalConf = reactive({
name: '', title: '',
remark: '', type: ''
menus: []
}) })
// 记录选中的子节点
const checkedKeys = ref([])
// 展开的节点
const expandedKeys = ref([])
// 选中事件
const check = (checkedKeys, e) => {
newRoleForm.menus = [...e.halfCheckedKeys, ...checkedKeys]
}
const addClick = () => { const addClick = () => {
addVisible.value = !addVisible.value
// 弹出modal 并获取菜单树 // 弹出modal 并获取菜单树
getMenus().then((res) => (treeData.value = res.data)) modalConf.title = '新增角色'
modalConf.type = 'create'
modalRef.value.showModal = true
} }
// 新增modal 确定的回调
const onOk = () => {
formRef.value.validateFields().then(() => {
// 表单验证通过
addRole(newRoleForm).then((res) => {
if (res.msg === '请求成功') {
message.success('新增成功')
// 1. 关闭 modal
addVisible.value = !addVisible.value
// 2. 重置响应式数据
formRef.value.resetFields()
checkedKeys.value = []
expandedKeys.value = []
// 3. 刷新页面数据
getPageData()
}
})
})
}
// 新增modal 取消回调
const onCancel = () => {
// 2. 重置响应式数据
formRef.value.resetFields()
checkedKeys.value = []
expandedKeys.value = []
}
/**更新 */
/**
* 编辑时获取数据 回显到put modal
* @param {} record 行数据
*/
// modal 里表达响应式数据
const putRoleForm = reactive({
name: '',
remark: '',
menus: []
})
// 点击编辑弹modal事件
const putClick = (record) => { const putClick = (record) => {
putVisible.value = !putVisible.value modalConf.title = '编辑角色'
console.log(record, '父组件') modalConf.type = 'update'
getPutModalData(record) modalRef.value.openModal(record)
} }
const getPutModalData = (record) => { const { title, type } = toRefs(modalConf)
// 打开编辑的modal
getMenus().then((res) => (treeData.value = res.data))
// 通过角色获取菜单, 已有菜单
getRoleMenu(record.id).then((res) => {
function _mids(menus) {
for (const menu of menus) {
if (menu.children) {
_mids(menu.children)
} else {
putRoleForm.menus.push(menu.id)
}
}
}
_mids(res.data)
})
putId.value = record.id
putRoleForm.name = record.name
putRoleForm.remark = record.remark
}
// modal 是否显示
const putVisible = ref(false)
// modal 里的 表单 对象
const putRoleFormRef = ref()
// 记录 数据的 id 方便修改
const putId = ref()
//modal 事件
const onOkPut = () => {
//校验数据
putRoleFormRef.value.validateFields().then(() => {
//验证通过
putRole(putId.value, putRoleForm).then((res) => {
if (res.msg === '请求成功') {
message.success('修改成功')
// 1. 关闭 modal
putVisible.value = !putVisible.value
// 2. 重置响应式数据
putRoleFormRef.value.resetFields()
// 3. 重新拉取数据
getPageData()
}
})
})
}
const onCancelPut = () => {
putRoleFormRef.value.resetFields()
}
// tree
const treeData = ref()
</script> </script>
<template> <template>
@@ -218,62 +120,8 @@ const treeData = ref()
@delete-click="delClick" @delete-click="delClick"
> >
</Table> </Table>
<!-- 新增 -->
<a-modal
v-model:visible="addVisible"
title="新建角色"
ok-text="创建"
cancel-text="取消"
@ok="onOk"
@cancel="onCancel"
>
<a-form ref="formRef" :model="newRoleForm" :rules="rules">
<a-form-item name="name" label="名称">
<a-input v-model:value="newRoleForm.name" />
</a-form-item>
<a-form-item name="remark" label="描述">
<a-input v-model:value="newRoleForm.remark" />
</a-form-item>
<a-form-item name="menus" label="菜单">
<a-tree
checkable
:tree-data="treeData"
:fieldNames="treeFieldNames"
@check="check"
v-model:checkedKeys="checkedKeys"
v-model:expandedKeys="expandedKeys"
>
</a-tree>
</a-form-item>
</a-form>
</a-modal>
<!-- 修改 --> <RoleModal ref="modalRef" :modal-title="title" :modal-type="type" />
<a-modal
v-model:visible="putVisible"
title="编辑角色"
ok-text="确认"
cancel-text="取消"
@ok="onOkPut"
@cancel="onCancelPut"
>
<a-form ref="putRoleFormRef" :model="putRoleForm" :rules="rules">
<a-form-item name="name" label="名称">
<a-input v-model:value="putRoleForm.name" />
</a-form-item>
<a-form-item name="remark" label="描述">
<a-input v-model:value="putRoleForm.remark" />
</a-form-item>
<a-form-item name="menus" label="菜单">
<a-tree
checkable
:tree-data="treeData"
:fieldNames="treeFieldNames"
v-model:checkedKeys="putRoleForm.menus"
></a-tree>
</a-form-item>
</a-form>
</a-modal>
</div> </div>
</template> </template>

View File

@@ -1,10 +1,11 @@
<script setup> <script setup>
import { reactive, ref } from 'vue' import { reactive, ref, watch } from 'vue'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { addUserRules, putUserRules } from './conf' import { addUserRules, putUserRules } from './conf'
import { addUser, putUser } from '@/service/user' import { addUser, putUser, getUserInfo } from '@/service/user'
import { userStore } from '@/stores/user' import { userStore } from '@/stores/user'
import { getRoles } from '@/service/role'
const props = defineProps({ const props = defineProps({
modalTitle: { modalTitle: {
@@ -15,22 +16,10 @@ const props = defineProps({
// create or update // create or update
type: String, type: String,
default: 'create' default: 'create'
},
roleOptions: {
// 角色列表
type: Array,
default: () => []
},
userId: {
// 更新才会使用
type: Number,
require: false
} }
}) })
const emits = defineEmits(['modalCancel']) const store = userStore()
const sotre = userStore()
/** 页面数据 */ /** 页面数据 */
const formRef = ref() const formRef = ref()
@@ -50,6 +39,34 @@ const putUserForm = reactive({
roles: [] roles: []
}) })
// modal 状态打开
const showModal = ref(false)
// 更新数据的 用户id
const userId = ref()
// 监听modal状态是否为打开 打开就请求数据
const roleOptions = ref([])
watch(showModal, async () => {
if (showModal.value) {
const res = await getRoles({ limit: 100 })
roleOptions.value = res.data.items.map((e) => ({ label: e.name, value: e.id }))
}
})
// 打开modal时的处理 - 更新
const openModal = async (record) => {
// 打开编辑的modal
showModal.value = !showModal.value
userId.value = record.id
// 加载当前用户id 具备的用户角色
const res = await getUserInfo(record.id)
putUserForm.roles = res.data.roles.map((e) => e.id)
// 昵称信息
putUserForm.nickname = res.data.nickname
putUserForm.password = '加密之后的密码'
}
// 点击modal 确定
const onOk = () => { const onOk = () => {
formRef.value.validateFields().then(async () => { formRef.value.validateFields().then(async () => {
let res let res
@@ -59,36 +76,31 @@ const onOk = () => {
} else { } else {
const { nickname, password, roles } = putUserForm const { nickname, password, roles } = putUserForm
let rids = roles.map((e, i) => ({ rid: e, status: i === 0 ? 5 : 1 })) let rids = roles.map((e, i) => ({ rid: e, status: i === 0 ? 5 : 1 }))
res = await putUser(props.userId, { nickname, password, roles: rids }) res = await putUser(userId.value, {
nickname,
password,
roles: rids
})
if (userId.value === store.userInfo.id) {
// 并且修改了激活角色
if (rids[0]['rid'] !== store.userInfo.roles[0]['id']) {
store.getUserData(userId.value)
}
}
} }
message.success(res.msg)
formRef.value.resetFields() formRef.value.resetFields()
showModal.value = !showModal.value showModal.value = !showModal.value
store.isPush = true
}) })
} }
// 点击modal 取消
const onCancel = () => { const onCancel = () => {
formRef.value.resetFields() formRef.value.resetFields()
emits('modalCancel')
} }
const showModal = ref(false) defineExpose({ showModal, openModal })
// 添加用户
const addUserAction = () => {
formRef.value.validateFields().then(() => {
// 表单验证通过
newUserForm.roles = newUserForm.roles.map((e, i) => ({ rid: e, status: i === 0 ? 5 : 1 }))
addUser(newUserForm).then((res) => {
if (res.msg === '请求成功') {
message.success('新增成功')
// 2. 重置响应式数据
formRef.value.resetFields()
// 1. 关闭 modal
showModal.value = !showModal.value
}
})
})
}
</script> </script>
<template> <template>

View File

@@ -22,7 +22,7 @@ const resetEvent = () => {
<template> <template>
<div class="search"> <div class="search">
<a-form ref="formRef" layout="inline" :model="queryForm"> <a-form ref="formRef" layout="inline" :model="queryForm" name="search">
<a-form-item label="用户名" name="username"> <a-form-item label="用户名" name="username">
<a-input placeholder="用户名" v-model:value="queryForm.username"> </a-input> <a-input placeholder="用户名" v-model:value="queryForm.username"> </a-input>
</a-form-item> </a-form-item>

View File

@@ -3,21 +3,37 @@ import { ref, reactive, onMounted } from 'vue'
import Table from '@/components/table/table.vue' import Table from '@/components/table/table.vue'
import { getUsers, queryUser, delUser, addUser, getUserInfo, putUser } from '@/service/user' import { getUsers, queryUser, delUser } from '@/service/user'
import { getRoles } from '@/service/role'
import { columns, addUserRules, putUserRules } from './conf' import { columns } from './conf'
import { message } from 'ant-design-vue'
import { userStore } from '@/stores/user'
import UserSearch from './user-search.vue' import UserSearch from './user-search.vue'
import UserModal from './user-modal.vue'
import { userStore } from '@/stores/user'
import { message } from 'ant-design-vue'
const store = userStore() const store = userStore()
// 监听sotre 中的isPush 刷新页面数据
store.$subscribe((mutation, state) => {
if (state.isPush) {
getPageData()
state.isPush = false
}
})
// 是否查询 // 是否查询
const isQuery = ref(false) const isQuery = ref(false)
// 列表数据 // 列表数据
const dataSource = ref([]) const dataSource = ref([])
const modalRef = ref()
// modal 配置
const modalConf = reactive({
title: '',
type: ''
})
//分页响应式配置 //分页响应式配置
const pagination = reactive({ const pagination = reactive({
current: 1, //当前页 current: 1, //当前页
@@ -63,119 +79,29 @@ const clickQuery = (form) => {
// 重置搜索框 // 重置搜索框
const resetQueryForm = () => { const resetQueryForm = () => {
isQuery.value = false isQuery.value = false
getPageData() store.isPush = true
} }
// 删除 // 删除
const delClick = (record) => { const delClick = async (record) => {
delUser(record.id) const res = await delUser(record.id)
message.success(res.msg)
getPageData() getPageData()
} }
/**新增用户 */ /**新增 */
const addVisible = ref(false)
const formRef = ref(null)
const newUserForm = reactive({
username: '',
nickname: '',
password: '',
roles: []
})
// 选择角色
const roleOptions = ref([])
const addClick = () => { const addClick = async () => {
addVisible.value = !addVisible.value modalConf.title = '新增用户'
// 请求角色信息 modalConf.type = 'create'
getRoles({ limit: 100 }).then((res) => { modalRef.value.showModal = !modalRef.value.showModal
roleOptions.value = res.data.items.map((e) => ({ label: e.name, value: e.id }))
})
} }
// 新增modal 确定的回调 /**编辑 */
const onOk = () => { const putClick = async (record) => {
formRef.value.validateFields().then(() => { modalConf.title = '编辑用户'
// 表单验证通过 modalConf.type = 'update'
newUserForm.roles = newUserForm.roles.map((e, i) => ({ rid: e, status: i === 0 ? 5 : 1 })) modalRef.value.openModal(record)
addUser(newUserForm).then((res) => {
if (res.msg === '请求成功') {
message.success('新增成功')
// 1. 关闭 modal
addVisible.value = !addVisible.value
// 2. 重置响应式数据
formRef.value.resetFields()
}
})
})
}
// 新增modal 取消回调
const onCancel = () => {
// 2. 重置响应式数据
formRef.value.resetFields()
}
/**更新用户 */
const putClick = (record) => {
// 打开编辑的modal
putVisible.value = !putVisible.value
// 请求所有角色信息
getRoles({ limit: 100 }).then((res) => {
roleOptions.value = res.data.items.map((e) => ({ label: e.name, value: e.id }))
})
putId.value = record.id
// 加载当前用户id 具备的用户角色
getUserInfo(record.id).then((res) => {
// 角色信息
putUserForm.roles = res.data.roles.map((e) => e.id)
// 昵称信息
putUserForm.nickname = res.data.nickname
putUserForm.password = '加密之后的密码'
})
}
const putVisible = ref(false)
const putUserFormRef = ref()
const putUserForm = reactive({
nickname: '',
password: '',
roles: []
})
const putId = ref()
//modal 事件
const onOkPut = async () => {
//校验数据
putUserFormRef.value.validateFields().then(async () => {
//验证通过
const { nickname, password, roles } = putUserForm
let rids = roles.map((e, i) => ({ rid: e, status: i === 0 ? 5 : 1 }))
const res = await putUser(putId.value, { nickname, password, roles: rids })
if (res.msg === '请求成功') {
message.success('修改成功')
// 1. 关闭 modal
putVisible.value = !putVisible.value
// 2. 重置响应式数据
putUserFormRef.value.resetFields()
// 修改了自己
if (putId.value === store.userInfo.id) {
// 并且修改了激活角色
if (rids[0]['rid'] !== store.userInfo.roles[0]['id']) {
store.getUserData(putId.value)
// 刷新组件 todo
}
} else {
// 3. 刷新页面数据
getPageData()
}
}
})
}
const onCancelPut = () => {
putUserFormRef.value.resetFields()
} }
</script> </script>
@@ -184,6 +110,7 @@ const onCancelPut = () => {
<!-- 查询 --> <!-- 查询 -->
<UserSearch @query-click="clickQuery" @reset-click="resetQueryForm" /> <UserSearch @query-click="clickQuery" @reset-click="resetQueryForm" />
<!-- 列表数据 -->
<Table <Table
:columns="columns" :columns="columns"
:data-source="dataSource" :data-source="dataSource"
@@ -193,67 +120,10 @@ const onCancelPut = () => {
@create-click="addClick" @create-click="addClick"
@update-click="putClick" @update-click="putClick"
@delete-click="delClick" @delete-click="delClick"
> />
</Table>
<!-- 新增 用户--> <!-- 新增&编辑 -->
<a-modal <UserModal ref="modalRef" :modal-title="modalConf.title" :modal-type="modalConf.type" />
v-model:visible="addVisible"
title="新建用户"
ok-text="创建"
cancel-text="取消"
@ok="onOk"
@cancel="onCancel"
>
<a-form ref="formRef" :model="newUserForm" :rules="addUserRules">
<a-form-item name="username" label="账号">
<a-input v-model:value="newUserForm.username" placeholder="用于登录" />
</a-form-item>
<a-form-item name="nickname" label="昵称">
<a-input v-model:value="newUserForm.nickname" />
</a-form-item>
<a-form-item name="password" label="密码">
<a-input-password v-model:value="newUserForm.password" autocomplete="on" />
</a-form-item>
<a-form-item name="roles" label="角色">
<a-select
v-model:value="newUserForm.roles"
mode="multiple"
style="width: 100%"
placeholder="默认激活第一个角色"
:options="roleOptions"
></a-select>
</a-form-item>
</a-form>
</a-modal>
<!-- 修改用户 -->
<a-modal
v-model:visible="putVisible"
title="编辑用户"
ok-text="确认"
cancel-text="取消"
@ok="onOkPut"
@cancel="onCancelPut"
>
<a-form ref="putUserFormRef" :model="putUserForm" :rules="putUserRules">
<a-form-item name="nickname" label="昵称">
<a-input v-model:value="putUserForm.nickname" />
</a-form-item>
<a-form-item name="password" label="密码">
<a-input-password v-model:value="putUserForm.password" autocomplete="on" />
</a-form-item>
<a-form-item name="roles" label="角色">
<a-select
v-model:value="putUserForm.roles"
mode="multiple"
style="width: 100%"
placeholder="默认激活第一个角色"
:options="roleOptions"
></a-select>
</a-form-item>
</a-form>
</a-modal>
</div> </div>
</template> </template>