【升级】新增用户组功能-账号体系、业务体系

pull/244/head
俞宝山 2024-12-24 04:37:24 +08:00
parent 2b1f59acec
commit 2648e2ecc3
37 changed files with 2432 additions and 1 deletions

View File

@ -0,0 +1,44 @@
import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/biz/group/` + url, ...arg)
/**
* 用户组Api接口管理器
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
export default {
// 获取用户组分页
bizGroupPage(data) {
return request('page', data, 'get')
},
// 提交用户组表单 edit为true时为编辑默认为新增
bizGroupSubmitForm(data, edit = false) {
return request(edit ? 'edit' : 'add', data)
},
// 删除用户组
bizGroupDelete(data) {
return request('delete', data)
},
// 获取用户组详情
bizGroupDetail(data) {
return request('detail', data, 'get')
},
// 获取用户组下的用户
bizGroupOwnUser(data) {
return request('ownUser', data, 'get')
},
// 获取机构树
bizGroupOrgTreeSelector(data) {
return request('orgTreeSelector', data, 'get')
},
// 获取用户选择器
bizGroupUserSelector(data) {
return request('userSelector', data, 'get')
},
// 给用户组授权用户
bizGroupGrantUser(data) {
return request('grantUser', data)
}
}

View File

@ -0,0 +1,44 @@
import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/sys/group/` + url, ...arg)
/**
* 用户组Api接口管理器
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
export default {
// 获取用户组分页
sysGroupPage(data) {
return request('page', data, 'get')
},
// 提交用户组表单 edit为true时为编辑默认为新增
sysGroupSubmitForm(data, edit = false) {
return request(edit ? 'edit' : 'add', data)
},
// 删除用户组
sysGroupDelete(data) {
return request('delete', data)
},
// 获取用户组详情
sysGroupDetail(data) {
return request('detail', data, 'get')
},
// 获取用户组下的用户
sysGroupOwnUser(data) {
return request('ownUser', data, 'get')
},
// 获取机构树
sysGroupOrgTreeSelector(data) {
return request('orgTreeSelector', data, 'get')
},
// 获取用户选择器
sysGroupUserSelector(data) {
return request('userSelector', data, 'get')
},
// 给用户组授权用户
sysGroupGrantUser(data) {
return request('grantUser', data)
}
}

View File

@ -0,0 +1,81 @@
<template>
<xn-form-container
:title="formData.id ? '编辑用户组' : '增加用户组'"
:width="700"
v-model:open="open"
:destroy-on-close="true"
@close="onClose"
>
<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
<a-form-item label="名称:" name="name">
<a-input v-model:value="formData.name" placeholder="请输入名称" allow-clear />
</a-form-item>
<a-form-item label="备注:" name="remark">
<a-textarea v-model:value="formData.remark" placeholder="请输入备注" :auto-size="{ minRows: 3, maxRows: 5 }" />
</a-form-item>
<a-form-item label="排序码:" name="sortCode">
<a-input-number v-model:value="formData.sortCode" placeholder="请输入排序码" :min="1" :max="10000" style="width: 100%" />
</a-form-item>
</a-form>
<template #footer>
<a-button style="margin-right: 8px" @click="onClose"></a-button>
<a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
</template>
</xn-form-container>
</template>
<script setup name="bizGroupForm">
import { cloneDeep } from 'lodash-es'
import { required } from '@/utils/formRules'
import bizGroupApi from '@/api/biz/bizGroupApi'
//
const open = ref(false)
const emit = defineEmits({ successful: null })
const formRef = ref()
//
const formData = ref({})
const submitLoading = ref(false)
//
const onOpen = (record) => {
open.value = true
if (record) {
let recordData = cloneDeep(record)
formData.value = Object.assign({}, recordData)
}
}
//
const onClose = () => {
formRef.value.resetFields()
formData.value = {}
open.value = false
}
//
const formRules = {
name: [required('请输入名称')],
sortCode: [required('请输入排序码')],
}
//
const onSubmit = () => {
formRef.value
.validate()
.then(() => {
submitLoading.value = true
const formDataParam = cloneDeep(formData.value)
bizGroupApi
.bizGroupSubmitForm(formDataParam, formDataParam.id)
.then(() => {
onClose()
emit('successful')
})
.finally(() => {
submitLoading.value = false
})
})
.catch(() => {})
}
//
defineExpose({
onOpen
})
</script>

View File

@ -0,0 +1,183 @@
<template>
<a-card :bordered="false">
<a-form ref="searchFormRef" name="advanced_search" :model="searchFormState" class="ant-advanced-search-form">
<a-row :gutter="24">
<a-col :span="6">
<a-form-item label="名称" name="name">
<a-input v-model:value="searchFormState.name" placeholder="请输入名称" />
</a-form-item>
</a-col>
<a-col :span="6">
<a-button type="primary" @click="tableRef.refresh()"></a-button>
<a-button style="margin: 0 8px" @click="reset"></a-button>
</a-col>
</a-row>
</a-form>
<s-table
ref="tableRef"
:columns="columns"
:data="loadData"
:alert="options.alert.show"
bordered
:row-key="(record) => record.id"
:tool-config="toolConfig"
:row-selection="options.rowSelection"
>
<template #operator class="table-operator">
<a-space>
<a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('bizGroupAdd')">
<template #icon><plus-outlined /></template>
新增
</a-button>
<xn-batch-button
v-if="hasPerm('bizGroupBatchDelete')"
buttonName="批量删除"
icon="DeleteOutlined"
buttonDanger
:selectedRowKeys="selectedRowKeys"
@batchCallBack="deleteBatchBizGroup"
/>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<a-space>
<a @click="formRef.onOpen(record)" v-if="hasPerm('bizGroupEdit')"></a>
<a-divider type="vertical" v-if="hasPerm(['bizGroupEdit', 'bizGroupGrantUser'], 'and')" />
<a @click="openGroupUserSelector(record)" v-if="hasPerm('bizGroupGrantUser')"></a>
<a-divider type="vertical" v-if="hasPerm(['bizGroupEdit', 'bizGroupDelete'], 'and')" />
<a-popconfirm title="确定要删除吗?" @confirm="deleteBizGroup(record)">
<a-button type="link" danger size="small" v-if="hasPerm('bizGroupDelete')"></a-button>
</a-popconfirm>
</a-space>
</template>
</template>
</s-table>
</a-card>
<Form ref="formRef" @successful="tableRef.refresh()" />
<xn-user-selector
ref="userSelectorRef"
:org-tree-api="selectorApiFunction.orgTreeApi"
:user-page-api="selectorApiFunction.userPageApi"
data-type="object"
:user-show="false"
@onBack="userCallBack"
/>
</template>
<script setup name="bizGroupIndex">
import { cloneDeep } from 'lodash-es'
import Form from './form.vue'
import bizGroupApi from '@/api/biz/bizGroupApi'
const searchFormState = ref({})
const searchFormRef = ref()
const tableRef = ref()
const formRef = ref()
const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
const recordCacheData = ref()
const userSelectorRef = ref()
const columns = [
{
title: '名称',
dataIndex: 'name'
},
{
title: '备注',
dataIndex: 'remark'
},
{
title: '排序码',
dataIndex: 'sortCode'
},
{
title: '创建时间',
dataIndex: 'createTime'
}
]
//
if (hasPerm(['bizGroupEdit', 'bizGroupGrantUser', 'bizGroupDelete'])) {
columns.push({
title: '操作',
dataIndex: 'action',
align: 'center',
width: 220
})
}
const selectedRowKeys = ref([])
//
const options = {
// columns needTotal: true
alert: {
show: false,
clear: () => {
selectedRowKeys.value = ref([])
}
},
rowSelection: {
onChange: (selectedRowKey, selectedRows) => {
selectedRowKeys.value = selectedRowKey
}
}
}
const loadData = (parameter) => {
const searchFormParam = cloneDeep(searchFormState.value)
return bizGroupApi.bizGroupPage(Object.assign(parameter, searchFormParam)).then((data) => {
return data
})
}
//
const reset = () => {
searchFormRef.value.resetFields()
tableRef.value.refresh(true)
}
//
const deleteBizGroup = (record) => {
let params = [
{
id: record.id
}
]
bizGroupApi.bizGroupDelete(params).then(() => {
tableRef.value.refresh(true)
})
}
//
const deleteBatchBizGroup = (params) => {
bizGroupApi.bizGroupDelete(params).then(() => {
tableRef.value.clearRefreshSelected()
})
}
//
const openGroupUserSelector = (record) => {
//
recordCacheData.value = record
//
const param = {
id: record.id
}
bizGroupApi.bizGroupOwnUser(param).then((data) => {
userSelectorRef.value.showUserPlusModal(data)
})
}
//
const userCallBack = (value) => {
const param = {
id: recordCacheData.value.id,
grantInfoList: value
}
bizGroupApi.bizGroupGrantUser(param).then(() => {})
}
// API
const selectorApiFunction = {
orgTreeApi: (param) => {
return bizGroupApi.bizGroupOrgTreeSelector(param).then((data) => {
return Promise.resolve(data)
})
},
userPageApi: (param) => {
return bizGroupApi.bizGroupUserSelector(param).then((data) => {
return Promise.resolve(data)
})
}
}
</script>

View File

@ -0,0 +1,90 @@
<template>
<xn-form-container
:title="formData.id ? '编辑用户组' : '增加用户组'"
:width="700"
v-model:open="open"
:destroy-on-close="true"
@close="onClose"
>
<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
<a-form-item label="名称:" name="name">
<a-input v-model:value="formData.name" placeholder="请输入名称" allow-clear />
</a-form-item>
<a-form-item label="备注:" name="remark">
<a-textarea v-model:value="formData.remark" placeholder="请输入备注" :auto-size="{ minRows: 3, maxRows: 5 }" />
</a-form-item>
<a-form-item label="排序码:" name="sortCode">
<a-input-number
v-model:value="formData.sortCode"
placeholder="请输入排序码"
:min="1"
:max="10000"
style="width: 100%"
/>
</a-form-item>
</a-form>
<template #footer>
<a-button style="margin-right: 8px" @click="onClose"></a-button>
<a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
</template>
</xn-form-container>
</template>
<script setup name="sysGroupForm">
import { cloneDeep } from 'lodash-es'
import { required } from '@/utils/formRules'
import sysGroupApi from '@/api/sys/groupApi'
//
const open = ref(false)
const emit = defineEmits({ successful: null })
const formRef = ref()
//
const formData = ref({})
const submitLoading = ref(false)
//
const onOpen = (record) => {
open.value = true
formData.value = {
sortCode: 99
}
if (record) {
let recordData = cloneDeep(record)
formData.value = Object.assign({}, recordData)
}
}
//
const onClose = () => {
formRef.value.resetFields()
formData.value = {}
open.value = false
}
//
const formRules = {
name: [required('请输入名称')],
sortCode: [required('请输入排序码')]
}
//
const onSubmit = () => {
formRef.value
.validate()
.then(() => {
submitLoading.value = true
const formDataParam = cloneDeep(formData.value)
sysGroupApi
.sysGroupSubmitForm(formDataParam, formDataParam.id)
.then(() => {
onClose()
emit('successful')
})
.finally(() => {
submitLoading.value = false
})
})
.catch(() => {})
}
//
defineExpose({
onOpen
})
</script>

View File

@ -0,0 +1,179 @@
<template>
<a-card :bordered="false">
<a-form ref="searchFormRef" name="advanced_search" :model="searchFormState" class="ant-advanced-search-form">
<a-row :gutter="24">
<a-col :span="6">
<a-form-item label="名称" name="name">
<a-input v-model:value="searchFormState.name" placeholder="请输入名称" />
</a-form-item>
</a-col>
<a-col :span="6">
<a-button type="primary" @click="tableRef.refresh()"></a-button>
<a-button style="margin: 0 8px" @click="reset"></a-button>
</a-col>
</a-row>
</a-form>
<s-table
ref="tableRef"
:columns="columns"
:data="loadData"
:alert="options.alert.show"
bordered
:row-key="(record) => record.id"
:tool-config="toolConfig"
:row-selection="options.rowSelection"
>
<template #operator class="table-operator">
<a-space>
<a-button type="primary" @click="formRef.onOpen()">
<template #icon><plus-outlined /></template>
新增
</a-button>
<xn-batch-button
buttonName="批量删除"
icon="DeleteOutlined"
buttonDanger
:selectedRowKeys="selectedRowKeys"
@batchCallBack="deleteBatchSysGroup"
/>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<a-space>
<a @click="formRef.onOpen(record)"></a>
<a-divider type="vertical" />
<a @click="openGroupUserSelector(record)"></a>
<a-divider type="vertical" />
<a-popconfirm title="确定要删除吗?" @confirm="deleteSysGroup(record)">
<a-button type="link" danger size="small">删除</a-button>
</a-popconfirm>
</a-space>
</template>
</template>
</s-table>
</a-card>
<Form ref="formRef" @successful="tableRef.refresh()" />
<xn-user-selector
ref="userSelectorRef"
:org-tree-api="selectorApiFunction.orgTreeApi"
:user-page-api="selectorApiFunction.userPageApi"
data-type="object"
:user-show="false"
@onBack="userCallBack"
/>
</template>
<script setup name="sysGroupIndex">
import { cloneDeep } from 'lodash-es'
import Form from './form.vue'
import sysGroupApi from '@/api/sys/groupApi'
const searchFormState = ref({})
const searchFormRef = ref()
const tableRef = ref()
const formRef = ref()
const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
const recordCacheData = ref()
const userSelectorRef = ref()
const columns = [
{
title: '名称',
dataIndex: 'name'
},
{
title: '备注',
dataIndex: 'remark'
},
{
title: '排序码',
dataIndex: 'sortCode'
},
{
title: '创建时间',
dataIndex: 'createTime'
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
width: 220
}
]
const selectedRowKeys = ref([])
//
const options = {
// columns needTotal: true
alert: {
show: false,
clear: () => {
selectedRowKeys.value = ref([])
}
},
rowSelection: {
onChange: (selectedRowKey, selectedRows) => {
selectedRowKeys.value = selectedRowKey
}
}
}
const loadData = (parameter) => {
const searchFormParam = cloneDeep(searchFormState.value)
return sysGroupApi.sysGroupPage(Object.assign(parameter, searchFormParam)).then((data) => {
return data
})
}
//
const reset = () => {
searchFormRef.value.resetFields()
tableRef.value.refresh(true)
}
//
const deleteSysGroup = (record) => {
let params = [
{
id: record.id
}
]
sysGroupApi.sysGroupDelete(params).then(() => {
tableRef.value.refresh(true)
})
}
//
const deleteBatchSysGroup = (params) => {
sysGroupApi.sysGroupDelete(params).then(() => {
tableRef.value.clearRefreshSelected()
})
}
//
const openGroupUserSelector = (record) => {
//
recordCacheData.value = record
//
const param = {
id: record.id
}
sysGroupApi.sysGroupOwnUser(param).then((data) => {
userSelectorRef.value.showUserPlusModal(data)
})
}
//
const userCallBack = (value) => {
const param = {
id: recordCacheData.value.id,
grantInfoList: value
}
sysGroupApi.sysGroupGrantUser(param).then(() => {})
}
// API
const selectorApiFunction = {
orgTreeApi: (param) => {
return sysGroupApi.sysGroupOrgTreeSelector(param).then((data) => {
return Promise.resolve(data)
})
},
userPageApi: (param) => {
return sysGroupApi.sysGroupUserSelector(param).then((data) => {
return Promise.resolve(data)
})
}
}
</script>

View File

@ -0,0 +1,41 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.api;
import java.util.List;
/**
* Api
*
* @author xuyuxiang
* @date 2022/6/6 11:33
**/
public interface SysGroupApi {
/**
*
*
* @author xuyuxiang
* @date 2022/5/13 21:00
*/
List<String> ownUser(String userId);
/**
*
*
* @author xuyuxiang
* @date 2022/8/1 18:28
*/
void grantUser(String userId, List<String> roleIdList);
}

