mirror of https://gitee.com/xiaonuobase/snowy
【更新】移动端按钮授权基本完成
parent
e288a19078
commit
ba0ed7978f
|
@ -1,32 +0,0 @@
|
||||||
import { baseRequest } from '@/utils/request'
|
|
||||||
|
|
||||||
const request = (url, ...arg) => baseRequest(`/mobile/menu/` + url, ...arg)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移动端菜单Api接口管理器
|
|
||||||
*
|
|
||||||
* @author yubaoshan
|
|
||||||
* @date 2023/01/28 22:42
|
|
||||||
**/
|
|
||||||
export default {
|
|
||||||
// 获取移动端菜单tree
|
|
||||||
mobileMenuTree(data) {
|
|
||||||
return request('tree', data, 'get')
|
|
||||||
},
|
|
||||||
// 获取移动端菜单列表
|
|
||||||
mobileMenuList(data) {
|
|
||||||
return request('list', data, 'get')
|
|
||||||
},
|
|
||||||
// 提交移动端菜单表单 edit为true时为编辑,默认为新增
|
|
||||||
mobileMenuSubmitForm(data, edit = false) {
|
|
||||||
return request(edit ? 'add' : 'edit', data)
|
|
||||||
},
|
|
||||||
// 删除移动端菜单
|
|
||||||
mobileMenuDelete(data) {
|
|
||||||
return request('delete', data)
|
|
||||||
},
|
|
||||||
// 获取移动端菜单详情
|
|
||||||
mobileMenuDetail(data) {
|
|
||||||
return request('detail', data, 'get')
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2022] [https://www.xiaonuo.vip]
|
||||||
|
* Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
|
||||||
|
* 1.请不要删除和修改根目录下的LICENSE文件。
|
||||||
|
* 2.请不要删除和修改Snowy源码头部的版权声明。
|
||||||
|
* 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
|
||||||
|
* 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
|
||||||
|
* 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
|
||||||
|
* 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
|
||||||
|
*/
|
||||||
|
import { baseRequest } from '@/utils/request'
|
||||||
|
|
||||||
|
const request = (url, ...arg) => baseRequest(`/mobile/button/${url}`, ...arg)
|
||||||
|
/**
|
||||||
|
* 按钮
|
||||||
|
*
|
||||||
|
* @author yubaoshan
|
||||||
|
* @date 2022-09-22 22:33:20
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
// 获取按钮分页
|
||||||
|
mobileButtonPage(data) {
|
||||||
|
return request('page', data, 'get')
|
||||||
|
},
|
||||||
|
// 提交表单 edit为true时为编辑,默认为新增
|
||||||
|
mobileButtonSubmitForm(data, edit = false) {
|
||||||
|
return request(edit ? 'add' : 'edit', data)
|
||||||
|
},
|
||||||
|
// 删除按钮
|
||||||
|
mobileButtonDelete(data) {
|
||||||
|
return request('delete', data)
|
||||||
|
},
|
||||||
|
// 获取按钮详情
|
||||||
|
mobileButtonDetail(data) {
|
||||||
|
return request('detail', data, 'get')
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,7 +33,7 @@ export default {
|
||||||
mobileMenuDetail(data) {
|
mobileMenuDetail(data) {
|
||||||
return request('detail', data, 'get')
|
return request('detail', data, 'get')
|
||||||
},
|
},
|
||||||
// 获取类别选择器
|
// 获取模块选择器
|
||||||
mobileMenuModuleSelector(data) {
|
mobileMenuModuleSelector(data) {
|
||||||
return request('moduleSelector', data, 'get')
|
return request('moduleSelector', data, 'get')
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="visible"
|
||||||
|
:title="formData.id ? '编辑按钮' : '增加按钮'"
|
||||||
|
:width="500"
|
||||||
|
:mask-closable="false"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@ok="onSubmit"
|
||||||
|
@cancel="onClose"
|
||||||
|
>
|
||||||
|
<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
|
||||||
|
<a-form-item label="显示名称:" name="title">
|
||||||
|
<a-input v-model:value="formData.title" placeholder="请输入显示名称" allow-clear />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="编码:" name="code">
|
||||||
|
<a-input v-model:value="formData.code" placeholder="请输入按钮编码" allow-clear />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="排序:" name="sortCode">
|
||||||
|
<a-slider v-model:value="formData.sortCode" :max="100" :min="0" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { required } from '@/utils/formRules'
|
||||||
|
import buttonApi from '@/api/mobile/resource/buttonApi'
|
||||||
|
// 默认是关闭状态
|
||||||
|
let visible = $ref(false)
|
||||||
|
const emit = defineEmits({ successful: null })
|
||||||
|
const formRef = ref()
|
||||||
|
// 表单数据,也就是默认给一些数据
|
||||||
|
const formData = ref({})
|
||||||
|
const recordData = ref()
|
||||||
|
// 打开弹框
|
||||||
|
const onOpen = (record, buttonData) => {
|
||||||
|
visible = true
|
||||||
|
recordData.value = record
|
||||||
|
formData.value = {
|
||||||
|
sortCode: 99
|
||||||
|
}
|
||||||
|
if (buttonData) {
|
||||||
|
formData.value = Object.assign({}, buttonData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 关闭弹框
|
||||||
|
const onClose = () => {
|
||||||
|
formRef.value.resetFields()
|
||||||
|
visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认要校验的
|
||||||
|
const formRules = {
|
||||||
|
title: [required('请输入按钮名称')],
|
||||||
|
code: [required('请输入按钮编码')]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证并提交数据
|
||||||
|
const onSubmit = () => {
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(() => {
|
||||||
|
const defParam = {
|
||||||
|
category: 'BUTTON',
|
||||||
|
// module: recordData.value.module,
|
||||||
|
parentId: recordData.value.id
|
||||||
|
}
|
||||||
|
const param = Object.assign(defParam, formData.value)
|
||||||
|
buttonApi.mobileButtonSubmitForm(param, !formData.value.id).then(() => {
|
||||||
|
onClose()
|
||||||
|
emit('successful')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用这个函数将子组件的一些数据和方法暴露出去
|
||||||
|
defineExpose({
|
||||||
|
onOpen
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<template>
|
||||||
|
<a-drawer
|
||||||
|
title="按钮权限"
|
||||||
|
:width="650"
|
||||||
|
:visible="visible"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
:body-style="{ paddingBottom: '80px' }"
|
||||||
|
:footer-style="{ textAlign: 'right' }"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<s-table
|
||||||
|
ref="table"
|
||||||
|
:columns="columns"
|
||||||
|
:data="loadData"
|
||||||
|
:alert="false"
|
||||||
|
:row-key="(record) => record.id"
|
||||||
|
:tool-config="toolConfig"
|
||||||
|
>
|
||||||
|
<template #operator class="table-operator">
|
||||||
|
<a-button type="primary" @click="buttonForm.onOpen(recordData)">
|
||||||
|
<template #icon>
|
||||||
|
<plus-outlined />
|
||||||
|
</template>
|
||||||
|
<span>新增按钮</span>
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a @click="buttonForm.onOpen(recordData, record)">编辑</a>
|
||||||
|
<a-divider type="vertical" />
|
||||||
|
<a-popconfirm title="确定要删除此按钮吗?" @confirm="removeButton(record)">
|
||||||
|
<a-button type="link" danger size="small">删除</a-button>
|
||||||
|
</a-popconfirm>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</s-table>
|
||||||
|
</a-drawer>
|
||||||
|
<Form ref="buttonForm" @successful="table.refresh(true)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import buttonApi from '@/api/mobile/resource/buttonApi'
|
||||||
|
import Form from './form.vue'
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'title'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '编码',
|
||||||
|
dataIndex: 'code'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '排序',
|
||||||
|
dataIndex: 'sortCode',
|
||||||
|
sorter: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
align: 'center',
|
||||||
|
scopedSlots: { customRender: 'action' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
const toolConfig = { refresh: true, height: false, columnSetting: false, striped: false }
|
||||||
|
// 默认是关闭状态
|
||||||
|
let visible = $ref(false)
|
||||||
|
const searchFormState = ref()
|
||||||
|
const buttonForm = ref()
|
||||||
|
const recordData = ref()
|
||||||
|
const table = ref()
|
||||||
|
|
||||||
|
// 打开抽屉
|
||||||
|
const onOpen = (record) => {
|
||||||
|
recordData.value = record
|
||||||
|
searchFormState.value = {
|
||||||
|
parentId: record.id,
|
||||||
|
category: 'BUTTON'
|
||||||
|
}
|
||||||
|
visible = true
|
||||||
|
}
|
||||||
|
// 关闭抽屉
|
||||||
|
const onClose = () => {
|
||||||
|
visible = false
|
||||||
|
}
|
||||||
|
// 加载按钮数据
|
||||||
|
const loadData = (parameter) => {
|
||||||
|
return buttonApi.mobileButtonPage(Object.assign(parameter, searchFormState.value)).then((res) => {
|
||||||
|
return res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 删除
|
||||||
|
const removeButton = (record) => {
|
||||||
|
let params = [
|
||||||
|
{
|
||||||
|
id: record.id
|
||||||
|
}
|
||||||
|
]
|
||||||
|
buttonApi.mobileButtonDelete(params).then((res) => {
|
||||||
|
table.value.refresh(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 调用这个函数将子组件的一些数据和方法暴露出去
|
||||||
|
defineExpose({
|
||||||
|
onOpen
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -62,7 +62,7 @@
|
||||||
<a-popconfirm title="确定要删除吗?" @confirm="deleteMobileMenu(record)">
|
<a-popconfirm title="确定要删除吗?" @confirm="deleteMobileMenu(record)">
|
||||||
<a-button type="link" danger size="small">删除</a-button>
|
<a-button type="link" danger size="small">删除</a-button>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
<div v-if="record.parentId === '0'">
|
<div v-if="record.parentId === '0' || record.menuType === 'MENU'">
|
||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a-dropdown>
|
<a-dropdown>
|
||||||
<a class="ant-dropdown-link">
|
<a class="ant-dropdown-link">
|
||||||
|
@ -74,6 +74,9 @@
|
||||||
<a-menu-item v-if="record.parentId === '0'">
|
<a-menu-item v-if="record.parentId === '0'">
|
||||||
<a @click="changeModuleFormRef.onOpen(record)">更改模块</a>
|
<a @click="changeModuleFormRef.onOpen(record)">更改模块</a>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
|
<a-menu-item v-if="record.menuType === 'MENU'">
|
||||||
|
<a @click="button.onOpen(record)">按钮权限</a>
|
||||||
|
</a-menu-item>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</template>
|
</template>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
|
@ -85,12 +88,14 @@
|
||||||
</a-card>
|
</a-card>
|
||||||
<Form ref="formRef" @successful="table.refresh(true)" />
|
<Form ref="formRef" @successful="table.refresh(true)" />
|
||||||
<changeModuleForm ref="changeModuleFormRef" @successful="table.refresh(true)"/>
|
<changeModuleForm ref="changeModuleFormRef" @successful="table.refresh(true)"/>
|
||||||
|
<Button ref="button" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="mobileMenuIndex">
|
<script setup name="mobileMenuIndex">
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import Form from './form.vue'
|
import Form from './form.vue'
|
||||||
import changeModuleForm from './changeModuleForm.vue'
|
import changeModuleForm from './changeModuleForm.vue'
|
||||||
|
import Button from '../button/index.vue'
|
||||||
import mobileMenuApi from '@/api/mobile/resource/menuApi'
|
import mobileMenuApi from '@/api/mobile/resource/menuApi'
|
||||||
let searchFormState = reactive({})
|
let searchFormState = reactive({})
|
||||||
let moduleList = ref([])
|
let moduleList = ref([])
|
||||||
|
@ -99,6 +104,7 @@
|
||||||
const table = ref()
|
const table = ref()
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
const changeModuleFormRef = ref()
|
const changeModuleFormRef = ref()
|
||||||
|
const button = ref()
|
||||||
const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
|
const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,11 +29,23 @@
|
||||||
{{ record.parentName }}
|
{{ record.parentName }}
|
||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="column.dataIndex === 'title'">
|
<template v-if="column.dataIndex === 'title'">
|
||||||
<a-checkbox :checked="record.nameCheck" @update:checked="(val) => changeSub(record, val)">{{
|
<a-checkbox :checked="record.nameCheck" @update:checked="(val) => changeSub(record, val)">{{
|
||||||
record.title
|
record.title
|
||||||
}}</a-checkbox>
|
}}</a-checkbox>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-if="column.dataIndex === 'button'">
|
||||||
|
<template v-if="record.button.length > 0">
|
||||||
|
<template v-for="(item, index) in record.button" :key="item.id">
|
||||||
|
<a-checkbox v-model:checked="item.check" @change="(evt) => changeChildCheckBox(record, evt)">{{
|
||||||
|
item.title
|
||||||
|
}}</a-checkbox>
|
||||||
|
<br v-if="(index + 1) % 5 === 0" />
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
|
@ -45,14 +57,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="grantMobileResourceForm">
|
<script setup name="grantMobileResourceForm">
|
||||||
import tool from '@/utils/tool'
|
|
||||||
import roleApi from '@/api/sys/roleApi'
|
import roleApi from '@/api/sys/roleApi'
|
||||||
const spinningLoading = ref(false)
|
const spinningLoading = ref(false)
|
||||||
let firstShowMap = $ref({})
|
let firstShowMap = $ref({})
|
||||||
const emit = defineEmits({ successful: null })
|
const emit = defineEmits({ successful: null })
|
||||||
const submitLoading = ref(false)
|
const submitLoading = ref(false)
|
||||||
// 抽屉的宽度
|
// 抽屉的宽度
|
||||||
const drawerWidth = 600
|
const drawerWidth = 1000
|
||||||
// 自动获取宽度,默认获取浏览器的宽度的90%
|
// 自动获取宽度,默认获取浏览器的宽度的90%
|
||||||
//(window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) * 0.9
|
//(window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) * 0.9
|
||||||
|
|
||||||
|
@ -76,6 +87,11 @@
|
||||||
title: '菜单',
|
title: '菜单',
|
||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
width: 200
|
width: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'button',
|
||||||
|
title: '按钮授权',
|
||||||
|
dataIndex: 'button'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
const echoDatalist = ref([])
|
const echoDatalist = ref([])
|
||||||
|
@ -104,6 +120,7 @@
|
||||||
loadDatas.value = echoDatalist.value[0].menu
|
loadDatas.value = echoDatalist.value[0].menu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const checkFieldKeys = ['button']
|
||||||
let visible = $ref(false)
|
let visible = $ref(false)
|
||||||
// 返回的数据模型,最终需要转换成这样
|
// 返回的数据模型,最终需要转换成这样
|
||||||
let resultDataModel = {
|
let resultDataModel = {
|
||||||
|
@ -129,6 +146,16 @@
|
||||||
resEcho.grantInfoList.forEach((grant) => {
|
resEcho.grantInfoList.forEach((grant) => {
|
||||||
if (item.id === grant.menuId) {
|
if (item.id === grant.menuId) {
|
||||||
menueCheck.value++
|
menueCheck.value++
|
||||||
|
// 处理按钮
|
||||||
|
if (grant.buttonInfo) {
|
||||||
|
grant.buttonInfo.forEach((button) => {
|
||||||
|
item.button.forEach((itemButton) => {
|
||||||
|
if (button === itemButton.id) {
|
||||||
|
itemButton.check = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -169,10 +196,33 @@
|
||||||
item.check = val
|
item.check = val
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const checkAllChildNotChecked = (record) => {
|
||||||
|
const allChecked = checkFieldKeys.every((key) => {
|
||||||
|
// 遍历所有的字段
|
||||||
|
const child = record[key]
|
||||||
|
return child.every((field) => !field.check)
|
||||||
|
})
|
||||||
|
return allChecked
|
||||||
|
}
|
||||||
|
const changeChildCheckBox = (record, evt) => {
|
||||||
|
let checked = evt.target.checked
|
||||||
|
if (!checked && checkAllChildNotChecked(record)) {
|
||||||
|
// 这里注释掉勾选去掉所有按钮,联动去掉菜单
|
||||||
|
/*record.nameCheck = false
|
||||||
|
record.parentCheck = false*/
|
||||||
|
} else if (checked) {
|
||||||
|
record.nameCheck = checked
|
||||||
|
record.parentCheck = checked
|
||||||
|
}
|
||||||
|
}
|
||||||
// 二级菜单的勾选
|
// 二级菜单的勾选
|
||||||
const changeSub = (record, val) => {
|
const changeSub = (record, val) => {
|
||||||
// 选中二级菜单
|
// 选中二级菜单
|
||||||
record.nameCheck = val
|
record.nameCheck = val
|
||||||
|
checkFieldKeys.forEach((key) => {
|
||||||
|
// 遍历所有的字段
|
||||||
|
handleOnlySelf(record, key, val)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
// 当点击首列的勾选
|
// 当点击首列的勾选
|
||||||
const changeParent = (record, val) => {
|
const changeParent = (record, val) => {
|
||||||
|
@ -205,10 +255,16 @@
|
||||||
if (table.menu) {
|
if (table.menu) {
|
||||||
table.menu.forEach((item) => {
|
table.menu.forEach((item) => {
|
||||||
const grantInfo = {
|
const grantInfo = {
|
||||||
menuId: ''
|
menuId: '',
|
||||||
|
buttonInfo: []
|
||||||
}
|
}
|
||||||
if (item.nameCheck) {
|
if (item.nameCheck) {
|
||||||
grantInfo.menuId = item.id
|
grantInfo.menuId = item.id
|
||||||
|
item.button.forEach((button) => {
|
||||||
|
if (button.check) {
|
||||||
|
grantInfo.buttonInfo.push(button.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
resultDataModel.grantInfoList.push(grantInfo)
|
resultDataModel.grantInfoList.push(grantInfo)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue