@xtdev/xt-miniprogram-ui 1.2.86 → 1.2.88
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.
|
@@ -25,24 +25,24 @@ Component({
|
|
|
25
25
|
type: Object,
|
|
26
26
|
value: {},
|
|
27
27
|
},
|
|
28
|
-
// 闪光灯模式:auto/on/off/torch
|
|
29
|
-
flash: {
|
|
30
|
-
type: String,
|
|
31
|
-
value: 'off',
|
|
32
|
-
},
|
|
33
28
|
},
|
|
34
29
|
|
|
35
30
|
data: {
|
|
36
|
-
currentTime:
|
|
31
|
+
currentTime: "", // 当前时间
|
|
32
|
+
currentHours: '', // 当前时间 HH
|
|
33
|
+
currentMinutes: '', // 当前时间 mm
|
|
37
34
|
currentDateTime: '', // 完整日期时间
|
|
38
35
|
previewImage: '', // 预览图片路径
|
|
39
36
|
isLoading: false,
|
|
40
37
|
systemInfo: null,
|
|
41
38
|
dpr: 2,
|
|
39
|
+
devicePosition: "back", // 摄像头位置 back: 后置 front: 前置
|
|
40
|
+
flashlight: 'off', // 闪光灯 auto/on/off/torch
|
|
42
41
|
},
|
|
43
42
|
|
|
44
43
|
lifetimes: {
|
|
45
44
|
attached() {
|
|
45
|
+
this.initFont();
|
|
46
46
|
this.initComponent();
|
|
47
47
|
},
|
|
48
48
|
detached() {
|
|
@@ -51,6 +51,41 @@ Component({
|
|
|
51
51
|
},
|
|
52
52
|
|
|
53
53
|
methods: {
|
|
54
|
+
initFont() {
|
|
55
|
+
wx.loadFontFace({
|
|
56
|
+
family: 'FengTan-Regular', // 注意:这里的名称要和下面使用时完全一致
|
|
57
|
+
source: 'url("https://img.tanjiu.cn/home/C706753403526887.ttf")',
|
|
58
|
+
success: () => {
|
|
59
|
+
console.log('字体加载成功');
|
|
60
|
+
},
|
|
61
|
+
fail: (err) => {
|
|
62
|
+
console.error('字体加载失败', err);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* 翻转摄像头
|
|
68
|
+
*/
|
|
69
|
+
switchCamera() {
|
|
70
|
+
const { devicePosition } = this.data;
|
|
71
|
+
this.setData({
|
|
72
|
+
devicePosition: devicePosition === 'back' ? 'front' : 'back'
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
/**
|
|
76
|
+
* 开关闪光灯
|
|
77
|
+
*/
|
|
78
|
+
switchFlashLight() {
|
|
79
|
+
let { flashlight } = this.data;
|
|
80
|
+
flashlight = flashlight === 'off' ? 'on' : 'off';
|
|
81
|
+
this.setData({
|
|
82
|
+
flashlight
|
|
83
|
+
});
|
|
84
|
+
wx.showToast({
|
|
85
|
+
title: flashlight === 'off' ? '闪光灯已关闭' : '闪光灯已开启',
|
|
86
|
+
icon: 'none'
|
|
87
|
+
});
|
|
88
|
+
},
|
|
54
89
|
/**
|
|
55
90
|
* 初始化组件
|
|
56
91
|
*/
|
|
@@ -89,6 +124,8 @@ Component({
|
|
|
89
124
|
|
|
90
125
|
this.setData({
|
|
91
126
|
currentTime: `${hours}:${minutes}`,
|
|
127
|
+
currentHours: hours,
|
|
128
|
+
currentMinutes: minutes,
|
|
92
129
|
currentDateTime: `${year}年${month}月${day}日${hours}:${minutes}`,
|
|
93
130
|
});
|
|
94
131
|
};
|
|
@@ -101,7 +138,7 @@ Component({
|
|
|
101
138
|
* 拍照
|
|
102
139
|
*/
|
|
103
140
|
takePhoto() {
|
|
104
|
-
if (this.data.isLoading) return;
|
|
141
|
+
if (this.data.isLoading) {return;}
|
|
105
142
|
|
|
106
143
|
this.setData({ isLoading: true });
|
|
107
144
|
|
|
@@ -171,7 +208,8 @@ Component({
|
|
|
171
208
|
.exec(res => {
|
|
172
209
|
if (!res[0] || !res[0].node) {
|
|
173
210
|
// 使用离屏Canvas
|
|
174
|
-
this.createWithOffscreenCanvas(imagePath, imgInfo).then(resolve)
|
|
211
|
+
this.createWithOffscreenCanvas(imagePath, imgInfo).then(resolve)
|
|
212
|
+
.catch(reject);
|
|
175
213
|
return;
|
|
176
214
|
}
|
|
177
215
|
|
|
@@ -284,19 +322,19 @@ Component({
|
|
|
284
322
|
const shortSide = Math.min(width, height);
|
|
285
323
|
const scale = shortSide / 750; // 以750rpx为基准计算缩放比
|
|
286
324
|
|
|
287
|
-
const { watermarkData,
|
|
325
|
+
const { watermarkData, currentHours, currentMinutes, currentDateTime } = this.data;
|
|
288
326
|
const tagText = watermarkData.tagText || '拍照记录';
|
|
289
327
|
const tagColor = '#7b2d8e'; // 固定紫色
|
|
290
328
|
|
|
291
329
|
// ============ 尺寸参数(与CSS保持一致)============
|
|
292
330
|
const radius = 8 * scale;
|
|
293
331
|
const tagPaddingV = 12 * scale; // 标签垂直padding
|
|
294
|
-
const tagPaddingH =
|
|
332
|
+
const tagPaddingH = 12 * scale; // 标签水平padding
|
|
295
333
|
const tagFontSize = 40 * scale; // 标签字体大小
|
|
296
|
-
const timeFontSize =
|
|
334
|
+
const timeFontSize = 48 * scale; // 时间字体大小
|
|
297
335
|
|
|
298
|
-
const infoPaddingV =
|
|
299
|
-
const infoPaddingH =
|
|
336
|
+
const infoPaddingV = 16 * scale; // 信息区垂直padding
|
|
337
|
+
const infoPaddingH = 16 * scale; // 信息区水平padding
|
|
300
338
|
const infoX = 16 * scale; // 距离左边16rpx
|
|
301
339
|
|
|
302
340
|
// 文字尺寸
|
|
@@ -306,7 +344,7 @@ Component({
|
|
|
306
344
|
|
|
307
345
|
// 警告标签尺寸
|
|
308
346
|
const warningFontSize = 20 * scale;
|
|
309
|
-
const warningPaddingH =
|
|
347
|
+
const warningPaddingH = 8 * scale;
|
|
310
348
|
const warningPaddingV = 4 * scale;
|
|
311
349
|
const warningRadius = 4 * scale;
|
|
312
350
|
const warningMarginRight = 8 * scale;
|
|
@@ -345,7 +383,7 @@ Component({
|
|
|
345
383
|
const tagHeight = tagFontSize + tagPaddingV * 2;
|
|
346
384
|
|
|
347
385
|
const tagX = infoX; // 与info-container左对齐
|
|
348
|
-
const tagY = infoY - tagHeight -
|
|
386
|
+
const tagY = infoY - tagHeight - 12 * scale; // 在info-container上方16rpx
|
|
349
387
|
|
|
350
388
|
// 标签背景(左上和左下圆角)
|
|
351
389
|
ctx.fillStyle = tagColor;
|
|
@@ -358,8 +396,8 @@ Component({
|
|
|
358
396
|
ctx.fillText(tagText, tagX + tagPaddingH, tagY + tagHeight / 2);
|
|
359
397
|
|
|
360
398
|
// 时间背景(右上和右下圆角)
|
|
361
|
-
ctx.font = `bold ${timeFontSize}px "
|
|
362
|
-
const timeTextWidth = ctx.measureText(
|
|
399
|
+
ctx.font = `bold ${timeFontSize}px "FengTan-Regular"`;
|
|
400
|
+
const timeTextWidth = ctx.measureText("00:00").width;
|
|
363
401
|
const timeWidth = timeTextWidth + tagPaddingH * 2;
|
|
364
402
|
|
|
365
403
|
ctx.fillStyle = '#ffffff';
|
|
@@ -367,8 +405,13 @@ Component({
|
|
|
367
405
|
ctx.fill();
|
|
368
406
|
|
|
369
407
|
// 时间文字
|
|
370
|
-
ctx.fillStyle = '#
|
|
371
|
-
ctx.fillText(
|
|
408
|
+
ctx.fillStyle = '#000000';
|
|
409
|
+
ctx.fillText(currentHours, tagX + tagWidth + tagPaddingH, tagY + tagHeight / 2 + 2);
|
|
410
|
+
ctx.fillText(currentMinutes, tagX + tagWidth + tagPaddingH + 70 * scale, tagY + tagHeight / 2 + 2);
|
|
411
|
+
|
|
412
|
+
ctx.font = `bold ${nameFontSize}px "PingFang SC", sans-serif`;
|
|
413
|
+
ctx.fillText(":", tagX + tagWidth + tagPaddingH + 56 * scale, tagY + tagHeight / 2);
|
|
414
|
+
|
|
372
415
|
|
|
373
416
|
// ============ 绘制信息区背景 ============
|
|
374
417
|
// 渐变背景(从左到右,90deg)
|
|
@@ -393,7 +436,7 @@ Component({
|
|
|
393
436
|
|
|
394
437
|
// 业务信息行
|
|
395
438
|
if (watermarkData.businessInfo) {
|
|
396
|
-
ctx.font =
|
|
439
|
+
ctx.font = `bold ${businessFontSize}px "PingFang SC", sans-serif`;
|
|
397
440
|
ctx.fillStyle = '#ffffff';
|
|
398
441
|
ctx.fillText(watermarkData.businessInfo, textX, currentY);
|
|
399
442
|
|
|
@@ -408,7 +451,7 @@ Component({
|
|
|
408
451
|
|
|
409
452
|
// 店铺名称
|
|
410
453
|
if (watermarkData.shopName) {
|
|
411
|
-
ctx.font =
|
|
454
|
+
ctx.font = `bold ${businessFontSize}px "PingFang SC", sans-serif`;
|
|
412
455
|
ctx.fillStyle = '#ffffff';
|
|
413
456
|
ctx.fillText(watermarkData.shopName, textX, currentY);
|
|
414
457
|
currentY += businessFontSize + infoRowMargin;
|
|
@@ -418,13 +461,13 @@ Component({
|
|
|
418
461
|
let dateTimeX = textX;
|
|
419
462
|
if (watermarkData.timeWarning) {
|
|
420
463
|
// 绘制时间异常标签
|
|
421
|
-
ctx.font =
|
|
464
|
+
ctx.font = `bold ${warningFontSize}px "PingFang SC", sans-serif`;
|
|
422
465
|
const warningText = '时间异常';
|
|
423
466
|
const warningTextWidth = ctx.measureText(warningText).width;
|
|
424
467
|
const warningTagWidth = warningTextWidth + warningPaddingH * 2;
|
|
425
468
|
const warningTagHeight = warningFontSize + warningPaddingV * 2;
|
|
426
469
|
|
|
427
|
-
ctx.fillStyle = '#
|
|
470
|
+
ctx.fillStyle = '#DB1C1C';
|
|
428
471
|
this.drawRoundRect(ctx, textX, currentY, warningTagWidth, warningTagHeight, warningRadius);
|
|
429
472
|
ctx.fill();
|
|
430
473
|
|
|
@@ -435,7 +478,7 @@ Component({
|
|
|
435
478
|
|
|
436
479
|
dateTimeX = textX + warningTagWidth + warningMarginRight;
|
|
437
480
|
}
|
|
438
|
-
ctx.font =
|
|
481
|
+
ctx.font = `bold ${infoFontSize}px "PingFang SC", sans-serif`;
|
|
439
482
|
ctx.fillStyle = '#ffffff';
|
|
440
483
|
ctx.fillText(currentDateTime, dateTimeX, currentY);
|
|
441
484
|
currentY += infoFontSize + infoRowMargin;
|
|
@@ -444,13 +487,13 @@ Component({
|
|
|
444
487
|
let addressX = textX;
|
|
445
488
|
if (watermarkData.locationWarning) {
|
|
446
489
|
// 绘制位置异常标签
|
|
447
|
-
ctx.font =
|
|
490
|
+
ctx.font = `bold ${warningFontSize}px "PingFang SC", sans-serif`;
|
|
448
491
|
const warningText = '位置异常';
|
|
449
492
|
const warningTextWidth = ctx.measureText(warningText).width;
|
|
450
493
|
const warningTagWidth = warningTextWidth + warningPaddingH * 2;
|
|
451
494
|
const warningTagHeight = warningFontSize + warningPaddingV * 2;
|
|
452
495
|
|
|
453
|
-
ctx.fillStyle = '#
|
|
496
|
+
ctx.fillStyle = '#DB1C1C';
|
|
454
497
|
this.drawRoundRect(ctx, textX, currentY, warningTagWidth, warningTagHeight, warningRadius);
|
|
455
498
|
ctx.fill();
|
|
456
499
|
|
|
@@ -462,7 +505,7 @@ Component({
|
|
|
462
505
|
addressX = textX + warningTagWidth + warningMarginRight;
|
|
463
506
|
}
|
|
464
507
|
const address = watermarkData.address;
|
|
465
|
-
ctx.font =
|
|
508
|
+
ctx.font = `bold ${infoFontSize}px "PingFang SC", sans-serif`;
|
|
466
509
|
ctx.fillStyle = '#ffffff';
|
|
467
510
|
ctx.fillText(address, addressX, currentY);
|
|
468
511
|
currentY += infoFontSize + infoRowMargin;
|
|
@@ -493,7 +536,7 @@ Component({
|
|
|
493
536
|
*/
|
|
494
537
|
confirmPhoto() {
|
|
495
538
|
const { previewImage } = this.data;
|
|
496
|
-
if (!previewImage) return;
|
|
539
|
+
if (!previewImage) {return;}
|
|
497
540
|
|
|
498
541
|
// 触发事件,将图片路径传递给父组件
|
|
499
542
|
this.triggerEvent('confirm', {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<view class="watermark-camera-container">
|
|
2
2
|
<!-- 相机区域 -->
|
|
3
3
|
<view class="camera-section" wx:if="{{!previewImage}}">
|
|
4
|
-
<camera device-position="
|
|
4
|
+
<camera device-position="{{devicePosition}}" flash="{{flashlight}}" class="camera" binderror="onCameraError" />
|
|
5
5
|
|
|
6
6
|
<!-- 实时水印预览层 -->
|
|
7
7
|
<view class="watermark-preview-layer">
|
|
8
8
|
<!-- 左上角标签 -->
|
|
9
9
|
<view class="tag-container">
|
|
10
10
|
<view class="tag-label">{{watermarkData.tagText || '拍照记录'}}</view>
|
|
11
|
-
<view class="tag-time">{{
|
|
11
|
+
<view class="tag-time">{{currentHours}}<text class="pingfang">:</text>{{currentMinutes}}</view>
|
|
12
12
|
</view>
|
|
13
13
|
|
|
14
14
|
<!-- 底部信息区 -->
|
|
@@ -55,9 +55,11 @@
|
|
|
55
55
|
|
|
56
56
|
<!-- 拍照按钮 -->
|
|
57
57
|
<view class="shutter-area">
|
|
58
|
+
<image class="shutter-icon" bind:tap="switchFlashLight" src="{{flashlight == 'on'? 'https://img.tanjiu.cn/home/hXyjajQeyx7nF4dSiFrFM2Ws7Hhbw3fj.png': 'https://img.tanjiu.cn/home/ijXc7GwrFSPi5ttEEJzA7n4Hd3zpGDNE.png'}}" mode="aspectFit" binderror="" bindload=""></image>
|
|
58
59
|
<view class="shutter-btn" bindtap="takePhoto">
|
|
59
60
|
<view class="shutter-inner"></view>
|
|
60
61
|
</view>
|
|
62
|
+
<image class="shutter-icon" bind:tap="switchCamera" src="https://img.tanjiu.cn/home/Jmiyy8h2SiZ8YaMWrNTzcHS3C5XGap3c.png" mode="aspectFit" binderror="" bindload=""></image>
|
|
61
63
|
</view>
|
|
62
64
|
</view>
|
|
63
65
|
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
.tag-container .tag-label {
|
|
44
|
-
padding: 12rpx
|
|
44
|
+
padding: 16rpx 12rpx;
|
|
45
45
|
background-color: #7b2d8e;
|
|
46
46
|
color: #fff;
|
|
47
47
|
font-size: 40rpx;
|
|
@@ -50,18 +50,23 @@
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
.tag-container .tag-time {
|
|
53
|
-
padding: 12rpx
|
|
53
|
+
padding: 12rpx;
|
|
54
54
|
background-color: #fff;
|
|
55
55
|
color: #333;
|
|
56
|
-
font-size:
|
|
56
|
+
font-size: 48rpx;
|
|
57
57
|
font-weight: bold;
|
|
58
|
+
font-family: FengTan-Regular;
|
|
58
59
|
border-radius: 0 8rpx 8rpx 0;
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
.pingfang{
|
|
63
|
+
font-family: PingFang SC-Regular, PingFang SC !important;
|
|
64
|
+
}
|
|
65
|
+
|
|
61
66
|
.info-container {
|
|
62
67
|
background: linear-gradient(90deg, #000000 0%, rgba(0, 0, 0, 0) 100%);
|
|
63
68
|
opacity: 0.5;
|
|
64
|
-
padding:
|
|
69
|
+
padding: 16rpx;
|
|
65
70
|
margin-left: 16rpx;
|
|
66
71
|
margin-bottom: 16rpx;
|
|
67
72
|
border-radius: 8rpx;
|
|
@@ -109,8 +114,9 @@
|
|
|
109
114
|
|
|
110
115
|
.warning-tag {
|
|
111
116
|
display: inline-block;
|
|
112
|
-
background-color: #
|
|
117
|
+
background-color: #DB1C1C;
|
|
113
118
|
color: #fff;
|
|
119
|
+
font-weight: 800;
|
|
114
120
|
font-size: 20rpx;
|
|
115
121
|
padding: 4rpx 12rpx;
|
|
116
122
|
border-radius: 4rpx;
|
|
@@ -123,7 +129,7 @@
|
|
|
123
129
|
left: 0;
|
|
124
130
|
right: 0;
|
|
125
131
|
display: flex;
|
|
126
|
-
justify-content:
|
|
132
|
+
justify-content: space-evenly;
|
|
127
133
|
align-items: center;
|
|
128
134
|
pointer-events: auto;
|
|
129
135
|
}
|
|
@@ -199,8 +205,8 @@
|
|
|
199
205
|
position: fixed;
|
|
200
206
|
left: -9999rpx;
|
|
201
207
|
top: -9999rpx;
|
|
202
|
-
width:
|
|
203
|
-
height:
|
|
208
|
+
width: 1px;
|
|
209
|
+
height: 1px;
|
|
204
210
|
}
|
|
205
211
|
|
|
206
212
|
.loading-overlay {
|
|
@@ -240,3 +246,8 @@
|
|
|
240
246
|
font-size: 28rpx;
|
|
241
247
|
margin-top: 20rpx;
|
|
242
248
|
}
|
|
249
|
+
|
|
250
|
+
.shutter-icon{
|
|
251
|
+
width: 48rpx;
|
|
252
|
+
height: 48rpx;
|
|
253
|
+
}
|