View File

@ -0,0 +1,176 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import vip.xiaonuo.biz.modular.group.param.*;
import vip.xiaonuo.biz.modular.user.entity.BizUser;
import vip.xiaonuo.common.annotation.CommonLog;
import vip.xiaonuo.common.pojo.CommonResult;
import vip.xiaonuo.biz.modular.group.entity.BizGroup;
import vip.xiaonuo.biz.modular.group.service.BizGroupService;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
@Tag(name = "用户组控制器")
@RestController
@Validated
public class BizGroupController {
@Resource
private BizGroupService bizGroupService;
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
@Operation(summary = "获取用户组分页")
@SaCheckPermission("/biz/group/page")
@GetMapping("/biz/group/page")
public CommonResult<Page<BizGroup>> page(BizGroupPageParam bizGroupPageParam) {
return CommonResult.data(bizGroupService.page(bizGroupPageParam));
}
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
@Operation(summary = "添加用户组")
@CommonLog("添加用户组")
@SaCheckPermission("/biz/group/add")
@PostMapping("/biz/group/add")
public CommonResult<String> add(@RequestBody @Valid BizGroupAddParam bizGroupAddParam) {
bizGroupService.add(bizGroupAddParam);
return CommonResult.ok();
}
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
@Operation(summary = "编辑用户组")
@CommonLog("编辑用户组")
@SaCheckPermission("/biz/group/edit")
@PostMapping("/biz/group/edit")
public CommonResult<String> edit(@RequestBody @Valid BizGroupEditParam bizGroupEditParam) {
bizGroupService.edit(bizGroupEditParam);
return CommonResult.ok();
}
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
@Operation(summary = "删除用户组")
@CommonLog("删除用户组")
@SaCheckPermission("/biz/group/delete")
@PostMapping("/biz/group/delete")
public CommonResult<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
List<BizGroupIdParam> bizGroupIdParamList) {
bizGroupService.delete(bizGroupIdParamList);
return CommonResult.ok();
}
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
@Operation(summary = "获取用户组详情")
@SaCheckPermission("/biz/group/detail")
@GetMapping("/biz/group/detail")
public CommonResult<BizGroup> detail(@Valid BizGroupIdParam bizGroupIdParam) {
return CommonResult.data(bizGroupService.detail(bizGroupIdParam));
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "获取用户组下的用户")
@SaCheckPermission("/biz/group/ownUser")
@GetMapping("/biz/group/ownUser")
public CommonResult<List<String>> ownUser(@Valid BizGroupIdParam bizGroupIdParam) {
return CommonResult.data(bizGroupService.ownUser(bizGroupIdParam));
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "获取组织树选择器")
@SaCheckPermission("/biz/group/orgTreeSelector")
@GetMapping("/biz/group/orgTreeSelector")
public CommonResult<List<Tree<String>>> orgTreeSelector() {
return CommonResult.data(bizGroupService.orgTreeSelector());
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "获取用户选择器")
@SaCheckPermission("/biz/group/userSelector")
@GetMapping("/biz/group/userSelector")
public CommonResult<Page<BizUser>> userSelector(BizGroupSelectorUserParam bizGroupSelectorUserParam) {
return CommonResult.data(bizGroupService.userSelector(bizGroupSelectorUserParam));
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "给用户组授权用户")
@CommonLog("给用户组授权用户")
@SaCheckPermission("/biz/group/grantUser")
@PostMapping("/biz/group/grantUser")
public CommonResult<String> grantUser(@RequestBody @Valid BizGroupGrantUserParam bizGroupGrantUserParam) {
bizGroupService.grantUser(bizGroupGrantUserParam);
return CommonResult.ok();
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import vip.xiaonuo.common.pojo.CommonEntity;
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
@Getter
@Setter
@TableName("SYS_GROUP")
public class BizGroup extends CommonEntity {
/** 主键 */
@TableId
@Schema(description = "主键")
private String id;
/** 名称 */
@Schema(description = "名称")
private String name;
/** 备注 */
@Schema(description = "备注")
private String remark;
/** 排序码 */
@Schema(description = "排序码")
private Integer sortCode;
/** 扩展信息 */
@Schema(description = "扩展信息")
private String extJson;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.enums;
import lombok.Getter;
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
@Getter
public enum BizGroupEnum {
/** 测试 */
TEST("TEST");
private final String value;
BizGroupEnum(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import vip.xiaonuo.biz.modular.group.entity.BizGroup;
/**
* Mapper
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
public interface BizGroupMapper extends BaseMapper<BizGroup> {
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="vip.xiaonuo.biz.modular.group.mapper.BizGroupMapper">
</mapper>

View File

@ -0,0 +1,44 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
@Getter
@Setter
public class BizGroupAddParam {
/** 名称 */
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "name不能为空")
private String name;
/** 备注 */
@Schema(description = "备注")
private String remark;
/** 排序码 */
@Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "sortCode不能为空")
private Integer sortCode;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
@Getter
@Setter
public class BizGroupEditParam {
/** 主键 */
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "id不能为空")
private String id;
/** 名称 */
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "name不能为空")
private String name;
/** 备注 */
@Schema(description = "备注")
private String remark;
/** 排序码 */
@Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "sortCode不能为空")
private Integer sortCode;
}

