@neatui/vue 2.0.9 → 2.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neatui/vue",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
4
4
  "description": "basic component ui",
5
5
  "main": "./src/index.ts",
6
6
  "license": "MIT",
@@ -20,14 +20,14 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@fekit/floor": "^2.2.2",
23
- "@fekit/follow": "^1.0.10",
23
+ "@fekit/follow": "^1.3.0",
24
24
  "@fekit/itable": "^1.1.6",
25
25
  "@fekit/pullload": "^1.3.5",
26
26
  "@fekit/scale": "^2.0.1",
27
27
  "@fekit/scrollto": "^3.0.3",
28
28
  "@fekit/toast": "^2.2.3",
29
29
  "@fekit/url": "^2.0.1",
30
- "@fekit/utils": "^2.10.21",
30
+ "@fekit/utils": "^2.15.0",
31
31
  "@rollup/plugin-commonjs": "^26.0.1",
32
32
  "@rollup/plugin-node-resolve": "^15.2.3",
33
33
  "@vue/compiler-sfc": "^3.4.30",
@@ -38,6 +38,6 @@
38
38
  "rollup-plugin-vue": "^6.0.0",
39
39
  "swiper": "^11.0.4",
40
40
  "vue-cropper": "^0.6.4",
41
- "vuedraggable": "^4.1.0"
41
+ "vuedraggable": "^2.24.3"
42
42
  }
43
43
  }
