455 lines
11 KiB
Vue
455 lines
11 KiB
Vue
<template>
|
|
<view class="searchhis-page">
|
|
<!-- 搜索框 -->
|
|
<search-box
|
|
v-model="searchText"
|
|
placeholder="输入手艺人/服务/店铺等"
|
|
@search="onSearch"
|
|
@confirm="onSearch"
|
|
/>
|
|
|
|
<view class="history_content">
|
|
<!-- 历史搜索 -->
|
|
<view class="history-section">
|
|
<view class="section-header">
|
|
<view class="header-left">
|
|
<text class="section-title">历史搜索</text>
|
|
</view>
|
|
<view v-if="isDel" class="del_select">
|
|
<view @click="showConfirmModal = true" class="allDel"
|
|
>全部删除</view
|
|
>
|
|
<image
|
|
class="split"
|
|
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/35ec857d-02c6-41e1-b6e9-fea885625743"
|
|
/>
|
|
<view class="allDel" @click="isDel = false">完成</view>
|
|
</view>
|
|
<view v-else class="header-right" @click="isDel = true">
|
|
<image
|
|
class="delete-icon"
|
|
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/e454c821-7fb3-4c89-8cc4-e7771361985b"
|
|
></image>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 标签分类 -->
|
|
<view class="category-section">
|
|
<view
|
|
class="history-list history_list history_cau"
|
|
v-if="historyList.length"
|
|
>
|
|
<view v-for="item in historyList" class="history-item history_item">
|
|
<text class="history-text text-overflow-1">{{ item }}</text>
|
|
</view>
|
|
</view>
|
|
<!-- 历史记录列表 -->
|
|
<view
|
|
class="history-list history_list history_list_show"
|
|
v-if="historyList.length"
|
|
>
|
|
<view
|
|
v-for="(item, index) in showHistoryList"
|
|
class="history-item"
|
|
@click="selectHistory(item)"
|
|
>
|
|
<text class="history-text text-overflow-1">{{ item }}</text>
|
|
<image
|
|
@click="removeHistory(index)"
|
|
v-if="isDel"
|
|
class="delIcon"
|
|
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/9cc3f293-80ca-41ab-b964-90e144fcdcfb"
|
|
/>
|
|
</view>
|
|
<view
|
|
v-if="!isDel && !isMore && this.historyList.length > this.maxNum"
|
|
class="history-item del_tag"
|
|
style="padding: 0"
|
|
@click="isMore = true"
|
|
>
|
|
<image
|
|
class="moreIcon"
|
|
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/201c503d-ed9e-4090-9f14-1f6ffdabcc93"
|
|
/>
|
|
</view>
|
|
</view>
|
|
<view class="history-null" v-else>暂无搜索历史</view>
|
|
</view>
|
|
|
|
<!-- 热门搜索 -->
|
|
<view class="history-section" style="margin-top: 40rpx">
|
|
<view class="section-header">
|
|
<view class="header-left">
|
|
<text class="section-title">热门搜索</text>
|
|
</view>
|
|
<view class="header-right" @click="getHotList">
|
|
<image
|
|
class="delete-icon"
|
|
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/22482af8-2036-411a-b7f7-f7dbf76441a0"
|
|
></image>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 标签分类 -->
|
|
<view class="category-section">
|
|
<!-- 历史记录列表 -->
|
|
<view class="history-list" v-if="hotList.length">
|
|
<view
|
|
v-for="(item, index) in hotList"
|
|
:key="index"
|
|
class="history-item"
|
|
@click="selectHistory(item)"
|
|
>
|
|
<text class="history-text text-overflow-1">{{ item }}</text>
|
|
</view>
|
|
</view>
|
|
<view class="history-null" v-else>暂无热门搜索</view>
|
|
</view>
|
|
</view>
|
|
<confirm-modal
|
|
:visible="showConfirmModal"
|
|
title="确认删除最近搜索记录吗?"
|
|
cancel-text="取消"
|
|
confirm-text="删除"
|
|
@cancel="showConfirmModal = false"
|
|
@confirm="clearHistory"
|
|
/>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import confirmModal from "./components/confirm-modal.vue";
|
|
import searchBox from "./components/search-box.vue";
|
|
import request from "../../utils/request";
|
|
export default {
|
|
components: {
|
|
searchBox,
|
|
confirmModal,
|
|
},
|
|
data() {
|
|
return {
|
|
searchText: "",
|
|
historyList: [],
|
|
hotList: [],
|
|
isMore: false,
|
|
isDel: false,
|
|
maxNum: 20,
|
|
showConfirmModal: false, // 控制自定义弹窗的显示
|
|
};
|
|
},
|
|
mounted() {},
|
|
async onShow() {
|
|
this.uploadHistory();
|
|
this.getHotList();
|
|
this.updateMaxNum();
|
|
},
|
|
watch: {
|
|
isDel(nVal) {
|
|
if (!nVal) {
|
|
this.updateMaxNum();
|
|
}
|
|
},
|
|
},
|
|
computed: {
|
|
showHistoryList() {
|
|
if (this.isMore || this.isDel) {
|
|
return this.historyList.slice(0, 20);
|
|
} else {
|
|
return this.historyList.slice(
|
|
0,
|
|
this.historyList.length > this.maxNum ? this.maxNum : 20
|
|
);
|
|
}
|
|
},
|
|
},
|
|
methods: {
|
|
updateMaxNum() {
|
|
this.$nextTick(async () => {
|
|
if (!this.historyList.length) return;
|
|
const count = await this.calculateTwoRowsItems();
|
|
this.maxNum = count;
|
|
});
|
|
},
|
|
async calculateTwoRowsItems() {
|
|
|
|
return new Promise(async (resolve) => {
|
|
const containerRect = await new Promise((res) => {
|
|
uni
|
|
.createSelectorQuery()
|
|
.in(this)
|
|
.select(".history_list_show")
|
|
.boundingClientRect(res)
|
|
.exec();
|
|
});
|
|
|
|
if (!containerRect) {
|
|
resolve(0);
|
|
return;
|
|
}
|
|
const containerWidth = containerRect.width + 10;
|
|
const itemRects = await new Promise((res) => {
|
|
uni
|
|
.createSelectorQuery()
|
|
.in(this)
|
|
.selectAll(".history_item")
|
|
.boundingClientRect(res)
|
|
.exec();
|
|
});
|
|
console.log(itemRects,'zzz')
|
|
|
|
if (!itemRects || itemRects.length === 0) {
|
|
resolve(0);
|
|
return;
|
|
}
|
|
// 提取所有 item 的宽度(过滤无效值)
|
|
const itemWidths = itemRects
|
|
.map((rect) => rect?.width || 0)
|
|
.filter((w) => w > 0);
|
|
const horizontalGap = 10; // 假设 item 之间的水平间距为 10rpx
|
|
let currentRowWidth = 0; // 当前行已占用宽度
|
|
let rowCount = 1; // 当前行数(从 1 开始)
|
|
let totalItems = 0; // 总数量
|
|
|
|
for (const width of itemWidths) {
|
|
// 计算当前 item 加入后的总宽度(含间距)
|
|
const requiredWidth =
|
|
currentRowWidth + width + (currentRowWidth > 0 ? horizontalGap : 0);
|
|
|
|
if (requiredWidth <= containerWidth) {
|
|
// 能放入当前行
|
|
currentRowWidth = requiredWidth;
|
|
totalItems++;
|
|
} else {
|
|
// 超出当前行,换行
|
|
rowCount++;
|
|
if (rowCount > 2) {
|
|
// 超过两行,停止计算
|
|
break;
|
|
}
|
|
// 放入新行
|
|
currentRowWidth = width;
|
|
totalItems++;
|
|
}
|
|
}
|
|
console.log(
|
|
currentRowWidth,
|
|
containerWidth,
|
|
totalItems,
|
|
itemWidths.length,
|
|
currentRowWidth + itemRects[0].height < containerWidth
|
|
);
|
|
|
|
if (
|
|
totalItems === itemWidths.length ||
|
|
currentRowWidth + itemRects[0].height + 10 < containerWidth
|
|
) {
|
|
resolve(totalItems);
|
|
} else {
|
|
resolve(totalItems - 1);
|
|
}
|
|
});
|
|
},
|
|
getHotList() {
|
|
request
|
|
.post("/user/AppSearchLog/list", { page: 1, limit: 20 })
|
|
.then((res) => {
|
|
console.log(res.data.list, "res.data.list");
|
|
this.hotList = res.data.list.map((it) => it.search_val);
|
|
});
|
|
},
|
|
openMore() {},
|
|
uploadHistory() {
|
|
let that = this;
|
|
that.historyList = uni.getStorageSync("historyList") || [];
|
|
},
|
|
removeHistory(index, value) {
|
|
const list = this.historyList.filter((_, i) => {
|
|
if (index === i) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
});
|
|
if (value) {
|
|
list.unshift(value);
|
|
}
|
|
this.historyList = list;
|
|
uni.setStorageSync("historyList", list);
|
|
},
|
|
onSearch() {
|
|
let that = this;
|
|
if (!that.searchText.trim()) return;
|
|
// 添加到历史记录
|
|
let i = that.historyList.indexOf(that.searchText);
|
|
setTimeout(() => {
|
|
if (i != -1) {
|
|
this.removeHistory(i, that.searchText);
|
|
} else {
|
|
this.historyList = [that.searchText, ...this.historyList];
|
|
uni.setStorageSync("historyList", this.historyList);
|
|
}
|
|
}, 200);
|
|
// TODO: 执行搜索
|
|
uni.navigateTo({
|
|
url: `/pages/search/search-result?searchText=${this.searchText}`,
|
|
});
|
|
},
|
|
selectHistory(item) {
|
|
if (this.isDel) return;
|
|
let that = this;
|
|
that.searchText = item;
|
|
that.onSearch();
|
|
},
|
|
clearHistory() {
|
|
this.isDel = false;
|
|
this.showConfirmModal = false;
|
|
let that = this;
|
|
that.historyList = [];
|
|
that.haveHistory = false;
|
|
uni.removeStorageSync("historyList");
|
|
},
|
|
},
|
|
onLoad() {
|
|
// 从本地存储加载历史记录
|
|
try {
|
|
const history = uni.getStorageSync("searchHistory");
|
|
if (history) {
|
|
this.historyList = JSON.parse(history);
|
|
}
|
|
} catch (e) {
|
|
console.error("Failed to load search history:", e);
|
|
}
|
|
},
|
|
onUnload() {
|
|
// 保存历史记录到本地存储
|
|
try {
|
|
uni.setStorageSync("searchHistory", JSON.stringify(this.historyList));
|
|
} catch (e) {
|
|
console.error("Failed to save search history:", e);
|
|
}
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.del_select {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 18rpx;
|
|
font-size: 26rpx;
|
|
color: #999999;
|
|
.split {
|
|
width: 2rpx;
|
|
height: 24rpx;
|
|
}
|
|
}
|
|
|
|
.history_content {
|
|
background-color: #fff;
|
|
height: 100%;
|
|
padding: 24rpx 30rpx;
|
|
}
|
|
|
|
.searchhis-page {
|
|
background-color: #f2f4f7;
|
|
/* #ifdef APP-PLUS */
|
|
padding-top: var(--status-bar-height);
|
|
/* #endif */
|
|
height: 100vh;
|
|
overflow: hidden;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.history-section {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.header-left {
|
|
flex-direction: row;
|
|
align-items: center;
|
|
}
|
|
|
|
.clock-icon {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
margin-right: 20rpx;
|
|
}
|
|
|
|
.section-title {
|
|
font-weight: 500;
|
|
font-size: 30rpx;
|
|
color: #333333;
|
|
}
|
|
|
|
.delete-icon {
|
|
width: 26rpx;
|
|
height: 26rpx;
|
|
}
|
|
|
|
.category-section {
|
|
}
|
|
|
|
.category-title {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.history-list {
|
|
margin-top: 20rpx;
|
|
display: flex;
|
|
flex-flow: row wrap;
|
|
gap: 10rpx;
|
|
margin-right: 50rpx;
|
|
}
|
|
|
|
.history-item {
|
|
max-width: 400rpx;
|
|
font-size: 24rpx;
|
|
color: #5b5b5b;
|
|
padding: 12rpx 24rpx;
|
|
background: #f6f5f7;
|
|
border-radius: 29rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 57rpx;
|
|
min-width: 57rpx;
|
|
box-sizing: border-box;
|
|
gap: 12rpx;
|
|
.delIcon {
|
|
width: 13rpx;
|
|
height: 13rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
}
|
|
|
|
.history-text {
|
|
width: 100%;
|
|
}
|
|
.moreIcon {
|
|
width: 15rpx;
|
|
height: 9rpx;
|
|
}
|
|
.history-null {
|
|
padding-top: 20rpx;
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
box-sizing: border-box;
|
|
}
|
|
.history_cau {
|
|
position: absolute;
|
|
right: -100000rpx;
|
|
z-index: -100;
|
|
visibility: hidden;
|
|
}
|
|
</style>
|