@shijiu/jsview-vue-samples 2.2.35 → 2.2.128

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.
@@ -0,0 +1,388 @@
1
+ <!--
2
+ * @Author: ChenChanghua
3
+ * @Date: 2021-06-10 14:17:17
4
+ * @LastEditors: ChenChanghua
5
+ * @LastEditTime: 2022-07-11 18:20:58
6
+ * @Description: file content
7
+ -->
8
+ <script setup>
9
+ import posterHolder from "../PerformanceTest/assets/holder_logo.png";
10
+ import couponLeft from "../PerformanceTest/assets/coupon_left.png";
11
+ import couponRight from "../PerformanceTest/assets/coupon_right.png";
12
+ import couponMid from "../PerformanceTest/assets/coupon_mid.png";
13
+ import borderLeft from "../PerformanceTest/assets/line_left.png";
14
+ import borderMid from "../PerformanceTest/assets/line_mid.png";
15
+ import borderRight from "../PerformanceTest/assets/line_right.png";
16
+ import { ref, computed } from "vue";
17
+
18
+ const picUrl = "http://img.alicdn.com/bao/uploaded/i3/2207313464483/O1CN01Ab4vWz1izGAyRL1Yf_!!0-item_pic.jpg";
19
+
20
+ const props = defineProps({
21
+ data: Object,
22
+ // query: Object,
23
+ // onEdge: Function,
24
+ // onAction: Object,
25
+ });
26
+
27
+ const focused = ref(false);
28
+ const onFocus = () => {
29
+ focused.value = true;
30
+ };
31
+
32
+ const onBlur = () => {
33
+ focused.value = false;
34
+ };
35
+
36
+ // props.onAction.register("onFocus", onFocus);
37
+ // props.onAction.register("onBlur", onBlur);
38
+
39
+ const focusTransform = computed(() => {
40
+ return focused.value ? "scale3d(1.2, 1.2, 1)" : null;
41
+ });
42
+
43
+ const savePrizeWidth = computed(() => {
44
+ return 10 * props.data.savePrize.length + 26;
45
+ });
46
+
47
+ const soldTotalWidth = computed(() => {
48
+ let width = 44 + 22; //base width;
49
+ if (props.data.soldTotal >= 10000) {
50
+ let text = parseInt(props.data.soldTotal / 10000) + "";
51
+ width += text.length * 12 + 22;
52
+ } else {
53
+ width += (props.data.soldTotal + "").length * 12;
54
+ }
55
+ return width;
56
+ });
57
+
58
+ const soldTotalText = computed(() => {
59
+ let text = "";
60
+ if (props.data.soldTotal >= 10000) {
61
+ text = parseInt(props.data.soldTotal / 10000) + "万";
62
+ } else {
63
+ text = props.data.soldTotal;
64
+ }
65
+ return text;
66
+ });
67
+ </script>
68
+
69
+ <template>
70
+ <div
71
+ class="frame-background"
72
+ :style="{
73
+ transform: focusTransform,
74
+ }"
75
+ >
76
+ <div class="poster-holder">
77
+ <div
78
+ :style="{
79
+ width: 107,
80
+ height: 23,
81
+ left: 53,
82
+ top: 95,
83
+ backgroundImage: posterHolder,
84
+ }"
85
+ />
86
+ </div>
87
+ <div
88
+ class="poster"
89
+ :style="{
90
+ backgroundImage: `url(${picUrl})`,
91
+ }"
92
+ />
93
+ <div class="title-font title-layout">
94
+ {{ data.index + data.name }}
95
+ </div>
96
+ <div
97
+ :style="{
98
+ height: 24,
99
+ left: 13,
100
+ top: 256,
101
+ width: savePrizeWidth,
102
+ }"
103
+ >
104
+ <div
105
+ :style="{ width: 5, height: 24, backgroundImage: couponLeft }"
106
+ />
107
+ <div
108
+ :style="{
109
+ left: 5,
110
+ width: savePrizeWidth - 11,
111
+ height: 24,
112
+ backgroundImage: couponMid,
113
+ }"
114
+ />
115
+ <div
116
+ :style="{
117
+ left: savePrizeWidth - 6,
118
+ width: 5,
119
+ height: 24,
120
+ backgroundImage: couponRight,
121
+ }"
122
+ />
123
+ <div
124
+ class="ticket-text"
125
+ :style="{
126
+ width: savePrizeWidth,
127
+ }"
128
+ >
129
+ {{ `${data.savePrize}元券` }}
130
+ </div>
131
+ </div>
132
+
133
+ <div
134
+ :style="{
135
+ top: 256,
136
+ left: 27 + savePrizeWidth,
137
+ }"
138
+ >
139
+ <div
140
+ :style="{ width: 7, height: 25, backgroundImage: borderLeft }"
141
+ />
142
+ <div
143
+ :style="{
144
+ left: 7,
145
+ width: soldTotalWidth - 13,
146
+ height: 25,
147
+ backgroundImage: borderMid,
148
+ }"
149
+ />
150
+ <div
151
+ :style="{
152
+ left: soldTotalWidth - 7,
153
+ width: 7,
154
+ height: 25,
155
+ backgroundImage: borderRight,
156
+ }"
157
+ />
158
+ <div
159
+ class="sold-text"
160
+ :style="{
161
+ width: soldTotalWidth,
162
+ }"
163
+ >
164
+ {{ `已售${soldTotalText}件` }}
165
+ </div>
166
+ </div>
167
+
168
+ <div
169
+ :style="{
170
+ height: 24,
171
+ left: 13,
172
+ top: 270,
173
+ width: savePrizeWidth,
174
+ }"
175
+ >
176
+ <div
177
+ :style="{ width: 5, height: 24, backgroundImage: couponLeft }"
178
+ />
179
+ <div
180
+ :style="{
181
+ left: 5,
182
+ width: savePrizeWidth - 11,
183
+ height: 24,
184
+ backgroundImage: couponMid,
185
+ }"
186
+ />
187
+ <div
188
+ :style="{
189
+ left: savePrizeWidth - 6,
190
+ width: 5,
191
+ height: 24,
192
+ backgroundImage: couponRight,
193
+ }"
194
+ />
195
+ <div
196
+ class="ticket-text"
197
+ :style="{
198
+ width: savePrizeWidth,
199
+ }"
200
+ >
201
+ {{ `${data.savePrize}元券` }}
202
+ </div>
203
+ </div>
204
+ <div
205
+ :style="{
206
+ top: 270,
207
+ left: 27 + savePrizeWidth,
208
+ }"
209
+ >
210
+ <div
211
+ :style="{ width: 7, height: 25, backgroundImage: borderLeft }"
212
+ />
213
+ <div
214
+ :style="{
215
+ left: 7,
216
+ width: soldTotalWidth - 13,
217
+ height: 25,
218
+ backgroundImage: borderMid,
219
+ }"
220
+ />
221
+ <div
222
+ :style="{
223
+ left: soldTotalWidth - 7,
224
+ width: 7,
225
+ height: 25,
226
+ backgroundImage: borderRight,
227
+ }"
228
+ />
229
+ <div
230
+ class="sold-text"
231
+ :style="{
232
+ width: soldTotalWidth,
233
+ }"
234
+ >
235
+ {{ `已售${soldTotalText}件` }}
236
+ </div>
237
+ </div>
238
+
239
+ <div
240
+ :style="{
241
+ height: 24,
242
+ left: 13,
243
+ top: 280,
244
+ width: savePrizeWidth,
245
+ }"
246
+ >
247
+ <div
248
+ :style="{ width: 5, height: 24, backgroundImage: couponLeft }"
249
+ />
250
+ <div
251
+ :style="{
252
+ left: 5,
253
+ width: savePrizeWidth - 11,
254
+ height: 24,
255
+ backgroundImage: couponMid,
256
+ }"
257
+ />
258
+ <div
259
+ :style="{
260
+ left: savePrizeWidth - 6,
261
+ width: 5,
262
+ height: 24,
263
+ backgroundImage: couponRight,
264
+ }"
265
+ />
266
+ <div
267
+ class="ticket-text"
268
+ :style="{
269
+ width: savePrizeWidth,
270
+ }"
271
+ >
272
+ {{ `${data.savePrize}元券` }}
273
+ </div>
274
+ </div>
275
+ <div
276
+ :style="{
277
+ top: 280,
278
+ left: 27 + savePrizeWidth,
279
+ }"
280
+ >
281
+ <div
282
+ :style="{ width: 7, height: 25, backgroundImage: borderLeft }"
283
+ />
284
+ <div
285
+ :style="{
286
+ left: 7,
287
+ width: soldTotalWidth - 13,
288
+ height: 25,
289
+ backgroundImage: borderMid,
290
+ }"
291
+ />
292
+ <div
293
+ :style="{
294
+ left: soldTotalWidth - 7,
295
+ width: 7,
296
+ height: 25,
297
+ backgroundImage: borderRight,
298
+ }"
299
+ />
300
+ <div
301
+ class="sold-text"
302
+ :style="{
303
+ width: soldTotalWidth,
304
+ }"
305
+ >
306
+ {{ `已售${soldTotalText}件` }}
307
+ </div>
308
+ </div>
309
+
310
+ <div class="prize-title-font prize-title-layout">券后</div>
311
+ <div class="prize-font">
312
+ {{ `¥${data.prize - data.savePrize}` }}
313
+ </div>
314
+ </div>
315
+ </template>
316
+
317
+ <style scoped>
318
+ .frame-background {
319
+ width: 213;
320
+ height: 337;
321
+ border-radius: 10;
322
+ background-color: #f7f7f4;
323
+ transition: transform 0.2s linear;
324
+ }
325
+
326
+ .poster-holder {
327
+ width: 213;
328
+ height: 213;
329
+ border-radius: 10 10 0 0;
330
+ background-color: #cfcac6;
331
+ }
332
+ .poster {
333
+ width: 213;
334
+ height: 213;
335
+ border-radius: 7 7 0 0;
336
+ }
337
+
338
+ .title-font {
339
+ font-size: 21;
340
+ color: #73665c;
341
+ line-height: 29;
342
+ overflow: hidden;
343
+ white-space: nowrap;
344
+ text-overflow: ellipsis;
345
+ text-align: center;
346
+ }
347
+ .title-layout {
348
+ top: 221;
349
+ left: 13;
350
+ width: 193;
351
+ height: 29;
352
+ }
353
+ .ticket-text {
354
+ height: 24;
355
+ color: #ffffff;
356
+ font-size: 16;
357
+ text-align: center;
358
+ line-height: 24;
359
+ }
360
+ .sold-text {
361
+ height: 25;
362
+ color: #ff7a00;
363
+ font-size: 20;
364
+ text-align: center;
365
+ line-height: 25;
366
+ }
367
+ .prize-title-layout {
368
+ width: 35;
369
+ height: 24;
370
+ top: 296;
371
+ left: 13;
372
+ }
373
+ .prize-title-font {
374
+ color: #de2825;
375
+ text-align: center;
376
+ font-size: 17;
377
+ line-height: 24;
378
+ }
379
+ .prize-font {
380
+ top: 289;
381
+ left: 53;
382
+ width: 158; /*213 - 55*/
383
+ height: 37;
384
+ line-height: 37;
385
+ font-size: 28;
386
+ color: #de2825;
387
+ }
388
+ </style>
@@ -0,0 +1,203 @@
1
+ <!--
2
+ * @Author: ChenChanghua
3
+ * @Date: 2023-03-09 15:33:54
4
+ * @Description: file content
5
+ -->
6
+ <script setup>
7
+ import { ref, onMounted } from "vue";
8
+ import borderLeft from "../PerformanceTest/assets/line_left.png";
9
+ import borderMid from "../PerformanceTest/assets/line_mid.png";
10
+ import borderRight from "../PerformanceTest/assets/line_right.png";
11
+
12
+ const props = defineProps({
13
+ data: Object,
14
+ onAction: Object,
15
+ pre: String,
16
+ });
17
+
18
+ console.log("Massive-MetroItem item created ", props.pre, props.data.content);
19
+
20
+ const focused = ref(false);
21
+
22
+ // 自身的焦点状态自己记录, 通过回调来改变
23
+ const onFocus = () => {
24
+ focused.value = true;
25
+ };
26
+ const onBlur = () => {
27
+ focused.value = false;
28
+ };
29
+ const onClick = () => {
30
+ console.log("item onclick ", props.data);
31
+ };
32
+
33
+ // 一般在create的时候进行回调的注册, 使用 option api的可以在created时进行注册
34
+ props.onAction.register("onFocus", onFocus);
35
+ props.onAction.register("onBlur", onBlur);
36
+ props.onAction.register("onClick", onClick);
37
+
38
+
39
+ onMounted(()=>{
40
+ console.log("Massive-MetroItem item mounted ", props.pre, props.data.content);
41
+ })
42
+
43
+ </script>
44
+
45
+ <template>
46
+ <div
47
+ :style="{
48
+ width: data.width,
49
+ height: data.height,
50
+ transform: focused ? 'scale3d(1.2, 1.2, 1.2)' : '',
51
+ transition: 'transform 0.2s linear',
52
+ }"
53
+ >
54
+ <div
55
+ v-if="focused"
56
+ :style="{
57
+ left: -2,
58
+ top: -2,
59
+ width: data.width + 4,
60
+ height: data.height + 4,
61
+ backgroundColor: '#FF0000',
62
+ }"
63
+ ></div>
64
+ <div
65
+ :style="{
66
+ width: data.width,
67
+ height: data.height,
68
+ fontSize: 30,
69
+ color: '#FFFFFF',
70
+ backgroundColor: data.color,
71
+ }"
72
+ >
73
+ {{ data.content }}
74
+ </div>
75
+
76
+ <div class="box1">
77
+ <div class="border-left" :style="{ backgroundImage: borderLeft }"></div>
78
+ <div
79
+ class="border-mid"
80
+ :style="{
81
+ backgroundImage: borderMid,
82
+ }"
83
+ ></div>
84
+ <div
85
+ class="border-right"
86
+ :style="{
87
+ backgroundImage: borderRight,
88
+ }"
89
+ ></div>
90
+ <div class="prize-title-font prize-title-layout">券后</div>
91
+ </div>
92
+
93
+ <div class="box2">
94
+ <div class="border-left" :style="{ backgroundImage: borderLeft }"></div>
95
+ <div
96
+ class="border-mid"
97
+ :style="{
98
+ backgroundImage: borderMid,
99
+ }"
100
+ ></div>
101
+ <div
102
+ class="border-right"
103
+ :style="{
104
+ backgroundImage: borderRight,
105
+ }"
106
+ ></div>
107
+ <div class="prize-title-font prize-title-layout">券后</div>
108
+ </div>
109
+
110
+ <div class="sold-text">
111
+ {{ `已售12件` }}
112
+ </div>
113
+ <div class="prize-font">
114
+ {{ `¥40` }}
115
+ </div>
116
+ </div>
117
+ </template>
118
+
119
+ <style scoped>
120
+ .box1 {
121
+ left: 5;
122
+ top: 40;
123
+ }
124
+
125
+ .box2 {
126
+ left: 45;
127
+ top: 40;
128
+ }
129
+
130
+ .border-left {
131
+ width: 7;
132
+ height: 25;
133
+ }
134
+ .border-mid {
135
+ left: 7;
136
+ width: 37;
137
+ height: 25;
138
+ }
139
+ .border-right {
140
+ left: 43;
141
+ width: 7;
142
+ height: 25;
143
+ }
144
+ .frame-background {
145
+ width: 213;
146
+ height: 337;
147
+ border-radius: 10;
148
+ background-color: #f7f7f4;
149
+ transition: transform 0.2s linear;
150
+ }
151
+
152
+ .poster-holder {
153
+ width: 213;
154
+ height: 213;
155
+ border-radius: 10 10 0 0;
156
+ background-color: #cfcac6;
157
+ }
158
+ .poster {
159
+ width: 213;
160
+ height: 213;
161
+ border-radius: 7 7 0 0;
162
+ }
163
+
164
+ .title-layout {
165
+ width: 193;
166
+ height: 29;
167
+ }
168
+ .ticket-text {
169
+ height: 24;
170
+ color: #ffffff;
171
+ font-size: 16;
172
+ text-align: center;
173
+ line-height: 24;
174
+ }
175
+ .sold-text {
176
+ top: 60;
177
+ width: 100;
178
+ height: 25;
179
+ color: #ff7a00;
180
+ font-size: 20;
181
+ text-align: center;
182
+ line-height: 25;
183
+ }
184
+ .prize-title-layout {
185
+ width: 35;
186
+ height: 24;
187
+ left: 13;
188
+ }
189
+ .prize-title-font {
190
+ color: #de2825;
191
+ text-align: center;
192
+ font-size: 17;
193
+ line-height: 24;
194
+ }
195
+ .prize-font {
196
+ left: 50;
197
+ width: 158; /*213 - 55*/
198
+ height: 37;
199
+ line-height: 37;
200
+ font-size: 28;
201
+ color: #de2825;
202
+ }
203
+ </style>
@@ -0,0 +1,101 @@
1
+ <script setup>
2
+ import { HORIZONTAL, VERTICAL, MetroWidget, useFocusHub } from "jsview";
3
+ import { shallowRef } from "vue";
4
+ import Item from "./Item.vue";
5
+
6
+ const props = defineProps({
7
+ data: Object,
8
+ onItemEdge: Function,
9
+ onAction: Object,
10
+ });
11
+ const focusHub = useFocusHub();
12
+ const mwRef = shallowRef(null);
13
+
14
+ const measures = (item) => {
15
+ return item;
16
+ };
17
+ const randomColor = () => {
18
+ let randomColor = Math.round(Math.random() * 2 ** 24).toString(16);
19
+ return (
20
+ "#" + new Array(6 - randomColor.length).fill("0").join("") + randomColor
21
+ );
22
+ };
23
+ const provideData = () => {
24
+ const data = [];
25
+ for (let i = 0; i < 42; i++) {
26
+ data.push({
27
+ width: 100,
28
+ height: 90,
29
+ marginRight: 10,
30
+ marginBottom: 10,
31
+ content: i,
32
+ color: randomColor(),
33
+ });
34
+ }
35
+ return data;
36
+ };
37
+ const onFocus = (rect) => {
38
+ /** 重要代码: 参数rect为父MetroWidget传递的, 焦点过来的区域
39
+ * 因此需要调用setEnterFocusRect来设置焦点进入区域, 以寻找最近的焦点
40
+ */
41
+ mwRef.value?.setEnterFocusRect(rect);
42
+ focusHub.setFocus(props.data.name);
43
+ };
44
+ const onBlur = () => {
45
+ //onBlur时需要返还焦点给父MetroWidget
46
+ focusHub.returnFocusToParent();
47
+ };
48
+
49
+ props.onAction.register("onFocus", onFocus);
50
+ props.onAction.register("onBlur", onBlur);
51
+
52
+ const onScroll = () => {
53
+ console.log("testtest on scroll", props.name);
54
+ };
55
+ </script>
56
+
57
+ <template>
58
+ <div
59
+ :style="{
60
+ width: 900,
61
+ height: 50,
62
+ fontSize: 30,
63
+ color: '#FFFFFF',
64
+ }"
65
+ >
66
+ {{ data.name }}
67
+ </div>
68
+ <!-- 重要代码: sendFocusRectEvent可以让MetroWidget的item在获焦时发送事件, 通知父的MetroWidget进行滚动 -->
69
+ <!-- 重要代码: onItemEdge直接作为onEdge回调, 既子MetroWidget到达边缘时触发父的onItemEdge -->
70
+ <metro-widget
71
+ ref="mwRef"
72
+ :onScroll="onScroll"
73
+ :name="data.name"
74
+ :top="30"
75
+ :width="data.width"
76
+ :height="data.height"
77
+ :provideData="provideData"
78
+ :direction="VERTICAL"
79
+ :padding="{
80
+ left: 30,
81
+ right: 30,
82
+ top: 10,
83
+ bottom: 10,
84
+ }"
85
+ :measures="measures"
86
+ :onEdge="onItemEdge"
87
+ :sendFocusRectEvent="false"
88
+ :enableItemRenderBreak="true"
89
+ :placeHolderSetting="{
90
+ backgroundColor: 'rgba(78,105,127, 0.8)',
91
+ focusBackgroundColor: '#770088aa',
92
+ borderRadius: 10,
93
+ gap: 10,
94
+ }"
95
+ :keepTraceRange="2"
96
+ >
97
+ <template #renderItem="{ data, onAction }">
98
+ <item :data="data" :onAction="onAction" :pre="props.data.name" />
99
+ </template>
100
+ </metro-widget>
101
+ </template>
@@ -0,0 +1,17 @@
1
+ let data1 = [];
2
+
3
+ // 添加300个模拟数据
4
+ for (let i = 0; i < 40; i++) {
5
+ data1.push({
6
+ index: i,
7
+ name: `商品:骆驼奶粉蛋白质粉,限时抢购,立刻发货,序号:${i}`,
8
+ prize: `${Math.floor(Math.random() * 200) +
9
+ 200}` /* 测试数据要保证比最高优惠券(300左右)要高 */,
10
+ savePrize: `${i}`,
11
+ soldTotal: `${Math.floor(Math.random() * 50000)}`,
12
+ pictUrl:
13
+ "http://img.alicdn.com/bao/uploaded/i3/2207313464483/O1CN01Ab4vWz1izGAyRL1Yf_!!0-item_pic.jpg",
14
+ });
15
+ }
16
+
17
+ export { data1 };