hy-app 0.4.9 → 0.4.11
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-grid/hy-grid.vue +2 -2
- package/components/hy-image/hy-image.vue +8 -6
- package/components/hy-qrcode/hy-qrcode.vue +24 -11
- package/components/hy-qrcode/index.scss +7 -6
- package/components/hy-qrcode/qrcode.js +134 -0
- package/components/hy-search/hy-search.vue +13 -6
- package/components/hy-search/index.scss +4 -0
- package/components/hy-watermark/hy-watermark.vue +409 -17
- package/libs/composables/useShare.ts +12 -0
- package/libs/utils/inspect.ts +69 -43
- package/package.json +2 -2
- package/web-types.json +1 -1
|
@@ -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
|
|
|
@@ -151,8 +151,8 @@ const itemStyle = computed<CSSProperties>(() => {
|
|
|
151
151
|
/**
|
|
152
152
|
* @description 点击事件
|
|
153
153
|
* */
|
|
154
|
-
const childClick = (
|
|
155
|
-
emit("click",
|
|
154
|
+
const childClick = (temp: string | Record<string, any>) => {
|
|
155
|
+
emit("click", temp);
|
|
156
156
|
};
|
|
157
157
|
</script>
|
|
158
158
|
|
|
@@ -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,11 +1,17 @@
|
|
|
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"
|
|
8
|
-
|
|
14
|
+
type="2d"
|
|
9
15
|
:style="{ width: addUnit(size), height: addUnit(size) }"
|
|
10
16
|
/>
|
|
11
17
|
<!-- #endif -->
|
|
@@ -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;
|
|
@@ -1176,6 +1176,108 @@ let QRCode = {};
|
|
|
1176
1176
|
}
|
|
1177
1177
|
return options.foreground;
|
|
1178
1178
|
};
|
|
1179
|
+
// 为2D Canvas添加辅助函数
|
|
1180
|
+
function drawIconWithBackground(canvas, ctx, options, qrCodeAlg) {
|
|
1181
|
+
// 在小程序中使用canvas.createImage()而不是wx.createImage()
|
|
1182
|
+
const img = canvas.createImage();
|
|
1183
|
+
img.src = options.image;
|
|
1184
|
+
img.onload = function() {
|
|
1185
|
+
var ratioImgSize = options.imageSize || 40;
|
|
1186
|
+
var x = Number(((options.size - ratioImgSize) / 2).toFixed(2));
|
|
1187
|
+
var y = Number(((options.size - ratioImgSize) / 2).toFixed(2));
|
|
1188
|
+
|
|
1189
|
+
// 绘制圆角矩形背景
|
|
1190
|
+
drawRoundedRect2D(ctx, x, y, ratioImgSize, ratioImgSize, 2, options.background);
|
|
1191
|
+
|
|
1192
|
+
// 绘制图标
|
|
1193
|
+
ctx.drawImage(img, x, y, ratioImgSize, ratioImgSize);
|
|
1194
|
+
|
|
1195
|
+
// 导出图片
|
|
1196
|
+
exportCanvasImage(canvas, options);
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
// 添加错误处理
|
|
1200
|
+
img.onerror = function(e) {
|
|
1201
|
+
console.error('Failed to load QR code icon:', e);
|
|
1202
|
+
// 即使图标加载失败也要导出二维码
|
|
1203
|
+
exportCanvasImage(canvas, options);
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
function drawRoundedRect2D(ctx, x, y, width, height, r, fillColor) {
|
|
1208
|
+
ctx.beginPath();
|
|
1209
|
+
ctx.moveTo(x + r, y);
|
|
1210
|
+
ctx.arcTo(x + width, y, x + width, y + r, r);
|
|
1211
|
+
ctx.arcTo(x + width, y + height, x + width - r, y + height, r);
|
|
1212
|
+
ctx.arcTo(x, y + height, x, y + height - r, r);
|
|
1213
|
+
ctx.arcTo(x, y, x + r, y, r);
|
|
1214
|
+
ctx.closePath();
|
|
1215
|
+
ctx.fillStyle = fillColor;
|
|
1216
|
+
ctx.fill();
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
function exportCanvasImage(canvas, options) {
|
|
1220
|
+
setTimeout(() => {
|
|
1221
|
+
wx.canvasToTempFilePath({
|
|
1222
|
+
canvas: canvas,
|
|
1223
|
+
quality: 1,
|
|
1224
|
+
success: function(res) {
|
|
1225
|
+
if (options.cbResult) {
|
|
1226
|
+
options.cbResult(res.tempFilePath);
|
|
1227
|
+
}
|
|
1228
|
+
},
|
|
1229
|
+
fail: function(res) {
|
|
1230
|
+
if (options.cbResult) {
|
|
1231
|
+
options.cbResult(res);
|
|
1232
|
+
}
|
|
1233
|
+
},
|
|
1234
|
+
complete: function() {
|
|
1235
|
+
uni.hideLoading();
|
|
1236
|
+
}
|
|
1237
|
+
}, options.context);
|
|
1238
|
+
}, options.text.length + 100);
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
// 2D Canvas二维码绘制函数
|
|
1242
|
+
function drawQRCode2D(canvas, ctx, options, qrCodeAlg) {
|
|
1243
|
+
var count = qrCodeAlg.getModuleCount();
|
|
1244
|
+
var ratioSize = options.size;
|
|
1245
|
+
|
|
1246
|
+
// 清除画布
|
|
1247
|
+
ctx.clearRect(0, 0, ratioSize, ratioSize);
|
|
1248
|
+
// 设置背景色
|
|
1249
|
+
ctx.fillStyle = options.background;
|
|
1250
|
+
ctx.fillRect(0, 0, ratioSize, ratioSize);
|
|
1251
|
+
|
|
1252
|
+
//计算每个点的长宽
|
|
1253
|
+
var tileW = (ratioSize / count).toPrecision(4);
|
|
1254
|
+
var tileH = (ratioSize / count).toPrecision(4);
|
|
1255
|
+
|
|
1256
|
+
//绘制二维码
|
|
1257
|
+
for (var row = 0; row < count; row++) {
|
|
1258
|
+
for (var col = 0; col < count; col++) {
|
|
1259
|
+
var w = Math.ceil((col + 1) * tileW) - Math.floor(col * tileW);
|
|
1260
|
+
var h = Math.ceil((row + 1) * tileW) - Math.floor(row * tileW);
|
|
1261
|
+
var foreground = getForeGround({
|
|
1262
|
+
row: row,
|
|
1263
|
+
col: col,
|
|
1264
|
+
count: count,
|
|
1265
|
+
options: options
|
|
1266
|
+
});
|
|
1267
|
+
ctx.fillStyle = qrCodeAlg.modules[row][col] ? foreground : options.background;
|
|
1268
|
+
ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
if (options.image) {
|
|
1273
|
+
// 绘制中间图标
|
|
1274
|
+
drawIconWithBackground(canvas, ctx, options, qrCodeAlg);
|
|
1275
|
+
} else {
|
|
1276
|
+
// 导出图片
|
|
1277
|
+
exportCanvasImage(canvas, options);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1179
1281
|
// 创建canvas
|
|
1180
1282
|
let createCanvas = function (options) {
|
|
1181
1283
|
if (options.showLoading) {
|
|
@@ -1184,6 +1286,38 @@ let QRCode = {};
|
|
|
1184
1286
|
mask: true
|
|
1185
1287
|
});
|
|
1186
1288
|
}
|
|
1289
|
+
|
|
1290
|
+
// 尝试使用2D Canvas (小程序端)
|
|
1291
|
+
try {
|
|
1292
|
+
if (!options.nvueContext && typeof wx !== 'undefined' && wx.createSelectorQuery) {
|
|
1293
|
+
const query = wx.createSelectorQuery().in(options.context);
|
|
1294
|
+
query.select('#' + options.canvasId)
|
|
1295
|
+
.fields({ node: true, size: true })
|
|
1296
|
+
.exec((res) => {
|
|
1297
|
+
if (res[0] && res[0].node) {
|
|
1298
|
+
const canvas = res[0].node;
|
|
1299
|
+
const ctx = canvas.getContext('2d');
|
|
1300
|
+
|
|
1301
|
+
// 设置canvas尺寸
|
|
1302
|
+
const dpr = wx.getSystemInfoSync().pixelRatio;
|
|
1303
|
+
canvas.width = options.size * dpr;
|
|
1304
|
+
canvas.height = options.size * dpr;
|
|
1305
|
+
ctx.scale(dpr, dpr);
|
|
1306
|
+
|
|
1307
|
+
// 创建二维码算法实例
|
|
1308
|
+
var qrCodeAlg = new QRCodeAlg(options.text, options.correctLevel);
|
|
1309
|
+
|
|
1310
|
+
// 使用2D Canvas绘制
|
|
1311
|
+
drawQRCode2D(canvas, ctx, options, qrCodeAlg);
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1316
|
+
} catch (e) {
|
|
1317
|
+
console.warn('2D Canvas initialization failed, falling back to legacy mode:', e);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
// 回退到传统Canvas方式
|
|
1187
1321
|
var ctx = "";
|
|
1188
1322
|
if (options.nvueContext) {
|
|
1189
1323
|
ctx = options.nvueContext;
|
|
@@ -17,10 +17,11 @@
|
|
|
17
17
|
borderColor: borderColor,
|
|
18
18
|
}"
|
|
19
19
|
>
|
|
20
|
-
<template
|
|
21
|
-
<slot name="label">
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
<template>
|
|
21
|
+
<slot v-if="$slots.label" name="label"></slot>
|
|
22
|
+
<text v-else-if="label" class="hy-search__content__label">{{
|
|
23
|
+
label
|
|
24
|
+
}}</text>
|
|
24
25
|
</template>
|
|
25
26
|
<view class="hy-search__content__icon" v-if="searchIcon">
|
|
26
27
|
<HyIcon
|
|
@@ -50,7 +51,10 @@
|
|
|
50
51
|
placeholder-class="hy-search__content__input--placeholder"
|
|
51
52
|
:placeholder="placeholder"
|
|
52
53
|
:placeholder-style="`color: ${placeholderColor}`"
|
|
53
|
-
class="
|
|
54
|
+
:class="[
|
|
55
|
+
'hy-search__content__input',
|
|
56
|
+
disabled && 'hy-search__content__input--disabled',
|
|
57
|
+
]"
|
|
54
58
|
type="text"
|
|
55
59
|
:always-embed="true"
|
|
56
60
|
:style="[
|
|
@@ -213,7 +217,10 @@ const props = defineProps({
|
|
|
213
217
|
default: "",
|
|
214
218
|
},
|
|
215
219
|
/** 输入框左边的图标属性集合,可以为图标名称或图片路径 */
|
|
216
|
-
searchIcon:
|
|
220
|
+
searchIcon: {
|
|
221
|
+
type: [Boolean, Object] as PropType<HyIconProps | boolean>,
|
|
222
|
+
default: { name: IconConfig.SEARCH },
|
|
223
|
+
},
|
|
217
224
|
/** 组件与其他上下左右之间的距离,带单位的字符串形式,如"30px" */
|
|
218
225
|
margin: {
|
|
219
226
|
type: [String, Number],
|
|
@@ -59,6 +59,10 @@ $hy-search-close-size: 20px !default;
|
|
|
59
59
|
color: $hy-text-color;
|
|
60
60
|
background-color: $hy-background--empty;
|
|
61
61
|
|
|
62
|
+
@include m(disabled) {
|
|
63
|
+
color: $hy-text-color--disabled;
|
|
64
|
+
}
|
|
65
|
+
|
|
62
66
|
@include m(placeholder) {
|
|
63
67
|
font-size: 25rpx;
|
|
64
68
|
color: $hy-text-color--placeholder;
|