Authored by 陈峰

Merge branch '20180917' into 'master'

20180917



See merge request !53
/**
* 优惠券管理controller
* @author: leo <y.huang@yoho.cn>
* @date: 08/08/2018
*/
const guoChaoModel = require('../models/guochao');
const guochaoController = {
list: async function(req, res) {
let list = await req.ctx(guoChaoModel).list();
return res.json(list);
},
listPage(req, res) {
res.render('guochao/list', {
bodyClass: 'nav-md',
module: 'admin',
page: 'guochao'
});
},
async updatePage(req, res) {
let result = await req.ctx(guoChaoModel).findById(req.query.id);
if (result instanceof Array) {
result = result[0];
}
res.render('guochao/guochao-option', {
bodyClass: 'nav-md',
module: 'admin',
content: result,
page: 'guochao-option'
});
},
update: async function(req, res) {
let result = await req.ctx(guoChaoModel).update(req.body);
return res.json(result);
},
};
module.exports = guochaoController;
... ...
/* eslint-disable array-callback-return */
const { actGuochaoShop } = require('../../../db');
class GuochaoModel extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
list() {
return actGuochaoShop.findAll({order: [['sort', 'desc']]});
}
update(obj) {
return actGuochaoShop.update({ url: obj.url, sort: obj.sort, place: obj.place }, {where: {id: obj.id}});
}
findById(id) {
return actGuochaoShop.findById(id);
}
}
module.exports = GuochaoModel;
... ...
... ... @@ -10,11 +10,17 @@ const activity = require('./controllers/activity');
const user = require('./controllers/user');
const coupon = require('./controllers/coupon');
const multipart = require('connect-multiparty');
const guochao = require('./controllers/guochao');
const mutilpartMiddleware = multipart();
// 管理员[page]
router.get('/login', admin.loginPage);
// 国潮排行[page]
router.get('/guochao/list', guochao.listPage);
router.get('/guochao/update', guochao.updatePage);
// 活动管理[page]
router.get('/activity/list', activity.activityListPage);
router.get('/activity/create', activity.createActivityPage);
... ... @@ -48,6 +54,10 @@ router.get('/coupon/update', coupon.couponOptionPage);
router.post('/api/login', admin.login);
router.post('/api/logout', admin.logout);
// 国潮排行[page]
router.get('/api/guochao/list', guochao.list);
router.post('/api/guochao/update', guochao.update);
// 活动管理[ajax]
router.post('/api/activity/list', activity.activityList);
router.post('/api/activity/create', activity.createActivity);
... ...
<div class="right_col" role="main">
<div class="col-md-12 col-sm-12 col-xs-12">
<div class="x_panel">
{{# content}}
<div class="x_title">
<h2>修改品牌信息</h2>
<div class="clearfix"></div>
</div>
<form id="createForm" class="form-horizontal form-label-left">
<input class="form-imput" type="hidden" data-type="id" id="id" value="{{id}}">
<input id="place" type="hidden" value="{{place}}">
<div class="item form-group">
<label class="control-label col-md-3 col-sm-3 col-xs-12" for="actName">
商铺id<span class="required">*</span>
</label>
<div class="col-md-6 col-sm-6 col-xs-12">
<input class="form-control col-md-7 col-xs-12"
data-type="shopId"
data-toggle="tooltip"
data-placement="bottom"
title="商铺id不能为空"
name="shopName"
type="text"
maxlength="50"
value="{{shop_id}}">
</div>
</div>
<div class="item form-group">
<label class="control-label col-md-3 col-sm-3 col-xs-12" for="actName">
商家logo图片<span class="required">*</span>
</label>
<div class="col-md-6 col-sm-6 col-xs-12">
<img src="{{logo}}" class="col-md-6 product-thumb {{#unless logo}}hide{{/unless}}">
</div>
</div>
<div class="item form-group">
<label class="control-label col-md-3 col-sm-3 col-xs-12" for="actName">
链接地址<span class="required">*</span>
</label>
<div class="col-md-6 col-sm-6 col-xs-12">
<input class="form-control col-md-7 col-xs-12 form-imput"
data-type="url"
data-toggle="tooltip"
data-placement="bottom"
title="链接地址不能为空"
name="shopName"
type="text"
maxlength="50"
value="{{url}}">
</div>
</div>
<div class="item form-group">
<label class="control-label col-md-3 col-sm-3 col-xs-12" for="actName">排序<span
class="required">*</span>
</label>
<div class="col-md-2 col-sm-2 col-xs-12">
<input id="actVoteLimit" class="form-control col-md-2 form-imput"
data-type="sort"
data-toggle="tooltip" data-placement="bottom" title="排序"
name="actVoteLimit"
type="text"
maxlength="10"
value="{{sort}}"><span style="color:#d44950">备注:排序权重数大的排在前面</span>
</div>
</div>
<div class="item form-group">
<label class="control-label col-md-3 col-sm-3 col-xs-12">
位置
</label>
<div class="col-md-6 col-sm-6 col-xs-12">
<label class="control-label col-md-1">
<input type="radio" name="place" required="required"
class="form-contro col-md-7 col-xs-12" value="0">
</label>
<label class="control-label col-md-1">
<input type="radio" name="place" required="required"
class="form-contro col-md-7 col-xs-12" value="1">
</label>
</div>
</div>
<div class="item form-group">
<div class="col-md-2 col-md-offset-5 action-wrap">
<button type="button" class="btn btn-primary btn-save">保存</button>
</div>
</div>
</form>
<a id="upload-btn"></a>
{{/ content}}
</div>
</div>
</div>
... ...
<!-- page content -->
<div class="right_col" role="main">
<div class="">
<div class="row">
<div class="col-md-12 col-sm-12 col-xs-12">
<div class="x_panel">
<div class="x_title">
</div>
<div class="x_content">
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr class="headings">
<th class="column-title">ID</th>
<th class="column-title">logo</th>
<th class="column-title">品牌名</th>
<th class="column-title">排序</th>
<th class="column-title">位置</th>
<th class="column-title">收藏数</th>
<th class="column-title">操作</th>
</tr>
</thead>
<tbody class="guochao-list">
</tbody>
</table>
</div>
<div class="table-pagination coupon-pagination pull-right"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- /page content -->
... ...
... ... @@ -28,15 +28,18 @@ let createY100Data = async function(req, res, next, actId, data, index) {
let content = '';
let createTime = moment().format('YYYY-MM-DD hh:mm:ss');
item.skns_1 = (item.skns_1 || '').replace(/ /g, '').replace(/\r/g, '').replace(/\n/g, '');
item.skns_2 = (item.skns_2 || '').replace(/ /g, '').replace(/\r/g, '').replace(/\n/g, '');
let skns = (item.skns_1 || '') + '||' + (item.skns_2 || '');
let career = item.career;
let interest = item.interest;
let career = item.career || '';
let interest = item.interest || '';
let style = item.style;
let tag = item.tag;
let tag = item.tag || '';
let desc = item.desc || '';
let top = item.top || 0;
let head_url = item.head_url;
let img_url = item.img_url;
let head_url = item.head_url || '';
let img_url = item.img_url || '';
const articleId = await req.ctx(ActivityModel).createArticle({actId, name, content, createTime});
const numRes = await req.ctx(ActivityModel).getY100ArticleNums(actId);
... ...
/**
* 优惠券管理controller
* @author: leo <y.huang@yoho.cn>
* @date: 08/08/2018
*/
const GuochaoModel = require('../models/guochao');
const _ = require('lodash');
const guochaoController = {
async addFav(req, res, next) {
let param = req.body;
let sessionKey = param.sessionKey;
// 调用接口传参时切勿使用toString获得字符串
let uid = {
toString: () => {
return _.parseInt(req.body.uid);
},
sessionKey,
};
try {
let r = await req.ctx(GuochaoModel).addFavAsync(uid, param.id, 'shop');
res.json(r);
} catch (e) {
next;
}
},
list: async function(req, res, next) {
try {
let result = await req.ctx(GuochaoModel).list();
res.json({
data: result,
code: 200,
result: true
});
} catch (e) {
next;
}
}
};
module.exports = guochaoController;
... ...
/* eslint-disable array-callback-return */
const { actGuochaoShop } = require('../../../db');
class Guochao extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
async addFavAsync(uid, id, type) {
console.log({uid, id, type});
try {
await this.get({ data: {
method: 'app.favorite.add',
id: id,
uid: uid,
type: type
}});
let item = await actGuochaoShop.findOne({where: {shop_id: id}});
let result = await item.increment('collect_count');
return Promise.resolve({code: 200, result: true, data: result});
} catch (e) {
console.log(e.toString());
return Promise.resolve({code: 202, result: false, errorMsg: e});
}
}
async list() {
return actGuochaoShop.findAll({order: [['sort', 'desc']]});
}
}
module.exports = Guochao;
... ...
... ... @@ -11,7 +11,7 @@ const prize = require('./controllers/prize');
const shoes = require('./controllers/shoes');
const yohood = require('./controllers/yohood');
const coupon = require('./controllers/coupon');
const guochao = require('./controllers/guochao');
const excel = require('./controllers/excel');
const multipart = require('connect-multiparty');
const mutilpartMiddleware = multipart();
... ... @@ -52,8 +52,11 @@ router.get('/coupon/getCouponSendFlags', coupon.couponSendFlag);
router.post('/coupon/couponGet', coupon.couponGet);
router.get('/coupon/couponUserOwner', coupon.couponUserOwner);
//图片处理
router.get('/shoes/getBase64ImageData', shoes.getImageData);
// guochao
router.post('/guochao/addFav', guochao.addFav);
router.get('/guochao/list', guochao.list);
// 图片处理git
router.get('/shoes/getBase64ImageData', shoes.getImageData);
module.exports = router;
... ...
... ... @@ -146,8 +146,8 @@ class Y100Model extends global.yoho.BaseModel {
if (skns) {
const product_skns = skns.split('||')[0] || '';
const recommend_skns = skns.split('||')[1] || '';
const product_skns = skns.split('||')[0].replace(/\r/g, '').replace(/\n/g, '').replace(/ /g, '') || '';
const recommend_skns = skns.split('||')[1].replace(/\r/g, '').replace(/\n/g, '').replace(/ /g, '') || '';
const productsResult = await this.get({
data: {
... ...
module.exports = {
test: {
username: 'root',
password: '123456',
database: 'yoho_activity_platform',
port: '3306',
host: '0.0.0.0',
dialect: 'mysql',
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
},
seederStorage: 'sequelize'
},
production: {
username: 'yh_vpc_bak',
password: 'yoho@2Y$^YpNb7hp',
database: 'yoho_activity_platform',
port: '3307',
host: '10.67.2.144',
dialect: 'mysql',
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
},
seederStorage: 'sequelize'
}
}[process.env.NODE_ENV || 'test'];
... ...
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const config = require('../config/database');
const logger = global.yoho.logger;
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, Object.assign(config, {
logging: (log) => {
logger.info(log);
}
}));
fs.readdirSync(path.join(__dirname, './models'))
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
let model = sequelize.import(path.join(__dirname, './models', file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
module.exports = db;
... ...
module.exports = {
timestamps: false,
paranoid: false,
underscored: true,
freezeTableName: true,
};
... ...
/* eslint new-cap: "off" */
const options = require('../model-opts');
module.exports = function(sequelize, DataTypes) {
const actGuochaoShop = sequelize.define('actGuochaoShop', {
id: {
type: DataTypes.INTEGER(8),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
logo: {
type: DataTypes.STRING(200),
allowNull: true
},
url: {
type: DataTypes.STRING(300),
allowNull: true,
},
sort: {
type: DataTypes.INTEGER(8),
allowNull: true,
defaultValue: '0'
},
place: {
type: DataTypes.INTEGER(2),
allowNull: true,
defaultValue: '0'
},
collect_count: {
type: DataTypes.INTEGER(8),
allowNull: true,
defaultValue: '0'
},
shop_id: {
type: DataTypes.INTEGER(10),
allowNull: true,
defaultValue: '0'
},
shop_name: {
type: DataTypes.STRING(50),
allowNull: true,
}
}, Object.assign(options, {tableName: 'act_guochao_shop'}));
return actGuochaoShop;
};
... ...
... ... @@ -68,6 +68,11 @@
<li><a href="/admin/coupon/list">券列表</a></li>
</ul>
</li>
<li><a><i class="fa fa-ticket"></i> 国潮排行 <span class="fa fa-chevron-down"></span></a>
<ul class="nav child_menu">
<li><a href="/admin/guochao/list">品牌列表</a></li>
</ul>
</li>
</ul>
</div>
</div>
... ...
... ... @@ -56,6 +56,8 @@
"memory-cache": "^0.1.6",
"moment": "^2.18.1",
"mysql": "^2.13.0",
"sequelize": "^4.38.0",
"mysql2": "^1.6.1",
"nodemailer": "^4.4.1",
"nodemailer-smtp-transport": "^2.7.4",
"passport": "^0.3.2",
... ...
No preview for this file type
require('admin/coupon-option.page.css');
require('bootstrap-daterangepicker');
require('bootpag/lib/jquery.bootpag.min');
function bindEditPageEvent() {
function packInfo() {
let resData = {};
let error;
$('.form-imput').each(function() {
let $this = $(this);
let val = $this.val();
let data = $this.data();
if (!val && !error) {
error = data.empty || `请填写${data.type}`;
}
resData[data.type] = val;
});
if (error) {
alert(error);// eslint-disable line
return;
}
resData.place = $('input[name=place]:checked').val();
return resData;
}
function radioInit() {
let place = parseInt($('#place').val());
if (place) {
$($('input[name=place]')[1]).attr('checked', true);
} else {
$($('input[name=place]')[0]).attr('checked', true);
}
}
radioInit();
$('.btn-save').on('click', function() {
let info = packInfo();
if (!info || window.saveing) {
return;
}
window.saveing = true;
$.ajax({
method: 'post',
url: '/admin/api/guochao/update',
contentType: 'application/json',
data: JSON.stringify(info)
}).then(() => {
window.saveing = false;
alert('保存成功');
});
});
}
(function() {
bindEditPageEvent();
}());
... ...
/* eslint-disable eqeqeq */
require('admin/user.page.css');
require('bootpag/lib/jquery.bootpag.min');
const _ = require('lodash');
function bind_table_pagination() {
const $ul = $('.guochao-list');
const fetchRender = () => {
$.ajax({
url: '/admin/api/guochao/list',
}).then(result => {
const list = result;
let html = '';
_.each(list, item => {
if (item.place) {
item.placeText = '下';
} else {
item.placeText = '上';
}
html += `
<tr class="even pointer">
<td class="">${item.id}</td>
<td class=""><img src="${item.logo}" style="background: #000000" width="100" height="50"/></td>
<td class="">${item.shop_name}</td>
<td class="">${item.sort}</td>
<td class="">${item.placeText}</td>
<td class="">${item.collect_count}</td>
<td class="">
<a class="btn btn-info btn-update" href="/admin/guochao/update?id=${item.id}">修改</a>
</td>
</tr>`;
});
$ul.html(html);
});
};
fetchRender();
}
(function() {
bind_table_pagination();
}());
... ...
@import "user/user";
td {
word-break: break-all;
}
... ...