// 搜索用户页面 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` }); } });