hookehuyr

refactor: 将本地图片资源替换为CDN链接并优化页面样式

重构多个页面的图片资源引用,将本地图片替换为CDN链接
优化ActivitiesCover页面布局和样式,简化海报展示逻辑
更新MyFamily页面数据获取逻辑,使用真实API数据
删除不再使用的本地图片资源文件
<svg width="400" height="200" viewBox="0 0 400 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- 背景渐变 -->
<defs>
<linearGradient id="bg-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#E3F2FD;stop-opacity:1" />
<stop offset="100%" style="stop-color:#BBDEFB;stop-opacity:1" />
</linearGradient>
</defs>
<!-- 背景 -->
<rect width="400" height="200" fill="url(#bg-gradient)"/>
<!-- 房子图标 -->
<g transform="translate(150, 60)">
<!-- 房子主体 -->
<rect x="20" y="40" width="60" height="50" fill="#FFF3E0" stroke="#FF9800" stroke-width="2" rx="4"/>
<!-- 屋顶 -->
<polygon points="10,45 50,15 90,45" fill="#FF5722" stroke="#D84315" stroke-width="2"/>
<!-- 门 -->
<rect x="35" y="65" width="15" height="25" fill="#8D6E63" rx="2"/>
<circle cx="46" cy="77" r="1.5" fill="#FFF"/>
<!-- 窗户 -->
<rect x="25" y="50" width="12" height="10" fill="#81D4FA" stroke="#0277BD" stroke-width="1" rx="1"/>
<rect x="63" y="50" width="12" height="10" fill="#81D4FA" stroke="#0277BD" stroke-width="1" rx="1"/>
<!-- 窗户十字 -->
<line x1="31" y1="50" x2="31" y2="60" stroke="#0277BD" stroke-width="0.5"/>
<line x1="25" y1="55" x2="37" y2="55" stroke="#0277BD" stroke-width="0.5"/>
<line x1="69" y1="50" x2="69" y2="60" stroke="#0277BD" stroke-width="0.5"/>
<line x1="63" y1="55" x2="75" y2="55" stroke="#0277BD" stroke-width="0.5"/>
</g>
<!-- 文字 -->
<text x="200" y="130" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#666" font-weight="500">温馨家庭</text>
<text x="200" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#999">点击上传家庭封面图</text>
</svg>
\ No newline at end of file
<!--
* @Date: 2025-08-27 17:44:10
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-08-29 11:35:46
* @LastEditTime: 2025-09-02 21:37:13
* @FilePath: /lls_program/src/components/BottomNav.vue
* @Description: 文件描述
-->
......@@ -23,14 +23,15 @@
<script setup>
import { computed, shallowRef } from 'vue';
import Taro from '@tarojs/taro';
import homeIcon from '@/assets/images/icon/home.svg';
import homeIconActive from '@/assets/images/icon/home_active.svg';
import rewardsIcon from '@/assets/images/icon/rewards.svg';
import rewardsIconActive from '@/assets/images/icon/rewards_active.svg';
import activitiesIcon from '@/assets/images/icon/activities.svg';
import activitiesIconActive from '@/assets/images/icon/activities_active.svg';
import meIcon from '@/assets/images/icon/me.svg';
import meIconActive from '@/assets/images/icon/me_active.svg';
//
const homeIcon = 'https://cdn.ipadbiz.cn/lls_prog/icon/home.svg';
const homeIconActive = 'https://cdn.ipadbiz.cn/lls_prog/icon/home_active.svg';
const rewardsIcon = 'https://cdn.ipadbiz.cn/lls_prog/icon/rewards.svg';
const rewardsIconActive = 'https://cdn.ipadbiz.cn/lls_prog/icon/rewards_active.svg';
const activitiesIcon = 'https://cdn.ipadbiz.cn/lls_prog/icon/activities.svg';
const activitiesIconActive = 'https://cdn.ipadbiz.cn/lls_prog/icon/activities_active.svg';
const meIcon = 'https://cdn.ipadbiz.cn/lls_prog/icon/me.svg';
const meIconActive = 'https://cdn.ipadbiz.cn/lls_prog/icon/me_active.svg';
const navItems = shallowRef([
{ path: '/pages/Dashboard/index', icon: homeIcon, activeIcon: homeIconActive, label: '首页' },
......
.activities-cover-container {
width: 100%;
min-height: 100vh;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
}
// 海报区域
.poster-section {
position: relative;
width: 100%;
height: 500rpx;
height: 100vh;
overflow: hidden;
}
.poster-image {
// 背景图片
.background-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-fit: contain;
object-position: top center;
z-index: 1;
}
.poster-overlay {
// 为容器添加背景色,避免下方空白
.activities-cover-container::before {
content: '';
position: absolute;
bottom: 0;
top: 0;
left: 0;
right: 0;
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
padding: 60rpx 40rpx 40rpx;
color: white;
}
.activity-title {
font-size: 48rpx;
font-weight: bold;
margin-bottom: 16rpx;
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.5);
}
.activity-subtitle {
font-size: 28rpx;
margin-bottom: 12rpx;
opacity: 0.9;
}
.activity-date {
font-size: 24rpx;
opacity: 0.8;
display: flex;
align-items: center;
&::before {
content: '📅';
margin-right: 8rpx;
}
width: 100%;
height: 100%;
background: linear-gradient(180deg, #f0f8ff 0%, #e6f3ff 50%, #ddeeff 100%);
z-index: 0;
}
// 分享按钮
......@@ -62,114 +36,32 @@
right: 40rpx;
width: 80rpx;
height: 80rpx;
background-color: rgba(0, 0, 0, 0.5);
background-color: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 32rpx;
font-size: 28rpx;
z-index: 10;
backdrop-filter: blur(10rpx);
&:active {
background-color: rgba(0, 0, 0, 0.7);
background-color: rgba(0, 0, 0, 0.8);
}
}
// 详情区域
.details-section {
flex: 1;
padding: 40rpx;
background-color: white;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin: 40rpx 0 24rpx 0;
position: relative;
&:first-child {
margin-top: 0;
}
&::before {
content: '';
position: absolute;
left: -16rpx;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 24rpx;
background-color: #1890ff;
border-radius: 3rpx;
}
}
.activity-description {
font-size: 28rpx;
line-height: 1.6;
color: #666;
margin-bottom: 20rpx;
}
.rules-list {
margin-bottom: 20rpx;
}
.rule-item {
font-size: 26rpx;
line-height: 1.5;
color: #666;
margin-bottom: 16rpx;
padding-left: 20rpx;
position: relative;
&::before {
content: '';
position: absolute;
left: 0;
top: 20rpx;
width: 8rpx;
height: 8rpx;
background-color: #1890ff;
border-radius: 50%;
}
}
.rewards-list {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.reward-item {
display: flex;
align-items: center;
padding: 20rpx;
background-color: #f8f9fa;
border-radius: 12rpx;
border-left: 6rpx solid #52c41a;
}
.reward-icon {
font-size: 32rpx;
margin-right: 16rpx;
}
.reward-text {
font-size: 26rpx;
color: #333;
flex: 1;
}
// 底部区域
.bottom-section {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 40rpx;
padding-bottom: 180rpx; // 为底部导航留出空间
background-color: white;
border-top: 1rpx solid #f0f0f0;
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
backdrop-filter: blur(20rpx);
z-index: 5;
}
.location-tip {
......@@ -177,10 +69,11 @@
align-items: center;
justify-content: center;
padding: 24rpx;
background-color: #fff7e6;
border: 1rpx solid #ffd591;
background-color: rgba(255, 247, 230, 0.9);
border: 1rpx solid rgba(255, 213, 145, 0.8);
border-radius: 12rpx;
margin-bottom: 32rpx;
backdrop-filter: blur(10rpx);
}
.tip-icon {
......@@ -191,6 +84,7 @@
.tip-text {
font-size: 26rpx;
color: #d46b08;
font-weight: 500;
}
.join-button {
......@@ -198,7 +92,14 @@
height: 88rpx;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: bold;
font-weight: 600;
box-shadow: 0 8rpx 24rpx rgba(59, 130, 246, 0.4);
backdrop-filter: blur(10rpx);
&:active {
transform: translateY(2rpx);
box-shadow: 0 4rpx 12rpx rgba(59, 130, 246, 0.3);
}
&.nut-button--primary {
background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
......@@ -314,9 +215,3 @@
border: none;
}
}
.join-button {
&.nut-button--loading {
opacity: 0.7;
}
}
......
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-02 15:27:05
* @LastEditTime: 2025-09-02 21:39:49
* @FilePath: /lls_program/src/pages/ActivitiesCover/index.vue
* @Description: 活动海报页面 - 展示活动信息并处理定位授权
-->
<template>
<view class="activities-cover-container">
<!-- 活动海报区域 -->
<view class="poster-section">
<image
:src="activityData.posterUrl"
class="poster-image"
mode="aspectFill"
/>
<!-- 活动信息覆盖层 -->
<view class="poster-overlay">
<view class="activity-title">{{ activityData.title }}</view>
<view class="activity-subtitle">{{ activityData.subtitle }}</view>
<view class="activity-date">{{ activityData.dateRange }}</view>
</view>
<!-- 分享按钮 -->
<view @tap="shareActivity" class="share-button">
<!-- <nut-icon name="share" color="white" size="20" /> -->
<text>分享</text>
</view>
</view>
<!-- 活动详情区域 -->
<view class="details-section">
<view class="section-title">活动详情</view>
<view class="activity-description">{{ activityData.description }}</view>
<view class="section-title">参与规则</view>
<view class="rules-list">
<view
v-for="(rule, index) in activityData.rules"
:key="index"
class="rule-item"
>
{{ index + 1 }}. {{ rule }}
</view>
</view>
<!-- 背景图片 -->
<image
:src="defaultPoster"
class="background-image"
mode="scaleToFill"
/>
<view class="section-title">活动奖励</view>
<view class="rewards-list">
<view
v-for="(reward, index) in activityData.rewards"
:key="index"
class="reward-item"
>
<view class="reward-icon">🏆</view>
<view class="reward-text">{{ reward }}</view>
</view>
</view>
<!-- 分享按钮 -->
<view @tap="shareActivity" class="share-button">
<text>分享</text>
</view>
<!-- 底部按钮区域 -->
......@@ -129,7 +90,11 @@ import Taro from '@tarojs/taro'
import "./index.less"
import BottomNav from '../../components/BottomNav.vue'
import PosterBuilder from '../../components/PosterBuilder/index.vue'
// 接口信息
import { getMyFamiliesAPI } from '@/api/family'
// 默认海报图
const defaultPoster = 'https://cdn.ipadbiz.cn/lls_prog/images/welcome.png';
/**
* 活动海报页面组件
* 功能:展示活动信息、处理定位授权、跳转到活动页面
......@@ -630,9 +595,15 @@ const savePoster = () => {
}
// 页面挂载时检查定位授权状态
onMounted(() => {
// TODO: 是否加入家庭
hasJoinedFamily.value = Math.random > 0.5 ? true : false;
onMounted(async () => {
// 获取用户是否加入家庭
const { code, data } = await getMyFamiliesAPI()
if (code) {
// 如果加入家庭
if (data.length) {
hasJoinedFamily.value = true
}
}
// 检查定位授权弹窗
checkLocationAuth()
})
......
<!--
* @Date: 2025-08-27 17:44:53
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-02 17:52:24
* @LastEditTime: 2025-09-02 21:40:15
* @FilePath: /lls_program/src/pages/CreateFamily/index.vue
* @Description: 文件描述
-->
......@@ -174,10 +174,10 @@ import { ref, nextTick, computed } from 'vue';
import Taro from '@tarojs/taro';
import { Tips, Photograph, Right } from '@nutui/icons-vue-taro';
import BASE_URL from '@/utils/config';
import defaultFamilyCoverSvg from '@/assets/images/default-family-cover.png';
// 接口信息
import { createFamilyAPI } from '@/api/family';
const defaultFamilyCoverSvg = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png';
const familyName = ref('');
const familyIntro = ref('');
const selectedDistrict = ref(null);
......
......@@ -202,7 +202,7 @@ import PointsCollector from '@/components/PointsCollector.vue'
import WeRunAuth from '@/components/WeRunAuth.vue'
import { useMediaPreview } from '@/composables/useMediaPreview';
// 默认家庭封面图
import defaultFamilyCover from '@/assets/images/default-family-cover.png';
const defaultFamilyCover = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png';
// 默认头像
const defaultAvatar = 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
// 接口信息
......@@ -393,7 +393,7 @@ useDidShow(async () => {
return; // 直接返回,不执行后续逻辑
}
}
// 只有在用户已加入家庭的情况下才初始化页面数据
initPageData();
......
<!--
* @Date: 2025-08-27 17:44:53
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-02 20:00:30
* @LastEditTime: 2025-09-02 21:41:17
* @FilePath: /lls_program/src/pages/EditFamily/index.vue
* @Description: 文件描述
-->
......@@ -173,7 +173,8 @@ import Taro from '@tarojs/taro';
import { Edit, Tips, Photograph, Right } from '@nutui/icons-vue-taro';
// import AppHeader from '../../components/AppHeader.vue';
import BASE_URL from '@/utils/config';
import defaultFamilyCoverSvg from '@/assets/images/default-family-cover.png';
//
const defaultFamilyCoverSvg = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png';
const familyName = ref('');
const familyIntro = ref('');
......
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-02 14:42:39
* @LastEditTime: 2025-09-02 21:45:14
* @FilePath: /lls_program/src/pages/MyFamily/index.vue
* @Description: 我的家庭页面 - 展示用户加入的家庭列表
-->
......@@ -18,7 +18,7 @@
<view class="relative">
<!-- 当前家庭标记 -->
<view
v-if="family.isCurrent"
v-if="family.is_in"
class="absolute top-2 right-2 bg-blue-500 text-white text-xs px-2 py-1 rounded-sm z-10"
>
当前家庭
......@@ -26,7 +26,7 @@
<!-- 封面图 -->
<image
:src="family.coverImage"
:src="family.avatar_url || defaultFamilyCoverSvg"
class="w-full h-44 object-cover"
mode="aspectFill"
/>
......@@ -46,7 +46,7 @@
<!-- 成员头像叠加效果 -->
<view class="avatar-overlap">
<image
v-for="(member, index) in family.members.slice(0, 4)"
v-for="(member, index) in family?.members?.slice(0, 4) || []"
:key="member.id"
:src="member.avatar"
class="avatar-item w-8 h-8 rounded-full border-2 border-white object-cover"
......@@ -54,16 +54,16 @@
/>
<!-- 更多成员数量显示 -->
<view
v-if="family.members.length > 4"
v-if="family?.members?.length > 4"
class="w-8 h-8 rounded-full bg-gray-300 border-2 border-white flex items-center justify-center text-xs text-gray-600"
:style="{ zIndex: 6 }"
>
+{{ family.members.length - 4 }}
+{{ family?.members?.length - 4 }}
</view>
</view>
<!-- 总成员数 -->
<view class="ml-3 text-sm text-gray-600">
{{ family.members.length }} 位家庭成员
{{ family?.members?.length || 0 }} 位家庭成员
</view>
</view>
</view>
......@@ -71,7 +71,7 @@
<!-- 操作按钮 -->
<view class="flex gap-3 justify-end">
<view
v-if="!family.isCurrent"
v-if="!family.is_in"
@tap="switchToFamily(family.id)"
class="px-4 py-2 bg-blue-500 text-white text-sm rounded-lg"
>
......@@ -93,7 +93,6 @@
<Home size="48" />
</view>
<view class="text-gray-500 mb-2">您还没有加入任何家庭</view>
<view class="text-gray-400 text-sm">点击下方按钮加入家庭,开始健康之旅</view>
</view>
</view>
......@@ -116,6 +115,10 @@ import { ref, onMounted, computed } from 'vue';
import Taro, { useDidShow } from '@tarojs/taro';
import { Home } from '@nutui/icons-vue-taro';
import './index.less';
import { getMyFamiliesAPI } from '@/api/family';
//
const defaultFamilyCoverSvg = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png';
// 获取接口数据
// 响应式数据
const familyList = ref([]);
......@@ -123,44 +126,49 @@ const familyList = ref([]);
/**
* 初始化页面数据
*/
const initPageData = () => {
const initPageData = async () => {
const { code, data } = await getMyFamiliesAPI();
if (code) {
familyList.value = data;
console.warn(data);
}
// 模拟家庭数据
familyList.value = [
{
id: 1,
name: '幸福之家',
ownerName: '张明明',
coverImage: 'https://images.unsplash.com/photo-1511895426328-dc8714191300?w=400&h=200&fit=crop',
isCurrent: true,
members: [
{ id: 1, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' },
{ id: 2, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' },
{ id: 3, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' }
]
},
{
id: 2,
name: '欢乐之家',
ownerName: '李志强',
coverImage: 'https://images.unsplash.com/photo-1502086223501-7ea6ecd79368?w=400&h=200&fit=crop',
isCurrent: false,
members: [
{ id: 4, avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face' },
{ id: 5, avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face' }
]
},
{
id: 3,
name: '快乐之家',
ownerName: '王芳',
coverImage: 'https://images.unsplash.com/photo-1502086223501-7ea6ecd79368?w=400&h=200&fit=crop',
isCurrent: false,
members: [
{ id: 6, avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face' },
{ id: 7, avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face' }
]
},
];
// familyList.value = [
// {
// id: 1,
// name: '幸福之家',
// ownerName: '张明明',
// avatar_url: 'https://images.unsplash.com/photo-1511895426328-dc8714191300?w=400&h=200&fit=crop',
// is_in: true,
// members: [
// { id: 1, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' },
// { id: 2, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' },
// { id: 3, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop&crop=face' }
// ]
// },
// {
// id: 2,
// name: '欢乐之家',
// ownerName: '李志强',
// avatar_url: 'https://images.unsplash.com/photo-1502086223501-7ea6ecd79368?w=400&h=200&fit=crop',
// is_in: false,
// members: [
// { id: 4, avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face' },
// { id: 5, avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face' }
// ]
// },
// {
// id: 3,
// name: '快乐之家',
// ownerName: '王芳',
// avatar_url: 'https://images.unsplash.com/photo-1502086223501-7ea6ecd79368?w=400&h=200&fit=crop',
// is_in: false,
// members: [
// { id: 6, avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop&crop=face' },
// { id: 7, avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop&crop=face' }
// ]
// },
// ];
};
// 如果家庭列表存在时, 才显示加入新家庭的按钮
......@@ -184,7 +192,7 @@ const switchToFamily = (familyId) => {
// 切换家庭逻辑 - 先清除所有当前标记,再设置新的当前家庭
familyList.value = familyList.value.map(f => ({
...f,
isCurrent: f.id === familyId
is_in: f.id === familyId
}));
console.log('切换家庭后的列表:', familyList.value);
......@@ -214,7 +222,7 @@ const exitFamily = (familyId) => {
// 退出家庭逻辑
const exitingFamily = familyList.value.find(f => f.id === familyId);
if (exitingFamily?.isCurrent) {
if (exitingFamily?.is_in) {
// 如果退出的是当前家庭,需要返回我的页面
familyList.value = familyList.value.filter(f => f.id !== familyId);
......@@ -250,8 +258,6 @@ const joinNewFamily = () => {
});
};
// 页面加载时初始化数据
useDidShow(() => {
initPageData();
......
......@@ -146,7 +146,9 @@ import { ref, onMounted } from 'vue';
import Taro from '@tarojs/taro';
import { Left, Photograph, Close } from '@nutui/icons-vue-taro';
import BASE_URL from '@/utils/config';
import playIcon from '@/assets/images/icon/play.svg';
//
const playIcon = 'https://cdn.ipadbiz.cn/lls_prog/icon/play.svg';
// 响应式数据
const uploadedFile = ref(null);
......