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 { useDispatch , useFormContext } from '@/components/DefaultRoot.jsx' ;
8+ import { useTranslation } from 'react-i18next' ;
9+ import PropTypes from 'prop-types' ;
10+ import React from 'react' ;
11+ import { Collapse , Form , Image } from 'antd' ;
12+ import { EyeOutlined } from '@ant-design/icons' ;
13+
14+ const { Panel} = Collapse ;
15+
16+ /**
17+ * 开始节点应用配置表单。
18+ *
19+ * @param item 应用配置结构体。
20+ * @param disabled 是否禁用。
21+ * @param configs 开始节点相关配置。
22+ * @returns {JSX.Element } 开始节点应用配置表单的DOM。
23+ */
24+ const _AppConfiguration = ( { item, disabled, configs} ) => {
25+ const dispatch = useDispatch ( ) ;
26+ const form = useFormContext ( ) ;
27+ const { t} = useTranslation ( ) ;
28+ const appChatStyle = item ?. value ?. find ( v => v . name === 'appChatStyle' ) ?? { } ;
29+
30+ const renderOption = ( config , option ) => {
31+ const isSelected = appChatStyle . value === option . value ;
32+ const optionCount = config . options . length ;
33+ const flexBasis = optionCount >= 3 ? 'calc(33.333% - 11px)' : '1' ;
34+
35+ return (
36+ < div
37+ key = { option . value }
38+ onClick = { ( ) => ! disabled && handleOptionClick ( config , option ) }
39+ style = { {
40+ flex : `0 0 ${ flexBasis } ` ,
41+ padding : '12px' ,
42+ border : `2px solid ${ isSelected ? '#1890ff' : '#d9d9d9' } ` ,
43+ borderRadius : '4px' ,
44+ cursor : disabled ? 'not-allowed' : 'pointer' ,
45+ textAlign : 'center' ,
46+ background : disabled ? '#f5f5f5' : 'white' ,
47+ opacity : disabled ? 0.6 : 1 ,
48+ } }
49+ >
50+ { option . image && (
51+ < div className = { 'jade-custom-image-container' } >
52+ < Image
53+ src = { option . image }
54+ width = { 111 }
55+ height = { 62.28 }
56+ style = { { borderRadius : '4px' } }
57+ preview = { {
58+ mask : (
59+ < div style = { {
60+ display : 'flex' ,
61+ justifyContent : 'center' ,
62+ alignItems : 'center' ,
63+ height : '100%' ,
64+ backgroundColor : 'transparent' ,
65+ } } >
66+ < EyeOutlined style = { { fontSize : '20px' , color : '#000' } } />
67+ </ div >
68+ ) ,
69+ } }
70+ />
71+ </ div >
72+ ) }
73+ < span className = { 'jade-font-size jade-font-color' } >
74+ { t ( option . label ) }
75+ </ span >
76+ </ div >
77+ ) ;
78+ } ;
79+
80+ const handleOptionClick = ( config , option ) => {
81+ form . setFieldsValue ( { [ `${ config . name } ` ] : option . value } ) ;
82+ dispatch ( {
83+ actionType : 'changeAppConfig' ,
84+ name : config . name ,
85+ value : option . value ,
86+ } ) ;
87+ } ;
88+
89+ return (
90+ < Collapse bordered = { false } className = "jade-custom-collapse" defaultActiveKey = { [ 'configPanel' ] } >
91+ < Panel
92+ key = { 'configPanel' }
93+ header = {
94+ < div className = "panel-header" style = { { display : 'flex' , alignItems : 'center' , justifyContent : 'flex-start' } } >
95+ < span className = "jade-panel-header-font" > { t ( 'appConfig' ) } </ span >
96+ </ div >
97+ }
98+ className = "jade-panel"
99+ >
100+ < div className = { `jade-custom-panel-content` } >
101+ { configs ?. appChatStyle && ( ( ) => {
102+ const appChatStyleConfig = configs . appChatStyle ;
103+ return (
104+ < Form . Item
105+ key = { appChatStyleConfig . name }
106+ className = "jade-form-item"
107+ label = { t ( appChatStyleConfig . label ) }
108+ name = { `${ appChatStyleConfig . name } ` }
109+ rules = { appChatStyleConfig . rules }
110+ validateTrigger = "onBlur"
111+ initialValue = { appChatStyle . value }
112+ >
113+ < div style = { { display : 'flex' , flexDirection : 'row' , flexWrap : 'wrap' , gap : '16px' , width : '100%' } } >
114+ { appChatStyleConfig . options . map ( option => renderOption ( appChatStyleConfig , option ) ) }
115+ </ div >
116+ </ Form . Item >
117+ ) ;
118+ } ) ( ) }
119+ </ div >
120+ </ Panel >
121+ </ Collapse >
122+ ) ;
123+ } ;
124+
125+ _AppConfiguration . propTypes = {
126+ item : PropTypes . shape ( {
127+ value : PropTypes . arrayOf (
128+ PropTypes . shape ( {
129+ name : PropTypes . string . isRequired ,
130+ value : PropTypes . any
131+ } )
132+ ) . isRequired
133+ } ) . isRequired ,
134+ disabled : PropTypes . bool . isRequired ,
135+ configs : PropTypes . shape ( {
136+ appChatStyle : PropTypes . shape ( {
137+ name : PropTypes . string ,
138+ options : PropTypes . arrayOf (
139+ PropTypes . shape ( {
140+ value : PropTypes . any . isRequired ,
141+ label : PropTypes . string . isRequired ,
142+ image : PropTypes . string
143+ } )
144+ )
145+ } )
146+ } )
147+ } ;
148+
149+ const areEqual = ( prevProps , nextProps ) => {
150+ return prevProps . item === nextProps . item &&
151+ prevProps . disabled === nextProps . disabled &&
152+ prevProps . config === nextProps . config ;
153+ } ;
154+
155+ export const AppConfiguration = React . memo ( _AppConfiguration , areEqual ) ;
0 commit comments