149 lines
4.0 KiB
JavaScript
149 lines
4.0 KiB
JavaScript
// pages/wiki/index.js
|
|
import { MOCK_WIKI } from '../../utils/mockData';
|
|
|
|
Page({
|
|
data: {
|
|
// Data Source (effectively the backend result)
|
|
filteredSourceList: [],
|
|
|
|
// Display Data (rendered list)
|
|
displayedList: [],
|
|
|
|
// Filter State
|
|
searchQuery: '',
|
|
activeCategory: '全部',
|
|
|
|
// Pagination State
|
|
page: 1,
|
|
pageSize: 5,
|
|
isLoading: false,
|
|
hasMore: true,
|
|
|
|
// Modal State
|
|
showIdentifyModal: false
|
|
},
|
|
|
|
onLoad() {
|
|
// Initial Load
|
|
this.filterList();
|
|
},
|
|
|
|
onShow() {
|
|
if (typeof this.getTabBar === 'function' &&
|
|
this.getTabBar()) {
|
|
this.getTabBar().setData({ selected: 3 });
|
|
}
|
|
},
|
|
|
|
// Search Input Handler
|
|
onSearchInput(e) {
|
|
this.setData({ searchQuery: e.detail.value }, () => {
|
|
this.filterList();
|
|
});
|
|
},
|
|
|
|
// Category Filter Handler
|
|
setCategory(e) {
|
|
this.setData({ activeCategory: e.currentTarget.dataset.cat }, () => {
|
|
this.filterList();
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Simulates "Backend" Search & Filtering
|
|
* Resets pagination and prepares the filtered data source.
|
|
*/
|
|
filterList() {
|
|
const { searchQuery, activeCategory } = this.data;
|
|
let result = MOCK_WIKI;
|
|
|
|
// Filter by Search Query
|
|
if (searchQuery) {
|
|
const q = searchQuery.toLowerCase();
|
|
result = result.filter(item =>
|
|
item.name.toLowerCase().includes(q) ||
|
|
item.scientificName.toLowerCase().includes(q)
|
|
);
|
|
}
|
|
|
|
// Filter by Category
|
|
if (activeCategory !== '全部') {
|
|
result = result.filter(item => item.category.includes(activeCategory));
|
|
}
|
|
|
|
this.setData({
|
|
filteredSourceList: result,
|
|
displayedList: [],
|
|
page: 1,
|
|
hasMore: true
|
|
}, () => {
|
|
this.loadMoreData();
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Simulates "Backend" Pagination
|
|
* Appends the next page of data from filteredSourceList to displayedList.
|
|
* key-value data path update is used for performance optimization.
|
|
*/
|
|
loadMoreData() {
|
|
const { isLoading, hasMore, page, pageSize, filteredSourceList, displayedList } = this.data;
|
|
|
|
if (isLoading || !hasMore) return;
|
|
|
|
this.setData({ isLoading: true });
|
|
|
|
// Simulate Network Delay
|
|
setTimeout(() => {
|
|
const startIndex = (page - 1) * pageSize;
|
|
const endIndex = startIndex + pageSize;
|
|
const newItems = filteredSourceList.slice(startIndex, endIndex);
|
|
|
|
const isLastPage = endIndex >= filteredSourceList.length;
|
|
|
|
if (newItems.length > 0) {
|
|
// Performance Optimization: Use data path to append items
|
|
// Instead of setData({ displayedList: [...old, ...new] })
|
|
const updateData = {};
|
|
const currentLen = displayedList.length;
|
|
newItems.forEach((item, index) => {
|
|
updateData[`displayedList[${currentLen + index}]`] = item;
|
|
});
|
|
|
|
updateData['page'] = page + 1;
|
|
updateData['hasMore'] = !isLastPage;
|
|
updateData['isLoading'] = false;
|
|
|
|
this.setData(updateData);
|
|
} else {
|
|
this.setData({
|
|
hasMore: false,
|
|
isLoading: false
|
|
});
|
|
}
|
|
}, 500);
|
|
},
|
|
|
|
// Infinite Scroll Handler
|
|
onReachBottom() {
|
|
this.loadMoreData();
|
|
},
|
|
|
|
goToDetail(e) {
|
|
const item = e.currentTarget.dataset.item;
|
|
wx.navigateTo({
|
|
url: `/pages/wiki/detail/index?id=${item.id}`
|
|
});
|
|
},
|
|
|
|
openIdentifyModal() { this.setData({ showIdentifyModal: true }); },
|
|
|
|
onPopupVisibleChange(e) {
|
|
this.setData({
|
|
showIdentifyModal: e.detail.visible
|
|
});
|
|
},
|
|
|
|
closeIdentifyModal() { this.setData({ showIdentifyModal: false }); }
|
|
})
|