添加管理
This commit is contained in:
parent
968b91a69d
commit
4eaaa6d4bc
@ -72,7 +72,72 @@ const commonRoute = [
|
|||||||
},
|
},
|
||||||
component: () => import("@/views/artworkreturn/index.vue"),
|
component: () => import("@/views/artworkreturn/index.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/posimanage/create",
|
||||||
|
name: "PosiManageCre",
|
||||||
|
meta: {
|
||||||
|
title: "岗位管理",
|
||||||
|
},
|
||||||
|
component: () => import("../views/manage/posimanage/create"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/orgmanage",
|
||||||
|
name: "OrgManage",
|
||||||
|
meta: {
|
||||||
|
title: "组织管理",
|
||||||
|
},
|
||||||
|
component: () => import("../views/manage/orgmanage/index"),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: "/posimanage",
|
||||||
|
name: "PosiManage",
|
||||||
|
meta: {
|
||||||
|
title: "岗位管理",
|
||||||
|
},
|
||||||
|
component: () => import("../views/manage/posimanage/index"),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: "/posirecordlog",
|
||||||
|
name: "PosiRecordLog",
|
||||||
|
meta: {
|
||||||
|
title: "岗位操作记录",
|
||||||
|
},
|
||||||
|
component: () => import("../views/manage/posirecordlog/index"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/peomanage",
|
||||||
|
name: "PeoManage",
|
||||||
|
meta: {
|
||||||
|
title: "人员管理",
|
||||||
|
},
|
||||||
|
component: () => import("../views/manage/peomanage/index"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/peomanage/personnelManage",
|
||||||
|
name: "personnelManage",
|
||||||
|
meta: {
|
||||||
|
title: "人员管理",
|
||||||
|
},
|
||||||
|
component: () => import("../views/manage/peomanage/personnelManage"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/peomanage/create",
|
||||||
|
name: "PeoManageCre",
|
||||||
|
meta: {
|
||||||
|
title: "人员管理",
|
||||||
|
},
|
||||||
|
component: () => import("../views/manage/peomanage/create"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/peomanage/editPeo",
|
||||||
|
name: "PeoManageEdi",
|
||||||
|
meta: {
|
||||||
|
title: "人员管理",
|
||||||
|
},
|
||||||
|
component: () => import("../views/manage/peomanage/editPeo"),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default commonRoute;
|
export default commonRoute;
|
||||||
|
430
src/views/manage/orgmanage/index.vue
Normal file
430
src/views/manage/orgmanage/index.vue
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row"
|
||||||
|
style="padding: 35px">
|
||||||
|
<div class="col-3 fl-pa-md"
|
||||||
|
style="
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: rgba(188, 188, 188, 0.18) 0px 3px 6px 1px;
|
||||||
|
">
|
||||||
|
<div class="row font-16"
|
||||||
|
style="color: #764cf6; border-bottom: 1px solid #c1b2e5">
|
||||||
|
<div class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6">
|
||||||
|
组织架构
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row"
|
||||||
|
style="height: 76vh; overflow: auto">
|
||||||
|
<fl-tree :data="state.treeData"
|
||||||
|
:expandedKeys="state.expandedKeys"
|
||||||
|
:refreshCount="state.treeRefreshCount"
|
||||||
|
:clickKey="state.clickKey"
|
||||||
|
:config="{
|
||||||
|
actions: ['edit', 'add', 'subtraction'],
|
||||||
|
addShow: '[%=level%]!==4',
|
||||||
|
}"
|
||||||
|
@triggerTreeAction="handleTreeAction"
|
||||||
|
@triggerTreeClick="handleTreeClick"></fl-tree>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-9 row fl-px-md">
|
||||||
|
<div style="background: #fff"
|
||||||
|
class="fl-pa-md">
|
||||||
|
<div class="col-12 row font-16"
|
||||||
|
style="color: #764cf6; border-bottom: 1px solid #c1b2e5">
|
||||||
|
<div class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6">
|
||||||
|
{{ state.treeSelectData.title || "平台开发管理项目组" }}所有人员
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 row fl-mt-sm">
|
||||||
|
<fln-table :config="state.tableConfig"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount"
|
||||||
|
:fatherData="state.treeSelectData">
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 岗位
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
import flTree from "@/components/flnlayout/tree/flnindex.vue";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
} from "vue";
|
||||||
|
import { Local } from "@/utils/storage.js";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
const router = useRouter();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
const state = reactive({
|
||||||
|
dialogData: {},
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
searchConfig: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "姓名",
|
||||||
|
field: "nickName",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "请输入姓名",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "手机号",
|
||||||
|
field: "telNum",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "请输入手机号",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "岗位",
|
||||||
|
field: "positionName",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "请输入岗位",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "员工工号",
|
||||||
|
field: "jobNum",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "请输入员工工号",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: "员工工号",
|
||||||
|
field: "jobNum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "姓名",
|
||||||
|
field: "nickName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
title: "手机号",
|
||||||
|
field: "telNum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 360,
|
||||||
|
title: "岗位",
|
||||||
|
align: 'left',
|
||||||
|
field: "nowPositions",
|
||||||
|
type: "tags",
|
||||||
|
tagConfig: {
|
||||||
|
tagField: "name",
|
||||||
|
tagBgColorField: "color",
|
||||||
|
showLength: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
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 = () => {
|
||||||
|
console.log("handleCreatePosi");
|
||||||
|
};
|
||||||
|
|
||||||
|
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 === "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 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;
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.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>
|
893
src/views/manage/peomanage/create.vue
Normal file
893
src/views/manage/peomanage/create.vue
Normal file
@ -0,0 +1,893 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row" style="padding: 35px; margin-bottom: 80px">
|
||||||
|
<div
|
||||||
|
class="col-12 row"
|
||||||
|
style="
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 17px 20px;
|
||||||
|
box-shadow: 0 3px 6px 1px rgba(188, 188, 188, 0.18);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 row font-20"
|
||||||
|
style="color: #764cf6; border-bottom: 1px solid #c1b2e5"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="state.pageType === 'create'"
|
||||||
|
class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6"
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="state.pageType === 'edit'"
|
||||||
|
class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="state.pageType === 'view'"
|
||||||
|
class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6"
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 row">
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="text"
|
||||||
|
:val="state.formData.nickName"
|
||||||
|
:config="{
|
||||||
|
label: '姓名:',
|
||||||
|
field: 'nickName',
|
||||||
|
placeholder: '请输入姓名',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValBlur="handleValBlur"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="text"
|
||||||
|
:val="state.formData.telNum"
|
||||||
|
:config="{
|
||||||
|
label: '手机号:',
|
||||||
|
field: 'telNum',
|
||||||
|
placeholder: '请输入手机号',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="text"
|
||||||
|
:val="state.formData.mailAccount"
|
||||||
|
:config="{
|
||||||
|
label: '邮箱:',
|
||||||
|
field: 'mailAccount',
|
||||||
|
placeholder: '自动生成',
|
||||||
|
}"
|
||||||
|
:disable="true"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="date"
|
||||||
|
:val="state.formData.enterDate"
|
||||||
|
:config="{
|
||||||
|
label: '入职时间:',
|
||||||
|
field: 'enterDate',
|
||||||
|
placeholder: '请输入入职时间',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="select"
|
||||||
|
:val="state.formData.status"
|
||||||
|
:config="{
|
||||||
|
placeholder: '请输入状态',
|
||||||
|
label: '状态:',
|
||||||
|
field: 'status',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '有效',
|
||||||
|
value: 'notactive',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '无效',
|
||||||
|
value: 'left',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="text"
|
||||||
|
:val="state.formData.jobNum"
|
||||||
|
:config="{
|
||||||
|
label: '员工工号:',
|
||||||
|
field: 'jobNum',
|
||||||
|
placeholder: '请输入员工工号',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item fl-mt-md row col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="upload"
|
||||||
|
title="图片上传"
|
||||||
|
:config="{
|
||||||
|
limit4096: true,
|
||||||
|
label: '员工近照:',
|
||||||
|
field: 'recentImg',
|
||||||
|
placeholder: '请输入员工近照',
|
||||||
|
style: 'width:80px',
|
||||||
|
}"
|
||||||
|
:val="state.formData.recentImg"
|
||||||
|
:otherParams="{
|
||||||
|
source: 'artwork',
|
||||||
|
mask: '',
|
||||||
|
type: 'image',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-item fl-mt-md row col-3">
|
||||||
|
<div class="col-12 row items-center">
|
||||||
|
<fln-form-item
|
||||||
|
type="upload"
|
||||||
|
title="图片上传"
|
||||||
|
:config="{
|
||||||
|
limit4096: true,
|
||||||
|
label: '员工头像:',
|
||||||
|
field: 'avatar',
|
||||||
|
placeholder: '请输入员工近照',
|
||||||
|
style: 'width:80px',
|
||||||
|
}"
|
||||||
|
:val="state.formData.avatar"
|
||||||
|
:otherParams="{
|
||||||
|
source: 'artwork',
|
||||||
|
mask: '',
|
||||||
|
type: 'image',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
>
|
||||||
|
<template #uploadRight v-if="!calcPageDisable()">
|
||||||
|
<div class="row" style="width: calc(100% - 84px)">
|
||||||
|
<img
|
||||||
|
v-for="(item, index) in state.defaultImgList"
|
||||||
|
:src="item + '?x-oss-process=image/resize,w_158,h_158'"
|
||||||
|
:key="index"
|
||||||
|
class="img-avatar"
|
||||||
|
:class="
|
||||||
|
state.defaultImgSelect == index ? 'border-active' : ''
|
||||||
|
"
|
||||||
|
@click="handleSetImg(item, index)"
|
||||||
|
/>
|
||||||
|
</div> </template
|
||||||
|
></fln-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="col-12 row fl-mt-md"
|
||||||
|
style="
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 17px 20px;
|
||||||
|
box-shadow: 0 3px 6px 1px rgba(188, 188, 188, 0.18);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
Array.isArray(state.depPositions) &&
|
||||||
|
state.depPositions.filter((item) => item.positions?.length > 0)
|
||||||
|
.length > 0
|
||||||
|
"
|
||||||
|
class="col-12 row"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 fl-mt-md row items-center fl-pb-xs"
|
||||||
|
style="min-height: 40px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 row justify-between items-center fl-px-md"
|
||||||
|
style="
|
||||||
|
min-height: 40px;
|
||||||
|
background: #46299dff;
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="color-white">设置所属部门及岗位</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="border: 1px solid #c3c3c3; border-radius: 0 0 3px 3px"
|
||||||
|
class="col-12 row fl-pb-xs"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 row"
|
||||||
|
style="padding: 11px 0; background: #dfd7f2"
|
||||||
|
>
|
||||||
|
<div class="col-3 text-center">所属部门</div>
|
||||||
|
<div class="col-6 text-left">所属岗位</div>
|
||||||
|
</div>
|
||||||
|
<template v-for="(row, rowIdx) in state.depPositions">
|
||||||
|
<div
|
||||||
|
class="col-12 row fl-py-sm"
|
||||||
|
v-if="row.positions?.length > 0"
|
||||||
|
:style="
|
||||||
|
rowIdx !== state.depPositions.length - 1
|
||||||
|
? 'border-bottom:1px solid #c3c3c3'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
:key="rowIdx"
|
||||||
|
>
|
||||||
|
<div class="col-3 row items-center justify-center">
|
||||||
|
{{ row.name }}
|
||||||
|
</div>
|
||||||
|
<div class="col-6 row items-center">
|
||||||
|
<div
|
||||||
|
v-for="(tag, idx) in row.positions"
|
||||||
|
:key="idx"
|
||||||
|
class="fl-mr-sm fl-px-sm fl-py-xs row items-center fl-mb-xs"
|
||||||
|
style="border: solid 1px #ded7f1; border-radius: 3px"
|
||||||
|
:style="{
|
||||||
|
borderColor: tag.color,
|
||||||
|
color: tag.color || '#fff',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<n-popover :show-arrow="true">
|
||||||
|
<template #trigger>
|
||||||
|
{{ tag.name }}
|
||||||
|
</template>
|
||||||
|
{{ tag.name }}
|
||||||
|
</n-popover>
|
||||||
|
|
||||||
|
<close-circle-outlined
|
||||||
|
v-if="!calcPageDisable()"
|
||||||
|
class="fl-ml-md"
|
||||||
|
@click="handleClearPage(rowIdx, tag)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 row">
|
||||||
|
<div
|
||||||
|
class="col-3 row fl-px-md"
|
||||||
|
style="overflow: auto; box-shadow: 0 3px 6px 1px #bcbcbc2e"
|
||||||
|
>
|
||||||
|
<fln-tree
|
||||||
|
:data="state.treeData"
|
||||||
|
:expandedKeys="state.expandedKeys"
|
||||||
|
:refreshCount="state.treeRefreshCount"
|
||||||
|
:clickKey="state.clickKey"
|
||||||
|
@triggerTreeClick="handleTreeClick"
|
||||||
|
></fln-tree>
|
||||||
|
</div>
|
||||||
|
<div class="col-9 row fl-pl-md" style="align-content: flex-start">
|
||||||
|
<fln-table
|
||||||
|
class="artwork-table"
|
||||||
|
:config="state.tableConfig"
|
||||||
|
:defaultSelectedRows="state.tableDefaultPositions"
|
||||||
|
:clearSelectRowKey="state.tableClearKey"
|
||||||
|
:fatherData="state.treeSelectData"
|
||||||
|
:fatherParams="state.tableSearchData"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount"
|
||||||
|
@triggerRowSelect="handleTableRowSelect"
|
||||||
|
@triggerRowSelectAll="handleTableCheckAll"
|
||||||
|
>
|
||||||
|
<template #table-header>
|
||||||
|
<span style="color: #fd0000" class="fl-mx-sm">*</span>
|
||||||
|
请至少勾选一个岗位</template
|
||||||
|
>
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="width-100 row fl-pt-md fl-pb-lg"
|
||||||
|
style="position: fixed; bottom: 0px; background: #f0f0f5"
|
||||||
|
>
|
||||||
|
<div class="col-10 row justify-center">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
class="fl-mr-md"
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #ffffffff"
|
||||||
|
@click="handleBack"
|
||||||
|
>返回</n-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
v-if="state.pageType === 'edit'"
|
||||||
|
style="width: 161px; height: 34px; background: #46299dff; color: #fff"
|
||||||
|
@click="handleSave"
|
||||||
|
>保存</n-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
v-if="state.pageType === 'create'"
|
||||||
|
style="width: 161px; height: 34px; background: #46299dff; color: #fff"
|
||||||
|
@click="handleCreate"
|
||||||
|
>保存</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
import flnFormItem from "@/components/flnlayout/form/flnformItem.vue";
|
||||||
|
import flnTree from "@/components/flnlayout/tree/flnindex.vue";
|
||||||
|
|
||||||
|
import { CloseCircleOutlined } from "@ant-design/icons-vue";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onActivated,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
watch,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter, useRoute } from "vue-router";
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
const state = reactive({
|
||||||
|
tableClearKey: null,
|
||||||
|
treeSelectData: {},
|
||||||
|
tableDefaultPositions: [],
|
||||||
|
depPositions: [],
|
||||||
|
clickKey: "",
|
||||||
|
treeRefreshCount: 0,
|
||||||
|
expandedKeys: [],
|
||||||
|
treeData: [],
|
||||||
|
formData: {
|
||||||
|
nickName: null,
|
||||||
|
telNum: null,
|
||||||
|
status: "notactive",
|
||||||
|
positionName: null,
|
||||||
|
jobNum: null,
|
||||||
|
mailAccount: null,
|
||||||
|
enterDate: null,
|
||||||
|
recentImg: null,
|
||||||
|
avatar: null,
|
||||||
|
},
|
||||||
|
tableSearchData: {},
|
||||||
|
selectedRows: [],
|
||||||
|
tableConfig: {
|
||||||
|
hasSelection: true,
|
||||||
|
requestbysf: true,
|
||||||
|
rowKey: "ID",
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "data",
|
||||||
|
pageField: "page",
|
||||||
|
pageSizeField: "pageSize",
|
||||||
|
url: "/position/v2/list",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
label: "departmentID",
|
||||||
|
field: "key",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: "岗位ID",
|
||||||
|
field: "ID",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
align: "left",
|
||||||
|
title: "岗位名",
|
||||||
|
field: "name",
|
||||||
|
type: "sfBgColor",
|
||||||
|
bgConfig: {
|
||||||
|
bgColorField: "color",
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "tooltip",
|
||||||
|
align: "left",
|
||||||
|
width: 120,
|
||||||
|
title: "岗位描述",
|
||||||
|
field: "remark",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 360,
|
||||||
|
align: "left",
|
||||||
|
title: "页面权限",
|
||||||
|
field: "menuAuths",
|
||||||
|
type: "tags",
|
||||||
|
tagConfig: {
|
||||||
|
showLength: 3,
|
||||||
|
bgColor: "#fff",
|
||||||
|
borderRadius: "14px",
|
||||||
|
style: "border-radius: 14px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
defaultImgList: [
|
||||||
|
"https://cdns.fontree.cn/fonchain-main/prod/runtime/image/avart/0/d5f416d5-0b95-4b2c-82c4-6218d4017d17.jpg",
|
||||||
|
"https://cdns.fontree.cn/fonchain-main/prod/runtime/image/avart/0/012a339a-53d2-43f7-ae47-84d444d5ca6f.jpg",
|
||||||
|
"https://cdns.fontree.cn/fonchain-main/prod/runtime/file/avart/11/48ae18e2-37a4-4eab-bd03-5fe1099892c3.jpg",
|
||||||
|
"https://cdns.fontree.cn/fonchain-main/prod/runtime/file/avart/11/0a53fd8a-951e-4a8e-8d71-0198dad5e7ae.jpg",
|
||||||
|
],
|
||||||
|
defaultImgSelect: null,
|
||||||
|
btnLoading: false,
|
||||||
|
pageType: "create",
|
||||||
|
});
|
||||||
|
watch(
|
||||||
|
() => state.clickKey,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
state.tableDefaultPositions =
|
||||||
|
state.depPositions.filter((item) => item.ID === state.clickKey).length > 0
|
||||||
|
? state.depPositions.filter((item) => item.ID === state.clickKey)[0]
|
||||||
|
.positions
|
||||||
|
: [];
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getTreeData();
|
||||||
|
if (route.query.type) {
|
||||||
|
state.pageType = route.query.type;
|
||||||
|
}
|
||||||
|
if (route.query.type === "view") {
|
||||||
|
state.tableConfig.hasSelection = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onActivated(() => {
|
||||||
|
getTreeData();
|
||||||
|
if (route.query.type) {
|
||||||
|
state.pageType = route.query.type;
|
||||||
|
}
|
||||||
|
if (route.query.type === "view") {
|
||||||
|
state.tableConfig.hasSelection = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onMounted(() => {});
|
||||||
|
const getPageData = () => {
|
||||||
|
if (route.query.ID) {
|
||||||
|
let url = "/user/v2/detail";
|
||||||
|
let params = {
|
||||||
|
ID: Number(route.query.ID),
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.formData = {
|
||||||
|
nickName: res.data.nickName,
|
||||||
|
telNum: res.data.telNum,
|
||||||
|
status: res.data.status,
|
||||||
|
positionName: res.data.positionName,
|
||||||
|
jobNum: res.data.jobNum,
|
||||||
|
mailAccount: res.data.mailAccount,
|
||||||
|
enterDate: res.data.enterDate,
|
||||||
|
recentImg: res.data.recentImg,
|
||||||
|
avatar: res.data.avatar,
|
||||||
|
};
|
||||||
|
state.depPositions = res.data.depPositions || [];
|
||||||
|
state.tableDefaultPositions =
|
||||||
|
state.depPositions.filter((item) => item.ID === state.clickKey)
|
||||||
|
.length > 0
|
||||||
|
? state.depPositions.filter(
|
||||||
|
(item) => item.ID === state.clickKey
|
||||||
|
)[0].positions
|
||||||
|
: [];
|
||||||
|
state.depPositions.forEach((item) => {
|
||||||
|
item.isLeader = item.isLeader || false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取数据失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取数据失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取数据失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getTreeData = () => {
|
||||||
|
let url = "/department/v2/tree/all";
|
||||||
|
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 (!state.expandedKeys.includes(data[0].key)) {
|
||||||
|
state.expandedKeys.push(data[0].key);
|
||||||
|
}
|
||||||
|
state.treeRefreshCount++;
|
||||||
|
if (JSON.stringify(state.treeSelectData) === "{}") {
|
||||||
|
state.treeSelectData = data[0];
|
||||||
|
state.clickKey = data[0].key;
|
||||||
|
}
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
if (route.query.ID) {
|
||||||
|
getPageData();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
processError("获取失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const calcTreeData = (data) => {
|
||||||
|
for (let item of data) {
|
||||||
|
item.key = item.ID;
|
||||||
|
item.title = item.name;
|
||||||
|
if (item.sons) {
|
||||||
|
item.children = item.sons;
|
||||||
|
calcTreeData(item.children);
|
||||||
|
}
|
||||||
|
delete item.ID;
|
||||||
|
delete item.name;
|
||||||
|
delete item.sons;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleValChange = ({ val, config }) => {
|
||||||
|
state.formData[config.field] = val;
|
||||||
|
};
|
||||||
|
const handleValBlur = ({ val, config }) => {
|
||||||
|
if (config.field === "nickName" && state.formData.nickName) {
|
||||||
|
let url = "/user/mail/account";
|
||||||
|
let params = {
|
||||||
|
nickName: val,
|
||||||
|
ID: route.query.ID ? Number(route.query.ID) : null,
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.formData.mailAccount = res.data.mailAccount;
|
||||||
|
} else {
|
||||||
|
processError("生成邮箱错误:" + res.msg);
|
||||||
|
state.formData.mailAccount = "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {},
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
state.tableSearchData = JSON.parse(JSON.stringify(state.formData));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTableRowSelect = ({ record, selected, selectedRows }) => {
|
||||||
|
if (
|
||||||
|
state.depPositions.filter((item) => item.ID === state.clickKey).length === 0
|
||||||
|
) {
|
||||||
|
state.depPositions.push({
|
||||||
|
isLeader: false,
|
||||||
|
ID: state.clickKey,
|
||||||
|
name: state.treeSelectData.title,
|
||||||
|
positions: selectedRows.map((item) => {
|
||||||
|
return {
|
||||||
|
ID: item.ID,
|
||||||
|
name: item.name,
|
||||||
|
color: item.color,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
state.depPositions.forEach((item) => {
|
||||||
|
if (item.ID === state.clickKey) {
|
||||||
|
if (selected) {
|
||||||
|
// 当前部门有其他子岗位时不直接覆盖
|
||||||
|
item.positions = item.positions.filter(
|
||||||
|
(depItem) => depItem.ID !== record.ID
|
||||||
|
);
|
||||||
|
item.positions = item.positions.concat([
|
||||||
|
{
|
||||||
|
ID: record.ID,
|
||||||
|
name: record.name,
|
||||||
|
color: record.color,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
item.positions = item.positions.filter(
|
||||||
|
(depItem) => depItem.ID !== record.ID
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
state.depPositions = state.depPositions.filter((item) => {
|
||||||
|
return item.positions && item.positions.length > 0;
|
||||||
|
});
|
||||||
|
state.selectedRows = selectedRows;
|
||||||
|
};
|
||||||
|
const handleTableCheckAll = ({ selectedRowKeys, selectedRows }) => {
|
||||||
|
if (
|
||||||
|
state.depPositions.filter((item) => item.ID === state.clickKey).length === 0
|
||||||
|
) {
|
||||||
|
state.depPositions.push({
|
||||||
|
isLeader: false,
|
||||||
|
ID: state.clickKey,
|
||||||
|
name: state.treeSelectData.title,
|
||||||
|
positions: selectedRows.map((item) => {
|
||||||
|
return {
|
||||||
|
ID: item.ID,
|
||||||
|
name: item.name,
|
||||||
|
color: item.color,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
state.depPositions.forEach((item) => {
|
||||||
|
if (item.ID === state.clickKey) {
|
||||||
|
item.positions = selectedRows.map((item) => {
|
||||||
|
return {
|
||||||
|
ID: item.ID,
|
||||||
|
name: item.name,
|
||||||
|
color: item.color,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
state.depPositions = state.depPositions.filter((item) => {
|
||||||
|
return item.positions && item.positions.length > 0;
|
||||||
|
});
|
||||||
|
state.selectedRows = selectedRows;
|
||||||
|
};
|
||||||
|
const handleDialogSave = () => {
|
||||||
|
state.dialogDel = false;
|
||||||
|
};
|
||||||
|
const handleDialogBack = () => {
|
||||||
|
state.dialogDel = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTreeClick = ({ selectedKey, tree }) => {
|
||||||
|
state.clickKey = tree.key;
|
||||||
|
state.treeSelectData = tree;
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
};
|
||||||
|
const calcPageDisable = () => {
|
||||||
|
return state.pageType === "view";
|
||||||
|
};
|
||||||
|
const handleSetImg = (item, index) => {
|
||||||
|
state.formData.avatar = "";
|
||||||
|
nextTick(() => {
|
||||||
|
state.formData.avatar = item;
|
||||||
|
state.defaultImgSelect = index;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleCreate = () => {
|
||||||
|
if (
|
||||||
|
state.formData.jobNum === null ||
|
||||||
|
state.formData.jobNum === "" ||
|
||||||
|
state.formData.jobNum === undefined
|
||||||
|
) {
|
||||||
|
processError("请输入员工工号");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.btnLoading = true;
|
||||||
|
state.depPositions = state.depPositions.filter((item) => {
|
||||||
|
return item.positions && item.positions.length > 0;
|
||||||
|
});
|
||||||
|
let url = "/user/v2/create";
|
||||||
|
let params = {
|
||||||
|
depPositions: state.depPositions,
|
||||||
|
};
|
||||||
|
Object.assign(params, state.formData);
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
router.go(-1);
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleSave = () => {
|
||||||
|
if (
|
||||||
|
state.formData.jobNum === null ||
|
||||||
|
state.formData.jobNum === "" ||
|
||||||
|
state.formData.jobNum === undefined
|
||||||
|
) {
|
||||||
|
processError("请输入员工工号");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.btnLoading = true;
|
||||||
|
state.depPositions = state.depPositions.filter((item) => {
|
||||||
|
return item.positions && item.positions.length > 0;
|
||||||
|
});
|
||||||
|
let url = "/user/v2/update";
|
||||||
|
let params = {
|
||||||
|
ID: Number(route.query.ID),
|
||||||
|
depPositions: state.depPositions,
|
||||||
|
};
|
||||||
|
Object.assign(params, state.formData);
|
||||||
|
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
getPageData();
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleLink = (path) => {
|
||||||
|
router.push(path);
|
||||||
|
};
|
||||||
|
const handleBack = () => {
|
||||||
|
router.go(-1);
|
||||||
|
};
|
||||||
|
const calcDepPositions = () => {
|
||||||
|
for (let key in state.depPositions) {
|
||||||
|
let data = state.depPositions[key];
|
||||||
|
if (!data || JSON.stringify(data) === "[]") {
|
||||||
|
delete state.depPositions[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleClearPage = (idx, clearItem) => {
|
||||||
|
state.depPositions[idx].positions.forEach((item, index) => {
|
||||||
|
if (item.name === clearItem.name) {
|
||||||
|
state.depPositions[idx].positions.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.depPositions[idx].positions.length === 0) {
|
||||||
|
state.depPositions.splice(idx, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
state.tableClearKey = clearItem.ID;
|
||||||
|
};
|
||||||
|
const calcSfBgColorWidth = (val) => {
|
||||||
|
if (val) {
|
||||||
|
return val.length * 15 + "px !important";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.avatar-uploader > .ant-upload) {
|
||||||
|
background: #fafafcff;
|
||||||
|
}
|
||||||
|
:deep(.ant-image) {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
:deep(.ant-image-img) {
|
||||||
|
object-fit: cover !important;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
:deep(.ant-image-mask) {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
:deep(.ant-upload) {
|
||||||
|
color: #c1b2e5;
|
||||||
|
}
|
||||||
|
:deep(.ant-select) {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
:deep(.ant-select-selector .ant-select-selection-placeholder) {
|
||||||
|
color: #c3c3c3 !important;
|
||||||
|
&::placeholder {
|
||||||
|
color: #c3c3c3 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.ant-select:not(.ant-select-customize-input) .ant-select-selector) {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.img-avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
margin: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.border-active {
|
||||||
|
border: 2px solid #764cf6;
|
||||||
|
}
|
||||||
|
</style>
|
893
src/views/manage/peomanage/editPeo.vue
Normal file
893
src/views/manage/peomanage/editPeo.vue
Normal file
@ -0,0 +1,893 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row" style="padding: 35px; margin-bottom: 80px">
|
||||||
|
<div
|
||||||
|
class="col-12 row"
|
||||||
|
style="
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 17px 20px;
|
||||||
|
box-shadow: 0 3px 6px 1px rgba(188, 188, 188, 0.18);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 row font-20"
|
||||||
|
style="color: #764cf6; border-bottom: 1px solid #c1b2e5"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="state.pageType === 'create'"
|
||||||
|
class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6"
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="state.pageType === 'edit'"
|
||||||
|
class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="state.pageType === 'view'"
|
||||||
|
class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6"
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 row">
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="text"
|
||||||
|
:val="state.formData.nickName"
|
||||||
|
:config="{
|
||||||
|
label: '姓名:',
|
||||||
|
field: 'nickName',
|
||||||
|
placeholder: '请输入姓名',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValBlur="handleValBlur"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="text"
|
||||||
|
:val="state.formData.telNum"
|
||||||
|
:config="{
|
||||||
|
label: '手机号:',
|
||||||
|
field: 'telNum',
|
||||||
|
placeholder: '请输入手机号',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="text"
|
||||||
|
:val="state.formData.mailAccount"
|
||||||
|
:config="{
|
||||||
|
label: '邮箱:',
|
||||||
|
field: 'mailAccount',
|
||||||
|
placeholder: '自动生成',
|
||||||
|
}"
|
||||||
|
:disable="true"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="date"
|
||||||
|
:val="state.formData.enterDate"
|
||||||
|
:config="{
|
||||||
|
label: '入职时间:',
|
||||||
|
field: 'enterDate',
|
||||||
|
format: 'YYYY-MM-dd',
|
||||||
|
placeholder: '请输入入职时间',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="select"
|
||||||
|
:val="state.formData.status"
|
||||||
|
:config="{
|
||||||
|
placeholder: '请输入状态',
|
||||||
|
label: '状态:',
|
||||||
|
field: 'status',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '有效',
|
||||||
|
value: 'notactive',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '无效',
|
||||||
|
value: 'left',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item fl-mt-md row items-center col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="text"
|
||||||
|
:val="state.formData.jobNum"
|
||||||
|
:config="{
|
||||||
|
label: '员工工号:',
|
||||||
|
field: 'jobNum',
|
||||||
|
placeholder: '请输入员工工号',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="search-item fl-mt-md row col-3">
|
||||||
|
<fln-form-item
|
||||||
|
type="upload"
|
||||||
|
title="图片上传"
|
||||||
|
:config="{
|
||||||
|
limit4096: true,
|
||||||
|
label: '员工近照:',
|
||||||
|
field: 'recentImg',
|
||||||
|
placeholder: '请输入员工近照',
|
||||||
|
style: 'width:80px',
|
||||||
|
}"
|
||||||
|
:val="state.formData.recentImg"
|
||||||
|
:otherParams="{
|
||||||
|
source: 'artwork',
|
||||||
|
mask: '',
|
||||||
|
type: 'image',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-item fl-mt-md row col-3">
|
||||||
|
<div class="col-12 row items-center">
|
||||||
|
<fln-form-item
|
||||||
|
type="upload"
|
||||||
|
title="图片上传"
|
||||||
|
:config="{
|
||||||
|
limit4096: true,
|
||||||
|
label: '员工头像:',
|
||||||
|
field: 'avatar',
|
||||||
|
placeholder: '请输入员工近照',
|
||||||
|
style: 'width:80px',
|
||||||
|
}"
|
||||||
|
:val="state.formData.avatar"
|
||||||
|
:otherParams="{
|
||||||
|
source: 'artwork',
|
||||||
|
mask: '',
|
||||||
|
type: 'image',
|
||||||
|
}"
|
||||||
|
:disable="calcPageDisable()"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
>
|
||||||
|
<template #uploadRight v-if="!calcPageDisable()">
|
||||||
|
<div class="row" style="width: calc(100% - 84px)">
|
||||||
|
<img
|
||||||
|
v-for="(item, index) in state.defaultImgList"
|
||||||
|
:src="item + '?x-oss-process=image/resize,w_158,h_158'"
|
||||||
|
:key="index"
|
||||||
|
class="img-avatar"
|
||||||
|
:class="
|
||||||
|
state.defaultImgSelect == index ? 'border-active' : ''
|
||||||
|
"
|
||||||
|
@click="handleSetImg(item, index)"
|
||||||
|
/>
|
||||||
|
</div> </template
|
||||||
|
></fln-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="col-12 row fl-mt-md"
|
||||||
|
style="
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 17px 20px;
|
||||||
|
box-shadow: 0 3px 6px 1px rgba(188, 188, 188, 0.18);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
Array.isArray(state.depPositions) &&
|
||||||
|
state.depPositions.filter((item) => item.positions?.length > 0)
|
||||||
|
.length > 0
|
||||||
|
"
|
||||||
|
class="col-12 row"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 fl-mt-md row items-center fl-pb-xs"
|
||||||
|
style="min-height: 40px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 row justify-between items-center fl-px-md"
|
||||||
|
style="
|
||||||
|
min-height: 40px;
|
||||||
|
background: #46299dff;
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="color-white">设置所属部门及岗位</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="border: 1px solid #c3c3c3; border-radius: 0 0 3px 3px"
|
||||||
|
class="col-12 row fl-pb-xs"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 row"
|
||||||
|
style="padding: 11px 0; background: #dfd7f2"
|
||||||
|
>
|
||||||
|
<div class="col-3 text-center">所属部门</div>
|
||||||
|
<div class="col-6 text-left">所属岗位</div>
|
||||||
|
</div>
|
||||||
|
<template v-for="(row, rowIdx) in state.depPositions">
|
||||||
|
<div
|
||||||
|
class="col-12 row fl-py-sm"
|
||||||
|
v-if="row.positions?.length > 0"
|
||||||
|
:style="
|
||||||
|
rowIdx !== state.depPositions.length - 1
|
||||||
|
? 'border-bottom:1px solid #c3c3c3'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
:key="rowIdx"
|
||||||
|
>
|
||||||
|
<div class="col-3 row items-center justify-center">
|
||||||
|
{{ row.name }}
|
||||||
|
</div>
|
||||||
|
<div class="col-6 row items-center">
|
||||||
|
<div
|
||||||
|
v-for="(tag, idx) in row.positions"
|
||||||
|
:key="idx"
|
||||||
|
class="fl-mr-sm fl-px-sm fl-py-xs row items-center fl-mb-xs"
|
||||||
|
style="border: solid 1px #ded7f1; border-radius: 3px"
|
||||||
|
:style="{
|
||||||
|
borderColor: tag.color,
|
||||||
|
color: tag.color || '#fff',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<n-popover :show-arrow="true">
|
||||||
|
<template #trigger>
|
||||||
|
{{ tag.name }}
|
||||||
|
</template>
|
||||||
|
{{ tag.name }}
|
||||||
|
</n-popover>
|
||||||
|
|
||||||
|
<close-circle-outlined
|
||||||
|
v-if="!calcPageDisable()"
|
||||||
|
class="fl-ml-md"
|
||||||
|
@click="handleClearPage(rowIdx, tag)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 row">
|
||||||
|
<div
|
||||||
|
class="col-3 row fl-px-md"
|
||||||
|
style="overflow: auto; box-shadow: 0 3px 6px 1px #bcbcbc2e"
|
||||||
|
>
|
||||||
|
<fln-tree
|
||||||
|
:data="state.treeData"
|
||||||
|
:expandedKeys="state.expandedKeys"
|
||||||
|
:refreshCount="state.treeRefreshCount"
|
||||||
|
:clickKey="state.clickKey"
|
||||||
|
@triggerTreeClick="handleTreeClick"
|
||||||
|
></fln-tree>
|
||||||
|
</div>
|
||||||
|
<div class="col-9 row fl-pl-md" style="align-content: flex-start">
|
||||||
|
<fln-table
|
||||||
|
class="artwork-table"
|
||||||
|
:config="state.tableConfig"
|
||||||
|
:defaultSelectedRows="state.tableDefaultPositions"
|
||||||
|
:clearSelectRowKey="state.tableClearKey"
|
||||||
|
:fatherData="state.treeSelectData"
|
||||||
|
:fatherParams="state.tableSearchData"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount"
|
||||||
|
@triggerRowSelect="handleTableRowSelect"
|
||||||
|
@triggerRowSelectAll="handleTableCheckAll"
|
||||||
|
>
|
||||||
|
<template #table-header>
|
||||||
|
<span style="color: #fd0000" class="fl-mx-sm">*</span>
|
||||||
|
请至少勾选一个岗位</template
|
||||||
|
>
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="width-100 row fl-pt-md fl-pb-lg"
|
||||||
|
style="position: fixed; bottom: 0px; background: #f0f0f5"
|
||||||
|
>
|
||||||
|
<div class="col-10 row justify-center">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
class="fl-mr-md"
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #ffffffff"
|
||||||
|
@click="handleBack"
|
||||||
|
>返回</n-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
v-if="state.pageType === 'edit'"
|
||||||
|
style="width: 161px; height: 34px; background: #46299dff; color: #fff"
|
||||||
|
@click="handleSave"
|
||||||
|
>保存</n-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
v-if="state.pageType === 'create'"
|
||||||
|
style="width: 161px; height: 34px; background: #46299dff; color: #fff"
|
||||||
|
@click="handleCreate"
|
||||||
|
>保存</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
import flnFormItem from "@/components/flnlayout/form/flnformItem.vue";
|
||||||
|
import flnTree from "@/components/flnlayout/tree/flnindex.vue";
|
||||||
|
|
||||||
|
import { CloseCircleOutlined } from "@ant-design/icons-vue";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onActivated,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
watch,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter, useRoute } from "vue-router";
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
const state = reactive({
|
||||||
|
tableClearKey: null,
|
||||||
|
treeSelectData: {},
|
||||||
|
tableDefaultPositions: [],
|
||||||
|
depPositions: [],
|
||||||
|
clickKey: "",
|
||||||
|
treeRefreshCount: 0,
|
||||||
|
expandedKeys: [],
|
||||||
|
treeData: [],
|
||||||
|
formData: {
|
||||||
|
nickName: null,
|
||||||
|
telNum: null,
|
||||||
|
status: "notactive",
|
||||||
|
positionName: null,
|
||||||
|
jobNum: null,
|
||||||
|
mailAccount: null,
|
||||||
|
enterDate: null,
|
||||||
|
recentImg: null,
|
||||||
|
avatar: null,
|
||||||
|
},
|
||||||
|
tableSearchData: {},
|
||||||
|
selectedRows: [],
|
||||||
|
tableConfig: {
|
||||||
|
hasSelection: true,
|
||||||
|
requestbysf: true,
|
||||||
|
rowKey: "ID",
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "data",
|
||||||
|
pageField: "page",
|
||||||
|
pageSizeField: "pageSize",
|
||||||
|
url: "/position/v2/list",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
label: "departmentID",
|
||||||
|
field: "key",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: "岗位ID",
|
||||||
|
field: "ID",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
align: "left",
|
||||||
|
title: "岗位名",
|
||||||
|
field: "name",
|
||||||
|
type: "sfBgColor",
|
||||||
|
bgConfig: {
|
||||||
|
bgColorField: "color",
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "tooltip",
|
||||||
|
align: "left",
|
||||||
|
width: 120,
|
||||||
|
title: "岗位描述",
|
||||||
|
field: "remark",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 360,
|
||||||
|
align: "left",
|
||||||
|
title: "页面权限",
|
||||||
|
field: "menuAuths",
|
||||||
|
type: "tags",
|
||||||
|
tagConfig: {
|
||||||
|
showLength: 3,
|
||||||
|
bgColor: "#fff",
|
||||||
|
borderRadius: "14px",
|
||||||
|
style: "border-radius: 14px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
defaultImgList: [
|
||||||
|
"https://cdns.fontree.cn/fonchain-main/prod/runtime/image/avart/0/d5f416d5-0b95-4b2c-82c4-6218d4017d17.jpg",
|
||||||
|
"https://cdns.fontree.cn/fonchain-main/prod/runtime/image/avart/0/012a339a-53d2-43f7-ae47-84d444d5ca6f.jpg",
|
||||||
|
"https://cdns.fontree.cn/fonchain-main/prod/runtime/file/avart/11/48ae18e2-37a4-4eab-bd03-5fe1099892c3.jpg",
|
||||||
|
"https://cdns.fontree.cn/fonchain-main/prod/runtime/file/avart/11/0a53fd8a-951e-4a8e-8d71-0198dad5e7ae.jpg",
|
||||||
|
],
|
||||||
|
defaultImgSelect: null,
|
||||||
|
btnLoading: false,
|
||||||
|
pageType: "create",
|
||||||
|
});
|
||||||
|
watch(
|
||||||
|
() => state.clickKey,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
state.tableDefaultPositions =
|
||||||
|
state.depPositions.filter((item) => item.ID === state.clickKey).length > 0
|
||||||
|
? state.depPositions.filter((item) => item.ID === state.clickKey)[0]
|
||||||
|
.positions
|
||||||
|
: [];
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getTreeData();
|
||||||
|
if (route.query.type) {
|
||||||
|
state.pageType = route.query.type;
|
||||||
|
}
|
||||||
|
if (route.query.type === "view") {
|
||||||
|
state.tableConfig.hasSelection = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onActivated(() => {
|
||||||
|
getTreeData();
|
||||||
|
if (route.query.type) {
|
||||||
|
state.pageType = route.query.type;
|
||||||
|
}
|
||||||
|
if (route.query.type === "view") {
|
||||||
|
state.tableConfig.hasSelection = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onMounted(() => {});
|
||||||
|
const getPageData = () => {
|
||||||
|
if (route.query.ID) {
|
||||||
|
let url = "/user/v2/boss/staff/detail";
|
||||||
|
let params = {
|
||||||
|
ID: Number(route.query.ID),
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.formData = {
|
||||||
|
nickName: res.data.nickName,
|
||||||
|
telNum: res.data.telNum,
|
||||||
|
status: res.data.status,
|
||||||
|
positionName: res.data.positionName,
|
||||||
|
jobNum: res.data.jobNum,
|
||||||
|
mailAccount: res.data.mailAccount,
|
||||||
|
enterDate: res.data.enterDate,
|
||||||
|
recentImg: res.data.recentImg,
|
||||||
|
avatar: res.data.avatar,
|
||||||
|
};
|
||||||
|
state.depPositions = res.data.depPositions || [];
|
||||||
|
state.tableDefaultPositions =
|
||||||
|
state.depPositions.filter((item) => item.ID === state.clickKey)
|
||||||
|
.length > 0
|
||||||
|
? state.depPositions.filter(
|
||||||
|
(item) => item.ID === state.clickKey
|
||||||
|
)[0].positions
|
||||||
|
: [];
|
||||||
|
state.depPositions.forEach((item) => {
|
||||||
|
item.isLeader = item.isLeader || false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取数据失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取数据失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取数据失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getTreeData = () => {
|
||||||
|
let params = {};
|
||||||
|
$request.HTTP.components.viewMyTree(params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0 && Array.isArray(res.data.nodes)) {
|
||||||
|
let data = res.data.nodes;
|
||||||
|
calcTreeData(data);
|
||||||
|
state.treeData = data;
|
||||||
|
if (!state.expandedKeys.includes(data[0].key)) {
|
||||||
|
state.expandedKeys.push(data[0].key);
|
||||||
|
}
|
||||||
|
state.treeRefreshCount++;
|
||||||
|
if (JSON.stringify(state.treeSelectData) === "{}") {
|
||||||
|
state.treeSelectData = data[0];
|
||||||
|
state.clickKey = data[0].key;
|
||||||
|
}
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
if (route.query.ID) {
|
||||||
|
getPageData();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
processError("获取失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const calcTreeData = (data) => {
|
||||||
|
for (let item of data) {
|
||||||
|
item.key = item.ID;
|
||||||
|
item.title = item.name;
|
||||||
|
if (item.sons) {
|
||||||
|
item.children = item.sons;
|
||||||
|
calcTreeData(item.children);
|
||||||
|
}
|
||||||
|
delete item.ID;
|
||||||
|
delete item.name;
|
||||||
|
delete item.sons;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleValChange = ({ val, config }) => {
|
||||||
|
state.formData[config.field] = val;
|
||||||
|
};
|
||||||
|
const handleValBlur = ({ val, config }) => {
|
||||||
|
if (config.field === "nickName" && state.formData.nickName) {
|
||||||
|
let url = "/user/mail/account";
|
||||||
|
let params = {
|
||||||
|
nickName: val,
|
||||||
|
ID: route.query.ID ? Number(route.query.ID) : null,
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.formData.mailAccount = res.data.mailAccount;
|
||||||
|
} else {
|
||||||
|
processError("生成邮箱错误:" + res.msg);
|
||||||
|
state.formData.mailAccount = "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {},
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
state.tableSearchData = JSON.parse(JSON.stringify(state.formData));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTableRowSelect = ({ record, selected, selectedRows }) => {
|
||||||
|
if (
|
||||||
|
state.depPositions.filter((item) => item.ID === state.clickKey).length === 0
|
||||||
|
) {
|
||||||
|
state.depPositions.push({
|
||||||
|
isLeader: false,
|
||||||
|
ID: state.clickKey,
|
||||||
|
name: state.treeSelectData.title,
|
||||||
|
positions: selectedRows.map((item) => {
|
||||||
|
return {
|
||||||
|
ID: item.ID,
|
||||||
|
name: item.name,
|
||||||
|
color: item.color,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
state.depPositions.forEach((item) => {
|
||||||
|
if (item.ID === state.clickKey) {
|
||||||
|
if (selected) {
|
||||||
|
// 当前部门有其他子岗位时不直接覆盖
|
||||||
|
item.positions = item.positions.filter(
|
||||||
|
(depItem) => depItem.ID !== record.ID
|
||||||
|
);
|
||||||
|
item.positions = item.positions.concat([
|
||||||
|
{
|
||||||
|
ID: record.ID,
|
||||||
|
name: record.name,
|
||||||
|
color: record.color,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
item.positions = item.positions.filter(
|
||||||
|
(depItem) => depItem.ID !== record.ID
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
state.depPositions = state.depPositions.filter((item) => {
|
||||||
|
return item.positions && item.positions.length > 0;
|
||||||
|
});
|
||||||
|
state.selectedRows = selectedRows;
|
||||||
|
};
|
||||||
|
const handleTableCheckAll = ({ selectedRowKeys, selectedRows }) => {
|
||||||
|
if (
|
||||||
|
state.depPositions.filter((item) => item.ID === state.clickKey).length === 0
|
||||||
|
) {
|
||||||
|
state.depPositions.push({
|
||||||
|
isLeader: false,
|
||||||
|
ID: state.clickKey,
|
||||||
|
name: state.treeSelectData.title,
|
||||||
|
positions: selectedRows.map((item) => {
|
||||||
|
return {
|
||||||
|
ID: item.ID,
|
||||||
|
name: item.name,
|
||||||
|
color: item.color,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
state.depPositions.forEach((item) => {
|
||||||
|
if (item.ID === state.clickKey) {
|
||||||
|
item.positions = selectedRows.map((item) => {
|
||||||
|
return {
|
||||||
|
ID: item.ID,
|
||||||
|
name: item.name,
|
||||||
|
color: item.color,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
state.depPositions = state.depPositions.filter((item) => {
|
||||||
|
return item.positions && item.positions.length > 0;
|
||||||
|
});
|
||||||
|
state.selectedRows = selectedRows;
|
||||||
|
};
|
||||||
|
const handleDialogSave = () => {
|
||||||
|
state.dialogDel = false;
|
||||||
|
};
|
||||||
|
const handleDialogBack = () => {
|
||||||
|
state.dialogDel = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTreeClick = ({ selectedKey, tree }) => {
|
||||||
|
state.clickKey = tree.key;
|
||||||
|
state.treeSelectData = tree;
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
};
|
||||||
|
const calcPageDisable = () => {
|
||||||
|
return state.pageType === "view";
|
||||||
|
};
|
||||||
|
const handleSetImg = (item, index) => {
|
||||||
|
state.formData.avatar = "";
|
||||||
|
nextTick(() => {
|
||||||
|
state.formData.avatar = item;
|
||||||
|
state.defaultImgSelect = index;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleCreate = () => {
|
||||||
|
if (
|
||||||
|
state.formData.jobNum === null ||
|
||||||
|
state.formData.jobNum === "" ||
|
||||||
|
state.formData.jobNum === undefined
|
||||||
|
) {
|
||||||
|
processError("请输入员工工号");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.btnLoading = true;
|
||||||
|
state.depPositions = state.depPositions.filter((item) => {
|
||||||
|
return item.positions && item.positions.length > 0;
|
||||||
|
});
|
||||||
|
let url = "/user/v2/create";
|
||||||
|
let params = {
|
||||||
|
depPositions: state.depPositions,
|
||||||
|
};
|
||||||
|
Object.assign(params, state.formData);
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
router.go(-1);
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleSave = () => {
|
||||||
|
if (
|
||||||
|
state.formData.jobNum === null ||
|
||||||
|
state.formData.jobNum === "" ||
|
||||||
|
state.formData.jobNum === undefined
|
||||||
|
) {
|
||||||
|
processError("请输入员工工号");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.btnLoading = true;
|
||||||
|
state.depPositions = state.depPositions.filter((item) => {
|
||||||
|
return item.positions && item.positions.length > 0;
|
||||||
|
});
|
||||||
|
let url = "/user/v2/boss/staff/update";
|
||||||
|
let params = {
|
||||||
|
ID: Number(route.query.ID),
|
||||||
|
depPositions: state.depPositions,
|
||||||
|
};
|
||||||
|
Object.assign(params, state.formData);
|
||||||
|
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
getPageData();
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleLink = (path) => {
|
||||||
|
router.push(path);
|
||||||
|
};
|
||||||
|
const handleBack = () => {
|
||||||
|
router.go(-1);
|
||||||
|
};
|
||||||
|
const calcDepPositions = () => {
|
||||||
|
for (let key in state.depPositions) {
|
||||||
|
let data = state.depPositions[key];
|
||||||
|
if (!data || JSON.stringify(data) === "[]") {
|
||||||
|
delete state.depPositions[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleClearPage = (idx, clearItem) => {
|
||||||
|
state.depPositions[idx].positions.forEach((item, index) => {
|
||||||
|
if (item.name === clearItem.name) {
|
||||||
|
state.depPositions[idx].positions.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.depPositions[idx].positions.length === 0) {
|
||||||
|
state.depPositions.splice(idx, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
state.tableClearKey = clearItem.ID;
|
||||||
|
};
|
||||||
|
const calcSfBgColorWidth = (val) => {
|
||||||
|
if (val) {
|
||||||
|
return val.length * 15 + "px !important";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.avatar-uploader > .ant-upload) {
|
||||||
|
background: #fafafcff;
|
||||||
|
}
|
||||||
|
:deep(.ant-image) {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
:deep(.ant-image-img) {
|
||||||
|
object-fit: cover !important;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
:deep(.ant-image-mask) {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
:deep(.ant-upload) {
|
||||||
|
color: #c1b2e5;
|
||||||
|
}
|
||||||
|
:deep(.ant-select) {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
:deep(.ant-select-selector .ant-select-selection-placeholder) {
|
||||||
|
color: #c3c3c3 !important;
|
||||||
|
&::placeholder {
|
||||||
|
color: #c3c3c3 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.ant-select:not(.ant-select-customize-input) .ant-select-selector) {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.img-avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
margin: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.border-active {
|
||||||
|
border: 2px solid #764cf6;
|
||||||
|
}
|
||||||
|
</style>
|
578
src/views/manage/peomanage/index.vue
Normal file
578
src/views/manage/peomanage/index.vue
Normal file
@ -0,0 +1,578 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row" style="padding: 35px">
|
||||||
|
<div
|
||||||
|
class="col-3 fl-pa-md"
|
||||||
|
style="
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: rgba(188, 188, 188, 0.18) 0px 3px 6px 1px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="row font-16"
|
||||||
|
style="color: #764cf6; border-bottom: 1px solid #c1b2e5"
|
||||||
|
>
|
||||||
|
<div class="fl-py-sm" style="border-bottom: 4px solid #764cf6">
|
||||||
|
组织架构
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" style="height: 76vh; overflow: auto">
|
||||||
|
<fl-tree
|
||||||
|
:data="state.treeData"
|
||||||
|
:expandedKeys="state.expandedKeys"
|
||||||
|
:refreshCount="state.treeRefreshCount"
|
||||||
|
:clickKey="state.clickKey"
|
||||||
|
@triggerTreeClick="handleTreeClick"
|
||||||
|
></fl-tree>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-9 row fl-px-md" style="align-items: flex-start">
|
||||||
|
<fln-table
|
||||||
|
:config="state.tableConfig"
|
||||||
|
:fatherData="state.treeSelectData"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount"
|
||||||
|
@triggerRowActions="handleRowActions"
|
||||||
|
@triggerTableBatchActions="handleTableBatchActions"
|
||||||
|
>
|
||||||
|
<template #search-header>
|
||||||
|
<div
|
||||||
|
class="col-12 row font-18"
|
||||||
|
style="
|
||||||
|
color: #764cf6;
|
||||||
|
border-bottom: 1px solid #c1b2e5;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="fl-py-sm" style="border-bottom: 4px solid #764cf6">
|
||||||
|
{{ state.treeSelectData.title || "平台开发管理项目组" }}所有人员
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<n-button @click="goToPeoManage" v-permission="'per-system-btn'">
|
||||||
|
系统所有人员
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
import flTree from "@/components/flnlayout/tree/flnindex.vue";
|
||||||
|
import { NButton, NPopover } from "naive-ui";
|
||||||
|
import { Local } from "@/utils/storage.js";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
const router = useRouter();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request, $hadRule } =
|
||||||
|
currentInstance.appContext.config.globalProperties;
|
||||||
|
const state = reactive({
|
||||||
|
permission: false,
|
||||||
|
clickKey: "",
|
||||||
|
treeRefreshCount: 0,
|
||||||
|
expandedKeys: [],
|
||||||
|
treeData: [],
|
||||||
|
btnLoading: false,
|
||||||
|
treeSelectData: {},
|
||||||
|
selectedRows: [],
|
||||||
|
tableConfig: {
|
||||||
|
tableScrollWitdh: 600,
|
||||||
|
hasSelection: true,
|
||||||
|
rowKey: "ID",
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "data",
|
||||||
|
pageField: "page",
|
||||||
|
pageSizeField: "pageSize",
|
||||||
|
|
||||||
|
url: "user/v2/list",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
label: "fatherDepartmentId",
|
||||||
|
field: "key",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
searchConfig: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "姓名",
|
||||||
|
field: "nickName",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "手机号",
|
||||||
|
field: "telNum",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
label: "状态",
|
||||||
|
field: "status",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
config: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "有效",
|
||||||
|
value: "notactive",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "无效",
|
||||||
|
value: "left",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "员工工号",
|
||||||
|
field: "jobNum",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "部门",
|
||||||
|
field: "departmentName",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "岗位",
|
||||||
|
field: "positionName",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "邮箱",
|
||||||
|
field: "mailAccount",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "rangdate",
|
||||||
|
label: "入职时间",
|
||||||
|
class: "col-4",
|
||||||
|
field: ["startEnterDate", "endEnterDate"],
|
||||||
|
placeholder: ["开始时间", "结束时间"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
title: "员工工号",
|
||||||
|
field: "jobNum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
title: "姓名",
|
||||||
|
field: "nickName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "tooltip",
|
||||||
|
title: "手机",
|
||||||
|
field: "telNum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 360,
|
||||||
|
title: "归属部门",
|
||||||
|
align: "left",
|
||||||
|
field: "depPositions",
|
||||||
|
type: "tags",
|
||||||
|
tagConfig: {
|
||||||
|
tagField: "name",
|
||||||
|
showLength: 3,
|
||||||
|
bgColor: "#E0E0E6FF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 360,
|
||||||
|
title: $hadRule("posi-edit-btn")
|
||||||
|
? "岗位(可点击岗位修改权限)"
|
||||||
|
: "岗位",
|
||||||
|
align: "left",
|
||||||
|
field: "positions",
|
||||||
|
render(row, index) {
|
||||||
|
const positions = row.positions;
|
||||||
|
if (!positions || positions.length === 0) {
|
||||||
|
return h("span", "No positions available");
|
||||||
|
}
|
||||||
|
// 渲染前3个标签
|
||||||
|
const visibleTags = positions.slice(0, 3).map((position) =>
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
marginRight: "2px",
|
||||||
|
borderWidth: "1px",
|
||||||
|
borderStyle: "solid",
|
||||||
|
color: position.color,
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
if ($hadRule("posi-edit-btn")) {
|
||||||
|
router.push(
|
||||||
|
`/posimanage/create?ID=${position.ID}&&type=edit`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ default: () => position.name }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 如果标签数量超过3个,渲染省略号按钮
|
||||||
|
if (positions.length > 3) {
|
||||||
|
const hiddenTags = positions.slice(3);
|
||||||
|
visibleTags.push(
|
||||||
|
h(
|
||||||
|
NPopover,
|
||||||
|
{
|
||||||
|
trigger: "hover",
|
||||||
|
placement: "bottom",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
trigger: () =>
|
||||||
|
h(
|
||||||
|
"span",
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
marginLeft: "10px",
|
||||||
|
borderWidth: "1px",
|
||||||
|
borderStyle: "solid",
|
||||||
|
color: "#000",
|
||||||
|
cursor: "pointer",
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
padding: "10px 15px",
|
||||||
|
borderRadius: "5px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"..."
|
||||||
|
),
|
||||||
|
default: () =>
|
||||||
|
h(
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
padding: "10px",
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
borderRadius: "5px",
|
||||||
|
boxShadow: "0 2px 12px rgba(0, 0, 0, 0.1)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hiddenTags.map((position) =>
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
marginRight: "2px",
|
||||||
|
borderWidth: "1px",
|
||||||
|
borderStyle: "solid",
|
||||||
|
color: position.color,
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
if ($hadRule("posi-edit-btn")) {
|
||||||
|
router.push(
|
||||||
|
`/posimanage/create?ID=${position.ID}&&type=edit`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ default: () => position.name }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visibleTags;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
width: 260,
|
||||||
|
title: "邮箱",
|
||||||
|
field: "mailAccount",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
type: "avatar",
|
||||||
|
title: "员工头像",
|
||||||
|
field: "avatar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
type: "avatar",
|
||||||
|
title: "员工近照",
|
||||||
|
field: "recentImg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
title: "状态",
|
||||||
|
field: "status",
|
||||||
|
config: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "有效",
|
||||||
|
value: "notactive",
|
||||||
|
class: "color-primary",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "无效",
|
||||||
|
value: "left",
|
||||||
|
class: "color-draft",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
title: "入职时间",
|
||||||
|
field: "enterDate",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 200,
|
||||||
|
title: "最近一次更新时间",
|
||||||
|
field: "updatedAt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 140,
|
||||||
|
fixed: "right",
|
||||||
|
title: "操作人",
|
||||||
|
field: "operatorName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 200,
|
||||||
|
fixed: "right",
|
||||||
|
title: "操作",
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: "act_view",
|
||||||
|
type: "label",
|
||||||
|
label: "查看",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: "act_edit",
|
||||||
|
type: "label",
|
||||||
|
label: "修改",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableBatchActions: [
|
||||||
|
{
|
||||||
|
notLimitSelect: true,
|
||||||
|
actionType: "peo-create",
|
||||||
|
type: "primary",
|
||||||
|
label: "新增人员",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: "peo-pass-set",
|
||||||
|
style: "background:#F7EFFFFF;color:#8352B4FF",
|
||||||
|
type: "primary",
|
||||||
|
label: "重置密码",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getTreeData();
|
||||||
|
});
|
||||||
|
onMounted(() => {});
|
||||||
|
|
||||||
|
const handleRowActions = ({ btnConfig, rowData }) => {
|
||||||
|
state.dialogData = rowData;
|
||||||
|
Local.set("orgmanage_treeSelectData", state.treeSelectData);
|
||||||
|
if (btnConfig.actionType === "act_edit") {
|
||||||
|
router.push(`/peomanage/editPeo?ID=${rowData.ID}&&type=edit`);
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "act_view") {
|
||||||
|
router.push(`/peomanage/editPeo?ID=${rowData.ID}&&type=view`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleTableBatchActions = ({ selectedRows, btnConfig, fatherData }) => {
|
||||||
|
state.selectedRows = selectedRows;
|
||||||
|
if (btnConfig.actionType === "peo-create") {
|
||||||
|
handleCreatePeo();
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "peo-pass-set") {
|
||||||
|
handleResetPass();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCreatePeo = () => {
|
||||||
|
router.push("/peomanage/editPeo");
|
||||||
|
};
|
||||||
|
|
||||||
|
const goToPeoManage = () => {
|
||||||
|
router.push("/peomanage/personnelManage");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleResetPass = () => {
|
||||||
|
state.btnLoading = true;
|
||||||
|
let url = "/user/v2/reset/pwd";
|
||||||
|
let params = {
|
||||||
|
IDs: state.selectedRows.map((item) => item.ID),
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.selectedRows = [];
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
//只有自己的树
|
||||||
|
const getTreeData = () => {
|
||||||
|
let params = {};
|
||||||
|
$request.HTTP.components.viewMyTree(params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0 && Array.isArray(res.data.nodes)) {
|
||||||
|
let data = res.data.nodes;
|
||||||
|
calcTreeData(data);
|
||||||
|
state.treeData = data;
|
||||||
|
|
||||||
|
// 获取最近点击的部门
|
||||||
|
let localSelect = Local.get("orgmanage_treeSelectData");
|
||||||
|
if (localSelect && JSON.stringify(localSelect) !== "{}") {
|
||||||
|
state.treeSelectData = localSelect;
|
||||||
|
state.expandedKeys = localSelect.pathIds;
|
||||||
|
state.clickKey = localSelect.key;
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
state.treeRefreshCount++;
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
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 handleTreeClick = ({ selectedKey, tree }) => {
|
||||||
|
state.clickKey = tree.key;
|
||||||
|
state.treeSelectData = tree;
|
||||||
|
Local.set("orgmanage_treeSelectData", state.treeSelectData);
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.ant-select) {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
:deep(.ant-select-selector .ant-select-selection-placeholder) {
|
||||||
|
color: #c3c3c3 !important;
|
||||||
|
&::placeholder {
|
||||||
|
color: #c3c3c3 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.ant-select:not(.ant-select-customize-input) .ant-select-selector) {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
483
src/views/manage/peomanage/personnelManage.vue
Normal file
483
src/views/manage/peomanage/personnelManage.vue
Normal file
@ -0,0 +1,483 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row"
|
||||||
|
style="padding: 35px">
|
||||||
|
<div class="col-12 row">
|
||||||
|
<fln-table :config="state.tableConfig"
|
||||||
|
:fatherData="state.treeSelectData"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount"
|
||||||
|
@triggerRowActions="handleRowActions"
|
||||||
|
@triggerTableBatchActions="handleTableBatchActions">
|
||||||
|
<template #search-header>
|
||||||
|
<div class="col-12 row font-18"
|
||||||
|
style="color: #764cf6; border-bottom: 1px solid #c1b2e5; display: flex; justify-content: space-between; align-items: center;">
|
||||||
|
<div class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6">
|
||||||
|
系统所有人员
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<n-button @click="goToIndex">
|
||||||
|
返回部门人员
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<n-modal v-model:show="state.dialogDel"
|
||||||
|
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 v-if="state.dialogData.type === 'one'"
|
||||||
|
class="font-20"
|
||||||
|
style="color: #1f2225ff; margin: 80px 0">
|
||||||
|
确定删除该人员吗? 删除后将不可恢复!
|
||||||
|
</div>
|
||||||
|
<div v-if="state.dialogData.type === 'batch'"
|
||||||
|
class="font-20"
|
||||||
|
style="color: #1f2225ff; margin: 80px 0">
|
||||||
|
确定删除选中的人员吗? 删除后将不可恢复!
|
||||||
|
</div>
|
||||||
|
<div class="col-12 row justify-center">
|
||||||
|
<n-button tertiary
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #fff"
|
||||||
|
class="fl-mr-md"
|
||||||
|
@click="handleDialogBack">返回</n-button>
|
||||||
|
|
||||||
|
<n-button tertiary
|
||||||
|
style="width: 161px; background: #46299dff; color: #fff"
|
||||||
|
@click="handleDialogSave">确定</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</n-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
import { NButton } from "naive-ui";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
const router = useRouter();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
const state = reactive({
|
||||||
|
dialogDel: false,
|
||||||
|
dialogData: {},
|
||||||
|
|
||||||
|
btnLoading: false,
|
||||||
|
selectedRows: [],
|
||||||
|
tableConfig: {
|
||||||
|
tableScrollWitdh: 600,
|
||||||
|
hasSelection: true,
|
||||||
|
rowKey: "ID",
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "data",
|
||||||
|
pageField: "page",
|
||||||
|
pageSizeField: "pageSize",
|
||||||
|
url: "user/v2/list",
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
searchConfig: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "姓名",
|
||||||
|
field: "nickName",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "手机号",
|
||||||
|
field: "telNum",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
label: "状态",
|
||||||
|
field: "status",
|
||||||
|
placeholder: "",
|
||||||
|
config: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "有效",
|
||||||
|
value: "notactive",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "无效",
|
||||||
|
value: "left",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "员工工号",
|
||||||
|
field: "jobNum",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "部门",
|
||||||
|
field: "departmentName",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "岗位",
|
||||||
|
field: "positionName",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "邮箱",
|
||||||
|
field: "mailAccount",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "rangdate",
|
||||||
|
label: "入职时间",
|
||||||
|
field: ["startEnterDate", "endEnterDate"],
|
||||||
|
placeholder: ["开始时间", "结束时间"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
title: "员工工号",
|
||||||
|
field: "jobNum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
title: "姓名",
|
||||||
|
field: "nickName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "tooltip",
|
||||||
|
title: "手机",
|
||||||
|
field: "telNum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 360,
|
||||||
|
title: "归属部门",
|
||||||
|
align: 'left',
|
||||||
|
field: "depPositions",
|
||||||
|
type: "tags",
|
||||||
|
tagConfig: {
|
||||||
|
tagField: "name",
|
||||||
|
showLength: 3,
|
||||||
|
bgColor: "#E0E0E6FF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 360,
|
||||||
|
title: "岗位",
|
||||||
|
align: 'left',
|
||||||
|
field: "positions",
|
||||||
|
type: "tags",
|
||||||
|
tagConfig: {
|
||||||
|
tagField: "name",
|
||||||
|
tagBgColorField: "color",
|
||||||
|
showLength: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 260,
|
||||||
|
title: "邮箱",
|
||||||
|
field: "mailAccount",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
type: "avatar",
|
||||||
|
title: "员工头像",
|
||||||
|
field: "avatar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
type: "avatar",
|
||||||
|
title: "员工近照",
|
||||||
|
field: "recentImg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
title: "状态",
|
||||||
|
field: "status",
|
||||||
|
config: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "有效",
|
||||||
|
value: "notactive",
|
||||||
|
class: "color-primary",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "无效",
|
||||||
|
value: "left",
|
||||||
|
class: "color-draft",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
title: "入职时间",
|
||||||
|
field: "enterDate",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 160,
|
||||||
|
title: "最近一次更新时间",
|
||||||
|
field: "updatedAt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 140,
|
||||||
|
fixed: "right",
|
||||||
|
title: "操作人",
|
||||||
|
field: "operatorName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 200,
|
||||||
|
fixed: "right",
|
||||||
|
title: "操作",
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: "act_view",
|
||||||
|
type: "label",
|
||||||
|
label: "查看",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: "act_edit",
|
||||||
|
type: "label",
|
||||||
|
label: "修改",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: "act_del",
|
||||||
|
type: "label",
|
||||||
|
label: "删除",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableBatchActions: [
|
||||||
|
{
|
||||||
|
notLimitSelect: true,
|
||||||
|
actionType: "peo-create",
|
||||||
|
type: "primary",
|
||||||
|
label: "新建人员",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: "peo-pass-set",
|
||||||
|
style: "background:#F7EFFFFF;color:#8352B4FF",
|
||||||
|
type: "primary",
|
||||||
|
label: "重置密码",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
onBeforeMount(() => { });
|
||||||
|
onMounted(() => { });
|
||||||
|
|
||||||
|
const handleRowActions = ({ btnConfig, rowData }) => {
|
||||||
|
state.dialogData = rowData;
|
||||||
|
if (btnConfig.actionType === "act_del") {
|
||||||
|
if (rowData.status !== "left") {
|
||||||
|
processError("该人员在职,不可删除");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.dialogData.type = "one";
|
||||||
|
state.dialogDel = true;
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "act_edit") {
|
||||||
|
router.push(`/peomanage/create?ID=${rowData.ID}&&type=edit`);
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "act_view") {
|
||||||
|
router.push(`/peomanage/create?ID=${rowData.ID}&&type=view`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleTableBatchActions = ({ selectedRows, btnConfig, fatherData }) => {
|
||||||
|
state.selectedRows = selectedRows
|
||||||
|
|
||||||
|
if (btnConfig.actionType === "peo-create") {
|
||||||
|
handleCreatePeo();
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "peo-pass-set") {
|
||||||
|
handleResetPass();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const goToIndex = () => {
|
||||||
|
router.push("/peomanage");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCreatePeo = () => {
|
||||||
|
router.push("/peomanage/create");
|
||||||
|
};
|
||||||
|
const handleResetPass = () => {
|
||||||
|
state.btnLoading = true;
|
||||||
|
let url = "/user/v2/reset/pwd";
|
||||||
|
let params = {
|
||||||
|
IDs: state.selectedRows.map((item) => item.ID),
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.selectedRows = [];
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteBatch = () => {
|
||||||
|
state.dialogData.type = "batch";
|
||||||
|
state.dialogDel = true;
|
||||||
|
};
|
||||||
|
const handleDeleteBatchSave = () => {
|
||||||
|
state.btnLoading = true;
|
||||||
|
let url = "/user/v2/batch/remove";
|
||||||
|
let params = {
|
||||||
|
IDs: state.selectedRows.map((item) => item.ID),
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.selectedRows = [];
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
state.dialogDel = false;
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
state.dialogDel = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
state.dialogDel = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleDialogSave = () => {
|
||||||
|
if (state.dialogData.type === "batch") {
|
||||||
|
handleDeleteBatchSave();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.btnLoading = true;
|
||||||
|
let url = "/user/v2/remove";
|
||||||
|
let params = {
|
||||||
|
ID: state.dialogData.ID,
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
state.dialogDel = false;
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
state.dialogDel = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
state.dialogDel = false;
|
||||||
|
state.btnLoading = false;
|
||||||
|
processError("操作失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleDialogBack = () => {
|
||||||
|
state.dialogDel = false;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.ant-select) {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
:deep(.ant-select-selector .ant-select-selection-placeholder) {
|
||||||
|
color: #c3c3c3 !important;
|
||||||
|
&::placeholder {
|
||||||
|
color: #c3c3c3 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.ant-select:not(.ant-select-customize-input) .ant-select-selector) {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
311
src/views/manage/posimanage/aboutApproval.vue
Normal file
311
src/views/manage/posimanage/aboutApproval.vue
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
<template>
|
||||||
|
<n-modal v-model:show="state.dialogModal" :mask-closable="false">
|
||||||
|
<n-card
|
||||||
|
style="width: 80vw"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<template #header-extra>
|
||||||
|
<n-button @click="triggerCalcApproval" text style="font-size: 24px">
|
||||||
|
<n-icon>
|
||||||
|
<close-icon />
|
||||||
|
</n-icon>
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
<div class="row justify-center fl-pa-md" style="color: #333639">
|
||||||
|
<div class="row col-12 fl-mt-lg">
|
||||||
|
<div class="col-12">请选择审批类型</div>
|
||||||
|
<div class="col-12 fl-mt-md overflow-auto" style="height: 60vh">
|
||||||
|
<fln-table
|
||||||
|
:config="state.tableConfig"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount"
|
||||||
|
@triggerSelectCheck="handleTableSelectCheck"
|
||||||
|
>
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 row justify-center fl-mt-md">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #fff"
|
||||||
|
class="fl-mr-md"
|
||||||
|
@click="triggerCalcApproval"
|
||||||
|
>上一步</n-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #46299dff; color: #fff"
|
||||||
|
:disabled="state.selectedRows.length === 0"
|
||||||
|
@click="triggerCalcApproval('submit')"
|
||||||
|
>确定</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
// 岗位新建中 选模版时的添加审批
|
||||||
|
import {
|
||||||
|
UpOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
CloseCircleOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
DragOutlined,
|
||||||
|
} from "@ant-design/icons-vue";
|
||||||
|
import flnFormItem from "@/components/flnlayout/form/flnformItem.vue";
|
||||||
|
import flAboutApproval from "./aboutApproval.vue";
|
||||||
|
import draggable from "vuedraggable";
|
||||||
|
import { Close as CloseIcon } from "@vicons/ionicons5";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter, useRoute } from "vue-router";
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
import { ChevronDownOutline, ChevronUpOutline } from "@vicons/ionicons5";
|
||||||
|
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
const emit = defineEmits(["triggerCalcApproval"]);
|
||||||
|
const state = reactive({
|
||||||
|
btnLoading: false,
|
||||||
|
dialogModal: true,
|
||||||
|
tableConfig: {
|
||||||
|
tableScrollWitdh: 600,
|
||||||
|
rowKey: "ID",
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "GroupList",
|
||||||
|
url: "/approval/v2/only-group",
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: "审批类型分组",
|
||||||
|
field: "Title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
field: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
field: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
field: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
field: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
field: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
expandConfig: {
|
||||||
|
defaultSelectedRows: [],
|
||||||
|
tableScrollWitdh: 600,
|
||||||
|
rowKey: "ID",
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "TypeList",
|
||||||
|
url: "/approval/v2/type/all",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
label: "domain",
|
||||||
|
field: "Domain",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "groupId",
|
||||||
|
field: "ID",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
type: "selection",
|
||||||
|
width: 50,
|
||||||
|
disabled(row) {
|
||||||
|
return row.Auths[0].UserID !== 0 || row.Auths[0].IsAll !== 0;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "流程名称",
|
||||||
|
field: "Title",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "发起人",
|
||||||
|
dataIndex: "Auths",
|
||||||
|
key: "Auths",
|
||||||
|
render(row) {
|
||||||
|
return h(
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
style:
|
||||||
|
"word-break:break-all;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;",
|
||||||
|
title: `${getAuths(row?.Auths)}`,
|
||||||
|
},
|
||||||
|
`${getAuths(row?.Auths)}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "审批节点",
|
||||||
|
key: "ApprovalUsers",
|
||||||
|
dataIndex: "ApprovalUsers",
|
||||||
|
render(row) {
|
||||||
|
return h("div", {}, `${getApprovalUsers(row?.ApprovalUsers)}`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "抄送",
|
||||||
|
dataIndex: "CopyUsers",
|
||||||
|
key: "CopyUsers",
|
||||||
|
render(row) {
|
||||||
|
return h(
|
||||||
|
"div",
|
||||||
|
{},
|
||||||
|
`${
|
||||||
|
Array.isArray(row.CopyUsers)
|
||||||
|
? row.CopyUsers.map((item) =>
|
||||||
|
item.ID !== 0
|
||||||
|
? item.Name
|
||||||
|
: `${item.DepartmentName}-${item.PositionName}`
|
||||||
|
).join(",")
|
||||||
|
: "-"
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "备注",
|
||||||
|
dataIndex: "Remark",
|
||||||
|
key: "Remark",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
selectedRows: [],
|
||||||
|
});
|
||||||
|
onBeforeMount(() => {
|
||||||
|
state.dialogModal = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {});
|
||||||
|
const getAuths = (auths) => {
|
||||||
|
if (auths) {
|
||||||
|
if (auths && auths.length === 1 && auths[0].IsAll === 1) {
|
||||||
|
return "全公司人员";
|
||||||
|
} else {
|
||||||
|
return auths
|
||||||
|
.filter((item) => item.IsAll === 0)
|
||||||
|
.map((item) =>
|
||||||
|
item.Name ? item.Name : item.DepartmentName + item.PositionName
|
||||||
|
)
|
||||||
|
.filter(Boolean)
|
||||||
|
.join("—");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getApprovalUsers = (userList) => {
|
||||||
|
let user = "";
|
||||||
|
if (userList) {
|
||||||
|
user = userList
|
||||||
|
.filter((item) => item.DepartmentUID !== "undefined")
|
||||||
|
.map((item) => {
|
||||||
|
return {
|
||||||
|
flow:
|
||||||
|
item.IsDirect === 1 && item.IsDesignate === 1
|
||||||
|
? `直属第${item.Level}级`
|
||||||
|
: item.IsDirect === 1
|
||||||
|
? `直属${item.Level}级`
|
||||||
|
: item.Name
|
||||||
|
? item.Name
|
||||||
|
: item.DepartmentName + item.PositionName,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.map((item) => item.flow)
|
||||||
|
.join("—");
|
||||||
|
} else {
|
||||||
|
user = "";
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
};
|
||||||
|
const triggerCalcApproval = (type) => {
|
||||||
|
if (type === "submit") {
|
||||||
|
emit("triggerCalcApproval", state.selectedRows);
|
||||||
|
} else {
|
||||||
|
emit("triggerCalcApproval", []);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleTableSelectCheck = (data) => {
|
||||||
|
if (data && Array.isArray(data.selectedRow)) {
|
||||||
|
data.selectedRow = data.selectedRow.filter((item) => {
|
||||||
|
if (item) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.action === "check" || data.action === "checkAll") {
|
||||||
|
state.selectedRows = state.selectedRows.concat(data.selectedRow);
|
||||||
|
state.selectedRows = state.selectedRows.filter((item, index, arr) => {
|
||||||
|
return (
|
||||||
|
arr.findIndex((obj) => JSON.stringify(obj) === JSON.stringify(item)) ===
|
||||||
|
index
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.action === "uncheck") {
|
||||||
|
state.selectedRows = state.selectedRows.filter((item) => {
|
||||||
|
return item.ID !== data.selectedRow.ID;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.action === "uncheckAll") {
|
||||||
|
state.selectedRows = state.selectedRows.filter((item) => {
|
||||||
|
return (
|
||||||
|
data.selectedRow.findIndex((obj) => {
|
||||||
|
return obj.ID === item.ID;
|
||||||
|
}) === -1
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
state.tableConfig.expandConfig.defaultSelectedRows = state.selectedRows;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:deep(
|
||||||
|
.fln-table
|
||||||
|
.n-data-table-table
|
||||||
|
.n-checkbox.n-checkbox--disabled
|
||||||
|
.n-checkbox-box
|
||||||
|
) {
|
||||||
|
background-color: #d5d5d5 !important;
|
||||||
|
}
|
||||||
|
</style>
|
156
src/views/manage/posimanage/components/flnindex.vue
Normal file
156
src/views/manage/posimanage/components/flnindex.vue
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<template>
|
||||||
|
<div class="fl-tree width-100 fl-mt-md">
|
||||||
|
<div class="row justify-end">
|
||||||
|
<div style="margin-right: 220px">是否为销售部门</div>
|
||||||
|
</div>
|
||||||
|
<n-tree
|
||||||
|
v-if="state.treeLoading"
|
||||||
|
block-line
|
||||||
|
:default-expanded-keys="state.expandedKeys"
|
||||||
|
:default-selected-keys="state.clickKey"
|
||||||
|
label-field="name"
|
||||||
|
key-field="key"
|
||||||
|
:expand-on-click="true"
|
||||||
|
:render-label="renderLabel"
|
||||||
|
:data="state.treeData"
|
||||||
|
@update:selected-keys="handleSelectTree"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
defineEmits,
|
||||||
|
watch,
|
||||||
|
nextTick,
|
||||||
|
} from "vue";
|
||||||
|
|
||||||
|
import treeLabel from "./treelabel.vue";
|
||||||
|
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
let props = defineProps({
|
||||||
|
data: Object,
|
||||||
|
refreshCount: Number,
|
||||||
|
config: Object,
|
||||||
|
expandedKeys: Array,
|
||||||
|
clickKey: [String, Number],
|
||||||
|
});
|
||||||
|
const state = reactive({
|
||||||
|
expandedKeys: [],
|
||||||
|
editTitle: "",
|
||||||
|
treeData: [],
|
||||||
|
clickKey: [],
|
||||||
|
treeLoading: true,
|
||||||
|
selectOptions: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.refreshCount,
|
||||||
|
() => {
|
||||||
|
state.clickKey = [props.clickKey];
|
||||||
|
state.treeLoading = false;
|
||||||
|
nextTick(() => {
|
||||||
|
state.treeData = props.data;
|
||||||
|
calcDefaultConfig(state.treeData, 1);
|
||||||
|
state.treeLoading = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.expandedKeys,
|
||||||
|
() => {
|
||||||
|
state.clickKey = [props.clickKey];
|
||||||
|
state.expandedKeys = props.expandedKeys;
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
state.clickKey = [props.clickKey];
|
||||||
|
state.treeData = props.data;
|
||||||
|
calcDefaultConfig(state.treeData, 1);
|
||||||
|
state.expandedKeys = state.treeData.map((item) => item.key);
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getSelectOptions();
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits([
|
||||||
|
"triggerTreeAction",
|
||||||
|
"triggerTreeClick",
|
||||||
|
"triggerTreeDefaultClick",
|
||||||
|
]);
|
||||||
|
const handleSelectTree = (keys, option, meta) => {
|
||||||
|
if (keys.length === 1) {
|
||||||
|
emit("triggerTreeClick", { selectedKey: keys[0], tree: option[0] });
|
||||||
|
} else {
|
||||||
|
emit("triggerTreeDefaultClick");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const renderLabel = (option, checked) => {
|
||||||
|
return h(
|
||||||
|
treeLabel,
|
||||||
|
{
|
||||||
|
dataRef: option,
|
||||||
|
checked: checked,
|
||||||
|
config: props.config,
|
||||||
|
clickKey: props.clickKey,
|
||||||
|
options: state.selectOptions,
|
||||||
|
onTriggerTreeAction: handleTreeAction,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const calcDefaultConfig = (data, level) => {
|
||||||
|
for (let item of data) {
|
||||||
|
if (!item.key) {
|
||||||
|
item.key = item.title + "_" + level;
|
||||||
|
}
|
||||||
|
item.edit = false;
|
||||||
|
if (item.children) {
|
||||||
|
calcDefaultConfig(item.children, level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const override = ({ option }) => {
|
||||||
|
if (option.children) {
|
||||||
|
return "toggleExpand";
|
||||||
|
}
|
||||||
|
return "default";
|
||||||
|
};
|
||||||
|
const handleTreeAction = ({ type, val }) => {
|
||||||
|
emit("triggerTreeAction", { type, val });
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSelectOptions = () => {
|
||||||
|
let url = "department/head/list";
|
||||||
|
let params = {};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
let resData = res.data.list || [];
|
||||||
|
state.selectOptions = resData.filter((item) => item.alias);
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
240
src/views/manage/posimanage/components/treelabel.vue
Normal file
240
src/views/manage/posimanage/components/treelabel.vue
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row items-center">
|
||||||
|
<div v-if="state.treeData.edit">
|
||||||
|
<n-input v-model:value="state.editTitle" style="width: 120px" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<n-popover trigger="hover" v-else>
|
||||||
|
<template #trigger>
|
||||||
|
<div style="width: 120px" class="fl-px-sm sf-text-ellipsis">
|
||||||
|
{{ state.treeData.title }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div>{{ state.treeData.title }}</div>
|
||||||
|
</n-popover>
|
||||||
|
<div class="row" style="width: calc(100% - 120px)">
|
||||||
|
<div class="col-4 row items-center">
|
||||||
|
<n-icon
|
||||||
|
:component="CreateOutline"
|
||||||
|
class="fl-ml-sm"
|
||||||
|
size="20"
|
||||||
|
v-if="config?.actions.includes('edit') && !state.treeData.edit"
|
||||||
|
@click.stop="handleTreeEdit(state.treeData)"
|
||||||
|
/>
|
||||||
|
<n-icon
|
||||||
|
:component="Remove"
|
||||||
|
size="20"
|
||||||
|
v-if="
|
||||||
|
config?.actions.includes('subtraction') &&
|
||||||
|
!state.treeData.edit &&
|
||||||
|
visibleFormItem(config.subtractionShow, state.treeData)
|
||||||
|
"
|
||||||
|
class="fl-ml-sm"
|
||||||
|
@click.stop="handleTreeSubtraction(state.treeData)"
|
||||||
|
/>
|
||||||
|
<n-icon
|
||||||
|
:component="Add"
|
||||||
|
size="20"
|
||||||
|
v-if="
|
||||||
|
config?.actions.includes('add') &&
|
||||||
|
!state.treeData.edit &&
|
||||||
|
visibleFormItem(config.addShow, state.treeData)
|
||||||
|
"
|
||||||
|
class="fl-ml-sm"
|
||||||
|
@click.stop="handleTreeAdd(state.treeData)"
|
||||||
|
/>
|
||||||
|
<drag-outlined
|
||||||
|
v-if="
|
||||||
|
config?.actions.includes('move') &&
|
||||||
|
!state.treeData.edit &&
|
||||||
|
visibleFormItem(config.moveShow, state.treeData)
|
||||||
|
"
|
||||||
|
class="fl-ml-sm"
|
||||||
|
@click.stop="handleTreeMove(state.treeData)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- <n-icon :component="MoveOutline"
|
||||||
|
size="20"
|
||||||
|
v-if="config?.actions.includes('move')&&!state.treeData.edit&&visibleFormItem(config.moveShow, state.treeData)"
|
||||||
|
class="fl-ml-sm"
|
||||||
|
@click.stop="handleTreeMove(state.treeData)" /> -->
|
||||||
|
|
||||||
|
<n-icon
|
||||||
|
:component="Checkmark"
|
||||||
|
size="20"
|
||||||
|
v-if="state.treeData.edit"
|
||||||
|
class="fl-ml-sm"
|
||||||
|
@click.stop="handleTreeSave(state.treeData)"
|
||||||
|
/>
|
||||||
|
<n-icon
|
||||||
|
:component="Close"
|
||||||
|
size="20"
|
||||||
|
v-if="state.treeData.edit"
|
||||||
|
class="fl-ml-md"
|
||||||
|
@click.stop="handleTreeNotSave(state.treeData)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 row items-center justify-end" @click.stop>
|
||||||
|
<div>
|
||||||
|
<n-radio-group
|
||||||
|
v-model:value="state.radioVal"
|
||||||
|
@update:value="handleRadioChange"
|
||||||
|
>
|
||||||
|
<n-space>
|
||||||
|
<n-radio :value="true"> 是 </n-radio>
|
||||||
|
<n-radio :value="false"> 否 </n-radio>
|
||||||
|
</n-space>
|
||||||
|
</n-radio-group>
|
||||||
|
</div>
|
||||||
|
<div class="fl-ml-md" style="width: 200px" @click="handleSelectClick">
|
||||||
|
<n-select
|
||||||
|
v-model:value="state.selectVal"
|
||||||
|
size="small"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择对应部门"
|
||||||
|
label-field="alias"
|
||||||
|
value-field="storeId"
|
||||||
|
:options="options"
|
||||||
|
@update:value="handleSelectChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onBeforeMount, onMounted, watch, getCurrentInstance } from "vue";
|
||||||
|
import { visibleFormItem } from "@/utils/helper/form";
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
import {
|
||||||
|
UpOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
CloseCircleOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
DragOutlined,
|
||||||
|
} from "@ant-design/icons-vue";
|
||||||
|
import {
|
||||||
|
Add,
|
||||||
|
Checkmark,
|
||||||
|
Close,
|
||||||
|
CreateOutline,
|
||||||
|
Remove,
|
||||||
|
MoveOutline,
|
||||||
|
} from "@vicons/ionicons5";
|
||||||
|
let props = defineProps({
|
||||||
|
dataRef: Object,
|
||||||
|
checked: Boolean,
|
||||||
|
config: Object,
|
||||||
|
clickKey: [String, Number],
|
||||||
|
options: Array,
|
||||||
|
});
|
||||||
|
const state = reactive({
|
||||||
|
expandedKeys: [],
|
||||||
|
editTitle: "",
|
||||||
|
treeData: [],
|
||||||
|
radioVal: null,
|
||||||
|
selectVal: null,
|
||||||
|
});
|
||||||
|
onBeforeMount(() => {
|
||||||
|
state.treeData = props.dataRef.option;
|
||||||
|
state.radioVal = state.treeData.sync;
|
||||||
|
if (state.treeData.syncId) {
|
||||||
|
state.selectVal = state.treeData.syncId * 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
watch(
|
||||||
|
() => props.dataRef.option,
|
||||||
|
(val) => {
|
||||||
|
state.treeData = props.dataRef.option;
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {});
|
||||||
|
const emit = defineEmits(["triggerTreeAction", "triggerTreeClick"]);
|
||||||
|
|
||||||
|
// const myComponentRef = ref(null);
|
||||||
|
const handleTreeEdit = () => {
|
||||||
|
state.editTitle = state.treeData.title;
|
||||||
|
state.treeData.edit = true;
|
||||||
|
// myComponentRef.value.$forceUpdate();
|
||||||
|
};
|
||||||
|
const handleTreeAdd = () => {
|
||||||
|
emit("triggerTreeAction", { type: "add", val: state.treeData });
|
||||||
|
};
|
||||||
|
const handleTreeMove = () => {
|
||||||
|
emit("triggerTreeAction", { type: "move", val: state.treeData });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTreeSubtraction = () => {
|
||||||
|
emit("triggerTreeAction", { type: "subtraction", val: state.treeData });
|
||||||
|
};
|
||||||
|
const handleTreeSave = () => {
|
||||||
|
state.treeData.title = state.editTitle;
|
||||||
|
emit("triggerTreeAction", { type: "save", val: state.treeData });
|
||||||
|
};
|
||||||
|
const handleTreeNotSave = () => {
|
||||||
|
state.editTitle = "";
|
||||||
|
emit("triggerTreeAction", { type: "cancel", val: state.treeData });
|
||||||
|
};
|
||||||
|
const handleRadioChange = (val) => {
|
||||||
|
let url = "department/v2/update";
|
||||||
|
let params = {
|
||||||
|
ID: state.treeData.key,
|
||||||
|
name: state.treeData.title,
|
||||||
|
sync: val,
|
||||||
|
syncID: state.treeData.syncId,
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.treeData.sync = val;
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleSelectChange = (val) => {
|
||||||
|
let syncID = "";
|
||||||
|
if (val === null || val === undefined || val === "") {
|
||||||
|
syncID = "";
|
||||||
|
} else {
|
||||||
|
syncID = val + "";
|
||||||
|
}
|
||||||
|
let url = "department/v2/update";
|
||||||
|
let params = {
|
||||||
|
ID: state.treeData.key,
|
||||||
|
name: state.treeData.title,
|
||||||
|
sync: state.treeData.sync,
|
||||||
|
syncID: syncID,
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.treeData.syncId = syncID;
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleSelectClick = () => {
|
||||||
|
console.log(props.options);
|
||||||
|
};
|
||||||
|
</script>
|
1324
src/views/manage/posimanage/create.vue
Normal file
1324
src/views/manage/posimanage/create.vue
Normal file
File diff suppressed because it is too large
Load Diff
942
src/views/manage/posimanage/dialogCreate.vue
Normal file
942
src/views/manage/posimanage/dialogCreate.vue
Normal file
@ -0,0 +1,942 @@
|
|||||||
|
<template>
|
||||||
|
<n-modal v-model:show="state.dialogModal" :mask-closable="false">
|
||||||
|
<n-card
|
||||||
|
style="width: 1050px"
|
||||||
|
:bordered="false"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="col-12 row justify-center relative">
|
||||||
|
<div style="font-size: 20px; font-weight: bold; color: #1f2225ff">
|
||||||
|
新增岗位
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #header-extra>
|
||||||
|
<n-button @click="handleDialogBack" text style="font-size: 24px">
|
||||||
|
<n-icon>
|
||||||
|
<close-icon />
|
||||||
|
</n-icon>
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="row justify-center fl-pb-md" style="color: #333639">
|
||||||
|
<div class="col-12 row">
|
||||||
|
<div class="search-item fl-mb-sm row items-center">
|
||||||
|
<div>*岗位名</div>
|
||||||
|
<fln-form-item
|
||||||
|
style="width: 180px; margin-left: 45px"
|
||||||
|
type="text"
|
||||||
|
:config="{
|
||||||
|
placeholder: '请输入岗位名',
|
||||||
|
field: 'name',
|
||||||
|
}"
|
||||||
|
:val="state.formData.name"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-item fl-mb-sm row items-center">
|
||||||
|
<div style="margin-left: 16px">岗位描述</div>
|
||||||
|
<fln-form-item
|
||||||
|
style="width: 180px; margin-left: 38px"
|
||||||
|
type="text"
|
||||||
|
:config="{
|
||||||
|
placeholder: '请输入岗位描述',
|
||||||
|
field: 'remark',
|
||||||
|
}"
|
||||||
|
:val="state.formData.remark"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-item fl-mb-sm row items-center">
|
||||||
|
<div style="margin-left: 16px">标签颜色</div>
|
||||||
|
<fln-form-item
|
||||||
|
style="width: 122px; margin-left: 38px"
|
||||||
|
type="colorpicker"
|
||||||
|
:val="state.formData.color"
|
||||||
|
:config="{
|
||||||
|
field: 'color',
|
||||||
|
}"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-item fl-mb-sm row items-center">
|
||||||
|
<fln-form-item
|
||||||
|
style="margin-left: 38px"
|
||||||
|
type="checkbox"
|
||||||
|
:val="state.formData.isOwner"
|
||||||
|
:config="{
|
||||||
|
field: 'isOwner',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '设为部门负责人',
|
||||||
|
value: 'true',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}"
|
||||||
|
@triggerValChange="handleValChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row col-12 fl-mt-sm">
|
||||||
|
<div class="col-12 row justify-between fl-mt-md fl-mb-sm">
|
||||||
|
<div>请选择以下模板进行新增岗位:</div>
|
||||||
|
<div>
|
||||||
|
可将该岗位模板加入到审批中,<span
|
||||||
|
class="cursor"
|
||||||
|
style="color: #6c00ff"
|
||||||
|
@click="state.dialogApproval = true"
|
||||||
|
>去试试</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<fl-about-approval
|
||||||
|
:show="state.dialogApproval"
|
||||||
|
@triggerCalcApproval="handleApproval"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="col-12 row">
|
||||||
|
<div
|
||||||
|
v-for="(temp, tempidx) in state.tempList"
|
||||||
|
:key="tempidx"
|
||||||
|
class="fl-py-xs text-center cursor fl-mr-sm fl-mb-sm row justify-center items-center"
|
||||||
|
:style="[
|
||||||
|
state.selectTemplate === temp.name
|
||||||
|
? { border: '1px solid #46299d' }
|
||||||
|
: {},
|
||||||
|
]"
|
||||||
|
style="
|
||||||
|
border-radius: 3px;
|
||||||
|
min-width: 176px;
|
||||||
|
background: #f7efff;
|
||||||
|
color: #8352b4;
|
||||||
|
"
|
||||||
|
@click="handleTempClick(temp)"
|
||||||
|
>
|
||||||
|
{{ temp.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="fl-my-lg row col-12">
|
||||||
|
<div class="col-2 font-14 fl-mb-md">已选模版:</div>
|
||||||
|
<div class="col-10 row items-center fl-mb-md">
|
||||||
|
<div
|
||||||
|
class="fl-py-xs text-center row justify-center items-center"
|
||||||
|
style="
|
||||||
|
border-radius: 3px;
|
||||||
|
min-width: 193px;
|
||||||
|
background: #f7f7f7ff;
|
||||||
|
border: solid 1px #e0e0e5ff;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ state.selectTemplate }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 font-14">
|
||||||
|
*所选页面
|
||||||
|
<span style="color: #1f2225ff">{{
|
||||||
|
state.selectedRows.length
|
||||||
|
}}</span>
|
||||||
|
个:
|
||||||
|
</div>
|
||||||
|
<n-spin
|
||||||
|
class="fl-ml-md"
|
||||||
|
v-if="state.dataLoading"
|
||||||
|
v-show="state.dataLoading"
|
||||||
|
description="获取中..."
|
||||||
|
style="color: #1f2225ff"
|
||||||
|
/>
|
||||||
|
<div v-else class="col-10 row">
|
||||||
|
<div
|
||||||
|
v-for="(select, idx) in state.selectedRows"
|
||||||
|
:key="idx"
|
||||||
|
class="fl-py-xs text-center fl-mr-sm fl-mb-sm row justify-center items-center"
|
||||||
|
style="
|
||||||
|
border-radius: 3px;
|
||||||
|
min-width: 193px;
|
||||||
|
background: #f7f7f7ff;
|
||||||
|
border: solid 1px #e0e0e5ff;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<n-tooltip trigger="hover">
|
||||||
|
<template #trigger>
|
||||||
|
{{ select.name }}
|
||||||
|
</template>
|
||||||
|
{{ select.name }}
|
||||||
|
</n-tooltip>
|
||||||
|
<close-circle-outlined
|
||||||
|
class="fl-ml-md"
|
||||||
|
@click="handleClearPage(select)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="row items-center fl-mr-sm fl-mb-sm">
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #e0e0e5;
|
||||||
|
width: 27px;
|
||||||
|
height: 27px;
|
||||||
|
"
|
||||||
|
class="row items-center justify-center fl-mr-sm cursor"
|
||||||
|
@click="handleEditSelectTemp"
|
||||||
|
>
|
||||||
|
<n-icon>
|
||||||
|
<ChevronUpOutline v-if="state.showTempRuleListData" />
|
||||||
|
<ChevronDownOutline v-else />
|
||||||
|
</n-icon>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span style="color: rgba(0, 0, 0, 0.3)">点击展开可进行编辑</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="state.showTempRuleListData"
|
||||||
|
style="max-height: 40vh"
|
||||||
|
class="overflow-auto col-12 row"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(row, rowIdx) in state.listData"
|
||||||
|
:key="rowIdx"
|
||||||
|
class="col-12 fl-mb-md row items-center fl-pb-xs"
|
||||||
|
style="min-height: 40px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 row justify-between items-center fl-px-md"
|
||||||
|
style="min-height: 40px; background: #46299dff"
|
||||||
|
:style="{ borderRadius: row.showChild ? '3px 3px 0 0' : '3px' }"
|
||||||
|
>
|
||||||
|
<div class="color-white">
|
||||||
|
<n-checkbox
|
||||||
|
v-model:checked="row.selected"
|
||||||
|
@update:checked="(e) => handlePageSelectChange(e)"
|
||||||
|
>
|
||||||
|
</n-checkbox>
|
||||||
|
{{ row.name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
v-if="!row.showChild"
|
||||||
|
style="background: #ffffffff; color: #46299dff"
|
||||||
|
icon-placement="right"
|
||||||
|
round
|
||||||
|
secondary
|
||||||
|
strong
|
||||||
|
size="small"
|
||||||
|
@click="row.showChild = true"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<n-icon>
|
||||||
|
<ChevronDownOutline />
|
||||||
|
</n-icon>
|
||||||
|
</template>
|
||||||
|
展开
|
||||||
|
</n-button>
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
v-if="row.showChild"
|
||||||
|
style="background: #ffffffff; color: #46299dff"
|
||||||
|
icon-placement="right"
|
||||||
|
round
|
||||||
|
secondary
|
||||||
|
strong
|
||||||
|
size="small"
|
||||||
|
@click="row.showChild = false"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<n-icon>
|
||||||
|
<ChevronUpOutline />
|
||||||
|
</n-icon>
|
||||||
|
</template>
|
||||||
|
收起
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="row.showChild"
|
||||||
|
style="border: 1px solid #1f2225ff; border-radius: 0 0 3px 3px"
|
||||||
|
class="col-12 row"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12 row"
|
||||||
|
style="padding: 11px 0; background: #dfd7f2"
|
||||||
|
>
|
||||||
|
<div class="col-3 text-center">按钮权限</div>
|
||||||
|
<div class="col-3 text-center">列表权限</div>
|
||||||
|
<div class="col-3 text-center">数据范围权限</div>
|
||||||
|
<div class="col-3 text-center">列表字段权限</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 row">
|
||||||
|
<div class="col-3 fl-py-md">
|
||||||
|
<div class="" style="margin-left: 30%">
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
Array.isArray(row.buttonList) &&
|
||||||
|
row.buttonList.length > 1
|
||||||
|
"
|
||||||
|
class="row"
|
||||||
|
>
|
||||||
|
<n-checkbox
|
||||||
|
v-model:checked="row.btnSelectedAll"
|
||||||
|
:indeterminate="row.btnIndeterminate"
|
||||||
|
@update:checked="
|
||||||
|
(e) => handleBtnSelectAllChange(e, rowIdx)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
全选
|
||||||
|
</n-checkbox>
|
||||||
|
</div>
|
||||||
|
<n-checkbox-group
|
||||||
|
v-model:value="row.btnSelected"
|
||||||
|
@update:value="(e) => handleBtnSelectChange(e, rowIdx)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-12"
|
||||||
|
v-for="(btn, btnIdx) in row.buttonList"
|
||||||
|
:key="btnIdx"
|
||||||
|
>
|
||||||
|
<n-checkbox :value="btn.ID">
|
||||||
|
{{ btn.name }}
|
||||||
|
</n-checkbox>
|
||||||
|
</div>
|
||||||
|
</n-checkbox-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-9 row">
|
||||||
|
<div
|
||||||
|
v-for="(list, listIdx) in row.interfaceList"
|
||||||
|
:key="listIdx"
|
||||||
|
class="col-12 row"
|
||||||
|
:style="{
|
||||||
|
'border-left':
|
||||||
|
row.interfaceList.length > 1 ? '1px solid #C1B2E5' : '',
|
||||||
|
'border-bottom':
|
||||||
|
listIdx !== row.interfaceList.length - 1
|
||||||
|
? '1px solid #C1B2E5'
|
||||||
|
: '',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="col-4 row fl-pa-md justify-center">
|
||||||
|
<n-checkbox
|
||||||
|
v-model:checked="list.selected"
|
||||||
|
@update:checked="
|
||||||
|
(e) => handleListSelectChange(e, rowIdx, listIdx)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ list.name }}
|
||||||
|
</n-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-4 row fl-pa-md justify-center">
|
||||||
|
<n-radio-group v-model:value="list.limitSelected">
|
||||||
|
<n-radio
|
||||||
|
:style="radioStyle"
|
||||||
|
v-for="(limit, limitIdx) in list.limit"
|
||||||
|
:key="limitIdx"
|
||||||
|
:value="limit.value"
|
||||||
|
>
|
||||||
|
<div class="relative">
|
||||||
|
{{ limit.label }}
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
v-if="
|
||||||
|
list.limitSelected === 5 && limit.value === 5
|
||||||
|
"
|
||||||
|
size="small"
|
||||||
|
style="
|
||||||
|
position: absolute;
|
||||||
|
right: -120px;
|
||||||
|
width: 70px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #6d5c9c;
|
||||||
|
border: 1px solid #8a67ef;
|
||||||
|
"
|
||||||
|
@click.stop="
|
||||||
|
handleChangeSelfLimitData(rowIdx, listIdx, list)
|
||||||
|
"
|
||||||
|
>设置</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</n-radio>
|
||||||
|
</n-radio-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-4 row fl-pa-md justify-center">
|
||||||
|
<n-checkbox-group
|
||||||
|
v-if="Array.isArray(list.positionRuleFields)"
|
||||||
|
v-model:value="list.fieldsSelected"
|
||||||
|
>
|
||||||
|
<div class="col-12">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
class="fl-ml-md"
|
||||||
|
size="small"
|
||||||
|
style="
|
||||||
|
width: 70px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #6d5c9c;
|
||||||
|
border: 1px solid #8a67ef;
|
||||||
|
"
|
||||||
|
@click="handleEditField(rowIdx, listIdx)"
|
||||||
|
>设置</n-button
|
||||||
|
>
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
class="fl-ml-md"
|
||||||
|
size="small"
|
||||||
|
style="
|
||||||
|
width: 70px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #6d5c9c;
|
||||||
|
border: 1px solid #8a67ef;
|
||||||
|
"
|
||||||
|
@click="handleEditFieldSort(rowIdx, listIdx)"
|
||||||
|
>排序</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="col-12"
|
||||||
|
v-for="(field, fieldIdx) in list.positionRuleFields"
|
||||||
|
:key="fieldIdx"
|
||||||
|
>
|
||||||
|
<n-checkbox :value="field.ID">
|
||||||
|
{{ field.fieldCnName }}
|
||||||
|
</n-checkbox>
|
||||||
|
</div>
|
||||||
|
</n-checkbox-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 row justify-center fl-mt-md">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #fff"
|
||||||
|
class="fl-mr-md"
|
||||||
|
@click="handleDialogBack"
|
||||||
|
>返回</n-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #46299dff; color: #fff"
|
||||||
|
:loading="state.btnLoading"
|
||||||
|
@click="handleDialogSubmit"
|
||||||
|
>保存</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
|
||||||
|
<fl-limit-data
|
||||||
|
v-if="state.dialogSelfLimtiData"
|
||||||
|
:fatherData="state.dataDepartmentIds"
|
||||||
|
@triggerLimitData="handleLimitData"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
// 岗位新建方式选择 弹窗
|
||||||
|
import {
|
||||||
|
UpOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
CloseCircleOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
DragOutlined,
|
||||||
|
} from "@ant-design/icons-vue";
|
||||||
|
import { Close as CloseIcon } from "@vicons/ionicons5";
|
||||||
|
import flnFormItem from "@/components/flnlayout/form/flnformItem.vue";
|
||||||
|
import flAboutApproval from "./aboutApproval.vue";
|
||||||
|
import draggable from "vuedraggable";
|
||||||
|
import flLimitData from "./limitData.vue";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter, useRoute } from "vue-router";
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
import { ChevronDownOutline, ChevronUpOutline } from "@vicons/ionicons5";
|
||||||
|
import { Local } from "@/utils/storage.js";
|
||||||
|
|
||||||
|
const emits = defineEmits(["triggerClose"]);
|
||||||
|
const radioStyle = reactive({
|
||||||
|
display: "flex",
|
||||||
|
height: "30px",
|
||||||
|
lineHeight: "30px",
|
||||||
|
});
|
||||||
|
let props = defineProps({
|
||||||
|
fatherData: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const state = reactive({
|
||||||
|
selectedRows: [],
|
||||||
|
dialogField: false,
|
||||||
|
dialogData: {
|
||||||
|
fieldList: [],
|
||||||
|
},
|
||||||
|
listData: [],
|
||||||
|
formData: {
|
||||||
|
name: "",
|
||||||
|
remark: "",
|
||||||
|
color: "#1F2225",
|
||||||
|
isOwner: [],
|
||||||
|
},
|
||||||
|
btnLoading: false,
|
||||||
|
pageType: "create",
|
||||||
|
enabled: true,
|
||||||
|
dialogFieldSort: false,
|
||||||
|
dataLoading: false,
|
||||||
|
dialogModal: true,
|
||||||
|
tempList: [],
|
||||||
|
selectTemplate: "",
|
||||||
|
showTempRuleListData: false,
|
||||||
|
dialogApproval: false,
|
||||||
|
dialogSelfLimtiData: false,
|
||||||
|
dialogLimitData: {},
|
||||||
|
dataDepartmentIds: [],
|
||||||
|
approvalData: [],
|
||||||
|
});
|
||||||
|
onBeforeMount(() => {
|
||||||
|
console.log("onBeforeMount");
|
||||||
|
state.dialogModal = true;
|
||||||
|
getTempData();
|
||||||
|
if (route.query.type) {
|
||||||
|
state.pageType = route.query.type;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {});
|
||||||
|
const getTempData = () => {
|
||||||
|
let url = "/position/v2/model/list";
|
||||||
|
$request.HTTP.components.postDataByParams(url, {}).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.tempList = res.data || [];
|
||||||
|
state.selectTemplate = state.tempList[0].name || "无数据";
|
||||||
|
if (state.tempList.length > 0) {
|
||||||
|
getRulesData(state.tempList[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取数据失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取数据失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取数据失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const getRulesData = (temp) => {
|
||||||
|
let url = "/position/v2/model/detail";
|
||||||
|
$request.HTTP.components.postDataByParams(url, { uuid: temp.uuid }).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
let data = res.data.positionTreeRule;
|
||||||
|
data.map((item) => {
|
||||||
|
item.selected = false;
|
||||||
|
item.showChild = false;
|
||||||
|
|
||||||
|
item.btnSelected = [];
|
||||||
|
item.btnSelectedAll = false;
|
||||||
|
item.btnIndeterminate = false;
|
||||||
|
if (Array.isArray(item.interfaceList)) {
|
||||||
|
item.interfaceList.map((listItem) => {
|
||||||
|
listItem.selected = false;
|
||||||
|
listItem.limit = [
|
||||||
|
{
|
||||||
|
label: "仅自己",
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "自己及下属",
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "本部门",
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "所有",
|
||||||
|
value: 4,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
listItem.limitSelected = 4;
|
||||||
|
listItem.positionRuleFields = listItem.positionRuleFields || [];
|
||||||
|
listItem.fieldsSelected = listItem.positionRuleFields.map(
|
||||||
|
(item) => item.ID
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
state.listData = data;
|
||||||
|
setRulesDataDefaultVal(data, state.listData);
|
||||||
|
state.selectedRows = state.listData.filter((item) => item.selected);
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取数据失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取数据失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取数据失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleValChange = ({ val, config }) => {
|
||||||
|
state.formData[config.field] = val;
|
||||||
|
};
|
||||||
|
const handleDialogSubmit = () => {
|
||||||
|
if (state.formData.name === "") {
|
||||||
|
processError("请填写岗位名称");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let url = "/position/v2/create";
|
||||||
|
let params = {
|
||||||
|
name: state.formData.name,
|
||||||
|
remark: state.formData.remark,
|
||||||
|
color: state.formData.color,
|
||||||
|
positionTreeRule: [],
|
||||||
|
departmentID: Number(props.fatherData.key),
|
||||||
|
isLeader: state.formData.isOwner.length > 0,
|
||||||
|
};
|
||||||
|
let data = state.listData;
|
||||||
|
data
|
||||||
|
.filter((item) => item.selected)
|
||||||
|
.map((item) => {
|
||||||
|
let obj = {
|
||||||
|
ID: item.ID,
|
||||||
|
buttonList: Array.isArray(item.buttonList)
|
||||||
|
? item.buttonList.filter((btnItem) =>
|
||||||
|
item.btnSelected.includes(btnItem.ID)
|
||||||
|
)
|
||||||
|
: [],
|
||||||
|
interfaceList: Array.isArray(item.interfaceList)
|
||||||
|
? item.interfaceList
|
||||||
|
.filter((listItem) => listItem.selected)
|
||||||
|
.map((listItem) => {
|
||||||
|
return {
|
||||||
|
ID: listItem.ID,
|
||||||
|
dataRange: listItem.limitSelected,
|
||||||
|
positionRuleFields: Array.isArray(listItem.positionRuleFields)
|
||||||
|
? listItem.positionRuleFields.filter((fieldItem) =>
|
||||||
|
listItem.fieldsSelected.includes(fieldItem.ID)
|
||||||
|
)
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
params.positionTreeRule.push(obj);
|
||||||
|
});
|
||||||
|
state.btnLoading = true;
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
// 岗位绑定审批发起人
|
||||||
|
if (state.approvalData.length > 0) {
|
||||||
|
let url = "/approval/v2/create-auth";
|
||||||
|
let params = {
|
||||||
|
typeId: state.approvalData.map((item) => item.ID),
|
||||||
|
departmentUID: res.data.DepartmentID.toString(),
|
||||||
|
departmentName: res.data.DepartmentName,
|
||||||
|
positionUID: res.data.ID.toString(),
|
||||||
|
positionName: res.data.Name,
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
emits("triggerClose");
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
processError("操作失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
state.btnLoading = false;
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
emits("triggerClose");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.btnLoading = false;
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleBack = () => {
|
||||||
|
router.go(-1);
|
||||||
|
};
|
||||||
|
const handleEditField = (rowIdx, listIdx) => {
|
||||||
|
state.dialogData.clickData = state.listData[rowIdx];
|
||||||
|
state.dialogData.ID = state.listData[rowIdx].interfaceList[listIdx].ID;
|
||||||
|
state.dialogData.rowIdx = rowIdx;
|
||||||
|
state.dialogData.listIdx = listIdx;
|
||||||
|
state.dialogData.fieldList = JSON.parse(
|
||||||
|
JSON.stringify(
|
||||||
|
state.listData[rowIdx].interfaceList[listIdx].positionRuleFields.map(
|
||||||
|
(item) => {
|
||||||
|
return {
|
||||||
|
ID: item.ID,
|
||||||
|
field: item.fieldKey,
|
||||||
|
fieldCnName: item.fieldCnName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
state.dialogField = true;
|
||||||
|
};
|
||||||
|
const handleBtnSelectAllChange = (checked, idx) => {
|
||||||
|
if (checked) {
|
||||||
|
state.listData[idx].btnSelected = state.listData[idx].buttonList.map(
|
||||||
|
(item) => item.ID
|
||||||
|
);
|
||||||
|
state.listData[idx].btnIndeterminate = false;
|
||||||
|
} else {
|
||||||
|
state.listData[idx].btnSelected = [];
|
||||||
|
state.listData[idx].btnIndeterminate = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleBtnSelectChange = (e, idx) => {
|
||||||
|
if (e.length === 0) {
|
||||||
|
state.listData[idx].btnSelectedAll = false;
|
||||||
|
state.listData[idx].btnIndeterminate = false;
|
||||||
|
} else if (e.length === state.listData[idx].buttonList.length) {
|
||||||
|
state.listData[idx].btnSelectedAll = true;
|
||||||
|
state.listData[idx].btnIndeterminate = false;
|
||||||
|
} else {
|
||||||
|
state.listData[idx].btnSelectedAll = false;
|
||||||
|
state.listData[idx].btnIndeterminate = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleListSelectChange = (e, rowIdx, listIdx) => {
|
||||||
|
state.listData[rowIdx].listSelected = state.listData[
|
||||||
|
rowIdx
|
||||||
|
].interfaceList.filter((item) => item.selected);
|
||||||
|
};
|
||||||
|
const handlePageSelectChange = (e) => {
|
||||||
|
state.selectedRows = state.listData.filter((item) => item.selected);
|
||||||
|
};
|
||||||
|
const handleClearPage = (select) => {
|
||||||
|
state.listData.forEach((item) => {
|
||||||
|
if (item.name === select.name) {
|
||||||
|
item.selected = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
state.selectedRows = state.listData.filter((item) => item.selected);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelDialogFieldList = (delIdx) => {
|
||||||
|
state.dialogData.fieldList.splice(delIdx, 1);
|
||||||
|
};
|
||||||
|
const handleCreDialogFieldList = () => {
|
||||||
|
state.dialogData.fieldList.push({
|
||||||
|
field: "",
|
||||||
|
fieldCnName: "",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDialogBack = () => {
|
||||||
|
state.dialogField = false;
|
||||||
|
emits("triggerClose");
|
||||||
|
};
|
||||||
|
const handleLink = (path) => {
|
||||||
|
router.push(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setRulesDataDefaultVal = (pageData, listData) => {
|
||||||
|
pageData.map((pageDataItem) => {
|
||||||
|
listData.map((listItem) => {
|
||||||
|
if (pageDataItem.ID === listItem.ID) {
|
||||||
|
listItem.selected = true;
|
||||||
|
listItem.showChild = false;
|
||||||
|
|
||||||
|
listItem.btnSelected = Array.isArray(pageDataItem.buttonList)
|
||||||
|
? pageDataItem.buttonList.map((btnItem) => btnItem.ID)
|
||||||
|
: [];
|
||||||
|
if (
|
||||||
|
Array.isArray(listItem.interfaceList) &&
|
||||||
|
Array.isArray(pageDataItem.interfaceList)
|
||||||
|
) {
|
||||||
|
listItem.interfaceList.map((interfaceItem) => {
|
||||||
|
pageDataItem.interfaceList.map((pageDataInterfaceItem) => {
|
||||||
|
if (interfaceItem.ID === pageDataInterfaceItem.ID) {
|
||||||
|
interfaceItem.selected = true;
|
||||||
|
interfaceItem.limitSelected = pageDataInterfaceItem.dataRange;
|
||||||
|
pageDataInterfaceItem.positionRuleFields =
|
||||||
|
pageDataInterfaceItem.positionRuleFields || [];
|
||||||
|
interfaceItem.fieldsSelected =
|
||||||
|
pageDataInterfaceItem.positionRuleFields.map(
|
||||||
|
(fieldItem) => fieldItem.ID
|
||||||
|
);
|
||||||
|
interfaceItem.positionRuleFields.map((fieldItem) => {
|
||||||
|
pageDataInterfaceItem.positionRuleFields.map(
|
||||||
|
(pageDataFieldItem) => {
|
||||||
|
if (fieldItem.ID === pageDataFieldItem.ID) {
|
||||||
|
fieldItem.index = pageDataFieldItem.index || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditFieldSort = (rowIdx, listIdx) => {
|
||||||
|
state.dialogData.clickData = state.listData[rowIdx];
|
||||||
|
state.dialogData.ID = state.listData[rowIdx].interfaceList[listIdx].ID;
|
||||||
|
state.dialogData.rowIdx = rowIdx;
|
||||||
|
state.dialogData.listIdx = listIdx;
|
||||||
|
let fieldsSelected =
|
||||||
|
state.listData[rowIdx].interfaceList[listIdx].fieldsSelected;
|
||||||
|
let fieldList = [];
|
||||||
|
state.listData[rowIdx].interfaceList[listIdx].positionRuleFields.map(
|
||||||
|
(item) => {
|
||||||
|
if (fieldsSelected.includes(item.ID)) {
|
||||||
|
fieldList.push({
|
||||||
|
ID: item.ID,
|
||||||
|
field: item.fieldKey,
|
||||||
|
fieldCnName: item.fieldCnName,
|
||||||
|
index: item.index || 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
fieldList.sort((a, b) => {
|
||||||
|
return a.index - b.index;
|
||||||
|
});
|
||||||
|
state.dialogData.fieldList = fieldList;
|
||||||
|
state.dialogFieldSort = true;
|
||||||
|
};
|
||||||
|
const handleDialogSortSave = () => {
|
||||||
|
let rowIdx = state.dialogData.rowIdx;
|
||||||
|
let listIdx = state.dialogData.listIdx;
|
||||||
|
|
||||||
|
state.dialogData.fieldList.forEach((item, idx) => {
|
||||||
|
item.index = idx + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
state.listData[rowIdx].interfaceList[listIdx].positionRuleFields.map(
|
||||||
|
(item) => {
|
||||||
|
state.dialogData.fieldList.map((fieldItem) => {
|
||||||
|
if (item.ID === fieldItem.ID) {
|
||||||
|
item.index = fieldItem.index;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
state.dialogFieldSort = false;
|
||||||
|
};
|
||||||
|
const handleDialogSortBack = () => {
|
||||||
|
state.dialogFieldSort = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTempClick = (temp) => {
|
||||||
|
state.selectTemplate = temp.name;
|
||||||
|
getRulesData(temp);
|
||||||
|
};
|
||||||
|
const handleEditSelectTemp = () => {
|
||||||
|
state.showTempRuleListData = !state.showTempRuleListData;
|
||||||
|
};
|
||||||
|
const handleApproval = (approvalData) => {
|
||||||
|
state.approvalData = approvalData;
|
||||||
|
state.dialogApproval = false;
|
||||||
|
};
|
||||||
|
const handleChangeSelfLimitData = (rowIdx, listIdx, list) => {
|
||||||
|
state.dialogLimitData = {
|
||||||
|
rowIdx,
|
||||||
|
listIdx,
|
||||||
|
};
|
||||||
|
state.dataDepartmentIds = list.dataDepartmentIds;
|
||||||
|
state.dialogSelfLimtiData = true;
|
||||||
|
};
|
||||||
|
const handleLimitData = (data) => {
|
||||||
|
let rowIdx = state.dialogLimitData.rowIdx;
|
||||||
|
let listIdx = state.dialogLimitData.listIdx;
|
||||||
|
state.listData[rowIdx].interfaceList[listIdx].dataDepartmentIds = data;
|
||||||
|
state.dialogSelfLimtiData = false;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.n-card-header {
|
||||||
|
}
|
||||||
|
</style>
|
628
src/views/manage/posimanage/editAuth.vue
Normal file
628
src/views/manage/posimanage/editAuth.vue
Normal file
@ -0,0 +1,628 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="posimanageeditAuth"></div>
|
||||||
|
<n-modal v-model:show="state.showModal" :mask-closable="false">
|
||||||
|
<n-card
|
||||||
|
style="width: 80vw"
|
||||||
|
:bordered="false"
|
||||||
|
class="create-contianer"
|
||||||
|
size="huge"
|
||||||
|
width="1200px"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="title-visible">{{ props.title }}</div>
|
||||||
|
</template>
|
||||||
|
<template #header-extra>
|
||||||
|
<img
|
||||||
|
src="@/assets/image/icon/close-tabs.png"
|
||||||
|
class="close-icon"
|
||||||
|
@click="handleClose"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="center-content">
|
||||||
|
<div class="left-box">
|
||||||
|
<div class="title">基础设置</div>
|
||||||
|
<div class="content" ref="modalSelect">
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
name="custom-validation"
|
||||||
|
:model="formState"
|
||||||
|
:rules="rules"
|
||||||
|
v-bind="layout"
|
||||||
|
:hideRequiredMark="true"
|
||||||
|
>
|
||||||
|
<a-form-item label="权限类型" name="type">
|
||||||
|
<a-radio-group
|
||||||
|
v-model:value="formState.type"
|
||||||
|
@change="changeType"
|
||||||
|
name="radioGroup"
|
||||||
|
>
|
||||||
|
<a-radio :value="'menu'">菜单权限</a-radio>
|
||||||
|
<a-radio :value="'button'">按钮权限</a-radio>
|
||||||
|
<a-radio :value="'interface'">列表字段权限</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="菜单管理"
|
||||||
|
name="menuType"
|
||||||
|
v-if="formState.type == 'menu'"
|
||||||
|
>
|
||||||
|
<a-radio-group
|
||||||
|
v-model:value="formState.menuType"
|
||||||
|
name="radioGroup"
|
||||||
|
>
|
||||||
|
<a-radio :value="'1'">父级菜单</a-radio>
|
||||||
|
<a-radio :value="'2'">子级菜单</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="上级菜单"
|
||||||
|
name="pid"
|
||||||
|
v-if="formState.menuType == '2'"
|
||||||
|
>
|
||||||
|
<n-select
|
||||||
|
v-model:value="formState.pid"
|
||||||
|
:options="state.menuList"
|
||||||
|
label-field="Title"
|
||||||
|
value-field="ID"
|
||||||
|
filterable
|
||||||
|
/>
|
||||||
|
<!-- <a-select ref="select"
|
||||||
|
v-model:value="formState.pid"
|
||||||
|
style="width: 200px">
|
||||||
|
<a-select-option v-for="(item,index) in state.menuList"
|
||||||
|
:key="index"
|
||||||
|
:value="item.ID">{{item.Title}}</a-select-option>
|
||||||
|
</a-select> -->
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="权限名称" name="title">
|
||||||
|
<n-input
|
||||||
|
v-model:value="formState.title"
|
||||||
|
autocomplete="off"
|
||||||
|
maxLength="12"
|
||||||
|
placeholder="最长输入12个字符"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="上级权限"
|
||||||
|
name="pid"
|
||||||
|
v-if="formState.type !== 'menu'"
|
||||||
|
>
|
||||||
|
<n-tree-select
|
||||||
|
filterable
|
||||||
|
v-model:value="formState.pid"
|
||||||
|
:options="state.menuTreeList"
|
||||||
|
@update:value="handleUpdatemenuTreeValue"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="路由/按钮名/接口名" name="url">
|
||||||
|
<n-input
|
||||||
|
v-model:value="formState.url"
|
||||||
|
autocomplete="off"
|
||||||
|
:placeholder="
|
||||||
|
formState.type == 'menu' ? '不做路由跳转可为空' : ''
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="图标"
|
||||||
|
name="icon"
|
||||||
|
v-if="formState.type == 'menu' && formState.menuType == '1'"
|
||||||
|
>
|
||||||
|
<Upload
|
||||||
|
:maxCount="1"
|
||||||
|
v-model:uploadVal="formState.icon"
|
||||||
|
:zIndex="9000"
|
||||||
|
class="upload"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="选中图标"
|
||||||
|
name="grayIcon"
|
||||||
|
v-if="formState.type == 'menu' && formState.menuType == '1'"
|
||||||
|
>
|
||||||
|
<Upload
|
||||||
|
:maxCount="1"
|
||||||
|
v-model:uploadVal="formState.grayIcon"
|
||||||
|
:zIndex="9000"
|
||||||
|
class="upload"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="排序"
|
||||||
|
name="weigh"
|
||||||
|
v-if="formState.type == 'menu'"
|
||||||
|
>
|
||||||
|
<n-input-number
|
||||||
|
:show-button="false"
|
||||||
|
v-model:value="formState.weigh"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="1-100,越大排序越靠前"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<div v-show="formState.type == 'interface'" class="row">
|
||||||
|
<div class="col-4 text-right">
|
||||||
|
列表字段<span style="margin: 0 8px 0 2px">:</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-8">
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in formState.ruleFields"
|
||||||
|
:key="index"
|
||||||
|
style="margin-bottom: 10px"
|
||||||
|
>
|
||||||
|
<div class="flex">
|
||||||
|
<n-input
|
||||||
|
v-model:value="item.fieldCnName"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="列表字段中文名称"
|
||||||
|
style="margin-bottom: 10px; width: 200px"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="cancel-btn"
|
||||||
|
@click="cancelRule(index)"
|
||||||
|
v-if="formState.ruleFields.length > 1"
|
||||||
|
>移除</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<n-input
|
||||||
|
type="textarea"
|
||||||
|
v-model:value="item.fieldKey"
|
||||||
|
placeholder="列表字段对应value值"
|
||||||
|
:autosize="{ minRows: 2, maxRows: 5 }"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-4 row"></div>
|
||||||
|
<div class="col-8 row">
|
||||||
|
<a-button @click="addInput" style="width: 120px">
|
||||||
|
<PlusOutlined />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="row justify-end">
|
||||||
|
<div class="footer-content" v-if="state.isEdit">
|
||||||
|
<!-- <a-popconfirm title="是否确认删除该权限,删除后不可恢复?"
|
||||||
|
cancel-text="取消"
|
||||||
|
ok-text="确定"
|
||||||
|
@confirm="handleDel"
|
||||||
|
@cancel="departmentCel">
|
||||||
|
<a-button class="basic-btn">删除该权限</a-button>
|
||||||
|
</a-popconfirm> -->
|
||||||
|
<a-button
|
||||||
|
class="primary-btn"
|
||||||
|
:loading="state.btnLoading"
|
||||||
|
@click="handleUpdate"
|
||||||
|
>完成修改</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="footer-content" v-else>
|
||||||
|
<a-button class="basic-btn" @click="resetForm">清空</a-button>
|
||||||
|
<a-button
|
||||||
|
class="primary-btn"
|
||||||
|
:loading="state.btnLoading"
|
||||||
|
@click="handleCreate"
|
||||||
|
>完成设置</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 权限新建弹窗 旧代码
|
||||||
|
import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons-vue";
|
||||||
|
import {
|
||||||
|
defineProps,
|
||||||
|
defineEmits,
|
||||||
|
watch,
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
unref,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
} from "vue";
|
||||||
|
import Upload from "@/components/upload.vue";
|
||||||
|
import { Form, message } from "ant-design-vue";
|
||||||
|
import { processSuccess, processError } from "@/utils/helper/message";
|
||||||
|
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
|
||||||
|
const emits = defineEmits(["submit", "triggerClose"]);
|
||||||
|
let props = defineProps({
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const state = reactive({
|
||||||
|
btnLoading: false,
|
||||||
|
menuList: [],
|
||||||
|
menuTreeList: [],
|
||||||
|
isEdit: false,
|
||||||
|
showModal: true,
|
||||||
|
});
|
||||||
|
onMounted(() => {
|
||||||
|
state.showModal = true;
|
||||||
|
getMenu();
|
||||||
|
getMenuTree();
|
||||||
|
if (props.data?.id) {
|
||||||
|
state.isEdit = true;
|
||||||
|
getDetail();
|
||||||
|
} else {
|
||||||
|
state.isEdit = false;
|
||||||
|
formState.dataOpen = true;
|
||||||
|
formState.method = "*";
|
||||||
|
formState.type = "";
|
||||||
|
formState.icon = "";
|
||||||
|
formState.pid = null;
|
||||||
|
formState.title = "";
|
||||||
|
formState.menuType = "";
|
||||||
|
formState.url = "";
|
||||||
|
formState.weigh = "";
|
||||||
|
formState.ruleFields = [{ fieldKey: "", fieldCnName: "" }];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
emits("triggerClose");
|
||||||
|
resetForm();
|
||||||
|
state.isEdit = false;
|
||||||
|
};
|
||||||
|
const layout = {
|
||||||
|
labelCol: { span: 8 },
|
||||||
|
wrapperCol: { span: 16 },
|
||||||
|
};
|
||||||
|
const formRef = ref();
|
||||||
|
const formState = reactive({
|
||||||
|
grayIcon: "",
|
||||||
|
dataOpen: true,
|
||||||
|
method: "*",
|
||||||
|
type: "", // 'menu'菜单,'button'按钮组件,'interface'列表字段权限
|
||||||
|
icon: "",
|
||||||
|
pid: null,
|
||||||
|
title: "",
|
||||||
|
menuType: "",
|
||||||
|
url: "",
|
||||||
|
weigh: "",
|
||||||
|
ruleFields: [{ fieldKey: "", fieldCnName: "" }],
|
||||||
|
});
|
||||||
|
const filedJsonV = async (_rule, value) => {
|
||||||
|
// 验空
|
||||||
|
if (
|
||||||
|
formState.type === "interface" &&
|
||||||
|
formState.ruleFields.some((val) => val.fieldKey == "" || val.fieldKey == "")
|
||||||
|
) {
|
||||||
|
return Promise.reject("请补充完整");
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const urlV = async (_rule, value) => {
|
||||||
|
// 验空
|
||||||
|
if (formState.type === "menu" && formState.menuType === "1") {
|
||||||
|
return Promise.resolve();
|
||||||
|
} else {
|
||||||
|
if (value == "") {
|
||||||
|
return Promise.reject("请输入路由/唯一标识");
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const rules = {
|
||||||
|
type: [{ required: true, message: "请选择权限类型", trigger: "change" }],
|
||||||
|
icon: [{ required: true, message: "请上传Icon", trigger: "change" }],
|
||||||
|
grayIcon: [{ required: true, message: "请上传选中Icon", trigger: "change" }],
|
||||||
|
menuType: [{ required: true, message: "请选择菜单等级", trigger: "change" }],
|
||||||
|
pid: [
|
||||||
|
{ required: true, message: "请选择上级权限/上级菜单", trigger: "change" },
|
||||||
|
],
|
||||||
|
title: [{ required: true, message: "请输入权限名称", trigger: "change" }],
|
||||||
|
url: [{ required: true, validator: urlV, trigger: "change" }], // message: '请输入路由/唯一标识',
|
||||||
|
weigh: [{ required: true, message: "请输入排序", trigger: "change" }],
|
||||||
|
ruleFields: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: filedJsonV,
|
||||||
|
trigger: ["blur, change"],
|
||||||
|
type: "array",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const resetForm = () => {
|
||||||
|
formRef.value.resetFields();
|
||||||
|
};
|
||||||
|
const addInput = () => {
|
||||||
|
formState.ruleFields.push({ fieldKey: "", fieldCnName: "" });
|
||||||
|
};
|
||||||
|
const cancelRule = (index) => {
|
||||||
|
formState.ruleFields.splice(index, 1);
|
||||||
|
};
|
||||||
|
const changeType = () => {
|
||||||
|
formState.dataOpen = true;
|
||||||
|
formState.method = "*";
|
||||||
|
// formState.type = ''
|
||||||
|
formState.icon = "";
|
||||||
|
formState.pid = null;
|
||||||
|
formState.title = "";
|
||||||
|
formState.url = "";
|
||||||
|
formState.weigh = "";
|
||||||
|
formState.menuType = "";
|
||||||
|
formState.ruleFields = [{ fieldKey: "", fieldCnName: "" }];
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCreate = () => {
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(() => {
|
||||||
|
formState.pid = formState.pid ? Number(formState.pid) : 0;
|
||||||
|
formState.weigh = formState.weigh ? Number(formState.weigh) : 1;
|
||||||
|
|
||||||
|
state.btnLoading = true;
|
||||||
|
let url = "/rule/create";
|
||||||
|
let params = formState;
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
processSuccess("添加成功");
|
||||||
|
handleClose();
|
||||||
|
emits("triggerClose");
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
processError("操作失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((error) => {});
|
||||||
|
};
|
||||||
|
const handleDel = () => {
|
||||||
|
$request.HTTP.permission
|
||||||
|
.ruleRemove({ ID: formState.ID })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status == 0) {
|
||||||
|
message.success({
|
||||||
|
content: "删除成功",
|
||||||
|
duration: 2,
|
||||||
|
onClose() {
|
||||||
|
handleClose();
|
||||||
|
emits("triggerClose");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error(res.msg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
message.error(e.response?.data?.msg || "操作失败,请稍后再试");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const departmentCel = () => {};
|
||||||
|
const handleUpdate = () => {
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(() => {
|
||||||
|
formState.pid = formState.pid ? Number(formState.pid) : 0;
|
||||||
|
formState.weigh = formState.weigh ? Number(formState.weigh) : 1;
|
||||||
|
|
||||||
|
state.btnLoading = true;
|
||||||
|
let url = "/rule/v2/update";
|
||||||
|
let params = formState;
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
message.success({
|
||||||
|
content: "修改成功",
|
||||||
|
duration: 2,
|
||||||
|
onClose() {
|
||||||
|
handleClose();
|
||||||
|
emits("triggerClose");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
processError("操作失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMenu = () => {
|
||||||
|
$request.HTTP.permission
|
||||||
|
.menuFList()
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status == 0) {
|
||||||
|
state.menuList = res.data.data;
|
||||||
|
} else {
|
||||||
|
message.error(res.msg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
message.error(e.response?.data?.msg || "操作失败,请稍后再试");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMenuTree = () => {
|
||||||
|
$request.HTTP.permission
|
||||||
|
.menuSList()
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status == 0) {
|
||||||
|
state.menuTreeList = res.data.data.map((item) => {
|
||||||
|
let obj = {
|
||||||
|
label: item.Title,
|
||||||
|
key: item.ID,
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
if (item.Son) {
|
||||||
|
obj.children = item.Son.map((i) => {
|
||||||
|
return {
|
||||||
|
key: i.ID,
|
||||||
|
label: i.Title,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error(res.msg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
message.error(e.response?.data?.msg || "操作失败,请稍后再试");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleUpdatemenuTreeValue = (val) => {
|
||||||
|
formState.pid = val;
|
||||||
|
};
|
||||||
|
const getDetail = () => {
|
||||||
|
let url = "/rule/v2/detail";
|
||||||
|
let params = {
|
||||||
|
ID: props.data.id,
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.status === 0) {
|
||||||
|
formState.ID = res.data.ID;
|
||||||
|
formState.type = res.data.type;
|
||||||
|
formState.title = res.data.title;
|
||||||
|
formState.url = res.data.url;
|
||||||
|
if (res.data.type == "button") {
|
||||||
|
formState.pid = res.data.pid;
|
||||||
|
}
|
||||||
|
if (res.data.type == "menu") {
|
||||||
|
formState.icon = res.data.icon;
|
||||||
|
formState.grayIcon = res.data.grayIcon;
|
||||||
|
formState.weigh = res.data.weigh;
|
||||||
|
formState.pid = res.data.pid;
|
||||||
|
formState.menuType = res.data.menuType;
|
||||||
|
}
|
||||||
|
if (res.data.type == "interface") {
|
||||||
|
formState.pid = res.data.pid;
|
||||||
|
formState.ruleFields = res.data.ruleFields;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.title-visible {
|
||||||
|
text-align: center;
|
||||||
|
color: $theme-primary;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
:deep(.ant-modal-body) {
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
.create-contianer {
|
||||||
|
.ant-input {
|
||||||
|
color: #6d5c9c;
|
||||||
|
}
|
||||||
|
.center-content {
|
||||||
|
height: 65vh;
|
||||||
|
display: flex;
|
||||||
|
.title {
|
||||||
|
width: fit-content;
|
||||||
|
padding-left: 10px;
|
||||||
|
border-left: 4px solid $theme-primary;
|
||||||
|
color: $text-theme;
|
||||||
|
margin: 19px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-box {
|
||||||
|
width: 55%;
|
||||||
|
padding-right: 30px;
|
||||||
|
.content {
|
||||||
|
height: 54vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
color: $text-theme;
|
||||||
|
}
|
||||||
|
:deep(.ant-form-item-label > label) {
|
||||||
|
color: $text-theme;
|
||||||
|
}
|
||||||
|
.ant-form-item input[type="text"],
|
||||||
|
input,
|
||||||
|
textarea {
|
||||||
|
background: #e3dfea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-select :deep(.ant-select-selector) {
|
||||||
|
background: #e3dfea;
|
||||||
|
}
|
||||||
|
.control-item {
|
||||||
|
:deep(.ant-form-item-control) {
|
||||||
|
margin-left: 0px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.cancel-btn {
|
||||||
|
color: #999999;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: $text-theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.upload {
|
||||||
|
:deep(.ant-image) {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
:deep(.ant-image-img) {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.footer-content {
|
||||||
|
margin: 10px 0;
|
||||||
|
button {
|
||||||
|
width: 130px;
|
||||||
|
height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
674
src/views/manage/posimanage/index.vue
Normal file
674
src/views/manage/posimanage/index.vue
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row" style="padding: 35px">
|
||||||
|
<div
|
||||||
|
class="col-3 fl-pa-md"
|
||||||
|
style="
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: rgba(188, 188, 188, 0.18) 0px 3px 6px 1px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="row font-16"
|
||||||
|
style="color: #764cf6; border-bottom: 1px solid #c1b2e5"
|
||||||
|
>
|
||||||
|
<div class="fl-py-sm" style="border-bottom: 4px solid #764cf6">
|
||||||
|
组织架构
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" style="height: 76vh; overflow: auto">
|
||||||
|
<fl-tree
|
||||||
|
:data="state.treeData"
|
||||||
|
:expandedKeys="state.expandedKeys"
|
||||||
|
:refreshCount="state.treeRefreshCount"
|
||||||
|
:clickKey="state.clickKey"
|
||||||
|
@triggerTreeClick="handleTreeClick"
|
||||||
|
></fl-tree>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-9 fl-px-md">
|
||||||
|
<div style="background: #fff" class="fl-pa-md">
|
||||||
|
<div
|
||||||
|
class="col-12 row font-18"
|
||||||
|
style="
|
||||||
|
color: #764cf6;
|
||||||
|
border-bottom: 1px solid #c1b2e5;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="fl-py-sm" style="border-bottom: 4px solid #764cf6">
|
||||||
|
岗位管理
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<n-button @click="goToOrgManage" v-permission="'org-manage-btn'">
|
||||||
|
组织管理
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 row fl-mt-sm">
|
||||||
|
<fln-table
|
||||||
|
:config="state.tableConfig"
|
||||||
|
:fatherData="state.treeSelectData"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount"
|
||||||
|
@triggerRowActions="handleRowActions"
|
||||||
|
@triggerTableBatchActions="handleTableBatchActions"
|
||||||
|
>
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 row fl-mt-md">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #39109c; color: #fff"
|
||||||
|
@click="handlePermissMgm"
|
||||||
|
>权限列表</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<n-modal
|
||||||
|
v-model:show="state.dialogDel"
|
||||||
|
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
|
||||||
|
v-if="state.dialogData.type === 'one'"
|
||||||
|
class="font-20"
|
||||||
|
style="color: #6d5c9c; margin: 80px 0"
|
||||||
|
>
|
||||||
|
确定删除该岗位吗?
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="state.dialogData.type === 'batch'"
|
||||||
|
class="font-20"
|
||||||
|
style="color: #6d5c9c; margin: 80px 0"
|
||||||
|
>
|
||||||
|
确定删除选中的岗位吗?
|
||||||
|
</div>
|
||||||
|
<div class="col-12 row justify-center">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #fff"
|
||||||
|
class="fl-mr-md"
|
||||||
|
@click="handleDialogBack"
|
||||||
|
>返回</n-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #46299dff; color: #fff"
|
||||||
|
@click="handleDialogSave"
|
||||||
|
>确定</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</n-modal>
|
||||||
|
|
||||||
|
<fl-posi-permiss-mgm
|
||||||
|
v-if="state.dialogPermissMgm"
|
||||||
|
@triggerClose="state.dialogPermissMgm = false"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<orgManage
|
||||||
|
:orgVisible="state.org.orgVisible"
|
||||||
|
:title="'组织管理'"
|
||||||
|
@orgHandleOk="orgHandleOk"
|
||||||
|
></orgManage>
|
||||||
|
|
||||||
|
<fl-posi-dialog-create
|
||||||
|
v-if="state.dialogPosiCreate"
|
||||||
|
:fatherData="state.treeSelectData"
|
||||||
|
@triggerClose="handleDialogCreateClose"
|
||||||
|
></fl-posi-dialog-create>
|
||||||
|
|
||||||
|
<n-modal
|
||||||
|
v-model:show="state.dialogLinkerNum"
|
||||||
|
style="width: 800px"
|
||||||
|
:mask-closable="true"
|
||||||
|
preset="card"
|
||||||
|
>
|
||||||
|
<div class="row justify-center fl-pa-md">
|
||||||
|
<fln-table
|
||||||
|
:config="state.linkerNumConfig"
|
||||||
|
:fatherData="state.dialogData"
|
||||||
|
:refreshCount="state.linkerNumConfig.refreshCount"
|
||||||
|
>
|
||||||
|
</fln-table>
|
||||||
|
|
||||||
|
<div class="col-12 row justify-center fl-mt-md">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #fff"
|
||||||
|
class="fl-mr-md"
|
||||||
|
@click="state.dialogLinkerNum = false"
|
||||||
|
>关闭</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</n-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 岗位
|
||||||
|
import flPosiPermissMgm from "./permissionDialog.vue";
|
||||||
|
import { NButton } from "naive-ui";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
h,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import login from "@/api/login";
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
import flTree from "@/components/flnlayout/tree/flnindex.vue";
|
||||||
|
import flPosiDialogCreate from "./dialogCreate.vue";
|
||||||
|
|
||||||
|
import { Local } from "@/utils/storage.js";
|
||||||
|
import orgManage from "./orgManage.vue";
|
||||||
|
const router = useRouter();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
const title = ref("");
|
||||||
|
const state = reactive({
|
||||||
|
clickKey: "",
|
||||||
|
treeRefreshCount: 0,
|
||||||
|
expandedKeys: [],
|
||||||
|
treeData: [],
|
||||||
|
treeSelectData: {},
|
||||||
|
dialogPermissMgm: false,
|
||||||
|
dialogDel: false,
|
||||||
|
dialogData: {},
|
||||||
|
btnLoading: false,
|
||||||
|
selectedRows: [],
|
||||||
|
title: "",
|
||||||
|
org: {
|
||||||
|
orgVisible: false,
|
||||||
|
},
|
||||||
|
dialogLinkerNum: false,
|
||||||
|
tableConfig: {
|
||||||
|
tableScrollWitdh: 600,
|
||||||
|
rowKey: "ID",
|
||||||
|
hasSelection: true,
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "data",
|
||||||
|
pageField: "page",
|
||||||
|
pageSizeField: "pageSize",
|
||||||
|
url: "/position/v2/list",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
label: "departmentID",
|
||||||
|
field: "key",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
searchConfig: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "岗位ID",
|
||||||
|
field: "ID",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "岗位名",
|
||||||
|
field: "name",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "页面权限",
|
||||||
|
field: "menuAuth",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "操作人",
|
||||||
|
field: "operatorName",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "rangdate",
|
||||||
|
label: "最近一次更新时间",
|
||||||
|
field: ["updateStartAt", "updateEndAt"],
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: ["开始", "结束"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: "岗位ID",
|
||||||
|
field: "ID",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 140,
|
||||||
|
title: "岗位名",
|
||||||
|
field: "name",
|
||||||
|
type: "sfBgColor",
|
||||||
|
bgConfig: {
|
||||||
|
bgColorField: "color",
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// width: 120,
|
||||||
|
// type: "select",
|
||||||
|
// title: "部门负责人",
|
||||||
|
// field: "",
|
||||||
|
// config: {
|
||||||
|
// options: [
|
||||||
|
// {
|
||||||
|
// label: "是",
|
||||||
|
// value: 1,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
type: "tooltip",
|
||||||
|
title: "岗位描述",
|
||||||
|
field: "remark",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 360,
|
||||||
|
title: "页面权限",
|
||||||
|
field: "menuAuths",
|
||||||
|
type: "tags",
|
||||||
|
tagConfig: {
|
||||||
|
showLength: 3,
|
||||||
|
bgColor: "#fff",
|
||||||
|
borderRadius: "14px",
|
||||||
|
style: "border-radius: 14px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 140,
|
||||||
|
sorter: true,
|
||||||
|
title: "被关联人数",
|
||||||
|
field: "linkerNum",
|
||||||
|
render(row) {
|
||||||
|
return h(
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
style: "color: #409eff; cursor: pointer",
|
||||||
|
onClick: () => {
|
||||||
|
handleLinkerNum(row);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
row.linkerNum
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 140,
|
||||||
|
title: "操作人",
|
||||||
|
field: "operatorName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 160,
|
||||||
|
title: "最近一次更新时间",
|
||||||
|
field: "updatedAt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 200,
|
||||||
|
title: "操作",
|
||||||
|
fixed: "right",
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: "act_view",
|
||||||
|
type: "label",
|
||||||
|
label: "查看",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
permission: "r_manage_posimanage_btn_edit",
|
||||||
|
actionType: "act_edit",
|
||||||
|
type: "label",
|
||||||
|
label: "修改",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
permission: "r_manage_posimanage_btn_delete",
|
||||||
|
actionType: "act_del",
|
||||||
|
type: "label",
|
||||||
|
label: "删除",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tableBatchActions: [
|
||||||
|
{
|
||||||
|
permission: "r_manage_posimanage_btn_create",
|
||||||
|
notLimitSelect: true,
|
||||||
|
style: "background:#F7EFFFFF;color:#8352B4FF",
|
||||||
|
actionType: "posi-direct-create",
|
||||||
|
type: "primary",
|
||||||
|
label: "新建岗位",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
permission: "r_manage_posimanage_btn_create",
|
||||||
|
notLimitSelect: true,
|
||||||
|
style: "background:#F7EFFFFF;color:#8352B4FF",
|
||||||
|
actionType: "posi-create",
|
||||||
|
type: "primary",
|
||||||
|
label: "模版新建岗位",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
linkerNumConfig: {
|
||||||
|
tableScrollWitdh: 300,
|
||||||
|
rowKey: "ID",
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "data",
|
||||||
|
pageField: "page",
|
||||||
|
pageSizeField: "pageSize",
|
||||||
|
url: "/user/v2/list",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
label: "positionId",
|
||||||
|
field: "ID",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: "员工工号",
|
||||||
|
field: "jobNum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "姓名",
|
||||||
|
field: "nickName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "手机",
|
||||||
|
field: "telNum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
title: "状态",
|
||||||
|
field: "status",
|
||||||
|
config: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "有效",
|
||||||
|
value: "notactive",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "无效",
|
||||||
|
value: "left",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
dialogPosiCreate: false,
|
||||||
|
});
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getTreeData();
|
||||||
|
});
|
||||||
|
onMounted(() => {});
|
||||||
|
|
||||||
|
const getTreeData = () => {
|
||||||
|
let url = "/department/v2/tree/filter";
|
||||||
|
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;
|
||||||
|
// 获取最近点击的部门
|
||||||
|
let localSelect = Local.get("posimanage_treeSelectData");
|
||||||
|
if (localSelect && JSON.stringify(localSelect) !== "{}") {
|
||||||
|
state.treeSelectData = localSelect;
|
||||||
|
state.expandedKeys = localSelect.pathIds;
|
||||||
|
state.clickKey = localSelect.key;
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.treeRefreshCount++;
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
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 handleTreeClick = ({ selectedKey, tree }) => {
|
||||||
|
state.clickKey = tree.key;
|
||||||
|
state.treeSelectData = tree;
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
Local.set("posimanage_treeSelectData", state.treeSelectData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRowActions = ({ btnConfig, rowData }) => {
|
||||||
|
state.dialogData = rowData;
|
||||||
|
Local.set("posimanage_treeSelectData", state.treeSelectData);
|
||||||
|
if (btnConfig.actionType === "act_del") {
|
||||||
|
state.dialogData.type = "one";
|
||||||
|
state.dialogDel = true;
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "act_edit") {
|
||||||
|
router.push(
|
||||||
|
`/posimanage/create?departmentID=${state.clickKey}&&ID=${rowData.ID}&&type=edit`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "act_view") {
|
||||||
|
router.push(
|
||||||
|
`/posimanage/create?departmentID=${state.clickKey}&&ID=${rowData.ID}&&type=view`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTableBatchActions = ({ selectedRows, btnConfig, fatherData }) => {
|
||||||
|
state.selectedRows = selectedRows;
|
||||||
|
if (btnConfig.actionType === "posi-create") {
|
||||||
|
Local.set("posimanage_treeSelectData", state.treeSelectData);
|
||||||
|
state.dialogPosiCreate = true;
|
||||||
|
// router.push(
|
||||||
|
// `/posimanage/create?departmentID=${state.clickKey}&&type=create`
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "posi-delete-bat") {
|
||||||
|
handleDeleteBatch();
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "posi-direct-create") {
|
||||||
|
router.push(
|
||||||
|
`/posimanage/create?departmentID=${
|
||||||
|
Local.get("posimanage_treeSelectData").key
|
||||||
|
}&&type=create`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteBatch = () => {
|
||||||
|
state.dialogData.type = "batch";
|
||||||
|
state.dialogDel = true;
|
||||||
|
};
|
||||||
|
const handleDeleteBatchSave = () => {
|
||||||
|
state.btnLoading = true;
|
||||||
|
let url = "/position/v2/batch/remove";
|
||||||
|
let params = {
|
||||||
|
IDs: state.selectedRows.map((item) => item.ID),
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.selectedRows = [];
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
state.dialogDel = false;
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 单个删除
|
||||||
|
const handleDialogSave = () => {
|
||||||
|
if (state.dialogData.type === "batch") {
|
||||||
|
handleDeleteBatchSave();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.btnLoading = true;
|
||||||
|
let url = "/position/v2/batch/remove";
|
||||||
|
let params = {
|
||||||
|
IDs: [state.dialogData.ID],
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
state.dialogDel = false;
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
state.btnLoading = false;
|
||||||
|
state.dialogDel = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
state.dialogDel = false;
|
||||||
|
state.btnLoading = false;
|
||||||
|
processError("操作失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleDialogBack = () => {
|
||||||
|
state.dialogDel = false;
|
||||||
|
};
|
||||||
|
const handlePermissMgm = () => {
|
||||||
|
state.dialogPermissMgm = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 组织管理
|
||||||
|
const goToOrgManage = () => {
|
||||||
|
state.org = { orgVisible: true };
|
||||||
|
};
|
||||||
|
const orgHandleOk = () => {
|
||||||
|
state.org.orgVisible = false;
|
||||||
|
getTreeData();
|
||||||
|
};
|
||||||
|
const handleDialogCreateClose = () => {
|
||||||
|
state.dialogPosiCreate = false;
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
};
|
||||||
|
const handleLinkerNum = (row) => {
|
||||||
|
console.log(row);
|
||||||
|
state.dialogData = row;
|
||||||
|
state.dialogLinkerNum = true;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.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>
|
134
src/views/manage/posimanage/limitData.vue
Normal file
134
src/views/manage/posimanage/limitData.vue
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
<template>
|
||||||
|
<n-modal v-model:show="state.dialogModal"
|
||||||
|
:mask-closable="false">
|
||||||
|
<n-card style="width: 600px"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true">
|
||||||
|
<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: #1f2225">
|
||||||
|
自定义数据范围权限
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #header-extra>
|
||||||
|
<n-button @click="handleLimitData"
|
||||||
|
text
|
||||||
|
style="font-size: 24px">
|
||||||
|
<n-icon>
|
||||||
|
<close-icon />
|
||||||
|
</n-icon>
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
<div class="row justify-center fl-pa-md"
|
||||||
|
style="color: #333639">
|
||||||
|
<div class="col-12 text-center font-14"
|
||||||
|
style="color: #333639">
|
||||||
|
被勾选的部门相关权限可被查看
|
||||||
|
</div>
|
||||||
|
<n-tree block-line
|
||||||
|
checkable
|
||||||
|
:selectable="false"
|
||||||
|
:data="state.treeData"
|
||||||
|
:default-checked-keys="props.fatherData"
|
||||||
|
@update:checked-keys="updateCheckedKeys" />
|
||||||
|
|
||||||
|
<div class="col-12 row justify-center fl-mt-md">
|
||||||
|
<n-button tertiary
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #fff"
|
||||||
|
class="fl-mr-md"
|
||||||
|
@click="handleLimitData">返回</n-button>
|
||||||
|
|
||||||
|
<n-button tertiary
|
||||||
|
style="width: 161px; background: #46299dff; color: #fff"
|
||||||
|
@click="handleLimitData('submit')">保存</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 权限 自定义数据范围
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
} from "vue";
|
||||||
|
import { Close as CloseIcon } from "@vicons/ionicons5";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
let props = defineProps({
|
||||||
|
fatherData: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const state = reactive({
|
||||||
|
treeData: [],
|
||||||
|
dialogModal: true,
|
||||||
|
selectedKeys: []
|
||||||
|
});
|
||||||
|
onBeforeMount(() => {
|
||||||
|
state.dialogModal = true;
|
||||||
|
getTreeData()
|
||||||
|
if (props.fatherData) {
|
||||||
|
state.selectedKeys = props.fatherData;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
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 emits = defineEmits(["triggerLimitData"]);
|
||||||
|
const handleLimitData = (type) => {
|
||||||
|
if (type === 'submit') {
|
||||||
|
emits("triggerLimitData", state.selectedKeys);
|
||||||
|
} else {
|
||||||
|
emits("triggerLimitData", []);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateCheckedKeys = (keys) => {
|
||||||
|
state.selectedKeys = keys;
|
||||||
|
};
|
||||||
|
</script>
|
576
src/views/manage/posimanage/orgManage.vue
Normal file
576
src/views/manage/posimanage/orgManage.vue
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
<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>
|
311
src/views/manage/posimanage/permissionDialog.vue
Normal file
311
src/views/manage/posimanage/permissionDialog.vue
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
<template>
|
||||||
|
<n-modal v-model:show="state.dialogModal" :mask-closable="false">
|
||||||
|
<n-card
|
||||||
|
style="width: 80vw"
|
||||||
|
:bordered="false"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="col-12 row justify-center relative">
|
||||||
|
<div style="font-size: 20px; font-weight: bold; color: #1f2225ff">
|
||||||
|
权限列表
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #header-extra>
|
||||||
|
<n-button @click="handleDialogBack" text style="font-size: 24px">
|
||||||
|
<n-icon>
|
||||||
|
<close-icon />
|
||||||
|
</n-icon>
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="row justify-center fl-px-md fl-pb-md">
|
||||||
|
<div class="col-12 overflow-auto" style="height: 60vh">
|
||||||
|
<fln-table
|
||||||
|
:config="state.tableConfig"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount"
|
||||||
|
:defaultSelectedRows="state.selectedRows"
|
||||||
|
@triggerRowActions="handleRowActions"
|
||||||
|
@triggerSelectCheck="handleTableSelectCheck"
|
||||||
|
>
|
||||||
|
<template #table-header-box>
|
||||||
|
<div class="col-12 row fl-mb-sm justify-between">
|
||||||
|
<div class="row items-center">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #eff3ff; color: #6b69a3"
|
||||||
|
class="fl-mr-md"
|
||||||
|
:disabled="state.selectedRows.length === 0"
|
||||||
|
@click="handleQuickSelectPosi"
|
||||||
|
>快速添加到岗位</n-button
|
||||||
|
>
|
||||||
|
<div v-if="state.selectedRows.length > 0">
|
||||||
|
已选 {{ state.selectedRows.length }} 个
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #9c9ad3; color: #ffffff"
|
||||||
|
@click="handleCreatePermiss"
|
||||||
|
>新增权限</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 row justify-center fl-mt-md">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #fff"
|
||||||
|
class="fl-mr-md"
|
||||||
|
@click="handleDialogBack"
|
||||||
|
>返回</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
<Auth
|
||||||
|
v-if="state.showModal"
|
||||||
|
:title="state.modalAuth.title"
|
||||||
|
:data="state.modalAuth.data"
|
||||||
|
@triggerClose="handleCloseEditAuth"
|
||||||
|
/>
|
||||||
|
<fl-permission-bind-posi
|
||||||
|
v-if="state.diallogPosi"
|
||||||
|
:fatherData="state.selectedRows"
|
||||||
|
@triggerClose="handleQuickSelectPosiClose"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
// 权限列表 管理
|
||||||
|
import {
|
||||||
|
UpOutlined,
|
||||||
|
DownOutlined,
|
||||||
|
CloseCircleOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
DragOutlined,
|
||||||
|
} from "@ant-design/icons-vue";
|
||||||
|
import { Close as CloseIcon } from "@vicons/ionicons5";
|
||||||
|
import flnFormItem from "@/components/flnlayout/form/flnformItem.vue";
|
||||||
|
import flAboutApproval from "./aboutApproval.vue";
|
||||||
|
import flPermissionBindPosi from "./permissionbindposi.vue";
|
||||||
|
import draggable from "vuedraggable";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter, useRoute } from "vue-router";
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
import { ChevronDownOutline, ChevronUpOutline } from "@vicons/ionicons5";
|
||||||
|
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
import Auth from "./editAuth.vue";
|
||||||
|
const emits = defineEmits(["triggerClose"]);
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
selectedRows: [],
|
||||||
|
btnLoading: false,
|
||||||
|
dialogModal: true,
|
||||||
|
|
||||||
|
tableConfig: {
|
||||||
|
tableScrollWitdh: 600,
|
||||||
|
rowKey: "ID",
|
||||||
|
hasSelection: true,
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "data",
|
||||||
|
pageField: "page",
|
||||||
|
pageSizeField: "pageSize",
|
||||||
|
url: "/rule/list",
|
||||||
|
},
|
||||||
|
searchStyle: "padding-top:0px !important;",
|
||||||
|
searchConfig: [
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
label: "权限类型",
|
||||||
|
field: "Type",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
config: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: "menu",
|
||||||
|
label: "菜单权限",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "button",
|
||||||
|
label: "按钮权限",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "interface",
|
||||||
|
label: "接口权限",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "权限名称",
|
||||||
|
field: "Title",
|
||||||
|
class: "col-4",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: "权限编号",
|
||||||
|
field: "ID",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "tooltip",
|
||||||
|
title: "权限名",
|
||||||
|
field: "Title",
|
||||||
|
maxWidth: "100%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
title: "权限类型",
|
||||||
|
field: "Type",
|
||||||
|
config: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: "menu",
|
||||||
|
label: "菜单权限",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "button",
|
||||||
|
label: "按钮权限",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "interface",
|
||||||
|
label: "接口权限",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 200,
|
||||||
|
title: "操作",
|
||||||
|
fixed: "right",
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: "act_edit",
|
||||||
|
type: "label",
|
||||||
|
label: "修改",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: "act_del",
|
||||||
|
type: "label",
|
||||||
|
label: "删除",
|
||||||
|
shape: "round",
|
||||||
|
class: "fl-mx-xs fl-mt-xs",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
showModal: false,
|
||||||
|
modalAuth: { title: "新增权限", data: null },
|
||||||
|
diallogPosi: false,
|
||||||
|
});
|
||||||
|
onBeforeMount(() => {
|
||||||
|
state.dialogModal = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {});
|
||||||
|
|
||||||
|
const handleDialogBack = () => {
|
||||||
|
state.dialogField = false;
|
||||||
|
emits("triggerClose");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRowActions = ({ btnConfig, rowData }) => {
|
||||||
|
if (btnConfig.actionType === "act_edit") {
|
||||||
|
state.modalAuth = { title: "修改与删除-权限", data: { id: rowData.ID } };
|
||||||
|
state.showModal = true;
|
||||||
|
}
|
||||||
|
if (btnConfig.actionType === "act_del") {
|
||||||
|
$request.HTTP.permission
|
||||||
|
.ruleRemove({ ID: rowData.ID })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status == 0) {
|
||||||
|
processSuccess("删除成功");
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
} else {
|
||||||
|
processError(res.msg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
processError(e.response?.data?.msg || "操作失败");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTableSelectCheck = (data) => {
|
||||||
|
if (data && Array.isArray(data.selectedRow)) {
|
||||||
|
data.selectedRow = data.selectedRow.filter((item) => {
|
||||||
|
if (item) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.action === "check" || data.action === "checkAll") {
|
||||||
|
state.selectedRows = state.selectedRows.concat(data.selectedRow);
|
||||||
|
state.selectedRows = state.selectedRows.filter((item, index, arr) => {
|
||||||
|
return (
|
||||||
|
arr.findIndex((obj) => JSON.stringify(obj) === JSON.stringify(item)) ===
|
||||||
|
index
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.action === "uncheck") {
|
||||||
|
state.selectedRows = state.selectedRows.filter((item) => {
|
||||||
|
return item.ID !== data.selectedRow.ID;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.action === "uncheckAll") {
|
||||||
|
state.selectedRows = state.selectedRows.filter((item) => {
|
||||||
|
return (
|
||||||
|
data.selectedRow.findIndex((obj) => {
|
||||||
|
return obj.ID === item.ID;
|
||||||
|
}) === -1
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleCreatePermiss = () => {
|
||||||
|
state.modalAuth = { title: "新增权限", data: null };
|
||||||
|
state.showModal = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleQuickSelectPosi = () => {
|
||||||
|
state.diallogPosi = true;
|
||||||
|
};
|
||||||
|
const handleQuickSelectPosiClose = () => {
|
||||||
|
state.selectedRows = [];
|
||||||
|
state.diallogPosi = false;
|
||||||
|
};
|
||||||
|
const handleCloseEditAuth = (val) => {
|
||||||
|
state.showModal = false;
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
308
src/views/manage/posimanage/permissionbindposi.vue
Normal file
308
src/views/manage/posimanage/permissionbindposi.vue
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
<template>
|
||||||
|
<n-modal v-model:show="state.dialogModal" :mask-closable="false">
|
||||||
|
<n-card
|
||||||
|
style="width: 80vw"
|
||||||
|
:bordered="false"
|
||||||
|
size="huge"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
<template #header-extra>
|
||||||
|
<n-button @click="handleDialogBack" text style="font-size: 24px">
|
||||||
|
<n-icon>
|
||||||
|
<close-icon />
|
||||||
|
</n-icon>
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="row justify-center fl-pa-md overflow-auto"
|
||||||
|
style="max-height: 60vh"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-3 fl-pa-md row"
|
||||||
|
style="
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: rgba(188, 188, 188, 0.18) 0px 3px 6px 1px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<fl-tree
|
||||||
|
:data="state.treeData"
|
||||||
|
:expandedKeys="state.expandedKeys"
|
||||||
|
:refreshCount="state.treeRefreshCount"
|
||||||
|
:clickKey="state.clickKey"
|
||||||
|
@triggerTreeClick="handleTreeClick"
|
||||||
|
></fl-tree>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-9 fl-px-md">
|
||||||
|
<fln-table
|
||||||
|
:config="state.tableConfig"
|
||||||
|
:fatherData="state.treeSelectData"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount"
|
||||||
|
:defaultSelectedRows="state.selectedRows"
|
||||||
|
@triggerRowActions="handleRowActions"
|
||||||
|
@triggerSelectCheck="handleTableSelectCheck"
|
||||||
|
>
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 row justify-center fl-mt-md">
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #c7c7c9ff; color: #fff"
|
||||||
|
class="fl-mr-md"
|
||||||
|
@click="handleDialogBack"
|
||||||
|
>上一步</n-button
|
||||||
|
>
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
style="width: 161px; background: #46299d; color: #fff"
|
||||||
|
class="fl-mr-md"
|
||||||
|
@click="handleDialogSave"
|
||||||
|
>保存</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 岗位
|
||||||
|
import { NButton } from "naive-ui";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
nextTick,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import login from "@/api/login";
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
import flTree from "@/components/flnlayout/tree/flnindex.vue";
|
||||||
|
import { Close as CloseIcon } from "@vicons/ionicons5";
|
||||||
|
import { Local } from "@/utils/storage.js";
|
||||||
|
const router = useRouter();
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
const emits = defineEmits(["triggerClose"]);
|
||||||
|
let props = defineProps({
|
||||||
|
fatherData: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const state = reactive({
|
||||||
|
clickKey: "",
|
||||||
|
treeRefreshCount: 0,
|
||||||
|
expandedKeys: [],
|
||||||
|
treeData: [],
|
||||||
|
treeSelectData: {},
|
||||||
|
btnLoading: false,
|
||||||
|
selectedRows: [],
|
||||||
|
tableConfig: {
|
||||||
|
tableScrollWitdh: 600,
|
||||||
|
rowKey: "ID",
|
||||||
|
hasSelection: true,
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "data",
|
||||||
|
pageField: "page",
|
||||||
|
pageSizeField: "pageSize",
|
||||||
|
url: "/position/v2/list",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
label: "departmentID",
|
||||||
|
field: "key",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: "岗位ID",
|
||||||
|
field: "ID",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 140,
|
||||||
|
title: "岗位名",
|
||||||
|
field: "name",
|
||||||
|
type: "sfBgColor",
|
||||||
|
bgConfig: {
|
||||||
|
bgColorField: "color",
|
||||||
|
color: "#fff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 120,
|
||||||
|
type: "tooltip",
|
||||||
|
title: "岗位描述",
|
||||||
|
field: "remark",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 360,
|
||||||
|
title: "页面权限",
|
||||||
|
field: "menuAuths",
|
||||||
|
type: "tags",
|
||||||
|
tagConfig: {
|
||||||
|
showLength: 3,
|
||||||
|
bgColor: "#fff",
|
||||||
|
borderRadius: "14px",
|
||||||
|
style: "border-radius: 14px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 140,
|
||||||
|
sorter: true,
|
||||||
|
title: "被关联人数",
|
||||||
|
field: "linkerNum",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
dialogModal: true,
|
||||||
|
});
|
||||||
|
onBeforeMount(() => {
|
||||||
|
state.dialogModal = true;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
state.treeRefreshCount++;
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "获取失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("获取失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
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 handleTreeClick = ({ selectedKey, tree }) => {
|
||||||
|
state.clickKey = tree.key;
|
||||||
|
state.treeSelectData = tree;
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRowActions = ({ btnConfig, rowData }) => {
|
||||||
|
Local.set("posimanage_treeSelectData", state.treeSelectData);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDialogSave = () => {
|
||||||
|
if (state.selectedRows.length > 50) {
|
||||||
|
return processError("最多选择50个岗位!");
|
||||||
|
}
|
||||||
|
state.btnLoading = true;
|
||||||
|
let url = "/position/v2/batch/bind/auth";
|
||||||
|
let params = {
|
||||||
|
ids: state.selectedRows.map((item) => item.ID),
|
||||||
|
ruleIds: props.fatherData.map((item) => item.ID),
|
||||||
|
};
|
||||||
|
$request.HTTP.components.postDataByParams(url, params).then(
|
||||||
|
(res) => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
if (res.status === 0) {
|
||||||
|
state.tableConfig.refreshCount++;
|
||||||
|
processSuccess("操作成功!");
|
||||||
|
emits("triggerClose");
|
||||||
|
} else {
|
||||||
|
processError(res.msg || "操作失败!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
processError("操作失败!");
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
state.btnLoading = false;
|
||||||
|
processError("操作失败!");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const handleDialogBack = () => {
|
||||||
|
emits("triggerClose");
|
||||||
|
};
|
||||||
|
const handleTableSelectCheck = (data) => {
|
||||||
|
if (data && Array.isArray(data.selectedRow)) {
|
||||||
|
data.selectedRow = data.selectedRow.filter((item) => {
|
||||||
|
if (item) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.action === "check" || data.action === "checkAll") {
|
||||||
|
state.selectedRows = state.selectedRows.concat(data.selectedRow);
|
||||||
|
state.selectedRows = state.selectedRows.filter((item, index, arr) => {
|
||||||
|
return (
|
||||||
|
arr.findIndex((obj) => JSON.stringify(obj) === JSON.stringify(item)) ===
|
||||||
|
index
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.action === "uncheck") {
|
||||||
|
state.selectedRows = state.selectedRows.filter((item) => {
|
||||||
|
return item.ID !== data.selectedRow.ID;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.action === "uncheckAll") {
|
||||||
|
state.selectedRows = state.selectedRows.filter((item) => {
|
||||||
|
return (
|
||||||
|
data.selectedRow.findIndex((obj) => {
|
||||||
|
return obj.ID === item.ID;
|
||||||
|
}) === -1
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
149
src/views/manage/posirecordlog/index.vue
Normal file
149
src/views/manage/posirecordlog/index.vue
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row"
|
||||||
|
style="padding: 35px">
|
||||||
|
<div class="col-12 row">
|
||||||
|
<fln-table :config="state.tableConfig"
|
||||||
|
:refreshCount="state.tableConfig.refreshCount">
|
||||||
|
<template #search-header>
|
||||||
|
<div class="col-12 row font-18"
|
||||||
|
style="color: #764cf6; border-bottom: 1px solid #c1b2e5;">
|
||||||
|
<div class="fl-py-sm"
|
||||||
|
style="border-bottom: 4px solid #764cf6;">
|
||||||
|
岗位操作记录
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</fln-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 岗位
|
||||||
|
import { NButton } from "naive-ui";
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
onBeforeMount,
|
||||||
|
onMounted,
|
||||||
|
getCurrentInstance,
|
||||||
|
computed,
|
||||||
|
} from "vue";
|
||||||
|
import { processError, processSuccess } from "@/utils/helper/message";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||||||
|
|
||||||
|
const currentInstance = getCurrentInstance();
|
||||||
|
const { $request } = currentInstance.appContext.config.globalProperties;
|
||||||
|
const title = ref("");
|
||||||
|
const state = reactive({
|
||||||
|
btnLoading: false,
|
||||||
|
selectedRows: [],
|
||||||
|
tableConfig: {
|
||||||
|
tableScrollWitdh: 600,
|
||||||
|
rowKey: "ID",
|
||||||
|
refreshCount: 0,
|
||||||
|
listUrl: {
|
||||||
|
resDataField: "list",
|
||||||
|
pageField: "page",
|
||||||
|
pageSizeField: "pageSize",
|
||||||
|
url: "/position/v2/log/list",
|
||||||
|
},
|
||||||
|
searchConfig: [
|
||||||
|
{
|
||||||
|
type: "select",
|
||||||
|
label: "操作类型",
|
||||||
|
field: "operateType",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "新增",
|
||||||
|
value: "add",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "修改",
|
||||||
|
value: "edit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "删除",
|
||||||
|
value: "del",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "查看",
|
||||||
|
value: "detail",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "操作人",
|
||||||
|
field: "operatorName",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "操作人账号",
|
||||||
|
field: "OperatorTel",
|
||||||
|
placeholder: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "rangdate",
|
||||||
|
label: "操作时间",
|
||||||
|
field: ["StartCreatedAt", "EndCreatedAt"],
|
||||||
|
placeholder: ["开始", "结束"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
title: "操作类型",
|
||||||
|
field: "operateType",
|
||||||
|
config: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "新增",
|
||||||
|
value: "add",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "修改",
|
||||||
|
value: "edit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "删除",
|
||||||
|
value: "del",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "查看",
|
||||||
|
value: "detail",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "tooltip",
|
||||||
|
title: "操作详情",
|
||||||
|
field: "info",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "tooltip",
|
||||||
|
title: "操作人",
|
||||||
|
field: "operatorName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作人账号",
|
||||||
|
field: "OperatorTel",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作时间",
|
||||||
|
field: "createdAt",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
onBeforeMount(() => {
|
||||||
|
});
|
||||||
|
onMounted(() => { });
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user