@@ -167,7 +167,6 @@
167
167
  if (state.view === 1) {
168
168
  state.view = 0;
169
169
  on.hide.forEach((fun: any) => {
170
- // isFunction(fun) && fun();
171
170
  if (isFunction(fun)) {
172
171
  fun();
173
172
  }
@@ -176,7 +175,6 @@
176
175
  if (state.view === 2) {
177
176
  state.view = 3;
178
177
  on.show.forEach((fun: any) => {
179
- // isFunction(fun) && fun();
180
178
  if (isFunction(fun)) {
181
179
  fun();
182
180
  }
@@ -200,13 +198,10 @@
200
198
  delete _tasks[id];
201
199
  });
202
200
  </script>
203
- <!-- <script lang="ts">
204
- export const LayerById = (id: any) => {
205
- return (window as any)._FEKIT_LAYER_TASKS[id];
206
- };
207
- </script> -->
208
201
 
209
202
  <style lang="scss">
203
+ @use '@neatui/css' as neatui;
204
+
210
205
  // 弹层
211
206
  .fekit-layer {
212
207
  position: fixed;
@@ -234,106 +229,54 @@
234
229
  }
235
230
 
236
231
  &-close {
232
+ cursor: pointer;
237
233
  position: absolute;
238
- width: 1.5em;
239
- height: 1.5em;
240
- left: 50%;
241
- bottom: -2.5rem;
242
- margin-left: -1rem;
234
+ width: 2em;
235
+ height: 2em;
236
+
237
+ color: var(--co-read);
238
+ bottom: auto;
239
+ top: 0.5em;
240
+ right: 0.5em;
241
+ left: auto;
242
+ box-shadow: none;
243
+
243
244
  padding: 0.25em;
245
+ margin-left: -1rem;
244
246
  text-align: center;
245
- transform: scale(1) translate3d(0, -100%, 0);
247
+ transform: scale(0.8);
246
248
  transition: all 0.2s;
247
- color: #fff;
248
- box-shadow: 0 0 0 2px currentColor;
249
249
  border-radius: 50%;
250
- opacity: 0;
251
250
  background:
252
- linear-gradient(45deg, transparent 44%, currentColor 45%, currentColor 56%, transparent 57%) no-repeat center / 50% 50%,
253
- linear-gradient(-45deg, transparent 44%, currentColor 45%, currentColor 56%, transparent 57%) no-repeat center / 50% 50%;
251
+ linear-gradient(45deg, transparent 44%, currentColor 45%, currentColor 55%, transparent 56%) no-repeat center / 50% 50%,
252
+ linear-gradient(-45deg, transparent 44%, currentColor 45%, currentColor 55%, transparent 56%) no-repeat center / 50% 50%;
254
253
 
255
254
  &:active {
256
255
  transform: scale(0.9);
257
256
  }
258
257
  }
259
258
 
260
- &[view='3'] {
261
- .fekit-layer-close {
262
- opacity: 0.85;
263
- transform: translate3d(0, 0, 0);
259
+ .fekit-layer-close {
260
+ &:hover {
261
+ transform: scale(0.8) rotate(90deg);
262
+ }
263
+ &:active {
264
+ transform: scale(0.7) rotate(90deg);
264
265
  }
265
266
  }
267
+ }
266
268
 
267
- // &-close {
268
- // position: absolute;
269
- // width: 2rem;
270
- // height: 2rem;
271
- // line-height: 2rem;
272
- // right: 0.5rem;
273
- // top: 0.5rem;
274
- // text-align: center;
275
- // transform: rotate(0deg);
276
- // transition: all 0.2s;
277
-
278
- // &:hover {
279
- // transform: rotate(-90deg);
280
- // }
281
- // }
282
-
283
- // &-close {
284
- // position: absolute;
285
- // width: 18px;
286
- // height: 18px;
287
- // right: 0.5em;
288
- // top: 0.5em;
289
- // padding: 0.25em;
290
- // text-align: center;
291
- // transition: all 0.2s;
292
- // // box-shadow: 0 0 0 1px currentColor;
293
- // border-radius: 50%;
294
- // background: linear-gradient(45deg, transparent 44%, currentColor 46%, currentColor 54%, transparent 56%) no-repeat center / 50% 50%,
295
- // linear-gradient(-45deg, transparent 44%, currentColor 46%, currentColor 54%, transparent 56%) no-repeat center / 50% 50%;
296
- // transform: scale(1) rotate(0deg);
297
- // opacity: 0.8;
298
- // transition: all 0.25s;
299
-
300
- // &:hover {
301
- // transform: scale(1) rotate(-90deg);
302
- // }
303
-
304
- // &:active {
305
- // transform: scale(0.8) rotate(-90deg);
306
- // }
269
+ @include neatui.mob {
270
+ .fekit-layer-close {
271
+ top: 1.5em;
272
+ right: 1.5em;
307
273
 
308
- // &::before {
309
- // position: absolute;
310
- // content: '';
311
- // width: 200%;
312
- // height: 200%;
313
- // left: -50%;
314
- // top: -50%;
315
- // }
316
- // }
274
+ color: var(--co-fore);
275
+ top: auto;
276
+ right: auto;
277
+ left: 50%;
278
+ bottom: -2.5rem;
279
+ box-shadow: 0 0 0 2px currentColor;
280
+ }
317
281
  }
318
-
319
- // html {
320
- // &[size='xs'] {
321
- // .fekit-layer-close {
322
- // width: 16px;
323
- // height: 16px;
324
- // }
325
- // }
326
- // &[size='l'] {
327
- // .fekit-layer-close {
328
- // width: 20px;
329
- // height: 20px;
330
- // }
331
- // }
332
- // &[size='xl'] {
333
- // .fekit-layer-close {
334
- // width: 22px;
335
- // height: 22px;
336
- // }
337
- // }
338
- // }
339
282
  </style>
@@ -0,0 +1,133 @@
1
+ import ResizeObserver from 'resize-observer-polyfill';
2
+ import raf from 'raf';
3
+
4
+ class Follow {
5
+ box: any[];
6
+ dom: any;
7
+ tip: any;
8
+ ing: any;
9
+ sub: any;
10
+ obs: any;
11
+ fun: (status: any) => void;
12
+ private css: () => void;
13
+ z: number;
14
+ constructor(dom: any, tip: any, fun = (_status: any) => {}) {
15
+ this.dom = dom;
16
+ this.tip = tip;
17
+ this.box = [];
18
+ this.css = this.setcss.bind(this);
19
+ this.fun = fun;
20
+ this.sub = this.tip.firstElementChild;
21
+ this.z = 0;
22
+ }
23
+ setcss() {
24
+ if (!this.ing) {
25
+ raf(() => {
26
+ this.ing = false;
27
+ const dr = this.dom?.getBoundingClientRect() || { width: 0, height: 0, top: 0, bottom: 0, left: 0, right: 0 };
28
+ const sr = this.sub?.getBoundingClientRect() || { height: 0 };
29
+ this.tip.style.inset = `${dr.top}px auto auto ${dr.left}px`;
30
+ this.tip.style.width = dr.width + 'px';
31
+ this.tip.style.height = dr.height + 'px';
32
+ this.fun('');
33
+ this.box.forEach((e: any) => {
34
+ const _ar = { top: 0, bottom: window.innerHeight, left: 0, right: window.innerWidth };
35
+ const ar = e === window ? _ar : e?.getBoundingClientRect() || _ar;
36
+ if (dr.bottom < ar.top || dr.top > ar.bottom || dr.right < ar.left || dr.left > ar.right) {
37
+ this.tip.style.opacity = '0';
38
+ this.sub.style.pointerEvents = 'none';
39
+ } else {
40
+ this.tip.style.opacity = '';
41
+ this.sub.style.pointerEvents = '';
42
+ }
43
+ if (dr.bottom + sr.height + 10 > ar.bottom) {
44
+ this.fun('b');
45
+ }
46
+ });
47
+ const tr = this.tip?.getBoundingClientRect() || { left: 0 };
48
+ const x = this.sub.offsetLeft + tr.left;
49
+ const arrow = this.sub.querySelector('[ui-tips-arrow]');
50
+ if (x < 0) {
51
+ this.sub.style.transform = `translate3d(${-x}px,0,0)`;
52
+ if (arrow && arrow.style) {
53
+ arrow.style.transform = `translateX(${x}px) rotate(45deg)`;
54
+ }
55
+ } else {
56
+ this.sub.style.transform = '';
57
+ if (arrow && arrow.style) {
58
+ arrow.style.transform = '';
59
+ }
60
+ }
61
+ });
62
+ this.ing = true;
63
+ }
64
+ }
65
+ listen() {
66
+ // 向上查询有滚动条的元素
67
+ const _find = (e: any) => {
68
+ // 判断是否为DOM节点
69
+ if (e) {
70
+ if (e.nodeType === 1) {
71
+ const css: any = window.getComputedStyle(e);
72
+ // 查询所有父组节点的最高层级
73
+ if (!isNaN(css.zIndex) && css.zIndex >= this.z) {
74
+ this.z = Number(css.zIndex) + 10;
75
+ } else {
76
+ this.z += 1;
77
+ }
78
+ // 节点是否有滚动条
79
+ if (
80
+ (css.overflowY === 'auto' || css.overflowY === 'scroll' || css.overflowX === 'auto' || css.overflowX === 'scroll') &&
81
+ (e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth)
82
+ ) {
83
+ this.box.push(e);
84
+ }
85
+ _find(e.parentNode);
86
+ } else if (e.nodeType === 9) {
87
+ console.log(42, e, e.nodeType);
88
+ this.box.push(window);
89
+ }
90
+ }
91
+ };
92
+ _find(this.dom);
93
+
94
+ // 自动层级
95
+ if (window.getComputedStyle(this.tip).zIndex) {
96
+ this.tip.style.zIndex = `${this.z}`;
97
+ }
98
+
99
+ this.css();
100
+ // 监听窗口尺寸变化
101
+ window.addEventListener('resize', this.css);
102
+ window.addEventListener('click', this.css);
103
+ // 监听滚动条的元素
104
+ this.box.forEach((e: any) => {
105
+ e.addEventListener('scroll', this.css);
106
+ });
107
+ // 监听移入事件
108
+ this.dom?.addEventListener('mouseenter', this.css);
109
+ // 监听参考元素变化
110
+ this.obs = new ResizeObserver(this.css);
111
+ if (this.dom) {
112
+ this.obs?.observe(this.dom);
113
+ }
114
+ if (this.sub) {
115
+ this.obs?.observe(this.sub);
116
+ }
117
+ }
118
+ remove() {
119
+ // console.log('移除监听');
120
+ // 清除窗口尺寸变化事件监听器
121
+ window.removeEventListener('resize', this.css);
122
+ window.removeEventListener('click', this.css);
123
+ // 清除滚动条元素的事件监听器
124
+ this.box.forEach((e: any) => {
125
+ e.removeEventListener('scroll', this.css);
126
+ });
127
+ // 清除鼠标移入事件监听器
128
+ this.dom?.removeEventListener('mouseenter', this.css);
129
+ // 清除监听参考元素变化
130
+ this.obs?.disconnect();
131
+ }
132
+ }
133
+ export default Follow;
@@ -285,7 +285,6 @@
285
285
  });
286
286
 
287
287
  const init = ([a = '', b = '']: any = []) => {
288
- console.log(a, b);
289
288
  // 开始
290
289
  if (a && isDateString(a)) {
291
290
  sta.panel = a;
@@ -1,271 +1,149 @@
1
1
  <template>
2
- <div ui-date="@a" class="fekit-date-view pr" :class="`${frame ? 'b-solid bk-line b-xs r-sm' : ''}`" ui-flex="col xy" style="width: 31em; height: 24.5em">
3
- <div class="flex-block" ui-flex="row xy">
4
- <div style="width: 20em; height: 100%">
5
- <div ui-date-head="" class="h-xs+ flex-fixed nx-sl mt-ss ny-ss b-solid bk-back -bb-xs" ui-flex="row xm">
6
- <div ui-flex="row lm" class="o-lm">
7
- <div ui-btn="@a s none :square" @click="prev('y')">
8
- <Icon name="double-arrow-left" />
9
- </div>
10
- <div ui-btn="@a s none :square" @click="prev('m')">
11
- <Icon name="arrow-left" />
12
- </div>
13
- </div>
14
- <div ui-flex="row cm" class="nx-ss-sub">
15
- <div ui-flex="row cm" class="nx-ss-sub">
16
- <p class="nx-ss-sub nowrap" ui-flex="row cm" ui-btns="@a none xs">
17
- <b @click="setPanelType('year')">{{ state.curr.y }}年</b>
18
- <b @click="setPanelType('month')">{{ state.curr.m }}月</b>
19
- </p>
20
- </div>
21
- </div>
22
- <div ui-flex="row rm" class="o-lm">
23
- <div ui-btn="@a s none :square" @click="next('m')">
24
- <Icon name="arrow-right" />
25
- </div>
26
- <div ui-btn="@a s none :square" @click="next('y')">
27
- <Icon name="double-arrow-right" />
28
- </div>
29
- </div>
30
- </div>
31
- <div ui-date-body="" class="flex-block pr">
32
- <div class="full nb-sm">
33
- <ul ui-flex="row am" class="fs-xs nx-sm nt-sm">
34
- <li class="flex-block ac"><span>日</span></li>
35
- <li class="flex-block ac"><span>一</span></li>
36
- <li class="flex-block ac"><span>二</span></li>
37
- <li class="flex-block ac"><span>三</span></li>
38
- <li class="flex-block ac"><span>四</span></li>
39
- <li class="flex-block ac"><span>五</span></li>
40
- <li class="flex-block ac"><span>六</span></li>
41
- </ul>
42
- <ul ui-date-days="" ui-flex="col xm" class="flex-wrap nx-sm">
43
- <li v-for="(week, idx) in state.curr.days" :key="idx" :ui-date-week="idx + 1" class="flex-block" ui-flex="row am" style="margin-bottom: -0.25em">
44
- <div v-for="(item, i) in week" :key="i" class="pr flex-block nb-sm" ui-flex="col xy">
45
- <div
46
- v-if="item.day"
47
- :ui-date-day="item.day"
48
- class="flex-block"
49
- :class="`${item.range ? 'bg-main-xs' : ''} ${item.sta ? 'r-lt-sl r-lb-sl' : ''} ${item.end ? 'r-rt-sl r-rb-sl' : ''}`"
50
- ui-flex="col cm"
51
- @click="change(item)"
52
- @mouseenter="setRangeValue(item)"
53
- >
54
- <div
55
- ui-flex="col cm"
56
- class="r-sm b-solid bk-none b-xs my-ss ux-scale"
57
- style="width: 1.8em; height: 1.8em"
58
- :class="`${item.isLastMonth || item.isNextMonth ? 'co-idle' : item.isHoliday ? 'co-risk' : ''} ${
59
- item.selected ? 'active bg-main-lm co-fore' : 'hover-bg-weak'
60
- }`"
61
- >
62
- <span>{{ item.day }}</span>
63
- </div>
64
- </div>
65
- <div class="pa full-x lh-xs ny-ss ob-no ol-no nowrap s-ml bold" style="transform-origin: 50% 100%" ui-flex="row ct" v-html="extras(item)"></div>
66
- </div>
67
- </li>
68
- </ul>
69
- </div>
2
+ <div ui-date="@a" class="fekit-date-view pr" :class="`${frame ? 'b-solid bk-line b-xs r-sm' : ''}`" ui-flex="col xy" style="width: 22em">
3
+ <div ui-date-head="" class="flex-fixed nx-ms mt-ss ny-sm b-solid bk-back" ui-flex="row xm">
4
+ <div ui-flex="row lm" class="o-lm">
5
+ <div ui-btn="@a s none :square" @click="prev()">
6
+ <Icon name="arrow-left" />
70
7
  </div>
71
8
  </div>
72
- <div style="width: 11em" class="flex-fixed b-solid bk-back bl-xs" ui-flex="col xy">
73
- <div ui-date-head="" class="h-xs+ flex-fixed nx-sl mt-ss ny-ss b-solid bk-back -bb-xs" ui-flex="row cm">
74
- <div ui-flex="row cm" class="nx-ss-sub">
75
- <div ui-flex="row cm" class="nx-ss-sub">
76
- <p class="nx-ss-sub nowrap" ui-flex="row cm" ui-btns="@a none xs">
77
- <b @click="setPanelType('year')">时间</b>
78
- </p>
79
- </div>
80
- </div>
9
+ <div ui-btns="@a none s" @click="setPanelType()">
10
+ <p v-if="state.type > 2" class="nowrap" ui-flex="row cm">
11
+ <b class="nx-ss">{{ panel.sta }}年</b>
12
+ <span class="nx-xs">-</span>
13
+ <b class="nx-ss">{{ panel.end }}年</b>
14
+ </p>
15
+ <p v-else-if="state.type === 1" class="nowrap" ui-flex="row cm">
16
+ <b class="nx-ss">{{ state.curr.y }}年</b>
17
+ </p>
18
+ <p v-else class="nowrap" ui-flex="row cm">
19
+ <b class="nx-xs">{{ state.curr.y }}年</b>
20
+ <b class="nx-xs">{{ state.curr.M }}月</b>
21
+ </p>
22
+ </div>
23
+ <div ui-flex="row rm" class="o-lm">
24
+ <div ui-btn="@a s none :square" @click="next()">
25
+ <Icon name="arrow-right" />
81
26
  </div>
82
- <div ui-date-body="" class="flex-block pr nl-ss n-ss-sub ac">
83
- <div class="full" ui-row="mob-8">
84
- <div class="full" ui-scroll=":y" style="padding-bottom: 15.2em">
85
- <ul ui-btns="@a none s :block">
86
- <li>00</li>
87
- <li>01</li>
88
- <li>02</li>
89
- <li>03</li>
90
- <li>04</li>
91
- <li>05</li>
92
- <li>06</li>
93
- <li>07</li>
94
- <li>08</li>
95
- <li>09</li>
96
- <li>10</li>
97
- <li>11</li>
98
- <li>12</li>
99
- <li>13</li>
100
- <li>14</li>
101
- <li>15</li>
102
- <li>16</li>
103
- <li>17</li>
104
- <li>18</li>
105
- <li>19</li>
106
- <li>20</li>
107
- <li>21</li>
108
- <li>22</li>
109
- <li>23</li>
110
- </ul>
111
- </div>
112
- <div class="full" ui-scroll=":y" style="padding-bottom: 15.2em">
113
- <ul ui-btns="@a none s :block">
114
- <li>00</li>
115
- <li>01</li>
116
- <li>02</li>
117
- <li>03</li>
118
- <li>04</li>
119
- <li>05</li>
120
- <li>06</li>
121
- <li>07</li>
122
- <li>08</li>
123
- <li>09</li>
124
-
125
- <li>10</li>
126
- <li>11</li>
127
- <li>12</li>
128
- <li>13</li>
129
- <li>14</li>
130
- <li>15</li>
131
- <li>16</li>
132
- <li>17</li>
133
- <li>18</li>
134
- <li>19</li>
135
-
136
- <li>20</li>
137
- <li>21</li>
138
- <li>22</li>
139
- <li>23</li>
140
- <li>24</li>
141
- <li>25</li>
142
- <li>26</li>
143
- <li>27</li>
144
- <li>28</li>
145
- <li>29</li>
146
-
147
- <li>30</li>
148
- <li>31</li>
149
- <li>32</li>
150
- <li>33</li>
151
- <li>34</li>
152
- <li>35</li>
153
- <li>36</li>
154
- <li>37</li>
155
- <li>38</li>
156
- <li>39</li>
157
-
158
- <li>40</li>
159
- <li>41</li>
160
- <li>42</li>
161
- <li>43</li>
162
- <li>44</li>
163
- <li>45</li>
164
- <li>46</li>
165
- <li>47</li>
166
- <li>48</li>
167
- <li>49</li>
168
-
169
- <li>50</li>
170
- <li>51</li>
171
- <li>52</li>
172
- <li>53</li>
173
- <li>54</li>
174
- <li>55</li>
175
- <li>56</li>
176
- <li>57</li>
177
- <li>58</li>
178
- <li>59</li>
179
- </ul>
180
- </div>
181
- <div class="full" ui-scroll=":y" style="padding-bottom: 15.2em">
182
- <ul ui-btns="@a none s :block">
183
- <li>00</li>
184
- <li>01</li>
185
- <li>02</li>
186
- <li>03</li>
187
- <li>04</li>
188
- <li>05</li>
189
- <li>06</li>
190
- <li>07</li>
191
- <li>08</li>
192
- <li>09</li>
193
-
194
- <li>10</li>
195
- <li>11</li>
196
- <li>12</li>
197
- <li>13</li>
198
- <li>14</li>
199
- <li>15</li>
200
- <li>16</li>
201
- <li>17</li>
202
- <li>18</li>
203
- <li>19</li>
204
-
205
- <li>20</li>
206
- <li>21</li>
207
- <li>22</li>
208
- <li>23</li>
209
- <li>24</li>
210
- <li>25</li>
211
- <li>26</li>
212
- <li>27</li>
213
- <li>28</li>
214
- <li>29</li>
215
-
216
- <li>30</li>
217
- <li>31</li>
218
- <li>32</li>
219
- <li>33</li>
220
- <li>34</li>
221
- <li>35</li>
222
- <li>36</li>
223
- <li>37</li>
224
- <li>38</li>
225
- <li>39</li>
226
-
227
- <li>40</li>
228
- <li>41</li>
229
- <li>42</li>
230
- <li>43</li>
231
- <li>44</li>
232
- <li>45</li>
233
- <li>46</li>
234
- <li>47</li>
235
- <li>48</li>
236
- <li>49</li>
237
-
238
- <li>50</li>
239
- <li>51</li>
240
- <li>52</li>
241
- <li>53</li>
242
- <li>54</li>
243
- <li>55</li>
244
- <li>56</li>
245
- <li>57</li>
246
- <li>58</li>
247
- <li>59</li>
248
- </ul>
27
+ </div>
28
+ </div>
29
+ <div ui-date-body="" class="flex-block pr">
30
+ <div v-if="state.type === 2" class="full n-ms">
31
+ <ul ui-row="mob-6" class="n-ms ny-sm-sub">
32
+ <li v-for="(year, idx) in panel.years" :key="idx" ui-flex="col cm" @click="setDateValue('y', year)">
33
+ <div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">{{ year }}</div>
34
+ </li>
35
+ </ul>
36
+ </div>
37
+ <div v-else-if="state.type === 1" class="full">
38
+ <ul ui-row="mob-4" class="n-ms ny-sm-sub">
39
+ <li ui-flex="col cm" @click="setDateValue('m', 1)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">1月</div></li>
40
+ <li ui-flex="col cm" @click="setDateValue('m', 2)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">2月</div></li>
41
+ <li ui-flex="col cm" @click="setDateValue('m', 3)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">3月</div></li>
42
+ <li ui-flex="col cm" @click="setDateValue('m', 4)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">4月</div></li>
43
+ <li ui-flex="col cm" @click="setDateValue('m', 5)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">5月</div></li>
44
+ <li ui-flex="col cm" @click="setDateValue('m', 6)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">6月</div></li>
45
+ <li ui-flex="col cm" @click="setDateValue('m', 7)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">7月</div></li>
46
+ <li ui-flex="col cm" @click="setDateValue('m', 8)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">8月</div></li>
47
+ <li ui-flex="col cm" @click="setDateValue('m', 9)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">9月</div></li>
48
+ <li ui-flex="col cm" @click="setDateValue('m', 10)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">10月</div></li>
49
+ <li ui-flex="col cm" @click="setDateValue('m', 11)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">11月</div></li>
50
+ <li ui-flex="col cm" @click="setDateValue('m', 12)"><div ui-flex="col cm" class="w-xs+ h-xs+ ac ux-none co-main:hover">12月</div></li>
51
+ </ul>
52
+ </div>
53
+ <div v-else class="full">
54
+ <ul ui-flex="row am" class="fs-xs nx-sm nt-sm">
55
+ <li class="flex-block ac"><span>日</span></li>
56
+ <li class="flex-block ac"><span>一</span></li>
57
+ <li class="flex-block ac"><span>二</span></li>
58
+ <li class="flex-block ac"><span>三</span></li>
59
+ <li class="flex-block ac"><span>四</span></li>
60
+ <li class="flex-block ac"><span>五</span></li>
61
+ <li class="flex-block ac"><span>六</span></li>
62
+ </ul>
63
+ <ul ui-date-days="" ui-flex="col xm" class="flex-wrap nx-sm">
64
+ <li v-for="(week, idx) in state.curr.days" :key="idx" :ui-date-week="idx + 1" class="flex-block" ui-flex="row am" style="margin-bottom: -0.25em">
65
+ <div v-for="(item, i) in week" :key="i" class="pr flex-block nb-sm" ui-flex="col xy">
66
+ <div
67
+ v-if="item.day"
68
+ :ui-date-day="item.day"
69
+ class="flex-block"
70
+ :class="`${item.range ? 'bg-main-xs' : ''} ${item.sta ? 'r-lt-sl r-lb-sl' : ''} ${item.end ? 'r-rt-sl r-rb-sl' : ''}`"
71
+ ui-flex="col cm"
72
+ @click="change(item)"
73
+ >
74
+ <div
75
+ ui-flex="col cm"
76
+ class="r-sm b-solid bk-none b-xs my-ss ux-scale co-main:hover"
77
+ style="width: 1.8em; height: 1.8em"
78
+ :class="`${item.isLastMonth || item.isNextMonth ? 'co-idle' : item.isHoliday ? 'co-risk' : ''} ${item.selected ? 'active bg-main-lm co-fore' : 'hover-bg-weak'}`"
79
+ >
80
+ <span>{{ item.day }}</span>
81
+ </div>
82
+ </div>
83
+ <div class="pa full-x lh-xs ny-ss ob-no ol-no nowrap s-ml bold" style="transform-origin: 50% 100%" ui-flex="row ct" v-html="extras(item)"></div>
249
84
  </div>
250
- </div>
251
- </div>
85
+ </li>
86
+ </ul>
87
+ </div>
88
+ </div>
89
+ <div v-if="!state.isNoTime && state.type === 0" class="ny-sm nx-ms">
90
+ <div class="full ac b-solid bk-back b-xs r-sm" ui-row="mob-8" style="width: 100%; height: 3em; padding: 0.5em">
91
+ <ul
92
+ :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
93
+ class="fekit-date-view-time-scroll"
94
+ ref="ths"
95
+ ui-scroll=":y xs"
96
+ ui-btns="@a none s :block"
97
+ data-type="h"
98
+ @scroll="timeScroll"
99
+ >
100
+ <li v-for="(item, idx) in hours" :key="idx">
101
+ {{ item }}
102
+ </li>
103
+ </ul>
104
+ <ul
105
+ :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
106
+ class="fekit-date-view-time-scroll"
107
+ ref="tms"
108
+ ui-scroll=":y xs"
109
+ ui-btns="@a none s :block"
110
+ data-type="m"
111
+ @scroll="timeScroll"
112
+ >
113
+ <li v-for="(item, idx) in seconds" :key="idx">
114
+ {{ item }}
115
+ </li>
116
+ </ul>
117
+ <ul
118
+ :style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
119
+ class="fekit-date-view-time-scroll"
120
+ ref="tss"
121
+ ui-scroll=":y xs"
122
+ ui-btns="@a none s :block"
123
+ data-type="s"
124
+ @scroll="timeScroll"
125
+ >
126
+ <li v-for="(item, idx) in seconds" :key="idx">
127
+ {{ item }}
128
+ </li>
129
+ </ul>
252
130
  </div>
253
131
  </div>
254
132
  <div v-if="tools" ui-date-foot="" ui-flex="row xm" class="flex-fixed nx-sl ny-sl b-solid bk-line-mm bt-xs">
255
133
  <div ui-flex="row lm" class="nl-ss">
256
- <p v-if="state.panel" ui-flex="row lm">
257
- <span ui-btn="@a xs none" class="nx-ss" @click="setPanelType('date')">{{ state.panel }}</span>
258
- <span v-if="!state.isNoTime" ui-btn="@a xs none" class="nx-ss" @click="setPanelType('time')"> {{ state.time.h }}:{{ state.time.m }}:{{ state.time.s }} </span>
259
- </p>
134
+ <div v-if="state.panel" ui-flex="row lm">
135
+ <span :anim-editing="state.type === 'date'" class="nx-ss">{{ idate(state.panel).format('YYYY-MM-DD') }}</span>
136
+ <span v-if="!state.isNoTime" :anim-editing="state.type === 'time'" class="nx-ss">{{ idate(state.panel).format('HH:mm:ss') }}</span>
137
+ </div>
260
138
  <div v-else-if="state.shortcuts?.length" ui-flex="row lm">
261
139
  <div class="mr-sm-sub nx-sl-sub ny-ss-sub lh-ss nowrap fs-ss dib-sub" ui-scroll=":x y:hidden">
262
- <p v-for="(item, idx) in state.shortcuts" :key="idx" class="bg-main-xs co-main r-xl" ui-btn="@a xs none :round" @click="item?.func">{{ item?.text }}</p>
263
- <p class="bg-main-xs co-main r-xl" ui-btn="@a xs none :round"><Icon class="co-main" name="more" /></p>
140
+ <p v-for="(item, idx) in state.shortcuts" :key="idx" class="bg-main-ss co-main r-xl" ui-btn="@a xs none :round" @click="item?.func">{{ item?.text }}</p>
141
+ <p class="bg-main-ss co-main r-xl" ui-btn="@a xs none :round"><Icon class="co-main" name="more" /></p>
264
142
  </div>
265
143
  </div>
266
144
  <div>&nbsp;</div>
267
145
  </div>
268
- <div class="ml-sm-sub" ui-flex="row rm">
146
+ <div class="ml-ss-sub" ui-flex="row rm">
269
147
  <button v-if="state.panel" ui-btn="@a xs none" class="nx-ss co-risk" @click="remove">清除</button>
270
148
  <button v-if="state.panel && !state.isNoTime" ui-btn="@a xs none" class="nx-ss co-main" @click="update">确定</button>
271
149
  </div>
@@ -273,10 +151,13 @@
273
151
  </div>
274
152
  </template>
275
153
  <script setup lang="ts">
276
- import { computed, reactive, watch } from 'vue';
277
- import { idate, isDateString, isObject, isString } from '@fekit/utils';
154
+ import { computed, ref, reactive, watch, onMounted } from 'vue';
155
+ import { isDateString, isObject, isString } from '@fekit/utils';
156
+ import { idate } from '@fekit/utils';
278
157
  import { Icon } from '../basic';
279
158
 
159
+ const _level: any = { 0: ['d', 1], 1: ['m', 1], 2: ['y', 10], 3: ['y', 100] };
160
+
280
161
  // 创建日期
281
162
  const cDate = (date: any = null) => {
282
163
  return isDateString(date) ? new Date(date) : new Date();
@@ -321,6 +202,7 @@
321
202
  shortcuts?: Array<'yesterday' | 'today' | 'tomorrow'>;
322
203
  extras?: (item: any) => string;
323
204
  time?: boolean | TimeProps;
205
+ lang?: string;
324
206
  }
325
207
  const props: any = withDefaults(defineProps<Props>(), {
326
208
  // 值
@@ -343,21 +225,42 @@
343
225
  format: 'YYYY-MM-DD',
344
226
  // 节假日
345
227
  holiday: () => ({}),
346
- time: false
228
+ time: false,
229
+ // 语言
230
+ lang: 'zh-CN'
231
+ });
232
+
233
+ // 小时
234
+ const hours = computed(() => {
235
+ const _hours: any = [];
236
+ for (let i = 0; i < 24; i++) {
237
+ _hours.push(i > 9 ? `${i}` : `0${i}`);
238
+ }
239
+ return _hours;
240
+ });
241
+ // 分秒
242
+ const seconds = computed(() => {
243
+ const _seconds: any = [];
244
+ for (let i = 0; i < 60; i++) {
245
+ _seconds.push(i > 9 ? `${i}` : `0${i}`);
246
+ }
247
+ return _seconds;
347
248
  });
348
249
 
349
250
  // 内部数据
350
251
  const state: any = reactive({
351
252
  // 面板显示时间
352
253
  panel: '',
254
+ // 面板年份选择
255
+ years: 0,
353
256
  // 当前时间计算
354
257
  curr: computed(() => {
355
258
  const date = idate(state.panel);
356
259
  const days = date.calendar({ group: true, value: [state.panel] });
357
- const { y = 0, M: m = 0, d = 0 } = date.attr || {};
358
- return { days, y, m, d };
260
+ return { days, ...date.attr };
359
261
  }),
360
- type: 'date',
262
+ // 当前面板类型
263
+ type: 0,
361
264
  // 值
362
265
  value: '',
363
266
  // 快捷选择
@@ -366,21 +269,70 @@
366
269
  return isString(item) ? shortcutsList[item] : item;
367
270
  });
368
271
  }),
369
- // 时间
370
- time: {
371
- h: '00',
372
- m: '00',
373
- s: '00'
374
- },
272
+ // 不带时间(只要时或分的也考虑到)
375
273
  isNoTime: computed(() => {
376
274
  if (isObject(props.time)) {
377
275
  return !(props.time.h || props.time.m || props.time.s);
378
276
  } else {
379
- return props.time;
277
+ return !props.time;
278
+ }
279
+ })
280
+ });
281
+
282
+ // 面板
283
+ const panel: any = reactive({
284
+ years: computed(() => {
285
+ const startYear = Math.floor(state.curr.year / 10) * 10;
286
+ const list = [];
287
+ for (let i = 0; i < 10; i++) {
288
+ list.push(startYear + i);
380
289
  }
290
+ return list;
291
+ }),
292
+ sta: computed(() => {
293
+ return panel.years[0];
294
+ }),
295
+ end: computed(() => {
296
+ return panel.years[9];
381
297
  })
382
298
  });
383
299
 
300
+ // 设置日期
301
+ const setDateValue = (type: any, value: number = 0, add: number = 0) => {
302
+ state.panel = upload(type, value, add);
303
+ // 面板返回上一级
304
+ state.type -= 1;
305
+ };
306
+
307
+ // 时分秒
308
+ const ths: any = ref(null);
309
+ const tms: any = ref(null);
310
+ const tss: any = ref(null);
311
+ const setTimeValue = () => {
312
+ const { H = 0, m = 0, s = 0 }: any = state.curr || {};
313
+ if (state.panel) {
314
+ if (ths.value && ths.value.children[H]) {
315
+ ths.value.scrollTop = ths.value.children[H].offsetTop;
316
+ }
317
+ if (tms.value && tms.value.children[m]) {
318
+ tms.value.scrollTop = tms.value.children[m].offsetTop;
319
+ }
320
+ if (tss.value && tss.value.children[s]) {
321
+ tss.value.scrollTop = tss.value.children[s].offsetTop;
322
+ }
323
+ } else {
324
+ if (ths.value && ths.value.children[H]) {
325
+ ths.value.scrollTop = ths.value.children[0].offsetTop;
326
+ }
327
+ if (tms.value && tms.value.children[m]) {
328
+ tms.value.scrollTop = tms.value.children[0].offsetTop;
329
+ }
330
+ if (tss.value && tss.value.children[s]) {
331
+ tss.value.scrollTop = tss.value.children[0].offsetTop;
332
+ }
333
+ }
334
+ };
335
+
384
336
  watch(
385
337
  () => props.modelValue,
386
338
  (value: any) => {
@@ -388,29 +340,80 @@
388
340
  state.panel = value || '';
389
341
  // 值
390
342
  state.value = value || '';
391
- // 时间
392
343
  },
393
344
  { deep: true, immediate: true }
394
345
  );
395
346
 
347
+ onMounted(() => {
348
+ setTimeValue();
349
+ });
350
+ watch(
351
+ () => state.panel,
352
+ () => {
353
+ setTimeValue();
354
+ }
355
+ );
356
+
396
357
  // 更新时间
397
- const upload = (a: any = 'm', b: any = 1) => {
358
+ const upload = (type: string = 'm', value: number = 0, add: number = 1) => {
398
359
  const date = cDate(state.panel);
399
- if (a === 'm') {
400
- date.setMonth(date.getMonth() + b);
401
- } else {
402
- date.setFullYear(date.getFullYear() + b);
360
+
361
+ switch (type) {
362
+ case 'y':
363
+ if (value !== 0) {
364
+ date.setFullYear(value);
365
+ } else {
366
+ date.setFullYear(date.getFullYear() + add);
367
+ }
368
+ break;
369
+ case 'm':
370
+ if (value !== 0) {
371
+ date.setMonth(value - 1);
372
+ } else {
373
+ date.setMonth(date.getMonth() + add);
374
+ }
375
+ break;
376
+ case 'd':
377
+ if (value !== 0) {
378
+ date.setDate(value);
379
+ } else {
380
+ date.setDate(date.getDate() + add);
381
+ }
382
+ break;
383
+ case 'h':
384
+ if (value !== 0) {
385
+ date.setHours(value);
386
+ } else {
387
+ date.setHours(date.getHours() + add);
388
+ }
389
+ break;
390
+ case 'n':
391
+ if (value !== 0) {
392
+ date.setMinutes(value);
393
+ } else {
394
+ date.setMinutes(date.getMinutes() + add);
395
+ }
396
+ break;
397
+ case 's':
398
+ if (value !== 0) {
399
+ date.setSeconds(value);
400
+ } else {
401
+ date.setSeconds(date.getSeconds() + add);
402
+ }
403
+ break;
404
+ default:
405
+ break;
403
406
  }
404
407
  return idate(date).format(props.format);
405
408
  };
406
409
 
407
410
  // 日期前翻
408
- const prev = (type: any = 'm') => {
409
- state.panel = upload(type, -1);
411
+ const prev = () => {
412
+ state.panel = upload(state.type > 0 ? 'y' : 'm', 0, state.type === 2 ? -10 : -1);
410
413
  };
411
414
  // 日期后翻
412
- const next = (type: any = 'm') => {
413
- state.panel = upload(type, 1);
415
+ const next = () => {
416
+ state.panel = upload(state.type > 0 ? 'y' : 'm', 0, state.type === 2 ? 10 : 1);
414
417
  };
415
418
 
416
419
  // 向外通信
@@ -418,7 +421,6 @@
418
421
  state.panel = item ? idate(item.date).format(props.format) : item;
419
422
  emits('change', state.value);
420
423
  if (state.isNoTime) {
421
- console.log('这是没有时间的');
422
424
  update();
423
425
  }
424
426
  };
@@ -431,41 +433,50 @@
431
433
 
432
434
  // 更新数据
433
435
  const update = () => {
434
- emits('update:modelValue', state.panel);
435
- emits('update', state.panel);
436
+ emits('update:modelValue', state.panel ? idate(state.panel).format(props.format) : '');
437
+ emits('update', state.panel ? idate(state.panel).format(props.format) : '');
436
438
  };
437
439
 
438
- // 设置范围
439
- const setRangeValue = (item: any) => {};
440
- // 设置面板类型
441
- const setPanelType = (type: any) => {
442
- state.type = type;
443
- };
444
- // 设置年份
445
- const setYear = (y: any) => {
446
- state.type = 'month';
440
+ // 面板类型
441
+ const setPanelType = () => {
442
+ if (state.type < 3) {
443
+ state.type += 1;
444
+ }
447
445
  };
448
- // 设置月份
449
- const setMonth = (m: any) => {
450
- state.type = 'date';
446
+
447
+ // 时间滚动
448
+ const _timer: any = ref(null);
449
+ const timeScroll = (ev: any) => {
450
+ const item: any = ev.target?.children[0];
451
+ const type: any = ev.target.getAttribute('data-type') || '';
452
+ if (state.panel && item) {
453
+ clearTimeout(_timer.value);
454
+ _timer.value = setTimeout(() => {
455
+ const h = item.offsetHeight;
456
+ const idx = Math.floor(ev.target.scrollTop / h);
457
+ const { YYYY = 0, MM = 0, DD = 0, HH = '', mm = '', ss = '' }: any = state.curr || {};
458
+ let _panel = `${YYYY}-${MM}-${DD}`;
459
+ if (type === 'h') {
460
+ _panel += ` ${idx}:${mm}:${ss}`;
461
+ }
462
+ if (type === 'm') {
463
+ _panel += ` ${HH}:${idx}:${ss}`;
464
+ }
465
+ if (type === 's') {
466
+ _panel += ` ${HH}:${mm}:${idx}`;
467
+ }
468
+ state.panel = idate(_panel).format('YYYY-MM-DD HH:mm:ss');
469
+ }, 100);
470
+ }
451
471
  };
452
472
  </script>
453
473
  <style lang="scss">
454
- @keyframes am-editing {
455
- 0%,
456
- 20% {
457
- opacity: 1;
458
- }
459
- 40%,
460
- 60% {
461
- opacity: 0;
474
+ .fekit-date-view-time-scroll {
475
+ position: relative;
476
+ height: 100%;
477
+ scroll-snap-type: y mandatory;
478
+ & > * {
479
+ scroll-snap-align: center;
462
480
  }
463
- 80%,
464
- 100% {
465
- opacity: 1;
466
- }
467
- }
468
- .am-editing {
469
- animation: am-editing 1s linear infinite;
470
481
  }
471
482
  </style>
@@ -18,8 +18,8 @@ import PageSelect from './PageSelect.vue';
18
18
  import SelectTree from './SelectTree/SelectTree@v1.vue';
19
19
 
20
20
  // import DateView from './DateView.vue';
21
- import DateView from './DateView@v2.vue';
22
- // import DateView from './DateView@v3.vue';
21
+ // import DateView from './DateView@v2.vue';
22
+ import DateView from './DateView@v3.vue';
23
23
  import DateRangeView from './DateRangeView@v3.vue';
24
24
  import DatePicker from './DatePicker.vue';
25
25
  import TimePicker from './TimePicker.vue';