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/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/Table/table/body/useCellValue.tsx +10 -6
- 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
|
},
|