#小程序云开发挑战赛#-BOSS百科-乐多多BOSS百科
发布于 4 年前 作者 wei35 1147 次浏览 来自 分享

1.用户痛点

随着“大众创业,万众创新”理念的推广,目前越来越多的人加入创业者大军。然而对于初为管理者或者准备成为管理者的人来说,他们迫切需要一种能快速提升管理知识的方式。然而传统的管理学丛书太系统,太专业,缺乏实用性。他们更希望是获取与自己实际情况相适配的管理经验。同时,对于这些群体来说,由于初为管理者,演讲水平都需要提高。要提高演讲水平,针对BOSS的高逼格词汇就自然而然成为了他们的必修之课。

2.市场机会

目前知识类产品主要有百度百科、百度知道、知乎等;百度百科做的是全行业的词条百科全书,百度知道、知乎做的是非标准化的问答。通过百度百科搜索词条时只有一大堆文字,缺少互动和实用性分享,内容篇幅大,用户很容易疲倦。而知道、知乎等,以问答方式回复指定问题,用户很难学习一个具体的词汇,并且回答者都是回答问题,缺少主动分享内容。同时,针对管理者的词条学习交流平台尚没有大玩家。

3.商业模式

以PUGC为平台核心商业模式,基于BOSS这个特定群体,提供内容分享和交流平台;初期通过系统采集管理类数据词条导入平台,通过吸引用户阅读和分享的方式吸引用户。从而促使用户发布词条;通过对用户发布词条的内容和热度的分享,筛选出专业用户,为他们提供创作者认证入口。最后形成BOSS交流管理经验的知识平台

4.目标用户

初为管理者或者即将成为管理者的BOSS们

5.产品架构(整体规划)

由于商业原因产品架构细分不提供。

6.盈利模式

1)流量广告

2)企业咨询服务

3)高端名片设计费用

4)针对小微企业的其他增值服务

5)需求匹配佣金

6)小微企业软件服务方案

7.产品演示

8.功能代码

1)首页(分页,小程序端操作数据库)

     data: {
    noMore: false,
    shouldRefresh:false,
    keyword: "",
    types:['全部','管理','产品','技术','市场','运营','其他'],
    selectType:'全部',
    pagenation: {
      pageSize: 10,
      currentPage: 1,
      hasMore: true
    },
    isLoading: false,
    dataList: [],
  },
   onReachBottom: function () {
      const {
        pagenation
      } = this.data;
    
      if (pagenation.hasMore) {
      this.queryDataList();
    }
  },
  getDataList() {
       //初始化分页
    let pagenation = this.data.pagenation;
    pagenation.currentPage = 1;
    pagenation.hasMore = true;
    this.setData({
      pagenation,
      dataList: [],
      nodata: false
    })
    this.queryDataList();
  },
  queryDataList() {
    let {
      pagenation,
      dataList,
      selectType
    } = this.data;
    wx.showLoading({
      title: '加载中...'
    });
    let start = (pagenation.currentPage - 1) * pagenation.pageSize;
    const db = wx.cloud.database()
    let _where = {};
    if (this.data.keyword) {
      _where = {
        name: {
          $regex: '.*' + this.data.keyword + '.*'//模糊查询
        }
      };
    }
    if(selectType!='全部'){
      _where.type = selectType;
    }
    db.collection('boss_entry')
    .field({
      _id:true,
      name:true,
      summary:true,
      readNum:true,
      likeNum:true
    })
    .where(_where)
    .orderBy('create_time','desc')
    .skip(start)
    .limit(pagenation.pageSize)
    .get().then(res => {
      wx.hideLoading();
      if (pagenation.currentPage === 1 && res.data.length === 0) {
        pagenation.hasMore = false;
        this.setData({
           nodata:true
          } 
        );
      } else {
        if (res.data.length === pagenation.pageSize) {
          pagenation.currentPage = pagenation.currentPage + 1;
          pagenation.hasMore = true;
        } else {
          pagenation.hasMore = false;
        }
      }
      dataList = dataList.concat(res.data)
      this.setData({
        dataList,
        pagenation
      })
    });
  },

2)云函数调用

