124 lines
2.9 KiB
JavaScript
124 lines
2.9 KiB
JavaScript
const { v4: uuidv4 } = require('uuid');
|
||
const crypto = require('crypto');
|
||
|
||
/**
|
||
* 生成唯一会员码
|
||
*/
|
||
function generateMemberCode() {
|
||
const timestamp = Date.now().toString(36);
|
||
const random = Math.random().toString(36).substring(2, 8);
|
||
return `M${timestamp}${random}`.toUpperCase();
|
||
}
|
||
|
||
/**
|
||
* 生成比赛码
|
||
*/
|
||
function generateMatchCode() {
|
||
const timestamp = Date.now().toString(36);
|
||
const random = Math.random().toString(36).substring(2, 6);
|
||
return `G${timestamp}${random}`.toUpperCase();
|
||
}
|
||
|
||
/**
|
||
* 生成订单号
|
||
*/
|
||
function generateOrderNo() {
|
||
const date = new Date();
|
||
const dateStr = date.getFullYear().toString() +
|
||
(date.getMonth() + 1).toString().padStart(2, '0') +
|
||
date.getDate().toString().padStart(2, '0');
|
||
const random = Math.random().toString().substring(2, 10);
|
||
return `PO${dateStr}${random}`;
|
||
}
|
||
|
||
/**
|
||
* 生成兑换码
|
||
*/
|
||
function generateExchangeCode() {
|
||
return uuidv4().replace(/-/g, '').toUpperCase().substring(0, 16);
|
||
}
|
||
|
||
/**
|
||
* 计算两点之间的距离(米)
|
||
*/
|
||
function calculateDistance(lat1, lon1, lat2, lon2) {
|
||
const R = 6371000; // 地球半径(米)
|
||
const dLat = toRad(lat2 - lat1);
|
||
const dLon = toRad(lon2 - lon1);
|
||
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
|
||
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||
return R * c;
|
||
}
|
||
|
||
function toRad(value) {
|
||
return value * Math.PI / 180;
|
||
}
|
||
|
||
/**
|
||
* 分页参数处理
|
||
*/
|
||
function getPagination(page = 1, pageSize = 10) {
|
||
const limit = Math.min(parseInt(pageSize) || 10, 100);
|
||
const offset = (Math.max(parseInt(page) || 1, 1) - 1) * limit;
|
||
return { limit, offset };
|
||
}
|
||
|
||
/**
|
||
* 统一响应格式
|
||
*/
|
||
function success(data = null, message = '操作成功') {
|
||
return { code: 0, message, data };
|
||
}
|
||
|
||
function error(message = '操作失败', code = 500) {
|
||
return { code, message };
|
||
}
|
||
|
||
function pageResult(list, total, page, pageSize) {
|
||
return {
|
||
code: 0,
|
||
data: {
|
||
list,
|
||
pagination: {
|
||
total,
|
||
page: parseInt(page),
|
||
pageSize: parseInt(pageSize),
|
||
totalPages: Math.ceil(total / pageSize)
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 获取完整URL(处理头像等资源路径)
|
||
* @param {string} path - 相对路径或完整URL
|
||
* @param {object} req - Express request对象(用于获取host)
|
||
* @returns {string} 完整URL
|
||
*/
|
||
function getFullUrl(path, req) {
|
||
if (!path) return '';
|
||
// 已经是完整URL,直接返回
|
||
if (path.startsWith('http://') || path.startsWith('https://')) {
|
||
return path;
|
||
}
|
||
// 相对路径,拼接服务器地址
|
||
const protocol = req?.protocol || 'http';
|
||
const host = req?.get('host') || `localhost:${process.env.PORT || 3000}`;
|
||
return `${protocol}://${host}${path}`;
|
||
}
|
||
|
||
module.exports = {
|
||
generateMemberCode,
|
||
generateMatchCode,
|
||
generateOrderNo,
|
||
generateExchangeCode,
|
||
calculateDistance,
|
||
getPagination,
|
||
success,
|
||
error,
|
||
pageResult,
|
||
getFullUrl
|
||
};
|