Преглед на файлове

🎨 优化整体字体大小

快乐的梦鱼 преди 1 месец
родител
ревизия
b5f9139544
променени са 79 файла, в които са добавени 542 реда и са изтрити 413 реда
  1. 3 16
      src/api/RequestModules.ts
  2. 2 0
      src/api/light/OfficialApi.ts
  3. 6 6
      src/common/components/FrameButton.vue
  4. 30 4
      src/common/components/form/RichTextEditor.vue
  5. 4 4
      src/common/components/parts/IndexCommonImageItem.vue
  6. 1 1
      src/common/components/parts/RoundTags.vue
  7. 3 2
      src/common/composeabe/UserTools.ts
  8. 14 8
      src/common/config/Theme.ts
  9. 1 1
      src/components/basic/Button.vue
  10. 3 3
      src/components/basic/Cell.vue
  11. 1 1
      src/components/basic/Image.vue
  12. 2 2
      src/components/dialog/ActionSheetItem.vue
  13. 2 2
      src/components/dialog/ActionSheetTitle.vue
  14. 2 2
      src/components/dialog/DialogButton.vue
  15. 2 2
      src/components/dialog/DialogInner.vue
  16. 1 1
      src/components/display/AvatarStack.vue
  17. 2 2
      src/components/display/Badge.vue
  18. 0 1
      src/components/display/Divider.vue
  19. 3 2
      src/components/display/Footer.vue
  20. 2 2
      src/components/display/Progress.vue
  21. 2 2
      src/components/display/Status.vue
  22. 2 2
      src/components/display/StepItem.vue
  23. 5 5
      src/components/display/Tag.vue
  24. 1 1
      src/components/display/TextEllipsis.vue
  25. 4 4
      src/components/display/block/TextBlock.vue
  26. 5 3
      src/components/dynamic/wrappers/PickerAddressField.vue
  27. 7 2
      src/components/dynamic/wrappers/PickerCityField.vue
  28. 1 1
      src/components/feedback/Empty.vue
  29. 2 2
      src/components/feedback/Result.vue
  30. 1 1
      src/components/feedback/ShareSheet.vue
  31. 5 5
      src/components/form/Calendar.vue
  32. 1 1
      src/components/form/CalendarItem.vue
  33. 1 1
      src/components/form/CheckBox.vue
  34. 6 6
      src/components/form/Field.vue
  35. 1 1
      src/components/form/NumberInputBox.vue
  36. 1 1
      src/components/form/Radio.vue
  37. 1 1
      src/components/form/Signature.vue
  38. 17 5
      src/components/form/UploaderListItem.vue
  39. 3 3
      src/components/keyboard/NumberKeyBoardInner.vue
  40. 2 2
      src/components/keyboard/PlateKeyBoardInner.vue
  41. 1 1
      src/components/keyboard/PlateKeyBoardInputBox.vue
  42. 3 2
      src/components/layout/grid/GridItem.vue
  43. 2 2
      src/components/list/IndexList.vue
  44. 3 3
      src/components/list/SimpleList.vue
  45. 2 2
      src/components/nav/IndexBar.vue
  46. 1 1
      src/components/nav/NavBar.vue
  47. 1 1
      src/components/nav/PaginationItem.vue
  48. 1 1
      src/components/nav/SegmentedControl.vue
  49. 1 1
      src/components/nav/SideBarItem.vue
  50. 1 1
      src/components/nav/TabBarItem.vue
  51. 5 3
      src/components/nav/Tabs.vue
  52. 18 16
      src/components/theme/Theme.ts
  53. 1 1
      src/components/theme/ThemeDefine.ts
  54. 2 1
      src/pages.json
  55. 2 3
      src/pages/article/details.vue
  56. 2 2
      src/pages/dig/components/TaskList.vue
  57. 11 10
      src/pages/dig/forms/common.vue
  58. 4 4
      src/pages/dig/forms/list-ordinary.vue
  59. 91 84
      src/pages/dig/forms/submits.vue
  60. 1 1
      src/pages/home/about/about.vue
  61. 1 1
      src/pages/home/about/contract.vue
  62. 1 0
      src/pages/home/chat/dependent/post/editor.vue
  63. 2 2
      src/pages/home/components/VillageRankList.vue
  64. 2 2
      src/pages/home/components/VillageUserRankList.vue
  65. 5 5
      src/pages/home/discover/details.vue
  66. 10 129
      src/pages/home/index.vue
  67. 44 0
      src/pages/home/recommend/CulturalTab.vue
  68. 58 0
      src/pages/home/recommend/GoodsTab.vue
  69. 35 0
      src/pages/home/recommend/RecommendTab.vue
  70. 46 0
      src/pages/home/recommend/TravelTab.vue
  71. 3 3
      src/pages/home/village/bless/my-orders.vue
  72. 1 1
      src/pages/home/village/index.vue
  73. 20 10
      src/pages/home/village/introd/card.vue
  74. 1 1
      src/pages/home/village/introd/tree.vue
  75. 2 2
      src/pages/home/village/rank/components/RankVillageItem.vue
  76. 2 2
      src/pages/home/village/rank/components/RankVolunteerItem.vue
  77. 1 1
      src/pages/home/village/task/index.vue
  78. 2 2
      src/pages/home/village/upgrade/my-orders.vue
  79. 1 1
      src/pages/home/village/volunteer/detail.vue

+ 3 - 16
src/api/RequestModules.ts

@@ -49,11 +49,11 @@ export class MengyuServerRequestModule<T extends DataModel> extends BaseAppServe
               apiInfo
             );
           }
