消息
This commit is contained in:
2
TUIKit/components/TUISearch/search-container/index.ts
Normal file
2
TUIKit/components/TUISearch/search-container/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import SearchContainer from './index.vue';
|
||||
export default SearchContainer;
|
||||
259
TUIKit/components/TUISearch/search-container/index.vue
Normal file
259
TUIKit/components/TUISearch/search-container/index.vue
Normal file
@@ -0,0 +1,259 @@
|
||||
<template>
|
||||
<div
|
||||
:class="[
|
||||
'tui-search-container',
|
||||
!isPC && 'tui-search-container-h5',
|
||||
isPC && `container-${props.popupPosition}`,
|
||||
`container-${props.searchType}`,
|
||||
]"
|
||||
>
|
||||
<div
|
||||
:class="[
|
||||
isPC && `tui-search-container-${props.popupPosition}`,
|
||||
!isPC && 'tui-search-container-h5-main',
|
||||
]"
|
||||
>
|
||||
<div
|
||||
v-if="props.searchType === 'conversation' && !isUniFrameWork"
|
||||
class="tui-search-header"
|
||||
>
|
||||
<div class="tui-search-header-title">
|
||||
{{ TUITranslateService.t("TUISearch.搜索会话内容") }}
|
||||
</div>
|
||||
<div
|
||||
class="tui-search-header-close"
|
||||
@click="closeSearchContainer"
|
||||
>
|
||||
<Icon
|
||||
:file="closeDarkIcon"
|
||||
width="14px"
|
||||
height="14px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tui-search-tabs">
|
||||
<div
|
||||
v-for="(tabItem, tabKey) in searchTypeList"
|
||||
:key="tabKey"
|
||||
:class="[
|
||||
'tui-search-tabs-item',
|
||||
currentSearchMessageType.key === tabItem.key && 'tui-search-tabs-item-selected',
|
||||
]"
|
||||
@click="selectSearchType(tabItem)"
|
||||
>
|
||||
{{ TUITranslateService.t(`TUISearch.${tabItem.label}`) }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- TUISearch search input slot -->
|
||||
<slot name="input" />
|
||||
<div
|
||||
v-if="isTimeTabsShow"
|
||||
class="tui-search-time"
|
||||
>
|
||||
<div
|
||||
v-for="(tabItem, tabKey) in searchMessageTimeList"
|
||||
:key="tabKey"
|
||||
:class="[
|
||||
'tui-search-time-item',
|
||||
currentSearchMessageTime.key === tabItem.key && 'tui-search-time-item-selected',
|
||||
]"
|
||||
@click="selectSearchTime(tabItem)"
|
||||
>
|
||||
<div
|
||||
v-if="tabItem.key === 'all'"
|
||||
class="tui-search-time-item-picker"
|
||||
>
|
||||
<div
|
||||
v-if="!isDatePickerShow"
|
||||
class="tui-search-time-item-all"
|
||||
@click.stop="handleSelectAllTimeClicked"
|
||||
>
|
||||
{{
|
||||
TUITranslateService.t(`TUISearch.选择时间`) +
|
||||
": " +
|
||||
TUITranslateService.t(`TUISearch.全部`)
|
||||
}}
|
||||
<Icon
|
||||
:file="downArrowIcon"
|
||||
width="14px"
|
||||
height="14px"
|
||||
/>
|
||||
</div>
|
||||
<div @click.stop>
|
||||
<DatePicker
|
||||
v-if="isDatePickerShow"
|
||||
type="range"
|
||||
:rangeTableType="datePickerRangeDisplayType"
|
||||
@pick="pickTimePeriod"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="isDatePickerShow"
|
||||
class="tui-search-time-item-close"
|
||||
@click="clearTimePicker"
|
||||
>
|
||||
<Icon
|
||||
class="icon"
|
||||
:file="closeIcon"
|
||||
width="14px"
|
||||
height="14px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ TUITranslateService.t(`TUISearch.${tabItem.label}`) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- TUISearch search result slot -->
|
||||
<slot name="result" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted } from '../../../adapter-vue';
|
||||
import {
|
||||
TUITranslateService,
|
||||
TUIStore,
|
||||
StoreName,
|
||||
} from '@tencentcloud/chat-uikit-engine';
|
||||
import { Dayjs } from 'dayjs';
|
||||
import {
|
||||
globalSearchTypeList,
|
||||
conversationSearchTypeList,
|
||||
searchMessageTypeDefault,
|
||||
} from '../search-type-list';
|
||||
import { searchMessageTimeList, searchMessageTimeDefault } from '../search-time-list';
|
||||
import Icon from '../../common/Icon.vue';
|
||||
import DatePicker from '../../common/DatePicker/index.vue';
|
||||
import downArrowIcon from '../../../assets/icon/down-icon.svg';
|
||||
import closeIcon from '../../../assets/icon/input-close.svg';
|
||||
import closeDarkIcon from '../../../assets/icon/close-dark.svg';
|
||||
import { isPC, isUniFrameWork } from '../../../utils/env';
|
||||
import { SEARCH_TYPE, ISearchMessageTime, ISearchMessageType, ISearchTimeTab, ISearchTypeTab } from '../type';
|
||||
|
||||
const props = defineProps({
|
||||
popupPosition: {
|
||||
type: String, // "bottom" / "aside"
|
||||
default: 'bottom',
|
||||
},
|
||||
searchType: {
|
||||
type: String,
|
||||
default: 'global', // "global" / "conversation"
|
||||
validator(value: string) {
|
||||
return ['global', 'conversation'].includes(value);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['searchConfigChange', 'closeInConversationSearch']);
|
||||
|
||||
const searchTypeList = computed(() =>
|
||||
props?.searchType === 'conversation' ? conversationSearchTypeList : globalSearchTypeList,
|
||||
);
|
||||
const currentSearchMessageType = ref(searchMessageTypeDefault[props?.searchType as SEARCH_TYPE]);
|
||||
const currentSearchMessageTime = ref(searchMessageTimeDefault);
|
||||
|
||||
const isTimeTabsShow = computed(() => {
|
||||
return (
|
||||
currentSearchMessageType.value.key !== 'contact'
|
||||
&& currentSearchMessageType.value.key !== 'group'
|
||||
);
|
||||
});
|
||||
const datePickerRangeDisplayType = computed((): string =>
|
||||
isPC && props.searchType === 'global' && !isUniFrameWork ? 'two' : 'one',
|
||||
);
|
||||
const isDatePickerShow = ref<boolean>(false);
|
||||
|
||||
function onCurrentSearchMessageTypeChange(typeObject: ISearchMessageType) {
|
||||
if (typeObject?.searchType === props?.searchType) {
|
||||
currentSearchMessageType.value
|
||||
= typeObject?.value || searchMessageTypeDefault[props?.searchType as SEARCH_TYPE];
|
||||
}
|
||||
}
|
||||
|
||||
function onCurrentSearchMessageTimeChange(timeObject: ISearchMessageTime) {
|
||||
if (timeObject?.searchType === props?.searchType) {
|
||||
currentSearchMessageTime.value = timeObject?.value || searchMessageTimeDefault;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
TUIStore.watch(StoreName.SEARCH, {
|
||||
currentSearchMessageType: onCurrentSearchMessageTypeChange,
|
||||
currentSearchMessageTime: onCurrentSearchMessageTimeChange,
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
TUIStore.unwatch(StoreName.SEARCH, {
|
||||
currentSearchMessageType: onCurrentSearchMessageTypeChange,
|
||||
currentSearchMessageTime: onCurrentSearchMessageTimeChange,
|
||||
});
|
||||
});
|
||||
|
||||
const selectSearchType = (item: ISearchTypeTab) => {
|
||||
TUIStore.update(StoreName.SEARCH, 'currentSearchMessageType', {
|
||||
value: item,
|
||||
searchType: props.searchType,
|
||||
});
|
||||
};
|
||||
|
||||
const selectSearchTime = (item: ISearchTimeTab) => {
|
||||
if (isDatePickerShow.value && item.key === 'all') {
|
||||
isDatePickerShow.value = false;
|
||||
} else {
|
||||
isDatePickerShow.value = false;
|
||||
TUIStore.update(StoreName.SEARCH, 'currentSearchMessageTime', {
|
||||
value: item,
|
||||
searchType: props.searchType,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectAllTimeClicked = () => {
|
||||
if (currentSearchMessageTime.value?.key !== 'all') {
|
||||
TUIStore.update(StoreName.SEARCH, 'currentSearchMessageTime', {
|
||||
value: searchMessageTimeDefault,
|
||||
searchType: props.searchType,
|
||||
});
|
||||
} else {
|
||||
isDatePickerShow.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
const pickTimePeriod = (time: typeof Dayjs) => {
|
||||
if (currentSearchMessageTime.value?.key === 'all') {
|
||||
const { startDate, endDate } = time;
|
||||
const timePosition = Number((endDate?.toDate()?.getTime() / 1000).toFixed(0));
|
||||
const timePeriod = timePosition - Number((startDate?.toDate()?.getTime() / 1000).toFixed(0));
|
||||
const newSearchMessageTime = {
|
||||
key: currentSearchMessageTime.value.key,
|
||||
label: currentSearchMessageTime.value.label,
|
||||
value: {
|
||||
timePosition,
|
||||
timePeriod,
|
||||
},
|
||||
};
|
||||
TUIStore.update(StoreName.SEARCH, 'currentSearchMessageTime', {
|
||||
value: newSearchMessageTime,
|
||||
searchType: props.searchType,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const clearTimePicker = () => {
|
||||
isDatePickerShow.value = false;
|
||||
if (currentSearchMessageTime.value?.key === 'all') {
|
||||
TUIStore.update(StoreName.SEARCH, 'currentSearchMessageTime', {
|
||||
value: searchMessageTimeDefault,
|
||||
searchType: props.searchType,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const closeSearchContainer = () => {
|
||||
emits('closeInConversationSearch');
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped src="./style/index.scss"></style>
|
||||
36
TUIKit/components/TUISearch/search-container/style/h5.scss
Normal file
36
TUIKit/components/TUISearch/search-container/style/h5.scss
Normal file
@@ -0,0 +1,36 @@
|
||||
.tui-search-container-h5 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.tui-search-container-h5-main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.tui-search-tabs {
|
||||
.tui-search-tabs-item {
|
||||
cursor: none;
|
||||
}
|
||||
}
|
||||
|
||||
.tui-search-time {
|
||||
background-color: #f4f4f4;
|
||||
|
||||
.tui-search-time-item {
|
||||
cursor: none;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tui-search-time-item-selected {
|
||||
background-color: rgba(0,122,255,0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
@import '../../../../assets/styles/common';
|
||||
@import './web';
|
||||
@import './h5';
|
||||
114
TUIKit/components/TUISearch/search-container/style/web.scss
Normal file
114
TUIKit/components/TUISearch/search-container/style/web.scss
Normal file
@@ -0,0 +1,114 @@
|
||||
.container-bottom {
|
||||
margin: 0 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container-conversation {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tui-search-container {
|
||||
&-bottom {
|
||||
position: absolute;
|
||||
min-width: 400px;
|
||||
width: fit-content;
|
||||
height: 453px;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: rgba(0,0,0,0.16) 0 3px 6px, rgba(0,0,0,0.23) 0 3px 6px;
|
||||
left: 0;
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
&-aside {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tui-search-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 20px 10px;
|
||||
|
||||
&-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 19.6px;
|
||||
font-family: "PingFang SC", sans-serif;
|
||||
}
|
||||
|
||||
&-close {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.tui-search-tabs {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.1);
|
||||
|
||||
&-item {
|
||||
padding: 10px 0;
|
||||
margin: 0 10px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
|
||||
&-selected {
|
||||
color: #007aff;
|
||||
border-bottom: 2px solid #007aff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tui-search-time {
|
||||
width: 100%;
|
||||
height: 43px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
box-sizing: border-box;
|
||||
|
||||
&-item {
|
||||
height: calc(100% - 20px);
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
border-radius: 5px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&-picker {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-close,
|
||||
&-all {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-selected {
|
||||
background-color: rgba(0,122,255,0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user