Showing
7 changed files
with
747 additions
and
7 deletions
@@ -56,7 +56,21 @@ const zeroBuy = { | @@ -56,7 +56,21 @@ const zeroBuy = { | ||
56 | res.setHeader('Content-Disposition', `attachment; filename=zerobuy_${id}_${new Date().getTime()}.xlsx`); | 56 | res.setHeader('Content-Disposition', `attachment; filename=zerobuy_${id}_${new Date().getTime()}.xlsx`); |
57 | res.end(excelExport.execute(result), 'binary'); | 57 | res.end(excelExport.execute(result), 'binary'); |
58 | }).catch(next); | 58 | }).catch(next); |
59 | - } | 59 | + }, |
60 | + zeroBuyEdit(req, res, next) { | ||
61 | + req.ctx(ActivityModel).getZerobuyContent(req.query.id).then(result => { | ||
62 | + res.render('activity/zero-buy-edit', { | ||
63 | + bodyClass: 'nav-md', | ||
64 | + content: result, | ||
65 | + module: 'admin', | ||
66 | + page: 'zero-buy' | ||
67 | + }); | ||
68 | + }).catch(next); | ||
69 | + }, | ||
70 | + zeroBuySave(req, res, next) { | ||
71 | + req.ctx(ActivityModel).saveZerobuyContent(req.body) | ||
72 | + .then(res.json).catch(next); | ||
73 | + }, | ||
60 | }; | 74 | }; |
61 | 75 | ||
62 | const activity = { | 76 | const activity = { |
@@ -18,8 +18,7 @@ const TB_ACT_ARTICLE_GOOD = 'act_article_good'; | @@ -18,8 +18,7 @@ const TB_ACT_ARTICLE_GOOD = 'act_article_good'; | ||
18 | const TB_ACT_ARTICLE_Y100 = 'act_article_y100'; | 18 | const TB_ACT_ARTICLE_Y100 = 'act_article_y100'; |
19 | 19 | ||
20 | const TABLE_ACT_PRIZE_PRODUCT = 'act_prize_product'; | 20 | const TABLE_ACT_PRIZE_PRODUCT = 'act_prize_product'; |
21 | - | ||
22 | -// const TABLE_ACT_PRIZE_PRODUCT_CONTENT = 'act_prize_product_content'; | 21 | +const TABLE_ACT_PRIZE_PRODUCT_CONTENT = 'act_prize_product_content'; |
23 | const TABLE_ACT_PRIZE_PRODUCT_USER = 'act_prize_product_user'; | 22 | const TABLE_ACT_PRIZE_PRODUCT_USER = 'act_prize_product_user'; |
24 | 23 | ||
25 | const timeFormat = (time) => { | 24 | const timeFormat = (time) => { |
@@ -30,6 +29,14 @@ const timeFormat = (time) => { | @@ -30,6 +29,14 @@ const timeFormat = (time) => { | ||
30 | return moment(time).format('YYYY-MM-DD HH:mm:ss'); | 29 | return moment(time).format('YYYY-MM-DD HH:mm:ss'); |
31 | }; | 30 | }; |
32 | 31 | ||
32 | +const parseJSON = (json) => { | ||
33 | + try { | ||
34 | + return JSON.parse(json); | ||
35 | + } catch(e) { // eslint-disable-line | ||
36 | + return ''; | ||
37 | + } | ||
38 | +}; | ||
39 | + | ||
33 | class AdminModel extends global.yoho.BaseModel { | 40 | class AdminModel extends global.yoho.BaseModel { |
34 | constructor(ctx) { | 41 | constructor(ctx) { |
35 | super(ctx); | 42 | super(ctx); |
@@ -565,6 +572,150 @@ class AdminModel extends global.yoho.BaseModel { | @@ -565,6 +572,150 @@ class AdminModel extends global.yoho.BaseModel { | ||
565 | }; | 572 | }; |
566 | }); | 573 | }); |
567 | } | 574 | } |
575 | + | ||
576 | + getZerobuyContent(id) { | ||
577 | + if (!id) { | ||
578 | + return Promise.resolve({}); | ||
579 | + } | ||
580 | + | ||
581 | + return Promise.all([ | ||
582 | + mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT} | ||
583 | + where id = :id limit 1;`, {id}), | ||
584 | + mysqlCli.query(`select * from ${TABLE_ACT_PRIZE_PRODUCT_CONTENT} | ||
585 | + where act_prize_id = :id;`, {id}) | ||
586 | + ]).then(result => { | ||
587 | + let resData = {}; | ||
588 | + let [product, content] = result; | ||
589 | + | ||
590 | + if (product && product.length) { | ||
591 | + resData = product[0]; | ||
592 | + resData.content = _.sortBy(content || [], o => { | ||
593 | + return o.sort; | ||
594 | + }); | ||
595 | + | ||
596 | + resData.time = `${timeFormat(resData.start_time)} - ${timeFormat(resData.end_time)}`; | ||
597 | + } | ||
598 | + | ||
599 | + return resData; | ||
600 | + }); | ||
601 | + } | ||
602 | + | ||
603 | + saveZerobuyContent(params) { | ||
604 | + let sqls = []; | ||
605 | + | ||
606 | + let times = _.split(params.time, ' - ', 2); | ||
607 | + let proParams = { | ||
608 | + id: params.id, | ||
609 | + name: params.name, | ||
610 | + price: params.price, | ||
611 | + sort: params.sort || 0, | ||
612 | + cover: params.cover, | ||
613 | + limit: params.limit, | ||
614 | + startTime: Date.parse(new Date(_.trim(times[0]).replace(/-/g, '/'))) / 1000, | ||
615 | + endTime: Date.parse(new Date(_.trim(times[1]).replace(/-/g, '/'))) / 1000 | ||
616 | + }; | ||
617 | + | ||
618 | + if (params.id) { | ||
619 | + sqls.push(mysqlCli.update(`update ${TABLE_ACT_PRIZE_PRODUCT} set | ||
620 | + name = :name, price = :price, \`limit\` = :limit, | ||
621 | + cover_img = :cover, sort = :sort, | ||
622 | + start_time = :startTime, end_time = :endTime | ||
623 | + where id = :id`, proParams)); | ||
624 | + | ||
625 | + // 更新楼层 | ||
626 | + let editFloors = params.editFloors ? parseJSON(params.editFloors) : ''; | ||
627 | + | ||
628 | + if (editFloors && editFloors.length) { | ||
629 | + let editParams = {}; | ||
630 | + let ids = []; | ||
631 | + let contentWhen = []; | ||
632 | + let sortWhen = []; | ||
633 | + | ||
634 | + _.forEach(editFloors, (value, index) => { | ||
635 | + let id = parseInt(value.id, 10); | ||
636 | + let contentKey = `content${index}`; | ||
637 | + let sortKey = `sort${index}`; | ||
638 | + | ||
639 | + if (!id) { | ||
640 | + return; | ||
641 | + } | ||
642 | + | ||
643 | + ids.push(id); | ||
644 | + contentWhen.push(`when ${id} then :${contentKey}`); | ||
645 | + sortWhen.push(`when ${id} then :${sortKey}`); | ||
646 | + editParams[contentKey] = value.content; | ||
647 | + editParams[sortKey] = value.sort; | ||
648 | + }); | ||
649 | + | ||
650 | + if (ids.length) { | ||
651 | + sqls.push(mysqlCli.update(`update ${TABLE_ACT_PRIZE_PRODUCT_CONTENT} set | ||
652 | + content = case id ${contentWhen.join(' ')} end, | ||
653 | + sort = case id ${sortWhen.join(' ')} end | ||
654 | + where id in (${ids.join(',')})`, editParams)); | ||
655 | + } | ||
656 | + } | ||
657 | + | ||
658 | + // 删除楼层 | ||
659 | + let deleteFloors = params.deleteFloors ? parseJSON(params.deleteFloors) : ''; | ||
660 | + | ||
661 | + if (deleteFloors && deleteFloors.length) { | ||
662 | + _.remove(deleteFloors, n => { | ||
663 | + return !(+n); | ||
664 | + }); | ||
665 | + | ||
666 | + if (deleteFloors.length) { | ||
667 | + sqls.push(mysqlCli.delete(`delete from ${TABLE_ACT_PRIZE_PRODUCT_CONTENT} | ||
668 | + where id in (${deleteFloors.join(',')})`, {})); | ||
669 | + } | ||
670 | + } | ||
671 | + } else { | ||
672 | + sqls.push(mysqlCli.insert(`insert into ${TABLE_ACT_PRIZE_PRODUCT} ( | ||
673 | + name, price, \`limit\`, sort, cover_img, start_time, end_time) values ( | ||
674 | + :name, :price, :limit, :sort, :cover, :startTime, :endTime | ||
675 | + )`, proParams)); | ||
676 | + } | ||
677 | + | ||
678 | + return Promise.all(sqls).then(result => { | ||
679 | + let pid = params.id || result[0]; | ||
680 | + | ||
681 | + // 删除楼层 | ||
682 | + let newFloors = params.newFloors ? parseJSON(params.newFloors) : ''; | ||
683 | + | ||
684 | + if (newFloors && newFloors.length) { | ||
685 | + let unionParams = {}; | ||
686 | + let union = []; | ||
687 | + | ||
688 | + _.forEach(newFloors, (value, index) => { | ||
689 | + if (!value.content) { | ||
690 | + return; | ||
691 | + } | ||
692 | + | ||
693 | + let typeKey = `type${index}`; | ||
694 | + let contentKey = `content${index}`; | ||
695 | + let sortKey = `sort${index}`; | ||
696 | + | ||
697 | + unionParams[typeKey] = value.type; | ||
698 | + unionParams[contentKey] = value.content; | ||
699 | + unionParams[sortKey] = value.sort; | ||
700 | + | ||
701 | + union.push(`select ${pid}, :${typeKey}, :${contentKey}, :${sortKey}`); | ||
702 | + }); | ||
703 | + | ||
704 | + if (union.length) { | ||
705 | + mysqlCli.insert(`insert into ${TABLE_ACT_PRIZE_PRODUCT_CONTENT} ( | ||
706 | + act_prize_id, floor_type, content, sort) | ||
707 | + ${union.join(' union all')}`, unionParams); | ||
708 | + } | ||
709 | + } | ||
710 | + | ||
711 | + return { | ||
712 | + code: 200, | ||
713 | + data: { | ||
714 | + id: pid | ||
715 | + } | ||
716 | + }; | ||
717 | + }); | ||
718 | + } | ||
568 | } | 719 | } |
569 | 720 | ||
570 | module.exports = AdminModel; | 721 | module.exports = AdminModel; |
@@ -24,6 +24,8 @@ router.get('/activity/zerobuy', activity.zeroBuyList); | @@ -24,6 +24,8 @@ router.get('/activity/zerobuy', activity.zeroBuyList); | ||
24 | router.post('/activity/zerobuy/switch', activity.zeroBuySwitch); | 24 | router.post('/activity/zerobuy/switch', activity.zeroBuySwitch); |
25 | router.post('/activity/zerobuy/publish', activity.zeroBuyPublish); | 25 | router.post('/activity/zerobuy/publish', activity.zeroBuyPublish); |
26 | router.get('/activity/zerobuy/export', activity.zeroBuyExport); | 26 | router.get('/activity/zerobuy/export', activity.zeroBuyExport); |
27 | +router.get('/activity/zerobuy/edit', activity.zeroBuyEdit); | ||
28 | +router.post('/activity/zerobuy/save', activity.zeroBuySave); | ||
27 | 29 | ||
28 | // 用户管理[page] | 30 | // 用户管理[page] |
29 | router.get('/user/list', user.userListPage); | 31 | router.get('/user/list', user.userListPage); |
1 | +<div class="right_col" role="main"> | ||
2 | + <div class="col-md-12 col-sm-12 col-xs-12"> | ||
3 | + <div class="x_panel"> | ||
4 | + {{# content}} | ||
5 | + <div class="x_title"> | ||
6 | + <h2>基本信息</h2> | ||
7 | + <div class="clearfix"></div> | ||
8 | + </div> | ||
9 | + <form id="createForm" class="form-horizontal form-label-left"> | ||
10 | + <input class="form-imput" type="hidden" data-type="id" value="{{id}}"> | ||
11 | + <div class="item form-group"> | ||
12 | + <label class="control-label col-md-3 col-sm-3 col-xs-12" for="actName"> | ||
13 | + 商品名称<span class="required">*</span> | ||
14 | + </label> | ||
15 | + <div class="col-md-6 col-sm-6 col-xs-12"> | ||
16 | + <input class="form-control col-md-7 col-xs-12 form-imput" | ||
17 | + data-type="name" | ||
18 | + data-toggle="tooltip" | ||
19 | + data-placement="bottom" | ||
20 | + title="商品名称不能为空" | ||
21 | + name="actName" | ||
22 | + type="text" | ||
23 | + maxlength="50" | ||
24 | + value="{{name}}"> | ||
25 | + </div> | ||
26 | + </div> | ||
27 | + <div class="item form-group"> | ||
28 | + <label class="control-label col-md-3 col-sm-3 col-xs-12" for="actName"> | ||
29 | + 商品图片<span class="required">*</span> | ||
30 | + </label> | ||
31 | + <div class="col-md-6 col-sm-6 col-xs-12"> | ||
32 | + <img src="{{cover_img}}" class="col-md-6 product-thumb {{#unless cover_img}}hide{{/unless}}"> | ||
33 | + | ||
34 | + <button type="button" class="btn btn-primary btn-upload-thumb" data-cover="{{cover_img}}">上传</button> | ||
35 | + </div> | ||
36 | + </div> | ||
37 | + <div class="item form-group"> | ||
38 | + <label class="control-label col-md-3 col-sm-3 col-xs-12" for="actName"> | ||
39 | + 商品价格<span class="required">*</span> | ||
40 | + </label> | ||
41 | + <div class="col-md-6 col-sm-6 col-xs-12"> | ||
42 | + <input class="form-control col-md-7 col-xs-12 form-imput" | ||
43 | + data-type="price" | ||
44 | + data-toggle="tooltip" | ||
45 | + data-placement="bottom" | ||
46 | + title="商品价格不能为空" | ||
47 | + name="actName" | ||
48 | + type="text" | ||
49 | + maxlength="10" | ||
50 | + value="{{price}}"> | ||
51 | + </div> | ||
52 | + </div> | ||
53 | + <div class="item form-group"> | ||
54 | + <label class="control-label col-md-3 col-sm-3 col-xs-12" for="activityTime">活动有效时间<span | ||
55 | + class="required">*</span> | ||
56 | + </label> | ||
57 | + <div class="col-md-6 col-sm-6 col-xs-12"> | ||
58 | + <div class="input-prepend input-group"> | ||
59 | + <span class="add-on input-group-addon"><i | ||
60 | + class="glyphicon glyphicon-calendar fa fa-calendar"></i></span> | ||
61 | + <input type="text" name="activityTime" id="activityTime" | ||
62 | + class="form-control col-md-7 col-xs-12 form-imput" | ||
63 | + data-type="time" | ||
64 | + placeholder="开始时间 - 结束时间" | ||
65 | + value="{{time}}"/> | ||
66 | + </div> | ||
67 | + </div> | ||
68 | + </div> | ||
69 | + <div class="item form-group"> | ||
70 | + <label class="control-label col-md-3 col-sm-3 col-xs-12" for="actName">开奖需要人数<span | ||
71 | + class="required">*</span> | ||
72 | + </label> | ||
73 | + <div class="col-md-2 col-sm-2 col-xs-12"> | ||
74 | + <input id="actVoteLimit" class="form-control col-md-2 form-imput" | ||
75 | + data-type="limit" | ||
76 | + data-toggle="tooltip" data-placement="bottom" title="开奖需要人数" | ||
77 | + name="actVoteLimit" | ||
78 | + type="text" | ||
79 | + maxlength="10" | ||
80 | + value="{{limit}}"> | ||
81 | + </div> | ||
82 | + </div> | ||
83 | + <div class="item form-group"> | ||
84 | + <label class="control-label col-md-3 col-sm-3 col-xs-12" for="actName">排序<span | ||
85 | + class="required">*</span> | ||
86 | + </label> | ||
87 | + <div class="col-md-2 col-sm-2 col-xs-12"> | ||
88 | + <input id="actVoteLimit" class="form-control col-md-2 form-imput" | ||
89 | + data-type="sort" | ||
90 | + data-toggle="tooltip" data-placement="bottom" title="排序" | ||
91 | + name="actVoteLimit" | ||
92 | + type="text" | ||
93 | + maxlength="10" | ||
94 | + value="{{sort}}"> | ||
95 | + </div> | ||
96 | + </div> | ||
97 | + </form> | ||
98 | + <div class="x_title"> | ||
99 | + <h2>详情内容</h2> | ||
100 | + <div class="clearfix"></div> | ||
101 | + </div> | ||
102 | + <div> | ||
103 | + <div class="col-md-6 col-md-offset-3 floor-view-box"> | ||
104 | + {{# content}} | ||
105 | + <div class="floor-item" | ||
106 | + data-id="{{id}}" | ||
107 | + data-sort="{{sort}}" | ||
108 | + data-content="{{content}}" | ||
109 | + {{#isEqualOr floor_type 1}} | ||
110 | + data-type="text"> | ||
111 | + | ||
112 | + <p class="item-content">{{content}}</p | ||
113 | + {{/isEqualOr}} | ||
114 | + {{#isEqualOr floor_type 2}} | ||
115 | + data-type="img"> | ||
116 | + <img src="{{content}}" class="item-content" | ||
117 | + {{/isEqualOr}} | ||
118 | + {{#isEqualOr floor_type 3}} | ||
119 | + data-type="video"> | ||
120 | + <video src="{{content}}" class="item-content"> | ||
121 | + 您的浏览器不支持 video 标签。 | ||
122 | + </video> | ||
123 | + {{/isEqualOr}} | ||
124 | + > | ||
125 | + | ||
126 | + <div class="option-btns"> | ||
127 | + <span class="glyphicon glyphicon-arrow-up up-item-btn"></span> | ||
128 | + <span class="glyphicon glyphicon-arrow-down down-item-btn"></span> | ||
129 | + </div> | ||
130 | + <span class="del-item-btn">删除</span> | ||
131 | + </div> | ||
132 | + {{/ content}} | ||
133 | + </div> | ||
134 | + <div class="col-md-6 col-md-offset-3"> | ||
135 | + <button type="button" class="btn btn-primary btn-add-floor" data-type="text">文本</button> | ||
136 | + <button type="button" class="btn btn-primary btn-add-floor" data-type="img">图片</button> | ||
137 | + <button type="button" class="btn btn-primary btn-add-floor" data-type="video">视频</button> | ||
138 | + </div> | ||
139 | + <div class="col-md-2 col-md-offset-10 action-wrap"> | ||
140 | + <button type="button" class="btn btn-primary btn-save-activity">保存</button> | ||
141 | + </div> | ||
142 | + </div> | ||
143 | + <a id="upload-btn"></a> | ||
144 | + | ||
145 | + {{/ content}} | ||
146 | + </div> | ||
147 | + </div> | ||
148 | +</div> |
1 | <!-- page content --> | 1 | <!-- page content --> |
2 | -<div class="right_col" role="main"> | 2 | +<div class="right_col zerobuy-list-page" role="main"> |
3 | <div class="col-md-12 col-sm-12 col-xs-12"> | 3 | <div class="col-md-12 col-sm-12 col-xs-12"> |
4 | <div class="x_panel"> | 4 | <div class="x_panel"> |
5 | + <div> | ||
6 | + <a href="/admin/activity/zerobuy/edit" class="btn btn-primary">创建抽奖活动</a> | ||
7 | + <div class="clearfix"></div> | ||
8 | +{{!-- | ||
9 | + <input type="text" class="form-control" aria-label="..."> | ||
10 | + <div class="btn-group"> | ||
11 | + <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">全部 <span class="caret"></span></button> | ||
12 | + <ul class="dropdown-menu"> | ||
13 | + <li><a href="#">关闭</a></li> | ||
14 | + <li><a href="#">开启</a></li> | ||
15 | + <li><a href="#">已开奖</a></li> | ||
16 | + </ul> | ||
17 | + </div> | ||
18 | + | ||
19 | + <button type="button" class="btn btn-primary">筛选</button> | ||
20 | + <button type="button" class="btn btn-primary">全部</button> --}} | ||
21 | + | ||
22 | + | ||
23 | + </div> | ||
24 | + | ||
5 | <table class="table table-bordered"> | 25 | <table class="table table-bordered"> |
6 | <thead> | 26 | <thead> |
7 | <tr class="headings"> | 27 | <tr class="headings"> |
1 | -require('admin/activity.page.css'); | 1 | +require('admin/zero-buy.page.css'); |
2 | +require('bootstrap-daterangepicker'); | ||
2 | 3 | ||
4 | +const _ = require('lodash'); | ||
3 | const $alert = $('#alert-modal'); | 5 | const $alert = $('#alert-modal'); |
4 | const $confirm = $('#confirm-modal'); | 6 | const $confirm = $('#confirm-modal'); |
5 | 7 | ||
6 | -function bindEvent() { | 8 | +function bindListPageEvent() { |
7 | const editFn = function() { | 9 | const editFn = function() { |
8 | window.open('/admin/activity/zerobuy/edit?id=' + | 10 | window.open('/admin/activity/zerobuy/edit?id=' + |
9 | $(this).data('id'), '_blank'); | 11 | $(this).data('id'), '_blank'); |
@@ -61,5 +63,342 @@ function bindEvent() { | @@ -61,5 +63,342 @@ function bindEvent() { | ||
61 | $('.sure-publish-btn').on('click', publishFn); | 63 | $('.sure-publish-btn').on('click', publishFn); |
62 | } | 64 | } |
63 | 65 | ||
66 | +let uploadedFn; | ||
67 | +let $upload; | ||
64 | 68 | ||
65 | -bindEvent(); | 69 | +function initUpload() { |
70 | + $upload = $('#upload-btn'); | ||
71 | + | ||
72 | + if (!$upload.length) { | ||
73 | + return; | ||
74 | + } | ||
75 | + | ||
76 | + const imgArr = ['image/jpeg', 'image/jpg', 'image/png']; | ||
77 | + | ||
78 | + // why? reference: https://github.com/qiniu/js-sdk/issues/266 | ||
79 | + Promise.all([ | ||
80 | + require('mOxie/bin/js/moxie'), | ||
81 | + require('plupload/js/plupload.dev'), | ||
82 | + require('qiniu-js') | ||
83 | + ]).then(([moxie, plupload]) => { | ||
84 | + window.moxie = moxie; | ||
85 | + window.plupload = plupload; | ||
86 | + | ||
87 | + Qiniu.uploader({ // eslint-disable-line | ||
88 | + runtimes: 'html5,flash,html4', | ||
89 | + browse_button: 'upload-btn', | ||
90 | + uptoken_url: '/api/getToken', | ||
91 | + unique_names: true, | ||
92 | + multi_selection: false, | ||
93 | + filters: { | ||
94 | + mime_types: [{ | ||
95 | + extensions: 'jpg,jpeg,png,mp4' | ||
96 | + }] | ||
97 | + }, | ||
98 | + dragdrop: false, | ||
99 | + domain: 'http://img01.yohoboys.com/', | ||
100 | + max_file_size: '10mb', | ||
101 | + max_retries: 3, | ||
102 | + chunk_size: '10mb', | ||
103 | + auto_start: true, | ||
104 | + init: { | ||
105 | + BeforeUpload: function(up) { | ||
106 | + window.checkup = up; | ||
107 | + }, | ||
108 | + UploadProgress: function() { | ||
109 | + console.log('上传中...'); | ||
110 | + }, | ||
111 | + FileUploaded: function(up, file, info) { | ||
112 | + var domain = up.getOption('domain'); | ||
113 | + var res = JSON.parse(info.response); | ||
114 | + var url = domain + res.key; | ||
115 | + | ||
116 | + uploadedFn && uploadedFn(url, imgArr.indexOf(file.type) >= 0); | ||
117 | + }, | ||
118 | + Error: function(up, err, errTip) { | ||
119 | + console.log(err, errTip); | ||
120 | + } | ||
121 | + } | ||
122 | + }); | ||
123 | + }); | ||
124 | +} | ||
125 | + | ||
126 | +function generateCid(id) { | ||
127 | + id = parseInt(id, 10) || 0; | ||
128 | + | ||
129 | + return Math.floor(Date.now() + Math.random() * 10000000000 * (id + 1)); | ||
130 | +} | ||
131 | + | ||
132 | +function bindEditPageEvent() { | ||
133 | + initUpload(); | ||
134 | + | ||
135 | + let $floorBox = $('.floor-view-box'); | ||
136 | + let floorContent = {}; | ||
137 | + const typeName = { | ||
138 | + text: '文本', | ||
139 | + img: '图片', | ||
140 | + video: '视频' | ||
141 | + }; | ||
142 | + | ||
143 | + const typeNum = { | ||
144 | + text: 1, | ||
145 | + img: 2, | ||
146 | + video: 3 | ||
147 | + }; | ||
148 | + | ||
149 | + function packInfo() { | ||
150 | + let resData = {}; | ||
151 | + let error; | ||
152 | + | ||
153 | + $('.form-imput').each(function() { | ||
154 | + let $this = $(this); | ||
155 | + let val = $this.val(); | ||
156 | + let data = $this.data(); | ||
157 | + | ||
158 | + if (!val && !error && data.type !== 'id') { | ||
159 | + error = data.empty || `请填写${data.type}`; | ||
160 | + } | ||
161 | + | ||
162 | + resData[data.type] = val; | ||
163 | + }); | ||
164 | + | ||
165 | + if (error) { | ||
166 | + alert(error); | ||
167 | + return; | ||
168 | + } | ||
169 | + | ||
170 | + resData.cover = $('.btn-upload-thumb').data('cover'); | ||
171 | + | ||
172 | + if (!resData.cover) { | ||
173 | + alert('请上传商品图'); | ||
174 | + return; | ||
175 | + } | ||
176 | + | ||
177 | + let newFloors = []; | ||
178 | + let editFloors = []; | ||
179 | + let deleteFloors = []; | ||
180 | + let index = 0; | ||
181 | + | ||
182 | + $floorBox.children('.floor-item').each(function() { | ||
183 | + let item = floorContent[$(this).data('cid')]; | ||
184 | + | ||
185 | + if (!item) { | ||
186 | + return; | ||
187 | + } | ||
188 | + | ||
189 | + if (!item.id) { | ||
190 | + newFloors.push({ | ||
191 | + content: item.newContent, | ||
192 | + sort: index | ||
193 | + }); | ||
194 | + } else if (item.newContent || +item.sort !== index) { | ||
195 | + editFloors.push({ | ||
196 | + id: item.id, | ||
197 | + type: typeNum[item.type] || 1, | ||
198 | + content: item.newContent || item.content, | ||
199 | + sort: index | ||
200 | + }); | ||
201 | + } | ||
202 | + index++; | ||
203 | + }); | ||
204 | + | ||
205 | + for (let i in floorContent) { | ||
206 | + if (floorContent.hasOwnProperty(i) && floorContent[i].id && floorContent[i].delete) { | ||
207 | + deleteFloors.push(floorContent[i].id); | ||
208 | + } | ||
209 | + } | ||
210 | + | ||
211 | + return _.assign(resData, { | ||
212 | + newFloors: newFloors.length ? JSON.stringify(newFloors) : '', | ||
213 | + editFloors: editFloors.length ? JSON.stringify(editFloors) : '', | ||
214 | + deleteFloors: deleteFloors.length ? JSON.stringify(deleteFloors) : '' | ||
215 | + }); | ||
216 | + } | ||
217 | + | ||
218 | + function GenUploadedFn($dom, isThumb) { | ||
219 | + if (isThumb) { | ||
220 | + return function(url, isImg) { | ||
221 | + if (!isImg) { | ||
222 | + alert('请上传图片'); | ||
223 | + } | ||
224 | + | ||
225 | + $dom.prev().attr('src', url).removeClass('hide'); | ||
226 | + $dom.data('cover', url); | ||
227 | + }; | ||
228 | + } | ||
229 | + | ||
230 | + return function(url, isImg) { | ||
231 | + let cid = $dom.data('cid'); | ||
232 | + let info = floorContent[cid]; | ||
233 | + let type = isImg ? 'img' : 'video'; | ||
234 | + let $content = $dom.children('.item-content'); | ||
235 | + | ||
236 | + info.newContent = url; | ||
237 | + | ||
238 | + if (info.type !== type || $content.hasClass('item-default')) { | ||
239 | + info.type = type; | ||
240 | + $content.remove(); | ||
241 | + $content.length = 0; | ||
242 | + } | ||
243 | + | ||
244 | + if ($content.length) { | ||
245 | + $content.attr('src', url); | ||
246 | + return; | ||
247 | + } | ||
248 | + | ||
249 | + console.log(isImg); | ||
250 | + if (isImg) { | ||
251 | + $dom.append(`<img src="${url}" class="item-content">`); | ||
252 | + } else { | ||
253 | + $dom.append(`<video src="${url}" class="item-content">您的浏览器不支持video标签。</video>`); | ||
254 | + } | ||
255 | + }; | ||
256 | + } | ||
257 | + | ||
258 | + $floorBox.children('.floor-item').each(() => { | ||
259 | + let $this = $(this); | ||
260 | + let data = $this.data(); | ||
261 | + let cid = generateCid(data.id); | ||
262 | + | ||
263 | + $this.data('cid', cid); | ||
264 | + floorContent[cid] = data; | ||
265 | + }); | ||
266 | + | ||
267 | + if (typeof ($.fn.daterangepicker) !== 'undefined') { | ||
268 | + $('#activityTime').daterangepicker({ | ||
269 | + timePicker: true, | ||
270 | + timePickerIncrement: 30, | ||
271 | + locale: { | ||
272 | + format: 'YYYY-MM-DD HH:mm:ss' | ||
273 | + } | ||
274 | + }); | ||
275 | + } | ||
276 | + | ||
277 | + $('.btn-upload-thumb').on('click', function() { | ||
278 | + uploadedFn = new GenUploadedFn($(this), true); | ||
279 | + $upload[0].click(); | ||
280 | + }); | ||
281 | + | ||
282 | + $('.floor-view-box').on('click', '.option-btns', function(e) { | ||
283 | + if (e && e.stopPropagation) { | ||
284 | + e.stopPropagation(); | ||
285 | + } else { | ||
286 | + window.event.cancelBubble = true; | ||
287 | + } | ||
288 | + | ||
289 | + let $this = $(e.target); | ||
290 | + let $parent = $this.closest('.floor-item'); | ||
291 | + | ||
292 | + if ($this.hasClass('up-item-btn')) { | ||
293 | + $parent.prev().before($parent); | ||
294 | + } else if ($this.hasClass('down-item-btn')) { | ||
295 | + $parent.next().after($parent); | ||
296 | + } | ||
297 | + }).on('click', '.del-item-btn', function(e) { | ||
298 | + if (e && e.stopPropagation) { | ||
299 | + e.stopPropagation(); | ||
300 | + } else { | ||
301 | + window.event.cancelBubble = true; | ||
302 | + } | ||
303 | + | ||
304 | + let $this = $(this).closest('.floor-item'); | ||
305 | + let cid = $this.data('cid'); | ||
306 | + | ||
307 | + if (floorContent[cid].id) { | ||
308 | + floorContent[cid].delete = true; | ||
309 | + } else { | ||
310 | + delete floorContent[cid]; | ||
311 | + } | ||
312 | + | ||
313 | + $this.remove(); | ||
314 | + }).on('click', '.edit-text', function(e) { | ||
315 | + if (e && e.stopPropagation) { | ||
316 | + e.stopPropagation(); | ||
317 | + } else { | ||
318 | + window.event.cancelBubble = true; | ||
319 | + } | ||
320 | + }).on('click', '.floor-item', function() { | ||
321 | + let $this = $(this); | ||
322 | + let data = $this.data(); | ||
323 | + | ||
324 | + switch (data.type) { | ||
325 | + case 'img': | ||
326 | + case 'video': | ||
327 | + uploadedFn = new GenUploadedFn($this); | ||
328 | + $upload[0].click(); | ||
329 | + break; | ||
330 | + default: | ||
331 | + let info = floorContent[data.cid]; | ||
332 | + let content = info.newContent || info.content; | ||
333 | + let $dom = $(`<textarea class="edit-text form-control">${content}</textarea>`); | ||
334 | + | ||
335 | + $dom.blur(function() { | ||
336 | + let val = $dom.val(); | ||
337 | + | ||
338 | + if (content !== val) { | ||
339 | + info.newContent = val; | ||
340 | + $this.children('.item-content').html(val); | ||
341 | + } | ||
342 | + | ||
343 | + $dom.remove(); | ||
344 | + }); | ||
345 | + | ||
346 | + $this.append($dom); | ||
347 | + break; | ||
348 | + } | ||
349 | + }); | ||
350 | + | ||
351 | + $('.btn-add-floor').on('click', function() { | ||
352 | + let $this = $(this); | ||
353 | + let data = { | ||
354 | + cid: generateCid(), | ||
355 | + type: $this.data('type') | ||
356 | + }; | ||
357 | + | ||
358 | + | ||
359 | + let $addDom = $('<div class="floor-item">' + | ||
360 | + '<p class="item-content item-default">' + typeName[data.type] + '</p>' + | ||
361 | + '<div class="option-btns">' + | ||
362 | + '<span class="glyphicon glyphicon-arrow-up up-item-btn"></span>' + | ||
363 | + '<span class="glyphicon glyphicon-arrow-down down-item-btn"></span>' + | ||
364 | + '</div>' + | ||
365 | + '<span class="del-item-btn">删除</span>' + | ||
366 | + '</div>'); | ||
367 | + | ||
368 | + | ||
369 | + $addDom.data(data); | ||
370 | + floorContent[data.cid] = data; | ||
371 | + | ||
372 | + $floorBox.append($addDom); | ||
373 | + }); | ||
374 | + | ||
375 | + $('.btn-save-activity').on('click', function() { | ||
376 | + let info = packInfo(); | ||
377 | + | ||
378 | + if (!info || window.saveing) { | ||
379 | + return; | ||
380 | + } | ||
381 | + | ||
382 | + window.saveing = true; | ||
383 | + | ||
384 | + $.ajax({ | ||
385 | + method: 'post', | ||
386 | + url: '/admin/activity/zerobuy/save', | ||
387 | + data: info | ||
388 | + }).then(res => { | ||
389 | + window.saveing = false; | ||
390 | + if (res.code === 200) { | ||
391 | + alert('保存成功'); | ||
392 | + location.href = '/admin/activity/zerobuy/edit?id=' + res.data.id; | ||
393 | + } else { | ||
394 | + alert(res.message || '保存失败'); | ||
395 | + } | ||
396 | + }); | ||
397 | + }); | ||
398 | +} | ||
399 | + | ||
400 | +if ($('.zerobuy-list-page').length) { | ||
401 | + bindListPageEvent(); | ||
402 | +} else { | ||
403 | + bindEditPageEvent(); | ||
404 | +} |
public/scss/admin/zero-buy.page.css
0 → 100644
1 | +@import '~bootstrap-daterangepicker'; | ||
2 | + | ||
3 | +.floor-view-box { | ||
4 | + min-height: 300px; | ||
5 | + border: 1px solid #ccc; | ||
6 | + border-radius: 4px; | ||
7 | + margin-top: 30px; | ||
8 | + margin-bottom: 30px; | ||
9 | + padding: 0; | ||
10 | +} | ||
11 | + | ||
12 | +.floor-item { | ||
13 | + position: relative; | ||
14 | + min-height: 100px; | ||
15 | + background-color: #eee; | ||
16 | +} | ||
17 | + | ||
18 | +.option-btns { | ||
19 | + position: absolute; | ||
20 | + top: 0; | ||
21 | + right: 10px; | ||
22 | + font-size: 20px; | ||
23 | +} | ||
24 | + | ||
25 | +.option-btns > * { | ||
26 | + display: inline-block; | ||
27 | + width: 30px; | ||
28 | + text-align: center; | ||
29 | + cursor: pointer; | ||
30 | +} | ||
31 | + | ||
32 | +.del-item-btn { | ||
33 | + position: absolute; | ||
34 | + top: 0; | ||
35 | + right: -60px; | ||
36 | + line-height: 30px; | ||
37 | + width: 60px; | ||
38 | + background-color: #d44950; | ||
39 | + color: #fff; | ||
40 | + text-align: center; | ||
41 | + display: none; | ||
42 | + cursor: pointer; | ||
43 | +} | ||
44 | + | ||
45 | +.floor-item > textarea { | ||
46 | + position: absolute; | ||
47 | + top: 28px; | ||
48 | + left: 0; | ||
49 | + right: 0; | ||
50 | + bottom: 0; | ||
51 | +} | ||
52 | + | ||
53 | +.floor-item > img, | ||
54 | +.floor-item > video { | ||
55 | + width: 100%; | ||
56 | +} | ||
57 | + | ||
58 | +.floor-item > p { | ||
59 | + padding: 30px 10px; | ||
60 | + text-align: center; | ||
61 | + word-break: break-all; | ||
62 | +} | ||
63 | + | ||
64 | +.floor-item:hover .del-item-btn { | ||
65 | + display: block; | ||
66 | +} |
-
Please register or login to post a comment