Files
crawler-plugin/app/assets/product-risk.js
2026-05-20 09:05:28 +08:00

2 lines
23 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 mt,o as wt,L as _t,a as c,c as d,b as m,B as bt,e as n,ac as St,ad as Ct,t as f,ae as E,af as It,ag as Tt,x as M,F as O,r as H,ah as Ae,n as Z,f as _,ai as Et,aj as Be,ak as Pt,al as Nt,g as v,h as ee,E as u,am as Rt,an as Dt,ao as $t,ap as Ft,aq as Mt,ar as Ot,as as Ut,at as Lt,au as xe,av as qt,aw as At,ax as Bt,i as fe,ay as xt,az as jt,U as Vt,_ as Kt,q as Jt,s as Ht}from"./pywebview-3bFwh9Cg.js";/* empty css */import{L as Qt}from"./listingFilters-BpGOU_pJ.js";import{c as zt}from"./categorized-timers-JPA-olTr.js";const Gt={class:"page-shell module-page"},Wt={class:"main-content"},Xt={class:"left-panel"},Yt={class:"input-zone"},Zt={class:"input-row"},es=["disabled"],ts={key:0,class:"empty-candidates"},ss={key:1,class:"candidate-table-scroll"},as=["onClick"],ns={class:"country-pref-checks"},os=["checked","disabled","onChange"],ls={class:"country-check-text"},rs={key:2,class:"country-order-panel"},us={class:"country-order-list"},is=["onDragstart","onDrop"],cs={class:"country-drag-label"},ds={key:3,class:"country-pref-status"},fs={class:"listing-filter-row"},vs={class:"run-row"},ps=["disabled"],hs=["disabled"],ys={key:4,class:"queue-debug-card"},ks={class:"queue-debug-line"},gs={key:0,class:"queue-debug-payload"},ms={class:"right-panel"},ws={class:"task-list-wrap"},_s={class:"clean-result-summary pr-summary"},bs={class:"summary-card"},Ss={class:"summary-card"},Cs={class:"summary-card"},Is={class:"summary-card"},Ts={key:0,class:"empty-tasks narrow"},Es=["onClick"],Ps={class:"result-list-wrap"},Ns={key:0,class:"empty-tasks"},Rs={key:0,class:"result-subsection"},Ds={class:"task-list clean-result-list"},$s={class:"left split-result-main"},Fs=["title"],Ms={class:"files"},Os={key:0,class:"files"},Us={key:1,class:"files"},Ls={class:"task-right split-result-actions"},qs=["onClick"],As=["onClick"],Bs={key:1,class:"result-subsection"},xs={class:"task-list clean-result-list"},js={class:"left split-result-main"},Vs=["title"],Ks={class:"files"},Js={key:0,class:"files"},Hs={key:1,class:"files"},Qs={class:"task-right split-result-actions"},zs=["onClick"],Gs=["onClick"],Ws=mt({__name:"BrandProductRiskTab",setup(Ys){const U=v(""),te=v([]),ve=v([]),p=v([]),Q=v(!1),z=v(!1),G=v(!1),se=v(!1),pe=v(!1),y=v(""),L=v(""),he=[{code:"DE",label:"德国"},{code:"UK",label:"英国"},{code:"FR",label:"法国"},{code:"IT",label:"意大利"},{code:"ES",label:"西班牙"}],h=v(["DE","UK","FR","IT","ES"]),D=v("SearchSuppressed"),q=v(null),ae=v(!1),ne=v(!1);let $=null;function ye(e){return he.find(s=>s.code===e)?.label??e}const je=ee(()=>{const e=h.value,t=new Set(e),s=e.map(o=>({code:o,label:ye(o)})),l=he.filter(o=>!t.has(o.code)).map(o=>({code:o.code,label:o.label}));return[...s,...l]});function Ve(e){return h.value.includes(e)}function ke(e){return h.value.length===1&&h.value[0]===e}function Ke(e,t){const s=t.target;if(s){if(!s.checked&&ke(e)){s.checked=!0,u.warning("至少保留 1 个国家");return}Je(e,s.checked)}}function Je(e,t){if(ne.value=!0,t)h.value.includes(e)||(h.value=[...h.value,e]);else{if(h.value.length<=1){u.warning("至少保留 1 个国家");return}h.value=h.value.filter(s=>s!==e)}ge()}function He(e){q.value=e}function Qe(){q.value=null}function ze(e){const t=q.value;if(q.value=null,t==null||t===e)return;ne.value=!0;const s=[...h.value],[l]=s.splice(t,1);s.splice(e,0,l),h.value=s,ge()}function ge(){$&&C.clearTimer("preference-save",$),$=C.setTimeout("preference-save",()=>{$=null,Ge()},450)}async function Ge(){if(!(h.value.length<1)){ae.value=!0;try{await Rt(h.value)}catch(e){u.error(e instanceof Error?e.message:"保存国家顺序失败")}finally{ae.value=!1}}}async function We(){try{const e=await Dt();if(ne.value)return;e?.country_codes?.length&&(h.value=[...e.country_codes])}catch{}}const A=v({candidateCount:0,processedTaskCount:0,successTaskCount:0,failedTaskCount:0}),P=v([]),k=v([]),N=v({}),g=v({}),S=v(null),oe=v(!1);let b=!1;const C=zt("product-risk");function W(){return typeof window<"u"&&window.localStorage.getItem("uid")||"0"}function me(){return`product-risk:tasks:${W()}`}function we(){return`product-risk:task-status:${W()}`}function _e(){return`product-risk:tasks-batch-snapshot:${W()}`}function be(){return`product-risk:matched-items:${W()}`}function X(e,t,s){if(!(typeof window>"u"))try{s?window.localStorage.removeItem(e):window.localStorage.setItem(e,JSON.stringify(t))}catch{}}function Xe(){try{const e=typeof window<"u"?window.localStorage.getItem(we()):null;if(!e)return;const t=JSON.parse(e),s={};for(const[l,o]of Object.entries(t)){const r=Number(l);r>0&&typeof o=="string"&&(s[r]=o)}N.value=s}catch{}}function le(){X(we(),N.value,Object.keys(N.value).length===0)}function Ye(){try{const e=typeof window<"u"?window.localStorage.getItem(_e()):null;if(!e)return;const t=JSON.parse(e),s={};for(const[l,o]of Object.entries(t)){const r=Number(l);r>0&&o&&typeof o=="object"&&(s[r]=o)}g.value=s}catch{}}function B(){X(_e(),g.value,Object.keys(g.value).length===0)}function Ze(){try{const e=typeof window<"u"?window.localStorage.getItem(be()):null;if(!e)return;const t=JSON.parse(e);Array.isArray(t)&&(p.value=t)}catch{}}function x(){X(be(),p.value,p.value.length===0)}function j(e){const t=(e.shopName||"").trim(),s=e.shopId??"";return`${t}${s}`}function Se(e){const t=e instanceof Error?e.message:String(e||"");return/记录不存在|任务不存在|不存在|已删除|not\s*found|404/i.test(t)}function F(e){if(!e.length)return;const t=new Set(e.map(s=>j(s)));p.value=p.value.filter(s=>!t.has(j(s))),x()}function et(e){P.value=P.value.filter(t=>!(e.resultId!=null&&t.resultId===e.resultId||e.taskId!=null&&t.taskId===e.taskId))}async function tt(e){const t=j(e),s=[...p.value];p.value=p.value.filter(o=>j(o)!==t),x();const l=(e.shopName||"").trim();if(!l){u.success("已从匹配结果中移除");return}try{(await $t(l))?.removed&&(await T(),await I(),V()),u.success("已从匹配结果中移除")}catch(o){if(Se(o)){await T(),await I(),V(),u.success("后端记录已不存在,已同步移除本地记录");return}p.value=s,x(),u.error(o instanceof Error?o.message:"同步后端失败")}}function V(){for(const e of[...k.value])P.value.some(s=>s.taskId===e)||R(e)}async function Ce(e){try{if(e.resultId!=null&&e.resultId>0)await Ft(e.resultId);else if(e.taskId!=null&&e.taskId>0)await Mt(e.taskId);else{u.warning("无法删除:缺少记录标识");return}e.taskId!=null&&e.taskId>0&&R(e.taskId),F([e]),await T(),await I(),V(),u.success("已删除")}catch(t){if(Se(t)){e.taskId!=null&&e.taskId>0&&R(e.taskId),F([e]),et(e),await I(),V(),u.success("后端记录已不存在,已同步移除本地记录");return}u.error(t instanceof Error?t.message:"删除失败")}}function st(){try{const e=typeof window<"u"?window.localStorage.getItem(me()):null;if(!e){k.value=[];return}const t=JSON.parse(e);k.value=Array.isArray(t)?t.filter(s=>typeof s=="number"):[]}catch{k.value=[]}}function Ie(){X(me(),k.value,k.value.length===0)}function Te(e){k.value.includes(e)||(k.value=[...k.value,e],Ie())}function R(e){if(k.value=k.value.filter(t=>t!==e),Ie(),delete N.value[e],le(),g.value[e]){const t={...g.value};delete t[e],g.value=t,B()}}function at(e){ve.value=e||[]}async function I(){try{A.value=await Ot()}catch{}}async function re(){try{te.value=await Ut(),await I()}catch(e){u.error(e instanceof Error?e.message:"加载备选失败")}}async function T(){try{P.value=(await Lt()).items||[]}catch{P.value=[]}}function Ee(e){return e&&N.value[e]||""}function Pe(e){const t=Ee(e);return t==="SUCCESS"||t==="FAILED"}const ue=ee(()=>{const e=P.value.filter(s=>s.taskId&&k.value.includes(s.taskId)&&!Pe(s.taskId)),t=new Set(e.map(s=>s.taskId).filter(s=>typeof s=="number"));for(const s of k.value){if(t.has(s))continue;const r=(g.value[s]?.items||[])[0];r&&e.push(r)}return e}),ie=ee(()=>P.value.filter(e=>!e.taskId||!k.value.includes(e.taskId)||Pe(e.taskId))),nt=ee(()=>ue.value.length>0||ie.value.length>0),ot=["无法连接到后端服务","bad gateway","gateway timeout","network error","timeout","502","503","504"];function ce(e){return b?Promise.resolve():C.sleep("queue-wait",e)}function lt(){C.clearCategory("queue-wait")}function Ne(e){const t=(e instanceof Error?e.message:String(e||"")).toLowerCase();return ot.some(s=>t.includes(s.toLowerCase()))}async function Re(e,t=10){let s=0;for(;;){if(b)throw new Error("component disposed");try{return await jt(e)}catch(l){if(s+=1,!Ne(l)||s>=t)throw l;y.value=`后端服务暂时不可用,正在重试创建任务(${s}/${t}...`,await ce(K())}}}async function De(){const e=k.value.filter(t=>t>0);if(e.length)try{const t=await xe(e);let s=!1;const l={...g.value};for(const o of t.items||[]){const r=o.task?.id,i=o.task?.status;if(typeof r=="number"&&r>0){const a=l[r];l[r]=a?{...a,task:{...a.task||{},...o.task||{}}}:o,i&&(N.value[r]=i,(i==="SUCCESS"||i==="FAILED")&&(R(r),s=!0))}}g.value=l,B(),le(),s&&(await T(),await I())}catch{}}function K(){return Vt()}function $e(e=!1){if(S.value){if(!e)return;C.clearTimer("task-poll",S.value),S.value=null}const t=async()=>{if(S.value=null,!b){if(oe.value){$e();return}if(k.value.length){oe.value=!0;try{await De()}finally{oe.value=!1}!b&&k.value.length>0&&(S.value=C.setTimeout("task-poll",t,K()))}}};b||(e?t():S.value=C.setTimeout("task-poll",t,K()))}function J(e=!1){S.value&&!e||$e(e)}function rt(){S.value&&(C.clearTimer("task-poll",S.value),S.value=null)}async function Fe(e){let t=0;const s=30;for(;;){if(b)return"STOPPED";try{const l=await xe([e]);t>0&&(y.value=`任务 ${e} 后端已恢复,继续等待执行结果...`),t=0;const o=(l.items||[]).find(i=>i.task?.id===e),r=o?.task?.status||"";if(o){const i=g.value[e];g.value={...g.value,[e]:i?{...i,task:{...i.task||{},...o.task||{}}}:o},B()}if(r&&(N.value[e]=r,le()),r==="SUCCESS"||r==="FAILED")return R(e),await T(),await I(),r}catch(l){if(!Ne(l))throw l;if(t+=1,t>=s)throw new Error(`任务 ${e} 等待后端恢复超时,请稍后手动刷新查看状态`);y.value=`任务 ${e} 运行中,正在等待后端服务恢复(${t}/${s}...`,(t===1||t%5===0)&&u.warning(`任务 ${e} 运行中,后端服务暂时不可用,正在自动重试`),await ce(K());continue}await ce(K())}}async function Me(){const e=U.value.trim();if(!e){u.warning("请输入店铺名称");return}Q.value=!0;try{await qt(e),U.value="",await re(),u.success("已加入备选")}catch(t){u.error(t instanceof Error?t.message:"保存失败")}finally{Q.value=!1}}async function ut(e){try{await At(e.id),await re(),p.value=[],x(),u.success("已删除")}catch(t){u.error(t instanceof Error?t.message:"删除失败")}}function it(){const e=new Set,t=U.value.trim();t&&e.add(t);for(const s of ve.value)s?.shop_name?.trim()&&e.add(s.shop_name.trim());return[...e]}function ct(e,t){const s=new Map;for(const r of t){const i=(r.shopName||"").trim();i&&s.set(i,r)}const l=new Set,o=[];for(const r of e){const i=(r.shopName||"").trim();i&&s.has(i)?(o.push(s.get(i)),l.add(i)):o.push(r)}for(const r of t){const i=(r.shopName||"").trim();if(!i){o.push(r);continue}l.has(i)||(o.push(r),l.add(i))}return o}async function dt(){const e=it();if(!e.length){u.warning("请勾选备选店铺,或在输入框中填写店名(可与勾选合并)");return}z.value=!0;try{const s=(await Bt(e)).items||[];p.value=ct(p.value,s),x(),s.length?u.success(`本次匹配 ${s.length} 个店铺名,表格共 ${p.value.length}`):u.warning("未返回匹配结果")}catch(t){u.error(t instanceof Error?t.message:"匹配失败")}finally{z.value=!1}}function de(e){const t=e.taskId;return t?Ee(t)||e.taskStatus||"":e.taskStatus||""}function Oe(e){const t=de(e);return t==="SUCCESS"?"已完成":t==="FAILED"?"失败":t==="RUNNING"?"执行中":e.success?"已完成":"等待中"}function Ue(e){const t=de(e);return t==="SUCCESS"||e.success?"success":t==="FAILED"?"failed":"running"}function Le(e){return!e.resultId||!e.fileReady&&!e.downloadUrl?!1:de(e)==="SUCCESS"||e.success===!0}async function qe(e){if(!e.resultId)return;const t=fe(),s=xt(e.resultId),l=e.outputFilename||`${e.shopName||"result"}.zip`;if(!t?.save_file_from_url_new){u.error("当前客户端未提供 save_file_from_url_new无法下载文件");return}const o=await t.save_file_from_url_new(s,l);o.success?u.success(`已保存:${o.path||l}`):o.error&&o.error!=="用户取消"&&u.error(o.error)}function ft(e){const t=(e||"").trim();return{MATCHED:"已匹配",PENDING:"待匹配",CONFLICT:"需人工确认",INDEX_STALE:"索引过期"}[t]||t||"—"}function vt(e){const t=(e.matchMessage||"").trim();return t||(e.matched&&e.matchStatus==="MATCHED"?"紫鸟索引已命中,可推送队列;打开店铺地址由 Python 侧处理":e.matched?"已关联索引,请结合状态列查看是否可推送":"未命中或未就绪,请检查店铺名与索引刷新")}async function pt(){pe.value=!0,await gt()}function ht(){return p.value.find(e=>e.matched)}function yt(){return D.value==="SearchSuppressed"||D.value==="DetailPageRemoved"}async function kt(e){const t=fe();if(!t?.enqueue_json){u.error("当前环境未启用 pywebview enqueue_json");return}const s=await Re(e),l=s.taskId;g.value={...g.value,[l]:{task:{id:l,status:"RUNNING"},items:s.items}},B(),Te(l),J(!0);const o={type:"product-risk-resolve-run",ts:Date.now(),data:{taskId:l,items:e,country_codes:[...h.value],risk_listing_filter:D.value}};L.value=JSON.stringify(o,null,2);const r=await t.enqueue_json(o);if(!r?.success)throw R(l),new Error("任务 "+l+" 推送失败:"+(r?.error||"未知错误"));F(e),y.value="任务 "+l+" 已入队,共 "+e.length+" 个店铺,等待执行完成...";const i=await Fe(l);if(y.value="任务 "+l+(i==="SUCCESS"?" 已完成":" 执行失败"),i!=="SUCCESS")throw new Error(y.value)}async function gt(){if(b||se.value)return;if(!p.value.length){u.warning("请先匹配店铺");return}const e=fe();if(!e?.enqueue_json){u.error("当前环境未启用 pywebview enqueue_json");return}const t=p.value.filter(o=>o.matched);if(!t.length){u.warning("没有已匹配的店铺可推送");return}se.value=!0,G.value=!0,L.value="";let s=0,l=0;try{if(yt()){await kt(t),u.success("店铺推送已完成:成功 "+t.length+" 条,失败 0 条"),await T(),J(!0);return}let o=0;for(;!b&&pe.value;){const r=ht();if(!r)break;o+=1;try{const i=await Re([r]),a=i.taskId;g.value={...g.value,[a]:{task:{id:a,status:"RUNNING"},items:i.items}},B(),Te(a),J(!0);const w={type:"product-risk-resolve-run",ts:Date.now(),data:{taskId:a,items:[r],country_codes:[...h.value],risk_listing_filter:D.value}};L.value=JSON.stringify(w,null,2);const Y=await e.enqueue_json(w);if(!Y?.success){R(a),l+=1,y.value="第 "+o+" 条推送失败:"+(Y?.error||"未知错误")+",已自动继续下一条",u.error(y.value),F([r]);continue}if(F([r]),y.value="任务 "+a+" 已入队,等待执行完成...",await Fe(a)!=="SUCCESS"){l+=1,y.value="任务 "+a+" 执行失败,已自动继续下一条",u.error(y.value);continue}s+=1,y.value="任务 "+a+" 已完成"}catch(i){if(b)break;l+=1,y.value="第 "+o+" 条任务处理失败,已自动继续下一条:"+(i instanceof Error?i.message:"未知错误"),u.error(y.value),F([r]);continue}}(s>0||l>0)&&u.success("店铺推送已完成:成功 "+s+" 条,失败 "+l+" 条"),await T(),J(!0)}catch(o){if(b)return;y.value=o instanceof Error?o.message:"推送异常",u.error(y.value)}finally{se.value=!1,G.value=!1}}return wt(()=>{st(),Xe(),Ye(),Ze(),re().catch(()=>{}),We().catch(()=>{}),T().then(()=>(V(),De())).catch(()=>{}),I().catch(()=>{}),k.value.length&&J(!0)}),_t(()=>{b=!0,rt(),lt(),C.clearScope(),$&&C.clearTimer("preference-save",$)}),(e,t)=>{const s=Ct,l=It,o=Tt,r=Pt,i=Nt;return c(),d("div",Gt,[m(bt,{active:"product-risk"}),n("div",Wt,[n("aside",Xt,[t[7]||(t[7]=n("div",{class:"section-title"},"店铺名称",-1)),n("div",Yt,[t[3]||(t[3]=n("div",{class:"hint"},"输入店铺名后点「确认」加入下方备选区(按当前登录用户保存)。仅索引可命中的店铺可入库。勾选备选后点「匹配店铺」,再「推送到 Python 队列」。",-1)),n("div",Zt,[m(s,{modelValue:U.value,"onUpdate:modelValue":t[0]||(t[0]=a=>U.value=a),clearable:"",placeholder:"请输入店铺名称",onKeyup:St(Me,["enter"])},null,8,["modelValue"]),n("button",{type:"button",class:"opt-btn",disabled:Q.value,onClick:Me},f(Q.value?"保存中…":"确认"),9,es)])]),t[8]||(t[8]=n("div",{class:"section-title"},"备选区域",-1)),te.value.length?(c(),d("div",ss,[m(o,{data:te.value,"row-key":"id",height:"240",class:"candidate-table",onSelectionChange:at},{default:E(()=>[m(l,{type:"selection",width:"42"}),m(l,{prop:"shop_name",label:"店铺名","min-width":"120","show-overflow-tooltip":""}),m(l,{label:"操作",width:"72",align:"center"},{default:E(({row:a})=>[n("button",{type:"button",class:"link-danger",onClick:w=>ut(a)},"删除",8,as)]),_:1})]),_:1},8,["data"])])):(c(),d("div",ts,"暂无备选店铺,请先输入并确认")),t[9]||(t[9]=n("div",{class:"section-title"},"处理国家与顺序",-1)),t[10]||(t[10]=n("p",{class:"hint country-pref-hint"},[M(" 勾选需要处理的站点(可只选 23 国);上方勾选区"),n("strong",null,"先按已选顺序"),M("排列,其余未选国家排在后面。拖拽下方列表调整顺序后会与上方同步。设置会按当前登录用户保存。 ")],-1)),n("div",ns,[(c(!0),d(O,null,H(je.value,a=>(c(),d("label",{key:a.code,class:"country-check-row"},[n("input",{type:"checkbox",class:"country-check-input",checked:Ve(a.code),disabled:ke(a.code),onChange:w=>Ke(a.code,w)},null,40,os),n("span",ls,f(a.label)+""+f(a.code)+"",1)]))),128))]),h.value.length?(c(),d("div",rs,[t[5]||(t[5]=n("div",{class:"country-order-caption"},"已选顺序(拖拽 ⋮⋮ 调整)",-1)),n("div",us,[(c(!0),d(O,null,H(h.value,(a,w)=>(c(),d("div",{key:a,class:Z(["country-drag-row",{dragging:q.value===w}]),draggable:"true",onDragstart:Y=>He(w),onDragend:Qe,onDragover:t[1]||(t[1]=Ae(()=>{},["prevent"])),onDrop:Ae(Y=>ze(w),["prevent"])},[t[4]||(t[4]=n("span",{class:"drag-handle",title:"拖动排序"},"⋮⋮",-1)),n("span",cs,f(ye(a))+""+f(a)+"",1)],42,is))),128))])])):_("",!0),ae.value?(c(),d("div",ds,"保存中…")):_("",!0),t[11]||(t[11]=n("div",{class:"section-title"},"商品列表筛选",-1)),t[12]||(t[12]=n("p",{class:"hint listing-filter-hint"},"与「推送到 Python 队列」一并下发,供 Python 区分处理场景。",-1)),n("div",fs,[m(i,{modelValue:D.value,"onUpdate:modelValue":t[2]||(t[2]=a=>D.value=a),class:"listing-filter-select",teleported:"",placeholder:"选择筛选类型"},{default:E(()=>[(c(!0),d(O,null,H(Et(Qt),a=>(c(),Be(r,{key:a.value,label:a.label,value:a.value},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),n("div",vs,[n("button",{type:"button",class:"btn-run",disabled:z.value,onClick:dt},f(z.value?"匹配中…":"匹配店铺"),9,ps),n("button",{type:"button",class:"btn-run btn-queue",disabled:G.value||!p.value.length,onClick:pt},f(G.value?"推送中…":"推送到 Python 队列"),9,hs)]),t[13]||(t[13]=n("p",{class:"loading-msg"},[M("在搜索结果中禁止显示、详情页面已删除会把匹配店铺合并为一个任务入队避免同时打开多个紫鸟窗口其它筛选仍按店铺逐条入队。Python 每处理完一店可 POST "),n("code",null,"/api/product-risk-resolve/tasks/{taskId}/result"),M("(可多次,每次可只含已完成的店铺);全部完成后任务结束。前端轮询任务状态。 ")],-1)),y.value?(c(),d("div",ys,[t[6]||(t[6]=n("div",{class:"section-title queue-debug-title"},"推送结果",-1)),n("div",ks,f(y.value),1),L.value?(c(),d("pre",gs,f(L.value),1)):_("",!0)])):_("",!0)]),n("section",ms,[t[22]||(t[22]=n("div",{class:"panel-header"},"匹配与任务",-1)),n("div",ws,[n("div",_s,[n("div",bs,[t[14]||(t[14]=n("span",{class:"summary-label"},"备选店铺数",-1)),n("strong",null,f(A.value.candidateCount),1)]),n("div",Ss,[t[15]||(t[15]=n("span",{class:"summary-label"},"已结束任务",-1)),n("strong",null,f(A.value.processedTaskCount),1)]),n("div",Cs,[t[16]||(t[16]=n("span",{class:"summary-label"},"成功任务",-1)),n("strong",null,f(A.value.successTaskCount),1)]),n("div",Is,[t[17]||(t[17]=n("span",{class:"summary-label"},"失败任务",-1)),n("strong",null,f(A.value.failedTaskCount),1)])]),t[21]||(t[21]=n("div",{class:"subsection-title"},"匹配结果",-1)),p.value.length?(c(),Be(o,{key:1,data:p.value,"row-key":j,"highlight-current-row":!1,class:"result-table match-table"},{default:E(()=>[m(l,{prop:"shopName",label:"店铺名","min-width":"100"}),m(l,{label:"匹配",width:"72",align:"center"},{default:E(({row:a})=>[n("span",{class:Z(a.matched?"ok":"fail")},f(a.matched?"是":"否"),3)]),_:1}),m(l,{prop:"shopId",label:"店铺ID","min-width":"120","show-overflow-tooltip":""}),m(l,{prop:"platform",label:"平台",width:"88","show-overflow-tooltip":""}),m(l,{prop:"companyName",label:"公司","min-width":"100","show-overflow-tooltip":""}),m(l,{label:"状态",width:"100","show-overflow-tooltip":""},{default:E(({row:a})=>[M(f(ft(a.matchStatus)),1)]),_:1}),m(l,{label:"说明","min-width":"140","show-overflow-tooltip":""},{default:E(({row:a})=>[M(f(vt(a)),1)]),_:1}),m(l,{label:"操作",width:"72",align:"center"},{default:E(({row:a})=>[n("button",{type:"button",class:"link-danger",onClick:w=>tt(a)},"删除",8,Es)]),_:1})]),_:1},8,["data"])):(c(),d("div",Ts,"完成「匹配店铺」后,在此展示紫鸟索引匹配结果,供核对后再推送队列。")),n("div",Ps,[t[20]||(t[20]=n("div",{class:"result-list-header"},[n("span",null,"处理记录")],-1)),nt.value?(c(),d(O,{key:1},[ue.value.length?(c(),d("div",Rs,[t[18]||(t[18]=n("div",{class:"result-subsection-title"},"当前任务",-1)),n("ul",Ds,[(c(!0),d(O,null,H(ue.value,a=>(c(),d("li",{key:`cur-${a.resultId}-${a.taskId}`,class:"task-item split-result-item"},[n("div",$s,[n("span",{class:"id",title:a.shopName||""},f(a.shopName||"-"),9,Fs),n("div",Ms,"任务 ID"+f(a.taskId??"-"),1),a.platform?(c(),d("div",Os,"平台:"+f(a.platform),1)):_("",!0),a.error?(c(),d("div",Us,"错误:"+f(a.error),1)):_("",!0)]),n("div",Ls,[n("span",{class:Z(["status",Ue(a)])},f(Oe(a)),3),Le(a)?(c(),d("button",{key:0,type:"button",class:"download",onClick:w=>qe(a)}," 下载 ",8,qs)):_("",!0),n("button",{type:"button",class:"btn-delete",onClick:w=>Ce(a)},"删除",8,As)])]))),128))])])):_("",!0),ie.value.length?(c(),d("div",Bs,[t[19]||(t[19]=n("div",{class:"result-subsection-title"},"历史记录",-1)),n("ul",xs,[(c(!0),d(O,null,H(ie.value,a=>(c(),d("li",{key:`his-${a.resultId}-${a.taskId}`,class:"task-item split-result-item"},[n("div",js,[n("span",{class:"id",title:a.shopName||""},f(a.shopName||"-"),9,Vs),n("div",Ks,"任务 ID"+f(a.taskId??"-"),1),a.outputFilename?(c(),d("div",Js,"文件:"+f(a.outputFilename),1)):_("",!0),a.error?(c(),d("div",Hs,"错误:"+f(a.error),1)):_("",!0)]),n("div",Qs,[n("span",{class:Z(["status",Ue(a)])},f(Oe(a)),3),Le(a)?(c(),d("button",{key:0,type:"button",class:"download",onClick:w=>qe(a)}," 下载 ",8,zs)):_("",!0),n("button",{type:"button",class:"btn-delete",onClick:w=>Ce(a)},"删除",8,Gs)])]))),128))])])):_("",!0)],64)):(c(),d("div",Ns,"暂无处理记录。推送队列并等待 Python 回传后,将在此显示下载链接。"))])])])])])}}}),Xs=Kt(Ws,[["__scopeId","data-v-bde90137"]]);Jt(Xs).use(Ht).mount("#app");