Procházet zdrojové kódy

🎨 按要求优化AI帮写看图写作按钮入口

快乐的梦鱼 před 5 dny
rodič
revize
627395b054

+ 5 - 4
src/components/form/Uploader.vue

@@ -274,7 +274,7 @@ export interface UploaderInstance {
 const toast = ref<ToastInstance>();
 const dialog = ref<DialogAlertRoot>();
 
-const emit = defineEmits([ 'click', 'updateList' ]);
+const emit = defineEmits([ 'click', 'updateList', 'allUploaded' ]);
 const props = withDefaults(defineProps<UploaderProps>(), {
   disabled: false,
   maxUploadCount: 1,
@@ -567,14 +567,15 @@ function startUploadItem(item: UploaderItem) {
   });
 }
 //开始上传条目
-function startUploadMulitItem(items: UploaderItem[]) : Promise<void> {
+async function startUploadMulitItem(items: UploaderItem[]) : Promise<void> {
   if (props.uploadQueueMode === 'sequential')
-    return items.reduce((promiseChain, currentItem) =>
+    await items.reduce((promiseChain, currentItem) =>
       promiseChain.then(() => startUploadItem(currentItem)).catch(() => startUploadItem(currentItem)),
       Promise.resolve()
     );
   else
-    return Promise.all(items.map(item => startUploadItem(item))) as unknown as Promise<void>;
+    await Promise.all(items.map(item => startUploadItem(item))) as unknown as Promise<void>;
+  emit('allUploaded');
 }
 
 defineExpose<UploaderInstance>({

+ 12 - 0
src/components/utils/DialogAction.ts

@@ -66,10 +66,22 @@ function confirm(option: {
   })
 }
 
+function loading(title?: string) {
+  uni.showLoading({
+    title: title || '加载中',
+    mask: true,
+  });
+}
+function hideLoading() {
+  uni.hideLoading();
+}
+
 export {
   toast,
   alert,
   confirm, 
+  loading,
+  hideLoading,
 }
 
 export default {

+ 21 - 3
src/pages/home/chat/dependent/post/components/agent.vue

@@ -48,7 +48,7 @@
           <template #header>
             <scroll-view scroll-x>
               <FlexRow align="center" padding="padding.md" gap="gap.md">
-                <Button v-if="showImageWritingBtn" text="看图写作" @click="showImageWritingDialog = true" />
+                <Button text="看图写作" @click="imageWriting" />
                 <Button v-if="showContinueBtn" text="AI续写" @click="showContinueDialog = true" />
                 <Button v-if="showPolishBtn" text="AI润色" @click="showPolishDialog = true" />
                 <Button v-if="showCorrectBtn" text="AI订正" @click="confirmCorrect" />
@@ -189,6 +189,7 @@ const showSessionSidebar = ref(false);
 //快速操作控制
 //=============================================
 
+const lastClickedNeedImageWriting = ref(false);
 const showImageWritingDialog = ref(false);
 const imageWritingContent = ref('');
 const imageWritingLength = ref(300);
@@ -199,6 +200,21 @@ const imageWritingLengthOptions = [
   { text: '约500字', value: 500 },
 ];
 
+function imageWriting() {
+  if (props.images.length == 0) {
+    emit('upload');
+    lastClickedNeedImageWriting.value = true;
+    return;
+  }
+  lastClickedNeedImageWriting.value = false;
+  showImageWritingDialog.value = true;
+}
+function openImageWritingDialogIfLastClicked() {
+  if (props.images.length > 0 && lastClickedNeedImageWriting.value) {
+    lastClickedNeedImageWriting.value = false;
+    showImageWritingDialog.value = true;
+  }
+}
 function confirmImageWriting() {
   showImageWritingDialog.value = false;
   if (props.content.length > 0) {
@@ -263,12 +279,10 @@ const isAnySubDialogShow = computed(() =>
 );
 
 /**
-  - 看图写作 — 有上传图片时显示
   - AI续写 — 有图片或正文超 8 字时显示
   - AI润色 / AI总结 — 正文超 50 字时显示
   - AI订正 — 正文超 20 字时显示
  */
-const showImageWritingBtn = computed(() => props.images.length > 0);
 const showContinueBtn = computed(() => props.images.length > 0 || props.content.length > 8);
 const showPolishBtn = computed(() => props.content.length > 50);
 const showCorrectBtn = computed(() => props.content.length > 20);
@@ -473,6 +487,10 @@ const {
   isSelectMode,
 } = useChatSelection();
 
+defineExpose({
+  openImageWriting: () => imageWriting(),
+  openImageWritingDialogIfLastClicked,
+})
 onMounted(() => {
   interfaceManager.scrollToBottom?.();
 });

+ 12 - 1
src/pages/home/chat/dependent/post/publish.vue

@@ -36,8 +36,10 @@
             :maxUploadCount="9" 
             :upload="uploadImage"
             @updateList="onUpdateList"
+            @allUploaded="onAllUploaded"
           />
-          <FlexRow justify="flex-end" align="center">
+          <FlexRow justify="flex-end" align="center" gap="gap.md">
+            <Button text="AI看图写作" @click="openImageWriting" />
             <Tbutton 
               :title="title"
               :content="content"
@@ -56,6 +58,7 @@
         </FlexRow>
       </ProvideVar>
       <Agent 
+        ref="agentRef"
         v-model:showAgentPopup="showAgentPopup"
         v-model:title="title"
         v-model:content="content"
@@ -94,6 +97,7 @@ import Height from '@/components/layout/space/Height.vue';
 import type { UploaderAction, UploaderItem } from '@/components/form/Uploader';
 import { back, backAndCallOnPageBack } from '@/components/utils/PageAction';
 import LightVillageApi from '@/api/light/LightVillageApi';
+import Button from '@/components/basic/Button.vue';
 
 const { querys } = useLoadQuerys({
   tag: '',
@@ -121,6 +125,7 @@ const images = ref<{
   localUrl: string;
 }[]>([]);
 
+const agentRef = ref<InstanceType<typeof Agent>>();
 const uploader = ref<UploaderInstance>();
 
 const showAgentPopup = ref(false);
@@ -237,7 +242,13 @@ function publish() {
     },
   });
 }
+function openImageWriting() {
+  agentRef.value?.openImageWriting();
+}
 
+function onAllUploaded() {
+  agentRef.value?.openImageWritingDialogIfLastClicked();
+}
 function onUpdateList(list: UploaderItem[]) {
   images.value = list.map((item) => ({
     url: item.uploadedPath || '',

+ 17 - 19
src/pages/home/index.vue

@@ -206,7 +206,7 @@
 </template>
 
 <script setup lang="ts">
-import { onBeforeMount, onMounted, ref, watch } from 'vue';
+import { onMounted, ref, watch } from 'vue';
 import { useTheme } from '@/components/theme/ThemeDefine';
 import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
 import { useStorageVar } from '@/components/composeabe/StorageVar';
@@ -215,8 +215,10 @@ import { useGetCurrentLocation } from './composeabe/GetCurrentLocation';
 import { useAuthStore } from '@/store/auth';
 import { useRequireLogin } from '@/common/composeabe/RequireLogin';
 import { useUserTools } from '@/common/composeabe/UserTools';
-import { ArrayUtils, waitTimeOut } from '@imengyu/imengyu-utils';
-import { toast } from '@/components/utils/DialogAction';
+import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
+import { useGetNotice } from './village/composeabe/GetNotice';
+import { waitTimeOut } from '@imengyu/imengyu-utils';
+import { toast, loading, hideLoading } from '@/components/utils/DialogAction';
 import { navTo } from '@/components/utils/PageAction';
 import { injectAppConfiguration } from '@/api/system/useAppConfiguration';
 import Image from '@/components/basic/Image.vue';
@@ -231,30 +233,20 @@ import VillageUserRankList from './components/VillageUserRankList.vue';
 import Popup from '@/components/dialog/Popup.vue';
 import CitySelect from './components/CitySelect.vue';
 import VillageMyFollow from './components/VillageMyFollow.vue';
-import MapApi from '@/api/map/MapApi';
 import LightMap from './components/LightMap.vue';
 import NoticeBar from '@/components/display/NoticeBar.vue';
 import StatusBarSpace from '@/components/layout/space/StatusBarSpace.vue';
 import LightVillageApi, { VillageListItem } from '@/api/light/LightVillageApi';
-import type { RegionItem } from '@/api/map/RegionApi';
 import Width from '@/components/layout/space/Width.vue';
-import MasonryGrid from '@/components/layout/masonry/MasonryGrid.vue';
-import MasonryGridItem from '@/components/layout/masonry/MasonryGridItem.vue';
 import IndexCommonImageItem from '@/common/components/parts/IndexCommonImageItem.vue';
 import IntroClamTip from './village/dialogs/IntroClamTip.vue';
 import MemoryTimeOut from '@/components/composeabe/MemoryTimeOut';
-import Touchable from '@/components/feedback/Touchable.vue';
-import Icon from '@/components/basic/Icon.vue';
-import Text from '@/components/basic/Text.vue';
 import ImageSwiper from '@/common/components/parts/ImageSwiper.vue';
-import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
 import VillageInfoApi, { type CommonInfoModel } from '@/api/inhert/VillageInfoApi';
 import SimplePageListLoader from '@/components/loader/SimplePageListLoader.vue';
 import PostIndex from './village/dialogs/PostIndex.vue';
-import TreeApi from '@/api/light/TreeApi';
-import { SimpleTimer } from '@/components/utils/Timer';
-import { useGetNotice } from './village/composeabe/GetNotice';
 import FrameButton from '@/common/components/FrameButton.vue';
+import type { RegionItem } from '@/api/map/RegionApi';
 
 const emit = defineEmits(['goVillage','goDig']);
 const authStore = useAuthStore();
@@ -381,6 +373,8 @@ function handleSearch() {
 
 async function loadInfo() {
 
+  loading('载入数据中');
+
   //如果不是志愿者,则显示认领村庄提示
   const isVolunteer = await getIsVolunteer();
   if (!isVolunteer) {
@@ -402,11 +396,15 @@ async function loadInfo() {
     console.error(error);
   }
 
-  if (villageStore.myFollowVillages.length > 0) {
-    const currentVillage = villageStore.loadCurrentVillage();
-    const id = (villageStore.myFollowVillages.find(p => p.id === currentVillage) as VillageListItem || villageStore.myFollowVillages[0]).id;
-    const res = await LightVillageApi.getVillageDetails(id)
-    villageStore.setCurrentVillage(res);
+  try {
+    if (villageStore.myFollowVillages.length > 0) {
+      const currentVillage = villageStore.loadCurrentVillage();
+      const id = (villageStore.myFollowVillages.find(p => p.id === currentVillage) as VillageListItem || villageStore.myFollowVillages[0]).id;
+      const res = await LightVillageApi.getVillageDetails(id)
+      villageStore.setCurrentVillage(res);
+    }
+  } finally { 
+    hideLoading();
   }
 }