<script setup lang="ts">
import { ElMessage, ElMessageBox } from "element-plus";
import { computed, defineAsyncComponent, onMounted, reactive, ref } from "vue";

import AdminLoginView from "./components/AdminLoginView.vue";
import TableRowActions from "./components/TableRowActions.vue";
import {
  systemSettingDefinitions,
  type SystemSettingValue,
} from "./config/systemSettings";
import { api, clearToken, getToken, saveToken } from "./services/api";
import type {
  AdminProfile,
  EntitlementPlan,
  ModelItem,
  SystemConfigItem,
} from "./types/api";

const AgentManagementView = defineAsyncComponent(
  () => import("./components/AgentManagementView.vue"),
);
const AttentionManagementView = defineAsyncComponent(
  () => import("./components/AttentionManagementView.vue"),
);
const ContentGenerationConfigView = defineAsyncComponent(
  () => import("./components/ContentGenerationConfigView.vue"),
);
const DashboardView = defineAsyncComponent(
  () => import("./components/DashboardView.vue"),
);
const EntitlementManagementView = defineAsyncComponent(
  () => import("./components/EntitlementManagementView.vue"),
);
const KnowledgeManagementView = defineAsyncComponent(
  () => import("./components/KnowledgeManagementView.vue"),
);
const RecordAuditView = defineAsyncComponent(
  () => import("./components/RecordAuditView.vue"),
);
const RetrievalLogView = defineAsyncComponent(
  () => import("./components/RetrievalLogView.vue"),
);
const UserManagementView = defineAsyncComponent(
  () => import("./components/UserManagementView.vue"),
);
const SsoIntegrationView = defineAsyncComponent(
  () => import("./components/SsoIntegrationView.vue"),
);
const SystemConfigView = defineAsyncComponent(
  () => import("./components/SystemConfigView.vue"),
);
const AdminManagementView = defineAsyncComponent(
  () => import("./components/AdminManagementView.vue"),
);
const FeedbackManagementView = defineAsyncComponent(() => import("./components/FeedbackManagementView.vue"));

const admin = ref<AdminProfile | null>(null);
const activeMenu = ref("dashboard");
const loading = ref(false);
const passwordDialogVisible = ref(false);
const passwordSaving = ref(false);
const passwordForm = reactive({ currentPassword: "", newPassword: "", confirmPassword: "" });

const can = (permission: string) => Boolean(admin.value?.isSuperAdmin || admin.value?.permissions.includes(permission));
const menuPermissions: Record<string, string> = {
  dashboard: "dashboard.view", users: "users.view", entitlements: "entitlements.view",
  knowledge: "knowledge.view", prompt: "prompt.view", models: "models.view",
  "content-generation": "content-generation.view", configs: "configs.view", sso: "sso.view",
  records: "records.view", retrievals: "retrievals.view", attention: "attention.view", admins: "admins.view",
  feedback: "feedback.view",
};

const entitlementPlans = ref<EntitlementPlan[]>([]);
const models = ref<ModelItem[]>([]);
const configs = ref<SystemConfigItem[]>([]);
const savingSystemSettings = ref(false);
const systemSettingsBaseline = ref<Record<string, string>>({});
const previewKnowledgeId = ref<number | null>(null);
const editingModelId = ref<number | null>(null);

const modelForm = reactive({
  provider: "openai-compatible",
  displayName: "",
  apiType: "openai_compatible",
  modelName: "",
  baseUrl: "https://api.openai.com/v1",
  apiUrl: "",
  apiKey: "",
  authType: "bearer",
  apiVersion: "",
  temperature: null as number | null,
  topP: null as number | null,
  topK: null as number | null,
  presencePenalty: null as number | null,
  frequencyPenalty: null as number | null,
  maxToken: 8192 as number | null,
  contextWindow: null as number | null,
  streamEnabled: 1,
  responseFormat: "",
  extraParams: "",
  remark: "",
  timeoutSecond: 30,
  inputPricePer1k: null as number | null,
  outputPricePer1k: null as number | null,
  currency: "CNY",
  usageScenarios: "",
  allowSummary: 1,
  allowReport: 1,
  allowFixedInfo: 1,
  allowSimpleKnowledge: 1,
  allowDeepChat: 1,
});

const quickModelForm = reactive({
  provider: "deepseek",
  modelName: "deepseek-v4-pro",
  apiKey: "",
});