onAddWord(){
      let {baseInfoData,typeIndex} = this.data;      
      //验证图文列表
      let selfContentArr = this.data.selfContentArr;
      baseInfoData.selfContentArr = selfContentArr;
      baseInfoData.type = this.data.types[typeIndex];
      wx.cloud.callFunction({
        name:'addWord',
        data:{
          baseInfoData
        },
        success:function(res){
            console.log('[云函数addWord返回:',res);
            if(res.result.code==0){
                 wx.showToast({
                  icon:'none',
                  title:'保存成功!'
                 })
                 setTimeout(function(){
                  const pages = getCurrentPages()
                  const prevPage = pages[pages.length-2] 
                  prevPage.setData({
                     shouldRefreshtrue
                  })
                  wx.navigateBack()
                 },1500)
                 
            }else{
              wx.showToast({
                icon:'none',
                title:res.result.msg
                })
            }
        }
      });
  }

3)云函数

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  // API 调用都保持和云函数当前所在环境一致
  env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()

// 云函数入口函数
exports.main = async (event, context) => {
  var baseInfoData = event.baseInfoData;
  //验证参数
  if (!baseInfoData) {
    return {
      code: 500,
      msg: '参数不能为空!'
    }
  }
  if (!baseInfoData.name) {
    return {
      code: 500,
      msg: '请输入词条名称!'
    }
  }
  if (!baseInfoData.chnName) {
    return {
      code: 500,
      msg: '请输入词条中文名!'
    }
  }
  if (!baseInfoData.summary) {
    return {
      code: 500,
      msg: '请输入词条概述!'
    }
  }

  //鉴黄
  try {
    await cloud.openapi.security.msgSecCheck({
      content: JSON.stringify(baseInfoData)
    })
  } catch (e) {
    console.log(e)
    if (e.errCode == 87014) {
      return {
        code: 500,
        msg: '您提交了含有违法违规的内容!'
      }
    }
  }
  try {
    //判断词条是否已经存在
    var _data = {};
    await db.collection('boss_entry').where({
      name: baseInfoData.name
    }).get().then((res) => {
        if(res.data.length>0){
          _data = res.data[0]
        }
    });
    if (_data._id && _data._id!= baseInfoData._id) {
      return {
        code: 500,
        msg: '该词条已经存在!'
      }
    }
  
    if(baseInfoData._id){  
      const _id = baseInfoData._id;  
      delete baseInfoData._id;
      await db.collection('boss_entry').doc(_id).update({
        data: baseInfoData
      });
    }else{
      const wxContext = cloud.getWXContext()
       //存openid  
      baseInfoData.openid = wxContext.OPENID;
      baseInfoData.create_time = new Date().getTime()/1000;
      baseInfoData.readNum = 0;
      baseInfoData.likeNum = 0;
      await db.collection('boss_entry').add({
        data: baseInfoData
      });
    }
    return {
      code: 0
    }    
  } catch (e) {
    console.log('[异常信息]新增词条失败,异常信息如下:', e)
    return {
      code: 500,
      msg: '服务繁忙,请稍后重试!'
    }
  }
}

4)多图上传组件和云存储

