index.vue 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <script setup lang="ts" name="ViewsChatIndex">
  2. import { ref, onMounted } from 'vue';
  3. import { type Conversation, type Plugin } from '../../api/dto';
  4. import { saveConversation, getAllConversations } from '../../api/chat';
  5. import Sidebar from '../components/Sidebar.vue';
  6. import ChatView from '../components/ChatView.vue';
  7. import { PageWrapper } from '@jeesite/core/components/Page';
  8. const plugins = ref<Plugin[]>([
  9. {
  10. id: 'none',
  11. name: '插件暂不支持',
  12. icon: '🐱',
  13. description: '插件暂不支持',
  14. enabled: true,
  15. version: '1.0.0',
  16. },
  17. ]);
  18. const currentConversation = ref<Conversation>({
  19. id: 1,
  20. title: '新建对话',
  21. timestamps: new Date().toLocaleString(),
  22. status: 'active',
  23. });
  24. const conversations = ref<Conversation[]>([]);
  25. // 初始化 SolonClaw 会话(如果不存在)
  26. async function initSolonClawConversation() {
  27. const stored = await getAllConversations();
  28. const solonClawExists = stored.some((c) => c.id === 'SolonClaw');
  29. if (!solonClawExists) {
  30. const solonClawConv: Conversation = {
  31. id: 'SolonClaw',
  32. title: '猎影',
  33. timestamps: new Date().toLocaleString(),
  34. status: 'active',
  35. isPermanent: true,
  36. icon: '🦊',
  37. };
  38. await saveConversation(solonClawConv);
  39. conversations.value.unshift(solonClawConv);
  40. }
  41. }
  42. async function newConversation() {
  43. const newConv: Conversation = {
  44. id: Date.now(),
  45. title: '新建对话',
  46. timestamps: new Date().toLocaleString(),
  47. status: 'active',
  48. };
  49. conversations.value.unshift(newConv);
  50. currentConversation.value = newConv;
  51. await saveConversation(newConv);
  52. }
  53. function selectConversation(conv: Conversation) {
  54. currentConversation.value = conv;
  55. }
  56. function togglePlugin(pluginId: string) {
  57. const plugin = plugins.value.find((p) => p.id === pluginId);
  58. if (plugin) {
  59. plugin.enabled = !plugin.enabled;
  60. }
  61. }
  62. onMounted(async () => {
  63. // 初始化 SolonClaw 会话 已内置
  64. await initSolonClawConversation();
  65. // 从数据库加载会话列表
  66. const storedConversations = await getAllConversations();
  67. if (storedConversations.length > 0) {
  68. conversations.value = storedConversations as Conversation[];
  69. }
  70. selectConversation(conversations.value[0]);
  71. });
  72. </script>
  73. <template>
  74. <PageWrapper :sidebarWidth="292">
  75. <template #sidebar>
  76. <Sidebar
  77. :conversations="conversations"
  78. :current-conversation="currentConversation"
  79. :plugins="plugins"
  80. @new-conversation="newConversation"
  81. @select-conversation="selectConversation"
  82. @toggle-plugin="togglePlugin"
  83. />
  84. </template>
  85. <ChatView :current-conversation="currentConversation" :plugins="plugins" />
  86. </PageWrapper>
  87. </template>
  88. <style scoped lang="less">
  89. /* 全局样式保持不变,在 App.vue 中定义 */
  90. .app-container {
  91. display: flex;
  92. width: 100%;
  93. height: 100%;
  94. }
  95. ::-webkit-scrollbar {
  96. width: 8px;
  97. height: 8px;
  98. }
  99. ::-webkit-scrollbar-track {
  100. background: transparent;
  101. }
  102. ::-webkit-scrollbar-thumb {
  103. background: @cb-vscode-widget-border;
  104. border-radius: 4px;
  105. }
  106. ::-webkit-scrollbar-thumb:hover {
  107. background: @cb-border-color;
  108. }
  109. </style>