基于java SpringBoot和Vue uniapp的影楼摄影预约小程序

news/2024/7/20 4:19:04 标签: uni-app, 小程序

摘要

        今天信息技术的发展很快,其足迹在我们的生活中随处可见。它影响着我们的衣食住行等各种需求。影响也在逐渐增加,逐渐渗透到各行各业,在这种背景下,经过实地考察后,为了让婚纱照管理更加高效方便,我决定开发一个摄影棚预约管理系统。随着社会的进步和时代的发展,科学技术不断向前发展,在21世纪,这是一个信息技术的时代。计算机技术的时代日新月异,计算机以前所未有的创新方式改变着世界的面貌,人们的现代化速度越来越快,生活方式发生了前所未有的新变化。计算机可以解决的问题数量大大增加,可以更有效地处理实际问题,节省大量时间。为此,影楼摄影预约系统的设计符合当前的现实。

实现的功能

本系统分为普通用户和管理员两种角色,普通用户是小程序端,管理员是PC浏览器端。

功能应该包括:注册登录、预约摄影功能、选择场景管理订单、分享照片的社区、个人中心等功能。

注册、登录:未注册用户可以注册,有了账号后可以登录小程序

预约摄影功能:用户通过小程序登录后可以选择预约摄影;

选择场景管理订单:根据不同的订单管理自己预约信息;

分享照片的社区:主要是用户可以把自己喜欢的照片分享出去,也可以起到给影楼引流和宣传的作用;

个人中心:用户可以管理自己的个人信息。

用到的技术

后端 java语言的SpringBoot框架,MySql数据库,Maven依赖管理;

前端 Vue.js语法的UniApp框架。

部分代码展示

<template>
	<view class="container">
		<!-- 小程序头部兼容 -->
		<!-- #ifdef MP -->
		<view class="mp-search-box">
			<input @confirm="search" class="ser-input" type="text" value="输入关键字搜索"  />
		</view>
		<!-- #endif -->
		
		<!-- 头部轮播 -->
		<view class="carousel-section">
			<!-- 标题栏和状态栏占位符 -->
			<view class="titleNview-placing"></view>
			<!-- 背景色区域 -->
			<view class="titleNview-background" :style="{backgroundColor:titleNViewBackground}"></view>
			<swiper class="carousel" circular @change="swiperChange">
				<swiper-item v-for="(item, index) in carouselList" :key="index" class="carousel-item" @click="navToDetailPage({title: '轮播广告'})">
					<image mode="aspectFill" :src="item.src" />
				</swiper-item>
			</swiper>
			<!-- 自定义swiper指示器 -->
			<view class="swiper-dots">
				<text class="num">{{swiperCurrent+1}}</text>
				<text class="sign">/</text>
				<text class="num">{{swiperLength}}</text>
			</view>
		</view>
		
		<view class="block-wrap">
			<u-grid :col="4" :border="false" >
				<u-grid-item index="0" @click="changeType(0)" >
					<image class="gn-icon" src="/static/picture-album.png"></image>
					<view class="grid-text" :class="tab==0?'selTab':''">摄影服装</view>
				</u-grid-item>
				<u-grid-item index="1" @click="changeType(1)" >
					<image class="gn-icon" src="/static/map-draw.png"></image>
					<view class="grid-text"  :class="tab==1?'selTab':''">拍摄场地</view>
				</u-grid-item>
				<u-grid-item index="2">
					<image class="gn-icon" @click="toOrder()" src="/static/camera.png"></image>
					<view class="grid-text">预约拍摄</view>
				</u-grid-item>
			</u-grid>
		</view>
		
		<!-- 分类 -->
		<!-- <view class="cate-section">
			<view class="cate-item" v-for="(item,index) in typeList" :key="item.id" @click="navTo(item.id)">
				<image :src="'/static/temp/t'+(index+1)+'.png'"></image>
				<text>{{item.name}}</text>
			</view>
			
		</view> -->
		
		<!-- <view class="ad-1">
			<image src="/static/temp/hot.png" mode="scaleToFill"></image>
		</view> -->
		
		

		<!-- 猜你喜欢 -->
		<view class="f-header m-t">
			<image src="/static/temp/h1.png"></image>
			<view class="tit-box">
				<text class="tit">{{ tab == 0?"服装列表":"场地列表" }}</text>
				<text class="tit2">{{ tab == 0?"Cloth":"Place" }}</text>
			</view>
			<!-- <text class="yticon icon-you"></text> -->
		</view>
		
		<view class="guess-section">
			<view 
				v-for="(item, index) in dataList" :key="index"
				class="guess-item"
				@click="toInfo(item)"
			>
				<view class="image-wrapper">
					<image :src="picUrl+item.pic1" mode="aspectFill"></image>
				</view>
				
				<text class="title clamp">{{item.name}}</text>
				<view class="base" >
					<view v-if="index2<3" class="tag" v-for="(item2,index2) in splitTag(item.tag)" :key="index2">{{item2}}</view>
				</view>
				<text class="price">{{tab==0?"服装":"影棚"}}租金:¥{{item.price}}</text>
			</view>
		</view>
		

	</view>
</template>

<script>
	import appRequest from "@/common/appRequestUrl.js";
	export default {

		data() {
			return {
				tab:0,
				picUrl:appRequest.urlMap.getPicById,
				titleNViewBackground: '',
				swiperCurrent: 0,
				swiperLength: 0,
				carouselList: [],
				dataList: [],
				user:"",
				typeList:[],
				userInfo:"",
				name:""
			};
		},
		onLoad() {
			this.getData();
			// this.getType();	
				//options
					
		},onShow() {
			// this.user = appRequest.getUserInfo();
			// this.getGoods();
			
		},
		onNavigationBarSearchInputConfirmed(e) {
			if(e.text){
				this.name = e.text;
				this.getData();
			}
		},
		methods: {
			toOrder(){
				uni.navigateTo({
					url:"/pages/order/order"
				})
			},
			search(e) {
				this.name = e.detail.value;
				this.getData();
			},
			splitTag(text){
				return text.split(" ");
			},
			changeType(index){
				this.tab = index;
				if(index<2){
					this.getData();
				}
				
			},
			toLogin(){
				let _this = this;
				let userInfo = appRequest.getUserInfo();
				if(!userInfo){
					wx.login({
						success(res) {
							if (res.code) {
								let code = res.code;
								uni.showModal({
									title: "登录",
									content: "请授权获取微信信息用于登录",
									success: function(res) {
										if (res.confirm) {
											_this.getUserLogin(code);
										}
									}
								})
				
							} else {
								console.log('登录失败!' + res.errMsg)
							}
						}
					})
				
				}else{
					this.userInfo = userInfo;
				}
			},getUserLogin(code){
				let _this = this;
				uni.clearStorage();
				wx.getUserProfile({
					desc: '使用前需要微信授权登录', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
					success: (res) => {
						console.log(JSON.stringify(res));
						appRequest.request({
							method: "GET",
							data: {
								code: code,
								enData: res.encryptedData,
								iv:res.iv,
								userInfo:res.userInfo
							},
							url: appRequest.urlMap.loginCheck,
							success: function(res) {
								if(res.data.code == 200){
									try {
										uni.setStorageSync('userInfo', res.data.data);
										uni.switchTab({
											url:"/pages/index/index"
										})
									} catch (e) {
										//callback()
										uni.clearStorage();
									}	
								}else{
									//callback()
								}
							},
							fail: function(res) {
								//callback();
							}
						})
					},fail: (err) => {
						console.log(err);
					}
				})
			},
			toInfo(item){
				uni.navigateTo({
					url:"../product/product?id="+item.id
				})
			},
			navTo(id){
				try {
					uni.setStorageSync('currId', id);
				} catch (e) {
					
				}	
				uni.switchTab({
					url:"../category/category"
				})
			},
			getData(){
				let _this = this;
				appRequest.request({
					method: "POST",
					url: appRequest.urlMap.findPhClothPlaceList,
					data:{
						type:_this.tab,
						validFlag:1,
						name:_this.name
					},
					success: function(res) {
						
						if(res.data.code == 200){
							_this.dataList = res.data.data;
							_this.carouselList = [];
							_this.swiperLength = 3;
							for(var i=0;i<3;i++){
								var obj = _this.dataList[i];
								if(obj){
									_this.carouselList.push({
										src: _this.picUrl+obj.pic1,
										background: "rgb(203, 87, 60)"
									});
								}
								
							}
							
						}else{
							_this.$api.msg(res.data.msg);
						}
				
					},
					fail: function(res) {
						_this.$api.msg("请求异常");
					}
				})
			},
			
			/**
			 * 请求静态数据只是为了代码不那么乱
			 * 分次请求未作整合
			 */
			async loadData() {
				let carouselList = await this.$api.json('carouselList');
				this.titleNViewBackground = carouselList[0].background;
				this.swiperLength = 5;
				this.carouselList = carouselList;
				
				// let goodsList = await this.$api.json('goodsList');
				// this.goodsList = goodsList || [];
			},
			//轮播图切换修改背景色
			swiperChange(e) {
				const index = e.detail.current;
				this.swiperCurrent = index;
				this.titleNViewBackground = this.carouselList[index].background;
			},
			//详情页
			navToDetailPage(item) {
				//测试数据没有写id,用title代替
				let id = item.title;
				uni.navigateTo({
					url: `/pages/product/product?id=${id}`
				})
			}
		}
		
	}
</script>

演示视频

基于SpringBoot和UniAPP影楼摄影预约小程序


http://www.niftyadmin.cn/n/5004237.html

相关文章

23.09.5 《CLR via C#》 笔记5

第六章 类型和成员基础 类型可以定义0或多个以下成员&#xff1a;常量、字段、实例构造器、类型构造器、方法、操作符重载、转换操作符、属性、事件、类型类型的可见性分为public和internal(默认)C#中&#xff0c;成员的可访问性分为private、protected、internal、protected …

合宙Air724UG LuatOS-Air LVGL API控件-滑动条 (Slider)

滑动条 (Slider) 滑动条看起来和进度条是有些是有些像&#xff0c;但不同的是滑动条可以进行数值选择。 示例代码 -- 回调函数 slider_event_cb function(obj, event)if event lvgl.EVENT_VALUE_CHANGED then local val (lvgl.slider_get_value(obj) or "0")..&…

一种编程语言,

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

中项2023错题集

()不属于智慧城市的基本原则。 A. 以人为本 务实推进 B. 因地制宜 科学有序 C. 政府主导 协同创新 D. 可管可控 确保安全 答案&#xff1a; C 智慧城市的基本原则是以人为本&#xff0c;务实推进;因地制宜&#xff0c;科学有序;市场为主&#xff0c;协同创新;可管可控、确…

【LeetCode】双指针求解和为s的两个数字

Problem: 剑指 Offer 57. 和为s的两个数字 文章目录 题目解析算法思路分析复杂度Code 题目解析 首先来讲解一下本题的思路 我们看到本题的意思很简单&#xff0c;就是去这个nums这个数组中进行寻找&#xff0c;如果找到了两个数相加之和为target的话&#xff0c;那构成一个结果…

使用redis实现队列功能

使用redis实现队列功能 操作方法描述LPUSHLong lPush(String key, String… values)将一个或多个值 value 插入到列表 key 的表头&#xff0c;返回插入后列表中value的数量&#xff0c;若key不存在&#xff0c;会创建一个新的列表并执行 LPUSH 操作RPOPLPUSHString rPopLPush(S…

Less常用内置函数

1&#xff0c;类型函数 isnumber(value) - 判断是否为数字isstring(value) - 判断是否为字符串isurl(value) - 判断是否为urliscolor(value) - 判断是否为颜色isunit(value, unit) - 判断value值是否为指定单位 示例&#xff1a; isnumber(12); // true isnumber(#333); // f…

Angular 怎么封装基础组件?

在Angular中&#xff0c;封装基础组件通常是通过创建自定义Angular组件来实现的。这些自定义组件可以包含通用的功能和样式&#xff0c;然后可以在应用中多次重复使用。以下是一个简单的示例&#xff0c;说明如何封装一个基础组件。 假设我们要创建一个通用的警告框组件&#…