背景剖析

书籍是人类提高的阶梯,在信息高度发达而塌实的当下,静下心来读书成为都市人群的新趋势, 很多读书社团应运而生,那么通过设计一款小程序,把读书会搬到手机上,通过小程序理解最热门的书单和作家,能够每天组织浏览打卡和评比;书友会时常组织书友进行线下流动,那么通过小程序能够不便的搞定报名、签到、流动信息收集,流动完结后还能够进行评估。

性能布局

数据库设计

EnrollModel.DB_STRUCTURE = {    _pid: 'string|true',    ENROLL_ID: 'string|true',    ENROLL_TITLE: 'string|true|comment=题目',    ENROLL_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中',    ENROLL_CATE_ID: 'string|true|default=0|comment=分类',    ENROLL_CATE_NAME: 'string|false|comment=分类冗余',    ENROLL_START: 'int|false|comment=开始工夫',    ENROLL_END: 'int|false|comment=完结工夫',    ENROLL_DAY_CNT: 'int|false|comment=继续天数',    ENROLL_ORDER: 'int|true|default=9999',    ENROLL_VOUCH: 'int|true|default=0',    ENROLL_FORMS: 'array|true|default=[]',    ENROLL_OBJ: 'object|true|default={}',    ENROLL_JOIN_FORMS: 'array|true|default=[]',    ENROLL_DAYS: 'array|true|default=[]',    ENROLL_QR: 'string|false',    ENROLL_VIEW_CNT: 'int|true|default=0',    ENROLL_JOIN_CNT: 'int|true|default=0',    ENROLL_USER_CNT: 'int|true|default=0',    ENROLL_USER_LIST: 'array|true|default=[]|comment={name,id,pic}',    ENROLL_ADD_TIME: 'int|true',    ENROLL_EDIT_TIME: 'int|true',    ENROLL_ADD_IP: 'string|false',    ENROLL_EDIT_IP: 'string|false',};EnrollJoinModel.DB_STRUCTURE = {    _pid: 'string|true',    ENROLL_JOIN_ID: 'string|true',    ENROLL_JOIN_ENROLL_ID: 'string|true|comment=打卡PK',    ENROLL_JOIN_USER_ID: 'string|true|comment=用户ID',    ENROLL_JOIN_DAY: 'string|true|comment=日期',    ENROLL_JOIN_FORMS: 'array|true|default=[]|comment=表单',    ENROLL_JOIN_STATUS: 'int|true|default=1|comment=状态 1=胜利',     ENROLL_JOIN_ADD_TIME: 'int|true',    ENROLL_JOIN_EDIT_TIME: 'int|true',    ENROLL_JOIN_ADD_IP: 'string|false',    ENROLL_JOIN_EDIT_IP: 'string|false',};

外围实现

class EnrollService extends BaseProjectService {    // 获取以后打卡状态    getJoinStatusDesc(enroll) {        let timestamp = this._timestamp;        if (enroll.ENROLL_STATUS == 0)            return '已进行';        else if (enroll.ENROLL_START > timestamp)            return '未开始';        else if (enroll.ENROLL_END <= timestamp)            return '已完结';        else            return '进行中';    }    // 获取某日动静    async getEnrollJoinByDay(enrollId, day = '') {        if (!day) day = timeUtil.time('Y-M-D');        let where = {            ENROLL_JOIN_ENROLL_ID: enrollId,            ENROLL_JOIN_DAY: day,            ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC        }        let joinParams = {            from: UserModel.CL,            localField: 'ENROLL_JOIN_USER_ID',            foreignField: 'USER_MINI_OPENID',            as: 'user',        };        let orderBy = {            ENROLL_JOIN_ADD_TIME: 'desc'        }        let list = await EnrollJoinModel.getListJoin(joinParams, where, 'ENROLL_JOIN_ADD_TIME,user.USER_NAME,user.USER_PIC', orderBy, 1, 100, false, 0);        return list.list;    }    // 获取某流动排行    async getEnrollUserRank(enrollId) {        let where = {            ENROLL_USER_ENROLL_ID: enrollId        }        let joinParams = {            from: UserModel.CL,            localField: 'ENROLL_USER_MINI_OPENID',            foreignField: 'USER_MINI_OPENID',            as: 'user',        };        let orderBy = {            ENROLL_USER_JOIN_CNT: 'desc'        }        let fields = 'ENROLL_USER_JOIN_CNT,ENROLL_USER_LAST_DAY,user.USER_NAME,user.USER_PIC';        let list = await EnrollUserModel.getListJoin(joinParams, where, fields, orderBy, 1, 100, false, 0);        return list.list;    }    /** 浏览信息 */    async viewEnroll(userId, id) {        let fields = '*';        let where = {            _id: id,            ENROLL_STATUS: EnrollModel.STATUS.COMM        }        let enroll = await EnrollModel.getOne(where, fields);        if (!enroll) return null;        EnrollModel.inc(id, 'ENROLL_VIEW_CNT', 1);        // 判断用户今日是否有打卡        let whereJoin = {            ENROLL_JOIN_USER_ID: userId,            ENROLL_JOIN_ENROLL_ID: id,            ENROLL_JOIN_DAY: timeUtil.time('Y-M-D'),            ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC        }        let enrollJoin = await EnrollJoinModel.getOne(whereJoin);        if (enrollJoin) {            enroll.myEnrollJoinId = enrollJoin._id;        }        else {            enroll.myEnrollJoinId = '';        }        // 某日打卡列表        enroll.activity = await this.getEnrollJoinByDay(id);        // 打卡日期数组        let dayList = [];        let start = timeUtil.timestamp2Time(enroll.ENROLL_START, 'Y-M-D');        start = timeUtil.time2Timestamp(start);        let today = timeUtil.time2Timestamp(timeUtil.time('Y-M-D'));        for (let k = start; k <= today;) {            let month = timeUtil.timestamp2Time(k, 'M月');            if (month.startsWith('0')) month = month.substring(1);            let date = timeUtil.timestamp2Time(k, 'D');            let day = timeUtil.timestamp2Time(k, 'Y-M-D');            dayList.push({ month, date, day });            k = k + 86400 * 1000;        }        enroll.dayList = dayList;        // 排行榜         let rankList = await this.getEnrollUserRank(id);        enroll.rankList = rankList;        return enroll;    }    /** 获得分页列表 */    async getEnrollList({        search, // 搜寻条件        sortType, // 搜寻菜单        sortVal, // 搜寻菜单        orderBy, // 排序         page,        size,        isTotal = true,        oldTotal    }) {        orderBy = orderBy || {            'ENROLL_ORDER': 'asc',            'ENROLL_ADD_TIME': 'desc'        };        let fields = 'ENROLL_USER_LIST,ENROLL_JOIN_CNT,ENROLL_OBJ,ENROLL_USER_CNT,ENROLL_TITLE,ENROLL_START,ENROLL_END,ENROLL_ORDER,ENROLL_STATUS,ENROLL_CATE_NAME,ENROLL_OBJ';        let where = {};        where.and = {            _pid: this.getProjectId() //简单的查问在此处标注PID        };        where.and.ENROLL_STATUS = EnrollModel.STATUS.COMM; // 状态          if (util.isDefined(search) && search) {            where.or = [{                ENROLL_TITLE: ['like', search]            },];        } else if (sortType && util.isDefined(sortVal)) {            // 搜寻菜单            switch (sortType) {                case 'cateId': {                    if (sortVal) where.and.ENROLL_CATE_ID = String(sortVal);                    break;                }                case 'sort': {                    orderBy = this.fmtOrderBySort(sortVal, 'ENROLL_ADD_TIME');                    break;                }                case 'today': { //明天                    let day = timeUtil.time('Y-M-D');                    where.and.ENROLL_DAYS = day;                    break;                }                case 'tomorrow': { //明日                    let day = timeUtil.time('Y-M-D', 86400);                    where.and.ENROLL_DAYS = day;                    break;                }                case 'yesterday': { //昨天                     let day = timeUtil.time('Y-M-D', -86400);                    where.and.ENROLL_DAYS = day;                    break;                }                case 'month': { //本月                     let day = timeUtil.time('Y-M-D');                    let start = timeUtil.getMonthFirstTimestamp(day);                    let end = timeUtil.getMonthLastTimestamp(day);                    start = timeUtil.timestamp2Time(start, 'Y-M-D');                    end = timeUtil.timestamp2Time(end, 'Y-M-D');                     where.and.ENROLL_DAYS = ['between', start, end];                    break;                }            }        }        return await EnrollModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);    }    /** 获得我的打卡分页列表 */    async getMyEnrollUserList(userId, {        search, // 搜寻条件        sortType, // 搜寻菜单        sortVal, // 搜寻菜单        orderBy, // 排序         page,        size,        isTotal = true,        oldTotal    }) {        orderBy = orderBy || {            'ENROLL_USER_ADD_TIME': 'asc'        };        let fields = 'ENROLL_USER_LAST_DAY,ENROLL_USER_ENROLL_ID,ENROLL_USER_JOIN_CNT,enroll.ENROLL_TITLE,enroll.ENROLL_OBJ.cover,enroll.ENROLL_USER_CNT,enroll.ENROLL_CATE_NAME,enroll.ENROLL_DAY_CNT,enroll.ENROLL_START,enroll.ENROLL_END,enroll.ENROLL_STATUS';        let where = {            ENROLL_USER_MINI_OPENID: userId        };        if (util.isDefined(search) && search) {            where['enroll.ENROLL_TITLE'] = {                $regex: '.*' + search,                $options: 'i'            };        } else if (sortType) {            // 搜寻菜单            let timestamp = this._timestamp;            switch (sortType) {                case 'stop': {                    where['enroll.ENROLL_STATUS'] = 0;                    break;                }                case 'un': {                    where['enroll.ENROLL_START'] = ['>', timestamp];                    break;                }                case 'over': {                    where['enroll.ENROLL_END'] = ['<=', timestamp];                    break;                }                case 'run': {                    where['enroll.ENROLL_STATUS'] = 1;                    where['enroll.ENROLL_START'] = ['<=', timestamp];                    where['enroll.ENROLL_END'] = ['>', timestamp];                    break;                }            }        }        let joinParams = {            from: EnrollModel.CL,            localField: 'ENROLL_USER_ENROLL_ID',            foreignField: '_id',            as: 'enroll',        };        let result = await EnrollUserModel.getListJoin(joinParams, where, fields, orderBy, page, size, isTotal, oldTotal);        let list = result.list;        for (let k = 0; k < list.length; k++) {            let enroll = {                ENROLL_START: list[k].enroll.ENROLL_START,                ENROLL_END: list[k].enroll.ENROLL_END,                ENROLL_STATUS: list[k].enroll.ENROLL_STATUS,            }            let status = this.getJoinStatusDesc(enroll);            if (status == '进行中') {                if (list[k].ENROLL_USER_LAST_DAY == timeUtil.time('Y-M-D'))                    status = '已打卡';            }            list[k].status = status;            list[k].last = list[k].ENROLL_USER_LAST_DAY.split('-')[1] + '-' + list[k].ENROLL_USER_LAST_DAY.split('-')[2];        }        return result;    }    /** 获得我的打卡清单列表 */    async getMyEnrollJoinList(userId, {        enrollId,        search, // 搜寻条件        sortType, // 搜寻菜单        sortVal, // 搜寻菜单        orderBy, // 排序         page,        size,        isTotal = true,        oldTotal    }) {        orderBy = orderBy || {            'ENROLL_JOIN_ADD_TIME': 'desc'        };        let fields = '*';        let where = {            ENROLL_JOIN_USER_ID: userId,            ENROLL_JOIN_ENROLL_ID: enrollId        };        return await EnrollJoinModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);    }    //################## 打卡     addEnrollUserList(userList, user) {        //查问是否存在 并删除        for (let k = 0; k < userList.length; k++) {            if (userList[k].id == user.id)                userList.splice(k, 1);        }        userList.unshift(user);        // 判断个数, 多的删除        if (userList.length > 3)            userList.splice(userList.length - 1, 1);        return userList;    }    // 打卡     async enrollJoin(userId, enrollId, forms) {        let user = await UserModel.getOne({ USER_MINI_OPENID: userId, USER_STATUS: UserModel.STATUS.COMM });        if (!user) this.AppError('用户不存在');        // 打卡是否完结        let whereEnroll = {            _id: enrollId,            ENROLL_STATUS: EnrollModel.STATUS.COMM        }        let enroll = await EnrollModel.getOne(whereEnroll);        if (!enroll)            this.AppError('该打卡流动不存在或者曾经进行');        // 是否打卡开始        if (enroll.ENROLL_START > this._timestamp)            this.AppError('该打卡流动尚未开始');        // 是否过了打卡完结期        if (enroll.ENROLL_END < this._timestamp)            this.AppError('该打卡流动曾经完结');        let day = timeUtil.time('Y-M-D');        // 本人今日是否曾经有打卡        let whereMy = {            ENROLL_JOIN_USER_ID: userId,            ENROLL_JOIN_ENROLL_ID: enrollId,            ENROLL_JOIN_DAY: day,            ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC        }        let my = await EnrollJoinModel.getOne(whereMy);        if (my) {            this.AppError('您今日已打卡,毋庸反复打卡');        }        // 入库        let data = {            ENROLL_JOIN_USER_ID: userId,            ENROLL_JOIN_ENROLL_ID: enrollId,            ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC,            ENROLL_JOIN_DAY: day,            ENROLL_JOIN_FORMS: forms        }        let enrollJoinId = await EnrollJoinModel.insert(data);        // 统计数量        this.statEnrollJoin(enrollId, userId);        // 更新用户头像         let userList = enroll.ENROLL_USER_LIST;        userList = this.addEnrollUserList(userList, { pic: user.USER_PIC, id: userId, name: user.USER_NAME });        EnrollModel.edit(enrollId, { ENROLL_USER_LIST: userList });        return { enrollJoinId }    }    // 统计    async statEnrollJoin(enrollId, userId = '', del = false) {        // 总体统计        let where = {            ENROLL_JOIN_ENROLL_ID: enrollId,            ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC        }        let joinCnt = await EnrollJoinModel.count(where);        let userCnt = await EnrollJoinModel.distinctCnt(where, 'ENROLL_JOIN_USER_ID');        let data = {            ENROLL_JOIN_CNT: joinCnt,            ENROLL_USER_CNT: userCnt,        }        await EnrollModel.edit(enrollId, data);        // 用户统计        if (!userId) return;        where = {            ENROLL_JOIN_USER_ID: userId,            ENROLL_JOIN_ENROLL_ID: enrollId,            ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC        }        let userJoinCnt = await EnrollJoinModel.count(where);        let enrollUserData = {};        enrollUserData.ENROLL_USER_LAST_DAY = timeUtil.time('Y-M-D');        enrollUserData.ENROLL_USER_JOIN_CNT = userJoinCnt;        enrollUserData.ENROLL_USER_DAY_CNT = userJoinCnt;        where = {            ENROLL_USER_MINI_OPENID: userId,            ENROLL_USER_ENROLL_ID: enrollId        };        await EnrollUserModel.insertOrUpdate(where, enrollUserData);        if (del) {            //删除打卡记录,则更新最近打卡工夫            let last = '';            where = {                ENROLL_JOIN_USER_ID: userId,                ENROLL_JOIN_ENROLL_ID: enrollId,                ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC            }            let lastModel = await EnrollJoinModel.getOne(where, 'ENROLL_JOIN_DAY', { 'ENROLL_JOIN_ADD_TIME': 'desc' });            if (lastModel) last = lastModel.ENROLL_JOIN_DAY;            where = {                ENROLL_USER_MINI_OPENID: userId,                ENROLL_USER_ENROLL_ID: enrollId            };            await EnrollUserModel.edit(where, { ENROLL_USER_LAST_DAY: last });        }    }}

UI设计










后端UI设计














代码

git代码地址