hookehuyr

feat: 添加权限控制显示兑换相关功能

根据用户角色控制显示兑换按钮和积分信息
在多个组件中添加isOwner/isCreator判断
修改头像显示模式为aspectFill
......@@ -3,8 +3,9 @@
<!-- 中心圆形显示总积分 -->
<view class="center-circle">
<view class="total-points" @tap="handleGoToRewards">
<text v-if="!isOwner" class="family-points-label">家庭总积分</text>
<text class="points-number">{{ animatedTotalPoints }}分</text>
<text class="points-label">去兑换</text>
<text v-if="isOwner" class="points-label">去兑换</text>
</view>
</view>
......@@ -55,7 +56,11 @@ const props = defineProps({
familyId: {
type: [String, Number],
required: true
}
},
isOwner: {
type: Boolean,
default: false
},
})
// 响应式数据
......@@ -80,7 +85,7 @@ const generatePointsData = () => {
if (!props.pendingPoints || props.pendingPoints.length === 0) {
return [];
}
const pointsItems = props.pendingPoints.map(item => ({
id: item.id,
points: parseInt(item.points),
......@@ -335,6 +340,9 @@ useDidShow(() => {
* 处理去兑换点击事件
*/
const handleGoToRewards = () => {
if (!props.isOwner) {
return
}
Taro.navigateTo({
url: '/pages/RewardCategories/index',
})
......@@ -382,7 +390,14 @@ const handleGoToRewards = () => {
.points-label {
display: block;
font-size: 24rpx;
margin-top: 8rpx;
margin-top: 10rpx;
opacity: 0.9;
}
.family-points-label {
display: block;
font-size: 24rpx;
margin-bottom: 10rpx;
opacity: 0.9;
}
......
......@@ -3,8 +3,9 @@
<!-- 中心圆形显示总积分 -->
<view class="center-circle1">
<view class="total-points" @tap="handleGoToRewards">
<text v-if="!isOwner" class="family-points-label">家庭总积分</text>
<text class="points-number">{{ animatedTotalPoints }}分</text>
<text class="points-label">去兑换</text>
<text v-if="isOwner" class="points-label">去兑换</text>
</view>
</view>
</view>
......@@ -24,6 +25,10 @@ const props = defineProps({
height: {
type: String,
default: '30vh'
},
isOwner: {
type: Boolean,
default: false
}
})
......@@ -72,6 +77,9 @@ onMounted(() => {
* 处理去兑换点击事件
*/
const handleGoToRewards = () => {
if (!props.isOwner) {
return
}
Taro.navigateTo({
url: '/pages/RewardCategories/index',
})
......@@ -116,10 +124,17 @@ const handleGoToRewards = () => {
line-height: 1;
}
.family-points-label {
display: block;
font-size: 24rpx;
margin-bottom: 10rpx;
opacity: 0.9;
}
.points-label {
display: block;
font-size: 24rpx;
margin-top: 8rpx;
margin-top: 10rpx;
opacity: 0.9;
}
......
......@@ -55,12 +55,14 @@
:total-points="finalTotalPoints"
:pending-points="pendingPoints"
:family-id="family_id"
:is-owner="familyOwner"
@collection-complete="handleCollectionComplete"
/>
</template>
<template v-else>
<TotalPointsDisplay
:total-points="finalTotalPoints"
:is-owner="familyOwner"
height="13vh"
/>
</template>
......@@ -86,7 +88,7 @@
</view>
<view class="grid grid-cols-4 gap-2">
<view v-for="member in familyMembers" :key="member.user_id" class="flex flex-col items-center">
<image :src="member.avatar_url || defaultAvatar" :alt="member.role" class="w-16 h-16 rounded-full mb-1" />
<image :src="member.avatar_url || defaultAvatar" mode="aspectFill" :alt="member.role" class="w-16 h-16 rounded-full mb-1" />
<span class="text-sm text-gray-700">
{{ member?.today_step?.toLocaleString() }}步
</span>
......
<!--
* @Date: 2025-08-27 17:47:46
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-03 20:02:11
* @LastEditTime: 2025-09-03 21:30:51
* @FilePath: /lls_program/src/pages/Profile/index.vue
* @Description: 文件描述
-->
......@@ -14,7 +14,7 @@
<!-- User profile section -->
<view class="px-4 pt-8 pb-6 flex items-center justify-between">
<view class="flex items-center">
<image :src="userInfo.avatarUrl || defaultAvatar" alt="User avatar" class="w-16 h-16 rounded-full border-2 border-white" />
<image :src="userInfo.avatarUrl || defaultAvatar" alt="User avatar" mode="aspectFill" class="w-16 h-16 rounded-full border-2 border-white" />
<view class="ml-4">
<h1 class="text-xl font-bold text-white">{{ userInfo.nickName }}</h1>
</view>
......
......@@ -54,7 +54,7 @@
</view>
<!-- Bottom Button -->
<view class="fixed bottom-0 left-0 right-0 p-4 bg-white border-t border-gray-100">
<view v-if="isCreator" class="fixed bottom-0 left-0 right-0 p-4 bg-white border-t border-gray-100">
<nut-button type="primary" size="large" block color="#3B82F6" @click="handleRedeem">
立即兑换
</nut-button>
......@@ -64,8 +64,11 @@
<script setup>
import { ref } from 'vue';
import Taro from '@tarojs/taro';
import Taro, { useDidShow } from '@tarojs/taro';
import AppHeader from '../../components/AppHeader.vue';
import { getUserProfileAPI } from '@/api/user';
const isCreator = ref(false);
// Mock reward data based on the image
const reward = ref({
......@@ -120,4 +123,21 @@ const handleRedeem = () => {
}
});
};
const initData = async () => {
// 获取用户信息,判断是否为创建者
try {
const { code, data } = await getUserProfileAPI();
if (code) {
isCreator.value = data?.user?.is_creator || false;
}
} catch (error) {
console.error('获取用户信息失败:', error);
isCreator.value = false;
}
};
useDidShow(() => {
initData();
});
</script>
......
<!--
* @Date: 2025-08-27 17:47:26
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-08-29 20:32:08
* @LastEditTime: 2025-09-03 21:43:41
* @FilePath: /lls_program/src/pages/Rewards/index.vue
* @Description: 文件描述
-->
<template>
<view class="min-h-screen flex flex-col bg-white">
<!-- Blue header background -->
<view class="bg-blue-500 h-48 absolute w-full top-0 left-0 z-0"></view>
<view v-if="isCreator" class="bg-blue-500 h-48 absolute w-full top-0 left-0 z-0"></view>
<!-- <AppHeader title="兑换中心" :showBack="false" /> -->
<!-- Content -->
<view class="relative z-10 flex-1 pb-20">
<!-- Points display -->
<view class="pt-8 pb-8 flex flex-col items-center">
<view v-if="isCreator" class="pt-8 pb-8 flex flex-col items-center">
<h2 class="text-4xl font-bold text-white mb-1">{{ totalPoints }}分</h2>
<p class="text-white text-opacity-80">我的积分</p>
</view>
......@@ -60,7 +60,7 @@
</view>
<view class="ml-4 px-4 py-2 bg-blue-500 text-white rounded-lg text-sm flex-shrink-0"
@click="goToRewardDetail(reward)">
{{ reward.points }}分兑换
{{ isCreator ? reward.points + '分兑换' : '查看' }}
</view>
</view>
</view>
......@@ -74,12 +74,14 @@
import { ref, computed, onMounted } from 'vue';
import Taro, { useDidShow } from '@tarojs/taro';
import { ScreenLittle, Search2 } from '@nutui/icons-vue-taro';
import { getUserProfileAPI } from '@/api/user';
const searchQuery = ref('');
const selectedPoints = ref(null);
const sortOrder = ref('desc'); // 'asc' or 'desc'
const totalPoints = ref(0);
const isCreator = ref(false);
const sortedRewardItems = computed(() => {
let items = [...rewardItems.value];
......@@ -156,7 +158,20 @@ const goToRewardDetail = (reward) => {
};
const initData = async () => {
totalPoints.value = '9856';
// 获取用户信息,判断是否为创建者
try {
const { code, data } = await getUserProfileAPI();
if (code) {
isCreator.value = data?.user?.is_creator || false;
// 只有创建者才显示积分
if (isCreator.value) {
totalPoints.value = '9856';
}
}
} catch (error) {
console.error('获取用户信息失败:', error);
isCreator.value = false;
}
console.warn('初始化数据')
}
......
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-03 17:02:11
* @LastEditTime: 2025-09-03 21:05:25
* @FilePath: /lls_program/src/pages/auth/index.vue
* @Description: 文件描述
-->
......