数据权限

szh-new
sunzehua 2 months ago
parent 58a26e0570
commit 369a6809a7

@ -1,8 +1,22 @@
<template>
<BasicModal v-bind="$attrs" :use-wrapper="true" :title="getTitle" :width="670" @register="registerModal"
<BasicModal v-bind="$attrs" :use-wrapper="true" :title="getTitle" :width="900" @register="registerModal"
@ok="handleSave">
<!-- 费用模版表单 -->
<BasicForm @register="registerForm" @linkageForm="ChangeColumnView" />
<div style="font-weight: bold;font-size: 12px;">权限规则</div>
<div style="margin-bottom: 10px" >
<a-button type="link" @click="copy('{loginUser}')"><i class="icon-fuzhi3 iconfont"></i>本人</a-button>
<a-button type="link" @click="copy('{loginDept}')"><i class="icon-fuzhi3 iconfont"></i>本部门</a-button>
<a-button type="link" @click="copy('{loginOrg}')"><i class="icon-fuzhi3 iconfont"></i>本公司</a-button>
<a-select v-model:value="orgListValue" @change="handleCopySelect" size="small" mode="multiple" style="width: 250px">
<a-select-option v-for="(item, index) in orgList" :value="item.value" :key="index">{{ item.label
}}</a-select-option>
</a-select>
<a-select v-model:value="userListValue" @change="handleCopySelectUser" size="small" mode="multiple" style="width: 250px;margin-left: 20px">
<a-select-option v-for="(item, index) in userList" :value="item.value" :key="index">{{ item.label
}}</a-select-option>
</a-select>
</div>
<!-- 费用字段表格 -->
<columnView ref="RefcolumnView" title="" :IsApi="true" :schemas="ColumnViewschemas" v-show="columnViewType">
</columnView>
@ -29,6 +43,9 @@ import { BasicModal, useModalInner } from '/@/components/Modal'
import { BasicForm, useForm } from '/@/components/Form/index'
import { getDictOption } from '/@/utils/dictUtil'
import { getColumns, getClientPermissionList } from '/@/api/system/role'
import {
getOrgList,GetUserList
} from '/@/api/common'
import columnView from './columnView.vue'
//
// import { formSchema } from './columns'
@ -38,6 +55,8 @@ import { ApiEdit, ApiInfo } from './api'
import { useMessage } from '/@/hooks/web/useMessage'
import { getTablesByClient } from '/@/views/baseinfo/formcopy/api'
const columnViewData: any = ref([])
const orgList = ref([]) as any
const userList = ref([]) as any
onMounted(() => {
getTablesByClient().then(res => {
if (res.succeeded) {
@ -50,12 +69,28 @@ onMounted(() => {
})
}
})
getOrgList().then(res => {
orgList.value = res.data
})
GetUserList().then(res => {
userList.value = res.data
})
})
const userListValue = ref([])
const orgListValue = ref([])
const props = defineProps({
customerName: { type: String },
customerId: { type: String },
})
function copy(text) {
var cInput = document.createElement('input');
cInput.value = text;
document.body.appendChild(cInput);
cInput.select(); //
document.execCommand('copy');
document.body.removeChild(cInput);
createMessage.success('复制成功')
}
const formSchema = [
{
label: '主键Id',
@ -191,7 +226,7 @@ const formSchema = [
label: '可视/可操作',
component: 'Switch',
colProps: { span: 6 },
defaultValue: false,
defaultValue: 'visible',
componentProps: {
checkedChildren: '可视',
checkedValue: 'visible',
@ -206,10 +241,10 @@ const formSchema = [
colProps: { span: 6 },
defaultValue: 0,
componentProps: {
checkedChildren: '用',
checkedValue: 1,
unCheckedChildren: '用',
unCheckedValue: 0,
checkedChildren: '用',
checkedValue: 0,
unCheckedChildren: '用',
unCheckedValue: 1,
},
},
{
@ -223,6 +258,24 @@ const formSchema = [
},
]
function handleCopySelect(val) {
val = val.join(',')
var cInput = document.createElement('input');
cInput.value = val;
document.body.appendChild(cInput);
cInput.select(); //
document.execCommand('copy');
document.body.removeChild(cInput);
}
function handleCopySelectUser(val) {
val = val.join(',')
var cInput = document.createElement('input');
cInput.value = val;
document.body.appendChild(cInput);
cInput.select(); //
document.execCommand('copy');
document.body.removeChild(cInput);
}
// Emits
const emit = defineEmits(['success', 'register'])
const isUpdate = ref(true)
@ -259,6 +312,8 @@ const [registerModal, { setModalProps, closeModal, updateFormField }] = useModal
if (unref(isUpdate)) {
setModalProps({ confirmLoading: true })
rowId.value = data.record.id
orgListValue.value = []
userListValue.value = []
const res: API.DataResult = await ApiInfo({ id: unref(rowId) })
if (res.succeeded) {
setFieldsValue({
@ -270,7 +325,7 @@ const [registerModal, { setModalProps, closeModal, updateFormField }] = useModal
setTimeout(() => {
RefcolumnView.value.init(JSON.parse(res.data.dataRules))
}, 200);
detailId.value = res.data.id
}
} else {
@ -312,6 +367,9 @@ async function handleSave(exit) {
setModalProps({ confirmLoading: false, loading: false })
}
}
</script>
<style scoped lang="less">
/deep/ .ant-form-small {
margin-top: 0px !important;
}
</style>

@ -58,4 +58,11 @@ export function DeleteDetails(data: PageRequest) {
method: 'post',
data
})
}
export function BatchCopyDataRuleTemplate(data: PageRequest) {
return request<DataResult>({
url: '/mainApi/CodeDataRuleTemplate/BatchCopyDataRuleTemplate',
method: 'post',
data
})
}

@ -42,11 +42,12 @@ export const columns: BasicColumn[] = [
{
title: '排序号',
dataIndex: 'orderNo',
// width: 200,
width: 50,
},
{
title: '可视/可操作',
dataIndex: 'ruleType',
width: 120,
customRender: ({ text }) => {
if (text === 'visible') {
return '可视'

@ -17,7 +17,7 @@
<template #title>
<span>复制</span>
</template>
<a-button v-repeat type="link" @click="handleCreate">
<a-button v-repeat type="link" @click="handleCopy">
<img src="../../../assets/svg/infoclient/fuzhi.svg" class="SvgImg" />
</a-button>
</a-tooltip>
@ -26,12 +26,7 @@
<span>删除</span>
</template>
<span class="ds-action-svg-btn">
<a-popconfirm
title="确定删除当前选中数据?"
ok-text="是"
cancel-text="否"
@confirm="handleDelete"
>
<a-popconfirm title="确定删除当前选中数据?" ok-text="" cancel-text="" @confirm="handleDelete">
<a-button v-repeat type="link">
<img src="../../../assets/svg/infoclient/shanchu.svg" class="SvgImg" />
</a-button>
@ -57,15 +52,13 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
icon: 'clarity:note-edit-line',
tooltip: '编辑',
onClick: handleAudit.bind(null, record),
},
]"
/>
<TableAction :actions="[
{
icon: 'clarity:note-edit-line',
tooltip: '编辑',
onClick: handleAudit.bind(null, record),
},
]" />
</template>
</template>
</BasicTable>
@ -73,120 +66,139 @@
</div>
</template>
<script lang="ts" setup>
import { defineComponent, onMounted, ref } from 'vue'
import { BasicTable, useTable, TableAction, SorterResult } from '/@/components/Table'
import { ApiList, ApiDel } from './api'
import { useModal } from '/@/components/Modal'
import TenantAuditStepModal from './TenantAuditStepModal.vue'
import { columns, searchFormSchema } from './columns'
import { formatParams } from '/@/hooks/web/common'
import { useMessage } from '/@/hooks/web/useMessage'
const { notification } = useMessage()
const [registerModal, { openModal }] = useModal()
const [registerTable, { reload, getSelectRows, getForm, getPaginationRef }] = useTable({
title: '',
api: async (p) => {
const res: API.DataResult = await ApiList(p)
return new Promise((resolve) => {
resolve({ data: [...res.data], total: res.count })
})
},
beforeFetch: (p) => {
return formatParams(p)
},
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
isTreeTable: false,
pagination: true,
striped: true,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: true,
indexColumnProps: {
width: 60,
},
canResize: true,
resizeHeightOffset: 35,
immediate: true,
actionColumn: {
width: 80,
title: '操作',
dataIndex: 'action',
fixed: 'right',
},
// rowSelection: { type: 'checkbox' },
// clickToRowSelect: false,
})
function handleCreate() {
openModal(true, {
isUpdate: false,
})
}
function handleAudit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
import { defineComponent, onMounted, ref } from 'vue'
import { BasicTable, useTable, TableAction, SorterResult } from '/@/components/Table'
import { ApiList, ApiDel, BatchCopyDataRuleTemplate } from './api'
import { useModal } from '/@/components/Modal'
import TenantAuditStepModal from './TenantAuditStepModal.vue'
import { columns, searchFormSchema } from './columns'
import { formatParams } from '/@/hooks/web/common'
import { useMessage } from '/@/hooks/web/useMessage'
const { notification } = useMessage()
const [registerModal, { openModal }] = useModal()
const [registerTable, { reload, getSelectRows, getForm, getPaginationRef }] = useTable({
title: '',
api: async (p) => {
const res: API.DataResult = await ApiList(p)
return new Promise((resolve) => {
resolve({ data: [...res.data], total: res.count })
})
},
beforeFetch: (p) => {
return formatParams(p)
},
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
isTreeTable: false,
pagination: true,
striped: true,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: true,
indexColumnProps: {
width: 60,
},
canResize: true,
resizeHeightOffset: 35,
immediate: true,
actionColumn: {
width: 80,
title: '操作',
dataIndex: 'action',
fixed: 'right',
},
// rowSelection: { type: 'checkbox' },
// clickToRowSelect: false,
})
function handleCreate() {
openModal(true, {
isUpdate: false,
})
}
function handleAudit(record: Recordable) {
openModal(true, {
record,
isUpdate: true,
})
}
function handleCopy() {
let ids = []
ids = getSelectRows().map((item) => {
return item.id
})
if (ids.length == 0) {
notification.error('请选择要复制的数据')
return false
}
//
async function handleDelete(record: Recordable) {
const select = getSelectRows()
let ApiData: any = {
ids: [],
}
if (select.length === 0) {
notification.warning({ message: '请至少选择一条数据', duration: 3 })
return false
} else {
ApiData.ids = select.map((item) => {
return item.id
})
}
ApiDel(ApiData).then((res) => {
console.log(res)
notification.success({ message: res.message, duration: 3 })
BatchCopyDataRuleTemplate({ids:ids}).then(res=>{
if(res.succeeded){
notification.success('复制成功')
reload()
}
})
}
//
async function handleDelete(record: Recordable) {
const select = getSelectRows()
let ApiData: any = {
ids: [],
}
if (select.length === 0) {
notification.warning({ message: '请至少选择一条数据', duration: 3 })
return false
} else {
ApiData.ids = select.map((item) => {
return item.id
})
// const res: API.DataResult = await ApiDel({
// id: '',
// ids: [record.id],
// })
// if (res.succeeded) {
// notification.success({ message: res.message, duration: 3 })
// reload()
// } else {
// notification.error({ message: res.message, duration: 3 })
// }
}
function handleSuccess() {
ApiDel(ApiData).then((res) => {
console.log(res)
notification.success({ message: res.message, duration: 3 })
reload()
}
})
// const res: API.DataResult = await ApiDel({
// id: '',
// ids: [record.id],
// })
// if (res.succeeded) {
// notification.success({ message: res.message, duration: 3 })
// reload()
// } else {
// notification.error({ message: res.message, duration: 3 })
// }
}
function handleSuccess() {
reload()
}
</script>
<style lang="less" scoped>
.ds-table-detail {
margin-top: -16px;
.title {
font-size: 12px;
font-weight: 700;
letter-spacing: 1px;
line-height: 15.84px;
color: rgba(51, 56, 61, 1);
text-align: left;
}
}
.SvgImg {
width: 16px;
.ds-table-detail {
margin-top: -16px;
.title {
font-size: 12px;
font-weight: 700;
letter-spacing: 1px;
line-height: 15.84px;
color: rgba(51, 56, 61, 1);
text-align: left;
}
.tableTitleBox {
.ant-btn-link {
border-radius: 2px;
color: #000;
font-size: 16px;
}
}
.SvgImg {
width: 16px;
}
.tableTitleBox {
.ant-btn-link {
border-radius: 2px;
color: #000;
font-size: 16px;
}
}
</style>

@ -24,4 +24,46 @@ export function GetCodeDataRuleList(params) {
method: 'post',
data: params
})
}
}
export function AssignDataRuleScope(params) {
return request<DataResult>({
url: '/mainApi/CodeDataRule/AssignDataRuleScope',
method: 'post',
data: params
})
}
export function GetDataRuleTemplateSelectList(params) {
return request<DataResult>({
url: '/mainApi/CodeDataRuleTemplate/GetDataRuleTemplateSelectList',
method: 'post',
params: params
})
}
export function CopyDataRuleScope(params) {
return request<DataResult>({
url: '/mainApi/CodeDataRule/CopyDataRuleScope',
method: 'post',
data: params
})
}
export function UserVisibleDataRuleScopeApply(params) {
return request<DataResult>({
url: '/mainApi/CodeDataRule/UserVisibleDataRuleScopeApply',
method: 'post',
data: params
})
}
export function UserOperateDataRuleScopeApply(params) {
return request<DataResult>({
url: '/mainApi/CodeDataRule/UserOperateDataRuleScopeApply',
method: 'post',
data: params
})
}

@ -1,22 +1,12 @@
<template>
<div class="main">
<div class="top">
<a-tooltip placement="top" :mouseEnterDelay="0.5">
<template #title>
<span>新建</span>
</template>
<span class="ds-action-svg-btn">
<a-button @click="GoDetailed(false)" v-repeat type="link">
<img src="../../../assets/svg/infoclient/baocun.svg" class="SvgImg" />
</a-button>
</span>
</a-tooltip>
<a-button>复制设置并应用</a-button>
<a-button type="link" @click="openRule"><i class="icon-fuzhi3 iconfont"></i>复制设置并应用</a-button>
</div>
<div class="tree-box">
<div class="tree-item">
<div class="tree-item border-left">
<div class="title">用户</div>
<BasicTree ref="treeRef" check-strictly :tree-data="treeData" @select="handleSelect">
<BasicTree ref="treeRef" check-strictly :treeData="treeData" @select="handleSelect">
<template #title="custom">
<span>{{ custom.node.title }}</span>
</template>
@ -24,13 +14,50 @@
</div>
<div class="tree-item">
<div class="title">用户权限配置</div>
<BasicTree ref="menuTreeRef" check-strictly :tree-data="menuTree" @select="handleSelectMenu">
<template #title="custom">
<span>{{ custom.node.name }}</span>
<a-spin :spinning="menuLoad">
<BasicTree ref="menuTreeRef" check-strictly :treeData="menuTree" @select="handleSelectMenu">
<template #title="custom">
<span>{{ custom.node.name }}</span>
</template>
</BasicTree>
</a-spin>
</div>
<div class="table-item">
<BasicTable class="ds-table-detail" @register="registerTable">
<template #tableTitle>
<span style="font-size: 12px;font-weight: bold;color: black">数据权限列表</span>
<a-button type="link" @click="setLook(1)"><i class="icon-yulan1 iconfont"></i>应用可视范围</a-button>
<a-button type="link" @click="setLook(2)"><i class="icon-shichuang-duoge iconfont"></i>应用操作范围到当前页</a-button>
</template>
</BasicTree>
<template v-slot:bodyCell="{ column, record }">
<template v-if="column.key === 'visibleRuleScopeName'">
<a-select @change="handleChangeLook($event, record)" v-model:value="record.visibleTemplateId" size="small"
style="width: 100%">
<a-select-option v-for="(item, index) in lookSelect" :key="index" :value="item.id">{{ item.ruleScopeName
}}</a-select-option>
</a-select>
</template>
<template v-if="column.key === 'operateRuleScopeName'">
<a-select @change="handleChangeLook($event, record)" v-model:value="record.operateTemplateId" size="small"
style="width: 100%">
<a-select-option v-for="(item, index) in actionSelect" :key="index" :value="item.id">{{
item.ruleScopeName }}</a-select-option>
</a-select>
</template>
</template>
</BasicTable>
</div>
</div>
<a-modal @ok="handleCopy" width="800px" @cancel="openFlag = false" :visible="openFlag" title="选择用户复制">
<a-spin :spinning="copyLoad" >
<BasicTree key="value" v-model:checkedKeys="checkedKeys" checkable check-strictly :treeData="treeDataCopy">
<template #title="custom">
<span>{{ custom.node.title }}</span>
</template>
</BasicTree>
</a-spin>
</a-modal>
</div>
</template>
<script lang="ts" setup>
@ -38,53 +65,231 @@ import { defineComponent, onMounted, ref } from 'vue'
import { BasicTable, useTable, TableAction } from '/@/components/Table'
import { getDataRuleList } from '/@/api/system/datarule'
import { useModal } from '/@/components/Modal'
import { GetOrgUserTree, GetClientUserPermissions,GetCodeDataRuleList } from './api'
import {
GetOrgUserTree, GetClientUserPermissions, GetCodeDataRuleList, UserVisibleDataRuleScopeApply,
GetDataRuleTemplateSelectList, AssignDataRuleScope, CopyDataRuleScope, UserOperateDataRuleScopeApply
} from './api'
import { BasicTree } from '/@/components/Tree/index'
import { useMessage } from '../../../hooks/web/useMessage'
const { createMessage } = useMessage()
// import { columns, searchFormSchema } from './columns'
const treeData = ref([])
const treeDataCopy = ref([])
const menuTree = ref([])
const openFlag = ref(false)
onMounted(() => {
GetOrgUserTree().then(res => {
treeData.value = res.data
treeDataCopy.value = JSON.parse(JSON.stringify(res.data))
treeData.value.forEach(item => {
processNode(item);
});
treeDataCopy.value.forEach(item => {
item.disabled = true
processNodeCheck(item);
});
})
setProps({
rowSelection: {
onChange: onSelectChange
}
})
})
const menuLoad = ref(false)
const userId = ref('')
const copyLoad = ref(false)
function onSelectChange() {
}
const checkedKeys = ref([]) as any
function handleCopy() {
if (!checkedKeys.value.checked || checkedKeys.value.checked.length == 0) {
createMessage.warning('请选择要复制的用户')
return false
}
if (!userId.value) {
createMessage.warning('请选择要被复制的用户')
return false
}
const data = {
userId: userId.value,
copyUserIds: checkedKeys.value.checked
}
copyLoad.value = true
CopyDataRuleScope(data).then(res => {
if(res.succeeded){
createMessage.success('复制成功')
}
copyLoad.value = false
}).catch(err => {
copyLoad.value = false
})
}
function setLook(type) {
if (!userId.value) {
createMessage.warning('请选择用户')
return false
}
if (getSelectRows().length == 0) {
createMessage.warning('请选择要应用的数据')
return false
}
if (getSelectRows().length > 1) {
createMessage.warning('只能选择一条')
return false
}
const data = {
userId: userId.value,
ruleId: getSelectRows()[0].id
}
setLoading(true)
if (type == 1) {
UserVisibleDataRuleScopeApply(data).then(res => {
if (res.succeeded) {
createMessage.success('应用成功')
}
setLoading(false)
}).catch(err => {
setLoading(false)
})
} else {
UserOperateDataRuleScopeApply(data).then(res => {
if (res.succeeded) {
createMessage.success('应用成功')
}
setLoading(false)
}).catch(err => {
setLoading(false)
})
}
}
function handleSelect(selectedKeys: any, info: any) {
if (info.node.id) {
userId.value = info.node.value
menuLoad.value = true
GetClientUserPermissions({ id: info.node.value }).then(res => {
menuTree.value = res.data
menuLoad.value = false
}).catch(err => {
menuLoad.value = false
})
}
}
function handleSelectMenu(selectedKeys: any, info: any){
console.log(info)
if(info.node.children==null || info.node.children.length==0){
const lookSelect = ref([]) as any
const actionSelect = ref([]) as any
function handleSelectMenu(selectedKeys: any, info: any) {
if (info.node.children == null || info.node.children.length == 0) {
const data = {
permissionId: info.node.id,
id:userId.value
permissionId: info.node.parentId,
userId: userId.value
}
GetCodeDataRuleList(data).then(res=>{
setLoading(true)
GetCodeDataRuleList(data).then(res => {
if (res.succeeded) {
setTableData(res.data)
}
setLoading(false)
}).catch(err => {
setLoading(false)
})
GetDataRuleTemplateSelectList({ id: info.node.parentId, ruleType: 'visible' }).then(res => {
lookSelect.value = res.data
})
GetDataRuleTemplateSelectList({ id: info.node.parentId, ruleType: 'operate' }).then(res => {
actionSelect.value = res.data
})
}
}
function openRule() {
openFlag.value = true
}
const columns = [
{ dataIndex: 'templateName', width: 100, title: '权限模板类型' },
{ dataIndex: 'description', width: 100, title: '权限描述' },
{ dataIndex: 'note', width: 100, title: '备注' },
{ dataIndex: 'visibleRuleScopeName', width: 100, title: '可视范围' },
{ dataIndex: 'operateRuleScopeName', width: 100, title: '操作范围' },
]
const ruleList = ref([])
const [registerTable, { reload, setLoading, setTableData, getSelectRows, setProps }] = useTable({
immediate: false,
columns,
isTreeTable: false,
pagination: true,
striped: true,
useSearchForm: false,
bordered: true,
showIndexColumn: false,
canResize: true,
resizeHeightOffset: 35,
})
function handleChangeLook(val, row) {
const data = {} as any
lookSelect.value.forEach(item => {
if (item.id == val) {
data.templateId = item.id
data.ruleType = item.ruleType
data.ruleScope = item.ruleScope
data.ruleScopeName = item.ruleScopeName
}
})
data.id = row.id
setLoading(true)
AssignDataRuleScope(data).then(res => {
if (res.succeeded) {
createMessage.success('更新成功')
}
setLoading(false)
})
}
function processNodeCheck(node) {
// children userList
if (node.children && node.children.length === 0 && node.userList) {
node.children = node.userList.map(user => {
// title disabled
return {
...user,
title: user.userName,
disabled: false,
value: user.id,
key: user.id
};
});
} else {
// disabled true
if (node.children) {
node.children = node.children.map(child => {
return {
...child,
key: child.id,
disabled: true
};
});
}
}
//
if (node.children) {
node.children.forEach(child => {
processNodeCheck(child);
});
}
}
function processNode(node) {
// children userList
if (node.children && node.children.length === 0 && node.userList) {
node.children = node.userList.map(user => {
// title
return {
...user,
title: user.userName,
value: user.id
};
});
}
node.children = node.userList.map(user => {
// title
return {
...user,
title: user.userName,
value: user.id
};
});
}
//
if (node.children) {
@ -97,12 +302,12 @@ function processNode(node) {
</script>
<style lang="less" scoped>
.main {
height: 100vh;
height: 80vh;
}
.top {
background-color: rgba(245, 249, 252, 1);
padding: 10px;
padding: 8px 10px;
}
.SvgImg {
@ -118,6 +323,7 @@ function processNode(node) {
.tree-item {
width: 20%;
padding: 0 15px;
.title {
font-size: 12px;
@ -127,8 +333,20 @@ function processNode(node) {
}
}
.border-left {
border-right: 1px solid #ebebeb;
}
.table-item {
width: 50%;
}
/deep/ .ant-tree-node-selected {
color: #257afa;
background-color: #f5f9fc !important;
}
/deep/ .vben-basic-table .ant-table-wrapper .ant-table.ant-table-bordered .ant-table-title {
padding-top: 0px !important;
}
</style>

Loading…
Cancel
Save