fix
This commit is contained in:
parent
268c131aa7
commit
b5a2504dbd
@ -18,6 +18,24 @@ export const departmentV2AllPosition = (data) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const departmentV2TreeAll = (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/department/v2/tree/all',
|
||||||
|
baseURL:import.meta.env.VITE_EPR_BASEURL,
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const userV2List = (data) => {
|
||||||
|
return request({
|
||||||
|
url: '/user/v2/list',
|
||||||
|
baseURL:import.meta.env.VITE_EPR_BASEURL,
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const groupCreateDept = (data) => {
|
export const groupCreateDept = (data) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/v1/group/create-dept',
|
url: '/api/v1/group/create-dept',
|
||||||
|
@ -46,6 +46,14 @@
|
|||||||
"enablePullDownRefresh":false
|
"enablePullDownRefresh":false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/chooseMembers/index",
|
||||||
|
"type": "page",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"enablePullDownRefresh":false
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/chooseGroupAdmin/index",
|
"path": "pages/chooseGroupAdmin/index",
|
||||||
"type": "page",
|
"type": "page",
|
||||||
|
692
src/pages/chooseMembers/index.vue
Normal file
692
src/pages/chooseMembers/index.vue
Normal file
@ -0,0 +1,692 @@
|
|||||||
|
<template>
|
||||||
|
<div class="outer-layer">
|
||||||
|
<div>
|
||||||
|
<tm-navbar :hideBack="false" hideHome title="选择部门"> </tm-navbar>
|
||||||
|
</div>
|
||||||
|
<div class="root">
|
||||||
|
<div
|
||||||
|
class="w-full h-[1134rpx] mb-[20rpx] pl-[32rpx] pr-[32rpx] pb-[20rpx] overflow-y-auto"
|
||||||
|
>
|
||||||
|
<div class="pl-[16rpx] pr-[16rpx] pt-[22rpx] pb-[24rpx] bg-[#FFFFFF]">
|
||||||
|
<tm-input
|
||||||
|
placeholder="请输入…"
|
||||||
|
color="#F9F9FD"
|
||||||
|
:round="1"
|
||||||
|
prefix="tmicon-search"
|
||||||
|
prefixColor="#46299D"
|
||||||
|
searchBgColor="#F9F9FD"
|
||||||
|
focusColor="#F9F9FD"
|
||||||
|
v-model="searchVal"
|
||||||
|
></tm-input>
|
||||||
|
<div
|
||||||
|
v-if="crumbs.length"
|
||||||
|
class="w-full overflow-x-auto mt-[22rpx] leading-[48rpx] text-[#2F2F2F] flex items-center no-scrollbar"
|
||||||
|
ref="crumbsContainer"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in crumbs"
|
||||||
|
class="flex items-center text-[28rpx] leading-[48rpx] whitespace-nowrap"
|
||||||
|
:class="[
|
||||||
|
index === crumbsIndex ? 'text-[#747474]' : 'text-[#46299D]',
|
||||||
|
index === 0 ? '' : 'ml-[12rpx]',
|
||||||
|
]"
|
||||||
|
@click="handleCrumbsClick(index)"
|
||||||
|
>
|
||||||
|
<div>{{ item.name }}</div>
|
||||||
|
<div
|
||||||
|
v-if="index !== crumbs.length - 1"
|
||||||
|
class="ml-[20rpx] flex items-center mb-[2rpx]"
|
||||||
|
>
|
||||||
|
<tm-icon
|
||||||
|
name="tmicon-angle-right"
|
||||||
|
:font-size="20"
|
||||||
|
:color="index !== crumbs.length - 1 ? '#7A58DE' : '#C1B4EA'"
|
||||||
|
></tm-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="pl-[32rpx] bg-[#FFFFFF] mt-[20rpx] h-[110rpx] flex items-center"
|
||||||
|
@click="()=>allCheck(allCheckStatus)"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<checkBox
|
||||||
|
:disabled="currentCrumbs?.sons?.length === 0"
|
||||||
|
:modelValue="allCheckStatus"
|
||||||
|
></checkBox>
|
||||||
|
</div>
|
||||||
|
<div class="font-bold text-[28rpx] leading-[54rpx] ml-[20rpx]">
|
||||||
|
全选
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="currentCrumbs?.sons?.length"
|
||||||
|
v-for="item in currentCrumbs?.sons"
|
||||||
|
class="pl-[32rpx] bg-[#FFFFFF] mt-[20rpx] h-[110rpx] flex items-center"
|
||||||
|
>
|
||||||
|
<div class="w-full flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex items-center"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<checkBox
|
||||||
|
:disabled="!item?.sons?.length"
|
||||||
|
v-model="item.checkStatus"
|
||||||
|
@change="(val) => checkItemChange(item, val)"
|
||||||
|
></checkBox>
|
||||||
|
</div>
|
||||||
|
<div class="font-bold text-[28rpx] leading-[54rpx] ml-[20rpx]">
|
||||||
|
{{ item.name }} ({{ getDepTotalMembers(item) }})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.sons?.length" class="flex items-center mr-[32rpx]">
|
||||||
|
<div class="vDivider mr-[32rpx]"></div>
|
||||||
|
<div @click="() => toNextLevel(item)" class="flex items-center">
|
||||||
|
<div class="mr-[12rpx]">
|
||||||
|
<tm-image
|
||||||
|
:width="26"
|
||||||
|
:height="26"
|
||||||
|
:src="item.checkStatus !== 'checked' ? downDep : downDepDis"
|
||||||
|
></tm-image>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="text-[28rpx] leading-[54rpx] font-bold"
|
||||||
|
:class="
|
||||||
|
item.checkStatus !== 'checked'
|
||||||
|
? 'text-[#46299D]'
|
||||||
|
: 'text-[#C1B4EA]'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
下级
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="currentMembers.length"
|
||||||
|
v-for="item in currentMembers"
|
||||||
|
class="pl-[32rpx] pr-[32rpx] bg-[#FFFFFF] mt-[20rpx] h-[110rpx] flex items-center"
|
||||||
|
>
|
||||||
|
<div class="w-full flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex items-center"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<checkBox
|
||||||
|
:modelValue="membersCheckedKeys.filter(v=>v.ID === item.ID).length>0?'checked':'noChecked'"
|
||||||
|
@change="(val) => checkMember(item, val)"
|
||||||
|
></checkBox>
|
||||||
|
</div>
|
||||||
|
<div class="ml-[20rpx] flex items-center">
|
||||||
|
<div class="userAvatar flex items-center justify-center">
|
||||||
|
{{ item.nickName.slice(-2) }}
|
||||||
|
</div>
|
||||||
|
<div class="ml-[20rpx] flex flex-col items-center">
|
||||||
|
<div class="text-[28rpx] font-bold" >{{ item.nickName }}</div>
|
||||||
|
<div class="text-[20rpx] text-[#747474]" >{{ item.jobNum }}</div>
|
||||||
|
</div>
|
||||||
|
<tm-popover position="tc">
|
||||||
|
<div class="ml-[20rpx] flex h-[68rpx] flex-wrap line-clamp-2 max-w-[342rpx]">
|
||||||
|
<div
|
||||||
|
v-for="post in item.positions"
|
||||||
|
class="postTag truncate mb-[4rpx] mr-[14rpx] max-w-[164rpx]"
|
||||||
|
>
|
||||||
|
{{ post.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template v-slot:label>
|
||||||
|
<div class="max-h-[250rpx] overflow-y-auto pt-[10rpx] pl-[18rpx] pr-[18rpx] pb-[12rpx]">
|
||||||
|
<div
|
||||||
|
v-for="post in item.positions"
|
||||||
|
class="postTag truncate mb-[10rpx] "
|
||||||
|
>
|
||||||
|
{{ post.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</tm-popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="h-[162rpx] pl-[32rpx] pr-[32rpx] bg-[#FFFFFF]">
|
||||||
|
<div class="mt-[14rpx] flex justify-between">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div @click="openDrawer" class="flex items-center text-[28rpx] leading-[60rpx] text-[#000000] font-bold">
|
||||||
|
<div>已选择:</div>
|
||||||
|
<div>{{ totalMembers }}人</div>
|
||||||
|
<div class="ml-[28rpx]">
|
||||||
|
<tm-icon :fontSize="24" color="#46299D" name="tmicon-angle-up"></tm-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-[24rpx] leading-[24rpx] text-[#7A58DE] w-[280rpx] truncate ">
|
||||||
|
<span v-for="item in allCheckedList" >
|
||||||
|
{{ item.name }}({{ item.staffNum }})
|
||||||
|
</span>
|
||||||
|
<span v-for="(item,index) in membersCheckedKeys" >
|
||||||
|
{{ item.nickName }}
|
||||||
|
{{ index!== membersCheckedKeys.length-1?',':"" }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="btnBox">
|
||||||
|
<tm-button
|
||||||
|
@click="handleConfirm"
|
||||||
|
color="#46299D"
|
||||||
|
:disabled="!allCheckedList.length"
|
||||||
|
disabledColor="#E6E6E6"
|
||||||
|
:margin="[0]"
|
||||||
|
:shadow="0"
|
||||||
|
:width="264"
|
||||||
|
:height="76"
|
||||||
|
size="large"
|
||||||
|
label="确定"
|
||||||
|
>
|
||||||
|
</tm-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<tm-drawer
|
||||||
|
placement="bottom"
|
||||||
|
v-model:show="showWin"
|
||||||
|
:height="800"
|
||||||
|
:hideHeader="true"
|
||||||
|
:round="5"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col w-full h-full pt-[36rpx] pl-[32rpx] pr-[32rpx] leading-[60rpx]" >
|
||||||
|
<div class="text-[32rpx] font-bold flex items-center justify-between" >
|
||||||
|
<div class="flex items-center ml-[10rpx]">
|
||||||
|
<div>已选择部门数:</div>
|
||||||
|
<div>{{ allCheckedList.length }}</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="text-[#7A58DE] mr-[10rpx]"
|
||||||
|
@click="()=>showWin = false"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 pb-[20rpx] overflow-y-auto pt-[30rpx]" >
|
||||||
|
<div
|
||||||
|
v-for="(item,index) in allCheckedList"
|
||||||
|
class="flex flex-col"
|
||||||
|
>
|
||||||
|
<div v-if="index ===0" class="divider" ></div>
|
||||||
|
<div
|
||||||
|
class="flex items-center justify-between mt-[36rpx] font-bold text-[#000000] leading-[54rpx] mb-[34rpx]"
|
||||||
|
>
|
||||||
|
<div class="text-[28rpx] ml-[10rpx]">{{ item.name }}({{ item.staffNum }})</div>
|
||||||
|
<div class="diyBtn">
|
||||||
|
<tm-button @click="()=>deleteNode(item)" :disabled="userDepIds.includes(item.ID)" :margin="[10]" :shadow="0" text size="small" :width="106" :height="50" outlined label="移除"></tm-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="divider" ></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="(item,index) in membersCheckedKeys"
|
||||||
|
class="flex flex-col"
|
||||||
|
>
|
||||||
|
<div v-if="index ===0 && allCheckedList.length==0" class="divider" ></div>
|
||||||
|
<div
|
||||||
|
class="flex items-center justify-between mt-[36rpx] font-bold text-[#000000] leading-[54rpx] mb-[34rpx]"
|
||||||
|
>
|
||||||
|
<div class="text-[28rpx] ml-[10rpx] flex">
|
||||||
|
<div>
|
||||||
|
{{ item.nickName }}({{ item.jobNum }})
|
||||||
|
</div>
|
||||||
|
<div class="ml-[20rpx] flex h-[68rpx] flex-wrap line-clamp-2 max-w-[342rpx]">
|
||||||
|
<div
|
||||||
|
v-for="post in item.positions"
|
||||||
|
class="postTag truncate mb-[4rpx] mr-[14rpx] max-w-[164rpx]"
|
||||||
|
>
|
||||||
|
{{ post.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="diyBtn">
|
||||||
|
<tm-button @click="()=>deleteMember(item)" :margin="[10]" :shadow="0" text size="small" :width="106" :height="50" outlined label="移除"></tm-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="divider" ></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</tm-drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch, computed, onMounted,nextTick } from "vue";
|
||||||
|
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||||
|
import { useChatList } from "@/store/chatList/index.js";
|
||||||
|
import { useAuth } from "@/store/auth";
|
||||||
|
import { useTalkStore, useUserStore } from "@/store";
|
||||||
|
import { useGroupTypeStore } from "@/store/groupType";
|
||||||
|
import downDep from "@/static/image/chatList/downDep.png";
|
||||||
|
import downDepDis from "@/static/image/chatList/downDepDis.png";
|
||||||
|
import checkBox from "@/components/checkBox/index.vue";
|
||||||
|
import lodash from 'lodash'
|
||||||
|
|
||||||
|
const {
|
||||||
|
groupActiveIndex,
|
||||||
|
getDepsTreeMy,
|
||||||
|
depTreeMyList,
|
||||||
|
crumbs,
|
||||||
|
crumbsIndex,
|
||||||
|
depCheckedKeys,
|
||||||
|
getDepMembers,
|
||||||
|
membersCheckedKeys,
|
||||||
|
allChooseMembers,
|
||||||
|
} = useGroupTypeStore();
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const searchVal = ref("");
|
||||||
|
const crumbsContainer = ref(null);
|
||||||
|
const showWin = ref(false);
|
||||||
|
const currentMembers = ref([])
|
||||||
|
|
||||||
|
const getAllCheckedNodes = (node, checkedNodes = []) => {
|
||||||
|
if (node.checkStatus === 'checked') {
|
||||||
|
checkedNodes.push(node);
|
||||||
|
}
|
||||||
|
if (node.sons && Array.isArray(node.sons)) {
|
||||||
|
node.sons.forEach(son => getAllCheckedNodes(son, checkedNodes));
|
||||||
|
}
|
||||||
|
return checkedNodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
const userDepIds = computed(() => {
|
||||||
|
return userStore.deps.map(v=>v.dept_id);
|
||||||
|
});
|
||||||
|
|
||||||
|
const calculateTotalStaffNum = (node) => {
|
||||||
|
let total = node.staffNum || 0;
|
||||||
|
if (node.sons && Array.isArray(node.sons)) {
|
||||||
|
node.sons.forEach(son => {
|
||||||
|
total += calculateTotalStaffNum(son);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
};
|
||||||
|
|
||||||
|
const allCheckedList = computed(() => {
|
||||||
|
const checkedNodes = [];
|
||||||
|
depTreeMyList.value.forEach(node => getAllCheckedNodes(node, checkedNodes));
|
||||||
|
console.log("checkedNodes", checkedNodes);
|
||||||
|
|
||||||
|
return checkedNodes;
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentCrumbs = computed(() => {
|
||||||
|
if (crumbs.value[crumbsIndex.value] ) {
|
||||||
|
if (searchVal.value && searchVal.value !== "") {
|
||||||
|
let filterSons = crumbs.value[crumbsIndex.value].sons.filter((item) =>
|
||||||
|
item.name.includes(searchVal.value)
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...crumbs.value[crumbsIndex.value],
|
||||||
|
sons: filterSons,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log("allCheckedList", crumbs.value[crumbsIndex.value]);
|
||||||
|
return crumbs.value[crumbsIndex.value];
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
});
|
||||||
|
|
||||||
|
const getCurrentMembers = async (depItem) => {
|
||||||
|
const res = await getDepMembers({
|
||||||
|
departmentId:depItem.ID,
|
||||||
|
status:'notactive'
|
||||||
|
})
|
||||||
|
if (res.status === 0) {
|
||||||
|
currentMembers.value = res.data.data.length?res.data.data.map(v=>{
|
||||||
|
return {
|
||||||
|
...v,
|
||||||
|
isMember:true,
|
||||||
|
}
|
||||||
|
}):[]
|
||||||
|
}else{
|
||||||
|
currentMembers.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkMember = (item, val) => {
|
||||||
|
if (val === 'checked') {
|
||||||
|
membersCheckedKeys.value.push(item)
|
||||||
|
}else {
|
||||||
|
membersCheckedKeys.value = membersCheckedKeys.value.filter(v=>v.ID !==item.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => currentCrumbs.value, (newValue, oldValue) => {
|
||||||
|
getCurrentMembers(newValue)
|
||||||
|
})
|
||||||
|
|
||||||
|
const allCheckStatus = computed(() => {
|
||||||
|
if (!currentCrumbs.value.sons) {
|
||||||
|
return "noChecked";
|
||||||
|
}
|
||||||
|
const allChecked = currentCrumbs.value.sons.every((son) => son.checkStatus === "checked");
|
||||||
|
const someChecked =currentCrumbs.value.sons.some(
|
||||||
|
(son) =>
|
||||||
|
son.checkStatus === "checked" || son.checkStatus === "halfChecked"
|
||||||
|
);
|
||||||
|
if (allChecked) {
|
||||||
|
return "checked";
|
||||||
|
} else if (someChecked) {
|
||||||
|
return "halfChecked";
|
||||||
|
} else {
|
||||||
|
return "noChecked";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const findNodeById = (node, targetId) => {
|
||||||
|
if (node.ID === targetId) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (node.sons && Array.isArray(node.sons)) {
|
||||||
|
for (const son of node.sons) {
|
||||||
|
const found = findNodeById(son, targetId);
|
||||||
|
if (found) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const findParentNode = (node, targetId) => {
|
||||||
|
if (!node.sons || !Array.isArray(node.sons)) return null;
|
||||||
|
for (const son of node.sons) {
|
||||||
|
if (son.ID === targetId) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
const parent = findParentNode(son, targetId);
|
||||||
|
if (parent) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 检查并更新父节点的状态
|
||||||
|
const updateParentStatus = (node) => {
|
||||||
|
const parent = findParentNode(depTreeMyList.value[0], node.ID);
|
||||||
|
if (!parent) return;
|
||||||
|
if (parent.checkStatus !== "checked"){
|
||||||
|
const allChecked =
|
||||||
|
parent.sons &&
|
||||||
|
Array.isArray(parent.sons) &&
|
||||||
|
parent.sons.every((son) => son.checkStatus === "checked");
|
||||||
|
const someChecked =
|
||||||
|
parent.sons &&
|
||||||
|
Array.isArray(parent.sons) &&
|
||||||
|
parent.sons.some(
|
||||||
|
(son) =>
|
||||||
|
son.checkStatus === "checked" || son.checkStatus === "halfChecked"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (allChecked) {
|
||||||
|
parent.checkStatus = "halfChecked";
|
||||||
|
} else if (someChecked) {
|
||||||
|
parent.checkStatus = "halfChecked";
|
||||||
|
} else {
|
||||||
|
parent.checkStatus = "noChecked";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateParentStatus(parent);
|
||||||
|
};
|
||||||
|
//根据子节点状态更新当前节点状态
|
||||||
|
const updateNodeStatus = (node) => {
|
||||||
|
if (!node.sons || !Array.isArray(node.sons)) return;
|
||||||
|
const allChecked = node.sons.every(son => son.checkStatus === 'checked');
|
||||||
|
const someChecked = node.sons.some(son => son.checkStatus === 'checked' || son.checkStatus === 'halfChecked');
|
||||||
|
|
||||||
|
if (allChecked) {
|
||||||
|
node.checkStatus = 'halfChecked';
|
||||||
|
} else if (someChecked) {
|
||||||
|
node.checkStatus = 'halfChecked';
|
||||||
|
} else {
|
||||||
|
node.checkStatus = 'noChecked';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新当前节点及其所有子节点的状态
|
||||||
|
const updateCheckStatus = (node, status) => {
|
||||||
|
node.checkStatus = status;
|
||||||
|
if (node.sons && Array.isArray(node.sons) && node.sons.length > 0) {
|
||||||
|
node.sons.forEach((son) => updateCheckStatus(son, status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkItemChange = (item, val) => {
|
||||||
|
// 更新当前节点及其子节点的状态
|
||||||
|
updateCheckStatus(item, val);
|
||||||
|
|
||||||
|
// 更新父节点的状态
|
||||||
|
updateParentStatus(item);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteNode = (item) => {
|
||||||
|
const treeNode = findNodeById(depTreeMyList.value[0], item.ID);
|
||||||
|
if (!treeNode) return;
|
||||||
|
treeNode.checkStatus = "noChecked";
|
||||||
|
updateNodeStatus(treeNode);
|
||||||
|
updateParentStatus(treeNode);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteMember = (item) => {
|
||||||
|
membersCheckedKeys.value = membersCheckedKeys.value.filter(v=>v.ID !== item.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
const toNextLevel = async (item) => {
|
||||||
|
if (item.checkStatus !== "checked") {
|
||||||
|
crumbs.value.push(item);
|
||||||
|
crumbsIndex.value++;
|
||||||
|
await nextTick();
|
||||||
|
if (crumbsContainer.value) {
|
||||||
|
crumbsContainer.value.scrollLeft = crumbsContainer.value.scrollWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCrumbsClick = (index) => {
|
||||||
|
crumbsIndex.value = index;
|
||||||
|
crumbs.value = crumbs.value.slice(0, index + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const allCheck = (status) => {
|
||||||
|
let statusT = 'noChecked';
|
||||||
|
if (status === "checked") {
|
||||||
|
statusT = "noChecked";
|
||||||
|
} else {
|
||||||
|
statusT = "checked";
|
||||||
|
}
|
||||||
|
currentCrumbs.value.sons.forEach((item) => {
|
||||||
|
const itemT = findNodeById(depTreeMyList.value[0], item.ID)
|
||||||
|
if (!itemT) return;
|
||||||
|
checkItemChange(itemT, statusT);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const openDrawer = () => {
|
||||||
|
showWin.value = true;
|
||||||
|
if (allCheckedList.length>0) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// watch(() => depTreeMyList.value, (newValue, oldValue) => {
|
||||||
|
// console.log("depTreeMyList", newValue);
|
||||||
|
|
||||||
|
// }, { deep: true });
|
||||||
|
|
||||||
|
// watch(() => searchVal.value, (newValue, oldValue) => {
|
||||||
|
// console.log("searchVal", newValue);
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
const getDepTotalMembers = (item) => {
|
||||||
|
const rootNode = depTreeMyList.value[0];
|
||||||
|
const targetNode = findNodeById(rootNode, item.ID);
|
||||||
|
if (targetNode) {
|
||||||
|
return calculateTotalStaffNum(targetNode);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalMembers = computed(() => {
|
||||||
|
const depMembers = allCheckedList.value.reduce((sum, item) => sum + item.staffNum, 0);
|
||||||
|
const memberCount = membersCheckedKeys.value.length;
|
||||||
|
return depMembers + memberCount;
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleConfirm = async () => {
|
||||||
|
uni.showLoading()
|
||||||
|
const listT = membersCheckedKeys.value.map(v=>v)
|
||||||
|
const res = await getDepMembers({
|
||||||
|
departmentIds:allCheckedList.value.map(v=>v.ID),
|
||||||
|
status:'notactive',
|
||||||
|
})
|
||||||
|
if (res.status == 0 && res.data?.data?.length) {
|
||||||
|
res.data?.data.forEach(v=>{
|
||||||
|
listT.push(v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
allChooseMembers.value = listT
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
const initCheckedKeys = () => {
|
||||||
|
depCheckedKeys.value.forEach((item) => {
|
||||||
|
const node = findNodeById(depTreeMyList.value[0], item.ID);
|
||||||
|
if (node) {
|
||||||
|
node.checkStatus = "checked";
|
||||||
|
updateParentStatus(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const init = async () => {
|
||||||
|
crumbsIndex.value = 0;
|
||||||
|
await getDepsTreeMy();
|
||||||
|
crumbs.value = depTreeMyList.value.length ? [depTreeMyList.value[0]] : [];
|
||||||
|
initCheckedKeys();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
uni-page-body,
|
||||||
|
page {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.outer-layer {
|
||||||
|
overflow-y: auto;
|
||||||
|
flex: 1;
|
||||||
|
background-image: url("@/static/image/clockIn/z3280@3x.png");
|
||||||
|
background-size: cover;
|
||||||
|
padding-bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.root {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding-top: 18rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.divider {
|
||||||
|
height: 1rpx;
|
||||||
|
background-color: #707070;
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
.vDivider {
|
||||||
|
width: 1rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
background-color: #b4b4b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-placeholder {
|
||||||
|
width: 192rpx;
|
||||||
|
height: 192rpx;
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
.groupCard {
|
||||||
|
height: 272rpx;
|
||||||
|
width: 100%;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
&.firstPanel {
|
||||||
|
background-image: url("@/static/image/chatList/zu6033@2x.png");
|
||||||
|
}
|
||||||
|
&.secondPanel {
|
||||||
|
background-image: url("@/static/image/chatList/zu6031@2x.png");
|
||||||
|
margin-top: 28rpx;
|
||||||
|
margin-bottom: 28rpx;
|
||||||
|
}
|
||||||
|
&.thirdPanel {
|
||||||
|
background-image: url("@/static/image/chatList/zu6032@2x.png");
|
||||||
|
}
|
||||||
|
&.activePanel {
|
||||||
|
box-shadow: 0 0 0 3rpx #46299d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btnBox {
|
||||||
|
:deep(uni-button[disabled="true"]) {
|
||||||
|
color: #bebebe !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.no-scrollbar {
|
||||||
|
-ms-overflow-style: none; /* IE and Edge */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-scrollbar::-webkit-scrollbar {
|
||||||
|
display: none; /* Chrome, Safari, and Opera */
|
||||||
|
}
|
||||||
|
.diyBtn {
|
||||||
|
:deep(uni-button) {
|
||||||
|
color: #191919 !important;
|
||||||
|
border: 1rpx solid #D6D6D8 !important;
|
||||||
|
background-color: #FFFFFF !important;
|
||||||
|
&[disabled="true"] {
|
||||||
|
color: #BEBEBE !important;
|
||||||
|
border: 1rpx solid #E6E6E6 !important;
|
||||||
|
background-color: #E6E6E6 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.userAvatar{
|
||||||
|
background: linear-gradient(#674BBC, #46299D);
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: 36rpx;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.postTag{
|
||||||
|
background-color: #EEE9F8;
|
||||||
|
height: 32rpx;
|
||||||
|
line-height: 32rpx;
|
||||||
|
font-size: 20rpx;
|
||||||
|
padding: 0 12rpx 0 12rpx;
|
||||||
|
color: #46299D;
|
||||||
|
}
|
||||||
|
</style>
|
@ -47,7 +47,7 @@
|
|||||||
群类型
|
群类型
|
||||||
</div>
|
</div>
|
||||||
<div @click="chooseGroupType" class="left-box" >
|
<div @click="chooseGroupType" class="left-box" >
|
||||||
<div class="text-[#B4B4B4] text-[28rpx]" >
|
<div class="text-[#B4B4B4] text-[28rpx] font-bold" >
|
||||||
<span v-if="groupActiveIndex ===-1">请选择群类型</span>
|
<span v-if="groupActiveIndex ===-1">请选择群类型</span>
|
||||||
<span v-else-if="groupActiveIndex ===0">普通群</span>
|
<span v-else-if="groupActiveIndex ===0">普通群</span>
|
||||||
<span v-else-if="groupActiveIndex ===1">部门群</span>
|
<span v-else-if="groupActiveIndex ===1">部门群</span>
|
||||||
@ -76,6 +76,38 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="groupActiveIndex===0" class="input-group w-full flex flex-col mt-[20rpx] leading-[40rpx]" >
|
||||||
|
<div class="flex items-center justify-between" >
|
||||||
|
<div class="input-item">
|
||||||
|
群成员
|
||||||
|
</div>
|
||||||
|
<div @click="chooseMembers" class="left-box" >
|
||||||
|
<div class="ml-[32rpx] flex items-center" >
|
||||||
|
<div v-if="!groupAdmins.length" class="text-[#B4B4B4] text-[28rpx] font-bold mr-[32rpx]">全部({{ 0 }})</div>
|
||||||
|
<tm-icon :font-size="22" color="#747474" name="tmicon-angle-right"></tm-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="groupAdmins.length" class="mt-[32rpx]" >
|
||||||
|
<div
|
||||||
|
v-for="(item,index) in groupAdmins"
|
||||||
|
class="text-[#747474] text-[28rpx] leading-[40rpx] font-bold"
|
||||||
|
:class="[
|
||||||
|
index !==0 ? 'mt-[10rpx]':'',
|
||||||
|
depsNoExpanded&&index>4 ? 'hidden':''
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
<div class="text-[#46299D] text-[28rpx] mt-[20rpx] font-bold flex justify-center" >
|
||||||
|
<div v-if="groupAdmins.length>5" @click="depsNoExpanded = !depsNoExpanded" class="w-[100rpx]">
|
||||||
|
{{ depsNoExpanded? '展开':'收起' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="groupActiveIndex===1" class="input-group w-full flex flex-col mt-[20rpx] leading-[40rpx]" >
|
<div v-if="groupActiveIndex===1" class="input-group w-full flex flex-col mt-[20rpx] leading-[40rpx]" >
|
||||||
<div class="flex items-center justify-between" >
|
<div class="flex items-center justify-between" >
|
||||||
<div class="input-item">
|
<div class="input-item">
|
||||||
@ -179,6 +211,12 @@ const chooseGroupAdmin = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chooseMembers = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/chooseMembers/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const handleConfirm = async () => {
|
const handleConfirm = async () => {
|
||||||
if (groupActiveIndex.value === 0) {
|
if (groupActiveIndex.value === 0) {
|
||||||
|
|
||||||
@ -276,7 +314,7 @@ page {
|
|||||||
margin-left: 84rpx;
|
margin-left: 84rpx;
|
||||||
line-height: 40rpx;
|
line-height: 40rpx;
|
||||||
width: 404rpx;
|
width: 404rpx;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.left-box {
|
.left-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -5,7 +5,7 @@ import { userInfoApi } from "@/api/user";
|
|||||||
import {ref} from 'vue'
|
import {ref} from 'vue'
|
||||||
export const useAuth = createGlobalState(() => {
|
export const useAuth = createGlobalState(() => {
|
||||||
// const token = useStorage('token', '', uniStorage)
|
// const token = useStorage('token', '', uniStorage)
|
||||||
const token = ref('79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941ca1430937103230a1e32a1715f569f3efdbe6f8cb8b7b8642bd679668081b9b08f693d1b5be6002d936ec51e1e3e0c4927de9e32ac99a109b326e5d2bda27ec87624bb416ec70d2a95a2e190feeba9f0d6bae8571b3dfe89c824712344759a8f2bff9d70747c52525cf6a5614f9c770bca461a9b9c247b6dca97bcf83bbaf99bb726752c4fe1e9a4aa7de5c4cf3e88a3e480801280d45cdc124f9d8221105d8529c7c268c1251c3477bff5c051043bf9804c4f7096c5178cc01261bbedf04108b969333baf0bd5226c426de3591fc50b70691f2a5e275fa67ea3a7301df448929c13e4b71bf2182b6bfc270e21c142aa693844a0a175637f907e4438786a6e5e50')
|
const token = ref('79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941ca1430937103230a1e32a1715f569f3efdbe6f8cb8b7b8642bd679668081b9b08f693d1b5be6002d936ec51e1e3e0c4927de9e32ac99a109b326e5d2bda27ec87624bb416ec70d2a95a2e190feeba9f0d6bae8571b3dfe89c824712344759a8f2bff9d70747c52525cf6a5614f9c770bca461a9b9c247b6dca97bcf83bbaf99bb726752c4fe1e9a4aa7de5c4cf3e88a3e480801280d45cdc124f9d8221105d8529c7c268c1251c3477bff5c051043bf9803f725aa97cbe369f1902315052eb4ee0e925840addd5e7796254066f2f9eb3f99f69f3d0db26bd940f47a18fa7b6182c6c7de87ee1a00936b7c90024c6085c65ffc3b8d20562eea48ff0b303a7795c67')
|
||||||
const refreshToken = useStorage('refreshToken', '', uniStorage)
|
const refreshToken = useStorage('refreshToken', '', uniStorage)
|
||||||
const userInfo = useStorage('userInfo', {}, uniStorage)
|
const userInfo = useStorage('userInfo', {}, uniStorage)
|
||||||
const leaderList = useStorage('leaderList', [], uniStorage)
|
const leaderList = useStorage('leaderList', [], uniStorage)
|
||||||
|
@ -5,7 +5,7 @@ import lodash from 'lodash'
|
|||||||
import {ref} from 'vue'
|
import {ref} from 'vue'
|
||||||
import {createGlobalState,useStorage} from '@vueuse/core'
|
import {createGlobalState,useStorage} from '@vueuse/core'
|
||||||
import {uniStorage} from "@/utils/uniStorage.js"
|
import {uniStorage} from "@/utils/uniStorage.js"
|
||||||
import {departmentV2TreeMy,departmentV2AllPosition,groupCreateDept} from '@/api/deps/index.js'
|
import {departmentV2TreeMy,departmentV2AllPosition,groupCreateDept,departmentV2TreeAll,userV2List} from '@/api/deps/index.js'
|
||||||
|
|
||||||
export const useGroupTypeStore = createGlobalState(() => {
|
export const useGroupTypeStore = createGlobalState(() => {
|
||||||
const groupName = ref('')
|
const groupName = ref('')
|
||||||
@ -16,11 +16,11 @@ export const useGroupTypeStore = createGlobalState(() => {
|
|||||||
const crumbsIndex = ref(0)
|
const crumbsIndex = ref(0)
|
||||||
const depCheckedKeys = ref([]) // 选中的部门keys
|
const depCheckedKeys = ref([]) // 选中的部门keys
|
||||||
const groupAdmins = ref([]) // 选中的管理员
|
const groupAdmins = ref([]) // 选中的管理员
|
||||||
|
const membersCheckedKeys = ref([]) // 选中的人员keys
|
||||||
// const halfCheckedKeys = ref([])
|
const allChooseMembers = ref([])
|
||||||
|
|
||||||
const getDepsTreeMy= async()=>{
|
const getDepsTreeMy= async()=>{
|
||||||
const res = await departmentV2TreeMy()
|
const res = await departmentV2TreeAll()
|
||||||
if(res.status===0){
|
if(res.status===0){
|
||||||
depTreeMyList.value = res.data.nodes
|
depTreeMyList.value = res.data.nodes
|
||||||
}
|
}
|
||||||
@ -33,6 +33,11 @@ export const useGroupTypeStore = createGlobalState(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getDepMembers= async(param)=>{
|
||||||
|
const res = await userV2List(param)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
const resetGroupInfo = () => {
|
const resetGroupInfo = () => {
|
||||||
groupName.value = '';
|
groupName.value = '';
|
||||||
groupActiveIndex.value = -1;
|
groupActiveIndex.value = -1;
|
||||||
@ -77,5 +82,8 @@ export const useGroupTypeStore = createGlobalState(() => {
|
|||||||
groupAdmins,
|
groupAdmins,
|
||||||
resetGroupInfo,
|
resetGroupInfo,
|
||||||
createDepGroup,
|
createDepGroup,
|
||||||
|
getDepMembers,
|
||||||
|
membersCheckedKeys,
|
||||||
|
allChooseMembers,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user