const quickModelProviders = [
  {
    label: "DeepSeek",
    provider: "deepseek",
    apiType: "openai_compatible",
    baseUrl: "https://api.deepseek.com",
    authType: "bearer",
    apiVersion: "",
    temperature: null,
    topP: null,
    maxToken: null,
    contextWindow: null,
    models: [
      { label: "deepseek-v4-pro", value: "deepseek-v4-pro" },
      { label: "deepseek-v4-flash", value: "deepseek-v4-flash" },
    ],
  },
  {
    label: "MiniMax",
    provider: "minimax",
    apiType: "openai_compatible",
    baseUrl: "https://api.minimaxi.com/v1",
    authType: "bearer",
    apiVersion: "",
    temperature: null,
    topP: null,
    maxToken: null,
    contextWindow: null,
    models: [
      { label: "MiniMax-Text-01", value: "MiniMax-Text-01" },
      { label: "MiniMax-M3", value: "MiniMax-M3" },
    ],
  },
] as const;

const protocolPresets = [
  {
    label: "OpenAI 兼容协议",
    provider: "openai-compatible",
    apiType: "openai_compatible",
    baseUrl: "https://api.openai.com/v1",
    apiUrl: "",
    authType: "bearer",
  },
  {
    label: "Anthropic Messages 协议",
    provider: "anthropic-compatible",
    apiType: "anthropic_messages",
    baseUrl: "https://api.anthropic.com",
    apiUrl: "",
    authType: "api_key",
    apiVersion: "2023-06-01",
    temperature: null,
    topP: null,
    topK: null,
  },
];

const nullableModelFields = [
  "temperature",
  "topP",
  "topK",
  "presencePenalty",
  "frequencyPenalty",
  "contextWindow",
  "responseFormat",
  "extraParams",
  "remark",
  "inputPricePer1k",
  "outputPricePer1k",
  "usageScenarios",
] as const;

const systemSettingValues = reactive<Record<string, SystemSettingValue>>({});
systemSettingDefinitions.forEach((setting) => {
  systemSettingValues[setting.key] = setting.defaultValue;
});
const systemSettingsDirty = computed(() =>
  systemSettingDefinitions.some(
    (setting) =>
      serializeSystemSettingValue(systemSettingValues[setting.key]) !==
      systemSettingsBaseline.value[setting.key],
  ),
);

onMounted(async () => {
  if (!getToken()) return;
  try {
    admin.value = await api.profile();
    passwordDialogVisible.value = admin.value.mustChangePassword;
    if (!admin.value.mustChangePassword) await enterFirstAvailableMenu();
  } catch {
    clearToken();
  }
});

async function login(credentials: { username: string; password: string }) {
  loading.value = true;
  try {
    const result = await api.login(credentials.username, credentials.password);
    saveToken(result.token);
    admin.value = result.admin;
    passwordDialogVisible.value = result.admin.mustChangePassword;
    if (!result.admin.mustChangePassword) await enterFirstAvailableMenu();
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "登录失败");
  } finally {
    loading.value = false;
  }
}

async function logout() {
  try {
    await api.logout();
  } finally {
    clearToken();
    admin.value = null;
  }
}

async function switchMenu(menu: string) {
  if (!can(menuPermissions[menu])) return;
  activeMenu.value = menu;
  await loadCurrentMenu();
}

async function enterFirstAvailableMenu() {
  const first = Object.keys(menuPermissions).find((menu) => can(menuPermissions[menu]));
  activeMenu.value = first ?? "dashboard";
  if (first) await loadCurrentMenu();
}

async function changeInitialPassword() {
  if (passwordForm.newPassword.length < 8) return ElMessage.warning("新密码至少 8 位");
  if (passwordForm.newPassword !== passwordForm.confirmPassword) return ElMessage.warning("两次输入的新密码不一致");
  passwordSaving.value = true;
  try {
    await api.changeAdminPassword({ currentPassword: passwordForm.currentPassword, newPassword: passwordForm.newPassword });
    if (admin.value) admin.value.mustChangePassword = false;
    passwordDialogVisible.value = false;
    Object.assign(passwordForm, { currentPassword: "", newPassword: "", confirmPassword: "" });
    ElMessage.success("密码已修改，请使用新密码登录");
    await logout();
  } catch (error) { ElMessage.error(error instanceof Error ? error.message : "密码修改失败"); }
  finally { passwordSaving.value = false; }
}

