Files
crawler-plugin/app/assets/query-asin.js
铭坤 8c5edc6ad6 new file: assets/_plugin-vue_export-helper-Dh4yMZWw.js
new file:   assets/_plugin-vue_export-helper-xvHHTGU_.css
	new file:   assets/appearance-patent-BNTrbLJh.css
	new file:   assets/appearance-patent-BPCrG75P.css
	new file:   assets/appearance-patent.js
	new file:   assets/brand-1nUVsWrm.js
	new file:   assets/brand-5-W0Wonr.js
	new file:   assets/brand-BATjYfEL.js
	new file:   assets/brand-BZije8D7.js
	new file:   assets/brand-C0Q5LZ0P.js
	new file:   assets/brand-CFZZtTv8.js
	new file:   assets/brand-CKgrwtni.js
	new file:   assets/brand-CRmRvyGD.js
	new file:   assets/brand-CXHemZwJ.js
	new file:   assets/brand-DBpLCgAF.js
	new file:   assets/brand-DRn3N4FA.js
	new file:   assets/brand-DZ5_PGnw.js
	new file:   assets/brand-DysFlQbZ.js
	new file:   assets/brand-UU-ckLq6.js
	new file:   assets/convert-1dkFPbKa.css
	new file:   assets/convert-6b0yq-M0.css
	new file:   assets/convert-7wWJ02Tw.css
	new file:   assets/convert-BKSNvX8i.css
	new file:   assets/convert-BxkpMHO9.css
	new file:   assets/convert-CQ22EBpm.css
	new file:   assets/convert-Cfr3mUjs.css
	new file:   assets/convert-D4Yv2oRy.css
	new file:   assets/convert-DwbQug2y.css
	new file:   assets/dedupe-B0eqpVpj.css
	new file:   assets/dedupe-BHE_BCAJ.css
	new file:   assets/dedupe-BpNHwt51.css
	new file:   assets/dedupe-CS18ls2z.css
	new file:   assets/dedupe-DNlVfFj-.css
	new file:   assets/dedupe-Day_nGxq.css
	new file:   assets/dedupe-DyzjKbsT.css
	new file:   assets/dedupe-DzFvTfoj.css
	new file:   assets/dedupe-rhGu1E8E.css
	new file:   assets/delete-brand-BNvh4ru4.css
	new file:   assets/delete-brand-BP3XWKAC.css
	new file:   assets/delete-brand-BRIDBaoM.css
	new file:   assets/delete-brand-BcZomrN3.css
	new file:   assets/delete-brand-BgPrpPsj.css
	new file:   assets/delete-brand-ByeMdpEk.css
	new file:   assets/delete-brand-C-Rj3NMH.css
	new file:   assets/delete-brand-CDZTH98q.css
	new file:   assets/delete-brand-CS44Bk-y.css
	new file:   assets/delete-brand-CWLpe7lu.css
	new file:   assets/delete-brand-CdxGWtvK.css
	new file:   assets/delete-brand-Chu8awlt.css
	new file:   assets/delete-brand-CndjrFFS.css
	new file:   assets/delete-brand-CpNTe9WM.css
	new file:   assets/delete-brand-D7t16Ukk.css
	new file:   assets/delete-brand-DE0hLEak.css
	new file:   assets/delete-brand-DLyg-H8J.css
	new file:   assets/delete-brand-DO6pdlC3.css
	new file:   assets/delete-brand-DXSeQxXc.css
	new file:   assets/delete-brand-DZ6zYt8o.css
	new file:   assets/delete-brand-DfRLfrtm.css
	new file:   assets/delete-brand-Dl7T0pmm.css
	new file:   assets/delete-brand-Dt_MS9as.css
	new file:   assets/delete-brand-DvND7vBL.css
	new file:   assets/delete-brand-_jGFWTAn.css
	new file:   assets/el-alert-Ct0RpqUD.css
	new file:   assets/el-input-CezJelDw.css
	new file:   assets/el-input-xaztPnzw.css
	new file:   assets/el-table-column-Cy4YJvw0.css
	new file:   assets/listingFilters-B6-M_FNM.js
	new file:   assets/listingFilters-BmlAzw7M.css
	new file:   assets/listingFilters-BpGOU_pJ.js
	new file:   assets/listingFilters-CK58rX4v.css
	new file:   assets/patrol-delete-BPu1AAPM.css
	new file:   assets/patrol-delete-BctopIU4.css
	new file:   assets/patrol-delete-CSekhzSS.css
	new file:   assets/patrol-delete-DIvFZUTh.css
	new file:   assets/patrol-delete.js
	new file:   assets/price-track-1SjcUfP4.css
	new file:   assets/price-track-85NbckiJ.css
	new file:   assets/price-track-B5FVfJb_.css
	new file:   assets/price-track-BO5PtL0W.css
	new file:   assets/price-track-BccJT4Qr.css
	new file:   assets/price-track-BlSD-0un.css
	new file:   assets/price-track-BlVVl2eV.css
	new file:   assets/price-track-BwgEuRxe.css
	new file:   assets/price-track-CWQD_A7D.css
	new file:   assets/price-track-DNTcdRH8.css
	new file:   assets/price-track-Dv4EZPhf.css
	new file:   assets/price-track-Ji5JAoeR.css
	new file:   assets/price-track-RLJUgMl_.css
	new file:   assets/price-track-z8RU_FlW.css
	new file:   assets/price-track.js
	new file:   assets/product-risk-1G_ztqNY.css
	new file:   assets/product-risk-A5bhfaTH.css
	new file:   assets/product-risk-BBMcuGAw.css
	new file:   assets/product-risk-C3Yn2wAL.css
	new file:   assets/product-risk-CG-1Iq4P.css
	new file:   assets/product-risk-COeM91v5.css
	new file:   assets/product-risk-ClWs7d57.css
	new file:   assets/product-risk-CtpNfape.css
	new file:   assets/product-risk-DBsBE_mg.css
	new file:   assets/product-risk-DRYaWmI2.css
	new file:   assets/product-risk-Db49F4J5.css
	new file:   assets/product-risk-DoO8ZHM0.css
	new file:   assets/product-risk-DpSMKBCA.css
	new file:   assets/product-risk-DqFPFWEv.css
	new file:   assets/product-risk-cfL3Ch5-.css
	new file:   assets/product-risk-eXMv239F.css
	new file:   assets/product-risk-un2cxu--.css
	new file:   assets/product-risk.js
	new file:   assets/pywebview-3PePjYSu.js
	new file:   assets/pywebview-8G_9KMXd.css
	new file:   assets/pywebview-9YBa--7x.js
	new file:   assets/pywebview-B6ZNXusn.css
	new file:   assets/pywebview-BCPdlDdb.js
	new file:   assets/pywebview-BLoeiUcF.css
	new file:   assets/pywebview-BRrok0pS.js
	new file:   assets/pywebview-BT0f6KST.css
	new file:   assets/pywebview-BbIq-QPS.css
	new file:   assets/pywebview-Bc09DixN.js
	new file:   assets/pywebview-Bl6M97uH.js
	new file:   assets/pywebview-BnpJyyGZ.js
	new file:   assets/pywebview-Bt854mYs.js
	new file:   assets/pywebview-C5RGB8QW.css
	new file:   assets/pywebview-C66x_2Dh.js
	new file:   assets/pywebview-C8Bik-Sc.js
	new file:   assets/pywebview-CGwF8TuM.js
	new file:   assets/pywebview-CJLylbJu.js
	new file:   assets/pywebview-CeWJDVeG.js
	new file:   assets/pywebview-Chz98E9c.css
	new file:   assets/pywebview-ClWy2SbE.js
	new file:   assets/pywebview-Cq_E2BnJ.js
	new file:   assets/pywebview-Cs1Kot1q.js
	new file:   assets/pywebview-D-PKWjUg.js
	new file:   assets/pywebview-D-mMH8F6.css
	new file:   assets/pywebview-D4gpiFjY.js
	new file:   assets/pywebview-D74jYk6P.css
	new file:   assets/pywebview-D7_PdvyM.js
	new file:   assets/pywebview-D808cNhy.js
	new file:   assets/pywebview-DVgP2-kW.js
	new file:   assets/pywebview-Dee3nQjE.js
	new file:   assets/pywebview-DiP0HdY6.js
	new file:   assets/pywebview-Dp5dN8OO.css
	new file:   assets/pywebview-DuyK2jB1.js
	new file:   assets/pywebview-IqgMfeBe.css
	new file:   assets/pywebview-MkjZQlBu.css
	new file:   assets/pywebview-Q4glvYu5.css
	new file:   assets/pywebview-Rm5Hhqpf.js
	new file:   assets/pywebview-V_UIajJm.js
	new file:   assets/pywebview-hj_EXwAP.css
	new file:   assets/pywebview-ij4pgMq8.css
	new file:   assets/pywebview-leZCedEt.js
	new file:   assets/query-asin-B0yMJ9Or.css
	new file:   assets/query-asin-B5e5m-vs.css
	new file:   assets/query-asin-Bv7Jtgqa.css
	new file:   assets/query-asin-DZwJfwHU.css
	new file:   assets/query-asin.js
	new file:   assets/shop-match-Banz7DWL.css
	new file:   assets/shop-match-BiZP8IGM.css
	new file:   assets/shop-match-BrrGkYV7.css
	new file:   assets/shop-match-CVFsXUvd.css
	new file:   assets/shop-match-CfGJEHz0.css
	new file:   assets/shop-match-CfGWwDtw.css
	new file:   assets/shop-match-D0DGETCs.css
	new file:   assets/shop-match-DFEKOpvV.css
	new file:   assets/shop-match-DNFA8ceR.css
	new file:   assets/shop-match-DhT1CvMP.css
	new file:   assets/shop-match-L0xHTaQ2.css
	new file:   assets/shop-match-MsxXMG_G.css
	new file:   assets/shop-match-g3eRKhTP.css
	new file:   assets/shop-match.js
	new file:   assets/split-BoBVrLdC.css
	new file:   assets/split-BsJfbBqn.css
	new file:   assets/split-CRUIYKS6.css
	new file:   assets/split-DAa_Usoh.css
	new file:   assets/split-DidKJ84l.css
	new file:   assets/split-RNZYJ-zZ.css
	new file:   assets/split-R_8V5xgh.css
	new file:   assets/split-_O6NHqDj.css
	new file:   assets/split-mwLUJT1K.css
	new file:   assets/zh-cn-BjWx61Lu.js
	new file:   assets/zh-cn-C0iS6aoJ.js
	new file:   assets/zh-cn-CuE9Zzgz.js
	new file:   assets/zh-cn-DyKmB71i.js
	new file:   assets/zh-cn-Z9PBnl-n.js
