从0到1:商场导览小程序开发笔记一

背景

购物中心与商场小程序:旨在提供便捷的购物、导航、活动报名、服务查询等功能,让用户更好地体验购物和享受服务。通过提供便捷的购物、信息查询和互动预约等功能,提升了商场的服务水平和用户体验,帮助商场与消费者建立更紧密的联系,促进消费和提升品牌形象。

功能规划

其主要功能如下: 提供商场的基本信息,包括位置、营业时间、商户组成等,让用户了解商场的概况和特色

  • 品牌模块:按业态,楼层或者首字母提供商户列表指引,帮助用户快速找到目标店铺
  • 排行榜:品牌商铺可按评论,浏览数,点赞数,收藏数进行排行
  • 资讯模块:展示商户的优惠活动、打折信息等,让用户了解最新的优惠信息,促进消费
  • 活动模块:展示商场内举办的活动、展览、讲座等信息,吸引用户参与和了解商场文化。
  • 投诉建议:提供用户反馈通道,收集用户对商场服务和体验的意见建议,帮助商场改进服务质量
  • 会员系统:可修改个人资料,查看自己的活动报名,点赞,浏览,收藏,评论,投诉建议记录等。

概要设计

数据设计

bash 复制代码
ProductModel.DB_STRUCTURE = {
	_pid: 'string|true',
	PRODUCT_ID: 'string|true',

	PRODUCT_TITLE: 'string|false|comment=标题',
	PRODUCT_STATUS: 'int|true|default=1|comment=状态 0/1',

	PRODUCT_CATE_ID: 'array|true|comment=分类编号',
	PRODUCT_CATE_NAME: 'array|true|comment=分类冗余',

	PRODUCT_FIRST: 'string|false',

	PRODUCT_ORDER: 'int|true|default=9999',
	PRODUCT_VOUCH: 'int|true|default=0',

	PRODUCT_COMMENT_CNT: 'int|true|default=0',

	PRODUCT_QR: 'string|false',
	PRODUCT_VIEW_CNT: 'int|true|default=0|comment=访问次数',

	PRODUCT_COMMENT_CNT: 'int|true|default=0|comment=评价数',
	PRODUCT_FAV_CNT: 'int|true|default=0|comment=收藏数',
	
	PRODUCT_LIKE_CNT: 'int|true|default=0|comment=点赞数',
	PRODUCT_LIKE_LIST: 'array|true|default=[]|comment=点赞记录',

	PRODUCT_FORMS: 'array|true|default=[]',
	PRODUCT_OBJ: 'object|true|default={}',

	PRODUCT_ADD_TIME: 'int|true',
	PRODUCT_EDIT_TIME: 'int|true',
	PRODUCT_ADD_IP: 'string|false',
	PRODUCT_EDIT_IP: 'string|false',
};

ActivityModel.DB_STRUCTURE = {
	_pid: 'string|true',
	ACTIVITY_ID: 'string|true',

	ACTIVITY_TITLE: 'string|true|comment=标题',
	ACTIVITY_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=使用中',

	ACTIVITY_CATE_ID: 'string|true|default=0|comment=分类',
	ACTIVITY_CATE_NAME: 'string|false|comment=分类冗余',

	ACTIVITY_CANCEL_SET: 'int|true|default=1|comment=取消设置 0=不允,1=允许,2=仅截止前可取消',
	ACTIVITY_CHECK_SET: 'int|true|default=0|comment=审核 0=不需要审核,1=需要审核', 
	ACTIVITY_IS_MENU: 'int|true|default=1|comment=是否公开展示名单',

	ACTIVITY_MAX_CNT: 'int|true|default=20|comment=人数上限 0=不限',
	ACTIVITY_START: 'int|false|comment=活动开始时间',
	ACTIVITY_END: 'int|false|comment=活动截止时间',
	ACTIVITY_STOP: 'int|true|default=0|comment=报名截止时间 0=永不过期',

	ACTIVITY_ORDER: 'int|true|default=9999',
	ACTIVITY_VOUCH: 'int|true|default=0',

	ACTIVITY_FORMS: 'array|true|default=[]',
	ACTIVITY_OBJ: 'object|true|default={}',

	ACTIVITY_JOIN_FORMS: 'array|true|default=[]',

	ACTIVITY_ADDRESS: 'string|false|comment=详细地址',
	ACTIVITY_ADDRESS_GEO: 'object|false|comment=详细地址坐标参数',

	ACTIVITY_QR: 'string|false',
	ACTIVITY_VIEW_CNT: 'int|true|default=0',
	ACTIVITY_JOIN_CNT: 'int|true|default=0',
	ACTIVITY_COMMENT_CNT: 'int|true|default=0',
 

	ACTIVITY_ADD_TIME: 'int|true',
	ACTIVITY_EDIT_TIME: 'int|true',
	ACTIVITY_ADD_IP: 'string|false',
	ACTIVITY_EDIT_IP: 'string|false',
};

