const jwt = require('jsonwebtoken'); const sdk = require('@baiducloud/sdk'); const config = require('../config'); const { Keyv } = require('keyv'); const keyv = new Keyv(); const request = require('./request'); /** * 工具函数 */ module.exports = { /** * 接口成功输出 * @param {*} ctx 上下文对象 * @param {*} data 返回结果 * @param {*} code 返回状态码 */ success(ctx, data = '', code = 0) { ctx.body = { code, data, message: '操作成功', }; }, /** * 接口失败输出 * @param {*} ctx 上下文对象 * @param {*} message 返回信息 * @param {*} code 返回状态码 */ fail(ctx, message = '', code = -1, data = '') { ctx.body = { code, data, message, }; }, /** * 判断是否为空 * @param {*} val 判断值 * @returns */ isNotEmpty(val) { if (val === undefined || val == null || val === '') { return false; } else if (typeof val === 'string') { if (val.trim() === '') { return false; } else { return true; } } else { return true; } }, /** * 判断是否为数字 * @param {*} val 判断值 * @returns */ isNumber(val) { const isTrue = this.isNotEmpty(val); return isTrue && (typeof val === 'number' || isNaN(val) === false); }, /** * 验证环境是否合法 * @param {*} env 环境名称 * @returns */ checkEnv(env) { if (['stg', 'pre', 'prd'].includes(env)) { return true; } return false; }, /** * 获取cookie * @param {*} ctx 上下文对象 * @param {*} name cookie名称 * @returns */ getCookie(ctx, name) { return ctx.cookies.get(name); }, /** * 生成jwt-token * @param {*} payload 参数对象 * @returns jwt-token */ createToken(payload) { return jwt.sign(payload, config.JWT_SECRET, { expiresIn: config.JWT_EXPIRES_IN, }); }, /** * 解密jwt-token * @param {*} ctx 上下文对象 * @returns 解密后对象 */ decodeToken(ctx) { try { let [, authorization] = (ctx.request.headers?.authorization || '').split(' '); if (!authorization) { return ctx.throw(400, '账号信息异常,请重新登录'); } return jwt.verify(authorization, config.JWT_SECRET); } catch (error) { return ctx.throw(401, '账号信息异常,请重新登录'); } }, // 解密重置密码对应的token decodeResetToken(token) { return jwt.verify(token, config.JWT_SECRET); }, /** * 上传文件,用于自定义组件内容上传到bos * @param {*} fileName 文件名称 * @param {*} content 文件内容 * @returns 上传后云地址 */ async uploadString(userId, fileName, content) { let client = null; if (config.OSS_TYPE === 'minio') { // 创建 MinIO 客户端 client = new Minio.Client({ endPoint: config.OSS_ENDPOINT, port: config.OSS_PORT, // MinIO 默认端口 useSSL: config.OSS_USESSL, // 如果使用 HTTPS,请设置为 true accessKey: config.OSS_ACCESSKEY, secretKey: config.OSS_ACCESSKEYSECRET, }); } else if (config.OSS_TYPE === 'baidu') { const ossConfig = { endpoint: config.OSS_ENDPOINT, //传入Bucket所在区域域名 credentials: { ak: config.OSS_ACCESSKEY, //您的AccessKey sk: config.OSS_ACCESSKEYSECRET, //您的SecretAccessKey }, }; client = new sdk.BosClient(ossConfig); } else { client = new OSS({ // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。 region: config.OSS_REGION, // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 accessKeyId: config.OSS_ACCESSKEY, accessKeySecret: config.OSS_ACCESSKEYSECRET, authorizationV4: true, // 填写Bucket名称。 bucket: config.OSS_BUCKET, }); } let key = `libs/${userId}/${fileName}`; let ContentType = ''; if (fileName.endsWith('.js')) { ContentType = 'application/javascript; charset=utf-8'; } else if (fileName.endsWith('.html')) { ContentType = 'text/html; charset=utf-8'; } else if (fileName.endsWith('.json')) { ContentType = 'application/json; charset=utf-8'; } else if (fileName.endsWith('.css')) { ContentType = 'text/css; charset=utf-8'; } // 以字符串形式上传 if (config.OSS_TYPE === 'aliyun') { await client.put(key, Buffer.from(content, 'utf8')); } else { await client.putObject(config.OSS_BUCKET, key, Buffer.from(content, 'utf8'), { 'Content-Type': ContentType, // 添加http header 'Cache-Control': 'public, max-age=31536000', // 指定缓存指令 'x-bce-acl': 'public-read', }); } }, // 获取用户IP getClientIp(ctx) { let ip = ctx.request.headers['x-forwarded-for'] || ctx.request.headers['x-real-ip'] || ctx.request.headers['x-cluster-client-ip']; // 如果没有上述头,则使用ctx.request.ip(可能是本地IP或代理服务器的IP) if (!ip) { ip = ctx.request.ip; } // 由于X-Forwarded-For可能包含多个IP(逗号分隔),我们取第一个 if (ip && ip.includes(',')) { ip = ip.split(',')[0]; } return ip; }, };