mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-02-03 00:55:33 +08:00
前端和后端源码,合并到一个git仓库中,方便用户下载,避免前后端不匹配的问题
This commit is contained in:
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<Description @register="registerDesc" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, inject, onMounted, watch } from 'vue';
|
||||
import { queryIdTree } from '../depart.user.api';
|
||||
import { useBaseInfoForm } from '../depart.user.data';
|
||||
import { Description, useDescription } from '/@/components/Description/index';
|
||||
|
||||
const prefixCls = inject('prefixCls');
|
||||
const props = defineProps({
|
||||
data: { require: true, type: Object },
|
||||
});
|
||||
const treeData = ref([]);
|
||||
const { descItems } = useBaseInfoForm(treeData);
|
||||
|
||||
const [registerDesc, { setDescProps }] = useDescription({
|
||||
data: props.data,
|
||||
schema: descItems,
|
||||
column: 1,
|
||||
labelStyle: {
|
||||
width: '180px',
|
||||
},
|
||||
});
|
||||
|
||||
function setData(data) {
|
||||
setDescProps({ data });
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
watch(
|
||||
() => props.data,
|
||||
() => setData(props.data),
|
||||
{ immediate: true }
|
||||
);
|
||||
});
|
||||
// 动态查询 parentId 组件的 treeData
|
||||
queryIdTree().then((data) => (treeData.value = data));
|
||||
</script>
|
||||
@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<BasicDrawer
|
||||
title="部门角色权限配置"
|
||||
:width="650"
|
||||
:loading="loading"
|
||||
showFooter
|
||||
okText="保存并关闭"
|
||||
@ok="onSubmit(true)"
|
||||
@close="onClose"
|
||||
@register="registerDrawer"
|
||||
>
|
||||
<div>
|
||||
<a-spin :spinning="loading">
|
||||
<template v-if="treeData.length > 0">
|
||||
<BasicTree
|
||||
title="所拥有的部门权限"
|
||||
toolbar
|
||||
checkable
|
||||
:treeData="treeData"
|
||||
:checkedKeys="checkedKeys"
|
||||
:selectedKeys="selectedKeys"
|
||||
:expandedKeys="expandedKeys"
|
||||
:checkStrictly="checkStrictly"
|
||||
:clickRowToExpand="false"
|
||||
@check="onCheck"
|
||||
@expand="onExpand"
|
||||
@select="onSelect"
|
||||
>
|
||||
<template #title="{ slotTitle, ruleFlag }">
|
||||
<span>{{ slotTitle }}</span>
|
||||
<Icon v-if="ruleFlag" icon="ant-design:align-left-outlined" style="margin-left: 5px; color: red" />
|
||||
</template>
|
||||
</BasicTree>
|
||||
</template>
|
||||
<a-empty v-else description="无可配置部门权限" />
|
||||
</a-spin>
|
||||
</div>
|
||||
|
||||
<template #centerFooter>
|
||||
<a-button type="primary" :loading="loading" ghost @click="onSubmit(false)">仅保存</a-button>
|
||||
</template>
|
||||
</BasicDrawer>
|
||||
<DepartRoleDataRuleDrawer @register="registerDataRuleDrawer" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { BasicTree } from '/@/components/Tree/index';
|
||||
import { BasicDrawer, useDrawer, useDrawerInner } from '/@/components/Drawer';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
import DepartRoleDataRuleDrawer from './DepartRoleDataRuleDrawer.vue';
|
||||
import { queryTreeListForDeptRole, queryDeptRolePermission, saveDeptRolePermission } from '../depart.user.api';
|
||||
import { translateTitle } from "@/utils/common/compUtils";
|
||||
|
||||
defineEmits(['register']);
|
||||
const { createMessage } = useMessage();
|
||||
const loading = ref(false);
|
||||
const departId = ref('');
|
||||
const roleId = ref('');
|
||||
const treeData = ref<Array<any>>([]);
|
||||
const checkedKeys = ref<Array<any>>([]);
|
||||
const lastCheckedKeys = ref<Array<any>>([]);
|
||||
const expandedKeys = ref<Array<any>>([]);
|
||||
const selectedKeys = ref<Array<any>>([]);
|
||||
const allTreeKeys = ref<Array<any>>([]);
|
||||
const checkStrictly = ref(true);
|
||||
|
||||
// 注册抽屉组件
|
||||
const [registerDrawer, { closeDrawer }] = useDrawerInner((data) => {
|
||||
roleId.value = data.record.id;
|
||||
departId.value = data.record.departId;
|
||||
loadData();
|
||||
});
|
||||
// 注册数据规则授权弹窗抽屉
|
||||
const [registerDataRuleDrawer, dataRuleDrawer] = useDrawer();
|
||||
|
||||
async function loadData() {
|
||||
try {
|
||||
loading.value = true;
|
||||
// 用户角色授权功能,查询菜单权限树
|
||||
const { ids, treeList } = await queryTreeListForDeptRole({ departId: departId.value });
|
||||
if (ids.length > 0) {
|
||||
allTreeKeys.value = ids;
|
||||
expandedKeys.value = ids;
|
||||
//update-begin---author:wangshuai---date:2024-04-08---for:【issues/1169】我的部门功能中的【部门权限】中未翻译 t('') 多语言---
|
||||
treeData.value = translateTitle(treeList);
|
||||
//update-end---author:wangshuai---date:2024-04-08---for:【issues/1169】我的部门功能中的【部门权限】中未翻译 t('') 多语言---
|
||||
// 查询角色授权
|
||||
checkedKeys.value = await queryDeptRolePermission({ roleId: roleId.value });
|
||||
lastCheckedKeys.value = [checkedKeys.value];
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 重置页面
|
||||
function reset() {
|
||||
treeData.value = [];
|
||||
expandedKeys.value = [];
|
||||
checkedKeys.value = [];
|
||||
lastCheckedKeys.value = [];
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
// tree勾选复选框事件
|
||||
function onCheck(event) {
|
||||
if (checkStrictly.value) {
|
||||
checkedKeys.value = event.checked;
|
||||
} else {
|
||||
checkedKeys.value = event;
|
||||
}
|
||||
}
|
||||
|
||||
// tree展开事件
|
||||
function onExpand($expandedKeys) {
|
||||
expandedKeys.value = $expandedKeys;
|
||||
}
|
||||
|
||||
// tree选中事件
|
||||
function onSelect($selectedKeys, { selectedNodes }) {
|
||||
if (selectedNodes[0]?.ruleFlag) {
|
||||
let functionId = $selectedKeys[0];
|
||||
dataRuleDrawer.openDrawer(true, { roleId, departId, functionId });
|
||||
}
|
||||
selectedKeys.value = [];
|
||||
}
|
||||
|
||||
function doClose() {
|
||||
reset();
|
||||
closeDrawer();
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
reset();
|
||||
}
|
||||
|
||||
async function onSubmit(exit) {
|
||||
try {
|
||||
loading.value = true;
|
||||
let params = {
|
||||
roleId: roleId.value,
|
||||
permissionIds: checkedKeys.value.join(','),
|
||||
lastpermissionIds: lastCheckedKeys.value.join(','),
|
||||
};
|
||||
await saveDeptRolePermission(params);
|
||||
if (exit) {
|
||||
doClose();
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
if (!exit) {
|
||||
loadData();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<BasicDrawer title="数据规则/按钮权限配置" :width="365" @close="onClose" @register="registerDrawer">
|
||||
<a-spin :spinning="loading">
|
||||
<a-tabs defaultActiveKey="1">
|
||||
<a-tab-pane tab="数据规则" key="1">
|
||||
<a-checkbox-group v-model:value="dataRuleChecked" v-if="dataRuleList.length > 0">
|
||||
<a-row>
|
||||
<a-col :span="24" v-for="(item, index) in dataRuleList" :key="'dr' + index">
|
||||
<a-checkbox :value="item.id">{{ item.ruleName }}</a-checkbox>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<div style="width: 100%; margin-top: 15px">
|
||||
<a-button type="primary" :loading="loading" :size="'small'" preIcon="ant-design:save-filled" @click="saveDataRuleForRole">
|
||||
<span>点击保存</span>
|
||||
</a-button>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-checkbox-group>
|
||||
<a-empty v-else description="无配置信息" />
|
||||
</a-tab-pane>
|
||||
<!--<a-tab-pane tab="按钮权限" key="2">敬请期待!!!</a-tab-pane>-->
|
||||
</a-tabs>
|
||||
</a-spin>
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, unref } from 'vue';
|
||||
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
|
||||
|
||||
import { queryDepartRoleDataRule, saveDepartRoleDataRule } from '../depart.user.api';
|
||||
|
||||
defineEmits(['register']);
|
||||
const loading = ref<boolean>(false);
|
||||
const departId = ref('');
|
||||
const functionId = ref('');
|
||||
const roleId = ref('');
|
||||
const dataRuleList = ref<Array<any>>([]);
|
||||
const dataRuleChecked = ref<Array<any>>([]);
|
||||
|
||||
// 注册抽屉组件
|
||||
const [registerDrawer, { closeDrawer }] = useDrawerInner((data) => {
|
||||
roleId.value = unref(data.roleId);
|
||||
departId.value = unref(data.departId);
|
||||
functionId.value = unref(data.functionId);
|
||||
loadData();
|
||||
});
|
||||
|
||||
async function loadData() {
|
||||
try {
|
||||
loading.value = true;
|
||||
const { datarule, drChecked } = await queryDepartRoleDataRule(functionId, departId, roleId);
|
||||
dataRuleList.value = datarule;
|
||||
if (drChecked) {
|
||||
dataRuleChecked.value = drChecked.split(',');
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function saveDataRuleForRole() {
|
||||
let params = {
|
||||
permissionId: functionId.value,
|
||||
roleId: roleId.value,
|
||||
dataRuleIds: dataRuleChecked.value.join(','),
|
||||
};
|
||||
saveDepartRoleDataRule(params);
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
doReset();
|
||||
}
|
||||
|
||||
function doReset() {
|
||||
functionId.value = '';
|
||||
roleId.value = '';
|
||||
dataRuleList.value = [];
|
||||
dataRuleChecked.value = [];
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="addDepartRole">添加部门角色</a-button>
|
||||
<template v-if="selectedRowKeys.length > 0">
|
||||
<a-divider type="vertical" />
|
||||
<a-dropdown>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1" @click="onDeleteDepartRoleBatch">
|
||||
<icon icon="ant-design:delete-outlined" />
|
||||
<span>删除</span>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>
|
||||
<span>批量操作 </span>
|
||||
<icon icon="akar-icons:chevron-down" />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
</template>
|
||||
<!-- 插槽:行内操作按钮 -->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!-- 添加部门弹窗 -->
|
||||
<DepartRoleModal :departId="departId" @register="registerFormModal" @success="onFormModalSuccess" />
|
||||
<DepartRoleAuthDrawer @register="registerAuthDrawer" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject, ref, unref, watch, computed, onMounted } from 'vue';
|
||||
|
||||
import { ActionItem, BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
|
||||
import DepartRoleModal from './DepartRoleModal.vue';
|
||||
import DepartRoleAuthDrawer from './DepartRoleAuthDrawer.vue';
|
||||
import { deleteBatchDepartRole, departRoleList } from '../depart.user.api';
|
||||
import { departRoleColumns, departRoleSearchFormSchema } from '../depart.user.data';
|
||||
import { ColEx } from '/@/components/Form/src/types';
|
||||
|
||||
const prefixCls = inject('prefixCls');
|
||||
const props = defineProps({
|
||||
data: { require: true, type: Object },
|
||||
});
|
||||
defineEmits(['register']);
|
||||
// 当前选中的部门ID,可能会为空,代表未选择部门
|
||||
const departId = computed(() => props.data?.id);
|
||||
|
||||
// 自适应列配置
|
||||
const adaptiveColProps: Partial<ColEx> = {
|
||||
xs: 24, // <576px
|
||||
sm: 24, // ≥576px
|
||||
md: 24, // ≥768px
|
||||
lg: 12, // ≥992px
|
||||
xl: 12, // ≥1200px
|
||||
xxl: 8, // ≥1600px
|
||||
};
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext, createMessage } = useListPage({
|
||||
tableProps: {
|
||||
api: departRoleList,
|
||||
columns: departRoleColumns,
|
||||
canResize: false,
|
||||
formConfig: {
|
||||
labelWidth: 100,
|
||||
schemas: departRoleSearchFormSchema,
|
||||
baseColProps: adaptiveColProps,
|
||||
labelAlign: 'left',
|
||||
labelCol: {
|
||||
xs: 24,
|
||||
sm: 24,
|
||||
md: 24,
|
||||
lg: 9,
|
||||
xl: 7,
|
||||
xxl: 6,
|
||||
},
|
||||
wrapperCol: {},
|
||||
// 操作按钮配置
|
||||
actionColOptions: {
|
||||
...adaptiveColProps,
|
||||
style: { textAlign: 'left' },
|
||||
},
|
||||
},
|
||||
// 【issues/1064】列设置的 cacheKey
|
||||
tableSetting: { cacheKey: 'depart_user_departInfo' },
|
||||
// 请求之前对参数做处理
|
||||
beforeFetch(params) {
|
||||
params.deptId = departId.value;
|
||||
},
|
||||
// update-begin--author:liaozhiyang---date:20240517---for:【TV360X-53】未选择部门的情况下,部门角色全查出来了
|
||||
immediate: !!departId.value,
|
||||
// update-end--author:liaozhiyang---date:20240517---for:【TV360X-53】未选择部门的情况下,部门角色全查出来了
|
||||
},
|
||||
});
|
||||
|
||||
// 注册 ListTable
|
||||
const [registerTable, { reload, setProps, setLoading, updateTableDataRecord }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
|
||||
// 注册Form弹窗
|
||||
const [registerFormModal, formModal] = useModal();
|
||||
// 注册授权弹窗抽屉
|
||||
const [registerAuthDrawer, authDrawer] = useDrawer();
|
||||
|
||||
// 监听 data 更改,重新加载数据
|
||||
watch(
|
||||
() => props.data,
|
||||
() => reload()
|
||||
);
|
||||
onMounted(() => {
|
||||
// update-begin--author:liaozhiyang---date:20240517---for:【TV360X-53】未选择部门的情况下,部门角色全查出来了
|
||||
// reload();
|
||||
// update-end--author:liaozhiyang---date:20240517---for:【TV360X-53】未选择部门的情况下,部门角色全查出来了
|
||||
});
|
||||
|
||||
// 清空选择的行
|
||||
function clearSelection() {
|
||||
selectedRowKeys.value = [];
|
||||
}
|
||||
|
||||
// 添加部门角色
|
||||
function addDepartRole() {
|
||||
formModal.openModal(true, {
|
||||
isUpdate: false,
|
||||
record: {},
|
||||
});
|
||||
}
|
||||
|
||||
// 编辑部门角色
|
||||
function editDepartRole(record) {
|
||||
formModal.openModal(true, {
|
||||
isUpdate: true,
|
||||
record: record,
|
||||
});
|
||||
}
|
||||
|
||||
// 授权部门角色
|
||||
function permissionDepartRole(record) {
|
||||
authDrawer.openDrawer(true, { record });
|
||||
}
|
||||
|
||||
// 批量删除部门角色
|
||||
async function deleteDepartRole(idList, confirm) {
|
||||
if (!departId.value) {
|
||||
createMessage.warning('请先选择一个部门');
|
||||
} else {
|
||||
setLoading(true);
|
||||
let ids = unref(idList).join(',');
|
||||
try {
|
||||
await deleteBatchDepartRole({ ids }, confirm);
|
||||
return reload();
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
// 批量删除部门角色事件
|
||||
async function onDeleteDepartRoleBatch() {
|
||||
try {
|
||||
await deleteDepartRole(selectedRowKeys, true);
|
||||
// 批量删除成功后清空选择
|
||||
clearSelection();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 表单弹窗成功后的回调
|
||||
function onFormModalSuccess({ isUpdate, values }) {
|
||||
isUpdate ? updateTableDataRecord(values.id, values) : reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record): ActionItem[] {
|
||||
return [{ label: '编辑', onClick: editDepartRole.bind(null, record) }];
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉操作栏
|
||||
*/
|
||||
function getDropDownAction(record): ActionItem[] {
|
||||
return [
|
||||
{ label: '授权', onClick: permissionDepartRole.bind(null, record) },
|
||||
{
|
||||
label: '删除',
|
||||
color: 'error',
|
||||
popConfirm: {
|
||||
title: '确认要删除吗?',
|
||||
confirm: deleteDepartRole.bind(null, [record.id], false),
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<BasicModal :title="title" :width="800" v-bind="$attrs" @ok="handleOk" @register="registerModal">
|
||||
<BasicForm @register="registerForm" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, ref, unref } from 'vue';
|
||||
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
// noinspection ES6UnusedImports
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
|
||||
import { saveOrUpdateDepartRole } from '../depart.user.api';
|
||||
import { departRoleModalFormSchema } from '../depart.user.data';
|
||||
|
||||
const emit = defineEmits(['success', 'register']);
|
||||
const props = defineProps({
|
||||
// 当前部门ID
|
||||
departId: { require: true, type: String },
|
||||
});
|
||||
const prefixCls = inject('prefixCls');
|
||||
// 当前是否是更新模式
|
||||
const isUpdate = ref<boolean>(true);
|
||||
// 当前的弹窗数据
|
||||
const model = ref<object>({});
|
||||
const title = computed(() => (isUpdate.value ? '编辑' : '新增'));
|
||||
|
||||
//注册表单
|
||||
const [registerForm, { resetFields, setFieldsValue, validate, updateSchema }] = useForm({
|
||||
schemas: departRoleModalFormSchema,
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
|
||||
// 注册弹窗
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
await resetFields();
|
||||
isUpdate.value = unref(data?.isUpdate);
|
||||
// 无论新增还是编辑,都可以设置表单值
|
||||
let record = unref(data?.record);
|
||||
if (typeof record === 'object') {
|
||||
model.value = record;
|
||||
await setFieldsValue({ ...record });
|
||||
}
|
||||
});
|
||||
|
||||
//提交事件
|
||||
async function handleOk() {
|
||||
try {
|
||||
setModalProps({ confirmLoading: true });
|
||||
let values = await validate();
|
||||
values.departId = unref(props.departId);
|
||||
//提交表单
|
||||
await saveOrUpdateDepartRole(values, isUpdate.value);
|
||||
//关闭弹窗
|
||||
closeModal();
|
||||
//刷新列表
|
||||
emit('success', { isUpdate: unref(isUpdate), values });
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<BasicDrawer title="部门角色分配" :width="365" @close="onClose" @register="registerDrawer">
|
||||
<a-spin :spinning="loading">
|
||||
<template v-if="desformList.length > 0">
|
||||
<a-checkbox-group v-model:value="designNameValue">
|
||||
<a-row>
|
||||
<a-col :span="24" v-for="item of desformList">
|
||||
<a-checkbox :value="item.id">{{ item.roleName }}</a-checkbox>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-checkbox-group>
|
||||
<div style="width: 100%; margin-top: 15px">
|
||||
<a-button type="primary" :loading="loading" :size="'small'" preIcon="ant-design:save-filled" @click="onSubmit">
|
||||
<span>点击保存</span>
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<a-empty v-else description="无配置信息" />
|
||||
</a-spin>
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, unref } from 'vue';
|
||||
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
|
||||
|
||||
import { queryDepartRoleByUserId, queryDepartRoleUserList, saveDepartRoleUser } from '../depart.user.api';
|
||||
|
||||
defineEmits(['register']);
|
||||
const loading = ref<boolean>(false);
|
||||
const userId = ref('');
|
||||
const departId = ref('');
|
||||
const oldRoleId = ref('');
|
||||
const desformList = ref<Array<any>>([]);
|
||||
const designNameValue = ref<Array<any>>([]);
|
||||
|
||||
// 注册抽屉组件
|
||||
const [registerDrawer, { closeDrawer }] = useDrawerInner((data) => {
|
||||
userId.value = unref(data.userId);
|
||||
departId.value = unref(data.departId);
|
||||
loadData();
|
||||
});
|
||||
|
||||
async function loadData() {
|
||||
try {
|
||||
loading.value = true;
|
||||
const params = {
|
||||
departId: departId.value,
|
||||
userId: userId.value,
|
||||
};
|
||||
// 查询 DepartRole
|
||||
const [$desformList, $departRoleList] = await Promise.all([queryDepartRoleUserList(params), queryDepartRoleByUserId(params)]);
|
||||
desformList.value = $desformList;
|
||||
designNameValue.value = $departRoleList.map((item) => item.droleId);
|
||||
oldRoleId.value = designNameValue.value.join(',');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
try {
|
||||
loading.value = true;
|
||||
await saveDepartRoleUser({
|
||||
userId: userId.value,
|
||||
newRoleId: designNameValue.value.join(','),
|
||||
oldRoleId: oldRoleId.value,
|
||||
});
|
||||
doClose();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
doReset();
|
||||
}
|
||||
|
||||
function doClose() {
|
||||
doReset();
|
||||
closeDrawer();
|
||||
}
|
||||
|
||||
function doReset() {
|
||||
userId.value = '';
|
||||
departId.value = '';
|
||||
oldRoleId.value = '';
|
||||
desformList.value = [];
|
||||
designNameValue.value = [];
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<div class="bg-white m-4 mr-0 overflow-hidden">
|
||||
<a-spin :spinning="loading">
|
||||
<template v-if="userIdentity === '2'">
|
||||
<!--组织机构树-->
|
||||
<BasicTree
|
||||
v-if="!treeReloading"
|
||||
title="部门列表"
|
||||
toolbar
|
||||
search
|
||||
showLine
|
||||
:checkStrictly="true"
|
||||
:clickRowToExpand="false"
|
||||
:treeData="treeData"
|
||||
:selectedKeys="selectedKeys"
|
||||
:expandedKeys="expandedKeys"
|
||||
:autoExpandParent="autoExpandParent"
|
||||
@select="onSelect"
|
||||
@expand="onExpand"
|
||||
@search="onSearch"
|
||||
/>
|
||||
</template>
|
||||
<a-empty v-else description="普通员工无此权限" />
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { inject, nextTick, ref } from 'vue';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { BasicTree } from '/@/components/Tree';
|
||||
import { queryMyDepartTreeList, searchByKeywords } from '../depart.user.api';
|
||||
|
||||
const prefixCls = inject('prefixCls');
|
||||
const emit = defineEmits(['select']);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
let loading = ref<boolean>(false);
|
||||
// 部门树列表数据
|
||||
let treeData = ref<any[]>([]);
|
||||
// 当前展开的项
|
||||
let expandedKeys = ref<any[]>([]);
|
||||
// 当前选中的项
|
||||
let selectedKeys = ref<any[]>([]);
|
||||
// 是否自动展开父级
|
||||
let autoExpandParent = ref<boolean>(true);
|
||||
// 用户身份
|
||||
let userIdentity = ref<string>('2');
|
||||
// 树组件重新加载
|
||||
let treeReloading = ref<boolean>(false);
|
||||
|
||||
// 加载部门信息
|
||||
function loadDepartTreeData() {
|
||||
loading.value = true;
|
||||
treeData.value = [];
|
||||
queryMyDepartTreeList()
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
if (Array.isArray(res.result)) {
|
||||
treeData.value = res.result;
|
||||
userIdentity.value = res.message;
|
||||
autoExpandParentNode();
|
||||
}
|
||||
} else {
|
||||
createMessage.warning(res.message);
|
||||
}
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
}
|
||||
|
||||
loadDepartTreeData();
|
||||
|
||||
// 自动展开父节点,只展开一级
|
||||
function autoExpandParentNode() {
|
||||
let keys: Array<any> = [];
|
||||
treeData.value.forEach((item, index) => {
|
||||
if (item.children && item.children.length > 0) {
|
||||
keys.push(item.key);
|
||||
}
|
||||
if (index === 0) {
|
||||
// 默认选中第一个
|
||||
setSelectedKey(item.id, item);
|
||||
}
|
||||
});
|
||||
if (keys.length > 0) {
|
||||
reloadTree();
|
||||
expandedKeys.value = keys;
|
||||
}
|
||||
}
|
||||
|
||||
// 重新加载树组件,防止无法默认展开数据
|
||||
async function reloadTree() {
|
||||
await nextTick();
|
||||
treeReloading.value = true;
|
||||
await nextTick();
|
||||
treeReloading.value = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前选中的行
|
||||
*/
|
||||
function setSelectedKey(key: string, data?: object) {
|
||||
selectedKeys.value = [key];
|
||||
if (data) {
|
||||
emit('select', data);
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索事件
|
||||
function onSearch(value: string) {
|
||||
if (value) {
|
||||
loading.value = true;
|
||||
searchByKeywords({ keyWord: value, myDeptSearch: '1' })
|
||||
.then((result) => {
|
||||
if (Array.isArray(result)) {
|
||||
treeData.value = result;
|
||||
} else {
|
||||
createMessage.warning('未查询到部门信息');
|
||||
treeData.value = [];
|
||||
}
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
} else {
|
||||
loadDepartTreeData();
|
||||
}
|
||||
}
|
||||
|
||||
// 树选择事件
|
||||
function onSelect(selKeys, event) {
|
||||
if (selKeys.length > 0 && selectedKeys.value[0] !== selKeys[0]) {
|
||||
setSelectedKey(selKeys[0], event.selectedNodes[0]);
|
||||
} else {
|
||||
// 这样可以防止用户取消选择
|
||||
setSelectedKey(selectedKeys.value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// 树展开事件
|
||||
function onExpand(keys) {
|
||||
expandedKeys.value = keys;
|
||||
autoExpandParent.value = false;
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
/*升级antd3后,查询框与树贴的太近,样式优化*/
|
||||
:deep(.jeecg-tree-header) {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,231 @@
|
||||
<template>
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="selectAddUser">添加已有用户</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="createUser">新建用户</a-button>
|
||||
<template v-if="selectedRowKeys.length > 0">
|
||||
<a-dropdown>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1" @click="onUnlinkDepartUserBatch">
|
||||
<icon icon="bx:bx-unlink" />
|
||||
<span>取消关联</span>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>
|
||||
<span>批量操作 </span>
|
||||
<icon icon="akar-icons:chevron-down" />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
</template>
|
||||
<!-- 插槽:行内操作按钮 -->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<UserDrawer @register="registerDrawer" @success="onUserDrawerSuccess" />
|
||||
<DepartRoleUserAuthDrawer @register="registerUserAuthDrawer" />
|
||||
<UserSelectModal rowKey="id" @register="registerSelUserModal" @getSelectResult="onSelectUserOk" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, ref, unref, watch } from 'vue';
|
||||
import { ActionItem, BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
|
||||
import UserDrawer from '/@/views/system/user/UserDrawer.vue';
|
||||
import UserSelectModal from '/@/components/Form/src/jeecg/components/modal/UserSelectModal.vue';
|
||||
import DepartRoleUserAuthDrawer from './DepartRoleUserAuthDrawer.vue';
|
||||
import { departUserList, linkDepartUserBatch, unlinkDepartUserBatch } from '../depart.user.api';
|
||||
import { userInfoColumns, userInfoSearchFormSchema } from '../depart.user.data';
|
||||
import { ColEx } from '/@/components/Form/src/types';
|
||||
|
||||
const prefixCls = inject('prefixCls');
|
||||
const props = defineProps({
|
||||
data: { require: true, type: Object },
|
||||
});
|
||||
// 当前选中的部门ID,可能会为空,代表未选择部门
|
||||
const departId = computed(() => props.data?.id);
|
||||
|
||||
// 自适应列配置
|
||||
const adaptiveColProps: Partial<ColEx> = {
|
||||
xs: 24, // <576px
|
||||
sm: 24, // ≥576px
|
||||
md: 24, // ≥768px
|
||||
lg: 12, // ≥992px
|
||||
xl: 12, // ≥1200px
|
||||
xxl: 8, // ≥1600px
|
||||
};
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext, createMessage } = useListPage({
|
||||
tableProps: {
|
||||
api: departUserList,
|
||||
columns: userInfoColumns,
|
||||
canResize: false,
|
||||
formConfig: {
|
||||
schemas: userInfoSearchFormSchema,
|
||||
baseColProps: adaptiveColProps,
|
||||
labelAlign: 'left',
|
||||
labelCol: {
|
||||
xs: 24,
|
||||
sm: 24,
|
||||
md: 24,
|
||||
lg: 9,
|
||||
xl: 7,
|
||||
xxl: 5,
|
||||
},
|
||||
wrapperCol: {},
|
||||
// 操作按钮配置
|
||||
actionColOptions: {
|
||||
...adaptiveColProps,
|
||||
style: { textAlign: 'left' },
|
||||
},
|
||||
},
|
||||
// 【issues/1064】列设置的 cacheKey
|
||||
tableSetting: { cacheKey: 'depart_user_userInfo' },
|
||||
// 请求之前对参数做处理
|
||||
beforeFetch(params) {
|
||||
params.depId = departId.value;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 注册 ListTable
|
||||
const [registerTable, { reload, setProps, setLoading, updateTableDataRecord }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
() => reload()
|
||||
);
|
||||
//注册drawer
|
||||
const [registerDrawer, { openDrawer, setDrawerProps }] = useDrawer();
|
||||
const [registerUserAuthDrawer, userAuthDrawer] = useDrawer();
|
||||
// 注册用户选择 modal
|
||||
const [registerSelUserModal, selUserModal] = useModal();
|
||||
|
||||
// 清空选择的行
|
||||
function clearSelection() {
|
||||
selectedRowKeys.value = [];
|
||||
}
|
||||
|
||||
// 查看部门角色
|
||||
function showDepartRole(record) {
|
||||
userAuthDrawer.openDrawer(true, { userId: record.id, departId });
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
function createUser() {
|
||||
if (!departId.value) {
|
||||
createMessage.warning('请先选择一个部门');
|
||||
} else {
|
||||
openDrawer(true, {
|
||||
isUpdate: false,
|
||||
departDisabled: true,
|
||||
// 初始化负责部门
|
||||
nextDepartOptions: { value: props.data?.key, label: props.data?.title },
|
||||
record: {
|
||||
activitiSync: 1,
|
||||
userIdentity: 1,
|
||||
selecteddeparts: departId.value,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 查看用户详情
|
||||
function showUserDetail(record) {
|
||||
openDrawer(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
departDisabled: true,
|
||||
showFooter: false,
|
||||
});
|
||||
}
|
||||
|
||||
// 编辑用户信息
|
||||
function editUserInfo(record) {
|
||||
openDrawer(true, { isUpdate: true, record, departDisabled: true });
|
||||
}
|
||||
|
||||
// 选择添加已有用户
|
||||
function selectAddUser() {
|
||||
selUserModal.openModal();
|
||||
}
|
||||
|
||||
// 批量取消关联部门和用户之间的关系
|
||||
async function unlinkDepartUser(idList, confirm) {
|
||||
if (!departId.value) {
|
||||
createMessage.warning('请先选择一个部门');
|
||||
} else {
|
||||
setLoading(true);
|
||||
let userIds = unref(idList).join(',');
|
||||
try {
|
||||
await unlinkDepartUserBatch({ depId: departId.value, userIds }, confirm);
|
||||
return reload();
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
// 批量取消关联事件
|
||||
async function onUnlinkDepartUserBatch() {
|
||||
try {
|
||||
await unlinkDepartUser(selectedRowKeys, true);
|
||||
// 批量删除成功后清空选择
|
||||
clearSelection();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 选择用户成功
|
||||
async function onSelectUserOk(options, userIdList) {
|
||||
if (userIdList.length > 0) {
|
||||
try {
|
||||
setLoading(true);
|
||||
await linkDepartUserBatch(departId.value, userIdList);
|
||||
reload();
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户抽屉表单成功回调
|
||||
*/
|
||||
function onUserDrawerSuccess({ isUpdate, values }) {
|
||||
isUpdate ? updateTableDataRecord(values.id, values) : reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record): ActionItem[] {
|
||||
return [{ label: '编辑', onClick: editUserInfo.bind(null, record) }];
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉操作栏
|
||||
*/
|
||||
function getDropDownAction(record): ActionItem[] {
|
||||
return [
|
||||
{ label: '部门角色', onClick: showDepartRole.bind(null, record) },
|
||||
{ label: '用户详情', onClick: showUserDetail.bind(null, record) },
|
||||
{
|
||||
label: '取消关联',
|
||||
color: 'error',
|
||||
popConfirm: {
|
||||
title: '确认取消关联吗?',
|
||||
confirm: unlinkDepartUser.bind(null, [record.id], false),
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
159
jeecgboot-vue3/src/views/system/departUser/depart.user.api.ts
Normal file
159
jeecgboot-vue3/src/views/system/departUser/depart.user.api.ts
Normal file
@ -0,0 +1,159 @@
|
||||
import { unref } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const { createConfirm } = useMessage();
|
||||
|
||||
enum Api {
|
||||
treeList = '/sys/sysDepart/queryMyDeptTreeList',
|
||||
queryIdTree = '/sys/sysDepart/queryIdTree',
|
||||
searchBy = '/sys/sysDepart/searchBy',
|
||||
}
|
||||
|
||||
// 部门用户API
|
||||
enum DepartUserApi {
|
||||
list = '/sys/user/departUserList',
|
||||
link = '/sys/user/editSysDepartWithUser',
|
||||
unlink = '/sys/user/deleteUserInDepartBatch',
|
||||
}
|
||||
|
||||
// 部门角色API
|
||||
enum DepartRoleApi {
|
||||
list = '/sys/sysDepartRole/list',
|
||||
deleteBatch = '/sys/sysDepartRole/deleteBatch',
|
||||
save = '/sys/sysDepartRole/add',
|
||||
edit = '/sys/sysDepartRole/edit',
|
||||
queryTreeListForDeptRole = '/sys/sysDepartPermission/queryTreeListForDeptRole',
|
||||
queryDeptRolePermission = '/sys/sysDepartPermission/queryDeptRolePermission',
|
||||
saveDeptRolePermission = '/sys/sysDepartPermission/saveDeptRolePermission',
|
||||
dataRule = '/sys/sysDepartRole/datarule',
|
||||
getDeptRoleList = '/sys/sysDepartRole/getDeptRoleList',
|
||||
getDeptRoleByUserId = '/sys/sysDepartRole/getDeptRoleByUserId',
|
||||
saveDeptRoleUser = '/sys/sysDepartRole/deptRoleUserAdd',
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门树列表
|
||||
*/
|
||||
export const queryMyDepartTreeList = (params?) => defHttp.get({ url: Api.treeList, params }, { isTransformResponse: false });
|
||||
|
||||
/**
|
||||
* 查询数据,以树结构形式加载所有部门的名称
|
||||
*/
|
||||
export const queryIdTree = (params?) => defHttp.get({ url: Api.queryIdTree, params });
|
||||
|
||||
/**
|
||||
* 根据关键字搜索部门
|
||||
*/
|
||||
export const searchByKeywords = (params) => defHttp.get({ url: Api.searchBy, params });
|
||||
|
||||
/**
|
||||
* 查询部门下的用户信息
|
||||
*/
|
||||
export const departUserList = (params) => defHttp.get({ url: DepartUserApi.list, params });
|
||||
|
||||
/**
|
||||
* 批量添加部门和用户的关联关系
|
||||
*
|
||||
* @param departId 部门ID
|
||||
* @param userIdList 用户ID列表
|
||||
*/
|
||||
export const linkDepartUserBatch = (departId: string, userIdList: string[]) =>
|
||||
defHttp.post({ url: DepartUserApi.link, params: { depId: departId, userIdList } });
|
||||
|
||||
/**
|
||||
* 批量取消部门和用户的关联关系
|
||||
*/
|
||||
export const unlinkDepartUserBatch = (params, confirm = false) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const doDelete = () => {
|
||||
resolve(defHttp.delete({ url: DepartUserApi.unlink, params }, { joinParamsToUrl: true }));
|
||||
};
|
||||
if (confirm) {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '取消关联',
|
||||
content: '确定要取消关联吗?',
|
||||
onOk: () => doDelete(),
|
||||
onCancel: () => reject(),
|
||||
});
|
||||
} else {
|
||||
doDelete();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询部门角色信息
|
||||
*/
|
||||
export const departRoleList = (params) => defHttp.get({ url: DepartRoleApi.list, params });
|
||||
|
||||
/**
|
||||
* 保存或者更新部门角色
|
||||
*/
|
||||
export const saveOrUpdateDepartRole = (params, isUpdate) => {
|
||||
if (isUpdate) {
|
||||
return defHttp.put({ url: DepartRoleApi.edit, params });
|
||||
} else {
|
||||
return defHttp.post({ url: DepartRoleApi.save, params });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量删除部门角色
|
||||
*/
|
||||
export const deleteBatchDepartRole = (params, confirm = false) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const doDelete = () => {
|
||||
resolve(defHttp.delete({ url: DepartRoleApi.deleteBatch, params }, { joinParamsToUrl: true }));
|
||||
};
|
||||
if (confirm) {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '删除',
|
||||
content: '确定要删除吗?',
|
||||
onOk: () => doDelete(),
|
||||
onCancel: () => reject(),
|
||||
});
|
||||
} else {
|
||||
doDelete();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 用户角色授权功能,查询菜单权限树
|
||||
*/
|
||||
export const queryTreeListForDeptRole = (params) => defHttp.get({ url: DepartRoleApi.queryTreeListForDeptRole, params });
|
||||
/**
|
||||
* 查询角色授权
|
||||
*/
|
||||
export const queryDeptRolePermission = (params) => defHttp.get({ url: DepartRoleApi.queryDeptRolePermission, params });
|
||||
/**
|
||||
* 保存角色授权
|
||||
*/
|
||||
export const saveDeptRolePermission = (params) => defHttp.post({ url: DepartRoleApi.saveDeptRolePermission, params });
|
||||
|
||||
/**
|
||||
* 查询部门角色数据权限列表
|
||||
*/
|
||||
export const queryDepartRoleDataRule = (functionId, departId, roleId, params?) => {
|
||||
let url = `${DepartRoleApi.dataRule}/${unref(functionId)}/${unref(departId)}/${unref(roleId)}`;
|
||||
return defHttp.get({ url, params });
|
||||
};
|
||||
/**
|
||||
* 保存部门角色数据权限
|
||||
*/
|
||||
export const saveDepartRoleDataRule = (params) => defHttp.post({ url: DepartRoleApi.dataRule, params });
|
||||
/**
|
||||
* 查询部门角色用户授权
|
||||
*/
|
||||
export const queryDepartRoleUserList = (params) => defHttp.get({ url: DepartRoleApi.getDeptRoleList, params });
|
||||
/**
|
||||
* 根据 userId 查询部门角色用户授权
|
||||
*/
|
||||
export const queryDepartRoleByUserId = (params) => defHttp.get({ url: DepartRoleApi.getDeptRoleByUserId, params });
|
||||
/**
|
||||
* 保存部门角色用户授权
|
||||
*/
|
||||
export const saveDepartRoleUser = (params) => defHttp.post({ url: DepartRoleApi.saveDeptRoleUser, params });
|
||||
195
jeecgboot-vue3/src/views/system/departUser/depart.user.data.ts
Normal file
195
jeecgboot-vue3/src/views/system/departUser/depart.user.data.ts
Normal file
@ -0,0 +1,195 @@
|
||||
import { Ref } from 'vue';
|
||||
import { duplicateCheckDelay } from '/@/views/system/user/user.api';
|
||||
import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||
import { DescItem } from '/@/components/Description';
|
||||
import { findTree } from '/@/utils/common/compUtils';
|
||||
|
||||
// 用户信息 columns
|
||||
export const userInfoColumns: BasicColumn[] = [
|
||||
{
|
||||
title: '用户账号',
|
||||
dataIndex: 'username',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '用户名称',
|
||||
dataIndex: 'realname',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
dataIndex: 'orgCode',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex_dictText',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '电话',
|
||||
dataIndex: 'phone',
|
||||
width: 120,
|
||||
},
|
||||
];
|
||||
|
||||
// 用户信息查询条件表单
|
||||
export const userInfoSearchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'username',
|
||||
label: '用户账号',
|
||||
component: 'Input',
|
||||
},
|
||||
];
|
||||
|
||||
// 部门角色 columns
|
||||
export const departRoleColumns: BasicColumn[] = [
|
||||
{
|
||||
title: '部门角色名称',
|
||||
dataIndex: 'roleName',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '部门角色编码',
|
||||
dataIndex: 'roleCode',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
dataIndex: 'departId_dictText',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'description',
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
|
||||
// 部门角色查询条件表单
|
||||
export const departRoleSearchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'roleName',
|
||||
label: '部门角色名称',
|
||||
component: 'Input',
|
||||
},
|
||||
];
|
||||
|
||||
// 部门角色弹窗form表单
|
||||
export const departRoleModalFormSchema: FormSchema[] = [
|
||||
{
|
||||
label: 'id',
|
||||
field: 'id',
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
field: 'roleName',
|
||||
label: '部门角色名称',
|
||||
component: 'Input',
|
||||
rules: [
|
||||
{ required: true, message: '部门角色名称不能为空!' },
|
||||
{ min: 2, max: 30, message: '长度在 2 到 30 个字符', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
field: 'roleCode',
|
||||
label: '部门角色编码',
|
||||
component: 'Input',
|
||||
dynamicDisabled: ({ values }) => {
|
||||
return !!values.id;
|
||||
},
|
||||
dynamicRules: ({ model }) => {
|
||||
return [
|
||||
{ required: true, message: '部门角色编码不能为空!' },
|
||||
{ min: 0, max: 64, message: '长度不能超过 64 个字符', trigger: 'blur' },
|
||||
{
|
||||
validator: (_, value) => {
|
||||
if (/[\u4E00-\u9FA5]/g.test(value)) {
|
||||
return Promise.reject('部门角色编码不可输入汉字!');
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let params = {
|
||||
tableName: 'sys_depart_role',
|
||||
fieldName: 'role_code',
|
||||
fieldVal: value,
|
||||
dataId: model.id,
|
||||
};
|
||||
duplicateCheckDelay(params)
|
||||
.then((res) => {
|
||||
res.success ? resolve() : reject(res.message || '校验失败');
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err.message || '验证失败');
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'description',
|
||||
label: '描述',
|
||||
component: 'Input',
|
||||
rules: [{ min: 0, max: 126, message: '长度不能超过 126 个字符', trigger: 'blur' }],
|
||||
},
|
||||
];
|
||||
|
||||
// 基本信息form
|
||||
export function useBaseInfoForm(treeData: Ref<any[]>) {
|
||||
const descItems: DescItem[] = [
|
||||
{
|
||||
field: 'departName',
|
||||
label: '机构名称',
|
||||
},
|
||||
{
|
||||
field: 'parentId',
|
||||
label: '上级部门',
|
||||
render(val) {
|
||||
if (val) {
|
||||
let data = findTree(treeData.value, (item) => item.key == val);
|
||||
return data?.title ?? val;
|
||||
}
|
||||
return val;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'orgCode',
|
||||
label: '机构编码',
|
||||
},
|
||||
{
|
||||
field: 'orgCategory',
|
||||
label: '机构类型',
|
||||
render(val) {
|
||||
if (val === '1') {
|
||||
return '公司';
|
||||
} else if (val === '2') {
|
||||
return '部门';
|
||||
} else if (val === '3') {
|
||||
return '岗位';
|
||||
}
|
||||
return val;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'departOrder',
|
||||
label: '排序',
|
||||
},
|
||||
|
||||
{
|
||||
field: 'mobile',
|
||||
label: '手机号',
|
||||
},
|
||||
{
|
||||
field: 'address',
|
||||
label: '地址',
|
||||
},
|
||||
{
|
||||
field: 'memo',
|
||||
label: '备注',
|
||||
},
|
||||
];
|
||||
|
||||
return { descItems };
|
||||
}
|
||||
48
jeecgboot-vue3/src/views/system/departUser/index.less
Normal file
48
jeecgboot-vue3/src/views/system/departUser/index.less
Normal file
@ -0,0 +1,48 @@
|
||||
@prefix-cls: ~'@{namespace}-depart-user';
|
||||
|
||||
.@{prefix-cls} {
|
||||
&--tree-search {
|
||||
width: 100%;
|
||||
margin: 10px 0 20px;
|
||||
}
|
||||
|
||||
&--base-info-form {
|
||||
@media (min-width: 576px) {
|
||||
.no-border {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.ant-select.ant-select-disabled {
|
||||
.ant-select-selector {
|
||||
border: 0;
|
||||
color: black;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.ant-select-selector,
|
||||
.ant-select-selection-item {
|
||||
cursor: text !important;
|
||||
user-select: initial !important;
|
||||
}
|
||||
|
||||
.ant-select-selection-search,
|
||||
.ant-select-arrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 夜间模式样式兼容
|
||||
[data-theme='dark'] .@{prefix-cls} {
|
||||
&--base-info-form {
|
||||
.ant-select.ant-select-disabled {
|
||||
.ant-select-selector {
|
||||
color: #c9d1d9;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
49
jeecgboot-vue3/src/views/system/departUser/index.vue
Normal file
49
jeecgboot-vue3/src/views/system/departUser/index.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<a-row :class="['p-4', `${prefixCls}--box`]" :gutter="10">
|
||||
<a-col :xl="6" :lg="8" :md="10" :sm="24" style="flex: 1">
|
||||
<a-card :bordered="false" style="height: 100%">
|
||||
<DepartTree @select="onTreeSelect" />
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :xl="18" :lg="16" :md="14" :sm="24" style="flex: 1">
|
||||
<a-card :bordered="false" style="height: 100%">
|
||||
<a-tabs defaultActiveKey="user-info">
|
||||
<a-tab-pane tab="基本信息" key="base-info" forceRender>
|
||||
<DepartBaseInfoTab :data="departData" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="用户信息" key="user-info">
|
||||
<DepartUserInfoTab :data="departData" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="部门角色" key="role-info">
|
||||
<DepartRoleInfoTab :data="departData" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="system-depart-user">
|
||||
import { provide, ref } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
import DepartTree from './components/DepartTree.vue';
|
||||
import DepartBaseInfoTab from './components/DepartBaseInfoTab.vue';
|
||||
import DepartUserInfoTab from './components/DepartUserInfoTab.vue';
|
||||
import DepartRoleInfoTab from './components/DepartRoleInfoTab.vue';
|
||||
|
||||
const { prefixCls } = useDesign('depart-user');
|
||||
provide('prefixCls', prefixCls);
|
||||
|
||||
// 当前选中的部门信息
|
||||
let departData = ref({});
|
||||
|
||||
// 左侧树选择后触发
|
||||
function onTreeSelect(data) {
|
||||
departData.value = data;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import './index.less';
|
||||
</style>
|
||||
Reference in New Issue
Block a user