async function previewKnowledge(knowledgeId: number) {
  previewKnowledgeId.value = knowledgeId;
  await switchMenu("prompt");
}

function formatMoney(value?: number | null, currency = "CNY") {
  if (typeof value !== "number") return "-";
  if (currency === "MIXED") return "多币种，见明细";
  return `${currency || "CNY"} ${value.toFixed(6)}`;
}

async function loadCurrentMenu() {
  loading.value = true;
  try {
    if (activeMenu.value === "entitlements") await loadEntitlementPlans();
    if (activeMenu.value === "models") models.value = await api.models();
    if (activeMenu.value === "configs") {
      configs.value = await api.configs();
      hydrateSystemSettings();
    }
  } finally {
    loading.value = false;
  }
}

async function loadEntitlementPlans() {
  entitlementPlans.value = await api.entitlementPlans(true);
}

async function saveModel() {
  if (!validateModelForm()) return;
  const payload = buildModelPayload();
  if (editingModelId.value) {
    await api.updateModel(editingModelId.value, payload);
    ElMessage.success("模型已更新");
  } else {
    await api.createModel(payload);
    ElMessage.success("模型已新增");
  }
  resetModelForm();
  await loadCurrentMenu();
}

function buildModelPayload() {
  const payload = { ...modelForm } as Record<string, unknown>;
  nullableModelFields.forEach((field) => {
    if (payload[field] === undefined || payload[field] === "") {
      payload[field] = null;
    }
  });
  return payload;
}

const selectedQuickProvider = computed(() => {
  return (
    quickModelProviders.find(
      (item) => item.provider === quickModelForm.provider,
    ) ?? quickModelProviders[0]
  );
});

async function quickAddModel() {
  const provider = selectedQuickProvider.value;
  if (!provider) return;
  if (!quickModelForm.apiKey) {
    ElMessage.error("请填写 API Key");
    return;
  }

  await api.createModel({
    provider: provider.provider,
    displayName: `${provider.label} ${quickModelForm.modelName}`,
    apiType: provider.apiType,
    modelName: quickModelForm.modelName,
    baseUrl: provider.baseUrl,
    apiUrl: "",
    apiKey: quickModelForm.apiKey,
    authType: provider.authType,
    apiVersion: provider.apiVersion,
    temperature: null,
    topP: null,
    topK: null,
    presencePenalty: null,
    frequencyPenalty: null,
    maxToken: 8192,
    contextWindow: null,
    streamEnabled: 1,
    responseFormat: null,
    extraParams: null,
    remark: "快速添加",
    timeoutSecond: 30,
    inputPricePer1k: null,
    outputPricePer1k: null,
    currency: "CNY",
    usageScenarios: "正式对话",
    allowSummary: 1,
    allowReport: 1,
    allowFixedInfo: 1,
    allowSimpleKnowledge: 1,
    allowDeepChat: 1,
  });
  ElMessage.success(`${provider.label} 模型已新增`);
  quickModelForm.apiKey = "";
  await loadCurrentMenu();
}

function applyQuickProvider(provider: string) {
  const target = quickModelProviders.find((item) => item.provider === provider);
  if (!target) return;
  quickModelForm.modelName = target.models[0]?.value ?? "";
}

async function setModelAvailability(row: ModelItem, enabled: number) {
  await api.setModelAvailability(row.id, enabled);
  ElMessage.success(enabled === 1 ? "模型已加入可用池" : "模型已停用");
  await loadCurrentMenu();
}

async function setDefaultModel(row: ModelItem) {
  await api.setDefaultModel(row.id);
  ElMessage.success("默认主模型已更新");
  await loadCurrentMenu();
}

async function handleModelCommand(command: string, row: ModelItem) {
  if (command === "enable") return setModelAvailability(row, 1);
  if (command === "disable") return setModelAvailability(row, 0);
  if (command === "default") return setDefaultModel(row);
  return deleteModel(row.id);
}

async function deleteModel(id: number) {
  try {
    await ElMessageBox.confirm("确认删除该模型？删除后不可恢复。", "删除模型", {
      confirmButtonText: "确认删除",
      cancelButtonText: "取消",
      type: "warning",
    });
  } catch {
    return;
  }
  await api.deleteModel(id);
  ElMessage.success("模型已删除");
  await loadCurrentMenu();
}

