Преглед изворни кода

💊 修复采编编辑器卡死问题

快乐的梦鱼 пре 1 месец
родитељ
комит
466bfaa604

+ 13 - 10
src/common/components/form/RichTextEditor.vue

@@ -1,7 +1,7 @@
 <template>
   <FlexCol>
     <view class="richtext-preview-box" @click="() => !disabled && !readonly ? edit() : preview()">
-      <Parse v-if="modelValue" :content="modelValue" contentStyle="max-height:400px;word-break:break-all;overflow:hidden;" />
+      <Parse v-if="modelValue" :content="modelValue" contentStyle="max-height:300px;word-break:break-all;overflow:hidden;" />
       <Text v-else color="text.second">{{placeholder}}</Text>
       <view v-if="modelValue" class="richtext-preview-mask" :style="maskStyle" />
     </view>
@@ -40,7 +40,7 @@ export interface SpEditorProps {
       title: string,
       images: string[],
     }) => void,
-    storageInfo?: {
+    storageInfo?: () => {
       villageId: number,
       uploadPath: string,
     },
@@ -65,7 +65,7 @@ const theme = useTheme();
 
 let editorOpened = false;
 const maskStyle = computed(() => ({
-  height: theme.resolveThemeSize('RichTextEditorMaskHeight', 100),
+  height: theme.resolveThemeSize('RichTextEditorMaskHeight', 200),
   background: `linear-gradient(0deg, ${theme.resolveThemeColor(props.maskColor)} 0%, transparent 100%)`,
 }));
 
@@ -84,6 +84,7 @@ function preview() {
 async function edit() {
   editorOpened = true;
   const extraProps = props.extraProps.get();
+  const storageInfo = props.extraProps.storageInfo?.();
   const extraAiInfo = await props.getExtraAiInfo();
 
   console.log('加载编辑器', props.modelValue, extraProps, extraAiInfo);
@@ -99,8 +100,8 @@ async function edit() {
       maxLength: props.maxLength,
       enableAi: props.enableAi,
       extraAiInfo: extraAiInfo.join(','),
-      uploadSubpath: props.extraProps.storageInfo?.uploadPath,
-      villageId: props.extraProps.storageInfo?.villageId,
+      uploadSubpath: storageInfo?.uploadPath,
+      villageId: storageInfo?.villageId,
     }),
   })
 }
@@ -112,10 +113,12 @@ function doSaveContent() {
       const images = success.data.images;
       const title = success.data.title;
       emit('update:modelValue', content)
-      props.extraProps.update({
-        title: title,
-        images: images,
-      })
+      setTimeout(() => {
+        props.extraProps.update({
+          title: title,
+          images: images,
+        })
+      }, 1000);
     }
   })
 }