-          if (!json.success)
+          if (json.success === false)
             throw new RequestApiError(
               'businessError',
               json.message,
-              json.code.toString(),
+              json.code,
               json.code,
               json,
               json,
@@ -133,7 +133,7 @@ export class TencentMengyuServerRequestModule<T extends DataModel> extends BaseA
             throw new RequestApiError(
               'businessError',
               json.message,
-              json.status.toString(),
+              json.status,
               json.status,
               json,
               json,
@@ -169,19 +169,6 @@ export class TencentMengyuServerRequestModule<T extends DataModel> extends BaseA
 }
 
 /**
- * 地图服务请求模块
- */
-export class AMapServerRequestModule<T extends DataModel> extends BaseAppServerRequestModule<T> {
-  constructor() {
-    super('https://restapi.amap.com');
-    this.config.requestInterceptor = (url, req) => {
-      url = appendGetUrlParams(url, 'key', ApiCofig.amapServerKey);
-      return { newUrl: url, newReq: req };
-    };
-  }
-}
-
-/**
  * 更新服务请求模块
  */
 export class UpdateServerRequestModule<T extends DataModel> extends BaseAppServerRequestModule<T> {

+ 2 - 0
src/api/light/OfficialApi.ts

@@ -371,6 +371,8 @@ export class OfficialApi extends AppServerRequestModule<DataModel> {
       sticker_url: stickerUrl,
     });
     const raw = res.requireData();
+    if (!raw.data || !raw.data.msg) 
+      throw new Error('搜索贴图详细信息失败');
     const msg = (raw.data as KeyValue).msg as KeyValue;
     return {
       title: msg.title as string,

+ 6 - 6
src/common/components/FrameButton.vue

@@ -60,16 +60,16 @@ const backgroundCutBorderSize = computed(() => {
 });
 const fontSize = computed(() => {
   switch (props.size) {
-    case 'large': return 36;
-    case 'midium': return 28;
-    case 'small': return 26;
+    case 'large': return 'fontSize.lg';
+    case 'midium': return 'fontSize.md';
+    case 'small': return 'fontSize.sm';
   }
 });
 const iconSize = computed(() => {
   switch (props.size) {
-    case 'large': return 32;
-    case 'midium': return 26;
-    case 'small': return 26;
+    case 'large': return 'fontSize.lg';
+    case 'midium': return 'fontSize.md';
+    case 'small': return 'fontSize.sm';
   }
 });
 const image =  computed(() => {

+ 30 - 4
src/common/components/form/RichTextEditor.vue

@@ -1,20 +1,24 @@
 <template>
   <FlexCol>
     <view class="richtext-preview-box" @click="() => !disabled && !readonly ? edit() : preview()">
-      <Parse v-if="modelValue" :content="modelValue" contentStyle="max-height:300px;word-break:break-all;overflow:hidden;" />
+      <Parse 
+        v-if="modelValue" 
+        :content="modelValue" 
+        :contentStyle="contentStyle"
+      />
       <Text v-else color="text.second">{{placeholder}}</Text>
       <view v-if="modelValue" class="richtext-preview-mask" :style="maskStyle" />
     </view>
-    <FlexRow :gap="20" justify="flex-end" align="center">
+    <FlexRow gap="gap.md" justify="flex-end" align="center">
       <Button v-if="!disabled" icon="browse" text="预览" size="small" @click="preview" />
       <Button v-if="!disabled && !readonly" icon="edit" text="编辑" size="small" @click="edit" type="primary" />
-      <Text v-if="maxLength > 0" :text="`${modelValue?.length || 0}/${maxLength} 字`" fontConfig="subText" textAlign="right" />
+      <Text v-if="maxLength > 0" :text="`${modelValue?.length || 0}/${maxLength}字`" fontConfig="subText" fontSize="fontSize.sm" textAlign="right" />
     </FlexRow>
   </FlexCol>
 </template>
 
 <script setup lang="ts">
-import { computed, type PropType } from 'vue';
+import { computed, inject } from 'vue';
 import { propGetThemeVar, useTheme } from '@/components/theme/ThemeDefine';
 import { onPageShow } from '@dcloudio/uni-app';
 import { navTo } from '@/components/utils/PageAction';
@@ -23,6 +27,7 @@ import Button from '@/components/basic/Button.vue';
 import Text from '@/components/basic/Text.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
+import type { IDynamicFormRef } from '@/components/dynamic';
 
 export interface SpEditorProps {
   modelValue: string;
@@ -47,6 +52,7 @@ export interface SpEditorProps {
   },
   getExtraAiInfo?: () => string[]|Promise<string[]>,
   maskColor: string;
+  contentFontConfig?: string;
 }
 
 const props = withDefaults(defineProps<SpEditorProps>(), {
@@ -57,12 +63,27 @@ const props = withDefaults(defineProps<SpEditorProps>(), {
     update: () => {},
     storageInfo: undefined,
   }),
+  contentFontConfig: 'content',
   maskColor: () => propGetThemeVar('RichTextEditorMaskColor', '#fcf4e4'),
 })
 const emit = defineEmits(['update:modelValue'])
 
 const theme = useTheme();
 
+const formRef = inject<IDynamicFormRef>('formRef', {} as IDynamicFormRef);
+
+const contentStyle = computed(() => {
+  const fontConfig = theme.getText(props.contentFontConfig);
+  return {
+    maxHeight: '260px',
+    wordBreak: 'break-all',
+    overflow: 'hidden',
+    fontSize: fontConfig.fontSize,
+    lineHeight: fontConfig.lineHeight,
+    color: theme.resolveThemeColor(fontConfig.color as string),
+  }
+});
+
 let editorOpened = false;
 const maskStyle = computed(() => ({
   height: theme.resolveThemeSize('RichTextEditorMaskHeight', 200),
@@ -70,6 +91,7 @@ const maskStyle = computed(() => ({
 }));
 
 function preview() {
+  formRef.emitMessage('doNav');
   const extraProps = props.extraProps.get();
   uni.setStorage({
     key: 'editorContent',
@@ -82,6 +104,7 @@ function preview() {
   })
 }
 async function edit() {
+  formRef.emitMessage('doNav');
   editorOpened = true;
   const extraProps = props.extraProps.get();
   const storageInfo = props.extraProps.storageInfo?.();
@@ -113,6 +136,9 @@ function doSaveContent() {
       const images = success.data.images;
       const title = success.data.title;
       emit('update:modelValue', content)
+
+      console.log('编辑器保存', content, images, title);
+
       setTimeout(() => {
         props.extraProps.update({
           title: title,

+ 4 - 4
src/common/components/parts/IndexCommonImageItem.vue

@@ -8,8 +8,8 @@
     :imageHeight="fixHeight ? 270 : undefined"
     :imageRadius="15"
     :defaultImage="defaultImage"
-    :titleProps="{ fontSize: 34, color: 'gray', lines: 2 }"
-    :descProps="{ fontSize: 28, color: 'gray', lines: 2 }"
+    :titleProps="{ fontSize: '1.05rem', color: 'text.title', lines: 2 }"
+    :descProps="{ fontSize: '0.95rem', color: 'text.content', lines: 2 }"
     backgroundColor="transparent"
     @click="$emit('click')"
   >
@@ -17,11 +17,11 @@
       <FlexRow v-if="userName || likes" justify="space-between" align="center" :padding="[10,0]" :margin="[10,0,0,0]">
         <FlexRow align="center" :gap="10">
           <Avatar :url="userAvatar || image" defaultAvatar="https://xy.wenlvti.net/app_static/images/mine/DefaultAvatar.png" :size="40" />
-          <Text :text="userName" :fontSize="24" :lines="1" color="gray" />
+          <Text :text="userName" fontSize="fontSize.sm" :lines="1" color="gray" />
         </FlexRow>
         <FlexRow align="center" :gap="10">
           <Icon icon="good" :color="isLike ? 'primary' : 'gray'" :size="30" />
-          <Text :text="likes" :fontSize="30" :color="isLike ? 'primary' : 'gray'" />
+          <Text :text="likes" fontSize="fontSize.sm" :color="isLike ? 'primary' : 'gray'" />
         </FlexRow>
       </FlexRow>
     </template>

+ 1 - 1
src/common/components/parts/RoundTags.vue

@@ -1,6 +1,6 @@
 <template>
   <scroll-view scroll-x>
-    <FlexRow gap="gap.xl">
+    <FlexRow gap="gap.2xl">
       <Touchable 
         v-for="(tag, k) in tags"
         :key="k" 

+ 3 - 2
src/common/composeabe/UserTools.ts

@@ -27,11 +27,12 @@ export function useUserTools() {
     if (!authStore.isLogged) {
       return false;
     }
-    if (!authStore.isAdmin) {
+    if (authStore.isAdmin) {
       return true;
     }
     try {
-      return villageStore.myJoinedVillages.find(v => v.id === villageId)?.type === 'staff';
+      const info = villageStore.myJoinedVillages.find(v => v.id === villageId)
+      return info?.type === 'staff';
     } catch (e) {
       return false;
     }

+ 14 - 8
src/common/config/Theme.ts

@@ -34,42 +34,48 @@ export function configAppTheme() {
     theme.textConfigs.primaryTitle = {
       color: 'text.title',
       fontFamily: 'SongtiSCBlack',
-      fontSize: '40rpx',
+      fontSize: '1.5rem',
       fontWeight: 'bold',
     };
     theme.textConfigs.lightTitle = {
       color: 'text.titleLight',
       fontFamily: 'SongtiSCBlack',
-      fontSize: '40rpx',
+      fontSize: '1.3rem',
+      fontWeight: 'bold',
+    };
+    theme.textConfigs.subTitle = {
+      color: 'text.title',
+      fontFamily: 'SongtiSCBlack',
+      fontSize: '1.3rem',
       fontWeight: 'bold',
     };
     theme.textConfigs.lightGoldTitle = {
       color: 'text.gold',
       fontFamily: 'SongtiSCBlack',
-      fontSize: '40rpx',
+      fontSize: '1.15rem',
       fontWeight: 'bold',
     };
     theme.textConfigs.importantTitle = {
       color: 'text.title',
-      fontSize: '36rpx',
+      fontSize: '1.1rem',
       fontWeight: 'bold',
     };
     theme.textConfigs.lightImportantTitle = {
       color: 'text.title',
-      fontSize: '34rpx',
+      fontSize: '1.1rem',
     };
     theme.textConfigs.contentSpeicalText = {
       color: 'text.content',
-      fontSize: '30rpx',
+      fontSize: '1rem',
       fontFamily: 'SongtiSCBlack',
     };
     theme.textConfigs.contentText = {
       color: 'text.content',
-      fontSize: '26rpx',
+      fontSize: '1rem',
     };
     theme.textConfigs.secondText = {
       color: 'text.second',
-      fontSize: '24rpx',
+      fontSize: '0.9rem',
     };
 
 

+ 1 - 1
src/components/basic/Button.vue

@@ -227,7 +227,7 @@ const props = withDefaults(defineProps<ButtonProp>(), {
 });
 
 const FonstSizes = computed(() => ({
-  mini: themeContext.resolveThemeSize('ButtonMiniFonstSize', 'fontSize.xs'),
+  mini: themeContext.resolveThemeSize('ButtonMiniFonstSize', 'fontSize.sm'),
   small: themeContext.resolveThemeSize('ButtonSmallFonstSize', 'fontSize.sm'),
   medium: themeContext.resolveThemeSize('ButtonMediumFonstSize', 'fontSize.md'),
   large: themeContext.resolveThemeSize('ButtonLargeFonstSize', 'fontSize.lg'),

+ 3 - 3
src/components/basic/Cell.vue

@@ -236,9 +236,9 @@ provide<CellContext>(CellContextKey, {
 
 const themeVars = computed(() => theme.resolveThemeSizes({
   CellBorderWidth: 1,
-  CellFontSizeLarge: 36,
-  CellFontSizeMedium: 32,
-  CellFontSizeSmall: 28,
+  CellFontSizeLarge: 'fontSize.lg',
+  CellFontSizeMedium: 'fontSize.md',
+  CellFontSizeSmall: 'fontSize.sm',
   CellIconSize: 30,
   CellIconWidth: 40,
   CellHeightLarge: 100,

+ 1 - 1
src/components/basic/Image.vue

@@ -30,7 +30,7 @@
       />
       <view v-if="showFailed && isErrorState && !failedImage" class="inner-view error">
         <Icon icon="warning" color="text.second" :size="32" noError />
-        <Text v-if="realWidth > 50" color="text.second" :text="src ? '加载失败' : '暂无图片'" :fontSize="22" />
+        <Text v-if="realWidth > 50" color="text.second" :text="src ? '加载失败' : '暂无图片'" fontSize="fontSize.md" />
       </view>
       <view v-if="showLoading && isLoadState" class="inner-view loading">
         <ActivityIndicator

+ 2 - 2
src/components/dialog/ActionSheetItem.vue

@@ -41,11 +41,11 @@ const themeStyles = themeContext.useThemeStyles({
     backgroundColor: DynamicColor('ActionSheetItemBackgroundColor', 'white'),
   },
   itemTitle: {
-    fontSize: DynamicSize('ActionSheetItemTitleFontSize', 32),
+    fontSize: DynamicSize('ActionSheetItemTitleFontSize', 'fontSize.lg'),
     color: DynamicColor('ActionSheetItemTitleColor', 'text.content'),
   },
   itemSubTitle: {
-    fontSize: DynamicSize('ActionSheetItemSubTitleFontSize', 26),
+    fontSize: DynamicSize('ActionSheetItemSubTitleFontSize', 'fontSize.md'),
     color: DynamicColor('ActionSheetItemSubTitleColor', 'text.second'),
     marginTop: DynamicSize('ActionSheetItemSubTitleMarginTop', 4),
   },

+ 2 - 2
src/components/dialog/ActionSheetTitle.vue

@@ -79,11 +79,11 @@ const themeStyles = themeContext.useThemeStyles({
     paddingBottom: DynamicSize('ActionSheetTitleTextPaddingVertical', 10),
   },
   title: {
-    fontSize: DynamicSize('ActionSheetTitleTextFontSize', 32),
+    fontSize: DynamicSize('ActionSheetTitleTextFontSize', 'fontSize.lg'),
     color: DynamicColor('ActionSheetTitleTextColor', 'text.content'),
   },
   description: {
-    fontSize: DynamicSize('ActionSheetTitleDescriptionFontSize', 26),
+    fontSize: DynamicSize('ActionSheetTitleDescriptionFontSize', 'fontSize.md'),
     color: DynamicColor('ActionSheetTitleDescriptionColor', 'text.second'),
   },
 });

+ 2 - 2
src/components/dialog/DialogButton.vue

@@ -12,7 +12,7 @@
     <ActivityIndicator 
       v-if="loading"
       :color="themeContext.resolveThemeColor(buttonColor)" 
-      :size="themeContext.resolveThemeSize('DialogButtonTextFontSize', 30)"
+      :size="themeContext.resolveThemeSize('DialogButtonTextFontSize', 'fontSize.md')"
     />
     <text 
       v-else 
@@ -87,7 +87,7 @@ const themeStyles = themeContext.useThemeStyles({
     borderBottomColor: DynamicColor('DialogButtonBorderBottomColor', 'border.cell'),
   },
   buttonText: {
-    fontSize: DynamicSize('DialogButtonTextFontSize', 30),
+    fontSize: DynamicSize('DialogButtonTextFontSize', 'fontSize.md'),
     fontWeight: DynamicSize('DialogButtonTextFontWeight', 'bold'),
   },
 });

+ 2 - 2
src/components/dialog/DialogInner.vue

@@ -99,7 +99,7 @@ const themeStyles = themeContext.useThemeStyles({
     alignItems: 'center',
   },
   title: {
-    fontSize: DynamicSize('DialogTitleFontSize', 36),
+    fontSize: DynamicSize('DialogTitleFontSize', 'fontSize.lg'),
     color: DynamicColor('DialogTitleColor', 'text.content'),
     fontWeight: DynamicSize('DialogTitleFontWeight', 'bold'),
     textAlign: 'center',
@@ -108,7 +108,7 @@ const themeStyles = themeContext.useThemeStyles({
   contentText: {
     width: '100%',
     display: 'block',
-    fontSize: DynamicSize('DialogContentTextFontSize', 28),
+    fontSize: DynamicSize('DialogContentTextFontSize', 'fontSize.md'),
     color: DynamicColor('DialogContentTextColor', 'text.second'),
     textAlign: DynamicVar('DialogContentTextAlign', 'center'),
   },

+ 1 - 1
src/components/display/AvatarStack.vue

@@ -150,7 +150,7 @@ const themeStyles = themeContext.useThemeStyles({
     display: 'flex',
   },
   overflowCountText: {
-    fontSize: DynamicVar('AvatarStackOverflowCountTextFontSize', 12),
+    fontSize: DynamicVar('AvatarStackOverflowCountTextFontSize', 'fontSize.xs'),
     color: DynamicColor('AvatarStackOverflowCountTextColor', 'text.content'),
   },
 })

+ 2 - 2
src/components/display/Badge.vue

@@ -135,7 +135,7 @@ const props = withDefaults(defineProps<BadgeProps>(), {
   offset: () => propGetThemeVar('BadgeOffset', { x: 0, y: 0 }),
   badgeSize: () => propGetThemeVar('BadgeSize', 18),
   radius: () => propGetThemeVar('BadgeRadius', 20),
-  fontSize: () => propGetThemeVar('BadgeFontSize', 24),
+  fontSize: () => propGetThemeVar('BadgeFontSize', 'fontSize.md') as any,
   paddingVertical: () => propGetThemeVar('BadgePaddingVertical', 4),
   paddingHorizontal: () => propGetThemeVar('BadgePaddingHorizontal', 8),
   hiddenIfZero: true,
@@ -185,7 +185,7 @@ const currentStyle = computed(() => {
 });
 
 const textStyle = computed(() => {
-  const fontSize = themeContext.resolveThemeSize(props.fontSize, 24);
+  const fontSize = themeContext.resolveThemeSize(props.fontSize, 'fontSize.md');
   return {
     fontSize: fontSize,
     color: themeContext.resolveThemeColor('BadgeTextColor', 'white'),

+ 0 - 1
src/components/display/Divider.vue

@@ -126,7 +126,6 @@ const dotStyle = computed(() => {
 })
 const lineStyle = computed(() => {
   return {
-    fontSize: '22rpx',
     color: theme.resolveThemeColor(props.color),
     width: theme.resolveThemeSize(props.type === 'horizontal' ? '100%' : props.size),
     height: theme.resolveThemeSize(props.type === 'vertical' ? '100%' : props.size),

+ 3 - 2
src/components/display/Footer.vue

@@ -32,7 +32,8 @@
 </template>
 
 <script setup lang="ts">
-import Text, { type TextProps } from '../basic/Text.vue';
+import type { TextProps } from '../basic/Text';
+import Text from '../basic/Text.vue';
 import FlexCol from '../layout/FlexCol.vue';
 import FlexRow from '../layout/FlexRow.vue';
 import A, { type AProps } from '../typography/A.vue';
@@ -43,7 +44,7 @@ export interface FooterProps {
   padding?: number|number[],
   text?: string,
   textProps?: TextProps,
-  textSize?: number,
+  textSize?: number|string,
   textColor?: string,
   linkProps?: AProps,
   linkColor?: string,

+ 2 - 2
src/components/display/Progress.vue

@@ -261,14 +261,14 @@ const themeStyles = themeContext.useThemeStyles({
     textAlign: DynamicVar('ProgressTextAlign', 'center'),
     padding: DynamicSize2('ProgressTextPaddingVertical', 'ProgressTextPaddingHorizontal', 2, 2),
     borderRadius: DynamicSize('ProgressTextBorderRadius', 20),
-    fontSize: DynamicSize('ProgressTextFontSize', 24),
+    fontSize: DynamicSize('ProgressTextFontSize', 'fontSize.md'),
     color: DynamicColor('ProgressTextColor', 'white'),
   },
   progressTextSingle: {
     width: DynamicSize('ProgressTextWidth', 80),
     borderRadius: DynamicSize('ProgressTextBorderRadius', 15),
     textAlign: DynamicVar('ProgressTextAlign', 'center'),
-    fontSize: DynamicSize('ProgressTextFontSize', 24),
+    fontSize: DynamicSize('ProgressTextFontSize', 'fontSize.md'),
     color: DynamicColor('ProgressTextSingleColor', 'text.content'),
   },
 });

+ 2 - 2
src/components/display/Status.vue

@@ -9,7 +9,7 @@
 
 <script setup lang="ts">
 import { useTheme  } from '../theme/ThemeDefine';
-import type { TextProps } from '../basic/Text.vue';
+import type { TextProps } from '../basic/Text';
 import Text from '../basic/Text.vue';
 
 export interface StatusProps {
@@ -23,7 +23,7 @@ const themeContext = useTheme();
 const props = withDefaults(defineProps<StatusProps>(), {
   status: 'primary',
   textProps: () => ({
-    fontSize: 30,
+    fontSize: 'fontSize.md',
     color: 'text.content',
   }),
 });

+ 2 - 2
src/components/display/StepItem.vue

@@ -181,10 +181,10 @@ const themeStyles = themeContext.useThemeStyles({
     alignItems: 'center',
   },
   text: {
-    fontSize: DynamicSize('StepItemTextFontSize', 26),
+    fontSize: DynamicSize('StepItemTextFontSize', 'fontSize.md'),
   },
   content: {
-    fontSize: DynamicSize('StepItemContentFontSize', 26),
+    fontSize: DynamicSize('StepItemContentFontSize', 'fontSize.md'),
     marginTop: DynamicSize('StepItemContentMarginTop', 6),
     marginLeft: DynamicSize('StepItemContentMarginLeft', 6),
     display: 'flex',

+ 5 - 5
src/components/display/Tag.vue

@@ -115,11 +115,11 @@ const props = withDefaults(defineProps<TagProps>(), {
 });
 
 const FonstSizes = {
-  mini: themeContext.resolveThemeSize('TagSmallFonstSize', 22),
-  small: themeContext.resolveThemeSize('TagSmallFonstSize', 26),
-  medium: themeContext.resolveThemeSize('TagMediumFonstSize', 30),
-  large: themeContext.resolveThemeSize('TagLargeFonstSize', 36),
-  larger: themeContext.resolveThemeSize('TagLargeFonstSize', 48),
+  mini: themeContext.resolveThemeSize('TagSmallFonstSize', 'fontSize.sm'),
+  small: themeContext.resolveThemeSize('TagSmallFonstSize', 'fontSize.sm'),
+  medium: themeContext.resolveThemeSize('TagMediumFonstSize', 'fontSize.md'),
+  large: themeContext.resolveThemeSize('TagLargeFonstSize', 'fontSize.lg'),
+  larger: themeContext.resolveThemeSize('TagLargeFonstSize', 'fontSize.xl'),
 };
 
 const themeStyles = themeContext.useThemeStyles({

+ 1 - 1
src/components/display/TextEllipsis.vue

@@ -41,11 +41,11 @@
 
 <script setup lang="ts">
 import { computed, ref } from 'vue';
-import type { TextProps } from '../basic/Text.vue';
 import Text from '../basic/Text.vue';
 import FlexCol from '../layout/FlexCol.vue';
 import FlexView, { type FlexProps } from '../layout/FlexView.vue';
 import BackgroundBox from './block/BackgroundBox.vue';
+import type { TextProps } from '../basic/Text';
 
 export interface TextEllipsisProps extends TextProps {
   /**

+ 4 - 4
src/components/display/block/TextBlock.vue

@@ -11,10 +11,10 @@ export default {}
 
 <script setup lang="ts">
 import FlexCol from '../../layout/FlexCol.vue';
-import FlexRow from '../../layout/FlexRow.vue';
-import Text, { type TextProps } from '../../basic/Text.vue';
+import Text from '../../basic/Text.vue';
 import type { PropType } from 'vue';
 import Touchable from '@/components/feedback/Touchable.vue';
+import type { TextProps } from '@/components/basic/Text';
 
 defineEmits([ 'click' ])
 defineProps({	
@@ -36,7 +36,7 @@ defineProps({
     type: Object as PropType<TextProps>,
     default: () => ({
       color: 'text.second',
-      fontSize: 26,
+      fontSize: 'fontSize.md',
     }),
   },
   /**
@@ -57,7 +57,7 @@ defineProps({
     type: Object as PropType<TextProps>,
     default: () => ({
       color: 'text.content',
-      fontSize: 30,
+      fontSize: 'fontSize.md',
     }),
   },
   /**

+ 5 - 3
src/components/dynamic/wrappers/PickerAddressField.vue

@@ -1,12 +1,13 @@
 <template>
-  <FlexRow width="100%" align="center">
+  <FlexRow width="100%" gap="gap.lg" wrap align="center">
     <input 
       :value="modelValue"
       :placeholder="readonly ? '未填写' : '输入地址或者选择地图地址'"
       @input="handleInput"
     />
-    <Button v-if="!disabled && !readonly" type="primary" size="mini" icon="map" text="地图选择" @click="selectFromMap" />
-    <view v-else></view>
+    <FlexCol v-if="!disabled && !readonly" :margin="[10, 0]">
+      <Button type="primary" size="mini" icon="map" text="地图选择" @click="selectFromMap" />
+    </FlexCol>
   </FlexRow>
 </template>
 
@@ -14,6 +15,7 @@
 import { type PropType } from 'vue';
 import Button from '@/components/basic/Button.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
+import FlexCol from '@/components/layout/FlexCol.vue';
 
 const props = defineProps({
   modelValue: {

+ 7 - 2
src/components/dynamic/wrappers/PickerCityField.vue

@@ -1,5 +1,5 @@
 <template>
-  <FlexRow width="100%" align="center">
+  <FlexRow width="100%" wrap justify="flex-start" align="center">
     <CascaderField
       v-if="ChinaCityData.data.value"
       ref="fieldRef"
@@ -12,7 +12,9 @@
       v-bind="$attrs"
       :placeholder="readonly ? '未填写' : ($attrs.placeholder as string || '请选择省市区')" 
     />
-    <Button v-if="!disabled && !readonly" type="primary" size="mini" icon="map" text="地图选择" @click="selectCityFromMap" />
+    <FlexCol v-if="!disabled && !readonly" :margin="[10, 0]">
+      <Button type="primary" size="mini" icon="map" text="地图选择" @click="selectCityFromMap" />
+    </FlexCol>
   </FlexRow>
 </template>
 
@@ -23,6 +25,7 @@ import type { CascaderItem } from '@/components/form/Cascader.vue';
 import Button from '@/components/basic/Button.vue';
 import CascaderField from '@/components/form/CascaderField.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
+import FlexCol from '@/components/layout/FlexCol.vue';
 
 const props = defineProps({
   modelValue: {
@@ -80,6 +83,8 @@ function selectCityFromMap() {
           [info.adcode ])
         emit('selectedTownship', props.stringValue ? info.township : info.towncode, info.towncode)
         setTimeout(() => fieldRef.value?.confirm(), 200);
+      }).catch((e) => {
+        console.log('选择地址失败', e);
       })
     }
   })

+ 1 - 1
src/components/feedback/Empty.vue

@@ -50,7 +50,7 @@ const themeStyles = theme.useThemeStyles({
   },
   descriptionStyle: {
     paddingVertical: DynamicSize('EmptyDescriptionPaddingVertical', 8),
-    fontSize: DynamicSize('EmptyDescriptionFontSize', 26),
+    fontSize: DynamicSize('EmptyDescriptionFontSize', 'fontSize.md'),
     color: DynamicColor('EmptyDescriptionColor', 'text.second'),
     textAlign: 'center',
   },

+ 2 - 2
src/components/feedback/Result.vue

@@ -77,11 +77,11 @@ const defaultIconColor = computed(() => {
 
 const themeVars = themeContext.getVars({
   ResultIconSize: 100,
-  ResultTitleFontSize: 36,
+  ResultTitleFontSize: 'lg',
   ResultTitleColor: 'black',
   ResultTitleBold: true,
   ResultTitleMarginTop: 10,
-  ResultDescriptionFontSize: 28,
+  ResultDescriptionFontSize: 'fontSize.md',
   ResultDescriptionColor: 'text.second',
   ResultDescriptionBold: false,
   ResultDescriptionMarginTop: 10,

+ 1 - 1
src/components/feedback/ShareSheet.vue

@@ -136,7 +136,7 @@ const themeStyles = themeContext.useThemeStyles({
   },
   itemText: {
     marginTop: DynamicSize('ShareSheetItemTextMarginTop', 15),
-    fontSize: DynamicSize('ShareSheetItemTextFontSize', 26),
+    fontSize: DynamicSize('ShareSheetItemTextFontSize', 'fontSize.md'),
   },
 });
 

+ 5 - 5
src/components/form/Calendar.vue

@@ -126,7 +126,7 @@ import FlexCol from '../layout/FlexCol.vue';
 import FlexRow from '../layout/FlexRow.vue';
 import Height from '../layout/space/Height.vue';
 import CalendarItem from './CalendarItem.vue';
-import type { TextProps } from '../basic/Text.vue';
+import type { TextProps } from '../basic/Text';
 import calendar, { getFestival } from './CalendarUtils';
 import type { FlexProps } from '../layout/FlexView.vue';
 import FixedVirtualList from '../list/FixedVirtualList.vue';
@@ -303,9 +303,9 @@ const itemColors = computed(() => theme.resolveThemeColors({
   'CalendarTextColorSelectedInRange': 'primary',
 }));
 const itemSizes = computed(() => theme.resolveThemeSizes({
-  'CalendarTopTextSize': 22,
-  'CalendarTextSize': 30,
-  'CalendarBottomTextSize': 22,
+  'CalendarTopTextSize': 'fontSize.sm',
+  'CalendarTextSize': 'fontSize.md',
+  'CalendarBottomTextSize': 'fontSize.sm',
 }));
 
 const currentShowMonth = computed(() => new Date(`${currentYear.value}-${currentMonth.value + 1}-01`));
@@ -637,7 +637,7 @@ const theme = useTheme();
 
 export interface CalendarContext {
   itemColors: ComputedRef<Record<string, string>>,
-  itemSizes: ComputedRef<Record<string, number>>,
+  itemSizes: ComputedRef<Record<string, number|string>>,
   itemProps: Ref<FlexProps|undefined>,
   disabledDates: Ref<string[]|undefined>,
   pickType: Ref<string>,

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

@@ -40,7 +40,7 @@
 <script setup lang="ts">
 import { computed, inject } from 'vue';
 import { DateUtils } from '@imengyu/imengyu-utils';
-import type { TextProps } from '../basic/Text.vue';
+import type { TextProps } from '../basic/Text';
 import type { CalendarContext } from './Calendar.vue';
 import Text from '../basic/Text.vue';
 import Touchable from '../feedback/Touchable.vue';

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

@@ -190,7 +190,7 @@ const themeStyles = themeContext.useThemeStyles({
     justifyContent: 'center',
   },
   checkText: {
-    fontSize: DynamicSize('CheckBoxTextFontSize', 28),
+    fontSize: DynamicSize('CheckBoxTextFontSize', 'fontSize.md'),
   },
 });
 

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

@@ -628,7 +628,7 @@ const themeStyles = themeContext.useThemeStyles({
     gap: DynamicSize('FieldVerticalGap', 20),
   },
   requiredMark: {
-    fontSize: DynamicSize('FieldRequiredMark', 28),
+    fontSize: DynamicSize('FieldRequiredMark', 'fontSize.md'),
     alignSelf: 'flex-start',
     color: DynamicColor('FieldRequiredMark', 'danger'),
     paddingVertical: DynamicSize('FieldRequiredMarkPaddingVertical', 8),
@@ -636,7 +636,7 @@ const themeStyles = themeContext.useThemeStyles({
   },
   labelText: {
     marginRight: DynamicSize('FieldLabelMarginRight', 20),
-    fontSize: DynamicSize('FieldLabelFontSize', 28),
+    fontSize: DynamicSize('FieldLabelFontSize', 'fontSize.md'),
     alignSelf: 'flex-start',
     paddingVertical: DynamicSize('FieldLabelPaddingVertical', 8),
   },
@@ -649,26 +649,26 @@ const themeStyles = themeContext.useThemeStyles({
     flex: 1,
     width: 'auto',
     minWidth: '100rpx',
-    fontSize: DynamicSize('FieldFontSize', 28),
+    fontSize: DynamicSize('FieldFontSize', 'fontSize.md'),
     paddingVertical: DynamicSize('FieldInputPaddingVertical', 0),
     paddingHorizontal: DynamicSize('FieldInputPaddingHorizontal', 0),
   },
   errorMessageText: {
-    fontSize: DynamicSize('FieldErrorMessageFontSize', 24),
+    fontSize: DynamicSize('FieldErrorMessageFontSize', 'fontSize.md'),
     color: DynamicColor('FieldErrorMessageColor', 'danger'),
   },
   errorMessage: {
     marginTop: DynamicSize('FieldErrorMessageMarginTop', 12),
   },
   extraMessageText: {
-    fontSize: DynamicSize('FieldExtraMessageFontSize', 24),
+    fontSize: DynamicSize('FieldExtraMessageFontSize', 'fontSize.sm'),
     color: DynamicColor('FieldExtraMessageColor', 'text.second'),
   },
   extraMessage: {
     marginTop: DynamicSize('FieldExtraMessageMarginTop', 12),
   },
   wordLimitText: {
-    fontSize: DynamicSize('FieldWordLimitTextFontSize', 24),
+    fontSize: DynamicSize('FieldWordLimitTextFontSize', 'fontSize.sm'),
     color: DynamicColor('FieldWordLimitTextColor', 'text.second'),
     width: DynamicSize('FieldWordLimitTextWidth', '100%'),
     textAlign: DynamicVar('FieldWordLimitTextTextAlign', 'right'),

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

@@ -73,7 +73,7 @@ const themeStyles = themeContext.useThemeStyles({
     justifyContent: 'center',
   },
   text: {
-    fontSize: DynamicSize('NumberInputTextFontSize', 36),
+    fontSize: DynamicSize('NumberInputTextFontSize', 'fontSize.md'),
     width: DynamicSize('NumberInputTextWidth', 40),
     textAlign: 'center',
     color: DynamicColor('NumberInputTextColor', 'text.content'),

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

@@ -180,7 +180,7 @@ const themeStyles = themeContext.useThemeStyles({
     justifyContent: 'center',
   },
   checkText: {
-    fontSize: DynamicSize('RadioBoxTextFontSize', 28),
+    fontSize: DynamicSize('RadioBoxTextFontSize', 'fontSize.md'),
   },
 });
 

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

@@ -88,7 +88,7 @@ const containerStyle = computed(() => ({
   ...props.innerStyle
 }));
 const placeholderStyle = computed(() => ({
-  fontSize: theme.resolveThemeSize('SignaturePlaceholderFontSize', 26),
+  fontSize: theme.resolveThemeSize('SignaturePlaceholderFontSize', 'fontSize.md'),
   color: theme.resolveThemeColor('SignaturePlaceholderColor', 'text.second'),
   ...props.placeholderStyle
 }));

+ 17 - 5
src/components/form/UploaderListItem.vue

@@ -57,11 +57,18 @@
     <Icon v-else :icon="fileIcon" :color="itemMaskTextColor" :size="itemListStyleImageSize" />
 
     <FlexRow v-if="isListStyle" :flex="1" align="center">
-      <Width :size="20" />
+      <Width size="gap.lg" />
       <FlexCol :flex="1">
-        <Text :fontSize="26" wrap wordBreak="break-all" :text="item.name || StringUtils.path.getFileName(item.filePath)" />
-        <Text :fontSize="22" :text="item.message" />
-        <Height :size="10" /> 
+        <Text 
+          :fontSize="listStyleFontSizes.UploaderListItemListTextFontSize" 
+          wrap wordBreak="break-all" 
+          :text="item.name || StringUtils.path.getFileName(item.filePath)"
+        />
+        <Text 
+          :fontSize="listStyleFontSizes.UploaderListItemListMessageFontSize" 
+          :text="item.message" 
+        />
+        <Height size="gap.md" /> 
         <Progress :progressColor="selectStyleType(item.state, 'notstart', {
           notstart: 'primary',
           uploading: 'primary',
@@ -72,7 +79,7 @@
       <Icon v-if="item.state === 'success'" icon="select-bold" color="success" />
       <Icon v-else-if="item.state === 'fail'" icon="close-bold" color="danger" />
       <ActivityIndicator v-else-if="item.state === 'uploading'" :size="45" />
-      <Width :size="20" />
+      <Width size="gap.lg" />
       <IconButton v-if="showDelete" icon="trash" @click.stop="emit('delete')" />
     </FlexRow>
   </Touchable>
@@ -206,6 +213,11 @@ const isImage = computed(() => {
   )
 });
 
+const listStyleFontSizes = computed(() => themeContext.resolveThemeSizes({
+  'UploaderListItemListTextFontSize': 'fontSize.md',
+  'UploaderListItemListMessageFontSize': 'fontSize.sm',
+ }));
+
 const fileIcon = computed(() => {
   const ext = StringUtils.path.getFileExt(props.item.filePath || '');
   switch (ext) {

+ 3 - 3
src/components/keyboard/NumberKeyBoardInner.vue

@@ -272,10 +272,10 @@ const themeStyles = themeContext.useThemeStyles({
   },
   title: {
     color: DynamicColor('NumberKeyBoardTitleColor', 'black'),
-    fontSize: DynamicSize('NumberKeyBoardTitleFontSize', 32),
+    fontSize: DynamicSize('NumberKeyBoardTitleFontSize', 'fontSize.md'),
   },
   keyText: {
-    fontSize: DynamicSize('NumberKeyBoardKeyFontSize', 46),
+    fontSize: DynamicSize('NumberKeyBoardKeyFontSize', 'lg'),
   },
 });
 const keyTextStyle = computed(() => ({
@@ -285,7 +285,7 @@ const keyTextStyle = computed(() => ({
 }));
 const keyTextStyleFinish = computed(() => ({
   ...themeStyles.keyText.value,
-  fontSize: themeContext.resolveThemeSize('NumberKeyBoardKeyFinishFontSize', 40),
+  fontSize: themeContext.resolveThemeSize('NumberKeyBoardKeyFinishFontSize', 'fontSize.lg'),
   ...props.keyTextStyle,
   color: themeContext.resolveThemeColor(props.keyFinishTextColor),
 }));

+ 2 - 2
src/components/keyboard/PlateKeyBoardInner.vue

@@ -206,10 +206,10 @@ const themeStyles = themeContext.useThemeStyles({
   },
   title: {
     color: DynamicColor('PlateKeyBoardTitleColor', 'black'),
-    fontSize: DynamicSize('PlateKeyBoardTitleFontSize', 32),
+    fontSize: DynamicSize('PlateKeyBoardTitleFontSize', 'fontSize.md'),
   },
   keyText: {
-    fontSize: DynamicSize('PlateKeyBoardKeyFontSize', 34),
+    fontSize: DynamicSize('PlateKeyBoardKeyFontSize', 'fontSize.md'),
   },
   dot: {
     margin: DynamicSize('PlateKeyBoardDotMargin', 10),

+ 1 - 1
src/components/keyboard/PlateKeyBoardInputBox.vue

@@ -39,7 +39,7 @@ const themeStyles = themeContext.useThemeStyles({
   },
   inputBoxText: {
     display: 'flex',
-    fontSize: DynamicSize('PlateKeyBoardInputBoxFontSize', 32),
+    fontSize: DynamicSize('PlateKeyBoardInputBoxFontSize', 'fontSize.md'),
     fontWeight: DynamicSize('PlateKeyBoardInputBoxFontWeight', 'bold'),
     color: DynamicColor('PlateKeyBoardInputBoxColor', 'black'),
   },

+ 3 - 2
src/components/layout/grid/GridItem.vue

@@ -49,7 +49,8 @@ import { computed, inject } from 'vue';
 import type { FlexDirection } from '../FlexView.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
 import Icon from '@/components/basic/Icon.vue';
-import Text, { type TextProps } from '@/components/basic/Text.vue';
+import Text from '@/components/basic/Text.vue';
+import type { TextProps } from '@/components/basic/Text.js';
 
 
 export interface GridItemProps {  
@@ -189,7 +190,7 @@ const titleStyle = computed(() => {
 })
 const titleImageStyle = computed(() => {
   return {
-    fontSize: themeContext.resolveThemeSize('GridItemSubTitleFontSize', 24),
+    fontSize: themeContext.resolveThemeSize('GridItemSubTitleFontSize', 'fontSize.md'),
     marginTop: themeContext.resolveThemeSize('GridItemSubTitleMarginTop', 10),
   } 
 })

+ 2 - 2
src/components/list/IndexList.vue

@@ -207,7 +207,7 @@ const themeStyles = themeContext.useThemeStyles({
     alignItems: 'center',
     backgroundColor: DynamicColor('IndexedListHeaderBackgroundColor', 'background.page'),
     padding: DynamicSize2('IndexedListHeaderPaddingVertical', 'IndexedListHeaderPaddingHorizontal', 0, 30),
-    fontSize: DynamicSize('IndexedListHeaderFontSize', 24),
+    fontSize: DynamicSize('IndexedListHeaderFontSize', 'fontSize.md'),
     color: DynamicColor('IndexedListHeaderColor', 'text.second'),
     position: 'sticky',
   },
@@ -217,7 +217,7 @@ const themeStyles = themeContext.useThemeStyles({
     alignItems: 'center',
     paddingLeft: DynamicSize('IndexedListItemPaddingHorizontal', 30),
     paddingRight: DynamicSize('IndexedListItemPaddingHorizontal', 30),
-    fontSize: DynamicSize('IndexedListItemFontSize', 28),
+    fontSize: DynamicSize('IndexedListItemFontSize', 'fontSize.md'),
     borderTopWidth: DynamicSize('IndexedListItemBorderTopWidth', 0),
     borderBottomStyle: 'solid',
     borderBottomWidth: DynamicSize('IndexedListItemBorderBottomWidth', 2),

+ 3 - 3
src/components/list/SimpleList.vue

@@ -175,7 +175,7 @@ const themeContext = useTheme();
 const themeStyles = themeContext.useThemeStyles({
   item: {
     padding: DynamicSize2('SimpleListItemPaddingVertical', 'SimpleListItemPaddingHorizontal', 20, 35),
-    fontSize: DynamicSize('SimpleListItemFontSize', 28),
+    fontSize: DynamicSize('SimpleListItemFontSize', 'fontSize.md'),
     borderTopStyle: 'solid',
     borderTopWidth: DynamicSize('SimpleListItemBorderTopWidth', 0),
     borderTopColor: DynamicColor('SimpleListItemBorderColor', 'border.cell'),
@@ -188,12 +188,12 @@ const themeStyles = themeContext.useThemeStyles({
   },
   itemText: {
     flex: 1,
-    fontSize: DynamicSize('SimpleListItemTextFontSize', 28),
+    fontSize: DynamicSize('SimpleListItemTextFontSize', 'fontSize.md'),
     fontWeight: DynamicSize('SimpleListItemTextFontWeight', 'normal'),
     color: DynamicColor('SimpleListItemTextColor', 'text.content'),
   },
   itemTextChecked: {
-    fontSize: DynamicSize('SimpleListItemCheckedTextFontSize', 28),
+    fontSize: DynamicSize('SimpleListItemCheckedTextFontSize', 'fontSize.md'),
     fontWeight: DynamicVar('SimpleListItemCheckedTextFontWeight', 'bold'),
     color: DynamicColor('SimpleListItemCheckedTextColor', 'primary'),
   },

+ 2 - 2
src/components/nav/IndexBar.vue

@@ -147,7 +147,7 @@ const themeStyles = themeContext.useThemeStyles({
   },
   barItemText: {
     color: DynamicColor('IndexBarItemTextColor', 'text.content'),
-    fontSize: DynamicSize('IndexBarItemTextFontSize', 24),
+    fontSize: DynamicSize('IndexBarItemTextFontSize', 'fontSize.sm'),
   },
   indicator: {
     position: 'absolute',
@@ -166,7 +166,7 @@ const themeStyles = themeContext.useThemeStyles({
   },
   indicatorText: {
     color: DynamicVar('IndexBarIndicatorTextColor', 'white'),
-    fontSize: DynamicVar('IndexBarIndicatorTextFontSize', 50),
+    fontSize: DynamicVar('IndexBarIndicatorTextFontSize', 'fontSize.lg'),
     fontWeight: DynamicVar('IndexBarIndicatorTextFontWeight', 'bold'),
   },
 

+ 1 - 1
src/components/nav/NavBar.vue

@@ -214,7 +214,7 @@ const menuButtonInfo = {
 
 const titleTextStyle = theme.useThemeStyle({
   flex: 1,
-  fontSize: DynamicSize('NavBarTitleFontSize', 30),
+  fontSize: DynamicSize('NavBarTitleFontSize', 'fontSize.md'),
   paddingLeft: DynamicSize('NavBarTitlePaddingHorizontal', 15),
   paddingRight: DynamicSize('NavBarTitlePaddingHorizontal', 15),
 });

+ 1 - 1
src/components/nav/PaginationItem.vue

@@ -15,7 +15,7 @@ const themeStyles = themeContext.useThemeStyles({
     textAlign: 'center',
   },
   itemText: {
-    fontSize: DynamicSize('PaginationItemTextFontSize', 26),
+    fontSize: DynamicSize('PaginationItemTextFontSize', 'fontSize.md'),
     textAlign: DynamicSize('PaginationItemTextAlign', 'center'),
   },
 });

+ 1 - 1
src/components/nav/SegmentedControl.vue

@@ -139,7 +139,7 @@ const themeStyles = themeContext.useThemeStyles({
     textAlign: 'center',
   },
   itemText: {
-    fontSize: DynamicSize('SegmentedControlItemFontSize', 26),
+    fontSize: DynamicSize('SegmentedControlItemFontSize', 'fontSize.md'),
     textAlign: 'center',
   },
 });

+ 1 - 1
src/components/nav/SideBarItem.vue

@@ -83,7 +83,7 @@ const props = withDefaults(defineProps<SideBarItemProps>(), {
 const themeContext = useTheme();
 const themeStyles = themeContext.useThemeStyles({
   sideText: {
-    fontSize: DynamicSize('SideBarItemTextFontSize', 28),
+    fontSize: DynamicSize('SideBarItemTextFontSize', 'fontSize.md'),
   },
   sideItem: {
     position: 'relative',

+ 1 - 1
src/components/nav/TabBarItem.vue

@@ -167,7 +167,7 @@ const themeStyles = theme.useThemeStyles({
     justifyContent: 'center',
   },
   tabText: {
-    fontSize: DynamicSize('TabBarItemTextFontSize', 22),
+    fontSize: DynamicSize('TabBarItemTextFontSize', 'fontSize.sm'),
     marginTop: DynamicSize('TabBarItemTextMarginTop', 0),
   },
 });

+ 5 - 3
src/components/nav/Tabs.vue

@@ -49,6 +49,7 @@
               :style="{
                 color: tab.disabled ? themedDisableTextColor : (currentIndex == index ? themedActiveTextColor : themedTextColor),
                 whiteSpace: props.noWrap ? 'nowrap' : 'normal',
+                ...tabTextStyle,
                 ...(currentIndex == index ? activeTextStyle : textStyle),
               }"
             >
@@ -235,6 +236,10 @@ const props = withDefaults(defineProps<TabsProps>(), {
 
 const theme = useTheme();
 
+const tabTextStyle = theme.useThemeStyle({
+  fontSize: 'fontSize.md',
+});
+
 const tabPaddingHorizontal = computed(() => theme.getVar('TabsItemPaddingHorizontal', 10));
 const themedUnderlayColor = computed(() => theme.resolveThemeColor(props.underlayColor));
 const themedActiveTextColor = computed(() => theme.resolveThemeColor(props.activeTextColor));
@@ -357,9 +362,6 @@ function onTabClick(index: number) {
     flex-shrink: 0;
     flex-grow: 0;
   }
-  .tab-item-text {
-    font-size: 15px;
-  }
   .tab-indicator {
     position: absolute;
     border-radius: 3rpx;

+ 18 - 16
src/components/theme/Theme.ts

@@ -33,11 +33,13 @@ export const DefaultTheme : ThemeConfig = {
       '3xl': '60rpx',
     },
     fontSize: {
-      xs: 22,
-      sm: 26,
-      md: 30,
-      lg: 38,
-      xl: 46,
+      xs: '0.6rem',
+      sm: '0.8rem',
+      md: '1rem',
+      lg: '1.15rem',
+      xl: '1.26rem',
+      '2xl': '1.5rem',
+      '3xl': '1.7rem',
     },
     gap: {
       xs: '2rpx',
@@ -149,53 +151,53 @@ export const DefaultTheme : ThemeConfig = {
   textConfigs: {
     h1: {
       color: 'text.title',
-      fontSize: '50px',
+      fontSize: '3rem',
       fontWeight: 'bold',
     },
     h2: {
       color: 'text.title',
-      fontSize: '45rpx',
+      fontSize: '2.5rem',
       fontWeight: 'bold',
     },
     h3: {
       color: 'text.title',
-      fontSize: '40rpx',
+      fontSize: '1.8rem',
       fontWeight: 'bold',
     },
     h4: {
       color: 'text.title',
-      fontSize: '36rpx',
+      fontSize: '1.45rem',
       fontWeight: 'bold',
     },
     h5: {
       color: 'text.title',
-      fontSize: '30rpx',
+      fontSize: '1.25rem',
       fontWeight: 'bold',
     },
     h6: {
       color: 'text.title',
-      fontSize: '26rpx',
+      fontSize: '1rem',
       fontWeight: 'bold',
     },
     content: {
       color: 'text.content',
-      fontSize: '24rpx',
+      fontSize: '1rem',
     },
     subTitle: {
       color: 'text.content',
-      fontSize: '34rpx',
+      fontSize: '1.125rem',
     },
     subText: {
       color: 'text.content',
-      fontSize: '26rpx',
+      fontSize: '1rem',
     },
     subSecondText: {
       color: 'text.second',
-      fontSize: '26rpx',
+      fontSize: '1rem',
     },
     footerText: {
       color: 'text.second',
-      fontSize: '24rpx',
+      fontSize: '0.9rem',
     },
   }
 }

+ 1 - 1
src/components/theme/ThemeDefine.ts

@@ -126,7 +126,7 @@ export function useTheme() {
       return inValue;     
     return getColor(inValue, defaultValue);
   }
-  function resolveThemeSizes<T extends Record<string, string|number>>(defaults: T) {
+  function resolveThemeSizes<T extends Record<string, string|number>>(defaults: T) : Record<string, string|number> {
     const result : T = {} as T;
     for (let key in defaults) 
       result[key] = resolveThemeSize(key, defaults[key]) as any;

+ 2 - 1
src/pages.json

@@ -454,7 +454,8 @@
           "path": "forms/submits",
           "style": {
             "navigationBarTitleText": "我的投稿",
-            "enablePullDownRefresh": true
+            "enablePullDownRefresh": true,
+            "navigationStyle": "custom"
           }
         },
         {

+ 2 - 3
src/pages/article/details.vue

@@ -30,7 +30,7 @@
             width="100%"
           />
           <FlexCol :padding="20" :gap="14">
-            <H2>{{ loader.content.value.title }}</H2>
+            <H4 fontConfig="subTitle">{{ loader.content.value.title }}</H4>
             <FlexRow>
               <Text v-if="loader.content.value.from" :text="`来源:${loader.content.value.from}`" fontConfig="subText" />
               <Text :text="DataDateUtils.formatDate(loader.content.value.publishAt, 'YYYY-MM-dd')" fontConfig="subText" />
@@ -54,7 +54,7 @@
           
           <!-- 推荐 -->
           <FlexCol v-if="recommendListLoader.content.value?.length && querys.showRecommend" :padding="20">
-            <H4>相关推荐</H4>
+            <H4 fontConfig="subTitle" fontSize="fontSize.md">相关推荐</H4>
             <Box2LineImageRightShadow
               titleColor="black"
               v-for="item in recommendListLoader.content.value"
@@ -94,7 +94,6 @@ import FlexCol from "@/components/layout/FlexCol.vue";
 import Image from "@/components/basic/Image.vue";
 import H4 from "@/components/typography/H4.vue";
 import Text from "@/components/basic/Text.vue";
-import H2 from "@/components/typography/H2.vue";
 import FlexRow from "@/components/layout/FlexRow.vue";
 
 const loader = useSimpleDataLoader<

+ 2 - 2
src/pages/dig/components/TaskList.vue

@@ -74,8 +74,8 @@ defineProps({
           v-if="button" 
           src="https://xy.wenlvti.net/app_static/images/village/BoxButton.png"
           :touchable="enable"
-          :width="110"
-          :height="60"
+          :width="140"
+          :height="75"
           @click="$emit('click')"
         >  
           <FlexCol position="absolute" inset="0" center>

+ 11 - 10
src/pages/dig/forms/common.vue

@@ -25,6 +25,7 @@
                 :options="formDefine"
                 :model="formModel"
                 :globalParams="querys"
+                @doNav="handleDoNav"
                 @storageOverflow="handleStorageOverflow"
               />
             </ProvideVar>
@@ -38,10 +39,10 @@
           <PrimaryButton 
             text="提交"
             width="560rpx"
-            :loading="loading"
+            :loading="submitLoading"
             @click="debounceSubmit.executeWithDelay()"
           />
-          <Button v-if="querys.id > 0 && !loading" 
+          <Button v-if="querys.id > 0 && !submitLoading && !loading" 
             type="text" 
             textColor="danger" 
             text="删除"
@@ -59,7 +60,7 @@
 <script setup lang="ts">
 import { nextTick, ref, watch, type Ref } from 'vue';
 import { useLoadQuerys } from '@/components/composeabe/LoadQuerys';
-import { getVillageInfoForm, getVillageInfoFormIds, type SingleForm } from './forms';
+import { getVillageInfoForm, type SingleForm } from './forms';
 import { CollectableModulesIdMap } from "@/common/data/CollectableModulesIdMap";
 import { showError } from '@/common/composeabe/ErrorDisplay';
 import { backAndCallOnPageBack, navTo } from '@/components/utils/PageAction';
@@ -80,11 +81,11 @@ 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';
+import { onShow } from '@dcloudio/uni-app';
 
 const loading = ref(true);
 const show = ref(true);
+const submitLoading = ref(false);
 const deleteing = ref(false);
 const subTitle = ref('');
 
@@ -195,7 +196,7 @@ async function submit() {
     return;
   }
   try {
-    loading.value = true;
+    submitLoading.value = true;
 
     // 检查是否有上传中的文件
     const controls = formRef.value.getFormItemControlRefsByType<UploaderFieldInstance>('uploader');
@@ -230,7 +231,7 @@ async function submit() {
     showError(e);
   } finally {
     await waitTimeOut(2000);
-    loading.value = false;
+    submitLoading.value = false;
   }
 }
 function backPrev(needRefresh: boolean, isDeleted: boolean) {
@@ -327,13 +328,13 @@ watch(formModel, () => {
   saveLocalSaveDebounce.executeWithDelay();
 }, { deep: true })
 
-onHide(() => {
-  show.value = false;
-})
 onShow(() => {
   setTimeout(() => {
     show.value = true;
   }, 400);
 })
 
+function handleDoNav() {
+  show.value = false;
+}
 </script>

+ 4 - 4
src/pages/dig/forms/list-ordinary.vue

@@ -42,12 +42,12 @@
               backgroundImage="https://xy.wenlvti.net/app_static/images/village/BoxMid.png"
               :backgroundCutBorder="30"
               :backgroundCutBorderSize="30"
-              :padding="[16, 30]"
+              :padding="[16, 30, 16, 26]"
               align="center"
             >
               <Touchable 
                 :gap="20"
-                :padding="[15,20]"
+                :padding="[15,0]"
                 touchable
                 flex="1"
                 @click="goDetail(item)"
@@ -61,7 +61,7 @@
                   mode="aspectFill"
                 />
                 <FlexCol>
-                  <H4 :size="36" :maxWidth="300" :lines="1" fontFamily="SongtiSCBlack">{{ item.title }}</H4>
+                  <H5 :maxWidth="260" :lines="1" fontFamily="SongtiSCBlack">{{ item.title }}</H5>
                   <Text fontConfig="secondText" :text="item.desc" />
                   <Text fontConfig="secondText" :text="item.from" />
                 </FlexCol>
@@ -110,7 +110,7 @@ import FlexCol from '@/components/layout/FlexCol.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
 import Text from '@/components/basic/Text.vue';
 import Height from '@/components/layout/space/Height.vue';
-import H4 from '@/components/typography/H4.vue';
+import H5 from '@/components/typography/H5.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
 import XBarSpace from '@/components/layout/space/XBarSpace.vue';
 import Result from '@/components/feedback/Result.vue';

+ 91 - 84
src/pages/dig/forms/submits.vue

@@ -1,90 +1,96 @@
 <template>
-  <FlexCol :padding="30">
-    <SearchBar
-      v-model="searchText"
-      placeholder="搜一搜" 
-      @search="search"
-    />
-    <Height :height="20" />
-    <DropdownMenu>
-      <DropdownMenuItem 
-        v-model="filterStatus"
-        :options="[
-          { text: '全部状态', value: -100 },
-          { text: '未通过', value: CommonInfoModel.STATUS_REJECT },
-          { text: '待审核', value: CommonInfoModel.STATUS_AUDIT },
-          { text: '审核通过', value: CommonInfoModel.STATUS_PASS },
-          { text: '专家评估', value: CommonInfoModel.STATUS_EXPERT },
-          { text: '终审', value: CommonInfoModel.STATUS_FINAL },
-        ]"
-        type="single-check"
+  <CommonTopBanner title="我的投稿">
+    <FlexCol :padding="30">
+      <SearchBar
+        v-model="searchText"
+        placeholder="搜一搜" 
+        @search="search"
       />
-      <DropdownMenuItem 
-        v-model="filterVillage"
-        :options="villageListLoader.content.value || [{
-          text: '未选择村社',
-          value: -100,
-        }]"
-        type="single-check"
-      />
-    </DropdownMenu>
-    <Height :height="20" />
-    <SimplePageListLoader :loader="listLoader" :noEmpty="true">
-      <template #empty>
-        <Empty image="search" description="这里还没提交过投稿,欢迎成为志愿者投稿!">
-        </Empty>
-      </template>
-      <FlexCol :gap="20">
-        <Touchable 
-          v-for="item in listLoader.list.value"
-          :key="item.id" 
-          :padding="[15,20]"
-          radius="radius.md"
-          justify="space-between"
-          align="center"
-          backgroundColor="white"
-          direction="row"
-          touchable
-          @click="goDetail(item)"
-        >
-          <FlexRow align="center" :gap="20">
-            <Image 
-              :src="item.image"
-              :showFailed="false"
-              :width="150"
-              :height="150"
-              radius="radius.sm"
-              mode="aspectFill"
-            />
-            <FlexCol>
-              <H4 :size="36">{{ item.title }}</H4>
-              <Height :height="10" />
-              <Text :size="23" :text="`栏目: ${item.catalogName || item.collectModuleName || ''}`" />
-              <Text :size="23" :text="`时间: ${DataDateUtils.formatDate(item.updatedAt, 'YYYY-MM-dd')}`" />
-              <FlexRow align="center">
-                <Text :size="23" :text="`状态:`" />
-                <Tag 
-                  size="small"
-                  :text="(item.statusText as string)" 
-                  :type="selectObjectByType(item.status as string, CommonInfoModel.STATUS_REJECT.toString(), {
-                    [CommonInfoModel.STATUS_REJECT]: 'danger',
-                    [CommonInfoModel.STATUS_DRAFT]: 'default',
-                    [CommonInfoModel.STATUS_AUDIT]: 'warning',
-                    [CommonInfoModel.STATUS_PASS]: 'primary',
-                    [CommonInfoModel.STATUS_EXPERT]: 'primary',
-                    [CommonInfoModel.STATUS_FINAL]: 'success',
-                  })" 
+      <Height :height="20" />
+      
+      <BoxMid :padding="[10, 0]">
+        <DropdownMenu backgroundColor="transparent">
+          <DropdownMenuItem 
+            v-model="filterStatus"
+            :options="[
+              { text: '全部状态', value: -100 },
+              { text: '未通过', value: CommonInfoModel.STATUS_REJECT },
+              { text: '待审核', value: CommonInfoModel.STATUS_AUDIT },
+              { text: '审核通过', value: CommonInfoModel.STATUS_PASS },
+              { text: '专家评估', value: CommonInfoModel.STATUS_EXPERT },
+              { text: '终审', value: CommonInfoModel.STATUS_FINAL },
+            ]"
+            type="single-check"
+          />
+          <DropdownMenuItem 
+            v-model="filterVillage"
+            :options="villageListLoader.content.value || [{
+              text: '未选择村社',
+              value: -100,
+            }]"
+            type="single-check"
+          />
+        </DropdownMenu>
+      </BoxMid>
+      <Height :height="20" />
+      <SimplePageListLoader :loader="listLoader" :noEmpty="true">
+        <template #empty>
+          <Empty image="search" description="这里还没提交过投稿,欢迎成为志愿者投稿!">
+          </Empty>
+        </template>
+        <FlexCol :gap="20">
+          <BoxMid
+            v-for="item in listLoader.list.value"
+            :key="item.id"
+          >
+            <Touchable
+              radius="radius.md"
+              justify="space-between"
+              align="center"
+              direction="row"
+              touchable
+              @click="goDetail(item)"
+            >
+              <FlexRow align="center" :gap="20">
+                <Image 
+                  :src="item.image"
+                  :showFailed="false"
+                  :width="150"
+                  :height="150"
+                  radius="radius.sm"
+                  mode="aspectFill"
                 />
+                <FlexCol>
+                  <Text fontConfig="subTitle" :lines="2">{{ item.title }}</Text>
+                  <Height :height="10" />
+                  <Text fontConfig="contentText" fontSize="fontSize.sm" wrap :text="`栏目: ${item.catalogName || item.collectModuleName || ''}`" />
+                  <Text fontConfig="contentText" fontSize="fontSize.sm" :text="`时间: ${DataDateUtils.formatDate(item.updatedAt, 'YYYY-MM-dd')}`" />
+                  <FlexRow align="center">
+                    <Text fontConfig="contentText" fontSize="fontSize.sm" :text="`状态:`" />
+                    <Tag 
+                      size="small"
+                      :text="(item.statusText as string)" 
+                      :type="selectObjectByType(item.status as string, CommonInfoModel.STATUS_REJECT.toString(), {
+                        [CommonInfoModel.STATUS_REJECT]: 'danger',
+                        [CommonInfoModel.STATUS_DRAFT]: 'default',
+                        [CommonInfoModel.STATUS_AUDIT]: 'warning',
+                        [CommonInfoModel.STATUS_PASS]: 'primary',
+                        [CommonInfoModel.STATUS_EXPERT]: 'primary',
+                        [CommonInfoModel.STATUS_FINAL]: 'success',
+                      })" 
+                    />
+                  </FlexRow>
+                  <Text v-if="item.opinion" :size="23" :text="`审核意见: ${item.opinion}`" />
+                </FlexCol>
               </FlexRow>
-              <Text v-if="item.opinion" :size="23" :text="`审核意见: ${item.opinion}`" />
-            </FlexCol>
-          </FlexRow>
-          <Icon icon="arrow-right-bold" color="primary" :size="36" />
-        </Touchable>
-      </FlexCol>
-    </SimplePageListLoader>
-    <XBarSpace />
-  </FlexCol>
+              <Icon icon="arrow-right-bold" color="primary" :size="36" />
+            </Touchable> 
+          </BoxMid>
+        </FlexCol>
+      </SimplePageListLoader>
+      <XBarSpace />
+    </FlexCol>
+  </CommonTopBanner>
 </template>
 
 <script setup lang="ts">
@@ -104,7 +110,6 @@ import SearchBar from '@/components/form/SearchBar.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import Text from '@/components/basic/Text.vue';
 import Height from '@/components/layout/space/Height.vue';
-import H4 from '@/components/typography/H4.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
 import XBarSpace from '@/components/layout/space/XBarSpace.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
@@ -114,6 +119,8 @@ import DropdownMenu from '@/components/feedback/DropdownMenu.vue';
 import DropdownMenuItem from '@/components/feedback/DropdownMenuItem.vue';
 import VillageApi, { type VillageListItem } from '@/api/inhert/VillageApi';
 import { waitTimeOut } from '@imengyu/imengyu-utils';
+import BoxMid from '@/common/components/box/BoxMid.vue';
+import CommonTopBanner from '@/common/components/CommonTopBanner.vue';
 
 const searchText = ref('');
 const filterStatus = ref(-100);

+ 1 - 1
src/pages/home/about/about.vue

@@ -1,5 +1,5 @@
 <template>
-  <FlexCol>
+  <FlexCol padding="padding.md">
     <SimplePageContentLoader :loader="loader">
       <Parse :content="loader.content?.value?.content || ''" />
     </SimplePageContentLoader>

+ 1 - 1
src/pages/home/about/contract.vue

@@ -1,5 +1,5 @@
 <template>
-  <FlexCol>
+  <FlexCol padding="padding.md">
     <SimplePageContentLoader :loader="loader">
       <Parse :content="loader.content?.value?.content || ''" />
     </SimplePageContentLoader>

+ 1 - 0
src/pages/home/chat/dependent/post/editor.vue

@@ -140,6 +140,7 @@ function load() {
           url: image,
           type: 'image',
           filePath: image,
+          uploadedPath: image,
           state: image ? 'success' : 'notstart',
         })));
       }, 1000);

+ 2 - 2
src/pages/home/components/VillageRankList.vue

@@ -28,7 +28,7 @@
         center
         backgroundColor="rgba(0, 0, 0, 0.5)"
       >
-        <Text :text="item.title" fontConfig="h4" :lines="1" color="white" />
+        <Text :text="item.title" fontConfig="subTitle" :lines="1" color="white" />
       </FlexRow>
       <FlexCol 
         position="absolute"
@@ -46,7 +46,7 @@
             `url('https://xy.wenlvti.net/app_static/images/home/RankBadgeN.png')`,
         }"
       >
-        <Text v-if="item.rank > 1" fontConfig="h4" :text="item.rank" :lines="1" color="white" />
+        <Text v-if="item.rank > 1" fontConfig="subTitle" :text="item.rank" :lines="1" color="white" />
       </FlexCol>
     </Touchable>
   </FlexRow>

+ 2 - 2
src/pages/home/components/VillageUserRankList.vue

@@ -30,9 +30,9 @@
           defaultAvatar="https://xy.wenlvti.net/app_static/images/village/PlaceholderVolunteerNew.png"
         />
         <Height :height="item.rank == 1 ? 15 : 10" />
-        <Text fontConfig="h4" :text="item.title" :lines="1" color="white" />
+        <Text :fontSize="30" fontConfig="subTitle" :text="item.title" :lines="1" color="white" />
         <Height :height="6" />
-        <Text fontConfig="h2" :text="item.score >= 0 ? `${item.score}` : '等你加入'" :fontSize="30" :color="scoreColors[item.rank - 1]" fontFamily="SongtiSCBlack" />
+        <Text :text="item.score >= 0 ? `${item.score}` : '等你加入'" :fontSize="30" :color="scoreColors[item.rank - 1]" fontFamily="SongtiSCBlack" />
         <Text fontFamily="SongtiSCBlack" :fontSize="18" :text="scoreSuffix" :color="scoreColors[item.rank - 1]" />
       </FlexCol>
     </Touchable>

+ 5 - 5
src/pages/home/discover/details.vue

@@ -57,7 +57,7 @@
           </FlexCol>
           <FlexRow justify="space-between" padding="padding.md" >
             <FlexCol gap="gap.md">
-              <H3 class="size-ll color-title-text">{{ loader.content.value.title }}</H3>
+              <H4 fontFamily="SongtiSCBlack" wrap :maxWidth="700" :lines="2">{{ loader.content.value.title }}</H4>
               <FlexRow gap="gap.md">
                 <Text v-if="loader.content.value.keywords" color="text.second" :size="28">{{ loader.content.value.keywords.join(' ') }}</Text>
                 <Text color="text.second" :size="28">{{ DataDateUtils.formatDate(loader.content.value.publishAt, 'YYYY-MM-dd') }}</Text>
@@ -107,8 +107,8 @@
             <FlexRow gap="gap.md" align="center">
               <Icon icon="info" size="40" />
               <template v-if="true" >
-                <Text fontConfig="subText" text="本文章仅代表作者个人观点," />
-                <Text fontConfig="subText" bold text="暂未通过村(社区)审核" />
+                <Text fontConfig="subText" fontSize="fontSize.sm" text="本文章仅代表作者个人观点," />
+                <Text fontConfig="subText" fontSize="fontSize.sm" bold text="暂未通过村(社区)审核" />
               </template>
               <Text v-else fontConfig="subText" text="本文章仅代表作者个人观点" />
             </FlexRow>
@@ -116,7 +116,7 @@
           
           <!-- 推荐 -->
           <FlexCol v-if="recommendListLoader.content.value?.length" :padding="30">
-            <H5>相关推荐</H5>
+            <H5 fontFamily="SongtiSCBlack">相关推荐</H5>
             <Box2LineImageRightShadow
               titleColor="title-text"
               v-for="item in recommendListLoader.content.value"
@@ -158,7 +158,7 @@ import FlexCol from "@/components/layout/FlexCol.vue";
 import Image from "@/components/basic/Image.vue";
 import Text from "@/components/basic/Text.vue";
 import H5 from "@/components/typography/H5.vue";
-import H3 from "@/components/typography/H3.vue";
+import H4 from "@/components/typography/H4.vue";
 import Avatar from "@/components/display/Avatar.vue";
 import Touchable from "@/components/feedback/Touchable.vue";
 import StatusBarSpace from "@/components/layout/space/StatusBarSpace.vue";

+ 10 - 129
src/pages/home/index.vue

@@ -163,89 +163,11 @@
       />
     </view>
 
-    <FlexCol padding="padding.md">
-      <SimplePageListLoader v-if="recommendTabCurrent === 0" :loader="recommendLoader">
-        <MasonryGrid :items="recommendLoader.list.value" itemKey="id">
-          <template #default="{ item }">
-            <IndexCommonImageItem
-              :width="354"
-              :image="item.image"
-              :title="item.title"
-              :desc="item.content ?? ''"
-              :userName="item.villageVolunteerName ?? ''"
-              :userAvatar="item.villageVolunteerAvatar"
-              :likes="item.likeNum"
-              :isLike="item.likeType === 1"
-              @click="handleGoRecommendDetails(item)"
-            />
-          </template>
-        </MasonryGrid>
-      </SimplePageListLoader>
-      <SimplePageListLoader v-else-if="recommendTabCurrent === 1" :loader="goodsLoader">
-        <FlexRow wrap justify="space-around" gap="gap.sm">
-          <BoxMid
-            v-for="good in goodsLoader.list.value" :key="good.id"
-            :innerStyle="{
-              width: 'calc(50% - 70rpx)',
-            }"
-          >
-            <Touchable direction="column" gap="gap.lg" @click="handleGoRecommendDetails(good)">
-              <Image 
-                :src="good.image"
-                :radius="20"
-                width="100%"
-                height="300rpx"
-                mode="aspectFill"
-              />
-              <Text :text="good.title" fontConfig="titleText" />
-              <FlexRow align="center" gap="gap.md">
-                <Avatar 
-                  :src="good.villageVolunteerAvatar"
-                  :size="40"
-                  defaultAvatar="https://xy.wenlvti.net/app_static/images/mine/DefaultAvatar.png"
-                />
-                <Text :text="`发布人: ${good.villageVolunteerName}`" fontConfig="contentText" />
-              </FlexRow>
-            </Touchable>
-          </BoxMid>
-          <FlexCol v-if="goodsLoader.list.value && goodsLoader.list.value.length % 2 !== 0" width="calc(50%)" />
-        </FlexRow>
-      </SimplePageListLoader>
-      <SimplePageListLoader v-else-if="recommendTabCurrent === 2" :loader="travelLoader">
-        <FlexRow wrap justify="space-between" gap="gap.sm">
-          <IndexCommonImageItem
-            v-for="item in travelLoader.list.value" :key="item.id"
-            :width="354"
-            fixHeight
-            :image="item.image"
-            :title="item.title"
-            :desc="item.content ?? ''"
-            :userName="item.villageVolunteerName ?? ''"
-            :userAvatar="item.villageVolunteerAvatar"
-            :likes="item.likeNum"
-            :isLike="item.likeType === 1"
-            @click="handleGoRecommendDetails(item)"
-          />
-        </FlexRow>
-      </SimplePageListLoader>
-      <SimplePageListLoader v-else-if="recommendTabCurrent === 3" :loader="culturalLoader">
-        <FlexRow wrap justify="space-between" gap="gap.sm">
-          <IndexCommonImageItem
-            v-for="item in culturalLoader.list.value" :key="item.id"
-            :width="354"
-            fixHeight
-            :image="item.image"
-            :title="item.title"
-            :desc="item.content ?? ''"
-            :userName="item.villageVolunteerName ?? ''"
-            :userAvatar="item.villageVolunteerAvatar"
-            :likes="item.likeNum"
-            :isLike="item.likeType === 1"
-            @click="handleGoRecommendDetails(item)"
-          />
-        </FlexRow>
-      </SimplePageListLoader>
-
+    <FlexCol :padding="30">
+      <RecommendTab v-if="recommendTabCurrent === 0" @goDetails="handleGoRecommendDetails" />
+      <GoodsTab v-else-if="recommendTabCurrent === 1" @goDetails="handleGoRecommendDetails" />
+      <TravelTab v-else-if="recommendTabCurrent === 2" @goDetails="handleGoRecommendDetails" />
+      <CulturalTab v-else-if="recommendTabCurrent === 3" @goDetails="handleGoRecommendDetails" />
     </FlexCol>
 
     <Height :height="200" />
@@ -287,13 +209,11 @@ import { useGetCurrentLocation } from './composeabe/GetCurrentLocation';
 import { useAuthStore } from '@/store/auth';
 import { useRequireLogin } from '@/common/composeabe/RequireLogin';
 import { useUserTools } from '@/common/composeabe/UserTools';
-import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
 import { useGetNotice } from './village/composeabe/GetNotice';
 import { waitTimeOut } from '@imengyu/imengyu-utils';
 import { toast, loading, hideLoading, confirm } from '@/components/utils/DialogAction';
 import { navTo } from '@/components/utils/PageAction';
 import { injectAppConfiguration } from '@/api/system/useAppConfiguration';
-import { CollectableModulesIdMap } from '@/common/data/CollectableModulesIdMap';
 import Image from '@/components/basic/Image.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
 import FlexRow from '@/components/layout/FlexRow.vue';
@@ -311,25 +231,22 @@ import NoticeBar from '@/components/display/NoticeBar.vue';
 import StatusBarSpace from '@/components/layout/space/StatusBarSpace.vue';
 import LightVillageApi, { VillageListItem, type VillageMapItem } from '@/api/light/LightVillageApi';
 import Width from '@/components/layout/space/Width.vue';
-import IndexCommonImageItem from '@/common/components/parts/IndexCommonImageItem.vue';
 import IntroClamTip from './village/dialogs/IntroClamTip.vue';
 import MemoryTimeOut from '@/components/composeabe/MemoryTimeOut';
 import ImageSwiper from '@/common/components/parts/ImageSwiper.vue';
-import VillageInfoApi, { type CommonInfoModel } from '@/api/inhert/VillageInfoApi';
-import SimplePageListLoader from '@/components/loader/SimplePageListLoader.vue';
+import { type CommonInfoModel } from '@/api/inhert/VillageInfoApi';
 import PostIndex from './village/dialogs/PostIndex.vue';
 import FrameButton from '@/common/components/FrameButton.vue';
 import type { RegionItem } from '@/api/map/RegionApi';
 import BubbleTip from '@/components/feedback/BubbleTip.vue';
 import BannerApi from '@/api/system/Banner';
 import Tabs from '@/components/nav/Tabs.vue';
-import BoxMid from '@/common/components/box/BoxMid.vue';
-import Touchable from '@/components/feedback/Touchable.vue';
-import Text from '@/components/basic/Text.vue';
-import Avatar from '@/components/display/Avatar.vue';
-import MasonryGrid from '@/components/layout/masonry/MasonryGrid.vue';
 import { DynamicColor, statusBarHeight } from '@/components/theme/ThemeTools';
 import SimpleTransition from '@/components/anim/SimpleTransition.vue';
+import RecommendTab from './recommend/RecommendTab.vue';
+import GoodsTab from './recommend/GoodsTab.vue';
+import TravelTab from './recommend/TravelTab.vue';
+import CulturalTab from './recommend/CulturalTab.vue';
 
 const props = defineProps({
   currentScrollTop: {
@@ -425,42 +342,6 @@ const recommendTabs = ref([
     value: 3,
   },
 ]);
-const recommendLoader = useSimplePageListLoader(20, async (page, pageSize) => {
-  return await VillageInfoApi.getListForDiscover({ page, pageSize });
-}, true);
-const goodsLoader = useSimplePageListLoader(20, async (page, pageSize) => {
-  return await VillageInfoApi.getListForDiscover({
-    page,
-    pageSize, 
-    collectModuleId: CollectableModulesIdMap['goods'],
-  });
-}, false);
-const travelLoader = useSimplePageListLoader(20, async (page, pageSize) => {
-  return await VillageInfoApi.getMiltListForDiscover({
-    page,
-    pageSize, 
-    collectModuleIds: [
-      CollectableModulesIdMap['travel_guide'],
-      CollectableModulesIdMap['route'],
-      CollectableModulesIdMap['environment'],
-      CollectableModulesIdMap['relic'],
-      CollectableModulesIdMap['spots'],
-
-    ],
-  });
-}, true);
-const culturalLoader = useSimplePageListLoader(20, async (page, pageSize) => {
-  return await VillageInfoApi.getMiltListForDiscover({
-    page,
-    pageSize, 
-    collectModuleIds: [
-      CollectableModulesIdMap['cultural'],
-      CollectableModulesIdMap['folk_culture'],
-      CollectableModulesIdMap['story'],
-    ],
-  });
-}, true);
-
 const stickyStyle = themeContext.useThemeStyle({
   position: 'sticky',
   top: (statusBarHeight - 10) + 'px',

+ 44 - 0
src/pages/home/recommend/CulturalTab.vue

@@ -0,0 +1,44 @@
+<template>
+  <SimplePageListLoader :loader="loader">
+    <FlexRow wrap justify="space-between" gap="gap.sm">
+      <IndexCommonImageItem
+        v-for="item in loader.list.value" :key="item.id"
+        :width="340"
+        fixHeight
+        :image="item.image"
+        :title="item.title"
+        :desc="item.content ?? ''"
+        :userName="item.villageVolunteerName ?? ''"
+        :userAvatar="item.villageVolunteerAvatar"
+        :likes="item.likeNum"
+        :isLike="item.likeType === 1"
+        @click="$emit('goDetails', item)"
+      />
+    </FlexRow>
+  </SimplePageListLoader>
+</template>
+
+<script setup lang="ts">
+import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
+import VillageInfoApi, { type CommonInfoModel } from '@/api/inhert/VillageInfoApi';
+import { CollectableModulesIdMap } from '@/common/data/CollectableModulesIdMap';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import IndexCommonImageItem from '@/common/components/parts/IndexCommonImageItem.vue';
+import SimplePageListLoader from '@/components/loader/SimplePageListLoader.vue';
+
+defineEmits<{
+  (e: 'goDetails', item: CommonInfoModel): void;
+}>();
+
+const loader = useSimplePageListLoader(20, async (page, pageSize) => {
+  return await VillageInfoApi.getMiltListForDiscover({
+    page,
+    pageSize,
+    collectModuleIds: [
+      CollectableModulesIdMap['cultural'],
+      CollectableModulesIdMap['folk_culture'],
+      CollectableModulesIdMap['story'],
+    ],
+  });
+});
+</script>

+ 58 - 0
src/pages/home/recommend/GoodsTab.vue

@@ -0,0 +1,58 @@
+<template>
+  <SimplePageListLoader :loader="loader">
+    <FlexRow wrap justify="space-around" gap="gap.sm">
+      <BoxMid
+        v-for="good in loader.list.value" :key="good.id"
+        :innerStyle="{
+          width: 'calc(50% - 70rpx)',
+        }"
+      >
+        <Touchable direction="column" gap="gap.lg" @click="$emit('goDetails', good)">
+          <Image
+            :src="good.image"
+            :radius="20"
+            width="100%"
+            height="300rpx"
+            mode="aspectFill"
+          />
+          <Text :text="good.title" fontConfig="titleText" />
+          <FlexRow align="center" gap="gap.md">
+            <Avatar
+              :src="good.villageVolunteerAvatar"
+              :size="40"
+              defaultAvatar="https://xy.wenlvti.net/app_static/images/mine/DefaultAvatar.png"
+            />
+            <Text :text="`发布人: ${good.villageVolunteerName}`" fontConfig="contentText" />
+          </FlexRow>
+        </Touchable>
+      </BoxMid>
+      <FlexCol v-if="loader.list.value && loader.list.value.length % 2 !== 0" width="calc(50%)" />
+    </FlexRow>
+  </SimplePageListLoader>
+</template>
+
+<script setup lang="ts">
+import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
+import VillageInfoApi, { type CommonInfoModel } from '@/api/inhert/VillageInfoApi';
+import { CollectableModulesIdMap } from '@/common/data/CollectableModulesIdMap';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import BoxMid from '@/common/components/box/BoxMid.vue';
+import Touchable from '@/components/feedback/Touchable.vue';
+import Image from '@/components/basic/Image.vue';
+import Text from '@/components/basic/Text.vue';
+import Avatar from '@/components/display/Avatar.vue';
+import SimplePageListLoader from '@/components/loader/SimplePageListLoader.vue';
+
+defineEmits<{
+  (e: 'goDetails', item: CommonInfoModel): void;
+}>();
+
+const loader = useSimplePageListLoader(20, async (page, pageSize) => {
+  return await VillageInfoApi.getListForDiscover({
+    page,
+    pageSize,
+    collectModuleId: CollectableModulesIdMap['goods'],
+  });
+});
+</script>

+ 35 - 0
src/pages/home/recommend/RecommendTab.vue

@@ -0,0 +1,35 @@
+<template>
+  <SimplePageListLoader :loader="loader">
+    <MasonryGrid :items="loader.list.value" itemKey="id">
+      <template #default="{ item }">
+        <IndexCommonImageItem
+          :width="354"
+          :image="item.image"
+          :title="item.title"
+          :desc="item.content ?? ''"
+          :userName="item.villageVolunteerName ?? ''"
+          :userAvatar="item.villageVolunteerAvatar"
+          :likes="item.likeNum"
+          :isLike="item.likeType === 1"
+          @click="$emit('goDetails', item)"
+        />
+      </template>
+    </MasonryGrid>
+  </SimplePageListLoader>
+</template>
+
+<script setup lang="ts">
+import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
+import VillageInfoApi, { type CommonInfoModel } from '@/api/inhert/VillageInfoApi';
+import IndexCommonImageItem from '@/common/components/parts/IndexCommonImageItem.vue';
+import MasonryGrid from '@/components/layout/masonry/MasonryGrid.vue';
+import SimplePageListLoader from '@/components/loader/SimplePageListLoader.vue';
+
+defineEmits<{
+  (e: 'goDetails', item: CommonInfoModel): void;
+}>();
+
+const loader = useSimplePageListLoader(20, async (page, pageSize) => {
+  return await VillageInfoApi.getListForDiscover({ page, pageSize });
+});
+</script>

+ 46 - 0
src/pages/home/recommend/TravelTab.vue

@@ -0,0 +1,46 @@
+<template>
+  <SimplePageListLoader :loader="loader">
+    <FlexRow wrap justify="space-between" gap="gap.sm">
+      <IndexCommonImageItem
+        v-for="item in loader.list.value" :key="item.id"
+        :width="340"
+        fixHeight
+        :image="item.image"
+        :title="item.title"
+        :desc="item.content ?? ''"
+        :userName="item.villageVolunteerName ?? ''"
+        :userAvatar="item.villageVolunteerAvatar"
+        :likes="item.likeNum"
+        :isLike="item.likeType === 1"
+        @click="$emit('goDetails', item)"
+      />
+    </FlexRow>
+  </SimplePageListLoader>
+</template>
+
+<script setup lang="ts">
+import { useSimplePageListLoader } from '@/components/composeabe/loader/SimplePageListLoader';
+import VillageInfoApi, { type CommonInfoModel } from '@/api/inhert/VillageInfoApi';
+import { CollectableModulesIdMap } from '@/common/data/CollectableModulesIdMap';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import IndexCommonImageItem from '@/common/components/parts/IndexCommonImageItem.vue';
+import SimplePageListLoader from '@/components/loader/SimplePageListLoader.vue';
+
+defineEmits<{
+  (e: 'goDetails', item: CommonInfoModel): void;
+}>();
+
+const loader = useSimplePageListLoader(20, async (page, pageSize) => {
+  return await VillageInfoApi.getMiltListForDiscover({
+    page,
+    pageSize,
+    collectModuleIds: [
+      CollectableModulesIdMap['travel_guide'],
+      CollectableModulesIdMap['route'],
+      CollectableModulesIdMap['environment'],
+      CollectableModulesIdMap['relic'],
+      CollectableModulesIdMap['spots'],
+    ],
+  });
+});
+</script>

+ 3 - 3
src/pages/home/village/bless/my-orders.vue

@@ -19,12 +19,12 @@
           >
             <FlexCol>
               <Text fontConfig="lightImportantTitle" fontFamily="SongtiSCBlack">{{ item.blessName }}</Text>
-              <Text :fontSize="23" :text="`${item.villageName} ${item.addLight}乡源光/${item.addFruit}乡源果`" />
+              <Text fontConfig="subTitle" fontSize="fontSize.sm" wrap :text="`${item.villageName} ${item.addLight}乡源光/${item.addFruit}乡源果`" />
             </FlexCol>
-            <FlexRow gap="gap.xl">
+            <FlexRow gap="gap.xl" align="center">
               <FlexCol align="flex-end">
                 <FlexRow align="center" gap="gap.sm">
-                  <Text :fontSize="23" fontConfig="lightGoldTitle">¥</Text>
+                  <Text fontSize="fontSize.sm" fontConfig="lightGoldTitle">¥</Text>
                   <Text fontConfig="lightGoldTitle">{{ item.amount }}</Text>
                   <Width :width="10" />
                   <Tag size="small" :text="item.statusText" :type="getStatusTypeByStatusText(item.statusText)" />

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

@@ -190,7 +190,7 @@ onMounted(async () => {
   }
   await waitTimeOut(100);
   delayShow.value = true;
-  await waitTimeOut(1000);
+  await waitTimeOut(2500);
   handleTestGoTree();
   delayShowAround.value = true;
 });

+ 20 - 10
src/pages/home/village/introd/card.vue

@@ -79,18 +79,20 @@
         </FlexRow>
       </FlexRow>
 
-      <FlexRow gap="gap.md" justify="space-between" align="flex-start">
+      <FlexView :direction="descOpen ? 'column' : 'row'" gap="gap.md" justify="space-between" align="flex-start">
         <!-- 简介 -->
         <TextEllipsis 
           fontConfig="secondText"
-          :outerProps="{ direction: 'row', width: '490rpx' }"
+          :outerProps="{ direction: 'row', width: descOpen ? '' : '490rpx' }"
           :lines="1" 
           :expandable="(villageInfoLoader.content.value?.desc as string || '').length > 20"
           :text="(villageInfoLoader.content.value?.desc as string) || '暂无简介,欢迎您来编写完善!'"
           wordBreak="break-all"
+          @expand="descOpen = true;"
+          @collapse="descOpen = false;"
         />
         <Button size="mini" icon="edit-filling" text="编辑简介" @click="handleGoEdit" />
-      </FlexRow>
+      </FlexView>
 
       <!-- 状态与申请 -->
       <FlexRow 
@@ -130,7 +132,7 @@
       <FlexRow justify="space-between" align="center">
         <FlexRow align="center" gap="gap.sm">
           <Icon name="https://xy.wenlvti.net/app_static/images/village/IconMap.png" size="fontSize.md" />
-          <Text :text="villageInfoLoader.content.value?.address" fontConfig="contentText" />
+          <Text :text="villageInfoLoader.content.value?.address" fontConfig="contentText" fontSize="fontSize.sm" />
         </FlexRow>
         <Button size="mini" icon="picture" text="村社相册" @click="handleGoGallery" />
       </FlexRow>
@@ -157,14 +159,14 @@
 
       <FlexRow backgroundColor="background.tertiary" radius="radius.md" :padding="[30, 20]">
         <Touchable direction="column" center gap="gap.sm" flexBasis="25%" @click="navTo('/pages/home/village/task/index')">
-          <Text text="乡源光" fontConfig="secondText" />
+          <Text text="乡源光" fontConfig="secondText" fontSize="fontSize.sm" />
           <Text :text="villageInfoLoader.content.value?.light || '0'" fontConfig="importantTitle" />
           <Button type="text" size="mini" text="做任务" @click="navTo('/pages/home/village/task/index')" />
         </Touchable>
         <Divider type="vertical" />
         <FlexCol center gap="gap.sm" flexBasis="25%">
           <Touchable direction="column" center @click="navTo('/pages/home/village/volunteer/list', { villageId: villageStore.currentVillage?.id ?? undefined })">
-            <Text text="乡源人数" fontConfig="contentText" />
+            <Text text="乡源人数" fontConfig="contentText" fontSize="fontSize.sm" />
             <Text :text="villageInfoLoader.content.value?.memberCount|| '0'" fontConfig="importantTitle" />
           </Touchable>
           <WxButton openType="share">
@@ -175,7 +177,7 @@
         <Touchable direction="column" center gap="gap.sm" flexBasis="25%" @click="navTo('/pages/home/village/follow/list', {
           villageId: villageStore.currentVillage?.id ?? undefined,
         })">
-          <Text text="关注人数" fontConfig="contentText" />
+          <Text text="关注人数" fontConfig="contentText" fontSize="fontSize.sm" />
           <Text :text="villageInfoLoader.content.value?.followerCount|| '0'" fontConfig="importantTitle" />
           <Height :size="36" />
         </Touchable>
@@ -185,10 +187,14 @@
           type="text" 
           size="small" 
           textColor="text.title"
-          text="新手上路" 
           rightIcon="arrow-right" 
           @click="handleGoNew()"
-        />
+        >
+          <FlexCol>
+            <Text text="新手" fontConfig="contentText" />
+            <Text text="上路" fontConfig="contentText" />
+          </FlexCol>
+        </Button>
       </FlexRow>
     </BackgroundBox>
 
@@ -404,6 +410,7 @@ import Avatar from '@/components/display/Avatar.vue';
 import ChangeNickDialog from '../dialogs/ChangeNickDialog.vue';
 import StaffInfoDialog from '../dialogs/StaffInfoDialog.vue';
 import ShareQRDialog from '../dialogs/ShareQRDialog.vue';
+import FlexView from '@/components/layout/FlexView.vue';
 
 const emit = defineEmits<{
   (e: 'goTree'): void;
@@ -470,6 +477,7 @@ const isStaff = computed(() => staffInfo.value?.type === 'staff');
 
 const shareQRDialog = ref<InstanceType<typeof ShareQRDialog>>();
 
+const descOpen = ref(false);
 const rankActiveTag = ref('文化积分');
 const listActiveTag = ref('广场');
 
@@ -579,7 +587,9 @@ async function checkIsStaff(needTopic?: boolean) {
     } else {
       const goUpgrade = await confirm({
         title: '提示',
-        content: '您还不是管理员,无法管理贴图哦。您可以联系村社管理员将你添加为管理员,若当前村社暂无管理员,您可以点击“去升级”将您升级为管理员。',
+        content: '您还不是管理员,无法管理'
+          + (needTopic ? '贴图' : '内容') 
+          + '。您可以联系村社管理员将你添加为管理员,若当前村社暂无管理员,您可以点击“去升级”将您升级为管理员。',
         confirmText: '去升级',
         cancelText: '取消',
       });

+ 1 - 1
src/pages/home/village/introd/tree.vue

@@ -136,7 +136,7 @@
           <Image :src="item.image" :width="210" :height="250" radius="radius.md" mode="aspectFill" />
           <BackgroundBox
             backgroundImage="https://xy.wenlvti.net/app_static/images/village/ImageBlessingBar.png"
-            :padding="10"
+            :padding="[0,10]"
             :width="210"
           >
             <Text textAlign="center" :text="item.name" fontConfig="contentText" fontFamily="SongtiSCBlack" color="white" />

+ 2 - 2
src/pages/home/village/rank/components/RankVillageItem.vue

@@ -19,7 +19,7 @@
           height="60rpx"
           center
         >
-          <Text :text="rank" fontConfig="h4" color="white" />
+          <Text :text="rank" fontConfig="h4" color="white" fontFamily="SongtiSCBlack" />
         </BackgroundBox>
         <Image 
           :src="image" 
@@ -43,7 +43,7 @@
           width="100"
         >
           <Image src="https://xy.wenlvti.net/app_static/images/village/IconLight.png" width="30rpx" height="30rpx" mode="aspectFill" />
-          <Text :text="points || 0" fontConfig="contentText" />
+          <Text :text="points || 0" fontConfig="contentText" fontSize="fontSize.sm" />
         </BackgroundBox>
       </FlexRow>
     </Touchable>

+ 2 - 2
src/pages/home/village/rank/components/RankVolunteerItem.vue

@@ -20,7 +20,7 @@
           height="90rpx"
           center
         >
-          <Text :text="rank" fontConfig="h5" color="white" />
+          <Text :text="rank" fontConfig="h5" color="white" fontFamily="SongtiSCBlack" />
         </BackgroundBox>
         <Avatar 
           :url="image" 
@@ -44,7 +44,7 @@
           width="200"
         >
           <Image src="https://xy.wenlvti.net/app_static/images/village/IconFruit.png" width="30rpx" height="30rpx" mode="aspectFill" />
-          <Text :text="`${scoreSuffix} ${score}`" fontConfig="contentText" />
+          <Text :text="`${scoreSuffix} ${score}`" fontConfig="contentText" fontSize="fontSize.sm" />
         </BackgroundBox>
       </FlexRow>
     </BackgroundBox>

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

@@ -23,7 +23,7 @@
                 <Width :size="5" />
                 <FlexCol gap="gap.md">
                   <Text fontConfig="lightImportantTitle" fontFamily="SongtiSCBlack">{{ item.name }}</Text>
-                  <Text :fontSize="23" :text="item.desc" />
+                  <Text fontSize="fontSize.sm" :text="item.desc" />
                   <Text v-if="item.points > 0" fontConfig="secondText">+{{ item.points }}文化积分</Text>
                   <FlexRow align="center" gap="gap.md">
                     <Button v-if="item.rewardFruit > 0" icon="https://xy.wenlvti.net/app_static/images/village/IconFruit.png" size="mini" :text="`+${item.rewardFruit}乡源果`" />

+ 2 - 2
src/pages/home/village/upgrade/my-orders.vue

@@ -19,7 +19,7 @@
           >
             <FlexCol>
               <Text fontConfig="lightImportantTitle" fontFamily="SongtiSCBlack">{{ item.levelName }}</Text>
-              <Text :fontSize="23" :text="`${item.villageName} ${item.vipLevel}级`" />
+              <Text fontSize="fontSize.sm" :text="`${item.villageName} ${item.vipLevel}级`" />
               <Text v-if="item.payType === 1" :fontSize="21" fontConfig="secondText">线上支付</Text>
               <Text v-else-if="item.payType === 2" :fontSize="21" fontConfig="secondText">对公付款</Text>
               <Text v-else-if="item.payType === 3" :fontSize="21" fontConfig="secondText">乡源果支付</Text>
@@ -27,7 +27,7 @@
             <FlexRow gap="gap.xl">
               <FlexCol align="flex-end">
                 <FlexRow align="center" gap="gap.sm">
-                  <Text :fontSize="23" fontConfig="lightGoldTitle">¥</Text>
+                  <Text fontSize="fontSize.sm" fontConfig="lightGoldTitle">¥</Text>
                   <Text fontConfig="lightGoldTitle">{{ item.price }}</Text>
                   <Width :width="10" />
                   <Tag size="small" :text="item.statusText" :type="getStatusTypeByStatusText(item.statusText)" />

+ 1 - 1
src/pages/home/village/volunteer/detail.vue

@@ -17,7 +17,7 @@
           />
           <Width :width="60" />
           <FlexCol gap="gap.md">
-            <H3>{{ infoLoader.content.value.name }}</H3>
+            <H3 fontConfig="lightTitle">{{ infoLoader.content.value.name }}</H3>
             <FlexRow align="center" gap="gap.md">
               <Text text="个人等级" fontConfig="contentText" />
               <Tag :text="(infoLoader.content.value.level || 0) + '级'" />