Pārlūkot izejas kodu

📦 ai相关模块代码分包拆分大小优化

快乐的梦鱼 3 nedēļas atpakaļ
vecāks
revīzija
b3e238f2e7
59 mainītis faili ar 302 papildinājumiem un 109 dzēšanām
  1. 1 1
      src/api/agent/Agent.ts
  2. 16 1
      src/components/dialog/Popup.vue
  3. 93 41
      src/components/feedback/BubbleBox.vue
  4. 20 0
      src/pages.json
  5. 1 0
      src/pages/chat/components/ChatFooter.vue
  6. 5 4
      src/pages/chat/components/ChatMessage.vue
  7. 0 0
      src/pages/home/chat/components/ChatMessageContainer.vue
  8. 0 0
      src/pages/home/chat/components/Compoents/ExpandButton.vue
  9. 0 0
      src/pages/home/chat/components/Footer/ChatMulitSelectBar.vue
  10. 0 0
      src/pages/home/chat/components/Session/ChatSessionRenameDialog.vue
  11. 0 0
      src/pages/home/chat/components/Session/ChatSessionSidebar.vue
  12. 0 0
      src/pages/home/chat/components/Session/ChatSessionSidebarEmpty.vue
  13. 0 0
      src/pages/home/chat/components/Session/ChatSessionSidebarGroupHeader.vue
  14. 0 0
      src/pages/home/chat/components/Session/ChatSessionSidebarItem.vue
  15. 0 0
      src/pages/home/chat/components/Session/ChatSessionSidebarLoadMore.vue
  16. 0 0
      src/pages/home/chat/components/zero-markdown-view/changelog.md
  17. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/highlight/config.js
  18. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/highlight/index.js
  19. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/highlight/prism.min.js
  20. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/latex/index.js
  21. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/latex/katex.min.js
  22. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/markdown/index.js
  23. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/markdown/marked.min.js
  24. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/mp-html.vue
  25. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/node/node.vue
  26. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/parser.js
  27. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/style/index.js
  28. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/mp-html/style/parser.js
  29. 0 0
      src/pages/home/chat/components/zero-markdown-view/components/zero-markdown-view/zero-markdown-view.vue
  30. 0 0
      src/pages/home/chat/components/zero-markdown-view/package.json
  31. 0 0
      src/pages/home/chat/components/zero-markdown-view/readme.md
  32. 0 0
      src/pages/home/chat/composables/useChatExportSave.ts
  33. 0 0
      src/pages/home/chat/composables/useChatHistoryItemsPager.ts
  34. 0 0
      src/pages/home/chat/composables/useChatRecordInput.ts
  35. 0 0
      src/pages/home/chat/composables/useChatSelection.ts
  36. 0 0
      src/pages/home/chat/composables/useChatSession.ts
  37. 0 0
      src/pages/home/chat/core/Chat.ts
  38. 0 0
      src/pages/home/chat/core/Context.ts
  39. 0 0
      src/pages/home/chat/core/Groups.ts
  40. 0 0
      src/pages/home/chat/core/Messages.ts
  41. 0 0
      src/pages/home/chat/core/StaticMessages.ts
  42. 1 1
      src/pages/chat/core/ToolCall.ts
  43. 0 0
      src/pages/home/chat/core/Tools.ts
  44. 0 0
      src/pages/home/chat/core/speical/ssemp.ts
  45. 0 0
      src/pages/home/chat/core/strategy/ContextSlideWindowStrategy.ts
  46. 12 12
      src/pages/chat/dependent/post/agent.vue
  47. 75 0
      src/pages/home/chat/dependent/post/components/tbutton.vue
  48. 0 0
      src/pages/home/chat/dependent/post/composables/agentTools.ts
  49. 28 17
      src/pages/chat/dependent/post/publish.vue
  50. 7 7
      src/pages/chat/index.vue
  51. 0 0
      src/pages/home/chat/model/Message.ts
  52. 0 0
      src/pages/home/chat/utils/ChatUtils.ts
  53. 6 2
      src/pages/home/index.vue
  54. 5 2
      src/pages/home/village/components/VillageGallery.vue
  55. 1 1
      src/pages/home/village/dialogs/PostIndex.vue
  56. 1 1
      src/pages/home/village/gallery/index.vue
  57. 20 13
      src/pages/home/village/index.vue
  58. 9 5
      src/pages/home/village/introd/card.vue
  59. 1 1
      src/pages/index.vue

+ 1 - 1
src/api/agent/Agent.ts