@@ -132,7 +135,7 @@ onPageShow(() => {
 .richtext-preview-box {
   position: relative;
   flex: 1;
-  min-height: 400rpx;
+  min-height: 300rpx;
   margin-bottom: 15rpx;
 
   .richtext-preview-mask {

+ 6 - 2
src/components/dynamic/DynamicForm.vue

@@ -68,11 +68,15 @@ const finalOptions = computed<IDynamicFormOptions>(() => ({
   ...defaultDynamicFormOptions,
   ...options.value,
 }));
+const formRules = computed(() => finalOptions.value.formRules);
+const nestObjectMargin = computed(() => finalOptions.value.nestObjectMargin);
+const suppressEmptyError = computed(() => finalOptions.value.suppressEmptyError);
 
 provide('rawModel', model);
 provide('globalParams', toRef(props, 'globalParams'));
-provide('finalOptions', finalOptions);
-
+provide('formRules', formRules);
+provide('nestObjectMargin', nestObjectMargin);
+provide('suppressEmptyError', suppressEmptyError);
 
 const formEditor = ref<FormInstance>();
 const widgetsRefMap = new Map<string, IDynamicFormWidgetRef>();

+ 8 - 9
src/components/dynamic/DynamicFormControl.vue

@@ -46,7 +46,8 @@
       ...item.formProps,
     }"
   >
-    <!-- <text>fullName: {{item.name}}</text> -->
+    <!-- <text>fullName: {{item.name}}</text>
+    <button @click="navTo('/pages/test/blank')">Test</button> -->
     <slot name="insertion">
       <template v-if="item.type === 'custom'">
         <slot name="formCeil" :data="data" />
@@ -287,17 +288,17 @@ import TimePickerField from '../form/TimePickerField.vue';
 import DatePickerField from '../form/DatePickerField.vue';
 import UploaderField, { type UploaderFieldProps } from '../form/UploaderField.vue';
 import RadioIdField from './wrappers/RadioIdField.vue';
-import type { RadioIdFieldProps } from './wrappers/RadioIdField';
-import Rate, { type RateProps } from '../form/Rate.vue';
-import ComponentConfigs from '@/common/components/dynamicf/ComponentConfigs';
 import ComponentRender from '@/common/components/dynamicf/ComponentRender.vue';
-import type { Rules } from 'async-validator';
 import PickerAddressField from './wrappers/PickerAddressField.vue';
 import Button from '../basic/Button.vue';
 import Alert from '../feedback/Alert.vue';
 import Image from '../basic/Image.vue';
 import SignatureField from '../form/SignatureField.vue';
 import CheckBoxTreeList, { type CheckBoxTreeListProps } from './wrappers/CheckBoxTreeList.vue';
+import type { RadioIdFieldProps } from './wrappers/RadioIdField';
+import Rate, { type RateProps } from '../form/Rate.vue';
+import ComponentConfigs from '@/common/components/dynamicf/ComponentConfigs';
+import type { Rules } from 'async-validator';
 import { useInjectFormContext, useInjectFormItemContext } from '../form/FormContext';
 
 export interface FormCeilProps {
@@ -369,11 +370,9 @@ const props = defineProps({
 });
 
 const emit = defineEmits([ 'update:model' ]);
-const formItemRef = ref();
-const finalOptions = inject<Ref<IDynamicFormOptions>>('finalOptions'); 
+const formRules = inject<Ref<Rules>>('formRules'); 
 const globalParams = inject<Ref<IDynamicFormObject>>('globalParams');
 const formRef = inject<IDynamicFormRef>('formRef');
-const formName = inject('formName', '');
 const context = useInjectFormItemContext();
 const formContext = useInjectFormContext();
 const disabled = computed(() => props.disabled || formContext?.disabled.value || context?.disabled.value);
@@ -390,7 +389,7 @@ function evaluateCallback(val: unknown|IDynamicFormItemCallback<unknown>) {
         parent: props.parent,
         form: formRef!,
         formGlobalParams: globalParams?.value || {},
-        formRules: (finalOptions?.value.formRules ?? {}) as Record<string, Rules>,
+        formRules: formRules?.value ?? {} as Record<string, Rules>,
         isFirst: props.isFirst,
         isLast: props.isLast,
       }

+ 6 - 6
src/components/dynamic/group/FormGroup.vue

@@ -1,5 +1,5 @@
 <template>
-  <div :class="[
+  <view :class="[
     'dynamic-form-group', 
     {
       'collapsed': collapsed,
@@ -7,17 +7,17 @@
       'plain': plain,
     }
   ]">
-    <h5 v-if="title" class="title" @click="collapsible ? collapsed = !collapsed : null">
-      <span class="title-text">{{ title }}</span>
+    <view v-if="title" class="title" @click="collapsible ? collapsed = !collapsed : null">
+      <text class="title-text">{{ title }}</text>
       <view class="title-right">
-        <span class="title-right-text" v-show="collapsed">点击展开更多</span>
+        <text class="title-right-text" v-show="collapsed">点击展开更多</text>
         <Icon :size="22" icon="arrow-down" v-if="collapsible" innerClass="collapsible-icon" />
       </view>
-    </h5>
+    </view>
     <Row v-if="!collapsed" :justify="(justify as any)" :gutter="gutter">
       <slot />
     </Row>
-  </div>
+  </view>
 </template>
 
 <script lang="ts" setup>

+ 26 - 12
src/components/dynamic/nest/DynamicFormItemContainer.vue

@@ -4,7 +4,7 @@
     v-if="isShow"
     :class="[
       'dynamic-form-item-wrapper',
-      finalOptions?.nestObjectMargin !== false && item.nestObjectMargin !== false ? 'nest-with-margin' : '',
+      nestObjectMargin !== false && item.nestObjectMargin !== false ? 'nest-with-margin' : '',
     ]"
     :data-dynamic-form-item="item.name"
     :data-dynamic-form-item-type="item.type"
@@ -18,7 +18,7 @@
       v-if="item.type === 'object'" 
       :model="model"
       :modelWithDefault="finalModel"
-      :suppressEmptyError="editmode || finalOptions?.suppressEmptyError || item.suppressEmptyError"
+      :suppressEmptyError="editmode || suppressEmptyError || item.suppressEmptyError"
       :name="name"
       checkType="object"
     >
@@ -53,9 +53,11 @@
         @update:model="(v: unknown) => (model as IDynamicFormObject)[child.name] = v"
         :disabled="disabled || evaluateCallback(item.disabled)"
       >
+        <!-- #ifndef MP -->
         <template #formCeil="values">
           <slot name="formCeil" :data="values.data" />
         </template>
+        <!-- #endif -->
       </DynamicFormItemContainer>
     </DynamicFormCheckEmpty>
     <!--对象组-->
@@ -63,7 +65,7 @@
       v-else-if="item.type === 'object-group'" 
       :model="model"
       :modelWithDefault="finalModel"
-      :suppressEmptyError="editmode || finalOptions?.suppressEmptyError || item.suppressEmptyError"
+      :suppressEmptyError="editmode || suppressEmptyError || item.suppressEmptyError"
       :name="name"
       checkType="object"
     >
@@ -86,9 +88,11 @@
             @update:model="(v: unknown) => (model as IDynamicFormObject)[child.name] = v"
             :disabled="disabled || evaluateCallback(item.disabled)"
           >
+            <!-- #ifndef MP -->
             <template #formCeil="values">
               <slot name="formCeil" :data="values.data" />
             </template>
+            <!-- #endif -->
           </DynamicFormItemContainer>
         </Row>
       </FormGroup>
@@ -113,9 +117,11 @@
           @update:model="(v: unknown) => (parentModel as IDynamicFormObject)[child.name] = v"
           :disabled="disabled || evaluateCallback(item.disabled)"
         >
+          <!-- #ifndef MP -->
           <template #formCeil="values">
             <slot name="formCeil" :data="values.data" />
           </template>
+          <!-- #endif -->
         </DynamicFormItemContainer>
       </Row>
     </FormGroup>
@@ -149,9 +155,11 @@
             @update:model="(v: unknown) => (parentModel as IDynamicFormObject)[child.name] = v"
             :disabled="disabled || evaluateCallback(item.disabled)"
           >
+            <!-- #ifndef MP -->
             <template #formCeil="values">
               <slot name="formCeil" :data="values.data" />
             </template>
+            <!-- #endif -->
           </DynamicFormItemContainer>
         </Row>
       </template>
@@ -161,7 +169,7 @@
       v-else-if="item.type === 'array-single'"
       :model="model"
       :modelWithDefault="finalModel"
-      :suppressEmptyError="editmode || finalOptions?.suppressEmptyError || item.suppressEmptyError"
+      :suppressEmptyError="editmode || suppressEmptyError || item.suppressEmptyError"
       :name="name"
       checkType="array"
     >
@@ -187,6 +195,7 @@
             :deleteCallback="item.deleteChildrenCallback"
             v-bind="(item.additionalProps as IDynamicFormObject)"
           >
+            <!-- #ifndef MP -->
             <template #addButton="props">
               <slot name="arrayButtonAdd" :onClick="props.onClick" />
             </template>
@@ -197,6 +206,7 @@
                 :onDownClick="props.onDownClick"
               />
             </template>
+            <!-- #endif -->
             <template #child="{ item, pitem, kname, model: child, onUpdateValue, isFirst, isLast }">
               <DynamicFormItemContainer
                 :item="item"
@@ -221,7 +231,7 @@
       v-else-if="item.type === 'array-object'"
       :model="model"
       :modelWithDefault="finalModel"
-      :suppressEmptyError="editmode || finalOptions?.suppressEmptyError || item.suppressEmptyError"
+      :suppressEmptyError="editmode || suppressEmptyError || item.suppressEmptyError"
       :name="name"
       checkType="array"
     >
@@ -249,6 +259,7 @@
             :deleteCallback="item.deleteChildrenCallback"
             v-bind="(item.additionalProps as IDynamicFormObject)"
           >
+            <!-- #ifndef MP -->
             <template #addButton="props">
               <slot name="arrayButtonAdd" :onClick="props.onClick" />
             </template>
@@ -259,6 +270,7 @@
                 :onDownClick="props.onDownClick"
               />
             </template>
+            <!-- #endif -->
             <template #child="{ item, pitem, kname, model: child, onUpdateValue, isFirst, isLast }">
               <DynamicFormItemContainer
                 :item="item"
@@ -273,9 +285,11 @@
                 :disabled="disabled || evaluateCallback(item.disabled)"
                 @update:model="(v: unknown) => onUpdateValue(v)"
               >
+                <!-- #ifndef MP -->
                 <template #formCeil="values">
                   <slot name="formCeil" :data="values.data" />
                 </template>
+                <!-- #endif -->
               </DynamicFormItemContainer>
             </template>
           </FormArrayGroup>
@@ -283,7 +297,7 @@
       </DynamicFormItemNormal>
     </DynamicFormCheckEmpty>
     <!--正常条目-->
-    <DynamicFormItemNormal
+     <DynamicFormItemNormal
       v-else
       :item="item"
       :parent="parent"
@@ -296,9 +310,11 @@
       :isLast="isLast"
       @update:model="(v: unknown) => $emit('update:model', v)"
     >
+      <!-- #ifndef MP -->
       <template #formCeil="values">
         <slot name="formCeil" :data="values.data" />
       </template>
+      <!-- #endif -->
     </DynamicFormItemNormal>
   </Col>
 </template>
@@ -356,11 +372,12 @@ defineSlots<{
 }>()
 
 const propsP = toRefs(props);
-const finalOptions = inject<Ref<IDynamicFormOptions>>('finalOptions'); 
+const formRules = inject<Ref<Rules>>('formRules'); 
+const nestObjectMargin = inject<Ref<boolean>>('nestObjectMargin'); 
+const suppressEmptyError = inject<Ref<boolean>>('suppressEmptyError'); 
 const globalParams = inject<Ref<IDynamicFormObject>>('globalParams');
 const formRef = inject<IDynamicFormRef>('formRef');
 const editmode = inject('editmode', false);
-const formName = inject('formName', '')
 
 //判断是否显示当前条目
 const isShow = computed(() => props.item.show === undefined || evaluateCallback(props.item.show));
@@ -389,16 +406,13 @@ function evaluateCallback<T>(val: T|IDynamicFormItemCallback<T>) {
         item: propsP.item.value,
         form: formRef!,
         formGlobalParams: globalParams?.value || {},
-        formRules: (finalOptions?.value.formRules ?? {}) as Record<string, Rules>,
+        formRules: formRules?.value ?? {} as Record<string, Rules>,
         isFirst: propsP.isFirst.value,
         isLast: propsP.isLast.value,
       }
     );
   return val as T;
 }
