model

app/model/goods_cate.js

module.exports = app => {
    const mongoose = app.mongoose;
    const Schema = mongoose.Schema;
    var d=new Date();
   
    const GoodsCateSchema = new Schema({
      title:{ type:String },
      cate_img: { type: String  },
      filter_attr: { type: String  },      //筛选id
      link:{ type: String  },  
      template:{ /*指定当前分类的模板*/
          type:String
      },
      pid:{
          type:Schema.Types.Mixed  //混合类型 
      },
      sub_title:{  /*seo相关的标题  关键词  描述*/
        type:String
      },
      keywords:{
        type:String
      },
      description:{
        type:String
      },
      status: { type: Number,default:1  },    
      add_time: {           
        type:Number,        
        default: d.getTime()    
      }
    }); 
    return mongoose.model('GoodsCate', GoodsCateSchema,'goods_cate');
  }

router.js

   router.get('/admin/goodsCate', controller.admin.goodsCate.index);
   router.get('/admin/goodsCate/add', controller.admin.goodsCate.add);
   router.post('/admin/goodsCate/doAdd', controller.admin.goodsCate.doAdd);

增加

controller

app/controller/admin/goodsCate.js
  async add(){
    var result = await this.ctx.model.GoodsCate.find({'pid':'0'})
    await this.ctx.render('admin/goodsCate/add',{
        cateList:result
    });
  }

  async doAdd(){
    let parts = this.ctx.multipart({ autoFields: true });
    let files = {};               
    let stream;
    while ((stream = await parts()) != null) {
        if (!stream.filename) {          
          break;
        }       
        let fieldname = stream.fieldname;  //file表单的名字

        //上传图片的目录
        let dir=await this.service.tools.getUploadFile(stream.filename);
        let target = dir.uploadDir;
        let writeStream = fs.createWriteStream(target);

        await pump(stream, writeStream);  

        files=Object.assign(files,{
          [fieldname]:dir.saveDir    
        })
        
    }         
    if(parts.field.pid!=0){    
        parts.field.pid=this.app.mongoose.Types.ObjectId(parts.field.pid);    //调用mongoose里面的方法把字符串转换成ObjectId      
       
    }
    let goodsCate =new this.ctx.model.GoodsCate(Object.assign(files,parts.field));
    await goodsCate.save();
    await this.success('/admin/goodsCate','增加分类成功');
  }

view

app/view/admin/goodsCate/add.html
  1. 一级分类的pid是0,顶级分类
  2. 二级分类的pid_id,一级分类(如下图的手机/电话卡)

<%- include ../public/page_header.html %>

<div class="panel panel-default">              
    <div class="panel-heading">
        增加商品分类
    </div>
    <div class="panel-body">
        <div class="table-responsive input-form">
            <form action="/admin/goodsCate/doAdd?_csrf=<%=csrf%>" method="post" enctype="multipart/form-data">
                <ul class="form_input">                       
                        <li>  <span>分类名称:</span> <input type="text" name="title" class="input"/></li>                         
                        <li>  <span>上级分类:</span>                         
                            <select name="pid" id="pid">                                    
                                <option value="0">顶级分类</option> 
                                <%for(var i=0;i<cateList.length;i++){%>                                    
                                        <option value="<%=cateList[i]._id%>"><%=cateList[i].title%></option>                                           
                                <%}%>
                               
                            </select>
                        </li>  
                        <li> <span>分类图片:</span>  <input type="file" name="cate_img"/></li>  
                        <li> <span>筛选属性:</span> <input type="text" name="filter_attr" class="input"/></li> 
                        <li>  <span>跳转地址:</span>  <input type="text" name="link" class="input"/></li>     
                        <li>  <span>分类模板:</span> <input type="text" name="template" class="input"/><span>空表示默认模板</span></li>
                        <li>  <span>Seo标题:</span> <input type="text" name="sub_title" class="input"/></li>
                        <li>  <span>Seo关键词: </span><input type="text" name="keywords" class="input"/></li>
                        <li>  <span>Seo描述:</span> <textarea name="description" id="description" cols="84" rows="4"></textarea></li>                   
                        <li>  <span>排  序:</span> <input type="text" name="sort"/></li>       
                        <li>  <span>状  态:</span> <input type="radio" name="status" checked value="1" id="a"/> <label for="a">显示</label>    <input type="radio" name="status" value="0" id="b"/><label for="b">隐藏</label>  </li>                             
                        <li>
                            <br/>
                            <button type="submit" class="btn btn-primary">提交</button>
                        </li>
                </ul>
            </form>
        </div>
    </div>
</div>
</body>
</html>

效果

clipboard.png

查找

controller

app/controller/admin/goodsCate.js
  1. 通过pid关联自己查询
  2. match筛选pid为0的数据
  async index() {
    var result=await this.ctx.model.GoodsCate.aggregate([     
        {
          $lookup:{
            from:'goods_cate',
            localField:'_id',
            foreignField:'pid',
            as:'items'      
          }      
       },
       {
          $match:{
            "pid":'0'
          }
       }   
    ])
    console.log(JSON.stringify(result));
    await this.ctx.render('admin/goodsCate/index',{
      list:result
    });
  }

