From 97c82746d8cb99e439ee433da2415100abac67b2 Mon Sep 17 00:00:00 2001 From: pfewmlupo <3097217416@qq.com> Date: Sun, 17 Nov 2024 20:53:17 +0800 Subject: [PATCH] =?UTF-8?q?Add=20=E6=B3=A8=E9=87=8A=EF=BC=884=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 注释(4) | 442 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 442 insertions(+) create mode 100644 注释(4) diff --git a/注释(4) b/注释(4) new file mode 100644 index 0000000..8428340 --- /dev/null +++ b/注释(4) @@ -0,0 +1,442 @@ +poetizepoetize-im-uisrcApp.vue + + + + + + + + +poetizepoetize-im-uisrcutilstiows.js + +// 导入reconnecting-websocket库,这是一个会自动重连的WebSocket实现 +import ReconnectingWebSocket from 'reconnecting-websocket'; + +/** + * 创建一个WebSocket连接的构造函数 + * @param {string} ws_protocol - WebSocket协议,'wss'用于加密连接,'ws'用于非加密连接 + * @param {string} ip - WebSocket服务器的IP地址 + * @param {string|number} port - WebSocket服务器的端口号,如果为空字符串则不使用端口号 + * @param {string} paramStr - 附加在WebSocket URL后面的请求参数,例如:'name=张三&id=12' + * @param {string} binaryType - WebSocket接收二进制数据的类型,'blob'或'arraybuffer' + */ +export default function (ws_protocol, ip, port, paramStr, binaryType) { + // 将传入的参数赋值给当前对象的属性 + this.ws_protocol = ws_protocol; + this.ip = ip; + this.port = port; + this.paramStr = paramStr; + this.binaryType = binaryType; + + // 根据传入的参数构建WebSocket的URL + if (port === "") { + // 如果端口号为空字符串,则URL不包括端口号 + this.url = ws_protocol + '://' + ip + '/socket'; + } else { + // 否则,URL包括端口号 + this.url = ws_protocol + '://' + ip + ":" + port + '/socket'; + } + // 如果存在请求参数,则将它们添加到URL的末尾 + if (paramStr) { + this.url += '?' + paramStr; + } + + // 定义一个方法用于建立WebSocket连接 + this.connect = () => { + // 创建一个新的ReconnectingWebSocket实例,并传入构建的URL + let ws = new ReconnectingWebSocket(this.url); + // 将创建的WebSocket实例保存到当前对象的ws属性中 + this.ws = ws; + // 设置WebSocket接收二进制数据的类型 + ws.binaryType = this.binaryType; + + // 定义WebSocket连接打开时的回调函数 + ws.onopen = function (event) { + // 在这里可以添加获取离线消息的逻辑,但当前为空实现 + } + + // 定义WebSocket连接关闭时的回调函数 + ws.onclose = function (event) { + // 当前为空实现,可以在这里添加处理连接关闭的逻辑 + } + + // 定义WebSocket发生错误时的回调函数 + ws.onerror = function (event) { + // 当前为空实现,可以在这里添加处理错误的逻辑 + } + } + + // 定义一个方法用于通过WebSocket发送数据 + this.send = (data) => { + // 使用当前对象的ws属性(即WebSocket实例)的send方法发送数据 + this.ws.send(data); + } +} + + +poetizepoetize-im-uisrcutilsrequest.js + +// 导入axios库,用于发送HTTP请求 +import axios from "axios"; +// 导入constant模块,该模块可能包含一些全局常量,如API的基础URL +import constant from "./constant"; +// 导入qs库,用于处理URL参数序列化/反序列化 +import qs from "qs"; + +// 导入Vuex的store实例,用于全局状态管理 +import store from "../store"; + +// 设置axios的默认基础URL +axios.defaults.baseURL = constant.baseURL; + +// 添加请求拦截器 +axios.interceptors.request.use( + function (config) { + // 在请求发送之前,可以在这里添加一些配置或处理逻辑 + // 比如添加token到请求头中(但在这个例子中,token是在每个请求中单独添加的) + return config; // 返回配置对象,继续请求 + }, + function (error) { + // 请求发生错误时的处理逻辑 + // 比如显示错误提示、记录日志等 + return Promise.reject(error); // 返回Promise.reject,中断请求 + } +); + +// 添加响应拦截器 +axios.interceptors.response.use( + function (response) { + // 响应成功时的处理逻辑 + // 检查响应数据中的code,如果不等于200,则视为错误处理 + if ( + response.data !== null && + response.data.hasOwnProperty("code") && + response.data.code !== 200 + ) { + if (response.data.code === 300) { + // 特定错误码处理,比如用户未登录或token过期 + store.commit("loadCurrentUser", {}); // 清除Vuex中的用户信息 + localStorage.removeItem("userToken"); // 移除本地存储中的token + window.location.href = constant.webBaseURL + "/user"; // 重定向到登录页面 + } + return Promise.reject(new Error(response.data.message)); // 返回Promise.reject,中断请求链,并携带错误信息 + } else { + return response; // 返回响应对象,继续后续处理 + } + }, + function (error) { + // 响应发生错误时的处理逻辑 + // 比如显示错误提示、记录日志等 + return Promise.reject(error); // 返回Promise.reject,中断请求链 + } +); + +// 导出HTTP请求工具集 +export default { + // 发送POST请求的方法 + post(url, params = {}, json = true) { + let config = { + headers: { "Authorization": localStorage.getItem("userToken") } // 添加token到请求头 + }; + + return new Promise((resolve, reject) => { + axios + .post( + url, + json ? params : qs.stringify(params), // 根据json参数决定发送的数据格式 + config + ) + .then(res => { + resolve(res.data); // 请求成功,解析并返回响应数据 + }) + .catch(err => { + reject(err); // 请求失败,返回错误信息 + }); + }); + }, + + // 发送GET请求的方法 + get(url, params = {}) { + let headers = { "Authorization": localStorage.getItem("userToken") }; // 添加token到请求头 + + return new Promise((resolve, reject) => { + axios.get(url, { params: params, headers: headers }) // 发送GET请求,携带参数和请求头 + .then(res => { + resolve(res.data); // 请求成功,解析并返回响应数据 + }) + .catch(err => { + reject(err); // 请求失败,返回错误信息 + }); + }); + }, + + // 发送文件上传请求的方法 + upload(url, param, option) { + let config = { + headers: { + "Authorization": localStorage.getItem("userToken"), + "Content-Type": "multipart/form-data" // 设置内容类型为文件上传 + }, + timeout: 60000 // 设置请求超时时间 + }; + if (typeof option !== "undefined") { + // 如果提供了上传进度回调,则添加onUploadProgress监听器 + config.onUploadProgress = progressEvent => { + if (progressEvent.total > 0) { + progressEvent.percent = progressEvent.loaded / progressEvent.total * 100; // 计算上传进度百分比 + } + option.onProgress(progressEvent); // 调用传入的回调,传递进度信息 + }; + } + + return new Promise((resolve, reject) => { + axios + .post(url, param, config) // 发送POST请求,上传文件 + .then(res => { + resolve(res.data); // 请求成功,解析并返回响应数据 + }) + .catch(err => { + reject(err); // 请求失败,返回错误信息 + }); + }); + }, + + // 发送七牛云文件上传请求的方法(可能不需要token,因为七牛云上传通常通过临时凭证) + uploadQiniu(url, param) { + let config = { + headers: { "Content-Type": "multipart/form-data" }, // 设置内容类型为文件上传 + timeout: 60000 // 设置请求超时时间 + }; + + return new Promise((resolve, reject) => { + axios + .post(url, param, config) // 发送POST请求,上传文件到七牛云 + .then(res => { + resolve(res.data); // 请求成功,解析并返回响应数据 + }) + .catch(err => { + reject(err); // 请求失败,返回错误信息 + }); + }); + } +}; + + +poetizepoetize-im-uisrcutilsim.js + +// 引入常量配置文件 +import constant from "./constant"; +// 引入CryptoJS库,用于加密和解密操作 +import CryptoJS from 'crypto-js'; +// 引入Vuex的store实例,用于全局状态管理 +import store from '../store'; +// 引入Element Plus库的ElMessage组件,用于显示消息提示 +import {ElMessage} from "element-plus"; + +// 导出一个包含多个工具函数的对象 +export default { + /** + * 判断当前设备是否为移动设备 + * @returns {boolean} 如果是移动设备返回true,否则返回false + */ + mobile() { + // 使用正则表达式匹配userAgent字符串,判断是否为移动设备 + let flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i); + // 如果匹配到且匹配结果数组长度大于0,则返回true,表示是移动设备 + return flag && flag.length > 0; + }, + + /** + * 判断一个值是否为空 + * @param {any} value - 要判断的值 + * @returns {boolean} 如果值为空返回true,否则返回false + */ + isEmpty(value) { + // 判断值是否为undefined、null、空字符串、空数组或空对象 + if (typeof value === "undefined" || value === null || + (typeof value === "string" && value.trim() === "") || + (Array.isArray(value) && value.length === 0) || + (value.constructor === Object && Object.keys(value).length === 0)) { + return true; + } else { + return false; + } + }, + + /** + * 使用AES算法加密明文 + * @param {string} plaintText - 要加密的明文 + * @returns {string} 加密后的密文,经过Base64编码并替换特定字符 + */ + encrypt(plaintText) { + // 设置加密选项,使用ECB模式和Pkcs7填充 + let options = { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }; + // 从常量配置中获取加密密钥,并转换为Utf8编码 + let key = CryptoJS.enc.Utf8.parse(constant.cryptojs_key); + // 使用AES算法加密明文,并转换为字符串,同时替换特定字符以适应某些场景 + let encryptedData = CryptoJS.AES.encrypt(plaintText, key, options); + return encryptedData.toString().replace(/\//g, "_").replace(/\+/g, "-"); + }, + + /** + * 使用AES算法解密密文 + * @param {string} encryptedBase64Str - 要解密的密文,经过Base64编码并可能包含特定替换字符 + * @returns {string} 解密后的明文 + */ + decrypt(encryptedBase64Str) { + // 将密文中的特定替换字符还原为Base64编码的字符 + let val = encryptedBase64Str.replace(/\-/g, '+').replace(/_/g, '/'); + // 设置解密选项,与加密时相同 + let options = { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }; + // 从常量配置中获取加密密钥,并转换为Utf8编码 + let key = CryptoJS.enc.Utf8.parse(constant.cryptojs_key); + // 使用AES算法解密密文,并转换为Utf8编码的字符串 + let decryptedData = CryptoJS.AES.decrypt(val, key, options); + return CryptoJS.enc.Utf8.stringify(decryptedData); + }, + + /** + * 将文本中的表情符号转换为对应的图片标签 + * @param {string} content - 包含表情符号的文本 + * @returns {string} 表情符号被替换为图片标签后的文本 + */ + faceReg(content) { + // 使用正则表达式匹配文本中的表情符号,并替换为对应的图片标签 + content = content.replace(/ +$$ +[^\[^ +$$ +]+\]/g, (word) => { + // 从常量配置的表情符号列表中查找匹配的索引 + let index = constant.emojiList.indexOf(word.replace("[", "").replace("]", "")); + if (index > -1) { + // 根据索引构造图片URL,并返回图片标签 + let url = store.state.sysConfig['webStaticResourcePrefix'] + "emoji/q" + (index + 1) + ".gif"; + return ''; + } else { + // 如果没有找到匹配的表情符号,则原样返回 + return word; + } + }); + return content; + }, + + /** + * 将文本中的图片链接转换为图片标签 + * @param {string} content - 包含图片链接的文本 + * @returns {string} 图片链接被替换为图片标签后的文本 + */ + pictureReg(content) { + // 使用正则表达式匹配文本中的图片链接,并替换为对应的图片标签 + content = content.replace(/ +$$ +[^\[^ +$$ +]+\]/g, (word) => { + // 查找图片链接中的逗号分隔符,以获取图片描述和链接 + let index = word.indexOf(","); + if (index > -1) { + let arr = word.replace("[", "").replace("]", "").split(","); + // 返回图片标签,包含描述作为title属性 + return ''; + } else { + // 如果没有找到逗号分隔符,则原样返回 + return word; + } + }); + return content; + }, + + /** + * 将日期字符串转换为时间戳 + * @param {string} dateStr - 日期字符串,格式为YYYY-MM-DD或YYYY-MM-DD HH:mm:ss + * @returns {number} 转换后的时间戳(毫秒) + */ + getDateTimeStamp(dateStr) { + // 将日期字符串中的短横线替换为斜杠,以适应Date.parse方法的格式要求 + return Date.parse(dateStr.replace(/-/gi, "/")); + }, + + /** + * 计算两个日期之间的时间差,并返回友好的时间差字符串 + * @param {string} dateStr - 要比较的日期字符串,格式为YYYY-MM-DD HH:mm:ss + * @returns {string} 友好的时间差字符串,如“3天前”、“2小时前”等 + */ + getDateDiff(dateStr) { + // 将日期字符串转换为时间戳(秒),并获取当前时间的时间戳(秒) + let publishTime = Date.parse(dateStr.replace(/-/gi, "/")) / 1000, + timeNow = Math.floor(new Date().getTime() / 1000), + d = timeNow - publishTime, // 计算时间差(秒) + // ...(省略了部分代码,包括日期格式化和时间差计算的详细逻辑) + // 根据时间差返回不同的友好时间差字符串 + if (d_days > 0 && d_days < 3) { + return d_days + '天前'; + } else if (d_days <= 0 && d_hours > 0) { + return d_hours + '小时前'; + } else if (d_hours <= 0 && d_minutes > 0) { + return d_minutes + '分钟前'; + } else if (d_seconds < 60) { + if (d_seconds <= 0) { + return '刚刚发表'; + } else { + return d_seconds + '秒前'; + } + } else if (d_days >= 3 && d_days < 30) { + return M + '-' + D + ' ' + H + ':' + m; + } else if (d_days >= 30) { + return Y + '-' + M + '-' + D + ' ' + H + ':' + m; + } + }, + + /** + * 保存资源信息到服务器 + * @param {Vue组件实例} that - 调用此方法的Vue组件实例 + * @param {string} type - 资源类型 + * @param {string} path - 资源路径 + * @param {number} size - 资源大小(字节) + * @param {string} mimeType - 资源MIME类型 + * @param {string} originalName - 资源原始名称 + * @param {string} storeType - 存储类型 + */