新增自定义头像通用组件;进行发起群聊、选择部门页面部分重构

This commit is contained in:
wangyifeng 2025-01-24 17:01:50 +08:00
parent 8704691821
commit 2e3b0b994b
18 changed files with 540 additions and 553 deletions

View File

@ -1,29 +1,94 @@
<script setup>
import TmImage from "@/uni_modules/tmui/components/tm-image/tm-image.vue";
import {useAuth} from "@/store/auth";
import { useClockIn } from "@/store/clockIn/index.js";
const {userInfo}=useAuth()
const {workingTimeInfoData,actionTypeData} = useClockIn()
</script>
<template>
<div class="flex-shrink-0 pl-[16rpx] pr-[40rpx] flex items-center rounded-[8rpx] w-[686rpx] h-[154rpx] bg-white">
<div class="rounded-full overflow-hidden w-[96rpx] h-[96rpx]">
<tm-image preview :width="96" :height="96" :src="userInfo.Avatar"></tm-image>
</div>
<div class="ml-[20rpx]">
<div class="flex items-center">
<div class="text-[32rpx] text-black">{{ userInfo.NickName }}</div>
<div class="mx-[14rpx] h-[30rpx] w-[1rpx] bg-[#F7F7F7]"></div>
<div class="w-[40rpx] h-[40rpx]">
<img v-if="actionTypeData.isWorkDay ===1" class="w-[40rpx] h-[40rpx]" src="@/static/image/clockIn/zu3275@3x.png" alt="">
<img v-else class="w-[40rpx] h-[40rpx]" src="@/static/image/clockIn/rest3275@2x.png" alt="">
</div>
</div>
<div class="mt-[5rpx] flex">
<div class="text-[24rpx] text-[#999999]">{{ workingTimeInfoData.WorkTimeTemplateName }}</div>
<div class="text-[#46299D] text-[24rpx]">考勤规则</div>
</div>
</div>
<slot name="right"></slot>
<div class="avatar-module" :style="customStyle">
<img :src="avatar" v-if="avatar" />
<span v-else :style="customTextStyle">{{ text_avatar }}</span>
</div>
</template>
<script setup>
//
import groupNormal from '@/static/image/chatList/groupNormal.png'
import groupDepartment from '@/static/image/chatList/groupDepartment.png'
import groupProject from '@/static/image/chatList/groupProject.png'
import groupCompany from '@/static/image/chatList/groupCompany.png'
import { computed, defineProps } from 'vue'
const props = defineProps({
mode: {
//1=2=
type: Number,
default: 0,
},
avatar: {
//
type: String,
default: '',
},
userName: {
//
type: String,
default: '',
},
groupType: {
//1=2=3=4=/
type: Number,
default: 0,
},
customStyle: {
//
type: Object,
default() {
return {}
},
},
customTextStyle: {
//
type: Object,
default() {
return {}
},
},
})
//
const avatar = computed(() => {
let avatar_img = props?.avatar
if (!avatar_img) {
if (props?.mode === 1) {
} else if (props?.mode === 2) {
if (props?.groupType === 1) {
avatar_img = groupNormal
} else if (props?.groupType === 2) {
avatar_img = groupDepartment
} else if (props?.groupType === 3) {
avatar_img = groupProject
} else if (props?.groupType === 4) {
avatar_img = groupCompany
}
}
}
return avatar_img
})
//
const text_avatar = computed(() => {
return props?.userName.length >= 2
? props?.userName.slice(-2)
: props?.userName
})
</script>
<style lang="scss" scoped>
.avatar-module {
border-radius: 50%;
overflow: hidden;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
background: linear-gradient(to right, #674bbc, #46299d);
flex-shrink: 0;
img {
width: 100%;
height: 100%;
}
}
</style>

View File

@ -44,22 +44,26 @@ const clickBtn = () => {
justify-content: center;
.custom-sub-btn-class {
background-color: #eee9f8;
padding: 18rpx 185rpx;
padding: 18rpx 0;
border-radius: 8rpx;
box-shadow: 0 6px 12px 2px rgba(188, 188, 188, 0.08);
font-size: 28rpx;
font-weight: 500;
line-height: 40rpx;
color: $theme-primary;
width: 426rpx;
height: 76rpx;
}
.custom-btn-class {
background-color: $theme-primary;
padding: 18rpx 185rpx;
padding: 18rpx 0;
border-radius: 8rpx;
box-shadow: 0 6px 12px 2px rgba(188, 188, 188, 0.08);
font-size: 28rpx;
font-weight: 500;
line-height: 40rpx;
width: 426rpx;
height: 76rpx;
}
}
.custom-btn-bottom {

View File

@ -3,9 +3,16 @@
:hideBack="props.hideBack"
hideHome
:title="props.title"
:shadow="0"
:shadow="props.shadowNum"
:fontSize="34"
/>
>
<template #left>
<slot name="left"></slot>
</template>
<template #right>
<slot name="right"></slot>
</template>
</tm-navbar>
</template>
<script setup>
import tmNavbar from '@/uni_modules/tmui/components/tm-navbar/tm-navbar.vue'
@ -22,6 +29,11 @@ const props = defineProps({
type: Boolean,
default: false,
},
shadowNum: {
//
type: Number,
default: 1,
},
})
</script>

View File

@ -22,9 +22,9 @@
<img v-if="memberItem.avatar" :src="memberItem.avatar" />
<span v-if="!memberItem.avatar" class="text-[24rpx] font-bold">
{{
memberItem.nickname.length >= 2
? memberItem.nickname.slice(-2)
: memberItem.nickname
(memberItem.nickname || memberItem.nickName).length >= 2
? (memberItem.nickname || memberItem.nickName).slice(-2)
: memberItem.nickname || memberItem.nickName
}}
</span>
</div>
@ -38,7 +38,7 @@
</div>
<div class="group-member-name">
<span class="text-[24rpx] font-regular">
{{ memberItem.nickname }}
{{ memberItem.nickname || memberItem.nickName }}
</span>
</div>
</div>
@ -86,10 +86,11 @@ const props = defineProps({
//
const toUserDetailPage = (userItem) => {
console.log(userItem.erp_user_id)
console.log(userItem)
uni.navigateTo({
url:
'/pages/dialog/dialogDetail/userDetail?erpUserId=' + userItem.erp_user_id,
'/pages/dialog/dialogDetail/userDetail?erpUserId=' +
(userItem.erp_user_id || userItem.ID),
})
}
@ -103,7 +104,8 @@ const groupAddMembers = () => {
//
const groupRemoveMembers = () => {
uni.navigateTo({
url: '/pages/chatSettings/groupManage/selectMembers?manageType=removeMembers',
url:
'/pages/chatSettings/groupManage/selectMembers?manageType=removeMembers',
})
}
</script>

View File

@ -3,13 +3,7 @@
<div class="root">
<ZPaging ref="zPaging" :show-scrollbar="false">
<template #top>
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
<div class="navBar-title flex flex-col items-center justify-center">
<span class="text-[34rpx] font-medium">
{{ $t('chat.settings.editAvatar') }}
</span>
</div>
</tm-navbar>
<customNavbar :title="$t('chat.settings.editAvatar')"></customNavbar>
</template>
<div class="edit-group-info">
<div class="group-avatar">

View File

@ -3,13 +3,9 @@
<div class="root">
<ZPaging ref="zPaging" :show-scrollbar="false">
<template #top>
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
<div class="navBar-title flex flex-col items-center justify-center">
<span class="text-[34rpx] font-medium">
{{ $t('chat.settings.editGroupName') }}
</span>
</div>
</tm-navbar>
<customNavbar
:title="$t('chat.settings.editGroupName')"
></customNavbar>
</template>
<div class="edit-group-info">
<div class="group-avatar">

View File

@ -3,13 +3,7 @@
<div class="root">
<ZPaging ref="zPaging" :show-scrollbar="false">
<template #top>
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
<div class="navBar-title flex flex-col items-center justify-center">
<span class="text-[34rpx] font-medium">
{{ $t('chat.settings.groupAdmin') }}
</span>
</div>
</tm-navbar>
<customNavbar :title="$t('chat.settings.groupAdmin')"></customNavbar>
</template>
<div class="manage-group-admin">
<span class="manage-group-admin-title text-[28rpx] font-regular">

View File

@ -11,13 +11,7 @@
:loading-more-enabled="false"
>
<template #top>
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
<div class="navBar-title flex flex-col items-center justify-center">
<span class="text-[34rpx] font-medium">
{{ $t('chat.settings.groupMember') }}
</span>
</div>
</tm-navbar>
<customNavbar :title="$t('chat.settings.groupMember')"></customNavbar>
</template>
<div class="group-members-list">
<groupMemberList

View File

@ -3,13 +3,7 @@
<div class="root">
<ZPaging ref="zPaging" :show-scrollbar="false">
<template #top>
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
<div class="navBar-title flex flex-col items-center justify-center">
<span class="text-[34rpx] font-medium">
{{ $t('chat.settings.groupGag') }}
</span>
</div>
</tm-navbar>
<customNavbar :title="$t('chat.settings.groupGag')"></customNavbar>
</template>
<div class="manage-group-silence">
<span class="manage-group-silence-title text-[28rpx] font-regular">

View File

@ -3,11 +3,9 @@
<div class="root">
<ZPaging ref="zPaging" :show-scrollbar="false">
<template #top>
<tm-navbar
<customNavbar
:hideBack="state.editMode === 3 ? false : true"
hideHome
title=""
:leftWidth="220"
:title="$t('chat.settings.groupNotice')"
>
<template #left v-if="state.editMode !== 3">
<div class="nav-bar-cancel-btn">
@ -16,11 +14,6 @@
</span>
</div>
</template>
<div class="navBar-title flex flex-col items-center justify-center">
<span class="text-[34rpx] font-medium">
{{ $t('chat.settings.groupNotice') }}
</span>
</div>
<template #right>
<div
v-if="state.editMode !== 3"
@ -42,7 +35,7 @@
</span>
</div>
</template>
</tm-navbar>
</customNavbar>
</template>
<div class="notice-text-area">
<div class="notice-view-area">

View File

@ -11,40 +11,7 @@
@scroll="onScroll"
>
<template #top>
<tm-navbar
:hideBack="false"
hideHome
title=""
:leftWidth="220"
id="topArea"
>
<div class="navBar-title flex flex-col items-center justify-center">
<span
class="text-[34rpx] font-medium"
v-if="state.manageType === 'silence'"
>
{{ $t('chat.manage.addSilenceMember') }}
</span>
<span
class="text-[34rpx] font-medium"
v-if="state.manageType === 'admin'"
>
{{ $t('chat.manage.addAdmin') }}
</span>
<span
class="text-[34rpx] font-medium"
v-if="state.manageType === 'searchRecord'"
>
{{ $t('search.condition.member') }}
</span>
<span
class="text-[34rpx] font-medium"
v-if="state.manageType === 'removeMembers'"
>
{{ $t('select.member.remove') }}
</span>
</div>
</tm-navbar>
<customNavbar :title="pageTitle" id="topArea"></customNavbar>
</template>
<div class="select-members">
<div
@ -229,6 +196,8 @@ import {
ServeRemoveMembersGroup,
} from '@/api/group/index.js'
import { useDialogueStore, useGroupStore, useGroupTypeStore } from '@/store'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const zPaging = ref()
useZPaging(zPaging)
@ -325,6 +294,21 @@ onMounted(() => {
})
})
//
const pageTitle = computed(() => {
let page_title = ''
if (state.manageType === 'silence') {
page_title = t('chat.manage.addSilenceMember')
} else if (state.manageType === 'admin') {
page_title = t('chat.manage.addAdmin')
} else if (state.manageType === 'searchRecord') {
page_title = t('search.condition.member')
} else if (state.manageType === 'removeMembers') {
page_title = t('select.member.remove')
}
return page_title
})
//
const handleIntersection = (entries) => {
if (state.isAssign) {

View File

@ -3,13 +3,7 @@
<div class="root">
<ZPaging ref="zPaging" :show-scrollbar="false">
<template #top>
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
<div class="navBar-title flex flex-col items-center justify-center">
<span class="text-[34rpx] font-medium">
{{ $t('index.chat.settings') }}
</span>
</div>
</tm-navbar>
<customNavbar :title="$t('index.chat.settings')"></customNavbar>
</template>
<div class="chat-settings">
<div class="chat-group-base-infos chat-settings-card">

View File

@ -1,12 +1,11 @@
<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="choose-deps-page">
<zPaging ref="zPaging" :show-scrollbar="false">
<template #top>
<customNavbar :title="$t('pageTitle.select.department')"></customNavbar>
</template>
<div class="choose-deps">
<div class="w-full pl-[32rpx] pr-[32rpx] overflow-y-auto">
<div class="pl-[16rpx] pr-[16rpx] pt-[22rpx] pb-[24rpx] bg-[#FFFFFF]">
<tm-input
placeholder="请输入…"
@ -66,9 +65,7 @@
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 class="flex items-center">
<div>
<checkBox
:disabled="!item?.sons?.length"
@ -80,14 +77,19 @@
{{ item.name }}
</div>
</div>
<div v-if="item.sons?.length" class="flex items-center mr-[32rpx]">
<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"
:src="
item.checkStatus !== 'checked' ? downDep : downDepDis
"
></tm-image>
</div>
<div
@ -105,18 +107,29 @@
</div>
</div>
</div>
</div>
<template #bottom>
<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
@click="openDrawer"
class="flex items-center text-[28rpx] leading-[60rpx] text-[#000000] font-bold"
>
<div>已选择部门数</div>
<div>{{ allCheckedList.length }}</div>
<div class="ml-[28rpx]">
<tm-icon :fontSize="24" color="#46299D" name="tmicon-angle-up"></tm-icon>
<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">
{{ allCheckedList.map(v=>v.name).toString() }}
<div
class="text-[24rpx] leading-[24rpx] text-[#7A58DE] w-[280rpx] truncate"
>
{{ allCheckedList.map((v) => v.name).toString() }}
</div>
</div>
<div class="btnBox">
@ -131,9 +144,7 @@
:height="76"
size="large"
label="确定"
>
</tm-button>
</div>
></tm-button>
</div>
</div>
</div>
@ -144,15 +155,19 @@
: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 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"
@click="() => (showWin = false)"
>
确定
</div>
@ -168,7 +183,18 @@
>
<div class="text-[28rpx] ml-[10rpx]">{{ item.name }}</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>
<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>
@ -176,18 +202,21 @@
</div>
</div>
</tm-drawer>
</template>
</zPaging>
</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 zPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
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 {
@ -197,201 +226,204 @@ const {
crumbs,
crumbsIndex,
depCheckedKeys,
} = useGroupTypeStore();
} = useGroupTypeStore()
const userStore = useUserStore()
const searchVal = ref("");
const crumbsContainer = ref(null);
const showWin = ref(false);
const searchVal = ref('')
const crumbsContainer = ref(null)
const showWin = ref(false)
const getAllCheckedNodes = (node, checkedNodes = []) => {
if (node.checkStatus === 'checked') {
checkedNodes.push(node);
checkedNodes.push(node)
}
if (node.sons && Array.isArray(node.sons)) {
node.sons.forEach(son => getAllCheckedNodes(son, checkedNodes));
node.sons.forEach((son) => getAllCheckedNodes(son, checkedNodes))
}
return checkedNodes
}
return checkedNodes;
};
const userDepIds = computed(() => {
return userStore.deps.map(v=>v.dept_id);
});
return userStore.deps.map((v) => v.dept_id)
})
const allCheckedList = computed(() => {
const checkedNodes = [];
depTreeMyList.value.forEach(node => getAllCheckedNodes(node, checkedNodes));
console.log("checkedNodes", checkedNodes);
const checkedNodes = []
depTreeMyList.value.forEach((node) => getAllCheckedNodes(node, checkedNodes))
console.log('checkedNodes', checkedNodes)
return checkedNodes;
return checkedNodes
})
const currentCrumbs = computed(() => {
if (crumbs.value[crumbsIndex.value]) {
if (searchVal.value && searchVal.value !== "") {
if (searchVal.value && searchVal.value !== '') {
let filterSons = crumbs.value[crumbsIndex.value].sons.filter((item) =>
item.name.includes(searchVal.value)
);
item.name.includes(searchVal.value),
)
return {
...crumbs.value[crumbsIndex.value],
sons: filterSons,
};
}
console.log("allCheckedList", crumbs.value[crumbsIndex.value]);
return crumbs.value[crumbsIndex.value];
}
console.log('allCheckedList', crumbs.value[crumbsIndex.value])
return crumbs.value[crumbsIndex.value]
}
return {}
});
})
const allCheckStatus = computed(() => {
if (!currentCrumbs.value.sons) {
return "noChecked";
return 'noChecked'
}
const allChecked = currentCrumbs.value.sons.every((son) => son.checkStatus === "checked");
const allChecked = currentCrumbs.value.sons.every(
(son) => son.checkStatus === 'checked',
)
const someChecked = currentCrumbs.value.sons.some(
(son) =>
son.checkStatus === "checked" || son.checkStatus === "halfChecked"
);
(son) => son.checkStatus === 'checked' || son.checkStatus === 'halfChecked',
)
if (allChecked) {
return "checked";
return 'checked'
} else if (someChecked) {
return "halfChecked";
return 'halfChecked'
} else {
return "noChecked";
return 'noChecked'
}
})
const findNodeById = (node, targetId) => {
if (node.ID === targetId) {
return node;
return node
}
if (node.sons && Array.isArray(node.sons)) {
for (const son of node.sons) {
const found = findNodeById(son, targetId);
const found = findNodeById(son, targetId)
if (found) {
return found;
return found
}
}
}
return null;
};
return null
}
const findParentNode = (node, targetId) => {
if (!node.sons || !Array.isArray(node.sons)) return null;
if (!node.sons || !Array.isArray(node.sons)) return null
for (const son of node.sons) {
if (son.ID === targetId) {
return node;
return node
}
const parent = findParentNode(son, targetId);
const parent = findParentNode(son, targetId)
if (parent) {
return parent;
return parent
}
}
return null;
};
return null
}
//
const updateParentStatus = (node) => {
const parent = findParentNode(depTreeMyList.value[0], node.ID);
if (!parent) return;
if (parent.checkStatus !== "checked"){
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");
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"
);
son.checkStatus === 'checked' || son.checkStatus === 'halfChecked',
)
if (allChecked) {
parent.checkStatus = "halfChecked";
parent.checkStatus = 'halfChecked'
} else if (someChecked) {
parent.checkStatus = "halfChecked";
parent.checkStatus = 'halfChecked'
} else {
parent.checkStatus = "noChecked";
parent.checkStatus = 'noChecked'
}
}
updateParentStatus(parent);
};
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 (!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';
node.checkStatus = 'halfChecked'
} else if (someChecked) {
node.checkStatus = 'halfChecked';
node.checkStatus = 'halfChecked'
} else {
node.checkStatus = 'noChecked';
node.checkStatus = 'noChecked'
}
}
};
//
const updateCheckStatus = (node, status) => {
node.checkStatus = status;
node.checkStatus = status
if (node.sons && Array.isArray(node.sons) && node.sons.length > 0) {
node.sons.forEach((son) => updateCheckStatus(son, status));
node.sons.forEach((son) => updateCheckStatus(son, status))
}
}
};
const checkItemChange = (item, val) => {
//
updateCheckStatus(item, val);
updateCheckStatus(item, val)
//
updateParentStatus(item);
};
updateParentStatus(item)
}
const deleteNode = (item) => {
const treeNode = findNodeById(depTreeMyList.value[0], item.ID);
if (!treeNode) return;
treeNode.checkStatus = "noChecked";
updateNodeStatus(treeNode);
updateParentStatus(treeNode);
};
const treeNode = findNodeById(depTreeMyList.value[0], item.ID)
if (!treeNode) return
treeNode.checkStatus = 'noChecked'
updateNodeStatus(treeNode)
updateParentStatus(treeNode)
}
const toNextLevel = async (item) => {
if (item.checkStatus !== "checked") {
crumbs.value.push(item);
crumbsIndex.value++;
await nextTick();
if (item.checkStatus !== 'checked') {
crumbs.value.push(item)
crumbsIndex.value++
await nextTick()
if (crumbsContainer.value) {
crumbsContainer.value.scrollLeft = crumbsContainer.value.scrollWidth;
crumbsContainer.value.scrollLeft = crumbsContainer.value.scrollWidth
}
}
}
};
const handleCrumbsClick = (index) => {
crumbsIndex.value = index;
crumbs.value = crumbs.value.slice(0, index + 1);
};
crumbsIndex.value = index
crumbs.value = crumbs.value.slice(0, index + 1)
}
const allCheck = (status) => {
let statusT = 'noChecked';
if (status === "checked") {
statusT = "noChecked";
let statusT = 'noChecked'
if (status === 'checked') {
statusT = 'noChecked'
} else {
statusT = "checked";
statusT = 'checked'
}
currentCrumbs.value.sons.forEach((item) => {
const itemT = findNodeById(depTreeMyList.value[0], item.ID)
if (!itemT) return;
checkItemChange(itemT, statusT);
});
};
if (!itemT) return
checkItemChange(itemT, statusT)
})
}
const openDrawer = () => {
showWin.value = true;
showWin.value = true
if (allCheckedList.length > 0) {
}
};
}
// watch(() => depTreeMyList.value, (newValue, oldValue) => {
// console.log("depTreeMyList", newValue);
@ -404,54 +436,48 @@ const openDrawer = () => {
const handleConfirm = () => {
depCheckedKeys.value = lodash.cloneDeep(allCheckedList.value)
console.log("depCheckedKeys", depCheckedKeys.value);
console.log('depCheckedKeys', depCheckedKeys.value)
uni.navigateBack();
uni.navigateBack()
}
const initCheckedKeys = () => {
depCheckedKeys.value.forEach((item) => {
const node = findNodeById(depTreeMyList.value[0], item.ID);
const node = findNodeById(depTreeMyList.value[0], item.ID)
if (node) {
node.checkStatus = "checked";
updateParentStatus(node);
node.checkStatus = 'checked'
updateParentStatus(node)
}
})
}
});
};
const init = async () => {
crumbsIndex.value = 0;
await getDepsTreeMy();
crumbs.value = depTreeMyList.value.length ? [depTreeMyList.value[0]] : [];
initCheckedKeys();
};
crumbsIndex.value = 0
await getDepsTreeMy()
crumbs.value = depTreeMyList.value.length ? [depTreeMyList.value[0]] : []
initCheckedKeys()
}
onMounted(() => {
init();
});
init()
})
</script>
<style scoped lang="scss">
uni-page-body,
page {
::v-deep .zp-paging-container-content {
height: 100%;
display: flex;
}
.outer-layer {
overflow-y: auto;
.choose-deps-page {
.choose-deps {
flex: 1;
background-image: url("@/static/image/clockIn/z3280@3x.png");
display: flex;
flex-direction: column;
background-image: url('@/static/image/clockIn/z3280@3x.png');
background-size: cover;
padding-bottom: 0;
display: flex;
flex-direction: column;
padding: 20rpx 0;
}
.root {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
padding-top: 18rpx;
overflow: hidden;
}
.divider {
height: 1rpx;
background-color: #707070;
@ -478,22 +504,22 @@ page {
background-repeat: no-repeat;
border-radius: 12rpx;
&.firstPanel {
background-image: url("@/static/image/chatList/zu6033@2x.png");
background-image: url('@/static/image/chatList/zu6033@2x.png');
}
&.secondPanel {
background-image: url("@/static/image/chatList/zu6031@2x.png");
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");
background-image: url('@/static/image/chatList/zu6032@2x.png');
}
&.activePanel {
box-shadow: 0 0 0 3rpx #46299d;
}
}
.btnBox {
:deep(uni-button[disabled="true"]) {
:deep(uni-button[disabled='true']) {
color: #bebebe !important;
}
}
@ -508,12 +534,12 @@ page {
.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;
border: 1rpx solid #d6d6d8 !important;
background-color: #ffffff !important;
&[disabled='true'] {
color: #bebebe !important;
border: 1rpx solid #e6e6e6 !important;
background-color: #e6e6e6 !important;
}
}
}

View File

@ -8,12 +8,12 @@
<div class="group-avatar flex items-center justify-center">
<div class="avatar-placeholder" v-if="groupActiveIndex === -1"></div>
<div v-else>
<tm-image
:width="192"
:height="192"
:round="24"
:src="avatarImg"
></tm-image>
<avatarModule
:mode="2"
:avatar="avatarImg"
:groupType="groupType"
:customStyle="{ width: '192rpx', height: '192rpx' }"
></avatarModule>
</div>
</div>
<div class="input-group flex items-center justify-between">
@ -60,7 +60,10 @@
</div>
</div>
</div>
<div v-if="depCheckedKeys.length" class="mt-[32rpx]">
<div
v-if="depCheckedKeys.length && groupActiveIndex === 1"
class="mt-[32rpx]"
>
<div
v-for="(item, index) in depCheckedKeys"
class="text-[#747474] text-[28rpx] leading-[40rpx] font-bold"
@ -99,7 +102,7 @@
v-if="!groupAdmins.length"
class="text-[#B4B4B4] text-[28rpx] font-bold mr-[32rpx]"
>
全部({{ 0 }})
全部({{ allChooseMembers?.length || 0 }})
</div>
<tm-icon
:font-size="22"
@ -109,29 +112,14 @@
</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>
<groupMemberList
:groupType="3"
:is_manager="true"
:memberList="allChooseMembers"
:memberListsLimit="
groupActiveIndex == 0 || groupActiveIndex == 2 ? 13 : 15
"
></groupMemberList>
</div>
<div
@ -197,6 +185,8 @@
<script setup>
import zPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import customBtn from '@/components/custom-btn/custom-btn.vue'
import groupMemberList from '../chatSettings/components/groupMembersList.vue'
import avatarModule from '@/components/avatar-module/index.vue'
import { ref, watch, computed } from 'vue'
import { onShow, onLoad } from '@dcloudio/uni-app'
@ -205,9 +195,6 @@ import { useAuth } from '@/store/auth'
import { useTalkStore, useUserStore } from '@/store'
import addCircle from '@/static/image/chatList/addCircle.png'
import cahtPopover from '@/static/image/chatList/cahtPopover.png'
import groupDepartment from '@/static/image/chatList/groupDepartment.png'
import groupProject from '@/static/image/chatList/groupProject.png'
import groupNormal from '@/static/image/chatList/groupNormal.png'
import { ServeCreateGroup } from '@/api/group/index'
import { useGroupTypeStore } from '@/store/groupType'
@ -227,24 +214,26 @@ const { userInfo } = useAuth()
const groupChatType = ref('')
const depsNoExpanded = ref(true)
const avatarImg = computed(() => {
let srcT = ''
//
const groupType = computed(() => {
let group_type = ''
switch (groupActiveIndex.value) {
case 0:
srcT = groupNormal
group_type = 1
break
case 1:
srcT = groupDepartment
group_type = 2
break
case 2:
srcT = groupProject
group_type = 3
break
default:
srcT = groupNormal
group_type = ''
}
return srcT
return group_type
})
//
const chooseGroupType = () => {
uni.navigateTo({
url: '/pages/chooseGroupType/index',
@ -263,8 +252,9 @@ const chooseMembers = () => {
})
}
//
const handleConfirm = async () => {
console.log(allChooseMembers.value)
// console.log(allChooseMembers.value)
let erp_ids = ''
if (allChooseMembers?.value?.length > 0) {
allChooseMembers?.value?.forEach((ele) => {
@ -316,6 +306,7 @@ const handleConfirm = async () => {
}
}
//
const confirmBtnStatus = computed(() => {
let disabledT = false
console.log(groupActiveIndex.value !== -1)
@ -328,9 +319,6 @@ const confirmBtnStatus = computed(() => {
}
switch (groupActiveIndex.value) {
case 0:
if (allChooseMembers?.value?.length < 3) {
return true
}
break
case 1:
if (!depCheckedKeys.value.length) {
@ -341,9 +329,6 @@ const confirmBtnStatus = computed(() => {
}
break
case 2:
if (allChooseMembers?.value?.length < 3) {
return true
}
break
default:
break
@ -364,8 +349,9 @@ onShow(() => {
.create-group-chat {
background-image: url('@/static/image/clockIn/z3280@3x.png');
background-size: cover;
background-position: center bottom;
width: 100%;
padding: 0 32rpx;
padding: 0 32rpx 20rpx;
.group-avatar {
padding: 60rpx 0;
.avatar-placeholder {
@ -402,9 +388,4 @@ onShow(() => {
display: flex;
align-items: center;
}
.btnBox {
:deep(uni-button[disabled='true']) {
color: #bebebe !important;
}
}
</style>

View File

@ -3,13 +3,7 @@
<div class="root">
<ZPaging ref="zPaging" :show-scrollbar="false">
<template #top>
<tm-navbar
class="tmNavBar"
:hideBack="false"
hideHome
title=""
:leftWidth="220"
></tm-navbar>
<customNavbar class="tmNavBar"></customNavbar>
</template>
<div class="user-detail-info">
<div class="user-info-head user-info-card">

View File

@ -9,15 +9,23 @@
: ''
"
>
<div
class="avatar-img"
:class="props?.conditionType ? 'avatar-img-condition' : ''"
>
<img v-if="avatarImg !== 'textImg'" :src="avatarImg" />
<span v-if="avatarImg === 'textImg'" class="text-[32rpx] font-bold">
{{ imgText }}
</span>
</div>
<avatarModule
:mode="props.searchItem?.group_type === 0 ? 1 : 2"
:avatar="avatarImg"
:userName="resultName"
:groupType="props.searchItem?.group_type"
:customStyle="{
width: props?.conditionType ? '64rpx' : '96rpx',
height: props?.conditionType ? '64rpx' : '96rpx',
margin: props?.conditionType ? '0 18rpx 0 0' : '0 20rpx 0 0',
}"
:customTextStyle="{
fontSize: props?.conditionType ? '20rpx' : '32rpx',
fontWeight: 'bold',
color: '#fff',
lineHeight: '44rpx',
}"
></avatarModule>
<div class="result-info">
<div
class="info-name"
@ -75,10 +83,7 @@
</div>
</template>
<script setup>
import groupDepartment from '@/static/image/chatList/groupDepartment.png'
import groupProject from '@/static/image/chatList/groupProject.png'
import groupNormal from '@/static/image/chatList/groupNormal.png'
import groupCompany from '@/static/image/chatList/groupCompany.png'
import avatarModule from '@/components/avatar-module/index.vue'
import {
ref,
watch,
@ -167,14 +172,8 @@ const getKeyValue = (keys) => {
//
const avatarImg = computed(() => {
let avatar = getKeyValue(keyMapping[props.searchResultKey]?.avatar)
if (!avatar) {
avatar = groupTypeMapping[props.searchItem?.group_type]?.defaultImg
}
if (props?.conditionType) {
avatar = props.searchItem.avatar
if (!avatar) {
avatar = groupTypeMapping[0]?.defaultImg
}
}
return avatar
})
@ -195,25 +194,20 @@ const imgText = computed(() => {
// -groupType
const groupTypeMapping = {
0: {
defaultImg: 'textImg',
},
1: {
defaultImg: groupNormal,
},
2: {
result_type: t('index.mine.department'),
result_type_color: '#377EC6',
defaultImg: groupDepartment,
},
3: {
result_type: t('index.mine.project'),
result_type_color: '#C1681C',
defaultImg: groupProject,
},
4: {
result_type: t('index.type.company'),
result_type_color: '#7A58DE',
defaultImg: groupCompany,
},
}
//
@ -262,35 +256,6 @@ const resultDetail = computed(() => {
padding: 22rpx 0 24rpx;
border-bottom: 1px solid $theme-border-color;
.avatar-img {
width: 96rpx;
height: 96rpx;
margin: 0 20rpx 0 0;
border-radius: 50%;
overflow: hidden;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
background: linear-gradient(to right, #674bbc, #46299d);
flex-shrink: 0;
img {
width: 100%;
height: 100%;
}
span {
color: #fff;
line-height: 44rpx;
}
}
.avatar-img-condition {
width: 64rpx;
height: 64rpx;
margin: 0 18rpx 0 0;
span {
font-size: 20rpx;
}
}
.result-info {
width: 100%;
.info-name {

View File

@ -11,13 +11,7 @@
:inside-more="true"
>
<template #top v-if="state.showPageTitle">
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
<div class="navBar-title flex flex-col items-center justify-center">
<span class="text-[34rpx] font-medium">
{{ state.pageTitle }}
</span>
</div>
</tm-navbar>
<customNavbar :title="state.pageTitle"></customNavbar>
</template>
<div v-if="state.condition === 'date'" class="search-by-date">
<tm-time-picker

View File

@ -138,5 +138,6 @@
"select.member.remove": "选择要移除的人",
"select.member.num": "已选择",
"statistic.unit.person": "人",
"pageTitle.create.group": "发起群聊"
"pageTitle.create.group": "发起群聊",
"pageTitle.select.department": "选择部门"
}