2 lines
18 KiB
JavaScript
2 lines
18 KiB
JavaScript
import{d as je,o as qe,q as Oe,a as u,c as i,b as Ke,e as a,F as se,r as te,t as r,w as Ve,v as Ye,f as h,u as _e,n as Qe,g as p,h as j,i as q,E as v,_ as We,j as Xe,k as Ze}from"./pywebview-B8lwamDf.js";import{B as es,H as ss,I as ts,v as ye,J as as,K as ls,L as ns,s as rs,M as os,N as us,F as is,O as cs}from"./java-modules-B9jblDzU.js";import{e as ds}from"./brand-DE-sObfq.js";import{c as fs}from"./categorized-timers-JPA-olTr.js";const vs={class:"page-shell module-page"},gs={class:"main-content"},ps={class:"left-panel"},hs={class:"upload-zone"},ks={class:"selected-files"},_s={key:0},ys={class:"condition-card"},Is={class:"switch-row"},ws={class:"run-row"},Ss=["disabled"],Ps=["disabled"],Cs={key:0,class:"parse-card"},bs={key:1,class:"queue-payload"},ms={class:"right-panel"},Ns={class:"task-list-wrap"},Fs={class:"clean-result-summary"},Ts={class:"summary-card"},Es={class:"summary-card"},Rs={class:"summary-card"},As={class:"summary-card"},Ds={class:"result-list-wrap"},Us={key:0,class:"empty-tasks"},xs={key:1,class:"task-list clean-result-list"},$s={class:"left"},Ms={class:"id"},Gs={class:"files"},zs={class:"files"},Ls={class:"files"},Bs={class:"files"},Hs={key:0,class:"files result-hint"},Js={key:1,class:"file-progress"},js={class:"file-progress-meta"},qs={class:"file-progress-track"},Os={key:0,class:"file-progress-count"},Ks={class:"task-right"},Vs={class:"status running"},Ys=["onClick"],Qs={class:"result-list-wrap"},Ws={key:0,class:"empty-tasks"},Xs={key:1,class:"task-list clean-result-list"},Zs={class:"left"},et={class:"id"},st={class:"files"},tt={class:"files"},at={class:"files"},lt={key:0,class:"files"},nt={key:1,class:"files result-hint"},rt={key:2,class:"file-progress"},ot={class:"file-progress-meta"},ut={class:"file-progress-track"},it={key:0,class:"file-progress-count"},ct={key:3,class:"files"},dt={class:"task-right"},ft=["onClick"],vt=["onClick"],gt=3e3,pt=je({__name:"BrandSimilarAsinTab",setup(kt){const D=p([]),m=p([]),I=p(null),w=p(null),U=p(!1),x=p(!1),O=p(!1),S=p(""),d=p([]),c=p([]),k=p(null),K=p(!1);let N=null,ae=0,F=!1;const T=fs("similar-asin"),E=p({pendingTaskCount:0,processedTaskCount:0,successTaskCount:0,failedTaskCount:0}),f=p([]),_=p({}),R=j(()=>I.value||w.value),V=j(()=>{const e=I.value;return!e?.taskId||f.value.some(t=>t.taskId===e.taskId)?null:{taskId:e.taskId,sourceFilename:e.sourceFilename,rowCount:e.acceptedRows,taskStatus:"PENDING",success:!1}}),le=j(()=>{const e=new Set([...d.value,...c.value]),s=f.value.filter(l=>{const n=y(l);return l.taskId!=null&&(e.has(l.taskId)||n==="RUNNING"||n==="PENDING")}).map(l=>re(l));for(const[l,n]of Object.entries(_.value)){const o=Number(l);!Number.isFinite(o)||o<=0||!e.has(o)&&y(n)!=="RUNNING"&&y(n)!=="PENDING"||s.some(g=>g.taskId===o)||s.push(re(n))}return V.value?s.some(l=>l.taskId===V.value?.taskId)?s:[V.value,...s]:s}),ne=j(()=>f.value.filter(e=>{const s=y(e);return s!=="RUNNING"&&s!=="PENDING"}));function re(e){if(e.taskId==null)return e;const s=_.value[e.taskId];return s?{...e,...s,sourceFilename:s.sourceFilename||e.sourceFilename,resultFilename:s.resultFilename||e.resultFilename,rowCount:s.rowCount??e.rowCount,createdAt:s.createdAt||e.createdAt}:e}function $(){return is("similar-asin").trim()}function M(e){if(!e)return"-";const s=new Date(e);if(Number.isNaN(s.getTime()))return e;const t=s.getFullYear(),l=String(s.getMonth()+1).padStart(2,"0"),n=String(s.getDate()).padStart(2,"0"),o=String(s.getHours()).padStart(2,"0"),g=String(s.getMinutes()).padStart(2,"0"),J=String(s.getSeconds()).padStart(2,"0");return`${t}-${l}-${n} ${o}:${g}:${J}`}function Ie(e){return e?e.length<=10?"***":`${e.slice(0,6)}***${e.slice(-4)}`:""}function we(e){return{...e,data:e.data?{...e.data,api_key:Ie(String(e.data.api_key||""))}:e.data}}function oe(){return typeof window<"u"&&window.localStorage.getItem("uid")||"0"}function Se(){return Number(oe())||0}function Y(){return`similar-asin:tasks:${oe()}`}function Pe(e){return{taskId:e.taskId,totalRows:e.totalRows,acceptedRows:e.acceptedRows,groupCount:e.groupCount,droppedRows:e.droppedRows}}function P(){if(typeof window>"u")return;const e=Array.from(new Set([...d.value,...c.value]));e.length?window.localStorage.setItem(Y(),JSON.stringify(e)):window.localStorage.removeItem(Y())}function Ce(){if(!(typeof window>"u"))try{const e=window.localStorage.getItem(Y()),s=e?JSON.parse(e):[];d.value=Array.isArray(s)?s.filter(t=>typeof t=="number"&&t>0):[]}catch{d.value=[]}}async function ue(e){const s=q();if(!s?.upload_file_to_java)throw new Error("当前桌面端未提供文件上传能力");const t=[];for(const l of e){const n=typeof l=="string"?l:l.absolutePath,o=typeof l=="string"?void 0:l.relativePath,g=await s.upload_file_to_java(n,o);if(!g?.success||!g.data)throw new Error(g?.error||g?.message||`上传失败:${n}`);t.push(g.data)}return t}async function be(){const e=q();if(!e?.select_brand_xlsx_files||!e.upload_file_to_java){v.warning("当前桌面端未提供文件选择或上传能力");return}const s=await e.select_brand_xlsx_files();if(!s?.length)return;const t=await ue(s);m.value=t,D.value=t.map(l=>l.relativePath||l.originalFilename||l.fileKey),I.value=null,w.value=null,S.value=""}async function me(){const e=q();if(!e?.select_brand_folder||!e.upload_file_to_java){v.warning("当前桌面端未提供文件夹选择或上传能力");return}try{const s=await e.select_brand_folder();if(!s)return;const t=await ds(s);if(!t.success||!t.items?.length){v.warning(t.error||"该文件夹下没有可用的 xlsx 文件");return}const l=await ue(t.items);m.value=l,D.value=t.items.map(n=>n.relativePath||n.absolutePath),I.value=null,w.value=null,S.value="",v.success(`已选择文件夹内 ${t.items.length} 个 Excel 文件`)}catch(s){v.error(s instanceof Error?s.message:"选择失败")}}async function Ne(){if(!m.value.length){v.warning("请先选择 Excel");return}if(!$()){v.warning("请先在左上角设置中填写货源查询密钥");return}U.value=!0;try{const e=m.value.map(t=>({fileKey:t.fileKey,originalFilename:t.originalFilename,relativePath:t.relativePath})),s=await ss(e,$(),O.value);I.value=s,w.value=null,S.value="",v.success(`解析完成,共 ${s.acceptedRows} 条`)}catch(e){v.error(e instanceof Error?e.message:"解析失败")}finally{U.value=!1}}async function Fe(){const e=q(),s=I.value,t=s?.taskId;if(!t){v.warning("请先解析文件");return}if(!e?.enqueue_json){v.error("当前环境未启用 pywebview enqueue_json");return}if(!$()){v.warning("请先在左上角设置中填写货源查询密钥");return}x.value=!0;try{const l={type:"similar-asin-run",ts:Date.now(),data:{taskId:t,user_id:Se(),api_key:$(),sourceFileCount:s.sourceFileCount||0,totalRows:s.totalRows||0,acceptedRows:s.acceptedRows||0,groupCount:s.groupCount||0}};S.value=JSON.stringify(we(l),null,2),await ts(t);const n=await e.enqueue_json(l);if(!n?.success){v.error(n?.error||"推送失败");return}w.value=Pe(s),Te(t),ie(),await z(),await L({force:!0}),v.success("已推送到 Python 队列")}finally{x.value=!1}}function ie(){I.value=null,S.value=""}function Te(e){d.value.includes(e)||(d.value=[...d.value,e],P()),C()}function Q(e){if(d.value=d.value.filter(s=>s!==e),!c.value.includes(e)){const s={..._.value};delete s[e],_.value=s}P()}function Ee(e){c.value.includes(e)||(c.value=[...c.value,e],P()),C()}function G(e){if(c.value=c.value.filter(s=>s!==e),!d.value.includes(e)){const s={..._.value};delete s[e],_.value=s}P()}function Re(e){if(e&&(Q(e),G(e),I.value?.taskId===e&&ie(),w.value?.taskId===e&&(w.value=null),f.value=f.value.filter(s=>s.taskId!==e),_.value[e])){const s={..._.value};delete s[e],_.value=s}}function C(){F||k.value==null&&Ae(!0)}function ce(){k.value!=null&&(T.clearTimer("task-poll",k.value),k.value=null)}function Ae(e=!1){if(F)return;if(k.value!=null){if(!e)return;T.clearTimer("task-poll",k.value),k.value=null}const s=async()=>{k.value=null,!F&&(!d.value.length&&!c.value.length||(await De(),!F&&k.value==null&&(d.value.length||c.value.length)&&(k.value=T.setTimeout("task-poll",s,ye()))))};e?s():k.value=T.setTimeout("task-poll",s,ye())}async function De(){if(K.value||!d.value.length&&!c.value.length){!d.value.length&&!c.value.length&&ce();return}K.value=!0;try{let e=!1,s=!1;const t=Array.from(new Set([...d.value,...c.value]));if(t.length){const l=await cs(t,{force:c.value.length>0});for(const n of l.items||[]){const o=n.task;if(!o?.id)continue;const g=n.items?.[0];if(g&&(_.value={..._.value,[o.id]:g},Ue(g)),(o.status==="SUCCESS"||o.status==="FAILED")&&(Q(o.id),e=!0,o.status==="SUCCESS"?Ee(o.id):G(o.id)),g&&o.status==="SUCCESS"&&c.value.includes(o.id)){const J=(g.fileStatus||"").toUpperCase();(g.fileReady||J==="SUCCESS"||J==="FAILED")&&(G(o.id),e=!0,s=!0)}}l.missingTaskIds?.length&&(l.missingTaskIds.forEach(n=>{Q(n),G(n)}),s=!0,e=!0)}e&&await z(),s&&await L(),xe()}finally{K.value=!1}}function Ue(e){if(!e.taskId&&!e.resultId)return;const s=f.value.findIndex(t=>e.resultId!=null&&t.resultId===e.resultId||e.taskId!=null&&t.taskId===e.taskId);s>=0?f.value[s]={...f.value[s],...e}:f.value=[e,...f.value]}function xe(){if(!c.value.length)return;const e=[];for(const s of c.value){const t=f.value.find(o=>o.taskId===s);if(!t){e.push(s);continue}const l=(t.taskStatus||"").toUpperCase(),n=(t.fileStatus||"").toUpperCase();l==="FAILED"||t.fileReady||n==="SUCCESS"||n==="FAILED"||l==="SUCCESS"&&e.push(s)}c.value=e,P(),c.value.length&&C()}function $e(){const e=f.value.filter(s=>s.taskId!=null&&b(s)).map(s=>s.taskId);c.value=Array.from(new Set(e)),P(),c.value.length&&C()}function Me(){const e=f.value.filter(s=>s.taskId!=null&&y(s)==="RUNNING").map(s=>s.taskId);e.length&&(d.value=Array.from(new Set([...d.value,...e])),P(),C())}async function z(){E.value=await as()}async function L(e={}){const s=Date.now();if(!(!e.force&&f.value.length&&s-ae<gt))return N||(N=ls().then(t=>{f.value=Ge(f.value,t.items||[]),ae=Date.now()}).finally(()=>{N=null}),N)}function Ge(e,s){const t=new Map,l=new Map;for(const n of e||[])n.taskId!=null&&t.set(n.taskId,n),n.resultId!=null&&l.set(n.resultId,n);return(s||[]).map(n=>{const o=n.resultId!=null?l.get(n.resultId):n.taskId!=null?t.get(n.taskId):void 0;return ze(o,n)})}function ze(e,s){return!e||!((y(e)==="RUNNING"||b(e)||A(e))&&!A(s)&&!Z(s))?s:{...s,fileJobId:s.fileJobId??e.fileJobId,fileStatus:s.fileStatus||e.fileStatus,fileError:s.fileError||e.fileError,fileReady:s.fileReady||e.fileReady,fileProgressPercent:W(s.fileProgressPercent)?s.fileProgressPercent:e.fileProgressPercent,fileProgressCurrent:W(s.fileProgressCurrent)?s.fileProgressCurrent:e.fileProgressCurrent,fileProgressTotal:W(s.fileProgressTotal)?s.fileProgressTotal:e.fileProgressTotal,fileProgressMessage:(s.fileProgressMessage||"").trim()?s.fileProgressMessage:e.fileProgressMessage}}function W(e){const s=Number(e);return Number.isFinite(s)&&s>0}function de(e){const s=y(e);return s==="RUNNING"?"执行中":s==="PENDING"?"已解析待推送":b(e)?"结果生成中":X(e)?"结果生成失败":s==="SUCCESS"||e.success?"已完成":s==="FAILED"?"失败":"等待中"}function Le(e){const s=y(e);return s==="RUNNING"||b(e)?"running":X(e)||s==="FAILED"?"failed":s==="SUCCESS"||e.success?"success":"pending"}function b(e){const s=y(e),t=(e.fileStatus||"").toUpperCase();return!(s!=="SUCCESS"||Z(e)||t==="FAILED"||t==="SUCCESS")}function y(e){return(e.taskStatus||"").toUpperCase()}function X(e){return(e.fileStatus||"").toUpperCase()==="FAILED"}function B(e){if(X(e))return e.fileError||"结果文件生成失败,请稍后重试或检查后端日志";if(A(e)||!b(e))return"";const s=(e.fileStatus||"").toUpperCase();return s==="RUNNING"?"任务已完成,正在等待 Coze 回流并组装结果文件,下载按钮稍后出现":s==="PENDING"?"任务已完成,结果文件已入队,正在等待后端开始处理":"任务已完成,正在生成结果文件,下载按钮稍后出现"}function Z(e){return!!(e.resultId&&(e.fileReady||e.downloadUrl))}function H(e){const s=Number(e.fileProgressPercent||0);return Number.isFinite(s)&&s>0?Math.max(0,Math.min(100,Math.round(s))):he(e)?pe(e)==="PENDING"?6:10:0}function fe(e,s){const t=(e.fileProgressMessage||"").trim();return t?/coze/i.test(t)||/Coze|回流/.test(t)?/submitting/i.test(t)||/提交/.test(t)?"正在提交 Coze 批次":/生成结果|结果文件|组装/i.test(t)?"Coze 已回流,正在生成结果文件":/waiting/i.test(t)||/等待/.test(t)||/\d+\s*\/\s*\d+/.test(t)?"Coze 回流中,等待结果回传":"Coze 处理中":/assembling|xlsx|组装|生成结果/i.test(t)?"正在组装结果文件":t:s}function ve(e){const s=(e.fileProgressMessage||"").trim(),t=Be(s),l=t?.current??e.fileProgressCurrent??0,n=t?.total??e.fileProgressTotal??0;return/coze/i.test(s)||/Coze|回流/.test(s)?/submitting/i.test(s)||/提交/.test(s)?`Coze 提交批次 ${l}/${n}`:`Coze 回流批次 ${l}/${n}`:`当前阶段 ${l}/${n}`}function Be(e){const s=e.match(/(\d+)\s*\/\s*(\d+)/);if(!s)return null;const t=Number(s[1]),l=Number(s[2]);return!Number.isFinite(t)||!Number.isFinite(l)?null:{current:t,total:l}}function A(e){return(y(e)==="RUNNING"||b(e))&&(ge(e)||he(e))}function ge(e){return ee(e)||Number(e.fileProgressPercent||0)>0||!!(e.fileProgressMessage||"").trim()}function ee(e){return(e.fileProgressTotal||0)>0}function pe(e){return(e.fileStatus||"").toUpperCase()}function He(e){const s=pe(e);return e.fileJobId!=null||s==="PENDING"||s==="RUNNING"}function he(e){return He(e)&&!ge(e)}async function Je(e){if(!e.resultId)return;const s=e.downloadUrl||ns(e.resultId),t=e.resultFilename||`${e.sourceFilename||"similar-asin"}.xlsx`,l=await rs(s,t,`similar-asin:${e.resultId}`);l.success?v.success(`已保存: ${l.path||t}`):l.error&&l.error!=="用户取消"&&v.error(l.error)}async function ke(e){try{const s=y(e),t=e.taskId;t!=null&&(s==="RUNNING"||s==="PENDING"||!e.resultId)?(await os(t),Re(t)):e.resultId&&(await us(e.resultId),e.taskId&&(f.value=f.value.filter(n=>n.taskId!==e.taskId))),await z(),await L({force:!0}),v.success("已删除")}catch(s){v.error(s instanceof Error?s.message:"删除失败")}}return qe(async()=>{Ce(),await Promise.all([z().catch(()=>{}),L().catch(()=>{})]),$e(),Me(),(d.value.length||c.value.length)&&C()}),Oe(()=>{F=!0,ce(),T.clearScope()}),(e,s)=>(u(),i("div",vs,[Ke(es,{active:"similar-asin"}),a("div",gs,[a("aside",ps,[s[5]||(s[5]=a("div",{class:"section-title"},"上传文件",-1)),a("div",hs,[s[1]||(s[1]=a("div",{class:"hint"},"选择 Excel 后点击解析,后端会提取 id、ASIN、国家、价格,每一行都会独立送检。",-1)),a("div",{class:"btns"},[a("button",{type:"button",class:"opt-btn",onClick:be},"选择 Excel"),a("button",{type:"button",class:"opt-btn",onClick:me},"选择文件夹")]),a("div",ks,[D.value.length?(u(!0),i(se,{key:1},te(D.value,t=>(u(),i("span",{key:t},r(t),1))),128)):(u(),i("span",_s,"暂未选择文件"))])]),a("div",ys,[s[4]||(s[4]=a("div",{class:"section-title"},"检测条件",-1)),a("label",Is,[s[2]||(s[2]=a("span",null,[a("strong",null,"图片检测"),a("em",null,"开启后请求 Coze 时携带 img_switch=true")],-1)),Ve(a("input",{"onUpdate:modelValue":s[0]||(s[0]=t=>O.value=t),type:"checkbox"},null,512),[[Ye,O.value]]),s[3]||(s[3]=a("i",null,null,-1))])]),a("div",ws,[a("button",{type:"button",class:"btn-run",disabled:U.value||!m.value.length,onClick:Ne},r(U.value?"解析中...":"解析并创建任务"),9,Ss),a("button",{type:"button",class:"btn-run btn-queue",disabled:x.value||!I.value?.taskId,onClick:Fe},r(x.value?"推送中...":"推送到 Python 队列"),9,Ps)]),s[6]||(s[6]=a("p",{class:"loading-msg"},"Python 回传字段按 id、asin、国家、价格、标题、图片链接数组提交;后端接收分片后按 10 条一批送检,结果区展示真实 Coze 批次进度。",-1)),R.value?(u(),i("div",Cs,[a("div",null,"任务 ID:"+r(R.value.taskId),1),a("div",null,"总行数:"+r(R.value.totalRows)+",有效:"+r(R.value.acceptedRows)+",过滤:"+r(R.value.droppedRows),1)])):h("",!0),S.value?(u(),i("pre",bs,r(S.value),1)):h("",!0)]),a("section",ms,[s[14]||(s[14]=a("div",{class:"panel-header"},"货源查询",-1)),a("div",Ns,[a("div",Fs,[a("div",Ts,[s[7]||(s[7]=a("span",{class:"summary-label"},"运行中任务",-1)),a("strong",null,r(E.value.pendingTaskCount),1)]),a("div",Es,[s[8]||(s[8]=a("span",{class:"summary-label"},"已结束任务",-1)),a("strong",null,r(E.value.processedTaskCount),1)]),a("div",Rs,[s[9]||(s[9]=a("span",{class:"summary-label"},"成功任务",-1)),a("strong",null,r(E.value.successTaskCount),1)]),a("div",As,[s[10]||(s[10]=a("span",{class:"summary-label"},"失败任务",-1)),a("strong",null,r(E.value.failedTaskCount),1)])]),s[13]||(s[13]=a("div",{class:"subsection-title"},"匹配任务",-1)),a("div",Ds,[s[11]||(s[11]=a("div",{class:"result-list-header"},[a("span",null,"当前任务")],-1)),le.value.length?(u(),i("ul",xs,[(u(!0),i(se,null,te(le.value,t=>(u(),i("li",{key:`cur-${t.taskId}`,class:"task-item"},[a("div",$s,[a("span",Ms,r(t.sourceFilename||"货源查询"),1),a("div",Gs,"任务 ID:"+r(t.taskId),1),a("div",zs,"开始时间:"+r(M(t.startedAt||t.createdAt)),1),a("div",Ls,"结束时间:"+r(M(t.finishedAt)),1),a("div",Bs,"行数:"+r(t.rowCount??"-"),1),B(t)?(u(),i("div",Hs,r(B(t)),1)):h("",!0),A(t)?(u(),i("div",Js,[a("div",js,[a("span",null,r(fe(t,"处理中")),1),a("span",null,"总进度 "+r(H(t))+"%",1)]),a("div",qs,[a("div",{class:"file-progress-bar",style:_e({width:`${H(t)}%`})},null,4)]),ee(t)?(u(),i("div",Os,r(ve(t)),1)):h("",!0)])):h("",!0)]),a("div",Ks,[a("span",Vs,r(de(t)),1),a("button",{type:"button",class:"btn-delete",onClick:l=>ke(t)},"删除",8,Ys)])]))),128))])):(u(),i("div",Us,"暂无当前任务"))]),a("div",Qs,[s[12]||(s[12]=a("div",{class:"result-list-header"},[a("span",null,"历史记录")],-1)),ne.value.length?(u(),i("ul",Xs,[(u(!0),i(se,null,te(ne.value,t=>(u(),i("li",{key:`his-${t.resultId}-${t.taskId}`,class:"task-item"},[a("div",Zs,[a("span",et,r(t.sourceFilename||"货源查询"),1),a("div",st,"任务 ID:"+r(t.taskId??"-"),1),a("div",tt,"开始时间:"+r(M(t.startedAt||t.createdAt)),1),a("div",at,"结束时间:"+r(M(t.finishedAt)),1),t.resultFilename?(u(),i("div",lt,r(t.resultFilename||"下载结果"),1)):h("",!0),B(t)?(u(),i("div",nt,r(B(t)),1)):h("",!0),A(t)?(u(),i("div",rt,[a("div",ot,[a("span",null,r(fe(t,"结果生成中")),1),a("span",null,"总进度 "+r(H(t))+"%",1)]),a("div",ut,[a("div",{class:"file-progress-bar",style:_e({width:`${H(t)}%`})},null,4)]),ee(t)?(u(),i("div",it,r(ve(t)),1)):h("",!0)])):h("",!0),t.error?(u(),i("div",ct,"错误:"+r(t.error),1)):h("",!0)]),a("div",dt,[a("span",{class:Qe(["status",Le(t)])},r(de(t)),3),Z(t)?(u(),i("button",{key:0,type:"button",class:"download",onClick:l=>Je(t)},"下载",8,ft)):h("",!0),t.resultId?(u(),i("button",{key:1,type:"button",class:"btn-delete",onClick:l=>ke(t)},"删除",8,vt)):h("",!0)])]))),128))])):(u(),i("div",Ws,"暂无历史记录"))])])])])]))}}),ht=We(pt,[["__scopeId","data-v-b77550eb"]]);Xe(ht).use(Ze).mount("#app");
|