branchErp/src/views/manage/posimanage/orgManage.vue
2025-09-23 10:04:22 +08:00

577 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="org-dialog">
<n-modal
class="org-dialog"
v-model:show="props.orgVisible"
:z-index="1999"
:mask-closable="true"
style="min-width: 1000px; max-width: 1200px"
:to="app"
>
<n-card
:bordered="false"
:title="props.title"
size="huge"
role="dialog"
aria-modal="true"
>
<template #header-extra>
<div class="close-box">
<n-button @click="closeFn" text style="font-size: 24px">
<n-icon>
<close-icon />
</n-icon>
</n-button>
</div>
</template>
<div class="item-box">
<fl-tree
:data="state.treeData"
:expandedKeys="state.expandedKeys"
:refreshCount="state.treeRefreshCount"
:clickKey="state.clickKey"
:config="{
actions: ['edit', 'add', 'subtraction', 'move'],
moveShow: '[%=level%]>0',
subtractionShow: '[%=level%]>0',
}"
@triggerTreeAction="handleTreeAction"
@triggerTreeClick="handleTreeClick"
></fl-tree>
</div>
<template #footer>
<div
style="text-align: center; padding-left: 20px; padding-right: 10px"
>
<n-button class="button-box" @click="closeFn"> 返回 </n-button>
</div>
</template>
</n-card>
</n-modal>
<n-modal
v-model:show="state.dialogAddTree"
style="width: 600px"
:mask-closable="false"
preset="card"
>
<template #header>
<div
class="col-12 row justify-center relative"
style="border-bottom: 1px solid #dfd7f2"
>
<div style="font-size: 20px; font-weight: bold; color: #1f2225ff">
添加组织
</div>
</div>
</template>
<div class="row justify-center fl-pa-md">
<div class="fl-my-lg font-20">
<n-input
v-model:value="state.dialogAddTreeData"
placeholder="请输入组织名称"
/>
</div>
<div class="col-12 row justify-center">
<n-button
tertiary
style="width: 161px; background: #764cf6; color: #fff"
class="fl-mr-md"
@click="handleDialogAddTreeSave"
>保存</n-button
>
<n-button
tertiary
style="width: 161px; background: #eeeaf7; color: #774ff6"
@click="state.dialogAddTree = false"
>返回</n-button
>
</div>
</div>
</n-modal>
<n-modal
v-model:show="state.dialogSubtractionTree"
style="width: 600px"
:mask-closable="false"
preset="card"
>
<template #header>
<div
class="col-12 row justify-center relative"
style="border-bottom: 1px solid #dfd7f2"
>
<div style="font-size: 20px; font-weight: bold; color: #1f2225ff">
删除组织
</div>
</div>
</template>
<div class="row justify-center fl-pa-md">
<div class="font-20" style="margin: 115px 0">
是否确认删除该组织及其子组织如有
</div>
<div class="col-12 row justify-center">
<n-button
tertiary
style="width: 161px; background: #764cf6; color: #fff"
class="fl-mr-md"
@click="handleDialogSubtractionTreeSave"
>确定</n-button
>
<n-button
tertiary
style="width: 161px; background: #eeeaf7; color: #774ff6"
@click="state.dialogSubtractionTree = false"
>返回</n-button
>
</div>
</div>
</n-modal>
<n-modal
v-model:show="state.dialogMoveTree"
style="width: 600px"
:mask-closable="false"
preset="card"
>
<template #header>
<div
class="col-12 row justify-center relative"
style="border-bottom: 1px solid #dfd7f2"
>
<div style="font-size: 20px; font-weight: bold; color: #1f2225ff">
移动
</div>
</div>
</template>
<div class="row justify-center fl-pa-md">
<div class="fl-my-lg font-20">
<div class="font-16 fl-mb-md">请选择部门节点</div>
<fln-form-item
type="select"
:val="null"
:fatherData="state.dialogData"
:config="{
placeholder: '选择归属组织',
config: {
optionConfig: {
resDataField: 'list',
url: '/department/v2/base/all/list',
params: [
{
label: 'notDepartmentIds',
field: 'key',
type: 'Array',
},
],
labelField: 'name',
valueField: 'ID',
},
},
}"
:clearable="true"
@triggerValChange="handleValChange"
/>
<div class="font-14 fl-mt-sm" style="color: #ef0000">
确认后所选部门及其所有子部门将统一归属于新选定的上级部门之下且保持原有子部门层级关系不变
</div>
</div>
<div class="col-12 row justify-center fl-mt-md">
<n-button
tertiary
style="width: 161px; background: #eeeaf7; color: #774ff6"
class="fl-mr-md"
@click="state.dialogMoveTree = false"
>取消</n-button
>
<n-button
tertiary
style="width: 161px; background: #764cf6; color: #fff"
@click="handleDialogMoveTreeSave"
>确定</n-button
>
</div>
</div>
</n-modal>
</div>
</template>
<script setup>
// 组织管理
import flnTable from "@/components/flnlayout/table/flntable.vue";
import flTree from "./components/flnindex.vue";
import {
ref,
reactive,
onBeforeMount,
defineProps,
defineEmits,
onMounted,
getCurrentInstance,
computed,
} from "vue";
import { Close as CloseIcon } from "@vicons/ionicons5";
import { Local } from "@/utils/storage.js";
import {
processError,
processSuccess,
processWarning,
} from "@/utils/helper/message";
import { useRouter } from "vue-router";
import flnFormItem from "@/components/flnlayout/form/flnformItem.vue";
const router = useRouter();
const currentInstance = getCurrentInstance();
const { $request } = currentInstance.appContext.config.globalProperties;
const app = document.getElementById("app");
const state = reactive({
dialogData: {},
dialogMoveTree: false,
dialogMoveTreeData: null,
departmentOptions: [],
dialogAddTree: false,
dialogAddTreeData: "",
dialogSubtractionTree: false,
treeSelectData: {},
clickKey: "",
treeRefreshCount: 0,
expandedKeys: [],
treeData: [],
btnLoading: false,
selectedRows: [],
tableConfig: {
requestbysf: true,
rowKey: "ID",
refreshCount: 0,
listUrl: {
resDataField: "data",
pageField: "page",
pageSizeField: "pageSize",
url: "user/v2/list",
params: [
{
label: "departmentID",
field: "key",
},
],
},
},
});
const props = defineProps({
orgVisible: {
type: Boolean,
default: false,
},
title: {
type: String,
require: true,
},
});
onBeforeMount(() => {
let treeSelectData = Local.get("orgmanage_treeSelectData");
if (treeSelectData) {
state.treeSelectData = treeSelectData;
state.clickKey = treeSelectData.key;
}
getTreeData();
});
onMounted(() => {});
const getTreeData = () => {
let url = "/department/v2/tree/my";
let params = {};
$request.HTTP.components.postDataByParams(url, params).then(
(res) => {
if (res.status === 0 && Array.isArray(res.data.nodes)) {
let data = res.data.nodes;
calcTreeData(data);
state.treeData = data;
if (JSON.stringify(state.treeSelectData) === "{}") {
state.treeSelectData = data[0];
state.clickKey = data[0].key;
}
if (
state.clickKey === data[0].key &&
!state.expandedKeys.includes(data[0].key)
) {
state.expandedKeys.push(data[0].key);
}
if (!state.expandedKeys.includes(state.clickKey)) {
state.expandedKeys.push(state.clickKey);
}
if (data.length === 1 && !state.expandedKeys.includes(data[0].key)) {
state.expandedKeys.push(data[0].key);
}
state.treeRefreshCount++;
state.tableConfig.refreshCount++;
} else {
processError(res.msg || "获取失败!");
}
},
() => {
processError("获取失败!");
},
() => {
processError("获取失败!");
}
);
};
const handleCreatePosi = () => {};
const handleValChange = ({ val, config, selectOpt }) => {
state.dialogMoveTreeData = selectOpt;
};
const handleTreeAction = ({ type, val }) => {
state.dialogData = val;
if (type === "add") {
state.clickKey = val.key;
state.treeSelectData = val;
state.tableConfig.refreshCount++;
state.dialogAddTreeData = "";
state.dialogAddTree = true;
}
if (type === "move") {
state.clickKey = val.key;
state.treeSelectData = val;
state.tableConfig.refreshCount++;
state.dialogMoveTreeData = {};
state.dialogMoveTree = true;
}
if (type === "subtraction") {
state.dialogSubtractionTree = true;
}
if (type === "save") {
let url = "/department/v2/update";
let params = {
name: val.title,
ID: val.key,
};
$request.HTTP.components.postDataByParams(url, params).then(
(res) => {
if (res.status === 0) {
getTreeData();
} else {
processError(res.msg || "操作失败!");
}
},
() => {
processError("操作失败!");
},
() => {
processError("操作失败!");
}
);
}
if (type === "cancel") {
getTreeData();
}
};
const handleTreeClick = ({ selectedKey, tree }) => {
state.clickKey = tree.key;
state.treeSelectData = tree;
Local.set("orgmanage_treeSelectData", tree);
state.tableConfig.refreshCount++;
};
// const handleTreeDefaultClick = () => {
// state.treeSelectData = state.treeData[0];
// state.clickKey = state.treeData[0].key;
// Local.remove("orgmanage_treeSelectData");
// state.tableConfig.refreshCount++;
// };
const handleCloseModal = () => {
// emits("triggerCloseModal");
};
const handleDialogMoveTreeSave = () => {
let url = "/department/v2/update";
let params = {
ID: state.dialogData.key,
name: state.dialogData.label,
pid: state.dialogMoveTreeData.value,
};
$request.HTTP.components.postDataByParams(url, params).then(
(res) => {
if (res.status === 0) {
if (Array.isArray(res.data.levelPathList)) {
state.expandedKeys = [];
res.data.levelPathList.forEach((treeid) => {
if (!state.expandedKeys.includes(treeid)) {
state.expandedKeys.push(treeid);
}
});
}
getTreeData();
state.dialogMoveTree = false;
if (
(state.dialogMoveTreeData.level || 0) +
1(state.dialogData.sonMaxDepth || 0) +
1 >
8
) {
processWarning("组织数已超过8级建议不要再增加高度");
} else {
processSuccess("操作成功!");
}
} else {
processError(res.msg || "操作失败!");
}
},
() => {
processError("操作失败!");
state.dialogAddTree = false;
},
() => {
state.dialogAddTree = false;
processError("操作失败!");
}
);
};
// 树 新增
const handleDialogAddTreeSave = () => {
let url = "/department/v2/create";
let params = {
name: state.dialogAddTreeData,
pid: state.dialogData.key,
};
$request.HTTP.components.postDataByParams(url, params).then(
(res) => {
if (res.status === 0) {
if (Array.isArray(res.data.levelPathList)) {
state.expandedKeys = [];
res.data.levelPathList.forEach((treeid) => {
if (!state.expandedKeys.includes(treeid)) {
state.expandedKeys.push(treeid);
}
});
}
getTreeData();
state.dialogAddTree = false;
if (state.dialogData.level > 7) {
processWarning("组织数已超过8级建议不要再增加高度");
}
} else {
processError(res.msg || "操作失败!");
}
},
() => {
processError("操作失败!");
state.dialogAddTree = false;
},
() => {
state.dialogAddTree = false;
processError("操作失败!");
}
);
};
// 树 减
const handleDialogSubtractionTreeSave = () => {
let url = "/department/v2/remove";
let params = {
ID: state.dialogData.key,
};
$request.HTTP.components.postDataByParams(url, params).then(
(res) => {
if (res.status === 0) {
getTreeData();
state.dialogSubtractionTree = false;
} else {
processError(res.msg || "操作失败!");
}
},
() => {
processError("操作失败!");
state.dialogSubtractionTree = false;
},
() => {
state.dialogSubtractionTree = false;
processError("操作失败!");
}
);
};
const calcTreeData = (data) => {
for (let item of data) {
item.key = item.ID;
item.label = item.name;
item.title = item.name;
if (item.sons) {
item.children = item.sons;
calcTreeData(item.children);
}
delete item.ID;
delete item.name;
delete item.sons;
}
};
const emit = defineEmits(["update:orgVisible", "orgHandleOk"]);
const closeFn = () => {
emit("orgHandleOk");
};
watch(
() => props.orgVisible,
(val) => {
let treeSelectData = Local.get("orgmanage_treeSelectData");
if (treeSelectData) {
state.treeSelectData = treeSelectData;
state.clickKey = treeSelectData.key;
}
getTreeData();
}
);
</script>
<style lang="scss" scoped>
.org-dialog {
text-align: center;
.naive-modal-body {
height: 750px !important;
}
}
.item-box {
height: 50vh;
overflow: auto;
text-align: center;
padding-left: 100px;
padding-right: 100px;
}
.button-box {
width: 150px;
background-color: rgba(199, 199, 201, 1);
color: #fff;
}
.search-item {
:deep(.ant-input-affix-wrapper) {
background: #fff;
color: #c3c3c3;
}
:deep(.ant-input) {
color: #000;
&::placeholder {
color: #c3c3c3;
}
}
:deep(.ant-picker-input > input) {
color: #000;
&::placeholder {
color: #c3c3c3;
}
}
:deep(.ant-picker) {
width: 100%;
border-radius: 20px;
background: #fff !important;
color: #c3c3c3;
border: none;
}
:deep(.ant-picker-input > input) {
color: #000;
&::placeholder {
color: #c3c3c3;
}
}
}
</style>