onclick="f1()"和onclick="return f1()"的区别是什么?

本文介绍如何使用JavaScript阻止HTML链接的默认行为,通过return false来取消浏览器的默认跳转操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接:http://zhidao.baidu.com/question/126351894.html

是有区别的,具体请看如下解释。
浏览器会对页面元素的某些操作产生默认行为,比如说你有个链接:
<a href="http://zhidao.baidu.com">百度知道</a>
当你点击它的时候,浏览器就会跳转到百度知道的页面,实际上这是浏览器对a元素的点击操作(即onclick)产生的默认事件处理。
假如我们希望当点击这个链接时弹出一个对话框,可以这样做:
function f1(){
  alert("你点了我");
}
<a href="http://zhidao.baidu.com" onclick="f1()">百度知道</a>
我们发现会弹出一个对话框,但是页面还是跳到了百度知道,如果我们不希望浏览器自动跳到百度知道该怎么做呢?
首先在f1函数中加入一句话:
function f1(){
  alert("你点了我");
  return false;
}
接着在onclick中这样写:
<a href="http://zhidao.baidu.com" onclick="return f1()">百度知道</a>
因为f1()的返回值是false,所以onclick所对应的函数的返回值也是false。现在我们发现点击这个链接只会弹出对话框,而不会跳到百度知道,这里就是把浏览器的默认行为取消了。
如果f1()函数没有return false,也可以直接把return false加在onclick中,比如:onclick="f1();return false"。
import ToolBenefitOperator from '@aiComponents/BenefitOperator'; import AiToolBlockItem from '@aiComponents/BlockItem'; import { AiToolSquareCoverCard } from '@aiComponents/CardItems'; import AiToolConfigProvider from '@aiComponents/ConfigProvider'; import DrawSizeControls from '@aiComponents/DrawSizeControls'; import DrawStepOperateLayoutPC from '@aiComponents/DrawStepOperateLayout/pc'; import AiToolGenerateModal from '@aiComponents/GenerateModal'; import ToolVerticalIntroduceLayoutPC2 from '@aiComponents/IntroduceLayout/pc/vertical2'; import ToolVerticalIntroduceLayoutContent1 from '@aiComponents/IntroduceLayout/pc/vertical2/componetns/content1'; import MaterialIntroduceModal from '@aiComponents/MaterialIntroduceModal'; import { AiToolVipOptionItem } from '@aiComponents/OptionItems'; import ToggleGenerateInfoPanelItem from '@aiComponents/ToggleInfoPanel/PanelItem.tsx'; import { QuestionCircleOutlined } from '@ant-design/icons'; import IconFont from '@components/IconFont'; import ImageSelectorWrapModal from '@components/ImageSelectorWrapModal'; import ProductAuth from '@components/ProductAuth'; import ThemeButton from '@components/ThemeButton'; import ThemeConfigProvider from '@components/ThemeConfigProvider'; import ThemeSegmented from '@components/ThemeSegmented'; import ThemeTextArea from '@components/ThemeTextArea'; import ToolEquityCountWrap from '@components/ToolEquityCountWrap'; import { requestAdvanceDrawSubStyleConfigCategory } from '@services/advanceDraw/config.ts'; import { requestComfyUIDrawGenerate } from '@services/advanceDraw/generate.ts'; import { requestModelRender } from '@services/comfyUI.ts'; import { CoolImage } from '@wander/common-components'; import { Collapse, Image, message, Popover, Typography } from 'antd'; import classNames from 'classnames/bind'; import type { CSSProperties } from 'react'; import { useTranslation } from 'react-i18next'; import type { UploadImageType } from '@/components/UploadImageCard'; import UploadImageCard from '@/components/UploadImageCard'; import { enlargeDownloadOptions } from '@/config/aiTool.ts'; import { jzxzComfyUIDrawSizeTypeList } from '@/config/comfyUI.ts'; import KjlResultQuickAccessBox from '@/pages/AiTools/components/KjlResultQuickAccessBox'; import ToggleGenerateInfoPopover from '@/pages/AiTools/components/ToggleInfoPanel'; import { lockingMaterialList } from '@/pages/AiTools/Draw/configs.ts'; import GenerateCountLimitModal from '@/pages/AiTools/InspirationDraw/Operate/jzxz/components/GenerateCountLimitModal'; import { modelRenderGenerateCountList, modelRenderSpeedupKey, modelRenderToolKey, modelRenderToolName, TRACK_MODEL_RENDER_NAME, } from '@/pages/AiTools/ModelRender/config.ts'; import JzxzResultQuickAccessBox from '@/pages/AiTools/ModelRender/Operate/components/JzxzQuickToolMenu'; import ModelRenderStyleCategoryGrid from '@/pages/AiTools/ModelRender/Operate/components/StyleCategoryGrid'; import useModelRender from '@/pages/AiTools/ModelRender/Operate/hooks.ts'; import { LockingMaterialTypeEnum } from '@/types/draw.ts'; import styles from './index.module.less'; const cx = classNames.bind(styles); const { Paragraph } = Typography; const { Panel } = Collapse; const ModelRenderOperatePC = () => { const { spatialPositionConfig, setSpatialCategoryIndex, imageSelectorWrapModalRef, materialIntroduceModalRef, generateComfyUiModalRef, setSelectPositionIndex, generateParams, resultImageSelectIndex, setLockingMaterialType, introduceLayoutShow, setIntroduceLayoutShow, setDescription, modelScenarioActiveIndex, onBaseImageFinish, setPreciseRender, onComfyUiGenerateSuccess, onBaseImageChange, onStepStart, styleCategoryList, spatialCategoryIndex, baseImageCardRef, productType, styleCategoryGridRef, setStyleCategoryList, toolEquityCountWrapRef, drawStepOperateLayoutRef, generateComfyUiPreciseRenderingModalRef, description, lockingMaterialType, preciseRender, selectPositionIndex, styleImageCardRef, handleScenarioClick, setFilteredStyleCategoryList, jzxzCategoryList, filteredStyleCategoryList, scenarioKey, onGenerateCountsChange, generateCounts, sizeType, setSizeType, limitModalOpen, setLimitModalOpen, generateCountLimitModalRef, baseImageTagList, } = useModelRender(); const { t } = useTranslation(); // 第一步 底图的上传 const firstStepRender = (uploadImage: UploadImageType | null) => { return ( <> <div className={cx('first_content')}> <UploadImageCard.Card style={{ minHeight: '100%', height: 'auto', }} ref={baseImageCardRef} onUploadImageChange={onBaseImageChange} enableKjlUpload enableScreenshot={productType === 'JZXZ'} uploadImageIcon={{ customUploadBtn: (className) => { return ( <> <div className={className} onClick={() => { imageSelectorWrapModalRef.current?.setModalStatus('SELECT_MODAL'); }} > {t('HuabanUploadBtn-rWrt')} </div> </> ); }, }} onScreenshotSuccess={(value) => { imageSelectorWrapModalRef.current?.setModalStatus('LEAFER_FRAME'); imageSelectorWrapModalRef.current?.onGenerateFrame({ width: value.width, height: value.height, url: value.largeUrl, }); setTimeout(() => { imageSelectorWrapModalRef.current?.setOperationType('CLIP_FRAME'); }, 600); }} hidden={!!uploadImage} /> <div className={cx('image_wrap')} hidden={!uploadImage}> <CoolImage placeholder={{ type: 'loadingIcon' }} className={cx('image')} style={{ objectFit: 'contain' }} src={uploadImage?.largeUrl} alt="" /> </div> <div className={cx('operator_btn_wrap')} hidden={!uploadImage}> <IconFont type="micro-icon-edit" className={cx('operator_icon')} onClick={() => { imageSelectorWrapModalRef.current?.setModalStatus('LEAFER_FRAME'); // 画板没有原图信息的时候 先创建画板 const originImageInfo = imageSelectorWrapModalRef.current?.getOriginImgInfo(); if (!originImageInfo?.url && uploadImage) { imageSelectorWrapModalRef.current?.onGenerateFrame({ url: uploadImage?.largeUrl, width: uploadImage.width, height: uploadImage.height, }); } }} /> <IconFont type="micro-icon-trash-can" className={cx('operator_icon')} onClick={() => { baseImageCardRef.current?.setUploadImage(null); imageSelectorWrapModalRef.current?.clearFrame(); }} /> </div> </div> </> ); }; // JKJL 第二步内容 const secondStepRender = ( <> <div className={cx('first_category_wrap')}> {styleCategoryList.map((value, index) => ( <div key={value.mid} className={cx('first_category_item', { active: index === spatialCategoryIndex, })} onClick={async () => { setSpatialCategoryIndex(index); styleCategoryGridRef.current?.setFirstCategoryIndex(index); styleCategoryGridRef.current?.resetSecondCategoryIndex?.(); if (!value.children && value.justCategory) { try { styleCategoryGridRef.current?.setSecondCategoryRequesting(true); const subCategoryList = await requestAdvanceDrawSubStyleConfigCategory(value.mid); // 替换当前类目下的子类目信息 setStyleCategoryList( styleCategoryList.map((value1, index1) => { if (index1 === index) { return { ...value1, children: subCategoryList, }; } return value1; }), ); styleCategoryGridRef.current?.setSecondCategoryRequesting(false); } catch (e) { styleCategoryGridRef.current?.setSecondCategoryRequesting(false); console.error(e); } } }} > {value.name} </div> ))} </div> <div className={cx('spatial_position_wrap')}> {spatialPositionConfig[styleCategoryList[spatialCategoryIndex]?.mid || '']?.map( (value, index) => ( <div className={cx('spatial_position_item', { active: index === selectPositionIndex, })} key={index} onClick={() => { setSelectPositionIndex(index); }} > <AiToolSquareCoverCard coverUrl={value.coverUrl} extra={<span className={cx('spatial_position_name')}>{value.name}</span>} /> </div> ), )} </div> </> ); // JZXZ第二步 const jzxzSecondStepRender = () => { const currentList = filteredStyleCategoryList.length > 0 ? filteredStyleCategoryList : styleCategoryList; // 获取当前选中的类目MID const currentCategoryMid = currentList[spatialCategoryIndex]?.mid; return ( <> <div className={cx('first_category_wrap')}> {currentList.map((value, index) => ( <div key={value.mid} className={cx('first_category_item', { active: index === spatialCategoryIndex, })} onClick={async () => { setSpatialCategoryIndex(index); console.log('index', index); styleCategoryGridRef.current?.setFirstCategoryIndex(index); if (!value.children && value.justCategory) { try { styleCategoryGridRef.current?.setSecondCategoryRequesting(true); const subCategoryList = await requestAdvanceDrawSubStyleConfigCategory( value.mid, ); // 更新原始列表 setStyleCategoryList((prev) => prev.map((item) => item.mid === value.mid ? { ...item, children: subCategoryList } : item, ), ); // 更新过滤列表 setFilteredStyleCategoryList((prev) => prev.map((item) => item.mid === value.mid ? { ...item, children: subCategoryList } : item, ), ); styleCategoryGridRef.current?.setSecondCategoryRequesting(false); } catch (e) { styleCategoryGridRef.current?.setSecondCategoryRequesting(false); console.error(e); } } }} > {value.name} </div> ))} </div> {currentCategoryMid && spatialPositionConfig[currentCategoryMid] && ( <div className={cx('spatial_position_wrap')}> {spatialPositionConfig[currentCategoryMid].map((value, index) => ( <div className={cx('spatial_position_item', { active: index === selectPositionIndex, })} key={index} onClick={() => setSelectPositionIndex(index)} > <AiToolSquareCoverCard coverUrl={value.coverUrl} extra={<span className={cx('spatial_position_name')}>{value.name}</span>} /> </div> ))} </div> )} </> ); }; // 酷家乐-精确渲染 const secondCategoryPreciseRendering = (url: string) => ( <> {/* 二级类目前新增精确渲染 */} <div className={cx('second_category_item', { active: preciseRender, })} onClick={() => { setPreciseRender(true); }} > <AiToolSquareCoverCard coverUrl={url} extra={ <> <div className={cx('second_category_recommended')}> <span>推荐</span> </div> <span className={cx('second_category_name')}>精确渲染</span> </> } /> </div> </> ); // 第三步内容 const thirdStepRender = ( <> <ModelRenderStyleCategoryGrid ref={styleCategoryGridRef} categoryList={styleCategoryList} onCategoryListChange={(list) => { setStyleCategoryList(list); }} secondCategoryExtra={[ secondCategoryPreciseRendering( 'https://gd-hbimg.huaban.com/d113fdba55b570c14f9e6dd85053e20fe66e59f5cd9c6-KWo2yS_fw1200webp', ), secondCategoryPreciseRendering( 'https://gd-hbimg.huaban.com/4d623892958842956954557d10427f47f7331c3bcfbdc-Xa8fgu_fw1200webp', ), ]} hideActive={preciseRender} onSecondCategoryChange={() => { setPreciseRender(false); }} scenarioKey={scenarioKey} /> {!preciseRender || (scenarioKey !== 'indoor' && ( <> <div className={cx('step_title')} style={{ marginTop: 40 }}> 更多设置 </div> <ProductAuth productTypes={['JKJL']}> <div className={cx('step_sub_title')}> 上传风格参考图添加更多设置可以定制化生成对应风格,进一步加强生成图的风格准确性,此处做选填。 </div> </ProductAuth> <Collapse ghost expandIconPosition="end"> <ProductAuth productTypes={['JKJL']}> <Panel header="上传参考图(选填)" key="reference"> <div className={cx('reference_image_wrap')}> <UploadImageCard> {() => <UploadImageCard.Card hideDeleteBtn={false} ref={styleImageCardRef} />} </UploadImageCard> </div> </Panel> </ProductAuth> <Panel header="更多设置(选填)" key="more"> <div className={cx('more_settings_wrap')}> <ThemeConfigProvider themeConfigs={{ JKJL: { textArea: { borderColor: '#dfdfdf', borderWidth: '1px', }, segmented: { '--border-width': '1px', '--border-color': '#dfdfdf', } as CSSProperties, }, }} > <AiToolBlockItem title="描述词"> <ThemeTextArea placeholder="写下你的绘画想法创意" value={description} onChange={(e) => { setDescription(e.target.value); }} /> </AiToolBlockItem> <AiToolBlockItem title={ <span> {t('AiTools-Draw-ControlNet-BaseImage-WREs5')} <QuestionCircleOutlined style={{ marginLeft: 4 }} onClick={() => { materialIntroduceModalRef.current?.setModalStatus('INTRODUCE'); }} /> </span> } extra={ <ThemeSegmented block style={{ width: 180 }} value={lockingMaterialType} options={lockingMaterialList.map((item) => ({ label: t(item.labelKey), value: item.value, }))} onChange={(item) => { setLockingMaterialType(item.value); }} /> } /> </ThemeConfigProvider> </div> </Panel> </Collapse> ; </> ))} </> ); // 生成参数弹窗 const generateParamsContent = ( <div> <ToggleGenerateInfoPanelItem title="创意描述"> {() => { return ( <Paragraph ellipsis={{ rows: 4 }}> <span style={{ margin: '10px 0 0', color: 'rgb(255 255 255 / 80%)' }}> {description || '无'} </span> </Paragraph> ); }} </ToggleGenerateInfoPanelItem> <ToggleGenerateInfoPanelItem title="创作类目" description={generateParams.styleAlias?.join('/')} /> <ToggleGenerateInfoPanelItem title="空间位置" description={ spatialPositionConfig[styleCategoryList[spatialCategoryIndex]?.mid || '']?.[ selectPositionIndex ].name || '' } /> <ToggleGenerateInfoPanelItem title="底图"> {(imageCardClassName) => { return ( <div className={imageCardClassName}> <Image src={generateParams.baseImage} preview width="100%" height={154} style={{ objectFit: 'contain', }} /> </div> ); }} </ToggleGenerateInfoPanelItem> {generateParams.styleImage && ( <ToggleGenerateInfoPanelItem title="参考图"> {(imageCardClassName) => { return ( <div className={imageCardClassName}> <Image src={generateParams.styleImage} preview width="100%" height={154} style={{ objectFit: 'contain', }} /> </div> ); }} </ToggleGenerateInfoPanelItem> )} <ToggleGenerateInfoPanelItem title="材质锁定" description={t(LockingMaterialTypeEnum[lockingMaterialType || 'OFF'])} /> </div> ); return ( <> <ToolVerticalIntroduceLayoutPC2 toolName={modelRenderToolName} description="一键AI渲染酷家乐室内设计模型,比传统渲染方式更加真实,细腻,高效~支持多种室内风格渲染!" show={introduceLayoutShow} onClickUseBtn={() => { setIntroduceLayoutShow(false); }} content={ <> <ToolVerticalIntroduceLayoutContent1 items={[ { beforeUrl: 'https://gd-hbimg.huaban.com/dc74bbd45daaaf4973d71e64785ed7e2d6cb0eed5ec75-7Gc6aa', afterUrl: 'https://gd-hbimg.huaban.com/63a044eec1c55566f7304e79d1f1c2828c51c8ba9d774-4jCT7E', }, { beforeUrl: 'https://gd-hbimg.huaban.com/ffefde120630092f0244bf346c1d974e51e5dd9bb5fe2-NvzNpK', afterUrl: 'https://gd-hbimg.huaban.com/2d776cae122ab64c90697906540a706664ce21809d1e6-XyYWf1', }, { beforeUrl: 'https://gd-hbimg.huaban.com/6519e79f2c37ee2a1b75025376b10f6d574edfc4f0d17-8ReO7g', afterUrl: 'https://gd-hbimg.huaban.com/82c0c13e8abcb63243697acde385fc569b9b3fd5ba214-nh471F', }, ]} /> </> } /> <UploadImageCard> {(uploadImage) => ( <> <ProductAuth productTypes={['JKJL']}> <DrawStepOperateLayoutPC trackToolName={TRACK_MODEL_RENDER_NAME} ref={drawStepOperateLayoutRef} downloadConfig={{ enlargeDownloadOptions, }} items={[ { title: '上传模型底图', subTitle: '大师级渲染,从上传底图开始!', content: ( <div className={cx('first_content')}> <UploadImageCard.Card style={{ minHeight: '100%', height: 'auto', }} ref={baseImageCardRef} onUploadImageChange={onBaseImageChange} enableKjlUpload uploadImageIcon={{ customUploadBtn: (className) => { return ( <div className={className} onClick={() => { imageSelectorWrapModalRef.current?.setModalStatus( 'SELECT_MODAL', ); }} > {t('HuabanUploadBtn-rWrt')} </div> ); }, }} onScreenshotSuccess={(value) => { imageSelectorWrapModalRef.current?.setModalStatus('LEAFER_FRAME'); imageSelectorWrapModalRef.current?.onGenerateFrame({ width: value.width, height: value.height, url: value.largeUrl, }); setTimeout(() => { imageSelectorWrapModalRef.current?.setOperationType('CLIP_FRAME'); }, 600); }} hidden={!!uploadImage} /> <div className={cx('image_wrap')} hidden={!uploadImage}> <CoolImage placeholder={{ type: 'loadingIcon' }} className={cx('image')} style={{ objectFit: 'contain' }} src={uploadImage?.largeUrl} alt="" /> </div> <div className={cx('operator_btn_wrap')} hidden={!uploadImage}> <IconFont type="micro-icon-edit" className={cx('operator_icon')} onClick={() => { imageSelectorWrapModalRef.current?.setModalStatus('LEAFER_FRAME'); // 画板没有原图信息的时候 先创建画板 const originImageInfo = imageSelectorWrapModalRef.current?.getOriginImgInfo(); if (!originImageInfo?.url && uploadImage) { imageSelectorWrapModalRef.current?.onGenerateFrame({ url: uploadImage?.largeUrl, width: uploadImage.width, height: uploadImage.height, }); } }} /> <IconFont type="micro-icon-trash-can" className={cx('operator_icon')} onClick={() => { baseImageCardRef.current?.setUploadImage(null); imageSelectorWrapModalRef.current?.clearFrame(); }} /> </div> </div> ), beforeNextStep: async () => { if (!baseImageCardRef.current?.uploadImage) { message.warn('请先上传底图'); return false; } return true; }, }, { title: '选择空间位置', subTitle: '选择正确的位置可以确保生成图更准确。', content: secondStepRender, }, { title: '选择渲染风格', subTitle: '选择想要生成的风格大模型,可以让生成结果更偏向自己的喜好。', content: thirdStepRender, }, ]} onStepStart={onStepStart} uploadImage={uploadImage} resultExtra={ <> {/* 快捷使用 */} <KjlResultQuickAccessBox className={cx('quick_access_box')} extraBottomItems={[ { title: '迭代渲染', iconKey: 'micro-icon-iterative-render', onClick: () => { const generateImage = drawStepOperateLayoutRef.current?.generateImageList[ resultImageSelectIndex ]; if (generateImage) { drawStepOperateLayoutRef.current.setShowType('STEP'); drawStepOperateLayoutRef.current.setCurrent(0); baseImageCardRef.current?.setUploadImage({ thumbUrl: generateImage.url, largeUrl: generateImage.url, width: generateImage.width, height: generateImage.height, }); } }, }, ]} /> {/* 参数明细 */} <ToggleGenerateInfoPopover placement="leftTop" className={cx('generate_params_wrap')} content={generateParamsContent} > {(open) => { return <IconFont type={open ? 'micro-icon-close' : 'micro-icon-tip'} />; }} </ToggleGenerateInfoPopover> </> } stepFooterExtra={ <ToolEquityCountWrap toolKey={modelRenderToolKey} showToolName={modelRenderToolName} trackToolName={TRACK_MODEL_RENDER_NAME} ref={toolEquityCountWrapRef} > <ToolBenefitOperator style={{ marginTop: 8, }} toolKey={modelRenderToolKey} trackToolName={TRACK_MODEL_RENDER_NAME} showToolEquityInfo={() => { toolEquityCountWrapRef.current?.showToolEquityInfo(); }} showToolCountUsageIntro={() => { toolEquityCountWrapRef.current?.showToolCountUsageIntro(); }} showToolBuyCount={() => { toolEquityCountWrapRef.current?.showToolBuyCount(); }} /> </ToolEquityCountWrap> } /> </ProductAuth> <ProductAuth productTypes={['JZXZ']}> <DrawStepOperateLayoutPC trackToolName={TRACK_MODEL_RENDER_NAME} ref={drawStepOperateLayoutRef} downloadConfig={{ enlargeDownloadOptions, }} items={[ { title: '选择模型场景', subTitle: '请根据实际情况选择合适的渲染场景', content: ( <> <div className={cx('scenario_wrap')}> {jzxzCategoryList.map((item, index) => ( <div key={item.key} className={cx('scenario_item', productType.toLowerCase(), { active: modelScenarioActiveIndex === index, })} onClick={() => handleScenarioClick(item, index)} > <div className={cx('scenario_item_image')}> <img src={item.coverUrl} alt={item.name} className={cx('scenario_image')} /> </div> <ThemeButton size="large" shape="circle" className={cx('start_btn', { no_active: modelScenarioActiveIndex !== index, })} > {item.name} </ThemeButton> </div> ))} </div> </> ), }, { title: '上传模型底图', subTitle: '大师级渲染,从上传底图开始!', content: firstStepRender(uploadImage), beforeNextStep: async () => { // if (!baseImageCardRef.current?.uploadImage) { // message.warn('请先上传底图'); // return false; // } if (modelScenarioActiveIndex === 1) { return true; } else { drawStepOperateLayoutRef.current?.setCurrent(3); return false; } }, }, { title: '选择空间位置', subTitle: '选择正确的位置可以确保生成图更准确。', content: jzxzSecondStepRender(), }, { title: '选择渲染风格', subTitle: '选择想要生成的风格大模型,可以让生成结果更偏向自己的喜好。', content: thirdStepRender, previousStep: async () => { if (modelScenarioActiveIndex === 1) { return true; } else { drawStepOperateLayoutRef.current?.setCurrent(1); return false; } }, beforeNextStep: () => { return Promise.resolve(false); }, nextStepBtn: ( <Popover trigger={scenarioKey === 'indoor' ? [] : 'hover'} open={scenarioKey === 'indoor' ? false : undefined} showArrow={false} overlayInnerStyle={{ borderRadius: 10, paddingTop: 8 }} content={ <AiToolConfigProvider themeConfig={{ OptionItem: { '--text-color': '#919191', '--box-background': '#f2f2f2', '--border-radius': '10px', } as CSSProperties, }} > <div className={cx('popover_content')}> {/* 生成尺寸 */} <AiToolBlockItem title={t('AiTools-MixedRawImage-Operate-pc-Jcode')}> <DrawSizeControls value={sizeType} list={jzxzComfyUIDrawSizeTypeList} onChange={(item) => { setSizeType(item); }} /> </AiToolBlockItem> {/* 生成张数 */} <AiToolBlockItem title={t('AiTools-Draw-ConfigPopover-GenerateNum-kijAD')} > <div className={cx('size_grid')}> {modelRenderGenerateCountList.map((item, index) => ( <AiToolVipOptionItem availableType={item.availableType} label={t(item.labelKey)} key={index} active={item.value === generateCounts} onClick={() => { onGenerateCountsChange(item); }} /> ))} </div> </AiToolBlockItem> </div> </AiToolConfigProvider> } > <ThemeButton className={cx('btn_start')} size="large" onClick={onStepStart}> 开始渲染 <IconFont hidden={scenarioKey === 'indoor'} className={cx('icon_down')} type="micro-icon-arrow-down" /> </ThemeButton> </Popover> ), }, ]} uploadImage={uploadImage} resultExtra={ <> <JzxzResultQuickAccessBox className={cx('quick_access_box')} /> </> } stepFooterExtra={ <ToolEquityCountWrap toolKey={modelRenderToolKey} showToolName={modelRenderToolName} trackToolName={TRACK_MODEL_RENDER_NAME} ref={toolEquityCountWrapRef} > <ToolBenefitOperator style={{ marginTop: 8, }} toolKey={modelRenderToolKey} trackToolName={TRACK_MODEL_RENDER_NAME} showToolEquityInfo={() => { toolEquityCountWrapRef.current?.showToolEquityInfo(); }} showToolCountUsageIntro={() => { toolEquityCountWrapRef.current?.showToolCountUsageIntro(); }} showToolBuyCount={() => { toolEquityCountWrapRef.current?.showToolBuyCount(); }} /> </ToolEquityCountWrap> } /> </ProductAuth> </> )} </UploadImageCard> {/* 迁移内容的原图片效果图库 */} <ImageSelectorWrapModal ref={imageSelectorWrapModalRef} queryTagImages={{ categoryList: baseImageTagList, introduce: t('AiTools-DecorationDesign-Operate-pc-f4eJ'), modalTitle: t('AiTools-Draw-ControlNet-BaseImage-b2tNh'), iconClassName: cx('style_refer_image'), }} onFinish={onBaseImageFinish} hideDiyDraw /> {/* 酷家乐 */} <AiToolGenerateModal displayType="MASK" className={cx('generate_mask_container')} customerRef={generateComfyUiModalRef} toolKey={modelRenderToolKey} trackToolName={TRACK_MODEL_RENDER_NAME} request={requestComfyUIDrawGenerate} speedupKey={modelRenderSpeedupKey} pollingConfig={{ processingType: 'COMFYUI_COMPOSE', imageDetectMode: 'NONE', }} onGenerateSuccess={onComfyUiGenerateSuccess} onCancel={() => { // 蒙层关闭 回到进度展示 drawStepOperateLayoutRef.current?.setShowType('STEP'); }} /> {/* 精确渲染 */} <AiToolGenerateModal displayType="MASK" className={cx('generate_mask_container')} customerRef={generateComfyUiPreciseRenderingModalRef} toolKey={modelRenderToolKey} trackToolName={TRACK_MODEL_RENDER_NAME} request={requestModelRender} speedupKey={modelRenderSpeedupKey} pollingConfig={{ processingType: 'COMFYUI_COMPOSE', imageDetectMode: 'NONE', }} onGenerateSuccess={onComfyUiGenerateSuccess} onCancel={() => { // 蒙层关闭 回到进度展示 drawStepOperateLayoutRef.current?.setShowType('STEP'); }} /> <MaterialIntroduceModal ref={materialIntroduceModalRef} /> <GenerateCountLimitModal ref={generateCountLimitModalRef} open={limitModalOpen} onCancel={() => { setLimitModalOpen(false); }} /> </> ); }; export default ModelRenderOperatePC;import { AiToolImageCoverCard, AiToolSquareCoverCard } from '@aiComponents/CardItems'; import AiToolGridList from '@aiComponents/GridList'; import Loading from '@components/Loading'; import ProductAuth from '@components/ProductAuth'; import { requestAdvanceDrawSubStyleConfigCategory } from '@services/advanceDraw/config.ts'; import { useMount } from 'ahooks'; import classNames from 'classnames/bind'; import { floor } from 'lodash'; import type { Dispatch, ReactNode, SetStateAction } from 'react'; import { useCallback } from 'react'; import { forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react'; import Media from 'react-media'; import type { GetAdvanceDrawLeafGenerateArgsByMidsType } from '@/pages/AiTools/AdvanceDraw/utils.ts'; import { getComfyUIDrawLeafGenerateArgsByMids } from '@/pages/AiTools/AdvanceDraw/utils.ts'; import { useStore } from '@/store/createStore.ts'; import type { AdvanceDrawStyleCategoryItem } from '@/types/advanceDraw'; import styles from './index.module.less'; const cx = classNames.bind(styles); export type ModelRenderStyleCategoryGridRef = { setFirstCategoryIndex: Dispatch<SetStateAction<number>>; setSecondCategoryRequesting: Dispatch<SetStateAction<boolean>>; getComfyUIDrawLeafGenerateArgsByMids: () => GetAdvanceDrawLeafGenerateArgsByMidsType; // 二级类目名称获取 getSelectedSecondCategoryName: () => string; // 重置二级类目 resetSecondCategoryIndex: () => void; }; type Props = { categoryList: AdvanceDrawStyleCategoryItem[]; onCategoryListChange: (list: AdvanceDrawStyleCategoryItem[]) => void; secondCategoryExtra: ReactNode[]; hideActive: boolean; onSecondCategoryChange: (index: number) => void; // 场景key值 scenarioKey: string; }; // 二级类目最小宽度 const MIN_SECOND_CATEGORY_CARD_WIDTH = 150; // 二级类目间距 const SECOND_CATEGORY_GRID_GAP = 16; /** * 模型渲染风格类目 */ const ModelRenderStyleCategoryGrid = forwardRef<ModelRenderStyleCategoryGridRef, Props>( ( { categoryList, onCategoryListChange, secondCategoryExtra, hideActive, onSecondCategoryChange, scenarioKey, }, ref, ) => { const { productType } = useStore((state) => state.productInfo); const secondCategoryRef = useRef<HTMLDivElement | null>(null); // 二级类目 列数 const [secondCategoryGridColumns, setSecondCategoryGridColumns] = useState(0); // 一级类目索引 const [firstCategoryIndex, setFirstCategoryIndex] = useState(0); // 二级类目索引 const [secondCategoryIndex, setSecondCategoryIndex] = useState(0); // 二级类目请求中 const [secondCategoryRequesting, setSecondCategoryRequesting] = useState(false); // 所有层级分类列表 const { secondCategoryList } = useMemo(() => { if (!categoryList.length) { return { secondCategoryList: [], }; } // 二级类目列表 const secondCategoryList = categoryList[firstCategoryIndex]?.children || []; return { secondCategoryList, }; }, [categoryList, firstCategoryIndex, secondCategoryIndex]); // 计算列数 const calculateColumns = useCallback(() => { if (secondCategoryRef.current?.offsetWidth) { const secondContainerWidth = secondCategoryRef.current?.offsetWidth; // 计算列数 setSecondCategoryGridColumns( floor( (secondContainerWidth + SECOND_CATEGORY_GRID_GAP) / (MIN_SECOND_CATEGORY_CARD_WIDTH + SECOND_CATEGORY_GRID_GAP), ), ); } }, []); useMount(() => { calculateColumns(); }); useImperativeHandle(ref, () => ({ setFirstCategoryIndex, setSecondCategoryRequesting, getComfyUIDrawLeafGenerateArgsByMids: () => { const firstCategory = categoryList[firstCategoryIndex]; const secondeCategory = firstCategory.children?.[secondCategoryIndex]; const selectMids = [firstCategory.mid]; if (secondeCategory) { selectMids.push(secondeCategory.mid); } return getComfyUIDrawLeafGenerateArgsByMids(categoryList, selectMids); }, getSelectedSecondCategoryName: () => { if (categoryList.length > firstCategoryIndex) { const secondCategoryList = categoryList[firstCategoryIndex]?.children || []; if (secondCategoryList.length > secondCategoryIndex) { return secondCategoryList[secondCategoryIndex]?.name || ''; } } return ''; }, resetSecondCategoryIndex: () => { setSecondCategoryIndex(0); }, })); console.log('setFirstCategoryIndex', firstCategoryIndex); return ( <> <div className={cx('first_category_wrap')} hidden={scenarioKey !== 'indoor' && productType === 'JZXZ'} > {categoryList.map((value, index) => ( <div key={value.mid} className={cx('first_category_item', { active: index === firstCategoryIndex, })} onClick={async () => { setFirstCategoryIndex(index); setSecondCategoryIndex(0); if (!value.children && value.justCategory) { try { setSecondCategoryRequesting(true); const subCategoryList = await requestAdvanceDrawSubStyleConfigCategory( value.mid, ); // 替换当前类目下的子类目信息 onCategoryListChange( categoryList.map((value1, index1) => { if (index1 === index) { return { ...value1, children: subCategoryList, }; } return value1; }), ); setSecondCategoryRequesting(false); } catch (e) { setSecondCategoryRequesting(false); console.error(e); } } }} > {value.name} </div> ))} </div> <Media queries={{ small: '(max-width: 768px)', large: '(min-width: 769px)', }} > {(matches) => ( <> {matches.large && ( <> {secondCategoryRequesting && <Loading height={200} iconWidth={100} />} <div className={cx('second_category_wrap')} style={{ gridTemplateColumns: `repeat(${secondCategoryGridColumns}, 1fr)`, }} ref={secondCategoryRef} > <ProductAuth productTypes={['JKJL']}> <div hidden={!secondCategoryList.length}> {secondCategoryExtra[firstCategoryIndex]} </div> </ProductAuth> {secondCategoryList.map((value, index) => ( <div className={cx('second_category_item', { active: productType === 'JKJL' ? index === secondCategoryIndex && !hideActive : index === secondCategoryIndex, })} key={value.mid} onClick={() => { setSecondCategoryIndex(index); onSecondCategoryChange(index); }} > <AiToolSquareCoverCard coverUrl={value.coverUrl} extra={<span className={cx('second_category_name')}>{value.name}</span>} /> </div> ))} </div> </> )} {matches.small && ( <> {secondCategoryRequesting && <Loading height={200} iconWidth={100} />} <div className={cx('second_category_wrap')} ref={secondCategoryRef}> {/* {secondCategoryList.map((value, index) => (*/} {/* <div*/} {/* className={cx('second_category_item', {*/} {/* active:*/} {/* productType === 'JKJL'*/} {/* ? index === secondCategoryIndex && !hideActive*/} {/* : index === secondCategoryIndex,*/} {/* })}*/} {/* key={value.mid}*/} {/* onClick={() => {*/} {/* setSecondCategoryIndex(index);*/} {/* onSecondCategoryChange(index);*/} {/* }}*/} {/* >*/} {/* <AiToolSquareCoverCard*/} {/* coverUrl={value.coverUrl}*/} {/* extra={<span className={cx('second_category_name')}>{value.name}</span>}*/} {/* />*/} {/* </div>*/} {/* ))}*/} <> <AiToolGridList list={secondCategoryList} renderItem={(item, index) => { return ( <AiToolImageCoverCard label={item.name} active={index === secondCategoryIndex} coverUrl={item.coverUrl} onClick={() => { setSecondCategoryIndex(index); onSecondCategoryChange(index); }} /> ); }} /> </> </div> </> )} </> )} </Media> </> ); }, ); export default ModelRenderStyleCategoryGrid; 为什么第一次点击的时候styleCategoryGridRef.current?.setFirstCategoryIndex(index);没有生效firstCategoryIndex依旧是默认的0,第二次点击就生效了
08-01
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>模型性能展示</title> <style> body { font-family: Arial, sans-serif; max-width: 1000px; margin: 0 auto; padding: 20px; color: #333; } h1 { color: #1a73e8; border-bottom: 2px solid #1a73e8; padding-bottom: 10px; } .chip-selection { margin: 20px 0; padding: 15px; background-color: #f5f5f5; border-radius: 5px; } .chip-option { display: inline-block; margin-right: 20px; padding: 10px 20px; background-color: #e8f0fe; border-radius: 5px; cursor: pointer; transition: all 0.3s; } .chip-option:hover { background-color: #d2e3fc; } .chip-option.selected { background-color: #1a73e8; color: white; } .group-section { margin-top: 30px; display: none; } .group-title { font-size: 18px; font-weight: bold; margin-bottom: 15px; color: #1a73e8; } .group-items { display: flex; flex-wrap: wrap; gap: 10px; } .group-item { padding: 8px 15px; background-color: #f1f3f4; border-radius: 5px; cursor: pointer; } .group-item:hover { background-color: #e0e0e0; } .footer { margin-top: 40px; font-size: 12px; color: #666; text-align: center; } </style> </head> <body> <h1>模型性能</h1> <div class="chip-selection"> <h2>节点性能</h2> <div> <div class="chip-option" onclick="selectChip('single')">BS9SX1A单芯片</div> <div class="chip-option" onclick="selectChip('double')">Ascend610Lite双芯片</div> </div> </div> <div id="group-section" class="group-section"> <div class="group-title">分组</div> <div class="group-items"> <div class="group-item" onclick="showGroupInfo('model')">模型名</div> <div class="group-item" onclick="showGroupInfo('size')">模型大小</div> <div class="group-item" onclick="showGroupInfo('frame')">帧率</div> <div class="group-item" onclick="showGroupInfo('core')">核数</div> <div class="group-item" onclick="showGroupInfo('delay')">时延</div> <div class="group-item" onclick="showGroupInfo('bandwidth')">带宽</div> <div class="group-item" onclick="showGroupInfo('quantization')">量化率</div> </div> </div> <div class="footer"> <p>Huawei Proprietary - Restricted Distribution</p> <p id="current-date"></p> </div> <script> // 显示当前日期 const now = new Date(); const options = { year: 'numeric', month: 'long', day: 'numeric' }; document.getElementById('current-date').textContent = now.toLocaleDateString('zh-CN', options); // 选择芯片类型 function selectChip(type) { // 更新选中状态 const options = document.querySelectorAll('.chip-option'); options.forEach(opt => opt.classList.remove('selected')); if(type === 'single') { options[0].classList.add('selected'); } else { options[1].classList.add('selected'); } // 显示分组区域 document.getElementById('group-section').style.display = 'block'; } // 显示分组信息 function showGroupInfo(group) { // 这里可以添加显示具体分组信息的逻辑 alert('您选择了: ' + group + ' 分组\n实际应用中这里会显示详细数据'); } </script> </body> </html>我该如何使用这个html脚本与后端python脚本进行交互?
07-23
用函数获取元素添加点击事件 <body> <input type="text" id="new-todo" placeholder="Add new todo" /> <button onclick="addTodo()">添加</button> <ul id="todo-list"></ul> <h2>Show:</h2> <button onclick="showTodos('all')">All</button> <button onclick="showTodos('active')">Active</button> <button onclick="showTodos('completed')">删除</button> <script> // 加载本地存储的数据 function loadTodos() { let todos = localStorage.getItem('todos'); return todos ? JSON.parse(todos) : []; } // 保存数据到本地存储 function saveTodos(todos) { localStorage.setItem('todos', JSON.stringify(todos)); } // 添加新任务 function addTodo() { let text = document.getElementById('new-todo').value.trim(); if (!text) return; let todos = loadTodos(); todos.push({ text, completed: false }); saveTodos(todos); renderTodos(todos); document.getElementById('new-todo').value = ''; } // 渲染任务列表 function renderTodos(todos) { let listElement = document.getElementById('todo-list'); listElement.innerHTML = ''; todos.forEach((todo, index) => { let li = document.createElement('li'); li.textContent = todo.text; if (todo.completed) li.classList.add('completed'); li.addEventListener('click', () => toggleTodo(index)); listElement.appendChild(li); }); } // 切换任务完成状态 function toggleTodo(index) { let todos = loadTodos(); todos[index].completed = !todos[index].completed; saveTodos(todos); renderTodos(todos); } // 显示不同类型的任务 function showTodos(filter) { let todos = loadTodos(); let filteredTodos; switch (filter) { case 'active': filteredTodos = todos.filter(todo => !todo.completed); break; case 'completed': filteredTodos = todos.filter(todo => todo.completed); break; default: filteredTodos = todos; } renderTodos(filteredTodos); } // 初始化时渲染任务列表 document.addEventListener('DOMContentLoaded', () => { let todos = loadTodos(); renderTodos(todos); }); </script> </body>
最新发布
08-04
import { AiToolImageCoverCard, AiToolSquareCoverCard } from '@aiComponents/CardItems'; import Loading from '@components/Loading'; import { requestAdvanceDrawSubStyleConfigCategory } from '@services/advanceDraw/config.ts'; import { useMount } from 'ahooks'; import classNames from 'classnames/bind'; import { floor } from 'lodash'; import type { Dispatch, SetStateAction } from 'react'; import { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState } from 'react'; import type { GetAdvanceDrawLeafGenerateArgsByMidsType } from '@/pages/AiTools/AdvanceDraw/utils.ts'; import { getComfyUIDrawLeafGenerateArgsByMids } from '@/pages/AiTools/AdvanceDraw/utils.ts'; import type { AdvanceDrawStyleCategoryItem } from '@/types/advanceDraw'; import styles from './index.module.less'; const cx = classNames.bind(styles); export type ModelRenderStyleCategoryGridRef = { setFirstCategoryIndex: Dispatch<SetStateAction<number>>; setSecondCategoryRequesting: Dispatch<SetStateAction<boolean>>; getComfyUIDrawLeafGenerateArgsByMids: () => | GetAdvanceDrawLeafGenerateArgsByMidsType | 'PreciseRendering'; }; type Props = { categoryList: AdvanceDrawStyleCategoryItem[]; onCategoryListChange: (list: AdvanceDrawStyleCategoryItem[]) => void; }; // 二级类目最小宽度 const MIN_SECOND_CATEGORY_CARD_WIDTH = 150; // 二级类目间距 const SECOND_CATEGORY_GRID_GAP = 16; // 三级类目最小宽度 const MIN_THIRD_CATEGORY_CARD_WIDTH = 120; // 三级类目间距 const THIRD_CATEGORY_GRID_GAP = 12; // 三级类目padding const THIRD_CATEGORY_WRAP_PADDING = 16; /** * 模型渲染风格类目 */ const ModelRenderStyleCategoryGrid = forwardRef<ModelRenderStyleCategoryGridRef, Props>( ({ categoryList, onCategoryListChange }, ref) => { const secondCategoryRef = useRef<HTMLDivElement | null>(null); // 二级类目 列数 const [secondCategoryGridColumns, setSecondCategoryGridColumns] = useState(0); // 三 级类目列表 const [thirdCategoryGridColumns, setThirdCategoryGridColumns] = useState(0); // 一级类目索引 const [firstCategoryIndex, setFirstCategoryIndex] = useState(0); // 二级类目索引 const [secondCategoryIndex, setSecondCategoryIndex] = useState(-1); // 三级类目索引 const [thirdCategoryIndex, setThirdCategoryIndex] = useState(0); // 二级类目请求中 const [secondCategoryRequesting, setSecondCategoryRequesting] = useState(false); // 所有层级分类列表 const { secondCategoryList, thirdCategoryList } = useMemo(() => { if (!categoryList.length) { return { secondCategoryList: [], thirdCategoryList: [], }; } // 二级类目列表 const secondCategoryList = categoryList[firstCategoryIndex]?.children || []; // 三级类目列表 const thirdCategoryList = secondCategoryList[secondCategoryIndex]?.children || []; return { secondCategoryList, thirdCategoryList, }; }, [categoryList, firstCategoryIndex, secondCategoryIndex]); // 计算列数 const calculateColumns = useCallback(() => { if (secondCategoryRef.current?.offsetWidth) { const secondContainerWidth = secondCategoryRef.current?.offsetWidth; const thirdContainerWidth = secondCategoryRef.current?.offsetWidth - THIRD_CATEGORY_WRAP_PADDING * 2; // 计算列数 setSecondCategoryGridColumns( floor( (secondContainerWidth + SECOND_CATEGORY_GRID_GAP) / (MIN_SECOND_CATEGORY_CARD_WIDTH + SECOND_CATEGORY_GRID_GAP), ), ); setThirdCategoryGridColumns( floor( (thirdContainerWidth + THIRD_CATEGORY_GRID_GAP) / (MIN_THIRD_CATEGORY_CARD_WIDTH + THIRD_CATEGORY_GRID_GAP), ), ); } }, []); useMount(() => { calculateColumns(); }); useImperativeHandle(ref, () => ({ setFirstCategoryIndex, setSecondCategoryRequesting, getComfyUIDrawLeafGenerateArgsByMids: () => { if (secondCategoryIndex === -1) { return 'PreciseRendering'; } const firstCategory = categoryList[firstCategoryIndex]; const secondeCategory = firstCategory.children?.[secondCategoryIndex]; const thirdCategory = secondeCategory?.children?.[thirdCategoryIndex]; const selectMids = [firstCategory.mid]; if (secondeCategory) { selectMids.push(secondeCategory.mid); } if (thirdCategory) { selectMids.push(thirdCategory.mid); } return getComfyUIDrawLeafGenerateArgsByMids(categoryList, selectMids); }, })); return ( <> <div className={cx('first_category_wrap')}> {categoryList.map((value, index) => ( <div key={value.mid} className={cx('first_category_item', { active: index === firstCategoryIndex, })} onClick={async () => { setFirstCategoryIndex(index); setSecondCategoryIndex(-1); setThirdCategoryIndex(0); if (!value.children && value.justCategory) { try { setSecondCategoryRequesting(true); const subCategoryList = await requestAdvanceDrawSubStyleConfigCategory( value.mid, ); // 替换当前类目下的子类目信息 onCategoryListChange( categoryList.map((value1, index1) => { if (index1 === index) { return { ...value1, children: subCategoryList, }; } return value1; }), ); setSecondCategoryRequesting(false); } catch (e) { setSecondCategoryRequesting(false); console.error(e); } } }} > {value.name} </div> ))} </div> {secondCategoryRequesting && <Loading height={200} iconWidth={100} />} <div className={cx('second_category_wrap')} style={{ gridTemplateColumns: `repeat(${secondCategoryGridColumns}, 1fr)`, }} ref={secondCategoryRef} > {/* 二级类目前新增精确渲染 */} <div className={cx('second_category_item', { active: -1 === secondCategoryIndex, })} onClick={() => { setSecondCategoryIndex(-1); setThirdCategoryIndex(0); }} > <AiToolSquareCoverCard coverUrl={ firstCategoryIndex === 0 ? 'https://gd-hbimg.huaban.com/3bc374cfcf042c25555da1aff0f76adec1ec6bbd9dd70-2wtBwE_fw1200webp' : 'https://gd-hbimg.huaban.com/f4a66d792060691660dff9fdab52b176cf2db0c367f2a-teB6Pa_fw658webp' } extra={ <> <div className={cx('second_category_recommended')}> <span>推荐</span> </div> <span className={cx('second_category_name')}>精确渲染</span> </> } /> </div> {secondCategoryList.map((value, index) => ( <div className={cx('second_category_item', { active: index === secondCategoryIndex, })} key={value.mid} onClick={() => { setSecondCategoryIndex(index); setThirdCategoryIndex(0); }} > <AiToolSquareCoverCard coverUrl={value.coverUrl} extra={<span className={cx('second_category_name')}>{value.name}</span>} /> </div> ))} </div> {!!thirdCategoryList?.length && ( <div className={cx('third_category_wrap')} style={{ gridTemplateColumns: `repeat(${thirdCategoryGridColumns}, 1fr)`, gridColumn: `1 / span ${secondCategoryGridColumns}`, order: (floor(secondCategoryIndex / secondCategoryGridColumns) + 1) * secondCategoryGridColumns * 5 - 1, }} > <div className={cx('triangle_icon')} style={{ left: `calc(${floor((((secondCategoryIndex + 1) % secondCategoryGridColumns || secondCategoryGridColumns) / secondCategoryGridColumns - 1 / (secondCategoryGridColumns * 2)) * 100, 2)}% - 6px)`, }} /> {thirdCategoryList.map((item, index) => { return ( <div key={index} style={{ order: index * 5, }} > <AiToolImageCoverCard active={thirdCategoryIndex === index} coverUrl={item.coverUrl || ''} label={item.name} onClick={() => { setThirdCategoryIndex(index); }} /> </div> ); })} </div> )} </> ); }, ); export default ModelRenderStyleCategoryGrid;import ToolBenefitOperator from '@aiComponents/BenefitOperator'; import AiToolBlockItem from '@aiComponents/BlockItem'; import { AiToolSquareCoverCard } from '@aiComponents/CardItems'; import type { DrawStepOperateLayoutPcRef } from '@aiComponents/DrawStepOperateLayout/pc'; import DrawStepOperateLayoutPC from '@aiComponents/DrawStepOperateLayout/pc'; import AiToolGenerateModal, { type AiToolGenerateModalRef } from '@aiComponents/GenerateModal'; import ToolVerticalIntroduceLayoutPC2 from '@aiComponents/IntroduceLayout/pc/vertical2'; import ToolVerticalIntroduceLayoutContent1 from '@aiComponents/IntroduceLayout/pc/vertical2/componetns/content1'; import ToggleGenerateInfoPanelItem from '@aiComponents/ToggleInfoPanel/PanelItem.tsx'; import type { MaterialIntroduceModalRef } from '@aiDrawComponents/ControlNet/BaseImage/MaterialIntroduceModal.tsx'; import MaterialIntroduceModal from '@aiDrawComponents/ControlNet/BaseImage/MaterialIntroduceModal.tsx'; import { QuestionCircleOutlined } from '@ant-design/icons'; import IconFont from '@components/Iconfont'; import type { ImageSelectorWrapModalRef } from '@components/ImageSelectorWrapModal'; import ImageSelectorWrapModal from '@components/ImageSelectorWrapModal'; import ThemeConfigProvider from '@components/ThemeConfigProvider'; import ThemeSegmented from '@components/ThemeSegmented'; import ThemeTextArea from '@components/ThemeTextArea'; import ToolEquityCountWrap, { type ToolEquityCountWrapRef } from '@components/ToolEquityCountWrap'; import { requestAdvanceDrawFirstStyleCategoryList, requestAdvanceDrawSubStyleConfigCategory, } from '@services/advanceDraw/config.ts'; import { requestComfyUIDrawGenerate, type RequestComfyUIDrawParams, } from '@services/advanceDraw/generate.ts'; import type { RequestModelRenderImageParams } from '@services/comfyUI.ts'; import { requestModelRenderImage } from '@services/comfyUI.ts'; import { getRandomNum, mergeDrawPromptStacks } from '@utils/ai.ts'; import { decodeImageUrl } from '@utils/string.ts'; import { getImageSizeInfo } from '@wander/base-utils'; import { CoolImage } from '@wander/common-components'; import { useAsyncEffect, useMount } from 'ahooks'; import { Collapse, Image, message, Typography } from 'antd'; import classNames from 'classnames/bind'; import type { CSSProperties } from 'react'; import { useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useSearchParams } from 'react-router-dom'; import type { ImageSelectorModalProps } from '@/components/ImageSelectorModal'; import UploadImageCard, { type UploadImageCardProps, type UploadImageCardRef, } from '@/components/UploadImageCard'; import { enlargeDownloadOptions } from '@/config/aiTool.ts'; import useGetConfigValue from '@/hooks/useGetConfigValue.ts'; import { ADVANCE_DRAW_DEFAULT_NEGATIVE_KEYWORDS } from '@/pages/AiTools/AdvanceDraw/constants.ts'; import type { GetAdvanceDrawLeafGenerateArgsByMidsType } from '@/pages/AiTools/AdvanceDraw/utils.ts'; import KjlResultQuickAccessBox from '@/pages/AiTools/components/KjlResultQuickAccessBox'; import ToggleGenerateInfoPopover from '@/pages/AiTools/components/ToggleInfoPanel'; import { lockingMaterialList } from '@/pages/AiTools/Draw/configs.ts'; import { modelRenderSpeedupKey, modelRenderToolKey, modelRenderToolName, TRACK_MODEL_RENDER_NAME, } from '@/pages/AiTools/ModelRender/config.ts'; import type { ModelRenderStyleCategoryGridRef } from '@/pages/AiTools/ModelRender/Operate/components/StyleCategoryGrid'; import ModelRenderStyleCategoryGrid from '@/pages/AiTools/ModelRender/Operate/components/StyleCategoryGrid'; import { useToolRouterStore } from '@/pages/AiTools/Router/store/createStore.ts'; import { useStore } from '@/store/createStore.ts'; import type { AdvanceDrawStyleCategoryItem } from '@/types/advanceDraw.ts'; import type { AiToolProcessSuccessResponse } from '@/types/ai'; import type { LockingMaterialType } from '@/types/draw'; import { LockingMaterialTypeEnum } from '@/types/draw'; import styles from './index.module.less'; const cx = classNames.bind(styles); const { Paragraph } = Typography; const { Panel } = Collapse; // 空间位置显示 type SpatialPositionListItem = { name: string; coverUrl: string; // 描述 description: string; }; const ModelRenderOperatePC = () => { const { t } = useTranslation(); const addBaseImage = useToolRouterStore((state) => state.addBaseImage); const { productType } = useStore((state) => state.productInfo); const [searchParams, setSearchParams] = useSearchParams(); // 介绍页显示 const [introduceLayoutShow, setIntroduceLayoutShow] = useState( productType === 'JKJL' && !searchParams.get('url'), ); // 步骤条ref const drawStepOperateLayoutRef = useRef<DrawStepOperateLayoutPcRef>(null); // 底图上传卡片ref const baseImageCardRef = useRef<UploadImageCardRef>(null); // 风格参考图ref const styleImageCardRef = useRef<UploadImageCardRef>(null); // 迁移内容的原图片效果图库 const imageSelectorWrapModalRef = useRef<ImageSelectorWrapModalRef>(null); // 锁定材质弹窗ref const materialIntroduceModalRef = useRef<MaterialIntroduceModalRef>(null); // 空间位置列表 const spatialPositionConfig = useGetConfigValue<Record<string, SpatialPositionListItem[]>>({ key: 'jzxz_model_render_spatial_config', }) || {}; // 风格类目配置 const styleCategoryMids: string[] = useGetConfigValue<string[][]>({ key: 'jzxz_model_render_style_categories_config', })?.map((value) => value[0]) || []; // 空间位置选中索引 const [selectPositionIndex, setSelectPositionIndex] = useState(0); // 空间位置类目选中索引 (类目可以切换 然后需要分开存储) const [spatialCategoryIndex, setSpatialCategoryIndex] = useState(0); // 高级风格类目 const [styleCategoryList, setStyleCategoryList] = useState<AdvanceDrawStyleCategoryItem[]>([]); // 锁定材质 const [lockingMaterialType, setLockingMaterialType] = useState<LockingMaterialType>('OFF'); // 描述词 const [description, setDescription] = useState(''); // 存储生成参数 const [generateParams, setGenerateParams] = useState({ baseImage: '', styleImage: '', styleAlias: [] as string[], }); // 刷新工具次数 const refreshToolEquityUserUseInfo = useStore((state) => state.refreshToolEquityUserUseInfo); // comfyUI 创作弹框-高级版 const generateComfyUiModalRef = useRef<AiToolGenerateModalRef<RequestComfyUIDrawParams>>(null); // comfyUI 创作弹框-精确 const generateComfyUiPreciseRenderingModalRef = useRef<AiToolGenerateModalRef<RequestModelRenderImageParams>>(null); // 工具次数ref const toolEquityCountWrapRef = useRef<ToolEquityCountWrapRef>(null); // 类目ref const styleCategoryGridRef = useRef<ModelRenderStyleCategoryGridRef>(null); // 图片上传成功 const onBaseImageFinish: ImageSelectorModalProps['onFinish'] = (item) => { baseImageCardRef.current?.setUploadImage(item); }; // 底图改变事件 const onBaseImageChange: UploadImageCardProps['onUploadImageChange'] = (uploadImage) => { if (uploadImage) { addBaseImage({ url: uploadImage.largeUrl, width: uploadImage.width, height: uploadImage.height, }); } else { addBaseImage(null); } }; // 响应-高级版 const onComfyUiGenerateSuccess = async (response: AiToolProcessSuccessResponse) => { try { const result = response.imageList[0]; // 刷新次数 refreshToolEquityUserUseInfo(modelRenderToolKey); const sizeInfo = await getImageSizeInfo(result); // 设置layout显示 drawStepOperateLayoutRef.current?.setGenerateImage({ url: result, ...sizeInfo, }); } catch (e) { console.error(e); } }; // 精确渲染 const generatePreciseRendering = () => { const baseImage = baseImageCardRef.current?.uploadImage; if (!baseImage) { return; } const styleImage = styleImageCardRef.current?.uploadImage; drawStepOperateLayoutRef.current?.setShowType('PREVIEW'); setGenerateParams({ baseImage: baseImage.largeUrl || '', styleImage: styleImage?.largeUrl || '', styleAlias: [], }); generateComfyUiPreciseRenderingModalRef.current?.generateTask({ seed: getRandomNum(), baseImageUrl: baseImage.largeUrl || '', }); }; // 高级生图渲染 const generateStandardRendering = (styleArgs: GetAdvanceDrawLeafGenerateArgsByMidsType) => { const baseImage = baseImageCardRef.current?.uploadImage; if (!baseImage) { return; } const styleImage = styleImageCardRef.current?.uploadImage; const { modelName = '', loraParamses = [], builtStyleReferImage, exactRender, styleAlias, promptPrefix = '', negativePromptPrefix = '', samplerName = 'euler', scheduler = 'normal', steps = 30, cfg = 3.5, } = styleArgs || {}; const dealPromptsInfo = mergeDrawPromptStacks({ prompts: { placeholder: description, keyword: description, }, promptsPrefix: { placeholder: '', keyword: `${promptPrefix},${spatialPositionConfig[styleCategoryList[spatialCategoryIndex].mid][selectPositionIndex].description},${styleAlias?.[0]}`, }, negativePromptsPrefix: { placeholder: '', keyword: negativePromptPrefix, }, defaultNegativeKeyword: ADVANCE_DRAW_DEFAULT_NEGATIVE_KEYWORDS, }); drawStepOperateLayoutRef.current?.setShowType('PREVIEW'); setGenerateParams({ baseImage: baseImage.largeUrl || '', styleImage: styleImage?.largeUrl || '', styleAlias: styleAlias || [], }); generateComfyUiModalRef.current?.generateTask({ // 精确渲染 exactRender: exactRender || false, baseImage: { url: baseImage.largeUrl, width: baseImage.width, height: baseImage.height, guidanceStart: 0, guidanceEnd: 1, weight: 0.6, model: 'XL/xinsir-controlnet-union-sdxl-1.0_promax.safetensors', ...((styleAlias || []).findIndex((value) => value.search('通用') > -1) > -1 ? { preprocessor: 'none', controlNetKey: 'fineOutline', } : { preprocessor: 'LineArtPreprocessor', controlNetKey: 'smoothSontours', }), enable: true, }, ...(styleImage ? { styleReferImage: { url: styleImage.largeUrl, weight: 0.6, guidanceStart: 0, guidanceEnd: 1, }, } : {}), sizeType: 'ULTRA_2K', seed: getRandomNum(), builtStyleReferImage, prompt: dealPromptsInfo.prompts.keyword, negativePrompt: dealPromptsInfo.negativePrompts.keyword, modelName, loraParamses, // 材质锁定配置项 lockingMaterialType, enableSpatialDepth: false, cfg, // 迭代步数 steps, // 采样器名称 samplerName, // 调度器 scheduler, }); }; // 点击开始创作 const onStepStart = () => { if (!toolEquityCountWrapRef.current?.verifyUseStatus()) { return; } const styleArgs = styleCategoryGridRef.current?.getComfyUIDrawLeafGenerateArgsByMids?.(); if (styleArgs === 'PreciseRendering') { generatePreciseRendering(); } else { generateStandardRendering(styleArgs as GetAdvanceDrawLeafGenerateArgsByMidsType); } }; // 点击一级类目 useAsyncEffect(async () => { let categoryList = await requestAdvanceDrawFirstStyleCategoryList(); categoryList = categoryList.filter((value) => styleCategoryMids.includes(value.mid)); if (categoryList[0].justCategory) { const subCategoryList = await requestAdvanceDrawSubStyleConfigCategory(categoryList[0].mid); // 替换当前类目下的子类目信息 categoryList.splice(0, 1, { ...categoryList[0], children: subCategoryList, }); } setStyleCategoryList(categoryList); }, []); useMount(() => { const url = decodeImageUrl(searchParams.get('url') || ''); const width = searchParams.get('width'); const height = searchParams.get('height'); // 工具快捷使用 if (url && height && width) { baseImageCardRef.current?.setUploadImage({ largeUrl: url, thumbUrl: url, width: Number(width), height: Number(height), }); setSearchParams({}); } }); // 第二步内容 const secondStepRender = ( <> <div className={cx('first_category_wrap')}> {styleCategoryList.map((value, index) => ( <div key={value.mid} className={cx('first_category_item', { active: index === spatialCategoryIndex, })} onClick={async () => { setSpatialCategoryIndex(index); styleCategoryGridRef.current?.setFirstCategoryIndex(index); if (!value.children && value.justCategory) { try { styleCategoryGridRef.current?.setSecondCategoryRequesting(true); const subCategoryList = await requestAdvanceDrawSubStyleConfigCategory(value.mid); // 替换当前类目下的子类目信息 setStyleCategoryList( styleCategoryList.map((value1, index1) => { if (index1 === index) { return { ...value1, children: subCategoryList, }; } return value1; }), ); styleCategoryGridRef.current?.setSecondCategoryRequesting(false); } catch (e) { styleCategoryGridRef.current?.setSecondCategoryRequesting(false); console.error(e); } } }} > {value.name} </div> ))} </div> <div className={cx('spatial_position_wrap')}> {spatialPositionConfig[styleCategoryList[spatialCategoryIndex]?.mid || '']?.map( (value, index) => ( <div className={cx('spatial_position_item', { active: index === selectPositionIndex, })} key={index} onClick={() => { setSelectPositionIndex(index); }} > <AiToolSquareCoverCard coverUrl={value.coverUrl} extra={<span className={cx('spatial_position_name')}>{value.name}</span>} /> </div> ), )} </div> </> ); // 第三步内容 const thirdStepRender = ( <> <ModelRenderStyleCategoryGrid ref={styleCategoryGridRef} categoryList={styleCategoryList} onCategoryListChange={(list) => { setStyleCategoryList(list); }} /> <div className={cx('step_title')} style={{ marginTop: 40 }}> 更多设置 </div> <div className={cx('step_sub_title')}> 上传风格参考图添加更多设置可以定制化生成对应风格,进一步加强生成图的风格准确性,此处做选填。 </div> <Collapse ghost expandIconPosition="end"> <Panel header="上传参考图(选填)" key="reference"> <div className={cx('reference_image_wrap')}> <UploadImageCard> {() => <UploadImageCard.Card hideDeleteBtn={false} ref={styleImageCardRef} />} </UploadImageCard> </div> </Panel> <Panel header="更多设置(选填)" key="more"> <div className={cx('more_settings_wrap')}> <ThemeConfigProvider themeConfigs={{ JKJL: { textArea: { borderColor: '#dfdfdf', borderWidth: '1px', }, segmented: { '--border-width': '1px', '--border-color': '#dfdfdf', } as CSSProperties, }, }} > <AiToolBlockItem title="描述词"> <ThemeTextArea placeholder="写下你的绘画想法创意" value={description} onChange={(e) => { setDescription(e.target.value); }} /> </AiToolBlockItem> <AiToolBlockItem title={ <span> {t('AiTools-Draw-ControlNet-BaseImage-WREs5')} <QuestionCircleOutlined style={{ marginLeft: 4 }} onClick={() => { materialIntroduceModalRef.current?.setModalStatus('INTRODUCE'); }} /> </span> } extra={ <ThemeSegmented block style={{ width: 180 }} value={lockingMaterialType} options={lockingMaterialList.map((item) => ({ label: t(item.labelKey), value: item.value, }))} onChange={(item) => { setLockingMaterialType(item.value); }} /> } /> </ThemeConfigProvider> </div> </Panel> </Collapse> </> ); // 生成参数弹窗 const generateParamsContent = ( <div> <ToggleGenerateInfoPanelItem title="创意描述"> {() => { return ( <Paragraph ellipsis={{ rows: 4 }}> <span style={{ margin: '10px 0 0', color: 'rgb(255 255 255 / 80%)' }}> {description || '无'} </span> </Paragraph> ); }} </ToggleGenerateInfoPanelItem> <ToggleGenerateInfoPanelItem title="创作类目" description={generateParams.styleAlias?.join('/')} /> <ToggleGenerateInfoPanelItem title="空间位置" description={ spatialPositionConfig[styleCategoryList[spatialCategoryIndex]?.mid || '']?.[ selectPositionIndex ].name || '' } /> <ToggleGenerateInfoPanelItem title="底图"> {(imageCardClassName) => { return ( <div className={imageCardClassName}> <Image src={generateParams.baseImage} preview width="100%" height={154} style={{ objectFit: 'contain', }} /> </div> ); }} </ToggleGenerateInfoPanelItem> {generateParams.styleImage && ( <ToggleGenerateInfoPanelItem title="参考图"> {(imageCardClassName) => { return ( <div className={imageCardClassName}> <Image src={generateParams.styleImage} preview width="100%" height={154} style={{ objectFit: 'contain', }} /> </div> ); }} </ToggleGenerateInfoPanelItem> )} <ToggleGenerateInfoPanelItem title="材质锁定" description={t(LockingMaterialTypeEnum[lockingMaterialType || 'OFF'])} /> </div> ); return ( <> <ToolVerticalIntroduceLayoutPC2 toolName={modelRenderToolName} description="一键AI渲染酷家乐室内设计模型,比传统渲染方式更加真实,细腻,高效~支持多种室内风格渲染!" show={introduceLayoutShow} onClickUseBtn={() => { setIntroduceLayoutShow(false); }} content={ <> <ToolVerticalIntroduceLayoutContent1 items={[ { beforeUrl: 'https://gd-hbimg.huaban.com/dc74bbd45daaaf4973d71e64785ed7e2d6cb0eed5ec75-7Gc6aa', afterUrl: 'https://gd-hbimg.huaban.com/63a044eec1c55566f7304e79d1f1c2828c51c8ba9d774-4jCT7E', }, { beforeUrl: 'https://gd-hbimg.huaban.com/ffefde120630092f0244bf346c1d974e51e5dd9bb5fe2-NvzNpK', afterUrl: 'https://gd-hbimg.huaban.com/2d776cae122ab64c90697906540a706664ce21809d1e6-XyYWf1', }, { beforeUrl: 'https://gd-hbimg.huaban.com/6519e79f2c37ee2a1b75025376b10f6d574edfc4f0d17-8ReO7g', afterUrl: 'https://gd-hbimg.huaban.com/82c0c13e8abcb63243697acde385fc569b9b3fd5ba214-nh471F', }, ]} /> </> } /> <UploadImageCard> {(uploadImage) => ( <> <DrawStepOperateLayoutPC trackToolName={TRACK_MODEL_RENDER_NAME} ref={drawStepOperateLayoutRef} downloadConfig={{ enlargeDownloadOptions, }} items={[ { title: '上传模型底图', subTitle: '大师级渲染,从上传底图开始!', content: ( <div className={cx('first_content')}> <UploadImageCard.Card style={{ minHeight: '100%', height: 'auto', }} ref={baseImageCardRef} onUploadImageChange={onBaseImageChange} enableKjlUpload uploadImageIcon={{ customUploadBtn: (className) => { return ( <div className={className} onClick={() => { imageSelectorWrapModalRef.current?.setModalStatus('SELECT_MODAL'); }} > {t('HuabanUploadBtn-rWrt')} </div> ); }, }} onScreenshotSuccess={(value) => { imageSelectorWrapModalRef.current?.setModalStatus('LEAFER_FRAME'); imageSelectorWrapModalRef.current?.onGenerateFrame({ width: value.width, height: value.height, url: value.largeUrl, }); setTimeout(() => { imageSelectorWrapModalRef.current?.setOperationType('CLIP_FRAME'); }, 600); }} hidden={!!uploadImage} /> <div className={cx('image_wrap')} hidden={!uploadImage}> <CoolImage placeholder={{ type: 'loadingIcon' }} className={cx('image')} style={{ objectFit: 'contain' }} src={uploadImage?.largeUrl} alt="" /> </div> <div className={cx('operator_btn_wrap')} hidden={!uploadImage}> <IconFont type="micro-icon-edit" className={cx('operator_icon')} onClick={() => { imageSelectorWrapModalRef.current?.setModalStatus('LEAFER_FRAME'); // 画板没有原图信息的时候 先创建画板 const originImageInfo = imageSelectorWrapModalRef.current?.getOriginalImageInfo(); if (!originImageInfo?.url && uploadImage) { imageSelectorWrapModalRef.current?.onGenerateFrame({ url: uploadImage?.largeUrl, width: uploadImage.width, height: uploadImage.height, }); } }} /> <IconFont type="micro-icon-trash-can" className={cx('operator_icon')} onClick={() => { baseImageCardRef.current?.setUploadImage(null); imageSelectorWrapModalRef.current?.clearFrame(); }} /> </div> </div> ), beforeNextStep: async () => { if (!baseImageCardRef.current?.uploadImage) { message.warn('请先上传底图'); return false; } return true; }, }, { title: '选择空间位置', subTitle: '选择正确的位置可以确保生成图更准确。', content: secondStepRender, }, { title: '选择渲染风格', subTitle: '选择想要生成的风格大模型,可以让生成结果更偏向自己的喜好。', content: thirdStepRender, }, ]} onStepStart={onStepStart} uploadImage={uploadImage} resultExtra={ <> {/* 快捷使用 */} <KjlResultQuickAccessBox className={cx('quick_access_box')} extraBottomItems={[ { title: '迭代渲染', iconKey: 'micro-icon-iterative-render', onClick: () => { const generateImage = drawStepOperateLayoutRef.current?.generateImage; if (generateImage) { drawStepOperateLayoutRef.current.setShowType('STEP'); drawStepOperateLayoutRef.current.setCurrent(0); baseImageCardRef.current?.setUploadImage({ thumbUrl: generateImage.url, largeUrl: generateImage.url, width: generateImage.width, height: generateImage.height, }); } }, }, ]} /> {/* 参数明细 */} <ToggleGenerateInfoPopover placement="leftTop" className={cx('generate_params_wrap')} content={generateParamsContent} > {(open) => { return <IconFont type={open ? 'micro-icon-close' : 'micro-icon-tip'} />; }} </ToggleGenerateInfoPopover> </> } stepFooterExtra={ <ToolEquityCountWrap toolKey={modelRenderToolKey} showToolName={modelRenderToolName} trackToolName={TRACK_MODEL_RENDER_NAME} ref={toolEquityCountWrapRef} > <ToolBenefitOperator style={{ marginTop: 8, }} toolKey={modelRenderToolKey} trackToolName={TRACK_MODEL_RENDER_NAME} showToolEquityInfo={() => { toolEquityCountWrapRef.current?.showToolEquityInfo(); }} showToolCountUsageIntro={() => { toolEquityCountWrapRef.current?.showToolCountUsageIntro(); }} showToolBuyCount={() => { toolEquityCountWrapRef.current?.showToolBuyCount(); }} /> </ToolEquityCountWrap> } /> </> )} </UploadImageCard> {/* 迁移内容的原图片效果图库 */} <ImageSelectorWrapModal ref={imageSelectorWrapModalRef} queryTagImages={{ categoryList: [ { name: '室内', tag: '室内底图', sourceType: 'JZXZ', }, ], introduce: t('AiTools-DecorationDesign-Operate-pc-f4eJ'), modalTitle: t('AiTools-Draw-ControlNet-BaseImage-b2tNh'), iconClassName: cx('style_refer_image'), }} onFinish={onBaseImageFinish} hideDiyDraw /> <AiToolGenerateModal displayType="MASK" className={cx('generate_mask_container')} customerRef={generateComfyUiModalRef} toolKey={modelRenderToolKey} trackToolName={TRACK_MODEL_RENDER_NAME} request={requestComfyUIDrawGenerate} speedupKey={modelRenderSpeedupKey} pollingConfig={{ processingType: 'COMFYUI_COMPOSE', imageDetectMode: 'NONE', }} onGenerateSuccess={onComfyUiGenerateSuccess} onCancel={() => { // 蒙层关闭 回到进度展示 drawStepOperateLayoutRef.current?.setShowType('STEP'); }} /> {/* 精确渲染 */} <AiToolGenerateModal displayType="MASK" className={cx('generate_mask_container')} customerRef={generateComfyUiPreciseRenderingModalRef} toolKey={modelRenderToolKey} trackToolName={TRACK_MODEL_RENDER_NAME} request={requestModelRenderImage} speedupKey={modelRenderSpeedupKey} pollingConfig={{ processingType: 'COMFYUI_COMPOSE', imageDetectMode: 'NONE', }} onGenerateSuccess={onComfyUiGenerateSuccess} onCancel={() => { // 蒙层关闭 回到进度展示 drawStepOperateLayoutRef.current?.setShowType('STEP'); }} /> <MaterialIntroduceModal ref={materialIntroduceModalRef} /> </> ); }; export default ModelRenderOperatePC; 如果secondCategoryIndex === -1,这部分隐藏 <div className={cx('step_title')} style={{ marginTop: 40 }}> 更多设置 </div> <div className={cx('step_sub_title')}> 上传风格参考图添加更多设置可以定制化生成对应风格,进一步加强生成图的风格准确性,此处做选填。 </div> <Collapse ghost expandIconPosition="end"> <Panel header="上传参考图(选填)" key="reference"> <div className={cx('reference_image_wrap')}> <UploadImageCard> {() => <UploadImageCard.Card hideDeleteBtn={false} ref={styleImageCardRef} />} </UploadImageCard> </div> </Panel> <Panel header="更多设置(选填)" key="more"> <div className={cx('more_settings_wrap')}> <ThemeConfigProvider themeConfigs={{ JKJL: { textArea: { borderColor: '#dfdfdf', borderWidth: '1px', }, segmented: { '--border-width': '1px', '--border-color': '#dfdfdf', } as CSSProperties, }, }} > <AiToolBlockItem title="描述词"> <ThemeTextArea placeholder="写下你的绘画想法创意" value={description} onChange={(e) => { setDescription(e.target.value); }} /> </AiToolBlockItem> <AiToolBlockItem title={ <span> {t('AiTools-Draw-ControlNet-BaseImage-WREs5')} <QuestionCircleOutlined style={{ marginLeft: 4 }} onClick={() => { materialIntroduceModalRef.current?.setModalStatus('INTRODUCE'); }} /> </span> } extra={ <ThemeSegmented block style={{ width: 180 }} value={lockingMaterialType} options={lockingMaterialList.map((item) => ({ label: t(item.labelKey), value: item.value, }))} onChange={(item) => { setLockingMaterialType(item.value); }} /> } /> </ThemeConfigProvider> </div> </Panel> </Collapse>完整修改
07-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值