@@ -2,7 +2,7 @@ import { DataModel, type KeyValue } from "@imengyu/js-request-transform";
 import { appendGetUrlParams, assertNotNull, RandomUtils } from "@imengyu/imengyu-utils";
 import { useAuthStore } from "@/store/auth";
 import { RestfulApi } from "../restful";
-import { SSE } from "@/pages/chat/core/speical/ssemp";
+import { SSE } from "@/pages/home/chat/core/speical/ssemp";
 import type OpenAI from "openai";
 import { CommonPageResult } from "@/api/restful/types";
 import { AgentChatFile } from "./AgentChatFile";

+ 16 - 1
src/components/dialog/Popup.vue

@@ -29,6 +29,10 @@
           alignItems: 'flex-end',
           justifyContent: 'center',
         },
+        fill: {
+          alignItems: 'stretch',
+          justifyContent: 'stretch',
+        },
       }),
       top: inset[0] ? `${themeContext.resolveThemeSize(inset[0])}` : undefined,
       right: inset[1] ? `${themeContext.resolveThemeSize(inset[1])}` : undefined,
@@ -86,6 +90,10 @@
             height: '100%',
             width: themeContext.resolveThemeSize(props.size),
           },
+          fill: {
+            height: '100%',
+            width: '100%',
+          },
         }),
         zIndex: popupZIndex + 2,
         backgroundColor: themeContext.resolveThemeColor(backgroundColor),
@@ -132,8 +140,15 @@ import { getCurrentZIndex } from './CommonRoot';
 
 /**
  * Popup 的显示位置
+ * 
+ * * center: 居中弹出
+ * * top: 从上弹出
+ * * bottom: 从下弹出
+ * * left: 从左弹出
+ * * right: 从右弹出
+ * * fill: 充满屏幕
  */
-export type PopupPosition = 'center'|'top'|'bottom'|'left'|'right';
+export type PopupPosition = 'center'|'top'|'bottom'|'left'|'right'|'fill';
 /**
  * Popup 关闭按钮显示位置
  */

+ 93 - 41
src/components/feedback/BubbleBox.vue

@@ -13,7 +13,6 @@
       <template #show="{ classNames }">
         <view class="nana-bubble-box-popup-mask" @click="hide" />
         <FlexView
-          v-if="items?.length"
           position="absolute"
           :direction="direction"
           :backgroundColor="backgroundColor"
@@ -42,29 +41,31 @@
               borderLeftColor: 'transparent',
             }"
           />
-          <Touchable
-            v-for="item in items"
-            :key="item.text"
-            direction="row"
-            align-items="center"
-            :gap="10"
-            :padding="[5, 20]"
-            v-bind="itemProps"
-            @click="handleItemClick(item)"
-          >
-            <Icon
-              :name="item.icon"
-              :size="44"
-              :color="item.textColor || itemTextColor"
-              v-bind="{ ...itemIconProps, ...item.iconProps }"
-            />
-            <Text 
-              :wrap="false" 
-              v-bind="itemTextProps" 
-              :color="item.textColor || itemTextColor"
-              :text="item.text" 
-            />
-          </Touchable>
+          <slot name="content">
+            <Touchable
+              v-for="item in items"
+              :key="item.text"
+              direction="row"
+              align-items="center"
+              :gap="10"
+              :padding="[5, 20]"
+              v-bind="itemProps"
+              @click="handleItemClick(item)"
+            >
+              <Icon
+                :name="item.icon"
+                :size="44"
+                :color="item.textColor || itemTextColor"
+                v-bind="{ ...itemIconProps, ...item.iconProps }"
+              />
+              <Text 
+                :wrap="false" 
+                v-bind="itemTextProps" 
+                :color="item.textColor || itemTextColor"
+                :text="item.text" 
+              />
+            </Touchable>
+          </slot>
         </FlexView>
       </template>
     </SimpleTransition>
@@ -74,7 +75,7 @@
 <script setup lang="ts">
 import { computed, ref } from 'vue';
 import { propGetThemeVar, useTheme } from '../theme/ThemeDefine';
-import { selectObjectByType } from '../theme/ThemeTools';
+import { selectObjectByType, selectStyleType } from '../theme/ThemeTools';
 import type { FlexProps } from '../layout/FlexView.vue';
 import type { TextProps } from '../basic/Text.vue';
 import Icon, { type IconProps } from '../basic/Icon.vue';
