Browse Source

📦 采集系统优化

快乐的梦鱼 4 days ago
parent
commit
82b3f323f8

+ 23 - 5
src/api/collect/AssessmentContent.ts

@@ -225,12 +225,22 @@ export class SelfAssessmentDetail extends DataModel<SelfAssessmentDetail> {
         },
       },
     };
+    this._blackList.toServer = [
+      'createtime',
+      'updatetime',
+      'deletetime',
+    ]
     this._convertKeyType = (key) => {
       if (key.endsWith('Text') || key.endsWith('_text')) {
         return { clientSide: 'string', serverSide: 'undefined' };
       }
       return undefined;
     };
+    this._beforeSolveClient = (data) => {
+      if (data.id == 0)
+        delete data.id;
+      return data;
+    }
   }
 
   id = 0 as number;
@@ -277,7 +287,17 @@ export class AgreementDetail extends DataModel<AgreementDetail> {
       activity: { clientSide: 'number', serverSide: 'number' },
       course: { clientSide: 'number', serverSide: 'number' },
       level: { clientSide: 'number', serverSide: 'number' },
+      updatetime: { clientSide: 'date', serverSide: 'undefined' },
     };
+    this._blackList.toServer = [
+      'createtime',
+      'updatetime',
+      'deletetime',
+    ]
+    this._beforeSolveClient = (data) => {
+      if (data.id == 0)
+        delete data.id;
+    }
   }
 
   id = 0 as number;
