瀏覽代碼

按要求修改和优化

快乐的梦鱼 2 月之前
父節點
當前提交
bffd16bc98

+ 80 - 0
src/api/Utils.ts

@@ -12,4 +12,84 @@ export function transformSomeToArray(source: any) {
     }
   }
   return source;
+}
+
+export interface FindAPropCondition {
+  /**
+   * 匹配类型
+   * startWith: (需要name)匹配以指定字符串开头的属性值
+   * endWith: (需要name)匹配以指定字符串结尾的属性值
+   * contain: (需要name)匹配包含指定字符串的属性值
+   * match: (需要name)匹配完全等于指定字符串的属性值
+   * selectOnlyOne: 如果只有一个key,仅返回此key的属性值
+   * selectAtLestOne: 如果没有匹配到任何属性值,返回keys中第一个
+   */
+  type: 'startWith'|'endWith'|'contain'|'match'|'selectOnlyOne'|'selectAtLestOne';
+  name?: string;
+}
+export function findAProp(source: Record<string, any>, matchConditions: FindAPropCondition[]) {
+  // 获取source对象的所有键
+  const keys = Object.keys(source);
+
+  if (matchConditions.some(cond => cond.type === 'selectOnlyOne')) {
+    // 如果只有一个key,仅返回此key的属性值
+    if (keys.length === 1)
+      return source[keys[0]];
+  } 
+
+  // 遍历所有匹配条件
+  for (const condition of matchConditions) {
+    switch (condition.type) {
+      case 'startWith':
+        if (condition.name) {
+          // 查找以指定字符串开头的属性值
+          for (const key of keys) {
+            if (key.startsWith(condition.name)) {
+              return source[key];
+            }
+          }
+        }
+        break;
+      case 'endWith':
+        if (condition.name) {
+          // 查找以指定字符串开头的属性值
+          for (const key of keys) {
+            if (key.endsWith(condition.name)) {
+              return source[key];
+            }
+          }
+        }
+        break;
+      case 'match':
+        if (condition.name) {
+          // 查找完全等于指定字符串的属性值
+          for (const key of keys) {
+            if (key === condition.name) {
+              return source[key];
+            }
+          }
+        }
+        break;
+      case 'contain':
+        if (condition.name) {
+          // 查找包含指定字符串的属性值
+          for (const key of keys) {
+            if (key.includes(condition.name)) {
+              return source[key];
+            }
+          }
+        }
+        break;
+    }
+  }
+
+  if (matchConditions.some(cond => cond.type === 'selectAtLestOne')) {
+    // 如果没有匹配到任何属性值,返回keys中第一个
+    if (keys.length > 0) {
+      return source[keys[0]];
+    }
+  }
+  
+  // 如果所有条件都未匹配到,返回undefined
+  return undefined;
 }

+ 8 - 1
src/api/inhert/VillageApi.ts

@@ -1,6 +1,6 @@
 import { CONVERTER_ADD_DEFAULT, DataModel, transformArrayDataModel } from '@imengyu/js-request-transform';
 import { AppServerRequestModule } from '../RequestModules';
