import { defineComponent, ref, reactive, computed, unref, useSSRContext } from 'vue'; import { ssrRenderAttrs, ssrIncludeBooleanAttr, ssrLooseContain, ssrLooseEqual, ssrRenderList, ssrRenderAttr, ssrInterpolate, ssrRenderClass } from 'vue/server-renderer'; import { u as useApi } from './useApi-B-E5eLsI.mjs'; import { u as useToast } from './useToast-CS21XT61.mjs'; import { L as LANG_OPTIONS } from './useLangOptions-DMhiAuTa.mjs'; import { _ as _export_sfc } from './server.mjs'; import './useLoading-D4zrSa2m.mjs'; import '../nitro/nitro.mjs'; import 'node:http'; import 'node:https'; import 'node:events'; import 'node:buffer'; import 'node:fs'; import 'node:path'; import 'node:crypto'; import 'node:url'; import '../routes/renderer.mjs'; import 'vue-bundle-renderer/runtime'; import 'unhead/server'; import 'devalue'; import 'unhead/utils'; import 'pinia'; import 'perfect-debounce'; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "meetingsvc", __ssrInlineRender: true, setup(__props) { useApi(); useToast(); const REGIONS = [ { 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 regionLabel(v) { return REGIONS.find((r) => r.value === v)?.label ?? "区域" + v; } const apps = ref([]); const scopeApp = ref(""); const scopeRegion = ref(0); const items = ref([]); const available = ref([]); const kindCats = ref({ "1": [8], "2": [3], "3": [5, 9] }); const llmClientChoice = ref(false); const isOverride = ref(false); const loading = ref(false); const saving = ref(false); const busy = ref(false); const probeLang = ref("zh-CN"); ref(null); ref(null); const addKind = ref(1); const addForm = reactive({ svc_id: "", cost_hint: 0, is_default: false, client_visible: false }); const costEdit = reactive({ row_id: 0, name: "", kind: 1, cost_hint: 0 }); function kindLabel(k) { return k === 1 ? "识别" : k === 2 ? "翻译" : "总结"; } function costUnit(k) { return k === 1 ? "元/小时" : k === 2 ? "元/百万字符" : "元/百万token"; } function langName(code) { return LANG_OPTIONS.find((o) => o.code === code)?.name ?? code; } function catsHas(cats, v) { return (cats || "").split(",").map((x) => Number(x.trim())).includes(v); } const svcMap = computed(() => { const m = /* @__PURE__ */ new Map(); for (const s of available.value) m.set(s.id, s); return m; }); function svcName(id) { return svcMap.value.get(id)?.name ?? id; } function svcProvider(id) { return svcMap.value.get(id)?.provider ?? "?"; } function svcLangs(id) { return svcMap.value.get(id)?.languages ?? ""; } function isVision(id) { return catsHas(svcMap.value.get(id)?.categories ?? "", 9); } function ofKind(k) { return items.value.filter((o) => o.kind === k).sort((a, b) => a.priority - b.priority); } function addable(k) { const cats = kindCats.value[String(k)] ?? []; const used = new Set(items.value.filter((o) => o.kind === k).map((o) => o.svc_id)); return available.value.filter((s) => !used.has(s.id) && s.categories.split(",").some((c) => cats.includes(Number(c.trim())))); } function svcSupportsLang(id, lang) { const ls = svcLangs(id); if (!ls) return true; return ls.split(",").map((x) => x.trim()).includes(lang); } const asrHit = computed(() => ofKind(1).find((o) => o.enabled && svcSupportsLang(o.svc_id, probeLang.value)) ?? null); const mtHit = computed(() => ofKind(2).find((o) => o.enabled) ?? null); function asrSkipped(o) { return asrHit.value?.row_id !== o.row_id && (!o.enabled || !svcSupportsLang(o.svc_id, probeLang.value)); } function asrWhyClass(o) { if (asrHit.value?.row_id === o.row_id) return "ok"; if (!o.enabled || !svcSupportsLang(o.svc_id, probeLang.value)) return "no"; return ""; } function asrWhy(o) { if (asrHit.value?.row_id === o.row_id) { return svcLangs(o.svc_id) ? `✓ 当前源语言(${langName(probeLang.value)})由它承接` : `✓ 未限定语言,先落到它(实际支持由引擎判断)`; } if (!o.enabled) return "已停用,跳过"; if (!svcSupportsLang(o.svc_id, probeLang.value)) return `不支持 ${langName(probeLang.value)}(${probeLang.value}),跳过 → 顺延下一个`; return "备用:前面都跳过时接手"; } const langSum = computed(() => { const missing = []; const groups = []; let unlimitedKinds = 0; for (const k of [1, 2, 3]) { const list = ofKind(k).filter((o) => o.enabled); if (!list.length) { missing.push(k); continue; } const union = /* @__PURE__ */ new Set(); let unlimited = false; for (const o of list) { const ls = svcLangs(o.svc_id).split(",").map((x) => x.trim()).filter(Boolean); if (!ls.length) { unlimited = true; break; } ls.forEach((l) => union.add(l)); } if (unlimited) unlimitedKinds++; else groups.push({ kind: k, langs: [...union] }); } if (!groups.length) return { missing, unlimited: true, langs: [], groups, unlimitedKinds }; const langs = groups.reduce((acc, g) => acc.filter((l) => g.langs.includes(l)), [...groups[0].langs]).sort((a, b) => langOrder(a) - langOrder(b)); return { missing, unlimited: false, langs, groups, unlimitedKinds }; }); function langOrder(code) { const i = LANG_OPTIONS.findIndex((o) => o.code === code); return i < 0 ? Number.MAX_SAFE_INTEGER : i; } const langSumFormula = computed(() => { const parts = []; for (const k of [1, 2, 3]) { if (langSum.value.missing.includes(k)) { parts.push(`${kindLabel(k)} 未配置`); continue; } const g = langSum.value.groups.find((x) => x.kind === k); parts.push(`${kindLabel(k)} ${g ? g.langs.length + " 种" : "全语种"}`); } return parts.join(" ∩ "); }); const llmDefault = computed(() => ofKind(3).find((o) => o.is_default) ?? null); const pickable = computed(() => ofKind(3).filter((o) => o.enabled && o.client_visible)); return (_ctx, _push, _parent, _attrs) => { _push(`
识别 / 翻译 / 总结三段,从第三方服务配置里选已配好的服务来编排(不再单独填凭据)。 先配「全局默认」作兜底,再按应用 / 区域覆盖——没配覆盖的应用自动继承全局默认。