Переглянути джерело

feat(模型管理) 静态页面

hanyang 1 рік тому
батько
коміт
098eaf4fbf

+ 8 - 0
src/api/knowledge.js

@@ -0,0 +1,8 @@
+import request from '../base/ajax';
+// 知识库列表;
+export function getKnowledges(params) {
+  return request({
+    url: `/api/knowledge/list?current=${params.current}&pageSize=${params.pageSize}`,
+    method: 'post'
+  });
+}

+ 8 - 0
src/base/api/knowledge.js

@@ -0,0 +1,8 @@
+import request from '../ajax';
+// 知识库列表
+export function getKnowledges(params) {
+  return request({
+    url: `/api/knowledge/list?current=${params.current}&pageSize=${params.pageSize}`,
+    method: 'get'
+  });
+}

+ 0 - 2
src/index.js

@@ -38,6 +38,4 @@ setupI18n().then((i18n) => {
   app.use(i18n);
   app.mount('#app');
   initTheme();
-  console.log(i18n);
-  window.$t = i18n.global.t;
 });

+ 39 - 0
src/modules/Model/CollapseItem.vue

@@ -0,0 +1,39 @@
+<template>
+  <div class="collapse-item">
+    <div class="name">{{ models.name }}</div>
+    <a-button type="primary" @click="toUse">使用</a-button>
+    <icon-delete class="delete-icon" @click="toDelete" />
+  </div>
+</template>
+
+<script setup>
+const props = defineProps({
+  models: {
+    type: Object,
+    required: true
+  }
+});
+
+const toUse = () => {};
+const toDelete = () => {};
+</script>
+
+<style lang="css" scoped>
+.collapse-item {
+  display: flex;
+  align-items: center;
+  gap: 50px;
+  padding: 10px 30px;
+}
+.name {
+  min-width: 150px;
+  font-size: 14px;
+  font-weight: bold;
+}
+
+.delete-icon {
+  font-size: 20px;
+  color: rgb(var(--orange-5));
+  cursor: pointer;
+}
+</style>

+ 180 - 3
src/modules/Model/MessageBody.vue

@@ -3,25 +3,194 @@
     <div class="body-item">
       <div class="item-title">
         <div class="title">添加了的模型</div>
-        <div class="icon">展开 <icon-down /></div>
+        <div class="icon" @click="changeStatusAdd">
+          <template v-if="added_show_status"> 收起 <icon-up /> </template>
+          <template v-if="!added_show_status"> 展开 <icon-down /> </template>
+        </div>
       </div>
-      <ModelList v-for="item in 3"></ModelList>
+      <transition name="expand-collapse" @before-enter="beforeEnter" @enter="enter" @leave="leave">
+        <div v-if="added_show_status">
+          <ModelList v-for="item in added_data" :key="item.id" :model_item="item" @showMore="showMoreModel"></ModelList>
+        </div>
+      </transition>
     </div>
     <div class="body-item">
       <div class="item-title">
         <div class="title">待添加的模型</div>
-        <div class="icon">展开 <icon-down /></div>
+        <div class="icon" @click="changeStatusUnAdd">
+          <template v-if="unadd_show_status"> 收起 <icon-up /> </template>
+          <template v-if="!unadd_show_status"> 展开 <icon-down /> </template>
+        </div>
       </div>
+      <transition name="expand-collapse" @before-enter="beforeEnter" @enter="enter" @leave="leave">
+        <div v-if="unadd_show_status" class="card-list">
+          <CardItem v-for="item in un_added_data" :key="item.id" :name="item.name" :img_src="item.img_src">
+            <template #labels>
+              {{ item.keyword }}
+            </template>
+            <template #description>
+              {{ item.desc }}
+            </template>
+            <template #bottom>
+              <a-button>
+                <template #icon> <icon-plus /> </template>添加模型</a-button
+              ></template
+            >
+          </CardItem>
+        </div>
+      </transition>
     </div>
   </div>
 </template>
 
 <script setup>
