update
init
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
<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-tabs>
|
||||
</a-spin>
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, unref } from 'vue';
|
||||
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
|
||||
|
||||
import { queryDepartDataRule, saveDepartDataRule } from '../depart.api';
|
||||
|
||||
defineEmits(['register']);
|
||||
const loading = ref<boolean>(false);
|
||||
const departId = ref('');
|
||||
const functionId = ref('');
|
||||
const dataRuleList = ref<Array<any>>([]);
|
||||
const dataRuleChecked = ref<Array<any>>([]);
|
||||
|
||||
// 注册抽屉组件
|
||||
const [registerDrawer, { closeDrawer }] = useDrawerInner((data) => {
|
||||
departId.value = unref(data.departId);
|
||||
functionId.value = unref(data.functionId);
|
||||
loadData();
|
||||
});
|
||||
|
||||
async function loadData() {
|
||||
try {
|
||||
loading.value = true;
|
||||
const { datarule, drChecked } = await queryDepartDataRule(functionId, departId);
|
||||
dataRuleList.value = datarule;
|
||||
if (drChecked) {
|
||||
dataRuleChecked.value = drChecked.split(',');
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function saveDataRuleForRole() {
|
||||
let params = {
|
||||
departId: departId.value,
|
||||
permissionId: functionId.value,
|
||||
dataRuleIds: dataRuleChecked.value.join(','),
|
||||
};
|
||||
saveDepartDataRule(params);
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
doReset();
|
||||
}
|
||||
|
||||
function doReset() {
|
||||
functionId.value = '';
|
||||
dataRuleList.value = [];
|
||||
dataRuleChecked.value = [];
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<BasicModal :title="title" :width="800" v-bind="$attrs" @ok="handleOk" @register="registerModal">
|
||||
<BasicForm @register="registerForm">
|
||||
<template #addressInfo="{ model }">
|
||||
<a-input style="width: calc(100% - 100px)" v-model:value="model['address']" :disabled="true" />
|
||||
<a-button style="margin-left: 10px" @click="viewMap"> 查看地图</a-button>
|
||||
</template>
|
||||
</BasicForm>
|
||||
</BasicModal>
|
||||
|
||||
<Map @register="registerMap" :state="state" ref="map" @get-position="getPosition" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, computed, inject, ref, unref, onMounted } from 'vue';
|
||||
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
|
||||
|
||||
import { saveOrUpdateDepart } from '../depart.api';
|
||||
import { useBasicFormSchema, orgCategoryOptions } from '../depart.data';
|
||||
import Map from '/@/views/consult/resource/components/Map.vue';
|
||||
|
||||
const [registerMap, { openModal }] = useModal();
|
||||
const state = ref({});
|
||||
|
||||
const emit = defineEmits(['success', 'register']);
|
||||
const props = defineProps({
|
||||
rootTreeData: { type: Array, default: () => [] },
|
||||
});
|
||||
const prefixCls = inject('prefixCls');
|
||||
// 当前是否是更新模式
|
||||
const isUpdate = ref<boolean>(false);
|
||||
// 当前的弹窗数据
|
||||
const model = ref<object>({});
|
||||
const title = computed(() => (isUpdate.value ? '编辑' : '新增'));
|
||||
|
||||
//注册表单
|
||||
const [registerForm, { resetFields, setFieldsValue, validate, updateSchema, getFieldsValue }] = useForm({
|
||||
schemas: useBasicFormSchema().basicFormSchema,
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
|
||||
// 打开地图弹窗
|
||||
function viewMap() {
|
||||
openModal(true, {
|
||||
record: { ...getFieldsValue(), ...state.value },
|
||||
});
|
||||
}
|
||||
|
||||
async function getPosition(val) {
|
||||
let { pname, cityname, adname, address, name } = val.handleItem || '';
|
||||
let nameList = [pname, cityname, adname, address, name];
|
||||
let str = '';
|
||||
nameList.map((item) => {
|
||||
if (item !== undefined) {
|
||||
str += item;
|
||||
}
|
||||
});
|
||||
await setFieldsValue({
|
||||
lat: val.lat,
|
||||
lng: val.lng,
|
||||
address: str,
|
||||
});
|
||||
state.value = {
|
||||
...state.value,
|
||||
latitude: val.lat,
|
||||
longitude: val.lng,
|
||||
address: str,
|
||||
};
|
||||
}
|
||||
// 注册弹窗
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
await resetFields();
|
||||
isUpdate.value = unref(data?.isUpdate);
|
||||
// 当前是否为添加子级
|
||||
let isChild = unref(data?.isChild);
|
||||
let categoryOptions = isChild ? orgCategoryOptions.child : orgCategoryOptions.root;
|
||||
// 隐藏不需要展示的字段
|
||||
updateSchema([
|
||||
{
|
||||
field: 'parentId',
|
||||
show: isChild,
|
||||
componentProps: {
|
||||
// 如果是添加子部门,就禁用该字段
|
||||
disabled: isChild,
|
||||
treeData: props.rootTreeData,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'orgCode',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
field: 'orgCategory',
|
||||
componentProps: { options: categoryOptions },
|
||||
},
|
||||
]);
|
||||
|
||||
let record = unref(data?.record);
|
||||
if (typeof record !== 'object') {
|
||||
record = {};
|
||||
}
|
||||
// 赋默认值
|
||||
record = Object.assign(
|
||||
{
|
||||
departOrder: 0,
|
||||
orgCategory: categoryOptions[0].value,
|
||||
},
|
||||
record
|
||||
);
|
||||
model.value = record;
|
||||
await setFieldsValue({ ...record });
|
||||
});
|
||||
|
||||
// 提交事件
|
||||
async function handleOk() {
|
||||
try {
|
||||
setModalProps({ confirmLoading: true });
|
||||
let values = await validate();
|
||||
//提交表单
|
||||
await saveOrUpdateDepart(values, isUpdate.value);
|
||||
//关闭弹窗
|
||||
closeModal();
|
||||
//刷新列表
|
||||
emit('success');
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<a-spin :spinning="loading">
|
||||
<BasicForm @register="registerForm">
|
||||
<template #addressInfo="{ model }">
|
||||
<a-input style="width: calc(100% - 100px)" v-model:value="model['address']" :disabled="true" />
|
||||
<a-button style="margin-left: 10px" @click="viewMap" :disabled="!hasPer"> 查看地图</a-button>
|
||||
</template>
|
||||
</BasicForm>
|
||||
<div class="j-box-bottom-button offset-20" style="margin-top: 30px" v-if="hasPer">
|
||||
<div class="j-box-bottom-button-float">
|
||||
<a-button preIcon="ant-design:sync-outlined" @click="onReset">重置</a-button>
|
||||
<a-button preIcon="ant-design:save-filled" type="primary" @click="onSubmit">保存</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<Map @register="registerMap" :state="state" ref="map" @get-position="getPosition" />
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, computed, inject, ref, unref, onMounted } from 'vue';
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { saveOrUpdateDepart } from '../depart.api';
|
||||
import { useBasicFormSchema, orgCategoryOptions } from '../depart.data';
|
||||
import Map from '/@/views/consult/resource/components/Map.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { orgManageApi } from '/@/utils/auth/buttonAuth/system';
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
|
||||
const { hasPermission } = usePermission();
|
||||
|
||||
const [registerMap, { openModal }] = useModal();
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
const props = defineProps({
|
||||
data: { type: Object, default: () => ({}) },
|
||||
rootTreeData: { type: Array, default: () => [] },
|
||||
});
|
||||
const { userInfo } = useUserStore();
|
||||
const prefixCls = inject('prefixCls');
|
||||
const loading = ref<boolean>(false);
|
||||
// 当前是否是更新模式
|
||||
const isUpdate = ref<boolean>(true);
|
||||
// 当前的弹窗数据
|
||||
const model = ref<object>({});
|
||||
const state = ref({});
|
||||
//注册表单
|
||||
const [registerForm, { resetFields, setFieldsValue, validate, updateSchema, getFieldsValue, clearValidate, setProps }] = useForm({
|
||||
labelWidth: 130,
|
||||
schemas: useBasicFormSchema().basicFormSchema,
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
|
||||
const categoryOptions = computed(() => {
|
||||
if (!!props?.data?.parentId) {
|
||||
return orgCategoryOptions.child;
|
||||
} else {
|
||||
return orgCategoryOptions.root;
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
// 禁用字段
|
||||
updateSchema([
|
||||
{ field: 'parentId', componentProps: { disabled: true } },
|
||||
{ field: 'orgCode', componentProps: { disabled: true } },
|
||||
]);
|
||||
// data 变化,重填表单
|
||||
watch(
|
||||
() => props.data,
|
||||
async () => {
|
||||
let record = unref(props.data);
|
||||
if (typeof record !== 'object') {
|
||||
record = {};
|
||||
}
|
||||
model.value = record;
|
||||
await resetFields();
|
||||
await setFieldsValue({ ...record });
|
||||
updateState(record);
|
||||
|
||||
await setProps({ disabled: !hasPer.value });
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
// 更新 父部门 选项
|
||||
watch(
|
||||
() => props.rootTreeData,
|
||||
async () => {
|
||||
updateSchema([
|
||||
{
|
||||
field: 'parentId',
|
||||
componentProps: { treeData: props.rootTreeData },
|
||||
},
|
||||
]);
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
// 监听并更改 orgCategory options
|
||||
watch(
|
||||
categoryOptions,
|
||||
async () => {
|
||||
updateSchema([
|
||||
{
|
||||
field: 'orgCategory',
|
||||
componentProps: { options: categoryOptions.value },
|
||||
},
|
||||
]);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
await clearValidate();
|
||||
});
|
||||
|
||||
const hasPer = computed(() => {
|
||||
// 修改此字段
|
||||
return (
|
||||
(!!userInfo?.roleCodes && (userInfo?.roleCodes.includes('admin') || userInfo?.roleCodes.includes('system'))) ||
|
||||
(hasPermission(orgManageApi.departManageList) && props.data.manager)
|
||||
);
|
||||
});
|
||||
|
||||
function updateState(val) {
|
||||
state.value = {
|
||||
latitude: val.lat,
|
||||
longitude: val.lng,
|
||||
address: val.address,
|
||||
};
|
||||
}
|
||||
|
||||
// 打开地图弹窗
|
||||
function viewMap() {
|
||||
openModal(true, {
|
||||
record: { ...getFieldsValue(), ...state.value },
|
||||
});
|
||||
}
|
||||
|
||||
// 关闭地图
|
||||
async function getPosition(val) {
|
||||
let { pname, cityname, adname, address, name } = val.handleItem || '';
|
||||
let nameList = [pname, cityname, adname, address, name];
|
||||
let str = '';
|
||||
nameList.map((item) => {
|
||||
if (item !== undefined) {
|
||||
str += item;
|
||||
}
|
||||
});
|
||||
await setFieldsValue({
|
||||
lat: val.lat,
|
||||
lng: val.lng,
|
||||
address: str,
|
||||
});
|
||||
state.value = {
|
||||
...state.value,
|
||||
latitude: val.lat,
|
||||
longitude: val.lng,
|
||||
address: str,
|
||||
};
|
||||
}
|
||||
// 重置表单
|
||||
async function onReset() {
|
||||
await resetFields();
|
||||
await setFieldsValue({ ...model.value });
|
||||
}
|
||||
|
||||
// 提交事件
|
||||
async function onSubmit() {
|
||||
try {
|
||||
loading.value = true;
|
||||
let values = await validate();
|
||||
values = Object.assign({}, model.value, values);
|
||||
//提交表单
|
||||
await saveOrUpdateDepart(values, isUpdate.value);
|
||||
//刷新列表
|
||||
emit('success');
|
||||
Object.assign(model.value, values);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
/*begin 兼容暗夜模式*/
|
||||
.j-box-bottom-button-float {
|
||||
background-color: @component-background;
|
||||
border-top: 1px solid @border-color-base;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
</style>
|
||||
@@ -0,0 +1,361 @@
|
||||
<template>
|
||||
<a-card :bordered="false" style="height: 100%">
|
||||
<div class="j-table-operator" style="width: 100%">
|
||||
<a-button preIcon="ant-design:plus-outlined" type="primary" v-auth="'system:depart:add'" @click="onAddDepart" v-if="hasPer"
|
||||
>新增</a-button
|
||||
>
|
||||
<a-button preIcon="ant-design:plus-outlined" type="primary" v-auth="'system:depart:add'" @click="onAddChildDepart()">添加下级</a-button>
|
||||
<!-- 2024年3月15日09:26:36 暂时注掉导入导出-->
|
||||
<!-- <a-upload name="file" :showUploadList="false" :customRequest="onImportXls">-->
|
||||
<!-- <a-button type="primary" preIcon="ant-design:import-outlined">导入</a-button>-->
|
||||
<!-- </a-upload>-->
|
||||
<!-- <a-button preIcon="ant-design:export-outlined" type="primary" @click="onExportXls">导出</a-button>-->
|
||||
<!-- <a-button type="primary" preIcon="ant-design:sync-outlined">同步企微?</a-button>-->
|
||||
<!-- <a-button type="primary" preIcon="ant-design:sync-outlined">同步钉钉?</a-button>-->
|
||||
<template v-if="checkedKeys.length > 0">
|
||||
<a-dropdown>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1" @click="onDeleteBatch">
|
||||
<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>
|
||||
</div>
|
||||
<a-alert type="info" show-icon class="alert" style="margin-bottom: 8px">
|
||||
<template #message>
|
||||
<template v-if="checkedKeys.length > 0">
|
||||
<span>已选中 {{ checkedKeys.length }} 条记录</span>
|
||||
<a-divider type="vertical" />
|
||||
<a @click="checkedKeys = []">清空</a>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>未选中任何数据</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-alert>
|
||||
<a-spin :spinning="loading" class="spin-tree">
|
||||
<a-input-search placeholder="按部门名称搜索…" style="margin-bottom: 10px" @search="onSearch" />
|
||||
<!--组织机构树-->
|
||||
|
||||
<!-- checkable-->
|
||||
<template v-if="treeData.length > 0">
|
||||
<a-tree
|
||||
v-if="!treeReloading"
|
||||
:clickRowToExpand="false"
|
||||
:treeData="treeData"
|
||||
:selectedKeys="selectedKeys"
|
||||
:checkStrictly="checkStrictly"
|
||||
:load-data="loadChildrenTreeData"
|
||||
:checkedKeys="checkedKeys"
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
@check="onCheck"
|
||||
@select="onSelect"
|
||||
>
|
||||
<template #title="{ key: treeKey, title, dataRef }">
|
||||
<a-dropdown :trigger="['contextmenu']">
|
||||
<Popconfirm
|
||||
:visible="visibleTreeKey === treeKey"
|
||||
title="确定要删除吗?"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
placement="rightTop"
|
||||
@confirm="onDelete(dataRef)"
|
||||
@visibleChange="onVisibleChange"
|
||||
>
|
||||
<span>{{ title }}</span>
|
||||
</Popconfirm>
|
||||
|
||||
<template
|
||||
#overlay
|
||||
v-if="
|
||||
dataRef?.manager ||
|
||||
(!!userInfo?.roleCodes && (userInfo?.roleCodes.includes('admin') || userInfo?.roleCodes.includes('system')))
|
||||
"
|
||||
>
|
||||
<a-menu @click="">
|
||||
<a-menu-item key="1" @click="onAddChildDepart(dataRef)">添加子级</a-menu-item>
|
||||
<a-menu-item key="2" @click="visibleTreeKey = treeKey">
|
||||
<span style="color: red">删除</span>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
</a-tree>
|
||||
</template>
|
||||
<a-empty v-else description="暂无数据" />
|
||||
</a-spin>
|
||||
<DepartFormModal :rootTreeData="treeData" @register="registerModal" @success="loadRootTreeData" />
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineExpose, inject, nextTick, ref, unref, computed } from 'vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useMethods } from '/@/hooks/system/useMethods';
|
||||
import { Api, deleteBatchDepart, queryDepartTreeSync } from '../depart.api';
|
||||
import { searchByKeywords } from '/@/views/system/departUser/depart.user.api';
|
||||
import DepartFormModal from '/@/views/system/depart/components/DepartFormModal.vue';
|
||||
import { message, Popconfirm } from 'ant-design-vue';
|
||||
|
||||
const prefixCls = inject('prefixCls');
|
||||
const emit = defineEmits(['select', 'rootTreeData']);
|
||||
const { createMessage } = useMessage();
|
||||
const { handleImportXls, handleExportXls } = useMethods();
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { orgManageApi } from '/@/utils/auth/buttonAuth/system';
|
||||
const { userInfo } = useUserStore();
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
|
||||
const { hasPermission } = usePermission();
|
||||
|
||||
const loading = ref<boolean>(false);
|
||||
// 部门树列表数据
|
||||
const treeData = ref<any[]>([]);
|
||||
// 当前选中的项
|
||||
const checkedKeys = ref<any[]>([]);
|
||||
// 当前展开的项
|
||||
const expandedKeys = ref<any[]>([]);
|
||||
// 当前选中的项
|
||||
const selectedKeys = ref<any[]>([]);
|
||||
// 树组件重新加载
|
||||
const treeReloading = ref<boolean>(false);
|
||||
// 树父子是否关联
|
||||
const checkStrictly = ref<boolean>(true);
|
||||
// 当前选中的部门
|
||||
const currentDepart = ref<any>(null);
|
||||
// 控制确认删除提示框是否显示
|
||||
const visibleTreeKey = ref<any>(null);
|
||||
// 搜索关键字
|
||||
const searchKeyword = ref('');
|
||||
|
||||
// 注册 modal
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
|
||||
// 加载顶级部门信息
|
||||
async function loadRootTreeData() {
|
||||
try {
|
||||
loading.value = true;
|
||||
treeData.value = [];
|
||||
const result = await queryDepartTreeSync();
|
||||
if (Array.isArray(result)) {
|
||||
treeData.value = result;
|
||||
}
|
||||
if (expandedKeys.value.length === 0) {
|
||||
autoExpandParentNode();
|
||||
} else {
|
||||
if (selectedKeys.value.length === 0) {
|
||||
let item = treeData.value[0];
|
||||
if (item) {
|
||||
// 默认选中第一个
|
||||
setSelectedKey(item.id, item);
|
||||
}
|
||||
} else {
|
||||
emit('select', currentDepart.value);
|
||||
}
|
||||
}
|
||||
emit('rootTreeData', treeData.value);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
loadRootTreeData();
|
||||
|
||||
// 加载子级部门信息
|
||||
async function loadChildrenTreeData(treeNode) {
|
||||
try {
|
||||
const result = await queryDepartTreeSync({
|
||||
pid: treeNode.dataRef.id,
|
||||
});
|
||||
if (result && result.length == 0) {
|
||||
treeNode.dataRef.isLeaf = true;
|
||||
} else {
|
||||
treeNode.dataRef.children = result;
|
||||
if (expandedKeys.value.length > 0) {
|
||||
// 判断获取的子级是否有当前展开的项
|
||||
let subKeys: any[] = [];
|
||||
for (let key of expandedKeys.value) {
|
||||
if (result.findIndex((item) => item.id === key) !== -1) {
|
||||
subKeys.push(key);
|
||||
}
|
||||
}
|
||||
if (subKeys.length > 0) {
|
||||
expandedKeys.value = [...expandedKeys.value];
|
||||
}
|
||||
}
|
||||
}
|
||||
treeData.value = [...treeData.value];
|
||||
emit('rootTreeData', treeData.value);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// 自动展开父节点,只展开一级
|
||||
function autoExpandParentNode() {
|
||||
let item = treeData.value[0];
|
||||
if (item) {
|
||||
if (!item.isLeaf) {
|
||||
expandedKeys.value = [item.key];
|
||||
}
|
||||
// 默认选中第一个
|
||||
setSelectedKey(item.id, item);
|
||||
reloadTree();
|
||||
} else {
|
||||
emit('select', null);
|
||||
}
|
||||
}
|
||||
|
||||
// 重新加载树组件,防止无法默认展开数据
|
||||
async function reloadTree() {
|
||||
await nextTick();
|
||||
treeReloading.value = true;
|
||||
await nextTick();
|
||||
treeReloading.value = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前选中的行
|
||||
*/
|
||||
function setSelectedKey(key: string, data?: object) {
|
||||
selectedKeys.value = [key];
|
||||
if (data) {
|
||||
currentDepart.value = data;
|
||||
emit('select', data);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加一级部门
|
||||
function onAddDepart() {
|
||||
if (!hasPer.value) return message.info('无权限');
|
||||
openModal(true, { isUpdate: false, isChild: false });
|
||||
}
|
||||
|
||||
// 添加子级部门
|
||||
function onAddChildDepart(data = currentDepart.value) {
|
||||
if (!hasPer.value) return message.info('无权限');
|
||||
if (data == null) {
|
||||
createMessage.warning('请先选择一个部门');
|
||||
return;
|
||||
}
|
||||
const record = { parentId: data.id };
|
||||
openModal(true, { isUpdate: false, isChild: true, record });
|
||||
}
|
||||
|
||||
// 搜索事件
|
||||
async function onSearch(value: string) {
|
||||
if (value) {
|
||||
try {
|
||||
loading.value = true;
|
||||
treeData.value = [];
|
||||
let result = await searchByKeywords({ keyWord: value });
|
||||
if (Array.isArray(result)) {
|
||||
treeData.value = result;
|
||||
}
|
||||
autoExpandParentNode();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
} else {
|
||||
loadRootTreeData();
|
||||
}
|
||||
searchKeyword.value = value;
|
||||
}
|
||||
|
||||
// 树复选框选择事件
|
||||
function onCheck(e) {
|
||||
if (Array.isArray(e)) {
|
||||
checkedKeys.value = e;
|
||||
} else {
|
||||
checkedKeys.value = e.checked;
|
||||
}
|
||||
}
|
||||
|
||||
// 树选择事件
|
||||
function onSelect(selKeys, event) {
|
||||
if (selKeys.length > 0 && selectedKeys.value[0] !== selKeys[0]) {
|
||||
setSelectedKey(selKeys[0], event.selectedNodes[0]);
|
||||
} else {
|
||||
// 这样可以防止用户取消选择
|
||||
setSelectedKey(selectedKeys.value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 ids 删除部门
|
||||
* @param idListRef array
|
||||
* @param confirm 是否显示确认提示框
|
||||
*/
|
||||
async function doDeleteDepart(idListRef, confirm = true) {
|
||||
const idList = unref(idListRef);
|
||||
if (idList.length > 0) {
|
||||
try {
|
||||
loading.value = true;
|
||||
await deleteBatchDepart({ ids: idList.join(',') }, confirm);
|
||||
await loadRootTreeData();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除单个部门
|
||||
async function onDelete(data) {
|
||||
if (!hasPer.value) return message.info('无权限');
|
||||
if (data) {
|
||||
onVisibleChange(false);
|
||||
doDeleteDepart([data.id], false);
|
||||
}
|
||||
}
|
||||
|
||||
// 批量删除部门
|
||||
async function onDeleteBatch() {
|
||||
try {
|
||||
if (!hasPer.value) return message.info('无权限');
|
||||
await doDeleteDepart(checkedKeys);
|
||||
checkedKeys.value = [];
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
function onVisibleChange(visible) {
|
||||
if (!visible) {
|
||||
visibleTreeKey.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
function onImportXls(d) {
|
||||
if (!hasPer.value) return message.info('无权限');
|
||||
handleImportXls(d, Api.importExcelUrl, () => {
|
||||
loadRootTreeData();
|
||||
});
|
||||
}
|
||||
|
||||
function onExportXls() {
|
||||
if (!hasPer.value) return message.info('无权限');
|
||||
handleExportXls('部门信息', Api.exportXlsUrl);
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
loadRootTreeData,
|
||||
});
|
||||
|
||||
const hasPer = computed(() => {
|
||||
// 修改此字段
|
||||
return (
|
||||
(!!userInfo?.roleCodes && (userInfo?.roleCodes.includes('admin') || userInfo?.roleCodes.includes('system'))) ||
|
||||
(hasPermission(orgManageApi.departManageList) && currentDepart.value?.manager)
|
||||
);
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,176 @@
|
||||
<template>
|
||||
<a-spin :spinning="loading">
|
||||
<template v-if="treeData.length > 0">
|
||||
<BasicTree
|
||||
ref="basicTree"
|
||||
class="depart-rule-tree"
|
||||
checkable
|
||||
:treeData="treeData"
|
||||
:checkedKeys="checkedKeys"
|
||||
:selectedKeys="selectedKeys"
|
||||
:expandedKeys="expandedKeys"
|
||||
:checkStrictly="checkStrictly"
|
||||
style="height: 500px; overflow: auto"
|
||||
@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="无可配置部门权限" />
|
||||
|
||||
<div class="j-box-bottom-button offset-20" style="margin-top: 30px">
|
||||
<div class="j-box-bottom-button-float">
|
||||
<a-dropdown :trigger="['click']" placement="top">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="3" @click="toggleCheckALL(true)">全部勾选</a-menu-item>
|
||||
<a-menu-item key="4" @click="toggleCheckALL(false)">取消全选</a-menu-item>
|
||||
<a-menu-item key="5" @click="toggleExpandAll(true)">展开所有</a-menu-item>
|
||||
<a-menu-item key="6" @click="toggleExpandAll(false)">收起所有</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button style="float: left">
|
||||
树操作
|
||||
<Icon icon="ant-design:up-outlined" />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
<a-button preIcon="ant-design:save-filled" type="primary" @click="onSubmit">保存</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
<DepartDataRuleDrawer @register="registerDataRuleDrawer" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { watch, computed, inject, ref, nextTick } from 'vue';
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
import { BasicTree } from '/@/components/Tree/index';
|
||||
import DepartDataRuleDrawer from './DepartDataRuleDrawer.vue';
|
||||
import { queryRoleTreeList, queryDepartPermission, saveDepartPermission } from '../depart.api';
|
||||
|
||||
const props = defineProps({
|
||||
data: { type: Object, default: () => ({}) },
|
||||
});
|
||||
// 当前选中的部门ID,可能会为空,代表未选择部门
|
||||
const departId = computed(() => props.data?.id);
|
||||
|
||||
const prefixCls = inject('prefixCls');
|
||||
const basicTree = ref();
|
||||
const loading = ref<boolean>(false);
|
||||
const treeData = ref<any[]>([]);
|
||||
const expandedKeys = ref<Array<any>>([]);
|
||||
const selectedKeys = ref<Array<any>>([]);
|
||||
const checkedKeys = ref<Array<any>>([]);
|
||||
const lastCheckedKeys = ref<Array<any>>([]);
|
||||
const checkStrictly = ref(true);
|
||||
|
||||
// 注册数据规则授权弹窗抽屉
|
||||
const [registerDataRuleDrawer, dataRuleDrawer] = useDrawer();
|
||||
|
||||
// onCreated
|
||||
loadData();
|
||||
watch(departId, () => loadDepartPermission(), { immediate: true });
|
||||
|
||||
async function loadData() {
|
||||
try {
|
||||
loading.value = true;
|
||||
let { treeList } = await queryRoleTreeList();
|
||||
treeData.value = treeList;
|
||||
await nextTick();
|
||||
toggleExpandAll(true);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDepartPermission() {
|
||||
if (departId.value) {
|
||||
try {
|
||||
loading.value = true;
|
||||
let keys = await queryDepartPermission({ departId: departId.value });
|
||||
checkedKeys.value = keys;
|
||||
lastCheckedKeys.value = [...keys];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
try {
|
||||
loading.value = true;
|
||||
await saveDepartPermission({
|
||||
departId: departId.value,
|
||||
permissionIds: checkedKeys.value.join(','),
|
||||
lastpermissionIds: lastCheckedKeys.value.join(','),
|
||||
});
|
||||
await loadData();
|
||||
await loadDepartPermission();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// tree勾选复选框事件
|
||||
function onCheck(event) {
|
||||
if (!Array.isArray(event)) {
|
||||
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, { departId, functionId });
|
||||
}
|
||||
selectedKeys.value = [];
|
||||
}
|
||||
|
||||
// 切换父子关联
|
||||
async function toggleCheckStrictly(flag) {
|
||||
checkStrictly.value = flag;
|
||||
await nextTick();
|
||||
checkedKeys.value = basicTree.value.getCheckedKeys();
|
||||
}
|
||||
|
||||
// 切换展开收起
|
||||
async function toggleExpandAll(flag) {
|
||||
basicTree.value.expandAll(flag);
|
||||
await nextTick();
|
||||
expandedKeys.value = basicTree.value.getExpandedKeys();
|
||||
}
|
||||
|
||||
// 切换全选
|
||||
async function toggleCheckALL(flag) {
|
||||
basicTree.value.checkAll(flag);
|
||||
await nextTick();
|
||||
checkedKeys.value = basicTree.value.getCheckedKeys();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
// 【VUEN-188】解决滚动条不灵敏的问题
|
||||
.depart-rule-tree :deep(.scrollbar__bar) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/*begin 兼容暗夜模式*/
|
||||
.j-box-bottom-button-float {
|
||||
background-color: @component-background;
|
||||
border-top: 1px solid @border-color-base;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
</style>
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<BasicDrawer width="800px" :title="isUpdate ? '修改部门管理员' : '添加部门管理员'" @register="registerModal" destroyOnClose @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm">
|
||||
<template #roles="{ model, field }">
|
||||
<a-input v-model:value="model[field]" readonly style="cursor: pointer" @click="clickShowTransfer" />
|
||||
</template>
|
||||
</BasicForm>
|
||||
<transfer-modal @register="registerTransferModal" :orgInfo="{ orgCode: props.orgCode, departId: props.departId }" @success="handleSuccess" />
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicForm from '/@/components/Form/src/BasicForm.vue';
|
||||
import { useForm } from '/@/components/Form';
|
||||
import { ref } from 'vue';
|
||||
import { formSchema } from '/@/views/system/depart/components/departManage/departManageList.data';
|
||||
import BasicDrawer from '/@/components/Drawer/src/BasicDrawer.vue';
|
||||
import { useDrawerInner } from '/@/components/Drawer';
|
||||
import { addUserEndowDepartManager } from '/@/views/system/depart/components/departManage/departManageList.api';
|
||||
import TransferModal from '/@/views/system/depart/components/departManage/components/transferModal.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { dealPassword } from '/@/views/system/user/user.data';
|
||||
|
||||
const props = defineProps({
|
||||
orgCode: { type: String, default: () => '' },
|
||||
departId: { type: String, default: () => '' },
|
||||
});
|
||||
|
||||
const [registerTransferModal, { openModal }] = useModal();
|
||||
|
||||
const roleCodes = ref<string>('');
|
||||
const listData = ref<Array<any>>([]);
|
||||
|
||||
const isUpdate = ref<boolean>(false);
|
||||
const emit = defineEmits(['success']);
|
||||
|
||||
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
|
||||
//labelWidth: 150,
|
||||
schemas: formSchema(isUpdate.value),
|
||||
showActionButtonGroup: false,
|
||||
baseColProps: { span: 24 },
|
||||
});
|
||||
|
||||
const [registerModal, { closeDrawer, setDrawerProps }] = useDrawerInner(async (data) => {
|
||||
await resetFields();
|
||||
roleCodes.value = '';
|
||||
listData.value = [];
|
||||
setDrawerProps({ confirmLoading: false, showFooter: data.showFooter, showOkBtn: data.showFooter, showCancelBtn: data.showFooter });
|
||||
// listData.value = [];
|
||||
// isUpdate.value = data.isUpdate;
|
||||
//
|
||||
// if (unref(isUpdate)) {
|
||||
// await setFieldsValue({
|
||||
// ...data.record,
|
||||
// });
|
||||
// await clearValidate();
|
||||
// }
|
||||
});
|
||||
|
||||
function clickShowTransfer() {
|
||||
openModal(true, {
|
||||
list: listData.value,
|
||||
});
|
||||
}
|
||||
|
||||
function preSubmit(values) {
|
||||
return {
|
||||
...values,
|
||||
extension: values,
|
||||
};
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
const values = await validate();
|
||||
setDrawerProps({ confirmLoading: true });
|
||||
// if (!values.birthday) {
|
||||
// values.birthday = values.idCard.substring(6, 10) + '-' + values.idCard.substring(10, 12) + '-' + values.idCard.substring(12, 14);
|
||||
// }
|
||||
// values['orgCode'] = props.orgCode;
|
||||
// setDrawerProps({ confirmLoading: true });
|
||||
// //提交表单
|
||||
values['roleCodes'] = roleCodes.value;
|
||||
values['orgCode'] = props.orgCode;
|
||||
values['password'] = dealPassword(values['password']);
|
||||
await addUserEndowDepartManager(values);
|
||||
closeDrawer();
|
||||
//刷新列表
|
||||
emit('success');
|
||||
} finally {
|
||||
setDrawerProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
|
||||
function handleSuccess(list) {
|
||||
listData.value = list;
|
||||
let ids = '';
|
||||
let names = '';
|
||||
list.map((item, index) => {
|
||||
item = JSON.parse(item);
|
||||
if (index === 0) {
|
||||
ids += item.id;
|
||||
names += item.roleCode;
|
||||
} else {
|
||||
ids += ',' + item.id;
|
||||
names += ',' + item.roleCode;
|
||||
}
|
||||
});
|
||||
|
||||
setFieldsValue({
|
||||
roles: names,
|
||||
});
|
||||
roleCodes.value = ids;
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
:deep(.ant-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
.question-choose {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
&:before {
|
||||
content: '';
|
||||
width: 36%;
|
||||
height: 1px;
|
||||
background-color: #000000;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
width: 36%;
|
||||
height: 1px;
|
||||
background-color: #000000;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
}
|
||||
}
|
||||
:deep(.ant-col-sm-18) {
|
||||
max-width: 100%;
|
||||
}
|
||||
:deep(.input-number .ant-input-number-input-wrap input) {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<BasicDrawer width="50%" title="选择用户" @register="registerModal" destroyOnClose @close="handleClose">
|
||||
<BasicTable @register="registerTable">
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<transfer-modal @register="registerTransferModal" :orgInfo="{ orgCode: props.orgCode, departId: props.departId }" @success="handleSuccess" />
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicTable from '/@/components/Table/src/BasicTable.vue';
|
||||
import BasicDrawer from '/@/components/Drawer/src/BasicDrawer.vue';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { noManagerUsers } from '/@/views/system/depart/components/departManage/departManageList.api';
|
||||
import { selectColumns, searchFormSchemaSelect } from '/@/views/system/depart/components/departManage/departManageList.data';
|
||||
import { useDrawerInner } from '/@/components/Drawer';
|
||||
import { TableAction } from '/@/components/Table';
|
||||
import TransferModal from '/@/views/system/depart/components/departManage/components/transferModal.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
|
||||
const props = defineProps({
|
||||
orgCode: { type: String, default: () => '' },
|
||||
departId: { type: String, default: () => '' },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['reloadTable']);
|
||||
|
||||
const [registerTransferModal, { openModal }] = useModal();
|
||||
|
||||
//注册table数据
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '员工',
|
||||
api: noManagerUsers,
|
||||
columns: selectColumns,
|
||||
canResize: false,
|
||||
clickToRowSelect: false,
|
||||
beforeFetch: (params) => {
|
||||
if (params['orgCode2']) {
|
||||
params['orgCode'] = params['orgCode2'];
|
||||
} else {
|
||||
params['orgCode'] = params['orgCode1'];
|
||||
}
|
||||
return params;
|
||||
},
|
||||
formConfig: {
|
||||
//labelWidth: 120,
|
||||
schemas: searchFormSchemaSelect,
|
||||
autoSubmitOnEnter: true,
|
||||
showAdvancedButton: false,
|
||||
fieldMapToNumber: [],
|
||||
fieldMapToTime: [],
|
||||
labelWidth: 100,
|
||||
baseColProps: {
|
||||
xs: 12,
|
||||
sm: 12,
|
||||
md: 8,
|
||||
lg: 8,
|
||||
xl: 8,
|
||||
xxl: 8,
|
||||
},
|
||||
actionColOptions: {
|
||||
style: {
|
||||
paddingLeft: '104px',
|
||||
},
|
||||
span: 24,
|
||||
offset: 0,
|
||||
xs: 12,
|
||||
sm: 12,
|
||||
md: 8,
|
||||
lg: 8,
|
||||
xl: 8,
|
||||
xxl: 8,
|
||||
},
|
||||
},
|
||||
actionColumn: {
|
||||
width: 80,
|
||||
fixed: 'right',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
|
||||
function getTableAction(record: Recordable) {
|
||||
return [
|
||||
{
|
||||
label: record.departId && record.departId.includes(props.departId) ? '修改' : '绑定',
|
||||
onClick: handleBind.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const [registerModal, { closeDrawer }] = useDrawerInner(async () => {
|
||||
selectedRowKeys.value = [];
|
||||
});
|
||||
|
||||
function handleBind(record: Recordable) {
|
||||
openModal(true, {
|
||||
record,
|
||||
});
|
||||
// if (!props.orgCode) {
|
||||
// return message.error('请选择需要管理的部门');
|
||||
// }
|
||||
//
|
||||
// relevanceDepartManager(props.orgCode, data).then(() => {
|
||||
// closeDrawer();
|
||||
// emit('reloadTable');
|
||||
// });
|
||||
}
|
||||
|
||||
function handleSuccess() {
|
||||
reload();
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
emit('reloadTable');
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
:deep(.ant-form-item-control-input-content) {
|
||||
//display: flex;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<BasicModal @register="transferModal" destroyOnClose @ok="handleSubmit" zIndex="1002" width="700px" title="选择角色">
|
||||
<div style="display: flex; align-items: center; justify-content: center">
|
||||
<a-transfer
|
||||
v-model:target-keys="targetKeys"
|
||||
v-model:selected-keys="selectedKeys"
|
||||
:data-source="mockData"
|
||||
show-search
|
||||
:list-style="{
|
||||
width: '250px',
|
||||
height: '500px',
|
||||
}"
|
||||
:filter-option="filterOption"
|
||||
:titles="['无权限', '已有权限']"
|
||||
:render="(item) => item.roleName"
|
||||
@change="handleChange"
|
||||
@select-change="handleSelectChange"
|
||||
@scroll="handleScroll"
|
||||
/>
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicModal from '/@/components/Modal/src/BasicModal.vue';
|
||||
import { ref } from 'vue';
|
||||
import { addManagerDepartAndEndowRole, listCustom, userRoles } from '/@/views/system/depart/components/departManage/departManageList.api';
|
||||
import { useModalInner } from '/@/components/Modal';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
||||
const props = defineProps({
|
||||
orgInfo: propTypes.object.def({ orgCode: '', departId: '' }),
|
||||
});
|
||||
|
||||
const userId = ref<string>('');
|
||||
const targetKeys = ref<Array<any>>([]);
|
||||
const selectedKeys = ref<Array<any>>([]);
|
||||
const mockData = ref<Array<any>>([]);
|
||||
const emit = defineEmits(['success']);
|
||||
|
||||
const [transferModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
selectedKeys.value = [];
|
||||
mockData.value = [];
|
||||
userId.value = data?.record?.userId;
|
||||
targetKeys.value = userId.value ? [] : data.list;
|
||||
const { records } = await listCustom({ pageNo: 1, pageSize: 9999, systemFlag: false });
|
||||
let haveList = [];
|
||||
if (userId.value) {
|
||||
haveList = await userRoles({ userId: data.record.userId, pageNo: 1, pageSize: 9999 });
|
||||
}
|
||||
mockData.value = records.map((item: any) => {
|
||||
// targetKeys.value?.push(item.roleCode);
|
||||
if (haveList.includes(item.roleCode)) {
|
||||
targetKeys.value?.push(item.id);
|
||||
}
|
||||
// selectedKeys.value?.push(item.id);
|
||||
return { ...{ key: userId.value ? item.id : JSON.stringify({ id: item.id, roleCode: item.roleName }) }, ...item };
|
||||
});
|
||||
});
|
||||
|
||||
function handleChange() {}
|
||||
function handleSelectChange() {}
|
||||
function handleScroll() {}
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
if (userId.value) {
|
||||
let params = {
|
||||
...props.orgInfo,
|
||||
userId: userId.value,
|
||||
roleIds: targetKeys.value,
|
||||
};
|
||||
setModalProps({ confirmLoading: true });
|
||||
await addManagerDepartAndEndowRole(params);
|
||||
closeModal();
|
||||
emit('success');
|
||||
} else {
|
||||
closeModal();
|
||||
emit('success', targetKeys.value);
|
||||
}
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
function filterOption(inputValue: string, option) {
|
||||
return option.roleName.indexOf(inputValue) > -1;
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less"></style>
|
||||
@@ -0,0 +1,28 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
list = '/health-system/sys/sysDepart/departManagers',
|
||||
addDepartManager = '/health-system/sys/healthUserEmployeeEx/addDepartManager',
|
||||
// noManagerUsers = '/health-system/sys/user/noManagerUsers',
|
||||
noManagerUsers = '/health-system/sys/user/listUser',
|
||||
listCustom = '/health-system/sys/role/listCustom',
|
||||
userRoles = '/health-system/sys/user/userRoles',
|
||||
relevanceDepartManager = '/health-system/sys/sysDepart/relevanceDepartManager',
|
||||
cancelDepartManager = '/health-system/sys/sysDepart/cancelDepartManager',
|
||||
addManagerDepartAndEndowRole = '/health-system/sys/role/addManagerDepartAndEndowRole',
|
||||
addUserEndowDepartManager = '/health-system/sys/user/addUserEndowDepartManager',
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
export const list = (params) => defHttp.get({ url: Api.list, params });
|
||||
export const noManagerUsers = (params) => defHttp.get({ url: Api.noManagerUsers, params });
|
||||
export const listCustom = (params) => defHttp.get({ url: Api.listCustom, params });
|
||||
export const userRoles = (params) => defHttp.get({ url: Api.userRoles, params });
|
||||
export const addManagerDepartAndEndowRole = (params) => defHttp.post({ url: Api.addManagerDepartAndEndowRole, params });
|
||||
export const addUserEndowDepartManager = (params) => defHttp.post({ url: Api.addUserEndowDepartManager, params });
|
||||
export const addDepartManager = (params) => defHttp.post({ url: Api.addDepartManager, params });
|
||||
export const relevanceDepartManager = (orgCode, params) => defHttp.post({ url: Api.relevanceDepartManager + '?orgCode=' + orgCode, params });
|
||||
export const cancelDepartManager = (orgCode, params) => defHttp.post({ url: Api.cancelDepartManager + '?orgCode=' + orgCode, params });
|
||||
@@ -0,0 +1,250 @@
|
||||
import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||
import { getSecondaryDepartmentList, getThirdDepartmentList } from '/@/views/system/user/user.api';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { checkPassword } from '/@/hooks/checkPassword/checkPassword';
|
||||
//列表数据
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '员工账号',
|
||||
align: 'center',
|
||||
dataIndex: 'userName',
|
||||
},
|
||||
{
|
||||
title: '员工姓名',
|
||||
align: 'center',
|
||||
dataIndex: 'realName',
|
||||
},
|
||||
// {
|
||||
// title: '员工编号',
|
||||
// align: 'center',
|
||||
// dataIndex: 'workNo',
|
||||
// },
|
||||
{
|
||||
title: '单位名称',
|
||||
align: 'center',
|
||||
dataIndex: 'secondDepart',
|
||||
},
|
||||
{
|
||||
title: '部门名称',
|
||||
align: 'center',
|
||||
dataIndex: 'depart',
|
||||
},
|
||||
];
|
||||
export const selectColumns: BasicColumn[] = [
|
||||
{
|
||||
title: '员工账号',
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
dataIndex: 'userName',
|
||||
},
|
||||
{
|
||||
title: '员工姓名',
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
dataIndex: 'realName',
|
||||
},
|
||||
// {
|
||||
// title: '员工编号',
|
||||
// align: 'center',
|
||||
// dataIndex: 'workNo',
|
||||
// },
|
||||
{
|
||||
title: '单位名称',
|
||||
align: 'center',
|
||||
dataIndex: 'secondDepart',
|
||||
},
|
||||
{
|
||||
title: '部门名称',
|
||||
align: 'center',
|
||||
dataIndex: 'depart',
|
||||
},
|
||||
];
|
||||
|
||||
//查询数据
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
label: '员工姓名',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
},
|
||||
];
|
||||
export const searchFormSchemaSelect: FormSchema[] = [
|
||||
{
|
||||
label: '单位',
|
||||
field: 'orgCode1',
|
||||
component: 'ApiSelect',
|
||||
componentProps: ({ formModel }) => {
|
||||
return {
|
||||
api: getSecondaryDepartmentList,
|
||||
resultField: 'result',
|
||||
labelField: 'departName',
|
||||
valueField: 'orgCode',
|
||||
immediate: true,
|
||||
onChange: (_value, option) => {
|
||||
formModel.secondOrgId = option?.id || '';
|
||||
formModel.secondOrgCode = option?.orgCode || '';
|
||||
if (formModel?.thirdOrgId) {
|
||||
formModel.thirdOrgId = '';
|
||||
formModel.thirdOrgCode = '';
|
||||
}
|
||||
},
|
||||
onDeselect: () => {
|
||||
formModel.thirdOrgId = '';
|
||||
formModel.thirdOrgCode = '';
|
||||
},
|
||||
showSearch: true,
|
||||
filterOption: (input: string, option: any): boolean => {
|
||||
const str: string = input.toLowerCase();
|
||||
return option.label.toLowerCase().indexOf(str) >= 0;
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '部门',
|
||||
field: 'orgCode2',
|
||||
component: 'ApiSelect',
|
||||
componentProps: ({ formModel }) => {
|
||||
return {
|
||||
api: getThirdDepartmentList,
|
||||
resultField: 'list',
|
||||
labelField: 'departName',
|
||||
params: {
|
||||
secondDepartId: formModel?.secondOrgId || 'defghjkl',
|
||||
},
|
||||
valueField: 'orgCode',
|
||||
immediate: false,
|
||||
onChange: (_value, option) => {
|
||||
formModel.thirdOrgId = option?.id || '';
|
||||
formModel.thirdOrgCode = option?.orgCode || '';
|
||||
},
|
||||
onDeselect: () => {
|
||||
formModel.thirdOrgId = '';
|
||||
formModel.thirdOrgCode = '';
|
||||
},
|
||||
onFocus: () => {
|
||||
if (!formModel.secondOrgId) {
|
||||
return message.warn('请先选择单位!');
|
||||
}
|
||||
},
|
||||
showSearch: true,
|
||||
filterOption: (input: string, option: any): boolean => {
|
||||
const str: string = input.toLowerCase();
|
||||
return option.label.toLowerCase().indexOf(str) >= 0;
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '员工姓名',
|
||||
field: 'realName',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '员工编号',
|
||||
field: 'workNo',
|
||||
component: 'Input',
|
||||
},
|
||||
];
|
||||
|
||||
//表单数据
|
||||
export const schema: FormSchema[] = [
|
||||
{
|
||||
label: '员工姓名',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
},
|
||||
];
|
||||
|
||||
export const formSchema: (isUpdate: boolean) => FormSchema[] = (isUpdate) => {
|
||||
return [
|
||||
{
|
||||
label: '用户账号',
|
||||
field: 'username',
|
||||
component: 'Input',
|
||||
componentProps: ({ formModel }) => {
|
||||
return {
|
||||
onInput: () => {
|
||||
formModel.username = formModel.username.replace(/[^a-zA-Z0-9_]/g, '');
|
||||
},
|
||||
autocomplete: 'off',
|
||||
};
|
||||
},
|
||||
required: true,
|
||||
dynamicDisabled: isUpdate,
|
||||
},
|
||||
{
|
||||
label: '密码',
|
||||
field: 'password',
|
||||
component: 'StrengthMeter',
|
||||
componentProps: {
|
||||
autocomplete: 'new-password',
|
||||
},
|
||||
dynamicRules: () => {
|
||||
return [
|
||||
{
|
||||
required: true,
|
||||
validator: (_, value) => {
|
||||
let { message } = checkPassword(value);
|
||||
if (message === 'ok') {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject(message);
|
||||
}
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
];
|
||||
},
|
||||
required: !isUpdate,
|
||||
show: !isUpdate,
|
||||
},
|
||||
{
|
||||
label: '姓名',
|
||||
field: 'realname',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: '员工编号', // 原来为工号
|
||||
field: 'workNo',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
ifShow: false,
|
||||
},
|
||||
{
|
||||
label: '角色',
|
||||
field: 'roles',
|
||||
component: 'Input',
|
||||
slot: 'roles',
|
||||
required: true,
|
||||
},
|
||||
// {
|
||||
// label: '部门',
|
||||
// field: 'orgCode',
|
||||
// component: 'JSelectDeptStaff',
|
||||
// componentProps: ({ formModel }) => {
|
||||
// return {
|
||||
// sync: true,
|
||||
// checkStrictly: true,
|
||||
// defaultExpandLevel: 1,
|
||||
// initOptions: isUpdate
|
||||
// ? [
|
||||
// {
|
||||
// value: formModel.departId,
|
||||
// label: ' ' + formModel.secondDepartName + ' - ' + formModel.departName + ' ',
|
||||
// },
|
||||
// ]
|
||||
// : [],
|
||||
// };
|
||||
// },
|
||||
// required: true,
|
||||
// },
|
||||
{
|
||||
label: '',
|
||||
field: 'id',
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
];
|
||||
};
|
||||
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--引用表格-->
|
||||
<BasicTable :rowSelection="rowSelection" @register="registerTable">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button preIcon="ant-design:plus-outlined" type="primary" v-auth="'system:depart-manage-list:add'" @click="handleAdd">
|
||||
新增
|
||||
</a-button>
|
||||
<a-button type="primary" @click="selectUser">选择用户</a-button>
|
||||
<a-button type="primary" @click="largeUnbind">批量解绑</a-button>
|
||||
</template>
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!-- 表单区域 -->
|
||||
<depart-manage-list-drawer @register="registerModal" @success="handleSuccess" :orgCode="props.data?.orgCode" />
|
||||
<select-no-manager @register="registerModal1" @reloadTable="handleSuccess" :orgCode="props.data?.orgCode" :departId="props.data?.id" />
|
||||
<RestPass @register="restPassModal" />
|
||||
|
||||
<transfer-modal
|
||||
@register="registerTransferModal"
|
||||
:orgInfo="{ orgCode: props.data?.orgCode, departId: props.data?.id }"
|
||||
@success="handleSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { columns, searchFormSchema } from './departManageList.data';
|
||||
import { list, cancelDepartManager } from './departManageList.api';
|
||||
import DepartManageListDrawer from '/@/views/system/depart/components/departManage/components/departManageListDrawer.vue';
|
||||
import SelectNoManager from '/@/views/system/depart/components/departManage/components/selectNoManager.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import RestPass from '/@/views/system/user/restPass/RestPass.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import TransferModal from '/@/views/system/depart/components/departManage/components/transferModal.vue';
|
||||
const [registerModal, { openDrawer }] = useDrawer();
|
||||
const [registerModal1, { openDrawer: openDrawer1 }] = useDrawer();
|
||||
const [restPassModal, { openModal: restPassModel }] = useModal();
|
||||
const [registerTransferModal, { openModal: openModal1 }] = useModal();
|
||||
const showFooter = ref(true);
|
||||
|
||||
function selectUser() {
|
||||
openDrawer1(true);
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
data: { type: Object, default: () => ({}) },
|
||||
});
|
||||
watch(
|
||||
() => props.data?.orgCode,
|
||||
() => {
|
||||
reload({ page: 1 });
|
||||
}
|
||||
);
|
||||
//注册table数据
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '员工',
|
||||
api: list,
|
||||
rowKey: 'userId',
|
||||
columns,
|
||||
canResize: false,
|
||||
clickToRowSelect: false,
|
||||
beforeFetch: (params) => {
|
||||
params['orgCode'] = props.data?.orgCode;
|
||||
return params;
|
||||
},
|
||||
formConfig: {
|
||||
labelWidth: 100,
|
||||
schemas: searchFormSchema,
|
||||
autoSubmitOnEnter: true,
|
||||
showAdvancedButton: false,
|
||||
fieldMapToNumber: [],
|
||||
fieldMapToTime: [],
|
||||
baseColProps: {
|
||||
xs: 8, // <576px
|
||||
sm: 8, // ≥576px
|
||||
md: 8, // ≥768px
|
||||
lg: 8, // ≥992px
|
||||
xl: 12, // ≥1200px
|
||||
xxl: 12, // ≥1600px
|
||||
},
|
||||
actionColOptions: {
|
||||
offset: 0,
|
||||
span: 8,
|
||||
xs: 8, // <576px
|
||||
sm: 8, // ≥576px
|
||||
md: 8, // ≥768px
|
||||
lg: 8, // ≥992px
|
||||
xl: 12, // ≥1200px
|
||||
xxl: 12, // ≥1600px
|
||||
},
|
||||
},
|
||||
actionColumn: {
|
||||
width: 170,
|
||||
fixed: 'right',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
/**
|
||||
* 新增事件
|
||||
*/
|
||||
function handleAdd() {
|
||||
showFooter.value = true;
|
||||
openDrawer(true, {
|
||||
isUpdate: false,
|
||||
showFooter: true,
|
||||
type: '新增',
|
||||
});
|
||||
}
|
||||
function handleUnBind(d) {
|
||||
let orgCode = props.data?.orgCode;
|
||||
if (!orgCode) {
|
||||
return message.error('请选择需要管理的部门');
|
||||
}
|
||||
cancelDepartManager(orgCode, d).then(() => {
|
||||
reload();
|
||||
});
|
||||
}
|
||||
function largeUnbind() {
|
||||
if (selectedRowKeys.value.length === 0) return message.info('请至少选择一条数据');
|
||||
handleUnBind(selectedRowKeys.value);
|
||||
}
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
(selectedRowKeys.value = []) && reload();
|
||||
}
|
||||
// 修改密码弹窗
|
||||
function restPass(record) {
|
||||
restPassModel(true, {
|
||||
record: record.userId,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 下拉操作栏
|
||||
*/
|
||||
function getAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '修改',
|
||||
onClick: handleEditBind.bind(null, record),
|
||||
},
|
||||
{
|
||||
label: '解绑',
|
||||
onClick: handleUnBind.bind(null, [record.userId]),
|
||||
},
|
||||
{
|
||||
label: '重置密码',
|
||||
onClick: restPass.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function handleEditBind(record: Recordable) {
|
||||
openModal1(true, {
|
||||
record,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,95 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const { createConfirm } = useMessage();
|
||||
|
||||
enum Api {
|
||||
list = '/health-system/sys/sysDepart/departUsers',
|
||||
save = '/sys/healthUserEmployeeEx/add',
|
||||
edit = '/sys/healthUserEmployeeEx/edit',
|
||||
deleteOne = '/sys/healthUserEmployeeEx/delete',
|
||||
deleteBatch = '/sys/healthUserEmployeeEx/deleteBatch',
|
||||
importExcel = '/sys/healthUserEmployeeEx/importExcel',
|
||||
exportXls = '/sys/healthUserEmployeeEx/exportXls',
|
||||
queryById = '/sys/healthUserEmployeeEx/queryById',
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出api
|
||||
* @param params
|
||||
*/
|
||||
export const getExportUrl = Api.exportXls;
|
||||
|
||||
export const queryByIdUrl = Api.queryById;
|
||||
|
||||
/**
|
||||
* 请求编辑数据
|
||||
*/
|
||||
export const resEditData = async (params) => {
|
||||
return await defHttp.get({ url: Api.queryById, params }, { joinParamsToUrl: true });
|
||||
};
|
||||
|
||||
/**
|
||||
* 导入api
|
||||
*/
|
||||
export const getImportUrl = Api.importExcel;
|
||||
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
export const list = (params) => defHttp.get({ url: Api.list, params });
|
||||
|
||||
/**
|
||||
* 删除单个
|
||||
*/
|
||||
export const deleteOne = (params, handleSuccess) => {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '确认删除',
|
||||
content: '是否确认删除',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
return defHttp
|
||||
.delete(
|
||||
{
|
||||
url: Api.deleteOne,
|
||||
data: params,
|
||||
},
|
||||
{ joinParamsToUrl: true }
|
||||
)
|
||||
.then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
* @param params
|
||||
*/
|
||||
export const batchDelete = (params, handleSuccess) => {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '确认删除',
|
||||
content: '是否删除选中数据',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 保存或者更新
|
||||
* @param params
|
||||
*/
|
||||
export const saveOrUpdate = (params, isUpdate) => {
|
||||
const url = isUpdate ? Api.edit : Api.save;
|
||||
return defHttp.post({ url: url, params });
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||
import { h } from 'vue';
|
||||
import { Image, message } from 'ant-design-vue';
|
||||
import { getDefaultImage, getFileAccessHttpUrl } from '/@/utils/common/compUtils';
|
||||
import { getSecondaryDepartmentList, getThirdDepartmentList } from '/@/views/system/user/user.api';
|
||||
//列表数据
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '用户账号',
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
dataIndex: 'username',
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
dataIndex: 'realname',
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
align: 'center',
|
||||
dataIndex: 'sex_dictText',
|
||||
width: 64,
|
||||
},
|
||||
{
|
||||
title: '身份证号',
|
||||
align: 'center',
|
||||
dataIndex: 'idCard',
|
||||
width: 160,
|
||||
},
|
||||
];
|
||||
|
||||
//查询数据
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
label: '用户账号',
|
||||
field: 'username',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '用户姓名',
|
||||
field: 'realname',
|
||||
component: 'Input',
|
||||
},
|
||||
];
|
||||
|
||||
//表单数据
|
||||
@@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable">
|
||||
<!--插槽:table标题-->
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!-- 表单区域 -->
|
||||
<!-- 重置密码 -->
|
||||
<RestPass @register="restPassModal" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, unref, watch } from 'vue';
|
||||
import { BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { columns, searchFormSchema } from './departUserList.data';
|
||||
import { batchDelete, deleteOne, getExportUrl, getImportUrl, list, resEditData } from './departUserList.api';
|
||||
import { message } from 'ant-design-vue';
|
||||
import RestPass from '/@/views/system/user/restPass/RestPass.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { lockUser } from '/@/views/system/user/hospitalDoctor/HospitalDoctor.api';
|
||||
const [registerDrawer, { openDrawer }] = useDrawer();
|
||||
const [restPassModal, { openModal: restPaddModel }] = useModal();
|
||||
const showFooter = ref(true);
|
||||
|
||||
const props = defineProps({
|
||||
data: { type: Object, default: () => ({}) },
|
||||
});
|
||||
watch(
|
||||
() => props.data?.orgCode,
|
||||
() => {
|
||||
reload();
|
||||
}
|
||||
);
|
||||
//注册table数据
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
title: '员工',
|
||||
api: list,
|
||||
columns,
|
||||
canResize: false,
|
||||
clickToRowSelect: false,
|
||||
formConfig: {
|
||||
//labelWidth: 120,
|
||||
schemas: searchFormSchema,
|
||||
autoSubmitOnEnter: true,
|
||||
showAdvancedButton: false,
|
||||
fieldMapToNumber: [],
|
||||
fieldMapToTime: [],
|
||||
actionColOptions: {
|
||||
offset: 0,
|
||||
span: 8,
|
||||
xs: 8, // <576px
|
||||
sm: 8, // ≥576px
|
||||
md: 8, // ≥768px
|
||||
lg: 8, // ≥992px
|
||||
xl: 8, // ≥1200px
|
||||
xxl: 8, // ≥1600px
|
||||
},
|
||||
},
|
||||
actionColumn: {
|
||||
width: 80,
|
||||
fixed: 'right',
|
||||
},
|
||||
},
|
||||
exportConfig: {
|
||||
name: '员工',
|
||||
url: getExportUrl,
|
||||
},
|
||||
importConfig: {
|
||||
url: getImportUrl,
|
||||
success: handleSuccess,
|
||||
},
|
||||
});
|
||||
|
||||
const [registerTable, { reload }, { selectedRowKeys }] = tableContext;
|
||||
/**
|
||||
* 新增事件
|
||||
*/
|
||||
function handleAdd() {
|
||||
showFooter.value = true;
|
||||
openDrawer(true, {
|
||||
isUpdate: false,
|
||||
type: '新增',
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 编辑事件
|
||||
*/
|
||||
function handleEdit(record: Recordable, type) {
|
||||
showFooter.value = true;
|
||||
getEdit(record, type);
|
||||
}
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
function handleDetail(record: Recordable, type) {
|
||||
showFooter.value = false;
|
||||
getEdit(record, type);
|
||||
}
|
||||
/**
|
||||
* 获取编辑数据
|
||||
*/
|
||||
function getEdit(record, type) {
|
||||
resEditData({ id: record.id }).then((res) => {
|
||||
openDrawer(true, {
|
||||
record: {
|
||||
...res.extension,
|
||||
...res,
|
||||
orgCode: res?.depart?.id,
|
||||
departId: res?.depart?.id,
|
||||
departName: res?.depart?.departName,
|
||||
secondDepartName: res?.secondDepart?.departName,
|
||||
},
|
||||
type,
|
||||
isUpdate: true,
|
||||
showFooter: unref(showFooter),
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 删除事件
|
||||
*/
|
||||
async function handleDelete(record) {
|
||||
await deleteOne({ id: record.id }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 批量删除事件
|
||||
*/
|
||||
async function batchHandleDelete() {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
message.warning('未选中任何数据');
|
||||
return;
|
||||
}
|
||||
await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
(selectedRowKeys.value = []) && reload();
|
||||
}
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record) {
|
||||
return [];
|
||||
}
|
||||
// 重置密码
|
||||
function restPass(record) {
|
||||
restPaddModel(true, {
|
||||
record: record.id,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
});
|
||||
}
|
||||
// 1 锁定用户 2 激活用户
|
||||
async function handleUserOpt(record, type) {
|
||||
const params = {
|
||||
userId: record.id,
|
||||
status: type,
|
||||
};
|
||||
await lockUser(params, type, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 下拉操作栏
|
||||
*/
|
||||
function getDropDownAction(record) {
|
||||
return [
|
||||
// {
|
||||
// label: '编辑',
|
||||
// onClick: handleEdit.bind(null, record, '编辑'),
|
||||
// auth: 'system:health_user_employee_ex:edit',
|
||||
// },
|
||||
// {
|
||||
// label: '详情',
|
||||
// onClick: handleDetail.bind(null, record, '详情'),
|
||||
// },
|
||||
// {
|
||||
// label: '删除',
|
||||
// onClick: handleDelete.bind(null, record),
|
||||
// auth: 'system:health_user_employee_ex:delete',
|
||||
// },
|
||||
{
|
||||
label: '重置密码',
|
||||
onClick: restPass.bind(null, record),
|
||||
},
|
||||
{
|
||||
label: '锁定用户',
|
||||
auth: 'system:user:frozen',
|
||||
onClick: handleUserOpt.bind(null, record, 2),
|
||||
},
|
||||
{
|
||||
label: '激活用户',
|
||||
auth: 'system:user:frozen',
|
||||
onClick: handleUserOpt.bind(null, record, 1),
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.ant-table-title) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,125 @@
|
||||
import { unref } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const { createConfirm } = useMessage();
|
||||
|
||||
export enum Api {
|
||||
queryDepartTreeSync = '/sys/sysDepart/queryDepartTreeSync',
|
||||
save = '/sys/sysDepart/add',
|
||||
edit = '/sys/sysDepart/edit',
|
||||
delete = '/sys/sysDepart/delete',
|
||||
deleteBatch = '/sys/sysDepart/deleteBatch',
|
||||
exportXlsUrl = '/sys/sysDepart/exportXls',
|
||||
importExcelUrl = '/sys/sysDepart/importExcel',
|
||||
|
||||
roleQueryTreeList = '/sys/role/queryTreeList',
|
||||
queryDepartPermission = '/sys/permission/queryDepartPermission',
|
||||
saveDepartPermission = '/sys/permission/saveDepartPermission',
|
||||
|
||||
dataRule = '/sys/sysDepartPermission/datarule',
|
||||
|
||||
getCurrentUserDeparts = '/sys/user/getCurrentUserDeparts',
|
||||
selectDepart = '/sys/selectDepart',
|
||||
getUpdateDepartInfo = '/sys/user/getUpdateDepartInfo',
|
||||
doUpdateDepartInfo = '/sys/user/doUpdateDepartInfo',
|
||||
changeDepartChargePerson = '/sys/user/changeDepartChargePerson',
|
||||
departTree = '/sys/core/getDepartTree',
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门树列表
|
||||
*/
|
||||
export const queryDepartTreeSync = (params?) => defHttp.get({ url: Api.queryDepartTreeSync, params });
|
||||
|
||||
/**
|
||||
* 保存或者更新部门角色
|
||||
*/
|
||||
export const saveOrUpdateDepart = (params, isUpdate) => {
|
||||
if (isUpdate) {
|
||||
return defHttp.put({ url: Api.edit, params });
|
||||
} else {
|
||||
return defHttp.post({ url: Api.save, params });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量删除部门角色
|
||||
*/
|
||||
export const deleteBatchDepart = (params, confirm = false) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const doDelete = () => {
|
||||
resolve(defHttp.delete({ url: Api.deleteBatch, params }, { joinParamsToUrl: true }));
|
||||
};
|
||||
if (confirm) {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '删除',
|
||||
content: '确定要删除吗?',
|
||||
onOk: () => doDelete(),
|
||||
onCancel: () => reject(),
|
||||
});
|
||||
} else {
|
||||
doDelete();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取权限树列表
|
||||
*/
|
||||
export const queryRoleTreeList = (params?) => defHttp.get({ url: Api.roleQueryTreeList, params });
|
||||
/**
|
||||
* 查询部门权限
|
||||
*/
|
||||
export const queryDepartPermission = (params?) => defHttp.get({ url: Api.queryDepartPermission, params });
|
||||
/**
|
||||
* 保存部门权限
|
||||
*/
|
||||
export const saveDepartPermission = (params) => defHttp.post({ url: Api.saveDepartPermission, params });
|
||||
|
||||
/**
|
||||
* 查询部门数据权限列表
|
||||
*/
|
||||
export const queryDepartDataRule = (functionId, departId, params?) => {
|
||||
const url = `${Api.dataRule}/${unref(functionId)}/${unref(departId)}`;
|
||||
return defHttp.get({ url, params });
|
||||
};
|
||||
/**
|
||||
* 保存部门数据权限
|
||||
*/
|
||||
export const saveDepartDataRule = (params) => defHttp.post({ url: Api.dataRule, params });
|
||||
/**
|
||||
* 获取登录用户部门信息
|
||||
*/
|
||||
export const getUserDeparts = (params?) => defHttp.get({ url: Api.getCurrentUserDeparts, params });
|
||||
/**
|
||||
* 切换选择部门
|
||||
*/
|
||||
export const selectDepart = (params?) => defHttp.put({ url: Api.selectDepart, params });
|
||||
|
||||
/**
|
||||
* 编辑部门前获取部门相关信息
|
||||
* @param id
|
||||
*/
|
||||
export const getUpdateDepartInfo = (id) => defHttp.get({ url: Api.getUpdateDepartInfo, params: { id } });
|
||||
|
||||
/**
|
||||
* 编辑部门
|
||||
* @param params
|
||||
*/
|
||||
export const doUpdateDepartInfo = (params) => defHttp.put({ url: Api.doUpdateDepartInfo, params });
|
||||
|
||||
/**
|
||||
* 删除部门
|
||||
* @param id
|
||||
*/
|
||||
export const deleteDepart = (id) => defHttp.delete({ url: Api.delete, params: { id } }, { joinParamsToUrl: true });
|
||||
|
||||
/**
|
||||
* 设置负责人 取消负责人
|
||||
* @param params
|
||||
*/
|
||||
export const changeDepartChargePerson = (params) => defHttp.put({ url: Api.changeDepartChargePerson, params });
|
||||
|
||||
export const departTree = (params) => defHttp.get({ url: Api.departTree, params });
|
||||
@@ -0,0 +1,219 @@
|
||||
import { FormSchema } from '/@/components/Form';
|
||||
import { getDictCache } from '/@/utils/dict';
|
||||
import { isQH } from '/@/utils/getEnv';
|
||||
|
||||
function checkPhone(_, value) {
|
||||
const rule = /^[0-9,]+$/;
|
||||
if (value && !rule.test(value)) {
|
||||
return Promise.reject('只能输入数字和英文逗号!');
|
||||
}
|
||||
if (value?.length > 11) {
|
||||
const reg = /^1[3456789]\d{9}$/;
|
||||
const strs = value.split(',');
|
||||
for (let i = 0; i < strs.length; i++) {
|
||||
if (!reg.test(strs[i])) {
|
||||
return Promise.reject('第' + (i + 1) + '个手机号码格式不正确!');
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// 部门基础表单
|
||||
export function useBasicFormSchema() {
|
||||
const basicFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'departName',
|
||||
label: '机构名称',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入机构/部门名称',
|
||||
},
|
||||
rules: [{ required: true, message: '机构名称不能为空' }],
|
||||
},
|
||||
{
|
||||
field: 'parentId',
|
||||
label: '上级部门',
|
||||
component: 'TreeSelect',
|
||||
componentProps: {
|
||||
treeData: [],
|
||||
placeholder: '无',
|
||||
dropdownStyle: { maxHeight: '200px', overflow: 'auto' },
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'orgCode',
|
||||
label: '机构编码',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入机构编码',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'orgCategory',
|
||||
label: '机构类型',
|
||||
component: 'RadioButtonGroup',
|
||||
componentProps: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'orgClass',
|
||||
label: '机构分类',
|
||||
component: 'JDictSelectTag',
|
||||
defaultValue: '1',
|
||||
componentProps: () => {
|
||||
return {
|
||||
type: 'radio',
|
||||
dictCode: 'orgclass',
|
||||
allowClear: false,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'departOrder',
|
||||
label: '排序',
|
||||
component: 'InputNumber',
|
||||
componentProps: {},
|
||||
},
|
||||
{
|
||||
field: 'mobile',
|
||||
label: '电话',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入电话',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'fax',
|
||||
label: '传真',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入传真',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '健康管理员姓名',
|
||||
field: 'healthManageUserName',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '健康管理员电话',
|
||||
field: 'healthManageUserMobile',
|
||||
component: 'Input',
|
||||
componentProps: () => {
|
||||
return {
|
||||
placeholder: '请输入健康管理员电话,多个电话请用英文逗号隔开',
|
||||
};
|
||||
},
|
||||
dynamicRules: () => {
|
||||
return [
|
||||
{
|
||||
validator: checkPhone,
|
||||
trigger: 'blur',
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '健康管理员地址',
|
||||
field: 'healthManageUserAddress',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '职业体检管理员姓名',
|
||||
field: 'medialManageUserName',
|
||||
component: 'Input',
|
||||
show: !isQH(),
|
||||
},
|
||||
{
|
||||
label: '职业体检管理员电话',
|
||||
field: 'medialManageUserMobile',
|
||||
component: 'Input',
|
||||
show: !isQH(),
|
||||
componentProps: () => {
|
||||
return {
|
||||
placeholder: '请输入体检管理员电话,多个电话请用英文逗号隔开',
|
||||
};
|
||||
},
|
||||
dynamicRules: () => {
|
||||
return [
|
||||
{
|
||||
validator: checkPhone,
|
||||
trigger: 'blur',
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '职业体检管理员地址',
|
||||
field: 'medialManageUserAddress',
|
||||
component: 'Input',
|
||||
show: !isQH(),
|
||||
},
|
||||
{
|
||||
label: '健康监测管理员姓名',
|
||||
field: 'monitorManageUserName',
|
||||
component: 'Input',
|
||||
show: !isQH(),
|
||||
},
|
||||
{
|
||||
label: '健康监测管理员电话',
|
||||
field: 'monitorManageUserMobile',
|
||||
component: 'Input',
|
||||
componentProps: () => {
|
||||
return {
|
||||
placeholder: '请输入健康监测管理员电话,多个电话请用英文逗号隔开',
|
||||
};
|
||||
},
|
||||
show: !isQH(),
|
||||
dynamicRules: () => {
|
||||
return [
|
||||
{
|
||||
validator: checkPhone,
|
||||
trigger: 'blur',
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '详细地址',
|
||||
field: 'address',
|
||||
component: 'Input',
|
||||
slot: 'addressInfo',
|
||||
// required: true,
|
||||
},
|
||||
{
|
||||
label: '经度',
|
||||
field: 'lng',
|
||||
component: 'InputNumber',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
label: '纬度',
|
||||
field: 'lat',
|
||||
component: 'InputNumber',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
field: 'memo',
|
||||
label: '备注',
|
||||
component: 'InputTextArea',
|
||||
componentProps: {
|
||||
placeholder: '请输入备注',
|
||||
},
|
||||
},
|
||||
];
|
||||
return { basicFormSchema };
|
||||
}
|
||||
|
||||
// 机构类型选项
|
||||
export const orgCategoryOptions = {
|
||||
// 一级部门
|
||||
root: [{ value: '1', label: '公司' }],
|
||||
// 子级部门
|
||||
child: [
|
||||
{ value: '2', label: '部门' },
|
||||
{ value: '3', label: '岗位' },
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
//noinspection LessUnresolvedVariable
|
||||
@prefix-cls: ~'@{namespace}-depart-manage';
|
||||
|
||||
.@{prefix-cls} {
|
||||
&--box {
|
||||
.ant-tabs-nav {
|
||||
padding: 0 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<div class="outer">
|
||||
<div class="inner">
|
||||
<a-row :class="['p-4', `${prefixCls}--box`]" type="flex" :gutter="10" style="height: 100%">
|
||||
<a-col :xl="12" :lg="24" :md="24" class="col-l">
|
||||
<DepartLeftTree ref="leftTree" @select="onTreeSelect" @rootTreeData="onRootTreeData" />
|
||||
</a-col>
|
||||
<a-col :xl="12" :lg="24" :md="24" class="col-r">
|
||||
<div style="height: 100%" class="depart-manage">
|
||||
<a-tabs v-show="departData != null" v-model:activeKey="activeKey" defaultActiveKey="base-info">
|
||||
<a-tab-pane tab="基本信息" key="base-info" forceRender style="position: relative">
|
||||
<div style="padding: 20px; overflow: hidden; background-color: #ffffff">
|
||||
<DepartFormTab :data="departData" :rootTreeData="rootTreeData" @success="onSuccess" />
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<!-- <a-tab-pane tab="部门权限" key="role-info">-->
|
||||
<!-- <div style="padding: 0 20px 20px">-->
|
||||
<!-- <DepartRuleTab :data="departData" />-->
|
||||
<!-- </div>-->
|
||||
<!-- </a-tab-pane>-->
|
||||
<a-tab-pane
|
||||
tab="部门管理员"
|
||||
key="depart-manage"
|
||||
v-if="(hasPermission(orgManageApi.departManageList) && manager) || hasPer"
|
||||
>
|
||||
<div style="padding: 0 20px 20px">
|
||||
<depart-manage-list :data="departData" />
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="部门用户" key="depart-user" v-if="hasPermission(orgManageApi.departUserList)">
|
||||
<div style="padding: 0 20px 20px">
|
||||
<depart-user-list :activeKey="activeKey" :data="departData" />
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<div v-show="departData == null" style="padding-top: 40px">
|
||||
<a-empty description="尚未选择部门" />
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="system-depart">
|
||||
import { provide, ref, computed } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import DepartLeftTree from './components/DepartLeftTree.vue';
|
||||
import DepartFormTab from './components/DepartFormTab.vue';
|
||||
import DepartUserList from './components/departUser/departUserList.vue';
|
||||
import DepartManageList from './components/departManage/departManageList.vue';
|
||||
import { usePermission } from '/@/hooks/web/usePermission';
|
||||
import { orgManageApi } from '/@/utils/auth/buttonAuth/system';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
const { hasPermission } = usePermission();
|
||||
|
||||
const { prefixCls } = useDesign('depart-manage');
|
||||
provide('prefixCls', prefixCls);
|
||||
|
||||
// 给子组件定义一个ref变量
|
||||
const leftTree = ref();
|
||||
const activeKey = ref('base-info');
|
||||
|
||||
// 当前选中的部门信息
|
||||
const departData = ref({});
|
||||
const rootTreeData = ref<any[]>([]);
|
||||
const { userInfo } = useUserStore();
|
||||
|
||||
// 左侧树选择后触发
|
||||
function onTreeSelect(data) {
|
||||
departData.value = data;
|
||||
manager.value = data?.manager;
|
||||
|
||||
if (data?.orgType == 1) {
|
||||
activeKey.value = 'base-info';
|
||||
}
|
||||
}
|
||||
|
||||
const manager = ref();
|
||||
// 左侧树rootTreeData触发
|
||||
function onRootTreeData(data) {
|
||||
rootTreeData.value = data;
|
||||
}
|
||||
|
||||
function onSuccess() {
|
||||
leftTree.value.loadRootTreeData();
|
||||
}
|
||||
const hasPer = computed(() => {
|
||||
// 修改此字段
|
||||
return !!userInfo?.roleCodes && (userInfo?.roleCodes.includes('admin') || userInfo?.roleCodes.includes('system'));
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import './index.less';
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
/*begin 兼容暗夜模式*/
|
||||
.depart-manage {
|
||||
background-color: @component-background;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
|
||||
.outer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.inner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.spin-tree .ant-tree .ant-tree-icon-hide) {
|
||||
height: 100px !important;
|
||||
}
|
||||
|
||||
.col-l,
|
||||
.col-r {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.col-l {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
:deep(.col-l, .col-r) {
|
||||
width: calc(50% - 20px);
|
||||
padding: 0 !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user