PC QUICKSTEPS 2/E

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版、作者信息和本声明。否则将追究法律责任。 http://blog.youkuaiyun.com/topmvp - topmvp
Step-by-Step, Full-Color Graphics!

Get started using your PC right away--the QuickSteps way. Color screenshots and clear instructions show you how to manage, customize, and troubleshoot your desktop or laptop PC. Follow along and learn how to install and configure hardware and software, use Windows Vista, manage files, access and navigate the Internet, set up a home network, secure your PC, and much more. Get the book that gets you up and running on your PC in no time.

Use these handy guideposts:
*Shortcuts for accomplishing common tasks
*Need-to-know facts in concise narrative
*Helpful reminders or alternate ways of doing things
*Bonus information related to the topic being covered
*Errors and pitfalls to avoid

http://rapidshare.com/files/171627261/0071599835.rar
http://depositfiles.com/files/u01bwon1s
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 type { MaterialIntroduceModalRef } from '@aiComponents/MaterialIntroduceModal'; import MaterialIntroduceModal from '@aiComponents/MaterialIntroduceModal'; import ToggleGenerateInfoPanelItem from '@aiComponents/ToggleInfoPanel/PanelItem.tsx'; import { QuestionCircleOutlined } from '@ant-design/icons'; import IconFont from '@components/Iconfont'; import type { ImageSelectorWrapModalRef } from '@components/ImageSelectorWrapModal'; 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, { 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 type { UploadImageType } from '@/components/UploadImageCard'; 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 scenarioListItem = [ { name: '建筑', coverUrl: 'https://gd-hbimg.huaban.com/bdc46d3401c6319e58749b275b8a00f4d24716e018ed64-PyRBDr_fw1200webp', }, { name: '室内', coverUrl: 'https://gd-hbimg.huaban.com/d113fdba55b570c14f9e6dd85053e20fe66e59f5cd9c6-KWo2yS_fw1200webp', }, { name: '景观', coverUrl: 'https://gd-hbimg.huaban.com/c6b5104002f69d75dca57f072257f94222f688d531c69-bNzUzn_fw1200webp', }, { name: '规划', coverUrl: 'https://gd-hbimg.huaban.com/31401d2c21663350a49df3181f9b34ee2dbaa6a9b8cd9-MMDggY_fw1200webp', }, ]; 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 [preciseRender, setPreciseRender] = useState(true); // 建筑学长-选择模型场景index const [modelScenarioActiveIndex, setModelScenarioActiveIndex] = useState(0); // 图片上传成功 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, imageGenerateNum: 1, }); }; // 点击开始创作 const onStepStart = () => { if (!toolEquityCountWrapRef.current?.verifyUseStatus()) { return; } const styleArgs = styleCategoryGridRef.current?.getComfyUIDrawLeafGenerateArgsByMids?.(); if (preciseRender) { 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 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?.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> </> ); }; // 第二步内容 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 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); }} /> {!preciseRender && ( <> <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) => ( <> <ProductAuth productTypes={['JKJL']}> <DrawStepOperateLayoutPC trackToolName={TRACK_MODEL_RENDER_NAME} ref={drawStepOperateLayoutRef} downloadConfig={{ enlargeDownloadOptions, }} items={[ { title: '上传模型底图', subTitle: '大师级渲染,从上传底图开始!', content: firstStepRender(uploadImage), 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> } /> </ProductAuth> <ProductAuth productTypes={['JZXZ']}> <DrawStepOperateLayoutPC trackToolName={TRACK_MODEL_RENDER_NAME} ref={drawStepOperateLayoutRef} downloadConfig={{ enlargeDownloadOptions, }} items={[ { title: '选择模型场景', subTitle: '请根据实际情况选择合适的渲染场景', content: ( <> <div className={cx('scenario_wrap')}> {scenarioListItem.map((item, index) => ( <div key={index} className={cx('scenario_item', { active: modelScenarioActiveIndex === index, })} onClick={() => { setModelScenarioActiveIndex(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; } 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> } /> </ProductAuth> </> )} </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; 步骤一直显示的是4步 ,只是 modelScenarioActiveIndex !== 1 跳过第三步直接到第四步
07-22
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、付费专栏及课程。

余额充值