async function testModel(id: number) {
  const result = await api.testModel(id);
  if (result.ok) {
    ElMessage.success(result.message);
  } else {
    ElMessage.error(result.message);
  }
}

function applyModelPreset(label: string) {
  const preset = protocolPresets.find((item) => item.label === label);
  if (!preset) return;
  Object.assign(
    modelForm,
    {
      apiVersion: "",
      authType: "bearer",
      temperature: null,
      topP: null,
      topK: null,
      presencePenalty: null,
      frequencyPenalty: null,
      responseFormat: "",
      streamEnabled: 1,
    },
    preset,
  );
}

function editModel(row: ModelItem) {
  editingModelId.value = row.id;
  Object.assign(modelForm, {
    provider: row.provider,
    displayName: row.displayName ?? "",
    apiType: row.apiType,
    modelName: row.modelName,
    baseUrl: row.baseUrl ?? "",
    apiUrl: row.apiUrl,
    apiKey: "",
    authType: row.authType,
    apiVersion: row.apiVersion ?? "",
    temperature: row.temperature ?? null,
    topP: row.topP ?? null,
    topK: row.topK ?? null,
    presencePenalty: row.presencePenalty ?? null,
    frequencyPenalty: row.frequencyPenalty ?? null,
    maxToken: row.maxToken ?? 8192,
    contextWindow: row.contextWindow ?? null,
    streamEnabled: row.streamEnabled,
    responseFormat: row.responseFormat ?? "",
    extraParams: row.extraParams ?? "",
    remark: row.remark ?? "",
    timeoutSecond: row.timeoutSecond,
    inputPricePer1k: row.inputPricePer1k ?? null,
    outputPricePer1k: row.outputPricePer1k ?? null,
    currency: row.currency || "CNY",
    usageScenarios: row.usageScenarios ?? "",
    allowSummary: row.allowSummary ?? 1,
    allowReport: row.allowReport ?? 1,
    allowFixedInfo: row.allowFixedInfo ?? 1,
    allowSimpleKnowledge: row.allowSimpleKnowledge ?? 1,
    allowDeepChat: row.allowDeepChat ?? 1,
  });
}

function resetModelForm() {
  editingModelId.value = null;
  Object.assign(modelForm, {
    provider: "openai-compatible",
    displayName: "",
    apiType: "openai_compatible",
    modelName: "",
    baseUrl: "https://api.openai.com/v1",
    apiUrl: "",
    apiKey: "",
    authType: "bearer",
    apiVersion: "",
    temperature: null,
    topP: null,
    topK: null,
    presencePenalty: null,
    frequencyPenalty: null,
    maxToken: 8192,
    contextWindow: null,
    streamEnabled: 1,
    responseFormat: "",
    extraParams: "",
    remark: "",
    timeoutSecond: 30,
    inputPricePer1k: null,
    outputPricePer1k: null,
    currency: "CNY",
    usageScenarios: "",
    allowSummary: 1,
    allowReport: 1,
    allowFixedInfo: 1,
    allowSimpleKnowledge: 1,
    allowDeepChat: 1,
  });
}

function validateModelForm() {
  if (!modelForm.apiUrl && !modelForm.baseUrl) {
    ElMessage.error("请填写 Base URL 或 API URL");
    return false;
  }
  if (!editingModelId.value && !modelForm.apiKey) {
    ElMessage.error("新增模型必须填写 API Key");
    return false;
  }
  if (modelForm.extraParams.trim()) {
    try {
      const extraParams = JSON.parse(modelForm.extraParams);
      if (
        !extraParams ||
        Array.isArray(extraParams) ||
        typeof extraParams !== "object"
      ) {
        throw new Error("高级 JSON 参数必须是对象");
      }
    } catch (error) {
      ElMessage.error(
        error instanceof Error ? error.message : "高级 JSON 参数不是合法 JSON",
      );
      return false;
    }
  }
  return true;
}

async function saveSystemSettings() {
  if (savingSystemSettings.value || !systemSettingsDirty.value) return;
  savingSystemSettings.value = true;
  try {
    await Promise.all(
      systemSettingDefinitions.map((setting) =>
        api.saveConfig({
          configKey: setting.key,
          configValue: serializeSystemSettingValue(
            systemSettingValues[setting.key],
          ),
          description: setting.description,
        }),
      ),
    );
    configs.value = await api.configs();
    hydrateSystemSettings();
    ElMessage.success("系统配置已保存");
  } catch (error) {
    ElMessage.error(
      error instanceof Error ? error.message : "系统配置保存失败，请重试",
    );
  } finally {
    savingSystemSettings.value = false;
  }
}