+import { ref } from 'vue';
 import ModelList from './ModelList.vue';
+import CardItem from '../../views/manage-common/CardItem.vue';
+import intelligentFrame1 from '../../assets/image/management/intelligent-frame1.png';
+import intelligentFrame2 from '../../assets/image/management/intelligent-frame2.png';
+import intelligentFrame3 from '../../assets/image/management/intelligent-frame3.png';
+import intelligentFrame4 from '../../assets/image/management/intelligent-frame4.png';
+import intelligentFrame5 from '../../assets/image/management/intelligent-frame5.png';
+import intelligentFrame6 from '../../assets/image/management/intelligent-frame6.png';
+import intelligentFrame7 from '../../assets/image/management/intelligent-frame7.png';
+import intelligentFrame8 from '../../assets/image/management/intelligent-frame8.png';
+import { useCollapse } from './use-collapse';
+
+const { beforeEnter, enter, leave } = useCollapse(1000);
+
+const added_data = ref([
+  {
+    id: '1',
+    name: 'OpenAl-APl-Compatible',
+    desc: 'LLM,TEXT EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame1,
+    show_more: false,
+    models: [
+      {
+        id: '1-1',
+        name: 'deepseek-chat2'
+      },
+      {
+        id: '1-2',
+        name: 'deepseek-coder'
+      },
+      {
+        id: '1-3',
+        name: 'deepseek-coder'
+      }
+    ]
+  },
+  {
+    id: '2',
+    name: 'OpenAl-APl-Compatible',
+    desc: 'LLM,TEXT EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame7,
+    show_more: false,
+    models: [
+      {
+        id: '1-1',
+        name: 'deepseek-chat2'
+      },
+      {
+        id: '1-2',
+        name: 'deepseek-coder'
+      },
+      {
+        id: '1-3',
+        name: 'deepseek-coder'
+      }
+    ]
+  }
+]);
+const un_added_data = ref([
+  {
+    id: '1',
+    name: 'BaiduYiyan',
+    keyword: 'LLM,TEXT',
+    desc: 'EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame1
+  },
+  {
+    id: '2',
+    name: 'BaiduYiyan',
+    keyword: 'LLM,TEXT',
+    desc: 'EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame2
+  },
+  {
+    id: '3',
+    name: 'BaiduYiyan',
+    keyword: 'LLM,TEXT',
+    desc: 'EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame3
+  },
+  {
+    id: '4',
+    name: 'BaiduYiyan',
+    keyword: 'LLM,TEXT',
+    desc: 'EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame4
+  },
+  {
+    id: '5',
+    name: 'BaiduYiyan',
+    keyword: 'LLM,TEXT',
+    desc: 'EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame5
+  },
+  {
+    id: '6',
+    name: 'BaiduYiyan',
+    keyword: 'LLM,TEXT',
+    desc: 'EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame6
+  },
+  {
+    id: '7',
+    name: 'BaiduYiyan',
+    keyword: 'LLM,TEXT',
+    desc: 'EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame7
+  },
+  {
+    id: '8',
+    name: 'BaiduYiyan',
+    keyword: 'LLM,TEXT',
+    desc: 'EMBEDDING,SPEECH2TEXT,MODERATION',
+    img_src: intelligentFrame8
+  }
+]);
+// 展开收起状态
+const added_show_status = ref(true);
+const unadd_show_status = ref(true);
+
+const changeStatusAdd = () => {
+  added_show_status.value = !added_show_status.value;
+  if (!added_show_status.value) {
+    added_data.value.forEach((item) => {
+      item.show_more = false;
+    });
+  }
+};
+const changeStatusUnAdd = () => {
+  unadd_show_status.value = !unadd_show_status.value;
+};
+
+const showMoreModel = (item) => {
+  const index = added_data.value.findIndex((u) => u.id === item.id);
+  if (index !== -1) {
+    added_data.value[index].show_more = !added_data.value[index].show_more;
+  }
+};
 </script>
 <style scoped lang="css">
 .model-body {
   height: calc(100% - 80px);
+  overflow-y: auto;
+}
+.model-body::-webkit-scrollbar {
+  display: none;
 }
 .body-item {
   margin-bottom: 50px;
@@ -31,10 +200,18 @@ import ModelList from './ModelList.vue';
   display: flex;
   flex-direction: row;
   justify-content: space-between;
+  margin-bottom: 20px;
   cursor: pointer;
 }
 .title {
   font-size: 16px;
   font-weight: bold;
 }
