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

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": "plain-design",
3
- "version": "1.0.0-beta.37",
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
  },