Commit 9373addb authored by 郭志伟's avatar 郭志伟

feat(init): 代码优化

parent c6a3dc05
This diff is collapsed.
import http from '@/service/httpDecorator';
import config from '@/config';
const { talosHost, faceHost } = config;
export default {
// 获取信用钱包用户信息
getXhkInfo() {
return http.get(`${talosHost}/api/kdsp/profile/vcc/user-account`);
},
getUserInfo() {
return http.get(`${talosHost}/api/kdsp/user/about`);
}
};
// 发送短信
export const smsCode = param => {
const data = { ...param, smsMerchant: 'XIN_YONG_QIAN_BAO' };
return http.post(`${talosHost}/vcc/usercenter/send_vcc_sms_code`, data);
};
// KA流程节点
export const kaGetNextUrl = params => {
let options = {
sonVccChannel: true
};
return http.get(`${talosHost}/api/kdsp/ka/process/get-next-url`, { params }, options);
};
// 验证短信并登录
export const friendLogin = data => {
return http.post(`${talosHost}/vcc/usercenter/fast_login_by_sms_code`, data);
};
// 验证短信类型
export const captchaType = data => {
return http.post(`${talosHost}/vcc/usercenter/captcha_type`, data);
};
// 获取图形验证
export const captcha = () => {
return http.get(`${talosHost}/vcc/usercenter/qg_captcha`);
};
export const getFaceUrl = params => {
return http.get(`${faceHost}/auth-center/ex/face/h5/auth_url.json`, { params });
};
export default {
MP_URL_MAP: {
home: '/pages/index/index',
webview: '/pages/webview/webview',
// webview: '/pages/groupbuy/webview',
middleWay: '/pages/webview/middleWay',
goodDetail: '/pages/product/goodDetail',
landPage: '/pages/landing/goods',
searchPage: '/pages/search/index'
}
};
export const APP_ID = '102';
export const PUBLIC_KEY = `
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCGf4wnNJXHXM54wsmxTwhpiPaAp27zM
3QsrWu1+GOMoCDmAEOb2jYjyNhwBIeV9eY0fwoK+MfWBywbonypyXs1j5l/mTmFRQ8IZY
+xZF0t01cornoMpKJncoNiwqc9OnsiwGPqzIs/iLalBonppqhWSn0g99vFS2qgr0WnOWl
qLQIDAQAB
-----END PUBLIC KEY-----
`;
export const PRIVATE_KEY = `
-----BEGIN RSA PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIC46noXi7VhxDMCQNK3x
k7uVQICaIwhQ6Ye5c5XYaM9IgUhFUioQZ3llelM3oAnYqLuAZMU0POcNqm8qmr7I3fc8A
SZZKm5XUm6i/PI++xT+5c9zhHHsHumoSoTJ/bpS8xNhDFz/X2JQTIn6izFtBBnsMJRx5K
aJWXYebk1RyCVAgMBAAECgYA27bGxE+ccKXINykJbKOzItc80ok52raMuejTaTlNt0yJ3
SdzJOnN1q4jDG3g++4+Nsz6cwt8/dUOmPsoCCNTjMDUg40Cl8NopPMXvo/INwd2vJSEFr
JyC629pl3N7E18Iqjdt8jMy/zEMSDMPh7+NDtSDQqfQpeT0w31/Q1qdwQJBALtk/xIIPN
/zyCZcAIKtXvp0FrHslEL55q01kV6bwhyfAnyz+GcGJwxPWOKJ1FRCnzjOZRc3ygekMZU
WGLjszDkCQQCv2Qo/q97pjw4QwxsTwuuQKlLhAuBr2W0eTsnou9tk3i7PJX/xQXlccp0C
FRWAe3xdpYtapUiMJ8zpKkw+PC89AkBdn9UMRk9buKmL+LVMlJ/6U5uvIzrjx4UnjrblZ
L5znEIa2bPGjT1fGhmXfTM3Md3o/L1m/zmR3cfj65lIcw6JAkB0uf6qmz0CDnrIt6pOqN
HTRbT0NgOgs5hSSPyQJ7sPrsilqn/ONqcHrfD5A+PdAJtiUlQ5nIOWvYiwseogWbUFAkB
y6/cB1HblHJzuyJwaAW9vLNmbqeKW5DhU2QG7Jp1uUgk4GcopDAgFWlAjbQcBCGDyStHH
YxINn+qpKviRkeFf
-----END RSA PRIVATE KEY-----
`;
/*
* @Description: autoSaveForm mixins
* @LastEditors: gzw
* @Date: 2019-08-14 15:53:37
* @LastEditTime: 2020-12-15 19:17:44
*/
import localStorage from '@/service/localStorage.service';
export default {
data() {
return {
autoSaveTimer: null
};
},
methods: {
autoSaveHandler(key, saveKey, interval = 1000) {
if (this.autoSaveTimer) {
clearTimeout(this.autoSaveTimer);
}
const val = this[key];
this.autoSaveTimer = setTimeout(() => {
localStorage.set(saveKey, val);
}, interval);
},
clearSaveHandler(key) {
localStorage.remove(key);
},
hasAutoSaveData(key) {
return !!localStorage.get(key);
},
getSaveParams(key) {
return localStorage.get(key);
},
getSaveInfoHandler(key, target) {
this[target] = localStorage.get(key);
this[target + 'Cache'] = JSON.parse(JSON.stringify(localStorage.get(key)));
this.$forceUpdate();
}
}
};
/*
* @Description: 页面跳转时保存当前浏览位置和数据,返回时加载原有数据
* @Date: 2020-11-19 11:49:00
* @LastEditors: gzw
* @LastEditTime: 2020-11-19 14:46:51
*/
export default {
data() {
return {
cacheKey: '',
saveKeys: [],
loadCache: false
};
},
methods: {
setListCache() {
const val = {};
if (!this.saveKeys || !this.saveKeys.length) return;
this.saveKeys.forEach(item => {
val[item] = this[item];
});
val.scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
sessionStorage.setItem(this.cacheKey, JSON.stringify(val));
},
clearListCache() {
sessionStorage.removeItem(this.cacheKey);
},
hasListCache() {
return !!sessionStorage.getItem(this.cacheKey);
},
getListCache() {
this.loadCache = true;
const listCache = JSON.parse(sessionStorage.getItem(this.cacheKey));
this.saveKeys.forEach(item => {
this[item] = listCache[item];
});
document.documentElement.scrollTop = listCache.scrollTop;
document.body.scrollTop = listCache.scrollTop;
this.clearListCache();
this.$nextTick(() => {
this.loadCache = false;
});
}
}
};
export default [
{
path: '/',
redirect: '/error'
redirect: '/pay'
},
{
path: '/pay',
......
/*
* @Description: 数据加密,aes加密数据主体,rsa加密aes密钥,aes密钥前端自己存储
* @Date: 2020-12-08 11:08:28
* @LastEditors: gzw
* @LastEditTime: 2021-07-07 17:44:22
*/
import { cipher as AES, util as UTIL, pki as PKI, md as SHA1 } from 'node-forge';
import uuidv1 from 'uuid/v1';
import { parseTime } from './utils.service';
import { APP_ID, PUBLIC_KEY, PRIVATE_KEY } from '@/config/encrypt.config';
import CryptoJS from 'crypto-js';
import pay from '@/api/pay.api';
/**
* @description: 数据加密
* @param {String} data 数据源
* @return {String} 加密后的数据base64
*/
export function encryption(data = '') {
if (!data) return null;
const key = generateRandomStr(16);
const iv = key; // 后台约定iv与key一致
const plaintext = typeof data === 'object' ? JSON.stringify(data) : data;
const body = encryptDataByAes(plaintext, key, iv); // AES加密数据
const encryptKey = encryptDataByPb(key); // RSA公钥加密AES密钥
const signData = generateSign(plaintext);
return {
appId: APP_ID,
body,
encryptKey,
...signData
};
}
/**
* @description: 数据加密
* @message {String} message 数据源
......@@ -48,85 +16,3 @@ export async function encryptByDESModeEBC(message) {
});
return encrypted.ciphertext.toString().toLocaleUpperCase();
}
/**
* @description: AES加密数据,默认CBC, Pki#cs7
* @param {String} txt 数据源
* @param {String} key 密钥,16位字符串
* @param {String} iv 初始化向量
* @return {String} 加密后的数据base64
*/
function encryptDataByAes(txt, key, iv) {
const cipher = AES.createCipher('AES-CBC', key);
cipher.start({ iv });
cipher.update(UTIL.createBuffer(txt, 'utf8'));
cipher.finish();
const ciphertext = cipher.output.getBytes();
return buffer2Base64(ciphertext);
}
/**
* @description: 使用RSA公钥加密数据
* @param {String} txt 数据源
* @return {String} 加密后的数据base64
*/
function encryptDataByPb(txt) {
const publicKey = PKI.publicKeyFromPem(PUBLIC_KEY);
const pbData = publicKey.encrypt(txt);
return buffer2Base64(pbData);
}
/**
* @description: RSA私钥+SHA1生成签名
* 签名组成结构nonce+appid+timestamp+body
* @param {String} txt 数据源
* @return {Object} 生成的sign数据,时间戳、Nonce
*/
function generateSign(txt) {
const timestamp = parseTime('');
const nonce = generateNonce();
const privateKey = PKI.privateKeyFromPem(PRIVATE_KEY);
const md = SHA1.sha1.create();
md.update(nonce + APP_ID + timestamp + txt, 'utf8');
let sign = privateKey.sign(md);
sign = buffer2Base64(sign);
return {
timestamp,
nonce,
sign
};
}
/**
* @description: buffer转base64
* @param {Buffer} buf buffer源数据
* @return {String} base64 字符串
*/
function buffer2Base64(buf) {
return UTIL.encode64(buf);
}
/**
* @description: 生成nonce(uuid)
* 规则:以当前时间的uuid作为name,以随机生成的uuid作为namespace,生成最终的uuid
* @return {String} 生成的uuid
*/
function generateNonce() {
return uuidv1();
}
/**
* @description: 生成随机字符串
* @param {Number} n 位数
* @return {String} 生成的字符串
*/
function generateRandomStr(n) {
const len = n || 32;
const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789';
const maxPos = chars.length;
let pwd = '';
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
import HttpRequest from '@qg/ui-request';
import { Toast } from '@qg/cherry-ui';
import store from '@/store';
import { appVersion, isApp, isWxMp } from '@/service/validation.service';
import { appVersion, isWxMp } from '@/service/validation.service';
import { getVccChannel } from './userInfo.service';
import localStorage from '@/service/localStorage.service';
import sessionStorage from '@/service/sessionStorage.service';
import MpBridge from '@/service/mp';
import Bridge from '@qg/js-bridge';
function getURLSearchParams(json) {
if (!json) return '';
......@@ -24,11 +22,6 @@ const http = new HttpRequest(
const { data, config } = res;
const returnRawData = config.rawData;
if (returnRawData) return [data, null];
// if (data.businessCode === '401' || data.businessCode === '0401') {
// // router.push({ name: 'login' });
// window.localStorage.removeItem('vccToken');
// window.sessionStorage.removeItem('vccToken');
// }
const success =
(data.code === '0000' && data.businessCode === '0000') || data.business_code === 0;
if (success) {
......@@ -47,29 +40,10 @@ const http = new HttpRequest(
) {
localStorage.remove('vccToken');
sessionStorage.remove('vccToken');
if (isApp) {
const nativeBridge = new Bridge();
window.xyqbNativeEvent = function(res) {
const json = typeof res === 'string' ? JSON.parse(res) : res;
if (json.event === 'getTokenSuccess') {
const appData = json.data || {};
if (appData && appData.token) {
localStorage.set('vccToken', appData.token);
sessionStorage.set('vccToken', appData.token);
setTimeout(() => {
window.location.reload();
}, 500);
}
}
};
nativeBridge.getToken();
}
if (isWxMp) {
const nativeBridge = new MpBridge();
nativeBridge.getToken({
clear: 1
});
}
const toast = Toast('未登录!');
toast.onClose = () => {
window.location.href = document.referrer;
};
}
console.error(error);
......
/*
* @Description: h5 与 mp 交互
* @Date: 2021-04-29 15:19:37
* @LastEditors: gzw
* @LastEditTime: 2021-06-07 19:30:02
*/
import qs from 'qs';
import commonCfg from '../config/common.setting';
const { MP_URL_MAP } = commonCfg;
class Mp {
constructor() {
this.callbackQueue = {};
this.wx = require('weixin-js-sdk');
}
// 小程序中postMessage在特定时机(小程序后退、组件销毁、分享)触发; 如果需要立即触发,需要navigateTo跳转
run(data, callback, immediate = false) {
const { wx } = this;
console.log(data.event);
if (immediate) {
const url = `${MP_URL_MAP.middleWay}${qs.stringify(data, {
encode: true,
addQueryPrefix: true
})}`;
if (callback) this.callbackQueue[data.event] = callback;
wx.miniProgram.navigateTo({
url,
success: () => {
this.bindListener();
}
});
} else {
wx.miniProgram.postMessage({ data });
}
}
getToken(data, callback = () => {}) {
this.run({ event: 'getToken', ...data }, callback, true);
}
closeBrowser() {
const { wx } = this;
wx.miniProgram.navigateBack();
}
openNewUrl(data = {}) {
const { wx } = this;
const { newUrl } = data;
console.log(newUrl);
if (/(https|http):\/\//gi.test(newUrl)) {
// window.location.href = newUrl;
wx.miniProgram.navigateTo({
url: `${MP_URL_MAP['webview']}?url=${encodeURIComponent(JSON.stringify(newUrl))}`
});
} else if (/xyqb:\/\//gi.test(newUrl)) {
let urlTag = '';
if (/goodsdetail|goodsDetail/gi.test(newUrl)) {
urlTag = 'goodDetail';
} else if (/goodsList/gi.test(newUrl)) {
urlTag = 'landPage';
} else if (/discover|homepage/gi.test(newUrl)) {
urlTag = 'home';
} else {
urlTag = 'home';
}
if (urlTag) {
const url = `${MP_URL_MAP[urlTag]}?${newUrl.split('?')[1]}`;
wx.miniProgram[urlTag === 'home' ? 'reLaunch' : 'navigateTo']({ url });
}
} else {
wx.miniProgram[data.type || 'navigateTo']({
url: newUrl
});
}
}
getHashData(that, currentHref) {
const hashArr = decodeURIComponent(currentHref).split('#/');
const lastHashStr = hashArr[hashArr.length - 1];
const hashData = qs.parse(lastHashStr);
this.callbackQueue[hashData.event](hashData.data);
this.unBindListener();
}
// TODO hashchange使用非匿名函数,获取location是异步的
bindListener() {
window.addEventListener(
'hashchange',
() => {
this.getHashData(this, window.location.href);
},
false
);
}
// TODO
unBindListener() {
window.removeEventListener(
'hashchange',
() => {
this.getHashData(this, window.location.href);
},
false
);
}
}
export default Mp;
import localStorage from './localStorage.service';
export const basicOptions = {
// 职业选项
jobs: [
{
value: 'WORKER',
name: '工人'
},
{
value: 'TEACHER',
name: '教师'
},
{
value: 'WHITE_COLLAR',
name: '白领'
},
{
value: 'CAREER_BUILDER',
name: '创业者'
},
{
value: 'SELF_EMPLOYER',
name: '个体户'
},
{
value: 'EMPLOYEE',
name: '公司职员'
},
{
value: 'BISUNESS_ENTITY',
name: '企业法人'
},
{
value: 'ONLINE_STORE_OWNER',
name: '网店店主'
},
{
value: 'UNEMPLOYED',
name: '暂无职业'
},
{
value: 'OTHER',
name: '其他'
}
],
// 学历选项
educationList: [
{
value: 'MASTER',
name: '硕士及以上'
},
{
value: 'UNDER_GRADUATE',
name: '本科'
},
{
value: 'JUNIOR_COLLEGE',
name: '大专'
},
{
value: 'TECHNICAL_SECONDARY_SCHOOL',
name: '中专'
},
{
value: 'TECHNICAL_SCHOOL',
name: '技校'
},
{
value: 'HIGH_SCHOOL',
name: '高中'
},
{
value: 'MIDDLE_SCHOOL',
name: '初中'
},
{
value: 'PRIMARY_SCHOOL',
name: '小学'
},
{
value: 'OTHER',
name: '其他'
}
],
// 月收入选项
incomeRangeList: [
{
value: 'BELOW_1000',
name: '小于1000元'
},
{
value: 'BELOW_3000',
name: '1000至3000元'
},
{
value: 'BELOW_5000',
name: '3000至5000元'
},
{
value: 'BELOW_8000',
name: '5000至8000元'
},
{
value: 'BELOW_10000',
name: '8000至10000元'
},
{
value: 'BELOW_15000',
name: '10000至15000元'
},
{
value: 'BELOW_20000',
name: '15000至20000元'
},
{
value: 'ABOVE_20000',
name: '大于20000元'
}
],
emailList: [
{
value: 1,
name: 'qq.com'
},
{
value: 2,
name: '163.com'
},
{
value: 3,
name: '126.com'
},
{
value: 4,
name: 'icloud.com'
},
{
value: 5,
name: '139.com'
},
{
value: 6,
name: '189.com'
},
{
value: 7,
name: 'gmail.com'
}
]
};
export const relation = [
{
value: 'PARENT',
name: '父母'
},
{
value: 'CHILDREN',
name: '子女'
},
{
value: 'BROTHER',
name: '兄弟姐妹'
},
{
value: 'COLLEAGUE',
name: '同事'
},
{
value: 'CLASSMATE',
name: '同学'
},
{
value: 'FRIEND',
name: '朋友'
},
{
value: 'SPOUSE',
name: '夫妻'
},
{
value: 'SELF',
name: '本人'
},
{
value: 'OTHER',
name: '其他'
}
];
// 消费额度申请合同列表
export const authList = [
{
id: 328,
contractTemplateName: '客户非学生承诺函'
},
{
id: 9,
contractTemplateName: '个人信息查询及使用综合授权书'
}
];
export const qoutaList = [
{
id: 281,
contractTemplateName: '上海银行直销银行电子账户服务协议'
},
{
id: 414,
contractTemplateName: '享花卡消费贷款服务协议'
},
{
id: 413,
contractTemplateName: '享花卡服务协议'
},
{
id: 412,
contractTemplateName: '委托扣款授权书'
}
];
export const xyqbDownLink =
'https://activity.q-gp.com/activity/59a4d7f7f70cff7a37fed830?from=singlemessage&isappinstalled=0';
export const toUseUrl = 'xyqb://mall/goodsList?title=品牌尖货&labelId=58&categoryId=';
export function wxsdk() {
if (+localStorage.get('vccChannel') !== 159913) return; // 是否是小程序
var oHead = document.getElementsByTagName('head').item(0);
......
import user from '@/api/user.api';
import store from '@/store';
import { getQueryString, parseSearch } from './utils.service';
import { parseSearch } from './utils.service';
import localStorage from './localStorage.service';
// eslint-disable-next-line space-before-function-paren
export const getUserInfo = async () => {
const [data] = await user.getUserInfo();
const { userInfo } = data || {};
store.commit('CHANGE_LOGIN', userInfo);
return userInfo;
};
export const getToKen = () => {
const vccToken = getQueryString('vccToken');
const oldToken = localStorage.get('vccToken') || '';
if (!oldToken) {
store.commit('CHANGE_TOKEN', vccToken);
}
};
export function getVccChannel(channelKey = 'vccChannel') {
if (channelKey === 'sonVccChannel') {
......
import { isAndroid, isIOS, isXyqb, isWxMp } from './validation.service';
import Bridge from '@qg/js-bridge';
import MpBridge from '@/service/mp';
const jsBridge = new Bridge();
import Vue from 'vue';
import config from '@/config';
export const EventBus = new Vue();
import qs from 'qs';
/**
* 替换邮箱字符
* @param {String} email 输入字符串
* @return: {Function} new_email 邮箱
*/
export function regEmail(email) {
if (String(email).indexOf('@') > 0) {
const str = email.split('@');
let _s = '';
if (str[0].length > 3) {
for (var i = 0; i < str[0].length - 3; i++) {
_s += '*';
}
}
var new_email = str[0].substr(0, 3) + _s + '@' + str[1];
}
return new_email;
}
/**
* 替换手机字符
* @param {String} mobile 输入字符串
* @return: {Function} new_email 邮箱
*/
export function regMobile(mobile) {
if (mobile.length > 7) {
var new_mobile = mobile.substr(0, 3) + '****' + mobile.substr(7);
}
return new_mobile;
}
/**
* 去除两侧空格
* @param {String} s 输入字符串
* @return: {Function} new_email 邮箱
*/
export function stringTrim(s) {
s = stringTrimLeft(s);
return stringTrimRight(s);
}
/**
* 去除左侧空格
* @param {String} s 输入字符串
* @return: {Function} new_email 邮箱
*/
export function stringTrimLeft(s) {
return s.replace(/^[\s\n\t]+/g, '');
}
/**
* 去除右侧空格
* @param {String} s 输入字符串
* @return: {Function} new_email 邮箱
*/
export function stringTrimRight(s) {
return s.replace(/[\s\n\t]+$/g, '');
}
/**
* 只能输入中文、英文、数字
* @param {String} str 输入字符串
* @return: {String} new_stremail 中文、英文、数字
*/
export function filterSc(str) {
// eslint-disable-next-line
return str.replace(/[^\a-\z\A-\Z0-9\u4E00-\u9FA5]/g, "");
}
/**
* 字符长度(中文)
* @param {String} str 输入字符串
* @return: {Number} len 长度
*/
export function strLen(str) {
var len = 0;
for (var i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
//单字节加1
if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
len++;
} else {
len += 2;
}
}
return len;
}
/**
* 替换emoji表情
* @param {String} name 输入字符串
* @return: {String} str 字符串
*/
export function filterEmoji(name) {
// eslint-disable-next-line
let str = name.replace(
// eslint-disable-next-line
/[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/gi,
''
);
return str;
}
import { isAndroid, isIOS } from './validation.service';
/**
* hash路由获取url参数
......@@ -136,75 +27,6 @@ export function parseSearch(searchString) {
return result;
}, {});
}
/**
* 时间转换
* @param {String} time 需要转换的时间
* @param {String} cFormat 格式 {y}-{m}-{d} {h}:{i}:{s}
* @return: {String} timeStr 转换完成的时间
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return '-';
}
if (time == null) {
return '-';
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}';
let date;
if (time == '') {
date = new Date();
} else if (typeof time === 'object') {
date = time;
} else if (!isNaN(time) && ('' + time).length === 10) {
time = parseInt(time) * 1000;
} else {
if (String(time).indexOf('T') > -1) {
time = time.replace(/T/g, ' ').replace(/\..*/g, '');
}
if (
(String(time).indexOf('-') > -1 || String(time).indexOf('.') > -1) &&
String(time).indexOf('T') == -1
) {
time = time.replace(/-|\./g, '/');
}
date = new Date(time);
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
};
const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key];
if (key === 'a') {
return ['', '', '', '', '', '', ''][value];
}
if (result.length > 0 && value < 10) {
value = '0' + value;
}
return value || 0;
});
return timeStr;
}
//返回拨打标签
export function regPhone(data) {
const regExp = new RegExp(/((0\d{2,3}-\d{7,8})|(1[358674]\d{9}))/, 'g'); //匹配电话,以便能直接拨打
const newData = data.replace(regExp, "<a class='tel' href='tel:$1'>$1</a>");
return newData;
}
export function formatPhone(phone) {
const reg = /^(\d{3})(\d{4})(\d{4})$/;
const matches = reg.exec(phone);
const newPhone = matches[1] + ' ' + matches[2] + ' ' + matches[3];
return newPhone;
}
/**
* @description: 移动端监听软键盘弹起或收起,IOS,android
* @param {Boolean} off 是否销毁
......@@ -295,17 +117,6 @@ export function changeTitleOfIOS() {
}
}
export function getParameterByName(name, url) {
if (!url) url = window.location.href;
// eslint-disable-next-line no-useless-escape
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
// 清除键盘
export function clearKeyboard() {
var input = document.getElementsByTagName('input');
......@@ -317,118 +128,3 @@ export function clearKeyboard() {
textarea[i].blur();
}
}
export function idNoFormat(value) {
return value.replace(/(\d{6})(\d{0,8})?(\d{0,4})?/, function(res, $1, $2, $3) {
if (res.length <= 6) {
return $1;
}
if (res.length <= 14) {
return $1 + ' ' + $2;
}
return $1 + ' ' + $2 + ' ' + $3;
});
}
export function dateFormat(value) {
return value.replace(/(\d{4})(\d{2})(\d{2})/, '$1.$2.$3');
}
export function getQueryString(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
// HEX转RGB
export function hexToRgb(hex) {
var rgb = [];
for (let i = 1; i < 7; i += 2) {
rgb.push(parseInt('0x' + hex.slice(i, i + 2)));
}
return rgb;
}
export function setAppTitleColor(bgcolor = '#fff') {
if (!isXyqb) return;
const isGradient = Array.isArray(bgcolor);
let rgbColor = isGradient ? bgcolor[0] : bgcolor;
if (rgbColor.toLocaleLowerCase().indexOf('#') > -1) rgbColor = hexToRgb(rgbColor);
const isDarkContent = 0.213 * rgbColor[0] + 0.715 * rgbColor[1] + 0.072 * rgbColor[2] <= 255 / 2;
const colors = isGradient
? [bgcolor[0].substr(1), bgcolor[1].substr(1)]
: [bgcolor.substr(1), bgcolor.substr(1)];
jsBridge.run({
event: 'resetNavigationBarColor',
data: {
isDarkContent,
colors
}
});
}
export function paramsParentheses(pointer) {
let params = pointer.$route.query;
const path = pointer.$route.path;
Object.keys(params).indexOf('vccToken') > -1 && delete params.vccToken;
const paramsString = qs.stringify(params);
return `${config.localHost}${path}?` + paramsString;
}
export function firstGroupShare(shareInfo, type) {
if (!isWxMp) return;
const nativeBridge = new MpBridge();
if (!shareInfo) {
nativeBridge.run({
event: 'showShareView',
data: {
shareDic: {
title: `[0元购] 羊小咩Plus`,
link: '/pages/index/index', // 页面地址
imgUrl:
'https://img.lkbang.net/activity/share/default/shareDefault.png?imageMogr2/thumbnail/500x500/quality/75/interlace/1' // 图片地
}
}
});
return;
}
// eslint-disable-next-line no-unused-vars
const vccTokenString = `vccToken=${encodeURIComponent('{token}')}`;
let linkPath = '';
let detailData = {
skuNo: shareInfo.skuNo,
goodsSpecialId: shareInfo.goodsSpecialId,
activityId: shareInfo.activityId,
templateId: shareInfo.templateId,
templateDetailId: shareInfo.templateDetailId,
vccToken: encodeURIComponent('{token}')
};
switch (type) {
case 0:
linkPath = `${config.localHost}/groupBuy/list?activityId=${shareInfo.activityId}&${vccTokenString}`;
break;
case 1:
linkPath = `${config.localHost}/orderList/0?${vccTokenString}`;
break;
case 2:
case 3:
shareInfo.groupBuyGroupId && (detailData.groupBuyGroupId = shareInfo.groupBuyGroupId);
linkPath = qs.stringify(detailData);
linkPath = `${config.localHost}/groupBuy/skuInfo?${linkPath}`;
break;
}
shareInfo.linkPath = `/pages/groupbuy/webview?url=${encodeURIComponent(
JSON.stringify(linkPath)
)}`;
const tagName = type ? '[0元购] ' : '';
nativeBridge.run({
event: 'showShareView',
data: {
shareDic: {
title: `${tagName}${shareInfo.skuName}`,
link: shareInfo.linkPath, // 页面地址
imgUrl: shareInfo.skuImg // 图片地
}
}
});
}
/*eslint-disable*/
import { stringTrim } from './utils.service';
// 判断输入内容是否为空
export function isNull(str) {
return str === undefined || str.length === 0 || str === null;
}
// 判断输入内容去掉空格是否为空
export function isTrimNull(str) {
if (str === undefined || str.length === 0 || str === null) {
return true;
}
return stringTrim(str).length === 0;
}
// 判断日期类型是否为YYYY-MM-DD格式的类型
export function isDate(str) {
if (!isNull(str)) {
const reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/;
const r = str.match(reg);
return r !== null;
}
}
// 判断日期类型是否为YYYY-MM-DD hh:mm:ss格式的类型
export function isDateTime(str) {
if (!isNull(str)) {
const reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;
const r = str.match(reg);
return r !== null;
}
return false;
}
// 判断日期类型是否为hh:mm:ss格式的类型
export function isTime(str) {
if (!isNull(str)) {
const reg = /^((20|21|22|23|[0-1]\d)\:[0-5][0-9])(\:[0-5][0-9])?$/;
return reg.test(str);
}
return false;
}
// 校验是否合法日期
export function isValidDate(date) {
return date instanceof Date && !isNaN(date.getTime());
}
// 判断输入的字符是否为英文字母
export function isLetter(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z]+$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为整数
export function isInteger(str) {
if (!isNull(str)) {
const reg = /^[-+]?\d*$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为身份证号
export function isIdNo(str) {
if (!isNull(str)) {
const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为中文姓名最少两个中文字符
export function isChineseName(str) {
if (!isNull(str)) {
const reg = /^[\u0391-\uFFE5\·]{2,}$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否以数字开头
export function isStartWithInteger(str) {
if (!isNull(str)) {
const reg = /^[0-9].*$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为双精度
export function isDouble(str) {
if (!isNull(str)) {
const reg = /^[-\+]?\d+(\.\d+)?$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为:a-z,A-Z,0-9,_,并以字母开头
export function isProgramVar(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z][a-zA-Z0-9_]*$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为:a-z,A-Z,0-9,_,并以大写字母开头
export function isProgramClassName(str) {
if (!isNull(str)) {
const reg = /^[A-Z][a-zA-Z0-9_]*$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为中文
export function isChinese(str) {
if (!isNull(str)) {
const reg = /^[\u0391-\uFFE5]+$/;
return reg.test(str);
}
return false;
}
// 判断输入的EMAIL格式是否正确
export function isEmail(str) {
if (!isNull(str)) {
const reg = /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/g;
return reg.test(str);
}
return false;
}
// 判断输入的邮编(只能为六位)是否正确
export function isZIP(str) {
if (!isNull(str)) {
const reg = /^\d{6}$/;
return reg.test(str);
}
}
// 判断字符串的长度是否满足条件
export function isLengthValidate(str, len) {
if (str) {
if (str.length <= len) {
return true;
} else {
return false;
}
} else {
return true;
}
}
// 判断输入的字符是否为:a-z,A-Z,0-9,_,汉字
export function isProgramName(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z0-9_\u4e00-\u9fa5]+$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为:a-z,A-Z,0-9,_,汉字
export function isProgramCode(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z0-9_\u4e00-\u9fa5]+$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否以http://或者https://开头,且必须是个网址
export function isProgramWeb(str) {
if (!isNull(str)) {
let reg = /^((https|http)?:\/\/)[^\s]+/;
return reg.test(str);
}
return false;
}
export function isValueTypeMatched(type, value) {
switch (type) {
case 'Integer':
if (!/^\-?\d+$/.test(value)) {
return false;
}
break;
case 'Double':
if (!/^\-?\d+\.\d+$/.test(value)) {
return false;
}
break;
case 'Long':
if (!/^\-?\d+$/.test(value)) {
return false;
}
break;
case 'Boolean':
if (value !== 'true' && value !== 'false') {
return false;
}
break;
default:
return true;
}
return true;
}
export function isProperties(str) {
if (!isNull(str)) {
let reg = /^[a-zA-Z\u4e00-\u9fa5][a-zA-Z_0-9\u4e00-\u9fa5]*\s*=\s*[a-zA-Z_0-9\u4e00-\u9fa5]+/;
return reg.test(str);
}
return false;
}
// 拒绝码以大写字母开头,包含数字、大写字母、下划线,且为四段式
export function isUppercase(str) {
const reg = /^[A-Z]([A-Z0-9]*_){1}([A-Z0-9]+_){2}[A-Z0-9]+$/;
return reg.test(str);
}
//判断用户名
export function isUserName(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z\d_]{4,20}$/;
return reg.test(str);
}
return false;
}
//判断密码
export function isPassword(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z\d]{6,14}$/;
return reg.test(str);
}
return false;
}
//判断手机号
export function isPhone(str) {
if (!isNull(str)) {
const reg = /^1[3456789]\d{9}$/;
return reg.test(str);
}
return false;
}
// 判断税号
export function isTax(str) {
if (!isNull(str)) {
const reg = /^[A-Z0-9]{15}$|^[A-Z0-9]{17}$|^[A-Z0-9]{18}$|^[A-Z0-9]{20}$/;
return reg.test(str);
}
return false;
}
// 判断银行号
export function isBankNumber(str) {
if (!isNull(str)) {
const reg = /^[0-9]{16}$|^[0-9]{17}$|^[0-9]{19}$/;
return reg.test(str);
}
return false;
}
// 判断中文地址不能少于5个汉字,且必须有一位数字
export function isChnAddress(str) {
const isNum = /[0-9]\d*/;
const isChinese_var = /[\u4e00-\u9fa5]/g;
if (!isNull(str)) {
return isNum.test(str) && str.match(isChinese_var).length >= 5;
}
return false;
}
const ua = window.navigator.userAgent.toLowerCase();
// 判断微信环境
export const isWechat = ua.match(/MicroMessenger/i) == "micromessenger";
export const isWechat = ua.match(/MicroMessenger/i) == 'micromessenger';
// 判断小程序
export const isWxMp = ua.match(/miniProgram/i) == 'miniprogram';
// 判断羊小咩(信用钱包)环境
export const isApp = ua.match(/xyqb/i) == "xyqb";
// 判断真享生活
export const isVcc = ua.match(/VCC/i) == "vcc";
export const isApp = ua.match(/xyqb/i) == 'xyqb';
// 判断IOS环境
export const isIOS = /iphone|ipad|ipod/.test(ua);
......@@ -301,14 +15,4 @@ export const isIOS = /iphone|ipad|ipod/.test(ua);
export const isAndroid = /android/.test(ua);
// 判断
export const appVersion = ua.match(/xyqb\/([\d|.]+)/) ? ua.match(/xyqb\/([\d|.]+)/)[1] : "7.7.00";
// 判断羊小咩环境
export const isXyqb = ua.match(/xyqb/i) == "xyqb";
export const isQQ = ua.match(/QQ/i) == 'qq';
export const isWeiBo = ua.match(/Weibo/i) == 'weibo';
export const isDingTalk = ua.match(/DingTalk/i) == 'dingtalk';
export const appVersion = ua.match(/xyqb\/([\d|.]+)/) ? ua.match(/xyqb\/([\d|.]+)/)[1] : '7.7.00';
......@@ -20,6 +20,7 @@
</div>
</template>
<script>
// TODO 协议需要对接需求http://confluence.quantgroup.cn/pages/viewpage.action?pageId=52461913
export default {
name: 'Contract',
props: {
......
......@@ -4,7 +4,7 @@ export const goUrlExtends = {
goHome() {
// 商城地址
setTimeout(() => {
this.$router.replace({ name: 'home' });
window.location.href = document.referrer;
}, 500);
},
goOrderList() {
......
......@@ -261,7 +261,7 @@ export default {
async queryPayInfo() {
const [data, error] = await queryPayInfo({
orderNo: this.orderNo,
isUsedMergePayMethod: false
isUsedMergePayMethod: true
});
if (error && codeArr.indexOf(error?.response?.businessCode) < 0) {
this.payResult('Fail');
......
<template>
<div>
<div v-if="isSuccess" class="card">
<div class="info">
<cr-image
width="100px"
height="100px"
class="info__image"
src="https://img.lkbang.net/xcx/pay-success.png"
/>
<div class="info__desc">
<p class="info__text">订单支付成功!</p>
<p v-if="money" class="info__text info__money">实付¥{{ money }}</p>
<p v-if="freeAmount > 0" class="info__text info__free">已优惠¥{{ freeAmount }}</p>
</div>
</div>
<div :class="['actions', 'no-order']">
<cr-button shape="circle" type="primary" @click="goHome">返回</cr-button>
</div>
</div>
<div v-else class="card">
<div class="info">
<cr-image
width="100px"
height="100px"
class="info__image"
src="https://img.lkbang.net/xcx/pay-fail.png"
/>
<p class="info__text">订单支付失败!</p>
</div>
<p class="tips">
{{ reason }}
</p>
<cr-button type="primary" shape="circle" class="info_button" @click="goPay"
>重新支付</cr-button
>
</div>
<RecoGoods v-if="!getReturnUrl()" />
</div>
</template>
<script>
import RecoGoods from '@/components/RecoGoods.vue';
import cookies from '@/service/cookieStorage.service';
import { isApp } from '@/service/validation.service';
import { goUrlExtends } from './extends';
import { payTypeMap } from './STATIC_DATA';
export default {
components: { RecoGoods },
extends: goUrlExtends,
data() {
return {
money: '00.00',
orderNo: null,
isSuccess: false,
freeAmount: 0,
payStatus: '',
returnUrl: ''
};
},
created() {
this.getQuery();
const { orderNo, reason, payType } = this.$route.query;
const { success } = this.$route.meta;
const amount = cookies.get('amount') || {};
this.money = amount.finalAmt;
this.orderNo = orderNo;
this.reason = reason || '';
this.isSuccess = success || false;
this.freeAmount = amount.freeAmount;
this.payStatus = success ? '订单支付成功' : '订单支付失败';
this.$track.registeredEvents('h5_RechargeResultPageExposure', {
pay_status: this.payStatus
});
this.isSuccess &&
isApp &&
this.util.run({
event: 'reyunAnalytics',
data: {
method: 'PaySuccess', //string submitOrder OR PaySuccess
orderId: orderNo, //string 订单号
amount: amount.finalAmt, //float 金额
payType: payTypeMap[payType] //string 支付类型
}
});
},
methods: {
getQuery() {
this.returnUrl = cookies.get('returnUrl') || '';
},
goPay() {
this.$track.registeredEvents('h5_RechargeResultPageClick', {
pay_status: this.payStatus,
buttons_name: '重新支付'
});
this.$router.replace({ name: 'pay', query: { orderNo: this.orderNo } });
}
}
};
</script>
<style lang="less" scoped>
.card {
margin: @padding-sm;
background-color: @white;
border-radius: @border-radius-sm;
padding: 28px @padding-sm @padding-sm @padding-sm;
.info {
display: flex;
justify-content: center;
align-items: center;
&__image {
width: 100px;
height: 100px;
}
&__text {
.text-16;
margin-left: @padding-md;
}
&__desc {
display: flex;
flex-direction: column;
}
&__money {
margin-top: @padding-xs;
}
&__free {
.text-13;
margin-top: @padding-xs;
color: @font-color-light;
}
}
.tips {
.text-12;
text-align: center;
margin-top: @padding-lg;
color: @font-color-light;
}
.actions {
display: flex;
flex-direction: row;
margin-top: @padding-lg;
justify-content: space-between;
&.no-order {
justify-content: center;
}
&__back {
color: @cherry-color-error;
border: 1px solid @cherry-color-error;
}
&__order {
@primary-bg();
margin-left: @padding-sm;
}
button {
// flex: 1;
.text-17;
width: 161px;
}
}
.info_button {
width: 100%;
}
}
</style>
<template>
<div class="card">
<div class="info">
<cr-image
width="63px"
height="63px"
class="info__image"
src="../../assets/images/paying.png"
/>
<div v-if="init" class="info__desc">
<p class="info__text">
<span v-if="time">{{ time }}s)</span>支付中...
</p>
</div>
</div>
<p class="tips">
努力返回支付结果中,请留心查看!
</p>
<div :class="['actions', 'no-order']">
<cr-button shape="circle" type="primary" @click="goHome">返回</cr-button>
</div>
</div>
</template>
<script>
import { queryPayStatus } from '@/api/pay.api';
import cookies from '@/service/cookieStorage.service';
import { goUrlExtends } from './extends';
export default {
components: {},
extends: goUrlExtends,
data() {
return {
orderNo: null,
timer: null,
time: 10,
init: false,
returnUrl: ''
};
},
created() {
this.orderNo = this.$route.query.orderNo || cookies.get('orderNo')?.orderNo;
},
mounted() {
this.getQuery();
this.$track.registeredEvents('h5_RechargeResultPageExposure', {
pay_status: '正在支付'
});
this.$dialog({
message: '请确认订单已完成支付',
confirmButtonText: '已完成支付',
cancelButtonText: '重新支付',
confirmButtonColor: '#EC1500',
onCancel: () => {
this.$track.registeredEvents('h5_RechargeResultPageClick', {
pay_status: '正在支付',
buttons_name: '重新支付'
});
this.goPay();
},
onConfirm: () => {
this.init = true;
this.loop();
}
});
},
beforeDestroy() {
clearInterval(this.timer);
},
methods: {
getQuery() {
this.returnUrl = cookies.get('returnUrl') || '';
},
loop() {
this.query();
this.timer = setInterval(() => {
this.time -= 1;
if (this.time % 2 === 0) {
this.query();
}
if (this.time < 1) {
clearInterval(this.timer);
}
}, 2000);
},
goSuccess() {
// 支付成功
this.$router.push({ name: 'paySuccess' });
},
goPay() {
this.$router.replace({ name: 'pay', query: { orderNo: this.orderNo } });
},
async query() {
const [data, error] = await queryPayStatus({ orderNo: this.orderNo });
if (error) {
this.$router.push({
name: 'payFail',
query: { reason: error.message, orderNo: this.orderNo }
});
return;
}
if (+data?.payStatus === 3) {
this.goSuccess();
}
}
}
};
</script>
<style lang="less" scoped>
.card {
margin: @padding-sm;
background-color: @white;
border-radius: @border-radius-sm;
padding: 28px @padding-sm @padding-sm @padding-sm;
.info {
display: flex;
justify-content: center;
align-items: center;
&__image {
width: 100px;
height: 100px;
}
&__text {
.text-16;
margin-left: @padding-md;
}
&__desc {
display: flex;
flex-direction: column;
}
&__money {
margin-top: @padding-xs;
}
&__free {
.text-13;
margin-top: @padding-xs;
color: @font-color-light;
}
}
.tips {
.text-12;
text-align: center;
margin-top: @padding-lg;
color: @font-color-light;
}
.actions {
display: flex;
flex-direction: row;
margin-top: @padding-lg;
justify-content: space-between;
&.no-order {
justify-content: center;
}
&__back {
color: @cherry-color-error;
border: 1px solid @cherry-color-error;
}
&__order {
@primary-bg();
margin-left: @padding-sm;
}
button {
.text-17;
width: 161px;
}
}
.info_button {
width: 100%;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment