健身房项目 Uniapp+若依Vue3版搭建!!
本次系统实现主要负责前端前端功能的实现。其中系统前端主要分为三大部分,首页,教练列表页,我的页面。
- 首页
首页的实现效果如图
1.会员卡组件
首页的Vip会员卡部分,团课活动的DataPicker,团课选择都采用了组件化封装的方式,接收方式为父子组件传参模式具体代码如下。
<template> <!-- 卡片横向排列 --> <view class="card-section"> <!-- 动态渲染卡片 --> <view class="card" v-for="card in cardData" :key="card.id" > <view class="card-title">{ { card.name }}</view> <view class="card-price">¥{ { card.price }}</view> <button class="card-button" @click="handlePurchase(card.id)" > 立即抢购 </button> </view> </view> </template> <script setup> import { defineProps } from "vue"; // 接收父组件传递的数据 defineProps({ cardData: { type: Array, required: true, // 必填属性 }, }); // 处理抢购事件 const handlePurchase = (id) => { console.log(`抢购商品ID: ${id}`); }; </script> |
此处可以通过外界的数据传入实现数据的动态生成。
- 日期组件DatePicker
日期组件DatePicker主要实现的效果为能够左右滑动的一个日期组件,并且能够显示一周内的数据。点击选中后能够传给父组件进行以日期为条件的条件查询,查询到该日期下的团课数据,并且能够点击预约进入团课详情页面。通过对dom的操作,能够实现点击滑动的丝滑操作,使用js实现的。
<template> <view class="data-pick scroll-container"> <!-- 日期项 --> <view class="date-item" v-for="(item, index) in weekDates" :key="index" :id="`date-${index}`" :class="{ active: selectedDate === item.date }" @click="handleDateClick(item.date, index)" > <text class="weekday">{ { item.weekday }}</text> <text class="date">{ { item.date }}</text> </view> </view> </template> <script setup> import { ref, onMounted } from "vue"; const props = defineProps({ // 初始化的周数据 weekDates: { type: Array, required: true, }, }); const emit = defineEmits(["dateSelected"]); // 选中的日期 const selectedDate = ref(""); // 点击日期事件 const handleDateClick = (date, index) => { selectedDate.value = date; emit("dateSelected", date); // 向父组件发送选中日期 const container = document.querySelector(".scroll-container"); const clickedElement = document.getElementById(`date-${index}`); if (!container || !clickedElement) return; const containerWidth = container.offsetWidth; const containerScrollLeft = container.scrollLeft; const elementLeft = clickedElement.offsetLeft; const elementWidth = clickedElement.offsetWidth; const elementRight = elementLeft + elementWidth; const offset = 200; if (elementLeft < containerScrollLeft) { container.scrollTo({ left: elementLeft - offset, behavior: "smooth", }); } else if (elementRight > containerScrollLeft + containerWidth) { const scrollToPosition = elementRight - containerWidth + offset; container.scrollTo({ left: scrollToPosition, behavior: "smooth", }); } }; // 设置默认选中的日期为今天 onMounted(() => { const today = new Date().toISOString().split("T")[0]; // 获取当前日期(格式:YYYY-MM-DD) const todayItem = props.weekDates.find((item) => item.date === today); if (todayItem) { selectedDate.value = todayItem.date; // 如果今天在 weekDates 中,设置为选中状态 } }); </script> |
- Img组件
用来拼接后端接收的图片url和后端服务器的ip地址,避免了每个带有图片的页面都是使用专门的函数来进行image的src的处理。
<template> <image :src="decodedSrc" class="img" :mode="mode" /> </template> <script> import { computed, watch } from "vue"; const SERVER_IP = "http://121.36.99.152:8090"; export default { name: "ImgComponent", props: { src: { type: String, required: true, // 图片路径必填 }, mode: { type: String, default: "aspectFill", // 默认裁剪模式 }, }, setup(props) { // 解码并显示可读中文路径 const decodeURL = (url) => { try { return decodeURIComponent(url); // 将 URL 中的乱码解码为中文 } catch (error) { console.error("解码错误:", error); return url; // 解码失败返回原始 URL } }; // 计算最终的图片路径(解码后) const decodedSrc = computed(() => { let completeURL; if (!props.src.startsWith("http")) { // 如果 src 不是完整 URL,则拼接服务器 IP completeURL = `${SERVER_IP}${props.src}`; } else { completeURL = props.src; } return completeURL; // 解码路径中的中文部分 }); // 动态监听 src 的变化(可选) watch( () => props.src, (newSrc) => { console.log("src 发生了变化:", newSrc); } ); return { decodedSrc, }; }, }; </script> |
- request封装
对request的封装方便了我的请求的发送。
// utils/request.js // 基础路径配置 const BASE_URL = 'http://121.36.99.152:8090'; // 替换为你的后端基础地址 export default function request(options) { return new Promise((resolve, reject) => { const token = uni.getStorageSync('token'); // 从本地存储获取 token uni.request({ url: `${BASE_URL}${options.url}`, // 自动拼接基础路径和具体接口路径 method: options.method || 'GET', // 默认请求方法为 GET data: options.data || {}, // 默认空数据 header: { 'Content-Type': 'application/json', Authorization: token ? `Bearer ${token}` : '', // 自动携带 Token ...options.header // 合并自定义请求头 }, success: (response) => { if (response.statusCode === 200) { resolve(response.data); // 返回业务数据 } else { // 处理错误,可能包括业务状态码错误 uni.showToast({ title: response.data?.message || '请求失败', icon: 'none' }); reject(response); } }, fail: (error) => { // 网络错误处理 uni.showToast({ title: '网络错误,请稍后重试', icon: 'none' }); reject(error); } }); }); } // 添加封装的常用方法 export const get = (url, data, header = {}) => { return request({ url, method: 'GET', data, header }); }; export const post = (url, data, header = {}) => { return request({ url, method: 'POST', data, header }); }; export const put = (url, data, header = {}) => { return request({ url, method: 'PUT', data, header }); }; export const del = (url, data, header = {}) => { return request({ url, method: 'DELETE', data, header }); }; |
- api封装
导出api函数与后端请求做对接
// 查询首页信息 import { get } from "../request/request"; // 获取轮播图的信息 export const getSwiperImg=()=>{ return get('/homeImage') } // 获取vip卡的信息 export const getVipInfo= () =>{ return get('/MembershipCard') } // 获取首页的部分团课信息 export const getGroupClass=(startTime)=>{ return get('/GroupClass/list',{startTime}) } // 获取教练列表 export const getCoachList=()=>{ return get('/Coach/list') } // 根据id获取团课详情 export const getLessonDetai=(id)=>{ return get(`/GroupClass/${id}`) } // 获取教练详情 export const getCoachDetail=(id)=>{ return get(`/CoachClass/${id}`) } // 获取category列表 export const getCategoryList=()=>{ return get('/Category/list') } // 获取分类下的团课信息 export const getGroupClassByCategory=(categoryId)=>{ return get('/GroupClass/list',{categoryId}) } // 获取商品列表 export const getProductList=()=>{ return get('/commodity/list') } |
- 教练界面
教练页面主要是查出教练界面,里面包含各教练的简略信息,用于用户的初步的检索。
- 我的页面
我的页面是一个十分丰富的页面,里面包含很多待开发的功能,比如课程,订单,优惠卡券,邀请好友,金币等,可以用来增加用的粘性。下方还有个人勋章,涌动日历,身体数据,后期还能进行和用户app进行连接。
- 团课页面
团课页面是用户在主页点击进入的页面,主要的功能是通过category查询当前分类下的团课,并且能根据上方的DataPicker查看当日下的团课的安排,并且能够进行点击进入团课详情的页面,进行进一步的查看。
- 训练营界面
训练营界面也是用户在首页通过点击进入的界面。
原文地址:https://blog.csdn.net/weixin_73733267/article/details/145312422
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!