You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1 lines
17 KiB
1 lines
17 KiB
import{g as $e,B as Se,c as i,a as t,p,q as M,F as g,r as x,H as P,t as a,d as S,I as re,n as C,v as Y,L as ce,l as m,s as Ue,b as pe,m as z,x as u,y as je,z as U,A as Ie,o,_ as Ne}from"./Dv-LAQo6.js";import{u as Re}from"./mz7Huk5H.js";import{u as Te}from"./D7SVvy69.js";import{l as ve}from"./ChQPCk92.js";import{_ as D}from"./CZJGstC3.js";import"./D0vUT4uH.js";const Be={class:"flex items-center justify-between mb-5 flex-wrap gap-3"},Ee={class:"flex items-center gap-3 flex-wrap"},Oe=["value"],Me=["value"],ze={class:"flex items-center justify-between mb-5"},De={class:"flex items-center gap-3"},Ge={class:"font-semibold text-slate-800 text-sm"},qe={class:"region-chip"},Fe={class:"ed-section"},Pe={class:"lang-row"},Ye={class:"lang-field"},He={class:"flex items-center justify-between"},We={class:"any-toggle"},Je=["checked"],Ke={key:0,class:"any-box"},Qe={class:"dir-col"},Xe=["title"],Ze={class:"dir-tip"},et={class:"lang-field"},tt={class:"flex items-center justify-between"},st={class:"any-toggle"},lt=["checked"],nt={key:0,class:"any-box"},at={class:"grid grid-cols-3 gap-3 mt-3"},ot=["value"],it={class:"ed-section"},ut={class:"grid grid-cols-2 gap-3"},dt={value:"",disabled:""},rt=["label"],ct=["value"],pt={key:0,class:"agent-preview"},vt={class:"text-xs text-slate-500"},bt={key:0,class:"text-[11px] text-slate-400"},gt={key:1,class:"text-[11px] text-amber-600"},mt={key:1,class:"ed-warn"},ft={class:"ed-footer"},yt={class:"flex items-center gap-2 text-sm cursor-pointer"},xt={key:0,class:"text-center py-20 text-slate-300"},_t={key:1,class:"rule-list"},kt=["onClick"],ht={class:"prio-cell"},At={class:"prio"},wt={class:"order"},Ct={class:"cond-cell"},Vt={class:"flex items-center gap-2 flex-wrap"},Lt={class:"text-slate-400 font-bold"},$t={key:0,class:"text-[11px] text-slate-400 mt-1"},St={key:0},Ut={class:"agent-cell"},jt={class:"text-xs text-slate-700"},It={class:"text-xs text-slate-500"},Nt={class:"text-right"},Rt={key:0,class:"badge badge-success badge-xs mr-2"},Tt={key:1,class:"badge badge-ghost badge-xs mr-2"},Bt=["onClick"],Et={class:"ct-box"},Ot={class:"grid grid-cols-2 gap-3"},Mt={class:"text-sm font-semibold text-slate-800 mb-1"},zt={class:"text-xs text-slate-600"},Dt={key:0},Gt={key:1,class:"text-sm text-amber-700"},qt={class:"flex gap-3 justify-end mt-5"},Ft={class:"ct-overlay"},Pt={class:"ct-box"},Yt={class:"text-xs text-slate-400 mb-3"},Ht={class:"flex items-center justify-between mb-1"},Wt={class:"flex gap-2"},Jt={class:"sync-region-grid"},Kt=["onClick"],Qt=["checked","onClick"],Xt={class:"flex gap-3 justify-end"},Zt=["disabled"],H="*",es=$e({__name:"calltranslate",setup(ts){const V=[{value:1,label:"中国"},{value:2,label:"美国"},{value:3,label:"东亚"},{value:4,label:"东南亚"},{value:5,label:"南亚"},{value:6,label:"中东"},{value:7,label:"欧洲"},{value:8,label:"俄罗斯"},{value:9,label:"非洲"},{value:10,label:"南美"},{value:11,label:"北美"},{value:12,label:"大洋洲"},{value:13,label:"巴西"},{value:14,label:"印度"}];function W(s){return V.find(e=>e.value===s)?.label??"区域"+s}const _={translate:{label:"🧩 三段式翻译",color:"#059669",bg:"#dcfce7"},"ast-translate":{label:"🚀 端到端翻译",color:"#c2410c",bg:"#fff7ed"}};function G(s){return s&&_[s]?_[s].label:s||"未知"}function J(s){const e=s?_[s]:void 0;return e?{background:e.bg,color:e.color}:{background:"#f1f5f9",color:"#64748b"}}const{webApi:k,consoleApi:be}=Re(),{success:q,error:v}=Te(),f=u(""),F=u([]),L=u(V[0].value),j=u([]),h=u([]),I=u(!1),A=u(null),K=u(null),Q=u(0),n=je({name:"",srcLangs:"",dstLangs:"",srcAny:!1,dstAny:!1,bidir:!0,region:0,priority:100,agentId:"",remark:"",enable:!0}),X=U(()=>h.value.filter(s=>s.type in _)),ge=U(()=>Object.keys(_).map(s=>({type:s,label:_[s].label,items:X.value.filter(e=>e.type===s)})).filter(s=>s.items.length)),b=U(()=>h.value.find(s=>s.id===n.agentId)||null),Z=U(()=>{const s=b.value;if(!s||!s.support_langs)return"";const e=s.support_langs.split(",").map(y=>y.trim()).filter(Boolean);if(!e.length)return"";const c=[...n.srcAny?[]:n.srcLangs.split(","),...n.dstAny?[]:n.dstLangs.split(",")].map(y=>y.trim()).filter(Boolean).filter(y=>!e.includes(y));return c.length?`Agent「${s.name||s.id}」未声明支持:${c.join("、")}`:""});function $(s){return(s||"").trim()===H}function w(s){if($(s))return"任意语言";const e=(s||"").split(",").map(l=>l.trim()).filter(Boolean);return e.length?e.length<=3?e.map(l=>ve(l)).join("、"):e.slice(0,3).map(l=>ve(l)).join("、")+` 等 ${e.length} 种`:"—"}function me(s){return h.value.find(e=>e.id===s)?.name||s||"未配置"}function ee(s){return h.value.find(e=>e.id===s)?.type||""}async function fe(){try{const s=await be("products/list",{});F.value=(s??[]).map(e=>e.name).filter(Boolean)}catch{F.value=[]}}async function ye(){try{const s=await k("getagents",{app_name:f.value});h.value=s?.items??[]}catch{h.value=[]}}async function N(){try{const s=await k("getcalltranslaterules",{app_name:f.value,region:L.value});j.value=s?.items??[]}catch(s){v(s?.message??"加载失败"),j.value=[]}}async function te(){await Promise.all([ye(),N()])}function se(){Ie(()=>K.value?.scrollIntoView({behavior:"smooth",block:"nearest"}))}function le(s){n.name=s?.name??"",n.srcAny=$(s?.src_langs),n.dstAny=$(s?.dst_langs),n.srcLangs=n.srcAny?"":s?.src_langs??"",n.dstLangs=n.dstAny?"":s?.dst_langs??"",n.bidir=s?!!s.bidir:!0,n.region=s?s.region:L.value,n.priority=s?.priority??100,n.agentId=s?.agent_id??"",n.remark=s?.remark??"",n.enable=s?s.enable!==!1:!0}function xe(){A.value=null,le(null),I.value=!0,se()}function _e(s){A.value=s,le(s),I.value=!0,se()}function R(){I.value=!1,A.value=null}function ne(s){s==="src"?(n.srcAny=!n.srcAny,n.srcAny&&(n.srcLangs="")):(n.dstAny=!n.dstAny,n.dstAny&&(n.dstLangs=""))}function ke(){return{id:A.value?A.value.id:0,app_name:f.value,region:n.region,name:n.name.trim(),src_langs:n.srcAny?H:n.srcLangs,dst_langs:n.dstAny?H:n.dstLangs,bidir:n.bidir,agent_id:n.agentId,priority:n.priority||0,enable:n.enable,remark:n.remark.trim()}}async function ae(){const s=ke();if(!s.src_langs)return v("源语言必选(或勾选「任意语言」)"),!1;if(!s.dst_langs)return v("目标语言必选(或勾选「任意语言」)"),!1;if(!s.agent_id)return v("请选择翻译 Agent"),!1;try{const e=await k("savecalltranslaterule",s);return Q.value=e?.id??0,await N(),!0}catch(e){return v(e?.message??"保存失败"),!1}}async function he(){await ae()&&(R(),q("保存成功"))}function Ae(s){window.confirm(`确定删除规则「${s.name||"#"+s.id}」吗?`)&&k("delcalltranslaterules",{ids:[s.id]}).then(()=>{q("已删除"),N()}).catch(e=>v(e?.message??"删除失败"))}const T=u(!1),oe=u(""),r=u([]),ie=U(()=>V.filter(s=>s.value!==n.region));function we(){if(!n.agentId){v("请先选择翻译 Agent");return}oe.value=`将「${n.srcAny?"任意语言":w(n.srcLangs)} ${n.bidir?"⇄":"→"} ${n.dstAny?"任意语言":w(n.dstLangs)}」这条规则复制到其他区域。`,r.value=[],T.value=!0}function ue(s){const e=r.value.indexOf(s);e>=0?r.value.splice(e,1):r.value.push(s)}function de(s){r.value=s?ie.value.map(e=>e.value):[]}async function Ce(){const s=[...r.value];if(T.value=!1,!!await ae()){R();try{const e=await k("synccalltranslaterules",{rule_ids:[Q.value],target_regions:s});q(`已保存并同步到:${s.map(W).join("、")}(${e?.synced??0} 条)`)}catch(e){v(e?.message??"同步失败")}}}const B=u(!1),E=u("zh-CN"),O=u("en-US"),d=u(null);function Ve(){d.value=null,B.value=!0}async function Le(){if(!E.value||!O.value){v("请选择源语言与目标语言");return}try{d.value=await k("testcalltranslaterule",{app_name:f.value,region:L.value,src_lang:E.value,dst_lang:O.value})}catch(s){v(s?.message??"试算失败")}}return Se(async()=>{await fe(),await te()}),(s,e)=>(o(),i("div",null,[t("div",Be,[e[23]||(e[23]=t("div",null,[t("h2",{class:"text-lg font-semibold text-slate-800"},"通话翻译规则"),t("p",{class:"text-xs text-slate-400 mt-1"}," 一条规则覆盖「多源语言 × 多目标语言」,命中后走它指定的 Agent。多条规则按优先级从高到低匹配,第一条命中的生效。 ")],-1)),t("div",Ee,[e[21]||(e[21]=t("span",{class:"text-sm text-slate-500"},"作用域",-1)),p(t("select",{"onUpdate:modelValue":e[0]||(e[0]=l=>f.value=l),class:"select select-bordered select-sm",onChange:te},[e[20]||(e[20]=t("option",{value:""},"全局默认",-1)),(o(!0),i(g,null,x(F.value,l=>(o(),i("option",{key:l,value:l},a(l),9,Oe))),128))],544),[[M,f.value]]),e[22]||(e[22]=t("span",{class:"text-sm text-slate-500"},"区域",-1)),p(t("select",{"onUpdate:modelValue":e[1]||(e[1]=l=>L.value=l),class:"select select-bordered select-sm",onChange:N},[(o(),i(g,null,x(V,l=>t("option",{key:l.value,value:l.value},a(l.label),9,Me)),64))],544),[[M,L.value,void 0,{number:!0}]]),t("button",{class:"btn btn-ghost btn-sm",onClick:Ve},"🔍 选路试算"),t("button",{class:"btn btn-primary btn-sm text-white",onClick:xe},"+ 新增规则")])]),p(t("div",{ref_key:"editorRef",ref:K,class:"editor-panel"},[t("div",ze,[t("div",De,[t("h3",Ge,a(A.value?"编辑规则":"新增规则"),1),t("span",qe,a(f.value||"全局默认"),1)]),t("button",{class:"btn btn-ghost btn-xs",onClick:R},"✕ 关闭")]),t("section",Fe,[e[32]||(e[32]=t("div",{class:"ed-section-title"},"匹配条件",-1)),t("div",Pe,[t("div",Ye,[t("div",He,[e[25]||(e[25]=t("span",{class:"ed-label"},"源语言",-1)),t("label",We,[t("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary",checked:n.srcAny,onChange:e[2]||(e[2]=l=>ne("src"))},null,40,Je),e[24]||(e[24]=S(" 任意语言 ",-1))])]),n.srcAny?(o(),i("div",Ke,"任意源语言")):(o(),re(D,{key:1,modelValue:n.srcLangs,"onUpdate:modelValue":e[3]||(e[3]=l=>n.srcLangs=l),multiple:""},null,8,["modelValue"]))]),t("div",Qe,[t("button",{type:"button",class:C(["dir-btn",{on:n.bidir}]),title:n.bidir?"点击改为单向":"点击改为双向(反向也走这条规则)",onClick:e[4]||(e[4]=l=>n.bidir=!n.bidir)},a(n.bidir?"⇄":"→"),11,Xe),t("span",Ze,a(n.bidir?"双向互译":"单向翻译"),1)]),t("div",et,[t("div",tt,[e[27]||(e[27]=t("span",{class:"ed-label"},"目标语言",-1)),t("label",st,[t("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary",checked:n.dstAny,onChange:e[5]||(e[5]=l=>ne("dst"))},null,40,lt),e[26]||(e[26]=S(" 任意语言 ",-1))])]),n.dstAny?(o(),i("div",nt,"任意目标语言")):(o(),re(D,{key:1,modelValue:n.dstLangs,"onUpdate:modelValue":e[6]||(e[6]=l=>n.dstLangs=l),multiple:""},null,8,["modelValue"]))])]),t("div",at,[t("div",null,[e[29]||(e[29]=t("span",{class:"ed-label"},"生效区域",-1)),p(t("select",{"onUpdate:modelValue":e[7]||(e[7]=l=>n.region=l),class:"select select-bordered select-sm w-full"},[e[28]||(e[28]=t("option",{value:0},"全部区域(兜底)",-1)),(o(),i(g,null,x(V,l=>t("option",{key:l.value,value:l.value},a(l.label),9,ot)),64))],512),[[M,n.region,void 0,{number:!0}]])]),t("div",null,[e[30]||(e[30]=t("span",{class:"ed-label"},"优先级(越大越先匹配)",-1)),p(t("input",{"onUpdate:modelValue":e[8]||(e[8]=l=>n.priority=l),type:"number",class:"input input-bordered input-sm w-full"},null,512),[[Y,n.priority,void 0,{number:!0}]])]),t("div",null,[e[31]||(e[31]=t("span",{class:"ed-label"},"规则名(便于识别)",-1)),p(t("input",{"onUpdate:modelValue":e[9]||(e[9]=l=>n.name=l),class:"input input-bordered input-sm w-full",placeholder:"如 中日韩端到端"},null,512),[[Y,n.name]])])])]),t("section",it,[e[35]||(e[35]=t("div",{class:"ed-section-title"},"命中后使用的 Agent",-1)),t("div",ut,[t("div",null,[e[33]||(e[33]=t("span",{class:"ed-label"},[S("翻译 Agent "),t("i",{class:"req"},"*")],-1)),p(t("select",{"onUpdate:modelValue":e[10]||(e[10]=l=>n.agentId=l),class:"select select-bordered select-sm w-full"},[t("option",dt,a(X.value.length?"请选择 Agent":"(无可用 Agent,请先去 Agent 配置里创建)"),1),(o(!0),i(g,null,x(ge.value,l=>(o(),i("optgroup",{key:l.type,label:l.label},[(o(!0),i(g,null,x(l.items,c=>(o(),i("option",{key:c.id,value:c.id},a(c.name||c.id),9,ct))),128))],8,rt))),128))],512),[[M,n.agentId]])]),t("div",null,[e[34]||(e[34]=t("span",{class:"ed-label"},"备注",-1)),p(t("input",{"onUpdate:modelValue":e[11]||(e[11]=l=>n.remark=l),class:"input input-bordered input-sm w-full",placeholder:"可留空"},null,512),[[Y,n.remark]])])]),b.value?(o(),i("div",pt,[t("span",{class:"type-badge",style:ce(J(b.value.type))},a(G(b.value.type)),5),t("span",vt,a(b.value.description||"(无描述)"),1),b.value.support_langs?(o(),i("span",bt,"支持:"+a(b.value.support_langs),1)):m("",!0),b.value.enable?m("",!0):(o(),i("span",gt,"⚠ 该 Agent 当前为停用状态"))])):m("",!0),Z.value?(o(),i("p",mt,"⚠ "+a(Z.value),1)):m("",!0)]),t("div",ft,[t("label",yt,[p(t("input",{"onUpdate:modelValue":e[12]||(e[12]=l=>n.enable=l),type:"checkbox",class:"checkbox checkbox-sm checkbox-primary"},null,512),[[Ue,n.enable]]),e[36]||(e[36]=t("span",null,"启用",-1)),e[37]||(e[37]=t("span",{class:"text-xs text-slate-400"},"停用的规则不参与选路",-1))]),t("div",{class:"flex gap-2"},[t("button",{class:"btn btn-ghost btn-sm",onClick:R},"取消"),t("button",{class:"btn btn-outline btn-sm",onClick:we},"保存并同步…"),t("button",{class:"btn btn-primary btn-sm text-white",onClick:he},"保存")])])],512),[[P,I.value]]),j.value.length?(o(),i("div",_t,[e[39]||(e[39]=t("div",{class:"rule-head"},[t("span",null,"优先级"),t("span",null,"匹配条件"),t("span",null,"Agent"),t("span",null,"区域"),t("span",{class:"text-right"},"操作")],-1)),(o(!0),i(g,null,x(j.value,(l,c)=>(o(),i("div",{key:l.id,class:C(["rule-row",{off:!l.enable}]),onClick:y=>_e(l)},[t("div",ht,[t("span",At,a(l.priority),1),t("span",wt,"#"+a(c+1),1)]),t("div",Ct,[t("div",Vt,[t("span",{class:C(["lang-badge",{any:$(l.src_langs)}])},a(w(l.src_langs)),3),t("span",Lt,a(l.bidir?"⇄":"→"),1),t("span",{class:C(["lang-badge",{any:$(l.dst_langs)}])},a(w(l.dst_langs)),3)]),l.name||l.remark?(o(),i("div",$t,[S(a(l.name),1),l.remark?(o(),i("span",St," · "+a(l.remark),1)):m("",!0)])):m("",!0)]),t("div",Ut,[t("span",{class:"type-badge",style:ce(J(ee(l.agent_id)))},a(G(ee(l.agent_id))),5),t("span",jt,a(me(l.agent_id)),1)]),t("div",It,a(l.region===0?"全部区域":W(l.region)),1),t("div",Nt,[l.enable?(o(),i("span",Rt,"启用")):(o(),i("span",Tt,"停用")),t("button",{class:"btn btn-ghost btn-xs text-error",onClick:z(y=>Ae(l),["stop"])},"删除",8,Bt)])],10,kt))),128))])):(o(),i("div",xt,[...e[38]||(e[38]=[t("div",{class:"text-5xl mb-3"},"🌐",-1),t("p",{class:"text-sm"},"当前区域还没有翻译规则",-1),t("p",{class:"text-xs mt-1"},"建议先加一条「任意 → 任意」的兜底规则,再往上叠精确规则",-1)])])),p(t("div",{class:"ct-overlay",onClick:e[16]||(e[16]=z(l=>B.value=!1,["self"]))},[t("div",Et,[e[42]||(e[42]=t("h3",{class:"text-base font-semibold text-slate-800 mb-1"},"选路试算",-1)),e[43]||(e[43]=t("p",{class:"text-xs text-slate-400 mb-4"},"用后端运行时同一套匹配逻辑,算一遍这个方向实际会走哪条规则。",-1)),t("div",Ot,[t("div",null,[e[40]||(e[40]=t("span",{class:"ed-label"},"源语言",-1)),pe(D,{modelValue:E.value,"onUpdate:modelValue":e[13]||(e[13]=l=>E.value=l)},null,8,["modelValue"])]),t("div",null,[e[41]||(e[41]=t("span",{class:"ed-label"},"目标语言",-1)),pe(D,{modelValue:O.value,"onUpdate:modelValue":e[14]||(e[14]=l=>O.value=l)},null,8,["modelValue"])])]),d.value?(o(),i("div",{key:0,class:C(["test-result",{miss:!d.value.matched}])},[d.value.matched?(o(),i(g,{key:0},[t("div",Mt," 命中规则:"+a(d.value.rule?.name||"#"+d.value.rule?.id)+"(优先级 "+a(d.value.rule?.priority)+") ",1),t("div",zt,[S(a(w(d.value.rule?.src_langs))+" "+a(d.value.rule?.bidir?"⇄":"→")+" "+a(w(d.value.rule?.dst_langs))+" · Agent:"+a(d.value.agent?.name||d.value.rule?.agent_id)+" ",1),d.value.agent?(o(),i("span",Dt,"("+a(G(d.value.agent.type))+")",1)):m("",!0)])],64)):(o(),i("div",Gt,"没有任何规则命中 —— 这个方向的通话翻译会不可用,建议补一条兜底规则。"))],2)):m("",!0),t("div",qt,[t("button",{class:"btn btn-ghost",onClick:e[15]||(e[15]=l=>B.value=!1)},"关闭"),t("button",{class:"btn btn-primary text-white",onClick:Le},"试算")])])],512),[[P,B.value]]),p(t("div",Ft,[t("div",Pt,[e[45]||(e[45]=t("h3",{class:"text-base font-semibold text-slate-800 mb-1"},"同步到其他区域",-1)),t("p",Yt,a(oe.value),1),e[46]||(e[46]=t("div",{class:"text-xs px-3 py-2 rounded-lg mb-3",style:{background:"#f0fdf4",border:"1px solid #bbf7d0",color:"#15803d"}}," ✦ 同步内容:语言条件、Agent、优先级、启停状态一并复制到目标区域。 ",-1)),t("div",Ht,[e[44]||(e[44]=t("span",{class:"text-xs font-semibold text-slate-500"},"选择目标区域",-1)),t("div",Wt,[t("button",{class:"btn btn-ghost btn-xs",onClick:e[17]||(e[17]=l=>de(!0))},"全选"),t("button",{class:"btn btn-ghost btn-xs",onClick:e[18]||(e[18]=l=>de(!1))},"清空")])]),t("div",Jt,[(o(!0),i(g,null,x(ie.value,l=>(o(),i("label",{key:l.value,class:C(["sync-region-item",{checked:r.value.includes(l.value)}]),onClick:z(c=>ue(l.value),["prevent"])},[t("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary",checked:r.value.includes(l.value),onClick:z(c=>ue(l.value),["stop"])},null,8,Qt),t("span",null,a(l.label),1)],10,Kt))),128))]),e[47]||(e[47]=t("p",{class:"text-[11px] text-slate-400 mb-5"},"⚠ 目标区域已有「同 Agent + 同语言条件」的规则则覆盖,否则新建。",-1)),t("div",Xt,[t("button",{class:"btn btn-ghost",onClick:e[19]||(e[19]=l=>T.value=!1)},"取消"),t("button",{class:"btn btn-primary text-white",disabled:!r.value.length,onClick:Ce}," 保存并同步"+a(r.value.length?"("+r.value.length+" 个区域)":""),9,Zt)])])],512),[[P,T.value]])]))}}),us=Ne(es,[["__scopeId","data-v-c0bab860"]]);export{us as default};
|
|
|