function hydrateSystemSettings() {
  const configMap = new Map(
    configs.value.map((item) => [item.configKey, item.configValue]),
  );
  systemSettingDefinitions.forEach((setting) => {
    systemSettingValues[setting.key] = normalizeSystemSettingValue(
      setting,
      configMap.get(setting.key),
    );
  });
  systemSettingsBaseline.value = Object.fromEntries(
    systemSettingDefinitions.map((setting) => [
      setting.key,
      serializeSystemSettingValue(systemSettingValues[setting.key]),
    ]),
  );
}

function updateSystemSetting(key: string, value: SystemSettingValue) {
  if (systemSettingValues[key] === value) return;
  systemSettingValues[key] = value;
}

function normalizeSystemSettingValue(
  setting: (typeof systemSettingDefinitions)[number],
  rawValue?: string,
) {
  if (rawValue === undefined || rawValue === "") {
    return setting.defaultValue;
  }
  if (setting.type === "switch") {
    return ["1", "true", "yes", "on", "启用"].includes(rawValue.toLowerCase());
  }
  if (
    setting.type === "text" ||
    setting.type === "password" ||
    setting.type === "select"
  ) {
    return rawValue;
  }
  const parsed = Number(rawValue);
  if (Number.isFinite(parsed)) {
    return parsed;
  }
  return setting.defaultValue;
}

function serializeSystemSettingValue(value: SystemSettingValue) {
  if (typeof value === "boolean") return value ? "true" : "false";
  return String(value);
}

async function clearFeishuCache() {
  try {
    const result = await api.clearFeishuCache();
    ElMessage.success(result.message || `已清空 ${result.cleared} 条缓存`);
  } catch (e: any) {
    ElMessage.error(e.message || "刷新缓存失败");
  }
}
</script>

