chat-app/src/pages/chooseDeps/index.vue

372 lines
10 KiB
Vue
Raw Normal View History

2024-12-30 06:47:02 +00:00
<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(currentCrumbs.checkStatus)"
>
<div>
<checkBox
:disabled="currentCrumbs?.sons?.length === 0"
:modelValue="currentCrumbs.checkStatus"
></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 }}
</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>
<div class="h-[162rpx] flex justify-center bg-[#FFFFFF]">
<div class="mt-[14rpx] btnBox">
<tm-button
color="#46299D"
disabled="true"
disabledColor="#E6E6E6"
:margin="[0]"
:shadow="0"
:width="426"
:height="76"
size="large"
label="确定"
>
</tm-button>
</div>
</div>
</div>
</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,
onChoosenDeps,
} = useGroupTypeStore();
const searchVal = ref("");
const crumbsContainer = ref(null);
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,
};
}
return crumbs.value[crumbsIndex.value];
}
return {}
});
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;
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 = "checked";
} else if (someChecked) {
parent.checkStatus = "halfChecked";
} else {
parent.checkStatus = "noChecked";
}
updateParentStatus(parent);
};
// 更新当前节点及其所有子节点的状态
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 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";
}
if (searchVal.value && searchVal.value !== "") {
currentCrumbs.value.sons.forEach((item) => {
const itemT = findNodeById(depTreeMyList.value[0], item.ID)
if (!itemT) return;
checkItemChange(itemT, statusT);
});
} else {
if (crumbs.value[crumbsIndex.value] && crumbs.value[crumbsIndex.value].sons?.length) {
const parent = findParentNode(depTreeMyList.value[0], crumbs.value[crumbsIndex.value].sons[0].ID);
if (!parent) return;
checkItemChange(parent, statusT ==='checked' ? "checked":"noChecked");
}
}
};
watch(() => depTreeMyList.value, (newValue, oldValue) => {
console.log("depTreeMyList", newValue);
}, { deep: true });
watch(() => searchVal.value, (newValue, oldValue) => {
console.log("searchVal", newValue);
});
const init = async () => {
crumbsIndex.value = 0;
await getDepsTreeMy();
crumbs.value = depTreeMyList.value.length ? [depTreeMyList.value[0]] : [];
};
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: #7c7c7c;
opacity: 0.6;
}
.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 */
}
</style>