关键实现

bash 复制代码
async getAllProduct(floorOptions) {
		// 所有记录
		let orderBy = {
			PRODUCT_ORDER: 'asc',
			PRODUCT_ADD_TIME: 'desc'
		}
		let fields = 'PRODUCT_TITLE,PRODUCT_CATE_NAME,PRODUCT_CATE_ID,PRODUCT_FIRST,PRODUCT_CATE_ID,PRODUCT_CATE_NAME,PRODUCT_OBJ.floor,PRODUCT_OBJ.logo,PRODUCT_OBJ.address';
		let where = { PRODUCT_STATUS: 1 };

		let productList = await ProductModel.getAll(where, fields, orderBy, 1000);

		for (let k = 0; k < productList.length; k++) {
			productList[k].PRODUCT_CATE_NAME = productList[k].PRODUCT_CATE_NAME.join(' - ');
		}

		//### 按楼层 
		let floorList = [];
		for (let k = 0; k < floorOptions.length; k++) {
			let name = floorOptions[k];

			let list = [];
			for (let j = 0; j < productList.length; j++) {
				if (productList[j].PRODUCT_OBJ.floor == name) {
					list.push({
						id: productList[j]._id,
						img: productList[j].PRODUCT_OBJ.logo[0],
						name: productList[j].PRODUCT_TITLE,
						cate: productList[j].PRODUCT_CATE_NAME ,
						detail: productList[j].PRODUCT_OBJ.address,
						floor: productList[j].PRODUCT_OBJ.floor,
					});
				}

			}

			let node = {
				name,
				list
			}
			floorList.push(node);
		}

		//### 按字母
		let charList = [];
		for (let k = 65; k <= 90; k++) {
			let name = String.fromCharCode(k);

			let list = [];
			for (let j = 0; j < productList.length; j++) {
				if (productList[j].PRODUCT_FIRST == name) {
					list.push({
						id: productList[j]._id,
						img: productList[j].PRODUCT_OBJ.logo[0],
						name: productList[j].PRODUCT_TITLE,
						cate: productList[j].PRODUCT_CATE_NAME ,
						detail: productList[j].PRODUCT_OBJ.address,
						floor: productList[j].PRODUCT_OBJ.floor,
					});
				}

			}

			let node = {
				name,
				list
			}
			charList.push(node);
		}

		// 其他字符
		let otherList = [];
		for (let j = 0; j < productList.length; j++) {
			let first = productList[j].PRODUCT_FIRST;
			first = first.charCodeAt(0);
			if (first < 65 || first > 90) {
				otherList.push({
					id: productList[j]._id,
					img: productList[j].PRODUCT_OBJ.logo[0],
					name: productList[j].PRODUCT_TITLE,
					cate: productList[j].PRODUCT_CATE_NAME ,
					detail: productList[j].PRODUCT_OBJ.address,
					floor: productList[j].PRODUCT_OBJ.floor,
				});
			}

		}
		charList.push({ name: '其他', list: otherList });


		//### 按分类
		let cateList = [];
		let cate1Options = await Cate1Model.getAll({ CATE1_STATUS: 1 }, 'CATE1_TITLE', { 'CATE1_ORDER': 'asc', 'CATE1_ADD_TIME': 'desc' });
		for (let k = 0; k < cate1Options.length; k++) {
			let name = cate1Options[k].CATE1_TITLE;

			let list = [];
			for (let j = 0; j < productList.length; j++) {
				if (productList[j].PRODUCT_CATE_ID.includes(cate1Options[k]._id)) {
					list.push({
						id: productList[j]._id,
						img: productList[j].PRODUCT_OBJ.logo[0],
						name: productList[j].PRODUCT_TITLE,
						cate: productList[j].PRODUCT_CATE_NAME ,
						detail: productList[j].PRODUCT_OBJ.address,
						floor: productList[j].PRODUCT_OBJ.floor,
					});
				}

			}

			let node = {
				name,
				list
			}
			cateList.push(node);
		}

		return { productList, floorList, charList, cateList }
	}

	async likeProduct(userId, id) {
		// 是否点赞
		let product = await ProductModel.getOne(id, 'PRODUCT_LIKE_LIST');
		if (!product) this.AppError('记录不存在');

		let arr = product.PRODUCT_LIKE_LIST;
		let flag = false;
		if (arr.includes(userId)) {
			arr = arr.filter(item => item != userId);
			flag = false;
		}
		else {
			arr.push(userId);
			flag = true;
		}
		await ProductModel.edit(id, {
			PRODUCT_LIKE_LIST: arr,
			PRODUCT_LIKE_CNT: arr.length
		});

		return flag;
	}

	/** 浏览资讯信息 */
	async viewProduct(userId, id) {

		let fields = '*';

		let where = {
			_id: id,
			PRODUCT_STATUS: 1
		}
		let product = await ProductModel.getOne(where, fields);
		if (!product) return null;

		product.like = product.PRODUCT_LIKE_LIST.includes(userId) ? true : false;

		delete product.PRODUCT_LIKE_LIST;

		ProductModel.inc(id, 'PRODUCT_VIEW_CNT', 1);

		return product;
	}


	/** 取得分页列表 */
	async getProductList({
		cateId,
		search, // 搜索条件
		sortType, // 搜索菜单
		sortVal, // 搜索菜单
		orderBy, // 排序 
		page,
		size,
		isTotal = true,
		oldTotal
	}) {

		orderBy = orderBy || {
			'PRODUCT_ORDER': 'asc',
			'PRODUCT_ADD_TIME': 'desc'
		};
		let fields = 'PRODUCT_LIKE_CNT,PRODUCT_FAV_CNT,PRODUCT_COMMENT_CNT,PRODUCT_VIEW_CNT,PRODUCT_TITLE,PRODUCT_CATE_ID,PRODUCT_ADD_TIME,PRODUCT_ORDER,PRODUCT_STATUS,PRODUCT_CATE_NAME,PRODUCT_OBJ';

		let where = {};
		where.and = {
			_pid: this.getProjectId() //复杂的查询在此处标注PID
		};
		where.and.PRODUCT_STATUS = 1; // 状态 

		if (cateId && cateId !== '0') where.and.PRODUCT_CATE_ID = cateId;

		if (util.isDefined(search) && search) {
			where.or = [
				{ PRODUCT_TITLE: ['like', search] },
			];
		} else if (sortType && util.isDefined(sortVal)) {
			// 搜索菜单
			switch (sortType) {
				case 'sort': {
					orderBy = this.fmtOrderBySort(sortVal, 'PRODUCT_ADD_TIME');
					break;
				}
				case 'cateId': {
					if (sortVal) where.and.PRODUCT_CATE_ID = String(sortVal);
					break;
				}
			}
		}

		return await ProductModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);
	}

	async getMyLikeProductList(userId, {
		search, // 搜索条件
		sortType, // 搜索菜单
		sortVal, // 搜索菜单
		orderBy, // 排序 
		page,
		size,
		isTotal = true,
		oldTotal
	}) {

		orderBy = orderBy || {
			'PRODUCT_ORDER': 'asc',
			'PRODUCT_ADD_TIME': 'desc'
		};
		let fields = 'PRODUCT_LIKE_CNT,PRODUCT_FAV_CNT,PRODUCT_COMMENT_CNT,PRODUCT_VIEW_CNT,PRODUCT_TITLE,PRODUCT_CATE_ID,PRODUCT_ADD_TIME,PRODUCT_ORDER,PRODUCT_STATUS,PRODUCT_CATE_NAME,PRODUCT_OBJ';

		let where = {};
		where.and = {
			_pid: this.getProjectId() //复杂的查询在此处标注PID
		};
		where.and.PRODUCT_LIKE_LIST = userId;


		if (util.isDefined(search) && search) {
			where.or = [
				{ PRODUCT_TITLE: ['like', search] },
			];
		} else if (sortType && util.isDefined(sortVal)) {
			// 搜索菜单
			switch (sortType) {
				case 'sort': {
					orderBy = this.fmtOrderBySort(sortVal, 'PRODUCT_ADD_TIME');
					break;
				}
			}
		}

		return await ProductModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);
	}

UI设计






后台管理系统



代码分享

git下载

相关推荐
.生产的驴2 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
汤姆yu8 小时前
基于微信小程序的乡村旅游系统
微信小程序·旅游·乡村旅游
计算机徐师兄8 小时前
基于TP5框架的家具购物小程序的设计与实现【附源码、文档】
小程序·php·家具购物小程序·家具购物微信小程序·家具购物
曲辒净9 小时前
微信小程序实现二维码海报保存分享功能
微信小程序·小程序
朽木成才10 小时前
小程序快速实现大模型聊天机器人
小程序·机器人
peachSoda710 小时前
随手记:小程序使用uni.createVideoContext视频无法触发播放
小程序
何极光10 小时前
uniapp小程序样式穿透
前端·小程序·uni-app
小墨&晓末11 小时前
【PythonGui实战】自动摇号小程序
python·算法·小程序·系统安全
oil欧哟1 天前
🤔认真投入一个月做的小程序,能做成什么样子?有人用吗?
前端·vue.js·微信小程序
汤姆yu1 天前
基于微信小程序的消防隐患在线举报系统
微信小程序·小程序·消防隐患