chat-app/src/pages/search/searchByCondition/index.vue
wangyifeng 226a24b06b
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
处理提测前的样式问题
2025-03-10 09:57:21 +08:00

710 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="outer-layer search-by-condition-page">
<div class="root">
<ZPaging
ref="zPaging"
:show-scrollbar="false"
@query="queryAllSearch"
:refresher-enabled="false"
:auto="false"
:loading-more-default-as-loading="true"
:inside-more="true"
>
<template #top v-if="state.showPageTitle">
<customNavbar :title="state.pageTitle"></customNavbar>
</template>
<div v-if="state.condition === 'date'" class="search-by-date">
<tm-time-picker
:show="state.showMonthPicker"
:showDetail="{
year: true,
month: true,
day: false,
hour: false,
minute: false,
second: false,
am_pm: false,
}"
:showSuffix="{
year: '',
month: '',
}"
:defaultValue="state.nowDate"
format="YYYY年MM月"
start=""
:end="state.maxDate"
@confirm="confirmSelectedMonth"
:round="0"
:title="$t('search.condition.date_pickerTitle')"
>
<div class="search-date-picker">
<span class="text-[28rpx] font-regular">
{{ state.selectedMonth }}
</span>
<img src="/src/static/image/search/down-pointer.png" />
</div>
</tm-time-picker>
<tm-calendar-view
:show="true"
:hideTool="true"
:hideButton="true"
:dateStyle="state.dateStyle"
:defaultValue="state.selectedDateArray"
v-model="state.selectedDateArray"
:disabledDate="state.disabledDateArray"
@click="selectDate"
model="day"
:end="state.maxDate"
@getDArray="getDArray"
:showDefault="false"
></tm-calendar-view>
</div>
<div
class="search-by-condition-input-list"
v-if="
state.condition === 'imgAndVideo' ||
state.condition === 'file' ||
state.condition === 'link'
"
:style="{
padding: state.condition === 'imgAndVideo' ? '0 27rpx' : '',
}"
>
<div
class="search-by-condition-input"
v-if="state.condition === 'file' || state.condition === 'link'"
>
<customInput
:searchText="state.searchText"
:first_talk_record_infos="state.first_talk_record_infos"
@inputSearchText="inputSearchText"
></customInput>
<span
@click="cancelSearch"
class="search-by-condition-input-text text-[32rpx] font-medium"
>
{{ $t('cancel') }}
</span>
</div>
<div class="search-by-condition-list">
<div class="condition-dimensionality">
<div
class="condition-dimensionality-each"
v-for="(conditionItem,
conditionIndex) in state.searchResultList"
:key="conditionIndex"
>
<div class="condition-dimensionality-each-month">
<span class="text-[28rpx] font-regular">
{{ conditionItem.dateMonth }}
</span>
</div>
<div
class="condition-each-resultList"
:class="[
state.condition === 'imgAndVideo'
? 'condition-type-imgAndVideo-result'
: '',
]"
>
<div
class="condition-each-resultList-each"
v-for="(item, index) in conditionItem.monthResultList"
:key="index"
:style="{
border: state.condition === 'imgAndVideo' ? '0' : '',
padding:
state.condition === 'imgAndVideo' ? '0 0 10rpx' : '',
}"
>
<div
class="condition-result-imgAndVideo"
v-if="state.condition === 'imgAndVideo'"
>
<div
class="condition-result-imgAndVideo-area"
v-if="item?.extra?.items?.length > 0"
>
<div
class="condition-result-imgAndVideo-each"
v-for="(imgItem, imgIndex) in item?.extra?.items"
:key="imgIndex"
>
<tm-image
preview
:src="imgItem?.content"
v-if="imgItem?.type == 3"
model="aspectFill"
/>
</div>
</div>
<div
class="condition-result-imgAndVideo-area"
v-if="item?.extra?.url"
>
<tm-image
preview
:src="
item?.msg_type === 3
? item?.extra?.url
: item?.msg_type === 5
? item?.extra?.cover
: ''
"
model="aspectFill"
/>
</div>
</div>
<div
class="condition-each-result-main"
v-if="
state.condition === 'file' || state.condition === 'link'
"
>
<searchItem
:searchItem="item"
:conditionType="state.msg_type"
></searchItem>
<span
class="text-[24rpx] font-medium condition-each-result-main-date"
>
{{ item.dateTime }}
</span>
</div>
<div
class="condition-each-result-attachments"
v-if="
state.condition === 'file' || state.condition === 'link'
"
>
<div class="attachment-avatar">
<img
:src="item?.extra?.file_avatar"
v-if="state.condition === 'file'"
/>
<img
src="/src/static/image/search/result-link-icon.png"
v-if="state.condition === 'link'"
/>
</div>
<div class="attachment-info">
<div class="attachment-info-title">
<span
class="text-[28rpx] font-regular"
v-if="state.condition === 'file'"
>
{{ item?.extra?.name }}
</span>
<span
class="text-[28rpx] font-regular"
v-if="state.condition === 'link'"
>
{{ $t('record.share.link') }}
</span>
</div>
<div
class="attachment-sub-info"
:style="{
margin:
state.condition === 'file' ? '20rpx 0 0' : '',
}"
>
<span
class="text-[24rpx] font-regular"
v-if="state.condition === 'file'"
>
{{ item?.extra?.typeText }}
</span>
<span
class="text-[24rpx] font-regular"
v-if="state.condition === 'file'"
style="margin: 0 0 0 20rpx;"
>
{{ item?.extra?.fileSize }}
</span>
<span
class="text-[24rpx] font-regular"
v-if="state.condition === 'link'"
>
{{ item?.extra?.content }}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ZPaging>
</div>
</div>
</template>
<script setup>
import fileType_PPT from '@/static/image/search/fileType_PPT.png'
import fileType_EXCEL from '@/static/image/search/fileType_EXCEL.png'
import fileType_WORD from '@/static/image/search/fileType_WORD.png'
import fileType_PDF from '@/static/image/search/fileType_PDF.png'
import fileType_Files from '@/static/image/search/fileType_Files.png'
import { fileFormatSize, fileSuffix } from '@/utils/strings'
import searchItem from '../components/searchItem.vue'
import customInput from '@/components/custom-input/custom-input.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 { parseTime } from '@/utils/datetime'
import { onMounted, reactive, computed, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { ServeTalkDate } from '@/api/search/index'
import { ServeFindTalkRecords } from '@/api/chat/index'
import { useDialogueStore } from '@/store'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const zPaging = ref()
useZPaging(zPaging)
const dialogueStore = useDialogueStore()
const dialogueParams = reactive({
talk_type: computed(() => dialogueStore.talk.talk_type),
receiver_id: computed(() => dialogueStore.talk.receiver_id),
})
let nowDay = new Date().setHours(0, 0, 0, 0)
const state = reactive({
receiver_id: '', //目标人id
pageTitle: '', //页面标题
dateStyle: [], //日期样式
nowDate: new Date(nowDay), //当前时间
maxDate: new Date(nowDay), //可选择最大时间
selectedDateArray: Array(new Date(nowDay)), //选择的月份数组
showMonthPicker: false, //是否显示月份选择
selectedMonth: new Date(nowDay), //当前选择的月份
disabledDateArray: [], //被禁用的日期数组
dArray: [], //日历日期数组
showPageTitle: false, //是否显示页面标题
searchText: '', //搜索内容
first_talk_record_infos: Object,
searchResultList: [], //搜索结果列表
cursor: 0, //上次查询的游标
msg_type: 0, //查询的消息类型
})
onLoad((options) => {
console.log(options)
if (options.receiver_id) {
state.receiver_id = Number(options.receiver_id)
}
if (options.condition) {
state.condition = options.condition
if (options.condition === 'date') {
state.showPageTitle = true
state.pageTitle = t('search.condition.date')
ServeQueryTalkDate(parseTime(state.nowDate, '{y}{m}'))
} else if (options.condition === 'imgAndVideo') {
state.showPageTitle = true
state.pageTitle = t('record.searchType.imgWithVideo')
state.msg_type = '3,5'
queryAllSearch()
} else if (options.condition === 'file') {
console.log(dialogueParams)
let first_talk_record_infos = {
receiver_name: t('record.searchType.files'),
}
state.first_talk_record_infos = Object.assign(
{},
state.first_talk_record_infos,
first_talk_record_infos,
)
state.msg_type = 6
queryAllSearch()
} else if (options.condition === 'link') {
console.log(dialogueParams)
let first_talk_record_infos = {
receiver_name: t('record.searchType.link'),
}
state.first_talk_record_infos = Object.assign(
{},
state.first_talk_record_infos,
first_talk_record_infos,
)
state.msg_type = 14
queryAllSearch()
}
}
})
onMounted(() => {
state.selectedMonth = parseTime(state.selectedMonth, '{y}年{m}月')
state.dateStyle = [
{
date: state.nowDate, //日期
text: false, //浅色背景。
color: '#46299D', //主题色.
extra: '今天', //额外的内容,在日期下方显示的文本。
},
]
})
//查看存在聊天记录的天数
const ServeQueryTalkDate = (month) => {
let params = {
month: month,
talk_type: 2, //1私聊2群聊
receiver_id: state.receiver_id, //目标人id
}
const resp = ServeTalkDate(params)
console.log(resp)
resp.then(({ code, data }) => {
console.log(data)
if (code == 200) {
if (data && data.length > 0) {
const formattedData = data.map(
(item) =>
item.substring(0, 4) +
'/' +
item.substring(4, 6) +
'/' +
item.substring(6, 8),
)
let disabledDateArray = state.dArray.filter(
(dIt) => !formattedData.includes(dIt),
)
disabledDateArray = disabledDateArray.map((item) =>
item.replace(/\//g, '-'),
)
console.log(disabledDateArray)
state.disabledDateArray = disabledDateArray
} else {
state.disabledDateArray = state.dArray
}
} else {
}
})
resp.catch(() => {})
}
//点击选择日期
const selectDate = (e) => {
if (e == parseTime(state.nowDate, '{y}/{m}/{d}')) {
console.log('==今日')
state.dateStyle = [
{
date: state.nowDate, //日期
text: false, //浅色背景。
color: '#46299D', //主题色.
extra: '今天', //额外的内容,在日期下方显示的文本。
},
]
} else {
state.dateStyle = [
{
date: state.nowDate, //日期
text: false, //浅色背景。
color: '', //主题色.
extra: '今天', //额外的内容,在日期下方显示的文本。
},
{
date: new Date(e), //日期
text: false, //浅色背景。
color: '#46299D', //主题色.
},
]
}
}
//点击确认选择月份
const confirmSelectedMonth = (e) => {
console.log(e)
state.selectedMonth = parseTime(e, '{y}年{m}月')
// console.log()
let newDate = new Date(e)
newDate.setHours(0, 0, 0, 0)
newDate.setDate(1)
state.selectedDateArray = Array(new Date(newDate))
state.dateStyle = [
{
date: state.nowDate, //日期
text: false, //浅色背景。
color: '', //主题色.
extra: '今天', //额外的内容,在日期下方显示的文本。
},
]
ServeQueryTalkDate(parseTime(e, '{y}{m}'))
}
//获取日历日期数组
const getDArray = (dArray) => {
state.dArray = dArray
}
//输入搜索内容
const inputSearchText = (e) => {
state.searchText = e
}
//点击取消搜索
const cancelSearch = () => {
uni.navigateBack({
delta: 1,
})
}
//查询数据
const queryAllSearch = () => {
let params = {
talk_type: dialogueParams.talk_type, //1私聊2群聊
receiver_id: dialogueParams.receiver_id, //目标用户id或群聊id
msg_type: state.msg_type, //消息类型0:全部;2:代码;3:图片;4:音频;5:视频;6:文件;7:位置;9:会话;11群投票;12图文混合
cursor: state.cursor, //上次查询的游标
limit: 10, //数据行数
no_limit: '', //1不限制
direction: 'up', //down向下查最新up向上查老数据
start_time: '',
end_time: '',
group_member_user_id: 0, //群成员id当查询群历史消息的时候需要指定群成员的时候送
}
console.log(params)
const resp = ServeFindTalkRecords(params)
console.log(resp)
resp.then(({ code, data }) => {
console.log(data)
if (code == 200) {
let dateList = state.searchResultList
let noMore = false
if (data?.items?.length > 0) {
data.items.forEach((item) => {
item.dateTime = parseTime(item?.created_at, '{m}/{d}')
item.extra.fileSize = fileFormatSize(item?.extra?.size)
item.extra.typeText = item?.extra?.name
? fileSuffix(item?.extra?.name)
: ''
item.extra.file_avatar = fileTypeAvatar(item?.extra?.typeText)
console.log(item.extra.type)
let year = new Date(item.created_at).getFullYear()
let month = new Date(item.created_at).getMonth() + 1
let dateMonth =
year == state.nowDate.getFullYear() &&
month == state.nowDate.getMonth() + 1
? t('result.date.nowMonth')
: year + '年' + month + '月'
if (dateList.length > 0) {
let hasAdd = false
dateList.forEach((dateItem) => {
if (dateItem.dateMonth === dateMonth) {
dateItem.monthResultList.push(item)
hasAdd = true
}
})
if (!hasAdd) {
console.log(dateList)
dateList.push({
dateMonth: dateMonth,
monthResultList: [item],
})
}
} else {
dateList.push({
dateMonth: dateMonth,
monthResultList: [item],
})
}
})
} else {
noMore = true
}
console.log(dateList)
state.cursor = data?.cursor
zPaging.value?.completeByNoMore(dateList, noMore)
} else {
zPaging.value?.complete([])
}
})
resp.catch(() => {
zPaging.value?.complete([])
})
}
//文件类型图标
const fileTypeAvatar = (fileType) => {
let file_type_avatar = fileType_Files
if (fileType) {
if (fileType === 'ppt' || fileType === 'pptx') {
file_type_avatar = fileType_PPT
} else if (fileType === 'pdf') {
file_type_avatar = fileType_PDF
} else if (fileType === 'doc' || fileType === 'docx') {
file_type_avatar = fileType_WORD
} else if (fileType === 'xls' || fileType === 'xlsx') {
file_type_avatar = fileType_EXCEL
} else {
file_type_avatar = fileType_Files
}
}
return file_type_avatar
}
</script>
<style scoped lang="scss">
.search-by-date {
.search-date-picker {
padding: 20rpx 32rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
span {
line-height: 40rpx;
color: $theme-hint-text;
}
img {
width: 18rpx;
height: 11rpx;
margin: 0 0 0 26rpx;
}
}
}
body::v-deep .text-overflow-1 {
color: #666666 !important;
line-height: 44rpx !important;
font-size: 32rpx !important;
font-weight: bold !important;
}
body::v-deep .tmicon-times-circle-fill {
width: 37rpx;
height: 37rpx;
}
body::v-deep .round-3 {
background: linear-gradient(to right, #674bbc, #46299d);
}
.search-by-condition-input-list {
padding: 20rpx 48rpx 0 42rpx;
.search-by-condition-input {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.search-by-condition-input-text {
flex-shrink: 0;
margin: 0 0 0 20rpx;
color: $theme-primary;
}
}
.search-by-condition-list {
.condition-dimensionality {
.condition-dimensionality-each {
.condition-dimensionality-each-month {
padding: 24rpx 0 10rpx;
span {
line-height: 40rpx;
color: $theme-hint-text;
}
}
.condition-each-resultList {
.condition-each-resultList-each {
border-bottom: 1px solid $theme-border-color;
padding: 0 0 20rpx;
.condition-each-result-main {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.condition-each-result-main-date {
line-height: 34rpx;
color: $theme-hint-text;
}
}
.condition-each-result-attachments {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
padding: 24rpx 30rpx;
background-color: #f3f3f3;
border-radius: 8rpx;
.attachment-avatar {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
flex-shrink: 0;
img {
width: 96rpx;
height: 96rpx;
}
}
.attachment-info {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
margin: 0 0 0 22rpx;
.attachment-info-title {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
span {
line-height: 40rpx;
color: $theme-text;
}
}
.attachment-sub-info {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
span {
line-height: 34rpx;
color: $theme-hint-text;
word-break: break-all;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
}
}
.condition-type-imgAndVideo-result {
border-bottom: 0;
padding: 0;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
flex-wrap: wrap;
.condition-each-resultList-each {
.condition-result-imgAndVideo {
margin: 0 5rpx;
::v-deep .overflow {
width: 164rpx !important;
height: 164rpx !important;
}
.condition-result-imgAndVideo-area {
::v-deep .overflow {
width: 164rpx !important;
height: 164rpx !important;
}
::v-deep .round-0 {
width: 164rpx !important;
height: 164rpx !important;
}
}
}
}
}
}
}
}
}
</style>