Component({
    properties: {
        tempFilePaths:{
            type:Array,
            value:[]
        }
    },
    data:{
        type:1//1 image 2 video
        durationSize:15,//视频秒数限制
        mSize:2.5,//数据最大为2.5M
        isShowWarn:false,
        showTitle:'',
        videoNum:0,//图片限制9张
        imageNum:0,//视频1个
        canUpload:true
    },
    attached(){
        if(this.properties.tempFilePaths.length >0){
            this.setData({
                tempFilePaths:this.properties.tempFilePaths,
            })
        }
    },
    methods: {
        chooseImage(){
            let that = this;
            that.checkNum();
            if(that.data.imageNum >= 9){
                this.setData({
                    isShowWarn:true,
                    showTitle:'一个模块最多只能上传9张图片'
                });
                this.triggerEvent('showModel',true);
                return;
            }
            that.setData({
                canUpload:false
            })
            let count = 9-this.data.imageNum;
            wx.chooseImage({
                count: count,
                sizeType: [ 'compressed'],
                sourceType: ['album''camera'],
                success(res) {
                    // tempFilePath可以作为img标签的src属性显示图片
                    that.setData({
                        type:1,
                    });
                    that.uploadFile(res.tempFilePaths);
                },
                fail(){
                    that.setData({
                        canUpload:true
                    });
                }
            })
        },
        delMedia(e){
            let index = e.currentTarget.dataset.index;
            let newListPaths =  this.properties.tempFilePaths;
            newListPaths.splice(index,1);
            this.setData({
                tempFilePaths:newListPaths
            });
            this.triggerEvent('updateFilePaths',newListPaths);
        },
        chooseVideo(){
            let that = this;
            that.checkNum();
            if(that.data.videoNum >= 1){
                this.setData({
                    isShowWarn:true,
                    showTitle:'一个模块最多只能上传1个视频'
                });
                
                return;
            }
            that.setData({
                canUpload:false
            })
            wx.chooseVideo({
                sourceType: ['album''camera'],
                maxDuration: 15,
                camera: 'back',
                success(res) {
                    let checkResult = that.checkSize(res);
                    if(!checkResult){
                        return;
                    }
                    that.setData({
                        type:2,
                    });
                    let path = [];
                    path[0] = res.tempFilePath;
                    that.uploadFile(path);
                },
                fail(){
                    that.setData({
                        canUpload:true
                    });
                }
            })
        },
        uuid(){
            var s = [];
            var hexDigits = "0123456789abcdef";
            for (var i = 0; i < 36; i++) {
                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
            }
            s[14] = "4"// bits 12-15 of the time_hi_and_version field to 0010
            s[19] = hexDigits.substr((s[19] & 0x3) | 0x81); // bits 6-7 of the clock_seq_hi_and_reserved to 01
            s[8] = s[13] = s[18] = s[23] = "-";

            var uuid = s.join("");
            return uuid;
        },
        uploadFile(path){
            let globalData = getApp().globalData;
            const HOST_URL = globalData.requestUrl;
            let token = wx.getStorageSync('token') || '';
            let that = this;
            let uploads = [];
            for(let i=0; inew Promise((resolve,reject) => {
                    wx.cloud.uploadFile({
                        cloudPath:that.uuid()+path[i].match(/\.[^.]+?$/)[0],
                        filePath: path[i],
                        success: function (res{
                            console.log('res',res);
                            if(res.fileID){
                                let url =res.fileID;
                                let meidaObj = {};
                                if(that.data.type == 1){
                                    meidaObj ={
                                        type:1,
                                        imageUrl: url
                                    };
                                } else {
                                    meidaObj = {
                                        type:2,
                                        videoUrl: url
                                    }
                                }
                                resolve(meidaObj)
                            } else {
                                reject('后端接口返回错误,image_uri');
                            }
                        },
                        fail: function (e{
                            reject(e)
                        },
                    })
                })
            }
            Promise.all(uploads).then((result)=>{
                if(!result){
                    return;
                }
                let tempFilePaths = [...that.properties.tempFilePaths, ...result];
                that.setData({
                    tempFilePaths: tempFilePaths,
                    canUpload:true
                });
                that.triggerEvent('updateFilePaths',tempFilePaths);
            }).catch(function(err{
                this.setData({//防止用户上传间隙,直接再点上传
                    canUpload:true
                });
            });
        },
        checkSize(res){
            let size = Number((res.size/1048576).toFixed(1));
            if(res.errMsg != 'chooseVideo:ok'){
                this.setData({
                    isShowWarn:true,
                    showTitle:'上传视频错误'
                });
                
                return false;
            }
            else if(res.duration > this.data.durationSize){
                this.setData({
                    isShowWarn:true,
                    showTitle:'视频上传最大长度15秒'
                });
                
                return false;
            }
            else if( size> this.data.mSize){//设置上传视频最大长度限制3M
                this.setData({
                    isShowWarn:true,
                    showTitle:'视频不能超过2.5兆,请裁剪后上传'
                });
                
                return false;
            }
            else {
                return true;
            }
        },
        confirm(){
            this.setData({
                isShowWarn:false
            });
            
        },
        onCancel(){
            this.setData({
                isShowWarn:false
            });
            
        },
        checkNum(){
            let tempFilePaths = this.data.tempFilePaths;
            let videoNum = 0;
            let imageNum = 0;
            tempFilePaths.forEach((item) => {
                if(item.type == 1){
                    imageNum = imageNum +1
                } else {
                    videoNum = videoNum+1;
                }
            });
            this.setData({
                imageNum:imageNum,
                videoNum:videoNum
            })
        }
    },
});

开源地址:https://gitee.com/princeframe/boss-baike.git

9.团队介绍

重庆乐多多科技有限公司CEO,从事互联网产品研发、运营10余年,曾在多家互联网公司担任架构师、CTO、产品总监等职位,曾参与多个信息化项目和互联网项目,在电商、支付、旅游、政务、内容产品等领域有着丰富的经验。

10.体验二维码

2 回复

可以可以

功能操作很简洁,针对的目标用户群体非常清晰。很多比较流行的百科讲解,每天开会或者演讲的时候都用得上。还可以在这个平台结交一些高端的人才。好用!有价值!期待你们的继续更新迭代!

回到顶部