lxui-uni 0.0.2 → 0.0.4
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/README.md +6 -0
- package/components/lx-header/lx-header.vue +250 -0
- package/{lib → components/lx-hello}/lx-hello.vue +5 -0
- package/components/lx-image/index.ts +3 -0
- package/components/lx-image/lx-image.vue +102 -0
- package/components/lx-list/lx-list.vue +162 -0
- package/components/lx-list-state/lx-list-state.vue +92 -0
- package/components/lx-operate-bottom/lx-operate-bottom.vue +107 -0
- package/components/lx-submit-btn/lx-submit-btn.vue +61 -0
- package/components/lx-upload/lx-upload.vue +192 -0
- package/index.ts +11 -4
- package/package.json +2 -2
- package/theme.scss +228 -0
- package/types/components.d.ts +23 -0
- package/util/index.ts +294 -0
- package/util/useListLoadClass.ts +143 -0
- package/vite.config.ts +1 -0
- package/lib/lx-image.vue +0 -82
package/theme.scss
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/*============================= 文字尺寸 =============================*/
|
|
2
|
+
$font-size-20: 20rpx;
|
|
3
|
+
$font-size-22: 22rpx;
|
|
4
|
+
$font-size-24: 24rpx;
|
|
5
|
+
$font-size-26: 26rpx;
|
|
6
|
+
$font-size-28: 28rpx;
|
|
7
|
+
$font-size-30: 30rpx;
|
|
8
|
+
$font-size-32: 32rpx;
|
|
9
|
+
$font-size-34: 34rpx;
|
|
10
|
+
$font-size-36: 36rpx;
|
|
11
|
+
$font-size-38: 38rpx;
|
|
12
|
+
$font-size-40: 40rpx;
|
|
13
|
+
// 主题颜色
|
|
14
|
+
$main-color: #ff8d1a;
|
|
15
|
+
|
|
16
|
+
image {
|
|
17
|
+
width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@mixin btn-line {
|
|
22
|
+
font-size: $font-size-32;
|
|
23
|
+
color: $main-color;
|
|
24
|
+
padding: 16rpx 26rpx;
|
|
25
|
+
border: 2rpx solid $main-color;
|
|
26
|
+
text-align: center;
|
|
27
|
+
border-radius: 180rpx;
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@mixin btn-solid {
|
|
32
|
+
font-size: $font-size-32;
|
|
33
|
+
color: #fff;
|
|
34
|
+
background-color: $main-color;
|
|
35
|
+
padding: 16rpx 26rpx;
|
|
36
|
+
border: 2rpx solid $main-color;
|
|
37
|
+
text-align: center;
|
|
38
|
+
border-radius: 8rpx;
|
|
39
|
+
box-sizing: border-box;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 间隔线
|
|
43
|
+
.line_box {
|
|
44
|
+
width: 100%;
|
|
45
|
+
height: 16rpx;
|
|
46
|
+
background-color: #f2f2f2;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// 弹框公用
|
|
52
|
+
.dialog_content_lx {
|
|
53
|
+
.dialog_icon_lx {
|
|
54
|
+
margin: 0 auto;
|
|
55
|
+
width: 116rpx;
|
|
56
|
+
height: 116rpx;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.dialog_txt_lx {
|
|
60
|
+
text-align: center;
|
|
61
|
+
margin-top: 20rpx;
|
|
62
|
+
font-size: $font-size-34;
|
|
63
|
+
color: rgba(0, 0, 0, 1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.dialog_sub_btns_lx {
|
|
68
|
+
padding: 0 36rpx;
|
|
69
|
+
|
|
70
|
+
.dialog_submit_btn_lx {
|
|
71
|
+
@include btn-line;
|
|
72
|
+
background-color: $main-color;
|
|
73
|
+
color: #fff;
|
|
74
|
+
margin-bottom: 20rpx;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.dialog_cancel_btn_lx {
|
|
78
|
+
@include btn-line;
|
|
79
|
+
color: rgba(128, 128, 128, 1);
|
|
80
|
+
border-color: rgba(128, 128, 128, 1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 弹框公用
|
|
85
|
+
|
|
86
|
+
/*============================= 弹性盒子 =============================*/
|
|
87
|
+
@mixin displayFlex($align: center, $justify: center) {
|
|
88
|
+
display: flex;
|
|
89
|
+
flex-wrap: nowrap;
|
|
90
|
+
flex-direction: row;
|
|
91
|
+
align-items: $align;
|
|
92
|
+
justify-content: $justify;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@mixin alignItems($align: center) {
|
|
96
|
+
@include displayFlex($align, center);
|
|
97
|
+
|
|
98
|
+
&-start {
|
|
99
|
+
@include displayFlex($align, flex-start);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&-center {
|
|
103
|
+
@include displayFlex($align, center);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&-end {
|
|
107
|
+
@include displayFlex($align, flex-end);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
&-between {
|
|
111
|
+
@include displayFlex($align, space-between);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
&-around {
|
|
115
|
+
@include displayFlex($align, space-around);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&-evenly {
|
|
119
|
+
@include displayFlex($align, space-evenly);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.flex {
|
|
124
|
+
@include displayFlex;
|
|
125
|
+
|
|
126
|
+
&-center {
|
|
127
|
+
@include alignItems(center);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
&-start {
|
|
131
|
+
@include alignItems(flex-start);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
&-end {
|
|
135
|
+
@include alignItems(flex-end);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* #ifdef MP-TOUTIAO */
|
|
140
|
+
.row {
|
|
141
|
+
flex-direction: row;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.row-reverse {
|
|
145
|
+
flex-direction: row-reverse;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.column {
|
|
149
|
+
flex-direction: column;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.column-reverse {
|
|
153
|
+
flex-direction: column-reverse;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.wrap {
|
|
157
|
+
flex-wrap: wrap;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.nowrap {
|
|
161
|
+
flex-wrap: nowrap;
|
|
162
|
+
}
|
|
163
|
+
/* #endif */
|
|
164
|
+
|
|
165
|
+
[class*="flex-"],
|
|
166
|
+
[class^="flex"] {
|
|
167
|
+
&.row {
|
|
168
|
+
flex-direction: row;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
&.row-reverse {
|
|
172
|
+
flex-direction: row-reverse;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
&.column {
|
|
176
|
+
flex-direction: column;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
&.column-reverse {
|
|
180
|
+
flex-direction: column-reverse;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
&.wrap {
|
|
184
|
+
flex-wrap: wrap;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
&.nowrap {
|
|
188
|
+
flex-wrap: nowrap;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 生成flex1等占位
|
|
193
|
+
@for $i from 1 through 5 {
|
|
194
|
+
.flex#{$i} {
|
|
195
|
+
flex: #{$i};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/*============================= 文字溢出 =============================*/
|
|
200
|
+
|
|
201
|
+
%text-ellipsis-lint {
|
|
202
|
+
text-overflow: ellipsis;
|
|
203
|
+
white-space: normal;
|
|
204
|
+
display: -webkit-box;
|
|
205
|
+
-webkit-box-orient: vertical;
|
|
206
|
+
overflow: hidden;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.text-ellipsis {
|
|
210
|
+
--line: 1;
|
|
211
|
+
@extend %text-ellipsis-lint;
|
|
212
|
+
-webkit-line-clamp: var(--line);
|
|
213
|
+
|
|
214
|
+
&-1 {
|
|
215
|
+
@extend %text-ellipsis-lint;
|
|
216
|
+
-webkit-line-clamp: 1;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
&-2 {
|
|
220
|
+
@extend %text-ellipsis-lint;
|
|
221
|
+
-webkit-line-clamp: 2;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
&-3 {
|
|
225
|
+
@extend %text-ellipsis-lint;
|
|
226
|
+
-webkit-line-clamp: 3;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import lxHeader from '../components/lx-header/lx-header.vue'
|
|
2
|
+
import lxHello from '../components/lx-hello/lx-hello.vue'
|
|
3
|
+
import lxImage from '../components/lx-image/lx-image.vue'
|
|
4
|
+
import lxList from '../components/lx-list/lx-list.vue'
|
|
5
|
+
import lxListState from '../components/lx-list-state/lx-list-state.vue'
|
|
6
|
+
import lxOperateBottom from '../components/lx-operate-bottom/lx-operate-bottom.vue'
|
|
7
|
+
import lxSubmitBtn from '../components/lx-submit-btn/lx-submit-btn.vue'
|
|
8
|
+
import lxUpload from '../components/lx-upload/lx-upload.vue'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
declare module 'vue' {
|
|
12
|
+
export interface GlobalComponents {
|
|
13
|
+
"lx-header": typeof lxHeader,
|
|
14
|
+
"lx-hello": typeof lxHello,
|
|
15
|
+
"lx-image": typeof lxImage,
|
|
16
|
+
"lx-list": typeof lxList,
|
|
17
|
+
"lx-list-state": typeof lxListState,
|
|
18
|
+
"lx-operate-bottom": typeof lxOperateBottom,
|
|
19
|
+
"lx-submit-btn": typeof lxSubmitBtn,
|
|
20
|
+
"lx-upload": typeof lxUpload,
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
package/util/index.ts
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 公共跳转方法
|
|
3
|
+
* @author liux
|
|
4
|
+
* @date 2023-08-15 14:17
|
|
5
|
+
* @param { string } url 跳转路径
|
|
6
|
+
* @param { "navigateTo" | "redirectTo" | "reLaunch" | "switchTab" } [mode=navigateTo] 跳转模式
|
|
7
|
+
* @param { object } params 跳转传参
|
|
8
|
+
* @example
|
|
9
|
+
* goToPage({ url: 'pages/index/index', mode: 'navigateTo', params: {'id': 1} })
|
|
10
|
+
* @returns { void }
|
|
11
|
+
*/
|
|
12
|
+
type pageMode = 'navigateTo' | 'redirectTo' | 'reLaunch' | 'switchTab'
|
|
13
|
+
|
|
14
|
+
interface goToPageInt {
|
|
15
|
+
url: string
|
|
16
|
+
mode?: pageMode
|
|
17
|
+
params?: {
|
|
18
|
+
[n: string]: string | number | boolean
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const goToPage = ({ url, mode = 'navigateTo', params = {} }: goToPageInt): void => {
|
|
23
|
+
if (!url || url.length === 0) {
|
|
24
|
+
throw Error('"url" is a required parameter')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const urlEncode = (params: any = {}) => {
|
|
28
|
+
const result :string[] = []
|
|
29
|
+
for (const k in params) {
|
|
30
|
+
if (!params[k]) continue
|
|
31
|
+
result.push(k + '=' + params[k])
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return result.join('&')
|
|
35
|
+
}
|
|
36
|
+
// const storage = JSON.parse(uni.getStorageSync('LX_user'))
|
|
37
|
+
// const token = storage?.userInfo?.token
|
|
38
|
+
// if(!token) {
|
|
39
|
+
// url = 'pages/login/loginXcx'
|
|
40
|
+
// mode = 'navigateTo'
|
|
41
|
+
// }
|
|
42
|
+
const queryStr = !isEmpty(params) ? '?' + urlEncode(params) : ''
|
|
43
|
+
const obj = { url: `/${url}${queryStr}` }
|
|
44
|
+
console.log('obj', obj)
|
|
45
|
+
switch (mode) {
|
|
46
|
+
case 'navigateTo':
|
|
47
|
+
uni.navigateTo(obj)
|
|
48
|
+
break
|
|
49
|
+
case 'redirectTo':
|
|
50
|
+
uni.redirectTo(obj)
|
|
51
|
+
break
|
|
52
|
+
case 'reLaunch':
|
|
53
|
+
uni.reLaunch(obj)
|
|
54
|
+
break
|
|
55
|
+
case 'switchTab':
|
|
56
|
+
uni.switchTab(obj)
|
|
57
|
+
break
|
|
58
|
+
default:
|
|
59
|
+
throw Error(`${mode} does not exist`)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 判断是否为空对象
|
|
65
|
+
* @author liux
|
|
66
|
+
* @date 2023-08-15 14:17
|
|
67
|
+
* @license MIT
|
|
68
|
+
* @param {*} object 源对象
|
|
69
|
+
* @returns { boolean }
|
|
70
|
+
*/
|
|
71
|
+
export const isEmptyObject = (object: any): boolean => {
|
|
72
|
+
return Object.keys(object).length === 0
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 判断是否为对象
|
|
77
|
+
* @author liux
|
|
78
|
+
* @date 2023-08-15 14:17
|
|
79
|
+
* @license MIT
|
|
80
|
+
* @param {*} object 源对象
|
|
81
|
+
* @returns { boolean }
|
|
82
|
+
*/
|
|
83
|
+
export const isObject = (object: any): boolean => {
|
|
84
|
+
return Object.prototype.toString.call(object) === '[object Object]'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 判断是否为数组
|
|
89
|
+
* @author liux
|
|
90
|
+
* @license MIT
|
|
91
|
+
* @param {*} object 源对象
|
|
92
|
+
* @returns { boolean }
|
|
93
|
+
*/
|
|
94
|
+
export const isArray = (object: any): boolean => {
|
|
95
|
+
return Object.prototype.toString.call(object) === '[object Array]'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 判断是否为空
|
|
100
|
+
* @author liux
|
|
101
|
+
* @license MIT
|
|
102
|
+
* @param {*} value 源对象
|
|
103
|
+
* @returns { boolean }
|
|
104
|
+
*/
|
|
105
|
+
export const isEmpty = (value: any): boolean => {
|
|
106
|
+
if (isArray(value)) {
|
|
107
|
+
return value.length === 0
|
|
108
|
+
}
|
|
109
|
+
if (isObject(value)) {
|
|
110
|
+
return isEmptyObject(value)
|
|
111
|
+
}
|
|
112
|
+
return !value
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 格式化时间戳(多格式)
|
|
117
|
+
* @author liux
|
|
118
|
+
* @license MIT
|
|
119
|
+
* @param { number } time 长度为 10 | 13 的时间戳
|
|
120
|
+
* @param { string } [format=yyyy-MM-dd] format 转换格式
|
|
121
|
+
* @example
|
|
122
|
+
* formatTime(1691744378556, 'yyyy-MM-dd HH:mm:ss')
|
|
123
|
+
* @returns { string }
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
export const formatTime = (time: number, format: string = 'yyyy-MM-dd HH:mm:ss'): string => {
|
|
127
|
+
const len = time.toString().trim().length
|
|
128
|
+
if (len !== 10 && len !== 13) {
|
|
129
|
+
throw Error('"time" is a error parameter')
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
time = len !== 13 ? time * 1000 : time
|
|
133
|
+
|
|
134
|
+
if (!time) return ''
|
|
135
|
+
const date = new Date(time)
|
|
136
|
+
const M = (date.getMonth() + 1).toString()
|
|
137
|
+
const d = date.getDate().toString()
|
|
138
|
+
const H = date.getHours().toString()
|
|
139
|
+
const m = date.getMinutes().toString()
|
|
140
|
+
const s = date.getSeconds().toString()
|
|
141
|
+
const timeObject: {
|
|
142
|
+
[n: string]: string
|
|
143
|
+
} = {
|
|
144
|
+
yyyy: date.getFullYear().toString(),
|
|
145
|
+
MM: M.padStart(2, '0'),
|
|
146
|
+
dd: d.padStart(2, '0'),
|
|
147
|
+
HH: H.padStart(2, '0'),
|
|
148
|
+
mm: m.padStart(2, '0'),
|
|
149
|
+
ss: s.padStart(2, '0'),
|
|
150
|
+
M: M,
|
|
151
|
+
d: d,
|
|
152
|
+
H: H,
|
|
153
|
+
m: m,
|
|
154
|
+
s: s
|
|
155
|
+
}
|
|
156
|
+
const reg = new RegExp(Object.keys(timeObject).join('|'), 'g')
|
|
157
|
+
const res = format.replace(reg, (k) => {
|
|
158
|
+
return timeObject[k]
|
|
159
|
+
})
|
|
160
|
+
return res
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 判断当前时间是否在一个时间区间内
|
|
164
|
+
export const isTimeIn = (start: string, end: string) => {
|
|
165
|
+
// 获取当前时间
|
|
166
|
+
const currentTime = new Date()
|
|
167
|
+
const startArr = start.split(':').map(Number)
|
|
168
|
+
// 设置开始时间为10:00
|
|
169
|
+
const startTime = new Date()
|
|
170
|
+
startTime.setHours(startArr[0], startArr[1])
|
|
171
|
+
|
|
172
|
+
// 设置结束时间为20:00
|
|
173
|
+
const endArr = end.split(':').map(Number)
|
|
174
|
+
const endTime = new Date()
|
|
175
|
+
endTime.setHours(endArr[0], endArr[1])
|
|
176
|
+
|
|
177
|
+
// 检查当前时间是否在10:00到20:00之间
|
|
178
|
+
if (currentTime >= startTime && currentTime <= endTime) {
|
|
179
|
+
// console.log('当前时间在之间')
|
|
180
|
+
} else {
|
|
181
|
+
// console.log('当前时间不在之间')
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* 防抖函数
|
|
187
|
+
* @author liux
|
|
188
|
+
* @license MIT
|
|
189
|
+
* @param {function} fn
|
|
190
|
+
* @param {umber} [wait=1000] wait
|
|
191
|
+
* @returns { void }
|
|
192
|
+
*/
|
|
193
|
+
export const debounce = <T extends (...args: any[]) => any>(fn: T, wait: number = 1000): ((...args: Parameters<T>) => void) => {
|
|
194
|
+
let timer: number | null
|
|
195
|
+
|
|
196
|
+
return function (this: any, ...args: Parameters<T>) {
|
|
197
|
+
if (timer) clearTimeout(timer)
|
|
198
|
+
|
|
199
|
+
timer = setTimeout(() => {
|
|
200
|
+
fn.apply(this, args)
|
|
201
|
+
}, wait)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 节流函数
|
|
207
|
+
* @author liux
|
|
208
|
+
* @date 2023-08-15 14:17
|
|
209
|
+
* @license MIT
|
|
210
|
+
* @param { function } fn
|
|
211
|
+
* @param { number } [wait=1000] wait
|
|
212
|
+
*/
|
|
213
|
+
export const throttle = <T extends (...args: any[]) => any>(fn: T, wait: number = 1000) => {
|
|
214
|
+
let timer: number = Date.now()
|
|
215
|
+
return function (this: any, ...args: Parameters<T>) {
|
|
216
|
+
if (Date.now() - timer >= wait) {
|
|
217
|
+
fn.apply(this, args)
|
|
218
|
+
timer = Date.now()
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* 保存图片到本地
|
|
225
|
+
* @author liux
|
|
226
|
+
* @param { string } url 需要下载的图片
|
|
227
|
+
* @example
|
|
228
|
+
* saveImgData('/upload/images/img.png')
|
|
229
|
+
* @returns
|
|
230
|
+
*/
|
|
231
|
+
export const saveImgData = debounce((url: string) => {
|
|
232
|
+
uni.showLoading({ title: '图片保存中...', mask: true })
|
|
233
|
+
// 判断图片地址是否有http
|
|
234
|
+
if (url.indexOf('http') === -1) {
|
|
235
|
+
url = import.meta.env.VITE_APP_BASE_URL + url
|
|
236
|
+
}
|
|
237
|
+
uni.downloadFile({
|
|
238
|
+
url,
|
|
239
|
+
success: (res: any) => {
|
|
240
|
+
if (res.statusCode === 200) {
|
|
241
|
+
uni.saveImageToPhotosAlbum({
|
|
242
|
+
filePath: res.tempFilePath,
|
|
243
|
+
success: () => {
|
|
244
|
+
uni.showToast({
|
|
245
|
+
title: '保存成功~',
|
|
246
|
+
icon: 'none',
|
|
247
|
+
duration: 2000
|
|
248
|
+
})
|
|
249
|
+
},
|
|
250
|
+
fail: () => {
|
|
251
|
+
uni.showToast({
|
|
252
|
+
title: '保存失败~',
|
|
253
|
+
icon: 'none',
|
|
254
|
+
duration: 2000
|
|
255
|
+
})
|
|
256
|
+
},
|
|
257
|
+
complete: () => {
|
|
258
|
+
uni.hideLoading()
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
})
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* 设置剪贴板
|
|
268
|
+
* @author liux
|
|
269
|
+
* @param { string } data 需要复制的内容
|
|
270
|
+
* @example
|
|
271
|
+
* setClipboardData('123456')
|
|
272
|
+
* @returns
|
|
273
|
+
*/
|
|
274
|
+
export const setClipboardData = (data: string) => {
|
|
275
|
+
uni.setClipboardData({
|
|
276
|
+
data: data,
|
|
277
|
+
success: () => {
|
|
278
|
+
uni.showToast({
|
|
279
|
+
title: '复制成功',
|
|
280
|
+
icon: 'none',
|
|
281
|
+
duration: 2000
|
|
282
|
+
})
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export default {
|
|
288
|
+
goToPage,
|
|
289
|
+
formatTime,
|
|
290
|
+
debounce,
|
|
291
|
+
throttle,
|
|
292
|
+
saveImgData,
|
|
293
|
+
setClipboardData
|
|
294
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @description: 分页请求
|
|
3
|
+
* @fileName: useListLoadClass.ts
|
|
4
|
+
* @author: lxx
|
|
5
|
+
* @date: 2023-07-08 08:55:52
|
|
6
|
+
* @version: V1.0.0
|
|
7
|
+
*/
|
|
8
|
+
import { reactive, ref, computed } from "vue"
|
|
9
|
+
class LoadDataClass {
|
|
10
|
+
// 请求参数
|
|
11
|
+
static queryParams = reactive({
|
|
12
|
+
page: 1,
|
|
13
|
+
limit: 10
|
|
14
|
+
})
|
|
15
|
+
// 列表数据
|
|
16
|
+
list = ref<any[]>([])
|
|
17
|
+
total = ref(0)
|
|
18
|
+
// 前置处理方法
|
|
19
|
+
afterLoadData: Function | undefined
|
|
20
|
+
// 请求方法
|
|
21
|
+
Query: Function
|
|
22
|
+
// 加载状态参数
|
|
23
|
+
isLoading = ref(false)
|
|
24
|
+
// 无更多数据了
|
|
25
|
+
isNoData = computed(() => {
|
|
26
|
+
if (LoadDataClass.queryParams.page * LoadDataClass.queryParams.limit >= this.total.value) {
|
|
27
|
+
return true
|
|
28
|
+
} else {
|
|
29
|
+
return false
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
// 显示暂无数据
|
|
33
|
+
isEmpty = computed(() => {
|
|
34
|
+
if (this.total.value === 0) {
|
|
35
|
+
return true
|
|
36
|
+
} else {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
constructor(apiFunctions: Function, afterLoadData?: Function, options: any = {}) {
|
|
42
|
+
this.queryParamsReset()
|
|
43
|
+
this.Query = apiFunctions
|
|
44
|
+
this.afterLoadData = afterLoadData
|
|
45
|
+
// console.log('options', options)
|
|
46
|
+
// 存在额外参数拼接
|
|
47
|
+
this.setParams(options)
|
|
48
|
+
}
|
|
49
|
+
// 加载数据
|
|
50
|
+
LoadData = async () => {
|
|
51
|
+
uni.showLoading({
|
|
52
|
+
title: '加载中...'
|
|
53
|
+
})
|
|
54
|
+
this.isLoading.value = true
|
|
55
|
+
const res = await this.Query(LoadDataClass.queryParams)
|
|
56
|
+
this.afterLoadData && this.afterLoadData(res)
|
|
57
|
+
this.total.value = res.data.total
|
|
58
|
+
this.list.value = this.list.value.concat(res.data.items)
|
|
59
|
+
|
|
60
|
+
uni.hideLoading()
|
|
61
|
+
uni.stopPullDownRefresh()
|
|
62
|
+
this.isLoading.value = false
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 添加额外参数刷新
|
|
66
|
+
* @param options: 参数
|
|
67
|
+
* @param isClear: 是否清空数据 false
|
|
68
|
+
*/
|
|
69
|
+
setParams = (options: any, isClear: boolean = false) => {
|
|
70
|
+
if (isClear) {
|
|
71
|
+
this.queryParamsReset()
|
|
72
|
+
} else {
|
|
73
|
+
LoadDataClass.queryParams.page = 1
|
|
74
|
+
}
|
|
75
|
+
this.list.value = []
|
|
76
|
+
LoadDataClass.queryParams = Object.assign(LoadDataClass.queryParams, options)
|
|
77
|
+
// 加载数据
|
|
78
|
+
this.LoadData()
|
|
79
|
+
}
|
|
80
|
+
// 加载更多
|
|
81
|
+
LoadMore = () => {
|
|
82
|
+
if (this.isNoData.value || this.isLoading.value) return // 无数据或者加载中不进行加载
|
|
83
|
+
LoadDataClass.queryParams.page += 1
|
|
84
|
+
this.LoadData()
|
|
85
|
+
}
|
|
86
|
+
// 重置参数
|
|
87
|
+
queryParamsReset = () => {
|
|
88
|
+
LoadDataClass.queryParams = reactive({
|
|
89
|
+
page: 1,
|
|
90
|
+
limit: 10
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 刷新
|
|
96
|
+
* @param isClear: 是否清空数据
|
|
97
|
+
*/
|
|
98
|
+
ReLoad = (isClear: boolean = false) => {
|
|
99
|
+
this.isLoading.value = false
|
|
100
|
+
this.list.value = []
|
|
101
|
+
if (isClear) {
|
|
102
|
+
this.queryParamsReset()
|
|
103
|
+
} else {
|
|
104
|
+
LoadDataClass.queryParams.page = 1
|
|
105
|
+
}
|
|
106
|
+
this.LoadData()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 分页加载数据方法
|
|
111
|
+
* @param api: ListAPI 方法
|
|
112
|
+
* @param afterLoadData: res数据前置处理方法
|
|
113
|
+
* @returns
|
|
114
|
+
*/
|
|
115
|
+
interface LoadDataInt {
|
|
116
|
+
api: Function
|
|
117
|
+
afterLoadData?: Function
|
|
118
|
+
options?: any
|
|
119
|
+
isNeedReachBottom?: boolean
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function LoadData({ api, afterLoadData, options, isNeedReachBottom = true }: LoadDataInt) {
|
|
123
|
+
const data = new LoadDataClass(api, afterLoadData, options)
|
|
124
|
+
|
|
125
|
+
// 下拉加载
|
|
126
|
+
if (isNeedReachBottom) {
|
|
127
|
+
onReachBottom(() => {
|
|
128
|
+
console.log('onReachBottom')
|
|
129
|
+
data.LoadMore()
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
list: data.list,
|
|
135
|
+
isLoading: data.isLoading,
|
|
136
|
+
isNoData: data.isNoData,
|
|
137
|
+
isEmpty: data.isEmpty,
|
|
138
|
+
ReLoad: data.ReLoad,
|
|
139
|
+
setParams: data.setParams,
|
|
140
|
+
LoadMore: data.LoadMore
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|