Files
geg-gas-web/src/views/system/user/components/RoleModal.vue
2025-10-21 18:04:02 +08:00

149 lines
4.6 KiB
Vue

<template>
<BasicModal v-bind="$attrs" @register="registerModal" :width="800" title="新增角色" :fixedHeight="true" @ok="handleSubmit">
<a-tabs v-model:activeKey="activeKey" @change="handleTabChange">
<a-tab-pane key="1" tab="全部">
<BasicTable @register="registerTableAll" />
</a-tab-pane>
<a-tab-pane key="2" tab="已选" force-render>
<BasicTable @register="registerTableSelected" />
</a-tab-pane>
<template #rightExtra>
<div class="left-extra">
<a-input v-model:value="searchText" placeholder="请输入查询关键字" @keypress.enter="handleSearch">
<template #prefix>
<SearchOutlined style="color: #ccc" />
</template>
</a-input>
<span class="left-text">已选中{{ num }}</span>
</div>
<a-button type="primary" danger :icon="h(DeleteOutlined)" @click="handleClear"> 清空 </a-button>
</template>
</a-tabs>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, h } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
import { getRolePageList } from '/@/api/system/role';
import { useI18n } from '/@/hooks/web/useI18n';
import { DeleteOutlined, SearchOutlined } from '@ant-design/icons-vue';
import { cloneDeep } from 'lodash-es';
const { t } = useI18n();
const columns: BasicColumn[] = [
{
title: t('角色名称'),
dataIndex: 'name',
align: 'center'
},
{
title: t('角色编码'),
dataIndex: 'code',
align: 'center'
}
];
const activeKey = ref('1');
const selectedList = ref<any[]>([]);
const num = ref(0);
const searchText = ref('');
const emits = defineEmits(['success']);
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
setModalProps({ confirmLoading: false });
setSelectedRowKeys1(data.roles?.map((x) => x.id) || []);
selectedList.value = cloneDeep(data.roles);
setTableData(selectedList.value);
reload();
});
const [registerTableAll, { getSelectRows, setSelectedRowKeys: setSelectedRowKeys1, getSelectRowKeys: getSelectRowKeys1, reload }] = useTable({
api: getRolePageList,
rowKey: 'id',
columns,
beforeFetch: (params) => {
return { ...params, name: searchText.value };
},
rowSelection: {
type: 'checkbox',
onChange: (val) => {
num.value = val.length;
}
},
striped: false
});
const [registerTableSelected, { setTableData, setSelectedRowKeys: setSelectedRowKeys2, getSelectRowKeys: getSelectRowKeys2 }] = useTable({
dataSource: selectedList.value,
rowKey: 'id',
columns,
rowSelection: {
type: 'checkbox',
onChange: (val) => {
num.value = val.length;
}
},
striped: false
});
const handleTabChange = (key) => {
if (key === '2') {
setSelectedRowKeys2(cloneDeep(getSelectRowKeys1()));
selectedList.value = cloneDeep(getSelectRows());
setTableData(selectedList.value);
} else {
setSelectedRowKeys1(getSelectRowKeys2());
}
};
const handleSearch = () => {
searchText.value;
reload();
};
const handleClear = () => {
setSelectedRowKeys1([]);
};
const handleSubmit = () => {
emits('success', getSelectRows());
closeModal();
};
</script>
<style lang="less" scoped>
:deep(.vben-basic-table .ant-table-wrapper) {
height: auto;
}
:deep(.ant-tabs-nav-wrap) {
flex: none !important;
}
:deep(.ant-tabs-extra-content) {
display: flex;
align-items: center;
justify-content: space-between;
width: 80%;
margin-left: 60px;
.left-extra {
display: flex;
align-items: center;
.left-text {
width: 90px;
margin-left: 10px;
color: #5e95ff;
}
}
}
:deep(.ant-input-affix-wrapper) {
border-radius: 10px;
background: #f8f8f8;
border: none;
}
:deep(.ant-input) {
background: #f8f8f8;
}
</style>