11<template >
22 <tiny-form label-position =" left" label-width =" 60px" show-message :model =" formData" :rules =" rules" >
33 <tiny-form-item label =" 事件名" prop =" eventName" >
4- <tiny-input v-model =" formData.eventName" :placeholder =" eventNameTip" @blur =" changeEventName" ></tiny-input >
4+ <tiny-input class =" event-name" v-model =" formData.eventName" :placeholder =" eventNameTip" @blur =" changeEventName" >
5+ <template #suffix >
6+ <tiny-popover placement =" bottom-end" trigger =" hover" :close-delay =" 0" @show =" state.showPopover = true" >
7+ <template #reference >
8+ <tiny-icon-rich-text-link :class =" { 'bind-propertys': isUpdateEvent }" />
9+ </template >
10+ <div class =" property-list" v-show =" state.showPopover" >
11+ <div class =" property-list-title" >
12+ <tiny-icon-rich-text-link />
13+ 双向绑定属性
14+ </div >
15+ <ul class =" property-list-content" >
16+ <li
17+ v-for =" (item, index) in propertys"
18+ :key =" index"
19+ :class =" { existed: eventNameList.has(`onUpdate:${item.property}`) }"
20+ @click =" usePropertysToBeEvent(item)"
21+ >
22+ <div >{{ item.property }}</div >
23+ </li >
24+ </ul >
25+ </div >
26+ </tiny-popover >
27+ </template >
28+ </tiny-input >
529 </tiny-form-item >
630 <tiny-form-item label =" 标签名" >
731 <tiny-input v-model =" label" ></tiny-input >
1640<script lang="ts">
1741/* metaService: engine.plugins.blockmanage.BlockEventForm */
1842import { computed , reactive , watch } from ' vue'
19- import { Input as TinyInput , Form as TinyForm , FormItem as TinyFormItem } from ' @opentiny/vue'
43+ import { Input as TinyInput , Form as TinyForm , FormItem as TinyFormItem , TinyPopover } from ' @opentiny/vue'
2044import { REGEXP_EVENT_NAME , verifyEventName } from ' @opentiny/tiny-engine-common/js/verification'
21- import { getEditEvent , getEditEventName , renameBlockEventName } from ' ./js/blockSetting'
45+ import {
46+ getEditBlockPropertyList ,
47+ getEditBlockEvents ,
48+ getEditEvent ,
49+ getEditEventName ,
50+ renameBlockEventName
51+ } from ' ./js/blockSetting'
52+ import { IconRichTextLink } from ' @opentiny/vue-icon'
2253
2354export default {
2455 components: {
2556 TinyForm ,
2657 TinyInput ,
27- TinyFormItem
58+ TinyFormItem ,
59+ TinyPopover ,
60+ TinyIconRichTextLink: IconRichTextLink ()
2861 },
2962 setup() {
30- const eventNameTip = ' 事件名为小写字符开头的驼峰形式,例:customEvent'
63+ const propertys = computed (() => getEditBlockPropertyList ())
64+ const events = computed (() => getEditBlockEvents ())
65+ const state = reactive ({
66+ showPopover: false
67+ })
68+ const eventNameTip = ' 事件名为小写字符或onUpdate:开头的驼峰形式,例:customEvent, onUpdate:propsName'
3169 const linked = computed (() => (getEditEvent () || {}).linked )
70+ const eventNameList = computed (() => new Set (Object .keys (events .value )))
3271
3372 const label = computed ({
3473 get : () => getEditEvent ()?.label ?.zh_CN || ' ' ,
@@ -56,8 +95,35 @@ export default {
5695 eventName: getEditEventName () || ' '
5796 })
5897
98+ const isUpdateEvent = computed (() => formData .eventName .startsWith (' onUpdate:' ))
99+
100+ const usePropertysToBeEvent = (item : any ) => {
101+ if (item .label ?.text ?.zh_CN ) label .value = item .label .text .zh_CN
102+ renameBlockEventName (` onUpdate:${item .property } ` , getEditEventName ())
103+ state .showPopover = false
104+ }
105+
59106 const rules = {
60- eventName: [{ pattern: REGEXP_EVENT_NAME , message: eventNameTip , trigger: ' change' }]
107+ eventName: [
108+ {
109+ pattern: REGEXP_EVENT_NAME ,
110+ validator : (rule : any /* IFormInnerRule */ , value : string , callback : (e ? : Error ) => void ) => {
111+ if (isUpdateEvent .value ) {
112+ const matched = / ^ onUpdate:[a-zA-Z _$][\w $] * $ / .test (value )
113+ const propertyMatched = propertys .value .some ((item ) => item .property === value .replace (' onUpdate:' , ' ' ))
114+ return matched && propertyMatched
115+ ? callback ()
116+ : callback (new Error (` ${value } 需要有对应的 ${value .replace (' onUpdate:' , ' ' )} 在属性中定义 ` ))
117+ }
118+ if (! rule .pattern .test (value )) {
119+ callback (new Error (eventNameTip ))
120+ } else {
121+ callback ()
122+ }
123+ },
124+ trigger: ' change'
125+ }
126+ ]
61127 }
62128
63129 watch (
@@ -74,13 +140,19 @@ export default {
74140 }
75141
76142 return {
143+ state ,
144+ propertys ,
145+ events ,
77146 rules ,
78147 label ,
79148 linked ,
80149 formData ,
81150 description ,
82151 eventNameTip ,
83- changeEventName
152+ eventNameList ,
153+ isUpdateEvent ,
154+ changeEventName ,
155+ usePropertysToBeEvent
84156 }
85157 }
86158}
@@ -92,4 +164,47 @@ export default {
92164 padding : 15px 0px ;
93165 border-top : 1px solid var (--te-block-event-link-border-color );
94166}
167+
168+ .event-name {
169+ :deep(.tiny-input__inner.tiny-input__inner ) {
170+ padding-right : var (--tv-Input-suffix-padding-right );
171+ padding-left : var (--tv-Input-suffix-padding-left );
172+ }
173+ .bind-propertys {
174+ fill : var (--te-component-common-block-add-text-color );
175+ }
176+ }
177+
178+ .property-list {
179+ .property-list-title {
180+ display : flex ;
181+ align-items : center ;
182+ font-weight : bold ;
183+ text-align : left ;
184+ gap : 6px ;
185+ margin-bottom : 6px ;
186+ }
187+ .property-list-content {
188+ max-height : 200px ;
189+ overflow-y : scroll ;
190+ overflow-x : hidden ;
191+ padding-inline-start : 10px ;
192+ padding-inline-end : 10px ;
193+ }
194+ li {
195+ padding : 0 12px ;
196+ margin : 0 -16px ;
197+ line-height : 24px ;
198+ cursor : pointer ;
199+ & :hover {
200+ background : var (--te-component-common-bg-color-hover );
201+ }
202+ }
203+
204+ .existed {
205+ cursor : not-allowed ;
206+ pointer-events : none ;
207+ color : var (--te-component-common-text-color-disabled );
208+ }
209+ }
95210 </style >
0 commit comments