Initial commit
This commit is contained in:
71
miniprogram/utils/addressParse.js
Normal file
71
miniprogram/utils/addressParse.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import { areaData } from '../config/index';
|
||||
|
||||
const addressParse = (provinceName, cityName, countryName) => {
|
||||
console.log('[地址解析工具] 开始解析地址');
|
||||
console.log('[地址解析工具] 输入参数:', { provinceName, cityName, countryName });
|
||||
console.log('[地址解析工具] 地区数据总数:', areaData ? areaData.length : 0);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
console.log('[地址解析工具] 开始查找省份:', provinceName);
|
||||
const province = areaData.find((v) => v.label === provinceName);
|
||||
|
||||
if (!province) {
|
||||
console.error('[地址解析工具] 未找到省份:', provinceName);
|
||||
console.log('[地址解析工具] 可用省份列表:', areaData.map(p => p.label));
|
||||
reject('未找到省份: ' + provinceName);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[地址解析工具] 找到省份:', { label: province.label, value: province.value });
|
||||
const { value: provinceCode } = province;
|
||||
|
||||
console.log('[地址解析工具] 开始查找城市:', cityName);
|
||||
console.log('[地址解析工具] 省份下城市数量:', province.children ? province.children.length : 0);
|
||||
|
||||
const city = province.children.find((v) => v.label === cityName);
|
||||
|
||||
if (!city) {
|
||||
console.error('[地址解析工具] 未找到城市:', cityName);
|
||||
console.log('[地址解析工具] 省份下可用城市列表:', province.children.map(c => c.label));
|
||||
reject('未找到城市: ' + cityName);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[地址解析工具] 找到城市:', { label: city.label, value: city.value });
|
||||
const { value: cityCode } = city;
|
||||
|
||||
console.log('[地址解析工具] 开始查找区县:', countryName);
|
||||
console.log('[地址解析工具] 城市下区县数量:', city.children ? city.children.length : 0);
|
||||
|
||||
const country = city.children.find((v) => v.label === countryName);
|
||||
|
||||
if (!country) {
|
||||
console.error('[地址解析工具] 未找到区县:', countryName);
|
||||
console.log('[地址解析工具] 城市下可用区县列表:', city.children.map(d => d.label));
|
||||
reject('未找到区县: ' + countryName);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[地址解析工具] 找到区县:', { label: country.label, value: country.value });
|
||||
const { value: districtCode } = country;
|
||||
|
||||
const result = {
|
||||
provinceCode,
|
||||
cityCode,
|
||||
districtCode,
|
||||
};
|
||||
|
||||
console.log('[地址解析工具] 地址解析成功:', result);
|
||||
resolve(result);
|
||||
} catch (error) {
|
||||
console.error('[地址解析工具] 地址解析异常:', error);
|
||||
console.error('[地址解析工具] 异常堆栈:', error.stack);
|
||||
reject('地址解析失败: ' + (error.message || error));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
addressParse,
|
||||
};
|
||||
110
miniprogram/utils/env-switcher.js
Normal file
110
miniprogram/utils/env-switcher.js
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 环境切换辅助工具
|
||||
* 用于在开发过程中快速切换不同的后端环境
|
||||
*/
|
||||
|
||||
// 环境配置映射
|
||||
const ENV_CONFIG = {
|
||||
development: {
|
||||
name: '开发环境',
|
||||
description: '本地后端服务 (localhost:8080)',
|
||||
apiBase: 'http://localhost:8080/api/v1',
|
||||
useMock: false,
|
||||
color: '#52c41a'
|
||||
},
|
||||
production: {
|
||||
name: '生产环境',
|
||||
description: '线上正式服务器',
|
||||
apiBase: 'https://tral.cc/api/v1',
|
||||
useMock: false,
|
||||
color: '#f5222d'
|
||||
},
|
||||
test: {
|
||||
name: '测试环境',
|
||||
description: '测试服务器',
|
||||
apiBase: 'https://tral.cc/api/v1',
|
||||
useMock: false,
|
||||
color: '#1890ff'
|
||||
},
|
||||
mock: {
|
||||
name: 'Mock模式',
|
||||
description: '使用本地模拟数据',
|
||||
apiBase: 'http://localhost:8080/api/v1',
|
||||
useMock: true,
|
||||
color: '#722ed1'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前环境信息
|
||||
*/
|
||||
export function getCurrentEnv() {
|
||||
const { config } = require('../config/index');
|
||||
return {
|
||||
current: config.environment,
|
||||
config: ENV_CONFIG[config.environment],
|
||||
apiBase: config.apiBase,
|
||||
useMock: config.useMock
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有可用环境
|
||||
*/
|
||||
export function getAllEnvs() {
|
||||
return ENV_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示当前环境信息(已禁用)
|
||||
*/
|
||||
export function showCurrentEnv() {
|
||||
const envInfo = getCurrentEnv();
|
||||
// 环境提示已禁用,仅返回环境信息
|
||||
return envInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 环境启动提示(已禁用)
|
||||
*/
|
||||
export function envStartupTip() {
|
||||
// 环境提示已禁用
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查网络连接
|
||||
*/
|
||||
export function checkNetworkConnection() {
|
||||
const envInfo = getCurrentEnv();
|
||||
|
||||
if (typeof wx !== 'undefined') {
|
||||
wx.request({
|
||||
url: `${envInfo.apiBase}/health`,
|
||||
method: 'GET',
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
console.log('✅ 后端服务连接正常');
|
||||
wx.showToast({
|
||||
title: '服务连接正常',
|
||||
icon: 'success'
|
||||
});
|
||||
} else {
|
||||
console.warn('⚠️ 后端服务响应异常:', res.statusCode);
|
||||
wx.showToast({
|
||||
title: '服务响应异常',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('❌ 后端服务连接失败:', error);
|
||||
wx.showModal({
|
||||
title: '连接失败',
|
||||
content: `无法连接到后端服务\n${envInfo.apiBase}\n\n请检查:\n1. 后端服务是否启动\n2. 网络连接是否正常\n3. 环境配置是否正确`,
|
||||
showCancel: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
45
miniprogram/utils/getPermission.js
Normal file
45
miniprogram/utils/getPermission.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const getPermission = ({ code, name }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.getSetting({
|
||||
success: (res) => {
|
||||
if (res.authSetting[code] === false) {
|
||||
wx.showModal({
|
||||
title: `获取${name}失败`,
|
||||
content: `获取${name}失败,请在【右上角】-小程序【设置】项中,将【${name}】开启。`,
|
||||
confirmText: '去设置',
|
||||
confirmColor: '#FA550F',
|
||||
cancelColor: '取消',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
wx.openSetting({
|
||||
success(settinRes) {
|
||||
if (settinRes.authSetting[code] === true) {
|
||||
resolve();
|
||||
} else {
|
||||
console.warn('用户未打开权限', name, code);
|
||||
reject();
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
},
|
||||
fail() {
|
||||
reject();
|
||||
},
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
fail() {
|
||||
reject();
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getPermission,
|
||||
};
|
||||
51
miniprogram/utils/mock.js
Normal file
51
miniprogram/utils/mock.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 随机打散字符串
|
||||
* @param {number} n 长度
|
||||
* @param {string} str 字符串
|
||||
* @returns
|
||||
*/
|
||||
function generateMixed(n, str) {
|
||||
var res = '';
|
||||
for (var i = 0; i < n; i++) {
|
||||
var id = Math.ceil(Math.random() * 35);
|
||||
res += str[id];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机数
|
||||
* @param {number} min 最小值
|
||||
* @param {number} max 最大值
|
||||
* @returns
|
||||
*/
|
||||
function getRandomNum(min, max) {
|
||||
var range = max - min;
|
||||
var rand = Math.random();
|
||||
return min + Math.round(rand * range);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机IP
|
||||
* @returns
|
||||
*/
|
||||
function mockIp() {
|
||||
return `10.${getRandomNum(1, 254)}.${getRandomNum(1, 254)}.${getRandomNum(
|
||||
1,
|
||||
254,
|
||||
)}`;
|
||||
}
|
||||
|
||||
function mockReqId() {
|
||||
return `${getRandomNum(100000, 999999)}.${new Date().valueOf()}${getRandomNum(
|
||||
1000,
|
||||
9999,
|
||||
)}.${getRandomNum(10000000, 99999999)}`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateMixed,
|
||||
mockIp,
|
||||
mockReqId,
|
||||
getRandomNum,
|
||||
};
|
||||
133
miniprogram/utils/util.js
Normal file
133
miniprogram/utils/util.js
Normal file
@@ -0,0 +1,133 @@
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const formatTime = (date, template) => dayjs(date).format(template);
|
||||
|
||||
/**
|
||||
* 格式化价格数额为字符串
|
||||
* 可对小数部分进行填充,默认不填充
|
||||
* @param price 价格数额,以分为单位!
|
||||
* @param fill 是否填充小数部分 0-不填充 1-填充第一位小数 2-填充两位小数
|
||||
*/
|
||||
function priceFormat(price, fill = 0) {
|
||||
if (isNaN(price) || price === null || price === Infinity) {
|
||||
return price;
|
||||
}
|
||||
|
||||
let priceFormatValue = Math.round(parseFloat(`${price}`) * 10 ** 8) / 10 ** 8; // 恢复精度丢失
|
||||
priceFormatValue = `${Math.ceil(priceFormatValue) / 100}`; // 向上取整,单位转换为元,转换为字符串
|
||||
if (fill > 0) {
|
||||
// 补充小数位数
|
||||
if (priceFormatValue.indexOf('.') === -1) {
|
||||
priceFormatValue = `${priceFormatValue}.`;
|
||||
}
|
||||
const n = fill - priceFormatValue.split('.')[1]?.length;
|
||||
for (let i = 0; i < n; i++) {
|
||||
priceFormatValue = `${priceFormatValue}0`;
|
||||
}
|
||||
}
|
||||
return priceFormatValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取cdn裁剪后链接
|
||||
*
|
||||
* @param {string} url 基础链接
|
||||
* @param {number} width 宽度,单位px
|
||||
* @param {number} [height] 可选,高度,不填时与width同值
|
||||
*/
|
||||
const cosThumb = (url, width, height = width) => {
|
||||
if (url.indexOf('?') > -1) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (url.indexOf('http://') === 0) {
|
||||
url = url.replace('http://', 'https://');
|
||||
}
|
||||
|
||||
return `${url}?imageMogr2/thumbnail/${~~width}x${~~height}`;
|
||||
};
|
||||
|
||||
const get = (source, paths, defaultValue) => {
|
||||
if (typeof paths === 'string') {
|
||||
paths = paths
|
||||
.replace(/\[/g, '.')
|
||||
.replace(/\]/g, '')
|
||||
.split('.')
|
||||
.filter(Boolean);
|
||||
}
|
||||
const { length } = paths;
|
||||
let index = 0;
|
||||
while (source != null && index < length) {
|
||||
source = source[paths[index++]];
|
||||
}
|
||||
return source === undefined || index === 0 ? defaultValue : source;
|
||||
};
|
||||
let systemWidth = 0;
|
||||
/** 获取系统宽度,为了减少启动消耗所以在函数里边做初始化 */
|
||||
export const loadSystemWidth = () => {
|
||||
if (systemWidth) {
|
||||
return systemWidth;
|
||||
}
|
||||
|
||||
try {
|
||||
({ screenWidth: systemWidth, pixelRatio } = wx.getSystemInfoSync());
|
||||
} catch (e) {
|
||||
systemWidth = 0;
|
||||
}
|
||||
return systemWidth;
|
||||
};
|
||||
|
||||
/**
|
||||
* 转换rpx为px
|
||||
*
|
||||
* @description
|
||||
* 什么时候用?
|
||||
* - 布局(width: 172rpx)已经写好, 某些组件只接受px作为style或者prop指定
|
||||
*
|
||||
*/
|
||||
const rpx2px = (rpx, round = false) => {
|
||||
loadSystemWidth();
|
||||
|
||||
// px / systemWidth = rpx / 750
|
||||
const result = (rpx * systemWidth) / 750;
|
||||
|
||||
if (round) {
|
||||
return Math.floor(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 手机号码*加密函数
|
||||
* @param {string} phone 电话号
|
||||
* @returns
|
||||
*/
|
||||
const phoneEncryption = (phone) => {
|
||||
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
|
||||
};
|
||||
|
||||
// 内置手机号正则字符串
|
||||
const innerPhoneReg =
|
||||
'^1(?:3\\d|4[4-9]|5[0-35-9]|6[67]|7[0-8]|8\\d|9\\d)\\d{8}$';
|
||||
|
||||
/**
|
||||
* 手机号正则校验
|
||||
* @param phone 手机号
|
||||
* @param phoneReg 正则字符串
|
||||
* @returns true - 校验通过 false - 校验失败
|
||||
*/
|
||||
const phoneRegCheck = (phone) => {
|
||||
const phoneRegExp = new RegExp(innerPhoneReg);
|
||||
return phoneRegExp.test(phone);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
formatTime,
|
||||
priceFormat,
|
||||
cosThumb,
|
||||
get,
|
||||
rpx2px,
|
||||
phoneEncryption,
|
||||
phoneRegCheck,
|
||||
};
|
||||
Reference in New Issue
Block a user