lushixing 3 ماه پیش
والد
کامیت
6652cec96c
6فایلهای تغییر یافته به همراه615 افزوده شده و 653 حذف شده
  1. 28 0
      pnpm-lock.yaml
  2. 3 3
      src/router/routes.ts
  3. 573 0
      src/views/ToolDirect.vue
  4. 1 0
      src/views/chat.vue
  5. 10 1
      src/views/index.vue
  6. 0 649
      src/views/search.vue

+ 28 - 0
pnpm-lock.yaml

@@ -23,6 +23,9 @@ importers:
       dompurify:
         specifier: ^3.2.5
         version: 3.2.5
+      hotspot-vue3:
+        specifier: ^1.0.1
+        version: 1.0.1(typescript@5.8.3)
       js-cookie:
         specifier: ^3.0.5
         version: 3.0.5
@@ -1856,6 +1859,9 @@ packages:
   core-js-compat@3.42.0:
     resolution: {integrity: sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==}
 
+  core-js@3.45.1:
+    resolution: {integrity: sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==}
+
   cose-base@1.0.3:
     resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==}
 
@@ -2529,6 +2535,9 @@ packages:
   hookified@1.9.0:
     resolution: {integrity: sha512-2yEEGqphImtKIe1NXWEhu6yD3hlFR4Mxk4Mtp3XEyScpSt4pQ4ymmXA1zzxZpj99QkFK+nN0nzjeb2+RUi/6CQ==}
 
+  hotspot-vue3@1.0.1:
+    resolution: {integrity: sha512-tTrUnpFXDH5QRnDJwkeHQSUCtZO9OH2DuGGPTLamCaBisqoToDDGtmJ1Oz3A7I4p7suGB0Wy8wXYUNPQBVH/dg==}
+
   html-tags@3.3.1:
     resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==}
     engines: {node: '>=8'}
@@ -3694,6 +3703,11 @@ packages:
   vscode-uri@3.0.8:
     resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
 
