Files
crawler-plugin/app/assets/similar-asin.js
2026-05-06 00:01:49 +08:00

5 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{d as De,o as xe,L as Ke,a as o,c,b as w,B as $e,e as t,F as Y,r as Q,t as i,w as ue,G as ce,f as h,V as Be,W as Le,X as Ge,Y as He,N as Me,n as qe,g as p,h as U,i as D,E as f,a6 as ze,a7 as je,U as de,a8 as Ve,a9 as Oe,aa as Je,ab as Ye,ac as Qe,ad as We,_ as Xe,q as Ze,s as es}from"./pywebview-RBTI4RuH.js";/* empty css */import{e as ss}from"./brand-1lGM3Wzk.js";import{c as ts}from"./categorized-timers-JPA-olTr.js";const as={class:"page-shell module-page"},ls={class:"main-content"},ns={class:"left-panel"},is={class:"upload-zone"},rs={class:"selected-files"},os={key:0},us={class:"prompt-card"},cs={class:"secret-card"},ds={class:"run-row"},fs=["disabled"],ps=["disabled"],vs={key:0,class:"parse-card"},ys={key:1,class:"queue-payload"},gs={class:"right-panel"},hs={class:"task-list-wrap"},_s={class:"clean-result-summary"},ms={class:"summary-card"},ks={class:"summary-card"},ws={class:"summary-card"},Is={class:"summary-card"},Ss={class:"result-list-wrap preview-wrap"},bs={class:"result-list-header"},Cs={key:0,class:"muted"},Fs={key:0,class:"empty-tasks"},Ts={class:"result-list-wrap"},Ps={key:0,class:"empty-tasks"},As={key:1,class:"task-list clean-result-list"},Es={class:"left"},Ns={class:"id"},Rs={class:"files"},Us={class:"files"},Ds={class:"task-right"},xs={class:"status running"},Ks=["onClick"],$s={class:"result-list-wrap"},Bs={key:0,class:"empty-tasks"},Ls={key:1,class:"task-list clean-result-list"},Gs={class:"left"},Hs={class:"id"},Ms={class:"files"},qs={key:0,class:"files"},zs={key:1,class:"files result-hint"},js={key:2,class:"file-progress"},Vs={class:"file-progress-meta"},Os={class:"file-progress-track"},Js={class:"file-progress-count"},Ys={key:3,class:"files"},Qs={class:"task-right"},Ws=["onClick"],Xs=["onClick"],fe=`1. 图案与形象限制不含各国国旗及类似图案无各国领导人画像不含圣诞老人形象排除迪士尼、漫威、三丽鸥等所有指定动漫IP的图案与关联物品且不涉及知名油画作品图案。
2. 品类排除:非图书、刀具、服装;不含药品、带容器的粉末及液体;与吸烟行为无关,无医疗标志。
3. 功能与配件要求:不可充电且不带电池,无磁吸功能;配件多的情况下需完全匹配。
4. 规格与外观限制不含体积大的家具类物品如椅子、桌子、大镜子、柜子不带任何品牌logo无多种款式可选。`,Zs=3e3,et=De({__name:"BrandSimilarAsinTab",setup(tt){const x=p([]),b=p([]),_=p(null),I=p([]),C=p(null),M=p(""),q=p(""),K=p(!1),$=p(!1),m=p(""),v=p([]),d=p([]),y=p(null),z=p(!1);let F=null,W=0,T=!1;const P=ts("similar-asin"),A=p({pendingTaskCount:0,processedTaskCount:0,successTaskCount:0,failedTaskCount:0}),g=p([]),k=U(()=>_.value?.items?.length?_.value.items:I.value.flatMap(e=>e.items||[])),pe=U(()=>k.value),E=U(()=>_.value||C.value),X=U(()=>g.value.filter(e=>e.taskId!=null&&v.value.includes(e.taskId))),Z=U(()=>g.value.filter(e=>{const s=H(e);return s!=="RUNNING"&&s!=="PENDING"}));function ee(){return M.value.trim()||fe}function B(){return q.value.trim()}function ve(e){return e?e.length<=10?"***":`${e.slice(0,6)}***${e.slice(-4)}`:""}function ye(e){return{...e,data:e.data?{...e.data,api_key:ve(String(e.data.api_key||""))}:e.data}}function ge(){return typeof window<"u"&&window.localStorage.getItem("uid")||"0"}function j(){return`similar-asin:tasks:${ge()}`}function he(e){return{taskId:e.taskId,totalRows:e.totalRows,acceptedRows:e.acceptedRows,groupCount:e.groupCount,droppedRows:e.droppedRows}}function S(){if(typeof window>"u")return;const e=Array.from(new Set([...v.value,...d.value]));e.length?window.localStorage.setItem(j(),JSON.stringify(e)):window.localStorage.removeItem(j())}function _e(){if(!(typeof window>"u"))try{const e=window.localStorage.getItem(j()),s=e?JSON.parse(e):[];v.value=Array.isArray(s)?s.filter(l=>typeof l=="number"&&l>0):[]}catch{v.value=[]}}async function se(e){const s=D();if(!s?.upload_file_to_java)throw new Error("当前桌面端未提供文件上传能力");const l=[];for(const r of e){const a=typeof r=="string"?r:r.absolutePath,n=typeof r=="string"?void 0:r.relativePath,u=await s.upload_file_to_java(a,n);if(!u?.success||!u.data)throw new Error(u?.error||u?.message||`上传失败:${a}`);l.push(u.data)}return l}async function me(){const e=D();if(!e?.select_brand_xlsx_files||!e.upload_file_to_java){f.warning("当前环境不支持文件选择或上传");return}const s=await e.select_brand_xlsx_files();if(!s?.length)return;const l=await se(s);b.value=l,x.value=l.map(r=>r.relativePath||r.originalFilename||r.fileKey),_.value=null,I.value=[],C.value=null,m.value=""}async function ke(){const e=D();if(!e?.select_brand_folder){f.warning("当前环境不支持文件夹选择,请在本地客户端中打开");return}try{const s=await e.select_brand_folder();if(!s)return;const l=await ss(s);if(!l.success||!l.items?.length){f.warning(l.error||"该文件夹下没有可用的 xlsx 文件");return}const r=await se(l.items);b.value=r,x.value=l.items.map(a=>a.relativePath||a.absolutePath),_.value=null,I.value=[],C.value=null,m.value="",f.success(`已选择文件夹内 ${l.items.length} 个 Excel 文件`)}catch(s){f.error(s instanceof Error?s.message:"选择失败")}}async function we(){if(!b.value.length){f.warning("请先选择 Excel");return}if(!B()){f.warning("请先填写密钥");return}K.value=!0;try{const e=b.value.map(l=>({fileKey:l.fileKey,originalFilename:l.originalFilename,relativePath:l.relativePath})),s=await ze(e,ee(),B());_.value=s,C.value=null,I.value=s.items?.length?[{sourceFileKey:s.items[0]?.sourceFileKey,sourceFilename:s.items[0]?.sourceFilename,groupKey:`similar-asin:${s.taskId}`,baseId:"",displayId:s.items[0]?.displayId,itemCount:s.items.length,items:s.items}]:[],m.value="",f.success(`解析完成,共 ${s.acceptedRows}`)}catch(e){f.error(e instanceof Error?e.message:"解析失败")}finally{K.value=!1}}async function Ie(){const e=D(),s=_.value,l=s?.taskId;if(!l||!k.value.length){f.warning("请先解析文件");return}if(!e?.enqueue_json){f.error("当前环境未启用 pywebview enqueue_json");return}if(!B()){f.warning("请先填写密钥");return}$.value=!0;try{const r={type:"similar-asin-run",ts:Date.now(),data:{taskId:l,prompt:s.aiPrompt||ee(),api_key:B(),groups:I.value.map(n=>({sourceFileKey:n.sourceFileKey||"",sourceFilename:n.sourceFilename||"",groupKey:n.groupKey||"",baseId:n.baseId||"",displayId:n.displayId||"",items:(n.items||[]).map(u=>({sourceFileKey:u.sourceFileKey||"",sourceFilename:u.sourceFilename||"",rowToken:u.rowToken||"",groupKey:u.groupKey||"",id:u.displayId,asin:u.asin,country:u.country,price:u.price||"",url:u.url||"",title:u.title||"",target_urls:[]}))})),rows:k.value.map(n=>({sourceFileKey:n.sourceFileKey||"",sourceFilename:n.sourceFilename||"",rowToken:n.rowToken||"",groupKey:n.groupKey||"",id:n.displayId,asin:n.asin,country:n.country,price:n.price||"",url:n.url||"",title:n.title||"",target_urls:[]}))}};m.value=JSON.stringify(ye(r),null,2),await je(l);const a=await e.enqueue_json(r);if(!a?.success){f.error(a?.error||"推送失败");return}C.value=he(s),be(l),Se(),await L(),await G({force:!0}),f.success("已推送到 Python 队列")}finally{$.value=!1}}function Se(){_.value=null,I.value=[],m.value=""}function be(e){v.value.includes(e)||(v.value=[...v.value,e],S()),N()}function V(e){v.value=v.value.filter(s=>s!==e),S()}function Ce(e){d.value.includes(e)||(d.value=[...d.value,e],S()),N()}function O(e){d.value=d.value.filter(s=>s!==e),S()}function N(){T||y.value==null&&Fe(!0)}function te(){y.value!=null&&(P.clearTimer("task-poll",y.value),y.value=null)}function Fe(e=!1){if(T)return;if(y.value!=null){if(!e)return;P.clearTimer("task-poll",y.value),y.value=null}const s=async()=>{y.value=null,!T&&(!v.value.length&&!d.value.length||(await Te(),!T&&y.value==null&&(v.value.length||d.value.length)&&(y.value=P.setTimeout("task-poll",s,de()))))};e?s():y.value=P.setTimeout("task-poll",s,de())}async function Te(){if(z.value||!v.value.length&&!d.value.length){!v.value.length&&!d.value.length&&te();return}z.value=!0;try{let e=!1,s=!1;const l=Array.from(new Set([...v.value,...d.value]));if(l.length){const r=await We(l,{force:d.value.length>0});for(const a of r.items||[]){const n=a.task;if(!n?.id)continue;const u=a.items?.[0];if(u&&Pe(u),(n.status==="SUCCESS"||n.status==="FAILED")&&(V(n.id),e=!0,n.status==="SUCCESS"?Ce(n.id):O(n.id)),u&&n.status==="SUCCESS"&&d.value.includes(n.id)){const oe=(u.fileStatus||"").toUpperCase();(u.fileReady||oe==="SUCCESS"||oe==="FAILED")&&(O(n.id),e=!0,s=!0)}}r.missingTaskIds?.length&&(r.missingTaskIds.forEach(a=>{V(a),O(a)}),s=!0,e=!0)}e&&await L(),s&&await G(),Ae()}finally{z.value=!1}}function Pe(e){if(!e.taskId&&!e.resultId)return;const s=g.value.findIndex(l=>e.resultId!=null&&l.resultId===e.resultId||e.taskId!=null&&l.taskId===e.taskId);s>=0?g.value[s]={...g.value[s],...e}:g.value=[e,...g.value]}function Ae(){if(!d.value.length)return;const e=[];for(const s of d.value){const l=g.value.find(n=>n.taskId===s);if(!l){e.push(s);continue}const r=(l.taskStatus||"").toUpperCase(),a=(l.fileStatus||"").toUpperCase();r==="FAILED"||l.fileReady||a==="SUCCESS"||a==="FAILED"||r==="SUCCESS"&&e.push(s)}d.value=e,S(),d.value.length&&N()}function Ee(){const e=g.value.filter(s=>s.taskId!=null&&R(s)).map(s=>s.taskId);d.value=Array.from(new Set(e)),S(),d.value.length&&N()}async function L(){A.value=await Ve()}async function G(e={}){const s=Date.now();if(!(!e.force&&g.value.length&&s-W<Zs))return F||(F=Oe().then(l=>{g.value=l.items||[],W=Date.now()}).finally(()=>{F=null}),F)}function ae(e){const s=H(e);return s==="RUNNING"?"执行中":s==="PENDING"?"已解析待推送":R(e)?"结果生成中":J(e)?"结果生成失败":s==="SUCCESS"||e.success?"已完成":s==="FAILED"?"失败":"等待中"}function Ne(e){const s=H(e);return s==="RUNNING"||R(e)?"running":J(e)||s==="FAILED"?"failed":s==="SUCCESS"||e.success?"success":"pending"}function R(e){const s=H(e),l=(e.fileStatus||"").toUpperCase();return!(s!=="SUCCESS"||ne(e)||l==="FAILED"||l==="SUCCESS")}function H(e){return(e.taskStatus||"").toUpperCase()}function J(e){return(e.fileStatus||"").toUpperCase()==="FAILED"}function le(e){if(J(e))return e.fileError||"结果文件生成失败,请稍后重试或检查后端日志";if(!R(e))return"";const s=(e.fileStatus||"").toUpperCase();return s==="RUNNING"?"任务已完成,正在请求 Coze 或组装结果文件,下载按钮稍后出现":s==="PENDING"?"任务已完成,结果文件已入队,正在等待后端生成":"任务已完成,正在生成结果文件,下载按钮稍后出现"}function ne(e){return!!(e.resultId&&(e.fileReady||e.downloadUrl))}function ie(e){const s=Number(e.fileProgressPercent||0);return Number.isFinite(s)?Math.max(0,Math.min(100,Math.round(s))):0}function Re(e){return R(e)&&(e.fileProgressTotal||0)>0}async function Ue(e){if(!e.resultId)return;const s=D();if(!s?.save_file_from_url_new){f.error("当前客户端未提供下载能力");return}const l=e.downloadUrl||Je(e.resultId),r=e.resultFilename||`${e.sourceFilename||"similar-asin"}.xlsx`,a=await s.save_file_from_url_new(l,r);a.success?f.success(`已保存: ${a.path||r}`):a.error&&a.error!=="用户取消"&&f.error(a.error)}async function re(e){try{e.taskStatus==="RUNNING"&&e.taskId?(await Ye(e.taskId),V(e.taskId)):e.resultId&&await Qe(e.resultId),await L(),await G({force:!0}),f.success("已删除")}catch(s){f.error(s instanceof Error?s.message:"删除失败")}}return xe(async()=>{_e(),await Promise.all([L().catch(()=>{}),G().catch(()=>{})]),Ee(),(v.value.length||d.value.length)&&N()}),Ke(()=>{T=!0,te(),P.clearScope()}),(e,s)=>{const l=Ge,r=He;return o(),c("div",as,[w($e,{active:"similar-asin"}),t("div",ls,[t("aside",ns,[s[6]||(s[6]=t("div",{class:"section-title"},"上传文件",-1)),t("div",is,[s[2]||(s[2]=t("div",{class:"hint"},"选择 Excel 后点击解析,后端会提取 id、ASIN、国家、价格每一行都会独立送检。",-1)),t("div",{class:"btns"},[t("button",{type:"button",class:"opt-btn",onClick:me},"选择 Excel"),t("button",{type:"button",class:"opt-btn",onClick:ke},"选择文件夹")]),t("div",rs,[x.value.length?(o(!0),c(Y,{key:1},Q(x.value,a=>(o(),c("span",{key:a},i(a),1))),128)):(o(),c("span",os,"暂未选择文件"))])]),t("div",us,[s[3]||(s[3]=t("div",{class:"section-title"},"AI 提示词",-1)),ue(t("textarea",{"onUpdate:modelValue":s[0]||(s[0]=a=>M.value=a),class:"prompt-input",rows:"8",placeholder:"可选,留空时使用下方默认提示词"},null,512),[[ce,M.value]]),s[4]||(s[4]=t("div",{class:"prompt-default-label"},"留空时默认使用以下提示词",-1)),t("div",{class:"prompt-preview"},i(fe))]),t("div",cs,[s[5]||(s[5]=t("div",{class:"section-title"},"密钥",-1)),ue(t("input",{"onUpdate:modelValue":s[1]||(s[1]=a=>q.value=a),class:"secret-input",type:"password",autocomplete:"off",spellcheck:"false"},null,512),[[ce,q.value]])]),t("div",ds,[t("button",{type:"button",class:"btn-run",disabled:K.value||!b.value.length,onClick:we},i(K.value?"解析中...":"解析并创建任务"),9,fs),t("button",{type:"button",class:"btn-run btn-queue",disabled:$.value||!k.value.length,onClick:Ie},i($.value?"推送中...":"推送到 Python 队列"),9,ps)]),s[7]||(s[7]=t("p",{class:"loading-msg"},"Python 回传字段按 id、asin、国家、价格、标题、图片链接数组提交后端接收分片后按 10 条一批送检。",-1)),E.value?(o(),c("div",vs,[t("div",null,"任务 ID"+i(E.value.taskId),1),t("div",null,"总行数:"+i(E.value.totalRows)+",有效:"+i(E.value.acceptedRows)+",过滤:"+i(E.value.droppedRows),1)])):h("",!0),m.value?(o(),c("pre",ys,i(m.value),1)):h("",!0)]),t("section",gs,[s[16]||(s[16]=t("div",{class:"panel-header"},"相似ASIN检测",-1)),t("div",hs,[t("div",_s,[t("div",ms,[s[8]||(s[8]=t("span",{class:"summary-label"},"运行中任务",-1)),t("strong",null,i(A.value.pendingTaskCount),1)]),t("div",ks,[s[9]||(s[9]=t("span",{class:"summary-label"},"已结束任务",-1)),t("strong",null,i(A.value.processedTaskCount),1)]),t("div",ws,[s[10]||(s[10]=t("span",{class:"summary-label"},"成功任务",-1)),t("strong",null,i(A.value.successTaskCount),1)]),t("div",Is,[s[11]||(s[11]=t("span",{class:"summary-label"},"失败任务",-1)),t("strong",null,i(A.value.failedTaskCount),1)])]),s[15]||(s[15]=t("div",{class:"subsection-title"},"匹配任务",-1)),t("div",Ss,[t("div",bs,[s[12]||(s[12]=t("span",null,"解析结果",-1)),k.value.length?(o(),c("span",Cs,"共 "+i(k.value.length)+" 条",1)):h("",!0)]),k.value.length?(o(),Be(r,{key:1,data:pe.value,height:"120",class:"result-table"},{default:Le(()=>[w(l,{prop:"displayId",label:"ID",width:"90"}),w(l,{prop:"asin",label:"ASIN",width:"130"}),w(l,{prop:"country",label:"国家",width:"100"}),w(l,{prop:"price",label:"价格",width:"90"}),w(l,{prop:"title",label:"标题","min-width":"160","show-overflow-tooltip":""}),w(l,{prop:"url",label:"URL","min-width":"160","show-overflow-tooltip":""})]),_:1},8,["data"])):(o(),c("div",Fs,"暂无解析结果"))]),t("div",Ts,[s[13]||(s[13]=t("div",{class:"result-list-header"},[t("span",null,"当前任务")],-1)),X.value.length?(o(),c("ul",As,[(o(!0),c(Y,null,Q(X.value,a=>(o(),c("li",{key:`cur-${a.taskId}`,class:"task-item"},[t("div",Es,[t("span",Ns,i(a.sourceFilename||"相似ASIN检测"),1),t("div",Rs,"任务 ID"+i(a.taskId),1),t("div",Us,"行数:"+i(a.rowCount??"-"),1)]),t("div",Ds,[t("span",xs,i(ae(a)),1),t("button",{type:"button",class:"btn-delete",onClick:n=>re(a)},"删除",8,Ks)])]))),128))])):(o(),c("div",Ps,"暂无当前任务"))]),t("div",$s,[s[14]||(s[14]=t("div",{class:"result-list-header"},[t("span",null,"历史记录")],-1)),Z.value.length?(o(),c("ul",Ls,[(o(!0),c(Y,null,Q(Z.value,a=>(o(),c("li",{key:`his-${a.resultId}-${a.taskId}`,class:"task-item"},[t("div",Gs,[t("span",Hs,i(a.sourceFilename||"相似ASIN检测"),1),t("div",Ms,"任务 ID"+i(a.taskId??"-"),1),a.resultFilename?(o(),c("div",qs,i(a.resultFilename||"下载结果"),1)):h("",!0),le(a)?(o(),c("div",zs,i(le(a)),1)):h("",!0),Re(a)?(o(),c("div",js,[t("div",Vs,[t("span",null,i(a.fileProgressMessage||"结果生成中"),1),t("span",null,i(ie(a))+"%",1)]),t("div",Os,[t("div",{class:"file-progress-bar",style:Me({width:`${ie(a)}%`})},null,4)]),t("div",Js,i(a.fileProgressCurrent||0)+"/"+i(a.fileProgressTotal||0),1)])):h("",!0),a.error?(o(),c("div",Ys,"错误:"+i(a.error),1)):h("",!0)]),t("div",Qs,[t("span",{class:qe(["status",Ne(a)])},i(ae(a)),3),ne(a)?(o(),c("button",{key:0,type:"button",class:"download",onClick:n=>Ue(a)},"下载",8,Ws)):h("",!0),a.resultId?(o(),c("button",{key:1,type:"button",class:"btn-delete",onClick:n=>re(a)},"删除",8,Xs)):h("",!0)])]))),128))])):(o(),c("div",Bs,"暂无历史记录"))])])])])])}}}),st=Xe(et,[["__scopeId","data-v-4d018902"]]);Ze(st).use(es).mount("#app");