commit 06961cae048c0da13033dbdd33599327075f3b30 Author: unknown Date: Sat Dec 27 17:16:03 2025 +0800 upload project diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..115cc02 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,31 @@ +/* + * Eslint config file + * Documentation: https://eslint.org/docs/user-guide/configuring/ + * Install the Eslint extension before using this feature. + */ +module.exports = { + env: { + es6: true, + browser: true, + node: true, + }, + ecmaFeatures: { + modules: true, + }, + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + }, + globals: { + wx: true, + App: true, + Page: true, + getCurrentPages: true, + getApp: true, + Component: true, + requirePlugin: true, + requireMiniProgram: true, + }, + // extends: 'eslint:recommended', + rules: {}, +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07e9f4d --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# Windows +[Dd]esktop.ini +Thumbs.db +$RECYCLE.BIN/ + +# macOS +.DS_Store +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes + +# Node.js +node_modules/ + +# Local overrides +config/config.private.js diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..313f70a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "cSpell.enabled": true, + "cSpell.ignorePaths": [ + "**/*.wxml", + "**/*.wxss" + ], + "files.associations": { + "*.wxml": "html", + "*.wxss": "css" + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/app.js b/app.js new file mode 100644 index 0000000..98d97fc --- /dev/null +++ b/app.js @@ -0,0 +1,1037 @@ +// app.js +const config = require('./config/config.js'); +const authManager = require('./utils/auth.js'); +const apiClient = require('./utils/api-client.js'); +const accountSyncManager = require('./utils/account-sync.js'); +const animationManager = require('./utils/animation-manager.js'); +const versionManager = require('./utils/simple-version-manager.js'); +const screen = require('./utils/screen-adapter'); +const { V2NIMConst, NIM } = require('./dist/nim'); +const realtimeLogger = require('./utils/realtime-logger.js'); + + +App({ + globalData: { + screen, + userInfo:null, + isLoggedIn: false, + appConfig: { + name: config.appName, + version: config.appVersion + }, + systemInfo: null, + networkStatus: 'unknown', + needOpenLocationFavoriteBar: false, + realtimeLogger: realtimeLogger + }, + async initScreen(page) { + try { + // 检查 screen 是否已正确导入 + if (!screen || !screen.init) { + console.error('屏幕适配器未正确导入'); + return; + } + await screen.init(page); + } catch (error) { + console.error('屏幕适配初始化失败:', error); + // 不抛出错误,让页面继续加载 + } + }, + // 小程序启动 + onLaunch: async function () { + console.log('=== FindMe小程序启动 ==='); + console.log('版本:', config.appVersion); + console.log('环境:', config.debug?.enabled ? '开发' : '生产'); + + try { + // 🔥 0. 优先检查版本更新(必须在所有逻辑之前) + const hasVersionUpdate = versionManager.checkVersionUpdate(); + if (hasVersionUpdate) { + console.log('⚠️ 检测到版本更新,停止启动流程'); + return; // 如果有版本更新,停止后续所有逻辑,等待用户处理 + } + + // 1. 初始化系统信息 + await this.initSystemInfo(); + + // 2. 监听网络状态 + this.initNetworkMonitoring(); + + // 3. 初始化认证管理器 + await this.initAuth(); + + // 4. 静默登录检查 + await this.checkSilentLogin(); + + // 🔥 再次检查版本更新(防止在初始化过程中版本发生变化) + const hasVersionUpdateAfter = versionManager.checkVersionUpdate(); + if (hasVersionUpdateAfter) { + console.log('⚠️ 初始化过程中检测到版本更新,停止启动流程'); + return; + } + + // 5. 🔥 在登录成功后初始化 NIM SDK + if (this.globalData.isLoggedIn) { + await this.initNim(); + } + + console.log('=== 小程序启动完成 ==='); + + // 🔥 最后一次检查版本更新(在跳转前) + const hasVersionUpdateBeforeJump = versionManager.checkVersionUpdate(); + if (hasVersionUpdateBeforeJump) { + console.log('⚠️ 跳转前检测到版本更新,取消自动跳转'); + return; + } + + // 6. 根据token检查结果决定跳转 + // 🔥 如果token存在(无论是否过期后刷新),都跳转到地图页面 + const finalUserInfo = wx.getStorageSync('userInfo'); + const hasToken = finalUserInfo?.token || wx.getStorageSync('token'); + + // 如果token存在且已登录(包括刷新后登录),直接跳转到地图页面 + if (hasToken && this.globalData.isLoggedIn) { + console.log('✅ Token存在且已登录(或已刷新),直接跳转到地图页面'); + setTimeout(() => { + // 🔥 跳转前再次确认版本更新状态 + const finalVersionCheck = versionManager.checkVersionUpdate(); + if (!finalVersionCheck) { + wx.reLaunch({ + url: '/pages/map/map' + }); + } + }, 0); + } else if (hasToken && !this.globalData.isLoggedIn) { + // 🔥 如果token存在但登录状态为false,说明token失效且刷新失败 + // 这种情况下清理数据,跳转到登录页面 + console.log('⚠️ Token存在但已失效且刷新失败,清理登录数据,跳转到登录页面'); + authManager.clearAuthData(); + setTimeout(() => { + wx.reLaunch({ + url: '/pages/login/login' + }); + }, 100); + } else { + console.log('⚠️ 没有token,保持启动页或跳转到登录页'); + // 没有token的情况,可以由启动页处理后续跳转逻辑 + } + + } catch (error) { + console.error('小程序启动过程中发生错误:', error); + } + }, + + // 小程序显示 + onShow: function () { + console.log('=== 小程序从后台恢复 ==='); + + // 🔥 全局版本检查 - 每次从后台切回都检查 + const hasVersionUpdate = versionManager.checkVersionUpdate(); + if (hasVersionUpdate) { + console.log('⚠️ 检测到版本更新'); + return; // 如果有版本更新,直接返回,等待用户处理 + } + + // 检查网络状态 + this.checkNetworkStatus(); + + // 如果用户已登录,检查token是否需要刷新 + if (this.globalData.isLoggedIn) { + this.refreshTokenIfNeeded(); + + // 🔥 检查并重新初始化 NIM(防止黑屏后断开) + this.checkAndReconnectNim(); + + // 🔥 自动检查账号同步状态(延迟执行,避免阻塞主流程) + setTimeout(() => { + this.checkAccountSync(); + }, 2000); + } + }, + + // 小程序隐藏 + onHide: function () { + + }, + + // 小程序错误处理 + onError: function (error) { + console.error('小程序全局错误:', error); + + // 这里可以集成错误上报服务 + // 例如:errorReporter.report(error); + }, + + // 页面未找到 + onPageNotFound: function (res) { + console.error('页面未找到:', res); + + // 重定向到首页 + wx.reLaunch({ + url: '/pages/map/map' + }); + }, + + // 全局路由拦截 + onRoute: function () { + // 监听页面跳转 + const originalNavigateTo = wx.navigateTo; + const originalRedirectTo = wx.redirectTo; + const originalSwitchTab = wx.switchTab; + const originalReLaunch = wx.reLaunch; + + const app = this; + const needAuthPages = [ + '/pages/social/friends/friends', + '/pages/message/message', + '/pages/circle/circle' + ]; + + // 重写navigateTo方法 + wx.navigateTo = function (options) { + const url = options.url.split('?')[0]; + if (needAuthPages.includes(url) && !app.globalData.isLoggedIn) { + console.log('拦截未授权访问:', url); + // 直接跳转到登录页 + return originalRedirectTo({ + url: '/pages/login/login', + success: options.success, + fail: options.fail + }); + } + return originalNavigateTo.call(this, options); + }; + + // 同样处理其他跳转方法 + wx.redirectTo = function (options) { + const url = options.url.split('?')[0]; + if (needAuthPages.includes(url) && !app.globalData.isLoggedIn) { + console.log('拦截未授权访问:', url); + return originalRedirectTo({ + url: '/pages/login/login', + success: options.success, + fail: options.fail + }); + } + return originalRedirectTo.call(this, options); + }; + + wx.switchTab = function (options) { + const url = options.url.split('?')[0]; + if (needAuthPages.includes(url) && !app.globalData.isLoggedIn) { + console.log('拦截未授权访问Tab:', url); + return originalRedirectTo({ + url: '/pages/login/login', + success: options.success, + fail: options.fail + }); + } + return originalSwitchTab.call(this, options); + }; + + wx.reLaunch = function (options) { + const url = options.url.split('?')[0]; + if (needAuthPages.includes(url) && !app.globalData.isLoggedIn) { + console.log('拦截未授权访问:', url); + return originalRedirectTo({ + url: '/pages/login/login', + success: options.success, + fail: options.fail + }); + } + return originalReLaunch.call(this, options); + }; + }, + + // 初始化 NIM SDK + async initNim() { + realtimeLogger.nim('initNim-start', { timestamp: Date.now() }); + + // 只有用户已登录才初始化 NIM + if (!this.globalData.isLoggedIn || !this.globalData.userInfo) { + console.log('⚠️ 用户未登录,跳过NIM初始化') + realtimeLogger.warn('NIM初始化跳过-用户未登录', { + isLoggedIn: this.globalData.isLoggedIn, + hasUserInfo: !!this.globalData.userInfo + }); + return + } + + const userInfo = this.globalData.userInfo + // 使用登录接口返回的 NIM 账号和密码 + const nimAccount = userInfo?.neteaseIMAccid || userInfo.user?.neteaseIMAccid + const nimToken = userInfo?.neteaseIMToken || userInfo.user?.neteaseIMToken + + if (!nimAccount || !nimToken) { + console.warn('⚠️ 缺少NIM账号或token,跳过NIM初始化') + realtimeLogger.error('NIM初始化失败-缺少凭证', { + hasNimAccount: !!nimAccount, + hasNimToken: !!nimToken, + userInfoKeys: Object.keys(userInfo || {}), + userKeys: Object.keys(userInfo?.user || {}) + }); + return + } + + console.log('🔥 开始初始化NIM SDK...') + console.log('NIM账号:', nimAccount) + console.log('NIM Token:', nimToken) + + realtimeLogger.nim('nim-credentials', { + nimAccount: nimAccount, + hasNimToken: !!nimToken, + nimTokenLength: nimToken?.length || 0 + }); + + // NIM SDK 配置 + const params = { + appkey: config.nim?.appkey, + apiVersion: config.nim?.apiVersion, + enableV2CloudConversation: config.nim?.enableV2CloudConversation, + debugLevel: config.debug?.enabled ? 'debug' : 'log' + } + + realtimeLogger.nim('nim-config', { + appkey: params.appkey, + debugLevel: params.debugLevel, + apiVersion: params.apiVersion + }); + + // 获取或创建 NIM 实例 + const nim = NIM.getInstance(params) + this.globalData.nim = nim + + realtimeLogger.nim('nim-instance-created', { hasInstance: !!nim }); + + try { + realtimeLogger.nim('nim-login-start', { + nimAccount: nimAccount, + timestamp: Date.now() + }); + + // 登录 NIM + await nim.V2NIMLoginService.login(nimAccount, nimToken, { + retryCount: 3, // 登录失败后,重试登录的次数 + timeout: 60000, // 登录超时时间,单位毫秒 + forceMode: true, // 多端登录互踢时,是否强制登录 + authType: 0 + }) + + realtimeLogger.nim('nim-login-success', { + nimAccount: nimAccount, + timestamp: Date.now() + }); + } catch (err) { + console.error('❌ NIM登录失败:', err) + realtimeLogger.error('NIM登录失败', { + nimAccount: nimAccount, + error: err.toString(), + errorMessage: err.message || '', + errorCode: err.code || '', + timestamp: Date.now() + }); + return; // 登录失败直接返回 + } + console.log('✅ NIM登录成功') + // 初始化会话管理器 + const nimConversationManager = require('./utils/nim-conversation-manager.js') + nimConversationManager.init(nim) + realtimeLogger.nim('conversation-manager-initialized', {}); + + // 初始化在线状态管理器 + const nimPresenceManager = require('./utils/nim-presence-manager.js') + nimPresenceManager.init(nim) + console.log('✅ NIM 在线状态管理器已初始化') + realtimeLogger.nim('presence-manager-initialized', {}); + + // 同步当前用户信息到 NIM + const nimUserManager = require('./utils/nim-user-manager.js') + nimUserManager.init() + realtimeLogger.nim('user-manager-initialized', {}); + + // 提取用户头像和昵称 + const avatar = userInfo.user?.avatar || userInfo.avatar + const nickname = userInfo.user?.nickname || userInfo.nickname + + if (avatar || nickname) { + realtimeLogger.nim('sync-user-info-start', { + hasAvatar: !!avatar, + hasNickname: !!nickname + }); + + let res = await nimUserManager.updateSelfUserInfo({ + avatar: avatar, + nickname: nickname + }) + if (!res) { + console.warn('⚠️ 同步用户信息到NIM失败') + realtimeLogger.error('同步用户信息到NIM失败', { + avatar: avatar, + nickname: nickname + }); + return + } + console.log('✅ 用户信息已同步到 NIM') + realtimeLogger.nim('sync-user-info-success', {}); + } + console.log('✅ NIM SDK初始化完成') + realtimeLogger.nim('initNim-complete', { timestamp: Date.now() }); + }, + + // 登出 NIM + async logoutNim() { + try { + if (this.globalData.nim) { + await this.globalData.nim.V2NIMLoginService.logout() + console.log('✅ NIM登出成功') + } + } catch (error) { + console.error('❌ NIM登出失败:', error) + } + }, + + // 🔥 检查并重连 NIM(用于从后台恢复时) + async checkAndReconnectNim() { + try { + // 检查是否已有 NIM 实例 + if (!this.globalData.nim) { + console.log('⚠️ NIM 实例不存在,执行初始化'); + await this.initNim(); + return; + } + + // 检查 NIM 连接状态 + const nim = this.globalData.nim; + const loginService = nim.V2NIMLoginService; + + // 获取当前登录状态 + let loginStatus; + try { + loginStatus = await loginService.getLoginStatus(); + console.log('📡 NIM 登录状态:', loginStatus); + } catch (error) { + console.warn('获取 NIM 登录状态失败:', error); + loginStatus = 0; // 假设未登录 + } + + // V2NIMLoginStatus: 0-未登录, 1-登录中, 2-已登录, 3-登录失败 + if (loginStatus !== 2) { + console.log('🔄 NIM 未处于登录状态,重新登录'); + realtimeLogger.nim('nim-reconnect-triggered', { + loginStatus: loginStatus, + timestamp: Date.now() + }); + + // 重新初始化 NIM + await this.initNim(); + } else { + console.log('✅ NIM 已连接,无需重连'); + } + } catch (error) { + console.error('❌ 检查 NIM 连接状态失败:', error); + realtimeLogger.error('NIM重连检查失败', { + error: error.toString(), + timestamp: Date.now() + }); + + // 如果检查失败,尝试重新初始化 + try { + console.log('🔄 尝试重新初始化 NIM'); + await this.initNim(); + } catch (retryError) { + console.error('❌ 重新初始化 NIM 失败:', retryError); + } + } + }, + + // 未处理的Promise拒绝 + onUnhandledRejection: function (res) { + console.error('未处理的Promise拒绝:', res); + }, + + // 初始化系统信息 + async initSystemInfo() { + try { + // 使用新的API替代废弃的wx.getSystemInfoSync + const [windowInfo, deviceInfo, appBaseInfo] = await Promise.all([ + this.getWindowInfo(), + this.getDeviceInfo(), + this.getAppBaseInfo() + ]); + + // 合并系统信息 + const systemInfo = { + ...windowInfo, + ...deviceInfo, + ...appBaseInfo + }; + + this.globalData.systemInfo = systemInfo; + + console.log('系统信息初始化成功:', { + platform: systemInfo.platform, + version: systemInfo.version, + model: systemInfo.model, + language: systemInfo.language + }); + + } catch (error) { + console.error('获取系统信息失败,使用兜底方案:', error); + // 兜底使用统一的系统信息工具 + try { + const { getSystemInfoSync } = require('./utils/system-info-helper.js'); + const systemInfo = getSystemInfoSync(); + this.globalData.systemInfo = systemInfo; + } catch (fallbackError) { + console.error('兜底方案也失败:', fallbackError); + } + } + }, + + // 获取窗口信息 + getWindowInfo() { + return new Promise((resolve) => { + try { + const windowInfo = wx.getWindowInfo(); + resolve(windowInfo); + } catch (error) { + console.warn('获取窗口信息失败:', error); + resolve({}); + } + }); + }, + + // 获取设备信息 + getDeviceInfo() { + return new Promise((resolve) => { + try { + const deviceInfo = wx.getDeviceInfo(); + resolve(deviceInfo); + } catch (error) { + console.warn('获取设备信息失败:', error); + resolve({}); + } + }); + }, + + // 获取应用基础信息 + getAppBaseInfo() { + return new Promise((resolve) => { + try { + const appBaseInfo = wx.getAppBaseInfo(); + resolve(appBaseInfo); + } catch (error) { + console.warn('获取应用信息失败:', error); + resolve({}); + } + }); + }, + + // 初始化网络监听 + initNetworkMonitoring() { + // 获取当前网络状态 + wx.getNetworkType({ + success: (res) => { + this.globalData.networkStatus = res.networkType; + + } + }); + + // 监听网络状态变化 + wx.onNetworkStatusChange((res) => { + this.globalData.networkStatus = res.networkType; + console.log('网络状态变化:', res); + + if (res.isConnected) { + + // 网络恢复时,重新检查登录状态 + if (this.globalData.isLoggedIn) { + this.refreshTokenIfNeeded(); + } + } else { + + } + }); + }, + + // 初始化认证管理器 + async initAuth() { + try { + + await authManager.init(); + + } catch (error) { + console.error('认证管理器初始化失败:', error); + } + }, + + // 静默登录检查 + async checkSilentLogin() { + try { + // 🔥 先检查本地存储的token + const storedUserInfo = wx.getStorageSync('userInfo'); + const directToken = wx.getStorageSync('token'); + + console.log('🔍 本地token检查:', { + hasStoredUserInfo: !!storedUserInfo, + hasUserInfoToken: !!(storedUserInfo?.token), + hasDirectToken: !!directToken, + userInfoTokenLength: storedUserInfo?.token?.length || 0, + directTokenLength: directToken?.length || 0 + }); + + // 如果没有任何token,直接返回(不设置登录状态) + if (!storedUserInfo?.token && !directToken) { + console.log('⚠️ 没有找到token,保持未登录状态'); + this.globalData.isLoggedIn = false; + this.globalData.userInfo = null; + return; + } + + // 🔥 检查token是否过期,如果过期则尝试刷新 + let userInfo = storedUserInfo; + if (userInfo && userInfo.token) { + const isTokenValid = authManager.isTokenValid(userInfo); + + if (!isTokenValid) { + console.log('⚠️ Token已过期,尝试刷新token...'); + + // 尝试刷新token + if (userInfo.refreshToken) { + const refreshResult = await authManager.refreshTokenIfNeeded(userInfo); + + if (refreshResult) { + console.log('✅ Token刷新成功'); + // 刷新成功后,从存储中获取更新后的userInfo + userInfo = wx.getStorageSync('userInfo'); + this.globalData.userInfo = userInfo; + this.globalData.isLoggedIn = true; + apiClient.setToken(userInfo.token); + } else { + console.log('❌ Token刷新失败,清理登录数据,跳转到登录页面'); + // 刷新失败,清理数据 + authManager.clearAuthData(); + this.globalData.isLoggedIn = false; + this.globalData.userInfo = null; + // 跳转到登录页面 + setTimeout(() => { + wx.reLaunch({ + url: '/pages/login/login' + }); + }, 100); + return; + } + } else { + console.log('❌ 没有refreshToken,无法刷新,清理登录数据,跳转到登录页面'); + // 没有refreshToken,无法刷新 + authManager.clearAuthData(); + this.globalData.isLoggedIn = false; + this.globalData.userInfo = null; + // 跳转到登录页面 + setTimeout(() => { + wx.reLaunch({ + url: '/pages/login/login' + }); + }, 100); + return; + } + } else { + console.log('✅ Token未过期,使用现有token'); + // Token未过期,直接使用 + this.globalData.userInfo = userInfo; + this.globalData.isLoggedIn = true; + apiClient.setToken(userInfo.token); + } + } else { + // 有directToken但没有完整的userInfo,尝试通过silentLogin处理 + const isAuthenticated = await authManager.silentLogin(); + + if (isAuthenticated) { + console.log('✅ 通过silentLogin验证成功'); + const finalUserInfo = wx.getStorageSync('userInfo'); + if (finalUserInfo && finalUserInfo.token && finalUserInfo.token.length > 0) { + this.globalData.userInfo = finalUserInfo; + this.globalData.isLoggedIn = true; + } else { + console.error('❌ silentLogin成功但无法获取有效token'); + this.globalData.isLoggedIn = false; + this.globalData.userInfo = null; + } + } else { + console.log('❌ silentLogin验证失败,清理登录数据'); + this.globalData.isLoggedIn = false; + this.globalData.userInfo = null; + authManager.clearAuthData(); + } + } + + } catch (error) { + console.error('❌ 静默登录检查失败:', error); + this.globalData.isLoggedIn = false; + this.globalData.userInfo = null; + + // 🔥 出错时清理存储数据 + wx.removeStorageSync('userInfo'); + wx.removeStorageSync('token'); + } + }, + + // 检查网络状态 + checkNetworkStatus() { + wx.getNetworkType({ + success: (res) => { + const oldStatus = this.globalData.networkStatus; + this.globalData.networkStatus = res.networkType; + + if (oldStatus !== res.networkType) { + + } + }, + fail: (error) => { + console.error('获取网络类型失败:', error); + } + }); + }, + + // 刷新token(如果需要) + async refreshTokenIfNeeded() { + try { + if (!this.globalData.userInfo) { + return; + } + + const isValid = authManager.isTokenValid(this.globalData.userInfo); + if (!isValid) { + + const refreshed = await authManager.refreshTokenIfNeeded(this.globalData.userInfo); + + if (refreshed) { + + // 🔥 修复:获取完整的认证信息 + const storedUserInfo = wx.getStorageSync('userInfo'); + if (storedUserInfo && storedUserInfo.token) { + this.globalData.userInfo = storedUserInfo; + + } + } else { + + this.handleAuthExpired(); + } + } + } catch (error) { + console.error('Token刷新检查失败:', error); + } + }, + + // 处理认证过期 + handleAuthExpired() { + console.log('认证已过期,清除登录状态'); + + authManager.clearAuthData(); + this.globalData.isLoggedIn = false; + this.globalData.userInfo = null; + + // 只更新登录状态,不强制跳转到登录页 + // 让用户先进入地图页面,使用需要登录的功能时再跳转 + + }, + + // 手动登录方法(供页面调用) + async login(loginData) { + try { + console.log('执行登录,保存用户信息'); + realtimeLogger.login('login-start', { + hasToken: !!loginData.token, + hasAccessToken: !!loginData.access_token, + hasNeteaseIMAccid: !!loginData.neteaseIMAccid, + hasNeteaseIMToken: !!loginData.neteaseIMToken + }); + + if (!loginData.token) { + loginData.token = loginData.access_token; + } + // 使用认证管理器保存登录信息 + const success = await authManager.saveAuthData(loginData); + + if (success) { + // 🔥 修复:获取完整的认证信息 + const storedUserInfo = wx.getStorageSync('userInfo'); + if (storedUserInfo && storedUserInfo.token) { + this.globalData.userInfo = storedUserInfo; + this.globalData.isLoggedIn = true; + console.log('登录信息保存成功,包含token'); + + // 🔥 登录成功后立即初始化 NIM SDK + if (storedUserInfo.neteaseIMAccid && storedUserInfo.neteaseIMToken) { + console.log('检测到 NIM 凭证,开始初始化 NIM SDK...'); + realtimeLogger.login('has-nim-credentials', { + hasNeteaseIMAccid: !!storedUserInfo.neteaseIMAccid, + hasNeteaseIMToken: !!storedUserInfo.neteaseIMToken + }); + await this.initNim(); + } else { + console.warn('⚠️ 登录数据中缺少 NIM 凭证,跳过 NIM 初始化'); + realtimeLogger.warn('登录数据缺少NIM凭证', { + userInfoKeys: Object.keys(storedUserInfo || {}) + }); + } + + realtimeLogger.login('login-success', {}); + return true; + } else { + console.error('登录信息保存失败:无法获取完整用户信息'); + return false; + } + } else { + console.error('登录信息保存失败'); + return false; + } + + } catch (error) { + console.error('登录处理失败:', error); + return false; + } + }, + + // 登出方法(供页面调用) + async logout() { + try { + console.log('执行登出'); + + // 🔥 设置退出登录标志,防止登录页误判 + wx.setStorageSync('isLoggingOut', true); + + // 🔥 先登出 NIM + await this.logoutNim(); + + const success = await authManager.logout(); + + // 🔥 无论服务端登出是否成功,都要清除本地状态 + this.globalData.isLoggedIn = false; + this.globalData.userInfo = null; + this.globalData.nim = null; // 🔥 清除 NIM 实例 + + // 🔥 清除可能残留的登录信息 + wx.removeStorageSync('userInfo'); + wx.removeStorageSync('token'); + wx.removeStorageSync('testWechatLogin-loginData'); + + console.log('✅ 登出完成,已清除所有登录状态'); + return success; + + } catch (error) { + console.error('登出失败:', error); + // 🔥 即使失败也要清除状态 + this.globalData.isLoggedIn = false; + this.globalData.userInfo = null; + this.globalData.nim = null; + wx.removeStorageSync('isLoggingOut'); + return false; + } + }, + + // 检查是否需要登录(供页面调用) + // autoRedirect: 可选,是否在未登录时自动跳转登录页,默认false + requireAuth(autoRedirect = false) { + return authManager.requireAuth(autoRedirect); + }, + + // 获取用户显示信息(供页面调用) + getUserDisplayInfo() { + return authManager.getUserDisplayInfo(); + }, + + // 检查用户权限(供页面调用) + hasPermission(permission) { + return authManager.hasPermission(permission); + }, + + // 获取当前token(供页面调用) + getCurrentToken() { + return authManager.getCurrentToken(); + }, + + // 等待认证初始化完成(供页面调用) + async waitForAuth() { + await authManager.waitForInitialization(); + return this.globalData.isLoggedIn; + }, + + // 检查网络连接 + isNetworkAvailable() { + return this.globalData.networkStatus !== 'none'; + }, + + // 显示网络错误提示 + showNetworkError() { + if (!this.isNetworkAvailable()) { + wx.showToast({ + title: '网络连接不可用', + icon: 'none', + duration: 2000 + }); + return true; + } + return false; + }, + + // 更新全局头像并通知页面 + updateUserAvatar(serverUrl, options = {}) { + if (!serverUrl) { + console.warn('updateUserAvatar 调用时缺少有效的头像地址'); + return false; + } + + try { + const cachedUrl = options.cachedUrl || serverUrl; + const providedInfo = options.userInfo; + const storedInfo = providedInfo || this.globalData.userInfo || wx.getStorageSync('userInfo') || {}; + const userBucket = storedInfo.user || {}; + + userBucket.avatar = serverUrl; + userBucket.avatarUrl = serverUrl; + storedInfo.user = userBucket; + storedInfo.avatar = serverUrl; + storedInfo.avatarUrl = serverUrl; + + this.globalData.userInfo = storedInfo; + if (storedInfo.token) { + this.globalData.isLoggedIn = true; + } + + wx.setStorageSync('userInfo', storedInfo); + if (cachedUrl) { + wx.setStorageSync('latestAvatarUrl', cachedUrl); + } else { + wx.setStorageSync('latestAvatarUrl', serverUrl); + } + + const payload = { + avatarUrl: serverUrl, + cachedUrl, + userInfo: storedInfo + }; + + const pages = getCurrentPages(); + pages.forEach((page) => { + try { + if (typeof page.onAvatarUpdated === 'function') { + page.onAvatarUpdated(payload); + } + + const displayUrl = cachedUrl || serverUrl; + const updates = {}; + + if (Object.prototype.hasOwnProperty.call(page.data || {}, 'userInfo')) { + updates['userInfo.avatarUrl'] = displayUrl; + updates['userInfo.avatar'] = displayUrl; + } + + if (page.data && page.data.userInfo && typeof page.data.userInfo === 'object' && page.data.userInfo.user) { + updates['userInfo.user.avatar'] = displayUrl; + updates['userInfo.user.avatarUrl'] = displayUrl; + } + + if (page.data && page.data.userInfo && typeof page.data.userInfo === 'object' && page.data.userInfo.profile) { + updates['userInfo.profile.avatar'] = displayUrl; + } + + if (Object.prototype.hasOwnProperty.call(page.data || {}, 'avatar')) { + updates.avatar = displayUrl; + } + if (Object.prototype.hasOwnProperty.call(page.data || {}, 'avatarUrl')) { + updates.avatarUrl = displayUrl; + } + + if (Object.keys(updates).length > 0) { + page.setData(updates); + } + } catch (pageError) { + console.error('更新页面头像失败:', page.route, pageError); + } + }); + + return true; + } catch (error) { + console.error('更新全局头像失败:', error); + return false; + } + }, + + // 全局错误处理工具 + handleError(error, context = '') { + console.error(`${context} 错误:`, error); + + // 根据错误类型显示不同提示 + let message = '操作失败,请重试' + error; + + if (error.message) { + message = error.message; + } else if (error.errMsg) { + if (error.errMsg.includes('timeout')) { + message = '请求超时,请检查网络连接'; + } else if (error.errMsg.includes('fail')) { + message = '网络连接失败'; + } + } + + wx.showToast({ + title: message, + icon: 'none', + duration: 2000 + }); + }, + + // 显示加载状态 + showLoading(title = '加载中...') { + wx.showLoading({ + title: title, + mask: true + }); + }, + + // 隐藏加载状态 + hideLoading() { + wx.hideLoading(); + }, + + // 兼容性方法 - 检查登录状态 + isLoggedIn() { + return this.globalData.isLoggedIn; + }, + + // 兼容性方法 - 获取用户信息 + getUserInfo() { + return this.globalData.userInfo; + }, + + // 兼容性方法 - 获取token + getToken() { + return authManager.getCurrentToken(); + }, + + // 🔥 账号同步检查 + async checkAccountSync() { + try { + + // 检查是否应该跳过绑定提示 + if (accountSyncManager.shouldSkipBinding()) { + + return; + } + + // 自动检查并引导用户绑定手机号 + await accountSyncManager.autoCheckAndBind(); + + } catch (error) { + console.error('账号同步检查失败:', error); + // 不影响主要功能,静默处理错误 + } + }, + + // 🔥 全局版本检查方法 - 供页面调用 + checkAppVersionUpdate: function () { + return versionManager.checkVersionUpdate(); + } +}) + diff --git a/app.json b/app.json new file mode 100644 index 0000000..ea7ee7e --- /dev/null +++ b/app.json @@ -0,0 +1,184 @@ +{ + "requestDomain": [ + "https://newkmsapi.qixincha.com", + "https://api.faxianwo.me" + ], + "sdkVersion": "2.21.0", + "pages": [ + "pages/splash/splash", + "pages/login/login", + "pages/login/mobile-login-page", + "pages/login/profile-page", + "pages/map/map", + "pages/message/message", + "pages/message/chat/chat", + "pages/social/friends/friends", + "pages/circle/circle", + "pages/webview/webview" + ], + "window": { + "backgroundTextStyle": "light", + "navigationBarBackgroundColor": "#000000", + "navigationBarTitleText": "FindMe", + "navigationBarTextStyle": "white", + "backgroundColor": "#f8f9fa", + "enablePullDownRefresh": false, + "onReachBottomDistance": 50 + }, + "networkTimeout": { + "request": 15000, + "downloadFile": 15000, + "uploadFile": 20000, + "connectSocket": 20000 + }, + "debug": false, + "darkmode": true, + "themeLocation": "theme.json", + "permission": { + "scope.userLocation": { + "desc": "你的位置信息将用于小程序位置接口的效果展示" + }, + "scope.camera": { + "desc": "需使用摄像头扫描二维码及控制手电筒,实现扫码、照明功能" + } + }, + "usingComponents": {}, + "requiredBackgroundModes": [ + "location" + ], + "requiredPrivateInfos": [ + "getLocation", + "chooseLocation" + ], + "sitemapLocation": "sitemap.json", + "lazyCodeLoading": "requiredComponents", + "subpackages": [ + { + "root": "subpackages/social-remark", + "pages": [ + "friend-remark" + ] + }, + { + "root": "subpackages/realname", + "pages": [ + "realname", + "camera-verify", + "faceid-webview", + "verify-success" + ] + }, + { + "root": "subpackages/social", + "pages": [ + "friend-detail/friend-detail", + "user-preview/user-preview", + "search/search", + "friend-requests/friend-requests", + "tag-friends/tag-friends", + "friend-selector/friend-selector" + ] + }, + { + "root": "subpackages/profile", + "pages": [ + "profile/profile", + "personal-details/personal-details", + "avatar-edit/avatar-edit" + ] + }, + { + "root": "subpackages/qr", + "pages": [ + "qr-code/qr-code", + "qr-scan/qr-scan" + ] + }, + { + "root": "subpackages/media", + "pages": [ + "camera/camera", + "edit/edit", + "edits/edits", + "visibility-selector/visibility-selector" + ] + }, + { + "root": "subpackages/map-extras", + "pages": [ + "locationList/locationList", + "searchLocation/searchLocation" + ] + }, + { + "root": "subpackages/group", + "pages": [ + "create-group/create-group", + "group-info/group-info", + "group-members/group-members", + "group-announcement/group-announcement", + "create-group-chat/create-group-chat", + "caht-groups-list/caht-groups-list" + ] + }, + { + "root": "subpackages/settings", + "pages": [ + "notification-settings/notification-settings", + "about/update-log/update-log", + "about/about", + "settingss/settingss", + "feedback/feedback", + "account-security/account-security", + "phone-binding/phone-binding", + "chat-settings/chat-settings" + ] + }, + { + "root": "subpackages/search", + "pages": [ + "global-search/global-search" + ] + }, + { + "root": "subpackages/dev-tools", + "pages": [ + "websocket-test/websocket-test" + ], + "independent": true + } + ], + "tabBar": { + "color": "#999999", + "selectedColor": "#ffffff", + "backgroundColor": "rgba(30, 30, 30, 0)", + "borderStyle": "white", + "custom": true, + "list": [ + { + "pagePath": "pages/map/map", + "text": "发现", + "iconPath": "images/index/location.png", + "selectedIconPath": "images/index/location-active.png" + }, + { + "pagePath": "pages/circle/circle", + "text": "圈子", + "iconPath": "images/index/circle.png", + "selectedIconPath": "images/index/circle-active.png" + }, + { + "pagePath": "pages/message/message", + "text": "聊天", + "iconPath": "images/index/message.png", + "selectedIconPath": "images/index/message-active.png" + }, + { + "pagePath": "pages/social/friends/friends", + "text": "我的", + "iconPath": "images/index/friend.png", + "selectedIconPath": "images/index/friend-active.png" + } + ] + } +} \ No newline at end of file diff --git a/app.wxss b/app.wxss new file mode 100644 index 0000000..4f5807f --- /dev/null +++ b/app.wxss @@ -0,0 +1,101 @@ +/**app.wxss**/ +/* 导入设计系统和组件样式 */ +@import './styles/design-system.wxss'; +@import './styles/components.wxss'; +@import './styles/responsive.wxss'; +/* 导入通用屏幕适配样式 */ +@import './styles/screen-adaption.wxss'; + +/* 全局基础样式 */ +page { + /* height: 100%; */ + overflow: hidden; + margin: 0; + padding: 0; + box-sizing: border-box; + background-color: #f8f9fa; + min-height: 100vh; +} + +/* 默认容器样式 - 保持向后兼容 */ +.container { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + padding: 200rpx 0; + box-sizing: border-box; +} + +/* 全屏容器 - 新的推荐方式 */ +.app-container { + height: 100vh; + min-height: 100vh; + max-height: 100vh; + display: flex; + flex-direction: column; + overflow: hidden; + box-sizing: border-box; + position: relative; +} + +/* 内容区域 */ +.content-area { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; +} + +/* 防止长按选择 */ +text, view, image { + -webkit-user-select: none; + user-select: none; + box-sizing: border-box; +} + +/* 滚动条样式 */ +::-webkit-scrollbar { + width: 4px; + height: 4px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.1); + border-radius: 2px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(0, 0, 0, 0.2); +} + +/* 玻璃效果样式 */ +.tab-bar-glass { + /* 基础玻璃效果 */ + background: rgba(30, 30, 30, 0.7); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + + /* 添加细微边框增强效果 */ + border-top: 1px solid rgba(255, 255, 255, 0.1); + + /* 阴影效果增强层次感 */ + box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); +} + +/* 修复iOS上的样式问题 */ +.tab-bar-glass::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: inherit; + z-index: -1; +} diff --git a/components/media-preview/media-preview.js b/components/media-preview/media-preview.js new file mode 100644 index 0000000..defa820 --- /dev/null +++ b/components/media-preview/media-preview.js @@ -0,0 +1,550 @@ +// 🎨 媒体预览组件逻辑 +const mediaManager = require('../../subpackages/media/utils/media-manager.js'); + +Component({ + properties: { + // 是否显示预览 + visible: { + type: Boolean, + value: false + }, + + // 媒体列表 + mediaList: { + type: Array, + value: [] + }, + + // 当前索引 + currentIndex: { + type: Number, + value: 0 + }, + + // 是否可以分享 + canShare: { + type: Boolean, + value: true + }, + + // 是否可以编辑 + canEdit: { + type: Boolean, + value: false + }, + + // 是否可以删除 + canDelete: { + type: Boolean, + value: false + }, + + // 是否显示底部操作栏 + showFooter: { + type: Boolean, + value: true + }, + + // 是否显示手势提示 + showGestureTips: { + type: Boolean, + value: true + } + }, + + data: { + // 当前媒体 + currentMedia: {}, + + // 音频播放状态 + audioPlaying: false, + audioProgress: 0, + audioCurrentTime: 0, + + // 手势提示定时器 + gestureTimer: null + }, + + observers: { + 'mediaList, currentIndex': function(mediaList, currentIndex) { + if (mediaList && mediaList.length > 0 && currentIndex >= 0 && currentIndex < mediaList.length) { + this.setData({ + currentMedia: mediaList[currentIndex] + }); + } + } + }, + + lifetimes: { + attached() { + + }, + + detached() { + + this.cleanup(); + } + }, + + methods: { + // 🎨 ===== 基础操作 ===== + + // 阻止事件冒泡 + stopPropagation() { + // 阻止点击事件冒泡到遮罩层 + }, + + // 遮罩点击 + onMaskTap() { + this.closePreview(); + }, + + // 关闭预览 + closePreview() { + this.setData({ + visible: false + }); + + this.triggerEvent('close'); + this.cleanup(); + }, + + // 清理资源 + cleanup() { + // 停止音频播放 + if (this.data.audioPlaying) { + this.stopAudio(); + } + + // 清理定时器 + if (this.data.gestureTimer) { + clearTimeout(this.data.gestureTimer); + } + }, + + // 🎨 ===== 图片操作 ===== + + // 轮播图切换 + onSwiperChange(e) { + const currentIndex = e.detail.current; + this.setData({ + currentIndex: currentIndex + }); + + this.triggerEvent('indexchange', { + currentIndex: currentIndex + }); + }, + + // 图片加载完成 + onImageLoad(e) { + + const index = e.currentTarget.dataset.index; + const mediaList = this.data.mediaList; + + if (mediaList[index]) { + mediaList[index].loading = false; + mediaList[index].error = false; + + this.setData({ + mediaList: mediaList + }); + } + }, + + // 图片加载失败 + onImageError(e) { + console.error('❌ 图片加载失败'); + + const index = e.currentTarget.dataset.index; + const mediaList = this.data.mediaList; + + if (mediaList[index]) { + mediaList[index].loading = false; + mediaList[index].error = true; + + this.setData({ + mediaList: mediaList + }); + } + }, + + // 图片点击 + onImageTap(e) { + // 可以实现双击放大等功能 + + }, + + // 重试加载 + retryLoad(e) { + const index = e.currentTarget.dataset.index; + const mediaList = this.data.mediaList; + + if (mediaList[index]) { + mediaList[index].loading = true; + mediaList[index].error = false; + + this.setData({ + mediaList: mediaList + }); + } + }, + + // 🎨 ===== 视频操作 ===== + + // 视频播放 + onVideoPlay() { + + this.triggerEvent('videoplay'); + }, + + // 视频暂停 + onVideoPause() { + + this.triggerEvent('videopause'); + }, + + // 视频结束 + onVideoEnded() { + + this.triggerEvent('videoended'); + }, + + // 视频错误 + onVideoError(e) { + console.error('❌ 视频播放错误:', e.detail); + wx.showToast({ + title: '视频播放失败', + icon: 'none' + }); + }, + + // 视频时间更新 + onVideoTimeUpdate(e) { + // 可以用于显示播放进度 + + }, + + // 🎨 ===== 音频操作 ===== + + // 切换音频播放 + toggleAudioPlay() { + if (this.data.audioPlaying) { + this.pauseAudio(); + } else { + this.playAudio(); + } + }, + + // 播放音频 + playAudio() { + // 这里需要实现音频播放逻辑 + + this.setData({ + audioPlaying: true + }); + + // 模拟播放进度 + this.startAudioProgress(); + }, + + // 暂停音频 + pauseAudio() { + + this.setData({ + audioPlaying: false + }); + + this.stopAudioProgress(); + }, + + // 停止音频 + stopAudio() { + + this.setData({ + audioPlaying: false, + audioProgress: 0, + audioCurrentTime: 0 + }); + + this.stopAudioProgress(); + }, + + // 开始音频进度更新 + startAudioProgress() { + this.audioProgressTimer = setInterval(() => { + const currentTime = this.data.audioCurrentTime + 1; + const duration = this.data.currentMedia.duration || 100; + const progress = (currentTime / duration) * 100; + + this.setData({ + audioCurrentTime: currentTime, + audioProgress: Math.min(progress, 100) + }); + + if (progress >= 100) { + this.stopAudio(); + } + }, 1000); + }, + + // 停止音频进度更新 + stopAudioProgress() { + if (this.audioProgressTimer) { + clearInterval(this.audioProgressTimer); + this.audioProgressTimer = null; + } + }, + + // 🎨 ===== 文件操作 ===== + + // 打开文件 + openFile() { + const currentMedia = this.data.currentMedia; + + wx.openDocument({ + filePath: currentMedia.tempFilePath || currentMedia.url, + fileType: currentMedia.extension, + success: () => { + + }, + fail: (error) => { + console.error('❌ 文件打开失败:', error); + wx.showToast({ + title: '无法打开此文件', + icon: 'none' + }); + } + }); + }, + + // 保存文件 + async saveFile() { + const currentMedia = this.data.currentMedia; + + try { + wx.showLoading({ + title: '保存中...' + }); + + // 如果是网络文件,先下载 + let filePath = currentMedia.tempFilePath; + if (!filePath && currentMedia.url) { + const downloadResult = await mediaManager.downloadFile(currentMedia.url); + if (downloadResult.success) { + filePath = downloadResult.tempFilePath; + } else { + throw new Error('下载失败'); + } + } + + // 保存到本地 + const result = await new Promise((resolve, reject) => { + wx.saveFile({ + tempFilePath: filePath, + success: resolve, + fail: reject + }); + }); + + wx.hideLoading(); + wx.showToast({ + title: '保存成功', + icon: 'success' + }); + + } catch (error) { + wx.hideLoading(); + console.error('❌ 文件保存失败:', error); + wx.showToast({ + title: '保存失败', + icon: 'none' + }); + } + }, + + // 🎨 ===== 操作按钮 ===== + + // 下载媒体 + async downloadMedia() { + const currentMedia = this.data.currentMedia; + + if (!currentMedia.url) { + wx.showToast({ + title: '无法下载', + icon: 'none' + }); + return; + } + + try { + wx.showLoading({ + title: '下载中...' + }); + + const result = await mediaManager.downloadFile(currentMedia.url, { + fileName: currentMedia.name + }); + + wx.hideLoading(); + + if (result.success) { + wx.showToast({ + title: '下载完成', + icon: 'success' + }); + + this.triggerEvent('download', { + media: currentMedia, + filePath: result.tempFilePath + }); + } else { + throw new Error(result.error); + } + + } catch (error) { + wx.hideLoading(); + console.error('❌ 下载失败:', error); + wx.showToast({ + title: '下载失败', + icon: 'none' + }); + } + }, + + // 分享媒体 + shareMedia() { + const currentMedia = this.data.currentMedia; + + this.triggerEvent('share', { + media: currentMedia + }); + }, + + // 编辑媒体 + editMedia() { + const currentMedia = this.data.currentMedia; + + this.triggerEvent('edit', { + media: currentMedia, + index: this.data.currentIndex + }); + }, + + // 删除媒体 + deleteMedia() { + const currentMedia = this.data.currentMedia; + + wx.showModal({ + title: '删除确认', + content: '确定要删除这个文件吗?', + success: (res) => { + if (res.confirm) { + this.triggerEvent('delete', { + media: currentMedia, + index: this.data.currentIndex + }); + } + } + }); + }, + + // 收藏媒体 + favoriteMedia() { + const currentMedia = this.data.currentMedia; + const favorited = !currentMedia.favorited; + + // 更新收藏状态 + currentMedia.favorited = favorited; + this.setData({ + currentMedia: currentMedia + }); + + this.triggerEvent('favorite', { + media: currentMedia, + favorited: favorited + }); + + wx.showToast({ + title: favorited ? '已收藏' : '已取消收藏', + icon: 'success' + }); + }, + + // 显示更多操作 + showMoreActions() { + const actions = ['转发', '设为壁纸', '添加到相册', '举报']; + + wx.showActionSheet({ + itemList: actions, + success: (res) => { + this.triggerEvent('moreaction', { + action: actions[res.tapIndex], + media: this.data.currentMedia + }); + } + }); + }, + + // 🎨 ===== 工具方法 ===== + + // 格式化文件大小 + formatFileSize(size) { + if (!size) return '未知大小'; + + const units = ['B', 'KB', 'MB', 'GB']; + let unitIndex = 0; + let fileSize = size; + + while (fileSize >= 1024 && unitIndex < units.length - 1) { + fileSize /= 1024; + unitIndex++; + } + + return `${fileSize.toFixed(1)} ${units[unitIndex]}`; + }, + + // 格式化时长 + formatDuration(duration) { + if (!duration) return '00:00'; + + const minutes = Math.floor(duration / 60); + const seconds = Math.floor(duration % 60); + + return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; + }, + + // 格式化时间 + formatTime(time) { + if (!time) return '00:00'; + + const minutes = Math.floor(time / 60); + const seconds = Math.floor(time % 60); + + return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; + }, + + // 获取文件图标 + getFileIcon(extension) { + const iconMap = { + 'pdf': '📄', + 'doc': '📝', + 'docx': '📝', + 'xls': '📊', + 'xlsx': '📊', + 'ppt': '📽️', + 'pptx': '📽️', + 'txt': '📃', + 'zip': '🗜️', + 'rar': '🗜️', + 'mp3': '🎵', + 'wav': '🎵', + 'mp4': '🎬', + 'avi': '🎬' + }; + + return iconMap[extension] || '📄'; + } + } +}); + diff --git a/components/media-preview/media-preview.json b/components/media-preview/media-preview.json new file mode 100644 index 0000000..a89ef4d --- /dev/null +++ b/components/media-preview/media-preview.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} diff --git a/components/media-preview/media-preview.wxml b/components/media-preview/media-preview.wxml new file mode 100644 index 0000000..0a88dd4 --- /dev/null +++ b/components/media-preview/media-preview.wxml @@ -0,0 +1,192 @@ + + + + + + + + + + + {{currentMedia.name || '媒体预览'}} + + {{formatFileSize(currentMedia.size)}} + + + + + + + 📥 + + + + + 📤 + + + + + + + + + + + + + + + + + + + + + + 加载中... + + + + + + 加载失败 + + 重试 + + + + + + + + + {{currentIndex + 1}} / {{mediaList.length}} + + + + + + + + + + {{formatDuration(currentMedia.duration)}} + {{currentMedia.width}}×{{currentMedia.height}} + + + + + + + {{getFileIcon(currentMedia.extension)}} + + + + {{currentMedia.name}} + {{formatFileSize(currentMedia.size)}} + {{currentMedia.extension.toUpperCase()}} 文件 + + + + + 打开文件 + + + 保存到本地 + + + + + + + + + 🎵 + + + + + {{audioPlaying ? '⏸️' : '▶️'}} + + + + + + + + {{formatTime(audioCurrentTime)}} + {{formatTime(currentMedia.duration)}} + + + + + + + {{currentMedia.name}} + {{formatFileSize(currentMedia.size)}} + + + + + + + + + + ✏️ + 编辑 + + + + + 🗑️ + 删除 + + + + + {{currentMedia.favorited ? '❤️' : '🤍'}} + {{currentMedia.favorited ? '已收藏' : '收藏'}} + + + + + + 更多 + + + + + + + + 双击放大 · 滑动切换 · 点击关闭 + + diff --git a/components/media-preview/media-preview.wxss b/components/media-preview/media-preview.wxss new file mode 100644 index 0000000..8164f7f --- /dev/null +++ b/components/media-preview/media-preview.wxss @@ -0,0 +1,586 @@ +/* 🎨 媒体预览组件样式 */ + +/* CSS变量定义 */ +.media-preview-container { + --preview-bg: rgba(0, 0, 0, 0.9); + --header-bg: rgba(0, 0, 0, 0.7); + --text-primary: #FFFFFF; + --text-secondary: rgba(255, 255, 255, 0.7); + --button-bg: rgba(255, 255, 255, 0.1); + --button-active: rgba(255, 255, 255, 0.2); + --border-color: rgba(255, 255, 255, 0.2); + --shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.3); +} + +/* 🎨 预览容器 */ +.media-preview-container { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + display: flex; + flex-direction: column; + background: var(--preview-bg); + animation: fadeIn 0.3s ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +/* 🎨 背景遮罩 */ +.preview-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: transparent; +} + +/* 🎨 预览内容 */ +.preview-content { + flex: 1; + display: flex; + flex-direction: column; + position: relative; + z-index: 1; +} + +/* 🎨 头部工具栏 */ +.preview-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 32rpx; + background: var(--header-bg); + backdrop-filter: blur(20rpx); + border-bottom: 1rpx solid var(--border-color); +} + +.header-info { + flex: 1; + min-width: 0; +} + +.media-title { + display: block; + font-size: 32rpx; + font-weight: 600; + color: var(--text-primary); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + margin-bottom: 8rpx; +} + +.media-info { + font-size: 26rpx; + color: var(--text-secondary); +} + +.header-actions { + display: flex; + align-items: center; + gap: 16rpx; +} + +.action-btn { + width: 72rpx; + height: 72rpx; + border-radius: 36rpx; + background: var(--button-bg); + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + backdrop-filter: blur(10rpx); +} + +.action-btn:active { + background: var(--button-active); + transform: scale(0.9); +} + +.action-btn.close-btn { + background: rgba(255, 59, 48, 0.8); +} + +.action-icon { + font-size: 32rpx; + color: var(--text-primary); +} + +/* 🎨 媒体容器 */ +.media-container { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + position: relative; +} + +/* 🎨 图片预览 */ +.image-preview { + width: 100%; + height: 100%; + position: relative; +} + +.image-swiper { + width: 100%; + height: 100%; +} + +.image-item { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + position: relative; +} + +.preview-image { + max-width: 100%; + max-height: 100%; + border-radius: 16rpx; + box-shadow: var(--shadow); +} + +.image-counter { + position: absolute; + bottom: 40rpx; + left: 50%; + transform: translateX(-50%); + padding: 12rpx 24rpx; + background: var(--header-bg); + border-radius: 24rpx; + backdrop-filter: blur(20rpx); +} + +.counter-text { + font-size: 28rpx; + color: var(--text-primary); + font-weight: 500; +} + +/* 🎨 视频预览 */ +.video-preview { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; +} + +.preview-video { + width: 100%; + max-height: 80%; + border-radius: 16rpx; + box-shadow: var(--shadow); +} + +.video-info { + position: absolute; + bottom: 40rpx; + left: 50%; + transform: translateX(-50%); + display: flex; + gap: 24rpx; + padding: 12rpx 24rpx; + background: var(--header-bg); + border-radius: 24rpx; + backdrop-filter: blur(20rpx); +} + +.video-duration, +.video-size { + font-size: 26rpx; + color: var(--text-secondary); +} + +/* 🎨 文件预览 */ +.file-preview { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 80rpx 40rpx; + text-align: center; +} + +.file-icon-container { + width: 200rpx; + height: 200rpx; + border-radius: 32rpx; + background: var(--button-bg); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 40rpx; + backdrop-filter: blur(20rpx); + border: 2rpx solid var(--border-color); +} + +.file-icon { + font-size: 120rpx; +} + +.file-details { + margin-bottom: 60rpx; +} + +.file-name { + display: block; + font-size: 36rpx; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 16rpx; + word-break: break-word; +} + +.file-size, +.file-type { + display: block; + font-size: 28rpx; + color: var(--text-secondary); + margin-bottom: 8rpx; +} + +.file-actions { + display: flex; + gap: 24rpx; +} + +.file-action-btn { + padding: 24rpx 48rpx; + background: var(--button-bg); + border-radius: 32rpx; + border: 1rpx solid var(--border-color); + transition: all 0.3s ease; + backdrop-filter: blur(20rpx); +} + +.file-action-btn:active { + background: var(--button-active); + transform: scale(0.95); +} + +.action-text { + font-size: 30rpx; + color: var(--text-primary); + font-weight: 500; +} + +/* 🎨 音频预览 */ +.audio-preview { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 80rpx 40rpx; +} + +.audio-player { + display: flex; + flex-direction: column; + align-items: center; + gap: 40rpx; + margin-bottom: 60rpx; +} + +.audio-cover { + width: 200rpx; + height: 200rpx; + border-radius: 100rpx; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + display: flex; + align-items: center; + justify-content: center; + box-shadow: var(--shadow); +} + +.audio-icon { + font-size: 80rpx; + color: white; +} + +.audio-controls { + display: flex; + align-items: center; + gap: 32rpx; + width: 100%; + max-width: 600rpx; +} + +.play-btn { + width: 96rpx; + height: 96rpx; + border-radius: 48rpx; + background: var(--button-bg); + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + backdrop-filter: blur(20rpx); + border: 2rpx solid var(--border-color); +} + +.play-btn:active { + background: var(--button-active); + transform: scale(0.9); +} + +.play-btn.playing { + background: rgba(52, 199, 89, 0.8); +} + +.play-icon { + font-size: 40rpx; + color: var(--text-primary); +} + +.audio-progress { + flex: 1; +} + +.progress-bar { + height: 8rpx; + background: var(--button-bg); + border-radius: 4rpx; + margin-bottom: 16rpx; + overflow: hidden; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); + border-radius: 4rpx; + transition: width 0.3s ease; +} + +.time-info { + display: flex; + justify-content: space-between; +} + +.current-time, +.total-time { + font-size: 24rpx; + color: var(--text-secondary); +} + +.audio-info { + text-align: center; +} + +.audio-name { + display: block; + font-size: 32rpx; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 12rpx; + word-break: break-word; +} + +.audio-size { + font-size: 26rpx; + color: var(--text-secondary); +} + +/* 🎨 加载和错误状态 */ +.loading-overlay, +.error-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: var(--preview-bg); + border-radius: 16rpx; +} + +.loading-spinner { + width: 60rpx; + height: 60rpx; + border: 4rpx solid var(--border-color); + border-top: 4rpx solid var(--text-primary); + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 24rpx; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.loading-text, +.error-text { + font-size: 28rpx; + color: var(--text-secondary); + margin-bottom: 24rpx; +} + +.error-icon { + font-size: 80rpx; + margin-bottom: 24rpx; +} + +.retry-btn { + padding: 16rpx 32rpx; + background: var(--button-bg); + border-radius: 24rpx; + border: 1rpx solid var(--border-color); + transition: all 0.3s ease; +} + +.retry-btn:active { + background: var(--button-active); + transform: scale(0.95); +} + +.retry-text { + font-size: 26rpx; + color: var(--text-primary); +} + +/* 🎨 底部操作栏 */ +.preview-footer { + padding: 32rpx; + background: var(--header-bg); + backdrop-filter: blur(20rpx); + border-top: 1rpx solid var(--border-color); +} + +.footer-actions { + display: flex; + justify-content: space-around; + align-items: center; +} + +.footer-btn { + display: flex; + flex-direction: column; + align-items: center; + gap: 8rpx; + padding: 16rpx; + border-radius: 16rpx; + transition: all 0.3s ease; + min-width: 120rpx; +} + +.footer-btn:active { + background: var(--button-bg); + transform: scale(0.95); +} + +.footer-icon { + font-size: 32rpx; +} + +.footer-text { + font-size: 24rpx; + color: var(--text-secondary); +} + +/* 🎨 手势提示 */ +.gesture-tips { + position: absolute; + bottom: 160rpx; + left: 50%; + transform: translateX(-50%); + padding: 16rpx 32rpx; + background: var(--header-bg); + border-radius: 32rpx; + backdrop-filter: blur(20rpx); + animation: tipsFadeIn 0.5s ease-out 1s both; +} + +@keyframes tipsFadeIn { + from { + opacity: 0; + transform: translateX(-50%) translateY(20rpx); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } +} + +.tips-text { + font-size: 24rpx; + color: var(--text-secondary); + text-align: center; +} + +/* 📱 响应式设计 */ +@media screen and (max-width: 375px) { + .preview-header { + padding: 24rpx; + } + + .media-title { + font-size: 28rpx; + } + + .action-btn { + width: 64rpx; + height: 64rpx; + } + + .action-icon { + font-size: 28rpx; + } + + .file-icon-container { + width: 160rpx; + height: 160rpx; + } + + .file-icon { + font-size: 96rpx; + } +} + +@media screen and (min-width: 414px) { + .preview-header { + padding: 40rpx; + } + + .media-title { + font-size: 36rpx; + } + + .action-btn { + width: 80rpx; + height: 80rpx; + } + + .action-icon { + font-size: 36rpx; + } + + .file-icon-container { + width: 240rpx; + height: 240rpx; + } + + .file-icon { + font-size: 140rpx; + } +} diff --git a/components/mention-selector/mention-selector.js b/components/mention-selector/mention-selector.js new file mode 100644 index 0000000..807207e --- /dev/null +++ b/components/mention-selector/mention-selector.js @@ -0,0 +1,179 @@ +// 💬 @提醒选择组件逻辑 +const groupChatManager = require('../../utils/group-chat-manager.js'); + +Component({ + properties: { + // 是否显示 + visible: { + type: Boolean, + value: false + }, + + // 群ID + groupId: { + type: String, + value: '' + }, + + // 当前用户ID + currentUserId: { + type: String, + value: '' + }, + + // 是否显示@全体成员 + showMentionAll: { + type: Boolean, + value: true + } + }, + + data: { + // 成员数据 + allMembers: [], + filteredMembers: [], + + // 搜索关键词 + searchKeyword: '', + + // 加载状态 + loading: false + }, + + observers: { + 'visible': function(visible) { + if (visible && this.data.groupId) { + this.loadGroupMembers(); + } + }, + + 'groupId': function(groupId) { + if (groupId && this.data.visible) { + this.loadGroupMembers(); + } + } + }, + + methods: { + // 加载群成员 + async loadGroupMembers() { + if (!this.data.groupId) return; + + try { + this.setData({ + loading: true + }); + + const result = await groupChatManager.getGroupMembers(this.data.groupId); + + if (result.success) { + // 过滤掉当前用户 + const members = result.data.filter(member => member.userId !== this.data.currentUserId); + + this.setData({ + allMembers: members, + loading: false + }); + + // 应用搜索过滤 + this.applyFilter(); + + } else { + throw new Error(result.error || '获取群成员失败'); + } + + } catch (error) { + this.setData({ + loading: false + }); + + console.error('❌ 加载群成员失败:', error); + wx.showToast({ + title: '加载成员失败', + icon: 'none' + }); + } + }, + + // 搜索输入 + onSearchInput(e) { + const keyword = e.detail.value; + this.setData({ + searchKeyword: keyword + }); + this.applyFilter(); + }, + + // 清除搜索 + clearSearch() { + this.setData({ + searchKeyword: '' + }); + this.applyFilter(); + }, + + // 应用搜索过滤 + applyFilter() { + const keyword = this.data.searchKeyword.toLowerCase(); + let filtered = this.data.allMembers; + + if (keyword) { + filtered = this.data.allMembers.filter(member => { + const name = (member.nickname || member.username || '').toLowerCase(); + return name.includes(keyword); + }); + } + + this.setData({ + filteredMembers: filtered + }); + }, + + // @全体成员 + onMentionAll() { + + this.triggerEvent('mention', { + type: 'all', + text: '所有人', + userIds: this.data.allMembers.map(member => member.userId) + }); + + this.onClose(); + }, + + // @特定成员 + onMentionMember(e) { + const member = e.currentTarget.dataset.member; + + this.triggerEvent('mention', { + type: 'user', + text: member.nickname || member.username, + userId: member.userId, + userIds: [member.userId] + }); + + this.onClose(); + }, + + // 关闭选择器 + onClose() { + this.setData({ + searchKeyword: '', + filteredMembers: this.data.allMembers + }); + + this.triggerEvent('close'); + }, + + // 点击遮罩 + onMaskTap() { + this.onClose(); + }, + + // 阻止事件冒泡 + stopPropagation() { + // 阻止点击事件冒泡 + } + } +}); + diff --git a/components/mention-selector/mention-selector.json b/components/mention-selector/mention-selector.json new file mode 100644 index 0000000..a89ef4d --- /dev/null +++ b/components/mention-selector/mention-selector.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} diff --git a/components/mention-selector/mention-selector.wxml b/components/mention-selector/mention-selector.wxml new file mode 100644 index 0000000..24a7920 --- /dev/null +++ b/components/mention-selector/mention-selector.wxml @@ -0,0 +1,85 @@ + + + + + + 选择要@的成员 + + + + + + + + + 🔍 + + + + + + + + + + + + + + @ + + + + + 所有人 + @全体成员 + + + + @ + + + + + + + + + 群主 + + + 管理员 + + + + + {{item.nickname || item.username}} + {{item.status || ''}} + + + + @ + + + + + + 👥 + 没有找到相关成员 + + + + diff --git a/components/mention-selector/mention-selector.wxss b/components/mention-selector/mention-selector.wxss new file mode 100644 index 0000000..96b824c --- /dev/null +++ b/components/mention-selector/mention-selector.wxss @@ -0,0 +1,378 @@ +/* 💬 @提醒选择组件样式 */ + +/* CSS变量定义 */ +:host { + --primary-color: #007AFF; + --primary-light: #5AC8FA; + --success-color: #34C759; + --warning-color: #FF9500; + --background-color: #F2F2F7; + --surface-color: #FFFFFF; + --text-primary: #000000; + --text-secondary: #8E8E93; + --text-tertiary: #C7C7CC; + --border-color: #E5E5EA; + --shadow-light: 0 1rpx 3rpx rgba(0, 0, 0, 0.1); + --shadow-medium: 0 4rpx 12rpx rgba(0, 0, 0, 0.15); + --radius-small: 8rpx; + --radius-medium: 12rpx; + --radius-large: 20rpx; +} + +/* 🌙 深色模式支持 */ +@media (prefers-color-scheme: dark) { + :host { + --primary-color: #0A84FF; + --primary-light: #64D2FF; + --success-color: #30D158; + --warning-color: #FF9F0A; + --background-color: #000000; + --surface-color: #1C1C1E; + --text-primary: #FFFFFF; + --text-secondary: #8E8E93; + --text-tertiary: #48484A; + --border-color: #38383A; + --shadow-light: 0 1rpx 3rpx rgba(0, 0, 0, 0.3); + --shadow-medium: 0 4rpx 12rpx rgba(0, 0, 0, 0.4); + } +} + +.mention-selector-container { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: flex-end; + animation: fadeIn 0.3s ease-out; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +.selector-content { + width: 100%; + max-height: 80vh; + background: var(--surface-color); + border-radius: var(--radius-large) var(--radius-large) 0 0; + box-shadow: var(--shadow-medium); + animation: slideUp 0.3s ease-out; + display: flex; + flex-direction: column; + overflow: hidden; +} + +@keyframes slideUp { + from { + transform: translateY(100%); + } + to { + transform: translateY(0); + } +} + +/* 🎨 选择器头部 */ +.selector-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 32rpx; + border-bottom: 1rpx solid var(--border-color); + background: var(--background-color); +} + +.header-title { + font-size: 36rpx; + font-weight: 600; + color: var(--text-primary); +} + +.close-btn { + width: 64rpx; + height: 64rpx; + border-radius: 32rpx; + background: var(--surface-color); + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.close-btn:active { + background: var(--border-color); + transform: scale(0.9); +} + +.close-icon { + font-size: 28rpx; + color: var(--text-secondary); +} + +/* 🎨 搜索框 */ +.search-container { + padding: 24rpx 32rpx; + background: var(--surface-color); + border-bottom: 1rpx solid var(--border-color); +} + +.search-input-wrapper { + display: flex; + align-items: center; + background: var(--background-color); + border: 1rpx solid var(--border-color); + border-radius: var(--radius-small); + padding: 0 24rpx; + transition: all 0.3s ease; +} + +.search-input-wrapper:focus-within { + border-color: var(--primary-color); + box-shadow: 0 0 0 4rpx rgba(0, 122, 255, 0.1); +} + +.search-icon { + font-size: 28rpx; + color: var(--text-secondary); + margin-right: 16rpx; +} + +.search-input { + flex: 1; + height: 80rpx; + font-size: 28rpx; + color: var(--text-primary); +} + +.clear-search { + width: 48rpx; + height: 48rpx; + border-radius: 24rpx; + background: var(--text-tertiary); + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.clear-search:active { + transform: scale(0.9); +} + +.clear-icon { + font-size: 24rpx; + color: white; +} + +/* 🎨 成员列表 */ +.members-list { + flex: 1; + background: var(--surface-color); +} + +.member-item { + display: flex; + align-items: center; + padding: 24rpx 32rpx; + border-bottom: 1rpx solid var(--border-color); + transition: all 0.2s ease; +} + +.member-item:last-child { + border-bottom: none; +} + +.member-item:active { + background: var(--background-color); +} + +.member-item.mention-all { + background: rgba(0, 122, 255, 0.05); +} + +.member-item.mention-all:active { + background: rgba(0, 122, 255, 0.1); +} + +.member-avatar-container { + position: relative; + margin-right: 24rpx; +} + +.member-avatar { + width: 80rpx; + height: 80rpx; + border-radius: 40rpx; + border: 2rpx solid var(--border-color); +} + +.mention-all-avatar { + width: 80rpx; + height: 80rpx; + border-radius: 40rpx; + background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%); + display: flex; + align-items: center; + justify-content: center; + border: 2rpx solid var(--border-color); +} + +.mention-all-icon { + font-size: 36rpx; + color: white; + font-weight: bold; +} + +.role-badge { + position: absolute; + bottom: -6rpx; + right: -6rpx; + padding: 4rpx 8rpx; + border-radius: 12rpx; + border: 2rpx solid var(--surface-color); +} + +.role-badge.owner { + background: var(--warning-color); +} + +.role-badge.admin { + background: var(--primary-color); +} + +.role-text { + font-size: 20rpx; + color: white; + font-weight: 600; +} + +.member-info { + flex: 1; + min-width: 0; +} + +.member-name { + font-size: 30rpx; + font-weight: 500; + color: var(--text-primary); + display: block; + margin-bottom: 8rpx; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.member-desc { + font-size: 26rpx; + color: var(--text-secondary); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.member-action { + display: flex; + align-items: center; + justify-content: center; + width: 64rpx; + height: 64rpx; + border-radius: 32rpx; + background: var(--primary-color); + transition: all 0.2s ease; +} + +.member-action:active { + transform: scale(0.9); +} + +.action-text { + font-size: 28rpx; + color: white; + font-weight: bold; +} + +/* 🎨 空状态 */ +.empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 80rpx 40rpx; + text-align: center; +} + +.empty-icon { + font-size: 120rpx; + margin-bottom: 24rpx; + opacity: 0.5; +} + +.empty-text { + font-size: 28rpx; + color: var(--text-secondary); +} + +/* 📱 响应式设计 */ +@media screen and (max-width: 375px) { + .selector-header, + .search-container, + .member-item { + padding-left: 24rpx; + padding-right: 24rpx; + } + + .member-avatar, + .mention-all-avatar { + width: 64rpx; + height: 64rpx; + border-radius: 32rpx; + } + + .mention-all-icon { + font-size: 28rpx; + } + + .member-action { + width: 48rpx; + height: 48rpx; + border-radius: 24rpx; + } + + .action-text { + font-size: 24rpx; + } +} + +@media screen and (min-width: 414px) { + .selector-header, + .search-container, + .member-item { + padding-left: 40rpx; + padding-right: 40rpx; + } + + .member-avatar, + .mention-all-avatar { + width: 96rpx; + height: 96rpx; + border-radius: 48rpx; + } + + .mention-all-icon { + font-size: 40rpx; + } + + .member-action { + width: 80rpx; + height: 80rpx; + border-radius: 40rpx; + } + + .action-text { + font-size: 32rpx; + } +} diff --git a/components/message-action-menu/message-action-menu.js b/components/message-action-menu/message-action-menu.js new file mode 100644 index 0000000..a248999 --- /dev/null +++ b/components/message-action-menu/message-action-menu.js @@ -0,0 +1,535 @@ +// ✨ 消息操作菜单组件逻辑 +const messageInteractionManager = require('../../utils/message-interaction-manager.js'); + +Component({ + properties: { + // 是否显示菜单 + visible: { + type: Boolean, + value: false + }, + + // 消息对象 + message: { + type: Object, + value: {} + }, + + // 是否是自己的消息 + isOwnMessage: { + type: Boolean, + value: false + }, + + // 可用的操作 + actions: { + type: Object, + value: { + quote: true, // 引用回复 + forward: true, // 转发 + favorite: true, // 收藏 + multiSelect: true, // 多选 + copy: true, // 复制 + recall: true, // 撤回 + delete: true, // 删除 + report: true // 举报 + } + }, + + // 是否显示表情回应 + showReactions: { + type: Boolean, + value: true + }, + + // 是否显示消息信息 + showMessageInfo: { + type: Boolean, + value: false + } + }, + + data: { + // 常用表情 + commonEmojis: ['👍', '❤️', '😂', '😮', '😢', '😡'], + + // 是否可以撤回 + canRecall: false, + + // 表情选择器 + showEmojiPicker: false, + currentEmojiCategory: 'recent', + currentEmojiList: [], + + // 表情分类 + emojiCategories: { + recent: ['👍', '❤️', '😂', '😮', '😢', '😡', '🎉', '🔥'], + smileys: ['😀', '😃', '😄', '😁', '😆', '😅', '😂', '🤣', '😊', '😇', '🙂', '🙃', '😉', '😌', '😍', '🥰', '😘', '😗', '😙', '😚', '😋', '😛', '😝', '😜', '🤪', '🤨', '🧐', '🤓', '😎', '🤩', '🥳'], + gestures: ['👍', '👎', '👌', '✌️', '🤞', '🤟', '🤘', '🤙', '👈', '👉', '👆', '🖕', '👇', '☝️', '👋', '🤚', '🖐️', '✋', '🖖', '👏', '🙌', '🤲', '🤝', '🙏'], + hearts: ['❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍', '🤎', '💔', '❣️', '💕', '💞', '💓', '💗', '💖', '💘', '💝', '💟'] + } + }, + + observers: { + 'message, isOwnMessage': function(message, isOwnMessage) { + if (message && message.messageId) { + this.checkRecallPermission(); + } + } + }, + + lifetimes: { + attached() { + + this.initEmojiList(); + } + }, + + methods: { + // ✨ ===== 基础操作 ===== + + // 阻止事件冒泡 + stopPropagation() { + // 阻止点击事件冒泡到遮罩层 + }, + + // 遮罩点击 + onMaskTap() { + this.closeMenu(); + }, + + // 关闭菜单 + closeMenu() { + this.setData({ + visible: false, + showEmojiPicker: false + }); + + this.triggerEvent('close'); + }, + + // 👍 ===== 表情回应操作 ===== + + // 表情点击 + async onReactionTap(e) { + const emoji = e.currentTarget.dataset.emoji; + + try { + const userId = wx.getStorageSync('userId'); + if (!userId) { + // 未登录用户不显示提示,直接跳转到登录页 + wx.navigateTo({ url: '/pages/login/login' }); + return; + } + + // 添加表情回应 + const result = await messageInteractionManager.addReaction( + this.data.message.messageId, + emoji, + userId + ); + + if (result.success) { + // 触发表情回应事件 + this.triggerEvent('reaction', { + messageId: this.data.message.messageId, + emoji: emoji, + action: 'add' + }); + + // 关闭菜单 + this.closeMenu(); + + wx.showToast({ + title: '表情回应已添加', + icon: 'success' + }); + } else { + wx.showToast({ + title: result.error || '添加失败', + icon: 'none' + }); + } + + } catch (error) { + console.error('❌ 添加表情回应失败:', error); + wx.showToast({ + title: '操作失败', + icon: 'none' + }); + } + }, + + // 显示更多表情 + showMoreEmojis() { + this.setData({ + showEmojiPicker: true, + currentEmojiCategory: 'recent' + }); + this.updateEmojiList(); + }, + + // 关闭表情选择器 + closeEmojiPicker() { + this.setData({ + showEmojiPicker: false + }); + }, + + // 切换表情分类 + switchEmojiCategory(e) { + const category = e.currentTarget.dataset.category; + this.setData({ + currentEmojiCategory: category + }); + this.updateEmojiList(); + }, + + // 表情选择 + async onEmojiSelect(e) { + const emoji = e.currentTarget.dataset.emoji; + + // 添加到最近使用 + this.addToRecentEmojis(emoji); + + // 执行表情回应 + await this.onReactionTap({ currentTarget: { dataset: { emoji } } }); + }, + + // 初始化表情列表 + initEmojiList() { + this.setData({ + currentEmojiList: this.data.emojiCategories.recent + }); + }, + + // 更新表情列表 + updateEmojiList() { + const category = this.data.currentEmojiCategory; + const emojiList = this.data.emojiCategories[category] || []; + + this.setData({ + currentEmojiList: emojiList + }); + }, + + // 添加到最近使用表情 + addToRecentEmojis(emoji) { + let recentEmojis = [...this.data.emojiCategories.recent]; + + // 移除已存在的 + recentEmojis = recentEmojis.filter(e => e !== emoji); + + // 添加到开头 + recentEmojis.unshift(emoji); + + // 限制数量 + if (recentEmojis.length > 20) { + recentEmojis = recentEmojis.slice(0, 20); + } + + // 更新数据 + this.setData({ + [`emojiCategories.recent`]: recentEmojis + }); + + // 如果当前显示的是最近分类,更新列表 + if (this.data.currentEmojiCategory === 'recent') { + this.setData({ + currentEmojiList: recentEmojis + }); + } + }, + + // 🎯 ===== 操作按钮处理 ===== + + // 操作点击 + async onActionTap(e) { + const action = e.currentTarget.dataset.action; + + switch (action) { + case 'quote': + this.handleQuote(); + break; + case 'forward': + this.handleForward(); + break; + case 'favorite': + this.handleFavorite(); + break; + case 'multiSelect': + this.handleMultiSelect(); + break; + case 'copy': + this.handleCopy(); + break; + case 'recall': + this.handleRecall(); + break; + case 'delete': + this.handleDelete(); + break; + case 'report': + this.handleReport(); + break; + default: + console.warn('⚠️ 未知操作:', action); + } + }, + + // 处理引用回复 + handleQuote() { + + this.triggerEvent('action', { + action: 'quote', + message: this.data.message + }); + + this.closeMenu(); + }, + + // 处理转发 + handleForward() { + + this.triggerEvent('action', { + action: 'forward', + message: this.data.message + }); + + this.closeMenu(); + }, + + // 处理收藏 + async handleFavorite() { + + try { + const userId = wx.getStorageSync('userId'); + const messageId = this.data.message.messageId; + const isFavorited = this.data.message.favorited; + + let result; + if (isFavorited) { + result = await messageInteractionManager.unfavoriteMessage(messageId, userId); + } else { + result = await messageInteractionManager.favoriteMessage(messageId, userId); + } + + if (result.success) { + this.triggerEvent('action', { + action: 'favorite', + message: this.data.message, + favorited: !isFavorited + }); + + wx.showToast({ + title: isFavorited ? '已取消收藏' : '已收藏', + icon: 'success' + }); + } else { + wx.showToast({ + title: result.error || '操作失败', + icon: 'none' + }); + } + + } catch (error) { + console.error('❌ 收藏操作失败:', error); + wx.showToast({ + title: '操作失败', + icon: 'none' + }); + } + + this.closeMenu(); + }, + + // 处理多选 + handleMultiSelect() { + + this.triggerEvent('action', { + action: 'multiSelect', + message: this.data.message + }); + + this.closeMenu(); + }, + + // 处理复制 + handleCopy() { + + if (this.data.message.msgType === 'text') { + wx.setClipboardData({ + data: this.data.message.content, + success: () => { + wx.showToast({ + title: '已复制到剪贴板', + icon: 'success' + }); + } + }); + } + + this.closeMenu(); + }, + + // 处理撤回 + async handleRecall() { + + try { + const userId = wx.getStorageSync('userId'); + const messageId = this.data.message.messageId; + + const result = await messageInteractionManager.recallMessage(messageId, userId); + + if (result.success) { + this.triggerEvent('action', { + action: 'recall', + message: this.data.message + }); + + wx.showToast({ + title: '消息已撤回', + icon: 'success' + }); + } else { + wx.showToast({ + title: result.error || '撤回失败', + icon: 'none' + }); + } + + } catch (error) { + console.error('❌ 撤回消息失败:', error); + wx.showToast({ + title: '撤回失败', + icon: 'none' + }); + } + + this.closeMenu(); + }, + + // 处理删除 + handleDelete() { + + wx.showModal({ + title: '删除消息', + content: '确定要删除这条消息吗?', + success: (res) => { + if (res.confirm) { + this.triggerEvent('action', { + action: 'delete', + message: this.data.message + }); + } + } + }); + + this.closeMenu(); + }, + + // 处理举报 + handleReport() { + + wx.showActionSheet({ + itemList: ['垃圾信息', '违法违规', '色情内容', '暴力内容', '其他'], + success: (res) => { + const reasons = ['spam', 'illegal', 'sexual', 'violence', 'other']; + const reason = reasons[res.tapIndex]; + + this.triggerEvent('action', { + action: 'report', + message: this.data.message, + reason: reason + }); + } + }); + + this.closeMenu(); + }, + + // 🔧 ===== 工具方法 ===== + + // 检查撤回权限 + async checkRecallPermission() { + try { + const userId = wx.getStorageSync('userId'); + const messageId = this.data.message.messageId; + + if (!userId || !messageId) { + this.setData({ canRecall: false }); + return; + } + + const result = await messageInteractionManager.checkRecallPermission(messageId, userId); + this.setData({ canRecall: result.allowed }); + + } catch (error) { + console.error('❌ 检查撤回权限失败:', error); + this.setData({ canRecall: false }); + } + }, + + // 格式化时间 + formatTime(timestamp) { + if (!timestamp) return ''; + + const date = new Date(timestamp); + const now = new Date(); + const diffMs = now.getTime() - date.getTime(); + const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); + + if (diffDays === 0) { + // 今天 + return date.toLocaleTimeString('zh-CN', { + hour: '2-digit', + minute: '2-digit' + }); + } else if (diffDays === 1) { + // 昨天 + return '昨天 ' + date.toLocaleTimeString('zh-CN', { + hour: '2-digit', + minute: '2-digit' + }); + } else { + // 更早 + return date.toLocaleDateString('zh-CN') + ' ' + date.toLocaleTimeString('zh-CN', { + hour: '2-digit', + minute: '2-digit' + }); + } + }, + + // 获取消息类型文本 + getMessageTypeText(msgType) { + const typeMap = { + 'text': '文本', + 'image': '图片', + 'video': '视频', + 'voice': '语音', + 'file': '文件', + 'location': '位置', + 'card': '名片' + }; + + return typeMap[msgType] || '未知'; + }, + + // 格式化文件大小 + formatFileSize(size) { + if (!size) return ''; + + const units = ['B', 'KB', 'MB', 'GB']; + let unitIndex = 0; + let fileSize = size; + + while (fileSize >= 1024 && unitIndex < units.length - 1) { + fileSize /= 1024; + unitIndex++; + } + + return `${fileSize.toFixed(1)} ${units[unitIndex]}`; + } + } +}); + diff --git a/components/message-action-menu/message-action-menu.json b/components/message-action-menu/message-action-menu.json new file mode 100644 index 0000000..a89ef4d --- /dev/null +++ b/components/message-action-menu/message-action-menu.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} diff --git a/components/message-action-menu/message-action-menu.wxml b/components/message-action-menu/message-action-menu.wxml new file mode 100644 index 0000000..fb869cb --- /dev/null +++ b/components/message-action-menu/message-action-menu.wxml @@ -0,0 +1,191 @@ + + + + + + + + + + + 添加表情回应 + + + + + {{item}} + + + + + + + + + + + + + + + 💬 + + 引用 + + + + + + 📤 + + 转发 + + + + + + {{message.favorited ? '⭐' : '☆'}} + + {{message.favorited ? '取消收藏' : '收藏'}} + + + + + + 📋 + + 多选 + + + + + + 📄 + + 复制 + + + + + + 🔄 + + 撤回 + + + + + + 🗑️ + + 删除 + + + + + + ⚠️ + + 举报 + + + + + + + 发送时间: + {{formatTime(message.timestamp)}} + + + + 编辑时间: + {{formatTime(message.editedAt)}} + + + + 消息类型: + {{getMessageTypeText(message.msgType)}} + + + + 文件大小: + {{formatFileSize(message.size)}} + + + + + + + + + + 选择表情 + + + + + + + + 最近 + + + 笑脸 + + + 手势 + + + 爱心 + + + + + + + {{item}} + + + + + diff --git a/components/message-action-menu/message-action-menu.wxss b/components/message-action-menu/message-action-menu.wxss new file mode 100644 index 0000000..5d8e427 --- /dev/null +++ b/components/message-action-menu/message-action-menu.wxss @@ -0,0 +1,446 @@ +/* ✨ 消息操作菜单组件样式 */ + +/* CSS变量定义 */ +.message-action-menu { + --menu-bg: rgba(0, 0, 0, 0.8); + --content-bg: #FFFFFF; + --border-color: #E5E5EA; + --text-primary: #000000; + --text-secondary: #8E8E93; + --text-danger: #FF3B30; + --button-bg: #F2F2F7; + --button-active: #E5E5EA; + --shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.2); + --radius: 16rpx; +} + +/* 🌙 深色模式支持 */ +@media (prefers-color-scheme: dark) { + .message-action-menu { + --content-bg: #1C1C1E; + --border-color: #38383A; + --text-primary: #FFFFFF; + --text-secondary: #8E8E93; + --text-danger: #FF453A; + --button-bg: #2C2C2E; + --button-active: #3A3A3C; + --shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.4); + } +} + +/* 🎨 菜单容器 */ +.message-action-menu { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9998; + display: flex; + align-items: flex-end; + justify-content: center; + animation: fadeIn 0.3s ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +/* 🎨 背景遮罩 */ +.menu-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--menu-bg); +} + +/* 🎨 菜单内容 */ +.menu-content { + width: 100%; + max-width: 750rpx; + background: var(--content-bg); + border-radius: var(--radius) var(--radius) 0 0; + box-shadow: var(--shadow); + animation: slideUp 0.3s ease-out; + overflow: hidden; +} + +@keyframes slideUp { + from { + transform: translateY(100%); + } + to { + transform: translateY(0); + } +} + +/* 🎨 表情回应区域 */ +.reactions-section { + padding: 32rpx; + border-bottom: 1rpx solid var(--border-color); +} + +.reactions-title { + margin-bottom: 24rpx; +} + +.title-text { + font-size: 32rpx; + font-weight: 600; + color: var(--text-primary); +} + +.reactions-grid { + display: flex; + flex-wrap: wrap; + gap: 16rpx; +} + +.reaction-item { + width: 88rpx; + height: 88rpx; + border-radius: 44rpx; + background: var(--button-bg); + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + border: 2rpx solid transparent; +} + +.reaction-item:active { + background: var(--button-active); + transform: scale(0.9); +} + +.reaction-emoji { + font-size: 48rpx; +} + +.more-emoji { + border: 2rpx dashed var(--border-color); + background: transparent; +} + +.more-icon { + font-size: 32rpx; + color: var(--text-secondary); +} + +/* 🎨 操作按钮区域 */ +.actions-section { + padding: 16rpx 0; +} + +.action-item { + display: flex; + align-items: center; + padding: 24rpx 32rpx; + transition: all 0.2s ease; + border-bottom: 1rpx solid var(--border-color); +} + +.action-item:last-child { + border-bottom: none; +} + +.action-item:active { + background: var(--button-bg); +} + +.action-item.danger { + color: var(--text-danger); +} + +.action-item.danger .action-text { + color: var(--text-danger); +} + +.action-icon { + width: 72rpx; + height: 72rpx; + border-radius: 36rpx; + background: var(--button-bg); + display: flex; + align-items: center; + justify-content: center; + margin-right: 24rpx; +} + +.action-item.danger .action-icon { + background: rgba(255, 59, 48, 0.1); +} + +.icon-text { + font-size: 32rpx; +} + +.action-text { + font-size: 32rpx; + color: var(--text-primary); + font-weight: 500; +} + +/* 🎨 消息信息区域 */ +.message-info-section { + padding: 32rpx; + background: var(--button-bg); + border-top: 1rpx solid var(--border-color); +} + +.info-item { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16rpx; +} + +.info-item:last-child { + margin-bottom: 0; +} + +.info-label { + font-size: 28rpx; + color: var(--text-secondary); +} + +.info-value { + font-size: 28rpx; + color: var(--text-primary); + font-weight: 500; +} + +/* 🎨 表情选择器弹窗 */ +.emoji-picker-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + background: var(--menu-bg); + display: flex; + align-items: center; + justify-content: center; + animation: fadeIn 0.3s ease-out; +} + +.emoji-picker-content { + width: 90%; + max-width: 600rpx; + height: 80%; + max-height: 800rpx; + background: var(--content-bg); + border-radius: var(--radius); + box-shadow: var(--shadow); + display: flex; + flex-direction: column; + overflow: hidden; + animation: scaleIn 0.3s ease-out; +} + +@keyframes scaleIn { + from { + transform: scale(0.8); + opacity: 0; + } + to { + transform: scale(1); + opacity: 1; + } +} + +.emoji-picker-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 32rpx; + border-bottom: 1rpx solid var(--border-color); +} + +.picker-title { + font-size: 36rpx; + font-weight: 600; + color: var(--text-primary); +} + +.close-btn { + width: 64rpx; + height: 64rpx; + border-radius: 32rpx; + background: var(--button-bg); + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.close-btn:active { + background: var(--button-active); + transform: scale(0.9); +} + +.close-icon { + font-size: 28rpx; + color: var(--text-secondary); +} + +/* 🎨 表情分类标签 */ +.emoji-categories { + display: flex; + border-bottom: 1rpx solid var(--border-color); +} + +.category-tab { + flex: 1; + padding: 24rpx 16rpx; + text-align: center; + transition: all 0.2s ease; + border-bottom: 4rpx solid transparent; +} + +.category-tab.active { + border-bottom-color: #007AFF; +} + +.category-tab:active { + background: var(--button-bg); +} + +.tab-text { + font-size: 28rpx; + color: var(--text-secondary); + font-weight: 500; +} + +.category-tab.active .tab-text { + color: #007AFF; + font-weight: 600; +} + +/* 🎨 表情网格 */ +.emoji-grid-container { + flex: 1; + padding: 16rpx; +} + +.emoji-grid { + display: flex; + flex-wrap: wrap; + gap: 8rpx; +} + +.emoji-grid-item { + width: 88rpx; + height: 88rpx; + border-radius: 16rpx; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.emoji-grid-item:active { + background: var(--button-bg); + transform: scale(0.9); +} + +.grid-emoji { + font-size: 48rpx; +} + +/* 📱 响应式设计 */ +@media screen and (max-width: 375px) { + .reactions-section { + padding: 24rpx; + } + + .reaction-item { + width: 72rpx; + height: 72rpx; + border-radius: 36rpx; + } + + .reaction-emoji { + font-size: 40rpx; + } + + .action-item { + padding: 20rpx 24rpx; + } + + .action-icon { + width: 64rpx; + height: 64rpx; + border-radius: 32rpx; + margin-right: 20rpx; + } + + .icon-text { + font-size: 28rpx; + } + + .action-text { + font-size: 28rpx; + } + + .emoji-grid-item { + width: 72rpx; + height: 72rpx; + } + + .grid-emoji { + font-size: 40rpx; + } +} + +@media screen and (min-width: 414px) { + .reactions-section { + padding: 40rpx; + } + + .reaction-item { + width: 96rpx; + height: 96rpx; + border-radius: 48rpx; + } + + .reaction-emoji { + font-size: 52rpx; + } + + .action-item { + padding: 28rpx 40rpx; + } + + .action-icon { + width: 80rpx; + height: 80rpx; + border-radius: 40rpx; + margin-right: 28rpx; + } + + .icon-text { + font-size: 36rpx; + } + + .action-text { + font-size: 36rpx; + } + + .emoji-grid-item { + width: 96rpx; + height: 96rpx; + } + + .grid-emoji { + font-size: 52rpx; + } +} diff --git a/components/voice-message/voice-message.js b/components/voice-message/voice-message.js new file mode 100644 index 0000000..bd03f51 --- /dev/null +++ b/components/voice-message/voice-message.js @@ -0,0 +1,161 @@ + +Component({ + properties: { + // 语音消息数据 + voiceData: { + type: Object, + value: {}, + observer: 'onVoiceDataChange' + }, + + // 是否为自己发送的消息 + isSelf: { + type: Boolean, + value: false + }, + + // 消息ID + messageId: { + type: String, + value: '' + } + }, + + data: { + // 播放状态 + isPlaying: false, + + // 波形数据 + waveformData: [], + + // 语音信息 + voiceUrl: '', + voiceDuration: 0 + }, + + lifetimes: { + attached() { + this.initComponent(); + }, + + detached() { + this.cleanup(); + } + }, + + methods: { + // 初始化组件 + initComponent() { + // 生成波形数据 + this.generateWaveform(); + + // 获取全局音频上下文 + const app = getApp(); + this.audioContext = app.globalData.audioContext || wx.createInnerAudioContext(); + + // 注册音频事件 + this.setupAudioEvents(); + }, + + // 语音数据变化处理 + onVoiceDataChange(newData, oldData) { + if (!newData || JSON.stringify(newData) === JSON.stringify(oldData)) { + return; + } + + this.setData({ + voiceUrl: newData.url || '', + voiceDuration: newData.duration || 0 + }); + + // 重新生成波形 + this.generateWaveform(); + }, + + // 设置音频事件监听 + setupAudioEvents() { + if (!this.audioContext) return; + + this.audioContext.onPlay(() => { + if (this.isCurrentAudio()) { + this.setData({ isPlaying: true }); + } + }); + + this.audioContext.onPause(() => { + if (this.isCurrentAudio()) { + this.setData({ isPlaying: false }); + } + }); + + this.audioContext.onEnded(() => { + if (this.isCurrentAudio()) { + this.setData({ isPlaying: false }); + } + }); + + this.audioContext.onError((err) => { + console.error('语音播放错误:', err); + if (this.isCurrentAudio()) { + this.setData({ isPlaying: false }); + wx.showToast({ title: '播放失败', icon: 'none' }); + } + }); + }, + + // 检查是否为当前音频 + isCurrentAudio() { + return this.audioContext && this.audioContext.src === this.data.voiceUrl; + }, + + // 切换播放状态 + togglePlay() { + if (!this.data.voiceUrl) { + wx.showToast({ title: '语音地址无效', icon: 'none' }); + return; + } + + try { + if (this.data.isPlaying) { + this.audioContext.pause(); + } else { + // 停止其他正在播放的音频 + if (this.audioContext.src !== this.data.voiceUrl) { + this.audioContext.src = this.data.voiceUrl; + } + this.audioContext.play(); + } + } catch (error) { + console.error('播放语音失败:', error); + wx.showToast({ title: '播放失败', icon: 'none' }); + } + }, + + // 生成波形数据 + generateWaveform() { + const duration = this.data.voiceDuration || 1000; + const barCount = Math.min(Math.max(Math.floor(duration / 200), 8), 30); // 8-30个波形条 + + const waveformData = []; + for (let i = 0; i < barCount; i++) { + // 生成随机高度,模拟真实波形 + const height = Math.random() * 60 + 20; // 20-80%的高度 + waveformData.push(height); + } + + this.setData({ waveformData }); + }, + + // 清理资源 + cleanup() { + // 如果当前正在播放,停止播放 + if (this.data.isPlaying && this.audioContext) { + try { + this.audioContext.stop(); + } catch (e) { + // 忽略停止错误 + } + } + } + } +}); diff --git a/components/voice-message/voice-message.json b/components/voice-message/voice-message.json new file mode 100644 index 0000000..a89ef4d --- /dev/null +++ b/components/voice-message/voice-message.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} diff --git a/components/voice-message/voice-message.wxml b/components/voice-message/voice-message.wxml new file mode 100644 index 0000000..794a874 --- /dev/null +++ b/components/voice-message/voice-message.wxml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + {{formatDuration(duration)}} + + + + + + + + + + {{formatTime(currentTime)}} + {{formatTime(duration)}} + + + + + + + 加载中... + + + + + ⚠️ + 播放失败 + 重试 + + diff --git a/components/voice-message/voice-message.wxss b/components/voice-message/voice-message.wxss new file mode 100644 index 0000000..57c9ccd --- /dev/null +++ b/components/voice-message/voice-message.wxss @@ -0,0 +1,392 @@ +/* 🎤 语音消息组件样式 */ + +/* CSS变量定义 */ +.voice-message-container { + --primary-color: #007AFF; + --primary-light: #5AC8FA; + --success-color: #34C759; + --warning-color: #FF9500; + --danger-color: #FF3B30; + --background-light: #F2F2F7; + --background-dark: #1C1C1E; + --text-primary: #000000; + --text-secondary: #8E8E93; + --border-color: #E5E5EA; + --shadow-light: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); + --radius-medium: 12rpx; + --radius-large: 20rpx; +} + +/* 🌙 深色模式支持 */ +@media (prefers-color-scheme: dark) { + .voice-message-container { + --primary-color: #0A84FF; + --background-light: #2C2C2E; + --background-dark: #1C1C1E; + --text-primary: #FFFFFF; + --text-secondary: #8E8E93; + --border-color: #38383A; + --shadow-light: 0 2rpx 8rpx rgba(0, 0, 0, 0.3); + } +} + +.voice-message-container { + max-width: 100%; + width: 100%; + margin: 8rpx 0; + position: relative; + box-sizing: border-box; +} + +/* 🎨 语音气泡 */ +.voice-bubble { + display: flex; + align-items: center; + padding: 24rpx; + border-radius: var(--radius-large); + box-shadow: var(--shadow-light); + transition: all 0.3s ease; + min-width: 200rpx; + position: relative; + overflow: hidden; + width: 100%; + max-width: 100%; + box-sizing: border-box; +} + +/* 自己发送的消息 - 使用聊天气泡的绿色 */ +.voice-message-container.self .voice-bubble { + background: #4DD1A1; + color: white; +} + +/* 他人发送的消息 - 使用聊天气泡的灰色 */ +.voice-message-container.other .voice-bubble { + background: #D9D9D9; + color: var(--text-primary); + border: 1rpx solid rgba(255,255,255,0.03); +} + +/* 播放状态 */ +.voice-message-container.playing .voice-bubble { + transform: scale(1.02); +} + +.voice-message-container.self.playing .voice-bubble { + background: #3CB88F; /* 稍微深一点的绿色表示播放中 */ +} + +.voice-message-container.other.playing .voice-bubble { + background: #C0C0C0; /* 稍微深一点的灰色表示播放中 */ + border-color: #A0A0A0; +} + +/* 🎵 播放按钮 */ +.play-button { + width: 80rpx; + height: 80rpx; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 24rpx; + transition: all 0.3s ease; + position: relative; + box-sizing: border-box; + overflow: hidden; + flex-shrink: 0; /* 不允许在flex布局中被压缩 */ + flex: 0 0 auto; /* 宽高由自身决定 */ + min-width: 80rpx; /* 保底宽度,维持正圆 */ +} + +.voice-message-container.self .play-button { + background: rgba(255, 255, 255, 0.3); /* 在绿色背景上更明显的白色按钮 */ +} + +.voice-message-container.other .play-button { + background: rgba(0, 0, 0, 0.15); /* 在灰色背景上的深色按钮 */ +} + +.play-button:active { + transform: scale(0.95); +} + +.play-icon { + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; +} + +.play-icon .icon { + font-size: 32rpx; + font-weight: bold; +} + +.voice-message-container.self .play-icon .icon { + color: white; /* 白色图标在绿色背景上 */ +} + +.voice-message-container.other .play-icon .icon { + color: #333333; /* 深色图标在灰色背景上 */ +} + +/* 播放动画 */ +.play-icon.play .icon { + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.7; } +} + +/* 🌊 语音波形 */ +.voice-waveform { + flex: 1; + margin-right: 24rpx; + height: 60rpx; + display: flex; + align-items: center; + min-width: 0; /* 允许在狭窄容器中收缩,避免溢出 */ + overflow: hidden; +} + +.waveform-container { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + height: 100%; + gap: 4rpx; +} + +.wave-bar { + width: 6rpx; + border-radius: 3rpx; + transition: all 0.3s ease; + min-height: 8rpx; +} + +.voice-message-container.self .wave-bar { + background: rgba(255, 255, 255, 0.5); /* 在绿色背景上更明显的波形 */ +} + +.voice-message-container.other .wave-bar { + background: rgba(0, 0, 0, 0.2); /* 在灰色背景上的深色波形 */ +} + +.voice-message-container.self .wave-bar.active { + background: white; + transform: scaleY(1.2); +} + +.voice-message-container.other .wave-bar.active { + background: rgba(0, 0, 0, 0.5); /* 深色波形激活状态 */ + transform: scaleY(1.2); +} + +/* 波形动画 */ +.voice-message-container.playing .wave-bar.active { + animation: waveAnimation 1.5s ease-in-out infinite; +} + +@keyframes waveAnimation { + 0%, 100% { transform: scaleY(1); } + 50% { transform: scaleY(1.5); } +} + +/* ⏱️ 语音时长 */ +.voice-duration { + min-width: 60rpx; + text-align: right; +} + +.duration-text { + font-size: 24rpx; + font-weight: 500; +} + +.voice-message-container.self .duration-text { + color: rgba(255, 255, 255, 0.95); /* 白色时长文字在绿色背景上 */ +} + +.voice-message-container.other .duration-text { + color: rgba(0, 0, 0, 0.6); /* 深色时长文字在灰色背景上 */ +} + +/* 📊 播放进度条 */ +.progress-container { + margin-top: 16rpx; + padding: 0 24rpx; +} + +.progress-bar { + height: 4rpx; + background: var(--border-color); + border-radius: 2rpx; + overflow: hidden; + margin-bottom: 8rpx; +} + +.progress-fill { + height: 100%; + background: var(--primary-color); + border-radius: 2rpx; + transition: width 0.1s linear; +} + +.progress-time { + display: flex; + justify-content: space-between; + align-items: center; +} + +.current-time, +.total-time { + font-size: 20rpx; + color: var(--text-secondary); +} + +/* 🔄 加载状态 */ +.loading-container { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.1); + border-radius: var(--radius-large); + backdrop-filter: blur(10rpx); +} + +.loading-spinner { + width: 40rpx; + height: 40rpx; + border: 3rpx solid rgba(255, 255, 255, 0.3); + border-top: 3rpx solid white; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-right: 16rpx; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.loading-text { + font-size: 24rpx; + color: white; +} + +/* ⚠️ 错误状态 */ +.error-container { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 59, 48, 0.1); + border-radius: var(--radius-large); + backdrop-filter: blur(10rpx); + gap: 12rpx; +} + +.error-icon { + font-size: 32rpx; +} + +.error-text { + font-size: 24rpx; + color: var(--danger-color); +} + +.retry-button { + font-size: 24rpx; + color: var(--primary-color); + text-decoration: underline; + transition: all 0.2s ease; +} + +.retry-button:active { + opacity: 0.7; +} + +/* 🎨 特殊效果 */ +.voice-bubble::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(45deg, transparent 30%, rgba(255, 255, 255, 0.1) 50%, transparent 70%); + opacity: 0; + transition: opacity 0.3s ease; + pointer-events: none; +} + +.voice-bubble:active::before { + opacity: 1; +} + +/* 📱 响应式设计 */ +/* 去除设备宽度相关的硬编码,统一依赖父容器宽度以避免溢出 */ + +/* 🎭 动画增强 */ +.voice-message-container { + animation: slideIn 0.3s ease-out; +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(20rpx); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* 长按效果 */ +.voice-bubble { + user-select: none; + -webkit-user-select: none; +} + +.voice-bubble:active { + transform: scale(0.98); +} + +/* 可访问性 */ +.voice-bubble[aria-pressed="true"] { + outline: 2rpx solid var(--primary-color); + outline-offset: 4rpx; +} + +/* 状态指示器 */ +.voice-message-container::after { + content: ''; + position: absolute; + top: -4rpx; + right: -4rpx; + width: 16rpx; + height: 16rpx; + border-radius: 8rpx; + opacity: 0; + transition: all 0.3s ease; +} + +.voice-message-container.playing::after { + opacity: 1; + background: var(--success-color); + animation: pulse 2s infinite; +} diff --git a/config/config.js b/config/config.js new file mode 100644 index 0000000..4b845ca --- /dev/null +++ b/config/config.js @@ -0,0 +1,253 @@ +// 小程序配置文件 - 对应Fl`utter的app_config.dart + +function mergeDeep(target = {}, source = {}) { + const result = Array.isArray(target) ? target.slice() : Object.assign({}, target); + if (!source || typeof source !== 'object') { + return result; + } + + Object.keys(source).forEach((key) => { + const sourceValue = source[key]; + const targetValue = result[key]; + + if (Array.isArray(sourceValue)) { + result[key] = sourceValue.slice(); + } else if ( + sourceValue && + typeof sourceValue === 'object' && + !Array.isArray(sourceValue) && + targetValue && + typeof targetValue === 'object' && + !Array.isArray(targetValue) + ) { + result[key] = mergeDeep(targetValue, sourceValue); + } else if (sourceValue !== undefined) { + result[key] = sourceValue; + } + }); + + return result; +} + +let privateConfig = {}; +try { + // eslint-disable-next-line global-require, import/no-unresolved + privateConfig = require('./config.private.js'); +} catch (error) { + const message = error && error.message ? String(error.message) : ''; + const isMissing = error?.code === 'MODULE_NOT_FOUND' || message.includes('not defined'); + if (!isMissing) { + console.warn('加载私有配置失败:', error); + } else if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'development') { + console.info('未检测到 config.private.js,使用默认配置'); + } +} + +const baseConfig = { + // 应用信息 + appName: "FindMe", + appVersion: "1.0.30", // 全局版本检查功能版本 + // API配置 - 使用正确的域名 + api: { + baseUrl: "https://api.faxianwo.me", + baseAmapUrl: "https://restapi.amap.com/v3", + timeout: 15000 + }, + + // scana配置 + scana: { + textBusinessId: '2084889082944577806', + imageBusinessId: '2084888991278039310', + appId: '68ce8147f243650001486434', + secretKey: 'd5b263da-99b8-11f0-97a4-fa163e917534' + }, + + // WebSocket配置 - 使用正确的WebSocket路径 + websocket: { + baseUrl: "wss://api.faxianwo.me", + url: "wss://api.faxianwo.me/api/v1/ws", // 🔥 恢复正确的WebSocket路径 + heartbeatInterval: 30000, // 30秒 + reconnectBaseDelay: 2000, // 重连基础延迟 + maxReconnectAttempts: 10 // 最大重连次数 + }, + + // 高德地图配置 + // amapKey: '55e1d9a4c6c0f9fa4c75656fe3060641', + // amapKey: '9212b693317725fca66ae697ec444fd5', + amapKey: '9da0f2a1538b5857dba24ac9aa9f30cc', + // amapKey: '97320669caa10f1f8168b0f1aecc2c08', + + // NIM配置 + nim: { + appkey: '008ea0d044bd46e5b2281cb5fc3f627b', + apiVersion: 'v2', + enableV2CloudConversation: true + }, + + // 腾讯云COS配置 - 用于文件存储 + cos: { + // 存储桶配置 + bucket: 'findme-1375214531', + region: 'ap-guangzhou', + // 临时密钥服务地址 (后端提供) + stsUrl: '/api/v1/cos/sts', + // 文件检查接口 (检查文件是否已存在) + fileCheckUrl: '/api/v1/cos/file/check', + // 文件记录保存接口 + fileRecordUrl: '/api/v1/cos/file/record', + // 是否使用全球加速 + useAccelerate: false, + // 分块上传配置 + sliceSize: 1024 * 1024 * 5, // 5MB 大于此大小使用分块上传 + chunkSize: 1024 * 1024 * 1, // 1MB 分块大小 + // 文件路径格式: user/{userId}/{fileType}/{timestamp}_{fileName} + pathFormat: 'user/{userId}/{fileType}/{timestamp}_{fileName}' + }, + + // 网络超时设置 (保持向后兼容) + networkTimeout: { + request: 15000, + upload: 60000, + download: 60000 + }, + + // 位置刷新间隔 + locationUpdateInterval: 30000, // 30秒 + + // 文件大小限制 (小程序有自己的限制,这里作为前端验证) + fileSizeLimit: { + image: 10 * 1024 * 1024, // 10MB + video: 50 * 1024 * 1024, // 50MB + audio: 5 * 1024 * 1024, // 5MB + file: 50 * 1024 * 1024 // 50MB + }, + + // 支持的文件类型 + supportedFileTypes: { + image: ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'], + video: ['mp4', 'avi', 'wmv', 'mov', '3gp'], + audio: ['mp3', 'wav', 'ogg', 'aac', 'm4a'] + }, + + // 缓存设置 + cache: { + maxAge: 7 * 24 * 60 * 60, // 7天 + resourceExpireTime: { + image: 4 * 3600, // 4小时 + video: 2 * 3600, // 2小时 + audio: 2 * 3600, // 2小时 + file: 1 * 3600, // 1小时 + avatar: 24 * 3600 // 24小时 + }, + // 版本管理配置 + versionManagement: { + enableAutoClear: true, // 版本更新时自动清理缓存 + periodicClearInterval: 7 * 24 * 60 * 60 * 1000, // 7天定期清理 + showUpdateNotification: true // 显示更新通知 + } + }, + + // API端点路径 + apiPaths: { + // 身份验证相关(统一使用user路径) + auth: { + sendVerifyCode: '/api/v1/user/send-verify-code', + login: '/api/v1/user/login', + wechatLogin: '/api/v1/user/wechat-login', + refresh: '/api/v1/auth/refresh', + logout: '/api/v1/user/logout' + }, + // 用户相关 + user: { + profile: '/api/v1/user/profile', + updateProfile: '/api/v1/user/profile', + setting: '/api/v1/user/setting', + bindPhone: '/api/v1/user/bind-phone', + detectMerge: '/api/v1/user/detect-merge', + mergeAccount: '/api/v1/user/merge-account' + }, + + // 位置相关 + location: { + update: '/api/v1/location/update', + getFriends: '/api/v1/location/friends', + getStrangers: '/api/v1/location/strangers', + privacy: '/api/v1/location/privacy' + }, + + // 聊天相关 - 根据接口文档修正API路径 + chat: { + conversations: '/api/v1/chat/conversations', + history: '/api/v1/chat/history', // 修正:使用正确的历史消息接口 + messages: '/api/v1/chat/history', // 保持向后兼容 + send: '/api/v1/chat/send', + batchRead: '/api/v1/chat/batch-read', // 新增:批量已读 + markAllRead: '/api/v1/chat/mark-all-read', // 新增:全部已读 + unreadTotal: '/api/v1/chat/unread/total', // 新增:总未读数 + settings: '/api/v1/chat/settings', // 新增:聊天设置 + backup: '/api/v1/chat/backup', // 新增:备份 + restore: '/api/v1/chat/restore', // 新增:恢复 + danmaku: '/api/v1/chat/danmaku', // 新增:弹幕 + emoji: '/api/v1/chat/emoji/packages', // 新增:表情包 + syncPull: '/api/v1/chat/sync/pull', // 新增:同步拉取 + syncAck: '/api/v1/chat/sync/ack', // 新增:同步确认 + upload: '/api/v1/file/upload' + }, + + // 社交相关 + social: { + friends: '/api/v1/social/friends', + addFriend: '/api/v1/social/friend/add', + acceptFriend: '/api/v1/social/friend/handle-request', + deleteFriend: '/api/v1/social/friend', + search: '/api/v1/social/search', + friendRequests: '/api/v1/social/friend/requests', + friendRequestsCount: '/api/v1/social/friend/requests/count', + groups: '/api/v1/social/groups', + groupsCount: '/api/v1/social/groups/count' + }, + + + }, + + // 小程序特有配置 + miniprogram: { + // 页面路径 + pages: { + splash: '/pages/splash/splash', + login: '/pages/login/login', + main: '/pages/main/main', + map: '/pages/map/map', + friends: '/pages/social/friends/friends', + message: '/pages/message/message', + profile: '/subpackages/profile/profile/profile' + }, + + // 主题配置 + theme: { + primaryColor: '#3cc51f', + backgroundColor: '#F5F5F5', + textColor: '#333333', + subTextColor: '#999999' + }, + + // 地图配置 + map: { + defaultZoom: 16, + minZoom: 3, + maxZoom: 20, + showLocation: true, + showScale: true, + showCompass: true + } + }, + + // 调试配置 + debug: { + enabled: true, + showLog: true, + mockData: false + } +}; + +module.exports = mergeDeep(baseConfig, privateConfig); diff --git a/config/config.private.example.js b/config/config.private.example.js new file mode 100644 index 0000000..07c0f54 --- /dev/null +++ b/config/config.private.example.js @@ -0,0 +1,22 @@ +/** + * 私有配置示例文件 + * 复制为 config.private.js 并填入真实密钥,仅在本地开发或安全的CI环境中使用。 + */ +module.exports = { + scana: { + textBusinessId: '', + imageBusinessId: '', + appId: '', + secretKey: '' + }, + amapKey: '', + + // 腾讯云COS配置 - 已配置正式环境 + cos: { + bucket: 'findme-1375214531', // 存储桶名称 + region: 'ap-guangzhou', // 地域 + stsUrl: '/api/v1/cos/sts', // 临时密钥接口 + fileCheckUrl: '/api/v1/cos/file/check', // 文件去重检查接口 + fileRecordUrl: '/api/v1/cos/file/record' // 文件记录保存接口 + } +}; diff --git a/custom-tab-bar/index.js b/custom-tab-bar/index.js new file mode 100644 index 0000000..b122198 --- /dev/null +++ b/custom-tab-bar/index.js @@ -0,0 +1,352 @@ +const config = require('../config/config.js'); +const apiClient = require('../utils/api-client.js'); + +Component({ + data: { + selected: 0, + color: '#999999', + selectedColor: '#ffffff', + showCameraAction: false, // 拍照弹窗显示状态 + cameraActive: false, // 发布按钮激活状态 + list: [ + { + pagePath: '/pages/map/map', + text: '发现', + iconPath: '/images/index/location.png', + selectedIconPath: '/images/index/location-active.png' + }, + { + pagePath: '/pages/circle/circle', + text: '圈子', + iconPath: '/images/index/circle.png', + selectedIconPath: '/images/index/circle-active.png' + }, + { + pagePath: '/subpackages/media/camera/camera', + iconPath: '/images/index/phone.png', + text: '发布', + selectedIconPath: '/images/index/phone-active.png' + }, + + { + pagePath: '/pages/message/message', + text: '聊天', + iconPath: '/images/index/message.png', + selectedIconPath: '/images/index/message-active.png' + }, + { + pagePath: '/pages/social/friends/friends', + text: '好友', + iconPath: '/images/index/friend.png', + selectedIconPath: '/images/index/friend-active.png' + } + ] + }, + + + /** + * 用户点击右上角分享 + */ + onShareAppMessage(options) { + // options.from 可以是 'button' 或 'menu' + // 'button' 表示通过页面内的分享按钮触发 + // 'menu' 表示通过右上角菜单的分享按钮触发 + + return { + title: 'Find Me', // 分享标题 + path: '/custom-tab-bar/index/index', // 分享路径,必须是以 / 开头的完整路径 + imageUrl: '/images/findme-logo.png', // 分享图标,可以是本地图片或网络图片 + success(res) { + // 分享成功后的回调 + console.log('分享成功', res); + // 可以在这里添加统计代码等 + }, + fail(res) { + // 分享失败后的回调 + console.log('分享失败', res); + } + } + }, + + attached() { + // 已通过CSS调整适配所有设备 + try { + const counts = wx.getStorageSync('unreadCounts') || {}; + const friends = Number(counts.friends || 0); + const messages = Number(counts.messages || 0); + if (friends || messages) { + this.setData({ + friendsBadge: friends, + messagesBadge: messages + }); + } + } catch (_) {} + }, + methods: { + // 对外暴露:设置好友请求角标数量 + setFriendsBadge(count) { + const n = Number(count) || 0; + if (this.data.friendsBadge === n) return; + this.setData({ friendsBadge: n < 0 ? 0 : n }); + }, + // 对外暴露:设置消息未读角标数量 + setMessagesBadge(count) { + const n = Number(count) || 0; + if (this.data.messagesBadge === n) return; + this.setData({ messagesBadge: n < 0 ? 0 : n }); + }, + // 清除所有角标 + clearBadges() { + this.setData({ friendsBadge: 0, messagesBadge: 0 }); + }, + switchTab(e) { + const data = e.currentTarget.dataset; + const url = data.path; + const index = data.index; + + // 获取当前页面信息 + const pages = getCurrentPages(); + const currentPage = pages[pages.length - 1]; + + // 检查是否是"发布"按钮(索引2)- 直接跳转到编辑页面 + if (index === 2) { + // 切换发布按钮激活状态 + this.setData({ cameraActive: !this.data.cameraActive }); + // 检查登录状态 + const app = getApp(); + if (!app.globalData.isLoggedIn) { + wx.navigateTo({ + url: '/pages/login/login?from=camera' + }); + return; + } + // 已登录时直接跳转到编辑页面 + wx.navigateTo({ + url: '/subpackages/media/edits/edits', + fail: (err) => { + console.error('跳转编辑页面失败:', err); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none' + }); + // 跳转失败时重置激活状态 + this.setData({ cameraActive: false }); + } + }); + return; + } + + // 切换到其他按钮时,取消发布按钮激活状态 + if (this.data.cameraActive) { + this.setData({ cameraActive: false }); + } + + // 先更新选中状态(其他 tabBar 页面) + this.setData({ + selected: index + }); + + // 检查是否是"发现"按钮(索引0) + if (index === 0) { + // 检查当前是否已经在地图页面 + if (currentPage.route === 'pages/map/map') { + // 如果已经在地图页面,直接打开地点收藏栏 + currentPage.onOpenLocationFavoriteBar(); + } else { + const app = getApp(); + // 如果不在地图页面,先跳转到地图页面,然后通过全局变量标记需要打开收藏栏 + wx.switchTab({ + url, + success: () => { + // 设置全局变量,让地图页面加载后知道需要打开收藏栏 + app.globalData.needOpenLocationFavoriteBar = true; + } + }); + } + return; + } + + // 检查是否是"圈子"按钮(索引1) + if (index === 1) { + // 检查登录状态 + const app = getApp(); + if (!app.globalData.isLoggedIn) { + wx.navigateTo({ + url: '/pages/login/login?from=circle' + }); + return; + } + // 正常跳转到圈子页面 + wx.switchTab({ + url + }); + return; + } + + // 检查是否是"聊天"按钮(索引3) + if (index === 3) { + // 检查登录状态 + const app = getApp(); + if (!app.globalData.isLoggedIn) { + wx.navigateTo({ + url: '/pages/login/login?from=message' + }); + return; + } + // 已登录时正常跳转 + wx.switchTab({ + url + }); + return; + } + + // 检查是否是"我的"按钮(索引4)- 跳转到好友列表页面 + if (index === 4) { + // 检查登录状态 + const app = getApp(); + if (!app.globalData.isLoggedIn) { + wx.navigateTo({ + url: '/pages/login/login?from=friends' + }); + return; + } + // 已登录时跳转到好友列表页面(使用 switchTab,因为它在 tabBar 中) + wx.switchTab({ + url: '/pages/social/friends/friends' + }); + return; + } + + // 其他按钮正常跳转 + wx.switchTab({ + url + }); + }, + + // 显示拍照弹窗 + showCameraActionSheet() { + this.setData({ showCameraAction: true }); + }, + + // 隐藏拍照弹窗 + hideCameraActionSheet() { + this.setData({ showCameraAction: false, cameraActive: false }); + }, + + // 拍照 + takePhoto() { + this.hideCameraActionSheet(); + wx.navigateTo({ + url: '/subpackages/media/camera/camera', + fail: (err) => { + console.error('跳转拍照页面失败:', err); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none' + }); + } + }); + }, + + // 从相册选择 + chooseImage() { + this.hideCameraActionSheet(); + wx.chooseImage({ + count: 1, + sizeType: ['original', 'compressed'], + sourceType: ['album'], + success: (res) => { + const tempFilePath = res.tempFilePaths[0]; + wx.showLoading({ title: '上传中...', mask: true }); + + // 上传图片 + this.uploadImage(tempFilePath) + .then(imageUrl => { + wx.hideLoading(); + if (imageUrl) { + wx.navigateTo({ + url: `/subpackages/media/edits/edits?imagePath=${encodeURIComponent(imageUrl)}`, + fail: (err) => { + console.error('跳转编辑页失败:', err); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none' + }); + } + }); + } + }) + .catch(error => { + wx.hideLoading(); + console.error('上传失败:', error); + wx.showToast({ + title: error.message || '上传失败,请重试', + icon: 'none' + }); + }); + }, + fail: (error) => { + console.error('选择图片失败:', error); + if (error.errMsg && !error.errMsg.includes('cancel')) { + wx.showToast({ + title: '选择图片失败', + icon: 'none' + }); + } + } + }); + }, + + // 上传图片 + uploadImage(tempFilePath) { + return new Promise((resolve, reject) => { + wx.uploadFile({ + url: `${config.api.baseUrl}/api/v1/file/upload`, + filePath: tempFilePath, + name: 'file', + formData: { + file_type: 'image', + usage_type: 'feed' + }, + header: { + 'Authorization': `Bearer ${apiClient.getToken()}` + }, + success: (uploadRes) => { + if (apiClient.is401Error(uploadRes)) { + const app = getApp(); + const isLoggedIn = app?.globalData?.isLoggedIn || false; + apiClient.handle401Error(isLoggedIn); + if (isLoggedIn) { + reject(new Error('登录已过期,请重新登录')); + } else { + resolve(null); + } + return; + } + + try { + const data = JSON.parse(uploadRes.data); + if (data.code === 0) { + const fileData = data?.data?.data || data?.data || {}; + const imageUrl = fileData.file_url || fileData.fileUrl || fileData.url; + if (imageUrl) { + resolve(imageUrl); + } else { + reject(new Error('上传成功但未获取到图片URL')); + } + } else { + reject(new Error(data.message || '上传失败')); + } + } catch (error) { + reject(new Error('响应解析失败')); + } + }, + fail: (error) => { + console.error('上传失败:', error); + reject(new Error(error.errMsg || '上传失败')); + } + }); + }); + } + } +}); diff --git a/custom-tab-bar/index.json b/custom-tab-bar/index.json new file mode 100644 index 0000000..32640e0 --- /dev/null +++ b/custom-tab-bar/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} \ No newline at end of file diff --git a/custom-tab-bar/index.wxml b/custom-tab-bar/index.wxml new file mode 100644 index 0000000..e8d6265 --- /dev/null +++ b/custom-tab-bar/index.wxml @@ -0,0 +1,33 @@ + + + + + + + {{item.text}} + + + + + + + + + 拍照 + + + + 从相册选择 + + + + 取消 + + + \ No newline at end of file diff --git a/custom-tab-bar/index.wxss b/custom-tab-bar/index.wxss new file mode 100644 index 0000000..629921a --- /dev/null +++ b/custom-tab-bar/index.wxss @@ -0,0 +1,163 @@ +/* custom-tab-bar/index.wxss - 自定义底部导航栏样式文件 */ + +.tab-bar { + position: fixed; /* 固定定位,使导航栏始终显示在屏幕底部 */ + bottom: 40rpx; /* 距离屏幕底部20px -> 40rpx */ + left: 100rpx; /* 距离屏幕左侧50px -> 100rpx */ + right: 100rpx; /* 距离屏幕右侧50px -> 100rpx */ + min-height: 200rpx; /* 导航栏最小高度(用户希望保持较大值) */ + height: auto; /* 高度自适应内容 */ + display: flex; /* 使用flex布局 */ + justify-content: space-around; /* 水平均匀分布子元素 */ + align-items: center; /* 垂直居中对齐子元素 */ + padding: 20rpx; /* 内边距10px -> 20rpx */ + box-sizing: border-box; /* 盒模型为border-box,宽高包含内边距和边框 */ + z-index: 9999; /* 层级设为最高,确保在其他元素之上 */ + border-radius: 52rpx; /* 设置圆角,创建胶囊形状 26px -> 52rpx */ +} + +/* 深灰色玻璃效果 - 继承自app.wxss并增强 */ +.tab-bar-glass { + /* 基础玻璃效果 */ + background: rgba(30, 30, 30, 0.7); /* 设置半透明深灰色背景,透明度0.7 */ + backdrop-filter: blur(20rpx); /* 设置背景模糊效果,10px -> 20rpx */ + -webkit-backdrop-filter: blur(20rpx); /* WebKit内核浏览器兼容,设置背景模糊效果 */ + + /* 添加细微边框增强效果 */ + border-top: 2rpx solid rgba(255, 255, 255, 0.1); /* 顶部边框为1px -> 2rpx白色半透明线 */ + + /* 阴影效果增强层次感 */ + box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.1); /* 设置底部阴影,增强悬浮感 2px -> 4rpx, 10px -> 20rpx */ +} + +.tab-bar-item { + flex: 1; /* 让每个按钮占据相同的宽度 */ + display: flex; /* 使用flex布局 */ + flex-direction: column; /* 垂直方向排列子元素(图标在上,文字在下) */ + align-items: center; /* 水平居中对齐子元素 */ + justify-content: center; /* 垂直居中对齐子元素 */ + height: 100%; /* 高度充满父容器 */ + box-sizing: border-box; /* 盒模型为border-box */ +} + +.tab-bar-icon { + width: 55rpx; /* 图标宽度 */ + height: 55rpx; /* 图标高度 */ + margin-bottom: 8rpx; /* 与下方文字的间距 */ + display: block; /* 显示为块级元素 */ + transition: transform 0.3s ease, width 0.3s ease, height 0.3s ease; /* 添加过渡效果 */ +} + +/* 🔥 所有tab选中时图标放大 */ +.tab-bar-icon.tab-icon-active { + width: 80rpx; /* 选中时图标宽度增大 */ + height: 80rpx; /* 选中时图标高度增大 */ + margin-bottom: 0; /* 选中时没有文字,不需要间距 */ +} + +/* 拍照按钮(索引2)未激活时:正常大小图标,显示文字 */ +.camera-icon-normal { + width: 55rpx !important; /* 正常大小 */ + height: 55rpx !important; /* 正常大小 */ + margin-bottom: 8rpx !important; /* 有文字,需要间距 */ +} + +/* 拍照按钮(索引2)激活时:大图标,不显示文字 */ +.camera-icon-large { + width: 80rpx !important; /* 拍照按钮图标更大 */ + height: 80rpx !important; /* 拍照按钮图标更大 */ + margin-bottom: 0 !important; /* 没有文字,不需要间距 */ +} + +.tab-bar-text { + font-size: 24rpx; /* 文字大小12px -> 24rpx */ + line-height: 24rpx; /* 行高12px -> 24rpx,与字体大小一致确保单行显示 */ +} + +/* 触摸反馈效果 */ +.tab-bar-item:active { + opacity: 0.7; /* 触摸时透明度降低到0.7,提供视觉反馈 */ +} + +/* 拍照功能弹窗样式 */ +.camera-action-sheet { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 10000; + transform: none !important; + -webkit-transform: none !important; +} + +.camera-action-sheet.show { + display: block; +} + +.action-sheet-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 1; + background-color: rgba(0, 0, 0, 0.4); +} + +.action-sheet-content { + position: absolute; + bottom: 0; + left: 0; + right: 0; + z-index: 2; + background: #222; + border-radius: 16px 16px 0 0; + padding: 8px 0; +} + +.action-sheet-item { + padding: 20px 0; + text-align: center; + background: #222; + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + position: relative; +} + +.action-sheet-item::after { + display: none; +} + +.action-sheet-item.primary { + background: #222; +} + +.action-sheet-item.cancel { + background: #222; + margin-top: 8px; +} + +.action-sheet-item.cancel::after { + display: none; +} + +.action-sheet-divider { + height: 8px; + background-color: #111; + margin: 8px 0; +} + +.action-sheet-divider-thin { + height: 2px; + background-color: #111; + margin: 4px 0; +} + +.action-text { + font-size: 16px; + color: #fff; +} \ No newline at end of file diff --git a/dist/cos-wx-sdk-v5.min.js b/dist/cos-wx-sdk-v5.min.js new file mode 100644 index 0000000..55b0f0f --- /dev/null +++ b/dist/cos-wx-sdk-v5.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.COS=t():e.COS=t()}(window,(function(){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/Users/chrisftian/Documents/projects/cos-sdk/cos-wx-sdk-v5/dist",n(n.s=8)}([function(e,t,n){"use strict";function i(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(!e)return;if("string"==typeof e)return o(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return o(e,t)}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var i=0,a=function(){};return{s:a,n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r,s=!0,c=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return s=e.done,e},e:function(e){c=!0,r=e},f:function(){try{s||null==n.return||n.return()}finally{if(c)throw r}}}}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n=0;--a){var r=this.tryEntries[a],s=r.completion;if("root"===r.tryLoc)return o("end");if(r.tryLoc<=this.prev){var c=i.call(r,"catchLoc"),l=i.call(r,"finallyLoc");if(c&&l){if(this.prev=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&i.call(o,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),O(n),y}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var i=n.completion;if("throw"===i.type){var o=i.arg;O(n)}return o}}throw Error("illegal catch attempt")},delegateYield:function(t,n,i){return this.delegate={iterator:I(t),resultName:n,nextLoc:i},"next"===this.method&&(this.arg=e),y}},t}function r(e,t,n,i,o,a,r){try{var s=e[a](r),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(i,o)}function s(e){return s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},s(e)}var c=n(10),l=n(13),p=n(14),u=p.btoa,d=wx.getFileSystemManager(),f=n(2),m=n(15),h=m.XMLParser,g=m.XMLBuilder,v=new h({ignoreDeclaration:!0,ignoreAttributes:!0,parseTagValue:!1,trimValues:!1}),y=new g,x=function e(t){if(A(t))for(var n in t){var i=t[n];"string"==typeof i?"#text"===n&&delete t[n]:Array.isArray(i)?i.forEach((function(t){e(t)})):A(i)&&e(i)}};function k(e){return encodeURIComponent(e).replace(/!/g,"%21").replace(/'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/\*/g,"%2A")}function b(e,t){var n=[];for(var i in e)e.hasOwnProperty(i)&&n.push(t?k(i).toLowerCase():i);return n.sort((function(e,t){return(e=e.toLowerCase())===(t=t.toLowerCase())?0:e>t?1:-1}))}var C=["cache-control","content-disposition","content-encoding","content-length","content-md5","content-type","expect","expires","host","if-match","if-modified-since","if-none-match","if-unmodified-since","origin","range","transfer-encoding","pic-operations"],S=function(){},w=function(e){var t={};for(var n in e)e.hasOwnProperty(n)&&void 0!==e[n]&&null!==e[n]&&(t[n]=e[n]);return t};function T(e){return E(e,(function(e){return"object"===s(e)&&null!==e?T(e):e}))}function R(e,t){return P(t,(function(n,i){e[i]=t[i]})),e}function B(e){return e instanceof Array}function A(e){return"[object Object]"===Object.prototype.toString.call(e)}function P(e,t){for(var n in e)e.hasOwnProperty(n)&&t(e[n],n)}function E(e,t){var n=B(e)?[]:{};for(var i in e)e.hasOwnProperty(i)&&(n[i]=t(e[i],i));return n}var O=function(e,t){if(t=R({},t),"getAuth"!==e&&"getV4Auth"!==e&&"getObjectUrl"!==e){var n=t.Headers||{};if(t&&"object"===s(t)){!function(){for(var e in t)t.hasOwnProperty(e)&&e.indexOf("x-cos-")>-1&&(n[e]=t[e])}();U.each({"x-cos-mfa":"MFA","Content-MD5":"ContentMD5","Content-Length":"ContentLength","Content-Type":"ContentType",Expect:"Expect",Expires:"Expires","Cache-Control":"CacheControl","Content-Disposition":"ContentDisposition","Content-Encoding":"ContentEncoding",Range:"Range","If-Modified-Since":"IfModifiedSince","If-Unmodified-Since":"IfUnmodifiedSince","If-Match":"IfMatch","If-None-Match":"IfNoneMatch","x-cos-copy-source":"CopySource","x-cos-copy-source-Range":"CopySourceRange","x-cos-metadata-directive":"MetadataDirective","x-cos-copy-source-If-Modified-Since":"CopySourceIfModifiedSince","x-cos-copy-source-If-Unmodified-Since":"CopySourceIfUnmodifiedSince","x-cos-copy-source-If-Match":"CopySourceIfMatch","x-cos-copy-source-If-None-Match":"CopySourceIfNoneMatch","x-cos-acl":"ACL","x-cos-grant-read":"GrantRead","x-cos-grant-write":"GrantWrite","x-cos-grant-full-control":"GrantFullControl","x-cos-grant-read-acp":"GrantReadAcp","x-cos-grant-write-acp":"GrantWriteAcp","x-cos-storage-class":"StorageClass","x-cos-traffic-limit":"TrafficLimit","x-cos-mime-limit":"MimeLimit","x-cos-forbid-overwrite":"ForbidOverwrite","x-cos-server-side-encryption-customer-algorithm":"SSECustomerAlgorithm","x-cos-server-side-encryption-customer-key":"SSECustomerKey","x-cos-server-side-encryption-customer-key-MD5":"SSECustomerKeyMD5","x-cos-server-side-encryption":"ServerSideEncryption","x-cos-server-side-encryption-cos-kms-key-id":"SSEKMSKeyId","x-cos-server-side-encryption-context":"SSEContext","Pic-Operations":"PicOperations"},(function(e,i){void 0!==t[e]&&(n[i]=t[e])})),t.Headers=w(n)}}return t},j=function(e){return new Promise((function(t,n){d.readFile({filePath:e,success:function(e){t(e.data)},fail:function(e){n((null==e?void 0:e.errMsg)||"")}})}))},I=function(){var e,t=(e=a().mark((function e(t,n,i){return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if("postObject"!==t){e.next=4;break}i(),e.next=21;break;case 4:if("putObject"!==t){e.next=20;break}if(void 0!==n.Body||!n.FilePath){e.next=17;break}return e.prev=6,e.next=9,j(n.FilePath);case 9:n.Body=e.sent,e.next=17;break;case 12:return e.prev=12,e.t0=e.catch(6),n.Body=void 0,i({error:"readFile error, ".concat(e.t0)}),e.abrupt("return");case 17:void 0!==n.Body?(n.ContentLength=n.Body.byteLength,i(null,n.ContentLength)):i({error:"missing param Body"}),e.next=21;break;case 20:n.FilePath?d.stat({path:n.FilePath,success:function(e){var t=e.stats;n.FileStat=t,n.FileStat.FilePath=n.FilePath;var o=t.isDirectory()?0:t.size;n.ContentLength=o=o||0,i(null,o)},fail:function(e){i(e)}}):i({error:"missing param FilePath"});case 21:case"end":return e.stop()}}),e,null,[[6,12]])})),function(){var t=this,n=arguments;return new Promise((function(i,o){var a=e.apply(t,n);function s(e){r(a,i,o,s,c,"next",e)}function c(e){r(a,i,o,s,c,"throw",e)}s(void 0)}))});return function(e,n,i){return t.apply(this,arguments)}}(),_=function(e){return Date.now()+(e||0)},N=function(e,t){if(!e||!t)return-1;e=e.split("."),t=t.split(".");for(var n=Math.max(e.length,t.length);e.lengtha)return 1;if(o=0);return function(){return!1,i}}(),U={noop:S,formatParams:O,apiWrapper:function(e,t){return function(n,i){var o,a=this;if("function"==typeof n&&(i=n,n={}),n=O(e,n),a.options.EnableReporter)if("sliceUploadFile"===n.calledBySdk||"sliceCopyFile"===n.calledBySdk)o=n.tracker&&n.tracker.generateSubTracker({apiName:e});else if(["uploadFile","uploadFiles"].includes(e))o=null;else{var r=0;n.Body&&(r="string"==typeof n.Body?n.Body.length:n.Body.size||n.Body.byteLength||0);var s=a.options.UseAccelerate||"string"==typeof a.options.Domain&&a.options.Domain.includes("accelerate.");o=new f({Beacon:a.options.BeaconReporter,clsReporter:a.options.ClsReporter,bucket:n.Bucket,region:n.Region,apiName:e,realApi:e,accelerate:s,fileKey:n.Key,fileSize:r,deepTracker:a.options.DeepTracker,customId:a.options.CustomId,delay:a.options.TrackerDelay})}n.tracker=o;var c=function(e){return e&&e.headers&&(e.headers["x-ci-request-id"]&&(e.RequestId=e.headers["x-ci-request-id"]),e.headers["x-cos-request-id"]&&(e.RequestId=e.headers["x-cos-request-id"]),e.headers["x-cos-version-id"]&&(e.VersionId=e.headers["x-cos-version-id"]),e.headers["x-cos-delete-marker"]&&(e.DeleteMarker=e.headers["x-cos-delete-marker"])),e},l=function(e,t){o&&o.report(e,t),i&&i(c(e),c(t))},p=function(){if("getService"!==e&&"abortUploadTask"!==e){var t=function(e,t){var n=t.Bucket,i=t.Region,o=t.Key;if(e.indexOf("Bucket")>-1||"deleteMultipleObject"===e||"multipartList"===e||"listObjectVersions"===e){if(!n)return"Bucket";if(!i)return"Region"}else if(e.indexOf("Object")>-1||e.indexOf("multipart")>-1||"sliceUploadFile"===e||"abortUploadTask"===e||"uploadFile"===e){if(!n)return"Bucket";if(!i)return"Region";if(!o)return"Key"}return!1}(e,n);if(t)return"missing param "+t;if(n.Region){if(n.Region.indexOf("cos.")>-1)return'param Region should not be start with "cos."';if(!/^([a-z\d-]+)$/.test(n.Region))return"Region format error.";!a.options.CompatibilityMode&&-1===n.Region.indexOf("-")&&"yfb"!==n.Region&&"default"!==n.Region&&n.Region}if(n.Bucket){if(!/^([a-z\d-]+)-(\d+)$/.test(n.Bucket))if(n.AppId)n.Bucket=n.Bucket+"-"+n.AppId;else{if(!a.options.AppId)return'Bucket should format as "test-1250000000".';n.Bucket=n.Bucket+"-"+a.options.AppId}n.AppId&&delete n.AppId}n.Key&&"/"===n.Key.substr(0,1)&&(n.Key=n.Key.substr(1))}}(),u=["getAuth","getObjectUrl"].includes(e);if(!u&&!i)return new Promise((function(e,o){if(i=function(t,n){t?o(t):e(n)},p)return l({error:p});t.call(a,n,l)}));if(p)return l({error:p});var d=t.call(a,n,l);return u?d:void 0}},xml2json:function(e){var t=v.parse(e);return x(t),t},json2xml:function(e){return y.build(e)},md5:c,clearKey:w,fileSlice:function(e,t,n,i){e?d.readFile({filePath:e,position:t,length:n-t,success:function(e){i(e.data)},fail:function(){i(null)}}):i(null)},getBodyMd5:function(e,t,n){n=n||S,e&&t&&t instanceof ArrayBuffer?U.getFileMd5(t,(function(e,t){n(t)})):n()},getFileMd5:function(e,t){var n=c(e);return t&&t(n),n},binaryBase64:function(e){var t,n,i,o="";for(t=0,n=e.length/2;t-1||i.indexOf("x-ci-")>-1||C.indexOf(i)>-1)&&(t[n]=e[n])}return t}(T(e.Headers||e.headers||{})),c=e.Key||"";e.UseRawKey?t=e.Pathname||e.pathname||"/"+c:0!==(t=e.Pathname||e.pathname||c).indexOf("/")&&(t="/"+t);var p=!1!==e.ForceSignHost;if(!s.Host&&!s.host&&e.Bucket&&e.Region&&p&&(s.Host=e.Bucket+".cos."+e.Region+".myqcloud.com"),n&&i){var u=Math.round(_(e.SystemClockOffset)/1e3)-1,d=u,f=e.Expires||e.expires;d+=void 0===f?900:1*f||0;var m=n,h=o||u+";"+d,g=o||u+";"+d,v=b(s,!0).join(";").toLowerCase(),y=b(r,!0).join(";").toLowerCase(),x=l.HmacSHA1(g,i).toString(),k=[a,t,U.obj2str(r,!0),U.obj2str(s,!0),""].join("\n"),S=["sha1",h,l.SHA1(k).toString(),""].join("\n");return["q-sign-algorithm=sha1","q-ak="+m,"q-sign-time="+h,"q-key-time="+g,"q-header-list="+v,"q-url-param-list="+y,"q-signature="+l.HmacSHA1(S,x).toString()].join("&")}},compareVersion:N,canFileSlice:L,isCIHost:function(e){return/^https?:\/\/([^/]+\.)?ci\.[^/]+/.test(e)},error:function(e,t){var n=e;return e.message=e.message||null,"string"==typeof t?(e.error=t,e.message=t):"object"===s(t)&&null!==t&&(R(e,t),(t.code||t.name)&&(e.code=t.code||t.name),t.message&&(e.message=t.message),t.stack&&(e.stack=t.stack)),"function"==typeof Object.defineProperty&&(Object.defineProperty(e,"name",{writable:!0,enumerable:!1}),Object.defineProperty(e,"message",{enumerable:!0})),e.name=t&&t.name||e.name||e.code||"Error",e.code||(e.code=e.name),e.error||(e.error=T(n)),e},getSourceParams:function(e){var t=this.options.CopySourceParser;if(t)return t(e);var n=e.match(/^([^.]+-\d+)\.cos(v6|-cdc|-internal)?\.([^.]+)\.((myqcloud\.com)|(tencentcos\.cn))\/(.+)$/);return n?{Bucket:n[1],Region:n[3],Key:n[7]}:null},encodeBase64:function(e,t){var n=p.encode(e);return t&&(n=n.replaceAll("+","-").replaceAll("/","_").replaceAll("=","")),n},simplifyPath:function(e){var t,n=[],o=i(e.split("/"));try{for(o.s();!(t=o.n()).done;){var a=t.value;".."===a?n.length&&n.pop():a.length&&"."!==a&&n.push(a)}}catch(e){o.e(e)}finally{o.f()}return"/"+n.join("/")},arrayBufferToString:function(e){return new TextDecoder("utf-8").decode(e)},parseResBody:function(e){var t;if(e&&"string"==typeof e){var n=e.trim(),i=0===n.indexOf("<"),o=0===n.indexOf("{");if(i)t=U.xml2json(e)||{};else if(o)try{var a=e.replace(/\n/g," "),r=JSON.parse(a);t="[object Object]"===Object.prototype.toString.call(r)?r:e}catch(n){t=e}else t=e}else t=e||{};return t}};e.exports=U},function(e,t,n){"use strict";const i=":A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",o="["+i+"]["+(i+"\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040")+"]*",a=new RegExp("^"+o+"$");t.isExist=function(e){return void 0!==e},t.isEmptyObject=function(e){return 0===Object.keys(e).length},t.merge=function(e,t,n){if(t){const i=Object.keys(t),o=i.length;for(let a=0;a=0;--o){var r=this.tryEntries[o],s=r.completion;if("root"===r.tryLoc)return i("end");if(r.tryLoc<=this.prev){var c=a.call(r,"catchLoc"),l=a.call(r,"finallyLoc");if(c&&l){if(this.prev=0;--n){var i=this.tryEntries[n];if(i.tryLoc<=this.prev&&a.call(i,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),O(n),y}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var i=n.completion;if("throw"===i.type){var o=i.arg;O(n)}return o}}throw Error("illegal catch attempt")},delegateYield:function(t,n,i){return this.delegate={iterator:I(t),resultName:n,nextLoc:i},"next"===this.method&&(this.arg=e),y}},t}function a(e,t,n,i,o,a,r){try{var s=e[a](r),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(i,o)}function r(e){return function(){var t=this,n=arguments;return new Promise((function(i,o){var r=e.apply(t,n);function s(e){a(r,i,o,s,c,"next",e)}function c(e){a(r,i,o,s,c,"throw",e)}s(void 0)}))}}function s(e,t,n){return(t=l(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){for(var n=0;n5&&"xml"===i)return m("InvalidXml","XML declaration allowed only at the start of the document.",g(e,t));if("?"==e[t]&&">"==e[t+1]){t++;break}}return t}function s(e,t){if(e.length>t+5&&"-"===e[t+1]&&"-"===e[t+2]){for(t+=3;t"===e[t+2]){t+=2;break}}else if(e.length>t+8&&"D"===e[t+1]&&"O"===e[t+2]&&"C"===e[t+3]&&"T"===e[t+4]&&"Y"===e[t+5]&&"P"===e[t+6]&&"E"===e[t+7]){let n=1;for(t+=8;t"===e[t]&&(n--,0===n))break}else if(e.length>t+9&&"["===e[t+1]&&"C"===e[t+2]&&"D"===e[t+3]&&"A"===e[t+4]&&"T"===e[t+5]&&"A"===e[t+6]&&"["===e[t+7])for(t+=8;t"===e[t+2]){t+=2;break}return t}t.validate=function(e,t){t=Object.assign({},o,t);const n=[];let c=!1,l=!1;"\ufeff"===e[0]&&(e=e.substr(1));for(let o=0;o"!==e[o]&&" "!==e[o]&&"\t"!==e[o]&&"\n"!==e[o]&&"\r"!==e[o];o++)y+=e[o];if(y=y.trim(),"/"===y[y.length-1]&&(y=y.substring(0,y.length-1),o--),u=y,!i.isName(u)){let t;return t=0===y.trim().length?"Invalid space after '<'.":"Tag '"+y+"' is an invalid name.",m("InvalidTag",t,g(e,o))}const x=p(e,o);if(!1===x)return m("InvalidAttr","Attributes for '"+y+"' have open quote.",g(e,o));let k=x.value;if(o=x.index,"/"===k[k.length-1]){const n=o-k.length;k=k.substring(0,k.length-1);const i=d(k,t);if(!0!==i)return m(i.err.code,i.err.msg,g(e,n+i.err.line));c=!0}else if(v){if(!x.tagClosed)return m("InvalidTag","Closing tag '"+y+"' doesn't have proper closing.",g(e,o));if(k.trim().length>0)return m("InvalidTag","Closing tag '"+y+"' can't have attributes or invalid starting.",g(e,h));if(0===n.length)return m("InvalidTag","Closing tag '"+y+"' has not been opened.",g(e,h));{const t=n.pop();if(y!==t.tagName){let n=g(e,t.tagStartPos);return m("InvalidTag","Expected closing tag '"+t.tagName+"' (opened in line "+n.line+", col "+n.col+") instead of closing tag '"+y+"'.",g(e,h))}0==n.length&&(l=!0)}}else{const i=d(k,t);if(!0!==i)return m(i.err.code,i.err.msg,g(e,o-k.length+i.err.line));if(!0===l)return m("InvalidXml","Multiple possible root nodes found.",g(e,o));-1!==t.unpairedTags.indexOf(y)||n.push({tagName:y,tagStartPos:h}),c=!0}for(o++;o0)||m("InvalidXml","Invalid '"+JSON.stringify(n.map((e=>e.tagName)),null,4).replace(/\r?\n/g,"")+"' found.",{line:1,col:1}):m("InvalidXml","Start tag expected.",1)};const c='"',l="'";function p(e,t){let n="",i="",o=!1;for(;t"===e[t]&&""===i){o=!0;break}n+=e[t]}return""===i&&{value:n,index:t,tagClosed:o}}const u=new RegExp("(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['\"])(([\\s\\S])*?)\\5)?","g");function d(e,t){const n=i.getAllMatches(e,u),o={};for(let e=0;e{for(const n of e){if("string"==typeof n&&t===n)return!0;if(n instanceof RegExp&&n.test(t))return!0}}:()=>!1}},function(e,t){var n=function(e){var t={},n=function(e){return!t[e]&&(t[e]=[]),t[e]};e.on=function(e,t){n(e).push(t)},e.off=function(e,t){for(var i=n(e),o=i.length-1;o>=0;o--)t===i[o]&&i.splice(o,1)},e.emit=function(e,t){for(var i=n(e).map((function(e){return e})),o=0;o=0;n--){var o=i[n][2];(!o||o+2592e3=0;a--){var r=i[a];(r[0]===e&&r[1]===t||e!==r[0]&&0===r[0].indexOf(o))&&i.splice(a,1)}i.unshift([e,t,Math.round(Date.now()/1e3)]),i.length>n&&i.splice(n),l()}},removeUploadId:function(e){c(),delete p.using[e];for(var t=i.length-1;t>=0;t--)i[t][1]===e&&i.splice(t,1);l()}};e.exports=p},function(e,t,n){var i=n(9);e.exports=i},function(e,t,n){"use strict";var i=n(0),o=n(6),a=n(25),r=n(26),s=n(32),c=n(3),l={SecretId:"",SecretKey:"",SecurityToken:"",StartTime:0,ExpiredTime:0,ChunkRetryTimes:2,FileParallelLimit:3,ChunkParallelLimit:3,ChunkSize:1048576,SliceSize:1048576,CopyChunkParallelLimit:20,CopyChunkSize:10485760,CopySliceSize:10485760,MaxPartNumber:1e4,ProgressInterval:1e3,UploadQueueSize:1e4,Domain:"",ServiceDomain:"",Protocol:"",CompatibilityMode:!1,ForcePathStyle:!1,Timeout:0,CorrectClockSkew:!0,SystemClockOffset:0,UploadCheckContentMd5:!1,UploadAddMetaMd5:!1,UploadIdCacheLimit:50,UseAccelerate:!1,ForceSignHost:!0,HttpDNSServiceId:"",SimpleUploadMethod:"postObject",AutoSwitchHost:!1,CopySourceParser:null,ObjectKeySimplifyCheck:!0,DeepTracker:!1,TrackerDelay:5e3,CustomId:"",BeaconReporter:null,ClsReporter:null},p=function(e){if(this.options=i.extend(i.clone(l),e||{}),this.options.FileParallelLimit=Math.max(1,this.options.FileParallelLimit),this.options.ChunkParallelLimit=Math.max(1,this.options.ChunkParallelLimit),this.options.ChunkRetryTimes=Math.max(0,this.options.ChunkRetryTimes),this.options.ChunkSize=Math.max(1048576,this.options.ChunkSize),this.options.CopyChunkParallelLimit=Math.max(1,this.options.CopyChunkParallelLimit),this.options.CopyChunkSize=Math.max(1048576,this.options.CopyChunkSize),this.options.CopySliceSize=Math.max(0,this.options.CopySliceSize),this.options.MaxPartNumber=Math.max(1024,Math.min(1e4,this.options.MaxPartNumber)),this.options.Timeout=Math.max(0,this.options.Timeout),this.options.EnableReporter=this.options.BeaconReporter||this.options.ClsReporter,this.options.AppId,this.options.SecretId&&this.options.SecretId.indexOf(" "),this.options.SecretKey&&this.options.SecretKey.indexOf(" "),this.options.ForcePathStyle)throw new Error("ForcePathStyle is not supported");o.init(this),a.init(this)};r.init(p,a),s.init(p,a),p.util={md5:i.md5,xml2json:i.xml2json,json2xml:i.json2xml,encodeBase64:i.encodeBase64},p.getAuthorization=i.getAuth,p.version=c.version,e.exports=p},function(e,t,n){(function(e){var t;function i(e){return i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i(e)}!function(){"use strict";var o="input is invalid type",a="object"===("undefined"==typeof window?"undefined":i(window)),r=a?window:{};r.JS_MD5_NO_WINDOW&&(a=!1),!a&&"object"===("undefined"==typeof self?"undefined":i(self))&&(r=self);var s,c=!r.JS_MD5_NO_COMMON_JS&&"object"===i(e)&&e.exports,l=n(12),p=!r.JS_MD5_NO_ARRAY_BUFFER&&"undefined"!=typeof ArrayBuffer,u="0123456789abcdef".split(""),d=[128,32768,8388608,-2147483648],f=[0,8,16,24],m=["hex","array","digest","buffer","arrayBuffer","base64"],h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""),g=[];if(p){var v=new ArrayBuffer(68);s=new Uint8Array(v),g=new Uint32Array(v)}!r.JS_MD5_NO_NODE_JS&&Array.isArray||(Array.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)}),!p||!r.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW&&ArrayBuffer.isView||(ArrayBuffer.isView=function(e){return"object"===i(e)&&e.buffer&&e.buffer.constructor===ArrayBuffer});var y=function(e){return function(t){return new x(!0).update(t)[e]()}};function x(e){if(e)g[0]=g[16]=g[1]=g[2]=g[3]=g[4]=g[5]=g[6]=g[7]=g[8]=g[9]=g[10]=g[11]=g[12]=g[13]=g[14]=g[15]=0,this.blocks=g,this.buffer8=s;else if(p){var t=new ArrayBuffer(68);this.buffer8=new Uint8Array(t),this.blocks=new Uint32Array(t)}else this.blocks=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];this.h0=this.h1=this.h2=this.h3=this.start=this.bytes=this.hBytes=0,this.finalized=this.hashed=!1,this.first=!0}x.prototype.update=function(e){if(!this.finalized){var t,n=i(e);if("string"!==n){if("object"!==n)throw o;if(null===e)throw o;if(!p||e.constructor!==ArrayBuffer&&"ArrayBuffer"!==e.constructor.name){if(!(Array.isArray(e)||p&&ArrayBuffer.isView(e)))throw o}else e=new Uint8Array(e);t=!0}for(var a,r,s=0,c=e.length,l=this.blocks,u=this.buffer8;s>2]|=e[s]<>6,u[r++]=128|63&a):a<55296||a>=57344?(u[r++]=224|a>>12,u[r++]=128|a>>6&63,u[r++]=128|63&a):(a=65536+((1023&a)<<10|1023&e.charCodeAt(++s)),u[r++]=240|a>>18,u[r++]=128|a>>12&63,u[r++]=128|a>>6&63,u[r++]=128|63&a);else for(r=this.start;s>2]|=a<>2]|=(192|a>>6)<>2]|=(128|63&a)<=57344?(l[r>>2]|=(224|a>>12)<>2]|=(128|a>>6&63)<>2]|=(128|63&a)<>2]|=(240|a>>18)<>2]|=(128|a>>12&63)<>2]|=(128|a>>6&63)<>2]|=(128|63&a)<=64?(this.start=r-64,this.hash(),this.hashed=!0):this.start=r}return this.bytes>4294967295&&(this.hBytes+=this.bytes/4294967296<<0,this.bytes=this.bytes%4294967296),this}},x.prototype.finalize=function(){if(!this.finalized){this.finalized=!0;var e=this.blocks,t=this.lastByteIndex;e[t>>2]|=d[3&t],t>=56&&(this.hashed||this.hash(),e[0]=e[16],e[16]=e[1]=e[2]=e[3]=e[4]=e[5]=e[6]=e[7]=e[8]=e[9]=e[10]=e[11]=e[12]=e[13]=e[14]=e[15]=0),e[14]=this.bytes<<3,e[15]=this.hBytes<<3|this.bytes>>>29,this.hash()}},x.prototype.hash=function(){var e,t,n,i,o,a,r=this.blocks;this.first?t=((t=((e=((e=r[0]-680876937)<<7|e>>>25)-271733879<<0)^(n=((n=(-271733879^(i=((i=(-1732584194^2004318071&e)+r[1]-117830708)<<12|i>>>20)+e<<0)&(-271733879^e))+r[2]-1126478375)<<17|n>>>15)+i<<0)&(i^e))+r[3]-1316259209)<<22|t>>>10)+n<<0:(e=this.h0,t=this.h1,n=this.h2,t=((t+=((e=((e+=((i=this.h3)^t&(n^i))+r[0]-680876936)<<7|e>>>25)+t<<0)^(n=((n+=(t^(i=((i+=(n^e&(t^n))+r[1]-389564586)<<12|i>>>20)+e<<0)&(e^t))+r[2]+606105819)<<17|n>>>15)+i<<0)&(i^e))+r[3]-1044525330)<<22|t>>>10)+n<<0),t=((t+=((e=((e+=(i^t&(n^i))+r[4]-176418897)<<7|e>>>25)+t<<0)^(n=((n+=(t^(i=((i+=(n^e&(t^n))+r[5]+1200080426)<<12|i>>>20)+e<<0)&(e^t))+r[6]-1473231341)<<17|n>>>15)+i<<0)&(i^e))+r[7]-45705983)<<22|t>>>10)+n<<0,t=((t+=((e=((e+=(i^t&(n^i))+r[8]+1770035416)<<7|e>>>25)+t<<0)^(n=((n+=(t^(i=((i+=(n^e&(t^n))+r[9]-1958414417)<<12|i>>>20)+e<<0)&(e^t))+r[10]-42063)<<17|n>>>15)+i<<0)&(i^e))+r[11]-1990404162)<<22|t>>>10)+n<<0,t=((t+=((e=((e+=(i^t&(n^i))+r[12]+1804603682)<<7|e>>>25)+t<<0)^(n=((n+=(t^(i=((i+=(n^e&(t^n))+r[13]-40341101)<<12|i>>>20)+e<<0)&(e^t))+r[14]-1502002290)<<17|n>>>15)+i<<0)&(i^e))+r[15]+1236535329)<<22|t>>>10)+n<<0,t=((t+=((i=((i+=(t^n&((e=((e+=(n^i&(t^n))+r[1]-165796510)<<5|e>>>27)+t<<0)^t))+r[6]-1069501632)<<9|i>>>23)+e<<0)^e&((n=((n+=(e^t&(i^e))+r[11]+643717713)<<14|n>>>18)+i<<0)^i))+r[0]-373897302)<<20|t>>>12)+n<<0,t=((t+=((i=((i+=(t^n&((e=((e+=(n^i&(t^n))+r[5]-701558691)<<5|e>>>27)+t<<0)^t))+r[10]+38016083)<<9|i>>>23)+e<<0)^e&((n=((n+=(e^t&(i^e))+r[15]-660478335)<<14|n>>>18)+i<<0)^i))+r[4]-405537848)<<20|t>>>12)+n<<0,t=((t+=((i=((i+=(t^n&((e=((e+=(n^i&(t^n))+r[9]+568446438)<<5|e>>>27)+t<<0)^t))+r[14]-1019803690)<<9|i>>>23)+e<<0)^e&((n=((n+=(e^t&(i^e))+r[3]-187363961)<<14|n>>>18)+i<<0)^i))+r[8]+1163531501)<<20|t>>>12)+n<<0,t=((t+=((i=((i+=(t^n&((e=((e+=(n^i&(t^n))+r[13]-1444681467)<<5|e>>>27)+t<<0)^t))+r[2]-51403784)<<9|i>>>23)+e<<0)^e&((n=((n+=(e^t&(i^e))+r[7]+1735328473)<<14|n>>>18)+i<<0)^i))+r[12]-1926607734)<<20|t>>>12)+n<<0,t=((t+=((a=(i=((i+=((o=t^n)^(e=((e+=(o^i)+r[5]-378558)<<4|e>>>28)+t<<0))+r[8]-2022574463)<<11|i>>>21)+e<<0)^e)^(n=((n+=(a^t)+r[11]+1839030562)<<16|n>>>16)+i<<0))+r[14]-35309556)<<23|t>>>9)+n<<0,t=((t+=((a=(i=((i+=((o=t^n)^(e=((e+=(o^i)+r[1]-1530992060)<<4|e>>>28)+t<<0))+r[4]+1272893353)<<11|i>>>21)+e<<0)^e)^(n=((n+=(a^t)+r[7]-155497632)<<16|n>>>16)+i<<0))+r[10]-1094730640)<<23|t>>>9)+n<<0,t=((t+=((a=(i=((i+=((o=t^n)^(e=((e+=(o^i)+r[13]+681279174)<<4|e>>>28)+t<<0))+r[0]-358537222)<<11|i>>>21)+e<<0)^e)^(n=((n+=(a^t)+r[3]-722521979)<<16|n>>>16)+i<<0))+r[6]+76029189)<<23|t>>>9)+n<<0,t=((t+=((a=(i=((i+=((o=t^n)^(e=((e+=(o^i)+r[9]-640364487)<<4|e>>>28)+t<<0))+r[12]-421815835)<<11|i>>>21)+e<<0)^e)^(n=((n+=(a^t)+r[15]+530742520)<<16|n>>>16)+i<<0))+r[2]-995338651)<<23|t>>>9)+n<<0,t=((t+=((i=((i+=(t^((e=((e+=(n^(t|~i))+r[0]-198630844)<<6|e>>>26)+t<<0)|~n))+r[7]+1126891415)<<10|i>>>22)+e<<0)^((n=((n+=(e^(i|~t))+r[14]-1416354905)<<15|n>>>17)+i<<0)|~e))+r[5]-57434055)<<21|t>>>11)+n<<0,t=((t+=((i=((i+=(t^((e=((e+=(n^(t|~i))+r[12]+1700485571)<<6|e>>>26)+t<<0)|~n))+r[3]-1894986606)<<10|i>>>22)+e<<0)^((n=((n+=(e^(i|~t))+r[10]-1051523)<<15|n>>>17)+i<<0)|~e))+r[1]-2054922799)<<21|t>>>11)+n<<0,t=((t+=((i=((i+=(t^((e=((e+=(n^(t|~i))+r[8]+1873313359)<<6|e>>>26)+t<<0)|~n))+r[15]-30611744)<<10|i>>>22)+e<<0)^((n=((n+=(e^(i|~t))+r[6]-1560198380)<<15|n>>>17)+i<<0)|~e))+r[13]+1309151649)<<21|t>>>11)+n<<0,t=((t+=((i=((i+=(t^((e=((e+=(n^(t|~i))+r[4]-145523070)<<6|e>>>26)+t<<0)|~n))+r[11]-1120210379)<<10|i>>>22)+e<<0)^((n=((n+=(e^(i|~t))+r[2]+718787259)<<15|n>>>17)+i<<0)|~e))+r[9]-343485551)<<21|t>>>11)+n<<0,this.first?(this.h0=e+1732584193<<0,this.h1=t-271733879<<0,this.h2=n-1732584194<<0,this.h3=i+271733878<<0,this.first=!1):(this.h0=this.h0+e<<0,this.h1=this.h1+t<<0,this.h2=this.h2+n<<0,this.h3=this.h3+i<<0)},x.prototype.hex=function(){this.finalize();var e=this.h0,t=this.h1,n=this.h2,i=this.h3;return u[e>>4&15]+u[15&e]+u[e>>12&15]+u[e>>8&15]+u[e>>20&15]+u[e>>16&15]+u[e>>28&15]+u[e>>24&15]+u[t>>4&15]+u[15&t]+u[t>>12&15]+u[t>>8&15]+u[t>>20&15]+u[t>>16&15]+u[t>>28&15]+u[t>>24&15]+u[n>>4&15]+u[15&n]+u[n>>12&15]+u[n>>8&15]+u[n>>20&15]+u[n>>16&15]+u[n>>28&15]+u[n>>24&15]+u[i>>4&15]+u[15&i]+u[i>>12&15]+u[i>>8&15]+u[i>>20&15]+u[i>>16&15]+u[i>>28&15]+u[i>>24&15]},x.prototype.toString=x.prototype.hex,x.prototype.digest=function(){this.finalize();var e=this.h0,t=this.h1,n=this.h2,i=this.h3;return[255&e,e>>8&255,e>>16&255,e>>24&255,255&t,t>>8&255,t>>16&255,t>>24&255,255&n,n>>8&255,n>>16&255,n>>24&255,255&i,i>>8&255,i>>16&255,i>>24&255]},x.prototype.array=x.prototype.digest,x.prototype.arrayBuffer=function(){this.finalize();var e=new ArrayBuffer(16),t=new Uint32Array(e);return t[0]=this.h0,t[1]=this.h1,t[2]=this.h2,t[3]=this.h3,e},x.prototype.buffer=x.prototype.arrayBuffer,x.prototype.base64=function(){for(var e,t,n,i="",o=this.array(),a=0;a<15;)e=o[a++],t=o[a++],n=o[a++],i+=h[e>>>2]+h[63&(e<<4|t>>>4)]+h[63&(t<<2|n>>>6)]+h[63&n];return e=o[a],i+=h[e>>>2]+h[e<<4&63]+"=="};var k=function(){var e=y("hex");e.getCtx=e.create=function(){return new x},e.update=function(t){return e.create().update(t)};for(var t=0;t>>2]|=(n[o>>>2]>>>24-o%4*8&255)<<24-(i+o)%4*8;else if(65535>>2]=n[o>>>2];else t.push.apply(t,n);return this.sigBytes+=e,this},clamp:function(){var t=this.words,n=this.sigBytes;t[n>>>2]&=4294967295<<32-n%4*8,t.length=e.ceil(n/4)},clone:function(){var e=a.clone.call(this);return e.words=this.words.slice(0),e},random:function(t){for(var n=[],i=0;i>>2]>>>24-i%4*8&255;n.push((o>>>4).toString(16)),n.push((15&o).toString(16))}return n.join("")},parse:function(e){for(var t=e.length,n=[],i=0;i>>3]|=parseInt(e.substr(i,2),16)<<24-i%8*4;return new r.init(n,t/2)}},l=s.Latin1={stringify:function(e){var t=e.words;e=e.sigBytes;for(var n=[],i=0;i>>2]>>>24-i%4*8&255));return n.join("")},parse:function(e){for(var t=e.length,n=[],i=0;i>>2]|=(255&e.charCodeAt(i))<<24-i%4*8;return new r.init(n,t)}},p=s.Utf8={stringify:function(e){try{return decodeURIComponent(escape(l.stringify(e)))}catch(e){throw Error("Malformed UTF-8 data")}},parse:function(e){return l.parse(unescape(encodeURIComponent(e)))}},u=i.BufferedBlockAlgorithm=a.extend({reset:function(){this._data=new r.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=p.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(t){var n=this._data,i=n.words,o=n.sigBytes,a=this.blockSize,s=o/(4*a);if(t=(s=t?e.ceil(s):e.max((0|s)-this._minBufferSize,0))*a,o=e.min(4*t,o),t){for(var c=0;cl;l++){if(16>l)a[l]=0|e[t+l];else{var p=a[l-3]^a[l-8]^a[l-14]^a[l-16];a[l]=p<<1|p>>>31}p=(i<<5|i>>>27)+c+a[l],p=20>l?p+(1518500249+(o&r|~o&s)):40>l?p+(1859775393+(o^r^s)):60>l?p+((o&r|o&s|r&s)-1894007588):p+((o^r^s)-899497514),c=s,s=r,r=o<<30|o>>>2,o=i,i=p}n[0]=n[0]+i|0,n[1]=n[1]+o|0,n[2]=n[2]+r|0,n[3]=n[3]+s|0,n[4]=n[4]+c|0},_doFinalize:function(){var e=this._data,t=e.words,n=8*this._nDataBytes,i=8*e.sigBytes;return t[i>>>5]|=128<<24-i%32,t[14+(i+64>>>9<<4)]=Math.floor(n/4294967296),t[15+(i+64>>>9<<4)]=n,e.sigBytes=4*t.length,this._process(),this._hash},clone:function(){var e=o.clone.call(this);return e._hash=this._hash.clone(),e}}),n.SHA1=o._createHelper(r),n.HmacSHA1=o._createHmacHelper(r),function(){var e=l,t=e.enc.Utf8;e.algo.HMAC=e.lib.Base.extend({init:function(e,n){e=this._hasher=new e.init,"string"==typeof n&&(n=t.parse(n));var i=e.blockSize,o=4*i;n.sigBytes>o&&(n=e.finalize(n)),n.clamp();for(var a=this._oKey=n.clone(),r=this._iKey=n.clone(),s=a.words,c=r.words,l=0;l>>2]>>>24-a%4*8&255)<<16|(t[a+1>>>2]>>>24-(a+1)%4*8&255)<<8|t[a+2>>>2]>>>24-(a+2)%4*8&255,s=0;s<4&&a+.75*s>>6*(3-s)&63));var c=i.charAt(64);if(c)for(;o.length%4;)o.push(c);return o.join("")},parse:function(e){var t=e.length,n=this._map,i=n.charAt(64);if(i){var o=e.indexOf(i);-1!=o&&(t=o)}for(var a=[],r=0,s=0;s>>6-s%4*2;a[r>>>2]|=(l|p)<<24-r%4*8,r++}return c.create(a,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},e.exports=l},function(e,t){var n=function(e){var t=(e=e||{}).Base64,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",i=function(e){for(var t={},n=0,i=e.length;n>>6)+o(128|63&t):o(224|t>>>12&15)+o(128|t>>>6&63)+o(128|63&t);var t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320);return o(240|t>>>18&7)+o(128|t>>>12&63)+o(128|t>>>6&63)+o(128|63&t)},r=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,s=function(e){return e.replace(r,a)},c=function(e){var t=[0,2,1][e.length%3],i=e.charCodeAt(0)<<16|(e.length>1?e.charCodeAt(1):0)<<8|(e.length>2?e.charCodeAt(2):0);return[n.charAt(i>>>18),n.charAt(i>>>12&63),t>=2?"=":n.charAt(i>>>6&63),t>=1?"=":n.charAt(63&i)].join("")},l=e.btoa?function(t){return e.btoa(t)}:function(e){return e.replace(/[\s\S]{1,3}/g,c)},p=function(e){return l(s(e))},u=function(e,t){return t?p(String(e)).replace(/[+\/]/g,(function(e){return"+"==e?"-":"_"})).replace(/=/g,""):p(String(e))},d=new RegExp(["[À-ß][€-¿]","[à-ï][€-¿]{2}","[ð-÷][€-¿]{3}"].join("|"),"g"),f=function(e){switch(e.length){case 4:var t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return o(55296+(t>>>10))+o(56320+(1023&t));case 3:return o((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return o((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},m=function(e){return e.replace(d,f)},h=function(e){var t=e.length,n=t%4,a=(t>0?i[e.charAt(0)]<<18:0)|(t>1?i[e.charAt(1)]<<12:0)|(t>2?i[e.charAt(2)]<<6:0)|(t>3?i[e.charAt(3)]:0),r=[o(a>>>16),o(a>>>8&255),o(255&a)];return r.length-=[0,0,2,1][n],r.join("")},g=e.atob?function(t){return e.atob(t)}:function(e){return e.replace(/[\s\S]{1,4}/g,h)},v=function(e){return m(g(e))},y=function(e){return v(String(e).replace(/[-_]/g,(function(e){return"-"==e?"+":"/"})).replace(/[^A-Za-z0-9\+\/]/g,""))};return{VERSION:"2.1.9",atob:g,btoa:l,fromBase64:y,toBase64:u,utob:s,encode:u,encodeURI:function(e){return u(e,!0)},btou:m,decode:y,noConflict:function(){var n=e.Base64;return e.Base64=t,n}}}();e.exports=n},function(e,t,n){"use strict";const i=n(4),o=n(16),a=n(23);e.exports={XMLParser:o,XMLValidator:i,XMLBuilder:a}},function(e,t,n){const{buildOptions:i}=n(17),o=n(18),{prettify:a}=n(22),r=n(4);e.exports=class{constructor(e){this.externalEntities={},this.options=i(e)}parse(e,t){if("string"==typeof e);else{if(!e.toString)throw new Error("XML data is accepted in String or Bytes[] form.");e=e.toString()}if(t){!0===t&&(t={});const n=r.validate(e,t);if(!0!==n)throw Error(`${n.err.msg}:${n.err.line}:${n.err.col}`)}const n=new o(this.options);n.addExternalEntities(this.externalEntities);const i=n.parseXml(e);return this.options.preserveOrder||void 0===i?i:a(i,this.options)}addEntity(e,t){if(-1!==t.indexOf("&"))throw new Error("Entity value can't have '&'");if(-1!==e.indexOf("&")||-1!==e.indexOf(";"))throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for ' '");if("&"===t)throw new Error("An entity with value '&' is not permitted");this.externalEntities[e]=t}}},function(e,t){const n={preserveOrder:!1,attributeNamePrefix:"@_",attributesGroupName:!1,textNodeName:"#text",ignoreAttributes:!0,removeNSPrefix:!1,allowBooleanAttributes:!1,parseTagValue:!0,parseAttributeValue:!1,trimValues:!0,cdataPropName:!1,numberParseOptions:{hex:!0,leadingZeros:!0,eNotation:!0},tagValueProcessor:function(e,t){return t},attributeValueProcessor:function(e,t){return t},stopNodes:[],alwaysCreateTextNode:!1,isArray:()=>!1,commentPropName:!1,unpairedTags:[],processEntities:!0,htmlEntities:!1,ignoreDeclaration:!1,ignorePiTags:!1,transformTagName:!1,transformAttributeName:!1,updateTag:function(e,t,n){return e}};t.buildOptions=function(e){return Object.assign({},n,e)},t.defaultOptions=n},function(e,t,n){"use strict";const i=n(1),o=n(19),a=n(20),r=n(21),s=n(5);function c(e){const t=Object.keys(e);for(let n=0;n0)){r||(e=this.replaceEntitiesValue(e));const i=this.options.tagValueProcessor(t,e,n,o,a);if(null==i)return e;if(typeof i!=typeof e||i!==e)return i;if(this.options.trimValues)return b(e,this.options.parseTagValue,this.options.numberParseOptions);return e.trim()===e?b(e,this.options.parseTagValue,this.options.numberParseOptions):e}}function p(e){if(this.options.removeNSPrefix){const t=e.split(":"),n="/"===e.charAt(0)?"/":"";if("xmlns"===t[0])return"";2===t.length&&(e=n+t[1])}return e}const u=new RegExp("([^\\s=]+)\\s*(=\\s*(['\"])([\\s\\S]*?)\\3)?","gm");function d(e,t,n){if(!0!==this.options.ignoreAttributes&&"string"==typeof e){const n=i.getAllMatches(e,u),o=n.length,a={};for(let e=0;e",s,"Closing Tag is not closed.");let o=e.substring(s+2,t).trim();if(this.options.removeNSPrefix){const e=o.indexOf(":");-1!==e&&(o=o.substr(e+1))}this.options.transformTagName&&(o=this.options.transformTagName(o)),n&&(i=this.saveTextToParentTag(i,n,r));const a=r.substring(r.lastIndexOf(".")+1);if(o&&-1!==this.options.unpairedTags.indexOf(o))throw new Error(`Unpaired tag can not be used as closing tag: `);let c=0;a&&-1!==this.options.unpairedTags.indexOf(a)?(c=r.lastIndexOf(".",r.lastIndexOf(".")-1),this.tagsNodeStack.pop()):c=r.lastIndexOf("."),r=r.substring(0,c),n=this.tagsNodeStack.pop(),i="",s=t}else if("?"===e[s+1]){let t=x(e,s,!1,"?>");if(!t)throw new Error("Pi Tag is not closed.");if(i=this.saveTextToParentTag(i,n,r),this.options.ignoreDeclaration&&"?xml"===t.tagName||this.options.ignorePiTags);else{const e=new o(t.tagName);e.add(this.options.textNodeName,""),t.tagName!==t.tagExp&&t.attrExpPresent&&(e[":@"]=this.buildAttributesMap(t.tagExp,r,t.tagName)),this.addChild(n,e,r)}s=t.closeIndex+1}else if("!--"===e.substr(s+1,3)){const t=y(e,"--\x3e",s+4,"Comment is not closed.");if(this.options.commentPropName){const o=e.substring(s+4,t-2);i=this.saveTextToParentTag(i,n,r),n.add(this.options.commentPropName,[{[this.options.textNodeName]:o}])}s=t}else if("!D"===e.substr(s+1,2)){const t=a(e,s);this.docTypeEntities=t.entities,s=t.i}else if("!["===e.substr(s+1,2)){const t=y(e,"]]>",s,"CDATA is not closed.")-2,o=e.substring(s+9,t);i=this.saveTextToParentTag(i,n,r);let a=this.parseTextData(o,n.tagname,r,!0,!1,!0,!0);null==a&&(a=""),this.options.cdataPropName?n.add(this.options.cdataPropName,[{[this.options.textNodeName]:o}]):n.add(this.options.textNodeName,a),s=t+2}else{let a=x(e,s,this.options.removeNSPrefix),c=a.tagName;const l=a.rawTagName;let p=a.tagExp,u=a.attrExpPresent,d=a.closeIndex;this.options.transformTagName&&(c=this.options.transformTagName(c)),n&&i&&"!xml"!==n.tagname&&(i=this.saveTextToParentTag(i,n,r,!1));const f=n;if(f&&-1!==this.options.unpairedTags.indexOf(f.tagname)&&(n=this.tagsNodeStack.pop(),r=r.substring(0,r.lastIndexOf("."))),c!==t.tagname&&(r+=r?"."+c:c),this.isItStopNode(this.options.stopNodes,r,c)){let t="";if(p.length>0&&p.lastIndexOf("/")===p.length-1)"/"===c[c.length-1]?(c=c.substr(0,c.length-1),r=r.substr(0,r.length-1),p=c):p=p.substr(0,p.length-1),s=a.closeIndex;else if(-1!==this.options.unpairedTags.indexOf(c))s=a.closeIndex;else{const n=this.readStopNodeData(e,l,d+1);if(!n)throw new Error(`Unexpected end of ${l}`);s=n.i,t=n.tagContent}const i=new o(c);c!==p&&u&&(i[":@"]=this.buildAttributesMap(p,r,c)),t&&(t=this.parseTextData(t,c,r,!0,u,!0,!0)),r=r.substr(0,r.lastIndexOf(".")),i.add(this.options.textNodeName,t),this.addChild(n,i,r)}else{if(p.length>0&&p.lastIndexOf("/")===p.length-1){"/"===c[c.length-1]?(c=c.substr(0,c.length-1),r=r.substr(0,r.length-1),p=c):p=p.substr(0,p.length-1),this.options.transformTagName&&(c=this.options.transformTagName(c));const e=new o(c);c!==p&&u&&(e[":@"]=this.buildAttributesMap(p,r,c)),this.addChild(n,e,r),r=r.substr(0,r.lastIndexOf("."))}else{const e=new o(c);this.tagsNodeStack.push(n),c!==p&&u&&(e[":@"]=this.buildAttributesMap(p,r,c)),this.addChild(n,e,r),n=e}i="",s=d}}else i+=e[s]}return t.child};function m(e,t,n){const i=this.options.updateTag(t.tagname,n,t[":@"]);!1===i||("string"==typeof i?(t.tagname=i,e.addChild(t)):e.addChild(t))}const h=function(e){if(this.options.processEntities){for(let t in this.docTypeEntities){const n=this.docTypeEntities[t];e=e.replace(n.regx,n.val)}for(let t in this.lastEntities){const n=this.lastEntities[t];e=e.replace(n.regex,n.val)}if(this.options.htmlEntities)for(let t in this.htmlEntities){const n=this.htmlEntities[t];e=e.replace(n.regex,n.val)}e=e.replace(this.ampEntity.regex,this.ampEntity.val)}return e};function g(e,t,n,i){return e&&(void 0===i&&(i=0===Object.keys(t.child).length),void 0!==(e=this.parseTextData(e,t.tagname,n,!1,!!t[":@"]&&0!==Object.keys(t[":@"]).length,i))&&""!==e&&t.add(this.options.textNodeName,e),e=""),e}function v(e,t,n){const i="*."+n;for(const n in e){const o=e[n];if(i===o||t===o)return!0}return!1}function y(e,t,n,i){const o=e.indexOf(t,n);if(-1===o)throw new Error(i);return o+t.length-1}function x(e,t,n,i=">"){const o=function(e,t,n=">"){let i,o="";for(let a=t;a",n,`${t} is not closed`);if(e.substring(n+2,a).trim()===t&&(o--,0===o))return{tagContent:e.substring(i,n),i:a};n=a}else if("?"===e[n+1]){n=y(e,"?>",n+1,"StopNode is not closed.")}else if("!--"===e.substr(n+1,3)){n=y(e,"--\x3e",n+3,"StopNode is not closed.")}else if("!["===e.substr(n+1,2)){n=y(e,"]]>",n,"StopNode is not closed.")-2}else{const i=x(e,n,">");if(i){(i&&i.tagName)===t&&"/"!==i.tagExp[i.tagExp.length-1]&&o++,n=i.closeIndex}}}function b(e,t,n){if(t&&"string"==typeof e){const t=e.trim();return"true"===t||"false"!==t&&r(e,n)}return i.isExist(e)?e:""}e.exports=class{constructor(e){this.options=e,this.currentNode=null,this.tagsNodeStack=[],this.docTypeEntities={},this.lastEntities={apos:{regex:/&(apos|#39|#x27);/g,val:"'"},gt:{regex:/&(gt|#62|#x3E);/g,val:">"},lt:{regex:/&(lt|#60|#x3C);/g,val:"<"},quot:{regex:/&(quot|#34|#x22);/g,val:'"'}},this.ampEntity={regex:/&(amp|#38|#x26);/g,val:"&"},this.htmlEntities={space:{regex:/&(nbsp|#160);/g,val:" "},cent:{regex:/&(cent|#162);/g,val:"¢"},pound:{regex:/&(pound|#163);/g,val:"£"},yen:{regex:/&(yen|#165);/g,val:"¥"},euro:{regex:/&(euro|#8364);/g,val:"€"},copyright:{regex:/&(copy|#169);/g,val:"©"},reg:{regex:/&(reg|#174);/g,val:"®"},inr:{regex:/&(inr|#8377);/g,val:"₹"},num_dec:{regex:/&#([0-9]{1,7});/g,val:(e,t)=>String.fromCharCode(Number.parseInt(t,10))},num_hex:{regex:/&#x([0-9a-fA-F]{1,6});/g,val:(e,t)=>String.fromCharCode(Number.parseInt(t,16))}},this.addExternalEntities=c,this.parseXml=f,this.parseTextData=l,this.resolveNameSpace=p,this.buildAttributesMap=d,this.isItStopNode=v,this.replaceEntitiesValue=h,this.readStopNodeData=k,this.saveTextToParentTag=g,this.addChild=m,this.ignoreAttributesFn=s(this.options.ignoreAttributes)}}},function(e,t,n){"use strict";e.exports=class{constructor(e){this.tagname=e,this.child=[],this[":@"]={}}add(e,t){"__proto__"===e&&(e="#__proto__"),this.child.push({[e]:t})}addChild(e){"__proto__"===e.tagname&&(e.tagname="#__proto__"),e[":@"]&&Object.keys(e[":@"]).length>0?this.child.push({[e.tagname]:e.child,":@":e[":@"]}):this.child.push({[e.tagname]:e.child})}}},function(e,t,n){const i=n(1);function o(e,t){let n="";for(;t"===e[t]){if(d?"-"===e[t-1]&&"-"===e[t-2]&&(d=!1,i--):i--,0===i)break}else"["===e[t]?u=!0:f+=e[t];else{if(u&&r(e,t))t+=7,[entityName,val,t]=o(e,t+1),-1===val.indexOf("&")&&(n[p(entityName)]={regx:RegExp(`&${entityName};`,"g"),val:val});else if(u&&s(e,t))t+=8;else if(u&&c(e,t))t+=8;else if(u&&l(e,t))t+=9;else{if(!a)throw new Error("Invalid DOCTYPE");d=!0}i++,f=""}if(0!==i)throw new Error("Unclosed DOCTYPE")}return{entities:n,i:t}}},function(e,t){const n=/^[-+]?0x[a-fA-F0-9]+$/,i=/^([\-\+])?(0*)(\.[0-9]+([eE]\-?[0-9]+)?|[0-9]+(\.[0-9]+([eE]\-?[0-9]+)?)?)$/;!Number.parseInt&&window.parseInt&&(Number.parseInt=window.parseInt),!Number.parseFloat&&window.parseFloat&&(Number.parseFloat=window.parseFloat);const o={hex:!0,leadingZeros:!0,decimalPoint:".",eNotation:!0};e.exports=function(e,t={}){if(t=Object.assign({},o,t),!e||"string"!=typeof e)return e;let a=e.trim();if(void 0!==t.skipLike&&t.skipLike.test(a))return e;if(t.hex&&n.test(a))return Number.parseInt(a,16);{const n=i.exec(a);if(n){const i=n[1],o=n[2];let r=function(e){if(e&&-1!==e.indexOf("."))return"."===(e=e.replace(/0+$/,""))?e="0":"."===e[0]?e="0"+e:"."===e[e.length-1]&&(e=e.substr(0,e.length-1)),e;return e}(n[3]);const s=n[4]||n[6];if(!t.leadingZeros&&o.length>0&&i&&"."!==a[2])return e;if(!t.leadingZeros&&o.length>0&&!i&&"."!==a[1])return e;{const n=Number(a),c=""+n;return-1!==c.search(/[eE]/)||s?t.eNotation?n:e:-1!==a.indexOf(".")?"0"===c&&""===r||c===r||i&&c==="-"+r?n:e:o?r===c||i+r===c?n:e:a===c||a===i+c?n:e}}return e}}},function(e,t,n){"use strict";function i(e,t,n){let s;const c={};for(let l=0;l0&&(c[t.textNodeName]=s):void 0!==s&&(c[t.textNodeName]=s),c}function o(e){const t=Object.keys(e);for(let e=0;e","g"),val:">"},{regex:new RegExp("<","g"),val:"<"},{regex:new RegExp("'","g"),val:"'"},{regex:new RegExp('"',"g"),val:"""}],processEntities:!0,stopNodes:[],oneListGroup:!1};function r(e){this.options=Object.assign({},a,e),!0===this.options.ignoreAttributes||this.options.attributesGroupName?this.isAttribute=function(){return!1}:(this.ignoreAttributesFn=o(this.options.ignoreAttributes),this.attrPrefixLen=this.options.attributeNamePrefix.length,this.isAttribute=l),this.processTextOrObjNode=s,this.options.format?(this.indentate=c,this.tagEndChar=">\n",this.newLine="\n"):(this.indentate=function(){return""},this.tagEndChar=">",this.newLine="")}function s(e,t,n,i){const o=this.j2x(e,n+1,i.concat(t));return void 0!==e[this.options.textNodeName]&&1===Object.keys(e).length?this.buildTextValNode(e[this.options.textNodeName],t,o.attrStr,n):this.buildObjectNode(o.val,t,o.attrStr,n)}function c(e){return this.options.indentBy.repeat(e)}function l(e){return!(!e.startsWith(this.options.attributeNamePrefix)||e===this.options.textNodeName)&&e.substr(this.attrPrefixLen)}r.prototype.build=function(e){return this.options.preserveOrder?i(e,this.options):(Array.isArray(e)&&this.options.arrayNodeName&&this.options.arrayNodeName.length>1&&(e={[this.options.arrayNodeName]:e}),this.j2x(e,0,[]).val)},r.prototype.j2x=function(e,t,n){let i="",o="";const a=n.join(".");for(let r in e)if(Object.prototype.hasOwnProperty.call(e,r))if(void 0===e[r])this.isAttribute(r)&&(o+="");else if(null===e[r])this.isAttribute(r)?o+="":"?"===r[0]?o+=this.indentate(t)+"<"+r+"?"+this.tagEndChar:o+=this.indentate(t)+"<"+r+"/"+this.tagEndChar;else if(e[r]instanceof Date)o+=this.buildTextValNode(e[r],r,"",t);else if("object"!=typeof e[r]){const n=this.isAttribute(r);if(n&&!this.ignoreAttributesFn(n,a))i+=this.buildAttrPairStr(n,""+e[r]);else if(!n)if(r===this.options.textNodeName){let t=this.options.tagValueProcessor(r,""+e[r]);o+=this.replaceEntitiesValue(t)}else o+=this.buildTextValNode(e[r],r,"",t)}else if(Array.isArray(e[r])){const i=e[r].length;let a="",s="";for(let c=0;c"+e+o}},r.prototype.closeTag=function(e){let t="";return-1!==this.options.unpairedTags.indexOf(e)?this.options.suppressUnpairedNode||(t="/"):t=this.options.suppressEmptyNode?"/":`>`+this.newLine;if(!1!==this.options.commentPropName&&t===this.options.commentPropName)return this.indentate(i)+`\x3c!--${e}--\x3e`+this.newLine;if("?"===t[0])return this.indentate(i)+"<"+t+n+"?"+this.tagEndChar;{let o=this.options.tagValueProcessor(t,e);return o=this.replaceEntitiesValue(o),""===o?this.indentate(i)+"<"+t+n+this.closeTag(t)+this.tagEndChar:this.indentate(i)+"<"+t+n+">"+o+"0&&this.options.processEntities)for(let t=0;t`,p=!1;continue}if(f===t.commentPropName){l+=c+`\x3c!--${d[f][0][t.textNodeName]}--\x3e`,p=!0;continue}if("?"===f[0]){const e=o(d[":@"],t),n="?xml"===f?"":c;let i=d[f][0][t.textNodeName];i=0!==i.length?" "+i:"",l+=n+`<${f}${i}${e}?>`,p=!0;continue}let h=c;""!==h&&(h+=t.indentBy);const g=c+`<${f}${o(d[":@"],t)}`,v=n(d[f],t,m,h);-1!==t.unpairedTags.indexOf(f)?t.suppressUnpairedNode?l+=g+">":l+=g+"/>":v&&0!==v.length||!t.suppressEmptyNode?v&&v.endsWith(">")?l+=g+`>${v}${c}`:(l+=g+">",v&&""!==c&&(v.includes("/>")||v.includes("`):l+=g+"/>",p=!0}return l}function i(e){const t=Object.keys(e);for(let n=0;n0&&t.processEntities)for(let n=0;n0&&(i="\n"),n(e,t,"",i)}},function(e,t,n){var i=n(7),o=n(0),a={};e.exports.transferToTaskMethod=function(e,t){a[t]=e[t],e[t]=function(e,n){e.SkipTask?a[t].call(this,e,n):this._addTask(t,e,n)}},e.exports.init=function(e){var t,n,r=[],s={},c=0,l=0,p=function(e){var t={id:e.id,Bucket:e.Bucket,Region:e.Region,Key:e.Key,FilePath:e.FilePath,state:e.state,loaded:e.loaded,size:e.size,speed:e.speed,percent:e.percent,hashPercent:e.hashPercent,error:e.error};return e.FilePath&&(t.FilePath=e.FilePath),t},u=(n=function(){t=0,e.emit("task-list-update",{list:o.map(r,p)}),e.emit("list-update",{list:o.map(r,p)})},function(){t||(t=setTimeout(n))}),d=function(){if(!(r.length<=e.options.UploadQueueSize)){for(var t=0;te.options.UploadQueueSize;){var n="waiting"===r[t].state||"checking"===r[t].state||"uploading"===r[t].state;r[t]&&n?t++:(s[r[t].id]&&delete s[r[t].id],r.splice(t,1),l--)}u()}},f=function t(){if(!(c>=e.options.FileParallelLimit)){for(;r[l]&&"waiting"!==r[l].state;)l++;if(!(l>=r.length)){var n=r[l];l++,c++,n.state="checking",n.params.onTaskStart&&n.params.onTaskStart(p(n)),!n.params.UploadData&&(n.params.UploadData={});var i=o.formatParams(n.api,n.params);a[n.api].call(e,i,(function(i,o){e._isRunningTask(n.id)&&("checking"!==n.state&&"uploading"!==n.state||(n.state=i?"error":"success",i&&(n.error=i),c--,u(),t(),n.callback&&n.callback(i,o),"success"===n.state&&(n.params&&(delete n.params.UploadData,delete n.params.Body,delete n.params),delete n.callback)),d())})),u(),setTimeout(t)}}},m=function(t,n){var o=s[t];if(o){var a=o&&"waiting"===o.state,r=o&&("checking"===o.state||"uploading"===o.state);if("canceled"===n&&"canceled"!==o.state||"paused"===n&&a||"paused"===n&&r){if("paused"===n&&o.params.Body&&"function"==typeof o.params.Body.pipe)return;o.state=n,e.emit("inner-kill-task",{TaskId:t,toState:n});try{var l=o&&o.params&&o.params.UploadData.UploadId}catch(e){}"canceled"===n&&l&&i.removeUsing(l),u(),r&&(c--,f()),"canceled"===n&&(o.params&&(delete o.params.UploadData,delete o.params.Body,delete o.params),delete o.callback)}d()}};e._addTasks=function(t){o.each(t,(function(t){e._addTask(t.api,t.params,t.callback,!0)})),u()},e._addTask=function(t,n,i,a){var c="postObject"===e.options.SimpleUploadMethod?"postObject":"putObject";"sliceUploadFile"!==t||o.canFileSlice()||(t=c),n=o.formatParams(t,n);var l=o.uuid();n.TaskId=l,n.onTaskReady&&n.onTaskReady(l);var p={params:n,callback:i,api:t,index:r.length,id:l,Bucket:n.Bucket,Region:n.Region,Key:n.Key,FilePath:n.FilePath||"",state:"waiting",loaded:0,size:0,speed:0,percent:0,hashPercent:0,error:null},m=n.onHashProgress;n.onHashProgress=function(t){e._isRunningTask(p.id)&&(p.hashPercent=t.percent,m&&m(t),u())};var h=n.onProgress;return n.onProgress=function(t){e._isRunningTask(p.id)&&("checking"===p.state&&(p.state="uploading"),p.loaded=t.loaded,p.size=t.total,p.speed=t.speed,p.percent=t.percent,h&&h(t),u())},o.getFileSize(t,n,(function(e,t){e?i(e):(s[l]=p,r.push(p),p.size=t,!a&&u(),f(),d())})),l},e._isRunningTask=function(e){var t=s[e];return!(!t||"checking"!==t.state&&"uploading"!==t.state)},e.getTaskList=function(){return o.map(r,p)},e.cancelTask=function(e){m(e,"canceled")},e.pauseTask=function(e){m(e,"paused")},e.restartTask=function(e){var t=s[e];!t||"paused"!==t.state&&"error"!==t.state||(t.state="waiting",u(),l=Math.min(l,t.index),f())},e.isUploadRunning=function(){return c||l-1?"{Region}.myqcloud.com":"cos.{Region}.myqcloud.com",e.ForcePathStyle||(a="{Bucket}."+a)),a=(a=a.replace(/\{\{AppId\}\}/gi,i).replace(/\{\{Bucket\}\}/gi,n).replace(/\{\{Region\}\}/gi,r).replace(/\{\{.*?\}\}/gi,"")).replace(/\{AppId\}/gi,i).replace(/\{BucketName\}/gi,n).replace(/\{Bucket\}/gi,t).replace(/\{Region\}/gi,r).replace(/\{.*?\}/gi,""),/^[a-zA-Z]+:\/\//.test(a)||(a="https://"+a),"/"===a.slice(-1)&&(a=a.slice(0,-1));var c=a;return e.ForcePathStyle&&(c+="/"+t),c+="/",s&&(c+=o.camSafeUrlEncode(s).replace(/%2F/g,"/")),e.isLocation&&(c=c.replace(/^https?:\/\//,"")),c}var l=function(e){if(!e.Bucket||!e.Region)return"";var t=void 0===e.UseAccelerate?this.options.UseAccelerate:e.UseAccelerate;return(e.Url||c({ForcePathStyle:this.options.ForcePathStyle,protocol:this.options.Protocol,domain:this.options.Domain,bucket:e.Bucket,region:t?"accelerate":e.Region})).replace(/^https?:\/\/([^/]+)(\/.*)?$/,"$1")};function p(e,t){var n=o.clone(e.Headers),i="";o.each(n,(function(e,t){(""===e||["content-type","cache-control"].indexOf(t.toLowerCase())>-1)&&delete n[t],"host"===t.toLowerCase()&&(i=e)}));var a=!1!==e.ForceSignHost;!i&&e.SignHost&&a&&(n.Host=e.SignHost);var r=!1,s=function(e,n){r||(r=!0,n&&n.XCosSecurityToken&&!n.SecurityToken&&((n=o.clone(n)).SecurityToken=n.XCosSecurityToken,delete n.XCosSecurityToken),t&&t(e,n))},c=this,l=e.Bucket||"",p=e.Region||"",u="name/cos:PostObject"!==e.Action&&e.Key?e.Key:"";c.options.ForcePathStyle&&l&&(u=l+"/"+u);var d="/"+u,f={},m=e.Scope;if(!m){var h=e.Action||"",g=e.ResourceKey||e.Key||"";m=e.Scope||[{action:h,bucket:l,region:p,prefix:g}]}var v=o.md5(JSON.stringify(m));c._StsCache=c._StsCache||[],function(){var e,t;for(e=c._StsCache.length-1;e>=0;e--){t=c._StsCache[e];var n=Math.round(o.getSkewTime(c.options.SystemClockOffset)/1e3)+30;if(t.StartTime&&n=t.ExpiredTime)c._StsCache.splice(e,1);else if(!t.ScopeLimit||t.ScopeLimit&&t.ScopeKey===v){f=t;break}}}();var y=function(){var t="";f.StartTime&&e.Expires?t=f.StartTime+";"+(f.StartTime+1*e.Expires):f.StartTime&&f.ExpiredTime&&(t=f.StartTime+";"+f.ExpiredTime);var i={Authorization:o.getAuth({SecretId:f.TmpSecretId,SecretKey:f.TmpSecretKey,Method:e.Method,Pathname:d,Query:e.Query,Headers:n,Expires:e.Expires,SystemClockOffset:c.options.SystemClockOffset,KeyTime:t,ForceSignHost:a}),SecurityToken:f.SecurityToken||f.XCosSecurityToken||"",Token:f.Token||"",ClientIP:f.ClientIP||"",ClientUA:f.ClientUA||"",SignFrom:"client"};s(null,i)},x=function(e){if(e.Authorization){var t=!1,n=e.Authorization;if(n)if(n.indexOf(" ")>-1)t=!1;else if(n.indexOf("q-sign-algorithm=")>-1&&n.indexOf("q-ak=")>-1&&n.indexOf("q-sign-time=")>-1&&n.indexOf("q-key-time=")>-1&&n.indexOf("q-url-param-list=")>-1)t=!0;else try{(n=atob(n)).indexOf("a=")>-1&&n.indexOf("k=")>-1&&n.indexOf("t=")>-1&&n.indexOf("r=")>-1&&n.indexOf("b=")>-1&&(t=!0)}catch(e){}if(!t)return o.error(new Error("getAuthorization callback params format error"))}else{if(!e.TmpSecretId)return o.error(new Error('getAuthorization callback params missing "TmpSecretId"'));if(!e.TmpSecretKey)return o.error(new Error('getAuthorization callback params missing "TmpSecretKey"'));if(!e.SecurityToken&&!e.XCosSecurityToken)return o.error(new Error('getAuthorization callback params missing "SecurityToken"'));if(!e.ExpiredTime)return o.error(new Error('getAuthorization callback params missing "ExpiredTime"'));if(e.ExpiredTime&&10!==e.ExpiredTime.toString().length)return o.error(new Error('getAuthorization callback params "ExpiredTime" should be 10 digits'));if(e.StartTime&&10!==e.StartTime.toString().length)return o.error(new Error('getAuthorization callback params "StartTime" should be 10 StartTime'))}return!1};if(f.ExpiredTime&&f.ExpiredTime-o.getSkewTime(c.options.SystemClockOffset)/1e3>60)y();else if(c.options.getAuthorization)c.options.getAuthorization.call(c,{Bucket:l,Region:p,Method:e.Method,Key:u,Pathname:d,Query:e.Query,Headers:n,Scope:m,SystemClockOffset:c.options.SystemClockOffset,ForceSignHost:a},(function(e){"string"==typeof e&&(e={Authorization:e});var t=x(e);if(t)return s(t);e.Authorization?s(null,e):((f=e||{}).Scope=m,f.ScopeKey=v,c._StsCache.push(f),y())}));else{if(!c.options.getSTS)return function(){var t="";if(c.options.StartTime&&e.Expires){if(10!==c.options.StartTime.toString().length)return s(o.error(new Error('params "StartTime" should be 10 digits')));t=c.options.StartTime+";"+(c.options.StartTime+1*e.Expires)}else if(c.options.StartTime&&c.options.ExpiredTime){if(10!==c.options.StartTime.toString().length)return s(o.error(new Error('params "StartTime" should be 10 digits')));if(10!==c.options.ExpiredTime.toString().length)return s(o.error(new Error('params "ExpiredTime" should be 10 digits')));t=c.options.StartTime+";"+1*c.options.ExpiredTime}var i={Authorization:o.getAuth({SecretId:e.SecretId||c.options.SecretId,SecretKey:e.SecretKey||c.options.SecretKey,Method:e.Method,Pathname:d,Query:e.Query,Headers:n,Expires:e.Expires,KeyTime:t,SystemClockOffset:c.options.SystemClockOffset,ForceSignHost:a}),SecurityToken:c.options.SecurityToken||c.options.XCosSecurityToken,SignFrom:"client"};return s(null,i),i}();c.options.getSTS.call(c,{Bucket:l,Region:p},(function(e){(f=e||{}).Scope=m,f.ScopeKey=v,f.TmpSecretId||(f.TmpSecretId=f.SecretId),f.TmpSecretKey||(f.TmpSecretKey=f.SecretKey);var t=x(f);if(t)return s(t);c._StsCache.push(f),y()}))}return""}function u(e){var t=this,n=!1,i=!1,a=!1,r=e.headers&&(e.headers.date||e.headers.Date)||e.error&&e.error.ServerTime;try{var s=e.error.Code,c=e.error.Message;("RequestTimeTooSkewed"===s||"AccessDenied"===s&&"Request has expired"===c)&&(a=!0)}catch(e){}if(e){if(a&&r){var l=Date.parse(r);this.options.CorrectClockSkew&&Math.abs(o.getSkewTime(this.options.SystemClockOffset)-l)>=3e4&&(this.options.SystemClockOffset=l-Date.now(),n=!0)}else{if(5===Math.floor(e.statusCode/100))return{canRetry:!0,networkError:!1};if("timeout"===e.message)return{canRetry:!0,networkError:t.options.AutoSwitchHost}}if(e.statusCode){var p=Math.floor(e.statusCode/100),u=(null==e?void 0:e.headers)&&(null==e?void 0:e.headers["x-cos-request-id"]);[3,4,5].includes(p)&&!u&&(n=t.options.AutoSwitchHost,i=!0)}else n=!0,i=t.options.AutoSwitchHost}return{canRetry:n,networkError:i}}function d(e){var t=e.requestUrl,n=e.clientCalcSign,i=e.networkError;if(!this.options.AutoSwitchHost)return!1;if(!t)return!1;if(!n)return!1;if(!i)return!1;return/^https?:\/\/[^\/]*\.cos\.[^\/]*\.myqcloud\.com(\/.*)?$/.test(t)&&!/^https?:\/\/[^\/]*\.cos\.accelerate\.myqcloud\.com(\/.*)?$/.test(t)}function f(e,t){var n=this;!e.headers&&(e.headers={}),!e.qs&&(e.qs={}),e.VersionId&&(e.qs.versionId=e.VersionId),e.qs=o.clearKey(e.qs),e.headers&&(e.headers=o.clearKey(e.headers)),e.qs&&(e.qs=o.clearKey(e.qs));var i=o.clone(e.qs);e.action&&(i[e.action]="");var a=e.url||e.Url,r=e.SignHost||l.call(this,{Bucket:e.Bucket,Region:e.Region,Url:a}),s=e.tracker;!function o(a){var c=n.options.SystemClockOffset;e.SwitchHost&&(r=r.replace(/myqcloud.com/,"tencentcos.cn")),s&&s.setParams({signStartTime:(new Date).getTime(),httpRetryTimes:a-1}),p.call(n,{Bucket:e.Bucket||"",Region:e.Region||"",Method:e.method,Key:e.Key,Query:i,Headers:e.headers,SignHost:r,Action:e.Action,ResourceKey:e.ResourceKey,Scope:e.Scope,ForceSignHost:n.options.ForceSignHost},(function(i,r){i?t(i):(s&&s.setParams({signEndTime:(new Date).getTime(),httpStartTime:(new Date).getTime()}),e.AuthData=r,m.call(n,e,(function(i,l){var p=!1,f=!1;if(i){var m=u.call(n,i);p=m.canRetry||c!==n.options.SystemClockOffset,f=m.networkError}if(s&&s.setParams({httpEndTime:(new Date).getTime()}),i&&a<4&&p){e.headers&&(delete e.headers.Authorization,delete e.headers.token,delete e.headers.clientIP,delete e.headers.clientUA,e.headers["x-cos-security-token"]&&delete e.headers["x-cos-security-token"],e.headers["x-ci-security-token"]&&delete e.headers["x-ci-security-token"]);var h=d.call(n,{requestUrl:(null==i?void 0:i.url)||"",clientCalcSign:"client"===(null==r?void 0:r.SignFrom),networkError:f});e.SwitchHost=h,e.headers["x-cos-sdk-retry"]="true",o(a+1)}else t(i,l)})))}))}(1)}function m(e,t){var n=this,a=e.TaskId;if(!a||n._isRunningTask(a)){var r=e.Bucket,s=e.Region,l=e.Key,p=e.method||"GET",u=e.url||e.Url,d=e.body,f=e.json,m=e.rawBody,h=e.dataType,g=n.options.HttpDNSServiceId;n.options.UseAccelerate&&(s="accelerate"),u=u||c({ForcePathStyle:n.options.ForcePathStyle,protocol:n.options.Protocol,domain:n.options.Domain,bucket:r,region:s,object:l}),e.SwitchHost&&(u=u.replace(/myqcloud.com/,"tencentcos.cn"));var v=l?u:"";e.action&&(u=u+"?"+e.action),e.qsStr&&(u=u.indexOf("?")>-1?u+"&"+e.qsStr:u+"?"+e.qsStr);var y={method:p,url:u,headers:e.headers,qs:e.qs,filePath:e.filePath,body:d,json:f,httpDNSServiceId:g,dataType:h},x="x-cos-security-token";o.isCIHost(u)&&(x="x-ci-security-token"),y.headers.Authorization=e.AuthData.Authorization,e.AuthData.Token&&(y.headers.token=e.AuthData.Token),e.AuthData.ClientIP&&(y.headers.clientIP=e.AuthData.ClientIP),e.AuthData.ClientUA&&(y.headers.clientUA=e.AuthData.ClientUA),e.AuthData.SecurityToken&&(y.headers[x]=e.AuthData.SecurityToken),y.headers&&(y.headers=o.clearKey(y.headers)),y=o.clearKey(y),e.onProgress&&"function"==typeof e.onProgress&&(y.onProgress=function(t){if(!a||n._isRunningTask(a)){var i=t?t.loaded:0;e.onProgress({loaded:i,total:t.total})}}),this.options.Timeout&&(y.timeout=this.options.Timeout),n.options.ForcePathStyle&&(y.pathStyle=n.options.ForcePathStyle),n.emit("before-send",y);var k,b=y.url.includes("accelerate."),C=y.qs?Object.keys(y.qs).map((function(e){return"".concat(e,"=").concat(y.qs[e])})).join("&"):"",S=C?y.url+"?"+C:y.url;if(e.tracker)e.tracker.setParams({url:S,httpMethod:y.method,accelerate:b,httpSize:(null===(k=y.body)||void 0===k?void 0:k.size)||0}),e.tracker.parent&&!e.tracker.parent.params.url&&e.tracker.parent.setParams({url:v,accelerate:b});var w=i(y,(function(e,i,r){if("abort"!==e){var s,c=function(e,r){if(a&&n.off("inner-kill-task",T),!s){s=!0;var c={};i&&i.statusCode&&(c.statusCode=i.statusCode),i&&i.headers&&(c.headers=i.headers),e?(y.url&&(c.url=y.url),y.method&&(c.method=y.method),e=o.extend(e||{},c),t(e,null)):(r=o.extend(r||{},c),t(null,r)),w=null}};if(e)c({error:e});else{var l=i.statusCode,p=2===Math.floor(l/100);if(m){if(p)return c(null,{body:r});if(r instanceof ArrayBuffer){var u=o.arrayBufferToString(r),d=o.parseResBody(u);return c({error:d.Error||d})}}var f=o.parseResBody(r);p?f.Error?c({error:f.Error}):c(null,f):c({error:f.Error||f})}}})),T=function e(t){t.TaskId===a&&(w&&w.abort&&w.abort(),n.off("inner-kill-task",e))};a&&n.on("inner-kill-task",T)}}var h={getService:function(e,t){"function"==typeof e&&(t=e,e={});var n="https:",i=this.options.ServiceDomain,a=e.Region;i?(i=i.replace(/\{\{Region\}\}/gi,a||"").replace(/\{\{.*?\}\}/gi,""),/^[a-zA-Z]+:\/\//.test(i)||(i=n+"//"+i),"/"===i.slice(-1)&&(i=i.slice(0,-1))):i=a?n+"//cos."+a+".myqcloud.com":n+"//service.cos.myqcloud.com";i.replace(/^https?:\/\/([^/]+)(\/.*)?$/,"$1"),f.call(this,{Action:"name/cos:GetService",url:i,method:"GET",headers:e.Headers,tracker:e.tracker},(function(e,n){if(e)return t(e);var i=n&&n.ListAllMyBucketsResult&&n.ListAllMyBucketsResult.Buckets&&n.ListAllMyBucketsResult.Buckets.Bucket||[];i=o.isArray(i)?i:[i];var a=n&&n.ListAllMyBucketsResult&&n.ListAllMyBucketsResult.Owner||{};t(null,{Buckets:i,Owner:a,statusCode:n.statusCode,headers:n.headers})}))},putBucket:function(e,t){var n=this,i="";if(e.BucketAZConfig){var a={BucketAZConfig:e.BucketAZConfig};i=o.json2xml({CreateBucketConfiguration:a})}f.call(this,{Action:"name/cos:PutBucket",method:"PUT",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,body:i,tracker:e.tracker},(function(i,o){if(i)return t(i);var a=c({protocol:n.options.Protocol,domain:n.options.Domain,bucket:e.Bucket,region:e.Region,isLocation:!0});t(null,{Location:a,statusCode:o.statusCode,headers:o.headers})}))},headBucket:function(e,t){f.call(this,{Action:"name/cos:HeadBucket",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,method:"HEAD",tracker:e.tracker},(function(e,n){t(e,n)}))},getBucket:function(e,t){var n={};n.prefix=e.Prefix||"",n.delimiter=e.Delimiter,n.marker=e.Marker,n["max-keys"]=e.MaxKeys,n["encoding-type"]=e.EncodingType,f.call(this,{Action:"name/cos:GetBucket",ResourceKey:n.prefix,method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,qs:n,tracker:e.tracker},(function(e,n){if(e)return t(e);var i=n.ListBucketResult||{},a=i.Contents||[],r=i.CommonPrefixes||[];a=o.isArray(a)?a:[a],r=o.isArray(r)?r:[r];var s=o.clone(i);o.extend(s,{Contents:a,CommonPrefixes:r,statusCode:n.statusCode,headers:n.headers}),t(null,s)}))},deleteBucket:function(e,t){f.call(this,{Action:"name/cos:DeleteBucket",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,method:"DELETE",tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},putBucketAcl:function(e,t){var n=e.Headers,i="";if(e.AccessControlPolicy){var a=o.clone(e.AccessControlPolicy||{}),r=a.Grants||a.Grant;r=o.isArray(r)?r:[r],delete a.Grant,delete a.Grants,a.AccessControlList={Grant:r},i=o.json2xml({AccessControlPolicy:a}),n["Content-Type"]="application/xml",n["Content-MD5"]=o.binaryBase64(o.md5(i))}o.each(n,(function(e,t){0===t.indexOf("x-cos-grant-")&&(n[t]=s(n[t]))})),f.call(this,{Action:"name/cos:PutBucketACL",method:"PUT",Bucket:e.Bucket,Region:e.Region,headers:n,action:"acl",body:i,tracker:e.tracker},(function(e,n){if(e)return t(e);t(null,{statusCode:n.statusCode,headers:n.headers})}))},getBucketAcl:function(e,t){f.call(this,{Action:"name/cos:GetBucketACL",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"acl",tracker:e.tracker},(function(e,n){if(e)return t(e);var i=n.AccessControlPolicy||{},a=i.Owner||{},s=i.AccessControlList.Grant||[];s=o.isArray(s)?s:[s];var c=r(i);n.headers&&n.headers["x-cos-acl"]&&(c.ACL=n.headers["x-cos-acl"]),c=o.extend(c,{Owner:a,Grants:s,statusCode:n.statusCode,headers:n.headers}),t(null,c)}))},putBucketCors:function(e,t){var n=(e.CORSConfiguration||{}).CORSRules||e.CORSRules||[];n=o.clone(o.isArray(n)?n:[n]),o.each(n,(function(e){o.each(["AllowedOrigin","AllowedHeader","AllowedMethod","ExposeHeader"],(function(t){var n=t+"s",i=e[n]||e[t]||[];delete e[n],e[t]=o.isArray(i)?i:[i]}))}));var i={CORSRule:n};e.ResponseVary&&(i.ResponseVary=e.ResponseVary);var a=o.json2xml({CORSConfiguration:i}),r=e.Headers;r["Content-Type"]="application/xml",r["Content-MD5"]=o.binaryBase64(o.md5(a)),f.call(this,{Action:"name/cos:PutBucketCORS",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:a,action:"cors",headers:r,tracker:e.tracker},(function(e,n){if(e)return t(e);t(null,{statusCode:n.statusCode,headers:n.headers})}))},getBucketCors:function(e,t){f.call(this,{Action:"name/cos:GetBucketCORS",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"cors",tracker:e.tracker},(function(e,n){if(e)if(404===e.statusCode&&e.error&&"NoSuchCORSConfiguration"===e.error.Code){var i={CORSRules:[],statusCode:e.statusCode};e.headers&&(i.headers=e.headers),t(null,i)}else t(e);else{var a=n.CORSConfiguration||{},r=a.CORSRules||a.CORSRule||[];r=o.clone(o.isArray(r)?r:[r]);var s=a.ResponseVary;o.each(r,(function(e){o.each(["AllowedOrigin","AllowedHeader","AllowedMethod","ExposeHeader"],(function(t){var n=t+"s",i=e[n]||e[t]||[];delete e[t],e[n]=o.isArray(i)?i:[i]}))})),t(null,{CORSRules:r,ResponseVary:s,statusCode:n.statusCode,headers:n.headers})}}))},deleteBucketCors:function(e,t){f.call(this,{Action:"name/cos:DeleteBucketCORS",method:"DELETE",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"cors",tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode||e.statusCode,headers:n.headers})}))},getBucketLocation:function(e,t){f.call(this,{Action:"name/cos:GetBucketLocation",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"location",tracker:e.tracker},(function(e,n){if(e)return t(e);t(null,n)}))},getBucketPolicy:function(e,t){f.call(this,{Action:"name/cos:GetBucketPolicy",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"policy",rawBody:!0,tracker:e.tracker},(function(e,n){if(e)return e.statusCode&&403===e.statusCode?t({ErrorStatus:"Access Denied"}):e.statusCode&&405===e.statusCode?t({ErrorStatus:"Method Not Allowed"}):e.statusCode&&404===e.statusCode?t({ErrorStatus:"Policy Not Found"}):t(e);var i={};try{i=JSON.parse(n.body)}catch(e){}t(null,{Policy:i,statusCode:n.statusCode,headers:n.headers})}))},putBucketPolicy:function(e,t){var n=e.Policy,i=n;try{"string"==typeof n?n=JSON.parse(i):i=JSON.stringify(n)}catch(e){t({error:"Policy format error"})}var a=e.Headers;a["Content-Type"]="application/json",a["Content-MD5"]=o.binaryBase64(o.md5(i)),f.call(this,{Action:"name/cos:PutBucketPolicy",method:"PUT",Bucket:e.Bucket,Region:e.Region,action:"policy",body:i,headers:a,json:!0,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},deleteBucketPolicy:function(e,t){f.call(this,{Action:"name/cos:DeleteBucketPolicy",method:"DELETE",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"policy",tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode||e.statusCode,headers:n.headers})}))},putBucketTagging:function(e,t){var n=e.Tagging||{},i=n.TagSet||n.Tags||e.Tags||[];i=o.clone(o.isArray(i)?i:[i]);var a=o.json2xml({Tagging:{TagSet:{Tag:i}}}),r=e.Headers;r["Content-Type"]="application/xml",r["Content-MD5"]=o.binaryBase64(o.md5(a)),f.call(this,{Action:"name/cos:PutBucketTagging",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:a,action:"tagging",headers:r,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},getBucketTagging:function(e,t){f.call(this,{Action:"name/cos:GetBucketTagging",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"tagging",tracker:e.tracker},(function(e,n){if(e)if(404!==e.statusCode||!e.error||"Not Found"!==e.error&&"NoSuchTagSet"!==e.error.Code)t(e);else{var i={Tags:[],statusCode:e.statusCode};e.headers&&(i.headers=e.headers),t(null,i)}else{var a=[];try{a=n.Tagging.TagSet.Tag||[]}catch(e){}a=o.clone(o.isArray(a)?a:[a]),t(null,{Tags:a,statusCode:n.statusCode,headers:n.headers})}}))},deleteBucketTagging:function(e,t){f.call(this,{Action:"name/cos:DeleteBucketTagging",method:"DELETE",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"tagging",tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},putBucketLifecycle:function(e,t){var n=(e.LifecycleConfiguration||{}).Rules||e.Rules||[];n=o.clone(n);var i=o.json2xml({LifecycleConfiguration:{Rule:n}}),a=e.Headers;a["Content-Type"]="application/xml",a["Content-MD5"]=o.binaryBase64(o.md5(i)),f.call(this,{Action:"name/cos:PutBucketLifecycle",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:i,action:"lifecycle",headers:a,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},getBucketLifecycle:function(e,t){f.call(this,{Action:"name/cos:GetBucketLifecycle",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"lifecycle",tracker:e.tracker},(function(e,n){if(e)if(404===e.statusCode&&e.error&&"NoSuchLifecycleConfiguration"===e.error.Code){var i={Rules:[],statusCode:e.statusCode};e.headers&&(i.headers=e.headers),t(null,i)}else t(e);else{var a=[];try{a=n.LifecycleConfiguration.Rule||[]}catch(e){}a=o.clone(o.isArray(a)?a:[a]),t(null,{Rules:a,statusCode:n.statusCode,headers:n.headers})}}))},deleteBucketLifecycle:function(e,t){f.call(this,{Action:"name/cos:DeleteBucketLifecycle",method:"DELETE",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"lifecycle",tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},putBucketVersioning:function(e,t){if(e.VersioningConfiguration){var n=e.VersioningConfiguration||{},i=o.json2xml({VersioningConfiguration:n}),a=e.Headers;a["Content-Type"]="application/xml",a["Content-MD5"]=o.binaryBase64(o.md5(i)),f.call(this,{Action:"name/cos:PutBucketVersioning",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:i,action:"versioning",headers:a,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))}else t({error:"missing param VersioningConfiguration"})},getBucketVersioning:function(e,t){f.call(this,{Action:"name/cos:GetBucketVersioning",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"versioning",tracker:e.tracker},(function(e,n){e||!n.VersioningConfiguration&&(n.VersioningConfiguration={}),t(e,n)}))},putBucketReplication:function(e,t){var n=o.clone(e.ReplicationConfiguration),i=o.json2xml({ReplicationConfiguration:n});i=(i=i.replace(/<(\/?)Rules>/gi,"<$1Rule>")).replace(/<(\/?)Tags>/gi,"<$1Tag>");var a=e.Headers;a["Content-Type"]="application/xml",a["Content-MD5"]=o.binaryBase64(o.md5(i)),f.call(this,{Action:"name/cos:PutBucketReplication",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:i,action:"replication",headers:a,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},getBucketReplication:function(e,t){f.call(this,{Action:"name/cos:GetBucketReplication",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"replication",tracker:e.tracker},(function(e,n){if(e)if(404!==e.statusCode||!e.error||"Not Found"!==e.error&&"ReplicationConfigurationnotFoundError"!==e.error.Code)t(e);else{var i={ReplicationConfiguration:{Rules:[]},statusCode:e.statusCode};e.headers&&(i.headers=e.headers),t(null,i)}else e||!n.ReplicationConfiguration&&(n.ReplicationConfiguration={}),n.ReplicationConfiguration.Rule&&(n.ReplicationConfiguration.Rules=n.ReplicationConfiguration.Rule,delete n.ReplicationConfiguration.Rule),t(e,n)}))},deleteBucketReplication:function(e,t){f.call(this,{Action:"name/cos:DeleteBucketReplication",method:"DELETE",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"replication",tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},putBucketWebsite:function(e,t){if(e.WebsiteConfiguration){var n=o.clone(e.WebsiteConfiguration||{}),i=n.RoutingRules||n.RoutingRule||[];i=o.isArray(i)?i:[i],delete n.RoutingRule,delete n.RoutingRules,i.length&&(n.RoutingRules={RoutingRule:i});var a=o.json2xml({WebsiteConfiguration:n}),r=e.Headers;r["Content-Type"]="application/xml",r["Content-MD5"]=o.binaryBase64(o.md5(a)),f.call(this,{Action:"name/cos:PutBucketWebsite",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:a,action:"website",headers:r,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))}else t({error:"missing param WebsiteConfiguration"})},getBucketWebsite:function(e,t){f.call(this,{Action:"name/cos:GetBucketWebsite",method:"GET",Bucket:e.Bucket,Region:e.Region,Key:e.Key,headers:e.Headers,action:"website",tracker:e.tracker},(function(e,n){if(e)if(404===e.statusCode&&"NoSuchWebsiteConfiguration"===e.error.Code){var i={WebsiteConfiguration:{},statusCode:e.statusCode};e.headers&&(i.headers=e.headers),t(null,i)}else t(e);else{var a=n.WebsiteConfiguration||{};if(a.RoutingRules){var r=o.clone(a.RoutingRules.RoutingRule||[]);r=o.makeArray(r),a.RoutingRules=r}t(null,{WebsiteConfiguration:a,statusCode:n.statusCode,headers:n.headers})}}))},deleteBucketWebsite:function(e,t){f.call(this,{Action:"name/cos:DeleteBucketWebsite",method:"DELETE",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"website",tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},putBucketReferer:function(e,t){if(e.RefererConfiguration){var n=o.clone(e.RefererConfiguration||{}),i=n.DomainList||{},a=i.Domains||i.Domain||[];(a=o.isArray(a)?a:[a]).length&&(n.DomainList={Domain:a});var r=o.json2xml({RefererConfiguration:n}),s=e.Headers;s["Content-Type"]="application/xml",s["Content-MD5"]=o.binaryBase64(o.md5(r)),f.call(this,{Action:"name/cos:PutBucketReferer",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:r,action:"referer",headers:s,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))}else t({error:"missing param RefererConfiguration"})},getBucketReferer:function(e,t){f.call(this,{Action:"name/cos:GetBucketReferer",method:"GET",Bucket:e.Bucket,Region:e.Region,Key:e.Key,headers:e.Headers,action:"referer",tracker:e.tracker},(function(e,n){if(e)if(404===e.statusCode&&"NoSuchRefererConfiguration"===e.error.Code){var i={WebsiteConfiguration:{},statusCode:e.statusCode};e.headers&&(i.headers=e.headers),t(null,i)}else t(e);else{var a=n.RefererConfiguration||{};if(a.DomainList){var r=o.makeArray(a.DomainList.Domain||[]);a.DomainList={Domains:r}}t(null,{RefererConfiguration:a,statusCode:n.statusCode,headers:n.headers})}}))},putBucketDomain:function(e,t){var n=(e.DomainConfiguration||{}).DomainRule||e.DomainRule||[];n=o.clone(n);var i=o.json2xml({DomainConfiguration:{DomainRule:n}}),a=e.Headers;a["Content-Type"]="application/xml",a["Content-MD5"]=o.binaryBase64(o.md5(i)),f.call(this,{Action:"name/cos:PutBucketDomain",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:i,action:"domain",headers:a,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},getBucketDomain:function(e,t){f.call(this,{Action:"name/cos:GetBucketDomain",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"domain",tracker:e.tracker},(function(e,n){if(e)return t(e);var i=[];try{i=n.DomainConfiguration.DomainRule||[]}catch(e){}i=o.clone(o.isArray(i)?i:[i]),t(null,{DomainRule:i,statusCode:n.statusCode,headers:n.headers})}))},deleteBucketDomain:function(e,t){f.call(this,{Action:"name/cos:DeleteBucketDomain",method:"DELETE",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"domain",tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},putBucketOrigin:function(e,t){var n=(e.OriginConfiguration||{}).OriginRule||e.OriginRule||[];n=o.clone(n);var i=o.json2xml({OriginConfiguration:{OriginRule:n}}),a=e.Headers;a["Content-Type"]="application/xml",a["Content-MD5"]=o.binaryBase64(o.md5(i)),f.call(this,{Action:"name/cos:PutBucketOrigin",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:i,action:"origin",headers:a,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},getBucketOrigin:function(e,t){f.call(this,{Action:"name/cos:GetBucketOrigin",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"origin",tracker:e.tracker},(function(e,n){if(e)return t(e);var i=[];try{i=n.OriginConfiguration.OriginRule||[]}catch(e){}i=o.clone(o.isArray(i)?i:[i]),t(null,{OriginRule:i,statusCode:n.statusCode,headers:n.headers})}))},deleteBucketOrigin:function(e,t){f.call(this,{Action:"name/cos:DeleteBucketOrigin",method:"DELETE",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"origin",tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},putBucketLogging:function(e,t){var n=o.json2xml({BucketLoggingStatus:e.BucketLoggingStatus||""}),i=e.Headers;i["Content-Type"]="application/xml",i["Content-MD5"]=o.binaryBase64(o.md5(n)),f.call(this,{Action:"name/cos:PutBucketLogging",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:n,action:"logging",headers:i,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},getBucketLogging:function(e,t){f.call(this,{Action:"name/cos:GetBucketLogging",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"logging",tracker:e.tracker},(function(e,n){if(e)return t(e);delete n.BucketLoggingStatus._xmlns,t(null,{BucketLoggingStatus:n.BucketLoggingStatus,statusCode:n.statusCode,headers:n.headers})}))},putBucketInventory:function(e,t){var n=o.clone(e.InventoryConfiguration);if(n.OptionalFields){var i=n.OptionalFields||[];n.OptionalFields={Field:i}}if(n.Destination&&n.Destination.COSBucketDestination&&n.Destination.COSBucketDestination.Encryption){var a=n.Destination.COSBucketDestination.Encryption;Object.keys(a).indexOf("SSECOS")>-1&&(a["SSE-COS"]=a.SSECOS,delete a.SSECOS)}var r=o.json2xml({InventoryConfiguration:n}),s=e.Headers;s["Content-Type"]="application/xml",s["Content-MD5"]=o.binaryBase64(o.md5(r)),f.call(this,{Action:"name/cos:PutBucketInventory",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:r,action:"inventory",qs:{id:e.Id},headers:s,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},getBucketInventory:function(e,t){f.call(this,{Action:"name/cos:GetBucketInventory",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"inventory",qs:{id:e.Id},tracker:e.tracker},(function(e,n){if(e)return t(e);var i=n.InventoryConfiguration;if(i&&i.OptionalFields&&i.OptionalFields.Field){var a=i.OptionalFields.Field;o.isArray(a)||(a=[a]),i.OptionalFields=a}if(i.Destination&&i.Destination.COSBucketDestination&&i.Destination.COSBucketDestination.Encryption){var r=i.Destination.COSBucketDestination.Encryption;Object.keys(r).indexOf("SSE-COS")>-1&&(r.SSECOS=r["SSE-COS"],delete r["SSE-COS"])}t(null,{InventoryConfiguration:i,statusCode:n.statusCode,headers:n.headers})}))},listBucketInventory:function(e,t){f.call(this,{Action:"name/cos:ListBucketInventory",method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"inventory",qs:{"continuation-token":e.ContinuationToken},tracker:e.tracker},(function(e,n){if(e)return t(e);var i=n.ListInventoryConfigurationResult,a=i.InventoryConfiguration||[];a=o.isArray(a)?a:[a],delete i.InventoryConfiguration,o.each(a,(function(e){if(e&&e.OptionalFields&&e.OptionalFields.Field){var t=e.OptionalFields.Field;o.isArray(t)||(t=[t]),e.OptionalFields=t}if(e.Destination&&e.Destination.COSBucketDestination&&e.Destination.COSBucketDestination.Encryption){var n=e.Destination.COSBucketDestination.Encryption;Object.keys(n).indexOf("SSE-COS")>-1&&(n.SSECOS=n["SSE-COS"],delete n["SSE-COS"])}})),i.InventoryConfigurations=a,o.extend(i,{statusCode:n.statusCode,headers:n.headers}),t(null,i)}))},deleteBucketInventory:function(e,t){f.call(this,{Action:"name/cos:DeleteBucketInventory",method:"DELETE",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"inventory",qs:{id:e.Id},tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},putBucketAccelerate:function(e,t){if(e.AccelerateConfiguration){var n={AccelerateConfiguration:e.AccelerateConfiguration||{}},i=o.json2xml(n),a={"Content-Type":"application/xml"};a["Content-MD5"]=o.binaryBase64(o.md5(i)),f.call(this,{Interface:"putBucketAccelerate",Action:"name/cos:PutBucketAccelerate",method:"PUT",Bucket:e.Bucket,Region:e.Region,body:i,action:"accelerate",headers:a,tracker:e.tracker},(function(e,n){if(e)return t(e);t(null,{statusCode:n.statusCode,headers:n.headers})}))}else t({error:"missing param AccelerateConfiguration"})},getBucketAccelerate:function(e,t){f.call(this,{Interface:"getBucketAccelerate",Action:"name/cos:GetBucketAccelerate",method:"GET",Bucket:e.Bucket,Region:e.Region,action:"accelerate",tracker:e.tracker},(function(e,n){e||!n.AccelerateConfiguration&&(n.AccelerateConfiguration={}),t(e,n)}))},getObject:function(e,t){if(this.options.ObjectKeySimplifyCheck&&"/"===o.simplifyPath(e.Key))return void t(o.error(new Error("The Getobject Key is illegal")));var n=e.Query||{},i=e.QueryString||"",a=e.tracker;a&&a.setParams({signStartTime:(new Date).getTime()}),n["response-content-type"]=e.ResponseContentType,n["response-content-language"]=e.ResponseContentLanguage,n["response-expires"]=e.ResponseExpires,n["response-cache-control"]=e.ResponseCacheControl,n["response-content-disposition"]=e.ResponseContentDisposition,n["response-content-encoding"]=e.ResponseContentEncoding,f.call(this,{Action:"name/cos:GetObject",method:"GET",Bucket:e.Bucket,Region:e.Region,Key:e.Key,VersionId:e.VersionId,headers:e.Headers,qs:n,qsStr:i,rawBody:!0,dataType:e.DataType,tracker:a},(function(n,i){if(n){var a=n.statusCode;return e.Headers["If-Modified-Since"]&&a&&304===a?t(null,{NotModified:!0}):t(n)}t(null,{Body:i.body,ETag:o.attr(i.headers,"etag",""),statusCode:i.statusCode,headers:i.headers})}))},headObject:function(e,t){f.call(this,{Action:"name/cos:HeadObject",method:"HEAD",Bucket:e.Bucket,Region:e.Region,Key:e.Key,VersionId:e.VersionId,headers:e.Headers,tracker:e.tracker},(function(n,i){if(n){var a=n.statusCode;return e.Headers["If-Modified-Since"]&&a&&304===a?t(null,{NotModified:!0,statusCode:a}):t(n)}i.ETag=o.attr(i.headers,"etag",""),t(null,i)}))},listObjectVersions:function(e,t){var n={};n.prefix=e.Prefix||"",n.delimiter=e.Delimiter,n["key-marker"]=e.KeyMarker,n["version-id-marker"]=e.VersionIdMarker,n["max-keys"]=e.MaxKeys,n["encoding-type"]=e.EncodingType,f.call(this,{Action:"name/cos:GetBucketObjectVersions",ResourceKey:n.prefix,method:"GET",Bucket:e.Bucket,Region:e.Region,headers:e.Headers,qs:n,action:"versions",tracker:e.tracker},(function(e,n){if(e)return t(e);var i=n.ListVersionsResult||{},a=i.DeleteMarker||[];a=o.isArray(a)?a:[a];var r=i.Version||[];r=o.isArray(r)?r:[r];var s=o.clone(i);delete s.DeleteMarker,delete s.Version,o.extend(s,{DeleteMarkers:a,Versions:r,statusCode:n.statusCode,headers:n.headers}),t(null,s)}))},putObject:function(e,t){var n=this,i=e.ContentLength,r=o.throttleOnProgress.call(n,i,e.onProgress),s=e.Headers;s["Cache-Control"]||s["cache-control"]||(s["Cache-Control"]=""),s["Content-Type"]||s["content-type"]||(s["Content-Type"]=a.getType(e.Key)||"application/octet-stream");var l=e.UploadAddMetaMd5||n.options.UploadAddMetaMd5||n.options.UploadCheckContentMd5,p=e.tracker;l&&p&&p.setParams({md5StartTime:(new Date).getTime()}),o.getBodyMd5(l,e.Body,(function(a){a&&(p&&p.setParams({md5EndTime:(new Date).getTime()}),n.options.UploadCheckContentMd5&&(s["Content-MD5"]=o.binaryBase64(a)),(e.UploadAddMetaMd5||n.options.UploadAddMetaMd5)&&(s["x-cos-meta-md5"]=a)),void 0!==e.ContentLength&&(s["Content-Length"]=e.ContentLength),r(null,!0),f.call(n,{Action:"name/cos:PutObject",TaskId:e.TaskId,method:"PUT",Bucket:e.Bucket,Region:e.Region,Key:e.Key,headers:e.Headers,qs:e.Query,body:e.Body,onProgress:r,tracker:p},(function(a,s){if(a)return r(null,!0),t(a);r({loaded:i,total:i},!0);var l=c({ForcePathStyle:n.options.ForcePathStyle,protocol:n.options.Protocol,domain:n.options.Domain,bucket:e.Bucket,region:n.options.UseAccelerate?"accelerate":e.Region,object:e.Key});l=l.substr(l.indexOf("://")+3),s.Location=l,s.ETag=o.attr(s.headers,"etag",""),t(null,s)}))}))},postObject:function(e,t){var n=this,i={},a=e.FilePath;if(a){for(var r in i["Cache-Control"]=e.CacheControl,i["Content-Disposition"]=e.ContentDisposition,i["Content-Encoding"]=e.ContentEncoding,i["Content-MD5"]=e.ContentMD5,i["Content-Length"]=e.ContentLength,i["Content-Type"]=e.ContentType,i.Expect=e.Expect,i.Expires=e.Expires,i["x-cos-acl"]=e.ACL,i["x-cos-grant-read"]=e.GrantRead,i["x-cos-grant-write"]=e.GrantWrite,i["x-cos-grant-full-control"]=e.GrantFullControl,i["x-cos-storage-class"]=e.StorageClass,i["x-cos-mime-limit"]=e.MimeLimit,i["x-cos-traffic-limit"]=e.TrafficLimit,i["x-cos-forbid-overwrite"]=e.ForbidOverwrite,i["x-cos-server-side-encryption-customer-algorithm"]=e.SSECustomerAlgorithm,i["x-cos-server-side-encryption-customer-key"]=e.SSECustomerKey,i["x-cos-server-side-encryption-customer-key-MD5"]=e.SSECustomerKeyMD5,i["x-cos-server-side-encryption"]=e.ServerSideEncryption,i["x-cos-server-side-encryption-cos-kms-key-id"]=e.SSEKMSKeyId,i["x-cos-server-side-encryption-context"]=e.SSEContext,delete i["Content-Length"],delete i["content-length"],e)r.indexOf("x-cos-meta-")>-1&&(i[r]=e[r]);var s=o.throttleOnProgress.call(n,i["Content-Length"],e.onProgress);f.call(this,{Action:"name/cos:PostObject",method:"POST",Bucket:e.Bucket,Region:e.Region,Key:e.Key,headers:i,qs:e.Query,filePath:a,TaskId:e.TaskId,onProgress:s,tracker:e.tracker},(function(i,o){if(s(null,!0),i)return t(i);if(o&&o.headers){var r=o.headers,l=r.etag||r.Etag||r.ETag||"",p=a.substr(a.lastIndexOf("/")+1),u=c({ForcePathStyle:n.options.ForcePathStyle,protocol:n.options.Protocol,domain:n.options.Domain,bucket:e.Bucket,region:e.Region,object:e.Key.replace(/\$\{filename\}/g,p),isLocation:!0});return t(null,{Location:u,statusCode:o.statusCode,headers:r,ETag:l})}t(null,o)}))}else t({error:"missing param FilePath"})},deleteObject:function(e,t){f.call(this,{Action:"name/cos:DeleteObject",method:"DELETE",Bucket:e.Bucket,Region:e.Region,Key:e.Key,headers:e.Headers,VersionId:e.VersionId,tracker:e.tracker},(function(e,n){if(e){var i=e.statusCode;return i&&204===i?t(null,{statusCode:i}):i&&404===i?t(null,{BucketNotFound:!0,statusCode:i}):t(e)}t(null,{statusCode:n.statusCode,headers:n.headers})}))},getObjectAcl:function(e,t){var n={};e.VersionId&&(n.versionId=e.VersionId),f.call(this,{Action:"name/cos:GetObjectACL",method:"GET",Bucket:e.Bucket,Region:e.Region,Key:e.Key,headers:e.Headers,qs:n,action:"acl",tracker:e.tracker},(function(e,n){if(e)return t(e);var i=n.AccessControlPolicy||{},a=i.Owner||{},s=i.AccessControlList&&i.AccessControlList.Grant||[];s=o.isArray(s)?s:[s];var c=r(i);n.headers&&n.headers["x-cos-acl"]&&(c.ACL=n.headers["x-cos-acl"]),c=o.extend(c,{Owner:a,Grants:s,statusCode:n.statusCode,headers:n.headers}),t(null,c)}))},putObjectAcl:function(e,t){var n=e.Headers,i="";if(e.AccessControlPolicy){var a=o.clone(e.AccessControlPolicy||{}),r=a.Grants||a.Grant;r=o.isArray(r)?r:[r],delete a.Grant,delete a.Grants,a.AccessControlList={Grant:r},i=o.json2xml({AccessControlPolicy:a}),n["Content-Type"]="application/xml",n["Content-MD5"]=o.binaryBase64(o.md5(i))}o.each(n,(function(e,t){0===t.indexOf("x-cos-grant-")&&(n[t]=s(n[t]))})),f.call(this,{Action:"name/cos:PutObjectACL",method:"PUT",Bucket:e.Bucket,Region:e.Region,Key:e.Key,action:"acl",headers:n,body:i,tracker:e.tracker},(function(e,n){if(e)return t(e);t(null,{statusCode:n.statusCode,headers:n.headers})}))},optionsObject:function(e,t){var n=e.Headers;n.Origin=e.Origin,n["Access-Control-Request-Method"]=e.AccessControlRequestMethod,n["Access-Control-Request-Headers"]=e.AccessControlRequestHeaders,f.call(this,{Action:"name/cos:OptionsObject",method:"OPTIONS",Bucket:e.Bucket,Region:e.Region,Key:e.Key,headers:n,tracker:e.tracker},(function(e,n){if(e)return e.statusCode&&403===e.statusCode?t(null,{OptionsForbidden:!0,statusCode:e.statusCode}):t(e);var i=n.headers||{};t(null,{AccessControlAllowOrigin:i["access-control-allow-origin"],AccessControlAllowMethods:i["access-control-allow-methods"],AccessControlAllowHeaders:i["access-control-allow-headers"],AccessControlExposeHeaders:i["access-control-expose-headers"],AccessControlMaxAge:i["access-control-max-age"],statusCode:n.statusCode,headers:n.headers})}))},putObjectCopy:function(e,t){var n=e.Headers;!n["Cache-Control"]&&n["cache-control"]&&(n["Cache-Control"]="");var i=e.CopySource||"",a=o.getSourceParams.call(this,i);if(a){var r=a.Bucket,s=a.Region,c=decodeURIComponent(a.Key);f.call(this,{Scope:[{action:"name/cos:GetObject",bucket:r,region:s,prefix:c},{action:"name/cos:PutObject",bucket:e.Bucket,region:e.Region,prefix:e.Key}],method:"PUT",Bucket:e.Bucket,Region:e.Region,Key:e.Key,VersionId:e.VersionId,headers:e.Headers,tracker:e.tracker},(function(e,n){if(e)return t(e);var i=o.clone(n.CopyObjectResult||{});o.extend(i,{statusCode:n.statusCode,headers:n.headers}),t(null,i)}))}else t({error:"CopySource format error"})},deleteMultipleObject:function(e,t){var n=e.Objects||[],i=e.Quiet;n=o.isArray(n)?n:[n];var a=o.json2xml({Delete:{Object:n,Quiet:i||!1}}),r=e.Headers;r["Content-Type"]="application/xml",r["Content-MD5"]=o.binaryBase64(o.md5(a));var s=o.map(n,(function(t){return{action:"name/cos:DeleteObject",bucket:e.Bucket,region:e.Region,prefix:t.Key}}));f.call(this,{Scope:s,method:"POST",Bucket:e.Bucket,Region:e.Region,body:a,action:"delete",headers:r,tracker:e.tracker},(function(e,n){if(e)return t(e);var i=n.DeleteResult||{},a=i.Deleted||[],r=i.Error||[];a=o.isArray(a)?a:[a],r=o.isArray(r)?r:[r];var s=o.clone(i);o.extend(s,{Error:r,Deleted:a,statusCode:n.statusCode,headers:n.headers}),t(null,s)}))},restoreObject:function(e,t){var n=e.Headers;if(e.RestoreRequest){var i=e.RestoreRequest||{},a=o.json2xml({RestoreRequest:i});n["Content-Type"]="application/xml",n["Content-MD5"]=o.binaryBase64(o.md5(a)),f.call(this,{Action:"name/cos:RestoreObject",method:"POST",Bucket:e.Bucket,Region:e.Region,Key:e.Key,VersionId:e.VersionId,body:a,action:"restore",headers:n,tracker:e.tracker},(function(e,n){t(e,n)}))}else t({error:"missing param RestoreRequest"})},putObjectTagging:function(e,t){var n=e.Tagging||{},i=n.TagSet||n.Tags||e.Tags||[];i=o.clone(o.isArray(i)?i:[i]);var a=o.json2xml({Tagging:{TagSet:{Tag:i}}}),r=e.Headers;r["Content-Type"]="application/xml",r["Content-MD5"]=o.binaryBase64(o.md5(a)),f.call(this,{Interface:"putObjectTagging",Action:"name/cos:PutObjectTagging",method:"PUT",Bucket:e.Bucket,Key:e.Key,Region:e.Region,body:a,action:"tagging",headers:r,VersionId:e.VersionId,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},getObjectTagging:function(e,t){f.call(this,{Interface:"getObjectTagging",Action:"name/cos:GetObjectTagging",method:"GET",Key:e.Key,Bucket:e.Bucket,Region:e.Region,headers:e.Headers,action:"tagging",VersionId:e.VersionId,tracker:e.tracker},(function(e,n){if(e)if(404!==e.statusCode||!e.error||"Not Found"!==e.error&&"NoSuchTagSet"!==e.error.Code)t(e);else{var i={Tags:[],statusCode:e.statusCode};e.headers&&(i.headers=e.headers),t(null,i)}else{var a=[];try{a=n.Tagging.TagSet.Tag||[]}catch(e){}a=o.clone(o.isArray(a)?a:[a]),t(null,{Tags:a,statusCode:n.statusCode,headers:n.headers})}}))},deleteObjectTagging:function(e,t){f.call(this,{Interface:"deleteObjectTagging",Action:"name/cos:DeleteObjectTagging",method:"DELETE",Bucket:e.Bucket,Region:e.Region,Key:e.Key,headers:e.Headers,action:"tagging",VersionId:e.VersionId,tracker:e.tracker},(function(e,n){return e&&204===e.statusCode?t(null,{statusCode:e.statusCode}):e?t(e):void t(null,{statusCode:n.statusCode,headers:n.headers})}))},appendObject:function(e,t){f.call(this,{Action:"name/cos:AppendObject",method:"POST",Bucket:e.Bucket,Region:e.Region,action:"append",Key:e.Key,body:e.Body,qs:{position:e.Position},headers:e.Headers,tracker:e.tracker},(function(e,n){if(e)return t(e);t(null,n)}))},uploadPartCopy:function(e,t){var n=e.CopySource||"",i=o.getSourceParams.call(this,n);if(i){var a=i.Bucket,r=i.Region,s=decodeURIComponent(i.Key);f.call(this,{Scope:[{action:"name/cos:GetObject",bucket:a,region:r,prefix:s},{action:"name/cos:PutObject",bucket:e.Bucket,region:e.Region,prefix:e.Key}],method:"PUT",Bucket:e.Bucket,Region:e.Region,Key:e.Key,VersionId:e.VersionId,qs:{partNumber:e.PartNumber,uploadId:e.UploadId},headers:e.Headers,tracker:e.tracker},(function(e,n){if(e)return t(e);var i=o.clone(n.CopyPartResult||{});o.extend(i,{statusCode:n.statusCode,headers:n.headers}),t(null,i)}))}else t({error:"CopySource format error"})},multipartInit:function(e,t){var n=e.Headers,i=e.tracker;n["Cache-Control"]||n["cache-control"]||(n["Cache-Control"]=""),n["Content-Type"]||n["content-type"]||(n["Content-Type"]=a.getType(e.Key)||"application/octet-stream"),f.call(this,{Action:"name/cos:InitiateMultipartUpload",method:"POST",Bucket:e.Bucket,Region:e.Region,Key:e.Key,action:"uploads",headers:e.Headers,qs:e.Query,tracker:i},(function(e,n){return e?(i&&i.parent&&i.parent.setParams({errorNode:"multipartInit"}),t(e)):(n=o.clone(n||{}))&&n.InitiateMultipartUploadResult?t(null,o.extend(n.InitiateMultipartUploadResult,{statusCode:n.statusCode,headers:n.headers})):void t(null,n)}))},multipartUpload:function(e,t){var n=this;o.getFileSize("multipartUpload",e,(function(){var i=e.tracker,a=n.options.UploadCheckContentMd5;a&&i&&i.setParams({md5StartTime:(new Date).getTime()}),o.getBodyMd5(a,e.Body,(function(r){r&&(e.Headers["Content-MD5"]=o.binaryBase64(r),a&&i&&i.setParams({md5EndTime:(new Date).getTime()})),i&&i.setParams({partNumber:e.PartNumber}),f.call(n,{Action:"name/cos:UploadPart",TaskId:e.TaskId,method:"PUT",Bucket:e.Bucket,Region:e.Region,Key:e.Key,qs:{partNumber:e.PartNumber,uploadId:e.UploadId},headers:e.Headers,onProgress:e.onProgress,body:e.Body||null,tracker:i},(function(e,n){if(e)return i&&i.parent&&i.parent.setParams({errorNode:"multipartUpload"}),t(e);t(null,{ETag:o.attr(n.headers,"etag",{}),statusCode:n.statusCode,headers:n.headers})}))}))}))},multipartComplete:function(e,t){for(var n=this,i=e.UploadId,a=e.Parts,r=e.tracker,s=0,l=a.length;s-1?function(e){var t=e.match(/q-url-param-list.*?(?=&)/g)[0],n="q-url-param-list="+encodeURIComponent(t.replace(/q-url-param-list=/,"")).toLowerCase(),i=new RegExp(t,"g");return e.replace(i,n)}(n.Authorization):"sign="+encodeURIComponent(n.Authorization)),n.SecurityToken&&(i+="&x-cos-security-token="+n.SecurityToken),n.ClientIP&&(i+="&clientIP="+n.ClientIP),n.ClientUA&&(i+="&clientUA="+n.ClientUA),n.Token&&(i+="&token="+n.Token),r&&(i+="&"+r),setTimeout((function(){t(null,{Url:i})}))}}));return d?(s+="?"+d.Authorization+(d.SecurityToken?"&x-cos-security-token="+d.SecurityToken:""),r&&(s+="&"+r)):r&&(s+="?"+r),s},getAuth:function(e){return o.getAuth({SecretId:e.SecretId||this.options.SecretId||"",SecretKey:e.SecretKey||this.options.SecretKey||"",Bucket:e.Bucket,Region:e.Region,Method:e.Method,Key:e.Key,Query:e.Query,Headers:e.Headers,Expires:e.Expires,SystemClockOffset:this.options.SystemClockOffset})}};e.exports.init=function(e,t){t.transferToTaskMethod(h,"postObject"),t.transferToTaskMethod(h,"putObject"),o.each(h,(function(t,n){e.prototype[n]=o.apiWrapper(n,t)}))}},function(e,t){function n(e){return encodeURIComponent(e).replace(/!/g,"%21").replace(/'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/\*/g,"%2A")}var i=function(e,t){var i,o,a,r=[],s=function(e,t){var i=[];for(var o in e)e.hasOwnProperty(o)&&i.push(t?n(o).toLowerCase():o);return i.sort((function(e,t){return(e=e.toLowerCase())===(t=t.toLowerCase())?0:e>t?1:-1}))}(e);for(i=0;i-1||m.indexOf(h)>-1)&&(f[h]=e.headers[h]);a["x-cos-acl"]&&(f.acl=a["x-cos-acl"]),!f["Content-Type"]&&(f["Content-Type"]=""),(n=wx.uploadFile({url:r,method:s,name:"file",header:a,filePath:o,formData:f,timeout:e.timeout,success:function(e){p(null,e)},fail:function(e){p(e.errMsg,e)}})).onProgressUpdate((function(e){c&&c({loaded:e.totalBytesSent,total:e.totalBytesExpectedToSend,progress:e.progress/100})}))}else{var g=e.qs&&i(e.qs)||"";g&&(r+=(r.indexOf("?")>-1?"&":"?")+g),a["Content-Length"]&&delete a["Content-Length"];var v={url:r,method:s,header:a,dataType:"text",data:e.body,responseType:e.dataType||"text",timeout:e.timeout,redirect:"manual",success:function(e){p(null,e)},fail:function(e){p(e.errMsg,e)}};l&&Object.assign(v,{enableHttpDNS:!0,httpDNSServiceId:l}),n=wx.request(v)}return n}},function(e,t,n){"use strict";let i=n(29);e.exports=new i(n(30),n(31))},function(e,t,n){"use strict";function i(){this._types=Object.create(null),this._extensions=Object.create(null);for(let e=0;e=0;--o){var r=this.tryEntries[o],s=r.completion;if("root"===r.tryLoc)return i("end");if(r.tryLoc<=this.prev){var c=a.call(r,"catchLoc"),l=a.call(r,"finallyLoc");if(c&&l){if(this.prev=0;--n){var i=this.tryEntries[n];if(i.tryLoc<=this.prev&&a.call(i,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),O(n),y}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var i=n.completion;if("throw"===i.type){var o=i.arg;O(n)}return o}}throw Error("illegal catch attempt")},delegateYield:function(t,n,i){return this.delegate={iterator:I(t),resultName:n,nextLoc:i},"next"===this.method&&(this.arg=e),y}},t}function o(e){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o(e)}function a(e,t,n,i,o,a,r){try{var s=e[a](r),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(i,o)}function r(e){return function(){var t=this,n=arguments;return new Promise((function(i,o){var r=e.apply(t,n);function s(e){a(r,i,o,s,c,"next",e)}function c(e){a(r,i,o,s,c,"throw",e)}s(void 0)}))}}var s=n(7),c=n(33),l=n(6).EventProxy,p=n(0),u=n(2);function d(e,t){var n=e.TaskId,i=e.Bucket,o=e.Region,a=e.Key,r=e.StorageClass,u=this,d={},h=e.FileSize,g=e.SliceSize,v=Math.ceil(h/g),y=0,x=p.throttleOnProgress.call(u,h,e.onHashProgress),k=function(t,n){var i=t.length;if(0===i)return n(null,!0);if(i>v)return n(null,!1);if(i>1&&Math.max(t[0].Size,t[1].Size)!==g)return n(null,!1);!function o(a){if(a=c.length)b.emit("has_and_check_upload_id",t);else{var d=c[l];if(!p.isInArray(t,d))return s.removeUploadId(d),void r(l+1);s.using[d]?r(l+1):m.call(u,{Bucket:i,Region:o,Key:a,UploadId:d,tracker:e.tracker},(function(e,t){u._isRunningTask(n)&&(e?(s.removeUploadId(d),r(l+1)):b.emit("upload_id_available",{UploadId:d,PartList:t.PartList}))}))}}(0)}else b.emit("has_and_check_upload_id",t)})),b.on("get_remote_upload_id_list",(function(){f.call(u,{Bucket:i,Region:o,Key:a,tracker:e.tracker},(function(t,o){if(u._isRunningTask(n)){if(t)return b.emit("error",t);var c=p.filter(o.UploadList,(function(e){return e.Key===a&&(!r||e.StorageClass.toUpperCase()===r.toUpperCase())})).reverse().map((function(e){return e.UploadId||e.UploadID}));if(c.length)b.emit("seek_local_avail_upload_id",c);else{var l,d=s.getFileId(e.FileStat,e.ChunkSize,i,a);d&&(l=s.getUploadIdList(d))&&p.each(l,(function(e){s.removeUploadId(e)})),b.emit("no_available_upload_id")}}}))})),b.emit("get_remote_upload_id_list")}function f(e,t){var n=this,i=[],o={Bucket:e.Bucket,Region:e.Region,Prefix:e.Key,calledBySdk:e.calledBySdk||"sliceUploadFile",tracker:e.tracker};!function e(){n.multipartList(o,(function(n,a){if(n)return t(n);i.push.apply(i,a.Upload||[]),"true"===a.IsTruncated?(o.KeyMarker=a.NextKeyMarker,o.UploadIdMarker=a.NextUploadIdMarker,e()):t(null,{UploadList:i})}))}()}function m(e,t){var n=this,i=[],o={Bucket:e.Bucket,Region:e.Region,Key:e.Key,UploadId:e.UploadId,calledBySdk:"sliceUploadFile",tracker:e.tracker};!function e(){n.multipartListPart(o,(function(n,a){if(n)return t(n);i.push.apply(i,a.Part||[]),"true"===a.IsTruncated?(o.PartNumberMarker=a.NextPartNumberMarker,e()):t(null,{PartList:i})}))}()}function h(e,t){var n=this,i=e.TaskId,o=e.Bucket,a=e.Region,r=e.Key,s=e.UploadData,l=e.FileSize,u=e.SliceSize,d=Math.min(e.AsyncLimit||n.options.ChunkParallelLimit||1,256),f=e.FilePath,m=Math.ceil(l/u),h=0,v=e.ServerSideEncryption,y=p.filter(s.PartList,(function(e){return e.Uploaded&&(h+=e.PartNumber>=m&&l%u||u),!e.Uploaded})),x=e.onProgress;c.eachLimit(y,d,(function(t,c){if(n._isRunningTask(i)){var p=t.PartNumber,d=Math.min(l,t.PartNumber*u)-(t.PartNumber-1)*u,m=0;g.call(n,{TaskId:i,Bucket:o,Region:a,Key:r,SliceSize:u,FileSize:l,PartNumber:p,ServerSideEncryption:v,FilePath:f,UploadData:s,onProgress:function(e){h+=e.loaded-m,m=e.loaded,x({loaded:h,total:l})},tracker:e.tracker},(function(e,o){n._isRunningTask(i)&&(e?h-=m:(h+=d-m,t.ETag=o.ETag),x({loaded:h,total:l}),c(e||null,o))}))}}),(function(e){if(n._isRunningTask(i))return e?t(e):void t(null,{UploadId:s.UploadId,SliceList:s.PartList})}))}function g(e,t){var n=this,i=e.TaskId,o=e.Bucket,a=e.Region,r=e.Key,s=e.FileSize,l=e.FilePath,u=1*e.PartNumber,d=e.SliceSize,f=e.ServerSideEncryption,m=e.UploadData,h=n.options.ChunkRetryTimes+1,g=e.Headers||{},v=d*(u-1),y=d,x=v+d;x>s&&(y=(x=s)-v);var k=["x-cos-traffic-limit","x-cos-mime-limit"],b={};p.each(g,(function(e,t){k.indexOf(t)>-1&&(b[t]=e)})),p.fileSlice(l,v,x,(function(s){var l=p.getFileMd5(s),d=l?p.binaryBase64(l):null,g=m.PartList[u-1];c.retry(h,(function(t){n._isRunningTask(i)&&n.multipartUpload({TaskId:i,Bucket:o,Region:a,Key:r,ContentLength:y,PartNumber:u,UploadId:m.UploadId,ServerSideEncryption:f,Body:s,Headers:b,onProgress:e.onProgress,ContentMD5:d,calledBySdk:"sliceUploadFile",tracker:e.tracker},(function(e,o){if(n._isRunningTask(i))return e?t(e):(g.Uploaded=!0,t(null,o))}))}),(function(e,o){if(n._isRunningTask(i))return t(e,o)}))}))}function v(e,t){var n=e.Bucket,i=e.Region,o=e.Key,a=e.UploadId,r=e.SliceList,s=this,l=this.options.ChunkRetryTimes+1,p=r.map((function(e){return{PartNumber:e.PartNumber,ETag:e.ETag}}));c.retry(l,(function(t){s.multipartComplete({Bucket:n,Region:i,Key:o,UploadId:a,Parts:p,calledBySdk:"sliceUploadFile",Headers:e.Headers||{},tracker:e.tracker},t)}),(function(e,n){t(e,n)}))}function y(e,t){var n=e.Bucket,i=e.Region,o=e.Key,a=e.AbortArray,r=e.AsyncLimit||1,s=this,l=0,p=new Array(a.length);c.eachLimit(a,r,(function(t,a){var r=l;if(o&&o!==t.Key)return p[r]={error:{KeyNotMatch:!0}},void a(null);var c=t.UploadId||t.UploadID;s.multipartAbort({Bucket:n,Region:i,Key:t.Key,Headers:e.Headers,UploadId:c},(function(e){var o={Bucket:n,Region:i,Key:t.Key,UploadId:c};p[r]={error:e,task:o},a(null)})),l++}),(function(e){if(e)return t(e);for(var n=[],i=[],o=0,a=p.length;or?"sliceUploadFile":"putObject",t.tracker=new u({Beacon:a.options.BeaconReporter,clsReporter:a.options.ClsReporter,bucket:t.Bucket,region:t.Region,apiName:"uploadFile",realApi:f,fileKey:t.Key,fileSize:c,accelerate:d,deepTracker:a.options.DeepTracker,customId:a.options.CustomId,delay:a.options.TrackerDelay})),p.each(t,(function(e,t){"object"!==o(e)&&"function"!=typeof e&&(l[t]=e)})),m=t.onTaskReady,t.onTaskReady=function(e){l.TaskId=e,m&&m(e)},h=t.onFileFinish,g=function(e,i){t.tracker&&t.tracker.report(e,i),h&&h(e,i,l),n&&n(e,i)},v="postObject"===a.options.SimpleUploadMethod?"postObject":"putObject",y=c>r?"sliceUploadFile":v,s.push({api:y,params:t,callback:g}),a._addTasks(s);case 24:case"end":return e.stop()}}),e,this,[[3,9]])})))).apply(this,arguments)}function k(){return k=r(i().mark((function e(t,n){var a,s,c,l,d,f,m,h,g,v,y;return i().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a=this,s=void 0===t.SliceSize?a.options.SliceSize:t.SliceSize,c=0,l=0,d=p.throttleOnProgress.call(a,l,t.onProgress),f=t.files.length,m=t.onFileFinish,h=Array(f),g=function(e,t,i){d(null,!0),m&&m(e,t,i),h[i.Index]={options:i,error:e,data:t},--f<=0&&n&&n(null,{files:h})},v=[],y=function(){return t.files.map((function(e,t){return new Promise(function(){var n=r(i().mark((function n(r){var f,m,h,y,x,k,b,C,S,w,T;return i().wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return f=0,n.prev=1,n.next=4,p.getFileSizeByPath(e.FilePath);case 4:f=n.sent,n.next=9;break;case 7:n.prev=7,n.t0=n.catch(1);case 9:m={Index:t,TaskId:""},c+=f,a.options.EnableReporter&&(h=a.options.UseAccelerate||"string"==typeof a.options.Domain&&a.options.Domain.includes("accelerate."),y=f>s?"sliceUploadFile":"putObject",e.tracker=new u({Beacon:a.options.BeaconReporter,clsReporter:a.options.ClsReporter,bucket:e.Bucket,region:e.Region,apiName:"uploadFiles",realApi:y,fileKey:e.Key,fileSize:f,accelerate:h,deepTracker:a.options.DeepTracker,customId:a.options.CustomId,delay:a.options.TrackerDelay})),p.each(e,(function(e,t){"object"!==o(e)&&"function"!=typeof e&&(m[t]=e)})),x=e.onTaskReady,e.onTaskReady=function(e){m.TaskId=e,x&&x(e)},k=0,b=e.onProgress,e.onProgress=function(e){l=l-k+e.loaded,k=e.loaded,b&&b(e),d({loaded:l,total:c})},C=e.onFileFinish,S=function(t,n){e.tracker&&e.tracker.report(t,n),C&&C(t,n),g&&g(t,n,m)},w="postObject"===a.options.SimpleUploadMethod?"postObject":"putObject",T=f>s?"sliceUploadFile":w,v.push({api:T,params:e,callback:S}),r(!0);case 24:case"end":return n.stop()}}),n,null,[[1,7]])})));return function(e){return n.apply(this,arguments)}}())}))},e.next=13,Promise.all(y());case 13:a._addTasks(v);case 14:case"end":return e.stop()}}),e,this)}))),k.apply(this,arguments)}function b(e,t){var n=e.TaskId,i=e.Bucket,o=e.Region,a=e.Key,r=e.CopySource,s=e.UploadId,l=1*e.PartNumber,p=e.CopySourceRange,u=this.options.ChunkRetryTimes+1,d=this;c.retry(u,(function(t){d.uploadPartCopy({TaskId:n,Bucket:i,Region:o,Key:a,CopySource:r,UploadId:s,PartNumber:l,CopySourceRange:p,onProgress:e.onProgress,tracker:e.tracker,calledBySdk:e.calledBySdk},(function(e,n){t(e||null,n)}))}),(function(e,n){return t(e,n)}))}var C={sliceUploadFile:function(e,t){var n=this;if(!p.canFileSlice())return e.SkipTask=!0,void("postObject"===n.options.SimpleUploadMethod?n.postObject(e,t):n.putObject(e,t));var i,o,a=new l,r=e.TaskId,c=e.Bucket,u=e.Region,f=e.Key,m=e.FilePath,g=e.ChunkSize||e.SliceSize||n.options.ChunkSize,y=e.AsyncLimit,x=e.StorageClass,k=e.ServerSideEncryption,b=e.onHashProgress,C=e.tracker;C&&C.setParams({chunkSize:g}),a.on("error",(function(i){if(n._isRunningTask(r)){var o={UploadId:e.UploadData.UploadId||"",err:i,error:i};return t(o)}})),a.on("upload_complete",(function(n){var i=p.extend({UploadId:e.UploadData.UploadId||""},n);t(null,i)})),a.on("upload_slice_complete",(function(t){var l={};p.each(e.Headers,(function(e,t){var n=t.toLowerCase();0!==n.indexOf("x-cos-meta-")&&"pic-operations"!==n||(l[t]=e)})),v.call(n,{Bucket:c,Region:u,Key:f,UploadId:t.UploadId,SliceList:t.SliceList,Headers:l,tracker:C},(function(e,c){if(n._isRunningTask(r)){if(s.removeUsing(t.UploadId),e)return o(null,!0),a.emit("error",e);s.removeUploadId(t.UploadId),o({loaded:i,total:i},!0),a.emit("upload_complete",c)}}))})),a.on("get_upload_data_finish",(function(t){var l=s.getFileId(e.FileStat,e.ChunkSize,c,f);l&&s.saveUploadId(l,t.UploadId,n.options.UploadIdCacheLimit),s.setUsing(t.UploadId),o(null,!0),h.call(n,{TaskId:r,Bucket:c,Region:u,Key:f,FilePath:m,FileSize:i,SliceSize:g,AsyncLimit:y,ServerSideEncryption:k,UploadData:t,onProgress:o,tracker:C},(function(e,t){if(n._isRunningTask(r))return e?(o(null,!0),a.emit("error",e)):void a.emit("upload_slice_complete",t)}))})),a.on("get_file_size_finish",(function(){if(o=p.throttleOnProgress.call(n,i,e.onProgress),e.UploadData.UploadId)a.emit("get_upload_data_finish",e.UploadData);else{var t=p.extend({TaskId:r,Bucket:c,Region:u,Key:f,Headers:e.Headers,StorageClass:x,FilePath:m,FileSize:i,SliceSize:g,onHashProgress:b,tracker:C},e);t.FileSize=i,d.call(n,t,(function(t,i){if(n._isRunningTask(r)){if(t)return a.emit("error",t);e.UploadData.UploadId=i.UploadId,e.UploadData.PartList=i.PartList,a.emit("get_upload_data_finish",e.UploadData)}}))}})),i=e.ContentLength,delete e.ContentLength,!e.Headers&&(e.Headers={}),p.each(e.Headers,(function(t,n){"content-length"===n.toLowerCase()&&delete e.Headers[n]})),function(){for(var t=[1,2,4,8,16,32,64,128,256,512,1024,2048,4096,5120],o=1048576,a=0;a=w&&y%k||k),!e.Uploaded}));c.eachLimit(f,C,(function(t,n){var s=t.PartNumber,p=t.CopySourceRange,d=t.end-t.start,f=0;c.retry(S,(function(t){b.call(i,{Bucket:o,Region:a,Key:r,CopySource:u,UploadId:l.UploadId,PartNumber:s,CopySourceRange:p,tracker:e.tracker,calledBySdk:"sliceCopyFile",onProgress:function(e){T+=e.loaded-f,f=e.loaded,x({loaded:T,total:y})}},t)}),(function(e,i){if(e)return n(e);x({loaded:T,total:y}),T+=d-f,t.ETag=i.ETag,n(e||null,i)}))}),(function(e){if(e)return s.removeUsing(l.UploadId),x(null,!0),t(e);n.emit("copy_slice_complete",l)}))})),n.on("get_chunk_size_finish",(function(){var c=function(){i.multipartInit({Bucket:o,Region:a,Key:r,Headers:A,tracker:e.tracker,calledBySdk:"sliceCopyFile"},(function(i,o){if(i)return t(i);e.UploadId=o.UploadId,n.emit("get_copy_data_finish",{UploadId:e.UploadId,PartList:e.PartList})}))},l=s.getCopyFileId(u,R,k,o,r),d=s.getUploadIdList(l);if(!l||!d)return c();!function t(l){if(l>=d.length)return c();var u=d[l];if(s.using[u])return t(l+1);m.call(i,{Bucket:o,Region:a,Key:r,UploadId:u,tracker:e.tracker,calledBySdk:"sliceCopyFile"},(function(i,o){if(i)s.removeUploadId(u),t(l+1);else{if(s.using[u])return t(l+1);var a={},r=0;p.each(o.PartList,(function(e){var t=parseInt(e.Size),n=r+t-1;a[e.PartNumber+"|"+r+"|"+n]=e.ETag,r+=t})),p.each(e.PartList,(function(e){var t=a[e.PartNumber+"|"+e.start+"|"+e.end];t&&(e.ETag=t,e.Uploaded=!0)})),n.emit("get_copy_data_finish",{UploadId:u,PartList:e.PartList})}}))}(0)})),n.on("get_file_size_finish",(function(){var o;if(function(){for(var t=[1,2,4,8,16,32,64,128,256,512,1024,2048,4096,5120],n=1048576,o=0;o11&&(B[t]=e)})),n.emit("get_file_size_finish")}else t({error:'get Content-Length error, please add "Content-Length" to CORS ExposeHeader setting.'})}))}else t({error:"CopySource format error"})}};e.exports.init=function(e,t){t.transferToTaskMethod(C,"sliceUploadFile"),p.each(C,(function(t,n){e.prototype[n]=p.apiWrapper(n,t)}))}},function(e,t){var n={eachLimit:function(e,t,n,i){if(i=i||function(){},!e.length||t<=0)return i();var o=0,a=0,r=0;!function s(){if(o>=e.length)return i();for(;r=e.length?i():s())}))}()},retry:function(e,t,n){e<1?n():function i(o){t((function(t,a){t&&o{for(var r in i)e.o(i,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:i[r]})}};e.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),e.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==e.g?e.g:"undefined"!=typeof self?self:{};function i(e){var t={exports:{}};return e(t,t.exports),t.exports}var r,s,n,o,a,c,d,l,h,p,u,m,g,v,f,_,I,y,E,M,T,S,N,C,A,O,R,b,k,L,V,P,D,w,U,x,F,B,j,G,$,H,Y,q,K,W,J,z,X,Q,Z,ee,te,ie,re,se,ne=i(function(e){var t=Object.prototype.hasOwnProperty,i="~";function r(){}function s(e,t,i){this.fn=e,this.context=t,this.once=i||!1}function n(e,t,r,n,o){if("function"!=typeof r)throw new TypeError("The listener must be a function");var a=new s(r,n||e,o),c=i?i+t:t;return e._events[c]?e._events[c].fn?e._events[c]=[e._events[c],a]:e._events[c].push(a):(e._events[c]=a,e._eventsCount++),e}function o(e,t){0==--e._eventsCount?e._events=new r:delete e._events[t]}function a(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(i=!1)),a.prototype.eventNames=function(){var e,r,s=[];if(0===this._eventsCount)return s;for(r in e=this._events)t.call(e,r)&&s.push(i?r.slice(1):r);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(e)):s},a.prototype.listeners=function(e){var t=i?i+e:e,r=this._events[t];if(!r)return[];if(r.fn)return[r.fn];for(var s=0,n=r.length,o=new Array(n);s=0;--s){var n=this.tryEntries[s],o=n.completion;if("root"===n.tryLoc)return i("end");if(n.tryLoc<=this.prev){var a=r.call(n,"catchLoc"),c=r.call(n,"finallyLoc");if(a&&c){if(this.prev=0;--i){var s=this.tryEntries[i];if(s.tryLoc<=this.prev&&r.call(s,"finallyLoc")&&this.prev=0;--t){var i=this.tryEntries[t];if(i.finallyLoc===e)return this.complete(i.completion,i.afterLoc),T(i),h}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var i=this.tryEntries[t];if(i.tryLoc===e){var r=i.completion;if("throw"===r.type){var s=r.arg;T(i)}return s}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,i){return this.delegate={iterator:N(e),resultName:t,nextLoc:i},"next"===this.method&&(this.arg=void 0),h}},t}function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t(e)}function i(e,t){for(var i=0;i2&&void 0!==arguments[2]?arguments[2]:{};if(i.priority||(i.priority=this.getEventPriority(e,t)),this.reportConfig.isDataReportEnable&&e){if("login"===e&&!1===t.succeed&&t.process_id){var s=t.extension&&t.extension.find(function(e){return"TCP"===e.operation_type}),n=s&&s.target||"",o=t.process_id+n,a=this.lastFailLogin[o]||0;if(t.start_time-athis.reportConfig.msgListMaxSize&&this.highPriorityMsgList.shift(),this.msgList.length>this.reportConfig.msgListMaxSize&&this.msgList.shift(),this.lowPriorityMsgList.length>this.reportConfig.msgListMaxSize&&this.lowPriorityMsgList.shift(),this.doReport()}}},{key:"reportTraceStart",value:function(e,t){if(this.reportConfig.isDataReportEnable&&e&&!this.traceMsgCache[e]){var i=Object.assign(Object.assign({start_time:Date.now()},t),{extension:[]});this.traceMsgCache[e]=i}}},{key:"reportTraceUpdate",value:function(e){}},{key:"reportTraceUpdateV2",value:function(e,t,i){var r,s=this;if(this.reportConfig.isDataReportEnable&&this.traceMsgCache[e]){var n=this.traceMsgCache[e].extension,o=n.length,a=(new Date).getTime();0===o?t.duration=a-this.traceMsgCache[e].start_time:n[o-1].end_time?t.duration=a-n[o-1].end_time:t.duration=a-this.traceMsgCache[e].start_time,n.push(Object.assign({end_time:a},t));var c=n.length-1;(null==i?void 0:i.asyncParams)&&((r=this.traceMsgCache[e]).asyncPromiseArray||(r.asyncPromiseArray=[]),this.traceMsgCache[e].asyncPromiseArray.push(i.asyncParams.then(function(t){s.traceMsgCache[e]&&s.traceMsgCache[e].extension[c]&&Object.assign(s.traceMsgCache[e].extension[c],t)})))}}},{key:"reportTraceEnd",value:function(e){var t,i=this,r=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(this.reportConfig.isDataReportEnable&&this.traceMsgCache[e])if("nos"!==e||!1===r){"boolean"==typeof r?this.traceMsgCache[e].succeed=!!r:this.traceMsgCache[e].state=r,this.traceMsgCache[e].duration=Date.now()-this.traceMsgCache[e].start_time,this.traceMsgCache[e].extension.forEach(function(e){delete e.end_time});var s=this.traceMsgCache[e];if(this.traceMsgCache[e]=null,s.asyncPromiseArray){(t=this.endedAsyncMsgByModule)[e]||(t[e]=[]),this.endedAsyncMsgByModule[e].push(s);var n=function(){i.endedAsyncMsgByModule[e]&&i.endedAsyncMsgByModule[e].includes(s)&&(delete s.asyncPromiseArray,i.report(e,s,{priority:i.getEventPriority(e,s)}))};Promise.all(s.asyncPromiseArray).then(n).catch(n)}else this.report(e,s,{priority:this.getEventPriority(e,s)})}else this.traceMsgCache[e]=null}},{key:"getEventPriority",value:function(e,t){if("exceptions"===e){if(0===t.action)return"HIGH";if(2===t.action)return"HIGH";if(1===t.action&&0!==t.exception_service)return"HIGH"}else{if("msgReceive"===e)return"LOW";if("nim_api_trace"===e)return"LOW"}return"NORMAL"}},{key:"reportTraceCancel",value:function(e){this.reportConfig.isDataReportEnable&&(this.endedAsyncMsgByModule[e]=[],this.traceMsgCache[e]=null)}},{key:"pause",value:function(){this.reportConfig.isDataReportEnable&&(this.isUploadEnable=!1)}},{key:"restore",value:function(){this.reportConfig.isDataReportEnable&&(this.isUploadEnable=!0,this.initConfigLoaded||this.initUploadConfig())}},{key:"destroy",value:function(){var e=this;this.reportConfig.isDataReportEnable&&(Object.keys(this.traceMsgCache).forEach(function(t){e.reportTraceEnd(t,1)}),null!==this.timer&&clearTimeout(this.timer),this.setConfig=s,this.report=s,this.reportTraceStart=s,this.reportTraceUpdate=s,this.reportTraceEnd=s,this.pause=s,this.restore=s,this.destroy=s,this.reqRetryCount=0,this.cacheMsgList=[],this.traceMsgCache={},this.lowPriorityMsgList=[],this.msgList=[],this.highPriorityMsgList=[],this.reportConfig={},this.isDestroyed=!0)}},{key:"initUploadConfig",value:function(){var i,r;return function(e,t,i,r){function s(e){return e instanceof i?e:new i(function(t){t(e)})}return new(i||(i=Promise))(function(t,i){function n(e){try{a(r.next(e))}catch(e){i(e)}}function o(e){try{a(r.throw(e))}catch(e){i(e)}}function a(e){e.done?t(e.value):s(e.value).then(n,o)}a((r=r.apply(e,[])).next())})}(this,0,void 0,e().mark(function s(){var n,o,a,c,d,l=this;return e().wrap(function(s){for(;;)switch(s.prev=s.next){case 0:if(!this.loading){s.next=2;break}return s.abrupt("return");case 2:this.loading=!0,n=this.reportConfig.common||{},o=this.reportConfig.compassDataEndpoint.split(",").map(function(e){return"".concat(e,"/").concat(l.configPath)}),a=e().mark(function t(s){return e().wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(!l.initConfigLoaded&&!l.isDestroyed){e.next=2;break}return e.abrupt("return","break");case 2:return e.prev=2,e.next=5,l.reportConfig.request(o[s],{method:"GET",dataType:"json",params:{deviceId:n.dev_id,sdkVer:n.sdk_ver,platform:n.platform,hostEnv:n.host_env,appkey:n.app_key},timeout:l.reportConfig.timeout}).then(function(e){var t,i;if(!l.isDestroyed){if(200===e.status&&e.data&&200===e.data.code){l.initConfigLoaded=!0;var r=e.data.data||{};l.reportConfig.maxSize=r.maxSize>1e3?1e3:r.maxSize,l.reportConfig.maxInterval=r.maxInterval>1e4?1e4:r.maxInterval,l.reportConfig.maxInterval=r.maxInterval<10?10:r.maxInterval,l.reportConfig.minInterval=r.minInterval<2?2:r.minInterval,l.reportConfig.maxDelay=r.maxDelay||300,l.reportConfig.maxInterval=1e3*l.reportConfig.maxInterval,l.reportConfig.minInterval=1e3*l.reportConfig.minInterval,l.reportConfig.maxDelay=1e3*l.reportConfig.maxDelay,r.endpoint?l.dataReportEndpoint=r.endpoint:l.dataReportEndpoint=o[s],l.serverAllowUpload=!0,l.loading=!1,l.reportHeartBeat()}else 200===e.status&&(l.initConfigLoaded=!0);null===(i=null===(t=l.reportConfig)||void 0===t?void 0:t.logger)||void 0===i||i.log("Get reporter upload config success")}}).catch(function(e){var t,i;l.isDestroyed||(l.loading=!1,null===(i=null===(t=l.reportConfig)||void 0===t?void 0:t.logger)||void 0===i||i.error("Get reporter upload config failed",e),l.reqRetryCount<12&&(l.reqRetryCount++,setTimeout(function(){l.isDestroyed||l.initUploadConfig()},8e3)))});case 5:e.next=14;break;case 7:if(e.prev=7,e.t0=e.catch(2),!l.isDestroyed){e.next=11;break}return e.abrupt("return",{v:void 0});case 11:l.loading=!1,null===(r=null===(i=l.reportConfig)||void 0===i?void 0:i.logger)||void 0===r||r.error("Exec reporter request failed",e.t0),l.reqRetryCount<12&&(l.reqRetryCount++,setTimeout(function(){l.isDestroyed||l.initUploadConfig()},8e3));case 14:case"end":return e.stop()}},t,null,[[2,7]])}),c=0;case 7:if(!(c2*this.reportConfig.maxSize?this.reportConfig.minInterval:this.reportConfig.maxInterval;Date.now()-this.lastReportTime>=e&&this.upload()}}},{key:"getUploadMsg",value:function(){var e=this,t={},i=Date.now();this.highPriorityMsgList=this.highPriorityMsgList.filter(function(t){return i-t.createTime{var o=e[n].type,a=i?`In ${i}, `:"";if(null==t){var c=`${a}param is null or undefined`;throw r?new me({detail:{reason:c,data:{key:n},rules:"required"}}):new ue(c,{key:n},"required")}if(void 0===t[n]){if(!1===e[n].required)return void(s[n]=t[n]);var d=`${a}param '${n}' is required`;throw r?new me({detail:{reason:d,data:{key:n},rules:"required"}}):new ue(d,{key:n},"required")}var l=Ie[o];if(l&&!l(t,n,e[n],r)){var h=`${a}param '${n}' unexpected`,p={key:n,value:t[n]};throw r?new me({detail:{reason:h,data:p,rules:JSON.stringify(e[n],fe)}}):new ue(h,p,JSON.stringify(e[n],fe))}s[n]=t[n]}),s}var Ie={string:function(e,t,i){var{allowEmpty:r,max:s,min:n,regExp:o}=i,a=e[t];return!("string"!=typeof a||!1===r&&""===a||"number"==typeof s&&a.length>s||"number"==typeof n&&a.lengths)},boolean:function(e,t){return"boolean"==typeof e[t]},file:function(e,t){return!0},enum:function(e,t,i){var{values:r}=i,s=e[t];return!r||r.indexOf(s)>-1},jsonstr:function(e,t){try{var i=JSON.parse(e[t]);return"object"==typeof i&&null!==i}catch(e){return!1}},func:function(e,t){return"function"==typeof e[t]},array:function(e,t,i,r=!1){var{itemType:s,itemRules:n,rules:o,min:a,max:c,values:d}=i,l=e[t];if(!Array.isArray(l))return!1;if("number"==typeof c&&l.length>c)return!1;if("number"==typeof a&&l.length{_e({[i]:n},{[i]:e},`${t}[${i}]`,r)});else if(o)l.forEach((e,i)=>_e(o,e,`${t}[${i}]`,r));else if("enum"===s){if(d&&function(e,t){return t=t||[],(e=e||[]).filter(e=>-1===t.indexOf(e))}(l,d).length)return!1}else if(s&&!l.every(e=>typeof e===s))return!1;return!0},object:function(e,t,i,r=!1){var{rules:s,allowEmpty:n}=i,o=e[t];if("object"!=typeof o||null===o)return!1;if(s){var a=Object.keys(s),c=Object.keys(o).filter(e=>a.indexOf(e)>-1);if(!1===n&&0===c.length)return!1;_e(s,o,t,r)}return!0}};function ye(e,t){if(!e)throw new pe({code:de.V2NIM_ERROR_CODE_ILLEGAL_STATE});_e({conversationId:{type:"string",allowEmpty:!1,regExp:new RegExp(`^${e}\\|[1-3]\\|`)}},{conversationId:t},"",!0)}class Ee{constructor(){this.timerList=[],this.id=1,this.timer=null,this.timeout=0}addTimer(e,t=0,i=1){var r=(new Date).getTime(),s=this.id;return this.timerList.push({id:s,loop:i,count:0,timeout:r+t,interval:t,callback:e}),this.id++,this.checkTimer(r),s}checkTimer(e=(new Date).getTime()){if(this.removeFinished(),0!==this.timerList.length||null==this.timer){var t=0;for(var i of this.timerList)(0===t||t>i.timeout)&&(t=i.timeout);0!==this.timerList.length&&(null===this.timer||t=t.timeout&&(t.callback(),t.count++,t.timeout=e+t.interval);this.clerTime(),this.checkTimer(e)}clerTime(){null!==this.timer&&(clearTimeout(this.timer),this.timer=null)}deleteTimer(e){for(var t=this.timerList.length-1;t>=0;t--)this.timerList[t].id===e&&this.timerList.splice(t,1)}removeFinished(){for(var e=this.timerList.length-1;e>=0;e--){var t=this.timerList[e];t.loop>=0&&t.count>=t.loop&&this.timerList.splice(e,1)}}destroy(){this.clerTime(),this.timerList=[],this.id=1,this.timer=null}}function Me(e,t){var i={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(i[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var s=0;for(r=Object.getOwnPropertySymbols(e);sPromise.resolve({net_type:0,net_connect:!0}),onNetworkStatusChange(e){},offNetworkStatusChange(){}},Ae={isActive:()=>!0,getStatus:()=>0,setStatus(e){},destroy(){}},Oe={setLogger:function(e){throw new Error("setLogger not implemented.")},platform:"",WebSocket:class{constructor(e,t){throw this.CONNECTING=0,this.OPEN=1,this.CLOSING=2,this.CLOSED=3,this.binaryType="",new Error("Method not implemented.")}close(e,t){throw new Error("Method not implemented.")}send(e){throw new Error("Method not implemented.")}onclose(e){throw new Error("Method not implemented.")}onerror(e){throw new Error("Method not implemented.")}onmessage(e){throw new Error("Method not implemented.")}onopen(e){throw new Error("Method not implemented.")}},localStorage:{},request:function(e,t){throw new Error("request not implemented.")},uploadFile:function(e){throw new Error("uploadFile not implemented.")},getSystemInfo:function(){throw new Error("getSystemInfo not implemented.")},getFileUploadInformation(e){throw new Error("getFileUploadInformation not implemented.")},envPayload:{},net:Ce,powerMonitor:Ae,logStorage:class{constructor(e){}open(){return Promise.resolve()}close(){}addLogs(e){return Promise.resolve()}extractLogs(){return Promise.resolve()}afterUpload(){return Promise.resolve()}}},Re=["error","warn","log","debug"],be=function(){},ke=["off","error","warn","log","debug"];class Le{constructor(e,t={}){this.storageArr=[],this.debugLevel="off",this.timer=0,this.strategies={debug:{name:"debg",func:console.log},log:{name:"info",func:console.log},warn:{name:"warn",func:console.warn},error:{name:"erro",func:console.error}},this.debug=be,this.log=be,this.warn=be,this.error=be,this.iid=Math.round(1e3*Math.random()),this.debugLevel=ke.includes(e)?e:"off",t.debugLevel&&(this.debugLevel=ke.includes(t.debugLevel)?t.debugLevel:this.debugLevel),this.logStorage=!1===t.storageEnable?null:new Oe.logStorage(null==t?void 0:t.storageName),this.setOptions(t),this.setLogFunc(this.debugLevel),this.setTimer(),Oe.setLogger(this),this.open()}getDebugMode(){return"debug"===this.debugLevel}open(){this.logStorage&&this.logStorage.open().then(()=>{this.log("Logger::open success")}).catch(e=>{this.warn("Logger::open failed",e)})}setOptions(e){if(e&&e.logFunc){var t=e.logFunc;for(var i in t){var r=i,s=t[r];s&&(this.strategies[r].func=s)}}}setLogFunc(e,t="log"){var i=Re.findIndex(t=>t===e),r=Re.findIndex(e=>e===t);Re.forEach((e,t)=>{this[e]=function(){if(!(t>i&&t>r)){var s=Array.prototype.slice.call(arguments),n=this.strategies[e],o=this.formatArgs(s,n.name);t<=r&&this.logStorage&&this.prepareSaveLog(o,e),t<=i&&n.func(o)}}})}extractLogs(){var e;return this.logStorage?null===(e=this.logStorage)||void 0===e?void 0:e.extractLogs():Promise.resolve("")}afterUpload(){var e;return this.logStorage?null===(e=this.logStorage)||void 0===e?void 0:e.afterUpload():Promise.resolve("")}prepareSaveLog(e,t){this.storageArr.push({text:e,level:t,time:Date.now(),iid:this.iid}),this.timer||this.setTimer(),this.storageArr.length>=100&&(this.triggerTimer(),this.storageArr=[])}saveLogs(){return Te(this,void 0,void 0,function*(){if(this.logStorage){var e=this.storageArr;this.storageArr=[];try{yield this.logStorage.addLogs(e)}catch(e){}}})}clearTimer(){this.timer&&clearTimeout(this.timer),this.timer=0}setTimer(){this.clearTimer(),this.timer=setTimeout(this.triggerTimer.bind(this),5e3)}triggerTimer(){this.clearTimer(),this.saveLogs()}formatArgs(e,t){var i=new Date;return`[NIM ${this.iid} ${t} ${i.getMonth()+1}-${i.getDate()} ${i.getHours()}:${i.getMinutes()}:${i.getSeconds()}:${i.getMilliseconds()}] `+e.map(e=>e instanceof pe?e.toString():e instanceof Error?e&&e.message?e.message:e:"object"==typeof e?JSON.stringify(e):e).join(" ")}destroy(){this.debug=be,this.log=be,this.warn=be,this.error=be,this.saveLogs(),this.clearTimer(),this.storageArr=[],this.logStorage&&this.logStorage.close()}}function Ve(e,t){if("object"!=typeof e||null===e)return e;for(var i=(t=t||"").split("."),r=0;r{}),t=t||{}){var n=r(e[s],t[s]);e[s]=void 0===n?t[s]:n}for(var o in i){var a=r(e[o],i[o]);e[o]=void 0===a?i[o]:a}return e}({},e,t,function(e,t){return void 0===t?e:t})}function xe(){return Promise.resolve()}function Fe(){}function Be(e){var t=e.lastIndexOf("."),i=t>-1?e.slice(t+1):"";return/^\d+$/.test(i.trim())&&(i=""),i}function je(e,t,i){return 0===e.length||e[0][t]<=i?0:e[e.length-1][t]>i?e.length:e.findIndex((r,s)=>{if(e[s-1]&&e[s-1][t]>i&&i>=r[t])return!0})}function Ge(e,t,i,r){var s="number"==typeof Ve(e,"raw.r[0]")?`${e.raw.r[0]}`:void 0;return t[i]=t[i]||s||r,t}class $e{constructor(e){this.lastSuccUploadHost="",this.core=e}getFileUploadInformation(e){return Oe.getFileUploadInformation(e)}request(e,t,i){var r=(new Date).getTime(),s=(null==i?void 0:i.exception_service)||0;return Oe.request(e,t).catch(i=>{var n,o,a,c,d=i;throw this.core.reporter.reportTraceStart("exceptions",{user_id:this.core.options.account||(null===(o=null===(n=this.core)||void 0===n?void 0:n.auth)||void 0===o?void 0:o.account),trace_id:null===(c=null===(a=this.core.clientSocket)||void 0===a?void 0:a.socket)||void 0===c?void 0:c.sessionId,start_time:r,action:1,exception_service:s}),this.core.reporter.reportTraceUpdateV2("exceptions",{code:"number"==typeof d.code?d.code:0,description:d.message||`${d.code}`,operation_type:0,target:e,context:t?JSON.stringify(t):""},{asyncParams:Oe.net.getNetworkStatus()}),this.core.reporter.reportTraceEnd("exceptions",1),i})}uploadFile(e,t){var i,r,s,n;return Te(this,void 0,void 0,function*(){for(var o="BROWSER"===Oe.platform,a=o?e.chunkUploadHostBackupList:e.commonUploadHostBackupList,c=o?e.chunkUploadHost:e.commonUploadHost,d=a.indexOf(c),l=-1===d?[c,...a]:[c,...a.slice(0,d),...a.slice(d+1)],h=Math.max(l.indexOf(this.lastSuccUploadHost),0),p=null,u=0;u200||e.errCode>200))throw e}}var He="https://abt-online.netease.im/v1/api/abt/client/getExperimentInfo";class Ye{constructor(e,t){this.abtInfo={},this.core=e,this.config=Ue({isAbtestEnable:!0,abtestUrl:He,abtestProjectKey:"imElite_sdk_abtest_web"},t)}setOptions(e){this.config=Ue(this.config,e)}abtRequest(){var e,t;return Te(this,void 0,void 0,function*(){if(this.config.isAbtestEnable&&!this.abtInfo.experiments&&this.config.abtestUrl){var i;try{i=yield this.core.adapters.request(this.config.abtestUrl,{method:"POST",dataType:"json",headers:{sdktype:"ABTest"},data:{clientInfo:{projectKey:this.config.abtestProjectKey,appKey:this.core.options.appkey,osType:"Web",sdkVersion:"10.9.50",deviceId:this.core.config.deviceId},useLocalCache:!0}},{exception_service:7})}catch(e){this.core.logger.warn("ABTest request failed")}this.abtInfo=(null===(t=null===(e=null==i?void 0:i.data)||void 0===e?void 0:e.data)||void 0===t?void 0:t.abtInfo)||{}}})}}class qe{constructor(){this.abortFns=[]}add(e){var t=function(e){var t={},i=new Promise(function(e,i){t.abort=i});return t.promise=Promise.race([e,i]),t}(e);return this.abortFns.push(t.abort),t.promise}clear(e){this.abortFns.forEach(t=>t(e||new pe({code:de.V2NIM_ERROR_CODE_CANCELLED,detail:{reason:"Aborted"}}))),this.abortFns=[]}destroy(){this.clear()}}var Ke={tolerantRTT:3e3,bestRTT:100,maxChances:5,enable:!0},We={timestamp:0,rtt:0,baseClock:0,baseTime:0};class Je{constructor(e,t,i="getServerTime"){this.serverOrigin=We,this.config=Ke,this.isSettingNTP=!1,this.currentChance=0,this.failedDelay=2e3,this.successDelay=3e5,this.timer=0,this.cmdName="getServerTime",this.core=e,this.logger=e.logger,this.promiseManager=new qe,this.cmdName=i,t&&this.setOptions(t)}setOptions(e){this.config=Object.assign({},Ke,this.config,e)}reset(){this.timer&&clearTimeout(this.timer),this.promiseManager.clear(),this.serverOrigin=We,this.currentChance=0}setOriginTimetick(){return Te(this,void 0,void 0,function*(){if(this.config.enable&&!(this.isSettingNTP||this.currentChance>=this.config.maxChances)){var e=Ve(this.core,"auth.status"),t=Ve(this.core,"status"),i=Ve(this.core,"V2NIMLoginService.lifeCycle.loginStatus");if("logined"===e||"logined"===t||1===i){this.isSettingNTP=!0,this.currentChance++,this.timer&&clearTimeout(this.timer),this.timer=0;var r,s="TimeOrigin::setOriginTimetick:",n=Date.now();this.core.logger.debug(`${s} getServerTime start, times ${this.currentChance}`);try{r=Ve(yield this.promiseManager.add(this.core.sendCmd(this.cmdName)),"content.time"),this.isSettingNTP=!1}catch(e){var o=e;return this.isSettingNTP=!1,this.logger.warn(`${s} Calculate Delay time, getServerTime error`,o),void(o.code!==de.V2NIM_ERROR_CODE_CANCELLED&&(clearTimeout(this.timer),this.timer=setTimeout(this.setOriginTimetick.bind(this),this.failedDelay)))}if(!r)return this.core.logger.warn(`${s} Calculate Delay time incorrect format`),void(this.config.enable=!1);var a=Date.now()-n;this.doSet(r,a)}}})}doSet(e,t){var i="TimeOrigin::setOriginTimetick:";t>this.config.tolerantRTT?(this.logger.warn(`${i} denied RTT:${t}`),clearTimeout(this.timer),this.timer=setTimeout(this.setOriginTimetick.bind(this),this.failedDelay)):t>this.config.bestRTT?(this.serverOrigin.rtt&&t>=this.serverOrigin.rtt?this.logger.warn(`${i} ignore RTT:${t}`):(this.setServerOrigin(t,e),this.logger.log(`${i} accept reluctantly RTT:${t}`)),clearTimeout(this.timer),this.timer=setTimeout(this.setOriginTimetick.bind(this),this.failedDelay)):(this.setServerOrigin(t,e),this.logger.debug(`${i} accept best RTT:${t}`),this.currentChance=0,clearTimeout(this.timer),this.timer=setTimeout(this.setOriginTimetick.bind(this),this.successDelay))}getNTPTime(e){if(void 0===e&&(e=this.getTimeNode()),this.checkNodeReliable(e)){var t=Math.floor(e.time-this.serverOrigin.baseTime);return this.serverOrigin.timestamp+t}return Date.now()}checkNodeReliable(e){if(void 0===e&&(e=this.getTimeNode()),this.serverOrigin.timestamp){if(0===this.serverOrigin.baseClock)return!0;var t=e.clock-this.serverOrigin.baseClock,i=e.time-this.serverOrigin.baseTime;return Math.abs(i-t)<500}return!1}checkPerformance(){return"BROWSER"===Oe.platform&&!("undefined"==typeof performance||!performance.now)}static checkPerformance(){return"BROWSER"===Oe.platform&&!("undefined"==typeof performance||!performance.now)}getTimeNode(){return{clock:this.checkPerformance()?performance.now():0,time:Date.now()}}static getTimeNode(){return{clock:Je.checkPerformance()?performance.now():0,time:Date.now()}}setServerOrigin(e,t){this.serverOrigin={timestamp:t+Math.floor(e/2),rtt:e,baseClock:this.checkPerformance()?performance.now():0,baseTime:Date.now()}}}var ze={user_id:"",trace_id:"",action:7,exception_service:6,duration:0,start_time:0,state:1,extension:[]};class Xe{constructor(e,t){this.traceData=ze,this.core=e,this.traceData=Object.assign({},ze,t),this.traceData.extension=[]}reset(){this.traceData=Object.assign({},ze),this.traceData.extension=[]}start(){var e,t;this.reset(),this.traceData.user_id=this.core.account,this.traceData.trace_id=(null===(t=null===(e=this.core.clientSocket)||void 0===e?void 0:e.socket)||void 0===t?void 0:t.sessionId)||"",this.traceData.start_time=(new Date).getTime()}update(e){return Te(this,void 0,void 0,function*(){var{net_type:t,net_connect:i}=yield Oe.net.getNetworkStatus();this.traceData.extension.push(Object.assign({code:0,foreground:!0,foreg_backg_switch:!1,net_type:t,net_connect:i},e))})}end(e){var t=this.traceData.extension[0],i=this.traceData.extension[1];if(t&&0===t.operation_type&&i&&1===i.operation_type){var r=t.net_type!==i.net_type||t.net_connect!==i.net_connect;if(e||!r)return this.traceData.duration=(new Date).getTime()-this.traceData.start_time,this.core.reporter.report("exceptions",this.traceData),void this.reset();this.reset()}else this.reset()}}var Qe={user_id:"",trace_id:"",net_connect:!0,net_type:0,duration:0,start_time:0,history:[],succeed:!1};class Ze{constructor(e){this.traceData=Qe,this.core=e,this.reset()}reset(){this.traceData=Object.assign({},Qe),this.traceData.history=[]}start(e){this.reset(),this.traceData.user_id=e,this.traceData.start_time=Date.now()}updateBegin(e){this.traceData.history.push(Object.assign({head:"",body:"",start_time:Date.now(),httpdns:!1,index:0},e))}updateComplete(e){this.traceData.history.forEach(t=>{t.target===e.target&&(Object.assign(t,e),t.duration=Date.now()-t.start_time)})}end(e){return Te(this,void 0,void 0,function*(){if(this.traceData.succeed=e,this.traceData.history=this.traceData.history.filter(e=>void 0!==e.code),0!==this.traceData.history.length){this.traceData.duration=Date.now()-this.traceData.start_time;var{net_type:t,net_connect:i}=yield Oe.net.getNetworkStatus();this.traceData.net_type=t,this.traceData.net_connect=i,this.core.reporter.report("nim_sdk_lbs_records",this.traceData),this.reset()}else this.reset()})}}function et(e){var t,i,r=!0;return"boolean"==typeof(null===(t=null==e?void 0:e.reporterConfig)||void 0===t?void 0:t.enableCompass)?r=e.reporterConfig.enableCompass:"boolean"==typeof(null===(i=null==e?void 0:e.reporterConfig)||void 0===i?void 0:i.isDataReportEnable)&&(r=e.reporterConfig.isDataReportEnable),r}var it={},rt={},st={},nt={apiVersion:"v1",debugLevel:"off",needReconnect:!0,reconnectionAttempts:Number.MAX_SAFE_INTEGER,lbsUrls:["https://lbs.netease.im/lbs/webconf.jsp"],linkUrl:"weblink.netease.im:443",abtestUrl:He,isAbtestEnable:!0};class ot extends ne{constructor(e,t={}){if(super(),this.instanceName="NIM",this.pluginMap={},this.eventBus=new ne,this.options={},this.V2NIMConversationIdUtil={},this.V2NIMMessageCreator={},this.V2NIMMessageAttachmentCreator={},this.V2NIMClientAntispamUtil={},this.DataStructureConverter={},this.V2NIMMessageConverter={},this.V2NIMMessageLogUtil={},this.V2NIMMessageExtendUtil={},this.V2NIMStorageUtil={},this.V2NIMNotificationService={},this.V2NIMStorageService={},this.auth={},this.V1NIMLoginService={},this.V2NIMLoginService={},this.clientSocket={},this.V2NIMSyncService={},this.V2NIMLocalConversationService={},this.V2NIMConversationService={},this.V2NIMConversationGroupService={},this.V2NIMMessageService={},this.V2NIMTeamService={},this.V2NIMUserService={},this.V2NIMFriendService={},this.V2NIMSettingService={},this.V2NIMAIService={},this.V2NIMSignallingService={},this.V2NIMSubscriptionService={},this.V2NIMPassthroughService={},this.YSFService={},this.offlinePush={},this.sync={},this.msg={},this.msgLog={},this.session={},this.cloudSession={},this.misc={},this.user={},this.friend={},this.systemMessage={},this.team={},this.event={},this.msgExtend={},this.cloudStorage={},this.passThrough={},this.superTeam={},this.plugin={},this.signaling={},this.qchatChannel={},this.qchatMedia={},this.qchatMsg={},this.qchatRole={},this.qchatServer={},this.pluginMap=st,this.logger=new Le(e.debugLevel,t.loggerConfig),t.privateConf){var{authConfig:i,cloudStorageConfig:r,reporterConfig:s}=this.getConfigFromPrivate(t.privateConf);Object.assign(e,i),this.setInitOptions(e),this.otherOptions=Object.assign(Object.assign({},t),{cloudStorageConfig:Object.assign(Object.assign({storageKeyPrefix:"NIM"},t.cloudStorageConfig),r),reporterConfig:Object.assign(Object.assign({},t.reporterConfig),s),V1NIMLoginServiceConfig:Object.assign(Object.assign(Object.assign({},e),t.V1NIMLoginServiceConfig),i),V2NIMLoginServiceConfig:Object.assign(Object.assign({},t.V2NIMLoginServiceConfig),i)})}else this.setInitOptions(e),this.otherOptions=Object.assign(Object.assign({},t),{V1NIMLoginServiceConfig:Object.assign(Object.assign({},e),t.V1NIMLoginServiceConfig),cloudStorageConfig:Object.assign({storageKeyPrefix:"NIM"},t.cloudStorageConfig)});this.timerManager=new Ee,this.timeOrigin=new Je(this),this.adapters=new $e(this),this.abtest=new Ye(this,Object.assign(Object.assign({isAbtestEnable:this.options.isAbtestEnable,abtestUrl:this.options.abtestUrl},this.otherOptions.abtestConfig),{abtestProjectKey:"imElite_sdk_abtest_web"}));var n=Oe.getSystemInfo(),o=function(e,t){var i,r,s=null===(i=null==t?void 0:t.reporterConfig)||void 0===i?void 0:i.compassDataEndpoint,n=null===(r=null==t?void 0:t.reporterConfig)||void 0===r?void 0:r.reportConfigUrl;if(s)return s;if(n){var o=n.match(/^https:\/\/([^/]+)\/*/);if(Array.isArray(o)&&o.length>=1)return`https://${o[1]}`;e.error(`Invalid reportConfigUrl: ${n}`)}return we()?"https://statistic.live.126.net":"https://statistic.live.126.net,https://statistic-overseas.yunxinfw.com"}(this.logger,this.otherOptions);this.reporter=new oe(Object.assign(Object.assign({},o?{compassDataEndpoint:o}:{}),{isDataReportEnable:et(this.otherOptions),common:{app_key:e.appkey,dev_id:"",platform:"Web",sdk_ver:"10.9.50",env:"online",os_name:n.os,os_ver:n.osVer,lib_env:n.libEnv,host_env:n.hostEnv,host_env_ver:n.hostEnvVer,manufactor:n.manufactor,model:n.model,v2:"v1"!==this.options.apiVersion},request:Oe.request,logger:this.logger,autoStart:!0})),this.reporterHookLinkKeep=new Xe(this),this.reporterHookLBS=new Ze(this),this.getServiceKeys(Object.keys(it)).forEach(e=>{if(!this[e]||!this[e].name){var t=it[e];this[e]=new t(this)}}),Object.keys(it).forEach(e=>{this.callSetOptions(e)}),Object.keys(rt).forEach(e=>{var t=rt[e];void 0!==t&&(this[e]=new t(this))}),ot.instance=this,this.logger.log(`NIM init, version:10.9.50, sdk version:100950, appkey:${e.appkey}`)}getServiceKeys(e){var t=e.findIndex(e=>"V1NIMLoginService"===e);if(t>-1){var i=e[t];e.splice(t,1),"v1"===this.options.apiVersion&&e.unshift(i)}var r=e.findIndex(e=>"V2NIMLoginService"===e);if(r>-1){var s=e[r];e.splice(r,1),"v2"===this.options.apiVersion&&e.unshift(s)}var n=e.findIndex(e=>"sync"===e);if(n>-1){var o=e[n];e.splice(n,1),"v1"===this.options.apiVersion&&e.push(o)}var a=e.findIndex(e=>"V2NIMSyncService"===e);if(a>-1){var c=e[a];e.splice(a,1),"v2"===this.options.apiVersion&&e.push(c)}return e}static getInstance(e,t){if(!ot.instance){if(e)return new ot(e,t);throw new Error("Instance not exist, please input options")}if(e){if(ot.instance.options.account===e.account&&ot.instance.options.appkey===e.appkey)return ot.instance.setOptions(e),ot.instance;throw new Error("Unexpected login")}return ot.instance}setInitOptions(e){_e({appkey:{type:"string"},apiVersion:{type:"enum",values:["v1","v2"],required:!1},binaryWebsocket:{type:"boolean",required:!1},needReconnect:{type:"boolean",required:!1},reconnectionAttempts:{type:"number",required:!1},customClientType:{type:"number",min:1,required:!1},authType:{type:"number",min:0,max:2,required:!1},lbsUrls:{type:"array",itemType:"string",min:1,required:!1},linkUrl:{type:"string",allowEmpty:!1,required:!1}},e),this.options=Object.assign(Object.assign({},nt),e)}getConfigFromPrivate(e){var t;return e?{authConfig:JSON.parse(JSON.stringify({appkey:e.appkey||void 0,lbsUrls:e.weblbsUrl?[e.weblbsUrl]:void 0,linkUrl:e.link_web||void 0,linkSSL:null!==(t=e.websdkSsl)&&void 0!==t?t:void 0})),cloudStorageConfig:JSON.parse(JSON.stringify({chunkUploadHost:e.nos_uploader||void 0,commonUploadHost:e.nos_uploader||void 0,commonUploadHostBackupList:e.nos_uploader?[e.nos_uploader]:void 0,chunkUploadHostBackupList:e.nos_uploader?[e.nos_uploader]:void 0,uploadReplaceFormat:e.nos_downloader_v2?`${e.nosSsl?"https://":"http://"}${e.nos_downloader_v2}`:void 0,downloadUrl:void 0!==e.nos_accelerate?e.nos_accelerate:void 0,downloadHostList:""===e.nos_accelerate_host?[]:"string"==typeof e.nos_accelerate_host?[e.nos_accelerate_host]:Array.isArray(e.nos_accelerate_host)?e.nos_accelerate_host:void 0})),reporterConfig:JSON.parse(JSON.stringify({enableCompass:"boolean"==typeof e.enableCompass?e.enableCompass:void 0,compassDataEndpoint:e.compassDataEndpoint||void 0}))}:{authConfig:{},cloudStorageConfig:{},reporterConfig:{}}}connect(e={}){return this.V1NIMLoginService.login(e)}setOptions(e){if("object"==typeof e&&null!==e){if(Object.prototype.hasOwnProperty.call(e,"account")&&e.account!==this.options.account||Object.prototype.hasOwnProperty.call(e,"appkey")&&e.appkey!==this.options.appkey)throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"NIM::setOptions account and appkey is not allowed to reset"}});if(Object.prototype.hasOwnProperty.call(e,"apiVersion")&&e.apiVersion!==this.options.apiVersion)throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"NIM::setOptions apiVersion is not allowed to reset"}});if(Object.prototype.hasOwnProperty.call(e,"binaryWebsocket")&&e.binaryWebsocket!==this.options.binaryWebsocket)throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"NIM::setOptions binaryWebsocket is not allowed to reset"}});_e({token:{type:"string",required:!1},needReconnect:{type:"boolean",required:!1},reconnectionAttempts:{type:"number",required:!1},customClientType:{type:"number",min:1,required:!1},authType:{type:"number",min:0,max:2,required:!1},lbsUrls:{type:"array",itemType:"string",min:1,required:!1},linkUrl:{type:"string",allowEmpty:!1,required:!1}},e),this.logger.log("NIM::setOptions options is",e),this.options=Object.assign(Object.assign({},this.options),e),this.V1NIMLoginService.setOptions&&this.V1NIMLoginService.setOptions(this.options)}}getOptions(){return this.options}disconnect(){return this.V1NIMLoginService.logout()}_disconnect(){return"v1"===this.options.apiVersion?this.V1NIMLoginService.logout():"v2"===this.options.apiVersion?0===Ve(this.V2NIMLoginService,"lifeCycle.connectStatus")&&0===Ve(this.V2NIMLoginService,"lifeCycle.loginStatus")?Promise.resolve():this.V2NIMLoginService.logout():Promise.resolve()}destroy(){return ot.instance=void 0,this._disconnect().then(()=>{this.status="destroyed",this.removeAllListeners(),this.eventBus.removeAllListeners(),this.logger.destroy(),this.reporter.destroy(),this.timerManager.destroy(),this._clearModuleData("destroy"),this._removeAllModuleListeners(),this.connect=xe,this.disconnect=xe,this._disconnect=xe,this.destroy=xe})}_clearModuleData(e="logout"){Object.values(this).forEach(t=>{t&&"function"==typeof t.reset&&t.reset(e)})}_removeAllModuleListeners(){Object.values(this).forEach(e=>{e&&"function"==typeof e.removeAllListeners&&e.removeAllListeners()})}kick(e){return this.V1NIMLoginService.kick(e)}sendCmd(e,t,i){return this.clientSocket.sendCmd(e,t,i)}emit(e,...t){try{var i=Date.now(),r=super.emit(e,...t),s=Date.now()-i;return s>=10&&this.logger.warn(`Core::emit event: ${e} process takes: ${s}ms`),r}catch(t){return this.logger.error(`Core::emit event: ${e}. Error: ${t}`),setTimeout(()=>{throw this.logger.error(`Core::emit throw error in setTimeout. event: ${e}. Error: ${t}`),t},0),!1}}get account(){return this.auth.account}get status(){return this.V1NIMLoginService.status}set status(e){this.V1NIMLoginService.status=e}get config(){return{timeout:8e3,deviceId:this.auth.deviceId}}_registerDep(e,t){this[t]&&this[t].name||(this[t]=new e(this),this.callSetOptions(t))}callSetOptions(e){var t=`${e}Config`,i=`${e}Options`,r=this.otherOptions[t]||this.otherOptions[i]||{},s=Ve(this,`${e}.setOptions`);"function"==typeof s&&("cloudStorage"===e&&(r=this.otherOptions[t]||this.otherOptions.serverConfig||{}),s.call(this[e],r))}static registerService(e,t){it[t]=e}static registerPrivateService(e,t){rt[t]=e}static registerPlugin(e,t){st[t]=e}}ot.sdkVersion=100950,ot.sdkVersionFormat="10.9.50";var at={},ct={};function dt(e,t,i,r){var s=at[e];if(!s)return i.error("createCmd:: can not find cmd config: ",e),null;var n={SER:t,SID:s.sid,CID:s.cid,Q:[]};return s.params&&r&&s.params.forEach(function(e){var t=r[e.name];if(null!=t){var i=e.type,{reflectMapper:s,select:o}=e;switch(e.type){case"PropertyArray":i="ArrayMable",t=t.map(e=>({t:"Property",v:s?pt(e,s,o):e}));break;case"Property":t=s?pt(t,s,o):t;break;case"Bool":t=t?"true":"false"}n.Q.push({t:i,v:t})}}),{packet:n,hasPacketResponse:"boolean"!=typeof s.hasPacketResponse||s.hasPacketResponse,hasPacketTimer:"boolean"!=typeof s.hasPacketTimer||s.hasPacketTimer}}function lt(e,t){var i;try{i=JSON.parse(e)}catch(i){return void t.error(`Parse command error:"${e}"`)}var r=i.sid+"_"+i.cid,s=i.r;if(["4_1","4_2","4_10","4_11"].includes(r)){var n=i.r[1].headerPacket;r=`${n.sid}_${n.cid}`,i.sid=n.sid,i.cid=n.cid,s=i.r[1].body}var o=ct[r],a=[];if(o&&o.length>0){for(var c of o)a.push(ht(i,c.config,c.cmd,s,t));return a}t.error("parseCmd:: mapper not exist",r,i.code)}function ht(e,t,i,r,s){var n,o={cmd:i,raw:e,error:null,service:null==t?void 0:t.service,content:{},__receiveTimeNode:Je.getTimeNode()};(18===t.sid||t.sid>=26&&t.sid<100)&&(e.code=function(e){if("number"!=typeof e||e!=e)throw new pe({code:de.V2NIM_ERROR_CODE_INTERNAL,detail:{reason:"Read code failed",rawData:`${e}`}});if(e<0||e>=0&&e<1e3||e>=2e4&&e<=20099)return e;var t=(65535&e)>>9;return 1e5+1e3*(t-=t<=38?1:2)+(511&e)}(e.code));var a=function(e,t){var i=le[e],r=ve[e];return null===r?null:new pe({code:e,desc:i||r||e,detail:{cmd:t,timetag:Date.now()}})}(e.code,i);if(o.error=a,o.error){if(o.error.detail.cmd=i,!(null===(n=null==t?void 0:t.ignoreErrCodes)||void 0===n?void 0:n.includes(e.code)))return o;s.warn("parseCmd:: ignore error ",o.error),o.error.detail.ignore=!0}return t.response&&t.response.forEach((e,t)=>{var i=r[t],s=e.type,n=e.name,a=e.reflectMapper;if(void 0!==i)switch(s){case"Property":o.content[n]=a?ut(i,a):i;break;case"PropertyArray":o.content[n]=i.map(e=>a?ut(e,a):e);break;case"Int":case"Long":case"Byte":o.content[n]=+i;break;case"Bool":o.content[n]="true"===i||!0===i||1===i;break;default:o.content[n]=i}}),o}function pt(e,t,i){var r={};for(var s in e=function(e,t){var i={};for(var r in t){var s=t[r],n="number"==typeof s?r:s.access?s.access:r,o=n.split("."),a=e;for(var c of o){if(void 0===a[c]||null===a[c]){a=void 0;break}a=a[c]}void 0!==a&&(i[n]=a)}return i}(e,t),t){var n=t[s],o="number"==typeof n?s:n.access?n.access:s;if(!i||i.includes(s))if(o in e){if("number"==typeof n)r[n]=e[o];else if("object"==typeof n)if(n.converter){var a=n.converter(e[o],e);void 0!==a&&(r[n.id]=a)}else r[n.id]=e[o]}else"object"==typeof n&&n.def&&("function"==typeof n.def?r[n.id]=n.def(e):r[n.id]=n.def)}return r}function ut(e,t){var i={};for(var r in e){var s=t[r];if("string"==typeof s)i[s]=e[r];else if("object"==typeof s&&"prop"in s){var n=s.access?s.access:s.prop;if(s.converter){var o=s.converter(e[r],e);void 0!==o&&(i[n]=o)}else s.type&&"number"===s.type?i[n]=+e[r]:s.type&&"boolean"===s.type?i[n]=!("0"===e[r]||!e[r]):i[n]=e[r]}}for(var a in t){var c=t[a];if(c&&void 0!==c.def){var d=c.access?c.access:c.prop;d in i||("function"==typeof c.def?i[d]=c.def(e):i[d]=c.def)}}return i=function(e){var t={},i=function(i){var r=i.split(".");r.reduce(function(t,s,n){return t[s]||(t[s]=isNaN(Number(r[n+1]))?r.length-1==n?e[i]:{}:[])},t)};for(var r in e)i(r);return t}(i),i}function mt(e){for(var t in Object.assign(at,e.cmdConfig),e.cmdMap){var i=e.cmdMap[t],r=e.cmdConfig[i];if(r)if(Array.isArray(ct[t])){var s=!1;for(var n of ct[t])if(n.cmd===i&&n.config.service===r.service){s=!0;break}s||ct[t].push({config:r,cmd:i})}else ct[t]=[{config:r,cmd:i}]}}function gt(e){var t={};for(var i in e){var r=e[i];"number"==typeof r?t[r]=i:"object"==typeof r&&(t[r.id]={prop:i,type:r.retType,access:r.retAccess?r.retAccess:r.access?r.access:i,def:r.retDef,converter:r.retConverter})}return t}function vt(e){return e?1:0}function ft(e){if(e&&"object"==typeof e)try{return JSON.stringify(e)}catch(e){return}}function _t(e){if(e&&"string"==typeof e)try{return JSON.parse(e)}catch(e){return}}function It(e,t){if(!Se(t))return{};var i=JSON.parse(JSON.stringify(t)),r=yt(e,i);return JSON.parse(JSON.stringify(Object.assign(Object.assign({},i),r)))}function yt(e,t){if(!Se(t))return{};var i={};return Object.keys(e).forEach(r=>{var s=e[r].type;if("string"!=typeof s){var n=yt(e[r],t);Object.keys(n).length>0&&(i[r]=n)}else{var o=e[r],a=o.rawKey||r,c=Et[s](t,a,o);void 0!==c&&(t[a]=void 0,i[r]=c)}}),i}var Et={number:function(e,t){if(void 0!==e[t])return+e[t]},string:function(e,t){if(void 0!==e[t])return e[t]},boolean:function(e,t){return+e[t]>0||0!=+e[t]&&void 0},enum:function(e,t,i){return i.values[e[t]]},object:function(e,t){if(void 0!==e[t])try{return JSON.parse(e[t])}catch(e){return{}}}};function Mt(e){return It({type:{type:"number"},port:{type:"number"},customClientType:{type:"number"},timestamp:{type:"number"},loginType:{type:"number"}},e)}var Tt={"26_3":"v2Login","26_5":"v2Logout","26_8":"v2KickOffline","26_9":"v2BeKicked","26_10":"v2LoginClientChange","36_1":"v2GetChatroomLinkAddress"},St={"1_2":"heartbeat","2_7":"nimLoginClientChange","24_8":"qchatLoginClientChange"},Nt={webLoginReqTag:{clientType:3,os:4,sdkVersion:6,appLogin:8,protocolVersion:9,pushTokenName:10,pushToken:11,clientId:13,appkey:18,account:19,browser:24,clientSession:26,deviceInfo:32,isReactNative:112,customTag:38,customClientType:39,sdkHumanVersion:40,hostEnv:41,userAgent:42,libEnv:44,authType:115,thirdPartyExtension:116,env:119,isRoutable:120,token:1e3},mixAuthRepTag:{clientId:1,consid:2,clientIP:3,port:4,type:5,customClientType:6,timestamp:7,customTag:8,os:9,pushType:10,hasTokenPreviously:11,loginType:12},nimAuthRepTag:{type:3,os:4,mac:5,clientId:13,account:19,deviceInfo:32,customTag:38,customClientType:39,consid:102,clientIP:103,port:104,timestamp:109,pushType:110,hasTokenPreviously:111},qchatAuthRepTag:{clientId:8,consid:102,clientIP:103,port:104,type:6,customClientType:13,timestamp:105,os:30,pushType:100,hasTokenPreviously:101}},Ct={v2Login:{sid:26,cid:3,service:"auth",params:[{type:"Property",name:"tag",reflectMapper:Nt.webLoginReqTag}],response:[{type:"Property",name:"data",reflectMapper:gt(Nt.mixAuthRepTag)},{type:"PropertyArray",name:"loginClients",reflectMapper:gt(Nt.mixAuthRepTag)}]},v2Logout:{sid:26,cid:5,service:"auth"},v2KickOffline:{sid:26,cid:8,service:"auth",params:[{type:"StrArray",name:"clientIds"}],response:[{type:"StrArray",name:"clientIds"}]},v2BeKicked:{sid:26,cid:9,service:"auth",response:[{type:"Int",name:"clientType"},{type:"Int",name:"reason"},{type:"String",name:"reasonDesc"},{type:"Int",name:"customClientType"}]},v2LoginClientChange:{sid:26,cid:10,service:"auth",response:[{type:"Byte",name:"state"},{type:"PropertyArray",name:"datas",reflectMapper:gt(Nt.mixAuthRepTag)}]},v2GetChatroomLinkAddress:{sid:36,cid:1,service:"auth",params:[{type:"Long",name:"roomId"},{type:"Bool",name:"miniProgram"}],response:[{type:"StrArray",name:"linkAddress"}]}},At={heartbeat:{sid:1,cid:2,service:"auth"},nimLoginClientChange:{sid:2,cid:7,service:"auth",response:[{type:"Byte",name:"state"},{type:"PropertyArray",name:"datas",reflectMapper:gt(Nt.nimAuthRepTag)}]},qchatLoginClientChange:{sid:24,cid:8,service:"auth",response:[{type:"Byte",name:"state"},{type:"Property",name:"data",reflectMapper:gt(Nt.qchatAuthRepTag)}]}},Ot=Rt;function Rt(e){e=e||{},this.ms=e.min||100,this.max=e.max||1e4,this.factor=e.factor||2,this.jitter=e.jitter>0&&e.jitter<=1?e.jitter:0,this.attempts=0}Rt.prototype.duration=function(){var e=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var t=Math.random(),i=Math.floor(t*this.jitter*e);e=1&Math.floor(10*t)?e+i:e-i}return 0|Math.min(e,this.max)},Rt.prototype.reset=function(){this.attempts=0},Rt.prototype.setMin=function(e){this.ms=e},Rt.prototype.setMax=function(e){this.max=e},Rt.prototype.setJitter=function(e){this.jitter=e};var bt=function(e){var t;if(void 0!==e)return(t=Pt(e)).sign=1,t},kt=function(e){return"[object Array]"===Object.prototype.toString.call(e)},Lt=function(e){return["number"==typeof e,"string"==typeof e&&e.length>0,kt(e)&&e.length>0,e instanceof Pt].some(function(e){return!0===e})},Vt="Invalid Number";function Pt(e){var t;if(!(this instanceof Pt))return new Pt(e);if(this.number=[],this.sign=1,this.rest=0,Lt(e)){if(kt(e)){for((e.length&&"-"===e[0]||"+"===e[0])&&(this.sign="+"===e[0]?1:-1,e.shift(0)),t=e.length-1;t>=0;t--)if(!this.addDigit(e[t]))return}else for("-"!==(e=e.toString()).charAt(0)&&"+"!==e.charAt(0)||(this.sign="+"===e.charAt(0)?1:-1,e=e.substring(1)),t=e.length-1;t>=0;t--)if(!this.addDigit(parseInt(e.charAt(t),10)))return}else this.number=Vt}Pt.prototype.addDigit=function(e){return function(e){return/^\d$/.test(e)}(e)?(this.number.push(e),this):(this.number=Vt,!1)},Pt.prototype._compare=function(e){var t,i;if(!Lt(e))return null;if(t=Pt(e),this.sign!==t.sign)return this.sign;if(this.number.length>t.number.length)return this.sign;if(this.number.length=0;i--){if(this.number[i]>t.number[i])return this.sign;if(this.number[i]0},Pt.prototype.gte=function(e){return this._compare(e)>=0},Pt.prototype.equals=function(e){return 0===this._compare(e)},Pt.prototype.lte=function(e){return this._compare(e)<=0},Pt.prototype.lt=function(e){return this._compare(e)<0},Pt.prototype.subtract=function(e){var t;return void 0===e?this:(t=Pt(e),this.sign!==t.sign?(this.number=Pt._add(this,t),this):(this.sign=this.lt(t)?-1:1,this.number=bt(this).lt(bt(t))?Pt._subtract(t,this):Pt._subtract(this,t),this))},Pt._add=function(e,t){var i,r=0,s=Math.max(e.number.length,t.number.length);for(i=0;i0;i++)e.number[i]=(r+=(e.number[i]||0)+(t.number[i]||0))%10,r=Math.floor(r/10);return e.number},Pt._subtract=function(e,t){var i,r=0,s=e.number.length;for(i=0;i0;)i++;return i>0&&e.number.splice(-i),e.number},Pt.prototype.multiply=function(e){if(void 0===e)return this;var t,i,r=Pt(e),s=0,n=[];if(this.isZero()||r.isZero())return Pt(0);for(this.sign*=r.sign,t=0;t0;i++)n[t+i]=(s+=(n[t+i]||0)+this.number[t]*(r.number[i]||0))%10,s=Math.floor(s/10);return this.number=n,this},Pt.prototype.divide=function(e){if(void 0===e)return this;var t,i,r=Pt(e),s=[],n=Pt(0);if(r.isZero())return this.number="Invalid Number - Division By Zero",this;if(this.isZero())return this.rest=Pt(0),this;if(this.sign*=r.sign,r.sign=1,1===r.number.length&&1===r.number[0])return this.rest=Pt(0),this;for(t=this.number.length-1;t>=0;t--)for(n.multiply(10),n.number[0]=this.number[t],s[t]=0;r.lte(n);)s[t]++,n.subtract(r);for(t=0,i=s.length-1;0===s[i-t]&&i-t>0;)t++;return t>0&&s.splice(-t),this.rest=n,this.number=s,this},Pt.prototype.mod=function(e){return this.divide(e).rest},Pt.prototype.isZero=function(){var e;for(e=0;e=0;e--)t+=this.number[e];return this.sign>0?t:"-"+t};var Dt,wt=Math.pow(2,32);function Ut(e){for(var t=new Uint8Array(5),i=new DataView(t.buffer),r=0;4294967168&e;)i.setUint8(r++,127&e|128),e>>>=7;return i.setUint8(r++,127&e),t.slice(0,r)}class xt{constructor(e){this.offset=0,this.buffer=new Uint8Array(e),this.view=new DataView(e)}checkBufferBoundaryAccess(){return this.offset>=this.buffer.byteLength}length(){var e;return(null===(e=this.view)||void 0===e?void 0:e.byteLength)||0}getBuffer(){return this.view.buffer}getOffset(){return this.offset}popRaw(e){try{var t=this.buffer.slice(this.offset,this.offset+e);return this.offset+=e,t}catch(e){throw new Error(`UnpackException raw ${e&&e.message}`)}}popByte(){try{var e=this.view.getUint8(this.offset);return this.offset+=1,e}catch(e){throw new Error(`UnpackException byte ${e&&e.message}`)}}popVarbin(){return this.popRaw(this.popVarInt())}popString(){try{return function(e){return"function"==typeof TextDecoder?new TextDecoder("utf-8").decode(e):function(e){for(var t="",i=0;i0)for(var o=0;o5)throw new Error("Variable length quantity is too long")}while(128&i);return t}popLong(){try{var e=function(e,t=!1){var i=new DataView(e.buffer),[r,s]=t?[4,0]:[0,4],n=i.getUint32(r,t),o=i.getUint32(s,t);return n>0?n*wt+o:o}(this.buffer.slice(this.offset,this.offset+8),!0);return this.offset+=8,Number(e)}catch(e){throw new Error(`UnpackException long ${e&&e.message}`)}}popShort(){try{var e=this.view.getUint16(this.offset,!0);return this.offset+=2,e}catch(e){throw new Error(`UnpackException short ${e&&e.message}`)}}popBoolean(){return this.popByte()>0}toString(){return Array.from(new Uint8Array(this.buffer)).toString()}reset(){this.offset=0,this.buffer=null,this.view=null}}class Ft{constructor(e){this.packetLength=0,this.serviceId=0,this.commandId=0,this.serialId=0,this.tag=0,this.resCode=200,this.innerHeader=null,this.msgId=0,this.bodyArr=[],this.unpack=new xt(e)}reset(){this.innerHeader=null,this.bodyArr=[],this.unpack.reset()}getBodyDetail(){return this.bodyArr.join("")}unmarshalHeader(){var e=this._unmarshalHeader();this.packetLength=e.packetLength,this.serviceId=e.serviceId,this.commandId=e.commandId,this.serialId=e.serialId,this.tag=e.tag,this.resCode=e.resCode,4===e.serviceId&&[1,2,10,11].includes(e.commandId)&&(this.msgId=this.unmarshalLong(),this.innerHeader=this._unmarshalHeader())}_unmarshalHeader(){var e=this.unpack.popVarInt(),t=this.unpack.popByte(),i=this.unpack.popByte(),r=this.unpack.popShort(),s=this.unpack.popByte(),n=200;return this.hasRescode(s)&&(n=this.unpack.popShort()),{packetLength:e,serviceId:t,commandId:i,serialId:r,tag:s,resCode:n}}hasRescode(e){return 0!=((e=e||this.tag)&Ft.RES_CODE)}getHeader(){return{packetLength:this.packetLength,sid:this.serviceId,cid:this.commandId,ser:this.serialId,code:this.resCode}}getInnerHeader(){return this.innerHeader?{sid:this.innerHeader.serviceId,cid:this.innerHeader.commandId}:null}unmarshalProperty(){var e=this.unpack.popVarInt(),t={};this.bodyArr.push(`\nProperty(${e}) {`);for(var i=0;i0&&this.packetLength>this.unpack.length())throw new Error(`UnpackException packetLength(${this.packetLength}) greater than bufferLength(${this.unpack.length()})`);var i=[];return e&&e.forEach(e=>{if(!this.unpack.checkBufferBoundaryAccess())switch(e.type){case"PropertyArray":i.push(this.unmarshalPropertyArray());break;case"Property":i.push(this.unmarshalProperty());break;case"Byte":i.push(this.unpack.popByte());break;case"Int":i.push(this.unpack.popInt());break;case"Bool":i.push(this.unpack.popBoolean());break;case"Long":i.push(this.unmarshalLong());break;case"LongArray":i.push(this.unmarshalLongArray());break;case"String":i.push(this.unpack.popString());break;case"StrArray":i.push(this.unmarshalStrArray());break;case"StrStrMap":i.push(this.unmarshalStrStrMap());break;case"StrLongMap":i.push(this.unmarshalStrLongMap());break;case"LongLongMap":i.push(this.unmarshalLongLongMap());break;case"KVArray":i.push(this.unmarshalKVArray())}}),this.innerHeader?t.r[1].body=i:t.r=i,JSON.stringify(t)}}Ft.RES_CODE=2;class Bt{constructor(){this.offset=0,this.pageSize=1024,this.capacity=1048576,this.buffer=new Uint8Array(this.pageSize),this.view=new DataView(this.buffer.buffer)}reset(){this.offset=0,this.buffer=null,this.view=null}size(){return this.offset}getBuffer(){return this.buffer.slice(0,this.offset).buffer}ensureCapacity(e){var t=this.offset+e;if(t>this.capacity)throw new Error("PackException over limit");if(t>this.buffer.byteLength){var i=Math.ceil(t/this.pageSize)*this.pageSize,r=new Uint8Array(i);r.set(this.buffer),this.buffer=r,this.view=new DataView(this.buffer.buffer)}}putRaw(e){this.ensureCapacity(e.length);try{this.buffer.set(e,this.offset),this.offset+=e.length}catch(e){throw new Error("PackException raw")}}putByte(e){this.ensureCapacity(1);try{this.view.setUint8(this.offset++,e)}catch(e){throw new Error("PackException byte")}}putString(e){try{var t=function(e){if("function"==typeof TextEncoder)return(new TextEncoder).encode(e);var t=function(e){for(var t=[],i=e.length,r=0;r>n),n-=6;n>=0;)t.push(128|s>>n&63),n-=6;r+=s>=65536?2:1}return t}(e);return new Uint8Array(t)}(e);this.putVarbin(t)}catch(e){throw new Error("PackException string")}}putInt(e){this.ensureCapacity(4);try{this.view.setInt32(this.offset,e,!0),this.offset+=4}catch(e){throw new Error("PackException int")}}putVarInt(e){var t=Ut(e);this.putRaw(t)}putBoolean(e){this.ensureCapacity(1);try{this.view.setUint8(this.offset++,e?1:0)}catch(e){throw new Error("PackException boolean")}}putLong(e){this.ensureCapacity(8);try{var t=function(e,t=!1){var i=new Uint8Array(8),r=new DataView(i.buffer),s=Number(e>wt-1?e/wt:0),n=Number(4294967295&e),[o,a]=t?[4,0]:[0,4];return r.setUint32(o,s,t),r.setUint32(a,n,t),i}(e,!0);this.buffer.set(t,this.offset),this.offset+=8}catch(e){throw new Error("PackException long")}}putStringAsLong(e){this.ensureCapacity(8);try{var t=function(e,t=!1){var i=new Uint8Array(8),r=new DataView(i.buffer),s=Pt(e).divide(wt).number.reverse().join(""),n=Pt(e).mod(wt).number.reverse().join(""),o=Number(s),a=Number(n),[c,d]=t?[4,0]:[0,4];return r.setUint32(c,o,t),r.setUint32(d,a,t),i}(e,!0);this.buffer.set(t,this.offset),this.offset+=8}catch(e){throw new Error("PackException stringAsLong")}}putShort(e){this.ensureCapacity(2);try{this.view.setInt16(this.offset,e,!0),this.offset+=2}catch(e){throw new Error("PackException short")}}putVarbin(e){if(!e)return this.ensureCapacity(1),this.putVarInt(0);if(e.byteLength>Math.pow(2,31)-2)throw new Error("PackException varbin. too long");var t=Ut(e.length);this.ensureCapacity(t.length+e.length);try{this.buffer.set(t,this.offset),this.offset+=t.length,this.buffer.set(e,this.offset),this.offset+=e.length}catch(e){throw new Error("PackException varbin")}}}function jt(e){if("number"!=typeof e){if(null==e)return!1;e=Number(e)}if(isNaN(e))throw new Error("Number type conversion error");return!0}function Gt(e){return null==e}class $t{constructor(e,t,i){this.pack=new Bt,this.packetLength=0,this.serviceId=0,this.commandId=0,this.serialId=0,this.tag=0,this.serviceId=e,this.commandId=t,this.serialId=i}marshalHeader(){this.pack.putVarInt(this.packetLength),this.pack.putByte(this.serviceId),this.pack.putByte(this.commandId),this.pack.putShort(this.serialId),this.pack.putByte(this.tag)}marshalProperty(e){var t=Object.keys(e).filter(e=>!Gt(e));this.pack.putVarInt(t.length),t.forEach(t=>{this.pack.putVarInt(Number(t)),Array.isArray(e[t])||"[object Object]"===Object.prototype.toString.call(e[t])?this.pack.putString(JSON.stringify(e[t])):this.pack.putString(String(e[t]))})}marshalPropertyArray(e){var t=e.length;this.pack.putVarInt(t),e.forEach(e=>{this.marshalProperty(null==e?void 0:e.v)})}marshalStrArray(e){var t=e.filter(e=>!Gt(e)),i=t.length;this.pack.putVarInt(i),t.forEach(e=>{this.pack.putString(String(e))})}marshalLongArray(e){var t=e.filter(e=>jt(e)),i=t.length;this.pack.putVarInt(i),t.forEach(e=>{this.putLong(e)})}marshalStrStrMap(e){var t=Object.keys(e).filter(t=>!Gt(e[t])&&!Gt(t));this.pack.putVarInt(t.length),t.forEach(t=>{this.pack.putString(String(t)),this.pack.putString(String(e[t]))})}marshalStrLongMap(e){var t=Object.keys(e).filter(t=>jt(e[t])&&!Gt(t));this.pack.putVarInt(t.length),t.forEach(t=>{this.pack.putString(String(t)),this.putLong(e[t])})}marshalLongLongMap(e){var t=Object.keys(e).filter(t=>{var i=Number(t);return jt(i)&&jt(e[i])});this.pack.putVarInt(t.length),t.forEach(t=>{var i=Number(t);this.putLong(i),this.putLong(e[i])})}marshalKVArray(e){var t=e.length;this.pack.putVarInt(t),e.forEach(e=>{this.marshalStrStrMap(e)})}putLong(e){"string"==typeof e&&e.length>15?this.pack.putStringAsLong(e):this.pack.putLong(Number(e))}marshal(e,t){return this.marshalHeader(),t&&t.forEach((t,i)=>{var r,s=t.type,n=null===(r=e[i])||void 0===r?void 0:r.v;if(!Gt(n))switch(s){case"PropertyArray":this.marshalPropertyArray(n);break;case"Property":this.marshalProperty(n);break;case"Byte":if(!jt(n))return;this.pack.putByte(Number(n));break;case"Int":if(!jt(n))return;this.pack.putInt(Number(n));break;case"Bool":"false"===n?n=!1:"true"===n&&(n=!0),this.pack.putBoolean(n);break;case"Long":if(!jt(n))return;this.putLong(n);break;case"LongArray":this.marshalLongArray(n);break;case"String":this.pack.putString(String(n));break;case"StrArray":this.marshalStrArray(n);break;case"StrStrMap":this.marshalStrStrMap(n);break;case"StrLongMap":this.marshalStrLongMap(n);break;case"LongLongMap":this.marshalLongLongMap(n);break;case"KVArray":this.marshalKVArray(n)}}),this.pack.getBuffer()}reset(){this.pack.reset()}}class Ht extends ne{constructor(e,t,i){super(),this.websocket=null,this.socketConnectTimer=0,this.linkSSL=!0,this.url="",this.core=e,this.url=t,this.linkSSL=i,this.status="disconnected",this.logger=e.logger,this.connect()}connect(){"connecting"!==this.status&&"connected"!==this.status?(this.status="connecting",this._createWebsocket(`${this.linkSSL?"wss":"ws"}://${this.url}/websocket`)):this.logger.warn("imsocket::socket is connecting or connected",this.status)}close(){if(this.status="disconnected",this.websocket){this.logger.log("imsocket:: close websocket");try{this.websocket.close()}catch(e){this.logger.warn("imsocket::attempt to close websocket error",e)}this.clean(),this.emit("disconnect")}}clean(){this.status="disconnected",clearTimeout(this.socketConnectTimer),this.websocket&&(this.socketUrl=void 0,this.websocket.onmessage=null,this.websocket.onopen=null,this.websocket.onerror=null,this.websocket.onclose=null,this.websocket=null)}onConnect(){this.status="connected",this.emit("connect"),clearTimeout(this.socketConnectTimer)}_createWebsocket(e){this.socketConnectTimer=setTimeout(()=>{this.logger.error("imsocket::Websocket connect timeout. url: ",e),this.emit("connectFailed",new pe({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_CONNECT_TIMEOUT:415,detail:{reason:`imsocket::Websocket connect timeout. url: ${e}`}}))},this.core.options.socketConnectTimeout||8e3),this.socketUrl=e,this.websocket=new Oe.WebSocket(e),this.websocket.binaryType="arraybuffer",this.websocket.onmessage=this.onMessage.bind(this),this.websocket.onclose=e=>{e=e||{},this.logger.log(`imsocket::Websocket onclose done ${e.wasClean}/${e.code}/${e.reason}`),"connected"===this.status?(this.clean(),this.emit("disconnect")):(this.clean(),this.emit("connectFailed",new pe({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_CONNECT_FAILED:414,detail:{reason:"imsocket::Websocket onclose done"}})))},this.websocket.onerror=e=>{this.logger.error("imsocket::Websocket onerror",e),"connected"===this.status?(this.clean(),this.emit("disconnect")):(this.clean(),this.emit("connectFailed",new pe({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_CONNECT_FAILED:414,detail:{reason:"imsocket::Websocket onerror."}})))},this.websocket.onopen=()=>{this.onConnect()}}onMessage(e){if(e.data){var t=new Ft(e.data),i={sid:-1,cid:-1,ser:-1,packetLength:-1},r=null;try{t.unmarshalHeader(),i=t.getHeader(),r=t.getInnerHeader()}catch(t){this.reportBinaryError({err:t,sid:r?r.sid:null==i?void 0:i.sid,cid:r?r.cid:null==i?void 0:i.cid,rawBuf:e.data,type:"decode"})}var s=r?r.sid:i.sid,n=r?r.cid:i.cid,o=`${s}_${n}`,a=ct[o];if(a&&a.length>0){var c,d=a[0].config;try{c=t.unmarshal(d.response)}catch(r){var l=t.getBodyDetail();this.reportBinaryError({err:r,rawBuf:e.data,sid:s,cid:n,parseDetail:l,type:"decode"}),t.reset();var h=Object.assign(Object.assign({},i),{sid:s,cid:n,code:de.V2NIM_ERROR_CODE_UNPACK_ERROR});return this.logger.error(`imsocket::onMessage "${h.sid}_${h.cid}", ser ${h.ser}, packetLength ${h.packetLength} unmarshal error. ${l} \n`,r),void this.emit("message",JSON.stringify(h))}this.emit("message",c)}else this.core.logger.warn("imsocket::onMessage cmd not found",o);t.reset()}}send(e,t,i,r,s){var n,o,a=new $t(e,t,i),c=at[r],d="";try{d=JSON.stringify(s),o=a.marshal(JSON.parse(d),c.params)}catch(r){throw this.reportBinaryError({err:r,sid:e,cid:t,rawStr:d,type:"encode"}),a.reset(),new pe({code:de.V2NIM_ERROR_CODE_PACK_ERROR,detail:{reason:`${e}-${t}, ser ${i} marshal error`,rawError:r}})}null===(n=this.websocket)||void 0===n||n.send(o),a.reset()}reportBinaryError(e){var t,i,r,{err:s,rawStr:n,sid:o,cid:a,type:c,parseDetail:d}=e,l=e.rawBuf;if(l){try{r=function(e){if("function"!=typeof btoa)return"";for(var t="",i=new Uint8Array(e),r=i.byteLength,s=0;s{this.isReconnect=!0})}setSessionId(e){this.socket&&(this.socket.sessionId=e)}setLinkSSL(e){this.linkSSL=e}connect(e,t=!1){var i,r;return Te(this,void 0,void 0,function*(){this.isReconnect=t;var s=this.core.auth.getConnectStatus();if(1===s){var n=`clientSocket::connect status is ${s}, and would not repeat connect`,o=new pe({code:de.V2NIM_ERROR_CODE_ILLEGAL_STATE,detail:{reason:n}});return this.logger.warn(n),Promise.reject(o)}this.auth.lifeCycle.processEvent("connect");try{yield this.auth.doLoginStepsManager.add(this.doConnect(e)),this.logger.log(`clientSocketV2:: connect success with link url: ${e}, isReconnect: ${t}`),this.core.reporter.reportTraceUpdateV2("login",{operation_type:"TCP",target:e,code:200,mixlink:!0,succeed:!0},{asyncParams:Oe.net.getNetworkStatus()}),this.auth.lifeCycle.processEvent("connectSucc")}catch(t){var a=t;if(this.core.reporter.reportTraceUpdateV2("login",{operation_type:"TCP",target:e,code:a.code||0,description:`connectFailed:${a.message}`,mixlink:!0,succeed:!1},{asyncParams:Oe.net.getNetworkStatus()}),a.code===de.V2NIM_ERROR_CODE_CANCELLED||a.code===de.V2NIM_ERROR_CODE_TIMEOUT)throw null===(i=this.socket)||void 0===i||i.close(),null===(r=this.socket)||void 0===r||r.removeAllListeners(),this.socket=void 0,t;throw this.logger.warn(`clientSocketV2::connect failed with link url: ${e}`,a),this.auth.lifeCycle.processEvent("connectFail",a),t}})}doConnect(e){var t=!1;return new Promise((i,r)=>{this.socket=new Ht(this.core,e,this.linkSSL),this.socket.on("connect",()=>{this.logger.log("clientSocketV2::socket on connect",e),this.core.reporterHookLinkKeep.start(),this.core.reporterHookLinkKeep.update({code:0,description:"connection begin",operation_type:0,target:e}),t=!0,i()}),this.socket.on("message",this.onMessage.bind(this)),this.socket.on("disconnect",i=>Te(this,void 0,void 0,function*(){t=!0,this.logger.log(`clientSocketV2::socket on disconnect ${e}`,i),yield this.core.reporterHookLinkKeep.update({code:(null==i?void 0:i.code)||0,description:(null==i?void 0:i.reason)||"socket on disconnect",operation_type:1,target:e}),this.core.reporterHookLinkKeep.end(!1),this.doDisconnect(Dt.OFFLINE,"SocketOnDisconnect")})),this.socket.on("connectFailed",i=>{t?this.ping():(this.logger.error(`clientSocketV2::connectFailed:${e}, reason:${i&&i.message}`),this.cleanSocket()),t=!0,r(i)})})}cleanSocket(){this.socket&&("function"==typeof this.socket.removeAllListeners&&this.socket.removeAllListeners(),"function"==typeof this.socket.close&&this.socket.close(),this.socket=void 0)}resetSocketConfig(){this.backoff.reset(),this.initOnlineListener()}doDisconnect(e,t){if(this.logger.log(`clientSocketV2::doDisconnect:type:${e},reason:`,t),0!==this.core.auth.getConnectStatus()){var i={1:"close",2:"kicked",3:"broken"}[e]||"";this.markAllCmdInvaild(new pe({code:de.V2NIM_ERROR_CODE_DISCONNECT,detail:{reason:"Packet timeout due to instance disconnect",disconnect_reason:i}})),this.timerManager.destroy(),clearTimeout(this.pingTimer),this.cleanSocket(),e===Dt.ACTIVE||e===Dt.KICKED?this.destroyOnlineListener():e===Dt.OFFLINE&&(this.auth.lifeCycle.processEvent("connectionBroken",new pe({code:de.V2NIM_ERROR_CODE_DISCONNECT,detail:{reason:"connection broken due to internal reasons"}})),this.logger.log(`clientSocketV2::doDisconnect: pending reconnect ${this.isReconnect}`),this.isReconnect&&this.auth.lifeCycle.processEvent("waiting"))}else this.logger.warn("clientSocketV2::doDisconnect:already disconnected")}sendCmd(e,t,i){var r=this.core.auth.getLoginStatus(),s={cmd:e};if(1!==r&&!["v2Login","login","chatroomLogin","v2ChatroomLogin"].includes(e))return this.logger.warn(`clientSocketV2::NIM login status is ${r}, so can not sendCmd ${e}`),Promise.reject(new pe({code:de.V2NIM_ERROR_CODE_ILLEGAL_STATE,detail:Object.assign({reason:"Can not sendCmd due to no logined"},s)}));var n="heartbeat"!==e,o=n?this.packetSer++:0,a=dt(e,o,this.logger,t);if(!a){var c=new pe({code:de.V2NIM_ERROR_CODE_INTERNAL,detail:Object.assign(Object.assign({},s),{reason:`SendCmd::createCmd error: ${o} ${e}`})});return this.logger.error(c),Promise.reject(c)}var{packet:d,hasPacketResponse:l,hasPacketTimer:h}=a,p=JSON.stringify(d);n&&(this.logger.getDebugMode()?this.logger.debug(`clientSocketV2::sendCmd: ${d.SID}_${d.CID},${e},ser:${o}`,p):this.logger.log(`clientSocketV2::sendCmd: ${d.SID}_${d.CID},${e},ser:${o}`));var u=(new Date).getTime();return new Promise((r,n)=>{l&&this.sendingCmdMap.set(o,{cmd:e,params:t,callback:[r,n],timer:h?setTimeout(()=>{var t=new pe({code:de.V2NIM_ERROR_CODE_PROTOCOL_TIMEOUT,detail:Object.assign({ser:o,reason:`Packet Timeout: ser ${o} cmd ${e}`,timetag:(new Date).getTime()},s)});this.markCmdInvalid(o,t,e)},i&&i.timeout?i.timeout:this.packetTimeout):null});try{this.socket.send(d.SID,d.CID,o,e,d.Q),l||r(d)}catch(t){var a=new pe({code:de.V2NIM_ERROR_CODE_PROTOCOL_SEND_FAILED,detail:Object.assign({ser:o,reason:"Unable to send packet"+(t&&t.message?": "+t.message:""),timetag:(new Date).getTime(),rawError:t},s)});this.markCmdInvalid(o,a,e),n(a)}}).catch(e=>Te(this,void 0,void 0,function*(){var t=e;return[de.V2NIM_ERROR_CODE_DISCONNECT,de.V2NIM_ERROR_CODE_PROTOCOL_TIMEOUT,de.V2NIM_ERROR_CODE_PROTOCOL_SEND_FAILED].includes(t.code)?(this.reportSendCmdFailed(t,{sid:d.SID,cid:d.CID,ser:o},u),Promise.reject(t)):Promise.reject(t)}))}reportSendCmdFailed(e,t,i){var r;this.reporter.reportTraceStart("exceptions",{user_id:this.core.auth.getLoginUser(),trace_id:null===(r=this.socket)||void 0===r?void 0:r.sessionId,start_time:i,action:2,exception_service:6});var s=Ve(e,"detail.disconnect_reason")||"",n=e.code===de.V2NIM_ERROR_CODE_DISCONNECT?JSON.stringify({disconnect_reason:s}):e.detail.reason;this.reporter.reportTraceUpdateV2("exceptions",{code:e.code,description:n,operation_type:1,target:`${t.sid}-${t.cid}`,context:`${t.ser}`},{asyncParams:Oe.net.getNetworkStatus()}),this.reporter.reportTraceEnd("exceptions",1)}onMessage(e){var t=lt(e,this.logger);if(t&&t.length>0){var i=t[0],r=i.raw.ser;for(var s of(i.error&&(this.logger.error("clientSocketV2::onMessage packet error",`${i.raw.sid}_${i.raw.cid}, ser:${r},`,i.error),i.error.code===de.V2NIM_ERROR_CODE_UNPACK_ERROR&&this.core.eventBus.emit("BinaryClientSocket/unpackError")),"heartbeat"!==i.cmd&&(this.logger.getDebugMode()?this.logger.debug(`clientSocketV2::recvCmd ${i.raw.sid}_${i.raw.cid},${i.cmd},ser:${r}`,e):this.logger.log(`clientSocketV2::recvCmd ${i.raw.sid}_${i.raw.cid},${i.cmd},ser:${r},code:${i.raw.code}`)),t))this.packetHandler(s)}}packetHandler(e){var t,i,r,s;if(e){var n=e.raw.ser,o=this.sendingCmdMap.get(n);if(o&&o.cmd===e.cmd){var{callback:a,timer:c,params:d}=o;if(clearTimeout(c),e.params=d,this.sendingCmdMap.delete(n),"heartbeat"===e.cmd)return void a[0]();var l=null===(i=null===(t=this.core[e.service])||void 0===t?void 0:t.process)||void 0===i?void 0:i.call(t,e);l&&"function"==typeof l.then?l.then(e=>{a[0](e)}).catch(e=>{a[1](e)}):(this.logger.log("clientSocketV2::handlerFn without promise",e.service,e.cmd),a[0](e))}else{var h=null===(s=null===(r=this.core[e.service])||void 0===r?void 0:r.process)||void 0===s?void 0:s.call(r,e);h&&"function"==typeof h.then&&h.catch(e=>{this.logger.error("clientSocketV2::no obj cache, no process handler",e)})}}}markCmdInvalid(e,t,i){var r=this.sendingCmdMap.get(e);if(r){var{callback:s,timer:n}=r;n&&clearTimeout(n),this.sendingCmdMap.delete(e),this.logger.warn(`clientSocketV2::packet ${e}, ${i} is invalid:`,t),s[1](t)}}markAllCmdInvaild(e){this.logger.log("markAllCmdInvaild",e),this.sendingCmdMap.forEach(t=>{var{callback:i,timer:r,cmd:s}=t;this.logger.log(`clientSocketV2::markAllCmdInvaild:cmd ${s}`),r&&clearTimeout(r),i[1](e)}),this.sendingCmdMap.clear()}ping(){var e;return Te(this,void 0,void 0,function*(){clearTimeout(this.pingTimer);try{yield this.sendCmd("heartbeat")}catch(t){if(t.code===de.V2NIM_ERROR_CODE_DISCONNECT)return;if(yield this.testHeartBeat5Timeout())return yield this.core.reporterHookLinkKeep.update({code:0,description:"Heartbeat-discovered link failure",operation_type:1,target:null===(e=this.socket)||void 0===e?void 0:e.url}),this.core.reporterHookLinkKeep.end(!0),void this.doDisconnect(Dt.OFFLINE,"PingError")}this.pingTimer=setTimeout(()=>{this.ping()},3e4)})}testHeartBeat5Timeout(){return Te(this,void 0,void 0,function*(){clearTimeout(this.pingTimer);for(var e=0;e<5;e++)try{return yield this.sendCmd("heartbeat",{},{timeout:3e3}),!1}catch(t){this.logger.log(`clientSocketV2::test heartbeat ${e} Timeout`)}return!0})}initOnlineListener(){this.hasNetworkListener||(this.logger.log("clientSocketV2::onlineListener:init"),this.hasNetworkListener=!0,Oe.net.onNetworkStatusChange(e=>{this.logger.log("clientSocketV2::onlineListener:network change",e);var t=this.auth.getLoginStatus();e.isConnected&&1===t?this.ping():e.isConnected&&3===t?(this.logger.log("clientSocketV2::onlineListener:online and connectStatus is waiting, do reLogin"),this.auth.reconnect.clearReconnectTimer(),this.auth.reconnect.doReLogin()):e.isConnected||this.doDisconnect(Dt.OFFLINE,"OfflineListener")}))}destroyOnlineListener(){this.logger.log("clientSocketV2::onlineListener:destroy"),Oe.net.offNetworkStatusChange(),this.hasNetworkListener=!1}}var qt,Kt=["disconnect","connect","heartbeat","message","json","event","ack","error","noop"],Wt=["transport not supported","client not handshaken","unauthorized"],Jt=["reconnect"];class zt extends ne{constructor(e,t,i){super(),this.websocket=null,this.socketConnectTimer=0,this.url="",this.linkSSL=!0,this.core=e,this.url=t,this.linkSSL=i,this.status="disconnected",this.logger=e.logger,this.connect()}connect(){"connecting"!==this.status&&"connected"!==this.status?(this.status="connecting",this.core.adapters.request(`${this.linkSSL?"https":"http"}://${this.url}/socket.io/1/?t=${Date.now()}`,{method:"GET",dataType:"text",timeout:this.core.options.xhrConnectTimeout||8e3},{exception_service:6}).then(e=>{if("connecting"===this.status){var[t,i]=e.data.split(":");return this.sessionId=t,this.logger.log(`imsocket::XHR success. status ${this.status}, ${"connecting"===this.status?"continue websocket connection":"stop websocket connection"}`),this._createWebsocket(`${this.linkSSL?"wss":"ws"}://${this.url}/socket.io/1/websocket/${t}`)}}).catch(e=>{if("connecting"===this.status){var t=`imsocket::XHR fail. raw message: "${(e=e||{}).message}", code: "${e.code}"`,i=e.code;i="v2"===Ve(this.core,"options.apiVersion")?e.code===de.V2NIM_ERROR_CODE_CONNECT_TIMEOUT?de.V2NIM_ERROR_CODE_CONNECT_TIMEOUT:de.V2NIM_ERROR_CODE_CONNECT_FAILED:408===e.code?408:415;var r=new pe({code:i,detail:{reason:t,rawError:e}});this.logger.error(t),this.status="disconnected",this.emit("handshakeFailed",r)}})):this.logger.warn("imsocket::socket is connecting or connected",this.status)}close(){if(this.status="disconnected",this.websocket){this.logger.log("imsocket:: close websocket");try{this.websocket.send(this.encodePacket({type:"disconnect"}))}catch(e){this.logger.warn("imsocket::attempt to send encodePacket error",e)}try{this.websocket.close()}catch(e){this.logger.warn("imsocket::attempt to close websocket error",e)}this.clean(),this.emit("disconnect",{code:0,reason:"Active close websocket"})}}clean(){this.status="disconnected",clearTimeout(this.socketConnectTimer),this.websocket&&(this.socketUrl=void 0,this.websocket.onmessage=null,this.websocket.onopen=null,this.websocket.onerror=null,this.websocket.onclose=null,this.websocket=null)}onConnect(){this.status="connected",this.emit("connect"),clearTimeout(this.socketConnectTimer)}_createWebsocket(e){this.socketConnectTimer=setTimeout(()=>{this.logger.error("imsocket::Websocket connect timeout. url: ",this.socketUrl),this.emit("handshakeFailed",new pe({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_CONNECT_TIMEOUT:415,detail:{reason:`imsocket::Websocket connect timeout. url: ${this.socketUrl}`}}))},this.core.options.socketConnectTimeout||8e3),this.socketUrl=e,this.websocket=new Oe.WebSocket(e),this.websocket.onmessage=this.onMessage.bind(this),this.websocket.onclose=e=>{e=e||{},this.logger.log(`imsocket::Websocket onclose done ${e.wasClean}/${e.code}/${e.reason}`),this.clean(),this.emit("disconnect",{code:e.code||0,reason:e.reason})},this.websocket.onerror=e=>{this.logger.error("imsocket::Websocket onerror",e),"logined"===this.core.status&&this.core.clientSocket.ping()}}onMessage(e){var t,i=this.decodePacket(e.data);if(i)switch(i.type){case"connect":this.onConnect();break;case"disconnect":this.close(),this.emit("disconnect",{code:0,reason:"MessageEvent type disconnect"});break;case"message":case"json":this.emit("message",i.data);break;case"event":i.name&&this.emit(i.name,i.args);break;case"error":"unauthorized"===i.reason?this.emit("connect_failed",i.reason):this.emit("error",i.reason),this.logger.error("imsocket::Websocket connect failed, onmessage type error. url: ",this.socketUrl),clearTimeout(this.socketConnectTimer),this.emit("handshakeFailed",new pe({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_CONNECT_FAILED:408,detail:{reason:`imsocket::Websocket connect failed, onMessage socket error. url: ${this.socketUrl}`}}));break;case"heartbeat":null===(t=this.websocket)||void 0===t||t.send(this.encodePacket({type:"heartbeat"}));break;default:this.logger.warn("imsocket::Websocket no handler type",i.type)}}encodePacket(e){var t,i,{type:r,id:s="",endpoint:n="",ack:o}=e,a=null;if(!r)return"";switch(r){case"error":t=e.reason?Wt.indexOf(e.reason):"",i=e.advice?Jt.indexOf(e.advice):"",""===t&&""===i||(a=t+(""!==i?"+"+i:""));break;case"message":""!==e.data&&(a=e.data);break;case"event":t={name:e.name},t=e.args&&e.args.length?{name:e.name,args:e.args}:{name:e.name},a=JSON.stringify(t);break;case"json":a=JSON.stringify(e.data);break;case"connect":e.qs&&(a=e.qs);break;case"ack":a=e.ackId+(e.args&&e.args.length?"+"+JSON.stringify(e.args):"")}var c=[Kt.indexOf(r),s+("data"===o?"+":""),n];return null!=a&&c.push(a),c.join(":")}decodePacket(e){if(e)if("�"!=e.charAt(0)){var t=e.match(/([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/);if(t){var i,[,r,s,n,o,a]=t,c={type:Kt[+r],endpoint:o};switch(s&&(c.id=s,c.ack=!n||"data"),c.type){case"error":i=a.split("+"),c.reason=Wt[+i[0]]||"";break;case"message":c.data=a||"";break;case"connect":c.qs=a||"";break;case"event":try{var d=JSON.parse(a);c.name=d.name,c.args=d.args}catch(e){this.logger.error("imsocket::parseData::type::event error",e)}c.args=c.args||[];break;case"json":try{c.data=JSON.parse(a)}catch(e){this.logger.error("imsocket::parseData::type::json error",e)}break;case"ack":if((i=a.match(/^([0-9]+)(\+)?(.*)/))&&(c.ackId=i[1],c.args=[],i[3]))try{c.args=i[3]?JSON.parse(i[3]):[]}catch(e){this.logger.error("imsocket::parseData::type::ack error",e)}}return c}}else this.logger.error("imsocket::unrecognize dataStr",e.slice(0,20))}send(e){var t,i={data:e,type:"message",endpoint:""};null===(t=this.websocket)||void 0===t||t.send(this.encodePacket(i))}}!function(e){e[e.ACTIVE=1]="ACTIVE",e[e.KICKED=2]="KICKED",e[e.OFFLINE=3]="OFFLINE"}(qt||(qt={}));class Xt{constructor(e){this.isReconnect=!1,this.packetTimeout=8e3,this.linkSSL=!0,this.packetSer=1,this.backoff=new Ot({max:8e3,min:1600,jitter:.01}),this.sendingCmdMap=new Map,this.pingTimer=0,this.hasNetworkListener=!1,this.core=e,this.auth=e.auth,this.logger=e.logger,this.reporter=e.reporter,this.timerManager=e.timerManager,this.eventBus=e.eventBus,this.setListener()}setListener(){this.core.eventBus.on("V2NIMLoginService/loginLifeCycleLoginSucc",()=>{this.isReconnect=!0})}setSessionId(e){this.socket&&(this.socket.sessionId=e)}setLinkSSL(e){this.linkSSL=e}connect(e,t=!1){var i,r;return Te(this,void 0,void 0,function*(){this.isReconnect=t;var s=this.core.auth.getConnectStatus();if(1===s){var n=`clientSocket::connect status is ${s}, and would not repeat connect`,o=new pe({code:de.V2NIM_ERROR_CODE_ILLEGAL_STATE,detail:{reason:n}});return this.logger.warn(n),Promise.reject(o)}this.auth.lifeCycle.processEvent("connect");try{yield this.auth.doLoginStepsManager.add(this.doConnect(e)),this.logger.log(`clientSocketV2:: connect success with link url: ${e}, isReconnect: ${t}`),this.core.reporter.reportTraceUpdateV2("login",{operation_type:"TCP",target:e,code:200,mixlink:!0,succeed:!0},{asyncParams:Oe.net.getNetworkStatus()}),this.auth.lifeCycle.processEvent("connectSucc")}catch(t){var a=t;if(this.core.reporter.reportTraceUpdateV2("login",{operation_type:"TCP",target:e,code:a.code||0,description:`connectFailed:${a.message}`,mixlink:!0,succeed:!1},{asyncParams:Oe.net.getNetworkStatus()}),a.code===de.V2NIM_ERROR_CODE_CANCELLED||a.code===de.V2NIM_ERROR_CODE_TIMEOUT)throw null===(i=this.socket)||void 0===i||i.close(),null===(r=this.socket)||void 0===r||r.removeAllListeners(),this.socket=void 0,t;throw this.logger.warn(`clientSocketV2::connect failed with link url: ${e}`,a),this.auth.lifeCycle.processEvent("connectFail",a),t}})}doConnect(e){var t=!1;return new Promise((i,r)=>{this.socket=new zt(this.core,e,this.linkSSL),this.socket.on("connect",()=>{this.logger.log("clientSocketV2::socket on connect",e),this.core.reporterHookLinkKeep.start(),this.core.reporterHookLinkKeep.update({code:0,description:"connection begin",operation_type:0,target:e}),t=!0,i()}),this.socket.on("message",this.onMessage.bind(this)),this.socket.on("disconnect",i=>Te(this,void 0,void 0,function*(){t=!0,this.logger.log("clientSocketV2::socket on disconnect",i),yield this.core.reporterHookLinkKeep.update({code:(null==i?void 0:i.code)||0,description:(null==i?void 0:i.reason)||"socket on disconnect",operation_type:1,target:e}),this.core.reporterHookLinkKeep.end(!1),this.doDisconnect(qt.OFFLINE,"SocketOnDisconnect")})),this.socket.on("handshakeFailed",e=>{t?this.ping():(this.logger.error(`clientSocketV2::handshake failed: "${e&&e.message}"`),this.cleanSocket()),t=!0,r(e)})})}cleanSocket(){this.socket&&("function"==typeof this.socket.removeAllListeners&&this.socket.removeAllListeners(),"function"==typeof this.socket.close&&this.socket.close(),this.socket=void 0)}resetSocketConfig(){this.backoff.reset(),this.initOnlineListener()}doDisconnect(e,t){if(this.logger.log(`clientSocketV2::doDisconnect:type:${e},reason:`,t),0!==this.core.auth.getConnectStatus()){var i={1:"close",2:"kicked",3:"broken"}[e]||"";this.markAllCmdInvaild(new pe({code:de.V2NIM_ERROR_CODE_DISCONNECT,detail:{reason:"Packet timeout due to instance disconnect",disconnect_reason:i}})),this.timerManager.destroy(),clearTimeout(this.pingTimer),this.cleanSocket(),e===qt.ACTIVE||e===qt.KICKED?this.destroyOnlineListener():e===qt.OFFLINE&&(this.auth.lifeCycle.processEvent("connectionBroken",new pe({code:de.V2NIM_ERROR_CODE_DISCONNECT,detail:{reason:"connection broken due to internal reasons"}})),this.logger.log(`clientSocketV2::doDisconnect: pending reconnect ${this.isReconnect}`),this.isReconnect&&this.auth.lifeCycle.processEvent("waiting"))}else this.logger.warn("clientSocketV2::doDisconnect:already disconnected")}sendCmd(e,t,i){var r=this.core.auth.getLoginStatus(),s={cmd:e};if(1!==r&&!["v2Login","login","chatroomLogin","v2ChatroomLogin"].includes(e))return this.logger.warn(`clientSocketV2::NIM login status is ${r}, so can not sendCmd ${e}`),Promise.reject(new pe({code:de.V2NIM_ERROR_CODE_ILLEGAL_STATE,detail:Object.assign({reason:"Can not sendCmd due to no logined"},s)}));var n="heartbeat"!==e,o=n?this.packetSer++:0,a=dt(e,o,this.logger,t);if(!a){var c=new pe({code:de.V2NIM_ERROR_CODE_INTERNAL,detail:Object.assign(Object.assign({},s),{reason:`SendCmd::createCmd error: ${o} ${e}`})});return this.logger.error(c),Promise.reject(c)}var{packet:d,hasPacketResponse:l,hasPacketTimer:h}=a,p=JSON.stringify(d);n&&(this.logger.getDebugMode()?this.logger.debug(`clientSocketV2::sendCmd: ${d.SID}_${d.CID},${e},ser:${o}`,p):this.logger.log(`clientSocketV2::sendCmd: ${d.SID}_${d.CID},${e},ser:${o}`));var u=(new Date).getTime();return new Promise((r,n)=>{l&&this.sendingCmdMap.set(o,{cmd:e,params:t,callback:[r,n],timer:h?setTimeout(()=>{var t=new pe({code:de.V2NIM_ERROR_CODE_PROTOCOL_TIMEOUT,detail:Object.assign({ser:o,reason:`Packet Timeout: ser ${o} cmd ${e}`,timetag:(new Date).getTime()},s)});this.markCmdInvalid(o,t,e)},i&&i.timeout?i.timeout:this.packetTimeout):null});try{this.socket.send(p),l||r(d)}catch(t){var a=new pe({code:de.V2NIM_ERROR_CODE_PROTOCOL_SEND_FAILED,detail:Object.assign({ser:o,reason:"Unable to send packet"+(t&&t.message?": "+t.message:""),timetag:(new Date).getTime(),rawError:t},s)});this.markCmdInvalid(o,a,e),n(a)}}).catch(e=>Te(this,void 0,void 0,function*(){var t,i=e;if(![de.V2NIM_ERROR_CODE_DISCONNECT,de.V2NIM_ERROR_CODE_PROTOCOL_TIMEOUT,de.V2NIM_ERROR_CODE_PROTOCOL_SEND_FAILED].includes(i.code))return Promise.reject(i);this.reporter.reportTraceStart("exceptions",{user_id:this.core.auth.getLoginUser(),trace_id:null===(t=this.socket)||void 0===t?void 0:t.sessionId,start_time:u,action:2,exception_service:6});var r=Ve(i,"detail.disconnect_reason")||"",s=i.code===de.V2NIM_ERROR_CODE_DISCONNECT?JSON.stringify({disconnect_reason:r}):i.detail.reason;return this.reporter.reportTraceUpdateV2("exceptions",{code:i.code,description:s,operation_type:1,target:`${d.SID}-${d.CID}`,context:`${d.SER}`},{asyncParams:Oe.net.getNetworkStatus()}),this.reporter.reportTraceEnd("exceptions",1),Promise.reject(i)}))}onMessage(e){var t=lt(e,this.logger);if(t&&t.length>0){var i=t[0],r=i.raw.ser;for(var s of(i.error&&this.logger.error("clientSocketV2::onMessage packet error",`${i.raw.sid}_${i.raw.cid}, ser:${r},`,i.error),"heartbeat"!==i.cmd&&(this.logger.getDebugMode()?this.logger.debug(`clientSocketV2::recvCmd ${i.raw.sid}_${i.raw.cid},${i.cmd},ser:${r}`,i.content):this.logger.log(`clientSocketV2::recvCmd ${i.raw.sid}_${i.raw.cid},${i.cmd},ser:${r};code:${i.raw.code}`)),t))this.packetHandler(s)}}packetHandler(e){var t,i,r,s;if(e){var n=e.raw.ser,o=this.sendingCmdMap.get(n);if(o&&o.cmd===e.cmd){var{callback:a,timer:c,params:d}=o;if(clearTimeout(c),e.params=d,this.sendingCmdMap.delete(n),"heartbeat"===e.cmd)return void a[0]();var l=null===(i=null===(t=this.core[e.service])||void 0===t?void 0:t.process)||void 0===i?void 0:i.call(t,e);l&&"function"==typeof l.then?l.then(e=>{a[0](e)}).catch(e=>{a[1](e)}):(this.logger.log("clientSocketV2::handlerFn without promise",e.service,e.cmd),a[0](e))}else{var h=null===(s=null===(r=this.core[e.service])||void 0===r?void 0:r.process)||void 0===s?void 0:s.call(r,e);h&&"function"==typeof h.then&&h.catch(e=>{this.logger.error("clientSocketV2::no obj cache, no process handler",e)})}}}markCmdInvalid(e,t,i){var r=this.sendingCmdMap.get(e);if(r){var{callback:s,timer:n}=r;n&&clearTimeout(n),this.sendingCmdMap.delete(e),this.logger.warn(`clientSocketV2::packet ${e}, ${i} is invalid:`,t),s[1](t)}}markAllCmdInvaild(e){this.logger.log("markAllCmdInvaild",e),this.sendingCmdMap.forEach(t=>{var{callback:i,timer:r,cmd:s}=t;this.logger.log(`clientSocketV2::markAllCmdInvaild:cmd ${s}`),r&&clearTimeout(r),i[1](e)}),this.sendingCmdMap.clear()}ping(){var e;return Te(this,void 0,void 0,function*(){clearTimeout(this.pingTimer);try{yield this.sendCmd("heartbeat")}catch(t){if(t.code===de.V2NIM_ERROR_CODE_DISCONNECT)return;if(yield this.testHeartBeat5Timeout())return yield this.core.reporterHookLinkKeep.update({code:0,description:"Heartbeat-discovered link failure",operation_type:1,target:null===(e=this.socket)||void 0===e?void 0:e.url}),this.core.reporterHookLinkKeep.end(!0),void this.doDisconnect(qt.OFFLINE,"PingError")}this.pingTimer=setTimeout(()=>{this.ping()},3e4)})}testHeartBeat5Timeout(){return Te(this,void 0,void 0,function*(){clearTimeout(this.pingTimer);for(var e=0;e<5;e++)try{return yield this.sendCmd("heartbeat",{},{timeout:3e3}),!1}catch(t){this.logger.log(`clientSocketV2::test heartbeat ${e} Timeout`)}return!0})}initOnlineListener(){this.hasNetworkListener||(this.logger.log("clientSocketV2::onlineListener:init"),this.hasNetworkListener=!0,Oe.net.onNetworkStatusChange(e=>{this.logger.log("clientSocketV2::onlineListener:network change",e);var t=this.auth.getConnectStatus(),i=this.auth.getLoginStatus();e.isConnected&&1===i?this.ping():e.isConnected&&3===t?(this.logger.log("clientSocketV2::onlineListener:online and connectStatus is waiting, do reLogin"),this.auth.reconnect.clearReconnectTimer(),this.auth.reconnect.doReLogin()):e.isConnected||this.doDisconnect(qt.OFFLINE,"OfflineListener")}))}destroyOnlineListener(){this.logger.log("clientSocketV2::onlineListener:destroy"),Oe.net.offNetworkStatusChange(),this.hasNetworkListener=!1}}class Qt{constructor(e){var t,i;this.currenRetryCount=0,this.backoff=new Ot({max:8e3,min:1600,jitter:.01}),this.reconnectTimer=0,this.core=e,this.auth=e.V2NIMLoginService,null===(i=(t=Oe.powerMonitor).on)||void 0===i||i.call(t,"onPowerMonitorTurnActive",()=>{this.core.logger.debug("reconnect::powerMonitor turn active"),3===this.auth.getLoginStatus()&&(this.core.logger.log("reconnect::powerMonitor turn active, try to reconnect"),this.auth.reconnect.clearReconnectTimer(),this.auth.reconnect.doReLogin())})}reset(){this.currenRetryCount=0,this.backoff.reset(),this.reconnectTimer&&clearTimeout(this.reconnectTimer)}destroy(){var e,t;this.currenRetryCount=0,this.backoff.reset(),this.reconnectTimer&&clearTimeout(this.reconnectTimer),Oe.powerMonitor.destroy(),null===(t=(e=Oe.powerMonitor).off)||void 0===t||t.call(e,"onPowerMonitorTurnActive")}clearReconnectTimer(){this.reconnectTimer&&clearTimeout(this.reconnectTimer)}attempToReLogin(){var e=this.backoff.duration();if("function"==typeof this.reconnectDelayProvider)try{var t=this.reconnectDelayProvider(e);"number"==typeof t&&t>=0&&(e=t>=1e3?t:t+200+Math.ceil(300*Math.random()))}catch(e){this.core.logger.error("reconnect::connectDelayProvider excute failed,",e)}return this.currenRetryCount++,this.core.logger.log(`reconnect::reconnect timer is about to be set, delay ${e} ms, current retry count is ${this.currenRetryCount}`),this.core.reporter.reportTraceStart("login",{user_id:this.auth.getLoginUser(),action:"auto_login",binary_websocket:this.auth.binaryWebsocket}),this.clearReconnectTimer(),this.reconnectTimer=setTimeout(()=>{this.core.logger.log("reconnect::reconnect timer is now triggered");var e=this.auth.getConnectStatus();3===e?this.doReLogin():this.core.logger.warn(`reconnect::reconnect timer is over because connect status now is ${e}`)},e),!0}doReLogin(){if(!Oe.powerMonitor.isActive())return this.core.logger.log("reconnect::reLogin skip, cause app powerMonitor is not active"),void this.auth.lifeCycle.processEvent("waiting");this.auth.loginOption.forceMode=!1,this.auth.originLoginPromise=this.auth.doLogin(!0);var e=this.auth.previousLoginManager.add(this.auth.originLoginPromise);return e.then(()=>{this.core.reporter.reportTraceEnd("login",!0)}).catch(e=>{var t=e;if(this.core.logger.warn("reconnect::try login but failed due to",t),this.core.reporter.reportTraceEnd("login",!1),this.auth.checkLoginTerminalCode(t&&t.code))return this.auth.clientSocket.doDisconnect(Dt.ACTIVE,"ReloginTerminated"),void this.auth.lifeCycle.processEvent("exited",t);t&&399===t.code&&this.auth.lbs.reset(),this.auth.lifeCycle.processEvent("waiting")}),e}_setReconnectDelayProvider(e){this.reconnectDelayProvider=e}}function Zt(e){e=e||[];for(var t=[],i=0;i0){var e=this.socketLinkUrls.shift();return this.core.logger.log("V2NIMLoginService::getLbsInfos:use cache link",e),Promise.resolve(e)}this.auth.lifeCycle.processEvent("addressing"),this.core.reporterHookLBS.start(this.core.account);var t=Zt(this.auth.config.lbsUrls);try{var i=yield this.ladderLoad(t);if(200!==i.status||!i.data)throw this.core.logger.error("V1NIMLoginService::getLbsInfos:error status",i.status,i),new pe({code:de.V2NIM_ERROR_CODE_INTERNAL,detail:{reason:`V2NIMLoginService::getLbsInfos failed, status ${i.status}`}});this.success(i)}catch(e){var r=e;if(this.core.logger.error(`V2NIMLoginService::lbs getLbsInfos error, use default link: ${this.auth.config.linkUrl}. error:`,e),this.reportForFail(t[0],r.code,r.message),this.checkTerminator(r.code))throw e;this.socketLinkUrls=[this.auth.config.linkUrl]}return this.socketLinkUrls.shift()})}checkTerminator(e){return e===de.V2NIM_ERROR_CODE_CANCELLED||e===de.V2NIM_ERROR_CODE_TIMEOUT}generateUrl(e){var t=(e=this.processLbsUrl(e)).indexOf("?")>-1?"&":"?";return e+t+"k="+this.core.options.appkey+"&id="+this.core.auth.getLoginUser()+"&sv=180&pv=1&networkType=0&lv=1"}processLbsUrl(e){return we()?e.replace("/webconf","/wxwebconf"):e}requstLbs(e){return this.auth.doLoginStepsManager.add(this.core.adapters.request(this.generateUrl(e),{method:"GET",dataType:"json",timeout:8e3}))}setLadderTimer(e,t,i,r){this.timer&&clearTimeout(this.timer);var s=e[t];this.timer=setTimeout(()=>{s&&(this.setLadderTimer(e,t+1,i,r),this.core.logger.log(`V2NIMLoginService::getLbsInfos ${t}:`,this.processLbsUrl(s)),this.reportForLbsStart(s,t),this.requstLbs(s).then(e=>{this.reset(),i(Object.assign(Object.assign({},e),{url:s}))}).catch(i=>{var n;if(this.core.logger.warn(`V2NIMLoginService::getLbsInfos ${t} failed:`,i),this.failedCount+=1,this.reportForFailOnce(s,i.code,(null===(n=i.detail)||void 0===n?void 0:n.reason)||i.message),this.failedCount>=e.length||this.checkTerminator(i.code))return this.reset(),void r(i)}))},2e3)}ladderLoad(e){return new Promise((t,i)=>{e.length>1&&this.setLadderTimer(e,1,t,i);var r=e[0];this.core.logger.log("V2NIMLoginService::getLbsInfos 0:",r),this.reportForLbsStart(r,0),this.requstLbs(r).then(e=>{this.reset(),t(Object.assign(Object.assign({},e),{url:r}))}).catch(t=>{var s;this.failedCount+=1,this.core.logger.warn("V2NIMLoginService::getLbsInfos 0 failed:",t),this.reportForFailOnce(r,t.code,(null===(s=t.detail)||void 0===s?void 0:s.reason)||t.message),(this.failedCount>=e.length||this.checkTerminator(t.code))&&(this.reset(),i(t))})})}success(e){var t,i,r=e.data.common,s=r["mix.link"]||[],n=r["link.default"]||[];this.socketLinkUrls=s.concat(n).concat(this.auth.config.linkUrl),e.data["nos-chunk"]&&(null===(t=this.core.cloudStorage)||void 0===t?void 0:t.setOptions)&&(this.core.logger.log("getLbsInfos success. lbs.nos-chunk",e.data["nos-chunk"]),this.core.cloudStorage.setOptions({chunkUploadHost:e.data["nos-chunk"]})),Array.isArray(e.data.nosup)&&e.data.nosup.length>0&&(null===(i=this.core.cloudStorage)||void 0===i?void 0:i.setOptions)&&(this.core.logger.log("getLbsInfos success. lbs.nosup",e.data.nosup),this.core.cloudStorage.setOptions({commonUploadHostBackupList:e.data.nosup,commonUploadHost:e.data.nosup[0]})),this.core.logger.log("V2NIMLoginService::getLbsInfos success, socket link:",this.socketLinkUrls.slice(0),"chunkUploadHost: ",e.data["nos-chunk"]),this.reportForLbsSuccess(e.url,e.data)}reportForLbsStart(e,t){this.core.reporterHookLBS.updateBegin({target:e,index:t})}reportForLbsSuccess(e,t){this.core.reporterHookLBS.updateComplete({target:e,code:200,body:JSON.stringify(t)}),this.core.reporterHookLBS.end(!0),this.core.reporter.reportTraceUpdateV2("login",{operation_type:"HTTP",target:e,code:200,succeed:!0},{asyncParams:Oe.net.getNetworkStatus()})}reportForFailOnce(e,t,i){this.core.reporterHookLBS.updateComplete({target:e,code:t,body:i})}reportForFail(e,t,i){this.core.reporterHookLBS.end(!1),this.core.reporter.reportTraceUpdateV2("login",{operation_type:"HTTP",target:e,description:i,code:t,succeed:!1},{asyncParams:Oe.net.getNetworkStatus()})}reset(){this.socketLinkUrls=[],this.failedCount=0,clearTimeout(this.timer)}}class ti{constructor(e){this.lastLoginClientKey="__NIM_LAST_LOGIN_CLIENT__",this.loginClients=[],this.loginClientOfThisConnection={},this.core=e,this.auth=e.V2NIMLoginService}verifyAuthentication(e){var t,i;return Te(this,void 0,void 0,function*(){var r=yield this.auth.doLoginStepsManager.add(this.refreshLoginToken(this.auth.account)),s=yield this.auth.doLoginStepsManager.add(this.refreshThirdPartyExt(this.auth.account));this.auth.token=r;var n,o=Oe.getSystemInfo(),a={appkey:this.core.options.appkey,account:this.auth.account,token:r,authType:this.auth.loginOption.authType,appLogin:e?0:1,clientType:16,clientSession:this.auth.clientSession,clientId:this.auth.deviceId,sdkVersion:100950,userAgent:this.core.options.loginSDKTypeParamCompat?"Native/10.9.50":o.userAgent.replace("{{appkey}}",this.core.options.appkey).slice(0,299),libEnv:this.core.options.flutterSdkVersion?"FLUTTER":this.core.options.loginSDKTypeParamCompat?void 0:o.libEnv,hostEnv:this.core.options.flutterSdkVersion?4:this.core.options.loginSDKTypeParamCompat?0:o.hostEnvEnum,sdkHumanVersion:this.core.options.flutterSdkVersion||"10.9.50",os:o.os,browser:o.browser,protocolVersion:1,customClientType:this.auth.config.customClientType,customTag:this.auth.config.customTag,thirdPartyExtension:s,isRoutable:!1===(null===(t=this.auth.loginOption.routeConfig)||void 0===t?void 0:t.routeEnabled)?0:1,env:null===(i=this.auth.loginOption.routeConfig)||void 0===i?void 0:i.routeEnvironment},c=o.os.toLowerCase(),d=110===o.hostEnvEnum;"UNIAPP"===Oe.platform&&d?(a.isReactNative=1,a.clientType="ios"===c?2:"android"===c?1:65,o.pushDeviceInfo&&o.pushDeviceInfo.MANUFACTURER&&(a.deviceInfo=JSON.stringify(Object.assign({IS_SUPPORT_HONOR:!0},o.pushDeviceInfo)))):"React Native"===Oe.platform&&(this.core.logger.log("V2NIMLoginService deviceInfo",this.core.V2NIMLoginService.deviceInfo,"os",c),a.isReactNative=1,a.clientType="ios"===c?2:1,a.deviceInfo=JSON.stringify(Object.assign({IS_SUPPORT_HONOR:!0},this.core.V2NIMLoginService.deviceInfo))),this.core.logger.log(`V2NIMLoginService::do login,accid:${a.account};clientSession:${a.clientSession};appLogin:${a.appLogin}`);try{n=yield this.auth.doLoginStepsManager.add(this.auth.clientSocket.sendCmd("v2Login",{tag:a}))}catch(e){var l=e;if(this.core.reporter.reportTraceUpdateV2("login",{operation_type:"protocol",target:"26-3",code:l.code||0,succeed:!1,description:l.message},{asyncParams:Oe.net.getNetworkStatus()}),l.code===de.V2NIM_ERROR_CODE_CANCELLED||l.code===de.V2NIM_ERROR_CODE_TIMEOUT)throw l;throw this.processLoginFailed(l),l}var{data:h,loginClients:p}=n.content;return this.changeLoginClient(1,p),this.core.reporter.reportTraceUpdateV2("login",{operation_type:"protocol",target:"26-3",code:200,succeed:!0},{asyncParams:Oe.net.getNetworkStatus()}),this.loginClientOfThisConnection=Mt(h),this.core.clientSocket.setSessionId(h.consid),Oe.localStorage.setItem(this.lastLoginClientKey,JSON.stringify(Object.assign({account:this.auth.account},this.loginClientOfThisConnection))),this.loginClientOfThisConnection})}refreshLoginToken(e){return Te(this,void 0,void 0,function*(){if(0===this.auth.loginOption.authType)return this.auth.token;if("function"!=typeof this.auth.loginOption.tokenProvider)return this.auth.token;try{var t=yield this.auth.loginOption.tokenProvider(e);if("string"==typeof t)return t;throw this.core.logger.error("V2NIMLoginService::excute tokenProvider complete but got Unexpected value:",t),new pe({code:de.V2NIM_ERROR_CODE_CALLBACK_FAILED,detail:{reason:"Excute tokenProvider complete but got Unexpected value",rawData:t}})}catch(e){var i=e,r=i;throw i.code!==de.V2NIM_ERROR_CODE_CALLBACK_FAILED&&(this.core.logger.error("V2NIMLoginService::excute tokenProvider error:",i),r=new pe({code:de.V2NIM_ERROR_CODE_CALLBACK_FAILED,desc:"Excute tokenProvider error",detail:{rawError:e}})),this.processLoginFailed(i),r}})}refreshThirdPartyExt(e){return Te(this,void 0,void 0,function*(){if("function"!=typeof this.auth.loginOption.loginExtensionProvider)return"";try{var t=yield this.auth.loginOption.loginExtensionProvider(e);if("string"==typeof t)return t;throw this.core.logger.error("V2NIMLoginService::excute loginExtensionProvider complete but got Unexpected value:",t),new pe({code:de.V2NIM_ERROR_CODE_CALLBACK_FAILED,detail:{reason:"Excute loginExtensionProvider complete but got Unexpected value",rawData:t}})}catch(e){var i=e,r=i;if(i.code!==de.V2NIM_ERROR_CODE_CALLBACK_FAILED&&(this.core.logger.error("V2NIMLoginService::excute loginExtensionProvider error:",i),r=new pe({code:de.V2NIM_ERROR_CODE_CALLBACK_FAILED,detail:{reason:"Excute loginExtensionProvider error",rawError:e}})),2===this.auth.loginOption.authType)throw this.processLoginFailed(i),r;return""}})}processLoginFailed(e){this.auth.clientSocket.doDisconnect(Dt.ACTIVE,e),this.checkLoginTerminalCode(e.code)&&(this.auth.authenticator.reset(),this.auth.authenticator.clearLastLoginClient()),this.auth.lifeCycle.processEvent("loginFail",e)}changeLoginClient(e,t){var i=t.map(e=>Mt(e));if(1===e)this.loginClients=i,this.auth.emit("onLoginClientChanged",e,this.loginClients);else if(2===e){var r=i.filter(e=>{var t=this.loginClients.filter(t=>t.clientId===e.clientId);return this.loginClients.push(e),0===t.length});r.length>0&&this.auth.emit("onLoginClientChanged",e,r)}else if(3===e){var s=i.filter(e=>(function(e,t){t=t||(()=>!0);for(var i=[],r=(e=e||[]).length,s=0,n=0;nt.clientId===e.clientId&&t.consid===e.consid),0===this.loginClients.filter(t=>t.clientId===e.clientId).length));s.length>0&&this.auth.emit("onLoginClientChanged",e,s)}}checkAutoLogin(e){if(e)return!1;var t=Oe.localStorage.getItem(this.lastLoginClientKey);if(!t)return!1;var i="",r="";try{var s=JSON.parse(t);i=Ve(s,"clientId"),r=Ve(s,"account")}catch(e){return!1}return i===this.auth.deviceId&&r===this.auth.account}checkLoginTerminalCode(e){return[de.V2NIM_ERROR_CODE_CANCELLED,de.V2NIM_ERROR_CODE_TIMEOUT,de.V2NIM_ERROR_CODE_HANDSHAKE,302,317,de.V2NIM_ERROR_CODE_FORBIDDEN,de.V2NIM_ERROR_CODE_NOT_FOUND,de.V2NIM_ERROR_CODE_PARAMETER_ERROR,de.V2NIM_ERROR_CODE_MULTI_LOGIN_FORBIDDEN,422,de.V2NIM_ERROR_CODE_IM_DISABLED,de.V2NIM_ERROR_CODE_APPKEY_NOT_EXIST,de.V2NIM_ERROR_CODE_BUNDLEID_CHECK_FAILED,de.V2NIM_ERROR_CODE_APPKEY_BLOCKED,de.V2NIM_ERROR_CODE_INVALID_TOKEN,de.V2NIM_ERROR_CODE_ROBOT_NOT_ALLOWED,de.V2NIM_ERROR_CODE_ACCOUNT_NOT_EXIST,de.V2NIM_ERROR_CODE_ACCOUNT_BANNED,de.V2NIM_ERROR_CODE_USER_PROFILE_NOT_EXIST].includes(e)}reset(){this.loginClients=[],this.loginClientOfThisConnection={}}clearLastLoginClient(){Oe.localStorage.removeItem(this.lastLoginClientKey)}}class ii extends ne{constructor(e,t){super(),this.name=e,this.logger=t.logger,this.core=t}checkV2(){var e=this.core.options.apiVersion;if("v2"===e)return!0;throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:`The version "${e}" of client is not supported.`}})}checkLogin(){if(0===this.core.V2NIMLoginService.getLoginStatus())throw new pe({code:de.V2NIM_ERROR_CODE_ILLEGAL_STATE,detail:{reason:"Client logout."}})}emit(e,...t){this.logger.debug(`${this.name}::emit event: '${e.toString()}',`,void 0!==t[0]?t[0]:"",void 0!==t[1]?t[1]:"",void 0!==t[2]?t[2]:"");try{return super.emit(e,...t)}catch(t){return setTimeout(()=>{throw this.logger.error(`${this.name}::emit throw error in setTimeout. event: ${e.toString()}. Error`,t),t},0),!1}}process(e){var t=this[e.cmd+"Handler"],i=this.handler&&this.handler[e.cmd+"Handler"];if("function"==typeof t||"function"==typeof i){if(e.error)return this.logger.error(`${e.cmd}::recvError`,e.error),Promise.reject(e.error);try{var r=t?t.call(this,e):i.call(this.handler,e);return Promise.resolve(r)}catch(e){return Promise.reject(e)}}var s=Ve(e,"error.detail.ignore");return e.error&&!s?Promise.reject(e.error):Promise.resolve(e)}}class ri{constructor(e){this.name="V2NIMLoginLifeCycle",this.loginStatus=0,this.connectStatus=0,this.core=e,this.auth=e.V2NIMLoginService,this.logger=e.logger}processEvent(e,t,i){var r=this.getConnectStatus();switch(e){case"addressing":this.logger.log(`${this.name}::addressing`),this.setLoginStatus(2),this.setConnectStatus(2);break;case"connect":this.logger.log(`${this.name}::connecting`),this.setLoginStatus(2),this.setConnectStatus(2);break;case"connectSucc":this.logger.log(`${this.name}::connect success`),this.setLoginStatus(2),this.setConnectStatus(1);break;case"connectFail":this.logger.log(`${this.name}::connect fail`,t),this.setLoginStatus(3),this.setConnectStatus(0,t);break;case"connectionBroken":this.logger.log(`${this.name}::connectionBroken:`,t),this.setLoginStatus(3),this.setConnectStatus(0,t),this.core.eventBus.emit("V2NIMLoginService/loginLifeCycleDisconnected",t);break;case"loginSucc":this.logger.log(`${this.name}::login success, verify authentication success`),this.setLoginStatus(1),this.core.eventBus.emit("V2NIMLoginService/loginLifeCycleLoginSucc",i);break;case"loginFail":if(this.logger.log(`${this.name}::login fail due to verify authentication failed:`,t),!t)return;this.setLoginStatus(this.auth.authenticator.checkLoginTerminalCode(t.code)?0:3),this.setConnectStatus(0,t),this.auth.emit("onLoginFailed",t);break;case"logout":this.logger.log(`${this.name}::logout`),this.setLoginStatus(0),this.setConnectStatus(0),this.core.eventBus.emit("V2NIMLoginService/loginLifeCycleLogout");break;case"kicked":this.logger.log(`${this.name}::kicked`,i),this.setLoginStatus(0),this.setConnectStatus(0,t),this.core.eventBus.emit("V2NIMLoginService/loginLifeCycleKicked");break;case"exited":this.logger.log(`${this.name}::exited`,t),this.setLoginStatus(0),this.setConnectStatus(0,t);break;case"waiting":this.logger.log(`${this.name}::waiting to reconnect`),this.setLoginStatus(3),this.setConnectStatus(3),2!==r&&this.auth.reconnect.attempToReLogin()}}getConnectStatus(){return this.connectStatus}getLoginStatus(){return this.loginStatus}setLoginStatus(e){e!==this.loginStatus&&(this.loginStatus=e,this.auth.emit("onLoginStatus",e))}setConnectStatus(e,t){if(e!==this.connectStatus){var i=this.connectStatus;this.connectStatus=e,this.auth.emit("onConnectStatus",e),this.delegateConnectEvent(i,e,t)}}delegateConnectEvent(e,t,i){1===e&&0===t&&i&&this.auth.emit("onDisconnected",i),2===e&&0===t&&i&&this.auth.emit("onConnectFailed",i)}}class si{constructor(e){this.core=e,this.auth=e.V2NIMLoginService,this.datas=[]}switchDataSync(e){return Te(this,void 0,void 0,function*(){var{type:t,state:i,error:r,subType:s}=e,n=this.datas.filter(e=>e.type===t&&e.subType===s);n.length>0?(n[0].state=i,n[0].error=r):this.datas.push({type:t,state:i,subType:s});var o=this.datas.every(e=>3===e.state);1===t&&(2===i&&"mainSync"===s?(this.core.eventBus.emit("V2NIMLoginService/syncing"),this.auth.emit("onDataSync",t,i)):3===i&&o&&(this.core.eventBus.emit("V2NIMLoginService/syncDone",r),this.auth.emit("onDataSync",t,i,r)))})}checkSyncing(){return this.datas.some(e=>"mainSync"===e.subType&&2===e.state)}reset(){this.datas=[]}}var ni={"6_3":"notifylog","6_4":"uploadLog","6_23":"getServerTime","6_31":"notifyDetect","6_32":"uploadDetect","6_37":"wsDetect"},oi={type:1,params:2,result:3,t1:100,t2:101,t3:102,t4:103,t5:104,t6:105},ai={k1:1,k2:2,k3:3,k4:4,k5:5,k6:6,k7:7,k8:8,k9:9,k10:10},ci={notifylog:{sid:6,cid:3,service:"misc"},uploadLog:{sid:6,cid:4,service:"misc",hasPacketResponse:!1,params:[{type:"String",name:"url"},{type:"Property",name:"data",reflectMapper:{type:1,content:2}}]},getServerTime:{sid:6,cid:23,service:"misc",response:[{type:"Long",name:"time"}]},notifyDetect:{sid:6,cid:31,service:"misc",response:[{type:"Property",name:"data",reflectMapper:gt(oi)}]},uploadDetect:{sid:6,cid:32,service:"misc",hasPacketResponse:!1,params:[{type:"Property",name:"data",reflectMapper:oi}]},wsDetect:{sid:6,cid:37,service:"misc",params:[{type:"Property",name:"tag",reflectMapper:ai}],response:[{type:"Property",name:"data",reflectMapper:gt(ai)}]}},di={type:{type:"number"},t1:{type:"number"},t2:{type:"number"},t3:{type:"number"},t4:{type:"number"},t5:{type:"number"},t6:{type:"number"}};class li extends class{constructor(e,t){this.name=e,this.core=t,this.name=e,this.logger=t.logger,this.core=t}process(e){var t=this[e.cmd+"Handler"];if("function"==typeof t)return t.call(this,e);var i=Ve(e,"error.detail.ignore");return e.error&&!i?Promise.reject(e.error):Promise.resolve(e)}}{constructor(e){super("misc",e),this.logLock=!1,this.core=e,mt({cmdMap:ni,cmdConfig:ci}),this.setListener()}setListener(){this.core.eventBus.on("BinaryClientSocket/unpackError",this.wsDetect.bind(this)),this.core.eventBus.on("V2NIMLoginService/loginLifeCycleLoginSucc",()=>{this.core.timeOrigin.setOriginTimetick()}),this.core.eventBus.on("logined",()=>{this.core.timeOrigin.setOriginTimetick()})}getServerTime(){return Te(this,void 0,void 0,function*(){var e=yield this.core.clientSocket.sendCmd("getServerTime");return parseInt(e.content.time)})}wsDetect(e){return Te(this,void 0,void 0,function*(){var t=Object.assign({k1:"val1",k2:"val2"},e),i=null;try{i=(yield this.core.clientSocket.sendCmd("wsDetect",{tag:t})).content.data}catch(e){var r=e;return void(r.code===de.V2NIM_ERROR_CODE_UNPACK_ERROR?(this.logger.warn("misc::wsDetect:998"),this.wsDetectUnreliable(),this.reportBinarySocketDetectResult("packet 998")):this.logger.warn(`misc::wsDetect:failed ${r.code}`))}i&&JSON.stringify(i)!==JSON.stringify(t)?(this.logger.warn("misc::wsDetect:content unreliable"),this.wsDetectUnreliable(),this.reportBinarySocketDetectResult("content unreliable")):this.logger.log("misc::wsDetect:success")})}wsDetectUnreliable(){this.core.clientSocket.doDisconnect(3,"WSDetectUnreliable")}reportBinarySocketDetectResult(e){var t;this.core.reporter.reportTraceStart("exceptions",{user_id:this.core.account,trace_id:null===(t=this.core.clientSocket.socket)||void 0===t?void 0:t.sessionId,start_time:Date.now(),action:2,exception_service:9}),this.core.reporter.reportTraceUpdateV2("exceptions",{code:998,description:`wsDetect::reconnect cause: ${e}`,operation_type:"5",target:"6-37"}),this.core.reporter.reportTraceEnd("exceptions",1)}notifyDetectHandler(e){return Te(this,void 0,void 0,function*(){var t=function(e){return It(di,e)}(e.content.data);t.t3=e.__receiveTimeNode.time,t.t4=Date.now();try{yield this.core.clientSocket.sendCmd("uploadDetect",{data:t})}catch(e){this.core.logger.warn("misc::notifyDetectHandler:upload failed",e)}})}notifylogHandler(){return Te(this,void 0,void 0,function*(){var e=void 0;if(this.logLock)this.core.logger.warn("misc::notifylogHandler:locked");else{this.logLock=!0;try{e=yield this.core.logger.extractLogs()}catch(e){return void(this.logLock=!1)}if(e){var t="";try{t=(yield this.core.cloudStorage.uploadFile("string"==typeof e?{type:"file",filePath:e}:{type:"file",file:e})).url}catch(e){return void(this.logLock=!1)}if(t){t+=(t.indexOf("?")>0?"&":"?")+"download="+(new Date).getTime()+"_web.log";try{yield this.core.clientSocket.sendCmd("uploadLog",{url:t})}catch(e){return void(this.logLock=!1)}try{yield this.logger.afterUpload()}catch(e){}this.logLock=!1}else this.logLock=!1}else this.logLock=!1}})}}function hi(e,t){e=e||{};var i={};return(t=t||[]).forEach(t=>{void 0!==e[t]&&(i[t]=e[t])}),i}var pi={retryCount:{type:"number",min:0,required:!1},forceMode:{type:"boolean",required:!1},authType:{type:"enum",values:[0,1,2],required:!1},syncLevel:{type:"enum",values:[1,0],required:!1},routeConfig:{type:"object",required:!1,rules:{routeEnabled:{type:"boolean",required:!1},routeEnvironment:{type:"string",required:!1}}}},ui=["https://lbs.netease.im/lbs/webconf.jsp"],mi={retryCount:3,timeout:6e4,forceMode:!1,authType:0,syncLevel:0},gi={"27_1":"v2NIMSync","27_10":"v2QChatSync"},vi={v2NIMSync:{sid:27,cid:1,service:"V2NIMSyncService",hasPacketTimer:!1,params:[{type:"Property",name:"tag",reflectMapper:{myInfo:1,offlineMsgs:2,teams:3,roamingMsgs:7,relations:9,friends:11,friendUsers:13,msgReceipts:14,myTeamMembers:15,donnop:16,recallMsg:17,sessionAck:18,broadcastMsgs:20,avSignal:21,superTeams:22,mySuperTeamMembers:23,superTeamRoamingMsgs:24,deleteSuperTeamMsg:25,superTeamSessionAck:26,deleteSelfMsgs:27,stickTopSessions:28,sessionHistoryMsgsDelete:29,p2pTeamModifyMessage:30,superTeamModifyMessage:31,filterMsgs:100}}],response:[{type:"Long",name:"timetag"}]},v2QChatSync:{sid:27,cid:10,service:"V2NIMSyncService",hasPacketTimer:!1,params:[{type:"Property",name:"tag",reflectMapper:{systemNotification:1,pushConfig:2}}],response:[{type:"Long",name:"timetag"}]}},fi={debug(...e){},log(...e){},warn(...e){},error(...e){}};function _i(e){fi=e}function Ii(){return fi}var yi={wifi:2,"2g":3,"3g":4,"4g":5,"5g":6,ethernet:1,unknown:0,none:0,notreachable:0,wwan:0};function Ei(e){var t=null;return{getNetworkStatus:()=>new Promise((t,i)=>{e.getNetworkType({success:function(e){var i;i="boolean"==typeof e.networkAvailable?e.networkAvailable:"none"!==e.networkType.toLowerCase(),t({net_type:yi[e.networkType.toLowerCase()],net_connect:i})},fail:function(){i(new Error("getNetworkType failed"))}})}),onNetworkStatusChange(i){this.offNetworkStatusChange(),e.onNetworkStatusChange&&(t=function(e){var t=e.networkType.toLowerCase();i({isConnected:e.isConnected||"none"!==t,networkType:yi[t]})},e.onNetworkStatusChange(t))},offNetworkStatusChange(){e.offNetworkStatusChange&&(t&&e.offNetworkStatusChange(t),t=null)}}}Ii(),i(function(e,t){e.exports=function(){class e extends Error{constructor(e,t,i,r){super(i),this.source=e,this.code=t,this.desc=i,this.detail=r||{}}}return function(t,i={dataType:"json",method:"GET",timeout:5e3}){var r="text"===i.dataType?"text/plain; charset=UTF-8":"application/json; charset=UTF-8",s="GET"===i.method?function(e){if(e){var t="";return Object.keys(e).forEach(function(i,r){t+=0===r?"?":"&",t+=`${i}=${e[i]}`}),t}return""}(i.params):"";return new Promise(function(n,o){if(window.XMLHttpRequest){var a,c=new XMLHttpRequest;if(c.onreadystatechange=function(){if(4===c.readyState)if(200===c.status){try{a=JSON.parse(c.response||"{}")}catch(e){a=c.response}n({status:c.status,data:a})}else setTimeout(()=>{o(new e(1,c.status,`readyState: ${c.readyState}; statusText: ${c.statusText}`))},0)},c.open(i.method,`${t}${s}`),c.timeout=i.timeout||5e3,c.setRequestHeader("Content-Type",r),i.headers)for(var d in i.headers)c.setRequestHeader(d,i.headers[d]);c.ontimeout=function(t){o(new e(1,408,t&&t.message?t.message:"request timeout"))},c.send(JSON.stringify(i.data))}else o(new e(2,10400,"request no suppout"))})}}()}),i(function(e,t){self,e.exports=function(){var e={d:function(t,i){for(var r in i)e.o(i,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:i[r]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t={};e.d(t,{default:function(){return y}});var i=function e(t){for(var i in function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.directUploadAddr="https://wanproxy-web.127.net",this.retryCount=4,this.trunkSize=4194304,this.trunkUploadTimeout=5e4,this.getOffsetTimeout=1e4,this.version="1.0",this.enableCache=!0,this.logger=console,this.onError=function(e){},this.onProgress=function(e){},this.onUploadProgress=function(e){},this.onComplete=function(e){},this.onUploadInfo=function(e){},t)this[i]=t[i]};function r(e,t){var i="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!i){if(Array.isArray(e)||(i=function(e,t){if(e){if("string"==typeof e)return s(e,t);var i=Object.prototype.toString.call(e).slice(8,-1);return"Object"===i&&e.constructor&&(i=e.constructor.name),"Map"===i||"Set"===i?Array.from(e):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?s(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){i&&(e=i);var r=0,n=function(){};return{s:n,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,c=!1;return{s:function(){i=i.call(e)},n:function(){var e=i.next();return a=e.done,e},e:function(e){c=!0,o=e},f:function(){try{a||null==i.return||i.return()}finally{if(c)throw o}}}}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var i=0,r=new Array(t);iy.expireTime?n.removeItem(c):s.push({fileInfo:d,key:c})}}}catch(e){a.e(e)}finally{a.f()}if(s.length>y.maxFileCache){var l,h=r(s.sort(function(e,t){return t.fileInfo.modifyAt-e.fileInfo.modifyAt}).slice(y.maxFileCache));try{for(h.s();!(l=h.n()).done;){var p=l.value;0===p.key.indexOf("_NosUploader_")&&n.removeItem(p.key)}}catch(e){h.e(e)}finally{h.f()}}}},a=o;function c(e){return(c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function d(e){var t="function"==typeof Map?new Map:void 0;return(d=function(e){if(null===e||(i=e,-1===Function.toString.call(i).indexOf("[native code]")))return e;var i;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return l(e,arguments,u(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),p(r,e)})(e)}function l(e,t,i){return(l=h()?Reflect.construct:function(e,t,i){var r=[null];r.push.apply(r,t);var s=new(Function.bind.apply(e,r));return i&&p(s,i.prototype),s}).apply(null,arguments)}function h(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function p(e,t){return(p=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function u(e){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}var m=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&p(e,t)}(s,e);var t,i,r=(t=s,i=h(),function(){var e,r=u(t);if(i){var s=u(this).constructor;e=Reflect.construct(r,arguments,s)}else e=r.apply(this,arguments);return function(e,t){return!t||"object"!==c(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}(this,e)});function s(e,t){var i;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,s),(i=r.call(this,"NosUploadError:"+e)).errCode=t,i.errMsg=e,i}return s}(d(Error)),g=function e(t,i,r){if("uploading"===t.uploadState){var s=t.config,n=t.param,o=a.getUploadContext(t.fileKey);if(!o)return r(0);var c=new XMLHttpRequest,d=s.directUploadAddr+"/".concat(n.bucketName)+"/".concat(encodeURIComponent(n.objectName))+"?uploadContext"+"&context=".concat(o)+"&version=".concat(s.version);c.onreadystatechange=function(){var n;if("abort"!==t.uploadState&&4===c.readyState){var o;try{o=JSON.parse(c.responseText)}catch(e){o={errMsg:"JsonParseError in getOffset. xhr.status = "+c.status+". xhr.responseText: "+c.responseText,errCode:500}}200===c.status?o.errCode?t.config.onError(new m(o.errMsg,o.errCode)):r(o.offset):c.status.toString().match(/^5/)?e(t,i-1,r):i>0?("function"==typeof(null===(n=s.logger)||void 0===n?void 0:n.error)&&s.logger.error("getOffset(".concat(d,") error. retry after 3 seconds. ").concat((new Date).toTimeString())),setTimeout(function(){e(t,i-1,r)},3500)):c.status?(a.removeFileInfo(t.fileKey),s.onError(new m("getOffset(".concat(d,") error: ").concat(c.status," ").concat(c.statusText)))):s.onError(new m("getOffset(".concat(d,") error. no Error Code")))}},c.open("get",d),c.setRequestHeader("x-nos-token",n.token),c.timeout=s.getOffsetTimeout,c.send()}};function v(e,t){(null==t||t>e.length)&&(t=e.length);for(var i=0,r=new Array(t);i=t.file.size,h=l?t.file.size:i+o.trunkSize,p=Date.now(),u=new XMLHttpRequest,g=o.directUploadAddr+"/".concat(n.bucketName)+"/".concat(encodeURIComponent(n.objectName)),f={};u.upload.onprogress=function(e){if("abort"!==t.uploadState){var r=0;if(e.lengthComputable){var s=i+e.loaded;r=s/t.file.size,o.onProgress(r),o.onUploadProgress({loaded:s,total:t.file.size,percentage:r,percentageText:(100*r).toFixed(2)+"%"})}else o.onError(new m("browser does not support query upload progress"))}},u.onload=function(){if(200!==u.status){var e=u.getAllResponseHeaders();if(e){var t=e.split("\n").reduce(function(e,t){if(0===t.length)return e;var i,r=function(e){if(Array.isArray(e))return e}(i=t.split(": "))||function(e){var t=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=t){var i,r,s=[],n=!0,o=!1;try{for(t=t.call(e);!(n=(i=t.next()).done)&&(s.push(i.value),2!==s.length);n=!0);}catch(e){o=!0,r=e}finally{try{n||null==t.return||t.return()}finally{if(o)throw r}}return s}}(i)||function(e){if(e){if("string"==typeof e)return v(e,2);var t=Object.prototype.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?v(e,2):void 0}}(i)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),s=r[0],n=r[1];return e[s]=n,e},{});o.onUploadInfo({rsp_headers:t})}}},u.onreadystatechange=function(){var n,c;if("abort"!==t.uploadState&&4===u.readyState){var d;try{d=JSON.parse(u.responseText)}catch(e){"function"==typeof(null===(n=o.logger)||void 0===n?void 0:n.error)&&o.logger.error("JsonParseError in uploadTrunk. xhr.status = "+u.status+". xhr.responseText: "+u.responseText,e),d={errMsg:"JsonParseError in uploadTrunk. xhr.status = "+u.status+". xhr.responseText: "+u.responseText}}o.onUploadInfo({transfer_latency:Date.now()-p}),200===u.status?(o.onUploadInfo({http_code:200}),t.setContext(d.context),l?(s(),t.setComplete()):e(t,d.offset,o.retryCount,s)):u.status.toString().match(/^5/)?(o.onUploadInfo({http_code:u.status,req_headers:f}),r>0?e(t,i,r-1,s):(a.removeFileInfo(t.fileKey),o.onError(new m(d.errMsg,d.errCode)))):(o.onUploadInfo({http_code:u.status||0,req_headers:f}),r>0?("function"==typeof(null===(c=o.logger)||void 0===c?void 0:c.error)&&o.logger.error("uploadTrunk(".concat(g,") error. retry after 3 seconds. ").concat((new Date).toTimeString())),setTimeout(function(){e(t,i,r-1,s)},3500)):u.status?(a.removeFileInfo(t.fileKey),o.onError(new m("uploadTrunk(".concat(g,") error: ").concat(u.status," ").concat(u.statusText)))):o.onError(new m("uploadTrunk(".concat(g,") error. no Error Code. Please check your network"))))}};var _=g+"?offset=".concat(i)+"&complete=".concat(l)+"&context=".concat(d)+"&version=".concat(o.version);if(o.onUploadInfo({remote_addr:_,part_size:l?t.file.size-i:o.trunkSize,index:Math.ceil(i/o.trunkSize)}),u.open("post",_),u.setRequestHeader("x-nos-token",n.token),f["x-nos-token"]=n.token,n.md5&&(u.setRequestHeader("content-md5",n.md5),f["content-md5"]=n.md5),t.file.type&&(u.setRequestHeader("content-type",t.file.type),f["content-type"]=t.file.type),u.timeout=o.trunkUploadTimeout,"undefined"!=typeof FileReader){var I=new FileReader;I.addEventListener("load",function(e){var t;(null===(t=null==e?void 0:e.target)||void 0===t?void 0:t.result)instanceof ArrayBuffer&&e.target.result.byteLength>0?u.send(e.target.result):o.onError(new m("Read ArrayBuffer failed",194003))}),I.addEventListener("error",function(e){var t=e.target.error;o.onError(new m("Read ArrayBuffer error. ".concat(t.toString()),194003))}),I.readAsArrayBuffer(c.call(t.file,i,h))}else u.send(c.call(t.file,i,h))}},_=function(){function e(t,i,r){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.uploadState="paused",this.config=r,this.file=t,this.param=i,this.fileKey=a.initFile(i,t,this.config.enableCache),this.resume()}var t;return(t=[{key:"resume",value:function(){var e=this;if("uploading"!==this.uploadState){this.setUploadState("uploading");var t=this.config;g(this,t.retryCount,function(i){f(e,i,t.retryCount,function(){e.setUploadState("ended"),"function"==typeof t.onComplete&&t.onComplete(e.param)})})}}},{key:"pause",value:function(){this.setUploadState("paused")}},{key:"abort",value:function(){"ended"!==this.uploadState&&"abort"!==this.uploadState&&(this.setUploadState("abort"),this.config.onError(new m("Upload Aborted",10499)))}},{key:"setUploadState",value:function(e){e!==this.uploadState&&(this.uploadState=e)}},{key:"setContext",value:function(e){a.setUploadContext(this.fileKey,e,this.config.enableCache),this.param.ctx=e}},{key:"setComplete",value:function(){a.setComplete(this.fileKey,this.config.enableCache),this.setUploadState("ended")}}])&&function(e,t){for(var i=0;iI.expireTime?(a.removeFileInfo(t),null):{uploadInfo:Object.assign({bucketName:i.bucket,objectName:i.obj,token:i.token,ctx:i.ctx},i.payload?{payload:i.payload}:{}),complete:i.end}},setMaxFileCache:function(e){I.maxFileCache=e},setExpireTime:function(e){I.expireTime=e},printCaches:function(){if("undefined"!=typeof localStorage)for(var e=0,t=Object.keys(localStorage);e-1&&r<=a)for(;++i3?"WebKit":/\bOpera\b/.test(w)&&(/\bOPR\b/.test(t)?"Blink":"Presto"))||/\b(?:Midori|Nook|Safari)\b/i.test(t)&&!/^(?:Trident|EdgeHTML)$/.test(D)&&"WebKit"||!D&&/\bMSIE\b/i.test(t)&&("Mac OS"==F?"Tasman":"Trident")||"WebKit"==D&&/\bPlayStation\b(?! Vita\b)/i.test(w)&&"NetFront")&&(D=[a]),"IE"==w&&(a=(/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(t)||0)[1])?(w+=" Mobile",F="Windows Phone "+(/\+$/.test(a)?a:a+".x"),k.unshift("desktop mode")):/\bWPDesktop\b/i.test(t)?(w="IE Mobile",F="Windows Phone 8.x",k.unshift("desktop mode"),P||(P=(/\brv:([\d.]+)/.exec(t)||0)[1])):"IE"!=w&&"Trident"==D&&(a=/\brv:([\d.]+)/.exec(t))&&(w&&k.push("identifying as "+w+(P?" "+P:"")),w="IE",P=a[1]),V){if(function(e,t){var i=null!=e?typeof e[t]:"number";return!(/^(?:boolean|number|string|undefined)$/.test(i)||"object"==i&&!e[t])}(i,"global"))if(T&&(b=(a=T.lang.System).getProperty("os.arch"),F=F||a.getProperty("os.name")+" "+a.getProperty("os.version")),S){try{P=i.require("ringo/engine").version.join("."),w="RingoJS"}catch(t){(a=i.system)&&a.global.system==i.system&&(w="Narwhal",F||(F=a[0].os||null))}w||(w="Rhino")}else"object"==typeof i.process&&!i.process.browser&&(a=i.process)&&("object"==typeof a.versions&&("string"==typeof a.versions.electron?(k.push("Node "+a.versions.node),w="Electron",P=a.versions.electron):"string"==typeof a.versions.nw&&(k.push("Chromium "+P,"Node "+a.versions.node),w="NW.js",P=a.versions.nw)),w||(w="Node.js",b=a.arch,F=a.platform,P=(P=/[\d.]+/.exec(a.version))?P[0]:null));else g(a=i.runtime)==I?(w="Adobe AIR",F=a.flash.system.Capabilities.os):g(a=i.phantom)==M?(w="PhantomJS",P=(a=a.version||null)&&a.major+"."+a.minor+"."+a.patch):"number"==typeof A.documentMode&&(a=/\bTrident\/(\d+)/i.exec(t))?(P=[P,A.documentMode],(a=+a[1]+4)!=P[1]&&(k.push("IE "+P[1]+" mode"),D&&(D[1]=""),P[1]=a),P="IE"==w?String(P[1].toFixed(1)):P[0]):"number"==typeof A.documentMode&&/^(?:Chrome|Firefox)\b/.test(w)&&(k.push("masking as "+w+" "+P),w="IE",P="11.0",D=["Trident"],F="Windows");F=F&&u(F)}if(P&&(a=/(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(P)||/(?:alpha|beta)(?: ?\d)?/i.exec(t+";"+(V&&n.appMinorVersion))||/\bMinefield\b/i.test(t)&&"a")&&(L=/b/i.test(a)?"beta":"alpha",P=P.replace(RegExp(a+"\\+?$"),"")+("beta"==L?C:N)+(/\d+\+?/.exec(a)||"")),"Fennec"==w||"Firefox"==w&&/\b(?:Android|Firefox OS|KaiOS)\b/.test(F))w="Firefox Mobile";else if("Maxthon"==w&&P)P=P.replace(/\.[\d.]+/,".x");else if(/\bXbox\b/i.test(U))"Xbox 360"==U&&(F=null),"Xbox 360"==U&&/\bIEMobile\b/.test(t)&&k.unshift("mobile mode");else if(!/^(?:Chrome|IE|Opera)$/.test(w)&&(!w||U||/Browser|Mobi/.test(w))||"Windows CE"!=F&&!/Mobi/i.test(t))if("IE"==w&&V)try{null===i.external&&k.unshift("platform preview")}catch(t){k.unshift("embedded")}else(/\bBlackBerry\b/.test(U)||/\bBB10\b/.test(t))&&(a=(RegExp(U.replace(/ +/g," *")+"/([.\\d]+)","i").exec(t)||0)[1]||P)?(F=((a=[a,/BB10/.test(t)])[1]?(U=null,x="BlackBerry"):"Device Software")+" "+a[0],P=null):this!=m&&"Wii"!=U&&(V&&O||/Opera/.test(w)&&/\b(?:MSIE|Firefox)\b/i.test(t)||"Firefox"==w&&/\bOS X (?:\d+\.){2,}/.test(F)||"IE"==w&&(F&&!/^Win/.test(F)&&P>5.5||/\bWindows XP\b/.test(F)&&P>8||8==P&&!/\bTrident\b/.test(t)))&&!c.test(a=e.call(m,t.replace(c,"")+";"))&&a.name&&(a="ing as "+a.name+((a=a.version)?" "+a:""),c.test(w)?(/\bIE\b/.test(a)&&"Mac OS"==F&&(F=null),a="identify"+a):(a="mask"+a,w=R?u(R.replace(/([a-z])([A-Z])/g,"$1 $2")):"Opera",/\bIE\b/.test(a)&&(F=null),V||(P=null)),D=["Presto"],k.push(a));else w+=" Mobile";(a=(/\bAppleWebKit\/([\d.]+\+?)/i.exec(t)||0)[1])&&(a=[parseFloat(a.replace(/\.(\d)$/,".0$1")),a],"Safari"==w&&"+"==a[1].slice(-1)?(w="WebKit Nightly",L="alpha",P=a[1].slice(0,-1)):P!=a[1]&&P!=(a[2]=(/\bSafari\/([\d.]+\+?)/i.exec(t)||0)[1])||(P=null),a[1]=(/\b(?:Headless)?Chrome\/([\d.]+)/i.exec(t)||0)[1],537.36==a[0]&&537.36==a[2]&&parseFloat(a[1])>=28&&"WebKit"==D&&(D=["Blink"]),V&&(l||a[1])?(D&&(D[1]="like Chrome"),a=a[1]||((a=a[0])<530?1:a<532?2:a<532.05?3:a<533?4:a<534.03?5:a<534.07?6:a<534.1?7:a<534.13?8:a<534.16?9:a<534.24?10:a<534.3?11:a<535.01?12:a<535.02?"13+":a<535.07?15:a<535.11?16:a<535.19?17:a<536.05?18:a<536.1?19:a<537.01?20:a<537.11?"21+":a<537.13?23:a<537.18?24:a<537.24?25:a<537.36?26:"Blink"!=D?"27":"28")):(D&&(D[1]="like Safari"),a=(a=a[0])<400?1:a<500?2:a<526?3:a<533?4:a<534?"4+":a<535?5:a<537?6:a<538?7:a<601?8:a<602?9:a<604?10:a<606?11:a<608?12:"12"),D&&(D[1]+=" "+(a+="number"==typeof a?".x":/[.+]/.test(a)?"":"+")),"Safari"==w&&(!P||parseInt(P)>45)?P=a:"Chrome"==w&&/\bHeadlessChrome/i.test(t)&&k.unshift("headless")),"Opera"==w&&(a=/\bzbov|zvav$/.exec(F))?(w+=" ",k.unshift("desktop mode"),"zvav"==a?(w+="Mini",P=null):w+="Mobile",F=F.replace(RegExp(" *"+a+"$"),"")):"Safari"==w&&/\bChrome\b/.exec(D&&D[1])?(k.unshift("desktop mode"),w="Chrome Mobile",P=null,/\bOS X\b/.test(F)?(x="Apple",F="iOS 4.3+"):F=null):/\bSRWare Iron\b/.test(w)&&!P&&(P=j("Chrome")),P&&0==P.indexOf(a=/[\d.]+$/.exec(F))&&t.indexOf("/"+a+"-")>-1&&(F=_(F.replace(a,""))),F&&-1!=F.indexOf(w)&&!RegExp(w+" OS").test(F)&&(F=F.replace(RegExp(" *"+v(w)+" *"),"")),D&&!/\b(?:Avant|Nook)\b/.test(w)&&(/Browser|Lunascape|Maxthon/.test(w)||"Safari"!=w&&/^iOS/.test(F)&&/\bSafari\b/.test(D[1])||/^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|SRWare Iron|Vivaldi|Web)/.test(w)&&D[1])&&(a=D[D.length-1])&&k.push(a),k.length&&(k=["("+k.join("; ")+")"]),x&&U&&U.indexOf(x)<0&&k.push("on "+x),U&&k.push((/^on /.test(k[k.length-1])?"":"on ")+U),F&&(a=/ ([\d.+]+)$/.exec(F),d=a&&"/"==F.charAt(F.length-a[0].length-1),F={architecture:32,family:a&&!d?F.replace(a[0],""):F,version:a?a[1]:null,toString:function(){var e=this.version;return this.family+(e&&!d?" "+e:"")+(64==this.architecture?" 64-bit":"")}}),(a=/\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(b))&&!/\bi686\b/i.test(b)?(F&&(F.architecture=64,F.family=F.family.replace(RegExp(" *"+a),"")),w&&(/\bWOW64\b/i.test(t)||V&&/\w(?:86|32)$/.test(n.cpuClass||n.platform)&&!/\bWin64; x64\b/i.test(t))&&k.unshift("32-bit")):F&&/^OS X/.test(F.family)&&"Chrome"==w&&parseFloat(P)>=39&&(F.architecture=64),t||(t=null);var G={};return G.description=t,G.layout=D&&D[0],G.manufacturer=x,G.name=w,G.prerelease=L,G.product=U,G.ua=t,G.version=w&&P,G.os=F||{architecture:null,family:null,version:null,toString:function(){return"null"}},G.parse=e,G.toString=function(){return this.description||""},G.version&&k.unshift(P),G.name&&k.unshift(w),F&&w&&(F!=String(F).split(" ")[0]||F!=w.split(" ")[0]&&!U)&&k.push(U?"("+F+")":"on "+F),k.length&&(G.description=k.join(" ")),G}();s&&n?m(I,function(e,t){s[t]=e}):r.platform=I}).call(t)}),Ii();var Mi=Ii();class Ti extends ne{constructor(e){super(),this.env=e,this.status=0,this.appShowListener=null,this.appHideListener=null,this.flag=!1,this._initAppLifecycleListener()}isActive(){return 0===this.status}getStatus(){return this.status}setStatus(e){var t=this.status;e!==t&&(this.status=e,0===e&&1===t&&this.emit("onPowerMonitorTurnActive"),Mi.log("Adapter powerMonitor::setStatus: ",e))}destroy(){this.status=0,this.flag=!1,this._canIUse()&&(this.appShowListener&&(this.env.offAppShow(this.appShowListener),this.appShowListener=null),this.appHideListener&&(this.env.offAppHide(this.appHideListener),this.appHideListener=null))}_initAppLifecycleListener(){this.flag||(!1!==this._canIUse()?(this.appShowListener=()=>{var e=this.status;this.status=0,1===e&&this.emit("onPowerMonitorTurnActive"),Mi.log("Adapter powerMonitor::onAppShow status:",this.status)},this.appHideListener=()=>{this.status=1,Mi.log("Adapter powerMonitor::onAppHide status:",this.status)},this.env.onAppShow(this.appShowListener),this.env.onAppHide(this.appHideListener),this.flag=!0,Mi.log("Adapter powerMonitor::_initAppLifecycleListener success")):Mi.warn("Adapter powerMonitor::_initAppLifecycleListener env.onAppShow/env.onAppHide not available"))}_canIUse(){return void 0!==this.env&&"function"==typeof this.env.onAppShow&&"function"==typeof this.env.onAppHide&&"function"==typeof this.env.offAppShow&&"function"==typeof this.env.offAppHide}}function Si(){return"undefined"!=typeof tt&&tt.getSystemInfoSync?tt:"undefined"!=typeof swan&&swan.getSystemInfoSync?swan:"undefined"!=typeof my&&my.getSystemInfoSync?my:"undefined"!=typeof wx&&wx.getAppBaseInfo?wx:void 0}class Ni{constructor(e="nim_logs"){this.dirPath="",this.filePath="",this.copyFilePath="",this.maxCapacity=26214400,this.remainCapacity=8388608,this.count=0,this.maxCount=60,this.lastErrorMsg=void 0;var t=Si();t&&(this.dirPath=`${t.env.USER_DATA_PATH}/__nim`,this.filePath=`${this.dirPath}/${e}.log`,this.copyFilePath=`${this.dirPath}/${e}_copy.log`)}makeDir(){var e=Si();if(e){var t=Ii(),i=e.getFileSystemManager();try{var r=i.accessSync(this.dirPath);t.log("logStorage::access dir:",r),("object"==typeof r&&null!==r?r.error||r.errno||r.errCode||r.errNo:0)>200&&i.mkdirSync(this.dirPath,!0)}catch(e){i.mkdirSync(this.dirPath,!0)}try{var s=i.accessSync(this.filePath);t.log("logStorage::access file:",s),("object"==typeof s&&null!==s?s.error||s.errno||s.errCode||s.errNo:0)>200&&i.writeFileSync(this.filePath,"===","utf8")}catch(e){i.writeFileSync(this.filePath,"===","utf8")}}}open(){return Te(this,void 0,void 0,function*(){if(Si()){var e=Ii();try{this.makeDir(),e.log(`logStorage::open log file success:${this.filePath}`)}catch(t){e.warn(`logStorage::open log file failed:${this.filePath}`,t)}yield this.checkCapacity(this.remainCapacity)}})}checkCapacity(e){return Te(this,void 0,void 0,function*(){var t=Si();if(t){var i=Ii(),r=t.getFileSystemManager(),s=this.getSize();if(s>this.maxCapacity){i.log(`logStorage::checksize:exceed,${s} byte`);var n="";try{n=yield this.readLogs(s-e)}catch(e){return void i.log("logStorage::checkCapacity:read failed",e)}i.log(`logStorage::checksize:read success ${s-e} byte`);try{r.unlinkSync(this.filePath)}catch(e){return void i.log("logStorage::checkCapacity:unlink failed",e)}try{r.writeFileSync(this.filePath,n,"utf8")}catch(e){return void i.log("logStorage::checkCapacity:write failed",e)}}else i.log(`logStorage::checkCapacity:not exceeding,${s} byte`)}})}getSize(){var e,t=Si();if(!t)return 0;var i,r=Ii(),s=t.getFileSystemManager();try{i=s.statSync(this.filePath,!1)}catch(e){return r.warn("logStorage::stat failed",e),0}return i.size||(null===(e=i.stats)||void 0===e?void 0:e.size)}readLogs(e=0){var t=Si();if(!t)return Promise.resolve("");var i=Ii(),r=t.getFileSystemManager();return new Promise((t,s)=>{r.readFile({filePath:this.filePath,encoding:"utf8",position:e,success:e=>{var r=e.data;"string"==typeof r?(i.warn(`logStorage::readLogs success ${r.length}`),t(r)):(i.warn("logStorage::readLogs empty"),s(new Error("logStorage::readLogs empty")))},fail:e=>{var t=e.errMsg||e.errorMessage||e.message;i.warn(`logStorage::readLogs failed ${t}`);var r={code:e.errCode||0,message:t};s(r)}})})}close(){}addLogs(e){var t=Si();if(!t)return Promise.resolve();var i=Ii(),r=e.map(e=>e.text).concat("").join("\n");try{t.getFileSystemManager().appendFileSync(this.filePath,r,"utf8")}catch(e){var s=e.errMsg||e.errorMessage||e.message;this.lastErrorMsg!==s&&i.warn("logStorage::append failed",e),this.lastErrorMsg=s}return this.count+=1,this.count>this.maxCount&&(this.count=0,this.checkCapacity(this.remainCapacity)),Promise.resolve()}extractLogs(){return Te(this,void 0,void 0,function*(){var e=Si();if(e){var t=Ii(),i=this.getSize(),r=e.getFileSystemManager();if(i>0){try{r.copyFileSync(this.filePath,this.copyFilePath)}catch(e){return void t.warn("logStorage::copyFileSync failed",e)}return this.copyFilePath}t.warn("logStorage::extractLogs empty")}})}afterUpload(){return Te(this,void 0,void 0,function*(){var e=Si();if(e){var t=Ii(),i=e.getFileSystemManager();try{i.unlinkSync(this.copyFilePath)}catch(e){return void t.log("logStorage::delete copyFilePath failed",e)}}})}}function Ci(e){var t=Ii(),i=Si(),r=e.headers||{};return e.md5&&(r["Content-MD5"]=e.md5),new Promise((s,n)=>{var o=i.uploadFile(Object.assign(Object.assign({url:`${e.commonUploadHost}/${e.nosToken.bucket}`},Object.keys(r).length>0?{header:r}:{}),{formData:{Object:decodeURIComponent(e.nosToken.objectName),"x-nos-token":e.nosToken.token,"x-nos-entity-type":"json"},name:"file",fileName:"file",fileType:e.type,filePath:e.filePath,success(t){if(200==t.statusCode){e.onUploadInfo&&e.onUploadInfo({http_code:t.statusCode});var i={};if("string"==typeof t.data)try{i=JSON.parse(t.data)}catch(i){e.onUploadInfo&&e.onUploadInfo({exception:`JSON parse error:${t.data}`}),n({code:t.statusCode,message:t.errMsg,rawData:t.data})}i.name=e.filePath,i.ext=i.name&&i.name.lastIndexOf(".")>-1?i.name.slice(i.name.lastIndexOf(".")+1).toLowerCase():"",s(i)}else e.onUploadInfo&&e.onUploadInfo({http_code:t.statusCode,exception:t.data,rsp_headers:t.header,req_headers:r}),n({code:t.statusCode,message:t.errMsg,rawData:t.data})},fail(t){e.onUploadInfo&&e.onUploadInfo({http_code:0,exception:t,req_headers:r}),9===t.error||21104===t.errNo||"string"==typeof t.errMsg&&t.errMsg.indexOf("abort")>-1?t.code=de.V2NIM_ERROR_CODE_CANCELLED:t.code=t.error||t.errNo||t.errno||t.errCode||t.code,t.message=t.errMsg||t.errorMessage,n(t)}}));try{e.onUploadStart&&e.onUploadStart(o)}catch(e){t.error("uploadFile: options.onUploadStart error",e),o.abort(),n(e)}e.onUploadProgress&&o.onProgressUpdate(function(t){var i=t.totalBytesExpectedToWrite||t.totalBytesExpectedToSend,r=t.totalBytesWritten||t.totalBytesSent;e.onUploadProgress&&e.onUploadProgress({total:i,loaded:r,percentage:parseFloat((r/i).toFixed(2)),percentageText:t.progress+"%"})})})}function Ai(e){return null}var Oi={clear:()=>wx.clearStorageSync(),getItem:e=>wx.getStorageSync(e),setItem:(e,t)=>wx.setStorageSync(e,t),removeItem:e=>wx.removeStorageSync(e)};function Ri(e,t){return t&&(t.header=t.headers,t.data=t.data||(null==t?void 0:t.params)||{}),new Promise((i,r)=>{wx.request(Object.assign(Object.assign({url:e},t),{success:function(t){"number"==typeof(t=t||{}).statusCode&&t.statusCode.toString().startsWith("2")?(t={data:t.data,status:t.statusCode,errMsg:t.errMsg,header:t.header},i(t)):r({code:t.statusCode||0,message:t.data||`wechat request fail. url: ${e}`})},fail:function(t){var i=`wechat request fail. url: ${e}`;r(t?{code:5===t.errno?de.V2NIM_ERROR_CODE_TIMEOUT:t.errno,message:t.errMsg||i}:{code:0,message:i})}}))})}function bi(){var e=wx.getSystemInfoSync()||{};return{os:e.platform||"",osVer:e.system||"",browser:"",browserVer:"",libEnv:"MINIAPP",hostEnv:"WeiXin",hostEnvEnum:6,hostEnvVer:e.version,model:e.SDKVersion,manufactor:"WeiXin",userAgent:`NIM/Web/WeChatMiniApp(${e.SDKVersion})/V10.9.50/{{appkey}}`,pushDeviceInfo:{PRODUCT:e.model,DEVICE:e.model,MANUFACTURER:e.brand}}}class ki{constructor(e,t=""){if(this.CONNECTING=0,this.OPEN=1,this.CLOSING=2,this.CLOSED=3,this.binaryType="",this.onclose=function(e){Ii().log("wx-app: sockets on close ",e)},this.onerror=function(e){Ii().error("wx-app: sockets error ",e)},this.onmessage=function(e){},this.onopen=function(){},!e)throw new Error("Failed to construct 'socket': url required");this.url=e.replace(/:443(\/|$)/,"$1"),this.protocol=t,this.readyState=this.CONNECTING;var i=this.protocol?{protocols:[this.protocol]}:{};this.socketTask=wx.connectSocket(Object.assign(Object.assign({url:this.url},i),{fail:e=>{this.errorHandler(e)},success:()=>{}})),this.socketTask.onOpen(e=>{this.readyState=this.OPEN,this.binaryType?this.onopen():this.onmessage&&this.onmessage({type:"open",header:e})}),this.socketTask.onError(e=>{this.errorHandler(e)}),this.socketTask.onClose(e=>{this.readyState=this.CLOSED;var{code:t,reason:i,wasClean:r}=e;"function"==typeof this.onclose&&this.onclose&&this.onclose({code:t,reason:i,wasClean:r,type:"close"})}),this.socketTask.onMessage(e=>{this.onmessage&&this.onmessage(e)})}close(){this.socketTask.close({code:1e3,reason:"user force close websocket",complete:()=>{this.socketTask=null}})}send(e){if(this.readyState!==this.OPEN)throw new Error(`wx-app: socket sendMsg when readyState=${this.readyState}`);if(!("string"==typeof e||e instanceof ArrayBuffer))throw new TypeError("wx-app: socket sendMsg only String/ArrayBuffer supported");this.socketTask.send({data:e})}errorHandler(e){Ii().error("wx-app::ws: onerror ",e),this.readyState=this.CLOSED,this.onerror&&this.onerror({type:"error",message:e&&e.errMsg})}}class Li{constructor(e){this.name="V2NIMConversationIdUtil",this.core=e}conversationId(e,t){return`${this.core.account}|${e}|${t}`}p2pConversationId(e){return`${this.core.account}|1|${e}`}teamConversationId(e){return`${this.core.account}|2|${e}`}superTeamConversationId(e){return`${this.core.account}|3|${e}`}messageConversationId(e){return 1===e.conversationType?e.senderId===this.core.account?this.p2pConversationId(e.receiverId):this.p2pConversationId(e.senderId):2===e.conversationType?this.teamConversationId(e.receiverId):this.superTeamConversationId(e.receiverId)}parseConversationType(e){try{if(e&&e.startsWith(`${this.core.account}|`)){var t=e.replace(`${this.core.account}|`,"");return Number(t[0])}return this.core.logger.warn(`conversationId is not start with ${this.core.account}`),0}catch(e){return 0}}parseConversationTargetId(e){try{return e&&e.startsWith(`${this.core.account}|`)?e.replace(`${this.core.account}|`,"").slice(2):(this.core.logger.warn(`conversationId is not start with ${this.core.account}`),"")}catch(e){return""}}convertToV1ConversationId(e){var t=this.parseConversationType(e);return`${1===t?"p2p":2===t?"team":"superTeam"}|${this.parseConversationTargetId(e)}`}}class Vi{constructor(){this.messages=new Map,this.capacity=1e4}reset(){this.messages.clear()}getMessageById(e){if(e)return this.messages.get(e)}getMessagesByConversationId(e){var t=[];return this.messages.forEach(i=>{i.conversationId===e&&t.push(i)}),t}getLastMessageOfConversation(e){var t=this.getMessagesByConversationId(e);if(0!==t.length)return t.reduce((e,t)=>t.createTime>e.createTime?t:e,t[0])}upsertMessages(e){e.forEach(e=>{this.setLRU(e.messageClientId,e)})}setLRU(e,t){if(this.messages.has(e))this.messages.delete(e);else if(this.messages.size>=this.capacity){var i=this.messages.keys().next().value;i&&this.messages.delete(i)}this.messages.set(e,t)}deleteMessage(e){this.messages.delete(e)}deleteMessages(e,t){this.messages.forEach(i=>{e===i.conversationId&&(!t||t&&i.createTimee.senderId!==this.core.account))throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"getTeamMessageReceipts: exist messages senderId is not current user"}});if(e.some(t=>t.receiverId!==e[0].receiverId))throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"getTeamMessageReceipts: exist messages receiverId is not same"}});return(yield this.core.sendCmd("v2GetTeamMessageReceipts",{tag:e})).content.data.map(e=>Object.assign(Object.assign({},e),{conversationId:this.core.V2NIMConversationIdUtil.teamConversationId(e.receiverId)}))})}getTeamMessageReceiptDetail(e){return Te(this,void 0,void 0,function*(){if(_e(Xi,{message:e},"",!0),e.senderId!==this.core.account)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:`getTeamMessageReceiptDetail::senderId ${e.senderId} incorrect`}});var t=yield this.core.sendCmd("v2GetTeamMessageReceiptDetail",{tag:e});return{readReceipt:{conversationId:this.core.V2NIMConversationIdUtil.teamConversationId(e.receiverId),messageClientId:e.messageClientId,messageServerId:e.messageServerId,readCount:t.content.readAccountList.length,unreadCount:t.content.unreadAccountList.length},readAccountList:t.content.readAccountList,unreadAccountList:t.content.unreadAccountList}})}sendTeamMessageReceipts(e){return Te(this,void 0,void 0,function*(){if(e.some(t=>t.conversationId!==e[0].conversationId))throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"getTeamMessageReceipts: conversationId not same"}});if(_e(zi,{messages:e},"",!0),e.some(e=>e.senderId===this.core.account))throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"getTeamMessageReceipts: exist messages senderId is not current user"}});yield this.core.sendCmd("v2SendTeamMessageReceipts",{tag:e})})}syncP2PMessagReceiptsHandler(e){var t=e.content.data.map(e=>{var t=this.core.V2NIMConversationIdUtil.p2pConversationId(e.senderId),i=e.createTime;return this.p2pMessageReceipts[t]=i,{conversationId:t,timestamp:i}});this.service.emit("onReceiveP2PMessageReadReceipts",t)}onP2PMessageReceiptsHandler(e){var t=this.core.V2NIMConversationIdUtil.p2pConversationId(e.content.data.senderId),i=e.content.data.createTime;this.p2pMessageReceipts[t]=i,this.service.emit("onReceiveP2PMessageReadReceipts",[{conversationId:t,timestamp:i}])}onTeamMessageReceiptsHandler(e){var t=e.content.data.map(e=>({conversationId:this.core.V2NIMConversationIdUtil.teamConversationId(e.receiverId),messageServerId:e.messageServerId,messageClientId:e.messageClientId,readCount:e.readCount,unreadCount:e.unreadCount,latestReadAccount:e.latestReadAccount}));this.service.emit("onReceiveTeamMessageReadReceipts",t)}}var dr={"31_1":"v2TeamCreate","32_1":"v2SuperTeamCreate","31_5":"v2TeamInviteMembers","32_5":"v2SuperTeamInviteMembers","31_6":"v2TeamKickMembers","32_6":"v2SuperTeamKickMembers","31_8":"v2TeamLeave","32_7":"v2SuperTeamLeave","31_7":"v2TeamUpdateInfo","32_8":"v2SuperTeamUpdateInfo","31_9":"v2TeamGetInfo","32_9":"v2SuperTeamGetInfo","31_12":"v2TeamDismiss","32_4":"v2SuperTeamDismiss","31_13":"v2TeamApplyToJoin","32_20":"v2SuperTeamApplyToJoin","31_14":"v2TeamAcceptJoinApplication","32_21":"v2SuperTeamAcceptJoinApplication","31_15":"v2TeamRejectJoinApplication","32_22":"v2SuperTeamRejectJoinApplication","31_16":"v2TeamAddManagers","32_26":"v2SuperTeamAddManagers","31_17":"v2TeamRemoveManagers","32_27":"v2SuperTeamRemoveManagers","31_18":"v2TeamTransferOwner","32_31":"v2SuperTeamTransferOwner","31_19":"v2TeamUpdateSelfMemberInfo","32_10":"v2SuperTeamUpdateSelfMemberInfo","31_20":"v2TeamUpdateMember","32_30":"v2SuperTeamUpdateMember","31_21":"v2TeamAcceptInvitation","32_23":"v2SuperTeamAcceptInvitation","31_22":"v2TeamRejectInvite","32_24":"v2SuperTeamRejectInvite","31_33":"v2TeamGetMemberInvitor","32_35":"v2SuperTeamGetMemberInvitor","31_25":"v2TeamMemberSetChatBannedStatus","32_29":"v2SuperTeamMemberSetChatBannedStatus","31_32":"v2TeamSetChatBannedMode","32_28":"v2SuperTeamSetChatBannedMode","31_34":"v2TeamGetByIds","32_36":"v2SuperTeamGetByIds","31_35":"v2TeamMemberGetListByIds","32_37":"v2SuperTeamMemberGetListByIds","31_36":"v2TeamMemberGetList","8_101":"v2TeamCreateMultiSync","8_109":"v2TeamSync","8_119":"v2TeamMemberUpdateMultiSync","8_126":"v2TeamMembersOfSelfInSync","21_101":"v2SuperTeamCreateMultiSync","21_109":"v2SuperTeamSync","21_110":"v2SuperTeamMemberUpdateMultiSync","21_111":"v2SuperTeamMembersOfSelfInSync"},lr={antispamBusinessId:1},hr="V2NIMTeamService",pr={teamId:1,name:3,teamType:{id:4,retConverter:e=>0==+e?1:+e},ownerAccountId:5,memberLimit:{id:6,retType:"number"},isValidTeam:{id:8,retConverter:(e,t)=>1==+e&&(void 0===t[13]||1==+t[13])},memberCount:{id:9,retType:"number"},memberUpdateTime:{id:10,retType:"number"},createTime:{id:11,retType:"number"},updateTime:{id:12,retType:"number"},intro:14,announcement:15,joinMode:{id:16,retType:"number"},serverExtension:18,customerExtension:19,avatar:20,agreeMode:{id:21,retType:"number"},inviteMode:{id:22,retType:"number"},updateInfoMode:{id:23,retType:"number"},updateExtensionMode:{id:24,retType:"number"},chatBannedMode:{id:101,retType:"number"}},ur={teamId:1,accountId:3,memberRole:{id:4,retType:"number"},teamNick:5,bits:{id:7,retType:"number"},inTeam:{id:9,retType:"boolean"},joinTime:{id:10,retType:"number"},updateTime:{id:11,retType:"number"},serverExtension:12,chatBanned:{id:13,retType:"boolean"},invitorAccountId:14,followAccountIds:{id:16,retConverter:e=>{try{return JSON.parse(e)}catch(e){return[]}}}},mr={teamId:1,accountId:3,memberRole:{id:4,retType:"number"},teamNick:5,bits:{id:7,retType:"number"},inTeam:{id:9,retType:"boolean"},updateTime:{id:11,retType:"number"},serverExtension:12,chatBanned:{id:13,retType:"boolean"},invitorAccountId:14,joinTime:{id:15,retType:"number"},followAccountIds:{id:17,retConverter:e=>{try{return JSON.parse(e)}catch(e){return[]}}}},gr={accountIds:{id:1,converter:e=>JSON.stringify(e)},operation:2},vr={v2TeamCreate:{sid:31,cid:1,service:hr,params:[{type:"Property",name:"team",reflectMapper:pr},{type:"StrArray",name:"inviteeAccountIds"},{type:"String",name:"postscript"},{type:"Property",name:"antispamConfig",reflectMapper:lr}],response:[{type:"Property",name:"team",reflectMapper:gt(pr)},{type:"StrArray",name:"failedList"}]},v2SuperTeamCreate:{sid:32,cid:1,service:hr,params:[{type:"Property",name:"team",reflectMapper:pr},{type:"StrArray",name:"inviteeAccountIds"},{type:"String",name:"postscript"},{type:"Property",name:"antispamConfig",reflectMapper:lr}],response:[{type:"Property",name:"team",reflectMapper:gt(pr)},{type:"StrArray",name:"failedList"}]},v2TeamInviteMembers:{sid:31,cid:5,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"},{type:"String",name:"ps"},{type:"String",name:"attach"}],response:[{type:"Long",name:"time"},{type:"StrArray",name:"abortedAccidList"}]},v2SuperTeamInviteMembers:{sid:32,cid:5,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"},{type:"String",name:"ps"},{type:"String",name:"attach"}],response:[{type:"StrArray",name:"abortedAccidList"},{type:"Long",name:"time"}]},v2TeamUpdateInfo:{sid:31,cid:7,service:hr,params:[{type:"Property",name:"team",reflectMapper:pr},{type:"Property",name:"antispamConfig",reflectMapper:lr}],response:[{type:"Long",name:"teamId"},{type:"Long",name:"timestamp"}]},v2SuperTeamUpdateInfo:{sid:32,cid:8,service:hr,params:[{type:"Property",name:"team",reflectMapper:pr},{type:"Property",name:"antispamConfig",reflectMapper:lr}],response:[{type:"Long",name:"timestamp"}]},v2TeamLeave:{sid:31,cid:8,service:hr,params:[{type:"Long",name:"teamId"}]},v2SuperTeamLeave:{sid:32,cid:7,service:hr,params:[{type:"Long",name:"teamId"}]},v2TeamGetInfo:{sid:31,cid:9,service:hr,params:[{type:"Long",name:"teamId"}],response:[{type:"Property",name:"team",reflectMapper:gt(pr)}]},v2SuperTeamGetInfo:{sid:32,cid:9,service:hr,params:[{type:"Long",name:"teamId"}],response:[{type:"Property",name:"team",reflectMapper:gt(pr)}]},v2TeamGetByIds:{sid:31,cid:34,service:hr,params:[{type:"LongArray",name:"teamIds"}],response:[{type:"PropertyArray",name:"teams",reflectMapper:gt(pr)},{type:"LongArray",name:"tids"}]},v2SuperTeamGetByIds:{sid:32,cid:36,service:hr,params:[{type:"LongArray",name:"teamIds"}],response:[{type:"PropertyArray",name:"teams",reflectMapper:gt(pr)},{type:"LongArray",name:"tids"}]},v2TeamDismiss:{sid:31,cid:12,service:hr,params:[{type:"Long",name:"teamId"}]},v2SuperTeamDismiss:{sid:32,cid:4,service:hr,params:[{type:"Long",name:"teamId"}]},v2TeamAcceptInvitation:{sid:31,cid:21,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"from"}],response:[{type:"Property",name:"team",reflectMapper:gt(pr)}]},v2SuperTeamAcceptInvitation:{sid:32,cid:23,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"from"}],response:[{type:"Property",name:"team",reflectMapper:gt(pr)}]},v2TeamRejectInvite:{sid:31,cid:22,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"from"},{type:"String",name:"ps"}]},v2SuperTeamRejectInvite:{sid:32,cid:24,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"from"},{type:"String",name:"ps"}]},v2TeamKickMembers:{sid:31,cid:6,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"}]},v2SuperTeamKickMembers:{sid:32,cid:6,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"}]},v2TeamApplyToJoin:{sid:31,cid:13,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"ps"}],response:[{type:"Property",name:"team",reflectMapper:gt(pr)},{type:"Int",name:"isInTeam"}]},v2SuperTeamApplyToJoin:{sid:32,cid:20,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"ps"}],response:[{type:"Property",name:"team",reflectMapper:gt(pr)},{type:"Int",name:"isInTeam"}]},v2TeamAcceptJoinApplication:{sid:31,cid:14,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"from"}]},v2SuperTeamAcceptJoinApplication:{sid:32,cid:21,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"from"}]},v2TeamRejectJoinApplication:{sid:31,cid:15,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"from"},{type:"String",name:"ps"}]},v2SuperTeamRejectJoinApplication:{sid:32,cid:22,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"from"},{type:"String",name:"ps"}]},v2TeamAddManagers:{sid:31,cid:16,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"}]},v2SuperTeamAddManagers:{sid:32,cid:26,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"}]},v2TeamRemoveManagers:{sid:31,cid:17,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"}]},v2SuperTeamRemoveManagers:{sid:32,cid:27,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"}]},v2TeamTransferOwner:{sid:31,cid:18,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"account"},{type:"Bool",name:"leave"}]},v2SuperTeamTransferOwner:{sid:32,cid:31,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"account"},{type:"Bool",name:"leave"}]},v2TeamUpdateSelfMemberInfo:{sid:31,cid:19,service:hr,params:[{type:"Property",name:"teamMember",reflectMapper:ur},{type:"Property",name:"specialFollowUpdate",reflectMapper:gr},{type:"Property",name:"antispam",reflectMapper:lr}],response:[{type:"Property",name:"data",reflectMapper:gt(ur)}]},v2SuperTeamUpdateSelfMemberInfo:{sid:32,cid:10,service:hr,params:[{type:"Property",name:"teamMember",reflectMapper:mr},{type:"Property",name:"specialFollowUpdate",reflectMapper:gr},{type:"Property",name:"antispam",reflectMapper:lr}],response:[{type:"Property",name:"data",reflectMapper:gt(mr)}]},v2TeamUpdateMember:{sid:31,cid:20,service:hr,params:[{type:"Property",name:"teamMember",reflectMapper:ur},{type:"Property",name:"antispam",reflectMapper:lr}]},v2SuperTeamUpdateMember:{sid:32,cid:30,service:hr,params:[{type:"Property",name:"teamMember",reflectMapper:mr},{type:"Property",name:"antispam",reflectMapper:lr}]},v2TeamGetMemberInvitor:{sid:31,cid:33,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"}],response:[{type:"StrStrMap",name:"accountsMap"}]},v2SuperTeamGetMemberInvitor:{sid:32,cid:35,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accounts"}],response:[{type:"StrStrMap",name:"accountsMap"}]},v2TeamMemberSetChatBannedStatus:{sid:31,cid:25,service:hr,params:[{type:"Long",name:"teamId"},{type:"String",name:"accountId"},{type:"Int",name:"chatBanned"}]},v2SuperTeamMemberSetChatBannedStatus:{sid:32,cid:29,service:hr,params:[{type:"Long",name:"teamId"},{type:"StrArray",name:"accountId"},{type:"Int",name:"chatBanned"}]},v2TeamSetChatBannedMode:{sid:31,cid:32,service:hr,params:[{type:"Long",name:"teamId"},{type:"Int",name:"chatBannedMode"}]},v2SuperTeamSetChatBannedMode:{sid:32,cid:28,service:hr,params:[{type:"Long",name:"teamId"},{type:"Int",name:"chatBannedMode"}]},v2TeamMemberGetListByIds:{sid:31,cid:35,service:hr,params:[{type:"StrArray",name:"tag"}],response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(ur)}]},v2SuperTeamMemberGetListByIds:{sid:32,cid:37,service:hr,params:[{type:"StrArray",name:"tag"}],response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(mr)}]},v2TeamMemberGetList:{sid:31,cid:36,service:hr,params:[{type:"Property",name:"tag",reflectMapper:{teamId:1,teamType:2,roleQueryType:3,onlyChatBanned:{id:4,converter:e=>+e},nextToken:5,limit:6,direction:7}}],response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(ur)},{type:"Property",name:"pageInfo",reflectMapper:{1:"hasMore",2:"nextToken"}}]},v2TeamSync:{sid:8,cid:109,service:hr,response:[{type:"Long",name:"timetag"},{type:"PropertyArray",name:"datas",reflectMapper:gt(pr)}]},v2TeamCreateMultiSync:{sid:8,cid:101,service:hr,response:[{type:"Property",name:"data",reflectMapper:gt(pr)}]},v2TeamMemberUpdateMultiSync:{sid:8,cid:119,service:hr,response:[{type:"Property",name:"data",reflectMapper:gt(ur)}]},v2TeamMembersOfSelfInSync:{sid:8,cid:126,service:hr,response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(ur)},{type:"Long",name:"timetag"}]},v2SuperTeamSync:{sid:21,cid:109,service:hr,response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(pr)},{type:"Bool",name:"isAll"},{type:"Long",name:"timetag"}]},v2SuperTeamCreateMultiSync:{sid:21,cid:101,service:hr,response:[{type:"Property",name:"data",reflectMapper:gt(pr)}]},v2SuperTeamMemberUpdateMultiSync:{sid:21,cid:110,service:hr,response:[{type:"Property",name:"data",reflectMapper:gt(mr)}]},v2SuperTeamMembersOfSelfInSync:{sid:21,cid:111,service:hr,response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(mr)},{type:"Long",name:"timetag"}]}};function fr(e,t){if(!e)return{};var i=e;return i.tinfo&&(i.tinfo=function(e){return ut(e,gt(pr))}(i.tinfo),i.tinfo.teamType=t),i.uinfos,void 0!==i.mute&&(i.mute=parseInt(i.mute)),i}function _r(e,t,i={}){return Object.assign({teamId:e,teamType:t,name:"",ownerAccountId:"",memberLimit:0,memberCount:0,createTime:0,updateTime:0,intro:"",announcement:"",avatar:"",joinMode:0,agreeMode:0,inviteMode:0,updateInfoMode:0,updateExtensionMode:0,chatBannedMode:0,isValidTeam:!0},i)}function Ir(e,t,i,r={}){return Object.assign({teamId:e,teamType:t,accountId:i,joinTime:0,inTeam:!0,memberRole:0,chatBanned:!1},r)}function yr(e,t=1){return e.map(e=>function(e,t=1){return e.teamType=t,e.chatBanned=void 0!==e.chatBanned&&e.chatBanned,e}(e,t))}function Er(e,t,i){var r,s=Object.assign(Object.assign({},t),{conversationId:e.V2NIMConversationIdUtil.messageConversationId(t),isSelf:t.senderId===e.account,sendingState:1,messageStatus:{errorCode:(null===(r=null==t?void 0:t.messageStatus)||void 0===r?void 0:r.errorCode)||200},messageSource:i||0});if(s.threadReply&&(s.threadReply=Object.assign(Object.assign({},s.threadReply),{conversationType:s.conversationType,conversationId:s.conversationId})),s.threadRoot&&(s.threadRoot=Object.assign(Object.assign({},s.threadRoot),{conversationType:s.conversationType,conversationId:s.conversationId})),s.isInBlackList&&(s.sendingState=2,s.messageStatus.errorCode=de.V2NIM_ERROR_CODE_ACCOUNT_IN_BLOCK_LIST,delete s.isInBlackList),s.streamConfig){var n=Ve(s.streamConfig,"isStream");if(!1===n)delete s.streamConfig;else if(!0===n&&void 0===s.streamConfig.status)delete s.streamConfig,t.aiConfig&&(t.aiConfig.aiStream=!0,t.aiConfig.aiStreamStatus=0);else if("number"==typeof s.streamConfig.status)return s.streamConfig={status:s.streamConfig.status},function(e){if(e.streamConfig&&e.aiConfig&&(e.aiConfig.aiStream=!0,e.aiConfig.aiStreamStatus=e.streamConfig.status,e.aiConfig.aiRAGs&&(e.streamConfig.rags=e.aiConfig.aiRAGs)),e.attachment&&e.streamConfig){var t=e.attachment;e.streamConfig.lastChunk={content:t.msg,messageTime:e.createTime,chunkTime:t.timestamp,type:t.type,index:t.index},e.aiConfig&&(e.aiConfig.aiStreamLastChunk=e.streamConfig.lastChunk),delete e.attachment}return e.aiConfig&&void 0===e.aiConfig.accountId&&delete e.aiConfig,e}(s)}return s.aiConfig&&void 0===s.aiConfig.accountId&&delete s.aiConfig,Mr(s,e)}function Mr(e,t){return 5===e.messageType?function(e,t){var i,r,s,n,o,a=t.attachment||{};if(t.attachment&&"type"in t.attachment)return t;var c=void 0;if(null===(i=a.data)||void 0===i?void 0:i.tinfo){var{id:d,data:l}=a,h=d>400?2:1,{tinfo:p}=fr(Object.assign({},l),h);c={},c=Me(p,["teamId"])}var u=Object.assign(Object.assign(Object.assign(Object.assign({raw:a.raw,type:Ar(e,a.id)},c?{updatedTeamInfo:c}:{}),{targetIds:(null===(r=a.data)||void 0===r?void 0:r.ids)||((null===(s=a.data)||void 0===s?void 0:s.id)?[a.data.id]:[])}),"string"==typeof(null===(n=a.data)||void 0===n?void 0:n.attach)?{serverExtension:a.data.attach}:{}),"number"==typeof(null===(o=a.data)||void 0===o?void 0:o.mute)?{chatBanned:0!==a.data.mute}:{});return Object.assign(Object.assign({},t),{attachment:u})}(t,e):100===e.messageType?function(e,t){var i,r,s;if("string"==typeof(null===(i=t.attachment)||void 0===i?void 0:i.raw)&&(null===(s=null===(r=e.V2NIMMessageService)||void 0===r?void 0:r.customAttachmentParsers)||void 0===s?void 0:s.length)>0){var n=t.subType||0,o=e.V2NIMMessageService.customAttachmentParsers,a=t.attachment.raw;o.some(i=>{try{var r=i(n,a);if(Se(r))return r.raw=a,t.attachment=r,!0}catch(t){return e.logger.warn(`customAttachmentParser: subType ${n}, raw: ${a}. parse error with ${t}`),!1}return!1})}return t}(t,e):e}function Tr(e,t){return Object.assign(Object.assign({},t),{conversationId:e.V2NIMConversationIdUtil.messageConversationId(t)})}function Sr(e,t){var{createTime:i,senderId:r,receiverId:s,conversationType:n}=t;return{conversationType:n,conversationId:e.V2NIMConversationIdUtil.messageConversationId({conversationType:n,senderId:r,receiverId:s}),senderId:t.senderId,receiverId:t.receiverId,messageServerId:t.messageServerId,createTime:i,messageClientId:t.messageClientId}}function Nr(e,t){var i={7:1,8:2,12:3,13:1,14:2}[t.sysMsgType];return{postscript:t.postscript,revokeType:{7:1,8:2,12:3,13:4,14:5}[t.sysMsgType]||0,revokeAccountId:t.opeAccount||t.senderId,callbackExtension:t.callbackExtension,serverExtension:t.attach||"",messageRefer:{conversationType:i,conversationId:e.V2NIMConversationIdUtil.messageConversationId(Object.assign(Object.assign({},t),{conversationType:i,senderId:t.senderId,receiverId:t.receiverId})),senderId:t.senderId,receiverId:t.receiverId,messageServerId:t.messageServerId,createTime:t.deleteMsgCreatetime,messageClientId:t.messageClientId}}}function Cr(e,t){return{conversationId:1===t.conversationType?e.V2NIMConversationIdUtil.p2pConversationId(t.receiverId):2===t.conversationType?e.V2NIMConversationIdUtil.teamConversationId(t.teamId):e.V2NIMConversationIdUtil.superTeamConversationId(t.teamId),deleteTime:t.deleteTime,serverExtension:t.serverExtension}}function Ar(e,t){var i={0:0,401:401,1:1,402:402,2:2,403:403,3:3,404:404,4:4,405:405,5:5,410:410,6:6,406:406,7:7,407:407,8:8,408:408,9:9,411:411,10:10,409:409};return void 0===i[t]&&e.logger.warn(`[V2NIMMessageService] undefined notification type: ${t}`),"number"==typeof i[t]?i[t]:-1}function Or(e,t){if(!t)return"";switch(e){case 100:return t.raw||"";case 1:case 3:case 2:case 6:return function(e){var t=e,{width:i,height:r,duration:s,path:n,file:o,raw:a,ctx:c,payload:d,bucketName:l,objectName:h,token:p,ext:u}=t,m=Me(t,["width","height","duration","path","file","raw","ctx","payload","bucketName","objectName","token","ext"]),g="string"==typeof u&&"."===u[0]?u.slice(1):u;return JSON.stringify(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},m),void 0===u?{}:{ext:g}),void 0===i?{}:{w:i}),void 0===r?{}:{h:r}),void 0===s?{}:{dur:s}))}(t);case 4:return function(e){return JSON.stringify({lat:e.latitude,lng:e.longitude,title:e.address})}(t);case 12:return function(e){var t=Me(e,["raw"]);try{return JSON.stringify(Object.assign(Object.assign({},t),{durations:e.durations.map(e=>({accid:e.accountId,duration:e.duration}))}))}catch(t){return JSON.stringify(e)}}(t);default:return t.raw||JSON.stringify(t)}}class Rr{constructor(e){this.core=e}doSendFile(e,t){return Te(this,void 0,void 0,function*(){var i=e.attachment;try{var[r,s]=yield this.core.V2NIMStorageService._uploadFile({taskId:e.messageClientId,uploadParams:{fileObj:(null==i?void 0:i.file)||(null==i?void 0:i.path),sceneName:null==i?void 0:i.sceneName}},t,{fileType:e.messageType}),n=Object.assign(Object.assign({},i),{uploadState:1});void 0!==s.w&&(n.width=n.width||s.w),void 0!==s.h&&(n.height=n.height||s.h),void 0!==s.dur&&(n.duration=n.duration||s.dur),n.ext=n.ext&&-1===n.ext.indexOf(".")?`.${n.ext}`:n.ext;var o=["w","h","dur","ext","name"];for(var a in s)o.includes(a)||(n[a]=s[a]);var{raw:c,file:d,path:l}=n,h=Me(n,["raw","file","path"]);e.attachment=JSON.parse(JSON.stringify(h)),e.attachment&&(e.attachment.raw=Or(e.messageType,e.attachment))}catch(t){throw e.attachment&&(e.attachment.uploadState=2),t}})}cancelMessageAttachmentUpload(e){return Te(this,void 0,void 0,function*(){if(_e({messageClientId:{type:"string",allowEmpty:!1}},e,"",!0),![2,6,1,3].includes(e.messageType))throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:`cancelMessageAttachmentUpload: messageType ${e.messageType} incorrect`}});if(2===e.sendingState||1===e.sendingState)throw new pe({code:de.V2NIM_ERROR_CODE_RESOURCE_NOT_EXIST,detail:{reason:"cancelMessageAttachmentUpload: message is already failed or succeeded"}});yield this.core.V2NIMStorageService._cancelUploadFile(e.messageClientId)})}}var br="V2NIMMessageService",kr={"30_1":"v2SendP2pMessage","31_2":"v2SendTeamMessage","30_31":"v2MessageP2pModify","31_37":"v2MessageTeamModify","32_38":"v2MessageSuperTeamModify","7_33":"v2MessageOnModified","4_27":"v2MessageSyncModified","4_28":"v2MessageSuperTeamSyncModified","4_5":"v2BatchMarkRead","4_12":"syncP2PMessagReceipts","30_11":"v2SendP2PMessageReceipt","31_28":"v2SendTeamMessageReceipts","32_2":"v2SendSuperTeamMessage","7_12":"onP2PMessageReceipts","8_31":"onTeamMessageReceipts","31_29":"v2GetTeamMessageReceipts","31_30":"v2GetTeamMessageReceiptDetail","7_2":"onMsg","8_3":"onMsg","7_101":"onMsg","8_102":"onMsg","21_3":"onMsg","21_102":"onMsg","4_4":"syncOfflineMsgs","4_9":"syncRoamingMsgs","4_17":"syncRoamingMsgs","30_13":"v2RevokeMessage","32_17":"v2RevokeSuperTeamMessage","7_14":"onRevokeMessage","7_15":"syncRevokeMessage","21_18":"onRevokeMessage","21_117":"onRevokeMessage","30_23":"v2DeleteMessage","30_24":"v2DeleteMessages","4_21":"syncOnDeleteMessages","7_123":"onDeleteMessage","7_124":"onDeleteMessages","29_17":"v2DownloadLocalAntiSpamVocabs"},Lr={conversationType:{id:0,converter:xr,retConverter:Fr},receiverId:1,senderId:2,fromClientType:4,fromDeviceId:5,fromNick:6,createTime:{id:7,retType:"number"},messageType:{id:8,retType:"number"},text:9,attachment:{id:10,converter:(e,t)=>Or(t.messageType,e),retConverter:(e,t)=>function(e,t){var i;try{switch(i=JSON.parse(e),t){case 100:return{raw:e};case 4:return function(e,t){return{latitude:t.lat,longitude:t.lng,address:t.title,raw:e}}(e,i);case 2:case 3:case 1:case 6:return function(e,t){var{w:i,h:r,dur:s,ext:n}=t,o=Me(t,["w","h","dur","ext"]),a="string"==typeof n&&"."!==n[0]?`.${n}`:n;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},o),void 0===n?{}:{ext:a}),void 0===i?{}:{width:i}),void 0===r?{}:{height:r}),void 0===s?{}:{duration:s}),{raw:e})}(e,i);case 12:return function(e,t){return Object.assign(Object.assign({},t),{durations:t.durations.map(e=>({accountId:e.accid,duration:e.duration})),raw:e})}(e,i);default:return"object"==typeof i&&i?Object.assign(Object.assign({},i),{raw:e}):{raw:e}}}catch(t){return"object"==typeof i&&i?Object.assign(Object.assign({},i),{raw:e}):{raw:e}}}(e,Number(t[8]))},messageClientId:11,messageServerId:12,resend:{id:13,converter:vt,retType:"boolean"},userUpdateTime:{id:14,retType:"number"},serverExtension:15,pushPayload:{id:16,access:"pushConfig.pushPayload"},pushContent:{id:17,access:"pushConfig.pushContent"},forcePushAccountIds:{id:18,access:"pushConfig.forcePushAccountIds",def:e=>{if(e["pushConfig.forcePush"])return"#%@all@%#"},converter:(e,t)=>{if(t["pushConfig.forcePush"])return e?JSON.stringify(e):"#%@all@%#"},retConverter(e){if("#%@all@%#"!==e&&e)try{return JSON.parse(e)}catch(e){return[]}}},forcePushContent:{id:19,access:"pushConfig.forcePushContent"},forcePush:{id:20,access:"pushConfig.forcePush",converter:vt,retType:"boolean"},antispamCustomMessageEnabled:{id:21,def:e=>Ve(e,"antispamConfig.antispamCustomMessage")?1:void 0,retConverter:()=>{}},antispamCustomMessage:{id:22,access:"antispamConfig.antispamCustomMessage"},antispamBusinessId:{id:23,access:"antispamConfig.antispamBusinessId"},clientAntispamHit:{id:24,access:"clientAntispamHit",converter:vt,retType:"boolean"},antispamEnabled:{id:25,access:"antispamConfig.antispamEnabled",converter:vt,retType:"boolean"},needAck:{id:26,access:"messageConfig.readReceiptEnabled",converter:vt,retType:"boolean"},lastMessageUpdateEnabled:{id:28,access:"messageConfig.lastMessageUpdateEnabled",converter:vt,retType:"boolean"},threadReplySenderId:{id:29,access:"threadReply.senderId"},threadReplyReceiverId:{id:30,access:"threadReply.receiverId"},threadReplyTime:{id:31,access:"threadReply.createTime",retType:"number"},threadReplyServerId:{id:32,access:"threadReply.messageServerId"},threadReplyClientId:{id:33,access:"threadReply.messageClientId"},threadRootSenderId:{id:34,access:"threadRoot.senderId"},threadRootReceiverId:{id:35,access:"threadRoot.receiverId"},threadRootTime:{id:36,access:"threadRoot.createTime",retType:"number"},threadRootServerId:{id:37,access:"threadRoot.messageServerId"},threadRootClientId:{id:38,access:"threadRoot.messageClientId"},isDeleted:{id:39,converter:vt,retType:"boolean"},callbackExtension:40,subType:{id:41,retType:"number"},antispamCheating:{id:42,access:"antispamConfig.antispamCheating"},routeEnvironment:{id:43,access:"routeConfig.routeEnvironment"},antispamExtension:{id:44,access:"antispamConfig.antispamExtension"},antispamResult:45,__clientExt:{id:46,converter:ft,retConverter:_t},robotFunction:{id:47,access:"robotConfig.function"},robotTopic:{id:48,access:"robotConfig.topic"},robotCustomContent:{id:49,access:"robotConfig.customContent"},robotAccount:{id:50,access:"robotConfig.accountId"},_conversationOnlineSyncNotify:{id:51},_conversationOnlineSyncData:{id:52},aiAgentMsgDirection:{id:55,access:"aiConfig.aiStatus",retAccess:"aiConfig.aiStatus",retType:"number"},aiAgentAccount:{id:56,access:"aiConfig.accountId",retAccess:"aiConfig.accountId"},aiAgentContent:{id:57,access:"aiConfig.content",converter:ft,retConverter:Fe},aiAgentMessages:{id:58,access:"aiConfig.messages",converter:ft,retConverter:Fe},aiAgentPromptVariables:{id:59,access:"aiConfig.promptVariables",retConverter:Fe},aiAgentModelConfigParams:{id:60,access:"aiConfig.modelConfigParams",converter:ft,retConverter:Fe},errorCode:{id:61,access:"messageStatus.errorCode",converter:Fe,retType:"number"},modifyTime:{id:62,retType:"number"},modifyAccountId:63,aiStream:{id:65,access:"aiConfig.aiStream",retAccess:"streamConfig.isStream",converter:vt,retConverter:function(e){return 1===parseInt(e)}},aiRAGs:{id:66,access:"aiConfig.aiRAGs",retConverter:function(e){try{var t=JSON.parse(e);return t&&t.length>0?t.map(e=>(e.desc&&(e.description=e.desc,delete e.desc),e)):[]}catch(e){return[]}}},aiStreamStatus:{id:67,access:"streamConfig.status",retType:"number"},historyEnabled:{id:100,access:"messageConfig.historyEnabled",converter:vt,retType:"boolean"},roamingEnabled:{id:101,access:"messageConfig.roamingEnabled",converter:vt,retType:"boolean"},onlineSyncEnabled:{id:102,access:"messageConfig.onlineSyncEnabled",converter:vt,retType:"boolean"},routeEnabled:{id:105,access:"routeConfig.routeEnabled",converter:vt,retType:"boolean"},isInBlackList:{id:106,access:"isInBlackList",converter:vt,retType:"boolean"},pushEnable:{id:107,access:"pushConfig.pushEnabled",converter:vt,retType:"boolean"},offlineEnabled:{id:108,access:"messageConfig.offlineEnabled",converter:vt,retType:"boolean"},unreadEnabled:{id:109,access:"messageConfig.unreadEnabled",converter:vt,retType:"boolean"},pushNickEnabled:{id:110,access:"pushConfig.pushNickEnabled",converter:vt,retType:"boolean"},msgAckSnapshot:{id:112,retType:"number"},receiverIds:{id:154,access:"targetConfig.receiverIds",converter:ft,retConverter:()=>{}},inclusive:{id:155,access:"targetConfig.inclusive",converter:e=>e?1:2,retConverter:()=>{}},newMemberVisible:{id:156,access:"targetConfig.newMemberVisible",converter:e=>e?1:2,retConverter:()=>{}}},Vr=(gt(Lr),{conversationType:{id:1,access:"messageRefer.conversationType",retType:"number"},senderId:{id:2,access:"messageRefer.senderId"},receiverId:{id:3,access:"messageRefer.receiverId"},messageServerId:{id:4,access:"messageRefer.messageServerId"},messageClientId:{id:5,access:"messageRefer.messageClientId"},createTime:{id:6,access:"messageRefer.createTime",retType:"number"},deleteTime:{id:7,retType:"number"},serverExtension:8});gt(Vr);var Pr={version:1,md5:2,nosurl:3,thesaurus:4},Dr={createTime:{id:0,retType:"number"},sysMsgType:1,receiverId:2,senderId:3,postscript:4,attach:5,pushContent:8,pushPayload:9,messageClientId:10,messageServerId:11,deleteMsgCreatetime:{id:14,retType:"number"},opeAccount:16,env:21,callbackExtension:22},wr={receiverId:0,messageServerId:1,readCount:{id:100,retType:"number"},unreadCount:{id:101,retType:"number"},messageClientId:102,latestReadAccount:103},Ur={v2BatchMarkRead:{sid:4,cid:5,service:br,hasPacketResponse:!1,params:[{type:"Byte",name:"sid"},{type:"Byte",name:"cid"},{type:"LongArray",name:"ids"}]},v2SendP2pMessage:{sid:30,cid:1,service:br,params:[{type:"Property",name:"tag",reflectMapper:Lr}],response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},onMsg:{sid:7,cid:2,service:br,response:[{type:"Property",name:"msg",reflectMapper:gt(Lr)}]},syncOfflineMsgs:{sid:4,cid:4,service:br,response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(Lr)}]},syncRoamingMsgs:{sid:4,cid:9,service:br,response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(Lr)}]},v2SendP2PMessageReceipt:{sid:30,cid:11,service:br,params:[{type:"Property",name:"tag",reflectMapper:Lr}],response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},v2RevokeMessage:{sid:30,cid:13,service:br,params:[{type:"Property",name:"tag",reflectMapper:Dr}]},v2DeleteMessage:{sid:30,cid:23,service:br,params:[{type:"Property",name:"tag",reflectMapper:Vr}],response:[{type:"Long",name:"timetag"}]},v2DeleteMessages:{sid:30,cid:24,service:br,params:[{type:"PropertyArray",name:"tag",reflectMapper:Vr}],response:[{type:"Long",name:"timetag"}]},v2SendTeamMessage:{sid:31,cid:2,service:br,params:[{type:"Property",name:"tag",reflectMapper:Lr}],response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},v2SendTeamMessageReceipts:{sid:31,cid:28,service:br,params:[{type:"PropertyArray",name:"tag",reflectMapper:wr}],response:[{type:"PropertyArray",name:"tag",reflectMapper:gt(wr)}]},v2SendSuperTeamMessage:{sid:32,cid:2,service:br,params:[{type:"Property",name:"tag",reflectMapper:Lr}],response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},v2RevokeSuperTeamMessage:{sid:32,cid:17,service:br,params:[{type:"Property",name:"tag",reflectMapper:Dr}]},syncP2PMessagReceipts:{sid:4,cid:12,service:br,response:[{type:"PropertyArray",name:"data",reflectMapper:gt(Lr)}]},onP2PMessageReceipts:{sid:7,cid:12,service:br,response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},v2GetTeamMessageReceipts:{sid:31,cid:29,service:br,params:[{type:"PropertyArray",name:"tag",reflectMapper:wr}],response:[{type:"PropertyArray",name:"data",reflectMapper:gt(wr)}]},v2GetTeamMessageReceiptDetail:{sid:31,cid:30,service:br,params:[{type:"Property",name:"tag",reflectMapper:wr,select:["receiverId","messageServerId"]}],response:[{type:"Property",name:"data",reflectMapper:gt(wr)},{type:"StrArray",name:"readAccountList"},{type:"StrArray",name:"unreadAccountList"}]},onTeamMessageReceipts:{sid:8,cid:31,service:br,response:[{type:"PropertyArray",name:"data",reflectMapper:gt(wr)}]},onRevokeMessage:{sid:7,cid:14,service:br,response:[{type:"Property",name:"data",reflectMapper:gt(Dr)}]},syncRevokeMessage:{sid:7,cid:15,service:br,response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(Dr)}]},syncOnDeleteMessages:{sid:4,cid:21,service:br,response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(Vr)}]},onDeleteMessage:{sid:7,cid:123,service:br,response:[{type:"Property",name:"data",reflectMapper:gt(Vr)}]},onDeleteMessages:{sid:7,cid:124,service:br,response:[{type:"PropertyArray",name:"data",reflectMapper:gt(Vr)}]},v2DownloadLocalAntiSpamVocabs:{sid:29,cid:17,service:br,params:[{type:"Property",name:"tag",reflectMapper:Pr}],response:[{type:"Property",name:"data",reflectMapper:gt(Pr)}]},v2MessageP2pModify:{sid:30,cid:31,service:br,params:[{type:"Property",name:"tag",reflectMapper:Lr}],response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},v2MessageTeamModify:{sid:31,cid:37,service:br,params:[{type:"Property",name:"tag",reflectMapper:Lr}],response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},v2MessageSuperTeamModify:{sid:32,cid:38,service:br,params:[{type:"Property",name:"tag",reflectMapper:Lr}],response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},v2MessageOnModified:{sid:7,cid:33,service:br,response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},v2MessageSyncModified:{sid:4,cid:27,service:br,response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(Lr)},{type:"Long",name:"time"}]},v2MessageSuperTeamSyncModified:{sid:4,cid:28,service:br,response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(Lr)},{type:"Long",name:"time"}]}};function xr(e){return 1===e?0:2===e?1:3===e?5:void 0}function Fr(e){var t=parseInt(e);return 0===t?1:1===t?2:5===t?3:0}var Br={timestamp:{id:0,retType:"number"},type:{id:1,retType:"number"},receiverId:2,senderId:3,postscript:4,content:5,idServer:6,offlineEnabled:{id:7,converter:vt,retConverter:function(e,t){return"0"!==t[6]&&!!parseInt(e)},access:"notificationConfig.offlineEnabled"},pushContent:{id:8,access:"pushConfig.pushContent"},pushPayload:{id:9,access:"pushConfig.pushPayload"},deletedIdClient:10,deletedIdServer:11,antispamEnabled:{id:12,converter:vt,retType:"boolean",access:"antispamConfig.antispamEnabled"},antispamCustomNotification:{id:13,access:"antispamConfig.antispamCustomNotification"},deletedMsgCreateTime:14,deletedMsgFromNick:15,opeAccount:16,forcePushAccountIds:{id:18,access:"pushConfig.forcePushAccountIds",def:e=>{if(101===e.type&&e["pushConfig.forcePush"])return"#%@all@%#"},converter:(e,t)=>{if(t["pushConfig.forcePush"])return e?JSON.stringify(e):"#%@all@%#"},retConverter(e){if("#%@all@%#"!==e&&e)try{return JSON.parse(e)}catch(e){return[]}}},forcePushContent:{id:19,access:"pushConfig.forcePushContent"},forcePush:{id:20,converter:vt,retType:"boolean",access:"pushConfig.forcePush"},routeEnvironment:{id:21,access:"routeConfig.routeEnvironment"},callbackExt:22,clientNotificationId:{id:23,access:"notificationConfig.clientNotificationId"},conversationOnlineSyncNotify:24,conversationOnlineSyncData:25,routeEnabled:{id:105,converter:vt,retType:"boolean",access:"routeConfig.routeEnabled"},pushEnabled:{id:107,converter:vt,retType:"boolean",access:"pushConfig.pushEnabled"},unreadEnabled:{id:109,converter:vt,retType:"boolean",access:"notificationConfig.unreadEnabled"},pushNickEnabled:{id:110,converter:vt,retType:"boolean",access:"pushConfig.pushNickEnabled"}},jr={id:1,senderId:2,timestamp:{id:4,retType:"number"},content:5},Gr=(gt(Br),gt(jr),gt(jr),gt(Br),gt(Br),gt(Br),{"4_5":"ysfBatchMarkRead","101_1":"ysfSendMessage","101_2":"ysfOnMsg","4_100":"ysfSyncOfflineMsgs","101_3":"ysfOnSysNotification","101_7":"ysfSendCustomNotification","4_101":"ysfSyncSysNotification"}),$r={ysfBatchMarkRead:{sid:4,cid:5,service:"YSFService",hasPacketResponse:!1,params:[{type:"Byte",name:"sid"},{type:"Byte",name:"cid"},{type:"LongArray",name:"ids"}]},ysfSendMessage:{sid:101,cid:1,service:"YSFService",params:[{type:"Property",name:"tag",reflectMapper:Lr}],response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},ysfOnMsg:{sid:101,cid:2,service:"YSFService",response:[{type:"Property",name:"data",reflectMapper:gt(Lr)}]},ysfSyncOfflineMsgs:{sid:4,cid:100,service:"YSFService",response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(Lr)}]},ysfOnSysNotification:{sid:101,cid:3,service:"YSFService",response:[{type:"Property",name:"data",reflectMapper:gt(Br)}]},ysfSendCustomNotification:{sid:101,cid:7,service:"YSFService",params:[{type:"Property",name:"tag",reflectMapper:Br}]},ysfSyncSysNotification:{sid:4,cid:101,service:"YSFService",response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(Br)}]}},Hr={content:{type:"string",allowEmpty:!1},params:{type:"object",required:!1,rules:{notificationConfig:{type:"object",required:!1,rules:{offlineEnabled:{type:"boolean",required:!1},unreadEnabled:{type:"boolean",required:!1}}},pushConfig:{type:"object",required:!1,rules:{pushEnabled:{type:"boolean",required:!1},pushNickEnabled:{type:"boolean",required:!1},pushContent:{type:"string",required:!1},pushPayload:{type:"string",required:!1},forcePush:{type:"boolean",required:!1},forcePushContent:{type:"string",required:!1},forcePushAccountIds:{type:"array",required:!1,itemType:"string"}}},antispamConfig:{type:"object",required:!1,rules:{antispamEnabled:{type:"boolean",required:!1},antispamCustomNotification:{type:"string",required:!1}}},routeConfig:{type:"object",required:!1,rules:{routeEnabled:{type:"boolean",required:!1},routeEnvironment:{type:"string",required:!1}}}}}};class Yr{constructor(e){this.core=e}generateNotificationTag(e,t,i={}){var r=this.core.V2NIMConversationIdUtil.parseConversationType(e),s=this.core.V2NIMConversationIdUtil.parseConversationTargetId(e),n=Date.now();return Object.assign(Object.assign({},i),{notificationConfig:Object.assign({unreadEnabled:!0,offlineEnabled:!0},null==i?void 0:i.notificationConfig),pushConfig:Object.assign({pushEnabled:!0,pushNickEnabled:!0},null==i?void 0:i.pushConfig),antispamConfig:Object.assign({antispamEnabled:!0},null==i?void 0:i.antispamConfig),routeConfig:Object.assign({routeEnabled:!0},null==i?void 0:i.routeConfig),timestamp:n,type:{1:100,2:101,3:103}[r],receiverId:s,content:t})}}function qr(e){var t="object"==typeof e?e:void 0,i="string"==typeof e?e:void 0;if(!t&&!i)throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"getFileOrPath::incorrect file and path"}});if("string"==typeof i)if(0===i.indexOf("nim-external")){var r=document.getElementById(i);if(!(r&&r.files&&r.files[0]))throw new pe({code:de.V2NIM_ERROR_CODE_FILE_NOT_FOUND,detail:{reason:`getFileOrPath::file not exist: ${i}`}});t=r.files[0]}else if("BROWSER"===Oe.platform)throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:`getFileOrPath::incorrect path: ${i}`}});if("object"==typeof t&&void 0===t.size)throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"getFileOrPath::file no size"}});return{file:t,path:i}}var Kr={attachment:{type:"object",rules:{url:{type:"string",allowEmpty:!1}}},thumbSize:{type:"object",rules:{width:{type:"number",required:!1,min:0},height:{type:"number",required:!1,min:0}}}};class Wr extends ii{constructor(e){super("V2NIMStorageUtil",e),this.core=e}imageThumbUrl(e,t){return e+`?imageView&thumbnail=${t}z${t}`}videoCoverUrl(e,t){return e+`?vframe&offset=${t}`}getImageThumbUrl(e,t){return Te(this,void 0,void 0,function*(){this.checkV2();var i=e;_e(Kr,{attachment:i,thumbSize:t},"",!0),t.width=t.width||0,t.height=t.height||0,0===t.width&&0===t.height&&(t.width=150);var r=i.url;try{r=yield this.core.V2NIMStorageService.shortUrlToLong(i.url)}catch(e){this.core.logger.warn("shortUrlToLong error:",e)}return{url:this.core.cloudStorage.getThumbUrl(r,t)}})}getVideoCoverUrl(e,t){return Te(this,void 0,void 0,function*(){this.checkV2();var i=e;_e(Kr,{attachment:i,thumbSize:t},"",!0),t.width=t.width||0,t.height=t.height||0,0===t.width&&0===t.height&&(t.width=150);var r=i.url;try{r=yield this.core.V2NIMStorageService.shortUrlToLong(i.url)}catch(e){this.core.logger.warn("shortUrlToLong error:",e)}return{url:this.core.cloudStorage.getVideoCoverUrl(r,t)}})}}var Jr,zr,Xr={file:{md5:"$(Etag)",size:"$(ObjectSize)"},image:{md5:"$(Etag)",size:"$(ObjectSize)",w:"$(ImageInfo.Width)",h:"$(ImageInfo.Height)",orientation:"$(ImageInfo.Orientation)"},audio:{md5:"$(Etag)",size:"$(ObjectSize)",dur:"$(AVinfo.Audio.Duration)"},video:{md5:"$(Etag)",size:"$(ObjectSize)",dur:"$(AVinfo.Video.Duration)",w:"$(AVinfo.Video.Width)",h:"$(AVinfo.Video.Height)"}},Qr={accessKeyId:"",secretAccessKey:"",sessionToken:"",region:"",maxRetries:0,bucket:"",objectName:"",token:"",shortUrl:""};function Zr(e="file"){var t=Xr[e]||{};return JSON.stringify(t).replace(/"/gi,'\\"')}!function(e){e[e.nos=1]="nos",e[e.s3=2]="s3"}(Jr||(Jr={})),function(e){e[e.dontNeed=-1]="dontNeed",e[e.time=2]="time",e[e.urls=3]="urls"}(zr||(zr={}));var es={chunkUploadHost:"https://wannos-web.127.net",chunkUploadHostBackupList:["https://fileup.chatnos.com","https://oss.chatnos.com"],commonUploadHost:"https://fileup.chatnos.com",commonUploadHostBackupList:["https://oss.chatnos.com"],chunkMaxSize:4194304e4,commonMaxSize:104857600,uploadReplaceFormat:"https://{host}/{object}",cdn:{defaultCdnDomain:"nim-nosdn.netease.im",cdnDomain:"",bucket:"nim",objectNamePrefix:""},downloadUrl:"https://{bucket}-nosdn.netease.im/{object}",downloadHostList:["nos.netease.com"],nosCdnEnable:!0,isNeedToGetUploadPolicyFromServer:!0};function ts(e,t){e=e||{},t=t||(()=>!0);var i={};for(var r in e)t(e[r])&&(i[r]=e[r]);return i}class is{constructor(e,t){this.nosCdnHostTimer=0,this.nosErrorCount=0,this.core=e,this.cloudStorage=t}get config(){return this.cloudStorage.config}reset(){this.nosErrorCount=0}getNosAccessToken(e){return Te(this,void 0,void 0,function*(){var t=Ve(yield this.core.sendCmd("getNosAccessToken",{tag:e}),"content.nosAccessTokenTag.token"),i=e.url;return{token:t,url:-1!==i.indexOf("?")?i+"&token="+t:i+"?token="+t}})}deleteNosAccessToken(e){return Te(this,void 0,void 0,function*(){yield this.core.sendCmd("deleteNosAccessToken",{tag:e})})}nosUpload(e,t,i){var r,s,n,o,a,c,d,l,h,p;return Te(this,void 0,void 0,function*(){var u=Ve(this.core,"config.cdn.bucket"),m={tag:e.nosScenes||u||"nim"};e.nosSurvivalTime&&(m.expireSec=e.nosSurvivalTime);var g,v=this.core.adapters.getFileUploadInformation(e);if(v&&v.complete&&t.destroy(),!i&&!v)try{g=yield this.core.sendCmd("getNosToken",{responseBody:Zr(e.type),nosToken:m})}catch(e){if(this.core.logger.error("uploadFile:: getNosToken error",e),t.destroy(),e instanceof pe)throw e;throw new ge({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_FILE_UPLOAD_FAILED:400,detail:{reason:"getNosToken error",rawError:e,curProvider:1}})}var f=this.config.uploadReplaceFormat.replace("{bucket}",this.config.cdn.bucket).replace("{host}",this.config.cdn.cdnDomain||this.config.cdn.defaultCdnDomain).replace("{object}",v?null===(r=v.uploadInfo)||void 0===r?void 0:r.objectName:i?null==i?void 0:i.objectName:g.content.nosToken.objectName),_="";i&&i.shortUrl&&(_=i.shortUrl),(null===(o=null===(n=null===(s=null==v?void 0:v.uploadInfo)||void 0===s?void 0:s.payload)||void 0===n?void 0:n.mixStoreToken)||void 0===o?void 0:o.shortUrl)&&(_=v.uploadInfo.payload.mixStoreToken.shortUrl);var I,y=_||f;try{var E=v?{token:null===(a=null==v?void 0:v.uploadInfo)||void 0===a?void 0:a.token,bucket:null===(c=null==v?void 0:v.uploadInfo)||void 0===c?void 0:c.bucketName,objectName:null===(d=null==v?void 0:v.uploadInfo)||void 0===d?void 0:d.objectName}:i||g.content.nosToken;this.core.logger.log("uploadFile:: uploadFile params",{nosToken:E,chunkUploadHost:this.config.chunkUploadHost,chunkUploadHostBackupList:this.config.chunkUploadHostBackupList,commonUploadHost:this.config.commonUploadHost,commonUploadHostBackupList:this.config.commonUploadHostBackupList,platform:Oe.platform});var M="BROWSER"===Oe.platform?this.config.chunkUploadHost:`${this.config.commonUploadHost}/${E&&E.bucket}`,T="UNIAPP"===Oe.platform||"MINIAPP"===(null===(l=Oe.getSystemInfo())||void 0===l?void 0:l.libEnv)?4:i?2:0,S=e.filePath?e.filePath:"object"==typeof e.file?e.file.name:"";t.update({remote_addr:M,operation_type:T}),S&&t.update({local_file:S}),I=yield this.core.adapters.uploadFile(Object.assign(Object.assign(Object.assign(Object.assign({},e),{nosToken:E,chunkUploadHost:this.config.chunkUploadHost,chunkUploadHostBackupList:this.config.chunkUploadHostBackupList,commonUploadHost:this.config.commonUploadHost,commonUploadHostBackupList:this.config.commonUploadHostBackupList,maxSize:e.maxSize||this.config.chunkMaxSize}),i?{payload:{mixStoreToken:i}}:{}),{onUploadInfo:e=>{t.update(Object.assign({},e))}}),t)}catch(r){this.core.logger.error("uploadFile::nos uploadFile error:",r);var N="v2"===Ve(this.core,"options.apiVersion");if(r.code===de.V2NIM_ERROR_CODE_CANCELLED||10499===r.errCode)throw new ge({code:N?de.V2NIM_ERROR_CODE_CANCELLED:400,detail:{reason:Ve(r,"message")||"Request abort",rawError:r,curProvider:1}});if(N&&r.errCode===de.V2NIM_ERROR_CODE_FILE_OPEN_FAILED)throw new pe({code:de.V2NIM_ERROR_CODE_FILE_OPEN_FAILED,detail:{reason:Ve(r,"message")||"Read file failed",rawError:r,curProvider:1}});var{net_connect:C}=yield Oe.net.getNetworkStatus();if(!1===C)throw new ge({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_FILE_UPLOAD_FAILED:400,detail:{reason:"No network",rawError:r,curProvider:1}});if(i){if(this.nosErrorCount<=0){try{this.cloudStorage.mixStorage._addCircuitTimer()}catch(t){throw new ge({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_FILE_UPLOAD_FAILED:400,detail:{reason:"All upload attempts failed",rawError:t,curProvider:this.cloudStorage.mixStorage.curProvider,mixStorePolicy:this.cloudStorage.mixStorage.mixStorePolicy,file:e.file||e.filePath}})}return this.nosErrorCount=Ve(this.cloudStorage,"mixStorePolicy.nosPolicy.uploadConfig.retryPolicy.retry"),this.cloudStorage._uploadFile(e,t)}return this.nosErrorCount--,this.nosUpload(e,t,i)}throw new ge({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_FILE_UPLOAD_FAILED:400,detail:{reason:"NOS attempts failed",rawError:r,curProvider:1}})}var A=null==I?void 0:I.type,O=A&&A.indexOf("/")>-1?A.slice(0,A.indexOf("/")):"";O||(O=e.type||"");var R,b={image:"imageInfo",video:"vinfo",audio:"vinfo"};if(!b[O])return Object.assign({url:y},I);if(I.w&&I.h||I.dur)return Object.assign({url:y},I);try{R=yield this.core.adapters.request(`${f}?${b[O]}`,{method:"GET",dataType:"json",timeout:5e3},{exception_service:3})}catch(e){var k=e;return t.update({exception:`Fetch media info failed;url:${f}?${b[O]};errMsg:${(null===(h=k.detail)||void 0===h?void 0:h.reason)||k.message}`,external_code:k.code}),this.core.logger.error("uploadFile:: fetch file info error",e),Object.assign({url:y},I)}if(R){var{data:L}=R,V="imageInfo"===b[O]?L:null===(p=null==L?void 0:L.GetVideoInfo)||void 0===p?void 0:p.VideoInfo;return ts({url:y,name:I.name,size:I.size,ext:I.ext,w:null==V?void 0:V.Width,h:null==V?void 0:V.Height,orientation:null==V?void 0:V.Orientation,dur:null==V?void 0:V.Duration,audioCodec:null==V?void 0:V.AudioCodec,videoCodec:null==V?void 0:V.VideoCodec,container:null==V?void 0:V.Container},function(e){return void 0!==e})}return Object.assign({url:y},I)})}_getNosCdnHost(){var e;return Te(this,void 0,void 0,function*(){var t;try{t=yield this.core.sendCmd("getNosCdnHost")}catch(e){return void this.core.logger.error("getNosCdnHost::error",e)}if(t){var i=null===(e=null==t?void 0:t.content)||void 0===e?void 0:e.nosConfigTag,r=parseInt(null==i?void 0:i.expire);0!==r&&i.cdnDomain?-1===r?(this.config.cdn.bucket=i.bucket,this.config.cdn.cdnDomain=i.cdnDomain,this.config.cdn.objectNamePrefix=i.objectNamePrefix):(this.config.cdn.bucket=i.bucket,this.config.cdn.cdnDomain=i.cdnDomain,this.config.cdn.objectNamePrefix=i.objectNamePrefix,this.nosCdnHostTimer=this.core.timerManager.addTimer(()=>{this._getNosCdnHost()},1e3*r)):(this.config.cdn.bucket="",this.config.cdn.cdnDomain="",this.config.cdn.objectNamePrefix="")}})}}var rs={"6_2":"getNosToken","6_22":"getOriginUrl","6_24":"getNosAccessToken","6_25":"deleteNosAccessToken","6_26":"getNosCdnHost","6_27":"getGrayscaleConfig","6_28":"getMixStorePolicy","6_29":"getMixStoreToken","6_30":"getFileAuthToken"},ss={nosToken:{objectName:1,token:2,bucket:3,expireTime:4,expireSec:7,tag:8,shortUrl:9},mixStoreTokenReqTag:{provider:0,tokenCount:1,nosSurvivalTime:2,tag:3,returnBody:4,policyVersion:5},nosConfigTag:{bucket:1,cdnDomain:2,expire:3,objectNamePrefix:4},grayConfigTag:{config:0,ttl:1},mixStorePolicyTag:{providers:0,ttl:1,mixEnable:2,nosPolicy:3,s3Policy:4,policyVersion:5},mixStoreTokenResTag:{provider:0,accessKeyId:1,secretAccessKey:2,sessionToken:3,token:4,expireTime:5,bucket:6,objectName:7,fileExpireSec:8,tag:9,shortUrl:10,region:11},nosSafeUrlTag:{safeUrl:0,originUrl:1},mixStoreAuthTokenReqTag:{type:1,urls:2},mixStoreAuthTokenResTag:{type:1,tokens:2,token:3,ttl:4},nosAccessTokenTag:{token:0,url:1,userAgent:2,ext:3}},ns={getNosToken:{sid:6,cid:2,service:"cloudStorage",params:[{type:"String",name:"responseBody"},{type:"Property",name:"nosToken",entity:"nosToken",reflectMapper:ss.nosToken}],response:[{type:"Property",name:"nosToken",reflectMapper:gt(ss.nosToken)}]},getOriginUrl:{sid:6,cid:22,service:"cloudStorage",params:[{type:"Property",name:"nosSafeUrlTag",reflectMapper:ss.nosSafeUrlTag}],response:[{type:"Property",name:"nosSafeUrlTag",reflectMapper:gt(ss.nosSafeUrlTag)}]},getNosCdnHost:{sid:6,cid:26,service:"cloudStorage",response:[{type:"Property",name:"nosConfigTag",reflectMapper:gt(ss.nosConfigTag)}]},getGrayscaleConfig:{sid:6,cid:27,service:"cloudStorage",params:[{type:"Property",name:"config"}],response:[{type:"Property",name:"grayConfigTag",reflectMapper:gt(ss.grayConfigTag)}]},getMixStorePolicy:{sid:6,cid:28,service:"cloudStorage",params:[{type:"LongArray",name:"supportType"}],response:[{type:"Property",name:"mixStorePolicyTag",reflectMapper:gt(ss.mixStorePolicyTag)}]},getMixStoreToken:{sid:6,cid:29,service:"cloudStorage",params:[{type:"Property",name:"mixStoreTokenReqTag",reflectMapper:ss.mixStoreTokenReqTag}],response:[{type:"Property",name:"mixStoreTokenResTag",reflectMapper:gt(ss.mixStoreTokenResTag)}]},getFileAuthToken:{sid:6,cid:30,service:"cloudStorage",params:[{type:"Property",name:"mixStoreAuthTokenReqTag",reflectMapper:ss.mixStoreAuthTokenReqTag}],response:[{type:"Property",name:"mixStoreAuthTokenResTag",reflectMapper:gt(ss.mixStoreAuthTokenResTag)}]},getNosAccessToken:{sid:6,cid:24,service:"cloudStorage",params:[{type:"Property",name:"tag",reflectMapper:ss.nosAccessTokenTag}],response:[{type:"Property",name:"tag",reflectMapper:gt(ss.nosAccessTokenTag)}]},deleteNosAccessToken:{sid:6,cid:25,service:"cloudStorage",params:[{type:"Property",name:"tag",reflectMapper:ss.nosAccessTokenTag}]}};class os{constructor(e,t){this.GRAYKEY="AllGrayscaleConfig",this.MIXSTOREKEY="AllMixStorePolicy",this.grayConfig={mixStoreEnable:!1,timeStamp:0,ttl:0},this.mixStorePolicy={providers:[],timeStamp:0,ttl:0,s3Policy:null,nosPolicy:null,policyVersion:void 0},this.curProvider=1,this.mixStoreErrorCount=10,this.circuitTimer=0,this.core=e,this.cloudStorage=t,this.logger=e.logger}reset(){this.grayConfig=null,this.mixStorePolicy={providers:[],timeStamp:0,ttl:0,s3Policy:null,nosPolicy:null,policyVersion:void 0},this.curProvider=1,this.mixStoreErrorCount=10}getGrayscaleConfig(e,t){var i;return Te(this,void 0,void 0,function*(){if(Oe.localStorage)try{Oe.localStorage.getItem&&Oe.localStorage.getItem(this.GRAYKEY)&&(this.grayConfig=JSON.parse(Oe.localStorage.getItem(this.GRAYKEY))[e])}catch(e){Oe.localStorage.getItem(this.GRAYKEY)&&this.core.logger.error("uploadFile:: JSON.parse grayscaleConfig error ",e)}if(!this.grayConfig||this.grayConfig.timeStamp+1e3*this.grayConfig.ttlt){var i=this.mixStorePolicy.timeStamp+1e3*this.mixStorePolicy.ttl-t;this.core.timerManager.addTimer(this._getMixStorePolicy.bind(this,e),i)}}catch(t){Oe.localStorage.getItem(this.MIXSTOREKEY)&&JSON.parse(Oe.localStorage.getItem(this.MIXSTOREKEY))[e]&&this.core.logger.error("uploadFile:: JSON.parse mixStorePolicy error ",t)}if(!this.mixStorePolicy||this.mixStorePolicy.timeStamp+1e3*this.mixStorePolicy.ttl<=t)try{var r=(yield this.core.sendCmd("getMixStorePolicy",{supportType:this.cloudStorage.aws.s3?[1,2]:[1]})).content.mixStorePolicyTag;this.mixStorePolicy={providers:[],timeStamp:0,ttl:0,s3Policy:null,nosPolicy:null,policyVersion:void 0},this.mixStorePolicy.policyVersion=r.policyVersion,this.mixStorePolicy.ttl=Number(r.ttl),this.mixStorePolicy.providers=r.providers.split(","),this.circuitTimer&&this.core.timerManager.deleteTimer(this.circuitTimer),this.curProvider=parseInt(this.mixStorePolicy.providers[0]),this.mixStorePolicy.nosPolicy=r.nosPolicy?JSON.parse(r.nosPolicy):null,this.mixStorePolicy.s3Policy=r.s3Policy?JSON.parse(r.s3Policy):null,null===this.mixStorePolicy.s3Policy?this.mixStorePolicy.providers=["1"]:null===this.mixStorePolicy.nosPolicy?this.mixStorePolicy.providers=["2"]:this.mixStorePolicy.providers=this.mixStorePolicy.s3Policy.priority{this.logger.log(`uploadFile:: upload policy will change,now policy:${this.curProvider} nextProvider:${parseInt(this.mixStorePolicy.providers[0])}`),this.curProvider=parseInt(this.mixStorePolicy.providers[0]),this.core.timerManager.deleteTimer(this.circuitTimer)},1e3*i)}throw new Error("uploadFile will not retry again")}getFileAuthToken(e){return Te(this,void 0,void 0,function*(){return(yield this.core.sendCmd("getFileAuthToken",{mixStoreAuthTokenReqTag:e})).content.mixStoreAuthTokenResTag})}}var as=-1;class cs{constructor(e,t){this.s3=null,this.core=e,this.cloudStorage=t,this.logger=e.logger}get mixStorePolicy(){return this.cloudStorage.mixStorage.mixStorePolicy}s3Upload(e,t,i){return Te(this,void 0,void 0,function*(){var r;if(as+=1,e.file)r=e.file;else if("string"==typeof e.fileInput){this.logger.warn("fileInput will abandon,Please use file or filepath");var s=document.getElementById(e.fileInput);if(!(s&&s.files&&s.files[0]))throw new Error("Can not get file from fileInput");r=s.files[0]}else{if(!(e.fileInput&&e.fileInput.files&&e.fileInput.files[0]))throw new Error(`Can not get file from fileInput ${e.fileInput}`);r=e.fileInput.files[0]}if(!this.mixStorePolicy.s3Policy)throw new Error("dont get s3 policy");var n={accessKeyId:i.accessKeyId,secretAccessKey:i.secretAccessKey,sessionToken:i.sessionToken,region:i.region,maxRetries:this.mixStorePolicy.s3Policy.uploadConfig.retryPolicy.retry},o=this.s3,a=decodeURIComponent(i.bucket),c=decodeURIComponent(i.objectName),d=r,l=`https://${a}.s3.amazonaws.com/${c}`,h={},p=this.mixStorePolicy.s3Policy;if(p&&p.uploadConfig&&Array.isArray(p.uploadConfig.uploadUrl)&&p.uploadConfig.uploadUrl.length>0){var u=p.uploadConfig.uploadUrl.length;as%=u,h.endpoint=p.uploadConfig.uploadUrl[as],h.s3ForcePathStyle=!0,l=`${h.endpoint}/${a}/${c}`}t.update({local_file:r.name,remote_addr:l,operation_type:1});var m=new o(h);m.config.update(n);var g={Bucket:a,Key:c,Body:d,Metadata:{token:i.token},ContentType:d.type||"application/octet-stream"};this.core.logger.log("uploadFile:: s3 upload params:",g);var v=m.upload(g);return v.on("httpUploadProgress",i=>{t.update({index:i.part});var r=parseFloat((i.loaded/i.total).toFixed(2));e.onUploadProgress&&e.onUploadProgress({total:i.total,loaded:i.loaded,percentage:r,percentageText:Math.round(100*r)+"%"})}),new Promise((r,s)=>{var n=(new Date).getTime();v.send((o,l)=>Te(this,void 0,void 0,function*(){var h,p,u;if(o&&"RequestAbortedError"===o.code)this.logger.error("uploadFile:","api::s3:upload file abort.",o),t.update({http_code:o.statusCode,exception:o}),s(new ge({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_CANCELLED:400,detail:{reason:"S3RequestAbortedError",rawError:o,curProvider:2}}));else{if(!o){t.update({http_code:200});var m=this.mixStorePolicy.s3Policy.cdnSchema;m=(m=m.replace("{cdnDomain}",this.mixStorePolicy.s3Policy.dlcdn)).replace("{objectName}",l.Key);var g={size:d.size,name:d.name,url:i.shortUrl?i.shortUrl:m,ext:d.name.split(".")[1]||"unknown"},v=e.type||"",f={image:"imageInfo"};return r(f[v]?yield this.getS3FileInfo({url:m,infoSuffix:f[v],s3Result:g}):g)}t.update({http_code:o.statusCode,exception:o}),this.core.reporter.reportTraceStart("exceptions",{user_id:this.core.options.account||(null===(p=null===(h=this.core)||void 0===h?void 0:h.auth)||void 0===p?void 0:p.account),trace_id:null===(u=this.core.clientSocket.socket)||void 0===u?void 0:u.sessionId,start_time:n,action:1,exception_service:4}),this.core.reporter.reportTraceUpdateV2("exceptions",{code:"number"==typeof o.status?o.status:"number"==typeof o.code?o.code:0,description:o.message||`${o.code}`,operation_type:1,target:JSON.stringify({bucket:a,object:c})},{asyncParams:Oe.net.getNetworkStatus()}),this.core.reporter.reportTraceEnd("exceptions",1);var{net_connect:_}=yield Oe.net.getNetworkStatus();if(!1===_)return s(new ge({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_FILE_UPLOAD_FAILED:400,detail:{reason:"No network",rawError:o,curProvider:this.cloudStorage.mixStorage.curProvider}}));try{this.cloudStorage.mixStorage._addCircuitTimer()}catch(t){return s(new ge({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_FILE_UPLOAD_FAILED:400,detail:{reason:"All upload attempts failed",rawError:t,curProvider:this.cloudStorage.mixStorage.curProvider,mixStorePolicy:this.mixStorePolicy,file:e.file||e.filePath}}))}r(this.cloudStorage._uploadFile(e,t))}})),e.onUploadStart&&e.onUploadStart(v)})})}getS3FileInfo(e){var t;return Te(this,void 0,void 0,function*(){var i,{url:r,infoSuffix:s,s3Result:n}=e;try{i=yield this.core.adapters.request(`${r}?${s}`,{method:"GET",dataType:"text",timeout:5e3},{exception_service:3})}catch(e){return this.core.logger.error("uploadFile:: fetch file info error",e),n}if(i){var{data:o}=i,a="imageInfo"===s?o:null===(t=null==o?void 0:o.GetVideoInfo)||void 0===t?void 0:t.VideoInfo;return ts(Object.assign(Object.assign({},n),{w:null==a?void 0:a.Width,h:null==a?void 0:a.Height,orientation:null==a?void 0:a.Orientation,dur:null==a?void 0:a.Duration,audioCodec:null==a?void 0:a.AudioCodec,videoCodec:null==a?void 0:a.VideoCodec,container:null==a?void 0:a.Container}),function(e){return void 0!==e})}return this.core.logger.error("uploadFile:: fetch s3 file info no result",`${r}?${s}`),n})}}var ds={user_id:"",trace_id:"",action:0,state:0,duration:0,start_time:0,offset:0,full_size:0,transferred_size:0,operation_type:0,remote_addr:"",local_file:"",retry_times:0,index:0,part_size:0,transfer_latency:0,http_code:0,exception:"",req_headers:"",rsp_headers:""},ls="ReporterHook::setMonitorForResources:";class hs{constructor(e,t){this.traceData=ds,this.core=e,this.id=Math.round(1e3*Math.random()),this.traceData=Object.assign({},ds,t)}start(){var e,t;this.core&&(this.reset(),this.traceData.user_id=this.core.account,this.traceData.trace_id=(null===(t=null===(e=this.core.clientSocket)||void 0===e?void 0:e.socket)||void 0===t?void 0:t.sessionId)||"",this.traceData.start_time="timeOrigin"in this.core?this.core.timeOrigin.getNTPTime():Date.now())}update(e){return Te(this,void 0,void 0,function*(){if(this.core&&this.traceData.user_id){if(e.transferred_size&&this.core.logger.log(`${this.id}.${ls} upload update`,e),"object"==typeof e.exception)try{e.exception=JSON.stringify(e.exception)}catch(t){e.exception="UnknownObject"}if("object"==typeof e.req_headers)try{e.req_headers=JSON.stringify(e.req_headers)}catch(t){e.req_headers="UnknownObject"}if("object"==typeof e.rsp_headers)try{e.rsp_headers=JSON.stringify(e.rsp_headers)}catch(t){e.rsp_headers="UnknownObject"}Object.assign(this.traceData,e)}})}end(e){this.core&&this.traceData.user_id&&(this.core.logger.log(`${ls} upload end cause of ${e}`),this.traceData.state=e,this.traceData.duration=("timeOrigin"in this.core?this.core.timeOrigin.getNTPTime():Date.now())-(this.traceData.start_time||0),this.core.reporter.report("nim_sdk_resources",this.traceData),this.traceData=ds,this.destroy())}reset(){this.traceData=Object.assign({},ds)}destroy(){this.core=void 0,this.traceData=ds}}class ps{constructor(e,t={}){this.config={},this.uploadTaskMap={},this.name="cloudStorage",this.logger=e.logger,this.core=e,this.nos=new is(e,this),this.mixStorage=new os(e,this),this.aws=new cs(e,this),mt({cmdMap:rs,cmdConfig:ns}),this.setOptions(t),this.setListeners()}setOptions(e={}){var t=e.storageKeyPrefix||"NIMClient";this.mixStorage.GRAYKEY=t+"-AllGrayscaleConfig",this.mixStorage.MIXSTOREKEY=t+"-AllMixStorePolicy";var{s3:i}=e,r=Me(e,["s3"]),s=Object.assign({},es,this.config);if(r&&Object.prototype.hasOwnProperty.call(r,"cdn")){var n=Object.assign(Object.assign({},s.cdn),r.cdn);this.config=Object.assign({},s,r),this.config.cdn=n}else this.config=Object.assign({},s,r);i&&(this.aws.s3=i)}setListeners(){this.core.eventBus.on("kicked",this._clearUnCompleteTask.bind(this)),this.core.eventBus.on("disconnect",this._clearUnCompleteTask.bind(this)),this.core.eventBus.on("V2NIMLoginService/loginLifeCycleLogout",this._clearUnCompleteTask.bind(this)),this.core.eventBus.on("V2NIMLoginService/loginLifeCycleKicked",this._clearUnCompleteTask.bind(this))}_clearUnCompleteTask(){Object.keys(this.uploadTaskMap).forEach(e=>{var t=this.uploadTaskMap[e];t&&t.abort&&t.abort()}),this.uploadTaskMap={}}init(e=Date.now()){return Te(this,void 0,void 0,function*(){this.mixStorage.reset(),this.nos.reset(),this.config.isNeedToGetUploadPolicyFromServer&&(yield this.mixStorage.getGrayscaleConfig(this.core.options.appkey,e)),yield this.nos._getNosCdnHost()})}processCallback(e,t,i){var r=e.onUploadProgress,s=e.onUploadDone,n=e.onUploadStart;return{onUploadStart:"function"==typeof n?e=>{this.uploadTaskMap[t]=e;try{n(e)}catch(e){this.logger.error("CloudStorage::uploadFile:options.onUploadStart execute error",e)}}:e=>{this.uploadTaskMap[t]=e},onUploadProgress:"function"==typeof r?e=>{i.update({transferred_size:e.loaded,full_size:e.total});try{r(e)}catch(e){this.logger.error("CloudStorage::uploadFile:options.onUploadProgress execute error",e)}}:e=>{i.update({transferred_size:e.loaded,full_size:e.total})},onUploadDone:"function"==typeof s?e=>{i.end(0);try{s(e)}catch(e){this.logger.error("CloudStorage::uploadFile:options.onUploadDone execute error",e)}}:()=>{i.end(0)},taskKey:t}}uploadFile(e){return Te(this,void 0,void 0,function*(){if(_e({maxSize:{type:"number",required:!1},type:{type:"enum",values:["file","image","audio","video"]}},e),!e.fileInput&&!e.file&&!e.filePath)throw new Error("uploadFile needs target file object or a filePath");if(e.type&&"file"!==e.type){var t=Ve(e,"file.type");if(t&&"string"==typeof t&&-1===t.indexOf(e.type))throw new Error(`The meta type "${t}" does not match "${e.type}"`)}var i=new hs(this.core);if(i.start(),e.file)i.update({full_size:e.file.size,local_file:e.file.name});else if("string"==typeof e.fileInput){var r=document.getElementById(e.fileInput);r&&r.files&&r.files[0]&&i.update({full_size:r.files[0].size,local_file:r.files[0].name})}else e.fileInput&&e.fileInput.files&&e.fileInput.files[0]&&i.update({full_size:e.fileInput.files[0].size,local_file:e.fileInput.files[0].name});var s=De(),{onUploadStart:n,onUploadProgress:o,onUploadDone:a}=this.processCallback(e,s,i);e.onUploadStart=n,e.onUploadProgress=o,e.onUploadDone=a;var c=null;try{c=yield this._uploadFile(e,i),e.md5&&(c.md5=e.md5),delete this.uploadTaskMap[s]}catch(e){throw delete this.uploadTaskMap[s],i.end((e&&e.code)===de.V2NIM_ERROR_CODE_CANCELLED?3:1),e}return c&&(c.size=void 0===c.size?void 0:Number(c.size),c.w=void 0===c.w?void 0:Number(c.w),c.h=void 0===c.h?void 0:Number(c.h),c.dur=void 0===c.dur?void 0:Number(c.dur)),c.url=decodeURIComponent(c.url),e.onUploadDone({size:c.size,name:c.name,url:c.url,ext:c.name.split(".")[1]||"unknown"}),c})}_uploadFile(e,t){var i,r;return Te(this,void 0,void 0,function*(){if(!Ve(this.mixStorage,"grayConfig.mixStoreEnable")||!Ve(this.mixStorage,"mixStorePolicy.providers.length"))return this.logger.log("uploadFile:: uploadFile begin, use old nos"),this.nos.nosUpload(e,t);this.logger.log(`uploadFile::_uploadFile, grayConfig enable:${Ve(this.mixStorage,"grayConfig.mixStoreEnable")} curProvider:${Ve(this.mixStorage,"curProvider")}`);var s=this.core.adapters.getFileUploadInformation(e),n=!0;s?!1===s.complete&&2===this.mixStorage.curProvider?n=!1:s.complete&&t.destroy():n=!1,this.aws.s3||(this.mixStorage.curProvider=1);var o=Qr;if(!n)try{o=(yield this.core.sendCmd("getMixStoreToken",{mixStoreTokenReqTag:{provider:this.mixStorage.curProvider,tokenCount:1,tag:"qchat",nosSurvivalTime:e.nosSurvivalTime,returnBody:Zr(e.type),policyVersion:this.mixStorage.mixStorePolicy.policyVersion}})).content.mixStoreTokenResTag}catch(e){if(this.core.logger.error("uploadFile:: getMixStoreToken error",e),t.destroy(),e instanceof pe)throw e;throw new ge({code:"v2"===Ve(this.core,"options.apiVersion")?de.V2NIM_ERROR_CODE_FILE_UPLOAD_FAILED:400,detail:{reason:"getMixStoreToken error",rawError:e,curProvider:this.mixStorage.curProvider,mixStorePolicy:this.mixStorage.mixStorePolicy}})}return n?this.nos.nosUpload(e,t,null===(r=null===(i=null==s?void 0:s.uploadInfo)||void 0===i?void 0:i.payload)||void 0===r?void 0:r.mixStoreToken):2===this.mixStorage.curProvider?this.aws.s3Upload(e,t,o):this.nos.nosUpload(e,t,o)})}getThumbUrl(e,t){var i,r,s,n,o;if(!new RegExp(/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?/).test(e))return this.logger.error("illegal file url:"+e),e;var[a,c,d,l,h,p,u,m]=/^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/.exec(e);if(null===(i=this.grayConfig)||void 0===i?void 0:i.mixStoreEnable){var g=this._getUrlType(e);if(2===g&&this.mixStorePolicy.s3Policy&&Ve(this.mixStorePolicy,"s3Policy.thumbPolicy.imagethumb"))return(null===(s=null===(r=this.mixStorePolicy.s3Policy)||void 0===r?void 0:r.thumbPolicy)||void 0===s?void 0:s.imagethumb).replace("{cdnDomain}",this.mixStorePolicy.s3Policy.dlcdn).replace("{objectName}",p).replace("{x}",t.width.toString()).replace("{y}",t.height.toString());if(1===g&&this.mixStorePolicy.nosPolicy&&Ve(this.mixStorePolicy,"nosPolicy.thumbPolicy.imagethumb"))return(null===(o=null===(n=this.mixStorePolicy.nosPolicy)||void 0===n?void 0:n.thumbPolicy)||void 0===o?void 0:o.imagethumb).replace("{cdnDomain}",this.mixStorePolicy.nosPolicy.dlcdn).replace("{objectName}",p).replace("{x}",t.width.toString()).replace("{y}",t.height.toString())}return e.includes("?")?e+`&imageView&thumbnail=${t.width}x${t.height}`:e+`?imageView&thumbnail=${t.width}x${t.height}`}getVideoCoverUrl(e,t){var i,r,s,n,o;if(!new RegExp(/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?/).test(e))return this.logger.error("illegal file url:"+e),e;var[a,c,d,l,h,p,u,m]=/^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/.exec(e);if(null===(i=this.grayConfig)||void 0===i?void 0:i.mixStoreEnable){var g=this._getUrlType(e);if(2===g&&this.mixStorePolicy.s3Policy&&Ve(this.mixStorePolicy,"s3Policy.thumbPolicy.vframe"))return(null===(s=null===(r=this.mixStorePolicy.s3Policy)||void 0===r?void 0:r.thumbPolicy)||void 0===s?void 0:s.vframe).replace("{cdnDomain}",this.mixStorePolicy.s3Policy.dlcdn).replace("{objectName}",p).replace("{x}",t.width.toString()).replace("{y}",t.height.toString()).replace("{offset}","0").replace("{type}","png");if(1===g&&this.mixStorePolicy.nosPolicy&&Ve(this.mixStorePolicy,"nosPolicy.thumbPolicy.vframe"))return(null===(o=null===(n=this.mixStorePolicy.nosPolicy)||void 0===n?void 0:n.thumbPolicy)||void 0===o?void 0:o.vframe).replace("{cdnDomain}",this.mixStorePolicy.nosPolicy.dlcdn).replace("{objectName}",p).replace("{x}",t.width.toString()).replace("{y}",t.height.toString()).replace("{offset}","0").replace("{type}","png")}return e.includes("?")?e+`&vframe&offset=0&resize=${t.width}x${t.height}&type=png`:e+`?vframe&offset=0&resize=${t.width}x${t.height}&type=png`}getPrivateUrl(e){var t;if(!new RegExp(/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?/).test(e))return this.logger.error("illegal file url:"+e),"";var[i,r,s,n,o,a,c,d]=/^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/.exec(e);if(null===(t=this.grayConfig)||void 0===t?void 0:t.mixStoreEnable){var l=this._getUrlType(e);return 2===l&&this.mixStorePolicy.s3Policy&&(e=this.mixStorePolicy.s3Policy.cdnSchema.replace("{cdnDomain}",this.mixStorePolicy.s3Policy.dlcdn).replace("{objectName}",a)),1===l&&this.mixStorePolicy.nosPolicy&&(e=this.mixStorePolicy.nosPolicy.cdnSchema.replace("{cdnDomain}",this.mixStorePolicy.nosPolicy.dlcdn).replace("{objectName}",a)),e}var{downloadUrl:h,downloadHostList:p,nosCdnEnable:u}=this.config,m=this.config.cdn.cdnDomain,g=this.config.cdn.objectNamePrefix?decodeURIComponent(this.config.cdn.objectNamePrefix):"",v=decodeURIComponent(a),f=v.indexOf(g);if(m&&f>-1&&u)return`${r}:${s}${m}/${v.slice(f)}`;if(p.includes(n)&&a.includes("/")){var _=a.indexOf("/"),I=a.substring(0,_),y=a.substring(_+1);return h.replace("{bucket}",I).replace("{object}",y)}var E=p.filter(e=>"string"==typeof n&&n.includes(e))[0],M=E?n.replace(E,"").replace(/\W/g,""):null;return M?h.replace("{bucket}",M).replace("{object}",a):e}getOriginUrl(e){return Te(this,void 0,void 0,function*(){return"string"==typeof e&&e.includes("_im_url=1")?(yield this.core.sendCmd("getOriginUrl",{nosSafeUrlTag:{safeUrl:e}})).content.nosSafeUrlTag.originUrl:e})}getFileToken(e){return Te(this,void 0,void 0,function*(){_e({type:{type:"number",min:2,max:3},urls:{type:"array",required:!1,itemType:"string"}},e);var t=this.mixStorePolicy.nosPolicy?this.mixStorePolicy.nosPolicy.authPolicy.policyType:null,i=this.mixStorePolicy.s3Policy?this.mixStorePolicy.s3Policy.authPolicy.policyType:null;if(t===String(-1)&&i===String(-1))throw this.logger.error("don't need token"),new Error("don't need token");if(2===e.type){if(t&&t.indexOf(String(2))>=0||i&&i.indexOf(String(2))>0)return this.mixStorage.getFileAuthToken(e);throw this.logger.error("don't support time token "),new Error("don't support type time token ")}if(!e.urls||!e.urls.length)throw this.logger.error("urls is required when urls token"),new Error("urls is required when urls token");var r=[],s=[];if(e.urls.forEach(e=>{var t=this._getUrlType(e);1===t&&s.push(e),2===t&&r.push(e)}),(!i||0!==r.length&&i.indexOf(String(3))<0)&&(this.logger.warn("s3 url don't support url token"),r=[]),(!t||0!==s.length&&t.indexOf(String(3))<0)&&(this.logger.warn("nos url don't support url token"),s=[]),0===r.length&&0===s.length)throw this.logger.error("not support urls"),new Error("not support urls");if(0===r.length||0===s.length)return e.urls=JSON.stringify(e.urls),this.mixStorage.getFileAuthToken(e)})}_getUrlType(e){return this.mixStorePolicy.nosPolicy&&this.mixStorePolicy.nosPolicy.dlcdns.some(t=>e.indexOf(t)>=0)?1:this.mixStorePolicy.s3Policy&&this.mixStorePolicy.s3Policy.dlcdns.some(t=>e.indexOf(t)>=0)?2:null}getNosAccessToken(e){return _e({url:{type:"string",allowEmpty:!1}},e),this.nos.getNosAccessToken(e)}deleteNosAccessToken(e){return _e({token:{type:"string",allowEmpty:!1}},e),this.nos.deleteNosAccessToken(e)}get grayConfig(){return this.mixStorage.grayConfig}get mixStorePolicy(){return this.mixStorage.mixStorePolicy}process(e){var t=Ve(e,"error.detail.ignore");return e.error&&!t?Promise.reject(e.error):Promise.resolve(e)}}class us extends ii{constructor(e){super("V2NIMStorageService",e),this.sceneMap={nim_default_profile_icon:{sceneName:"nim_default_profile_icon",expireTime:0},nim_default_im:{sceneName:"nim_default_im",expireTime:0},nim_system_nos_scene:{sceneName:"nim_system_nos_scene",expireTime:0},nim_security:{sceneName:"nim_security",expireTime:0}},this.uploadingMessageInfo={},this.core=e,this.core._registerDep(ps,"cloudStorage"),this.core._registerDep(Wr,"V2NIMStorageUtil")}addCustomStorageScene(e,t){return this.checkV2(),_e({sceneName:{type:"string",allowEmpty:!1},expireTime:{type:"number",min:0}},{sceneName:e,expireTime:t},"",!0),this.sceneMap[e]={sceneName:e,expireTime:t},{sceneName:e,expireTime:t}}getStorageSceneList(){return this.checkV2(),Object.values(this.sceneMap)}getStorageScene(e){return e&&this.sceneMap[e]||this.sceneMap.nim_default_im}hasStorageScene(e){return void 0!==this.sceneMap[e]}createUploadFileTask(e){if(this.checkV2(),"string"==typeof e.fileObj&&0===e.fileObj.indexOf("nim-external")){var t=document.getElementById(e.fileObj);t&&t.files&&t.files[0]&&(e.fileObj=t.files[0])}return{taskId:De(),uploadParams:e}}uploadFile(e,t){return Te(this,void 0,void 0,function*(){return this.checkV2(),_e({taskId:{type:"string",allowEmpty:!1}},e,"fileTask",!0),(yield this._uploadFile(e,t))[0]})}uploadFileWithMetaInfo(e,t){return Te(this,void 0,void 0,function*(){return this.checkV2(),_e({taskId:{type:"string",allowEmpty:!1}},e,"fileTask",!0),function(e){var{url:t,name:i,size:r,ext:s,md5:n,h:o,w:a,orientation:c,dur:d,audioCodec:l,videoCodec:h,container:p}=e;return JSON.parse(JSON.stringify({url:t,name:i,size:r,ext:s,md5:n,height:o,width:a,orientation:c,duration:d,audioCodec:l,videoCodec:h,container:p}))}((yield this._uploadFile(e,t))[1])})}_uploadFile(e,t,i){var r;return Te(this,void 0,void 0,function*(){if(!this.core.cloudStorage||!this.core.cloudStorage.uploadFile)throw new Error('Service "cloudStorage" does not exist');var{uploadParams:s,taskId:n}=e,{file:o,path:a}=qr(s.fileObj),{fileType:c}=i||{};if(this.uploadingMessageInfo[n])throw new pe({code:de.V2NIM_ERROR_CODE_RESOURCE_ALREADY_EXIST,detail:{reason:"V2NIMStorageService.uploadFile: repeat upload"}});try{var d={};o?d.file=o:a&&(0===(null==a?void 0:a.indexOf("nim-external"))?d.fileInput=a:d.filePath=a);var l=this.getStorageScene(s.sceneName);if(d.nosScenes=l.sceneName,d.nosSurvivalTime=l.expireTime,d.type=1===c?"image":2===c?"audio":3===c?"video":"file",d.file&&this.core.pluginMap["browser-md5-file"]){var h=yield this.getFileMd5(this.core.pluginMap["browser-md5-file"],n,d.file);d.md5=h}d.onUploadProgress=e=>{"function"==typeof t&&t(Math.round(100*e.percentage))},d.onUploadStart=e=>{var t;if(null===(t=this.uploadingMessageInfo[n])||void 0===t?void 0:t.abort)return e.abort(),void delete this.uploadingMessageInfo[n];this.uploadingMessageInfo[n]={abort:!1,task:e}},this.uploadingMessageInfo[n]={abort:!1};var p=yield this.core.cloudStorage.uploadFile(d);if(null===(r=this.uploadingMessageInfo[n])||void 0===r?void 0:r.abort)throw new pe({code:de.V2NIM_ERROR_CODE_CANCELLED,detail:{reason:"upload file aborted"}});return delete this.uploadingMessageInfo[n],[p.url,p]}catch(e){throw delete this.uploadingMessageInfo[n],this.core.logger.error("sendFile:: upload File error or abort.",e),e}})}cancelUploadFile(e){return Te(this,void 0,void 0,function*(){this.checkV2(),yield this._cancelUploadFile(e.taskId)})}_cancelUploadFile(e){return Te(this,void 0,void 0,function*(){this.checkV2();var t=this.uploadingMessageInfo[e];if(null==t?void 0:t.task)try{this.logger.log("V2NIMStorageService.cancelUploadFile: uploadInfo task exist"),yield t.task.abort(),delete this.uploadingMessageInfo[e]}catch(t){delete this.uploadingMessageInfo[e],this.core.logger.error("cancelMessageAttachmentUpload::abort error.",t)}else{if(!t)throw new pe({code:de.V2NIM_ERROR_CODE_RESOURCE_NOT_EXIST,detail:{reason:"V2NIMStorageService.cancelUploadFile: uploadInfo not exist"}});this.logger.log("V2NIMStorageService.cancelUploadFile: uploadInfo task not exist"),t.abort=!0}})}getFileMd5(e,t,i){return Te(this,void 0,void 0,function*(){return new Promise((r,s)=>{var n,o=new e;(null===(n=this.uploadingMessageInfo[t])||void 0===n?void 0:n.abort)?s(new pe({code:de.V2NIM_ERROR_CODE_CANCELLED,detail:{reason:"upload file aborted"}})):this.uploadingMessageInfo[t]={abort:!1,task:o};try{o.md5(i,(e,t)=>{"aborted"===e?s(new pe({code:de.V2NIM_ERROR_CODE_CANCELLED,detail:{reason:e}})):e?s(new pe({code:de.V2NIM_ERROR_CODE_INTERNAL,detail:{reason:"md5 calculate error in callback",rawError:e}})):r(t)})}catch(e){s(new pe({code:de.V2NIM_ERROR_CODE_INTERNAL,detail:{reason:"md5 calculate error",rawError:e}}))}})})}shortUrlToLong(e){return Te(this,void 0,void 0,function*(){return this.checkV2(),this.core.cloudStorage.getOriginUrl(e)})}getImageThumbUrl(e,t){return Te(this,void 0,void 0,function*(){return this.core.V2NIMStorageUtil.getImageThumbUrl(e,t)})}getVideoCoverUrl(e,t){return Te(this,void 0,void 0,function*(){return this.core.V2NIMStorageUtil.getVideoCoverUrl(e,t)})}}class ms extends ii{constructor(e){super("V2NIMMessageCreator",e),this.name="V2NIMMessageCreator",this.defaultNosSceneName="nim_default_im",this.core=e}createMessage(e,t){return Object.assign(Object.assign(Object.assign({messageClientId:De(),messageType:e,createTime:this.core.timeOrigin.getNTPTime(),sendingState:0,messageStatus:{errorCode:200},messageSource:0,isSelf:!0},t),t.attachment?{attachment:Object.assign(Object.assign({},t.attachment),{raw:Or(e,t.attachment)})}:{}),{senderId:"",receiverId:"",conversationType:0,conversationId:"",messageServerId:"",messageConfig:Object.assign({unreadEnabled:!0,roamingEnabled:!0,readReceiptEnabled:!1,lastMessageUpdateEnabled:!0,historyEnabled:!0,onlineSyncEnabled:!0,offlineEnabled:!0},t.messageConfig),pushConfig:Object.assign({pushEnabled:!0,pushNickEnabled:!0,forcePush:!1},t.pushConfig),routeConfig:Object.assign({routeEnabled:!0},t.routeConfig),antispamConfig:Object.assign({antispamEnabled:!0},t.antispamConfig)})}createTextMessage(e){return this.checkV2(),_e({text:{type:"string",allowEmpty:!1}},{text:e},"",!0),this.createMessage(0,{text:e})}createImageMessage(e,t,i,r,s){this.checkV2(),_e(ir,{name:t,sceneName:i,width:r,height:s},"",!0);var n=this.createGenericFileMessageAttachment(e,t,i,void 0,r,s,"jpeg");return this.createMessage(1,{attachment:n,attachmentUploadState:0})}createAudioMessage(e,t,i,r){this.checkV2(),_e(er,{name:t,sceneName:i,duration:r},"",!0);var s=this.createGenericFileMessageAttachment(e,t,i,r,void 0,void 0,"aac");return this.createMessage(2,{attachment:s,attachmentUploadState:0})}createVideoMessage(e,t,i,r,s,n){this.checkV2(),_e(tr,{name:t,sceneName:i,duration:r,width:s,height:n},"",!0);var o=this.createGenericFileMessageAttachment(e,t,i,r,s,n,"mp4");return this.createMessage(3,{attachment:o,attachmentUploadState:0})}createFileMessage(e,t,i){this.checkV2(),_e(Zi,{name:t,sceneName:i},"",!0);var r=this.createGenericFileMessageAttachment(e,t,i,void 0,void 0,void 0,"txt");return this.createMessage(6,{attachment:r,attachmentUploadState:0})}createGenericFileMessageAttachment(e,t,i,r,s,n,o){if(i=i||this.defaultNosSceneName,!this.core.V2NIMStorageService.hasStorageScene)throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"V2NIMStorageService not exist"}});if(!this.core.V2NIMStorageService.hasStorageScene(i))throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"sceneName: "+i+" has not been added"}});var{file:a,path:c}=qr(e),d=Object.assign(Object.assign(Object.assign({name:t,uploadState:0,sceneName:i||this.defaultNosSceneName},r?{duration:r}:{}),s?{width:s}:{}),n?{height:n}:{});if(a){var l=a.name.lastIndexOf("."),h=-1===l?a.name:a.name.substring(0,l);d.name=d.name||h,d.size=a.size,d.ext=`.${Be(a.name)||Be(t||"")||o}`}else if(c){var p=c.lastIndexOf("/"),u=c.lastIndexOf("."),m=-1===u?c.substring(p+1):c.substring(p+1,u);d.name=d.name||m,d.ext=`.${Be(c)||Be(t||"")||o}`}return d=JSON.parse(JSON.stringify(d)),c?d.path=c:a&&(d.file=a),d}createLocationMessage(e,t,i){return this.checkV2(),_e({latitude:{type:"number",allowEmpty:!1},longitude:{type:"number",allowEmpty:!1},address:{type:"string",allowEmpty:!1}},{latitude:e,longitude:t,address:i},"",!0),this.createMessage(4,{attachment:{latitude:e,longitude:t,address:i}})}createCustomMessage(e,t){return this.checkV2(),_e({text:{type:"string"}},{text:e},"",!0),_e({rawAttachment:{type:"string"}},{rawAttachment:t},"",!0),this.createMessage(100,{text:e,attachment:{raw:t}})}createCustomMessageWithAttachment(e,t){return this.checkV2(),_e({raw:{type:"string"}},e,"attachment",!0),_e({subType:{type:"number",min:0,required:!1}},{subType:t},"",!0),this.createMessage(100,t?{attachment:e,subType:t}:{attachment:e})}createCallMessage(e,t,i,r,s){return this.checkV2(),_e({type:{type:"number",allowEmpty:!1}},{type:e},"",!0),_e({channelId:{type:"string",allowEmpty:!1}},{channelId:t},"",!0),_e({status:{type:"number",allowEmpty:!1}},{status:i},"",!0),_e({durations:{type:"array",allowEmpty:!1}},{durations:r},"",!0),this.createMessage(12,{text:s||"",attachment:{type:e,channelId:t,durations:r,status:i}})}createForwardMessage(e){if(this.checkV2(),!e||[11,5,7,10].includes(e.messageType))return null;var t={messageClientId:De(),messageType:e.messageType};return e.text&&(t.text=e.text),e.attachment&&(t.attachment=e.attachment),e.attachment&&"uploadState"in e.attachment&&(t.attachmentUploadState=e.attachment.uploadState),this.createMessage(e.messageType,t)}createTipsMessage(e){return this.checkV2(),_e({text:{type:"string",allowEmpty:!1}},{text:e},"",!0),this.createMessage(10,{text:e})}}class gs{constructor(){this.name="V2NIMMessageAttachmentCreator"}createLocationMessageAttachment(e,t,i){return{latitude:"number"==typeof e?e:0,longitude:"number"==typeof t?t:0,address:"string"==typeof i?i:""}}createCustomMessageAttachment(e){return{raw:"string"==typeof e?e:""}}}class vs{constructor(e){this.config={enable:!1},this.name="V2NIMClientAntispamUtil",this.core=e}setOptions(e){this.config=Object.assign(this.config,e)}reset(e){"destroy"===e&&(this.vocabInfo=void 0)}downloadLocalAntiSpamVocabs(){return Te(this,void 0,void 0,function*(){if(this.config.enable&&!this.vocabInfo)try{var e=yield this.core.sendCmd("v2DownloadLocalAntiSpamVocabs",{tag:{version:0,md5:""}});this.vocabInfo=Object.assign(Object.assign({},e.content.data),{thesaurus:JSON.parse(e.content.data.thesaurus).thesaurus})}catch(e){this.core.logger.warn("V2NIMLocalAntispamUtil::downloadLocalAntiSpamVocabs error",e)}})}checkTextAntispam(e,t="**"){if(!this.config.enable)return{operateType:0,replacedText:e};if(_e({text:{type:"string",required:!0,allowEmpty:!1},replace:{type:"string"}},{text:e,replace:t},"",!0),!this.vocabInfo)return{operateType:0,replacedText:e};for(var i=e,r=0;r=0){n=!0;var a=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");o=new RegExp(a,"g")}}else 2===i&&(o=new RegExp(t,"g")).test(e)&&(n=!0);if(n&&o)switch(r){case 1:return{operateType:1,replacedText:e.replace(o,s)};case 2:return{operateType:2,replacedText:e};case 3:return{operateType:3,replacedText:e}}return{operateType:0,replacedText:e}}}class fs extends ii{constructor(e){super("YSFService",e),this.core._registerDep(Li,"V2NIMConversationIdUtil"),this.core._registerDep(ms,"V2NIMMessageCreator"),this.core._registerDep(gs,"V2NIMMessageAttachmentCreator"),this.core._registerDep(vs,"V2NIMClientAntispamUtil"),this.core._registerDep(us,"V2NIMStorageService"),this.sendUtil=new _s(this.core,this),this.fileUtil=new Rr(this.core),this.model=new Vi,this.notificationUtil=new Yr(this.core),mt({cmdMap:Gr,cmdConfig:$r})}emit(e,...t){var i,r=`${this.name}::emit ${e.toString()}`;if("onSendMessage"===e){var s=t[0];this.logger.log(`${r}`,`${s.messageClientId}/${s.messageServerId};createTime:${s.createTime};`,`sendingState:${s.sendingState};attachmentUploadState:${s.attachmentUploadState||0};messageStatus:${null===(i=s.messageStatus)||void 0===i?void 0:i.errorCode}`)}else if("onReceiveMessages"===e){var n=t[0];this.logger.log(`${r}`,n.map(e=>`${e.messageClientId}/${e.messageServerId};createTime:${e.createTime}`))}else if("onReceiveCustomNotifications"===e){var o=t[0];this.logger.log(`${r}`,o.map(e=>`sender:${e.senderId};receiver:${e.receiverId};ctype:${e.conversationType};time:${e.timestamp}`))}else this.logger.log(`${r}`,...t);return super.emit(e,...t)}sendMessage(e,t,i={},r){return Te(this,void 0,void 0,function*(){_e({message:{type:"object"}},{message:e},"",!0),e.messageClientId=e.messageClientId||De(),_e(Gi,{conversationId:t,message:e,params:i},"",!0),ye(this.core.account,t);var s=this.core.timeOrigin.getTimeNode(),{messageBeforeSend:n,clientAntispamResult:o,hiddenParams:a}=this.sendUtil.prepareMessage(e,t,i),c=yield this.sendUtil.doSendMessage({apiCallingTimeNode:s,messageBeforeSend:n,clientAntispamResult:o,hiddenParams:a,progress:r});return c.message.senderId===c.message.receiverId&&this.markMsgsAck([c.message]),c})}sendCustomNotification(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),ye(this.core.account,e),_e(Hr,{content:t,params:i},"",!0);var r=this.notificationUtil.generateNotificationTag(e,t,i);r.type=100,yield this.core.sendCmd("ysfSendCustomNotification",{tag:r})})}sendMessageFn(e){}cancelMessageAttachmentUpload(e){return this.fileUtil.cancelMessageAttachmentUpload(e)}markMsgsAck(e){if(e&&e.length>0){var t=e.map(e=>e.messageServerId).filter(e=>e&&"0"!==e);0!==t.length&&this.core.sendCmd("ysfBatchMarkRead",{sid:101,cid:2,ids:t})}}markNotificationAck(e){if(e&&e.length>0){var t=e.map(e=>e.idServer).filter(e=>e&&"0"!==e);0!==t.length&&this.core.sendCmd("ysfBatchMarkRead",{sid:101,cid:3,ids:t})}}ysfOnMsgHandler(e){var t=Ge(e,e.content.data,"messageServerId"),i=Er(this.core,t);delete i.__clientExt,this.emit("onReceiveMessages",[i]),this.model.upsertMessages([i]),this.markMsgsAck([i])}ysfSyncOfflineMsgsHandler(e){var t=e.content.datas;t=t.map(e=>Er(this.core,e)),this.markMsgsAck(t),this.emit("onReceiveMessages",t),this.model.upsertMessages(t)}ysfOnSysNotificationHandler(e){var t=Ge(e,e.content.data,"idServer");this.markNotificationAck([t]);var i=this.processSystemNotification(t);i&&this.emit("onReceiveCustomNotifications",[i])}processSystemNotification(e){var t=Object.assign(Object.assign({},e),{conversationType:1});return delete t.type,t}ysfSyncSysNotificationHandler(e){this.markNotificationAck(e.content.datas);var t=e.content.datas.sort((e,t)=>e.timestamp-t.timestamp).map(e=>this.processSystemNotification(e)).filter(e=>e);t&&this.emit("onReceiveCustomNotifications",t)}}class _s{constructor(e,t){this.uploadingMessageInfo={},this.core=e,this.service=t}prepareMessage(e,t,i,r){var s=this.checkIfResend(e),n=this.generateSendMessage({message:e,params:i,resend:s,conversationId:t,replyMessage:r}),o=Object.assign({},i.targetConfig?{targetConfig:i.targetConfig}:{}),{clientAntispamResult:a,text:c}=this.checkIfAntispam(i,n);return n.text=c,n.clientAntispamHit=!!a&&3===a.operateType,{messageBeforeSend:n,clientAntispamResult:a,hiddenParams:o}}checkIfAntispam(e,t){var i,r=t.text;if(e.clientAntispamEnabled&&(0===t.messageType||10===t.messageType))if(1===(i=this.core.V2NIMClientAntispamUtil.checkTextAntispam?this.core.V2NIMClientAntispamUtil.checkTextAntispam(t.text||"",e.clientAntispamReplace):{operateType:0,replacedText:""}).operateType)r=i.replacedText;else if(2===i.operateType)throw this.service.emit("onSendMessage",Object.assign(Object.assign({},t),{sendingState:2,messageStatus:{errorCode:de.V2NIM_ERROR_CODE_CLIENT_ANTISPAM}})),new pe({code:de.V2NIM_ERROR_CODE_CLIENT_ANTISPAM,detail:{reason:"sendMessage: text intercepted by client antispam"}});return{clientAntispamResult:i,text:r}}doMsgReceiveReport(e,t){if(e.senderId!==this.core.account){var i=Ve(e,"__clientExt.statistics.apiCallingTime")||0,r=Ve(e,"__clientExt.statistics.sendTime")||0,s=Ve(e,"__clientExt.statistics.attachUploadDuration")||0,n=this.core.timeOrigin.getNTPTime(),o=e.createTime,a=this.core.timeOrigin.checkNodeReliable(t.__receiveTimeNode)?this.core.timeOrigin.getNTPTime(t.__receiveTimeNode):n;this.core.reporter.report("msgReceive",{msgId:e.messageServerId,clientId:e.messageClientId,serverTime:e.createTime,receiveTime:a,fromAccid:1===e.conversationType?e.senderId:"",toAccid:e.receiverId,type:xr(e.conversationType),tid:1===e.conversationType?"":e.receiverId,apiCallingTime:i,sendTime:r,attachUploadDuration:s,callbackTime:n,preHandleTime:n,result:200,failReason:"",rt:n-o})}}checkIfResend(e){var t=this.service.model.getMessageById(e.messageClientId),i=!1;if("messageServerId"in e&&"0"!==e.messageServerId&&""!==e.messageServerId)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"sendMessage: message has already been sent"}});if(t&&"messageServerId"in t&&"0"!==t.messageServerId&&""!==t.messageServerId)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"sendMessage: message has already been sent"}});return t&&(i=!0),i}doSendMessage(e){var t;return Te(this,void 0,void 0,function*(){var i,r,{apiCallingTimeNode:s,messageBeforeSend:n,clientAntispamResult:o,hiddenParams:a,progress:c}=e,d={},l=this.service instanceof fs;if(l)i="ysfSendMessage";else if(1===n.conversationType)i="v2SendP2pMessage";else if(2===n.conversationType)i="v2SendTeamMessage";else{if(3!==n.conversationType)throw new me({detail:{reason:`conversationType: ${n.conversationType} is not supported`}});i="v2SendSuperTeamMessage"}if(this.service.sendMessageFn(n),!l&&this.core.eventBus.emit("forwardSend/V2NIMMessageService/sendMsg",n),!n.attachment||!("uploadState"in n.attachment)||n.attachment.url||0!==n.attachment.uploadState&&2!==n.attachment.uploadState)this.service.emit("onSendMessage",n);else{var h=Date.now();try{n.attachmentUploadState=3,n.attachment.uploadState=3,this.service.emit("onSendMessage",n),yield this.service.fileUtil.doSendFile(n,c),n.attachmentUploadState=1,n.attachment.uploadState=1,this.service.emit("onSendMessage",n)}catch(e){throw n.attachmentUploadState=2,n.attachment.uploadState=2,n.sendingState=2,n.messageStatus={errorCode:e.code||de.V2NIM_ERROR_CODE_UNKNOWN},this.service.emit("onSendMessage",n),d.attachUploadDuration=Date.now()-h,this.doSendMessageFailed(s,d,n,e),e}d.attachUploadDuration=Date.now()-h}this.core.timeOrigin.checkNodeReliable(s)&&(d.apiCallingTime=this.core.timeOrigin.getNTPTime(s),d.sendTime=this.core.timeOrigin.getNTPTime(),n.__clientExt={statistics:d});try{r=yield this.core.sendCmd(i,{tag:Object.assign({},n,a)})}catch(e){throw this.doSendMessageFailed(s,d,n,e),n.sendingState=2,n.messageStatus={errorCode:e.code||de.V2NIM_ERROR_CODE_UNKNOWN},this.service.emit("onSendMessage",n),e}var p=Ve(r,"content.data.errorCode"),u=Object.assign(Object.assign(Object.assign(Object.assign({},n),r.content.data),n.aiConfig?{aiConfig:Object.assign(Object.assign({},n.aiConfig),(null===(t=r.content.data)||void 0===t?void 0:t.aiConfig)||{})}:{}),{sendingState:1,messageStatus:{errorCode:p&&200!==p?p:200}});this.service.sendMessageFn(u),!l&&this.core.eventBus.emit("forwardSend/V2NIMMessageService/sendMsg",u),this.doMsgSendReport(s,d,n);var m=u.antispamResult;return m&&(u.messageStatus.errorCode=de.V2NIM_ERROR_CODE_SERVER_ANTISPAM),delete u.antispamResult,this.service.emit("onSendMessage",u),Object.assign(Object.assign({message:u},m?{antispamResult:m}:{}),o?{clientAntispamResult:o}:{})})}doSendMessageFailed(e,t,i,r){var s=Object.assign(Object.assign({},i),{sendingState:2});this.core.eventBus.emit("forwardSend/V2NIMMessageService/sendMsg",s),this.service.sendMessageFn(s),this.doMsgSendReport(e,t,i,r)}doMsgSendReport(e,t,i,r){t.apiCallingTime=this.core.timeOrigin.getNTPTime(e),t.sendTime=this.core.timeOrigin.getNTPTime();var s=this.core.timeOrigin.getNTPTime(),n=Ve(r,"detail.reason");this.core.reporter.report("msgSend",{msgId:i.messageServerId,clientId:i.messageClientId,msgTime:i.createTime,fromAccid:1===i.conversationType?i.senderId:"",toAccid:i.receiverId,type:xr(i.conversationType),tid:1===i.conversationType?"":i.receiverId,result:r?r.code:200,failReason:n||(null==r?void 0:r.message)||"",rt:s-t.apiCallingTime,apiCallingTime:t.apiCallingTime,sendTime:t.sendTime,attachUploadDuration:t.attachUploadDuration,apiCallbackTime:s})}generateSendMessage(e){var t,i,{conversationId:r,replyMessage:s,resend:n,message:o,params:a}=e,c={};if(s){var d=s.threadRoot;c={threadReply:{senderId:s.senderId,receiverId:s.receiverId,messageServerId:s.messageServerId,createTime:s.createTime,messageClientId:s.messageClientId,conversationType:s.conversationType,conversationId:s.conversationId},threadRoot:{senderId:d?d.senderId:s.senderId,receiverId:d?d.receiverId:s.receiverId,messageServerId:d?d.messageServerId:s.messageServerId,createTime:d?d.createTime:s.createTime,messageClientId:d?d.messageClientId:s.messageClientId,conversationType:d?d.conversationType:s.conversationType,conversationId:d?d.conversationId:s.conversationId}}}var l=this.core.V2NIMConversationIdUtil.parseConversationType(r),h=this.core.V2NIMConversationIdUtil.parseConversationTargetId(r);a.pushConfig&&!0!==a.pushConfig.forcePush&&(delete a.pushConfig.forcePushContent,delete a.pushConfig.forcePushAccountIds);var p={},u={};if(a.aiConfig){var m=Ve(a,"aiConfig.content.msg"),g=Ve(a,"aiConfig.content.type")||0;m?u={msg:m,type:g}:void 0===m&&0===o.messageType&&(u={msg:o.text||"",type:g}),(p=Object.assign({aiStreamStatus:0,aiStream:!1},a.aiConfig)).aiStatus=1,void 0!==u.msg&&(p.content=u)}var v=null===(i=null===(t=this.core.V2NIMUserService)||void 0===t?void 0:t.model)||void 0===i?void 0:i.getUser(this.core.account),f=(null==v?void 0:v.updateTime)||0;return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},o),c),{messageConfig:Object.assign(Object.assign({},o.messageConfig),a.messageConfig),routeConfig:Object.assign(Object.assign({},o.routeConfig),a.routeConfig),pushConfig:Object.assign(Object.assign({},o.pushConfig),a.pushConfig),antispamConfig:Object.assign(Object.assign({},o.antispamConfig),a.antispamConfig),robotConfig:Object.assign(Object.assign({},o.robotConfig),a.robotConfig)}),p&&p.accountId?{aiConfig:p}:{}),o.attachment?{attachment:Object.assign({},o.attachment)}:{}),{resend:n,senderId:this.core.account,conversationType:l,receiverId:h,conversationId:this.core.V2NIMConversationIdUtil.messageConversationId({conversationType:l,senderId:this.core.account,receiverId:h})}),f?{userUpdateTime:f}:{}),{sendingState:3})}}class Is{constructor(e,t){this.core=e,this.service=t}checkIfModify(e,t){if("0"===e.messageServerId)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"modifyMessage: messageServerId cannot be empty"}});if(![0,1,2,3,4,6,10,12,100].includes(e.messageType))throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:`modifyMessage: messageType ${e.messageType} not correct`}});if([0,1,2,3,6,10,12].includes(e.messageType)&&t.attachment)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:`modifyMessage: messageType ${e.messageType} can not modify attachment`}});var i=["subType","text","serverExtension","attachment"];if(!i.some(e=>void 0!==Ve(t,e)))throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"modifyMessage: missing modified params"}});if(i.every(i=>"attachment"===i?e.attachment&&t.attachment?Or(e.messageType,e.attachment)===Or(e.messageType,t.attachment):!t.attachment:Ve(e,i)===Ve(t,i)))throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"modifyMessage: no change"}})}prepareMessage(e,t){var i=this.generateSendMessage(e,t),{clientAntispamResult:r,text:s}=this.checkIfAntispam(t,i);return i.text=s,i.clientAntispamHit=!!r&&3===r.operateType,{messageBeforeSend:i,clientAntispamResult:r}}modifyMessage(e,t){return Te(this,void 0,void 0,function*(){var i;if(1===e.conversationType)i="v2MessageP2pModify";else if(2===e.conversationType)i="v2MessageTeamModify";else{if(3!==e.conversationType)throw new me({detail:{reason:`conversationType: ${e.conversationType} is not supported`}});i="v2MessageSuperTeamModify"}var r=yield this.core.sendCmd(i,{tag:e});if(t&&3===t.operateType)return{errorCode:de.V2NIM_ERROR_CODE_CLIENT_ANTISPAM,clientAntispamResult:t};var s=Object.assign(Object.assign({},e),r.content.data),n=s.antispamResult;if(n)return Object.assign({errorCode:de.V2NIM_ERROR_CODE_SERVER_ANTISPAM,antispamResult:n},t?{clientAntispamResult:t}:{});delete s.antispamResult;var o=Er(this.core,s);return this.service.model.upsertMessages([o]),this.core.eventBus.emit("V2NIMMessageService/modifyMsg",o),this.core.eventBus.emit("forwardSend/V2NIMMessageService/modifyMsg",o),Object.assign(Object.assign({errorCode:200,message:o},n?{antispamResult:n}:{}),t?{clientAntispamResult:t}:{})})}checkIfAntispam(e,t){var i,r=t.text;if(e.clientAntispamEnabled&&(0===t.messageType||10===t.messageType))if(1===(i=this.core.V2NIMClientAntispamUtil.checkTextAntispam?this.core.V2NIMClientAntispamUtil.checkTextAntispam(t.text||"",e.clientAntispamReplace):{operateType:0,replacedText:""}).operateType)r=i.replacedText;else if(2===i.operateType)throw new pe({code:de.V2NIM_ERROR_CODE_CLIENT_ANTISPAM,detail:{reason:"sendMessage: text intercepted by client antispam"}});return{clientAntispamResult:i,text:r}}generateSendMessage(e,t){var i;return Object.assign(Object.assign({messageConfig:{lastMessageUpdateEnabled:null===(i=e.messageConfig)||void 0===i?void 0:i.lastMessageUpdateEnabled},routeConfig:Object.assign({routeEnabled:!0},t.routeConfig),pushConfig:Object.assign({pushEnabled:!0,pushNickEnabled:!0,forcePush:!1},t.pushConfig),antispamConfig:Object.assign({antispamEnabled:!0},t.antispamConfig)},t.attachment?{attachment:t.attachment}:{}),{conversationType:e.conversationType,senderId:e.senderId,receiverId:e.receiverId,createTime:e.createTime,messageClientId:e.messageClientId,messageServerId:e.messageServerId,messageType:e.messageType,subType:t.subType,text:t.text,serverExtension:t.serverExtension})}}class ys{constructor(e,t){this.emitRevokeMessage=e=>{var t=e.map(e=>{var t=Nr(this.core,e);return 3===t.messageRefer.conversationType?this.core.eventBus.emit("V2NIMSync/updateTimetag",{deleteSuperTeamMsg:e.createTime}):this.core.eventBus.emit("V2NIMSync/updateTimetag",{recallMsg:e.createTime}),t});t.forEach(e=>{this.service.model.deleteMessage(e.messageRefer.messageClientId)}),this.service.emit("onMessageRevokeNotifications",t),this.core.eventBus.emit("V2NIMMessageService/revokeMessages",t)},this.core=e,this.service=t,this.logger=e.logger}revokeMessage(e,t){return Te(this,void 0,void 0,function*(){if(_e($i,{message:e,params:t},"",!0),ye(this.core.account,e.conversationId),1===e.conversationType&&e.senderId!==this.core.account)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"revokeMessage: p2p message senderId is not current user"}});if(!e.messageServerId||"0"===e.messageServerId)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"revokeMessage: cannot revoke message with invalid messageServerId: "+e.messageServerId}});var i=3===e.conversationType?"v2RevokeSuperTeamMessage":"v2RevokeMessage",r=Object.assign(Object.assign(Object.assign({},e),t),{attach:t&&t.serverExtension,sysMsgType:{1:7,2:8,3:12}[e.conversationType],opeAccount:this.core.account});yield this.core.sendCmd(i,{tag:r});var s=[JSON.parse(JSON.stringify({postscript:t&&t.postscript,revokeType:{1:1,2:2,3:3}[e.conversationType],revokeAccountId:this.core.account,serverExtension:t&&t.serverExtension,messageRefer:Sr(this.core,e)}))];this.revokeMessagesFn(s),this.core.eventBus.emit("forwardSend/V2NIMMessageService/revokeMessage",r)})}deleteMessage(e,t){return Te(this,void 0,void 0,function*(){if(_e(qi,e,"",!0),3===e.sendingState)this.service.fileUtil.cancelMessageAttachmentUpload(e);else if(e.sendingState&&1!==e.sendingState)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"deleteMessage: cannot delete unsent message"}});var i={messageRefer:Sr(this.core,e),serverExtension:t},r=Date.now();e.messageServerId&&"0"!==e.messageServerId&&(r=(yield this.core.sendCmd("v2DeleteMessage",{tag:i})).content.timetag);var s=[{serverExtension:t,messageRefer:Sr(this.core,e),deleteTime:r}];this.core.eventBus.emit("forwardSend/V2NIMMessageService/deleteSelfMsgs",[Object.assign(Object.assign({},i),{deleteTime:r})]),this.deleteMessagesFn(s)})}deleteMessages(e,t){return Te(this,void 0,void 0,function*(){_e(Ki,{messages:e},"",!0);var i=[],r=[];if(0===e.length)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"deleteMessages: message array length is 0"}});for(var s=e[0].conversationId,n=0;n=1&&e[n].conversationId!==s)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"deleteMessages: only allow to delete messages from same conversation"}});e[n].messageServerId&&"0"!==e[n].messageServerId?i.push(e[n]):r.push(e[n])}var o=Date.now(),a=[...r];try{if(i.length>0){var c=yield this.core.sendCmd("v2DeleteMessages",{tag:i.map(e=>({messageRefer:e,serverExtension:t}))});o=c.content.timetag,a=[...a,...i]}}catch(e){if(0===r.length)throw e;this.logger.warn("V2NIMMessageService:deleteMessages: delete messages with serverId failed")}var d=a.map(e=>({serverExtension:t,messageRefer:Sr(this.core,e),deleteTime:o}));this.core.eventBus.emit("forwardSend/V2NIMMessageService/deleteSelfMsgs",a.map(e=>({messageRefer:e,serverExtension:t,deleteTime:o}))),this.deleteMessagesFn(d)})}revokeMessagesFn(e){e.forEach(e=>{this.service.model.deleteMessage(e.messageRefer.messageClientId)}),this.service.emit("onMessageRevokeNotifications",e),this.core.eventBus.emit("V2NIMMessageService/revokeMessages",e)}deleteMessagesFn(e){e.forEach(e=>{this.service.model.deleteMessage(e.messageRefer.messageClientId),this.core.eventBus.emit("V2NIMSync/updateTimetag",{deleteSelfMsgs:e.deleteTime})}),this.service.emit("onMessageDeletedNotifications",e),this.core.eventBus.emit("V2NIMMessageService/deleteMessages",e)}}class Es{constructor(e,t){this.core=e,this.service=t,this.logger=e.logger}stopAIStreamMessage(e,t){var i;return Te(this,void 0,void 0,function*(){this.checkAI(),yield this.core.sendCmd("v2AIStopModelStreamCall",{tag:{serverId:e.messageServerId,clientId:e.messageClientId,type:e.conversationType,from:e.senderId,to:e.receiverId,aiAccount:null===(i=e.aiConfig)||void 0===i?void 0:i.accountId,opeType:t.operationType,updateContent:t.updateContent,messageTime:e.createTime}}),this.logger.log(`V2AIUtil::streamMessageStop,clientId:${e.messageClientId}`),this.core.V2NIMAIService.model.completeAiStream(e.messageClientId)})}regenAIMessage(e,t){var i,r,s,n,o,a,c,d;return Te(this,void 0,void 0,function*(){this.checkAI();var l=this.core.V2NIMAIService.model.getAiStream(e.messageClientId);if(l){if(!(null==l?void 0:l.isComplete))throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:`msg::regenAIMessage streamCache is not complete, msgId:${e.messageClientId}`}})}else if(-1===(null===(i=e.streamConfig)||void 0===i?void 0:i.status)||1===(null===(r=e.streamConfig)||void 0===r?void 0:r.status))throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:`msg::regenAIMessage message streamConfig.status forbidden ${e.streamConfig.status}`}});yield this.core.sendCmd("v2AIRegenMessage",{tag:{fromAccount:e.senderId,to:e.receiverId,aiAccount:null===(s=e.aiConfig)||void 0===s?void 0:s.accountId,serverId:e.messageServerId,clientId:e.messageClientId,time:e.createTime,type:e.conversationType,opeType:t.operationType,replyMsgFromAccount:null===(n=e.threadReply)||void 0===n?void 0:n.senderId,replyMsgToAccount:null===(o=e.threadReply)||void 0===o?void 0:o.receiverId,replyMsgTime:null===(a=e.threadReply)||void 0===a?void 0:a.createTime,replyMsgIdServer:null===(c=e.threadReply)||void 0===c?void 0:c.messageServerId,replyMsgIdClient:null===(d=e.threadReply)||void 0===d?void 0:d.messageClientId}}),1===t.operationType&&this.core.V2NIMAIService.model.setAiStream(e.messageClientId,{isComplete:!1,queryStatus:0,chunks:[]})})}checkAI(){if(!this.hasAI())throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"V2NIMAIService is not registered"}})}hasAI(){var e;return!!(null===(e=this.core.V2NIMAIService)||void 0===e?void 0:e.name)}}class Ms{constructor(e,t){this.core=e,this.service=t,this.model=t.model,this.receiptUtil=t.receiptUtil,this.logger=this.core.logger}setAIStreamPlaceholder(e){this.service.aiUtil.hasAI()&&e.forEach(e=>{var t;1===(null===(t=e.streamConfig)||void 0===t?void 0:t.status)&&this.core.V2NIMAIService.model.setAiStream(e.messageClientId,{isComplete:!1,queryStatus:0,chunks:[],msg:e},!0)})}onMsgHandler(e){var t=Ge(e,e.content.msg,"messageServerId"),{_conversationOnlineSyncNotify:i,_conversationOnlineSyncData:r}=t,s=Me(t,["_conversationOnlineSyncNotify","_conversationOnlineSyncData"]),n=Er(this.core,s,1),o=this.service._filterMessage(n);this.logger.log(`v2OnMsgHandler::recvMsg ${n.messageClientId}/${n.messageServerId}/${n.createTime};isHitFilter:${o}`),3===n.conversationType?this.core.eventBus.emit("V2NIMSync/updateTimetag",{superTeamRoamingMsgs:n.createTime,offlineMsgs:n.createTime}):this.core.eventBus.emit("V2NIMSync/updateTimetag",{roamingMsgs:n.createTime,offlineMsgs:n.createTime}),this.service.config.compatibleWithV1||(this.service.markMsgsAck([n]),this.service.sendUtil.doMsgReceiveReport(n,e)),delete n.__clientExt,this.setAIStreamPlaceholder([n]),5!==n.messageType&&this.core.V2NIMUserService.checkUserUpdate&&this.core.V2NIMUserService.checkUserUpdate(n,n.userUpdateTime),5===n.messageType&&this.core.eventBus.emit("V2NIMTeamService/notification",t),o||(this.service.emit("onReceiveMessages",[n]),this.model.upsertMessages([n]),i&&this.core.eventBus.emit("V2NIMConversationService/conversationOnlineSyncNotify",{content:{info:JSON.parse(i),data:JSON.parse(r)}},n),this.core.eventBus.emit("V2NIMMessageService/onMsg",n))}syncOfflineMsgsHandler(e){var t=e.content.datas;t=t.map(e=>Er(this.core,e,2)),0!==(t=this.service._filterMessagesByFn(t)).length&&(!this.service.config.compatibleWithV1&&this.service.markMsgsAck(t),this.service.emit("onReceiveMessages",t),this.model.upsertMessages(t),this.core.eventBus.emit("V2NIMMessageService/offlineMsgs",t))}syncRoamingMsgsHandler(e){var t=e.content.datas;t=t.map(e=>Er(this.core,e,3)),this.setAIStreamPlaceholder(t),0!==(t=this.service._filterMessagesByFn(t)).length&&(this.service.emit("onReceiveMessages",t),this.model.upsertMessages(t),this.core.eventBus.emit("V2NIMMessageService/roamingMsgs",t))}onP2PMessageReceiptsHandler(e){this.receiptUtil.onP2PMessageReceiptsHandler(e)}onTeamMessageReceiptsHandler(e){this.receiptUtil.onTeamMessageReceiptsHandler(e)}syncP2PMessagReceiptsHandler(e){this.receiptUtil.syncP2PMessagReceiptsHandler(e)}syncRevokeMessageHandler(e){this.service.deleteUtil.emitRevokeMessage(e.content.datas)}onRevokeMessageHandler(e){var t=e.content.data;this.service.deleteUtil.emitRevokeMessage([t])}onDeleteMessageHandler(e){var t=e.content.data,i={serverExtension:t.serverExtension,deleteTime:t.deleteTime,messageRefer:Tr(this.core,t.messageRefer)};this.service.deleteUtil.deleteMessagesFn([i])}onDeleteMessagesHandler(e){var t=e.content.data.map(e=>({serverExtension:e.serverExtension,deleteTime:e.deleteTime,messageRefer:Tr(this.core,e.messageRefer)}));this.service.deleteUtil.deleteMessagesFn(t)}syncOnDeleteMessagesHandler(e){var t=e.content.datas.map(e=>({serverExtension:e.serverExtension,deleteTime:e.deleteTime,messageRefer:Tr(this.core,e.messageRefer)}));this.service.emit("onMessageDeletedNotifications",t)}v2MessageOnModifiedHandler(e){var t=Er(this.core,e.content.data);this.model.upsertMessages([t]),this.service.aiUtil.hasAI()&&this.core.V2NIMAIService.model.completeAiStream(t.messageClientId),this.core.eventBus.emit("forwardSend/V2NIMMessageService/modifyMsg",t),this.core.eventBus.emit("V2NIMMessageService/modifyMsg",t),this.core.eventBus.emit("V2NIMSync/updateTimetag",3===t.conversationType?{superTeamModifyMessage:t.modifyTime}:{p2pTeamModifyMessage:t.modifyTime}),this.service.emit("onReceiveMessagesModified",[t])}v2MessageSyncModifiedHandler(e){var t=e.content.datas.map(e=>Er(this.core,e)).filter(e=>{var t,i=(null===(t=this.model.getMessageById(e.messageClientId))||void 0===t?void 0:t.modifyTime)||0;return(e.modifyTime||0)>i});t.length>0&&(this.model.upsertMessages(t),t.forEach(e=>{this.service.aiUtil.hasAI()&&this.core.V2NIMAIService.model.completeAiStream(e.messageClientId),this.core.eventBus.emit("forwardSend/V2NIMMessageService/modifyMsg",e)}),this.service.emit("onReceiveMessagesModified",t))}v2MessageSyncSuperTeamModifiedHandler(e){this.v2MessageSyncModifiedHandler(e)}}class Ts{constructor(e,t){this.core=e,this.service=t,this.logger=this.core.logger}setListener(){this.core.eventBus.on("forwardReceive/V2NIMMessageService/sendMsg",this.service.sendMessageFn.bind(this.service)),this.core.eventBus.on("forwardReceive/V2NIMMessageService/revokeMessages",this.service.deleteUtil.emitRevokeMessage.bind(this.service.deleteUtil)),this.core.eventBus.on("forwardReceive/V2NIMMessageService/deleteMessages",this.service.deleteUtil.deleteMessagesFn.bind(this.service.deleteUtil)),this.core.eventBus.on("V2NIMConversationService/deleteConversation",e=>{e.forEach(e=>this.service.model.deleteMessages(e))}),this.core.eventBus.on("V2NIMAIService/receiveMessagesModified",e=>this.service.emit("onReceiveMessagesModified",e))}beforeEmit(e,...t){var i,r,s,n=`${this.service.name}::emit ${e.toString()}`;if("onSendMessage"===e){var o=t[0];this.logger.log(`${n}`,`${o.messageClientId}/${o.messageServerId}/${o.createTime};`,`sendingState:${o.sendingState};attachmentUploadState:${o.attachmentUploadState||0};messageStatus:${null===(i=o.messageStatus)||void 0===i?void 0:i.errorCode};config.lastMsg:${null===(r=o.messageConfig)||void 0===r?void 0:r.lastMessageUpdateEnabled};config.unread:${null===(s=o.messageConfig)||void 0===s?void 0:s.unreadEnabled}`)}else if("onReceiveMessages"===e||"onReceiveMessagesModified"===e){var a=t[0];this.logger.log(`${n}`,a.map(e=>{var t,i;return`${e.messageClientId}/${e.messageServerId}/${e.createTime};config.lastMsg:${null===(t=e.messageConfig)||void 0===t?void 0:t.lastMessageUpdateEnabled};config.unread:${null===(i=e.messageConfig)||void 0===i?void 0:i.unreadEnabled}`}))}else if("onMessageRevokeNotifications"===e){var c=t[0];this.logger.log(`${n}`,c.map(e=>`msg:${e.messageRefer.messageClientId}/${e.messageRefer.messageServerId};revokeAccountId:${e.revokeAccountId}`))}else if("onMessageDeletedNotifications"===e){var d=t[0];this.logger.log(`${n}`,d.map(e=>`msg:${e.messageRefer.messageClientId}/${e.messageRefer.messageServerId};deleteTime:${e.deleteTime}`))}else this.logger.log(`${n}`,...t)}}var Ss={3:"super_team",1:"p2p",0:"p2p",2:"team"};var Ns,Cs={id:1,ext:2,createTime:{id:3,retType:"number"},updateTime:{id:4,retType:"number"}};function As(e,t,i=0,r){var s,n;t=Mr(t,e);var{messageType:o,subType:a,text:c,attachment:d,serverExtension:l}=t,h="";if(t.senderId!==e.account&&5!==o){h=Ve(t,"fromNick");var p=null===(n=null===(s=e.V2NIMFriendService)||void 0===s?void 0:s.model)||void 0===n?void 0:n.getFriend(t.senderId);p&&p.alias&&(h=p.alias)}return JSON.parse(JSON.stringify({lastMessageState:i,messageRefer:Sr(e,t),messageType:o,subType:a,text:c,attachment:d,serverExtension:l,callbackExtension:t.callbackExtension,sendingState:r,senderName:h}))}function Os(e,t){return t&&t.length>0?t.map(t=>Rs(e,t)):[]}function Rs(e,t){var i=t;if("string"==typeof i.lastMessage)if(""===i.lastMessage);else if(1===i.lastMessageState){var r=Nr(e,ut(JSON.parse(i.lastMessage),gt(Dr)));i.lastMessage=function(e,t){var{messageRefer:i,revokeAccountId:r,revokeType:s,callbackExtension:n,serverExtension:o,postscript:a}=t,c=function(e,t,i,r){var s,n,o,a,c,d,l,h;if(t!==e.account){var p=null===(n=null===(s=e.V2NIMFriendService)||void 0===s?void 0:s.model)||void 0===n?void 0:n.getFriend(t);if(p&&p.alias)return p.alias;if(2===i){var u=null===(a=null===(o=e.V2NIMTeamService)||void 0===o?void 0:o.memberModel)||void 0===a?void 0:a.getById(r,1,t);if(u&&u.teamNick)return u.teamNick}else if(3===i){var m=null===(d=null===(c=e.V2NIMTeamService)||void 0===c?void 0:c.memberModel)||void 0===d?void 0:d.getById(r,1,t);if(m&&m.teamNick)return m.teamNick}var g=null===(h=null===(l=e.V2NIMUserService)||void 0===l?void 0:l.model)||void 0===h?void 0:h.getUser(t);return g&&g.name?g.name:void 0}}(e,t.revokeAccountId,t.messageRefer.conversationType,t.messageRefer.receiverId)||"";return JSON.parse(JSON.stringify({lastMessageState:1,messageRefer:i,revokeAccountId:r,revokeType:s,callbackExtension:n,serverExtension:o,text:a||"",senderName:c}))}(e,r)}else if(0===i.lastMessageState){var s=ut(JSON.parse(i.lastMessage),gt(Lr));i.lastMessage=As(e,s,i.lastMessageState,s.senderId===e.account?1:void 0)}else 2===i.lastMessageState&&delete i.lastMessage;return i}function bs(e){var{version:t,deleteFlag:i}=e;return{conversation:Me(e,["version","deleteFlag"]),version:t,deleteFlag:i}}gt(Cs),gt(Cs),gt(Cs),gt(Cs),gt(Cs),Math.max,Math.min,function(e){e[e.createConversation=1]="createConversation",e[e.deleteConversation=2]="deleteConversation",e[e.updateConversation=3]="updateConversation",e[e.setConversationTop=4]="setConversationTop",e[e.clearConversationUnread=5]="clearConversationUnread",e[e.addConversationToGroup=6]="addConversationToGroup",e[e.removeConversationFromGroup=7]="removeConversationFromGroup",e[e.modifyConversationOnSendMessage=8]="modifyConversationOnSendMessage",e[e.modifyConversationOnDeleteMessage=9]="modifyConversationOnDeleteMessage",e[e.modifyConversationOnRecallMessage=10]="modifyConversationOnRecallMessage",e[e.modifyConversationOnClearMessage=11]="modifyConversationOnClearMessage",e[e.oneClickClearConversationUnread=12]="oneClickClearConversationUnread",e[e.modifyConversationOnUpdateMessage=13]="modifyConversationOnUpdateMessage"}(Ns||(Ns={}));var ks={type:"array",itemRules:{type:"enum",values:[1,2,3]},min:1};class Ls{constructor(){this.map=new Map,this.readTimeMap=new Map}set(e){e.forEach(e=>{e=this.processConversation(e),this.map.set(e.conversationId,e)})}reset(){this.map.clear(),this.readTimeMap.clear()}count(){return this.map.size}sort(){var e=Array.from(this.map.values());e.sort((e,t)=>t.sortOrder-e.sortOrder),this.map.clear(),e.forEach(e=>{this.map.set(e.conversationId,e)})}processConversation(e){return"string"==typeof e.lastMessage&&delete e.lastMessage,void 0===e.localExtension&&(e.localExtension=""),e}getById(e){return this.map.get(e)}getStickTopList(){return Array.from(this.map.values()).filter(e=>e.stickTop).sort((e,t)=>t.sortOrder-e.sortOrder)}getAll(){return Array.from(this.map.values()).sort((e,t)=>t.sortOrder-e.sortOrder)}getByOption(e,t,i){var{conversationTypes:r,onlyUnread:s,conversationGroupIds:n}=i,o=[];this.map.forEach(e=>{if((!(r&&r.length>0)||r.includes(e.type))&&(!s||e.unreadCount)&&(!i.ignoreMuted||!e.mute)){if(n){var t=e.groupIds,a=(null==t?void 0:t.length)||0;if(0===n.length&&a>0)return;if(n.length>0&&0===a)return;if(n.length>0&&a>0&&!n.some(e=>t&&t.includes(e)))return}o.push(e)}}),o=o.sort((e,t)=>t.sortOrder-e.sortOrder);var a=0;e>0&&(a=je(o,"sortOrder",e),o[a]&&o[a].sortOrder===e&&(a+=1));var c=o.slice(a).length;return(o=o.slice(a,a+t)).length>0?{offset:c>t?o[o.length-1].sortOrder:0,finished:!(c>t),conversationList:o}:{offset:0,finished:!0,conversationList:o}}upsert(e){var t=e.conversationId,i=this.map.get(t);if(!i)return e=this.processConversation(Object.assign({},e)),this.map.set(t,e),e.unreadCount>0;var r=e.unreadCount!==i.unreadCount,s=Object.assign({},i,e);return s=this.processConversation(s),this.map.set(t,s),r}bulkUpsert(e){var t=!1;return e.forEach(e=>{this.upsert(e)&&(t=!0)}),t}deleteById(e){var t=this.getById(e);if(t)return this.map.delete(e),t}updateReadTime(e,t){this.readTimeMap.set(e,t)}getReadTime(e){return this.readTimeMap.get(e)||0}}function Vs(e,t){var i=typeof e;if(i!==typeof t)return!1;if("object"===i){if(Object.prototype.toString.call(e)!==Object.prototype.toString.call(t))return!1;if(Array.isArray(e)){if(e.length!==t.length)return!1;for(var r=0;r{if(2===e.lastMessageState&&this.service.compute.hasMessageService){this.conversationIdsForBackFill[e.conversationId]=!0;var t=this.core.V2NIMMessageService.model.getLastMessageOfConversation(e.conversationId);e.lastMessage=t?As(this.core,t,e.lastMessageState,t.sendingState):""}else this.conversationIdsForBackFill[e.conversationId]=!1;delete e.lastMessageState}),e}recvConversationFromSyncAction(e){var{syncType:t}=Ve(e,"content.info"),i=Os(this.core,Ve(e,"content.datas"));0===(t=parseInt(t))?(i.forEach(e=>{this.initFieldVersion(e.conversationId,e.version)}),i=this.setBackFillIds(i),this.setModel(i)):(i=this.setBackFillIds(i),this.recvConversationForCreated(i)!!e.conversationId),i=Ve(e,"content.info"),r=t.map(e=>`id:${e.conversationId}, ver:${e.version}`).join(";");if(this.core.logger.getDebugMode()?this.core.logger.debug(`V2NIMConversation::recvConversation: ${r}.`,i,t):this.core.logger.log(`V2NIMConversation::recvConversation: ${r}.`,i),2===i.type){var s=t.map(e=>(delete this.fieldVersion[e.conversationId],this.service.model.deleteById(e.conversationId),e.conversationId));return this.service.emit("onConversationDeleted",s),void this.service.unread.digestUnreadCountChange()}12!==i.type?(i.type,t=this.setBackFillIds(t),this.recvConversationForCreated(t)!this.fieldVersion[e.conversationId]);return t.reduce((e,t)=>{if(!this.fieldVersion[t.conversationId]){this.initFieldVersion(t.conversationId,t.version),e=!!this.updateModel(t)||e;var i=this.service.model.getById(t.conversationId);return i&&this.service.triggerConversationCreated(i),e}return e},!1)&&this.service.unread.digestUnreadCountChange(),t.length}recvConversationForChanged(e){var t=this.bulkCompare(e);if(0!==t.length){this.bulkUpdateModel(t);var i=t.map(e=>this.service.model.getById(e.conversationId)).filter(e=>!!e);this.service.triggerConversationChanged(i)}}processTempPacket(){this.tempPacket.forEach(e=>{this.recvConversation(e)}),this.tempPacket=[]}bulkCompare(e){return e.map(e=>this.compare(e)).filter(e=>!!e)}compare(e){var{version:t,conversationId:i,deleteFlag:r,type:s}=e,n={},o=0;return["stickTop","groupIds","serverExtension","localExtension","lastMessage","lastMessageState","unreadCount","sortOrder","createTime","updateTime","lastReadTime"].forEach(r=>{var s=r;if(void 0!==e[s]){var a=this.fieldVersion[i];a&&"number"==typeof a[s]&&a[s]>=t||(this.fieldVersion[i]=this.fieldVersion[i]||{},this.fieldVersion[i][s]=t,n[s]=e[s],o+=1)}}),o?Object.assign(Object.assign({},n),{conversationId:i,deleteFlag:r,version:t,type:s}):void 0}bulkUpdateModel(e){var t=!1;e.forEach(e=>{this.updateModel(e)&&(t=!0)}),t&&this.service.unread.digestUnreadCountChange()}initFieldVersion(e,t){this.fieldVersion[e]={stickTop:t,groupIds:t,serverExtension:t,lastMessage:t,lastMessageState:t,unreadCount:t,sortOrder:t,createTime:t,updateTime:t,lastReadTime:t}}initConversation(e,t){var i=Date.now();return Object.assign({conversationId:e,type:this.core.V2NIMConversationIdUtil.parseConversationType(e),stickTop:!1,localExtension:"",serverExtension:"",unreadCount:0,lastReadTime:0,createTime:i,updateTime:i,sortOrder:i},t)}updateModel(e){var{deleteFlag:t,conversation:i}=bs(e);if(t){var r=this.service.model.deleteById(i.conversationId);return!!(r&&r.unreadCount>0)}return this.service.model.upsert(i)}setModel(e){var t=e.filter(e=>!e.deleteFlag).map(e=>bs(e).conversation);this.service.model.set(t)}updateModelWithLastMessage(e,t,i,r){var s=this.service.model.getById(e),n=t?As(this.core,t,i,r):void 0;if(!Vs(null==s?void 0:s.lastMessage,n))if(s){var o=Object.assign(Object.assign({},s),{sortOrder:n?s.stickTop?n.messageRefer.createTime+1e15:n.messageRefer.createTime:s.sortOrder,lastMessage:n});this.service.model.upsert(o),this.service.triggerConversationChanged([o])}else{this.initFieldVersion(e,-1);var a=this.initConversation(e,{lastMessage:n});this.service.model.upsert(a),this.service.triggerConversationCreated(a)}}updateModelByRevoke(e){var t=[];e.forEach(e=>{var{postscript:i,messageRefer:r}=e,s=Me(e,["postscript","messageRefer"]),n=r.conversationId,o=this.service.model.getById(n);o&&o.lastMessage&&o.lastMessage.messageRefer.messageClientId===r.messageClientId&&1!==o.lastMessage.lastMessageState&&(o.lastMessage.lastMessageState=1,i&&(o.lastMessage.text=i),Object.assign(o.lastMessage,s),this.service.model.upsert(o),t.push(o))}),t.length>0&&this.service.triggerConversationChanged(t)}compareAndUpdateModel(e){this.core.logger.log("V2NIMConversation::compareAndUpdateModel",e.map(e=>e.conversationId));var t=!1,i=[];e.forEach(e=>{var r=this.compare(e);if(r){var s=this.service.model.getById(e.conversationId);this.updateModel(r)&&(t=!0);var n=this.service.model.getById(e.conversationId);n&&(s?i.push(n):this.service.triggerConversationCreated(n))}}),i.length>0&&this.service.triggerConversationChanged(i),t&&this.service.unread.digestUnreadCountChange()}compareAndDeleteModel(e){this.core.logger.log("V2NIMConversation::compareAndDeleteModel",e);var t=e.reduce((e,t)=>{delete this.fieldVersion[t];var i=this.service.model.deleteById(t);return!!(i&&i.unreadCount>0)||e},!1);this.service.emit("onConversationDeleted",e),t&&this.service.unread.digestUnreadCountChange()}compareAndDeleteGroupInModel(e,t){this.core.logger.log("V2NIMConversation::compareAndDeleteGroupInModel",e,t);var i=[];Object.keys(this.fieldVersion).forEach(r=>{var s=this.fieldVersion[r];if(void 0===s.groupIds||e>s.groupIds){s.groupIds=e;var n=this.service.model.getById(r);if(n&&n.groupIds&&n.groupIds.length>0){var o=n.groupIds.filter(e=>e!==t);if(o.length!==n.groupIds.length){var a=Object.assign(Object.assign({},n),{groupIds:o});this.service.model.upsert(a),a&&i.push(a)}}}}),i.length>0&&this.service.triggerConversationChanged(i)}compareAndClearUnreadInModel(e){var{oneClickClearUnreadType:t,oneClickClearUnreadVersion:i,oneClickClearUnreadLastReadTime:r,oneClickClearUnreadConversationType:s,oneClickClearUnreadGroupId:n}=e;this.core.logger.log(`V2NIMConversation::compareAndClearUnreadInModel.ver:${i};type:${t};lastReadTime:${r};filter:${s||""};grounp:${n||""}`);var o=[],a=[];if(1===t)a=this.service.model.getAll();else if(s||n){var c=this.service.model.count();a=this.service.model.getByOption(0,c,{conversationTypes:s,conversationGroupIds:n?[n]:void 0}).conversationList}a.forEach(e=>{var t=e.conversationId,s=this.fieldVersion[t];if(void 0===s.unreadCount||i>s.unreadCount){s.unreadCount=i,s.lastReadTime=i;var n=e.unreadCount,a=Object.assign(Object.assign({},e),{lastReadTime:r,unreadCount:0});this.service.model.upsert(a),n>0&&o.push(a)}}),o.length>0&&this.service.triggerConversationChanged(o),this.service.unread.digestUnreadCountChange()}backfillLastMsg(e,t){var i=e=Zt(e);(t||0!==(i=e.filter(e=>this.conversationIdsForBackFill[e])).length)&&i.forEach(e=>{var t=Ve(this.service.model.getById(e),"lastMessage.messageRefer.messageClientId"),i=this.service.compute.hasMessageService?this.core.V2NIMMessageService.model.getLastMessageOfConversation(e):void 0;(i&&i.messageClientId)!==t&&(this.conversationIdsForBackFill[e]=!1,i?this.updateModelWithLastMessage(e,i,2,i.sendingState):this.updateModelWithLastMessage(e,void 0,2,0))})}}var Ds,ws={"28_1":"v2ConversationCreate","28_2":"v2ConversationDelete","28_3":"v2ConversationUpdate","28_4":"v2ConversationSetTop","28_5":"v2ConversationUnreadClear","28_6":"v2ConversationGet","28_7":"v2ConversationGetByIds","28_8":"v2ConversationGetList","28_17":"v2ConversationsDelete","28_18":"v2ConversationsUnreadClear","28_19":"v2ConversationSync","28_20":"v2ConversationNotifySync","28_21":"v2ConversationNotifySyncOnline","28_23":"v2ConversationClearTotalUnread","28_24":"v2ConversationClearTypeUnread","28_25":"v2ConversationClearGroupUnread","4_14":"syncConversationReadTime","4_20":"syncSuperTeamReadTime","4_22":"v2SyncSessionsWithMoreRoaming","4_25":"v2SyncSessionReliableInfo","30_16":"v2MarkConversationReadTime","32_25":"v2MarkSuperTeamReadTime","7_116":"v2MultiDeviceConversationReadTime","21_125":"v2MultiDeviceSuperTeamReadTime"},Us="V2NIMConversationService",xs={conversationId:1,type:{id:2,retType:"number"},serverExtension:3,groupIds:{id:4,retConverter:e=>e?JSON.parse(e):void 0},lastMessage:5,lastMessageState:{id:6,retType:"number"},unreadCount:{id:7,retType:"number"},stickTop:{id:8,retType:"boolean"},sortOrder:{id:9,retType:"number"},version:{id:10,retType:"number"},deleteFlag:{id:11,retType:"boolean"},createTime:{id:12,retType:"number"},updateTime:{id:13,retType:"number"},lastReadTime:{id:14,retType:"number"}},Fs={type:{id:1,retType:"number"},oneClickClearUnreadType:{id:2,retType:"number"},oneClickClearUnreadConversationType:{id:3,retConverter:_t},oneClickClearUnreadGroupId:{id:4,retType:"string"},oneClickClearUnreadVersion:{id:5,retType:"number"},oneClickClearUnreadLastReadTime:{id:6,retType:"number"}},Bs={v2ConversationCreate:{sid:28,cid:1,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationId:1}}],response:[{type:"Property",name:"data",reflectMapper:gt(xs)}]},v2ConversationDelete:{sid:28,cid:2,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationId:1,clearMessage:2}}],response:[{type:"Property",name:"data",reflectMapper:gt(xs)}]},v2ConversationUpdate:{sid:28,cid:3,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationId:1,serverExtension:2}}],response:[{type:"Property",name:"data",reflectMapper:gt(xs)}]},v2ConversationSetTop:{sid:28,cid:4,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationId:1,stickTop:2}}],response:[{type:"Property",name:"data",reflectMapper:gt(xs)}]},v2ConversationUnreadClear:{sid:28,cid:5,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationId:1}}],response:[{type:"Property",name:"data",reflectMapper:gt(xs)}]},v2ConversationGet:{sid:28,cid:6,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationId:1}}],response:[{type:"Property",name:"data",reflectMapper:gt(xs)}]},v2ConversationGetByIds:{sid:28,cid:7,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationIds:1}}],response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(xs)},{type:"Property",name:"info",reflectMapper:{1:"failedMap"}}]},v2ConversationGetList:{sid:28,cid:8,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{cursor:1,limit:2}}],response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(xs)},{type:"Property",name:"info",reflectMapper:{1:"hasMore",2:"offset"}}]},v2ConversationsDelete:{sid:28,cid:17,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationIds:1,clearMessage:2}}],response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(xs)},{type:"Property",name:"info",reflectMapper:{1:"failedMap"}}]},v2ConversationsUnreadClear:{sid:28,cid:18,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationIds:1}}],response:[{type:"PropertyArray",name:"datas",reflectMapper:gt(xs)},{type:"Property",name:"info",reflectMapper:{1:"failedMap"}}]},v2ConversationSync:{sid:28,cid:19,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{cursor:1}}],response:[{type:"Property",name:"info",reflectMapper:{1:"nextCursor",2:"syncType"}}]},v2ConversationNotifySync:{sid:28,cid:20,service:Us,response:[{type:"Property",name:"info",reflectMapper:{1:"nextCursor",2:"syncType"}},{type:"PropertyArray",name:"datas",reflectMapper:gt(xs)}]},v2ConversationNotifySyncOnline:{sid:28,cid:21,service:Us,response:[{type:"Property",name:"info",reflectMapper:gt(Fs)},{type:"PropertyArray",name:"datas",reflectMapper:gt(xs)}]},v2ConversationClearTotalUnread:{sid:28,cid:23,service:Us,response:[{type:"Property",name:"info",reflectMapper:gt(Fs)}]},v2ConversationClearTypeUnread:{sid:28,cid:24,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{conversationType:1}}],response:[{type:"Property",name:"info",reflectMapper:gt(Fs)}]},v2ConversationClearGroupUnread:{sid:28,cid:25,service:Us,params:[{type:"Property",name:"tag",reflectMapper:{groupId:1}}],response:[{type:"Property",name:"info",reflectMapper:gt(Fs)}]},syncConversationReadTime:{sid:4,cid:14,service:Us,response:[{type:"StrLongMap",name:"p2p"},{type:"LongLongMap",name:"team"},{type:"Long",name:"timetag"}]},syncSuperTeamReadTime:{sid:4,cid:20,service:Us,response:[{type:"LongLongMap",name:"superTeam"}]},v2SyncSessionsWithMoreRoaming:{sid:4,cid:22,service:Us,response:[]},v2SyncSessionReliableInfo:{sid:4,cid:25,service:Us,response:[]},v2MarkConversationReadTime:{sid:30,cid:16,service:Us,params:[{type:"Byte",name:"scene"},{type:"String",name:"to"},{type:"Long",name:"timetag"}]},v2MarkSuperTeamReadTime:{sid:32,cid:25,service:Us,params:[{type:"Long",name:"to"},{type:"Long",name:"timetag"}]},v2MultiDeviceConversationReadTime:{sid:30,cid:116,service:Us,response:[{type:"Byte",name:"scene"},{type:"String",name:"to"},{type:"Long",name:"timetag"}]},v2MultiDeviceSuperTeamReadTime:{sid:21,cid:125,service:Us,response:[{type:"Long",name:"to"},{type:"Long",name:"timetag"}]}};class js{constructor(e,t){this.totalUnreadCount=void 0,this.unreadCountByFilter={},this.core=e,this.service=t}reset(){this.totalUnreadCount=void 0,this.unreadCountByFilter={}}getTotalUnreadCount(){return this.totalUnreadCount}resetTotalAfterSyncDone(){var e=this.service.model.getAll().reduce((e,t)=>e+(t.unreadCount||0),0),t=this.totalUnreadCount;return void 0!==t&&t===e||(this.totalUnreadCount=e,this.service.emit("onTotalUnreadCountChanged",e)),e}digestUnreadCountChange(){this._digest()}_digest(){var e=this.totalUnreadCount,t=this.service.model.getAll().reduce((e,t)=>e+(t.unreadCount||0),0);this.core.logger.log(`V2NIMConversation::digestUnreadCountChange:oldUnreadCount ${e}, newUnreadCount ${t}`),e!==t&&(this.totalUnreadCount=t,this.service.emit("onTotalUnreadCountChanged",t)),Object.keys(this.unreadCountByFilter).forEach(e=>{var t=JSON.parse(e),i=this.getUnreadCountByFilter(t),r=this.unreadCountByFilter[e];this.unreadCountByFilter[e]=i,t.equals=$s.bind(t),r!==i&&this.service.emit("onUnreadCountChangedByFilter",t,i)})}getUnreadCountByIds(e){return e.reduce((e,t)=>{var i=this.service.model.getById(t);return e+(i&&i.unreadCount||0)},0)}getUnreadCountByFilter(e){var t=this.service.model.count();return this.service.model.getByOption(0,t,{conversationTypes:e.conversationTypes,conversationGroupIds:e.conversationGroupId?[e.conversationGroupId]:void 0,ignoreMuted:e.ignoreMuted}).conversationList.reduce((e,t)=>e+(t.unreadCount||0),0)}addFilter(e){var t=Gs(e);if(void 0!==this.unreadCountByFilter[t])throw new pe({code:de.V2NIM_ERROR_CODE_RESOURCE_ALREADY_EXIST});var i=JSON.parse(t),r=this.getUnreadCountByFilter(i);this.unreadCountByFilter[t]=r,this.service.emit("onUnreadCountChangedByFilter",i,r)}deleteFilter(e){var t=Gs(e);if(void 0===this.unreadCountByFilter[t])throw new pe({code:de.V2NIM_ERROR_CODE_RESOURCE_NOT_EXIST});delete this.unreadCountByFilter[t]}}function Gs(e){var{conversationTypes:t}=e;return t&&(t=t.sort()),JSON.stringify({conversationGroupId:e.conversationGroupId,conversationTypes:t,ignoreMuted:e.ignoreMuted})}function $s(e){return JSON.stringify(this)===Gs(e)}function Hs(e){var t=JSON.parse(e);return Object.keys(t).map(e=>({conversationId:e,error:new pe({code:t[e]})}))}!function(e){e[e.createConversationGroup=1]="createConversationGroup",e[e.deleteConversationGroup=2]="deleteConversationGroup",e[e.updateConversationGroup=3]="updateConversationGroup",e[e.addConversationToGroup=4]="addConversationToGroup",e[e.removeConversationFromGroup=5]="removeConversationFromGroup"}(Ds||(Ds={}));class Ys{constructor(e,t){this.core=e,this.service=t}get hasUserService(){var e;return!!(null===(e=this.core.V2NIMUserService)||void 0===e?void 0:e.name)}get hasFriendService(){var e;return!!(null===(e=this.core.V2NIMFriendService)||void 0===e?void 0:e.name)}get hasTeamService(){var e;return!!(null===(e=this.core.V2NIMTeamService)||void 0===e?void 0:e.name)}get hasMessageService(){var e;return!!(null===(e=this.core.V2NIMMessageService)||void 0===e?void 0:e.name)}computeConvs(e){return e.map(e=>this.computeConv(e))}computeConv(e){var t,i,r,s,n;if(0===e.type)return e;var o=this.core.V2NIMConversationIdUtil.parseConversationType(e.conversationId),a=this.core.V2NIMConversationIdUtil.parseConversationTargetId(e.conversationId),c={};if(e.lastReadTime||(c.lastReadTime=this.service.model.getReadTime(e.conversationId)),(null===(t=this.core.V2NIMSettingService)||void 0===t?void 0:t.name)&&(c.mute=this.core.V2NIMSettingService.getConversationMuteStatus(e.conversationId)),1===o&&this.hasUserService){var d,l=this.core.V2NIMUserService.model.getUser(a),h=this.hasFriendService?this.core.V2NIMFriendService.model.getFriend(a):void 0;e.conversationId!==(null===(i=e.lastMessage)||void 0===i?void 0:i.messageRefer.conversationId)||0!==(null===(r=e.lastMessage)||void 0===r?void 0:r.lastMessageState)&&2!==(null===(s=e.lastMessage)||void 0===s?void 0:s.lastMessageState)||(d=null===(n=e.lastMessage)||void 0===n?void 0:n.senderName),c.name=(null==h?void 0:h.alias)||(null==l?void 0:l.name)||d||a,c.avatar=(null==l?void 0:l.avatar)||""}else if(2===o&&this.hasTeamService){var p=this.core.V2NIMTeamService.model.getById(a,1);c.name=(null==p?void 0:p.name)||a,c.avatar=(null==p?void 0:p.avatar)||""}else if(3===o&&this.hasTeamService){var u=this.core.V2NIMTeamService.model.getById(a,2);c.name=(null==u?void 0:u.name)||a,c.avatar=(null==u?void 0:u.avatar)||""}return Object.assign(e,c),e}computeReadTimeForMark(e){var t,i,r,s=e.conversationId,n=this.service.model.getReadTime(s);if(null===(i=null===(t=null==e?void 0:e.lastMessage)||void 0===t?void 0:t.messageRefer)||void 0===i?void 0:i.createTime)r=e.lastMessage.messageRefer.createTime;else{if(!this.core.timeOrigin.checkNodeReliable())return n||0;r=this.core.timeOrigin.getNTPTime()}return r}}class qs{constructor(e,t){this.core=e,this.service=t,this.model=this.service.model,this.logger=this.core.logger}get ifEnabled(){return!0===this.core.options.enableV2CloudConversation}v2ConversationNotifySyncHandler(e){this.ifEnabled&&this.service.versionCache.recvConversationFromSyncAction(e)}v2ConversationNotifySyncOnlineHandler(e){this.ifEnabled&&this.service.versionCache.recvConversation(e)}syncConversationReadTimeHandler(e){var t,i,r;if(this.ifEnabled){if(null===(t=null==e?void 0:e.content)||void 0===t?void 0:t.p2p)for(var[s,n]of Object.entries(e.content.p2p))this.model.updateReadTime(this.core.V2NIMConversationIdUtil.p2pConversationId(s),n),this.service.emit("onConversationReadTimeUpdated",this.core.V2NIMConversationIdUtil.p2pConversationId(s),n);if(null===(r=null===(i=null==e?void 0:e.content)||void 0===i?void 0:i.team)||void 0===r?void 0:r.m_map)for(var[o,a]of Object.entries(e.content.team.m_map))this.model.updateReadTime(this.core.V2NIMConversationIdUtil.teamConversationId(o),a),this.service.emit("onConversationReadTimeUpdated",this.core.V2NIMConversationIdUtil.teamConversationId(o),a)}}syncSuperTeamReadTimeHandler(e){var t,i;if(this.ifEnabled&&(null===(i=null===(t=null==e?void 0:e.content)||void 0===t?void 0:t.superTeam)||void 0===i?void 0:i.m_map))for(var[r,s]of Object.entries(e.content.superTeam.m_map))this.model.updateReadTime(this.core.V2NIMConversationIdUtil.superTeamConversationId(r),s),this.service.emit("onConversationReadTimeUpdated",this.core.V2NIMConversationIdUtil.superTeamConversationId(r),s)}v2MultiDeviceConversationReadTimeHandler(e){var t;this.ifEnabled&&(null===(t=null==e?void 0:e.content)||void 0===t?void 0:t.to)&&(0===e.content.scene?(this.model.updateReadTime(this.core.V2NIMConversationIdUtil.p2pConversationId(e.content.to),e.content.timetag),this.service.emit("onConversationReadTimeUpdated",this.core.V2NIMConversationIdUtil.p2pConversationId(e.content.to),e.content.timetag)):(this.model.updateReadTime(this.core.V2NIMConversationIdUtil.teamConversationId(e.content.to),e.content.timetag),this.service.emit("onConversationReadTimeUpdated",this.core.V2NIMConversationIdUtil.teamConversationId(e.content.to),e.content.timetag)))}v2MultiDeviceSuperTeamReadTimeHandler(e){var t;this.ifEnabled&&(null===(t=null==e?void 0:e.content)||void 0===t?void 0:t.to)&&(this.model.updateReadTime(this.core.V2NIMConversationIdUtil.superTeamConversationId(e.content.to),e.content.timetag),this.service.emit("onConversationReadTimeUpdated",this.core.V2NIMConversationIdUtil.superTeamConversationId(e.content.to),e.content.timetag))}}class Ks{constructor(e,t){this.core=e,this.service=t,this.model=this.service.model,this.versionCache=this.service.versionCache,this.logger=this.core.logger}setListener(){this.core.eventBus.on("V2NIMLoginService/loginLifeCycleLoginSucc",()=>this.versionCache.doSync()),this.core.eventBus.on("V2NIMConversationService/conversationOnlineSyncNotify",this.conversationOnlineSyncNotify.bind(this)),this.core.eventBus.on("V2NIMMessageService/sendMessage",this.sendMessage.bind(this)),this.core.eventBus.on("V2NIMMessageService/deleteMessages",this.deleteMessages.bind(this)),this.core.eventBus.on("V2NIMMessageService/revokeMessages",this.revokeMessages.bind(this)),this.core.eventBus.on("V2NIMMessageService/roamingMsgs",this.roamingOrOfflineMsgs.bind(this)),this.core.eventBus.on("V2NIMMessageService/offlineMsgs",this.roamingOrOfflineMsgs.bind(this)),this.core.eventBus.on("V2NIMSettingService/setMute",this.setMute.bind(this))}beforeEmit(e,...t){var i,r,s=`${this.service.name}::emit ${e.toString()}`;if("onConversationCreated"===e){var n=t[0];this.logger.log(`${s}`,`id:${n.conversationId};unread:${n.unreadCount};lastMsg:${null===(i=n.lastMessage)||void 0===i?void 0:i.messageRefer.messageClientId}/${null===(r=n.lastMessage)||void 0===r?void 0:r.messageRefer.messageServerId}`)}else if("onConversationChanged"===e){var o=t[0];this.logger.log(`${s}`,o.map(e=>{var t,i;return`id:${e.conversationId};unread:${e.unreadCount};lastMsg:${null===(t=e.lastMessage)||void 0===t?void 0:t.messageRefer.messageClientId}/${null===(i=e.lastMessage)||void 0===i?void 0:i.messageRefer.messageServerId}`}))}else this.logger.log(`${s}`,...t)}conversationOnlineSyncNotify(e,t){var i;!1!==(null===(i=null==t?void 0:t.messageConfig)||void 0===i?void 0:i.lastMessageUpdateEnabled)&&(e.content.info=ut(e.content.info,gt(Fs)),e.content.data=ut(e.content.data,gt(xs)),t&&(e.content.data.lastMessage=As(this.core,t,0)),e.content.datas=[e.content.data],this.service.handler.v2ConversationNotifySyncOnlineHandler.call(this,e))}sendMessage(e,t){var i,r;1===t&&!0===(null===(i=e.messageConfig)||void 0===i?void 0:i.historyEnabled)||!1!==(null===(r=null==e?void 0:e.messageConfig)||void 0===r?void 0:r.lastMessageUpdateEnabled)&&this.versionCache.updateModelWithLastMessage(e.conversationId,e,2,t)}deleteMessages(e){var t=e.map(e=>e.messageRefer.conversationId);this.versionCache.backfillLastMsg(t,!0)}revokeMessages(e){this.versionCache.updateModelByRevoke(e)}roamingOrOfflineMsgs(e){var t=Zt(e.map(e=>e.conversationId));this.versionCache.backfillLastMsg(t,!1)}setMute(e,t){var i=this.model.getById(e);i&&i.mute!==t&&(i.mute=t,this.model.upsert(i),this.service.triggerConversationChanged([i]))}}var Ws={groupId:1,name:2,serverExtension:3,createTime:4,updateTime:5};gt(Ws),gt(xs),gt(Ws),gt(Ws),gt(Ws),gt(Ws),gt(xs),gt(xs),gt(Ws);var Js="V2NIMMessageLogUtil",zs={"30_6":"v2GetMessageList","33_2":"v2GetMessageListByRefers","30_9":"v2ClearRoamingMessage","30_18":"v2ClearHistoryMessage","7_118":"onClearHistoryMessage","4_24":"syncClearHistoryMessage","31_23":"v2GetTeamMessageList","32_14":"v2GetSuperTeamMessageList"},Xs={conversationType:{id:0,retType:"number"},receiverId:1,deleteRoam:{id:2,converter:vt},teamId:3,onlineSync:{id:4,converter:vt},deleteTime:{id:6,retType:"number"},serverExtension:7},Qs=[{type:"Long",name:"beginTime"},{type:"Long",name:"endTime"},{type:"Long",name:"lastMsgId"},{type:"Int",name:"limit"},{type:"Bool",name:"direction"},{type:"LongArray",name:"msgTypes"}],Zs={v2GetMessageList:{sid:30,cid:6,service:Js,params:[{type:"String",name:"to"},...Qs],response:[{type:"PropertyArray",name:"msgs",reflectMapper:gt(Lr)}]},v2GetMessageListByRefers:{sid:33,cid:2,service:Js,params:[{type:"PropertyArray",name:"tag",reflectMapper:Lr,select:["conversationType","senderId","receiverId","createTime","messageServerId"]}],response:[{type:"PropertyArray",name:"msgs",reflectMapper:gt(Lr)}]},v2ClearRoamingMessage:{sid:30,cid:9,service:Js,params:[{type:"StrArray",name:"conversationIds"}]},v2ClearHistoryMessage:{sid:30,cid:18,service:Js,params:[{type:"Property",name:"tag",reflectMapper:Xs}],response:[{type:"Long",name:"timetag"}]},v2GetTeamMessageList:{sid:31,cid:23,service:Js,params:[{type:"Long",name:"to"},...Qs],response:[{type:"PropertyArray",name:"msgs",reflectMapper:gt(Lr)}]},v2GetSuperTeamMessageList:{sid:32,cid:14,service:Js,params:[{type:"Long",name:"to"},...Qs],response:[{type:"PropertyArray",name:"msgs",reflectMapper:gt(Lr)}]},onClearHistoryMessage:{sid:7,cid:118,service:Js,response:[{type:"Property",name:"data",reflectMapper:gt(Xs)}]},syncClearHistoryMessage:{sid:4,cid:24,service:Js,response:[{type:"PropertyArray",name:"data",reflectMapper:gt(Xs)}]}},en={conversationType:{id:1,converter:xr,retConverter:Fr,access:"messageRefer.conversationType"},senderId:{id:2,access:"messageRefer.senderId"},receiverId:{id:3,access:"messageRefer.receiverId"},createTime:{id:4,retType:"number",access:"messageRefer.createTime"},messageServerId:{id:5,access:"messageRefer.messageServerId"},messageClientId:{id:6,access:"messageRefer.messageClientId"},detail:7,modify:{id:8,retType:"number"}},tn={conversationType:{id:1,access:"messageRefer.conversationType",retConverter:Fr},senderId:{id:2,access:"messageRefer.senderId"},receiverId:{id:3,access:"messageRefer.receiverId"},time:{id:4,access:"messageRefer.createTime",converter:vt,retType:"number"},messageServerId:{id:5,access:"messageRefer.messageServerId"},messageClientId:{id:6,access:"messageRefer.messageClientId"},operatorId:7,serverExtension:8,createTime:{id:9,converter:vt,retType:"number"},updateTime:{id:10,converter:vt,retType:"number"}},rn={operatorId:1,index:{id:2,retType:"number"},createTime:{id:3,retType:"number"},serverExtension:4,pushEnabled:{id:5,access:"pushConfig.pushEnabled",converter:vt},needBadge:{id:6,access:"pushConfig.needBadge",converter:vt},title:{id:7,access:"pushConfig.title"},pushContent:{id:8,access:"pushConfig.pushContent"},pushPayload:{id:9,access:"pushConfig.pushPayload"}},sn={accid:1,serverExtension:2,createTime:{id:3,retType:"number"},updateTime:{id:4,retType:"number"}},nn={collectionId:1,collectionType:{id:2,retType:"number"},collectionData:3,serverExtension:4,uniqueId:5,createTime:{id:6,retType:"number"},updateTime:{id:7,retType:"number"}};Object.assign(Object.assign({},{keyword:1,beginTime:2,endTime:3,messageLimit:5,sortOrder:{id:6,converter:e=>0===e?2:1},p2pAccountIds:{id:7,converter:e=>e.join(",")},teamIds:{id:8,converter:e=>e.join(",")},senderAccountIds:{id:9,converter:e=>e.join(",")},messageTypes:{id:10,converter:e=>e.join(",")},messageSubtypes:{id:11,converter:e=>e.join(",")}}),{conversationLimit:4});gt(tn),gt(Lr),gt(rn),gt(Lr),gt(rn),gt(en),gt(Lr),gt(sn),gt(Lr),gt(sn),gt(Lr),gt(sn),gt(nn),gt(nn),gt(nn),gt(Lr),gt(Lr),gt(Lr),gt(Lr),gt({total:{id:1,retType:"number"},timestamp:{id:2,retType:"number"}}),gt(Lr);var on,an={joinMode:{type:"enum",values:[1,0,2],required:!1},agreeMode:{type:"enum",values:[0,1],required:!1},inviteMode:{type:"enum",values:[1,0],required:!1},updateInfoMode:{type:"enum",values:[1,0],required:!1},updateExtensionMode:{type:"enum",values:[1,0],required:!1},chatBannedMode:{type:"enum",values:[0,1],required:!1}},cn={type:"object",required:!0,rules:Object.assign({name:{type:"string",allowEmpty:!1},teamType:{type:"enum",values:[1,2]},memberLimit:{type:"number",min:1,required:!1}},an)},dn={type:"array",min:1,itemType:"string"},ln={type:"boolean"},hn={type:"string"},pn={type:"string",allowEmpty:!1},un={type:"object",rules:{antispamBusinessId:{type:"string",required:!1}},required:!1},mn={teamId:{type:"string",regExp:/^[1-9]\d*$/,allowEmpty:!1}},gn={teamIds:{type:"array",itemRules:{type:"string",allowEmpty:!1,regExp:/^[1-9]\d*$/},min:1}},vn={teamType:{type:"enum",values:[1,2]}},fn={teamTypes:{type:"array",itemType:"enum",values:[1,2],required:!1}},_n={inviteeParams:{type:"object",required:!0,rules:{inviteeAccountIds:dn,postscript:Object.assign(Object.assign({},hn),{required:!1}),serverExtension:Object.assign(Object.assign({},hn),{required:!1})}}},In={updateTeamInfoParams:{type:"object",required:!0,rules:Object.assign({name:{type:"string",allowEmpty:!1,required:!1},memberLimit:{type:"number",min:1,required:!1}},an)}},yn={type:"enum",values:[0,2]},En={memberInfoParams:{type:"object",rules:{teamNick:{type:"string",required:!1},serverExtension:{type:"string",required:!1},antispamConfig:{type:"object",required:!1,rules:{antispamBusinessId:{type:"string",required:!1}}}}}},Mn={chatBannedMode:{type:"enum",values:[0,1]}},Tn={queryOption:{type:"object",rules:{roleQueryType:{type:"enum",values:[0,2,1]},onlyChatBanned:{type:"boolean",required:!1},direction:{type:"enum",values:[1,0],required:!1},limit:{type:"number",min:1,required:!1},nextToken:{type:"string",required:!1}}}},Sn={teamId:mn.teamId,teamType:{type:"enum",values:[1,2]},operatorAccountId:{type:"string",allowEmpty:!1}},Nn={actionType:{type:"enum",values:[2,0,1,3]}},Cn={actionType:{type:"enum",values:[2]}},An={actionType:{type:"enum",values:[0]}},On={types:{type:"array",itemType:"enum",values:[0,2,1,3],required:!1},status:{type:"array",itemType:"enum",values:[1,3,0,2],required:!1},offset:{type:"number",min:0,required:!1},limit:{type:"number",min:1,required:!1}},Rn={teamId:mn.teamId,teamType:vn.teamType,accountIds:dn},bn={accountId:{type:"string",allowEmpty:!1},teamNick:{type:"string"},antispamConfig:{type:"object",required:!1,rules:{antispamBusinessId:{type:"string",required:!1}}}};class kn{constructor(){this.teamMap=new Map,this.superTeamMap=new Map}set(e){e.forEach(e=>{this.chooseMap(e.teamType).set(e.teamId,e)})}reset(){this.teamMap.clear(),this.superTeamMap.clear()}count(e,t=!0){var i=this.chooseMap(e),r=0;return i.forEach(e=>{t&&e.isValidTeam&&r++,t||r++}),r}chooseMap(e){return 2===e?this.superTeamMap:1===e?this.teamMap:new Map}getById(e,t,i=!0){var r=this.chooseMap(t).get(e);if(r){if(i&&r.isValidTeam)return r;if(!i)return r}}getAll(e,t=!0){var i=this.chooseMap(e);return Array.from(i.values()).filter(e=>!(!t||!e.isValidTeam)||!t||void 0).sort((e,t)=>t.updateTime-e.updateTime)}upsert(e){var t=e.teamId,i=e.teamType,r=this.chooseMap(i),s=r.get(t)||{},n=Object.assign({},s,e);return r.set(t,n),n}deleteById(e,t){var i=this.getById(e,t);if(i)return i.isValidTeam=!1,i}searchTeamByKeyword(e){var t=[];return this.teamMap.forEach(i=>{i.name.includes(e)&&t.push(i)}),this.superTeamMap.forEach(i=>{i.name.includes(e)&&t.push(i)}),t}}class Ln{constructor(){this.teamMembers=[],this.superTeamMembers=[],this.maxSize=2e3}reset(){this.teamMembers=[],this.superTeamMembers=[]}setData(e){e.forEach(e=>{this.chooseList(e.teamType).push(e)})}chooseList(e){return 2===e?this.superTeamMembers:1===e?this.teamMembers:[]}getById(e,t,i){return this.chooseList(t).find(t=>t.teamId===e&&t.accountId===i)}upsert(e){var t=e.teamType,i=e.teamId,r=this.chooseList(t),s=r.findIndex(t=>t.teamId===i&&t.accountId===e.accountId);-1===s?r.push(e):r[s]=Object.assign(Object.assign({},r[s]),e),r.length>this.maxSize&&r.shift()}deleteByAccount(e,t,i){var r=this.chooseList(t),s=r.findIndex(t=>t.teamId===e&&t.accountId===i);if(-1!==s){var n=r[s];return n.inTeam=!1,r.splice(s,1),n}}deleteByTeamId(e,t){var i=this.chooseList(t).filter(t=>t.teamId!==e);2===t?this.superTeamMembers=i:this.teamMembers=i}}class Vn{constructor(e,t){this.core=e,this.service=t}processNotification(e){var{attachment:t,senderId:i,receiverId:r,createTime:s}=e,{id:n,data:o}=t,a=n>400?2:1,{id:c,ids:d,tinfo:l,mute:h}=fr(o,a),p=this.service.model.getById(r,a);switch(this.core.logger.log(`v2Team::processNotification, notificationType:${n}, teamId:${r}`,o),n){case on.SUPER_TEAM_INVITATION:case on.TEAM_INVITATION:d.includes(this.core.account)&&this.onTeamJoined(l),this.onTeamMembersJoined(l,d.filter(e=>e!==this.core.account));break;case on.SUPER_TEAM_INVITE_ACCEPT:case on.TEAM_INVITE_ACCEPT:i===this.core.account?this.onTeamJoined(l):this.onTeamMemberJoined(l,i);break;case on.SUPER_TEAM_APPLY_ACCEPT:case on.TEAM_APPLY_ACCEPT:c===this.core.account?this.onTeamJoined(l):this.onTeamMemberJoined(l,c);break;case on.SUPER_TEAM_ADD_MANAGER:case on.TEAM_ADD_MANAGER:this.updateTeamMemberRole(r,a,d,{memberRole:2,updateTime:s});break;case on.SUPER_TEAM_REMOVE_MANAGER:case on.TEAM_REMOVE_MANAGER:this.updateTeamMemberRole(r,a,d,{memberRole:0,updateTime:s});break;case on.SUPER_TEAM_KICK:case on.TEAM_KICK:this.onTeamInfoUpdated(l),d.forEach(e=>{e===this.core.account?this.onTeamLeft(r,a,!0):this.onTeamMemberKicked(i,l.teamId,l.teamType,e)});break;case on.SUPER_TEAM_LEAVE:case on.TEAM_LEAVE:l?this.onTeamInfoUpdated(l):p&&i===this.core.account&&(p.isValidTeam=!1,this.onTeamInfoUpdated(p)),i===this.core.account?this.onTeamLeft(r,a,!1):this.onTeamMemberLeft(r,a,i);break;case on.SUPER_TEAM_DISMISS:case on.TEAM_DISMISS:this.onTeamDismissed(r,a);break;case on.SUPER_TEAM_UPDATE:case on.TEAM_UPDATED:this.onTeamInfoUpdated(l);break;case on.SUPER_TEAM_TRANSFER_OWNER:case on.TEAM_TRANSFER_OWNER:this.onTeamInfoUpdated(l),this.updateTeamMemberRole(r,a,[i,l.ownerAccountId],[{memberRole:0,updateTime:s},{memberRole:1,updateTime:s,joinTime:s}],!1);break;case on.SUPER_TEAM_MEMBER_MUTE:case on.TEAM_MEMBER_MUTE:this.service.model.upsert(l),this.updateTeamMemberRole(r,a,c?[c]:d,{chatBanned:0!==h,updateTime:s})}}onTeamJoined(e){this.service.model.upsert(e),this.service.emit("onTeamJoined",e),this.service.getTeamMemberListByIds(e.teamId,e.teamType,[this.core.account]).catch(e=>{this.core.logger.error("Get Member error after onTeamJoined",e)})}onTeamLeft(e,t,i){var r=this.service.model.deleteById(e,t)||_r(e,t,{isValidTeam:!1});this.service.memberModel.deleteByAccount(e,t,this.core.account),this.service.emit("onTeamLeft",r,i)}onTeamDismissed(e,t){var i=this.service.model.deleteById(e,t);i||(i=_r(e,t,{isValidTeam:!1})),this.service.memberModel.deleteByTeamId(e,t),this.service.emit("onTeamDismissed",i)}onTeamInfoUpdated(e){var t=this.service.model.upsert(e);this.service.emit("onTeamInfoUpdated",t)}onTeamMemberJoined(e,t){this.service.model.upsert(e),this.service.emit("onTeamInfoUpdated",e);var i=e.updateTime||e.createTime,r=Ir(e.teamId,e.teamType,t,{joinTime:i,updateTime:i});this.service.emit("onTeamMemberJoined",[r])}onTeamMembersJoined(e,t){var i=e.updateTime||e.createTime,r=t.map(t=>Ir(e.teamId,e.teamType,t,{joinTime:i,updateTime:i}));0!==r.length&&(this.service.model.upsert(e),this.service.emit("onTeamInfoUpdated",e),this.service.emit("onTeamMemberJoined",r))}onTeamMemberLeft(e,t,i){var r=this.service.memberModel.deleteByAccount(e,t,i);r||(r=Ir(e,t,i,{inTeam:!1})),this.service.emit("onTeamMemberLeft",[r])}onTeamMemberKicked(e,t,i,r){var s=this.service.memberModel.deleteByAccount(t,i,r);s||(s=Ir(t,i,r,{inTeam:!1})),this.service.emit("onTeamMemberKicked",e,[s])}onTeamMemberInfoUpdated(e){e.forEach(e=>{if(e.accountId===this.core.account&&this.core.V2NIMSettingService.name&&this.core.V2NIMConversationIdUtil.name){var t=1===e.teamType?this.core.V2NIMConversationIdUtil.teamConversationId(e.teamId):this.core.V2NIMConversationIdUtil.superTeamConversationId(e.teamId),i=this.core.V2NIMSettingService.getConversationMuteStatus(t);this.core.eventBus.emit("V2NIMSettingService/setMute",t,i)}}),this.service.emit("onTeamMemberInfoUpdated",e)}updateTeamMemberRole(e,t,i,r,s=!0){return Te(this,void 0,void 0,function*(){var n=i.filter((i,s)=>{var n=this.service.memberModel.getById(e,t,i);return n&&this.service.memberModel.upsert(Object.assign(Object.assign({},n),Array.isArray(r)?r[s]:r)),!n});if(s&&n.length>0)try{(yield this.service.getTeamMemberListByIds(e,t,n)).forEach(e=>this.service.memberModel.upsert(e))}catch(e){this.core.logger.warn("v2Team::processNotification, getTeamMemberListByIds failed",e)}var o=i.map((i,n)=>{var o=this.service.memberModel.getById(e,t,i);return o||s?o:Ir(e,t,i,Array.isArray(r)?r[n]:r)}).filter(e=>!!e);o.length>0&&this.onTeamMemberInfoUpdated(o)})}processSysNotification(e){var{receiverId:t,postscript:i,senderId:r,timestamp:s,content:n}=e,o={};try{o=JSON.parse(n)}catch(e){this.core.logger.warn("v2Team::processSysNotification, parse content failed",n)}var a={actionType:{0:0,1:1,2:2,3:3,15:0,16:1,17:2,18:3}[e.type],teamId:t,teamType:e.type>=15?2:1,operatorAccountId:r,postscript:i,timestamp:s,actionStatus:0,read:!1};o.attach&&(a.serverExtension=o.attach),this.core.logger.log("v2Team::processSysNotification, type:",e.type,a),this.service.notificationModel.create(a),this.service.emit("onReceiveTeamJoinActionInfo",a)}updateTeamActionStatus(e,t){this.service.notificationModel.update({teamId:e.teamId,teamType:e.teamType,operatorAccountId:e.operatorAccountId,actionType:e.actionType,actionStatus:t})}checkIfExpired(e){return!(!e||509!==e&&(e>=500&&e<=599||e>=19e4))}}!function(e){e[e.TEAM_INVITATION=0]="TEAM_INVITATION",e[e.TEAM_KICK=1]="TEAM_KICK",e[e.TEAM_LEAVE=2]="TEAM_LEAVE",e[e.TEAM_UPDATED=3]="TEAM_UPDATED",e[e.TEAM_DISMISS=4]="TEAM_DISMISS",e[e.TEAM_APPLY_ACCEPT=5]="TEAM_APPLY_ACCEPT",e[e.TEAM_TRANSFER_OWNER=6]="TEAM_TRANSFER_OWNER",e[e.TEAM_ADD_MANAGER=7]="TEAM_ADD_MANAGER",e[e.TEAM_REMOVE_MANAGER=8]="TEAM_REMOVE_MANAGER",e[e.TEAM_INVITE_ACCEPT=9]="TEAM_INVITE_ACCEPT",e[e.TEAM_MEMBER_MUTE=10]="TEAM_MEMBER_MUTE",e[e.SUPER_TEAM_INVITATION=401]="SUPER_TEAM_INVITATION",e[e.SUPER_TEAM_KICK=402]="SUPER_TEAM_KICK",e[e.SUPER_TEAM_LEAVE=403]="SUPER_TEAM_LEAVE",e[e.SUPER_TEAM_UPDATE=404]="SUPER_TEAM_UPDATE",e[e.SUPER_TEAM_DISMISS=405]="SUPER_TEAM_DISMISS",e[e.SUPER_TEAM_TRANSFER_OWNER=406]="SUPER_TEAM_TRANSFER_OWNER",e[e.SUPER_TEAM_ADD_MANAGER=407]="SUPER_TEAM_ADD_MANAGER",e[e.SUPER_TEAM_REMOVE_MANAGER=408]="SUPER_TEAM_REMOVE_MANAGER",e[e.SUPER_TEAM_MEMBER_MUTE=409]="SUPER_TEAM_MEMBER_MUTE",e[e.SUPER_TEAM_APPLY_ACCEPT=410]="SUPER_TEAM_APPLY_ACCEPT",e[e.SUPER_TEAM_INVITE_ACCEPT=411]="SUPER_TEAM_INVITE_ACCEPT"}(on||(on={}));class Pn{constructor(){this.list=[],this.maxCount=1e3}reset(){this.list=[]}checkSameAction(e,t,i=!1){return e.teamId===t.teamId&&e.teamType===t.teamType&&e.actionType===t.actionType&&e.operatorAccountId===t.operatorAccountId&&(!i||e.timestamp===t.timestamp)}create(e){this.list.push(e),this.list.length>this.maxCount&&this.list.shift()}update(e){this.list.forEach(t=>{this.checkSameAction(t,e)&&0===t.actionStatus&&Object.assign(t,e)})}delete(e){this.list=this.list.map(t=>{if(!this.checkSameAction(t,e,!1))return t}).filter(e=>e)}getByOption(e){var{types:t,status:i,offset:r=0,limit:s=50}=e,n=[];this.list.forEach(e=>{t&&t.length>0&&!t.includes(e.actionType)||i&&i.length>0&&!i.includes(e.actionStatus)||n.push(e)}),n=n.sort((e,t)=>t.timestamp-e.timestamp);var o=0;r>0&&(o=je(n,"timestamp",r),n[o]&&n[o].timestamp===r&&(o+=1));var a=n.slice(o).length;return(n=n.slice(o,o+s)).length>0?{offset:a>s?n[n.length-1].timestamp:0,finished:!(a>s),infos:n}:{offset:0,finished:!0,infos:n}}setRead(e){for(var t of this.list)this.checkSameAction(t,e)&&(t.read=!0)}setAllRead(){for(var e of this.list)e.read=!0}getUnreadCount(){var e=new Set;for(var t of this.list)t.read||0!==t.actionStatus||0!==t.actionType&&2!==t.actionType||e.add(`${t.operatorAccountId}_${t.teamType}_${t.teamId}`);return e.size}}class Dn{constructor(e,t){this.core=e,this.service=t,this.model=t.model,this.memberModel=t.memberModel,this.notification=t.notification,this.logger=this.core.logger}setListener(){this.core.eventBus.on("V2NIMTeamService/onSyncStarted",()=>{this.service.emit("onSyncStarted")}),this.core.eventBus.on("V2NIMTeamService/onSyncFinished",()=>{this.service.emit("onSyncFinished")}),this.core.eventBus.on("V2NIMTeamService/onSyncFailed",e=>{this.service.emit("onSyncFailed",e)}),this.core.eventBus.on("forwardReceive/V2NIMTeamService/created",e=>{this.model.upsert(e);var t=Ir(e.teamId,e.teamType,this.core.account,{memberRole:1});this.memberModel.upsert(t),this.service.emit("onTeamCreated",e)}),this.core.eventBus.on("forwardReceive/V2NIMTeamService/updateSelfTeamMemberInfo",e=>{this.memberModel.upsert(e),this.service.emit("onTeamInfoUpdated",[e])}),this.core.eventBus.on("forwardReceive/V2NIMTeamService/updateTeamActionStatus",this.notification.updateTeamActionStatus.bind(this.notification)),this.core.eventBus.on("V2NIMTeamService/sysNotification",this.notification.processSysNotification.bind(this.notification)),this.core.eventBus.on("V2NIMTeamService/notification",this.notification.processNotification.bind(this.notification))}beforeEmit(e,...t){var i=`${this.service.name}::emit ${e.toString()}`;if("onTeamCreated"===e||"onTeamDismissed"===e||"onTeamJoined"===e||"onTeamLeft"===e||"onTeamInfoUpdated"===e){var r=t[0];this.logger.log(`${i}`,`team:${r.teamId}_${r.teamType};updateTime:${r.updateTime}`)}else if("onTeamMemberJoined"===e||"onTeamMemberLeft"===e||"onTeamMemberInfoUpdated"===e){var s=t[0];this.logger.log(`${i}`,s.map(e=>`team:${e.teamId}_${e.teamType};account:${e.accountId}`))}else if("onTeamMemberKicked"===e){var n=t[0],o=t[1];this.logger.log(`${i}`,`operator${n}`,o.map(e=>`team:${e.teamId}_${e.teamType};account:${e.accountId}`))}else this.logger.log(`${i}`,...t)}onSyncDone(e){e?this.service.emit("onSyncFailed",e):this.service.emit("onSyncFinished")}}class wn{constructor(e,t){this.core=e,this.service=t,this.model=t.model,this.memberModel=t.memberModel,this.logger=this.core.logger}v2TeamSyncHandler(e){this.model.set(e.content.datas)}v2SuperTeamSyncHandler(e){this.model.set(e.content.datas)}v2TeamCreateMultiSyncHandler(e){var t=e.content.data;this.model.upsert(t);var i=Ir(t.teamId,t.teamType,this.core.account,{memberRole:1});this.memberModel.upsert(i),this.service.emit("onTeamCreated",t)}v2SuperTeamCreateMultiSyncHandler(e){var t=e.content.data;this.model.upsert(t);var i=Ir(t.teamId,t.teamType,this.core.account,{memberRole:1});this.memberModel.upsert(i),this.service.emit("onTeamCreated",t)}v2TeamMemberUpdateMultiSyncHandler(e){var t=e.content.data;t.teamType=1;var i=this.memberModel.getById(t.teamId,t.teamType,t.accountId);this.service.notification.updateTeamMemberRole(t.teamId,t.teamType,[t.accountId],t),t.accountId===this.core.account&&i&&i.bits!==t.bits&&this.core.eventBus.emit("V2NIMSettingService/updateBits",t.teamId,t.teamType,t.bits)}v2SuperTeamMemberUpdateMultiSyncHandler(e){var t=e.content.data;t.teamType=2;var i=this.memberModel.getById(t.teamId,t.teamType,t.accountId);this.service.notification.updateTeamMemberRole(t.teamId,t.teamType,[t.accountId],t),t.accountId===this.core.account&&i&&i.bits!==t.bits&&this.core.eventBus.emit("V2NIMSettingService/updateBits",t.teamId,t.teamType,t.bits)}v2TeamMembersOfSelfInSyncHandler(e){e.content.datas.forEach(e=>{e.teamType=1,this.memberModel.upsert(e)})}v2SuperTeamMembersOfSelfInSyncHandler(e){e.content.datas.forEach(e=>{e.teamType=2,this.memberModel.upsert(e)})}}var Un="V2NIMUserService",xn={"34_3":"v2UpdateBlockList","34_7":"v2GetUserList","34_10":"v2UpdateSelfUserProfile","3_109":"v2SyncSelfUserInfo","3_110":"onUpdateUserProfile","3_103":"onUpdateBlockList","3_8":"syncBlockAndMuteList","34_5":"v2SetP2PMessageMuteMode","3_105":"v2OnUpdateMuteList"},Fn={accountId:1,name:3,avatar:4,sign:5,gender:{id:6,retType:"number"},email:7,birthday:8,mobile:9,serverExtension:10,createTime:{id:12,retType:"number"},updateTime:{id:13,retType:"number"}},Bn={v2UpdateBlockList:{sid:34,cid:3,service:Un,params:[{type:"String",name:"accountId"},{type:"Bool",name:"addToBlockList"}]},v2GetUserList:{sid:34,cid:7,service:Un,params:[{type:"StrArray",name:"accountIds"}],response:[{type:"PropertyArray",name:"data",reflectMapper:gt(Fn)}]},v2UpdateSelfUserProfile:{sid:34,cid:10,service:Un,params:[{type:"Property",name:"tag",reflectMapper:Fn}],response:[{type:"Long",name:"updateTime"}]},onUpdateUserProfile:{sid:3,cid:110,service:Un,response:[{type:"Property",name:"data",reflectMapper:gt(Fn)}]},onUpdateBlockList:{sid:3,cid:103,service:Un,response:[{type:"String",name:"accountId"},{type:"Bool",name:"addToBlockList"}]},syncBlockAndMuteList:{sid:3,cid:8,service:Un,response:[{type:"PropertyArray",name:"data",reflectMapper:gt({accountId:0,isMute:{id:1,retType:"boolean"},isBlock:{id:2,retType:"boolean"}})},{type:"Long",name:"timetag"}]},v2SyncSelfUserInfo:{sid:3,cid:109,service:Un,response:[{type:"Property",name:"user",reflectMapper:gt(Fn)}]},v2SetP2PMessageMuteMode:{sid:34,cid:5,service:Un,params:[{type:"String",name:"accountId"},{type:"Bool",name:"muteMode"}]},v2OnUpdateMuteList:{sid:3,cid:105,service:Un,response:[{type:"String",name:"accountId"},{type:"Bool",name:"mute"}]}};class jn{constructor(){this.muteList=new Set,this.userMap=new Map,this.blockList=[]}reset(){this.muteList.clear(),this.userMap.clear(),this.blockList=[]}setAccountMuteMode(e,t){1===t?this.muteList.add(e):this.muteList.delete(e)}setUser(e){this.userMap.set(e.accountId,e)}getUser(e){return this.userMap.get(e)}getUserListBySearchOption(e){return Array.from(this.userMap.values()).filter(t=>!(void 0!==e.searchName&&!e.searchName||!t.name.includes(e.keyword))||!(!e.searchAccountId||!t.accountId.includes(e.keyword))||!!(t.mobile&&e.searchMobile&&t.mobile.includes(e.keyword)))}addToBlockList(e){e.forEach(e=>{this.blockList.includes(e)||this.blockList.push(e)})}removeFromBlockList(e){e.forEach(e=>{var t=this.blockList.indexOf(e);-1!==t&&this.blockList.splice(t,1)})}checkBlock(e){var t={};return e.forEach(e=>{t[e]=this.blockList.includes(e)}),t}}var Gn={type:"string",required:!0,allowEmpty:!1},$n={type:"string",required:!1,allowEmpty:!0},Hn={name:{type:"string",required:!1,allowEmpty:!0},avatar:$n,sign:$n,email:$n,birthday:$n,mobile:$n,gender:{type:"number",required:!1},serverExtension:$n};class Yn extends ii{constructor(e){super("V2NIMUserService",e),mt({cmdMap:xn,cmdConfig:Bn}),this.model=new jn,"v2"===this.core.options.apiVersion&&this.setListener()}reset(){this.model.reset()}setListener(){this.core.eventBus.on("forwardReceive/V2NIMUserService/updateBlockList",(e,t)=>{t?this.model.addToBlockList([e]):this.model.removeFromBlockList([e]),t?this.emitBlockListAdded(e):this.emit("onBlockListRemoved",e)}),this.core.eventBus.on("forwardReceive/V2NIMUserService/updateUserProfile",e=>{this.updateUserProfileInMemory(e)})}emit(e,...t){var i=`${this.name}::emit ${e.toString()}`;if("onUserProfileChanged"===e){var r=t[0];this.logger.log(`${i}`,r.map(e=>`id:${e.accountId};name:${e.name};updateTime:${e.updateTime}`))}else if("onBlockListAdded"===e){var s=t[0];this.logger.log(`${i}`,`id:${s.accountId};name:${s.name};updateTime:${s.updateTime}`)}else this.logger.log(`${i}`,...t);return super.emit(e,...t)}getUserList(e){return Te(this,void 0,void 0,function*(){return this.checkV2(),this._getUserList(e)})}_getUserList(e){var t;return Te(this,void 0,void 0,function*(){_e({accountIds:dn},{accountIds:e},"",!0);var i=[];e.forEach(e=>{this.model.getUser(e)||i.push(e)});var r=null;i.length>0&&(r=yield this.core.sendCmd("v2GetUserList",{accountIds:i})),((null===(t=null==r?void 0:r.content)||void 0===t?void 0:t.data)||[]).forEach(e=>{this.model.setUser(e)});var s=[];return e.forEach(e=>{var t=this.model.getUser(e);t&&s.push(t)}),s})}getUserListFromCloud(e){return Te(this,void 0,void 0,function*(){this.checkV2(),_e({accountIds:{type:"array",min:1,max:500,itemType:"string"}},{accountIds:e},"",!0);var t=(yield this.core.sendCmd("v2GetUserList",{accountIds:e})).content.data||[],i=[];t.forEach(e=>{var t=this.model.getUser(e.accountId);this.compareUserForUpdate(t,e)&&i.push(e),this.model.setUser(e)});var r=e.reduce((e,t)=>{var i=this.model.getUser(t);return i&&e.push(i),e},[]);return i.length>0&&this.emit("onUserProfileChanged",i),r})}compareUserForUpdate(e,t){return!e||!("number"==typeof e.updateTime&&"number"==typeof t.updateTime&&e.updateTime>=t.updateTime)}updateSelfUserProfile(e){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(Hn,e,"",!0);var t=yield this.core.sendCmd("v2UpdateSelfUserProfile",{tag:Object.assign(Object.assign({},e),{accountId:this.core.account})});yield this.updateUserProfileInMemory(Object.assign(Object.assign({},e),{updateTime:t.content.updateTime}))})}addUserToBlockList(e){return Te(this,void 0,void 0,function*(){if(this.checkV2(),e===this.core.account)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"Cannot block yourself"}});_e({accountId:Gn},{accountId:e},"",!0),yield this.core.sendCmd("v2UpdateBlockList",{accountId:e,addToBlockList:!0}),this.model.addToBlockList([e]),this.emitBlockListAdded(e)})}removeUserFromBlockList(e){return Te(this,void 0,void 0,function*(){if(this.checkV2(),e===this.core.account)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"Cannot unblock yourself"}});_e({accountId:Gn},{accountId:e},"",!0),yield this.core.sendCmd("v2UpdateBlockList",{accountId:e,addToBlockList:!1}),this.model.removeFromBlockList([e]),this.emit("onBlockListRemoved",e)})}searchUserByOption(e){return Te(this,void 0,void 0,function*(){if(this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),_e({keyword:{type:"string",allowEmpty:!1},searchName:{type:"boolean",required:!1},searchAccountId:{type:"boolean",required:!1},searchMobile:{type:"boolean",required:!1}},e,"",!0),!1===(void 0===e.searchName||e.searchName)&&!e.searchAccountId&&!e.searchMobile)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"one of searchName, searchAccountId, searchMobile must be true"}});return this.model.getUserListBySearchOption(e)})}getBlockList(){return this.checkV2(),Promise.resolve(this.model.blockList)}checkBlock(e){return this.checkV2(),_e({accountIds:dn},{accountIds:e},"",!0),Promise.resolve(this.model.checkBlock(e))}updateUserProfileInMemory(e){return Te(this,void 0,void 0,function*(){var t=this.model.getUser(this.core.account);t?(Object.assign(t,e),this.model.setUser(t)):t=(yield this._getUserList([this.core.account]))[0],t&&this.emit("onUserProfileChanged",[t])})}onUpdateUserProfileHandler(e){return Te(this,void 0,void 0,function*(){var t=e.content.data;yield this.updateUserProfileInMemory(t)})}onUpdateBlockListHandler(e){var t=e.content.accountId;e.content.addToBlockList?(this.model.addToBlockList([t]),this.emitBlockListAdded(t)):(this.model.removeFromBlockList([t]),this.emit("onBlockListRemoved",t))}syncBlockAndMuteListHandler(e){e.content.data.forEach(e=>{e.isBlock?this.model.addToBlockList([e.accountId]):this.model.setAccountMuteMode(e.accountId,e.isMute?1:0)})}v2SyncSelfUserInfoHandler(e){var t=e.content.user;this.model.setUser(t)}checkUserUpdate(e,t){var i=e.senderId;i!==this.core.account&&this.refreshUserInfo(i,t)}refreshUserInfo(e,t=0){return Te(this,void 0,void 0,function*(){if(e&&"string"==typeof e){var i=this.model.getUser(e),r=[];if(!i||i&&"number"==typeof i.updateTime&&"number"==typeof t&&!isNaN(i.updateTime)&&!isNaN(t)&&i.updateTimethis.getFriend(e)).filter(e=>!!e)}getFriendListBySearchOption(e){return Array.from(this.validFriendIds.values()).map(e=>this.getFriend(e)).filter(t=>{var i=void 0===e.searchAlias||e.searchAlias;return!(void 0===t||!(i&&t.alias&&t.alias.includes(e.keyword)||e.searchAccountId&&t.accountId.includes(e.keyword)))})}getFriendByIds(e){return e.map(e=>this.getFriend(e)).filter(e=>!!e)}setFriendTimetag(e){this.friendTimetag=e}getFriendTimetag(){return this.friendTimetag}}class so{constructor(){this.list=[],this.maxCount=1e3}reset(){this.list=[]}updateFriendAddApplicationStatus(e,t,i){if(0!==t)for(var r of this.list)r.applicantAccountId===e&&0===r.status&&(r.status=t,r.operatorAccountId=i)}getAddApplicationList(e){var t=void 0===e.offset?0:e.offset,i=this.list.filter(t=>{var i=e.status||[];return 0===i.length||!!i.includes(t.status)}).reverse(),r=e.limit||50,s=i.slice(t,t+r),n=t+r>=i.length;return{infos:s,finished:n,offset:n?0:t+r}}checkSameApplication(e,t,i=!1){return e.applicantAccountId===t.applicantAccountId&&e.recipientAccountId===t.recipientAccountId&&(!i||e.timestamp===t.timestamp)}setAllApplicationRead(){for(var e of this.list)e.read=!0}setApplicationRead(e){for(var t of this.list)this.checkSameApplication(t,e)&&(t.read=!0)}getAddApplicationUnreadCount(){var e=new Set;for(var t of this.list)t.read||0!==t.status||e.add(t.applicantAccountId);return e.size}appendFriendAddApplication(e){this.list.push(e),this.list.length>this.maxCount&&this.list.shift()}clearApplicationList(){this.list=[]}deleteApplication(e){this.list=this.list.map(t=>{if(!this.checkSameApplication(t,e,!1))return t}).filter(e=>e)}}var no={need:{id:1,converter:e=>e?2:1,retConverter:e=>"2"===e}};gt(no),gt(no);var oo=oo||function(t){var i;"undefined"!=typeof window&&window.crypto&&(i=window.crypto),"undefined"!=typeof self&&self.crypto&&(i=self.crypto),"undefined"!=typeof globalThis&&globalThis.crypto&&(i=globalThis.crypto),!i&&"undefined"!=typeof window&&window.msCrypto&&(i=window.msCrypto),!i&&void 0!==e.g&&e.g.crypto&&(i=e.g.crypto);var r=function(){if(i){if("function"==typeof i.getRandomValues)try{return i.getRandomValues(new Uint32Array(1))[0]}catch(e){}if("function"==typeof i.randomBytes)try{return i.randomBytes(4).readInt32LE()}catch(e){}}throw new Error("Native crypto module could not be used to get secure random number.")},s=Object.create||function(){function e(){}return function(t){var i;return e.prototype=t,i=new e,e.prototype=null,i}}(),n={},o=n.lib={},a=o.Base={extend:function(e){var t=s(this);return e&&t.mixIn(e),t.hasOwnProperty("init")&&this.init!==t.init||(t.init=function(){t.$super.init.apply(this,arguments)}),t.init.prototype=t,t.$super=this,t},create:function(){var e=this.extend();return e.init.apply(e,arguments),e},init:function(){},mixIn:function(e){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);e.hasOwnProperty("toString")&&(this.toString=e.toString)},clone:function(){return this.init.prototype.extend(this)}},c=o.WordArray=a.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:4*e.length},toString:function(e){return(e||l).stringify(this)},concat:function(e){var t=this.words,i=e.words,r=this.sigBytes,s=e.sigBytes;if(this.clamp(),r%4)for(var n=0;n>>2]>>>24-n%4*8&255;t[r+n>>>2]|=o<<24-(r+n)%4*8}else for(var a=0;a>>2]=i[a>>>2];return this.sigBytes+=s,this},clamp:function(){var e=this.words,i=this.sigBytes;e[i>>>2]&=4294967295<<32-i%4*8,e.length=t.ceil(i/4)},clone:function(){var e=a.clone.call(this);return e.words=this.words.slice(0),e},random:function(e){for(var t=[],i=0;i>>2]>>>24-s%4*8&255;r.push((n>>>4).toString(16)),r.push((15&n).toString(16))}return r.join("")},parse:function(e){for(var t=e.length,i=[],r=0;r>>3]|=parseInt(e.substr(r,2),16)<<24-r%8*4;return new c.init(i,t/2)}},h=d.Latin1={stringify:function(e){for(var t=e.words,i=e.sigBytes,r=[],s=0;s>>2]>>>24-s%4*8&255;r.push(String.fromCharCode(n))}return r.join("")},parse:function(e){for(var t=e.length,i=[],r=0;r>>2]|=(255&e.charCodeAt(r))<<24-r%4*8;return new c.init(i,t)}},p=d.Utf8={stringify:function(e){try{return decodeURIComponent(escape(h.stringify(e)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(e){return h.parse(unescape(encodeURIComponent(e)))}},u=o.BufferedBlockAlgorithm=a.extend({reset:function(){this._data=new c.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=p.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(e){var i,r=this._data,s=r.words,n=r.sigBytes,o=this.blockSize,a=n/(4*o),d=(a=e?t.ceil(a):t.max((0|a)-this._minBufferSize,0))*o,l=t.min(4*d,n);if(d){for(var h=0;h>>2]>>>24-n%4*8&255)<<16|(t[n+1>>>2]>>>24-(n+1)%4*8&255)<<8|t[n+2>>>2]>>>24-(n+2)%4*8&255,a=0;a<4&&n+.75*a>>6*(3-a)&63));var c=r.charAt(64);if(c)for(;s.length%4;)s.push(c);return s.join("")},parse:function(e){var t=e.length,i=this._map,r=this._reverseMap;if(!r){r=this._reverseMap=[];for(var s=0;s>>6-n%4*2;r[s>>>2]|=o<<24-s%4*8,s++}return vo.create(r,s)}(e,t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},oo.enc.Base64,function(e){e.lib.Cipher||function(){var t=e,i=t.lib,r=i.Base,s=i.WordArray,n=i.BufferedBlockAlgorithm,o=t.enc;o.Utf8;var a=o.Base64,c=t.algo.EvpKDF,d=i.Cipher=n.extend({cfg:r.extend(),createEncryptor:function(e,t){return this.create(this._ENC_XFORM_MODE,e,t)},createDecryptor:function(e,t){return this.create(this._DEC_XFORM_MODE,e,t)},init:function(e,t,i){this.cfg=this.cfg.extend(i),this._xformMode=e,this._key=t,this.reset()},reset:function(){n.reset.call(this),this._doReset()},process:function(e){return this._append(e),this._process()},finalize:function(e){return e&&this._append(e),this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){function e(e){return"string"==typeof e?_:v}return function(t){return{encrypt:function(i,r,s){return e(r).encrypt(t,i,r,s)},decrypt:function(i,r,s){return e(r).decrypt(t,i,r,s)}}}}()});i.StreamCipher=d.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var l=t.mode={},h=i.BlockCipherMode=r.extend({createEncryptor:function(e,t){return this.Encryptor.create(e,t)},createDecryptor:function(e,t){return this.Decryptor.create(e,t)},init:function(e,t){this._cipher=e,this._iv=t}}),p=l.CBC=function(){var e=h.extend();function t(e,t,i){var r,s=this._iv;s?(r=s,this._iv=void 0):r=this._prevBlock;for(var n=0;n>>2];e.sigBytes-=t}};i.BlockCipher=d.extend({cfg:d.cfg.extend({mode:p,padding:u}),reset:function(){var e;d.reset.call(this);var t=this.cfg,i=t.iv,r=t.mode;this._xformMode==this._ENC_XFORM_MODE?e=r.createEncryptor:(e=r.createDecryptor,this._minBufferSize=1),this._mode&&this._mode.__creator==e?this._mode.init(this,i&&i.words):(this._mode=e.call(r,this,i&&i.words),this._mode.__creator=e)},_doProcessBlock:function(e,t){this._mode.processBlock(e,t)},_doFinalize:function(){var e,t=this.cfg.padding;return this._xformMode==this._ENC_XFORM_MODE?(t.pad(this._data,this.blockSize),e=this._process(!0)):(e=this._process(!0),t.unpad(e)),e},blockSize:4});var m=i.CipherParams=r.extend({init:function(e){this.mixIn(e)},toString:function(e){return(e||this.formatter).stringify(this)}}),g=(t.format={}).OpenSSL={stringify:function(e){var t=e.ciphertext,i=e.salt;return(i?s.create([1398893684,1701076831]).concat(i).concat(t):t).toString(a)},parse:function(e){var t,i=a.parse(e),r=i.words;return 1398893684==r[0]&&1701076831==r[1]&&(t=s.create(r.slice(2,4)),r.splice(0,4),i.sigBytes-=16),m.create({ciphertext:i,salt:t})}},v=i.SerializableCipher=r.extend({cfg:r.extend({format:g}),encrypt:function(e,t,i,r){r=this.cfg.extend(r);var s=e.createEncryptor(i,r),n=s.finalize(t),o=s.cfg;return m.create({ciphertext:n,key:i,iv:o.iv,algorithm:e,mode:o.mode,padding:o.padding,blockSize:e.blockSize,formatter:r.format})},decrypt:function(e,t,i,r){return r=this.cfg.extend(r),t=this._parse(t,r.format),e.createDecryptor(i,r).finalize(t.ciphertext)},_parse:function(e,t){return"string"==typeof e?t.parse(e,this):e}}),f=(t.kdf={}).OpenSSL={execute:function(e,t,i,r){r||(r=s.random(8));var n=c.create({keySize:t+i}).compute(e,r),o=s.create(n.words.slice(t),4*i);return n.sigBytes=4*t,m.create({key:n,iv:o,salt:r})}},_=i.PasswordBasedCipher=v.extend({cfg:v.cfg.extend({kdf:f}),encrypt:function(e,t,i,r){var s=(r=this.cfg.extend(r)).kdf.execute(i,e.keySize,e.ivSize);r.iv=s.iv;var n=v.encrypt.call(this,e,t,s.key,r);return n.mixIn(s),n},decrypt:function(e,t,i,r){r=this.cfg.extend(r),t=this._parse(t,r.format);var s=r.kdf.execute(i,e.keySize,e.ivSize,t.salt);return r.iv=s.iv,v.decrypt.call(this,e,t,s.key,r)}})}()}(oo);var fo=oo,_o=fo.lib.StreamCipher,Io=fo.algo,yo=Io.RC4=_o.extend({_doReset:function(){for(var e=this._key,t=e.words,i=e.sigBytes,r=this._S=[],s=0;s<256;s++)r[s]=s;s=0;for(var n=0;s<256;s++){var o=s%i,a=t[o>>>2]>>>24-o%4*8&255;n=(n+r[s]+a)%256;var c=r[s];r[s]=r[n],r[n]=c}this._i=this._j=0},_doProcessBlock:function(e,t){e[t]^=Eo.call(this)},keySize:8,ivSize:0});function Eo(){for(var e=this._S,t=this._i,i=this._j,r=0,s=0;s<4;s++){i=(i+e[t=(t+1)%256])%256;var n=e[t];e[t]=e[i],e[i]=n,r|=e[(e[t]+e[i])%256]<<24-8*s}return this._i=t,this._j=i,r}fo.RC4=_o._createHelper(yo);var Mo=Io.RC4Drop=yo.extend({cfg:yo.cfg.extend({drop:192}),_doReset:function(){yo._doReset.call(this);for(var e=this.cfg.drop;e>0;e--)Eo.call(this)}});fo.RC4Drop=_o._createHelper(Mo),oo.RC4;var To={accountId:1,name:3,avatar:4,sign:5,gender:{id:6,retType:"number"},email:7,birthday:8,mobile:9,serverExtension:10,aiModelType:{id:11,retType:"number"},modelConfig:{id:12,retConverter:e=>{if(e=_t(e)){var t=Object.keys(e).reduce((t,i)=>(t[function(e){return(e=e||"").split("_").map((e,t)=>0===t?e:e[0].toUpperCase()+e.slice(1)).join("")}(i)]=e[i],t),{});if("string"==typeof t.promptKeys)try{t.promptKeys=JSON.parse(t.promptKeys)}catch(e){}return t}}},yunxinConfig:{id:13,retConverter:e=>{if(e=_t(e))return e}},valid:{id:14,retType:"boolean"},createTime:{id:15,retType:"number"},updateTime:{id:16,retType:"number"}};function So(e){try{var t=JSON.parse(e);return"number"==typeof t.index?{msg:t.msg||"",type:t.type,lastChunk:{content:t.msg,chunkTime:parseInt(t.timestamp),type:t.type,index:parseInt(t.index)}}:t}catch(e){return}}function No(e){try{var t=JSON.parse(e);return t&&t.length>0?t.map(e=>(e.description=e.desc,delete e.desc,e)):[]}catch(e){return[]}}var Co={code:{id:1,retType:"number"},accountId:2,requestId:3,content:{id:4,retConverter:So},aiRAGs:{id:5,retConverter:No},timestamp:{id:6,retType:"number"},aiStreamStatus:{id:7,retType:"number"},aiStream:{id:8,retType:"boolean"}},Ao={serverId:1,clientId:2,type:{id:3,retType:"number"},content:{id:4,retConverter:So},aiRAGs:{id:6,retConverter:No}};gt(Co),gt(To),gt({hasMore:{id:16,retType:"boolean"},nextToken:2}),gt(Lr),gt(Co),gt(Ao);var Oo={accountId:1,uid:{id:2,retType:"number"},joinTime:{id:3,retType:"number"},expireTime:{id:4,retType:"number"},deviceId:5},Ro={channelType:{id:1,retType:"number",retAccess:"channelInfo.channelType"},channelName:{id:2,retAccess:"channelInfo.channelName"},channelId:{id:3,retAccess:"channelInfo.channelId"},createTime:{id:4,retType:"number",retAccess:"channelInfo.createTime"},expireTime:{id:5,retType:"number",retAccess:"channelInfo.expireTime"},creatorAccountId:{id:6,retAccess:"channelInfo.creatorAccountId"},channelExtension:{id:7,retAccess:"channelInfo.channelExtension"},channelValid:{id:8,retDef:!0,retAccess:"channelInfo.channelValid",retConverter:e=>1!==parseInt(e)},fromAccid:10,toAccid:11,requestId:12,pushEnabled:{id:13,access:"pushConfig.pushEnabled",converter:vt,retType:"boolean"},pushTitle:{id:14,access:"pushConfig.pushTitle"},pushContent:{id:15,access:"pushConfig.pushContent"},pushPayload:{id:16,access:"pushConfig.pushPayload"},unreadEnabled:{id:17,access:"signallingConfig.unreadEnabled",converter:vt,retType:"boolean",def:1},members:{id:18,retAccess:"members",retConverter:e=>{try{return JSON.parse(e).map(e=>ut(e,gt(Oo)))}catch(e){return}}},attach:{id:19,retConverter:_t},serverExtension:{id:20,retDef:""},offlineEnabled:{id:21,converter:vt,retType:"boolean",def:1},msgId:22,selfUid:{id:23,retType:"number",access:"signallingConfig.selfUid"},time:{id:24,retType:"number"},rtcChannelName:{id:25,access:"rtcConfig.rtcChannelName"},rtcTokenTtl:{id:26,retType:"number",access:"rtcConfig.rtcTokenTtl",retAccess:"rtcInfo.rtcTokenTtl"},rtcToken:{id:27,retAccess:"rtcInfo.rtcToken"},rtcParams:{id:28,access:"rtcConfig.rtcParams",retAccess:"rtcInfo.rtcParams"},callStatus:{id:30,retType:"number"}};gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro),gt(Ro);var bo,ko={"19_1":"v2PublishEvent","14_2":"v2OnUserStatusChange","19_3":"v2SubscribeUserStatus","19_4":"v2UnsubscribeUserStatus","19_5":"v2UnsubscribeAllUserStatus","19_6":"v2QuerySubscribeEvent","19_7":"v2QueryAllSubscribeEvent","14_9":"v2OnMultiUserStatusChange"},Lo="V2NIMSubscriptionService",Vo={eventType:{id:1,retType:"number"},statusType:{id:2,retType:"number"},uniqueId:3,extension:4,duration:{id:5,retType:"number"},onlineOnly:{id:6,retType:"boolean",converter:e=>e?1:2},multiSync:{id:7,retType:"boolean",converter:vt},publishTime:{id:10,retType:"number"},serverId:11,clientType:{id:12,retType:"number"},serverExtension:13,extensionReceived:14,accountId:103},Po={eventType:{id:1,retType:"number"},duration:{id:2,retType:"number"},immediateSync:{id:3,retType:"number",converter:vt},accountId:102,subscribeTime:{id:105,retType:"number"}},Do={v2PublishEvent:{sid:19,cid:1,service:Lo,params:[{type:"Property",name:"tag",reflectMapper:Vo}],response:[{type:"Property",name:"data",reflectMapper:gt(Vo)}]},v2OnUserStatusChange:{sid:14,cid:2,service:Lo,response:[{type:"Property",name:"data",reflectMapper:gt(Vo)}]},v2SubscribeUserStatus:{sid:19,cid:3,service:Lo,params:[{type:"Property",name:"tag",reflectMapper:Po},{type:"StrArray",name:"accountIds"}],response:[{type:"StrArray",name:"failedList"}]},v2UnsubscribeUserStatus:{sid:19,cid:4,service:Lo,params:[{type:"Property",name:"tag",reflectMapper:Po},{type:"StrArray",name:"accountIds"}],response:[{type:"StrArray",name:"failedList"}]},v2UnsubscribeAllUserStatus:{sid:19,cid:5,service:Lo,params:[{type:"Property",name:"tag",reflectMapper:Po}]},v2QuerySubscribeEvent:{sid:19,cid:6,service:Lo,params:[{type:"Property",name:"tag",reflectMapper:Po},{type:"StrArray",name:"accountIds"}],response:[{type:"PropertyArray",name:"data",reflectMapper:gt(Po)}]},v2QueryAllSubscribeEvent:{sid:19,cid:7,service:Lo,params:[{type:"Property",name:"tag",reflectMapper:Po}],response:[{type:"PropertyArray",name:"data",reflectMapper:gt(Po)}]},v2OnMultiUserStatusChange:{sid:14,cid:9,service:Lo,response:[{type:"PropertyArray",name:"data",reflectMapper:gt(Vo)}]}},wo={accountIds:{type:"array",required:!0,itemType:"string",min:1,max:100},duration:{type:"number",required:!1,min:60,max:2592e3},immediateSync:{type:"boolean",required:!1}},Uo={accountIds:{type:"array",required:!1,itemType:"string",max:100}},xo={statusType:{type:"number",required:!0,min:1e4,max:2147483647},duration:{type:"number",required:!1,min:60,max:604800},extension:{type:"jsonstr",required:!1},onlineOnly:{type:"boolean",required:!1},multiSync:{type:"boolean",required:!1}};!function(e){e[e.V2NIM_PROXY_REQUEST_METHOD_GET=1]="V2NIM_PROXY_REQUEST_METHOD_GET",e[e.V2NIM_PROXY_REQUEST_METHOD_POST=2]="V2NIM_PROXY_REQUEST_METHOD_POST",e[e.V2NIM_PROXY_REQUEST_METHOD_PUT=3]="V2NIM_PROXY_REQUEST_METHOD_PUT",e[e.V2NIM_PROXY_REQUEST_METHOD_DELETE=4]="V2NIM_PROXY_REQUEST_METHOD_DELETE"}(bo||(bo={}));gt({zone:1,path:2,method:3,header:4,body:5}),gt({fromAccountId:1,body:2,time:{id:3,retType:"number"}}),bo.V2NIM_PROXY_REQUEST_METHOD_DELETE,bo.V2NIM_PROXY_REQUEST_METHOD_GET,bo.V2NIM_PROXY_REQUEST_METHOD_POST,bo.V2NIM_PROXY_REQUEST_METHOD_PUT;var Fo=ot;Fo.registerService(class extends ii{constructor(e,t={}){var i;super("V2NIMLoginService",e),this.account="",this.previousLoginAccount="",this.token="",this.deviceId="",this.clientSession="",this.processId="",this.kickedDetail=null,this.binaryWebsocket=!0,this.core._registerDep(li,"misc"),mt({cmdMap:Tt,cmdConfig:Ct}),"v2"===e.options.apiVersion&&(mt({cmdMap:St,cmdConfig:At}),this.core.auth=this),this.previousLoginManager=new qe,this.doLoginStepsManager=new qe,this.loginTimerManager=new Ee,this.loginOption=Object.assign({},mi),this.config={lbsUrls:ui,linkUrl:"weblink.netease.im:443",linkSSL:!0},this.setOptions(t),e.V2NIMLoginService=this,!1!==this.core.options.binaryWebsocket&&"function"==typeof Uint8Array?(this.binaryWebsocket=!0,i=new Yt(this.core)):(this.binaryWebsocket=!1,i=new Xt(this.core)),this.clientSocket=i,"v2"===this.core.options.apiVersion&&(this.core.clientSocket=i),this.lifeCycle=new ri(e),this.reconnect=new Qt(e),this.lbs=new ei(e),this.authenticator=new ti(e),this.dataSync=new si(e)}get hasSettingService(){var e;return!!(null===(e=this.core.V2NIMSettingService)||void 0===e?void 0:e.name)}setOptions(e){var t,i,r;_e({lbsUrls:{type:"array",itemType:"string",min:1,required:!1},linkUrl:{type:"string",allowEmpty:!1,required:!1}},e,"",!0),this.config=Ue(this.config,e),null===(i=null===(t=this.core.clientSocket)||void 0===t?void 0:t.setLinkSSL)||void 0===i||i.call(t,null===(r=this.config.linkSSL)||void 0===r||r);var s="",n="";this.config.isFixedDeviceId?(s=Oe.localStorage.getItem("__NIM_DEVC_ID__")||De(),n=Oe.localStorage.getItem("__NIM_CLIENT_SESSION_ID__")||De(),Oe.localStorage.setItem("__NIM_DEVC_ID__",s),Oe.localStorage.setItem("__NIM_CLIENT_SESSION_ID__",n)):(s=De(),n=De()),this.deviceId=s,this.clientSession=n,this.core.reporter.setConfig({common:{dev_id:s}})}reset(){this.account="",this.token="",this.processId="",this.lbs.reset(),this.reconnect.destroy(),this.authenticator.reset(),this.authenticator.clearLastLoginClient(),this.dataSync.reset()}login(e,t,i={}){return Te(this,void 0,void 0,function*(){this._checkApiVersion();var r=Oe.getSystemInfo()||{},s=r.os?r.os.toLowerCase():"";if("React Native"===Oe.platform&&"android"===s&&this.hasSettingService&&Ve(this.core.V2NIMSettingService,"push.offlinePushPlugin"))try{this.deviceInfo=yield this.core.V2NIMSettingService.push.getRNDeviceInfo()}catch(e){this.logger.error(e)}if("string"!=typeof e||""===e.trim())throw new me({detail:{reason:"Account must be string"}});if(_e(pi,i,"",!0),0===(i=Ue(mi,i)).authType&&!t)throw new me({detail:{reason:"When authType is 0, token cannot be empty"}});if(""!==this.previousLoginAccount&&this.previousLoginAccount!==e&&this.core._clearModuleData(),0===this.getLoginStatus())this.logger.log(`V2NIMLoginService::login:allowLogin:${e}`,i);else{if(1===this.getLoginStatus())return this.smoothForLogined(e,t,i);if(2===this.getLoginStatus())return this.smoothForLogining(e,t,i)}this.account=e,this.previousLoginAccount=e,this.token=t,this.processId=De(),this.loginOption=Ue(mi,i),this.kickedDetail=null,this.loginTimerManager.destroy(),this.loginTimerManager.addTimer(()=>{var e=new pe({code:de.V2NIM_ERROR_CODE_TIMEOUT,detail:{reason:"Login API timeout"}});this.doLoginStepsManager.clear(e),this.previousLoginManager.clear(e),this.originLoginPromise=void 0,this.lifeCycle.processEvent("exited",e)},this.loginOption.timeout>0?this.loginOption.timeout:6e4,1);try{yield this.multiTryDoLogin(),this.loginTimerManager.destroy()}catch(e){throw this.loginTimerManager.destroy(),e}})}setAppVisibility(){this.logger.warn("V2NIMLoginService::setAppVisibility is deprecated @v10.9.40")}getChatroomLinkAddress(e,t){return Te(this,void 0,void 0,function*(){return _e({roomId:{type:"string",regExp:/^\d+$/,required:!0,allowEmpty:!1},miniProgram:{type:"boolean",required:!1}},{roomId:e,miniProgram:t},"",!0),t=void 0===t?we():t,(yield this.clientSocket.sendCmd("v2GetChatroomLinkAddress",{roomId:e,miniProgram:t})).content.linkAddress})}multiTryDoLogin(e){return Te(this,void 0,void 0,function*(){for(var t=new pe({code:de.V2NIM_ERROR_CODE_INTERNAL,detail:{reason:"loginFailed"}}),i=0;i<=this.loginOption.retryCount;i++){var r=`V2NIMLoginService::times of login try: ${i}`;i>0?this.logger.warn(r):this.logger.log(r);try{this.originLoginPromise=e||this.doLogin(!1),e=void 0;var s=yield this.previousLoginManager.add(this.originLoginPromise);return this.core.reporter.reportTraceEnd("login",!0),this.doLoginStepsManager.clear(),this.previousLoginManager.clear(),this.originLoginPromise=void 0,s}catch(e){if(t=e||t,this.logger.error(`V2NIMLoginService::login failed, times of login try: ${i}, err.code: ${null==t?void 0:t.code}, err.message: "${null==t?void 0:t.message}"`),t.code!==de.V2NIM_ERROR_CODE_CANCELLED&&this.core.reporter.reportTraceEnd("login",!1),this.reconnect.clearReconnectTimer(),this.checkLoginTerminalCode(t&&t.code))throw this.lifeCycle.processEvent("exited",t),t;t&&399===t.code&&this.lbs.reset()}}throw this.lifeCycle.processEvent("exited",t),t})}doLogin(e){var t,i;return Te(this,void 0,void 0,function*(){var r=!!e||this.authenticator.checkAutoLogin(this.loginOption.forceMode);this.core.reporter.reportTraceCancel("login"),this.core.reporter.reportTraceStart("login",r?{user_id:this.account,action:"auto_login",process_id:this.processId,binary_websocket:this.binaryWebsocket}:{user_id:this.account,action:"manual_login",process_id:this.processId,binary_websocket:this.binaryWebsocket}),this.core.reporter.reportTraceUpdateV2("login",{code:0,description:JSON.stringify(this.loginOption),operation_type:"conf_init",succeed:!0,duration:0,target:""},{asyncParams:Oe.net.getNetworkStatus()});var s=yield this.doLoginStepsManager.add(this.lbs.getLbsInfos());yield this.doLoginStepsManager.add(this.clientSocket.connect(s,e));var n=yield this.doLoginStepsManager.add(this.authenticator.verifyAuthentication(r));if(this.processId=De(),this.clientSocket.resetSocketConfig(),this.reconnect.reset(),this.dataSync.reset(),this.lifeCycle.processEvent("loginSucc",void 0,Object.assign(Object.assign({},n),{isReconnect:e})),this.clientSocket.ping(),this.core.abtest.abtRequest(),"function"==typeof(null===(t=this.core.V2NIMClientAntispamUtil)||void 0===t?void 0:t.downloadLocalAntiSpamVocabs)&&this.core.V2NIMClientAntispamUtil.downloadLocalAntiSpamVocabs(),"function"==typeof(null===(i=this.core.cloudStorage)||void 0===i?void 0:i.init))try{yield this.core.cloudStorage.init(n.timestamp)}catch(e){this.logger.warn("doLogin::cloudStorage init error",e)}return n})}smoothForLogined(e,t,i){return Te(this,void 0,void 0,function*(){var r=this.checkIsSameLogin(e,t,i);return this.logger.warn(`V2NIMLoginService::smoothForLogined:Logined, isSameLogin ${r}`),r?void 0:(yield this.logout(),this.login(e,t,i))})}smoothForLogining(e,t,i){return Te(this,void 0,void 0,function*(){var r=this.checkIsSameLogin(e,t,i);if(this.logger.warn(`V2NIMLoginService::smoothForLogining:Logining progress exists, abort the previous login attempt and start next attempt, isSameLogin ${r}`),this.previousLoginManager.clear(),this.reconnect.reset(),this.account=e,this.previousLoginAccount=e,this.token=t,this.loginOption=Ue(this.loginOption,i),!r)return this.doLoginStepsManager.clear(),this.clientSocket.doDisconnect(Dt.ACTIVE,"Aborted"),this.reset(),this.lifeCycle.processEvent("logout"),yield Promise.resolve(),this.login(e,t,i);if(!this.originLoginPromise)throw new pe({code:de.V2NIM_ERROR_CODE_INTERNAL,detail:{reason:"NoPreviousLoginExists"}});this.reconnect.reset(),yield Promise.resolve(),yield this.multiTryDoLogin(this.originLoginPromise)})}checkIsSameLogin(e,t,i){return this.account===e&&this.loginOption.authType===i.authType&&(0!==i.authType||this.token===t)}logout(){return Te(this,void 0,void 0,function*(){this._checkApiVersion(),this.doLoginStepsManager.clear(),this.previousLoginManager.clear(),this.loginTimerManager.destroy(),this.originLoginPromise=void 0;var e=this.getConnectStatus(),t=this.getLoginStatus();switch(t){case 1:try{yield this.clientSocket.sendCmd("v2Logout",void 0,{timeout:1e3}),this.clientSocket.doDisconnect(Dt.ACTIVE,"UserActiveDisconnect"),this.core._clearModuleData(),this.lifeCycle.processEvent("logout")}catch(e){this.logger.error("Instance::disconnect sendCmd:logout error",e),this.clientSocket.doDisconnect(Dt.ACTIVE,"UserActiveDisconnect"),this.core._clearModuleData(),this.lifeCycle.processEvent("logout")}break;case 2:case 3:this.clientSocket.doDisconnect(Dt.ACTIVE,"UserActiveDisconnect"),this.core._clearModuleData(),this.lifeCycle.processEvent("logout");break;case 0:throw this.core._clearModuleData(),new pe({code:de.V2NIM_ERROR_CODE_ILLEGAL_STATE,detail:{reason:`Illegal logout. loginStatus ${t}. connectStatus ${e}`}});default:throw this.core._clearModuleData(),new pe({code:de.V2NIM_ERROR_CODE_ILLEGAL_STATE,detail:{reason:`Illegal logout. illegal status: loginStatus ${t}. connectStatus ${e}`}})}})}getConnectStatus(){return this.lifeCycle.getConnectStatus()}getLoginStatus(){return this.lifeCycle.getLoginStatus()}getLoginUser(){return this.account}getLoginClients(){return function(e,t){e=e||[],t=t||"";for(var i=[],r=[],s=0;shi(e,["type","os","timestamp","customTag","customClientType","clientId","clientIP"]))}getCurrentLoginClient(){var e;if(null===(e=this.authenticator.loginClientOfThisConnection)||void 0===e?void 0:e.clientId)return hi(this.authenticator.loginClientOfThisConnection,["type","os","timestamp","customTag","customClientType","clientId","clientIP"])}getDataSync(){var e=this.dataSync.datas;return e&&e.length>0?e.map(e=>({type:e.type,state:e.state})):null}setReconnectDelayProvider(e){this.reconnect._setReconnectDelayProvider(e)}kickOffline(e){return Te(this,void 0,void 0,function*(){if(this._checkApiVersion(),_e({clientId:{type:"string",allowEmpty:!1}},e,"",!0),0===Ve(yield this.clientSocket.sendCmd("v2KickOffline",{clientIds:[e.clientId]}),"content.clientIds.length"))throw new pe({code:de.V2NIM_ERROR_CODE_REQUEST_FAILED})})}getKickedOfflineDetail(){return this.kickedDetail}checkLoginTerminalCode(e){return this.authenticator.checkLoginTerminalCode(e)}checkIllegalState(){if(!this.getLoginUser())throw new pe({code:de.V2NIM_ERROR_CODE_ILLEGAL_STATE})}_checkApiVersion(){if("v2"!==this.core.options.apiVersion)throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:'apiVersion is not "v2"'}})}v2LoginHandler(e){if(e.error)throw this.clientSocket.doDisconnect(Dt.ACTIVE,e.error),e.error;return e}v2LoginClientChangeHandler(e){this.authenticator.changeLoginClient(parseInt(e.content.state),e.content.datas)}nimLoginClientChangeHandler(e){this.authenticator.changeLoginClient(parseInt(e.content.state),e.content.datas)}qchatLoginClientChangeHandler(e){var t=parseInt(e.content.state);t=1===t?2:3,this.authenticator.changeLoginClient(t,[e.content.data])}v2BeKickedHandler(e){if(e.error)this.core.logger.error("v2BeKickedHandler error, ",e.error);else{var t=function(e){return It({reason:{type:"number"},clientType:{type:"number"},customClientType:{type:"number"}},e)}(e.content);this.core.logger.warn("v2Bekicked::",t),this.kickedDetail=t,this.clientSocket.doDisconnect(Dt.KICKED,t),this.core._clearModuleData(),this.lifeCycle.processEvent("kicked",new pe({code:de.V2NIM_ERROR_CODE_DISCONNECT,detail:{reason:"disconnect due to kicked"}}),t),this.emit("onKickedOffline",t)}}emit(e,...t){var i=`${this.name}::emit ${e.toString()}`;if("onLoginFailed"===e||"onDisconnected"===e||"onConnectFailed"===e){var r=t[0];this.logger.log(`${i}`,r.toString())}else if("onDataSync"===e){var s=t[2];this.logger.log(`${i}`,t[0],t[1],s&&s.toString())}else this.logger.log(`${i}`,...t);return super.emit(e,...t)}},"V2NIMLoginService"),Fo.registerService(class extends ii{constructor(e){super("V2NIMSyncService",e),this.teamKey=["teams","superTeams","myTeamMembers","mySuperTeamMembers"],this.config={},this.timetags={},"v2"===this.core.options.apiVersion&&(this.initEventListeners(),mt({cmdMap:gi,cmdConfig:vi}),this.setListener())}reset(){this.timetags={}}setListener(){this.core.eventBus.on("V2NIMSync/updateTimetag",e=>{Object.keys(e).forEach(t=>{e[t]>(this.timetags[t]||0)&&(this.timetags[t]=e[t])})})}setOptions(e){var t=this.core,i=!(!t.V2NIMConversationService.name&&!t.V2NIMLocalConversationService.name);return this.config=Object.assign({myInfo:!!t.V2NIMUserService.name,offlineMsgs:!!t.V2NIMMessageService.name,roamingMsgs:!!t.V2NIMMessageService.name,relations:!!t.V2NIMUserService.name,friends:!!t.V2NIMFriendService.name,friendUsers:!!t.V2NIMUserService.name,msgReceipts:!!t.V2NIMMessageService.name,broadcastMsgs:!!t.V2NIMNotificationService.name,recallMsg:!!t.V2NIMMessageService.name,sessionAck:i,superTeamSessionAck:i,stickTopSessions:i,superTeamRoamingMsgs:!!t.V2NIMTeamService.name,deleteSuperTeamMsg:!!t.V2NIMTeamService.name,deleteSelfMsgs:!!t.V2NIMMessageService.name,sessionHistoryMsgsDelete:!!t.V2NIMMessageService.name,avSignal:!!t.V2NIMSignallingService.name,teams:!!t.V2NIMTeamService.name,superTeams:!!t.V2NIMTeamService.name,myTeamMembers:!!t.V2NIMTeamService.name,mySuperTeamMembers:!!t.V2NIMTeamService.name,donnop:!!t.V2NIMSettingService.name,p2pTeamModifyMessage:!!t.V2NIMMessageService.name,superTeamModifyMessage:!!t.V2NIMMessageService.name},e),this.config}doBasicSync(){return Te(this,void 0,void 0,function*(){var e=Object.keys(this.config).filter(e=>!this.teamKey.includes(e)&&this.config[e]),t=this.genSyncParams(e);this.logger.log("V2Sync:basic",t);var i=(yield this.core.clientSocket.sendCmd("v2NIMSync",{tag:t})).content.timetag;this.setTimetags(i,e.filter(e=>"broadcastMsgs"!==e)),yield this.delaySyncDone(),yield this.handleImmediate(),this.core.logger.log("sync::basic sync complete in",i)})}doTeamSync(){return Te(this,void 0,void 0,function*(){var e=this.teamKey.filter(e=>this.config[e]);if(0!==e.length){var t=this.genSyncParams(e);this.core.eventBus.emit("V2NIMTeamService/onSyncStarted"),this.logger.log("V2Sync:team",t);var i=null;try{i=yield this.core.clientSocket.sendCmd("v2NIMSync",{tag:t})}catch(e){throw this.core.eventBus.emit("V2NIMTeamService/onSyncFailed",e),e}this.core.eventBus.emit("V2NIMTeamService/onSyncFinished");var r=i.content.timetag;this.setTimetags(r,this.teamKey),this.core.logger.log("sync::team sync complete in",r)}})}doQchatSync(){return Te(this,void 0,void 0,function*(){var e=yield this.core.clientSocket.sendCmd("v2QChatSync",{tag:{systemNotification:0}});this.core.logger.log("sync::qchat sync complete in",e.content.timetag)})}doSync(){return Te(this,void 0,void 0,function*(){var e=Ve(this.core,"V2NIMLoginService.authenticator.loginClientOfThisConnection.loginType");if(void 0!==e){if(this.logger.log(`sync::doSync:type ${e}`),this.core.V2NIMLoginService.dataSync.switchDataSync({type:1,state:2,subType:"mainSync"}),1===e)try{yield this.doBasicSync(),yield this.doTeamSync()}catch(e){return void this.doSyncComplete(e)}else if(2===e)try{yield this.doQchatSync()}catch(e){return void this.doSyncComplete(e)}else{if(3!==e)return;try{yield this.doBasicSync(),yield this.doTeamSync(),yield this.doQchatSync()}catch(e){return void this.doSyncComplete(e)}}this.doSyncComplete()}else this.logger.warn("sync::doSync: no loginType, stop sync")})}doSyncComplete(e){e&&this.core.logger.log("sync::doSync complete but got error",e),this.core.V2NIMLoginService.dataSync.switchDataSync({type:1,state:3,error:e,subType:"mainSync"})}initEventListeners(){this.core.eventBus.on("V2NIMLoginService/loginLifeCycleLoginSucc",()=>{this.doSync()})}genSyncParams(e){return e.reduce((e,t)=>{var i=t;return e[i]=this.timetags[i]||0,e},{})}setTimetags(e,t){t.forEach(t=>{this.timetags[t]=e})}handleImmediate(){return this.core.session&&this.core.session.onSyncDone&&this.core.session.onSyncDone(),Promise.resolve()}delaySyncDone(){var{hostEnvEnum:e}=Oe.getSystemInfo();return 102===e?(this.core.logger.log("sync: emit ALIAPP sycnHandler, handle later"),new Promise(e=>{setTimeout(()=>{e()},100)})):Promise.resolve()}},"V2NIMSyncService"),Ne(Oe,{setLogger:_i,platform:"WXAPP",localStorage:Oi,request:Ri,WebSocket:ki,uploadFile:Ci,getFileUploadInformation:Ai,getSystemInfo:bi,net:Ei(wx),powerMonitor:new Ti(wx),logStorage:Ni}),Fo.registerService(class extends ii{constructor(e,t={}){super("V2NIMMessageService",e),this.customAttachmentParsers=[],this.config={compatibleWithV1:!0},this.filterFn=void 0,this.core._registerDep(Li,"V2NIMConversationIdUtil"),this.core._registerDep(ms,"V2NIMMessageCreator"),this.core._registerDep(gs,"V2NIMMessageAttachmentCreator"),this.core._registerDep(vs,"V2NIMClientAntispamUtil"),this.receiptUtil=new cr(this.core,this),this.fileUtil=new Rr(this.core),this.sendUtil=new _s(this.core,this),this.modifyUtil=new Is(this.core,this),this.deleteUtil=new ys(this.core,this),this.aiUtil=new Es(this.core,this),this.model=new Vi,this.event=new Ts(this.core,this),this.handler=new Ms(this.core,this),"v2"===this.core.options.apiVersion&&(mt({cmdMap:kr,cmdConfig:Ur}),this.setOptions(t),this.setListener())}setOptions(e){var t;(null===(t=this.core.msg)||void 0===t?void 0:t.name)?this.config.compatibleWithV1=!0:this.config.compatibleWithV1=!1,this.config=Object.assign(this.config,e)}setListener(){this.event.setListener()}reset(){this.model.reset(),this.receiptUtil.reset()}emit(e,...t){return this.event.beforeEmit(e,...t),super.emit(e,...t)}checkExtendUtil(){var e;if(!(null===(e=this.core.V2NIMMessageExtendUtil)||void 0===e?void 0:e.name))throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"V2NIMMessageLogUtil is not registered"}})}checkLogUtil(){var e;if(!(null===(e=this.core.V2NIMMessageLogUtil)||void 0===e?void 0:e.name))throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"V2NIMMessageExtendUtil is not registered"}})}getMessageList(e){return Te(this,void 0,void 0,function*(){this.checkV2(),this.checkLogUtil();var t=yield this.core.V2NIMMessageLogUtil.getMessageList(e);return t=this._filterMessageByClearTime(e.conversationId,t),this._filterMessagesByFn(t)})}getMessageListEx(e){return Te(this,void 0,void 0,function*(){this.checkV2(),this.checkLogUtil();var t=yield this.core.V2NIMMessageLogUtil.getMessageList(e);return t=this._filterMessageByClearTime(e.conversationId,t),{messages:this._filterMessagesByFn(t),anchorMessage:t.length>0?t[t.length-1]:null}})}getMessageListByRefers(e){return this.checkV2(),this.checkLogUtil(),this.core.V2NIMMessageLogUtil.getMessageListByRefers(e)}clearHistoryMessage(e){return this.checkV2(),this.checkLogUtil(),this.core.V2NIMMessageLogUtil.clearHistoryMessage(e)}clearRoamingMessage(e){return this.checkV2(),this.checkLogUtil(),this.core.V2NIMMessageLogUtil.clearRoamingMessage(e)}pinMessage(e,t){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.pinMessage(e,t)}unpinMessage(e,t){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.unpinMessage(e,t)}updatePinMessage(e,t){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.updatePinMessage(e,t)}voiceToText(e){return this.checkV2(),this.checkExtendUtil(),"string"==typeof e.duration&&(e.duration=Number(e.duration)),this.core.V2NIMMessageExtendUtil.voiceToText(e)}getPinnedMessageList(e){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.getPinnedMessageList(e)}addQuickComment(e,t,i,r){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.addQuickComment(e,t,i,r)}removeQuickComment(e,t,i){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.removeQuickComment(e,t,i)}getQuickCommentList(e){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.getQuickCommentList(e)}addCollection(e){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.addCollection(e)}removeCollections(e){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.removeCollections(e)}updateCollectionExtension(e,t){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.updateCollectionExtension(e,t)}getCollectionListByOption(e){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.getCollectionListByOption(e)}getCollectionListExByOption(e){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.getCollectionListExByOption(e)}searchCloudMessages(e){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.searchCloudMessages(e)}searchCloudMessagesEx(e){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.searchCloudMessagesEx(e)}getThreadMessageList(e){return this.checkV2(),this.checkExtendUtil(),this.core.V2NIMMessageExtendUtil.getThreadMessageList(e)}registerCustomAttachmentParser(e){"function"==typeof e&&-1===this.customAttachmentParsers.indexOf(e)&&this.customAttachmentParsers.unshift(e)}unregisterCustomAttachmentParser(e){var t=this.customAttachmentParsers.indexOf(e);t>-1&&this.customAttachmentParsers.splice(t,1)}sendP2PMessageReceipt(e){return this.checkV2(),this.receiptUtil.sendP2PMessageReceipt(e)}isPeerRead(e){return this.checkV2(),this.receiptUtil.isPeerRead(e)}getP2PMessageReceipt(e){return this.checkV2(),this.receiptUtil.getP2PMessageReceipt(e)}getTeamMessageReceipts(e){return this.checkV2(),this.receiptUtil.getTeamMessageReceipts(e)}getTeamMessageReceiptDetail(e){return this.checkV2(),this.receiptUtil.getTeamMessageReceiptDetail(e)}sendTeamMessageReceipts(e){return this.checkV2(),this.receiptUtil.sendTeamMessageReceipts(e)}revokeMessage(e,t){return Te(this,void 0,void 0,function*(){return this.checkV2(),this.deleteUtil.revokeMessage(e,t)})}deleteMessage(e,t){return this.checkV2(),this.deleteUtil.deleteMessage(e,t)}deleteMessages(e,t){return this.checkV2(),this.deleteUtil.deleteMessages(e,t)}cancelMessageAttachmentUpload(e){return this.checkV2(),this.fileUtil.cancelMessageAttachmentUpload(e)}markMsgsAck(e){if(e&&e.length>0){var t=[],i=[];e.forEach(e=>{e.senderId===this.core.account&&e.senderId!==e.receiverId||(1===e.conversationType?t.push(e):2===e.conversationType&&i.push(e))}),t.length>0&&this.core.sendCmd("v2BatchMarkRead",{sid:7,cid:2,ids:t.map(e=>e.messageServerId)}),i.length>0&&this.core.sendCmd("v2BatchMarkRead",{sid:8,cid:3,ids:i.map(e=>e.messageServerId)})}}sendMessage(e,t,i={},r){var s;return Te(this,void 0,void 0,function*(){if(this.checkV2(),_e({message:{type:"object"}},{message:e},"",!0),e.messageClientId=e.messageClientId||De(),e.conversationId&&e.conversationId!==t)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"sendMessage: message.conversationId is not equal to conversationId"}});_e(Gi,{conversationId:t,message:e,params:i},"",!0),ye(this.core.account,t);var n=this.core.V2NIMConversationIdUtil.parseConversationType(t);if((2===n||3===n)&&i.robotConfig&&!i.robotConfig.accountId)throw new me({detail:{reason:"When conversationType is team or superTeam, account is required in robotInfo account is required"}});if(2!==n&&3!==n||!i.targetConfig)i.targetConfig=void 0;else{var o=i.targetConfig.receiverIds;if(3===n&&!1===i.targetConfig.inclusive)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"setting inclusive to false for super teams is not allowed"}});if(0===(o=o.filter(e=>e&&e!==this.core.account)).length)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"receiverIds cannot be empty or only contain yourself"}});i.targetConfig.receiverIds=o}(null===(s=i.aiConfig)||void 0===s?void 0:s.aiStream)&&this.aiUtil.checkAI();var a,c=this.core.timeOrigin.getTimeNode(),{messageBeforeSend:d,clientAntispamResult:l,hiddenParams:h}=this.sendUtil.prepareMessage(e,t,i);this.logger.log(`V2SendMessage start:${d.messageClientId}/${d.createTime};conversation:${t};`,`NTPTime:${this.core.timeOrigin.getNTPTime(c)}`);try{a=yield this.sendUtil.doSendMessage({apiCallingTimeNode:c,messageBeforeSend:d,clientAntispamResult:l,hiddenParams:h,progress:r})}catch(e){throw this.logger.warn(`V2SendMessage end:${d.messageClientId}.`,e instanceof pe?`failed:${e.code}`:"failed"),e}return a.message.senderId===a.message.receiverId&&this.markMsgsAck([a.message]),this.logger.log(`V2SendMessage end:${a.message.messageClientId}/${a.message.messageServerId}/${a.message.createTime}`),a})}replyMessage(e,t,i={},r){return Te(this,void 0,void 0,function*(){if(this.checkV2(),_e({message:{type:"object"}},{message:e},"",!0),e.messageClientId=e.messageClientId||De(),_e(ji,{message:e,replyMessage:t,params:i},"",!0),ye(this.core.account,t.conversationId),(2===e.conversationType||3===e.conversationType)&&i.robotConfig&&!i.robotConfig.accountId)throw new me({detail:{reason:"When conversationType is team or superTeam, account is required in robotInfo account is required"}});var s=this.core.timeOrigin.getTimeNode(),{messageBeforeSend:n,clientAntispamResult:o,hiddenParams:a}=this.sendUtil.prepareMessage(e,t.conversationId,i,t),c=yield this.sendUtil.doSendMessage({apiCallingTimeNode:s,messageBeforeSend:n,clientAntispamResult:o,hiddenParams:a,progress:r});return c.message.senderId===c.message.receiverId&&this.markMsgsAck([c.message]),c})}modifyMessage(e,t){this.checkV2(),this.checkLogin(),_e(rr,e,"message",!0),_e(sr,t,"params",!0),this.modifyUtil.checkIfModify(e,t);var{messageBeforeSend:i,clientAntispamResult:r}=this.modifyUtil.prepareMessage(e,t);return this.modifyUtil.modifyMessage(i,r)}stopAIStreamMessage(e,t){if(this.checkV2(),this.aiUtil.checkAI(),_e(nr,e,"message",!0),_e(or,t,"params",!0),2===t.operationType&&!t.updateContent)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"V2NIMMessage::stopAIStreamMessage updateContent empty"}});return this.aiUtil.stopAIStreamMessage(e,t)}regenAIMessage(e,t){return this.checkV2(),this.aiUtil.checkAI(),_e(nr,e,"message",!0),_e(ar,t,"params",!0),this.aiUtil.regenAIMessage(e,t)}sendMessageFn(e){if(e.msgAckSnapshot){var t=e.msgAckSnapshot,i={conversationId:e.conversationId,messageServerId:e.messageServerId,messageClientId:e.messageClientId,readCount:0,unreadCount:Number(t)};delete e.msgAckSnapshot,this.emit("onReceiveTeamMessageReadReceipts",[i])}e=Mr(e,this.core),this.model.upsertMessages([e]),this.core.eventBus.emit("V2NIMMessageService/sendMessage",e,e.sendingState)}setMessageFilter(e){null!=e?e&&"function"==typeof e.shouldIgnore&&(this.filterFn=e.shouldIgnore):this.filterFn=void 0}_filterMessage(e){if("function"==typeof this.filterFn)try{return!0===this.filterFn(e)}catch(t){return this.logger.error(`V2NIMMessage::triggerMessageFilter ${e.messageClientId} error:`,t),!1}return!1}_filterMessagesByFn(e){return e.filter(e=>!this._filterMessage(e))}_filterMessageByClearTime(e,t){var i=Oe.localStorage.getItem(`nim_${this.core.account}_${e}_clearTime`),r=i?parseInt(i):0;return r>0?t.filter(e=>e.createTime>=r):t}},"V2NIMMessageService"),Fo.registerService(class extends ii{constructor(e){super("V2NIMMessageLogUtil",e),this.clearHistoryMessageFn=e=>{var t=Cr(this.core,e);this.emitClearHistoryMessage([t])},this.core=e,this.service=this.core.V2NIMMessageService,"v2"===this.core.options.apiVersion&&(mt({cmdMap:zs,cmdConfig:Zs}),this.setListener())}setListener(){this.core.eventBus.on("forwardReceive/V2NIMMessageLogService/clearHistoryMessage",this.clearHistoryMessageFn)}getMessageListByRefers(e){return Te(this,void 0,void 0,function*(){if(this.checkV2(),_e(Yi,{messageRefers:e},"",!0),0===e.length)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"getMessageListByRefers: messageRefers cannot be an empty array"}});var t=[],i=e.map(e=>{var i=this.service.model.getMessageById(e.messageClientId);return!i&&e.messageServerId&&"0"!==e.messageServerId&&t.push(e),i}),r=[];if(t.length>0){var s=yield this.core.sendCmd("v2GetMessageListByRefers",{tag:t});r=s.content.msgs}return i.map((t,i)=>{if(t)return t;var s=e[i],n=r.find(e=>e.messageServerId===s.messageServerId);return n?Er(this.core,n):void 0}).filter(e=>void 0!==e&&!this.service._filterMessage(e))})}getMessageList(e){var t;return Te(this,void 0,void 0,function*(){this.checkV2(),_e(Hi,e,"",!0),ye(this.core.account,e.conversationId);var i=this.core.V2NIMConversationIdUtil.parseConversationType(e.conversationId),r=this.core.V2NIMConversationIdUtil.parseConversationTargetId(e.conversationId),s=1===i?"v2GetMessageList":2===i?"v2GetTeamMessageList":"v2GetSuperTeamMessageList",n=e.beginTime||0,o=e.endTime||0;if(0!==n&&0!==o&&n>o)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"getMessageList: beginTime cannot be greater than endTime"}});var a=void 0===e.direction?0:e.direction;if(e.anchorMessage)if(0===a){if(0===o)o=e.anchorMessage.createTime;else if(o!==e.anchorMessage.createTime)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"getMessageList: When providing anchorMessage, when sorting in descending order, endTime does not need to be provided, or endTime should be equal to anchorMessage.createTime"}})}else if(0===n)n=e.anchorMessage.createTime;else if(n!==e.anchorMessage.createTime)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"getMessageList: When providing anchorMessage, when sorting in ascending order, there is no need to provide beginTime, or beginTime should be equal to anchorMessage.createTime"}});var c=null===(t=e.anchorMessage)||void 0===t?void 0:t.messageServerId,d=yield this.core.sendCmd(s,{beginTime:n,endTime:o,lastMsgId:c||0,limit:e.limit||50,direction:a,msgTypes:e.messageTypes?e.messageTypes.slice():[],to:r}),{content:l}=d,h=l.msgs.map(e=>Er(this.core,e));return c&&(h=h.filter(e=>e.messageServerId!==c)),this.getMessageListMonkeyPatch(h,e)})}getMessageListMonkeyPatch(e,t){var i=t.conversationId,r=e,s=r.reduce((e,t)=>(e[t.messageClientId]=!0,e),{}),n=this.service.model.getMessagesByConversationId(i);n=n.sort((e,i)=>1===t.direction?e.createTime-i.createTime:i.createTime-e.createTime);var o=0,a=t.beginTime||0,c=t.endTime||0;t.anchorMessage&&(0===t.direction?c=t.anchorMessage.createTime:a=t.anchorMessage.createTime,o=n.findIndex(e=>{var i;return e.messageClientId===(null===(i=t.anchorMessage)||void 0===i?void 0:i.messageClientId)}),o+=1);for(var d=o;da&&(l.createTime1===t.direction?e.createTime-i.createTime:i.createTime-e.createTime)).slice(0,t.limit||50)}clearHistoryMessage(e){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(Wi,e,"",!0),ye(this.core.account,e.conversationId);var{conversationId:t,deleteRoam:i,onlineSync:r,serverExtension:s}=e,n=this.core.V2NIMConversationIdUtil.parseConversationType(t),o=this.core.V2NIMConversationIdUtil.parseConversationTargetId(t),a={deleteRoam:i,onlineSync:r,serverExtension:s,conversationType:n};1===n?a.receiverId=o:a.teamId=o;var c=this.core.timeOrigin.getNTPTime();e.clearMode=e.clearMode||0,0===e.clearMode&&(c=(yield this.core.sendCmd("v2ClearHistoryMessage",{tag:a})).content.timetag),2===e.clearMode&&Oe.localStorage.setItem(`nim_${this.core.account}_${t}_clearTime`,c.toString()),this.core.eventBus.emit("forwardSend/V2NIMMessageLogService/clearHistoryMessage",Object.assign(Object.assign({},a),{deleteTime:c})),this.emitClearHistoryMessage([{deleteTime:c,serverExtension:s,conversationId:t}])})}clearRoamingMessage(e){return Te(this,void 0,void 0,function*(){this.checkV2(),_e({conversationIds:{type:"array",itemType:"string",min:1}},{conversationIds:e},void 0,!0);var t=[];try{t=e.map(e=>{var t=this.core.V2NIMConversationIdUtil.parseConversationTargetId(e);return function(e,t){return`${Ss[e]}|${t}`}(this.core.V2NIMConversationIdUtil.parseConversationType(e),t)})}catch(t){throw this.logger.error(`V2NIMMessage::clearRoamingMessage with ${e}`,t),new pe({code:de.V2NIM_ERROR_CODE_PARAMETER_ERROR,detail:{reason:"Failed to create session",rawData:`${e}`}})}yield this.core.sendCmd("v2ClearRoamingMessage",{conversationIds:t})})}syncClearHistoryMessageHandler(e){var t=e.content.data.map(e=>Cr(this.core,e));this.emitClearHistoryMessage(t)}onClearHistoryMessageHandler(e){var t=Cr(this.core,e.content.data);this.emitClearHistoryMessage([t])}emitClearHistoryMessage(e){e.forEach(e=>{this.service.model.deleteMessages(e.conversationId,e.deleteTime),this.core.eventBus.emit("V2NIMSync/updateTimetag",{sessionHistoryMsgsDelete:e.deleteTime})}),this.core.eventBus.emit("V2NIMMessageLogUtil/onClearHistoryNotifications",e),this.service.emit("onClearHistoryNotifications",e)}},"V2NIMMessageLogUtil"),Fo.registerService(us,"V2NIMStorageService"),Fo.registerService(class extends ii{constructor(e,t={}){super("V2NIMConversationService",e),this.config={},this.model=new Ls,this.versionCache=new Ps(this.core,this),this.unread=new js(this.core,this),this.compute=new Ys(this.core,this),this.event=new Ks(this.core,this),this.handler=new qs(this.core,this),this.core._registerDep(Li,"V2NIMConversationIdUtil"),"v2"===this.core.options.apiVersion&&!0===this.core.options.enableV2CloudConversation&&(mt({cmdMap:ws,cmdConfig:Bs}),this.setOptions(t),this.setListener())}setOptions(e){this.config=Object.assign(this.config,e)}setListener(){this.event.setListener()}reset(){this.versionCache.reset(),this.model.reset(),this.unread.reset()}emit(e,...t){return this.event.beforeEmit(e,...t),super.emit(e,...t)}checkEnable(){if(!0!==this.core.options.enableV2CloudConversation)throw new pe({code:de.V2NIM_ERROR_CODE_MISUSE,detail:{reason:"V2CloudConversation is not enabled"}})}getConversationList(e,t){this.checkEnable(),this.checkV2(),_e({offset:{type:"number",min:0}},{offset:e},"",!0),_e({limit:{type:"number",min:1}},{limit:t},"",!0),this.core.V2NIMLoginService.checkIllegalState();var i=this.model.getByOption(e,t,{});return i.conversationList=this.compute.computeConvs(i.conversationList),Promise.resolve(i)}getConversationListByOption(e,t,i){this.checkEnable(),this.checkV2(),_e({offset:{type:"number",min:0}},{offset:e},"",!0),_e({limit:{type:"number",min:1}},{limit:t},"",!0),_e({option:{type:"object",required:!0,rules:{conversationTypes:{type:"array",itemType:"number",required:!1},onlyUnread:{type:"boolean",required:!1},conversationGroupIds:{type:"array",itemType:"string",required:!1}}}},{option:i},"",!0),this.core.V2NIMLoginService.checkIllegalState();var r=this.model.getByOption(e,t,i);return r.conversationList=this.compute.computeConvs(r.conversationList),Promise.resolve(r)}getConversation(e){return Te(this,void 0,void 0,function*(){this.checkEnable(),this.checkV2(),ye(this.core.account,e);var t=this.model.getById(e);if(t)return this.compute.computeConv(t);throw new pe({code:de.V2NIM_ERROR_CODE_RESOURCE_NOT_EXIST})})}getConversationListByIds(e){return Te(this,void 0,void 0,function*(){this.checkEnable(),this.checkV2(),_e({conversationIds:{type:"array",itemType:"string",min:1}},{conversationIds:e},"",!0),this.core.V2NIMLoginService.checkIllegalState();var t=e.map(e=>this.model.getById(e)).filter(e=>!!e);return this.compute.computeConvs(t)})}createConversation(e){return Te(this,void 0,void 0,function*(){this.checkEnable(),this.checkV2(),ye(this.core.account,e);var t=Ve(yield this.core.sendCmd("v2ConversationCreate",{tag:{conversationId:e}}),"content.data"),i=Rs(this.core,t);this.versionCache.compareAndUpdateModel([i]);var r=this.model.getById(e);if(r)return this.compute.computeConv(r);throw new pe({code:de.V2NIM_ERROR_CODE_RESOURCE_NOT_EXIST})})}deleteConversation(e,t){return Te(this,void 0,void 0,function*(){this.checkEnable(),this.checkV2(),ye(this.core.account,e),_e({clearMessage:{type:"boolean",required:!1}},{clearMessage:t},"",!0);try{yield this.core.sendCmd("v2ConversationDelete",{tag:{conversationId:e,clearMessage:Number(t||!1)}})}catch(t){this.logger.warn(`V2NIMConversationService:deleteConversation: delete conversation failed: ${e}`)}this.model.getById(e)&&(t&&this.core.eventBus.emit("V2NIMConversationService/deleteConversation",[e]),this.versionCache.compareAndDeleteModel([e]))})}deleteConversationListByIds(e,t){return Te(this,void 0,void 0,function*(){this.checkEnable(),this.checkV2(),_e({conversationIds:{type:"array",itemType:"string",min:1}},{conversationIds:e},"",!0),_e({clearMessage:{type:"boolean",required:!1}},{clearMessage:t},"",!0);var i=Hs(Ve(yield this.core.sendCmd("v2ConversationsDelete",{tag:{conversationIds:JSON.stringify(e),clearMessage:Number(t||!1)}}),"content.info.failedMap")).filter(e=>e.error.code!==de.V2NIM_ERROR_CODE_CONVERSATION_NOT_EXIST||!this.model.getById(e.conversationId));return i.length=n?(this.logger.log(`V2Conv::markConversationRead currentReadTime >= readTime ${e},${s},${n}`),s):(3===r?yield this.core.sendCmd("v2MarkSuperTeamReadTime",{timetag:n,to:i}):yield this.core.sendCmd("v2MarkConversationReadTime",{scene:1===r?0:2===r?1:2,timetag:n,to:i}),this.model.updateReadTime(e,n),n)})}getConversationReadTime(e){return Te(this,void 0,void 0,function*(){return this.checkEnable(),this.checkV2(),ye(this.core.account,e),this.model.getReadTime(e)})}subscribeUnreadCountByFilter(e){var t;this.checkEnable(),this.checkV2(),this.checkLogin(),this.valiteFilter(e),0===(null===(t=e.conversationTypes)||void 0===t?void 0:t.length)&&delete e.conversationTypes,this.unread.addFilter(e)}unsubscribeUnreadCountByFilter(e){var t;this.checkEnable(),this.checkV2(),this.checkLogin(),this.valiteFilter(e),0===(null===(t=e.conversationTypes)||void 0===t?void 0:t.length)&&delete e.conversationTypes,this.unread.deleteFilter(e)}valiteFilter(e){if(_e({filter:{type:"object",required:!0,rules:{conversationTypes:{type:"array",itemType:"number",required:!1},conversationGroupId:{type:"string",allowEmpty:!1,required:!1},ignoreMuted:{type:"boolean",required:!1}}}},{filter:e},"",!0),void 0===e.conversationTypes&&void 0===e.conversationGroupId&&!0!==e.ignoreMuted)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"Filter cannot be empty"}})}triggerConversationChanged(e){e=this.compute.computeConvs(e),(e=JSON.parse(JSON.stringify(e))).forEach(e=>{e.lastMessage||(e.lastMessage=void 0),delete e.lastMessageState}),this.emit("onConversationChanged",e)}triggerConversationCreated(e){e=this.compute.computeConv(e),delete(e=JSON.parse(JSON.stringify(e))).lastMessageState,this.emit("onConversationCreated",e)}},"V2NIMConversationService"),Fo.registerService(class extends ii{constructor(e){super("V2NIMTeamService",e),this.core._registerDep(Li,"V2NIMConversationIdUtil"),this.model=new kn,this.memberModel=new Ln,this.notificationModel=new Pn,this.notification=new Vn(e,this),this.event=new Dn(e,this),this.handler=new wn(e,this),"v2"===this.core.options.apiVersion&&(mt({cmdMap:dr,cmdConfig:vr}),this.setListener())}setListener(){this.event.setListener()}reset(){this.model.reset(),this.memberModel.reset(),this.notificationModel.reset()}emit(e,...t){return this.event.beforeEmit(e,...t),super.emit(e,...t)}createTeam(e,t,i,r){return Te(this,void 0,void 0,function*(){this.checkV2(),_e({createTeamParams:cn},{createTeamParams:e},"",!0),_e({inviteeAccountIds:Object.assign(Object.assign({},dn),{min:0,required:!1})},{inviteeAccountIds:t},"",!0),_e({antispamConfig:un},{antispamConfig:r},"",!0);var s=2===e.teamType?"v2SuperTeamCreate":"v2TeamCreate",n=yield this.core.sendCmd(s,{team:e,inviteeAccountIds:t||[],postscript:i||"",antispamConfig:r}),o=n.content.team;return this.model.upsert(o),this.getTeamMemberListByIds(o.teamId,o.teamType,[this.core.account]).catch(e=>{this.core.logger.error("Get Member error after createTeam",e)}),this.emit("onTeamCreated",o),{team:o,failedList:n.content.failedList}})}updateTeamInfo(e,t,i,r){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e(In,{updateTeamInfoParams:i},"",!0),_e({antispamConfig:un},{antispamConfig:r},"",!0);var s=Object.assign({teamId:e,teamType:t},i),n=2===t?"v2SuperTeamUpdateInfo":"v2TeamUpdateInfo";yield this.core.sendCmd(n,{team:s,antispamConfig:r}),this.model.upsert(s)})}leaveTeam(e,t){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0);var i=2===t?"v2SuperTeamLeave":"v2TeamLeave";yield this.core.sendCmd(i,{teamId:e}),this.model.deleteById(e,t)})}getTeamInfo(e,t){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0);var i=2===t?"v2SuperTeamGetInfo":"v2TeamGetInfo",r=this.model.getById(e,t,!1);if(r)return r;var s=(yield this.core.sendCmd(i,{teamId:e})).content.team;return this.model.upsert(s),s})}getJoinedTeamList(e){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(fn,{teamTypes:e},"",!0),this.core.V2NIMLoginService.checkIllegalState(),e&&0!==e.length||(e=[1,2]);var t=[];return e.forEach(e=>{t=t.concat(this.model.getAll(e))}),t.sort((e,t)=>e.createTime-t.createTime)})}getJoinedTeamCount(e){this.checkV2(),_e(fn,{teamTypes:e},"",!0),this.core.V2NIMLoginService.checkIllegalState(),e&&0!==e.length||(e=[1,2]);var t=0;return e.forEach(e=>{t+=this.model.count(e)}),t}getJoinedTeamMembers(e){this.checkV2(),_e(fn,{teamTypes:e},"",!0),this.core.V2NIMLoginService.checkIllegalState(),e&&0!==e.length||(e=[1,2]);var t=[];return e.forEach(e=>{var i=this.memberModel.chooseList(e).filter(e=>e.accountId===this.core.account);t=t.concat(i)}),Promise.resolve(t)}getTeamInfoByIds(e,t){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(gn,{teamIds:e},"",!0),_e(vn,{teamType:t},"",!0);var i=2===t?"v2SuperTeamGetByIds":"v2TeamGetByIds",r=e.map(e=>this.model.getById(e,t,!1)),s=e.filter((e,t)=>!r[t]);if(0===s.length)return r;var n=(yield this.core.sendCmd(i,{teamIds:s})).content.teams;return r.map((t,i)=>{if(t)return t;var r=e[i],s=n.find(e=>e.teamId===r);return s&&this.model.upsert(s),s}).filter(e=>!!e)})}dismissTeam(e,t){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0);var i=2===t?"v2SuperTeamDismiss":"v2TeamDismiss";yield this.core.sendCmd(i,{teamId:e})})}inviteMember(e,t,i,r){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e({inviteeAccountIds:dn},{inviteeAccountIds:i},"",!0),_e({postscript:Object.assign(Object.assign({},hn),{required:!1})},{postscript:r},"",!0);var s=2===t?"v2SuperTeamInviteMembers":"v2TeamInviteMembers";return(yield this.core.sendCmd(s,{teamId:e,accounts:i,ps:r||""})).content.abortedAccidList})}inviteMemberEx(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e(_n,{inviteeParams:i},"",!0);var r=2===t?"v2SuperTeamInviteMembers":"v2TeamInviteMembers";return(yield this.core.sendCmd(r,{teamId:e,accounts:i.inviteeAccountIds,ps:i.postscript||"",attach:i.serverExtension})).content.abortedAccidList})}acceptInvitation(e){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(Sn,e,"invitationInfo",!0),_e(Cn,e,"invitationInfo",!0);var{teamType:t,teamId:i,operatorAccountId:r}=e,s=2===t?"v2SuperTeamAcceptInvitation":"v2TeamAcceptInvitation";try{var n=yield this.core.sendCmd(s,{teamId:i,from:r});return this.notification.updateTeamActionStatus(e,1),n.content.team}catch(t){var o=t;throw this.notification.checkIfExpired(o.code)&&this.notification.updateTeamActionStatus(e,3),t}})}rejectInvitation(e,t){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(Sn,e,"invitationInfo",!0),_e(Cn,e,"invitationInfo",!0),_e({postscript:Object.assign(Object.assign({},hn),{required:!1})},{postscript:t},"",!0);var{teamType:i,teamId:r,operatorAccountId:s}=e,n=2===i?"v2SuperTeamRejectInvite":"v2TeamRejectInvite";try{yield this.core.sendCmd(n,{teamId:r,from:s,ps:t||""}),this.notification.updateTeamActionStatus(e,2)}catch(t){var o=t;throw this.notification.checkIfExpired(o.code)&&this.notification.updateTeamActionStatus(e,3),t}})}kickMember(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e({memberAccountIds:dn},{memberAccountIds:i},"",!0);var r=2===t?"v2SuperTeamKickMembers":"v2TeamKickMembers";yield this.core.sendCmd(r,{teamId:e,accounts:i})})}applyJoinTeam(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0);var r=2===t?"v2SuperTeamApplyToJoin":"v2TeamApplyToJoin",s=yield this.core.sendCmd(r,{teamId:e,ps:i||""}),n=s.content.team,o=s.content.isInTeam;return n.isValidTeam=!!n.isValidTeam&&!!o,n})}acceptJoinApplication(e){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(Sn,e,"applicationInfo",!0),_e(An,e,"applicationInfo",!0);var{teamType:t,teamId:i,operatorAccountId:r}=e,s=2===t?"v2SuperTeamAcceptJoinApplication":"v2TeamAcceptJoinApplication";try{yield this.core.sendCmd(s,{teamId:i,from:r}),this.notification.updateTeamActionStatus(e,1)}catch(t){var n=t;throw this.notification.checkIfExpired(n.code)&&this.notification.updateTeamActionStatus(e,3),t}})}rejectJoinApplication(e,t){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(Sn,e,"applicationInfo",!0),_e(An,e,"applicationInfo",!0),_e({postscript:Object.assign(Object.assign({},hn),{required:!1})},{postscript:t},"",!0);var{teamType:i,teamId:r,operatorAccountId:s}=e,n=2===i?"v2SuperTeamRejectJoinApplication":"v2TeamRejectJoinApplication";try{yield this.core.sendCmd(n,{teamId:r,from:s,ps:t||""}),this.notification.updateTeamActionStatus(e,2)}catch(t){var o=t;throw this.notification.checkIfExpired(o.code)&&this.notification.updateTeamActionStatus(e,3),t}})}updateTeamMemberRole(e,t,i,r){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e({memberAccountIds:dn},{memberAccountIds:i},"",!0),_e({memberRole:yn},{memberRole:r},"",!0);var s=2===r?"AddManagers":"RemoveManagers";s=2===t?`v2SuperTeam${s}`:`v2Team${s}`,yield this.core.sendCmd(s,{teamId:e,accounts:Zt(i)})})}transferTeamOwner(e,t,i,r){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e({accountId:pn},{accountId:i},"",!0),_e({leave:{type:"boolean",required:!1}},{leave:r},"",!0);var s=this.model.getById(e,t);if(s&&s.ownerAccountId===i)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"Transfer to self is not allowed"}});var n=2===t?"v2SuperTeamTransferOwner":"v2TeamTransferOwner";yield this.core.sendCmd(n,{teamId:e,account:i,leave:r||!1})})}updateSelfTeamMemberInfo(e,t,i){return Te(this,void 0,void 0,function*(){if(this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e(En,{memberInfoParams:i},"",!0),void 0===i.teamNick&&void 0===i.serverExtension)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER});var r=2===t?"v2SuperTeamUpdateSelfMemberInfo":"v2TeamUpdateSelfMemberInfo",s=Object.assign(Object.assign({},i),{teamId:e,accountId:this.core.account}),n=i.antispamConfig?{teamMember:s,specialFollowUpdate:{},antispam:i.antispamConfig}:{teamMember:s};yield this.core.sendCmd(r,n),yield this.notification.updateTeamMemberRole(e,t,[this.core.account],s);var o=this.memberModel.getById(e,t,this.core.account);if(this.core.V2NIMSettingService.name&&this.core.V2NIMConversationIdUtil.name){var a=1===t?this.core.V2NIMConversationIdUtil.teamConversationId(e):this.core.V2NIMConversationIdUtil.superTeamConversationId(e),c=this.core.V2NIMSettingService.getConversationMuteStatus(a);this.core.eventBus.emit("V2NIMSettingService/setMute",a,c)}this.core.eventBus.emit("forwardSend/V2NIMTeamService/updateSelfTeamMemberInfo",o)})}updateTeamMemberNick(e,t,i,r){return Te(this,void 0,void 0,function*(){if(this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e({accountId:pn},{accountId:i},"",!0),_e({nick:hn},{nick:r},"",!0),i===this.core.account)return this.updateSelfTeamMemberInfo(e,t,{teamNick:r});var s=2===t?"v2SuperTeamUpdateMember":"v2TeamUpdateMember";yield this.core.sendCmd(s,{teamMember:{teamNick:r,teamId:e,accountId:i}})})}updateTeamMemberNickEx(e,t,i){return Te(this,void 0,void 0,function*(){if(this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e(bn,i,"",!0),i.accountId===this.core.account)return this.updateSelfTeamMemberInfo(e,t,{teamNick:i.teamNick,antispamConfig:i.antispamConfig});var r=2===t?"v2SuperTeamUpdateMember":"v2TeamUpdateMember";yield this.core.sendCmd(r,{teamMember:{teamNick:i.teamNick,teamId:e,accountId:i.accountId},antispam:i.antispamConfig})})}setTeamChatBannedMode(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e(Mn,{chatBannedMode:i},"",!0);var r=2===t?"v2SuperTeamSetChatBannedMode":"v2TeamSetChatBannedMode";yield this.core.sendCmd(r,{teamId:e,chatBannedMode:i}),this.model.upsert({teamId:e,teamType:t,chatBannedMode:i})})}setTeamMemberChatBannedStatus(e,t,i,r){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e({accountId:pn},{accountId:i},"",!0),_e({chatBanned:ln},{chatBanned:r},"",!0);var s=2===t?"v2SuperTeamMemberSetChatBannedStatus":"v2TeamMemberSetChatBannedStatus";yield this.core.sendCmd(s,{teamId:e,accountId:2===t?[i]:i,chatBanned:r?1:0})})}getTeamMemberList(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e(Tn,{queryOption:i},"",!0);var r=void 0===i.direction?0:i.direction;r=0===r?1:0;var s=yield this.core.sendCmd("v2TeamMemberGetList",{tag:Object.assign(Object.assign({teamId:e,teamType:t,onlyChatBanned:!1,nextToken:"",limit:100},i),{direction:r})}),n=s.content.datas,o=Ve(s,"raw.r.0");return 2===t&&o&&o.map&&(n=o.map(e=>ut(e,gt(mr)))),{nextToken:s.content.pageInfo.nextToken||"",finished:!+s.content.pageInfo.hasMore,memberList:yr(n,t)}})}getTeamMemberListByIds(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e({accountIds:dn},{accountIds:i},"",!0);for(var r=2===t?"v2SuperTeamMemberGetListByIds":"v2TeamMemberGetListByIds",s=i.map(t=>`${e}|${t}`),n=[],o=0;othis.memberModel.upsert(e))}return n})}getTeamMemberInvitor(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(mn,{teamId:e},"",!0),_e(vn,{teamType:t},"",!0),_e({accountIds:dn},{accountIds:i},"",!0);var r=2===t?"v2SuperTeamGetMemberInvitor":"v2TeamGetMemberInvitor";return(yield this.core.sendCmd(r,{teamId:e,accounts:i})).content.accountsMap})}searchTeamByKeyword(e){return Te(this,void 0,void 0,function*(){return this.checkV2(),this.checkLogin(),_e({keyword:pn},{keyword:e},"",!0),this.model.searchTeamByKeyword(e)})}addTeamMembersFollow(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(Rn,{teamId:e,teamType:t,accountIds:i},"",!0);var r=2===t?"v2SuperTeamUpdateSelfMemberInfo":"v2TeamUpdateSelfMemberInfo",[s]=yield this.getTeamMemberListByIds(e,t,[this.core.account]),n=(yield this.core.sendCmd(r,{teamMember:{teamId:e},specialFollowUpdate:{accountIds:i,operation:1}})).content.data;Object.keys(n).length>0&&(Object.assign(s,n),this.emit("onTeamMemberInfoUpdated",[s]),this.memberModel.upsert(s))})}removeTeamMembersFollow(e,t,i){return Te(this,void 0,void 0,function*(){this.checkV2(),_e(Rn,{teamId:e,teamType:t,accountIds:i},"",!0);var[r]=yield this.getTeamMemberListByIds(e,t,[this.core.account]),s=2===t?"v2SuperTeamUpdateSelfMemberInfo":"v2TeamUpdateSelfMemberInfo",n=(yield this.core.sendCmd(s,{teamMember:{teamId:e},specialFollowUpdate:{accountIds:i,operation:0}})).content.data;Object.keys(n).length>0&&(Object.assign(r,n),this.emit("onTeamMemberInfoUpdated",[r]),this.memberModel.upsert(r))})}getTeamJoinActionInfoList(e){return this.checkV2(),_e(On,e,"option",!0),this.core.V2NIMLoginService.checkIllegalState(),Promise.resolve(this.notificationModel.getByOption(e))}clearAllTeamJoinActionInfo(){return Te(this,void 0,void 0,function*(){this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),this.notificationModel.reset()})}deleteTeamJoinActionInfo(e){return Te(this,void 0,void 0,function*(){this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),_e(Sn,e,"",!0),_e(Nn,e,"",!0),_e({timestamp:{type:"number",min:1}},e,"",!0),this.notificationModel.delete(e)})}setTeamJoinActionInfoRead(e){return Te(this,void 0,void 0,function*(){this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),e?(_e(Sn,e,"",!0),_e(Nn,e,"",!0),this.notificationModel.setRead(e)):this.notificationModel.setAllRead()})}getTeamJoinActionInfoUnreadCount(){return Te(this,void 0,void 0,function*(){return this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),this.notificationModel.getUnreadCount()})}},"V2NIMTeamService"),Fo.registerService(Yn,"V2NIMUserService"),Fo.registerService(class extends ii{constructor(e){super("V2NIMFriendService",e),this.notification=new io(this.core,this),this.model=new ro,this.notificationModel=new so,this.core._registerDep(Yn,"V2NIMUserService"),"v2"===this.core.options.apiVersion&&(mt({cmdMap:Kn,cmdConfig:Jn}),this.setListener())}reset(){this.model.reset()}setListener(){this.core.eventBus.on("V2NIMFriendService/sysNotification",this.notification.processSysNotification.bind(this.notification)),this.core.eventBus.on("forwardReceive/V2NIMFriendService/addFriend",this.handleAddFriend.bind(this)),this.core.eventBus.on("forwardReceive/V2NIMFriendService/deleteFriend",this.handleDeleteFriend.bind(this)),this.core.eventBus.on("forwardReceive/V2NIMFriendService/setFriendInfo",this.handleSetFriendInfo.bind(this)),this.core.eventBus.on("forwardReceive/V2NIMFriendService/acceptAddApplication",this.handlePassFriendApply.bind(this)),this.core.eventBus.on("forwardReceive/V2NIMFriendService/rejectAddApplication",this.handleRejectFriendApply.bind(this))}emit(e,...t){var i=`${this.name}::emit ${e.toString()}`;if("onFriendAdded"===e||"onFriendInfoChanged"===e){var r=t[0];this.logger.log(`${i}`,`${r.accountId};updateTime:${r.updateTime}`)}else this.logger.log(`${i}`,...t);return super.emit(e,...t)}get hasUserService(){var e;return!!(null===(e=this.core.V2NIMUserService)||void 0===e?void 0:e.name)}addFriend(e,t){return Te(this,void 0,void 0,function*(){if(this.checkV2(),e===this.core.account)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"Cannot add yourself"}});_e(zn,{accountId:e,params:t},"",!0),yield this.core.sendCmd("v2AddFriend",{accountId:e,verifyType:t.addMode,postscript:t.postscript||""}),1===t.addMode&&(yield this.handleAddFriend(e),this.notificationModel.updateFriendAddApplicationStatus(e,4,this.core.account))})}deleteFriend(e,t){return Te(this,void 0,void 0,function*(){if(this.checkV2(),e===this.core.account)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"Cannot delete yourself"}});_e(Xn,{accountId:e,params:t},"",!0),yield this.core.sendCmd("v2DeleteFriend",{accountId:e,params:t}),t.deleteAlias&&this.model.upsertFriend(e,{alias:""}),this.handleDeleteFriend(e)})}acceptAddApplication(e){return Te(this,void 0,void 0,function*(){this.checkV2(),eo(e,this.core.account);try{yield this.core.sendCmd("v2AddFriend",{accountId:e.applicantAccountId,verifyType:3,postscript:""}),this.handlePassFriendApply(e.applicantAccountId)}catch(t){throw this.handlePassFriendApply(e.applicantAccountId,t),t}})}rejectAddApplication(e,t){return Te(this,void 0,void 0,function*(){this.checkV2(),eo(e,this.core.account);try{yield this.core.sendCmd("v2AddFriend",{accountId:e.applicantAccountId,verifyType:4,postscript:t||""}),this.handleRejectFriendApply({applicantAccountId:e.applicantAccountId,recipientAccountId:e.recipientAccountId,operatorAccountId:this.core.account,postscript:t||"",timestamp:this.core.timeOrigin.getNTPTime(),read:!1,status:2})}catch(i){throw this.handleRejectFriendApply({applicantAccountId:e.applicantAccountId,recipientAccountId:e.recipientAccountId,operatorAccountId:this.core.account,postscript:t||"",timestamp:this.core.timeOrigin.getNTPTime(),read:!1,status:3},i),i}})}setFriendInfo(e,t){return Te(this,void 0,void 0,function*(){if(this.checkV2(),_e(Qn,{accountId:e,params:t},"",!0),e===this.core.account)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"Cannot set yourself"}});yield this.core.sendCmd("v2SetFriendInfo",{tag:Object.assign({accountId:e},t)}),this.handleSetFriendInfo(e,t)})}getFriendList(){return Te(this,void 0,void 0,function*(){return this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),this.computedFields(this.model.getFriendList())})}getFriendByIds(e){return Te(this,void 0,void 0,function*(){return this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),_e({accountIds:{type:"array",itemType:"string",required:!0,min:1}},{accountIds:e},"",!0),this.computedFields(this.model.getFriendByIds(e))})}checkFriend(e){return Te(this,void 0,void 0,function*(){this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),_e({accountIds:{type:"array",itemType:"string",required:!0,min:1}},{accountIds:e},"",!0);var t={};return e.forEach(e=>{t[e]=!!this.model.getFriend(e)}),t})}getAddApplicationList(e){return Te(this,void 0,void 0,function*(){return this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),_e(to,e,"",!0),this.notificationModel.getAddApplicationList(e)})}setAddApplicationRead(){return Te(this,void 0,void 0,function*(){this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),this.notificationModel.setAllApplicationRead()})}setAddApplicationReadEx(e){return Te(this,void 0,void 0,function*(){this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),e?(eo(e,this.core.account),this.notificationModel.setApplicationRead(e)):this.notificationModel.setAllApplicationRead()})}getAddApplicationUnreadCount(){return Te(this,void 0,void 0,function*(){return this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),this.notificationModel.getAddApplicationUnreadCount()})}clearAllAddApplication(){return Te(this,void 0,void 0,function*(){this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),this.notificationModel.clearApplicationList()})}deleteAddApplication(e){return Te(this,void 0,void 0,function*(){this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),eo(e,this.core.account),this.notificationModel.deleteApplication(e)})}searchFriendByOption(e){return Te(this,void 0,void 0,function*(){if(this.checkV2(),this.core.V2NIMLoginService.checkIllegalState(),_e({keyword:{type:"string",allowEmpty:!1},searchAccountId:{type:"boolean",required:!1}},e,"",!0),void 0!==e.searchAlias&&!e.searchAlias&&!e.searchAccountId)throw new pe({code:de.V2NIM_ERROR_CODE_INVALID_PARAMETER,detail:{reason:"searchAlias and searchAccountId cannot be false at the same time"}});return this.computedFields(this.model.getFriendListBySearchOption(e))})}v2OnAddFriendHandler(e){var{accountId:t,verifyType:i,postscript:r}=e.content;if(1===i)this.handleAddFriend(t),this.notificationModel.updateFriendAddApplicationStatus(t,4,this.core.account);else if(2===i){var s={applicantAccountId:this.core.account,recipientAccountId:t,operatorAccountId:this.core.account,postscript:r,timestamp:this.core.timeOrigin.getNTPTime(),status:0,read:!1};this.handleApplyFriend(s)}else if(3===i)this.handlePassFriendApply(t);else if(4===i){var n={applicantAccountId:t,recipientAccountId:this.core.account,operatorAccountId:this.core.account,postscript:r,timestamp:this.core.timeOrigin.getNTPTime(),status:2,read:!1};this.handleRejectFriendApply(n)}}v2OnDeleteFriendHandler(e){var{accountId:t}=e.content;this.handleDeleteFriend(t)}v2OnUpdateFriendInfoHandler(e){var{data:t}=e.content,i=this.model.upsertFriend(t.accountId,t);this.emit("onFriendInfoChanged",this.computedField(i))}v2SyncFriendListHandler(e){var{friends:t,timetag:i}=e.content;this.model.setFriendTimetag(i),t.forEach(e=>{e.serverExtension||(e.serverExtension=""),e.customerExtension||(e.customerExtension=""),0===e.relationShip?this.model.deleteFriend(e.accountId):this.model.upsertFriend(e.accountId,e)})}v2SyncFriendUserListHandler(e){var{users:t}=e.content;this.hasUserService&&t.forEach(e=>{this.core.V2NIMUserService.model.setUser(e)})}handleApplyFriend(e){this.emit("onFriendAddApplication",e)}handleAddFriend(e,t){return Te(this,void 0,void 0,function*(){this.model.addFriend(e),yield this.incrementSyncFriend(),yield this.core.V2NIMUserService.refreshUserInfo(e);var t=this.model.getFriend(e);t&&this.emit("onFriendAdded",this.computedField(t))})}handleDeleteFriend(e,t){t=void 0===t?1:t,this.emit("onFriendDeleted",e,t),this.model.deleteFriend(e)}handleSetFriendInfo(e,t){var i=this.model.upsertFriend(e,t);this.emit("onFriendInfoChanged",this.computedField(i))}handlePassFriendApply(e,t){var i=t?null==t?void 0:t.code:200;if(!(i>=19e4||i===de.V2NIM_ERROR_CODE_FRIEND_OPERATION_RATE_LIMIT))if(200===i||i===de.V2NIM_ERROR_CODE_FRIEND_ALREADY_EXIST)this.notificationModel.updateFriendAddApplicationStatus(e,1,this.core.account),this.handleAddFriend(e);else{if(i>=500&&i<=599&&509!==i)return;this.notificationModel.updateFriendAddApplicationStatus(e,3,this.core.account)}}handleRejectFriendApply(e,t){var i=t?null==t?void 0:t.code:200;if(!(i>=19e4||i===de.V2NIM_ERROR_CODE_FRIEND_OPERATION_RATE_LIMIT))if(200===i)this.emit("onFriendAddRejected",e),this.notificationModel.updateFriendAddApplicationStatus(e.applicantAccountId,2,this.core.account);else if(i===de.V2NIM_ERROR_CODE_FRIEND_ALREADY_EXIST)this.notificationModel.updateFriendAddApplicationStatus(e.applicantAccountId,1,this.core.account);else{if(i>=500&&i<=599&&509!==i)return;this.notificationModel.updateFriendAddApplicationStatus(e.applicantAccountId,3,this.core.account)}}incrementSyncFriend(){return Te(this,void 0,void 0,function*(){var e=yield this.core.sendCmd("v2IncFriendInfo",{timetag:this.model.getFriendTimetag()}),{friends:t,timetag:i}=e.content;this.model.setFriendTimetag(i),t.forEach(e=>{this.model.upsertFriend(e.accountId,e)})})}computedFields(e){return e.map(e=>this.computedField(e))}computedField(e){var t,i,r=null===(i=null===(t=this.core.V2NIMUserService)||void 0===t?void 0:t.model)||void 0===i?void 0:i.getUser(e.accountId);return r?Object.assign({},e,{userProfile:r}):e}},"V2NIMFriendService"),Fo.registerService(class extends ii{constructor(e){super("V2NIMSubscriptionService",e),"v2"===this.core.options.apiVersion&&mt({cmdMap:ko,cmdConfig:Do})}emit(e,...t){var i=`${this.name}::emit ${e.toString()}`;return this.logger.log(`${i}`,...t),super.emit(e,...t)}subscribeUserStatus(e){return Te(this,void 0,void 0,function*(){return this.checkLogin(),this.checkV2(),_e(wo,e,"",!0),(yield this.core.sendCmd("v2SubscribeUserStatus",{tag:{eventType:1,duration:e.duration||60,immediateSync:void 0!==e.immediateSync&&e.immediateSync},accountIds:e.accountIds})).content.failedList})}unsubscribeUserStatus(e){return Te(this,void 0,void 0,function*(){this.checkLogin(),this.checkV2(),_e(Uo,e,"",!0);var t=[];return e.accountIds.length>0?t=(yield this.core.sendCmd("v2UnsubscribeUserStatus",{tag:{eventType:1},accountIds:e.accountIds})).content.failedList:(yield this.core.sendCmd("v2UnsubscribeAllUserStatus",{tag:{eventType:1}}),t=[]),t})}publishCustomUserStatus(e){return Te(this,void 0,void 0,function*(){return this.checkLogin(),this.checkV2(),_e(xo,e,"",!0),(yield this.core.sendCmd("v2PublishEvent",{tag:Object.assign(Object.assign({},e),{eventType:1,uniqueId:De(),duration:e.duration||60,onlineOnly:void 0===e.onlineOnly||e.onlineOnly,multiSync:void 0!==e.multiSync&&e.multiSync})})).content.data})}queryUserStatusSubscriptions(e){return Te(this,void 0,void 0,function*(){this.checkLogin(),this.checkV2(),_e({accountIds:{type:"array",required:!0,itemType:"string",max:3e3}},{accountIds:e},"",!0);var t=[];if(e.length>0)for(var i=0;i({accountId:e.accountId,subscribeTime:e.subscribeTime,duration:e.duration})))}else{var s=yield this.core.sendCmd("v2QueryAllSubscribeEvent",{tag:{eventType:1}});t=t.concat(s.content.data.map(e=>({accountId:e.accountId,subscribeTime:e.subscribeTime,duration:e.duration})))}return t})}v2OnUserStatusChangeHandler(e){var t=e.content.data,{eventType:i,extensionReceived:r}=t,s=Me(t,["eventType","extensionReceived"]);1===i?this.emit("onUserStatusChanged",[Object.assign(Object.assign({},s),{extension:r})]):this.logger.log("v2OnUserStatusChangeHandler eventType = ",i,"msgEvent = ",t)}v2OnMultiUserStatusChangeHandler(e){var t=e.content.data.filter(e=>1===e.eventType).map(e=>{var{eventType:t,extensionReceived:i}=e,r=Me(e,["eventType","extensionReceived"]);return Object.assign(Object.assign({},r),{extension:i})});t.length>0&&this.emit("onUserStatusChanged",t)}},"V2NIMSubscriptionService");export{Fo as NIM,he as V2NIMConst}; \ No newline at end of file diff --git a/dist/nim.js.LICENSE.txt b/dist/nim.js.LICENSE.txt new file mode 100644 index 0000000..ae386fb --- /dev/null +++ b/dist/nim.js.LICENSE.txt @@ -0,0 +1 @@ +/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ diff --git a/dist/spark-md5.min.js b/dist/spark-md5.min.js new file mode 100644 index 0000000..2ef527d --- /dev/null +++ b/dist/spark-md5.min.js @@ -0,0 +1 @@ +(function(factory){if(typeof exports==="object"){module.exports=factory()}else if(typeof define==="function"&&define.amd){define(factory)}else{var glob;try{glob=window}catch(e){glob=self}glob.SparkMD5=factory()}})(function(undefined){"use strict";var add32=function(a,b){return a+b&4294967295},hex_chr=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];function cmn(q,a,b,x,s,t){a=add32(add32(a,q),add32(x,t));return add32(a<>>32-s,b)}function md5cycle(x,k){var a=x[0],b=x[1],c=x[2],d=x[3];a+=(b&c|~b&d)+k[0]-680876936|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[1]-389564586|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[2]+606105819|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[3]-1044525330|0;b=(b<<22|b>>>10)+c|0;a+=(b&c|~b&d)+k[4]-176418897|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[5]+1200080426|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[6]-1473231341|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[7]-45705983|0;b=(b<<22|b>>>10)+c|0;a+=(b&c|~b&d)+k[8]+1770035416|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[9]-1958414417|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[10]-42063|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[11]-1990404162|0;b=(b<<22|b>>>10)+c|0;a+=(b&c|~b&d)+k[12]+1804603682|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[13]-40341101|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[14]-1502002290|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[15]+1236535329|0;b=(b<<22|b>>>10)+c|0;a+=(b&d|c&~d)+k[1]-165796510|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[6]-1069501632|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[11]+643717713|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[0]-373897302|0;b=(b<<20|b>>>12)+c|0;a+=(b&d|c&~d)+k[5]-701558691|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[10]+38016083|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[15]-660478335|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[4]-405537848|0;b=(b<<20|b>>>12)+c|0;a+=(b&d|c&~d)+k[9]+568446438|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[14]-1019803690|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[3]-187363961|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[8]+1163531501|0;b=(b<<20|b>>>12)+c|0;a+=(b&d|c&~d)+k[13]-1444681467|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[2]-51403784|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[7]+1735328473|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[12]-1926607734|0;b=(b<<20|b>>>12)+c|0;a+=(b^c^d)+k[5]-378558|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[8]-2022574463|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[11]+1839030562|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[14]-35309556|0;b=(b<<23|b>>>9)+c|0;a+=(b^c^d)+k[1]-1530992060|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[4]+1272893353|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[7]-155497632|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[10]-1094730640|0;b=(b<<23|b>>>9)+c|0;a+=(b^c^d)+k[13]+681279174|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[0]-358537222|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[3]-722521979|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[6]+76029189|0;b=(b<<23|b>>>9)+c|0;a+=(b^c^d)+k[9]-640364487|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[12]-421815835|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[15]+530742520|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[2]-995338651|0;b=(b<<23|b>>>9)+c|0;a+=(c^(b|~d))+k[0]-198630844|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[7]+1126891415|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[14]-1416354905|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[5]-57434055|0;b=(b<<21|b>>>11)+c|0;a+=(c^(b|~d))+k[12]+1700485571|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[3]-1894986606|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[10]-1051523|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[1]-2054922799|0;b=(b<<21|b>>>11)+c|0;a+=(c^(b|~d))+k[8]+1873313359|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[15]-30611744|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[6]-1560198380|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[13]+1309151649|0;b=(b<<21|b>>>11)+c|0;a+=(c^(b|~d))+k[4]-145523070|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[11]-1120210379|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[2]+718787259|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[9]-343485551|0;b=(b<<21|b>>>11)+c|0;x[0]=a+x[0]|0;x[1]=b+x[1]|0;x[2]=c+x[2]|0;x[3]=d+x[3]|0}function md5blk(s){var md5blks=[],i;for(i=0;i<64;i+=4){md5blks[i>>2]=s.charCodeAt(i)+(s.charCodeAt(i+1)<<8)+(s.charCodeAt(i+2)<<16)+(s.charCodeAt(i+3)<<24)}return md5blks}function md5blk_array(a){var md5blks=[],i;for(i=0;i<64;i+=4){md5blks[i>>2]=a[i]+(a[i+1]<<8)+(a[i+2]<<16)+(a[i+3]<<24)}return md5blks}function md51(s){var n=s.length,state=[1732584193,-271733879,-1732584194,271733878],i,length,tail,tmp,lo,hi;for(i=64;i<=n;i+=64){md5cycle(state,md5blk(s.substring(i-64,i)))}s=s.substring(i-64);length=s.length;tail=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(i=0;i>2]|=s.charCodeAt(i)<<(i%4<<3)}tail[i>>2]|=128<<(i%4<<3);if(i>55){md5cycle(state,tail);for(i=0;i<16;i+=1){tail[i]=0}}tmp=n*8;tmp=tmp.toString(16).match(/(.*?)(.{0,8})$/);lo=parseInt(tmp[2],16);hi=parseInt(tmp[1],16)||0;tail[14]=lo;tail[15]=hi;md5cycle(state,tail);return state}function md51_array(a){var n=a.length,state=[1732584193,-271733879,-1732584194,271733878],i,length,tail,tmp,lo,hi;for(i=64;i<=n;i+=64){md5cycle(state,md5blk_array(a.subarray(i-64,i)))}a=i-64>2]|=a[i]<<(i%4<<3)}tail[i>>2]|=128<<(i%4<<3);if(i>55){md5cycle(state,tail);for(i=0;i<16;i+=1){tail[i]=0}}tmp=n*8;tmp=tmp.toString(16).match(/(.*?)(.{0,8})$/);lo=parseInt(tmp[2],16);hi=parseInt(tmp[1],16)||0;tail[14]=lo;tail[15]=hi;md5cycle(state,tail);return state}function rhex(n){var s="",j;for(j=0;j<4;j+=1){s+=hex_chr[n>>j*8+4&15]+hex_chr[n>>j*8&15]}return s}function hex(x){var i;for(i=0;i>16)+(y>>16)+(lsw>>16);return msw<<16|lsw&65535}}if(typeof ArrayBuffer!=="undefined"&&!ArrayBuffer.prototype.slice){(function(){function clamp(val,length){val=val|0||0;if(val<0){return Math.max(val+length,0)}return Math.min(val,length)}ArrayBuffer.prototype.slice=function(from,to){var length=this.byteLength,begin=clamp(from,length),end=length,num,target,targetArray,sourceArray;if(to!==undefined){end=clamp(to,length)}if(begin>end){return new ArrayBuffer(0)}num=end-begin;target=new ArrayBuffer(num);targetArray=new Uint8Array(target);sourceArray=new Uint8Array(this,begin,num);targetArray.set(sourceArray);return target}})()}function toUtf8(str){if(/[\u0080-\uFFFF]/.test(str)){str=unescape(encodeURIComponent(str))}return str}function utf8Str2ArrayBuffer(str,returnUInt8Array){var length=str.length,buff=new ArrayBuffer(length),arr=new Uint8Array(buff),i;for(i=0;i>2]|=buff.charCodeAt(i)<<(i%4<<3)}this._finish(tail,length);ret=hex(this._hash);if(raw){ret=hexToBinaryString(ret)}this.reset();return ret};SparkMD5.prototype.reset=function(){this._buff="";this._length=0;this._hash=[1732584193,-271733879,-1732584194,271733878];return this};SparkMD5.prototype.getState=function(){return{buff:this._buff,length:this._length,hash:this._hash.slice()}};SparkMD5.prototype.setState=function(state){this._buff=state.buff;this._length=state.length;this._hash=state.hash;return this};SparkMD5.prototype.destroy=function(){delete this._hash;delete this._buff;delete this._length};SparkMD5.prototype._finish=function(tail,length){var i=length,tmp,lo,hi;tail[i>>2]|=128<<(i%4<<3);if(i>55){md5cycle(this._hash,tail);for(i=0;i<16;i+=1){tail[i]=0}}tmp=this._length*8;tmp=tmp.toString(16).match(/(.*?)(.{0,8})$/);lo=parseInt(tmp[2],16);hi=parseInt(tmp[1],16)||0;tail[14]=lo;tail[15]=hi;md5cycle(this._hash,tail)};SparkMD5.hash=function(str,raw){return SparkMD5.hashBinary(toUtf8(str),raw)};SparkMD5.hashBinary=function(content,raw){var hash=md51(content),ret=hex(hash);return raw?hexToBinaryString(ret):ret};SparkMD5.ArrayBuffer=function(){this.reset()};SparkMD5.ArrayBuffer.prototype.append=function(arr){var buff=concatenateArrayBuffers(this._buff.buffer,arr,true),length=buff.length,i;this._length+=arr.byteLength;for(i=64;i<=length;i+=64){md5cycle(this._hash,md5blk_array(buff.subarray(i-64,i)))}this._buff=i-64>2]|=buff[i]<<(i%4<<3)}this._finish(tail,length);ret=hex(this._hash);if(raw){ret=hexToBinaryString(ret)}this.reset();return ret};SparkMD5.ArrayBuffer.prototype.reset=function(){this._buff=new Uint8Array(0);this._length=0;this._hash=[1732584193,-271733879,-1732584194,271733878];return this};SparkMD5.ArrayBuffer.prototype.getState=function(){var state=SparkMD5.prototype.getState.call(this);state.buff=arrayBuffer2Utf8Str(state.buff);return state};SparkMD5.ArrayBuffer.prototype.setState=function(state){state.buff=utf8Str2ArrayBuffer(state.buff,true);return SparkMD5.prototype.setState.call(this,state)};SparkMD5.ArrayBuffer.prototype.destroy=SparkMD5.prototype.destroy;SparkMD5.ArrayBuffer.prototype._finish=SparkMD5.prototype._finish;SparkMD5.ArrayBuffer.hash=function(arr,raw){var hash=md51_array(new Uint8Array(arr)),ret=hex(hash);return raw?hexToBinaryString(ret):ret};return SparkMD5}); diff --git a/images/AddFriend.svg b/images/AddFriend.svg new file mode 100644 index 0000000..722ee3f --- /dev/null +++ b/images/AddFriend.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/Album.svg b/images/Album.svg new file mode 100644 index 0000000..940eaa7 --- /dev/null +++ b/images/Album.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/Edit3.png b/images/Edit3.png new file mode 100644 index 0000000..58410e4 Binary files /dev/null and b/images/Edit3.png differ diff --git a/images/Findme avatar.png b/images/Findme avatar.png new file mode 100644 index 0000000..342c469 Binary files /dev/null and b/images/Findme avatar.png differ diff --git a/images/Icon.png b/images/Icon.png new file mode 100644 index 0000000..737f5b8 Binary files /dev/null and b/images/Icon.png differ diff --git a/images/Image.svg b/images/Image.svg new file mode 100644 index 0000000..d5ec87a --- /dev/null +++ b/images/Image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/Search.png b/images/Search.png new file mode 100644 index 0000000..f250d53 Binary files /dev/null and b/images/Search.png differ diff --git a/images/Selected.svg b/images/Selected.svg new file mode 100644 index 0000000..062fb97 --- /dev/null +++ b/images/Selected.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/StartGroupChat.svg b/images/StartGroupChat.svg new file mode 100644 index 0000000..ba4ae21 --- /dev/null +++ b/images/StartGroupChat.svg @@ -0,0 +1,3 @@ + + + diff --git a/images/Subtract.png b/images/Subtract.png new file mode 100644 index 0000000..7fd5f18 Binary files /dev/null and b/images/Subtract.png differ diff --git a/images/User.svg b/images/User.svg new file mode 100644 index 0000000..f15cefb --- /dev/null +++ b/images/User.svg @@ -0,0 +1,3 @@ + + + diff --git a/images/avatar.png b/images/avatar.png new file mode 100644 index 0000000..e62473f Binary files /dev/null and b/images/avatar.png differ diff --git a/images/back_arrow.svg b/images/back_arrow.svg new file mode 100644 index 0000000..4967696 --- /dev/null +++ b/images/back_arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/btn.png b/images/btn.png new file mode 100644 index 0000000..fc824a0 Binary files /dev/null and b/images/btn.png differ diff --git a/images/bus_stop.png b/images/bus_stop.png new file mode 100644 index 0000000..bd39c4e Binary files /dev/null and b/images/bus_stop.png differ diff --git a/images/cam.svg b/images/cam.svg new file mode 100644 index 0000000..14e0216 --- /dev/null +++ b/images/cam.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/comment.png b/images/comment.png new file mode 100644 index 0000000..580b86e Binary files /dev/null and b/images/comment.png differ diff --git a/images/cross.svg b/images/cross.svg new file mode 100644 index 0000000..0dc26a7 --- /dev/null +++ b/images/cross.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/default-avatar.png b/images/default-avatar.png new file mode 100644 index 0000000..d2d2dd6 Binary files /dev/null and b/images/default-avatar.png differ diff --git a/images/default-avatar.svg b/images/default-avatar.svg new file mode 100644 index 0000000..7ddfba0 --- /dev/null +++ b/images/default-avatar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/default-stranger.png b/images/default-stranger.png new file mode 100644 index 0000000..0de9b9f Binary files /dev/null and b/images/default-stranger.png differ diff --git a/images/download.png b/images/download.png new file mode 100644 index 0000000..5147ff5 Binary files /dev/null and b/images/download.png differ diff --git a/images/download.svg b/images/download.svg new file mode 100644 index 0000000..7246989 --- /dev/null +++ b/images/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/emoji/add-circle.svg b/images/emoji/add-circle.svg new file mode 100644 index 0000000..57278bf --- /dev/null +++ b/images/emoji/add-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/emoji/f-message.svg b/images/emoji/f-message.svg new file mode 100644 index 0000000..789edb0 --- /dev/null +++ b/images/emoji/f-message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/emoji/f-more.svg b/images/emoji/f-more.svg new file mode 100644 index 0000000..bfa65a7 --- /dev/null +++ b/images/emoji/f-more.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/emoji/m-emoji.svg b/images/emoji/m-emoji.svg new file mode 100644 index 0000000..7900532 --- /dev/null +++ b/images/emoji/m-emoji.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/emoji/r-Return.svg b/images/emoji/r-Return.svg new file mode 100644 index 0000000..e71f413 --- /dev/null +++ b/images/emoji/r-Return.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/emoji/s-input.svg b/images/emoji/s-input.svg new file mode 100644 index 0000000..cd84524 --- /dev/null +++ b/images/emoji/s-input.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/error-icon.svg b/images/error-icon.svg new file mode 100644 index 0000000..64cb15f --- /dev/null +++ b/images/error-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/findme-logo.png b/images/findme-logo.png new file mode 100644 index 0000000..df7f089 Binary files /dev/null and b/images/findme-logo.png differ diff --git a/images/flashlight.svg b/images/flashlight.svg new file mode 100644 index 0000000..ad4b2c7 --- /dev/null +++ b/images/flashlight.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/fram.svg b/images/fram.svg new file mode 100644 index 0000000..922beba --- /dev/null +++ b/images/fram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/friend-avatar.png b/images/friend-avatar.png new file mode 100644 index 0000000..7eeae77 Binary files /dev/null and b/images/friend-avatar.png differ diff --git a/images/friend-avatar.svg b/images/friend-avatar.svg new file mode 100644 index 0000000..207391c --- /dev/null +++ b/images/friend-avatar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/group/Search-d.svg b/images/group/Search-d.svg new file mode 100644 index 0000000..5ce2a4b --- /dev/null +++ b/images/group/Search-d.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/group/Search.svg b/images/group/Search.svg new file mode 100644 index 0000000..086bbb4 --- /dev/null +++ b/images/group/Search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/group/add.svg b/images/group/add.svg new file mode 100644 index 0000000..2407758 --- /dev/null +++ b/images/group/add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/group/edit.svg b/images/group/edit.svg new file mode 100644 index 0000000..f020d7d --- /dev/null +++ b/images/group/edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/group/groupChat.svg b/images/group/groupChat.svg new file mode 100644 index 0000000..9131831 --- /dev/null +++ b/images/group/groupChat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/group/menu.svg b/images/group/menu.svg new file mode 100644 index 0000000..1b9cbf8 --- /dev/null +++ b/images/group/menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/group/testImg.jpg b/images/group/testImg.jpg new file mode 100644 index 0000000..2b7a208 Binary files /dev/null and b/images/group/testImg.jpg differ diff --git a/images/heart-red.png b/images/heart-red.png new file mode 100644 index 0000000..0de81ed Binary files /dev/null and b/images/heart-red.png differ diff --git a/images/heart-white.png b/images/heart-white.png new file mode 100644 index 0000000..367aceb Binary files /dev/null and b/images/heart-white.png differ diff --git a/images/img-agreement-check-next.png b/images/img-agreement-check-next.png new file mode 100644 index 0000000..cbc88db Binary files /dev/null and b/images/img-agreement-check-next.png differ diff --git a/images/img-agreement-check.png b/images/img-agreement-check.png new file mode 100644 index 0000000..72a11dd Binary files /dev/null and b/images/img-agreement-check.png differ diff --git a/images/index/circle-active.png b/images/index/circle-active.png new file mode 100644 index 0000000..e31b2ec Binary files /dev/null and b/images/index/circle-active.png differ diff --git a/images/index/circle.png b/images/index/circle.png new file mode 100644 index 0000000..aad9fe8 Binary files /dev/null and b/images/index/circle.png differ diff --git a/images/index/friend-active.png b/images/index/friend-active.png new file mode 100644 index 0000000..baefd45 Binary files /dev/null and b/images/index/friend-active.png differ diff --git a/images/index/friend.png b/images/index/friend.png new file mode 100644 index 0000000..eaf0e46 Binary files /dev/null and b/images/index/friend.png differ diff --git a/images/index/location-active.png b/images/index/location-active.png new file mode 100644 index 0000000..88d77ec Binary files /dev/null and b/images/index/location-active.png differ diff --git a/images/index/location.png b/images/index/location.png new file mode 100644 index 0000000..6887be5 Binary files /dev/null and b/images/index/location.png differ diff --git a/images/index/message-active.png b/images/index/message-active.png new file mode 100644 index 0000000..bfda868 Binary files /dev/null and b/images/index/message-active.png differ diff --git a/images/index/message.png b/images/index/message.png new file mode 100644 index 0000000..cca0a08 Binary files /dev/null and b/images/index/message.png differ diff --git a/images/index/phone-active.png b/images/index/phone-active.png new file mode 100644 index 0000000..e2e4495 Binary files /dev/null and b/images/index/phone-active.png differ diff --git a/images/index/phone.png b/images/index/phone.png new file mode 100644 index 0000000..46cb1bb Binary files /dev/null and b/images/index/phone.png differ diff --git a/images/lightning.svg b/images/lightning.svg new file mode 100644 index 0000000..dca8c95 --- /dev/null +++ b/images/lightning.svg @@ -0,0 +1,3 @@ + + + diff --git a/images/like-active.svg b/images/like-active.svg new file mode 100644 index 0000000..a1dfc89 --- /dev/null +++ b/images/like-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/like.svg b/images/like.svg new file mode 100644 index 0000000..f2d29e5 --- /dev/null +++ b/images/like.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/loca.svg b/images/loca.svg new file mode 100644 index 0000000..4774635 --- /dev/null +++ b/images/loca.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/location.png b/images/location.png new file mode 100644 index 0000000..32349e6 Binary files /dev/null and b/images/location.png differ diff --git a/images/login/findme.png b/images/login/findme.png new file mode 100644 index 0000000..7b28962 Binary files /dev/null and b/images/login/findme.png differ diff --git a/images/map/AddFriend.svg b/images/map/AddFriend.svg new file mode 100644 index 0000000..722ee3f --- /dev/null +++ b/images/map/AddFriend.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/map/Camera.svg b/images/map/Camera.svg new file mode 100644 index 0000000..90f8271 --- /dev/null +++ b/images/map/Camera.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/map/Copy_logo.png b/images/map/Copy_logo.png new file mode 100644 index 0000000..f1e3c88 Binary files /dev/null and b/images/map/Copy_logo.png differ diff --git a/images/map/Email_logo.png b/images/map/Email_logo.png new file mode 100644 index 0000000..2320238 Binary files /dev/null and b/images/map/Email_logo.png differ diff --git a/images/map/Mapsettings.svg b/images/map/Mapsettings.svg new file mode 100644 index 0000000..b46945c --- /dev/null +++ b/images/map/Mapsettings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/map/Microblog_logo.png b/images/map/Microblog_logo.png new file mode 100644 index 0000000..97a30fb Binary files /dev/null and b/images/map/Microblog_logo.png differ diff --git a/images/map/More.svg b/images/map/More.svg new file mode 100644 index 0000000..ad94219 --- /dev/null +++ b/images/map/More.svg @@ -0,0 +1,3 @@ + + + diff --git a/images/map/QQ_logo.png b/images/map/QQ_logo.png new file mode 100644 index 0000000..f16d8c9 Binary files /dev/null and b/images/map/QQ_logo.png differ diff --git a/images/map/QRCode.svg b/images/map/QRCode.svg new file mode 100644 index 0000000..b077945 --- /dev/null +++ b/images/map/QRCode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/map/Scan.svg b/images/map/Scan.svg new file mode 100644 index 0000000..3160769 --- /dev/null +++ b/images/map/Scan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/map/Search-d.png b/images/map/Search-d.png new file mode 100644 index 0000000..31728a2 Binary files /dev/null and b/images/map/Search-d.png differ diff --git a/images/map/StartGroupChat.svg b/images/map/StartGroupChat.svg new file mode 100644 index 0000000..d45b366 --- /dev/null +++ b/images/map/StartGroupChat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/map/Tiktok_logo.png b/images/map/Tiktok_logo.png new file mode 100644 index 0000000..58de69d Binary files /dev/null and b/images/map/Tiktok_logo.png differ diff --git a/images/map/Wechat_logo.png b/images/map/Wechat_logo.png new file mode 100644 index 0000000..2a09fa9 Binary files /dev/null and b/images/map/Wechat_logo.png differ diff --git a/images/map/baidumap_logo.png b/images/map/baidumap_logo.png new file mode 100644 index 0000000..be1d318 Binary files /dev/null and b/images/map/baidumap_logo.png differ diff --git a/images/map/bottom_top.png b/images/map/bottom_top.png new file mode 100644 index 0000000..781dd48 Binary files /dev/null and b/images/map/bottom_top.png differ diff --git a/images/map/collect-map.png b/images/map/collect-map.png new file mode 100644 index 0000000..dcdc191 Binary files /dev/null and b/images/map/collect-map.png differ diff --git a/images/map/collected.png b/images/map/collected.png new file mode 100644 index 0000000..c5424f6 Binary files /dev/null and b/images/map/collected.png differ diff --git a/images/map/direction_arrow.png b/images/map/direction_arrow.png new file mode 100644 index 0000000..deea710 Binary files /dev/null and b/images/map/direction_arrow.png differ diff --git a/images/map/down_black.png b/images/map/down_black.png new file mode 100644 index 0000000..75e2f11 Binary files /dev/null and b/images/map/down_black.png differ diff --git a/images/map/download.png b/images/map/download.png new file mode 100644 index 0000000..5147ff5 Binary files /dev/null and b/images/map/download.png differ diff --git a/images/map/gaodemap_logo.png b/images/map/gaodemap_logo.png new file mode 100644 index 0000000..c444b53 Binary files /dev/null and b/images/map/gaodemap_logo.png differ diff --git a/images/map/get_address.png b/images/map/get_address.png new file mode 100644 index 0000000..fcbc2c1 Binary files /dev/null and b/images/map/get_address.png differ diff --git a/images/map/maker_position.png b/images/map/maker_position.png new file mode 100644 index 0000000..009074c Binary files /dev/null and b/images/map/maker_position.png differ diff --git a/images/map/maker_position.svg b/images/map/maker_position.svg new file mode 100644 index 0000000..aa11c21 --- /dev/null +++ b/images/map/maker_position.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/map/marker-select-position.png b/images/map/marker-select-position.png new file mode 100644 index 0000000..db27612 Binary files /dev/null and b/images/map/marker-select-position.png differ diff --git a/images/map/marker_blank.png b/images/map/marker_blank.png new file mode 100644 index 0000000..ed979a9 Binary files /dev/null and b/images/map/marker_blank.png differ diff --git a/images/map/marker_hong.png b/images/map/marker_hong.png new file mode 100644 index 0000000..31133ac Binary files /dev/null and b/images/map/marker_hong.png differ diff --git a/images/map/marker_lan.png b/images/map/marker_lan.png new file mode 100644 index 0000000..0659298 Binary files /dev/null and b/images/map/marker_lan.png differ diff --git a/images/map/marker_yinliao.png b/images/map/marker_yinliao.png new file mode 100644 index 0000000..ae4be8d Binary files /dev/null and b/images/map/marker_yinliao.png differ diff --git a/images/map/marker_yule.png b/images/map/marker_yule.png new file mode 100644 index 0000000..65c613e Binary files /dev/null and b/images/map/marker_yule.png differ diff --git a/images/map/more-black.png b/images/map/more-black.png new file mode 100644 index 0000000..e28d1e3 Binary files /dev/null and b/images/map/more-black.png differ diff --git a/images/map/more-white.png b/images/map/more-white.png new file mode 100644 index 0000000..e915d95 Binary files /dev/null and b/images/map/more-white.png differ diff --git a/images/map/navigate- map.png b/images/map/navigate- map.png new file mode 100644 index 0000000..46fef3c Binary files /dev/null and b/images/map/navigate- map.png differ diff --git a/images/map/online_dot.png b/images/map/online_dot.png new file mode 100644 index 0000000..630b943 Binary files /dev/null and b/images/map/online_dot.png differ diff --git a/images/map/ouyu-close.png b/images/map/ouyu-close.png new file mode 100644 index 0000000..ea0ebab Binary files /dev/null and b/images/map/ouyu-close.png differ diff --git a/images/map/ouyu-open.png b/images/map/ouyu-open.png new file mode 100644 index 0000000..fbca46e Binary files /dev/null and b/images/map/ouyu-open.png differ diff --git a/images/map/share-map.png b/images/map/share-map.png new file mode 100644 index 0000000..3f40524 Binary files /dev/null and b/images/map/share-map.png differ diff --git a/images/map/tengxunmap_logo.png b/images/map/tengxunmap_logo.png new file mode 100644 index 0000000..196f7d8 Binary files /dev/null and b/images/map/tengxunmap_logo.png differ diff --git a/images/merchant/go.PNG b/images/merchant/go.PNG new file mode 100644 index 0000000..d869a5d Binary files /dev/null and b/images/merchant/go.PNG differ diff --git a/images/my-avatar.svg b/images/my-avatar.svg new file mode 100644 index 0000000..fa6ceaf --- /dev/null +++ b/images/my-avatar.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/ouyu-close.png b/images/ouyu-close.png new file mode 100644 index 0000000..ea0ebab Binary files /dev/null and b/images/ouyu-close.png differ diff --git a/images/ouyu-open.png b/images/ouyu-open.png new file mode 100644 index 0000000..2381779 Binary files /dev/null and b/images/ouyu-open.png differ diff --git a/images/ph.png b/images/ph.png new file mode 100644 index 0000000..c5c449c Binary files /dev/null and b/images/ph.png differ diff --git a/images/placeholder.svg b/images/placeholder.svg new file mode 100644 index 0000000..46232a5 --- /dev/null +++ b/images/placeholder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/qr-code.png b/images/qr-code.png new file mode 100644 index 0000000..e6164bd Binary files /dev/null and b/images/qr-code.png differ diff --git a/images/qr-code.svg b/images/qr-code.svg new file mode 100644 index 0000000..3a7baa0 --- /dev/null +++ b/images/qr-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/refresh-2.svg b/images/refresh-2.svg new file mode 100644 index 0000000..93b6537 --- /dev/null +++ b/images/refresh-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/refresh.png b/images/refresh.png new file mode 100644 index 0000000..19ce799 Binary files /dev/null and b/images/refresh.png differ diff --git a/images/right-icon.svg b/images/right-icon.svg new file mode 100644 index 0000000..233a8ec --- /dev/null +++ b/images/right-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/scan.svg b/images/scan.svg new file mode 100644 index 0000000..2a6da25 --- /dev/null +++ b/images/scan.svg @@ -0,0 +1,3 @@ + + + diff --git a/images/self/approve_badge.png b/images/self/approve_badge.png new file mode 100644 index 0000000..b994961 Binary files /dev/null and b/images/self/approve_badge.png differ diff --git a/images/self/bag.png b/images/self/bag.png new file mode 100644 index 0000000..93bb6ae Binary files /dev/null and b/images/self/bag.png differ diff --git a/images/self/check.png b/images/self/check.png new file mode 100644 index 0000000..3d0e2a4 Binary files /dev/null and b/images/self/check.png differ diff --git a/images/self/cycle.png b/images/self/cycle.png new file mode 100644 index 0000000..0cbad29 Binary files /dev/null and b/images/self/cycle.png differ diff --git a/images/self/earth.png b/images/self/earth.png new file mode 100644 index 0000000..892cbad Binary files /dev/null and b/images/self/earth.png differ diff --git a/images/self/findme_logo_self.png b/images/self/findme_logo_self.png new file mode 100644 index 0000000..03dfd45 Binary files /dev/null and b/images/self/findme_logo_self.png differ diff --git a/images/self/fmale.svg b/images/self/fmale.svg new file mode 100644 index 0000000..2aac1f3 --- /dev/null +++ b/images/self/fmale.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/self/game.png b/images/self/game.png new file mode 100644 index 0000000..ee25aa5 Binary files /dev/null and b/images/self/game.png differ diff --git a/images/self/group-shop.png b/images/self/group-shop.png new file mode 100644 index 0000000..bfcb577 Binary files /dev/null and b/images/self/group-shop.png differ diff --git a/images/self/home-heart-fill.svg b/images/self/home-heart-fill.svg new file mode 100644 index 0000000..65582ca --- /dev/null +++ b/images/self/home-heart-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/self/icon-video.png b/images/self/icon-video.png new file mode 100644 index 0000000..1e335bb Binary files /dev/null and b/images/self/icon-video.png differ diff --git a/images/self/male.svg b/images/self/male.svg new file mode 100644 index 0000000..4fea914 --- /dev/null +++ b/images/self/male.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/self/picture.png b/images/self/picture.png new file mode 100644 index 0000000..48d1096 Binary files /dev/null and b/images/self/picture.png differ diff --git a/images/self/small.png b/images/self/small.png new file mode 100644 index 0000000..f406a53 Binary files /dev/null and b/images/self/small.png differ diff --git a/images/self/store.png b/images/self/store.png new file mode 100644 index 0000000..5740f2c Binary files /dev/null and b/images/self/store.png differ diff --git a/images/self/vip.png b/images/self/vip.png new file mode 100644 index 0000000..ffec5a5 Binary files /dev/null and b/images/self/vip.png differ diff --git a/images/share.svg b/images/share.svg new file mode 100644 index 0000000..85ac4e6 --- /dev/null +++ b/images/share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/stranger-avatar.svg b/images/stranger-avatar.svg new file mode 100644 index 0000000..ad7b3b4 --- /dev/null +++ b/images/stranger-avatar.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/tag.png b/images/tag.png new file mode 100644 index 0000000..95f34ca Binary files /dev/null and b/images/tag.png differ diff --git a/images/wx.png b/images/wx.png new file mode 100644 index 0000000..c82a9a8 Binary files /dev/null and b/images/wx.png differ diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..58d7b51 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "es2015", + "module": "commonjs" + } +} \ No newline at end of file diff --git a/libs/amap-wx.js b/libs/amap-wx.js new file mode 100644 index 0000000..6ccbad2 --- /dev/null +++ b/libs/amap-wx.js @@ -0,0 +1,110 @@ +/** + * 高德地图微信小程序SDK - 纯定位版 + * 只负责GPS定位,地址解析由后端处理 + */ + +class AMapWX { + constructor(options = {}) { + this.key = options.key || ''; + this.version = '1.5.0'; + + if (this.key) { + console.log(`API Key: ${this.key.substring(0, 8)}...`); + } + } + + /** + * 获取微信定位 - 主要功能 + * @param {function} callback - 定位回调函数 callback(location, error) + * @param {object} options - 定位选项 + */ + getWxLocation(callback, options = {}) { + const defaultOptions = { + type: 'gcj02', + isHighAccuracy: true, + highAccuracyExpireTime: 4000, + ...options + }; + + wx.getLocation({ + ...defaultOptions, + success: (res) => { + + const location = { + longitude: res.longitude, + latitude: res.latitude, + accuracy: res.accuracy || 0, + altitude: res.altitude || 0, + speed: res.speed || 0, + horizontalAccuracy: res.horizontalAccuracy || 0, + verticalAccuracy: res.verticalAccuracy || 0 + }; + + if (typeof callback === 'function') { + callback(location, null); + } + }, + fail: (err) => { + console.error('[AMapWX] 微信定位失败:', err); + + if (typeof callback === 'function') { + callback(null, err); + } + } + }); + } + + /** + * 计算两点间距离 + * @param {object} point1 - 起点 {longitude, latitude} + * @param {object} point2 - 终点 {longitude, latitude} + * @returns {number} 距离(米) + */ + calculateDistance(point1, point2) { + const R = 6371000; // 地球半径(米) + const lat1 = point1.latitude * Math.PI / 180; + const lat2 = point2.latitude * Math.PI / 180; + const deltaLat = (point2.latitude - point1.latitude) * Math.PI / 180; + const deltaLng = (point2.longitude - point1.longitude) * Math.PI / 180; + + const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + + Math.cos(lat1) * Math.cos(lat2) * + Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2); + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + return R * c; + } +} + +// 创建单例实例 +let amapInstance = null; + +const AmapWX = { + /** + * 获取SDK实例 + * @param {object} options - 配置选项 + * @returns {AMapWX} + */ + getInstance(options = {}) { + if (!amapInstance) { + amapInstance = new AMapWX(options); + } + return amapInstance; + }, + + /** + * 重置SDK实例 + * @param {object} options - 配置选项 + * @returns {AMapWX} + */ + resetInstance(options = {}) { + amapInstance = new AMapWX(options); + return amapInstance; + } +}; + +// 导出模块 +module.exports = { + AMapWX, + AmapWX +}; diff --git a/miniprogram_npm/crypto-js/index.js b/miniprogram_npm/crypto-js/index.js new file mode 100644 index 0000000..3bfde5f --- /dev/null +++ b/miniprogram_npm/crypto-js/index.js @@ -0,0 +1,7365 @@ +module.exports = (function() { +var __MODS__ = {}; +var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; }; +var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; }; +var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } }; +var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; }; +__DEFINE__(1758332250178, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./lib-typedarrays"), require("./enc-utf16"), require("./enc-base64"), require("./enc-base64url"), require("./md5"), require("./sha1"), require("./sha256"), require("./sha224"), require("./sha512"), require("./sha384"), require("./sha3"), require("./ripemd160"), require("./hmac"), require("./pbkdf2"), require("./evpkdf"), require("./cipher-core"), require("./mode-cfb"), require("./mode-ctr"), require("./mode-ctr-gladman"), require("./mode-ofb"), require("./mode-ecb"), require("./pad-ansix923"), require("./pad-iso10126"), require("./pad-iso97971"), require("./pad-zeropadding"), require("./pad-nopadding"), require("./format-hex"), require("./aes"), require("./tripledes"), require("./rc4"), require("./rabbit"), require("./rabbit-legacy"), require("./blowfish")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./lib-typedarrays", "./enc-utf16", "./enc-base64", "./enc-base64url", "./md5", "./sha1", "./sha256", "./sha224", "./sha512", "./sha384", "./sha3", "./ripemd160", "./hmac", "./pbkdf2", "./evpkdf", "./cipher-core", "./mode-cfb", "./mode-ctr", "./mode-ctr-gladman", "./mode-ofb", "./mode-ecb", "./pad-ansix923", "./pad-iso10126", "./pad-iso97971", "./pad-zeropadding", "./pad-nopadding", "./format-hex", "./aes", "./tripledes", "./rc4", "./rabbit", "./rabbit-legacy", "./blowfish"], factory); + } + else { + // Global (browser) + root.CryptoJS = factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS; + +})); +}, function(modId) {var map = {"./core":1758332250179,"./x64-core":1758332250180,"./lib-typedarrays":1758332250181,"./enc-utf16":1758332250182,"./enc-base64":1758332250183,"./enc-base64url":1758332250184,"./md5":1758332250185,"./sha1":1758332250186,"./sha256":1758332250187,"./sha224":1758332250188,"./sha512":1758332250189,"./sha384":1758332250190,"./sha3":1758332250191,"./ripemd160":1758332250192,"./hmac":1758332250193,"./pbkdf2":1758332250194,"./evpkdf":1758332250195,"./cipher-core":1758332250196,"./mode-cfb":1758332250197,"./mode-ctr":1758332250198,"./mode-ctr-gladman":1758332250199,"./mode-ofb":1758332250200,"./mode-ecb":1758332250201,"./pad-ansix923":1758332250202,"./pad-iso10126":1758332250203,"./pad-iso97971":1758332250204,"./pad-zeropadding":1758332250205,"./pad-nopadding":1758332250206,"./format-hex":1758332250207,"./aes":1758332250208,"./tripledes":1758332250209,"./rc4":1758332250210,"./rabbit":1758332250211,"./rabbit-legacy":1758332250212,"./blowfish":1758332250213}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250179, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(); + } + else if (typeof define === "function" && define.amd) { + // AMD + define([], factory); + } + else { + // Global (browser) + root.CryptoJS = factory(); + } +}(this, function () { + + /*globals window, global, require*/ + + /** + * CryptoJS core components. + */ + var CryptoJS = CryptoJS || (function (Math, undefined) { + + var crypto; + + // Native crypto from window (Browser) + if (typeof window !== 'undefined' && window.crypto) { + crypto = window.crypto; + } + + // Native crypto in web worker (Browser) + if (typeof self !== 'undefined' && self.crypto) { + crypto = self.crypto; + } + + // Native crypto from worker + if (typeof globalThis !== 'undefined' && globalThis.crypto) { + crypto = globalThis.crypto; + } + + // Native (experimental IE 11) crypto from window (Browser) + if (!crypto && typeof window !== 'undefined' && window.msCrypto) { + crypto = window.msCrypto; + } + + // Native crypto from global (NodeJS) + if (!crypto && typeof global !== 'undefined' && global.crypto) { + crypto = global.crypto; + } + + // Native crypto import via require (NodeJS) + if (!crypto && typeof require === 'function') { + try { + crypto = require('crypto'); + } catch (err) {} + } + + /* + * Cryptographically secure pseudorandom number generator + * + * As Math.random() is cryptographically not safe to use + */ + var cryptoSecureRandomInt = function () { + if (crypto) { + // Use getRandomValues method (Browser) + if (typeof crypto.getRandomValues === 'function') { + try { + return crypto.getRandomValues(new Uint32Array(1))[0]; + } catch (err) {} + } + + // Use randomBytes method (NodeJS) + if (typeof crypto.randomBytes === 'function') { + try { + return crypto.randomBytes(4).readInt32LE(); + } catch (err) {} + } + } + + throw new Error('Native crypto module could not be used to get secure random number.'); + }; + + /* + * Local polyfill of Object.create + + */ + var create = Object.create || (function () { + function F() {} + + return function (obj) { + var subtype; + + F.prototype = obj; + + subtype = new F(); + + F.prototype = null; + + return subtype; + }; + }()); + + /** + * CryptoJS namespace. + */ + var C = {}; + + /** + * Library namespace. + */ + var C_lib = C.lib = {}; + + /** + * Base object for prototypal inheritance. + */ + var Base = C_lib.Base = (function () { + + + return { + /** + * Creates a new object that inherits from this object. + * + * @param {Object} overrides Properties to copy into the new object. + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * field: 'value', + * + * method: function () { + * } + * }); + */ + extend: function (overrides) { + // Spawn + var subtype = create(this); + + // Augment + if (overrides) { + subtype.mixIn(overrides); + } + + // Create default initializer + if (!subtype.hasOwnProperty('init') || this.init === subtype.init) { + subtype.init = function () { + subtype.$super.init.apply(this, arguments); + }; + } + + // Initializer's prototype is the subtype object + subtype.init.prototype = subtype; + + // Reference supertype + subtype.$super = this; + + return subtype; + }, + + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + create: function () { + var instance = this.extend(); + instance.init.apply(instance, arguments); + + return instance; + }, + + /** + * Initializes a newly created object. + * Override this method to add some logic when your objects are created. + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * init: function () { + * // ... + * } + * }); + */ + init: function () { + }, + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn: function (properties) { + for (var propertyName in properties) { + if (properties.hasOwnProperty(propertyName)) { + this[propertyName] = properties[propertyName]; + } + } + + // IE won't copy toString using the loop above + if (properties.hasOwnProperty('toString')) { + this.toString = properties.toString; + } + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone: function () { + return this.init.prototype.extend(this); + } + }; + }()); + + /** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var WordArray = C_lib.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 4; + } + }, + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString: function (encoder) { + return (encoder || Hex).stringify(this); + }, + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat: function (wordArray) { + // Shortcuts + var thisWords = this.words; + var thatWords = wordArray.words; + var thisSigBytes = this.sigBytes; + var thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (var i = 0; i < thatSigBytes; i++) { + var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else { + // Copy one word at a time + for (var j = 0; j < thatSigBytes; j += 4) { + thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2]; + } + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + }, + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp: function () { + // Shortcuts + var words = this.words; + var sigBytes = this.sigBytes; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + }, + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + }, + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + random: function (nBytes) { + var words = []; + + for (var i = 0; i < nBytes; i += 4) { + words.push(cryptoSecureRandomInt()); + } + + return new WordArray.init(words, nBytes); + } + }); + + /** + * Encoder namespace. + */ + var C_enc = C.enc = {}; + + /** + * Hex encoding strategy. + */ + var Hex = C_enc.Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var hexChars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse: function (hexStr) { + // Shortcut + var hexStrLength = hexStr.length; + + // Convert + var words = []; + for (var i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray.init(words, hexStrLength / 2); + } + }; + + /** + * Latin1 encoding strategy. + */ + var Latin1 = C_enc.Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var latin1Chars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse: function (latin1Str) { + // Shortcut + var latin1StrLength = latin1Str.length; + + // Convert + var words = []; + for (var i = 0; i < latin1StrLength; i++) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray.init(words, latin1StrLength); + } + }; + + /** + * UTF-8 encoding strategy. + */ + var Utf8 = C_enc.Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify: function (wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse: function (utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + } + }; + + /** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset: function () { + // Initial values + this._data = new WordArray.init(); + this._nDataBytes = 0; + }, + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append: function (data) { + // Convert string to WordArray, else assume WordArray already + if (typeof data == 'string') { + data = Utf8.parse(data); + } + + // Append + this._data.concat(data); + this._nDataBytes += data.sigBytes; + }, + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process: function (doFlush) { + var processedWords; + + // Shortcuts + var data = this._data; + var dataWords = data.words; + var dataSigBytes = data.sigBytes; + var blockSize = this.blockSize; + var blockSizeBytes = blockSize * 4; + + // Count blocks ready + var nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + var nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (var offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray.init(processedWords, nBytesReady); + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone._data = this._data.clone(); + + return clone; + }, + + _minBufferSize: 0 + }); + + /** + * Abstract hasher template. + * + * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ + var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + */ + cfg: Base.extend(), + + /** + * Initializes a newly created hasher. + * + * @param {Object} cfg (Optional) The configuration options to use for this hash computation. + * + * @example + * + * var hasher = CryptoJS.algo.SHA256.create(); + */ + init: function (cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Set initial values + this.reset(); + }, + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + }, + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update: function (messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + }, + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + var hash = this._doFinalize(); + + return hash; + }, + + blockSize: 512/32, + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} hasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + _createHelper: function (hasher) { + return function (message, cfg) { + return new hasher.init(cfg).finalize(message); + }; + }, + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} hasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + _createHmacHelper: function (hasher) { + return function (message, key) { + return new C_algo.HMAC.init(hasher, key).finalize(message); + }; + } + }); + + /** + * Algorithm namespace. + */ + var C_algo = C.algo = {}; + + return C; + }(Math)); + + + return CryptoJS; + +})); +}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250180, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var X32WordArray = C_lib.WordArray; + + /** + * x64 namespace. + */ + var C_x64 = C.x64 = {}; + + /** + * A 64-bit word. + */ + var X64Word = C_x64.Word = Base.extend({ + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + init: function (high, low) { + this.high = high; + this.low = low; + } + + /** + * Bitwise NOTs this word. + * + * @return {X64Word} A new x64-Word object after negating. + * + * @example + * + * var negated = x64Word.not(); + */ + // not: function () { + // var high = ~this.high; + // var low = ~this.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ANDs this word with the passed word. + * + * @param {X64Word} word The x64-Word to AND with this word. + * + * @return {X64Word} A new x64-Word object after ANDing. + * + * @example + * + * var anded = x64Word.and(anotherX64Word); + */ + // and: function (word) { + // var high = this.high & word.high; + // var low = this.low & word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to OR with this word. + * + * @return {X64Word} A new x64-Word object after ORing. + * + * @example + * + * var ored = x64Word.or(anotherX64Word); + */ + // or: function (word) { + // var high = this.high | word.high; + // var low = this.low | word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise XORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to XOR with this word. + * + * @return {X64Word} A new x64-Word object after XORing. + * + * @example + * + * var xored = x64Word.xor(anotherX64Word); + */ + // xor: function (word) { + // var high = this.high ^ word.high; + // var low = this.low ^ word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the left. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftL(25); + */ + // shiftL: function (n) { + // if (n < 32) { + // var high = (this.high << n) | (this.low >>> (32 - n)); + // var low = this.low << n; + // } else { + // var high = this.low << (n - 32); + // var low = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the right. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftR(7); + */ + // shiftR: function (n) { + // if (n < 32) { + // var low = (this.low >>> n) | (this.high << (32 - n)); + // var high = this.high >>> n; + // } else { + // var low = this.high >>> (n - 32); + // var high = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Rotates this word n bits to the left. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotL(25); + */ + // rotL: function (n) { + // return this.shiftL(n).or(this.shiftR(64 - n)); + // }, + + /** + * Rotates this word n bits to the right. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotR(7); + */ + // rotR: function (n) { + // return this.shiftR(n).or(this.shiftL(64 - n)); + // }, + + /** + * Adds this word with the passed word. + * + * @param {X64Word} word The x64-Word to add with this word. + * + * @return {X64Word} A new x64-Word object after adding. + * + * @example + * + * var added = x64Word.add(anotherX64Word); + */ + // add: function (word) { + // var low = (this.low + word.low) | 0; + // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0; + // var high = (this.high + word.high + carry) | 0; + + // return X64Word.create(high, low); + // } + }); + + /** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var X64WordArray = C_x64.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 8; + } + }, + + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32: function () { + // Shortcuts + var x64Words = this.words; + var x64WordsLength = x64Words.length; + + // Convert + var x32Words = []; + for (var i = 0; i < x64WordsLength; i++) { + var x64Word = x64Words[i]; + x32Words.push(x64Word.high); + x32Words.push(x64Word.low); + } + + return X32WordArray.create(x32Words, this.sigBytes); + }, + + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + + // Clone "words" array + var words = clone.words = this.words.slice(0); + + // Clone each X64Word object + var wordsLength = words.length; + for (var i = 0; i < wordsLength; i++) { + words[i] = words[i].clone(); + } + + return clone; + } + }); + }()); + + + return CryptoJS; + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250181, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Check if typed arrays are supported + if (typeof ArrayBuffer != 'function') { + return; + } + + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + + // Reference original init + var superInit = WordArray.init; + + // Augment WordArray.init to handle typed arrays + var subInit = WordArray.init = function (typedArray) { + // Convert buffers to uint8 + if (typedArray instanceof ArrayBuffer) { + typedArray = new Uint8Array(typedArray); + } + + // Convert other array views to uint8 + if ( + typedArray instanceof Int8Array || + (typeof Uint8ClampedArray !== "undefined" && typedArray instanceof Uint8ClampedArray) || + typedArray instanceof Int16Array || + typedArray instanceof Uint16Array || + typedArray instanceof Int32Array || + typedArray instanceof Uint32Array || + typedArray instanceof Float32Array || + typedArray instanceof Float64Array + ) { + typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + } + + // Handle Uint8Array + if (typedArray instanceof Uint8Array) { + // Shortcut + var typedArrayByteLength = typedArray.byteLength; + + // Extract bytes + var words = []; + for (var i = 0; i < typedArrayByteLength; i++) { + words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); + } + + // Initialize this word array + superInit.call(this, words, typedArrayByteLength); + } else { + // Else call normal init + superInit.apply(this, arguments); + } + }; + + subInit.prototype = WordArray; + }()); + + + return CryptoJS.lib.WordArray; + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250182, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * UTF-16 BE encoding strategy. + */ + var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = { + /** + * Converts a word array to a UTF-16 BE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 BE string. + * + * @static + * + * @example + * + * var utf16String = CryptoJS.enc.Utf16.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 BE string to a word array. + * + * @param {string} utf16Str The UTF-16 BE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16.parse(utf16String); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + /** + * UTF-16 LE encoding strategy. + */ + C_enc.Utf16LE = { + /** + * Converts a word array to a UTF-16 LE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 LE string. + * + * @static + * + * @example + * + * var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 LE string to a word array. + * + * @param {string} utf16Str The UTF-16 LE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + function swapEndian(word) { + return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); + } + }()); + + + return CryptoJS.enc.Utf16; + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250183, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * Base64 encoding strategy. + */ + var Base64 = C_enc.Base64 = { + /** + * Converts a word array to a Base64 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Base64 string. + * + * @static + * + * @example + * + * var base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var map = this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + var base64Chars = []; + for (var i = 0; i < sigBytes; i += 3) { + var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + var triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + var paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64 string to a word array. + * + * @param {string} base64Str The Base64 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse: function (base64Str) { + // Shortcuts + var base64StrLength = base64Str.length; + var map = this._map; + var reverseMap = this._reverseMap; + + if (!reverseMap) { + reverseMap = this._reverseMap = []; + for (var j = 0; j < map.length; j++) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + var paddingChar = map.charAt(64); + if (paddingChar) { + var paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' + }; + + function parseLoop(base64Str, base64StrLength, reverseMap) { + var words = []; + var nBytes = 0; + for (var i = 0; i < base64StrLength; i++) { + if (i % 4) { + var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + var bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8); + nBytes++; + } + } + return WordArray.create(words, nBytes); + } + }()); + + + return CryptoJS.enc.Base64; + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250184, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * Base64url encoding strategy. + */ + var Base64url = C_enc.Base64url = { + /** + * Converts a word array to a Base64url string. + * + * @param {WordArray} wordArray The word array. + * + * @param {boolean} urlSafe Whether to use url safe + * + * @return {string} The Base64url string. + * + * @static + * + * @example + * + * var base64String = CryptoJS.enc.Base64url.stringify(wordArray); + */ + stringify: function (wordArray, urlSafe) { + if (urlSafe === undefined) { + urlSafe = true + } + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var map = urlSafe ? this._safe_map : this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + var base64Chars = []; + for (var i = 0; i < sigBytes; i += 3) { + var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + var triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + var paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64url string to a word array. + * + * @param {string} base64Str The Base64url string. + * + * @param {boolean} urlSafe Whether to use url safe + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Base64url.parse(base64String); + */ + parse: function (base64Str, urlSafe) { + if (urlSafe === undefined) { + urlSafe = true + } + + // Shortcuts + var base64StrLength = base64Str.length; + var map = urlSafe ? this._safe_map : this._map; + var reverseMap = this._reverseMap; + + if (!reverseMap) { + reverseMap = this._reverseMap = []; + for (var j = 0; j < map.length; j++) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + var paddingChar = map.charAt(64); + if (paddingChar) { + var paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + _safe_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', + }; + + function parseLoop(base64Str, base64StrLength, reverseMap) { + var words = []; + var nBytes = 0; + for (var i = 0; i < base64StrLength; i++) { + if (i % 4) { + var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + var bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8); + nBytes++; + } + } + return WordArray.create(words, nBytes); + } + }()); + + + return CryptoJS.enc.Base64url; + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250185, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var T = []; + + // Compute constants + (function () { + for (var i = 0; i < 64; i++) { + T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; + } + }()); + + /** + * MD5 hash algorithm. + */ + var MD5 = C_algo.MD5 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + + // Shortcuts + var H = this._hash.words; + + var M_offset_0 = M[offset + 0]; + var M_offset_1 = M[offset + 1]; + var M_offset_2 = M[offset + 2]; + var M_offset_3 = M[offset + 3]; + var M_offset_4 = M[offset + 4]; + var M_offset_5 = M[offset + 5]; + var M_offset_6 = M[offset + 6]; + var M_offset_7 = M[offset + 7]; + var M_offset_8 = M[offset + 8]; + var M_offset_9 = M[offset + 9]; + var M_offset_10 = M[offset + 10]; + var M_offset_11 = M[offset + 11]; + var M_offset_12 = M[offset + 12]; + var M_offset_13 = M[offset + 13]; + var M_offset_14 = M[offset + 14]; + var M_offset_15 = M[offset + 15]; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + + // Computation + a = FF(a, b, c, d, M_offset_0, 7, T[0]); + d = FF(d, a, b, c, M_offset_1, 12, T[1]); + c = FF(c, d, a, b, M_offset_2, 17, T[2]); + b = FF(b, c, d, a, M_offset_3, 22, T[3]); + a = FF(a, b, c, d, M_offset_4, 7, T[4]); + d = FF(d, a, b, c, M_offset_5, 12, T[5]); + c = FF(c, d, a, b, M_offset_6, 17, T[6]); + b = FF(b, c, d, a, M_offset_7, 22, T[7]); + a = FF(a, b, c, d, M_offset_8, 7, T[8]); + d = FF(d, a, b, c, M_offset_9, 12, T[9]); + c = FF(c, d, a, b, M_offset_10, 17, T[10]); + b = FF(b, c, d, a, M_offset_11, 22, T[11]); + a = FF(a, b, c, d, M_offset_12, 7, T[12]); + d = FF(d, a, b, c, M_offset_13, 12, T[13]); + c = FF(c, d, a, b, M_offset_14, 17, T[14]); + b = FF(b, c, d, a, M_offset_15, 22, T[15]); + + a = GG(a, b, c, d, M_offset_1, 5, T[16]); + d = GG(d, a, b, c, M_offset_6, 9, T[17]); + c = GG(c, d, a, b, M_offset_11, 14, T[18]); + b = GG(b, c, d, a, M_offset_0, 20, T[19]); + a = GG(a, b, c, d, M_offset_5, 5, T[20]); + d = GG(d, a, b, c, M_offset_10, 9, T[21]); + c = GG(c, d, a, b, M_offset_15, 14, T[22]); + b = GG(b, c, d, a, M_offset_4, 20, T[23]); + a = GG(a, b, c, d, M_offset_9, 5, T[24]); + d = GG(d, a, b, c, M_offset_14, 9, T[25]); + c = GG(c, d, a, b, M_offset_3, 14, T[26]); + b = GG(b, c, d, a, M_offset_8, 20, T[27]); + a = GG(a, b, c, d, M_offset_13, 5, T[28]); + d = GG(d, a, b, c, M_offset_2, 9, T[29]); + c = GG(c, d, a, b, M_offset_7, 14, T[30]); + b = GG(b, c, d, a, M_offset_12, 20, T[31]); + + a = HH(a, b, c, d, M_offset_5, 4, T[32]); + d = HH(d, a, b, c, M_offset_8, 11, T[33]); + c = HH(c, d, a, b, M_offset_11, 16, T[34]); + b = HH(b, c, d, a, M_offset_14, 23, T[35]); + a = HH(a, b, c, d, M_offset_1, 4, T[36]); + d = HH(d, a, b, c, M_offset_4, 11, T[37]); + c = HH(c, d, a, b, M_offset_7, 16, T[38]); + b = HH(b, c, d, a, M_offset_10, 23, T[39]); + a = HH(a, b, c, d, M_offset_13, 4, T[40]); + d = HH(d, a, b, c, M_offset_0, 11, T[41]); + c = HH(c, d, a, b, M_offset_3, 16, T[42]); + b = HH(b, c, d, a, M_offset_6, 23, T[43]); + a = HH(a, b, c, d, M_offset_9, 4, T[44]); + d = HH(d, a, b, c, M_offset_12, 11, T[45]); + c = HH(c, d, a, b, M_offset_15, 16, T[46]); + b = HH(b, c, d, a, M_offset_2, 23, T[47]); + + a = II(a, b, c, d, M_offset_0, 6, T[48]); + d = II(d, a, b, c, M_offset_7, 10, T[49]); + c = II(c, d, a, b, M_offset_14, 15, T[50]); + b = II(b, c, d, a, M_offset_5, 21, T[51]); + a = II(a, b, c, d, M_offset_12, 6, T[52]); + d = II(d, a, b, c, M_offset_3, 10, T[53]); + c = II(c, d, a, b, M_offset_10, 15, T[54]); + b = II(b, c, d, a, M_offset_1, 21, T[55]); + a = II(a, b, c, d, M_offset_8, 6, T[56]); + d = II(d, a, b, c, M_offset_15, 10, T[57]); + c = II(c, d, a, b, M_offset_6, 15, T[58]); + b = II(b, c, d, a, M_offset_13, 21, T[59]); + a = II(a, b, c, d, M_offset_4, 6, T[60]); + d = II(d, a, b, c, M_offset_11, 10, T[61]); + c = II(c, d, a, b, M_offset_2, 15, T[62]); + b = II(b, c, d, a, M_offset_9, 21, T[63]); + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + + var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); + var nBitsTotalL = nBitsTotal; + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( + (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | + (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) + ); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | + (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) + ); + + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 4; i++) { + // Shortcut + var H_i = H[i]; + + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + function FF(a, b, c, d, x, s, t) { + var n = a + ((b & c) | (~b & d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function GG(a, b, c, d, x, s, t) { + var n = a + ((b & d) | (c & ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function HH(a, b, c, d, x, s, t) { + var n = a + (b ^ c ^ d) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function II(a, b, c, d, x, s, t) { + var n = a + (c ^ (b | ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ + C.MD5 = Hasher._createHelper(MD5); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ + C.HmacMD5 = Hasher._createHmacHelper(MD5); + }(Math)); + + + return CryptoJS.MD5; + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250186, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Reusable object + var W = []; + + /** + * SHA-1 hash algorithm. + */ + var SHA1 = C_algo.SHA1 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476, + 0xc3d2e1f0 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + + // Computation + for (var i = 0; i < 80; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = (n << 1) | (n >>> 31); + } + + var t = ((a << 5) | (a >>> 27)) + e + W[i]; + if (i < 20) { + t += ((b & c) | (~b & d)) + 0x5a827999; + } else if (i < 40) { + t += (b ^ c ^ d) + 0x6ed9eba1; + } else if (i < 60) { + t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; + } else /* if (i < 80) */ { + t += (b ^ c ^ d) - 0x359d3e2a; + } + + e = d; + d = c; + c = (b << 30) | (b >>> 2); + b = a; + a = t; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ + C.SHA1 = Hasher._createHelper(SHA1); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ + C.HmacSHA1 = Hasher._createHmacHelper(SHA1); + }()); + + + return CryptoJS.SHA1; + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250187, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Initialization and round constants tables + var H = []; + var K = []; + + // Compute constants + (function () { + function isPrime(n) { + var sqrtN = Math.sqrt(n); + for (var factor = 2; factor <= sqrtN; factor++) { + if (!(n % factor)) { + return false; + } + } + + return true; + } + + function getFractionalBits(n) { + return ((n - (n | 0)) * 0x100000000) | 0; + } + + var n = 2; + var nPrime = 0; + while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2)); + } + K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); + + nPrime++; + } + + n++; + } + }()); + + // Reusable object + var W = []; + + /** + * SHA-256 hash algorithm. + */ + var SHA256 = C_algo.SHA256 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init(H.slice(0)); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + var f = H[5]; + var g = H[6]; + var h = H[7]; + + // Computation + for (var i = 0; i < 64; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var gamma0x = W[i - 15]; + var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ + ((gamma0x << 14) | (gamma0x >>> 18)) ^ + (gamma0x >>> 3); + + var gamma1x = W[i - 2]; + var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ + ((gamma1x << 13) | (gamma1x >>> 19)) ^ + (gamma1x >>> 10); + + W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; + } + + var ch = (e & f) ^ (~e & g); + var maj = (a & b) ^ (a & c) ^ (b & c); + + var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); + var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); + + var t1 = h + sigma1 + ch + K[i] + W[i]; + var t2 = sigma0 + maj; + + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + H[5] = (H[5] + f) | 0; + H[6] = (H[6] + g) | 0; + H[7] = (H[7] + h) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ + C.SHA256 = Hasher._createHelper(SHA256); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ + C.HmacSHA256 = Hasher._createHmacHelper(SHA256); + }(Math)); + + + return CryptoJS.SHA256; + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250188, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha256")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha256"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA256 = C_algo.SHA256; + + /** + * SHA-224 hash algorithm. + */ + var SHA224 = C_algo.SHA224 = SHA256.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 + ]); + }, + + _doFinalize: function () { + var hash = SHA256._doFinalize.call(this); + + hash.sigBytes -= 4; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ + C.SHA224 = SHA256._createHelper(SHA224); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ + C.HmacSHA224 = SHA256._createHmacHelper(SHA224); + }()); + + + return CryptoJS.SHA224; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./sha256":1758332250187}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250189, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + + function X64Word_create() { + return X64Word.create.apply(X64Word, arguments); + } + + // Constants + var K = [ + X64Word_create(0x428a2f98, 0xd728ae22), X64Word_create(0x71374491, 0x23ef65cd), + X64Word_create(0xb5c0fbcf, 0xec4d3b2f), X64Word_create(0xe9b5dba5, 0x8189dbbc), + X64Word_create(0x3956c25b, 0xf348b538), X64Word_create(0x59f111f1, 0xb605d019), + X64Word_create(0x923f82a4, 0xaf194f9b), X64Word_create(0xab1c5ed5, 0xda6d8118), + X64Word_create(0xd807aa98, 0xa3030242), X64Word_create(0x12835b01, 0x45706fbe), + X64Word_create(0x243185be, 0x4ee4b28c), X64Word_create(0x550c7dc3, 0xd5ffb4e2), + X64Word_create(0x72be5d74, 0xf27b896f), X64Word_create(0x80deb1fe, 0x3b1696b1), + X64Word_create(0x9bdc06a7, 0x25c71235), X64Word_create(0xc19bf174, 0xcf692694), + X64Word_create(0xe49b69c1, 0x9ef14ad2), X64Word_create(0xefbe4786, 0x384f25e3), + X64Word_create(0x0fc19dc6, 0x8b8cd5b5), X64Word_create(0x240ca1cc, 0x77ac9c65), + X64Word_create(0x2de92c6f, 0x592b0275), X64Word_create(0x4a7484aa, 0x6ea6e483), + X64Word_create(0x5cb0a9dc, 0xbd41fbd4), X64Word_create(0x76f988da, 0x831153b5), + X64Word_create(0x983e5152, 0xee66dfab), X64Word_create(0xa831c66d, 0x2db43210), + X64Word_create(0xb00327c8, 0x98fb213f), X64Word_create(0xbf597fc7, 0xbeef0ee4), + X64Word_create(0xc6e00bf3, 0x3da88fc2), X64Word_create(0xd5a79147, 0x930aa725), + X64Word_create(0x06ca6351, 0xe003826f), X64Word_create(0x14292967, 0x0a0e6e70), + X64Word_create(0x27b70a85, 0x46d22ffc), X64Word_create(0x2e1b2138, 0x5c26c926), + X64Word_create(0x4d2c6dfc, 0x5ac42aed), X64Word_create(0x53380d13, 0x9d95b3df), + X64Word_create(0x650a7354, 0x8baf63de), X64Word_create(0x766a0abb, 0x3c77b2a8), + X64Word_create(0x81c2c92e, 0x47edaee6), X64Word_create(0x92722c85, 0x1482353b), + X64Word_create(0xa2bfe8a1, 0x4cf10364), X64Word_create(0xa81a664b, 0xbc423001), + X64Word_create(0xc24b8b70, 0xd0f89791), X64Word_create(0xc76c51a3, 0x0654be30), + X64Word_create(0xd192e819, 0xd6ef5218), X64Word_create(0xd6990624, 0x5565a910), + X64Word_create(0xf40e3585, 0x5771202a), X64Word_create(0x106aa070, 0x32bbd1b8), + X64Word_create(0x19a4c116, 0xb8d2d0c8), X64Word_create(0x1e376c08, 0x5141ab53), + X64Word_create(0x2748774c, 0xdf8eeb99), X64Word_create(0x34b0bcb5, 0xe19b48a8), + X64Word_create(0x391c0cb3, 0xc5c95a63), X64Word_create(0x4ed8aa4a, 0xe3418acb), + X64Word_create(0x5b9cca4f, 0x7763e373), X64Word_create(0x682e6ff3, 0xd6b2b8a3), + X64Word_create(0x748f82ee, 0x5defb2fc), X64Word_create(0x78a5636f, 0x43172f60), + X64Word_create(0x84c87814, 0xa1f0ab72), X64Word_create(0x8cc70208, 0x1a6439ec), + X64Word_create(0x90befffa, 0x23631e28), X64Word_create(0xa4506ceb, 0xde82bde9), + X64Word_create(0xbef9a3f7, 0xb2c67915), X64Word_create(0xc67178f2, 0xe372532b), + X64Word_create(0xca273ece, 0xea26619c), X64Word_create(0xd186b8c7, 0x21c0c207), + X64Word_create(0xeada7dd6, 0xcde0eb1e), X64Word_create(0xf57d4f7f, 0xee6ed178), + X64Word_create(0x06f067aa, 0x72176fba), X64Word_create(0x0a637dc5, 0xa2c898a6), + X64Word_create(0x113f9804, 0xbef90dae), X64Word_create(0x1b710b35, 0x131c471b), + X64Word_create(0x28db77f5, 0x23047d84), X64Word_create(0x32caab7b, 0x40c72493), + X64Word_create(0x3c9ebe0a, 0x15c9bebc), X64Word_create(0x431d67c4, 0x9c100d4c), + X64Word_create(0x4cc5d4be, 0xcb3e42b6), X64Word_create(0x597f299c, 0xfc657e2a), + X64Word_create(0x5fcb6fab, 0x3ad6faec), X64Word_create(0x6c44198c, 0x4a475817) + ]; + + // Reusable objects + var W = []; + (function () { + for (var i = 0; i < 80; i++) { + W[i] = X64Word_create(); + } + }()); + + /** + * SHA-512 hash algorithm. + */ + var SHA512 = C_algo.SHA512 = Hasher.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0x6a09e667, 0xf3bcc908), new X64Word.init(0xbb67ae85, 0x84caa73b), + new X64Word.init(0x3c6ef372, 0xfe94f82b), new X64Word.init(0xa54ff53a, 0x5f1d36f1), + new X64Word.init(0x510e527f, 0xade682d1), new X64Word.init(0x9b05688c, 0x2b3e6c1f), + new X64Word.init(0x1f83d9ab, 0xfb41bd6b), new X64Word.init(0x5be0cd19, 0x137e2179) + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var H = this._hash.words; + + var H0 = H[0]; + var H1 = H[1]; + var H2 = H[2]; + var H3 = H[3]; + var H4 = H[4]; + var H5 = H[5]; + var H6 = H[6]; + var H7 = H[7]; + + var H0h = H0.high; + var H0l = H0.low; + var H1h = H1.high; + var H1l = H1.low; + var H2h = H2.high; + var H2l = H2.low; + var H3h = H3.high; + var H3l = H3.low; + var H4h = H4.high; + var H4l = H4.low; + var H5h = H5.high; + var H5l = H5.low; + var H6h = H6.high; + var H6l = H6.low; + var H7h = H7.high; + var H7l = H7.low; + + // Working variables + var ah = H0h; + var al = H0l; + var bh = H1h; + var bl = H1l; + var ch = H2h; + var cl = H2l; + var dh = H3h; + var dl = H3l; + var eh = H4h; + var el = H4l; + var fh = H5h; + var fl = H5l; + var gh = H6h; + var gl = H6l; + var hh = H7h; + var hl = H7l; + + // Rounds + for (var i = 0; i < 80; i++) { + var Wil; + var Wih; + + // Shortcut + var Wi = W[i]; + + // Extend message + if (i < 16) { + Wih = Wi.high = M[offset + i * 2] | 0; + Wil = Wi.low = M[offset + i * 2 + 1] | 0; + } else { + // Gamma0 + var gamma0x = W[i - 15]; + var gamma0xh = gamma0x.high; + var gamma0xl = gamma0x.low; + var gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7); + var gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); + + // Gamma1 + var gamma1x = W[i - 2]; + var gamma1xh = gamma1x.high; + var gamma1xl = gamma1x.low; + var gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6); + var gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); + + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + var Wi7 = W[i - 7]; + var Wi7h = Wi7.high; + var Wi7l = Wi7.low; + + var Wi16 = W[i - 16]; + var Wi16h = Wi16.high; + var Wi16l = Wi16.low; + + Wil = gamma0l + Wi7l; + Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); + Wil = Wil + gamma1l; + Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); + Wil = Wil + Wi16l; + Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); + + Wi.high = Wih; + Wi.low = Wil; + } + + var chh = (eh & fh) ^ (~eh & gh); + var chl = (el & fl) ^ (~el & gl); + var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); + var majl = (al & bl) ^ (al & cl) ^ (bl & cl); + + var sigma0h = ((ah >>> 28) | (al << 4)) ^ ((ah << 30) | (al >>> 2)) ^ ((ah << 25) | (al >>> 7)); + var sigma0l = ((al >>> 28) | (ah << 4)) ^ ((al << 30) | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7)); + var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9)); + var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9)); + + // t1 = h + sigma1 + ch + K[i] + W[i] + var Ki = K[i]; + var Kih = Ki.high; + var Kil = Ki.low; + + var t1l = hl + sigma1l; + var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); + var t1l = t1l + chl; + var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); + var t1l = t1l + Kil; + var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); + var t1l = t1l + Wil; + var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); + + // t2 = sigma0 + maj + var t2l = sigma0l + majl; + var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); + + // Update working variables + hh = gh; + hl = gl; + gh = fh; + gl = fl; + fh = eh; + fl = el; + el = (dl + t1l) | 0; + eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; + dh = ch; + dl = cl; + ch = bh; + cl = bl; + bh = ah; + bl = al; + al = (t1l + t2l) | 0; + ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; + } + + // Intermediate hash value + H0l = H0.low = (H0l + al); + H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); + H1l = H1.low = (H1l + bl); + H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); + H2l = H2.low = (H2l + cl); + H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); + H3l = H3.low = (H3l + dl); + H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); + H4l = H4.low = (H4l + el); + H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); + H5l = H5.low = (H5l + fl); + H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); + H6l = H6.low = (H6l + gl); + H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); + H7l = H7.low = (H7l + hl); + H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Convert hash to 32-bit word array before returning + var hash = this._hash.toX32(); + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + }, + + blockSize: 1024/32 + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ + C.SHA512 = Hasher._createHelper(SHA512); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ + C.HmacSHA512 = Hasher._createHmacHelper(SHA512); + }()); + + + return CryptoJS.SHA512; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./x64-core":1758332250180}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250190, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./sha512"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + var SHA512 = C_algo.SHA512; + + /** + * SHA-384 hash algorithm. + */ + var SHA384 = C_algo.SHA384 = SHA512.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0xcbbb9d5d, 0xc1059ed8), new X64Word.init(0x629a292a, 0x367cd507), + new X64Word.init(0x9159015a, 0x3070dd17), new X64Word.init(0x152fecd8, 0xf70e5939), + new X64Word.init(0x67332667, 0xffc00b31), new X64Word.init(0x8eb44a87, 0x68581511), + new X64Word.init(0xdb0c2e0d, 0x64f98fa7), new X64Word.init(0x47b5481d, 0xbefa4fa4) + ]); + }, + + _doFinalize: function () { + var hash = SHA512._doFinalize.call(this); + + hash.sigBytes -= 16; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ + C.SHA384 = SHA512._createHelper(SHA384); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ + C.HmacSHA384 = SHA512._createHmacHelper(SHA384); + }()); + + + return CryptoJS.SHA384; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./x64-core":1758332250180,"./sha512":1758332250189}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250191, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var C_algo = C.algo; + + // Constants tables + var RHO_OFFSETS = []; + var PI_INDEXES = []; + var ROUND_CONSTANTS = []; + + // Compute Constants + (function () { + // Compute rho offset constants + var x = 1, y = 0; + for (var t = 0; t < 24; t++) { + RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64; + + var newX = y % 5; + var newY = (2 * x + 3 * y) % 5; + x = newX; + y = newY; + } + + // Compute pi index constants + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; + } + } + + // Compute round constants + var LFSR = 0x01; + for (var i = 0; i < 24; i++) { + var roundConstantMsw = 0; + var roundConstantLsw = 0; + + for (var j = 0; j < 7; j++) { + if (LFSR & 0x01) { + var bitPosition = (1 << j) - 1; + if (bitPosition < 32) { + roundConstantLsw ^= 1 << bitPosition; + } else /* if (bitPosition >= 32) */ { + roundConstantMsw ^= 1 << (bitPosition - 32); + } + } + + // Compute next LFSR + if (LFSR & 0x80) { + // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 + LFSR = (LFSR << 1) ^ 0x71; + } else { + LFSR <<= 1; + } + } + + ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); + } + }()); + + // Reusable objects for temporary values + var T = []; + (function () { + for (var i = 0; i < 25; i++) { + T[i] = X64Word.create(); + } + }()); + + /** + * SHA-3 hash algorithm. + */ + var SHA3 = C_algo.SHA3 = Hasher.extend({ + /** + * Configuration options. + * + * @property {number} outputLength + * The desired number of bits in the output hash. + * Only values permitted are: 224, 256, 384, 512. + * Default: 512 + */ + cfg: Hasher.cfg.extend({ + outputLength: 512 + }), + + _doReset: function () { + var state = this._state = [] + for (var i = 0; i < 25; i++) { + state[i] = new X64Word.init(); + } + + this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var state = this._state; + var nBlockSizeLanes = this.blockSize / 2; + + // Absorb + for (var i = 0; i < nBlockSizeLanes; i++) { + // Shortcuts + var M2i = M[offset + 2 * i]; + var M2i1 = M[offset + 2 * i + 1]; + + // Swap endian + M2i = ( + (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) | + (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00) + ); + M2i1 = ( + (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) | + (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00) + ); + + // Absorb message into state + var lane = state[i]; + lane.high ^= M2i1; + lane.low ^= M2i; + } + + // Rounds + for (var round = 0; round < 24; round++) { + // Theta + for (var x = 0; x < 5; x++) { + // Mix column lanes + var tMsw = 0, tLsw = 0; + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + tMsw ^= lane.high; + tLsw ^= lane.low; + } + + // Temporary values + var Tx = T[x]; + Tx.high = tMsw; + Tx.low = tLsw; + } + for (var x = 0; x < 5; x++) { + // Shortcuts + var Tx4 = T[(x + 4) % 5]; + var Tx1 = T[(x + 1) % 5]; + var Tx1Msw = Tx1.high; + var Tx1Lsw = Tx1.low; + + // Mix surrounding columns + var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); + var tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + lane.high ^= tMsw; + lane.low ^= tLsw; + } + } + + // Rho Pi + for (var laneIndex = 1; laneIndex < 25; laneIndex++) { + var tMsw; + var tLsw; + + // Shortcuts + var lane = state[laneIndex]; + var laneMsw = lane.high; + var laneLsw = lane.low; + var rhoOffset = RHO_OFFSETS[laneIndex]; + + // Rotate lanes + if (rhoOffset < 32) { + tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); + tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); + } else /* if (rhoOffset >= 32) */ { + tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); + tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); + } + + // Transpose lanes + var TPiLane = T[PI_INDEXES[laneIndex]]; + TPiLane.high = tMsw; + TPiLane.low = tLsw; + } + + // Rho pi at x = y = 0 + var T0 = T[0]; + var state0 = state[0]; + T0.high = state0.high; + T0.low = state0.low; + + // Chi + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + // Shortcuts + var laneIndex = x + 5 * y; + var lane = state[laneIndex]; + var TLane = T[laneIndex]; + var Tx1Lane = T[((x + 1) % 5) + 5 * y]; + var Tx2Lane = T[((x + 2) % 5) + 5 * y]; + + // Mix rows + lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); + lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); + } + } + + // Iota + var lane = state[0]; + var roundConstant = ROUND_CONSTANTS[round]; + lane.high ^= roundConstant.high; + lane.low ^= roundConstant.low; + } + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + var blockSizeBits = this.blockSize * 32; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32); + dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var state = this._state; + var outputLengthBytes = this.cfg.outputLength / 8; + var outputLengthLanes = outputLengthBytes / 8; + + // Squeeze + var hashWords = []; + for (var i = 0; i < outputLengthLanes; i++) { + // Shortcuts + var lane = state[i]; + var laneMsw = lane.high; + var laneLsw = lane.low; + + // Swap endian + laneMsw = ( + (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) | + (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00) + ); + laneLsw = ( + (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) | + (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00) + ); + + // Squeeze state to retrieve hash + hashWords.push(laneLsw); + hashWords.push(laneMsw); + } + + // Return final computed hash + return new WordArray.init(hashWords, outputLengthBytes); + }, + + clone: function () { + var clone = Hasher.clone.call(this); + + var state = clone._state = this._state.slice(0); + for (var i = 0; i < 25; i++) { + state[i] = state[i].clone(); + } + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ + C.SHA3 = Hasher._createHelper(SHA3); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ + C.HmacSHA3 = Hasher._createHmacHelper(SHA3); + }(Math)); + + + return CryptoJS.SHA3; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./x64-core":1758332250180}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250192, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** @preserve + (c) 2012 by Cédric Mesnil. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var _zl = WordArray.create([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]); + var _zr = WordArray.create([ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]); + var _sl = WordArray.create([ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]); + var _sr = WordArray.create([ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]); + + var _hl = WordArray.create([ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]); + var _hr = WordArray.create([ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]); + + /** + * RIPEMD160 hash algorithm. + */ + var RIPEMD160 = C_algo.RIPEMD160 = Hasher.extend({ + _doReset: function () { + this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]); + }, + + _doProcessBlock: function (M, offset) { + + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + // Swap + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + // Shortcut + var H = this._hash.words; + var hl = _hl.words; + var hr = _hr.words; + var zl = _zl.words; + var zr = _zr.words; + var sl = _sl.words; + var sr = _sr.words; + + // Working variables + var al, bl, cl, dl, el; + var ar, br, cr, dr, er; + + ar = al = H[0]; + br = bl = H[1]; + cr = cl = H[2]; + dr = dl = H[3]; + er = el = H[4]; + // Computation + var t; + for (var i = 0; i < 80; i += 1) { + t = (al + M[offset+zl[i]])|0; + if (i<16){ + t += f1(bl,cl,dl) + hl[0]; + } else if (i<32) { + t += f2(bl,cl,dl) + hl[1]; + } else if (i<48) { + t += f3(bl,cl,dl) + hl[2]; + } else if (i<64) { + t += f4(bl,cl,dl) + hl[3]; + } else {// if (i<80) { + t += f5(bl,cl,dl) + hl[4]; + } + t = t|0; + t = rotl(t,sl[i]); + t = (t+el)|0; + al = el; + el = dl; + dl = rotl(cl, 10); + cl = bl; + bl = t; + + t = (ar + M[offset+zr[i]])|0; + if (i<16){ + t += f5(br,cr,dr) + hr[0]; + } else if (i<32) { + t += f4(br,cr,dr) + hr[1]; + } else if (i<48) { + t += f3(br,cr,dr) + hr[2]; + } else if (i<64) { + t += f2(br,cr,dr) + hr[3]; + } else {// if (i<80) { + t += f1(br,cr,dr) + hr[4]; + } + t = t|0; + t = rotl(t,sr[i]) ; + t = (t+er)|0; + ar = er; + er = dr; + dr = rotl(cr, 10); + cr = br; + br = t; + } + // Intermediate hash value + t = (H[1] + cl + dr)|0; + H[1] = (H[2] + dl + er)|0; + H[2] = (H[3] + el + ar)|0; + H[3] = (H[4] + al + br)|0; + H[4] = (H[0] + bl + cr)|0; + H[0] = t; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) | + (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) + ); + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 5; i++) { + // Shortcut + var H_i = H[i]; + + // Swap + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + + function f1(x, y, z) { + return ((x) ^ (y) ^ (z)); + + } + + function f2(x, y, z) { + return (((x)&(y)) | ((~x)&(z))); + } + + function f3(x, y, z) { + return (((x) | (~(y))) ^ (z)); + } + + function f4(x, y, z) { + return (((x) & (z)) | ((y)&(~(z)))); + } + + function f5(x, y, z) { + return ((x) ^ ((y) |(~(z)))); + + } + + function rotl(x,n) { + return (x<>>(32-n)); + } + + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ + C.RIPEMD160 = Hasher._createHelper(RIPEMD160); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ + C.HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160); + }(Math)); + + + return CryptoJS.RIPEMD160; + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250193, function(require, module, exports) { +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var C_algo = C.algo; + + /** + * HMAC algorithm. + */ + var HMAC = C_algo.HMAC = Base.extend({ + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} hasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + init: function (hasher, key) { + // Init hasher + hasher = this._hasher = new hasher.init(); + + // Convert string to WordArray, else assume WordArray already + if (typeof key == 'string') { + key = Utf8.parse(key); + } + + // Shortcuts + var hasherBlockSize = hasher.blockSize; + var hasherBlockSizeBytes = hasherBlockSize * 4; + + // Allow arbitrary length keys + if (key.sigBytes > hasherBlockSizeBytes) { + key = hasher.finalize(key); + } + + // Clamp excess bits + key.clamp(); + + // Clone key for inner and outer pads + var oKey = this._oKey = key.clone(); + var iKey = this._iKey = key.clone(); + + // Shortcuts + var oKeyWords = oKey.words; + var iKeyWords = iKey.words; + + // XOR keys with pad constants + for (var i = 0; i < hasherBlockSize; i++) { + oKeyWords[i] ^= 0x5c5c5c5c; + iKeyWords[i] ^= 0x36363636; + } + oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes; + + // Set initial values + this.reset(); + }, + + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset: function () { + // Shortcut + var hasher = this._hasher; + + // Reset + hasher.reset(); + hasher.update(this._iKey); + }, + + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update: function (messageUpdate) { + this._hasher.update(messageUpdate); + + // Chainable + return this; + }, + + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Shortcut + var hasher = this._hasher; + + // Compute HMAC + var innerHash = hasher.finalize(messageUpdate); + hasher.reset(); + var hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); + + return hmac; + } + }); + }()); + + +})); +}, function(modId) { var map = {"./core":1758332250179}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250194, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha256", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA256 = C_algo.SHA256; + var HMAC = C_algo.HMAC; + + /** + * Password-Based Key Derivation Function 2 algorithm. + */ + var PBKDF2 = C_algo.PBKDF2 = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hasher to use. Default: SHA256 + * @property {number} iterations The number of iterations to perform. Default: 250000 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: SHA256, + iterations: 250000 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.PBKDF2.create(); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + // Shortcut + var cfg = this.cfg; + + // Init HMAC + var hmac = HMAC.create(cfg.hasher, password); + + // Initial values + var derivedKey = WordArray.create(); + var blockIndex = WordArray.create([0x00000001]); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var blockIndexWords = blockIndex.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + var block = hmac.update(salt).finalize(blockIndex); + hmac.reset(); + + // Shortcuts + var blockWords = block.words; + var blockWordsLength = blockWords.length; + + // Iterations + var intermediate = block; + for (var i = 1; i < iterations; i++) { + intermediate = hmac.finalize(intermediate); + hmac.reset(); + + // Shortcut + var intermediateWords = intermediate.words; + + // XOR intermediate with block + for (var j = 0; j < blockWordsLength; j++) { + blockWords[j] ^= intermediateWords[j]; + } + } + + derivedKey.concat(block); + blockIndexWords[0]++; + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.PBKDF2 = function (password, salt, cfg) { + return PBKDF2.create(cfg).compute(password, salt); + }; + }()); + + + return CryptoJS.PBKDF2; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./sha256":1758332250187,"./hmac":1758332250193}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250195, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha1", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var MD5 = C_algo.MD5; + + /** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ + var EvpKDF = C_algo.EvpKDF = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hash algorithm to use. Default: MD5 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: MD5, + iterations: 1 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.EvpKDF.create(); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + var block; + + // Shortcut + var cfg = this.cfg; + + // Init hasher + var hasher = cfg.hasher.create(); + + // Initial values + var derivedKey = WordArray.create(); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + if (block) { + hasher.update(block); + } + block = hasher.update(password).finalize(salt); + hasher.reset(); + + // Iterations + for (var i = 1; i < iterations; i++) { + block = hasher.finalize(block); + hasher.reset(); + } + + derivedKey.concat(block); + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.EvpKDF = function (password, salt, cfg) { + return EvpKDF.create(cfg).compute(password, salt); + }; + }()); + + + return CryptoJS.EvpKDF; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./sha1":1758332250186,"./hmac":1758332250193}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250196, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./evpkdf")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./evpkdf"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Cipher core components. + */ + CryptoJS.lib.Cipher || (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var Base64 = C_enc.Base64; + var C_algo = C.algo; + var EvpKDF = C_algo.EvpKDF; + + /** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ + var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + cfg: Base.extend(), + + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + createEncryptor: function (key, cfg) { + return this.create(this._ENC_XFORM_MODE, key, cfg); + }, + + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + createDecryptor: function (key, cfg) { + return this.create(this._DEC_XFORM_MODE, key, cfg); + }, + + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }); + */ + init: function (xformMode, key, cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Store transform mode and key + this._xformMode = xformMode; + this._key = key; + + // Set initial values + this.reset(); + }, + + /** + * Resets this cipher to its initial state. + * + * @example + * + * cipher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-cipher logic + this._doReset(); + }, + + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * var encrypted = cipher.process('data'); + * var encrypted = cipher.process(wordArray); + */ + process: function (dataUpdate) { + // Append + this._append(dataUpdate); + + // Process available blocks + return this._process(); + }, + + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * var encrypted = cipher.finalize(); + * var encrypted = cipher.finalize('data'); + * var encrypted = cipher.finalize(wordArray); + */ + finalize: function (dataUpdate) { + // Final data update + if (dataUpdate) { + this._append(dataUpdate); + } + + // Perform concrete-cipher logic + var finalProcessedData = this._doFinalize(); + + return finalProcessedData; + }, + + keySize: 128/32, + + ivSize: 128/32, + + _ENC_XFORM_MODE: 1, + + _DEC_XFORM_MODE: 2, + + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + _createHelper: (function () { + function selectCipherStrategy(key) { + if (typeof key == 'string') { + return PasswordBasedCipher; + } else { + return SerializableCipher; + } + } + + return function (cipher) { + return { + encrypt: function (message, key, cfg) { + return selectCipherStrategy(key).encrypt(cipher, message, key, cfg); + }, + + decrypt: function (ciphertext, key, cfg) { + return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg); + } + }; + }; + }()) + }); + + /** + * Abstract base stream cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ + var StreamCipher = C_lib.StreamCipher = Cipher.extend({ + _doFinalize: function () { + // Process partial blocks + var finalProcessedBlocks = this._process(!!'flush'); + + return finalProcessedBlocks; + }, + + blockSize: 1 + }); + + /** + * Mode namespace. + */ + var C_mode = C.mode = {}; + + /** + * Abstract base block cipher mode template. + */ + var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({ + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + createEncryptor: function (cipher, iv) { + return this.Encryptor.create(cipher, iv); + }, + + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + createDecryptor: function (cipher, iv) { + return this.Decryptor.create(cipher, iv); + }, + + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + init: function (cipher, iv) { + this._cipher = cipher; + this._iv = iv; + } + }); + + /** + * Cipher Block Chaining mode. + */ + var CBC = C_mode.CBC = (function () { + /** + * Abstract base CBC mode. + */ + var CBC = BlockCipherMode.extend(); + + /** + * CBC encryptor. + */ + CBC.Encryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // XOR and encrypt + xorBlock.call(this, words, offset, blockSize); + cipher.encryptBlock(words, offset); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + /** + * CBC decryptor. + */ + CBC.Decryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + // Decrypt and XOR + cipher.decryptBlock(words, offset); + xorBlock.call(this, words, offset, blockSize); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function xorBlock(words, offset, blockSize) { + var block; + + // Shortcut + var iv = this._iv; + + // Choose mixing block + if (iv) { + block = iv; + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + block = this._prevBlock; + } + + // XOR blocks + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= block[i]; + } + } + + return CBC; + }()); + + /** + * Padding namespace. + */ + var C_pad = C.pad = {}; + + /** + * PKCS #5/7 padding strategy. + */ + var Pkcs7 = C_pad.Pkcs7 = { + /** + * Pads data using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to pad. + * @param {number} blockSize The multiple that the data should be padded to. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.pad(wordArray, 4); + */ + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Create padding word + var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes; + + // Create padding + var paddingWords = []; + for (var i = 0; i < nPaddingBytes; i += 4) { + paddingWords.push(paddingWord); + } + var padding = WordArray.create(paddingWords, nPaddingBytes); + + // Add padding + data.concat(padding); + }, + + /** + * Unpads data that had been padded using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to unpad. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.unpad(wordArray); + */ + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + /** + * Abstract base block cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ + var BlockCipher = C_lib.BlockCipher = Cipher.extend({ + /** + * Configuration options. + * + * @property {Mode} mode The block mode to use. Default: CBC + * @property {Padding} padding The padding strategy to use. Default: Pkcs7 + */ + cfg: Cipher.cfg.extend({ + mode: CBC, + padding: Pkcs7 + }), + + reset: function () { + var modeCreator; + + // Reset cipher + Cipher.reset.call(this); + + // Shortcuts + var cfg = this.cfg; + var iv = cfg.iv; + var mode = cfg.mode; + + // Reset block mode + if (this._xformMode == this._ENC_XFORM_MODE) { + modeCreator = mode.createEncryptor; + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + modeCreator = mode.createDecryptor; + // Keep at least one block in the buffer for unpadding + this._minBufferSize = 1; + } + + if (this._mode && this._mode.__creator == modeCreator) { + this._mode.init(this, iv && iv.words); + } else { + this._mode = modeCreator.call(mode, this, iv && iv.words); + this._mode.__creator = modeCreator; + } + }, + + _doProcessBlock: function (words, offset) { + this._mode.processBlock(words, offset); + }, + + _doFinalize: function () { + var finalProcessedBlocks; + + // Shortcut + var padding = this.cfg.padding; + + // Finalize + if (this._xformMode == this._ENC_XFORM_MODE) { + // Pad data + padding.pad(this._data, this.blockSize); + + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + // Process final blocks + finalProcessedBlocks = this._process(!!'flush'); + + // Unpad data + padding.unpad(finalProcessedBlocks); + } + + return finalProcessedBlocks; + }, + + blockSize: 128/32 + }); + + /** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string. + */ + var CipherParams = C_lib.CipherParams = Base.extend({ + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + init: function (cipherParams) { + this.mixIn(cipherParams); + }, + + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString: function (formatter) { + return (formatter || this.formatter).stringify(this); + } + }); + + /** + * Format namespace. + */ + var C_format = C.format = {}; + + /** + * OpenSSL formatting strategy. + */ + var OpenSSLFormatter = C_format.OpenSSL = { + /** + * Converts a cipher params object to an OpenSSL-compatible string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The OpenSSL-compatible string. + * + * @static + * + * @example + * + * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); + */ + stringify: function (cipherParams) { + var wordArray; + + // Shortcuts + var ciphertext = cipherParams.ciphertext; + var salt = cipherParams.salt; + + // Format + if (salt) { + wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); + } else { + wordArray = ciphertext; + } + + return wordArray.toString(Base64); + }, + + /** + * Converts an OpenSSL-compatible string to a cipher params object. + * + * @param {string} openSSLStr The OpenSSL-compatible string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); + */ + parse: function (openSSLStr) { + var salt; + + // Parse base64 + var ciphertext = Base64.parse(openSSLStr); + + // Shortcut + var ciphertextWords = ciphertext.words; + + // Test for salt + if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) { + // Extract salt + salt = WordArray.create(ciphertextWords.slice(2, 4)); + + // Remove salt from ciphertext + ciphertextWords.splice(0, 4); + ciphertext.sigBytes -= 16; + } + + return CipherParams.create({ ciphertext: ciphertext, salt: salt }); + } + }; + + /** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ + var SerializableCipher = C_lib.SerializableCipher = Base.extend({ + /** + * Configuration options. + * + * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL + */ + cfg: Base.extend({ + format: OpenSSLFormatter + }), + + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Encrypt + var encryptor = cipher.createEncryptor(key, cfg); + var ciphertext = encryptor.finalize(message); + + // Shortcut + var cipherCfg = encryptor.cfg; + + // Create and return serializable cipher params + return CipherParams.create({ + ciphertext: ciphertext, + key: key, + iv: cipherCfg.iv, + algorithm: cipher, + mode: cipherCfg.mode, + padding: cipherCfg.padding, + blockSize: cipher.blockSize, + formatter: cfg.format + }); + }, + + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Decrypt + var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext); + + return plaintext; + }, + + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); + */ + _parse: function (ciphertext, format) { + if (typeof ciphertext == 'string') { + return format.parse(ciphertext, this); + } else { + return ciphertext; + } + } + }); + + /** + * Key derivation function namespace. + */ + var C_kdf = C.kdf = {}; + + /** + * OpenSSL key derivation function. + */ + var OpenSSLKdf = C_kdf.OpenSSL = { + /** + * Derives a key and IV from a password. + * + * @param {string} password The password to derive from. + * @param {number} keySize The size in words of the key to generate. + * @param {number} ivSize The size in words of the IV to generate. + * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. + * + * @return {CipherParams} A cipher params object with the key, IV, and salt. + * + * @static + * + * @example + * + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); + */ + execute: function (password, keySize, ivSize, salt, hasher) { + // Generate random salt + if (!salt) { + salt = WordArray.random(64/8); + } + + // Derive key and IV + if (!hasher) { + var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt); + } else { + var key = EvpKDF.create({ keySize: keySize + ivSize, hasher: hasher }).compute(password, salt); + } + + + // Separate key and IV + var iv = WordArray.create(key.words.slice(keySize), ivSize * 4); + key.sigBytes = keySize * 4; + + // Return params + return CipherParams.create({ key: key, iv: iv, salt: salt }); + } + }; + + /** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ + var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({ + /** + * Configuration options. + * + * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL + */ + cfg: SerializableCipher.cfg.extend({ + kdf: OpenSSLKdf + }), + + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, cfg.salt, cfg.hasher); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Encrypt + var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg); + + // Mix in derived params + ciphertext.mixIn(derivedParams); + + return ciphertext; + }, + + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt, cfg.hasher); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Decrypt + var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg); + + return plaintext; + } + }); + }()); + + +})); +}, function(modId) { var map = {"./core":1758332250179,"./evpkdf":1758332250195}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250197, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Cipher Feedback block mode. + */ + CryptoJS.mode.CFB = (function () { + var CFB = CryptoJS.lib.BlockCipherMode.extend(); + + CFB.Encryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + CFB.Decryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { + var keystream; + + // Shortcut + var iv = this._iv; + + // Generate keystream + if (iv) { + keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + keystream = this._prevBlock; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + + return CFB; + }()); + + + return CryptoJS.mode.CFB; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250198, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Counter block mode. + */ + CryptoJS.mode.CTR = (function () { + var CTR = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = CTR.Encryptor = CTR.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Increment counter + counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0 + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTR.Decryptor = Encryptor; + + return CTR; + }()); + + + return CryptoJS.mode.CTR; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250199, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ + CryptoJS.mode.CTRGladman = (function () { + var CTRGladman = CryptoJS.lib.BlockCipherMode.extend(); + + function incWord(word) + { + if (((word >> 24) & 0xff) === 0xff) { //overflow + var b1 = (word >> 16)&0xff; + var b2 = (word >> 8)&0xff; + var b3 = word & 0xff; + + if (b1 === 0xff) // overflow b1 + { + b1 = 0; + if (b2 === 0xff) + { + b2 = 0; + if (b3 === 0xff) + { + b3 = 0; + } + else + { + ++b3; + } + } + else + { + ++b2; + } + } + else + { + ++b1; + } + + word = 0; + word += (b1 << 16); + word += (b2 << 8); + word += b3; + } + else + { + word += (0x01 << 24); + } + return word; + } + + function incCounter(counter) + { + if ((counter[0] = incWord(counter[0])) === 0) + { + // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 + counter[1] = incWord(counter[1]); + } + return counter; + } + + var Encryptor = CTRGladman.Encryptor = CTRGladman.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + + incCounter(counter); + + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTRGladman.Decryptor = Encryptor; + + return CTRGladman; + }()); + + + + + return CryptoJS.mode.CTRGladman; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250200, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Output Feedback block mode. + */ + CryptoJS.mode.OFB = (function () { + var OFB = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = OFB.Encryptor = OFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var keystream = this._keystream; + + // Generate keystream + if (iv) { + keystream = this._keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + OFB.Decryptor = Encryptor; + + return OFB; + }()); + + + return CryptoJS.mode.OFB; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250201, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Electronic Codebook block mode. + */ + CryptoJS.mode.ECB = (function () { + var ECB = CryptoJS.lib.BlockCipherMode.extend(); + + ECB.Encryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.encryptBlock(words, offset); + } + }); + + ECB.Decryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.decryptBlock(words, offset); + } + }); + + return ECB; + }()); + + + return CryptoJS.mode.ECB; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250202, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * ANSI X.923 padding strategy. + */ + CryptoJS.pad.AnsiX923 = { + pad: function (data, blockSize) { + // Shortcuts + var dataSigBytes = data.sigBytes; + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes; + + // Compute last byte position + var lastBytePos = dataSigBytes + nPaddingBytes - 1; + + // Pad + data.clamp(); + data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); + data.sigBytes += nPaddingBytes; + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + return CryptoJS.pad.Ansix923; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250203, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * ISO 10126 padding strategy. + */ + CryptoJS.pad.Iso10126 = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Pad + data.concat(CryptoJS.lib.WordArray.random(nPaddingBytes - 1)). + concat(CryptoJS.lib.WordArray.create([nPaddingBytes << 24], 1)); + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + return CryptoJS.pad.Iso10126; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250204, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * ISO/IEC 9797-1 Padding Method 2. + */ + CryptoJS.pad.Iso97971 = { + pad: function (data, blockSize) { + // Add 0x80 byte + data.concat(CryptoJS.lib.WordArray.create([0x80000000], 1)); + + // Zero pad the rest + CryptoJS.pad.ZeroPadding.pad(data, blockSize); + }, + + unpad: function (data) { + // Remove zero padding + CryptoJS.pad.ZeroPadding.unpad(data); + + // Remove one more byte -- the 0x80 byte + data.sigBytes--; + } + }; + + + return CryptoJS.pad.Iso97971; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250205, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Zero padding strategy. + */ + CryptoJS.pad.ZeroPadding = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Pad + data.clamp(); + data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); + }, + + unpad: function (data) { + // Shortcut + var dataWords = data.words; + + // Unpad + var i = data.sigBytes - 1; + for (var i = data.sigBytes - 1; i >= 0; i--) { + if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { + data.sigBytes = i + 1; + break; + } + } + } + }; + + + return CryptoJS.pad.ZeroPadding; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250206, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * A noop padding strategy. + */ + CryptoJS.pad.NoPadding = { + pad: function () { + }, + + unpad: function () { + } + }; + + + return CryptoJS.pad.NoPadding; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250207, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var CipherParams = C_lib.CipherParams; + var C_enc = C.enc; + var Hex = C_enc.Hex; + var C_format = C.format; + + var HexFormatter = C_format.Hex = { + /** + * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The hexadecimally encoded string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.format.Hex.stringify(cipherParams); + */ + stringify: function (cipherParams) { + return cipherParams.ciphertext.toString(Hex); + }, + + /** + * Converts a hexadecimally encoded ciphertext string to a cipher params object. + * + * @param {string} input The hexadecimally encoded string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.Hex.parse(hexString); + */ + parse: function (input) { + var ciphertext = Hex.parse(input); + return CipherParams.create({ ciphertext: ciphertext }); + } + }; + }()); + + + return CryptoJS.format.Hex; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250208, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Lookup tables + var SBOX = []; + var INV_SBOX = []; + var SUB_MIX_0 = []; + var SUB_MIX_1 = []; + var SUB_MIX_2 = []; + var SUB_MIX_3 = []; + var INV_SUB_MIX_0 = []; + var INV_SUB_MIX_1 = []; + var INV_SUB_MIX_2 = []; + var INV_SUB_MIX_3 = []; + + // Compute lookup tables + (function () { + // Compute double table + var d = []; + for (var i = 0; i < 256; i++) { + if (i < 128) { + d[i] = i << 1; + } else { + d[i] = (i << 1) ^ 0x11b; + } + } + + // Walk GF(2^8) + var x = 0; + var xi = 0; + for (var i = 0; i < 256; i++) { + // Compute sbox + var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; + SBOX[x] = sx; + INV_SBOX[sx] = x; + + // Compute multiplication + var x2 = d[x]; + var x4 = d[x2]; + var x8 = d[x4]; + + // Compute sub bytes, mix columns tables + var t = (d[sx] * 0x101) ^ (sx * 0x1010100); + SUB_MIX_0[x] = (t << 24) | (t >>> 8); + SUB_MIX_1[x] = (t << 16) | (t >>> 16); + SUB_MIX_2[x] = (t << 8) | (t >>> 24); + SUB_MIX_3[x] = t; + + // Compute inv sub bytes, inv mix columns tables + var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); + INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); + INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); + INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); + INV_SUB_MIX_3[sx] = t; + + // Compute next counter + if (!x) { + x = xi = 1; + } else { + x = x2 ^ d[d[d[x8 ^ x2]]]; + xi ^= d[d[xi]]; + } + } + }()); + + // Precomputed Rcon lookup + var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; + + /** + * AES block cipher algorithm. + */ + var AES = C_algo.AES = BlockCipher.extend({ + _doReset: function () { + var t; + + // Skip reset of nRounds has been set before and key did not change + if (this._nRounds && this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + var key = this._keyPriorReset = this._key; + var keyWords = key.words; + var keySize = key.sigBytes / 4; + + // Compute number of rounds + var nRounds = this._nRounds = keySize + 6; + + // Compute number of key schedule rows + var ksRows = (nRounds + 1) * 4; + + // Compute key schedule + var keySchedule = this._keySchedule = []; + for (var ksRow = 0; ksRow < ksRows; ksRow++) { + if (ksRow < keySize) { + keySchedule[ksRow] = keyWords[ksRow]; + } else { + t = keySchedule[ksRow - 1]; + + if (!(ksRow % keySize)) { + // Rot word + t = (t << 8) | (t >>> 24); + + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + + // Mix Rcon + t ^= RCON[(ksRow / keySize) | 0] << 24; + } else if (keySize > 6 && ksRow % keySize == 4) { + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + } + + keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; + } + } + + // Compute inv key schedule + var invKeySchedule = this._invKeySchedule = []; + for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) { + var ksRow = ksRows - invKsRow; + + if (invKsRow % 4) { + var t = keySchedule[ksRow]; + } else { + var t = keySchedule[ksRow - 4]; + } + + if (invKsRow < 4 || ksRow <= 4) { + invKeySchedule[invKsRow] = t; + } else { + invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^ + INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]]; + } + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX); + }, + + decryptBlock: function (M, offset) { + // Swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + + this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX); + + // Inv swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + }, + + _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { + // Shortcut + var nRounds = this._nRounds; + + // Get input, add round key + var s0 = M[offset] ^ keySchedule[0]; + var s1 = M[offset + 1] ^ keySchedule[1]; + var s2 = M[offset + 2] ^ keySchedule[2]; + var s3 = M[offset + 3] ^ keySchedule[3]; + + // Key schedule row counter + var ksRow = 4; + + // Rounds + for (var round = 1; round < nRounds; round++) { + // Shift rows, sub bytes, mix columns, add round key + var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++]; + var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++]; + var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++]; + var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++]; + + // Update state + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + // Shift rows, sub bytes, add round key + var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]; + var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]; + var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]; + var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]; + + // Set output + M[offset] = t0; + M[offset + 1] = t1; + M[offset + 2] = t2; + M[offset + 3] = t3; + }, + + keySize: 256/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ + C.AES = BlockCipher._createHelper(AES); + }()); + + + return CryptoJS.AES; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./enc-base64":1758332250183,"./md5":1758332250185,"./evpkdf":1758332250195,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250209, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Permuted Choice 1 constants + var PC1 = [ + 57, 49, 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 27, 19, 11, 3, + 60, 52, 44, 36, 63, 55, 47, 39, + 31, 23, 15, 7, 62, 54, 46, 38, + 30, 22, 14, 6, 61, 53, 45, 37, + 29, 21, 13, 5, 28, 20, 12, 4 + ]; + + // Permuted Choice 2 constants + var PC2 = [ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + ]; + + // Cumulative bit shift constants + var BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]; + + // SBOXes and round permutation constants + var SBOX_P = [ + { + 0x0: 0x808200, + 0x10000000: 0x8000, + 0x20000000: 0x808002, + 0x30000000: 0x2, + 0x40000000: 0x200, + 0x50000000: 0x808202, + 0x60000000: 0x800202, + 0x70000000: 0x800000, + 0x80000000: 0x202, + 0x90000000: 0x800200, + 0xa0000000: 0x8200, + 0xb0000000: 0x808000, + 0xc0000000: 0x8002, + 0xd0000000: 0x800002, + 0xe0000000: 0x0, + 0xf0000000: 0x8202, + 0x8000000: 0x0, + 0x18000000: 0x808202, + 0x28000000: 0x8202, + 0x38000000: 0x8000, + 0x48000000: 0x808200, + 0x58000000: 0x200, + 0x68000000: 0x808002, + 0x78000000: 0x2, + 0x88000000: 0x800200, + 0x98000000: 0x8200, + 0xa8000000: 0x808000, + 0xb8000000: 0x800202, + 0xc8000000: 0x800002, + 0xd8000000: 0x8002, + 0xe8000000: 0x202, + 0xf8000000: 0x800000, + 0x1: 0x8000, + 0x10000001: 0x2, + 0x20000001: 0x808200, + 0x30000001: 0x800000, + 0x40000001: 0x808002, + 0x50000001: 0x8200, + 0x60000001: 0x200, + 0x70000001: 0x800202, + 0x80000001: 0x808202, + 0x90000001: 0x808000, + 0xa0000001: 0x800002, + 0xb0000001: 0x8202, + 0xc0000001: 0x202, + 0xd0000001: 0x800200, + 0xe0000001: 0x8002, + 0xf0000001: 0x0, + 0x8000001: 0x808202, + 0x18000001: 0x808000, + 0x28000001: 0x800000, + 0x38000001: 0x200, + 0x48000001: 0x8000, + 0x58000001: 0x800002, + 0x68000001: 0x2, + 0x78000001: 0x8202, + 0x88000001: 0x8002, + 0x98000001: 0x800202, + 0xa8000001: 0x202, + 0xb8000001: 0x808200, + 0xc8000001: 0x800200, + 0xd8000001: 0x0, + 0xe8000001: 0x8200, + 0xf8000001: 0x808002 + }, + { + 0x0: 0x40084010, + 0x1000000: 0x4000, + 0x2000000: 0x80000, + 0x3000000: 0x40080010, + 0x4000000: 0x40000010, + 0x5000000: 0x40084000, + 0x6000000: 0x40004000, + 0x7000000: 0x10, + 0x8000000: 0x84000, + 0x9000000: 0x40004010, + 0xa000000: 0x40000000, + 0xb000000: 0x84010, + 0xc000000: 0x80010, + 0xd000000: 0x0, + 0xe000000: 0x4010, + 0xf000000: 0x40080000, + 0x800000: 0x40004000, + 0x1800000: 0x84010, + 0x2800000: 0x10, + 0x3800000: 0x40004010, + 0x4800000: 0x40084010, + 0x5800000: 0x40000000, + 0x6800000: 0x80000, + 0x7800000: 0x40080010, + 0x8800000: 0x80010, + 0x9800000: 0x0, + 0xa800000: 0x4000, + 0xb800000: 0x40080000, + 0xc800000: 0x40000010, + 0xd800000: 0x84000, + 0xe800000: 0x40084000, + 0xf800000: 0x4010, + 0x10000000: 0x0, + 0x11000000: 0x40080010, + 0x12000000: 0x40004010, + 0x13000000: 0x40084000, + 0x14000000: 0x40080000, + 0x15000000: 0x10, + 0x16000000: 0x84010, + 0x17000000: 0x4000, + 0x18000000: 0x4010, + 0x19000000: 0x80000, + 0x1a000000: 0x80010, + 0x1b000000: 0x40000010, + 0x1c000000: 0x84000, + 0x1d000000: 0x40004000, + 0x1e000000: 0x40000000, + 0x1f000000: 0x40084010, + 0x10800000: 0x84010, + 0x11800000: 0x80000, + 0x12800000: 0x40080000, + 0x13800000: 0x4000, + 0x14800000: 0x40004000, + 0x15800000: 0x40084010, + 0x16800000: 0x10, + 0x17800000: 0x40000000, + 0x18800000: 0x40084000, + 0x19800000: 0x40000010, + 0x1a800000: 0x40004010, + 0x1b800000: 0x80010, + 0x1c800000: 0x0, + 0x1d800000: 0x4010, + 0x1e800000: 0x40080010, + 0x1f800000: 0x84000 + }, + { + 0x0: 0x104, + 0x100000: 0x0, + 0x200000: 0x4000100, + 0x300000: 0x10104, + 0x400000: 0x10004, + 0x500000: 0x4000004, + 0x600000: 0x4010104, + 0x700000: 0x4010000, + 0x800000: 0x4000000, + 0x900000: 0x4010100, + 0xa00000: 0x10100, + 0xb00000: 0x4010004, + 0xc00000: 0x4000104, + 0xd00000: 0x10000, + 0xe00000: 0x4, + 0xf00000: 0x100, + 0x80000: 0x4010100, + 0x180000: 0x4010004, + 0x280000: 0x0, + 0x380000: 0x4000100, + 0x480000: 0x4000004, + 0x580000: 0x10000, + 0x680000: 0x10004, + 0x780000: 0x104, + 0x880000: 0x4, + 0x980000: 0x100, + 0xa80000: 0x4010000, + 0xb80000: 0x10104, + 0xc80000: 0x10100, + 0xd80000: 0x4000104, + 0xe80000: 0x4010104, + 0xf80000: 0x4000000, + 0x1000000: 0x4010100, + 0x1100000: 0x10004, + 0x1200000: 0x10000, + 0x1300000: 0x4000100, + 0x1400000: 0x100, + 0x1500000: 0x4010104, + 0x1600000: 0x4000004, + 0x1700000: 0x0, + 0x1800000: 0x4000104, + 0x1900000: 0x4000000, + 0x1a00000: 0x4, + 0x1b00000: 0x10100, + 0x1c00000: 0x4010000, + 0x1d00000: 0x104, + 0x1e00000: 0x10104, + 0x1f00000: 0x4010004, + 0x1080000: 0x4000000, + 0x1180000: 0x104, + 0x1280000: 0x4010100, + 0x1380000: 0x0, + 0x1480000: 0x10004, + 0x1580000: 0x4000100, + 0x1680000: 0x100, + 0x1780000: 0x4010004, + 0x1880000: 0x10000, + 0x1980000: 0x4010104, + 0x1a80000: 0x10104, + 0x1b80000: 0x4000004, + 0x1c80000: 0x4000104, + 0x1d80000: 0x4010000, + 0x1e80000: 0x4, + 0x1f80000: 0x10100 + }, + { + 0x0: 0x80401000, + 0x10000: 0x80001040, + 0x20000: 0x401040, + 0x30000: 0x80400000, + 0x40000: 0x0, + 0x50000: 0x401000, + 0x60000: 0x80000040, + 0x70000: 0x400040, + 0x80000: 0x80000000, + 0x90000: 0x400000, + 0xa0000: 0x40, + 0xb0000: 0x80001000, + 0xc0000: 0x80400040, + 0xd0000: 0x1040, + 0xe0000: 0x1000, + 0xf0000: 0x80401040, + 0x8000: 0x80001040, + 0x18000: 0x40, + 0x28000: 0x80400040, + 0x38000: 0x80001000, + 0x48000: 0x401000, + 0x58000: 0x80401040, + 0x68000: 0x0, + 0x78000: 0x80400000, + 0x88000: 0x1000, + 0x98000: 0x80401000, + 0xa8000: 0x400000, + 0xb8000: 0x1040, + 0xc8000: 0x80000000, + 0xd8000: 0x400040, + 0xe8000: 0x401040, + 0xf8000: 0x80000040, + 0x100000: 0x400040, + 0x110000: 0x401000, + 0x120000: 0x80000040, + 0x130000: 0x0, + 0x140000: 0x1040, + 0x150000: 0x80400040, + 0x160000: 0x80401000, + 0x170000: 0x80001040, + 0x180000: 0x80401040, + 0x190000: 0x80000000, + 0x1a0000: 0x80400000, + 0x1b0000: 0x401040, + 0x1c0000: 0x80001000, + 0x1d0000: 0x400000, + 0x1e0000: 0x40, + 0x1f0000: 0x1000, + 0x108000: 0x80400000, + 0x118000: 0x80401040, + 0x128000: 0x0, + 0x138000: 0x401000, + 0x148000: 0x400040, + 0x158000: 0x80000000, + 0x168000: 0x80001040, + 0x178000: 0x40, + 0x188000: 0x80000040, + 0x198000: 0x1000, + 0x1a8000: 0x80001000, + 0x1b8000: 0x80400040, + 0x1c8000: 0x1040, + 0x1d8000: 0x80401000, + 0x1e8000: 0x400000, + 0x1f8000: 0x401040 + }, + { + 0x0: 0x80, + 0x1000: 0x1040000, + 0x2000: 0x40000, + 0x3000: 0x20000000, + 0x4000: 0x20040080, + 0x5000: 0x1000080, + 0x6000: 0x21000080, + 0x7000: 0x40080, + 0x8000: 0x1000000, + 0x9000: 0x20040000, + 0xa000: 0x20000080, + 0xb000: 0x21040080, + 0xc000: 0x21040000, + 0xd000: 0x0, + 0xe000: 0x1040080, + 0xf000: 0x21000000, + 0x800: 0x1040080, + 0x1800: 0x21000080, + 0x2800: 0x80, + 0x3800: 0x1040000, + 0x4800: 0x40000, + 0x5800: 0x20040080, + 0x6800: 0x21040000, + 0x7800: 0x20000000, + 0x8800: 0x20040000, + 0x9800: 0x0, + 0xa800: 0x21040080, + 0xb800: 0x1000080, + 0xc800: 0x20000080, + 0xd800: 0x21000000, + 0xe800: 0x1000000, + 0xf800: 0x40080, + 0x10000: 0x40000, + 0x11000: 0x80, + 0x12000: 0x20000000, + 0x13000: 0x21000080, + 0x14000: 0x1000080, + 0x15000: 0x21040000, + 0x16000: 0x20040080, + 0x17000: 0x1000000, + 0x18000: 0x21040080, + 0x19000: 0x21000000, + 0x1a000: 0x1040000, + 0x1b000: 0x20040000, + 0x1c000: 0x40080, + 0x1d000: 0x20000080, + 0x1e000: 0x0, + 0x1f000: 0x1040080, + 0x10800: 0x21000080, + 0x11800: 0x1000000, + 0x12800: 0x1040000, + 0x13800: 0x20040080, + 0x14800: 0x20000000, + 0x15800: 0x1040080, + 0x16800: 0x80, + 0x17800: 0x21040000, + 0x18800: 0x40080, + 0x19800: 0x21040080, + 0x1a800: 0x0, + 0x1b800: 0x21000000, + 0x1c800: 0x1000080, + 0x1d800: 0x40000, + 0x1e800: 0x20040000, + 0x1f800: 0x20000080 + }, + { + 0x0: 0x10000008, + 0x100: 0x2000, + 0x200: 0x10200000, + 0x300: 0x10202008, + 0x400: 0x10002000, + 0x500: 0x200000, + 0x600: 0x200008, + 0x700: 0x10000000, + 0x800: 0x0, + 0x900: 0x10002008, + 0xa00: 0x202000, + 0xb00: 0x8, + 0xc00: 0x10200008, + 0xd00: 0x202008, + 0xe00: 0x2008, + 0xf00: 0x10202000, + 0x80: 0x10200000, + 0x180: 0x10202008, + 0x280: 0x8, + 0x380: 0x200000, + 0x480: 0x202008, + 0x580: 0x10000008, + 0x680: 0x10002000, + 0x780: 0x2008, + 0x880: 0x200008, + 0x980: 0x2000, + 0xa80: 0x10002008, + 0xb80: 0x10200008, + 0xc80: 0x0, + 0xd80: 0x10202000, + 0xe80: 0x202000, + 0xf80: 0x10000000, + 0x1000: 0x10002000, + 0x1100: 0x10200008, + 0x1200: 0x10202008, + 0x1300: 0x2008, + 0x1400: 0x200000, + 0x1500: 0x10000000, + 0x1600: 0x10000008, + 0x1700: 0x202000, + 0x1800: 0x202008, + 0x1900: 0x0, + 0x1a00: 0x8, + 0x1b00: 0x10200000, + 0x1c00: 0x2000, + 0x1d00: 0x10002008, + 0x1e00: 0x10202000, + 0x1f00: 0x200008, + 0x1080: 0x8, + 0x1180: 0x202000, + 0x1280: 0x200000, + 0x1380: 0x10000008, + 0x1480: 0x10002000, + 0x1580: 0x2008, + 0x1680: 0x10202008, + 0x1780: 0x10200000, + 0x1880: 0x10202000, + 0x1980: 0x10200008, + 0x1a80: 0x2000, + 0x1b80: 0x202008, + 0x1c80: 0x200008, + 0x1d80: 0x0, + 0x1e80: 0x10000000, + 0x1f80: 0x10002008 + }, + { + 0x0: 0x100000, + 0x10: 0x2000401, + 0x20: 0x400, + 0x30: 0x100401, + 0x40: 0x2100401, + 0x50: 0x0, + 0x60: 0x1, + 0x70: 0x2100001, + 0x80: 0x2000400, + 0x90: 0x100001, + 0xa0: 0x2000001, + 0xb0: 0x2100400, + 0xc0: 0x2100000, + 0xd0: 0x401, + 0xe0: 0x100400, + 0xf0: 0x2000000, + 0x8: 0x2100001, + 0x18: 0x0, + 0x28: 0x2000401, + 0x38: 0x2100400, + 0x48: 0x100000, + 0x58: 0x2000001, + 0x68: 0x2000000, + 0x78: 0x401, + 0x88: 0x100401, + 0x98: 0x2000400, + 0xa8: 0x2100000, + 0xb8: 0x100001, + 0xc8: 0x400, + 0xd8: 0x2100401, + 0xe8: 0x1, + 0xf8: 0x100400, + 0x100: 0x2000000, + 0x110: 0x100000, + 0x120: 0x2000401, + 0x130: 0x2100001, + 0x140: 0x100001, + 0x150: 0x2000400, + 0x160: 0x2100400, + 0x170: 0x100401, + 0x180: 0x401, + 0x190: 0x2100401, + 0x1a0: 0x100400, + 0x1b0: 0x1, + 0x1c0: 0x0, + 0x1d0: 0x2100000, + 0x1e0: 0x2000001, + 0x1f0: 0x400, + 0x108: 0x100400, + 0x118: 0x2000401, + 0x128: 0x2100001, + 0x138: 0x1, + 0x148: 0x2000000, + 0x158: 0x100000, + 0x168: 0x401, + 0x178: 0x2100400, + 0x188: 0x2000001, + 0x198: 0x2100000, + 0x1a8: 0x0, + 0x1b8: 0x2100401, + 0x1c8: 0x100401, + 0x1d8: 0x400, + 0x1e8: 0x2000400, + 0x1f8: 0x100001 + }, + { + 0x0: 0x8000820, + 0x1: 0x20000, + 0x2: 0x8000000, + 0x3: 0x20, + 0x4: 0x20020, + 0x5: 0x8020820, + 0x6: 0x8020800, + 0x7: 0x800, + 0x8: 0x8020000, + 0x9: 0x8000800, + 0xa: 0x20800, + 0xb: 0x8020020, + 0xc: 0x820, + 0xd: 0x0, + 0xe: 0x8000020, + 0xf: 0x20820, + 0x80000000: 0x800, + 0x80000001: 0x8020820, + 0x80000002: 0x8000820, + 0x80000003: 0x8000000, + 0x80000004: 0x8020000, + 0x80000005: 0x20800, + 0x80000006: 0x20820, + 0x80000007: 0x20, + 0x80000008: 0x8000020, + 0x80000009: 0x820, + 0x8000000a: 0x20020, + 0x8000000b: 0x8020800, + 0x8000000c: 0x0, + 0x8000000d: 0x8020020, + 0x8000000e: 0x8000800, + 0x8000000f: 0x20000, + 0x10: 0x20820, + 0x11: 0x8020800, + 0x12: 0x20, + 0x13: 0x800, + 0x14: 0x8000800, + 0x15: 0x8000020, + 0x16: 0x8020020, + 0x17: 0x20000, + 0x18: 0x0, + 0x19: 0x20020, + 0x1a: 0x8020000, + 0x1b: 0x8000820, + 0x1c: 0x8020820, + 0x1d: 0x20800, + 0x1e: 0x820, + 0x1f: 0x8000000, + 0x80000010: 0x20000, + 0x80000011: 0x800, + 0x80000012: 0x8020020, + 0x80000013: 0x20820, + 0x80000014: 0x20, + 0x80000015: 0x8020000, + 0x80000016: 0x8000000, + 0x80000017: 0x8000820, + 0x80000018: 0x8020820, + 0x80000019: 0x8000020, + 0x8000001a: 0x8000800, + 0x8000001b: 0x0, + 0x8000001c: 0x20800, + 0x8000001d: 0x820, + 0x8000001e: 0x20020, + 0x8000001f: 0x8020800 + } + ]; + + // Masks that select the SBOX input + var SBOX_MASK = [ + 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000, + 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f + ]; + + /** + * DES block cipher algorithm. + */ + var DES = C_algo.DES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + + // Select 56 bits according to PC1 + var keyBits = []; + for (var i = 0; i < 56; i++) { + var keyBitPos = PC1[i] - 1; + keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1; + } + + // Assemble 16 subkeys + var subKeys = this._subKeys = []; + for (var nSubKey = 0; nSubKey < 16; nSubKey++) { + // Create subkey + var subKey = subKeys[nSubKey] = []; + + // Shortcut + var bitShift = BIT_SHIFTS[nSubKey]; + + // Select 48 bits according to PC2 + for (var i = 0; i < 24; i++) { + // Select from the left 28 key bits + subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6); + + // Select from the right 28 key bits + subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6); + } + + // Since each subkey is applied to an expanded 32-bit input, + // the subkey can be broken into 8 values scaled to 32-bits, + // which allows the key to be used without expansion + subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31); + for (var i = 1; i < 7; i++) { + subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3); + } + subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27); + } + + // Compute inverse subkeys + var invSubKeys = this._invSubKeys = []; + for (var i = 0; i < 16; i++) { + invSubKeys[i] = subKeys[15 - i]; + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._subKeys); + }, + + decryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._invSubKeys); + }, + + _doCryptBlock: function (M, offset, subKeys) { + // Get input + this._lBlock = M[offset]; + this._rBlock = M[offset + 1]; + + // Initial permutation + exchangeLR.call(this, 4, 0x0f0f0f0f); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeRL.call(this, 2, 0x33333333); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeLR.call(this, 1, 0x55555555); + + // Rounds + for (var round = 0; round < 16; round++) { + // Shortcuts + var subKey = subKeys[round]; + var lBlock = this._lBlock; + var rBlock = this._rBlock; + + // Feistel function + var f = 0; + for (var i = 0; i < 8; i++) { + f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0]; + } + this._lBlock = rBlock; + this._rBlock = lBlock ^ f; + } + + // Undo swap from last round + var t = this._lBlock; + this._lBlock = this._rBlock; + this._rBlock = t; + + // Final permutation + exchangeLR.call(this, 1, 0x55555555); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeRL.call(this, 2, 0x33333333); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeLR.call(this, 4, 0x0f0f0f0f); + + // Set output + M[offset] = this._lBlock; + M[offset + 1] = this._rBlock; + }, + + keySize: 64/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + // Swap bits across the left and right words + function exchangeLR(offset, mask) { + var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask; + this._rBlock ^= t; + this._lBlock ^= t << offset; + } + + function exchangeRL(offset, mask) { + var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask; + this._lBlock ^= t; + this._rBlock ^= t << offset; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ + C.DES = BlockCipher._createHelper(DES); + + /** + * Triple-DES block cipher algorithm. + */ + var TripleDES = C_algo.TripleDES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + // Make sure the key length is valid (64, 128 or >= 192 bit) + if (keyWords.length !== 2 && keyWords.length !== 4 && keyWords.length < 6) { + throw new Error('Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.'); + } + + // Extend the key according to the keying options defined in 3DES standard + var key1 = keyWords.slice(0, 2); + var key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4); + var key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6); + + // Create DES instances + this._des1 = DES.createEncryptor(WordArray.create(key1)); + this._des2 = DES.createEncryptor(WordArray.create(key2)); + this._des3 = DES.createEncryptor(WordArray.create(key3)); + }, + + encryptBlock: function (M, offset) { + this._des1.encryptBlock(M, offset); + this._des2.decryptBlock(M, offset); + this._des3.encryptBlock(M, offset); + }, + + decryptBlock: function (M, offset) { + this._des3.decryptBlock(M, offset); + this._des2.encryptBlock(M, offset); + this._des1.decryptBlock(M, offset); + }, + + keySize: 192/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ + C.TripleDES = BlockCipher._createHelper(TripleDES); + }()); + + + return CryptoJS.TripleDES; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./enc-base64":1758332250183,"./md5":1758332250185,"./evpkdf":1758332250195,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250210, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + /** + * RC4 stream cipher algorithm. + */ + var RC4 = C_algo.RC4 = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + var keySigBytes = key.sigBytes; + + // Init sbox + var S = this._S = []; + for (var i = 0; i < 256; i++) { + S[i] = i; + } + + // Key setup + for (var i = 0, j = 0; i < 256; i++) { + var keyByteIndex = i % keySigBytes; + var keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff; + + j = (j + S[i] + keyByte) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + } + + // Counters + this._i = this._j = 0; + }, + + _doProcessBlock: function (M, offset) { + M[offset] ^= generateKeystreamWord.call(this); + }, + + keySize: 256/32, + + ivSize: 0 + }); + + function generateKeystreamWord() { + // Shortcuts + var S = this._S; + var i = this._i; + var j = this._j; + + // Generate keystream word + var keystreamWord = 0; + for (var n = 0; n < 4; n++) { + i = (i + 1) % 256; + j = (j + S[i]) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + + keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8); + } + + // Update counters + this._i = i; + this._j = j; + + return keystreamWord; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ + C.RC4 = StreamCipher._createHelper(RC4); + + /** + * Modified RC4 stream cipher algorithm. + */ + var RC4Drop = C_algo.RC4Drop = RC4.extend({ + /** + * Configuration options. + * + * @property {number} drop The number of keystream words to drop. Default 192 + */ + cfg: RC4.cfg.extend({ + drop: 192 + }), + + _doReset: function () { + RC4._doReset.call(this); + + // Drop + for (var i = this.cfg.drop; i > 0; i--) { + generateKeystreamWord.call(this); + } + } + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ + C.RC4Drop = StreamCipher._createHelper(RC4Drop); + }()); + + + return CryptoJS.RC4; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./enc-base64":1758332250183,"./md5":1758332250185,"./evpkdf":1758332250195,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250211, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm + */ + var Rabbit = C_algo.Rabbit = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Swap endian + for (var i = 0; i < 4; i++) { + K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff) | + (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00); + } + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ + C.Rabbit = StreamCipher._createHelper(Rabbit); + }()); + + + return CryptoJS.Rabbit; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./enc-base64":1758332250183,"./md5":1758332250185,"./evpkdf":1758332250195,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250212, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ + var RabbitLegacy = C_algo.RabbitLegacy = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ + C.RabbitLegacy = StreamCipher._createHelper(RabbitLegacy); + }()); + + + return CryptoJS.RabbitLegacy; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./enc-base64":1758332250183,"./md5":1758332250185,"./evpkdf":1758332250195,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +__DEFINE__(1758332250213, function(require, module, exports) { +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + const N = 16; + + //Origin pbox and sbox, derived from PI + const ORIG_P = [ + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, + 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89, + 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, + 0x9216D5D9, 0x8979FB1B + ]; + + const ORIG_S = [ + [ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, + 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, + 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, + 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, + 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, + 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, + 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, + 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, + 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, + 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, + 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, + 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, + 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, + 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, + 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, + 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, + 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, + 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, + 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, + 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, + 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, + 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, + 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, + 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, + 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, + 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, + 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, + 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, + 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, + 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, + 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, + 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, + 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, + 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, + 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, + 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, + 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, + 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, + 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, + 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, + 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, + 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, + 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, + 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, + 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, + 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, + 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, + 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, + 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A ], + [ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, + 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, + 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, + 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, + 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, + 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, + 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, + 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, + 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, + 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, + 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, + 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, + 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, + 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, + 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, + 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, + 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, + 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, + 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, + 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, + 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, + 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, + 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, + 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, + 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, + 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, + 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, + 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, + 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, + 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, + 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, + 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, + 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, + 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, + 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, + 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, + 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, + 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, + 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, + 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, + 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, + 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, + 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, + 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, + 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, + 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, + 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, + 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, + 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 ], + [ 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, + 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, + 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, + 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, + 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, + 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, + 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, + 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, + 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, + 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, + 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, + 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, + 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, + 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, + 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, + 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, + 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, + 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, + 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, + 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, + 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, + 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, + 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, + 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, + 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B, + 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, + 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, + 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, + 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, + 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, + 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, + 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D, + 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, + 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, + 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, + 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, + 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, + 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, + 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, + 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, + 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, + 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, + 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, + 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, + 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, + 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, + 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, + 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, + 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 ], + [ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, + 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, + 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, + 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, + 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, + 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, + 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, + 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, + 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, + 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, + 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, + 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, + 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, + 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, + 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, + 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, + 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, + 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, + 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, + 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, + 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, + 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, + 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, + 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, + 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, + 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, + 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, + 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, + 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, + 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, + 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, + 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, + 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, + 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, + 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, + 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, + 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, + 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, + 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, + 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, + 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, + 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, + 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, + 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, + 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, + 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, + 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, + 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, + 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 ] + ]; + + var BLOWFISH_CTX = { + pbox: [], + sbox: [] + } + + function F(ctx, x){ + let a = (x >> 24) & 0xFF; + let b = (x >> 16) & 0xFF; + let c = (x >> 8) & 0xFF; + let d = x & 0xFF; + + let y = ctx.sbox[0][a] + ctx.sbox[1][b]; + y = y ^ ctx.sbox[2][c]; + y = y + ctx.sbox[3][d]; + + return y; + } + + function BlowFish_Encrypt(ctx, left, right){ + let Xl = left; + let Xr = right; + let temp; + + for(let i = 0; i < N; ++i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = F(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[N]; + Xl = Xl ^ ctx.pbox[N + 1]; + + return {left: Xl, right: Xr}; + } + + function BlowFish_Decrypt(ctx, left, right){ + let Xl = left; + let Xr = right; + let temp; + + for(let i = N + 1; i > 1; --i){ + Xl = Xl ^ ctx.pbox[i]; + Xr = F(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx.pbox[1]; + Xl = Xl ^ ctx.pbox[0]; + + return {left: Xl, right: Xr}; + } + + /** + * Initialization ctx's pbox and sbox. + * + * @param {Object} ctx The object has pbox and sbox. + * @param {Array} key An array of 32-bit words. + * @param {int} keysize The length of the key. + * + * @example + * + * BlowFishInit(BLOWFISH_CTX, key, 128/32); + */ + function BlowFishInit(ctx, key, keysize) + { + for(let Row = 0; Row < 4; Row++) + { + ctx.sbox[Row] = []; + for(let Col = 0; Col < 256; Col++) + { + ctx.sbox[Row][Col] = ORIG_S[Row][Col]; + } + } + + let keyIndex = 0; + for(let index = 0; index < N + 2; index++) + { + ctx.pbox[index] = ORIG_P[index] ^ key[keyIndex]; + keyIndex++; + if(keyIndex >= keysize) + { + keyIndex = 0; + } + } + + let Data1 = 0; + let Data2 = 0; + let res = 0; + for(let i = 0; i < N + 2; i += 2) + { + res = BlowFish_Encrypt(ctx, Data1, Data2); + Data1 = res.left; + Data2 = res.right; + ctx.pbox[i] = Data1; + ctx.pbox[i + 1] = Data2; + } + + for(let i = 0; i < 4; i++) + { + for(let j = 0; j < 256; j += 2) + { + res = BlowFish_Encrypt(ctx, Data1, Data2); + Data1 = res.left; + Data2 = res.right; + ctx.sbox[i][j] = Data1; + ctx.sbox[i][j + 1] = Data2; + } + } + + return true; + } + + /** + * Blowfish block cipher algorithm. + */ + var Blowfish = C_algo.Blowfish = BlockCipher.extend({ + _doReset: function () { + // Skip reset of nRounds has been set before and key did not change + if (this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + var key = this._keyPriorReset = this._key; + var keyWords = key.words; + var keySize = key.sigBytes / 4; + + //Initialization pbox and sbox + BlowFishInit(BLOWFISH_CTX, keyWords, keySize); + }, + + encryptBlock: function (M, offset) { + var res = BlowFish_Encrypt(BLOWFISH_CTX, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + }, + + decryptBlock: function (M, offset) { + var res = BlowFish_Decrypt(BLOWFISH_CTX, M[offset], M[offset + 1]); + M[offset] = res.left; + M[offset + 1] = res.right; + }, + + blockSize: 64/32, + + keySize: 128/32, + + ivSize: 64/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg); + */ + C.Blowfish = BlockCipher._createHelper(Blowfish); + }()); + + + return CryptoJS.Blowfish; + +})); +}, function(modId) { var map = {"./core":1758332250179,"./enc-base64":1758332250183,"./md5":1758332250185,"./evpkdf":1758332250195,"./cipher-core":1758332250196}; return __REQUIRE__(map[modId], modId); }) +return __REQUIRE__(1758332250178); +})() +//miniprogram-npm-outsideDeps=["crypto"] +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..3b6d257 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1486 @@ +{ + "name": "findme-miniprogram", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "findme-miniprogram", + "dependencies": { + "cos-wx-sdk-v5": "^1.8.0", + "crypto-js": "^4.2.0", + "gcoord": "^1.0.7", + "nim-web-sdk-ng": "^10.9.50", + "spark-md5": "^3.0.2" + }, + "devDependencies": { + "webpack": "^5.102.1", + "webpack-cli": "^6.0.1" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", + "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", + "dev": true, + "engines": { + "node": ">=14.17.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "24.8.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.8.1.tgz", + "integrity": "sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==", + "dev": true, + "dependencies": { + "undici-types": "~7.14.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-3.0.1.tgz", + "integrity": "sha512-u8d0pJ5YFgneF/GuvEiDA61Tf1VDomHHYMjv/wc9XzYj7nopltpG96nXN5dJRstxZhcNpV1g+nT6CydO7pHbjA==", + "dev": true, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "webpack": "^5.82.0", + "webpack-cli": "6.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-3.0.1.tgz", + "integrity": "sha512-coEmDzc2u/ffMvuW9aCjoRzNSPDl/XLuhPdlFRpT9tZHmJ/039az33CE7uH+8s0uL1j5ZNtfdv0HkfaKRBGJsQ==", + "dev": true, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "webpack": "^5.82.0", + "webpack-cli": "6.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-3.0.1.tgz", + "integrity": "sha512-sbgw03xQaCLiT6gcY/6u3qBDn01CWw/nbaXl3gTdTFuJJ75Gffv3E3DBpgvY2fkkrdS1fpjaXNOmJlnbtKauKg==", + "dev": true, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "webpack": "^5.82.0", + "webpack-cli": "6.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.18", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.18.tgz", + "integrity": "sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w==", + "dev": true, + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/browserslist": { + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001751", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/cos-wx-sdk-v5": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/cos-wx-sdk-v5/-/cos-wx-sdk-v5-1.8.0.tgz", + "integrity": "sha512-CP4TKANIX5KvN6fjkPrFhdEfXjyBSExwBemRr2Ofa7ObN+Z8S62/eo6/d0WVKxSbneoPaXJzkf4AwZz7HOQXXg==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "fast-xml-parser": "4.5.0", + "mime": "^2.4.6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.237", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.237.tgz", + "integrity": "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.19.0.tgz", + "integrity": "sha512-DoSM9VyG6O3vqBf+p3Gjgr/Q52HYBBtO3v+4koAxt1MnWr+zEnxE+nke/yXS4lt2P4SYCHQ4V3f1i88LQVOpAw==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/fast-xml-parser": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", + "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gcoord": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/gcoord/-/gcoord-1.0.7.tgz", + "integrity": "sha512-UCN2iSm69jBOYz2ma2eg5I5imp65Cj70rcTTfMNSNMvZpR1U6oGjmVh080aCvC/6lN1ClkuOoBeaLuebw9AZJg==", + "license": "MIT", + "engines": { + "node": ">=16.11.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "dev": true, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nim-web-sdk-ng": { + "version": "10.9.50", + "resolved": "https://registry.npmjs.org/nim-web-sdk-ng/-/nim-web-sdk-ng-10.9.50.tgz", + "integrity": "sha512-Xj7NZwQ7whSUD6CkV20w1GcS0ardjtxDnQiV+EJzcwfIdQC938VCoQOdyegkoyGMgbUQ7khQ4moIhC2hP1FNAw==" + }, + "node_modules/node-releases": { + "version": "2.0.25", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.25.tgz", + "integrity": "sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==", + "dev": true + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spark-md5": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz", + "integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==", + "license": "(WTFPL OR MIT)" + }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser": { + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", + "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/undici-types": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz", + "integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==", + "dev": true + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.102.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz", + "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.26.3", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.3", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.11", + "watchpack": "^2.4.4", + "webpack-sources": "^3.3.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", + "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", + "dev": true, + "peer": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.6.1", + "@webpack-cli/configtest": "^3.0.1", + "@webpack-cli/info": "^3.0.1", + "@webpack-cli/serve": "^3.0.1", + "colorette": "^2.0.14", + "commander": "^12.1.0", + "cross-spawn": "^7.0.3", + "envinfo": "^7.14.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^6.0.1" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.82.0" + }, + "peerDependenciesMeta": { + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..82d8706 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "findme-miniprogram", + "main": ".eslintrc.js", + "scripts": { + "build": "webpack --config webpack.config.js" + }, + "dependencies": { + "cos-wx-sdk-v5": "^1.8.0", + "crypto-js": "^4.2.0", + "gcoord": "^1.0.7", + "nim-web-sdk-ng": "^10.9.50", + "spark-md5": "^3.0.2" + }, + "devDependencies": { + "webpack": "^5.102.1", + "webpack-cli": "^6.0.1" + } +} diff --git a/pages/circle/circle.js b/pages/circle/circle.js new file mode 100644 index 0000000..2c2926e --- /dev/null +++ b/pages/circle/circle.js @@ -0,0 +1,1808 @@ +const config = require('../../config/config.js'); +const apiClient = require('../../utils/api-client.js'); +const { getListImageUrl, getPreviewImageUrl, getOriginalImageUrl } = require('../../utils/image-url-optimizer.js'); + +Page({ + data: { + feedList: [], // 动态列表数据 + userList: [], // 用户列表(从头像模块显示) + page: 1, // 当前页码 + pageSize: 5, // 每页加载数量 + loading: false, // 是否正在加载 + noMore: false, // 是否没有更多数据 + currentYear: new Date().getFullYear(), // 当前年份 + // 定位相关数据 + latitude: null, + longitude: null, + radius: 30, + modeFrom: '', + feedUuid: '', + pendingFeedUuid: '', + scrollIntoFeedId: '', + highlightFeedUuid: '', + lastRedirectToken: '', + // 评论弹窗相关 + showCommentModal: false, // 是否显示评论弹窗 + currentFeedUuid: '', // 当前评论的动态UUID + currentFeedIndex: -1, // 当前评论的动态索引 + currentComments: [], // 当前显示的评论列表 + commentInputValue: '', // 评论输入内容 + // 回复相关 + replyingCommentId: null, // 当前正在回复的评论ID + replyingCommentIndex: null, // 当前正在回复的评论索引(一级评论) + replyingToCommentId: null, // 回复的目标评论ID(二级评论的父评论) + replyInputValue: '', // 回复输入内容 + showReplyInput: {}, // 控制每个评论的回复输入框显示状态 {commentId: true/false} + submittingReply: false // 是否正在提交回复,防止重复点击 + }, + + onLoad(options = {}) { + this._skipNextOnShowReload = true; + this.highlightTimer = null; + + const mapLatitude = parseFloat(options.latitude); + const mapLongitude = parseFloat(options.longitude); + const hasMapParams = !Number.isNaN(mapLatitude) && !Number.isNaN(mapLongitude); + + if (hasMapParams) { + const parsedRadius = parseInt(options.radius, 10); + const safeRadius = Number.isNaN(parsedRadius) ? this.data.radius : Math.max(10, parsedRadius); + + this._skipNextOnShowReload = true; + + this.setData({ + latitude: mapLatitude, + longitude: mapLongitude, + radius: safeRadius, + modeFrom: options.mode || 'map', + feedUuid: options.feedUuid || '', + pendingFeedUuid: options.feedUuid || '' + }, () => { + this.resetAndLoadFeedList(); + }); + return; + } + + // 先获取定位,再加载数据 + this.getLocation().then(() => { + this.loadFeedList(); + }).catch(() => {}); + + this.apiClient = apiClient; + }, + + // 获取用户地理位置 + getLocation() { + return new Promise((resolve, reject) => { + wx.getLocation({ + type: 'gcj02', + success: (res) => { + this.setData({ + latitude: res.latitude, + longitude: res.longitude + }); + resolve(); // 定位成功,允许加载数据 + }, + fail: (err) => { + wx.showToast({ + title: '获取位置失败,无法加载附近动态', + icon: 'none', + duration: 2000 + }); + reject(err); + } + }); + }); + }, + + resetAndLoadFeedList() { + if (!this.data.latitude || !this.data.longitude) { + return; + } + + this.setData({ page: 1, feedList: [], noMore: false, scrollIntoFeedId: '' }, () => { + this.loadFeedList(); + }); + }, + + onShow() { + // 🔥 设置tabBar选中状态为"圈子"(索引1) + try { + if (typeof this.getTabBar === 'function' && this.getTabBar()) { + this.getTabBar().setData({ selected: 1 }); + } + } catch (_) {} + + const appInstance = getApp(); + const redirectPayload = appInstance?.globalData?.mapFeedRedirect; + if (redirectPayload && redirectPayload.token && redirectPayload.token !== this.data.lastRedirectToken) { + appInstance.globalData.mapFeedRedirect = null; + this.applyRedirectPayload(redirectPayload); + return; + } + + if (this._skipNextOnShowReload) { + // 延迟清除标志,确保能捕获到预览关闭事件 + setTimeout(() => { + this._skipNextOnShowReload = false; + }, 500); + return; + } + + // 页面显示时刷新数据 + if (this.data.latitude && this.data.longitude) { + this.resetAndLoadFeedList(); + } + }, + + // 加载动态列表 + loadFeedList() { + // 检查是否有定位信息 + if (!this.data.latitude || !this.data.longitude) return; + + if (this.data.loading || this.data.noMore) return; + this.setData({ loading: true }); + + + // 通过字符串模板拼接带参数的URL + const { page, pageSize, latitude, longitude } = this.data; + // 查看所有动态 + const fullRequestUrl = `${config.api.baseUrl}/api/v1/feeds?` + + `type=timeline&` + + `page=${page}&` + + `pageSize=${pageSize}&` + + `latitude=${latitude}&` + + `longitude=${longitude}&` + + `radius=30`; + + // 先检查URL是否有效 + if (!fullRequestUrl || !fullRequestUrl.startsWith('http')) { + console.error('无效的请求URL:', fullRequestUrl); + this.setData({ loading: false }); + wx.showToast({ title: '加载失败,请重试', icon: 'none' }); + return; + } + + // 调用接口 + wx.request({ + url: fullRequestUrl, + method: 'GET', + header: { + 'Authorization': `Bearer ${apiClient.getToken() || ''}` + }, + success: (res) => { + + + if (res.data.data?.feeds && res.data.data.feeds.length > 0) { + + + if (res.data.data.feeds[0].media && res.data.data.feeds[0].media.length > 0) { + + } + } + + this.setData({ loading: false }); + + // 🔥 统一处理401 - 使用apiClient的统一处理 + if (apiClient.is401Error(res)) { + const app = getApp(); + const isLoggedIn = app?.globalData?.isLoggedIn || false; + apiClient.handle401Error(isLoggedIn); + return; + } + + if (res.data.code !== 200) { + wx.showToast({ + title: res.data.message || '加载失败', + icon: 'none' + }); + return; + } + + const newFeeds = res.data.data.feeds || []; + const processedFeeds = newFeeds.map((feed, feedIdx) => { + // 时间格式化 + let formattedTime = '未知时间'; + try { + formattedTime = this.formatTime(feed.createdAt || ''); + } catch (error) { + console.error('时间格式化失败:', error); + } + + // 用户信息 + const feedUser = feed.user || {}; + console.log("当前动态的用户信息", feedUser) + + // 处理用户头像URL + let validAvatar = feedUser.avatar || ''; + + if (validAvatar && !validAvatar.startsWith('http') && validAvatar.startsWith('/')) { + try { + const baseDomain = config.api.baseUrl.replace(/\/api\/v1$/, ''); + validAvatar = `${baseDomain}${validAvatar}`; + } catch (e) { + console.error(`头像路径转换失败:`, e); + } + } + + if (validAvatar && validAvatar.startsWith('http://')) { + validAvatar = validAvatar.replace('http://', 'https://'); + } + + if (!validAvatar || (!validAvatar.startsWith('http://') && !validAvatar.startsWith('https://'))) { + console.warn(`无效的头像URL,使用占位图:`, validAvatar); + validAvatar = '/images/findme-logo.png'; + } + + // 处理动态图片 + let processedMedia = []; + if (feed.media && Array.isArray(feed.media)) { + processedMedia = feed.media.map((mediaItem, index) => { + if (!mediaItem || typeof mediaItem !== 'object') { + console.warn(`动态${feed.id || index}的图片无效:`, mediaItem); + return { + url: '/images/placeholder.svg', + thumbnailUrl: '/images/placeholder.svg', + type: 'image' + }; + } + + // 确保图片URL有效 + let validUrl = mediaItem.url || mediaItem.src || ''; + let validThumbnailUrl = mediaItem.thumbnailUrl || mediaItem.thumbnail || validUrl; + + if (validUrl && !validUrl.startsWith('http') && validUrl.startsWith('/')) { + try { + const baseDomain = config.api.baseUrl.replace(/\/api\/v1$/, ''); + validUrl = `${baseDomain}${validUrl}`; + } catch (e) { + console.error(`图片路径转换失败:`, e); + } + } + + if (validUrl && validUrl.startsWith('http://')) { + validUrl = validUrl.replace('http://', 'https://'); + } + + if (!validUrl || (!validUrl.startsWith('http://') && !validUrl.startsWith('https://'))) { + console.warn(`无效的图片URL,使用占位图:`, validUrl); + validUrl = '/images/placeholder.svg'; + } + + if (validThumbnailUrl && !validThumbnailUrl.startsWith('http') && validThumbnailUrl.startsWith('/')) { + try { + const baseDomain = config.api.baseUrl.replace(/\/api\/v1$/, ''); + validThumbnailUrl = `${baseDomain}${validThumbnailUrl}`; + } catch (e) {} + } + + if (validThumbnailUrl && validThumbnailUrl.startsWith('http://')) { + validThumbnailUrl = validThumbnailUrl.replace('http://', 'https://'); + } + + if (!validThumbnailUrl || (!validThumbnailUrl.startsWith('http://') && !validThumbnailUrl.startsWith('https://'))) { + validThumbnailUrl = validUrl; + } + + // 优化图片URL,提高清晰度 + // 列表显示使用中等质量,预览使用高质量 + const optimizedUrl = getListImageUrl(validUrl, 750); + const optimizedThumbnailUrl = getListImageUrl(validThumbnailUrl, 400); + const originalUrl = getOriginalImageUrl(validUrl); // 保存原图URL用于预览 + + return { + ...mediaItem, + url: optimizedUrl, // 列表显示用优化后的URL + thumbnailUrl: optimizedThumbnailUrl, + originalUrl: originalUrl, // 保存原图URL + type: mediaItem.type || 'image', + loading: true // 初始状态为加载中 + }; + }).filter(Boolean); + } else if (feed.images && Array.isArray(feed.images)) { + processedMedia = feed.images.map(imageUrl => { + // 优化图片URL,提高清晰度 + const optimizedUrl = getListImageUrl(imageUrl, 750); + const originalUrl = getOriginalImageUrl(imageUrl); + return { + url: optimizedUrl, + thumbnailUrl: optimizedUrl, + originalUrl: originalUrl, + type: 'image', + loading: true // 初始状态为加载中 + }; + }); + } + + // 处理评论数据,格式化评论时间,组织嵌套结构 + let processedComments = []; + if (feed.comments && Array.isArray(feed.comments) && feed.comments.length > 0) { + // 获取当前用户ID,用于判断是否是自己的评论 + const app = getApp(); + const currentUser = app.globalData.userInfo?.user || {}; + const currentUserId = currentUser.id || currentUser.userId || currentUser.customId || ''; + + // 分离一级评论和回复 + const topLevelComments = []; // 一级评论(没有replyToId的) + const repliesList = []; // 所有回复(有replyToId的) + + feed.comments.forEach((item, idx) => { + // 判断是否是当前用户的评论 + const itemUserId = item.userId || item.user?.id || item.user?.userId || ''; + const isOwn = currentUserId && itemUserId && currentUserId.toString() === itemUserId.toString(); + + // 确保user对象存在,如果不存在则创建默认值 + const user = item.user || {}; + if (!user.nickname && item.userName) { + user.nickname = item.userName; + } + if (!user.nickname) { + user.nickname = '未知用户'; + } + + if (!item.replyToId) { + // 一级评论 + topLevelComments.push({ + ...item, + id: item.id || item.uuid || `comment_${feedIdx}_${idx}`, + formattedTime: item.formattedTime || this.formatCommentTime(item.createdAt || ''), + replies: [], + visibleReplyCount: 5, // 默认显示5条回复 + isOwn: isOwn, + user: user // 确保user对象被绑定 + }); + } else { + // 回复 + repliesList.push({ + ...item, + id: item.id || item.uuid || `reply_${feedIdx}_${idx}`, + formattedTime: item.formattedTime || this.formatCommentTime(item.createdAt || ''), + isOwn: isOwn, + user: user // 确保user对象被绑定 + }); + } + }); + + // 将回复组织到对应的一级评论下(支持多级嵌套) + // 使用多次遍历的方式,确保所有回复都能正确找到父节点 + let remainingReplies = [...repliesList]; + let maxIterations = 10; // 防止无限循环 + let iteration = 0; + + while (remainingReplies.length > 0 && iteration < maxIterations) { + iteration++; + const newRemainingReplies = []; + + remainingReplies.forEach(reply => { + // 先尝试在一级评论中查找 + const parentComment = topLevelComments.find(c => c.id === reply.replyToId); + if (parentComment) { + // 回复一级评论 + if (!parentComment.replies) { + parentComment.replies = []; + } + // 设置 replyToUser(如果父评论有 user 对象) + if (parentComment.user) { + reply.replyToUser = parentComment.user; + } + parentComment.replies.push(reply); + } else { + // 尝试在所有已处理的回复中查找父回复 + let found = false; + for (let comment of topLevelComments) { + if (comment.replies && comment.replies.length > 0) { + const targetReply = comment.replies.find(r => r.id === reply.replyToId); + if (targetReply) { + // 找到父回复,设置 replyToUser 并添加到同一评论的 replies 中 + if (targetReply.user) { + reply.replyToUser = targetReply.user; + } + // 在父回复后插入 + const targetIndex = comment.replies.findIndex(r => r.id === reply.replyToId); + if (targetIndex >= 0) { + comment.replies.splice(targetIndex + 1, 0, reply); + } else { + comment.replies.push(reply); + } + found = true; + break; + } + } + } + + if (!found) { + // 如果找不到父节点,可能是父节点还未处理,留到下一轮 + newRemainingReplies.push(reply); + } + } + }); + + remainingReplies = newRemainingReplies; + + // 如果这一轮没有处理任何回复,说明有循环依赖或找不到父节点,跳出 + if (remainingReplies.length === repliesList.length && iteration > 1) { + break; + } + } + + // 如果还有剩余回复(找不到父节点),作为第一个评论的回复(兜底处理) + if (remainingReplies.length > 0 && topLevelComments.length > 0) { + if (!topLevelComments[0].replies) { + topLevelComments[0].replies = []; + } + topLevelComments[0].replies.push(...remainingReplies); + } + + // 对一级评论按时间倒序排序(最新的在前),确保与本地添加评论的顺序一致 + topLevelComments.sort((a, b) => { + const timeA = new Date(a.createdAt || 0).getTime(); + const timeB = new Date(b.createdAt || 0).getTime(); + return timeB - timeA; // 倒序:最新在前 + }); + + // 对每个评论的回复也按时间倒序排序 + topLevelComments.forEach(comment => { + if (comment.replies && comment.replies.length > 0) { + comment.replies.sort((a, b) => { + const timeA = new Date(a.createdAt || 0).getTime(); + const timeB = new Date(b.createdAt || 0).getTime(); + return timeB - timeA; // 倒序:最新在前 + }); + } + }); + + processedComments = topLevelComments; + } + + return { + ...feed, + user: { + ...feedUser, + avatar: validAvatar, + nickname: feedUser.nickname || feedUser.customId || feedUser.phone || '未知用户', + }, + formattedTime: formattedTime, + media: processedMedia, + comments: processedComments || [], // 确保是数组 + visibleCommentCount: feed.visibleCommentCount || 20 // 默认显示20条评论,如果已存在则保留 + }; + }); + + // 排序动态 + const sortedFeeds = this.sortFeeds(processedFeeds); + + // 去重处理 + let finalFeeds = sortedFeeds; + if (this.data.page !== 1 && this.data.feedList && this.data.feedList.length > 0) { + // 获取现有动态ID的集合 + const existingIds = new Set(this.data.feedList.map(item => item.id || item.uuid || item.dynamicId)); + // 过滤掉已经存在的动态 + finalFeeds = sortedFeeds.filter(feed => { + const feedId = feed.id || feed.uuid || feed.dynamicId; + // 如果没有ID或ID不存在于现有集合中保留动态 + return !feedId || !existingIds.has(feedId); + }); + } + + const feedsToSet = finalFeeds.filter(feed => feed && typeof feed === 'object'); + + const updatedFeedList = this.data.page === 1 ? feedsToSet : [...this.data.feedList, ...feedsToSet]; + const pendingFeedUuid = this.data.pendingFeedUuid; + const foundTarget = pendingFeedUuid + ? updatedFeedList.some(feed => { + const feedId = feed.uuid || feed.id || feed.dynamicId; + return feedId && feedId === pendingFeedUuid; + }) + : false; + + // 🔥 提取唯一用户列表 + const uniqueUsers = this.extractUniqueUsers(updatedFeedList); + + this.setData({ + feedList: updatedFeedList, + userList: uniqueUsers, + page: this.data.page + 1, + noMore: !res.data.data.hasMore, + loading: false + }, () => { + this.afterFeedListUpdate(foundTarget, !res.data.data.hasMore); + }); + }, + fail: (err) => { + console.error(`=== 接口请求失败(${fullRequestUrl}) ===`, err); + this.setData({ loading: false }); + wx.showToast({ + title: '加载失败,请检查网络', + icon: 'none' + }); + } + }); + }, + + // 🔥 从动态列表中提取唯一用户 + extractUniqueUsers(feedList) { + const userMap = new Map(); + + if (!feedList || !Array.isArray(feedList)) { + return []; + } + + feedList.forEach(feed => { + if (feed.user && feed.user.customId) { + const customId = feed.user.customId; + // 如果用户不存在或者当前动态更新的用户信息更完整,则更新 + if (!userMap.has(customId) || + (!userMap.get(customId).avatar && feed.user.avatar) || + (!userMap.get(customId).nickname && feed.user.nickname)) { + userMap.set(customId, { + customId: customId, + avatar: feed.user.avatar || '/images/default-avatar.png', + nickname: feed.user.nickname || feed.user.customId || '用户' + }); + } + } + }); + + return Array.from(userMap.values()); + }, + + afterFeedListUpdate(foundTarget, noMore) { + const pendingUuid = this.data.pendingFeedUuid; + if (!pendingUuid) { + return; + } + + if (foundTarget) { + const targetFeed = this.data.feedList.find(feed => { + const feedId = feed.uuid || feed.id || feed.dynamicId; + return feedId && feedId === pendingUuid; + }); + + if (targetFeed) { + const targetId = targetFeed.uuid || targetFeed.id || targetFeed.dynamicId; + const anchorId = `feed-item-${targetId}`; + this.setData({ + scrollIntoFeedId: anchorId, + highlightFeedUuid: targetId, + pendingFeedUuid: '' + }); + + if (this.highlightTimer) { + clearTimeout(this.highlightTimer); + } + this.highlightTimer = setTimeout(() => { + this.setData({ + highlightFeedUuid: '', + scrollIntoFeedId: '' + }); + }, 4000); + } + return; + } + + if (!noMore) { + this.loadFeedList(); + } else { + this.setData({ pendingFeedUuid: '' }); + } + }, + + applyRedirectPayload(payload) { + const safeLatitude = parseFloat(payload.latitude); + const safeLongitude = parseFloat(payload.longitude); + if (Number.isNaN(safeLatitude) || Number.isNaN(safeLongitude)) { + return; + } + + const safeRadius = Math.max(10, parseInt(payload.radius, 10) || this.data.radius); + const feedUuid = payload.feedUuid || ''; + const redirectToken = payload.token || `${Date.now()}`; + + this.setData({ + latitude: safeLatitude, + longitude: safeLongitude, + radius: safeRadius, + modeFrom: payload.mode || 'map', + feedUuid, + pendingFeedUuid: feedUuid, + lastRedirectToken: redirectToken + }, () => { + this.resetAndLoadFeedList(); + }); + }, + + // 排序动态 + sortFeeds(feeds) { + const currentUser = getApp().globalData.userInfo || {}; + + const currentGender = currentUser.gender !== undefined ? currentUser.gender : 0; + + return [...feeds].sort((a, b) => { + // 确保用户信息存在 + const aUser = a.user || {}; + const bUser = b.user || {}; + const isAFriend = aUser.isFriend || false; + const isBFriend = bUser.isFriend || false; + + // 好友优先级高于非好友 + if (isAFriend && !isBFriend) return -1; + if (!isAFriend && isBFriend) return 1; + + // 好友/非好友分组内排序 + const aCreateTime = new Date(a.createdAt || 0).getTime(); + const bCreateTime = new Date(b.createdAt || 0).getTime(); + + if (isAFriend && isBFriend) { + // 好友:按发布时间倒序 + return bCreateTime - aCreateTime; + } else { + // 非好友:优先异性,再按时间倒序 + const aGender = aUser.gender !== undefined ? aUser.gender : currentGender; + const bGender = bUser.gender !== undefined ? bUser.gender : currentGender; + + const isAOpposite = aGender !== currentGender; + const isBOpposite = bGender !== currentGender; + + if (isAOpposite && !isBOpposite) return -1; + if (!isAOpposite && isBOpposite) return 1; + + // 同性别:按时间倒序 + return bCreateTime - aCreateTime; + } + }); + }, + + // 格式化时间 + formatTime(timeStr) { + if (!timeStr) return '未知时间'; + + const createTime = new Date(timeStr); + if (isNaN(createTime.getTime())) return '未知时间'; + + const now = new Date(); + const diffMinutes = Math.floor((now - createTime) / (1000 * 60)); + + // 5分钟内:刚刚 + if (diffMinutes < 5) return '刚刚'; + + // 格式化日期时间 + const year = createTime.getFullYear(); + const month = String(createTime.getMonth() + 1).padStart(2, '0'); + const day = String(createTime.getDate()).padStart(2, '0'); + const hour = String(createTime.getHours()).padStart(2, '0'); + const minute = String(createTime.getMinutes()).padStart(2, '0'); + + // 跨年份显示完整日期,同年份省略年份 + return year === this.data.currentYear + ? `${month}月${day}日 ${hour}:${minute}` + : `${year}年${month}月${day}日 ${hour}:${minute}`; + }, + + // 格式化评论时间 + formatCommentTime(timeStr) { + if (!timeStr) return ''; + + const commentTime = new Date(timeStr); + if (isNaN(commentTime.getTime())) return ''; + + const now = new Date(); + const diffMinutes = Math.floor((now - commentTime) / (1000 * 60)); + + // 5分钟内:显示"刚刚" + if (diffMinutes < 5) return '刚刚'; + + // 格式化日期时间 + const year = commentTime.getFullYear(); + const month = commentTime.getMonth() + 1; // 不加前导0,直接显示月份 + const day = commentTime.getDate(); + const hour = String(commentTime.getHours()).padStart(2, '0'); + const minute = String(commentTime.getMinutes()).padStart(2, '0'); + + // 当前年份:显示不带年份的日期和时间,例如:8月24日 17:11 + // 非当前年份:显示带年份的日期和时间,例如:2024年 8月24日 17:11 + const currentYear = now.getFullYear(); + return year === currentYear + ? `${month}月${day}日 ${hour}:${minute}` + : `${year}年 ${month}月${day}日 ${hour}:${minute}`; + }, + + // 滚动到底部加载更多 + onReachBottom() { + this.loadFeedList(); + }, + + // 返回首页功能 + navigateBackHome() { + wx.switchTab({ + url: '/pages/map/map' + }); + }, + + + handlePost() { + + // 跳转到发布页面 + wx.navigateTo({ + url: '/subpackages/media/edits/edits', + fail: (err) => { + console.error('跳转失败:', err); + wx.showToast({ + title: '跳转发布页面失败', + icon: 'none' + }); + } + }); + }, + + onHide() { + if (this.highlightTimer) { + clearTimeout(this.highlightTimer); + this.highlightTimer = null; + } + }, + + onUnload() { + if (this.highlightTimer) { + clearTimeout(this.highlightTimer); + this.highlightTimer = null; + } + }, + + + // 图片预览 + previewImage(e) { + try { + // 获取当前点击的图片索引和动态索引 + const { index, feedIndex } = e.currentTarget.dataset; + + // 获取当前动态的图片列表 + const feed = this.data.feedList[feedIndex]; + if (!feed || !feed.media || !feed.media.length) { + console.error('没有找到媒体数据'); + return; + } + + // 优先使用原始图片URL或高质量图片,确保预览完整清晰的图片 + const imageUrls = feed.media + .filter(item => item.type === 'image' && (item.originalUrl || item.url)) + .map(item => { + // 如果有原图URL,使用原图;否则使用高质量优化URL + if (item.originalUrl) { + return getPreviewImageUrl(item.originalUrl); + } + return getPreviewImageUrl(item.url); + }); + + if (!imageUrls.length) { + console.error('没有有效的图片URL'); + return; + } + + // 🔥 设置标志,防止预览关闭后触发页面刷新 + this._skipNextOnShowReload = true; + + // 调用微信小程序的图片预览API + wx.previewImage({ + current: imageUrls[index], // 当前显示图片的URL + urls: imageUrls, // 需要预览的图片URL列表 + success: () => { + // 预览打开成功,标志已设置,关闭时会触发 onShow + }, + fail: (err) => { + console.error('图片预览失败:', err); + // 预览失败,清除标志 + this._skipNextOnShowReload = false; + wx.showToast({ + title: '预览图片失败', + icon: 'none' + }); + } + }); + } catch (error) { + console.error('图片预览过程中出错:', error); + // 出错时清除标志 + this._skipNextOnShowReload = false; + wx.showToast({ + title: '预览图片失败', + icon: 'none' + }); + } + }, + + // 图片加载成功 + onImageLoad(e) { + const { index, feedIndex } = e.currentTarget.dataset; + const feedList = this.data.feedList; + + if (feedList[feedIndex] && feedList[feedIndex].media && feedList[feedIndex].media[index]) { + // 更新对应图片的加载状态 + const updatePath = `feedList[${feedIndex}].media[${index}].loading`; + this.setData({ + [updatePath]: false + }); + } + }, + + // 图片加载失败 + onImageError(e) { + const { index, feedIndex } = e.currentTarget.dataset; + const feedList = this.data.feedList; + + if (feedList[feedIndex] && feedList[feedIndex].media && feedList[feedIndex].media[index]) { + // 加载失败也隐藏 loading + const updatePath = `feedList[${feedIndex}].media[${index}].loading`; + this.setData({ + [updatePath]: false + }); + } + }, + + // 点击头像进入个人资料 + navigateToUserProfile(e) { + const customId = e.currentTarget.dataset.customId; + + if (!customId) return; + + // 获取当前用户信息 + const currentUser = getApp().globalData.userInfo || {}; + + const currentUserId = currentUser.user.customId || ''; + + // 检查是否是当前用户自己 + if (customId === currentUserId) { + this.navigateToSelfProfile(customId); + return; + } + + // 使用friendAPI判断是否是好友关系 + this.checkFriendRelation(customId); + }, + + // 跳转到个人主页 + navigateToSelfProfile(customId) { + + const targetUrl = `/subpackages/profile/profile/profile?customId=${customId}`; + wx.navigateTo({ + url: targetUrl, + fail: (err) => { + console.error('跳转个人主页失败:', err); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none' + }); + } + }); + }, + + // 检查好友关系 + async checkFriendRelation(customId) { + try { + const friendAPI = require('../../utils/friend-api.js'); + + // 显示加载提示 + wx.showLoading({ + title: '加载中...', + mask: true + }); + + // 获取好友详情 + const friendDetailResponse = await friendAPI.getFriendDetail(customId); + + wx.hideLoading(); + + if (friendDetailResponse && friendDetailResponse.code === 0 && friendDetailResponse.data){ + // 成功获取好友详情,说明是好友关系 + this.navigateToFriendProfile(customId); + return; + } + + // 跳转到陌生人主页 + this.navigateToStrangerProfile(customId); + + } catch (error) { + wx.hideLoading(); + console.error('检查好友关系失败:', error); + + // 跳转到陌生人主页 + this.navigateToStrangerProfile(customId); + } + }, + + // 跳转到好友主页 + navigateToFriendProfile(customId) { + + const targetUrl = `/subpackages/social/friend-detail/friend-detail?customId=${customId}`; + wx.navigateTo({ + url: targetUrl, + fail: (err) => { + console.error('跳转好友主页失败:', err); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none' + }); + } + }); + }, + + // 跳转到陌生人主页 + navigateToStrangerProfile(customId) { + + const targetUrl = `/subpackages/social/user-preview/user-preview?customId=${customId}`; + wx.navigateTo({ + url: targetUrl, + fail: (err) => { + console.error('跳转陌生人主页失败:', err); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none' + }); + } + }); + }, + + // 处理点赞 + async handleLike(e) { + const feedUuid = e.currentTarget.dataset.feedUuid; + const isLiked = e.currentTarget.dataset.isliked; + const feedIndex = e.currentTarget.dataset.feedIndex; // 获取当前动态索引 + if (!feedUuid) { + wx.showToast({ + title: '动态ID不存在', + icon: 'none' + }); + return; + } + + // 检查登录状态 + const app = getApp(); + if (!app.globalData.isLoggedIn) { + wx.showToast({ + title: '请先登录', + icon: 'none' + }); + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }); + }, 1500); + return; + } + + // TODO: 调用点赞API + console.log('点赞动态:', feedUuid); + + if(!isLiked){ + const response = await this.apiClient.addLikeDynamic(feedUuid); + if(response){ + if(response.code==200){ + wx.showToast({ + title: response.data.message, + icon: 'success', + duration: 1000 + }); + }else{ + wx.showToast({ + title: response.message, + icon: 'none', + duration: 1000 + }); + } + } + // 更新点赞状态和数量 + this.updateLikeStatus(feedIndex, true); + }else{ + const responseDelete= await this.apiClient.deleteLikeDynamic(feedUuid); + if(responseDelete){ + if(responseDelete.code==200){ + wx.showToast({ + title: responseDelete.data.message, + icon: 'success', + duration: 1000 + }); + }else{ + wx.showToast({ + title: responseDelete.message, + icon: 'none', + duration: 1000 + }); + } + } + // 更新点赞状态和数量 + this.updateLikeStatus(feedIndex, false); + } + + }, + + + +// 新增更新点赞状态的方法 +updateLikeStatus(feedIndex, isLiked) { + // 复制当前的动态列表 + const feedList = [...this.data.feedList]; + + // 检查当前动态是否存在 + if (feedList[feedIndex]) { + // 初始化interactions对象(防止undefined错误) + if (!feedList[feedIndex].interactions) { + feedList[feedIndex].interactions = { + likeCount: 0 + }; + } + + // 更新点赞状态 + feedList[feedIndex].isLiked = isLiked; + + // 更新点赞数量(点赞+1,取消点赞-1) + feedList[feedIndex].interactions.likeCount = + (feedList[feedIndex].interactions.likeCount || 0) + (isLiked ? 1 : -1); + + // 确保数量不会小于0 + if (feedList[feedIndex].interactions.likeCount < 0) { + feedList[feedIndex].interactions.likeCount = 0; + } + + // 更新数据 + this.setData({ + feedList: feedList + }); + } + +}, + // 处理评论 - 显示评论弹窗 + async handleComment(e) { + const feedUuid = e.currentTarget.dataset.feedUuid; + const feedIndex = e.currentTarget.dataset.feedIndex; + + if (!feedUuid) { + wx.showToast({ + title: '动态ID不存在', + icon: 'none' + }); + return; + } + + // 检查登录状态 + const app = getApp(); + if (!app.globalData.isLoggedIn) { + wx.showToast({ + title: '请先登录', + icon: 'none' + }); + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }); + }, 1500); + return; + } + + // 显示弹窗并加载评论 + this.setData({ + showCommentModal: true, + currentFeedUuid: feedUuid, + currentFeedIndex: feedIndex, + commentInputValue: '' + }); + + // 加载评论列表 + await this.loadComments(feedUuid, feedIndex); + }, + + // 加载评论列表 + async loadComments(feedUuid, feedIndex) { + try { + // 先尝试从feed数据中获取评论 + const feed = this.data.feedList[feedIndex]; + let comments = feed?.comments || []; + + // 如果有评论数据,格式化时间 + if (comments && comments.length > 0) { + comments = comments.map(comment => { + return { + ...comment, + formattedTime: comment.formattedTime || this.formatCommentTime(comment.createdAt || '') + }; + }); + } + + // 如果没有评论数据,尝试从API获取(如果有获取评论的API) + // TODO: 如果需要从API获取评论列表,在这里添加 + + this.setData({ + currentComments: comments + }); + } catch (error) { + console.error('加载评论失败:', error); + this.setData({ + currentComments: [] + }); + } + }, + + // 关闭评论弹窗 + closeCommentModal() { + this.setData({ + showCommentModal: false, + currentFeedUuid: '', + currentFeedIndex: -1, + currentComments: [], + commentInputValue: '' + }); + }, + + // 防止点击内容区域关闭弹窗 + preventClose() { + // 空函数,阻止事件冒泡 + }, + + // 评论输入 + onCommentInput(e) { + this.setData({ + commentInputValue: e.detail.value + }); + }, + + // 提交评论 + async submitComment() { + const { currentFeedUuid, currentFeedIndex, commentInputValue } = this.data; + + if (!commentInputValue || !commentInputValue.trim()) { + wx.showToast({ + title: '请输入评论内容', + icon: 'none', + duration: 1500 + }); + return; + } + + // 获取当前用户信息 + const app = getApp(); + const currentUser = app.globalData.userInfo?.user || {}; + const nickname = currentUser.nickname || currentUser.customId || '未知用户'; + + try { + const response = await this.apiClient.addCommentDynamic(currentFeedUuid, commentInputValue.trim(), null, nickname); + + if (response && response.code === 200) { + wx.showToast({ + title: '评论成功', + icon: 'success', + duration: 1000 + }); + + // 创建新评论对象(新发布的评论默认是自己的) + const newComment = { + id: response.data?.id || `comment_${Date.now()}`, + content: commentInputValue.trim(), + createdAt: response.data?.createdAt || new Date().toISOString(), + user: { + nickname: currentUser.nickname || currentUser.customId || '未知用户', + avatar: currentUser.avatar || '/images/findme-logo.png', + customId: currentUser.customId || '' + }, + formattedTime: this.formatCommentTime(response.data?.createdAt || new Date().toISOString()), + replies: [], + isOwn: true // 新发布的评论默认是自己的 + }; + + // 清空输入框 + this.setData({ + commentInputValue: '' + }); + + // 更新动态的评论列表和数量 - 使用路径更新方式避免渲染错误 + const feed = this.data.feedList[currentFeedIndex]; + if (feed) { + // 初始化 comments 数组(如果不存在) + const currentComments = feed.comments || []; + const updatedComments = [newComment, ...currentComments]; + + // 更新评论数量 + const currentCommentCount = feed.interactions?.commentCount || 0; + const visibleCommentCount = feed.visibleCommentCount || 5; + + // 使用路径更新方式,确保小程序能正确检测数据变化 + const updatePath = {}; + updatePath[`feedList[${currentFeedIndex}].comments`] = updatedComments; + updatePath[`feedList[${currentFeedIndex}].interactions.commentCount`] = currentCommentCount + 1; + + // 确保 visibleCommentCount 存在且至少为20 + if (!feed.visibleCommentCount || feed.visibleCommentCount < 20) { + updatePath[`feedList[${currentFeedIndex}].visibleCommentCount`] = 20; + } + + this.setData(updatePath); + } + + // 更新弹窗中的评论列表 + await this.loadComments(currentFeedUuid, currentFeedIndex); + + // 延迟关闭评论弹窗,让用户看到成功提示 + setTimeout(() => { + this.closeCommentModal(); + }, 800); + } else { + wx.showToast({ + title: response?.message || '评论失败', + icon: 'none', + duration: 1500 + }); + } + } catch (error) { + console.error('提交评论失败:', error); + wx.showToast({ + title: '评论失败,请重试', + icon: 'none', + duration: 1500 + }); + } + }, + + + + // 删除评论 + async deleteComment(e) { + const feedUuid = e.currentTarget.dataset.feedUuid; + const commentId = e.currentTarget.dataset.feedCommentId; + + if (!feedUuid) { + wx.showToast({ + title: '动态ID不存在', + icon: 'none' + }); + return; + } + + // 检查登录状态 + const app = getApp(); + if (!app.globalData.isLoggedIn) { + wx.showToast({ + title: '请先登录', + icon: 'none' + }); + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }); + }, 1500); + return; + } + + + const response = await this.apiClient.deleteCommentDynamic(feedUuid,commentId); + if(response){ + if(response.code==200){ + wx.showToast({ + title: "删除成功", + icon: 'success', + duration: 1000 + }); + }else{ + wx.showToast({ + title: "删除失败", + icon: 'none', + duration: 1000 + }); + } + } + + }, + + // 展开更多评论(每次增加20条,懒加载模式) + expandComments(e) { + const feedIndex = e.currentTarget.dataset.feedIndex; + this.loadMoreComments(feedIndex); + }, + + // 加载更多评论(懒加载,每次加载20条) + loadMoreComments(feedIndex) { + const feed = this.data.feedList[feedIndex]; + + if (feed && feed.comments) { + const currentCount = feed.visibleCommentCount || 20; // 当前显示的评论数量 + const totalCount = feed.comments.length; // 评论总数 + + // 如果已经显示全部,不继续加载 + if (currentCount >= totalCount) { + return; + } + + // 每次增加20条,但不超过总数 + // 例如:初始20条 -> 滚动后40条 -> 再滚动60条 -> 以此类推 + const newCount = Math.min(currentCount + 20, totalCount); + + if (newCount > currentCount) { + // 使用路径更新方式 + this.setData({ + [`feedList[${feedIndex}].visibleCommentCount`]: newCount + }); + } + } + }, + + // 评论区域滚动到底部时触发(懒加载评论和回复) + onCommentScrollToLower(e) { + const feedIndex = e.currentTarget.dataset.feedIndex; + if (feedIndex !== undefined && feedIndex !== null) { + const feed = this.data.feedList[feedIndex]; + + // 先尝试加载更多回复(优先处理回复) + if (feed && feed.comments) { + let hasMoreReplies = false; + feed.comments.forEach((comment, commentIndex) => { + if (comment.replies && comment.replies.length > 0) { + const currentCount = comment.visibleReplyCount || 5; + const totalCount = comment.replies.length; + + // 如果有未显示的回复,自动加载更多 + if (currentCount < totalCount) { + const newCount = Math.min(currentCount + 20, totalCount); + if (newCount > currentCount) { + this.setData({ + [`feedList[${feedIndex}].comments[${commentIndex}].visibleReplyCount`]: newCount + }); + hasMoreReplies = true; + } + } + } + }); + + // 如果有加载了回复,不继续加载评论(避免一次性加载太多) + if (hasMoreReplies) { + return; + } + } + + // 如果没有更多回复需要加载,则加载更多评论 + this.loadMoreComments(feedIndex); + } + }, + + // 展开更多回复(每次增加20条) + expandReplies(e) { + const feedIndex = e.currentTarget.dataset.feedIndex; + const commentIndex = e.currentTarget.dataset.commentIndex; + const feed = this.data.feedList[feedIndex]; + + if (feed && feed.comments && feed.comments[commentIndex]) { + const comment = feed.comments[commentIndex]; + const currentCount = comment.visibleReplyCount || 5; // 当前显示的回复数量(默认5条) + const totalCount = comment.replies ? comment.replies.length : 0; // 回复总数 + + // 每次增加20条,但不超过总数 + // 例如:初始5条 -> 点击后25条 -> 再点击45条 -> 以此类推 + const newCount = Math.min(currentCount + 20, totalCount); + + if (newCount > currentCount) { + // 使用路径更新方式 + this.setData({ + [`feedList[${feedIndex}].comments[${commentIndex}].visibleReplyCount`]: newCount + }); + } + } + }, + + // 点击回复按钮 + handleReplyClick(e) { + const feedIndex = e.currentTarget.dataset.feedIndex; + const commentId = e.currentTarget.dataset.commentId; + const commentIndex = e.currentTarget.dataset.commentIndex; + const replyId = e.currentTarget.dataset.replyId; // 如果是回复二级评论,这是被回复的二级评论ID + const replyToUserName = e.currentTarget.dataset.replyToUser || ''; + + // 生成唯一key:如果有replyId,说明是回复二级回复,key应该包含replyId + const replyKey = replyId + ? `feed_${feedIndex}_comment_${commentId}_reply_${replyId}` + : `feed_${feedIndex}_comment_${commentId}`; + + // 切换回复输入框显示状态 + const showReplyInput = { ...this.data.showReplyInput }; + + // 如果当前输入框已显示,则关闭;否则打开 + if (showReplyInput[replyKey]) { + showReplyInput[replyKey] = false; + this.setData({ + showReplyInput: showReplyInput, + replyInputValue: '', + replyingCommentId: null, + replyingCommentIndex: null, + replyingToCommentId: null + }); + } else { + // 关闭其他所有输入框 + Object.keys(showReplyInput).forEach(key => { + showReplyInput[key] = false; + }); + + // 打开当前输入框 + showReplyInput[replyKey] = true; + + // 获取feedUuid + const feed = this.data.feedList[feedIndex]; + const feedUuid = feed ? (feed.uuid || feed.id || feed.dynamicId) : ''; + + // 如果有replyId,说明是回复二级评论,需要设置replyToId + this.setData({ + showReplyInput: showReplyInput, + replyInputValue: replyToUserName ? `@${replyToUserName} ` : '', + replyingCommentId: commentId, + replyingCommentIndex: commentIndex, + replyingToCommentId: replyId || null, + currentFeedIndex: feedIndex, + currentFeedUuid: feedUuid + }); + } + }, + + // 回复输入 + onReplyInput(e) { + this.setData({ + replyInputValue: e.detail.value + }); + }, + + // 提交回复 + async submitReply(e) { + // 防止重复点击 + if (this.data.submittingReply) { + return; + } + + const feedIndex = e.currentTarget.dataset.feedIndex; + const commentId = e.currentTarget.dataset.commentId; + const commentIndex = e.currentTarget.dataset.commentIndex; + const { replyInputValue, replyingToCommentId } = this.data; + + // 移除 @用户名 前缀后,检查剩余内容是否为空 + const contentWithoutMention = replyInputValue ? replyInputValue.trim().replace(/^@[\S]+\s+/, '') : ''; + if (!replyInputValue || !replyInputValue.trim() || !contentWithoutMention) { + wx.showToast({ + title: '请输入回复内容', + icon: 'none', + duration: 1500 + }); + return; + } + + // 设置提交状态 + this.setData({ + submittingReply: true + }); + + // 获取feedUuid + const feed = this.data.feedList[feedIndex]; + if (!feed) { + wx.showToast({ + title: '动态不存在', + icon: 'none' + }); + return; + } + + const feedUuid = feed.uuid || feed.id || feed.dynamicId; + if (!feedUuid) { + wx.showToast({ + title: '动态ID不存在', + icon: 'none' + }); + return; + } + + // 检查登录状态并获取当前用户信息 + const app = getApp(); + if (!app.globalData.isLoggedIn) { + wx.showToast({ + title: '请先登录', + icon: 'none' + }); + setTimeout(() => { + wx.navigateTo({ + url: '/pages/login/login' + }); + }, 1500); + return; + } + + // 获取当前用户信息 + const currentUser = app.globalData.userInfo?.user || {}; + const nickname = currentUser.nickname || currentUser.customId || '未知用户'; + + try { + // 调用API提交回复(如果replyingToCommentId存在,说明是回复二级评论) + const replyToId = replyingToCommentId || commentId; + const response = await this.apiClient.addCommentDynamic(feedUuid, replyInputValue.trim(), replyToId, nickname); + + if (response && response.code === 200) { + wx.showToast({ + title: '回复成功', + icon: 'success', + duration: 1000 + }); + + // 创建新回复对象(新发布的回复默认是自己的) + const newReply = { + id: response.data?.id || `reply_${Date.now()}`, + content: replyInputValue.trim().replace(/^@[\S]+\s+/, ''), // 移除@用户名前缀 + createdAt: response.data?.createdAt || new Date().toISOString(), + user: { + nickname: currentUser.nickname || currentUser.customId || '未知用户', + avatar: currentUser.avatar || '/images/findme-logo.png', + customId: currentUser.customId || '' + }, + formattedTime: this.formatCommentTime(response.data?.createdAt || new Date().toISOString()), + replyToId: replyToId, + replyToUser: replyingToCommentId ? this.findReplyUser(this.data.feedList[feedIndex], commentId, replyingToCommentId) : null, + isOwn: true // 新发布的回复默认是自己的 + }; + + // 更新动态的评论列表 - 使用路径更新方式 + const feed = this.data.feedList[feedIndex]; + if (feed && feed.comments && feed.comments[commentIndex]) { + const comment = feed.comments[commentIndex]; + + // 初始化 replies 数组(如果不存在) + const currentReplies = comment.replies || []; + const updatedReplies = [newReply, ...currentReplies]; + + // 更新评论数量 + const currentCommentCount = feed.interactions?.commentCount || 0; + + // 使用路径更新方式,确保小程序能正确检测数据变化 + const updatePath = {}; + updatePath[`feedList[${feedIndex}].comments[${commentIndex}].replies`] = updatedReplies; + updatePath[`feedList[${feedIndex}].interactions.commentCount`] = currentCommentCount + 1; + + // 如果当前显示的回复数少于5条,增加到5条以确保能看到新回复 + const currentVisibleReplyCount = comment.visibleReplyCount || 5; + if (currentVisibleReplyCount < 5) { + updatePath[`feedList[${feedIndex}].comments[${commentIndex}].visibleReplyCount`] = 5; + } + + // 清空回复输入框和状态 + // 根据是否有replyingToCommentId来生成正确的key + const currentReplyingToCommentId = this.data.replyingToCommentId; + const replyKey = currentReplyingToCommentId + ? `feed_${feedIndex}_comment_${commentId}_reply_${currentReplyingToCommentId}` + : `feed_${feedIndex}_comment_${commentId}`; + const showReplyInput = { ...this.data.showReplyInput }; + showReplyInput[replyKey] = false; + + updatePath.showReplyInput = showReplyInput; + updatePath.replyInputValue = ''; + updatePath.replyingCommentId = null; + updatePath.replyingCommentIndex = null; + updatePath.replyingToCommentId = null; + updatePath.submittingReply = false; + + this.setData(updatePath); + } else { + // 如果找不到对应数据,只更新状态 + this.setData({ + submittingReply: false + }); + } + } else { + this.setData({ + submittingReply: false // 恢复提交状态 + }); + wx.showToast({ + title: response?.message || '回复失败', + icon: 'none', + duration: 1500 + }); + } + } catch (error) { + console.error('提交回复失败:', error); + this.setData({ + submittingReply: false // 恢复提交状态 + }); + wx.showToast({ + title: '回复失败,请重试', + icon: 'none', + duration: 1500 + }); + } + }, + + // 查找被回复的用户信息 + findReplyUser(feed, commentId, replyId) { + if (!feed || !feed.comments) return null; + + const comment = feed.comments.find(c => c.id === commentId); + if (!comment || !comment.replies) return null; + + const reply = comment.replies.find(r => r.id === replyId); + return reply ? reply.user : null; + }, + + // 删除评论 + async deleteComment(e) { + const { feedIndex, commentId, commentIndex } = e.currentTarget.dataset; + + // 检查参数(feedIndex可能是0,所以不能用!feedIndex判断) + if (feedIndex === undefined || feedIndex === null || commentId === undefined || commentId === null || commentIndex === undefined || commentIndex === null) { + console.error('删除评论参数错误:', { feedIndex, commentId, commentIndex, dataset: e.currentTarget.dataset }); + wx.showToast({ + title: '参数错误', + icon: 'none' + }); + return; + } + + console.log('删除评论,参数:', { feedIndex, commentId, commentIndex }); + + // 确认删除 + wx.showModal({ + title: '删除评论', + content: '确定要删除这条评论吗?', + confirmText: '删除', + confirmColor: '#ff4757', + success: async (res) => { + if (!res.confirm) return; + + const feed = this.data.feedList[feedIndex]; + if (!feed) { + wx.showToast({ + title: '动态不存在', + icon: 'none' + }); + return; + } + + const feedUuid = feed.uuid || feed.id || feed.dynamicId; + if (!feedUuid) { + wx.showToast({ + title: '动态ID不存在', + icon: 'none' + }); + return; + } + + try { + wx.showLoading({ + title: '删除中...', + mask: true + }); + + const response = await this.apiClient.deleteCommentDynamic(feedUuid, commentId); + + if (response && response.code === 200) { + wx.hideLoading(); + wx.showToast({ + title: '删除成功', + icon: 'success', + duration: 1000 + }); + + // 从本地列表中删除评论(通过ID匹配,更安全) + const currentComments = this.data.feedList[feedIndex].comments || []; + const updatedComments = currentComments.filter((c) => c.id !== commentId); + const currentCommentCount = (this.data.feedList[feedIndex].interactions.commentCount || 0) - 1; + + // 使用路径更新方式 + const updatePath = {}; + updatePath[`feedList[${feedIndex}].comments`] = updatedComments; + updatePath[`feedList[${feedIndex}].interactions.commentCount`] = Math.max(0, currentCommentCount); + + this.setData(updatePath); + } else { + wx.hideLoading(); + wx.showToast({ + title: response?.message || '删除失败', + icon: 'none', + duration: 1500 + }); + } + } catch (error) { + console.error('删除评论失败:', error); + wx.hideLoading(); + wx.showToast({ + title: '删除失败,请重试', + icon: 'none', + duration: 1500 + }); + } + } + }); + }, + + // 删除回复 + async deleteReply(e) { + const { feedIndex, commentId, commentIndex, replyId, replyIndex } = e.currentTarget.dataset; + + // 检查参数(feedIndex可能是0,所以不能用!feedIndex判断) + if (feedIndex === undefined || feedIndex === null || commentId === undefined || commentId === null || commentIndex === undefined || commentIndex === null || replyId === undefined || replyId === null || replyIndex === undefined || replyIndex === null) { + console.error('删除回复参数错误:', { feedIndex, commentId, commentIndex, replyId, replyIndex, dataset: e.currentTarget.dataset }); + wx.showToast({ + title: '参数错误', + icon: 'none' + }); + return; + } + + console.log('删除回复,参数:', { feedIndex, commentId, commentIndex, replyId, replyIndex }); + + // 确认删除 + wx.showModal({ + title: '删除回复', + content: '确定要删除这条回复吗?', + confirmText: '删除', + confirmColor: '#ff4757', + success: async (res) => { + if (!res.confirm) return; + + const feed = this.data.feedList[feedIndex]; + if (!feed) { + wx.showToast({ + title: '动态不存在', + icon: 'none' + }); + return; + } + + const feedUuid = feed.uuid || feed.id || feed.dynamicId; + if (!feedUuid) { + wx.showToast({ + title: '动态ID不存在', + icon: 'none' + }); + return; + } + + try { + wx.showLoading({ + title: '删除中...', + mask: true + }); + + const response = await this.apiClient.deleteCommentDynamic(feedUuid, replyId); + + if (response && response.code === 200) { + wx.hideLoading(); + wx.showToast({ + title: '删除成功', + icon: 'success', + duration: 1000 + }); + + // 从本地列表中删除回复(通过ID匹配,更安全) + const currentComments = this.data.feedList[feedIndex].comments || []; + // 通过commentId查找评论,而不是使用commentIndex(更安全) + const targetCommentIndex = currentComments.findIndex(c => c.id === commentId); + if (targetCommentIndex >= 0) { + const targetComment = currentComments[targetCommentIndex]; + if (targetComment && targetComment.replies) { + const updatedReplies = targetComment.replies.filter((r) => r.id !== replyId); + const currentCommentCount = (this.data.feedList[feedIndex].interactions.commentCount || 0) - 1; + + // 使用路径更新方式 + const updatePath = {}; + updatePath[`feedList[${feedIndex}].comments[${targetCommentIndex}].replies`] = updatedReplies; + updatePath[`feedList[${feedIndex}].interactions.commentCount`] = Math.max(0, currentCommentCount); + + this.setData(updatePath); + } + } + } else { + wx.hideLoading(); + wx.showToast({ + title: response?.message || '删除失败', + icon: 'none', + duration: 1500 + }); + } + } catch (error) { + console.error('删除回复失败:', error); + wx.hideLoading(); + wx.showToast({ + title: '删除失败,请重试', + icon: 'none', + duration: 1500 + }); + } + } + }); + }, +}); + + diff --git a/pages/circle/circle.json b/pages/circle/circle.json new file mode 100644 index 0000000..8c972a6 --- /dev/null +++ b/pages/circle/circle.json @@ -0,0 +1,9 @@ +{ + "navigationBarTitleText": "圈子", + "navigationBarBackgroundColor": "#000000", + "navigationBarTextStyle": "white", + "disableScroll": false, + "usingComponents": {}, + "enablePullDownRefresh": false, + "navigationStyle": "default" +} diff --git a/pages/circle/circle.wxml b/pages/circle/circle.wxml new file mode 100644 index 0000000..b5638fc --- /dev/null +++ b/pages/circle/circle.wxml @@ -0,0 +1,255 @@ + + + + + + + + + + 社交圈子 + + + + + + + + + + 发动态 + + + + + + + + + + + + {{feed.content || '无内容'}} + + + + + + + {{feed.interactions.likeCount || 0}} + + + 添加评论 + {{feed.interactions.commentCount || 0}} + + + + + + + + + + + + + + + + + + + + + + + {{comment.user ? comment.user.nickname : '未知用户'}} + - + {{comment.content}} + + + {{comment.formattedTime}} + 回复 + 删除 + + + + + + + + + {{reply.user ? reply.user.nickname : '未知用户'}} + 回复 + {{reply.replyToUser.nickname || '未知用户'}} + + + + {{reply.content}} + + + + {{reply.formattedTime}} + 回复 + 删除 + + + + + + + + {{submittingReply ? '发送中...' : '发送'}} + + + + + + 上划查看更多回复 + + + + ——展开更多回复 + + + + + + + + {{submittingReply ? '发送中...' : '发送'}} + + + + + ——展开更多回复 + + + + + + + + 加载中... + 没有更多内容了 + + + + + + + 暂无动态 + + + + + + + + 评论 + + × + + + + + + + + 发送 + + + + + + diff --git a/pages/circle/circle.wxs b/pages/circle/circle.wxs new file mode 100644 index 0000000..4d96f97 --- /dev/null +++ b/pages/circle/circle.wxs @@ -0,0 +1,19 @@ +// 截取数组的前n个元素 +function slice(array, count) { + if (!array) { + return []; + } + var len = array.length; + if (len === 0) { + return []; + } + var num = parseInt(count) || 5; + if (num <= 0) { + num = 5; + } + return array.slice(0, num > len ? len : num); +} + +module.exports = { + slice: slice +}; diff --git a/pages/circle/circle.wxss b/pages/circle/circle.wxss new file mode 100644 index 0000000..fa04644 --- /dev/null +++ b/pages/circle/circle.wxss @@ -0,0 +1,933 @@ +/* 页面背景 */ +page { + background-color: #000000; + margin: 0; + padding: 0; +} + +/* 容器样式 */ +.circle-container { + background-color: #0f0f12; + color: #ffffff; + height: 100vh; + display: flex; + flex-direction: column; + overflow: hidden; +} + +/* 滚动视图 */ +.scroll-view { + flex: 1; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + scroll-behavior: smooth; +} + +/* 单条动态 */ +.feed-item { + padding: 20rpx 0; + display: flex; + flex-direction: column; +} + +/* 动态框框 */ +.feed-item-box { + padding: 15rpx; + margin-bottom: 20rpx; + box-sizing: border-box; + border: 1rpx solid #242429; + transition: border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease; +} + +.feed-item-box.feed-highlight { + border-color: #5da0ff; + box-shadow: 0 0 32rpx rgba(93, 160, 255, 0.35); + transform: translateY(-6rpx); +} + +/* 用户信息 */ +.user-info { + display: flex; + align-items: center; + margin-bottom: 15rpx; +} + +.avatar { + width: 80rpx; + height: 80rpx; + border-radius: 50%; + margin-right: 15rpx; + object-fit: cover; +} + +.user-detail { + display: flex; + flex-direction: column; + justify-content: center; +} + +.username { + font-size: 32rpx; + margin-bottom: 5rpx; + font-weight: 500; +} + +.post-time { + font-size: 22rpx; + color: #888888; + letter-spacing: 1rpx; +} + +/* 点赞和评论功能容器 */ +.feed-actions { + display: flex; + align-items: center; + gap: 40rpx; + padding: 15rpx 0; + margin-bottom: 15rpx; +} + +.action-item { + display: flex; + align-items: center; + gap: 10rpx; + cursor: pointer; + padding: 8rpx 0; +} + +.action-button-text { + font-size: 28rpx; + color: #ffffff; + font-weight: 500; +} +.text-red{ + font-size: 28rpx; + color: #ff6460; + font-weight: 500; +} + +.like-icon { + width: 48rpx; + height: 48rpx; + object-fit: contain; +} + +.action-item:active .action-button-text { + opacity: 0.7; + transform: scale(0.98); +} + +.action-count { + font-size: 24rpx; + color: #aaaaaa; + font-weight: 400; +} + +.action-count-red { + font-size: 24rpx; + color: #ff6460; + font-weight: 400; +} + +/* 内容样式 */ +.feed-content { + font-size: 28rpx; + margin-top: 15rpx; + line-height: 40rpx; +} + +.feed-content text { + word-break: break-all !important; + word-wrap: break-word !important; + overflow-wrap: break-word !important; + white-space: pre-wrap !important; + display: block; + width: 100%; + overflow: hidden; + -webkit-hyphens: auto !important; + hyphens: auto !important; +} + +/* 评论显示区域 */ +.feed-comments-container { + margin-top: 20rpx; + margin-bottom: 20rpx; + padding: 20rpx; + background-color: #1a1a1d; + border-radius: 16rpx; + display: flex; + flex-direction: column; + gap: 16rpx; + max-height: 500rpx; + box-sizing: border-box; + overflow: hidden; +} + +.feed-comment-item { + display: flex; + flex-direction: column; +} + +.feed-comment-content { + display: flex; + flex-direction: row; + align-items: flex-start; + flex-wrap: wrap; + line-height: 36rpx; + word-wrap: break-word; + word-break: break-word; +} + +.feed-comment-name { + font-size: 26rpx; + color: #5da0ff; + font-weight: 500; + flex-shrink: 0; +} + +.feed-comment-separator { + font-size: 26rpx; + color: #888888; + margin: 0 8rpx; + flex-shrink: 0; +} + +.feed-comment-text { + font-size: 26rpx; + color: #cccccc; + flex: 1; + min-width: 0; + word-wrap: break-word; + word-break: break-word; + overflow-wrap: break-word; + white-space: pre-wrap; +} + +.feed-comment-time { + font-size: 26rpx; + color: #888888; + margin-left: 8rpx; + flex-shrink: 0; +} + +.feed-comment-reply { + font-size: 26rpx; + color: #5c5c5c; + margin-left: 16rpx; + flex-shrink: 0; + cursor: pointer; +} + +.feed-comment-delete { + font-size: 26rpx; + color: #757575; + margin-left: 16rpx; + flex-shrink: 0; + cursor: pointer; + padding: 4rpx 8rpx; + display: inline-block; +} + +.expand-comments-btn { + margin-top: 12rpx; + padding: 12rpx 0; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +} + +.expand-comments-btn:active { + opacity: 0.7; +} + +.expand-comments-text { + font-size: 26rpx; + color: #949494; +} + +/* 回复相关样式 */ +.feed-replies-container { + margin-top: 16rpx; + padding-left: 40rpx; + padding-top: 8rpx; + border-left: 2rpx solid #242429; + display: flex; + flex-direction: column; + gap: 12rpx; + width: 100%; + box-sizing: border-box; +} + +.expand-replies-btn { + margin-top: 8rpx; + padding: 12rpx 0; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +} + +.expand-replies-btn:active { + opacity: 0.7; +} + +.expand-replies-text { + font-size: 26rpx; + color: #949494; +} + +/* 上划查看更多回复提示 */ +.scroll-more-hint { + margin-top: 8rpx; + margin-bottom: 4rpx; + padding: 8rpx 0; + display: flex; + align-items: center; + justify-content: center; +} + +.scroll-more-text { + font-size: 24rpx; + color: #666666; + opacity: 0.8; +} + +.feed-reply-item { + display: flex; + flex-direction: column; +} + +.feed-reply-content { + display: flex; + flex-direction: column; + gap: 8rpx; +} + +.feed-reply-header { + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: wrap; + line-height: 36rpx; +} + +.feed-reply-body { + display: flex; + flex-direction: row; + align-items: flex-start; + line-height: 36rpx; + word-wrap: break-word; + word-break: break-word; + width: 100%; +} + +.feed-reply-body .feed-comment-text { + word-wrap: break-word; + word-break: break-word; + overflow-wrap: break-word; + white-space: pre-wrap; + width: 100%; +} + +.feed-reply-footer { + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: wrap; + line-height: 36rpx; + gap: 8rpx; + margin-top: 4rpx; +} + +.feed-reply-name { + font-size: 26rpx; + color: #5da0ff; + font-weight: 500; + flex-shrink: 0; +} + +.feed-reply-to { + font-size: 26rpx; + color: #888888; + margin: 0 4rpx; + flex-shrink: 0; +} + +.feed-reply-to-name { + font-size: 26rpx; + color: #5da0ff; + font-weight: 500; + flex-shrink: 0; +} + +.feed-reply-text-wrapper { + flex: 1; + min-width: 0; + word-wrap: break-word; + word-break: break-word; + overflow-wrap: break-word; + white-space: pre-wrap; +} + +.feed-reply-footer { + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: wrap; + margin-top: 8rpx; + line-height: 36rpx; +} + +.reply-input-container { + margin-top: 16rpx; + padding: 16rpx; + background-color: #242429; + border-radius: 12rpx; + display: flex; + align-items: center; + gap: 16rpx; +} + +.reply-input { + flex: 1; + background-color: #1a1a1d; + border-radius: 16rpx; + padding: 16rpx 20rpx; + font-size: 26rpx; + color: #ffffff; + min-height: 60rpx; + box-sizing: border-box; +} + +.reply-send-btn { + padding: 16rpx 32rpx; + background-color: #5da0ff; + border-radius: 16rpx; + min-width: 100rpx; + display: flex; + align-items: center; + justify-content: center; +} + +.reply-send-text { + font-size: 26rpx; + color: #ffffff; + font-weight: 500; +} + +.reply-send-btn:active { + opacity: 0.8; + transform: scale(0.98); +} + +.reply-send-btn-disabled { + opacity: 0.6; + pointer-events: none; +} + +.reply-send-btn-disabled:active { + opacity: 0.6; + transform: scale(1); +} + +/* 位置信息 */ +.location-info { + font-size: 24rpx; + color: #aaaaaa; + margin-bottom: 15rpx; + display: flex; + align-items: center; +} + +/* 图片样式 */ +.feed-images { + display: block; + margin-bottom: 10rpx; + background-color: #242424; + border-radius: 10rpx; + min-height: 80rpx; + overflow: hidden; +} + +.feed-images.multi-img { + display: flex; + flex-wrap: wrap; + gap: 10rpx; + align-items: flex-start; +} + +/* 图片包装容器 */ +.feed-img-wrapper { + width: 100%; + max-height: 400rpx; + overflow: hidden; + border-radius: 8rpx; + margin-bottom: 10rpx; + position: relative; + display: flex; + align-items: center; + justify-content: center; + background-color: #1a1a1a; +} + +/* 图片加载背景 */ +.image-loading { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(90deg, #1a1a1a 25%, #242424 50%, #1a1a1a 75%); + background-size: 200% 100%; + animation: loading-shimmer 1.5s ease-in-out infinite; + z-index: 1; + border-radius: 8rpx; +} + +/* Loading 动画 */ +@keyframes loading-shimmer { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} + +/* Loading 旋转图标 */ +.loading-spinner { + width: 60rpx; + height: 60rpx; + border: 4rpx solid rgba(255, 255, 255, 0.1); + border-top-color: rgba(255, 255, 255, 0.6); + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +.feed-img { + width: 100%; + max-height: 400rpx; + border-radius: 8rpx; + display: block; + box-sizing: border-box; + /* 使用 aspectFill 模式,超出部分裁剪,显示中间内容 */ + object-fit: cover; + object-position: center; + opacity: 0; + transition: opacity 0.3s ease-in-out; +} + +.feed-img.loaded { + opacity: 1; + z-index: 2; +} + +/* 多图 */ +.feed-images.multi-img .feed-img-wrapper { + width: calc(33.33% - 7rpx); + max-width: calc(33.33% - 7rpx); + max-height: 400rpx; + margin-bottom: 0; +} + +/* 加载提示 */ +.loading, .no-more { + text-align: center; + padding: 20rpx 0; + color: #aaaaaa; + font-size: 28rpx; +} + +/* 空列表提示 */ +.no-more:empty + .no-more { + margin-top: 40rpx; +} + +/* 标题容器 */ +.circle-title-container { + display: flex; + flex-direction: column; + padding: 0 35rpx 20rpx 35rpx; + box-sizing: border-box; +} + +.title-row { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + margin-bottom: 20rpx; + margin-top: 40rpx; +} + +.circle-title-text { + font-size: 40rpx; + color: #ffffff; + font-weight: 500; + height: 50rpx; + line-height: 50rpx; +} + +/* 头像滚动容器 */ +.avatar-scroll { + width: 100%; + white-space: nowrap; + margin-top: 10rpx; +} + +.avatar-list { + display: flex; + align-items: center; + gap: 30rpx; + padding: 10rpx 0; +} + +/* 头像项 */ +.avatar-item { + display: flex; + flex-direction: column; + align-items: center; + flex-shrink: 0; +} + +/* 渐变色圆形边框 */ +.avatar-border { + width: 160rpx; + height: 160rpx; + border-radius: 50%; + padding: 4rpx; + background: linear-gradient(135deg, #ff6460 0%, #ec42c8 33%, #435cff 66%, #00d5ff 100%); + position: relative; + display: flex; + align-items: center; + justify-content: center; + box-sizing: border-box; +} + +/* 头像图片 */ +.avatar-image { + width: 152rpx; + height: 152rpx; + border-radius: 50%; + background-color: #000000; + overflow: hidden; + display: block; +} + +/* 用户名 */ +.avatar-name { + font-size: 24rpx; + color: #ffffff; + margin-top: 10rpx; + max-width: 160rpx; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + text-align: center; +} + +/* 添加底部空间 */ +.main-content { + padding: 20rpx 30rpx; +} + +/* 按钮容器 */ +.floating-button-container { + position: absolute; + bottom: 260rpx; + right: 20rpx; + z-index: 10; + display: flex; + justify-content: flex-end; + padding: 10rpx; +} + +/* 页面标题样式 */ +.page-title { + background-color: #000000; + padding: 20rpx 0; + width: 100%; +} + +.title-text { + color: #ffffff; + font-size: 36rpx; + font-weight: bold; + text-align: left; + display: block; + margin-left: 0rpx; + padding-left: 42rpx; +} + +/* 发动态按钮样式*/ +.post-button { + display: flex; + align-items: center; + justify-content: space-between; + background-color: #141417; + border: 1rpx solid #404047; + border-radius: 18rpx; + padding: 15rpx 10rpx; + box-sizing: border-box; + margin-bottom: 20rpx; + height: 80rpx; +} + +/* 发布动态相机按钮样式 */ +.post-camera-icon { + width: 48rpx; + height: 48rpx; + object-fit: contain; + opacity: 1; + margin-right: 10rpx; +} + +.post-button-text { + color: #ffffff; + font-size: 28rpx; + font-weight: 500; + margin-left: 20rpx; +} + +/* 去除按钮默认伪元素样式 */ +.publish-button::after { + border: none; +} + +/* 完全取消点击反馈 */ +.publish-button:active { + transform: scale(1) !important; + opacity: 1 !important; + background: none !important; +} + +/* 暂无动态提示样式 */ +.empty-tip { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: #aaaaaa; + font-size: 32rpx; + z-index: 20; + background-color: rgba(0, 0, 0, 0.7); + padding: 20rpx 40rpx; + border-radius: 10rpx; +} + +/* 返回按钮容器 */ +.back-button-container { + position: absolute; + top: 30rpx; + left: 30rpx; + z-index: 999; +} + +/* 返回按钮样式 */ +.back-button { + background-color: rgba(255, 255, 255, 0.8); + border: 1rpx solid #e0e0e0; + border-radius: 50%; + width: 80rpx; + height: 80rpx; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + margin: 0; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1); +} + +/* 返回按钮图标 */ +.back-icon { + color: #333333; + font-size: 40rpx; + font-weight: bold; +} + +/* 位置图标 */ +.loca-icon { + width: 36rpx; + height: 36rpx; + margin-right: 10rpx; + margin-left: 5px; + flex-shrink: 0; + margin-top: 0; +} + +/* 评论弹窗 */ +.comment-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin-bottom:130px; + background-color: rgba(0, 0, 0, 0.6); + z-index: 10000; + display: flex; + align-items: flex-end; + padding-bottom: 280rpx; +} + +.comment-modal-content { + width: 100%; + background-color: #141417; + border-top-left-radius: 30rpx; + border-top-right-radius: 30rpx; + display: flex; + flex-direction: column; + max-height: 80vh; + box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.3); +} + +/* 弹窗头部 */ +.comment-modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 30rpx; + border-bottom: 1rpx solid #242429; +} + +.comment-modal-title { + font-size: 36rpx; + font-weight: 600; + color: #ffffff; +} + +.comment-modal-close { + width: 60rpx; + height: 60rpx; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background-color: #242429; +} + +.close-icon { + font-size: 48rpx; + color: #aaaaaa; + line-height: 1; +} + +/* 输入区域 */ +.comment-input-area { + display: flex; + align-items: center; + padding: 20rpx 30rpx; + border-bottom: 1rpx solid #242429; + background-color: #1a1a1d; + gap: 20rpx; +} + +.comment-input { + flex: 1; + background-color: #242429; + border-radius: 20rpx; + padding: 20rpx 24rpx; + font-size: 28rpx; + color: #ffffff; + min-height: 80rpx; + box-sizing: border-box; +} + +.comment-send-btn { + padding: 20rpx 40rpx; + background-color: #5da0ff; + border-radius: 20rpx; + min-width: 120rpx; + display: flex; + align-items: center; + justify-content: center; +} + +.send-btn-text { + font-size: 28rpx; + color: #ffffff; + font-weight: 500; +} + +.comment-send-btn:active { + opacity: 0.8; + transform: scale(0.98); +} + +/* 评论列表 */ +.comment-list { + flex: 1; + padding: 20rpx 30rpx; + max-height: calc(80vh - 280rpx); + min-height: 400rpx; +} + +.comment-item { + margin-bottom: 30rpx; + padding-bottom: 30rpx; + border-bottom: 1rpx solid #242429; +} + +.comment-item:last-child { + border-bottom: none; + margin-bottom: 0; + padding-bottom: 0; +} + +.comment-user-info { + display: flex; + align-items: flex-start; + gap: 20rpx; +} + +.comment-user-avatar { + width: 64rpx; + height: 64rpx; + border-radius: 50%; + flex-shrink: 0; +} + +.comment-content-wrapper { + flex: 1; + display: flex; + flex-direction: column; + gap: 10rpx; +} + +.comment-name { + font-size: 28rpx; + font-weight: 500; + color: #ffffff; +} + +.comment-text { + font-size: 28rpx; + color: #cccccc; + line-height: 40rpx; + word-break: break-all; +} + +.comment-time { + font-size: 24rpx; + color: #888888; +} + +.no-comments { + text-align: center; + padding: 100rpx 0; + color: #888888; + font-size: 28rpx; +} diff --git a/pages/login/login.js b/pages/login/login.js new file mode 100644 index 0000000..207f271 --- /dev/null +++ b/pages/login/login.js @@ -0,0 +1,543 @@ +// 登录页逻辑 - 真实登录实现 +const app = getApp(); +const config = require('../../config/config.js'); +const apiClient = require('../../utils/api-client.js'); +const systemInfoUtil = require('../../utils/system-info.js'); +const redirect = require("../../utils/redirect.js"); + +Page({ + data: { + showView: false, + showAgreeModal: false, + // 应用信息 + appName: config.appName || 'FindMe', + appVersion: config.appVersion || '1.0.0', + // 状态控制 + agreedToTerms: false, // 默认同意条款 + buildWechatPhoneNumber: false, // 当前微信对应的用户是否已经绑定手机号 + // 新增状态 + isLoading: false, // 加载状态 + loginError: '', // 登录错误信息 + retryCount: 0, // 重试次数 + maxRetries: 3, // 最大重试次数 + phoneNumber: '', // 当前绑定的手机号 + }, + + // ==================== 页面生命周期方法 ==================== + + /** + * 页面加载 + */ + onLoad: async function (options) { + // 保存来源信息 + this.fromPage = options.from || ''; + this.isFromLogout = options.from === 'logout'; + + // 如果是退出登录后的跳转,清除退出标志 + if (this.isFromLogout) { + setTimeout(() => { + wx.removeStorageSync('isLoggingOut'); + }, 100); + } + + // 清除之前的错误状态 + this.clearError(); + + // 使用新的屏幕适配器,解决滚动条问题 + try { + await app.initScreen(this); + + // 计算容器高度 + await systemInfoUtil.init(); + const adaptInfo = systemInfoUtil.getSystemAdaptInfo(); + const heightValue = adaptInfo.windowHeight - adaptInfo.navBarHeight; + this.setData({ + containerHeight: heightValue + 'px' + }); + } catch (error) { + console.error('屏幕适配器初始化失败:', error); + this.showError('页面初始化失败,请刷新重试'); + } + + // 开发环境下自动填充测试数据 + if (config.debug && config.debug.enabled) { + this.setData({ agreedToTerms: false }); + } + + // 移除自动登录测试,确保微信登录始终需要授权 + this.setData({ buildWechatPhoneNumber: false }); + }, + + /** + * 页面显示时检查登录状态 + */ + onShow: function () { + // 检查版本更新(优先级最高,防止版本更新后状态不一致) + const versionManager = require('../../utils/simple-version-manager.js'); + const hasVersionUpdate = versionManager.checkVersionUpdate(); + if (hasVersionUpdate) { + return; + } + + // 检查是否是退出登录后的跳转(优先级高于自动登录检查) + const isLoggingOut = wx.getStorageSync('isLoggingOut'); + const fromLogout = this.options?.from === 'logout'; + if (isLoggingOut || fromLogout) { + console.log('🔍 检测到退出登录标志,不执行自动跳转'); + setTimeout(() => { + wx.removeStorageSync('isLoggingOut'); + }, 100); + return; + } + + // 清除错误状态 + this.clearError(); + // 重置重试次数 + this.setData({ retryCount: 0 }); + + // 严格检查登录状态 + const storageUserInfo = wx.getStorageSync('userInfo'); + const globalUserInfo = app.globalData.userInfo; + + // 优先使用存储中的数据(存储是持久化的,更可靠) + const userInfo = storageUserInfo || globalUserInfo; + const hasValidToken = userInfo && userInfo.token && userInfo.token.length > 0; + const isLoggedIn = app.globalData.isLoggedIn; + + // 只有在存储和全局状态都有有效token的情况下才跳转 + if (isLoggedIn && hasValidToken && storageUserInfo && storageUserInfo.token && !isLoggingOut && !fromLogout) { + redirect.goMain(); + } else { + // 清理不一致的登录状态 + if (isLoggedIn && (!storageUserInfo || !storageUserInfo.token || !storageUserInfo.token.length)) { + console.log('🔍 检测到登录状态不一致,清理全局状态'); + app.globalData.isLoggedIn = false; + app.globalData.userInfo = null; + app.globalData.nim = null; + + if (storageUserInfo) { + wx.removeStorageSync('userInfo'); + } + wx.removeStorageSync('token'); + } + } + }, + + /** + * 页面隐藏时的处理 + */ + onHide: function () { + // 隐藏加载状态 + if (this.data.isLoading) { + this.hideLoading(); + } + }, + + /** + * 页面卸载时的处理 + */ + onUnload: function () { + // 清理定时器等资源 + if (this.loginTimer) { + clearTimeout(this.loginTimer); + this.loginTimer = null; + } + // 清理测试登录数据 + wx.removeStorageSync('testWechatLogin-loginData'); + }, + + /** + * 监听返回按钮 + */ + onBackPress: function() { + // 如果是从未登录的圈子按钮或消息按钮跳转过来的 + if (this.fromPage === 'circle' || this.fromPage === 'message') { + wx.switchTab({ + url: '/pages/map/map' + }); + return true; // 阻止默认返回行为 + } + return false; // 使用默认返回行为 + }, + + // ==================== UI工具方法 ==================== + + /** + * 显示提示信息 + */ + showToast: function (title, icon = 'none', duration = 2000) { + wx.showToast({ + title: title, + icon: icon, + duration: duration + }); + }, + + /** + * 显示加载状态 + */ + showLoading: function (title = '加载中...', mask = true) { + this.setData({ isLoading: true }); + wx.showLoading({ + title: title, + mask: mask + }); + }, + + /** + * 隐藏加载状态 + */ + hideLoading: function () { + this.setData({ isLoading: false }); + wx.hideLoading(); + }, + + /** + * 显示错误信息 + */ + showError: function (message) { + this.setData({ loginError: message }); + this.showToast(message, 'error'); + }, + + /** + * 清除错误信息 + */ + clearError: function () { + this.setData({ loginError: '' }); + }, + + // ==================== 缓存清理方法 ==================== + + /** + * 清除所有缓存 + */ + clearAllCache: function() { + try { + // 清除图片缓存 + const imageCacheManager = require('../../utils/image-cache-manager.js'); + imageCacheManager.clearAllCache(); + + // 清除网络缓存 + const networkOptimizer = require('../../utils/network-optimizer.js'); + if (networkOptimizer.clearCache) { + networkOptimizer.clearCache(); + } + + // 清除存储缓存 + const storageUtil = require('../../utils/storage.js'); + if (storageUtil.clearCache) { + storageUtil.clearCache(); + } + + // 清除临时数据(可选,保留用户token等重要数据) + const storageInfo = wx.getStorageInfoSync(); + const cacheKeys = storageInfo.keys.filter(key => + key.startsWith('cache_') || + key.startsWith('temp_') || + key.startsWith('old_') + ); + cacheKeys.forEach(key => { + wx.removeStorageSync(key); + }); + + console.log('✅ 登录时已清除缓存'); + } catch (error) { + console.error('清除缓存失败:', error); + } + }, + + // ==================== 登录相关方法 ==================== + + /** + * 本机号码一键登录 + */ + mphoneLogin: function () { + if (this.data.isLoading) { + return; + } + + if (!this.data.agreedToTerms) { + this.showToast('请先同意用户协议'); + return; + } + + this.clearAllCache(); + this.clearError(); + redirect.goMobileLogin(); + }, + + /** + * 微信快捷登录 - 获取手机号授权 + */ + onGetPhoneNumber: async function (e) { + if (this.data.isLoading) { + return; + } + + if (!this.data.agreedToTerms) { + this.showToast('请先同意用户协议'); + return; + } + + this.clearAllCache(); + + // 用户拒绝授权 + const { errMsg, code } = e.detail; + if (errMsg === 'getPhoneNumber:fail user deny') { + this.showToast('请允许获取手机号以完成登录'); + return; + } + + if (!code) { + this.showError('未能获取手机号授权码,请重试'); + return; + } + + this.clearError(); + this.showLoading('登录中...'); + + try { + const wechatCode = await this.getWechatCode(); + const loginResponse = await this.callWechatLoginAPI(wechatCode, code); + const loginData = loginResponse?.data || loginResponse; + + // 统一access_token字段 + if (!loginData.access_token && loginData.token) { + loginData.access_token = loginData.token; + } + + await this.loginSuccess(loginData); + + // 保存手机号信息 + const phoneNumber = loginData?.user?.phone || loginData?.phoneNumber || loginData?.phone; + if (phoneNumber) { + this.setData({ + buildWechatPhoneNumber: true, + phoneNumber: phoneNumber + }); + try { + wx.setStorageSync('phoneNumber', phoneNumber); + } catch (storageError) { + console.warn('缓存手机号失败:', storageError); + } + + if (app && app.globalData) { + app.globalData.phoneNumber = phoneNumber; + } + } + } catch (error) { + console.error('微信登录失败:', error); + this.showError(error.message || '微信登录失败,请重试'); + } finally { + this.hideLoading(); + } + }, + + /** + * 获取微信code + */ + getWechatCode: function () { + return new Promise((resolve, reject) => { + wx.login({ + success: (loginRes) => { + if (loginRes.code) { + resolve(loginRes.code); + } else { + console.error('获取微信code失败:', loginRes.errMsg); + reject(new Error(loginRes.errMsg || '获取微信授权码失败')); + } + }, + fail: (error) => { + console.error('微信login调用失败:', error); + reject(new Error(error.errMsg || '微信登录失败,请检查网络')); + } + }); + }); + }, + + /** + * 调用微信登录API + * @param {string} wechatCode - 微信登录授权代码 + * @param {string} phoneCode - 授权手机号代码(可选) + */ + callWechatLoginAPI: function (wechatCode, phoneCode = null) { + return apiClient.wechatLogin( + wechatCode, + phoneCode ? { phoneCode } : null + ); + }, + + /** + * 登录成功处理 + */ + loginSuccess: async function (loginData) { + redirect.goMain(); + try { + const success = await app.login(loginData); + const newUser = loginData?.newUser; + + if (success) { + this.clearError(); + wx.showToast({ + title: '登录成功', + icon: 'success', + duration: 1500 + }); + + // 延迟跳转,让用户看到成功提示 + setTimeout(() => { + if (newUser) { + // 新用户跳转到用户信息编辑页,传递用户信息用于预填 + this.prepareProfileData(loginData); + redirect.goProfile(); + } else { + // 老用户直接跳转到主页 + redirect.goMain(); + } + }, 1500); + } else { + throw new Error('登录信息保存失败'); + } + } catch (error) { + console.error('保存登录信息失败:', error); + this.showError('登录信息保存失败,请重试'); + throw error; + } + }, + + /** + * 准备用户资料数据,用于预填到 profile-page + */ + prepareProfileData: function (loginData) { + try { + // 从登录数据中提取用户信息 + const user = loginData?.user || loginData; + const profileData = { + nickname: user?.nickname || user?.nickName || '', + avatar: user?.avatar || user?.avatarUrl || '', + gender: this.mapGenderToProfileFormat(user?.gender) + }; + + // 保存到全局数据,供 profile-page 使用 + if (app && app.globalData) { + app.globalData.profilePreFillData = profileData; + } + + // 同时保存到本地存储作为备用 + wx.setStorageSync('profilePreFillData', profileData); + } catch (error) { + console.error('准备用户资料数据失败:', error); + } + }, + + /** + * 将后端性别格式转换为 profile-page 需要的格式 + * @param {number|string} gender - 后端返回的性别:0-未知,1-男,2-女,3-其他 + * @returns {string} 'man' 或 'woman' + */ + mapGenderToProfileFormat: function (gender) { + if (gender === 1 || gender === '1' || gender === 'man' || gender === 'male') { + return 'man'; + } else if (gender === 2 || gender === '2' || gender === 'woman' || gender === 'female') { + return 'woman'; + } + return 'man'; // 默认返回 'man' + }, + + /** + * 测试微信是否可以直接登录(用于调试) + */ + testWechatLogin: async function() { + try { + this.showLoading('检查登录状态...'); + wx.removeStorageSync('testWechatLogin-loginData'); + const wechatCode = await this.getWechatCode(); + const loginData = await this.callWechatLoginAPI(wechatCode); + + if (!loginData.access_token) { + return false; + } + + wx.setStorageSync('testWechatLogin-loginData', loginData); + return true; + } catch (error) { + console.error('测试微信登录失败:', error); + return false; + } finally { + this.hideLoading(); + } + }, + + /** + * 处理测试登录数据(用于调试) + */ + handleTap: async function() { + if (this.data.isLoading) { + return; + } + + if (!this.data.agreedToTerms) { + this.showToast('请先同意用户协议'); + return; + } + + this.clearAllCache(); + this.clearError(); + this.showLoading('登录中...'); + + try { + const loginData = wx.getStorageSync('testWechatLogin-loginData'); + if (!loginData) { + throw new Error('登录数据不存在,请重新授权'); + } + await this.loginSuccess(loginData); + } catch (error) { + console.error('登录失败:', error); + this.showError(error.message || '登录失败,请重试'); + } finally { + this.hideLoading(); + } + }, + + // ==================== 协议相关方法 ==================== + + /** + * 切换协议同意状态 + */ + toggleAgreement: function() { + this.setData({ + agreedToTerms: !this.data.agreedToTerms + }); + this.clearError(); + }, + + /** + * 打开协议弹窗 + */ + openAgreeModal: function() { + this.setData({ + showAgreeModal: true + }); + }, + + /** + * 同意协议 + */ + onAgree: function() { + this.setData({ + showAgreeModal: false, + agreedToTerms: true + }); + this.clearError(); + }, + + /** + * 不同意协议 + */ + onDisagree: function() { + this.setData({ + showAgreeModal: false + }); + }, +}); diff --git a/pages/login/login.json b/pages/login/login.json new file mode 100644 index 0000000..125870d --- /dev/null +++ b/pages/login/login.json @@ -0,0 +1,7 @@ +{ + "navigationBarTitleText": "", + "navigationBarBackgroundColor": "#0B3830", + "navigationBarTextStyle": "white", + "backgroundColor": "#667eea", + "disableScroll": true +} \ No newline at end of file diff --git a/pages/login/login.wxml b/pages/login/login.wxml new file mode 100644 index 0000000..f6ac805 --- /dev/null +++ b/pages/login/login.wxml @@ -0,0 +1,140 @@ + + \ No newline at end of file diff --git a/pages/login/login.wxss b/pages/login/login.wxss new file mode 100644 index 0000000..64cd6ae --- /dev/null +++ b/pages/login/login.wxss @@ -0,0 +1,234 @@ +.login-container{ + box-sizing: border-box; + height: 100%; + background: linear-gradient(160deg, #0B3830 20%, #111D26, #161522 100%); + color: white; +} +.firndMe{ + /* border: 1px solid red; */ + align-self: center; + display: flex; + height: 56%; + flex-direction: column; + justify-content: center; + align-items: center; + padding-top: 70rpx; +} +.firndMe .fm-img{ + width: 440rpx; + height: 440rpx; + max-width: 520rpx; + max-height: 520rpx; +} +/* Findme Logo */ +.findme-logo { + width: 444rpx; + height: 370rpx; + margin: 60rpx auto 20rpx auto; + display: block; +} + +/* FindmeIDCheck 图片 */ +.findme-id-check { + width: 512rpx; + height: 120rpx; + margin: 70rpx auto 40rpx auto; +} +.login{ + justify-self: center; + width: 100%; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + padding: 20rpx 40rpx 0 40rpx; +} +.button{ + width: 66%; + max-width: 700rpx; + height: 88rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 32rpx; + color: white; + font-weight: normal; + border-radius: 24rpx; + box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15); + transition: all 0.3s ease; + margin: 0 auto 60rpx auto; + position: relative; + overflow: hidden; +} +.button:active { + transform: scale(0.98); +} +.login-button{ + background: linear-gradient(135deg, #4A90E2 0%, #7B68EE 100%); +} +.login-button:active{ + background: linear-gradient(135deg, #3A7BC8 0%, #6A5ACD 100%); +} +.wechat-button{ + background: #07C160; +} +.wechat-button:active{ + background: #06A850; +} + +.login-icon{ + width: 20%; + height: 40rpx; + display: flex; + justify-content: center; + align-items: center; +} +.login-icon .icon-img{ + width: 40rpx; + height: 40rpx; +} +.login-icon .phone-icon{ + width: 40rpx; + height: 40rpx; +} +.login-icon .wechat-img{ + width: 40rpx; + height: 40rpx; +} + +.login-text{ + width: 80%; + text-align: center; + font-size: 32rpx; + font-weight: normal; + display: flex; + align-items: center; + justify-content: center; +} +.checkbox-group{ + /* border: 1px solid red; */ + justify-self:center; + align-self:center; + width: 100%; + height: 20%; + font-size: 12px; + display: flex; + justify-content: center; + align-items: center; + /* margin-bottom: 20px; */ +} +.contractTap{ + + display: flex; + justify-content: center; + align-items: center; +} + +.contract-img{ + flex: 0 0 auto; + width: 18px; + height: 18px; + max-width: 20px; + max-height: 20px; + +} +.label-text{ + justify-self: center; + display: flex; + justify-content: center; + align-items: center; + font-size:22rpx; +} +.agreement-text { + color: #ff0a0a; +} +.modal-mask { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.6); /* 遮罩层半透明黑色 */ + display: flex; + align-items: center; + justify-content: center; + /* border: 1px solid red; */ +} + + + + +/* 弹窗容器 */ +.modal-container { + position:relative; + display: flex; + justify-content: center; + flex-direction: column; + width: 80%; + max-height: 70vh; /* 限制弹窗高度,避免超出屏幕 */ + background: linear-gradient(160deg, #0B3830 20%, #111D26, #161522 100%); + border-radius: 24rpx; + color: white; + font-size: 12px; + /* border: 1px solid red; */ +} + +/* 标题 */ +.modal-title { + padding: 30rpx; + font-size: 34rpx; + font-weight: bold; + text-align: center; + border-bottom: 1rpx solid white; +} + +/* 协议内容区域(可滚动) */ +.modal-content { + padding: 10rpx ; + flex: 1; + min-height: 300rpx; /* 最小高度,确保内容区可见 */ + flex-wrap: wrap; + overflow-y:auto; + /* border: 1px red solid; */ +} + +.text-centen{ + + margin: 10px; +} +/* 协议文字样式 */ +.content-text { + font-size: 28rpx; + line-height: 1.8; + overflow:scroll; +} + +/* 按钮区域 */ +.modal-buttons { + /* position:absolute; */ + /* bottom: 0; */ + display: flex; + border-top: 1rpx solid white; +} + + +/* 按钮通用样式 */ +.btn { + flex: 1; /* 两个按钮平分宽度 */ + height: 100rpx; + line-height: 100rpx; + font-size: 32rpx; + margin: 0; /* 去掉默认边距 */ +} + +/* 不同意按钮(红色) */ +.cancel { + background: #fff; + color: #ff4d4f; /* 红色文字 */ +} + +/* 同意按钮(绿色) */ +.confirm { + background: transparent; + color: white; +} \ No newline at end of file diff --git a/pages/login/mobile-login-page.js b/pages/login/mobile-login-page.js new file mode 100644 index 0000000..d4c2a11 --- /dev/null +++ b/pages/login/mobile-login-page.js @@ -0,0 +1,842 @@ +// pages/login/mobile-login-page.js +const app = getApp(); +const config = require('../../config/config.js'); +const apiClient = require('../../utils/api-client.js'); +const systemInfoUtil = require('../../utils/system-info.js'); +const versionHelper = require('../../utils/version-helper.js'); +// const screenAdapter = require('../../utils/screen-adapter.js'); +const redirect = require("../../utils/redirect.js"); + + +Page({ + + /** + * 页面的初始数据 + */ + data: { + // 应用信息 + appName: config.appName || 'FindMe', + appVersion: config.appVersion || '1.0.0', + // 表单数据 + phoneNumber: '', + phoneError: '', + verifyCode: ['', '', '', ''], + verifyCodeError: '', + verifyCodeComplete: false, + focusIndex: -1, // 当前应该聚焦的输入框索引,-1表示无焦点 + phoneFocus: false, // 手机号输入框焦点状态 + phoneValid:false, + codeValid: false, + isnickNameError:'', + canLogin: false, + isLogging: false, + isWechatLogging: false, + // 验证码按钮状态 + codeButtonText: '获取验证码', + codeTimer: null, + codeCountdown: 0, + + // 系统适配信息 - 先设置默认值 + statusBarHeight: 44, + menuButtonHeight: 32, + menuButtonTop: 6, + navBarHeight: 88, + windowHeight: 667, + safeAreaBottom: 0, + + // 新增:单一输入框方案 + realCode: '', // 真实输入框的值 + isCodeInputFocused: false, // 控制伪光标显示 + cursorPosition: 0, // 光标位置 + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad : async function(options) { + console.log('页面加载,options:', options); + + // 应用屏幕适配到页面的数据 + await app.initScreen(this) + + // 使用新的屏幕适配器,解决滚动条问题 + // this.initScreenAdapter(); + + // 检查是否已有用户信息(如从启动页跳转过来) + this.checkAutoFillUserInfo(); + // 开发环境下自动填充测试数据 + if (config.debug && config.debug.enabled) { + this.setData({ + phoneNumber: ''// 测试手机号 15618371121 + }); + this.validateForm(); + } + + }, + // 表单验证 + // 表单验证 + validateForm: function () { + const { phoneNumber, verifyCode } = this.data + const phone = (phoneNumber || '').trim() + const verifyCodeString = Array.isArray(verifyCode) ? verifyCode.join('') : (verifyCode || '').trim() + const phoneReg = /^1[3-9]\d{9}$/; + const verifyCodeReg = /^\d{4}$/; + let isPhoneError = ''; + let isVerifyCodeError = ''; + let canSendCode = ''; + let isnickNameError = '' + if (!phoneReg.test(phone) && phone) { + isPhoneError = '请输入有效的11位数手机号码' + isnickNameError= true + + } else { + canSendCode = phoneReg.test(phone) && this.data.codeCountdown === 0; + } + if (!verifyCodeReg.test(verifyCodeString) && verifyCodeString) { + isVerifyCodeError = '请输入有效的4位数验证码' + } + this.setData({ + phoneNumber: phone, + phoneError: isPhoneError, + verifyCodeError: isVerifyCodeError, + canSendCode: canSendCode, + isnickNameError:isnickNameError + }) + }, + + + // 手机号输入过程中的处理 + onPhoneInputChange: function (e) { + const value = e.detail.value; + + this.setData({ + phoneNumber: value + }); + this.validateForm(); + }, + + // 手机号获得焦点时的处理 + onPhoneFocus: function (e) { + + this.setData({ + phoneFocus: true + }); + }, + + // 手机号失去焦点时的处理 + onPhoneInput: function (e) { + + this.setData({ + phoneFocus: false // 失去焦点时设置为false + }); + }, + + // 新增:点击特定格子聚焦到对应位置 + focusOnCodePosition: function(e) { + const index = parseInt(e.currentTarget.dataset.index); + + this.setData({ + isCodeInputFocused: true, + cursorPosition: index + }); + + // 延迟聚焦到真实输入框 + wx.nextTick(() => { + const query = wx.createSelectorQuery().in(this); + query.select('#real-code-input').node().exec((res) => { + if (res[0] && res[0].node) { + res[0].node.focus(); + // 设置光标位置 + res[0].node.setSelectionRange(index, index); + } + }); + }); + }, + + // 新增:点击验证码容器时聚焦 + focusOnCodeInput: function() { + this.setData({ + isCodeInputFocused: true, + cursorPosition: this.data.realCode.length // 设置光标到字符串末尾 + }); + + wx.nextTick(() => { + const query = wx.createSelectorQuery().in(this); + query.select('#real-code-input').node().exec((res) => { + if (res[0] && res[0].node) { + res[0].node.focus(); + // 设置光标到字符串末尾 + const cursorPos = this.data.realCode.length; + res[0].node.setSelectionRange(cursorPos, cursorPos); + } + }); + }); + }, + + // 新增:真实输入框的键盘事件处理 + onRealCodeKeyDown: function(e) { + const keyCode = e.detail.keyCode; + const value = e.detail.value; + + // 处理删除键 - 根据光标位置删除 + if (keyCode === 8) { // Backspace + if (this.data.cursorPosition > 0) { + const currentCode = this.data.realCode; + const newCode = currentCode.slice(0, this.data.cursorPosition - 1) + currentCode.slice(this.data.cursorPosition); + const newPosition = this.data.cursorPosition - 1; + + // 创建新的验证码数组 + const newVerifyCode = ['', '', '', '']; + for (let i = 0; i < newCode.length; i++) { + newVerifyCode[i] = newCode[i]; + } + + this.setData({ + realCode: newCode, + verifyCode: newVerifyCode, + cursorPosition: newPosition, + verifyCodeComplete: newCode.length >= 4 + }); + + // 同步输入框状态 + wx.nextTick(() => { + const query = wx.createSelectorQuery().in(this); + query.select('#real-code-input').node().exec((res) => { + if (res[0] && res[0].node) { + res[0].node.value = newCode; + res[0].node.setSelectionRange(newPosition, newPosition); + } + }); + }); + } + } + // 处理方向键 + else if (keyCode === 37) { // 左箭头 + if (this.data.cursorPosition > 0) { + this.setData({ + cursorPosition: this.data.cursorPosition - 1 + }); + } + } + else if (keyCode === 39) { // 右箭头 + if (this.data.cursorPosition < this.data.realCode.length) { + this.setData({ + cursorPosition: this.data.cursorPosition + 1 + }); + } + } + }, + + + // 新增:真实输入框的输入事件 + onRealCodeInput: function(e) { + const value = e.detail.value; + const digits = value.replace(/\D/g, '').slice(0, 4); // 只保留数字,最多4位 + + // 创建新的验证码数组 + const newVerifyCode = ['', '', '', '']; + for (let i = 0; i < digits.length; i++) { + newVerifyCode[i] = digits[i]; + } + + // 计算光标位置 + let newCursorPosition = digits.length; + + // 如果输入了新的字符,光标位置等于字符串长度 + // 如果删除了字符,保持当前光标位置 + if (digits.length > this.data.realCode.length) { + // 输入操作:光标在末尾 + newCursorPosition = digits.length; + } else if (digits.length < this.data.realCode.length) { + // 删除操作:保持当前光标位置 + newCursorPosition = Math.min(this.data.cursorPosition, digits.length); + } + + this.setData({ + realCode: digits, + verifyCode: newVerifyCode, + cursorPosition: newCursorPosition + }); + + if (digits.length >= 4) { + this.setData({ + verifyCodeComplete: true + }); + this.validateForm(); + // 可以在这里触发登录 + } else { + this.setData({ + verifyCodeComplete: false + }); + } + }, + + // 键盘确认按钮处理 - 当用户点击键盘上的"确定"时触发 + onCodeConfirm: function(e) { + const { verifyCode, phoneNumber } = this.data; + const verifyCodeString = Array.isArray(verifyCode) ? verifyCode.join('') : verifyCode; + + // 如果验证码已输入4位,自动执行登录 + if (verifyCodeString && verifyCodeString.length === 4 && phoneNumber) { + // 延迟一小段时间,确保输入框的值已更新 + setTimeout(() => { + this.handleLogin(); + }, 100); + } else if (!verifyCodeString || verifyCodeString.length < 4) { + // 验证码未填满时,提示用户 + wx.showToast({ + title: '请输入完整的4位验证码', + icon: 'none', + duration: 1500 + }); + } else if (!phoneNumber) { + // 手机号未填写时,提示用户 + wx.showToast({ + title: '请输入手机号码', + icon: 'none', + duration: 1500 + }); + } + }, + + // 验证码输入处理 - 统一处理输入和删除 + onCodeInput: function (e) { + const value = e.detail.value; + const index = parseInt(e.currentTarget.dataset.index); + const oldCode = [...this.data.verifyCode]; + const oldValue = oldCode[index]; + const isAllFilled = oldCode.every(code => code !== ''); + + // 提取数字字符 + const digits = value.replace(/\D/g, ''); + + // 处理多位输入(粘贴场景) + if (digits.length > 1) { + this.handlePastedCode(digits, index); + return; + } + + // 获取新的数字值 + const newDigit = digits.slice(0, 1); + const newCode = [...oldCode]; + newCode[index] = newDigit; + + // 判断操作类型 + const isDelete = oldValue && !newDigit; // 有值变无值 = 删除 + const isInput = !oldValue && newDigit; // 无值变有值 = 输入 + const isReplace = oldValue && newDigit && oldValue !== newDigit; // 替换 + + // 更新数据 + this.setData({ + verifyCode: newCode, + verifyCodeComplete: this.checkCodeComplete(newCode) + }); + + // 处理焦点逻辑 + if (isDelete) { + // 删除操作:回退到上一个输入框 + this.handleDeleteOperation(index); + } else if (isInput || isReplace) { + // 输入或替换操作:根据是否全部填满决定焦点移动 + this.handleInputOperation(index, isAllFilled); + } + + this.validateForm(); + }, + + // 处理删除操作的焦点移动 + handleDeleteOperation: function(currentIndex) { + if (currentIndex > 0) { + // 使用requestAnimationFrame确保在下一帧执行,减少跳动 + wx.nextTick(() => { + this.setData({ + focusIndex: currentIndex - 1 + }); + }, 50); // 延迟确保UI更新 + } + }, + + // 处理输入操作的焦点移动 + handleInputOperation: function(currentIndex, wasAllFilled) { + const isAllFilled = this.data.verifyCode.every(code => code !== ''); + + if (currentIndex < 3 && !isAllFilled) { + // 只有在不是全部填满的情况下才前进到下一个输入框 + wx.nextTick(() => { + this.setData({ + focusIndex: currentIndex + 1 + }); + }, 50); // 延迟确保UI更新 + } + }, + + // 处理粘贴的验证码 + handlePastedCode: function (pastedValue, currentIndex = 0) { + const digits = pastedValue.replace(/\D/g, '').slice(0, 4); + + if (digits.length === 0) return; + + const newCode = [...this.data.verifyCode]; + const digitsArray = digits.split(''); + + // 从当前位置开始填充 + for (let i = 0; i < digitsArray.length && (currentIndex + i) < 4; i++) { + newCode[currentIndex + i] = digitsArray[i]; + } + + // 计算最终焦点位置 + const finalIndex = Math.min(currentIndex + digits.length - 1, 3); + const isComplete = this.checkCodeComplete(newCode); + + this.setData({ + verifyCode: newCode, + focusIndex: isComplete ? -1 : finalIndex, // 完成时取消焦点 + verifyCodeComplete: isComplete + }); + + this.validateForm(); + }, + + // 验证码按键处理 - 备用删除键处理 + onCodeKeyDown: function (e) { + const index = parseInt(e.currentTarget.dataset.index); + const keyCode = e.detail.keyCode; + + // 备用删除键处理(如果onCodeInput处理不了的情况) + if (keyCode === 8) { + const currentValue = this.data.verifyCode[index]; + + // 如果当前位置无值且在onCodeInput中没有处理到,则手动回退 + if (!currentValue && index > 0) { + const newCode = [...this.data.verifyCode]; + newCode[index - 1] = ''; + + setTimeout(() => { + this.setData({ + verifyCode: newCode, + focusIndex: index - 1, + verifyCodeComplete: false + }); + this.validateForm(); + }, 10); + } + } + }, + + // 验证码输入框获得焦点 + onCodeFocus: function (e) { + this.setData({ + isCodeInputFocused: true, + verifyCodeError: '' // 清除错误提示 + }); + }, + + // 验证码输入框失去焦点 + onCodeBlur: function (e) { + this.setData({ + isCodeInputFocused: false + }); + this.validateForm(); + }, + + // 兜底系统信息初始化 + async fallbackSystemInfo() { + try { + await systemInfoUtil.init(); + const adaptInfo = systemInfoUtil.getSystemAdaptInfo(); + + this.setData({ + statusBarHeight: adaptInfo.statusBarHeight, + menuButtonHeight: adaptInfo.menuButtonHeight, + menuButtonTop: adaptInfo.menuButtonTop, + navBarHeight: adaptInfo.navBarHeight, + windowHeight: adaptInfo.windowHeight, + safeAreaBottom: adaptInfo.safeAreaBottom + }); + + } catch (error) { + console.error('兜底适配也失败,使用硬编码默认值:', error); + this.setData({ + statusBarHeight: 44, + menuButtonHeight: 32, + menuButtonTop: 6, + navBarHeight: 88, + windowHeight: 667, + safeAreaBottom: 0 + }); + } + }, + + // 检查自动填充用户信息 + checkAutoFillUserInfo() { + try { + const savedPhone = wx.getStorageSync('lastLoginPhone'); + if (savedPhone) { + this.setData({ + phoneNumber: savedPhone + }); + this.validateForm(); + } + } catch (error) { + + } + }, + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + // 页面渲染完成后设置手机号输入框焦点 + setTimeout(() => { + this.setData({ + phoneFocus: true + }); + }, 100); + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + // 🔥 优先检查版本更新 + const hasVersionUpdate = versionHelper.checkVersionOnShow(); + if (hasVersionUpdate) { + + return; // 如果有版本更新,停止后续初始化 + } + + // 页面显示时确保手机号输入框获得焦点 + setTimeout(() => { + this.setData({ + phoneFocus: true + }); + }, 150); + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + // 清理验证码倒计时定时器 + if (this.data.codeTimer) { + clearInterval(this.data.codeTimer); + } + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + /** + * 用户点击右上角分享 + */ + onShareAppMessage() { + + }, + + // 清除手机号 + clearPhone: function () { + this.setData({ + phoneNumber: '' + }); + this.validateForm(); + }, + + // 发送验证码 - 真实实现 + sendVerifyCode: function () { + + this.validateForm(); + const { phoneNumber, codeCountdown } = this.data; + if (codeCountdown > 0) { + + return; + } + + if (!this.data.canSendCode) { + wx.showToast({ + title: '请输入正确手机号', + icon: 'error', + duration: 2000 + }); + + return; + } + + // 显示加载状态 + wx.showLoading({ + title: '发送中...', + mask: true + }); + + // 调用真实API + apiClient.sendVerifyCode(phoneNumber) + .then(response => { + // 确保隐藏loading + wx.hideLoading(); + + // 开始倒计时 + this.startCodeCountdown(); + + // 延迟显示成功提示,确保loading完全消失 + setTimeout(() => { + wx.showToast({ + title: '验证码已发送', + icon: 'success', + duration: 2000 + }); + }, 100); + }) + .catch(error => { + // 确保隐藏loading + wx.hideLoading(); + + console.error('验证码发送失败:', error); + + let errorMessage = '发送失败,请重试'; + if (error.message) { + errorMessage = error.message; + } else if (error.code === 'PHONE_INVALID') { + errorMessage = '手机号格式不正确'; + } else if (error.code === 'TOO_FREQUENT') { + errorMessage = '发送太频繁,请稍后再试'; + } + + // 延迟显示错误提示,确保loading完全消失 + setTimeout(() => { + wx.showToast({ + title: errorMessage, + icon: 'error', + duration: 3000 + }); + }, 100); + }) + .finally(() => { + // 双重保险:确保loading被隐藏 + setTimeout(() => { + wx.hideLoading(); + }, 50); + }); + }, + + // 开始验证码倒计时 + startCodeCountdown: function () { + let countdown = 60; + + this.setData({ + codeCountdown: countdown, + codeButtonText: `${countdown}s后重发` + }); + + const timer = setInterval(() => { + countdown--; + + if (countdown <= 0) { + clearInterval(timer); + this.setData({ + codeCountdown: 0, + codeButtonText: '重新发送', + codeTimer: null + }); + this.validateForm(); + } else { + this.setData({ + codeCountdown: countdown, + codeButtonText: `${countdown}s后重发` + }); + } + }, 1000); + + this.setData({ + codeTimer: timer + }); + }, + + // 处理登录 - 真实实现 + handleLogin: function () { + this.validateForm(); + + const { phoneNumber, verifyCode } = this.data; + const verifyCodeString = Array.isArray(verifyCode) ? verifyCode.join('') : verifyCode; + + + if (!this.data.phoneNumber) { + wx.showToast({ + title: '请输入手机号码', + icon: 'error' + }) + return + } + if (!verifyCodeString) { + wx.showToast({ + title: '请输入验证码', + icon: 'error' + }) + return + }; + + // if (!this.data.canLogin || this.data.isLogging) { + // console.log('❌ 登录被阻止 - 按钮不可用或正在登录'); + // wx.showToast({ + // title: '请输入正确验证码', + // icon: 'error', + // duration: 2000 + // }) + // return; + // } + + + + + this.setData({ + isLogging: true + }); + + // 显示加载状态 + wx.showLoading({ + title: '登录中...', + mask: true + }); + + // 调用真实登录API + apiClient.login(phoneNumber, verifyCodeString) + .then(response => { + wx.hideLoading(); + + // 处理登录成功 + this.loginSuccess(response.data); + }) + .catch(error => { + wx.hideLoading(); + + console.error('登录失败:', error); + + this.setData({ + isLogging: false + }); + + let errorMessage = '登录失败,请重试'; + if (error.message) { + errorMessage = error.message; + } else if (error.code === 'VERIFY_CODE_INVALID') { + errorMessage = '验证码错误'; + } else if (error.code === 'VERIFY_CODE_EXPIRED') { + errorMessage = '验证码已过期,请重新获取'; + } else if (error.code === 'PHONE_NOT_FOUND') { + errorMessage = '手机号未注册'; + } + + wx.showToast({ + title: errorMessage, + icon: 'error', + duration: 3000 + }); + }); + }, + + // 登录成功处理 + loginSuccess: function (loginData) { + + try { + // 使用app.js中的登录方法保存用户信息 + const success = app.login(loginData); + const newUser=loginData?.newUser; + + if (success) { + // 🔥 调试:检查认证状态 + const authManager = require('../../utils/auth.js'); + authManager.debugAuthStatus(); + + // 保存最后登录的手机号 + if (this.data.phoneNumber) { + wx.setStorageSync('lastLoginPhone', this.data.phoneNumber); + } + + // 🔥 立即检查账号同步状态 + + this.checkAccountSyncAfterLogin(loginData); + + wx.showToast({ + title: '登录成功', + icon: 'success', + duration: 1500 + }); + + // 🔥 使用统一的跳转方法 + setTimeout(() => { + + if(newUser){ // @TODO 判断用户是否是第一次登陆,如果不是则不需要编辑用户信息 + redirect.goProfile() + }else{// 需要编辑的情况下,跳转到用户信息编辑页 + redirect.goMain(); + } + }, 1500); + } else { + throw new Error('登录信息保存失败'); + } + + } catch (error) { + console.error('保存登录信息失败:', error); + + wx.showToast({ + title: '登录信息保存失败', + icon: 'error', + duration: 2000 + }); + } + }, +// 🔥 登录成功后检查账号同步状态 +async checkAccountSyncAfterLogin(loginData) { + + try { + console.log('检查登录后的账号同步状态...', { + hasUser: !!loginData.user, + hasPhone: !!(loginData.user && loginData.user.phone), + phone: loginData.user?.phone + }); + + // 根据文档,优先检查needBindPhone字段,其次检查phone字段 + const needBindPhone = loginData.needBindPhone === true || + (!loginData.user || !loginData.user.phone || loginData.user.phone.trim() === ''); + + if (needBindPhone) { + + // 延迟显示绑定提示,确保登录流程完成 + setTimeout(() => { + const accountSyncManager = require('../../utils/account-sync.js'); + accountSyncManager.showPhoneBindingModal(); + }, 2000); + } else { + + } + + } catch (error) { + console.error('检查账号同步状态失败:', error); + } +}, +checkAccountSyncStatus: async function() { + try { + const syncStatus = await accountSync.getSyncStatus(); + this.setData({ + isAccountSynced: syncStatus.isSynced + }); + } catch (error) { + console.error('检查账号同步状态失败:', error); + } +} +}); diff --git a/pages/login/mobile-login-page.json b/pages/login/mobile-login-page.json new file mode 100644 index 0000000..f067e24 --- /dev/null +++ b/pages/login/mobile-login-page.json @@ -0,0 +1,10 @@ +{ + "usingComponents": { + + }, + "navigationBarTitleText": "手机号码登录", + "navigationBarBackgroundColor": "#000", + "navigationBarTextStyle": "white", + "backgroundColor": "#000" + +} \ No newline at end of file diff --git a/pages/login/mobile-login-page.wxml b/pages/login/mobile-login-page.wxml new file mode 100644 index 0000000..a6c0788 --- /dev/null +++ b/pages/login/mobile-login-page.wxml @@ -0,0 +1,56 @@ + + + + + + + 手机号码 + + +86 + + + + {{phoneError}} + + + + {{codeButtonText}} + + + + + + + {{verifyCode[index] || ''}} + + + {{verifyCodeError}} + + + + + 下一步 + + \ No newline at end of file diff --git a/pages/login/mobile-login-page.wxss b/pages/login/mobile-login-page.wxss new file mode 100644 index 0000000..3e3b915 --- /dev/null +++ b/pages/login/mobile-login-page.wxss @@ -0,0 +1,385 @@ +/* 手机号码登录页样式 */ +.container-phone{ + box-sizing: border-box; + display: flex; + min-height: 100vh; + flex-direction: column; + color: white; + font-size: clamp(32rpx, 4vw, 56rpx); + background-color:black; + /* border: 10px solid red; */ +} + +.phone-login{ + height: 200rpx; + display: flex; + justify-content: center; + align-items: flex-start; + font-size: clamp(76rpx, 10vw, 100rpx); + padding-top: 200rpx; + /* background-color: #4e4e4e; */ +} + +.phone-content{ + height: 100%; + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +.phone-content-common{ +/* border: 1px solid red; */ + font-size: clamp(24rpx, 10vw, 28rpx); + display: grid; + justify-items: center; + align-items: start; + gap: 20rpx; + width: 100%; + max-width: 600rpx; +} +.error-message{ +text-align: start; +width: 100%; +height: 40rpx; +/* border: 1px solid rgb(0, 255, 128); */ +color: red; +margin-top: 20rpx; + + +} + +.phone-text{ + justify-self: stretch; + width: 100%; + box-sizing: border-box; + padding: 0 30rpx; + color:#aaa; + height: 50rpx; + line-height: 50rpx; + margin-top: 20rpx; + display: flex; + align-items: center; + justify-content: space-between; +} +.phone-text-label{ + flex: 1; +} +.phone-number-input-phone{ +background-color:#232323; +width: clamp(560rpx, 60vw, 600rpx); +height: clamp(20rpx, 60vw, 100rpx); +display: grid; +align-items: center; +grid-template-columns: auto 1rpx 1fr; +grid-template-rows: 1fr; +border-radius: 12rpx; +padding: 0 16rpx; +/* color: #f80303; */ +} + +/* 当没有渐变边框时的默认样式 */ +.phone-number-input-phone:not(.gradient-border) { + border: 2rpx solid #494949; + background-color: #232323; + padding: 0 16rpx; +} + +.title{ +/* border: 1px solid red; */ +justify-self: center; +} +.phone-number-input{ + /* border: 1rpx solid #494949; */ + /* border: 1rpx solid #e70b0b; */ + background-color:#232323; + width: clamp(560rpx, 60vw, 600rpx); + height: clamp(20rpx, 60vw, 100rpx); + display: grid; + align-items: center; + grid-template-columns: 1fr auto 1fr 1fr; + grid-template-rows: 1fr; + border-radius: 12rpx; + color: #aaaaaa; + padding: 0 16rpx; +} +.title-mindle{ + width: 0.1rpx; + height: 40rpx; + position:relative; + z-index:2; + background: #aaa; + border-radius: 1rpx; + justify-self: center; +} + +/* 渐变边框样式 */ +.phone-number-input-phone.gradient-border { + position: relative !important; + background: linear-gradient(45deg, rgba(104, 249, 254, 0.6), rgba(170, 147, 237, 0.6)) !important; + padding: 0.5rpx !important; + border-radius: 16rpx !important; + border: none !important; + width: clamp(560rpx, 60vw, 600rpx) !important; + height: clamp(20rpx, 60vw, 100rpx) !important; + display: grid !important; + align-items: center !important; + grid-template-columns: auto 1rpx 1fr !important; + grid-template-rows: 1fr !important; + box-sizing: border-box !important; +} + +.phone-number-input-phone.gradient-border:before { + content: ''; + position: absolute; + top: 0.5rpx; + left: 0.5rpx; + right: 0.5rpx; + bottom: 0.5rpx; + background-color: #232323; + border-radius: 15rpx; + z-index: 1; +} + +.phone-number-input-phone .title { + justify-self: center; + position: relative; + z-index: 2; + width: auto; + width: 100rpx; + text-align:center; + color: #aaaaaa; +} +.phone-number-input-phone .phone-input { + width: 100%; + height: 100%; + margin-left:20rpx; + position: relative; + z-index: 2; + background: transparent; + border: none; + outline: none; + color: #aaaaaa; + font-size: 32rpx; + padding: 0; + box-sizing: border-box; +} + +/* 错误边框样式 */ +.error-border { + border: 2rpx solid #ff0000; +} + +/* 验证码输入框容器 */ +.verification-code-container { + position: relative; + display: flex; + justify-content: space-between; + width: clamp(560rpx, 60vw, 600rpx); + margin: 10rpx 0; +} + +/* 隐藏的真实输入框 - 完全隐藏光标 */ +.real-code-input { + position: absolute; + top: -9999px; /* 移到屏幕外 */ + left: -9999px; + width: 1px; + height: 1px; + opacity: 0; + z-index: -9999; + font-size: 16px; + color: transparent; + background: transparent; + border: none; + outline: none; + caret-color: transparent !important; + -webkit-text-fill-color: transparent; + text-shadow: none; + -webkit-appearance: none; + appearance: none; + -webkit-user-select: text; + user-select: text; + pointer-events: auto; + /* 额外的光标隐藏方法 */ + -webkit-tap-highlight-color: transparent; + -webkit-touch-callout: none; + /* 裁剪隐藏 */ + clip: rect(0, 0, 0, 0); + clip-path: inset(50%); + overflow: hidden; +} + +/* 验证码输入框 - 默认渐变边框 */ +.code-input { + width: 120rpx; + height: 120rpx; + background-color: #232323; + border-radius: 12rpx; + display: flex; + justify-content: center; + align-items: center; + font-size: 64rpx; + color: #aaa; + border: 2rpx solid transparent; /* 透明边框,为渐变留空间 */ + transition: all 0.2s ease-in-out; + position: relative; + z-index: 1; + /* 临时测试:直接使用渐变边框 */ + background: linear-gradient(#232323, #232323) padding-box, + linear-gradient(45deg, rgba(104, 249, 254, 0.6), rgba(170, 147, 237, 0.6)) border-box; + border: 2rpx solid transparent; +} + + +/* 验证码输入框文字 */ +.code-input-field { + font-size: 64rpx; + font-weight: normal; + color: #aaa; + text-align: center; + line-height: 1; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + position: relative; + z-index: 2; /* 确保文字在最上层 */ +} + +/* 验证码输入框聚焦状态 */ +.code-input.focus { + border-color: #68f9fe; + box-shadow: 0 0 0 4rpx rgba(104, 249, 254, 0.1); + transform: scale(1.05); +} + + + +/* 验证码输入框错误状态 */ +.code-input.error-border { + background: linear-gradient(#232323, #232323) padding-box, + linear-gradient(45deg, #ff0000, #ff0000) border-box !important; + border: 2rpx solid transparent !important; +} + + +/* 验证码输入框占位符样式 */ +.code-input-field::placeholder { + color: #666666; + font-size: 36rpx; +} + +/* 验证码输入框聚焦时的样式 */ +.code-input-field:focus { + color: #68f9fe; + transform: scale(1.05); + transition: all 0.2s ease-in-out; +} + +/* 验证码输入框动画效果 */ +.code-input { + animation: fadeIn 0.3s ease-in-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20rpx); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* 验证码输入框成功状态 */ +.code-input.success { + border-color: #00ff88; + background-color: rgba(0, 255, 136, 0.1); +} + +.code-input.success .code-input-field { + color: #00ff88; +} + +/* 重发验证码容器 */ +.resend-link { + color: #0076f5; + font-size: 28rpx; + padding: 0; + text-align: right; + line-height: 50rpx; +} + + +.phone-number-input .title{ + text-align: center; + width: 100rpx; +} +.phone-input{ +width: 100%; +height: 100%; +background: transparent; +border: none; +outline: none; +color: #aaaaaa; +font-size: 32rpx; +padding: 0; +box-sizing: border-box; +} + + + +.inpuet-btn{ + +width: 160rpx; +height: 60rpx; +line-height: 60rpx; +font-size: 26rpx; +font-weight: bolder; +background: #9E93DC; +border: 1rpx solid #494949; +color:white; +border-radius: 10rpx; +transition: all 0.2s ease; +text-align: center; +} +.inpuet-btn:active{ +background-color:#8b7cdf; +transform: translateY(2rpx); +} + + +.phone-next{ + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 200rpx; + box-sizing: border-box; +} + +.phone-next-btn{ +height: 100rpx; +width: 240rpx; +background: linear-gradient(135deg, #000000, #232323); +color: white; +text-align: center; +line-height: 100rpx; +border: 1rpx solid #4e4e4e; +border-radius: 60rpx; +font-size: 40rpx; +font-weight: 500; +box-shadow: +4rpx 4rpx 30rpx rgba(91, 196, 245, 0.1), +0 4rpx 8rpx rgba(255, 255, 255, 0.2) inset; +transition: all 0.2s ease; +} +.phone-next-btn:active{ +box-shadow: +0 -16rpx 32rpx rgba(18, 158, 240, 0.1) inset, /* 内层上阴影(凹陷) */ +0 4rpx 8rpx rgba(0, 0, 0, 0.1) inset; /* 内层下阴影 */ +transform: translateY(4rpx); /* 向下偏移,强化"按下"感 */ + +} \ No newline at end of file diff --git a/pages/login/profile-page.js b/pages/login/profile-page.js new file mode 100644 index 0000000..5cb28be --- /dev/null +++ b/pages/login/profile-page.js @@ -0,0 +1,328 @@ +// pages/login/profile-page.js +const formatUtil = require("../../utils/formatDate.js"); +const { calculateConstellationFromBirthday } = require("../../utils/formatDate.js"); +const redirect = require("../../utils/redirect.js"); +const apiClient = require('../../utils/api-client.js'); +const imageCacheManager = require('../../utils/image-cache-manager.js'); +const cosManager = require('../../utils/cos-manager.js'); +const nimUserManager = require('../../utils/nim-user-manager.js'); +const config = require('../../config/config.js'); +const app = getApp() +Page({ + /** + * 页面的初始数据 + */ + data: { + avatar: '', + currentDate: new Date().getTime(), + endDate: formatUtil.formatDate(formatUtil.getNYearsAgo(18)), + gender: "man", + nickname: '', + isnickNameError: '', + birthDate: formatUtil.formatDate(formatUtil.getNYearsAgo(18)), + age: '' + }, + + genderBtn(e) { + const gender = e.currentTarget.dataset.value; + this.setData({ gender }); + }, + nicknameInput(e) { + const newValue = e.detail.value; + this.checkInvalidChars(newValue); + this.setData({ nickname: newValue }); + }, + + checkInvalidChars(value) { + // 匹配英文、中文、数字之外的字符 + const invalidReg = /[^\a-zA-Z0-9\u4e00-\u9fa5]/g; + const hasInvalid = invalidReg.test(value); + + this.setData({ + showTip: hasInvalid, + nickNameError: hasInvalid ? '支持文字、字母、数字输入' : '', + isnickNameError: hasInvalid + }); + }, + bindDateChange(e) { + const birthDate = e.detail.value; + this.setData({ + birthDate, + age: formatUtil.calculateAge(birthDate) + '岁' + }); + }, + async onChooseAvatar(e) { + try { + const { avatarUrl } = e.detail; + console.log('用户选择头像,临时路径:', avatarUrl); + // 直接保存路径,上传时再验证(避免重复验证) + this.setData({ avatar: avatarUrl }); + } catch (error) { + console.error('❌ 选择头像失败:', error); + wx.showToast({ + title: '选择头像失败,请重试', + icon: 'none', + duration: 2000 + }); + } + }, + + // 上传头像到服务器(参考 profile.js 的实现) + async uploadAvatarToServer(tempFilePath) { + console.log('📤 开始上传头像,路径:', tempFilePath); + + if (!tempFilePath) { + throw new Error('头像路径为空,请重新选择头像'); + } + + // 验证文件路径是否可用 + try { + await new Promise((resolve, reject) => { + wx.getFileInfo({ + filePath: tempFilePath, + success: (res) => { + console.log('✅ 文件信息验证成功,大小:', res.size); + resolve(); + }, + fail: (err) => { + console.error('❌ 文件路径验证失败:', err); + reject(new Error('文件路径无效或文件不存在,请重新选择头像')); + } + }); + }); + } catch (error) { + console.error('❌ 验证文件失败:', error); + throw error; + } + + // 使用 COS 管理器上传头像(支持压缩、去重等功能) + const uploadResult = await cosManager.upload(tempFilePath, { + fileType: 'avatar', + enableDedup: true, + onProgress: (percent) => { + console.log('上传进度:', percent + '%'); + }, + enableCompress: false, + compressOptions: { + maxWidth: 400, + maxHeight: 400, + targetSize: 30 * 1024 + } + }); + + // 检查上传结果 + if (!uploadResult || !uploadResult.success || !uploadResult.fileUrl) { + const errorMsg = uploadResult?.error || uploadResult?.message || '上传失败:未获取到文件URL'; + console.error('❌ 上传结果异常:', uploadResult); + throw new Error(errorMsg); + } + + const avatarUrl = uploadResult.fileUrl; + console.log('✅ 头像上传成功,URL:', avatarUrl); + + // 更新全局用户信息 + if (app.globalData.userInfo?.user) { + app.globalData.userInfo.user.avatar = avatarUrl; + } + + // 同步到 NIM 和业务后端(静默处理,失败不影响主流程) + Promise.all([ + nimUserManager.updateSelfUserInfo({ avatar: avatarUrl }).catch(err => + console.error('⚠️ 同步头像到 NIM 失败:', err) + ), + apiClient.updateUserProfile({ avatar: avatarUrl }).catch(err => + console.error('⚠️ 同步头像到后端失败:', err) + ) + ]).then(() => { + console.log('✅ 头像已同步到 NIM 和业务后端'); + }); + + return avatarUrl; + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad: async function (options) { + // 应用屏幕适配到页面的数据 + await app.initScreen(this); + + // 预填用户信息(从登录数据中获取) + this.preFillUserInfo(); + }, + + /** + * 预填用户信息到表单 + */ + preFillUserInfo() { + // 优先从全局数据获取 + let profileData = app?.globalData?.profilePreFillData; + + // 如果全局数据没有,从本地存储获取 + if (!profileData) { + try { + profileData = wx.getStorageSync('profilePreFillData'); + } catch (e) { + console.warn('从本地存储获取数据失败:', e); + } + } + + // 如果还是没有,尝试从 userInfo 中获取 + if (!profileData) { + try { + const userInfo = wx.getStorageSync('userInfo'); + if (userInfo?.user) { + profileData = { + nickname: userInfo.user.nickname || userInfo.user.nickName || '', + avatar: userInfo.user.avatar || userInfo.user.avatarUrl || '', + gender: this.mapGenderToProfileFormat(userInfo.user.gender) + }; + } + } catch (e) { + console.warn('从userInfo获取数据失败:', e); + } + } + + // 如果有数据,预填到表单 + if (profileData) { + const updateData = {}; + if (profileData.nickname) updateData.nickname = profileData.nickname; + if (profileData.avatar) updateData.avatar = profileData.avatar; + if (profileData.gender) updateData.gender = profileData.gender; + + if (Object.keys(updateData).length > 0) { + this.setData(updateData); + console.log('✅ 已预填用户信息:', updateData); + } + + // 清除临时数据 + try { + app.globalData.profilePreFillData = null; + wx.removeStorageSync('profilePreFillData'); + } catch (e) { + console.warn('清除临时数据失败:', e); + } + } + }, + + /** + * 将后端性别格式转换为 profile-page 需要的格式 + * @param {number|string} gender - 后端返回的性别:0-未知,1-男,2-女,3-其他 + * @returns {string} 'man' 或 'woman' + */ + mapGenderToProfileFormat(gender) { + if (gender === 1 || gender === '1' || gender === 'man' || gender === 'male') { + return 'man'; + } else if (gender === 2 || gender === '2' || gender === 'woman' || gender === 'female') { + return 'woman'; + } + return 'man'; // 默认返回 'man' + }, + + /** + * 判断是否为临时文件路径 + */ + isTempFilePath(path) { + if (!path) return false; + return path.startsWith('wxfile://') || + path.startsWith('http://tmp/') || + path.startsWith('tmp/') || + (!path.startsWith('http://') && !path.startsWith('https://')); + }, + + async putProFile() { + const { nickname, gender, birthDate, avatar } = this.data; + + // 验证昵称 + if (!nickname) { + wx.showToast({ title: '请填写个人信息', icon: 'error' }); + return; + } + + const invalidReg = /[^\a-zA-Z0-9\u4e00-\u9fa5]/g; + if (invalidReg.test(nickname)) { + wx.showToast({ title: '支持文字、字母、数字输入', icon: 'error' }); + return; + } + + wx.showLoading({ title: '提交中...', mask: true }); + + try { + // 处理头像上传 + let avatarUrl = avatar; + const isTempPath = avatar && ( + avatar.startsWith('wxfile://') || + avatar.startsWith('http://tmp/') || + avatar.startsWith('tmp/') || + (!avatar.startsWith('http://') && !avatar.startsWith('https://')) + ); + + if (isTempPath) { + console.log('开始上传头像到服务器,临时路径:', avatar); + wx.showLoading({ title: '上传头像中...', mask: true }); + try { + avatarUrl = await this.uploadAvatarToServer(avatar); + this.setData({ avatar: avatarUrl }); + console.log('✅ 头像上传成功,URL:', avatarUrl); + } catch (uploadError) { + console.error('❌ 头像上传失败:', uploadError); + wx.hideLoading(); + wx.showToast({ + title: uploadError.message || '头像上传失败,请重试', + icon: 'none', + duration: 3000 + }); + return; // 上传失败,停止提交 + } + } + + // 根据生日计算星座 + const zodiacSign = birthDate ? calculateConstellationFromBirthday(birthDate) : ''; + + // 提交用户信息到后台 + await apiClient.updateUserProFileInfo( + nickname, + gender == 'man' ? 1 : 2, + birthDate || undefined, + avatarUrl || undefined, + zodiacSign || undefined + ); + // 保存成功后更新全局用户信息 + if (app.globalData.userInfo) { + // 更新全局用户信息 + if (!app.globalData.userInfo.user) { + app.globalData.userInfo.user = {}; + } + app.globalData.userInfo.user.nickname = nickname; + app.globalData.userInfo.user.gender = gender == 'man' ? 1 : 2; + if (birthDate) { + app.globalData.userInfo.user.birthday = birthDate; + } + if (avatarUrl) { + app.globalData.userInfo.user.avatar = avatarUrl; + } + if (zodiacSign) { + app.globalData.userInfo.user.zodiacSign = zodiacSign; + } + + // 同时更新本地存储 + try { + wx.setStorageSync('userInfo', app.globalData.userInfo); + console.log('✅ 全局用户信息已更新'); + } catch (e) { + console.warn('更新本地存储失败:', e); + } + } + wx.hideLoading(); + redirect.goMain(); + } catch (error) { + wx.hideLoading(); + console.error('提交失败:', error); + wx.showToast({ + title: error.message || '提交失败,请重试', + icon: 'error', + duration: 3000 + }); + } + } +}) diff --git a/pages/login/profile-page.json b/pages/login/profile-page.json new file mode 100644 index 0000000..53e2f5c --- /dev/null +++ b/pages/login/profile-page.json @@ -0,0 +1,8 @@ +{ + "usingComponents": { }, + "navigationBarTitleText": "个人信息", + "navigationBarBackgroundColor": "#000", + "navigationBarTextStyle": "white", + "backgroundColor": "#000", + "navigationStyle": "custom" +} \ No newline at end of file diff --git a/pages/login/profile-page.wxml b/pages/login/profile-page.wxml new file mode 100644 index 0000000..f1cfb35 --- /dev/null +++ b/pages/login/profile-page.wxml @@ -0,0 +1,40 @@ + + + 个人信息 + + + + + + + + + + {{nickNameError}} + + + + + + + + + + + + + + + + + + + 确定 + + + + \ No newline at end of file diff --git a/pages/login/profile-page.wxss b/pages/login/profile-page.wxss new file mode 100644 index 0000000..40ba5c5 --- /dev/null +++ b/pages/login/profile-page.wxss @@ -0,0 +1,281 @@ + +.personal-info-container{ + height: 100%; + box-sizing: border-box; + color: white; + display: flex; + flex-direction: column; + align-items: center; + + background: black; + min-height: 100vh; +} +.personal-info-title{ + box-sizing: border-box; + font-size: 64rpx; + justify-self: center; + margin-top: 260rpx; +} + + +.personal-info-imgs{ + box-sizing: border-box; + /* border: rgb(250, 32, 3) 5px solid; */ + height: 100%; + width: 80%; + display: flex; + justify-content:center; + justify-self:center; + margin-top:40rpx; + height: 120rpx; +} + +.avatar{ + padding: 0rpx; + width: 120rpx; + height: 120rpx; + border-radius: 50%; + background: rgba(255, 255, 255, 0.15); + transition: all 0.3s ease; + backdrop-filter: blur(20rpx); + -webkit-backdrop-filter: blur(20rpx); +} + +.avatar:active { + transform: scale(0.95); +} + +.avatar-image{ + width: 120rpx; + height: 120rpx; +} + + + +.avatar:active { + transform: scale(0.95); + box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.2); +} + +.personal-info-from{ + box-sizing: border-box; + /* border: rgb(250, 32, 3) 10rpx solid; */ + /* border: 2rpx solid red; */ + box-sizing: border-box; + display: grid; + grid-template-columns: 1fr; + grid-template-rows: repeat(6,1fr); + width: clamp(560rpx, 70vw, 840rpx); + height: clamp(640rpx,70vw, 800rpx); + justify-self: center; +} +.label-text{ + align-self: center; + font-size:32rpx; +} +.personal-info-inner{ + display: flex; + justify-content: center; + align-items: center; + border-radius: 16rpx; + background-color:#232323; + position: relative; + /* border: 2rpx solid red; */ +} + +/* 渐变边框样式 */ +.personal-info-inner.gradient-border { + background: linear-gradient(45deg, rgba(104, 249, 254, 0.6), rgba(170, 147, 237, 0.6)); + padding: 1rpx; + border-radius: 16rpx; +} + +.personal-info-inner.gradient-border:before { + content: ''; + position: absolute; + top: 1rpx; + left: 1rpx; + right: 1rpx; + bottom: 1rpx; + background-color: #232323; + border-radius: 15rpx; + z-index: 1; +} + +.personal-info-inner.gradient-border .mp-inpuet, +.personal-info-inner.gradient-border .picker-out { + position: relative; + z-index: 2; + background: transparent; +} + +/* 错误边框样式 */ +.personal-info-inner.error-border { + border: 2rpx solid #ff0000; + background-color: #232323; +} +.personal-info{ + height: clamp(60rpx,60vw, 100rpx); +} +.mp-inpuet{ + width: 100%; + height: 100%; + background: transparent; + border: none; + outline: none; + color: #aaaaaa; + font-size: 32rpx; + padding: 0 20rpx; + box-sizing: border-box; + text-align: left; +} + +.mp-inpuet::placeholder{ + color: #666666; + font-size: 32rpx; +} +.picker-out{ + width: 100%; + height: 120rpx; + display: flex; + align-items: center; + justify-content: flex-start; + position: relative; +} + +.picker { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: flex-start; + position: relative; +} +.mp-inpuet-text{ + width: 100%; + height: 100%; + background: transparent; + border: none; + outline: none; + color: #aaaaaa; + font-size: 32rpx; + padding: 0 20rpx; + box-sizing: border-box; + text-align: left; + line-height: 1; + display: flex; + align-items: center; + justify-content: flex-start; + position: relative; + z-index: 2; +} + +.mp-inpuet-text::placeholder{ + color: #666666; + font-size: 32rpx; +} + + +.personal-info-gender{ + display: grid; + grid-template-columns: repeat(2,1fr); + justify-self: start; +} + +/* 性别按钮基础样式 */ +.gender-btn { + box-sizing: border-box; + align-self: center; + width: 120rpx; + height: 100rpx; + color: #aaa; + line-height: 100rpx; + background: #232323; + border-radius: 16rpx; + transition: all 0.2s ease; + position: relative; + text-align: center; + font-size: 32rpx; + border: none; + padding: 0; +} + +.gender-btn:last-child { + margin-left: 40rpx; +} + +/* 渐变边框样式 */ +.gender-btn.gradient-border { + background: linear-gradient(45deg, rgba(104, 249, 254, 0.6), rgba(170, 147, 237, 0.6)); + padding: 1rpx; + border-radius: 16rpx; + position: relative; + color: #aaa; + z-index: 0; +} + +.gender-btn.gradient-border:before { + content: ''; + position: absolute; + top: 1rpx; + left: 1rpx; + right: 1rpx; + bottom: 1rpx; + background-color: #232323; + border-radius: 15rpx; + z-index: -1; +} + +/* 选中状态样式 */ +.gender-btn.gender-selected { + background: white; + color: black; + box-shadow: + 0 -8rpx 16rpx rgba(18, 158, 240, 0.2) inset, + 0 2rpx 4rpx rgba(0, 0, 0, 0.1) inset; + transform: translateY(4rpx); +} + + +.personal-info-btn{ + box-sizing: border-box; + justify-self: center; + align-self: center +} +.btn-next{ + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(135deg, #000000, #232323); + height: 100rpx; + width: 260rpx; + border-radius: 50rpx; + text-align: center; + color: white; + border: 2rpx solid #4e4e4e; + box-shadow: + 4rpx 4rpx 30rpx rgba(91, 196, 245, 0.1), + 0 4rpx 8rpx rgba(255, 255, 255, 0.2) inset; + transition: all 0.2s ease; + font-size: 40rpx; + font-weight: 500; + margin-top:60rpx; +} + +.btn-next:active{ + box-shadow: + 0 -16rpx 32rpx rgba(18, 158, 240, 0.1) inset, /* 内层上阴影(凹陷) */ + 0 4rpx 8rpx rgba(0, 0, 0, 0.1) inset; /* 内层下阴影 */ + transform: translateY(4rpx); /* 向下偏移,强化"按下"感 */ +} + +.error-message{ + text-align: start; + width: 80%; + height: 40rpx; + font-size: 24rpx; + /* border: 2rpx solid rgb(0, 255, 128); */ + color: red; + margin-top: 20rpx; + margin-left: 20rpx; +} \ No newline at end of file diff --git a/pages/map/map.js b/pages/map/map.js new file mode 100644 index 0000000..920c54a --- /dev/null +++ b/pages/map/map.js @@ -0,0 +1,6089 @@ +// 地图页面 - 高德地图SDK集成版本 +const app = getApp(); +const apiClient = require('../../utils/api-client.js'); +const { + MapUtils, + MAP_CONFIG +} = require('../../utils/map-config.js'); +const { + systemInfoHelper +} = require('../../utils/system-info-helper.js'); +const config = require('../../config/config.js'); +const authManager = require('../../utils/auth.js'); +// 使用完整版本的高德地图SDK,包含逆地理编码功能 +const { + AMapWX +} = require('../../libs/amap-wx.js'); +const { + MAP_FEED_MARKER_STYLE, + MAP_FEED_DEBOUNCE, + MAP_FEED_BUBBLE_LIMIT, + getFeedScalePreset, + buildBoundsPayload, + resolveFeedThumbnail, + buildCacheKey, + isCacheFresh +} = require('../../utils/map-feed-helpers.js'); +// 导入合作商家数据模块 +const { + getAllMerchants, + convertMerchantsToMarkers +} = require('../../utils/merchant-data.js'); + + +const wsManager = require('../../utils/websocket-manager-v2.js'); + +const marker_blank = '/images/map/marker_blank.png'; +const baseAmapUrl = config.api.baseAmapUrl; +const shouldUseMockData = !!config?.mockData; +const MAP_FEED_SINGLE_BASE_ID = 20000; +const MAP_FEED_CLUSTER_BASE_ID = 30000; +const MAP_FEED_ADMIN_BASE_ID = 40000; +const MAP_FEED_CLUSTER_STRANGER_ID = 50000; +const MAP_FEED_MARKER_STRANGER_ID = 70000; +const MAP_FEED_CLUSTER_FRIEND_ID = 60000; +const MAP_FEED_MARKER_FRIEND_ID = 80000; + +function formatFeedCountLabel(count) { + const safeCount = Number(count) || 0; + if (safeCount <= 0) { + return '暂无内容'; + } + if (safeCount >= 1000) { + return `${(safeCount / 1000).toFixed(1)}K 条内容`; + } + return `${safeCount} 条内容`; +} + +function formatHeatLabel(score) { + if (score === undefined || score === null) { + return '热度更新中'; + } + const value = Number(score); + if (Number.isNaN(value)) { + return '热度更新中'; + } + const rounded = Math.round(value); + if (rounded >= 95) { + return `热度爆棚 · ${rounded}`; + } + if (rounded >= 80) { + return `热度很高 · ${rounded}`; + } + if (rounded >= 60) { + return `热度上升 · ${rounded}`; + } + return '新鲜出炉'; +} + +function formatRadiusLabel(radius) { + const safeRadius = Math.max(20, Math.round(Number(radius) || 0)); + if (safeRadius >= 1000) { + return `范围约 ${(safeRadius / 1000).toFixed(1)} 公里`; + } + return `范围约 ${safeRadius} 米`; +} + +function buildBubbleData(payload = {}) { + const radiusValue = payload.radius || 200; + const radiusLabel = payload.radiusLabel || formatRadiusLabel(radiusValue); + return { + title: payload.title || '附近热点', + subtitle: payload.subtitle || '', + chip: payload.chip || '', + heat: payload.heat || '', + radiusLabel, + createdAt: payload.createdAt, + nickname: payload.nickname, + content: payload.content, + avatar: payload.avatar, + thumbnail: payload.thumbnail || '', + feeds: payload.feeds || [], + location: payload.location || null, + radius: radiusValue, + type: payload.type || 'map-feed-cluster', + tone: payload.tone || 'sunset' + }; +} + + +// 格式化后的模拟响应数据 +const mockResponseStrangerClusters = { + "code": 200, + "message": "success", + "data": { + "displayMode": "friends", + "totalUsers": 25, + "displayedUsers": 20, + "onlineUsers": 15, + "userPoints": [{ + "customId": "81149107", + "nickname": "用户7142", + "avatar": "https://oss.faxianwo.me/findme/images/731497293417c888e34942c14dd6e6ce.jpg", + "gender": 1, + "age": 25, + "latitude": 38.9042, + "longitude": 113.4074, + "address": "北京市朝阳区某某街道", + "district": "朝阳区", + "isOnline": true, + "lastSeen": 1706518800, + "stayTime": 3600, + "isMember": true, + "isFriend": true, + "relation": "friend", + "remark": "老同学", + "privacyLevel": 0, + "showPreciseLocation": true, + "distance": 150.5, + "distanceText": "150m", + "isCluster": false, + "clusterId": "" + }], + "clusters": [{ + "clusterId": "cluster_001", + "latitude": 39.9042, + "longitude": 116.4074, + "userCount": 5, + "onlineCount": 3, + "avatarPreview": [ + "https://example.com/avatar1.jpg", + "https://example.com/avatar2.jpg", + "https://example.com/avatar3.jpg" + ], + "isFriendCluster": true, + "canExpand": true, + "radius": 100.0 + }], + "bounds": { + "northEast": { + "latitude": 39.9142, + "longitude": 116.4174 + }, + "southWest": { + "latitude": 39.8942, + "longitude": 116.3974 + } + }, + "zoomLevel": 15, + "cacheHit": false, + "requestId": "req_1706518800123_4567", + "friendStats": { + "totalFriends": 25, + "onlineFriends": 15, + "offlineFriends": 10, + "nearbyFriends": 8, + "relationStats": { + "friend": 20, + "colleague": 3, + "family": 2 + } + } + } +} + + +const mockResponseStranger = { + "code": 200, + "message": "success", + "data": { + "displayMode": "friends", + "totalUsers": 25, + "displayedUsers": 20, + "onlineUsers": 15, + "userPoints": [{ + "customId": "81149107", + "nickname": "用户7142", + "avatar": "https://oss.faxianwo.me/findme/images/731497293417c888e34942c14dd6e6ce.jpg", + "gender": 1, + "age": 25, + "latitude": 39.9042, + "longitude": 116.4074, + "address": "北京市朝阳区某某街道", + "district": "朝阳区", + "isOnline": true, + "lastSeen": 1706518800, + "stayTime": 3600, + "isMember": true, + "isFriend": true, + "relation": "friend", + "remark": "老同学", + "privacyLevel": 0, + "showPreciseLocation": true, + "distance": 150.5, + "distanceText": "150m", + "isCluster": false, + "clusterId": "" + }], + "clusters": null, + "bounds": { + "northEast": { + "latitude": 39.9142, + "longitude": 116.4174 + }, + "southWest": { + "latitude": 39.8942, + "longitude": 116.3974 + } + }, + "zoomLevel": 15, + "cacheHit": false, + "requestId": "req_1706518800123_4567", + "friendStats": { + "totalFriends": 25, + "onlineFriends": 15, + "offlineFriends": 10, + "nearbyFriends": 8, + "relationStats": { + "friend": 20, + "colleague": 3, + "family": 2 + } + } + } +} + + + +const mockResponseDynamic = { + "code": 200, + "message": "success", + "data": { + "displayMode": "friends", + "totalUsers": 25, + "displayedUsers": 20, + "onlineUsers": 15, + "points": [{ + "feedUuid": "81149107", + "nickname": "用户7142", + "thumbnail": "https://oss.faxianwo.me/findme/images/731497293417c888e34942c14dd6e6ce.jpg", + "gender": 1, + "age": 25, + "latitude": 39.9042, + "longitude": 116.4074, + "address": "北京市朝阳区某某街道", + "district": "朝阳区", + "isOnline": true, + "lastSeen": 1706518800, + "stayTime": 3600, + "isMember": true, + "isFriend": true, + "relation": "friend", + "remark": "老同学", + "privacyLevel": 0, + "showPreciseLocation": true, + "distance": 150.5, + "distanceText": "150m", + "isCluster": false, + "clusterId": "" + }], + "clusters": null, + "bounds": { + "northEast": { + "latitude": 39.9142, + "longitude": 116.4174 + }, + "southWest": { + "latitude": 39.8942, + "longitude": 116.3974 + } + }, + "zoomLevel": 15, + "cacheHit": false, + "requestId": "req_1706518800123_4567", + "friendStats": { + "totalFriends": 25, + "onlineFriends": 15, + "offlineFriends": 10, + "nearbyFriends": 8, + "relationStats": { + "friend": 20, + "colleague": 3, + "family": 2 + } + } + } +} + + +const mockResponseFriendMarkerCluster = { + "code": 200, + "message": "success", + "data": { + "displayMode": "friends", + "totalUsers": 25, + "displayedUsers": 20, + "onlineUsers": 15, + "userPoints": [{ + "customId": "39361203", + "nickname": "用户4023", + "avatar": "", + "gender": 1, + "age": 25, + "latitude": 39.9742, + "longitude": 116.9074, + "address": "北京市朝阳区某某街道", + "district": "朝阳区", + "isOnline": true, + "lastSeen": 1706518800, + "stayTime": 3600, + "isMember": true, + "isFriend": true, + "relation": "friend", + "remark": "老同学", + "privacyLevel": 0, + "showPreciseLocation": true, + "distance": 150.5, + "distanceText": "150m", + "isCluster": false, + "clusterId": "" + }], + "bounds": { + "northEast": { + "latitude": 39.9142, + "longitude": 116.4174 + }, + "southWest": { + "latitude": 39.8942, + "longitude": 116.3974 + } + }, + "clusters": [{ + "clusterId": "cluster_001", + "latitude": 40.9042, + "longitude": 116.4074, + "userCount": 5, + "onlineCount": 3, + "avatarPreview": [ + "https://example.com/avatar1.jpg", + "https://example.com/avatar2.jpg", + "https://example.com/avatar3.jpg" + ], + "isFriendCluster": true, + "canExpand": true, + "radius": 100.0 + }], + "zoomLevel": 15, + "cacheHit": false, + "requestId": "req_1706518800123_4567", + "friendStats": { + "totalFriends": 25, + "onlineFriends": 15, + "offlineFriends": 10, + "nearbyFriends": 8, + "relationStats": { + "friend": 20, + "colleague": 3, + "family": 2 + } + } + } +} + +const mockResponseFriend = { + "code": 200, + "message": "success", + "data": { + "displayMode": "friends", + "totalUsers": 25, + "displayedUsers": 20, + "onlineUsers": 15, + "userPoints": [{ + "customId": "81149107", + "nickname": "用户7142", + "avatar": "", + "gender": 1, + "age": 25, + "latitude": 40.9042, + "longitude": 116.4074, + "address": "北京市朝阳区某某街道", + "district": "朝阳区", + "isOnline": true, + "lastSeen": 1706518800, + "stayTime": 3600, + "isMember": true, + "isFriend": true, + "relation": "friend", + "remark": "老同学", + "privacyLevel": 0, + "showPreciseLocation": true, + "distance": 150.5, + "distanceText": "150m", + "isCluster": false, + "clusterId": "" + }], + "clusters": null, + "bounds": { + "northEast": { + "latitude": 39.9142, + "longitude": 116.4174 + }, + "southWest": { + "latitude": 39.8942, + "longitude": 116.3974 + } + }, + "zoomLevel": 15, + "cacheHit": false, + "requestId": "req_1706518800123_4567", + "friendStats": { + "totalFriends": 25, + "onlineFriends": 15, + "offlineFriends": 10, + "nearbyFriends": 8, + "relationStats": { + "friend": 20, + "colleague": 3, + "family": 2 + } + } + } +} + + + +Page({ + data: { + showCameraAction: false, // 拍照弹窗 + isLoggedIn: app.globalData.isLoggedIn, // 登录状态 + isDarkMode:false, + amapFun: null, + poiAroundList: [], + showPoiAroundModal: false, + // 地图配置 + longitude: 0, + latitude: 0, + currentMapScale: 12, // 初始缩放级别,低于自动切换阈值 + + //商家信息 + merchantMarkers: [], + merchantList: [], // 商家列表数据 + merchantInfoModalVisible: false, + selectedMerchant: null, + activeMerchantId: null, // 当前激活的商户ID + + // 静态数据 + staticDataMarkers: [], // 存储静态数据标记 + + // 位置信息 + currentAddress: '获取位置中...', + addressDetail: null, + accuracy: 0, + currentDistrict: '新市区', // 设置默认地点名称 + currentCity: '乌鲁木齐', // 设置默认城市名称 + weatherInfo: null, + + // SDK状态 + amapReady: false, + amapError: null, + + // 好友数据 + friendsData: [], + // 用户信息 + userInfo: null, + userAvatar: '', + avatar: '', + avatarUrl: '', + showUserLocationIndicator: false, + showMyAvatarMarker: true, + myLocation: null, // 保存自己的位置信息 + + // 地图样式控制 + enableSatellite: false, + currentMapType: 'standard', // standard, satellite, traffic, transit + shouldFollowLocation: true, // 控制是否跟随用户位置移动 + autoSatelliteZoom: 18, // 超过此缩放级别自动切换卫星图 + maxScale: 22, // 地图最大缩放级别,设置为22以提高卫星图清晰度 + mapTheme: 'light', // 地图主题:light 或 dark + + // 系统适配 + statusBarHeight: 44, + menuButtonHeight: 32, + navBarHeight: 88, + safeAreaBottom: 0, + + // UI状态 + selectedUser: null, + currentFilter: 'friends', + friendsCount: 0, + strangersCount: 0, + showFilterModal: false, + + // 🔥 浮动UI状态 + isOnline: true, + friendRequestCount: 0, + unreadMessageCount: 0, + nearbyCount: 0, + + // 地址信息 + weather: null, + + // 默认位置(如果定位失败) + defaultLocation: { + latitude: 39.908692, + longitude: 116.397979, + address: '北京市' + }, + + // 地图动态相关 + locationDynamics: [], // 存储地图上的所有动态 + showDynamicInputModal: false, // 显示动态输入弹窗 + currentDynamicLocation: null, // 当前要发布动态的位置 + dynamicContent: '', // 动态内容 + selectedDynamic: null, // 当前选中的动态 + showDynamicDetailModal: false, // 显示动态详情弹窗 + mapFeedMode: 'nearby', + mapFeedLevel: 'street', + mapFeedLoading: false, + mapFeedError: '', + mapFeedMarkers: [], + mapFeedPreviewList: [], + activeFeedBubble: null, + activeFeedBubbleLoading: false, + hasUserInteractedWithMap: false, + poiDetail: { + address: '', // 预先定义 address 属性 + name: '' + }, + poiDetailShow: false, + showPoiRemindModal: false, + poiRemindRadius: 300, // 默认300米 + poiRemindCircle: null, + poiRemindMode: ['arrive'], // 多选,初始为到达 + showFriendSelectModal: false, + lastPoiForRemind: null, + allFriendsList: [], // 新增:用于好友选择弹窗的模拟数据 + // 新增 + friendSearchText: '', + filteredFriendsList: [], + showLocationMarkModal: false, + locationMarkSearchText: '', + locationMarkList: [], + filteredLocationMarkList: [], + + // 搜索相关状态 + showSearchBox: false, + searchKeyword: '', + searchResults: [], // 存储搜索结果 + searchResultInfoModalVisible: false, + placeMarkId: '', + // 更多菜单相关状态 + showMoreMenu: false, + + // 地图设置相关状态 + showMapSettings: false, + isClosingMapSettings: false, + mapStyle:null, + // POI提醒相关状态 + poiRemindSelectedFriends: [], // 存储已选择的好友信息 + + // 地点收藏栏相关状态 + showLocationFavoriteBar: false, // 控制收藏栏显示 + locationFavoriteTab: 'favorite', // 当前选中的标签:nearby或favorite + locationFavorites: [], // 所有收藏地点 + filteredLocationFavorites: [], // 过滤后的收藏地点 + locationFavoriteSearch: '', // 搜索关键词 + showTraffic: false, // 默认不显示交通拥堵 + merchantName: "", + merchant: "", + merchantAddress: "", + shareModalVisible: true, + shareShareVisible: false, + searchResultNavigationVisible: false, + selectResult: null, + addressIsFavorited: false, + longitude: 116.404, // 初始经度(示例:北京) + latitude: 39.915, // 初始纬度 + metric: "0米", // 米/千米 + imperial: "0英尺", // 英尺 + allMarkers: [], + userMarker: null, + renderKey: null, + poiDetailAddress: '详细地址', + busStops: [], // 公交站点标记 + busLines: [], // 公交线路 + isBusLayerVisible: false, // 公交图层显示状态 + busDataLoading: false, // 公交数据加载状态 + lastBusRegion: null, // 上一次加载公交数据的区域 + busDataExpireTime: 300000, // 公交数据缓存过期时间(5分钟) + busDataCache: new Map(), + mapClickCollect: '收藏', + // 数据存储 + busLines: [], + subwayLines: [], + markers: [], + polylines: [], + // 存储当前设备方向角度(0-360°) + // 标记是否支持设备方向 + isSupport: false, + // 标记是否已获取权限 + hasPermission: false, + mapClickCollect: '收藏', + isMapClick: false, + markers: [], + activeFeedBubbleSingle: null, + clusterMarkers: [], // 新增:存储聚合点 marker + polygons: [], // 存储多边形覆盖物 + clusterThreshold: 1000, //陌生人和好友聚合的临界值单位米 + activeFeedSingleVisible: false, + cacheEntryString: '', + directonAngle: -1, + mapFeedVisible: false, + startY: 0, + modalTranslateY: 0, + isMoving: false, + shareOptions: [{ + type: "wechat", + icon: "/images/map/Wechat_logo.png", + name: "微信" + }, + { + type: "douyin", + icon: "/images/map/Tiktok_logo.png", + name: "抖音" + }, + { + type: "weibo", + icon: "/images/map/Microblog_logo.png", + name: "微博" + }, + { + type: "email", + icon: "/images/map/Email_logo.png", + name: "邮箱" + }, + { + type: "qq", + icon: "/images/map/QQ_logo.png", + name: "QQ" + }, + { + type: "copy", + icon: "/images/map/Copy_logo.png", + name: "复制" + }, + ], + + }, + + + // 显示地点收藏栏 + onOpenLocationFavoriteBar() { + + this.initLocationFavorites(); + + this.setData({ + showLocationFavoriteBar: true, + locationFavoriteTab: 'favorite', + locationFavoriteSearch: '' + }); + + }, + + + // 关闭地点收藏栏 + onCloseLocationFavoriteBar() { + + this.setData({ + showLocationFavoriteBar: false + }); + }, + + // 初始化收藏地点数据 + initLocationFavorites() { + // 创建一些模拟数据 + if (!shouldUseMockData) { + this.setData({ + locationFavorites: [], + filteredLocationFavorites: [] + }); + return; + } + }, + + // 切换标签 + onChangeLocationFavoriteTab(e) { + const tab = e.currentTarget.dataset.tab; + this.setData({ + locationFavoriteTab: tab, + locationFavoriteSearch: '' + }); + + // 根据标签切换显示不同的内容 + if (tab === 'nearby') { + // 这里可以添加获取附近地点的逻辑 + // 暂时使用收藏地点数据 + this.setData({ + filteredLocationFavorites: this.data.locationFavorites + }); + } else if (tab === 'favorite') { + this.setData({ + filteredLocationFavorites: this.data.locationFavorites.filter(item => item.isFavorited) + }); + } + }, + + + previewImageAvatar(e) { + try { + // 获取当前点击的图片索引和动态索引 + const avatar = e.currentTarget.dataset.avatar; + // 🔥 设置标志,防止预览关闭后触发页面刷新 + this._skipNextOnShowReload = true; + const imageUrls=[avatar]; + // 调用微信小程序的图片预览API + wx.previewImage({ + current: avatar, + urls: imageUrls, + success: () => { + // 预览打开成功,标志已设置,关闭时会触发 onShow + }, + fail: (err) => { + console.error('图片预览失败:', err); + // 预览失败,清除标志 + this._skipNextOnShowReload = false; + wx.showToast({ + title: '预览图片失败', + icon: 'none' + }); + } + }); + } catch (error) { + console.error('图片预览过程中出错:', error); + // 出错时清除标志 + this._skipNextOnShowReload = false; + wx.showToast({ + title: '预览图片失败', + icon: 'none' + }); + } + }, + + + + + // 地点收藏搜索 + onLocationFavoriteSearch(e) { + const searchText = e.detail.value; + this.setData({ + locationFavoriteSearch: searchText + }); + + // 根据搜索关键词筛选地点 + let filtered = []; + if (this.data.locationFavoriteTab === 'nearby') { + filtered = this.data.locationFavorites.filter(item => + item.name.includes(searchText) || item.address.includes(searchText) + ); + } else { + filtered = this.data.locationFavorites.filter(item => + item.isFavorited && (item.name.includes(searchText) || item.address.includes(searchText)) + ); + } + + this.setData({ + filteredLocationFavorites: filtered + }); + }, + + + // 清除地点收藏搜索 + onClearLocationFavoriteSearch() { + this.setData({ + locationFavoriteSearch: '', + filteredLocationFavorites: this.data.locationFavoriteTab === 'nearby' ? + this.data.locationFavorites : this.data.locationFavorites.filter(item => item.isFavorited) + }); + }, + + // 切换地点收藏状态 + onToggleLocationFavorite(e) { + const id = e.currentTarget.dataset.id; + const locationFavorites = this.data.locationFavorites.map(item => { + if (item.id === id) { + item.isFavorited = !item.isFavorited; + } + return item; + }); + + // 根据当前标签和搜索词更新过滤后的列表 + let filtered = []; + if (this.data.locationFavoriteTab === 'nearby') { + filtered = locationFavorites.filter(item => + item.name.includes(this.data.locationFavoriteSearch) || + item.address.includes(this.data.locationFavoriteSearch) + ); + } else { + filtered = locationFavorites.filter(item => + item.isFavorited && (item.name.includes(this.data.locationFavoriteSearch) || + item.address.includes(this.data.locationFavoriteSearch)) + ); + } + + this.setData({ + locationFavorites: locationFavorites, + filteredLocationFavorites: filtered + }); + }, + + // 显示筛选选项弹窗 + showFilterOptions() { + this.setData({ + showFilterModal: true + }); + }, + + // 隐藏筛选选项弹窗 + hideFilterOptions() { + this.setData({ + showFilterModal: false + }); + }, + + initMapFeedState() { + if (this.mapFeedDebounceTimer) { + clearTimeout(this.mapFeedDebounceTimer); + } + + this.mapFeedDebounceTimer = null; + this.mapFeedCache = new Map(); + this.mapFeedMarkerLookup = new Map(); + this.mapStrangerMarkerLookup = new Map(); + + this.setData({ + mapFeedMarkers: [], + mapFeedPreviewList: [], + activeFeedBubble: null, + mapFeedMode: 'nearby', + mapFeedLevel: 'street', + mapFeedError: '', + mapFeedLoading: false + }); + }, + + // 显示拍照功能弹窗 + showCameraActionSheet() { + this.setData({ + showCameraAction: true + }); + }, + + // 隐藏拍照功能弹窗 + hideCameraActionSheet() { + this.setData({ + showCameraAction: false + }); + }, + + // 拍摄照片 + takePhoto() { + this.hideCameraActionSheet(); + // 检查登录状态 + + // 未登录进入登录页面 + if (!authManager.isLoggedIn()) { + + wx.navigateTo({ + url: '/pages/login/login' + }); + } else { + + wx.navigateTo({ + url: '/subpackages/media/camera/camera' // 已登录用户跳转到拍摄页面 + }); + } + }, + + // 从相册选择 + chooseImage() { + this.hideCameraActionSheet(); + // 检查登录状态 + + // 未登录进入登录页面 + if (!authManager.isLoggedIn()) { + + wx.navigateTo({ + url: '/pages/login/login' + }); + } else { + wx.chooseImage({ + count: 1, + sizeType: ['original', 'compressed'], + sourceType: ['album'], + success: (res) => { + const tempFilePath = res.tempFilePaths[0]; + // 显示加载提示 + wx.showLoading({ + title: '上传中...', + mask: true + }); + // 处理选择的图片 + this.uploadImage(tempFilePath) + .then(imageUrl => { + wx.hideLoading(); + wx.navigateTo({ + url: `/pages/edits/edits?imagePath=${encodeURIComponent(imageUrl)}`, + success: () => { + wx.showToast({ + title: '上传成功', + icon: 'success' + }); + }, + fail: (err) => { + console.error('跳转发布页失败:', err); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none' + }); + } + }); + }) + .catch(error => { + wx.hideLoading(); + console.error('上传过程出错:', error); + wx.showToast({ + title: error.message || '上传失败,请重试', + icon: 'none' + }); + }); + }, + fail: (error) => { + console.error('选择图片失败:', error); + wx.showToast({ + title: '选择图片失败', + icon: 'none' + }); + } + }); + } + }, + + // 上传图片 + uploadImage(tempFilePath) { + return new Promise((resolve, reject) => { + try { + + wx.uploadFile({ + url: `${config.api.baseUrl}/api/v1/file/upload`, + filePath: tempFilePath, + name: 'file', + formData: { + file_type: 'image', + usage_type: 'feed' + }, + header: { + 'Authorization': `Bearer ${apiClient.getToken()}` + }, + success: (uploadRes) => { + + // 🔥 统一处理401 - 使用apiClient的统一处理 + if (apiClient.is401Error(uploadRes)) { + const app = getApp(); + const isLoggedIn = app?.globalData?.isLoggedIn || false; + apiClient.handle401Error(isLoggedIn); + // 对已登录用户抛出错误 + if (isLoggedIn) { + reject(new Error('登录已过期,请重新登录')); + } else { + // 对未登录用户返回空数据 + resolve(null); + } + return; + } + + // 解析响应数据 + let result; + try { + result = JSON.parse(uploadRes.data); + } catch (e) { + console.error('解析响应JSON失败,响应数据:', uploadRes.data); + reject(new Error('解析服务器响应失败')); + return; + } + + // 上传成功 + if (uploadRes.statusCode === 200 && result.code === 0) { + if (result.data && result.data.file_url) { + resolve(result.data.file_url); + } else { + reject(new Error('服务器未返回图片URL')); + } + } else { + reject(new Error(result.msg || '上传失败')); + } + }, + fail: (error) => { + console.error('上传请求失败:', error); + let errorMsg = '网络请求失败,请检查网络'; + if (error.errMsg) { + errorMsg = error.errMsg; + } + reject(new Error(errorMsg)); + } + }); + } catch (error) { + console.error('上传图片到服务器失败:', error); + reject(error); + } + }); + }, + + // 显示筛选选项弹窗 + showFilterOptions() { + this.setData({ + showFilterModal: true + }); + }, + + // 隐藏筛选选项弹窗 + hideFilterOptions() { + this.setData({ + showFilterModal: false + }); + }, + + onLoad() { + console.log("on-->" + "onLoad"); + // 初始化模拟天气数据,确保天气信息始终显示 + if (shouldUseMockData) { + const mockWeatherInfo = { + temperature: 25, + weather: '晴', + icon: '☀️', + isCloudIcon: false, + humidity: 45, + windSpeed: 3.2, + windDir: '东南风', + aqi: 85, + city: this.data.currentCity || '乌鲁木齐', + updateTime: new Date().toLocaleTimeString('zh-CN') + }; + this.setData({ + weatherInfo: mockWeatherInfo + }); + console.debug('✅ 已设置模拟天气数据:', mockWeatherInfo); + } else { + this.setData({ + weatherInfo: null + }); + } + + this.amapFun = new AMapWX({ + key: config.amapKey + }); + // 使用已经创建的系统信息辅助实例 + this.systemInfoHelper = systemInfoHelper; + + // 获取系统信息和胶囊按钮位置 + const systemInfo = this.systemInfoHelper.getSystemInfoSync(); + const menuButtonInfo = this.systemInfoHelper.getMenuButtonBoundingClientRect(); + + // 计算导航栏高度和胶囊位置信息 + const navBarHeight = this.systemInfoHelper.getNavBarHeight(systemInfo); + + this.setData({ + statusBarHeight: systemInfo.statusBarHeight || 44, + navBarHeight: navBarHeight, + windowHeight: systemInfo.windowHeight || 667, + safeAreaBottom: systemInfo.safeArea?.bottom || 0, + menuButtonTop: menuButtonInfo.top || 48, + menuButtonRight: menuButtonInfo.right || 365, + menuButtonWidth: menuButtonInfo.width || 87, + menuButtonHeight: menuButtonInfo.height || 32 + }); + + // 初始化API客户端 + this.apiClient = apiClient; + + // 初始化地图动态状态 + this.initMapFeedState(); + + // 初始化静态数据 + this.initStaticData(); + + // 初始化合作商家数据 + this.initMerchantMarkers(); + + // 初始化地图上下文 + this.mapCtx = wx.createMapContext('main-map', this); + // this.mapCtx.initMarkerCluster({ + // enableDefaultStyle: false, // 使用默认聚合样式 + // zoomOnClick: true, // 点击聚合点自动放大 + // gridSize: 60, // 聚合计算网格大小,单位px + // complete(res) {} + // }); + this.initSystemInfo(); + this.initAMapSDK(); + console.log("onload----->" + Date.now()); + this.requestLocationPermission(); + + this.lastFriendsFetch = 0; + this.lastNearbyFetch = 0; + this.lastWeatherFetch = 0; + this.lastLocationSnapshot = null; + + // 🔥 加载浮动UI相关数据 + this.loadFloatingUIData(); + + // 注入模拟好友数据 + if (shouldUseMockData) { + const mockFriends = [{ + userId: 'u1', + nickname: '小明', + avatarUrl: '' + }, + { + userId: 'u2', + nickname: '小红', + avatarUrl: '' + }, + { + userId: 'u3', + nickname: '小刚', + avatarUrl: '' + }, + { + userId: 'u4', + nickname: '小美', + avatarUrl: '' + }, + { + userId: 'u5', + nickname: '小强', + avatarUrl: '' + } + ]; + this.setData({ + allFriendsList: mockFriends, + filteredFriendsList: mockFriends + }); + + const mockLocationMarkList = [{ + id: 'loc1', + lat: 44.897383746906186, + lng: 82.07800276534772, + name: '博尔塔拉长城医院', + remindFriends: [{ + userId: 'u1', + avatarUrl: '' + }, + { + userId: 'u2', + avatarUrl: '' + } + ], + remindType: 'arrive' + }, + { + id: 'loc2', + lat: 44.90334720165053, + lng: 82.06464725905994, + name: '博乐市第八中学', + remindFriends: [{ + userId: 'u3', + avatarUrl: '' + }], + remindType: 'leave' + } + ]; + + this.setData({ + locationMarkList: mockLocationMarkList, + filteredLocationMarkList: mockLocationMarkList + }); + } else { + this.setData({ + allFriendsList: [], + filteredFriendsList: [], + locationMarkList: [], + filteredLocationMarkList: [] + }); + + this.setData({ + isBusLayerVisible: wx.getStorageSync('busLayerState') || false + }); + } + + wx.showShareMenu({ + withShareTicket: true, // 可选,是否带上 shareTicket + menus: ['shareAppMessage', 'shareTimeline'] // 指定分享菜单,'shareAppMessage' 用于分享到聊天 + }) + + + // 初始化计算 + this.updateScale(); + this.startListening(); + // this.getCityBoundary("大理"); + this.loadUserInfo(); + // this.getInitialOrientation(); + this.checkSystemTheme(); + }, + +// 核心:判断系统主题 + 手机系统类型(安卓/苹果) +checkSystemTheme() { + try { + // 同步获取系统信息(含主题、系统类型等) + const systemInfo = wx.getSystemInfoSync(); + + // 1. 判断手机系统类型(安卓/苹果) + const isIOS = /ios/i.test(systemInfo.system); // 匹配 iOS 系统(忽略大小写) + const isAndroid = /android/i.test(systemInfo.system); // 匹配 Android 系统(忽略大小写) + + // 2. 判断系统主题(深色/浅色) + const isDark = systemInfo.theme === 'dark'; + + // 3. 更新数据(同时保存系统类型和主题状态) + if(isAndroid){ + this.setData({ + isDarkMode: false, + isIOS: isIOS, + isAndroid: isAndroid + }); + }else{ + this.setData({ + isDarkMode: isDark, + isIOS: isIOS, + isAndroid: isAndroid + }); + } + + + // 打印日志(清晰展示系统类型+主题) + console.log( + '当前设备:', + isIOS ? '苹果手机(iOS)' : isAndroid ? '安卓手机(Android)' : '其他设备', + ' | 系统主题:', + isDark ? '深色模式' : '浅色模式' + ); + } catch (err) { + // 异常处理(低版本微信/获取系统信息失败) + console.error('获取系统信息(主题+设备类型)失败:', err); + this.setData({ + isDarkMode: false, // 异常时默认浅色模式 + isIOS: false, + isAndroid: false + }); + } +}, + + + + + async loadUserInfo() { + try { + // 先从全局数据获取 + let userInfo = getApp().globalData.userInfo; + // 如果全局没有完整信息,从API获取 + + // const response = await this.apiClient.getUserInfo(); + // console.log("info--->2"+response); + // if (!userInfo) { + const response = await apiClient.getUserInfo(); + if (response && response.code === 0) { + userInfo = { + ...userInfo, + user: response.data + }; + // 更新全局数据 + getApp().globalData.userInfo = userInfo; + console.log("info--->1" + response); + } + // } + + this.setData({ + userInfo: userInfo + }); + + this.initWebSocketFriendFeatures(); + + } catch (error) { + console.error('❌ 获取用户信息失败:', error); + // 不影响主要功能,继续加载好友列表 + } + }, + + + getInitialOrientation() { + let that = this; + return new Promise((resolve, reject) => { + // 先检查设备是否支持罗盘(更准确的方向传感器) + wx.getSystemInfo({ + success: (sysInfo) => { + // 扩展支持检测:同时检查罗盘和设备运动传感器 + const supportCompass = typeof wx.onCompassChange === 'function'; + const supportMotion = typeof wx.onDeviceMotionChange === 'function'; + + if (!supportCompass && !supportMotion) { + console.warn('设备不支持方向感应,使用默认方向'); + resolve(0); // 返回默认角度(正北) + return; + } + + // 优先使用罗盘(方向更稳定) + if (supportCompass) { + const compassListener = (res) => { + // 罗盘返回的是与正北的夹角(0-360°) + const angle = Math.round(res.direction); + if (typeof angle === 'number' && !isNaN(angle)) { + this.setData({ + directonAngle: angle + }); + this.updateArrowDirection(angle); + wx.offCompassChange(compassListener); // 移除监听 + resolve(angle); + } + }; + + wx.onCompassChange(compassListener); + + // 启动罗盘(部分设备需要主动启动) + wx.startCompass({ + success: () => {}, + fail: () => { + wx.offCompassChange(compassListener); + fallbackToMotionSensor(resolve); // 启动失败时降级 + } + }); + } else { + // 无罗盘时使用设备运动传感器 + fallbackToMotionSensor(resolve); + } + + // 超时处理 + setTimeout(() => { + if (supportCompass) wx.offCompassChange(); + if (supportMotion) wx.offDeviceMotionChange(); + console.warn('获取方向超时,使用默认值'); + resolve(0); + }, 3000); + }, + fail: (err) => { + console.error('获取系统信息失败', err); + resolve(0); // 系统信息获取失败时仍返回默认值 + } + }); + + // 设备运动传感器降级处理 + function fallbackToMotionSensor(resolve) { + const motionListener = (deviceData) => { + // alpha值:绕z轴旋转角度(0-360°) + if (typeof deviceData.alpha === 'number' && !isNaN(deviceData.alpha)) { + const angle = Math.round(deviceData.alpha); + console.log("angle--->" + angle); + that.setData({ + directonAngle: angle + }); + that.updateArrowDirection(angle); + // wx.offDeviceMotionChange(motionListener); + resolve(angle); + } + }; + + wx.onDeviceMotionChange(motionListener); + + // 启动设备运动监听(部分设备需要) + // wx.startDeviceMotionListening({ + // interval: 'normal', + // success: () => {}, + // fail: (err) => { + // wx.offDeviceMotionChange(motionListener); + // console.warn('设备运动监听启动失败', err); + // resolve(0); + // } + // }); + } + }); + }, + + + + initWebSocketFriendFeatures() { + try { + console.log('🔌 初始化WebSocket好友事件监听器'); + // 绑定处理函数到 this,方便后续移除 + this.handleNotificationMessage = this.handleNotificationMessage.bind(this); + + wsManager.on('user_offline', this.handleNotificationMessage); + + } catch (error) { + console.error('初始化WebSocket功能失败:', error); + } + }, + + // 处理通知消息 + handleNotificationMessage(msg) { + try { + console.log('🔔 收到心跳---->:', msg); + } catch (error) { + console.error('处理通知消息失败:', error); + } + }, + + + // 调用高德接口获取城市边界 + getCityBoundary(cityName) { + let that = this; + wx.request({ + url: baseAmapUrl + '/config/district', + data: { + keywords: cityName, + subdistrict: 0, // 不返回子区域 + extensions: 'all', // 必须为all才能获取polyline + key: config.amapKey // 替换为你的Key + }, + success: (res) => { + if (res.data.status === '1' && res.data.districts.length > 0) { + const district = res.data.districts[0]; + const polyline = district.polyline; // 边界坐标串 + // 解析为小程序polygons格式 + const polygons = that.parsePolylineToPolygons(polyline, district.adcode); + // 更新地图数据 + this.setData({ + polygons: polygons + }); + } + }, + fail: (err) => { + console.error('获取边界失败:', err); + } + }); + }, + // 解析高德接口返回的polyline为小程序polygons格式 + parsePolylineToPolygons(polyline, cityId) { + const polygons = []; + // 按 | 分割多个环(每个环是一个独立多边形) + const rings = polyline.split('|'); + + rings.forEach((ring, index) => { + // 按 ; 分割单个环的坐标点 + const pointStrs = ring.split(';'); + // 转换为 { longitude, latitude } 格式 + const points = pointStrs.map(pointStr => { + const [lng, lat] = pointStr.split(',').map(Number); + return { + longitude: lng, + latitude: lat + }; + }); + + // 添加到polygons数组(可自定义样式) + polygons.push({ + id: `${cityId}_${index}`, // 唯一标识(主区域+子区域区分) + points, + fillColor: '#1098B0', + strokeColor: '#0DD2FC', + strokeWidth: 2, + fillOpacity: 0.6, + strokeDasharray: [5, 5] + }); + }); + + return polygons; + }, + + + + /** + * 生成区域唯一标识 + * @param {Object} region - 地图区域 + * @returns {String} 区域标识 + */ + getRegionKey(region) { + // 四舍五入到小数点后4位,减少精度导致的重复 + return [ + Math.round(region.southwest.latitude * 10000) / 10000, + Math.round(region.southwest.longitude * 10000) / 10000, + Math.round(region.northeast.latitude * 10000) / 10000, + Math.round(region.northeast.longitude * 10000) / 10000 + ].join(','); + }, + + /** + * 检查是否同一区域 + * @param {String} regionKey - 区域标识 + * @returns {Boolean} 是否同一区域 + */ + isSameRegion(regionKey) { + return this.data.lastBusRegion === regionKey; + }, + + /** + * 检查缓存是否过期 + * @param {String} regionKey - 区域标识 + * @returns {Boolean} 是否过期 + */ + isCacheExpired(regionKey) { + const cache = this.busDataCache.get(regionKey); + if (!cache) return true; + return Date.now() - cache.timestamp > this.data.busDataExpireTime; + }, + + + // 4. 更新箭头方向(根据实际业务场景修改) 可旋转但是会重复多个 + updateArrowDirection(angle) { + const targetIndex = this.data.markers.findIndex(marker => marker.id === 1); + + if (targetIndex !== -1) { + this.setData({ + directonAngle: angle, + [`markers[${targetIndex}].directonAngle`]: angle, + [`markers[${targetIndex}].directionPath`]: '/images/map/direction_arrow.png' + }); + } + + + }, + + + // 页面隐藏/卸载时停止监听(必须做,否则会耗电) + onHide() { + this.stopListening(); + }, + onUnload() { + this.stopListening(); + // 移除 WebSocket 通知监听器 + try { + if (this.handleNotificationMessage) { + wsManager.off('user_offline', this.handleNotificationMessage); + console.log('✅ 已移除 WebSocket 通知监听器'); + } + } catch (error) { + console.error('移除 WebSocket 通知监听器失败:', error); + } + }, + + // 停止监听的工具方法 + startListening() { + // 停止可能存在的旧监听(避免重复监听) + wx.stopDeviceMotionListening({}); + + // 新增:记录上一次的角度值,用于判断角度变化是否超过阈值 + let lastAngle = null; + // 记录上次更新时间 + let lastUpdateTime = 0; + // 角度变化阈值(度),超过此值才更新 + const ANGLE_THRESHOLD = 5; + // 最小更新间隔(毫秒),避免过于频繁更新 + const MIN_UPDATE_INTERVAL = 1000; + + // 启动新监听 + wx.startDeviceMotionListening({ + interval: 'game', // 高频监听(适合实时方向更新) + success: () => { + console.log('方向监听启动成功'); + + // 监听方向变化事件 + this.motionListener = wx.onDeviceMotionChange((res) => { + // res.alpha:设备绕垂直轴旋转角度(0-360°,0为正北) + if (typeof res.alpha === 'number' && !isNaN(res.alpha)) { + // 取整数角度,减少抖动 + const currentAngle = Math.round(res.alpha); + const now = Date.now(); + + // 满足以下条件才更新: + // 1. 距离上次更新超过最小间隔时间 + // 2. 角度变化超过阈值(首次记录时直接更新) + const isAngleChangedEnough = lastAngle === null || + Math.abs(currentAngle - lastAngle) >= ANGLE_THRESHOLD; + const isTimeEnough = now - lastUpdateTime >= MIN_UPDATE_INTERVAL; + + if (isAngleChangedEnough && isTimeEnough) { + console.log(`方向变化超过${ANGLE_THRESHOLD}度,更新角度: ${currentAngle}`); + this.updateArrowDirection(currentAngle); + // 更新记录值 + lastAngle = currentAngle; + lastUpdateTime = now; + } + if (this.data.directonAngle == -1) { + this.setData({ + directonAngle: currentAngle + }); + this.updateArrowDirection(currentAngle); + } + } + }); + }, + fail: (err) => { + console.error('监听启动失败:', err); + } + }); + }, + + + + // 页面隐藏/卸载时停止监听(必须做,否则会耗电) + onHide() { + this.stopListening(); + }, + onUnload() { + this.stopListening(); + }, + + // 停止监听的工具方法 + stopListening() { + if (this.motionListener) { + this.motionListener(); // 移除监听事件 + this.motionListener = null; + } + wx.stopDeviceMotionListening({}); // 停止监听服务 + }, + + + updateScale() { + const that = this + // 直接获取当前缩放级别(同步操作,无延迟) + this.mapCtx.getScale({ + success(res) { + const currentScale = res.scale + // 计算比例尺数值 + that.calcScale(currentScale) + }, + // 极端情况:如果获取失败,100ms后重试(确保最终能更新) + fail() { + setTimeout(() => { + that.updateScale() + }, 100) + } + }) + }, + + calcScale(scale) { + // 计算100px线段对应的实际距离(米) + const metersPerPx = 156543.03392 * Math.cos(39.915 * Math.PI / 180) / Math.pow(2, scale) + const totalMeters = metersPerPx * 100 // 100px线段的实际距离 + + // ---------------------- + // 公制单位:米 → 千米(自动转换+取整) + // ---------------------- + let metricText; + if (totalMeters >= 1000) { + // ≥1000米时转千米,四舍五入取整数 + const km = Math.round(totalMeters / 1000) + metricText = `${km}千米` + } else { + // <1000米时保留米,四舍五入取整数 + metricText = `${Math.round(totalMeters)}米` + } + metricText = metricText + // ---------------------- + // 英制单位:英尺 → 英里(自动转换+取整) + // 1英里 = 5280英尺(转换临界点) + // ---------------------- + const totalFeet = totalMeters * 3.28084 // 先转成英尺 + let imperialText; + if (totalFeet >= 5280) { + // ≥5280英尺时转英里,四舍五入取整数 + const miles = Math.round(totalFeet / 5280) + imperialText = `${miles}英里` + } else { + // <5280英尺时保留英尺,四舍五入取整数 + imperialText = `${Math.round(totalFeet)}英尺` + } + + this.setData({ + metric: metricText, + imperial: imperialText + }) + }, + + + onShow() { + console.log("on-->" + "onShow"); + // 同步全局登录状态 + this.setData({ + isLoggedIn: app.globalData.isLoggedIn, + userInfo: app.globalData.userInfo + }); + + if (this.data.amapReady) { + this.startLocationService(); + } + + // 设置tabBar选中状态为"发现"(索引0) + if (typeof this.getTabBar === 'function' && this.getTabBar()) { + this.getTabBar().setData({ + selected: 0 + }); + } + + if (app.globalData && app.globalData.needOpenLocationFavoriteBar) { + setTimeout(() => { + this.onOpenLocationFavoriteBar(); + }, 300); + app.globalData.needOpenLocationFavoriteBar = false; + } + }, + + onHide() { + this.stopLocationService(); + wx.hideLoading(); + }, + + onUnload() { + + this.stopLocationService(); + }, + + // 初始化高德地图SDK + initAMapSDK() { + try { + + // 使用完整版本的高德地图SDK,包含逆地理编码功能 + this.amapFun = new AMapWX({ + key: config.amapKey || '' // 需要有效的API Key才能使用全部功能 + }); + + this.setData({ + amapReady: true, + amapError: null + }); + + console.debug('✅ 高德地图SDK初始化成功'); + } catch (error) { + console.error('❌ 高德地图SDK初始化失败:', error); + + this.setData({ + amapReady: false, + amapError: error.message || '高德地图SDK初始化失败' + }); + + wx.showToast({ + title: '定位服务异常', + icon: 'none' + }); + } + }, + + // 初始化系统信息 + initSystemInfo() { + try { + const systemInfo = this.systemInfoHelper.getSystemInfoSync(); + const menuButtonInfo = wx.getMenuButtonBoundingClientRect(); + + const statusBarHeight = systemInfo.statusBarHeight || 44; + const menuButtonHeight = menuButtonInfo.height || 32; + const menuButtonTop = menuButtonInfo.top || statusBarHeight + 6; + const navBarHeight = statusBarHeight + menuButtonHeight + 10; + + this.setData({ + statusBarHeight: statusBarHeight, + menuButtonHeight: menuButtonHeight, + navBarHeight: navBarHeight, + windowHeight: systemInfo.windowHeight || 667, + safeAreaBottom: systemInfo.safeArea ? systemInfo.windowHeight - systemInfo.safeArea.bottom : 0 + }); + + } catch (error) { + console.error('获取系统信息失败:', error); + // 设置默认值 + this.setData({ + statusBarHeight: 44, + menuButtonHeight: 32, + menuButtonTop: 50, + navBarHeight: 88, + windowHeight: 667, + safeAreaBottom: 0 + }); + } + }, + + + // 请求位置权限 + requestLocationPermission() { + // 直接尝试获取位置,如果失败会自动触发权限请求 + this.getCurrentLocation(); + }, + + // 获取当前位置 - 双保险定位策略 + getCurrentLocation() { + if (!this.data.amapReady) { + this.getWxLocation(); // 降级方案 + return; + } + + this.amapFun.getWxLocation((location, error) => { + if (error) { + console.error('高德SDK获取位置失败:', error); + this.getWxLocation(); // 降级方案 + return; + } + + this.processLocationResult(location); + }, { + type: 'gcj02', + isHighAccuracy: true, + highAccuracyExpireTime: 4000 + }); + }, + + // 微信原生定位降级方案 + getWxLocation() { + wx.getLocation({ + type: 'gcj02', + isHighAccuracy: true, + highAccuracyExpireTime: 4000, + success: (location) => { + // 模拟高德地图数据格式,但不直接显示坐标 + const enhancedLocation = { + ...location, + address: '定位中...', // 使用友好的占位符 + formattedAddress: '', + province: '', + city: '', + district: '', + street: '' + }; + + this.processLocationResult(enhancedLocation); + + + }, + fail: (error) => { + console.error('微信原生定位也失败:', error); + this.handleLocationError(error); + } + }); + }, + + + + + // 🔥 新增:基于坐标的简化位置推断 - 修复版 + getLocationByCoordinates(latitude, longitude) { + + const lat = parseFloat(latitude); + const lng = parseFloat(longitude); + + let province = ''; + let city = ''; + let district = ''; + + // 基于经纬度范围的简化位置推断 + // 实际项目中可能需要调用专业的地理编码API或后端服务 + + // 北京地区 + if (lat >= 39.4 && lat <= 41.6 && lng >= 115.4 && lng <= 117.5) { + province = '北京'; + city = '北京市'; + district = '朝阳区'; + } + // 上海地区 + else if (lat >= 30.6 && lat <= 31.8 && lng >= 121.2 && lng <= 122.1) { + province = '上海'; + city = '上海市'; + district = '浦东新区'; + } + // 广州地区 + else if (lat >= 22.5 && lat <= 23.5 && lng >= 112.9 && lng <= 114.3) { + province = '广东'; + city = '广州市'; + district = '天河区'; + } + // 深圳地区 + else if (lat >= 22.4 && lat <= 22.8 && lng >= 113.7 && lng <= 114.6) { + province = '广东'; + city = '深圳市'; + district = '南山区'; + } + // 更多城市的判断(可以根据实际需求添加更多城市) + // 杭州地区 + else if (lat >= 29.0 && lat <= 30.5 && lng >= 118.0 && lng <= 120.0) { + province = '浙江'; + city = '杭州市'; + district = '西湖区'; + } + // 南京地区 + else if (lat >= 31.0 && lat <= 33.0 && lng >= 117.0 && lng <= 119.0) { + province = '江苏'; + city = '南京市'; + district = '玄武区'; + } + // 成都地区 + else if (lat >= 30.0 && lat <= 31.5 && lng >= 103.5 && lng <= 104.5) { + province = '四川'; + city = '成都市'; + district = '锦江区'; + } + // 其他地区 - 使用通用位置信息 + else { + // 改进:为了更好的用户体验,不再使用'地图'作为默认区域 + // 而是根据经纬度范围提供一个更有意义的默认位置 + const latInt = Math.round(lat); + const lngInt = Math.round(lng); + + // 使用经纬度整数部分作为位置标识,让用户知道这是一个估算的位置 + district = `${latInt}°${lngInt}°附近`; + city = '中国'; + province = '位置'; + } + + const address = province && city ? `${province}${city}${district}` : `${district}`; + + return { + province, + city, + district, + address + }; + }, + + // 处理位置结果 + processLocationResult(location) { + console.log('✅ 获取到经纬度: lat: ' + location.latitude + " long: " + location.longitude); + // 保存自己的位置信息 + const myLocation = { + latitude: location.latitude, + longitude: location.longitude, + accuracy: location.accuracy || 0 + }; + this.setData({ + myLocation: myLocation + }) + + const previousLocation = this.lastLocationSnapshot; + this.lastLocationSnapshot = myLocation; + + // 保存位置精度;仅在需要跟随或尚未初始化时更新地图中心 + const locationUpdate = { + accuracy: location.accuracy || 0, + myLocation: myLocation + }; + + const hasInitialCenter = typeof this.data.latitude === 'number' && typeof this.data.longitude === 'number' && + !Number.isNaN(this.data.latitude) && !Number.isNaN(this.data.longitude) && + this.data.latitude !== 0 && this.data.longitude !== 0; + + if (this.data.shouldFollowLocation || !hasInitialCenter) { + locationUpdate.latitude = location.latitude; + locationUpdate.longitude = location.longitude; + } + + this.setData(locationUpdate); + + // 创建用户位置标记(带头像和电量信息) + this.createUserMarkers(myLocation); + + // 只有在shouldFollowLocation为true时才移动地图 + if (this.mapCtx && this.data.shouldFollowLocation) { + try { + this.setData({ + shouldFollowLocation: false + }); + this.mapCtx.moveToLocation({ + latitude: location.latitude, + longitude: location.longitude, + success: () => { + console.debug('✅ 地图移动到当前位置成功'); + }, + fail: (error) => { + console.error('❌ 地图移动失败:', error); + } + }); + } catch (error) { + console.error('❌ 移动地图到当前位置时出现异常:', error); + } + } + + // 解析地址 - 使用Promise处理异步结果 + this.resolveAddress(location).then(() => { + // 地址解析完成后继续执行其他操作 + console.debug('✅ 地址解析完成,继续执行其他操作'); + }).catch((error) => { + console.error('⚠️ 地址解析过程中出现错误,但继续执行其他操作:', error); + }); + + // 加载好友位置 + const now = Date.now(); + if (!this.lastFriendsFetch || (now - this.lastFriendsFetch) > 45 * 1000) { + this.lastFriendsFetch = now; + if (!this.data.mapFeedVisible && !this.data.isOnline) { + this.loadFriendsLocation(); + } + } + + + // 获取附近用户 - 已启用 + if (!this.lastNearbyFetch || (now - this.lastNearbyFetch) > 45 * 1000) { + if (this.data.isOnline && !this.data.mapFeedVisible) { + this.lastNearbyFetch = now; + this.loadNearbyUsers(); + } + } + + this.scheduleMapFeedRefresh('location'); + }, + + // 创建用户位置标记(带头像和电量信息) + createUserMarkers(myLocation) { + // 安全地获取头像URL,处理 userInfo 可能为 null 的情况 + let avatarUrl = '/images/default-stranger.png'; // 默认头像 + if (app.globalData.userInfo && app.globalData.userInfo.user && app.globalData.userInfo.user.avatar) { + avatarUrl = app.globalData.userInfo.user.avatar; + } + if (avatarUrl.includes('myqcloud')) { + avatarUrl = avatarUrl + '?imageMogr2/auto-orient/thumbnail/100x100/quality/85'; + } + console.log("userInfoUrl--->" + avatarUrl); + let userMarkers = []; + const userMarker = { + id: 1, + latitude: myLocation.latitude, + longitude: myLocation.longitude, + iconPath: '/images/map/marker_blank.png', + avatarUrl: avatarUrl ? avatarUrl : '/images/default-stranger.png', + directionPath: '/images/map/direction_arrow.png', + type: 'mine', + directonAngle: this.data.directonAngle, + joinCluster: false, + title: "我", + height: 45, + width: 45, + customCallout: { + anchorX: 0, // 水平锚点设为 0.5(图标宽度的正中间) + anchorY: 70, // 垂直锚点设为 1(图标底部,紧贴地图坐标点) + display: 'ALWAYS' + }, + zIndex: 1 + } + + // this.data.allMarkers.push(userMarker); + + const existingIndex = this.data.allMarkers.findIndex(marker => marker.id === 1); + if (existingIndex == -1) { + this.data.allMarkers.push(userMarker); + } + userMarkers.push(userMarker); + this.updateMarkersByMarkersType(userMarkers); + }, + + + // 解析地址 - 多级解析策略 + async resolveAddress(location) { + console.log('🏠 处理地址信息,location数据:', location); + + let address = '未知位置'; + let addressDetail = {}; + let currentDistrict = ''; + let currentCity = ''; + let realLocationInfo = {}; + // 优先尝试获取真实位置信息(无论登录状态) + try { + realLocationInfo = await this.tryGetRealLocationInfo(location.latitude, location.longitude); + } catch (error) { + console.error('⚠️ 获取真实位置信息失败:', error); + } + + + if (realLocationInfo) { + address = realLocationInfo.address || address; + currentDistrict = realLocationInfo.district || currentDistrict; + // 不设置currentCity,只使用区级信息 + console.log('✅ 使用真实位置信息:', { + address, + currentDistrict + }); + } else { + // 从高德地图定位结果中获取地址信息 + if (location.address && location.address.trim()) { + address = location.address; + console.debug('✅ 使用高德地图返回的地址:', address); + } else if (location.formattedAddress && location.formattedAddress.trim()) { + address = location.formattedAddress; + console.debug('✅ 使用格式化地址:', address); + } else { + // 降级处理:使用坐标作为地址 + address = `位置: ${location.latitude.toFixed(6)}, ${location.longitude.toFixed(6)}`; + console.debug('⚠️ 降级使用坐标作为地址:', address); + } + } + + // 优先使用SDK返回的结构化地址 + if (location.province || location.city || location.district) { + addressDetail = { + province: location.province || '', + city: location.city || '', + district: location.district || '', + street: location.street || '', + streetNumber: location.streetNumber || '', + description: location.description || address + }; + + currentDistrict = location.district || ''; + // 不设置currentCity,只使用区级信息 + + } + + // 如果SDK没有返回结构化信息,从完整地址字符串中智能解析 + if (!currentDistrict && !currentCity && address) { + + // 智能解析中国地址格式的正则表达式 + const addressPattern = /(.*?)省?(.*?)市?(.*?)区?(.*?)县?(.*?)镇?(.*?)乡?(.*)/; + const match = address.match(addressPattern); + + if (match) { + const [, province, city, district] = match; + // 不设置currentCity,只使用区级信息 + currentDistrict = district; + console.debug('📍 正则解析结果:', { + province, + district: currentDistrict + }); + } + } + + // 降级处理:如果以上方法都失败,提取地址前几个字符作为区域显示 + if (!currentDistrict && !currentCity && address) { + // 最后的降级方案:使用地址的前几个字符 + currentDistrict = address.substring(0, 4) || '定位中...'; + console.debug('📍 降级使用地址前缀:', currentDistrict); + } + + console.debug('📍 最终解析的区域信息:', { + address, + currentDistrict, + currentCity, + locationData: location + }); + + this.setData({ + currentAddress: address, + addressDetail: addressDetail, + currentDistrict: currentDistrict, + currentCity: '' // 不显示城市信息,只显示区级信息 + }); + + if (!this.lastWeatherFetch || (Date.now() - this.lastWeatherFetch) > 30 * 60 * 1000) { + this.lastWeatherFetch = Date.now(); + this.loadWeatherInfo(location.latitude, location.longitude); + } + + // 更新位置信息到服务器 + this.updateLocationToServer({ + ...location, + address: address, + addressDetail: addressDetail + }); + }, + + // 更新位置到服务器 - 尝试从响应中获取地址信息 + async updateLocationToServer(locationData) { + try { + // 🔥 添加登录状态检查 + const app = getApp(); + const isLoggedIn = app?.globalData?.isLoggedIn || false; + + if (!isLoggedIn) { + + // 未登录状态下,使用设备直接返回的地址信息(如果有) + if (locationData.address) { + this.setData({ + currentDistrict: locationData.address, + locationLoading: false + }); + } + return { + success: false, + error: '用户未登录', + skipAuth: true + }; + } + + const systemInfo = this.systemInfoHelper.getSystemInfoSync(); + + const updateData = { + latitude: parseFloat(locationData.latitude), + longitude: parseFloat(locationData.longitude), + altitude: parseFloat(locationData.altitude) || 0, + accuracy: parseFloat(locationData.accuracy) || 0, + speed: parseFloat(locationData.speed) || 0, + direction: parseFloat(locationData.direction) || 0, + deviceType: 'miniprogram', + deviceModel: systemInfo.model || 'Unknown', + battery: systemInfo.battery || 100 + }; + console.log('✅ 上传的经纬度:', ' latitude ' + locationData.latitude + ' longitude ' + locationData.longitude); + const response = await this.apiClient.updateLocation(updateData); + console.log('✅ 位置更新成功,服务器响应:', response); + + // 🔥 优化:从服务器响应中获取准确的地址信息 + if (response && response.data) { + const serverData = response.data; + + // 检查服务器是否返回了地址信息 + if (serverData.address || serverData.district || serverData.city || serverData.province) { + + // 服务器位置信息是基于坐标查询的,比本地解析更准确 + // 对于登录用户,始终优先使用服务器返回的地址信息 + if (isLoggedIn) { + const newDistrict = serverData.district || serverData.city || this.data.currentDistrict; + const newAddress = serverData.address || this.data.currentAddress; + + this.setData({ + // currentDistrict: newDistrict, + currentCity: '', // 不显示城市信息,只使用区级信息 + currentAddress: newAddress + }); + + console.debug('✅ 已使用位置更新接口的地址信息更新左上角显示:', { + district: newDistrict, + address: newAddress + }); + } + // 对于未登录用户,如果当前区域信息不准确或缺失,优先使用服务器信息 + else if (!this.data.currentDistrict || + this.data.currentDistrict === '定位中...' || + this.data.currentDistrict === '位置信息' || + this.data.currentDistrict.includes('位置 ')) { + + const newDistrict = serverData.district || serverData.city || this.data.currentDistrict; + const newAddress = serverData.address || this.data.currentAddress; + + this.setData({ + // currentDistrict: newDistrict, + currentCity: '', // 不显示城市信息,只使用区级信息 + currentAddress: newAddress + }); + } + } + } + + } catch (error) { + console.error('❌ 位置更新失败:', error); + // 不阻断用户体验,仅记录错误 + } + }, + + // 处理位置错误 + handleLocationError(error) { + console.error('位置服务错误:', error); + + let errorMessage = '获取位置失败'; + + if (error.errMsg) { + if (error.errMsg.includes('auth deny')) { + errorMessage = '位置权限被拒绝,请在设置中开启位置权限'; + } else if (error.errMsg.includes('timeout')) { + errorMessage = '定位超时,请检查网络连接'; + } else if (error.errMsg.includes('locate fail')) { + errorMessage = '定位失败,请稍后重试'; + } + } + + wx.showToast({ + title: errorMessage, + icon: 'none', + duration: 3000 + }); + + // 设置默认位置(如果有的话) + if (this.data.defaultLocation) { + this.setData({ + longitude: this.data.defaultLocation.longitude, + latitude: this.data.defaultLocation.latitude, + currentAddress: this.data.defaultLocation.address || '位置获取失败' + }); + } + }, + + // 启动位置更新服务 - 增强版:实时位置更新 + startLocationService() { + + // 清除旧的定时器 + if (this.locationTimer) { + clearInterval(this.locationTimer); + } + + // if (!this.data.hasUserInteractedWithMap) { + // this.setData({ + // shouldFollowLocation: false + // }); + // } + + // 立即更新一次位置 + if (this.data.amapReady) { + this.getCurrentLocation(); + } + + const refreshInterval = config?.locationUpdateInterval || 30000; + + this.locationTimer = setInterval(() => { + if (this.data.amapReady) { + this.getCurrentLocation(); + } + }, refreshInterval); + }, + + // 停止位置更新服务 + stopLocationService() { + if (this.locationTimer) { + clearInterval(this.locationTimer); + this.locationTimer = null; + + } + }, + + // 计算两点之间的距离(米) + calculateDistance(lat1, lng1, lat2, lng2) { + const R = 6371000; // 地球半径(米) + const dLat = (lat2 - lat1) * Math.PI / 180; + const dLng = (lng2 - lng1) * Math.PI / 180; + const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * + Math.sin(dLng / 2) * Math.sin(dLng / 2); + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + return R * c; + }, + + // 格式化距离显示 + formatDistance(distance) { + if (distance < 1000) { + return Math.round(distance) + 'm'; + } else if (distance < 10000) { + return (distance / 1000).toFixed(1) + 'km'; + } else { + return Math.round(distance / 1000) + 'km'; + } + }, + + // 加载好友位置 + async loadFriendsLocation() { + try { + console.debug('👥 开始加载好友位置'); + // const response = await this.apiClient.getFriendsLocation(); + const [region, scaleResult] = await Promise.all([ + this.getMapRegion(), + this.getMapScale() + ]); + + let scale = Math.round(scaleResult?.scale || this.data.scale || 13); + const payload = buildBoundsPayload(region); + if (scale > 20) { + scale = 20; + } + const friendsAndStrangerSprams = { + "bounds": payload.bounds, + "zoomLevel": scale, + "displayMode": "friends", + // "maxPoints": 200, + // "clusterThreshold": 100, + // "onlineMode": "all", + "showOffline": true, + "clusterThreshold": this.data.clusterThreshold, + // "genderFilter": 0, + // "ageRangeMin": 18, + // "ageRangeMax": 35, + // "memberOnly": false, + // "enableRealTimeUpdate": false, + // "currentLat": this.data.myLocation.latitude, + // "currentLng": this.data.myLocation.longitude + } + let response = await this.apiClient.getFriendsAndStranger(friendsAndStrangerSprams); + + // 处理API响应数据结构 + + if (response && response.code === 0 && response.data) { + if (!this.data.mapFeedVisible && !this.data.isOnline) { + + // if (scale > 8) { + // response = mockResponseFriend + // } else { + // response = mockResponseFriendMarkerCluster; + // } + + this.addFriendsMarkersByResult(response.data); + this.setData({ + friendsData: response.data.userPoints + }); + + } + // 只保存数据,不直接操作markers数组 + // this.setData({ + // friendsData: friendsLocation, + // friendsCount: friendsLocation.length + // }); + // 调用统一的标记管理函数来更新地图标记 + } else { + console.debug('📍 暂无好友位置信息'); + this.setData({ + friendsCount: 0, + friendsData: [] + }); + // 调用统一的标记管理函数来更新地图标记 + } + } catch (error) { + console.error('❌ 加载好友位置失败:', error); + // this.setData({ + // friendsCount: 0, + // friendsData: [] + // }); + + // 调用统一的标记管理函数来更新地图标记 + // 只对已登录用户显示友好的错误提示 + const app = getApp(); + const isLoggedIn = app?.globalData?.isLoggedIn || false; + // if (isLoggedIn && error.message && !error.message.includes('401')) { + // wx.showToast({ + // title: '好友位置加载失败', + // icon: 'none', + // duration: 2000 + // }); + // } + } + }, + + + // 回到自己位置 - 定位按钮功能 + centerToUserLocation() { + if (!this.data.myLocation) { + this.getCurrentLocation(); + return; + } + // 设置为跟随用户位置,并重置交互标记 + this.setData({ + shouldFollowLocation: false, + hasUserInteractedWithMap: false + }); + + // 移动地图到自己的位置 + this.mapCtx.moveToLocation({ + latitude: this.data.myLocation.latitude, + longitude: this.data.myLocation.longitude + }); + + // 重置缩放级别到合适的级别 + this.setData({ + latitude: this.data.myLocation.latitude, + longitude: this.data.myLocation.longitude, + currentMapScale: 16 + }); + + // 获取地图上下文(关键:确保能拿到实时缩放级别) + this.mapCtx = wx.createMapContext('main-map') + // 初始化计算 + let that = this; + setTimeout(() => { + that.updateScale() + }, 1000) + + }, + + //收藏地址 + async onPoiFavoriteCommon(address, latitude, longitude, name) { + wx.request({ + url: `${config.api.baseUrl}/api/v1/location/place-mark`, + method: 'POST', + data: JSON.stringify({ + "name": name, + "category": "home", // "home" | "work" | "favorite" | "other" + "icon": "home_icon", + "latitude": latitude, + "longitude": longitude, + "address": address, + "description": "温馨的家", + "isPrivate": true, + "reminder": false + }), + header: { + 'Authorization': `Bearer ${apiClient.getToken()}`, + 'Content-Type': 'application/json', + }, + success: (res) => { + if (res.data.code === 0) { + this.setData({ + placeMarkId: res.data.data.placeMarkId, + mapClickCollect: '取消收藏' + }); + + wx.showToast({ + title: '已收藏', + icon: 'success' + }); + } else { + wx.showToast({ + title: '收藏失败', + icon: 'success' + }); + } + }, + fail: () => { + wx.showToast({ + title: '收藏失败,请重试', + icon: 'none' + }); + } + }); + }, + + + //取消收藏 + async onPoiCancelCommon(placeMarkId) { + wx.request({ + url: `${config.api.baseUrl}/api/v1/location/place-mark/${placeMarkId}`, + method: 'DELETE', + header: { + 'Authorization': `Bearer ${apiClient.getToken()}`, + 'Content-Type': 'application/json', + }, + success: (res) => { + if (res.data.code === 0) { + this.setData({ + placeMarkId: "", + mapClickCollect: "收藏" + }); + wx.showToast({ + title: '取消收藏成功', + icon: 'success' + }); + } else { + wx.showToast({ + title: '取消收藏失败', + icon: 'success' + }); + } + }, + fail: () => { + wx.showToast({ + title: '取消收藏失败,请重试', + icon: 'none' + }); + } + }); + }, + + + + //收藏地址 + async onPoiFavorite(e) { + const address = e.currentTarget.dataset.poidetail.address; + const latitude = e.currentTarget.dataset.poidetail.latitude; + const longitude = e.currentTarget.dataset.poidetail.longitude; + const name = e.currentTarget.dataset.poidetail.name; + if (this.data.placeMarkId == '') { //空 说明还没有收藏地址 + this.onPoiFavoriteCommon(address, latitude, longitude, name); + } else { //说明刚才收藏了 再点击就是取消 + this.onPoiCancelCommon(this.data.placeMarkId); + } + }, + + // 地图区域变化完成事件 + onMapRegionChange(e) { + // 无论缩放开始/进行中/结束,都强制更新(确保不遗漏) + + console.log("地图移动---->" + e.detail); + // this.addDynamicMarkersByResult(mockResponseDynamic.data); + + const type = e.causedBy; + if (type === 'scale') { //放大缩小 + this.updateScale() + } + const detail = e.detail || {}; + const changeType = e.type || 'unknown'; + // if (detail.causedBy !== 'update') { + + // } + + // 当地图被手动拖动时,停止跟随用户位置 + if (changeType === 'end' && (detail.causedBy === 'drag' || detail.causedBy === 'scale')) { + this.setData({ + shouldFollowLocation: false, + hasUserInteractedWithMap: true + }); + + } + + // 只在拖拽结束时处理,避免频繁触发 + if (changeType === 'end' && detail.scale) { + setTimeout(() => { + const currentScale = Math.round(detail.scale); + + + // this.setData({ + // currentMapScale: currentScale + // }); + + if (this.mapCtx && this.data.myLocation) { + try { + // 更新用户标记的位置 + // this.data.userMarker.latitude = this.data.myLocation.latitude; + // this.data.userMarker.longitude = this.data.myLocation.longitude; + + if (this.data.isOnline && !this.data.mapFeedVisible) { + this.loadNearbyUsers(); + } + + + if (!this.data.mapFeedVisible && !this.data.isOnline) { + this.loadFriendsLocation(); + } + + if (this.data.mapFeedVisible) { + this.scheduleMapFeedRefresh('location'); + } + + + } catch (error) { + console.error('⚠️ 地图区域变化后更新标记失败:', error); + } + } + }, 300); + + const isUserGesture = detail.causedBy === 'drag' || detail.causedBy === 'scale'; + if (isUserGesture) { + // this.scheduleMapFeedRefresh('region-change'); + } + } + }, + + + + + + // 地图点击事件 - 显示点击位置的POI资料卡 + onMapTap(e) { + // 点击地图时关闭用户详情卡片 + this.closeUserCard(); + this.hideFeedBubble(); + + // 获取点击位置的经纬度 + if (e && e.detail && e.detail.latitude && e.detail.longitude) { + // 相机移动到点击位置 + if (this.data.shouldFollowLocation) { + this.mapCtx && this.mapCtx.moveToLocation({ + latitude: e.detail.latitude, + longitude: e.detail.longitude + }); + } + } + }, + + // 地图长按事件 + onMapLongTap(e) { + // 只有在动态模式下才显示发布动态选项 + if (this.data.isOnline) { + // 保存当前长按位置 + const location = { + latitude: e.detail.latitude, + longitude: e.detail.longitude + }; + + this.setData({ + currentDynamicLocation: location, + showDynamicInputModal: true, + dynamicContent: '' + }); + } + // else { + // wx.showToast({ + // title: e && e.detail && e.detail.latitude && e.detail.longitude ? + // `长按:${e.detail.latitude.toFixed(6)},${e.detail.longitude.toFixed(6)}` : + // '长按地图操作', + // icon: 'none' + // }); + // } + }, + + // 关闭动态输入弹窗 + closeDynamicInputModal() { + this.setData({ + showDynamicInputModal: false, + dynamicContent: '' + }); + }, + + // 输入动态内容 + onDynamicContentInput(e) { + this.setData({ + dynamicContent: e.detail.value + }); + }, + + // 发布动态 + publishDynamic() { + const { + dynamicContent, + currentDynamicLocation + } = this.data; + + if (!dynamicContent.trim()) { + wx.showToast({ + title: '动态内容不能为空', + icon: 'none' + }); + return; + } + + if (!currentDynamicLocation) { + wx.showToast({ + title: '位置信息无效', + icon: 'none' + }); + return; + } + + // 创建新动态 + const newDynamic = { + id: Date.now(), // 使用时间戳作为唯一ID + content: dynamicContent.trim(), + latitude: currentDynamicLocation.latitude, + longitude: currentDynamicLocation.longitude, + creator: this.data.userInfo?.nickname || '匿名用户', + avatar: this.data.userInfo?.avatarUrl || '', + createTime: new Date().toISOString(), + likes: 0, + comments: [] + }; + + // 添加到动态列表 + const updatedDynamics = [...this.data.locationDynamics, newDynamic]; + + this.setData({ + locationDynamics: updatedDynamics, + showDynamicInputModal: false, + dynamicContent: '' + }); + + + wx.showToast({ + title: '动态发布成功', + icon: 'success' + }); + }, + + // 点击动态标记 + onDynamicMarkerTap(e) { + const markerId = e.detail.markerId; + + // 查找对应的动态 + const dynamic = this.data.locationDynamics.find(d => d.id === markerId); + + if (dynamic) { + this.setData({ + selectedDynamic: dynamic, + showDynamicDetailModal: true + }); + } + }, + + // 关闭动态详情弹窗 + closeDynamicDetailModal() { + this.setData({ + showDynamicDetailModal: false, + selectedDynamic: null + }); + }, + + onMarkerTap(e) { + const markerId = e.detail.markerId || e.markerId; + + if (markerId === 1) { + // 点击的是用户自己的位置 + return; + } + + const markers = this.data.markers || []; + const clickedMarker = markers.find(marker => String(marker.id) === String(markerId)); + const markerType = clickedMarker?.type || ''; + + + + // if (markerType === 'map-feed-cluster') { + // this.setData({ + // currentMapScale:18 + // }) + // this.toLocationByScale(18, clickedMarker.latitude, clickedMarker.longitude); + // return; + // } + + + if (markerType === 'stranger-cluster' || markerType === 'friend-cluster') { + this.setData({ + currentMapScale: 18 + }) + this.toLocationByScale(18, clickedMarker.latitude, clickedMarker.longitude); + return; + } + + if (markerType.startsWith('map-feed')) { + this.handleMapFeedMarkerTap(clickedMarker); + return; + } + + + if (markerType === 'staticData') { + this.hideFeedBubble(); + wx.showModal({ + title: clickedMarker?.title || '位置提示', + content: clickedMarker?.description || '暂无更多信息', + showCancel: false, + confirmText: '我知道了' + }); + return; + } + + if (markerType === 'merchant') { + this.hideFeedBubble(); + const merchantId = clickedMarker?.merchantId || (markerId >= 10000 ? markerId - 10000 : null); + const merchant = this.data.merchantList?.find(m => m.id === merchantId); + if (merchant) { + this.setData({ + selectedMerchant: merchant, + merchantInfoModalVisible: true, + activeMerchantId: merchantId + }); + // 更新markers中的active状态 + this.updateMerchantActiveState(merchantId); + } + return; + } + + if (markerType === 'dynamic') { + this.hideFeedBubble(); + const dynamic = this.data.locationDynamics.find(d => d.id === markerId); + if (dynamic) { + this.setData({ + selectedDynamic: dynamic, + showDynamicDetailModal: true + }); + } + return; + } + + + + if (markerType == 'friend-single') { + // 计算距离 + const myLocation = this.data.myLocation; + const distance = myLocation ? this.calculateDistance( + myLocation.latitude, myLocation.longitude, + clickedMarker.latitude, clickedMarker.longitude + ) : 0; + + this.setData({ + selectedUser: { + ...clickedMarker, + distance: distance > 0 ? this.formatDistance(distance) : '', + userId: clickedMarker.customId || clickedMarker.userId, + nickname: clickedMarker.nickname, + avatarUrl: clickedMarker.avatarUrl, + originAvatarUrl:clickedMarker.originAvatarUrl, + isFriend: true + } + }); + this.hideFeedBubble(); + + return; + } + if (markerType == 'stranger-single') { + if (clickedMarker) { + // 计算距离 + const myLocation = this.data.myLocation; + const distance = myLocation ? this.calculateDistance( + myLocation.latitude, myLocation.longitude, + clickedMarker.latitude, clickedMarker.longitude + ) : 0; + + this.setData({ + selectedUser: { + ...clickedMarker, + distance: distance > 0 ? this.formatDistance(distance) : '', + userId: clickedMarker.customId || clickedMarker.userId, + avatarUrl: clickedMarker.avatarUrl, + nickname: clickedMarker.nickname, + originAvatarUrl:clickedMarker.originAvatarUrl, + isFriend: false + } + }); + this.hideFeedBubble(); + + return; + } + } + }, + + toggleLike(){ + wx.showToast({ + title: '点赞成功', + icon: 'none' + }); + }, + + + // 地图POI点击事件 + onPoiTap(e) { + console.log('📍 POI点击事件:', e.detail); + let that = this; + const poi = { + name: e.detail.name, + address: '', + latitude: e.detail.latitude, + longitude: e.detail.longitude + }; + that.setData({ + poiDetail: poi, + renderKey: Date.now() + }) + + this.tryGetRealLocationInfo(e.detail.latitude, e.detail.longitude).then((realLocationInfo) => { + if (realLocationInfo) { + // 先重置数据,再重新赋值 + this.setData({ + poiDetailAddress: realLocationInfo.address, // 先清空 + poiDetailShow: true, + renderKey: Date.now() + }); + } + }); + + that.mapCtx && that.mapCtx.moveToLocation({ + latitude: poi.latitude, + longitude: poi.longitude, + success: () => { + // 地图移动完成后再设置数据,确保视图同步 + that.setData({ + latitude: poi.latitude, + longitude: poi.longitude, + currentMapScale: 17 + }); + } + }); + + // 获取地图上下文(关键:确保能拿到实时缩放级别) + that.mapCtx = wx.createMapContext('main-map') + setTimeout(() => { + that.updateScale() + }, 1000) + + that.setData({ + poiDetailShow: true + }); + + }, + + toLocationByScale(scale, lat, lon) { + let that = this; + this.mapCtx && this.mapCtx.moveToLocation({ + latitude: lat, + longitude: lon, + success: () => { + // 地图移动完成后再设置数据,确保视图同步 + that.setData({ + latitude: lat, + longitude: lon + }); + + if (scale != -1) { + setTimeout(() => { + that.updateScale() + }, 1000) + } + } + }); + + }, + + + + // 关闭POI详情卡片 + closePoiCard() { + this.setData({ + poiDetail: null, + poiDetailShow: false, + placeMarkId: '', + mapClickCollect: '收藏' + }); + }, + + // POI操作:导航 + onPoiNavigate() { + const poi = this.data.poiDetail; + if (!poi) { + wx.showToast({ + title: '无POI信息', + icon: 'none' + }); + return; + } + wx.openLocation({ + latitude: poi.latitude, + longitude: poi.longitude, + name: poi.name || '目标位置', + address: poi.address || '', + scale: 16 + }); + }, + + // POI操作:提醒 + onPoiRemind() { + // 关闭POI弹窗,打开提醒弹窗,初始化范围、好友、模式 + const poi = this.data.poiDetail; + this.setData({ + showPoiRemindModal: true, + poiRemindRadius: 300, + poiRemindSelectedFriends: [], + poiRemindMode: ['arrive'], // 多选 + showFriendSelectModal: false, + lastPoiForRemind: poi + }); + this.updatePoiRemindCircle(300); + if (poi) { + this.fitMapToCircle(poi.latitude, poi.longitude, 300); + } + }, + // 到达/离开提醒多选切换 + onPoiRemindModeChange(e) { + let values = e.detail.value; + if (!Array.isArray(values)) { + values = values ? [values] : []; + } + // 至少保留一个选项,若全取消则默认到达 + if (values.length === 0) { + values = ['arrive']; + } + this.setData({ + poiRemindMode: values + }); + }, + + // 切换好友选中状态 + onToggleFriendSelect(e) { + const userId = e.currentTarget.dataset.userid; + // 选满且未选中的不能再点 + if (this.data.poiRemindSelectedFriends.length >= 3 && !this.isFriendSelected(userId)) return; + let selected = this.data.poiRemindSelectedFriends.slice(); + const idx = selected.findIndex(f => f.userId === userId); + if (idx > -1) { + selected.splice(idx, 1); + } else { + if (selected.length >= 3) { + wx.showToast({ + title: '最多选择3位好友', + icon: 'none' + }); + return; + } + const friend = this.data.allFriendsList.find(f => f.userId === userId); + if (friend) selected.push(friend); + } + // 更新filteredFriendsList的selected字段 + const selectedIds = selected.map(f => f.userId); + const filteredFriendsList = this.data.filteredFriendsList.map(f => ({ + ...f, + selected: selectedIds.includes(f.userId) + })); + this.setData({ + poiRemindSelectedFriends: selected, + filteredFriendsList + }); + }, + + // 判断某个好友是否已被选中 + isFriendSelected(userId) { + return this.data.poiRemindSelectedFriends.some(f => f.userId === userId); + }, + + // 完成好友选择,关闭弹窗 + onFriendSelectDone() { + this.setData({ + showFriendSelectModal: false + }); + }, + + // 关闭弹窗 + onCloseFriendSelect() { + this.setData({ + showFriendSelectModal: false + }); + }, + + // 移除已选好友 + onRemoveSelectedFriend(e) { + const userId = e.currentTarget.dataset.userid; + let selected = this.data.poiRemindSelectedFriends.slice(); + const idx = selected.findIndex(f => f.userId === userId); + if (idx > -1) { + selected.splice(idx, 1); + // 更新filteredFriendsList的selected字段 + const selectedIds = selected.map(f => f.userId); + const filteredFriendsList = this.data.filteredFriendsList.map(f => ({ + ...f, + selected: selectedIds.includes(f.userId) + })); + this.setData({ + poiRemindSelectedFriends: selected, + filteredFriendsList + }); + } + }, + + // 关闭提醒弹窗 + closePoiRemindModal() { + this.setData({ + showPoiRemindModal: false + }); + this.updatePoiRemindCircle(0); // 隐藏圆圈 + }, + + // 拖动滑动条时更新范围和圆圈 + onPoiRemindRadiusChange(e) { + const radius = Number(e.detail.value); + this.setData({ + poiRemindRadius: radius + }); + this.updatePoiRemindCircle(radius); + // 地图相机包含提醒范围(自适应padding) + const poi = this.data.lastPoiForRemind; + if (poi) { + this.fitMapToCircle(poi.latitude, poi.longitude, radius); + } + }, + + // 更新地图上的圆圈覆盖物 + updatePoiRemindCircle(radius) { + const poi = this.data.poiDetail || this.data.lastPoiForRemind; + if (!poi || !radius) { + this.setData({ + circles: [] + }); + return; + } + this.setData({ + circles: [{ + latitude: poi.latitude, + longitude: poi.longitude, + color: '#667eea88', + fillColor: '#667eea22', + radius: radius, + strokeWidth: 2 + }], + lastPoiForRemind: poi + }); + }, + + // 刷新数据 + onRefresh() { + + wx.showToast({ + title: '刷新中...', + icon: 'loading', + duration: 1000 + }); + + // 重新获取位置和好友数据 + this.getCurrentLocation(); + + // 如果已有位置信息,直接刷新其他数据 + if (this.data.myLocation) { + this.loadWeatherInfo(this.data.myLocation.latitude, this.data.myLocation.longitude); + } + }, + + + + // 关闭用户详情卡片 + closeUserCard() { + this.setData({ + selectedUser: null + }); + }, + + // 开始聊天 + startChat(e) { + const userId = e.currentTarget.dataset.userid; + const niackName = e.currentTarget.dataset.nickname; + + // 获取当前用户信息 + const userInfo = this.data.userInfo; + if (!userInfo) { + wx.showToast({ + title: '用户信息错误', + icon: 'none' + }); + return; + } + + // 获取当前用户ID + const currentUserId = userInfo.user?.customId || userInfo.customId || ''; + if (!currentUserId) { + wx.showToast({ + title: '用户ID错误', + icon: 'none' + }); + return; + } + + // 构建会话ID(单聊格式) + // 🔥 修复:不传递conversationId,让聊天页面从API获取正确的会话ID + + // 跳转到聊天页面,使用正确的路径和参数格式 + + wx.navigateTo({ + url: `/pages/message/chat/chat?targetId=${userId}&name=${encodeURIComponent(niackName)}&chatType=0&sendMessage=${this.data.merchant}` + }); + + + }, + + // 添加好友 + addFriend(e) { + const userId = e.currentTarget.dataset.userid; + + // 实现添加好友逻辑 + wx.showModal({ + title: '添加好友', + content: '确定要添加这位用户为好友吗?', + success: (res) => { + if (res.confirm) { + // 调用添加好友API + this.performAddFriend(userId); + } + } + }); + }, + + // 执行添加好友 + async performAddFriend(userId) { + try { + const response = await this.apiClient.addFriend(userId, '通过地图添加'); + + if (response.code === 0) { + wx.showToast({ + title: '好友请求已发送', + icon: 'success' + }); + this.closeUserCard(); + } else { + throw new Error(response.message || '添加好友失败'); + } + } catch (error) { + console.error('添加好友失败:', error); + wx.showToast({ + title: error.message || '添加好友失败', + icon: 'none' + }); + } + }, + + // 查看用户资料 + viewProfile(e) { + const userId = e.currentTarget.dataset.userid; + + // 跳转到用户资料页面 + wx.navigateTo({ + url: `/pages/user-profile/user-profile?userId=${userId}` + }); + }, + + // 获取天气信息 + async loadWeatherInfo(latitude, longitude) { + try { + // 🔥 优化:优先使用第三方API获取天气信息,不依赖登录状态 + console.debug('🌤️ 开始获取天气信息'); + + // 1. 首先尝试通过腾讯地图API直接获取真实天气信息 + let weatherData = await this.tryGetRealWeatherInfo(latitude, longitude); + + // 2. 如果第三方API获取失败,再尝试调用服务器天气API + if (!weatherData) { + + const response = await this.apiClient.getWeatherInfo(latitude, longitude); + if (response && response.code === 0 && response.data) { + weatherData = response.data; + } else { + + } + } + + if (weatherData) { + + // 转换天气图标 + const weatherIcon = this.getWeatherIcon(weatherData.weather, weatherData.icon); + + // 判断是否为云彩图标 + const isCloudIcon = this.isCloudWeatherIcon(weatherData.weather, weatherData.icon, weatherIcon); + + const weatherInfo = { + temperature: Math.round(weatherData.temperature), + weather: weatherData.weather, + icon: weatherIcon, + isCloudIcon: isCloudIcon, + humidity: weatherData.humidity, + windSpeed: weatherData.windSpeed, + windDir: weatherData.windDir, + aqi: weatherData.aqi, + city: '', // 不显示城市信息,只使用区级信息 + updateTime: weatherData.updateTime + }; + + // 🔥 重要修复:使用天气接口返回的准确位置信息更新左上角显示 + if (weatherData.city) { + + // 天气接口返回的城市信息是最准确的(基于坐标查询的) + // 优先使用天气接口的位置信息更新左上角显示 + let newDistrict = this.data.currentDistrict; + + // 如果当前区域信息不准确或缺失,使用天气接口的城市信息 + if (!this.data.currentDistrict || + this.data.currentDistrict === '定位中...' || + this.data.currentDistrict === '位置信息' || + this.data.currentDistrict.includes('位置 ')) { + newDistrict = weatherData.city; + } + + // 更新区域显示信息 + this.setData({ + currentCity: '', // 不显示城市信息,只使用区级信息 + // currentDistrict: newDistrict, + weatherInfo: weatherInfo + }); + + } else { + // 没有城市信息时,只更新天气信息 + this.setData({ + weatherInfo: weatherInfo + }); + } + + console.debug('✅ 天气信息获取成功:', weatherInfo); + } else { + + // 提供默认天气信息 + await this.provideDefaultWeatherInfo(latitude, longitude); + } + } catch (error) { + console.error('❌ 获取天气信息失败:', error); + // 🔥 新增:提供默认天气信息,确保用户始终能看到天气数据 + await this.provideDefaultWeatherInfo(latitude, longitude); + } + }, + + // 提供默认天气信息 + async provideDefaultWeatherInfo(latitude, longitude) { + + // 尝试获取真实天气信息 + let defaultWeatherInfo = null; + + try { + // 尝试使用腾讯地图API的天气服务获取真实天气数据 + + const weatherResponse = await new Promise((resolve, reject) => { + wx.request({ + url: 'https://apis.map.qq.com/ws/weather/v1/', + data: { + location: `${latitude},${longitude}`, + key: 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77' + }, + success: resolve, + fail: reject + }); + }); + + // 处理天气API响应 + if (weatherResponse && weatherResponse.data && weatherResponse.data.status === 0 && weatherResponse.data.result) { + const weatherData = weatherResponse.data.result; + const currentWeather = weatherData.weather[0]; + + // 构建真实天气信息 + defaultWeatherInfo = { + temperature: parseInt(currentWeather.temp, 10), + weather: currentWeather.weather, + icon: this.getWeatherIcon(currentWeather.weather, ''), + isCloudIcon: this.isCloudWeatherIcon(currentWeather.weather, '', ''), + humidity: currentWeather.humidity, + windSpeed: currentWeather.wind.degree, + windDir: currentWeather.wind.direction, + aqi: weatherData.aqi, // 空气质量指数 + city: '', // 不显示城市信息,只使用区级信息 + updateTime: new Date().toLocaleTimeString() + }; + console.debug('✅ 成功获取真实天气信息:', defaultWeatherInfo); + } else { + console.warn('⚠️ 腾讯地图天气API返回数据异常'); + } + } catch (error) { + console.error('❌ 获取真实天气信息失败:', error); + } + + // 如果无法获取真实天气信息,才使用随机数据作为备选 + if (!defaultWeatherInfo) { + + const randomTemp = Math.floor(Math.random() * 20) + 15; // 15-35度 + const randomHumidity = Math.floor(Math.random() * 40) + 40; // 40-80% + const randomWindSpeed = Math.floor(Math.random() * 10) + 1; // 1-11级 + + const weatherConditions = ['晴', '多云', '阴', '小雨', '中雨', '大雨']; + const randomWeather = weatherConditions[Math.floor(Math.random() * weatherConditions.length)]; + + // 获取天气图标 + const weatherIcon = this.getWeatherIcon(randomWeather, ''); + const isCloudIcon = this.isCloudWeatherIcon(randomWeather, '', weatherIcon); + + // 构建默认天气信息 + defaultWeatherInfo = { + temperature: randomTemp, + weather: randomWeather, + icon: weatherIcon, + isCloudIcon: isCloudIcon, + humidity: randomHumidity, + windSpeed: randomWindSpeed, + windDir: '东北风', + aqi: 60, + city: '', // 不显示城市信息,只使用区级信息 + updateTime: new Date().toLocaleTimeString() + }; + } + + // 确保区域信息不为空 + let districtToShow = this.data.currentDistrict; + + // 先设置一个默认的占位文本,避免显示坐标 + if (!districtToShow || + districtToShow === '定位中...' || + districtToShow.includes('位置 ') || + districtToShow === '地图' || + districtToShow === '默认') { + // 立即设置一个友好的占位符,避免显示坐标 + this.setData({ + currentDistrict: '定位中...' + }); + } + + // 尝试通过API获取真实的地址信息,无论是否登录 + this.tryGetRealLocationInfo(latitude, longitude).then((realLocationInfo) => { + if (realLocationInfo && realLocationInfo.city) { + console.debug('✅ 成功获取真实地址信息:', realLocationInfo); + districtToShow = realLocationInfo.district || realLocationInfo.city; + } else { + + // 如果区域信息仍为空,使用坐标推断的位置 + if (!districtToShow || + districtToShow === '定位中...' || + districtToShow.includes('位置 ') || + districtToShow === '地图' || + districtToShow === '默认') { + // 或者尝试其他方式获取位置信息 + districtToShow = '北京市'; + } + } + + // 先设置天气信息 + this.setData({ + weatherInfo: defaultWeatherInfo + }); + + // 对于登录用户,保留从服务器获取的真实地址信息 + // 直接从全局获取登录状态,避免页面数据同步不及时的问题 + const app = getApp(); + const isLoggedIn = app?.globalData?.isLoggedIn || false; + + if (isLoggedIn && this.data.currentDistrict && + this.data.currentDistrict !== '定位中...' && + !this.data.currentDistrict.includes('位置 ') && + this.data.currentDistrict !== '地图' && + this.data.currentDistrict !== '默认') { + console.debug('✅ 登录用户,保留服务器返回的真实地址信息:', this.data.currentDistrict); + return; + } + + // 更新数据 + this.setData({ + currentCity: '' // 不显示城市信息,只显示区级信息 + // currentDistrict: districtToShow + }); + + console.debug('✅ 默认天气信息已提供:', defaultWeatherInfo); + }).catch((error) => { + console.error('❌ 获取真实地址信息失败:', error); + + // 如果区域信息仍为空,使用坐标推断的位置 + if (!districtToShow || + districtToShow === '定位中...' || + districtToShow.includes('位置 ') || + districtToShow === '地图' || + districtToShow === '默认') { + // 使用更具体的默认位置 + districtToShow = '北京市'; + // 不设置城市信息,只使用区级信息 + defaultWeatherInfo.city = ''; + } + + // 先设置天气信息 + this.setData({ + weatherInfo: defaultWeatherInfo + }); + + // 对于登录用户,保留从服务器获取的真实地址信息 + // 直接从全局获取登录状态,避免页面数据同步不及时的问题 + const app = getApp(); + const isLoggedIn = app?.globalData?.isLoggedIn || false; + + if (isLoggedIn && this.data.currentDistrict && + this.data.currentDistrict !== '定位中...' && + !this.data.currentDistrict.includes('位置 ') && + this.data.currentDistrict !== '地图' && + this.data.currentDistrict !== '默认') { + console.debug('✅ 登录用户,保留服务器返回的真实地址信息:', this.data.currentDistrict); + return; + } + + // 更新数据 + this.setData({ + currentCity: '', // 不显示城市信息,只使用区级信息 + // currentDistrict: districtToShow + }); + + }); + }, + + async tryGetRealWeatherInfo(latitude, longitude) { + return null; + }, + + // 尝试获取真实的位置信息 + tryGetRealLocationInfo(latitude, longitude) { + return new Promise((resolve, reject) => { + const key = config.amapKey; // 注意:需单独申请Web服务Key(与小程序Key不同) + wx.request({ + url: baseAmapUrl + `/geocode/regeo`, + data: { + location: `${longitude},${latitude}`, + key: key, + radius: 1000 + }, + success: (res) => { + if (res.data.status === '1') { + const addressComponent = res.data.regeocode.addressComponent; + const locationInfo = { + province: addressComponent.province || '', + city: addressComponent.city || '', + district: addressComponent.district || '', + address: res.data.regeocode.formatted_address || '' + }; + resolve(locationInfo); + } else { + reject(new Error('解析失败:' + res.data.info)); + } + }, + fail: reject + }); + }); + }, + + // 根据天气状况获取对应的表情符号 + getWeatherIcon(weather, iconCode) { + // 天气图标映射 + const weatherIcons = { + '晴': '☀️', + '多云': '⛅', + '阴': '☁️', + '小雨': '🌦️', + '中雨': '🌧️', + '大雨': '⛈️', + '雷雨': '⛈️', + '雪': '❄️', + '小雪': '🌨️', + '大雪': '❄️', + '雾': '🌫️', + '霾': '😷', + '沙尘': '🌪️' + }; + + // 根据iconCode映射 + const iconMapping = { + 'clear-day': '☀️', + 'clear-night': '🌙', + 'partly-cloudy-day': '⛅', + 'partly-cloudy-night': '☁️', + 'cloudy': '☁️', + 'rain': '🌧️', + 'sleet': '🌨️', + 'snow': '❄️', + 'wind': '💨', + 'fog': '🌫️' + }; + + let finalIcon = '🌤️'; + + // 优先使用iconCode映射,其次使用天气描述映射 + if (iconCode && iconMapping[iconCode]) { + finalIcon = iconMapping[iconCode]; + } else if (weather && weatherIcons[weather]) { + finalIcon = weatherIcons[weather]; + } + + return finalIcon; + }, + + // 判断是否为云彩相关图标(需要变成黑色) + isCloudWeatherIcon(weather, iconCode, icon) { + // 云彩相关的天气状况 + const cloudWeatherTypes = ['多云', '阴', '雾', '霾']; + + // 云彩相关的iconCode + const cloudIconCodes = ['partly-cloudy-day', 'partly-cloudy-night', 'cloudy', 'fog']; + + // 云彩相关的emoji + const cloudEmojis = ['⛅', '☁️', '🌫️']; + + // 检查各种条件 + if (weather && cloudWeatherTypes.includes(weather)) { + return true; + } + + if (iconCode && cloudIconCodes.includes(iconCode)) { + return true; + } + + if (icon && cloudEmojis.includes(icon)) { + return true; + } + + return false; + }, + + // 获取附近陌生人用户(新增功能) + async loadNearbyUsers() { + + try { + const myLocation = this.data.myLocation; + if (!myLocation) { + return; + } + console.debug('👥 开始获取附近用户'); + + const [region, scaleResult] = await Promise.all([ + this.getMapRegion(), + this.getMapScale() + ]); + + let scale = Math.round(scaleResult?.scale || this.data.scale || 13); + const payload = buildBoundsPayload(region); + if (scale > 20) { + scale = 20; + } + const friendsAndStrangerSprams = { + "bounds": payload.bounds, + "onlineMode": "all", + "zoomLevel": scale, + "displayMode": "strangers", + // "maxPoints": 200, + "clusterThreshold": this.data.clusterThreshold, + // "onlineMode": "all", + // "showOffline": true, + // "genderFilter": 0, + // "ageRangeMin": 18, + // "ageRangeMax": 35, + // "memberOnly": false, + // "enableRealTimeUpdate": false, + "currentLat": this.data.myLocation.latitude, + "currentLng": this.data.myLocation.longitude + } + let response = await this.apiClient.getFriendsAndStranger(friendsAndStrangerSprams); + + + if (response && response.code === 0 && response.data) { + if (this.data.isOnline && !this.data.mapFeedVisible) { + this.addStrangerMarkersByResult(response.data); + } + } else { + console.debug('📍 暂无附近用户'); + this.nearbyUsersData = []; + this.setData({ + strangersCount: 0 + }); + if (this.data.isOnline) { + // this.addStrangerMarkersData(); + } + } + } catch (error) { + console.error('❌ 获取附近用户失败:', error); + this.nearbyUsersData = []; + this.setData({ + strangersCount: 0 + }); + if (this.data.isOnline) { + // this.addStrangerMarkersData(); + } + } + }, + + //添加陌生人数据 + addStrangerMarkersByResult(responseStranger) { + const userPoints = responseStranger.userPoints || []; + const clusters = responseStranger.clusters || []; + this.clearMarkersByType("stranger-cluster"); + this.clearMarkersByType("stranger-single"); + + const strangerMarkers = userPoints.map((stranger, index) => { + // 为每个标记生成唯一id和随机经纬度偏移 + console.log("responseStranger--->single" + "lat--->" + stranger.latitude + "long--->" + stranger.longitude); + let avatarUrl = '/images/default-stranger.png'; + if (stranger.avatar) { + if (stranger.avatar.includes('myqcloud')) { + avatarUrl = stranger.avatar + '?imageMogr2/auto-orient/thumbnail/100x100/quality/85'; + } else { + avatarUrl = stranger.avatar + } + } + const marker = { + id: MAP_FEED_MARKER_STRANGER_ID + index, + // 基于基础坐标添加随机偏移(确保经纬度不同) + latitude: stranger.latitude, + longitude: stranger.longitude, + iconPath: marker_blank, + type: 'stranger-single', + customId: stranger.customId, + clusterColor: '#FF0000', + avatarUrl: avatarUrl, + originAvatarUrl: stranger.avatar, + merchantType: '', + isOnline: stranger.isOnline, + nickname: stranger.nickname, // 昵称加索引区分 + battery: 100, + width: 45, + height: 45, + radius: 380, + joinCluster: false, + title: stranger.nickname, + customCallout: { + anchorY: 50, + anchorX: 0, + display: 'ALWAYS' + }, + }; + return marker; + }); + + this.updateMarkersByMarkersType(strangerMarkers); + + const strangerClusterMarkers = clusters.map((stranger, index) => { + console.log("responseStranger--->cluster" + "lat--->" + stranger.latitude + "long--->" + stranger.longitude); + + const marker = { + // id: stranger.customId, + id: MAP_FEED_CLUSTER_STRANGER_ID + index, + latitude: stranger.latitude, + longitude: stranger.longitude, + iconPath: marker_blank, + feedCount: stranger.onlineCount, + customId: stranger.clusterId, + type: 'stranger-cluster', + badgeColor: MAP_FEED_MARKER_STYLE.stranger.background, + badgeTextColor: MAP_FEED_MARKER_STYLE.stranger.color, + battery: 100, + customCallout: { + anchorY: 50, + anchorX: 0, + display: 'ALWAYS' + }, + radius: 380, + width: 45, + height: 45, + }; + return marker; + }); + this.updateMarkersByMarkersType(strangerClusterMarkers); + }, + + + + //添加好友数据 + addFriendsMarkersByResult(responseStranger) { + const userPoints = responseStranger.userPoints || []; + const clusters = responseStranger.clusters || []; + // 生成100个经纬度不同的标记 + this.clearMarkersByType("friend-single"); + this.clearMarkersByType("friend-cluster"); + const friendMarkers = userPoints.map((stranger, index) => { + // 为每个标记生成唯一id和随机经纬度偏移 + let avatarUrl = '/images/default-stranger.png'; + if (stranger.avatar) { + if (stranger.avatar.includes('myqcloud')) { + avatarUrl = stranger.avatar + '?imageMogr2/auto-orient/thumbnail/100x100/quality/85'; + } else { + avatarUrl = stranger.avatar + } + } + const marker = { + // id: stranger.customId, + id: MAP_FEED_MARKER_FRIEND_ID + index, + // 基于基础坐标添加随机偏移(确保经纬度不同) + latitude: stranger.latitude, + longitude: stranger.longitude, + iconPath: marker_blank, + type: 'friend-single', + originAvatarUrl:stranger.avatar, + customId: stranger.customId, + clusterColor: '#FF0000', + avatarUrl: avatarUrl, + merchantType: '', + isOnline: stranger.isOnline, + nickname: stranger.nickname, // 昵称加索引区分 + battery: 100, + width: 45, + height: 45, + joinCluster: false, + title: stranger.nickname, + radius: 380, + customCallout: { + anchorY: 50, + anchorX: 0, + display: 'ALWAYS' + }, + }; + return marker; + }); + + this.updateMarkersByMarkersType(friendMarkers); + + const friendClusterMarkers = clusters.map((stranger, index) => { + // 为每个标记生成唯一id和随机经纬度偏移 + const marker = { + // id: stranger.customId, + id: MAP_FEED_CLUSTER_FRIEND_ID + index, + latitude: stranger.latitude, + longitude: stranger.longitude, + iconPath: marker_blank, + feedCount: stranger.onlineCount, + customId: stranger.clusterId, + type: 'friend-cluster', + badgeColor: MAP_FEED_MARKER_STYLE.stranger.background, + badgeTextColor: MAP_FEED_MARKER_STYLE.stranger.color, + battery: 100, + customCallout: { + anchorY: 50, + anchorX: 0, + display: 'ALWAYS' + }, + radius: 380, + width: 45, + height: 45, + }; + return marker; + }); + this.updateMarkersByMarkersType(friendClusterMarkers); + }, + + // 生成0.001到0.01之间的随机数(复用之前的方法) + getRandomNumber() { + const min = 0.001; + const max = 0.01; + return min + Math.random() * (max - min); + }, + + // 生成随机偏移量(可正负,扩大差异范围) + getRandomOffset() { + const min = -1.0; // 负偏移,扩大范围 + const max = 1.0; + return min + Math.random() * (max - min); + }, + + updateMarkersByMarkersType(toBeUpdateMarkers = []) { + if (toBeUpdateMarkers.length == 0) { + return; + } + + + // 验证标记点数据 + toBeUpdateMarkers.forEach((newMarker, index) => { + // 确保每个标记点都有必要的属性 + if (!newMarker.width || !newMarker.height) { + console.warn(`标记点 ${newMarker.id} 缺少尺寸属性,使用默认值`); + newMarker.width = newMarker.width || 45; + newMarker.height = newMarker.height || 45; + } + + if (!newMarker.id) { + console.error(`第 ${index} 个标记点缺少 id 属性`); + newMarker.id = Date.now() + index; // 生成临时 ID + } + }); + + // console.log('进入updateMarkers方法,参数:', JSON.stringify(toBeUpdateMarkers)); + // console.log('allMarkers:', JSON.stringify(this.data.allMarkers)); + let newMarkers = []; + newMarkers = this.data.allMarkers; + toBeUpdateMarkers.forEach(newMarker => { + // 查找是否已有相同id的marker + const existingIndex = this.data.allMarkers.findIndex(marker => marker.id === newMarker.id); + if (existingIndex > -1) { + // 存在:替换该位置的marker(更新所有属性) + // this.data.allMarkers[existingIndex] = newMarker; + newMarkers[existingIndex] = newMarker + } else { + // 不存在:添加到数组 + // this.data.allMarkers.push(newMarker); + newMarkers.push(newMarker); + } + }); + + console.log('最终显示的markers:', JSON.stringify(newMarkers)); + this.setData({ + allMarkers: newMarkers + }); + this.setData({ markers: [] }, () => { + this.setData({ markers: newMarkers }); + }); + }, + + + + + // 生成0.001到0.01之间的随机数(复用之前的方法) + getRandomNumber() { + const min = 0.001; + const max = 0.01; + return min + Math.random() * (max - min); + }, + + // 生成随机偏移量(可正负,扩大差异范围) + getRandomOffset() { + const min = -1.0; // 负偏移,扩大范围 + const max = 1.0; + return min + Math.random() * (max - min); + }, + + + + + + + + // 偶遇模式开关 + onDynamicToggle(e) { + + + if (this.data.mapFeedVisible) { + wx.showToast({ + title: '请先关闭动态', + icon: 'none', + duration: 1200 + }); + return; + } + + + this.setData({ + isOnline: !this.data.isOnline + }); + + + if (this.data.isOnline) { + this.clearMarkersByType("friend-single"); + this.clearMarkersByType("friend-cluster"); + this.loadNearbyUsers(); + this.setData({ + markers: this.data.allMarkers + }); + } else { + this.clearStranger(); + this.loadFriendsLocation() + } + }, + + //清除陌生人数据 + clearStranger() { + //关闭偶遇时 删除陌生人数据 + this.data.allMarkers = this.data.allMarkers.filter(item => { + // 返回 true 表示保留该元素,false 表示删除 + return item.type !== "stranger-single"; // 这里替换为你的判断条件 + }); + this.data.allMarkers = this.data.allMarkers.filter(item => { + // 返回 true 表示保留该元素,false 表示删除 + return item.type !== "stranger-cluster"; // 这里替换为你的判断条件 + }); + this.mapStrangerMarkerLookup.clear(); + this.setData({ + markers: this.data.allMarkers + }); + }, + + + clearMarkersByType(type) { + //关闭偶遇时 删除陌生人数据 + this.data.allMarkers = this.data.allMarkers.filter(item => { + // 返回 true 表示保留该元素,false 表示删除 + return item.type !== type; // 这里替换为你的判断条件 + }); + // this.setData({ + // markers: this.data.allMarkers + // }); + }, + + + //清除好友数据 + clearFriend() { + //关闭偶遇时 删除陌生人数据 + this.data.allMarkers = this.data.allMarkers.filter(item => { + // 返回 true 表示保留该元素,false 表示删除 + return item.type !== "friend-single"; // 这里替换为你的判断条件 + }); + this.data.allMarkers = this.data.allMarkers.filter(item => { + // 返回 true 表示保留该元素,false 表示删除 + return item.type !== "friend-cluster"; // 这里替换为你的判断条件 + }); + this.mapStrangerMarkerLookup.clear(); + this.setData({ + markers: this.data.allMarkers + }); + }, + + // 初始化静态数据 + initStaticData() { + // 模拟静态数据,实际项目中可能从API获取 + const staticData = [{ + id: 'static1', + title: '热门景点', + description: '游客推荐', + latitude: 44.897383746906186 + 0.005, + longitude: 82.07800276534772 + 0.005, + imageUrl: '/images/map/marker_lan.png' + }, + { + id: 'static2', + title: '美食推荐', + description: '当地特色', + latitude: 44.897383746906186 - 0.005, + longitude: 82.07800276534772 + 0.005, + imageUrl: '/images/map/marker_hong.png' + }, + { + id: 'static3', + title: '购物中心', + description: '购物天堂', + latitude: 44.897383746906186 + 0.005, + longitude: 82.07800276534772 - 0.005, + imageUrl: '/images/map/marker_yule.png' + } + ]; + + this.setData({ + staticDataMarkers: staticData + }); + + + }, + + // 初始化合作商家标记 + initMerchantMarkers() { + try { + // 获取所有商家数据 + const merchants = getAllMerchants(); + + // 将商家数据转换为marker格式 + const merchantMarkers = convertMerchantsToMarkers(merchants); + + // 保存商家列表到data中(用于点击事件查找) + this.setData({ + merchantList: merchants + }); + + // 将商家markers添加到地图 + if (merchantMarkers && merchantMarkers.length > 0) { + this.updateMarkersByMarkersType(merchantMarkers); + console.log('✅ 已加载', merchantMarkers.length, '个合作商家标记'); + } + } catch (error) { + console.error('❌ 初始化商家标记失败:', error); + } + }, + + scheduleMapFeedRefresh(trigger = 'auto') { + if (!this.mapCtx) { + return; + } + + if (!this.data.mapFeedVisible) { + if (this.mapFeedDebounceTimer) { + clearTimeout(this.mapFeedDebounceTimer); + this.mapFeedDebounceTimer = null; + } + return; + } + + + if (this.mapFeedDebounceTimer) { + clearTimeout(this.mapFeedDebounceTimer); + } + + this.mapFeedDebounceTimer = setTimeout(() => { + this.refreshMapFeeds(trigger); + }, MAP_FEED_DEBOUNCE); + }, + + async refreshMapFeeds(trigger = 'auto') { + if (!this.mapCtx || !this.apiClient) { + return; + } + + if (!this.data.mapFeedVisible) { + return; + } + + + if (!this.mapFeedCache) { + this.mapFeedCache = new Map(); + } + + try { + const [region, scaleResult] = await Promise.all([ + this.getMapRegion(), + this.getMapScale() + ]); + + const scale = scaleResult?.scale || this.data.scale || 13; + const preset = getFeedScalePreset(scale); + const payload = buildBoundsPayload(region); + + if (!payload) { + console.warn('⚠️ 地图区域数据无效,无法请求地图动态'); + return; + } + console.log("preset---->" + preset.mode); + console.log("scale---->" + scale); + if (preset.mode === 'nearby') { + payload.maxResults = 50; + } else { + payload.level = preset.level; + payload.maxResults = 80; + } + + const cacheKey = buildCacheKey(preset, payload); + const cachedEntry = this.mapFeedCache.get(cacheKey); + + + + this.setData({ + mapFeedLoading: true, + mapFeedError: '' + }); + + let response; + if (preset.mode === 'nearby') { + response = await this.apiClient.getMapFeedsNearby(payload); + } else { + response = await this.apiClient.getMapFeedsAdministrative(payload); + } + + if (!response || response.code !== 200 || !response.data) { + throw new Error(response?.message || '地图动态加载失败'); + + } + + + const isDataSame = JSON.stringify(this.data.cacheEntryString) === JSON.stringify(response.data); + this.setData({ + cacheEntryString: response.data + }); + this.mapFeedCache.set(cacheKey, { + data: response.data, + preset, + timestamp: Date.now() + }); + + + if (isDataSame) { + return; + } + if (preset.mode === 'nearby') { + this.addDynamicMarkersByResult(response.data); + } else { + this.addDynamicClusterByResult(response.data); + } + } catch (error) { + console.error('❌ 地图动态刷新失败:', error); + const errMsg = error?.errMsg || error?.message || ''; + const isTransient = errMsg.includes('getRegion') || errMsg.includes('getScale'); + + if (isTransient && this.data.mapFeedVisible) { + setTimeout(() => { + this.scheduleMapFeedRefresh('retry'); + }, 600); + } + + this.setData({ + mapFeedLoading: false, + mapFeedError: isTransient ? '' : (errMsg || '地图动态加载失败') + }); + } + }, + + cropImageToCenter(imagePath) { + return new Promise((resolve, reject) => { + const TARGET_CROP_W = 87; + const TARGET_CROP_H = 77; + const RADIUS = 10; + const SAFE_RADIUS = Math.min(RADIUS, TARGET_CROP_W / 2, TARGET_CROP_H / 2); + + if (typeof imagePath !== 'string' || !imagePath.trim()) { + return reject(new Error('图片路径不能为空')); + } + + wx.getImageInfo({ + src: imagePath, + success: (imgInfo) => { + const { width: ORI_W, height: ORI_H, path: ORI_LOCAL_PATH } = imgInfo; + + // 计算等比缩放比例 + const targetRatio = TARGET_CROP_W / TARGET_CROP_H; + const imageRatio = ORI_W / ORI_H; + + let scaledW, scaledH; + if (imageRatio > targetRatio) { + scaledH = TARGET_CROP_H; + scaledW = (ORI_W * TARGET_CROP_H) / ORI_H; + } else { + scaledW = TARGET_CROP_W; + scaledH = (ORI_H * TARGET_CROP_W) / ORI_W; + } + + // 计算裁剪中心点 + const centerX = (scaledW - TARGET_CROP_W) / 2; + const centerY = (scaledH - TARGET_CROP_H) / 2; + const cropX = Math.max(0, centerX); + const cropY = Math.max(0, centerY); + + const query = wx.createSelectorQuery(); + query.select('#cropCanvas') + .fields({ node: true, size: true }) + .exec((res) => { + if (!res[0] || !res[0].node) { + return reject(new Error('未找到Canvas画布')); + } + + const canvas = res[0].node; + const ctx = canvas.getContext('2d'); + const dpr = wx.getSystemInfoSync().pixelRatio; + + // 正确设置Canvas尺寸 + canvas.width = TARGET_CROP_W * dpr; + canvas.height = TARGET_CROP_H * dpr; + ctx.scale(dpr, dpr); + + ctx.imageSmoothingEnabled = true; + ctx.imageSmoothingQuality = 'high'; + + const image = canvas.createImage(); + image.src = ORI_LOCAL_PATH; + + image.onload = () => { + try { + ctx.clearRect(0, 0, TARGET_CROP_W, TARGET_CROP_H); + + // 创建圆角裁剪路径 + ctx.beginPath(); + this.createRoundedPath(ctx, 0, 0, TARGET_CROP_W, TARGET_CROP_H, SAFE_RADIUS); + ctx.clip(); + + // 绘制图片 + ctx.drawImage(image, -cropX, -cropY, scaledW, scaledH); + + // 导出图片 + wx.canvasToTempFilePath({ + canvas: canvas, + destWidth: TARGET_CROP_W * dpr, + destHeight: TARGET_CROP_H * dpr, + fileType: 'png', + quality: 1, + success: (res) => resolve(res.tempFilePath), + fail: (err) => reject(new Error(`导出失败:${err.errMsg}`)) + }); + } catch (e) { + reject(new Error(`绘制失败:${e.message}`)); + } + }; + + image.onerror = () => reject(new Error('图片加载失败')); + }); + }, + fail: (err) => reject(new Error(`获取图片信息失败:${err.errMsg}`)) + }); + }); + }, + + // 圆角路径创建函数 + createRoundedPath(ctx, x, y, width, height, radius) { + ctx.beginPath(); + ctx.moveTo(x + radius, y); + ctx.arcTo(x + width, y, x + width, y + height, radius); + ctx.arcTo(x + width, y + height, x, y + height, radius); + ctx.arcTo(x, y + height, x, y, radius); + ctx.arcTo(x, y, x + width, y, radius); + ctx.closePath(); + }, + + +/** + * 小程序版 - 动态添加Marker(保留你的原始逻辑,仅适配裁剪方法) + */ +async addDynamicMarkersByResult(responseStranger) { + console.log("responseStranger----->" + JSON.stringify(responseStranger)); + const userPoints = responseStranger.points || []; + const friendMarkers = userPoints.map(async (stranger, index) => { // 注意async + let thumbnail = "/images/findme-logo.png"; + let avatarUrl = ''; + + try { + if (stranger.thumbnail && stranger.thumbnail.includes('myqcloud')) { + // 清理腾讯云原有缩放参数(保留你的原始逻辑) + const cleanImageUrl = stranger.thumbnail.replace("thumbnail=300x300", ""); + // 调用小程序版裁剪方法 + thumbnail = await this.cropImageToCenter(stranger.thumbnail); + } else { + avatarUrl = stranger.thumbnail; // 保留你的原始逻辑 + } + + if (avatarUrl) { + thumbnail = marker_blank; // 保留你的原始逻辑(需确保marker_blank已定义) + } + } catch (error) { + // 裁剪失败兜底(保留你的原始逻辑) + console.error(`第${index}个marker裁剪失败:`, error); + thumbnail = "/images/findme-logo.png"; + } + + console.log("thumbnail-->" + thumbnail); + + // 保留你原始的marker结构,仅调整宽高为86/77 + const marker = { + id: Number(MAP_FEED_SINGLE_BASE_ID + index), // 需确保MAP_FEED_SINGLE_BASE_ID已定义 + latitude: stranger.location.latitude, + longitude: stranger.location.longitude, + iconPath: thumbnail ? thumbnail : "/images/findme-logo.png", + type: 'map-feed-single', + feedUuid: stranger.feedUuid, + likeCount: stranger.likeCount, + commentCount: stranger.commentCount, + clusterColor: '#FF0000', + avatarUrl: avatarUrl, + originalUrl: stranger.thumbnail ? stranger.thumbnail : "/images/findme-logo.png", + merchantType: '', + zIndex: 10, + battery: 100, + width: 87, // 裁剪宽度 + height: 77, // 裁剪高度 + imageLoaded: false, + radius: 380, + joinCluster: false, + customCallout: { + anchorY: 86, + anchorX: 0, + display: 'ALWAYS' + }, + }; + return marker; + }); + + // 等待所有marker异步处理完成 + const resolvedMarkers = await Promise.all(friendMarkers); + + // 保留你原始的清空/更新逻辑 + this.clearMarkersByType("map-feed-single"); + this.clearMarkersByType("map-feed-cluster"); + this.updateMarkersByMarkersType(resolvedMarkers); +}, + //添加区城市省级国家级动态数据 + addDynamicClusterByResult(responseStranger) { + const userPoints = responseStranger.userPoints || []; + const clusters = responseStranger.clusters || []; + const friendMarkers = userPoints.map((stranger, index) => { + // 为每个标记生成唯一id和随机经纬度偏移 + const marker = { + id: Number(MAP_FEED_SINGLE_BASE_ID + index), + // 基于基础坐标添加随机偏移(确保经纬度不同) + latitude: stranger.latitude, + longitude: stranger.longitude, + iconPath: marker_blank, + type: 'map-feed-single', + customId: stranger.customId, + clusterColor: '#FF0000', + avatarUrl: stranger.thumbnail ? stranger.thumbnail : '/images/findme-logo.png', + merchantType: '', + isOnline: stranger.isOnline, + nickname: stranger.nickname, // 昵称加索引区分 + battery: 100, + width: 45, + height: 45, + radius: 380, + joinCluster: false, + title: stranger.nickname, + customCallout: { + anchorY: 50, + anchorX: 0, + display: 'ALWAYS' + }, + }; + return marker; + }); + + this.updateMarkersByMarkersType(friendMarkers); + + const friendClusterMarkers = clusters.filter(stranger => stranger.count !== 1) // 过滤掉 count 为 1 的数据 + // const friendClusterMarkers = clusters // 过滤掉 count 为 1 的数据 + .map((stranger, index) => { + const marker = { + // id: stranger.customId, + id: Number(MAP_FEED_CLUSTER_BASE_ID + index), + latitude: stranger.location.latitude, + longitude: stranger.location.longitude, + iconPath: marker_blank, + feedCount: stranger.count, + customId: stranger.id, + type: 'map-feed-cluster', + badgeColor: MAP_FEED_MARKER_STYLE.cluster.background, + badgeTextColor: MAP_FEED_MARKER_STYLE.cluster.color, + battery: 100, + customCallout: { + anchorY: 50, + anchorX: 0, + display: 'ALWAYS' + }, + radius: 380, + width: 45, + height: 45, + }; + return marker; + }); + + // if (friendClusterMarkers.length > 0) { + this.clearMarkersByType("map-feed-single"); + this.clearMarkersByType("map-feed-cluster"); + // } + this.updateMarkersByMarkersType(friendClusterMarkers); + }, + + // 图片预览 + previewImage(e) { + try { + // 获取当前点击的图片索引和动态索引 + const originalurl = e.currentTarget.dataset.originalurl; + + // 优先使用原始图片URL或高质量图片,确保预览完整清晰的图片 + const imageUrls = [originalurl]; + // 🔥 设置标志,防止预览关闭后触发页面刷新 + this._skipNextOnShowReload = true; + console.log("originalurl--->"+imageUrls); + // 调用微信小程序的图片预览API + wx.previewImage({ + current: imageUrls[0], // 当前显示图片的URL + urls: imageUrls, // 需要预览的图片URL列表 + success: () => { + // 预览打开成功,标志已设置,关闭时会触发 onShow + }, + fail: (err) => { + console.error('图片预览失败:', err); + // 预览失败,清除标志 + this._skipNextOnShowReload = false; + wx.showToast({ + title: '预览图片失败', + icon: 'none' + }); + } + }); + } catch (error) { + console.error('图片预览过程中出错:', error); + // 出错时清除标志 + this._skipNextOnShowReload = false; + wx.showToast({ + title: '预览图片失败', + icon: 'none' + }); + } + }, + + // 触摸开始 + onTouchStart(e) { + this.setData({ + startY: e.touches[0].clientY, + isMoving: true + }); + }, + + // 触摸移动 + onTouchMove(e) { + if (!this.data.isMoving) return; + + const moveY = e.touches[0].clientY; + const diff = moveY - this.data.startY; + + // 只允许向下滑动 + if (diff > 0) { + this.setData({ + modalTranslateY: diff + }); + } + }, + + // 触摸结束 + onTouchEnd() { + // 滑动距离超过50px则关闭弹窗 + if (this.data.modalTranslateY > 50) { + if(this.data.searchResultNavigationVisible==true){ + this.handleHideBottmNavigation(); + this.setData({ + modalTranslateY: 0, + isMoving: false + }); + return; + } + + if(this.data.shareShareVisible==true){ + this.handleHideShareBottm(); + this.setData({ + modalTranslateY: 0, + isMoving: false + }); + return; + } + + if(this.data.searchResultInfoModalVisible==true){ + this.handleHideBottm(); + } + + } else { + // 否则复位 + this.setData({ + modalTranslateY: 0, + isMoving: false + }); + } + }, + + + + + //开启动态 + enableMapFeedView() { + this.closeUserCard(); + this.hideFeedBubble(); + this.setData({ + mapFeedVisible: true, + mapFeedError: '' + }, () => { + // 更新地图动态数据标记 + this.scheduleMapFeedRefresh('manual'); + }); + + wx.showToast({ + title: '已开启附近动态', + icon: 'none', + duration: 1200 + }); + }, + + disableMapFeedView(showToast = true) { + if (this.mapFeedDebounceTimer) { + clearTimeout(this.mapFeedDebounceTimer); + this.mapFeedDebounceTimer = null; + } + + this.hideFeedBubble(); + + if (this.mapFeedMarkerLookup) { + this.mapFeedMarkerLookup.clear(); + } + + this.setData({ + mapFeedVisible: false, + mapFeedMarkers: [], + mapFeedLoading: false, + mapFeedError: '' + }, () => { + this.data.allMarkers = this.data.allMarkers.filter(item => { + // 返回 true 表示保留该元素,false 表示删除 + return item.type !== "map-feed-single"; // 这里替换为你的判断条件 + }); + this.data.allMarkers = this.data.allMarkers.filter(item => { + // 返回 true 表示保留该元素,false 表示删除 + return item.type !== "map-feed-cluster"; // 这里替换为你的判断条件 + }); + this.setData({ + markers: this.data.allMarkers + }); + }); + + if (showToast) { + wx.showToast({ + title: '已关闭附近动态', + icon: 'none', + duration: 1200 + }); + } + }, + //关闭或开启动态 + toggleMapFeedView() { + + if (this.data.mapFeedVisible) { + this.disableMapFeedView(true); + if (this.data.isOnline) { + this.loadNearbyUsers(); + } + if (!this.data.isOnline) { + this.loadFriendsLocation(); + } + return; + } + + + if (!this.ensureLoggedInForAction()) { + return; + } + + this.clearStranger(); + this.clearFriend(); + + this.enableMapFeedView(); + }, + + showFeedBubble(bubble) { + this.setData({ + activeFeedBubble: bubble, + activeFeedBubbleLoading: false + }); + }, + + hideFeedBubble() { + this.setData({ + activeFeedBubble: null, + activeFeedBubbleSingle: null, + activeFeedBubbleLoading: false, + activeFeedSingleVisible: false + }); + }, + + async handleMapFeedMarkerTap(markerMeta) { + if (!markerMeta) { + return; + } + + // const markerMeta = this.mapFeedMarkerLookup?.get(marker.id); + // if (!markerMeta) { + // wx.showToast({ + // title: '内容已更新,请重试', + // icon: 'none' + // }); + // return; + // } + + if (markerMeta.type === 'map-feed-single') { + + let response = await this.apiClient.getFeedsDetail(markerMeta.feedUuid); + let nickName = ''; + let content = ''; + let avatar = ''; + if (response.data) { + nickName = response.data.user.nickname; + content = response.data.content; + avatar = response.data.user.avatar; + let formatted_time = this.formatCommentTime(response.data.createdAt); + const baseBubble = buildBubbleData({ + type: markerMeta.type, + title: markerMeta.payload?.name || '附近热力区', + nickname: nickName, + avatar: avatar, + content: content, + createdAt: formatted_time, + thumbnail: markerMeta.originalUrl, + location: markerMeta.location, + tone: 'sunset' + }); + this.setData({ + activeFeedBubbleSingle: baseBubble, + activeFeedSingleVisible: true + }); + } + + return; + } + + const radius = markerMeta.location?.radius || 320; + const countLabel = formatFeedCountLabel(markerMeta.payload?.count || 0); + const baseBubble = buildBubbleData({ + type: markerMeta.type, + title: markerMeta.payload?.name || '附近热力区', + // subtitle: markerMeta.payload?.count ? `含 ${countLabel}` : formatRadiusLabel(radius), + chip: countLabel, + // heat: formatHeatLabel(markerMeta.payload?.hotScore), + // thumbnail: resolveFeedThumbnail(markerMeta.payload), + feeds: markerMeta.feedCount, + location: markerMeta.location, + thumbnail: markerMeta.avatarUrl, + // radiusLabel: formatRadiusLabel(radius), + tone: 'sunset' + }); + + this.setData({ + activeFeedBubble: baseBubble, + activeFeedBubbleLoading: false + }); + // this.loadClusterPreview(markerMeta); + }, + + + + // 格式化评论时间 + formatCommentTime(timeStr) { + if (!timeStr) return ''; + + const commentTime = new Date(timeStr); + if (isNaN(commentTime.getTime())) return ''; + + const now = new Date(); + const diffMinutes = Math.floor((now - commentTime) / (1000 * 60)); + + // 5分钟内:显示"刚刚" + if (diffMinutes < 5) return '刚刚'; + + // 格式化日期时间 + const year = commentTime.getFullYear(); + const month = commentTime.getMonth() + 1; // 不加前导0,直接显示月份 + const day = commentTime.getDate(); + const hour = String(commentTime.getHours()).padStart(2, '0'); + const minute = String(commentTime.getMinutes()).padStart(2, '0'); + + // 当前年份:显示不带年份的日期和时间,例如:8月24日 17:11 + // 非当前年份:显示带年份的日期和时间,例如:2024年 8月24日 17:11 + const currentYear = now.getFullYear(); + return year === currentYear + ? `${month}月${day}日 ${hour}:${minute}` + : `${year}年 ${month}月${day}日 ${hour}:${minute}`; + }, + + async loadClusterPreview(markerMeta) { + if (!markerMeta || !markerMeta.payload) { + return; + } + + try { + this.setData({ + activeFeedBubbleLoading: true + }); + + const response = await this.apiClient.getMapClusterFeeds({ + location: { + latitude: Number(markerMeta.payload?.location?.latitude), + longitude: Number(markerMeta.payload?.location?.longitude) + }, + radius: 380, + limit: MAP_FEED_BUBBLE_LIMIT + }); + + if (!response || response.code !== 200) { + throw new Error(response?.message || '加载聚合动态失败'); + } + + const feeds = (response.data?.feeds || []).map((feed) => { + const likeCount = feed.interactions?.likeCount || 0; + const commentCount = feed.interactions?.commentCount || 0; + let description = '刚刚更新'; + if (likeCount > 0 || commentCount > 0) { + description = `👍 ${likeCount} · 💬 ${commentCount}`; + } + + return { + uuid: feed.uuid, + title: feed.location?.name || feed.user?.nickname || '附近动态', + description, + thumbnail: resolveFeedThumbnail({ + thumbnail: feed.media?.[0]?.thumbnailUrl || feed.media?.[0]?.url, + contentType: feed.type + }), + hotScore: feed.interactions?.likeCount || 0 + }; + }); + + const existingBubble = this.data.activeFeedBubble || {}; + const radius = existingBubble.radius || 320; + const clusterCount = markerMeta.payload?.count || feeds.length; + const countLabel = formatFeedCountLabel(clusterCount); + const bubble = buildBubbleData({ + type: markerMeta.type, + title: markerMeta.payload?.name || existingBubble.title || '附近热力区', + subtitle: markerMeta.payload?.count ? `含 ${countLabel}` : (existingBubble.subtitle || formatRadiusLabel(radius)), + chip: countLabel, + heat: formatHeatLabel(markerMeta.payload?.hotScore), + thumbnail: markerMeta.payload?.thumbnail || feeds[0]?.thumbnail || existingBubble.thumbnail, + feeds, + location: markerMeta.location, + radius, + radiusLabel: existingBubble.radiusLabel || formatRadiusLabel(radius), + tone: existingBubble.tone || 'sunset' + }); + + + + + this.showFeedBubble(bubble); + } catch (error) { + console.error('加载聚合预览失败:', error); + this.setData({ + activeFeedBubbleLoading: false + }); + wx.showToast({ + title: error.message || '加载失败', + icon: 'none' + }); + } + }, + + onFeedBubbleMoreTap(e) { + if (!this.ensureLoggedInForAction()) { + return; + } + + const { + lat, + lng, + radius + } = e.currentTarget.dataset || {}; + const bubble = this.data.activeFeedBubble || {}; + const latitude = Number(lat || bubble.location?.latitude || this.data.latitude); + const longitude = Number(lng || bubble.location?.longitude || this.data.longitude); + const radiusValue = Number(radius || bubble.radius || 200); + + if (Number.isNaN(latitude) || Number.isNaN(longitude)) { + wx.showToast({ + title: '位置信息不可用', + icon: 'none' + }); + return; + } + + this.hideFeedBubble(); + + const redirectToken = Date.now(); + const appInstance = getApp(); + if (appInstance && appInstance.globalData) { + appInstance.globalData.mapFeedRedirect = { + latitude, + longitude, + radius: Math.max(50, Math.round(radiusValue)), + feedUuid: bubble?.feeds?.[0]?.uuid || '', + mode: 'map', + token: redirectToken + }; + } + + wx.switchTab({ + url: '/pages/circle/circle' + }); + }, + + onFeedBubbleItemTap(e) { + if (!this.ensureLoggedInForAction()) { + return; + } + + const { + uuid, + lat, + lng, + radius + } = e.currentTarget.dataset || {}; + const bubble = this.data.activeFeedBubble || {}; + const latitude = Number(lat || bubble.location?.latitude || this.data.latitude); + const longitude = Number(lng || bubble.location?.longitude || this.data.longitude); + const radiusValue = Number(radius || bubble.radius || 200); + + if (Number.isNaN(latitude) || Number.isNaN(longitude)) { + wx.showToast({ + title: '位置信息不可用', + icon: 'none' + }); + return; + } + + this.hideFeedBubble(); + + const redirectToken = Date.now(); + const appInstance = getApp(); + if (appInstance && appInstance.globalData) { + appInstance.globalData.mapFeedRedirect = { + latitude, + longitude, + radius: Math.max(50, Math.round(radiusValue)), + feedUuid: uuid || '', + mode: 'map', + token: redirectToken + }; + } + + wx.switchTab({ + url: '/pages/circle/circle' + }); + }, + + getMapRegion() { + return new Promise((resolve, reject) => { + if (!this.mapCtx) { + reject(new Error('地图上下文未初始化')); + return; + } + + this.mapCtx.getRegion({ + success: resolve, + fail: reject + }); + }); + }, + + getMapScale() { + return new Promise((resolve, reject) => { + if (!this.mapCtx) { + reject(new Error('地图上下文未初始化')); + return; + } + + this.mapCtx.getScale({ + success: resolve, + fail: reject + }); + }); + }, + + // 加载浮动UI相关数据 + async loadFloatingUIData() { + try { + + // 并行加载各种统计数据 + await Promise.all([ + this.loadUnreadMessageCount(), + this.loadFriendRequestCount(), + this.loadNearbyCount() + ]); + + } catch (error) { + console.error('加载浮动UI数据失败:', error); + } + }, + + // 加载未读消息数 + async loadUnreadMessageCount() { + try { + // 这里应该调用消息API获取未读数 + // const response = await chatAPI.getTotalUnreadCount(); + // this.updateUnreadMessageCount(response.data?.count || 0); + + // 临时模拟数据 + this.updateUnreadMessageCount(0); + } catch (error) { + console.error('加载未读消息数失败:', error); + this.updateUnreadMessageCount(0); + } + }, + + // 加载好友请求数 + async loadFriendRequestCount() { + try { + // 这里应该调用好友API获取请求数 + // const response = await friendAPI.getFriendRequestCount(); + // this.updateFriendRequestCount(response.data?.count || 0); + + // 临时模拟数据 + this.updateFriendRequestCount(0); + } catch (error) { + console.error('加载好友请求数失败:', error); + this.updateFriendRequestCount(0); + } + }, + + // 加载附近的人数量 + async loadNearbyCount() { + try { + this.updateNearbyCount(this.data.strangersCount); + } catch (error) { + console.error('加载附近的人数量失败:', error); + this.updateNearbyCount(0); + } + }, + + // 🔥 ===== 浮动UI事件处理 ===== + + // 跳转到个人主页 + openProfile() { + + wx.navigateTo({ + url: '/subpackages/profile/profile/profile' + }); + }, + + // 打开好友页面 + openFriends() { + + wx.navigateTo({ + url: '/pages/social/friends/friends' + }); + }, + + // 打开消息页面 + openMessages() { + + wx.navigateTo({ + url: '/pages/message/message' + }); + }, + + // 打开WebSocket测试页面(开发调试用) + openWebSocketTest() { + + wx.navigateTo({ + url: '/subpackages/dev-tools/websocket-test/websocket-test' + }); + }, + + // ===== 搜索功能相关方法 ===== + // 显示搜索框 + showSearchBox() { + + this.setData({ + showSearchBox: true, + searchKeyword: '' + }); + }, + + // 隐藏搜索框 + hideSearchBox() { + + this.setData({ + showSearchBox: false, + searchKeyword: '' + }); + }, + + // 搜索输入处理 + onSearchInput(e) { + const keyword = e.detail.value; + this.setData({ + searchKeyword: keyword + }); + + // 如果输入内容不为空,开始搜索 + if (keyword.trim()) { + // 模拟搜索延迟 + setTimeout(() => { + this.searchPlaces(keyword); + }, 300); + } else { + // 清空搜索结果 + this.setData({ + searchResults: [] + }); + } + }, + + // 搜索确认处理 + onSearchConfirm() { + const keyword = this.data.searchKeyword.trim(); + if (keyword) { + + // 如果已有搜索结果,直接定位第一个结果 + if (this.data.searchResults && this.data.searchResults.length > 0) { + this.onSearchResultTap({ + currentTarget: { + dataset: { + item: this.data.searchResults[0] + } + } + }); + } else { + // 否则执行搜索 + this.searchPlaces(keyword); + wx.showToast({ + title: `搜索: ${keyword}`, + icon: 'none' + }); + } + } + }, + + // 搜索地点 + searchPlaces(keyword) { + // 显示加载提示 + wx.showLoading({ + title: '搜索中...', + mask: true + }); + + try { + // 高德地图 + const params = { + key: config.amapKey, + keywords: keyword, + city: this.data.currentCity || '全国', + citylimit: false, + location: this.data.myLocation ? `${this.data.myLocation.longitude},${this.data.myLocation.latitude}` : '' + }; + + // 调用高德地图API + wx.request({ + url: baseAmapUrl + '/assistant/inputtips', + data: params, + method: 'GET', + header: { + 'content-type': 'application/json' + }, + success: (res) => { + wx.hideLoading(); + + if (res.statusCode === 200 && res.data && res.data.status === '1' && res.data.tips) { + + // 转换格式 + const searchResults = res.data.tips.map((tip, index) => { + // 从location中提取经纬度 + let latitude = 0; + let longitude = 0; + if (tip.location && typeof tip.location === 'string' && tip.location.split(',').length === 2) { + const [lng, lat] = tip.location.split(','); + longitude = parseFloat(lng); + latitude = parseFloat(lat); + } + + // 根据类型设置不同的图标 + let icon = '📍'; + if (tip.name.includes('酒店')) icon = '🏨'; + else if (tip.name.includes('餐厅')) icon = '🍽️'; + else if (tip.name.includes('公园')) icon = '🌳'; + else if (tip.name.includes('地铁')) icon = '🚇'; + else if (tip.name.includes('购物中心') || tip.name.includes('广场')) icon = '🏬'; + + return { + id: `search_${index}`, + name: tip.name, + address: tip.address || tip.district || '地址不详', + latitude: latitude, + longitude: longitude, + district: tip.district, + icon: icon + }; + }); + + this.setData({ + searchResults: searchResults + }); + } else { + console.error('❌ 搜索失败,返回数据异常:', res.data); + wx.showToast({ + title: '未找到相关地点', + icon: 'none' + }); + + this.setData({ + searchResults: [] + }); + } + }, + fail: (error) => { + wx.hideLoading(); + console.error('❌ 搜索请求失败:', error); + wx.showToast({ + title: '搜索失败,请检查网络', + icon: 'none' + }); + + this.setData({ + searchResults: [] + }); + } + }); + } catch (error) { + wx.hideLoading(); + console.error('❌ 搜索过程发生异常:', error); + wx.showToast({ + title: '搜索过程发生异常', + icon: 'none' + }); + } + }, + + // 点击搜索结果 + onSearchResultTap(e) { + const item = e.currentTarget.dataset.item; + this.setData({ + selectResult: item, + selectedMerchant: item + }); + + // 隐藏搜索框和搜索结果 + this.setData({ + showSearchBox: false, + searchResults: [] + }); + + + // 在地图上添加标记 + const marker = { + id: new Date().getTime(), + latitude: item.latitude, + longitude: item.longitude, + width: 40, + height: 40, + type: 'search', // 标记类型:搜索结果 + iconPath: '/images/map/marker-select-position.png', + callout: { + content: item.name, + display: 'BYCLICK' + } + }; + + this.mapCtx.moveToLocation({ + latitude: item.latitude, + longitude: item.longitude + }); + + this.setData({ + latitude: item.latitude, + longitude: item.longitude, + currentMapScale: 17 + }); + + let that = this; + setTimeout(() => { + that.updateScale() + }, 1000) + + // 更新标记数组 + console.log("markers--->1-->" + this.data.markers.length) + + const filteredMarkers = this.data.allMarkers.filter(marker => marker.type !== 'search'); + this.setData({ + markers: filteredMarkers, + allMarkers: filteredMarkers + }); + + this.data.allMarkers.push(marker); + + this.setData({ + markers: this.data.allMarkers, + merchantName: item.name, + merchant: item.district + item.address, + }); + console.log("markers--->2-->" + this.data.markers.length) + this.setData({ + searchResultInfoModalVisible: true, + modalTranslateY:0, + shouldFollowLocation: false + }) + + // 显示提示信息 + wx.showToast({ + title: "定位成功", + icon: 'success' + }); + }, + handleHideBottm() { + const filteredMarkers = this.data.allMarkers.filter(marker => marker.type !== 'search'); + this.setData({ + markers: filteredMarkers, + allMarkers: filteredMarkers + }); + this.setData({ + placeMarkId: '', + mapClickCollect: '收藏', + searchResultInfoModalVisible: false, + shouldFollowLocation: false + }) + }, + handleHideBottmNavigation() { + this.setData({ + searchResultNavigationVisible: false + }) + }, + onSharechant() { + this.setData({ + shareShareVisible: true, + }) + }, + onNavigation() { + let distance = this.data.myLocation ? this.calculateDistance( + this.data.myLocation.latitude, this.data.myLocation.longitude, + this.data.selectResult.latitude, this.data.selectResult.longitude + ) : 0; + distance = this.formatDistance(distance); + this.setData({ + searchResultNavigationVisible: true, + distance: distance + }) + + }, + onNavigationTap(e) { + const type = e.currentTarget.dataset.type; + if (type == "gaode") { + this.guideToDouyin("请手动打开高德地图粘贴"); + } else if (type == "baidu") { + this.guideToDouyin("请手动打开百度地图粘贴"); + } else if (type == "tengxun") { + this.guideToDouyin("请手动打开腾讯地图粘贴"); + } else { + this.guideToDouyin("地址已复制"); + } + }, + handleShare(e) { + const type = e.currentTarget.dataset.type; + console.log("share--->" + type); + if (type == "douyin") { + this.guideToDouyin("请手动打开抖音粘贴"); + } else if (type == "weibo") { + this.guideToDouyin("请手动打开微博粘贴"); + } else if (type == "email") { + this.guideToDouyin("请手动打开邮箱粘贴"); + } else if (type == "qq") { + this.guideToDouyin("请手动打开QQ粘贴"); + } else if (type == "copy") { + this.guideToDouyin("地址已复制"); + } + }, + // 引导用户手动打开抖音 + guideToDouyin(title) { + // 先复制文字或保存图片(参考之前的代码) + this.copyShareText(); // 假设已实现复制文字的方法 + // 提示用户手动打开抖音 + wx.showModal({ + title: title, + content: this.data.merchant, + showCancel: false, + confirmText: '确定' + }); + }, + // 复制要分享的文字 + copyShareText() { + const text = this.data.merchant; + wx.setClipboardData({ + data: text, + success: () => {} + }); + }, + // 配置分享到聊天的内容(必填) + onShareAppMessage() { + return { + title: "Find Me", // 分享的文字内容 + path: '/custom-tab-bar/index/index', // 点击分享卡片跳转的页面 + imageUrl: "/images/findme-logo.png" // 分享时的图片(可选,增强展示效果) + }; + }, + // 在线图加载成功:标记为已加载 + handleAvatarLoaded(e) { + const { + index + } = e.currentTarget.dataset; // 获取当前 Marker 索引 + this.setData({ + [`markers[${index}].imageLoaded`]: true // 关键:给对应 Marker 添加加载完成状态 + }); + }, + + // 在线图加载失败(404/网络错误):保持默认图显示(避免在线图一直透明) + handleAvatarError(e) { + const { + index + } = e.currentTarget.dataset; + // 可选:如果想加载失败也显示默认图,这里不用改(在线图保持 opacity:0) + // 若想重试,可添加重试逻辑: + // const markers = this.data.markers; + // markers[index].avatarUrl = `${markers[index].avatarUrl}?t=${Date.now()}`; // 加时间戳避免缓存 + // this.setData({ markers }); + }, + + // 检查好友关系 + async checkFriendRelation(e) { + let customId = e.currentTarget.dataset.userid; + try { + const friendAPI = require('../../utils/friend-api.js'); + + // 显示加载提示 + wx.showLoading({ + title: '加载中...', + mask: true + }); + + // 获取好友详情 + const friendDetailResponse = await friendAPI.getFriendDetail(customId); + + wx.hideLoading(); + + if (friendDetailResponse && friendDetailResponse.code === 0 && friendDetailResponse.data) { + // 成功获取好友详情,说明是好友关系 + this.navigateToFriendProfile(customId); + return; + } + + // 跳转到陌生人主页 + this.navigateToStrangerProfile(customId); + + } catch (error) { + wx.hideLoading(); + console.error('检查好友关系失败:', error); + + // 跳转到陌生人主页 + this.navigateToStrangerProfile(customId); + } + }, + + // 跳转到好友主页 + navigateToFriendProfile(customId) { + if (!customId) { + console.error('customId 为空,无法跳转'); + wx.showToast({ title: '用户ID无效', icon: 'none' }); + return; + } + + const targetUrl = `/subpackages/social/friend-detail/friend-detail?customId=${customId}`; + console.log('准备跳转到好友页面:', targetUrl); + + wx.navigateTo({ + url: targetUrl, + success: () => { + console.log('✅ 成功跳转到好友页面'); + }, + fail: (err) => { + console.error('❌ navigateTo 跳转好友页面失败:', err); + // 如果 navigateTo 失败(可能是页面栈已满),尝试使用 redirectTo + wx.redirectTo({ + url: targetUrl, + success: () => { + console.log('✅ redirectTo 成功跳转到好友页面'); + }, + fail: (err2) => { + console.error('❌ redirectTo 也失败:', err2); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none', + duration: 2000 + }); + } + }); + } + }); + }, + + + // 跳转到陌生人主页 + navigateToStrangerProfile(customId) { + if (!customId) { + console.error('customId 为空,无法跳转'); + wx.showToast({ title: '用户ID无效', icon: 'none' }); + return; + } + + const targetUrl = `/subpackages/social/user-preview/user-preview?customId=${customId}`; + console.log('准备跳转到陌生人页面:', targetUrl); + + wx.navigateTo({ + url: targetUrl, + success: () => { + console.log('✅ 成功跳转到陌生人页面'); + }, + fail: (err) => { + console.error('❌ navigateTo 跳转陌生人页面失败:', err); + // 如果 navigateTo 失败(可能是页面栈已满),尝试使用 redirectTo + wx.redirectTo({ + url: targetUrl, + success: () => { + console.log('✅ redirectTo 成功跳转到陌生人页面'); + }, + fail: (err2) => { + console.error('❌ redirectTo 也失败:', err2); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none', + duration: 2000 + }); + } + }); + } + }); + }, + + handleHideShareBottm() { + this.setData({ + shareShareVisible: false + }) + }, + // ===== 更多菜单相关方法 ===== + // 切换更多菜单显示状态 + toggleMoreMenu() { + this.setData({ + showMoreMenu: !this.data.showMoreMenu, + showMapSettings: false // 确保地图设置不显示 + }); + + }, + + // 隐藏更多菜单 + hideMoreMenu() { + this.setData({ + showMoreMenu: false + }); + }, + + // 处理添加好友 + handleAddFriend() { + + this.hideMoreMenu(); + wx.navigateTo({ + url: '/subpackages/social/search/search' + }); + }, + + // 处理发起群聊 + handleStartGroupChat() { + + this.hideMoreMenu(); + wx.navigateTo({ + url: '/subpackages/group/create-group/create-group' + }); + }, + + // 处理显示二维码 + handleShowQRCode() { + this.hideMoreMenu(); + wx.navigateTo({ + url: '/subpackages/qr/qr-code/qr-code' + }); + }, + + // 处理扫一扫 + handleScanQRCode() { + this.hideMoreMenu(); + wx.scanCode({ + onlyFromCamera: false, + success: (res) => { + const scanResult = res.result || ''; + console.log('扫码结果:', scanResult); + + // 处理 FindMe 用户二维码格式: FINDME:{customId} + if (scanResult && scanResult.startsWith('FINDME:')) { + const customId = (scanResult.split(':')[1] || '').trim(); + + if (!customId) { + wx.showToast({ + title: '无效的用户二维码', + icon: 'none' + }); + return; + } + + // 检查是否是自己 + const currentUser = app.globalData.userInfo?.user; + if (currentUser && currentUser.customId === customId) { + wx.showToast({ + title: '这是你自己的二维码', + icon: 'none' + }); + return; + } + + // 检查好友关系并跳转 + this.handleScanResult(customId); + } else { + wx.showToast({ + title: '无效的二维码,这不是FindMe的用户二维码', + icon: 'none' + }); + } + }, + fail: (err) => { + // 用户取消不提示错误 + if (err.errMsg && !err.errMsg.includes('cancel')) { + console.error('扫一扫失败:', err); + wx.showToast({ + title: '扫码失败,请重试', + icon: 'none' + }); + } + } + }); + }, + + // 处理扫码结果(检查好友关系并跳转) + async handleScanResult(customId) { + if (!customId) { + wx.showToast({ + title: '用户ID无效', + icon: 'none' + }); + return; + } + + try { + const friendAPI = require('../../utils/friend-api.js'); + + // 显示加载提示 + wx.showLoading({ + title: '加载中...', + mask: true + }); + + // 获取好友详情 + const friendDetailResponse = await friendAPI.getFriendDetail(customId); + + wx.hideLoading(); + + // 判断是否是好友:code === 0 且有 data 数据 + const isFriend = friendDetailResponse?.code === 0 && friendDetailResponse?.data; + + console.log('扫码好友关系判断结果:', { + customId, + isFriend, + responseCode: friendDetailResponse?.code, + hasData: !!friendDetailResponse?.data + }); + + // 根据好友关系跳转到对应页面 + if (isFriend) { + this.navigateToFriendProfile(customId); + } else { + this.navigateToStrangerProfile(customId); + } + + } catch (error) { + wx.hideLoading(); + console.error('检查好友关系失败:', error); + + // 如果接口调用失败,默认当作陌生人处理 + console.log('接口调用失败,当作陌生人处理'); + this.navigateToStrangerProfile(customId); + } + }, + + // ===== 地图设置相关方法 ===== + // 打开地图设置 + openMapSettings() { + + this.setData({ + showMapSettings: true, + showMoreMenu: false // 确保更多菜单不显示 + }); + }, + + // 关闭地图设置 + closeMapSettings() { + + // 先添加滑出动画类 + this.setData({ + isClosingMapSettings: true + }); + + // 等待动画完成后再隐藏弹窗 + setTimeout(() => { + this.setData({ + showMapSettings: false, + isClosingMapSettings: false + }); + }, 300); // 与CSS动画时间一致 + }, + + // 设置地图图层 + setMapLayer(e) { + const layer = e.currentTarget.dataset.layer; + this.setData({ + showTraffic: false, + currentMapType: layer, + enableSatellite: layer === 'satellite' + }); + + + wx.showToast({ + title: this.getLayerTitle(layer), + icon: 'none' + }); + }, + + // 获取图层标题 + getLayerTitle(layer) { + const titles = { + 'standard': '标准地图', + 'satellite': '卫星地图', + 'jiache': '驾车模式', + 'gonggong': '公共交通模式' + }; + return titles[layer] || '地图模式'; + }, + + + // 打开好友选择弹窗 + onOpenFriendSelectModal() { + + // 同步selected字段 + const selectedIds = this.data.poiRemindSelectedFriends.map(f => f.userId); + const filteredFriendsList = this.data.filteredFriendsList.map(f => ({ + ...f, + selected: selectedIds.includes(f.userId) + })); + this.setData({ + showFriendSelectModal: true, + filteredFriendsList + }); + }, + + // 搜索输入 + onFriendSearchInput(e) { + const text = e.detail.value.trim(); + const list = this.data.allFriendsList.filter(f => !text || (f.nickname && f.nickname.indexOf(text) !== -1)); + // 同步selected字段 + const selectedIds = this.data.poiRemindSelectedFriends.map(f => f.userId); + const filteredFriendsList = list.map(f => ({ + ...f, + selected: selectedIds.includes(f.userId) + })); + this.setData({ + friendSearchText: text, + filteredFriendsList + }); + }, + + + + // 显示附近的人 + showNearbyPeople() { + + // 切换到显示附近的人 + this.setData({ + currentFilter: 'strangers' + }); + + // 刷新附近用户数据 + + this.loadNearbyUsers(); + + // 延迟显示toast,等待数据加载完成 + // setTimeout(() => { + // wx.showToast({ + // title: `发现${this.data.strangersCount}个附近的人`, + // icon: 'none', + // duration: 2000 + // }); + // }, 500); + }, + + // 显示好友位置 + showFriendsLocation() { + // 切换到显示好友 + this.setData({ + currentFilter: 'friends' + }); + + + + wx.showToast({ + title: `显示${this.data.friendsCount}个好友位置`, + icon: 'none', + duration: 2000 + }); + }, + + // 显示全部位置(好友和陌生人) + showAllLocations() { + + // 切换到显示全部 + this.setData({ + currentFilter: 'all' + }); + + // 刷新附近用户数据 + this.loadNearbyUsers(); + + // 延迟显示toast,等待数据加载完成 + setTimeout(() => { + wx.showToast({ + title: `显示${this.data.friendsCount}个好友和${this.data.strangersCount}个附近的人`, + icon: 'none', + duration: 2000 + }); + }, 500); + }, + + // 🔥 ===== 数据更新方法 ===== + + // 更新未读消息数 + updateUnreadMessageCount(count) { + this.setData({ + unreadMessageCount: count || 0 + }); + }, + + // 更新好友请求数 + updateFriendRequestCount(count) { + this.setData({ + friendRequestCount: count || 0 + }); + }, + + // 更新附近的人数量 + updateNearbyCount(count) { + this.setData({ + nearbyCount: count || 0 + }); + }, + + // 更新在线状态 + updateOnlineStatus(isOnline) { + this.setData({ + isOnline: isOnline !== false + }); + }, + + // 让地图相机完整显示以(lat, lng)为圆心,radius为半径的圆 + fitMapToCircle(lat, lng, radius) { + // 计算圆的四个边界点(上、下、左、右) + // 1度纬度约等于111km,1度经度约等于111km*cos(纬度) + const latDelta = radius / 111000; + const lngDelta = radius / (111000 * Math.cos(lat * Math.PI / 180)); + const points = [{ + latitude: lat + latDelta, + longitude: lng + }, // 上 + { + latitude: lat - latDelta, + longitude: lng + }, // 下 + { + latitude: lat, + longitude: lng + lngDelta + }, // 右 + { + latitude: lat, + longitude: lng - lngDelta + }, // 左 + { + latitude: lat, + longitude: lng + } // 圆心 + ]; + // padding自适应,半径越大padding越小,最小40最大100 + let padding = Math.max(40, 120 - Math.round(radius / 10)); + this.mapCtx && this.mapCtx.includePoints && this.mapCtx.includePoints({ + points, + padding: [padding, padding, padding, padding] + }); + }, + + // 保存POI提醒设置 + onSavePoiRemind() { + wx.showToast({ + title: '提醒设置已保存', + icon: 'success' + }); + }, + + // 打开地点标记弹窗 + onOpenLocationMarkModal() { + this.setData({ + showLocationMarkModal: true + }); + }, + // 关闭地点标记弹窗 + onCloseLocationMarkModal() { + this.setData({ + showLocationMarkModal: false + }); + }, + // 筛选输入 + onLocationMarkSearchInput(e) { + const text = e.detail.value.trim(); + const list = this.data.locationMarkList.filter(item => item.name.includes(text)); + this.setData({ + locationMarkSearchText: text, + filteredLocationMarkList: list + }); + }, + // 删除按钮(静态演示) + onDeleteLocationMark(e) { + wx.showToast({ + title: '删除演示', + icon: 'none' + }); + }, + // 修改按钮(静态演示) + onEditLocationMarkName(e) { + wx.showToast({ + title: '修改名称演示', + icon: 'none' + }); + }, + // 设置提醒好友(静态演示) + onSetRemindFriends(e) { + wx.showToast({ + title: '设置好友演示', + icon: 'none' + }); + }, + // 切换提醒类型(静态演示) + onToggleRemindType(e) { + wx.showToast({ + title: '切换类型演示', + icon: 'none' + }); + }, + // POI提醒名称输入 + onPoiRemindNameInput(e) { + const name = e.detail.value; + this.setData({ + 'lastPoiForRemind.name': name + }); + }, + + // 地点标记列表项点击事件 + onLocationMarkItemTap(e) { + const item = e.currentTarget.dataset.item; + + this.setData({ + showLocationMarkModal: false + }); + const poi = { + detail: { + name: item.name, + address: item.address || '', + latitude: item.lat, + longitude: item.lng + } + }; + this.onPoiTap(poi); + }, + + // 添加地点标记 + onAddLocationPlace() { + // 纯定位版SDK不支持getPoiAround功能 + wx.showModal({ + title: '提示', + content: '该功能暂不可用', + showCancel: false + }); + }, + onPoiAroundItemTap(e) { + const item = e.currentTarget.dataset.item; + this.setData({ + showPoiAroundModal: false + }); + const poi = { + detail: { + name: item.name, + address: item.address || '', + latitude: item.latitude, + longitude: item.longitude + } + }; + this.onPoiTap(poi); + }, + + onClosePoiAroundModal() { + this.setData({ + showPoiAroundModal: false + }); + }, + + closeMerchantInfo() { + this.setData({ + merchantInfoModalVisible: false, + activeMerchantId: null + }); + // 清除所有商户的active状态 + this.updateMerchantActiveState(null); + }, + + // 更新商户active状态 + updateMerchantActiveState(activeId) { + const markers = this.data.markers || []; + const updatedMarkers = markers.map(marker => { + if (marker.type === 'merchant') { + const markerBaseId = 10000; + const merchantId = marker.id - markerBaseId; + return { + ...marker, + isActive: merchantId === activeId + }; + } + return marker; + }); + this.setData({ + markers: updatedMarkers + }); + }, + preventClose(e) { + // 阻止事件冒泡,防止点击卡片内容时关闭弹窗 + // 注意:在微信小程序中,使用catchtap已自动阻止事件冒泡,不需要手动调用stopPropagation + // 此方法保留为空函数即可 + }, + + // 点击"去"按钮,提示截图享优惠 + onDishGoClick(e) { + console.log('点击了去按钮'); + wx.showToast({ + title: '截图享优惠', + icon: 'none', + duration: 2000 + }); + // 阻止事件冒泡,防止关闭弹窗 + if (e && e.stopPropagation) { + e.stopPropagation(); + } + }, + onFavoriteMerchant() { + const merchant = this.data.selectedMerchant; + merchant.isFavorited = !merchant.isFavorited; + this.setData({ + selectedMerchant: merchant, + merchantList: this.data.merchantList.map(m => m.id === merchant.id ? merchant : m) + }); + // 可加toast提示 + }, + onNavigateMerchant() { + const merchant = this.data.selectedMerchant; + wx.openLocation({ + latitude: merchant.latitude, + longitude: merchant.longitude, + name: merchant.name, + address: merchant.address, + scale: 16 + }); + }, + + //地点搜索结果的弹窗里的收藏 + onAddressCollect() { + this.setData({ + addressIsFavorited: !this.data.addressIsFavorited + }) + const merchant = this.data.selectedMerchant; + const address = merchant.address; + const latitude = merchant.latitude; + const longitude = merchant.longitude; + const name = merchant.name; + if (this.data.placeMarkId == '') { //空 说明还没有收藏地址 + this.onPoiFavoriteCommon(address, latitude, longitude, name); + } else { //说明刚才收藏了 再点击就是取消 + this.onPoiCancelCommon(this.data.placeMarkId); + } + }, + // 显示相机操作弹窗 + showCameraActionSheet() { + this.setData({ + showCameraAction: true + }); + }, + + + // 隐藏相机操作弹窗 + hideCameraActionSheet() { + this.setData({ + showCameraAction: false + }); + }, + + + ensureLoggedInForAction() { + if (this.data.isLoggedIn) { + return true; + } + + wx.showToast({ + title: '请先登录', + icon: 'none' + }); + this.navigateToLogin(); + return false; + }, + + // 导航到登录页面 + navigateToLogin() { + wx.navigateTo({ + url: '/pages/login/login' + }); + } +}); \ No newline at end of file diff --git a/pages/map/map.json b/pages/map/map.json new file mode 100644 index 0000000..2764922 --- /dev/null +++ b/pages/map/map.json @@ -0,0 +1,8 @@ +{ + "navigationBarTitleText": "FindMe", + "navigationBarBackgroundColor": "#667eea", + "navigationBarTextStyle": "white", + "backgroundColor": "#f8f9fa", + "navigationStyle": "custom", + "disableScroll": true +} diff --git a/pages/map/map.wxml b/pages/map/map.wxml new file mode 100644 index 0000000..765389d --- /dev/null +++ b/pages/map/map.wxml @@ -0,0 +1,875 @@ + + + + + + + + + + + + FindMe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{item.merchantName || item.name}} + + + + {{item.content.substr(0, 20)}}{{item.content.length > 20 ? '...' : + ''}} + + + + + + + + + + + + + + + + {{item.commentCount !== undefined ? (item.commentCount > 0 ? item.commentCount : 0) : 0}} + + + + + + + + + + + + + + + + {{item.feedCount}} + + + + + + + + + + + + + + + + + + {{metric}} + + + + + + + + + {{imperial}} + + + + + + + + + + + + 正在获取您的位置 + 首次定位可能需要几秒钟... + + + + + {{loadingText}} + + + + + + + + + + + + {{currentDistrict}} + + + + + {{weatherInfo.icon }} + {{weatherInfo.temperature}}° + + + + + + + + {{isOnline ? '偶遇' : '偶遇'}} + + + + + + + {{mapFeedVisible ? '动态' : '动态'}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{item.icon || '📍'}} + + {{item.name}} + {{item.address}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 添加好友 + + + + + + 发起群聊 + + + + 我的二维码 + + + + 扫一扫 + + + + + + + + + + + + 👥 + 仅好友 + + + 👤 + 仅陌生人 + + + 👨‍👩‍👧‍👦 + 全部用户 + + + + + + + + + + + + + + + + + + + + + + + {{activeFeedBubble.title}} + {{activeFeedBubble.subtitle}} + + + {{activeFeedBubble.chip}} + {{activeFeedBubble.heat}} + + + + + + 精选动态 + {{activeFeedBubble.feeds}}条推荐 + + + + 加载中... + 暂时没有推荐,稍后再来看看 + + + 打开附近动态 + + + 轻触地图空白处即可收起 + + + + + + + + + + + + + + + {{activeFeedBubbleSingle.nickname || '匿名用户'}} + {{activeFeedBubbleSingle.createdAt || '发布时间'}} + + + + + + {{activeFeedBubbleSingle.content}} + + + + + + + + + + 打开附近动态 + + + 轻触地图空白处即可收起 + + + + + + + + + + + + + + + {{selectedUser.nickname || '用户'}} + 距离 {{selectedUser.distance}}米 + 位置信息 + + + 在线 + + + + + + + + + + 💬 + 聊天 + + + + 加好友 + + + 👤 + 资料 + + + + + + + + + + + + + + + {{loadingText}} + 正在连接位置服务... + + + + + + + + + + + 📍 + + + {{poiDetail.name || 'POI'}} + {{poiDetailAddress}} + + + + + + + + + {{mapClickCollect}} + + + 🧭 + 导航 + + + + + + + + + + + + 地点设置 + 到达或离开该地点时提醒你和好友 + + + + POI + + + + + + 可点击编辑名称 + + {{lastPoiForRemind.address || '详细地址未知'}} + + + + + + + + + + + + + + + + + {{poiRemindSelectedFriends[index].nickname ? + poiRemindSelectedFriends[index].nickname.charAt(0) : 'U'}} + + + + + + + + + + + + + + + + 提醒范围 + {{poiRemindRadius}} 米 + + + + 拖动滑块,地图上圆圈范围会实时变化 + + + + + + + + 选择好友(最多3个) + + + + + + + + {{poiRemindSelectedFriends[index].nickname ? + poiRemindSelectedFriends[index].nickname.charAt(0) : 'U'}} + + + + + + + + + + + + + {{item.nickname ? item.nickname.charAt(0) : 'U'}} + + {{item.nickname}} + + + + + + + + + + + + + + + + + + + + + 地点标记 + + + 🔍 + + + + + + + + + + + {{item.name}} + {{item.lat}}, {{item.lng}} + + + + + + + + + + + + + + {{f.nickname ? f.nickname.charAt(0) : 'U'}} + + + + + + + {{item.remindType == 'arrive' ? '到达' : '离开'}} + + + + + + 📍 + 暂无收藏地址 + + + + + + + + + + + + + + + + + 附近地点 + + + + {{item.name}} + {{item.address}} + {{item.distanceStr}} + + + 暂无数据 + + 关闭 + + + + + + + + + + + + + + + + + + + {{selectedMerchant.name}} + + + {{selectedMerchant.dishInfo.title}} + + + + {{selectedMerchant.dishInfo.sales}} + {{selectedMerchant.dishInfo.ranking}} + + + + + {{selectedMerchant.dishInfo.rating}} 分 + {{selectedMerchant.dishInfo.shopName}} + + {{selectedMerchant.dishInfo.district}} + + + + + + + ¥{{selectedMerchant.dishInfo.groupPrice}}¥{{selectedMerchant.dishInfo.originalPrice}} + (团购价)省{{selectedMerchant.dishInfo.discount}}元 + + + + + 详细地址:{{selectedMerchant.address}} + + + + + + + + + + + + + 位置:{{merchantName}} + + + 详细地址:{{merchant}} + + + + + + + + + + + + + + + + + + + + 分享给好友 + + + + + + + + + + + + + + + + + + + 距离你{{distance}} + + + 详细地址:{{merchant}} + + + + + + 高德地图 + + + + 百度地图 + + + + 腾讯地图 + + + + + > + + \ No newline at end of file diff --git a/pages/map/map.wxss b/pages/map/map.wxss new file mode 100644 index 0000000..33c469f --- /dev/null +++ b/pages/map/map.wxss @@ -0,0 +1,5842 @@ +/* 地图页面 - 现代化设计 + 系统适配 */ +page { + margin: 0; + padding: 0; + box-sizing: border-box; + background: #f5f5f5; + --menuButtonRight: 20px; + /* 定义右侧按钮与屏幕边缘的间距 */ +} + +/* 地图容器 */ +.map-container { + position: relative; + width: 100%; + background: #f5f5f5; + padding-bottom: env(safe-area-inset-bottom); +} + + +.district-text.dark { + color: white; +} +.toggle-text.dark { + color: white; +} +.weather-temp .dark{ + color: white; +} + +/* 地图黑色主题基础样式 */ +.map-dark { + --map-background-color: #0a0a0a; + --map-control-color: #ffffff; + --map-label-color: #ffffff; + --map-poi-color: #ffffff; + --map-background: #000000; + --map-text-color: #ffffff; +} + +.custom-scale { + width: 100px; + position: absolute; + display: flex; + flex-direction: column; + align-items: center; + padding: 5rpx 12rpx; + border-radius: 4rpx; + box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.5); +} + +.scale-unit { + font-size: 18rpx; + color: #333; + line-height: 1.2; +} + +.metric { + /* 米/千米在上 */ + margin-bottom: 4rpx; +} + +.imperial { + /* 英尺在下 */ + margin-top: 4rpx; +} + +.scale-bar { + width: 80px; + /* 最大线段长度,可调整 */ + height: 4rpx; + background: #eee; + position: relative; +} + +.scale-line { + height: 100%; + background: #333; + /* 线段颜色 */ +} + + +/* 适配底部导航栏的地图容器 */ +.map-with-tabbar { + height: calc(100vh - env(safe-area-inset-bottom)); + position: relative; +} + +/* 底部导航栏玻璃效果适配 */ +page { + background: #f5f5f5; +} + +/* 修复地图页面底部内容不被遮挡 */ +.content-area { + padding-bottom: 0; +} + +/* 地图组件 */ +.map { + width: 100%; + height: 100%; +} + +/* 定位占位图 - 现代化设计 */ +.location-placeholder { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; +} + +.placeholder-content { + text-align: center; + color: white; + padding: 40px; +} + +.location-icon { + font-size: 64px; + margin-bottom: 20px; + animation: float 3s ease-in-out infinite; +} + +@keyframes float { + + 0%, + 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-10px); + } +} + +.placeholder-title { + font-size: 20px; + font-weight: 600; + margin-bottom: 8px; + display: block; +} + +.placeholder-subtitle { + font-size: 14px; + opacity: 0.8; + margin-bottom: 30px; + display: block; +} + +.location-progress { + width: 80px; + margin: 0 auto; +} + + + +.progress-fill { + width: 100%; + height: 100%; + background: rgba(255, 255, 255, 0.8); + border-radius: 2px; + animation: progress 2s ease-in-out infinite; +} + +@keyframes progress { + 0% { + transform: translateX(-100%); + } + + 100% { + transform: translateX(100%); + } +} + +.progress-text { + font-size: 12px; + opacity: 0.7; +} + +/* 自定义导航栏 */ +.custom-navigation-bar { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 999; + /* backdrop-filter: blur(10px); */ +} + +.status-bar-space { + width: 100%; +} + +.nav-content { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 16rpx; +} + +.nav-left, +.nav-right { + flex-shrink: 0; +} + +.nav-title { + flex: 1; + text-align: center; + color: white; + font-size: 32rpx; + font-weight: 600; + letter-spacing: 2rpx; +} + +/* 顶部状态栏 - 系统适配 */ +.top-bar { + position: absolute; + top: 0; + left: 0; + right: 0; + padding: 16rpx 32rpx; + background: linear-gradient(180deg, rgba(0, 0, 0, 0.3) 0%, transparent 100%); + z-index: 100; + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 20rpx; +} + +.location-info { + padding: 16rpx 20rpx; + display: flex; + align-items: center; + gap: 12rpx; + flex: 1; + min-width: 0; + transition: all 0.2s ease; +} + +.location-info:active { + background: rgba(255, 255, 255, 1); + transform: scale(0.98); +} + +.location-icon-small { + font-size: 24rpx; + opacity: 0.8; + flex-shrink: 0; +} + +.location-content { + flex: 1; + min-width: 0; +} + +.location-text { + font-size: 26rpx; + color: #2c3e50; + font-weight: 600; + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + line-height: 1.3; +} + +.location-debug { + font-size: 20rpx; + color: #7f8c8d; + margin-top: 2rpx; + display: block; + opacity: 0.8; +} + +.weather-info { + background: rgba(255, 255, 255, 0.95); + padding: 16rpx 20rpx; + border-radius: 48rpx; + backdrop-filter: blur(20rpx); + box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1); + display: flex; + align-items: center; + gap: 8rpx; + flex-shrink: 0; +} + +.weather-icon { + font-size: 24rpx; +} + +.weather-text { + font-size: 24rpx; + color: #2c3e50; + font-weight: 600; +} + +/* 顶部元素容器 - 统一的flex布局 */ +.top-elements-container { + position: absolute; + top: 0; + left: 0; + right: 0; + width: 100%; + z-index: 100; +} + +.top-elements-content { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 16rpx 32rpx; +} + +/* 左上角区域信息容器 - 垂直堆叠样式 */ +.top-left-info-container { + padding: 12rpx 16rpx; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + z-index: 100; + pointer-events: auto; + transition: all 0.3s ease; + margin-right: 10px; + flex-shrink: 0; + /* 确保左侧信息区域位置固定,不受到其他区域影响 */ +} + +/* 登录状态下的左侧信息容器样式 */ +.top-left-info-container.logged-in { + position: relative; + left: 0; + top: 0; + /* 保持默认样式 */ +} + +/* 未登录状态下的左侧信息容器样式 */ +.top-left-info-container.not-logged-in { + position: absolute; + left: 20rpx; + top: 0; + /* 固定在左上角,避免受其他元素影响 */ + z-index: 101; + /* 确保在最上层显示 */ +} + +.top-left-info-container:active { + transform: scale(0.98); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); +} + +/* 1. 地点位置样式 */ +.location-section { + display: flex; + color: #333 ; + align-items: center; + min-width: 100px; +} + +.district-text { + font-size: 48rpx; + font-weight: 700; + color: #333 ; + line-height: 1.2; + text-shadow: + 0 1px 2px rgba(255, 255, 255, 0.8), + 0 -1px 0 rgba(0, 0, 0, 0.1); +} + +/* 2. 天气信息样式 */ +.weather-section { + display: flex; + align-items: center; + gap: 16px; +} + +.weather-icon { + font-size: 36rpx; + animation: weather-float 3s ease-in-out infinite; + filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1)); +} + +/* 云彩图标特殊处理 - 黑色 */ +.weather-icon.cloud-icon { + filter: + drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1)) grayscale(1) brightness(0.3); +} + +@keyframes weather-float { + + 0%, + 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-2px); + } +} + +.weather-temp { + font-size: 32rpx; + font-weight: 700; + color: #333 ; + text-shadow: + 0 1px 2px rgba(255, 255, 255, 0.8), + 0 -1px 0 rgba(0, 0, 0, 0.1); +} + + + +/* 容器样式:横向排列 */ +.toggle-section { + display: flex; + align-items: center; + gap: 10px; + /* 文字与图片间距 */ + cursor: pointer; + padding:10px 15px 5px 0px; +} + +.toggle-section-dynamic { + display: flex; + align-items: center; + gap: 10px; + /* 文字与图片间距 */ + cursor: pointer; + padding:0px 15px 0px 0px; +} + +/* 文字样式 */ +.toggle-text { + font-size: 14px; + color:#333 +} + +/* 开关图片样式 */ +.switch-img { + width: 40px; + /* 图片宽度(根据你的图片尺寸调整) */ + height: auto; + /* 高度自适应,保持比例 */ +} + + + + + + + +/* 中间搜索区域样式 - 只适应右侧按钮区域,不适应左侧区域 */ +.search-area { + /* border: 2px solid #00ffcc; */ + display: flex; + justify-content: flex-end; + align-items: center; + padding-right: 10px; + margin-left: auto; +} + +/* 右侧元素容器样式 */ +.right-elements-container { + display: flex; + align-items: flex-start; + /* padding-right: calc(var(--menuButtonRight)- 16px); */ + padding-left: calc(var(--menuButtonLeft)); + /* 使用与微信胶囊相同的右侧间距 */ +} + +/* 适配深色模式 */ +@media (prefers-color-scheme: dark) { + .weather-temp { + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); + } + + .weather-icon { + filter: drop-shadow(0 1px 2px rgba(255, 255, 255, 0.1)); + } + + .weather-icon.cloud-icon { + filter: + drop-shadow(0 1px 2px rgba(255, 255, 255, 0.1)) grayscale(1) brightness(0.7); + } +} + +/* 🎨 现代化用户头像 -/* 右侧垂直按钮组 */ +.right-vertical-buttons { + display: flex; + flex-direction: column; + gap: 16rpx; +} + +.user-avatar { + width: 44px; + height: 44px; + animation: avatarSlideIn 0.8s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* 测试按钮样式 */ +.test-favorite-btn { + width: 88rpx; + height: 88rpx; + background: linear-gradient(145deg, #007AFF 0%, #5AC8FA 50%, #AF52DE 100%); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + position: relative; + box-shadow: + 0 8rpx 24rpx rgba(0, 122, 255, 0.3), + 0 3rpx 8rpx rgba(0, 122, 255, 0.2), + inset 0 1rpx 0 rgba(255, 255, 255, 0.3); + border: 3rpx solid rgba(255, 255, 255, 0.95); + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + backdrop-filter: blur(10rpx); + z-index: 1; +} + +.test-favorite-btn:active { + transform: scale(0.92); + box-shadow: + 0 4rpx 16rpx rgba(0, 122, 255, 0.4), + 0 2rpx 6rpx rgba(0, 122, 255, 0.3), + inset 0 1rpx 0 rgba(255, 255, 255, 0.2); +} + +@keyframes avatarSlideIn { + from { + opacity: 0; + transform: translateX(60rpx) scale(0.8); + } + + to { + opacity: 1; + transform: translateX(0) scale(1); + } +} + +.avatar-container { + width: 88rpx; + height: 88rpx; + border-radius: 50%; + background: linear-gradient(145deg, #007AFF 0%, #5AC8FA 50%, #AF52DE 100%); + display: flex; + align-items: center; + justify-content: center; + position: relative; + box-shadow: + 0 8rpx 24rpx rgba(0, 122, 255, 0.3), + 0 3rpx 8rpx rgba(0, 122, 255, 0.2), + inset 0 1rpx 0 rgba(255, 255, 255, 0.3); + border: 3rpx solid rgba(255, 255, 255, 0.95); + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + backdrop-filter: blur(10rpx); + z-index: 1; +} + +.avatar-container:active { + transform: scale(0.92); + box-shadow: + 0 4rpx 16rpx rgba(0, 122, 255, 0.4), + 0 2rpx 6rpx rgba(0, 122, 255, 0.3), + inset 0 1rpx 0 rgba(255, 255, 255, 0.2); +} + +/* 悬停效果 */ +@media (hover: hover) { + .avatar-container:hover { + transform: scale(1.05); + box-shadow: + 0 12rpx 32rpx rgba(0, 122, 255, 0.4), + 0 4rpx 12rpx rgba(0, 122, 255, 0.3), + inset 0 1rpx 0 rgba(255, 255, 255, 0.4); + } +} + +.avatar-image { + width: 100%; + height: 100%; + border-radius: 50%; + position: relative; + z-index: 10; +} + +.avatar-text { + font-size: 32rpx; + font-weight: 700; + color: white; + text-transform: uppercase; + text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3); + letter-spacing: 1rpx; + z-index: 2; +} + +/* 🎯 方向小针指示器 */ +.online-dot { + position: absolute; + bottom: -8rpx; + right: -8rpx; + width: 40rpx; + height: 40rpx; + background: url('/images/map/maker_position.png') no-repeat center center; + background-size: contain; + transform-origin: 50% 50%; + z-index: 3; +} + +/* 方向针样式设置完成 */ + +/* 右侧功能按钮组 */ +.right-controls { + position: absolute; + display: flex; + flex-direction: column; + gap: 12px; + z-index: 50; +} + +.control-btn { + width: 44px; + height: 44px; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(20px); + border-radius: 22px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + border: 1px solid rgba(255, 255, 255, 0.8); + transition: all 0.2s ease; +} + +.control-btn:active { + transform: scale(0.95); + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15); +} + +.btn-icon { + font-size: 18px; +} + +.refresh-icon { + transition: transform 0.3s ease; +} + +.refresh-btn:active .refresh-icon { + transform: rotate(180deg); +} + +/* 底部定位按钮 - 新增 */ +.location-btn { + position: absolute; + left: 50%; + transform: translateX(-50%); + z-index: 60; +} + +.location-btn-inner { + width: 40px; + height: 40px; + background: #41414149; + backdrop-filter: blur(20px); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4); + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +.location-btn:active .location-btn-inner { + transform: scale(0.95); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2); +} + +.location-btn .location-btn-inner .location-icon { + position: relative; + z-index: 2; + animation: none; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + margin: 0; + padding: 0; +} + +.location-btn .location-btn-inner .location-icon image { + width: 22px; + height: 22px; + display: block; + margin: 0; + padding: 0; + filter: brightness(0) invert(1); +} + +.location-ripple { + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + border-radius: 50%; + background: rgba(102, 126, 234, 0.3); + transform: translate(-50%, -50%); + animation: location-ripple 2s ease-in-out infinite; +} + +@keyframes location-ripple { + 0% { + width: 0; + height: 0; + opacity: 1; + } + + 100% { + width: 80px; + height: 80px; + opacity: 0; + } +} + +/* 地图动态浮层 */ +.feed-bubble-overlay { + position: absolute; + left: 0; + right: 0; + display: flex; + justify-content: center; + z-index: 1200; +} + +.feed-bubble-card { + position: relative; + width: calc(100% - 160rpx); + max-width: 700rpx; + padding: 32rpx 32rpx 28rpx; + border-radius: 36rpx; + background: rgba(24, 26, 36, 0.88); + color: #ffffff; + box-shadow: 0 28rpx 60rpx rgba(0, 0, 0, 0.35); + backdrop-filter: blur(28rpx); + border: 1px solid rgba(255, 255, 255, 0.08); +} + +.feed-bubble-card.sunset { + background: linear-gradient(160deg, rgba(59, 31, 99, 0.92), rgba(226, 92, 121, 0.85)); +} + +.feed-bubble-card.ocean { + background: linear-gradient(160deg, rgba(26, 61, 110, 0.9), rgba(66, 185, 208, 0.82)); +} + +.feed-bubble-handle { + width: 88rpx; + height: 8rpx; + border-radius: 999rpx; + background: rgba(255, 255, 255, 0.28); + margin: 0 auto 26rpx; +} + +.feed-bubble-header { + display: flex; + align-items: flex-start; + gap: 24rpx; +} + +.feed-bubble-title-block { + flex: 1; + min-width: 0; +} + +.feed-bubble-title { + display: block; + font-size: 36rpx; + font-weight: 600; + letter-spacing: 1rpx; +} + +.feed-bubble-subtitle { + display: block; + margin-top: 8rpx; + font-size: 26rpx; + color: rgba(255, 255, 255, 0.75); +} + +.feed-bubble-chip-group { + display: flex; + flex-direction: column; + gap: 16rpx; + align-items: flex-end; +} + +.feed-bubble-chip { + padding: 6rpx 20rpx; + border-radius: 999rpx; + background: rgba(255, 255, 255, 0.2); + font-size: 22rpx; + font-weight: 500; + color: #fff; +} + +.feed-bubble-chip.heat { + background: rgba(255, 194, 140, 0.24); + color: #ffe9db; +} + +.feed-bubble-close { + /* 调整位置到右上角 */ + position: absolute; + top: 1px; + right: 1px; + + /* 扩大点击区域 */ + width: 50px; + height: 50px; + + /* 保持图标居中 */ + display: flex; + align-items: center; + justify-content: center; + + /* 原有样式保留 */ + font-size: 28rpx; + color: rgba(255, 255, 255, 0.6); + + /* 可选:添加点击反馈 */ + border-radius: 50%; + transition: background-color 0.2s; +} + + +.feed-bubble-close:active { + background-color: rgba(255, 255, 255, 0.1); +} + + + +.feed-bubble-meta { + display: flex; + flex-wrap: wrap; + gap: 32rpx; + margin: 28rpx 0 12rpx; +} + +.feed-bubble-meta-item { + display: flex; + flex-direction: column; + min-width: 140rpx; +} + +.feed-bubble-meta-label { + font-size: 22rpx; + color: rgba(255, 255, 255, 0.6); +} + +.feed-bubble-meta-value { + font-size: 26rpx; + font-weight: 500; + margin-top: 6rpx; + color: #ffffff; +} + +.feed-bubble-loading, +.feed-bubble-empty { + text-align: center; + padding: 48rpx 0; + font-size: 26rpx; + color: rgba(255, 255, 255, 0.75); +} + +.feed-bubble-scroll { + margin: 6rpx 0 18rpx; + padding-bottom: 6rpx; + white-space: nowrap; +} + +.feed-bubble-card-item { + position: relative; + width: 220rpx; + height: 200rpx; + border-radius: 26rpx; + overflow: hidden; + margin-right: 24rpx; + flex: 0 0 auto; + display: inline-block; + background: rgba(255, 255, 255, 0.1); +} + +.feed-bubble-card-thumb { + width: 100%; + height: 100%; +} + +.feed-bubble-card-gradient { + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(0, 0, 0, 0.05) 10%, rgba(0, 0, 0, 0.75) 90%); +} + +.feed-bubble-card-info { + position: absolute; + left: 18rpx; + right: 18rpx; + bottom: 18rpx; + display: flex; + flex-direction: column; + gap: 6rpx; +} + +.feed-bubble-card-title { + font-size: 26rpx; + font-weight: 600; + color: #ffffff; + white-space: normal; + line-height: 1.34; +} + +.feed-bubble-card-desc { + font-size: 22rpx; + color: rgba(255, 255, 255, 0.75); +} + +.feed-bubble-actions { + margin-top: 12rpx; +} + +.feed-bubble-action { + width: 100%; + text-align: center; + padding: 22rpx 0; + border-radius: 999rpx; + font-size: 28rpx; + font-weight: 600; + letter-spacing: 1rpx; +} + +.feed-bubble-action.primary { + background: linear-gradient(135deg, rgba(92, 124, 255, 0.95), rgba(72, 200, 255, 0.95)); + color: #ffffff; + box-shadow: 0 16rpx 28rpx rgba(86, 143, 255, 0.35); +} + +.feed-bubble-action:active { + opacity: 0.86; +} + +.feed-bubble-tip { + margin-top: 18rpx; + text-align: center; + font-size: 22rpx; + color: rgba(255, 255, 255, 0.55); +} + +/* 用户详情卡片 - 现代化设计 */ +.user-card { + position: absolute; + left: 16px; + right: 16px; + background: rgba(0, 0, 0, 0.95); + backdrop-filter: blur(20px); + border-radius: 20px; + padding: 20px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); + border: 1px solid rgba(255, 255, 255, 0.1); + transform: translateY(100%); + opacity: 0; + transition: all 0.3s ease; + z-index: 100000; + /* 高于相机按钮 */ +} + +.user-card.show { + transform: translateY(0); + opacity: 1; +} + +/* 已移除上沿彩条 */ +.card-backdrop { + display: none; +} + +.card-header { + display: flex; + align-items: center; + margin-bottom: 16px; +} + +.card-avatar { + width: 48px; + height: 48px; + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + margin-right: 12px; + box-shadow: 0 4px 16px rgba(104, 249, 254, 0.3); + overflow: hidden; +} + + + +.card-avatar-url { + margin-right: 12px; + width: 48px; + height: 48px; + border-radius: 24px; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; + background: #f0f0f0; +} + +.avatar-img { + width: 100%; + height: 100%; + object-fit: cover; /* 保持比例并裁剪多余部分 */ +} + + +/* 用户头像样式 */ +.card-avatar image { + width: 100%; + height: 100%; + display: block; + object-fit: cover; +} + +/* POI地点头像样式 - 与其他按钮统一渐变 */ +.card-avatar.poi-avatar { + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + box-shadow: 0 4px 16px rgba(104, 249, 254, 0.3); +} + +.card-avatar-text { + color: white; + font-size: 18px; + font-weight: 600; +} + +.card-info { + flex: 1; + min-width: 0; +} + +.card-name { + font-size: 18px; + font-weight: 600; + color: #fff; + margin-bottom: 4px; + display: block; +} + + +.image-getaddress { + margin-top: 20px; + width: 100%; + height: 35px; +} + +.card-distance { + font-size: 13px; + color: #ccc; + margin-bottom: 4px; + display: block; +} + +.card-status { + display: flex; + align-items: center; + gap: 4px; +} + +.status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: #2ed573; + animation: pulse 2s ease-in-out infinite; +} + +@keyframes pulse { + + 0%, + 100% { + opacity: 1; + transform: scale(1); + } + + 50% { + opacity: 0.7; + transform: scale(1.2); + } +} + +.status-text { + font-size: 11px; + color: #2ed573; + font-weight: 500; +} + +.card-close { + width: 32px; + height: 32px; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.1); + transition: all 0.2s ease; +} + +.card-close:active { + background: rgba(255, 255, 255, 0.2); + transform: scale(0.9); +} + +.close-icon { + font-size: 16px; + color: #fff; +} + +.card-actions { + display: flex; + gap: 12px; + padding-top: 8px; +} + +/* 统一按钮样式 - 与发起群聊页面确定按钮风格一致 */ +.action-btn { + flex: 1; + display: flex; + flex-direction: row; + /* 修改为水平排列 */ + align-items: center; + justify-content: center; + gap: 6px; + padding: 12px 8px; + /* 调整为更适合水平排列的内边距 */ + border-radius: 16px; + transition: all 0.3s ease; + position: relative; + overflow: hidden; + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + border: 1px solid rgba(104, 249, 254, 0.7); + box-shadow: 0 6px 16px rgba(104, 249, 254, 0.3); + /* 增强阴影效果 */ +} + +.action-btn-share { + /* 1. 清除按钮自身基础样式 */ + border: none; + /* 去除边框 */ + background-color: transparent; + /* 背景色设为透明 */ + padding: 0; + /* 清除内边距 */ + margin: 0; + /* 清除外边距 */ + border-radius: 0; + /* 可选,去除圆角 */ + line-height: 1; + /* 调整行高,避免额外空间 */ + + /* 2. 设置按钮尺寸(或由内容决定) */ + display: inline-block; + /* 使按钮尺寸由内容撑开 */ + width: auto; + height: auto; +} + +/* 3. 【关键】清除小程序按钮独特的伪元素边框 */ +.action-btn-share::after { + border: none !important; + /* 必须使用 !important 确保覆盖默认样式 */ +} + +/* 4. 设置按钮内部图片的样式 */ +.action-btn-share image { + display: block; + /* 消除图片底部的空隙 */ + width: 80rpx; + /* 请根据您的图片尺寸和设计需求调整宽度 */ + height: 100rpx; + /* 请根据您的图片尺寸和设计需求调整高度 */ +} + + +/* 渐变背景增强 */ +.action-btn::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + z-index: -1; + opacity: 0.8; +} + +.action-btn:active { + transform: scale(0.98); + box-shadow: 0 2px 8px rgba(104, 249, 254, 0.3); +} + +/* 确保所有按钮使用相同的渐变背景 */ +.chat-btn, +.add-btn, +.profile-btn { + /* 继承基础action-btn样式,不再重复定义渐变背景 */ + box-shadow: 0 6px 16px rgba(104, 249, 254, 0.3); + /* 确保与基础按钮相同的阴影效果 */ +} + +/* 点击效果优化 */ +.chat-btn:active, +.add-btn:active, +.profile-btn:active { + transform: scale(0.96); + /* 更强的缩放效果 */ + box-shadow: 0 3px 8px rgba(104, 249, 254, 0.4); + /* 点击时的阴影变化 */ +} + + + +.action-text { + font-size: 13px; + font-weight: 600; + color: #000000; +} + +/* 浮动通知 */ +.floating-notifications { + position: absolute; + z-index: 90; +} + +.notification-item { + background: rgba(255, 255, 255, 0.95); + padding: 12rpx 20rpx; + border-radius: 32rpx; + backdrop-filter: blur(20rpx); + display: flex; + align-items: center; + gap: 12rpx; + box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1); + margin-bottom: 12rpx; + animation: slide-in-left 0.3s ease; +} + +.notification-icon { + font-size: 24rpx; +} + +.notification-text { + font-size: 24rpx; + color: #2c3e50; + font-weight: 500; +} + +@keyframes slide-in-left { + from { + transform: translateX(-100%); + opacity: 0; + } + + to { + transform: translateX(0); + opacity: 1; + } +} + +/* 加载提示 - 优化设计 */ +.loading-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; +} + +.loading-content { + text-align: center; + color: white; +} + +.loading-spinner { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 20px; +} + +.spinner-ring { + width: 20px; + height: 20px; + border: 2px solid rgba(255, 255, 255, 0.3); + border-top: 2px solid white; + border-radius: 50%; + margin: 0 3px; + animation: spin 1s linear infinite; +} + +.spinner-ring:nth-child(2) { + animation-delay: 0.1s; +} + +.spinner-ring:nth-child(3) { + animation-delay: 0.2s; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +.loading-text { + font-size: 16px; + font-weight: 600; + margin-bottom: 8px; + display: block; +} + +.loading-subtitle { + font-size: 13px; + opacity: 0.8; + display: block; +} + +/* 响应式设计 */ +@media (max-width: 375px) { + .right-controls { + right: 12px; + } + + .control-btn { + width: 40px; + height: 40px; + border-radius: 20px; + } + + .btn-icon { + font-size: 16px; + } + + .location-btn-inner { + width: 52px; + height: 52px; + border-radius: 26px; + } + + .location-btn .location-icon { + font-size: 20px; + } + + .user-card { + left: 12px; + right: 12px; + padding: 16px; + } + + .card-avatar { + width: 44px; + height: 44px; + } + + .card-avatar-text { + font-size: 16px; + } + + .action-btn { + padding: 10px 6px; + } +} + +/* 深色模式支持 */ +@media (prefers-color-scheme: dark) { + + .control-btn, + .location-btn-inner, + .user-card { + background: rgba(42, 42, 42, 0.95); + border-color: rgba(255, 255, 255, 0.1); + } + + .card-name { + color: #fff; + } + + .card-distance, + .close-icon, + .action-text { + color: #ccc; + } + + .card-close { + background: rgba(255, 255, 255, 0.1); + } + + .card-close:active { + background: rgba(255, 255, 255, 0.2); + } +} + +/* 🔥 ===== 新增浮动UI样式 ===== */ + +/* 浮动头像 */ +.floating-avatar { + position: fixed; + right: 32rpx; + z-index: 1000; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.floating-avatar:active { + transform: scale(0.95); +} + +.floating-avatar .avatar-container { + width: 96rpx; + height: 96rpx; + position: relative; + border-radius: 50%; + overflow: hidden; + box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.4); + border: 6rpx solid rgba(255, 255, 255, 0.95); +} + +.floating-avatar .user-avatar { + width: 100%; + height: 100%; + border-radius: 50%; +} + +.floating-avatar .avatar-ring { + position: absolute; + top: -6rpx; + left: -6rpx; + right: -6rpx; + bottom: -6rpx; + border: 4rpx solid transparent; + border-radius: 50%; + background: linear-gradient(45deg, #667eea, #764ba2, #f093fb); + background-clip: border-box; + animation: avatar-ring-rotate 3s linear infinite; +} + +@keyframes avatar-ring-rotate { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +.floating-avatar .online-indicator { + position: absolute; + bottom: 8rpx; + right: 8rpx; + width: 24rpx; + height: 24rpx; + background: #27ae60; + border: 4rpx solid white; + border-radius: 50%; + box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2); + animation: online-pulse 2s ease-in-out infinite; +} + +@keyframes online-pulse { + + 0%, + 100% { + transform: scale(1); + } + + 50% { + transform: scale(1.1); + } +} + +/* 底部浮动按钮组 */ +.floating-buttons { + position: fixed; + left: 50%; + transform: translateX(-50%); + display: flex; + gap: 24rpx; + z-index: 1000; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(20rpx); + border-radius: 40rpx; + padding: 16rpx 40rpx; + box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05); + border: 2rpx solid rgba(255, 255, 255, 0.8); +} + +.floating-btn { + display: flex; + flex-direction: column; + align-items: center; + gap: 8rpx; + padding: 12rpx 24rpx; + background: transparent; + border-radius: 32rpx; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + position: relative; + overflow: hidden; + min-width: 100rpx; +} + +.floating-btn:active { + transform: scale(0.95); +} + +.floating-btn::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1)); + opacity: 0; + transition: opacity 0.3s ease; +} + +.floating-btn:active::before { + opacity: 1; +} + +.floating-btn .btn-icon { + position: relative; + width: 56rpx; + height: 56rpx; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + background: #667eea; + box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.2); + z-index: 2; +} + +.floating-btn .icon-emoji { + font-size: 32rpx; + color: white; + filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.2)); +} + +/* 移除图标光晕效果 */ + +/* 移除光晕动画 */ + +.floating-btn .btn-label { + font-size: 22rpx; + font-weight: 600; + color: #333; + z-index: 2; + position: relative; +} + +/* 🎨 现代化通知徽章 */ +.floating-btn .notification-badge { + position: absolute; + top: 8rpx; + right: 8rpx; + min-width: 40rpx; + height: 40rpx; + background: linear-gradient(145deg, #FF6B6B 0%, #FF8E8E 100%); + border-radius: 20rpx; + display: flex; + align-items: center; + justify-content: center; + border: 3rpx solid rgba(255, 255, 255, 0.9); + box-shadow: + 0 6rpx 20rpx rgba(255, 107, 107, 0.4), + 0 2rpx 8rpx rgba(255, 107, 107, 0.3), + inset 0 1rpx 0 rgba(255, 255, 255, 0.3); + z-index: 3; + animation: badgePulse 2s ease-in-out infinite; +} + +@keyframes badgePulse { + + 0%, + 100% { + transform: scale(1); + box-shadow: + 0 6rpx 20rpx rgba(255, 107, 107, 0.4), + 0 2rpx 8rpx rgba(255, 107, 107, 0.3), + inset 0 1rpx 0 rgba(255, 255, 255, 0.3); + } + + 50% { + transform: scale(1.1); + box-shadow: + 0 8rpx 24rpx rgba(255, 107, 107, 0.5), + 0 3rpx 12rpx rgba(255, 107, 107, 0.4), + inset 0 1rpx 0 rgba(255, 255, 255, 0.4); + } +} + +.floating-btn .badge-text { + font-size: 20rpx; + font-weight: 700; + color: white; + line-height: 1; + padding: 0 6rpx; + text-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.2); +} + +/* 按钮特定样式 */ +.friends-btn .btn-icon { + background: #2ed573; +} + +.messages-btn .btn-icon { + background: #667eea; +} + +/* 地点按钮 - 当前选中状态 */ +.floating-btn.messages-btn:nth-child(3) .btn-icon { + background: #ff9500; + box-shadow: 0 4rpx 16rpx rgba(255, 149, 0, 0.3); +} + +/* 侧边操作按钮 */ +.side-actions, +.right-actions { + position: fixed; + display: flex; + flex-direction: column; + gap: 24rpx; + z-index: 900; +} + +.side-actions { + left: 32rpx; +} + +.right-actions { + right: 32rpx; +} + +.action-btn { + width: 88rpx; + height: 88rpx; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(20rpx); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.12); + border: 2rpx solid rgba(255, 255, 255, 0.8); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + position: relative; + overflow: hidden; +} + +.action-btn:active { + transform: scale(0.9); + box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.16); +} + +.action-btn .action-icon { + font-size: 36rpx; + filter: drop-shadow(0 2rpx 4rpx rgba(0, 0, 0, 0.1)); + z-index: 2; + position: relative; +} + +.action-btn .btn-ripple { + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + border-radius: 50%; + background: rgba(102, 126, 234, 0.2); + transform: translate(-50%, -50%); + transition: all 0.3s ease; +} + +.action-btn:active .btn-ripple { + width: 120rpx; + height: 120rpx; +} + +/* 特定按钮样式 */ +.location-btn .action-icon { + color: #667eea; +} + +.layer-btn .action-icon { + color: #2ed573; +} + +.search-btn .action-icon { + color: #ff9500; +} + +.nearby-btn .action-icon { + color: #ff6b6b; +} + +.post-btn .action-icon { + color: #a55eea; +} + +.nearby-count { + position: absolute; + top: -8rpx; + right: -8rpx; + min-width: 32rpx; + height: 32rpx; + background: #ff4757; + border-radius: 16rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 18rpx; + font-weight: 700; + color: white; + border: 3rpx solid white; + box-shadow: 0 4rpx 12rpx rgba(255, 71, 87, 0.4); + z-index: 3; +} + +/* 响应式适配 */ +@media (max-width: 375px) { + .floating-avatar { + right: 24rpx; + } + + .floating-avatar .avatar-container { + width: 80rpx; + height: 80rpx; + } + + .floating-buttons { + gap: 24rpx; + } + + .floating-btn { + padding: 20rpx; + min-width: 100rpx; + } + + .floating-btn .btn-icon { + width: 56rpx; + height: 56rpx; + } + + .floating-btn .icon-emoji { + font-size: 28rpx; + } + + .side-actions, + .right-actions { + gap: 20rpx; + } + + .side-actions { + left: 24rpx; + } + + .right-actions { + right: 24rpx; + } + + .action-btn { + width: 72rpx; + height: 72rpx; + } + + .action-btn .action-icon { + font-size: 32rpx; + } +} + +/* 🔥 ===== 新增样式 ===== */ + +/* 用户头像通知小红点 */ +.user-avatar .notification-dot { + position: absolute; + top: 8rpx; + right: 8rpx; + width: 16rpx; + height: 16rpx; + background: #ff4757; + border: 3rpx solid white; + border-radius: 50%; + box-shadow: 0 4rpx 12rpx rgba(255, 71, 87, 0.4); + z-index: 10; + animation: notification-pulse 2s ease-in-out infinite; +} + +@keyframes notification-pulse { + + 0%, + 100% { + transform: scale(1); + opacity: 1; + } + + 50% { + transform: scale(1.2); + opacity: 0.8; + } +} + +/* 附近的人数量显示 */ +.right-controls .nearby-count { + position: absolute; + top: -8rpx; + right: -8rpx; + min-width: 32rpx; + height: 32rpx; + background: #ff4757; + border-radius: 16rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 18rpx; + font-weight: 700; + color: white; + border: 3rpx solid white; + box-shadow: 0 4rpx 12rpx rgba(255, 71, 87, 0.4); + z-index: 3; + padding: 0 6rpx; +} + +/* 附近的人按钮样式 */ +.right-controls .nearby-btn { + position: relative; +} + +.right-controls .nearby-icon { + font-size: 20px; + color: #ff6b6b; +} + +/* 深色模式适配 */ +@media (prefers-color-scheme: dark) { + + .floating-btn, + .action-btn { + background: rgba(42, 42, 42, 0.95); + border-color: rgba(255, 255, 255, 0.1); + } + + .floating-btn .btn-label { + color: #fff; + } + + .floating-avatar .avatar-container { + border-color: rgba(42, 42, 42, 0.95); + } + + .user-avatar .notification-dot, + .nearby-count { + border-color: rgba(42, 42, 42, 0.95); + } +} + +/* 📱 响应式设计 - 现代化导航适配 */ +@media screen and (max-width: 375px) { + + /* 小屏幕适配 */ + .floating-buttons { + gap: 32rpx; + } + + .floating-btn { + min-width: 120rpx; + padding: 24rpx 20rpx; + } + + .floating-btn .btn-icon { + width: 64rpx; + height: 64rpx; + } + + .floating-btn .icon-emoji { + font-size: 32rpx; + } + + .floating-btn .btn-label { + font-size: 24rpx; + } + + .avatar-container { + width: 80rpx; + height: 80rpx; + } + + .avatar-text { + font-size: 28rpx; + } + + .online-dot { + width: 20rpx; + height: 20rpx; + } +} + +@media screen and (min-width: 414px) { + + /* 大屏幕优化 */ + .floating-buttons { + gap: 48rpx; + } + + .floating-btn { + min-width: 160rpx; + padding: 32rpx 28rpx; + } + + .floating-btn .btn-icon { + width: 80rpx; + height: 80rpx; + } + + .floating-btn .icon-emoji { + font-size: 40rpx; + } + + .floating-btn .btn-label { + font-size: 28rpx; + } + + .avatar-container { + width: 96rpx; + height: 96rpx; + } + + .avatar-text { + font-size: 36rpx; + } + + .online-dot { + width: 28rpx; + height: 28rpx; + } +} + +/* 🎨 特殊设备适配 */ +@media screen and (max-height: 667px) { + + /* iPhone SE等小屏设备 */ + .floating-buttons { + bottom: calc(env(safe-area-inset-bottom) + 32rpx) !important; + } +} + +@media screen and (min-height: 812px) { + + /* iPhone X及以上设备 */ + .floating-buttons { + bottom: calc(env(safe-area-inset-bottom) + 48rpx) !important; + } +} + +/* 🎨 横屏适配 */ +@media screen and (orientation: landscape) { + .floating-buttons { + gap: 24rpx; + bottom: calc(env(safe-area-inset-bottom) + 24rpx) !important; + } + + .floating-btn { + min-width: 100rpx; + padding: 20rpx 16rpx; + } + + .floating-btn .btn-label { + font-size: 22rpx; + } + + .avatar-container { + width: 72rpx; + height: 72rpx; + } + + .avatar-text { + font-size: 26rpx; + } +} + +.remind-slider-block { + margin: 18px 0 8px 0; + display: flex; + align-items: center; + gap: 10px; +} + +.remind-label { + font-size: 15px; + color: #333; + margin-right: 8px; +} + +.remind-value { + font-size: 15px; + color: #667eea; + margin-left: 8px; + font-weight: 600; +} + +.remind-desc { + font-size: 13px; + color: #888; + margin-top: 8px; + text-align: left; +} + +.remind-title-block { + margin-bottom: 8px; + text-align: left; +} + +.remind-title { + font-size: 18px; + font-weight: 700; + color: #333; + display: block; +} + +.remind-subtitle { + font-size: 13px; + color: #888; + margin-top: 2px; + display: block; +} + +.remind-friends-mode-row { + display: flex; + align-items: flex-end; + justify-content: space-between; + gap: 12px; + margin-bottom: 10px; +} + +.remind-friends-block { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 4px; +} + +.remind-friends-avatars { + display: flex; + gap: 4px; + margin-top: 2px; +} + +.avatar-placeholder { + background: #f0f0f0; + color: #bbb; +} + +.remind-mode-block { + display: flex; + align-items: center; + gap: 8px; +} + +.remind-mode-radio { + display: flex; + gap: 8px; +} + +.remind-mode-label { + font-size: 14px; + color: #333; + margin-right: 8px; + display: flex; + align-items: center; + gap: 2px; +} + +.remind-value.highlight { + color: #ff9500; + font-size: 17px; + font-weight: 700; +} + +.remind-mode-checkbox { + display: flex; + gap: 8px; +} + +/* 好友选择弹窗样式 */ +.friend-select-modal { + z-index: 20000; + position: fixed; + left: 0; + top: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.45); + display: flex; + align-items: center; + justify-content: center; +} + +.friend-select-content { + background: #fff; + border-radius: 18px; + width: 320px; + max-width: 90vw; + max-height: 70vh; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18); + display: flex; + flex-direction: column; + align-items: stretch; + padding: 20px 16px 12px 16px; +} + +.friend-select-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; +} + +.friend-select-title { + font-size: 18px; + font-weight: 700; + color: #333; + flex: 1; + text-align: left; +} + +.friend-select-close { + font-size: 22px; + color: #888; + padding: 0 8px; + cursor: pointer; + transition: color 0.2s; +} + +.friend-select-close:active { + color: #ff4757; +} + + +/* 好友选择弹窗美化 */ +.share-friends-list { + /* 确保滚动容器有足够内边距,避免内容贴边 */ + padding: 0 10px; +} + +.friend-list-scroll { + max-height: 45vh; + padding-bottom: 8px; +} + +.result-info-title { + color: #fff; + margin-top: 20px; + padding: 0 10px; + /* 与内容区对齐 */ +} + +.friend-item { + display: flex; + align-items: center; + padding: 10px; + border-radius: 10px; + margin-bottom: 8px; + background: transparent; + position: relative; + cursor: pointer; + /* 关键:使用justify-content: space-between实现两端对齐 */ + justify-content: space-between; + /* 固定左右内边距,确保文字长时两侧距离相等 */ + margin-left: auto; + margin-right: auto; + width: calc(100% - 20px); + /* 减去左右间距,确保居中对齐 */ +} + +/* 增加交互反馈 */ +.friend-item:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.friend-avatar { + width: 80px; + height: 80px; + border-radius: 10%; + /* 取消底部margin,改为右侧margin与文字分隔 */ + margin-right: 15px; + flex-shrink: 0; + /* 头像不压缩 */ +} + +.friend-name { + /* 使用rpx保持移动端适配一致性 */ + width: 70px; + font-size: 24rpx; + color: #fff; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + /* 关键:文字区域自适应,通过容器padding控制两侧距离 */ + padding-right: 15px; + /* 与头像左侧间距保持一致 */ + flex-grow: 1; + /* 文字区域占满剩余空间 */ + text-align: left; + /* 确保文字左对齐 */ +} + + +.friend-item:active { + transform: scale(0.97); + box-shadow: 0 2px 8px rgba(24, 144, 255, 0.10); +} + +.friend-item.selected { + background: #e6f7ff; + border: 1.5px solid #1890ff; + box-shadow: 0 2px 12px rgba(24, 144, 255, 0.10); +} + +.friend-item.selected .friend-avatar, +.friend-item.selected .friend-avatar-txt { + border: 2.5px solid #1890ff; + box-shadow: 0 0 0 2px #bae7ff; +} + +.friend-item.disabled { + background: #f5f5f5; + color: #bbb; + cursor: not-allowed; + opacity: 0.7; +} + +.friend-item.disabled .friend-avatar, +.friend-item.disabled .friend-avatar-txt { + filter: grayscale(1); + border: 2px solid #eee; +} + +.friend-avatar, +.friend-avatar-txt { + width: 36px; + height: 36px; + border-radius: 50%; + margin-right: 12px; + background: #f0f0f0; + display: flex; + align-items: center; + justify-content: center; + font-size: 16px; + color: #888; + font-weight: 600; + border: 2px solid #f0f0f0; + transition: border 0.18s, box-shadow 0.18s, filter 0.18s; +} + +.friend-nickname { + font-size: 15px; + color: #222; + font-weight: 500; + flex: 1; + letter-spacing: 0.5px; +} + +.friend-item.selected .friend-nickname { + color: #1890ff; +} + +.friend-check { + margin-left: auto; + color: #1890ff; + font-size: 18px; + font-weight: bold; + background: #fff; + border-radius: 50%; + width: 26px; + height: 26px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 1px 4px rgba(24, 144, 255, 0.08); + border: 2px solid #e6f7ff; + transition: background 0.18s, color 0.18s, border 0.18s; +} + +.friend-item.selected .friend-check { + background: #1890ff; + color: #fff; + border: 2px solid #fff; +} + +.friend-item.disabled .friend-check { + background: #eee; + color: #bbb; + border: 2px solid #eee; +} + +.friend-selected-row { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 10px; + min-height: 40px; +} + +.friend-selected-avatar { + width: 36px; + height: 36px; + border-radius: 50%; + background: #f0f0f0; + display: flex; + align-items: center; + justify-content: center; + position: relative; + font-size: 18px; + color: #888; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.08); + border: 2px solid #667eea; + cursor: pointer; + transition: box-shadow 0.2s; +} + +.friend-selected-avatar:active { + box-shadow: 0 4px 16px rgba(102, 126, 234, 0.18); +} + +.friend-selected-remove { + position: absolute; + top: -8px; + right: -8px; + width: 18px; + height: 18px; + background: #ff4757; + color: #fff; + border-radius: 50%; + font-size: 13px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 8px rgba(255, 71, 87, 0.18); + border: 2px solid #fff; +} + +.friend-selected-placeholder { + background: #f8f8f8; + color: #bbb; + border: 2px dashed #ddd; +} + +.friend-search-input { + width: 100%; + height: 32px; + border: 1px solid #e0e0e0; + border-radius: 8px; + padding: 0 12px; + font-size: 15px; + margin-bottom: 10px; + outline: none; + box-sizing: border-box; +} + +.friend-select-done[disabled] { + background: #eee !important; + color: #bbb !important; + border: none; +} + +.card-actions-right { + display: flex; + align-items: center; + gap: 8px; + position: absolute; + right: 12px; + top: 20px; +} + +.remind-save-btn { + padding: 0 14px; + height: 28px; + line-height: 28px; + font-size: 14px; + border-radius: 14px; + margin-right: 2px; +} + +/* 底部导航栏 */ +.bottom-tab-bar { + position: fixed; + left: 0; + right: 0; + bottom: 0; + height: 56px; + background: #fff; + display: flex; + align-items: center; + justify-content: space-around; + box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.06); + z-index: 10001; +} + +.tab-btn { + flex: 1; + height: 40px; + margin: 0 8px; + border: none; + background: none; + font-size: 16px; + color: #666; + border-radius: 20px; + transition: background 0.2s; +} + +.tab-btn:active { + background: #f0f4ff; + color: #1890ff; +} + +/* 地点标记弹窗美化 */ +.location-mark-modal { + z-index: 20000; + position: fixed; + left: 0; + top: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.45); + display: flex; + align-items: center; + justify-content: center; +} + +.location-mark-content { + background: #fff; + border-radius: 24px; + width: 370px; + max-width: 96vw; + max-height: 80vh; + box-shadow: 0 12px 40px rgba(24, 144, 255, 0.10), 0 2px 8px rgba(0, 0, 0, 0.10); + display: flex; + flex-direction: column; + padding: 0 0 18px 0; + overflow: hidden; +} + +.location-mark-header { + position: relative; + display: flex; + align-items: center; + justify-content: center; + height: 56px; + background: #f8fbff; +} + +.location-mark-title { + font-size: 20px; + font-weight: 700; + color: #222; + letter-spacing: 1px; +} + +.location-mark-close { + position: absolute; + right: 18px; + top: 50%; + transform: translateY(-50%); + font-size: 22px; + color: #bbb; + padding: 4px 8px; + border-radius: 50%; + cursor: pointer; + transition: background 0.2s, color 0.2s; +} + +.location-mark-close:active { + background: #f0f4ff; + color: #ff4757; +} + +.location-mark-divider { + height: 1px; + background: #f0f4ff; + margin: 0 0 8px 0; +} + +.location-mark-search-row { + display: flex; + align-items: center; + background: #f4f7fa; + border-radius: 18px; + margin: 16px 18px 10px 18px; + padding: 0 10px; + box-shadow: 0 1px 4px rgba(24, 144, 255, 0.04); + position: relative; +} + +.search-icon { + font-size: 15px; + color: #b0b8c7; +} + +.location-mark-search { + flex: 1; + height: 36px; + border: none; + background: transparent; + font-size: 15px; + outline: none; + padding: 0 4px; +} + +.clear-icon { + font-size: 16px; + color: #b0b8c7; + margin-left: 4px; + cursor: pointer; + transition: color 0.2s; +} + +.clear-icon:active { + color: #ff4757; +} + +.location-mark-list { + flex: 1; + min-height: 120px; + max-height: 340px; + overflow-y: auto; + padding: 0 12px 0 12px; +} + +.location-mark-item-card { + background: #fff; + border-radius: 16px; + box-shadow: 0 2px 12px rgba(24, 144, 255, 0.06); + margin-bottom: 16px; + padding: 0 0 0 0; + transition: box-shadow 0.2s; + display: flex; + flex-direction: column; +} + +.location-mark-item-card:active { + box-shadow: 0 4px 18px rgba(24, 144, 255, 0.13); +} + +.location-mark-item-main { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 16px 16px 10px 16px; +} + +.location-mark-item-info { + flex: 1; + min-width: 0; +} + +.location-mark-name-row { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 2px; +} + +.location-mark-name { + font-size: 17px; + font-weight: 700; + color: #1890ff; + max-width: 110px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.location-mark-edit-btn, +.location-mark-del-btn { + font-size: 13px; + padding: 0 8px; + height: 24px; + line-height: 24px; + border-radius: 12px; + margin-left: 2px; + display: flex; + align-items: center; + border: none; + background: #f4f7fa; + color: #1890ff; + transition: background 0.2s, color 0.2s; +} + +.location-mark-edit-btn:active { + background: #e6f7ff; + color: #1761a0; +} + +.location-mark-del-btn { + color: #ff4757; + background: #fff0f0; +} + +.location-mark-del-btn:active { + background: #ffeaea; + color: #c82333; +} + +.location-mark-edit-btn .iconfont, +.location-mark-del-btn .iconfont { + font-size: 15px; + margin-right: 2px; +} + +.location-mark-coord { + font-size: 13px; + color: #888; + overflow: hidden; + margin-top: 2px; +} + +.location-mark-meta { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 8px; + margin-left: 14px; +} + +.location-mark-friends { + display: flex; + align-items: center; + gap: 2px; +} + +.location-mark-friend-avatar { + width: 28px; + height: 28px; + border-radius: 50%; + background: #f0f0f0; + border: 1.5px solid #fff; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); + display: flex; + align-items: center; + justify-content: center; + font-size: 15px; + color: #888; + font-weight: 600; + overflow: hidden; +} + +.location-mark-friend-avatar image { + width: 100%; + height: 100%; + border-radius: 50%; +} + +.location-mark-friend-btn { + width: 28px; + height: 28px; + border-radius: 50%; + background: #e6f7ff; + color: #1890ff; + font-size: 20px; + line-height: 28px; + padding: 0; + border: none; + margin-left: 2px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 1px 4px rgba(24, 144, 255, 0.08); + transition: background 0.2s, color 0.2s; + cursor: pointer; +} + +.location-mark-friend-btn:active { + background: #bae7ff; + color: #1761a0; +} + +.location-mark-type-tag { + font-size: 13px; + color: #fff; + border-radius: 12px; + padding: 3px 16px; + cursor: pointer; + user-select: none; + font-weight: 600; + box-shadow: 0 1px 4px rgba(24, 144, 255, 0.08); + transition: background 0.2s; + margin-top: 4px; +} + +.location-mark-type-tag.arrive { + background: linear-gradient(90deg, #1890ff 60%, #40a9ff 100%); +} + +.location-mark-type-tag.leave { + background: linear-gradient(90deg, #faad14 60%, #ffd666 100%); + color: #fff; +} + +.location-mark-type-tag:active { + filter: brightness(0.92); +} + +.location-mark-empty { + text-align: center; + color: #bbb; + font-size: 16px; + margin-top: 60px; + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; +} + +.empty-icon { + font-size: 38px; + color: #e6f7ff; + margin-bottom: 2px; +} + +/* 遮罩层 */ +.location-mark-mask { + position: fixed; + left: 0; + top: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.45); + z-index: 20000; +} + +/* 弹窗内容区 */ +.location-mark-dialog { + position: fixed; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + background: #fff; + border-radius: 24px; + width: 370px; + max-width: 96vw; + max-height: 80vh; + box-shadow: 0 12px 40px rgba(24, 144, 255, 0.10), 0 2px 8px rgba(0, 0, 0, 0.10); + display: flex; + flex-direction: column; + padding: 0 0 18px 0; + overflow: hidden; + z-index: 20001; + animation: locationMarkDialogFadeIn 0.25s cubic-bezier(.4, 0, .2, 1); +} + +/* 弹窗动画 */ +@keyframes locationMarkDialogFadeIn { + 0% { + opacity: 0; + transform: translate(-50%, -46%) scale(0.96); + } + + 100% { + opacity: 1; + transform: translate(-50%, -50%) scale(1); + } +} + +.location-mark-dialog-animate { + animation: locationMarkDialogFadeIn 0.25s cubic-bezier(.4, 0, .2, 1); +} + +/* 底部弹出卡片样式 */ +.location-mark-sheet { + position: fixed; + left: 0; + right: 0; + bottom: 0; + background: #fff; + border-top-left-radius: 22px; + border-top-right-radius: 22px; + box-shadow: 0 -8px 32px rgba(24, 144, 255, 0.10), 0 -2px 8px rgba(0, 0, 0, 0.10); + z-index: 20001; + width: 100vw; + max-width: 100vw; + min-height: 220px; + max-height: 80vh; + display: flex; + flex-direction: column; + animation: locationMarkSheetSlideIn 0.28s cubic-bezier(.4, 0, .2, 1); +} + +@keyframes locationMarkSheetSlideIn { + 0% { + transform: translateY(60px); + opacity: 0; + } + + 100% { + transform: translateY(0); + opacity: 1; + } +} + +.location-mark-sheet-animate { + animation: locationMarkSheetSlideIn 0.28s cubic-bezier(.4, 0, .2, 1); +} + +.location-mark-sheet-handle-row { + display: flex; + align-items: center; + justify-content: space-between; + height: 32px; + padding: 0 12px 0 0; + position: relative; +} + +.location-mark-sheet-handle { + width: 44px; + height: 5px; + border-radius: 3px; + background: #e6eaf0; + margin: 10px auto 0 auto; +} + +.location-mark-sheet-close { + position: absolute; + right: 16px; + top: 8px; + font-size: 22px; + color: #bbb; + padding: 4px 8px; + border-radius: 50%; + cursor: pointer; + transition: background 0.2s, color 0.2s; + z-index: 1; +} + +.location-mark-sheet-close:active { + background: #f0f4ff; + color: #ff4757; +} + +.location-mark-sheet-title { + font-size: 18px; + font-weight: 700; + color: #222; + text-align: center; + margin-bottom: 6px; +} + +.location-mark-list-sheet { + flex: 1; + min-height: 120px; + max-height: 54vh; + overflow-y: auto; + padding: 0 12px 0 12px; +} + +/* 兼容原有卡片内容美化样式 */ + +/* POI提醒操作弹窗名称可编辑样式 */ +.card-name-editable { + margin-bottom: 2px; +} + +.card-name-input { + font-size: 17px; + font-weight: 700; + color: #222; + border: none; + background: transparent; + outline: none; + width: 100%; + padding: 0 0 2px 0; + border-bottom: 1.5px solid #e6eaf0; + transition: border-color 0.2s; +} + +.card-name-input:focus { + border-bottom: 1.5px solid #1890ff; +} + +.card-name-tip { + font-size: 12px; + color: #b0b8c7; + margin-top: 2px; + margin-left: 2px; +} + +/* 优化后的地点标记卡片布局 */ +.location-mark-item-card { + cursor: pointer; + transition: all 0.2s ease; + border-radius: 12px; + margin-bottom: 8px; + background: #fff; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + border: 1px solid #f0f0f0; +} + +.location-mark-item-card:active { + transform: scale(0.98); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1); + background: #f8f9fa; +} + +.location-mark-item-main-opt { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 16px 16px 6px 16px; +} + +.location-mark-item-info-opt { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + justify-content: center; +} + +.location-mark-name-opt { + font-size: 17px; + font-weight: 700; + color: #1890ff; + max-width: 140px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.location-mark-coord-opt { + font-size: 12px; + color: #b0b8c7; + margin-top: 2px; + max-width: 140px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.location-mark-actions-opt { + display: flex; + align-items: flex-start; + gap: 6px; + margin-left: 12px; +} + +.location-mark-edit-btn-opt, +.location-mark-del-btn-opt { + font-size: 13px; + padding: 0 8px; + height: 24px; + line-height: 24px; + border-radius: 12px; + display: flex; + align-items: center; + border: none; + background: #f4f7fa; + color: #1890ff; + transition: background 0.2s, color 0.2s; +} + +.location-mark-edit-btn-opt:active { + background: #e6f7ff; + color: #1761a0; +} + +.location-mark-del-btn-opt { + color: #ff4757; + background: #fff0f0; +} + +.location-mark-del-btn-opt:active { + background: #ffeaea; + color: #c82333; +} + +.location-mark-edit-btn-opt .iconfont, +.location-mark-del-btn-opt .iconfont { + font-size: 15px; + margin-right: 2px; +} + +.location-mark-meta-opt { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 16px 12px 16px; + gap: 8px; +} + +.location-mark-friends-opt { + display: flex; + align-items: center; + gap: 2px; +} + +.location-mark-friend-avatar-opt { + width: 22px; + height: 22px; + border-radius: 50%; + background: #f0f0f0; + border: 1.5px solid #fff; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + color: #888; + font-weight: 600; + overflow: hidden; +} + +.location-mark-friend-avatar-opt image { + width: 100%; + height: 100%; + border-radius: 50%; +} + +.location-mark-friend-btn-opt { + width: 22px; + height: 22px; + border-radius: 50%; + background: #e6f7ff; + color: #1890ff; + font-size: 16px; + line-height: 22px; + padding: 0; + border: none; + margin-left: 2px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 1px 4px rgba(24, 144, 255, 0.08); + transition: background 0.2s, color 0.2s; + cursor: pointer; +} + +.location-mark-friend-btn-opt:active { + background: #bae7ff; + color: #1761a0; +} + +.location-mark-type-tag-opt { + font-size: 12px; + color: #fff; + border-radius: 10px; + padding: 2px 12px; + cursor: pointer; + user-select: none; + font-weight: 600; + box-shadow: 0 1px 4px rgba(24, 144, 255, 0.08); + transition: background 0.2s; + margin-left: 8px; +} + +.location-mark-type-tag-opt.arrive { + background: linear-gradient(90deg, #1890ff 60%, #40a9ff 100%); +} + +.location-mark-type-tag-opt.leave { + background: linear-gradient(90deg, #faad14 60%, #ffd666 100%); + color: #fff; +} + +.location-mark-type-tag-opt:active { + filter: brightness(0.92); +} + +/* 地点标记浮动按钮 */ +.location-mark-fab { + position: absolute; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + width: 56px; + height: 56px; + border-radius: 50%; + background: linear-gradient(135deg, #1890ff 0%, #40a9ff 100%); + box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + z-index: 10; +} + +.location-mark-fab:active { + transform: translateX(-50%) scale(0.95); + box-shadow: 0 2px 8px rgba(24, 144, 255, 0.4); + background: linear-gradient(135deg, #1761a0 0%, #1890ff 100%); +} + +.location-mark-fab-icon { + font-size: 28px; + font-weight: 300; + color: #fff; + line-height: 1; + user-select: none; + transition: transform 0.2s ease; +} + +.location-mark-fab:active .location-mark-fab-icon { + transform: rotate(45deg); +} + +/*POI周边列表弹窗*/ +.poi-around-modal { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 9999; + display: flex; + align-items: flex-end; + justify-content: center; + font-family: "PingFang SC", "Microsoft YaHei", Arial, sans-serif; +} + +.poi-around-mask { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.32); +} + +.poi-around-sheet { + position: relative; + width: 92vw; + max-width: 500px; + background: #fff; + border-radius: 18px 18px 0 0; + padding: 24px 18px 18px 18px; + box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.10); + z-index: 1; + min-height: 220px; + animation: popUpSheet 0.25s cubic-bezier(.4, 1.4, .6, 1) 1; +} + +@keyframes popUpSheet { + from { + transform: translateY(100px); + opacity: 0; + } + + to { + transform: translateY(0); + opacity: 1; + } +} + +.poi-around-close-x { + position: absolute; + top: 14px; + right: 14px; + width: 32px; + height: 32px; + background: #f5f6fa; + border-radius: 50%; + color: #888; + font-size: 20px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.2s, color 0.2s; + z-index: 2; +} + +.poi-around-close-x:active { + background: #e6eaf0; + color: #1890ff; +} + +.poi-around-title { + font-size: 19px; + font-weight: bold; + margin-bottom: 16px; + text-align: center; + letter-spacing: 1px; + color: #222; +} + +.poi-around-list { + max-height: 52vh; + overflow-y: auto; + margin-bottom: 10px; +} + +.poi-around-item { + padding: 14px 0 10px 0; + border-bottom: 1px solid #f0f0f0; + cursor: pointer; + transition: background 0.18s; + border-radius: 8px; +} + +.poi-around-item:active { + background: #f5f8ff; +} + +.poi-around-name { + font-size: 16px; + font-weight: 600; + color: #1890ff; + margin-bottom: 2px; + word-break: break-all; +} + +.poi-around-address { + font-size: 13px; + color: #888; + margin-top: 1px; + word-break: break-all; +} + +.poi-around-distance { + font-size: 13px; + color: #faad14; + margin-top: 2px; +} + +.poi-around-close-btn { + margin: 18px auto 0 auto; + width: 90px; + text-align: center; + background: #f5f5f5; + border-radius: 10px; + padding: 10px 0; + color: #666; + font-size: 15px; + letter-spacing: 1px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04); + transition: background 0.2s, color 0.2s; +} + +.poi-around-close-btn:active { + background: #e6eaf0; + color: #1890ff; +} + +.poi-around-empty { + text-align: center; + color: #bbb; + padding: 32px 0; + font-size: 15px; +} + +/**搜索结果信息**/ +.result-info-modal { + position: fixed; + left: 0; + right: 0; + bottom: 0; + z-index: 999999; + display: flex; + justify-content: center; + align-items: flex-end; +} + +.merchant-info-meta-text { + font-size: 20px; + color: #ffffff; +} + +.merchant-info-meta-content { + margin-top: 10rpx; + font-size: 12px; + color: #ffffff; +} + +.result-info-card { + width: 100%; + background: #1C1C1E; + border-radius: 20px 20px 0 0; + box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.10); + padding: 0px 20px 18px 20px; + margin-bottom: env(safe-area-inset-bottom); + position: relative; + animation: slideUp 0.25s; +} + +/**商家信息**/ +.merchant-info-modal { + position: fixed; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + background: rgba(0, 0, 0, 0.3); + display: flex; + justify-content: center; + align-items: flex-end; + /* 为安卓设备提供足够的底部间距,避免内容被遮挡 */ + /* 在安卓上 env(safe-area-inset-bottom) 会返回 0,所以最小间距是 160rpx */ + padding-bottom: calc(40rpx + env(safe-area-inset-bottom) + 140rpx); +} + +.merchant-info-card { + width: 92vw; + background: linear-gradient(180deg, #ffffff 0%, #fafafa 100%); + border-radius: 32rpx; + box-shadow: 0 -12rpx 60rpx rgba(0, 0, 0, 0.15); + padding: 48rpx 40rpx 40rpx; + /* 移除 margin-bottom,改用父容器的 padding-bottom 来提供间距 */ + position: relative; + animation: slideUp 0.3s ease-out; + max-height: 70vh; + overflow-y: auto; +} + +@keyframes slideUp { + from { + transform: translateY(100%); + } + + to { + transform: translateY(0); + } +} + +.close-btn-abs { + position: absolute; + top: 14rpx; + right: 14rpx; + background: rgba(207, 207, 207, 0.95); + border: 2rpx solid rgba(0, 0, 0, 0.08); + border-radius: 50%; + width: 64rpx; + height: 64rpx; + line-height: 64rpx; + font-size: 44rpx; + display: flex; + align-items: center; + justify-content: center; + z-index: 10; + box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08); + padding: 0; + transition: all 0.2s ease; +} + +.close-btn-abs .close-icon { + color: #666; + font-size: 40rpx; + font-weight: 300; +} + +.close-btn-abs:active { + background: rgba(0, 0, 0, 0.05); + transform: scale(0.95); +} + +/* 菜品信息容器 */ +.dish-info-container { + display: flex; + flex-direction: column; + gap: 32rpx; + margin-top: 8rpx; + width: 100%; +} +.dish-image-row{ + display: flex; + gap: 24rpx; + align-items: flex-start; +} +.dish-description{ + font-size: 28rpx; + color: #666; + display: block; /* 确保文本元素正确显示 */ + width: 100%; + line-height: 1.6; +} +.dish-description-row{ + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; /* 最多显示2行 */ + line-clamp: 2; /* 标准属性,提升兼容性 */ + text-overflow: ellipsis; + word-break: break-all; + line-height: 1.6; + max-height: calc(1.6em * 2); /* 限制最大高度为2行 */ + margin-top: 4rpx; +} +/* 左侧:菜品宣传图 */ +.dish-image { + width: 220rpx; + height: 220rpx; + border-radius: 20rpx; + background: linear-gradient(135deg, #f5f5f5 0%, #e8e8e8 100%); + flex-shrink: 0; + box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08); + overflow: hidden; +} + +/* 右侧:菜品详情 */ +.dish-detail { + flex: 1; + min-width: 0; /* 允许 flex 子元素收缩 */ + display: flex; + flex-direction: column; + gap: 16rpx; + overflow: hidden; /* 防止内容溢出 */ + padding-top: 4rpx; +} + +/* 第一行:标题 */ +.dish-title-row { + display: flex; + align-items: flex-start; + min-width: 0; + width: 100%; +} + +.dish-title { + font-size: 36rpx; + font-weight: 700; + color: #2c3e50; + line-height: 1.5; + width: 100%; + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; /* 最多显示2行 */ + line-clamp: 2; /* 标准属性,提升兼容性 */ + text-overflow: ellipsis; + word-break: break-all; + max-height: calc(1.5em * 2); /* 限制最大高度为2行 */ + letter-spacing: 0.5rpx; +} + +/* 第二行:销售数据和排名 */ +.dish-sales-row { + display: flex; + align-items: center; + gap: 24rpx; + flex-wrap: wrap; +} +.dish-info-address{ + font-size: 26rpx; + color: #666; + margin-top: 8rpx; + display: block; /* 确保文本元素正确显示 */ + width: 100%; + padding: 16rpx 20rpx; + background: linear-gradient(135deg, #f8f9fa 0%, #f1f3f5 100%); + border-radius: 16rpx; + border: 1rpx solid rgba(0, 0, 0, 0.05); + line-height: 1.6; + word-break: break-all; +} + +.dish-sales { + font-size: 24rpx; + color: #666; + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + border-radius: 12rpx; + padding: 8rpx 16rpx; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex-shrink: 1; /* 允许收缩 */ + min-width: 0; + border: 1rpx solid rgba(0, 0, 0, 0.05); +} + +.dish-ranking { + font-size: 24rpx; + color: #ff6f3c; + background: linear-gradient(135deg, #fff5f2 0%, #ffe5d9 100%); + border-radius: 12rpx; + padding: 8rpx 16rpx; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex-shrink: 1; /* 允许收缩 */ + min-width: 0; + border: 1rpx solid rgba(255, 111, 60, 0.2); + font-weight: 500; +} + +/* 第三行:评分和店铺信息 */ +.dish-rating-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16rpx; + flex-wrap: nowrap; + min-width: 0; /* 允许 flex 子元素收缩 */ + overflow: hidden; /* 防止内容溢出 */ +} + +.dish-rating-left { + display: flex; + align-items: center; + gap: 16rpx; + flex: 1; + min-width: 0; /* 允许 flex 子元素收缩 */ + overflow: hidden; /* 防止内容溢出 */ +} + +.dish-rating { + font-size: 28rpx; + color: #ff6f3c; + font-weight: 700; + flex-shrink: 0; /* 评分不压缩 */ + display: flex; + align-items: center; +} + +.dish-shop-name { + font-size: 26rpx; + color: #666; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + min-width: 0; /* 允许 flex 子元素收缩 */ + padding-left: 12rpx; + border-left: 2rpx solid #e0e0e0; +} + +.dish-district { + font-size: 24rpx; + color: #999; + margin-left: auto; + flex-shrink: 0; /* 防止被压缩 */ + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 200rpx; /* 限制最大宽度 */ + background: #f5f5f5; + padding: 6rpx 12rpx; + border-radius: 8rpx; +} + +/* 第四行:价格信息 */ +.dish-price-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16rpx; + flex-wrap: nowrap; + margin-top: 12rpx; + padding: 24rpx 20rpx; + background: linear-gradient(135deg, #f5e9e9 0%, #ffffff 100%); + border-radius: 20rpx; + border: 1rpx solid rgba(255, 111, 60, 0.15); + position: relative; + min-width: 0; /* 允许 flex 子元素收缩 */ + overflow: hidden; /* 防止内容溢出 */ +} + +.dish-price-left { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8rpx; + flex: 1; + min-width: 0; /* 允许 flex 子元素收缩 */ + flex-wrap: nowrap; + z-index: 2; + margin-right: 100rpx; + overflow: hidden; /* 防止内容溢出 */ +} + +.dish-group-price { + font-size: 42rpx; + font-weight: 700; + color: #ff6f3c; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + line-height: 1.2; + letter-spacing: 1rpx; +} + +.dish-discount { + font-size: 24rpx; + color: #ff6f3c; + background: linear-gradient(135deg, #fff5f2 0%, #ffe5d9 100%); + border-radius: 10rpx; + padding: 6rpx 14rpx; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: fit-content; + border: 1rpx solid rgba(255, 111, 60, 0.2); + font-weight: 500; + margin-top: 8rpx; +} + +.dish-original-price { + font-size: 24rpx; + color: #999; + text-decoration: line-through; +} + +.dish-go-btn { + width: 180rpx; + height: 80rpx; + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%); + flex-shrink: 0; + z-index: 1; + filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.1)); + transition: transform 0.2s ease; +} + +.dish-buy-btn { + background: linear-gradient(135deg, #ff6f3c 0%, #ff8c5a 100%); + color: #fff; + border: none; + border-radius: 40rpx; + padding: 2rpx 40rpx; + font-size: 28rpx; + font-weight: 600; + margin-left: auto; + box-shadow: 0 4rpx 16rpx rgba(255, 111, 60, 0.3); +} + +.dish-buy-btn:active { + opacity: 0.8; +} + +.merchant-info-header { + display: flex; + justify-content: flex-start; + align-items: center; + margin-bottom: 2px; +} + +.merchant-name { + font-size: 20px; + font-weight: bold; + color: #222; + flex: 1; + line-height: 1.2; +} + +.merchant-info-row { + margin: 8px 0 0 0; + color: #666; + font-size: 14px; + display: flex; + flex-wrap: wrap; + gap: 12px; +} + +.merchant-info-meta { + margin-top: 2px; + color: #999; + font-size: 13px; +} + +.merchant-address { + color: #fff; + font-size: 15px; + font-weight: 500; +} + +.merchant-packages { + margin: 16px 0 8px 0; +} + +.package-card { + background: #f7f8fa; + border-radius: 12px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.03); + padding: 12px 14px 10px 14px; + margin-bottom: 10px; + display: flex; + flex-direction: column; + transition: box-shadow 0.2s; +} + +.package-card-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2px; +} + +.package-title { + font-weight: 600; + font-size: 15px; + color: #333; +} + +.package-price { + color: #1aad19; + font-weight: bold; + font-size: 15px; +} + +.package-desc { + color: #888; + font-size: 13px; + margin-top: 2px; +} + +.merchant-actions { + display: flex; + justify-content: flex-start; + margin-top: 14px; + gap: 10px; +} + + + +.merchant-navigation-img { + width: 80rpx; + /* 图标宽度 */ + height: 80rpx; + /* 图标高度 */ + margin-bottom: 10rpx; + /* 图标与文字的间距 */ +} + +.action-text-navigation { + font-size: 24rpx; + /* 文字大小 */ + color: #fff; + /* 文字颜色 */ + text-align: center; + /* 文字自身居中(增强对齐效果) */ +} + +.share-friends-scroll { + /* 容器样式,根据需要调整 */ + padding: 16px; +} + +.share-friends-list-share { + /* 滚动容器不换行 */ + white-space: nowrap; + /* 移除滚动条但保留功能(可选) */ + scrollbar-width: none; + -webkit-overflow-scrolling: touch; + /* 平滑滚动 */ +} + +/* 隐藏滚动条 */ +.share-friends-list-share::-webkit-scrollbar { + display: none; +} + +.friend-item-share { + /* 每个好友项 inline-block 确保横向排列 */ + display: inline-block; + /* 文本居中对齐 */ + text-align: center; + /* 项之间的间距 */ + margin-right: 20px; +} + +.avatar-container-share { + /* 头像容器固定宽度,确保对齐 */ + width: 64px; + height: 64px; + margin: 0 auto; + /* 水平居中 */ +} + +.friend-avatar-share { + /* 头像样式 */ + width: 100%; + height: 100%; + border-radius: 10%; + /* 圆形头像 */ + display: block; +} + +.friend-name-share { + /* 文本样式 */ + display: inline-block; + max-width: 80px; + /* 最大宽度,根据需要调整 */ + margin-top: 8px; + font-size: 14px; + color: #fff; + /* 文字超出时显示省略号 */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + /* 关键:左右内边距相等,确保对称 */ + padding: 0 8px; + /* 计算宽度确保整体居中 */ + box-sizing: border-box; +} + +.merchant-actions-img { + height: 25px; + width: 60px; +} + +.action-btn { + flex: 1; + margin: 0; + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + color: #000000; + border-radius: 9px; + font-size: 16px; + padding: 10px 0; + border: 1px solid rgba(104, 249, 254, 0.7); + font-weight: 500; + transition: background 0.15s, color 0.15s; +} + +.action-btn:active { + background: linear-gradient(23deg, #AA93ED, #68F9FE); +} + +.action-fav { + color: #000000; + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + border: 1px solid rgba(104, 249, 254, 0.7); +} + +.action-fav-share { + color: #000000; + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + border: 1px solid rgba(104, 249, 254, 0.7); +} + +.action-fav:active { + background: linear-gradient(23deg, #AA93ED, #68F9FE); +} + +.action-nav { + color: #000000; + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + border: 1px solid rgba(104, 249, 254, 0.7); +} + +.action-nav:active { + background: linear-gradient(23deg, #AA93ED, #68F9FE); +} + +.action-remind { + color: #000000; + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + border: 1px solid rgba(104, 249, 254, 0.7); +} + +.action-remind:active { + background: linear-gradient(23deg, #AA93ED, #68F9FE); +} + +/* 静态数据标记样式 */ +.callout-static-data-icon { + width: 50px; + /* 方形静态数据标记的宽度,比用户头像(35)大 */ + height: 50px; + /* 方形静态数据标记的高度,比用户头像(45)大 */ + border-radius: 8px; + /* 稍微圆角,保持方形外观 */ + background: rgba(255, 255, 255, 0.95); + border: 2px solid rgba(255, 255, 255, 0.8); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); + margin: 4px 0; + display: block; +} + +.callout-static-data-desc { + font-size: 12px; + color: #666; + margin-top: 2px; + text-align: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100px; +} + +/* 聚合点通用样式 */ +.callout-cluster { + width: 40rpx; + height: 40rpx; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + border: 2rpx solid white; + box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.2); +} + +.callout-cluster-count { + font-size: 24rpx; + font-weight: bold; + color: white; +} + + +.callout-feed { + position: relative; + width: 86px; + height: 77px; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + border: 2px solid #000; +} + + +.callout-feed-cluster { + width: 48px; + height: 48px; + border-radius: 24px; + display: flex; + align-items: center; + justify-content: center; + border: 2px solid #fff; +} + + + + + + +.online-thumb { + position: absolute; + top: 0; + left: 0; + z-index: 2; /* 在线图在上层 */ + opacity: 0; /* 初始透明 */ + transition: opacity 0.3s ease; /* 平滑过渡效果 */ +} + +/* 加载完成后显示在线图片 */ +.online-thumb.loaded { + opacity: 1; +} + + + + +.callout-feed-cluster { + font-size: 16px; + font-weight: 600; +} + +.callout-feed-count { + font-size: 16px; + font-weight: 600; +} + +/* ===================== 炫酷地图气泡 callout ===================== */ +.customCallout, +.callout-vertical { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + min-width: 110px; + max-width: 180px; + z-index: 999; + background: transparent; + box-shadow: none; + border: none; + padding: 0; +} + +.callout-bubble { + background: linear-gradient(23deg, #68F9FE 0%, #AA93ED 100%); + border-radius: 18px; + box-shadow: 0 4px 24px 0 rgba(104, 249, 254, 0.25), 0 0 12px 2px #fff3; + padding: 10px 16px 8px 16px; + display: flex; + flex-direction: column; + align-items: center; + position: relative; + border: 2px solid #fff; + animation: callout-pop 0.4s cubic-bezier(.68, -0.55, .27, 1.55); +} + +@keyframes callout-pop { + 0% { + transform: scale(0.7); + opacity: 0; + } + + 80% { + transform: scale(1.1); + opacity: 1; + } + + 100% { + transform: scale(1); + opacity: 1; + } +} + +.callout-user .callout-bubble { + background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); + box-shadow: 0 4px 24px 0 rgba(67, 233, 123, 0.18), 0 0 12px 2px #fff3; +} + +.callout-merchant .callout-bubble { + background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); + box-shadow: 0 4px 24px 0 rgba(250, 112, 154, 0.18), 0 0 12px 2px #fff3; +} + +.callout-static .callout-bubble { + background: linear-gradient(135deg, #4285f4 0%, #34a853 100%); + box-shadow: 0 4px 24px 0 rgba(66, 133, 244, 0.18), 0 0 12px 2px #fff3; +} + +.callout-nickname { + font-size: 15px; + font-weight: bold; + color: rgb(8, 8, 8); + margin-bottom: 6px; + text-align: center; + letter-spacing: 1px; + text-shadow: 0 2px 8px #0006, 0 0 6px #fff8; + max-width: 120px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.callout-text-glow { + text-shadow: 0 0 8px #fff, 0 2px 8px #0006, 0 0 16px #fff8; +} + +.callout-avatar { + width: 38px; + height: 38px; + border-radius: 50%; /* 圆形显示 */ + border: 2px solid #fff; + box-shadow: 0 0 8px 1px #fff8, 0 2px 4px #0003; + background: #eee; /* 图片加载前的占位背景 */ + object-fit: cover; /* 核心:从中心裁剪,保持比例填充容器 */ +} + + + + +.callout-avatar-dot { + width: 15px; + border-radius: 50%; + height: 15px; + background: #eee; + object-fit: cover; + overflow: hidden; +} + + +.callout-avatar-dot-stranger { + margin-top: -15px; + margin-left: 15px; + width: 15px; + border-radius: 50%; + height: 15px; + background: #eee; + object-fit: cover; + overflow: hidden; +} + +.callout-avatar-dot-mine { + width: 16px; /* 适当当缩小尺寸 */ + height: 16px; + border-radius: 50%; + position: absolute; + bottom: 15px; /* 距离头像底部2px */ + right: 15px; /* 距离头像右侧2px */ + border: 2px solid #ffffffff; /* 白色边框与头像边框呼应 */ + z-index: 2; /* 确保在头像上方显示 */ +} + +/* 解决头像被截断的容器样式 */ +.mine-avatar-container { + position: relative; + width: 88px; + /* 比头像大10px,避免边缘截断 */ + height: 88px; + overflow: visible; + /* 关键:允许内容超出容器显示 */ +} + +/* 修复头像显示不全问题 */ +.callout-avatar-mine { + width: 44px; + /* 原始头像尺寸 */ + height: 44px; + border-radius: 50%; + /* 保持圆形 */ + border: 2px solid #fff; + position: absolute; + top: 50%; + /* 垂直居中 */ + left: 50%; + /* 水平居中 */ + transform: translate(-50%, -50%); + /* 精准居中 */ + z-index: 1; + /* 确保头像在容器底层 */ +} + +/* 方向箭头样式(优化位置避免遮挡头像) */ +.direction-indicator { + position: absolute; + width: 18px; + height: 18px; + left: 50%; + transform-origin: 50% 40px; + /* 旋转原点=头像中心 */ + z-index: 2; + /* 箭头在头像上方 */ + margin-left: -9px; + margin-top:4px; + pointer-events: none; +} + + + + + + + + + +.callout-avatar-glow { + box-shadow: 0 0 16px 4px #38f9d7cc, 0 2px 8px #0003; +} + +.callout-battery { + display: flex; + align-items: center; + font-size: 13px; + color: rgb(10, 10, 10); + margin-top: 2px; + text-shadow: 0 1px 4px #0006; + font-weight: 500; + background: rgba(0, 0, 0, 0.12); + border-radius: 8px; + padding: 2px 8px 2px 4px; + min-width: 38px; + justify-content: center; +} + +.callout-battery-glow { + text-shadow: 0 0 8px #fff, 0 1px 4px #0006; +} + +.callout-battery-icon { + width: 16px; + height: 16px; + margin-right: 4px; + vertical-align: middle; +} + +.callout-merchant-icon { + width: 44px; + height: 44px; + border-radius: 12px; + margin-bottom: 4px; + background: #fff; + object-fit: cover; + box-shadow: 0 0 12px 2px #fff8, 0 2px 8px #0002; +} + + /* 商家名称高亮显示样式 */ + .callout-merchant-name { + font-size: 28rpx; + font-weight: bold; + color: #382200; + text-align: center; + padding: 8rpx 32rpx; + background: #FFFFFF; + border-radius: 24rpx; + border: 2rpx solid #000000; + box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1); + white-space: normal; + word-wrap: break-word; + word-break: break-all; + min-width: 160rpx; + max-width: 300rpx; + letter-spacing: 1rpx; + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 56rpx; + line-height: 1.2; + } + + .callout-merchant-name-active { + background: #FFE5D9; + border-color: #FF6F3C; + } + +.callout-merchant-glow { + box-shadow: 0 0 16px 4px #fa709acc, 0 2px 8px #0003; +} + + +/* 兼容旧结构的圆形icon和内容 */ +.circle { + width: 20px; + height: 20px; + border: 1px solid #ccc; + border-radius: 50%; +} + +.icon { + width: 16px; + height: 16px; +} + +.content { + flex: 0 1 auto; + margin: 0 10px; + font-size: 14px; +} + +/* 显示模式筛选弹窗样式 */ +.filter-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 1000; + display: flex; + align-items: center; + justify-content: center; +} + +.filter-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(4px); + animation: fadeIn 0.3s ease; +} + +.filter-options { + position: relative; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(20px); + border-radius: 24rpx; + padding: 20rpx 0; + box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.15); + border: 1px solid rgba(255, 255, 255, 0.8); + animation: slideUp 0.3s ease; + min-width: 60%; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(20rpx) scale(0.98); + } + + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.filter-option { + display: flex; + align-items: center; + gap: 20rpx; + padding: 30rpx 40rpx; + transition: all 0.2s ease; + position: relative; +} + +.filter-option:active { + background: rgba(0, 0, 0, 0.03); +} + +.filter-option.active { + background: rgba(102, 126, 234, 0.08); +} + +.filter-option.active::before { + content: ''; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); + width: 6rpx; + height: 40rpx; + background: linear-gradient(135deg, #667eea, #764ba2); + border-radius: 0 3rpx 3rpx 0; +} + +.filter-icon { + font-size: 36rpx; + flex-shrink: 0; +} + +.filter-text { + font-size: 32rpx; + color: #333; + font-weight: 500; + flex: 1; +} + +.filter-option.active .filter-text { + color: #667eea; + font-weight: 600; +} + +/* 分割线 */ +.filter-options .filter-option:not(:last-child)::after { + content: ''; + position: absolute; + bottom: 0; + left: 40rpx; + right: 40rpx; + height: 1rpx; + background: rgba(0, 0, 0, 0.06); +} + +/* 适配横屏和不同尺寸设备 */ +@media (min-width: 768px) { + .filter-options { + min-width: 40%; + max-width: 320px; + } +} + +/* 深色模式支持 */ +@media (prefers-color-scheme: dark) { + .filter-options { + background: rgba(26, 26, 26, 0.95); + border: 1px solid rgba(255, 255, 255, 0.1); + } + + .filter-text { + color: #e0e0e0; + } + + .filter-option:active { + background: rgba(255, 255, 255, 0.05); + } + + .filter-option.active { + background: rgba(102, 126, 234, 0.15); + } + + .filter-option:not(:last-child)::after { + background: rgba(255, 255, 255, 0.1); + } + + .filter-option.active .filter-text { + color: #8ea0fc; + } +} + +/* 调试按钮 */ +.debug-button { + position: absolute; + width: 44px; + height: 44px; + background: rgba(255, 255, 255, 0.9); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + z-index: 10; +} + +.debug-icon { + font-size: 20px; +} + +/* ===== 搜索相关样式 ===== */ +/* 搜索按钮样式:圆形、半透明黑色背景 */ +.search-btn { + width: 44px; + /* 按钮宽度 */ + height: 44px; + /* 按钮高度 */ + background: rgba(0, 0, 0, 0.8); + /* 半透明黑色背景 */ + border-radius: 50%; + /* 圆形按钮 */ + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + /* 阴影效果 */ + transition: all 0.3s ease; + /* 平滑过渡动画 */ + margin-right: 8px; + /* 在个人主页按钮左边保留适当间距 */ +} + +/* 搜索按钮点击状态:缩小并变为不透明黑色 */ +.search-btn:active { + transform: scale(0.95); + /* 缩小效果 */ + background: rgba(0, 0, 0, 1); + /* 不透明黑色 */ +} + +/* 搜索按钮内图标样式:白色SVG图标 */ +.search-btn .search-icon { + width: 20px; + /* 图标宽度 */ + height: 20px; + /* 图标高度 */ + filter: brightness(0) invert(1); + /* 滤镜效果:将图标变为白色 */ + position: static; + /* left: auto; */ +} + +/* 搜索建议列表容器 */ +.search-suggestions-container { + position: absolute; + top: calc(var(--nav-bar-height, 88px) + 70px); + left: 20rpx; + right: 20rpx; + max-height: 500rpx; + background-color: rgba(0, 0, 0, 0.9); + border-radius: 16rpx; + padding: 20rpx; + z-index: 200; + overflow-y: auto; + box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.5); +} + +/* 搜索中状态 */ +.searching-status { + display: flex; + align-items: center; + justify-content: center; + padding: 40rpx 20rpx; +} + +.searching-spinner { + width: 32rpx; + height: 32rpx; + border: 4rpx solid rgba(255, 255, 255, 0.3); + border-radius: 50%; + border-top-color: #fff; + animation: spin 1s linear infinite; + margin-right: 20rpx; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +.searching-text { + color: #fff; + font-size: 28rpx; +} + +/* 搜索历史 */ +.search-history-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20rpx; + padding-bottom: 20rpx; + border-bottom: 1rpx solid rgba(255, 255, 255, 0.2); +} + +.search-history-title { + color: #aaa; + font-size: 26rpx; +} + +.search-history-clear { + color: #ff9500; + font-size: 26rpx; +} + +.search-history-list { + display: flex; + flex-wrap: wrap; + gap: 16rpx; +} + +.search-history-item { + display: flex; + align-items: center; + background-color: rgba(255, 255, 255, 0.1); + padding: 12rpx 24rpx; + border-radius: 32rpx; + font-size: 26rpx; + color: #fff; +} + +.search-history-item:active { + background-color: rgba(255, 255, 255, 0.2); +} + +.history-icon { + width: 24rpx; + height: 24rpx; + margin-right: 12rpx; + filter: brightness(0) invert(1); +} + +/* 搜索建议列表 */ +/* .search-suggestions-list { + +} */ +.search-suggestion-item { + display: flex; + justify-content: space-between; + align-items: flex-start; + padding: 24rpx 0; + border-bottom: 1rpx solid rgba(255, 255, 255, 0.1); +} + +.search-suggestion-item:last-child { + border-bottom: none; +} + +.search-suggestion-item:active { + background-color: rgba(255, 255, 255, 0.05); +} + +.suggestion-content { + flex: 1; + margin-right: 20rpx; +} + +.suggestion-title { + display: block; + color: #fff; + font-size: 32rpx; + margin-bottom: 8rpx; +} + +.suggestion-address { + display: block; + color: #aaa; + font-size: 24rpx; + line-height: 1.4; +} + +.suggestion-distance { + color: #ff9500; + font-size: 24rpx; + white-space: nowrap; +} + +/* 无结果提示 */ +.no-results { + text-align: center; + padding: 60rpx 20rpx; + color: #aaa; + font-size: 28rpx; +} + +/* 适配iOS安全区域 */ +@media screen and (device-width: 375px) and (device-height: 812px) { + .search-suggestions-container { + top: calc(var(--nav-bar-height, 88px) + 80px); + } +} + +/* 搜索框容器样式:圆角矩形、白色背景、阴影效果 */ +.search-input-wrapper { + width: 100%; + max-width: 100%; + height: 44px; + /* 搜索框高度 */ + background: #ffffff; + /* 白色背景 */ + border-radius: 24px; + /* 圆角 */ + display: flex; + align-items: center; + padding: 0 16px; + /* 左右内边距 */ + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); + /* 阴影效果 */ + transition: all 0.3s ease; + /* 过渡动画 */ + animation: searchBoxSlideIn 0.3s ease; + /* 滑入动画 */ + backdrop-filter: blur(10px); + /* 背景模糊效果 */ +} + +/* 废弃的样式,使用.search-input-wrapper替代 */ +.search-input-container { + display: none; +} + +/* 搜索框滑入动画:从上方淡入并下滑 */ +@keyframes searchBoxSlideIn { + from { + opacity: 0; + /* 透明 */ + transform: translateY(-10px); + /* 向上偏移 */ + } + + to { + opacity: 1; + /* 不透明 */ + transform: translateY(0); + /* 回到原位 */ + } +} + +/* 搜索输入框样式:占据大部分空间、无边框 */ +.search-input { + flex: 1; + /* 占据剩余空间 */ + font-size: 14px; + /* 字体大小 */ + color: #333; + /* 黑色文字 */ + padding: 0; + margin: 0; + border: none; + /* 无边框 */ + background: transparent; + /* 透明背景 */ + outline: none; + /* 无轮廓线 */ + height: 32px; +} + +/* 搜索输入框占位符样式:灰色半透明文字 */ +.search-input::placeholder { + color: rgba(51, 51, 51, 0.5); + /* 灰色半透明 */ +} + +/* 搜索框关闭按钮样式:居中的关闭符号 */ +.search-input-close { + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; + color: rgba(51, 51, 51, 0.8); + /* 灰色文字 */ + font-size: 16px; + margin-left: 8px; + /* 与输入框的间距 */ +} + +/* ===== 右上角按钮组样式 - 在flex布局中已废弃,使用.right-elements-container替代 */ +.right-top-buttons { + display: none; +} + +.avatar-container { + position: relative; + width: 100%; + height: 100%; + border-radius: 50%; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); + overflow: hidden; +} + +.avatar-text { + color: white; + font-size: 16px; + font-weight: 600; +} + +.notification-dot { + position: absolute; + top: 2px; + right: 2px; + width: 8px; + height: 8px; + background: #ff4d4f; + border-radius: 50%; + border: 2px solid white; +} + +.right-vertical-buttons { + display: flex; + flex-direction: column; + gap: 16px; + align-items: center; +} + +.more-btn, +.mapsettings-btn { + width: 44px; + height: 44px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; +} + +.more-btn:active, +.mapsettings-btn:active { + transform: scale(0.95); +} + +.more-icon, +.mapsettings-icon { + width: 28px; + height: 28px; + filter: brightness(0) saturate(100%); + /* 浅色模式下全黑色 */ +} + +/* ===== 更多菜单弹窗样式 - 卡片形式 ===== */ +.more-menu-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 999; + display: flex; + justify-content: flex-end; + align-items: flex-start; + padding-right: 20px; + padding-top: 260px; +} + +.more-menu-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.3); +} + +.more-menu-content { + position: relative; + width: 200px; + background: #1a1a1a; + border-radius: 12px; + padding: 8px 0; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); + animation: popupMenu 0.25s ease-out; + overflow: hidden; +} + +@keyframes popupMenu { + from { + opacity: 0; + transform: translateY(-10px) scale(0.95); + } + + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.more-menu-item { + display: flex; + align-items: center; + padding: 14px 20px; + transition: all 0.2s ease; + position: relative; +} + +.more-menu-item:active { + background-color: rgba(255, 255, 255, 0.1); +} + +/* 菜单项之间的分割线 */ +.more-menu-item:not(:last-child)::after { + content: ''; + position: absolute; + bottom: 0; + left: 20px; + right: 20px; + height: 1px; + background-color: rgba(255, 255, 255, 0.1); +} + +.more-menu-icon { + width: 24px; + height: 24px; + margin-right: 14px; +} + +.more-menu-text { + font-size: 15px; + color: #ffffff; + flex: 1; +} + +/* 更多菜单中添加好友按钮的小红点样式 */ +.more-menu-item .notification-dot { + position: absolute; + top: 12px; + right: 12px; + width: 8px; + height: 8px; + background: #ff4d4f; + border-radius: 50%; + border: 2px solid white; +} + +/* 更多菜单项的容器样式调整 */ +.more-menu-item { + position: relative; +} + +/* ===== 地图设置弹窗样式 ===== */ +.map-settings-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 10002; + /* 提高z-index,确保在底部导航栏之上 */ + display: flex; + align-items: flex-end; + justify-content: center; +} + +.map-settings-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.3); +} + +.map-settings-content { + position: relative; + width: 100%; + background: black; + border-radius: 20px 20px 0 0; + padding: 12px; + box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.3); + animation: slideInUp 0.3s ease; + max-height: 80vh; + overflow-y: auto; + transition: transform 0.3s ease; +} + +.map-settings-content.sliding-down { + transform: translateY(100%); +} + +@keyframes slideInUp { + from { + transform: translateY(100%); + opacity: 0; + } + + to { + transform: translateY(0); + opacity: 1; + } +} + +@keyframes slideOutDown { + from { + transform: translateY(0); + opacity: 1; + } + + to { + transform: translateY(100%); + opacity: 0; + } +} + +.map-settings-title { + font-size: 20px; + font-weight: 600; + color: white; + text-align: center; + margin-bottom: 12px; +} + +.map-settings-section { + margin-bottom: 24px; +} + +.map-settings-section-title { + font-size: 16px; + font-weight: 600; + color: white; + margin-bottom: 16px; + display: block; +} + +.map-layer-options { + display: flex; + justify-content: space-around; + gap: 12px; + margin: 0 20px; +} + +.map-layer-option { + display: flex; + flex-direction: column; + align-items: center; + padding: 0px; + background: transparent; + border-radius: 20px; + transition: all 0.2s ease; + position: relative; + border: 3px solid transparent; + /* 默认无色透明边框 */ + flex: 1; + max-width: 150px; + height: 100px; +} + +.map-layer-option.active { + border: 3px solid #0cff18; + background: transparent; +} + +.map-layer-option:active { + transform: scale(0.98); +} + +.map-layer-icon { + font-size: 32px; +} + +.map-layer-text-bottom { + font-size: 14px; + color: white; + width: 100%; + text-align: center; + display: flex; + align-items: center; + justify-content: center; + height: 100%; + margin: 0; +} + +/* B框 - 图标框,占四分之三 */ +.map-layer-icon-box { + width: 100%; + height: 75%; + display: flex; + align-items: center; + justify-content: center; + border-top-left-radius: 12px; + border-top-right-radius: 12px; + padding: 16px 0; +} + +/* 探索按钮渐变背景 - 白粉黄绿色有角度 */ +.standard-bg { + background: linear-gradient(135deg, #ffffff 0%, #f0f0f0 20%, #e0ffe0 60%, #8bff8b 100%); +} + +/* 卫星按钮渐变背景 - 绿蓝青绿有角度 */ +.satellite-bg { + background: linear-gradient(135deg, #00cc00 0%, #0099cc 50%, #00cccc 75%, #00ffcc 100%); +} + +/* C框 - 文本框,占四分之一 */ +.map-layer-text-box { + width: 100%; + height: 25%; + background: #333; + display: flex; + align-items: center; + justify-content: center; + border-bottom-left-radius: 12px; + border-bottom-right-radius: 12px; + padding: 8px 0; +} + + +.map-layer-text-box-img { + height: 100%; + width: 100%; + align-items: center; + justify-content: center; + padding: 0px; +} + +.map-display-options { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 0; +} + +.map-display-text { + font-size: 16px; + color: white; +} + +.map-settings-actions { + margin-top: 32px; +} + +.map-settings-close-btn { + width: 100%; + height: 48px; + background: #007aff; + color: white; + font-size: 16px; + border: none; + border-radius: 24px; + box-shadow: 0 4px 12px rgba(0, 122, 255, 0.3); + transition: all 0.2s ease; +} + +.map-settings-close-btn:active { + transform: scale(0.98); + box-shadow: 0 2px 6px rgba(0, 122, 255, 0.3); +} + +/* 深色模式适配 */ +@media (prefers-color-scheme: dark) { + .search-btn { + background: rgba(30, 30, 30, 0.95); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + } + + .search-btn:active { + background: rgba(40, 40, 40, 1); + } + + .more-icon, + .mapsettings-icon { + filter: none; + /* 深色模式下使用原色 */ + } + + .search-input-wrapper { + background: rgba(30, 30, 30, 0.95); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); + } + + .search-input-container { + background: rgba(30, 30, 30, 0.95); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); + } + + .search-input { + color: #e0e0e0; + } + + .search-input::placeholder { + color: rgba(255, 255, 255, 0.6); + } + + .search-input-close { + color: #777; + } + + .more-menu-content { + background: #222; + box-shadow: -4px 0 16px rgba(0, 0, 0, 0.3); + } + + .more-menu-item:active { + background-color: #333; + } + + .more-menu-text { + color: #e0e0e0; + } + + .map-settings-content { + background: #222; + box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.3); + } + + .map-settings-title { + color: #e0e0e0; + } + + .map-settings-section-title { + color: #999; + } + + .map-layer-option { + background: #333; + color: #e0e0e0; + } + + .map-display-text { + color: #e0e0e0; + } + + /* 深色模式下的快速发布按钮样式 */ + .quick-publish-button { + background-color: #06b259; + box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.3); + } + + /* 深色模式下的相机图标样式 */ + .camera-icon { + filter: brightness(0) invert(1); + } +} + +/* 右下角快速发布动态按钮样式 */ +.quick-publish-container { + position: fixed; + bottom: 100rpx; + right: 40rpx; + z-index: 999; +} + +.quick-publish-button { + width: 160rpx; + height: 160rpx; + background-color: #07c160; + border-radius: 50%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15); + transition: all 0.3s ease; +} + +.quick-publish-button:active { + transform: scale(0.95); + opacity: 0.9; +} + +.quick-publish-plus { + color: white; + font-size: 80rpx; + font-weight: bold; + line-height: 1; + margin-top: -20rpx; +} + +.quick-publish-text { + color: white; + font-size: 24rpx; + margin-top: -10rpx; +} + +/* 地点收藏栏样式 */ +.location-favorite-bar { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 1000; + display: flex; + align-items: flex-end; +} + +.location-favorite-mask { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); +} + +.location-favorite-sheet { + width: 100%; + height: 60vh; + background-color: #000; + border-top-left-radius: 30rpx; + border-top-right-radius: 30rpx; + position: relative; + box-sizing: border-box; + transform: translateY(0); + transition: transform 0.3s ease; +} + +/* 地点收藏栏顶部 */ +.location-favorite-header { + position: relative; + padding-top: 20rpx; + padding-right: 30rpx; + display: flex; + justify-content: center; + align-items: flex-start; +} + +.location-favorite-sheet-handle { + width: 80rpx; + height: 8rpx; + background-color: #555; + border-radius: 4rpx; + margin-bottom: 30rpx; +} + +.location-favorite-sheet-close { + position: absolute; + right: 30rpx; + top: 20rpx; + width: 60rpx; + height: 60rpx; + display: flex; + align-items: center; + justify-content: center; + color: #fff; + font-size: 40rpx; +} + +/* 地点收藏栏搜索框 */ +.location-favorite-search { + margin: 0 30rpx 30rpx 30rpx; + position: relative; + display: flex; + align-items: center; +} + +.search-icon { + position: absolute; + left: 30rpx; + color: #888; + font-size: 32rpx; +} + +.result-menu-item { + /* 确保容器宽度充满父元素,为居中提供基础 */ + width: 100%; + /* 开启弹性布局,方便子元素居中 */ + display: flex; + /* 水平方向居中对齐 */ + justify-content: center; + /* 垂直方向可根据需要调整(这里顶部对齐) */ + align-items: flex-start; + /* 可添加适当的内边距控制位置 */ + padding: 2px 0; + /* 上下各10px间距,左右0 */ +} + +.result-menu-item image { + /* 控制图片大小(根据实际图片尺寸调整) */ + width: 30px; + /* 示例宽度 */ + height: 20px; + /* 示例高度,与宽度一致保持正方形 */ + /* 确保图片自适应容器大小 */ + object-fit: contain; + /* 移除可能的默认间距 */ + display: block; +} + + +.location-favorite-input { + width: 100%; + height: 80rpx; + background-color: #333; + border-radius: 40rpx; + padding-left: 80rpx; + padding-right: 80rpx; + color: #fff; + font-size: 28rpx; + box-sizing: border-box; +} + +.clear-icon { + position: absolute; + right: 30rpx; + color: #888; + font-size: 32rpx; +} + +/* 地点收藏栏选项卡 */ +.location-favorite-tabs { + display: flex; + margin: 0 30rpx 30rpx 30rpx; +} + +.location-favorite-tab { + margin-right: 40rpx; + font-size: 32rpx; + color: #fff; + padding-bottom: 10rpx; + position: relative; +} + +.location-favorite-tab.active { + background: linear-gradient(to right, #ff0000, #0000ff); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} + +.location-favorite-tab.active::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 4rpx; + background: linear-gradient(to right, #ff0000, #0000ff); +} + +/* 地点收藏栏列表 */ +.location-favorite-list { + height: calc(100% - 240rpx); + margin: 0 30rpx; + padding-right: 30rpx; + overflow-y: auto; +} + +.location-favorite-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 30rpx 0; + border-bottom: 1rpx solid #333; +} + +.location-favorite-item-content { + flex: 1; + margin-right: 20rpx; +} + +.location-favorite-item-name { + font-size: 32rpx; + color: #fff; + margin-bottom: 8rpx; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.location-favorite-item-coord { + font-size: 26rpx; + color: #888; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.location-favorite-item-star { + width: 60rpx; + height: 60rpx; + display: flex; + align-items: center; + justify-content: center; + color: #9c27b0; + font-size: 40rpx; +} + +.star-icon { + font-size: 40rpx; +} + +/* 地点收藏栏空状态 */ +.location-favorite-empty { + text-align: center; + padding: 100rpx 0; + color: #666; + font-size: 28rpx; +} + +/* 滚动条样式 */ +.location-favorite-list::-webkit-scrollbar { + width: 4rpx; +} + +.location-favorite-list::-webkit-scrollbar-track { + background: #222; +} + +.location-favorite-list::-webkit-scrollbar-thumb { + background: #555; + border-radius: 2rpx; +} + +.location-favorite-list::-webkit-scrollbar-thumb:hover { + background: #666; +} + +.map-feed-toggle { + position: absolute; + right: 40rpx; + padding: 12rpx 24rpx; + border-radius: 999rpx; + background: rgba(28, 31, 43, 0.88); + color: #ffffff; + font-size: 26rpx; + display: flex; + align-items: center; + gap: 12rpx; + box-shadow: 0 12rpx 30rpx rgba(0, 0, 0, 0.25); + backdrop-filter: blur(20rpx); + border: 1px solid rgba(255, 255, 255, 0.12); + z-index: 1100; +} + +.map-feed-toggle.active { + background: linear-gradient(135deg, rgba(93, 160, 255, 0.95), rgba(76, 226, 227, 0.9)); + box-shadow: 0 18rpx 34rpx rgba(93, 160, 255, 0.45); +} + +.map-feed-toggle-icon { + font-size: 30rpx; +} + +.map-feed-toggle-text { + font-size: 26rpx; + font-weight: 500; + letter-spacing: 2rpx; +} + + +/* ===== 搜索结果列表样式 ===== */ +/* 搜索结果容器样式:半透明白色背景、模糊效果 */ +.search-results-container { + width: 100%; + /* 宽度充满父容器 */ + background: rgba(255, 255, 255, 0.95); + /* 半透明白色背景 */ + backdrop-filter: blur(10px); + /* 背景模糊效果 */ + border-radius: 16px; + /* 圆角 */ + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); + /* 阴影效果 */ + overflow: hidden; + margin: 0 16px; + /* 左右边距 */ +} + +/* 搜索结果列表样式:可滚动、限制最大高度 */ +.search-results-list { + max-height: 400px; + /* 最大高度,超出部分可滚动 */ + overflow-y: auto; + /* 垂直滚动 */ +} + +/* 单个搜索结果项样式:横向布局、底部边框 */ +.search-result-item { + display: flex; + align-items: center; + padding: 16px; + /* 内边距 */ + border-bottom: 1px solid #f0f0f0; + /* 底部边框 */ + transition: background-color 0.2s ease; + /* 背景色过渡动画 */ +} + +/* 搜索结果项点击状态:背景色变化 */ +.search-result-item:active { + background-color: #f5f5f5; + /* 点击时的背景色 */ +} + +/* 最后一个搜索结果项:移除底部边框 */ +.search-result-item:last-child { + border-bottom: none; +} + +/* 结果图标样式:居中显示、固定尺寸 */ +.result-icon { + font-size: 24px; + /* 图标大小 */ + margin-right: 16px; + /* 与内容区的间距 */ + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; +} + +/* 结果内容区样式:占据剩余空间、防止溢出 */ +.result-content { + flex: 1; + /* 占据剩余空间 */ + min-width: 0; + /* 允许内容收缩,避免flex子项溢出 */ +} + +/* 结果名称样式:黑色粗体、单行显示 */ +.result-name { + font-size: 16px; + font-weight: 600; + /* 加粗 */ + color: #333; + /* 黑色文字 */ + margin-bottom: 4px; + overflow: hidden; + text-overflow: ellipsis; + /* 超出部分显示省略号 */ + white-space: nowrap; + /* 不换行 */ +} + +/* 结果地址样式:灰色文字、单行显示 */ +.result-address { + font-size: 14px; + color: #666; + /* 灰色文字 */ + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* ===== 未登录状态样式 ===== */ + +/* 登录提示按钮 */ +.login-prompt-btn { + width: 48px; + height: 48px; + background: rgba(0, 0, 0, 0.6); + border-radius: 24px; + display: flex; + align-items: center; + justify-content: center; + margin: 10px 0; + backdrop-filter: blur(5px); + transition: all 0.3s ease; +} + +.login-prompt-btn:active { + background: rgba(0, 0, 0, 0.8); + transform: scale(0.95); +} + +.login-prompt-text { + font-size: 12px; + color: white; + font-weight: 500; +} + +/* 登录后使用提示文字 */ +.login-required-text { + display: flex; + align-items: center; + justify-content: center; + padding: 8px 16px; + background: rgba(0, 0, 0, 0.6); + border-radius: 20px; + backdrop-filter: blur(5px); + transition: all 0.3s ease; +} + +.login-required-text:active { + background: rgba(0, 0, 0, 0.8); +} + +.login-required { + font-size: 12px; + color: white; + font-weight: 500; +} + +/* 登录按钮样式 */ +.login-btn { + background: rgba(0, 0, 0, 0.6); + color: white; + transition: all 0.3s ease; +} + +.login-btn:active { + background: rgba(0, 0, 0, 0.8); +} + + +.share-friends-list { + white-space: nowrap; +} + + + +/* 好友项 */ +.friend-item { + display: inline-block; + width: 120rpx; + text-align: center; + margin-right: 20rpx; +} + + +.friend-name { + font-size: 24rpx; + /* 文字大小 */ + color: #fff; + /* 文字颜色 */ + text-align: center; + /* 文字自身居中(增强对齐效果) */ +} + +.friend-avatar { + width: 80rpx; + height: 80rpx; + border-radius: 20%; + margin-bottom: 8rpx; +} + + +.friend-name { + font-size: 24rpx; + color: #fff; + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* 分享选项容器(自动换行) */ +.share-options { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; +} + +/* 分享选项项 */ +.option-item { + width: 25%; + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 30rpx; +} + +.option-icon { + width: 100rpx; + height: 100rpx; + margin-bottom: 8rpx; +} + +.option-name { + font-size: 24rpx; + color: #fff; +} + + +.feed-bubble-header { + display: flex; + align-items: flex-start; + padding: 16rpx; + gap: 12rpx; +} +.feed-bubble-avatar { + width: 80rpx; + height: 80rpx; + border-radius: 50%; + overflow: hidden; + flex-shrink: 0; +} +/* 外层容器:控制上下左右10px间距,高度自适应内容 */ +.feed-bubble-content { + padding: 5px; /* 上下左右各10px间距 */ + width: 100%; /* 按需设置宽度(如适配父容器) */ + box-sizing: border-box; /* 避免padding撑大宽度 */ +} + +/* 内容容器:限制最多3行,多余显示省略号,高度自适应 */ +.content-inner { + /* 关键:行数限制+省略号(修复压缩丢失问题) */ + display: -webkit-box; + -webkit-line-clamp: 3; /* 最多3行 */ + /* 重点:用注释包裹,防止被代码压缩移除 */ + /*! autoprefixer: off */ + -webkit-box-orient: vertical; + /*! autoprefixer: on */ + overflow: hidden; + text-overflow: ellipsis; + + /* 调整:行高建议用具体像素(真机更稳定) */ + font-size: 14px; + line-height: 22px; /* 替换1.5倍,14*1.5=21,取整22px,避免小数兼容性问题 */ + color: #fff; + + /* 新增:确保宽度足够(避免内容被强制换行成1行) */ + width: 100%; + box-sizing: border-box; +} +.feed-bubble-avatar image { + width: 100%; + height: 100%; +} +.feed-bubble-user-content { + padding-top:5px; + flex: 1; + overflow: hidden; +} +.feed-bubble-user-name { + font-size: 24rpx; + font-weight: 600; + color: #fff; + margin-bottom: 8rpx; + display: block; +} +.feed-bubble-post-content { + font-size: 22rpx; + color: #666; + line-height: 1.5; + display: -webkit-box; + color: #fff; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} +.feed-bubble-image-container { + width: 100%; + height: 320rpx; + overflow: hidden; + background-color: #f5f5f5; +} +.feed-bubble-post-image { + width: 100%; + height: 100%; + /* 禁用缩放(确保图片不被压缩) */ + transform: none !important; + object-fit: cover; /* 核心:从中心裁剪,保持比例填充容器 */ +} + + + +/* 原有样式完全保留,仅新增以下样式 + 微调定位 */ +.callout-feed-single { + position: relative; /* 原有已存在,无需重复写,仅作提醒 */ + width: 172rpx; + height: 152rpx; + border-radius: 10px; + display: block; /* 恢复原有布局流,不使用flex */ + border: 2px solid #000; + overflow: hidden; +} + +.callout-feed-thumb { + width: 100%; + height: 100%; /* 恢复原有图片高度,铺满容器 */ + border-radius: 10px; /* 恢复原有圆角 */ + display: block; + z-index: 911; +} + +/* 新增:左下方固定操作区(图片底部边框上方) */ +.callout-actions-fixed { + position: absolute; + bottom: 0px; /* 紧贴图片底部边框上方 */ + display: flex; + width:100%; + padding-bottom:2px; + padding-top:2px; + gap: 4px; /* 点赞和评论之间的间距 */ + z-index: 911; /* 确保在图片上方显示 */ + background-color: rgba(0, 0, 0, 0.3); /* 50% 透明度(中间值),黑色背景 */ +} + +/* 操作项通用样式 */ +.action-item { + display: flex; + align-items: center; + gap: 1px; /* 图标和数字间距 */ + padding: 1px 2px; + border-radius: 2px; +} + +/* 图标样式 */ +.action-icon { + width: 12px; + height: 12px; + margin:0px 5px 0px 5px +} + +/* 数字样式 */ +.action-count { + font-size: 10px; + color: #fff; + left:5px; + line-height: 1; +} + +/* 原有箭头样式保留 */ +.callout-arrow { + width: 24rpx; + height: 16rpx; + margin: 0 auto; + margin-top: -2rpx; + z-index: 1; +} + diff --git a/pages/message/chat/chat.js b/pages/message/chat/chat.js new file mode 100644 index 0000000..3619258 --- /dev/null +++ b/pages/message/chat/chat.js @@ -0,0 +1,3222 @@ +// 聊天页面逻辑 +const app = getApp(); +const mediaPicker = require('../../../utils/media-picker.js'); +const { initPageSystemInfo } = require('../../../utils/system-info-modern.js'); +const imageCacheManager = require('../../../utils/image-cache-manager.js'); +const nimConversationManager = require('../../../utils/nim-conversation-manager.js'); +const nimUserManager = require('../../../utils/nim-user-manager.js'); +const friendAPI = require('../../../utils/friend-api.js'); + +Page({ + data: { + // 聊天基本信息 + conversationId: '', + targetId: '', + chatName: '', + chatType: 0, // 0: 单聊, 1: 群聊 + isOnline: false, + isNewConversation: false, // 是否为新会话 + + // 消息数据 + messages: [], + hasMore: true, + lastMessageTime: 0, + unreadCount: 0, + loadingMessages: false, // 🔥 添加加载状态 + + // 输入相关 + inputType: 'text', // 'text' 或 'voice' + inputText: '', + inputFocus: false, + recording: false, + voiceCancel: false, // 🔥 语音录制取消标识 + isComposing: false, // 中文输入法状态 + + // 面板状态 + showEmojiPanel: false, + showMorePanel: false, + showVoiceRecorder: false, + + // 滚动相关 + scrollTop: 0, + scrollIntoView: '', + showScrollToBottom: false, // 🔥 控制滚动到底部按钮显示 + + // 常用表情 + commonEmojis: [ + '😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '🙃', + '😉', '😊', '😇', '🥰', '😍', '🤩', '😘', '😗', '😚', '😙', + '😋', '😛', '😜', '🤪', '😝', '🤑', '🤗', '🤭', '🤫', '🤔', + '🤐', '🤨', '😐', '😑', '😶', '😏', '😒', '🙄', '😬', '🤥', + '😌', '😔', '😪', '🤤', '😴', '😷', '🤒', '🤕', '🤢', '🤮', + '🤧', '🥵', '🥶', '🥴', '😵', '🤯', '🤠', '🥳', '🥸', '😎', + '🤓', '🧐', '😕', '😟', '🙁', '☹️', '😮', '😯', '😲', '😳', + '🥺', '😦', '😧', '😨', '😰', '😥', '😢', '😭', '😱', '😖', + '😣', '😞', '😓', '😩', '😫', '🥱', '😤', '😡', '😠', '🤬', + '👋', '🤚', '🖐️', '✋', '🖖', '👌', '🤌', '🤏', '✌️', '🤞', + '🤟', '🤘', '🤙', '👈', '👉', '👆', '🖕', '👇', '☝️', '👍', + '👎', '👊', '✊', '🤛', '🤜', '👏', '🙌', '👐', '🤲', '🤝' + ], + + // 用户信息 + userInfo: null, + userAvatar: '', + targetUserInfo: null, // 对方用户信息 + targetAvatar: '', // 对方头像 + + // 系统适配信息 + systemInfo: {}, + statusBarHeight: 0, + menuButtonHeight: 0, + menuButtonTop: 0, + navBarHeight: 0, + windowHeight: 0, + safeAreaBottom: 0, + keyboardHeight: 0, // 键盘高度 + inputAreaHeight: 0, // 输入框区域高度 + emojiPanelHeight: 0, // 表情面板高度 + + // 加载状态 + isLoading: false, + }, + + // 🔍 判断内容是否像图片(URL/Base64/JSON中包含图片URL) + _looksLikeImageContent(content) { + try { + if (!content) return false; + const isImgUrl = (u) => { + if (typeof u !== 'string') return false; + if (/^data:image\//i.test(u)) return true; + if (!/^https?:\/\//i.test(u)) return false; + return /\.(png|jpe?g|gif|webp|bmp|svg)(\?.*)?$/i.test(u); + }; + if (typeof content === 'string') { + const s = content.trim(); + if (isImgUrl(s)) return true; + if (s.startsWith('{') && s.endsWith('}')) { + try { + const obj = JSON.parse(s); + const u = obj?.file_url || obj?.url; + return isImgUrl(u || ''); + } catch (_) { return false; } + } + return false; + } + if (typeof content === 'object') { + const u = content.file_url || content.url; + return isImgUrl(u || ''); + } + return false; + } catch (_) { + return false; + } + }, + + // 🔥 将 NIM SDK V2 的数字类型枚举转换为 WXML 中使用的字符串类型 + // V2NIMMessageType: 0=文本, 1=图片, 2=语音, 3=视频, 4=位置, 5=通知, 6=文件, 10=提示, 100=自定义 + convertMessageTypeToString(messageType) { + const typeMap = { + 0: 'text', // 文本 + 1: 'image', // 图片 + 2: 'audio', // 语音(WXML中也兼容'voice') + 3: 'video', // 视频 + 4: 'location', // 位置 + 5: 'notification', // 通知 + 6: 'file', // 文件 + 10: 'tip', // 提示 + 100: 'custom' // 自定义 + }; + return typeMap[messageType] || 'text'; + }, + + + /** + * 点击自己头像 -> 跳转个人资料页 + */ + onSelfAvatarTap(e) { + try { + const userId = this.data.userInfo?.user?.customId; + if (!userId) return; + wx.navigateTo({ + url: `/subpackages/profile/profile/profile?userId=${userId}` + }); + } catch (err) { + console.error('进入个人资料失败', err); + } + }, + + /** + * 点击对方头像 -> 跳转好友详情页(单聊)或成员资料(群聊可后续拓展) + */ + async onPeerAvatarTap(e) { + try { + const senderId = e.currentTarget.dataset.senderId; + if (!senderId) { + console.warn('⚠️ senderId 为空,无法跳转'); + return; + } + // // 如果是自己就直接走自己的逻辑 + // const selfId = this.data.userInfo?.user?.customId; + // if (senderId === selfId) { + // this.onSelfAvatarTap(); + // return; + // } + + wx.showLoading({ title: '加载中...', mask: true }); + // 调用好友详情接口判断关系 + let res = await friendAPI.getFriendDetail(senderId) + wx.hideLoading(); + if (res?.code == 0 || res?.code == 200) { + console.log('√ 是好友,跳转好友详情页'); + wx.navigateTo({ + url: `/subpackages/social/friend-detail/friend-detail?customId=${senderId}` + }); + } else { + console.log('! 非好友,跳转陌生人预览页'); + wx.navigateTo({ + url: `/subpackages/social/user-preview/user-preview?customId=${senderId}` + }); + } + } catch (err) { + console.error('× 查询好友关系失败:', err); + wx.hideLoading(); + const senderId = e.currentTarget.dataset.senderId; + if (senderId) { + wx.navigateTo({ + url: `/subpackages/social/user-preview/user-preview?customId=${senderId}` + }); + } + } + }, + + async onLoad(options) { + + // 显示加载状态 + this.setData({ isLoading: true }); + + // 初始化系统信息(同步,立即完成) + this.initSystemInfo(); + + // 检查 NIM 状态 + const appInstance = getApp(); + this.nim = appInstance?.globalData?.nim || null; + this._nimOldestMessage = null; + + if (!this.nim || !this.nim.V2NIMMessageService || !this.nim.V2NIMConversationService) { + console.error('❌ NIM 服务不可用'); + wx.showToast({ + title: 'NIM服务不可用', + icon: 'none' + }); + return; + } + + console.log('✅ NIM消息服务可用,启用NIM模式加载消息'); + + // 并行初始化用户与聊天信息 + const userInfoPromise = this.initUserInfo(); + const chatInfoPromise = this.initChatInfo(options); + + await userInfoPromise; + + await chatInfoPromise; + + // 隐藏加载状态 + this.setData({ isLoading: false }); + + // 注册 NIM 监听器 + this.attachNIMListeners(); + }, + + onShow: function () { + console.log('聊天页面显示'); + + // 🔥 检查并重连 NIM(防止从后台恢复后 NIM 断开) + this.checkAndReconnectNim(); + + // 进入聊天页面时自动标记所有消息已读 + this.markAllMessagesRead(); + }, + + onReady() { + // 页面已就绪,获取输入框区域的实际高度 + this.updateInputAreaHeight(); + }, + + // 更新输入框区域高度 + updateInputAreaHeight() { + wx.createSelectorQuery() + .select('.input-area') + .boundingClientRect(rect => { + if (rect && rect.height) { + console.log('📏 输入框区域高度:', rect.height); + this.setData({ + inputAreaHeight: rect.height + }); + } + }) + .exec(); + }, + + onHide: function () { + // 页面隐藏时可以保持会话状态 + }, + + onUnload: function () { + // 🔥 清理录音相关定时器 + if (this.voiceStartTimer) { + clearTimeout(this.voiceStartTimer); + this.voiceStartTimer = null; + } + + // 页面卸载时清理 NIM 监听器 + this.detachNIMListeners(); + }, + + // 注册 NIM 事件监听器 + attachNIMListeners() { + console.log('📡 注册 NIM 事件监听器'); + + const nim = getApp().globalData.nim; + if (!nim || !nim.V2NIMMessageService) { + console.warn('⚠️ NIM SDK 不可用,无法注册监听器'); + return; + } + + // 🔥 使用 bind(this) 确保回调中的 this 上下文正确 + // 监听新消息 + this._nimMessageListener = this.handleNewNIMMessage.bind(this); + + // 🔥 监听消息撤回通知 + this._nimMessageRevokeListener = this.handleMessageRevokeNotifications.bind(this); + + // 注册监听器(根据NIM SDK文档调整) + try { + nim.V2NIMMessageService.on('onReceiveMessages', this._nimMessageListener); + nim.V2NIMMessageService.on('onMessageRevokeNotifications', this._nimMessageRevokeListener); + console.log('✅ NIM 监听器注册成功'); + } catch (error) { + console.error('❌ 注册 NIM 监听器失败:', error); + } + }, + + // 清理 NIM 事件监听器 + detachNIMListeners() { + console.log('🔌 清理 NIM 事件监听器'); + + const nim = getApp().globalData.nim; + if (!nim || !nim.V2NIMMessageService) { + return; + } + + try { + if (this._nimMessageListener) { + nim.V2NIMMessageService.off('onReceiveMessages', this._nimMessageListener); + this._nimMessageListener = null; + } + if (this._nimMessageRevokeListener) { + nim.V2NIMMessageService.off('onMessageRevokeNotifications', this._nimMessageRevokeListener); + this._nimMessageRevokeListener = null; + } + console.log('✅ NIM 监听器清理成功'); + } catch (error) { + console.error('❌ 清理 NIM 监听器失败:', error); + } + }, + + // 🔥 检查并重连 NIM(页面级别) + async checkAndReconnectNim() { + try { + const app = getApp(); + + // 触发全局 NIM 重连检查 + if (app && typeof app.checkAndReconnectNim === 'function') { + await app.checkAndReconnectNim(); + } + + // 检查 NIM 实例是否可用 + const nim = app.globalData.nim; + if (!nim || !nim.V2NIMMessageService) { + console.warn('⚠️ NIM 实例不可用'); + return; + } + + // 重新注册事件监听器(确保监听器有效) + if (!this._nimMessageListener || !this._nimMessageRevokeListener) { + console.log('🔄 重新注册 NIM 事件监听器'); + this.detachNIMListeners(); // 先清理旧的 + this.attachNIMListeners(); // 重新注册 + } + + // 检查会话管理器状态 + if (!nimConversationManager.getInitStatus()) { + console.log('🔄 重新初始化会话管理器'); + nimConversationManager.init(nim); + } + + console.log('✅ 聊天页面 NIM 状态检查完成'); + } catch (error) { + console.error('❌ 聊天页面 NIM 重连检查失败:', error); + } + }, + + // 处理 NIM 新消息 + async handleNewNIMMessage(messages) { + try { + console.log('📨 处理 NIM 新消息,数量:', messages?.length || 0); + + // 🔥 NIM SDK V2 的 onReceiveMessages 回调参数是消息数组 + if (!Array.isArray(messages) || messages.length === 0) { + console.warn('⚠️ 收到空消息数组或非数组数据'); + return; + } + + // 过滤出属于当前会话的消息 + const currentConversationMessages = messages.filter( + msg => msg.conversationId === this.data.conversationId + ); + + if (currentConversationMessages.length === 0) { + console.log('⚠️ 没有属于当前会话的消息,跳过'); + return; + } + + console.log('✅ 收到当前会话的新消息:', currentConversationMessages.length, '条'); + + // 格式化所有新消息 + const formattedMessages = await Promise.all( + currentConversationMessages.map(msg => this.formatMessage(msg)) + ); + + // 去重处理 - 防止重复显示已存在的消息 + const existingIds = new Set(this.data.messages.map(msg => msg.messageId)); + const uniqueNewMessages = formattedMessages.filter( + msg => !existingIds.has(msg.messageId) + ); + + if (uniqueNewMessages.length === 0) { + console.log('⚠️ 所有新消息均已存在,跳过重复添加'); + return; + } + + console.log('✅ 去重后新消息数量:', uniqueNewMessages.length); + + // 添加到消息列表 + const updatedMessages = this.data.messages.concat(uniqueNewMessages); + this.setMessagesWithDate(updatedMessages); + + // 滚动到底部 + setTimeout(() => this.scrollToBottom(), 100); + + // 标记已读 + await nimConversationManager.markConversationRead(this.data.conversationId); + + console.log('✅ 新消息处理完成'); + } catch (error) { + console.error('❌ 处理新消息失败:', error); + } + }, + + // 处理消息撤回通知 + handleMessageRevokeNotifications(revokeNotifications) { + try { + if (!Array.isArray(revokeNotifications) || revokeNotifications.length === 0) { + return; + } + + // 过滤出属于当前会话的撤回通知 + const currentConversationRevokes = revokeNotifications.filter( + revoke => revoke.messageRefer?.conversationId === this.data.conversationId + ); + + if (currentConversationRevokes.length === 0) { + return; + } + + // 更新本地消息状态 + currentConversationRevokes.forEach(revoke => { + const messageRefer = revoke.messageRefer; + if (!messageRefer) return; + + const messageServerId = messageRefer.messageServerId; + const messageClientId = messageRefer.messageClientId; + + // 尝试找到匹配的消息 + let foundMessage = null; + + // 方式1: 通过 messageServerId 查找 + if (messageServerId) { + foundMessage = this.data.messages.find(m => + m.messageId === messageServerId || + m._rawMessage?.messageServerId === messageServerId + ); + } + + // 方式2: 通过 messageClientId 查找 + if (!foundMessage && messageClientId) { + foundMessage = this.data.messages.find(m => + m.messageId === messageClientId || + m._rawMessage?.messageClientId === messageClientId + ); + } + + if (foundMessage) { + this.updateMessageToRecalled(foundMessage.messageId); + } + }); + } catch (error) { + console.error('处理撤回通知失败:', error); + } + }, + + // 初始化系统信息 + initSystemInfo() { + const pageSystemInfo = initPageSystemInfo(); + + this.setData({ + systemInfo: pageSystemInfo.systemInfo, + statusBarHeight: pageSystemInfo.statusBarHeight, + menuButtonHeight: pageSystemInfo.menuButtonHeight, + menuButtonTop: pageSystemInfo.menuButtonTop, + navBarHeight: pageSystemInfo.navBarHeight, + windowHeight: pageSystemInfo.windowHeight, + safeAreaBottom: pageSystemInfo.safeAreaBottom, + keyboardHeight: 0 // 初始化键盘高度 + }); + }, + + // 🔥 监听键盘高度变化 + onKeyboardHeightChange(e) { + const { height, duration } = e.detail; + + const inputAreaHeight = this.data.inputAreaHeight; + const totalBottom = inputAreaHeight + (height || 0); + + console.log('⌨️ 键盘高度变化:', { + keyboardHeight: height, + inputAreaHeight, + totalBottom, + duration + }); + + // 直接使用微信提供的键盘高度(单位:px) + this.setData({ + keyboardHeight: height || 0 + }, () => { + // 键盘弹出时,滚动到底部,确保最新消息可见 + if (height > 0) { + this.scrollToBottom(true); + } + }); + }, + + // 初始化聊天信息 + async initChatInfo(options) { + const inputConversationId = options.conversationId || ''; + const targetId = options.targetId || ''; + const chatName = decodeURIComponent(options.name || '聊天'); + const chatType = parseInt(options.chatType || 0); + const incomingTargetAvatar = options.targetAvatar || ''; + const sendMessage = options.sendMessage?.trim() || ''; + + // 临时设置基本信息 + this.setData({ + targetId, + chatName, + chatType, + inputText: sendMessage, + conversationId: inputConversationId, + targetAvatar: incomingTargetAvatar || this.data.targetAvatar || '' + }); + + // 🔥 动态设置导航栏标题为用户昵称 + wx.setNavigationBarTitle({ + title: chatName + }); + + // 🔥 从 NIM 获取对方用户信息(头像和昵称) + // 注意:如果 targetId 是会话ID格式(如 "p2p-xxx" 或 "16950956|1|33981539"),需要提取真实用户ID + if (targetId) { + let realUserId = targetId; + + // 🔥 如果是 NIM 会话ID格式(包含 | 分隔符),提取真实用户ID + // 格式:senderId|conversationType|receiverId(如 "16950956|1|33981539") + if (targetId.includes('|')) { + const parts = targetId.split('|'); + if (parts.length >= 3) { + // 对于单聊(type=1),receiverId 是对方用户ID(parts[2]) + realUserId = parts[2]; + console.log('🔧 从会话ID提取用户ID:', { conversationId: targetId, userId: realUserId }); + } + } + + await this.loadTargetUserInfo(realUserId); + } + + // 🔥 如果没有传入conversationId,先检查会话是否已存在 + if (!inputConversationId) { + console.log('🔍 未传入会话ID,检查是否已存在该会话'); + + if (!targetId) { + console.error('❌ 缺少 targetId,无法查询会话'); + return; + } + + // 使用NIM生成会话ID + const conversationId = this.buildNIMConversationId(targetId, chatType); + if (!conversationId) { + console.error('❌ 无法生成会话ID'); + return; + } + + console.log('🔍 生成的会话ID:', conversationId); + + // 🔥 检查会话是否已存在(从NIM SDK获取会话列表查询) + try { + const nim = getApp().globalData.nim; + if (nim && nim.V2NIMConversationService) { + // 🔥 获取会话列表并查找目标会话 + console.log('🔍 从NIM SDK查询会话是否存在...'); + const result = await nim.V2NIMConversationService.getConversationList(0, 100); + const existingConv = result?.conversationList?.find(c => c.conversationId === conversationId); + + if (existingConv) { + console.log('✅ 会话已存在,使用现有会话:', existingConv); + this.setData({ + conversationId, + isNewConversation: false + }); + + // 加载消息 + await this.loadMessages(); + return; + } else { + console.log('📝 会话不存在,标记为新会话'); + } + } + } catch (error) { + console.warn('⚠️ 查询会话失败,将作为新会话处理:', error); + } + + // 🔥 会话不存在,标记为新会话(不加载历史消息) + console.log('✅ 创建新会话ID:', conversationId); + this.setData({ + conversationId, + isNewConversation: true, + messages: [] + }); + return; + } + + // 使用传入的conversationId + this.setData({ conversationId: inputConversationId }); + + // 加载消息 + await this.loadMessages(); + }, + + // 🔥 验证并使用传入的会话ID + buildNIMConversationId(targetId, chatType) { + try { + if (!this.nim || !this.nim.V2NIMConversationIdUtil) { + return ''; + } + if (!targetId) { + return ''; + } + if (Number(chatType) === 1) { + return this.nim.V2NIMConversationIdUtil.teamConversationId(String(targetId)); + } + return this.nim.V2NIMConversationIdUtil.p2pConversationId(String(targetId)); + } catch (err) { + console.warn('构造 NIM 会话ID 失败:', err); + return ''; + } + }, + + // 🔥 从 NIM SDK 获取对方用户信息(包括头像和昵称) + async loadTargetUserInfo(targetId) { + try { + console.log('📡 从 NIM 获取用户信息:', targetId); + + // 🔥 使用 NIM SDK 获取用户信息 + const userInfo = await nimUserManager.getUserInfo(targetId); + + if (userInfo) { + const targetAvatar = userInfo.avatar || ''; + const targetNickname = userInfo.nickname || ''; + + // 🔥 先设置用户信息,头像缓存异步执行 + this.setData({ + targetUserInfo: { + avatar: targetAvatar, + nickname: targetNickname + }, + targetAvatar: targetAvatar, // 先使用原始URL + chatName: targetNickname || this.data.chatName // 更新聊天名称 + }); + + console.log('✅ 用户信息加载成功(从 NIM):', { targetNickname, targetAvatar }); + + // 🔥 异步缓存头像,不阻塞UI + if (targetAvatar) { + imageCacheManager.cacheAvatar(targetAvatar).then(cachedAvatar => { + this.setData({ + targetAvatar: cachedAvatar + }); + }).catch(error => { + console.error('❌ 对方头像缓存失败:', error); + }); + } + } else { + console.warn('⚠️ 从 NIM 未获取到用户信息'); + } + + } catch (error) { + console.error('❌ 从 NIM 获取用户信息异常:', error); + } + }, + + // 初始化用户信息 + async initUserInfo() { + // 先尝试从全局获取 + let userInfo = app.globalData.userInfo; + + // 如果全局没有,尝试从本地存储获取 + if (!userInfo || !userInfo.token) { + try { + const storedUserInfo = wx.getStorageSync('userInfo'); + if (storedUserInfo && storedUserInfo.token) { + userInfo = storedUserInfo; + // 更新全局数据 + app.globalData.userInfo = userInfo; + app.globalData.isLoggedIn = true; + + } + } catch (error) { + console.error('从本地存储获取用户信息失败:', error); + } + } + + // 确保有用户信息 + if (userInfo && userInfo.token) { + // 正确获取用户头像 + const userAvatar = userInfo.user?.avatar || userInfo.avatar || ''; + + + // 🔥 先设置用户信息,头像缓存异步执行 + this.setData({ + userInfo: userInfo, + userAvatar: userAvatar // 先使用原始URL + }); + + // 🔥 异步缓存头像,不阻塞UI + imageCacheManager.cacheAvatar(userAvatar).then(cachedAvatar => { + this.setData({ + userAvatar: cachedAvatar + }); + + }).catch(error => { + console.error('❌ 用户头像缓存失败:', error); + }); + + } else { + console.error('用户信息初始化失败,跳转到登录页'); + wx.reLaunch({ + url: '/pages/login/login' + }); + } + }, + + // 加载消息 - 使用 NIM SDK + async loadMessages(isLoadMore = false) { + try { + console.log('📨 加载聊天消息 (NIM SDK):', { + isLoadMore, + conversationId: this.data.conversationId + }); + + // 检查 conversationId + if (!this.data.conversationId) { + console.log('⚠️ 缺少 conversationId,无法加载消息'); + return; + } + + // 避免重复请求 + if (this.data.loadingMessages) { + console.log('⚠️ 消息正在加载中,跳过重复请求'); + return; + } + + // 设置加载状态 + this.setData({ loadingMessages: true }); + + // 获取 NIM 实例 + const nim = getApp().globalData.nim; + if (!nim || !nim.V2NIMMessageService) { + throw new Error('NIM SDK 未初始化'); + } + + // 使用 NIM SDK 获取历史消息 + const limit = 20; + const option = { + conversationId: this.data.conversationId, + endTime: isLoadMore && this.data.lastMessageTime ? this.data.lastMessageTime : Date.now(), + limit: limit, + direction: 0 // 1 表示查询比 endTime 更早的消息 + }; + + console.log('📡 查询参数:', option); + + const result = await nim.V2NIMMessageService.getMessageList(option); + + if (!result) { + console.log('⚠️ NIM SDK 返回空结果'); + this.setData({ loadingMessages: false, hasMore: false }); + return; + } + + const newMessages = result || []; + console.log('✅ NIM 消息回调:', newMessages); + console.log('✅ 从 NIM 获取到消息:', newMessages.length, '条'); + + // 格式化消息 + const formattedMessages = await Promise.all( + newMessages.map(msg => this.formatMessage(msg)) + ); + + // 判断是否是首次加载 + const isFirstLoad = this.data.messages.length === 0; + + // 去重处理 + const existingIds = new Set(this.data.messages.map(msg => msg.messageId)); + const uniqueNewMessages = formattedMessages.filter( + msg => !existingIds.has(msg.messageId) + ); + + // 合并并排序消息 + let sortedMessages; + if (isFirstLoad) { + sortedMessages = uniqueNewMessages.sort((a, b) => a.timestamp - b.timestamp); + } else { + const allMessages = uniqueNewMessages.concat(this.data.messages); + sortedMessages = allMessages.sort((a, b) => a.timestamp - b.timestamp); + } + + // 更新 lastMessageTime(最早消息的时间戳,用于分页) + const earliestMessage = newMessages.length > 0 + ? newMessages[newMessages.length - 1] + : null; + const newLastMessageTime = earliestMessage?.createTime || earliestMessage?.timestamp || 0; + + // 添加日期分隔符 + const annotated = this.recomputeDateDividers(this._filterDeleted(sortedMessages)); + + // 更新数据 + this.setData({ + messages: annotated, + hasMore: newMessages.length === limit, + lastMessageTime: newLastMessageTime, + loadingMessages: false + }); + + console.log('✅ 消息加载完成:', { + totalMessages: sortedMessages.length, + hasMore: newMessages.length === limit, + lastMessageTime: newLastMessageTime + }); + + // 首次加载时滚动到底部 + if (isFirstLoad && this.data.messages.length > 0) { + setTimeout(() => this.scrollToBottom(), 100); + } + } catch (error) { + console.error('❌ 加载消息失败:', error); + this.setData({ + hasMore: false, + loadingMessages: false + }); + wx.showToast({ + title: '加载消息失败', + icon: 'none' + }); + } + }, + + // 格式化消息 - 适配接口文档的数据结构,特殊处理图片消息 + async formatMessage(msgData) { + // 获取当前用户的NIM账号ID(用于判断消息是否为自己发送) + let currentNimAccountId = this.data.userInfo?.neteaseIMAccid || this.data.userInfo?.user?.neteaseIMAccid || ''; + + // 如果从data中获取不到,尝试从全局获取 + if (!currentNimAccountId) { + const app = getApp(); + const globalUserInfo = app.globalData.userInfo; + currentNimAccountId = globalUserInfo?.neteaseIMAccid || globalUserInfo?.user?.neteaseIMAccid || ''; + } + + // 如果还是获取不到,尝试从本地存储获取 + if (!currentNimAccountId) { + try { + const storedUserInfo = wx.getStorageSync('userInfo'); + currentNimAccountId = storedUserInfo?.neteaseIMAccid || storedUserInfo?.user?.neteaseIMAccid || ''; + } catch (error) { + console.error('从本地存储获取NIM账号ID失败:', error); + } + } + + // 适配 NIM SDK V2 官方字段名 + const senderId = msgData.senderId || msgData.senderAccountId; + const messageId = msgData.messageClientId || msgData.messageServerId || msgData.id || msgData.messageId; + const isSelf = senderId === currentNimAccountId; + + // 🔥 直接使用 NIM SDK V2 的 messageType 枚举值(无需转换) + // V2NIMMessageType: 0=文本, 1=图片, 2=语音, 3=视频, 4=位置, 5=通知, 6=文件, 10=提示, 100=自定义 + let messageType = msgData.messageType !== undefined ? msgData.messageType : msgData.msgType; + + // 🔥 获取消息内容 - NIM SDK V2 使用 text(文本) 或 attachment(附件) + let _rawContent; + if (msgData.text !== undefined && msgData.text !== null) { + _rawContent = msgData.text; + } else if (msgData.attachment !== undefined && msgData.attachment !== null) { + _rawContent = msgData.attachment; + } else if (msgData.content !== undefined && msgData.content !== null) { + _rawContent = msgData.content; + } else { + _rawContent = ''; + } + + // 标记为图片消息(1)但内容不是可用图片 -> 降级为文本(0) + if (messageType === 1) { + let hasValidImage = false; + try { + if (typeof _rawContent === 'string') { + const s = _rawContent.trim(); + if (/^https?:\/\//i.test(s) || /^data:image\//i.test(s)) { + hasValidImage = true; + } else if (s.startsWith('{') && s.endsWith('}')) { + const obj = JSON.parse(s); + const u = obj?.file_url || obj?.url; + hasValidImage = !!u; + } + } else if (typeof _rawContent === 'object' && _rawContent !== null) { + const u = _rawContent.file_url || _rawContent.url; + hasValidImage = !!u; + } + } catch (_) { hasValidImage = false; } + if (!hasValidImage) { + console.log('🔧 检测到图片类型但无有效URL,降级为文本'); + messageType = 0; // 降级为文本 + } + } + // 标记为文本(0)但内容像图片 -> 升级为图片(1) + if (messageType === 0 && this._looksLikeImageContent(_rawContent)) { + console.log('🖼️ 文本消息内容识别为图片,自动升级为图片类型'); + messageType = 1; + } + + // 🔥 撤回态识别(历史记录/服务端数据) + // 注意:撤回状态应该通过 msgData.isRecalled 字段判断,不应该依赖 sendingState + // sendingState 枚举值: 0=未知, 1=成功, 2=失败, 3=发送中 + const recalledFromServer = !!msgData.isRecalled; // 只通过 isRecalled 字段判断是否撤回 + + // 🔥 特殊处理媒体消息内容 + let processedContent = _rawContent; + if (messageType === 1) { // 图片 + processedContent = await this.parseImageContent(_rawContent); + console.log('🖼️ 图片消息处理结果:', processedContent); + } else if (messageType === 2) { // 语音 + processedContent = this.parseVoiceContent(_rawContent); + console.log('🎤 语音消息处理结果:', processedContent); + } else if (messageType === 6) { // 文件 + processedContent = this.parseFileContent(_rawContent); + console.log('📄 文件消息处理结果:', processedContent); + } else if (messageType === 4) { // 位置 + processedContent = this.parseLocationContent(_rawContent); + console.log('📍 位置消息处理结果:', processedContent); + } else if (messageType === 3) { // 视频 + processedContent = this.parseVideoContent(_rawContent); + console.log('🎬 视频消息处理结果:', processedContent); + } else if (messageType === 0) { // 文本 + processedContent = msgData.text || _rawContent; + } + + // 🔥 统一时间戳字段 - NIM SDK V2 使用 createTime + let timestamp = 0; + try { + // 优先使用 createTime,兼容其他时间字段 + if (typeof msgData.createTime === 'number') { + timestamp = msgData.createTime; + } else if (typeof msgData.sendTime === 'number') { + timestamp = msgData.sendTime; + } else if (typeof msgData.sendTime === 'string') { + const t = Date.parse(msgData.sendTime); + timestamp = isNaN(t) ? Date.now() : t; + } else { + timestamp = Number(msgData.timestamp || Date.now()); + } + } catch (_) { + timestamp = Date.now(); + } + + // 🔥 获取发送者头像(已通过 NIM getUserInfo 获取并缓存) + const senderAvatar = isSelf ? (this.data.userAvatar || '') : (this.data.targetAvatar || ''); + + // 🔥 处理消息发送状态 + let deliveryStatus; + if (isSelf) { + // 根据官方文档的正确枚举值处理 + if (msgData.sendingState === 3) { + deliveryStatus = 3; // 发送中 (V2NIM_MESSAGE_SENDING_STATE_SENDING) + } else if (msgData.sendingState === 2) { + deliveryStatus = 2; // 发送失败 (V2NIM_MESSAGE_SENDING_STATE_FAILED) + } else { + // 对于历史消息,默认为成功状态 + // 包括: sendingState为0(未知)、1(成功)、undefined、null或其他值的情况 + deliveryStatus = 1; // V2NIM_MESSAGE_SENDING_STATE_SUCCEEDED + console.log('📜 历史消息状态设为成功:', { + messageId: msgData.messageClientId || msgData.messageServerId, + sendingState: msgData.sendingState, + status: msgData.status, + finalStatus: deliveryStatus + }); + } + } else { + // 对方消息:成功状态 + deliveryStatus = 1; + } + + const baseMessage = { + messageId: messageId, + senderId: senderId, + targetId: msgData.receiverId || msgData.targetId, + content: processedContent, + msgType: this.convertMessageTypeToString(messageType), // 🔥 转换为字符串类型 (text/image/audio/video/location/file) + sendTime: timestamp, + timestamp: timestamp, + isSelf: isSelf, + senderName: msgData.senderName || (isSelf ? '我' : '对方'), + senderAvatar: senderAvatar, + deliveryStatus: deliveryStatus, + bubbleTime: this.formatBubbleTime(timestamp), + _rawMessage: msgData // 🔥 保存 NIM SDK 原始消息对象,用于撤回等操作 + }; + + // 🔥 调试:查看消息状态转换结果 + console.log('🔍 消息状态转换:', { + isSelf: isSelf, + sendingState: msgData.sendingState, + status: msgData.status, + deliveryStatus: baseMessage.deliveryStatus, + messageId: baseMessage.messageId, + messageType: 'formatMessage调用 - 历史消息处理' + }); + + // NIM SDK V2 撤回的消息会通过 onMessageRevokeNotifications 事件通知 + if (recalledFromServer) { + return { + ...baseMessage, + isRecalled: true, + msgType: 'system', // 🔥 系统消息类型使用字符串 + content: isSelf ? '你撤回了一条消息' : (msgData.senderName ? `${msgData.senderName}撤回了一条消息` : '对方撤回了一条消息'), + originalContent: processedContent + }; + } + + // 文件消息补充文件展示字段,便于WXML直接使用 + if (messageType === 6) { // 文件 + return { + ...baseMessage, + fileName: processedContent.fileName || msgData.fileName || '', + fileSize: this.formatFileSize(processedContent.fileSize || msgData.fileSize || 0), + fileType: processedContent.fileType || msgData.fileType || '' + }; + } + + // 🔥 位置消息:为兼容旧渲染逻辑,将名称/地址/经纬度同步到根级字段,避免显示默认“位置” + if (messageType === 4) { // 位置 + return { + ...baseMessage, + locationName: processedContent?.locationName || msgData.locationName || '位置', + locationAddress: processedContent?.address || msgData.locationAddress || '', + latitude: processedContent?.latitude, + longitude: processedContent?.longitude + }; + } + + // 🔥 视频消息:将URL和缩略图同步到根级字段,兼容WXML渲染 + if (messageType === 3) { // 视频 + return { + ...baseMessage, + content: processedContent.url || processedContent, // WXML 中使用 item.content 作为 src + thumbnail: processedContent.thumbnail || '', + duration: processedContent.duration || 0, + videoUrl: processedContent.url || '' + }; + } + + // 🔥 最终调试输出 + console.log('✅ formatMessage 完成:', { + messageId, + msgType: baseMessage.msgType, // 使用转换后的字符串类型 + msgTypeNumber: messageType, // 原始数字类型(用于调试) + content: processedContent, + deliveryStatus: baseMessage.deliveryStatus, + isSelf, + timestamp + }); + + return baseMessage; + }, + + // 🔥 解析语音内容 - 支持 NIM SDK V2 的 attachment 对象格式 + parseVoiceContent(content) { + try { + if (!content) return { url: '', duration: 0 }; + + // NIM SDK V2 的语音附件对象格式 + // attachment 通常包含: url, dur (duration), size 等字段 + if (typeof content === 'object' && content !== null) { + const url = content.url || content.path || content.voiceUrl || ''; + const duration = content.dur || content.duration || 0; // NIM SDK V2 使用 dur + const size = content.size || content.fileSize || 0; + + console.log('🎤 语音附件对象解析:', { url, duration, size }); + return { url, duration, size }; + } + + // 如果是字符串,尝试JSON解析 + if (typeof content === 'string') { + const trimmed = content.trim(); + if (trimmed.startsWith('{') && trimmed.endsWith('}')) { + try { + const obj = JSON.parse(trimmed); + const url = obj.url || obj.path || obj.voiceUrl || ''; + const duration = obj.dur || obj.duration || 0; + const size = obj.size || obj.fileSize || 0; + return { url, duration, size }; + } catch (e) { + // 继续按URL兜底 + } + } + // 直接当作URL使用 + return { url: trimmed, duration: 0 }; + } + + return { url: '', duration: 0 }; + } catch (error) { + console.error('❌ 解析语音内容失败:', error, content); + return { url: '', duration: 0 }; + } + }, + + // 🔥 解析文件内容 - 支持 NIM SDK V2 的 attachment 对象格式 + parseFileContent(content) { + try { + if (!content) return { url: '', fileName: '', fileSize: 0 }; + + // NIM SDK V2 的文件附件对象格式 + if (typeof content === 'object' && content !== null) { + const url = content.url || content.path || content.file_url || content.fileUrl || ''; + const fileName = content.name || content.fileName || content.file_name || ''; + const fileSize = content.size || content.fileSize || content.file_size || 0; + const ext = content.ext || content.fileType || content.file_type || ''; + + console.log('📄 文件附件对象解析:', { url, fileName, fileSize, ext }); + return { url, fileName, fileSize, fileType: ext }; + } + + // JSON字符串 + if (typeof content === 'string') { + const trimmed = content.trim(); + if (trimmed.startsWith('{') && trimmed.endsWith('}')) { + try { + const obj = JSON.parse(trimmed); + const url = obj.url || obj.path || obj.file_url || obj.fileUrl || ''; + const fileName = obj.name || obj.fileName || obj.file_name || ''; + const fileSize = obj.size || obj.fileSize || obj.file_size || 0; + const fileType = obj.ext || obj.fileType || obj.file_type || ''; + return { url, fileName, fileSize, fileType }; + } catch (e) { + // fallthrough to plain URL + } + } + // 纯URL + return { url: trimmed, fileName: '', fileSize: 0 }; + } + + return { url: '', fileName: '', fileSize: 0 }; + } catch (error) { + console.error('❌ 解析文件内容失败:', error, content); + return { url: '', fileName: '', fileSize: 0 }; + } + }, + + // 🔥 解析位置内容 - 支持 NIM SDK V2 的 attachment 对象格式 + parseLocationContent(content) { + try { + if (!content) return null; + let obj = content; + + // NIM SDK V2 的位置附件对象格式 + // attachment 通常包含: lat, lng, title, address 等字段 + if (typeof content === 'string') { + const trimmed = content.trim(); + if (trimmed.startsWith('{') && trimmed.endsWith('}')) { + try { + obj = JSON.parse(trimmed); + } catch (e) { + return null; + } + } else { + // 非JSON字符串,无法解析 + return null; + } + } + + // NIM SDK V2 使用 lat/lng,兼容 latitude/longitude + const lat = obj.lat ?? obj.latitude; + const lng = obj.lng ?? obj.longitude; + const address = obj.address || obj.addr || ''; + const locationName = obj.title || obj.locationName || obj.name || '位置'; + + console.log('📍 位置附件对象解析:', { lat, lng, address, locationName }); + + if (lat == null || lng == null) return null; + return { latitude: Number(lat), longitude: Number(lng), address, locationName }; + } catch (err) { + console.error('❌ 解析位置内容失败:', err, content); + return null; + } + }, + + // 🔥 解析视频内容 - 支持 NIM SDK V2 的 attachment 对象格式 + parseVideoContent(content) { + try { + if (!content) return { url: '', thumbnail: '' }; + + // NIM SDK V2 的视频附件对象格式 + if (typeof content === 'object' && content !== null) { + const url = content.url || content.path || ''; + const thumbnail = content.thumbUrl || content.coverUrl || content.thumbnail || ''; + const duration = content.dur || content.duration || 0; + const size = content.size || content.fileSize || 0; + const width = content.width || content.w || 0; + const height = content.height || content.h || 0; + + console.log('🎬 视频附件对象解析:', { url, thumbnail, duration, size, width, height }); + return { url, thumbnail, duration, size, width, height }; + } + + // JSON 字符串 + if (typeof content === 'string') { + const trimmed = content.trim(); + if (trimmed.startsWith('{') && trimmed.endsWith('}')) { + try { + const obj = JSON.parse(trimmed); + const url = obj.url || obj.path || ''; + const thumbnail = obj.thumbUrl || obj.coverUrl || obj.thumbnail || ''; + const duration = obj.dur || obj.duration || 0; + return { url, thumbnail, duration }; + } catch (e) { + // 继续按URL兜底 + } + } + // 直接当作URL使用 + return { url: trimmed, thumbnail: '' }; + } + + return { url: '', thumbnail: '' }; + } catch (error) { + console.error('❌ 解析视频内容失败:', error, content); + return { url: '', thumbnail: '' }; + } + }, + + // 🔥 根据官方文档,NIM SDK V2 的正确枚举值(0=未知, 1=成功, 2=失败, 3=发送中) + convertStatus(apiStatus) { + // NIM SDK V2 的 V2NIMMessageSendingState 枚举: + // V2NIM_MESSAGE_SENDING_STATE_UNKNOWN = 0 (未知状态) + // V2NIM_MESSAGE_SENDING_STATE_SUCCEEDED = 1 (发送成功) + // V2NIM_MESSAGE_SENDING_STATE_FAILED = 2 (发送失败) + // V2NIM_MESSAGE_SENDING_STATE_SENDING = 3 (发送中) + + console.log('🔄 convertStatus 输入:', { + apiStatus, + type: typeof apiStatus, + isUndefined: apiStatus === undefined, + isNull: apiStatus === null + }); + + // 🔥 直接返回数字枚举值,不转换为字符串 + // undefined/null 默认为成功状态 1 (历史消息通常没有状态字段,说明已成功) + if (apiStatus === undefined || apiStatus === null) { + console.log('🔄 状态映射 convertStatus: undefined/null -> 1 (历史消息默认成功)'); + return 1; // V2NIM_MESSAGE_SENDING_STATE_SUCCEEDED + } + + // 如果已经是数字,直接返回 + if (typeof apiStatus === 'number') { + // 验证是否为有效的 sendingState 枚举值 (0, 1, 2, 3) + if (apiStatus === 0 || apiStatus === 1 || apiStatus === 2 || apiStatus === 3) { + console.log('🔄 状态映射 convertStatus:', apiStatus, '(有效枚举值,保持不变)'); + return apiStatus; + } + // 对于历史消息,其他数字状态也默认为成功(因为能从服务器获取到说明已发送成功) + console.log('🔄 状态映射 convertStatus:', apiStatus, '-> 1 (历史消息其他数字状态,默认成功)'); + return 1; + } + + // 字符串状态转换为枚举值 + const s = String(apiStatus).toLowerCase(); + let result; + if (s === 'succeeded' || s === 'success' || s === 'sent' || s === 'delivered') { + result = 1; // SUCCEEDED + } else if (s === 'failed' || s === 'fail') { + result = 2; // FAILED + } else if (s === 'sending') { + result = 3; // SENDING + } else { + // 对于历史消息,未知状态默认为成功 + result = 1; // 默认成功 + } + + console.log('🔄 状态映射 convertStatus:', apiStatus, '->', result, '(历史消息处理)'); + return result; + }, + + // 🔥 解析图片内容 - 支持 NIM SDK V2 的 attachment 对象格式 + async parseImageContent(content) { + try { + + if (!content) return { type: 'url', url: '' }; + + // 1) NIM SDK V2 的 attachment 对象格式 + // attachment 通常包含: url, name, size, width, height 等字段 + if (typeof content === 'object') { + // NIM SDK V2 图片附件字段 + const url = content.url || content.file_url || content.path || ''; + const fileName = content.name || content.fileName || content.file_name || ''; + const fileSize = content.size || content.fileSize || content.file_size || 0; + const width = content.width || content.w || 0; + const height = content.height || content.h || 0; + + console.log('🖼️ 图片附件对象解析:', { url, fileName, fileSize, width, height }); + + if (/^data:image\//i.test(url)) { + return { type: 'base64', url, fileName, fileSize, width, height }; + } + if (url) { + const cachedUrl = await imageCacheManager.preloadImage(url); + return { type: 'url', url: cachedUrl, fileName, fileSize, width, height }; + } + // 对象但无 url,视为错误 + return { type: 'error', url: '', error: '图片内容缺少URL', originalContent: JSON.stringify(content).slice(0, 200) }; + } + + // 2) 字符串:Base64 + if (typeof content === 'string' && /^data:image\//i.test(content)) { + return { type: 'base64', url: content }; + } + + // 3) 字符串:URL + if (typeof content === 'string' && /^https?:\/\//i.test(content)) { + const cachedUrl = await imageCacheManager.preloadImage(content); + return { type: 'url', url: cachedUrl }; + } + + // 4) 字符串:尝试 JSON 解析 + if (typeof content === 'string') { + const s = content.trim(); + if (s.startsWith('{') && s.endsWith('}')) { + try { + const obj = JSON.parse(s); + const u = obj.url || obj.file_url || obj.path || ''; + if (u) { + const cachedUrl = await imageCacheManager.preloadImage(u); + return { + type: /^data:image\//i.test(u) ? 'base64' : 'url', + url: cachedUrl, + fileName: obj.name || obj.file_name || obj.fileName, + fileSize: obj.size || obj.file_size || obj.fileSize, + width: obj.width || obj.w, + height: obj.height || obj.h + }; + } + } catch (e) { + // fallthrough + } + } + } + + // 5) 其他:无法识别,按错误返回,避免把纯文本当图片 + return { type: 'error', url: '', error: '图片内容无效', originalContent: String(content).slice(0, 200) }; + } catch (err) { + console.error('❌ 解析图片内容失败:', err, content); + return { type: 'error', url: '', error: '解析失败', originalContent: String(content).slice(0, 200) }; + } + }, + + // 🔥 新增:解析视频内容,统一返回可用于