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/dist/plain-design.commonjs.min.js +1 -1
- package/dist/plain-design.min.css +7 -7
- package/dist/plain-design.min.js +1 -1
- package/dist/report.html +2 -2
- package/package.json +1 -1
- package/src/packages/components/Alert/alert.scss +2 -2
- package/src/packages/components/Application/theme/theme.ts +1 -0
- package/src/packages/components/AutoTable/filter/useTableOption.filter.form.tsx +1 -0
- package/src/packages/components/Button/button.scss +1 -1
- package/src/packages/components/Card/card.scss +1 -1
- package/src/packages/components/FilterFormMultiple/index.tsx +31 -10
- package/src/packages/components/Input/index.scss +2 -2
- package/src/packages/components/InputNumber/number.scss +10 -1
- package/src/packages/components/StackCard/index.tsx +236 -80
- package/src/packages/components/StackCard/stack-card.scss +12 -0
- package/src/packages/components/StackCardItem/index.tsx +2 -1
- package/src/packages/components/useNotice/notice.scss +1 -1
package/package.json
CHANGED
@@ -7,12 +7,12 @@
|
|
7
7
|
|
8
8
|
.alert-label {
|
9
9
|
font-size: plv(font-size-small);
|
10
|
-
line-height:
|
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:
|
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}/>
|
@@ -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
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
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:
|
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:
|
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
|
-
|
14
|
-
|
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
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
50
|
-
|
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
|
-
|
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
|
-
|
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 (
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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) {
|
76
|
-
|
77
|
-
|
78
|
-
|
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.
|
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
|
200
|
+
itemsList: [] as iStackItemDataMeta[],
|
118
201
|
/*子节点的val数组*/
|
119
202
|
itemValList: [] as (string | number)[],
|
120
203
|
/*子节点转换为循环列表的信息,distance为循环列表中元素距离选中元素的偏移量*/
|
121
|
-
listData: [] as
|
204
|
+
listData: [] as (iStackItemDataMeta & { distance: number })[],
|
122
205
|
/*最靠近选中元素的节点数据*/
|
123
|
-
closestItem: {} as
|
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
|
135
|
-
let
|
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
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
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
|
239
|
+
let pointLot = draggier.draggierState.lot;
|
148
240
|
/*拖拽的left距离向右偏移半个stackItemWidth得到offsetPointLeft, 通过offsetPointLeft在item的startLeft到endLeft之间的位置找到closetItem*/
|
149
|
-
let
|
241
|
+
let offsetPointLot = Math.floor(stackItemSize / 2 + pointLot);
|
150
242
|
/*计算每个item的startLeft以及endLeft*/
|
151
|
-
const itemsList:
|
243
|
+
const itemsList: iStackItemDataMeta[] = itemValList.map((_, index) => ({ index, startLot: index * stackItemSize, endLot: (index + 1) * stackItemSize, }));
|
152
244
|
|
153
245
|
/*总长度*/
|
154
|
-
const
|
246
|
+
const maxEndLot = itemsList[itemsList.length - 1]?.endLot;
|
155
247
|
|
156
248
|
/*修正left,超出maxListLeft或者小于0时,循环计算left使其落在0到maxListLeft的范围*/
|
157
|
-
if (!!itemsList.length && !!
|
158
|
-
while (
|
159
|
-
|
160
|
-
|
249
|
+
if (!!itemsList.length && !!maxEndLot) {
|
250
|
+
while (offsetPointLot > maxEndLot) {
|
251
|
+
offsetPointLot -= maxEndLot;
|
252
|
+
pointLot -= maxEndLot;
|
161
253
|
}
|
162
|
-
while (
|
163
|
-
|
164
|
-
|
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.
|
171
|
-
return { distance: Math.abs(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:
|
267
|
+
}, { distance: Infinity, item: null } as { distance: number, item: iStackItemDataMeta | null }).item!;
|
176
268
|
|
177
269
|
/*循环列表前半部分*/
|
178
|
-
const
|
270
|
+
const prevItemsList = itemsList.slice(0, closestItem.index);
|
179
271
|
/*循环列表后半部分*/
|
180
|
-
const
|
272
|
+
const nextItemsList = itemsList.slice(closestItem.index);
|
181
273
|
|
182
274
|
/*根据左侧右侧预留的空位填补前后列表*/
|
183
|
-
while (
|
184
|
-
while (
|
185
|
-
while (
|
186
|
-
const shiftItem =
|
187
|
-
if (
|
188
|
-
|
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 (
|
192
|
-
const popItem =
|
193
|
-
if (
|
194
|
-
|
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 =
|
291
|
+
const activeIndex = prevItemsList.length;
|
200
292
|
/*根据最靠近left的节点来计算当前的少量偏移*/
|
201
|
-
const
|
293
|
+
const offsetLot = closestItem.startLot - pointLot;
|
202
294
|
/*计算循环列表中每个节点距离选中节点的偏移距离*/
|
203
|
-
const list = [...
|
295
|
+
const list = [...prevItemsList, ...nextItemsList].map((item, index) => ({
|
204
296
|
...item,
|
205
|
-
distance: (index - activeIndex) *
|
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
|
-
|
218
|
-
|
219
|
-
|
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
|
354
|
+
const lot = item.distance + offsetLot;
|
224
355
|
/*根据偏移距离实时计算缩放大小,越靠近left,越接近1*/
|
225
|
-
const scale = Math.max(0, 1 - Number((Math.abs(
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
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
|
},
|