-
-provide<IEvaluateCallback>('evaluateCallback', evaluateCallback);
-
 defineOptions({
   name: 'DynamicFormItemContainer',
   options: {

+ 0 - 19
src/components/dynamic/nest/DynamicFormItemContainerFuckMp.vue

@@ -1,19 +0,0 @@
-<script setup lang="ts">
-import DynamicFormItemContainer, { type DynamicFormItemContainerProps } from './DynamicFormItemContainer.vue';
-
-defineProps<DynamicFormItemContainerProps>()
-defineEmits(['update:model'])
-defineOptions({
-  options: {
-    virtualHost: true,
-  }
-})
-</script>
-
-<template>
-  <DynamicFormItemContainer v-bind="($props as any)" @update:model="(val) => $emit('update:model', val)">
-    <template #formCeil="values">
-      <slot name="formCeil" :data="values.data" />
-    </template>
-  </DynamicFormItemContainer>
-</template>

+ 3 - 1
src/components/dynamic/nest/DynamicFormRoot.vue

@@ -35,6 +35,7 @@
           :onDownClick="props.onDownClick" 
         />
       </template>
+      <!-- #ifndef MP -->
       <template #formCeil="{ data }">
         <slot name="formCeil"
           :name="data.name"
@@ -49,13 +50,14 @@
           :additionalProps="data.additionalProps"
         />
       </template>
+      <!-- #endif -->
     </DynamicFormItemContainer>
     <slot name="endButton" />
   </template>
 </template>
 
 <script lang="ts" setup>
-import { computed, inject, type PropType } from 'vue';
+import { computed, type PropType } from 'vue';
 import DynamicFormItemContainer from './DynamicFormItemContainer.vue';
 import type { IDynamicFormObject, IDynamicFormOptions } from '..';
 import Alert from '@/components/feedback/Alert.vue';

+ 1 - 1
src/components/form/Field.vue

@@ -207,9 +207,9 @@ import IconButton from '../basic/IconButton.vue';
 import FlexCol from '../layout/FlexCol.vue';
 import FlexRow from '../layout/FlexRow.vue';
 import Touchable from '../feedback/Touchable.vue';
-import type { TextProps } from '../basic/Text.vue';
 import type { RuleItem } from 'async-validator';
 import Tag from '../display/Tag.vue';
+import type { TextProps } from '../basic/Text';
 
 
 export interface FieldInstance {

+ 6 - 9
src/components/layout/grid/Col.vue

@@ -1,19 +1,18 @@
 <template>
-  <FlexView
-    v-bind="props"
-    direction="column"
-    :innerStyle="{
+  <view
+    :style="{
+      display: 'flex',
+      flexDirection: 'column',
       position: 'relative',
       flexBasis: pec > 0 ? `${pec}%` : undefined,
       marginLeft: offset ? `${(offset / GRID_SIZE) * 100}%` : undefined,
       maxWidth: pec > 0 ? `${pec}%` : undefined,
       flexShrink: shrink ? 1 : 0,
       flexGrow: grow ? 1 : 0,
-      ...(innerStyle || {}),
     }"
   >
     <slot />
-  </FlexView>
+  </view>
 </template>
 
 <script setup lang="ts">
@@ -25,10 +24,8 @@
  * 此外,添加 offset 属性可以设置列的偏移宽度,计算方式与 span 相同。
  */
 import { computed, inject, toRefs } from 'vue';
-import type { FlexProps } from '../FlexView.vue';
-import FlexView from '../FlexView.vue';
 
-export interface ColProps extends FlexProps {
+export interface ColProps {
   /**
    * 列元素偏移距离
    */

+ 7 - 9
src/components/layout/grid/Row.vue

@@ -1,17 +1,15 @@
 <template>
-  <FlexView
-    v-bind="props"
-    direction="row"
-    :innerStyle="{
+  <view
+    :style="{
       display: inline ? 'flex-inline' : 'flex',
+      flexDirection: 'row',
       flex: flex,
       flexWrap: wrap ? 'wrap' : 'nowrap',
       gap: resolveThemeSize(gutter),
-      ...(innerStyle || {}),
     }"
   >
     <slot />
-  </FlexView>
+  </view>
 </template>
 
 <script setup lang="ts">
@@ -19,14 +17,14 @@
  * 24列栅格行组件。
  */
 import { useTheme } from '@/components/theme/ThemeDefine';
-import type { FlexProps } from '../FlexView.vue';
-import FlexView from '../FlexView.vue';
 
-export interface RowProps extends FlexProps {
+export interface RowProps {
   /**
    * 列元素之间的间距(单位为 px)
    */
   gutter?: number;
+
+  flex?: number;
   /**
    * 是否自动换行,默认 true
    */

+ 28 - 1
src/pages/dig/editor/preview.vue

@@ -2,12 +2,35 @@
   <FlexCol :padding="20">
     <Empty v-if="!content" image="search" description="空内容,请先编写内容后再预览" />
     <view v-else>
+      <swiper 
+        v-if="images.length > 0"
+        circular 
+        :indicator-dots="true"
+        :autoplay="true"
+        :interval="3000"
+        :duration="1000"
+        :style="{ height: '500rpx' }"
+      >
+        <swiper-item v-for="(item, key) in images" :key="key">
+          <view class="item">
+            <Image 
+              :src="item" 
+              width="100%"
+              :height="500"
+              mode="aspectFill" 
+              @click="onPreviewImage(key)"
+            />
+          </view>
+        </swiper-item>
+      </swiper>
       <Parse :content="content" />
     </view>
   </FlexCol>
 </template>
 
 <script setup lang="ts">
+import { useSwiperImagePreview } from '@/common/composeabe/SwiperImagePreview';
+import Image from '@/components/basic/Image.vue';
 import Parse from '@/components/display/parse/Parse.vue';
 import Empty from '@/components/feedback/Empty.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
@@ -15,12 +38,16 @@ import { onLoad } from '@dcloudio/uni-app';
 import { ref } from 'vue';
 
 const content = ref();
+const images = ref([]);
+
+const { onPreviewImage } = useSwiperImagePreview(() => images.value || []);
 
 onLoad(() => {
   uni.getStorage({
     key: 'editorContent',
     success: (success) => {
-      content.value = success.data;
+      content.value = success.data.content;
+      images.value = success.data.images;
     },
   })
 })

+ 49 - 19
src/pages/dig/forms/common.vue

@@ -2,7 +2,7 @@
   <CommonTopBanner :title="subTitle">
     <FlexCol padding="space.md">
       <LoadingPage v-if="loading" /> 
-      <FlexCol>
+      <FlexCol v-else>
         <Alert
           v-if="localSavedState"
           type="info"
@@ -10,23 +10,27 @@
         />
         <Height :height="20" />
         <BackgroundBox
+          v-if="show"
           backgroundImage="https://xy.wenlvti.net/app_static/images/village/BoxMid.png"
           :backgroundCutBorder="32"
           :backgroundCutBorderSize="36"
           :padding="24"
         >
-          <ProvideVar :vars="{
-            FieldBackgroundColor: 'transparent',
-          }">
-            <DynamicForm
-              ref="formRef"
-              :options="formDefine"
-              :model="formModel"
-              :globalParams="querys"
-              @storageOverflow="handleStorageOverflow"
-            />
-          </ProvideVar>
+          <scroll-view scroll-y style="height: 68vh">
+            <ProvideVar :vars="{
+              FieldBackgroundColor: 'transparent',
+            }">
+              <DynamicForm
+                ref="formRef"
+                :options="formDefine"
+                :model="formModel"
+                :globalParams="querys"
+                @storageOverflow="handleStorageOverflow"
+              />
+            </ProvideVar>
+          </scroll-view>
         </BackgroundBox>
+        <LoadingPage v-else loadingText="读取数据中..." /> 
         <Height :height="20" />
         <Button v-if="querys.isView" type="primary" :loading="loading" @click="backPrev(false, false)">返回</Button>
         <FlexCol v-else :gap="10" center>
@@ -37,7 +41,15 @@
             :loading="loading"
             @click="debounceSubmit.executeWithDelay()"
           />
-          <Button v-if="querys.id > 0 && !loading" type="text" textColor="danger" :loading="deleteing" @click="deleteInfo">删除</Button>
+          <Button v-if="querys.id > 0 && !loading" 
+            type="text" 
+            textColor="danger" 
+            icon="delete-filling"
+            :loading="deleteing" 
+            @click="deleteInfo"
+          >
+            删除
+          </Button>
         </FlexCol>
       </FlexCol>
       <XBarSpace />
@@ -68,11 +80,20 @@ import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
 import ProvideVar from '@/components/theme/ProvideVar.vue';
 import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
 import PrimaryButton from '@/common/components/PrimaryButton.vue';
+import { isTestEnv } from '@/common/config/AppCofig';
+import { onHide, onShow } from '@dcloudio/uni-app';
 
-const loading = ref(false);
+const loading = ref(true);
+const show = ref(true);
 const deleteing = ref(false);
 const subTitle = ref('');
 
+uni.onMemoryWarning((res) => {
+  uni.showModal({
+    content: 'onMemoryWarningReceive' + JSON.stringify(res), 
+  })
+});
+
 const formRef = ref<IDynamicFormRef>();
 const formModel = ref(new CommonInfoModel()) as Ref<CommonInfoModel>;
 const formDefine = ref<IDynamicFormOptions>({
@@ -104,8 +125,6 @@ const { querys } = useLoadQuerys({
     subTitle.value = querys.subTitle;
     uni.setNavigationBarTitle({  title: subTitle.value, })
   }
-  if (!formRef.value)
-    return;
 
   let formData = undefined;
   await waitTimeOut(800);
@@ -161,7 +180,7 @@ const { querys } = useLoadQuerys({
 
   await nextTick();
   await waitTimeOut(400);
-  formRef.value.initDefaultValuesToModel();
+  formRef.value?.initDefaultValuesToModel();
 
   console.log('提交数据', formModel.value);
 
@@ -233,7 +252,7 @@ async function deleteInfo() {
     cancelText: '取消',
     confirmText: '删除',
     confirmColor: 'danger',
-    confirmCountDown: 10,
+    confirmCountDown: 5,
     icon: 'delete-filling',
     iconColor: 'danger',
   });
@@ -282,15 +301,16 @@ async function loadLocalSave(formData: CommonInfoModel|undefined) {
   return formData;
 }
 function deleteLocalSave() {
+  console.log('删除暂存数据');
   const saveName = getSaveName();
   uni.removeStorageSync(saveName);
   localSavedState.value = false;
 }
 function saveLocalSave() {
+  console.log('保存暂存数据');
   const saveName = getSaveName();
   uni.setStorageSync(saveName, JSON.stringify(formModel.value.toServerSide()));
   localSavedState.value = true;
-  console.log('保存暂存数据');
 }
 
 async function handleStorageOverflow() {
@@ -312,4 +332,14 @@ watch(formModel, () => {
     return;
   saveLocalSaveDebounce.executeWithDelay();
 }, { deep: true })
+
+onHide(() => {
+  show.value = false;
+})
+onShow(() => {
+  setTimeout(() => {
+    show.value = true;
+  }, 400);
+})
+
 </script>

+ 4 - 4
src/pages/dig/forms/data/building.ts

@@ -123,10 +123,10 @@ export function villageInfoBuildingForm(title: string) : SingleForm  {
                   r.value.setValueByPath('images', extraProps.images);
                   r.value.setValueByPath('name', extraProps.title);
                 },
-                storageInfo: {
+                storageInfo: () => ({
                   villageId: r.value.getGlobalParams().villageId,
                   uploadPath: 'xiangyuan/building',
-                },
+                }),
               },
               getExtraAiInfo() {
                 return [ '用户正在栏目'+title+',编辑建筑 '+ r.value.getValueByPath('name') +' 建筑中的故事']
@@ -153,10 +153,10 @@ export function villageInfoBuildingForm(title: string) : SingleForm  {
                   r.value.setValueByPath('images', extraProps.images);
                   r.value.setValueByPath('name', extraProps.title);
                 },
-                storageInfo: {
+                storageInfo: () => ({
                   villageId: r.value.getGlobalParams().villageId,
                   uploadPath: 'xiangyuan/building',
-                },
+                }),
               },
               getExtraAiInfo() {
                 return [ '用户正在栏目'+title+',编辑建筑 '+ r.value.getValueByPath('name') +' 功能特点']

+ 2 - 2
src/pages/dig/forms/data/common.ts

@@ -59,10 +59,10 @@ export function villageCommonContent (ref: Ref<IDynamicFormRef>, options: {
                   ref.value.setValueByPath('images', extraProps.images);
                   ref.value.setValueByPath(options.titleKey || 'name', extraProps.title);
                 },
-                storageInfo: {
+                storageInfo: () => ({
                   villageId: ref.value.getGlobalParams().villageId,
                   uploadPath: options.uploadPath,
-                },
+                }),
               },
               getExtraAiInfo() {
                 return [ '用户正在栏目' + options.title + ',编辑 ' + ref.value.getValueByPath(options.titleKey || 'name') +' 的介绍内容']

+ 8 - 8
src/pages/dig/forms/data/element.ts

@@ -104,10 +104,10 @@ export const vilElementForm : SingleForm = [CommonInfoModel, (r) => ({
                 r.value.setValueByPath('images', extraProps.images);
                 r.value.setValueByPath('name', extraProps.title);
               },
-              storageInfo: {
+              storageInfo: () => ({
                 villageId: r.value.getGlobalParams().villageId,
                 uploadPath: 'xiangyuan/element',
-              },
+              }),
             },
             getExtraAiInfo() {
               return [ '用户正在栏目环境要素,编辑 '+ r.value.getValueByPath('name') +' 环境特点']
@@ -135,10 +135,10 @@ export const vilElementForm : SingleForm = [CommonInfoModel, (r) => ({
                 r.value.setValueByPath('images', extraProps.images);
                 r.value.setValueByPath('name', extraProps.title);
               },
-              storageInfo: {
+              storageInfo: () => ({
                 villageId: r.value.getGlobalParams().villageId,
                 uploadPath: 'xiangyuan/element',
-              },
+              }),
             },
             getExtraAiInfo() {
               return [ '用户正在栏目环境要素,编辑 '+ r.value.getValueByPath('name') +' 功能特点']
@@ -166,10 +166,10 @@ export const vilElementForm : SingleForm = [CommonInfoModel, (r) => ({
                 r.value.setValueByPath('images', extraProps.images);
                 r.value.setValueByPath('name', extraProps.title);
               },
-              storageInfo: {
+              storageInfo: () => ({
                 villageId: r.value.getGlobalParams().villageId,
                 uploadPath: 'xiangyuan/element',
-              },
+              }),
             },
             getExtraAiInfo() {
               return [ '用户正在栏目环境要素,编辑 '+ r.value.getValueByPath('name') +' 保存状况']
@@ -197,10 +197,10 @@ export const vilElementForm : SingleForm = [CommonInfoModel, (r) => ({
                 r.value.setValueByPath('images', extraProps.images);
                 r.value.setValueByPath('name', extraProps.title);
               },
-              storageInfo: {
+              storageInfo: () => ({
                 villageId: r.value.getGlobalParams().villageId,
                 uploadPath: 'xiangyuan/element',
-              },
+              }),
             },
             getExtraAiInfo() {
               return [ '用户正在栏目环境要素,编辑 '+ r.value.getValueByPath('name') +' 文化故事']

+ 10 - 10
src/pages/dig/forms/data/environment.ts

@@ -38,10 +38,10 @@ export const villageInfoEnvironmentForm : SingleForm= [CommonInfoModel, (r) => (
             r.value.setValueByPath('images', extraProps.images);
             r.value.setValueByPath('name', extraProps.title);
           },
-          storageInfo: {
+          storageInfo: () => ({
             villageId: r.value.getGlobalParams().villageId,
             uploadPath: 'xiangyuan/environment',
-          },
+          }),
         },
         getExtraAiInfo() {
           return [ '用户正在栏目环境格局,编辑 '+ r.value.getValueByPath('name') +' 自然环境特点']
@@ -72,10 +72,10 @@ export const villageInfoEnvironmentForm : SingleForm= [CommonInfoModel, (r) => (
             r.value.setValueByPath('images', extraProps.images);
             r.value.setValueByPath('name', extraProps.title);
           },
-          storageInfo: {
+          storageInfo: () => ({
             villageId: r.value.getGlobalParams().villageId,
             uploadPath: 'xiangyuan/environment',
-          },
+          }),
         },
         getExtraAiInfo() {
           return [ '用户正在栏目环境格局,编辑 '+ r.value.getValueByPath('name') +' 自然环境特点']
@@ -102,10 +102,10 @@ export const villageInfoEnvironmentForm : SingleForm= [CommonInfoModel, (r) => (
             r.value.setValueByPath('images', extraProps.images);
             r.value.setValueByPath('name', extraProps.title);
           },
-          storageInfo: {
+          storageInfo: () => ({
             villageId: r.value.getGlobalParams().villageId,
             uploadPath: 'xiangyuan/environment',
-          },
+          }),
         },
         getExtraAiInfo() {
           return [ '用户正在栏目环境格局,编辑 '+ r.value.getValueByPath('name') +' 自然环境格局']
@@ -132,10 +132,10 @@ export const villageInfoEnvironmentForm : SingleForm= [CommonInfoModel, (r) => (
             r.value.setValueByPath('images', extraProps.images);
             r.value.setValueByPath('name', extraProps.title);
           },
-          storageInfo: {
+          storageInfo: () => ({
             villageId: r.value.getGlobalParams().villageId,
             uploadPath: 'xiangyuan/environment',
-          },
+          }),
         },
         getExtraAiInfo() {
           return [ '用户正在栏目环境格局,编辑 '+ r.value.getValueByPath('name') +' 整体风貌特点']
@@ -162,10 +162,10 @@ export const villageInfoEnvironmentForm : SingleForm= [CommonInfoModel, (r) => (
             r.value.setValueByPath('images', extraProps.images);
             r.value.setValueByPath('name', extraProps.title);
           },
-          storageInfo: {
+          storageInfo: () => ({
             villageId: r.value.getGlobalParams().villageId,
             uploadPath: 'xiangyuan/environment',
-          },
+          }),
         },
         getExtraAiInfo() {
           return [ '用户正在栏目环境格局,编辑 '+ r.value.getValueByPath('name') +' 农业遗产信息']

+ 2 - 2
src/pages/dig/forms/data/food.ts

@@ -39,10 +39,10 @@ export function villageInfoFoodProductsForm(title: string) : SingleForm {
               r.value.setValueByPath('images', extraProps.images);
               r.value.setValueByPath('name', extraProps.title);
             },
-            storageInfo: {
+            storageInfo: () => ({
               villageId: r.value.getGlobalParams().villageId,
               uploadPath: 'xiangyuan/environment',
-            },
+            }),
           },
           getExtraAiInfo() {
             return [ '用户正在栏目' + title + ',编辑 '+ r.value.getValueByPath('name') +' 内容详情']

+ 4 - 4
src/pages/dig/forms/data/overview.ts

@@ -105,10 +105,10 @@ export const villageInfoOverviewForm : GroupForm = {
                   r.value.setValueByPath('images', extraProps.images);
                   r.value.setValueByPath('name', extraProps.title);
                 },
-                storageInfo: {
+                storageInfo: () => ({
                   villageId: r.value.getGlobalParams().villageId,
                   uploadPath: 'xiangyuan/environment',
-                },
+                }),
               },
               async getExtraAiInfo() {
                 const villageInfo = await LightVillageApi.getVillageDetails(r.value.getGlobalParams().villageId);
@@ -140,10 +140,10 @@ export const villageInfoOverviewForm : GroupForm = {
                   r.value.setValueByPath('images', extraProps.images);
                   r.value.setValueByPath('name', extraProps.title);
                 },
-                storageInfo: {
+                storageInfo: () => ({
                   villageId: r.value.getGlobalParams().villageId,
                   uploadPath: 'xiangyuan/environment',
-                },
+                }),
               },
               async getExtraAiInfo() {
                 const villageInfo = await LightVillageApi.getVillageDetails(r.value.getGlobalParams().villageId);

+ 4 - 4
src/pages/dig/forms/data/relic.ts

@@ -123,10 +123,10 @@ export const villageInfoRelicForm : SingleForm = [CommonInfoModel, (r) => ({
                 r.value.setValueByPath('images', extraProps.images);
                 r.value.setValueByPath('name', extraProps.title);
               },
-              storageInfo: {
+              storageInfo: () => ({
                 villageId: r.value.getGlobalParams().villageId,
                 uploadPath: 'xiangyuan/environment',
-              },
+              }),
             },
             getExtraAiInfo() {
               return [ '用户正在栏目非遗文物,编辑 '+ r.value.getValueByPath('name') +' 内容详情']
@@ -172,10 +172,10 @@ export const villageInfoRelicForm : SingleForm = [CommonInfoModel, (r) => ({
                 r.value.setValueByPath('images', extraProps.images);
                 r.value.setValueByPath('name', extraProps.title);
               },
-              storageInfo: {
+              storageInfo: () => ({
                 villageId: r.value.getGlobalParams().villageId,
                 uploadPath: 'xiangyuan/environment',
-              },
+              }),
             },
             getExtraAiInfo() {
               return [ '用户正在栏目非遗文物,编辑 '+ r.value.getValueByPath('name') +' 关于此文物的历史文化故事']

+ 1 - 0
src/pages/dig/forms/list-ordinary.vue

@@ -121,6 +121,7 @@ import Width from '@/components/layout/space/Width.vue';
 import PrimaryButton from '@/common/components/PrimaryButton.vue';
 import FrameButton from '@/common/components/FrameButton.vue';
 import IconButton from '@/components/basic/IconButton.vue';
+import { isTestEnv } from '@/common/config/AppCofig';
 
 const subTitle = ref('');
 const searchText = ref('');

+ 19 - 6
src/pages/index.vue

@@ -76,15 +76,28 @@ const { querys } = useLoadQuerys({
   openLogin: false,
   villageId: 0,
   userId: 0,
-}, (querys) => {
-  if (querys.openLogin) {
+  scense: '',
+}, (_querys) => {
+  if (_querys.openLogin) {
     navTo('/pages/user/login');
   }
-  if (querys.villageId) {
-    loadShareVillageInfo();
+  if (_querys.scense) {
+    //处理从二维码进入村社情况
+    const sp = _querys.scense.split(':');
+    switch (sp[0]) {
+      case 'invg':
+        if (sp.length > 1) {
+          querys.value.villageId = Number(sp[1]);
+        }
+        break;
+    }
   }
-  if (querys.userId) {
-    villageStore.setShareFromVillageUserId(querys.userId);
+  if (_querys.userId) {
+    villageStore.setShareFromVillageUserId(_querys.userId);
+  }
+  //普通分享进入村社情况
+  if (querys.value.villageId) {
+    loadShareVillageInfo();
   }
 });