快乐的梦鱼 3 тижнів тому
батько
коміт
9400773661

+ 3 - 0
src/common/components/parts/HomeTitle.vue

@@ -17,6 +17,9 @@
         <Text v-if="titleEnd" :text="titleEnd" fontConfig="primaryTitle" color="#5f3f2c" />
       </FlexRow>
     </template>
+    <template #right>
+      <slot name="right" />
+    </template>
   </SubTitle>
 </template>
 

+ 21 - 0
src/components/basic/BackgroundImageButton.vue

@@ -0,0 +1,21 @@
+<template>
+  <Touchable :activeOpacity="activeOpacity" @click="emit('click')">
+    <BackgroundBox v-bind="props">
+      <slot />
+    </BackgroundBox>
+  </Touchable>
+</template>
+
+<script setup lang="ts">
+import BackgroundBox, { type BackgroundBoxProps } from '../display/block/BackgroundBox.vue';
+import Touchable from '../feedback/Touchable.vue';
+
+const props = withDefaults(defineProps<BackgroundBoxProps & {
+  activeOpacity?: number;
+}>(), {
+  activeOpacity: 0.7,
+});
+
+const emit = defineEmits(['click']);
+
+</script>

+ 44 - 31
src/components/basic/Image.vue

@@ -6,37 +6,39 @@
     :class="innerClass"
     @click="handleClick"
   >
-    <view v-if="showBackgroundEffect" :style="(backgroundEffectStyle as any)">
-    </view>
-    <view v-if="showBackgroundEffect" :style="(backgroundEffectStyle2 as any)">
-    </view>
-    <image 
-      :style="{
-        width: precentOrFull(style.width),
-        height: precentOrFull(style.height),
-        borderRadius: themeContext.resolveThemeSize(props.radius),
-      }"
-      :mode="(mode as any)"
-      :lazyLoad="$attrs.lazyLoad"
-      :fadeShow="$attrs.fadeShow"
-      :webp="$attrs.webp"
-      :show-menu-by-longpress="$attrs.showMenuByLongpress"
-      :draggable="$attrs.draggable"
-      :src="isErrorState ? failedImage : (src || defaultImage)"
-      @loadstart="isLoadState = true"
-      @load="isLoadState = false"
-      @error="isErrorState = true; isLoadState = false"
-    />
-    <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" />
-    </view>
-    <view v-if="showLoading && isLoadState" class="inner-view loading">
-      <ActivityIndicator
-        :color="themeContext.resolveThemeColor(loadingColor)"
-        :size="themeContext.resolveThemeSize(loadingSize)"
+    <template v-if="mode !== 'borderImage'">
+      <view v-if="showBackgroundEffect" :style="(backgroundEffectStyle as any)">
+      </view>
+      <view v-if="showBackgroundEffect" :style="(backgroundEffectStyle2 as any)">
+      </view>
+      <image 
+        :style="{
+          width: precentOrFull(style.width),
+          height: precentOrFull(style.height),
+          borderRadius: themeContext.resolveThemeSize(props.radius),
+        }"
+        :mode="(mode as any)"
+        :lazyLoad="$attrs.lazyLoad"
+        :fadeShow="$attrs.fadeShow"
+        :webp="$attrs.webp"
+        :show-menu-by-longpress="$attrs.showMenuByLongpress"
+        :draggable="$attrs.draggable"
+        :src="isErrorState ? failedImage : (src || defaultImage)"
+        @loadstart="isLoadState = true"
+        @load="isLoadState = false"
+        @error="isErrorState = true; isLoadState = false"
       />
-    </view>
+      <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" />
+      </view>
+      <view v-if="showLoading && isLoadState" class="inner-view loading">
+        <ActivityIndicator
+          :color="themeContext.resolveThemeColor(loadingColor)"
+          :size="themeContext.resolveThemeSize(loadingSize)"
+        />
+      </view>
+    </template>
     <slot v-if="!src && !defaultImage" name="empty"></slot>
     <slot />
   </view>
@@ -111,11 +113,16 @@ export interface ImageProps {
    * @default 0
    */
   radius?: string|number,
+
+  borderImageSlice?: number,
+  borderImageRepeat?: 'stretch' | 'repeat' | 'round',
+  borderImageWidth?: number,
+
   /**
    * 内部样式
    */
   innerStyle?: object;
-  mode?: 'aspectFill' | 'aspectFit' | 'widthFix' | 'heightFix' | 'top' | 'bottom' | 'left' | 'right' | 'center',
+  mode?: 'aspectFill' | 'aspectFit' | 'widthFix' | 'heightFix' | 'top' | 'bottom' | 'left' | 'right' | 'center' | 'borderImage',
   innerClass?: string,
 }
 
@@ -159,6 +166,12 @@ const style = computed(() => {
     height: themeContext.resolveThemeSize(props.height),
     ...props.innerStyle,
   }
+  if (props.mode === 'borderImage') {
+    o.borderImageSource = `url('${props.src || props.defaultImage}')`;
+    o.borderImageSlice = props.borderImageSlice;
+    o.borderImageRepeat = props.borderImageRepeat;
+    o.borderImageWidth = props.borderImageWidth;
+  }
   return o;
 });
 const backgroundEffectStyle = computed(() => ({

+ 1 - 0
src/components/basic/ImageButton.vue

@@ -1,6 +1,7 @@
 <template>
   <Touchable :activeOpacity="activeOpacity" @click="emit('click')">
     <Image v-bind="props" />
+    <slot />
   </Touchable>
 </template>
 

+ 13 - 1
src/pages/home/village/introd/card.vue

@@ -124,7 +124,17 @@
     <VillageUserRankList />
 
     <!-- 魅力乡源 -->
-    <HomeTitle title="魅力乡源" />
+    <HomeTitle title="魅力乡源">
+      <template #right>
+        <BackgroundImageButton 
+          backgroundImage="https://xy.wenlvti.net/app_static/images/village/TagActive.png"
+          :backgroundCutBorder="[10, 10, 10, 10]"
+          :padding="[15, 20]"
+        >
+          <Text text="120乡源果兑换" fontConfig="contentText" color="white" />
+        </BackgroundImageButton>
+      </template>
+    </HomeTitle>
 
     <!-- 活力乡源 -->
     <HomeTitle title="活力乡源" />
@@ -155,6 +165,8 @@ import VillageRankList from '../../components/VillageRankList.vue';
 import RoundTags from '@/common/components/parts/RoundTags.vue';
 import VillageUserRankList from '../../components/VillageUserRankList.vue';
 import { ref } from 'vue';
+import ImageButton from '@/components/basic/ImageButton.vue';
+import BackgroundImageButton from '@/components/basic/BackgroundImageButton.vue';
 
 const villageInfoLoader = useSimpleDataLoader(async () => {
   return {