新增华为审核投诉功能 修改群聊低于三人按钮置灰逻辑 修改移出群自己在列表最上方并且不在列表出现问题
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run

This commit is contained in:
liwenhao 2025-04-11 09:51:06 +08:00
parent 2953d50e4b
commit a5d9009910
9 changed files with 7995 additions and 9970 deletions

2
auto-imports.d.ts vendored
View File

@ -70,6 +70,6 @@ declare global {
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue')
}

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,7 @@
"^tm-(.*)": "@/tmui/components/tm-$1/tm-$1.vue"
}
},
"pages": [
{
"pages": [{
"path": "pages/index/index",
"type": "page",
"style": {
@ -186,6 +185,14 @@
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/complaintReport/index",
"type": "page",
"style": {
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
}
],
"globalStyle": {

View File

@ -1,140 +1,94 @@
<template>
<div class="select-member-by-alphabet">
<ZPaging
ref="zPaging"
:show-scrollbar="false"
:use-virtual-list="true"
:virtual-list-col="5"
:refresher-enabled="false"
:loading-more-enabled="false"
@scroll="onScroll"
:fixed="false"
:height="props?.selectAreaHeight"
>
<ZPaging ref="zPaging" :show-scrollbar="false" :use-virtual-list="true" :virtual-list-col="5"
:refresher-enabled="false" :loading-more-enabled="false" @scroll="onScroll" :fixed="false"
:height="props?.selectAreaHeight">
<div class="select-members">
<div
class="search-member"
v-if="
<div class="search-member" v-if="
props?.manageType !== 'removeMembers' &&
!(
props?.manageType === 'admin' &&
(groupParams.groupInfo.group_type === 2 ||
groupParams.groupInfo.group_type === 4)
)
"
>
<customInput
:searchText="state.searchText"
@inputSearchText="inputSearchText"
></customInput>
">
<customInput :searchText="state.searchText" @inputSearchText="inputSearchText"></customInput>
</div>
<div
class="member-list"
:style="{
<div v-show="props?.manageType == 'removeMembers'" class="my-self">
<div class="my-self-left">
<image style="width: 72rpx;border-radius: 50%;" :src="mySelfMember.avatar" mode="widthFix"></image>
<div style="padding: 0 20rpx;">{{mySelfMember.nickname}}</div>
<img style="width: 66rpx;" src="@/static/image/chatSettings/is-mine.png" />
</div>
<div class="my-self-right">
{{ $t('group.identify.admin') }}
</div>
</div>
<div class="member-list" :style="{
padding: props?.manageType === 'searchRecord' ? '20rpx 0 0' : '',
}"
>
<div
class="member-list-alphabet-anchor-point"
:style="{
}">
<div class="member-list-alphabet-anchor-point" :style="{
top: props?.manageType === 'mention' ? '90rpx' : '',
}"
>
<div
class="member-list-alphabet-anchor-point-each"
v-for="(alphabetItem, alphabetIndex) in state?.alphabet"
:key="alphabetIndex"
:style="{
}">
<div class="member-list-alphabet-anchor-point-each" v-for="(alphabetItem, alphabetIndex) in state?.alphabet"
:key="alphabetIndex" :style="{
margin: state?.alphabet?.length > 17 ? '0' : '',
}"
@click.stop="scrollToView(alphabetItem)"
>
<span
class="text-[32rpx] font-regular"
:style="{
}" @click.stop="scrollToView(alphabetItem)">
<span class="text-[32rpx] font-regular" :style="{
color:
state.currentAlphabet === alphabetItem ? '#7A58DE' : '',
}"
>
}">
{{ alphabetItem }}
</span>
</div>
</div>
<div
class="member-list-alphabet"
v-for="(alphabetItem, alphabetIndex) in state.resultMemberList"
:key="alphabetIndex"
>
<div
class="member-list-alphabet-key"
:style="{
<div class="member-list-alphabet" v-for="(alphabetItem, alphabetIndex) in state.resultMemberList"
:key="alphabetIndex">
<div class="member-list-alphabet-key" :style="{
padding:
props?.manageType === 'searchRecord' ||
props?.manageType === 'removeMembers' ||
props?.manageType === 'mention'
? '10rpx 30rpx'
: '',
}"
v-if="
}" v-if="
alphabetItem?.memberList?.length > 0 &&
alphabetItem?.key !== '0'
"
:id="alphabetItem.key === '#' ? 'special-hash' : alphabetItem.key"
:ref="
" :id="alphabetItem.key === '#' ? 'special-hash' : alphabetItem.key" :ref="
(el) => {
if (el) alphabetElementRefs[alphabetIndex] = el
}
"
>
">
<span class="text-[32rpx] font-regular">
{{ alphabetItem.key }}
</span>
</div>
<div v-if="alphabetItem?.memberList?.length > 0">
<div
class="member-list-each"
v-for="(item, index) in alphabetItem?.memberList"
:key="index"
>
<div class="member-list-each" v-for="(item, index) in alphabetItem?.memberList" :key="index">
<tm-checkbox-group v-model="item.checkArr">
<selectMemberItem
:groupType="groupParams.groupInfo.group_type"
:memberItem="item"
@clickItem="handleClickItem(item)"
:manageType="props?.manageType"
:itemStyle="
<selectMemberItem :groupType="groupParams.groupInfo.group_type" :memberItem="item"
@clickItem="handleClickItem(item)" :manageType="props?.manageType" :itemStyle="
props?.manageType === 'searchRecord' ||
props?.manageType === 'removeMembers' ||
props?.manageType === 'mention'
? 'list'
: 'card'
"
>
">
<template #left v-if="props?.manageType !== 'searchRecord'">
<div
v-if="
<div v-if="
props?.manageType === 'removeMembers' && item?.is_mine
"
>
<tm-checkbox
color="#fff"
:transprent="true"
:border="0"
:disabled="true"
></tm-checkbox>
">
<tm-checkbox color="#fff" :transprent="true" :border="0" :disabled="true"></tm-checkbox>
</div>
<tm-checkbox
v-if="
<tm-checkbox v-if="
!(
props?.manageType === 'removeMembers' &&
item?.is_mine
) && props?.isMulSelect
"
:round="10"
:color="
" :round="10" :color="
item?.checkArr?.length > 0 ? '#46299d' : '#B4B4B4'
"
:outlined="
" :outlined="
item?.checkArr?.length > 0 ||
(props?.manageType === 'silence' &&
item.is_mute === 1) ||
@ -142,16 +96,12 @@
(item.leader === 1 || item.leader === 2))
? false
: true
"
:value="item.id"
:disabled="
" :value="item.id" :disabled="
(props?.manageType === 'silence' &&
item.is_mute === 1) ||
(props?.manageType === 'admin' &&
(item.leader === 1 || item.leader === 2))
"
@change="checkBoxChange"
></tm-checkbox>
" @change="checkBoxChange"></tm-checkbox>
</template>
</selectMemberItem>
</tm-checkbox-group>
@ -164,12 +114,12 @@
</div>
</template>
<script setup>
import customInput from '@/components/custom-input/custom-input.vue'
import selectMemberItem from '../components/select-member-item.vue'
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
import groupAllMember from '@/static/image/chatList/groupAllMember.png'
import {
import customInput from '@/components/custom-input/custom-input.vue'
import selectMemberItem from '../components/select-member-item.vue'
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
import groupAllMember from '@/static/image/chatList/groupAllMember.png'
import {
computed,
onMounted,
reactive,
@ -178,48 +128,52 @@ import {
nextTick,
defineProps,
defineEmits,
} from 'vue'
import {
} from 'vue'
import {
ServeGroupNoSpeak,
ServeEditGroupAdmin,
ServeGroupAssignAdmin,
ServeRemoveMembersGroup,
} from '@/api/group/index.js'
import { useDialogueStore, useGroupStore, useGroupTypeStore } from '@/store'
} from '@/api/group/index.js'
import {
useDialogueStore,
useGroupStore,
useGroupTypeStore
} from '@/store'
const emits = defineEmits([
const emits = defineEmits([
'updateSelectedMembersNum',
'getSelectResult',
'getMentionSelectLists',
])
])
const zPaging = ref()
useZPaging(zPaging)
const zPaging = ref()
useZPaging(zPaging)
const groupStore = useGroupStore()
const groupParams = reactive({
const groupStore = useGroupStore()
const groupParams = reactive({
groupInfo: computed(() => groupStore.groupInfo),
})
})
const groupTypeStore = useGroupTypeStore()
const groupTypeParams = reactive({
const groupTypeStore = useGroupTypeStore()
const groupTypeParams = reactive({
departmentAllPositions: computed(() => groupTypeStore.departmentAllPositions),
})
})
const dialogueStore = useDialogueStore()
const dialogueParams = reactive({
const dialogueStore = useDialogueStore()
const dialogueParams = reactive({
memberList: computed(() => {
const lowerCaseSearchText = state?.searchText.toLowerCase()
return dialogueStore.members.filter((item) =>
state?.searchText
? item.nickname.toLowerCase().includes(lowerCaseSearchText)
: true,
state?.searchText ?
item.nickname.toLowerCase().includes(lowerCaseSearchText) :
true,
)
}),
receiverId: computed(() => dialogueStore.talk.receiver_id),
})
})
const props = defineProps({
const props = defineProps({
manageType: {
//
type: String,
@ -240,42 +194,43 @@ const props = defineProps({
type: Boolean,
default: true,
},
})
})
const state = reactive({
const state = reactive({
searchText: '', //
alphabet: [], //A-Z
currentAlphabet: 'A', //A-Z
resultMemberList: [], //A-Z
isAssign: false, //view
scrollDirection: '', //
})
})
watch(
watch(
() => dialogueParams?.memberList,
(newMemberList) => {
assembleAlphabetMemberList(newMemberList)
}, {
deep: true
},
{ deep: true },
)
)
watch(
watch(
() => groupParams?.groupInfo,
(newGroupInfo) => {
assembleAlphabetMemberList(dialogueParams?.memberList)
}, {
deep: true
},
{ deep: true },
)
)
watch(
watch(
() => props?.isMulSelect,
(newIsMulSelect) => {
if (props?.manageType === 'mention') {
if (!newIsMulSelect) {
state.resultMemberList.unshift({
key: '0',
memberList: [
{
memberList: [{
avatar: groupAllMember,
erp_user_id: 0,
gender: 0,
@ -285,8 +240,7 @@ watch(
nickname: '所有人',
remark: '',
user_id: 0,
},
],
}, ],
})
} else {
if (state.resultMemberList[0].key === '0') {
@ -294,16 +248,18 @@ watch(
}
}
}
}, {
deep: true,
immediate: true
},
{ deep: true, immediate: true },
)
)
//A-Z tag
const alphabetElementRefs = ref([])
//
let observer
//A-Z tag
const alphabetElementRefs = ref([])
//
let observer
onMounted(() => {
onMounted(() => {
if (props?.manageType) {
assembleAlphabetMemberList(dialogueParams?.memberList)
}
@ -329,8 +285,10 @@ onMounted(() => {
observeElement(el, index)
})
}
}, {
immediate: true,
deep: true
},
{ immediate: true, deep: true },
)
if (alphabetElementRefs.value.length > 0) {
alphabetElementRefs.value.forEach((el, index) =>
@ -338,17 +296,17 @@ onMounted(() => {
)
}
})
})
})
//
const observeElement = (el, index) => {
//
const observeElement = (el, index) => {
if (el && observer) {
observer.observe(el)
}
}
}
//
const handleIntersection = (entries) => {
//
const handleIntersection = (entries) => {
if (state.isAssign) {
state.isAssign = false
return
@ -368,16 +326,16 @@ const handleIntersection = (entries) => {
}
}
})
}
}
//
const inputSearchText = (e) => {
//
const inputSearchText = (e) => {
// console.log(e)
state.searchText = e
}
}
//item
const handleClickItem = (item) => {
//item
const handleClickItem = (item) => {
if (
(props?.manageType === 'silence' && item.is_mute === 1) ||
(props?.manageType === 'admin' &&
@ -392,8 +350,7 @@ const handleClickItem = (item) => {
}
if (props?.manageType === 'searchRecord') {
uni.navigateTo({
url:
'/pages/search/searchByCondition/index?condition=member&groupMemberId=' +
url: '/pages/search/searchByCondition/index?condition=member&groupMemberId=' +
item.id,
})
return
@ -417,17 +374,30 @@ const handleClickItem = (item) => {
}
}
})
}
//A-Z
const assembleAlphabetMemberList = async (newMemberList) => {
}
const mySelfMember = ref({})
//A-Z
const assembleAlphabetMemberList = async (newMemberList) => {
if (props?.manageType === 'removeMembers' && Array.isArray(newMemberList)) {
// is_mine true
for (let i = 0; i < newMemberList.length; i++) {
const item = newMemberList[i];
if (item?.is_mine === true) {
mySelfMember.value = item;
newMemberList.splice(i, 1); //
break; //
}
}
}
if (
props?.manageType === 'searchRecord' ||
props?.manageType === 'removeMembers' ||
props?.manageType === 'mention'
) {
const resultMemberList = ref([])
const alphabet = Array.from({ length: 26 }, (_, i) =>
const alphabet = Array.from({
length: 26
}, (_, i) =>
String.fromCharCode(i + 65),
)
let tempAlphabet = []
@ -476,8 +446,7 @@ const assembleAlphabetMemberList = async (newMemberList) => {
if (props?.manageType === 'mention' && !props?.isMulSelect) {
resultMemberList.value.unshift({
key: '0',
memberList: [
{
memberList: [{
avatar: groupAllMember,
erp_user_id: 0,
gender: 0,
@ -487,8 +456,7 @@ const assembleAlphabetMemberList = async (newMemberList) => {
nickname: '所有人',
remark: '',
user_id: 0,
},
],
}, ],
})
}
state.resultMemberList = resultMemberList
@ -514,18 +482,16 @@ const assembleAlphabetMemberList = async (newMemberList) => {
}
getPosiByDep(departmentIdsArr)
} else {
state.resultMemberList = [
{
state.resultMemberList = [{
key: '',
memberList: newMemberList,
},
]
}, ]
}
}
}
}
//
const getPosiByDep = async (departmentIdsArr) => {
//
const getPosiByDep = async (departmentIdsArr) => {
await groupTypeStore.getPositionByDepartment({
IDs: departmentIdsArr,
})
@ -571,38 +537,36 @@ const getPosiByDep = async (departmentIdsArr) => {
if (state?.searchText) {
const lowerCaseSearchText = state?.searchText.toLowerCase()
departmentAllPositions = departmentAllPositions.filter((item) =>
state?.searchText
? item.nickname.toLowerCase().includes(lowerCaseSearchText)
: true,
state?.searchText ?
item.nickname.toLowerCase().includes(lowerCaseSearchText) :
true,
)
}
state.resultMemberList = [
{
state.resultMemberList = [{
key: '',
memberList: departmentAllPositions,
},
]
}
}, ]
}
//view
const scrollToView = (alphabet) => {
//view
const scrollToView = (alphabet) => {
state.currentAlphabet = alphabet
state.isAssign = true
//
const offsetHeight = document.getElementById('topArea')?.clientHeight
? document.getElementById('topArea').clientHeight - 1
: props?.manageType === 'mention'
? 140
: 80
const offsetHeight = document.getElementById('topArea')?.clientHeight ?
document.getElementById('topArea').clientHeight - 1 :
props?.manageType === 'mention' ?
140 :
80
// 使scrollIntoViewById
const targetId = alphabet === '#' ? 'special-hash' : alphabet
zPaging.value?.scrollIntoViewById(targetId, offsetHeight)
}
}
//
const onScroll = (e) => {
//
const onScroll = (e) => {
if (e.detail.deltaY < 0) {
state.scrollDirection = 'down'
} else if (e.detail.deltaY > 0) {
@ -610,19 +574,19 @@ const onScroll = (e) => {
} else {
state.scrollDirection = ''
}
}
}
//
const checkBoxChange = (e) => {
//
const checkBoxChange = (e) => {
if (e) {
emits('updateSelectedMembersNum', 1)
} else {
emits('updateSelectedMembersNum', -1)
}
}
}
//
const confirmSelectMembers = () => {
//
const confirmSelectMembers = () => {
let selectedUserIds = ''
let itemList = dialogueStore.members
let positionInfos = []
@ -669,12 +633,14 @@ const confirmSelectMembers = () => {
}
console.log(params)
const resp = ServeGroupNoSpeak(params)
resp.then(({ code, data }) => {
resp.then(({
code,
data
}) => {
console.log(data)
if (code == 200) {
useDialogueStore().updateGroupMembers()
} else {
}
} else {}
})
resp.catch(() => {})
} else if (props?.manageType === 'admin') {
@ -696,12 +662,14 @@ const confirmSelectMembers = () => {
}
console.log(params)
const resp = ServeGroupAssignAdmin(params)
resp.then(({ code, data }) => {
resp.then(({
code,
data
}) => {
console.log(data)
if (code == 200) {
useDialogueStore().updateGroupMembers()
} else {
}
} else {}
})
resp.catch(() => {})
} else if (
@ -716,12 +684,14 @@ const confirmSelectMembers = () => {
}
console.log(params)
const resp = ServeEditGroupAdmin(params)
resp.then(({ code, data }) => {
resp.then(({
code,
data
}) => {
console.log(data)
if (code == 200) {
groupStore.ServeGroupDetail()
} else {
}
} else {}
})
resp.catch(() => {})
}
@ -733,36 +703,63 @@ const confirmSelectMembers = () => {
}
console.log(params)
const resp = ServeRemoveMembersGroup(params)
resp.then(({ code, data }) => {
resp.then(({
code,
data
}) => {
console.log(data)
if (code == 200) {
// console.error(-selectedUserIds.split(',').length)
emits('updateSelectedMembersNum', -selectedUserIds.split(',').length)
useDialogueStore().updateGroupMembers()
groupStore.ServeGroupDetail()
} else {
}
} else {}
})
resp.catch(() => {})
} else if (props?.manageType === 'mention') {
emits('getSelectResult', selectUserInfos)
}
}
}
}
//
defineExpose({
//
defineExpose({
confirmSelectMembers,
})
})
</script>
<style lang="scss" scoped>
.select-member-by-alphabet {
.my-self {
padding: 10rpx 60rpx;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
.my-self-left {
display: flex;
align-items: center;
margin-left: 8%;
}
.my-self-right {
color: #b4b4b4;
padding: 0.1875rem 0.375rem;
border: #b4b4b4 1px solid;
border-radius: 8rpx;
font-size: 0.875rem;
}
}
.select-member-by-alphabet {
.select-members {
padding: 20rpx 32rpx;
.search-member {
padding: 22rpx 16rpx;
background-color: #fff;
}
.member-list {
.member-list-alphabet-anchor-point {
position: fixed;
@ -773,12 +770,14 @@ defineExpose({
flex-direction: column;
align-items: center;
justify-content: center;
.member-list-alphabet-anchor-point-each {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 0 0 14rpx;
span {
width: 52rpx;
text-align: center;
@ -787,9 +786,11 @@ defineExpose({
}
}
}
.member-list-alphabet {
.member-list-alphabet-key {
background-color: #f3f3f3;
span {
line-height: 44rpx;
color: $theme-text;
@ -798,5 +799,5 @@ defineExpose({
}
}
}
}
}
</style>

View File

@ -6,71 +6,42 @@
<customNavbar :title="$t('index.chat.settings')"></customNavbar>
</template>
<div class="chat-settings">
<div
class="chat-group-base-infos chat-settings-card"
v-if="dialogueParams.type === 2"
>
<div class="chat-group-base-infos chat-settings-card" v-if="dialogueParams.type === 2">
<div class="base-info-avatar" @click="toEditAvatarPage">
<avatarModule
:mode="2"
:avatar="groupParams?.groupInfo?.avatar"
:groupType="groupParams?.groupInfo?.group_type"
:customStyle="{ width: '96rpx', height: '96rpx' }"
></avatarModule>
<avatarModule :mode="2" :avatar="groupParams?.groupInfo?.avatar"
:groupType="groupParams?.groupInfo?.group_type" :customStyle="{ width: '96rpx', height: '96rpx' }">
</avatarModule>
</div>
<div class="base-info">
<div class="base-info-name">
<span class="text-[32rpx] font-medium">{{ groupName }}</span>
<span
class="base-info_num text-[32rpx] font-medium"
v-if="groupNum"
>
<span class="base-info_num text-[32rpx] font-medium" v-if="groupNum">
{{ '' + groupNum + '' }}
</span>
</div>
<div
v-if="groupParams?.groupInfo?.group_type !== 1 && groupType"
class="base-info-tag"
:style="{
<div v-if="groupParams?.groupInfo?.group_type !== 1 && groupType" class="base-info-tag" :style="{
borderColor:
groupTypeMapping[groupParams?.groupInfo?.group_type]
?.result_type_color,
}"
>
<span
class="text-[24rpx] font-medium"
:style="{
}">
<span class="text-[24rpx] font-medium" :style="{
color:
groupTypeMapping[groupParams?.groupInfo?.group_type]
?.result_type_color,
}"
>
}">
{{ groupType }}
</span>
</div>
</div>
<div
class="base-info-edit"
@click="toEditGroupInfoPage"
v-if="groupParams?.groupInfo?.is_manager"
>
<div class="base-info-edit" @click="toEditGroupInfoPage" v-if="groupParams?.groupInfo?.is_manager">
<img src="@/static/image/chatSettings/edit-btn.png" />
</div>
</div>
<div class="chat-group-members chat-group-infos chat-settings-card">
<div
class="chat-group-infos-each"
v-for="(item, index) in state.chatGroupMembers"
:key="index"
>
<settingFormItem
:item="item"
@toManagePage="toManagePage"
></settingFormItem>
<groupMemberList
:groupType="groupParams?.groupInfo?.group_type"
:is_manager="groupParams?.groupInfo?.is_manager"
:memberList="dialogueParams?.memberList"
<div class="chat-group-infos-each" v-for="(item, index) in state.chatGroupMembers" :key="index">
<settingFormItem :item="item" @toManagePage="toManagePage"></settingFormItem>
<groupMemberList :groupType="groupParams?.groupInfo?.group_type"
:is_manager="groupParams?.groupInfo?.is_manager" :memberList="dialogueParams?.memberList"
:memberListsLimit="
groupParams?.groupInfo?.group_type == 1 ||
groupParams?.groupInfo?.group_type == 3
@ -78,21 +49,13 @@
? 13
: 14
: 15
"
></groupMemberList>
"></groupMemberList>
</div>
</div>
<div class="chat-group-infos chat-settings-card">
<div
class="chat-group-infos-each"
v-for="(item, index) in state.chatGroupInfos"
:key="index"
>
<settingFormItem
:item="item"
@toManagePage="toManagePage"
:isManager="groupParams?.groupInfo?.is_manager"
></settingFormItem>
<div class="chat-group-infos-each" v-for="(item, index) in state.chatGroupInfos" :key="index">
<settingFormItem :item="item" @toManagePage="toManagePage"
:isManager="groupParams?.groupInfo?.is_manager"></settingFormItem>
</div>
</div>
<div class="chat-records-search chat-settings-card">
@ -100,92 +63,50 @@
<customInput :disabled="true"></customInput>
</div>
<div class="record-search-types">
<div
class="record-search-types-each"
v-for="(item, index) in state.recordSearchTypeList"
:key="index"
@click="toSearchByConditionPage(index)"
>
<div class="record-search-types-each" v-for="(item, index) in state.recordSearchTypeList" :key="index"
@click="toSearchByConditionPage(index)">
<img class="record-search-types-icon" :src="item.typeIcon" />
<span class="text-[24rpx] font-regular">{{ item.value }}</span>
</div>
</div>
</div>
<div class="chat-group-infos chat-settings-card">
<div
class="chat-group-infos-each"
v-for="(item, index) in state.chatSettings"
:key="index"
>
<settingFormItem
:item="item"
@toManagePage="toManagePage"
:sessionInfo="state?.sessionInfo"
@changeSwitch="changeSwitch"
></settingFormItem>
<div class="chat-group-infos-each" v-for="(item, index) in state.chatSettings" :key="index">
<settingFormItem :item="item" @toManagePage="toManagePage" :sessionInfo="state?.sessionInfo"
@changeSwitch="changeSwitch"></settingFormItem>
</div>
</div>
<div
class="chat-group-infos chat-settings-card"
v-if="groupParams?.groupInfo?.is_manager"
>
<div
class="chat-group-infos-each"
v-for="(item, index) in state.chatManagement"
:key="index"
>
<settingFormItem
:item="item"
@toManagePage="toManagePage"
></settingFormItem>
<div class="chat-group-infos chat-settings-card" v-if="groupParams?.groupInfo?.is_manager">
<div class="chat-group-infos-each" v-for="(item, index) in state.chatManagement" :key="index">
<settingFormItem :item="item" @toManagePage="toManagePage"></settingFormItem>
</div>
</div>
<div
class="chat-group-infos chat-settings-card"
>
<div
class="chat-group-infos-each"
v-for="(item, index) in state.chatReport"
:key="index"
>
<settingFormItem
:item="item"
@toManagePage="toManagePage"
></settingFormItem>
<div class="chat-group-infos chat-settings-card">
<div class="chat-group-infos-each" v-for="(item, index) in state.chatReport" :key="index">
<settingFormItem :item="item" @toManagePage="toManagePage"></settingFormItem>
</div>
</div>
<div class="clear-chat-record-btn chat-settings-card">
<div
@click="showConfirmPrompt(1)"
class="clear-chat-record-btn-each"
>
<div @click="showConfirmPrompt(1)" class="clear-chat-record-btn-each">
<span class="text-[32rpx] font-regular">
{{ $t('chat.settings.clearChatRecord') }}
</span>
</div>
<div
@click="showConfirmPrompt(2)"
class="clear-chat-record-btn-each"
v-if="
<div @click="showConfirmPrompt(2)" class="clear-chat-record-btn-each" v-if="
groupParams?.groupInfo?.is_manager &&
dialogueParams.type === 2 &&
(groupParams?.groupInfo?.group_type === 1 ||
groupParams?.groupInfo?.group_type === 3)
"
>
">
<span class="text-[32rpx] font-regular">
{{ $t('group.disband.btn') }}
</span>
</div>
<div
@click="showConfirmPrompt(3)"
class="clear-chat-record-btn-each"
v-if="
<div @click="showConfirmPrompt(3)" class="clear-chat-record-btn-each" v-if="
dialogueParams.type === 2 &&
(groupParams?.groupInfo?.group_type === 1 ||
groupParams?.groupInfo?.group_type === 3)
"
>
">
<span class="text-[32rpx] font-regular">
{{ $t('group.quit.btn') }}
</span>
@ -197,39 +118,55 @@
</div>
</template>
<script setup>
import avatarModule from '@/components/avatar-module/index.vue'
import useConfirm from '@/components/x-confirm/useConfirm.js'
import recordSearchTypeIcon_groupMember from '@/static/image/chatSettings/recordSearchTypeGroupMembers.png'
import recordSearchTypeIcon_date from '@/static/image/chatSettings/recordSearchTypeDate.png'
import recordSearchTypeIcon_imgAndVideo from '@/static/image/chatSettings/recordSearchTypeImgAndVideo.png'
import recordSearchTypeIcon_files from '@/static/image/chatSettings/recordSearchTypeFiles.png'
import recordSearchTypeIcon_link from '@/static/image/chatSettings/recordSearchTypeLink.png'
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import settingFormItem from './components/settingFormItem.vue'
import groupMemberList from './components/groupMembersList.vue'
import { computed, onMounted, reactive, watch } from 'vue'
import {
import avatarModule from '@/components/avatar-module/index.vue'
import useConfirm from '@/components/x-confirm/useConfirm.js'
import recordSearchTypeIcon_groupMember from '@/static/image/chatSettings/recordSearchTypeGroupMembers.png'
import recordSearchTypeIcon_date from '@/static/image/chatSettings/recordSearchTypeDate.png'
import recordSearchTypeIcon_imgAndVideo from '@/static/image/chatSettings/recordSearchTypeImgAndVideo.png'
import recordSearchTypeIcon_files from '@/static/image/chatSettings/recordSearchTypeFiles.png'
import recordSearchTypeIcon_link from '@/static/image/chatSettings/recordSearchTypeLink.png'
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import settingFormItem from './components/settingFormItem.vue'
import groupMemberList from './components/groupMembersList.vue'
import {
computed,
onMounted,
reactive,
watch
} from 'vue'
import {
useUserStore,
useTalkStore,
useDialogueStore,
useGroupStore,
useGroupTypeStore,
} from '@/store'
import { onLoad } from '@dcloudio/uni-app'
import {
} from '@/store'
import {
onLoad
} from '@dcloudio/uni-app'
import {
ServeInviteGroup,
ServeDismissGroup,
ServeSecedeGroup,
} from '@/api/group/index'
import { ServeTopTalkList, ServeSetNotDisturb } from '@/api/chat/index'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
import customInput from '@/components/custom-input/custom-input.vue'
const { showConfirm } = useConfirm()
const userStore = useUserStore()
const talkStore = useTalkStore()
const dialogueStore = useDialogueStore()
const dialogueParams = reactive({
} from '@/api/group/index'
import {
ServeTopTalkList,
ServeSetNotDisturb
} from '@/api/chat/index'
import {
useI18n
} from 'vue-i18n'
const {
t
} = useI18n()
import customInput from '@/components/custom-input/custom-input.vue'
const {
showConfirm
} = useConfirm()
const userStore = useUserStore()
const talkStore = useTalkStore()
const dialogueStore = useDialogueStore()
const dialogueParams = reactive({
uid: computed(() => userStore.uid),
index_name: computed(() => dialogueStore.index_name),
type: computed(() => dialogueStore.talk.talk_type),
@ -240,17 +177,17 @@ const dialogueParams = reactive({
num: computed(() => dialogueStore.members.length),
memberList: computed(() => dialogueStore.members),
adminList: computed(() => dialogueStore.getAdminList),
})
const talkParams = reactive({
})
const talkParams = reactive({
topItems: computed(() => talkStore.topItems),
disturbItems: computed(() => talkStore.disturbItems),
})
const groupStore = useGroupStore()
const groupParams = reactive({
})
const groupStore = useGroupStore()
const groupParams = reactive({
groupInfo: computed(() => groupStore.groupInfo),
groupNotice: computed(() => groupStore.groupNotice),
})
const state = reactive({
})
const state = reactive({
chatGroupMembers: [], //form-item
chatGroupInfos: [], //
recordSearchTypeList: [], //
@ -259,25 +196,26 @@ const state = reactive({
chatReport: [], //
groupId: '', //id
sessionId: '', //id
})
})
watch(
watch(
[() => groupParams.groupInfo, () => groupParams.groupNotice],
([newGroupInfo, newGroupNotice]) => {
updateGroupInfos()
}, {
deep: true
},
{ deep: true },
)
)
watch(
watch(
() => useGroupTypeStore()?.allChooseMembers?.value,
(newMembers) => {
// console.log(newMembers)
inviteMembersInGroup(newMembers)
},
)
)
onLoad(async (options) => {
onLoad(async (options) => {
console.log(dialogueParams)
if (options.groupId) {
console.log(options.groupId)
@ -304,11 +242,10 @@ onLoad(async (options) => {
})
}
}
})
})
onMounted(() => {
state.recordSearchTypeList = [
{
onMounted(() => {
state.recordSearchTypeList = [{
value: t('record.searchType.date'),
typeIcon: recordSearchTypeIcon_date,
},
@ -331,8 +268,7 @@ onMounted(() => {
typeIcon: recordSearchTypeIcon_groupMember,
})
}
state.chatSettings = [
{
state.chatSettings = [{
label: t('chat.settings.topSession'),
hasPointer: false,
value: '',
@ -347,26 +283,24 @@ onMounted(() => {
customInfo: 'switch',
},
]
state.chatReport = [
// {
// label: t('chat.settings.report'),
// hasPointer: true,
// },
]
})
state.chatReport = [{
label: t('chat.settings.report'),
hasPointer: true,
}, ]
})
//
const groupName = computed(() => {
//
const groupName = computed(() => {
return groupParams?.groupInfo?.group_name
})
})
//
const groupNum = computed(() => {
//
const groupNum = computed(() => {
return groupParams?.groupInfo?.group_num || 0
})
})
// -groupType
const groupTypeMapping = {
// -groupType
const groupTypeMapping = {
0: {},
1: {
result_type: t('index.mine.normal'),
@ -383,26 +317,23 @@ const groupTypeMapping = {
result_type: t('index.type.company'),
result_type_color: '#7A58DE',
},
}
}
//
const groupType = computed(() => {
//
const groupType = computed(() => {
return groupTypeMapping[groupParams?.groupInfo?.group_type]?.result_type || ''
})
})
//
const updateGroupInfos = () => {
state.chatGroupMembers = [
{
//
const updateGroupInfos = () => {
state.chatGroupMembers = [{
label: t('chat.settings.groupMember'),
hasPointer: true,
value: '全部(' + groupNum.value + '',
subValue: '',
customInfo: '',
},
]
state.chatGroupInfos = [
{
}, ]
state.chatGroupInfos = [{
label: t('chat.settings.groupName'),
hasPointer: groupParams?.groupInfo?.is_manager ? true : false,
value: groupName.value,
@ -434,8 +365,7 @@ const updateGroupInfos = () => {
}
})
}
state.chatManagement = [
{
state.chatManagement = [{
label: t('chat.settings.groupGag'),
hasPointer: true,
value: '',
@ -450,27 +380,27 @@ const updateGroupInfos = () => {
customInfo: '',
},
]
}
}
//
const toEditGroupInfoPage = () => {
//
const toEditGroupInfoPage = () => {
uni.navigateTo({
url: '/pages/chatSettings/groupManage/editGroupName',
})
}
}
//
const toEditAvatarPage = () => {
//
const toEditAvatarPage = () => {
if (!groupParams?.groupInfo?.is_manager) {
return
}
uni.navigateTo({
url: '/pages/chatSettings/groupManage/editAvatar',
})
}
}
//
const toManagePage = (label) => {
//
const toManagePage = (label) => {
console.log(label)
if (label) {
if (label === t('chat.settings.groupName')) {
@ -490,8 +420,7 @@ const toManagePage = (label) => {
})
} else if (label === t('chat.settings.groupMember')) {
uni.navigateTo({
url:
'/pages/chatSettings/groupManage/manageGroupMembers?groupId=' +
url: '/pages/chatSettings/groupManage/manageGroupMembers?groupId=' +
state.groupId,
})
} else if (label === t('chat.settings.groupGag')) {
@ -502,12 +431,16 @@ const toManagePage = (label) => {
uni.navigateTo({
url: '/pages/chatSettings/groupManage/manageGroupAdmin',
})
} else if (label === t('chat.settings.report')) {
uni.navigateTo({
url: '/pages/complaintReport/index',
})
}
}
}
}
//
const toSearchByConditionPage = (flag) => {
//
const toSearchByConditionPage = (flag) => {
let condition = ''
let flagIndex = 0
if (dialogueParams.type === 1) {
@ -515,8 +448,7 @@ const toSearchByConditionPage = (flag) => {
}
if (flag == flagIndex) {
uni.navigateTo({
url:
'/pages/chatSettings/groupManage/selectMembers?manageType=searchRecord',
url: '/pages/chatSettings/groupManage/selectMembers?manageType=searchRecord',
})
} else {
if (flag == flagIndex + 1) {
@ -532,10 +464,10 @@ const toSearchByConditionPage = (flag) => {
url: '/pages/search/searchByCondition/index?condition=' + condition,
})
}
}
}
//
const changeSwitch = (switchStatus, label) => {
//
const changeSwitch = (switchStatus, label) => {
let params
let resp
if (label == t('chat.settings.topSession')) {
@ -553,7 +485,10 @@ const changeSwitch = (switchStatus, label) => {
resp = ServeSetNotDisturb(params)
}
console.log(resp)
resp.then(({ code, data }) => {
resp.then(({
code,
data
}) => {
console.log(data)
if (code == 200) {
if (label == t('chat.settings.topSession')) {
@ -567,15 +502,14 @@ const changeSwitch = (switchStatus, label) => {
is_disturb: switchStatus ? 1 : 0,
})
}
} else {
}
} else {}
})
resp.catch(() => {})
}
}
//
const showConfirmPrompt = (flag) => {
//
const showConfirmPrompt = (flag) => {
let confirmContent = ''
let subContent = ''
let subContentColor = ''
@ -649,23 +583,25 @@ const showConfirmPrompt = (flag) => {
//退
ServeSecedeGroup({
group_id: dialogueParams.receiver_id,
}).then(({ code, message }) => {
}).then(({
code,
message
}) => {
if (code == 200) {
uni.navigateBack({
delta: 2,
})
} else {
}
} else {}
})
}
}
},
onCancel: () => {},
})
}
}
///
const inviteMembersInGroup = async (memberList) => {
///
const inviteMembersInGroup = async (memberList) => {
if (memberList?.length > 0) {
let erp_ids = ''
memberList.forEach((item) => {
@ -687,33 +623,32 @@ const inviteMembersInGroup = async (memberList) => {
useGroupTypeStore()?.resetGroupInfo()
}
}
}
}
//
const toSearchPage = () => {
//
const toSearchPage = () => {
// uni.navigateTo({
// url:
// '/pages/search/searchByCondition/index?condition=text'
// })
uni.navigateTo({
url:
'/pages/search/moreResult/moreResultDetail?talk_type=' +
url: '/pages/search/moreResult/moreResultDetail?talk_type=' +
dialogueParams.type +
'&receiver_id=' +
dialogueParams.receiver_id +
'&hideFirstRecord=1',
})
}
}
</script>
<style scoped lang="scss">
.outer-layer {
.outer-layer {
flex: 1;
background-image: url('@/static/image/clockIn/z3280@3x.png');
background-size: cover;
background-repeat: no-repeat;
}
}
.chat-settings-page {
.chat-settings-page {
.navBar-title {
span {
line-height: 48rpx;
@ -742,22 +677,27 @@ const toSearchPage = () => {
.base-info-avatar {
flex-shrink: 0;
}
.base-info {
width: 100%;
margin: 0 30rpx;
.base-info-name {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
span {
line-height: 44rpx;
color: $theme-text;
}
.base-info_num {
line-height: 44rpx;
}
}
.base-info-tag {
border: 2rpx solid #7a58de;
display: flex;
@ -768,6 +708,7 @@ const toSearchPage = () => {
margin: 10rpx 0 0;
border-radius: 8rpx;
width: 80rpx;
span {
flex-shrink: 0;
color: #7a58de;
@ -775,10 +716,12 @@ const toSearchPage = () => {
}
}
}
.base-info-edit {
width: 36rpx;
height: 36rpx;
flex-shrink: 0;
img {
width: 100%;
height: 100%;
@ -786,15 +729,16 @@ const toSearchPage = () => {
}
}
.chat-group-members {
}
.chat-group-members {}
.chat-group-infos {
padding: 0 16rpx;
.chat-group-infos-each {
padding: 32rpx 14rpx;
border-bottom: 1px solid $theme-border-color;
}
.chat-group-infos-each:last-child {
border-bottom: 0;
}
@ -809,6 +753,7 @@ const toSearchPage = () => {
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
.record-search-types-each {
width: calc(100% / 4);
display: flex;
@ -816,12 +761,14 @@ const toSearchPage = () => {
align-items: center;
justify-content: center;
margin: 36rpx 0 0;
.record-search-types-icon {
width: 106rpx;
height: 106rpx;
border-radius: 50%;
background-color: #f9f9f9;
}
span {
line-height: 34px;
color: #666666;
@ -835,6 +782,7 @@ const toSearchPage = () => {
flex-direction: column;
align-items: center;
justify-content: center;
.clear-chat-record-btn-each {
display: flex;
flex-direction: row;
@ -849,10 +797,11 @@ const toSearchPage = () => {
color: #cf3050;
}
}
.clear-chat-record-btn-each:last-child {
border-bottom: 0;
}
}
}
}
}
</style>

View File

@ -3,20 +3,358 @@
<div class="root">
<ZPaging ref="zPaging" :show-scrollbar="false">
<template #top>
<customNavbar class="tmNavBar"></customNavbar>
<customNavbar class="tmNavBar" :title="$t('complaint.title')"></customNavbar>
</template>
<!-- 投诉主体内容 -->
<view class="complaint-container">
<!-- 投诉类型选择 -->
<view class="form-item">
<text class="form-label">{{ $t('complaint.selectType') }}</text>
<picker mode="selector" :range="complaintTypes" range-key="label" @change="handleTypeChange">
<view class="picker">
{{ selectedType.label || $t('complaint.selectPlaceholder') }}
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
</view>
</picker>
</view>
<!-- 图片证据上传 -->
<view class="form-item">
<text class="form-label">{{ $t('complaint.imageEvidence') }}</text>
<view class="upload-area">
<view v-for="(img, index) in imageList" :key="index" class="image-wrapper">
<image :src="img" mode="aspectFill" class="uploaded-image" @click="previewImage(index)" />
<uni-icons type="close" size="18" color="#fff" class="delete-icon"
@click="removeImage(index)"></uni-icons>
</view>
<view v-if="imageList.length < 9" class="upload-btn" @click="chooseImage">
<uni-icons type="plusempty" size="28" color="#999"></uni-icons>
<text class="upload-text">{{ $t('complaint.addImage') }}</text>
</view>
</view>
</view>
<!-- 投诉内容 -->
<view class="form-item">
<text class="form-label">{{ $t('complaint.complaintContent') }}</text>
<textarea v-model="complaintContent" :placeholder="$t('complaint.contentPlaceholder')"
class="content-textarea"></textarea>
</view>
<!-- 投诉须知 -->
<view class="notice-box">
<view class="notice-header" @click="toggleNotice">
<text class="notice-title">{{ $t('complaint.noticeTitle') }}</text>
<text class="toggle-btn">
{{ isNoticeExpanded ? $t('complaint.collapse') : $t('complaint.expand') }}
</text>
</view>
<!-- 折叠状态只显示前两项 -->
<view class="notice-content" v-if="!isNoticeExpanded">
<view class="notice-item">
<text>{{ $t('complaint.noticeone') }}</text>
</view>
<view class="notice-item">
<text>{{ $t('complaint.noticetwo') }}</text>
</view>
</view>
<!-- 展开状态显示全部 -->
<view class="notice-content" v-else>
<view class="notice-item">
<text>{{ $t('complaint.noticeone') }}</text>
</view>
<view class="notice-item">
<text>{{ $t('complaint.noticetwo') }}</text>
</view>
<view class="notice-item">
<text>{{ $t('complaint.noticethree') }}</text>
</view>
<view class="notice-item">
<text>{{ $t('complaint.noticefour') }}</text>
</view>
<view class="notice-item">
<text>{{ $t('complaint.noticefive') }}</text>
</view>
<view class="notice-item">
<text>{{ $t('complaint.noticenoticeContent') }}</text>
</view>
</view>
</view>
<button class="submit-btn" :disabled="!selectedType.value" @click="handleSubmit">
{{ $t('complaint.submit') }}
</button>
</view>
</ZPaging>
<!-- 固定在底部的提交按钮 -->
</div>
</div>
</template>
<script setup>
<script setup>
import {
ref
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
import {
useI18n
} from 'vue-i18n';
const {
t
} = useI18n();
//
const complaintTypes = computed(() => [{
label: t('complaint.typeOptions.porn'),
value: 'porn'
},
{
label: t('complaint.typeOptions.illegal'),
value: 'illegal'
},
{
label: t('complaint.typeOptions.gambling'),
value: 'gambling'
},
{
label: t('complaint.typeOptions.violence'),
value: 'violence'
},
{
label: t('complaint.typeOptions.selfHarm'),
value: 'selfHarm'
},
{
label: t('complaint.typeOptions.other'),
value: 'other'
}
]);
//
const selectedType = ref({});
const imageList = ref([]);
const complaintContent = ref('');
const isNoticeExpanded = ref(false);
//
const toggleNotice = () => {
isNoticeExpanded.value = !isNoticeExpanded.value;
};
//
const handleTypeChange = (e) => {
selectedType.value = complaintTypes.value[e.detail.value];
};
//
const chooseImage = () => {
uni.chooseImage({
count: 9 - imageList.value.length,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
imageList.value = [...imageList.value, ...res.tempFilePaths];
}
});
};
//
const removeImage = (index) => {
imageList.value.splice(index, 1);
};
//
const previewImage = (index) => {
uni.previewImage({
current: index,
urls: imageList.value
});
};
//
const handleSubmit = () => {
const formData = {
type: selectedType.value,
images: imageList.value,
content: complaintContent.value
};
uni.showLoading({
title: t('complaint.toast.submitting') // 使
});
setTimeout(() => {
uni.hideLoading();
uni.showToast({
title: t('complaint.toast.success'),
icon: 'success'
});
selectedType.value = {};
imageList.value = [];
complaintContent.value = '';
//
setTimeout(() => {
uni.navigateBack();
}, 1500);
}, 2000);
};
onLoad(() => {
//
});
</script>
<style scoped lang="scss">
.outer-layer {
::v-deep .uni-picker-action-confirm {
color: #452aa1 !important;
}
.outer-layer {
flex: 1;
background-image: url('@/static/image/mine/1111.png');
background-size: cover;
background-repeat: no-repeat;
}
}
.complaint-container {
padding: 20rpx 30rpx;
background-color: rgba(255, 255, 255, 0.9);
margin: 20rpx;
border-radius: 16rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.form-item {
margin-bottom: 40rpx;
}
.form-label {
display: block;
font-size: 28rpx;
color: #333;
font-weight: 500;
margin-bottom: 20rpx;
}
.picker {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx;
background-color: #f7f7f7;
border-radius: 12rpx;
font-size: 28rpx;
color: #333;
}
.upload-area {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.upload-btn {
width: 160rpx;
height: 160rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #f7f7f7;
border-radius: 12rpx;
border: 1rpx dashed #ddd;
}
.upload-text {
font-size: 24rpx;
color: #999;
margin-top: 10rpx;
}
.image-wrapper {
width: 160rpx;
height: 160rpx;
position: relative;
border-radius: 12rpx;
overflow: hidden;
}
.uploaded-image {
width: 100%;
height: 100%;
}
.delete-icon {
position: absolute;
top: 8rpx;
right: 8rpx;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 50%;
padding: 4rpx;
}
.content-textarea {
width: 100%;
height: 200rpx;
padding: 20rpx;
background-color: #f7f7f7;
border-radius: 12rpx;
font-size: 28rpx;
color: #333;
}
.notice-box {
padding: 20rpx;
background-color: #f0f7ff;
border-radius: 12rpx;
margin: 40rpx 0;
}
.notice-title {
font-size: 28rpx;
color: #452aa1;
font-weight: bold;
display: block;
margin-bottom: 10rpx;
}
.notice-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 0;
}
.toggle-btn {
color: #452aa1;
font-size: 24rpx;
}
.notice-content {
font-size: 24rpx;
color: #666;
line-height: 1.6;
padding-bottom: 20rpx;
}
.submit-btn {
margin-top: 40rpx;
background-color: #452aa1;
color: white;
border-radius: 8rpx;
height: 90rpx;
line-height: 90rpx;
font-size: 32rpx;
&[disabled] {
background-color: #f0f0f0;
}
}
</style>

View File

@ -8,12 +8,8 @@
<div class="group-avatar flex items-center justify-center">
<div class="avatar-placeholder" v-if="groupActiveIndex === -1"></div>
<div v-else>
<avatarModule
:mode="2"
:avatar="avatarImg"
:groupType="groupType"
:customStyle="{ width: '192rpx', height: '192rpx' }"
></avatarModule>
<avatarModule :mode="2" :avatar="avatarImg" :groupType="groupType"
:customStyle="{ width: '192rpx', height: '192rpx' }"></avatarModule>
</div>
</div>
<div class="input-group flex items-center justify-between">
@ -21,25 +17,12 @@
群名称
</div>
<div class="input-box">
<tm-input
v-model="groupName"
:followTheme="false"
fontColor="#747474"
placeholderStyle="color: #B4B4B4"
focusColor="#FFF"
:fontSize="28"
:maxlength="20"
:height="40"
:transprent="true"
placeholder="请输入群名称1~20个字"
:padding="[0, 0]"
align="right"
></tm-input>
<tm-input v-model="groupName" :followTheme="false" fontColor="#747474" placeholderStyle="color: #B4B4B4"
focusColor="#FFF" :fontSize="28" :maxlength="20" :height="40" :transprent="true"
placeholder="请输入群名称1~20个字" :padding="[0, 0]" align="right"></tm-input>
</div>
</div>
<div
class="input-group w-full flex flex-col mt-[20rpx] leading-[40rpx]"
>
<div class="input-group w-full flex flex-col mt-[20rpx] leading-[40rpx]">
<div class="flex items-center justify-between">
<div class="input-item">
群类型
@ -52,117 +35,69 @@
<span v-else-if="groupActiveIndex === 2">项目群</span>
</div>
<div class="ml-[32rpx]">
<tm-icon
:font-size="22"
color="#747474"
name="tmicon-angle-right"
></tm-icon>
<tm-icon :font-size="22" color="#747474" name="tmicon-angle-right"></tm-icon>
</div>
</div>
</div>
<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"
<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"
:class="[
index !== 0 ? 'mt-[10rpx]' : '',
depsNoExpanded_1 && index > 4 ? 'hidden' : '',
]"
>
]">
{{ item.name }}
</div>
<div
class="text-[#46299D] text-[28rpx] mt-[20rpx] font-bold flex justify-center"
>
<div
v-if="depCheckedKeys.length > 5"
@click="depsNoExpanded_1 = !depsNoExpanded_1"
class="w-[100rpx]"
>
<div class="text-[#46299D] text-[28rpx] mt-[20rpx] font-bold flex justify-center">
<div v-if="depCheckedKeys.length > 5" @click="depsNoExpanded_1 = !depsNoExpanded_1" class="w-[100rpx]">
{{ depsNoExpanded_1 ? '展开' : '收起' }}
</div>
</div>
</div>
</div>
<div
v-if="groupActiveIndex === 0 || groupActiveIndex === 2"
class="input-group w-full flex flex-col mt-[20rpx] leading-[40rpx]"
>
<div v-if="groupActiveIndex === 0 || groupActiveIndex === 2"
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
class="text-[#B4B4B4] text-[28rpx] font-bold mr-[32rpx]"
>
<div class="text-[#B4B4B4] text-[28rpx] font-bold mr-[32rpx]">
全部({{ allChooseMembers?.length || 0 }})
</div>
<tm-icon
:font-size="22"
color="#747474"
name="tmicon-angle-right"
></tm-icon>
<tm-icon :font-size="22" color="#747474" name="tmicon-angle-right"></tm-icon>
</div>
</div>
</div>
<groupMemberList
:groupType="3"
:is_manager="true"
:memberList="allChooseMembers"
:memberListsLimit="15"
:hideAddRemoveBtns="true"
></groupMemberList>
<groupMemberList :groupType="3" :is_manager="true" :memberList="allChooseMembers" :memberListsLimit="15"
:hideAddRemoveBtns="true"></groupMemberList>
</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="input-item">
群管理员
</div>
<div @click="chooseGroupAdmin" class="left-box">
<div class="ml-[32rpx] flex items-center">
<div
v-if="!groupAdmins.length"
class="text-[#B4B4B4] text-[28rpx] font-bold mr-[32rpx]"
>
<div v-if="!groupAdmins.length" class="text-[#B4B4B4] text-[28rpx] font-bold mr-[32rpx]">
请选择群管理员
</div>
<tm-icon
:font-size="22"
color="#747474"
name="tmicon-angle-right"
></tm-icon>
<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"
<div v-for="(item, index) in groupAdmins" class="text-[#747474] text-[28rpx] leading-[40rpx] font-bold"
:class="[
index !== 0 ? 'mt-[10rpx]' : '',
depsNoExpanded_2 && 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_2 = !depsNoExpanded_2"
class="w-[100rpx]"
>
<div class="text-[#46299D] text-[28rpx] mt-[20rpx] font-bold flex justify-center">
<div v-if="groupAdmins.length > 5" @click="depsNoExpanded_2 = !depsNoExpanded_2" class="w-[100rpx]">
{{ depsNoExpanded_2 ? '展开' : '收起' }}
</div>
</div>
@ -170,34 +105,53 @@
</div>
</div>
<template #bottom>
<customBtn
:isBottom="true"
:btnText="$t('pageTitle.create.group')"
@click="handleConfirm"
:disabled="confirmBtnStatus"
></customBtn>
<customBtn :isBottom="true" :btnText="$t('pageTitle.create.group')" @click="handleConfirm"
:disabled="confirmBtnStatus"></customBtn>
</template>
</zPaging>
</div>
</template>
<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 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, onMounted } from 'vue'
import { onShow, onLoad, onUnload } from '@dcloudio/uni-app'
import { useChatList } from '@/store/chatList/index.js'
import { useAuth } from '@/store/auth'
import { useTalkStore, useUserStore, useGroupStore } from '@/store'
import addCircle from '@/static/image/chatList/addCircle.png'
import cahtPopover from '@/static/image/chatList/cahtPopover.png'
import { ServeCreateGroup } from '@/api/group/index'
import { useGroupTypeStore } from '@/store/groupType'
import { handleSetWebviewStyle } from '@/utils/common'
import {
ref,
watch,
computed,
onMounted
} from 'vue'
import {
onShow,
onLoad,
onUnload
} from '@dcloudio/uni-app'
import {
useChatList
} from '@/store/chatList/index.js'
import {
useAuth
} from '@/store/auth'
import {
useTalkStore,
useUserStore,
useGroupStore
} from '@/store'
import addCircle from '@/static/image/chatList/addCircle.png'
import cahtPopover from '@/static/image/chatList/cahtPopover.png'
import {
ServeCreateGroup
} from '@/api/group/index'
import {
useGroupTypeStore
} from '@/store/groupType'
import {
handleSetWebviewStyle
} from '@/utils/common'
const {
const {
groupName,
groupActiveIndex,
depCheckedKeys,
@ -205,29 +159,31 @@ const {
createDepGroup,
resetGroupInfo,
allChooseMembers,
} = useGroupTypeStore()
const talkStore = useTalkStore()
const userStore = useUserStore()
const groupStore = useGroupStore()
const { userInfo } = useAuth()
} = useGroupTypeStore()
const talkStore = useTalkStore()
const userStore = useUserStore()
const groupStore = useGroupStore()
const {
userInfo
} = useAuth()
const groupChatType = ref('')
const depsNoExpanded_1 = ref(true)
const depsNoExpanded_2 = ref(true)
const groupChatType = ref('')
const depsNoExpanded_1 = ref(true)
const depsNoExpanded_2 = ref(true)
onLoad(()=> {
onLoad(() => {
groupStore.$reset()
})
onUnload(()=> {
})
onUnload(() => {
resetGroupInfo();
})
onMounted(() => {
})
onMounted(() => {
handleSetWebviewStyle()
})
})
//
const groupType = computed(() => {
//
const groupType = computed(() => {
let group_type = ''
switch (groupActiveIndex.value) {
case 0:
@ -243,30 +199,29 @@ const groupType = computed(() => {
group_type = ''
}
return group_type
})
})
//
const chooseGroupType = () => {
//
const chooseGroupType = () => {
uni.navigateTo({
url: '/pages/chooseGroupType/index',
})
}
}
const chooseGroupAdmin = () => {
const chooseGroupAdmin = () => {
uni.navigateTo({
url:
'/pages/chatSettings/groupManage/selectMembers?manageType=admin&isCreateDepGroup=1',
url: '/pages/chatSettings/groupManage/selectMembers?manageType=admin&isCreateDepGroup=1',
})
}
}
const chooseMembers = () => {
const chooseMembers = () => {
uni.navigateTo({
url: '/pages/chooseByDeps/index?chooseMode=2',
})
}
}
//
const handleConfirm = async () => {
//
const handleConfirm = async () => {
// console.log(allChooseMembers.value)
let erp_ids = ''
if (allChooseMembers?.value?.length > 0) {
@ -315,70 +270,73 @@ const handleConfirm = async () => {
resetGroupInfo()
uni.navigateBack()
}
} else {
} else {}
}
}
//
const confirmBtnStatus = computed(() => {
let disabledT = false
//
const confirmBtnStatus = computed(() => {
//
if (
groupName.value === '' ||
(groupActiveIndex.value && groupActiveIndex.value === -1) ||
(!groupActiveIndex.value && groupActiveIndex.value !== 0)
) {
return true
return true;
}
//
let temp = []
allChooseMembers?.value?.forEach((ele) => {
if (ele.ID !== userInfo.value.ID) {
temp.push(ele)
}
})
switch (groupActiveIndex.value) {
case 0:
if(temp?.length < 2) {
disabledT = true
}
break
case 1:
if (!depCheckedKeys.value.length) {
disabledT = true
}
if (!groupAdmins.value.length) {
disabledT = true
}
break
case 2:
if(temp?.length < 2) {
disabledT = true
}
break
default:
break
}
return disabledT
})
onShow(() => {
//
const includesSelf = allChooseMembers.value?.some(member => member.ID === userInfo.value.ID);
const memberCount = allChooseMembers.value?.length || 0;
//
if (includesSelf && memberCount < 3) {
return true; // <3
}
if (!includesSelf && memberCount < 2) {
return true; // <2
}
//
let disabledT = false;
switch (groupActiveIndex.value) {
case 0: //
//
break;
case 1: //
if (!depCheckedKeys.value.length || !groupAdmins.value.length) {
disabledT = true;
}
break;
case 2: //
//
break;
default:
break;
}
return disabledT;
});
onShow(() => {
depsNoExpanded_1.value = true;
depsNoExpanded_2.value = true;
})
})
</script>
<style scoped lang="scss">
::v-deep .zp-paging-container-content {
::v-deep .zp-paging-container-content {
height: 100%;
display: flex;
}
}
.create-group-chat {
.create-group-chat {
background-image: url('@/static/image/clockIn/z3280@3x.png');
background-size: cover;
background-position: center bottom;
width: 100%;
padding: 0 32rpx 20rpx;
.group-avatar {
padding: 60rpx 0;
.avatar-placeholder {
width: 192rpx;
height: 192rpx;
@ -386,31 +344,35 @@ onShow(() => {
border-radius: 50%;
}
}
}
.divider {
}
.divider {
height: 1rpx;
background-color: #7c7c7c;
opacity: 0.6;
}
}
.input-group {
.input-group {
background-color: #fff;
padding: 38rpx 40rpx 32rpx 32rpx;
}
.input-item {
}
.input-item {
line-height: 40rpx;
font-size: 28rpx;
color: #000;
font-weight: bold;
}
.input-box {
}
.input-box {
margin-left: 84rpx;
line-height: 40rpx;
width: 404rpx;
font-weight: bold;
}
.left-box {
}
.left-box {
display: flex;
align-items: center;
}
}
</style>

View File

@ -71,5 +71,37 @@
"message.customerService.text":"Please call customer service",
"message.action.text":"perform logout operation",
"index.mine.upload":"Click To Upload",
"index.mine.reUpload":"Re-upload"
"index.mine.reUpload":"Re-upload",
"complaint": {
"title": "Complaint Report",
"selectType": "Select Complaint Type",
"selectPlaceholder": "Please select complaint type",
"imageEvidence": "Image Evidence (Max 9)",
"addImage": "Add Image",
"complaintContent": "Complaint Content (Optional)",
"contentPlaceholder": "Please describe in detail...",
"noticeTitle": "Notice",
"noticeone": "1. Please select the correct complaint category.",
"noticetwo":"2. Provide valid evidence such as images, chat records, etc.",
"noticethree": "3. Describe the violation details to help us review faster.",
"noticefour": "4. Do not submit duplicate complaints for the same issue.",
"noticefive":"5. Do not abuse the complaint system.",
"noticenoticeContent":"Thank you for helping us build a safe community. We will process your complaint as soon as possible. We hope your complaint is made in good faith with accurate information. We will take reasonable measures to protect your privacy and will not disclose your information to third parties without your consent, except as required by law. Abuse of the complaint system may result in restrictions.",
"submit": "Submit",
"expand": "Expand",
"collapse": "Collapse",
"typeOptions": {
"porn": "Underage Exploitation",
"illegal": "Fraud",
"gambling": "Illegal Activities",
"violence": "Harassment",
"selfHarm": "Harmful Content",
"other": "Other"
},
"toast": {
"selectType": "Please select complaint type",
"submitting": "Submitting...",
"success": "Complaint submitted successfully"
}
}
}

View File

@ -156,5 +156,37 @@
"popup.title.phone": "电话",
"pageTitle.view.deps": "查看部门",
"group.dismiss.confirm": "确定解散本群",
"chat.settings.report": "投诉"
"chat.settings.report": "投诉",
"complaint": {
"title": "投诉举报",
"selectType": "选择投诉内容",
"selectPlaceholder": "请选择投诉类型",
"imageEvidence": "图片证据(最多9张)",
"addImage": "添加图片",
"complaintContent": "投诉内容(选填)",
"contentPlaceholder": "请详细描述投诉内容...",
"noticeTitle": "投诉须知",
"noticeone":"1、请选择正确的投诉类目。",
"noticetwo":"2、提供有效的违规证据如:图片、聊天信息等",
"noticethree":"3、详细描述违规问题详情有助于我们的审核人员快速研判处置。",
"noticefour": "4、请勿针对同一问题重复投诉以免造成资源浪费。",
"noticefive":"5、请勿滥用投诉以免造成资源浪费",
"noticenoticeContent":"感谢您与我们共建安全社区环境,我们会尽快对您的投诉进行处理。同时我们希望您的投诉行为基于善意,提供准确有效的违规信息帮助我们更好的进行判断并且处理。同时我们会采取必要合理的措施保护投诉人的个人隐私信息,除法律法规规定的情形之外,在未获得用户许可的情况下,不会向第三方公开投诉人信息。如果存在滥用、重复无效投诉,我们可能会对投诉账号采取包括但不限于限制投诉频次、禁止投诉等限制",
"submit": "提交投诉",
"expand": "展开",
"collapse": "收起",
"typeOptions": {
"porn": "侵犯未成年",
"illegal": "欺诈骗钱",
"gambling": "违法违规",
"violence": "骚扰",
"selfHarm": "不良价值导向",
"other": "其他"
},
"toast": {
"selectType": "请选择投诉类型",
"submitting": "提交中...",
"success": "投诉提交成功"
}
}
}