plain-design 1.0.0-beta.38 → 1.0.0-beta.39

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plain-design",
3
- "version": "1.0.0-beta.38",
3
+ "version": "1.0.0-beta.39",
4
4
  "description": "",
5
5
  "main": "dist/plain-design.min.js",
6
6
  "module": "dist/plain-design.commonjs.min.js",
@@ -7,12 +7,12 @@
7
7
 
8
8
  .alert-label {
9
9
  font-size: plv(font-size-small);
10
- line-height: 1.5715;
10
+ line-height: plv(line-height);
11
11
  }
12
12
 
13
13
  .alert-desc {
14
14
  font-size: plv(font-size-small);
15
- line-height: 1.5715;
15
+ line-height: plv(line-height);
16
16
  }
17
17
 
18
18
  &.alert-has-icon {
@@ -75,6 +75,7 @@ function createOtherVars(prefix: string | null, referenceVariable: (name: string
75
75
  'background-hover': referenceVariable("gray-2"),
76
76
  'scrollbar-color': referenceVariable("gray-3"),
77
77
  'loading-mask-color': 'rgba(255,255,255,0.5)',
78
+ 'line-height': 'plv(line-height)',
78
79
 
79
80
  'font-size-mini': '12px',
80
81
  'font-size-small': '12px',
@@ -171,6 +171,7 @@ export const useTableOptionFilterForm = AutoModule.createRegistration((
171
171
  initialState={state.data}
172
172
  onSearch={handler.onNormalSearch}
173
173
  column={config.filterFormColumn}
174
+ searchButtonAttrs={{ mode: 'flat' }}
174
175
  v-slots={{
175
176
  operation: () => (
176
177
  <Button label={i18n('base.collapse').d('收起')} icon="pi-shrink" onClick={methods.toggleShow}/>
@@ -7,7 +7,7 @@
7
7
  outline: none;
8
8
  position: relative;
9
9
  text-align: center;
10
- line-height: 1.5715;
10
+ line-height: plv(line-height);
11
11
  white-space: nowrap;
12
12
  display: inline-block;
13
13
  user-select: none;
@@ -48,7 +48,7 @@
48
48
  width: 100%;
49
49
  color: plv(text-2);
50
50
  padding: 9px 12px;
51
- line-height: 1.5715;
51
+ line-height: plv(line-height);
52
52
  }
53
53
 
54
54
  .card-poster {
@@ -1,4 +1,4 @@
1
- import {computed, designComponent, getComponentCls, PropType, reactive, useClasses, watch} from "plain-design-composition";
1
+ import {computed, designComponent, getComponentCls, mergeAttrs, PropType, reactive, useClasses, watch} from "plain-design-composition";
2
2
  import {PlainObject} from "plain-utils/utils/event";
3
3
  import {Form} from "../Form";
4
4
  import {FormItem} from "../FormItem";
@@ -44,10 +44,14 @@ export type iFilterFormMultipleData = iFilterFormMultipleState & { filterQueryPa
44
44
  export const FilterFormMultiple = designComponent({
45
45
  name: 'filter-form-multiple',
46
46
  props: {
47
- filterOptions: { type: Array as PropType<iFilterOption[]> },
48
- initialState: { type: Object as PropType<iFilterFormMultipleState> },
49
- formAttrs: { type: Object as PropType<typeof Form.use.props> },
50
- column: { type: Number, default: 3 },
47
+ filterOptions: { type: Array as PropType<iFilterOption[]> }, // 删选表单配置对象
48
+ initialState: { type: Object as PropType<iFilterFormMultipleState> }, // 初始值
49
+ formAttrs: { type: Object as PropType<typeof Form.use.props> }, // 给Form传递的属性
50
+ column: { type: Number, default: 3 }, // 列数
51
+ hideSearchButton: { type: Boolean }, // 隐藏查询按钮
52
+ hideResetButton: { type: Boolean }, // 隐藏重置按钮
53
+ searchButtonAttrs: { type: Object as PropType<PlainObject> }, // 给查询按钮传递的属性
54
+ resetButtonAttrs: { type: Object as PropType<PlainObject> }, // 给重置按钮传递的属性
51
55
  },
52
56
  slots: ['operation'],
53
57
  emits: {
@@ -246,11 +250,28 @@ export const FilterFormMultiple = designComponent({
246
250
  if (formColumn == null) {return 1;}
247
251
  return Number(formColumn) - usingFilterOptions.value.length % Number(formColumn);
248
252
  })()}>
249
- <div className="filter-form-multiple-operation">
250
- {slots.operation()}
251
- <Button label={i18n('base.reset').d('重置')} icon="pi-delete" onClick={methods.reset}/>
252
- <Button label={i18n('base.query').d('查询')} mode="fill" icon="pi-search" onClick={methods.search}/>
253
- </div>
253
+ {(!props.hideResetButton || !props.hideSearchButton || slots.operation.isExist()) && (
254
+ <div className="filter-form-multiple-operation">
255
+ {slots.operation()}
256
+ {!props.hideResetButton && (
257
+ <Button {...mergeAttrs({
258
+ label: i18n('base.reset').d('重置'),
259
+ icon: "pi-delete",
260
+ onClick: methods.reset
261
+ }, props.resetButtonAttrs)}/>
262
+ )}
263
+ {!props.hideSearchButton && (
264
+ <Button
265
+ {...mergeAttrs({
266
+ label: i18n('base.query').d('查询'),
267
+ mode: "fill",
268
+ icon: "pi-search",
269
+ onClick: methods.search,
270
+ }, props.searchButtonAttrs)}
271
+ />
272
+ )}
273
+ </div>
274
+ )}
254
275
  </FormItem>
255
276
  </Form>
256
277
  </div>
@@ -41,7 +41,7 @@
41
41
  border: none;
42
42
  background-color: transparent;
43
43
  box-sizing: border-box;
44
- line-height: 1.5715;
44
+ line-height: plv(line-height);
45
45
  padding-top: 3px;
46
46
  padding-bottom: 3px;
47
47
  color: plv(text-2);
@@ -352,7 +352,7 @@
352
352
  display: inline-block;
353
353
  padding: 3px 12px;
354
354
  box-sizing: border-box;
355
- line-height: 1.5715;
355
+ line-height: plv(line-height);
356
356
  word-break: break-all;
357
357
  }
358
358
 
@@ -47,12 +47,21 @@
47
47
  }
48
48
  }
49
49
 
50
+ .number-prepend-button, .number-append-button {
51
+ transform: scale(0.9);
52
+ }
53
+
50
54
  @include sizeMixin(input, ()) {
51
55
  .number-button-container {
52
- width: $height,
56
+ width: $height;
57
+ height: calc(#{$height} - 2px);
53
58
  }
54
59
  }
55
60
  }
61
+
62
+ .input-box {
63
+ align-self: center;
64
+ }
56
65
  }
57
66
 
58
67
  @include prefix(number-resize) {
@@ -10,13 +10,17 @@ export const StackCard = designComponent({
10
10
  name: 'stack-card',
11
11
  props: {
12
12
  modelValue: { type: [String, Number] }, // 双向绑定值,当前显示哪一个子节点
13
- leftBufferCount: { type: Number }, // 左侧显示元素个数
14
- rightBufferCount: { type: Number }, // 右侧显示元素个数
13
+ prevBufferCount: { type: Number }, // 左/上侧显示元素个数
14
+ nextBufferCount: { type: Number }, // 右/下侧显示元素个数, 这个包含当前显示的元素,所以这个nextBufferCount不能小于1
15
15
  stackItemWidth: { type: Number, default: 24 }, // 每一张折叠卡片横向偏移距离
16
- stackItemHeight: { type: Number, default: 12 }, //每一张折叠卡片纵向向偏移距离
17
- scaleRate: { type: Number, default: 0.1 }, // 缩放比例
18
- verticalOffset: { type: Boolean }, // 开启纵向偏移
19
- verticalAlign: { type: String as PropType<'top' | 'center' | 'bottom'>, default: 'center' }, // 纵向对齐方式
16
+ stackItemHeight: { type: Number, default: 12 }, // 每一张折叠卡片纵向向偏移距离
17
+ scaleRate: { type: Number, default: 0.1 }, // 每一张折叠卡片缩放比例
18
+ demandRender: { type: Boolean }, // 按需渲染内容,当卡片没有展示的时候不渲染内容
19
+ flick: { type: Boolean }, // 轻拂模式,拖拽的时候不会触发卡片滚动,松开的时候才会触发切换,如果卡片内容有复杂的内容比如表单因为transform变化显示异常的情况下可以启用这个属性
20
+
21
+ vertical: { type: Boolean }, // 设置为true之后,开启纵向切换
22
+ verticalOffset: { type: Boolean }, // 横向切换下有效,开启纵向偏移
23
+ verticalAlign: { type: String as PropType<'top' | 'center' | 'bottom'>, default: 'center' }, // 横向切换下有效,纵向对齐方式
20
24
  },
21
25
  emits: {
22
26
  onUpdateModelValue: (val?: string | number) => true,
@@ -32,50 +36,129 @@ export const StackCard = designComponent({
32
36
 
33
37
  const classes = useClasses(() => [
34
38
  getComponentCls('stack-card'),
39
+ `stack-card-direction-${props.vertical ? 'vertical' : 'horizontal'}`,
35
40
  {
36
- 'stack-card-touching': draggier.draggierState.touching
41
+ 'stack-card-touching': draggier.draggierState.touching,
37
42
  }
38
43
  ]);
39
44
 
40
45
  const draggier = (() => {
41
46
 
42
- const draggierState = reactive({ left: 0, touching: false, });
47
+ /**
48
+ * 拖拽响应式状态
49
+ * @author 韦胜健
50
+ * @date 2024/2/1 14:34
51
+ * @param lot 缩写,left or top
52
+ * @param touching, 当前是否处于拖拽状态
53
+ */
54
+ const draggierState = reactive({ lot: 0, touching: false, });
43
55
 
44
56
  const touchstart = (e: TouchEvent | MouseEvent) => {
45
57
  e.preventDefault();
46
58
  e.stopPropagation();
47
59
 
48
60
  let staticState = {
49
- startLeft: draggierState.left,
50
- startX: 'touches' in e ? e.touches[0].clientX : e.clientX,
61
+ /*拖拽开始时的left or top*/
62
+ startLot: draggierState.lot,
63
+ /*拖拽开始时触点的x轴以及y轴位置*/
64
+ ...'touches' in e ? {
65
+ startX: e.touches[0].clientX,
66
+ startY: e.touches[0].clientY,
67
+ } : {
68
+ startX: e.clientX,
69
+ startY: e.clientY,
70
+ },
71
+ moveX: 0,
72
+ moveY: 0
51
73
  };
52
74
  const { effects: draggierEffects } = createEffects();
53
75
 
54
76
  const touchmove = (e: TouchEvent | MouseEvent) => {
55
- let durX = Math.ceil(('touches' in e ? e.touches[0].clientX : e.clientX) - staticState.startX);
77
+
78
+ Object.assign(
79
+ staticState,
80
+ 'touches' in e
81
+ ? {
82
+ moveX: e.touches[0].clientX,
83
+ moveY: e.touches[0].clientY
84
+ }
85
+ : {
86
+ moveX: e.clientX,
87
+ moveY: e.clientY
88
+ }
89
+ );
90
+
91
+ let { durX, durY } = {
92
+ durX: staticState.moveX - staticState.startX,
93
+ durY: staticState.moveY - staticState.startY
94
+ };
95
+
56
96
  if (!draggierState.touching) {
57
- if (Math.abs(durX) > 10) {
97
+ /*横向切换状态下,横向移动距离超过10个像素*/
98
+ /*或者纵向切换状态下,纵向移动距离超过10个像素*/
99
+ if ((!props.vertical && Math.abs(durX) > 10) || (props.vertical && Math.abs(durY) > 10)) {
58
100
  draggierState.touching = true;
59
101
  draggierEffects.push(() => {
60
102
  draggierState.touching = false;
61
- if (!!renderData) {
62
- /**
63
- * 设置滚动位置为最近的子节点
64
- * @author 韦胜健
65
- * @date 2024/1/4 21:12
66
- */
67
- const { closestItem, itemsList, itemValList } = renderData;
68
- draggierState.left = itemsList.find(i => i.index === closestItem.index)!.startLeft;
69
- const newVal = itemValList[closestItem.index];
70
- if (newVal != model.value) {model.value = newVal;}
103
+ if (!props.flick) {
104
+ if (!!renderData) {
105
+ /**
106
+ * 设置滚动位置为最近的子节点
107
+ * @author 韦胜健
108
+ * @date 2024/1/4 21:12
109
+ */
110
+ const { closestItem, itemsList, itemValList } = renderData;
111
+ draggierState.lot = itemsList.find(
112
+ (i) => i.index === closestItem.index
113
+ )!.startLot;
114
+ const newVal = itemValList[closestItem.index];
115
+ if (newVal != model.value) {
116
+ model.value = newVal;
117
+ // delay(300).then(() => refreshItemArrowProvider.refresh());
118
+ }
119
+ }
120
+ } else {
121
+ let activeIndex =
122
+ model.value == null ? -1 : renderData.itemValList.indexOf(model.value);
123
+ if (activeIndex == -1) {
124
+ activeIndex = 0;
125
+ }
126
+
127
+ let index =
128
+ ((): 1 | -1 => {
129
+ if (!props.vertical) {
130
+ return staticState.moveX > staticState.startX ? -1 : 1;
131
+ } else {
132
+ return staticState.moveY > staticState.startY ? -1 : 1;
133
+ }
134
+ })() + activeIndex;
135
+ if (index < 0) {
136
+ index = renderData.itemValList.length - 1;
137
+ }
138
+ if (index > renderData.itemValList.length - 1) {
139
+ index = 0;
140
+ }
141
+ draggierState.lot = renderData.itemsList.find((i) => i.index === index)!.startLot;
142
+ const newVal = renderData.itemValList[index];
143
+ if (newVal != model.value) {
144
+ model.value = newVal;
145
+ // delay(300).then(() => refreshItemArrowProvider.refresh());
146
+ }
71
147
  }
72
148
  });
73
149
  }
74
150
  }
75
- if (!draggierState.touching) {return;}
76
- /*实时设置滚动位置*/
77
- durX = Math.ceil(durX / 3);
78
- draggierState.left = -durX + staticState.startLeft;
151
+ if (!draggierState.touching) {
152
+ return;
153
+ }
154
+ if (!props.flick) {
155
+ /*实时设置滚动位置*/
156
+ durX = Math.ceil(durX / 3);
157
+ durY = Math.ceil(durY / 10);
158
+ draggierState.lot = !props.vertical
159
+ ? -durX + staticState.startLot
160
+ : -durY + staticState.startLot;
161
+ }
79
162
  };
80
163
 
81
164
  draggierEffects.push(addWindowListener('mousemove', touchmove));
@@ -99,7 +182,7 @@ export const StackCard = designComponent({
99
182
  if (activeIndex === -1) {return;}
100
183
  const newItem = renderData.itemsList.find(i => i.index === activeIndex);
101
184
  if (!!newItem) {
102
- draggier.draggierState.left = renderData.itemsList.find(i => i.index === activeIndex)!.startLeft;
185
+ draggier.draggierState.lot = renderData.itemsList.find(i => i.index === activeIndex)!.startLot;
103
186
  }
104
187
  },
105
188
  };
@@ -114,13 +197,13 @@ export const StackCard = designComponent({
114
197
 
115
198
  let renderData = {
116
199
  /*子节点信息,listLeft为子节点相对于o位置的偏移量*/
117
- itemsList: [] as { index: number, startLeft: number, endLeft: number }[],
200
+ itemsList: [] as iStackItemDataMeta[],
118
201
  /*子节点的val数组*/
119
202
  itemValList: [] as (string | number)[],
120
203
  /*子节点转换为循环列表的信息,distance为循环列表中元素距离选中元素的偏移量*/
121
- listData: [] as { index: number, startLeft: number, endLeft: number, distance: number }[],
204
+ listData: [] as (iStackItemDataMeta & { distance: number })[],
122
205
  /*最靠近选中元素的节点数据*/
123
- closestItem: {} as { index: number, startLeft: number, endLeft: number },
206
+ closestItem: {} as iStackItemDataMeta,
124
207
  };
125
208
 
126
209
  return () => {
@@ -131,104 +214,162 @@ export const StackCard = designComponent({
131
214
  const itemValList = items.map((i, index) => i.props?.val == null ? index : i.props?.val);
132
215
  const total = items.length;
133
216
 
134
- let leftBufferCount = props.leftBufferCount == null ? Math.ceil(total / 2) : props.leftBufferCount;
135
- let rightBufferCount = props.rightBufferCount == null ? Math.ceil(total / 2) : props.rightBufferCount;
217
+ let prevBufferCount = props.prevBufferCount == null ? Math.ceil(total / 2) : props.prevBufferCount;
218
+ let nextBufferCount = props.nextBufferCount == null ? Math.ceil(total / 2) : props.nextBufferCount;
136
219
 
137
220
  const elStyles = {} as CSSProperties;
138
- elStyles.paddingLeft = `${(leftBufferCount) * props.stackItemWidth}px`;
139
- elStyles.paddingRight = `${(rightBufferCount - 1) * props.stackItemWidth}px`;
140
- if (!!props.verticalOffset) {
141
- elStyles.paddingBottom = `${Math.max(leftBufferCount, rightBufferCount - 1) * props.stackItemHeight}px`;
221
+ if (!props.vertical) {
222
+ elStyles.paddingLeft = `${(prevBufferCount) * props.stackItemWidth}px`;
223
+ elStyles.paddingRight = `${(nextBufferCount - 1) * props.stackItemWidth}px`;
224
+ if (!!props.verticalOffset) {
225
+ elStyles.paddingBottom = `${Math.max(prevBufferCount, nextBufferCount - 1) * props.stackItemHeight}px`;
226
+ }
227
+ } else {
228
+ elStyles.paddingTop = `${(prevBufferCount) * props.stackItemHeight}px`;
229
+ elStyles.paddingBottom = `${(nextBufferCount - 1) * props.stackItemHeight}px`;
230
+ /*if (!!props.verticalOffset) {
231
+ elStyles.paddingBottom = `${Math.max(leftBufferCount, rightBufferCount - 1) * props.stackItemHeight}px`;
232
+ }*/
142
233
  }
143
234
 
144
235
  let itemStyles: CSSProperties[] = [];
236
+ const stackItemSize = !props.vertical ? props.stackItemWidth : props.stackItemHeight;
145
237
 
146
238
  /*实际中拖拽的left距离,与item的startLeft匹配,item的startLeft实际上是item的中心距离*/
147
- let pointLeft = draggier.draggierState.left;
239
+ let pointLot = draggier.draggierState.lot;
148
240
  /*拖拽的left距离向右偏移半个stackItemWidth得到offsetPointLeft, 通过offsetPointLeft在item的startLeft到endLeft之间的位置找到closetItem*/
149
- let offsetPointLeft = Math.floor(props.stackItemWidth / 2 + pointLeft);
241
+ let offsetPointLot = Math.floor(stackItemSize / 2 + pointLot);
150
242
  /*计算每个item的startLeft以及endLeft*/
151
- const itemsList: { index: number, startLeft: number, endLeft: number; }[] = itemValList.map((_, index) => ({ index, startLeft: index * props.stackItemWidth, endLeft: (index + 1) * props.stackItemWidth, }));
243
+ const itemsList: iStackItemDataMeta[] = itemValList.map((_, index) => ({ index, startLot: index * stackItemSize, endLot: (index + 1) * stackItemSize, }));
152
244
 
153
245
  /*总长度*/
154
- const maxEndLeft = itemsList[itemsList.length - 1]?.endLeft;
246
+ const maxEndLot = itemsList[itemsList.length - 1]?.endLot;
155
247
 
156
248
  /*修正left,超出maxListLeft或者小于0时,循环计算left使其落在0到maxListLeft的范围*/
157
- if (!!itemsList.length && !!maxEndLeft) {
158
- while (offsetPointLeft > maxEndLeft) {
159
- offsetPointLeft -= maxEndLeft;
160
- pointLeft -= maxEndLeft;
249
+ if (!!itemsList.length && !!maxEndLot) {
250
+ while (offsetPointLot > maxEndLot) {
251
+ offsetPointLot -= maxEndLot;
252
+ pointLot -= maxEndLot;
161
253
  }
162
- while (offsetPointLeft < 0) {
163
- offsetPointLeft += maxEndLeft;
164
- pointLeft += maxEndLeft;
254
+ while (offsetPointLot < 0) {
255
+ offsetPointLot += maxEndLot;
256
+ pointLot += maxEndLot;
165
257
  }
166
258
  }
167
259
 
168
260
  /*找到最靠近的位置*/
169
261
  const closestItem = itemsList.reduce((prev, item) => {
170
- if (item.startLeft <= offsetPointLeft && item.endLeft >= offsetPointLeft) {
171
- return { distance: Math.abs(item.startLeft - pointLeft), item };
262
+ if (item.startLot <= offsetPointLot && item.endLot >= offsetPointLot) {
263
+ return { distance: Math.abs(item.startLot - pointLot), item };
172
264
  } else {
173
265
  return prev;
174
266
  }
175
- }, { distance: Infinity, item: null } as { distance: number, item: { index: number, startLeft: number, endLeft: number } | null }).item!;
267
+ }, { distance: Infinity, item: null } as { distance: number, item: iStackItemDataMeta | null }).item!;
176
268
 
177
269
  /*循环列表前半部分*/
178
- const leftItemsList = itemsList.slice(0, closestItem.index);
270
+ const prevItemsList = itemsList.slice(0, closestItem.index);
179
271
  /*循环列表后半部分*/
180
- const rightItemsList = itemsList.slice(closestItem.index);
272
+ const nextItemsList = itemsList.slice(closestItem.index);
181
273
 
182
274
  /*根据左侧右侧预留的空位填补前后列表*/
183
- while (leftItemsList.length - rightItemsList.length > 1) {rightItemsList.push(leftItemsList.shift()!);}
184
- while (rightItemsList.length - leftItemsList.length > 1) {leftItemsList.unshift(rightItemsList.pop()!);}
185
- while (leftItemsList.length > leftBufferCount) {
186
- const shiftItem = leftItemsList.shift()!;
187
- if (rightItemsList.length < rightBufferCount) {
188
- rightItemsList.push(shiftItem);
275
+ while (prevItemsList.length - nextItemsList.length > 1) {nextItemsList.push(prevItemsList.shift()!);}
276
+ while (nextItemsList.length - prevItemsList.length > 1) {prevItemsList.unshift(nextItemsList.pop()!);}
277
+ while (prevItemsList.length > prevBufferCount) {
278
+ const shiftItem = prevItemsList.shift()!;
279
+ if (nextItemsList.length < nextBufferCount) {
280
+ nextItemsList.push(shiftItem);
189
281
  }
190
282
  }
191
- while (rightItemsList.length > rightBufferCount) {
192
- const popItem = rightItemsList.pop()!;
193
- if (leftItemsList.length < leftBufferCount) {
194
- leftItemsList.unshift(popItem);
283
+ while (nextItemsList.length > nextBufferCount) {
284
+ const popItem = nextItemsList.pop()!;
285
+ if (prevItemsList.length < prevBufferCount) {
286
+ prevItemsList.unshift(popItem);
195
287
  }
196
288
  }
197
289
 
198
290
  /*此时后半部分的第一个元素就是选中的元素,索引就是前半部分列表的最后一个位置+1*/
199
- const activeIndex = leftItemsList.length;
291
+ const activeIndex = prevItemsList.length;
200
292
  /*根据最靠近left的节点来计算当前的少量偏移*/
201
- const offsetLeft = closestItem.startLeft - pointLeft;
293
+ const offsetLot = closestItem.startLot - pointLot;
202
294
  /*计算循环列表中每个节点距离选中节点的偏移距离*/
203
- const list = [...leftItemsList, ...rightItemsList].map((item, index) => ({
295
+ const list = [...prevItemsList, ...nextItemsList].map((item, index) => ({
204
296
  ...item,
205
- distance: (index - activeIndex) * props.stackItemWidth,
297
+ distance: (index - activeIndex) * stackItemSize,
206
298
  zIndex: 0,
207
299
  }));
208
300
  /*先排序,然后根据顺序设置zIndex,最靠近left的节点zIndex最大*/
209
301
  list.sort((a, b) => Math.abs(a.distance) - Math.abs(b.distance)).forEach((i, index) => {
210
302
  i.zIndex = total - index;
211
303
  });
304
+
305
+ const isPrevOfClosetItem = (index: number) => {
306
+ index = index + 1;
307
+ if (index >= total) {index = 0;}
308
+ return index === closestItem.index;
309
+ };
310
+ const isNextOfClosetItem = (index: number) => {
311
+ index = index - 1;
312
+ if (index < 0) {index = total - 1;}
313
+ return index === closestItem.index;
314
+ };
315
+
212
316
  /*计算子节点样式*/
213
- itemStyles = itemsList.map((_, index) => {
317
+ itemStyles = itemsList.map((_, index): CSSProperties => {
214
318
  const item = list.find(i => i.index === index);
215
319
  if (!item) {
216
- /*不在前部分列表后部分列表的元素,可能是因为预留位置不足,这里不做显示*/
217
- return {
218
- opacity: 0,
219
- transition: 'none'
220
- };
320
+ const isPrevHidden = isPrevOfClosetItem(_.index);
321
+ const isNextHidden = !isPrevHidden && isNextOfClosetItem(_.index);
322
+
323
+ if (isPrevHidden) {
324
+ /*下一个就是closetItem,但是当前item隐藏,提前缩放以及进行位置偏移*/
325
+ return {
326
+ opacity: 0,
327
+ zIndex: total + 2,
328
+ pointerEvents: 'none',
329
+ transformOrigin: !props.vertical ? 'left' + (' ' + props.verticalAlign) : 'top',
330
+ transform: !props.vertical ?
331
+ `translate3d(${Math.ceil(-stackItemSize * 0.5)}px,0,0) scale(${1 - props.scaleRate / 2})` :
332
+ `translate3d(0,${Math.ceil(-stackItemSize * 0.5)}px,0) scale(${1 - props.scaleRate / 2})`
333
+ };
334
+ } else if (isNextHidden) {
335
+ /*上一个就是closetItem,但是当前item隐藏,提前缩放以及进行位置偏移*/
336
+ return {
337
+ opacity: 0,
338
+ zIndex: total + 2,
339
+ pointerEvents: 'none',
340
+ transformOrigin: !props.vertical ? 'right' + (' ' + props.verticalAlign) : 'bottom',
341
+ transform: !props.vertical ?
342
+ `translate3d(${Math.ceil(stackItemSize * 0.5)}px,0,0) scale(${1 - props.scaleRate / 2})` :
343
+ `translate3d(0,${Math.ceil(stackItemSize * 0.5)}px,0) scale(${1 - props.scaleRate / 2})`
344
+ };
345
+ } else {
346
+ /*不在前部分列表后部分列表的元素,可能是因为预留位置不足,这里不做显示*/
347
+ return {
348
+ opacity: 0,
349
+ transition: 'none'
350
+ };
351
+ }
221
352
  }
222
353
  /*元素的偏移距离*/
223
- const left = item.distance + offsetLeft;
354
+ const lot = item.distance + offsetLot;
224
355
  /*根据偏移距离实时计算缩放大小,越靠近left,越接近1*/
225
- const scale = Math.max(0, 1 - Number((Math.abs(left) / props.stackItemWidth * props.scaleRate).toFixed(2)));
226
- return {
227
- transform: `translate3d(${left}px,${props.verticalOffset ? `${left / props.stackItemWidth * props.stackItemHeight}px` : 0},0) scale(${scale})`,
228
- transformOrigin: `${left > 0 ? 'right' : 'left'} ${props.verticalAlign}`,
229
- zIndex: item.zIndex,
230
- // opacity: total - item.zIndex === 0 ? 1 : 0.75,
231
- };
356
+ const scale = Math.max(0, 1 - Number((Math.abs(lot) / stackItemSize * props.scaleRate).toFixed(2)));
357
+
358
+ if (!props.vertical) {
359
+ return {
360
+ transform: `translate3d(${lot}px,${props.verticalOffset ? `${lot / props.stackItemWidth * props.stackItemHeight}px` : 0},0) scale(${scale})`,
361
+ transformOrigin: `${lot > 0 ? 'right' : 'left'} ${props.verticalAlign}`,
362
+ zIndex: item.zIndex,
363
+ // opacity: total - item.zIndex === 0 ? 1 : 0.75,
364
+ };
365
+ } else {
366
+ return {
367
+ transform: `translate3d(0,${lot}px,0) scale(${scale})`,
368
+ transformOrigin: `${lot > 0 ? 'bottom' : 'top'}`,
369
+ zIndex: item.zIndex,
370
+ // opacity: total - item.zIndex === 0 ? 1 : 0.75,
371
+ };
372
+ }
232
373
  });
233
374
 
234
375
  renderData = {
@@ -246,6 +387,15 @@ export const StackCard = designComponent({
246
387
  return (
247
388
  <ItemComp
248
389
  {...mergeAttrs({ style: itemStyles[index] || {} }, Item.props)}
390
+ destroyContent={(() => {
391
+ if (!props.demandRender) {return false;}
392
+ if (!props.vertical) {
393
+ if (index === 0) {return false;}
394
+ }
395
+ if (isPrevOfClosetItem(index)) {return false;}
396
+ if (isNextOfClosetItem(index)) {return false;}
397
+ return !list.find(i => i.index === index);
398
+ })()}
249
399
  key={index}
250
400
  />
251
401
  );
@@ -258,3 +408,9 @@ export const StackCard = designComponent({
258
408
  });
259
409
 
260
410
  export default StackCard;
411
+
412
+ interface iStackItemDataMeta {
413
+ index: number,
414
+ startLot: number,
415
+ endLot: number
416
+ }
@@ -2,6 +2,18 @@
2
2
  display: block;
3
3
  box-sizing: border-box;
4
4
 
5
+ &.stack-card-direction-vertical {
6
+ height: 100%;
7
+
8
+ .stack-card-container {
9
+ height: 100%
10
+ }
11
+
12
+ @include comp(stack-card-item) {
13
+ height: 100%
14
+ }
15
+ }
16
+
5
17
  .stack-card-container {
6
18
  position: relative;
7
19
  @include comp(stack-card-item) {
@@ -4,6 +4,7 @@ export const StackCardItem = designComponent({
4
4
  name: 'stack-card-item',
5
5
  props: {
6
6
  val: { type: [String, Number] },
7
+ destroyContent: { type: Boolean }
7
8
  },
8
9
  slots: ['default'],
9
10
  setup({ props, slots, event: { emit } }) {
@@ -14,7 +15,7 @@ export const StackCardItem = designComponent({
14
15
 
15
16
  return () => (
16
17
  <div className={classes.value}>
17
- {slots.default()}
18
+ {!props.destroyContent && slots.default()}
18
19
  </div>
19
20
  );
20
21
  },
@@ -111,7 +111,7 @@
111
111
  font-size: plv(notice-content-font-size);
112
112
  padding-top: 16px;
113
113
  color: plv(text-2);
114
- line-height: 1.5715;
114
+ line-height: plv(line-height);
115
115
  }
116
116
 
117
117
  .notice-foot {