<template>
  <AdminLoginView v-if="!admin" :loading="loading" @submit="login" />

  <main v-else class="admin-shell">
    <aside class="sidebar">
      <div class="sidebar-title">大本营千问千答</div>
      <button
        v-if="can('dashboard.view')"
        :class="{ active: activeMenu === 'dashboard' }"
        @click="switchMenu('dashboard')"
      >
        数据看板
      </button>
      <button
        v-if="can('users.view')"
        :class="{ active: activeMenu === 'users' }"
        @click="switchMenu('users')"
      >
        用户管理
      </button>
      <button
        v-if="can('entitlements.view')"
        :class="{ active: activeMenu === 'entitlements' }"
        @click="switchMenu('entitlements')"
      >
        权益管理
      </button>
      <button
        v-if="can('knowledge.view')"
        :class="{ active: activeMenu === 'knowledge' }"
        @click="switchMenu('knowledge')"
      >
        知识库管理
      </button>
      <button
        v-if="can('prompt.view')"
        :class="{ active: activeMenu === 'prompt' }"
        @click="switchMenu('prompt')"
      >
        Agent 管理
      </button>
      <button
        v-if="can('models.view')"
        :class="{ active: activeMenu === 'models' }"
        @click="switchMenu('models')"
      >
        模型管理
      </button>
      <button
        v-if="can('content-generation.view')"
        :class="{ active: activeMenu === 'content-generation' }"
        @click="switchMenu('content-generation')"
      >
        内容生成
      </button>
      <button
        v-if="can('configs.view')"
        :class="{ active: activeMenu === 'configs' }"
        @click="switchMenu('configs')"
      >
        系统配置
      </button>
      <button
        v-if="can('sso.view')"
        :class="{ active: activeMenu === 'sso' }"
        @click="switchMenu('sso')"
      >
        应用接入
      </button>
      <button
        v-if="can('records.view')"
        :class="{ active: activeMenu === 'records' }"
        @click="switchMenu('records')"
      >
        记录审计
      </button>
      <button
        v-if="can('retrievals.view')"
        :class="{ active: activeMenu === 'retrievals' }"
        @click="switchMenu('retrievals')"
      >
        检索日志
      </button>
      <button
        v-if="can('feedback.view')"
        :class="{ active: activeMenu === 'feedback' }"
        @click="switchMenu('feedback')"
      >反馈管理</button>
      <button
        v-if="can('attention.view')"
        :class="{ active: activeMenu === 'attention' }"
        @click="switchMenu('attention')"
      >
        人工关注
      </button>
      <button
        v-if="admin.isSuperAdmin"
        :class="{ active: activeMenu === 'admins' }"
        @click="switchMenu('admins')"
      >管理员与权限</button>
    </aside>

    <section class="workspace">
      <header class="topbar">
        <div>
          <strong>{{ admin.name }}</strong>
          <span>管理员</span>
        </div>
        <el-button @click="logout">退出</el-button>
      </header>

      <section v-loading="loading" class="content">
        <DashboardView v-if="activeMenu === 'dashboard'" />

        <UserManagementView v-if="activeMenu === 'users'" />

        <template v-if="activeMenu === 'entitlements'">
          <EntitlementManagementView
            :plans="entitlementPlans"
            @refreshed="loadEntitlementPlans"
          />
        </template>

        <template v-if="activeMenu === 'knowledge'">
          <KnowledgeManagementView @preview="previewKnowledge" />
        </template>

        <template v-if="activeMenu === 'prompt'">
          <AgentManagementView
            :preview-knowledge-id="previewKnowledgeId"
            @consumed-preview="previewKnowledgeId = null"
          />
        </template>

        <template v-if="activeMenu === 'models'">
          <div class="page-head inline">
            <div>
              <h2>模型管理</h2>
              <p>
                可同时启用多个模型，但只保留一个默认主模型；正式聊天始终使用主模型，报告和摘要按能力标签分流并自动回退主模型。
              </p>
            </div>
            <el-button @click="resetModelForm">清空表单</el-button>
          </div>

          <section class="quick-model-panel">
            <div class="quick-model-head">
              <div>
                <h3>快速添加</h3>
                <p>
                  适用于 DeepSeek 和 MiniMax，只需要填写 API Key 并选择模型。
                </p>
              </div>
            </div>
            <div class="quick-model-grid">
              <el-form-item label="厂商">
                <el-select
                  v-model="quickModelForm.provider"
                  @change="applyQuickProvider"
                >
                  <el-option
                    v-for="provider in quickModelProviders"
                    :key="provider.provider"
                    :label="provider.label"
                    :value="provider.provider"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="模型">
                <el-select
                  v-model="quickModelForm.modelName"
                  :key="quickModelForm.provider"
                >
                  <el-option
                    v-for="model in selectedQuickProvider.models"
                    :key="model.value"
                    :label="model.label"
                    :value="model.value"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="API Key">
                <el-input
                  v-model="quickModelForm.apiKey"
                  placeholder="填写后保存，列表中只展示掩码"
                  show-password
                />
              </el-form-item>
              <el-form-item label=" ">
                <el-button
                  type="primary"
                  class="full-btn"
                  @click="quickAddModel"
                  >快速新增</el-button
                >
              </el-form-item>
            </div>
          </section>

          <el-form
            class="model-config-panel"
            label-position="top"
            :model="modelForm"
          >
            <div class="model-config-grid">
              <el-form-item label="协议模板">
                <el-select
                  placeholder="选择协议模板"
                  clearable
                  @change="applyModelPreset"
                >
                  <el-option
                    v-for="preset in protocolPresets"
                    :key="preset.label"
                    :label="preset.label"
                    :value="preset.label"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="供应商标识">
                <el-input
                  v-model="modelForm.provider"
                  placeholder="custom-openai / custom-anthropic"
                />
              </el-form-item>
              <el-form-item label="显示名称">
                <el-input
                  v-model="modelForm.displayName"
                  placeholder="例如：自建网关生产模型"
                />
              </el-form-item>
              <el-form-item label="协议类型">
                <el-select v-model="modelForm.apiType">
                  <el-option label="OpenAI 兼容" value="openai_compatible" />
                  <el-option
                    label="Anthropic Messages"
                    value="anthropic_messages"
                  />
                  <el-option label="MiniMax 官方" value="minimax" />
                </el-select>
              </el-form-item>
              <el-form-item label="模型名">
                <el-input
                  v-model="modelForm.modelName"
                  placeholder="gpt-4.1 / deepseek-chat / claude..."
                />
              </el-form-item>
              <el-form-item label="Base URL">
                <el-input
                  v-model="modelForm.baseUrl"
                  placeholder="https://api.example.com/v1"
                />
              </el-form-item>
              <el-form-item label="API URL（可覆盖）">
                <el-input
                  v-model="modelForm.apiUrl"
                  placeholder="留空则按协议自动拼接"
                />
              </el-form-item>
              <el-form-item label="鉴权方式">
                <el-select v-model="modelForm.authType">
                  <el-option label="Bearer Token" value="bearer" />
                  <el-option label="x-api-key" value="api_key" />
                </el-select>
              </el-form-item>
              <el-form-item label="API Key">
                <el-input
                  v-model="modelForm.apiKey"
                  placeholder="保存时会覆盖旧 Key"
                  show-password
                />
              </el-form-item>
              <el-form-item label="API Version">
                <el-input
                  v-model="modelForm.apiVersion"
                  placeholder="Anthropic 默认 2023-06-01"
                />
              </el-form-item>
              <el-form-item label="超时秒数">
                <el-input-number
                  v-model="modelForm.timeoutSecond"
                  :min="1"
                  :max="300"
                />
              </el-form-item>
              <el-form-item label="输入单价/千Token">
                <el-input-number
                  v-model="modelForm.inputPricePer1k"
                  :min="0"
                  :precision="6"
                  :step="0.001"
                  placeholder="不填则不估算成本"
                />
              </el-form-item>
              <el-form-item label="输出单价/千Token">
                <el-input-number
                  v-model="modelForm.outputPricePer1k"
                  :min="0"
                  :precision="6"
                  :step="0.001"
                  placeholder="不填则不估算成本"
                />
              </el-form-item>
              <el-form-item label="币种">
                <el-input
                  v-model="modelForm.currency"
                  placeholder="CNY / USD"
                  maxlength="10"
                />
              </el-form-item>
            </div>
            <el-form-item label="适用场景">
              <el-input
                v-model="modelForm.usageScenarios"
                placeholder="例如：正式对话、摘要、固定信息、报告批处理"
              />
            </el-form-item>
            <el-form-item label="可用能力">
              <div>
                <div class="entitlement-capabilities">
                  <el-checkbox
                    v-model="modelForm.allowFixedInfo"
                    :true-value="1"
                    :false-value="0"
                    >固定信息</el-checkbox
                  >
                  <el-checkbox
                    v-model="modelForm.allowSimpleKnowledge"
                    :true-value="1"
                    :false-value="0"
                    >简单知识</el-checkbox
                  >
                  <el-checkbox
                    v-model="modelForm.allowDeepChat"
                    :true-value="1"
                    :false-value="0"
                    >深度对话</el-checkbox
                  >
                  <el-checkbox
                    v-model="modelForm.allowSummary"
                    :true-value="1"
                    :false-value="0"
                    >摘要沉淀</el-checkbox
                  >
                  <el-checkbox
                    v-model="modelForm.allowReport"
                    :true-value="1"
                    :false-value="0"
                    >周期报告</el-checkbox
                  >
                </div>
                <small class="model-routing-help"
                  >默认主模型勾选某项能力时会优先承担该场景；如需专用模型接管，请取消主模型的对应能力，并为专用模型开启该能力。</small
                >
              </div>
            </el-form-item>
            <el-form-item label="备注">
              <el-input
                v-model="modelForm.remark"
                placeholder="用途、额度、注意事项等"
              />
            </el-form-item>
            <div class="actions">
              <el-button type="primary" @click="saveModel">{{
                editingModelId ? "保存模型" : "新增模型"
              }}</el-button>
              <el-button @click="resetModelForm">取消编辑</el-button>
            </div>
          </el-form>
          <el-table :data="models" stripe>
            <el-table-column prop="displayName" label="显示名称" width="170" />
            <el-table-column prop="provider" label="Provider" />
            <el-table-column prop="apiType" label="协议" width="170" />
            <el-table-column prop="modelName" label="模型" />
            <el-table-column label="估算单价" width="180">
              <template #default="{ row }"
                >{{ row.currency || "CNY" }} {{ row.inputPricePer1k ?? "-" }}/{{
                  row.outputPricePer1k ?? "-"
                }}</template
              >
            </el-table-column>
            <el-table-column label="分流能力" min-width="220">
              <template #default="{ row }">
                <div class="model-capability-tags">
                  <el-tag v-if="row.allowDeepChat === 1" size="small"
                    >深度对话</el-tag
                  >
                  <el-tag v-if="row.allowFixedInfo === 1" size="small"
                    >固定信息</el-tag
                  >
                  <el-tag v-if="row.allowSimpleKnowledge === 1" size="small"
                    >简单知识</el-tag
                  >
                  <el-tag
                    v-if="row.allowSummary === 1"
                    size="small"
                    type="success"
                    >摘要</el-tag
                  >
                  <el-tag
                    v-if="row.allowReport === 1"
                    size="small"
                    type="warning"
                    >报告</el-tag
                  >
                </div>
              </template>
            </el-table-column>
            <el-table-column
              prop="baseUrl"
              label="Base URL"
              min-width="220"
              show-overflow-tooltip
            />
            <el-table-column prop="authType" label="鉴权" width="110" />
            <el-table-column label="运行状态" width="150">
              <template #default="{ row }">
                <el-tag :type="row.enabled === 1 ? 'success' : 'info'">{{
                  row.enabled === 1 ? "可用" : "停用"
                }}</el-tag>
                <el-tag v-if="row.isDefault === 1" class="model-default-tag"
                  >主模型</el-tag
                >
              </template>
            </el-table-column>
            <el-table-column
              label="操作"
              width="190"
              fixed="right"
              align="center"
            >
              <template #default="{ row }">
                <TableRowActions
                  ><el-button size="small" @click="editModel(row)"
                    >编辑</el-button
                  ><el-button size="small" @click="testModel(row.id)"
                    >测试</el-button
                  ><el-dropdown
                    trigger="click"
                    teleported
                    @command="
                      (command: string) => handleModelCommand(command, row)
                    "
                    ><el-button size="small">更多</el-button
                    ><template #dropdown
                      ><el-dropdown-menu
                        ><el-dropdown-item
                          v-if="row.enabled !== 1"
                          command="enable"
                          >加入可用池</el-dropdown-item
                        ><el-dropdown-item
                          v-if="row.enabled === 1 && row.isDefault !== 1"
                          command="default"
                          >设为主模型</el-dropdown-item
                        ><el-dropdown-item
                          v-if="row.enabled === 1 && row.isDefault !== 1"
                          command="disable"
                          >停用</el-dropdown-item
                        ><el-dropdown-item
                          v-if="row.isDefault !== 1"
                          command="delete"
                          divided
                          >删除</el-dropdown-item
                        ></el-dropdown-menu
                      ></template
                    ></el-dropdown
                  ></TableRowActions
                >
              </template>
            </el-table-column>
          </el-table>
        </template>

        <ContentGenerationConfigView
          v-if="activeMenu === 'content-generation'"
        />

        <SsoIntegrationView v-if="activeMenu === 'sso'" />

        <SystemConfigView
          v-if="activeMenu === 'configs'"
          :values="systemSettingValues"
          :saving="savingSystemSettings"
          :dirty="systemSettingsDirty"
          @update="updateSystemSetting"
          @save="saveSystemSettings"
        />

        <RetrievalLogView v-if="activeMenu === 'retrievals'" />
        <AttentionManagementView v-if="activeMenu === 'attention'" />
        <FeedbackManagementView v-if="activeMenu === 'feedback'" :can-delete="can('feedback.delete')" />
        <RecordAuditView v-if="activeMenu === 'records'" />
        <AdminManagementView v-if="activeMenu === 'admins'" />
      </section>
    </section>
  </main>

  <el-dialog v-model="passwordDialogVisible" title="首次登录，请修改初始密码" width="460px" :close-on-click-modal="false" :close-on-press-escape="false" :show-close="false">
    <el-alert title="为保障账号安全，修改密码后需要重新登录。" type="warning" :closable="false" show-icon />
    <el-form label-position="top" class="password-form">
      <el-form-item label="当前初始密码"><el-input v-model="passwordForm.currentPassword" type="password" show-password /></el-form-item>
      <el-form-item label="新密码"><el-input v-model="passwordForm.newPassword" type="password" show-password placeholder="至少 8 位" /></el-form-item>
      <el-form-item label="确认新密码"><el-input v-model="passwordForm.confirmPassword" type="password" show-password /></el-form-item>
    </el-form>
    <template #footer><el-button @click="logout">退出登录</el-button><el-button type="primary" :loading="passwordSaving" @click="changeInitialPassword">确认修改</el-button></template>
  </el-dialog>
</template>