View File

@ -0,0 +1,42 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
@Setter
public class BizGroupGrantUserParam {
/** 用户组id */
@Schema(description = "用户组id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "id不能为空")
private String id;
/** 授权用户信息 */
@Schema(description = "授权用户信息", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "grantInfoList不能为空")
private List<String> grantInfoList;
}

View File

@ -0,0 +1,35 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
/**
* Id
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
@Getter
@Setter
public class BizGroupIdParam {
/** 主键 */
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "id不能为空")
private String id;
}

View File

@ -0,0 +1,52 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
@Getter
@Setter
public class BizGroupPageParam {
/** 当前页 */
@Schema(description = "当前页码")
private Integer current;
/** 每页条数 */
@Schema(description = "每页条数")
private Integer size;
/** 排序字段 */
@Schema(description = "排序字段字段驼峰名称userName")
private String sortField;
/** 排序方式 */
@Schema(description = "排序方式升序ASCEND降序DESCEND")
private String sortOrder;
/** 关键词 */
@Schema(description = "关键词")
private String searchKey;
/** 名称 */
@Schema(description = "名称")
private String name;
}

View File

@ -0,0 +1,44 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
@Setter
public class BizGroupSelectorUserParam {
/** 当前页 */
@Schema(description = "当前页码")
private Integer current;
/** 每页条数 */
@Schema(description = "每页条数")
private Integer size;
/** 组织id */
@Schema(description = "组织id")
private String orgId;
/** 姓名关键词 */
@Schema(description = "姓名关键词")
private String searchKey;
}

