Files
JuYou/API/static/web/assets/ProductImageWorkbenchView-DXsz9QbU.js
T
2026-08-25 17:59:42 +08:00

2 lines
16 KiB
JavaScript

import{d as we,u as ke,B as me,z as Ce,o as v,q as J,aa as Re,c as _,a as n,t as x,e as c,b as r,s as M,p as j,G as te,N as fe,j as ce,f as pe,k as s,A as R,C as Ie,I as Ue,ab as de,y as Pe,w as ge,n as Le,F as he,v as be,r as ze,H as Me,E as Te}from"./index-p1BAR2Hc.js";import{X as xe,A as X,P as _e,c as Be,T as $e,I as ae,D as De,s as Ee,G as Ae,j as Oe}from"./icons-CbZw_MCi.js";import{C as Se,a as ve}from"./CreativeSelect-CikGCVMP.js";import{A as je}from"./AssetPromptEditor-bfTzC_cs.js";import{L as Fe}from"./LoadingMedia-q1A6xJc7.js";import{d as Ne}from"./download-BrY2jnvm.js";import{_ as Ve}from"./_plugin-vue_export-helper-DlAUqK2U.js";import{f as Ge}from"./datetime-P3V4sQaP.js";const We={class:"image-stack"},He=["src"],qe={key:2,class:"mark-toolbar"},Xe=["disabled"],Je=["disabled"],Ye=["disabled"],Ke=we({__name:"ProductImageViewer",props:{modelValue:{type:Boolean},images:{},initialId:{},referenceBusy:{type:Boolean}},emits:["update:modelValue","reference"],setup(m,{emit:p}){const f=m,$=p,C=ke(),U=s(0),V=s(""),i=s(),o=s(),g=s(!1),h=s("brush"),P=s("#ef5b50"),D=s(4),T=s(!1),b=s({x:0,y:0}),B=s(),w=s([""]),y=s(0),E=s(!1);let k="";const I=R(()=>f.images[U.value]);function F(){$("update:modelValue",!1)}function N(){const t=f.images.findIndex(e=>e.id===f.initialId);U.value=t>=0?t:0,g.value=!1,w.value=[""],y.value=0,E.value=!1,G()}async function G(){k&&URL.revokeObjectURL(k),k="",V.value="";const t=I.value;if(t)try{if(t.mediaId){const e=await Ie.media(t.mediaId);k=URL.createObjectURL(e),V.value=k}else V.value=t.url}catch{V.value=t.url,C.error("图片读取失败")}}function W(){!i.value||!o.value||(o.value.width=i.value.clientWidth,o.value.height=i.value.clientHeight,E.value=!1)}function L(){var e;const t=(e=o.value)==null?void 0:e.getContext("2d");return t?(t.lineCap="round",t.lineJoin="round",t.strokeStyle=P.value,t.lineWidth=D.value,t):null}function Y(t){const e=o.value.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top}}function ne(t){var e;if(!(!g.value||!o.value)&&(b.value=Y(t),T.value=!0,B.value=(e=L())==null?void 0:e.getImageData(0,0,o.value.width,o.value.height),o.value.setPointerCapture(t.pointerId),h.value==="brush")){const a=L();a==null||a.beginPath(),a==null||a.moveTo(b.value.x,b.value.y)}}function K(t){if(!T.value)return;const e=L();if(!e||!o.value)return;const a=Y(t);if(h.value==="brush"){e.lineTo(a.x,a.y),e.stroke();return}B.value&&e.putImageData(B.value,0,0),h.value==="rect"?e.strokeRect(b.value.x,b.value.y,a.x-b.value.x,a.y-b.value.y):le(e,b.value.x,b.value.y,a.x,a.y)}function Q(t){T.value&&(K(t),T.value=!1,B.value=void 0,H())}function le(t,e,a,u,d){const l=Math.atan2(d-a,u-e),z=Math.max(10,D.value*3);t.beginPath(),t.moveTo(e,a),t.lineTo(u,d),t.lineTo(u-z*Math.cos(l-Math.PI/6),d-z*Math.sin(l-Math.PI/6)),t.moveTo(u,d),t.lineTo(u-z*Math.cos(l+Math.PI/6),d-z*Math.sin(l+Math.PI/6)),t.stroke()}function Z(){var e,a;const t=(a=(e=o.value)==null?void 0:e.getContext("2d"))==null?void 0:a.getImageData(0,0,o.value.width,o.value.height).data;return!t||!t.some(u=>u!==0)}function A(){E.value=!Z()}function H(){o.value&&(w.value=w.value.slice(0,y.value+1),w.value.push(o.value.toDataURL()),y.value=w.value.length-1,A())}function O(t){const e=o.value,a=e==null?void 0:e.getContext("2d");if(!e||!a)return;if(a.clearRect(0,0,e.width,e.height),!t){A();return}const u=new ae;u.onload=()=>{a.drawImage(u,0,0,e.width,e.height),A()},u.src=t}function oe(){y.value>0&&(y.value--,O(w.value[y.value]))}function se(){y.value<w.value.length-1&&(y.value++,O(w.value[y.value]))}function ie(){var t;!o.value||Z()||((t=o.value.getContext("2d"))==null||t.clearRect(0,0,o.value.width,o.value.height),H())}function q(t){U.value=(U.value+t+f.images.length)%f.images.length,g.value=!1,w.value=[""],y.value=0,E.value=!1,G()}function re(){return new Promise((t,e)=>{if(!i.value||!o.value)return e(new Error("图片尚未加载完成"));const a=document.createElement("canvas");a.width=i.value.naturalWidth,a.height=i.value.naturalHeight;const u=a.getContext("2d");if(!u)return e(new Error("图片编辑器初始化失败"));try{u.drawImage(i.value,0,0,a.width,a.height),u.drawImage(o.value,0,0,a.width,a.height)}catch{return e(new Error("图片读取失败"))}a.toBlob(d=>d?t(new File([d],`reference-${I.value.id}.png`,{type:"image/png"})):e(new Error("图片合成失败")),"image/png")})}async function ue(){if(!(!I.value||f.referenceBusy))try{$("reference",await re())}catch(t){C.error(t instanceof Error?t.message:"图片读取失败")}}async function S(){if(I.value)try{await Ne(I.value.mediaId,I.value.url,I.value.filename||`图片生成-${I.value.id}.png`)}catch{C.error("下载失败")}}return me(()=>f.modelValue,t=>{t&&(N(),Ue(W))}),me(()=>f.initialId,()=>{f.modelValue&&N()}),Ce(()=>{k&&URL.revokeObjectURL(k)}),(t,e)=>(v(),J(Re,{to:"body"},[m.modelValue&&I.value?(v(),_("div",{key:0,class:"product-image-viewer",onClick:pe(F,["self"])},[n("header",null,[e[8]||(e[8]=n("strong",null,"图片生成",-1)),n("span",null,x(U.value+1)+" / "+x(m.images.length),1),n("button",{type:"button",onClick:F},[c(r(xe),{size:22})])]),m.images.length>1?(v(),_("button",{key:0,class:"nav prev",type:"button",onClick:e[0]||(e[0]=a=>q(-1))},[c(r(X),{size:24})])):M("",!0),n("main",null,[n("div",We,[n("img",{ref_key:"image",ref:i,src:V.value,alt:"大图预览",onLoad:W},null,40,He),n("canvas",{ref_key:"canvas",ref:o,class:j({editing:g.value}),onPointerdown:ne,onPointermove:K,onPointerup:Q,onPointercancel:Q},null,34)])]),m.images.length>1?(v(),_("button",{key:1,class:"nav next",type:"button",onClick:e[1]||(e[1]=a=>q(1))},[c(r(X),{class:"next-icon",size:24})])):M("",!0),g.value?(v(),_("div",qe,[n("button",{type:"button",class:j({active:h.value==="brush"}),onClick:e[2]||(e[2]=a=>h.value="brush")},[c(r(_e),{size:17})],2),n("button",{type:"button",class:j({active:h.value==="rect"}),onClick:e[3]||(e[3]=a=>h.value="rect")},[c(r(Be),{size:17})],2),n("button",{type:"button",class:j({active:h.value==="arrow"}),onClick:e[4]||(e[4]=a=>h.value="arrow")},[c(r(X),{class:"next-icon",size:17})],2),te(n("input",{"onUpdate:modelValue":e[5]||(e[5]=a=>P.value=a),type:"color"},null,512),[[fe,P.value]]),te(n("input",{"onUpdate:modelValue":e[6]||(e[6]=a=>D.value=a),type:"range",min:"2",max:"14"},null,512),[[fe,D.value,void 0,{number:!0}]]),n("button",{type:"button",disabled:y.value===0,onClick:oe},[c(r(X),{size:17})],8,Xe),n("button",{type:"button",disabled:y.value>=w.value.length-1,onClick:se},[c(r(X),{class:"next-icon",size:17})],8,Je),n("button",{type:"button",onClick:ie},[c(r($e),{size:17})])])):M("",!0),n("footer",null,[n("button",{type:"button",class:j({active:g.value}),onClick:e[7]||(e[7]=a=>g.value=!g.value)},[c(r(_e),{size:17}),e[9]||(e[9]=ce("标记",-1))],2),n("button",{type:"button",disabled:m.referenceBusy,onClick:ue},[c(r(ae),{size:17}),ce(x(m.referenceBusy?"处理中":"作为参考图"),1)],8,Ye),n("button",{type:"button",onClick:S},[c(r(De),{size:17}),e[10]||(e[10]=ce("下载",-1))])])])):M("",!0)]))}}),Qe=Ve(Ke,[["__scopeId","data-v-96be3514"]]),ye=m=>m.data.data,ee={generate:m=>{const p=new FormData;return p.append("prompt",m.prompt),p.append("model_id",m.model_id),p.append("aspect_ratio",m.aspect_ratio),p.append("resolution",m.resolution),m.references.forEach(f=>p.append("references",f,f.name)),de.post("/product-images/generations",p,{timeout:0,headers:{"Content-Type":"multipart/form-data"}}).then(ye)},generations:()=>de.get("/product-images/generations").then(ye),removeGeneration:m=>de.delete(`/product-images/generations/${m}`)},Ze={class:"product-workbench"},et={class:"panel-block product-settings"},tt={class:"product-settings__body"},at={class:"product-field product-field--prompt"},nt={class:"prompt-editor-wrap"},lt={class:"prompt-count"},ot={class:"reference-section"},st={class:"reference-grid"},it=["onClick"],rt=["src","alt"],ut=["title","onClick"],ct=["disabled"],dt={class:"generation-parameters"},vt={class:"generation-parameters__grid"},pt={class:"product-settings__footer"},mt={class:"generation-button__content"},ft={class:"generation-button__action"},gt={key:0,class:"generation-button__price"},ht={class:"panel-block product-results"},bt={class:"panel-block__header"},_t={class:"product-results__body"},yt=["disabled","onClick"],wt={key:1,class:"result-card__state"},kt=["title"],Ct={class:"result-card__meta"},It=["title","onClick"],xt={key:0,class:"product-results__empty"},$t=we({__name:"ProductImageWorkbenchView",setup(m){const p=ke(),f=s({styles:[],models:[],prices:[]}),$=s(""),C=s(""),U=s("9:21"),V=s("1k"),i=s([]),o=s([]),g=s(!0),h=s(!1),P=s(-1),D=s(!1),T=s();let b;const B=R(()=>f.value.models.filter(t=>t.model_type==="image").map(t=>({label:t.channel_name?`【${t.channel_name}${t.name}`:t.name,value:t.id}))),w=["1:1","3:4","4:3","9:16","9:21","16:9"].map(t=>({label:t,value:t})),y=["1k","2k","4k"].map(t=>({label:t,value:t})),E=R(()=>o.value.filter(t=>t.public_url)),k=R(()=>[...E.value.map(t=>({id:t.task_id,mediaId:t.media_asset_id,url:t.public_url,prompt:t.prompt})),...i.value.map(t=>({id:t.id,url:t.url,prompt:t.name,filename:t.name}))]),I=R(()=>k.value[P.value]),F=R({get:()=>P.value>=0,set:t=>{t||q()}}),N=R(()=>o.value.some(t=>L.has(t.status))),G=R(()=>[...$.value].length),W=R(()=>{var e;const t=(e=f.value.prices)==null?void 0:e.find(a=>a.model_id===C.value&&a.price_key.toLowerCase()===V.value.toLowerCase());return t?Number(t.price).toFixed(2):""}),L=new Set(["pending_submission","submitting","submitted","processing","result_ready","downloading","cancel_requested"]),Y=R(()=>i.value.map(t=>({id:t.id,project_id:"product-images",asset_type:"custom",name:t.name,image_url:t.url,user_edited:!1})));async function ne(){var t;g.value=!0;try{const[e,a]=await Promise.all([Ie.options(),ee.generations()]);f.value=e,o.value=a,C.value||(C.value=((t=B.value[0])==null?void 0:t.value)||""),H()}catch(e){S(e,"加载图片生成失败")}finally{g.value=!1}}function K(){var t;!h.value&&i.value.length<4&&((t=T.value)==null||t.click())}function Q(t){const e=t.target,a=Array.from(e.files||[]);if(e.value="",!a.length)return;const u=new Set(i.value.map(d=>d.name));for(const d of a){if(i.value.length>=4)break;if(!d.type.startsWith("image/")){p.warning("仅支持上传图片");continue}if(u.has(d.name)){p.warning(`参考图名称重复:${d.name}`);continue}u.add(d.name),i.value.push({id:`${Date.now()}-${Math.random()}`,file:d,name:d.name,url:URL.createObjectURL(d)})}}function le(t){const e=i.value.findIndex(u=>u.id===t);if(e<0)return;const[a]=i.value.splice(e,1);URL.revokeObjectURL(a.url),$.value=$.value.replaceAll(`@${a.name}`,"")}async function Z(){if(!$.value.trim()){p.warning("请输入图片生成提示词");return}if(G.value>5e3){p.warning("提示词不能超过 5000 个字符");return}if(!C.value){p.warning("请选择图片模型");return}h.value=!0;try{await ee.generate({prompt:$.value,model_id:C.value,aspect_ratio:U.value,resolution:V.value,references:i.value.map(t=>t.file)}),h.value=!1,p.success("图片生成任务已提交"),await A()}catch(t){S(t,"提交生成失败")}finally{h.value=!1}}async function A(){try{o.value=await ee.generations(),H()}catch(t){O(),S(t,"刷新效果图失败")}}function H(){N.value&&b===void 0?b=window.setInterval(A,4e3):N.value||O()}function O(){b!==void 0&&window.clearInterval(b),b=void 0}async function oe(t){try{const e=t.public_url?"效果图":"生成记录";await Te.confirm(`删除后无法恢复,确定删除这条${e}吗?`,`删除${e}`,{confirmButtonText:"删除",cancelButtonText:"取消",type:"warning"}),await ee.removeGeneration(t.task_id),o.value=o.value.filter(a=>a.task_id!==t.task_id),q(),p.success("效果图已删除")}catch(e){e!=="cancel"&&e!=="close"&&S(e,"删除效果图失败")}}function se(t){const e=k.value.findIndex(a=>a.id===t.task_id);e>=0&&(P.value=e)}function ie(t){const e=k.value.findIndex(a=>a.id===t.id);e>=0&&(P.value=e)}function q(){P.value=-1}function re(t){if(i.value.length>=4){p.warning("参考图最多 4 张");return}const e=t.name||`参考图-${Date.now()}.png`;i.value.push({id:`${Date.now()}-${Math.random()}`,file:t,name:e,url:URL.createObjectURL(t)}),p.success("已加入参考图")}function ue(){i.value.forEach(t=>URL.revokeObjectURL(t.url)),i.value=[]}function S(t,e){const a=Le(t);p.error(a.message,a.copyText,e)}return Pe(ne),Ce(()=>{O(),ue()}),(t,e)=>{const a=ze("el-button"),u=Me("loading");return v(),J(Se,{class:"product-workbench-shell"},{default:ge(()=>{var d;return[n("div",Ze,[n("section",et,[e[11]||(e[11]=n("header",{class:"panel-block__header"},[n("strong",null,"生成设置")],-1)),te((v(),_("div",tt,[n("label",at,[e[5]||(e[5]=n("span",null,"提示词",-1)),n("div",nt,[c(je,{modelValue:$.value,"onUpdate:modelValue":e[0]||(e[0]=l=>$.value=l),assets:Y.value,variant:"drama-storyboard","floating-preview":"",placeholder:"输入提示词,输入 @ 插入参考图"},null,8,["modelValue","assets"]),n("small",lt,x(G.value)+" / 5000",1)])]),n("section",ot,[n("header",null,[e[6]||(e[6]=n("strong",null,"参考图",-1)),n("small",null,x(i.value.length)+" / 4 张",1)]),n("div",st,[(v(!0),_(he,null,be(i.value,l=>(v(),_("div",{key:l.id,class:"reference-item",onClick:z=>ie(l)},[n("img",{src:l.url,alt:l.name},null,8,rt),n("button",{type:"button",title:`删除 ${l.name}`,onClick:pe(z=>le(l.id),["stop"])},[c(r(xe),{size:16})],8,ut)],8,it))),128)),n("button",{type:"button",class:"reference-add",disabled:i.value.length>=4,onClick:K},[c(r(Ee),{size:22}),e[7]||(e[7]=n("span",null,"添加图片",-1))],8,ct)]),n("input",{ref_key:"fileInput",ref:T,type:"file",accept:"image/jpeg,image/png,image/webp",multiple:"",hidden:"",onChange:Q},null,544)]),n("section",dt,[e[8]||(e[8]=n("strong",null,"生成参数",-1)),n("div",vt,[c(ve,{modelValue:U.value,"onUpdate:modelValue":e[1]||(e[1]=l=>U.value=l),options:r(w),placement:"top-start",placeholder:"比例"},null,8,["modelValue","options"]),c(ve,{modelValue:V.value,"onUpdate:modelValue":e[2]||(e[2]=l=>V.value=l),options:r(y),placement:"top-start",placeholder:"分辨率"},null,8,["modelValue","options"])]),c(ve,{modelValue:C.value,"onUpdate:modelValue":e[3]||(e[3]=l=>C.value=l),options:B.value,placement:"top-start",placeholder:"请选择图片模型"},null,8,["modelValue","options"])])])),[[u,g.value]]),n("footer",pt,[c(a,{type:"primary",loading:h.value,disabled:g.value,onClick:Z},{default:ge(()=>[n("span",mt,[n("span",ft,[c(r(Ae),{size:17}),e[9]||(e[9]=n("strong",null,"开始生成",-1))]),W.value?(v(),_("small",gt,[n("b",null,x(W.value),1),e[10]||(e[10]=n("span",null,"积分",-1))])):M("",!0)])]),_:1},8,["loading","disabled"])])]),n("section",ht,[n("header",bt,[e[12]||(e[12]=n("strong",null,"效果图",-1)),n("small",null,x(o.value.length)+" 条",1)]),te((v(),_("div",_t,[(v(!0),_(he,null,be(o.value,l=>(v(),_("article",{key:l.task_id,class:j(["result-card",{"has-image":l.public_url}])},[n("button",{type:"button",class:"result-card__preview",disabled:!l.public_url,onClick:z=>se(l)},[l.public_url?(v(),J(Fe,{key:0,type:"image",src:l.public_url,alt:"图片生成效果"},null,8,["src"])):(v(),_("span",wt,[r(L).has(l.status)?(v(),J(r(Oe),{key:0,class:"is-spinning",size:26})):(v(),J(r(ae),{key:1,size:26})),n("b",null,x(r(L).has(l.status)?l.error_message?"结果同步中":"生成中":"生成失败"),1),l.error_message?(v(),_("small",{key:2,title:l.error_message},x(l.error_message),9,kt)):M("",!0)])),n("span",Ct,[n("strong",null,x(l.model_name||"图片模型"),1),n("time",null,x(r(Ge)(l.created_at)),1)])],8,yt),!r(L).has(l.status)||l.error_message?(v(),_("button",{key:0,type:"button",class:"result-card__delete",title:l.public_url?"删除效果图":"删除生成记录",onClick:pe(z=>oe(l),["stop"])},[c(r($e),{size:17})],8,It)):M("",!0)],2))),128)),!g.value&&!o.value.length?(v(),_("div",xt,[c(r(ae),{size:40}),e[13]||(e[13]=n("strong",null,"还没有效果图",-1)),e[14]||(e[14]=n("p",null,"完成左侧配置后开始生成。",-1))])):M("",!0)])),[[u,g.value]])])]),c(Qe,{modelValue:F.value,"onUpdate:modelValue":e[4]||(e[4]=l=>F.value=l),images:k.value,"initial-id":(d=I.value)==null?void 0:d.id,"reference-busy":D.value,onReference:re},null,8,["modelValue","images","initial-id","reference-busy"])]}),_:1})}}}),Bt=Ve($t,[["__scopeId","data-v-089063cf"]]);export{Bt as default};