view

app/view/admin/goodsCate/index.html
<%- include ../public/page_header.html %>


            <div class="panel panel-default">              
                    <div class="panel-heading clear">
                        <span>商品分类列表</span> <a href="/admin/goodsCate/add" class="btn btn-primary fr">增加商品分类</a>
                    </div>
                    <div class="panel-body">

                    <div class="table-responsive">
                        <table class="table table-bordered">
                            <thead>
                            <tr class="th">
                                <th>分类名称</th>
                                <th>分类图片</th>                                
                                <th class="text-center">排序</th> 
                                <th class="text-center">状态</th>                                           
                                <th class="text-center">操作</th>
                            </tr>
                            </thead>
                            <tbody>
                                    <%for(var i=0;i<list.length;i++){%>
                                            <tr>
                                                    <td><%=list[i].title%></td>  
                                                                                
                                                    <td><img class="pic" src="<%=list[i].cate_img%>" /></td>                                                 
                                                    <td class="text-center"><span onclick="app.editNum(this,'GoodsCate','sort','<%=list[i]._id%>')"><%=list[i].sort%></span></td>
                                                    <td class="text-center">
            
                                                        <%if(list[i].status==1){%>
            
                                                                <img src="/public/admin/images/yes.gif" onclick="app.changeStatus(this,'GoodsCate','status','<%=list[i]._id%>')" />
            
                                                        <%}else{%>
                                                                <img src="/public/admin/images/no.gif" onclick="app.changeStatus(this,'GoodsCate','status','<%=list[i]._id%>')" />
                                                        <%}%>
            
                                                    </td>                                                                    
                                                    <td class="text-center"> <a href="/admin/goodsCate/edit?id=<%=list[i]._id%>">修改</a> <a class="delete" href="/admin/delete?model=GoodsCate&id=<%=list[i]._id%>">删除</a></td>
                                                </tr>
                                                <%for(var j=0;j<list[i].items.length;j++){%>
                                                        <tr>
                                                                <td>-----<%=list[i].items[j].title%></td>                                                             
                                                                <td><img class="pic" src="<%=list[i].items[j].cate_img%>" /></td>    
                                                                <td class="text-center"><span onclick="app.editNum(this,'GoodsCate','sort','<%=list[i].items[j]._id%>')"><%=list[i].items[j].sort%></span></td>
                                                                <td class="text-center">
                        
                                                                    <%if(list[i].status==1){%>
                        
                                                                            <img src="/public/admin/images/yes.gif" onclick="app.changeStatus(this,'GoodsCate','status','<%=list[i].items[j]._id%>')" />
                        
                                                                    <%}else{%>
                                                                            <img src="/public/admin/images/no.gif" onclick="app.changeStatus(this,'GoodsCate','status','<%=list[i].items[j]._id%>')" />
                                                                    <%}%>
                        
                                                                </td>                                                                    
                                                                <td class="text-center"> <a href="/admin/goodsCate/edit?id=<%=list[i].items[j]._id%>">修改</a> <a class="delete" href="/admin/delete?model=GoodsCate&id=<%=list[i].items[j]._id%>">删除</a></td>
                                                            </tr>
                                                                      
                                                <%}%>           
                                    <%}%>                                
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
</body>
</html>

效果

  1. 红色为一级分类
  2. 蓝色为二级分类

clipboard.png

clipboard.png

上传图片时,生成多种分辨率的图片

安装依赖

cnpm install jimp --save

service

app/service/tools.js
  1. resize 尺寸
  2. quality 质量
  3. write 名字
const Jimp = require("jimp");  //生成缩略图的模块
  async jimpImg(target){
    //上传图片成功以后生成缩略图
    Jimp.read(target, (err, lenna) => {
     if (err) throw err;          
           lenna.resize(200, 200) // 尺寸
               .quality(90) // 质量                 
               .write(target+'_200x200'+path.extname(target)); // save 

           lenna.resize(400, 400) // 尺寸
               .quality(90) // 质量                  
               .write(target+'_400x400'+path.extname(target)); // save
     });
 }

controller

app/controller/admin/goodsCate.js
增加一行this.service.tools.jimpImg(target);
  async doAdd(){
    let parts = this.ctx.multipart({ autoFields: true });
    let files = {};               
    let stream;
    while ((stream = await parts()) != null) {
        if (!stream.filename) {          
          break;
        }       
        let fieldname = stream.fieldname;  //file表单的名字

        //上传图片的目录
        let dir=await this.service.tools.getUploadFile(stream.filename);
        let target = dir.uploadDir;
        let writeStream = fs.createWriteStream(target);

        await pump(stream, writeStream);  

        files=Object.assign(files,{
          [fieldname]:dir.saveDir    
        })
        this.service.tools.jimpImg(target);
        
    }         
    if(parts.field.pid!=0){    
        parts.field.pid=this.app.mongoose.Types.ObjectId(parts.field.pid);    //调用mongoose里面的方法把字符串转换成ObjectId      
       
    }
    let goodsCate =new this.ctx.model.GoodsCate(Object.assign(files,parts.field));
    await goodsCate.save();
    await this.success('/admin/goodsCate','增加分类成功');
  }

