iot-ui-vue/src/views/system/Menu/components/PermissChoose.vue

235 lines
6.9 KiB
Vue

<template>
<div class="permission-choose-container">
<a-input
v-model:value="searchValue"
style="width: 300px"
allowClear
placeholder="请输入权限名称"
@input="search.search"
:disabled="props.disabled"
/>
<div class="permission-table">
<a-row :gutter="24" class="table-head">
<a-col :span="props.firstWidth">权限名称</a-col
><a-col :span="24 - props.firstWidth">权限操作</a-col>
</a-row>
<div class="table-body" :style="{ 'max-height': props.maxHeight }">
<a-row
:gutter="24"
class="row"
v-for="rowItem in permission.list"
>
<a-col :span="props.firstWidth" class="item-name">
<a-checkbox
v-model:checked="rowItem.checkAll"
:indeterminate="rowItem.indeterminate"
@change="() => permission.selectAllOpions(rowItem)"
:disabled="props.disabled"
>
{{ rowItem.name }}
</a-checkbox>
</a-col>
<a-col :span="24 - props.firstWidth">
<a-checkbox-group
v-model:value="rowItem.checkedList"
:options="rowItem.options"
@change="((checkValue:string[])=>permission.selectOption(rowItem, checkValue))"
:disabled="props.disabled"
/>
</a-col>
</a-row>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { exportPermission_api } from '@/api/system/permission';
import { Form } from 'ant-design-vue';
Form.useInjectFormItemContext();
const props = defineProps<{
key: string;
value: any[];
firstWidth: number;
maxHeight: string;
disabled?: boolean;
}>();
const emits = defineEmits(['update:value']);
const searchValue = ref<string>('');
const search = reactive({
searchTimer: null as null | number,
search: () => {
if (search.searchTimer) {
clearTimeout(search.searchTimer);
}
search.searchTimer = setTimeout(() => {
nextTick(() => permission.getList());
search.searchTimer = null;
}, 1000);
},
});
const permission = reactive({
list: [] as permissionType[],
sourceList: [] as any[],
init: () => {
permission.getList();
watch(
() => props.key,
() => {
nextTick(() => {
permission.list = permission.makeList(
props.value,
permission.sourceList,
);
});
},
);
},
// 获取权限列表
getList: () => {
const params: paramsType = {
paging: false,
};
if (searchValue.value) {
params.terms = [
{ column: 'name$like', value: `%${searchValue.value}%` },
];
}
exportPermission_api(params).then((resp) => {
permission.sourceList = [...(resp.result as any[])];
permission.list = permission.makeList(
props.value,
resp.result as any[],
);
});
},
// 全选/取消全选
selectAllOpions: (row: permissionType) => {
row.indeterminate = false;
const newValue = props.value.filter(
(item) => item.permission !== row.id,
);
row = toRaw(row);
if (row.checkAll) {
row.checkedList = row.options.map((item) => item.value);
newValue.push({
permission: row.id,
actions: row.checkedList,
});
} else {
row.checkedList = [];
}
emits('update:value', newValue);
},
// 单选
selectOption: (row: permissionType, newValue: string[]) => {
const newProp = props.value.filter(
(item) => item.permission !== row.id,
);
if (newValue.length === row.options.length) {
row.checkAll = true;
row.indeterminate = false;
newProp.push({
permission: row.id,
actions: newValue,
});
} else if (newValue.length > 0) {
row.checkAll = false;
row.indeterminate = true;
newProp.push({
permission: row.id,
actions: newValue,
});
}
emits('update:value', newProp);
},
makeList: (checkedValue: any[], sourceList: any[]): permissionType[] => {
const result = sourceList.map((item) => {
const checked = checkedValue?.find(
(checkedItem) => checkedItem.permission === item.id,
);
const options = item.actions.map((actionItem: any) => ({
label: actionItem.name,
value: actionItem.action,
}));
return {
id: item.id,
name: item.name,
checkedList: (checked && checked.actions) || [],
checkAll:
(checked &&
item.actions &&
checked.actions.length === item.actions.length) ||
false,
indeterminate:
(checked &&
item.actions &&
checked.actions.length < item.actions.length) ||
false,
options,
};
}) as permissionType[];
return result;
},
});
permission.init();
type permissionType = {
id: string;
name: string;
checkedList: string[];
checkAll: boolean;
indeterminate: boolean;
options: any[];
};
type paramsType = {
paging: boolean;
terms?: object[];
};
</script>
<style lang="less" scoped>
.permission-choose-container {
.ant-input-affix-wrapper {
border-color: #d9d9d9 !important;
}
.permission-table {
margin-top: 12px;
font-size: 14px;
border: 1px solid #d9d9d9;
color: rgba(0, 0, 0, 0.85);
.table-head {
padding: 12px;
background-color: #d9d9d9;
margin: 0 !important;
}
.table-body {
overflow: auto;
.row {
margin: 0 !important;
border-bottom: 1px solid #d9d9d9;
> div {
padding: 8px 12px;
}
.item-name {
display: flex;
align-items: center;
border-right: 1px solid #d9d9d9;
}
}
}
}
}
</style>