-import { transformSomeToArray } from '../Utils';
+import { findAProp, transformSomeToArray } from '../Utils';
 
 export class VillageListItem extends DataModel<VillageListItem> {
   constructor() {
@@ -146,6 +146,12 @@ export class VillageCatalogListItem extends DataModel<VillageCatalogListItem> {
     };
     this._afterSolveServer = () => {
       this.haschild = (this.childlist as any[]).length > 0;
+      if (this.otherParams) {
+        this.typeId = findAProp(this.otherParams, [
+          { type: 'endWith', name: 'type' },
+          { type: 'match', name: 'nature' },
+        ]);
+      }
     }
     this._convertKeyType = (key, direction) => {
       if (key.endsWith('At'))
@@ -168,6 +174,7 @@ export class VillageCatalogListItem extends DataModel<VillageCatalogListItem> {
   villageName = '';
   spacer = '';
   haschild = false;
+  typeId = -1;
 }
 
 export class VillageApi extends AppServerRequestModule<DataModel> {

+ 2 - 0
src/common/config/AppCofig.ts

@@ -12,6 +12,8 @@ export default {
     '/pages/user/login',
     '/pages/user/register',
     '/pages/user/reset-password',
+    '/pages/dig/sharereg/share-reg-link',
+    '/pages/dig/sharereg/share-reg-page',
   ],
   defaultImage: 'https://mncdn.wenlvti.net/app_static/minnan/EmptyImage.png',
 }

+ 7 - 2
src/components/basic/Icon.vue

@@ -39,7 +39,7 @@
   <!-- #endif -->
 
   <WrappedImage
-    v-else-if="iconData.type == 'image'"
+    v-else-if="iconData.type == 'image' && iconData.value"
     :innerStyle="style"
     :innerClass="innerClass"
     :src="iconData.value"
@@ -87,11 +87,16 @@ const iconData = computed(() => {
       value: props.icon,
       fontFamily: 'iconfont',
     } as IconItem
-  } else if (!data) {
+  } else if (!data && props.icon) {
     return {
       type: 'image',
       value: props.icon,
     } as IconItem
+  } else if (!data) {
+    return {
+      type: 'none',
+      value: '',
+    } as IconItem
   }
   return data;
 });

+ 1 - 1
src/components/basic/IconUtils.ts

@@ -1,7 +1,7 @@
 import DefaultIcons from "../data/DefaultIcon.json";
 
 export type IconItem = {
-  type: 'iconfont'|'image'|'svg',
+  type: 'iconfont'|'image'|'svg'|'none',
   value: string,
   rawSvg?: string,
   fontFamily?: string,

+ 2 - 5
src/components/basic/Image.vue

@@ -169,16 +169,13 @@ function measureImage() {
     .in(instance)
     .select('#' + id)
     .boundingClientRect((rect) => {
-      if (rect) {
+      if (rect)
         realWidth.value = (rect as UniApp.NodeInfo).width || 0;
-        console.log('realWidth', realWidth.value);
-        
-      }
     }).exec();
 }
 
 watch(() => props.src, (newVal, oldVal) => {
-  if (newVal) {
+  if (!newVal) {
     isErrorState.value = true;
     isLoadState.value = false;
   } else

File diff suppressed because it is too large
+ 3 - 1
src/components/data/DefaultIcon.json


+ 1 - 0
src/components/feedback/Result.vue

@@ -16,6 +16,7 @@
       :bold="themeVars.ResultDescriptionBold"
       align="center"
     >{{ description }}</Text>
+    <slot />
   </FlexCol>
 </template>
 

+ 1 - 0
src/components/form/Picker.vue

@@ -11,6 +11,7 @@
         width: themeContext.resolveThemeSize(pickerWidth),
         height: themeContext.resolveThemeSize(pickerHeight),
       }"
+      immediate-change
       @change="bindChange" 
     >
       <picker-view-column v-for="(column,c) in columns" :key="c">

+ 7 - 0
src/pages.json

@@ -141,6 +141,13 @@
         "navigationBarTitleText": "发现详情页",
         "enablePullDownRefresh": true
       }
+    },
+    {
+      "path": "pages/dig/sharereg/share-reg-page",
+      "style": {
+        "navigationBarTitleText": "注册成为志愿者",
+        "enablePullDownRefresh": false
+      }
     }
   ],
   "globalStyle": {

+ 35 - 6
src/pages/dig/admin.vue

@@ -7,9 +7,28 @@
         :innerStyle="{ width: '460rpx' }"
         @confirm="search"
       />
-      <Button type="primary" @click="newData">+ 新增</Button>
+      <NButton type="primary" @click="newData">+ 新增</NButton>
     </FlexRow>
     <FlexCol :gap="20" :margin="[20,0,0,0]">
+
+      <button class="remove-button-style" open-type="share">
+        <Touchable 
+          direction="column"
+          center 
+          :padding="20"
+          :height="300"
+          backgroundColor="background.primary"
+          @click=""
+        >
+          <FlexCol position="relative">
+            <Icon icon="smile-filling" color="primary" :size="156" />
+            <Icon icon="share" color="warning" :size="56" :innerStyle="{ position: 'absolute', bottom: 0, right: '-40rpx' }" />
+          </FlexCol>
+          <Height :height="20" />
+          <Text :fontSize="26" color="primary" text="分享给志愿者注册,加入志愿者队伍" />
+        </Touchable>
+      </button>
+
       <FlexRow 
         v-for="item in listLoader.list.value"
         :key="item.id" 
@@ -39,19 +58,23 @@
 </template>
 
 <script setup lang="ts">
-import VillageApi from '@/api/inhert/VillageApi';
-import SimplePageListLoader from '@/common/components/SimplePageListLoader.vue';
+import { ref } from 'vue';
+import { navTo } from '@/components/utils/PageAction';
 import { useLoadQuerys } from '@/common/composeabe/LoadQuerys';
 import { useSimplePageListLoader } from '@/common/composeabe/SimplePageListLoader';
-import Button from '@/components/basic/Button.vue';
+import VillageApi from '@/api/inhert/VillageApi';
+import SimplePageListLoader from '@/common/components/SimplePageListLoader.vue';
+import NButton from '@/components/basic/Button.vue';
+import Icon from '@/components/basic/Icon.vue';
 import Image from '@/components/basic/Image.vue';
 import Text from '@/components/basic/Text.vue';
 import Empty from '@/components/feedback/Empty.vue';
 import SearchBar from '@/components/form/SearchBar.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
-import { navTo } from '@/components/utils/PageAction';
-import { ref } from 'vue';
+import Touchable from '@/components/feedback/Touchable.vue';
+import Height from '@/components/layout/space/Height.vue';
+import { onShareAppMessage } from '@dcloudio/uni-app';
 
 const { querys } = useLoadQuerys({ 
   id: 0,  
@@ -98,4 +121,10 @@ function goDetail(id: number) {
 function search() {
   listLoader.loadData(undefined, true);
 }
+
+onShareAppMessage(() => ({
+  title: '邀请你成为村社挖掘志愿者',
+  desc: '分享给你的志愿者可以采编村社文化资源信息,加入志愿者队伍,为村社贡献力量。',
+  path: '/pages/dig/sharereg/share-reg-page',
+}))
 </script>

+ 1 - 1
src/pages/dig/components/CollectModuleList.vue

@@ -71,7 +71,7 @@ async function loadList() {
             catalogItem: item,
             goForm: collectModuleInternalName ? [ 
               collectModuleInternalName, 
-              -1, 
+              item.typeId ?? -1, 
               formDefine?.[2].typeName, 
               collectModuleInternalName === 'overview' ? 'common' : undefined,
               item.title 

+ 0 - 2
src/pages/dig/forms/common.vue

@@ -120,8 +120,6 @@ const { querys } = useLoadQuerys({
   formRef.value.initDefaultValuesToModel();
 
   console.log(formModel.value);
-  
-
   await waitTimeOut(1000);
   canSaveNow = true;
 });

+ 1 - 1
src/pages/dig/forms/forms.ts

@@ -133,7 +133,7 @@ const villageInfoForm : Record<string, GroupForm> = {
 export function getVillageInfoForm(subType: string, subId: number) {
   const group = villageInfoForm[subType];
   if (!group)
-    throw new Error('subType ' + subType + ' not found');
+    throw new Error('未定义的表单类型: ' + subType);
   if (subId === -1) 
     return mergeFormItems(group);
   return group[subId];

+ 0 - 7
src/pages/dig/sharereg/share-reg-link.vue

@@ -1,7 +0,0 @@
-<template>
-
-</template>
-
-<script setup lang="ts">
-
-</script>

+ 60 - 0
src/pages/dig/sharereg/share-reg-page.vue

@@ -1,7 +1,67 @@
 <template>
+  <CommonRoot>
+    <FlexCol :gap="20" :padding="30">
+      <Result 
+        v-if="authStore.isLogged" 
+        status="success"
+        title="您已经是志愿者"
+        desc="赶快去采编村社文化资源信息吧"
+      >
+        <Height :size="20" />
+        <Button type="primary" @click="navTo('/pages/index')">返回首页</Button>
+      </Result>
+      <FlexCol v-else center :height="400">
+        
+        <Icon icon="smile-filling" color="primary" :size="156" />
+        <Height :height="20" />
+        <Text :fontSize="26" color="primary" text="欢迎注册,加入志愿者队伍" />
+        <Height :size="40" />
 
+        <!-- #ifdef MP-WEIXIN -->
+        <Button type="primary" block text="微信登录" @click="loginWechat" />
+        <Height :size="20" />
+        <!-- #endif -->
+      </FlexCol>
+    </FlexCol>
+  </CommonRoot>
 </template>
 
 <script setup lang="ts">
+import Button from '@/components/basic/Button.vue';
+import Result from '@/components/feedback/Result.vue';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import Height from '@/components/layout/space/Height.vue';
+import Icon from '@/components/basic/Icon.vue';
+import Text from '@/components/basic/Text.vue';
+import CommonRoot from '@/components/dialog/CommonRoot.vue';
+import { navTo } from '@/components/utils/PageAction';
+import { useAuthStore } from '@/store/auth';
+import { closeToast, toast } from '@/components/dialog/CommonRoot';
+import { showError } from '@/common/composeabe/ErrorDisplay';
 
+const authStore = useAuthStore();
+
+function loginWechat() {
+  toast({
+    type: 'loading',  
+    content: '登录中...',
+  })
+
+  Promise.all([
+    uni.login({ provider: 'weixin' }),
+    uni.getUserProfile({ desc: '用于完善会员资料' }),
+  ])
+    .then((res) => {
+      authStore.loginWechart(res[0].code, res[1]).then(() => {
+        toast({
+          type: 'success',  
+          content: '登录成功',
+        });
+        //collectStore.loadCollectableModules();
+        //setTimeout(() => redirectToIndex(), 200);
+      }).catch(showError);
+    })
+    .catch(showError)
+    .finally(() => closeToast());
+}
 </script>