+.card-list {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  gap: 20px;
+  transition: all 0.3s ease;
+}
 </style>

+ 57 - 24
src/modules/Model/ModelList.vue

@@ -1,44 +1,73 @@
 <template>
   <div class="model-list">
-    <div class="list-info">
-      <img src="../../assets/image/management/intelligent-frame1.png" alt="" />
-      <div class="info-desc">
-        <div class="name">OpenAl-APl-Compatible</div>
-        <div class="desc">LLM,TEXT EMBEDDING,SPEECH2TEXT,MODERATION</div>
+    <div class="list-header">
+      <div class="list-info">
+        <img :src="model_item.img_src" alt="" />
+        <div class="info-desc">
+          <div class="name">{{ model_item.name }}</div>
+          <div class="desc">{{ model_item.desc }}</div>
+        </div>
+      </div>
+      <div class="list-tools">
+        <a-space>
+          <a-button @click="handlerAddModel">
+            <template #icon>
+              <icon-plus />
+            </template>
+            添加模型
+          </a-button>
+          <a-button @click="showMoreModel(model_item)">
+            展示更多模型
+            <template v-if="model_item.show_more">
+              <icon-down />
+            </template>
+            <template v-if="!model_item.show_more">
+              <icon-up />
+            </template>
+          </a-button>
+          <icon-delete class="delete-icon" @click="handlerDeleteModel" />
+        </a-space>
       </div>
     </div>
-    <div class="list-tools">
-      <a-space>
-        <a-button @click="handlerAddModel">
-          <template #icon>
-            <icon-plus />
-          </template>
-          添加模型
-        </a-button>
-        <a-button @click="showMoreModel">
-          展示更多模型
-          <icon-down />
-        </a-button>
-        <icon-delete class="delete-icon" @click="handlerDeleteModel" />
-      </a-space>
-    </div>
+    <transition name="expand-collapse" @before-enter="beforeEnter" @enter="enter" @leave="leave">
+      <div v-if="model_item.show_more" class="list-collapse">
+        <CollapseItem v-for="item in model_item.models" :key="item.id" :models="item" />
+      </div>
+    </transition>
   </div>
 </template>
 
 <script setup>
+import CollapseItem from './CollapseItem.vue';
+import { useCollapse } from './use-collapse';
+
+const props = defineProps({
+  model_item: {
+    request: true,
+    type: Object
+  }
+});
+const emit = defineEmits(['showMore']);
+
+const { beforeEnter, enter, leave } = useCollapse(500);
+
 const handlerAddModel = () => {};
 const handlerDeleteModel = () => {};
-const showMoreModel = () => {};
+const showMoreModel = (item) => {
+  emit('showMore', item);
+};
 </script>
 <style scoped lang="css">
 .model-list {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
   padding: 20px 30px;
   margin-top: 10px;
   background-color: var(--color-bg-2);
 }
+.list-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
 .list-info {
   display: flex;
   flex-direction: row;
@@ -62,4 +91,8 @@ const showMoreModel = () => {};
   color: rgb(var(--orange-5));
   cursor: pointer;
 }
+.list-collapse {
+  padding: 20px;
+  max-height: 0;
+}
 </style>

+ 31 - 0
src/modules/Model/use-collapse.js