+  vue-class-component@8.0.0-rc.1:
+    resolution: {integrity: sha512-w1nMzsT/UdbDAXKqhwTmSoyuJzUXKrxLE77PCFVuC6syr8acdFDAq116xgvZh9UCuV0h+rlCtxXolr3Hi3HyPQ==}
+    peerDependencies:
+      vue: ^3.0.0
+
   vue-eslint-parser@10.1.3:
     resolution: {integrity: sha512-dbCBnd2e02dYWsXoqX5yKUZlOt+ExIpq7hmHKPb5ZqKcjf++Eo0hMseFTZMLKThrUk61m+Uv6A2YSBve6ZvuDQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -5652,6 +5666,8 @@ snapshots:
     dependencies:
       browserslist: 4.24.5
 
+  core-js@3.45.1: {}
+
   cose-base@1.0.3:
     dependencies:
       layout-base: 1.0.2
@@ -6448,6 +6464,14 @@ snapshots:
 
   hookified@1.9.0: {}
 
+  hotspot-vue3@1.0.1(typescript@5.8.3):
+    dependencies:
+      core-js: 3.45.1
+      vue: 3.5.14(typescript@5.8.3)
+      vue-class-component: 8.0.0-rc.1(vue@3.5.14(typescript@5.8.3))
+    transitivePeerDependencies:
+      - typescript
+
   html-tags@3.3.1: {}
 
   htmlparser2@8.0.2:
@@ -7711,6 +7735,10 @@ snapshots:
 
   vscode-uri@3.0.8: {}
 
+  vue-class-component@8.0.0-rc.1(vue@3.5.14(typescript@5.8.3)):
+    dependencies:
+      vue: 3.5.14(typescript@5.8.3)
+
   vue-eslint-parser@10.1.3(eslint@9.27.0(jiti@2.4.2)):
     dependencies:
       debug: 4.4.1

+ 3 - 3
src/router/routes.ts

@@ -7,9 +7,9 @@ const routes: Array<RouteRecordRaw> = [
     component: () => import('@/views/index.vue')
   },
   {
-    path: '/search-pages',
-    name: 'Search',
-    component: () => import('@/views/search.vue')
+    path: '/tool-direct/:id',
+    name: 'ToolDirect',
+    component: () => import('@/views/ToolDirect.vue')
   },
   {
     path: '/login',

+ 573 - 0
src/views/ToolDirect.vue

@@ -0,0 +1,573 @@
+<script lang="tsx" setup>
+const route = useRoute()
+
+const loading = ref(true)
+const description = ref('')
+
+setTimeout(() => {
+  loading.value = false
+}, 700)
+
+const pagesId = computed(() => {
+  return route.params.id
+})
+
+
+const pages = computed(() => {
+  let acc = {
+    title: '',
+    desc: '',
+    submitTitle: '',
+    placeholder: '',
+    uploadTitle: '',
+    uploadDesc: ''
+  }
+  switch(pagesId.value) {
+    case '1':
+      acc = {
+        title: '文生款',
+        desc: '通过详细的文字描述,AI将为您生成符合要求的服装设计方案。',
+        submitTitle: '详细描述您想要的服装款式、风格、颜色、材质等',
+        placeholder: '例如:一件适合夏季穿着的波西米亚风格长裙,采用丝绸面料,以佩斯利和花纹为主,土色调为橙色和蓝色...',
+        uploadTitle: '',
+        uploadDesc: ''
+      }
+      break
+    case '2':
+      acc = {
+        title: '图生款',
+        desc: '上传参考图片,AI将基于图片内容创作新的服装设计。',
+        submitTitle: '描述您希望基于参考图片做出的修改和调整',
+        placeholder: '例如:保持整体造型,但将颜色改为深蓝色,材质换成丝绒...',
+        uploadTitle: '',
+        uploadDesc: ''
+      }
+      break
+    case '3':
+      acc = {
+        title: '花型/面料',
+        desc: '描述您想要的花型图案或面料样式,AI将生成专业的设计效果。',
+        submitTitle: '描述您想要的花型图案或面料样式(如已上传参考图,请描述对其的修改需求)',
+        placeholder: '例如:设计一个复古花卉图案,包含玫瑰和叶子元素,适合用于丝巾。或者:保持现有图案的基本结构,但将颜色调整为暖色调...',
+        uploadTitle: '',
+        uploadDesc: ''
+      }
+      break
+    case '4':
+      acc = {
+        title: '面料/颜色测试',
+        desc: '上传服装设计图,通过文字描述更换颜色或面料。',
+        submitTitle: '描述您希望更换的颜色或面料',
+        placeholder: '例如:将上衣颜色改为天蓝色,材质更换为纯棉...',
+        uploadTitle: '',
+        uploadDesc: ''
+      }
+      break
+    case '5':
+      acc = {
+        title: '场景模拟',
+        desc: '上传服装设计图,生成试穿效果图或视频来确认氛围感。',
+        submitTitle: '描述您想要的场景氛围、模特姿势、拍摄角度等',
+        placeholder: '例如:在咖啡厅的温馨环境中,模特坐在窗边,自然光线,展现服装的日常穿搭效果...',
+        uploadTitle: '',
+        uploadDesc: ''
+      }
+      break
+    case '6':
+      acc = {
+        title: '线稿生成',
+        desc: '上传确定好的服装设计图,AI将提取静物轮廓生成专业线稿。',
+        submitTitle: '描述您希望提取线稿的方式或需求',
+        placeholder: '例如:提取服装的主要轮廓线条,保持设计细节,生成适合打版的专业线稿...',
+        uploadTitle: '',
+        uploadDesc: ''
+      }
+      break
+  }
+  acc.uploadTitle = '上传图片'
+  acc.uploadDesc = '拖拽文件到此处,或点击上传'
+  if (pagesId.value === '3') {
+    acc.uploadTitle = '上传花型或面料图案(可选)'
+    acc.uploadDesc = '点击上传现有花型或面料图案作为参考'
+  }
+  return acc
+})
+
+</script>
+
+<template>
+  <LayoutCenterPanel
+    :loading="loading"
+  >
+    <!-- 内容区域 -->
+    <div
+      flex="1 ~ col"
+      h-full
+      class="tool-direct-black"
+    >
+      <div
+        flex="~ items-center"
+        class="tools-header-block"
+      >
+        <div class="back">
+          <svg
+            xmlns="http://www.w3.org/2000/svg"
+            width="24"
+            height="24"
+            viewBox="0 0 24 24"
+            fill="none"
+            stroke="currentColor"
+            stroke-width="2"
+            stroke-linecap="round"
+            stroke-linejoin="round"
+          ><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg>
+        </div>
+        <header class="header-block">
+          <h1>设计智能体</h1>
+          <p>
+            <svg
+              xmlns="http://www.w3.org/2000/svg"
+              width="24"
+              height="24"
+              viewBox="0 0 24 24"
+              fill="none"
+              stroke-width="2"
+              stroke="currentColor"
+            ><path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z" /><path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z" /><path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4" /><path d="M17.599 6.5a3 3 0 0 0 .399-1.375" /><path d="M6.003 5.125A3 3 0 0 0 6.401 6.5" /><path d="M3.477 10.896a4 4 0 0 1 .585-.396" /><path d="M19.938 10.5a4 4 0 0 1 .585.396" /><path d="M6 18a4 4 0 0 1-1.967-.516" /><path d="M19.967 17.484A4 4 0 0 1 18 18" /></svg>
+            {{ pages.title }} - 专业设计工具
+          </p>
+        </header>
+      </div>
+      <div
+        flex="1 ~ col"
+        class="tool-direct-content-black"
+      >
+        <div
+          min-h-0
+          class="tool-direct-content"
+        >
+          <div class="tool-direct-left">
+            <div class="tool-direct-left__title">
+              <svg
+                xmlns="http://www.w3.org/2000/svg"
+                width="24"
+                height="24"
+                viewBox="0 0 24 24"
+                fill="none"
+                stroke="currentColor"
+                stroke-width="2"
+                stroke-linecap="round"
+                stroke-linejoin="round"
+              ><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" /><path d="M20 3v4" /><path d="M22 5h-4" /><path d="M4 17v2" /><path d="M5 18H3" /></svg>
+              <h3>{{ pages.title }}</h3>
+            </div>
+            <div class="tool-direct-left__desc">{{ pages.desc }}</div>
+            <div
+              v-if="pagesId != '1'"
+              class="tools-upload-black"
+            >
+              <div class="tools-upload__title">{{ pages.uploadTitle }}</div>
+              <div class="tools-upload">
+                <n-upload
+                  directory-dnd
+                  action="https://www.mocky.io/v2/5e4bafc63100007100d8b70f"
+                >
+                  <n-upload-dragger>
+                    <div style="margin-bottom: 12px">
+                      <svg
+                        xmlns="http://www.w3.org/2000/svg"
+                        width="24"
+                        height="24"
+                        viewBox="0 0 24 24"
+                        fill="none"
+                        stroke="currentColor"
+                        stroke-width="2"
+                        stroke-linecap="round"
+                        stroke-linejoin="round"
+                      ><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><polyline points="17 8 12 3 7 8" /><line
+                        x1="12"
+                        x2="12"
+                        y1="3"
+                        y2="15"
+                      /></svg>
+                    </div>
+                    <n-text style="font-size: 16px">
+                      {{ pages.uploadDesc }}
+                    </n-text>
+                    <n-p
+                      depth="3"
+                      style="margin: 8px 0 0 0"
+                    >
+                      支持 JPG, PNG, WEBP
+                    </n-p>
+                  </n-upload-dragger>
+                </n-upload>
+              </div>
+            </div>
+            <div
+              class="tool-direct-left__submit"
+              flex="1 ~ col"
+            >
+              <p>{{ pages.submitTitle }}</p>
+              <n-space
+                vertical
+                flex="1 ~ col"
+              >
+                <n-input
+                  v-model:value="description"
+                  class="full-input"
+                  type="textarea"
+                  :placeholder="pages.placeholder"
+                />
+              </n-space>
+            </div>
+            <div class="tool-direct-left__btns">
+              <svg
+                xmlns="http://www.w3.org/2000/svg"
+                width="24"
+                height="24"
+                viewBox="0 0 24 24"
+                fill="none"
+                stroke="currentColor"
+                stroke-width="2"
+                stroke-linecap="round"
+                stroke-linejoin="round"
+              ><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" /><path d="M20 3v4" /><path d="M22 5h-4" /><path d="M4 17v2" /><path d="M5 18H3" /></svg>
+              开始生成
+            </div>
+          </div>
+          <div
+            class="tool-direct-right"
+            flex="1 ~ col"
+          >
+            <div class="tool-direct-right__title">
+              <h3>生成结果</h3>
+            </div>
+            <div
+              class="tool-direct-right__result"
+              flex="1 ~ col"
+              h-full
+            >
+              <div
+                class="result-empty"
+                flex="1 ~ col"
+              >
+                <svg
+                  xmlns="http://www.w3.org/2000/svg"
+                  width="24"
+                  height="24"
+                  viewBox="0 0 24 24"
+                  fill="none"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                ><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" /><path d="M20 3v4" /><path d="M22 5h-4" /><path d="M4 17v2" /><path d="M5 18H3" /></svg>
+                生成的设计将在这里显示
+              </div>
+              <div
+                class="tool-direct-right__loading"
+                flex="1 ~ col"
+              >
+                <svg
+                  xmlns="http://www.w3.org/2000/svg"
+                  width="24"
+                  height="24"
+                  viewBox="0 0 24 24"
+                  fill="none"
+                  stroke="currentColor"
+                  stroke-width="2"
+                  stroke-linecap="round"
+                  stroke-linejoin="round"
+                  style="color: rgb(154, 120, 110);"
+                ><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg>
+                AI正在为您生成设计...
+              </div>
+              <div class="result-success">
+                <div class="preview-black__images">
+                  <div class="images-preview">
+                    <img
+                      src="https://www.goelia1995.com/cdn/shop/files/Office_Inspiration_bc3a97ac-629a-4886-8091-2aa8431de2aa.jpg?v=1754637750"
+                      alt=""
+                    >
+                  </div>
+                  <div class="images-preview__icon">
+                    <div class="like-icons icons">
+                      <svg
+                        xmlns="http://www.w3.org/2000/svg"
+                        width="24"
+                        height="24"
+                        viewBox="0 0 24 24"
+                        fill="none"
+                        stroke="#EF4444"
+                        stroke-width="2"
+                        stroke-linecap="round"
+                        stroke-linejoin="round"
+                      ><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z" /></svg>
+                    </div>
+                    <div class="download-icon icons">
+                      <svg
+                        xmlns="http://www.w3.org/2000/svg"
+                        width="24"
+                        height="24"
+                        viewBox="0 0 24 24"
+                        fill="none"
+                        stroke="currentColor"
+                        stroke-width="2"
+                        stroke-linecap="round"
+                        stroke-linejoin="round"
+                      ><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><polyline points="7 10 12 15 17 10" /><line
+                        x1="12"
+                        x2="12"
+                        y1="15"
+                        y2="3"
+                      /></svg>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </LayoutCenterPanel>
+</template>
+
+<style lang="scss">
+  .tool-direct-black {
+    padding: 24px;
+    background: #F7F3EE;
+    width: 100%;
+    height: 100%;
+    min-height: 100vh;
+  }
+  .tools-header-block {
+    display: flex;
+    gap: 16px;
+    align-items: center;
+    margin-bottom: 24px;
+
+    .back {
+      width: 40px;
+      height: 40px;
+      background-color: white;
+      color: rgb(80, 60, 55);
+      box-shadow: rgba(154, 120, 110, 0.2) 0px 1px 3px;
+      border-radius: 6px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      cursor: pointer;
+
+      svg {
+        width: 16px;
+        height: 16px;
+      }
+    }
+  }
+  .header-block {
+    h1 {
+      font-size: 30px;
+      line-height: 36px;
+      color: rgb(80, 60, 55);
+    }
+
+    p {
+      display: flex;
+      gap: 4px;
+      line-height: 24px;
+      font-size: 16px;
+      color: rgb(154, 120, 110);
+      align-items: center;
+      padding: 0;
+      margin: 0;
+      margin-top: 4px;
+
+      svg {
+        width: 16px;
+        height: 16px;
+        flex: 0 0 16px;
+      }
+    }
+  }
+  .tool-direct-content {
+    width: 100%;
+    max-width: 1536px;
+    margin: 0 auto;
+    display: flex;
+    align-items: stretch;
+    gap: 24px;
+    flex: 1 1 0%;
+
+    .tool-direct-left,
+    .tool-direct-right {
+      width: calc(50% - 12px);
+      flex: 1;
+      border: 1px solid rgba(154, 120, 110, 0.2);
+      box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+      background: rgb(255 255 255 / 0.8);
+      border-radius: 8px;
+      padding: 24px;
+      min-height: 282px;
+    }
+    .tool-direct-left {
+      display: flex;
+      flex-direction: column;
+      .tool-direct-left__title {
+        display: flex;
+        gap: 12px;
+        align-items: center;
+
+        h3 {
+          font-size: 24px;
+          line-height: 1;
+          color: rgb(80, 60, 55);
+        }
+
+        svg {
+          width: 20px;
+          height: 20px;
+          color: rgb(154, 120, 110);
+        }
+      }
+      .tool-direct-left__desc {
+        font-size: 14px;
+        color: rgb(154, 120, 110);
+        margin-top: 8px;
+      }
+      .tools-upload-black {
+        margin-top: 24px;
+        .tools-upload__title {
+          font-size: 14px;
+          line-height: 20px;
+          margin-bottom: 5px;
+        }
+      }
+      .tool-direct-left__submit {
+        margin-top: 24px;
+
+        .n-space > div {
+          height: 100%;
+        }
+        .full-input {
+          height: 100%;
+        }
+
+        p {
+          margin: 0;
+          font-size: 14px;
+          margin-bottom: 6px;
+        }
+      }
+      .tool-direct-left__btns {
+        margin-top: 24px;
+        background: linear-gradient(135deg, rgb(194, 140, 110), rgb(154, 120, 110));
+        border-radius: 6px;
+        padding: 8px 16px;
+        width: 100%;
+        display: flex;
+        align-items: center;
+        gap: 12px;
+        justify-content: center;
+        cursor: pointer;
+        font-size: 14px;
+        color: #fff;
+        min-height: 40px;
+
+        &:hover {
+          background: linear-gradient(135deg, rgb(194, 140, 110), rgb(154, 120, 110));
+          box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+        }
+
+        svg {
+          width: 16px;
+          height: 16px;
+          color: #fff;
+        }
+      }
+    }
+    .tool-direct-right {
+      .tool-direct-right__title {
+        margin-bottom: 24px;
+        h3 {
+          font-size: 24px;
+          line-height: 1;
+          color: rgb(80, 60, 55);
+        }
+      }
+      .result-empty {
+        align-items: center;
+        justify-content: center;
+        color: rgb(154, 120, 110);
+        font-size: 14px;
+        gap: 16px;
+        display: none;
+        svg {
+          width: 64px;
+          height: 64px;
+          color: rgb(154, 120, 110, 0.5);
+        }
+      }
+      .tool-direct-right__loading {
+        font-size: 14px;
+        gap: 16px;
+        align-items: center;
+        justify-content: center;
+        color: rgb(154, 120, 110);
+        display: none;
+
+        svg {
+          width: 48px;
+          height: 48px;
+          animation: spin 1s linear infinite;
+        }
+      }
+      .preview-black__images {
+        position: relative;
+        background: rgb(241 245 249 / var(--tw-bg-opacity, 1));
+        border-radius: 8px;
+        overflow: hidden;
+
+        img {
+          display: block;
+          max-width: 100%;
+        }
+
+        .images-preview__icon {
+          position: absolute;
+          bottom: 20px;
+          right: 20px;
+          gap: 8px;
+          display: none;
+          animation-duration: 300ms;
+
+          .icons {
+            width: 40px;
+            height: 40px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+            background: rgb(255 255 255 / 0.9);
+            border: 1px solid hsl(240 5.9% 90%);
+            border-radius: 6px;
+            cursor: pointer;
+
+            svg {
+              width: 16px;
+              height: 16px;
+            }
+          }
+        }
+
+        &:hover {
+          .images-preview__icon {
+            display: flex;
+          }
+        }
+      }
+    }
+  }
+  @keyframes spin{to{transform:rotate(360deg)}}
+</style>

+ 1 - 0
src/views/chat.vue

@@ -427,6 +427,7 @@ const hangdleSmearToolModal = () => {
                 height="24"
                 viewBox="0 0 24 24"
                 fill="none"
+                stroke-width="2"
                 stroke="currentColor"
               ><path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z" /><path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z" /><path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4" /><path d="M17.599 6.5a3 3 0 0 0 .399-1.375" /><path d="M6.003 5.125A3 3 0 0 0 6.401 6.5" /><path d="M3.477 10.896a4 4 0 0 1 .585-.396" /><path d="M19.938 10.5a4 4 0 0 1 .585.396" /><path d="M6 18a4 4 0 0 1-1.967-.516" /><path d="M19.967 17.484A4 4 0 0 1 18 18" /></svg>
               与设计智能体对话,释放无限创意

+ 10 - 1
src/views/index.vue

@@ -1,5 +1,4 @@
 <script lang="tsx" setup>
-import { type InputInst } from 'naive-ui'
 const router = useRouter()
 
 
@@ -37,6 +36,15 @@ const gotoChat = () => {
   })
 }
 
+const gotoToolDirect = (index) => {
+  router.push({
+    name: 'ToolDirect',
+    params: {
+      id: index + 1
+    }
+  })
+}
+
 interface ToolsItem {
   svg: string
   title: string
@@ -162,6 +170,7 @@ const Tools = ref<ToolsItem[]>([
                   <li
                     v-for="(acc, index) in Tools"
                     :key="index"
+                    @click="gotoToolDirect(index)"
                   >
                     <span
                       class="items-svg"

+ 0 - 649
src/views/search.vue

@@ -1,649 +0,0 @@
-<script lang="tsx" setup>
-import request from '@/utils/request'
-const router = useRouter()
-
-
-const loading = ref(true)
-const fileLoading = ref(false)
-const pdfPreview = ref(false)
-const iframeTitle = ref('')
-const iframeURL = ref('')
-const keywords = ref('')
-const isSearch = ref(false)
-interface KnowledgeItem {
-  file_name: string
-  extension: string
-  file_url: string
-  match_text: string
-  file_updated_at: string
-  cover_url: string
-}
-
-const knowledgeList = ref<KnowledgeItem[]>([])
-
-setTimeout(() => {
-  loading.value = false
-}, 700)
-
-
-const stylizingLoading = ref(false)
-
-
-/**
- * 输入字符串
- */
-const inputTextString = ref('')
-
-
-const refReaderMarkdownPreview = ref<any>()
-
-
-const handleResetState = () => {
-  inputTextString.value = ''
-
-  stylizingLoading.value = false
-  refReaderMarkdownPreview.value?.abortReader()
-  refReaderMarkdownPreview.value?.resetStatus()
-}
-handleResetState()
-
-const gotoHome = () => {
-  router.push({
-    name: 'Home',
-    query: {
-      tkn_8f9a1c7b3e24fd: 'c154d4a7-dad3-45d0-a11f-07893dd4fbba'
-    }
-  })
-}
-function debounce<T extends (...args: any[]) => void>(
-  fn: T,
-  delay: number
-): (...args: Parameters<T>) => void {
-  let timer: ReturnType<typeof setTimeout> | null = null
-  return (...args: Parameters<T>) => {
-    if (timer !== null) {
-      clearTimeout(timer)
-    }
-    timer = setTimeout(() => {
-      fn(...args) // 不使用 this
-    }, delay)
-  }
-}
-
-
-const inputSearch = debounce(() => {
-  if (!keywords.value) {
-    knowledgeList.value = []
-    return
-  }
-  const params = {
-    'client_id': `${ Date.now() + 10 }`,
-    'prompt': keywords.value
-  }
-  request.post(`/search`, params).then((res) => {
-    isSearch.value = true
-    if (res.data.code === 200) {
-      knowledgeList.value = res.data.content
-    } else {
-      window.$ModalMessage.error(res.data.message)
-    }
-  })
-}, 500)
-
-const clear = () => {
-  isSearch.value = false
-  knowledgeList.value = []
-}
-
-const openLink = (link: string, file_name: string) => {
-  previewFile(link.split('?')[0], file_name)
-}
-
-/**
- * 通用文件预览函数
- * @param fileUrl - 文件的公网 URL 地址
- */
-async function previewFile(fileUrl: string, file_name: string) {
-  const ext = fileUrl.split('.').pop()?.toLowerCase().split('?')[0] || ''
-  const open = (url: string) => {
-    location.href = url
-  }
-
-  const isOffice = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(ext)
-  const isText = ['txt', 'csv'].includes(ext)
-
-  if (ext === 'pdf') {
-    // fileLoading.value = true
-    // const disposition = await checkContentDisposition(fileUrl)
-    // if (disposition === 'inline') {
-    //   fileLoading.value = false
-    //   open(fileUrl)
-    // } else {
-    //   await openPdfAsBlob(fileUrl) // fallback:强制以 blob 打开
-    //   fileLoading.value = false
-    // }
-    iframeTitle.value = file_name
-    iframeURL.value = `${ location.origin }/pdfJS/web/viewer.html?file=${ encodeURIComponent(fileUrl) }`
-    pdfPreview.value = true
-  } else if (isOffice) {
-    const encoded = encodeURIComponent(fileUrl)
-    open(`https://view.officeapps.live.com/op/view.aspx?src=${ encoded }`)
-  } else if (isText) {
-    open(fileUrl)
-  } else {
-    // fallback:不支持的格式可以提示或触发下载
-    const a = document.createElement('a')
-    a.href = fileUrl
-    a.download = ''
-    a.click()
-  }
-}
-
-const closePreview = () => {
-  iframeTitle.value = ''
-  iframeURL.value = ''
-  pdfPreview.value = false
-}
-
-
-</script>
-
-<template>
-  <LayoutCenterPanel
-    :loading="loading"
-  >
-    <!-- 内容区域 -->
-    <div
-      flex="~ col"
-      h-full
-    >
-      <div
-        flex="~ justify-between items-center"
-      >
-        <div class="index-header-block">
-          <div class="index-header">
-            <div class="saerch-black">
-              <div class="saerch-black__input">
-                <span class="search-icon">
-                  <svg
-                    t="1751009112601"
-                    class="icon"
-                    viewBox="0 0 1024 1024"
-                    version="1.1"
-                    xmlns="http://www.w3.org/2000/svg"
-                    p-id="5234"
-                    xmlns:xlink="http://www.w3.org/1999/xlink"
-                    width="200"
-                    height="200"
-                  ><path
-                    d="M470.4 912c-112 0-224-41.6-310.4-128C-9.6 611.2-9.6 332.8 160 160c172.8-172.8 451.2-172.8 620.8 0 172.8 172.8 172.8 451.2 0 620.8C697.6 867.2 582.4 912 470.4 912z m0-803.2c-92.8 0-185.6 35.2-256 105.6-140.8 140.8-140.8 374.4 0 515.2 140.8 140.8 374.4 140.8 515.2 0 140.8-140.8 140.8-374.4 0-515.2-70.4-70.4-166.4-105.6-259.2-105.6z"
-                    p-id="5235"
-                  /><path
-                    d="M905.6 976l-160-160c-19.2-19.2-19.2-51.2 0-70.4s51.2-19.2 70.4 0l160 160c19.2 19.2 19.2 51.2 0 70.4-19.2 22.4-51.2 22.4-70.4 0z"
-                    p-id="5236"
-                  /></svg>
-                </span>
-                <div class="input-black">
-                  <n-input
-                    v-model:value="keywords"
-                    clearable
-                    type="text"
-                    placeholder="搜索知识库内容"
-                    @input="inputSearch"
-                    @clear="clear"
-                  />
-                </div>
-              </div>
-              <div
-                class="close"
-                @click="gotoHome"
-              >
-                取消
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <div
-        flex="1 ~ col"
-        min-h-0
-        pb-20
-        class="knowledge-black"
-      >
-        <div
-          v-if="knowledgeList.length"
-          class="knowledge-scroll"
-        >
-          <!-- 列表 -->
-          <div
-            class="knowledge__list"
-          >
-            <ul
-              class="knowledge__list-ul"
-            >
-              <li
-                v-for="(acc, index) in knowledgeList"
-                :key="index"
-                class="knowledge__list-items"
-                @click="openLink(acc.file_url, acc.file_name)"
-              >
-                <span
-                  v-if="acc.cover_url"
-                  class="items-img"
-                >
-                  <img
-                    :src="acc.cover_url"
-                    alt=""
-                  >
-                </span>
-                <span
-                  v-else
-                  class="items-img"
-                >GOELIA</span>
-                <div class="items-info">
-                  <h2 v-html="acc.file_name"></h2>
-                  <p
-                    v-if="acc.match_text"
-                    class="desc"
-                    v-html="acc.match_text"
-                  ></p>
-                  <div class="items-info-content">
-                    <span class="type">{{ acc.extension }}</span>
-                    <span class="line">|</span>
-                    <span class="date">{{ acc.file_updated_at }}</span>
-                  </div>
-                </div>
-              </li>
-            </ul>
-          </div>
-        </div>
-        <div
-          v-if="!knowledgeList.length && isSearch"
-          class="no-data"
-        >
-          未找到相关搜索结果
-        </div>
-      </div>
-    </div>
-    <div
-      v-if="fileLoading"
-      class="loading-block"
-    >
-      <div class="loading-items">
-        <div class="loading-container">
-          <div class="loading-overlay__spinner"></div>
-        </div>
-        <span class="loading-text">文件加载中...</span>
-      </div>
-    </div>
-    <div
-      v-if="pdfPreview"
-      class="pdf-black"
-    >
-      <div
-        class="header-block-div"
-        @click="closePreview()"
-      >
-        <span class="back"><svg
-          xmlns="http://www.w3.org/2000/svg"
-          viewBox="0 0 24 24"
-          aria-hidden="true"
-          focusable="false"
-          role="presentation"
-          class="icon icon-caret"
-        >
-          <path d="M 7.75 1.34375 L 6.25 2.65625 L 14.65625 12 L 6.25 21.34375 L 7.75 22.65625 L 16.75 12.65625 L 17.34375 12 L 16.75 11.34375 Z" />
-        </svg></span>
-        <div class="title-black">
-          <span
-            class="title"
-            v-html="iframeTitle"
-          ></span>
-          <span class="subtitle">文件预览</span>
-        </div>
-      </div>
-      <iframe
-        :src="iframeURL"
-        frameborder="0"
-      ></iframe>
-    </div>
-  </LayoutCenterPanel>
-</template>
-
-<style lang="scss">
-  .index-header-block {
-    padding: 0 14px;
-    width: 100%;
-    .logo {
-      padding: 10px 0;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      margin: 0 auto;
-      width: 100%;
-
-      img {
-        max-width: 140px;
-      }
-    }
-    .index-header {
-      margin: 10px 0;
-    }
-    .index-header .saerch-black{
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-      min-height: 40px;
-      gap: 10px;
-      width: 100%;
-
-      .saerch-black__input {
-        display: flex;
-        position: relative;
-        background: #EFEFEF;
-        border-radius: 8px;
-        height: 40px;
-        width: 100%;
-
-        .search-icon {
-          position: absolute;
-          top: 0;
-          left: 0;
-          width: 40px;
-          height: 40px;
-          display: flex;
-          justify-content: center;
-          align-items: center;
-
-          svg {
-            width: 16px;
-            height: 16px;
-          }
-        }
-        .input-black {
-          display: block;
-          width: 100%;
-          height: 100%;
-          padding-left: 40px;
-
-          .n-input {
-            height: 100%;
-            border: none;
-            background: none;
-            background-color: transparent;
-          }
-          .n-input .n-input-wrapper {
-            padding: 0;
-          }
-          .n-input__border,.n-input__state-border {
-            display: none;
-          }
-          .n-input .n-input__suffix, .n-input .n-input__prefix {
-            width: 40px;
-            margin: 0;
-          }
-          .n-base-clear > .n-base-clear__clear {
-            width: 25px;
-            height: 25px;
-            font-size: 25px;
-          }
-          .n-input .n-input__placeholder {
-            font-size: 16px;
-          }
-          .n-input .n-input__suffix .n-base-icon, .n-input .n-input__prefix .n-base-icon {
-            font-size: 25px;
-          }
-          .n-input__input-el {
-            border: none;
-            background: none;
-            display: block;
-            width: 100%;
-            height: 100%;
-            font-size: 16px;
-            color: #232323;
-            outline: none;
-          }
-        }
-      }
-      .close {
-        font-size: 14px;
-        white-space: nowrap;
-        color: #232323;
-        height: 40px;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        padding: 0 5px;
-        cursor: pointer;
-        font-size: 16px;
-        color: #232323;
-      }
-    }
-  }
-  .index-bottom {
-    .click-router {
-      position: absolute;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      z-index: 100;
-    }
-  }
-  .knowledge-black .no-data {
-    font-size: 16px;
-    display: flex;
-    width: 100%;
-    height: 100%;
-    justify-content: center;
-    align-items: center;
-    color: #999;
-  }
-  .knowledge-black .knowledge-scroll{
-    height: 100%;
-    overflow: hidden;
-    overflow-y: scroll;
-  }
-  .knowledge__list {
-    padding: 14px;
-
-    .knowledge__list-items {
-      display: flex;
-      align-items: center;
-      padding: 10px 0;
-      border-bottom: 1px solid #f2f2f2;
-      gap: 10px;
-
-      &:last-child {
-        border-bottom: none;
-      }
-
-      .items-img {
-        width: 60px;
-        height: 60px;
-        flex: 0 0 60px;
-        border-radius: 2px;
-        background: #f2f2f2;
-        color: #dddddd;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        font-size: 13px;
-
-        img {
-          display: block;
-          max-width: 100%;
-        }
-      }
-      .items-info {
-        width: calc(100% - 70px);
-        h2 {
-          font-size: 15px;
-          line-height: 1.5;
-          color: #232323;
-          font-weight: normal;
-          margin-bottom: 6px;
-          white-space: nowrap;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          b {
-            font-weight: normal;
-            color: #079D55;
-          }
-        }
-        .items-info-content {
-          display: flex;
-          gap: 8px;
-          font-size: 13px;
-          line-height: 1.5;
-          color: #999;
-          align-items: center;
-        }
-        .desc {
-          font-size: 12px;
-          margin: 0;
-          white-space: nowrap;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          color: #999;
-          line-height: 1.5;
-          margin-bottom: 6px;
-
-          br {
-            display: none;
-          }
-
-          b {
-            font-weight: normal;
-            color: #079D55;
-          }
-        }
-      }
-    }
-  }
-  .bottom-block .n-input {
-    border-radius: 14px;
-  }
-  .bottom-block .n-input.n-input--textarea .n-input__textarea-el {
-    max-height: 60px;
-  }
-  .loading-block {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    z-index: 99;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    .loading-items {
-      width: 150px;
-      height: 120px;
-      border-radius: 10px;
-      background: #4C4C4C;
-      display: flex;
-      flex-direction: column;
-      justify-content: center;
-    }
-    .loading-container {
-      display: flex;
-      justify-content: center;
-
-      .loading-overlay__spinner {
-        width: auto;
-        position: relative;
-        text-align: center;
-        font-size: 0;
-        display: flex;
-        justify-content: center;
-        &::before {
-          content: "";
-          width: 40px;
-          height: 40px;
-          box-sizing: border-box;
-          border-radius: 50%;
-          border: 3px solid #ccc;
-          border-right-color: #666;
-          border-bottom-color: #666;
-          border-left-color: #666;
-          animation: donutRotate 1s linear infinite;
-        }
-      }
-    }
-    .loading-text {
-      display: block;
-      text-align: center;
-      font-size: 16px;
-      color: #fff;
-      margin-top: 10px;
-    }
-  }
-  @keyframes donutRotate {
-      0% {
-          transform: rotate(0);
-      }
-
-      100% {
-          transform: rotate(360deg);
-      }
-  }
-  .pdf-black {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    z-index: 999;
-    background: #fff;
-    iframe {
-      display: block;
-      width: 100%;
-      height: calc(100% - 44px);
-    }
-    .header-block-div {
-      display: flex;
-      align-items: center;
-      gap: 5px;
-      cursor: pointer;
-      width: 100%;
-      display: flex;
-      padding-left: 16px;
-      padding-right: 16px;
-      min-height: 44px;
-      align-items: center;
-
-      .title-black {
-        display: flex;
-        flex-direction: column;
-        width: calc(100% - 25px);
-      }
-    }
-    .back {
-      display: flex;
-      align-items: center;
-
-      svg {
-        width: 16px;
-        height: 16px;
-        transform: rotate(180deg);
-      }
-    }
-    .title {
-      font-weight: bold;
-      font-size: 14px;
-      line-height: 1.5;
-      white-space: nowrap;
-      text-overflow: ellipsis;
-      overflow: hidden;
-      width: 100%;
-      display: block;
-    }
-    .subtitle {
-      font-size: 12px;
-      color: #999;
-      line-height: 1.5;
-    }
-  }
-</style>