add searchable

This commit is contained in:
Timi
2025-12-08 18:47:44 +08:00
parent 71fc077726
commit 00bcbf9e63
6 changed files with 243 additions and 68 deletions

View File

@ -2,6 +2,7 @@
import config from "../../config/index";
import { JournalPage, JournalPageType } from "../../types/Journal";
import Time from "../../utils/Time";
import Toolkit from "../../utils/Toolkit";
export type JournalListItem = {
id: number;
@ -16,9 +17,15 @@ interface JournalListData {
isFetching: boolean;
isFinished: boolean;
page: JournalPage;
searchValue: string;
}
Component({
// 组件实例类型扩展
interface ComponentInstance {
debouncedSearch?: ((keyword: string) => void) & { cancel(): void };
}
Component<JournalListData, {}, {}, ComponentInstance>({
options: {
styleIsolation: 'apply-shared'
},
@ -34,6 +41,14 @@ Component({
selectedId: {
type: Number,
value: undefined
},
searchable: {
type: Boolean,
value: false // 是否显示搜索框
},
mode: {
type: String,
value: 'select' // 'select' 选择模式 或 'navigate' 跳转模式
}
},
data: <JournalListData>{
@ -44,27 +59,63 @@ Component({
index: 0,
size: 16,
type: JournalPageType.PREVIEW
},
searchValue: ""
},
lifetimes: {
ready() {
// 创建防抖搜索函数
this.debouncedSearch = Toolkit.debounce(
(keyword: string) => {
this.resetAndSearch(keyword);
},
false, // 不立即执行,等待输入停止
400 // 400ms 延迟
);
// 组件加载时就获取数据
this.fetch();
},
detached() {
// 组件销毁时取消防抖
if (this.debouncedSearch) {
this.debouncedSearch.cancel();
}
}
},
observers: {
'visible': function(visible: boolean) {
// visible 从 false 变为 true 时,如果还没有数据则加载
if (visible && this.data.list.length === 0) {
this.fetch();
}
},
'type': function() {
this.resetPage();
}
},
methods: {
resetPage() {
const likeExample = this.data.searchValue ? {
idea: this.data.searchValue,
location: this.data.searchValue
} : undefined;
const equalsExample = this.properties.type ? {
type: this.properties.type
} : undefined;
this.setData({
page: {
index: 0,
size: 16,
type: JournalPageType.PREVIEW
type: JournalPageType.PREVIEW,
equalsExample,
likeExample
},
list: [],
isFinished: false
});
}
},
methods: {
},
fetch() {
if (this.data.isFetching || this.data.isFinished) {
return;
@ -88,7 +139,7 @@ Component({
const firstThumb = journal.items.find((item: any) => item.attachType === "THUMB");
return {
id: journal.id,
date: Time.toPassedDateTime(journal.createdAt),
date: Time.toPassedDate(journal.createdAt),
idea: journal.idea,
location: journal.location,
thumbUrl: firstThumb ? `${config.url}/attachment/read/${firstThumb.mongoId}` : undefined
@ -108,9 +159,70 @@ Component({
}
});
},
onSearchChange(e: WechatMiniprogram.CustomEvent) {
const value = e.detail.value.trim();
this.setData({ searchValue: value });
// 如果是清空操作不使用防抖clear 事件会处理)
if (value === "" && this.debouncedSearch) {
this.debouncedSearch.cancel();
return;
}
// 使用防抖自动搜索
if (this.debouncedSearch) {
this.debouncedSearch(value);
}
},
onSearchSubmit(e: WechatMiniprogram.CustomEvent) {
const value = e.detail.value.trim();
// 立即搜索,取消防抖
if (this.debouncedSearch) {
this.debouncedSearch.cancel();
}
this.resetAndSearch(value);
},
onSearchClear() {
// 取消防抖,立即搜索
if (this.debouncedSearch) {
this.debouncedSearch.cancel();
}
this.resetAndSearch("");
},
resetAndSearch(keyword: string) {
const likeExample = keyword ? {
idea: keyword,
location: keyword
} : undefined;
const equalsExample = this.properties.type ? {
type: this.properties.type
} : undefined;
this.setData({
searchValue: keyword,
list: [],
page: {
index: 0,
size: 16,
type: JournalPageType.PREVIEW,
equalsExample,
likeExample
},
isFetching: false,
isFinished: false
}, () => {
// 无论是否有搜索词,都重新获取列表
this.fetch();
});
},
onSelectItem(e: WechatMiniprogram.BaseEvent) {
const { id } = e.currentTarget.dataset;
this.triggerEvent('select', { id });
if (this.properties.mode === 'navigate') {
// 跳转模式:触发 navigate 事件
this.triggerEvent('navigate', { id });
} else {
// 选择模式:触发 select 事件
this.triggerEvent('select', { id });
}
},
onScrollToLower() {
this.fetch();