hy-app 0.4.9 → 0.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/hy-empty/hy-empty.vue +0 -1
- package/components/hy-empty/icon.ts +27 -7
- package/components/hy-image/hy-image.vue +8 -6
- package/components/hy-qrcode/hy-qrcode.vue +23 -10
- package/components/hy-qrcode/index.scss +7 -6
- package/libs/composables/useShare.ts +12 -0
- package/libs/utils/inspect.ts +69 -43
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IEmptyIcon } from "./typing";
|
|
2
2
|
|
|
3
|
-
const url = "https://
|
|
3
|
+
const url = "https://hy-design-uni.oss-cn-hangzhou.aliyuncs.com/image/";
|
|
4
4
|
|
|
5
5
|
const emptyIcon: IEmptyIcon = {
|
|
6
6
|
content: {
|
|
@@ -13,7 +13,7 @@ const emptyIcon: IEmptyIcon = {
|
|
|
13
13
|
},
|
|
14
14
|
address: {
|
|
15
15
|
desc: "没有收货地址",
|
|
16
|
-
icon: url + "png",
|
|
16
|
+
icon: url + "address.png",
|
|
17
17
|
},
|
|
18
18
|
network: {
|
|
19
19
|
desc: "没有网络",
|
|
@@ -21,19 +21,19 @@ const emptyIcon: IEmptyIcon = {
|
|
|
21
21
|
},
|
|
22
22
|
order: {
|
|
23
23
|
desc: "订单为空",
|
|
24
|
-
icon: url + "png",
|
|
24
|
+
icon: url + "order.png",
|
|
25
25
|
},
|
|
26
26
|
coupon: {
|
|
27
27
|
desc: "没有优惠券",
|
|
28
|
-
icon: url + "png",
|
|
28
|
+
icon: url + "coupon.png",
|
|
29
29
|
},
|
|
30
|
-
|
|
30
|
+
collect: {
|
|
31
31
|
desc: "暂无收藏",
|
|
32
32
|
icon: url + "collect.png",
|
|
33
33
|
},
|
|
34
34
|
history: {
|
|
35
35
|
desc: "无历史记录",
|
|
36
|
-
icon: url + "png",
|
|
36
|
+
icon: url + "history.png",
|
|
37
37
|
},
|
|
38
38
|
message: {
|
|
39
39
|
desc: "消息列表为空",
|
|
@@ -45,7 +45,27 @@ const emptyIcon: IEmptyIcon = {
|
|
|
45
45
|
},
|
|
46
46
|
integral: {
|
|
47
47
|
desc: "暂无积分",
|
|
48
|
-
icon: url + "
|
|
48
|
+
icon: url + "integral.png",
|
|
49
|
+
},
|
|
50
|
+
card: {
|
|
51
|
+
desc: "暂无银行卡",
|
|
52
|
+
icon: url + "card.png",
|
|
53
|
+
},
|
|
54
|
+
notification: {
|
|
55
|
+
desc: "暂无通知",
|
|
56
|
+
icon: url + "notification.png",
|
|
57
|
+
},
|
|
58
|
+
shop: {
|
|
59
|
+
desc: "暂无购物车",
|
|
60
|
+
icon: url + "shop.png",
|
|
61
|
+
},
|
|
62
|
+
activity: {
|
|
63
|
+
desc: "暂无活动",
|
|
64
|
+
icon: url + "activity.png",
|
|
65
|
+
},
|
|
66
|
+
loading: {
|
|
67
|
+
desc: "加载中",
|
|
68
|
+
icon: url + "loading.png",
|
|
49
69
|
},
|
|
50
70
|
};
|
|
51
71
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<hy-transition
|
|
3
3
|
mode="fade"
|
|
4
4
|
:show="show"
|
|
5
5
|
:style="transStyle"
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
height: addUnit(height),
|
|
25
25
|
borderRadius: shape == 'circle' ? '1000px' : addUnit(radius),
|
|
26
26
|
}"
|
|
27
|
+
referrerpolicy="no-referrer"
|
|
27
28
|
></image>
|
|
28
29
|
<view
|
|
29
30
|
v-if="showLoading && loading"
|
|
@@ -35,9 +36,10 @@
|
|
|
35
36
|
height: addUnit(height),
|
|
36
37
|
}"
|
|
37
38
|
>
|
|
38
|
-
<slot name="loading">
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
<slot v-if="$slots.loading" name="loading"></slot>
|
|
40
|
+
<template v-else>
|
|
41
|
+
<hy-loading :name="loadingIcon"></hy-loading>
|
|
42
|
+
</template>
|
|
41
43
|
</view>
|
|
42
44
|
<view
|
|
43
45
|
v-if="showError && isError && !loading"
|
|
@@ -47,11 +49,11 @@
|
|
|
47
49
|
}"
|
|
48
50
|
>
|
|
49
51
|
<slot name="error">
|
|
50
|
-
<
|
|
52
|
+
<hy-icon :name="errorIcon" size="30"></hy-icon>
|
|
51
53
|
</slot>
|
|
52
54
|
</view>
|
|
53
55
|
</view>
|
|
54
|
-
</
|
|
56
|
+
</hy-transition>
|
|
55
57
|
</template>
|
|
56
58
|
|
|
57
59
|
<script lang="ts">
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<view class="hy-qrcode" @longpress="onLongPress">
|
|
3
|
-
<view class="hy-qrcode__content"
|
|
3
|
+
<view class="hy-qrcode__content">
|
|
4
4
|
<!-- #ifndef APP-NVUE -->
|
|
5
|
+
<hy-image
|
|
6
|
+
:src="result"
|
|
7
|
+
:width="size"
|
|
8
|
+
:height="size"
|
|
9
|
+
@click="preview"
|
|
10
|
+
></hy-image>
|
|
5
11
|
<canvas
|
|
6
12
|
class="hy-qrcode__content--canvas"
|
|
7
13
|
:id="cid"
|
|
@@ -14,7 +20,7 @@
|
|
|
14
20
|
class="hy-qrcode__content--loading"
|
|
15
21
|
:style="{ width: addUnit(size), height: addUnit(size) }"
|
|
16
22
|
>
|
|
17
|
-
<
|
|
23
|
+
<hy-loading :text="loadingText" direction="column" />
|
|
18
24
|
</view>
|
|
19
25
|
</view>
|
|
20
26
|
</view>
|
|
@@ -32,12 +38,13 @@ export default {
|
|
|
32
38
|
</script>
|
|
33
39
|
|
|
34
40
|
<script setup lang="ts">
|
|
35
|
-
import { getCurrentInstance, ref,
|
|
41
|
+
import { getCurrentInstance, ref, watch, nextTick } from "vue";
|
|
36
42
|
import type { IQrcodeEmits } from "./typing";
|
|
37
43
|
import QRCode from "./qrcode.js";
|
|
38
44
|
import { addUnit, error } from "../../libs";
|
|
39
45
|
// 组件
|
|
40
46
|
import HyLoading from "../hy-loading/hy-loading.vue";
|
|
47
|
+
import HyImage from "../hy-image/hy-image.vue";
|
|
41
48
|
|
|
42
49
|
/**
|
|
43
50
|
* 根据提供的字符串前端JS生成二维码展示
|
|
@@ -104,7 +111,7 @@ const props = defineProps({
|
|
|
104
111
|
/** 加载中提示语 */
|
|
105
112
|
loadingText: {
|
|
106
113
|
type: String,
|
|
107
|
-
default: "
|
|
114
|
+
default: "二维码生成中...",
|
|
108
115
|
},
|
|
109
116
|
/** 是否预览 */
|
|
110
117
|
allowPreview: {
|
|
@@ -115,17 +122,12 @@ const props = defineProps({
|
|
|
115
122
|
const emit = defineEmits<IQrcodeEmits>();
|
|
116
123
|
|
|
117
124
|
const instance = getCurrentInstance();
|
|
118
|
-
const loading = ref(
|
|
125
|
+
const loading = ref(true);
|
|
119
126
|
const qrcode = ref("");
|
|
120
127
|
const result = ref("");
|
|
121
128
|
|
|
122
|
-
onMounted(() => {
|
|
123
|
-
initQrCode();
|
|
124
|
-
});
|
|
125
|
-
|
|
126
129
|
const initQrCode = () => {
|
|
127
130
|
if (props.text) {
|
|
128
|
-
loading.value = true;
|
|
129
131
|
qrcode.value = new QRCode({
|
|
130
132
|
context: instance, // 上下文环境
|
|
131
133
|
canvasId: props.cid, // canvas-id
|
|
@@ -150,6 +152,17 @@ const initQrCode = () => {
|
|
|
150
152
|
}
|
|
151
153
|
};
|
|
152
154
|
|
|
155
|
+
// 判断是否显示二维码
|
|
156
|
+
watch(
|
|
157
|
+
() => props.show,
|
|
158
|
+
(newValue) => {
|
|
159
|
+
if (newValue) {
|
|
160
|
+
nextTick(() => initQrCode());
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
{ immediate: true },
|
|
164
|
+
);
|
|
165
|
+
|
|
153
166
|
const _result = (res: any) => {
|
|
154
167
|
loading.value = false;
|
|
155
168
|
result.value = res;
|
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
@include e(content) {
|
|
6
6
|
position: relative;
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
@include m(canvas) {
|
|
9
|
+
position: fixed;
|
|
10
|
+
top: -99999rpx;
|
|
11
|
+
left: -99999rpx;
|
|
12
|
+
z-index: -99999;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
}
|
|
14
15
|
|
|
15
16
|
@include m(loading) {
|
|
16
17
|
display: flex;
|
|
@@ -2,9 +2,21 @@
|
|
|
2
2
|
* 全局分享hooks
|
|
3
3
|
* */
|
|
4
4
|
interface ShareConfig {
|
|
5
|
+
/**
|
|
6
|
+
* 标题名称
|
|
7
|
+
* */
|
|
5
8
|
title?: string;
|
|
9
|
+
/**
|
|
10
|
+
* 页面路径
|
|
11
|
+
* */
|
|
6
12
|
path?: string;
|
|
13
|
+
/**
|
|
14
|
+
* 分享朋友的封面图片
|
|
15
|
+
* */
|
|
7
16
|
friendImageUrl?: string;
|
|
17
|
+
/**
|
|
18
|
+
* 分享朋友圈的封面图片
|
|
19
|
+
* */
|
|
8
20
|
timelineImageUrl?: string;
|
|
9
21
|
}
|
|
10
22
|
|
package/libs/utils/inspect.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* @return {Boolean}
|
|
5
5
|
* */
|
|
6
6
|
export const isNumericString = (text: string | number): boolean => {
|
|
7
|
-
return typeof text ===
|
|
8
|
-
}
|
|
7
|
+
return typeof text === "string" && !isNaN(Number(text));
|
|
8
|
+
};
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @description 判断是否是数字
|
|
@@ -13,8 +13,8 @@ export const isNumericString = (text: string | number): boolean => {
|
|
|
13
13
|
* @return {Boolean}
|
|
14
14
|
* */
|
|
15
15
|
export const isNumber = (text: string | number): boolean => {
|
|
16
|
-
return typeof text ===
|
|
17
|
-
}
|
|
16
|
+
return typeof text === "number" || isNumericString(text);
|
|
17
|
+
};
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* @description 判断是否数组
|
|
@@ -23,12 +23,12 @@ export const isNumber = (text: string | number): boolean => {
|
|
|
23
23
|
*/
|
|
24
24
|
export const isArray = (arr: any): arr is Array<any> => {
|
|
25
25
|
// 如果 Array.isArray 函数可用,直接使用该函数检查
|
|
26
|
-
if (typeof Array.isArray ===
|
|
27
|
-
return Array.isArray(arr)
|
|
26
|
+
if (typeof Array.isArray === "function") {
|
|
27
|
+
return Array.isArray(arr);
|
|
28
28
|
}
|
|
29
29
|
// 否则,使用对象原型的 toString 方法进行检查
|
|
30
|
-
return Object.prototype.toString.call(arr) ===
|
|
31
|
-
}
|
|
30
|
+
return Object.prototype.toString.call(arr) === "[object Array]";
|
|
31
|
+
};
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* @description 判断是否对象
|
|
@@ -36,8 +36,8 @@ export const isArray = (arr: any): arr is Array<any> => {
|
|
|
36
36
|
* @return {Boolean}
|
|
37
37
|
*/
|
|
38
38
|
export const isObject = (obj: any): obj is Object => {
|
|
39
|
-
return Object.prototype.toString.call(obj) ===
|
|
40
|
-
}
|
|
39
|
+
return Object.prototype.toString.call(obj) === "[object Object]";
|
|
40
|
+
};
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* @description 是否为base64图片
|
|
@@ -46,7 +46,7 @@ export const isObject = (obj: any): obj is Object => {
|
|
|
46
46
|
*/
|
|
47
47
|
export function isBase64Image(url: string) {
|
|
48
48
|
// 使用正则表达式检查URL是否以"data:image"开头,这是Base64图片的常见前缀
|
|
49
|
-
return /^data:image\/(png|jpg|jpeg|gif|bmp);base64,/.test(url)
|
|
49
|
+
return /^data:image\/(png|jpg|jpeg|gif|bmp);base64,/.test(url);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -56,7 +56,7 @@ export function isBase64Image(url: string) {
|
|
|
56
56
|
*/
|
|
57
57
|
export function isImage(url: string) {
|
|
58
58
|
// 使用正则表达式检查URL是否以"data:image"开头,这是Base64图片的常见前缀
|
|
59
|
-
return /(\.jpg|\.jpeg|\.png|\.gif|\.bmp|\.webp)$/i.test(url)
|
|
59
|
+
return /(\.jpg|\.jpeg|\.png|\.gif|\.bmp|\.webp)$/i.test(url);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
@@ -64,8 +64,9 @@ export function isImage(url: string) {
|
|
|
64
64
|
* @param {String} value
|
|
65
65
|
*/
|
|
66
66
|
export function isVideo(value: string): boolean {
|
|
67
|
-
const VIDEO_REGEXP =
|
|
68
|
-
|
|
67
|
+
const VIDEO_REGEXP =
|
|
68
|
+
/\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i;
|
|
69
|
+
return VIDEO_REGEXP.test(value);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
/**
|
|
@@ -73,55 +74,80 @@ export function isVideo(value: string): boolean {
|
|
|
73
74
|
* @param {Number | String} value yyyy-mm-dd hh:mm:ss 或 时间戳
|
|
74
75
|
*/
|
|
75
76
|
export const isDate = (value: string | number) => {
|
|
76
|
-
if (!value) return false
|
|
77
|
+
if (!value) return false;
|
|
77
78
|
// number类型,判断是否是时间戳
|
|
78
|
-
if (typeof value ===
|
|
79
|
+
if (typeof value === "number") {
|
|
79
80
|
// len === 10 秒级时间戳 len === 13 毫秒级时间戳
|
|
80
81
|
if (value.toString().length !== 10 && value.toString().length !== 13) {
|
|
81
|
-
return false
|
|
82
|
+
return false;
|
|
82
83
|
}
|
|
83
|
-
return !isNaN(new Date(value).getTime())
|
|
84
|
+
return !isNaN(new Date(value).getTime());
|
|
84
85
|
}
|
|
85
|
-
if (typeof value ===
|
|
86
|
+
if (typeof value === "string") {
|
|
86
87
|
// 是否为string类型时间戳
|
|
87
|
-
const numV = Number(value)
|
|
88
|
+
const numV = Number(value);
|
|
88
89
|
if (!isNaN(numV)) {
|
|
89
90
|
if (numV.toString().length === 10 || numV.toString().length === 13) {
|
|
90
|
-
return !isNaN(new Date(numV).getTime())
|
|
91
|
+
return !isNaN(new Date(numV).getTime());
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
// 非时间戳,且长度在yyyy-mm-dd 至 yyyy-mm-dd hh:mm:ss 之间
|
|
94
95
|
if (value.length < 10 || value.length > 19) {
|
|
95
|
-
return false
|
|
96
|
+
return false;
|
|
96
97
|
}
|
|
97
|
-
const dateRegex = /^\d{4}[-\/]\d{2}[-\/]\d{2}( \d{1,2}:\d{2}(:\d{2})?)
|
|
98
|
+
const dateRegex = /^\d{4}[-\/]\d{2}[-\/]\d{2}( \d{1,2}:\d{2}(:\d{2})?)?$/;
|
|
98
99
|
if (!dateRegex.test(value)) {
|
|
99
|
-
return false
|
|
100
|
+
return false;
|
|
100
101
|
}
|
|
101
102
|
// 检查是否为有效日期
|
|
102
|
-
const dateValue = new Date(value)
|
|
103
|
-
return !isNaN(dateValue.getTime())
|
|
103
|
+
const dateValue = new Date(value);
|
|
104
|
+
return !isNaN(dateValue.getTime());
|
|
104
105
|
}
|
|
105
106
|
// 非number和string类型,不做校验
|
|
106
|
-
return false
|
|
107
|
-
}
|
|
107
|
+
return false;
|
|
108
|
+
};
|
|
108
109
|
|
|
109
110
|
/**
|
|
110
111
|
* @description 验证是否是手机号格式
|
|
111
|
-
* @param {
|
|
112
|
+
* @param {unknown} phone 手机号
|
|
112
113
|
*/
|
|
113
|
-
export const isPhone = (phone:
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
export const isPhone = (phone: unknown): boolean => {
|
|
115
|
+
if (typeof phone !== "string" && typeof phone !== "number") return false;
|
|
116
|
+
if (phone === "") return false;
|
|
117
|
+
|
|
118
|
+
const phoneStr = String(phone).trim();
|
|
119
|
+
// 处理 +86 12345678901 格式
|
|
120
|
+
const normalized = phoneStr.replace(/^\+86\s?/, "");
|
|
121
|
+
return /^1[3-9]\d{9}$/.test(normalized) && normalized.length === 11;
|
|
122
|
+
};
|
|
116
123
|
|
|
117
124
|
/**
|
|
118
125
|
* @description 验证身份证号码
|
|
119
|
-
* @param {
|
|
126
|
+
* @param {unknown} idCard 身份证号
|
|
120
127
|
* @return {Boolean}
|
|
121
128
|
*/
|
|
122
|
-
export const isIdCard = (idCard:
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
export const isIdCard = (idCard: unknown): boolean => {
|
|
130
|
+
if (typeof idCard !== "string" && typeof idCard !== "number") return false;
|
|
131
|
+
const str = String(idCard).trim().toUpperCase();
|
|
132
|
+
|
|
133
|
+
// 格式校验:15位或18位
|
|
134
|
+
if (!/(^\d{15}$)|(^\d{17}[\dX]$)/.test(str)) return false;
|
|
135
|
+
|
|
136
|
+
// 18位身份证:校验校验码
|
|
137
|
+
if (str.length === 18) {
|
|
138
|
+
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
|
|
139
|
+
const checksums = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
|
|
140
|
+
|
|
141
|
+
let sum = 0;
|
|
142
|
+
for (let i = 0; i < 17; i++) {
|
|
143
|
+
sum += parseInt(str[i]) * weights[i];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return checksums[sum % 11] === str[17];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return true; // 15位不校验
|
|
150
|
+
};
|
|
125
151
|
|
|
126
152
|
/**
|
|
127
153
|
* @description 验证是否是中文
|
|
@@ -129,17 +155,17 @@ export const isIdCard = (idCard: string): boolean => {
|
|
|
129
155
|
* @return {Boolean}
|
|
130
156
|
*/
|
|
131
157
|
export const isChinese = (zh: string): boolean => {
|
|
132
|
-
const reg = /^[\u4e00-\u9fa5]+$/gi
|
|
133
|
-
return reg.test(zh)
|
|
134
|
-
}
|
|
158
|
+
const reg = /^[\u4e00-\u9fa5]+$/gi;
|
|
159
|
+
return reg.test(zh);
|
|
160
|
+
};
|
|
135
161
|
|
|
136
162
|
/**
|
|
137
163
|
* @description 判断环境是否是H5
|
|
138
164
|
*/
|
|
139
165
|
export const isH5 = (() => {
|
|
140
|
-
let isH5 = false
|
|
166
|
+
let isH5 = false;
|
|
141
167
|
// #ifdef H5
|
|
142
|
-
isH5 = true
|
|
168
|
+
isH5 = true;
|
|
143
169
|
// #endif
|
|
144
|
-
return isH5
|
|
145
|
-
})()
|
|
170
|
+
return isH5;
|
|
171
|
+
})();
|