Files
kefu/deploy/token-usage-20260917/payload/admin-web/apps/web-antd/dist/js/desktop-config-C0xFrycF.js
T
2026-09-21 10:34:06 +08:00

1 line
14 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 e,E as t,On as n,_ as r,b as i,bt as a,ct as o,g as s,gn as ee,k as te,mt as c,o as l,qt as u,tr as d,v as ne,vn as f,y as p}from"./runtime-core.esm-bundler-DkysjgTd.js";import{t as m}from"./objectSpread2-BmonrgTA.js";import{n as h}from"./objectWithoutProperties-BjoYlK0I.js";import{t as re}from"./use-access-ObRBpYsT.js";import{h as ie}from"./useApi-CROJJdhE-oP73ypFI.js";import{n as g,t as ae}from"./form-CZK1ilUa.js";import{t as _}from"./select-DyNDAEL2.js";import{u as oe,w as se}from"./console-2d_MKq1R.js";import{a as v}from"./config-provider-D1kcLCP5.js";import{t as y}from"./alert-CkUknOsQ.js";import{t as b}from"./button-B2y2NpJm.js";import{t as x}from"./card-D3WO92mr.js";import{n as S,t as C}from"./descriptions-BP4B3brJ.js";import{r as ce,t as w}from"./input-DgEff0DC.js";import{t as T}from"./input-number-B39v8Wj_.js";import{t as E}from"./switch-CtSw_Hgg.js";var le={class:`p-5`},ue={class:`mb-2`},de={key:0,class:`mt-2`},fe={class:`mt-1 text-xs text-gray-500`},pe={class:`grid grid-cols-1 gap-x-8 gap-y-1 md:grid-cols-2`},me={class:`min-w-0`},he={class:`text-sm font-medium`},ge={class:`mt-0.5 text-xs text-gray-500`},_e={class:`grid grid-cols-1 gap-x-8 md:grid-cols-2`},D={class:`grid grid-cols-1 gap-x-6 md:grid-cols-3`},O={class:`mt-1 text-xs text-gray-500`},k={class:`w-40 shrink-0`},A={class:`min-w-0 flex-1`},j={key:1,class:`mt-2 text-xs text-gray-500`},M={class:`grid grid-cols-1 gap-x-6 md:grid-cols-4`},N={key:0,class:`mt-1 text-xs text-red-500`},P={key:1,class:`mt-1 text-xs text-gray-500`},F={key:0,class:`sticky bottom-0 -mx-5 border-t bg-white/90 px-5 py-3 backdrop-blur dark:bg-black/70`},I=te({__name:`desktop-config`,setup(te){let{hasAccessByCodes:I}=re(),L=s(()=>I([`config:write`])),ve=s(()=>I([`model:read`])),R=ie(),z=f(!1),B=f(!1),V=f(0),H=f(``),U=f(``),W=f(``),G=f(``),K=f(``),q=f(`[]`),J=f(``),Y=ee({ARCHIVE_AUTO_BACKUP_ENABLED:!0,ARCHIVE_AUTO_BACKUP_INTERVAL_MINUTES:60,AI_AGENT_NAME:``,AI_GATEWAY_URL:``,ZYT_LOGIN_API_URL:``,AI_CONTEXT_ENABLED:!0,AI_CONTEXT_MAX_ROUNDS:8,AI_COUNTER_INSULT_ENABLED:!1,AI_DEVELOPMENT_MODE:!1,AI_ENABLED:!0,AI_HOSPITAL_NAME:``,AI_MCP_ENABLED:!1,AI_MCP_MAX_ROUNDS:5,AI_MCP_SERVERS:[],AI_REVIEW_RULES:[],AI_UI_GUARD_ENABLED:!0,AI_USE_VISION:!0}),ye=[{key:`AI_ENABLED`,label:`启用 AI 自动回复`,hint:`总开关。关掉之后客户端只监听不回复。`},{key:`AI_USE_VISION`,label:`启用视觉识别`,hint:`图片和表情包走视觉模型识别,OCR 认不出时兜底。用哪个模型看「角色编排」里的媒体消息专用模型。`},{key:`AI_UI_GUARD_ENABLED`,label:`人工操作保护`,hint:`检测到有人在操作鼠标键盘时暂停自动化,避免抢焦点。`},{key:`AI_CONTEXT_ENABLED`,label:`携带上下文`,hint:`把最近几轮对话一起发给模型。关掉会省 token,但答复会失忆。`},{key:`AI_COUNTER_INSULT_ENABLED`,label:`应对辱骂`,hint:`客户情绪激动时用专门的话术回应,而不是照常答业务问题。`},{key:`AI_MCP_ENABLED`,label:`启用 MCP 工具`,hint:`允许模型调用挂号登记、客户查询等外部工具。工具在客户端本机执行。`},{key:`AI_DEVELOPMENT_MODE`,label:`开发模式`,hint:`打印详细日志、跳过部分节流。生产环境请关闭。`}];function X(){return Z.apply(this,arguments)}function Z(){return Z=h(function*(){z.value=!0;try{var e;let t=yield oe();Object.assign(Y,t.config),q.value=JSON.stringify((e=t.config.AI_MCP_SERVERS)==null?[]:e,null,2),V.value=t.version,H.value=t.updated_at,U.value=t.updated_by,W.value=t.model_settings_moved_to,G.value=t.gateway_url_effective,K.value=t.login_api_url_effective}finally{z.value=!1}}),Z.apply(this,arguments)}function be(){Y.AI_REVIEW_RULES.push({label:``,keywords:[],enabled:!0})}function xe(e){Y.AI_REVIEW_RULES.splice(e,1)}function Se(){for(let[e,t]of Y.AI_REVIEW_RULES.entries()){if(!t.label.trim())return`第 ${e+1} 条规则没有填名称`;if(t.keywords.length===0)return`规则「${t.label}」至少要有一个关键词,否则永远不会命中`}return``}function Q(){try{let e=JSON.parse(q.value||`[]`);return Array.isArray(e)?(J.value=``,e):(J.value=`JSON 根节点必须是数组`,null)}catch(e){return J.value=`不是有效的 JSON:${e.message}`,null}}function Ce(){return $.apply(this,arguments)}function $(){return $=h(function*(){let e=Q();if(e===null){v.warning(`MCP 服务器配置不是有效 JSON,请先修正`);return}let t=Se();if(t){v.warning(t);return}B.value=!0;try{let t=yield se(m(m({},Y),{},{AI_MCP_SERVERS:e}));v.success(`已发布为 v${t.version},桌面端下次同步时生效`),yield X()}finally{B.value=!1}}),$.apply(this,arguments)}return o(X),(o,s)=>(c(),i(`div`,le,[e(n(y),{class:`mb-4`,type:`warning`,"show-icon":``,message:`这份配置会下发到每一台桌面客户端`,description:`保存即产生新版本号,客户端下次同步就会拿到。改错一个字段是全线生效的,不是只影响你自己这台。`}),e(n(y),{class:`mb-4`,type:`info`,"show-icon":``},{message:u(()=>[...s[11]||(s[11]=[t(`模型配置不在这里`,-1)])]),description:u(()=>[r(`p`,ue,[s[12]||(s[12]=t(` 服务类型、API 地址、API Key、模型名称、温度、最大 tokens、请求超时——这些以前在本页的设置, 现在统一在 `,-1)),r(`b`,null,d(W.value||`AI 模型 → 模型清单 / 角色编排`),1),s[13]||(s[13]=t(`。 `,-1))]),s[16]||(s[16]=r(`p`,{class:`mb-2 text-xs`},` 搬走有三个原因:同一件事两个地方能配迟早会不一致;密钥留在这份配置里就必须明文下发到每一台客户端, 而模型清单里是加密存储、只返遮罩值;一个客户只能配一个模型的话,双模型并发和裁判根本无从谈起。 `,-1)),ve.value?(c(),i(`div`,de,[e(n(b),{size:`small`,onClick:s[0]||(s[0]=e=>n(R).push(`/model/catalog`))},{default:u(()=>[...s[14]||(s[14]=[t(`去模型清单`,-1)])]),_:1}),e(n(b),{size:`small`,class:`ml-2`,onClick:s[1]||(s[1]=e=>n(R).push(`/model/plan`))},{default:u(()=>[...s[15]||(s[15]=[t(`去角色编排`,-1)])]),_:1})])):p(``,!0)]),_:1}),e(n(x),{title:`当前生效的配置`,class:`mb-4`,loading:z.value},{default:u(()=>[e(n(C),{column:3,size:`small`,bordered:``},{default:u(()=>[e(n(S),{label:`版本`},{default:u(()=>[t(`v`+d(V.value),1)]),_:1}),e(n(S),{label:`最后修改`},{default:u(()=>[t(d(U.value||`—`),1)]),_:1}),e(n(S),{label:`时间`},{default:u(()=>[t(d(H.value||`—`),1)]),_:1})]),_:1})]),_:1},8,[`loading`]),e(n(ae),{model:Y,layout:`vertical`},{default:u(()=>[e(n(x),{title:`桌面账号登录`,class:`mb-4`,loading:z.value},{default:u(()=>[s[19]||(s[19]=r(`p`,{class:`mb-3 text-xs text-gray-500`},` 软件打开登录窗口后,会先请求本管理端的公开客户端配置,再按这里返回的地址请求 ZYT 登录。 换登录域名只需修改这一处,无需重新修改或打包桌面软件。 `,-1)),e(n(g),{label:`ZYT 登录 API 域名(留空 = 使用管理 API 启动配置)`},{default:u(()=>[e(n(w),{value:Y.ZYT_LOGIN_API_URL,"onUpdate:value":s[2]||(s[2]=e=>Y.ZYT_LOGIN_API_URL=e),disabled:!L.value,placeholder:`https://api.example.com`},null,8,[`value`,`disabled`]),r(`p`,fe,[s[17]||(s[17]=t(` 当前客户端实际获取:`,-1)),r(`code`,null,d(K.value||`—`),1)]),s[18]||(s[18]=r(`p`,{class:`mt-1 text-xs text-gray-500`},[t(` 填写完整的 `),r(`code`,null,`http://`),t(` 或 `),r(`code`,null,`https://`),t(` 基础地址,不要填写 `),r(`code`,null,`/api/login/account`),t(`;客户端会自动拼接登录接口路径。 `)],-1))]),_:1})]),_:1},8,[`loading`]),e(n(x),{title:`能力开关`,class:`mb-4`,loading:z.value},{default:u(()=>[r(`div`,pe,[(c(),i(l,null,a(ye,t=>r(`div`,{key:t.key,class:`flex items-start justify-between gap-4 border-b border-dashed py-3 last:border-0`},[r(`div`,me,[r(`div`,he,d(t.label),1),r(`div`,ge,d(t.hint),1)]),e(n(E),{checked:Y[t.key],"onUpdate:checked":e=>Y[t.key]=e,disabled:!L.value,class:`mt-1 shrink-0`},null,8,[`checked`,`onUpdate:checked`,`disabled`])])),64))])]),_:1},8,[`loading`]),e(n(x),{title:`企业微信数据库自动备份`,class:`mb-4`,loading:z.value},{default:u(()=>[s[21]||(s[21]=r(`p`,{class:`mb-3 text-xs text-gray-500`},` 软件启动后等待设定时间执行第一次增量备份,之后按相同间隔持续运行。只上传服务端检查点之后的新消息和新媒体,修改配置后客户端会自动同步,无需重启。 `,-1)),r(`div`,_e,[e(n(g),{label:`自动增量备份`},{default:u(()=>[e(n(E),{checked:Y.ARCHIVE_AUTO_BACKUP_ENABLED,"onUpdate:checked":s[3]||(s[3]=e=>Y.ARCHIVE_AUTO_BACKUP_ENABLED=e),disabled:!L.value},null,8,[`checked`,`disabled`])]),_:1}),e(n(g),{label:`启动等待及备份间隔(分钟)`},{default:u(()=>[e(n(T),{value:Y.ARCHIVE_AUTO_BACKUP_INTERVAL_MINUTES,"onUpdate:value":s[4]||(s[4]=e=>Y.ARCHIVE_AUTO_BACKUP_INTERVAL_MINUTES=e),min:1,max:10080,disabled:!L.value||!Y.ARCHIVE_AUTO_BACKUP_ENABLED,class:`w-full`},null,8,[`value`,`disabled`]),s[20]||(s[20]=r(`p`,{class:`mt-1 text-xs text-gray-500`},`范围 1 分钟至 7 天。`,-1))]),_:1})])]),_:1},8,[`loading`]),e(n(x),{title:`客服人格`,class:`mb-4`,loading:z.value},{default:u(()=>[s[23]||(s[23]=r(`p`,{class:`mb-3 text-xs text-gray-500`},` 这几项会拼进系统提示词,决定客户看到的是"谁"在说话。它们不是模型参数,所以留在这里。 `,-1)),r(`div`,D,[e(n(g),{label:`客服名称`},{default:u(()=>[e(n(w),{value:Y.AI_AGENT_NAME,"onUpdate:value":s[5]||(s[5]=e=>Y.AI_AGENT_NAME=e),disabled:!L.value,placeholder:`贴心管家`},null,8,[`value`,`disabled`])]),_:1}),e(n(g),{label:`机构名称`},{default:u(()=>[e(n(w),{value:Y.AI_HOSPITAL_NAME,"onUpdate:value":s[6]||(s[6]=e=>Y.AI_HOSPITAL_NAME=e),disabled:!L.value,placeholder:`甄养堂`},null,8,[`value`,`disabled`])]),_:1}),e(n(g),{label:`上下文轮数(1–50)`},{default:u(()=>[e(n(T),{value:Y.AI_CONTEXT_MAX_ROUNDS,"onUpdate:value":s[7]||(s[7]=e=>Y.AI_CONTEXT_MAX_ROUNDS=e),min:1,max:50,disabled:!L.value,class:`w-full`},null,8,[`value`,`disabled`]),s[22]||(s[22]=r(`p`,{class:`mt-1 text-xs text-gray-500`},` 记几轮对话。这是客户端行为,和"用哪个模型"无关。 `,-1))]),_:1})])]),_:1},8,[`loading`]),e(n(x),{title:`模型网关地址`,class:`mb-4`,loading:z.value},{default:u(()=>[s[26]||(s[26]=r(`p`,{class:`mb-3 text-xs text-gray-500`},` 桌面客户端只配一个后台地址,模型请求发到哪儿由这里决定、随配置一起下发。 换网关位置只需要改这一处,不用挨个动客户端。 `,-1)),e(n(g),{label:`地址(留空 = 按后台自己的地址自动推算)`},{default:u(()=>[e(n(w),{value:Y.AI_GATEWAY_URL,"onUpdate:value":s[8]||(s[8]=e=>Y.AI_GATEWAY_URL=e),disabled:!L.value,placeholder:`留空即可,绝大多数情况不用填`},null,8,[`value`,`disabled`]),r(`p`,O,[s[24]||(s[24]=t(` 当前实际下发:`,-1)),r(`code`,null,d(G.value||`—`),1)]),s[25]||(s[25]=r(`p`,{class:`mt-1 text-xs text-gray-500`},[t(` 只有网关在别的域名或别的机器上时才需要填。写完整地址(`),r(`code`,null,`https://…`),t(`) 或以 `),r(`code`,null,`/`),t(` 开头的路径(挂在本后台的域名下)。 `)],-1))]),_:1})]),_:1},8,[`loading`]),e(n(x),{title:`选择性审核规则`,class:`mb-4`,loading:z.value},{default:u(()=>[s[29]||(s[29]=r(`p`,{class:`mb-3 text-xs text-gray-500`},` 命中任意一条,那一条回复才会停下来贴进企业微信输入框等人工确认,不会自动按回车; 没命中的照常自动发送。关键词不区分大小写,客户这句话和模型准备发的回复, 沾上任意一边都算命中。 `,-1)),e(n(y),{class:`mb-3`,type:`info`,"show-icon":``,message:`还有一条内置规则不在这份清单里、关不掉`,description:`模型裁判把某条回复判成「高风险」时,无论有没有命中下面的关键词,同样会转人工。裁判只要在角色编排里配了就会一直打分,这个信号比关键词更贴近内容本身。`}),(c(!0),i(l,null,a(Y.AI_REVIEW_RULES,(a,o)=>(c(),i(`div`,{key:o,class:`mb-3 flex items-start gap-3 border-b border-dashed pb-3 last:border-0`},[r(`div`,k,[e(n(w),{value:a.label,"onUpdate:value":e=>a.label=e,disabled:!L.value,placeholder:`规则名称,例如「诊断」`},null,8,[`value`,`onUpdate:value`,`disabled`])]),r(`div`,A,[e(n(_),{value:a.keywords,"onUpdate:value":e=>a.keywords=e,mode:`tags`,disabled:!L.value,placeholder:`输入关键词后按回车,可以加多个`,style:{width:`100%`}},null,8,[`value`,`onUpdate:value`,`disabled`])]),e(n(E),{checked:a.enabled,"onUpdate:checked":e=>a.enabled=e,disabled:!L.value,class:`mt-1 shrink-0`},null,8,[`checked`,`onUpdate:checked`,`disabled`]),e(n(b),{danger:``,type:`link`,size:`small`,disabled:!L.value,class:`shrink-0`,onClick:e=>xe(o)},{default:u(()=>[...s[27]||(s[27]=[t(` 删除 `,-1)])]),_:1},8,[`disabled`,`onClick`])]))),128)),L.value?(c(),ne(n(b),{key:0,size:`small`,onClick:be},{default:u(()=>[...s[28]||(s[28]=[t(`+ 新增规则`,-1)])]),_:1})):p(``,!0),Y.AI_REVIEW_RULES.length===0?(c(),i(`p`,j,` 还没有配任何规则——除了上面那条内置的裁判高风险检查,其余全部自动发送。 `)):p(``,!0)]),_:1},8,[`loading`]),e(n(x),{title:`MCP 服务器`,class:`mb-4`,loading:z.value},{default:u(()=>[r(`div`,M,[e(n(g),{label:`单次最多调用工具轮数(1–20)`},{default:u(()=>[e(n(T),{value:Y.AI_MCP_MAX_ROUNDS,"onUpdate:value":s[9]||(s[9]=e=>Y.AI_MCP_MAX_ROUNDS=e),min:1,max:20,disabled:!L.value,class:`w-full`},null,8,[`value`,`disabled`])]),_:1})]),e(n(g),{label:`服务器清单(JSON 数组)`},{default:u(()=>[e(n(ce),{value:q.value,"onUpdate:value":s[10]||(s[10]=e=>q.value=e),rows:8,disabled:!L.value,status:J.value?`error`:void 0,spellcheck:`false`,class:`font-mono text-xs`,onBlur:Q},null,8,[`value`,`disabled`,`status`]),J.value?(c(),i(`p`,N,d(J.value),1)):(c(),i(`p`,P,` 工具跑在客户端本机(要连内网),所以配置在这里而不是模型清单里。 格式错误会当场拦下,不会等到桌面端同步之后才发现。 `))]),_:1})]),_:1},8,[`loading`]),L.value?(c(),i(`div`,F,[e(n(b),{type:`primary`,loading:B.value,onClick:Ce},{default:u(()=>[...s[30]||(s[30]=[t(`保存并发布新版本`,-1)])]),_:1},8,[`loading`]),e(n(b),{class:`ml-2`,disabled:B.value,onClick:X},{default:u(()=>[...s[31]||(s[31]=[t(`放弃修改`,-1)])]),_:1},8,[`disabled`])])):p(``,!0)]),_:1},8,[`model`])]))}});export{I as default};