Skip to content

Commit 76150cb

Browse files
Create MetaListItem.vue
1 parent 57424d5 commit 76150cb

1 file changed

Lines changed: 268 additions & 0 deletions

File tree

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
<template>
2+
<div
3+
:class="['item-content', { 'active-item': currentIndex === index }]"
4+
:key="item.itemId"
5+
>
6+
<div class="option-input">
7+
<div class="left">
8+
<slot name="content" :data="item"></slot>
9+
</div>
10+
<div class="right">
11+
<slot name="operate" :data="item">
12+
<template v-if="enabledOperation">
13+
<template v-for="item in dataScource.btnList" :key="item.type">
14+
<template v-if="item.type === 'edit'">
15+
<tiny-popover
16+
:key="itemData.index"
17+
v-model="itemData.option.isVisible"
18+
placement="bottom-start"
19+
:popper-class="['option-popper', { 'fixed-left': expand }]"
20+
:visible-arrow="!expand"
21+
title=""
22+
width="295"
23+
height="auto"
24+
trigger="manual"
25+
@hide="hide(item)"
26+
>
27+
<template v-if="itemData.option.isVisible">
28+
<div
29+
ref="addOptions"
30+
class="add-options"
31+
:style="`left:${itemData.left}px;top:${itemData.top}px`"
32+
>
33+
<icon-close
34+
class="tiny-svg-size icon-close"
35+
@click="closeEditOption"
36+
></icon-close>
37+
<slot name="metaForm">
38+
<meta-form
39+
v-bind="itemData"
40+
footerbtnHide="true"
41+
@changeItem="change"
42+
@cancel="cancel"
43+
@confirm="formConfirm"
44+
></meta-form>
45+
</slot>
46+
<slot name="footer"></slot></div
47+
></template>
48+
<template #reference>
49+
<span title="编辑">
50+
<component
51+
:is="item.icon"
52+
class="tiny-svg-size icon-edit"
53+
@click="btnClick($event, item.type)"
54+
></component>
55+
</span>
56+
</template>
57+
</tiny-popover>
58+
</template>
59+
</template>
60+
</template>
61+
<span title="拖拽">
62+
<icon-more class="tiny-svg-size icon-more"></icon-more>
63+
</span>
64+
</slot>
65+
</div>
66+
</div>
67+
</div>
68+
<!-- 遮罩层 -->
69+
<mask-modal :visible="showMask && !expand" @close="closeMask"></mask-modal>
70+
</template>
71+
72+
<script>
73+
import { reactive, watchEffect, ref } from "vue";
74+
import { Tooltip, Input, FormItem, Form, Popover, Button } from "@opentiny/vue";
75+
import { iconMore, iconClose } from "@opentiny/vue-icon";
76+
import { MaskModal, MetaForm } from "@opentiny/tiny-engine-common";
77+
78+
export default {
79+
components: {
80+
TinyTooltip: Tooltip,
81+
TinyInput: Input,
82+
TinyFormItem: FormItem,
83+
TinyForm: Form,
84+
TinyPopover: Popover,
85+
TinyButton: Button,
86+
MetaForm,
87+
MaskModal,
88+
IconClose: iconClose(),
89+
IconMore: iconMore(),
90+
},
91+
inheritAttrs: false,
92+
props: {
93+
item: {
94+
type: Object,
95+
default: () => {},
96+
},
97+
dataScource: {
98+
type: Object,
99+
default: () => {},
100+
},
101+
index: {
102+
type: Number,
103+
default: 0,
104+
},
105+
currentIndex: {
106+
type: Number,
107+
default: -1,
108+
},
109+
enabledOperation: {
110+
type: Boolean,
111+
default: true,
112+
},
113+
// 子级弹出层是否在左侧展开
114+
expand: {
115+
type: Boolean,
116+
default: false,
117+
},
118+
},
119+
emits: ["editItem", "changeItem"],
120+
setup(props, { emit }) {
121+
const itemData = reactive({});
122+
const showMask = ref(false);
123+
let top = ref(0);
124+
125+
const editList = () => {
126+
showMask.value = true;
127+
itemData.option.isVisible = true;
128+
};
129+
130+
const btnClick = ($event, action) => {
131+
switch (action) {
132+
case "edit":
133+
emit("editItem", { action: "edit", index: props.index });
134+
editList();
135+
break;
136+
default:
137+
emit("editItem", { index: props.index });
138+
editList();
139+
break;
140+
}
141+
};
142+
143+
const change = () => {
144+
emit("changeItem", itemData);
145+
};
146+
147+
const closeEditOption = () => {
148+
emit("closeItem");
149+
itemData.option.isVisible = false;
150+
showMask.value = false;
151+
};
152+
153+
const hide = () => {
154+
emit("hide");
155+
};
156+
157+
const isShowModal = ref(false);
158+
159+
const cancel = () => {
160+
itemData.option.isVisible = false;
161+
};
162+
163+
const formConfirm = (formData) => {
164+
emit("changeItem", { data: formData, index: props.index });
165+
itemData.option.isVisible = false;
166+
};
167+
168+
watchEffect(() => {
169+
itemData.option = props.item;
170+
itemData.textField = props.dataScource.textField;
171+
itemData.valueField = props.dataScource.valueField;
172+
itemData.label = props.dataScource.label;
173+
itemData.index = props.index;
174+
if (props.currentIndex !== props.index) {
175+
cancel();
176+
}
177+
});
178+
const closeMask = () => {
179+
showMask.value = false;
180+
itemData.option.isVisible = false;
181+
};
182+
183+
return {
184+
itemData,
185+
change,
186+
closeEditOption,
187+
btnClick,
188+
editList,
189+
hide,
190+
showMask,
191+
closeMask,
192+
top,
193+
isShowModal,
194+
formConfirm,
195+
cancel,
196+
};
197+
},
198+
};
199+
</script>
200+
201+
<style lang="less" scoped>
202+
.item-content {
203+
border-bottom: 1px solid var(--te-component-common-border-color-divider);
204+
background: var(--te-component-common-bg-color);
205+
margin-bottom: -1px;
206+
color: var(--te-component-common-text-color-primary);
207+
&.active-item {
208+
background-color: var(--te-component-meta-list-item-bg-color);
209+
}
210+
.option-input {
211+
display: flex;
212+
height: 28px;
213+
align-items: center;
214+
padding: 0 10px;
215+
& > div {
216+
overflow: hidden;
217+
.tiny-svg {
218+
margin-right: 5px;
219+
font-size: 12px;
220+
opacity: 0.4;
221+
margin-bottom: 2px;
222+
color: var(--te-component-common-text-color-primary);
223+
&:hover {
224+
cursor: pointer;
225+
opacity: 1;
226+
}
227+
}
228+
229+
&.left {
230+
flex: 1;
231+
display: flex;
232+
align-items: center;
233+
:deep(span) {
234+
white-space: nowrap;
235+
overflow: hidden;
236+
text-overflow: ellipsis;
237+
}
238+
}
239+
&.right {
240+
float: left;
241+
text-align: right;
242+
margin-right: 2px;
243+
.icon-more {
244+
font-size: 14px;
245+
flex-shrink: 0;
246+
cursor: move;
247+
}
248+
}
249+
}
250+
}
251+
}
252+
253+
.tiny-popover {
254+
position: relative;
255+
.icon-close {
256+
position: absolute;
257+
top: 6px;
258+
right: 10px;
259+
}
260+
}
261+
.add-options {
262+
overflow-y: auto;
263+
max-height: calc(100vh - 94px); // 94为头部高度和底部高度
264+
&.top {
265+
margin-bottom: 0;
266+
}
267+
}
268+
</style>

0 commit comments

Comments
 (0)