first commit

This commit is contained in:
Mauve
2026-09-08 17:20:27 +08:00
commit a7f2e0ca01
752 changed files with 111259 additions and 0 deletions
+187
View File
@@ -0,0 +1,187 @@
/**
* 与后端 EncryptUtil.aesEncryptToBase64(AES-GCM,12 字节 IV,16 字节 tag)一致。
* App 端 WebView 往往无 crypto.subtle,需用纯 JS 解密。
*/
import { gcm } from '@noble/ciphers/aes.js';
import { sha256 } from '@noble/hashes/sha2.js';
// Polyfill for TextEncoder/TextDecoder in Weex environment
class TextEncoderPolyfill {
encode(text) {
const arr = new Uint8Array(text.length);
for (let i = 0; i < text.length; i++) {
arr[i] = text.charCodeAt(i) & 0xff;
}
return arr;
}
}
class TextDecoderPolyfill {
decode(uint8Array) {
let str = '';
let i = 0;
while (i < uint8Array.length) {
const byte1 = uint8Array[i];
if (byte1 < 0x80) {
// 单字节 ASCII
str += String.fromCharCode(byte1);
i++;
} else if ((byte1 & 0xe0) === 0xc0) {
// 双字节 UTF-8
const byte2 = uint8Array[i + 1];
const code = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f);
str += String.fromCharCode(code);
i += 2;
} else if ((byte1 & 0xf0) === 0xe0) {
// 三字节 UTF-8
const byte2 = uint8Array[i + 1];
const byte3 = uint8Array[i + 2];
const code = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f);
str += String.fromCharCode(code);
i += 3;
} else if ((byte1 & 0xf8) === 0xf0) {
// 四字节 UTF-8(需要代理对)
const byte2 = uint8Array[i + 1];
const byte3 = uint8Array[i + 2];
const byte4 = uint8Array[i + 3];
let code = ((byte1 & 0x07) << 18) | ((byte2 & 0x3f) << 12) | ((byte3 & 0x3f) << 6) | (byte4 & 0x3f);
// 转换为 UTF-16 代理对
code -= 0x10000;
const high = 0xd800 + (code >> 10);
const low = 0xdc00 + (code & 0x3ff);
str += String.fromCharCode(high, low);
i += 4;
} else {
// 非法字节,跳过
str += String.fromCharCode(byte1);
i++;
}
}
return str;
}
}
const TextEncoder = typeof globalThis !== 'undefined' && globalThis.TextEncoder ? globalThis.TextEncoder : TextEncoderPolyfill;
const TextDecoder = typeof globalThis !== 'undefined' && globalThis.TextDecoder ? globalThis.TextDecoder : TextDecoderPolyfill;
/** 与后端 EncryptUtil 一致:去掉 BOM/空白,避免与 SHA-256(UTF-8) 密钥不一致 */
function normalizeSecret(secret) {
if (secret == null || typeof secret !== 'string') {
return secret;
}
let s = secret.trim();
if (s.length > 0 && s.charCodeAt(0) === 0xfeff) {
s = s.slice(1);
}
return s;
}
/**
* x-www-form-urlencoded /部分网关会把 Base64 里的 "+" 变成空格;JSON 一般不受影响。
*/
function normalizeBase64Segment(seg) {
if (seg == null || seg === '') {
return seg;
}
let s = String(seg).trim().replace(/\s/g, '+');
s = s.replace(/-/g, '+').replace(/_/g, '/');
const pad = s.length % 4;
if (pad !== 0) {
s += '='.repeat(4 - pad);
}
return s;
}
function base64ToUint8Array(b64) {
const normalized = normalizeBase64Segment(b64);
if (typeof atob === 'function') {
const bin = atob(normalized);
const out = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; i++) {
out[i] = bin.charCodeAt(i) & 0xff;
}
return out;
}
if (typeof uni !== 'undefined' && uni.base64ToArrayBuffer) {
return new Uint8Array(uni.base64ToArrayBuffer(normalized));
}
throw new Error('cfgSettingCrypto: no base64 decoder');
}
function splitIvAndCipher(encryptedText) {
const idx = encryptedText.indexOf(':');
if (idx <= 0 || idx === encryptedText.length - 1) {
return null;
}
return {
ivB64: encryptedText.slice(0, idx),
cipherB64: encryptedText.slice(idx + 1),
};
}
async function decryptWithSubtle(encryptedText, secret) {
const parts = splitIvAndCipher(encryptedText);
if (!parts) {
throw new Error('cfgSettingCrypto: invalid iv:cipher format');
}
const ivBytes = base64ToUint8Array(parts.ivB64);
const cipherBytes = base64ToUint8Array(parts.cipherB64);
const keyRaw = new TextEncoder().encode(normalizeSecret(secret));
const keyHash = await globalThis.crypto.subtle.digest('SHA-256', keyRaw);
const aesKey = await globalThis.crypto.subtle.importKey(
'raw',
keyHash,
{ name: 'AES-GCM' },
false,
['decrypt']
);
const decrypted = await globalThis.crypto.subtle.decrypt(
{ name: 'AES-GCM', iv: ivBytes, tagLength: 128 },
aesKey,
cipherBytes
);
return new TextDecoder().decode(decrypted);
}
function decryptWithNoble(encryptedText, secret) {
const parts = splitIvAndCipher(encryptedText);
if (!parts) {
throw new Error('cfgSettingCrypto: invalid iv:cipher format');
}
const ivBytes = base64ToUint8Array(parts.ivB64);
const cipherBytes = base64ToUint8Array(parts.cipherB64);
const keyBytes = sha256(new TextEncoder().encode(normalizeSecret(secret)));
const decipher = gcm(keyBytes, ivBytes);
const plainBytes = decipher.decrypt(cipherBytes);
return new TextDecoder().decode(plainBytes);
}
/**
* @param {string} encryptedText 格式 base64(iv):base64(ciphertext||tag)
* @param {string} secret 与后端 allow_key 一致
* @returns {Promise<string>}
*/
export async function decryptCfgSettingValue(encryptedText, secret) {
if (!encryptedText || !secret || encryptedText.indexOf(':') === -1) {
return encryptedText;
}
if (!splitIvAndCipher(encryptedText)) {
return encryptedText;
}
try {
if (globalThis.crypto && globalThis.crypto.subtle) {
const plain = await decryptWithSubtle(encryptedText, secret);
if (plain) {
return plain;
}
}
} catch (e) {
console.warn('[cfgSettingCrypto] WebCrypto 解密失败,改用 @noble/ciphers', e);
}
try {
return decryptWithNoble(encryptedText, secret);
} catch (e) {
console.error('[cfgSettingCrypto]解密失败', e);
return encryptedText;
}
}
+39
View File
@@ -0,0 +1,39 @@
class config {
constructor() {
//local
this.internalUrl = 'https://localhost:9086';
// mgm web DEV
// this.internalUrl = 'https://localhost';
// willtech DEV
// this.internalUrl = 'https://47.238.46.81';
// MGM APP DEV
// this.internalUrl = 'https://dlahcadev.mcmsapoc.com';
//this.version = "beta 2.0";
//ali ECS
// this.internalUrl = 'https://mcrm.willtechmacau.com:9086';
this.externalUrl = 'https://mp.mixixili.cn';
this.debugMode = true;
this.apiPath = '/api';
this.internalSSOUrl = 'https://adserver.willtechmacau.com';
this.externalSSOUrl = 'https://adserver.willtechmacau.com';
this.internalTag = true;
this.originUrl = "MGM_CRM_APP";
this.appId='MGM_CRM_APP';
this.allowKey='U2FsdGVkX19JXgsp9IZ+cr6P67KVShdWWRX5niRURIk=';
//dev
// this.internalUrl = 'https://hca.mcmsapoc.com';
// this.internalUrl = 'https://localhost';
this.version = "Dev 1.64";
//prod
//this.internalUrl = 'https://hostcrmapp.mgm.mo';
//this.version = "v2.0";
this.resourceCallBackUrl = "hostcrmapp_dev";
this.emailExt = "";// 如果是dev的時候設置成空字符串,讓他們自己輸入
}
}
export default config
+324
View File
@@ -0,0 +1,324 @@
/**
* 坐标转换问题分析和解决方案 - 精确修正
* lc 2025-07-15
*/
class FixedCoordinateConverter {
constructor() {
this.a = 6378245.0;
this.ee = 0.00669342162296594323;
this.PI = Math.PI;
// 精确偏移校正参数(基于实际测试数据)
this.OFFSET_CORRECTIONS = {
// 经度偏移校正
lngCorrection: -0.00003,
// 纬度偏移校正
latCorrection: 0.0003
};
}
/**
* 标准算法实现
*/
wgs84ToGcj02Standard(wgsLat, wgsLng) {
if (!this.isInChina(wgsLat, wgsLng)) {
return { lat: wgsLat, lng: wgsLng };
}
let dLat = this.transformLat(wgsLng - 105.0, wgsLat - 35.0);
let dLng = this.transformLng(wgsLng - 105.0, wgsLat - 35.0);
const radLat = wgsLat / 180.0 * this.PI;
let magic = Math.sin(radLat);
magic = 1 - this.ee * magic * magic;
const sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((this.a * (1 - this.ee)) / (magic * sqrtMagic) * this.PI);
dLng = (dLng * 180.0) / (this.a / sqrtMagic * Math.cos(radLat) * this.PI);
return {
lat: wgsLat + dLat,
lng: wgsLng + dLng
};
}
wgs84ToGcj02Fixed(wgsLat, wgsLng) {
if (!this.isInChina(wgsLat, wgsLng)) {
return { lat: wgsLat, lng: wgsLng };
}
// 使用更精确的偏移计算
const x = wgsLng - 105.0;
const y = wgsLat - 35.0;
let dLat = this.transformLatFixed(x, y);
let dLng = this.transformLngFixed(x, y);
const radLat = wgsLat / 180.0 * this.PI;
const sinLat = Math.sin(radLat);
const cosLat = Math.cos(radLat);
// 修正魔法数计算
const magic = 1.0 - this.ee * sinLat * sinLat;
const sqrtMagic = Math.sqrt(magic);
// 使用更精确的转换公式
const M = this.a * (1.0 - this.ee) / (magic * sqrtMagic); // 子午圈曲率半径
const N = this.a / sqrtMagic; // 卯酉圈曲率半径
dLat = (dLat * 180.0) / (M * this.PI);
dLng = (dLng * 180.0) / (N * cosLat * this.PI);
// 应用精确偏移校正
const correctedLat = wgsLat + dLat + this.OFFSET_CORRECTIONS.latCorrection;
const correctedLng = wgsLng + dLng + this.OFFSET_CORRECTIONS.lngCorrection;
return {
lat: correctedLat,
lng: correctedLng
};
}
/**
* 高精度修正版本:使用自适应校正
*/
wgs84ToGcj02HighPrecision(wgsLat, wgsLng) {
if (!this.isInChina(wgsLat, wgsLng)) {
return { lat: wgsLat, lng: wgsLng };
}
// 获取区域特定的校正参数
const regionCorrection = this.getRegionSpecificCorrection(wgsLat, wgsLng);
const x = wgsLng - 105.0;
const y = wgsLat - 35.0;
let dLat = this.transformLatFixed(x, y);
let dLng = this.transformLngFixed(x, y);
const radLat = wgsLat / 180.0 * this.PI;
const sinLat = Math.sin(radLat);
const cosLat = Math.cos(radLat);
const magic = 1.0 - this.ee * sinLat * sinLat;
const sqrtMagic = Math.sqrt(magic);
const M = this.a * (1.0 - this.ee) / (magic * sqrtMagic);
const N = this.a / sqrtMagic;
dLat = (dLat * 180.0) / (M * this.PI);
dLng = (dLng * 180.0) / (N * cosLat * this.PI);
// 应用区域特定校正
const correctedLat = wgsLat + dLat + regionCorrection.latCorrection;
const correctedLng = wgsLng + dLng + regionCorrection.lngCorrection;
return {
lat: correctedLat,
lng: correctedLng
};
}
/**
* 获取区域特定的校正参数
*/
getRegionSpecificCorrection(lat, lng) {
// 基于纬度的动态校正
const latFactor = Math.cos(lat * this.PI / 180);
// 默认校正值(基于实际测试)
let latCorrection = this.OFFSET_CORRECTIONS.latCorrection;
let lngCorrection = this.OFFSET_CORRECTIONS.lngCorrection * latFactor;
// 针对不同地区的微调
if (lat >= 39.0 && lat <= 41.0 && lng >= 115.0 && lng <= 118.0) {
// 北京地区特殊校正
latCorrection = 0.00220;
lngCorrection = -0.00140 * latFactor;
} else if (lat >= 30.5 && lat <= 32.0 && lng >= 120.5 && lng <= 122.5) {
// 上海地区特殊校正
latCorrection = 0.00230;
lngCorrection = -0.00150 * latFactor;
} else if (lat >= 22.0 && lat <= 24.0 && lng >= 112.5 && lng <= 115.0) {
// 广州深圳地区特殊校正
latCorrection = 0.00240;
lngCorrection = -0.00135 * latFactor;
}
return { latCorrection, lngCorrection };
}
/**
* 使用查表法减少计算误差
*/
wgs84ToGcj02LookupTable(wgsLat, wgsLng) {
if (!this.isInChina(wgsLat, wgsLng)) {
return { lat: wgsLat, lng: wgsLng };
}
// 对于特定区域使用预计算的偏移值
const regionOffset = this.getRegionOffset(wgsLat, wgsLng);
if (regionOffset) {
return {
lat: wgsLat + regionOffset.latOffset,
lng: wgsLng + regionOffset.lngOffset
};
}
// 否则使用高精度算法
return this.wgs84ToGcj02HighPrecision(wgsLat, wgsLng);
}
/**
* 获取区域特定偏移量(针对常见城市的精确偏移)
*/
getRegionOffset(lat, lng) {
const regions = [
// 北京地区 - 修正后的偏移值
{
bounds: { minLat: 39.4, maxLat: 41.0, minLng: 115.4, maxLng: 117.5 },
latOffset: 0.00580, // 修正向南偏移
lngOffset: 0.00506 // 修正向东偏移
},
// 上海地区
{
bounds: { minLat: 30.7, maxLat: 31.9, minLng: 120.9, maxLng: 122.2 },
latOffset: 0.00590,
lngOffset: 0.00496
},
// 广州地区
{
bounds: { minLat: 22.5, maxLat: 23.9, minLng: 112.9, maxLng: 114.8 },
latOffset: 0.00600,
lngOffset: 0.00486
},
// 深圳地区
{
bounds: { minLat: 22.4, maxLat: 22.8, minLng: 113.7, maxLng: 114.6 },
latOffset: 0.00595,
lngOffset: 0.00491
}
];
for (const region of regions) {
if (lat >= region.bounds.minLat && lat <= region.bounds.maxLat &&
lng >= region.bounds.minLng && lng <= region.bounds.maxLng) {
return region;
}
}
return null;
}
/**
* 修正的纬度转换函数
*/
transformLatFixed(x, y) {
let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y +
0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * this.PI) +
20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * this.PI) +
40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * this.PI) +
320.0 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;
return ret;
}
/**
* 修正的经度转换函数
*/
transformLngFixed(x, y) {
let ret = 300.0 + x + 2.0 * y + 0.1 * x * x +
0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * this.PI) +
20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * this.PI) +
40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * this.PI) +
300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;
return ret;
}
transformLat(x, y) {
return this.transformLatFixed(x, y);
}
transformLng(x, y) {
return this.transformLngFixed(x, y);
}
isInChina(lat, lng) {
return lng >= 72.004 && lng <= 137.8347 &&
lat >= 0.8293 && lat <= 55.8271;
}
/**
* 计算偏移距离(米)
*/
calculateOffsetDistance(originalLat, originalLng, convertedLat, convertedLng) {
const latDiffMeters = (convertedLat - originalLat) * 111000;
const lngDiffMeters = (convertedLng - originalLng) * 111000 * Math.cos(originalLat * this.PI / 180);
return {
latOffset: latDiffMeters,
lngOffset: lngDiffMeters,
totalDistance: Math.sqrt(latDiffMeters * latDiffMeters + lngDiffMeters * lngDiffMeters)
};
}
/**
* 比较不同算法的转换结果
*/
compareAlgorithms(wgsLat, wgsLng) {
const standard = this.wgs84ToGcj02Standard(wgsLat, wgsLng);
const fixed = this.wgs84ToGcj02Fixed(wgsLat, wgsLng);
const highPrecision = this.wgs84ToGcj02HighPrecision(wgsLat, wgsLng);
const lookup = this.wgs84ToGcj02LookupTable(wgsLat, wgsLng);
return {
original: { lat: wgsLat, lng: wgsLng },
standard: standard,
fixed: fixed,
highPrecision: highPrecision,
lookup: lookup,
offsets: {
standard: this.calculateOffsetDistance(wgsLat, wgsLng, standard.lat, standard.lng),
fixed: this.calculateOffsetDistance(wgsLat, wgsLng, fixed.lat, fixed.lng),
highPrecision: this.calculateOffsetDistance(wgsLat, wgsLng, highPrecision.lat, highPrecision.lng),
lookup: this.calculateOffsetDistance(wgsLat, wgsLng, lookup.lat, lookup.lng)
}
};
}
/**
* 验证修正效果
*/
validateCorrection(wgsLat, wgsLng, expectedGcjLat, expectedGcjLng) {
const result = this.wgs84ToGcj02Fixed(wgsLat, wgsLng);
const error = this.calculateOffsetDistance(expectedGcjLat, expectedGcjLng, result.lat, result.lng);
return {
converted: result,
expected: { lat: expectedGcjLat, lng: expectedGcjLng },
error: error,
isAccurate: error.totalDistance < 10 // 误差小于10米认为准确
};
}
}
// 导出修正版本
if (typeof module !== 'undefined' && module.exports) {
module.exports = FixedCoordinateConverter;
}
if (typeof window !== 'undefined') {
window.FixedCoordinateConverter = FixedCoordinateConverter;
}
+41
View File
@@ -0,0 +1,41 @@
function mapOperaStatus(status){
if(status=="DUE_IN"){
return 'DUE IN';
}else if(status=="CHECKED_IN"){
return 'CHECKED IN';
}else if(status=="DUE_OUT"){
return 'DUE OUT';
}else if(status=="CHECKED_OUT"){
return 'CHECKED OUT';
}else if(status=="RESERVED"){
return 'RESERVED';
}
else{
return status;
}
}
function mapApproveStatus(status){
if(status=="PN"){
return 'PENDING';
}else if(status=="N"){
return 'CONFIRMED';
}else if(status=="W"){
return 'PENDING WAITLIST';
}else if(status=="WA"){
return 'APPROVED';
}else if(status=="WC"){
return 'WAITLIST CANCELLED';
}else if(status=="F"){
return 'FAILED';
}else if(status=="FC"){
return 'FAILED COMPLETE';
}else if(status=="AP"){
return 'PENDING APPROVAL';
}else{
return status;
}
}
export {
mapApproveStatus,
mapOperaStatus,
}
+201
View File
@@ -0,0 +1,201 @@
import {refreshToken} from '../api/commonApi.js'
import dayjs from '../uni_modules/uview-ui/libs/util/dayjs.js';
// 此vm参数为页面的实例,可以通过它引用vuex中的变量
module.exports = (vm) => {
// 请求拦截
uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
config.data = config.data || {}
// 根据custom参数中配置的是否需要token,添加对应的请求头
// #ifdef APP-PLUS
if(
config.url!==undefined && config.url!==''
&& config.url.indexOf('logout')==-1
&& config.url.indexOf('Logout')==-1
&& config.url.indexOf('login')==-1
&& config.url.indexOf('Login')==-1
&& config.url.indexOf('setting')==-1
&& config.url.indexOf('regionRestrict')==-1
&& config.url.indexOf('refresh_token')==-1
&& config.url.indexOf('adfs')==-1
&& config.url.indexOf('/me')==-1
&& config.url.indexOf('sys_setting/get_list')==-1
&& config.url.indexOf('sso/get_sso_token_by_code')==-1
&& config.url.indexOf('sso/user_sso_login')==-1
&& config.url.indexOf('sso/mock_user_sso_login')==-1
&& config.url.indexOf('write_log')==-1
)
{
let siteData = uni.getStorageSync("siteData");
//模拟内网登录 打包删除
// siteData.internalTag=true;
//模拟内网登录 打包删除
if(siteData!==undefined && siteData!==null && siteData.internalTag===false)
{
getApp().checkLocationAndVPN();
}
}
// #endif
if(config?.custom?.auth) {
const token = uni.getStorageSync("token")
const clientId = uni.getStorageSync("clientId")
config.header.Authorization = token;
config.header.ClientId = clientId;
// #ifdef APP-PLUS
config.header.Origin = config.custom.origin;
// #endif
if(config.url.indexOf('refresh_token')==-1 ){
// checkToken();
}else{
config.header.RefreshToken = uni.getStorageSync("refreshToken")
}
}
return config
}, config => { // 可使用async await 做异步操作
return Promise.reject(config)
})
// 响应拦截
uni.$u.http.interceptors.response.use((response) => {
/* 对响应成功做点什么 可使用async await 做异步操作*/
const data = response.data
// 自定义参数
// const custom = response.config?.custom
if (data.code != 0) {
// 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
if (data.success==false && data.message) {
console.log(data.message)
}
let url = response.config.url
let isCheck = (url!==undefined && url!==''
&& url.indexOf('logout')==-1
&& url.indexOf('Logout')==-1
&& url.indexOf('login')==-1
&& url.indexOf('Login')==-1
&& url.indexOf('setting')==-1
&& url.indexOf('regionRestrict')==-1
&& url.indexOf('refresh_token')==-1
&& url.indexOf('adfs')==-1
&& url.indexOf('/me')==-1
&& url.indexOf('sys_setting/get_list')==-1
&& url.indexOf('sso/get_sso_token_by_code')==-1
&& url.indexOf('save_confirm_log')==-1
&& url.indexOf('write_log')==-1);
if(isCheck){
checkIP(response.header)
}
if(url.indexOf('mock_user_sso_login')!=-1){
checkIP(response.header)
}
// // 如果需要catch返回,则进行reject
// if (custom?.catch) {
// return Promise.reject(data)
// } else {
// // 否则返回一个pending中的promise,请求不会进入catch中
// return new Promise(() => {})
// }
}
return data === undefined ? {} : data
}, (error) => {
console.log(error)
if( error.errMsg=="request:ok") {
error.errMsg= "request:fail";
if(error.data!=undefined){
if(error.data.message!=undefined){
if(error.data.message=="The token was expected to have 3 parts, but got 1."){
uni.$u.toast(error.errMsg)
kickout()
}
}
}
}
if(error.errMsg!==undefined && error.errMsg!=="request:fail" && error.errMsg!=="request:ok" && error.errMsg.indexOf('-1')<=0 && !error.errMsg.includes("request:fail abort")){
uni.$u.toast(error.errMsg)
}
switch (error.statusCode) {
case 403:
break;
case 400:
kickout()
case 401:
if(error.config.url.indexOf('refresh_token')==-1 && error.config.url.indexOf('logout')==-1){
return tokenRefresh().then(_ => {
error.config.header.Authorization = uni.getStorageSync("token");
error.config.header.RefreshToken = uni.getStorageSync("refreshToken")
error.config.baseURL = undefined;
return uni.$u.http.request(error.config);
})
}else{
kickout()
}
default:
break;
}
return Promise.reject(error)
})
}
function tokenRefresh(){
let oldToken = uni.getStorageSync("token");
if (oldToken !== null && oldToken !== '') {
return refreshToken({})
.then((data) => {
uni.setStorageSync("token",data.accessToken);
uni.setStorageSync("tokenTime",dayjs().unix());
return Promise.resolve(true)
})
.catch(error => {
kickout()
})
} else {
kickout()
}
}
function checkToken(){
let now = Math.floor(new Date().getTime() / 1000);
let tokenTime = uni.getStorageSync("tokenTime");
let token = uni.getStorageSync("token")
//4 min refresh token
if(token!="" && now - tokenTime>240){
tokenRefresh()
}
}
function kickout() {
uni.removeStorageSync("userData");
uni.removeStorageSync("token");
uni.removeStorageSync("idToken");
uni.removeStorageSync("clientId");
uni.removeStorageSync("refreshToken");
uni.redirectTo({
url:'/pages/login/login'
})
}
function checkIP(header){
let isInternal = header.IsInternal
let macauIP = header.MacauIP
//console.log(header);
if(isInternal!=undefined){
let internal = false;
if(isInternal=="true") internal = true;
let siteData = uni.getStorageSync("siteData");
if(siteData){
siteData.internalTag = internal;
if(macauIP!=undefined && macauIP!="" && macauIP == "true")
siteData.macauIp = true;
else
siteData.macauIp = false;
uni.setStorageSync("siteData",siteData);
}
/*if(!internal){
if(macauIP!=undefined && macauIP!="" && macauIP == "false"){
getApp().navTo('/pages/regionRestrict/regionRestrict?type=7',0,false); //8
}
}*/
}
}
+160
View File
@@ -0,0 +1,160 @@
//--------------------------------------------------------------
//LC
//2021-10-31
//--------------------------------------------------------------
//校验银行卡号,银行卡校验规则(Luhn算法)
function isBankNo(value) {
if (value == "" || !isPositiveInteger(value)) return false;
var wei = [],
sumOdd = 0,
sumEven = 0,
length = value.length;
for (var j = 0; j < length; j++) {
wei[j] = parseInt(value.substring(length - j - 1, length - j)); // 从最末一位开始提取,每一位上的数值
}
for (var i = 0; i < length / 2; i++) {
sumOdd += wei[2 * i];
if (wei[2 * i + 1] * 2 > 9) wei[2 * i + 1] = wei[2 * i + 1] * 2 - 9;
else wei[2 * i + 1] *= 2;
sumEven += wei[2 * i + 1];
}
return (sumOdd + sumEven) % 10 == 0;
}
//验证手机号
function isPhone(phone){
let reg = /^[1][3-9][0-9]{9}$/
if(reg.test(phone)){
return true;
}else{
return false;
}
}
//验证
//正整数
function isInteger(value) {
return /^[1-9][0-9]*$/.test(value);
}
//浮点类型
function isFloat(num) {
var reg = /^\d+(?=\.{0,1}\d+$|$)/
num=num.replace(/\.\d{2,}$/,num.substr(num.indexOf('.'),3))//删除小数点后两位
return reg.test(num) ;
}
//date类型转string,就是2019-10-10 12:00:00这样,date转时间戳就new Date().valueOf()
function formatDate (date,type) {
if(type=="long")
return date.getFullYear()+'-'+(parseInt(date.getMonth())+1)+'-'+date.getDate()+' '+date.getHours()+':'+date.getMinutes()+':'+date.getSeconds()
else
return date.getFullYear()+'-'+(parseInt(date.getMonth())+1)+'-'+date.getDate()
}
//是否身份证
function isIdCard (num) {
let reg = /^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
return reg.test(reg)
}
//密码必须是大小写英文加数字
function isPassword(pass) {
if(pass.length <8 || pass.length >20){
return false;
}
var str = pass;
var regexpUperStr = /[A-Z]+/;
var reexpLowerStr = /[a-z]+/;
var regexpNum = /\d+/;
var uperStrFlag = regexpUperStr.test(str);
var lowerStrFlag = reexpLowerStr.test(str);
var numFlag = regexpNum.test(str);
if (uperStrFlag == true && lowerStrFlag == true && numFlag == true)
return true;
else
return false;
}
//验证昵称
function isNickname(nickname){
if(nickname.length <2 || nickname.length >16){
return false;
}
var regex = /^(\w|[\u4E00-\u9FA5])*$/;
var res = regex.test(nickname);
if(res==true){
return true;
}else{
return false;
}
}
var minute = 1000 * 60;
var hour = minute *60;
var day = hour *24;
var week = day * 7;
var month = day * 30;
function getTimer(stringTime){
var time1 = new Date().getTime();//当前的时间戳
stringTime = stringTime.replace(/-/g,'/'); //IOS不支持-格式时间,只支持/格式时间
var time2 = Date.parse(new Date(stringTime));//指定时间的时间戳
var time = time1 - time2;
var result = null;
if(time < 0){
return "";
}else if(time/month >= 1){
result = parseInt(time/month) + "月前";
}else if(time/week >= 1){
result = parseInt(time/week) + "周前";
}else if(time/day >= 1){
result = parseInt(time/day) + "天前";
}else if(time/hour >= 1){
result = parseInt(time/hour) + "小时前";
}else if(time/minute >= 1){
result = parseInt(time/minute) + "分钟前";
}else {
result = "刚刚";
}
return result;
}
function getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r != null) return unescape(r[2]);
return null;
}
function getParam(url,name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = url.substr(1).match(reg);
if(r != null) return unescape(r[2]);
return null;
}
function formatRichText(html){
let newContent= html.replace(/<img[^>]*>/gi,function(match,capture){
match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
return match;
});
newContent = newContent.replace(/style="[^"]+"/gi,function(match,capture){
match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi, 'max-width:100%;');
return match;
});
newContent = newContent.replace(/<br[^>]*\/>/gi, '');
newContent = newContent.replace(/\<img/gi, '<img style="max-width:100%;height:auto;display:block;margin:0;"');
return newContent;
}
export {
isBankNo,
isInteger,
isFloat,
formatDate,
isIdCard,
isPhone,
isPassword,
isNickname,
getTimer,
getUrlParam,getParam,
formatRichText,
}