model
app/model/goods_attr.js
module.exports = app => {
const mongoose = app.mongoose;
const Schema = mongoose.Schema;
var d=new Date();
const GoodsAttrSchema = new Schema({
goods_id: {type:Schema.Types.ObjectId },
cate_id:{
type:Schema.Types.ObjectId
},
attribute_id:{
type:Schema.Types.ObjectId
},
attribute_type:{
type: String
},
attribute_title:{
type: String
},
attribute_value:{
type: String
},
status: { type: Number,default:1 },
add_time: {
type:Number,
default: d.getTime()
}
});
return mongoose.model('GoodsAttr', GoodsAttrSchema,'goods_attr');
}
app/model/goods_image.js
module.exports = app => {
const mongoose = app.mongoose;
const Schema = mongoose.Schema;
var d=new Date();
const GoodsImageSchema = new Schema({
goods_id: {type:Schema.Types.ObjectId },
img_url: { type: String },
color_id:{
type:Schema.Types.Mixed, //混合类型
default: ''
},
status: { type: Number,default:1 },
add_time: {
type:Number,
default: d.getTime()
}
});
return mongoose.model('GoodsImage', GoodsImageSchema,'goods_image');
}
view
app/view/admin/goods/add.html
<%- include ../public/page_header.html %>
<!-- 富文本编辑器 -->
<link href="/public/admin/wysiwyg-editor/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<!-- Include Editor style. -->
<link href="/public/admin/wysiwyg-editor/css/froala_editor.pkgd.min.css" rel="stylesheet" type="text/css" />
<link href="/public/admin/wysiwyg-editor/css/froala_style.min.css" rel="stylesheet" type="text/css" />
<!-- 引入jquery -->
<!-- Include Editor JS files. -->
<script type="text/javascript" src="/public/admin/wysiwyg-editor/js/froala_editor.pkgd.min.js"></script>
<script type="text/javascript" src="/public/admin/wysiwyg-editor/js/zh_cn.js"></script>
<!-- 批量上传图片插件 -->
<link rel="stylesheet" type="text/css" href="/public/admin/webuploader/css/webuploader.css">
<link rel="stylesheet" type="text/css" href="/public/admin/webuploader/css/diyUpload.css">
<script type="text/javascript" src="/public/admin/webuploader/js/webuploader.html5only.min.js"></script>
<script type="text/javascript" src="/public/admin/webuploader/js/diyUpload.js"></script>
<div class="panel panel-default">
<div class="panel-body">
<div class="table-responsive input-form">
<form action="/admin/goods/doAdd?_csrf=<%=csrf%>" method="post" class="goods_content" enctype="multipart/form-data">
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#general" role="tab" data-toggle="tab">通用信息</a></li>
<li role="presentation"><a href="#detail" role="tab" data-toggle="tab">详细描述</a></li>
<li role="presentation"><a href="#mix" role="tab" data-toggle="tab">商品属性</a></li>
<li role="presentation"><a href="#attribute" role="tab" data-toggle="tab">规格与包装</a></li>
<li role="presentation"><a href="#photo" role="tab" data-toggle="tab">商品相册</a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="general">
<ul class="form_input">
<li> <span> 商品标题:</span> <input type="text" name="title" class="input"/></li>
<li> <span> 附属标题:</span> <input type="text" name="sub_title" class="input"/></li>
<li> <span>商品版本:</span> <input type="text" name="goods_version" class="input"/></li>
<li> <span>所属分类:</span>
<select name="cid" id="cid">
<%for(var i=0;i<goodsCate.length;i++){%>
<option value="<%=goodsCate[i]._id%>"><%=goodsCate[i].title%></option>
<%for(var j=0;j<goodsCate[i].items.length;j++){%>
<option value="<%=goodsCate[i].items[j]._id%>">----<%=goodsCate[i].items[j].title%></option>
<%}%>
<%}%>
</select>
<input type="hidden" name="cname" id="cname" />
</li>
<li> <span> 商品图片:</span> <input type="file" name="pic"/></li>
<li> <span>商品价格:</span> <input type="text" name="price"/></li>
<li> <span>商品原价:</span> <input type="text" name="old_price"/></li>
<li> <span>商品状态:</span> <input type="radio" value="1" name="status" checked/> 显示
<input type="radio" value="0" name="status"/> 隐藏
</li>
<li> <span>加入推荐:</span> <input type="checkbox" value="1" name="is_best"/> 精品
<input type="checkbox" value="1" name="is_hot"/> 热销
<input type="checkbox" value="1" name="is_new"/> 新品
</li>
</ul>
</div>
<div role="tabpanel" class="tab-pane" id="detail">
<textarea name="goods_content" id="content" cols="100" rows="8"></textarea>
</div>
<div role="tabpanel" class="tab-pane" id="mix">
<ul class="form_input">
<li> <span>商品颜色:</span>
<%for(var i=0;i<colorResult.length;i++){%>
<input type="checkbox" name="goods_color" value="<%=colorResult[i]._id%>" id="color_<%=colorResult[i]._id%>" /> <label for="color_<%=colorResult[i]._id%>"><%=colorResult[i].color_name%></label>
<%}%>
</li>
<li> <span>关联商品:</span>
<input type="text" name="relation_goods" class="relation_goods"/> <i>填写关联商品的id 多个以逗号隔开 格式:23,24,39</i>
</li>
<li> <span>关联赠品:</span>
<input type="text" name="goods_gift" class="goods_gift"/> <i>可为空 格式:23-2,39-5 说明:例如23-2 中的23表示商品id,2表示商品数量</i>
</li>
<li> <span>关联配件:</span>
<input type="text" name="goods_fitting" class="goods_fitting"/> <i>可为空 格式:23-2,39-5 说明:例如23-2 中的23表示商品id,2表示商品数量</i>
</li>
<li> <span>更多属性:</span>
<input type="text" name="goods_attr" class="goods_attr"/> <i> 格式: 颜色:红色,白色,黄色 | 尺寸:41,42,43</i>
</li>
</ul>
</div>
<div role="tabpanel" class="tab-pane" id="attribute">
<ul class="form_input">
<li> <span>商品类型: </span>
<select name="goods_type_id" id="goods_type_id">
<option value="0">--请选择商品类型--</option>
<%for(var i=0;i<goodsType.length;i++){%>
<option value="<%=goodsType[i]._id%>"><%=goodsType[i].title%></option>
<%}%>
</select>
</li>
</ul>
<ul class="form_input" id="goods_type_attribute">
</ul>
</div>
<div role="tabpanel" class="tab-pane" id="photo">
<div id="photoLib" class="photoLib"></div>
<div id="photoList">
</div>
</div>
</div>
<button type="submit" class="btn btn-success goods_content_btn">提交</button>
</form>
</div>
</div>
</div>
<script>
$(function(){
//关联商品类型
$('#goods_type_id').change(function(){
// alert($(this).val());
var cate_id=$(this).val();
var data='';
$.get('/admin/goods/goodsTypeAttribute?cate_id='+cate_id,function(response){
console.log(response.result);
data=response.result;
console.log(data.length);
var str="";
for(var i=0;i<data.length;i++){
if(data[i].attr_type==1){
str+='<li><span>'+data[i].title+': </span><input type="hidden" name="attr_id_list" value="'+data[i]._id+'" /> <input type="text" name="attr_value_list" /></li>'
}else if(data[i].attr_type==2){
str+='<li><span>'+data[i].title+': </span> <input type="hidden" name="attr_id_list" value="'+data[i]._id+'"> <textarea cols="50" rows="3" name="attr_value_list"></textarea></li>'
}else{
var arr=data[i].attr_value.split('\n');
str+='<li><span>'+data[i].title+': </span><input type="hidden" name="attr_id_list" value="'+data[i]._id+'">';
str+='<select name="attr_value_list">';
for(var j=0;j<arr.length;j++){
str+='<option value="'+arr[j]+'">'+arr[j]+'</option>';
}
str+='</select>';
str+='</li>';
}
}
$('#goods_type_attribute').html(str);
})
})
})
//富文本编辑器
$(function() {
$('#content').froalaEditor({
height: 300, //给编辑器设置默认的高度
language: 'zh_cn',
imageUploadURL: '/admin/goods/goodsUploadImage',
//根据不同的分辨率加载不同的配置
toolbarButtons: ['fullscreen', 'bold', 'italic', 'underline', 'strikeThrough', 'subscript', 'superscript', '|', 'fontFamily', 'fontSize', 'color', 'inlineStyle', 'paragraphStyle', '|', 'paragraphFormat', 'align', 'formatOL', 'formatUL', 'outdent', 'indent', 'quote', '-', 'insertLink', 'insertImage', 'insertVideo', 'embedly', 'insertFile', 'insertTable', '|', 'emoticons', 'specialCharacters', 'insertHR', 'selectAll', 'clearFormatting', '|', 'print', 'spellChecker', 'help', 'html', '|', 'undo', 'redo'],
toolbarButtonsMD: ['fullscreen', 'bold', 'italic', 'underline', 'strikeThrough', 'subscript', 'superscript', '|', 'fontFamily', 'fontSize', 'color', 'inlineStyle', 'paragraphStyle', '|', 'paragraphFormat', 'align', 'formatOL', 'formatUL', 'outdent', 'indent', 'quote', '-', 'insertLink', 'insertImage', 'insertVideo', 'embedly', 'insertFile', 'insertTable', '|', 'emoticons', 'specialCharacters', 'insertHR', 'selectAll', 'clearFormatting', '|', 'print', 'spellChecker', 'help', 'html', '|', 'undo', 'redo'],
toolbarButtonsSM: ['fullscreen', 'bold', 'italic', 'underline', 'strikeThrough', 'subscript', 'superscript', '|', 'fontFamily', 'fontSize', 'color', 'inlineStyle', 'paragraphStyle', '|', 'paragraphFormat', 'align', 'formatOL', 'formatUL', 'outdent', 'indent', 'quote', '-', 'insertLink', 'insertImage', 'insertVideo', 'embedly', 'insertFile', 'insertTable', '|', 'emoticons', 'specialCharacters', 'insertHR', 'selectAll', 'clearFormatting', '|', 'print', 'spellChecker', 'help', 'html', '|', 'undo', 'redo']
});
});
//批量上传图片
$(function(){
var photoStr='';
$('#photoLib').diyUpload({
url:'/admin/goods/goodsUploadPhoto',
success:function( response ) {
// console.info( data );
photoStr='<input type="hidden" name="goods_image_list" value='+response.link+' />';
$('#photoList').append(photoStr);
},
error:function( err ) {
console.info( err );
}
});
})
</script>
</body>
</html>
controller
app/controller/admin/goods.js
async add() {
//获取所有的颜色值
var colorResult = await this.ctx.model.GoodsColor.find({});
//获取所有的商品类型,对应包装与规格
var goodsType = await this.ctx.model.GoodsType.find({});
//获取商品分类
var goodsCate=await this.ctx.model.GoodsCate.aggregate([
{
$lookup:{
from:'goods_cate',
localField:'_id',
foreignField:'pid',
as:'items'
}
},
{
$match:{
"pid":'0'
}
}
])
await this.ctx.render('admin/goods/add',{
colorResult:colorResult,
goodsType:goodsType,
goodsCate:goodsCate
});
}
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
})
}
var formFields=Object.assign(files,parts.field);
console.log(formFields);
//增加商品信息
let goodsRes =new this.ctx.model.Goods(formFields);
var result=await goodsRes.save();
// console.log(result._id);
//增加图库信息
if(result._id){
var goods_image_list=formFields.goods_image_list;
for(var i=0;i<goods_image_list.length;i++){
let goodsImageRes =new this.ctx.model.GoodsImage({
goods_id:result._id,
img_url:goods_image_list[i]
});
await goodsImageRes.save();
}
}
//增加商品类型数据
if(result._id){
/*
attr_id_list:
[ '5bbac2f646f01a08f4a82e7c',
'5bbd7ea7e723b71e5815b7dd',
'5bbd7eb0e723b71e5815b7de',
'5bbd805ee723b71e5815b7df' ],
attr_value_list: [ 'windows', '8g', '1t', '1440*720\r\n' ] }
*/
var attr_value_list=formFields.attr_value_list;
var attr_id_list=formFields.attr_id_list;
for(var i=0;i<attr_value_list.length;i++){
//查询goods_type_attribute
if(attr_value_list[i]){
var goodsTypeAttributeResutl=await this.ctx.model.GoodsTypeAttribute.find({"_id":attr_id_list[i]})
let goodsAttrRes =new this.ctx.model.GoodsAttr({
goods_id:result._id,
cate_id:formFields.cate_id,
attribute_id:attr_id_list[i],
attribute_type:goodsTypeAttributeResutl[0].attr_type,
attribute_title:goodsTypeAttributeResutl[0].title,
attribute_value:attr_value_list[i]
});
await goodsAttrRes.save();
}
}
}
await this.success('/admin/goods','增加商品数据成功');
}
表关联



**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。