效果

clipboard.png

clipboard.png

编辑

controller

app/controller/admin/goodsCate.js
  async edit() {
    var id = this.ctx.request.query.id;
    var result = await this.ctx.model.GoodsCate.find({
      "_id": id
    });
    var cateList = await this.ctx.model.GoodsCate.find({
      "pid": '0'
    });
    await this.ctx.render('admin/goodsCate/edit', {
      cateList: cateList,
      list: result[0]
    });
  }

  async doEdit() {
    let parts = this.ctx.multipart({
      autoFields: true
    });
    let files = {};
    let stream;
    while ((stream = await parts()) != null) {
      if (!stream.filename) {
        break;
      }
      let fieldname = stream.fieldname; //file表单的名字

      //上传图片的目录
      let dir = await this.service.tools.getUploadFile(stream.filename);
      let target = dir.uploadDir;
      let writeStream = fs.createWriteStream(target);

      await pump(stream, writeStream);

      files = Object.assign(files, {
        [fieldname]: dir.saveDir
      })

      //生成缩略图
      this.service.tools.jimpImg(target);
    }

    if (parts.field.pid != 0) {
      parts.field.pid = this.app.mongoose.Types.ObjectId(parts.field.pid); //调用mongoose里面的方法把字符串转换成ObjectId         
    }

    var id = parts.field.id;
    var updateResult = Object.assign(files, parts.field);
    await this.ctx.model.GoodsCate.updateOne({
      "_id": id
    }, updateResult);
    await this.success('/admin/goodsCate', '修改分类成功');

  }

view

app/view/admin/goodsCate/edit.html
<%- include ../public/page_header.html %>

    <div class="panel panel-default">              
        <div class="panel-heading">
            编辑商品分类
        </div>
        <div class="panel-body">
            <div class="table-responsive input-form">
                <form action="/admin/goodsCate/doEdit?_csrf=<%=csrf%>" method="post" enctype="multipart/form-data">
                    <ul class="form_input">
                            <input type="hidden" name="id" value="<%=list._id%>" />
                            <li>  <span>分类名称:</span> <input type="text" name="title" class="input" value="<%=list.title%>"/></li>                             
                            <li>  <span>上级分类:</span>                         
                                <select name="pid" id="pid">                                    
                                    <option value="0">顶级分类</option> 
                                    <%for(var i=0;i<cateList.length;i++){%>                                    
                                            <option value="<%=cateList[i]._id%>" <%if(cateList[i]._id.toString()==list.pid){%> selected <%}%>><%=cateList[i].title%></option>                                           
                                    <%}%>                                    
                                </select>
                            </li>         
                            <li> <span>分类图片:</span>  <input type="file" name="cate_img"/>   

                                    <br /> 
                            
                                    <span> </span> <img class="pic" src="<%=list.cate_img%>" />                            
                            </li>     
                            <li> <span>筛选属性:</span> <input type="text" name="filter_attr" class="input" value="<%=list.filter_attr%>"/></li> 
        
                            <li>  <span>跳转地址:</span>  <input type="text" name="link" class="input" value="<%=list.link%>" /></li> 
        
                            <li>  <span>分类模板:</span> <input type="text" name="template" class="input" value="<%=list.template%>" /><span>空表示默认模板</span></li>
        
                            <li>  <span>Seo标题:</span> <input type="text" name="sub_title" class="input" value="<%=list.sub_title%>"/></li>
        
                            <li>  <span>Seo关键词: </span><input type="text" name="keywords" class="input" value="<%=list.keywords%>"/></li>
        
                            <li>  <span>Seo描述:</span> <textarea name="description" id="description" cols="84" rows="4"><%=list.description%></textarea></li>                   

                            <li>  <span>排  序:</span> <input type="text" name="sort" value="<%=list.sort%>"/></li>       
                                                     
                            
                            <li>  <span>状  态:</span> <input type="radio" name="status" <%if(list.status==1){%> checked <%}%> value="1" id="a"/> <label for="a">显示</label>    <input type="radio"  <%if(list.status==0){%> checked <%}%>  name="status" value="0" id="b"/><label for="b">隐藏</label>  </li>
                            <li>
                                <br/>
                                <button type="submit" class="btn btn-primary">提交</button>
                            </li>
                    </ul>
                </form>
            </div>
        </div>
    </div>
</body>
</html>

效果

默认选中上级分类

clipboard.png

表单最多提交个数

  1. egg默认设置表单提交个数为10
  2. Reach fields limit (code: Request_fields_limit) 翻译后 达到字段限制(代码:Request_fields_limit)

修改config,自定义个数

config/config.default.js
    config.multipart = {
      fields: '50'
   };

clipboard.png


渣渣辉
1.3k 声望147 粉丝

引用和评论

0 条评论