Files
crawler-plugin/app/assets/appearance-patent.js
2026-06-08 09:19:15 +08:00

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