| 1 | <template> |
| 2 | <div class="blur-gradient relative"> |
| 3 | <BlurEffect class="rotate-180" /> |
| 4 | |
| 5 | <n-scrollbar |
| 6 | x-scrollable |
| 7 | class="max-w-full" |
| 8 | trigger="none" |
| 9 | :theme-overrides="{ |
| 10 | railInsetHorizontalBottom: `auto 16px 4px 16px` |
| 11 | }" |
| 12 | > |
| 13 | <div class="flex items-end gap-4 p-4"> |
| 14 | <ChatQuestion |
| 15 | v-for="item of selectedExampleQuestions" |
| 16 | :key="item.question" |
| 17 | :entity="item" |
| 18 | @click="emit('select', item.question)" |
| 19 | /> |
| 20 | </div> |
| 21 | </n-scrollbar> |
| 22 | </div> |
| 23 | </template> |
| 24 | |
| 25 | <script setup lang="ts"> |
| 26 | import type { ExampleQuestion } from "@/types/copilotMCP.d" |
| 27 | import { NScrollbar, useMessage } from "naive-ui" |
| 28 | import { computed, ref, toRefs, watch } from "vue" |
| 29 | import Api from "@/api" |
| 30 | import BlurEffect from "@/components/common/BlurEffect.vue" |
| 31 | import ChatQuestion from "./ChatQuestion.vue" |
| 32 | |
| 33 | const props = defineProps<{ server: string }>() |
| 34 | |
| 35 | const emit = defineEmits<{ |
| 36 | (e: "select", value: string): void |
| 37 | }>() |
| 38 | |
| 39 | const { server } = toRefs(props) |
| 40 | |
| 41 | const loadingExampleQuestions = ref(false) |
| 42 | const message = useMessage() |
| 43 | const exampleQuestions = ref<{ server: string; questions: ExampleQuestion[] }[]>([]) |
| 44 | |
| 45 | const selectedExampleQuestions = computed<ExampleQuestion[]>( |
| 46 | () => exampleQuestions.value.find(o => o.server === server.value)?.questions || [] |
| 47 | ) |
| 48 | |
| 49 | function isServerExamplesFilled(server: string) { |
| 50 | return !!exampleQuestions.value.find(o => o.server === server)?.questions.length |
| 51 | } |
| 52 | |
| 53 | function getExampleQuestions(server: string) { |
| 54 | if (isServerExamplesFilled(server)) { |
| 55 | return |
| 56 | } |
| 57 | |
| 58 | loadingExampleQuestions.value = true |
| 59 | |
| 60 | Api.copilotMCP |
| 61 | .getExampleQuestions(server) |
| 62 | .then(res => { |
| 63 | if (res.data.success) { |
| 64 | upsertExampleQuestions(server, res.data.questions) |
| 65 | } else { |
| 66 | message.warning(res.data?.message || "An error occurred. Please try again later.") |
| 67 | } |
| 68 | }) |
| 69 | .catch(err => { |
| 70 | message.error(err.response?.data?.message || "An error occurred. Please try again later.") |
| 71 | }) |
| 72 | .finally(() => { |
| 73 | loadingExampleQuestions.value = false |
| 74 | }) |
| 75 | } |
| 76 | |
| 77 | function upsertExampleQuestions(server: string, questions: ExampleQuestion[]) { |
| 78 | if (!exampleQuestions.value.some(o => o.server === server)) { |
| 79 | exampleQuestions.value.push({ |
| 80 | server, |
| 81 | questions |
| 82 | }) |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | watch( |
| 87 | server, |
| 88 | val => { |
| 89 | if (val) { |
| 90 | getExampleQuestions(val) |
| 91 | } |
| 92 | }, |
| 93 | { immediate: true } |
| 94 | ) |
| 95 | </script> |
| 96 | |
| 97 | <style lang="scss" scoped> |
| 98 | .blur-gradient { |
| 99 | background: linear-gradient(to top, var(--bg-default-color) 0%, var(--bg-default-color) 20%, transparent 100%); |
| 100 | } |
| 101 | </style> |