基础项目
0 parents
Showing
53 changed files
with
2480 additions
and
0 deletions
.mini-ide/project-ide.json
0 → 100644
app.js
0 → 100644
1 | const fetchApi = require('./http/fetch-api.js'); | ||
2 | const api = require('./http/api'); | ||
3 | const config = require('./config'); | ||
4 | const router = require('./router/index'); | ||
5 | const storage = require('./utils/stroage'); | ||
6 | const util = require('./utils/util'); | ||
7 | const func = require('./utils/func'); | ||
8 | // console.log('api.login:', api.login) | ||
9 | |||
10 | // console.log('fetchApi:',fetchApi) | ||
11 | // console.log('fetchApi.get:',fetchApi.fetch) | ||
12 | |||
13 | App({ | ||
14 | get: fetchApi.fetchMethod, | ||
15 | post: (params) => { | ||
16 | params.method = 'post'; | ||
17 | return fetchApi.fetchMethod(params); | ||
18 | }, | ||
19 | delete: (params) => { | ||
20 | params.method = 'DELETE'; | ||
21 | return fetchApi.fetchMethod(params); | ||
22 | }, | ||
23 | uploadFile: fetchApi.uploadFile, // 单文件上传 | ||
24 | uploadFileMultiple: fetchApi.uploadFileMultiple, // 多文件上传, | ||
25 | api: api, | ||
26 | config: config, | ||
27 | router: router, | ||
28 | storage: storage, | ||
29 | util: util, | ||
30 | func: func, | ||
31 | tapData: util.getBindtapData, | ||
32 | globalData: { | ||
33 | userInfo: null, | ||
34 | profile: null, | ||
35 | wxcode: storage.getItem("wxcode"), | ||
36 | ui: { | ||
37 | colorUI: "#409EFF", | ||
38 | colorDanger: "#EE0A24" | ||
39 | }, | ||
40 | invitationCode: "", | ||
41 | statusBarHeight: 0, | ||
42 | }, | ||
43 | onLaunch(options) { | ||
44 | // 第一次打开 | ||
45 | // options.query == {number:1} | ||
46 | console.info('App onLaunch'); | ||
47 | }, | ||
48 | onShow(options) { | ||
49 | // 从后台被 scheme 重新打开 | ||
50 | // options.query == {number:1} | ||
51 | }, | ||
52 | |||
53 | /** | ||
54 | * 封装toast | ||
55 | * @returns | ||
56 | */ | ||
57 | toast(title, opt = { | ||
58 | icon: 'none' | ||
59 | }) { | ||
60 | let data = opt; | ||
61 | data.title = title | ||
62 | my.showToast({ | ||
63 | content: title | ||
64 | }) | ||
65 | return; | ||
66 | }, | ||
67 | }); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
app.json
0 → 100644
components/demo-item/demo-item.acss
0 → 100755
File mode changed
components/demo-item/demo-item.axml
0 → 100644
components/demo-item/demo-item.js
0 → 100644
components/demo-item/demo-item.json
0 → 100644
components/form/form.acss
0 → 100755
1 | .form-comp { | ||
2 | background: url('/images/form/form-bg-1.png') center no-repeat; | ||
3 | background-size: 100% 100%; | ||
4 | width: 723rpx; | ||
5 | height: 691rpx; | ||
6 | padding-top: 60rpx; | ||
7 | box-sizing: border-box; | ||
8 | text-align: center; | ||
9 | } | ||
10 | |||
11 | .form-comp-2 { | ||
12 | background: url('/images/form/form-bg-2.png') center no-repeat; | ||
13 | background-size: 100% 100%; | ||
14 | width: 723rpx; | ||
15 | height: 1021rpx; | ||
16 | } | ||
17 | |||
18 | .form-comp .number { | ||
19 | font-size: 52rpx; | ||
20 | font-weight: bold; | ||
21 | letter-spacing: 1.29rpx; | ||
22 | color: #131313; | ||
23 | } | ||
24 | |||
25 | .form-comp .tit { | ||
26 | font-size: 40rpx; | ||
27 | font-weight: bold; | ||
28 | text-align: center; | ||
29 | color: #ff027c; | ||
30 | margin: 14rpx auto 0; | ||
31 | } | ||
32 | |||
33 | .form-comp .tips { | ||
34 | font-size: 23rpx; | ||
35 | font-weight: 600; | ||
36 | color: #727272; | ||
37 | margin: 14rpx auto 0; | ||
38 | } | ||
39 | |||
40 | .form { | ||
41 | margin: 32rpx auto 0; | ||
42 | } | ||
43 | |||
44 | .form-item { | ||
45 | width: 647rpx; | ||
46 | height: 86rpx; | ||
47 | border-radius: 16rpx; | ||
48 | border: solid 1rpx #787878; | ||
49 | background-color: #fcf8ff; | ||
50 | margin: 0 auto 24rpx; | ||
51 | padding: 0 32rpx; | ||
52 | box-sizing: border-box; | ||
53 | display: flex; | ||
54 | align-items: center; | ||
55 | justify-content: space-between; | ||
56 | text-align: left; | ||
57 | } | ||
58 | |||
59 | .form-item .label { | ||
60 | display: flex; | ||
61 | width: 150rpx; | ||
62 | font-weight: bold; | ||
63 | font-size: 32rpx; | ||
64 | } | ||
65 | |||
66 | .form-item .label .requrie { | ||
67 | color: #f00; | ||
68 | font-weight: 500; | ||
69 | } | ||
70 | |||
71 | .form-item .ipt { | ||
72 | background-color: transparent; | ||
73 | flex: 1; | ||
74 | font-size: 28rpx; | ||
75 | } | ||
76 | |||
77 | .form-comp .submit-btn { | ||
78 | background: url('/images/form/submit-btn.png') center no-repeat; | ||
79 | background-size: 100% 100%; | ||
80 | width: 630rpx; | ||
81 | height: 102rpx; | ||
82 | margin: 40rpx auto 0; | ||
83 | } | ||
84 | |||
85 | .form-comp .submit-tips { | ||
86 | margin: 20rpx auto 0; | ||
87 | font-size: 23rpx; | ||
88 | font-weight: 600; | ||
89 | text-align: center; | ||
90 | color: #727272; | ||
91 | } | ||
92 | |||
93 | .form-comp .func {} | ||
94 | |||
95 | .form-comp .func .icon { | ||
96 | background: url('/images/form/icon-question.png') center no-repeat; | ||
97 | background-size: 100% 100%; | ||
98 | width: 30rpx; | ||
99 | height: 30rpx; | ||
100 | } | ||
101 | |||
102 | |||
103 | .untouch { | ||
104 | pointer-events: none; | ||
105 | } | ||
106 | |||
107 | .ani-heart { | ||
108 | animation: ani-heart-key 1.2s linear infinite; | ||
109 | } | ||
110 | |||
111 | @keyframes ani-heart-key { | ||
112 | 0% { | ||
113 | transform: scale(1); | ||
114 | } | ||
115 | |||
116 | 50% { | ||
117 | transform: scale(1.04); | ||
118 | } | ||
119 | |||
120 | 100% { | ||
121 | transform: scale(1); | ||
122 | } | ||
123 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
components/form/form.axml
0 → 100644
1 | <view class="form-comp {{!fold ? 'form-comp-2' : ''}}"> | ||
2 | <view class="number"> | ||
3 | {{item.mobile}} | ||
4 | </view> | ||
5 | <view class="tit"> | ||
6 | {{item && item.featureName || '发财旺运'}} | ||
7 | </view> | ||
8 | <view class="tips"> | ||
9 | 请如实填写以下信息,以便我们及时为您送达 | ||
10 | </view> | ||
11 | <view class="form"> | ||
12 | <view class="form-item"> | ||
13 | <view class="label"> | ||
14 | 姓 名 | ||
15 | <view class="requrie"> | ||
16 | * | ||
17 | </view> | ||
18 | </view> | ||
19 | <input | ||
20 | onBlur="onBlur" | ||
21 | onInput="inputEdit" | ||
22 | data-name="queryForm.name" | ||
23 | value="{{queryForm.name}}" | ||
24 | class="ipt" | ||
25 | placeholder="请输入姓名 (已加密)" | ||
26 | /> | ||
27 | </view> | ||
28 | |||
29 | <view class="form-item"> | ||
30 | <view class="label"> | ||
31 | 联系电话 | ||
32 | <view class="requrie"> | ||
33 | * | ||
34 | </view> | ||
35 | </view> | ||
36 | <input | ||
37 | onBlur="onBlur" | ||
38 | onInput="inputEdit" | ||
39 | data-name="queryForm.mobilePhone" | ||
40 | value="{{queryForm.mobilePhone}}" | ||
41 | class="ipt" | ||
42 | placeholder="请输入联系电话,并保持畅通" | ||
43 | type="number" | ||
44 | /> | ||
45 | </view> | ||
46 | |||
47 | <block a:if="{{ !fold}}"> | ||
48 | |||
49 | <view class="form-item"> | ||
50 | <view class="label"> | ||
51 | 身份证 | ||
52 | <view class="requrie"> | ||
53 | * | ||
54 | </view> | ||
55 | </view> | ||
56 | <input | ||
57 | onInput="inputEdit" | ||
58 | data-name="queryForm.identNo" | ||
59 | value="{{queryForm.identNo}}" | ||
60 | class="ipt" | ||
61 | placeholder="请输入身份证号 (已加密)" | ||
62 | type="idcard" | ||
63 | /> | ||
64 | </view> | ||
65 | |||
66 | <view class="form-item" onTap="onPickerArea"> | ||
67 | <view class="label"> | ||
68 | 所在地区 | ||
69 | <view class="requrie"> | ||
70 | * | ||
71 | </view> | ||
72 | </view> | ||
73 | <input value="{{areaStr}}" class="ipt untouch" placeholder="请选择省/市/区" /> | ||
74 | </view> | ||
75 | |||
76 | <view class="form-item"> | ||
77 | <input | ||
78 | onInput="inputEdit" | ||
79 | data-name="queryForm.address" | ||
80 | value="{{queryForm.address}}" | ||
81 | class="ipt" | ||
82 | placeholder="请输入详细地址 (*街道*小区*门牌号)" | ||
83 | /> | ||
84 | <view class="func"> | ||
85 | <view onTap="onAddressTips" class="icon icon-question"> | ||
86 | |||
87 | </view> | ||
88 | </view> | ||
89 | </view> | ||
90 | </block> | ||
91 | |||
92 | </view> | ||
93 | <view onTap="onSubmit" class="submit-btn ani-heart"></view> | ||
94 | <view class="submit-tips"> | ||
95 | 请保持联系号码畅通,我们可能随时与您联系 | ||
96 | </view> | ||
97 | </view> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
components/form/form.js
0 → 100644
1 | let app = getApp(); | ||
2 | |||
3 | // 联通专属 | ||
4 | import area from '/const/area-lt'; | ||
5 | |||
6 | Component({ | ||
7 | mixins: [], | ||
8 | data: { | ||
9 | queryForm: { | ||
10 | selectMobilePhone: "", // 从父组件中传入 | ||
11 | name: "", // 姓名 | ||
12 | mobilePhone: "", // 用户手机号 | ||
13 | identNo: "", // 证件号 | ||
14 | province: "", // 省 | ||
15 | provinceCode: "", // 省编号 | ||
16 | city: "", // 市 | ||
17 | cityCode: "", // 市编号 | ||
18 | district: "", // 区 | ||
19 | districtCode: "", // 区编号 | ||
20 | address: "", // 收货地址 | ||
21 | }, | ||
22 | areaStr: "", | ||
23 | |||
24 | fold: true | ||
25 | }, | ||
26 | |||
27 | props: { | ||
28 | item: { | ||
29 | type: Object, | ||
30 | value: null, | ||
31 | }, | ||
32 | |||
33 | // 发送自定义事件 onChange 貌似为固定值 | ||
34 | onChange(data) {}, | ||
35 | }, | ||
36 | didMount() { | ||
37 | // console.log("area:", area); | ||
38 | // let res = app.func.addressToTree(area); | ||
39 | // console.log("res:", res); | ||
40 | }, | ||
41 | didUpdate() {}, | ||
42 | didUnmount() {}, | ||
43 | methods: { | ||
44 | onBlur() { | ||
45 | if (this.data.queryForm.name && this.data.queryForm.mobilePhone) { | ||
46 | this.setData({ | ||
47 | fold: false, | ||
48 | }) | ||
49 | } | ||
50 | }, | ||
51 | |||
52 | // 封装 my.multiLevelSelect | ||
53 | // - 对于传入的数据,只向底层接口传递 name 和 subList | ||
54 | // - 对于选中的结果,替换成对应的完整数据条目再回调 | ||
55 | multiLevelSelect({ | ||
56 | title, | ||
57 | list, | ||
58 | success, | ||
59 | fail, | ||
60 | complete | ||
61 | }) { | ||
62 | const clean = ({ | ||
63 | name, | ||
64 | subList | ||
65 | }) => { | ||
66 | return { | ||
67 | name, | ||
68 | subList: subList && subList.map(clean) | ||
69 | }; | ||
70 | }; | ||
71 | const lookup = (array, index, pool) => { | ||
72 | if (array && index < array.length) { | ||
73 | array[index] = pool.filter(x => x.name === array[index].name)[0]; | ||
74 | lookup(array, index + 1, array[index].subList); | ||
75 | delete array[index].subList; // 方便回调中的 my.alert 演示。真实代码请删除此行,避免副作用 | ||
76 | } | ||
77 | }; | ||
78 | const wrap = func => | ||
79 | func && | ||
80 | (res => { | ||
81 | res.success && lookup(res.result, 0, list); | ||
82 | func(res); | ||
83 | }); | ||
84 | return my.multiLevelSelect({ | ||
85 | title, | ||
86 | list: list.map(clean), | ||
87 | success: wrap(success), | ||
88 | fail, | ||
89 | complete: wrap(complete), | ||
90 | }); | ||
91 | }, | ||
92 | |||
93 | // 选择地址 | ||
94 | onPickerArea() { | ||
95 | let areas = app.func.addressToTree(area); | ||
96 | console.log("areas:", areas); | ||
97 | |||
98 | let updateList = [] | ||
99 | areas.forEach(element => { | ||
100 | if (element.id == "440000") { | ||
101 | updateList.push(element); | ||
102 | } | ||
103 | }); | ||
104 | this.multiLevelSelect({ | ||
105 | title: '请选择所在地区', | ||
106 | list: updateList, | ||
107 | success: res => { | ||
108 | |||
109 | let region = res.result; | ||
110 | console.log(region) | ||
111 | this.setData({ | ||
112 | 'queryForm.province': region[0].name, | ||
113 | 'queryForm.city': region[1].name, | ||
114 | 'queryForm.district': region[2].name, | ||
115 | |||
116 | 'queryForm.provinceCode': region[0].id, | ||
117 | 'queryForm.cityCode': region[1].id, | ||
118 | 'queryForm.districtCode': region[2].id, | ||
119 | 'areaStr': region[0].name + region[1].name + region[2].name | ||
120 | }) | ||
121 | }, | ||
122 | fail: error => { | ||
123 | // console.error('multiLevelSelect fail: ', JSON.stringify(error)); | ||
124 | }, | ||
125 | }); | ||
126 | }, | ||
127 | // 显示地址tips | ||
128 | onAddressTips() { | ||
129 | my.showToast({ | ||
130 | content: "请输入详细准确的地址,字数不少于4字(例如:**街身份证* 道…),且不能包含特殊符号(例如:? !/0等,可以输入小写-号)" | ||
131 | }) | ||
132 | }, | ||
133 | |||
134 | |||
135 | /** | ||
136 | * input绑定 | ||
137 | * 多输入文本绑定 | ||
138 | * 在input/texarea中设置 data-name="属性值即可" | ||
139 | */ | ||
140 | inputEdit(e) { | ||
141 | let dataset = e.currentTarget.dataset; | ||
142 | let value = e.detail.value; | ||
143 | let name = dataset.name; | ||
144 | this.setData({ | ||
145 | [name]: value | ||
146 | }); | ||
147 | }, | ||
148 | |||
149 | /** | ||
150 | * 检查表单 | ||
151 | */ | ||
152 | checkSubmit() { | ||
153 | return new Promise((resolve, reject) => { | ||
154 | |||
155 | let { | ||
156 | name, | ||
157 | mobilePhone, | ||
158 | identNo, | ||
159 | district, | ||
160 | address | ||
161 | } = this.data.queryForm; | ||
162 | |||
163 | console.log("this.data.queryForm:", this.data.queryForm); | ||
164 | |||
165 | if (!name) { | ||
166 | app.toast("请输入姓名") | ||
167 | return; | ||
168 | } | ||
169 | |||
170 | if (!app.util.checkMobile(mobilePhone)) { | ||
171 | app.toast("请输入正确的手机号码") | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | if (!app.util.checkIdentNo(identNo)) { | ||
176 | app.toast("请输入正确的身份证号码") | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | if (!district) { | ||
181 | app.toast("请选择所在地区") | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | if (!address) { | ||
186 | app.toast("请输入详细地址") | ||
187 | return; | ||
188 | } | ||
189 | |||
190 | resolve(this.data.queryForm) | ||
191 | }); | ||
192 | }, | ||
193 | |||
194 | /** | ||
195 | * 提交表单 | ||
196 | */ | ||
197 | onSubmit() { | ||
198 | this.checkSubmit().then((params) => { | ||
199 | params.selectMobilePhone = this.props.item.mobile; | ||
200 | console.log("params:", params) | ||
201 | |||
202 | my.showLoading({ | ||
203 | content: '稍等片刻,订单提交中', | ||
204 | mask: true | ||
205 | }); | ||
206 | |||
207 | app.post({ | ||
208 | url: app.api.createOrder, | ||
209 | data: params, | ||
210 | }).then((result) => { | ||
211 | // 发送自定义事件 onChange 貌似为固定值 | ||
212 | this.props.onChange({ | ||
213 | name: "_evt_submit_complete" | ||
214 | }) | ||
215 | my.hideLoading(); | ||
216 | }).catch((err) => { | ||
217 | my.hideLoading(); | ||
218 | }); | ||
219 | }); | ||
220 | }, | ||
221 | }, | ||
222 | }); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
components/form/form.json
0 → 100644
components/succ/succ.acss
0 → 100755
1 | .succ-comp { | ||
2 | background: url('/images/form/form-bg-succ.png') center no-repeat; | ||
3 | background-size: 100% 100%; | ||
4 | width: 723rpx; | ||
5 | height: 620rpx; | ||
6 | padding-top: 104rpx; | ||
7 | box-sizing: border-box; | ||
8 | text-align: center; | ||
9 | } | ||
10 | |||
11 | .succ-comp .icon-succ { | ||
12 | background: url('/images/form/icon-succ.png') center no-repeat; | ||
13 | background-size: 100% 100%; | ||
14 | width: 231rpx; | ||
15 | height: 231rpx; | ||
16 | margin: 0 auto 0; | ||
17 | } | ||
18 | |||
19 | .succ-comp .tit { | ||
20 | font-size: 53rpx; | ||
21 | font-weight: 800; | ||
22 | text-align: center; | ||
23 | color: #ff027c; | ||
24 | margin: 36rpx auto 0; | ||
25 | } | ||
26 | |||
27 | .succ-comp .tips { | ||
28 | font-size: 23rpx; | ||
29 | font-weight: 600; | ||
30 | text-align: center; | ||
31 | color: #727272; | ||
32 | margin: 16rpx auto 0; | ||
33 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
components/succ/succ.axml
0 → 100644
components/succ/succ.js
0 → 100644
components/succ/succ.json
0 → 100644
config.js
0 → 100644
const/area-lt.js
0 → 100644
This diff could not be displayed because it is too large.
const/area-new.js
0 → 100644
This diff could not be displayed because it is too large.
const/area.js
0 → 100644
This diff could not be displayed because it is too large.
const/index.js
0 → 100644
This diff is collapsed.
Click to expand it.
env/index.js
0 → 100644
1 | /** | ||
2 | * BASE_API:api统一请求域名。(当前项目业务) | ||
3 | * API_PREFIX:请求业务词头前缀,项目划分 | ||
4 | * COMMON_API:平台通用请求域名。(单/多文件上传,省市区联查,场景二维码/小程序码等) | ||
5 | * IMG:oss图片地址前缀,用于访问 | ||
6 | * OSS_PATH:上传文件路径,用于上传 例如:'/weapp/xxx/' | ||
7 | * MODULE_CODE:后端给出 | ||
8 | * RSA_PUBLIC_KEY:公钥 | ||
9 | * AES_IV:偏移量 | ||
10 | * IS_POST_ENC:post方法是否开启自动开启加密 | ||
11 | */ | ||
12 | |||
13 | |||
14 | module.exports = { | ||
15 | dev: { | ||
16 | BASE_API: 'https://prettyapi.kdao.xin', | ||
17 | // BASE_API: 'https://prettyapi.letterbelieve.com', | ||
18 | // BASE_API: 'https://bizapi.kdao.xin', | ||
19 | API_PREFIX: '/zwPrettyNumApi', | ||
20 | COMMON_API: 'https://bizapi.kdao.xin', | ||
21 | IMG: 'https://cdn.kdao.xin/cdn/images', | ||
22 | OSS_PATH: '', | ||
23 | MODULE_CODE: 'd00b70ed26ed4f1291eb870662270e77', | ||
24 | RSA_PUBLIC_KEY: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4U9ZijHk0bsHh5YvsQu7E9l/S9sqRLlbLhxmcgoTCcH5nO3S4//VZ/Ns2sxRwSWrsCxGr+tIPXBofJErGf3teqxAspca/1pjaWGB3fQ44Q0+OPwv1l7vWgn81tdMIMizjHu31vrUTlcL9UDHfoLB9vht3mtrYsc7xTi8MnHlkWx+VZv8uS06sLRJqCBiIzZcdB30szCjNtcSm1A2sV4EnBzqCQnR4/0Bd33UVRVdJLFcez5OfKqTi3HS65adf6U8LjOdw5rE+NNPNJmggVGlWVRyw9MSkjbYS9W4lpGul22rIKODkLFnqEtW8VcG/1dFCka1ykMADOII+YXr6GDHQIDAQAB', | ||
25 | AES_IV: 'ce102d54b198462c', | ||
26 | IS_POST_ENC: true, | ||
27 | }, | ||
28 | prod: { | ||
29 | BASE_API: 'https://prettyapi.kdao.xin', | ||
30 | // BASE_API: 'https://prettyapi.letterbelieve.com', | ||
31 | // BASE_API: 'https://bizapi.kdao.xin', | ||
32 | API_PREFIX: '/zwPrettyNumApi', | ||
33 | COMMON_API: 'https://bizapi.kdao.xin', | ||
34 | IMG: 'https://cdn.kdao.xin/cdn/images', | ||
35 | OSS_PATH: '', | ||
36 | MODULE_CODE: 'd00b70ed26ed4f1291eb870662270e77', | ||
37 | RSA_PUBLIC_KEY: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4U9ZijHk0bsHh5YvsQu7E9l/S9sqRLlbLhxmcgoTCcH5nO3S4//VZ/Ns2sxRwSWrsCxGr+tIPXBofJErGf3teqxAspca/1pjaWGB3fQ44Q0+OPwv1l7vWgn81tdMIMizjHu31vrUTlcL9UDHfoLB9vht3mtrYsc7xTi8MnHlkWx+VZv8uS06sLRJqCBiIzZcdB30szCjNtcSm1A2sV4EnBzqCQnR4/0Bd33UVRVdJLFcez5OfKqTi3HS65adf6U8LjOdw5rE+NNPNJmggVGlWVRyw9MSkjbYS9W4lpGul22rIKODkLFnqEtW8VcG/1dFCka1ykMADOII+YXr6GDHQIDAQAB', | ||
38 | AES_IV: 'ce102d54b198462c', | ||
39 | IS_POST_ENC: true, | ||
40 | } | ||
41 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
http/api.js
0 → 100644
1 | module.exports = { | ||
2 | |||
3 | config: "/front/mallApi/configs", //会员配置 | ||
4 | login: '/front/userApi/login', // 登录 | ||
5 | wxLogin: "/front/userApi/code2session", // wx小程序登录 | ||
6 | profile: "/front/userApi/profile", // profile | ||
7 | |||
8 | profile: "/front/userApi/profile", // profile | ||
9 | |||
10 | // 1、这个接口一次查询会返回100个号码。 | ||
11 | // 2、后台限制了这个接口从联通获取号码的次数(5)次。多次调用后,如果超过次数,会默认以query = '' 返回结果。相同查询条件的结果会缓存起来,二次查询的结果是相同的。 | ||
12 | // 3、建议前台缓存返回的结果,翻页、AABB+组合需要前端自行做正则匹配。匹配结果不足时,可以从缓存中随机抽取号码补齐。 | ||
13 | // 4、缓存返回结果的时候做好去重操作 | ||
14 | selectNum: "/front/selectNum", // 选号 | ||
15 | |||
16 | createOrder: "/front/createOrder", // 下单 | ||
17 | |||
18 | /** | ||
19 | * 通用接口 | ||
20 | * 请求时 "mode"传"custom" | ||
21 | */ | ||
22 | areaQuery: 'https://api.k.wxpai.cn/bizproxy/kdapi/area', // post 区域查询 | ||
23 | |||
24 | // 文件上传 | ||
25 | uploadFile: '/common/upload', // 上传图片通用接口(需要后端协同开通用接口,目前没有通用接口) | ||
26 | // uploadFile: "/admin/upload", // 上传图片 | ||
27 | wxQrcodeCreate: '/open/wx/qrcode/create', //生成小程序码(需要后端协同开通用接口,目前没有通用接口) | ||
28 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
http/fetch-api.js
0 → 100644
1 | let config = require('./../config'); | ||
2 | let Storage = require('./../utils/stroage'); | ||
3 | let util = require('./../utils/util'); | ||
4 | let Router = require('./../router/index'); | ||
5 | let Encrypt = require('./../utils/enc/enc'); | ||
6 | let api = require('./api'); | ||
7 | const errMsg = '服务异常,请稍后重试'; | ||
8 | |||
9 | /** | ||
10 | * 重新获取 sessionId | ||
11 | * 1.重新获取wxcode, | ||
12 | * 2.调用login方法,传wxcode,给后端重新换取js_session | ||
13 | * @returns | ||
14 | */ | ||
15 | function login() { | ||
16 | return new Promise((resolve, reject) => { | ||
17 | // my.login({ | ||
18 | // success: (res) => { | ||
19 | |||
20 | let res = { | ||
21 | code: util.uuid() | ||
22 | } | ||
23 | |||
24 | let baseUrl = config.NET_CONFIG.BASE_API + config.NET_CONFIG.API_PREFIX; | ||
25 | let header = { | ||
26 | '-kd-platform-env': config.ENV, | ||
27 | '-kd-platform-module': config.NET_CONFIG.MODULE_CODE | ||
28 | } | ||
29 | |||
30 | |||
31 | let app = getApp(); | ||
32 | let globalData = app && app.globalData || null | ||
33 | let data = { | ||
34 | code: res.code, | ||
35 | miniproChannel: globalData.channelCode || "", | ||
36 | channelCode: globalData.channelCode || "", | ||
37 | parentMemberCode: globalData.parentMemberCode || "", | ||
38 | platform: "minipro", | ||
39 | }; | ||
40 | |||
41 | data = Encrypt.makeEncrypt(data); | ||
42 | my.request({ | ||
43 | // url: baseUrl + api.wxLogin, | ||
44 | url: baseUrl + api.login, | ||
45 | sid: false, | ||
46 | data: data, | ||
47 | method: 'POST', | ||
48 | header: header, | ||
49 | success: (res) => { | ||
50 | let { | ||
51 | code, | ||
52 | content | ||
53 | } = res.data; | ||
54 | if (code == 200 && content.sessionId) { | ||
55 | Storage.setItem('sessionId', content.sessionId); // 保存新的sessionId | ||
56 | resolve(); | ||
57 | } else { | ||
58 | reject(); | ||
59 | } | ||
60 | } | ||
61 | }) | ||
62 | // } | ||
63 | // }); | ||
64 | |||
65 | }); | ||
66 | } | ||
67 | |||
68 | |||
69 | /** | ||
70 | * 检查并埋下sessionId | ||
71 | * @param {*} sid 接口是否需要sessionId | ||
72 | * @returns | ||
73 | */ | ||
74 | function checkSessionId(sid) { | ||
75 | return new Promise((resolve, reject) => { | ||
76 | let sessionId = Storage.getItem('sessionId'); | ||
77 | if (sid) { | ||
78 | // 拥有sessionId | ||
79 | if (sessionId) { | ||
80 | resolve(); | ||
81 | } else { | ||
82 | // 重新获取 sessionId | ||
83 | login().then((result) => { | ||
84 | resolve(); | ||
85 | }).catch((err) => { | ||
86 | reject(); | ||
87 | }); | ||
88 | } | ||
89 | } else { | ||
90 | // 不需要 sessionId 忽略 | ||
91 | resolve(); | ||
92 | } | ||
93 | }); | ||
94 | } | ||
95 | |||
96 | |||
97 | |||
98 | function fetchMethod(val) { | ||
99 | let params = Object.assign({ | ||
100 | loading: false, | ||
101 | toast: true, | ||
102 | sid: true, | ||
103 | mode: "", | ||
104 | url: "", | ||
105 | data: null, | ||
106 | method: "GET", | ||
107 | enc: false | ||
108 | }, val); | ||
109 | let promise = new Promise((resolve, reject) => { | ||
110 | checkSessionId(params.sid).then(() => { | ||
111 | doRequest(params).then((result) => { | ||
112 | resolve(result); | ||
113 | }).catch((err) => { | ||
114 | // 404 或 403 错误码的时候需要重新拉一次 | ||
115 | if (err.code == 404 || err.code == 403) { | ||
116 | login().then((loginRes) => { | ||
117 | doRequest(params).then((result2) => { | ||
118 | resolve(result2); | ||
119 | }); | ||
120 | }).catch((err) => {}); | ||
121 | } else { | ||
122 | reject(err) | ||
123 | } | ||
124 | }); | ||
125 | }); | ||
126 | }); | ||
127 | return promise; | ||
128 | } | ||
129 | |||
130 | |||
131 | /** | ||
132 | * 做实际请求 | ||
133 | * @param {*} params | ||
134 | * @returns | ||
135 | */ | ||
136 | function doRequest(params) { | ||
137 | return new Promise((resolve, reject) => { | ||
138 | let { | ||
139 | loading, | ||
140 | toast, | ||
141 | mode, | ||
142 | url, | ||
143 | data, | ||
144 | method, | ||
145 | responseType, | ||
146 | enc | ||
147 | } = params; | ||
148 | let baseUrl = config.NET_CONFIG.BASE_API + config.NET_CONFIG.API_PREFIX; | ||
149 | |||
150 | // 使用通用接口前缀 | ||
151 | if (mode == "common") baseUrl = config.NET_CONFIG.COMMON_API; | ||
152 | // 自定义前缀,即不使用前缀 | ||
153 | if (mode == "custom") baseUrl = ""; | ||
154 | if (loading && mode != 'log') my.showLoading({ | ||
155 | content: '加载中', | ||
156 | mask: true | ||
157 | }); | ||
158 | |||
159 | // 判断是否开启post方法默认加密 | ||
160 | if (config.NET_CONFIG.IS_POST_ENC && (method == "post" || method == "POST")) { | ||
161 | enc = true; | ||
162 | } | ||
163 | if (enc) data = Encrypt.makeEncrypt(data); | ||
164 | |||
165 | // 设置请求头 | ||
166 | let header = { | ||
167 | '-kd-platform-env': config.ENV, | ||
168 | '-kd-platform-module': config.NET_CONFIG.MODULE_CODE, | ||
169 | 'sessionId': Storage.getItem("sessionId") | ||
170 | } | ||
171 | |||
172 | my.request({ | ||
173 | url: baseUrl + url, //请求地址 | ||
174 | data: data, //自定义参数 | ||
175 | method: method || 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT | ||
176 | header: header, | ||
177 | responseType: responseType, | ||
178 | success: (result) => { | ||
179 | // 日志上传不需要处理结果 | ||
180 | if (mode == 'log') return; | ||
181 | let res = result.data; | ||
182 | if (responseType == "arraybuffer") { | ||
183 | if (loading) my.hideLoading(); | ||
184 | resolve(res) | ||
185 | } else if (res.code === 200) { | ||
186 | if (loading) my.hideLoading(); | ||
187 | resolve(res.content); | ||
188 | } else { | ||
189 | my.hideLoading(); | ||
190 | // 404 不需要toast | ||
191 | if (toast && res.code != 404) { | ||
192 | my.showToast({ | ||
193 | content: res.errMsg || errMsg, | ||
194 | icon: 'none' | ||
195 | }) | ||
196 | } | ||
197 | reject(res); | ||
198 | } | ||
199 | }, | ||
200 | fail: (err) => { | ||
201 | my.hideLoading(); | ||
202 | } | ||
203 | }); | ||
204 | }); | ||
205 | } | ||
206 | |||
207 | |||
208 | |||
209 | // -------- 业务接口 Start -------- | ||
210 | |||
211 | /** | ||
212 | * 上传文件到恪道 | ||
213 | * @param {*} filePath 图片地址 | ||
214 | * @param {*} subPath 上传目录 (此参数为空则使用 oss目录) | ||
215 | */ | ||
216 | function uploadFile(filePath, subPath) { | ||
217 | return new Promise((resolve, reject) => { | ||
218 | if (!subPath && !config.NET_CONFIG.OSS_PATH) { | ||
219 | throw new Error('请配置上传目录 !'); | ||
220 | reject(); | ||
221 | return; | ||
222 | } | ||
223 | my.uploadFile({ | ||
224 | |||
225 | url: config.NET_CONFIG.BASE_API + config.NET_CONFIG.API_PREFIX + api.uploadFile, | ||
226 | filePath: filePath, | ||
227 | name: 'file', | ||
228 | header: { | ||
229 | 'content-type': 'multipart/form-data', | ||
230 | '-kd-platform-env': config.ENV, | ||
231 | '-kd-platform-module': config.NET_CONFIG.MODULE_CODE, | ||
232 | }, | ||
233 | formData: { | ||
234 | subPath: subPath || config.NET_CONFIG.OSS_PATH | ||
235 | }, | ||
236 | success(res) { | ||
237 | let result = JSON.parse(res.data).content; | ||
238 | resolve(result); | ||
239 | }, | ||
240 | fail() { | ||
241 | reject() | ||
242 | }, | ||
243 | complete() {} | ||
244 | }) | ||
245 | }); | ||
246 | } | ||
247 | |||
248 | |||
249 | /** | ||
250 | * 上传多个文件到服务器 | ||
251 | * urlList 需要上传的图片地址 (my.chooseImage 的 paths列表) | ||
252 | * | ||
253 | */ | ||
254 | function uploadFileMultiple(filePathList, subPath) { | ||
255 | return new Promise((resolve, reject) => { | ||
256 | if (!subPath && !config.NET_CONFIG.OSS_PATH) { | ||
257 | throw new Error('请配置上传目录 !'); | ||
258 | reject(); | ||
259 | return; | ||
260 | } | ||
261 | console.log("config.NET_CONFIG.COMMON_API + api.uploadFile:", config.NET_CONFIG.COMMON_API + api.uploadFile); | ||
262 | my.showLoading({ | ||
263 | content: `加载中` | ||
264 | }) | ||
265 | console.log("filePathList:", filePathList); | ||
266 | if (filePathList && filePathList.length > 0) { | ||
267 | let promiseList = []; | ||
268 | filePathList.forEach(element => { | ||
269 | let promiseItem = new Promise((resolve2, reject2) => { | ||
270 | uploadFile(element, subPath).then((result2) => { | ||
271 | resolve2(result2) | ||
272 | }).catch((err) => { | ||
273 | reject2(); | ||
274 | }); | ||
275 | }); | ||
276 | promiseList.push(promiseItem); | ||
277 | }); | ||
278 | console.log("promiseList:", promiseList); | ||
279 | Promise.all(promiseList).then(uploadFiles => { | ||
280 | my.hideLoading() | ||
281 | resolve(uploadFiles) | ||
282 | }, reason => { | ||
283 | my.hideLoading() | ||
284 | reject(); | ||
285 | }); | ||
286 | } else { | ||
287 | my.hideLoading() | ||
288 | resolve([]); | ||
289 | } | ||
290 | }); | ||
291 | } | ||
292 | |||
293 | module.exports = { | ||
294 | fetchMethod, | ||
295 | uploadFile, | ||
296 | uploadFileMultiple | ||
297 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
images/form/form-bg-1.png
0 → 100644
14.1 KB
images/form/form-bg-2.png
0 → 100644
16.1 KB
images/form/form-bg-succ.png
0 → 100644
13.8 KB
images/form/icon-question.png
0 → 100644
899 Bytes
images/form/icon-succ.png
0 → 100644
16.3 KB
images/form/submit-btn.png
0 → 100644
18.2 KB
images/index/index-bg-1.png
0 → 100644
132 KB
images/index/index-bg-2.png
0 → 100644
498 KB
images/index/number-item-bg.png
0 → 100644
6.67 KB
images/index/page-btn-next.png
0 → 100644
4.12 KB
images/index/page-btn-prev.png
0 → 100644
4 KB
images/index/search-icon.png
0 → 100644
506 Bytes
images/index/search-wrap-bg.png
0 → 100644
4.03 KB
mini.project.json
0 → 100644
pages/demo/demo.acss
0 → 100644
File mode changed
pages/demo/demo.axml
0 → 100644
pages/demo/demo.js
0 → 100644
1 | Page({ | ||
2 | onLoad(query) { | ||
3 | // 页面加载 | ||
4 | console.info(`Page onLoad with query: ${JSON.stringify(query)}`); | ||
5 | }, | ||
6 | onReady() { | ||
7 | // 页面加载完成 | ||
8 | }, | ||
9 | onShow() { | ||
10 | // 页面显示 | ||
11 | }, | ||
12 | onHide() { | ||
13 | // 页面隐藏 | ||
14 | }, | ||
15 | onUnload() { | ||
16 | // 页面被关闭 | ||
17 | }, | ||
18 | onTitleClick() { | ||
19 | // 标题被点击 | ||
20 | }, | ||
21 | onPullDownRefresh() { | ||
22 | // 页面被下拉 | ||
23 | }, | ||
24 | onReachBottom() { | ||
25 | // 页面被拉到底部 | ||
26 | }, | ||
27 | onShareAppMessage() { | ||
28 | // 返回自定义分享信息 | ||
29 | return { | ||
30 | title: 'My App', | ||
31 | desc: 'My App description', | ||
32 | path: 'pages/index/index', | ||
33 | }; | ||
34 | }, | ||
35 | }); |
pages/demo/demo.json
0 → 100644
1 | {} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
pages/index/index.acss
0 → 100644
1 | .top-space { | ||
2 | height: 0; | ||
3 | } | ||
4 | |||
5 | .page { | ||
6 | font-size: 0; | ||
7 | padding-bottom: 124rpx; | ||
8 | } | ||
9 | |||
10 | .main { | ||
11 | /* font-size: 28rpx; */ | ||
12 | } | ||
13 | |||
14 | .ebg { | ||
15 | font-size: 0; | ||
16 | width: 750rpx; | ||
17 | position: relative; | ||
18 | z-index: 11; | ||
19 | } | ||
20 | |||
21 | .table { | ||
22 | width: 750rpx; | ||
23 | height: 1120rpx; | ||
24 | background-image: linear-gradient(to top, #ede9ff, #d6c0ff); | ||
25 | box-sizing: border-box; | ||
26 | margin: 0px auto 0; | ||
27 | } | ||
28 | |||
29 | .func-wrap { | ||
30 | background: url('/images/index/search-wrap-bg.png') center no-repeat; | ||
31 | background-size: 100% 100%; | ||
32 | width: 701rpx; | ||
33 | height: 311rpx; | ||
34 | margin: 0 auto; | ||
35 | box-sizing: border-box; | ||
36 | padding-top: 60rpx; | ||
37 | } | ||
38 | |||
39 | .search-wrap { | ||
40 | width: 608rpx; | ||
41 | height: 58rpx; | ||
42 | border-radius: 16rpx; | ||
43 | border: solid 1rpx #905cff; | ||
44 | background-color: #fcf8ff; | ||
45 | margin: 0 auto 0; | ||
46 | display: flex; | ||
47 | justify-content: space-between; | ||
48 | align-items: center; | ||
49 | padding: 0rpx 0rpx 0rpx 19rpx; | ||
50 | } | ||
51 | |||
52 | .search-icon { | ||
53 | background: url('/images/index/search-icon.png') center no-repeat; | ||
54 | background-size: 100% 100%; | ||
55 | width: 32rpx; | ||
56 | height: 32rpx; | ||
57 | /* margin: 0rpx 19rpx 0rpx 12rpx; */ | ||
58 | } | ||
59 | |||
60 | .search-input { | ||
61 | flex: 1; | ||
62 | background-color: transparent; | ||
63 | padding: 0 12rpx; | ||
64 | box-sizing: border-box; | ||
65 | } | ||
66 | |||
67 | .search-btn { | ||
68 | width: 153rpx; | ||
69 | height: 58rpx; | ||
70 | line-height: 58rpx; | ||
71 | border-radius: 16rpx; | ||
72 | background-image: linear-gradient(to top, #be8bff, #7934ff); | ||
73 | text-align: center; | ||
74 | color: #fff; | ||
75 | font-weight: bold; | ||
76 | font-size: 30rpx; | ||
77 | } | ||
78 | |||
79 | .tag-list { | ||
80 | width: 614rpx; | ||
81 | margin: 21rpx auto 0; | ||
82 | display: flex; | ||
83 | flex-wrap: wrap; | ||
84 | } | ||
85 | |||
86 | .tag-list :nth-child(4n) { | ||
87 | margin-right: 0rpx; | ||
88 | } | ||
89 | |||
90 | .tag-item { | ||
91 | width: 140rpx; | ||
92 | height: 49rpx; | ||
93 | line-height: 50rpx; | ||
94 | border-radius: 21rpx; | ||
95 | text-align: center; | ||
96 | color: #fff; | ||
97 | font-weight: bold; | ||
98 | background-image: linear-gradient(to top, #be8bff, #7934ff); | ||
99 | margin-right: 18rpx; | ||
100 | margin-bottom: 11rpx; | ||
101 | font-size: 28rpx; | ||
102 | } | ||
103 | |||
104 | .tag-item-act { | ||
105 | background-image: linear-gradient(to top, #ff0072, #ff00a2); | ||
106 | } | ||
107 | |||
108 | /* 号码 */ | ||
109 | .number-wrap { | ||
110 | margin: 24rpx auto 0; | ||
111 | padding: 0 16rpx; | ||
112 | box-sizing: border-box; | ||
113 | position: relative; | ||
114 | z-index: 21; | ||
115 | height: 660rpx; | ||
116 | } | ||
117 | |||
118 | .number-list { | ||
119 | display: flex; | ||
120 | align-items: center; | ||
121 | justify-content: space-between; | ||
122 | flex-wrap: wrap; | ||
123 | /* max-height: 660rpx; */ | ||
124 | /* height: 660rpx; */ | ||
125 | overflow-y: hidden; | ||
126 | } | ||
127 | |||
128 | .number-item { | ||
129 | width: 341rpx; | ||
130 | height: 114rpx; | ||
131 | background: url('/images/index/number-item-bg.png') center no-repeat; | ||
132 | background-size: 100% 100%; | ||
133 | margin: 0 9rpx 18rpx; | ||
134 | font-size: 48rpx; | ||
135 | color: #fff; | ||
136 | font-weight: bold; | ||
137 | box-sizing: border-box; | ||
138 | text-align: center; | ||
139 | padding-top: 8rpx; | ||
140 | } | ||
141 | |||
142 | .number-item .text { | ||
143 | font-size: 48rpx; | ||
144 | color: #fff; | ||
145 | } | ||
146 | |||
147 | .number-item .highlight { | ||
148 | color: #fcff04; | ||
149 | } | ||
150 | |||
151 | .page-btn-wrap { | ||
152 | margin: 26rpx auto 0; | ||
153 | |||
154 | display: flex; | ||
155 | align-items: center; | ||
156 | justify-content: center; | ||
157 | } | ||
158 | |||
159 | .page-btn { | ||
160 | width: 184rpx; | ||
161 | height: 69rpx; | ||
162 | margin: 0 8px; | ||
163 | } | ||
164 | |||
165 | .btn-prev { | ||
166 | background: url('/images/index/page-btn-prev.png') center no-repeat; | ||
167 | background-size: 100% 100%; | ||
168 | } | ||
169 | |||
170 | .btn-next { | ||
171 | background: url('/images/index/page-btn-next.png') center no-repeat; | ||
172 | background-size: 100% 100%; | ||
173 | } | ||
174 | |||
175 | |||
176 | /* 弹窗框 */ | ||
177 | .popup { | ||
178 | position: fixed; | ||
179 | z-index: 1001; | ||
180 | top: 0; | ||
181 | left: 0; | ||
182 | width: 100vw; | ||
183 | height: 100vh; | ||
184 | display: flex; | ||
185 | justify-content: center; | ||
186 | align-items: center; | ||
187 | } | ||
188 | |||
189 | .popup .popup-mask { | ||
190 | position: fixed; | ||
191 | width: 100vw; | ||
192 | height: 100vh; | ||
193 | background-color: #000000; | ||
194 | opacity: .7; | ||
195 | } | ||
196 | |||
197 | .popup .dialog { | ||
198 | position: relative; | ||
199 | } | ||
200 | |||
201 | text { | ||
202 | color: #333; | ||
203 | font-size: 30rpx; | ||
204 | } | ||
205 | |||
206 | .highlight { | ||
207 | color: red; | ||
208 | } | ||
209 | |||
210 | .bot-btn { | ||
211 | background: url('/images/form/submit-btn.png') center no-repeat; | ||
212 | background-size: 100% 100%; | ||
213 | width: 630rpx; | ||
214 | height: 102rpx; | ||
215 | |||
216 | position: fixed; | ||
217 | left: 0; | ||
218 | right: 0; | ||
219 | bottom: 40rpx; | ||
220 | margin: auto; | ||
221 | z-index: 111; | ||
222 | } | ||
223 | |||
224 | |||
225 | .ani-heart { | ||
226 | animation: ani-heart-key 1.2s linear infinite; | ||
227 | } | ||
228 | |||
229 | @keyframes ani-heart-key { | ||
230 | 0% { | ||
231 | transform: scale(1); | ||
232 | } | ||
233 | |||
234 | 50% { | ||
235 | transform: scale(1.04); | ||
236 | } | ||
237 | |||
238 | 100% { | ||
239 | transform: scale(1); | ||
240 | } | ||
241 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
pages/index/index.axml
0 → 100644
1 | <view class="page"> | ||
2 | <view class="app__bgc bgc"></view> | ||
3 | <view class="app__bg bg"></view> | ||
4 | <view class="app__content main"> | ||
5 | <view class="top-space"></view> | ||
6 | <image class="ebg" mode="widthFix" src="/images/index/index-bg-1.png" /> | ||
7 | <view class="content"> | ||
8 | <view class="table"> | ||
9 | <view class="func-wrap"> | ||
10 | <view class="search-wrap"> | ||
11 | <view class="search-icon"></view> | ||
12 | <input | ||
13 | onInput="inputEdit" | ||
14 | onConfirm="onSearchConfirm" | ||
15 | data-name="queryForm.query" | ||
16 | value="{{queryForm.query}}" | ||
17 | class="search-input" | ||
18 | placeholder="请输入您喜欢的数字" | ||
19 | type="number" | ||
20 | /> | ||
21 | <view onTap="onSearch" class="search-btn"> | ||
22 | 搜 索 | ||
23 | </view> | ||
24 | </view> | ||
25 | <view class="tag-list"> | ||
26 | <view | ||
27 | a:for="{{ tagList }}" | ||
28 | onTap="onTagItem" | ||
29 | data-data="{{item}}" | ||
30 | data-index="{{index}}" | ||
31 | class="tag-item {{ tagIndex == index ? 'tag-item-act' : '' }}" | ||
32 | style="font-size: {{ item.fontSize || 28 }}rpx;" | ||
33 | > | ||
34 | {{item.name}} | ||
35 | </view> | ||
36 | </view> | ||
37 | </view> | ||
38 | |||
39 | <view class="number-wrap"> | ||
40 | <view class="number-list"> | ||
41 | <view | ||
42 | a:for="{{ numberList }}" | ||
43 | onTap="onNumberItem" | ||
44 | data-data="{{item}}" | ||
45 | data-index="{{index}}" | ||
46 | class="number-item" | ||
47 | > | ||
48 | <text a:for="{{ item.numberDisplayList }}" class="text {{item.highlight ? 'highlight' : ''}}"> | ||
49 | {{item.number}} | ||
50 | </text> | ||
51 | </view> | ||
52 | </view> | ||
53 | </view> | ||
54 | |||
55 | <view class="page-btn-wrap"> | ||
56 | <view onTap="onPagePrev" class="page-btn btn-prev"> | ||
57 | |||
58 | </view> | ||
59 | <view onTap="onPageNext" class="page-btn btn-next"> | ||
60 | |||
61 | </view> | ||
62 | </view> | ||
63 | </view> | ||
64 | </view> | ||
65 | <image class="ebg" mode="widthFix" src="/images/index/index-bg-2.png" /> | ||
66 | <view a:if="{{ shortCutVisible }}" onTap="toTop" class="bot-btn ani-heart"></view> | ||
67 | </view> | ||
68 | </view> | ||
69 | |||
70 | <view hidden="{{ !formVisible }}" class="popup"> | ||
71 | <view catchTap="onHideMask" class="popup-mask"></view> | ||
72 | <view class="dialog"> | ||
73 | <form-comp item="{{curNumberItem}}" onChange="evtcomp"></form-comp> | ||
74 | </view> | ||
75 | </view> | ||
76 | |||
77 | <view a:if="{{ succVisible }}" class="popup"> | ||
78 | <view catchTap="onHideMask" class="popup-mask"></view> | ||
79 | <view class="dialog"> | ||
80 | <succ-comp></succ-comp> | ||
81 | </view> | ||
82 | </view> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
pages/index/index.js
0 → 100644
1 | let app = getApp(); | ||
2 | |||
3 | // import { | ||
4 | // mobile_list | ||
5 | // } from '/const/index'; | ||
6 | |||
7 | |||
8 | // import { | ||
9 | // areas | ||
10 | // } from '/const/area-new'; | ||
11 | |||
12 | Page({ | ||
13 | |||
14 | data: { | ||
15 | queryForm: { | ||
16 | query: "", | ||
17 | }, | ||
18 | |||
19 | formVisible: false, | ||
20 | succVisible: false, | ||
21 | shortCutVisible: false, | ||
22 | |||
23 | tagIndex: 0, | ||
24 | tagList: [{ | ||
25 | name: "推荐", | ||
26 | val: "", | ||
27 | }, | ||
28 | { | ||
29 | name: "AAA+", | ||
30 | val: "AAA+", | ||
31 | }, | ||
32 | { | ||
33 | name: "AABB+", | ||
34 | val: "AABB+", | ||
35 | }, | ||
36 | { | ||
37 | name: "ABAB+", | ||
38 | val: "ABAB+", | ||
39 | }, | ||
40 | { | ||
41 | name: "ABBA", | ||
42 | val: "ABBA", | ||
43 | }, | ||
44 | { | ||
45 | name: "ABCAB", | ||
46 | val: "ABCAB", | ||
47 | }, | ||
48 | { | ||
49 | name: "ABCD", | ||
50 | val: "ABCD", | ||
51 | }, | ||
52 | { | ||
53 | name: "尾号6/8/9", | ||
54 | val: "LAST689", | ||
55 | fontSize: 26 | ||
56 | }, | ||
57 | ], | ||
58 | |||
59 | page: 1, | ||
60 | size: 10, | ||
61 | totalPages: 0, | ||
62 | |||
63 | // 总号码池 | ||
64 | numberPool: [], | ||
65 | // 命中池 | ||
66 | targetNumberList: [], | ||
67 | // 号码列表,当前展示号码 | ||
68 | numberList: [], | ||
69 | // 当前选择号码 | ||
70 | curNumberItem: null, | ||
71 | }, | ||
72 | onLoad(query) { | ||
73 | |||
74 | this.initData(); | ||
75 | |||
76 | // let area = {}; | ||
77 | // let province_list = {}; | ||
78 | // let city_list = {}; | ||
79 | // let county_list = {}; | ||
80 | // areas.forEach(element => { | ||
81 | // province_list[element[0]] = element[1] | ||
82 | // city_list[element[2]] = element[3] | ||
83 | // county_list[element[4]] = element[5] | ||
84 | // }); | ||
85 | // area.province_list = province_list; | ||
86 | // area.city_list = city_list; | ||
87 | // area.county_list = county_list; | ||
88 | // console.log(area); | ||
89 | |||
90 | }, | ||
91 | async initData() { | ||
92 | let numberPool = await this.getSelectNumberList(); | ||
93 | app.func.sortByLength(numberPool) | ||
94 | this.data.targetNumberList = numberPool; | ||
95 | this.data.page = 1; | ||
96 | this.refreshPage(); | ||
97 | |||
98 | |||
99 | // let beautyResAAA = app.func.checkBeautyNumberAAA('15014443959'); | ||
100 | // console.log("beautyResAAA:", beautyResAAA); | ||
101 | |||
102 | // let beautyResAABB = app.func.checkBeautyNumberAABB('15011337986'); | ||
103 | // console.log("beautyResAABB:", beautyResAABB); | ||
104 | |||
105 | // let beautyResABAB = app.func.checkBeautyNumberABAB('15056563959'); | ||
106 | // console.log("beautyResABAB:", beautyResABAB); | ||
107 | |||
108 | // let beautyResABBA = app.func.checkBeautyNumberABBA('15056653959'); | ||
109 | // console.log("beautyResABBA:", beautyResABBA); | ||
110 | |||
111 | // let beautyResABCAB = app.func.checkBeautyNumberABCAB('15056756959'); | ||
112 | // console.log("beautyResABCAB:", beautyResABCAB); | ||
113 | |||
114 | // let beautyResABCD = app.func.checkBeautyNumberABCD('15054323959'); | ||
115 | // console.log("beautyResABCD:", beautyResABCD); | ||
116 | |||
117 | // let beautyResLast = app.func.checkBeautyNumberLast('15054323959'); | ||
118 | // console.log("beautyResLast:", beautyResLast); | ||
119 | }, | ||
120 | |||
121 | // 页面滚动 | ||
122 | onPageScroll(e) { | ||
123 | let shortCutVisible = e.scrollTop > 700; | ||
124 | this.setData({ | ||
125 | shortCutVisible | ||
126 | }); | ||
127 | }, | ||
128 | |||
129 | toTop() { | ||
130 | console.log("toTop"); | ||
131 | my.pageScrollTo({ | ||
132 | scrollTop: 0, | ||
133 | duration: 300 | ||
134 | }) | ||
135 | }, | ||
136 | |||
137 | async onSearch() { | ||
138 | let numberPool = await this.getSelectNumberList(); | ||
139 | this.setData({ | ||
140 | tagIndex: 0 | ||
141 | }) | ||
142 | // numberPool = app.util.shuffleArray(numberPool); | ||
143 | this.data.targetNumberList = numberPool; | ||
144 | this.data.page = 1; | ||
145 | this.refreshPage(); | ||
146 | }, | ||
147 | |||
148 | onSearchConfirm() { | ||
149 | this.onSearch(); | ||
150 | }, | ||
151 | |||
152 | /** | ||
153 | * 获取 | ||
154 | */ | ||
155 | async getSelectNumberList() { | ||
156 | let res = await app.get({ | ||
157 | url: app.api.selectNum, | ||
158 | data: this.data.queryForm, | ||
159 | loading: true, | ||
160 | }); | ||
161 | // console.log(res); | ||
162 | let funcList = [ | ||
163 | app.func.checkBeautyNumberAAA, | ||
164 | app.func.checkBeautyNumberAABB, | ||
165 | app.func.checkBeautyNumberABAB, | ||
166 | app.func.checkBeautyNumberABBA, | ||
167 | app.func.checkBeautyNumberABCAB, | ||
168 | app.func.checkBeautyNumberABCD, | ||
169 | app.func.checkBeautyNumberLast, | ||
170 | ] | ||
171 | |||
172 | res.forEach(element => { | ||
173 | element.beautyList = [] | ||
174 | element.beautyObj = {} | ||
175 | funcList.forEach(funElement => { | ||
176 | let beautyRes = funElement(element.mobile); | ||
177 | if (beautyRes.beautyNum) { | ||
178 | element.beautyList.push(beautyRes); | ||
179 | element.beautyObj[beautyRes.type] = beautyRes; | ||
180 | } | ||
181 | }); | ||
182 | }); | ||
183 | |||
184 | let numberPool = res.concat(this.data.numberPool); | ||
185 | numberPool = app.util.uniqueArray(numberPool); | ||
186 | this.data.numberPool = numberPool; | ||
187 | return numberPool; | ||
188 | }, | ||
189 | |||
190 | // 点击标签 | ||
191 | onTagItem(evt) { | ||
192 | let item = app.tapData(evt); | ||
193 | let index = app.tapData(evt, "index"); | ||
194 | this.setData({ | ||
195 | queryForm: { | ||
196 | query: "", | ||
197 | }, | ||
198 | tagIndex: index, | ||
199 | }) | ||
200 | |||
201 | let numberPool = this.data.numberPool; | ||
202 | numberPool = app.util.shuffleArray(numberPool); | ||
203 | |||
204 | if (item.val) { | ||
205 | let targetNumberList = [] | ||
206 | numberPool.forEach(element => { | ||
207 | if (element.beautyObj[item.val]) { | ||
208 | targetNumberList.push(element); | ||
209 | } | ||
210 | }); | ||
211 | |||
212 | targetNumberList = targetNumberList.concat(numberPool); | ||
213 | targetNumberList = app.util.uniqueArray(targetNumberList); | ||
214 | this.data.targetNumberList = targetNumberList; | ||
215 | } else { | ||
216 | |||
217 | // app.func.sortByLength(numberPool) | ||
218 | this.data.targetNumberList = numberPool; | ||
219 | } | ||
220 | |||
221 | this.data.page = 1; | ||
222 | this.refreshPage(); | ||
223 | }, | ||
224 | |||
225 | /** | ||
226 | * 点击号码 | ||
227 | */ | ||
228 | onNumberItem(evt) { | ||
229 | let item = app.tapData(evt); | ||
230 | item.featureName = app.func.getFeatureName(item.mobile) | ||
231 | this.setData({ | ||
232 | curNumberItem: item, | ||
233 | formVisible: true, | ||
234 | }) | ||
235 | }, | ||
236 | |||
237 | |||
238 | // 上一页 | ||
239 | onPagePrev() { | ||
240 | this.data.page--; | ||
241 | if (this.data.page < 1) { | ||
242 | this.data.page = this.data.totalPages; | ||
243 | // return; | ||
244 | }; | ||
245 | this.refreshPage(); | ||
246 | }, | ||
247 | // 下一页 | ||
248 | onPageNext() { | ||
249 | this.data.page++; | ||
250 | |||
251 | if (this.data.page > this.data.totalPages) { | ||
252 | this.data.page = 1; | ||
253 | // return; | ||
254 | } | ||
255 | this.refreshPage(); | ||
256 | }, | ||
257 | |||
258 | refreshPage() { | ||
259 | let listObj = app.util.paginateArray(this.data.targetNumberList, this.data.page, this.data.pageSize); | ||
260 | let curTag = this.data.tagList[this.data.tagIndex]; | ||
261 | let curTagVal = curTag.val; | ||
262 | let list = listObj.list; | ||
263 | |||
264 | let query = this.data.queryForm.query; | ||
265 | /** | ||
266 | * 高亮数字 | ||
267 | * | ||
268 | * 1、如果query中有值,按query的值 | ||
269 | * 2、如果标签有值,按标签 | ||
270 | * 3、如果都没有,随机显示靓号 | ||
271 | */ | ||
272 | list.forEach(element => { | ||
273 | |||
274 | let beautyObj = null; | ||
275 | |||
276 | if (query) { | ||
277 | beautyObj = { | ||
278 | beautyNum: query, | ||
279 | index: element.mobile.indexOf(query), | ||
280 | len: query.length, | ||
281 | type: "query", | ||
282 | } | ||
283 | } else if (element.beautyObj[curTagVal]) { | ||
284 | beautyObj = element.beautyObj[curTagVal]; | ||
285 | } else { | ||
286 | // 默认靓号提示 | ||
287 | let len = element.beautyList.length; | ||
288 | if (len) { | ||
289 | beautyObj = element.beautyList[Math.floor(Math.random() * len)] || null | ||
290 | } | ||
291 | } | ||
292 | |||
293 | let numberDisplayList = [] | ||
294 | element.mobile.split("").forEach((ele, index) => { | ||
295 | let numberObj = { | ||
296 | number: ele, | ||
297 | highlight: beautyObj && index >= beautyObj.index && index <= beautyObj.index + beautyObj.len - 1, | ||
298 | } | ||
299 | numberDisplayList.push(numberObj); | ||
300 | }); | ||
301 | element.numberDisplayList = numberDisplayList; | ||
302 | }); | ||
303 | |||
304 | this.setData({ | ||
305 | numberList: list, | ||
306 | totalPages: listObj.totalPages, | ||
307 | }) | ||
308 | }, | ||
309 | |||
310 | |||
311 | /** | ||
312 | * input绑定 | ||
313 | * 多输入文本绑定 | ||
314 | * 在input/texarea中设置 data-name="属性值即可" | ||
315 | */ | ||
316 | inputEdit(e) { | ||
317 | let dataset = e.currentTarget.dataset; | ||
318 | let value = e.detail.value; | ||
319 | let name = dataset.name; | ||
320 | this.setData({ | ||
321 | [name]: value | ||
322 | }); | ||
323 | }, | ||
324 | |||
325 | |||
326 | evtcomp(evt) { | ||
327 | console.log("evtcomp evt:", evt) | ||
328 | let { | ||
329 | name, | ||
330 | data | ||
331 | } = evt; | ||
332 | // console.log("name:", name) | ||
333 | switch (name) { | ||
334 | case "_evt_hide": | ||
335 | this.hideMask(); | ||
336 | break; | ||
337 | case "_evt_submit_complete": | ||
338 | this.setData({ | ||
339 | formVisible: false, | ||
340 | succVisible: true, | ||
341 | }) | ||
342 | break; | ||
343 | } | ||
344 | }, | ||
345 | |||
346 | |||
347 | // 关闭蒙层 | ||
348 | onHideMask() { | ||
349 | this.setData({ | ||
350 | formVisible: false, | ||
351 | succVisible: false, | ||
352 | }) | ||
353 | }, | ||
354 | |||
355 | onShareAppMessage() { | ||
356 | // 返回自定义分享信息 | ||
357 | return { | ||
358 | title: '', | ||
359 | desc: '', | ||
360 | path: '', | ||
361 | }; | ||
362 | }, | ||
363 | }); | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
pages/index/index.json
0 → 100644
router/index.js
0 → 100644
1 | const routerPath = { | ||
2 | index: '/pages/index/index', | ||
3 | |||
4 | expCommon: '/pages/exp-common/exp-common', | ||
5 | expBus: '/pages/exp-bus/exp-bus', | ||
6 | expForm: '/pages/exp-form/exp-form', | ||
7 | article: '/pages/artcle/article', | ||
8 | |||
9 | example: '/pages/example/example', | ||
10 | more: '/pages/more/more', | ||
11 | } | ||
12 | |||
13 | function parse(data) { | ||
14 | let tempArr = []; | ||
15 | for (let key in data) { | ||
16 | tempArr.push(key + '=' + encodeURIComponent(data[key])); | ||
17 | } | ||
18 | return tempArr.join('&'); | ||
19 | } | ||
20 | |||
21 | function push(path, option = {}) { | ||
22 | if (typeof path == 'string') { | ||
23 | option.path = path; //兼容无参数路径 | ||
24 | } else { | ||
25 | if (path.name) { | ||
26 | path.path = path.name; | ||
27 | } | ||
28 | option = path; | ||
29 | } | ||
30 | // console.log("option:", option); | ||
31 | // 配置key值找到对应path | ||
32 | let url = routerPath[option.path] || routerPath['index']; | ||
33 | // console.log("url:", url); | ||
34 | // 读取传入的配置参数 | ||
35 | let { | ||
36 | query = {}, openType = 'navigate', duration = 0 | ||
37 | } = option; | ||
38 | // json 转换为 字符串拼接参数 | ||
39 | let params = parse(query) | ||
40 | // console.log("params:", params); | ||
41 | if (params) { | ||
42 | url = url + '?' + params; | ||
43 | } | ||
44 | // 是否需要延时跳转 | ||
45 | duration ? setTimeout(() => { | ||
46 | to(openType, url); | ||
47 | }, duration) : to(openType, url); | ||
48 | } | ||
49 | |||
50 | function to(openType, url) { | ||
51 | let obj = { | ||
52 | url | ||
53 | }; | ||
54 | |||
55 | if (openType == 'redirect') { | ||
56 | my.redirectTo(obj); | ||
57 | } else if (openType == 'reLaunch') { | ||
58 | my.reLaunch(obj); | ||
59 | } else if (openType == 'switchTab') { | ||
60 | my.switchTab(obj); | ||
61 | } else if (openType == 'back') { | ||
62 | my.navigateBack({ | ||
63 | delta: 1 | ||
64 | }); | ||
65 | } else { | ||
66 | my.navigateTo(obj); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | module.exports = { | ||
71 | parse, | ||
72 | push, | ||
73 | to | ||
74 | } |
utils/enc/crypto-js.min.js
0 → 100644
This diff is collapsed.
Click to expand it.
utils/enc/enc.js
0 → 100644
1 | const config = require('./../../config'); | ||
2 | const CryptoJS = require('./crypto-js.min'); | ||
3 | const Encrypt = require('./jsencrypt.min'); | ||
4 | |||
5 | var rsa = new Encrypt.JSEncrypt(); | ||
6 | |||
7 | function makeEncrypt(param) { | ||
8 | |||
9 | let key = config.NET_CONFIG.RSA_PUBLIC_KEY; // 公钥 | ||
10 | let iv = config.NET_CONFIG.AES_IV; // 偏移量 | ||
11 | |||
12 | rsa.setPublicKey(key); | ||
13 | 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(","); | ||
14 | |||
15 | function randomAesKey() { | ||
16 | let res = ""; | ||
17 | for (let i = 0; i < 16; i++) { | ||
18 | let id = Math.ceil(Math.random() * (chars.length - 1)); | ||
19 | res += chars[id]; | ||
20 | } | ||
21 | 1 | ||
22 | return res; | ||
23 | }; | ||
24 | |||
25 | function encryptContent(obj) { | ||
26 | let aesKey = randomAesKey(); | ||
27 | let key = CryptoJS.enc.Utf8.parse(aesKey); | ||
28 | let ivR = CryptoJS.enc.Utf8.parse(iv); | ||
29 | var encrypted = CryptoJS.AES.encrypt(JSON.stringify(obj), key, { | ||
30 | iv: ivR, | ||
31 | mode: CryptoJS.mode.CBC, | ||
32 | padding: CryptoJS.pad.Pkcs7 | ||
33 | }); | ||
34 | let content = encrypted.toString(); //返回的是base64格式的密文 | ||
35 | let securityKey = rsa.encrypt(aesKey); | ||
36 | |||
37 | let result = { | ||
38 | k: securityKey, | ||
39 | v: content | ||
40 | }; | ||
41 | return result; | ||
42 | }; | ||
43 | let data = encryptContent(param) | ||
44 | return data; | ||
45 | } | ||
46 | |||
47 | module.exports = { | ||
48 | makeEncrypt | ||
49 | } |
utils/enc/jsencrypt.min.js
0 → 100755
This diff is collapsed.
Click to expand it.
utils/func.js
0 → 100644
1 | // 不命中统一返回 | ||
2 | const NOT_MATCH_OBJ = { | ||
3 | beautyNum: "", | ||
4 | index: -1, | ||
5 | len: 0 | ||
6 | } | ||
7 | |||
8 | // 验证AABB | ||
9 | export function checkBeautyNumberAAA(phone) { | ||
10 | var reg = new RegExp('(.)\\1{2}', "g"); | ||
11 | if (phone.match(reg) != null) { | ||
12 | var result = phone.match(reg)[0].toString(); | ||
13 | return { | ||
14 | beautyNum: result, | ||
15 | index: phone.indexOf(result), | ||
16 | len: result.length, | ||
17 | type: "AAA+", | ||
18 | } | ||
19 | } | ||
20 | return NOT_MATCH_OBJ | ||
21 | } | ||
22 | |||
23 | // 验证AABB | ||
24 | export function checkBeautyNumberAABB(phone) { | ||
25 | var reg = new RegExp("(\\d)\\1((?!\\1)\\d)\\2", "g"); | ||
26 | if (phone.match(reg) != null) { | ||
27 | var result = phone.match(reg)[0].toString(); | ||
28 | return { | ||
29 | beautyNum: result, | ||
30 | index: phone.indexOf(result), | ||
31 | len: result.length, | ||
32 | type: "AABB+", | ||
33 | } | ||
34 | } | ||
35 | return NOT_MATCH_OBJ | ||
36 | } | ||
37 | |||
38 | // 验证ABAB | ||
39 | export function checkBeautyNumberABAB(phone) { | ||
40 | var reg = new RegExp("(\\d)((?!\\1)\\d)\\1\\2", "g"); | ||
41 | if (phone.match(reg) != null) { | ||
42 | var result = phone.match(reg)[0].toString(); | ||
43 | return { | ||
44 | beautyNum: result, | ||
45 | index: phone.indexOf(result), | ||
46 | len: result.length, | ||
47 | type: "ABAB+" | ||
48 | } | ||
49 | } | ||
50 | return NOT_MATCH_OBJ | ||
51 | } | ||
52 | |||
53 | |||
54 | // 验证AABB | ||
55 | export function checkBeautyNumberABBA(phone) { | ||
56 | var reg = new RegExp("(\\d)((?!\\1)\\d)\\2[\\d]", "g"); | ||
57 | if (phone.match(reg) != null) { | ||
58 | var result = phone.match(reg)[0].toString(); | ||
59 | if (result.substring(0, 1) == result.substring(3, 4)) { | ||
60 | return { | ||
61 | beautyNum: result, | ||
62 | index: phone.indexOf(result), | ||
63 | len: result.length, | ||
64 | type: "ABBA" | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | return NOT_MATCH_OBJ | ||
69 | } | ||
70 | |||
71 | |||
72 | // 验证ABCAB | ||
73 | export function checkBeautyNumberABCAB(phone) { | ||
74 | 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"); | ||
75 | if (phone.match(reg) != null) { | ||
76 | var result = phone.match(reg)[0].toString(); | ||
77 | if (result.substring(0, 2) == result.substring(3, 5)) { | ||
78 | return { | ||
79 | beautyNum: result, | ||
80 | index: phone.indexOf(result), | ||
81 | len: result.length, | ||
82 | type: "ABCAB" | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | return NOT_MATCH_OBJ | ||
87 | } | ||
88 | |||
89 | |||
90 | |||
91 | // 验证ABCD | ||
92 | export function checkBeautyNumberABCD(phone) { | ||
93 | var reg = new RegExp("(?:0123|1234|2345|3456|4567|5678|6789|7890|0987|9876|8765|7654|6543|5432|4321|3210)\\d", "g"); | ||
94 | if (phone.match(reg) != null) { | ||
95 | var result = phone.match(reg)[0].toString() | ||
96 | result = result.substring(0, 4); | ||
97 | return { | ||
98 | beautyNum: result, | ||
99 | index: phone.indexOf(result), | ||
100 | len: result.length, | ||
101 | type: "ABCD" | ||
102 | } | ||
103 | } | ||
104 | return NOT_MATCH_OBJ | ||
105 | } | ||
106 | |||
107 | |||
108 | // // 最后一位是6/8/9 | ||
109 | export function checkBeautyNumberLast(phone) { | ||
110 | const reg = new RegExp("\\d+[689]$"); | ||
111 | if (phone.match(reg) != null) { | ||
112 | return { | ||
113 | beautyNum: phone.slice(-1), | ||
114 | index: phone.length - 1, | ||
115 | len: 1, | ||
116 | type: "LAST689" | ||
117 | } | ||
118 | } | ||
119 | return NOT_MATCH_OBJ | ||
120 | } | ||
121 | |||
122 | // 获取吉祥口号 | ||
123 | export function getFeatureName(mobile) { | ||
124 | let featureName = { | ||
125 | 0: "寓意圆满", | ||
126 | 1: "大吉大利", | ||
127 | 2: "成双成对", | ||
128 | 3: "三生万物", | ||
129 | 4: "四季来财", | ||
130 | 5: "五福临门", | ||
131 | 6: "六六大顺", | ||
132 | 7: "升职加薪", | ||
133 | 8: "发财旺运", | ||
134 | 9: "富贵长久" | ||
135 | } | ||
136 | let num = mobile.slice(-1); | ||
137 | let result = featureName[num + '']; | ||
138 | return result; | ||
139 | } | ||
140 | |||
141 | export function sortByLength(array) { | ||
142 | array.sort((a, b) => a.beautyList.length > 0 ? -1 : 1); | ||
143 | } | ||
144 | |||
145 | // 支付宝省市区结构 | ||
146 | export function addressToTree(address) { | ||
147 | let districtssheng = address.province_list; | ||
148 | let districtsShi = address.city_list; | ||
149 | let districtsQu = address.county_list; | ||
150 | let newArrSheng = []; | ||
151 | for (var i in districtssheng) { | ||
152 | // 第一层循环遍历出省份 | ||
153 | let districtsShengObj = {} | ||
154 | districtsShengObj.id = i | ||
155 | districtsShengObj.name = districtssheng[i] | ||
156 | let newArrShi = [] | ||
157 | for (var s in districtsShi) { | ||
158 | //第二层循环出市 | ||
159 | if (i.substring(0, 2) === s.substring(0, 2)) { | ||
160 | // 以城市编码的前两位作为匹配项 | ||
161 | let shiobj = {}; | ||
162 | shiobj.id = s | ||
163 | shiobj.name = districtsShi[s] | ||
164 | let newArrQU = [] | ||
165 | for (var q in districtsQu) { | ||
166 | //第三层循环遍历出区 | ||
167 | if (s.substring(0, 4) == q.substring(0, 4)) { | ||
168 | //市与区以编码的前四位作为匹配 | ||
169 | let quobj = {}; | ||
170 | quobj.id = q | ||
171 | quobj.name = districtsQu[q] | ||
172 | newArrQU.push(quobj); | ||
173 | shiobj.subList = newArrQU; | ||
174 | } | ||
175 | } | ||
176 | newArrShi.push(shiobj); | ||
177 | districtsShengObj.subList = newArrShi; | ||
178 | //添加到所需的对象里 | ||
179 | } | ||
180 | } | ||
181 | newArrSheng.push(districtsShengObj) // 最后添加到数组里 | ||
182 | } | ||
183 | return newArrSheng; | ||
184 | } |
utils/stroage.js
0 → 100644
1 | function setItem(key, value, module_name) { | ||
2 | // console.log(key,value) | ||
3 | my.setStorageSync({ | ||
4 | key: key, | ||
5 | data: value | ||
6 | }); | ||
7 | |||
8 | // if (module_name) { | ||
9 | // let module_name_info = getItem(module_name) || {}; | ||
10 | // module_name_info[key] = value; | ||
11 | // try { | ||
12 | // my.setStorageSync(module_name, module_name_info); | ||
13 | // } catch (e) { | ||
14 | // my.setStorage({ | ||
15 | // key: module_name, | ||
16 | // data: module_name_info | ||
17 | // }) | ||
18 | // } | ||
19 | // } else { | ||
20 | // try { | ||
21 | // my.setStorageSync(key, value); | ||
22 | // } catch (e) { | ||
23 | // my.setStorage({ | ||
24 | // key: key, | ||
25 | // data: value | ||
26 | // }) | ||
27 | // } | ||
28 | // } | ||
29 | } | ||
30 | |||
31 | function getItem(key, module_name) { | ||
32 | // if (module_name) { | ||
33 | // let val = getItem(module_name); | ||
34 | // if (val) return val[key]; | ||
35 | // return ''; | ||
36 | // } | ||
37 | // return my.getStorageSync(key).data | ||
38 | return my.getStorageSync({ | ||
39 | key: key | ||
40 | }).data; | ||
41 | } | ||
42 | |||
43 | function clear(name) { | ||
44 | name ? my.removeStorageSync(name) : my.clearStorageSync() | ||
45 | } | ||
46 | |||
47 | module.exports = { | ||
48 | setItem, | ||
49 | getItem, | ||
50 | clear | ||
51 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
utils/util.js
0 → 100644
1 | // 正则 | ||
2 | const REGEXPS = { | ||
3 | "mobile": /^1\d{10}$/, | ||
4 | //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X。 | ||
5 | "identNo": /(^\d{15}$)|(^\d{17}([0-9]|X)$)/, | ||
6 | } | ||
7 | // 验证手机 | ||
8 | function checkMobile(str) { | ||
9 | return REGEXPS.mobile.test(str); | ||
10 | } | ||
11 | |||
12 | // 验证身份证 | ||
13 | function checkIdentNo(num) { | ||
14 | num = num.toUpperCase(); | ||
15 | return REGEXPS.identNo.test(num); | ||
16 | } | ||
17 | |||
18 | // 数组打乱顺序 | ||
19 | function randomSort(a, b) { | ||
20 | return Math.random() > 0.5 ? -1 : 1; | ||
21 | } | ||
22 | |||
23 | function shuffleArray(array) { | ||
24 | for (let i = array.length - 1; i > 0; i--) { | ||
25 | const j = Math.floor(Math.random() * (i + 1)); | ||
26 | [array[i], array[j]] = [array[j], array[i]]; | ||
27 | } | ||
28 | return array; | ||
29 | } | ||
30 | |||
31 | |||
32 | //普通生成uuid | ||
33 | function uuid() { | ||
34 | var s = []; | ||
35 | var hexDigits = "0123456789abcdef"; | ||
36 | for (var i = 0; i < 36; i++) { | ||
37 | s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); | ||
38 | } | ||
39 | s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010 | ||
40 | s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01 | ||
41 | s[8] = s[13] = s[18] = s[23] = "-"; | ||
42 | |||
43 | var uuid = s.join(""); | ||
44 | return uuid; | ||
45 | } | ||
46 | |||
47 | // 数组去重 | ||
48 | function uniqueArray(arr) { | ||
49 | return arr.reduce((result, item) => { | ||
50 | const duplicate = result.find(obj => JSON.stringify(obj) === JSON.stringify(item)); | ||
51 | if (!duplicate) { | ||
52 | result.push(item); | ||
53 | } | ||
54 | return result; | ||
55 | }, []); | ||
56 | } | ||
57 | |||
58 | // 模拟分页 | ||
59 | function paginateArray(arr, page, size = 10) { | ||
60 | const startIndex = (page - 1) * size; | ||
61 | const endIndex = startIndex + size; | ||
62 | const currentPageList = arr.slice(startIndex, endIndex); | ||
63 | const totalPages = Math.ceil(arr.length / size); | ||
64 | |||
65 | return { | ||
66 | list: currentPageList, | ||
67 | totalPages | ||
68 | }; | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * 链接参数转换为obj | ||
73 | * 入参 完整链接 | ||
74 | * @param {*} url | ||
75 | */ | ||
76 | function param2Obj(url) { | ||
77 | const search = url.split('?')[1] | ||
78 | if (!search) { | ||
79 | return {} | ||
80 | } | ||
81 | return JSON.parse( | ||
82 | '{"' + | ||
83 | decodeURIComponent(search) | ||
84 | .replace(/"/g, '\\"') | ||
85 | .replace(/&/g, '","') | ||
86 | .replace(/=/g, '":"') + | ||
87 | '"}' | ||
88 | ) | ||
89 | } | ||
90 | |||
91 | |||
92 | /** | ||
93 | * 分转元 | ||
94 | * @param {*} fen | ||
95 | * @returns | ||
96 | */ | ||
97 | export const regFenToYuan = (fen) => { | ||
98 | var num = fen; | ||
99 | num = fen * 0.01; | ||
100 | num += ''; | ||
101 | var reg = num.indexOf('.') > -1 ? /(\d{1,3})(?=(?:\d{3})+\.)/g : /(\d{1,3})(?=(?:\d{3})+$)/g; | ||
102 | num = num.replace(reg, '$1'); | ||
103 | num = toDecimal2(num) | ||
104 | return num | ||
105 | }; | ||
106 | |||
107 | /** | ||
108 | * 元转分 | ||
109 | * @param {*} yuan | ||
110 | * @param {*} digit | ||
111 | * @returns | ||
112 | */ | ||
113 | export const regYuanToFen = (yuan, digit = 100) => { | ||
114 | var m = 0, | ||
115 | s1 = yuan.toString(), | ||
116 | s2 = digit.toString(); | ||
117 | try { | ||
118 | m += s1.split(".")[1].length | ||
119 | } catch (e) {} | ||
120 | try { | ||
121 | m += s2.split(".")[1].length | ||
122 | } catch (e) {} | ||
123 | return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m) | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * 强制保留2位小数,如:2,会在2后面补上00.即2.00 | ||
128 | * @param {*} x | ||
129 | * @returns | ||
130 | */ | ||
131 | export const toDecimal2 = (x) => { | ||
132 | var f = parseFloat(x); | ||
133 | if (isNaN(f)) { | ||
134 | return false; | ||
135 | } | ||
136 | var f = Math.round(x * 100) / 100; | ||
137 | var s = f.toString(); | ||
138 | var rs = s.indexOf('.'); | ||
139 | if (rs < 0) { | ||
140 | rs = s.length; | ||
141 | s += '.'; | ||
142 | } | ||
143 | while (s.length <= rs + 2) { | ||
144 | s += '0'; | ||
145 | } | ||
146 | return s; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * 格式化数字,不足一位补充0 | ||
151 | * @param {*} n | ||
152 | */ | ||
153 | function formatNumber(n) { | ||
154 | n = n.toString() | ||
155 | return n[1] ? n : '0' + n | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * 获取屏幕剩余高度 | ||
160 | * useHeight 单位是rpx | ||
161 | * 默认返回单位是rpx 可通过unit参数改为 px | ||
162 | */ | ||
163 | function getLastScreenHeight(useHeight = 0, unit = 'rpx') { | ||
164 | let sysInfo = my.getSystemInfoSync(); | ||
165 | let clientHeight = sysInfo.windowHeight; | ||
166 | // 获取可使用窗口高度 | ||
167 | let clientWidth = sysInfo.windowWidth; | ||
168 | // 算出比例 | ||
169 | let ratio = 750 / clientWidth; | ||
170 | // 算出屏幕高度(单位rpx) | ||
171 | let height = clientHeight * ratio; | ||
172 | // 计算剩余高度 | ||
173 | let lastHeight = height - useHeight; | ||
174 | // 可转换成px | ||
175 | if (unit == 'px') { | ||
176 | lastHeight = lastHeight / 750 * clientWidth | ||
177 | } | ||
178 | return lastHeight; | ||
179 | } | ||
180 | |||
181 | |||
182 | /** | ||
183 | * px转rpx | ||
184 | * @param {*} value | ||
185 | */ | ||
186 | function pxToRpx(value) { | ||
187 | let sysInfo = my.getSystemInfoSync(); | ||
188 | let clientWidth = sysInfo.windowWidth; | ||
189 | let result = value / 750 * clientWidth | ||
190 | return result; | ||
191 | } | ||
192 | |||
193 | |||
194 | // 格式化星期几 | ||
195 | function formatWeek(week) { | ||
196 | let result = ""; | ||
197 | switch (week) { | ||
198 | case 1: | ||
199 | result = "一"; | ||
200 | break; | ||
201 | case 2: | ||
202 | result = "二"; | ||
203 | break; | ||
204 | case 3: | ||
205 | result = "三"; | ||
206 | break; | ||
207 | case 4: | ||
208 | result = "四"; | ||
209 | break; | ||
210 | case 5: | ||
211 | result = "五"; | ||
212 | break; | ||
213 | case 6: | ||
214 | result = "六"; | ||
215 | break; | ||
216 | case 0: | ||
217 | result = "日"; | ||
218 | break; | ||
219 | |||
220 | default: | ||
221 | break; | ||
222 | } | ||
223 | return result; | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * 格式化日期时间 支持Date和时间戳 | ||
228 | * @param {date} date 日期时间 | ||
229 | * @param {string} fmt 格式,如:'yyyy-MM-dd hh:mm:ss' | ||
230 | */ | ||
231 | function formatDate(date, fmt) { | ||
232 | if (!date) return '-' | ||
233 | // 把-换成/ 避免iOS和安卓真机问题 | ||
234 | |||
235 | if (isNaN(date)) { | ||
236 | var reg = /-/g; | ||
237 | date = date && date.replace(reg, '/'); | ||
238 | } | ||
239 | |||
240 | date = new Date(date) | ||
241 | const o = { | ||
242 | 'M+': date.getMonth() + 1, // 月份 | ||
243 | 'd+': date.getDate(), // 日 | ||
244 | 'h+': date.getHours(), // 小时 | ||
245 | 'm+': date.getMinutes(), // 分 | ||
246 | 's+': date.getSeconds(), // 秒 | ||
247 | 'q+': Math.floor((date.getMonth() + 3) / 3), // 季度 | ||
248 | S: date.getMilliseconds() // 毫秒 | ||
249 | } | ||
250 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)) | ||
251 | for (const k in o) { | ||
252 | if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))) | ||
253 | } | ||
254 | return fmt | ||
255 | } | ||
256 | |||
257 | |||
258 | |||
259 | /** | ||
260 | * 获取点击传值 | ||
261 | * @param {*} evt | ||
262 | * @param {*} key | ||
263 | */ | ||
264 | function getBindtapData(evt, key = "data") { | ||
265 | let keyStr = key || "data"; | ||
266 | return evt.currentTarget.dataset[keyStr]; | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * 从数组中获取 key未value的对象 | ||
271 | * @param {*} value | ||
272 | * @param {*} key | ||
273 | * @param {*} list | ||
274 | */ | ||
275 | function getObjByListKeyValue(value, key, list) { | ||
276 | let result = null; | ||
277 | list.forEach(element => { | ||
278 | if (element[key + ""] == value) { | ||
279 | result = element; | ||
280 | } | ||
281 | }); | ||
282 | return result; | ||
283 | } | ||
284 | |||
285 | /** | ||
286 | * 获取小程序码 | ||
287 | * path = "/pages/index/index?pa=1" | ||
288 | * @param {*} path | ||
289 | */ | ||
290 | function wxacodeGet(path) { | ||
291 | return " https://api.k.wxpai.cn/bizproxy/mzcfsapi/qrcode/create?path=" + encodeURIComponent(path); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * 根据url获取参数 | ||
296 | * @param {*} name | ||
297 | */ | ||
298 | function getQueryByUrl(name, url) { | ||
299 | return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(url) || [, ""])[1].replace(/\+/g, '%20')) || null; | ||
300 | } | ||
301 | |||
302 | |||
303 | /** | ||
304 | * 添加base前缀(my.arrayBufferToBase64方法不提供前缀) | ||
305 | */ | ||
306 | function addBase64Prefix(base64) { | ||
307 | return "data:image/PNG;base64," + base64; | ||
308 | } | ||
309 | |||
310 | |||
311 | /** | ||
312 | * @desc 函数防抖 | ||
313 | * @param func 函数 | ||
314 | * @param wait 延迟执行毫秒数 | ||
315 | * @param immediate true 表立即执行,false 表非立即执行 | ||
316 | */ | ||
317 | let debounceTimeout; | ||
318 | |||
319 | function debounce(func, wait, immediate) { | ||
320 | return function () { | ||
321 | let context = this; | ||
322 | let args = arguments; | ||
323 | |||
324 | if (debounceTimeout) clearTimeout(debounceTimeout); | ||
325 | if (immediate) { | ||
326 | var callNow = !debounceTimeout; | ||
327 | debounceTimeout = setTimeout(() => { | ||
328 | debounceTimeout = null; | ||
329 | }, wait) | ||
330 | if (callNow) func.apply(context, args) | ||
331 | } else { | ||
332 | debounceTimeout = setTimeout(function () { | ||
333 | func.apply(context, args) | ||
334 | }, wait); | ||
335 | } | ||
336 | }(); | ||
337 | } | ||
338 | |||
339 | /** | ||
340 | * @desc 函数节流 | ||
341 | * @param func 函数 | ||
342 | * @param wait 延迟执行毫秒数 | ||
343 | * @param type 1 表时间戳版,2 表定时器版 | ||
344 | * 时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。 | ||
345 | */ | ||
346 | let throttleTimeout; | ||
347 | let throttlePrevious; | ||
348 | |||
349 | function throttle(func, wait, type) { | ||
350 | if (type === 1) { | ||
351 | throttlePrevious = 0; | ||
352 | } else if (type === 2) { | ||
353 | throttleTimeout = 0; | ||
354 | } | ||
355 | return function () { | ||
356 | let context = this; | ||
357 | let args = arguments; | ||
358 | if (type === 1) { | ||
359 | let now = Date.now(); | ||
360 | |||
361 | if (now - throttlePrevious > wait) { | ||
362 | func.apply(context, args); | ||
363 | throttlePrevious = now; | ||
364 | } | ||
365 | } else if (type === 2) { | ||
366 | if (!throttleTimeout) { | ||
367 | throttleTimeout = setTimeout(() => { | ||
368 | throttleTimeout = null; | ||
369 | func.apply(context, args) | ||
370 | }, wait) | ||
371 | } | ||
372 | } | ||
373 | }(); | ||
374 | } | ||
375 | |||
376 | |||
377 | module.exports = { | ||
378 | shuffleArray: shuffleArray, | ||
379 | randomSort: randomSort, | ||
380 | uuid: uuid, | ||
381 | uniqueArray: uniqueArray, | ||
382 | paginateArray: paginateArray, | ||
383 | formatDate: formatDate, | ||
384 | formatNumber: formatNumber, | ||
385 | checkMobile: checkMobile, | ||
386 | checkIdentNo: checkIdentNo, | ||
387 | getLastScreenHeight: getLastScreenHeight, | ||
388 | debounce: debounce, | ||
389 | throttle: throttle, | ||
390 | param2Obj: param2Obj, | ||
391 | pxToRpx: pxToRpx, | ||
392 | formatWeek: formatWeek, | ||
393 | getBindtapData: getBindtapData, | ||
394 | wxacodeGet: wxacodeGet, | ||
395 | getObjByListKeyValue: getObjByListKeyValue, | ||
396 | getQueryByUrl: getQueryByUrl, | ||
397 | regFenToYuan: regFenToYuan, | ||
398 | regYuanToFen: regYuanToFen, | ||
399 | toDecimal2: toDecimal2, | ||
400 | addBase64Prefix: addBase64Prefix, | ||
401 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or sign in to post a comment