1

背景

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

功能规划

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

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

概要设计

image.png

数据设计

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',
};

关键实现

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设计

image.png
image.png
image.png
image.png
image.png
image.png

后台管理系统

image.png
image.png
image.png

代码分享

git下载


CC同学呀
27 声望13 粉丝

鹅厂程序猿一枚,交流v: cclinux0730