@@ -296,9 +316,7 @@ export class AgreementDetail extends DataModel<AgreementDetail> {
   ich = '' as string|null;
   partyASign = '' as string|null;
   partyBSign = '' as string|null;
-  createtime = '' as string;
-  updatetime = '' as string;
-  deletetime = '' as string|null;
+  updatetime = new Date();
 }
 
 export type IchCheckPaginated<T> = {
@@ -386,10 +404,10 @@ export class AssessmentContentApi extends AppServerRequestModule<DataModel> {
   }
 
   /**
-   * 保存传承协议(ShowDoc 文档 URL 为 saveAgreememt)
+   * 保存传承协议
    */
   async saveAgreement(dataModel: AgreementDetail) {
-    return this.post('/ich/check/saveAgreememt', '传承协议保存', dataModel.toServerSide());
+    return this.post('/ich/check/saveAgreement', '传承协议保存', dataModel.toServerSide());
   }
 
   /**

+ 3 - 0
src/common/components/upload/ImageUploadCo.ts

@@ -14,6 +14,9 @@ export function useImageSimpleUploadCo(additionData?: Record<string, any>) {
       }).catch((err) => {
         action.onError?.(err);
       })
+    return () => {
+      
+    }
   }
 }
 

+ 0 - 23
src/common/upload/ImageUploadCo.ts

@@ -1,23 +0,0 @@
-import CommonContent from "@/api/CommonContent";
-import type { AntUploadRequestOption, UploadCoInterface } from "@/components/dynamicf/UploadImageFormItem";
-
-export function useImageSimpleUploadCo(additionData?: Record<string, any>) : UploadCoInterface {
-
-  return {
-    uploadRequest: (requestOption: AntUploadRequestOption) => {
-      CommonContent.uploadSmallFile(requestOption.file, 'image', 'file', additionData)
-        .then((res) => {
-          requestOption.onSuccess?.({
-            url: res.fullurl,
-            key: res.fullurl,
-          }, null);
-        }).catch((err) => {
-          requestOption.onError?.(err, {});
-        })
-    },
-    getUrlByUploadResponse: (response: unknown) => {
-      return (response as any).url as string;
-    },
-  }
-}
-

+ 48 - 8
src/components/form/SignatureField.vue

@@ -15,10 +15,10 @@
         @cancel="popupShow = false"
         @confirm="onConfirm"
       />
-      <Signature ref="signatureRef" :innerStyle="{
-        width: '100%',
-        height: '400rpx',
-      }" />
+      <Signature 
+        ref="signatureRef" 
+        v-bind="props" 
+      />
     </FlexCol>
   </Popup> 
   <FlexCol width="100%" :gap="10">
@@ -29,7 +29,7 @@
 
 <script setup lang="ts">
 import { ref, toRef } from 'vue';
-import type { SignatureInstance } from '@/components/form/Signature.vue';
+import type { SignatureInstance, SignatureProps } from '@/components/form/Signature.vue';
 import { useFieldChildValueInjector } from './FormContext';
 import Signature from '@/components/form/Signature.vue';
 import FlexCol from '../layout/FlexCol.vue';
@@ -37,16 +37,36 @@ import Image from '../basic/Image.vue';
 import Popup from '../dialog/Popup.vue';
 import ActionSheetTitle, { type ActionSheetTitleProps } from '../dialog/ActionSheetTitle.vue';
 import Text from '../basic/Text.vue';
+import type { UploaderAction } from './Uploader';
 
-const props = withDefaults(defineProps<{
+export interface SignatureFieldProps extends Omit<SignatureProps, 'value'> {
   modelValue?: string | null;
+  /**
+   * 初始值
+   */
   initalValue?: string | null;
+  /**
+   * 标题
+   */
   title?: string;
   titleProps?: ActionSheetTitleProps;
+  /**
+   * 占位符
+   */
   placeholder?: string;
-}>(), {
+  /**
+   * 上传处理。允许用户在签名后自动上传图片。不提供则返回临时图片路径。
+   */
+  upload?: (item: UploaderAction) => (() => void);
+}
+
+const props = withDefaults(defineProps<SignatureFieldProps>(), {
   placeholder: '请签名',
   title: '签名',
+  innerStyle: () => ({
+    width: '100%',
+    height: '400rpx',
+  }),
 });
 const emit = defineEmits<{
   (e: 'update:modelValue', value: string | null): void;
@@ -73,7 +93,27 @@ function onConfirm() {
   if (signatureRef.value) {
     uni.showLoading();
     signatureRef.value.export().then((res) => {
-      updateValue(res);
+      // 如果上传处理,则上传图片
+      if (props.upload) {
+        props.upload({
+          item: {
+            filePath: res,
+            state: 'uploading',
+          },
+          onProgress: () => {},
+          onStart: () => {},
+          onError: (error) => {
+            uni.showToast({
+              title: '' + error,
+              icon: 'none',
+            })
+          },
+          onFinish: (result) => {
+            updateValue(result.uploadedUrl);
+          },
+        });
+      } else
+        updateValue(res);
       popupShow.value = false;
     }).catch((e) => {
       uni.showToast({

+ 1 - 1
src/components/loader/SimplePageContentLoader.vue

@@ -18,7 +18,7 @@
     </Empty>
   </view> 
   <view
-    v-if="showEmpty || loader?.status.value == 'nomore'"
+    v-if="showEmpty || loader?.status.value == 'nomore' || loader?.status.value == 'empty'"
     class="loader-view"
   >
     <Empty

+ 4 - 2
src/components/typography/B.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" bold>
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/H1.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" fontConfig="h1">
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/H2.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" fontConfig="h2">
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/H3.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" fontConfig="h3">
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/H4.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" fontConfig="h4">
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/H5.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" fontConfig="h5">
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/H6.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" fontConfig="h6">
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/I.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" italic>
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/P.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" fontConfig="p">
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/S.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" lineThrough>
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 4 - 2
src/components/typography/U.vue

@@ -1,11 +1,13 @@
 <template>
   <Text v-bind="props" underline>
-    <slot />
+    <slot v-if="$slots.default" />
   </Text>
 </template>
 
 <script setup lang="ts">
 import Text, { type TextProps } from '../basic/Text.vue';
 
-const props = defineProps<Partial<TextProps>>()
+const props = withDefaults(defineProps<Partial<TextProps>>(), {
+  wrap: true,
+});
 </script>

+ 7 - 7
src/pages.json

@@ -291,13 +291,6 @@
           }
         },
         {
-          "path": "assessment/index",
-          "style": {
-            "navigationBarTitleText": "自查评估",
-            "enablePullDownRefresh": false
-          }
-        },
-        {
           "path": "assessment/argeement-sign",
           "style": {
             "navigationBarTitleText": "传承协议签名",
@@ -324,6 +317,13 @@
             "navigationBarTitleText": "自查评估表列表",
             "enablePullDownRefresh": false
           }
+        },
+        {
+          "path": "assessment/evidence-list",
+          "style": {
+            "navigationBarTitleText": "佐证资料上传",
+            "enablePullDownRefresh": false
+          }
         }
       ]
     }

+ 1 - 1
src/pages/collect/assessment/argeement-sign-list.vue

@@ -1,6 +1,6 @@
 <template>
   <FlexCol padding="space.lg">
-    <SearchBar v-model="search" @search="loader.reload()" />
+    <SearchBar v-model="search" @search="loader.reload()" placeholder="输入关键词搜索"  />
     <SimplePageContentLoader :loader="loader">
       <template v-if="loader.isFinished.value">
         <FlexRow 

+ 15 - 1
src/pages/collect/assessment/argeement-sign.vue

@@ -143,6 +143,7 @@
                       <SignatureField
                         v-model="currentAgreement.partyBSign"
                         placeholder=""
+                        :upload="uploadAgreementSign"
                       />
                     </template>
                   </Field>
@@ -217,6 +218,7 @@ import Form, { type FormInstance } from '@/components/form/Form.vue';
 import type { Rules } from 'async-validator';
 import { useLoadQuerys } from '@/common/composeabe/LoadQuerys';
 import CommonRoot from '@/components/dialog/CommonRoot.vue';
+import { useImageSimpleUploadCo } from '@/common/components/upload/ImageUploadCo';
 
 const { querys } = useLoadQuerys({
   id: 0,
@@ -320,6 +322,17 @@ const signBlockStyle = {
   paddingTop: '8rpx',
 };
 
+async function loadBasicInfo() {
+  const basicInfo = await AssessmentContentApi.getInheritorBasic(authStore.userInfo?.id);
+  assertNotNull(currentAgreement.value, 'currentAgreement is null');
+  currentAgreement.value.partyB = basicInfo.name;
+  currentAgreement.value.mobile = basicInfo.mobile;
+  currentAgreement.value.idCard = basicInfo.idCard;
+  currentAgreement.value.ich = basicInfo.ichName;
+}
+
+const uploadAgreementSign = useImageSimpleUploadCo();
+
 const agreementYear = computed(() => currentAgreement.value?.year ?? new Date().getFullYear());
 
 const levelTitle = computed(() => {
@@ -348,7 +361,7 @@ const loader = useSimpleDataLoader(async () => {
     const detail = await AssessmentContentApi.getAgreementDetail(list.data[0].id);
     currentAgreement.value = detail;
     partyAStampDate.value = { year: '', month: '', day: '' };
-    partyBSignDate.value = { year: '', month: '', day: '' };
+    partyBSignDate.value = { year: detail.updatetime.getFullYear().toString(), month: (detail.updatetime.getMonth() + 1).toString(), day: detail.updatetime.getDate().toString() };
   } else {
     currentAgreement.value = null;
   }
@@ -370,6 +383,7 @@ function createAgreement() {
   partyAStampDate.value = { year: now.getFullYear().toString(), month: (now.getMonth() + 1).toString(), day: now.getDate().toString() };
   partyBSignDate.value = { year: now.getFullYear().toString(), month: (now.getMonth() + 1).toString(), day: now.getDate().toString() };
   currentAgreement.value = detail;
+  loadBasicInfo();
 }
 async function saveAgreement() {
   const detail = currentAgreement.value;

+ 4 - 1
src/pages/collect/assessment/evaluation-form.vue

@@ -100,6 +100,8 @@ import Stepper from '@/components/form/Stepper.vue';
 import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
 import type { RadioValueProps } from '@/components/dynamic/wrappers/RadioValue';
 import type { FieldProps } from '@/components/form/Field.vue';
+import type { SignatureFieldProps } from '@/components/form/SignatureField.vue';
+import { useImageSimpleUploadCo } from '@/common/components/upload/ImageUploadCo';
 
 const { querys } = useLoadQuerys({
   id: 0,
@@ -247,7 +249,8 @@ const formOptionsEnd = ref<IDynamicFormOptions>({
           type: 'sign',
           additionalProps: {
             placeholder: '请签名',
-          } as FieldProps,
+            upload: useImageSimpleUploadCo(),
+          } as SignatureFieldProps,
         }
       ],
     },

+ 1 - 1
src/pages/collect/assessment/evaluation-list.vue

@@ -1,6 +1,6 @@
 <template>
   <FlexCol padding="space.lg">
-    <SearchBar v-model="search" @search="loader.reload()" />
+    <SearchBar v-model="search" @search="loader.reload()" placeholder="输入关键词搜索"  />
     <SimplePageContentLoader :loader="loader">
       <template v-if="loader.isFinished.value">
         <Touchable 

+ 34 - 0
src/pages/collect/assessment/evidence-list.vue

@@ -0,0 +1,34 @@
+<template>
+  <FlexCol padding="space.lg">
+    <SearchBar v-model="search" @search="loader.reload()" placeholder="输入关键词搜索" />
+    <SimplePageContentLoader :loader="loader">
+      <template v-if="loader.isFinished.value">
+
+      </template>
+    </SimplePageContentLoader>
+    <XBarSpace />
+  </FlexCol>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue';
+import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
+import AssessmentContentApi from '@/api/collect/AssessmentContent';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import SimplePageContentLoader from '@/components/loader/SimplePageContentLoader.vue';
+import XBarSpace from '@/components/layout/space/XBarSpace.vue';
+import Text from '@/components/basic/Text.vue';
+import Icon from '@/components/basic/Icon.vue';
+import SearchBar from '@/components/form/SearchBar.vue';
+import Touchable from '@/components/feedback/Touchable.vue';
+import { navTo } from '@/components/utils/PageAction';
+
+const search = ref('');
+const loader = useSimplePageListLoader(10, async (page, pageSize) => {
+  
+  return {
+    list: [],
+    total: 0,
+  };
+});
+</script>

+ 0 - 15
src/pages/collect/assessment/index.vue

@@ -1,15 +0,0 @@
-<template>
-  <FlexCol padding="space.lg">
-    <CellGroup round> 
-      <Cell icon="https://mncdn.wenlvti.net/uploads/20250313/9fb29e8bdb66490034145c90f892773a.png" title="传承协议签名" showArrow touchable @click="navTo('argeement-sign')" />
-      <Cell icon="https://mncdn.wenlvti.net/uploads/20250313/66d4665b1da5075e60148312469b2630.png" title="自查评估表" showArrow touchable @click="navTo('evaluation-form')" />
-    </CellGroup>
-  </FlexCol>
-</template>
-
-<script setup lang="ts">
-import FlexCol from '@/components/layout/FlexCol.vue';
-import CellGroup from '@/components/basic/CellGroup.vue';
-import Cell from '@/components/basic/Cell.vue';
-import { navTo } from '@/components/utils/PageAction';
-</script>

+ 1 - 1
src/pages/collect/forms/form.vue

@@ -75,7 +75,7 @@
 <script setup lang="ts" generic="T extends DataModel, U extends DataModel">
 import { onMounted, ref, toRefs, type PropType, computed } from 'vue';
 import { useAuthStore } from '@/store/auth';
-import { useImageSimpleUploadCo } from '@/common/upload/ImageUploadCo';
+import { useImageSimpleUploadCo } from '@/common/components/upload/ImageUploadCo';
 import { alert, confirm, toast } from '@/components/utils/DialogAction';
 import { ArrowLeftOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
 import { formatError, waitTimeOut } from '@imengyu/imengyu-utils';

+ 3 - 1
src/pages/collect/inheritor.vue

@@ -32,7 +32,9 @@
         </FlexRow>
       </FlexRow>
       <CellGroup round>
-        <Cell icon="https://mncdn.wenlvti.net/uploads/20250313/9fb29e8bdb66490034145c90f892773a.png" title="自查评估" showArrow touchable @click="navTo('assessment/index')" />
+      <Cell icon="https://mncdn.wenlvti.net/uploads/20250313/9fb29e8bdb66490034145c90f892773a.png" title="传承协议签名" showArrow touchable @click="navTo('assessment/argeement-sign')" />
+      <Cell icon="https://mncdn.wenlvti.net/uploads/20250313/66d4665b1da5075e60148312469b2630.png" title="自查评估表" showArrow touchable @click="navTo('assessment/evaluation-form')" />
+      <Cell icon="https://mncdn.wenlvti.net/uploads/20250313/66d4665b1da5075e60148312469b2630.png" title="佐证资料上传" showArrow touchable @click="navTo('assessment/evidence-list')" />
       </CellGroup>
       <!-- <CellGroup round>
         <Cell icon="https://mncdn.wenlvti.net/uploads/20250313/1366973c061bf98594036e42c0344593.png" title="非遗项目资料采集" showArrow touchable @click="navTo('forms/ich')" />