View File

@ -0,0 +1,111 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.service;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import vip.xiaonuo.biz.modular.group.entity.BizGroup;
import vip.xiaonuo.biz.modular.group.param.*;
import vip.xiaonuo.biz.modular.user.entity.BizUser;
import java.util.List;
/**
* Service
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
public interface BizGroupService extends IService<BizGroup> {
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
Page<BizGroup> page(BizGroupPageParam bizGroupPageParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
void add(BizGroupAddParam bizGroupAddParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
void edit(BizGroupEditParam bizGroupEditParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
void delete(List<BizGroupIdParam> bizGroupIdParamList);
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
*/
BizGroup detail(BizGroupIdParam bizGroupIdParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
BizGroup queryEntity(String id);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
List<String> ownUser(BizGroupIdParam sysGroupIdParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
List<Tree<String>> orgTreeSelector();
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
Page<BizUser> userSelector(BizGroupSelectorUserParam bizGroupSelectorUserParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
void grantUser(BizGroupGrantUserParam bizGroupGrantUserParam);
}

View File

@ -0,0 +1,178 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.biz.modular.group.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.biz.modular.group.param.*;
import vip.xiaonuo.biz.modular.org.entity.BizOrg;
import vip.xiaonuo.biz.modular.org.service.BizOrgService;
import vip.xiaonuo.biz.modular.user.entity.BizUser;
import vip.xiaonuo.biz.modular.user.service.BizUserService;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.biz.modular.group.entity.BizGroup;
import vip.xiaonuo.biz.modular.group.mapper.BizGroupMapper;
import vip.xiaonuo.biz.modular.group.service.BizGroupService;
import vip.xiaonuo.sys.api.SysGroupApi;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Service
*
* @author yubaoshan
* @date 2024/12/24 03:33
**/
@Service
public class BizGroupServiceImpl extends ServiceImpl<BizGroupMapper, BizGroup> implements BizGroupService {
@Resource
private SysGroupApi sysGroupApi;
@Resource
private BizUserService bizUserService;
@Resource
private BizOrgService bizOrgService;
@Override
public Page<BizGroup> page(BizGroupPageParam bizGroupPageParam) {
QueryWrapper<BizGroup> queryWrapper = new QueryWrapper<BizGroup>().checkSqlInjection();
if(ObjectUtil.isNotEmpty(bizGroupPageParam.getName())) {
queryWrapper.lambda().like(BizGroup::getName, bizGroupPageParam.getName());
}
if(ObjectUtil.isAllNotEmpty(bizGroupPageParam.getSortField(), bizGroupPageParam.getSortOrder())) {
CommonSortOrderEnum.validate(bizGroupPageParam.getSortOrder());
queryWrapper.orderBy(true, bizGroupPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
StrUtil.toUnderlineCase(bizGroupPageParam.getSortField()));
} else {
queryWrapper.lambda().orderByAsc(BizGroup::getSortCode);
}
return this.page(CommonPageRequest.defaultPage(), queryWrapper);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void add(BizGroupAddParam bizGroupAddParam) {
BizGroup bizGroup = BeanUtil.toBean(bizGroupAddParam, BizGroup.class);
this.save(bizGroup);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void edit(BizGroupEditParam bizGroupEditParam) {
BizGroup bizGroup = this.queryEntity(bizGroupEditParam.getId());
BeanUtil.copyProperties(bizGroupEditParam, bizGroup);
this.updateById(bizGroup);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void delete(List<BizGroupIdParam> bizGroupIdParamList) {
// 执行删除
this.removeByIds(CollStreamUtil.toList(bizGroupIdParamList, BizGroupIdParam::getId));
}
@Override
public BizGroup detail(BizGroupIdParam bizGroupIdParam) {
return this.queryEntity(bizGroupIdParam.getId());
}
@Override
public BizGroup queryEntity(String id) {
BizGroup bizGroup = this.getById(id);
if(ObjectUtil.isEmpty(bizGroup)) {
throw new CommonException("用户组不存在id值为{}", id);
}
return bizGroup;
}
@Override
public List<String> ownUser(BizGroupIdParam sysGroupIdParam) {
return sysGroupApi.ownUser(sysGroupIdParam.getId());
}
@Override
public List<Tree<String>> orgTreeSelector() {
// 获取所有机构
List<BizOrg> allOrgList = bizOrgService.list();
// 定义机构集合
Set<BizOrg> bizOrgSet = CollectionUtil.newHashSet();
// 校验数据范围
List<String> loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope();
if(ObjectUtil.isNotEmpty(loginUserDataScope)) {
loginUserDataScope.forEach(orgId -> bizOrgSet.addAll(bizOrgService.getParentListById(allOrgList, orgId, true)));
} else {
return CollectionUtil.newArrayList();
}
List<TreeNode<String>> treeNodeList = bizOrgSet.stream().map(bizOrg ->
new TreeNode<>(bizOrg.getId(), bizOrg.getParentId(),
bizOrg.getName(), bizOrg.getSortCode()).setExtra(JSONUtil.parseObj(bizOrg)))
.collect(Collectors.toList());
return TreeUtil.build(treeNodeList, "0");
}
@Override
public Page<BizUser> userSelector(BizGroupSelectorUserParam bizGroupSelectorUserParam) {
LambdaQueryWrapper<BizUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 校验数据范围
List<String> loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope();
if(ObjectUtil.isNotEmpty(loginUserDataScope)) {
lambdaQueryWrapper.in(BizUser::getOrgId, loginUserDataScope);
} else {
return new Page<>();
}
// 只查询部分字段
lambdaQueryWrapper.select(BizUser::getId, BizUser::getAvatar, BizUser::getOrgId, BizUser::getPositionId, BizUser::getAccount,
BizUser::getName, BizUser::getSortCode, BizUser::getGender, BizUser::getEntryDate);
if (ObjectUtil.isNotEmpty(bizGroupSelectorUserParam.getOrgId())) {
// 如果机构id不为空则查询该机构及其子机构下的所有人
List<String> childOrgIdList = CollStreamUtil.toList(bizOrgService.getChildListById(bizOrgService
.getAllOrgList(), bizGroupSelectorUserParam.getOrgId(), true), BizOrg::getId);
if (ObjectUtil.isNotEmpty(childOrgIdList)) {
lambdaQueryWrapper.in(BizUser::getOrgId, childOrgIdList);
} else {
return new Page<>();
}
}
if(ObjectUtil.isNotEmpty(bizGroupSelectorUserParam.getSearchKey())) {
lambdaQueryWrapper.like(BizUser::getName, bizGroupSelectorUserParam.getSearchKey());
}
lambdaQueryWrapper.orderByAsc(BizUser::getSortCode);
return bizUserService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper);
}
@Override
public void grantUser(BizGroupGrantUserParam bizGroupGrantUserParam) {
sysGroupApi.grantUser(bizGroupGrantUserParam.getId(), bizGroupGrantUserParam.getGrantInfoList());
}
}

View File

@ -0,0 +1,166 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.controller;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import vip.xiaonuo.common.annotation.CommonLog;
import vip.xiaonuo.common.pojo.CommonResult;
import vip.xiaonuo.sys.modular.group.entity.SysGroup;
import vip.xiaonuo.sys.modular.group.param.*;
import vip.xiaonuo.sys.modular.group.service.SysGroupService;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import vip.xiaonuo.sys.modular.user.entity.SysUser;
import java.util.List;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Tag(name = "用户组控制器")
@RestController
@Validated
public class SysGroupController {
@Resource
private SysGroupService sysGroupService;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "获取用户组分页")
@GetMapping("/sys/group/page")
public CommonResult<Page<SysGroup>> page(SysGroupPageParam sysGroupPageParam) {
return CommonResult.data(sysGroupService.page(sysGroupPageParam));
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "添加用户组")
@CommonLog("添加用户组")
@PostMapping("/sys/group/add")
public CommonResult<String> add(@RequestBody @Valid SysGroupAddParam sysGroupAddParam) {
sysGroupService.add(sysGroupAddParam);
return CommonResult.ok();
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "编辑用户组")
@CommonLog("编辑用户组")
@PostMapping("/sys/group/edit")
public CommonResult<String> edit(@RequestBody @Valid SysGroupEditParam sysGroupEditParam) {
sysGroupService.edit(sysGroupEditParam);
return CommonResult.ok();
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "删除用户组")
@CommonLog("删除用户组")
@PostMapping("/sys/group/delete")
public CommonResult<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
List<SysGroupIdParam> sysGroupIdParamList) {
sysGroupService.delete(sysGroupIdParamList);
return CommonResult.ok();
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "获取用户组详情")
@GetMapping("/sys/group/detail")
public CommonResult<SysGroup> detail(@Valid SysGroupIdParam sysGroupIdParam) {
return CommonResult.data(sysGroupService.detail(sysGroupIdParam));
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "获取用户组下的用户")
@GetMapping("/sys/group/ownUser")
public CommonResult<List<String>> ownUser(@Valid SysGroupIdParam sysGroupIdParam) {
return CommonResult.data(sysGroupService.ownUser(sysGroupIdParam));
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "获取组织树选择器")
@GetMapping("/sys/group/orgTreeSelector")
public CommonResult<List<Tree<String>>> orgTreeSelector() {
return CommonResult.data(sysGroupService.orgTreeSelector());
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "获取用户选择器")
@GetMapping("/sys/group/userSelector")
public CommonResult<Page<SysUser>> userSelector(SysGroupSelectorUserParam sysGroupSelectorUserParam) {
return CommonResult.data(sysGroupService.userSelector(sysGroupSelectorUserParam));
}
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
@Operation(summary = "给用户组授权用户")
@CommonLog("给用户组授权用户")
@PostMapping("/sys/group/grantUser")
public CommonResult<String> grantUser(@RequestBody @Valid SysGroupGrantUserParam sysGroupGrantUserParam) {
sysGroupService.grantUser(sysGroupGrantUserParam);
return CommonResult.ok();
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.entity;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import vip.xiaonuo.common.pojo.CommonEntity;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
@Setter
@TableName("SYS_GROUP")
public class SysGroup extends CommonEntity {
/** 主键 */
@TableId
@Schema(description = "主键")
private String id;
/** 名称 */
@Schema(description = "名称")
private String name;
/** 备注 */
@Schema(description = "备注")
private String remark;
/** 排序码 */
@Schema(description = "排序码")
private Integer sortCode;
/** 扩展信息 */
@Schema(description = "扩展信息")
private String extJson;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.enums;
import lombok.Getter;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
public enum SysGroupEnum {
/** 测试 */
TEST("TEST");
private final String value;
SysGroupEnum(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import vip.xiaonuo.sys.modular.group.entity.SysGroup;
/**
* Mapper
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
public interface SysGroupMapper extends BaseMapper<SysGroup> {
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="vip.xiaonuo.sys.modular.group.mapper.SysGroupMapper">
</mapper>

View File

@ -0,0 +1,45 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
@Setter
public class SysGroupAddParam {
/** 名称 */
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "name不能为空")
private String name;
/** 备注 */
@Schema(description = "备注")
private String remark;
/** 排序码 */
@Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "sortCode不能为空")
private Integer sortCode;
}

View File

@ -0,0 +1,50 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
@Setter
public class SysGroupEditParam {
/** 主键 */
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "id不能为空")
private String id;
/** 名称 */
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "name不能为空")
private String name;
/** 备注 */
@Schema(description = "备注")
private String remark;
/** 排序码 */
@Schema(description = "排序码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "sortCode不能为空")
private Integer sortCode;
}

View File

@ -0,0 +1,42 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
@Setter
public class SysGroupGrantUserParam {
/** 用户组id */
@Schema(description = "用户组id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "id不能为空")
private String id;
/** 授权用户信息 */
@Schema(description = "授权用户信息", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "grantInfoList不能为空")
private List<String> grantInfoList;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
/**
* Id
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
@Setter
public class SysGroupIdParam {
/** 主键 */
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "id不能为空")
private String id;
}

View File

@ -0,0 +1,53 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
@Setter
public class SysGroupPageParam {
/** 当前页 */
@Schema(description = "当前页码")
private Integer current;
/** 每页条数 */
@Schema(description = "每页条数")
private Integer size;
/** 排序字段 */
@Schema(description = "排序字段字段驼峰名称userName")
private String sortField;
/** 排序方式 */
@Schema(description = "排序方式升序ASCEND降序DESCEND")
private String sortOrder;
/** 关键词 */
@Schema(description = "关键词")
private String searchKey;
/** 名称 */
@Schema(description = "名称")
private String name;
}

View File

@ -0,0 +1,44 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Getter
@Setter
public class SysGroupSelectorUserParam {
/** 当前页 */
@Schema(description = "当前页码")
private Integer current;
/** 每页条数 */
@Schema(description = "每页条数")
private Integer size;
/** 组织id */
@Schema(description = "组织id")
private String orgId;
/** 姓名关键词 */
@Schema(description = "姓名关键词")
private String searchKey;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.provider;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import vip.xiaonuo.sys.api.SysGroupApi;
import vip.xiaonuo.sys.modular.group.param.SysGroupGrantUserParam;
import vip.xiaonuo.sys.modular.group.param.SysGroupIdParam;
import vip.xiaonuo.sys.modular.group.service.SysGroupService;
import java.util.List;
/**
* API
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Service
public class SysGroupApiProvider implements SysGroupApi {
@Resource
private SysGroupService sysGroupService;
@Override
public List<String> ownUser(String groupId) {
SysGroupIdParam sysGroupIdParam = new SysGroupIdParam();
sysGroupIdParam.setId(groupId);
return sysGroupService.ownUser(sysGroupIdParam);
}
@Override
public void grantUser(String groupId, List<String> userIdList) {
SysGroupGrantUserParam sysGroupGrantUserParam = new SysGroupGrantUserParam();
sysGroupGrantUserParam.setId(groupId);
sysGroupGrantUserParam.setGrantInfoList(userIdList);
sysGroupService.grantUser(sysGroupGrantUserParam);
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.service;
import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import vip.xiaonuo.sys.modular.group.entity.SysGroup;
import vip.xiaonuo.sys.modular.group.param.*;
import vip.xiaonuo.sys.modular.user.entity.SysUser;
import java.util.List;
/**
* Service
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
public interface SysGroupService extends IService<SysGroup> {
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
Page<SysGroup> page(SysGroupPageParam sysGroupPageParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
void add(SysGroupAddParam sysGroupAddParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
void edit(SysGroupEditParam sysGroupEditParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
void delete(List<SysGroupIdParam> sysGroupIdParamList);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
SysGroup detail(SysGroupIdParam sysGroupIdParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
SysGroup queryEntity(String id);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
List<String> ownUser(SysGroupIdParam sysGroupIdParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
List<Tree<String>> orgTreeSelector();
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
Page<SysUser> userSelector(SysGroupSelectorUserParam sysGroupSelectorUserParam);
/**
*
*
* @author yubaoshan
* @date 2024/12/21 01:25
*/
void grantUser(SysGroupGrantUserParam sysGroupGrantUserParam);
}

View File

@ -0,0 +1,174 @@
/*
* Copyright [2022] [https://www.xiaonuo.vip]
*
* SnowyAPACHE LICENSE 2.0使
*
* 1.LICENSE
* 2.Snowy
* 3.使使
* 4. https://www.xiaonuo.vip
* 5.xiaonuobase@qq.com
* 6.Snowy https://www.xiaonuo.vip
*/
package vip.xiaonuo.sys.modular.group.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.sys.modular.group.entity.SysGroup;
import vip.xiaonuo.sys.modular.group.mapper.SysGroupMapper;
import vip.xiaonuo.sys.modular.group.param.*;
import vip.xiaonuo.sys.modular.group.service.SysGroupService;
import vip.xiaonuo.sys.modular.org.entity.SysOrg;
import vip.xiaonuo.sys.modular.org.service.SysOrgService;
import vip.xiaonuo.sys.modular.relation.entity.SysRelation;
import vip.xiaonuo.sys.modular.relation.enums.SysRelationCategoryEnum;
import vip.xiaonuo.sys.modular.relation.service.SysRelationService;
import vip.xiaonuo.sys.modular.user.entity.SysUser;
import vip.xiaonuo.sys.modular.user.service.SysUserService;
import java.util.List;
import java.util.stream.Collectors;
/**
* Service
*
* @author yubaoshan
* @date 2024/12/21 01:25
**/
@Service
public class SysGroupServiceImpl extends ServiceImpl<SysGroupMapper, SysGroup> implements SysGroupService {
@Resource
private SysRelationService sysRelationService;
@Resource
private SysUserService sysUserService;
@Resource
private SysOrgService sysOrgService;
@Override
public Page<SysGroup> page(SysGroupPageParam sysGroupPageParam) {
QueryWrapper<SysGroup> queryWrapper = new QueryWrapper<SysGroup>().checkSqlInjection();
if(ObjectUtil.isNotEmpty(sysGroupPageParam.getName())) {
queryWrapper.lambda().like(SysGroup::getName, sysGroupPageParam.getName());
}
if(ObjectUtil.isAllNotEmpty(sysGroupPageParam.getSortField(), sysGroupPageParam.getSortOrder())) {
CommonSortOrderEnum.validate(sysGroupPageParam.getSortOrder());
queryWrapper.orderBy(true, sysGroupPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
StrUtil.toUnderlineCase(sysGroupPageParam.getSortField()));
} else {
queryWrapper.lambda().orderByAsc(SysGroup::getSortCode);
}
return this.page(CommonPageRequest.defaultPage(), queryWrapper);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void add(SysGroupAddParam sysGroupAddParam) {
SysGroup sysGroup = BeanUtil.toBean(sysGroupAddParam, SysGroup.class);
this.save(sysGroup);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void edit(SysGroupEditParam sysGroupEditParam) {
SysGroup sysGroup = this.queryEntity(sysGroupEditParam.getId());
BeanUtil.copyProperties(sysGroupEditParam, sysGroup);
this.updateById(sysGroup);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void delete(List<SysGroupIdParam> sysGroupIdParamList) {
// 执行删除
this.removeByIds(CollStreamUtil.toList(sysGroupIdParamList, SysGroupIdParam::getId));
}
@Override
public SysGroup detail(SysGroupIdParam sysGroupIdParam) {
return this.queryEntity(sysGroupIdParam.getId());
}
@Override
public SysGroup queryEntity(String id) {
SysGroup sysGroup = this.getById(id);
if(ObjectUtil.isEmpty(sysGroup)) {
throw new CommonException("用户组不存在id值为{}", id);
}
return sysGroup;
}
@Override
public List<String> ownUser(SysGroupIdParam sysGroupIdParam) {
return sysRelationService.getRelationObjectIdListByTargetIdAndCategory(sysGroupIdParam.getId(),
SysRelationCategoryEnum.SYS_USER_HAS_GROUP.getValue());
}
@Override
public List<Tree<String>> orgTreeSelector() {
List<SysOrg> sysOrgList = sysOrgService.getAllOrgList();
List<TreeNode<String>> treeNodeList = sysOrgList.stream().map(sysOrg ->
new TreeNode<>(sysOrg.getId(), sysOrg.getParentId(), sysOrg.getName(), sysOrg.getSortCode()))
.collect(Collectors.toList());
return TreeUtil.build(treeNodeList, "0");
}
@Override
public Page<SysUser> userSelector(SysGroupSelectorUserParam sysGroupSelectorUserParam) {
LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 只查询部分字段
lambdaQueryWrapper.select(SysUser::getId, SysUser::getAvatar, SysUser::getOrgId, SysUser::getPositionId, SysUser::getAccount,
SysUser::getName, SysUser::getSortCode, SysUser::getGender, SysUser::getEntryDate);
// 如果查询条件为空,则直接查询
if(ObjectUtil.isAllEmpty(sysGroupSelectorUserParam.getOrgId(), sysGroupSelectorUserParam.getSearchKey())) {
return sysUserService.getAllUserSelectorList();
} else {
if (ObjectUtil.isNotEmpty(sysGroupSelectorUserParam.getOrgId())) {
// 如果组织id不为空则查询该组织及其子极其子下的所有人
List<String> childOrgIdList = CollStreamUtil.toList(sysOrgService.getChildListById(sysOrgService
.getAllOrgList(), sysGroupSelectorUserParam.getOrgId(), true), SysOrg::getId);
if (ObjectUtil.isNotEmpty(childOrgIdList)) {
lambdaQueryWrapper.in(SysUser::getOrgId, childOrgIdList);
} else {
return new Page<>();
}
}
if (ObjectUtil.isNotEmpty(sysGroupSelectorUserParam.getSearchKey())) {
lambdaQueryWrapper.like(SysUser::getName, sysGroupSelectorUserParam.getSearchKey());
}
lambdaQueryWrapper.orderByAsc(SysUser::getSortCode);
return sysUserService.page(CommonPageRequest.defaultPage(), lambdaQueryWrapper);
}
}
@Override
public void grantUser(SysGroupGrantUserParam sysGroupGrantUserParam) {
String id = sysGroupGrantUserParam.getId();
List<String> grantInfoList = sysGroupGrantUserParam.getGrantInfoList();
sysRelationService.remove(new LambdaQueryWrapper<SysRelation>().eq(SysRelation::getTargetId, id)
.eq(SysRelation::getCategory, SysRelationCategoryEnum.SYS_USER_HAS_GROUP.getValue()));
sysRelationService.saveBatch(grantInfoList.stream().map(userId -> {
SysRelation sysRelation = new SysRelation();
sysRelation.setObjectId(userId);
sysRelation.setTargetId(id);
sysRelation.setCategory(SysRelationCategoryEnum.SYS_USER_HAS_GROUP.getValue());
return sysRelation;
}).collect(Collectors.toList()));
}
}

View File

@ -45,7 +45,10 @@ public enum SysRelationCategoryEnum {
SYS_ROLE_HAS_MOBILE_MENU("SYS_ROLE_HAS_MOBILE_MENU"),
/** 角色拥有权限 */
SYS_ROLE_HAS_PERMISSION("SYS_ROLE_HAS_PERMISSION");
SYS_ROLE_HAS_PERMISSION("SYS_ROLE_HAS_PERMISSION"),
/** 用户拥有用户组 */
SYS_USER_HAS_GROUP("SYS_USER_HAS_GROUP");
private final String value;

View File

@ -157,6 +157,7 @@ public class GlobalConfigure implements WebMvcConfigurer {
"/auth/third/page",
"/client/user/**",
"/sys/org/**",
"/sys/group/**",
"/sys/position/**",
"/sys/button/**",
"/sys/menu/**",

View File

@ -662,6 +662,28 @@ INSERT INTO `MOBILE_RESOURCE` VALUES ('1623696236267024386', '162338076520231321
INSERT INTO `MOBILE_RESOURCE` VALUES ('1623696292042878977', '1623380765202313218', '编辑人员', 'mobileBizUserEdit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
INSERT INTO `MOBILE_RESOURCE` VALUES ('1623696346547859458', '1623380765202313218', '删除人员', 'mobileBizUserDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-- ----------------------------
-- Table structure for SYS_GROUP
-- ----------------------------
DROP TABLE IF EXISTS `SYS_GROUP`;
CREATE TABLE `SYS_GROUP` (
`ID` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
`NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称',
`REMARK` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
`SORT_CODE` int(11) NULL DEFAULT NULL COMMENT '排序码',
`EXT_JSON` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '扩展信息',
`DELETE_FLAG` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '删除标志',
`CREATE_TIME` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`CREATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建用户',
`UPDATE_TIME` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
`UPDATE_USER` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修改用户',
PRIMARY KEY (`ID`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户组' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of SYS_GROUP
-- ----------------------------
-- ----------------------------
-- Table structure for SYS_ORG
-- ----------------------------
@ -889,6 +911,9 @@ INSERT INTO `SYS_RELATION` VALUES ('1813960110876631049', '1570687866138206208',
INSERT INTO `SYS_RELATION` VALUES ('1813960110876631050', '1570687866138206208', '/biz/notice/page', 'SYS_ROLE_HAS_PERMISSION', '{\"apiUrl\":\"/biz/notice/page\",\"scopeCategory\":\"SCOPE_ALL\",\"scopeDefineOrgIdList\":[]}');
INSERT INTO `SYS_RELATION` VALUES ('1813959903803842580', '1570687866138206208', '1813959658013433858', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1813959658013433858\",\"buttonInfo\":[]}');
INSERT INTO `SYS_RELATION` VALUES ('1871280434097565701', '1570687866138206208', '1870158678418993154', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1870158678418993154\",\"buttonInfo\":[\"1870158678481907713\",\"1870158678481907714\",\"1870158678481907715\",\"1870158678481907716\"]}');
INSERT INTO `SYS_RELATION` VALUES ('1871280434097565751', '1570687866138206208', '1871278073018986498', 'SYS_ROLE_HAS_RESOURCE', '{\"menuId\":\"1871278073018986498\",\"buttonInfo\":[\"1871278073086095361\",\"1871278073086095362\",\"1871278073086095363\",\"1871278073086095364\",\"1871280381043814402\"]}');
-- ----------------------------
-- Table structure for SYS_RESOURCE
-- ----------------------------
@ -1009,6 +1034,14 @@ INSERT INTO `SYS_RESOURCE` VALUES ('1811290937503387650', '1811290937444667393',
INSERT INTO `SYS_RESOURCE` VALUES ('1811328402989662210', '1811290937444667393', '更新状态', NULL, 'bizNoticerUpdateStatus', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
INSERT INTO `SYS_RESOURCE` VALUES ('1811330359695400961', '1811290937444667393', '通知公告详情', NULL, 'bizNoticeDetail', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 6, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
INSERT INTO `SYS_RESOURCE` VALUES ('1870158678418993154', '1548901111999770726', '用户组管理', 'groupIndex', 'd4KUq2ZnK7', 'MENU', '1548901111999770525', 'MENU', '/sys/group', 'sys/group/index', 'team-outlined', NULL, 'TRUE', 99, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
INSERT INTO `SYS_RESOURCE` VALUES ('1871278073018986498', '1548901111999773977', '用户组', 'bizGroupIndex', 'HQVofyRf7Z', 'MENU', '1548901111999773976', 'MENU', '/biz/group', 'biz/group/index', 'team-outlined', NULL, 'TRUE', 55, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
INSERT INTO `SYS_RESOURCE` VALUES ('1871278073086095361', '1871278073018986498', '新增用户组', NULL, 'bizGroupAdd', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
INSERT INTO `SYS_RESOURCE` VALUES ('1871278073086095362', '1871278073018986498', '编辑用户组', NULL, 'bizGroupEdit', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
INSERT INTO `SYS_RESOURCE` VALUES ('1871278073086095363', '1871278073018986498', '删除用户组', NULL, 'bizGroupDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
INSERT INTO `SYS_RESOURCE` VALUES ('1871278073086095364', '1871278073018986498', '批量删除', NULL, 'bizGroupBatchDelete', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 4, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
INSERT INTO `SYS_RESOURCE` VALUES ('1871280381043814402', '1871278073018986498', '授权用户', NULL, 'bizGroupGrantUser', 'BUTTON', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 5, NULL, 'NOT_DELETE', NULL, NULL, NULL, NULL);
-- ----------------------------
-- Table structure for SYS_ROLE
-- ----------------------------