Authored by yyq

list

... ... @@ -14,7 +14,7 @@ const TABLE_ACT_PRIZE_PRODUCT_USER = 'act_prize_product_user';
const MINUTE_TIMES = 60;
const PRODUCT_CACHE_TIMES = MINUTE_TIMES * 5; // 商品(列表&详情)缓存时间
const RECENT_CODE_CACHE_TIME = MINUTE_TIMES; // 最近获取记录缓存时间
const MAX_JOIN_TIMES = 2; // 最大活动参与次数
const MAX_JOIN_TIMES = 5; // 最大活动参与次数
const userTimesCache = new MemoryCache();
... ... @@ -62,29 +62,20 @@ module.exports = class extends global.yoho.BaseModel {
* @param extra
* @returns {*}
*/
getList(status, page, extra = {}) {
const pageSize = 20;
getList(page, extra = {}) {
const pageSize = 10;
const actId = parseInt(extra.actId, 10) || 0;
status = parseInt(status, 10);
page = parseInt(page, 10) || 1;
if (_.isNaN(status)) {
status = '> 0';
} else if (status < 0) {
status = '>= 0';
} else {
status = `= ${status}`;
}
let limit = `${(page - 1) * pageSize},${page * pageSize}`;
return mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT}
where act_id = :actId and status ${status}
where act_id = :actId and status > 0
order by sort desc limit ${limit}`, {
actId
}, {
cache: extra.noCache ? 0 : PRODUCT_CACHE_TIMES
cache: PRODUCT_CACHE_TIMES
}).then(handelResult);
}
... ...
... ... @@ -23,14 +23,17 @@ const timeFormat = (time) => {
const zeroBuy = {
zeroBuyList(req, res, next) {
req.ctx(ActivityModel).getZerobuyList().then(result => {
res.render('activity/zero-buy-list', {
req.ctx(ActivityModel).getZerobuyList(req.query).then(result => {
res.render('activity/zero-buy-list', Object.assign(result, {
bodyClass: 'nav-md',
list: result,
module: 'admin',
page: 'activity'
});
page: 'zero-buy'
}));
}).catch(next);
},
zeroBuyStatusEdit(req, res, next) {
req.ctx(ActivityModel).editZerobuyStatus(req.body.id, req.body.status)
.then(res.json).catch(next);
}
};
... ...
... ... @@ -6,7 +6,7 @@
const mysqlCli = global.yoho.utils.mysqlCli;
const _ = require('lodash');
const zerobuyModel = require('../../activity/models/zero-buy');
const pager = require('../../../utils/pager');
const TB_USER = 'user';
const TB_ACTIVITY = 'activity';
... ... @@ -15,6 +15,11 @@ const TB_ACT_ARTICLE_IMG = 'act_article_img';
const TB_ACT_ARTICLE_GOOD = 'act_article_good';
const TB_ACT_ARTICLE_Y100 = 'act_article_y100';
const TABLE_ACT_PRIZE_PRODUCT = 'act_prize_product';
// const TABLE_ACT_PRIZE_PRODUCT_CONTENT = 'act_prize_product_content';
// const TABLE_ACT_PRIZE_PRODUCT_USER = 'act_prize_product_user';
class AdminModel extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
... ... @@ -363,12 +368,111 @@ class AdminModel extends global.yoho.BaseModel {
);
}
getZerobuyList(page) {
return this.ctx.req.ctx(zerobuyModel).getList(-1, page, {
noCache: true
}).then(result => {
console.log(result.data);
return result.data;
/**
* 获取0元购活动列表
* @param params
* @returns {*}
*/
getZerobuyList(params) {
const actId = 0;
const pageSize = 10;
const page = parseInt(params.page, 10) || 1;
return Promise.all([
mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT}
where act_id = :actId order by id desc
limit :start,:end`, {
actId,
start: (page - 1) * pageSize,
end: page * pageSize
}),
mysqlCli.query(`select count(*) as total from ${TABLE_ACT_PRIZE_PRODUCT}
where act_id = :actId`, {
actId
}),
]).then(result => {
let resData = {};
let now = new Date().getTime() / 1000;
const btns = [
{type: 'edit', color: 'info', name: '编辑'},
{type: 'switch', color: 'info', name: '开启/关闭'},
{type: 'export', color: 'info', name: '导出'},
{type: 'publish', color: 'danger', name: '开奖'}
];
resData.list = _.forEach(result[0], value => {
let statusStr = '';
value.btns = _.cloneDeep(btns);
switch (value.status) {
case 1:
statusStr = '开启';
_.set(value, 'btns[1]', {
type: 'switch-close',
color: 'info',
name: '关闭'
});
if (now > value.end_time) {
statusStr += ' 已结束';
} else if (now < value.start_time) {
statusStr += ' 未开始';
} else {
statusStr += ' 进行中';
}
break;
case 2:
statusStr = '已开奖';
delete value.btns[3];
delete value.btns[1];
break;
default:
statusStr = '关闭';
_.set(value, 'btns[1]', {
type: 'switch-open',
color: 'info',
name: '开启'
});
break;
}
value.statusStr = statusStr;
return value;
});
Object.assign(resData, pager(_.get(result, '[1].total', 1), params));
return resData;
});
}
/**
* 获取0元购活动列表
* @param id 活动id
* @returns {*}
*/
editZerobuyStatus(id, status) {
if (!id || !status) {
return {
code: 400,
message: '缺少参数'
};
}
return mysqlCli.update(`update ${TABLE_ACT_PRIZE_PRODUCT} set status = :status where id = :id`, {
id,
status
}).then(() => {
return {
code: 200,
message: '操作成功'
};
});
}
}
... ...
... ... @@ -21,6 +21,7 @@ router.get('/activity/createY100Article', activity.createY100ArticlePage);
router.get('/activity/y100Article', activity.actY100ArticleListPage);
router.get('/activity/upload_excel', activity.uploadExcelPage);
router.get('/activity/zerobuy', activity.zeroBuyList);
router.post('/activity/zerobuy/editStatus', activity.zeroBuyStatusEdit);
// 用户管理[page]
router.get('/user/list', user.userListPage);
... ...
... ... @@ -4,40 +4,96 @@
<div class="x_panel">
<table class="table table-bordered">
<thead>
<tr class="headings">
<th width="7%" class="column-title text-center">活动ID</th>
<th width="12%" class="clolumn-title text-center">商品名称</th>
<th width="12%" class="column-title text-center">活动状态</th>
<th width="10%" class="column-title text-center">活动有效时间</th>
<th width="10%" class="column-title text-center">开奖需要人数</th>
<th width="10%" class="column-title text-center">活动排序</th>
<th width="20%" class="column-title text-center">封面图</th>
<th width="29%" class="column-title text-center">操作</th>
</tr>
<tr class="headings">
<th width="7%" class="column-title text-center">活动ID</th>
<th width="12%" class="clolumn-title text-center">商品名称</th>
<th width="12%" class="column-title text-center">活动状态</th>
<th width="10%" class="column-title text-center">活动有效时间</th>
<th width="10%" class="column-title text-center">开奖需要人数</th>
<th width="10%" class="column-title text-center">活动排序</th>
<th width="20%" class="column-title text-center">封面图</th>
<th width="29%" class="column-title text-center">操作</th>
</tr>
</thead>
<tbody class="article-list">
<tbody >
{{#each list}}
<tr class="even pointer">
<tr>
<td class="text-center">{{id}}</td>
<td class="text-center">{{name}}</td>
<td class="text-center">{{repeatLimit}}</td>
<td class="text-center">{{voteLimit}}</td>
<td class="text-center">{{statusStr}}</td>
<td class="text-center">{{start_time}}-{{end_time}}</td>
<td class="text-center">{{limit}}</td>
<td class="text-center">{{sort}}</td>
<td class="text-center">
<image src="{{cover_img}}">
</td>
<td class="text-center" data-id="{{id}}">
<td class="text-center">
{{# btns}}
<button class="btn btn-danger btn-{{type}}">{{name}}</button>
<button class="btn btn-{{color}} btn-{{type}}" data-id="{{../id}}">{{name}}</button>
{{/ btns}}
</td>
</tr>
{{/each}}
</tbody>
</table>
<div class="table-pagination article-pagination pull-right"></div>
<div class="table-pagination article-pagination pull-right">
<nav aria-label="...">
<ul class="pagination">
{{# prePage}}
<li class="page-item">
<a class="page-link" href="{{url}}">上一页</a>
</li>
{{/ prePage}}
{{# pages}}
<li class="page-item{{#if cur}} active{{/if}}">
{{#if url}}
<a class="page-link" href="{{url}}">{{num}}</a>
{{^}}
<a class="page-link" href="javascript:;">{{num}}</a>
{{/if}}
</li>
{{/ pages}}
{{# nextLimit}}
<li class="page-item">
<a class="page-link" href="{{url}}">下一页</a>
</li>
{{/ nextLimit}}
</ul>
</nav>
</div>
</div>
</div>
</div>
<div id="alert-modal" class="modal fade in" style="display: none; ">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<p class="modal-text"></p>
</div>
<div class="modal-footer">
<a class="btn btn-success" data-dismiss="modal">好的</a>
</div>
</div>
</div>
</div>
<div id="confirm-modal" class="modal fade in" style="display: none; ">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>确认开奖</h3>
</div>
<div class="modal-body">
<p>确认将此活动设为开奖状态?开奖后无法进行状态变更</p>
</div>
<div class="modal-footer">
<a class="btn btn-success" data-dismiss="modal">取消</a>
<a class="btn btn-success sure-publish-btn">确定</a>
</div>
</div>
</div>
</div>
... ...
require('admin/activity.page.css');
const $alert = $('#alert-modal');
const $confirm = $('#confirm-modal');
// $('#alert-modal').modal('show')
function bindEvent() {
const editStatusFn = function(id, status) {
return $.ajax({
method: 'post',
url: '/admin/activity/zerobuy/editStatus',
data: {
id,
status
}
});
};
const editFn = function() {
window.open('/admin/activity/zerobuy/edit?id=' +
$(this).parent().data('id'), '_blank');
};
const switchFn = function() {
let $this = $(this);
let status = $this.hasClass('btn-switch-open') ? 1 : 0;
editStatusFn($this.data('id'), status).then(res => {
if (res.code === 200) {
location.reload();
} else {
$alert.find('.modal-text').text(res.message);
$alert.modal('show');
}
});
};
const exportFn = function() {
};
let publishId;
const publishFn = function() {
editStatusFn(publishId, 2).then(res => {
if (res.code === 200) {
location.reload();
} else {
$alert.find('.modal-text').text(res.message);
$alert.modal('show');
}
});
};
$('.btn-edit').on('click', editFn);
$('.btn-switch-open').on('click', switchFn);
$('.btn-switch-close').on('click', switchFn);
$('.btn-export').on('click', exportFn);
$('.btn-publish').on('click', function() {
publishId = $(this).data('id');
$confirm.modal('show');
});
$('.sure-publish-btn').on('click', publishFn);
}
bindEvent();
... ...
const _ = require('lodash');
/**
* 处理用于筛选的 URL , 拼接 URL 参数
* @param originParam 当前 URL 中的参数
* @param newParam 要拼接的 参数
* @returns {string}
*/
const handleFilterUrl = (originParam, newParam, delParam) => {
let dest = '?';
let tempOriginParam = {};
delParam = delParam || {};
tempOriginParam = Object.assign(tempOriginParam, originParam, newParam);
delete tempOriginParam.uid;
_.forEach(tempOriginParam, info => {
if (!delParam[info.key] && info.value) {
// NOTE: 这里会对 query 进行编码,因为 query 有可以能是中文
if (info.key === 'query') {
info.value = encodeURIComponent(info.value);
}
dest += `${info.key}=${info.value}&`;
}
});
return _.trim(dest, '&');
};
module.exports = (total, params = {}, baseUrl = '') => {
const curPage = _.parseInt(params.page || 1);
const pageSize = _.parseInt(params.limit) || 10;
const totalPage = _.ceil(total / pageSize);
const tip = {
start: (curPage - 1) * pageSize + 1,
end: curPage * pageSize > total ? total : curPage * pageSize,
total
};
let prePage, nextPage;
const pageUrl = handleFilterUrl(baseUrl, params, {page: '${page}'});
if (curPage > 1) {
prePage = {
url: pageUrl.replace('${page}', curPage - 1)
};
}
if (curPage < totalPage) {
nextPage = {
url: pageUrl.replace('${page}', curPage + 1)
};
}
let pages = [];
let pagesNums = totalPage > 5 ? 5 : totalPage;
let offsetPage = curPage + _.round(0 - pagesNums / 2); // 遍历页码左侧数字
if (offsetPage <= 0) {
offsetPage = 1;
} else if (offsetPage + pagesNums > totalPage) {
offsetPage = totalPage - pagesNums + 1;
}
const preLimit = offsetPage - 1; // 页码1和遍历页码左侧的距离
const nextLimit = totalPage - (offsetPage - 1 + pagesNums); // 总页码和遍历页码右侧的距离
if (preLimit === 1) { // 如果左侧间距为1则显示这个页码
pagesNums++;
offsetPage--;
}
if (nextLimit === 1) { // 如果右侧间距为1则显示这个页码
pagesNums++;
}
if (preLimit >= 2) {
pages = _.concat(pages, {
num: 1,
url: pageUrl.replace('${page}', 1),
}, {
num: '...'
});
}
if (offsetPage <= 0) {
offsetPage = 1;
} else if (offsetPage + pagesNums > totalPage) {
offsetPage = totalPage - pagesNums + 1;
}
for (let i = 0; i < pagesNums; i++) {
pages.push({
num: offsetPage,
url: pageUrl.replace('${page}', offsetPage),
cur: curPage === offsetPage
});
offsetPage++;
}
if (nextLimit >= 2) {
pages = _.concat(pages, {
num: '...'
}, {
num: totalPage,
url: pageUrl.replace('${page}', totalPage),
});
}
return {tip, prePage, nextPage, pages};
};
... ...