地址路径修改
This commit is contained in:
326
dist/utils/avatarUtils.js
vendored
Normal file
326
dist/utils/avatarUtils.js
vendored
Normal file
@@ -0,0 +1,326 @@
|
||||
"use strict";
|
||||
// 头像工具类 - 处理头像相关的功能
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AvatarUtils = exports.DefaultAvatars = exports.AvatarQuality = exports.AvatarSizes = void 0;
|
||||
/**
|
||||
* 头像尺寸配置
|
||||
*/
|
||||
exports.AvatarSizes = {
|
||||
// 小尺寸 - 用于列表、地图标记点等
|
||||
SMALL: 40,
|
||||
// 中等尺寸 - 用于用户面板、详情页等
|
||||
MEDIUM: 80,
|
||||
// 大尺寸 - 用于个人资料页等
|
||||
LARGE: 120,
|
||||
// 超大尺寸 - 用于编辑页面等
|
||||
XLARGE: 160
|
||||
};
|
||||
/**
|
||||
* 头像质量配置
|
||||
*/
|
||||
exports.AvatarQuality = {
|
||||
// 缩略图质量
|
||||
THUMBNAIL: 60,
|
||||
// 标准质量
|
||||
STANDARD: 80,
|
||||
// 高质量
|
||||
HIGH: 90
|
||||
};
|
||||
/**
|
||||
* 默认头像配置
|
||||
*/
|
||||
exports.DefaultAvatars = {
|
||||
// 默认用户头像
|
||||
USER: '/images/user-avatar.png',
|
||||
// 管理员头像
|
||||
ADMIN: '/images/admin-avatar.png',
|
||||
// 员工头像
|
||||
EMPLOYEE: '/images/employee-avatar.png',
|
||||
// 货运人员头像
|
||||
DELIVERY_PERSON: '/images/delivery-avatar.png'
|
||||
};
|
||||
/**
|
||||
* 头像工具类
|
||||
*/
|
||||
class AvatarUtils {
|
||||
/**
|
||||
* 获取默认头像URL
|
||||
* @param role 用户角色
|
||||
* @returns 默认头像URL
|
||||
*/
|
||||
static getDefaultAvatar(role) {
|
||||
switch (role) {
|
||||
case 'ADMIN':
|
||||
return exports.DefaultAvatars.ADMIN;
|
||||
case 'DELIVERY_PERSON':
|
||||
return exports.DefaultAvatars.DELIVERY_PERSON;
|
||||
case 'EMPLOYEE':
|
||||
return exports.DefaultAvatars.EMPLOYEE;
|
||||
default:
|
||||
return exports.DefaultAvatars.USER;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 生成头像占位符文本
|
||||
* @param name 用户名
|
||||
* @returns 占位符文本
|
||||
*/
|
||||
static generatePlaceholderText(name) {
|
||||
if (!name)
|
||||
return '👤';
|
||||
// 如果是中文名字,取最后一个字符
|
||||
if (/[\u4e00-\u9fa5]/.test(name)) {
|
||||
return name.charAt(name.length - 1);
|
||||
}
|
||||
// 如果是英文名字,取首字母
|
||||
return name.charAt(0).toUpperCase();
|
||||
}
|
||||
/**
|
||||
* 获取头像显示URL
|
||||
* @param avatarUrl 原始头像URL
|
||||
* @param size 目标尺寸
|
||||
* @param quality 图片质量
|
||||
* @returns 处理后的头像URL
|
||||
*/
|
||||
static getAvatarUrl(avatarUrl, _size = exports.AvatarSizes.MEDIUM, _quality = exports.AvatarQuality.STANDARD) {
|
||||
if (!avatarUrl) {
|
||||
return '';
|
||||
}
|
||||
// 如果是本地临时文件,直接返回
|
||||
if (avatarUrl.startsWith('http://tmp/') || avatarUrl.startsWith('wxfile://')) {
|
||||
return avatarUrl;
|
||||
}
|
||||
// 如果是网络图片,可以添加尺寸参数(如果后端支持)
|
||||
if (avatarUrl.startsWith('http')) {
|
||||
// 这里可以根据后端API添加尺寸参数
|
||||
// 例如:return `${avatarUrl}?width=${size}&quality=${quality}`;
|
||||
return avatarUrl;
|
||||
}
|
||||
return avatarUrl;
|
||||
}
|
||||
/**
|
||||
* 缩放头像图片
|
||||
* @param src 原始图片路径
|
||||
* @param width 目标宽度
|
||||
* @param height 目标高度
|
||||
* @returns Promise<string> 缩放后的图片路径
|
||||
*/
|
||||
static async resizeAvatar(src, width, height) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!src) {
|
||||
reject(new Error('图片路径不能为空'));
|
||||
return;
|
||||
}
|
||||
wx.getImageInfo({
|
||||
src,
|
||||
success: (_infoRes) => {
|
||||
const canvasId = `resize-canvas-${Date.now()}`;
|
||||
const ctx = wx.createCanvasContext(canvasId);
|
||||
// 绘制缩放后的图片
|
||||
ctx.drawImage(src, 0, 0, width, height);
|
||||
ctx.draw(false, () => {
|
||||
wx.canvasToTempFilePath({
|
||||
canvasId,
|
||||
destWidth: width,
|
||||
destHeight: height,
|
||||
success: (res) => {
|
||||
resolve(res.tempFilePath);
|
||||
},
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
},
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 裁剪头像为圆形
|
||||
* @param src 原始图片路径
|
||||
* @param size 裁剪尺寸
|
||||
* @returns Promise<string> 裁剪后的圆形头像路径
|
||||
*/
|
||||
static async cropAvatarToCircle(src, size = exports.AvatarSizes.MEDIUM) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!src) {
|
||||
reject(new Error('图片路径不能为空'));
|
||||
return;
|
||||
}
|
||||
wx.getImageInfo({
|
||||
src,
|
||||
success: (_infoRes) => {
|
||||
const canvasId = `circle-canvas-${Date.now()}`;
|
||||
const ctx = wx.createCanvasContext(canvasId);
|
||||
// 绘制圆形裁剪区域
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI);
|
||||
ctx.clip();
|
||||
// 绘制图片
|
||||
ctx.drawImage(src, 0, 0, size, size);
|
||||
ctx.restore();
|
||||
ctx.draw(false, () => {
|
||||
wx.canvasToTempFilePath({
|
||||
canvasId,
|
||||
destWidth: size,
|
||||
destHeight: size,
|
||||
success: (res) => {
|
||||
resolve(res.tempFilePath);
|
||||
},
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
},
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 压缩头像图片
|
||||
* @param src 原始图片路径
|
||||
* @param quality 压缩质量 (0-100)
|
||||
* @returns Promise<string> 压缩后的图片路径
|
||||
*/
|
||||
static async compressAvatar(src, quality = exports.AvatarQuality.STANDARD) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.compressImage({
|
||||
src,
|
||||
quality,
|
||||
success: (res) => {
|
||||
resolve(res.tempFilePath);
|
||||
},
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 缓存头像图片
|
||||
* @param avatarUrl 头像URL
|
||||
* @param cacheKey 缓存键
|
||||
* @returns Promise<string> 缓存后的图片路径
|
||||
*/
|
||||
static async cacheAvatar(avatarUrl, cacheKey) {
|
||||
if (!avatarUrl) {
|
||||
return '';
|
||||
}
|
||||
// 如果是本地文件,直接返回
|
||||
if (avatarUrl.startsWith('http://tmp/') || avatarUrl.startsWith('wxfile://')) {
|
||||
return avatarUrl;
|
||||
}
|
||||
const key = cacheKey || `avatar_${avatarUrl.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
||||
try {
|
||||
// 检查缓存
|
||||
const cachedPath = wx.getStorageSync(key);
|
||||
if (cachedPath) {
|
||||
// 验证缓存文件是否存在
|
||||
try {
|
||||
await this.checkFileExists(cachedPath);
|
||||
return cachedPath;
|
||||
}
|
||||
catch (error) {
|
||||
// 缓存文件不存在,重新下载
|
||||
console.log('缓存文件不存在,重新下载:', avatarUrl);
|
||||
}
|
||||
}
|
||||
// 下载头像
|
||||
const downloadRes = await this.downloadAvatar(avatarUrl);
|
||||
// 缓存头像路径
|
||||
wx.setStorageSync(key, downloadRes);
|
||||
return downloadRes;
|
||||
}
|
||||
catch (error) {
|
||||
console.error('缓存头像失败:', error);
|
||||
return avatarUrl;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 下载头像图片
|
||||
* @param url 头像URL
|
||||
* @returns Promise<string> 下载后的临时文件路径
|
||||
*/
|
||||
static downloadAvatar(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.downloadFile({
|
||||
url,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
resolve(res.tempFilePath);
|
||||
}
|
||||
else {
|
||||
reject(new Error(`下载失败,状态码: ${res.statusCode}`));
|
||||
}
|
||||
},
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 检查文件是否存在
|
||||
* @param filePath 文件路径
|
||||
* @returns Promise<boolean>
|
||||
*/
|
||||
static checkFileExists(filePath) {
|
||||
return new Promise((resolve) => {
|
||||
wx.getFileInfo({
|
||||
filePath,
|
||||
success: () => resolve(true),
|
||||
fail: () => resolve(false)
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 生成头像样式类名
|
||||
* @param size 尺寸
|
||||
* @param shape 形状
|
||||
* @param bordered 是否有边框
|
||||
* @param shadow 是否有阴影
|
||||
* @returns 样式类名字符串
|
||||
*/
|
||||
static generateAvatarClass(size, shape = 'circle', bordered = false, shadow = false) {
|
||||
const classes = [];
|
||||
// 尺寸类
|
||||
if (size <= exports.AvatarSizes.SMALL) {
|
||||
classes.push('avatar-small');
|
||||
}
|
||||
else if (size <= exports.AvatarSizes.MEDIUM) {
|
||||
classes.push('avatar-medium');
|
||||
}
|
||||
else if (size <= exports.AvatarSizes.LARGE) {
|
||||
classes.push('avatar-large');
|
||||
}
|
||||
else {
|
||||
classes.push('avatar-xlarge');
|
||||
}
|
||||
// 形状类
|
||||
classes.push(shape === 'circle' ? 'avatar-circle' : 'avatar-square');
|
||||
// 边框类
|
||||
if (bordered) {
|
||||
classes.push('avatar-bordered');
|
||||
}
|
||||
// 阴影类
|
||||
if (shadow) {
|
||||
classes.push('avatar-shadow');
|
||||
}
|
||||
return classes.join(' ');
|
||||
}
|
||||
/**
|
||||
* 清理头像缓存
|
||||
* @param cacheKey 缓存键(可选,不传则清理所有头像缓存)
|
||||
*/
|
||||
static clearAvatarCache(cacheKey) {
|
||||
if (cacheKey) {
|
||||
wx.removeStorageSync(cacheKey);
|
||||
}
|
||||
else {
|
||||
// 清理所有以 avatar_ 开头的缓存
|
||||
const storageInfo = wx.getStorageInfoSync();
|
||||
storageInfo.keys.forEach(key => {
|
||||
if (key.startsWith('avatar_')) {
|
||||
wx.removeStorageSync(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.AvatarUtils = AvatarUtils;
|
||||
exports.default = AvatarUtils;
|
||||
164
dist/utils/helpers.js
vendored
Normal file
164
dist/utils/helpers.js
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
"use strict";
|
||||
// 工具函数文件
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.formatCoordinate = formatCoordinate;
|
||||
exports.formatSingleCoordinate = formatSingleCoordinate;
|
||||
exports.calculateDistance = calculateDistance;
|
||||
exports.formatDistance = formatDistance;
|
||||
exports.showToast = showToast;
|
||||
exports.showLoading = showLoading;
|
||||
exports.hideLoading = hideLoading;
|
||||
exports.cacheUserAvatar = cacheUserAvatar;
|
||||
exports.showConfirmDialog = showConfirmDialog;
|
||||
/**
|
||||
* 格式化坐标信息
|
||||
* @param longitude 经度
|
||||
* @param latitude 纬度
|
||||
* @param decimalPlaces 保留小数位数,默认6位
|
||||
* @returns 格式化后的坐标字符串
|
||||
*/
|
||||
function formatCoordinate(longitude, latitude, decimalPlaces = 6) {
|
||||
const formattedLongitude = longitude.toFixed(decimalPlaces);
|
||||
const formattedLatitude = latitude.toFixed(decimalPlaces);
|
||||
return `经度 ${formattedLongitude}, 纬度 ${formattedLatitude}`;
|
||||
}
|
||||
/**
|
||||
* 格式化单个坐标值
|
||||
* @param coordinate 坐标值
|
||||
* @param decimalPlaces 保留小数位数,默认6位
|
||||
* @returns 格式化后的坐标字符串
|
||||
*/
|
||||
function formatSingleCoordinate(coordinate, decimalPlaces = 6) {
|
||||
return coordinate.toFixed(decimalPlaces);
|
||||
}
|
||||
/**
|
||||
* 计算两点之间的距离(简单的平面距离,非球面距离)
|
||||
* @param lng1 第一个点的经度
|
||||
* @param lat1 第一个点的纬度
|
||||
* @param lng2 第二个点的经度
|
||||
* @param lat2 第二个点的纬度
|
||||
* @returns 两点之间的距离(单位:米)
|
||||
*/
|
||||
function calculateDistance(lng1, lat1, lng2, lat2) {
|
||||
// 地球半径(单位:米)
|
||||
const EARTH_RADIUS = 6378137;
|
||||
// 将角度转换为弧度
|
||||
const radLat1 = (lat1 * Math.PI) / 180.0;
|
||||
const radLat2 = (lat2 * Math.PI) / 180.0;
|
||||
const a = radLat1 - radLat2;
|
||||
const b = (lng1 * Math.PI) / 180.0 - (lng2 * Math.PI) / 180.0;
|
||||
// 应用haversine公式计算球面距离
|
||||
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
|
||||
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
|
||||
s = s * EARTH_RADIUS;
|
||||
s = Math.round(s * 10000) / 10000; // 保留4位小数
|
||||
return s;
|
||||
}
|
||||
/**
|
||||
* 格式化距离(米转换为千米)
|
||||
* @param distance 距离(单位:米)
|
||||
* @returns 格式化后的距离字符串
|
||||
*/
|
||||
function formatDistance(distance) {
|
||||
if (distance < 1000) {
|
||||
return `${Math.round(distance)} 米`;
|
||||
}
|
||||
else {
|
||||
return `${(distance / 1000).toFixed(1)} 千米`;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 显示消息提示
|
||||
* @param title 提示信息
|
||||
* @param icon 图标类型,默认'none'
|
||||
* @param duration 显示时长,默认2000毫秒
|
||||
*/
|
||||
function showToast(title, icon = 'none', duration = 2000) {
|
||||
wx.showToast({
|
||||
title,
|
||||
icon,
|
||||
duration
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 显示加载提示
|
||||
* @param title 提示信息,默认'加载中...'
|
||||
*/
|
||||
function showLoading(title = '加载中...') {
|
||||
wx.showLoading({
|
||||
title
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 隐藏加载提示
|
||||
*/
|
||||
function hideLoading() {
|
||||
wx.hideLoading();
|
||||
}
|
||||
/**
|
||||
* 缓存用户头像图片
|
||||
* @param avatarUrl 头像URL地址
|
||||
* @returns Promise<string> 返回缓存后的头像路径或原始URL
|
||||
*/
|
||||
async function cacheUserAvatar(avatarUrl) {
|
||||
if (!avatarUrl)
|
||||
return '';
|
||||
try {
|
||||
// 检查是否已缓存
|
||||
const cachedPath = wx.getStorageSync(`avatar_${avatarUrl}`);
|
||||
if (cachedPath) {
|
||||
console.log('使用缓存的头像:', cachedPath);
|
||||
return cachedPath;
|
||||
}
|
||||
// 下载头像
|
||||
const downloadRes = await new Promise((resolve) => {
|
||||
wx.downloadFile({
|
||||
url: avatarUrl,
|
||||
success: (res) => resolve(res),
|
||||
fail: (err) => {
|
||||
console.error('下载头像失败:', err);
|
||||
resolve({ statusCode: 0 }); // 返回失败状态
|
||||
}
|
||||
});
|
||||
});
|
||||
if (downloadRes.statusCode === 200 && downloadRes.tempFilePath) {
|
||||
// 缓存头像路径
|
||||
wx.setStorageSync(`avatar_${avatarUrl}`, downloadRes.tempFilePath);
|
||||
console.log('头像下载并缓存成功:', downloadRes.tempFilePath);
|
||||
return downloadRes.tempFilePath;
|
||||
}
|
||||
else {
|
||||
console.warn('头像下载失败,使用原始URL:', avatarUrl);
|
||||
return avatarUrl;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('缓存头像过程中发生错误:', error);
|
||||
return avatarUrl;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 显示确认对话框
|
||||
* @param title 标题
|
||||
* @param content 内容
|
||||
* @returns Promise<boolean> 用户点击确定返回true,点击取消返回false
|
||||
*/
|
||||
function showConfirmDialog(title, content) {
|
||||
return new Promise((resolve) => {
|
||||
wx.showModal({
|
||||
title,
|
||||
content,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
resolve(true);
|
||||
}
|
||||
else if (res.cancel) {
|
||||
resolve(false);
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
85
dist/utils/roleUtils.js
vendored
Normal file
85
dist/utils/roleUtils.js
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
"use strict";
|
||||
/**
|
||||
* 角色工具类 - 处理角色枚举的转换和验证
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RoleMapping = exports.Role = void 0;
|
||||
exports.normalizeRole = normalizeRole;
|
||||
exports.getRoleText = getRoleText;
|
||||
exports.isValidRole = isValidRole;
|
||||
exports.getRoleOptions = getRoleOptions;
|
||||
/**
|
||||
* 角色枚举定义
|
||||
* 服务器可能返回数字角色值,前端使用字符串枚举
|
||||
*/
|
||||
var Role;
|
||||
(function (Role) {
|
||||
Role["DELIVERY_PERSON"] = "DELIVERY_PERSON";
|
||||
Role["ADMIN"] = "ADMIN"; // 管理员
|
||||
})(Role || (exports.Role = Role = {}));
|
||||
/**
|
||||
* 角色值映射
|
||||
* 服务器返回的数字角色值到前端字符串枚举的映射
|
||||
*/
|
||||
exports.RoleMapping = {
|
||||
0: Role.DELIVERY_PERSON, // 0对应配送员
|
||||
1: Role.ADMIN // 1对应管理员
|
||||
};
|
||||
/**
|
||||
* 将服务器返回的角色值转换为前端枚举
|
||||
* @param roleValue 服务器返回的角色值(可能是数字或字符串)
|
||||
* @returns 标准化的角色枚举值
|
||||
*/
|
||||
function normalizeRole(roleValue) {
|
||||
if (typeof roleValue === 'number') {
|
||||
// 如果是数字,使用映射表转换
|
||||
return exports.RoleMapping[roleValue] || Role.DELIVERY_PERSON;
|
||||
}
|
||||
// 如果是字符串,直接转换为大写进行比较
|
||||
const normalizedRole = roleValue.toUpperCase();
|
||||
// 检查是否是有效的角色值
|
||||
if (normalizedRole === Role.ADMIN) {
|
||||
return Role.ADMIN;
|
||||
}
|
||||
// 默认返回配送员
|
||||
return Role.DELIVERY_PERSON;
|
||||
}
|
||||
/**
|
||||
* 获取角色显示文本
|
||||
* @param role 角色枚举值
|
||||
* @returns 对应的中文显示文本
|
||||
*/
|
||||
function getRoleText(role) {
|
||||
switch (role) {
|
||||
case Role.ADMIN:
|
||||
return '管理员';
|
||||
case Role.DELIVERY_PERSON:
|
||||
return '配送员';
|
||||
default:
|
||||
return '未知角色';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 验证角色值是否有效
|
||||
* @param roleValue 角色值
|
||||
* @returns 是否有效
|
||||
*/
|
||||
function isValidRole(roleValue) {
|
||||
try {
|
||||
const normalized = normalizeRole(roleValue);
|
||||
return normalized === Role.ADMIN || normalized === Role.DELIVERY_PERSON;
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取角色选项列表(用于下拉选择器)
|
||||
* @returns 角色选项数组
|
||||
*/
|
||||
function getRoleOptions() {
|
||||
return [
|
||||
{ value: Role.DELIVERY_PERSON, label: '配送员' },
|
||||
{ value: Role.ADMIN, label: '管理员' }
|
||||
];
|
||||
}
|
||||
19
dist/utils/util.js
vendored
Normal file
19
dist/utils/util.js
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.formatTime = void 0;
|
||||
const formatTime = (date) => {
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
const hour = date.getHours();
|
||||
const minute = date.getMinutes();
|
||||
const second = date.getSeconds();
|
||||
return ([year, month, day].map(formatNumber).join('/') +
|
||||
' ' +
|
||||
[hour, minute, second].map(formatNumber).join(':'));
|
||||
};
|
||||
exports.formatTime = formatTime;
|
||||
const formatNumber = (n) => {
|
||||
const s = n.toString();
|
||||
return s[1] ? s : '0' + s;
|
||||
};
|
||||
Reference in New Issue
Block a user