d4acdcee by simon

基础项目

0 parents
{
"ignoreHttpDomainCheck": false
}
\ No newline at end of file
page {
/* background: #f7f7f7; */
}
const fetchApi = require('./http/fetch-api.js');
const api = require('./http/api');
const config = require('./config');
const router = require('./router/index');
const storage = require('./utils/stroage');
const util = require('./utils/util');
const func = require('./utils/func');
// console.log('api.login:', api.login)
// console.log('fetchApi:',fetchApi)
// console.log('fetchApi.get:',fetchApi.fetch)
App({
get: fetchApi.fetchMethod,
post: (params) => {
params.method = 'post';
return fetchApi.fetchMethod(params);
},
delete: (params) => {
params.method = 'DELETE';
return fetchApi.fetchMethod(params);
},
uploadFile: fetchApi.uploadFile, // 单文件上传
uploadFileMultiple: fetchApi.uploadFileMultiple, // 多文件上传,
api: api,
config: config,
router: router,
storage: storage,
util: util,
func: func,
tapData: util.getBindtapData,
globalData: {
userInfo: null,
profile: null,
wxcode: storage.getItem("wxcode"),
ui: {
colorUI: "#409EFF",
colorDanger: "#EE0A24"
},
invitationCode: "",
statusBarHeight: 0,
},
onLaunch(options) {
// 第一次打开
// options.query == {number:1}
console.info('App onLaunch');
},
onShow(options) {
// 从后台被 scheme 重新打开
// options.query == {number:1}
},
/**
* 封装toast
* @returns
*/
toast(title, opt = {
icon: 'none'
}) {
let data = opt;
data.title = title
my.showToast({
content: title
})
return;
},
});
\ No newline at end of file
{
"pages": [
"pages/index/index"
],
"window": {
"defaultTitle": "联通流量王"
},
"behavior": {
"requestReferrerStrategy": "page",
"requestReferrerStyle": "full",
"requestDefaultEnableCookie": true,
"connectSocketDefaultMultiple": true
}
}
<view>
New Component
</view>
\ No newline at end of file
Component({
mixins: [],
data: {},
props: {},
didMount() {},
didUpdate() {},
didUnmount() {},
methods: {},
});
{
"component": true,
"styleIsolation": "apply-shared"
}
.form-comp {
background: url('/images/form/form-bg-1.png') center no-repeat;
background-size: 100% 100%;
width: 723rpx;
height: 691rpx;
padding-top: 60rpx;
box-sizing: border-box;
text-align: center;
}
.form-comp-2 {
background: url('/images/form/form-bg-2.png') center no-repeat;
background-size: 100% 100%;
width: 723rpx;
height: 1021rpx;
}
.form-comp .number {
font-size: 52rpx;
font-weight: bold;
letter-spacing: 1.29rpx;
color: #131313;
}
.form-comp .tit {
font-size: 40rpx;
font-weight: bold;
text-align: center;
color: #ff027c;
margin: 14rpx auto 0;
}
.form-comp .tips {
font-size: 23rpx;
font-weight: 600;
color: #727272;
margin: 14rpx auto 0;
}
.form {
margin: 32rpx auto 0;
}
.form-item {
width: 647rpx;
height: 86rpx;
border-radius: 16rpx;
border: solid 1rpx #787878;
background-color: #fcf8ff;
margin: 0 auto 24rpx;
padding: 0 32rpx;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
text-align: left;
}
.form-item .label {
display: flex;
width: 150rpx;
font-weight: bold;
font-size: 32rpx;
}
.form-item .label .requrie {
color: #f00;
font-weight: 500;
}
.form-item .ipt {
background-color: transparent;
flex: 1;
font-size: 28rpx;
}
.form-comp .submit-btn {
background: url('/images/form/submit-btn.png') center no-repeat;
background-size: 100% 100%;
width: 630rpx;
height: 102rpx;
margin: 40rpx auto 0;
}
.form-comp .submit-tips {
margin: 20rpx auto 0;
font-size: 23rpx;
font-weight: 600;
text-align: center;
color: #727272;
}
.form-comp .func {}
.form-comp .func .icon {
background: url('/images/form/icon-question.png') center no-repeat;
background-size: 100% 100%;
width: 30rpx;
height: 30rpx;
}
.untouch {
pointer-events: none;
}
.ani-heart {
animation: ani-heart-key 1.2s linear infinite;
}
@keyframes ani-heart-key {
0% {
transform: scale(1);
}
50% {
transform: scale(1.04);
}
100% {
transform: scale(1);
}
}
\ No newline at end of file
<view class="form-comp {{!fold ? 'form-comp-2' : ''}}">
<view class="number">
{{item.mobile}}
</view>
<view class="tit">
{{item && item.featureName || '发财旺运'}}
</view>
<view class="tips">
请如实填写以下信息,以便我们及时为您送达
</view>
<view class="form">
<view class="form-item">
<view class="label">
姓 名
<view class="requrie">
*
</view>
</view>
<input
onBlur="onBlur"
onInput="inputEdit"
data-name="queryForm.name"
value="{{queryForm.name}}"
class="ipt"
placeholder="请输入姓名 (已加密)"
/>
</view>
<view class="form-item">
<view class="label">
联系电话
<view class="requrie">
*
</view>
</view>
<input
onBlur="onBlur"
onInput="inputEdit"
data-name="queryForm.mobilePhone"
value="{{queryForm.mobilePhone}}"
class="ipt"
placeholder="请输入联系电话,并保持畅通"
type="number"
/>
</view>
<block a:if="{{ !fold}}">
<view class="form-item">
<view class="label">
身份证
<view class="requrie">
*
</view>
</view>
<input
onInput="inputEdit"
data-name="queryForm.identNo"
value="{{queryForm.identNo}}"
class="ipt"
placeholder="请输入身份证号 (已加密)"
type="idcard"
/>
</view>
<view class="form-item" onTap="onPickerArea">
<view class="label">
所在地区
<view class="requrie">
*
</view>
</view>
<input value="{{areaStr}}" class="ipt untouch" placeholder="请选择省/市/区" />
</view>
<view class="form-item">
<input
onInput="inputEdit"
data-name="queryForm.address"
value="{{queryForm.address}}"
class="ipt"
placeholder="请输入详细地址 (*街道*小区*门牌号)"
/>
<view class="func">
<view onTap="onAddressTips" class="icon icon-question">
</view>
</view>
</view>
</block>
</view>
<view onTap="onSubmit" class="submit-btn ani-heart"></view>
<view class="submit-tips">
请保持联系号码畅通,我们可能随时与您联系
</view>
</view>
\ No newline at end of file
let app = getApp();
// 联通专属
import area from '/const/area-lt';
Component({
mixins: [],
data: {
queryForm: {
selectMobilePhone: "", // 从父组件中传入
name: "", // 姓名
mobilePhone: "", // 用户手机号
identNo: "", // 证件号
province: "", // 省
provinceCode: "", // 省编号
city: "", // 市
cityCode: "", // 市编号
district: "", // 区
districtCode: "", // 区编号
address: "", // 收货地址
},
areaStr: "",
fold: true
},
props: {
item: {
type: Object,
value: null,
},
// 发送自定义事件 onChange 貌似为固定值
onChange(data) {},
},
didMount() {
// console.log("area:", area);
// let res = app.func.addressToTree(area);
// console.log("res:", res);
},
didUpdate() {},
didUnmount() {},
methods: {
onBlur() {
if (this.data.queryForm.name && this.data.queryForm.mobilePhone) {
this.setData({
fold: false,
})
}
},
// 封装 my.multiLevelSelect
// - 对于传入的数据,只向底层接口传递 name 和 subList
// - 对于选中的结果,替换成对应的完整数据条目再回调
multiLevelSelect({
title,
list,
success,
fail,
complete
}) {
const clean = ({
name,
subList
}) => {
return {
name,
subList: subList && subList.map(clean)
};
};
const lookup = (array, index, pool) => {
if (array && index < array.length) {
array[index] = pool.filter(x => x.name === array[index].name)[0];
lookup(array, index + 1, array[index].subList);
delete array[index].subList; // 方便回调中的 my.alert 演示。真实代码请删除此行,避免副作用
}
};
const wrap = func =>
func &&
(res => {
res.success && lookup(res.result, 0, list);
func(res);
});
return my.multiLevelSelect({
title,
list: list.map(clean),
success: wrap(success),
fail,
complete: wrap(complete),
});
},
// 选择地址
onPickerArea() {
let areas = app.func.addressToTree(area);
console.log("areas:", areas);
let updateList = []
areas.forEach(element => {
if (element.id == "440000") {
updateList.push(element);
}
});
this.multiLevelSelect({
title: '请选择所在地区',
list: updateList,
success: res => {
let region = res.result;
console.log(region)
this.setData({
'queryForm.province': region[0].name,
'queryForm.city': region[1].name,
'queryForm.district': region[2].name,
'queryForm.provinceCode': region[0].id,
'queryForm.cityCode': region[1].id,
'queryForm.districtCode': region[2].id,
'areaStr': region[0].name + region[1].name + region[2].name
})
},
fail: error => {
// console.error('multiLevelSelect fail: ', JSON.stringify(error));
},
});
},
// 显示地址tips
onAddressTips() {
my.showToast({
content: "请输入详细准确的地址,字数不少于4字(例如:**街身份证* 道…),且不能包含特殊符号(例如:? !/0等,可以输入小写-号)"
})
},
/**
* input绑定
* 多输入文本绑定
* 在input/texarea中设置 data-name="属性值即可"
*/
inputEdit(e) {
let dataset = e.currentTarget.dataset;
let value = e.detail.value;
let name = dataset.name;
this.setData({
[name]: value
});
},
/**
* 检查表单
*/
checkSubmit() {
return new Promise((resolve, reject) => {
let {
name,
mobilePhone,
identNo,
district,
address
} = this.data.queryForm;
console.log("this.data.queryForm:", this.data.queryForm);
if (!name) {
app.toast("请输入姓名")
return;
}
if (!app.util.checkMobile(mobilePhone)) {
app.toast("请输入正确的手机号码")
return;
}
if (!app.util.checkIdentNo(identNo)) {
app.toast("请输入正确的身份证号码")
return;
}
if (!district) {
app.toast("请选择所在地区")
return;
}
if (!address) {
app.toast("请输入详细地址")
return;
}
resolve(this.data.queryForm)
});
},
/**
* 提交表单
*/
onSubmit() {
this.checkSubmit().then((params) => {
params.selectMobilePhone = this.props.item.mobile;
console.log("params:", params)
my.showLoading({
content: '稍等片刻,订单提交中',
mask: true
});
app.post({
url: app.api.createOrder,
data: params,
}).then((result) => {
// 发送自定义事件 onChange 貌似为固定值
this.props.onChange({
name: "_evt_submit_complete"
})
my.hideLoading();
}).catch((err) => {
my.hideLoading();
});
});
},
},
});
\ No newline at end of file
{
"component": true,
"styleIsolation": "apply-shared"
}
.succ-comp {
background: url('/images/form/form-bg-succ.png') center no-repeat;
background-size: 100% 100%;
width: 723rpx;
height: 620rpx;
padding-top: 104rpx;
box-sizing: border-box;
text-align: center;
}
.succ-comp .icon-succ {
background: url('/images/form/icon-succ.png') center no-repeat;
background-size: 100% 100%;
width: 231rpx;
height: 231rpx;
margin: 0 auto 0;
}
.succ-comp .tit {
font-size: 53rpx;
font-weight: 800;
text-align: center;
color: #ff027c;
margin: 36rpx auto 0;
}
.succ-comp .tips {
font-size: 23rpx;
font-weight: 600;
text-align: center;
color: #727272;
margin: 16rpx auto 0;
}
\ No newline at end of file
<view class="succ-comp">
<view class="icon-succ">
</view>
<view class="tit">
提交成功
</view>
<view class="tips">
您的订单正在审核发货
</view>
</view>
\ No newline at end of file
Component({
mixins: [],
data: {},
props: {},
didMount() {},
didUpdate() {},
didUnmount() {},
methods: {},
});
{
"component": true,
"styleIsolation": "apply-shared"
}
let ENV_CONFIG = require('./env/index');
const APPID = 'wx3e9333eb830173fc'
/** ====每次发布版本记得修改此环境配置==== */
const ENV = 'dev'; // dev prod
const NET_CONFIG = ENV_CONFIG[ENV];
module.exports = {
APPID,
ENV,
NET_CONFIG,
}
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
/**
* BASE_API:api统一请求域名。(当前项目业务)
* API_PREFIX:请求业务词头前缀,项目划分
* COMMON_API:平台通用请求域名。(单/多文件上传,省市区联查,场景二维码/小程序码等)
* IMG:oss图片地址前缀,用于访问
* OSS_PATH:上传文件路径,用于上传 例如:'/weapp/xxx/'
* MODULE_CODE:后端给出
* RSA_PUBLIC_KEY:公钥
* AES_IV:偏移量
* IS_POST_ENC:post方法是否开启自动开启加密
*/
module.exports = {
dev: {
BASE_API: 'https://prettyapi.kdao.xin',
// BASE_API: 'https://prettyapi.letterbelieve.com',
// BASE_API: 'https://bizapi.kdao.xin',
API_PREFIX: '/zwPrettyNumApi',
COMMON_API: 'https://bizapi.kdao.xin',
IMG: 'https://cdn.kdao.xin/cdn/images',
OSS_PATH: '',
MODULE_CODE: 'd00b70ed26ed4f1291eb870662270e77',
RSA_PUBLIC_KEY: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4U9ZijHk0bsHh5YvsQu7E9l/S9sqRLlbLhxmcgoTCcH5nO3S4//VZ/Ns2sxRwSWrsCxGr+tIPXBofJErGf3teqxAspca/1pjaWGB3fQ44Q0+OPwv1l7vWgn81tdMIMizjHu31vrUTlcL9UDHfoLB9vht3mtrYsc7xTi8MnHlkWx+VZv8uS06sLRJqCBiIzZcdB30szCjNtcSm1A2sV4EnBzqCQnR4/0Bd33UVRVdJLFcez5OfKqTi3HS65adf6U8LjOdw5rE+NNPNJmggVGlWVRyw9MSkjbYS9W4lpGul22rIKODkLFnqEtW8VcG/1dFCka1ykMADOII+YXr6GDHQIDAQAB',
AES_IV: 'ce102d54b198462c',
IS_POST_ENC: true,
},
prod: {
BASE_API: 'https://prettyapi.kdao.xin',
// BASE_API: 'https://prettyapi.letterbelieve.com',
// BASE_API: 'https://bizapi.kdao.xin',
API_PREFIX: '/zwPrettyNumApi',
COMMON_API: 'https://bizapi.kdao.xin',
IMG: 'https://cdn.kdao.xin/cdn/images',
OSS_PATH: '',
MODULE_CODE: 'd00b70ed26ed4f1291eb870662270e77',
RSA_PUBLIC_KEY: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4U9ZijHk0bsHh5YvsQu7E9l/S9sqRLlbLhxmcgoTCcH5nO3S4//VZ/Ns2sxRwSWrsCxGr+tIPXBofJErGf3teqxAspca/1pjaWGB3fQ44Q0+OPwv1l7vWgn81tdMIMizjHu31vrUTlcL9UDHfoLB9vht3mtrYsc7xTi8MnHlkWx+VZv8uS06sLRJqCBiIzZcdB30szCjNtcSm1A2sV4EnBzqCQnR4/0Bd33UVRVdJLFcez5OfKqTi3HS65adf6U8LjOdw5rE+NNPNJmggVGlWVRyw9MSkjbYS9W4lpGul22rIKODkLFnqEtW8VcG/1dFCka1ykMADOII+YXr6GDHQIDAQAB',
AES_IV: 'ce102d54b198462c',
IS_POST_ENC: true,
}
}
\ No newline at end of file
module.exports = {
config: "/front/mallApi/configs", //会员配置
login: '/front/userApi/login', // 登录
wxLogin: "/front/userApi/code2session", // wx小程序登录
profile: "/front/userApi/profile", // profile
profile: "/front/userApi/profile", // profile
// 1、这个接口一次查询会返回100个号码。
// 2、后台限制了这个接口从联通获取号码的次数(5)次。多次调用后,如果超过次数,会默认以query = '' 返回结果。相同查询条件的结果会缓存起来,二次查询的结果是相同的。
// 3、建议前台缓存返回的结果,翻页、AABB+组合需要前端自行做正则匹配。匹配结果不足时,可以从缓存中随机抽取号码补齐。
// 4、缓存返回结果的时候做好去重操作
selectNum: "/front/selectNum", // 选号
createOrder: "/front/createOrder", // 下单
/**
* 通用接口
* 请求时 "mode"传"custom"
*/
areaQuery: 'https://api.k.wxpai.cn/bizproxy/kdapi/area', // post 区域查询
// 文件上传
uploadFile: '/common/upload', // 上传图片通用接口(需要后端协同开通用接口,目前没有通用接口)
// uploadFile: "/admin/upload", // 上传图片
wxQrcodeCreate: '/open/wx/qrcode/create', //生成小程序码(需要后端协同开通用接口,目前没有通用接口)
}
\ No newline at end of file
let config = require('./../config');
let Storage = require('./../utils/stroage');
let util = require('./../utils/util');
let Router = require('./../router/index');
let Encrypt = require('./../utils/enc/enc');
let api = require('./api');
const errMsg = '服务异常,请稍后重试';
/**
* 重新获取 sessionId
* 1.重新获取wxcode,
* 2.调用login方法,传wxcode,给后端重新换取js_session
* @returns
*/
function login() {
return new Promise((resolve, reject) => {
// my.login({
// success: (res) => {
let res = {
code: util.uuid()
}
let baseUrl = config.NET_CONFIG.BASE_API + config.NET_CONFIG.API_PREFIX;
let header = {
'-kd-platform-env': config.ENV,
'-kd-platform-module': config.NET_CONFIG.MODULE_CODE
}
let app = getApp();
let globalData = app && app.globalData || null
let data = {
code: res.code,
miniproChannel: globalData.channelCode || "",
channelCode: globalData.channelCode || "",
parentMemberCode: globalData.parentMemberCode || "",
platform: "minipro",
};
data = Encrypt.makeEncrypt(data);
my.request({
// url: baseUrl + api.wxLogin,
url: baseUrl + api.login,
sid: false,
data: data,
method: 'POST',
header: header,
success: (res) => {
let {
code,
content
} = res.data;
if (code == 200 && content.sessionId) {
Storage.setItem('sessionId', content.sessionId); // 保存新的sessionId
resolve();
} else {
reject();
}
}
})
// }
// });
});
}
/**
* 检查并埋下sessionId
* @param {*} sid 接口是否需要sessionId
* @returns
*/
function checkSessionId(sid) {
return new Promise((resolve, reject) => {
let sessionId = Storage.getItem('sessionId');
if (sid) {
// 拥有sessionId
if (sessionId) {
resolve();
} else {
// 重新获取 sessionId
login().then((result) => {
resolve();
}).catch((err) => {
reject();
});
}
} else {
// 不需要 sessionId 忽略
resolve();
}
});
}
function fetchMethod(val) {
let params = Object.assign({
loading: false,
toast: true,
sid: true,
mode: "",
url: "",
data: null,
method: "GET",
enc: false
}, val);
let promise = new Promise((resolve, reject) => {
checkSessionId(params.sid).then(() => {
doRequest(params).then((result) => {
resolve(result);
}).catch((err) => {
// 404 或 403 错误码的时候需要重新拉一次
if (err.code == 404 || err.code == 403) {
login().then((loginRes) => {
doRequest(params).then((result2) => {
resolve(result2);
});
}).catch((err) => {});
} else {
reject(err)
}
});
});
});
return promise;
}
/**
* 做实际请求
* @param {*} params
* @returns
*/
function doRequest(params) {
return new Promise((resolve, reject) => {
let {
loading,
toast,
mode,
url,
data,
method,
responseType,
enc
} = params;
let baseUrl = config.NET_CONFIG.BASE_API + config.NET_CONFIG.API_PREFIX;
// 使用通用接口前缀
if (mode == "common") baseUrl = config.NET_CONFIG.COMMON_API;
// 自定义前缀,即不使用前缀
if (mode == "custom") baseUrl = "";
if (loading && mode != 'log') my.showLoading({
content: '加载中',
mask: true
});
// 判断是否开启post方法默认加密
if (config.NET_CONFIG.IS_POST_ENC && (method == "post" || method == "POST")) {
enc = true;
}
if (enc) data = Encrypt.makeEncrypt(data);
// 设置请求头
let header = {
'-kd-platform-env': config.ENV,
'-kd-platform-module': config.NET_CONFIG.MODULE_CODE,
'sessionId': Storage.getItem("sessionId")
}
my.request({
url: baseUrl + url, //请求地址
data: data, //自定义参数
method: method || 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
header: header,
responseType: responseType,
success: (result) => {
// 日志上传不需要处理结果
if (mode == 'log') return;
let res = result.data;
if (responseType == "arraybuffer") {
if (loading) my.hideLoading();
resolve(res)
} else if (res.code === 200) {
if (loading) my.hideLoading();
resolve(res.content);
} else {
my.hideLoading();
// 404 不需要toast
if (toast && res.code != 404) {
my.showToast({
content: res.errMsg || errMsg,
icon: 'none'
})
}
reject(res);
}
},
fail: (err) => {
my.hideLoading();
}
});
});
}
// -------- 业务接口 Start --------
/**
* 上传文件到恪道
* @param {*} filePath 图片地址
* @param {*} subPath 上传目录 (此参数为空则使用 oss目录)
*/
function uploadFile(filePath, subPath) {
return new Promise((resolve, reject) => {
if (!subPath && !config.NET_CONFIG.OSS_PATH) {
throw new Error('请配置上传目录 !');
reject();
return;
}
my.uploadFile({
url: config.NET_CONFIG.BASE_API + config.NET_CONFIG.API_PREFIX + api.uploadFile,
filePath: filePath,
name: 'file',
header: {
'content-type': 'multipart/form-data',
'-kd-platform-env': config.ENV,
'-kd-platform-module': config.NET_CONFIG.MODULE_CODE,
},
formData: {
subPath: subPath || config.NET_CONFIG.OSS_PATH
},
success(res) {
let result = JSON.parse(res.data).content;
resolve(result);
},
fail() {
reject()
},
complete() {}
})
});
}
/**
* 上传多个文件到服务器
* urlList 需要上传的图片地址 (my.chooseImage 的 paths列表)
*
*/
function uploadFileMultiple(filePathList, subPath) {
return new Promise((resolve, reject) => {
if (!subPath && !config.NET_CONFIG.OSS_PATH) {
throw new Error('请配置上传目录 !');
reject();
return;
}
console.log("config.NET_CONFIG.COMMON_API + api.uploadFile:", config.NET_CONFIG.COMMON_API + api.uploadFile);
my.showLoading({
content: `加载中`
})
console.log("filePathList:", filePathList);
if (filePathList && filePathList.length > 0) {
let promiseList = [];
filePathList.forEach(element => {
let promiseItem = new Promise((resolve2, reject2) => {
uploadFile(element, subPath).then((result2) => {
resolve2(result2)
}).catch((err) => {
reject2();
});
});
promiseList.push(promiseItem);
});
console.log("promiseList:", promiseList);
Promise.all(promiseList).then(uploadFiles => {
my.hideLoading()
resolve(uploadFiles)
}, reason => {
my.hideLoading()
reject();
});
} else {
my.hideLoading()
resolve([]);
}
});
}
module.exports = {
fetchMethod,
uploadFile,
uploadFileMultiple
}
\ No newline at end of file
{
"format": 2,
"developOptions": {
"hotReload": true
}
}
\ No newline at end of file
File mode changed
<view>
this is a blank page
</view>
Page({
onLoad(query) {
// 页面加载
console.info(`Page onLoad with query: ${JSON.stringify(query)}`);
},
onReady() {
// 页面加载完成
},
onShow() {
// 页面显示
},
onHide() {
// 页面隐藏
},
onUnload() {
// 页面被关闭
},
onTitleClick() {
// 标题被点击
},
onPullDownRefresh() {
// 页面被下拉
},
onReachBottom() {
// 页面被拉到底部
},
onShareAppMessage() {
// 返回自定义分享信息
return {
title: 'My App',
desc: 'My App description',
path: 'pages/index/index',
};
},
});
{}
\ No newline at end of file
.top-space {
height: 0;
}
.page {
font-size: 0;
padding-bottom: 124rpx;
}
.main {
/* font-size: 28rpx; */
}
.ebg {
font-size: 0;
width: 750rpx;
position: relative;
z-index: 11;
}
.table {
width: 750rpx;
height: 1120rpx;
background-image: linear-gradient(to top, #ede9ff, #d6c0ff);
box-sizing: border-box;
margin: 0px auto 0;
}
.func-wrap {
background: url('/images/index/search-wrap-bg.png') center no-repeat;
background-size: 100% 100%;
width: 701rpx;
height: 311rpx;
margin: 0 auto;
box-sizing: border-box;
padding-top: 60rpx;
}
.search-wrap {
width: 608rpx;
height: 58rpx;
border-radius: 16rpx;
border: solid 1rpx #905cff;
background-color: #fcf8ff;
margin: 0 auto 0;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0rpx 0rpx 0rpx 19rpx;
}
.search-icon {
background: url('/images/index/search-icon.png') center no-repeat;
background-size: 100% 100%;
width: 32rpx;
height: 32rpx;
/* margin: 0rpx 19rpx 0rpx 12rpx; */
}
.search-input {
flex: 1;
background-color: transparent;
padding: 0 12rpx;
box-sizing: border-box;
}
.search-btn {
width: 153rpx;
height: 58rpx;
line-height: 58rpx;
border-radius: 16rpx;
background-image: linear-gradient(to top, #be8bff, #7934ff);
text-align: center;
color: #fff;
font-weight: bold;
font-size: 30rpx;
}
.tag-list {
width: 614rpx;
margin: 21rpx auto 0;
display: flex;
flex-wrap: wrap;
}
.tag-list :nth-child(4n) {
margin-right: 0rpx;
}
.tag-item {
width: 140rpx;
height: 49rpx;
line-height: 50rpx;
border-radius: 21rpx;
text-align: center;
color: #fff;
font-weight: bold;
background-image: linear-gradient(to top, #be8bff, #7934ff);
margin-right: 18rpx;
margin-bottom: 11rpx;
font-size: 28rpx;
}
.tag-item-act {
background-image: linear-gradient(to top, #ff0072, #ff00a2);
}
/* 号码 */
.number-wrap {
margin: 24rpx auto 0;
padding: 0 16rpx;
box-sizing: border-box;
position: relative;
z-index: 21;
height: 660rpx;
}
.number-list {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
/* max-height: 660rpx; */
/* height: 660rpx; */
overflow-y: hidden;
}
.number-item {
width: 341rpx;
height: 114rpx;
background: url('/images/index/number-item-bg.png') center no-repeat;
background-size: 100% 100%;
margin: 0 9rpx 18rpx;
font-size: 48rpx;
color: #fff;
font-weight: bold;
box-sizing: border-box;
text-align: center;
padding-top: 8rpx;
}
.number-item .text {
font-size: 48rpx;
color: #fff;
}
.number-item .highlight {
color: #fcff04;
}
.page-btn-wrap {
margin: 26rpx auto 0;
display: flex;
align-items: center;
justify-content: center;
}
.page-btn {
width: 184rpx;
height: 69rpx;
margin: 0 8px;
}
.btn-prev {
background: url('/images/index/page-btn-prev.png') center no-repeat;
background-size: 100% 100%;
}
.btn-next {
background: url('/images/index/page-btn-next.png') center no-repeat;
background-size: 100% 100%;
}
/* 弹窗框 */
.popup {
position: fixed;
z-index: 1001;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.popup .popup-mask {
position: fixed;
width: 100vw;
height: 100vh;
background-color: #000000;
opacity: .7;
}
.popup .dialog {
position: relative;
}
text {
color: #333;
font-size: 30rpx;
}
.highlight {
color: red;
}
.bot-btn {
background: url('/images/form/submit-btn.png') center no-repeat;
background-size: 100% 100%;
width: 630rpx;
height: 102rpx;
position: fixed;
left: 0;
right: 0;
bottom: 40rpx;
margin: auto;
z-index: 111;
}
.ani-heart {
animation: ani-heart-key 1.2s linear infinite;
}
@keyframes ani-heart-key {
0% {
transform: scale(1);
}
50% {
transform: scale(1.04);
}
100% {
transform: scale(1);
}
}
\ No newline at end of file
<view class="page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<view class="app__content main">
<view class="top-space"></view>
<image class="ebg" mode="widthFix" src="/images/index/index-bg-1.png" />
<view class="content">
<view class="table">
<view class="func-wrap">
<view class="search-wrap">
<view class="search-icon"></view>
<input
onInput="inputEdit"
onConfirm="onSearchConfirm"
data-name="queryForm.query"
value="{{queryForm.query}}"
class="search-input"
placeholder="请输入您喜欢的数字"
type="number"
/>
<view onTap="onSearch" class="search-btn">
搜 索
</view>
</view>
<view class="tag-list">
<view
a:for="{{ tagList }}"
onTap="onTagItem"
data-data="{{item}}"
data-index="{{index}}"
class="tag-item {{ tagIndex == index ? 'tag-item-act' : '' }}"
style="font-size: {{ item.fontSize || 28 }}rpx;"
>
{{item.name}}
</view>
</view>
</view>
<view class="number-wrap">
<view class="number-list">
<view
a:for="{{ numberList }}"
onTap="onNumberItem"
data-data="{{item}}"
data-index="{{index}}"
class="number-item"
>
<text a:for="{{ item.numberDisplayList }}" class="text {{item.highlight ? 'highlight' : ''}}">
{{item.number}}
</text>
</view>
</view>
</view>
<view class="page-btn-wrap">
<view onTap="onPagePrev" class="page-btn btn-prev">
</view>
<view onTap="onPageNext" class="page-btn btn-next">
</view>
</view>
</view>
</view>
<image class="ebg" mode="widthFix" src="/images/index/index-bg-2.png" />
<view a:if="{{ shortCutVisible }}" onTap="toTop" class="bot-btn ani-heart"></view>
</view>
</view>
<view hidden="{{ !formVisible }}" class="popup">
<view catchTap="onHideMask" class="popup-mask"></view>
<view class="dialog">
<form-comp item="{{curNumberItem}}" onChange="evtcomp"></form-comp>
</view>
</view>
<view a:if="{{ succVisible }}" class="popup">
<view catchTap="onHideMask" class="popup-mask"></view>
<view class="dialog">
<succ-comp></succ-comp>
</view>
</view>
\ No newline at end of file
let app = getApp();
// import {
// mobile_list
// } from '/const/index';
// import {
// areas
// } from '/const/area-new';
Page({
data: {
queryForm: {
query: "",
},
formVisible: false,
succVisible: false,
shortCutVisible: false,
tagIndex: 0,
tagList: [{
name: "推荐",
val: "",
},
{
name: "AAA+",
val: "AAA+",
},
{
name: "AABB+",
val: "AABB+",
},
{
name: "ABAB+",
val: "ABAB+",
},
{
name: "ABBA",
val: "ABBA",
},
{
name: "ABCAB",
val: "ABCAB",
},
{
name: "ABCD",
val: "ABCD",
},
{
name: "尾号6/8/9",
val: "LAST689",
fontSize: 26
},
],
page: 1,
size: 10,
totalPages: 0,
// 总号码池
numberPool: [],
// 命中池
targetNumberList: [],
// 号码列表,当前展示号码
numberList: [],
// 当前选择号码
curNumberItem: null,
},
onLoad(query) {
this.initData();
// let area = {};
// let province_list = {};
// let city_list = {};
// let county_list = {};
// areas.forEach(element => {
// province_list[element[0]] = element[1]
// city_list[element[2]] = element[3]
// county_list[element[4]] = element[5]
// });
// area.province_list = province_list;
// area.city_list = city_list;
// area.county_list = county_list;
// console.log(area);
},
async initData() {
let numberPool = await this.getSelectNumberList();
app.func.sortByLength(numberPool)
this.data.targetNumberList = numberPool;
this.data.page = 1;
this.refreshPage();
// let beautyResAAA = app.func.checkBeautyNumberAAA('15014443959');
// console.log("beautyResAAA:", beautyResAAA);
// let beautyResAABB = app.func.checkBeautyNumberAABB('15011337986');
// console.log("beautyResAABB:", beautyResAABB);
// let beautyResABAB = app.func.checkBeautyNumberABAB('15056563959');
// console.log("beautyResABAB:", beautyResABAB);
// let beautyResABBA = app.func.checkBeautyNumberABBA('15056653959');
// console.log("beautyResABBA:", beautyResABBA);
// let beautyResABCAB = app.func.checkBeautyNumberABCAB('15056756959');
// console.log("beautyResABCAB:", beautyResABCAB);
// let beautyResABCD = app.func.checkBeautyNumberABCD('15054323959');
// console.log("beautyResABCD:", beautyResABCD);
// let beautyResLast = app.func.checkBeautyNumberLast('15054323959');
// console.log("beautyResLast:", beautyResLast);
},
// 页面滚动
onPageScroll(e) {
let shortCutVisible = e.scrollTop > 700;
this.setData({
shortCutVisible
});
},
toTop() {
console.log("toTop");
my.pageScrollTo({
scrollTop: 0,
duration: 300
})
},
async onSearch() {
let numberPool = await this.getSelectNumberList();
this.setData({
tagIndex: 0
})
// numberPool = app.util.shuffleArray(numberPool);
this.data.targetNumberList = numberPool;
this.data.page = 1;
this.refreshPage();
},
onSearchConfirm() {
this.onSearch();
},
/**
* 获取
*/
async getSelectNumberList() {
let res = await app.get({
url: app.api.selectNum,
data: this.data.queryForm,
loading: true,
});
// console.log(res);
let funcList = [
app.func.checkBeautyNumberAAA,
app.func.checkBeautyNumberAABB,
app.func.checkBeautyNumberABAB,
app.func.checkBeautyNumberABBA,
app.func.checkBeautyNumberABCAB,
app.func.checkBeautyNumberABCD,
app.func.checkBeautyNumberLast,
]
res.forEach(element => {
element.beautyList = []
element.beautyObj = {}
funcList.forEach(funElement => {
let beautyRes = funElement(element.mobile);
if (beautyRes.beautyNum) {
element.beautyList.push(beautyRes);
element.beautyObj[beautyRes.type] = beautyRes;
}
});
});
let numberPool = res.concat(this.data.numberPool);
numberPool = app.util.uniqueArray(numberPool);
this.data.numberPool = numberPool;
return numberPool;
},
// 点击标签
onTagItem(evt) {
let item = app.tapData(evt);
let index = app.tapData(evt, "index");
this.setData({
queryForm: {
query: "",
},
tagIndex: index,
})
let numberPool = this.data.numberPool;
numberPool = app.util.shuffleArray(numberPool);
if (item.val) {
let targetNumberList = []
numberPool.forEach(element => {
if (element.beautyObj[item.val]) {
targetNumberList.push(element);
}
});
targetNumberList = targetNumberList.concat(numberPool);
targetNumberList = app.util.uniqueArray(targetNumberList);
this.data.targetNumberList = targetNumberList;
} else {
// app.func.sortByLength(numberPool)
this.data.targetNumberList = numberPool;
}
this.data.page = 1;
this.refreshPage();
},
/**
* 点击号码
*/
onNumberItem(evt) {
let item = app.tapData(evt);
item.featureName = app.func.getFeatureName(item.mobile)
this.setData({
curNumberItem: item,
formVisible: true,
})
},
// 上一页
onPagePrev() {
this.data.page--;
if (this.data.page < 1) {
this.data.page = this.data.totalPages;
// return;
};
this.refreshPage();
},
// 下一页
onPageNext() {
this.data.page++;
if (this.data.page > this.data.totalPages) {
this.data.page = 1;
// return;
}
this.refreshPage();
},
refreshPage() {
let listObj = app.util.paginateArray(this.data.targetNumberList, this.data.page, this.data.pageSize);
let curTag = this.data.tagList[this.data.tagIndex];
let curTagVal = curTag.val;
let list = listObj.list;
let query = this.data.queryForm.query;
/**
* 高亮数字
*
* 1、如果query中有值,按query的值
* 2、如果标签有值,按标签
* 3、如果都没有,随机显示靓号
*/
list.forEach(element => {
let beautyObj = null;
if (query) {
beautyObj = {
beautyNum: query,
index: element.mobile.indexOf(query),
len: query.length,
type: "query",
}
} else if (element.beautyObj[curTagVal]) {
beautyObj = element.beautyObj[curTagVal];
} else {
// 默认靓号提示
let len = element.beautyList.length;
if (len) {
beautyObj = element.beautyList[Math.floor(Math.random() * len)] || null
}
}
let numberDisplayList = []
element.mobile.split("").forEach((ele, index) => {
let numberObj = {
number: ele,
highlight: beautyObj && index >= beautyObj.index && index <= beautyObj.index + beautyObj.len - 1,
}
numberDisplayList.push(numberObj);
});
element.numberDisplayList = numberDisplayList;
});
this.setData({
numberList: list,
totalPages: listObj.totalPages,
})
},
/**
* input绑定
* 多输入文本绑定
* 在input/texarea中设置 data-name="属性值即可"
*/
inputEdit(e) {
let dataset = e.currentTarget.dataset;
let value = e.detail.value;
let name = dataset.name;
this.setData({
[name]: value
});
},
evtcomp(evt) {
console.log("evtcomp evt:", evt)
let {
name,
data
} = evt;
// console.log("name:", name)
switch (name) {
case "_evt_hide":
this.hideMask();
break;
case "_evt_submit_complete":
this.setData({
formVisible: false,
succVisible: true,
})
break;
}
},
// 关闭蒙层
onHideMask() {
this.setData({
formVisible: false,
succVisible: false,
})
},
onShareAppMessage() {
// 返回自定义分享信息
return {
title: '',
desc: '',
path: '',
};
},
});
\ No newline at end of file
{
"usingComponents": {
"form-comp":"/components/form/form",
"succ-comp":"/components/succ/succ"
}
}
\ No newline at end of file
const routerPath = {
index: '/pages/index/index',
expCommon: '/pages/exp-common/exp-common',
expBus: '/pages/exp-bus/exp-bus',
expForm: '/pages/exp-form/exp-form',
article: '/pages/artcle/article',
example: '/pages/example/example',
more: '/pages/more/more',
}
function parse(data) {
let tempArr = [];
for (let key in data) {
tempArr.push(key + '=' + encodeURIComponent(data[key]));
}
return tempArr.join('&');
}
function push(path, option = {}) {
if (typeof path == 'string') {
option.path = path; //兼容无参数路径
} else {
if (path.name) {
path.path = path.name;
}
option = path;
}
// console.log("option:", option);
// 配置key值找到对应path
let url = routerPath[option.path] || routerPath['index'];
// console.log("url:", url);
// 读取传入的配置参数
let {
query = {}, openType = 'navigate', duration = 0
} = option;
// json 转换为 字符串拼接参数
let params = parse(query)
// console.log("params:", params);
if (params) {
url = url + '?' + params;
}
// 是否需要延时跳转
duration ? setTimeout(() => {
to(openType, url);
}, duration) : to(openType, url);
}
function to(openType, url) {
let obj = {
url
};
if (openType == 'redirect') {
my.redirectTo(obj);
} else if (openType == 'reLaunch') {
my.reLaunch(obj);
} else if (openType == 'switchTab') {
my.switchTab(obj);
} else if (openType == 'back') {
my.navigateBack({
delta: 1
});
} else {
my.navigateTo(obj);
}
}
module.exports = {
parse,
push,
to
}
const config = require('./../../config');
const CryptoJS = require('./crypto-js.min');
const Encrypt = require('./jsencrypt.min');
var rsa = new Encrypt.JSEncrypt();
function makeEncrypt(param) {
let key = config.NET_CONFIG.RSA_PUBLIC_KEY; // 公钥
let iv = config.NET_CONFIG.AES_IV; // 偏移量
rsa.setPublicKey(key);
let chars = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z".split(",");
function randomAesKey() {
let res = "";
for (let i = 0; i < 16; i++) {
let id = Math.ceil(Math.random() * (chars.length - 1));
res += chars[id];
}
1
return res;
};
function encryptContent(obj) {
let aesKey = randomAesKey();
let key = CryptoJS.enc.Utf8.parse(aesKey);
let ivR = CryptoJS.enc.Utf8.parse(iv);
var encrypted = CryptoJS.AES.encrypt(JSON.stringify(obj), key, {
iv: ivR,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
let content = encrypted.toString(); //返回的是base64格式的密文
let securityKey = rsa.encrypt(aesKey);
let result = {
k: securityKey,
v: content
};
return result;
};
let data = encryptContent(param)
return data;
}
module.exports = {
makeEncrypt
}
// 不命中统一返回
const NOT_MATCH_OBJ = {
beautyNum: "",
index: -1,
len: 0
}
// 验证AABB
export function checkBeautyNumberAAA(phone) {
var reg = new RegExp('(.)\\1{2}', "g");
if (phone.match(reg) != null) {
var result = phone.match(reg)[0].toString();
return {
beautyNum: result,
index: phone.indexOf(result),
len: result.length,
type: "AAA+",
}
}
return NOT_MATCH_OBJ
}
// 验证AABB
export function checkBeautyNumberAABB(phone) {
var reg = new RegExp("(\\d)\\1((?!\\1)\\d)\\2", "g");
if (phone.match(reg) != null) {
var result = phone.match(reg)[0].toString();
return {
beautyNum: result,
index: phone.indexOf(result),
len: result.length,
type: "AABB+",
}
}
return NOT_MATCH_OBJ
}
// 验证ABAB
export function checkBeautyNumberABAB(phone) {
var reg = new RegExp("(\\d)((?!\\1)\\d)\\1\\2", "g");
if (phone.match(reg) != null) {
var result = phone.match(reg)[0].toString();
return {
beautyNum: result,
index: phone.indexOf(result),
len: result.length,
type: "ABAB+"
}
}
return NOT_MATCH_OBJ
}
// 验证AABB
export function checkBeautyNumberABBA(phone) {
var reg = new RegExp("(\\d)((?!\\1)\\d)\\2[\\d]", "g");
if (phone.match(reg) != null) {
var result = phone.match(reg)[0].toString();
if (result.substring(0, 1) == result.substring(3, 4)) {
return {
beautyNum: result,
index: phone.indexOf(result),
len: result.length,
type: "ABBA"
}
}
}
return NOT_MATCH_OBJ
}
// 验证ABCAB
export function checkBeautyNumberABCAB(phone) {
var reg = new RegExp("(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){2}\\d{3}", "g");
if (phone.match(reg) != null) {
var result = phone.match(reg)[0].toString();
if (result.substring(0, 2) == result.substring(3, 5)) {
return {
beautyNum: result,
index: phone.indexOf(result),
len: result.length,
type: "ABCAB"
}
}
}
return NOT_MATCH_OBJ
}
// 验证ABCD
export function checkBeautyNumberABCD(phone) {
var reg = new RegExp("(?:0123|1234|2345|3456|4567|5678|6789|7890|0987|9876|8765|7654|6543|5432|4321|3210)\\d", "g");
if (phone.match(reg) != null) {
var result = phone.match(reg)[0].toString()
result = result.substring(0, 4);
return {
beautyNum: result,
index: phone.indexOf(result),
len: result.length,
type: "ABCD"
}
}
return NOT_MATCH_OBJ
}
// // 最后一位是6/8/9
export function checkBeautyNumberLast(phone) {
const reg = new RegExp("\\d+[689]$");
if (phone.match(reg) != null) {
return {
beautyNum: phone.slice(-1),
index: phone.length - 1,
len: 1,
type: "LAST689"
}
}
return NOT_MATCH_OBJ
}
// 获取吉祥口号
export function getFeatureName(mobile) {
let featureName = {
0: "寓意圆满",
1: "大吉大利",
2: "成双成对",
3: "三生万物",
4: "四季来财",
5: "五福临门",
6: "六六大顺",
7: "升职加薪",
8: "发财旺运",
9: "富贵长久"
}
let num = mobile.slice(-1);
let result = featureName[num + ''];
return result;
}
export function sortByLength(array) {
array.sort((a, b) => a.beautyList.length > 0 ? -1 : 1);
}
// 支付宝省市区结构
export function addressToTree(address) {
let districtssheng = address.province_list;
let districtsShi = address.city_list;
let districtsQu = address.county_list;
let newArrSheng = [];
for (var i in districtssheng) {
// 第一层循环遍历出省份
let districtsShengObj = {}
districtsShengObj.id = i
districtsShengObj.name = districtssheng[i]
let newArrShi = []
for (var s in districtsShi) {
//第二层循环出市
if (i.substring(0, 2) === s.substring(0, 2)) {
// 以城市编码的前两位作为匹配项
let shiobj = {};
shiobj.id = s
shiobj.name = districtsShi[s]
let newArrQU = []
for (var q in districtsQu) {
//第三层循环遍历出区
if (s.substring(0, 4) == q.substring(0, 4)) {
//市与区以编码的前四位作为匹配
let quobj = {};
quobj.id = q
quobj.name = districtsQu[q]
newArrQU.push(quobj);
shiobj.subList = newArrQU;
}
}
newArrShi.push(shiobj);
districtsShengObj.subList = newArrShi;
//添加到所需的对象里
}
}
newArrSheng.push(districtsShengObj) // 最后添加到数组里
}
return newArrSheng;
}
function setItem(key, value, module_name) {
// console.log(key,value)
my.setStorageSync({
key: key,
data: value
});
// if (module_name) {
// let module_name_info = getItem(module_name) || {};
// module_name_info[key] = value;
// try {
// my.setStorageSync(module_name, module_name_info);
// } catch (e) {
// my.setStorage({
// key: module_name,
// data: module_name_info
// })
// }
// } else {
// try {
// my.setStorageSync(key, value);
// } catch (e) {
// my.setStorage({
// key: key,
// data: value
// })
// }
// }
}
function getItem(key, module_name) {
// if (module_name) {
// let val = getItem(module_name);
// if (val) return val[key];
// return '';
// }
// return my.getStorageSync(key).data
return my.getStorageSync({
key: key
}).data;
}
function clear(name) {
name ? my.removeStorageSync(name) : my.clearStorageSync()
}
module.exports = {
setItem,
getItem,
clear
}
\ No newline at end of file
// 正则
const REGEXPS = {
"mobile": /^1\d{10}$/,
//身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X。
"identNo": /(^\d{15}$)|(^\d{17}([0-9]|X)$)/,
}
// 验证手机
function checkMobile(str) {
return REGEXPS.mobile.test(str);
}
// 验证身份证
function checkIdentNo(num) {
num = num.toUpperCase();
return REGEXPS.identNo.test(num);
}
// 数组打乱顺序
function randomSort(a, b) {
return Math.random() > 0.5 ? -1 : 1;
}
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
//普通生成uuid
function uuid() {
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = "-";
var uuid = s.join("");
return uuid;
}
// 数组去重
function uniqueArray(arr) {
return arr.reduce((result, item) => {
const duplicate = result.find(obj => JSON.stringify(obj) === JSON.stringify(item));
if (!duplicate) {
result.push(item);
}
return result;
}, []);
}
// 模拟分页
function paginateArray(arr, page, size = 10) {
const startIndex = (page - 1) * size;
const endIndex = startIndex + size;
const currentPageList = arr.slice(startIndex, endIndex);
const totalPages = Math.ceil(arr.length / size);
return {
list: currentPageList,
totalPages
};
}
/**
* 链接参数转换为obj
* 入参 完整链接
* @param {*} url
*/
function param2Obj(url) {
const search = url.split('?')[1]
if (!search) {
return {}
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"') +
'"}'
)
}
/**
* 分转元
* @param {*} fen
* @returns
*/
export const regFenToYuan = (fen) => {
var num = fen;
num = fen * 0.01;
num += '';
var reg = num.indexOf('.') > -1 ? /(\d{1,3})(?=(?:\d{3})+\.)/g : /(\d{1,3})(?=(?:\d{3})+$)/g;
num = num.replace(reg, '$1');
num = toDecimal2(num)
return num
};
/**
* 元转分
* @param {*} yuan
* @param {*} digit
* @returns
*/
export const regYuanToFen = (yuan, digit = 100) => {
var m = 0,
s1 = yuan.toString(),
s2 = digit.toString();
try {
m += s1.split(".")[1].length
} catch (e) {}
try {
m += s2.split(".")[1].length
} catch (e) {}
return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
}
/**
* 强制保留2位小数,如:2,会在2后面补上00.即2.00
* @param {*} x
* @returns
*/
export const toDecimal2 = (x) => {
var f = parseFloat(x);
if (isNaN(f)) {
return false;
}
var f = Math.round(x * 100) / 100;
var s = f.toString();
var rs = s.indexOf('.');
if (rs < 0) {
rs = s.length;
s += '.';
}
while (s.length <= rs + 2) {
s += '0';
}
return s;
}
/**
* 格式化数字,不足一位补充0
* @param {*} n
*/
function formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
}
/**
* 获取屏幕剩余高度
* useHeight 单位是rpx
* 默认返回单位是rpx 可通过unit参数改为 px
*/
function getLastScreenHeight(useHeight = 0, unit = 'rpx') {
let sysInfo = my.getSystemInfoSync();
let clientHeight = sysInfo.windowHeight;
// 获取可使用窗口高度
let clientWidth = sysInfo.windowWidth;
// 算出比例
let ratio = 750 / clientWidth;
// 算出屏幕高度(单位rpx)
let height = clientHeight * ratio;
// 计算剩余高度
let lastHeight = height - useHeight;
// 可转换成px
if (unit == 'px') {
lastHeight = lastHeight / 750 * clientWidth
}
return lastHeight;
}
/**
* px转rpx
* @param {*} value
*/
function pxToRpx(value) {
let sysInfo = my.getSystemInfoSync();
let clientWidth = sysInfo.windowWidth;
let result = value / 750 * clientWidth
return result;
}
// 格式化星期几
function formatWeek(week) {
let result = "";
switch (week) {
case 1:
result = "一";
break;
case 2:
result = "二";
break;
case 3:
result = "三";
break;
case 4:
result = "四";
break;
case 5:
result = "五";
break;
case 6:
result = "六";
break;
case 0:
result = "日";
break;
default:
break;
}
return result;
}
/**
* 格式化日期时间 支持Date和时间戳
* @param {date} date 日期时间
* @param {string} fmt 格式,如:'yyyy-MM-dd hh:mm:ss'
*/
function formatDate(date, fmt) {
if (!date) return '-'
// 把-换成/ 避免iOS和安卓真机问题
if (isNaN(date)) {
var reg = /-/g;
date = date && date.replace(reg, '/');
}
date = new Date(date)
const o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'h+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
S: date.getMilliseconds() // 毫秒
}
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
for (const k in o) {
if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
}
return fmt
}
/**
* 获取点击传值
* @param {*} evt
* @param {*} key
*/
function getBindtapData(evt, key = "data") {
let keyStr = key || "data";
return evt.currentTarget.dataset[keyStr];
}
/**
* 从数组中获取 key未value的对象
* @param {*} value
* @param {*} key
* @param {*} list
*/
function getObjByListKeyValue(value, key, list) {
let result = null;
list.forEach(element => {
if (element[key + ""] == value) {
result = element;
}
});
return result;
}
/**
* 获取小程序码
* path = "/pages/index/index?pa=1"
* @param {*} path
*/
function wxacodeGet(path) {
return " https://api.k.wxpai.cn/bizproxy/mzcfsapi/qrcode/create?path=" + encodeURIComponent(path);
}
/**
* 根据url获取参数
* @param {*} name
*/
function getQueryByUrl(name, url) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(url) || [, ""])[1].replace(/\+/g, '%20')) || null;
}
/**
* 添加base前缀(my.arrayBufferToBase64方法不提供前缀)
*/
function addBase64Prefix(base64) {
return "data:image/PNG;base64," + base64;
}
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
let debounceTimeout;
function debounce(func, wait, immediate) {
return function () {
let context = this;
let args = arguments;
if (debounceTimeout) clearTimeout(debounceTimeout);
if (immediate) {
var callNow = !debounceTimeout;
debounceTimeout = setTimeout(() => {
debounceTimeout = null;
}, wait)
if (callNow) func.apply(context, args)
} else {
debounceTimeout = setTimeout(function () {
func.apply(context, args)
}, wait);
}
}();
}
/**
* @desc 函数节流
* @param func 函数
* @param wait 延迟执行毫秒数
* @param type 1 表时间戳版,2 表定时器版
* 时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。
*/
let throttleTimeout;
let throttlePrevious;
function throttle(func, wait, type) {
if (type === 1) {
throttlePrevious = 0;
} else if (type === 2) {
throttleTimeout = 0;
}
return function () {
let context = this;
let args = arguments;
if (type === 1) {
let now = Date.now();
if (now - throttlePrevious > wait) {
func.apply(context, args);
throttlePrevious = now;
}
} else if (type === 2) {
if (!throttleTimeout) {
throttleTimeout = setTimeout(() => {
throttleTimeout = null;
func.apply(context, args)
}, wait)
}
}
}();
}
module.exports = {
shuffleArray: shuffleArray,
randomSort: randomSort,
uuid: uuid,
uniqueArray: uniqueArray,
paginateArray: paginateArray,
formatDate: formatDate,
formatNumber: formatNumber,
checkMobile: checkMobile,
checkIdentNo: checkIdentNo,
getLastScreenHeight: getLastScreenHeight,
debounce: debounce,
throttle: throttle,
param2Obj: param2Obj,
pxToRpx: pxToRpx,
formatWeek: formatWeek,
getBindtapData: getBindtapData,
wxacodeGet: wxacodeGet,
getObjByListKeyValue: getObjByListKeyValue,
getQueryByUrl: getQueryByUrl,
regFenToYuan: regFenToYuan,
regYuanToFen: regYuanToFen,
toDecimal2: toDecimal2,
addBase64Prefix: addBase64Prefix,
}
\ No newline at end of file