2026-04-28 21:36:49 +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 Je,o as Xe,L as Ge,a as u,c as i,b as v,B as Ye,e as n,a5 as Ze,a6 as es,t as r,V as I,W as ss,X as ts,f as p,U as as,n as te,x as Ie,F as ae,r as be,g as h,h as N,ba as ns,bb as os,bc as ls,E as d,bd as rs,be as us,bf as is,i as Se,bg as cs,bh as ds,bi as fs,bj as hs,bk as vs,T as j,bl as ps,_ as ys,aE as ms,q as gs,s as _s}from"./pywebview-C66x_2Dh.js";import{z as ws}from"./zh-cn-CuE9Zzgz.js";/* empty css *//* empty css */const ks={class:"page-shell module-page"},Is={class:"main-content"},bs={class:"left-panel"},Ss={class:"input-zone"},As={class:"input-row"},Cs=["disabled"],Ts={key:0,class:"empty-candidates"},Ns={key:1,class:"candidate-table-scroll"},$s=["onClick"],Es={class:"run-row"},Qs=["disabled"],qs=["disabled"],Ds={key:2,class:"queue-debug-card"},Ms={class:"queue-debug-line"},Ps={key:0,class:"queue-debug-payload"},Rs={class:"right-panel"},Bs={class:"task-list-wrap"},Fs={class:"clean-result-summary"},Ls={class:"summary-card"},xs={class:"summary-card"},Us={class:"summary-card"},Hs={class:"summary-card"},Os={key:0,class:"empty-tasks narrow"},Vs=["onClick"],js={class:"result-list-wrap"},zs={key:0,class:"empty-tasks"},Ks={key:0,class:"result-subsection"},Ws={class:"task-list"},Js={class:"left split-result-main"},Xs=["title"],Gs={class:"files"},Ys={key:0,class:"files"},Zs={key:1,class:"files"},et={key:2,class:"files"},st={class:"files"},tt={class:"files"},at={key:3,class:"files"},nt={class:"task-right"},ot=["onClick"],lt={key:1,class:"result-subsection"},rt={class:"task-list"},ut={class:"left split-result-main"},it=["title"],ct={class:"files"},dt={key:0,class:"files"},ft={key:1,class:"files"},ht={key:2,class:"files"},vt={class:"files"},pt={key:3,class:"files"},yt={class:"files"},mt={key:4,class:"files"},gt={class:"task-right"},_t=["onClick"],wt=["onClick"],Ae=30,kt=Je({__name:"BrandQueryAsinTab",setup(bt){const M=h(""),z=h([]),P=h([]),m=h([]),_=h([]),$=h({candidateCount:0,processedTaskCount:0,successTaskCount:0,failedTaskCount:0}),R=h(!1),B=h(!1),K=h(!1),y=h(""),W=h(""),f=h([]),c=h(null),b=h(null),S=h(!1),J=h(!1);let A=null;const ne=N(()=>m.value.filter(e=>e.matched&&(e.queryAsins||[]).some(s=>s.asins?.length))),F=N(()=>_.value.filter(e=>!he(e.taskStatus))),X=N(()=>_.value.filter(e=>he(e.taskStatus))),G=N(()=>!!c.value||f.value.length>0),L=N(()=>S.value||G.value),oe=N(()=>S.value&&G.value);function Y(){return typeof window<"u"&&window.localStorage.getItem("uid")||"0"}function le(){return`query-asin:matched:${Y()}`}function re(){return`query-asin:queue-state:${Y()}`}function k(e){return`${(e.shopName||"").trim()}::${e.shopId||""}`}function x(e){return`${e.taskId??0}:${e.resultId??0}`}function ue(e){return new Promise(s=>window.setTimeout(s,e))}function ie(e){const s=e instanceof Error?e.message.toLowerCase():String(e||"").toLowerCase();return s.includes("network error")||s.includes("failed to fetch")||s.includes("timeout")||s.includes("503")||s.includes("502")||s.includes("504")||s.includes("500")||s.includes("load failed")}async function Ce(e,s,o=20){let a=0;for(;;)try{return await e()}catch(l){if(!ie(l)||a>=o-1)throw l;a+=1,s?.(a,o),await ue(j())}}function ce(e,s){return`query-asin:${e}:${s||"shop"}:${Date.now()}`}function Z(e){if(!e)return"-";const s=new Date(e);if(Number.isNaN(s.getTime()))return e;const o=s.getFullYear(),a=String(s.getMonth()+1).padStart(2,"0"),l=String(s.getDate()).padStart(2,"0"),t=String(s.getHours()).padStart(2,"0"),g=String(s.getMinutes()).padStart(2,"0"),se=String(s.getSeconds()).padStart(2,"0");return`${o}-${a}-${l} ${t}:${g}:${se}`}function Te(e){const s=(e||"").trim();return{MATCHED:"已匹配",PENDING:"待匹配",CONFLICT:"需人工确认",INDEX_STALE:"索引过期"}[s]||s||"-"}function Ne(e){const s=(e.matchMessage||"").trim();return s||(e.matched&&e.matchStatus==="MATCHED"?"索引已命中,可推送到 Python 队列":e.matched?"已命中索引,请结合状态列确认":"未命中或未就绪,请检查店铺名")}function $e(e){const s=w(e),o=Math.max(...s.map(a=>a.asins?.length||0),1);return Array.from({length:o},(a,l)=>({shopName:l===0?e.shopName:"",countries:s.map(t=>({country:t.country,asin:t.asins?.[l]||""}))}))}function de(e){const s=w(e),o=s.reduce((l,t)=>l+(t.asins?.length||0),0);return`${s.filter(l=>l.asins?.length).map(l=>l.country).join("、")||"无国家"},共 ${o} 个 ASIN`}function U(e){return(e||[]).map(s=>({country:(s.country||"").trim().toUpperCase(),asins:Array.from(new Set((s.asins||[]).map(o=>(o||"").trim().toUpperCase()).filter(Boolean)))})).filter(s=>s.country&&s.asins.length)}function w(e){return U(e?.queryAsins?.length?e.queryAsins:e?.query_asins)}function H(e){return w(e).some(s=>s.asins.length)}function fe(e){const s=(e||"").trim(),o=[b.value,...f.value,...m.value],a=o.find(t=>(t?.shopName||"").trim()===s&&H(t)),l=o.find(t=>H(t));return w(a||l)}function C(e,s){const o=H(e)?w(e):w(s||void 0);return{...e,queryAsins:o.length?o:fe(e.shopName)}}function he(e){return e==="SUCCESS"||e==="FAILED"||e==="COMPLETED"}function ve(e){return e==="SUCCESS"||e==="COMPLETED"?"已完成":e==="FAILED"?"失败":"执行中"}function pe(e){return e==="SUCCESS"||e==="COMPLETED"?"success":e==="FAILED"?"failed":"running"}function Ee(e){return!!(e.resultId&&(e.fileReady||e.downloadUrl))}function ye(){typeof window>"u"||window.localStorage.setItem(le(),JSON.stringify(m.value))}function Qe(){try{const e=typeof window<"u"?window.localStorage.getItem(le()):null;m.value=e?JSON.parse(e):[]}catch{m.value=[]}}function T(){if(typeof window>"u")return;const e={pendingQueue:f.value,activeTaskId:c.value,activeQueueItem:b.value};window.localStorage.setItem(re(),JSON.stringify(e))}function qe(){try{const e=typeof window<"u"?window.localStorage.getItem(re()):null;if(!e)return;const s=JSON.parse(e);f.value=s.pendingQueue||[],c.value=s.activeTaskId??null,b.value=s.activeQueueItem??null}catch{f.value=[],c.value=null,b.value=null}}function E(){c.value=null,b.value=null,T()}function Q(){G.value||(S.value=!1,K.value=!1,J.value=!1,V(),T())}function De(e){const s=e instanceof Error?e.message:String(e||"");return/记录不存在|任务不存在|不存在|已删除|not\s*found|404/i.test(s)}function Me(e){_.value=_.value.filter(s=>!(e.resultId!=null&&s.resultId===e.resultId||e.taskId!=null&&s.taskId===e.taskId))}function Pe(e,s){const o=new Map;for(const a of e)o.set(k(a),a);for(const a of s)o.set(k(a),a);return Array.from(o.values())}async function q(){z.value=await ns()}async function O(){$.value=await os()}async function ee(){const e=await ls();_.value=(e.items||[]).map(s=>C(s))}async function D(){await Promise.all([O(),ee()])}function me(){if(!c.value){Q();return}if(_.value.some(o=>o.taskId===c.value))return;const s=c.value;E(),y.value=f.value.length?`任务 ${s} 已不存在,已跳过并继续剩余队列`:"当前任务已不存在,已释放本地队列状态",Q()}function Re(e){if(!e.length)return;const s=new Map(e.map(a=>[x(a),C(a)])),o=_.value.map(a=>{const l=s.get(x(a));if(!l)return C(a);const t=H(l)?w(l):w(a).length?w(a):fe(l.shopName||a.shopName);return{...a,...l,queryAsins:t}});for(const a of e){const l=x(a);o.some(t=>x(t)===l)||o.push(C(a))}_.value=o}async function ge(e){const s=Array.from(new Set((e&&e.length?e:F.value.map(a=>a.taskId??0)).filter(a=>Number.isFinite(a)&&a>0)));if(!s.length)return;const o=await ps(s);Re(o.items||[]),(o.missingTaskIds||[]).length&&(await ee(),me())}function Be(){if(V(),!L.value)return;const e=async()=>{A=null,L.value&&(await ge(),L.value&&(A=window.setTimeout(e,j()*2)))};A=window.setTimeout(e,j()*2)}function V(){A&&(window.clearTimeout(A),A=null)}function Fe(e){P.value=e}async function _e(){const e=M.value.trim();if(!e){d.warning("请输入店铺名");return}R.value=!0;try{await rs(e),M.value="",await Promise.all([q(),O()]),d.success("已加入备选区")}catch(s){d.error(s instanceof Error?s.message:"添加失败")}finally{R.value=!1}}async function Le(e){try{await us(e),P.value=P.value.filter(s=>s.id!==e),await Promise.all([q(),O()]),d.success("已删除")}catch(s){d.error(s instanceof Error?s.message:"删除失败")}}function xe(e,s){const o=new Map;for(const a of e)o.set(k(a),a);for(const a of s)o.set(k(a),a);return Array.from(o.values())}async function Ue(){const e=P.value.map(s=>s.shop_name).filter(Boolean);if(!e.length){d.warning("请先勾选备选区店铺");return}B.value=!0;try{const s=await is(e);m.value=xe(m.value,s.items||[]),ye(),d.success(`本次返回 ${s.items?.length||0} 条匹配结果`)}catch(s){d.error(s instanceof Error?s.message:"匹配失败")}finally{B.value=!1}}function He(e){if(L.value){d.warning("队列执行中,请等待当前串行任务结束后再调整");return}m.value=m.value.filter(s=>k(s)!==k(e)),ye()}function Oe(e){return{shopName:e.shopName,matched:e.matched,shopId:e.shopId,platform:e.platform,companyName:e.companyName,matchStatus:e.matchStatus,matchMessage:e.matchMessage,queryAsins:U(e.queryAsins)}}function Ve(e,s){const o=ce(e,s.shopName);return{type:"query-asin-run",ts:Date.now(),data:{taskId:e,user_id:Number(Y())||0,source:"frontend-vue-query-asin",submissionId:o,items:[{shopName:s.shopName,submissionId:o,shopId:s.shopId,platform:s.platform,companyName:s.companyName,matched:s.matched,matchStatus:s.matchStatus,matchMessage:s.matchMessage,queryAsins:U(s.queryAsins)}],query_asins:U(s.queryAsins),query_asin_rows:$e(s)}}}function je(e){return _.value.find(s=>s.taskId===e)}async function ze(e){let s=0;for(;;){try{if(await ge([e]),c.value!==e)return"FAILED";s>0&&(y.value=`任务 ${e} 后端已恢复,继续等待执行结果...`),s=0;const a=je(e)?.taskStatus||"";if(a==="SUCCESS"||a==="FAILED"||a==="COMPLETED")return a}catch(o){if(!ie(o))throw o;if(s+=1,s>=Ae)throw new Error(`任务 ${e} 等待后端恢复超时,请稍后刷新查看状态`);y.value=`任务 ${e} 执行中,正在等待后端服务恢复(${s}/${Ae}...`}await ue(j())}}async function we(){if(!S.value){S.value=!0,K.value=!0,Be();try{const e=Se();if(!e?.enqueue_json)throw new Error("当前客户端未提供 enqueue_json");for(;c.value||f.value.length;){if(c.value){const g=await ze(c.value);y.value=f.value.length>0?`任务 ${c.value} ${g==="SUCCESS"?"已完成":"执行失败"},自动继续下一个(剩余 ${f.value.length} 条)`:`任务 ${c.value} ${g==="SUCCESS"?"已完成":"执行失败"}`,E();continue}const s=f.value.shift();if(T(),!s)break;const o=await Ce(()=>cs([Oe(s)]),(g,se)=>{y.value=`后端服务暂时不可用,正在重试创建任务(${g}/${se}...`}),a=o.items?.[0]?C(o.items[0],s):void 0;if(!a?.taskId||!a.resultId)throw new Error("后端未返回有效任务标识");c.value=o.taskId,b.value=C(s,a),T(),await D();const l=Ve(o.taskId,a);W.value=JSON.stringify(l,null,2);const t=await e.enqueue_json(l);if(!t?.success){await ds(o.taskId,{shops:[{shopName:a.shopName||s.shopName||"",error:t?.error||`任务 ${o.taskId} 推送失败`,shopDone:!0,submissionId:ce(o.taskId,a.shopName||s.shopName)}]}),await D(),y.value=`任务 ${o.taskId} 推送失败,已自动继续下一个任务`,E();continue}y.value=f.value.length>0?`任务 ${o.taskId} 已入队,等待完成后自动继续下一个(剩余 ${f.value.length} 条)`:`任务 ${o.taskId} 已入队,等待执行完成`}y.value="串行队列已执行完成",await D(),d.success("查询ASIN队列已按顺序执行完成")}catch(e){const s=e instanceof Error?e.message:"队列执行失败";y.value=s,d.error(s),await D()}finally{S.value=!1,K.value=!1,V(),T()}}}async function Ke(){J.value=!0,Q();const e=ne.value;if(!e.length){d.warning("请先匹配可用店铺");return}f.value=Pe(f.value,e),T(),y.value=`已加入 ${e.length} 条店铺,开始串行执行`,await we()}async function We(e){if(!e.resultId)return;const s=Se();if(!s?.save_file_from_url_new){d.error("当前客户端未提供下载能力");return}const o=fs(e.resultId),a=e.outputFilename||`${e.shopName||"result"}.xlsx`,l=await s.save_file_from_url_new(o,a);l.success?d.success(`已保存: ${l.path||a}`):l.error&&l.error!=="用户取消"&&d.error(l.error)}async function ke(e){try{if(e.taskId)await hs(e.taskId),c.value===e.taskId&&E();else if(e.resultId)await vs(e.resultId);else throw new Error("缺少可删除的任务标识");await Promise.all([q(),D()]),Q(),d.success("已删除")}catch(s){if(De(s)){e.taskId&&c.value===e.taskId&&E(),Me(e),await q(),Q(),d.success("后端记录已不存在,已同步移除本地记录");return}d.error(s instanceof Error?s.message:"删除失败")}}return Xe(async()=>{Qe(),qe(),await Promise.all([q(),O(),ee()]),me(),(c.value||f.value.length)&&(J.value=!0,y.value=c.value!=null?`检测到未完成队列,继续等待任务 ${c.value} 完成并自动接续后续店铺`:`检测到未完成队列,继续执行剩余 ${f.value.length} 条店铺`,we())}),Ge(()=>{V()}),(e,s)=>{const o=es,a=ss,l=ts;return u(),i("div",ks,[v(Ye,{active:"query-asin"}),n("div",Is,[n("aside",bs,[s[3]||(s[3]=n("div",{class:"section-title"},"店铺输入",-1)),n("div",Ss,[s[1]||(s[1]=n("div",{class:"hint"}," 左侧负责录入店铺并加入备选区,确认命中后推送到 Python 队列。查询ASIN按店铺串行执行上一个任务完成后会自动开始下一个失败也会继续下一个。 ",-1)),n("div",As,[v(o,{modelValue:M.value,"onUpdate:modelValue":s[0]||(s[0]=t=>M.value=t),clearable:"",placeholder:"请输入店铺名后回车或点击添加",onKeyup:Ze(_e,["enter"])},null,8,["modelValue"]),n("button",{type:"button",class:"opt-btn",disabled:R.value,onClick:_e},r(R.value?"添加中...":"添加"),9,Cs)])]),s[4]||(s[4]=n("div",{class:"section-title"},"备选区",-1)),z.value.length?(u(),i("div",Ns,[v(l,{data:z.value,"row-key":"id",height:"260",class:"candidate-table",onSelectionChange:Fe},{default:I(()=>[v(a,{type:"selection",width:"42"}),v(a,{prop:"shop_name",label:"店铺名","min-width":"140","show-overflow-tooltip":""}),v(a,{label:"操作",width:"72",align:"center"},{default:I(({row:t})=>[n("button",{type:"button",class:"link-danger",onClick:g=>Le(t.id)}," 删除 ",8,$s)]),_:1})]),_:1},8,["data"])])):(u(),i("div",Ts," 暂无备选店铺,请先输入并添加 ")),n("div",Es,[n("button",{type:"button",class:"btn-run",disabled:B.value,onClick:Ue},r(B.value?"匹配中...":"匹配店铺"),9,Qs),n("button",{type:"button",class:"btn-run btn-queue",disabled:oe.value||!ne.value.length,onClick:Ke},r(oe.value?"串行执行中...":"推送到 Python 队列"),9,qs)]),s[5]||(s[5]=n("p",{class:"loading-msg"}," 当前页面会按店铺串行推送任务,并在任务成功或失败后自动接续下一个任务。服务端临时重启时会自动重试查询状态,恢复后继续后续店铺。 ",-1)),y.value?(u(),i("div",Ds,[s[2]||(s[2]=n("div",{class:"section-title queue-debug-title"},"队列状态",-1)),n("div",Ms,r(y.value),1),W.value?(u(),i("pre",Ps,r(W.value),1)):p("",!0)])):p("",!0)]),n("section",Rs,[s[14]||(s[14]=n("div",{class:"panel-header"},"匹配与任务",-1)),n("div",Bs,[n("div",Fs,[n("div",Ls,[s[6]||(s[6]=n("span",{class:"summary-label"},"备选店铺",-1)),n("strong",null,r($.value.candidateCount),1)]),n("div",xs,[s[7]||(s[7]=n("span",{class:"summary-label"},"已处理任务",-1)),n("strong",null,r($.value.processedTaskCount),1)]),n("div",Us,[s[8]||(s[8]=n("span",{class:"summary-label"},"成功任务",-1)),n("strong",null,r($.value.successTaskCount),1)]),n("div",Hs,[s[9]||(s[9]=n("span",{class:"summary-label"},"失败任务",-1)),n("strong",null,r($.value.failedTaskCount),1)])]),s[13]||(s[13]=n("div",{class:"subsection-title"},"匹配结果",-1)),m.value.length?(u(),as(l,{key:1,data:m.value,"row-key":k,"highlight-current-row":!1,class:"result-table match-table"},{default:I(()=>[v(a,{prop:"shopName",label:"店铺名","min-width":"120"}),v(a,{label:"匹配",width:"72",align:"center"},{default:I(({row:t})=>[n("span",{class:te(t.matched?"ok":"fail")},r(t.matched?"是":"否"),3)]),_:1}),v(a,{prop:"shopId",label:"店铺 ID","min-width":"120","show-overflow-tooltip":""}),v(a,{prop:"platform",label:"平台",width:"88","show-overflow-tooltip":""}),v(a,{prop:"companyName",label:"公司","min-width":"120","show-overflow-tooltip":""}),v(a,{label:"状态",width:"110","show-overflow-tooltip":""},{default:I(({row:t})=>[Ie(r(Te(t.matchStatus)),1)]),_:1}),v(a,{label:"说明","min-width":"180","show-overflow-tooltip":""},{default:I(({row:t})=>[Ie(r(Ne(t)),1)]),_:1}),v(a,{label:"操作",width:"72",align:"center"},{default:I(({row:t})=>[n("button",{type:"button",class:"link-danger",onClick:g=>He(t)}," 删除 ",8,Vs)]),_:1})]),_:1},8,["data"])):(u(),i("div",Os," 完成“匹配店铺”后,这里会展示匹配结果。 ")),n("div",js,[s[12]||(s[12]=n("div",{class:"result-list-header"},[n("span",null,"任务记录")],-1)),!F.value.length&&!X.value.length?(u(),i("div",zs," 暂无任务记录。推送到 Python 队列后,这里会展示当前任务和历史任务。 ")):(u(),i(ae,{key:1},[F.value.length?(u(),i("div",Ks,[s[10]||(s[10]=n("div",{class:"result-subsection-title"},"当前任务",-1)),n("ul",Ws,[(u(!0),i(ae,null,be(F.value,t=>(u(),i("li",{key:`${t.resultId}-${t.taskId}`,class:"task-item"},[n("div",Js,[n("span",{class:"id",title:t.shopName||""},r(t.shopName||"-"),9,Xs),n("div",Gs,"任务 ID: "+r(t.taskId??"-"),1),t.resultId?(u(),i("div",Ys," 结果 ID: "+r(t.resultId),1)):p("",!0),t.shopId?(u(),i("div",Zs," 店铺 ID: "+r(t.shopId),1)):p("",!0),t.platform?(u(),i("div",et," 平台: "+r(t.platform),1)):p("",!0),n("div",st," 创建时间: "+r(Z(t.createdAt)),1),n("div",tt," ASIN结构: "+r(de(t)),1),t.error?(u(),i("div",at," 错误: "+r(t.error),1)):p("",!0)]),n("div",nt,[n("span",{class:te(["status",pe(t.taskStatus)])},r(ve(t.taskStatus)),3),n("button",{type:"button",class:"btn-delete",onClick:g=>ke(t)}," 删除 ",8,ot)])]))),128))])])):p("",!0),X.value.length?(u(),i("div",lt,[s[11]||(s[11]=n("div",{class:"result-subsection-title"},"历史任务",-1)),n("ul",rt,[(u(!0),i(ae,null,be(X.value,t=>(u(),i("li",{key:`${t.resultId}-${t.taskId}`,class:"task-item"},[n("div",ut,[n("span",{class:"id",title:t.shopName||""},r(t.shopName||"-"),9,it),n("div",ct,"任务 ID: "+r(t.taskId??"-"),1),t.resultId?(u(),i("div",dt," 结果 ID: "+r(t.resultId),1)):p("",!0),t.shopId?(u(),i("div",ft," 店铺 ID: "+r(t.shopId),1)):p("",!0),t.platform?(u(),i("div",ht," 平台: "+r(t.platform),1)):p("",!0),n("div",vt," 创建时间: "+r(Z(t.createdAt)),1),t.finishedAt?(u(),i("div",pt," 完成时间: "+r(Z(t.finishedAt)),1)):p("",!0),n("div",yt," ASIN结构: "+r(de(t)),1),t.error?(u(),i("div",mt," 错误: "+r(t.error),1)):p("",!0)]),n("div",gt,[n("span",{class:te(["status",pe(t.taskStatus)])},r(ve(t.taskStatus)),3),Ee(t)?(u(),i("button",{key:0,type:"button",class:"archive",onClick:g=>We(t)}," 下载结果 ",8,_t)):p("",!0),n("button",{type:"button",class:"btn-delete",onClick:g=>ke(t)}," 删除 ",8,wt)])]))),128))])])):p("",!0)],64))])])])])])}}}),It=ys(kt,[["__scopeId","data-v-fc213f9d"]]);ms.locale("zh-cn");gs(It).use(_s,{locale:ws}).mount("#app");