uview-plus 3.4.4 → 3.4.6
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/changelog.md +16 -0
- package/components/u-action-sheet-data/u-action-sheet-data.vue +101 -0
- package/components/u-checkbox/u-checkbox.vue +3 -1
- package/components/u-picker-data/u-picker-data.vue +113 -0
- package/components/u-popup/u-popup.vue +21 -1
- package/components/u-tag/props.js +24 -3
- package/components/u-tag/tag.js +6 -1
- package/components/u-tag/u-tag.vue +21 -0
- package/components/u-upload/props.js +38 -1
- package/components/u-upload/u-upload.vue +294 -35
- package/components/u-upload/upload.js +8 -1
- package/components/u-upload/utils.js +14 -2
- package/libs/function/index.js +115 -28
- package/package.json +1 -1
package/changelog.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## 3.4.6(2025-03-25)
|
|
2
|
+
feat: checkbox触发change时携带name参数
|
|
3
|
+
|
|
4
|
+
feat: upload组件支持服务器本机和阿里云OSS自动上传功能及上传进度条
|
|
5
|
+
|
|
6
|
+
feat: upload组件支持视频预览及oss上传时获取视频封面图
|
|
7
|
+
|
|
8
|
+
feat: 新增up-action-sheet-data快捷组件
|
|
9
|
+
|
|
10
|
+
feat: 新增up-picker-data快捷组件
|
|
11
|
+
|
|
12
|
+
## 3.4.5(2025-03-24)
|
|
13
|
+
feat: tag组件新增textSize/height/padding/borderRadius属性
|
|
14
|
+
|
|
15
|
+
feat: 新增genLightColor自动计算浅色方法及tag组件支持autoBgColor自动计算背景色
|
|
16
|
+
|
|
1
17
|
## 3.4.4(2025-03-13)
|
|
2
18
|
feat: modal增加异步操作进行中点击取消弹出提示特性防止操作被中断
|
|
3
19
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="u-action-sheet-data">
|
|
3
|
+
<view class="u-action-sheet-data__trigger">
|
|
4
|
+
<slot name="trigger"></slot>
|
|
5
|
+
<up-input
|
|
6
|
+
v-if="!$slots['trigger']"
|
|
7
|
+
:modelValue="current"
|
|
8
|
+
disabled
|
|
9
|
+
disabledColor="#ffffff"
|
|
10
|
+
:placeholder="title"
|
|
11
|
+
border="none"
|
|
12
|
+
></up-input>
|
|
13
|
+
<view @click="show = true"
|
|
14
|
+
class="u-action-sheet-data__trigger__cover"></view>
|
|
15
|
+
</view>
|
|
16
|
+
<up-action-sheet
|
|
17
|
+
:show="show"
|
|
18
|
+
:actions="options"
|
|
19
|
+
:title="title"
|
|
20
|
+
safeAreaInsetBottom
|
|
21
|
+
:description="description"
|
|
22
|
+
@close="show = false"
|
|
23
|
+
@select="select"
|
|
24
|
+
>
|
|
25
|
+
</up-action-sheet>
|
|
26
|
+
</view>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script>
|
|
30
|
+
import {mapState} from 'vuex';
|
|
31
|
+
export default {
|
|
32
|
+
props: {
|
|
33
|
+
modelValue: {
|
|
34
|
+
type: [String, Number],
|
|
35
|
+
default: ''
|
|
36
|
+
},
|
|
37
|
+
title: {
|
|
38
|
+
type: String,
|
|
39
|
+
default: ''
|
|
40
|
+
},
|
|
41
|
+
description: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: ''
|
|
44
|
+
},
|
|
45
|
+
options: {
|
|
46
|
+
type: Array,
|
|
47
|
+
default: () => {
|
|
48
|
+
return []
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
valueKey: {
|
|
52
|
+
type: String,
|
|
53
|
+
default: 'value'
|
|
54
|
+
},
|
|
55
|
+
labelKey: {
|
|
56
|
+
type: String,
|
|
57
|
+
default: 'name'
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
data() {
|
|
61
|
+
return {
|
|
62
|
+
show: false,
|
|
63
|
+
current: '',
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
created() {
|
|
67
|
+
if (this.modelValue) {
|
|
68
|
+
this.options.forEach((ele) => {
|
|
69
|
+
if (ele[this.valueKey] == this.modelValue) {
|
|
70
|
+
this.current = ele[this.labelKey]
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
emits: ['update:modelValue'],
|
|
76
|
+
methods: {
|
|
77
|
+
hideKeyboard() {
|
|
78
|
+
uni.hideKeyboard()
|
|
79
|
+
},
|
|
80
|
+
select(e) {
|
|
81
|
+
this.$emit('update:modelValue', e[this.valueKey])
|
|
82
|
+
this.current = e[this.labelKey]
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<style lang="scss" scoped>
|
|
89
|
+
.u-action-sheet-data {
|
|
90
|
+
&__trigger {
|
|
91
|
+
position: relative;
|
|
92
|
+
&__cover {
|
|
93
|
+
position: absolute;
|
|
94
|
+
top: 0;
|
|
95
|
+
left: 0;
|
|
96
|
+
right: 0;
|
|
97
|
+
bottom: 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
</style>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="u-picker-data">
|
|
3
|
+
<view class="u-picker-data__trigger">
|
|
4
|
+
<slot name="trigger"></slot>
|
|
5
|
+
<up-input
|
|
6
|
+
v-if="!$slots['trigger']"
|
|
7
|
+
:modelValue="current"
|
|
8
|
+
disabled
|
|
9
|
+
disabledColor="#ffffff"
|
|
10
|
+
:placeholder="title"
|
|
11
|
+
border="none"
|
|
12
|
+
></up-input>
|
|
13
|
+
<view @click="show = true"
|
|
14
|
+
class="u-picker-data__trigger__cover"></view>
|
|
15
|
+
</view>
|
|
16
|
+
<up-picker
|
|
17
|
+
:show="show"
|
|
18
|
+
:columns="optionsInner"
|
|
19
|
+
:keyName="labelKey"
|
|
20
|
+
@confirm="select"
|
|
21
|
+
@cancel="cancel">
|
|
22
|
+
</up-picker>
|
|
23
|
+
</view>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script>
|
|
27
|
+
import {mapState} from 'vuex';
|
|
28
|
+
export default {
|
|
29
|
+
props: {
|
|
30
|
+
modelValue: {
|
|
31
|
+
type: [String, Number],
|
|
32
|
+
default: ''
|
|
33
|
+
},
|
|
34
|
+
title: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: ''
|
|
37
|
+
},
|
|
38
|
+
description: {
|
|
39
|
+
type: String,
|
|
40
|
+
default: ''
|
|
41
|
+
},
|
|
42
|
+
options: {
|
|
43
|
+
type: Array,
|
|
44
|
+
default: () => {
|
|
45
|
+
return []
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
valueKey: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: 'id'
|
|
51
|
+
},
|
|
52
|
+
labelKey: {
|
|
53
|
+
type: String,
|
|
54
|
+
default: 'name'
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
data() {
|
|
58
|
+
return {
|
|
59
|
+
show: false,
|
|
60
|
+
current: '',
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
created() {
|
|
64
|
+
if (this.modelValue) {
|
|
65
|
+
this.options.forEach((ele) => {
|
|
66
|
+
if (ele[this.valueKey] == this.modelValue) {
|
|
67
|
+
this.current = ele[this.labelKey]
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
computed: {
|
|
73
|
+
optionsInner() {
|
|
74
|
+
return [this.options];
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
emits: ['update:modelValue'],
|
|
78
|
+
methods: {
|
|
79
|
+
hideKeyboard() {
|
|
80
|
+
uni.hideKeyboard()
|
|
81
|
+
},
|
|
82
|
+
cancel() {
|
|
83
|
+
this.show = false;
|
|
84
|
+
},
|
|
85
|
+
select(e) {
|
|
86
|
+
const {
|
|
87
|
+
columnIndex,
|
|
88
|
+
index,
|
|
89
|
+
value,
|
|
90
|
+
} = e;
|
|
91
|
+
this.show = false;
|
|
92
|
+
// console.log(value);
|
|
93
|
+
this.$emit('update:modelValue', value[0][this.valueKey]);
|
|
94
|
+
this.current = value[0][this.labelKey];
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
</script>
|
|
99
|
+
|
|
100
|
+
<style lang="scss" scoped>
|
|
101
|
+
.u-picker-data {
|
|
102
|
+
&__trigger {
|
|
103
|
+
position: relative;
|
|
104
|
+
&__cover {
|
|
105
|
+
position: absolute;
|
|
106
|
+
top: 0;
|
|
107
|
+
left: 0;
|
|
108
|
+
right: 0;
|
|
109
|
+
bottom: 0;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
</style>
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view class="u-popup"
|
|
2
|
+
<view class="u-popup" :class="[customClass]">
|
|
3
|
+
<view class="u-popup__trigger">
|
|
4
|
+
<slot name="trigger">
|
|
5
|
+
</slot>
|
|
6
|
+
<view @click="open"
|
|
7
|
+
class="u-popup__trigger__cover"></view>
|
|
8
|
+
</view>
|
|
3
9
|
<u-overlay
|
|
4
10
|
:show="show"
|
|
5
11
|
@click="overlayClick"
|
|
@@ -188,6 +194,9 @@
|
|
|
188
194
|
this.$emit('close')
|
|
189
195
|
}
|
|
190
196
|
},
|
|
197
|
+
open(e) {
|
|
198
|
+
this.$emit('update:show', true)
|
|
199
|
+
},
|
|
191
200
|
close(e) {
|
|
192
201
|
this.$emit('update:show', false)
|
|
193
202
|
this.$emit('close')
|
|
@@ -240,6 +249,17 @@
|
|
|
240
249
|
|
|
241
250
|
.u-popup {
|
|
242
251
|
flex: $u-popup-flex;
|
|
252
|
+
|
|
253
|
+
&__trigger {
|
|
254
|
+
position: relative;
|
|
255
|
+
&__cover {
|
|
256
|
+
position: absolute;
|
|
257
|
+
top: 0;
|
|
258
|
+
left: 0;
|
|
259
|
+
right: 0;
|
|
260
|
+
bottom: 0;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
243
263
|
|
|
244
264
|
&__content {
|
|
245
265
|
background-color: $u-popup-content-background-color;
|
|
@@ -82,9 +82,30 @@ export const props = defineMixin({
|
|
|
82
82
|
type: String,
|
|
83
83
|
default: () => defProps.tag.icon,
|
|
84
84
|
},
|
|
85
|
-
|
|
85
|
+
// 自定义尺寸字体大小
|
|
86
|
+
textSize: {
|
|
86
87
|
type: String,
|
|
87
|
-
default: () => defProps.tag.
|
|
88
|
-
}
|
|
88
|
+
default: () => defProps.tag.textSize
|
|
89
|
+
},
|
|
90
|
+
// 自定义尺寸高度
|
|
91
|
+
height: {
|
|
92
|
+
type: String,
|
|
93
|
+
default: () => defProps.tag.height
|
|
94
|
+
},
|
|
95
|
+
// 自定义尺寸padding
|
|
96
|
+
padding: {
|
|
97
|
+
type: String,
|
|
98
|
+
default: () => defProps.tag.padding
|
|
99
|
+
},
|
|
100
|
+
// 自定义尺寸
|
|
101
|
+
borderRadius: {
|
|
102
|
+
type: String,
|
|
103
|
+
default: () => defProps.tag.borderRadius
|
|
104
|
+
},
|
|
105
|
+
// 自动计算背景色
|
|
106
|
+
autoBgColor: {
|
|
107
|
+
type: Number,
|
|
108
|
+
default: () => defProps.tag.autoBgColor
|
|
109
|
+
},
|
|
89
110
|
}
|
|
90
111
|
})
|
package/components/u-tag/tag.js
CHANGED
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
import { mpMixin } from '../../libs/mixin/mpMixin';
|
|
65
65
|
import { mixin } from '../../libs/mixin/mixin';
|
|
66
66
|
import test from '../../libs/function/test';
|
|
67
|
+
import { addUnit, genLightColor } from '../../libs/function/index';
|
|
67
68
|
/**
|
|
68
69
|
* Tag 标签
|
|
69
70
|
* @description tag组件一般用于标记和选择,我们提供了更加丰富的表现形式,能够较全面的涵盖您的使用场景
|
|
@@ -107,6 +108,19 @@
|
|
|
107
108
|
if(this.borderColor) {
|
|
108
109
|
style.borderColor = this.borderColor
|
|
109
110
|
}
|
|
111
|
+
if (this.height) {
|
|
112
|
+
style.height = addUnit(this.height)
|
|
113
|
+
style.lineHeight = addUnit(this.height)
|
|
114
|
+
}
|
|
115
|
+
if (this.padding) {
|
|
116
|
+
style.padding = this.padding
|
|
117
|
+
}
|
|
118
|
+
if (this.borderRadius) {
|
|
119
|
+
style.borderRadius = addUnit(this.borderRadius)
|
|
120
|
+
}
|
|
121
|
+
if (this.autoBgColor > 0 && this.color) {
|
|
122
|
+
style.backgroundColor = this.getBagColor(this.color)
|
|
123
|
+
}
|
|
110
124
|
return style
|
|
111
125
|
},
|
|
112
126
|
// nvue下,文本颜色无法继承父元素
|
|
@@ -115,6 +129,9 @@
|
|
|
115
129
|
if (this.color) {
|
|
116
130
|
style.color = this.color
|
|
117
131
|
}
|
|
132
|
+
if (this.textSize) {
|
|
133
|
+
style.textSize = addUnit(this.textSize)
|
|
134
|
+
}
|
|
118
135
|
return style
|
|
119
136
|
},
|
|
120
137
|
imgStyle() {
|
|
@@ -149,6 +166,10 @@
|
|
|
149
166
|
// 点击标签
|
|
150
167
|
clickHandler() {
|
|
151
168
|
this.$emit('click', this.name)
|
|
169
|
+
},
|
|
170
|
+
// 根据颜色计算浅色作为背景
|
|
171
|
+
getBagColor(darkColor) {
|
|
172
|
+
return genLightColor(darkColor, this.autoBgColor)
|
|
152
173
|
}
|
|
153
174
|
}
|
|
154
175
|
}
|
|
@@ -125,6 +125,43 @@ export const props = defineMixin({
|
|
|
125
125
|
previewImage: {
|
|
126
126
|
type: Boolean,
|
|
127
127
|
default: () => defProps.upload.previewImage
|
|
128
|
-
}
|
|
128
|
+
},
|
|
129
|
+
// 是否自动删除
|
|
130
|
+
autoDelete: {
|
|
131
|
+
type: Boolean,
|
|
132
|
+
default: () => defProps.upload.autoDelete
|
|
133
|
+
},
|
|
134
|
+
// 是否自动上传需要传递action指定地址
|
|
135
|
+
autoUpload: {
|
|
136
|
+
type: Boolean,
|
|
137
|
+
default: () => defProps.upload.autoUpload
|
|
138
|
+
},
|
|
139
|
+
// 自动上传接口地址
|
|
140
|
+
autoUploadApi: {
|
|
141
|
+
type: String,
|
|
142
|
+
default: () => defProps.upload.autoUploadApi
|
|
143
|
+
},
|
|
144
|
+
// 自动上传驱动,local/oss/cos/kodo
|
|
145
|
+
autoUploadDriver: {
|
|
146
|
+
type: String,
|
|
147
|
+
default: () => defProps.upload.autoUploadDriver
|
|
148
|
+
},
|
|
149
|
+
// 自动上传授权接口,比如oss的签名接口。
|
|
150
|
+
autoUploadAuthUrl: {
|
|
151
|
+
type: String,
|
|
152
|
+
default: () => defProps.upload.autoUploadAuthUrl
|
|
153
|
+
},
|
|
154
|
+
// 自动上传携带的header
|
|
155
|
+
autoUploadHeader: {
|
|
156
|
+
type: Object,
|
|
157
|
+
default: () => {
|
|
158
|
+
return defProps.upload.autoUploadHeader
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
// 本地计算视频封面
|
|
162
|
+
getVideoThumb: {
|
|
163
|
+
type: Boolean,
|
|
164
|
+
default: () => defProps.upload.getVideoThumb
|
|
165
|
+
},
|
|
129
166
|
}
|
|
130
167
|
})
|
|
@@ -18,6 +18,27 @@
|
|
|
18
18
|
height: addUnit(height)
|
|
19
19
|
}]"
|
|
20
20
|
/>
|
|
21
|
+
<template
|
|
22
|
+
v-else-if="(item.isVideo || (item.type && item.type === 'video')) && getVideoThumb">
|
|
23
|
+
<image
|
|
24
|
+
:src="item.thumb"
|
|
25
|
+
:mode="imageMode"
|
|
26
|
+
class="u-upload__wrap__preview__image"
|
|
27
|
+
@tap="onPreviewVideo(item, index)"
|
|
28
|
+
:style="[{
|
|
29
|
+
width: addUnit(width),
|
|
30
|
+
height: addUnit(height)
|
|
31
|
+
}]"
|
|
32
|
+
/>
|
|
33
|
+
<view v-if="item.status === 'success'"
|
|
34
|
+
class="u-upload__wrap__play"
|
|
35
|
+
@tap="onPreviewVideo(item, index)">
|
|
36
|
+
<slot name="playIcon"></slot>
|
|
37
|
+
<up-icon v-if="!$slots['playIcon']"
|
|
38
|
+
class="u-upload__wrap__play__icon"
|
|
39
|
+
name="play-right" size="22px"></up-icon>
|
|
40
|
+
</view>
|
|
41
|
+
</template>
|
|
21
42
|
<view
|
|
22
43
|
v-else
|
|
23
44
|
class="u-upload__wrap__preview__other"
|
|
@@ -54,6 +75,8 @@
|
|
|
54
75
|
v-if="item.message"
|
|
55
76
|
class="u-upload__status__message"
|
|
56
77
|
>{{ item.message }}</text>
|
|
78
|
+
<up-gap class="u-upload__progress" height="3px"
|
|
79
|
+
:style="{width: item.progress + '%'}"></up-gap>
|
|
57
80
|
</view>
|
|
58
81
|
<view
|
|
59
82
|
class="u-upload__deletable"
|
|
@@ -68,30 +91,45 @@
|
|
|
68
91
|
></u-icon>
|
|
69
92
|
</view>
|
|
70
93
|
</view>
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<u-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
<slot name="success">
|
|
95
|
+
<view
|
|
96
|
+
class="u-upload__success"
|
|
97
|
+
v-if="item.status === 'success'"
|
|
98
|
+
>
|
|
99
|
+
<!-- #ifdef APP-NVUE -->
|
|
100
|
+
<image
|
|
101
|
+
:src="successIcon"
|
|
102
|
+
class="u-upload__success__icon"
|
|
103
|
+
></image>
|
|
104
|
+
<!-- #endif -->
|
|
105
|
+
<!-- #ifndef APP-NVUE -->
|
|
106
|
+
<view class="u-upload__success__icon">
|
|
107
|
+
<u-icon
|
|
108
|
+
name="checkmark"
|
|
109
|
+
color="#ffffff"
|
|
110
|
+
size="12"
|
|
111
|
+
></u-icon>
|
|
112
|
+
</view>
|
|
113
|
+
<!-- #endif -->
|
|
88
114
|
</view>
|
|
89
|
-
|
|
90
|
-
</view>
|
|
115
|
+
</slot>
|
|
91
116
|
</view>
|
|
92
|
-
|
|
117
|
+
<up-popup
|
|
118
|
+
mode="center"
|
|
119
|
+
v-model:show="popupShow">
|
|
120
|
+
<video id="myVideo"
|
|
121
|
+
:src="currentItemIndex >= 0 ? lists[currentItemIndex].url : ''"
|
|
122
|
+
@error="videoErrorCallback" show-center-play-btn
|
|
123
|
+
object-fit='cover' show-fullscreen-btn='true'
|
|
124
|
+
enable-play-gesture controls
|
|
125
|
+
:autoplay="true" auto-pause-if-open-native
|
|
126
|
+
@loadedmetadata="loadedVideoMetadata"
|
|
127
|
+
:initial-time='0.1'>
|
|
128
|
+
</video>
|
|
129
|
+
</up-popup>
|
|
93
130
|
</template>
|
|
94
|
-
|
|
131
|
+
<canvas id="myCanvas" type="2d"
|
|
132
|
+
style="width: 100px; height: 150px;display: none;"></canvas>
|
|
95
133
|
<template v-if="isInCount">
|
|
96
134
|
<view
|
|
97
135
|
v-if="$slots.trigger"
|
|
@@ -185,6 +223,8 @@
|
|
|
185
223
|
// #endif
|
|
186
224
|
lists: [],
|
|
187
225
|
isInCount: true,
|
|
226
|
+
popupShow: false,
|
|
227
|
+
currentItemIndex: -1
|
|
188
228
|
}
|
|
189
229
|
},
|
|
190
230
|
watch: {
|
|
@@ -204,14 +244,74 @@
|
|
|
204
244
|
},
|
|
205
245
|
accept(newVal) {
|
|
206
246
|
this.formatFileList()
|
|
247
|
+
},
|
|
248
|
+
popupShow(newVal) {
|
|
249
|
+
if (!newVal) {
|
|
250
|
+
this.currentItemIndex = -1;
|
|
251
|
+
}
|
|
207
252
|
}
|
|
208
253
|
},
|
|
209
254
|
// #ifdef VUE3
|
|
210
|
-
emits: ['error', 'beforeRead', 'oversize', 'afterRead', 'delete', 'clickPreview'],
|
|
255
|
+
emits: ['error', 'beforeRead', 'oversize', 'afterRead', 'delete', 'clickPreview', 'update:fileList'],
|
|
211
256
|
// #endif
|
|
212
257
|
methods: {
|
|
213
258
|
addUnit,
|
|
214
259
|
addStyle,
|
|
260
|
+
videoErrorCallback() {},
|
|
261
|
+
loadedVideoMetadata(e) {
|
|
262
|
+
if (this.currentItemIndex < 0) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (this.autoUploadDriver != 'local') {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (!this.getVideoThumb) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
// 截取第一帧作为封面,oss等云存储场景直接使用拼接参数。
|
|
272
|
+
let w = this.lists[this.currentItemIndex].width;
|
|
273
|
+
let h = this.lists[this.currentItemIndex].height;
|
|
274
|
+
const dpr = uni.getSystemInfoSync().pixelRatio;
|
|
275
|
+
uni.createSelectorQuery().select('#myVideo').context(res => {
|
|
276
|
+
console.log('select video', res)
|
|
277
|
+
const myVideo = res.context
|
|
278
|
+
uni.createSelectorQuery()
|
|
279
|
+
.select('#myCanvas')
|
|
280
|
+
.fields({ node: true, size: true })
|
|
281
|
+
.exec(([res]) => {
|
|
282
|
+
console.log('select canvas', res)
|
|
283
|
+
const ctx1 = res[0].node.getContext('2d')
|
|
284
|
+
res[0].node.width = w * dpr
|
|
285
|
+
res[0].node.height = h * dpr
|
|
286
|
+
// Draw the first frame and export it as an image
|
|
287
|
+
// myVideo.onPlay(() => {
|
|
288
|
+
setTimeout(() => {
|
|
289
|
+
captureFirstFrame()
|
|
290
|
+
}, 500)
|
|
291
|
+
// })
|
|
292
|
+
const captureFirstFrame = () => {
|
|
293
|
+
ctx1.drawImage(myVideo, 0, 0, w * dpr, h * dpr)
|
|
294
|
+
wx.canvasToTempFilePath({
|
|
295
|
+
canvas: res[0].node,
|
|
296
|
+
success: (result) => {
|
|
297
|
+
console.log('First frame image path:', result
|
|
298
|
+
.tempFilePath)
|
|
299
|
+
// Now you can use the image path (result.tempFilePath)
|
|
300
|
+
this.fileList['currentItemIndex'].thumb = result.tempFilePath
|
|
301
|
+
},
|
|
302
|
+
fail: (err) => {
|
|
303
|
+
console.error('Failed to export image:', err)
|
|
304
|
+
}
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Capture the first frame
|
|
309
|
+
setInterval(() => {
|
|
310
|
+
ctx1.drawImage(myVideo, 0, 0, w * dpr, h * dpr);
|
|
311
|
+
}, 1000 / 24)
|
|
312
|
+
}).exec()
|
|
313
|
+
}).exec()
|
|
314
|
+
},
|
|
215
315
|
formatFileList() {
|
|
216
316
|
const {
|
|
217
317
|
fileList = [], maxCount
|
|
@@ -304,7 +404,7 @@
|
|
|
304
404
|
index: index == null ? this.fileList.length : index,
|
|
305
405
|
};
|
|
306
406
|
},
|
|
307
|
-
onAfterRead(file) {
|
|
407
|
+
async onAfterRead(file) {
|
|
308
408
|
const {
|
|
309
409
|
maxSize,
|
|
310
410
|
afterRead
|
|
@@ -313,25 +413,158 @@
|
|
|
313
413
|
file.some((item) => item.size > maxSize) :
|
|
314
414
|
file.size > maxSize;
|
|
315
415
|
if (oversize) {
|
|
416
|
+
uni.showToast({
|
|
417
|
+
title: '超过大小限制'
|
|
418
|
+
})
|
|
316
419
|
this.$emit('oversize', Object.assign({
|
|
317
420
|
file
|
|
318
421
|
}, this.getDetail()));
|
|
319
422
|
return;
|
|
320
423
|
}
|
|
321
|
-
|
|
322
|
-
|
|
424
|
+
let len = this.fileList.length;
|
|
425
|
+
if (this.autoUpload) {
|
|
426
|
+
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
|
|
427
|
+
let lists = [].concat(file);
|
|
428
|
+
let fileListLen = this.fileList.length;
|
|
429
|
+
lists.map((item) => {
|
|
430
|
+
this.fileList.push({
|
|
431
|
+
...item,
|
|
432
|
+
status: 'uploading',
|
|
433
|
+
message: '上传中',
|
|
434
|
+
progress: 0
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
let that = this;
|
|
438
|
+
this.$emit('update:fileList', this.fileList);
|
|
439
|
+
for (let i = 0; i < lists.length; i++) {
|
|
440
|
+
let j = i;
|
|
441
|
+
let result = '';
|
|
442
|
+
switch(this.autoUploadDriver) {
|
|
443
|
+
case 'cos': // 腾讯云
|
|
444
|
+
break;
|
|
445
|
+
case 'kodo': // 七牛云
|
|
446
|
+
break;
|
|
447
|
+
case 'oss':
|
|
448
|
+
case 'upload_oss':
|
|
449
|
+
// 阿里云前端直传
|
|
450
|
+
// 获取签名
|
|
451
|
+
console.log()
|
|
452
|
+
let formData = {};
|
|
453
|
+
let ret = await uni.request({
|
|
454
|
+
url: this.autoUploadAuthUrl,
|
|
455
|
+
method: 'get',
|
|
456
|
+
header: this.autoUploadHeader,
|
|
457
|
+
data: {
|
|
458
|
+
filename: lists[j].name
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
// console.log(ret);
|
|
462
|
+
let res0 = ret.data;
|
|
463
|
+
if (res0.code == 200) {
|
|
464
|
+
// 路径 + 文件名 + 扩展名
|
|
465
|
+
// 不传递filename就要拼接key
|
|
466
|
+
// res0.data.params.key = res0.data.params.dir + res0.data.params.uniqidName + fileExt;
|
|
467
|
+
formData = res0.data.params;
|
|
468
|
+
} else {
|
|
469
|
+
uni.showToast({
|
|
470
|
+
title: res0.msg,
|
|
471
|
+
duration: 1500
|
|
472
|
+
});
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
var uploadTask = uni.uploadFile({
|
|
476
|
+
url: res0.data.params.host,
|
|
477
|
+
filePath: lists[j].url,
|
|
478
|
+
name: 'file',
|
|
479
|
+
// fileType: 'video', // 仅支付宝小程序,且必填。
|
|
480
|
+
// header: header,
|
|
481
|
+
formData: formData,
|
|
482
|
+
success: (uploadFileRes) => {
|
|
483
|
+
result = res0.data.params.host + '/' + res0.data.params.key;
|
|
484
|
+
let thumb = '';
|
|
485
|
+
if (this.accept === 'video' || test.video(result)) {
|
|
486
|
+
thumb = result + '?x-oss-process=video/snapshot,t_10000,m_fast';
|
|
487
|
+
}
|
|
488
|
+
that.succcessUpload(len + j, result, thumb);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
uploadTask.onProgressUpdate((res) => {
|
|
492
|
+
that.updateUpload(len + j, {
|
|
493
|
+
progress: res.progress
|
|
494
|
+
});
|
|
495
|
+
// console.log('上传进度' + res.progress);
|
|
496
|
+
// console.log('已经上传的数据长度' + res.totalBytesSent);
|
|
497
|
+
// console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend);
|
|
498
|
+
});
|
|
499
|
+
break;
|
|
500
|
+
case 'local':
|
|
501
|
+
default:
|
|
502
|
+
// 服务器本机上传
|
|
503
|
+
var uploadTask = uni.uploadFile({
|
|
504
|
+
url: this.autoUploadApi,
|
|
505
|
+
filePath: lists[j].url,
|
|
506
|
+
name: 'file',
|
|
507
|
+
// fileType: 'video', // 仅支付宝小程序,且必填。
|
|
508
|
+
header: this.autoUploadHeader,
|
|
509
|
+
success: (r) => {
|
|
510
|
+
result = res0.data.params.host + '/' + res0.data.params.key;
|
|
511
|
+
that.succcessUpload(len + j, result);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
uploadTask.onProgressUpdate((res) => {
|
|
515
|
+
that.updateUpload(len + j, {
|
|
516
|
+
progress: res.progress
|
|
517
|
+
});
|
|
518
|
+
// console.log('上传进度' + res.progress);
|
|
519
|
+
// console.log('已经上传的数据长度' + res.totalBytesSent);
|
|
520
|
+
// console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend);
|
|
521
|
+
});
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
} else {
|
|
526
|
+
if (typeof afterRead === 'function') {
|
|
527
|
+
afterRead(file, this.getDetail());
|
|
528
|
+
}
|
|
529
|
+
this.$emit('afterRead', Object.assign({
|
|
530
|
+
file
|
|
531
|
+
}, this.getDetail()));
|
|
323
532
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
533
|
+
},
|
|
534
|
+
updateUpload(index, param) {
|
|
535
|
+
let item = this.fileList[index];
|
|
536
|
+
this.fileList.splice(index, 1, {
|
|
537
|
+
...item,
|
|
538
|
+
status: 'uploading',
|
|
539
|
+
message: '',
|
|
540
|
+
progress: param.progress
|
|
541
|
+
});
|
|
542
|
+
this.$emit('update:fileList', this.fileList);
|
|
543
|
+
},
|
|
544
|
+
succcessUpload(index, url, thumb = '') {
|
|
545
|
+
let item = this.fileList[index];
|
|
546
|
+
this.fileList.splice(index, 1, {
|
|
547
|
+
...item,
|
|
548
|
+
status: 'success',
|
|
549
|
+
message: '',
|
|
550
|
+
url: url,
|
|
551
|
+
progress: 100,
|
|
552
|
+
thumb: thumb
|
|
553
|
+
});
|
|
554
|
+
this.$emit('update:fileList', this.fileList);
|
|
327
555
|
},
|
|
328
556
|
deleteItem(index) {
|
|
329
|
-
this
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
557
|
+
if (this.autoDelete) {
|
|
558
|
+
this.fileList.splice(index, 1);
|
|
559
|
+
this.$emit('update:fileList', this.fileList);
|
|
560
|
+
} else {
|
|
561
|
+
this.$emit(
|
|
562
|
+
'delete',
|
|
563
|
+
Object.assign(Object.assign({}, this.getDetail(index)), {
|
|
564
|
+
file: this.fileList[index],
|
|
565
|
+
})
|
|
566
|
+
);
|
|
567
|
+
}
|
|
335
568
|
},
|
|
336
569
|
// 预览图片
|
|
337
570
|
onPreviewImage(previewItem, index) {
|
|
@@ -360,7 +593,7 @@
|
|
|
360
593
|
},
|
|
361
594
|
});
|
|
362
595
|
},
|
|
363
|
-
onPreviewVideo(index) {
|
|
596
|
+
onPreviewVideo(previewItem, index) {
|
|
364
597
|
if (!this.previewFullImage) return;
|
|
365
598
|
let current = 0;
|
|
366
599
|
const sources = [];
|
|
@@ -380,6 +613,11 @@
|
|
|
380
613
|
if (sources.length < 1) {
|
|
381
614
|
return;
|
|
382
615
|
}
|
|
616
|
+
// #ifndef MP-WEIXIN
|
|
617
|
+
this.popupShow = true;
|
|
618
|
+
this.currentItemIndex = index;
|
|
619
|
+
console.log(this.lists[this.currentItemIndex])
|
|
620
|
+
// #endif
|
|
383
621
|
// #ifdef MP-WEIXIN
|
|
384
622
|
wx.previewMedia({
|
|
385
623
|
sources: sources,
|
|
@@ -500,6 +738,21 @@
|
|
|
500
738
|
}
|
|
501
739
|
}
|
|
502
740
|
}
|
|
741
|
+
&__wrap__play {
|
|
742
|
+
position: absolute;
|
|
743
|
+
top: 0px;
|
|
744
|
+
left: 0px;
|
|
745
|
+
bottom: 0px;
|
|
746
|
+
right: 0px;
|
|
747
|
+
display: flex;
|
|
748
|
+
justify-content: center;
|
|
749
|
+
align-items: center;
|
|
750
|
+
&__icon {
|
|
751
|
+
background: #fff;
|
|
752
|
+
border-radius: 100px;
|
|
753
|
+
opacity: 0.8;
|
|
754
|
+
};
|
|
755
|
+
}
|
|
503
756
|
|
|
504
757
|
&__deletable {
|
|
505
758
|
position: absolute;
|
|
@@ -557,6 +810,12 @@
|
|
|
557
810
|
/* #endif */
|
|
558
811
|
}
|
|
559
812
|
}
|
|
813
|
+
&__progress {
|
|
814
|
+
background-color: $u-primary !important;
|
|
815
|
+
position: absolute;
|
|
816
|
+
bottom: 0;
|
|
817
|
+
left: 0;
|
|
818
|
+
}
|
|
560
819
|
|
|
561
820
|
&__status {
|
|
562
821
|
position: absolute;
|
|
@@ -32,6 +32,13 @@ export default {
|
|
|
32
32
|
uploadText: '',
|
|
33
33
|
width: 80,
|
|
34
34
|
height: 80,
|
|
35
|
-
previewImage: true
|
|
35
|
+
previewImage: true,
|
|
36
|
+
autoDelete: false,
|
|
37
|
+
autoUpload: false,
|
|
38
|
+
autoUploadApi: '',
|
|
39
|
+
autoUploadAuthUrl: '',
|
|
40
|
+
autoUploadDriver: '',
|
|
41
|
+
autoUploadHeader: {},
|
|
42
|
+
getVideoThumb: false
|
|
36
43
|
}
|
|
37
44
|
}
|
|
@@ -21,21 +21,30 @@ function formatImage(res) {
|
|
|
21
21
|
// #ifdef H5
|
|
22
22
|
name: item.name,
|
|
23
23
|
file: item
|
|
24
|
+
// #endif
|
|
25
|
+
// #ifndef H5
|
|
26
|
+
name: res.tempFilePath.split('/').pop() + '.png',
|
|
24
27
|
// #endif
|
|
25
28
|
}))
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
function formatVideo(res) {
|
|
31
|
+
function formatVideo(res) {
|
|
32
|
+
console.log(res)
|
|
29
33
|
return [
|
|
30
34
|
{
|
|
31
35
|
...pickExclude(res, ['tempFilePath', 'thumbTempFilePath', 'errMsg']),
|
|
32
36
|
type: 'video',
|
|
33
37
|
url: res.tempFilePath,
|
|
34
38
|
thumb: res.thumbTempFilePath,
|
|
35
|
-
size: res.size,
|
|
39
|
+
size: res.size,
|
|
40
|
+
width: res.width || 0, // APP 2.1.0+、H5、微信小程序、京东小程序
|
|
41
|
+
height: res.height || 0, // APP 2.1.0+、H5、微信小程序、京东小程序
|
|
36
42
|
// #ifdef H5
|
|
37
43
|
name: res.name,
|
|
38
44
|
file: res
|
|
45
|
+
// #endif
|
|
46
|
+
// #ifndef H5
|
|
47
|
+
name: res.tempFilePath.split('/').pop() + '.mp4',
|
|
39
48
|
// #endif
|
|
40
49
|
}
|
|
41
50
|
]
|
|
@@ -50,6 +59,9 @@ function formatMedia(res) {
|
|
|
50
59
|
size: item.size,
|
|
51
60
|
// #ifdef H5
|
|
52
61
|
file: item
|
|
62
|
+
// #endif
|
|
63
|
+
// #ifndef H5
|
|
64
|
+
name: res.tempFilePath.split('/').pop() + (res.type === 'video' ? '.mp4': '.png'),
|
|
53
65
|
// #endif
|
|
54
66
|
}))
|
|
55
67
|
}
|
package/libs/function/index.js
CHANGED
|
@@ -49,12 +49,12 @@ export function sleep(value = 30) {
|
|
|
49
49
|
* @returns {string} 返回所在平台(小写)
|
|
50
50
|
* @link 运行期判断平台 https://uniapp.dcloud.io/frame?id=判断平台
|
|
51
51
|
*/
|
|
52
|
-
export function os() {
|
|
53
|
-
// #ifdef APP || H5 || MP-WEIXIN
|
|
54
|
-
return uni.getDeviceInfo().platform.toLowerCase()
|
|
55
|
-
// #endif
|
|
56
|
-
// #ifndef APP || H5 || MP-WEIXIN
|
|
57
|
-
return uni.getSystemInfoSync().platform.toLowerCase()
|
|
52
|
+
export function os() {
|
|
53
|
+
// #ifdef APP || H5 || MP-WEIXIN
|
|
54
|
+
return uni.getDeviceInfo().platform.toLowerCase()
|
|
55
|
+
// #endif
|
|
56
|
+
// #ifndef APP || H5 || MP-WEIXIN
|
|
57
|
+
return uni.getSystemInfoSync().platform.toLowerCase()
|
|
58
58
|
// #endif
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
@@ -63,26 +63,26 @@ export function os() {
|
|
|
63
63
|
*/
|
|
64
64
|
export function sys() {
|
|
65
65
|
return uni.getSystemInfoSync()
|
|
66
|
-
}
|
|
67
|
-
export function getWindowInfo() {
|
|
68
|
-
let ret = {}
|
|
69
|
-
// #ifdef APP || H5 || MP-WEIXIN
|
|
70
|
-
ret = uni.getWindowInfo()
|
|
71
|
-
// #endif
|
|
72
|
-
// #ifndef APP || H5 || MP-WEIXIN
|
|
73
|
-
ret = sys()
|
|
74
|
-
// #endif
|
|
75
|
-
return ret
|
|
76
|
-
}
|
|
77
|
-
export function getDeviceInfo() {
|
|
78
|
-
let ret = {}
|
|
79
|
-
// #ifdef APP || H5 || MP-WEIXIN
|
|
80
|
-
ret = uni.getDeviceInfo()
|
|
81
|
-
// #endif
|
|
82
|
-
// #ifndef APP || H5 || MP-WEIXIN
|
|
83
|
-
ret = sys()
|
|
84
|
-
// #endif
|
|
85
|
-
return ret
|
|
66
|
+
}
|
|
67
|
+
export function getWindowInfo() {
|
|
68
|
+
let ret = {}
|
|
69
|
+
// #ifdef APP || H5 || MP-WEIXIN
|
|
70
|
+
ret = uni.getWindowInfo()
|
|
71
|
+
// #endif
|
|
72
|
+
// #ifndef APP || H5 || MP-WEIXIN
|
|
73
|
+
ret = sys()
|
|
74
|
+
// #endif
|
|
75
|
+
return ret
|
|
76
|
+
}
|
|
77
|
+
export function getDeviceInfo() {
|
|
78
|
+
let ret = {}
|
|
79
|
+
// #ifdef APP || H5 || MP-WEIXIN
|
|
80
|
+
ret = uni.getDeviceInfo()
|
|
81
|
+
// #endif
|
|
82
|
+
// #ifndef APP || H5 || MP-WEIXIN
|
|
83
|
+
ret = sys()
|
|
84
|
+
// #endif
|
|
85
|
+
return ret
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/**
|
|
@@ -730,12 +730,99 @@ export function getValueByPath(obj, path) {
|
|
|
730
730
|
}, obj);
|
|
731
731
|
}
|
|
732
732
|
|
|
733
|
+
/**
|
|
734
|
+
* 生成同色系浅色背景色
|
|
735
|
+
* @param {string} textColor - 支持 #RGB、#RRGGBB、rgb()、rgba() 格式
|
|
736
|
+
* @param {number} [lightness=85] - 目标亮度百分比(默认85%)
|
|
737
|
+
* @returns {string} 十六进制颜色值
|
|
738
|
+
*/
|
|
739
|
+
export function genLightColor(textColor, lightness = 95) {
|
|
740
|
+
// 手动解析颜色值(避免使用document)
|
|
741
|
+
const rgb = parseColorWithoutDOM(textColor);
|
|
742
|
+
|
|
743
|
+
// RGB转HSL色域
|
|
744
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
745
|
+
|
|
746
|
+
// 生成浅色背景
|
|
747
|
+
const bgHsl = {
|
|
748
|
+
h: hsl.h,
|
|
749
|
+
s: hsl.s,
|
|
750
|
+
l: Math.min(lightness, 95)
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
return hslToHex(bgHsl.h, bgHsl.s, bgHsl.l);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/* 手动解析颜色字符串(兼容uni-app环境) */
|
|
757
|
+
function parseColorWithoutDOM(colorStr) {
|
|
758
|
+
// 统一转小写处理
|
|
759
|
+
const str = colorStr.toLowerCase().trim();
|
|
760
|
+
|
|
761
|
+
// 处理十六进制格式
|
|
762
|
+
if (str.startsWith('#')) {
|
|
763
|
+
const hex = str.replace('#', '');
|
|
764
|
+
const fullHex = hex.length === 3 ?
|
|
765
|
+
hex.split('').map(c => c + c).join('') : hex;
|
|
766
|
+
|
|
767
|
+
return {
|
|
768
|
+
r: parseInt(fullHex.substring(0,2), 16),
|
|
769
|
+
g: parseInt(fullHex.substring(2,4), 16),
|
|
770
|
+
b: parseInt(fullHex.substring(4,6), 16)
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// 处理rgb/rgba格式
|
|
775
|
+
const rgbMatch = str.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
776
|
+
if (rgbMatch) {
|
|
777
|
+
return {
|
|
778
|
+
r: +rgbMatch[1],
|
|
779
|
+
g: +rgbMatch[2],
|
|
780
|
+
b: +rgbMatch[3]
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
throw new Error('Invalid color format');
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
// 辅助函数:RGB 转 HSL(色相、饱和度、亮度)
|
|
788
|
+
function rgbToHsl(r, g, b) {
|
|
789
|
+
r /= 255, g /= 255, b /= 255;
|
|
790
|
+
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
791
|
+
let h, s, l = (max + min) / 2;
|
|
792
|
+
|
|
793
|
+
if (max === min) {
|
|
794
|
+
h = s = 0; // achromatic
|
|
795
|
+
} else {
|
|
796
|
+
const d = max - min;
|
|
797
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
798
|
+
switch (max) {
|
|
799
|
+
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
|
800
|
+
case g: h = (b - r) / d + 2; break;
|
|
801
|
+
case b: h = (r - g) / d + 4; break;
|
|
802
|
+
}
|
|
803
|
+
h = (h * 60).toFixed(1);
|
|
804
|
+
}
|
|
805
|
+
return { h: +h, s: +(s * 100).toFixed(1), l: +(l * 100).toFixed(1) };
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// 辅助函数:HSL 转十六进制
|
|
809
|
+
function hslToHex(h, s, l) {
|
|
810
|
+
l /= 100;
|
|
811
|
+
const a = s * Math.min(l, 1 - l) / 100;
|
|
812
|
+
const f = n => {
|
|
813
|
+
const k = (n + h / 30) % 12;
|
|
814
|
+
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
815
|
+
return Math.round(255 * color).toString(16).padStart(2, '0');
|
|
816
|
+
};
|
|
817
|
+
return `#${f(0)}${f(8)}${f(4)}`;
|
|
818
|
+
}
|
|
819
|
+
|
|
733
820
|
export default {
|
|
734
821
|
range,
|
|
735
822
|
getPx,
|
|
736
823
|
sleep,
|
|
737
824
|
os,
|
|
738
|
-
sys,
|
|
825
|
+
sys,
|
|
739
826
|
getWindowInfo,
|
|
740
827
|
random,
|
|
741
828
|
guid,
|
|
@@ -762,5 +849,5 @@ export default {
|
|
|
762
849
|
page,
|
|
763
850
|
pages,
|
|
764
851
|
getValueByPath,
|
|
765
|
-
|
|
852
|
+
genLightColor
|
|
766
853
|
}
|