@@ -0,0 +1,31 @@
+import { ref } from 'vue';
+
+// 自定义 Hook 用于过渡效果
+export function useCollapse(initialMaxHeight = 500) {
+  const collapseMaxHeight = ref(initialMaxHeight); // 固定的最大高度
+  // 过渡钩子 - 在元素开始进入时
+  const beforeEnter = (el) => {
+    el.style.maxHeight = 0;
+  };
+
+  // 过渡钩子 - 进入时
+  const enter = (el, done) => {
+    el.offsetHeight; // 强制重排
+    el.style.transition = 'max-height 0.5s ease';
+    el.style.maxHeight = `${collapseMaxHeight.value}px`; // 使用固定的最大高度
+    done();
+  };
+
+  // 过渡钩子 - 离开时
+  const leave = (el, done) => {
+    el.style.transition = 'max-height 0.5s ease';
+    el.style.maxHeight = 0; // 收起时的最小高度
+    done();
+  };
+
+  return {
+    beforeEnter,
+    enter,
+    leave
+  };
+}

+ 19 - 1
src/modules/knowledge/MessageBody.vue

@@ -22,12 +22,13 @@
 </template>
 
 <script setup>
-import { ref } from 'vue';
+import { ref, reactive, onMounted } from 'vue';
 import CardItem from '../../views/manage-common/CardItem.vue';
 import knowledgeFrame1 from '../../assets/image/management/knowledge-frame1.png';
 import knowledgeFrame2 from '../../assets/image/management/knowledge-frame2.png';
 import knowledgeFrame3 from '../../assets/image/management/knowledge-frame3.png';
 import knowledgeFrame4 from '../../assets/image/management/knowledge-frame4.png';
+import { getKnowledges } from '../../api/knowledge';
 
 const moke_data = ref([
   {
@@ -79,12 +80,29 @@ const moke_data = ref([
     time: '2024:11:11 12:00:00'
   }
 ]);
+const pages = reactive({
+  current: 1,
+  pageSize: 18
+});
 
 const handleSelect = ({ value }) => {
   if (value === 'edit') {
   } else {
   }
 };
+
+const getKnowledgesList = async () => {
+  try {
+    const res = await getKnowledges({ current: pages.current, pageSize: pages.pageSize });
+    console.log(res);
+  } catch (err) {
+    console.log(err, 'flag');
+  }
+};
+
+onMounted(() => {
+  // getKnowledgesList();
+});
 </script>
 <style scoped lang="css">
 .body-container {

+ 1 - 1
src/views/layout/ContentContainer.vue

@@ -8,7 +8,7 @@
 .content-container {
   background-color: var(--color-fill-2);
   flex-grow: 1;
-
+  height: calc(100% - 80px);
   padding: 16px;
 }
 </style>

+ 13 - 9
src/views/manage-common/CardItem.vue

@@ -4,12 +4,13 @@
       <img :src="img_src" class="logo" />
       <div class="name">{{ name }}</div>
     </div>
-    <div class="card-des">
-      <slot name="description"></slot>
-    </div>
     <div class="card-label">
       <slot name="labels"></slot>
     </div>
+    <div class="card-des">
+      <slot name="description"></slot>
+    </div>
+
     <div class="card-bottom">
       <slot name="bottom"></slot>
     </div>
@@ -36,7 +37,8 @@ const props = defineProps({
 <style scoped lang="css">
 .card-container {
   position: relative;
-  width: calc((100vw - 160px) / 7);
+  width: calc((100vw / 7) - 18px);
+  flex-grow: 0;
   padding: 10px 20px;
   background-color: var(--color-bg-2);
 }
@@ -46,18 +48,20 @@ const props = defineProps({
   font-weight: bold;
   color: var(--color-neutral-8);
 }
+.card-label {
+  width: 100%;
+  margin-top: 15px;
+  color: var(--color-neutral-4);
+}
 .card-des {
   display: -webkit-box;
   overflow: hidden;
-  margin-top: 10px;
+  margin-top: 5px;
+  color: var(--color-neutral-4);
   -webkit-line-clamp: 2;
   -webkit-box-orient: vertical;
   text-overflow: ellipsis;
 }
-.card-label {
-  width: 100%;
-  margin-top: 15px;
-}
 
 .card-bottom {
   position: absolute;