1+ /*---------------------------------------------------------------------------------------------
2+ * Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+ * This file is a part of the ModelEngine Project.
4+ * Licensed under the MIT License. See License.txt in the project root for license information.
5+ *--------------------------------------------------------------------------------------------*/
6+
7+ import { Button , Col , Collapse , Form , Popover , Row } from 'antd' ;
8+ import { useFormContext , useShapeContext } from '@/components/DefaultRoot.jsx' ;
9+ import PropTypes from 'prop-types' ;
10+ import { Trans , useTranslation } from 'react-i18next' ;
11+ import React , { useState } from 'react' ;
12+ import FullScreenIcon from '../asserts/icon-full-screen.svg?react' ;
13+ import { JadeCollapse } from '@/components/common/JadeCollapse.jsx' ;
14+ import { PromptDrawer } from "@/components/common/prompt/PromptDrawer.jsx" ;
15+ import TextArea from "antd/es/input/TextArea.js" ;
16+ import { QuestionCircleOutlined } from "@ant-design/icons" ;
17+ import * as Proptypes from "prop-types" ;
18+
19+ const { Panel} = Collapse ;
20+
21+ /**
22+ * 文本模板组件。
23+ *
24+ * @param name 表单名称
25+ * @param title 标题文本
26+ * @param placeHolder 输入框占位符文本
27+ * @param template 文字模板对象
28+ * @param labelName 标签名称
29+ * @param onChange 内容变化时的回调函数
30+ * @param disabled 是否禁用输入框
31+ * @param maxLength 输入内容的最大长度限制
32+ * @returns {Element } 返回文本模板组件的JSX元素
33+ * @constructor
34+ */
35+ const _TemplatePanel = ( { name, title, placeHolder, template, labelName, onChange, disabled, maxLength} ) => {
36+ const shape = useShapeContext ( ) ;
37+ const { t} = useTranslation ( ) ;
38+ const form = useFormContext ( ) ;
39+
40+ const [ promptOpen , setPromptOpen ] = useState ( false ) ;
41+
42+ const promptContent = ( < div className = { 'jade-font-size' } style = { { lineHeight : '1.2' } } >
43+ < Trans i18nKey = 'promptPopover' components = { { p : < p /> } } />
44+ </ div > ) ;
45+
46+ const _onChange = ( templateText ) => {
47+ onChange ( templateText ) ;
48+ form . setFieldsValue ( { [ name ] : templateText } ) ;
49+ } ;
50+
51+ /**
52+ * 失焦时才设置值,对于必填项.若为空,则不设置
53+ *
54+ * @param e event事件
55+ */
56+ const changeOnBlur = ( e ) => {
57+ if ( template . value !== e . target . value ) {
58+ _onChange ( e . target . value ) ;
59+ }
60+ } ;
61+
62+ return ( < JadeCollapse defaultActiveKey = { [ 'templatePanel' ] } >
63+ < Panel
64+ key = "templatePanel"
65+ header = { < >
66+ < div className = { 'required-after' } style = { { display : 'flex' , alignItems : 'center' , width : '100%' } } >
67+ < span className = 'jade-second-title' > { title } </ span >
68+ { promptContent && < Popover
69+ content = { [ promptContent ] }
70+ align = { { offset : [ 0 , 3 ] } }
71+ overlayClassName = { 'jade-custom-popover' }
72+ >
73+ < QuestionCircleOutlined className = 'jade-panel-header-popover-content' />
74+ </ Popover > }
75+ < div className = { 'prompt-title-buttons' } >
76+ < Button
77+ disabled = { disabled }
78+ type = 'text'
79+ className = 'icon-button'
80+ style = { { height : '100%' } }
81+ onClick = { ( ) => setPromptOpen ( true ) } >
82+ < FullScreenIcon />
83+ </ Button >
84+ </ div >
85+ </ div >
86+ </ > }
87+ className = "jade-panel"
88+ >
89+ < div className = "jade-custom-panel-content" >
90+ < Row gutter = { 16 } >
91+ < Col span = { 24 } >
92+ < div className = { 'prompt-container' } >
93+ < Form . Item
94+ className = 'jade-form-item'
95+ name = { name }
96+ rules = { [ { required : true , message : t ( 'paramCannotBeEmpty' ) } ] }
97+ initialValue = { template . value }
98+ validateTrigger = 'onBlur'
99+ >
100+ < TextArea
101+ disabled = { disabled }
102+ maxLength = { 2000 }
103+ className = 'jade-textarea-input jade-font-size'
104+ onBlur = { ( e ) => changeOnBlur ( e ) }
105+ placeholder = { placeHolder }
106+ />
107+ </ Form . Item >
108+ < PromptDrawer
109+ value = { template . value }
110+ name = { name }
111+ title = { title }
112+ rules = { [ { required : true , message : t ( 'paramCannotBeEmpty' ) } ] }
113+ placeHolder = { placeHolder }
114+ container = { shape . page . graph . div . parentElement }
115+ open = { promptOpen }
116+ onClose = { ( ) => setPromptOpen ( false ) }
117+ onConfirm = { ( v ) => _onChange ( v ) }
118+ labelName = { labelName }
119+ maxLength = { maxLength }
120+ />
121+ </ div >
122+ </ Col >
123+ </ Row >
124+ </ div >
125+ </ Panel >
126+ </ JadeCollapse > ) ;
127+ } ;
128+
129+ _TemplatePanel . propTypes = {
130+ name : PropTypes . string . isRequired ,
131+ title : PropTypes . string . isRequired ,
132+ placeHolder : PropTypes . string . isRequired ,
133+ template : PropTypes . object . isRequired ,
134+ labelName : PropTypes . string . isRequired ,
135+ onChange : Proptypes . func . isRequired ,
136+ disabled : PropTypes . bool ,
137+ maxLength : PropTypes . number ,
138+ } ;
139+
140+ const areEqual = ( prevProps , nextProps ) => {
141+ return prevProps . template === nextProps . template ;
142+ } ;
143+
144+ export const TemplatePanel = React . memo ( _TemplatePanel , areEqual ) ;
0 commit comments