findme-miniprogram-frontend/subpackages/social/search/search.js
2025-12-27 17:16:03 +08:00

438 lines
11 KiB
JavaScript
Raw Permalink 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.

// 搜索用户页面
const app = getApp();
const friendAPI = require('../../../utils/friend-api.js');
Page({
data: {
// 搜索相关
searchKeyword: '',
searchResults: [],
loading: false,
hasSearched: false,
// 搜索类型
searchType: 'all', // all, nickname, custom_id, phone
searchTypes: [
{ value: 'all', label: '全部' },
{ value: 'nickname', label: '昵称' },
{ value: 'custom_id', label: 'ID' },
{ value: 'phone', label: '手机号' }
],
// 分页
currentPage: 1,
pageSize: 20,
hasMore: true,
// 系统信息
statusBarHeight: 0,
navBarHeight: 0,
scanningUser: false,
scanCache: {} // { customId: { timestamp, relationStatus } }
},
// 扫一扫二维码(识别 FINDME 格式并跳转)
scanQRCode() {
wx.scanCode({
onlyFromCamera: false,
success: async (res) => {
const scanResult = res.result || '';
// 解析 FINDME 格式FINDME:customId
if (scanResult.startsWith('FINDME:')) {
const customId = scanResult.replace('FINDME:', '').trim();
// 检查是否是好友关系
this.checkFriendRelationFromScan(customId);
} else {
wx.showToast({
title: '无法识别二维码内容',
icon: 'none',
duration: 2000
});
}
},
fail: (err) => {
// 用户取消不提示错误
if (err.errMsg && !err.errMsg.includes('cancel')) {
wx.showToast({
title: '扫码失败,请重试',
icon: 'none'
});
}
}
});
},
// 检查好友关系(从扫码调用)
async checkFriendRelationFromScan(customId) {
if (this.data.scanningUser) return;
this.setData({ scanningUser: true });
wx.showLoading({ title: '加载中...', mask: true });
const friendDetailResponse = await friendAPI.getFriendDetail(customId).catch(() => null);
wx.hideLoading();
const isFriend = friendDetailResponse?.code === 0 && friendDetailResponse?.data;
this.setData({ scanningUser: false });
this.navigateToUserDetail(customId, isFriend);
},
// 跳转到用户详情页面
navigateToUserDetail(customId, isFriend = false) {
const url = isFriend
? `/subpackages/social/friend-detail/friend-detail?customId=${customId}`
: `/subpackages/social/user-preview/user-preview?customId=${customId}`;
wx.navigateTo({
url: url,
fail: (err) => {
console.error('跳转失败:', err);
wx.showToast({ title: '跳转失败,请重试', icon: 'none' });
}
});
},
async fetchScannedUserBasicInfo(customId) {
try {
// 使用精确ID搜索
const resp = await friendAPI.searchUsers(customId, 'custom_id', 1, 1);
const users = resp?.data?.users || [];
const user = users[0];
wx.hideLoading();
if (!user) {
wx.showToast({ title: '用户不存在', icon: 'none' });
this.setData({ scanningUser: false });
return;
}
// 非好友:跳转预览页面
this.setData({ scanningUser: false });
wx.navigateTo({
url: `/subpackages/social/user-preview/user-preview?customId=${customId}`,
fail: (err) => {
console.warn('navigateTo user-preview 失败,尝试 redirectTo:', err);
wx.redirectTo({ url: `/subpackages/social/user-preview/user-preview?customId=${customId}` });
}
});
} catch (error) {
wx.hideLoading();
console.error('查询用户失败:', error);
wx.showToast({ title: '查询失败', icon: 'none' });
this.setData({ scanningUser: false });
}
},
handleGenericScan(raw) {
wx.showModal({
title: '二维码内容',
content: raw.length > 200 ? raw.slice(0,200) + '...' : raw,
showCancel: false
});
},
onLoad(options) {
this.initSystemInfo();
// 如果有传入的搜索关键词,直接搜索
if (options.keyword) {
this.setData({
searchKeyword: decodeURIComponent(options.keyword)
});
this.performSearch();
}
},
// 初始化系统信息
initSystemInfo() {
try {
// 使用新的API替代已弃用的wx.getSystemInfoSync
const windowInfo = wx.getWindowInfo();
const menuButton = wx.getMenuButtonBoundingClientRect();
const statusBarHeight = windowInfo.statusBarHeight || 0;
// 使用更紧凑的高度:状态栏
const navBarHeight = statusBarHeight;
this.setData({
statusBarHeight,
navBarHeight
});
} catch (error) {
console.error('获取系统信息失败,使用兜底方案:', error);
// 兜底方案
try {
const systemInfo = wx.getSystemInfoSync();
const statusBarHeight = systemInfo.statusBarHeight || 0;
const navBarHeight = statusBarHeight + 36;
this.setData({
statusBarHeight,
navBarHeight
});
} catch (fallbackError) {
console.error('兜底方案也失败了:', fallbackError);
// 设置默认值
this.setData({
statusBarHeight: 20,
navBarHeight: 56
});
}
}
},
// 返回上一页
// 已移除自定义返回按钮,使用小程序自带返回
// 搜索输入
onSearchInput(e) {
this.setData({
searchKeyword: e.detail.value
});
if(!(e.detail.value)){
this.clearSearch()
}
},
// 搜索确认
onSearchConfirm() {
this.performSearch();
},
// 清空搜索
clearSearch() {
this.setData({
searchKeyword: '',
searchResults: [],
hasSearched: false,
currentPage: 1,
hasMore: true
});
},
// 切换搜索类型
onSearchTypeChange(e) {
const searchType = e.currentTarget.dataset.type;
this.setData({
searchType
});
if (this.data.searchKeyword) {
this.performSearch();
}
},
// 执行搜索
async performSearch() {
const keyword = this.data.searchKeyword.trim();
if (!keyword) {
wx.showToast({
title: '请输入搜索关键词',
icon: 'none'
});
return;
}
// 基于搜索类型的输入校验
const { searchType } = this.data;
if (searchType === 'custom_id') {
// ID: 1-20位纯数字
if (!/^\d{1,20}$/.test(keyword)) {
wx.showToast({
title: 'ID需为1-20位纯数字',
icon: 'none'
});
return;
}
} else if (searchType === 'phone') {
// 手机号11位数字
if (!/^\d{11}$/.test(keyword)) {
wx.showToast({
title: '手机号需为11位数字',
icon: 'none'
});
return;
}
}
this.setData({
loading: true,
currentPage: 1,
searchResults: [],
hasMore: true
});
try {
const response = await friendAPI.searchUsers(
keyword,
this.data.searchType,
1,
this.data.pageSize
);
// 根据正确的接口文档处理API响应结构
const searchData = response.data || {};
const users = searchData.users || [];
const total = searchData.total || 0;
this.setData({
searchResults: users,
hasSearched: true,
hasMore: users.length >= this.data.pageSize && this.data.currentPage * this.data.pageSize < total,
loading: false
});
if (users.length === 0) {
wx.showToast({
title: '未找到相关用户',
icon: 'none'
});
}
} catch (error) {
console.error('搜索失败:', error);
this.setData({
loading: false,
hasSearched: true
});
wx.showToast({
title: error.message || '搜索失败',
icon: 'none'
});
}
},
// 加载更多
async loadMore() {
if (!this.data.hasMore || this.data.loading) return;
this.setData({ loading: true });
try {
const response = await friendAPI.searchUsers(
this.data.searchKeyword,
this.data.searchType,
this.data.currentPage + 1,
this.data.pageSize
);
const searchData = response.data || {};
const newUsers = searchData.users || [];
const total = searchData.total || 0;
const newResults = [...this.data.searchResults, ...newUsers];
this.setData({
searchResults: newResults,
currentPage: this.data.currentPage + 1,
hasMore: newResults.length < total,
loading: false
});
} catch (error) {
console.error('加载更多失败:', error);
this.setData({ loading: false });
}
},
// 添加好友
async addFriend(e) {
const { customId, nickname } = e.currentTarget.dataset;
try {
// 显示输入框让用户输入验证消息
const result = await this.showAddFriendDialog(nickname);
if (!result.confirm) return;
wx.showLoading({ title: '发送中...' });
// 输入阶段已限制50字这里仅做去空白
const safeMessage = (result.message || '').trim();
await friendAPI.addFriend(customId, safeMessage);
wx.hideLoading();
wx.showToast({
title: '好友请求已发送',
icon: 'success'
});
// 更新按钮状态
const updatedResults = this.data.searchResults.map(user => {
if (user.customId === customId) {
return {
...user,
relationStatus: 'pending',
actionText: '等待验证',
canAddFriend: false
};
}
return user;
});
this.setData({
searchResults: updatedResults
});
} catch (error) {
wx.hideLoading();
console.error('添加好友失败:', error);
wx.showToast({
title: error.message || '添加好友失败',
icon: 'none'
});
}
},
// 显示添加好友对话框
showAddFriendDialog(nickname) {
return new Promise((resolve) => {
try {
// 默认文案
const selfNick = app.globalData?.userInfo?.user?.nickname || '';
const base = `我是 ${selfNick}`;
this._addDialogResolve = resolve; // 存到实例属性,避免放到 data
this.setData({
addDialogVisible: true,
addDialogNickname: nickname || '',
addDialogMessage: base
});
} catch (e) {
console.error('打开添加好友对话框失败', e);
resolve({ confirm: false });
}
});
},
// 对话框输入变更(已在组件层 maxlength=50 限制)
onAddDialogInput(e) {
const value = (e.detail.value || '').slice(0, 50);
this.setData({ addDialogMessage: value });
},
// 取消添加
onAddDialogCancel() {
try { this.setData({ addDialogVisible: false }); } catch (_) {}
if (this._addDialogResolve) {
this._addDialogResolve({ confirm: false });
this._addDialogResolve = null;
}
},
// 确认添加
onAddDialogConfirm() {
const msg = (this.data.addDialogMessage || '').trim();
try { this.setData({ addDialogVisible: false }); } catch (_) {}
if (this._addDialogResolve) {
this._addDialogResolve({ confirm: true, message: msg });
this._addDialogResolve = null;
}
},
// 发送消息
sendMessage(e) {
const { customId, nickname } = e.currentTarget.dataset;
wx.navigateTo({
url: `/pages/message/chat/chat?targetId=${customId}&name=${encodeURIComponent(nickname)}&chatType=0`
});
}
});