@@ -97,6 +98,11 @@ export interface BubbleBoxProps {
    */
   position?: 'left' | 'right' | 'top' | 'bottom',
   /**
+   * 气泡在横轴上的对齐位置,默认居中
+   * @default center
+   */
+  crossPosition?: 'left' | 'center' | 'right',
+  /**
    * 触发点击事件模式
    * @default click
    */
@@ -212,6 +218,68 @@ function hide() {
   enterLock();
 }
 
+const innerStyle = computed(() => {
+  const horzLayout = selectStyleType(props.crossPosition, 'left', {
+    left: {
+      k: 'top',
+      y: '0%',
+      t: 'translateY(0%)',
+    },
+    center: {
+      k: 'top',
+      y: '50%',
+      t: 'translateY(-50%)',
+    },
+    right: {
+      k: 'bottom',
+      y: '0',
+      t: 'translateY(0%)',
+    }
+  });
+  const vertLayout = selectStyleType(props.crossPosition, 'left', {
+    left: {
+      k: 'left',
+      x: '0%',
+      t: 'translateX(0%)',
+    },
+    center: {
+      k: 'left',
+      x: '50%',
+      t: 'translateX(-50%)',
+    },
+    right: {
+      k: 'right',
+      x: '0%',
+      t: 'translateX(0%)',
+    }
+  });
+  return {
+    ...props.innerStyle,
+    ...selectStyleType(props.position, 'top', {
+      left: {
+        [horzLayout.k]: horzLayout.y,
+        right: '100%',
+        transform: horzLayout.t + ' translateX(0)',
+      },
+      right: {
+        [horzLayout.k]: horzLayout.y,
+        left: '100%',
+        transform: horzLayout.t + '',
+      },
+      top: {
+        top: '0%',
+        [vertLayout.k]: vertLayout.x,
+        transform: vertLayout.t + ' translateY(-100%)',
+      },
+      bottom: {
+        bottom: '0%',
+        [vertLayout.k]: vertLayout.x,
+        transform: vertLayout.t + ' translateY(100%)',
+      }
+    })
+  }
+})
+
 defineExpose<BubbleBoxExpose>({
   show,
   hide,
@@ -235,10 +303,6 @@ defineOptions({
     transition: opacity ease-in-out 0.2s;
 
     &.left {
-      top: 50%;
-      right: 100%;
-      transform: translateY(-50%) translateX(0);
-
       .nana-bubble-box-arrow {
         top: 50%;
         left: 100%;
@@ -246,10 +310,6 @@ defineOptions({
       }
     }
     &.right {
-      top: 50%;
-      left: 100%;
-      transform: translateY(-50%);
-
       .nana-bubble-box-arrow {
         top: 50%;
         left: 0;
@@ -257,10 +317,6 @@ defineOptions({
       }
     }
     &.top {
-      bottom: -100%;
-      left: 50%;
-      transform: translateX(-50%) translateY(-100%);
-
       .nana-bubble-box-arrow {
         top: 100%;
         left: 50%;
@@ -268,10 +324,6 @@ defineOptions({
       }
     }
     &.bottom {
-      top: 100%;
-      left: 50%;
-      transform: translateX(-50%);
-
       .nana-bubble-box-arrow {
         top: 0;
         left: 50%;

+ 20 - 0
src/pages.json

@@ -406,6 +406,26 @@
       ]
     },
     {
+      "root": "pages/home/chat",
+      "pages": [
+        {
+          "path": "index",
+          "style": {
+            "navigationBarTitleText": "AI助理",
+            "enablePullDownRefresh": false
+          }
+        },
+        {
+          "path": "dependent/post/publish",
+          "style": {
+            "navigationBarTitleText": "发贴图",
+            "navigationStyle": "custom",
+            "enablePullDownRefresh": false
+          }
+        }
+      ]
+    },
+    {
       "root": "pages/home/village/games",
       "pages": [
         {

+ 1 - 0
src/pages/chat/components/ChatFooter.vue

@@ -4,6 +4,7 @@
     <FlexRow
       position="relative" 
       border="1px solid #e0e0e0" 
+      backgroundColor="white" 
       :radius="30"
       :padding="20"
       :margin="20"

+ 5 - 4
src/pages/chat/components/ChatMessage.vue

@@ -21,7 +21,7 @@
         :class="{ 'expanded': contentExpanded }"
       >
         <!-- 工具图标 -->
-        <Icon v-if="message.role === 'tool'" class="prefix icon" name="ai-tools" />
+        <Icon v-if="message.role === 'tool'" class="prefix icon" name="ai-tools" :size="26" />
         <!-- 加载和失败状态 -->
         <ActivityIndicator v-if="message.state === 'loading'" class="prefix icon" />
         <Icon icon="warning" v-else-if="message.state === 'error'" class="prefix icon" />
@@ -79,7 +79,7 @@
         </div>
       </div>
 
-      <!-- 额外内容 -->
+      <!-- 额外内容
       <div 
         v-if="message.extra" 
         :class="{
@@ -97,7 +97,8 @@
           <ExpandButton v-model:expanded="extraExpanded" />
         </div>
       </div>
-        
+      -->
+
       <!-- 额外快捷操作 -->
       <div v-if="message.actions" class="actions-container">
         <Button v-for="action in message.actions" :key="action" @click="emit('action', action)">
@@ -329,7 +330,7 @@ function onLongpress() {
   flex-direction: row;
   align-items: flex-start;
   gap: 10rpx;
-  margin-bottom: 20rpx;
+  margin-bottom: 10rpx;
   user-select: text;
   -webkit-user-select: text;
 

src/pages/chat/components/ChatMessageContainer.vue → src/pages/home/chat/components/ChatMessageContainer.vue


src/pages/chat/components/Compoents/ExpandButton.vue → src/pages/home/chat/components/Compoents/ExpandButton.vue


src/pages/chat/components/Footer/ChatMulitSelectBar.vue → src/pages/home/chat/components/Footer/ChatMulitSelectBar.vue


src/pages/chat/components/Session/ChatSessionRenameDialog.vue → src/pages/home/chat/components/Session/ChatSessionRenameDialog.vue


src/pages/chat/components/Session/ChatSessionSidebar.vue → src/pages/home/chat/components/Session/ChatSessionSidebar.vue


src/pages/chat/components/Session/ChatSessionSidebarEmpty.vue → src/pages/home/chat/components/Session/ChatSessionSidebarEmpty.vue


src/pages/chat/components/Session/ChatSessionSidebarGroupHeader.vue → src/pages/home/chat/components/Session/ChatSessionSidebarGroupHeader.vue


src/pages/chat/components/Session/ChatSessionSidebarItem.vue → src/pages/home/chat/components/Session/ChatSessionSidebarItem.vue


src/pages/chat/components/Session/ChatSessionSidebarLoadMore.vue → src/pages/home/chat/components/Session/ChatSessionSidebarLoadMore.vue


src/pages/chat/components/zero-markdown-view/changelog.md → src/pages/home/chat/components/zero-markdown-view/changelog.md


src/pages/chat/components/zero-markdown-view/components/mp-html/highlight/config.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/highlight/config.js


src/pages/chat/components/zero-markdown-view/components/mp-html/highlight/index.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/highlight/index.js


src/pages/chat/components/zero-markdown-view/components/mp-html/highlight/prism.min.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/highlight/prism.min.js


src/pages/chat/components/zero-markdown-view/components/mp-html/latex/index.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/latex/index.js


src/pages/chat/components/zero-markdown-view/components/mp-html/latex/katex.min.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/latex/katex.min.js


src/pages/chat/components/zero-markdown-view/components/mp-html/markdown/index.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/markdown/index.js


src/pages/chat/components/zero-markdown-view/components/mp-html/markdown/marked.min.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/markdown/marked.min.js


src/pages/chat/components/zero-markdown-view/components/mp-html/mp-html.vue → src/pages/home/chat/components/zero-markdown-view/components/mp-html/mp-html.vue


src/pages/chat/components/zero-markdown-view/components/mp-html/node/node.vue → src/pages/home/chat/components/zero-markdown-view/components/mp-html/node/node.vue


src/pages/chat/components/zero-markdown-view/components/mp-html/parser.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/parser.js


src/pages/chat/components/zero-markdown-view/components/mp-html/style/index.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/style/index.js


src/pages/chat/components/zero-markdown-view/components/mp-html/style/parser.js → src/pages/home/chat/components/zero-markdown-view/components/mp-html/style/parser.js


src/pages/chat/components/zero-markdown-view/components/zero-markdown-view/zero-markdown-view.vue → src/pages/home/chat/components/zero-markdown-view/components/zero-markdown-view/zero-markdown-view.vue


src/pages/chat/components/zero-markdown-view/package.json → src/pages/home/chat/components/zero-markdown-view/package.json


src/pages/chat/components/zero-markdown-view/readme.md → src/pages/home/chat/components/zero-markdown-view/readme.md


src/pages/chat/composables/useChatExportSave.ts → src/pages/home/chat/composables/useChatExportSave.ts


src/pages/chat/composables/useChatHistoryItemsPager.ts → src/pages/home/chat/composables/useChatHistoryItemsPager.ts


src/pages/chat/composables/useChatRecordInput.ts → src/pages/home/chat/composables/useChatRecordInput.ts


src/pages/chat/composables/useChatSelection.ts → src/pages/home/chat/composables/useChatSelection.ts


src/pages/chat/composables/useChatSession.ts → src/pages/home/chat/composables/useChatSession.ts


src/pages/chat/core/Chat.ts → src/pages/home/chat/core/Chat.ts


src/pages/chat/core/Context.ts → src/pages/home/chat/core/Context.ts


src/pages/chat/core/Groups.ts → src/pages/home/chat/core/Groups.ts


src/pages/chat/core/Messages.ts → src/pages/home/chat/core/Messages.ts


src/pages/chat/core/StaticMessages.ts → src/pages/home/chat/core/StaticMessages.ts


+ 1 - 1
src/pages/chat/core/ToolCall.ts

@@ -28,7 +28,7 @@ export function useToolCalls(
       const name = call.function.name;
       const tool = toolsManager.toolRegistry.value.get(name);
       const newToolMessageId = LocalMessageIdPool.getNextId();
-      const toolMsg = messagesManager.addMessage(ChatMessageModel.createTool(name, `调用工具 ${name}`, newToolMessageId) as ChatMessageModel);;
+      const toolMsg = messagesManager.addMessage(ChatMessageModel.createTool(name, `AI自动工作`, newToolMessageId) as ChatMessageModel);;
       toolMsg.parentId = parentMessageId;
 
       try {

src/pages/chat/core/Tools.ts → src/pages/home/chat/core/Tools.ts


src/pages/chat/core/speical/ssemp.ts → src/pages/home/chat/core/speical/ssemp.ts


src/pages/chat/core/strategy/ContextSlideWindowStrategy.ts → src/pages/home/chat/core/strategy/ContextSlideWindowStrategy.ts


+ 12 - 12
src/pages/chat/dependent/post/agent.vue

@@ -1,5 +1,5 @@
 <template>
-  <FlexCol v-if="showSessionSidebar" position="relative" width="100%" height="100%">
+  <FlexCol v-if="showSessionSidebar" position="relative" width="100%">
     <NavBar 
       title="历史会话" 
       leftButton="close-bold" 
@@ -47,17 +47,17 @@
 
 <script setup lang="ts">  
 import { onMounted, ref, type Ref } from 'vue';
-import { useChatSession } from '../../composables/useChatSession';
-import { useChat, type ChatInterfaceManager } from '../../core/Chat';
-import { useChatHistoryItemsPager } from '../../composables/useChatHistoryItemsPager';
-import { useChatSelection } from '../../composables/useChatSelection';
-import { useAgentTools } from './composables/agentTools';
-import { ChatMessage as ChatMessageModel } from '../../model/Message';
-import { ChatGroups } from '../../core/Groups';
-import ChatFooter from '../../components/ChatFooter.vue';
-import ChatMessageContainer from '../../components/ChatMessageContainer.vue';
-import ChatSessionSidebar from '../../components/Session/ChatSessionSidebar.vue';
-import ChatMulitSelectBar from '../../components/Footer/ChatMulitSelectBar.vue';
+import { useChatSession } from '../../../composables/useChatSession';
+import { useChat, type ChatInterfaceManager } from '../../../core/Chat';
+import { useChatHistoryItemsPager } from '../../../composables/useChatHistoryItemsPager';
+import { useChatSelection } from '../../../composables/useChatSelection';
+import { useAgentTools } from '../composables/agentTools';
+import { ChatMessage as ChatMessageModel } from '../../../model/Message';
+import { ChatGroups } from '../../../core/Groups';
+import ChatFooter from '../../../components/ChatFooter.vue';
+import ChatMessageContainer from '../../../components/ChatMessageContainer.vue';
+import ChatSessionSidebar from '../../../components/Session/ChatSessionSidebar.vue';
+import ChatMulitSelectBar from '../../../components/Footer/ChatMulitSelectBar.vue';
 import NavBar from '@/components/nav/NavBar.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 

+ 75 - 0
src/pages/home/chat/dependent/post/components/tbutton.vue

@@ -0,0 +1,75 @@
+<template>
+  <BubbleBox 
+    ref="bubbleBoxRef"
+    trigger="none"
+    position="left"
+    backgroundColor="rgba(0,0,0,0.9)"
+    :innerProps="{
+      width: '400rpx',
+    }"
+  >
+    <template #content>
+      <FlexRow align="center" gap="gap.md">
+        <Text :text="currentTipContent" fontConfig="contentText" color="white" touchable @click="openAiWindow" />
+        <IconButton icon="close" @click="hideTip" />
+      </FlexRow>
+    </template>
+    <Button icon="https://xy.wenlvti.net/app_static/images/village/IconAi.png" @click="openAiWindow">
+      AI帮你写
+    </Button>
+  </BubbleBox>
+</template>
+
+<script setup lang="ts">
+import Button from '@/components/basic/Button.vue';
+import IconButton from '@/components/basic/IconButton.vue';
+import Text from '@/components/basic/Text.vue';
+import BubbleBox from '@/components/feedback/BubbleBox.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import { onMounted, ref } from 'vue';
+
+const props = defineProps<{
+  title: string;
+  content: string;
+  images: {
+    url: string;
+    localUrl: string;
+  }[];
+}>();
+
+const emit = defineEmits([ 'showAi' ]);
+
+/**
+ * 能助手提示:
+ * 0. 监听编辑器内容  
+ * 1. 当用户进入后,长时间 15s 没有内容变更,则触发 "不知道怎么写?来和我讨论灵感吧"
+ * 2. 当用户上传图片后,则触发 “让我来为你根据素材智能编写吧”
+ * 
+ * 3. 用户已写一段文字,防抖,一段时间内触发 
+ * “灵感枯竭?让我来为你拓展文化选题”
+ * "让我来为你润色文稿叙述更优雅动人"
+ * "让我来为你校对纠错精准修正文史细节"
+ * 
+ */
+
+const bubbleBoxRef = ref<InstanceType<typeof BubbleBox>>();
+const currentTipContent = ref('');
+
+function hideTip() {
+  bubbleBoxRef.value?.hide();
+}
+function showTip(message: string) {
+  currentTipContent.value = message;
+  bubbleBoxRef.value?.show();
+}
+function openAiWindow() {
+  emit('showAi', currentTipContent.value);
+  hideTip();
+}
+
+onMounted(() => {
+  setTimeout(() => {
+    showTip('不知道怎么写?让我来帮你吧');
+  }, 1000);
+})
+</script>

src/pages/chat/dependent/post/composables/agentTools.ts → src/pages/home/chat/dependent/post/composables/agentTools.ts


+ 28 - 17
src/pages/chat/dependent/post/publish.vue

@@ -1,5 +1,5 @@
 <template>
-  <CommonTopBanner title="AI帮你写微信贴图">
+  <CommonTopBanner title="贴图">
     <FlexCol position="relative" padding="space.lg" align="center">   
       <FlexCol position="absolute" :right="0" :top="0">
         <PrimaryButton
@@ -37,18 +37,33 @@
             multiline 
             placeholder="输入内容(可选)" 
             :maxLength="1000" 
-            rows="4" 
+            rows="10" 
             showWordLimit 
           />
+          <FlexRow justify="flex-end" align="center">
+            <Tbutton 
+              :title="title"
+              :content="content"
+              :images="images"
+              @showAi="showAgentPopup = true" 
+            />
+          </FlexRow>
         </BackgroundBox>
       </ProvideVar>
-      <Agent 
-        v-model:title="title"
-        v-model:content="content"
-        v-model:images="images"
-        @upload="uploader?.pick()"
-        @close="showAgentPopup = false" 
-      />
+      <Popup
+        v-model:show="showAgentPopup"
+        position="bottom"
+        :mask="false"
+        size="60vh"
+      >
+        <Agent 
+          v-model:title="title"
+          v-model:content="content"
+          v-model:images="images"
+          @upload="uploader?.pick()"
+          @close="showAgentPopup = false" 
+        />
+      </Popup>
     </FlexCol>
   </CommonTopBanner>
 </template>
@@ -66,18 +81,14 @@ import Field from '@/components/form/Field.vue';
 import Uploader, { type UploaderInstance } from '@/components/form/Uploader.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import ProvideVar from '@/components/theme/ProvideVar.vue';
-import Height from '@/components/layout/space/Height.vue';
-import ImageButton from '@/components/basic/ImageButton.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
-import Button from '@/components/basic/Button.vue';
-import XBarSpace from '@/components/layout/space/XBarSpace.vue';
-import IconButton from '@/components/basic/IconButton.vue';
 import Popup from '@/components/dialog/Popup.vue';
-import Agent from './agent.vue';
+import Agent from './components/agent.vue';
 import LightVillageApi, { PostMessage } from '@/api/light/LightVillageApi';
 import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
-import type { UploaderAction, UploaderItem } from '@/components/form/Uploader';
 import PrimaryButton from '@/common/components/PrimaryButton.vue';
+import Tbutton from './components/tbutton.vue';
+import type { UploaderAction, UploaderItem } from '@/components/form/Uploader';
 
 const { querys } = useLoadQuerys({
   tag: '',
@@ -210,7 +221,7 @@ onMounted(() => {
   setTimeout(() => {
     loadDraft();
     if (envVersion === 'develop') {
-      showAgentPopup.value = true;
+      //showAgentPopup.value = true;
     }
   }, 1000);
 });

+ 7 - 7
src/pages/chat/index.vue

@@ -53,17 +53,17 @@
 
 <script setup lang="ts">  
 import { onMounted, ref, type Ref } from 'vue';
-import { useChatSession } from '@/pages/chat/composables/useChatSession';
-import { useChat, type ChatInterfaceManager } from '@/pages/chat/core/Chat';
-import { useChatHistoryItemsPager } from '@/pages/chat/composables/useChatHistoryItemsPager';
-import { useChatSelection } from '@/pages/chat/composables/useChatSelection';
-import { ChatMessage as ChatMessageModel } from '@/pages/chat/model/Message';
+import { useChatSession } from './composables/useChatSession';
+import { useChat, type ChatInterfaceManager } from './core/Chat';
+import { useChatHistoryItemsPager } from './composables/useChatHistoryItemsPager';
+import { useChatSelection } from './composables/useChatSelection';
+import { ChatMessage as ChatMessageModel } from './model/Message';
 import ChatFooter from './components/ChatFooter.vue';
 import ChatMessageContainer from './components/ChatMessageContainer.vue';
 import NavBar from '@/components/nav/NavBar.vue';
-import ChatSessionSidebar from '@/pages/chat/components/Session/ChatSessionSidebar.vue';
+import ChatSessionSidebar from './components/Session/ChatSessionSidebar.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
-import ChatMulitSelectBar from '@/pages/chat/components/Footer/ChatMulitSelectBar.vue';
+import ChatMulitSelectBar from './components/Footer/ChatMulitSelectBar.vue';
 import IconButton from '@/components/basic/IconButton.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
 import CommonTopBanner from '@/common/components/CommonTopBanner.vue';

src/pages/chat/model/Message.ts → src/pages/home/chat/model/Message.ts


src/pages/chat/utils/ChatUtils.ts → src/pages/home/chat/utils/ChatUtils.ts


+ 6 - 2
src/pages/home/index.vue

@@ -411,8 +411,12 @@ async function loadInfo() {
   }
 
   //加载我的关注村庄
-  await villageStore.loadMyFollowVillages();
-  await villageStore.loadMyJoinedVillages();
+  try {
+    await villageStore.loadMyFollowVillages();
+    await villageStore.loadMyJoinedVillages();
+  } catch (error) {
+    console.error(error);
+  }
 
   if (villageStore.myFollowVillages.length > 0) {
     const currentVillage = villageStore.loadCurrentVillage();

+ 5 - 2
src/pages/home/village/components/VillageGallery.vue

@@ -45,7 +45,7 @@
 </template>
 
 <script setup lang="ts">
-import { computed } from 'vue';
+import { computed, watch } from 'vue';
 import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
 import { useAuthStore } from '@/store/auth';
 import FlexRow from '@/components/layout/FlexRow.vue';
@@ -66,7 +66,7 @@ const authStore = useAuthStore();
 const imageLoader = useSimpleDataLoader(async () => {
   return await GalleryApi.getAlbumList({
     villageId: props.villageId,
-    userId: authStore.userId,
+    //userId: authStore.userId,
     page: 1,
     pageSize: 18,
   });
@@ -87,6 +87,9 @@ const pagedImages = computed(() => {
 
 const pageCount = computed(() => pagedImages.value.length);
 
+watch(() => props.villageId, () => {
+  refresh();
+});
 
 function refresh() {
   imageLoader.reload();

+ 1 - 1
src/pages/home/village/dialogs/PostIndex.vue

@@ -51,7 +51,7 @@ const postList = [
     desc: '发布几张相片或一段文字,分享村里的点滴生活,风土人情...发布贴图还可赚取乡源果,快来为村社做贡献吧',
     onClick: () => {
       show.value = false;
-      navTo('/pages/home/village/post/publish');
+      navTo('/pages/home/chat/dependent/post/publish');
     },
   },
   {

+ 1 - 1
src/pages/home/village/gallery/index.vue

@@ -104,7 +104,7 @@ const authStore = useAuthStore();
 const galleryLoader = useSimplePageListLoader(30, async (page, pageSize) => {
   return await GalleryApi.getAlbumList({
     villageId: querys.value.villageId,
-    userId: authStore.userId,
+    //userId: authStore.userId,
     page,
     pageSize,
   });

+ 20 - 13
src/pages/home/village/index.vue

@@ -54,6 +54,18 @@
       </template>
       <Height :height="150" />
     </FlexCol>
+    <FlexCol v-else-if="topTab === 'village'" gap="gap.md">
+      <FlexCol v-if="!isLight" center :padding="[60,0]" gap="gap.md">
+        <Image src="https://xy.wenlvti.net/app_static/images/home/BadgeNew.png" :width="320" mode="widthFix" />
+        <Text text="您还未关注或者认领村社" fontConfig="primaryTitle" />
+        <Text text="欢迎关注或者认领村社,认领自己家乡参与建设,或四处看看" fontConfig="contentText" />
+        <Height :height="20" />
+        <FlexRow gap="gap.lg">
+          <FrameButton text="去认领村社" @click="handleGoSuscribe" primary />
+        </FlexRow>
+      </FlexCol>
+      <Height :height="150" />
+    </FlexCol>
     <Around 
       v-else 
       @selectVillage="onSelectVillage" 
@@ -119,6 +131,8 @@ const props = withDefaults(defineProps<{
 }>(), {
   showSwitch: false,
 });
+const emit = defineEmits(['goHome']);
+
 const isLight = computed(() => {
   return villageStore.currentVillage?.isLight ?? false;
 });
@@ -126,6 +140,9 @@ const isLight = computed(() => {
 function handleLight() {
   joinDialog.value?.show();
 }
+function handleGoSuscribe() {
+  emit('goHome');
+}
 
 function onSelectVillage(village: VillageListItem) {
   topTab.value = 'village';
@@ -134,13 +151,8 @@ function onSelectVillage(village: VillageListItem) {
 }
 
 watch(() => villageStore.currentVillage, (newVal) => {
-  if (!newVal) {
-    if (topTab.value === 'village')
-     topTab.value = 'around';
-  } else {
-    if (topTab.value === 'around')
-      topTab.value = 'village';
-  }
+  if (newVal && topTab.value === 'around')
+    topTab.value = 'village';
   tab.value = 'card';
 });
 
@@ -151,14 +163,9 @@ onMounted(async () => {
     });
   }
   if (isDevEnv) {
-    tab.value = 'tree';
+    //tab.value = 'tree';
   }
   await waitTimeOut(1000);
-  if (villageStore.currentVillage) {
-    topTab.value = 'village';
-  } else {
-    topTab.value = 'around';
-  }
 });
 
 defineExpose({

+ 9 - 5
src/pages/home/village/introd/card.vue

@@ -221,7 +221,7 @@
           @click="handleGoPublish()"
         >
           <Icon name="https://xy.wenlvti.net/app_static/images/village/IconLargeHistory.png" :size="30" />
-          <Text text="AI帮你写" fontConfig="contentText" />
+          <Text text="乡源AI帮你写" fontConfig="contentText" />
         </Touchable>
       </template>
     </HomeTitle>
@@ -283,8 +283,12 @@ const { getIsJoinedVillage } = useUserTools();
 const isJoined = ref(false);
 const villageInfoLoader = useSimpleDataLoader(async () => {
   const village = villageStore.currentVillage;  
-  if (village) 
-    isJoined.value = await getIsJoinedVillage(village.id);
+  try {
+    if (village) 
+      isJoined.value = await getIsJoinedVillage(village.id);
+  } catch {
+    isJoined.value = false;
+  }
   return {
     title: village?.name || '',
     desc: village?.desc || '',
@@ -367,11 +371,11 @@ function handleGoCollect(collectModuleId?: number, title?: string) {
 }
 function handleGoPublish() {
   requireLogin(async () => {
-    navTo('/pages/chat/dependent/post/publish', {
+    navTo('/pages/home/chat/dependent/post/publish', {
       tag: recommendTagName.value,
       villageId: villageStore.currentVillage?.id ?? undefined,
     });
-  }, '欢迎使用AI助手,登录后以便使用更多功能哦!');
+  }, '登录后以便发布文章使用更多功能哦!');
 }
 function handleGoGallery() {
   navTo('/pages/home/village/gallery/index', { 

+ 1 - 1
src/pages/index.vue

@@ -15,7 +15,7 @@
         align="left"
       />
       <HomeIndex v-show="tabIndex === 0" @goVillage="tabIndex = 1" @goDig="tabIndex = 2" />
-      <VillageIndex v-if="tabIndex === 1" showSwitch ref="villageIndex" />
+      <VillageIndex v-if="tabIndex === 1" showSwitch ref="villageIndex" @goHome="tabIndex=0" />
       <DigIndex v-else-if="tabIndex === 2" />
       <DiscoverIndex v-else-if="tabIndex === 3" @goVillage="tabIndex = 1" />
       <UserIndex v-else-if="tabIndex === 4" @goSubmit="tabIndex = 2" />