初始上传
85
addon/seckill/api/controller/Ordercreate.php
Executable file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* Index.php
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
* @author : niuteam
|
||||
* @date : 2022.8.8
|
||||
* @version : v5.0.0.1
|
||||
*/
|
||||
|
||||
namespace addon\seckill\api\controller;
|
||||
|
||||
use addon\seckill\model\SeckillOrderCreate as OrderCreateModel;
|
||||
use app\api\controller\BaseOrderCreateApi;
|
||||
|
||||
/**
|
||||
* 订单创建
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
class Ordercreate extends BaseOrderCreateApi
|
||||
{
|
||||
/**
|
||||
* 创建订单
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$token = $this->checkToken();
|
||||
if ($token[ 'code' ] < 0) return $this->response($token);
|
||||
$order_create = new OrderCreateModel();
|
||||
$data = [
|
||||
'order_key' => $this->params['order_key'] ?? '',
|
||||
'is_balance' => $this->params['is_balance'] ?? 0,//是否使用余额
|
||||
];
|
||||
$res = $order_create->setParam(array_merge($data, $this->getInputParam(), $this->getCommonParam(), $this->getDeliveryParam(), $this->getInvoiceParam()))->create();
|
||||
return $this->response($res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 计算信息
|
||||
*/
|
||||
public function calculate()
|
||||
{
|
||||
$token = $this->checkToken();
|
||||
if ($token[ 'code' ] < 0) return $this->response($token);
|
||||
$order_create = new OrderCreateModel();
|
||||
$data = [
|
||||
'order_key' => $this->params['order_key'] ?? '',//订单缓存
|
||||
'is_balance' => $this->params['is_balance'] ?? 0,//是否使用余额
|
||||
];
|
||||
$res = $order_create->setParam(array_merge($data, $this->getCommonParam(), $this->getDeliveryParam(), $this->getInvoiceParam()))->confirm();
|
||||
return $this->response($this->success($res));
|
||||
}
|
||||
|
||||
/**
|
||||
* 待支付订单 数据初始化
|
||||
* @return string
|
||||
*/
|
||||
public function payment()
|
||||
{
|
||||
$token = $this->checkToken();
|
||||
if ($token[ 'code' ] < 0) return $this->response($token);
|
||||
$order_create = new OrderCreateModel();
|
||||
$data = [
|
||||
'id' => $this->params[ 'seckill_id' ] ?? '',//秒杀id
|
||||
'num' => $this->params[ 'num' ] ?? 1,//秒杀商品数量(买几套)
|
||||
'sku_id' => $this->params[ 'sku_id' ] ?? '',//
|
||||
];
|
||||
if (empty($data[ 'id' ])) {
|
||||
return $this->response($this->error('', '缺少必填参数商品数据'));
|
||||
}
|
||||
if ($data[ 'num' ] < 0) {
|
||||
return $this->response($this->error('', '商品数量不能小于0'));
|
||||
}
|
||||
$res = $order_create->setParam(array_merge($data, $this->getCommonParam(), $this->getDeliveryParam()))->orderPayment();
|
||||
return $this->response($this->success($res));
|
||||
}
|
||||
|
||||
}
|
||||
68
addon/seckill/api/controller/Seckill.php
Executable file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\api\controller;
|
||||
|
||||
use addon\seckill\model\Seckill as SeckillModel;
|
||||
use app\api\controller\BaseApi;
|
||||
|
||||
|
||||
/**
|
||||
* 秒杀
|
||||
*/
|
||||
class Seckill extends BaseApi
|
||||
{
|
||||
|
||||
/**
|
||||
* 列表信息
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
|
||||
$today_time = strtotime(date("Y-m-d"), time());
|
||||
$time = time() - $today_time;//当日时间戳
|
||||
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'seckill_end_time', '>=', $time ]
|
||||
];
|
||||
$order = 'seckill_start_time asc';
|
||||
$field = 'id,name,seckill_start_time,seckill_end_time';
|
||||
|
||||
$seckill_model = new SeckillModel();
|
||||
$today_list = $seckill_model->getGoodsSeckillTimeList($condition, $field, $order);
|
||||
$today_list = is_array($today_list[ 'data' ]) ? array_values($today_list[ 'data' ]) : [];
|
||||
foreach ($today_list as $key => $val) {
|
||||
$val = $seckill_model->transformSeckillTime($val);
|
||||
$today_list[ $key ][ 'seckill_start_time_show' ] = "{$val['start_hour']}:{$val['start_minute']}:{$val['start_second']}";
|
||||
$today_list[ $key ][ 'seckill_end_time_show' ] = "{$val['end_hour']}:{$val['end_minute']}:{$val['end_second']}";
|
||||
$today_list[ $key ][ 'type' ] = "today";
|
||||
}
|
||||
|
||||
$condition = [
|
||||
[ 'site_id', '=', $this->site_id ],
|
||||
[ 'seckill_end_time', '<', $time ]
|
||||
];
|
||||
|
||||
$tomorrow_list = $seckill_model->getGoodsSeckillTimeList($condition, $field, $order);
|
||||
$tomorrow_list = is_array($tomorrow_list[ 'data' ]) ? array_values($tomorrow_list[ 'data' ]) : [];
|
||||
foreach ($tomorrow_list as $key => $val) {
|
||||
$val = $seckill_model->transformSeckillTime($val);
|
||||
$tomorrow_list[ $key ][ 'seckill_start_time_show' ] = "{$val['start_hour']}:{$val['start_minute']}:{$val['start_second']}";
|
||||
$tomorrow_list[ $key ][ 'seckill_end_time_show' ] = "{$val['end_hour']}:{$val['end_minute']}:{$val['end_second']}";
|
||||
$tomorrow_list[ $key ][ 'type' ] = "tomorrow";
|
||||
}
|
||||
|
||||
$res = [
|
||||
'list' => array_merge($today_list, $tomorrow_list)
|
||||
];
|
||||
return $this->response($this->success($res));
|
||||
}
|
||||
}
|
||||
246
addon/seckill/api/controller/Seckillgoods.php
Executable file
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\api\controller;
|
||||
|
||||
use addon\seckill\model\Poster;
|
||||
use addon\seckill\model\Seckill as SeckillModel;
|
||||
use addon\seckill\model\SeckillOrder;
|
||||
use app\api\controller\BaseApi;
|
||||
use app\model\goods\GoodsApi;
|
||||
|
||||
/**
|
||||
* 秒杀商品
|
||||
*/
|
||||
class Seckillgoods extends BaseApi
|
||||
{
|
||||
|
||||
/**
|
||||
* 【PC端在用】基础信息
|
||||
*/
|
||||
public function info()
|
||||
{
|
||||
$token = $this->checkToken();
|
||||
|
||||
$seckill_id = $this->params[ 'seckill_id' ] ?? 0;
|
||||
$sku_id = $this->params[ 'sku_id' ] ?? 0;
|
||||
if (empty($seckill_id)) {
|
||||
return $this->response($this->error('', 'REQUEST_ID'));
|
||||
}
|
||||
if (empty($sku_id)) {
|
||||
return $this->response($this->error('', 'REQUEST_ID'));
|
||||
}
|
||||
$seckill_model = new SeckillModel();
|
||||
$order_model = new SeckillOrder();
|
||||
$condition = [
|
||||
[ 'ps.id', '=', $seckill_id ],
|
||||
[ 'psg.sku_id', '=', $sku_id ],
|
||||
[ 'psg.site_id', '=', $this->site_id ],
|
||||
[ 'psg.status', '=', 1 ],
|
||||
[ 'ps.status', '=', 1 ],
|
||||
[ 'g.goods_state', '=', 1 ],
|
||||
[ 'g.is_delete', '=', 0 ]
|
||||
];
|
||||
$goods_sku_detail = $seckill_model->getSeckillGoodsInfo($condition, '')[ 'data' ];
|
||||
|
||||
// 限购
|
||||
if ($token[ 'code' ] >= 0 && $goods_sku_detail[ 'max_buy' ] > 0) {
|
||||
$goods_sku_detail[ 'purchased_num' ] = $seckill_model->getGoodsPurchasedNum($goods_sku_detail[ 'sku_id' ], $this->member_id);
|
||||
$goods_sku_detail[ 'is_limit' ] = 1;
|
||||
$goods_sku_detail[ 'limit_type' ] = 2;
|
||||
}
|
||||
|
||||
$res[ 'goods_sku_detail' ] = $goods_sku_detail;
|
||||
if (!empty($goods_sku_detail)) {
|
||||
$num = $order_model->getGoodsSeckillNum($seckill_id);
|
||||
$time_data = $seckill_model->getSeckillInfo($seckill_id)[ 'data' ];
|
||||
$goods_sku_detail[ 'sale_num' ] = $num;
|
||||
$goods_sku_detail[ 'seckill_start_time' ] = $time_data[ 'seckill_start_time' ];
|
||||
$goods_sku_detail[ 'seckill_end_time' ] = $time_data[ 'seckill_end_time' ];
|
||||
//判断商品规格项
|
||||
$goods_spec_format = $seckill_model->getGoodsSpecFormat($seckill_id, $this->site_id, $goods_sku_detail[ 'goods_spec_format' ]);
|
||||
$res[ 'goods_sku_detail' ][ 'goods_spec_format' ] = json_encode($goods_spec_format);
|
||||
} else {
|
||||
$sku_id = $seckill_model->getGoodsSpecFormat($seckill_id, $this->site_id, '');
|
||||
$res = [ 'type' => 'again', 'sku_id' => $sku_id ];
|
||||
}
|
||||
return $this->response($this->success($res));
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情信息
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
$token = $this->checkToken();
|
||||
$seckill_id = $this->params[ 'seckill_id' ] ?? 0;
|
||||
if (empty($seckill_id)) {
|
||||
return $this->response($this->error('', 'REQUEST_ID'));
|
||||
}
|
||||
$seckill_model = new SeckillModel();
|
||||
$condition = [
|
||||
[ 'ps.id', '=', $seckill_id ],
|
||||
[ 'psg.site_id', '=', $this->site_id ],
|
||||
[ 'psg.status', '=', 1 ],
|
||||
[ 'ps.status', '=', 1 ],
|
||||
[ 'g.goods_state', '=', 1 ],
|
||||
[ 'g.is_delete', '=', 0 ]
|
||||
];
|
||||
$goods_sku_detail = $seckill_model->getSeckillGoodsInfo($condition)[ 'data' ];
|
||||
if (empty($goods_sku_detail)) return $this->response($this->error());
|
||||
|
||||
// 限购
|
||||
if ($token[ 'code' ] >= 0 && $goods_sku_detail[ 'max_buy' ] > 0) {
|
||||
$goods_sku_detail[ 'purchased_num' ] = $seckill_model->getGoodsPurchasedNum($goods_sku_detail[ 'sku_id' ], $this->member_id);
|
||||
$goods_sku_detail[ 'is_limit' ] = 1;
|
||||
$goods_sku_detail[ 'limit_type' ] = 2;
|
||||
}
|
||||
|
||||
$time_data = $seckill_model->getSeckillInfo($seckill_id)[ 'data' ];
|
||||
$goods_sku_detail[ 'seckill_start_time' ] = $time_data[ 'seckill_start_time' ];
|
||||
$goods_sku_detail[ 'seckill_end_time' ] = $time_data[ 'seckill_end_time' ];
|
||||
$goods_sku_detail[ 'time_list' ] = $time_data[ 'time_list' ];
|
||||
|
||||
$res[ 'goods_sku_detail' ] = $goods_sku_detail;
|
||||
|
||||
if (!empty($goods_sku_detail[ 'goods_spec_format' ])) {
|
||||
//判断商品规格项
|
||||
$goods_spec_format = $seckill_model->getGoodsSpecFormat($seckill_id, $this->site_id, $goods_sku_detail[ 'goods_spec_format' ]);
|
||||
$res[ 'goods_sku_detail' ][ 'goods_spec_format' ] = json_encode($goods_spec_format);
|
||||
}
|
||||
|
||||
// 处理公共数据
|
||||
$goods_sku_api = new GoodsApi();
|
||||
$goods_sku_api->handleGoodsDetailData($res[ 'goods_sku_detail' ], $this->member_id, $this->site_id);
|
||||
|
||||
return $this->response($this->success($res));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商品SKU集合
|
||||
* @return false|string
|
||||
*/
|
||||
public function goodsSku()
|
||||
{
|
||||
$token = $this->checkToken();
|
||||
|
||||
$goods_id = $this->params[ 'goods_id' ] ?? 0;
|
||||
$seckill_id = $this->params[ 'seckill_id' ] ?? 0;
|
||||
if (empty($goods_id)) {
|
||||
return $this->response($this->error('', 'REQUEST_ID'));
|
||||
}
|
||||
if (empty($seckill_id)) {
|
||||
return $this->response($this->error('', 'REQUEST_ID'));
|
||||
}
|
||||
$seckill_model = new SeckillModel();
|
||||
$condition = [
|
||||
[ 'ps.id', '=', $seckill_id ],
|
||||
[ 'psg.goods_id', '=', $goods_id ],
|
||||
[ 'psg.site_id', '=', $this->site_id ],
|
||||
[ 'psg.status', '=', 1 ],
|
||||
[ 'ps.status', '=', 1 ],
|
||||
[ 'g.goods_state', '=', 1 ],
|
||||
[ 'g.is_delete', '=', 0 ]
|
||||
];
|
||||
$list = $seckill_model->getSeckillGoodsSkuList($condition);
|
||||
if (!empty($list[ 'data' ])) {
|
||||
foreach ($list[ 'data' ] as $k => $v) {
|
||||
if (!empty($v[ 'goods_spec_format' ])) {
|
||||
//判断商品规格项
|
||||
$goods_spec_format = $seckill_model->getGoodsSpecFormat($seckill_id, $this->site_id, $v[ 'goods_spec_format' ]);
|
||||
$list[ 'data' ][ $k ][ 'goods_spec_format' ] = json_encode($goods_spec_format);
|
||||
}
|
||||
|
||||
// 限购
|
||||
if ($token[ 'code' ] >= 0 && $v[ 'max_buy' ] > 0) {
|
||||
$list[ 'data' ][ $k ][ 'purchased_num' ] = $seckill_model->getGoodsPurchasedNum($v[ 'sku_id' ], $this->member_id);
|
||||
$list[ 'data' ][ $k ][ 'is_limit' ] = 1;
|
||||
$list[ 'data' ][ $k ][ 'limit_type' ] = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->response($list);
|
||||
}
|
||||
|
||||
public function page()
|
||||
{
|
||||
$seckill_time_id = $this->params[ 'seckill_time_id' ] ?? 0;
|
||||
$seckill_time_type = $this->params[ 'seckill_time_type' ] ?? 'today';
|
||||
$page = $this->params[ 'page' ] ?? 1;
|
||||
$page_size = $this->params[ 'page_size' ] ?? PAGE_LIST_ROWS;
|
||||
if (empty($seckill_time_id)) {
|
||||
return $this->response($this->error('', 'REQUEST_SECKILL_ID'));
|
||||
}
|
||||
|
||||
$seckill_model = new SeckillModel();
|
||||
$res = $seckill_model->getSeckillGoodsPageList($seckill_time_id, $this->site_id, $page, $page_size, $seckill_time_type);
|
||||
foreach ($res[ 'data' ][ 'list' ] as $key => $val) {
|
||||
if ($val[ 'price' ] != 0) {
|
||||
$discount_rate = floor($val[ 'seckill_price' ] / $val[ 'price' ] * 100);
|
||||
} else {
|
||||
$discount_rate = 100;
|
||||
}
|
||||
$res[ 'data' ][ 'list' ][ $key ][ 'discount_rate' ] = $discount_rate;
|
||||
}
|
||||
return $this->response($res);
|
||||
}
|
||||
|
||||
public function lists()
|
||||
{
|
||||
$seckill_time_id = $this->params[ 'seckill_time_id' ] ?? 0;
|
||||
$num = $this->params[ 'num' ] ?? null;
|
||||
|
||||
if (empty($seckill_time_id)) {
|
||||
return $this->response($this->error('', 'REQUEST_SECKILL_ID'));
|
||||
}
|
||||
|
||||
$seckill_model = new SeckillModel();
|
||||
$res = $seckill_model->getSeckillList($seckill_time_id, $this->site_id, $num);
|
||||
$list = $res[ 'data' ];
|
||||
foreach ($list as $key => $val) {
|
||||
if ($val[ 'price' ] != 0) {
|
||||
$discount_rate = floor($val[ 'seckill_price' ] / $val[ 'price' ] * 100);
|
||||
} else {
|
||||
$discount_rate = 100;
|
||||
}
|
||||
$list[ $key ][ 'discount_rate' ] = $discount_rate;
|
||||
}
|
||||
|
||||
return $this->response($this->success($list));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品海报
|
||||
*/
|
||||
public function poster()
|
||||
{
|
||||
$this->checkToken();
|
||||
|
||||
$promotion_type = 'seckill';
|
||||
$qrcode_param = json_decode($this->params[ 'qrcode_param' ], true);
|
||||
$qrcode_param[ 'source_member' ] = $this->member_id;
|
||||
$poster = new Poster();
|
||||
$res = $poster->goods($this->params[ 'app_type' ], $this->params[ 'page' ], $qrcode_param, $promotion_type, $this->site_id);
|
||||
return $this->response($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享图片
|
||||
* @return false|string
|
||||
*/
|
||||
public function shareImg()
|
||||
{
|
||||
$qrcode_param = json_decode($this->params[ 'qrcode_param' ], true);
|
||||
|
||||
$poster = new Poster();
|
||||
$res = $poster->shareImg($this->params[ 'page' ] ?? '', $qrcode_param, $this->site_id);
|
||||
return $this->response($res);
|
||||
}
|
||||
}
|
||||
21
addon/seckill/component/controller/Seckill.php
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace addon\seckill\component\controller;
|
||||
|
||||
use app\component\controller\BaseDiyView;
|
||||
|
||||
/**
|
||||
* 秒杀模块·组件
|
||||
*
|
||||
*/
|
||||
class Seckill extends BaseDiyView
|
||||
{
|
||||
|
||||
/**
|
||||
* 设计界面
|
||||
*/
|
||||
public function design()
|
||||
{
|
||||
return $this->fetch("seckill/design.html");
|
||||
}
|
||||
}
|
||||
110
addon/seckill/component/view/seckill/css/design.css
Executable file
@@ -0,0 +1,110 @@
|
||||
@CHARSET "UTF-8";
|
||||
.component-seckill .seckill-list{overflow: hidden;}
|
||||
/* 样式:单列 */
|
||||
.component-seckill .seckill-list .row1-of1{}
|
||||
.component-seckill .seckill-list .row1-of1 .item{display: flex;margin-bottom: 10px;padding: 8px;}
|
||||
.component-seckill .seckill-list .row1-of1 .item:last-child{margin-bottom: 0;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .img-wrap{width: 100px;height: 100px;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .img-wrap > img{width: 100%;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content{display: flex;justify-content: space-between;flex-direction: column;flex: 1;margin-left: 10px;padding: 3px 0;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .goods-name {}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .progress {display: flex;align-items: center;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .progress .bg {width: 120px;height: 10px;border-radius: 10px;margin-right: 10px;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .progress .bg .curr {width: 70px;height: 10px;border-radius: 10px;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .progress .num {font-size: 12px;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .bottom-wrap {display: flex;justify-content: space-between;align-items: center;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .bottom-wrap .price-wrap {display: flex;align-items: baseline;font-size: 12px;flex-wrap: wrap;width: 130px;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .bottom-wrap .price-wrap .discount-price {font-weight: bold;margin-right: 5px;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .bottom-wrap .price-wrap .unit{font-size: 12px;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .bottom-wrap .price-wrap .price{font-size: 16px;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .bottom-wrap .original-price {font-size: 12px;text-decoration: line-through;}
|
||||
.component-seckill .seckill-list .row1-of1 .item .content .bottom-wrap button {height: 25px;line-height: 25px;padding: 0 8px;font-size: 12px;}
|
||||
/* 风格二 */
|
||||
.component-seckill .seckill-list.style-2 .row1-of1 .item{padding: 16px;}
|
||||
.component-seckill .seckill-list.style-2 .row1-of1 .item .img-wrap{position: relative;overflow: hidden;}
|
||||
.component-seckill .seckill-list.style-2 .row1-of1 .item .content .bottom-wrap .price-wrap{flex-direction: column-reverse;}
|
||||
.component-seckill .seckill-list.style-2 .row1-of1 .item .content .progress .bg .curr{position: relative;}
|
||||
.component-seckill .seckill-list.style-2 .row1-of1 .item .content .progress-bar{position: absolute;right: 0; width: 15px;height: 15px;top: 50%;transform: translateY(-50%);}
|
||||
.component-seckill .seckill-list.style-2 .row1-of1 .item .content .progress .num{color: #FF3D3D !important;}
|
||||
|
||||
|
||||
/* 样式:双列 */
|
||||
.component-seckill .seckill-list .row1-of2{display: flex;flex-wrap: wrap;}
|
||||
.component-seckill .seckill-list .row1-of2 .item{overflow: hidden;margin-right: 10px;margin-top: 10px;width: calc(50% - 5px);display: flex;flex-direction: column;box-sizing: border-box;}
|
||||
.component-seckill .seckill-list .row1-of2 .item:nth-child(2n){margin-right: 0;}
|
||||
.component-seckill .seckill-list .row1-of2 .item:nth-of-type(1), .component-seckill .seckill-list .row1-of2 .item:nth-of-type(2){margin-top: 0;}
|
||||
.component-seckill .seckill-list .row1-of2 .item .img-wrap{height: 170px;text-align: center;width: calc(100% + 2px);}
|
||||
.component-seckill .seckill-list .row1-of2 .item .img-wrap > img{width: 100%;height: 100%;}
|
||||
.component-seckill .seckill-list .row1-of2 .item .content{display: flex;flex-direction: column;flex: 1;padding: 5px 10px;position: relative;}
|
||||
.component-seckill .seckill-list .row1-of2 .item .content .goods-name{}
|
||||
.component-seckill .seckill-list .row1-of2 .item .content .discount-price{display: flex;align-items: baseline;margin-top: 5px;font-weight: bold;line-height: 1;}
|
||||
.component-seckill .seckill-list .row1-of2 .item .content .discount-price .unit{font-size: 12px;}
|
||||
.component-seckill .seckill-list .row1-of2 .item .content .discount-price .price{font-size: 16px;}
|
||||
.component-seckill .seckill-list .row1-of2 .item .content .bottom-wrap{display: flex;justify-content: space-between;align-items: flex-end;}
|
||||
.component-seckill .seckill-list .row1-of2 .item .content .bottom-wrap .original-price{font-size: 12px;text-decoration: line-through;}
|
||||
.component-seckill .seckill-list .row1-of2 .item .content .bottom-wrap button {height: 25px;line-height: 27px;padding: 0 8px;font-size: 12px;}
|
||||
|
||||
/* 样式:横向滑动 */
|
||||
.component-seckill .seckill-list .horizontal-slide{box-sizing: border-box;justify-content: space-between;white-space: nowrap;overflow: hidden;margin: 10px;}
|
||||
.component-seckill .seckill-list .horizontal-slide .item {width: 97px;overflow: hidden;display: inline-block;margin-right: 10px;box-sizing: border-box;margin-top: 4px;}
|
||||
.component-seckill .seckill-list .horizontal-slide .item .img-wrap {width: 97px;height: 97px;overflow: hidden;position: relative;}
|
||||
.component-seckill .seckill-list .horizontal-slide .item .img-wrap > img{width: calc(100% + 1px);}
|
||||
.component-seckill .seckill-list .horizontal-slide .item .content {padding: 5px 10px;}
|
||||
.component-seckill .seckill-list .horizontal-slide .item .content .discount-price{margin-top: 5px;font-weight: bold;line-height: 1;display: flex;align-items: flex-end;}
|
||||
.component-seckill .seckill-list .horizontal-slide .item .content .discount-price .tag{display: none;}
|
||||
.component-seckill .seckill-list .horizontal-slide .item .content .discount-price .unit{font-size: 12px;}
|
||||
.component-seckill .seckill-list .horizontal-slide .item .content .discount-price .price{font-size: 16px;}
|
||||
.component-seckill .seckill-list .horizontal-slide .item .content .original-price{margin-top: 2px;font-size: 12px;text-decoration: line-through;}
|
||||
|
||||
/* 横向滑动——样式2 */
|
||||
.component-seckill .seckill-list.style-2 .horizontal-slide{}
|
||||
.component-seckill .seckill-list.style-2 .horizontal-slide .item{}
|
||||
.component-seckill .seckill-list.style-2 .horizontal-slide .item .content{padding:5px 15px;text-align: center;}
|
||||
.component-seckill .seckill-list.style-2 .horizontal-slide .item .content .discount-price{background: linear-gradient(to right,#FF5F17,#FE2F18);position: relative;padding: 4px 2px 4px 10px;border-top-right-radius: 5px;border-bottom-right-radius: 5px;justify-content: center;}
|
||||
.component-seckill .seckill-list.style-2 .horizontal-slide .item .content .discount-price .tag{display: block;position: absolute;width: 13px;left:-5px;top:0;}
|
||||
.component-seckill .seckill-list.style-2 .horizontal-slide .item .content .discount-price span{color: #ffffff;font-size: 13px;}
|
||||
.component-seckill .seckill-list.style-2 .horizontal-slide .item .content .discount-price .unit{font-size: 13px;}
|
||||
.component-seckill .seckill-list.style-2 .horizontal-slide .item .content .discount-price .price{margin-left: 3px;}
|
||||
.component-seckill .seckill-list.style-2 .horizontal-slide .item .content .original-price{margin-top: 5px;}
|
||||
|
||||
/* 头部风格公共 */
|
||||
.component-seckill .title-wrap .left-img{max-height: 20px; max-width: 78px;}
|
||||
|
||||
/* 头部风格一 */
|
||||
.component-seckill .title-wrap.style-1{display: flex;justify-content: space-between;align-items: center;padding: 10px;}
|
||||
.component-seckill .title-wrap.style-1 .time{display: flex;align-items: center;line-height: 1;margin-right: auto;margin-left: 10px;}
|
||||
.component-seckill .title-wrap.style-1 .time .seckill-title-name.text{margin-right: 5px;font-size: 12px;}
|
||||
.component-seckill .title-wrap.style-1 .time .number{font-size: 12px;border-radius: 3px;padding: 2px;}
|
||||
.component-seckill .title-wrap.style-1 .time .symbol{margin: 0 3px;}
|
||||
.component-seckill .title-wrap.style-1 .more{display: flex;align-items: center;}
|
||||
|
||||
/* 头部风格二 */
|
||||
.component-seckill .title-wrap.style-2{display: flex;justify-content: space-between;align-items: center;padding: 10px;}
|
||||
.component-seckill .title-wrap.style-2 .time{display: flex;align-items: center;line-height: 1;margin-right: auto;margin-left: 10px;border-radius: 15px;padding: 0 10px;height: 22px;background-image: radial-gradient(transparent 50%, #fff);font-size: 12px;}
|
||||
.component-seckill .title-wrap.style-2 .time .seckill-title-name.icon{font-size: 12px;background-image: radial-gradient(transparent 35%, #fff);border-radius: 50%;position: relative;margin-left: -10px;height: 22px;width: 22px;line-height: 22px;text-align: center;margin-right: 3px;}
|
||||
.component-seckill .title-wrap.style-2 .time .seckill-title-name.text{display: none;}
|
||||
.component-seckill .title-wrap.style-2 .more{display: flex;align-items: center;}
|
||||
|
||||
/* 头部风格三 */
|
||||
.component-seckill .title-wrap.style-3{display: flex;justify-content: space-between;align-items: center;padding: 10px;margin-bottom: 10px;height: 44px;box-sizing: border-box;background-repeat: no-repeat;background-size: cover;line-height: 1;border-radius: 9px 9px 0 0;}
|
||||
.component-seckill .title-wrap.style-3 .time{display: flex;align-items: center;line-height: 1;margin-right: auto;margin-left: 10px;}
|
||||
.component-seckill .title-wrap.style-3 .time .seckill-title-name.text{margin-right: 5px;font-size: 12px;color:#fff;position: relative;}
|
||||
.component-seckill .title-wrap.style-3 .time .seckill-title-name.text:after{content: "";position: absolute;left: -5px;height: 12px;width: 1px;background-color: #fff;}
|
||||
.component-seckill .title-wrap.style-3 .time .number{font-size: 12px;border-radius: 3px;padding: 2px;}
|
||||
.component-seckill .title-wrap.style-3 .time .symbol{margin: 0 3px;}
|
||||
.component-seckill .title-wrap.style-3 .more{display: flex;align-items: center;}
|
||||
|
||||
/* 头部风格四 */
|
||||
.component-seckill .title-wrap.style-4{display: flex;justify-content: space-between;align-items: center;padding: 10px;margin-bottom: 10px;height: 44px;box-sizing: border-box;background-repeat: no-repeat;background-size: cover;line-height: 1;border-radius: 9px 9px 0 0;}
|
||||
.component-seckill .title-wrap.style-4 .time{display: flex;align-items: center;line-height: 1;}
|
||||
.component-seckill .title-wrap.style-4 .time .seckill-title-name.text{margin-right: 10px;font-size: 13px;color:#666666;}
|
||||
.component-seckill .title-wrap.style-4 .time .number{font-size: 12px;border-radius: 3px;padding: 2px;}
|
||||
.component-seckill .title-wrap.style-4 .time .symbol{margin: 0 3px;}
|
||||
|
||||
/* 秒杀头部弹窗样式 */
|
||||
.component-seckill .style-list-box-seckill{display: none;}
|
||||
.style-list-con-seckill{display: flex;flex-wrap: wrap;}
|
||||
.style-list-con-seckill .style-li-seckill{overflow: hidden;display: flex;align-items: center;justify-content: center;width: 280px;height: 100px;margin-right: 12px;margin-top: 15px;cursor: pointer;border: 1px solid #ededed;background: #f7f8fa;}
|
||||
.style-list-con-seckill .style-li-seckill img{max-width: 280px;max-height: 220px;}
|
||||
.style-list-con-seckill .style-li-seckill:nth-child(1), .style-list-con-seckill .style-li-seckill:nth-child(2), .style-list-con-seckill .style-li-seckill:nth-child(3){margin-top: 0;}
|
||||
.style-list-con-seckill .style-li-seckill:nth-child(3n){margin-right: 0;}
|
||||
489
addon/seckill/component/view/seckill/design.html
Executable file
@@ -0,0 +1,489 @@
|
||||
<nc-component :data="data[index]" class="component-seckill">
|
||||
|
||||
<!-- 预览 -->
|
||||
<template slot="preview">
|
||||
|
||||
<div :class="['seckill-list',nc.style]" :style="{ backgroundColor: nc.componentBgColor,
|
||||
borderTopLeftRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
|
||||
borderTopRightRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
|
||||
borderBottomLeftRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
|
||||
borderBottomRightRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0) }">
|
||||
<div :class="['title-wrap',nc.titleStyle.style]" v-if="nc.titleStyle.isShow"
|
||||
:style="{'backgroundImage':'url('+ changeImgUrl(nc.titleStyle.backgroundImage) + '), linear-gradient(to right,' + nc.titleStyle.bgColorStart + ',' + nc.titleStyle.bgColorEnd + ')'}">
|
||||
<h3 v-if="nc.titleStyle.leftStyle == 'text'" :style="{fontSize: nc.titleStyle.fontSize + 'px',color: nc.titleStyle.textColor,fontWeight: nc.titleStyle.fontWeight ? 'bold' : ''}">{{ nc.titleStyle.leftText }}</h3>
|
||||
<img v-else class="left-img" :src="changeImgUrl(nc.titleStyle.leftImg)" />
|
||||
<div class="time" :style="{ background: nc.titleStyle.timeBgColor }">
|
||||
|
||||
<span :style="{color: nc.titleStyle.textColor}" class="seckill-title-name text">距离结束</span>
|
||||
<span v-if="nc.titleStyle.timeImageUrl" :class="['seckill-title-name icon',nc.titleStyle.timeImageUrl]" :style="{color : nc.titleStyle.numTextColor}"></span>
|
||||
|
||||
<span class="hour number" :style="{ background: 'linear-gradient(to right,' + nc.titleStyle.numBgColorStart + ',' + nc.titleStyle.numBgColorEnd + ')', color: nc.titleStyle.numTextColor }">22</span>
|
||||
<span class="symbol" :style="{ color: nc.titleStyle.colonColor }">:</span>
|
||||
<span class="minute number" :style="{ background: 'linear-gradient(to right,' + nc.titleStyle.numBgColorStart + ',' + nc.titleStyle.numBgColorEnd + ')', color: nc.titleStyle.numTextColor }">30</span>
|
||||
<span class="symbol" :style="{ color: nc.titleStyle.colonColor }">:</span>
|
||||
<span class="second number" :style="{ background: 'linear-gradient(to right,' + nc.titleStyle.numBgColorStart + ',' + nc.titleStyle.numBgColorEnd + ')', color: nc.titleStyle.numTextColor }">58</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="more" v-if="nc.titleStyle.moreSupport">
|
||||
<span :style="{fontSize: nc.titleStyle.moreFontSize + 'px',color: nc.titleStyle.moreColor}">{{nc.titleStyle.more}}</span>
|
||||
<i :style="{fontSize: nc.titleStyle.moreFontSize + 'px',color: nc.titleStyle.moreColor}" class="iconfont iconyoujiantou"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :class="nc.template">
|
||||
<template v-if="nc.tempData.previewList && Object.keys(nc.tempData.previewList).length">
|
||||
<template v-if="nc.template == 'row1-of1'">
|
||||
<div class="item" v-for="(item, previewIndex) in nc.tempData.previewList" :key="previewIndex"
|
||||
:style="{
|
||||
borderTopLeftRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
|
||||
borderTopRightRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
|
||||
borderBottomLeftRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0),
|
||||
borderBottomRightRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0),
|
||||
backgroundColor: nc.elementBgColor,
|
||||
boxShadow: nc.ornament.type == 'shadow' ? ('0 0 5px ' + nc.ornament.color) : '',
|
||||
border: nc.ornament.type == 'stroke' ? '1px solid ' + nc.ornament.color : ''}">
|
||||
<div class="img-wrap" :style="{ borderRadius: nc.imgAroundRadius + 'px' }">
|
||||
<img :style="{ borderRadius: nc.imgAroundRadius + 'px' }" :src="changeImgUrl('public/static/img/default_img/square.png')" />
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="goods-name" v-if="nc.goodsNameStyle.control" :style="{ color : nc.goodsNameStyle.color,fontWeight : nc.goodsNameStyle.fontWeight ? 'bold' : '' }" :class="[{'using-hidden' : nc.nameLineMode == 'single'},{'multi-hidden' : nc.nameLineMode == 'multiple'}]">{{ item.goods_name }}</div>
|
||||
<div class="progress" v-if="nc.progressStyle.control">
|
||||
<div class="bg" :style="{ backgroundColor : nc.progressStyle.bgColor }">
|
||||
<div class="curr" :style="{ backgroundColor : nc.progressStyle.currColor }">
|
||||
<img v-if="nc.template == 'row1-of1'&&nc.style == 'style-2'" class="progress-bar" src="{$resource_path}/img/progress_bar_01.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="num" :style="{ color : nc.saleStyle.color }">已抢65.32%</div>
|
||||
</div>
|
||||
<div class="bottom-wrap">
|
||||
<div class="price-wrap">
|
||||
<div class="discount-price" v-if="nc.priceStyle.mainControl">
|
||||
<span class="unit" :style="{ color : nc.priceStyle.mainColor }">¥</span>
|
||||
<span class="price" :style="{ color : nc.priceStyle.mainColor }">{{item.discount_price.split(".")[0]}}</span>
|
||||
<span class="unit" :style="{ color : nc.priceStyle.mainColor }">{{ "."+item.discount_price.split(".")[1]}}</span>
|
||||
</div>
|
||||
<div class="original-price" v-if="nc.priceStyle.lineControl && !(nc.template == 'row1-of1'&&nc.style == 'style-2')" :style="{ color : nc.priceStyle.lineColor }">¥{{item.line_price}}</div>
|
||||
<div v-else :style="{ color : nc.priceStyle.lineColor }">
|
||||
<span>原价:</span>
|
||||
<span class="original-price">¥{{item.line_price}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="layui-btn" v-if="nc.btnStyle.control" :style="{ background : 'linear-gradient(to right,' + nc.btnStyle.bgColorStart + ',' + nc.btnStyle.bgColorEnd + ')', color : nc.btnStyle.textColor,borderRadius : nc.btnStyle.aroundRadius + 'px' }">{{ nc.btnStyle.text }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="nc.template == 'row1-of2'">
|
||||
<div class="item" v-for="(item, previewIndex) in nc.tempData.previewList" :key="previewIndex"
|
||||
:style="{
|
||||
borderTopLeftRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
|
||||
borderTopRightRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
|
||||
borderBottomLeftRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0),
|
||||
borderBottomRightRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0),
|
||||
backgroundColor: nc.elementBgColor,
|
||||
boxShadow: nc.ornament.type == 'shadow' ? ('0 0 5px ' + nc.ornament.color) : '',
|
||||
border: nc.ornament.type == 'stroke' ? '1px solid ' + nc.ornament.color : ''}">
|
||||
<div class="img-wrap" :style="{ borderRadius: nc.imgAroundRadius + 'px' }">
|
||||
<img :style="{ borderRadius: nc.imgAroundRadius + 'px' }" :src="changeImgUrl('public/static/img/default_img/square.png')" />
|
||||
</div>
|
||||
<div class="content" v-if="nc.goodsNameStyle.control || nc.priceStyle.mainControl || nc.priceStyle.lineControl || nc.btnStyle.control">
|
||||
<div class="goods-name" v-if="nc.goodsNameStyle.control" :style="{ color : nc.goodsNameStyle.color,fontWeight : nc.goodsNameStyle.fontWeight ? 'bold' : '' }" :class="[{'using-hidden' : nc.nameLineMode == 'single'},{'multi-hidden' : nc.nameLineMode == 'multiple'}]">{{ item.goods_name }}</div>
|
||||
<div class="discount-price" v-if="nc.priceStyle.mainControl">
|
||||
<span class="unit" :style="{ color : nc.priceStyle.mainColor }">¥</span>
|
||||
<span class="price" :style="{ color : nc.priceStyle.mainColor }">{{item.discount_price.split(".")[0]}}</span>
|
||||
<span class="unit" :style="{ color : nc.priceStyle.mainColor }">{{"."+item.discount_price.split(".")[1]}}</span>
|
||||
</div>
|
||||
<div class="bottom-wrap">
|
||||
<div class="original-price" v-if="nc.priceStyle.lineControl" :style="{ color : nc.priceStyle.lineColor }">¥{{item.line_price}}</div>
|
||||
<button class="layui-btn" v-if="nc.btnStyle.control" :style="{ background : 'linear-gradient(to right,' + nc.btnStyle.bgColorStart + ',' + nc.btnStyle.bgColorEnd + ')', color : nc.btnStyle.textColor,borderRadius : nc.btnStyle.aroundRadius + 'px' }">{{ nc.btnStyle.text }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="nc.template == 'horizontal-slide'">
|
||||
<div v-for="(item,previewIndex) in Object.values(nc.tempData.previewList)" :key="previewIndex" class="item" v-if="previewIndex < 3"
|
||||
:style="{
|
||||
borderTopLeftRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
|
||||
borderTopRightRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
|
||||
borderBottomLeftRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0),
|
||||
borderBottomRightRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0),
|
||||
backgroundColor: nc.elementBgColor,
|
||||
marginLeft: nc.template == 'horizontal-slide' && (nc.slideMode == 'scroll' && nc.goodsMarginType=='diy' && (nc.goodsMarginNum+'px') || ((60 - nc.margin.both*2) /6 + 'px')) || '',
|
||||
marginRight: nc.template == 'horizontal-slide' && (nc.slideMode == 'scroll' && nc.goodsMarginType=='diy' && (nc.goodsMarginNum+'px') || ((60 - nc.margin.both*2) /6 + 'px')) || '',
|
||||
boxShadow: nc.ornament.type == 'shadow' ? ('0 0 5px ' + nc.ornament.color) : '',
|
||||
border: nc.ornament.type == 'stroke' ? '1px solid ' + nc.ornament.color : ''}">
|
||||
<div class="img-wrap" :style="{ borderRadius: nc.imgAroundRadius + 'px' }">
|
||||
<img :style="{ borderRadius: nc.imgAroundRadius + 'px' }" :src="changeImgUrl('public/static/img/default_img/square.png')" />
|
||||
</div>
|
||||
<div class="content" v-if="nc.goodsNameStyle.control || nc.priceStyle.mainControl">
|
||||
<div class="goods-name" v-if="nc.goodsNameStyle.control" :style="{ color : nc.goodsNameStyle.color,fontWeight : nc.goodsNameStyle.fontWeight ? 'bold' : '' }" :class="[{'using-hidden' : nc.nameLineMode == 'single'},{'multi-hidden' : nc.nameLineMode == 'multiple'}]">{{ item.goods_name }}</div>
|
||||
<div class="discount-price" v-if="nc.priceStyle.mainControl">
|
||||
<img class="tag" src="{$resource_path}/img/style_4_tag.png">
|
||||
<span class="unit" :style="{ color : nc.priceStyle.mainColor }">¥</span>
|
||||
<span class="price" :style="{ color : nc.priceStyle.mainColor }">{{item.discount_price.split(".")[0]}}</span>
|
||||
<span class="unit" :style="{ color : nc.priceStyle.mainColor }">{{"."+item.discount_price.split(".")[1]}}</span>
|
||||
</div>
|
||||
<div class="original-price" v-if="nc.priceStyle.lineControl" :style="{ color : nc.priceStyle.lineColor }">¥{{item.line_price}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<!-- 内容编辑 -->
|
||||
<template slot="edit-content">
|
||||
<template v-if="nc.lazyLoad">
|
||||
<seckill-list-sources></seckill-list-sources>
|
||||
|
||||
<div class="template-edit-title">
|
||||
<h3>商品数据</h3>
|
||||
<slide :data="{ field : 'count', label: '商品数量', min:1, max: 30}"></slide>
|
||||
</div>
|
||||
|
||||
<div class="template-edit-title">
|
||||
<h3>头部风格</h3>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label sm">头部状态</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.titleStyle.isShow = !nc.titleStyle.isShow" :class="{ 'layui-form-checked' : nc.titleStyle.isShow }">
|
||||
<span>{{ nc.titleStyle.isShow ? '显示' : '隐藏' }}</span>
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="nc.titleStyle.isShow">
|
||||
<div class="layui-form-item" v-if="nc.tempData.methods">
|
||||
<label class="layui-form-label sm">选择风格</label>
|
||||
<div class="layui-input-block">
|
||||
<div v-if="nc.titleStyle.styleName" class="text-color selected-style" @click="nc.tempData.methods.selectTopStyle">
|
||||
<span>{{nc.titleStyle.styleName}}</span>
|
||||
<i class="layui-icon layui-icon-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label sm">主标题类型</label>
|
||||
<div class="layui-input-block">
|
||||
<div @click="nc.titleStyle.leftStyle='text'" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.titleStyle.leftStyle=='text') }">
|
||||
<i class="layui-anim layui-icon">{{ nc.titleStyle.leftStyle=='text' ? "" : "" }}</i>
|
||||
<div>文字</div>
|
||||
</div>
|
||||
<div @click="nc.titleStyle.leftStyle='img'" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.titleStyle.leftStyle=='img') }">
|
||||
<i class="layui-anim layui-icon">{{ nc.titleStyle.leftStyle=='img' ? "" : "" }}</i>
|
||||
<div>图片</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item" v-if="nc.titleStyle.leftStyle=='text'">
|
||||
<label class="layui-form-label sm">标题文字</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" v-model="nc.titleStyle.leftText" maxlength="4" placeholder="限时秒杀" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item" v-if="nc.titleStyle.leftStyle=='img'">
|
||||
<label class="layui-form-label sm">标题图片</label>
|
||||
<div class="layui-input-block">
|
||||
<img-upload :data="{ data: nc.titleStyle,field:'leftImg'}" data-disabled="1"></img-upload>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item" v-if="nc.titleStyle.moreSupport">
|
||||
<label class="layui-form-label sm">右侧文字</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" v-model="nc.titleStyle.more" maxlength="8" placeholder="查看更多" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="template-edit-title">
|
||||
<h3>商品风格</h3>
|
||||
<div class="layui-form-item list-style" v-if="nc.tempData.templateList">
|
||||
<label class="layui-form-label sm">风格</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="source">{{ nc.tempData.templateList[nc.template].text }}</div>
|
||||
<div class="template-selected">
|
||||
<div v-for="(item,templateKey) in nc.tempData.templateList" :key="templateKey" class="source-item" :title="item.text"
|
||||
@click="nc.tempData.methods.selectTemplate(templateKey)"
|
||||
:class="[(nc.template == templateKey) ? 'text-color border-color' : '' ]">
|
||||
<i class='iconfont' :class='item.icon'></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="style-selected">
|
||||
<div v-for="(item,styleIndex) in nc.tempData.templateList[nc.template].styleList" :key="styleIndex" @click="nc.tempData.methods.selectTemplate('',item)" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.style==item.value) }">
|
||||
<i class="layui-anim layui-icon">{{ nc.style == item.value ? "" : "" }}</i>
|
||||
<div>{{item.text}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="template-edit-title" v-show="nc.btnStyle.support">
|
||||
<h3>购买按钮</h3>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label sm">是否显示</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.btnStyle.control = !nc.btnStyle.control" :class="{ 'layui-form-checked' : nc.btnStyle.control }">
|
||||
<span>{{ nc.btnStyle.control ? '显示' : '隐藏' }}</span>
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item" v-if="nc.btnStyle.control">
|
||||
<label class="layui-form-label sm">文字</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" v-model="nc.btnStyle.text" maxlength="6" placeholder="请输入按钮文字" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="template-edit-title">
|
||||
<h3>显示内容</h3>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label sm">商品名称</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.goodsNameStyle.control = !nc.goodsNameStyle.control" :class="{ 'layui-form-checked' : nc.goodsNameStyle.control }">
|
||||
<span>{{ nc.goodsNameStyle.control ? '显示' : '隐藏' }}</span>
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label sm">销售价</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.priceStyle.mainControl = !nc.priceStyle.mainControl" :class="{ 'layui-form-checked' : nc.priceStyle.mainControl }">
|
||||
<span>{{ nc.priceStyle.mainControl ? '显示' : '隐藏' }}</span>
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item" v-show="nc.progressStyle.support">
|
||||
<label class="layui-form-label sm">秒杀进度</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.progressStyle.control = !nc.progressStyle.control" :class="{ 'layui-form-checked' : nc.progressStyle.control }">
|
||||
<span>{{ nc.progressStyle.control ? '显示' : '隐藏' }}</span>
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item" v-show="nc.priceStyle.lineSupport">
|
||||
<label class="layui-form-label sm">划线价</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.priceStyle.lineControl = !nc.priceStyle.lineControl" :class="{ 'layui-form-checked' : nc.priceStyle.lineControl }">
|
||||
<span>{{ nc.priceStyle.lineControl ? '显示' : '隐藏' }}</span>
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item" v-show="nc.saleStyle.support">
|
||||
<label class="layui-form-label sm">商品销量</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.saleStyle.control = !nc.saleStyle.control" :class="{ 'layui-form-checked' : nc.saleStyle.control }">
|
||||
<span>{{ nc.saleStyle.control ? '显示' : '隐藏' }}</span>
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<!-- 弹框 -->
|
||||
<article class="style-list-box-seckill">
|
||||
<div class="style-list-seckill layui-form">
|
||||
<div class="style-list-con-seckill">
|
||||
<div class="style-li-seckill" v-for="(value,name,previewIndex) in nc.tempData.styleList" :key="name" :class="{'selected border-color': nc.titleStyle.style == name}" :data_key="name">
|
||||
<span class="layui-hide">风格{{previewIndex + 1}}</span>
|
||||
<img :src="'{$resource_path}/img/style_title_' + (previewIndex+1) + '.png'" />
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="style">
|
||||
<input type="hidden" name="style_name" />
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</template>
|
||||
|
||||
<!-- 样式编辑 -->
|
||||
<template slot="edit-style">
|
||||
<template v-if="nc.lazyLoad">
|
||||
<template v-if="nc.titleStyle.isShow">
|
||||
<div class="template-edit-title">
|
||||
<h3>头部样式</h3>
|
||||
<template v-if="nc.titleStyle.leftStyle == 'text'">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label sm">标题加粗</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.titleStyle.fontWeight = !nc.titleStyle.fontWeight" :class="{ 'layui-form-checked' : nc.titleStyle.fontWeight }">
|
||||
<span>加粗</span>
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<color :data="{ field : 'textColor', 'label' : '标题颜色', parent : 'titleStyle', defaultColor : '#303133' }"></color>
|
||||
<slide :data="{ field : 'fontSize',parent : 'titleStyle', label : '标题大小', min: 12, max : 16 }"></slide>
|
||||
</template>
|
||||
<color :data="{ field : 'bgColorStart,bgColorEnd', 'label' : '背景颜色', parent : 'titleStyle', defaultColor : '#FA6400,#FF287A' }"></color>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label sm">背景图片</label>
|
||||
<div class="layui-input-block">
|
||||
<img-upload :data="{ data: nc.titleStyle,field:'backgroundImage'}" data-disabled="1"></img-upload>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="template-edit-title">
|
||||
<h3>倒计时样式</h3>
|
||||
<nc-icon v-if="nc.titleStyle.style == 'style-2'" :data="{ field : 'timeImageUrl', parent : 'titleStyle'}"></nc-icon>
|
||||
<color :data="{ field : 'timeBgColor', 'label' : '背景颜色', parent : 'titleStyle', defaultColor : '#303133' }"></color>
|
||||
<color :data="{ field : 'numBgColorStart,numBgColorEnd', 'label' : '数字背景色', parent : 'titleStyle', defaultColor : '#FFFFFF' }"></color>
|
||||
<color :data="{ field : 'numTextColor', 'label' : '数字颜色', parent : 'titleStyle', defaultColor : '#303133' }"></color>
|
||||
<color :data="{ field : 'colonColor', 'label' : '冒号颜色', parent : 'titleStyle', defaultColor : '#FFFFFF' }"></color>
|
||||
|
||||
</div>
|
||||
<div class="template-edit-title" v-if="nc.titleStyle.moreSupport">
|
||||
<h3>“更多”样式</h3>
|
||||
<color :data="{ field : 'moreColor', 'label' : '文字颜色', parent : 'titleStyle', defaultColor : '#999999' }"></color>
|
||||
<slide :data="{ field : 'moreFontSize',parent : 'titleStyle', label : '文字大小', min: 12, max : 14 }"></slide>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="template-edit-title">
|
||||
<h3>商品样式</h3>
|
||||
|
||||
<div class="layui-form-item tag-wrap">
|
||||
<label class="layui-form-label sm">边框</label>
|
||||
<div class="layui-input-block">
|
||||
<div v-for="(item,ornamentIndex) in nc.tempData.ornamentList" :key="ornamentIndex" @click="nc.ornament.type=item.type" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.ornament.type==item.type) }">
|
||||
<i class="layui-anim layui-icon">{{ nc.ornament.type == item.type ? "" : "" }}</i>
|
||||
<div>{{item.text}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<color v-if="nc.ornament.type != 'default'" :data="{ field : 'color', 'label' : '边框颜色', parent : 'ornament', defaultColor : '#EDEDED' }"></color>
|
||||
|
||||
<slide :data="{ field : 'imgAroundRadius', label: '图片圆角', min:0, max: 50 }"></slide>
|
||||
|
||||
<div class="layui-form-item" v-if="nc.template == 'horizontal-slide'">
|
||||
<label class="layui-form-label sm">滚动方式</label>
|
||||
<div class="layui-input-block">
|
||||
<div @click="nc.slideMode = 'scroll' " :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.slideMode == 'scroll') }">
|
||||
<i class="layui-anim layui-icon">{{ nc.slideMode == 'scroll' ? "" : "" }}</i>
|
||||
<div>平移</div>
|
||||
</div>
|
||||
<div @click="nc.slideMode = 'slide' " :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.slideMode == 'slide') }">
|
||||
<i class="layui-anim layui-icon">{{ nc.slideMode == 'slide' ? "" : "" }}</i>
|
||||
<div>切屏</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item" v-show="nc.goodsNameStyle.control">
|
||||
<label class="layui-form-label sm">商品名称</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.goodsNameStyle.fontWeight = !nc.goodsNameStyle.fontWeight" :class="{ 'layui-form-checked' : nc.goodsNameStyle.fontWeight }">
|
||||
<span>加粗</span>
|
||||
<i class="layui-icon layui-icon-ok"></i>
|
||||
</div>
|
||||
<div v-for="(item,nameLineIndex) in nc.tempData.nameLineModeList" :key="nameLineIndex" @click="nc.nameLineMode=item.value" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.nameLineMode==item.value) }">
|
||||
<i class="layui-anim layui-icon">{{ nc.nameLineMode == item.value ? "" : "" }}</i>
|
||||
<div>{{item.text}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<color :data="{ field : 'elementBgColor', 'label' : '商品背景' }"></color>
|
||||
|
||||
<slide v-show="nc.elementAngle == 'round'" :data="{ field : 'topElementAroundRadius', label : '上圆角', max : 50 }"></slide>
|
||||
<slide v-show="nc.elementAngle == 'round'" :data="{ field : 'bottomElementAroundRadius', label : '下圆角', max : 50 }"></slide>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label sm">色调</label>
|
||||
<div class="layui-input-block">
|
||||
<div @click="nc.theme='default'" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.theme == 'default') }">
|
||||
<i class="layui-anim layui-icon">{{ nc.theme == 'default' ? "" : "" }}</i>
|
||||
<div>跟随主题风格</div>
|
||||
</div>
|
||||
<div @click="nc.theme='diy'" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.theme == 'diy') }">
|
||||
<i class="layui-anim layui-icon">{{ nc.theme == 'diy' ? "" : "" }}</i>
|
||||
<div>自定义</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="nc.theme == 'diy'">
|
||||
<color :data="{ field : 'color', 'label' : '商品名称', parent : 'goodsNameStyle', defaultColor : '#303133' }"></color>
|
||||
<color :data="{ field : 'mainColor', 'label' : '销售价', parent : 'priceStyle', defaultColor : '#FF6A00' }"></color>
|
||||
<div v-show="nc.progressStyle.support">
|
||||
<color :data="{ field : 'bgColor,currColor', 'label' : '秒杀进度', parent : 'progressStyle', defaultColor : '#FCECD7,#FDBE6C' }"></color>
|
||||
</div>
|
||||
<div v-show="nc.priceStyle.lineSupport">
|
||||
<color :data="{ field : 'lineColor', 'label' : '划线价', parent : 'priceStyle', defaultColor : '#999CA7' }"></color>
|
||||
</div>
|
||||
<div v-show="nc.saleStyle.support">
|
||||
<color :data="{ field : 'color', 'label' : '商品销量', parent : 'saleStyle', defaultColor : '#999CA7' }"></color>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="template-edit-title" v-show="nc.btnStyle.support && nc.btnStyle.control">
|
||||
<h3>购买按钮</h3>
|
||||
|
||||
<slide :data="{ field : 'aroundRadius', label: '圆角', min:0, max: 50, parent: 'btnStyle' }"></slide>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label sm">色调</label>
|
||||
<div class="layui-input-block">
|
||||
<div @click="nc.btnStyle.theme='default'" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.btnStyle.theme == 'default') }">
|
||||
<i class="layui-anim layui-icon">{{ nc.btnStyle.theme == 'default' ? "" : "" }}</i>
|
||||
<div>跟随主题风格</div>
|
||||
</div>
|
||||
<div @click="nc.btnStyle.theme='diy'" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.btnStyle.theme == 'diy') }">
|
||||
<i class="layui-anim layui-icon">{{ nc.btnStyle.theme == 'diy' ? "" : "" }}</i>
|
||||
<div>自定义</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="nc.btnStyle.theme == 'diy'">
|
||||
<color :data="{ field : 'bgColorStart,bgColorEnd', 'label' : '背景颜色', parent : 'btnStyle', defaultColor : '#FF7B1D,#FF1544' }"></color>
|
||||
<color :data="{ field : 'textColor', 'label' : '文字颜色', parent : 'btnStyle', defaultColor : '#FFFFFF' }"></color>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- 资源 -->
|
||||
<template slot="resource">
|
||||
<js>
|
||||
var seckillResourcePath = "{$resource_path}"; // http路径
|
||||
var seckillRelativePath = "{$relative_path}"; // 相对路径
|
||||
</js>
|
||||
<js src="{$resource_path}/js/design.js"></js>
|
||||
<css src="{$resource_path}/css/design.css"></css>
|
||||
</template>
|
||||
|
||||
</nc-component>
|
||||
BIN
addon/seckill/component/view/seckill/img/corner_mark.png
Executable file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
addon/seckill/component/view/seckill/img/progress_bar_01.png
Executable file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
addon/seckill/component/view/seckill/img/seckill_style_1.png
Executable file
|
After Width: | Height: | Size: 275 KiB |
BIN
addon/seckill/component/view/seckill/img/seckill_style_2.png
Executable file
|
After Width: | Height: | Size: 188 KiB |
BIN
addon/seckill/component/view/seckill/img/seckill_style_3.png
Executable file
|
After Width: | Height: | Size: 204 KiB |
BIN
addon/seckill/component/view/seckill/img/style2_title.png
Executable file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
addon/seckill/component/view/seckill/img/style3_title.png
Executable file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
addon/seckill/component/view/seckill/img/style_4_tag.png
Executable file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
addon/seckill/component/view/seckill/img/style_title_1.png
Executable file
|
After Width: | Height: | Size: 20 KiB |
BIN
addon/seckill/component/view/seckill/img/style_title_2.png
Executable file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
addon/seckill/component/view/seckill/img/style_title_3.png
Executable file
|
After Width: | Height: | Size: 13 KiB |
BIN
addon/seckill/component/view/seckill/img/style_title_3_bg.png
Executable file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
addon/seckill/component/view/seckill/img/style_title_3_name.png
Executable file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
addon/seckill/component/view/seckill/img/style_title_4.png
Executable file
|
After Width: | Height: | Size: 30 KiB |
BIN
addon/seckill/component/view/seckill/img/style_title_4_bg.png
Executable file
|
After Width: | Height: | Size: 19 KiB |
BIN
addon/seckill/component/view/seckill/img/style_title_4_name.png
Executable file
|
After Width: | Height: | Size: 4.7 KiB |
290
addon/seckill/component/view/seckill/js/design.js
Executable file
@@ -0,0 +1,290 @@
|
||||
var seckillListHtml = '<div style="display:none;"></div>';
|
||||
|
||||
Vue.component("seckill-list-sources", {
|
||||
template: seckillListHtml,
|
||||
data: function () {
|
||||
return {
|
||||
data: this.$parent.data,
|
||||
goodsSources: {
|
||||
initial: {
|
||||
text: "默认",
|
||||
icon: "iconmofang"
|
||||
},
|
||||
diy: {
|
||||
text: "手动选择",
|
||||
icon: "iconshoudongxuanze"
|
||||
},
|
||||
},
|
||||
templateList: {
|
||||
"row1-of1": {
|
||||
text: "单列",
|
||||
icon: "iconiPhone86",
|
||||
styleList: [
|
||||
{
|
||||
text: "样式1",
|
||||
value: "style-1",
|
||||
cartSupport: true, // 是否支持按钮
|
||||
lineSupport: true, // 是否支持划线价
|
||||
saleSupport: false, // 是否支持销量
|
||||
progressSupport: true // 是否支持进度
|
||||
},
|
||||
{
|
||||
text: "样式2",
|
||||
value: "style-2",
|
||||
cartSupport: true, // 是否支持按钮
|
||||
lineSupport: true, // 是否支持划线价
|
||||
saleSupport: false, // 是否支持销量
|
||||
progressSupport: true // 是否支持进度
|
||||
}
|
||||
],
|
||||
},
|
||||
"row1-of2": {
|
||||
text: "两列",
|
||||
icon: "iconyihanglianglie",
|
||||
styleList: [
|
||||
{
|
||||
text: "样式1",
|
||||
value: "style-1",
|
||||
cartSupport: true, // 是否支持购物车按钮
|
||||
lineSupport: true, // 是否支持划线价
|
||||
saleSupport: false, // 是否支持销量
|
||||
progressSupport: false // 是否支持进度
|
||||
},
|
||||
],
|
||||
},
|
||||
"horizontal-slide": {
|
||||
text: "横向滑动",
|
||||
icon: "iconshangpinliebiaohengxianghuadong",
|
||||
styleList: [
|
||||
{
|
||||
text: "样式1",
|
||||
value: "style-1",
|
||||
cartSupport: false, // 是否支持按钮
|
||||
lineSupport: true, // 是否支持划线价
|
||||
saleSupport: false,// 是否支持销量
|
||||
progressSupport: false // 是否支持进度
|
||||
},
|
||||
{
|
||||
text: "样式2",
|
||||
value: "style-2",
|
||||
cartSupport: false, // 是否支持按钮
|
||||
lineSupport: true, // 是否支持划线价
|
||||
saleSupport: false,// 是否支持销量
|
||||
progressSupport: false, // 是否支持进度
|
||||
mainColor: "#FFFFFF", // 销售价颜色
|
||||
goodsNameControl: false // 是否显示商品名称
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
ornamentList: [
|
||||
{
|
||||
type: 'default',
|
||||
text: '默认',
|
||||
},
|
||||
{
|
||||
type: 'shadow',
|
||||
text: '投影',
|
||||
},
|
||||
{
|
||||
type: 'stroke',
|
||||
text: '描边',
|
||||
},
|
||||
],
|
||||
nameLineModeList: [
|
||||
{
|
||||
text: "单行",
|
||||
value: "single"
|
||||
},
|
||||
{
|
||||
text: "多行",
|
||||
value: "multiple"
|
||||
}
|
||||
],
|
||||
styleList: {
|
||||
"style-1": {
|
||||
isShow: true,
|
||||
leftStyle: "text",
|
||||
leftImg: "",
|
||||
leftText: "限时秒杀",
|
||||
backgroundImage: '',
|
||||
bgColorStart: "#FFFFFF",
|
||||
bgColorEnd: "#FFFFFF",
|
||||
textColor: "#303133",
|
||||
timeImageUrl: "",
|
||||
timeBgColor: "",
|
||||
numBgColorStart: "#303133", // 数字背景色开始
|
||||
numBgColorEnd: "#303133", // 数字背景色结束
|
||||
numTextColor: "#FFFFFF", // 数字颜色
|
||||
colonColor: "#303133", // 冒号颜色
|
||||
moreColor: "#999999",
|
||||
more: "查看更多",
|
||||
moreSupport: true
|
||||
},
|
||||
"style-2": {
|
||||
isShow: true,
|
||||
leftStyle: "text",
|
||||
leftImg: "",
|
||||
leftText: "限时秒杀",
|
||||
backgroundImage: '',
|
||||
bgColorStart: "#FFFFFF",
|
||||
bgColorEnd: "#FFFFFF",
|
||||
textColor: "#303133",
|
||||
timeBgColor: "#303133",
|
||||
timeImageUrl: 'icondiy icon-system-seckill-time',
|
||||
numBgColorStart: "#303133",
|
||||
numBgColorEnd: "#303133",
|
||||
numTextColor: "#FFFFFF",
|
||||
colonColor: "#FFFFFF",
|
||||
moreColor: "#999999",
|
||||
more: "查看更多",
|
||||
moreSupport: true
|
||||
},
|
||||
"style-3": {
|
||||
isShow: true,
|
||||
leftStyle: "img",
|
||||
leftImg: seckillRelativePath + '/img/style_title_3_name.png',
|
||||
leftText: "",
|
||||
backgroundImage: seckillRelativePath + '/img/style_title_3_bg.png',
|
||||
bgColorStart: "#FA6400",
|
||||
bgColorEnd: "#FF287A",
|
||||
textColor: "#FFFFFF",
|
||||
timeBgColor: "",
|
||||
timeImageUrl: '',
|
||||
numBgColorStart: "#FFFFFF",
|
||||
numBgColorEnd: "#FFFFFF",
|
||||
numTextColor: "#FD3B54",
|
||||
colonColor: "#FFFFFF",
|
||||
moreColor: "#FFFFFF",
|
||||
more: "更多",
|
||||
moreSupport: true
|
||||
},
|
||||
"style-4": {
|
||||
isShow: true,
|
||||
leftStyle: "img",
|
||||
leftImg: seckillRelativePath + '/img/style_title_4_name.png',
|
||||
leftText: "",
|
||||
backgroundImage: seckillRelativePath + '/img/style_title_4_bg.png',
|
||||
bgColorStart: "#FFFFFF",
|
||||
bgColorEnd: "#FFFFFF",
|
||||
textColor: "#666666",
|
||||
timeBgColor: "",
|
||||
timeImageUrl: '',
|
||||
numBgColorStart: "#FF5F17",
|
||||
numBgColorEnd: "#FE2F18",
|
||||
numTextColor: "#FFFFFF",
|
||||
colonColor: "#FE3718",
|
||||
moreColor: "",
|
||||
more: "",
|
||||
moreSupport: false
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
if (!this.$parent.data.verify) this.$parent.data.verify = [];
|
||||
this.$parent.data.verify.push(this.verify);//加载验证方法
|
||||
|
||||
this.$parent.data.ignore = ['textColor']; //加载忽略内容 -- 其他设置中的属性设置
|
||||
this.$parent.data.ignoreLoad = true; // 等待忽略数组赋值后加载
|
||||
|
||||
var previewList = {};
|
||||
for (var i = 1; i < 5; i++) {
|
||||
previewList["goods_id_" + ns.gen_non_duplicate(i)] = {
|
||||
goods_name: "秒杀商品",
|
||||
discount_price: (Math.random() * 100 * i + 10).toFixed(2), // 随机价格
|
||||
line_price: (Math.random() * 100 * i + 100 + 10).toFixed(2), // 随机价格
|
||||
};
|
||||
}
|
||||
|
||||
// 组件所需的临时数据
|
||||
this.$parent.data.tempData = {
|
||||
goodsSources: this.goodsSources,
|
||||
templateList: this.templateList,
|
||||
ornamentList: this.ornamentList,
|
||||
nameLineModeList: this.nameLineModeList,
|
||||
styleList: this.styleList,
|
||||
previewList: previewList,
|
||||
methods: {
|
||||
addGoods: this.addGoods,
|
||||
selectTemplate: this.selectTemplate,
|
||||
selectTopStyle: this.selectTopStyle
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
verify: function (index) {
|
||||
var res = {code: true, message: ""};
|
||||
if (vue.data[index].sources === 'diy' && vue.data[index].goodsId.length === 0) {
|
||||
res.code = false;
|
||||
res.message = "请选择商品";
|
||||
}
|
||||
return res;
|
||||
},
|
||||
addGoods: function () {
|
||||
var self = this;
|
||||
goodsSelect(function (res) {
|
||||
self.$parent.data.goodsId = res;
|
||||
}, self.$parent.data.goodsId, {mode: "spu", promotion: "seckill", disabled: 0, post: ns.appModule});
|
||||
},
|
||||
selectTemplate(template, item) {
|
||||
if (template) {
|
||||
this.$parent.data.template = template;
|
||||
item = this.templateList[template].styleList[0];
|
||||
}
|
||||
|
||||
this.$parent.data.style = item.value;
|
||||
this.$parent.data.btnStyle.support = item.cartSupport;
|
||||
this.$parent.data.btnStyle.control = item.cartSupport;
|
||||
this.$parent.data.priceStyle.lineSupport = item.lineSupport;
|
||||
this.$parent.data.priceStyle.lineControl = item.lineSupport;
|
||||
this.$parent.data.saleStyle.support = item.saleSupport;
|
||||
this.$parent.data.saleStyle.control = item.saleSupport;
|
||||
this.$parent.data.progressStyle.support = item.progressSupport;
|
||||
this.$parent.data.progressStyle.control = item.progressSupport;
|
||||
|
||||
if (item.mainColor) {
|
||||
this.$parent.data.priceStyle.mainColor = item.mainColor;
|
||||
} else {
|
||||
this.$parent.data.priceStyle.mainColor = '#FF1745';
|
||||
}
|
||||
|
||||
if (item.goodsNameControl !== undefined) {
|
||||
this.$parent.data.goodsNameStyle.control = item.goodsNameControl;
|
||||
} else {
|
||||
this.$parent.data.goodsNameStyle.control = true;
|
||||
}
|
||||
|
||||
if (this.data.template == "row1-of1" && this.data.style == "style-2") {
|
||||
this.$parent.data.progressStyle.bgColor = "#FFD5D5";
|
||||
this.$parent.data.progressStyle.currColor = "#ff0400";
|
||||
}
|
||||
},
|
||||
selectTopStyle: function () {
|
||||
var self = this;
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: '风格选择',
|
||||
area: ['910px', '360px'],
|
||||
btn: ['确定', '返回'],
|
||||
content: $(".draggable-element[data-index='" + self.data.index + "'] .edit-attribute .style-list-box-seckill").html(),
|
||||
success: function (layero, index) {
|
||||
$(".layui-layer-content input[name='style']").val(self.data.titleStyle.style);
|
||||
$(".layui-layer-content input[name='style_name']").val(self.data.titleStyle.styleName);
|
||||
$("body").off("click", ".layui-layer-content .style-list-con-seckill .style-li-seckill").on("click", ".layui-layer-content .style-list-con-seckill .style-li-seckill", function () {
|
||||
$(this).addClass("selected border-color").siblings().removeClass("selected border-color bg-color-after");
|
||||
$(".layui-layer-content input[name='style']").val($(this).attr("data_key"));
|
||||
$(".layui-layer-content input[name='style_name']").val($(this).find("span").text());
|
||||
});
|
||||
},
|
||||
yes: function (index, layero) {
|
||||
self.data.titleStyle.style = $(".layui-layer-content input[name='style']").val();
|
||||
Object.assign(self.data.titleStyle, self.styleList[self.data.titleStyle.style]);
|
||||
self.data.titleStyle.styleName = $(".layui-layer-content input[name='style_name']").val();
|
||||
layer.closeAll();
|
||||
loadImgMagnify();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
68
addon/seckill/config/diy_view.php
Executable file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
|
||||
* =========================================================
|
||||
*/
|
||||
return [
|
||||
|
||||
// 自定义模板页面类型,格式:[ 'title' => '页面类型名称', 'name' => '页面标识', 'path' => '页面路径', 'value' => '页面数据,json格式' ]
|
||||
'template' => [],
|
||||
|
||||
// 后台自定义组件——装修
|
||||
'util' => [
|
||||
[
|
||||
'name' => 'Seckill',
|
||||
'title' => '秒杀',
|
||||
'type' => 'PROMOTION',
|
||||
'value' => '{"style":"style-1","sources":"initial","count":6,"goodsId":[],"goodsMarginType":"default","goodsMarginNum":10,"ornament":{"type":"default","color":"#EDEDED"},"nameLineMode":"single","template":"row1-of1","btnStyle":{"text":"去秒杀","textColor":"#FFFFFF","theme":"default","aroundRadius":25,"control":true,"support":true,"bgColorStart":"#FF7B1D","bgColorEnd":"#FF1544"},"imgAroundRadius":5,"saleStyle":{"color":"#999CA7","control":true,"support":true},"progressStyle":{"control":true,"support":true,"currColor":"#FDBE6C","bgColor":"#FCECD7"},"titleStyle":{"backgroundImage":"","isShow":true,"leftStyle":"text","leftImg":"","style":"style-1","styleName":"风格1","leftText":"限时秒杀","fontSize":16,"fontWeight":true,"textColor":"#303133","bgColorStart":"#FFFFFF","bgColorEnd":"#FFFFFF","more":"查看更多","moreColor":"#999999","moreFontSize":12,"timeBgColor":"","timeImageUrl":"","moreSupport":true,"colonColor":"#303133","numBgColorStart":"#303133","numBgColorEnd":"#303133","numTextColor":"#FFFFFF"},"slideMode":"scroll","theme":"default","priceStyle":{"mainColor":"#FF1745","mainControl":true,"lineColor":"#999CA7","lineControl":true,"lineSupport":true},"goodsNameStyle":{"color":"#303133","control":true,"fontWeight":false}}',
|
||||
'sort' => '30003',
|
||||
'support_diy_view' => '',
|
||||
'max_count' => 1,
|
||||
'icon' => 'iconfont iconmiaosha1'
|
||||
]
|
||||
],
|
||||
|
||||
// 自定义页面路径
|
||||
'link' => [
|
||||
[
|
||||
'name' => 'SECKILL',
|
||||
'title' => '秒杀',
|
||||
'parent' => 'MARKETING_LINK',
|
||||
'wap_url' => '',
|
||||
'web_url' => '',
|
||||
'sort' => 0,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'SECKILL_PREFECTURE',
|
||||
'title' => '秒杀专区',
|
||||
'wap_url' => '/pages_promotion/seckill/list',
|
||||
'web_url' => '',
|
||||
'sort' => 0
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
// 自定义图标库
|
||||
'icon_library' => [],
|
||||
|
||||
// uni-app 组件,格式:[ 'name' => '组件名称/文件夹名称', 'path' => '文件路径/目录路径' ],多个逗号隔开,自定义组件名称前缀必须是diy-,也可以引用第三方组件
|
||||
'component' => [],
|
||||
|
||||
// uni-app 页面,多个逗号隔开
|
||||
'pages' => [],
|
||||
|
||||
// 模板信息,格式:'title' => '模板名称', 'name' => '模板标识', 'cover' => '模板封面图', 'preview' => '模板预览图', 'desc' => '模板描述'
|
||||
'info' => [],
|
||||
|
||||
// 主题风格配色,格式可以自由定义扩展,【在uni-app中通过:this.themeStyle... 获取定义的颜色字段,例如:this.themeStyle.main_color】
|
||||
'theme' => [],
|
||||
|
||||
// 自定义页面数据,格式:[ 'title' => '页面名称', 'name' => "页面标识", 'value' => [页面数据,json格式] ]
|
||||
'data' => []
|
||||
];
|
||||
52
addon/seckill/config/event.php
Executable file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
// 事件定义文件
|
||||
return [
|
||||
'bind' => [
|
||||
|
||||
],
|
||||
|
||||
'listen' => [
|
||||
//秒杀开启
|
||||
'OpenSeckill' => [
|
||||
'addon\seckill\event\OpenSeckill',
|
||||
],
|
||||
//秒杀关闭
|
||||
'CloseSeckill' => [
|
||||
'addon\seckill\event\CloseSeckill',
|
||||
],
|
||||
//展示活动
|
||||
'ShowPromotion' => [
|
||||
'addon\seckill\event\ShowPromotion',
|
||||
],
|
||||
'PromotionType' => [
|
||||
'addon\seckill\event\PromotionType',
|
||||
],
|
||||
// 商品营销活动类型
|
||||
'GoodsPromotionType' => [
|
||||
'addon\seckill\event\GoodsPromotionType',
|
||||
],
|
||||
|
||||
// 商品营销活动信息
|
||||
'GoodsPromotion' => [
|
||||
'addon\seckill\event\GoodsPromotion',
|
||||
],
|
||||
|
||||
// 订单营销活动类型
|
||||
'OrderPromotionType' => [
|
||||
'addon\seckill\event\OrderPromotionType',
|
||||
],
|
||||
|
||||
// 订单关闭
|
||||
'OrderClose' => [
|
||||
'addon\seckill\event\OrderClose',
|
||||
],
|
||||
|
||||
// 活动专区——秒杀页面配置
|
||||
'PromotionZoneConfig' => [
|
||||
'addon\seckill\event\SeckillZoneConfig',
|
||||
]
|
||||
],
|
||||
|
||||
'subscribe' => [
|
||||
],
|
||||
];
|
||||
20
addon/seckill/config/info.php
Executable file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
return [
|
||||
'name' => 'seckill',
|
||||
'title' => '限时秒杀',
|
||||
'description' => '限时秒杀功能',
|
||||
'type' => 'promotion', //插件类型 system :系统插件 promotion:营销插件 tool:工具插件
|
||||
'status' => 1,
|
||||
'author' => '',
|
||||
'version' => '5.5.3',
|
||||
'version_no' => '553250709001',
|
||||
'content' => '',
|
||||
];
|
||||
97
addon/seckill/config/menu_shop.php
Executable file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 平台端菜单设置
|
||||
// +----------------------------------------------------------------------
|
||||
return [
|
||||
[
|
||||
'name' => 'PROMOTION_SECKILL',
|
||||
'title' => '限时秒杀',
|
||||
'url' => 'seckill://shop/seckill/goodslist',
|
||||
'parent' => 'PROMOTION_CENTER',
|
||||
'is_show' => 1,
|
||||
'is_control' => 1,
|
||||
'is_icon' => 0,
|
||||
'picture' => '',
|
||||
'picture_select' => '',
|
||||
'sort' => 100,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'PROMOTION_SECKILL_GOODS_LIST',
|
||||
'title' => '商品管理',
|
||||
'url' => 'seckill://shop/seckill/goodslist',
|
||||
'parent' => 'PROMOTION_CENTER',
|
||||
'is_show' => 1,
|
||||
'is_control' => 1,
|
||||
'is_icon' => 0,
|
||||
'picture' => '',
|
||||
'picture_select' => '',
|
||||
'sort' => 1,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'PROMOTION_SECKILL_GOODS_ADD',
|
||||
'title' => '添加商品',
|
||||
'url' => 'seckill://shop/seckill/addgoods',
|
||||
'sort' => 1,
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'PROMOTION_SECKILL_GOODS_UPDATE',
|
||||
'title' => '编辑商品',
|
||||
'url' => 'seckill://shop/seckill/updategoods',
|
||||
'sort' => 2,
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'PROMOTION_SECKILL_GOODS_DELETE',
|
||||
'title' => '删除商品',
|
||||
'url' => 'seckill://shop/seckill/deletegoods',
|
||||
'sort' => 3,
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'PROMOTION_SECKILL_TIME',
|
||||
'title' => '场次管理',
|
||||
'url' => 'seckill://shop/seckill/lists',
|
||||
'parent' => 'PROMOTION_CENTER',
|
||||
'is_show' => 1,
|
||||
'is_control' => 1,
|
||||
'is_icon' => 0,
|
||||
'picture' => '',
|
||||
'picture_select' => '',
|
||||
'sort' => 2,
|
||||
'child_list' => [
|
||||
[
|
||||
'name' => 'PROMOTION_SECKILL_ADD',
|
||||
'title' => '添加场次',
|
||||
'url' => 'seckill://shop/seckill/add',
|
||||
'sort' => 1,
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'PROMOTION_SECKILL_ADD',
|
||||
'title' => '编辑场次',
|
||||
'url' => 'seckill://shop/seckill/edit',
|
||||
'sort' => 2,
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
[
|
||||
'name' => 'PROMOTION_SECKILL_DELETE',
|
||||
'title' => '删除场次',
|
||||
'url' => 'seckill://shop/seckill/delete',
|
||||
'sort' => 3,
|
||||
'is_show' => 0,
|
||||
'type' => 'button',
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
],
|
||||
|
||||
];
|
||||
1
addon/seckill/data/install.sql
Executable file
@@ -0,0 +1 @@
|
||||
SET NAMES 'utf8';
|
||||
1
addon/seckill/data/uninstall.sql
Executable file
@@ -0,0 +1 @@
|
||||
SET NAMES 'utf8';
|
||||
27
addon/seckill/event/CloseSeckill.php
Executable file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
use addon\seckill\model\Seckill;
|
||||
|
||||
/**
|
||||
* 关闭活动
|
||||
*/
|
||||
class CloseSeckill
|
||||
{
|
||||
|
||||
public function handle($params)
|
||||
{
|
||||
$seckill = new Seckill();
|
||||
$res = $seckill->cronCloseSeckill($params[ 'relate_id' ]);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
64
addon/seckill/event/GoodsPromotion.php
Executable file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
use addon\seckill\model\Seckill;
|
||||
use app\model\goods\Goods as GoodsModel;
|
||||
|
||||
/**
|
||||
* 商品营销活动信息
|
||||
*/
|
||||
class GoodsPromotion
|
||||
{
|
||||
|
||||
/**
|
||||
* 商品营销活动信息
|
||||
* @param $param
|
||||
* @return array
|
||||
*/
|
||||
public function handle($param)
|
||||
{
|
||||
if (isset($param[ 'goods_sku_detail' ])) {
|
||||
$goods_info = $param[ 'goods_sku_detail' ];
|
||||
if (!empty($goods_info[ 'promotion_addon' ])) {
|
||||
$promotion_addon = json_decode($goods_info[ 'promotion_addon' ], true);
|
||||
if (!empty($promotion_addon[ 'seckill' ])) {
|
||||
return [
|
||||
'promotion_type' => 'seckill',
|
||||
'promotion_name' => '限时秒杀',
|
||||
'id' => $promotion_addon[ 'seckill' ]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (empty($param[ 'goods_id' ])) return [];
|
||||
$goods_model = new GoodsModel();
|
||||
$goods_info = $goods_model->getGoodsInfo([ [ 'goods_id', '=', $param[ 'goods_id' ] ] ], 'promotion_addon')[ 'data' ];
|
||||
if (!empty($goods_info[ 'promotion_addon' ])) {
|
||||
$promotion_addon = json_decode($goods_info[ 'promotion_addon' ], true);
|
||||
if (!empty($promotion_addon[ 'seckill' ])) {
|
||||
$seckill_model = new Seckill();
|
||||
$goods_detail = $seckill_model->getSeckillInfo($promotion_addon[ 'seckill' ])[ 'data' ];
|
||||
if (!empty($goods_detail)) {
|
||||
$time = time() - strtotime(date('Y-m-d'), time());
|
||||
if ($time > $goods_detail[ 'seckill_start_time' ] && $time < $goods_detail[ 'seckill_end_time' ]) {
|
||||
$goods_detail[ 'promotion_type' ] = 'seckill';
|
||||
$goods_detail[ 'promotion_name' ] = '限时秒杀';
|
||||
return $goods_detail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
28
addon/seckill/event/GoodsPromotionType.php
Executable file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
/**
|
||||
* 活动类型
|
||||
*/
|
||||
class GoodsPromotionType
|
||||
{
|
||||
|
||||
/**
|
||||
* 活动类型
|
||||
* @return array
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
return ['name' => '限时秒杀', 'short' => '秒', 'type' => 'seckill', 'color' => '#89689D', 'url' => 'seckill://shop/seckill/goodslist'];
|
||||
}
|
||||
}
|
||||
32
addon/seckill/event/Install.php
Executable file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
/**
|
||||
* 应用安装
|
||||
*/
|
||||
class Install
|
||||
{
|
||||
/**
|
||||
* 执行安装
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
/* try{
|
||||
execute_sql('addon/seckill/data/install.sql');
|
||||
return success();
|
||||
}catch (\Exception $e)
|
||||
{
|
||||
return error('', $e->getMessage());
|
||||
} */
|
||||
return success();
|
||||
}
|
||||
}
|
||||
27
addon/seckill/event/OpenSeckill.php
Executable file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
use addon\seckill\model\Seckill;
|
||||
|
||||
/**
|
||||
* 开启活动
|
||||
*/
|
||||
class OpenSeckill
|
||||
{
|
||||
|
||||
public function handle($params)
|
||||
{
|
||||
$seckill = new Seckill();
|
||||
$res = $seckill->cronOpenSeckill($params[ 'relate_id' ]);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
33
addon/seckill/event/OrderClose.php
Executable file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
use addon\seckill\model\SeckillOrder;
|
||||
|
||||
/**
|
||||
* 订单营销活动类型
|
||||
*/
|
||||
class OrderClose
|
||||
{
|
||||
|
||||
/**
|
||||
* 订单关闭
|
||||
* @param $params
|
||||
* @return array
|
||||
*/
|
||||
public function handle($params)
|
||||
{
|
||||
$seckill = new SeckillOrder();
|
||||
$res = $seckill->orderClose($params[ 'order_id' ]);
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
||||
27
addon/seckill/event/OrderPromotionType.php
Executable file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
/**
|
||||
* 订单营销活动类型
|
||||
*/
|
||||
class OrderPromotionType
|
||||
{
|
||||
|
||||
/**
|
||||
* 订单营销活动类型
|
||||
* @return array
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
return [ "name" => "秒杀", "type" => "seckill" ];
|
||||
}
|
||||
}
|
||||
27
addon/seckill/event/PromotionType.php
Executable file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
/**
|
||||
* 活动类型
|
||||
*/
|
||||
class PromotionType
|
||||
{
|
||||
|
||||
/**
|
||||
* 活动类型
|
||||
* @return array
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
return [ "name" => "秒杀", "type" => "seckill" ];
|
||||
}
|
||||
}
|
||||
37
addon/seckill/event/SeckillZoneConfig.php
Executable file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
|
||||
/**
|
||||
* 活动专区——限时秒杀页面配置
|
||||
*/
|
||||
class SeckillZoneConfig
|
||||
{
|
||||
|
||||
public function handle($params)
|
||||
{
|
||||
if (empty($params) || $params[ 'name' ] == 'seckill') {
|
||||
$data = [
|
||||
'name' => 'seckill', // 标识
|
||||
'title' => '限时秒杀', // 名称
|
||||
'url' => 'shop/adv/lists?keyword=NS_SECKILL', // 自定义跳转链接
|
||||
'preview' => 'addon/seckill/shop/view/public/img/zone_preview.png', // 预览图
|
||||
// 页面配置
|
||||
'value' => [
|
||||
'bg_color' => '#F83530'
|
||||
],
|
||||
];
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
91
addon/seckill/event/ShowPromotion.php
Executable file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 活动展示
|
||||
*/
|
||||
class ShowPromotion
|
||||
{
|
||||
public $promotion_type = 'time_limit';
|
||||
|
||||
/**
|
||||
* 活动展示
|
||||
* @param array $params
|
||||
* @return array
|
||||
*/
|
||||
public function handle($params = [])
|
||||
{
|
||||
$data = [
|
||||
'shop' => [
|
||||
[
|
||||
//插件名称
|
||||
'name' => 'seckill',
|
||||
//展示分类(根据平台端设置,shop:店铺营销,member:会员营销, tool:应用工具)
|
||||
'show_type' => 'shop',
|
||||
//展示主题
|
||||
'title' => '限时秒杀',
|
||||
//展示介绍
|
||||
'description' => '限时抢购引导客户快速下单',
|
||||
//展示图标
|
||||
'icon' => 'addon/seckill/icon.png',
|
||||
//跳转链接
|
||||
'url' => 'seckill://shop/seckill/goodslist',
|
||||
'summary' => $this->summary($params)
|
||||
]
|
||||
]
|
||||
|
||||
];
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 营销活动概况
|
||||
* @param $params
|
||||
* @return array
|
||||
*/
|
||||
private function summary($params)
|
||||
{
|
||||
if (empty($params)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if(isset($params['promotion_type']) && $params['promotion_type'] != $this->promotion_type){
|
||||
return [];
|
||||
}
|
||||
|
||||
//获取活动数量
|
||||
if (isset($params[ 'count' ])) {
|
||||
$count = model("promotion_seckill")->getCount([ [ 'site_id', '=', $params[ 'site_id' ] ] ]);
|
||||
return [
|
||||
'count' => $count
|
||||
];
|
||||
}
|
||||
//获取活动概况,需要获取开始时间与结束时间
|
||||
if (isset($params[ 'summary' ])) {
|
||||
$list = model("promotion_seckill")->getList([
|
||||
[ '', 'exp', Db::raw('not ( (`start_time` >= ' . $params[ 'end_time' ] . ') or (`end_time` <= ' . $params[ 'start_time' ] . '))') ],
|
||||
[ 'site_id', '=', $params[ 'site_id' ] ],
|
||||
[ 'status', '<>', 2 ],
|
||||
[ 'status', '<>', -1 ]
|
||||
], 'seckill_name as promotion_name,id as promotion_id,start_time,end_time', '', 'a', null, 'seckill_name');
|
||||
return !empty($list) ? [
|
||||
'time_limit' => [
|
||||
'count' => count($list),
|
||||
'detail' => $list,
|
||||
'color' => '#6D66FF'
|
||||
]
|
||||
] : [];
|
||||
}
|
||||
}
|
||||
}
|
||||
32
addon/seckill/event/UnInstall.php
Executable file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\event;
|
||||
|
||||
/**
|
||||
* 应用卸载
|
||||
*/
|
||||
class UnInstall
|
||||
{
|
||||
/**
|
||||
* 执行卸载
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
/* try{
|
||||
execute_sql('addon/seckill/data/uninstall.sql');
|
||||
return success();
|
||||
}catch (\Exception $e)
|
||||
{
|
||||
return error('', $e->getMessage());
|
||||
} */
|
||||
return error("系统插件不能删除");
|
||||
}
|
||||
}
|
||||
BIN
addon/seckill/icon.png
Executable file
|
After Width: | Height: | Size: 1.2 KiB |
618
addon/seckill/model/Poster.php
Executable file
@@ -0,0 +1,618 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\model;
|
||||
|
||||
use addon\postertemplate\model\PosterTemplate as PosterTemplateModel;
|
||||
use app\model\BaseModel;
|
||||
use app\model\system\Site;
|
||||
use app\model\upload\Upload;
|
||||
use app\model\web\Config;
|
||||
use extend\Poster as PosterExtend;
|
||||
|
||||
/**
|
||||
* 海报生成类
|
||||
*/
|
||||
class Poster extends BaseModel
|
||||
{
|
||||
/**
|
||||
* 商品海报
|
||||
*/
|
||||
public function goods($app_type, $page, $qrcode_param, $promotion_type, $site_id)
|
||||
{
|
||||
try {
|
||||
$goods_info = $this->getGoodsInfo($qrcode_param[ 'id' ]);
|
||||
if (empty($goods_info)) return $this->error('未获取到商品信息');
|
||||
|
||||
$qrcode_param[ 'id' ] = $qrcode_param[ 'seckillId' ];
|
||||
unset($qrcode_param[ 'seckillId' ]);
|
||||
|
||||
$qrcode_info = $this->getGoodsQrcode($app_type, $page, $qrcode_param, $promotion_type, $site_id);
|
||||
if ($qrcode_info[ 'code' ] < 0) return $qrcode_info;
|
||||
//判断海报是否存在或停用
|
||||
$template_info = $this->getTemplateInfo($goods_info[ 'template_id' ]);
|
||||
if (!empty($qrcode_param[ 'source_member' ])) {
|
||||
$member_info = $this->getMemberInfo($qrcode_param[ 'source_member' ]);
|
||||
}
|
||||
|
||||
$upload_config_model = new Config();
|
||||
$upload_config_result = $upload_config_model->getDefaultImg($site_id);
|
||||
|
||||
$site_model = new Site();
|
||||
$condition = array (
|
||||
[ "site_id", "=", $site_id ]
|
||||
);
|
||||
$site_info = $site_model->getSiteInfo($condition);
|
||||
|
||||
if (empty($goods_info[ 'template_id' ]) || empty($template_info) || $template_info[ 'template_status' ] == 0) {
|
||||
$poster_width = 720;
|
||||
$poster_height = 1150;
|
||||
|
||||
$poster = new PosterExtend($poster_width, $poster_height);
|
||||
|
||||
$option = [
|
||||
[
|
||||
'action' => 'setBackground', // 设背景色
|
||||
'data' => [ 255, 255, 255 ]
|
||||
],
|
||||
[
|
||||
'action' => 'imageCopy', // 写入商品图
|
||||
'data' => [
|
||||
explode(',', $goods_info[ 'sku_image' ])[ 0 ] ?? '',
|
||||
50,
|
||||
165,
|
||||
620,
|
||||
620,
|
||||
'square',
|
||||
true,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品名称
|
||||
'data' => [
|
||||
$goods_info[ 'sku_name' ],
|
||||
22,
|
||||
[ 35, 35, 35 ],
|
||||
50,
|
||||
915,
|
||||
360,
|
||||
2,
|
||||
true,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageCopy', // 写入商品二维码
|
||||
'data' => [
|
||||
$qrcode_info[ 'data' ][ 'path' ],
|
||||
435,
|
||||
825,
|
||||
240,
|
||||
240,
|
||||
'square',
|
||||
0,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入提示
|
||||
'data' => [
|
||||
'长按识别二维码',
|
||||
19,
|
||||
[ 102, 102, 102 ],
|
||||
465,
|
||||
1110,
|
||||
490,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品价格单位
|
||||
'data' => [
|
||||
'秒杀价:¥',
|
||||
22,
|
||||
[ 255, 0, 0 ],
|
||||
50,
|
||||
860,
|
||||
490,
|
||||
2,
|
||||
true,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品价格
|
||||
'data' => [
|
||||
$goods_info[ 'seckill_price' ],
|
||||
30,
|
||||
[ 255, 0, 0 ],
|
||||
188,
|
||||
862,
|
||||
490,
|
||||
2,
|
||||
true,
|
||||
1
|
||||
]
|
||||
],
|
||||
];
|
||||
if (!empty($member_info)) {
|
||||
$member_option = [
|
||||
[
|
||||
'action' => 'imageCircularCopy', // 写入用户头像
|
||||
'data' => [
|
||||
!empty($member_info[ 'headimg' ]) ? $member_info[ 'headimg' ] : $upload_config_result[ 'data' ][ 'value' ][ 'head' ],
|
||||
50,
|
||||
30,
|
||||
100,
|
||||
100
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入分享人昵称
|
||||
'data' => [
|
||||
$member_info[ 'nickname' ],
|
||||
22,
|
||||
[ 10, 10, 10 ],
|
||||
170,
|
||||
80,
|
||||
580,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入分享人昵称
|
||||
'data' => [
|
||||
'限时秒杀,抢到就是赚到',
|
||||
18,
|
||||
[ 102, 102, 102 ],
|
||||
170,
|
||||
115,
|
||||
580,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
]
|
||||
];
|
||||
$option = array_merge($option, $member_option);
|
||||
}
|
||||
} else {
|
||||
$condition = [
|
||||
[ 'template_id', '=', $goods_info[ 'template_id' ] ],
|
||||
[ 'site_id', '=', $site_id ]
|
||||
];
|
||||
$poster_template_model = new PosterTemplateModel();
|
||||
$poster_data = $poster_template_model->getPosterTemplateInfo($condition);
|
||||
$poster_data[ 'data' ][ 'template_json' ] = json_decode($poster_data[ 'data' ][ 'template_json' ], true);
|
||||
$poster_width = 720;
|
||||
$poster_height = 1280;
|
||||
$poster = new PosterExtend($poster_width, $poster_height);
|
||||
$fontRate = 0.725; // 20px 等于 14.5磅,换算比率 1px = 0.725磅
|
||||
if (!empty($poster_data[ 'data' ][ 'background' ])) {
|
||||
list($width, $height, $type, $attr) = getimagesize(img($poster_data[ 'data' ][ 'background' ]));
|
||||
$height = 720 * $height / $width;
|
||||
$back_ground = [
|
||||
'action' => 'imageCopy', // 写入背景图
|
||||
'data' => [
|
||||
img($poster_data[ 'data' ][ 'background' ]),
|
||||
0,
|
||||
0,
|
||||
$poster_width,
|
||||
$height,
|
||||
'square',
|
||||
true,
|
||||
1
|
||||
]
|
||||
];
|
||||
} else {
|
||||
$back_ground = [
|
||||
'action' => 'setBackground', // 设背景色
|
||||
'data' => [ 255, 255, 255 ]
|
||||
];
|
||||
}
|
||||
$ground = [
|
||||
[
|
||||
'action' => 'setBackground',
|
||||
'data' => [ 255, 255, 255 ]
|
||||
]
|
||||
];
|
||||
$option = [
|
||||
$back_ground,
|
||||
[
|
||||
'action' => 'imageText', // 写入店铺名称
|
||||
'data' => [
|
||||
$site_info[ 'data' ][ 'site_name' ],
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_name_font_size' ] * $fontRate * 2,
|
||||
hex2rgb($poster_data[ 'data' ][ 'template_json' ][ 'store_name_color' ]),
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_name_left' ] * 2,
|
||||
( $poster_data[ 'data' ][ 'template_json' ][ 'store_name_top' ] + $poster_data[ 'data' ][ 'template_json' ][ 'store_name_font_size' ] ) * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_name_width' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_name_height' ] * 2,
|
||||
true,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_name_is_show' ]
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageCopy', // 店铺logo
|
||||
'data' => [
|
||||
!empty($site_info[ 'data' ][ 'logo_square' ]) ? $site_info[ 'data' ][ 'logo_square' ] : getUrl() . '/app/shop/view/public/img/shop_logo.png',
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_logo_left' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_logo_top' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_logo_width' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_logo_height' ] * 2,
|
||||
'square',
|
||||
true,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'store_logo_is_show' ]
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageCopy', // 写入商品图
|
||||
'data' => [
|
||||
$goods_info[ 'sku_image' ],
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_img_left' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_img_top' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_img_width' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_img_height' ] * 2,
|
||||
!empty($poster_data[ 'data' ][ 'template_json' ][ 'goods_img_shape' ]) ? $poster_data[ 'data' ][ 'template_json' ][ 'goods_img_shape' ] : 'square',
|
||||
0,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_img_is_show' ]
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品名称
|
||||
'data' => [
|
||||
$goods_info[ 'sku_name' ],
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_name_font_size' ] * $fontRate * 2,
|
||||
hex2rgb($poster_data[ 'data' ][ 'template_json' ][ 'goods_name_color' ]),
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_name_left' ] * 2,
|
||||
( $poster_data[ 'data' ][ 'template_json' ][ 'goods_name_top' ] + $poster_data[ 'data' ][ 'template_json' ][ 'goods_name_font_size' ] ) * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_name_width' ] * 2,
|
||||
1,//文本行数 $poster_data['data']['template_json']['goods_name_height']*2,
|
||||
true,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_name_is_show' ]
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageCopy', // 写入商品二维码
|
||||
'data' => [
|
||||
$qrcode_info[ 'data' ][ 'path' ],
|
||||
$poster_data[ 'data' ][ 'qrcode_left' ] * 2,
|
||||
$poster_data[ 'data' ][ 'qrcode_top' ] * 2,
|
||||
$poster_data[ 'data' ][ 'qrcode_width' ] * 2,
|
||||
$poster_data[ 'data' ][ 'qrcode_height' ] * 2,
|
||||
'square',
|
||||
0,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品价格
|
||||
'data' => [
|
||||
'¥' . $goods_info[ 'seckill_price' ],
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_price_font_size' ] * $fontRate * 2,
|
||||
hex2rgb($poster_data[ 'data' ][ 'template_json' ][ 'goods_price_color' ]),
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_price_left' ] * 2,
|
||||
( $poster_data[ 'data' ][ 'template_json' ][ 'goods_price_top' ] + $poster_data[ 'data' ][ 'template_json' ][ 'goods_price_font_size' ] ) * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_price_width' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_price_height' ] * 2,
|
||||
true,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_price_is_show' ]
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
if ($goods_info[ 'price' ] == 0) {
|
||||
$line = '一一一';
|
||||
} else {
|
||||
$line = '一一一一';
|
||||
}
|
||||
$market_price = [
|
||||
[
|
||||
'action' => 'imageText', // 写入商品划线价格
|
||||
'data' => [
|
||||
'¥' . $goods_info[ 'price' ],
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_font_size' ] * $fontRate * 2,
|
||||
hex2rgb($poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_color' ]),
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_left' ] * 2,
|
||||
( $poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_top' ] + $poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_font_size' ] ) * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_width' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_height' ] * 2,
|
||||
true,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_is_show' ] ?? 0
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入线
|
||||
'data' => [
|
||||
$line,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_font_size' ] * $fontRate * 2,
|
||||
hex2rgb($poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_color' ]),
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_left' ] * 2 - 5,
|
||||
( $poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_top' ] + $poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_font_size' ] ) * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_width' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_height' ] * 2,
|
||||
true,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'goods_market_price_is_show' ]
|
||||
]
|
||||
],
|
||||
];
|
||||
$option = array_merge($option, $market_price);
|
||||
|
||||
if (!empty($member_info)) {
|
||||
$member_option = [
|
||||
[
|
||||
'action' => 'imageCopy', // 写入用户头像
|
||||
'data' => [
|
||||
!empty($member_info[ 'headimg' ]) ? $member_info[ 'headimg' ] : $upload_config_result[ 'data' ][ 'value' ][ 'head' ],
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'headimg_left' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'headimg_top' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'headimg_width' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'headimg_height' ] * 2,
|
||||
!empty($poster_data[ 'data' ][ 'template_json' ][ 'headimg_shape' ]) ? $poster_data[ 'data' ][ 'template_json' ][ 'headimg_shape' ] : 'square',
|
||||
0,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'headimg_is_show' ]
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入分享人昵称
|
||||
'data' => [
|
||||
$member_info[ 'nickname' ],
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'nickname_font_size' ] * $fontRate * 2,
|
||||
hex2rgb($poster_data[ 'data' ][ 'template_json' ][ 'nickname_color' ]),
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'nickname_left' ] * 2,
|
||||
( $poster_data[ 'data' ][ 'template_json' ][ 'nickname_top' ] + $poster_data[ 'data' ][ 'template_json' ][ 'nickname_font_size' ] ) * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'nickname_width' ] * 2,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'nickname_height' ] * 2,
|
||||
0,
|
||||
$poster_data[ 'data' ][ 'template_json' ][ 'nickname_is_show' ]
|
||||
]
|
||||
],
|
||||
];
|
||||
$option = array_merge($ground, $option, $member_option);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$option_res = $poster->create($option);
|
||||
if (is_array($option_res)) return $option_res;
|
||||
|
||||
$res = $option_res->jpeg('upload/poster/goods', 'goods_' . $promotion_type . '_' . $qrcode_param[ 'id' ] . '_' . $qrcode_param[ 'source_member' ] . '_' . time() . '_' . $app_type);
|
||||
if ($res[ 'code' ] == 0) {
|
||||
$upload = new Upload($site_id);
|
||||
$cloud_res = $upload->fileCloud($res[ 'data' ][ 'path' ]);
|
||||
if ($cloud_res[ 'code' ] >= 0) {
|
||||
return $this->success([ "path" => $cloud_res[ 'data' ] ]);
|
||||
} else {
|
||||
return $this->error();
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
} catch (\Exception $e) {
|
||||
return $this->error($e->getMessage() . $e->getFile() . $e->getLine());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
* @param unknown $member_id
|
||||
*/
|
||||
private function getMemberInfo($member_id)
|
||||
{
|
||||
$info = model('member')->getInfo([ 'member_id' => $member_id ], 'nickname,headimg');
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品信息
|
||||
* @param unknown $sku_id
|
||||
*/
|
||||
private function getGoodsInfo($id)
|
||||
{
|
||||
$alias = 'npsg';
|
||||
$join = [
|
||||
[ 'goods_sku ngs', 'npsg.sku_id = ngs.sku_id', 'inner' ]
|
||||
];
|
||||
$field = 'ngs.sku_name,ngs.introduction,ngs.sku_image,ngs.sku_id,npsg.seckill_price, npsg.seckill_id,ngs.template_id,ngs.price';
|
||||
$info = model('promotion_seckill_goods')->getInfo([ 'npsg.goods_id' => $id ], $field, $alias, $join);
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品二维码
|
||||
* @param unknown $app_type 请求类型
|
||||
* @param unknown $page uniapp页面路径
|
||||
* @param unknown $qrcode_param 二维码携带参数
|
||||
* @param string $promotion_type 活动类型 null为无活动
|
||||
*/
|
||||
private function getGoodsQrcode($app_type, $page, $qrcode_param, $promotion_type, $site_id)
|
||||
{
|
||||
$res = event('Qrcode', [
|
||||
'site_id' => $site_id,
|
||||
'app_type' => $app_type,
|
||||
'type' => 'create',
|
||||
'data' => $qrcode_param,
|
||||
'page' => $page,
|
||||
'qrcode_path' => 'upload/qrcode/goods',
|
||||
'qrcode_name' => 'goods_' . $promotion_type . '_' . $qrcode_param[ 'id' ] . '_' . $qrcode_param[ 'source_member' ] . '_' . $site_id,
|
||||
], true);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取海报信息
|
||||
* @param unknown $template_id
|
||||
*/
|
||||
private function getTemplateInfo($template_id)
|
||||
{
|
||||
$info = model('poster_template')->getInfo([ 'template_id' => $template_id ], 'template_id,template_status');
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享图片
|
||||
* @param $page
|
||||
* @param $qrcode_param
|
||||
* @param $site_id
|
||||
* @return array|\extend\multitype|PosterExtend|string|string[]
|
||||
*/
|
||||
public function shareImg($page, $qrcode_param, $site_id)
|
||||
{
|
||||
try {
|
||||
$goods_info = $this->getGoodsInfo($qrcode_param[ 'id' ]);
|
||||
if (empty($goods_info)) return $this->error('未获取到商品信息');
|
||||
|
||||
$poster_width = 600;
|
||||
$poster_height = 480;
|
||||
|
||||
$poster = new PosterExtend($poster_width, $poster_height);
|
||||
$option = [
|
||||
[
|
||||
'action' => 'setBackground', // 设背景色
|
||||
'data' => [ 255, 255, 255 ]
|
||||
],
|
||||
[
|
||||
'action' => 'imageCopy', // 商品图
|
||||
'data' => [
|
||||
$goods_info[ 'sku_image' ],
|
||||
30,
|
||||
145,
|
||||
200,
|
||||
200,
|
||||
'square',
|
||||
50,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品名称
|
||||
'data' => [
|
||||
$goods_info[ 'sku_name' ],
|
||||
22,
|
||||
[ 51, 51, 51 ],
|
||||
250,
|
||||
190,
|
||||
330,
|
||||
2,
|
||||
false,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品价格
|
||||
'data' => [
|
||||
'秒杀价:¥',
|
||||
15,
|
||||
[ 255, 0, 0 ],
|
||||
250,
|
||||
300,
|
||||
300,
|
||||
2,
|
||||
false,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品价格
|
||||
'data' => [
|
||||
$goods_info[ 'seckill_price' ],
|
||||
30,
|
||||
[ 255, 0, 0 ],
|
||||
345,
|
||||
300,
|
||||
300,
|
||||
2,
|
||||
false,
|
||||
1,
|
||||
PUBLIC_PATH . 'static/font/custom.ttf'
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品原价
|
||||
'data' => [
|
||||
'原 价:¥',
|
||||
15,
|
||||
[ 153, 153, 153 ],
|
||||
250,
|
||||
340,
|
||||
300,
|
||||
2,
|
||||
false,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageText', // 写入商品原价
|
||||
'data' => [
|
||||
$goods_info[ 'price' ],
|
||||
16,
|
||||
[ 153, 153, 153 ],
|
||||
345,
|
||||
338,
|
||||
300,
|
||||
2,
|
||||
false,
|
||||
1,
|
||||
PUBLIC_PATH . 'static/font/custom.ttf',
|
||||
]
|
||||
],
|
||||
// 划线(两条线)
|
||||
[
|
||||
'action' => 'imageline',
|
||||
'data' => [
|
||||
325,
|
||||
330,
|
||||
325 + imagettfbbox(16, 0, PUBLIC_PATH . 'static/font/custom.ttf', '¥ ' . $goods_info[ 'price' ])[ 2 ],
|
||||
330,
|
||||
[ 153, 153, 153 ],
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageline',
|
||||
'data' => [
|
||||
325,
|
||||
331,
|
||||
325 + imagettfbbox(16, 0, PUBLIC_PATH . 'static/font/custom.ttf', '¥ ' . $goods_info[ 'price' ])[ 2 ],
|
||||
331,
|
||||
[ 153, 153, 153 ],
|
||||
]
|
||||
],
|
||||
[
|
||||
'action' => 'imageCopy', // 背景图
|
||||
'data' => [
|
||||
img('upload/share_img/bg/seckill_1.png'),
|
||||
0,
|
||||
0,
|
||||
600,
|
||||
480,
|
||||
'square',
|
||||
0,
|
||||
1
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
$option_res = $poster->create($option);
|
||||
if (is_array($option_res)) {
|
||||
return $option_res;
|
||||
}
|
||||
|
||||
$res = $option_res->jpeg('upload/share_img/seckill_' . $goods_info[ 'seckill_id' ], 'sku_' . $goods_info[ 'sku_id' ]);
|
||||
return $res;
|
||||
} catch (\Exception $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
949
addon/seckill/model/Seckill.php
Executable file
@@ -0,0 +1,949 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\model;
|
||||
|
||||
use app\dict\order_refund\OrderRefundDict;
|
||||
use app\model\BaseModel;
|
||||
use app\model\goods\Goods;
|
||||
use app\model\order\Order;
|
||||
use app\model\system\Config as ConfigModel;
|
||||
use app\model\system\Cron;
|
||||
use think\facade\Cache;
|
||||
use think\facade\Db;
|
||||
|
||||
|
||||
/**
|
||||
* 限时秒杀(时段)
|
||||
*/
|
||||
class Seckill extends BaseModel
|
||||
{
|
||||
/**
|
||||
* 添加秒杀时段
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public function addSeckillTime($data)
|
||||
{
|
||||
if ($data[ 'seckill_start_time' ] > $data[ 'seckill_end_time' ]) {
|
||||
return $this->error('', '秒杀时间段设置错误');
|
||||
}
|
||||
|
||||
//时间段检测
|
||||
$seckill_count = model('promotion_seckill_time')->getCount([
|
||||
['seckill_start_time|seckill_end_time', 'between', [$data[ 'seckill_start_time' ], $data[ 'seckill_end_time' ]]],
|
||||
['site_id', '=', $data[ 'site_id' ]]
|
||||
]);
|
||||
if ($seckill_count > 0) {
|
||||
return $this->error('', '秒杀场次设置冲突');
|
||||
}
|
||||
$seckill_count = model('promotion_seckill_time')->getCount([
|
||||
['seckill_start_time', '<=', $data[ 'seckill_start_time' ]],
|
||||
['seckill_end_time', '>=', $data[ 'seckill_end_time' ]],
|
||||
['site_id', '=', $data[ 'site_id' ]]
|
||||
]);
|
||||
if ($seckill_count > 0) {
|
||||
return $this->error('', '秒杀场次设置冲突');
|
||||
}
|
||||
//添加数据
|
||||
$data[ 'create_time' ] = time();
|
||||
$seckill_id = model('promotion_seckill_time')->add($data);
|
||||
Cache::tag("promotion_seckill_time")->clear();
|
||||
return $this->success($seckill_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改秒杀时段
|
||||
* @param $data
|
||||
* @param $site_id
|
||||
* @return array
|
||||
*/
|
||||
public function editSeckillTime($data, $site_id)
|
||||
{
|
||||
if ($data[ 'seckill_start_time' ] > $data[ 'seckill_end_time' ]) {
|
||||
return $this->error('', '秒杀时间段设置错误');
|
||||
}
|
||||
//时间段检测
|
||||
$seckill_count = model('promotion_seckill_time')->getCount([
|
||||
['seckill_start_time|seckill_end_time', 'between', [$data[ 'seckill_start_time' ], $data[ 'seckill_end_time' ]]],
|
||||
['site_id', '=', $site_id],
|
||||
['id', '<>', $data[ 'id' ]]
|
||||
]);
|
||||
if ($seckill_count > 0) {
|
||||
return $this->error('', '秒杀场次设置冲突');
|
||||
}
|
||||
$seckill_count = model('promotion_seckill_time')->getCount([
|
||||
['seckill_start_time', '<=', $data[ 'seckill_start_time' ]],
|
||||
['seckill_end_time', '>=', $data[ 'seckill_end_time' ]],
|
||||
['site_id', '=', $site_id],
|
||||
['id', '<>', $data[ 'id' ]]
|
||||
]);
|
||||
if ($seckill_count > 0) {
|
||||
return $this->error('', '秒杀场次设置冲突');
|
||||
}
|
||||
|
||||
//更新数据
|
||||
$data[ 'modify_time' ] = time();
|
||||
$res = model('promotion_seckill_time')->update($data, [['id', '=', $data[ 'id' ]]]);
|
||||
Cache::tag("promotion_seckill_time")->clear();
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除秒杀时段
|
||||
* @param $seckill_time_id
|
||||
* @return array
|
||||
*/
|
||||
public function deleteSeckillTime($seckill_time_id)
|
||||
{
|
||||
$res = model('promotion_seckill_time')->delete([['id', '=', $seckill_time_id]]);
|
||||
if ($res) {
|
||||
|
||||
$goods = new Goods();
|
||||
|
||||
$condition = [
|
||||
['seckill_time_id', 'like', '%,' . $seckill_time_id . ',%']
|
||||
];
|
||||
$seckill_list = model('promotion_seckill')->getList($condition, 'id,seckill_time_id,goods_id');
|
||||
|
||||
foreach ($seckill_list as $k => $v) {
|
||||
|
||||
$time_ids = explode(',', trim($v[ 'seckill_time_id' ], ','));
|
||||
unset($time_ids[ array_search($seckill_time_id, $time_ids) ]);
|
||||
|
||||
if (empty($time_ids)) {
|
||||
$goods->modifyPromotionAddon($v[ 'goods_id' ], ['seckill' => $v[ 'id' ]], true);
|
||||
model('promotion_seckill_goods')->delete([['seckill_id', '=', $v[ 'id' ]]]);
|
||||
model('promotion_seckill')->delete([['id', '=', $v[ 'id' ]]]);
|
||||
} else {
|
||||
|
||||
$time_id = ',' . implode(',', $time_ids) . ',';
|
||||
model('promotion_seckill')->update(['seckill_time_id' => $time_id], [['id', '=', $v[ 'id' ]]]);
|
||||
model('promotion_seckill_goods')->update(['seckill_time_id' => $time_id], [['seckill_id', '=', $v[ 'id' ]]]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Cache::tag("promotion_seckill_time")->clear();
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒杀时段信息
|
||||
* @param $condition
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillTimeInfo($condition, $field = '*')
|
||||
{
|
||||
$res = model('promotion_seckill_time')->getInfo($condition, $field);
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒杀时段列表
|
||||
* @param array $condition
|
||||
* @param string $field
|
||||
* @param string $order
|
||||
* @param null $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillTimeList($condition = [], $field = '*', $order = '', $limit = null)
|
||||
{
|
||||
$list = model('promotion_seckill_time')->getList($condition, $field, $order, '', '', '', $limit);
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取有商品的秒杀时段列表
|
||||
* @param $condition
|
||||
* @param $field
|
||||
* @param string $order
|
||||
* @return array
|
||||
*/
|
||||
public function getGoodsSeckillTimeList($condition, $field, $order = 'seckill_start_time asc')
|
||||
{
|
||||
if (empty($field)) {
|
||||
$field = 'id, site_id, name, seckill_start_time, seckill_end_time';
|
||||
}
|
||||
|
||||
$seckill_time = model('promotion_seckill_time')->getList($condition, $field, $order);
|
||||
foreach ($seckill_time as $k => $v) {
|
||||
$condition = [
|
||||
['seckill_time_id', 'like', '%,' . $v[ 'id' ] . ',%'],
|
||||
['status', '=', 1],
|
||||
['g.goods_state', '=', 1],
|
||||
['g.is_delete', '=', 0]
|
||||
];
|
||||
$join = [
|
||||
['goods g', 'g.goods_id = psg.goods_id', 'inner']
|
||||
];
|
||||
$goods = model('promotion_seckill_goods')->getInfo($condition, 'id', 'psg', $join);
|
||||
if (empty($goods)) unset($seckill_time[ $k ]);
|
||||
}
|
||||
return $this->success($seckill_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换秒杀时间
|
||||
* @param $info
|
||||
* @return mixed
|
||||
*/
|
||||
public function transformSeckillTime($info)
|
||||
{
|
||||
$info[ 'start_hour' ] = floor($info[ 'seckill_start_time' ] / 3600);
|
||||
$info[ 'start_minute' ] = floor(($info[ 'seckill_start_time' ] % 3600) / 60);
|
||||
$info[ 'start_second' ] = $info[ 'seckill_start_time' ] % 60;
|
||||
|
||||
$info[ 'end_hour' ] = floor($info[ 'seckill_end_time' ] / 3600);
|
||||
$info[ 'end_minute' ] = floor(($info[ 'seckill_end_time' ] % 3600) / 60);
|
||||
$info[ 'end_second' ] = $info[ 'seckill_end_time' ] % 60;
|
||||
|
||||
if ($info[ 'start_hour' ] < 10) $info[ 'start_hour' ] = '0' . $info[ 'start_hour' ];
|
||||
if ($info[ 'start_minute' ] < 10) $info[ 'start_minute' ] = '0' . $info[ 'start_minute' ];
|
||||
if ($info[ 'start_second' ] < 10) $info[ 'start_second' ] = '0' . $info[ 'start_second' ];
|
||||
|
||||
if ($info[ 'end_hour' ] < 10) $info[ 'end_hour' ] = '0' . $info[ 'end_hour' ];
|
||||
if ($info[ 'end_minute' ] < 10) $info[ 'end_minute' ] = '0' . $info[ 'end_minute' ];
|
||||
if ($info[ 'end_second' ] < 10) $info[ 'end_second' ] = '0' . $info[ 'end_second' ];
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/******************************************************秒杀商品*********************************************************************/
|
||||
/**
|
||||
* 添加秒杀商品
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public function addSeckillGoods($data)
|
||||
{
|
||||
$cron = new Cron();
|
||||
$goods_data = $data[ 'goods_data' ];
|
||||
|
||||
if (empty($data[ 'seckill_time_id' ])) {
|
||||
return $this->error('', '请选择秒杀时段');
|
||||
}
|
||||
$seckill_time_id = explode(',', $data[ 'seckill_time_id' ]);
|
||||
|
||||
//时间段检测
|
||||
foreach ($seckill_time_id as $v) {
|
||||
$seckill_count = model('promotion_seckill')->getCount([
|
||||
['goods_id', 'in', $data[ 'goods_ids' ]],
|
||||
['status', 'in', '0,1'],
|
||||
['seckill_time_id', 'like', '%,' . $v . ',%'],
|
||||
['site_id', '=', $data[ 'site_id' ]],
|
||||
['', 'exp', Db::raw('not ( (`start_time` > ' . $data[ 'end_time' ] . ' and `start_time` > ' . $data[ 'start_time' ] . ' ) or (`end_time` < ' . $data[ 'start_time' ] . ' and `end_time` < ' . $data[ 'end_time' ] . '))')]//todo 修正 所有的优惠都要一样
|
||||
]);
|
||||
if ($seckill_count > 0) {
|
||||
return $this->error('', '有商品已设置秒杀,请不要重复设置');
|
||||
}
|
||||
}
|
||||
|
||||
model('promotion_seckill')->startTrans();
|
||||
try {
|
||||
$seckill_data = [
|
||||
'site_id' => $data[ 'site_id' ],
|
||||
'seckill_name' => $data[ 'seckill_name' ],
|
||||
'remark' => $data[ 'remark' ],
|
||||
'seckill_time_id' => ',' . $data[ 'seckill_time_id' ] . ',',
|
||||
'start_time' => $data[ 'start_time' ],
|
||||
'end_time' => $data[ 'end_time' ],
|
||||
'create_time' => time(),
|
||||
'sort' => $data[ 'sort' ],
|
||||
];
|
||||
|
||||
$goods = new Goods();
|
||||
$add_goods_data = [];
|
||||
foreach ($goods_data as $k => $v) {
|
||||
$seckill_data[ 'goods_id' ] = $v[ 'goods_id' ];
|
||||
$seckill_data[ 'goods_name' ] = $v[ 'sku_list' ][ 0 ][ 'sku_name' ];
|
||||
$seckill_data[ 'goods_image' ] = $v[ 'sku_list' ][ 0 ][ 'sku_image' ];
|
||||
$seckill_data[ 'seckill_price' ] = $v[ 'sku_list' ][ 0 ][ 'seckill_price' ];
|
||||
|
||||
if ($data[ 'start_time' ] <= time()) {
|
||||
$seckill_data[ 'status' ] = 1;//直接启动
|
||||
$seckill_id = model('promotion_seckill')->add($seckill_data);
|
||||
$goods->modifyPromotionAddon($v[ 'goods_id' ], ['seckill' => $seckill_id]);
|
||||
$cron->addCron(1, 0, "秒杀关闭", "CloseSeckill", $data[ 'end_time' ], $seckill_id);
|
||||
} else {
|
||||
$seckill_data[ 'status' ] = 0;
|
||||
$seckill_id = model('promotion_seckill')->add($seckill_data);
|
||||
$cron->addCron(1, 0, "秒杀开启", "OpenSeckill", $data[ 'start_time' ], $seckill_id);
|
||||
$cron->addCron(1, 0, "秒杀关闭", "CloseSeckill", $data[ 'end_time' ], $seckill_id);
|
||||
}
|
||||
|
||||
$goods_stock = 0; // 秒杀商品总库存
|
||||
|
||||
foreach ($v[ 'sku_list' ] as $key => $item) {
|
||||
$sku_info = model('goods_sku')->getInfo([['sku_id', '=', $item[ 'sku_id' ]]], 'goods_id, sku_id, sku_name,price,sku_image');
|
||||
$add_goods_data[] = [
|
||||
'site_id' => $data[ 'site_id' ],
|
||||
'seckill_id' => $seckill_id,
|
||||
'seckill_time_id' => ',' . $data[ 'seckill_time_id' ] . ',',
|
||||
'sku_id' => $item[ 'sku_id' ],
|
||||
'goods_id' => $item[ 'goods_id' ],
|
||||
'sku_image' => $sku_info[ 'sku_image' ],
|
||||
'sku_name' => $sku_info[ 'sku_name' ],
|
||||
'seckill_price' => $item[ 'seckill_price' ],
|
||||
'price' => $sku_info[ 'price' ],
|
||||
'stock' => $item[ 'seckill_stock' ],
|
||||
'max_buy' => $item[ 'max_buy' ],
|
||||
'status' => $seckill_data[ 'status' ]
|
||||
];
|
||||
$goods_stock += $item[ 'seckill_stock' ];
|
||||
}
|
||||
model('promotion_seckill')->update(['goods_stock' => $goods_stock], [['id', '=', $seckill_id]]);
|
||||
}
|
||||
model('promotion_seckill_goods')->addList($add_goods_data);
|
||||
foreach ($seckill_time_id as $v) {
|
||||
$count = model('promotion_seckill_goods')->getCount([['seckill_time_id', 'like', '%,' . $v . ',%']], '*', 'a', '', 'goods_id');
|
||||
model('promotion_seckill_time')->update(['goods_num' => $count], [['id', '=', $v]]);
|
||||
}
|
||||
model('promotion_seckill')->commit();
|
||||
return $this->success();
|
||||
} catch (\Exception $e) {
|
||||
model('promotion_seckill')->rollback();
|
||||
return $this->error('', $e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改秒杀商品
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public function editSeckillGoods($data)
|
||||
{
|
||||
$cron = new Cron();
|
||||
|
||||
if (empty($data[ 'seckill_time_id' ])) {
|
||||
return $this->error('', '请选择秒杀时段');
|
||||
}
|
||||
$seckill_time_id = explode(',', $data[ 'seckill_time_id' ]);
|
||||
|
||||
//时间段检测
|
||||
foreach ($seckill_time_id as $v) {
|
||||
$seckill_count = model('promotion_seckill')->getInfo([
|
||||
['goods_id', 'in', $data[ 'goods_ids' ]],
|
||||
['status', 'in', '0,1'],
|
||||
['site_id', '=', $data[ 'site_id' ]],
|
||||
['seckill_time_id', 'like', '%,' . $v . ',%'],
|
||||
['id', '<>', $data[ 'id' ]],
|
||||
['', 'exp', Db::raw('not ( (`start_time` > ' . $data[ 'end_time' ] . ' and `start_time` > ' . $data[ 'start_time' ] . ' ) or (`end_time` < ' . $data[ 'start_time' ] . ' and `end_time` < ' . $data[ 'end_time' ] . '))')]//todo 修正 所有的优惠都要一样
|
||||
]);
|
||||
if ($seckill_count > 0) {
|
||||
return $this->error('', '有商品已设置秒杀,请不要重复设置');
|
||||
}
|
||||
}
|
||||
|
||||
model('promotion_seckill')->startTrans();
|
||||
try {
|
||||
$seckill_data = [
|
||||
'site_id' => $data[ 'site_id' ],
|
||||
'seckill_name' => $data[ 'seckill_name' ],
|
||||
'remark' => $data[ 'remark' ],
|
||||
'seckill_time_id' => ',' . $data[ 'seckill_time_id' ] . ',',
|
||||
'start_time' => $data[ 'start_time' ],
|
||||
'end_time' => $data[ 'end_time' ],
|
||||
'modify_time' => time(),
|
||||
'sort' => $data[ 'sort' ],
|
||||
];
|
||||
|
||||
$goods = new Goods();
|
||||
$add_goods_data = [];
|
||||
$seckill_data[ 'goods_id' ] = $data[ 'sku_list' ][ 0 ][ 'goods_id' ];
|
||||
$seckill_data[ 'goods_name' ] = $data[ 'sku_list' ][ 0 ][ 'sku_name' ];
|
||||
$seckill_data[ 'goods_image' ] = $data[ 'sku_list' ][ 0 ][ 'sku_image' ];
|
||||
$seckill_data[ 'seckill_price' ] = $data[ 'sku_list' ][ 0 ][ 'seckill_price' ];
|
||||
|
||||
$seckill_id = $data[ 'id' ];
|
||||
|
||||
if ($data[ 'start_time' ] <= time()) {
|
||||
$seckill_data[ 'status' ] = 1;//直接启动
|
||||
model('promotion_seckill')->update($seckill_data, [['id', '=', $seckill_id]]);
|
||||
$goods->modifyPromotionAddon($data[ 'sku_list' ][ 0 ][ 'goods_id' ], ['seckill' => $seckill_id]);
|
||||
$cron->addCron(1, 0, "秒杀关闭", "CloseSeckill", $data[ 'end_time' ], $seckill_id);
|
||||
} else {
|
||||
$seckill_data[ 'status' ] = 0;
|
||||
model('promotion_seckill')->update($seckill_data, [['id', '=', $seckill_id]]);
|
||||
$cron->addCron(1, 0, "秒杀开启", "OpenSeckill", $data[ 'start_time' ], $seckill_id);
|
||||
$cron->addCron(1, 0, "秒杀关闭", "CloseSeckill", $data[ 'end_time' ], $seckill_id);
|
||||
}
|
||||
|
||||
model('promotion_seckill_goods')->delete([['seckill_id', '=', $seckill_id]]);
|
||||
|
||||
$goods_stock = 0; // 秒杀商品总库存
|
||||
|
||||
foreach ($data[ 'sku_list' ] as $key => $item) {
|
||||
$sku_info = model('goods_sku')->getInfo([['sku_id', '=', $item[ 'sku_id' ]]], 'goods_id, sku_id, sku_name,price,sku_image');
|
||||
$add_goods_data[] = [
|
||||
'site_id' => $data[ 'site_id' ],
|
||||
'seckill_id' => $seckill_id,
|
||||
'seckill_time_id' => ',' . $data[ 'seckill_time_id' ] . ',',
|
||||
'sku_id' => $item[ 'sku_id' ],
|
||||
'goods_id' => $item[ 'goods_id' ],
|
||||
'sku_image' => $sku_info[ 'sku_image' ],
|
||||
'sku_name' => $sku_info[ 'sku_name' ],
|
||||
'seckill_price' => $item[ 'seckill_price' ],
|
||||
'price' => $sku_info[ 'price' ],
|
||||
'stock' => $item[ 'seckill_stock' ],
|
||||
'max_buy' => $item[ 'max_buy' ],
|
||||
'status' => $seckill_data[ 'status' ]
|
||||
];
|
||||
$goods_stock += $item[ 'seckill_stock' ];
|
||||
}
|
||||
model('promotion_seckill')->update(['goods_stock' => $goods_stock], [['id', '=', $seckill_id]]);
|
||||
model('promotion_seckill_goods')->addList($add_goods_data);
|
||||
|
||||
foreach ($seckill_time_id as $v) {
|
||||
$count = model('promotion_seckill_goods')->getCount([['seckill_time_id', 'like', '%,' . $v . ',%']], '*', 'a', '', 'goods_id');
|
||||
model('promotion_seckill_time')->update(['goods_num' => $count], [['id', '=', $v]]);
|
||||
}
|
||||
model('promotion_seckill')->commit();
|
||||
return $this->success();
|
||||
} catch (\Exception $e) {
|
||||
model('promotion_seckill')->rollback();
|
||||
return $this->error('', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function seckillSort($id, $sort)
|
||||
{
|
||||
$res = model('promotion_seckill')->update(['sort' => $sort], [['id', '=', $id]]);
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀商品详情
|
||||
* @param array $condition
|
||||
* @param string $field
|
||||
* @param string $alias
|
||||
* @param array $join
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillDetail($condition = [], $field = '*', $alias = '', $join = [])
|
||||
{
|
||||
$info = model("promotion_seckill")->getInfo($condition, $field, $alias, $join);
|
||||
|
||||
$goods_sku = model('goods_sku')->getList([['goods_id', '=', $info[ 'goods_id' ]], ['is_delete', '=', 0], ['goods_state', '=', 1]], 'stock as goods_stock, goods_id, sku_id, sku_name,price,sku_image,stock');
|
||||
|
||||
$discount_goods = model("promotion_seckill_goods")->getList([['goods_id', '=', $info[ 'goods_id' ]], ['seckill_id', '=', $info[ 'id' ]]], '*');
|
||||
|
||||
foreach ($goods_sku as $k => $v) {
|
||||
$goods_sku[ $k ][ 'is_select' ] = 0;
|
||||
$goods_sku[ $k ][ 'seckill_price' ] = $v[ 'price' ];
|
||||
$goods_sku[ $k ][ 'seckill_stock' ] = 0;
|
||||
$goods_sku[ $k ][ 'max_buy' ] = 0;
|
||||
$goods_sku[ $k ][ 'stock' ] = numberFormat($goods_sku[ $k ][ 'stock' ]);
|
||||
$goods_sku[ $k ][ 'goods_stock' ] = numberFormat($goods_sku[ $k ][ 'goods_stock' ]);
|
||||
foreach ($discount_goods as $key => $val) {
|
||||
if ($val[ 'sku_id' ] == $v[ 'sku_id' ]) {
|
||||
$goods_sku[ $k ][ 'is_select' ] = 1;
|
||||
$goods_sku[ $k ][ 'seckill_price' ] = $val[ 'seckill_price' ];
|
||||
$goods_sku[ $k ][ 'seckill_stock' ] = $val[ 'stock' ];
|
||||
$goods_sku[ $k ][ 'max_buy' ] = $val[ 'max_buy' ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$info[ 'goods_sku' ] = $goods_sku;
|
||||
$info[ 'seckill_goods' ] = $discount_goods;
|
||||
|
||||
return $this->success($info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改秒杀商品限购数量
|
||||
* @param $seckill_id
|
||||
* @param $site_id
|
||||
* @param $sku_id
|
||||
* @param $max_buy
|
||||
* @return array
|
||||
*/
|
||||
public function editSeckillGoodsNum($seckill_id, $site_id, $sku_id, $max_buy)
|
||||
{
|
||||
$data = [
|
||||
'seckill_id' => $seckill_id,
|
||||
'site_id' => $site_id,
|
||||
'sku_id' => $sku_id,
|
||||
'max_buy' => $max_buy
|
||||
];
|
||||
model("promotion_seckill_goods")->update($data, [['seckill_id', '=', $seckill_id], ['sku_id', '=', $sku_id], ['site_id', '=', $site_id]]);
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除秒杀商品
|
||||
* @param $seckill_id
|
||||
* @param $site_id
|
||||
* @return array
|
||||
*/
|
||||
public function deleteSeckillGoods($seckill_id, $site_id)
|
||||
{
|
||||
$info = model("promotion_seckill")->getInfo([['id', '=', $seckill_id]], 'goods_id,seckill_time_id,status');
|
||||
|
||||
if (empty($info)) return $this->error('', '该秒杀活动不存在');
|
||||
if ($info[ 'status' ] == 1) return $this->error('', '该秒杀活动正在进行');
|
||||
|
||||
$goods = new Goods();
|
||||
$goods->modifyPromotionAddon($info[ 'goods_id' ], ['seckill' => $seckill_id], true);
|
||||
model("promotion_seckill")->delete([['id', '=', $seckill_id], ['site_id', '=', $site_id]]);
|
||||
$goods_num = model("promotion_seckill_goods")->delete([['seckill_id', '=', $seckill_id], ['site_id', '=', $site_id]]);
|
||||
$seckill_time_id = explode(',', $info[ 'seckill_time_id' ]);
|
||||
foreach ($seckill_time_id as $v) {
|
||||
$count = model('promotion_seckill_goods')->getCount([['seckill_time_id', 'like', '%,' . $v . ',%']], '*', 'a', '', 'goods_id');
|
||||
model('promotion_seckill_time')->update(['goods_num' => $count], [['id', '=', $v]]);
|
||||
}
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒杀详情
|
||||
* @param $seckill_id
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillInfo($seckill_id)
|
||||
{
|
||||
$seckill_info = model('promotion_seckill')->getInfo([['id', '=', $seckill_id]]);
|
||||
if (empty($seckill_info)) {
|
||||
return $this->success([]);
|
||||
}
|
||||
$seckill_info[ 'seckill_start_time' ] = 0;
|
||||
$seckill_info[ 'seckill_end_time' ] = 0;
|
||||
$today_time = strtotime(date("Y-m-d"), time());
|
||||
$time = time() - $today_time;//当日时间戳
|
||||
|
||||
$seckill_time_id = trim($seckill_info[ 'seckill_time_id' ], ',');
|
||||
$condition = [
|
||||
['id', 'in', $seckill_time_id],
|
||||
['seckill_start_time', '<=', $time],
|
||||
['seckill_end_time', '>', $time],
|
||||
];
|
||||
$time_list = model('promotion_seckill_time')->getList($condition, 'seckill_start_time, seckill_end_time', 'seckill_start_time asc', '', '', '', 1);
|
||||
if (count($time_list) > 0) {
|
||||
$seckill_info[ 'seckill_start_time' ] = $time_list[ 0 ][ 'seckill_start_time' ];
|
||||
$seckill_info[ 'seckill_end_time' ] = $time_list[ 0 ][ 'seckill_end_time' ];
|
||||
}
|
||||
|
||||
//所有秒杀时间段
|
||||
$seckill_time_id = trim($seckill_info[ 'seckill_time_id' ], ',');
|
||||
$condition = [
|
||||
['id', 'in', $seckill_time_id],
|
||||
];
|
||||
$time_list = model('promotion_seckill_time')->getList($condition, 'seckill_start_time, seckill_end_time', 'seckill_start_time asc');
|
||||
$seckill_info['time_list'] = $time_list;
|
||||
|
||||
return $this->success($seckill_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒杀列表
|
||||
* @param array $condition
|
||||
* @param int $page
|
||||
* @param int $page_size
|
||||
* @param string $order
|
||||
* @param string $field
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSeckillPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '', $alias = '', $join = [])
|
||||
{
|
||||
$list = model('promotion_seckill')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒杀商品列表
|
||||
* @param $seckill_time_id
|
||||
* @param $site_id
|
||||
* @param int $page
|
||||
* @param int $page_size
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillGoodsPageList($seckill_time_id, $site_id, $page = 1, $page_size = PAGE_LIST_ROWS, $seckill_time_type = 'today')
|
||||
{
|
||||
//判断时间段
|
||||
$seckill_time_info = model('promotion_seckill_time')->getInfo([['id', '=', $seckill_time_id]]);
|
||||
$day_start_time = strtotime(date('Y-m-d'));
|
||||
if($seckill_time_type == 'tomorrow'){
|
||||
$day_start_time += 3600*24;
|
||||
}
|
||||
$start_time = $day_start_time + $seckill_time_info['seckill_start_time'];
|
||||
$end_time = $day_start_time + $seckill_time_info['seckill_end_time'];
|
||||
|
||||
$alias = 'ps';
|
||||
$join = [
|
||||
['goods g', 'ps.goods_id = g.goods_id', 'inner'],
|
||||
['promotion_seckill_goods psg', 'psg.seckill_id = ps.id', 'inner'],
|
||||
['goods_sku gs', 'psg.sku_id = gs.sku_id', 'inner'],
|
||||
];
|
||||
$condition = [
|
||||
['ps.seckill_time_id', 'like', '%,' . $seckill_time_id . ',%'],
|
||||
['ps.status', '=', 1],
|
||||
['ps.start_time', '<=', $start_time],
|
||||
['ps.end_time', '>=', $end_time],
|
||||
['g.goods_state', '=', 1],
|
||||
['g.is_delete', '=', 0],
|
||||
['ps.site_id', '=', $site_id],
|
||||
];
|
||||
//展示库存要和实际库存做比较,取二者的较小值
|
||||
$sum_field = 'sum(IF(psg.stock < gs.stock, psg.stock, gs.stock))';
|
||||
$goods_stock_field = 'IF(ps.goods_stock < '.$sum_field.', ps.goods_stock, '.$sum_field.') as goods_stock';
|
||||
$field = 'ps.id,ps.site_id,ps.seckill_name,ps.status,ps.remark,ps.start_time,ps.end_time,'.$goods_stock_field.',
|
||||
ps.goods_id,ps.seckill_time_id,ps.seckill_price,ps.sale_num,
|
||||
g.goods_name,g.goods_image,g.price';
|
||||
$order = 'ps.sort asc,g.goods_id desc';
|
||||
$group = 'ps.id';
|
||||
$res = model('promotion_seckill')->pageList($condition, $field, $order, $page, $page_size, $alias, $join, $group);
|
||||
foreach ($res[ 'list' ] as $k => $v) {
|
||||
$res[ 'list' ][ $k ][ 'goods_stock' ] = numberFormat($res[ 'list' ][ $k ][ 'goods_stock' ]);
|
||||
}
|
||||
return $this->success($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒杀商品列表
|
||||
* @param $seckill_time_id
|
||||
* @param $site_id
|
||||
* @param null $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillList($seckill_time_id, $site_id, $limit = null)
|
||||
{
|
||||
$alias = 'ps';
|
||||
$join = [
|
||||
['goods g', 'ps.goods_id = g.goods_id', 'inner'],
|
||||
['promotion_seckill_goods psg', 'psg.seckill_id = ps.id', 'inner'],
|
||||
['goods_sku gs', 'psg.sku_id = gs.sku_id', 'inner'],
|
||||
];
|
||||
$condition = [
|
||||
['ps.seckill_time_id', 'like', '%,' . $seckill_time_id . ',%'],
|
||||
['ps.status', '=', 1],
|
||||
['g.goods_state', '=', 1],
|
||||
['g.is_delete', '=', 0],
|
||||
['ps.site_id', '=', $site_id]
|
||||
];
|
||||
//展示库存要和实际库存做比较,取二者的较小值
|
||||
$sum_field = 'sum(IF(psg.stock < gs.stock, psg.stock, gs.stock))';
|
||||
$goods_stock_field = 'IF(ps.goods_stock < '.$sum_field.', ps.goods_stock, '.$sum_field.') as goods_stock';
|
||||
$field = 'ps.id,ps.site_id,ps.seckill_name,ps.status,ps.remark,ps.start_time,ps.end_time,'.$goods_stock_field.',
|
||||
ps.goods_id,ps.seckill_time_id,ps.seckill_price,ps.sale_num,ps.goods_stock,
|
||||
g.goods_name,g.goods_image,g.price';
|
||||
$order = 'ps.sort asc';
|
||||
$group = 'ps.id';
|
||||
$list = model('promotion_seckill')->getList($condition, $field, $order, $alias, $join, $group, $limit);
|
||||
foreach ($list as $k => $v) {
|
||||
$list[ $k ][ 'goods_stock' ] = numberFormat($list[ $k ][ 'goods_stock' ]);
|
||||
}
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动秒杀事件
|
||||
* @param $seckill_id
|
||||
* @return array
|
||||
*/
|
||||
public function cronOpenSeckill($seckill_id)
|
||||
{
|
||||
$seckill_info = model('promotion_seckill')->getInfo([['id', '=', $seckill_id]], 'start_time,status, goods_id');
|
||||
if (!empty($seckill_info)) {
|
||||
if ($seckill_info[ 'start_time' ] <= time() && $seckill_info[ 'status' ] == 0) {
|
||||
model('promotion_seckill')->update(['status' => 1], [['id', '=', $seckill_id]]);
|
||||
model('promotion_seckill_goods')->update(['status' => 1], [['seckill_id', '=', $seckill_id]]);
|
||||
$goods = new Goods();
|
||||
$goods->modifyPromotionAddon($seckill_info[ 'goods_id' ], ['seckill' => $seckill_id]);
|
||||
return $this->success(1);
|
||||
} else {
|
||||
return $this->error("", "秒杀已开启或者关闭");
|
||||
}
|
||||
} else {
|
||||
return $this->error("", "秒杀不存在");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束秒杀事件
|
||||
* @param $seckill_id
|
||||
* @return array
|
||||
*/
|
||||
public function cronCloseSeckill($seckill_id)
|
||||
{
|
||||
$seckill_info = model('promotion_seckill')->getInfo([['id', '=', $seckill_id]], 'start_time,status, goods_id');
|
||||
if (!empty($seckill_info)) {
|
||||
//针对正在进行的活动
|
||||
if ($seckill_info[ 'status' ] == 1) {
|
||||
|
||||
model('promotion_seckill')->update(['status' => 2], [['id', '=', $seckill_id]]);
|
||||
model('promotion_seckill_goods')->update(['status' => 2], [['seckill_id', '=', $seckill_id]]);
|
||||
|
||||
$goods = new Goods();
|
||||
$goods->modifyPromotionAddon($seckill_info[ 'goods_id' ], ['seckill' => $seckill_id], true);
|
||||
|
||||
return $this->success();
|
||||
} else {
|
||||
return $this->error("", "正在进行的秒杀才能进行关闭操作");
|
||||
}
|
||||
} else {
|
||||
return $this->error("", "活动不存在");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动结束秒杀事件
|
||||
* @param $seckill_id
|
||||
* @return array
|
||||
*/
|
||||
public function closeSeckill($seckill_id)
|
||||
{
|
||||
$seckill_info = model('promotion_seckill')->getInfo([['id', '=', $seckill_id]], 'start_time,status, goods_id');
|
||||
if (!empty($seckill_info)) {
|
||||
//针对正在进行的活动
|
||||
if ($seckill_info[ 'status' ] == 1) {
|
||||
|
||||
model('promotion_seckill')->update(['status' => -1], [['id', '=', $seckill_id]]);
|
||||
model('promotion_seckill_goods')->update(['status' => -1], [['seckill_id', '=', $seckill_id]]);
|
||||
|
||||
$goods = new Goods();
|
||||
$goods->modifyPromotionAddon($seckill_info[ 'goods_id' ], ['seckill' => $seckill_id], true);
|
||||
|
||||
return $this->success();
|
||||
} else {
|
||||
return $this->error("", "正在进行的秒杀才能进行关闭操作");
|
||||
}
|
||||
} else {
|
||||
return $this->error("", "活动不存在");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品列表
|
||||
* @param $seckill_id
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillGoodsList($seckill_id)
|
||||
{
|
||||
$field = 'psg.*,sku.sku_name,sku.price,sku.sku_image';
|
||||
$alias = 'psg';
|
||||
$join = [
|
||||
[
|
||||
'goods g',
|
||||
'g.goods_id = psg.goods_id',
|
||||
'inner'
|
||||
],
|
||||
[
|
||||
'goods_sku sku',
|
||||
'sku.sku_id = psg.sku_id',
|
||||
'inner'
|
||||
]
|
||||
];
|
||||
$condition = [
|
||||
['psg.seckill_id', '=', $seckill_id],
|
||||
['g.is_delete', '=', 0], ['g.goods_state', '=', 1]
|
||||
];
|
||||
$list = model('promotion_seckill_goods')->getList($condition, $field, '', $alias, $join);
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒杀商品信息
|
||||
* @param array $condition
|
||||
* @param string $field
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillGoodsInfo($condition = [], $field = '')
|
||||
{
|
||||
if (empty($field)) {
|
||||
//展示库存要和实际库存做比较,取二者的较小值
|
||||
$stock_field = 'IF(psg.stock < sku.stock, psg.stock, sku.stock) as stock';
|
||||
$field = 'psg.id,psg.seckill_id,ps.goods_id,psg.sku_id,psg.seckill_price,psg.max_buy,'.$stock_field.',
|
||||
ps.status,ps.start_time,ps.end_time,(ps.sale_num + g.virtual_sale) as sale_num,ps.remark,
|
||||
sku.site_id,sku.sku_name,sku.sku_spec_format,sku.price,sku.promotion_type,
|
||||
sku.click_num,sku.collect_num,sku.sku_image,sku.sku_images,
|
||||
sku.goods_content,sku.goods_state,sku.is_virtual,sku.is_free_shipping,
|
||||
sku.goods_spec_format,sku.goods_attr_format,sku.introduction,sku.unit,
|
||||
sku.video_url,g.evaluate,sku.goods_service_ids,sku.support_trade_type,g.goods_image,
|
||||
ps.goods_stock,g.goods_name,sku.qr_id,g.stock_show,g.sale_show,g.label_name,g.category_id,g.sale_store';
|
||||
}
|
||||
$join = [
|
||||
['goods_sku sku', 'psg.sku_id = sku.sku_id', 'inner'],
|
||||
['goods g', 'g.goods_id = sku.goods_id', 'inner'],
|
||||
['promotion_seckill ps', 'ps.id = psg.seckill_id', 'inner'],
|
||||
];
|
||||
$seckill_goods_info = model('promotion_seckill_goods')->getInfo($condition, $field, 'psg', $join);
|
||||
if (!empty($seckill_goods_info)) {
|
||||
if (isset($seckill_goods_info[ 'sale_num' ])) {
|
||||
$seckill_goods_info[ 'sale_num' ] = numberFormat($seckill_goods_info[ 'sale_num' ]);
|
||||
}
|
||||
if (isset($seckill_goods_info[ 'goods_stock' ])) {
|
||||
$seckill_goods_info[ 'goods_stock' ] = numberFormat($seckill_goods_info[ 'goods_stock' ]);
|
||||
}
|
||||
if (isset($seckill_goods_info[ 'stock' ])) {
|
||||
$seckill_goods_info[ 'stock' ] = numberFormat($seckill_goods_info[ 'stock' ]);
|
||||
}
|
||||
}
|
||||
return $this->success($seckill_goods_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒杀商品信息
|
||||
* @param array $condition
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillGoodsSkuList($condition = [])
|
||||
{
|
||||
//展示库存要和实际库存做比较,取二者的较小值
|
||||
$stock_field = 'IF(psg.stock < sku.stock, psg.stock, sku.stock) as stock';
|
||||
$field = 'psg.id,psg.seckill_id,ps.goods_id,psg.sku_id,psg.seckill_price,psg.max_buy,'.$stock_field.',
|
||||
ps.status,ps.start_time,ps.end_time,ps.sale_num,sku.sku_name,sku.sku_spec_format,sku.price,sku.sku_image,sku.sku_images,sku.goods_spec_format,g.goods_image,ps.goods_stock';
|
||||
$join = [
|
||||
['goods_sku sku', 'psg.sku_id = sku.sku_id', 'inner'],
|
||||
['goods g', 'g.goods_id = sku.goods_id', 'inner'],
|
||||
['promotion_seckill ps', 'ps.id = psg.seckill_id', 'inner'],
|
||||
];
|
||||
$list = model('promotion_seckill_goods')->getList($condition, $field, 'psg.id asc', 'psg', $join);
|
||||
foreach ($list as $k => $v) {
|
||||
$list[ $k ][ 'goods_stock' ] = numberFormat($list[ $k ][ 'goods_stock' ]);
|
||||
$list[ $k ][ 'stock' ] = numberFormat($list[ $k ][ 'stock' ]);
|
||||
}
|
||||
return $this->success($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断规格值是否禁用
|
||||
* @param $seckill_id
|
||||
* @param $site_id
|
||||
* @param string $goods_spec_format
|
||||
* @return int|mixed
|
||||
*/
|
||||
public function getGoodsSpecFormat($seckill_id, $site_id, $goods_spec_format = '')
|
||||
{
|
||||
//获取活动参与的商品sku_ids
|
||||
$sku_ids = model('promotion_seckill_goods')->getColumn([['seckill_id', '=', $seckill_id], ['site_id', '=', $site_id]], 'sku_id');
|
||||
$goods_model = new Goods();
|
||||
$res = $goods_model->getGoodsSpecFormat($sku_ids, $goods_spec_format);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成砍价二维码
|
||||
* @param $seckill_id
|
||||
* @param string $name
|
||||
* @param string $type 类型 create创建 get获取
|
||||
* @return mixed|array
|
||||
*/
|
||||
public function qrcode($seckill_id, $name, $site_id, $type = 'create')
|
||||
{
|
||||
$data = [
|
||||
'site_id' => $site_id,
|
||||
'app_type' => "all", // all为全部
|
||||
'type' => $type, // 类型 create创建 get获取
|
||||
'data' => [
|
||||
"seckill_id" => $seckill_id
|
||||
],
|
||||
'page' => '/pages_promotion/seckill/detail',
|
||||
'qrcode_path' => 'upload/qrcode/seckill',
|
||||
'qrcode_name' => "seckill_qrcode_" . $seckill_id
|
||||
];
|
||||
|
||||
event('Qrcode', $data, true);
|
||||
$app_type_list = config('app_type');
|
||||
$path = [];
|
||||
foreach ($app_type_list as $k => $v) {
|
||||
switch ($k) {
|
||||
case 'h5':
|
||||
$wap_domain = getH5Domain();
|
||||
$path[ $k ][ 'status' ] = 1;
|
||||
$path[ $k ][ 'url' ] = $wap_domain . $data[ 'page' ] . '?id=' . $seckill_id;
|
||||
$path[ $k ][ 'img' ] = "upload/qrcode/seckill/seckill_qrcode_" . $seckill_id . "_" . $k . ".png";
|
||||
break;
|
||||
case 'weapp' :
|
||||
$config = new ConfigModel();
|
||||
$res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', 'shop'], ['config_key', '=', 'WEAPP_CONFIG']]);
|
||||
if (!empty($res[ 'data' ])) {
|
||||
if (empty($res[ 'data' ][ 'value' ][ 'qrcode' ])) {
|
||||
$path[ $k ][ 'status' ] = 2;
|
||||
$path[ $k ][ 'message' ] = '未配置微信小程序';
|
||||
} else {
|
||||
$path[ $k ][ 'status' ] = 1;
|
||||
$path[ $k ][ 'img' ] = $res[ 'data' ][ 'value' ][ 'qrcode' ];
|
||||
}
|
||||
|
||||
} else {
|
||||
$path[ $k ][ 'status' ] = 2;
|
||||
$path[ $k ][ 'message' ] = '未配置微信小程序';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'wechat' :
|
||||
$config = new ConfigModel();
|
||||
$res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', 'shop'], ['config_key', '=', 'WECHAT_CONFIG']]);
|
||||
if (!empty($res[ 'data' ])) {
|
||||
if (empty($res[ 'data' ][ 'value' ][ 'qrcode' ])) {
|
||||
$path[ $k ][ 'status' ] = 2;
|
||||
$path[ $k ][ 'message' ] = '未配置微信公众号';
|
||||
} else {
|
||||
$path[ $k ][ 'status' ] = 1;
|
||||
$path[ $k ][ 'img' ] = $res[ 'data' ][ 'value' ][ 'qrcode' ];
|
||||
}
|
||||
} else {
|
||||
$path[ $k ][ 'status' ] = 2;
|
||||
$path[ $k ][ 'message' ] = '未配置微信公众号';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$return = [
|
||||
'path' => $path,
|
||||
'name' => $name,
|
||||
];
|
||||
|
||||
return $this->success($return);
|
||||
}
|
||||
|
||||
public function urlQrcode($page, $qrcode_param, $promotion_type, $app_type, $site_id)
|
||||
{
|
||||
$params = [
|
||||
'site_id' => $site_id,
|
||||
'data' => $qrcode_param,
|
||||
'page' => $page,
|
||||
'promotion_type' => $promotion_type,
|
||||
'app_type' => $app_type,
|
||||
'h5_path' => $page . '?id=' . $qrcode_param[ 'id' ],
|
||||
'qrcode_path' => 'upload/qrcode/seckill',
|
||||
'qrcode_name' => 'seckill_qrcode_' . $promotion_type . '_' . $qrcode_param[ 'id' ] . '_' . $site_id,
|
||||
];
|
||||
$solitaire = event('PromotionQrcode', $params, true);
|
||||
return $this->success($solitaire);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员已购该商品数
|
||||
* @param $goods_id
|
||||
* @param $member_id
|
||||
* @return float
|
||||
*/
|
||||
public function getGoodsPurchasedNum($sku_id, $member_id)
|
||||
{
|
||||
$join = [
|
||||
['order o', 'o.order_id = og.order_id', 'left']
|
||||
];
|
||||
return model('order_goods')->getSum([
|
||||
['og.member_id', '=', $member_id],
|
||||
['og.sku_id', '=', $sku_id],
|
||||
['o.order_status', '<>', Order::ORDER_CLOSE],
|
||||
['o.promotion_type', '=', 'seckill'],
|
||||
['og.refund_status', '<>', OrderRefundDict::REFUND_COMPLETE]
|
||||
], 'og.num', 'og', $join);
|
||||
}
|
||||
|
||||
}
|
||||
74
addon/seckill/model/SeckillOrder.php
Executable file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\model;
|
||||
|
||||
use app\dict\order_refund\OrderRefundDict;
|
||||
use app\model\BaseModel;
|
||||
use app\model\order\Order;
|
||||
use app\model\order\OrderCreate;
|
||||
use app\model\order\OrderCreateTool;
|
||||
use app\model\order\OrderRefund;
|
||||
use app\model\system\Pay;
|
||||
use extend\exception\OrderException;
|
||||
use think\facade\Cache;
|
||||
|
||||
/**
|
||||
* 订单创建(秒杀)
|
||||
*
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
class SeckillOrder extends BaseModel
|
||||
{
|
||||
|
||||
/**
|
||||
* 订单关闭
|
||||
* @param $order_id
|
||||
*/
|
||||
public function orderClose($order_id)
|
||||
{
|
||||
$order_info = model('order')->getInfo([['order_id', '=', $order_id], ['promotion_type', '=', 'seckill'], ['order_status', '=', -1]], 'promotion_id');
|
||||
if (!empty($order_info)) {
|
||||
$condition = [
|
||||
['order_id', '=', $order_id]
|
||||
];
|
||||
$order_goods_list = model('order_goods')->getList($condition, 'order_goods_id,sku_id,num,refund_status,use_point');
|
||||
foreach ($order_goods_list as $k => $v) {
|
||||
// 返还库存
|
||||
model('promotion_seckill')->setInc([['id', '=', $order_info['promotion_id']]], 'goods_stock', $v['num']);
|
||||
model('promotion_seckill_goods')->setInc([['sku_id', '=', $v['sku_id']], ['seckill_id', '=', $order_info['promotion_id']]], 'stock', $v['num']);
|
||||
// 减少销量
|
||||
model('promotion_seckill')->setDec([['id', '=', $order_info['promotion_id']]], 'sale_num', $v['num']);
|
||||
}
|
||||
}
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取商品已秒杀数
|
||||
* @param $goods_id
|
||||
* @param $member_id
|
||||
* @return float
|
||||
*/
|
||||
public function getGoodsSeckillNum($seckill_id)
|
||||
{
|
||||
$join = [
|
||||
['order o', 'o.order_id = og.order_id', 'left']
|
||||
];
|
||||
return model('order_goods')->getSum([
|
||||
['o.order_status', '<>', Order::ORDER_CLOSE],
|
||||
['o.promotion_type', '=', 'seckill'],
|
||||
['o.promotion_id', '=', $seckill_id],
|
||||
['og.refund_status', '<>', OrderRefundDict::REFUND_COMPLETE],
|
||||
], 'og.num', 'og', $join);
|
||||
}
|
||||
}
|
||||
311
addon/seckill/model/SeckillOrderCreate.php
Executable file
@@ -0,0 +1,311 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\model;
|
||||
|
||||
use addon\store\model\StoreGoodsSku;
|
||||
use app\dict\order_refund\OrderRefundDict;
|
||||
use app\model\BaseModel;
|
||||
use app\model\order\Order;
|
||||
use app\model\order\OrderCreate;
|
||||
use app\model\order\OrderCreateTool;
|
||||
use app\model\order\OrderRefund;
|
||||
use app\model\store\Store;
|
||||
use extend\exception\OrderException;
|
||||
use think\facade\Cache;
|
||||
use app\model\express\Express;
|
||||
use app\model\system\Pay;
|
||||
use app\model\express\Config as ExpressConfig;
|
||||
use app\model\order\Config;
|
||||
use app\model\express\Local;
|
||||
|
||||
/**
|
||||
* 订单创建(秒杀)
|
||||
*
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
class SeckillOrderCreate extends BaseModel
|
||||
{
|
||||
|
||||
use OrderCreateTool;
|
||||
|
||||
public $seckill_id = 0;
|
||||
public $seckill_info = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->promotion_type = 'seckill';
|
||||
$this->promotion_type_name = '秒杀';
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单创建
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//计算
|
||||
$this->confirm();
|
||||
if ($this->error > 0) {
|
||||
return $this->error([ 'error_code' => $this->error ], $this->error_msg);
|
||||
}
|
||||
//订单创建数据
|
||||
$order_insert_data = $this->getOrderInsertData([ 'discount' ], 'invert');
|
||||
$order_insert_data[ 'store_id' ] = $this->store_id;
|
||||
$order_insert_data[ 'create_time' ] = time();
|
||||
$order_insert_data[ 'is_enable_refund' ] = 0;
|
||||
//订单类型以及状态
|
||||
$this->orderType();
|
||||
$order_insert_data[ 'promotion_id' ] = $this->seckill_info['id'];
|
||||
$order_insert_data[ 'order_type' ] = $this->order_type[ 'order_type_id' ];
|
||||
$order_insert_data[ 'order_type_name' ] = $this->order_type[ 'order_type_name' ];
|
||||
$order_insert_data[ 'order_status_name' ] = $this->order_type[ 'order_status' ][ 'name' ];
|
||||
$order_insert_data[ 'order_status_action' ] = json_encode($this->order_type[ 'order_status' ], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
model('order')->startTrans();
|
||||
//循环生成多个订单
|
||||
try {
|
||||
$this->order_id = model('order')->add($order_insert_data);
|
||||
$order_goods_insert_data = [];
|
||||
//订单项目表
|
||||
foreach ($this->goods_list as &$order_goods_v) {
|
||||
$order_goods_insert_data[] = $this->getOrderGoodsInsertData($order_goods_v);
|
||||
|
||||
model("promotion_seckill_goods")->setDec([ [ 'sku_id', '=', $order_goods_v[ 'sku_id' ] ], [ 'seckill_id', '=', $this->seckill_info[ "id" ] ] ], "stock", $order_goods_v[ 'num' ]);
|
||||
model("promotion_seckill")->setDec([ [ 'id', '=', $this->seckill_info[ "id" ] ] ], "goods_stock", $order_goods_v[ 'num' ]);
|
||||
// 增加销量 秒杀要用sale_num计算秒杀量,和普通订单付款后才算销量不一样
|
||||
model("promotion_seckill")->setInc([ [ 'id', '=', $this->seckill_info[ "id" ] ] ], "sale_num", $order_goods_v[ 'num' ]);
|
||||
}
|
||||
model('order_goods')->addList($order_goods_insert_data);
|
||||
|
||||
//扣除余额(统一扣除)
|
||||
$this->useBalance();
|
||||
//批量库存处理(卡密商品支付后在扣出库存)
|
||||
$this->batchDecOrderGoodsStock();
|
||||
model('order')->commit();
|
||||
//订单创建后事件
|
||||
$this->orderCreateAfter();
|
||||
//支付单据
|
||||
$pay = new Pay();
|
||||
$pay->addPay($this->site_id, $this->out_trade_no, $this->pay_type, $this->order_name, $this->order_name, $this->pay_money, '', 'OrderPayNotify', '', $this->order_id, $this->member_id);
|
||||
return $this->success($this->out_trade_no);
|
||||
} catch (\Exception $e) {
|
||||
model('order')->rollback();
|
||||
return $this->error('', $e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算后的进一步计算(不存缓存,每次都是重新计算)
|
||||
* @return array
|
||||
*/
|
||||
public function confirm()
|
||||
{
|
||||
$order_key = $this->param[ 'order_key' ];
|
||||
$this->getOrderCache($order_key);
|
||||
//初始化地址
|
||||
$this->initMemberAddress();
|
||||
//初始化门店信息
|
||||
$this->initStore();
|
||||
//配送计算
|
||||
$this->calculateDelivery();
|
||||
//批量校验配送方式
|
||||
$this->batchCheckDeliveryType();
|
||||
//计算发票相关
|
||||
$this->calculateInvoice();
|
||||
//计算余额
|
||||
$this->calculateBalcnce();
|
||||
$this->pay_money = $this->order_money - $this->balance_money;
|
||||
//设置过的商品项信息
|
||||
return get_object_vars($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单计算
|
||||
*/
|
||||
public function calculate()
|
||||
{
|
||||
//初始化会员地址
|
||||
$this->initMemberAddress();
|
||||
$this->initMemberAccount();//初始化会员账户
|
||||
//商品列表信息
|
||||
$this->getOrderGoodsCalculate();
|
||||
//查询秒杀信息
|
||||
$seckill_model = new Seckill();
|
||||
$seckill_info = $seckill_model->getSeckillInfo($this->seckill_id)[ 'data' ] ?? [];
|
||||
if (empty($seckill_info)) throw new OrderException("找不到可用的秒杀活动");
|
||||
$this->seckill_info = $seckill_info;
|
||||
//判断秒杀时间段是否符合
|
||||
$today_time = strtotime(date("Y-m-d"), time());
|
||||
$time = time() - $today_time;//当日时间戳
|
||||
if ($time < $this->seckill_info[ "seckill_start_time" ] || $time > $this->seckill_info[ "seckill_end_time" ]) {
|
||||
$this->error = 1;
|
||||
$this->error_msg = "当前商品秒杀活动未开启或已过期!";
|
||||
}
|
||||
|
||||
//秒杀库存
|
||||
if ($this->goods_list[ 0 ]) {
|
||||
$seckill_goods = $seckill_model->getSeckillGoodsInfo([ [ 'psg.seckill_id', '=', $this->seckill_id ], [ 'psg.sku_id', '=', $this->goods_list[ 0 ][ 'sku_id' ] ] ], 'psg.stock')[ 'data' ] ?? [];
|
||||
$seckill_goods_stock = $seckill_goods[ 'stock' ];
|
||||
if ($this->goods_list[ 0 ][ 'num' ] > $seckill_goods_stock) {
|
||||
$this->error = 1;
|
||||
$this->error_msg = "该商品库存不足";
|
||||
}
|
||||
}
|
||||
|
||||
// 秒杀商品限购 按每日某时段限购
|
||||
if ($this->goods_list[ 0 ][ 'limit_num' ] > 0) {
|
||||
$purchased_num = $this->getGoodsPurchasedNum($this->goods_list[ 0 ][ 'sku_id' ], $this->member_id, $this->seckill_info[ 'id' ]);
|
||||
if (($purchased_num + $this->goods_list[ 0 ][ 'num' ]) > $this->goods_list[ 0 ][ 'limit_num' ]) {
|
||||
$this->error = 1;
|
||||
$this->error_msg = "该商品每人限购{$this->goods_list[ 0 ]['limit_num']}件,您已购买{$purchased_num}件";
|
||||
}
|
||||
}
|
||||
$this->shopOrderCalculate();
|
||||
//获取发票相关
|
||||
$this->getInovice();
|
||||
$this->order_key = create_no();
|
||||
$this->setOrderCache(get_object_vars($this), $this->order_key);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 待付款订单
|
||||
* @param unknown $data
|
||||
*/
|
||||
public function orderPayment()
|
||||
{
|
||||
//计算
|
||||
$this->calculate();
|
||||
//查询配送信息
|
||||
$this->getDeliveryData();
|
||||
//订单初始项
|
||||
event('OrderPayment', [ 'order_object' => $this ]);
|
||||
return get_object_vars($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品的计算信息
|
||||
* @param unknown $data
|
||||
*/
|
||||
public function getOrderGoodsCalculate()
|
||||
{
|
||||
$this->getSeckillGoodsInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒杀商品列表信息
|
||||
* @param $id
|
||||
* @param $num
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public function getSeckillGoodsInfo()
|
||||
{
|
||||
$id = $this->param[ 'id' ];
|
||||
$sku_id = $this->param[ 'sku_id' ];
|
||||
$num = $this->param[ 'num' ];
|
||||
//组装商品列表
|
||||
$field = 'npsg.sku_id,npsg.seckill_id,npsg.seckill_price,npsg.max_buy as limit_num,ngs.sku_name, ngs.sku_no,
|
||||
ngs.price, ngs.discount_price, ngs.cost_price, ngs.stock, ngs.weight, ngs.volume, ngs.sku_image,
|
||||
ngs.site_id, ns.site_name, ngs.goods_state, ngs.is_virtual,ngs.supplier_id,ngs.form_id,
|
||||
ngs.is_free_shipping, ngs.shipping_template, ngs.goods_class, ngs.goods_class_name,ngs.goods_id,ngs.sku_spec_format,ngs.goods_name,ngs.support_trade_type';
|
||||
$alias = 'npsg';
|
||||
$join = [
|
||||
[
|
||||
'goods_sku ngs',
|
||||
'npsg.sku_id = ngs.sku_id',
|
||||
'inner'
|
||||
],
|
||||
[
|
||||
'site ns',
|
||||
'ngs.site_id = ns.site_id',
|
||||
'inner'
|
||||
]
|
||||
];
|
||||
|
||||
$condition = [
|
||||
[ 'npsg.sku_id', '=', $sku_id ],
|
||||
[ 'npsg.seckill_id', '=', $id ],
|
||||
[ 'npsg.site_id', '=', $this->site_id ]
|
||||
];
|
||||
$info = model("promotion_seckill_goods")->getInfo($condition, $field, $alias, $join);
|
||||
if (empty($info)) throw new OrderException('无效的商品!');
|
||||
//判断是否是虚拟订单
|
||||
$this->seckill_id = $info[ 'seckill_id' ];
|
||||
if ($info[ 'is_virtual' ]) {
|
||||
$this->is_virtual = 1;
|
||||
} else {
|
||||
$this->is_virtual = 0;
|
||||
}
|
||||
$info[ "num" ] = $num;
|
||||
$price = $info[ "seckill_price" ];//订单项商品单价
|
||||
$goods_money = $price * $info[ 'num' ];
|
||||
$info[ "price" ] = $price;
|
||||
$info[ 'goods_money' ] = $goods_money;//订单项商品总价
|
||||
$info[ 'real_goods_money' ] = $goods_money;//真实商品金额
|
||||
$info[ 'coupon_money' ] = 0;//优惠券金额
|
||||
$info[ 'promotion_money' ] = 0;//优惠金额
|
||||
|
||||
$this->site_name = $info[ 'site_name' ];
|
||||
$this->goods_money = $goods_money;
|
||||
$this->goods_list_str = $info[ 'sku_id' ] . ':' . $info[ 'num' ];
|
||||
$this->order_name = string_split("", ",", $info[ 'sku_name' ]);
|
||||
$this->goods_num = $info[ 'num' ];
|
||||
$this->goods_list[] = $info;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取店铺订单计算
|
||||
*/
|
||||
public function shopOrderCalculate()
|
||||
{
|
||||
//重新计算订单总额
|
||||
$this->getOrderMoney();
|
||||
//理论上是多余的操作
|
||||
if ($this->order_money < 0) {
|
||||
$this->order_money = 0;
|
||||
}
|
||||
//总结计算
|
||||
$this->pay_money = $this->order_money;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取会员该秒杀时段已购该商品数
|
||||
* @param $goods_id
|
||||
* @param $member_id
|
||||
* @return float
|
||||
*/
|
||||
public function getGoodsPurchasedNum($sku_id, $member_id, $seckill_id)
|
||||
{
|
||||
$join = [
|
||||
[ 'order o', 'o.order_id = og.order_id', 'left' ]
|
||||
];
|
||||
$num = model('order_goods')->getSum([
|
||||
[ 'og.member_id', '=', $member_id ],
|
||||
[ 'og.sku_id', '=', $sku_id ],
|
||||
[ 'o.order_status', '<>', Order::ORDER_CLOSE ],
|
||||
[ 'o.promotion_type', '=', 'seckill' ],
|
||||
[ 'o.promotion_id', '=', $seckill_id ],
|
||||
[ 'og.refund_status', '<>', OrderRefundDict::REFUND_COMPLETE ],
|
||||
[ 'o.create_time', 'between', [ date_to_time(date('Y-m-d 00:00:00')), time() ] ]
|
||||
], 'og.num', 'og', $join);
|
||||
return $num;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
141
addon/seckill/model/share/WchatShare.php
Executable file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\model\share;
|
||||
|
||||
use addon\seckill\model\Seckill;
|
||||
use app\model\share\WchatShareBase as BaseModel;
|
||||
use app\model\system\Config as ConfigModel;
|
||||
|
||||
/**
|
||||
* 分享
|
||||
*/
|
||||
class WchatShare extends BaseModel
|
||||
{
|
||||
protected $config = [
|
||||
[
|
||||
'title' => '秒杀分享',
|
||||
'config_key' => 'WCHAT_SHARE_CONFIG_SECKILL_PROMOTE',
|
||||
'path' => [ '/pages_promotion/seckill/detail' ],
|
||||
'method_prefix' => 'goodsDetail',
|
||||
],
|
||||
[
|
||||
'title' => '秒杀列表',
|
||||
'config_key' => 'WCHAT_SHARE_CONFIG_SECKILL_LIST_PROMOTE',
|
||||
'path' => [ '/pages_promotion/seckill/list' ],
|
||||
'method_prefix' => 'goodsList',
|
||||
],
|
||||
];
|
||||
|
||||
protected $sort = 8;
|
||||
|
||||
/**
|
||||
* 秒杀列表
|
||||
* @param $param
|
||||
* @return array
|
||||
*/
|
||||
protected function goodsListShareData($param)
|
||||
{
|
||||
//跳转路径
|
||||
$link = $this->getShareLink($param);
|
||||
$config_data = $this->goodsListShareConfig($param)[ 'value' ];
|
||||
|
||||
$data = [
|
||||
'link' => $link,
|
||||
'desc' => $config_data[ 'desc' ],
|
||||
'imgUrl' => $config_data[ 'imgUrl' ],
|
||||
'title' => $config_data[ 'title' ]
|
||||
];
|
||||
return [
|
||||
'permission' => [
|
||||
'hideOptionMenu' => false,
|
||||
'hideMenuItems' => [],
|
||||
],
|
||||
'data' => $data,//分享内容
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀列表分享配置
|
||||
* @param $param
|
||||
* @return array
|
||||
*/
|
||||
public function goodsListShareConfig($param)
|
||||
{
|
||||
$site_id = $param[ 'site_id' ];
|
||||
$config = $param[ 'config' ];
|
||||
|
||||
$config_model = new ConfigModel();
|
||||
$data = $config_model->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', $config[ 'config_key' ] ] ])[ 'data' ];
|
||||
if (empty($data[ 'value' ])) {
|
||||
$data[ 'value' ] = [
|
||||
'title' => "秒杀列表",
|
||||
'desc' => "秒杀进行时\n快来参与吧",
|
||||
'imgUrl' => ''
|
||||
];
|
||||
}
|
||||
if (empty($data[ 'value' ][ 'imgUrl' ])) {
|
||||
$data[ 'value' ][ 'imgUrl' ] = img('addon/seckill/icon.png');
|
||||
}
|
||||
return [
|
||||
'value' => $data[ 'value' ],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀分享数据
|
||||
* @param $param
|
||||
* @return array
|
||||
*/
|
||||
protected function goodsDetailShareData($param)
|
||||
{
|
||||
$url = $param[ 'url' ];
|
||||
|
||||
$parse_res = parse_url($url);
|
||||
parse_str($parse_res[ 'query' ] ?? '', $query);
|
||||
|
||||
if (isset($query[ 'seckill_id' ]) || $query[ 'id' ]) {
|
||||
$seckill_id = $query['seckill_id'] ?? $query['id'];
|
||||
$goods = new Seckill();
|
||||
$condition = [
|
||||
[ 'ps.id', '=', $seckill_id ],
|
||||
[ 'psg.site_id', '=', 1 ],
|
||||
[ 'psg.status', '=', 1 ],
|
||||
[ 'ps.status', '=', 1 ],
|
||||
[ 'g.is_delete', '=', 0 ]
|
||||
];
|
||||
$sku_info = $goods->getSeckillGoodsInfo($condition)[ 'data' ];
|
||||
if (!empty($sku_info)) {
|
||||
$config_model = new \app\model\share\WchatShare();
|
||||
$config_data = $config_model->goodsDetailShareConfig($param);
|
||||
|
||||
$title = str_replace('{goods_name}', $sku_info[ 'sku_name' ], $config_data[ 'value' ][ 'title' ]);
|
||||
$desc = str_replace('{price}', $sku_info[ 'seckill_price' ], $config_data[ 'value' ][ 'desc' ]);
|
||||
$link = $this->getShareLink($param);
|
||||
$image_url = $sku_info[ 'sku_image' ];
|
||||
|
||||
$data = [
|
||||
'title' => $title,
|
||||
'desc' => $desc,
|
||||
'link' => $link,
|
||||
'imgUrl' => $image_url,
|
||||
];
|
||||
return [
|
||||
'permission' => [
|
||||
'hideOptionMenu' => false,
|
||||
'hideMenuItems' => [],
|
||||
],
|
||||
'data' => $data,//分享内容
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
90
addon/seckill/model/share/WeappShare.php
Executable file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\model\share;
|
||||
|
||||
use app\model\share\WeappShareBase;
|
||||
use app\model\system\Config as ConfigModel;
|
||||
|
||||
/**
|
||||
* 分享
|
||||
*/
|
||||
class WeappShare extends WeappShareBase
|
||||
{
|
||||
protected $config = [
|
||||
[
|
||||
'title' => '秒杀列表',
|
||||
'config_key' => 'WEAPP_SHARE_CONFIG_SECKILL_LIST',
|
||||
'path' => ['/pages_promotion/seckill/list'],
|
||||
'method_prefix' => 'seckillList',
|
||||
],
|
||||
];
|
||||
|
||||
protected $sort = 9;
|
||||
|
||||
/**
|
||||
* 秒杀列表
|
||||
* @param $param
|
||||
* @return array
|
||||
*/
|
||||
protected function seckillListShareData($param)
|
||||
{
|
||||
//获取和替换配置数据
|
||||
$config_data = $this->seckillListShareConfig($param);
|
||||
$title = $config_data['value']['title'];
|
||||
$image_url = $config_data['value']['imageUrl'] ? img($config_data['value']['imageUrl']) : '';
|
||||
$path = $this->getSharePath($param);
|
||||
|
||||
$data = [
|
||||
'title' => $title,
|
||||
'path' => $path,
|
||||
'imageUrl' => $image_url,
|
||||
];
|
||||
return [
|
||||
'permission' => [
|
||||
'onShareAppMessage' => true,
|
||||
'onShareTimeline' => true,
|
||||
],
|
||||
'data' => $data,//分享内容
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀列表
|
||||
* @param $param
|
||||
* @return array
|
||||
*/
|
||||
protected function seckillListShareConfig($param)
|
||||
{
|
||||
$site_id = $param['site_id'];
|
||||
$config = $param['config'];
|
||||
|
||||
$config_model = new ConfigModel();
|
||||
$data = $config_model->getConfig([
|
||||
['site_id', '=', $site_id],
|
||||
['app_module', '=', 'shop'],
|
||||
['config_key', '=', $config['config_key']],
|
||||
])['data'];
|
||||
if (empty($data['value'])) {
|
||||
$data['value'] = [
|
||||
'title' => '参与秒杀,优惠多多!',
|
||||
'imageUrl' => '',
|
||||
];
|
||||
}
|
||||
$variable = [];
|
||||
|
||||
return [
|
||||
'value' => $data['value'],
|
||||
'variable' => $variable,
|
||||
];
|
||||
}
|
||||
}
|
||||
394
addon/seckill/shop/controller/Seckill.php
Executable file
@@ -0,0 +1,394 @@
|
||||
<?php
|
||||
/**
|
||||
* Niushop商城系统 - 团队十年电商经验汇集巨献!
|
||||
* =========================================================
|
||||
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
|
||||
* ----------------------------------------------
|
||||
* 官方网址: https://www.niushop.com
|
||||
* =========================================================
|
||||
*/
|
||||
|
||||
namespace addon\seckill\shop\controller;
|
||||
|
||||
use app\shop\controller\BaseShop;
|
||||
use addon\seckill\model\Seckill as SeckillModel;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* 秒杀控制器
|
||||
*/
|
||||
class Seckill extends BaseShop
|
||||
{
|
||||
public function __construct(App $app = null)
|
||||
{
|
||||
$this->replace = [
|
||||
'SECKILL_CSS' => __ROOT__ . '/addon/seckill/shop/view/public/css',
|
||||
'SECKILL_JS' => __ROOT__ . '/addon/seckill/shop/view/public/js',
|
||||
'SECKILL_IMG' => __ROOT__ . '/addon/seckill/shop/view/public/img',
|
||||
];
|
||||
parent::__construct($app);
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀时间段列表
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$condition[] = [ 'site_id', '=', $this->site_id ];
|
||||
$order = 'seckill_start_time asc';
|
||||
$field = '*';
|
||||
|
||||
$seckill_model = new SeckillModel();
|
||||
$res = $seckill_model->getSeckillTimeList($condition, $field, $order, null);
|
||||
foreach ($res[ 'data' ] as $key => $val) {
|
||||
$val = $seckill_model->transformSeckillTime($val);
|
||||
$res[ 'data' ][ $key ][ 'seckill_start_time_show' ] = "{$val['start_hour']}:{$val['start_minute']}:{$val['start_second']}";
|
||||
$res[ 'data' ][ $key ][ 'seckill_end_time_show' ] = "{$val['end_hour']}:{$val['end_minute']}:{$val['end_second']}";
|
||||
}
|
||||
return $res;
|
||||
} else {
|
||||
|
||||
return $this->fetch("seckill/lists");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加秒杀时间段
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$start_hour = input('start_hour', 0);
|
||||
$start_minute = input('start_minute', 0);
|
||||
$start_second = input('start_second', 0);
|
||||
|
||||
$end_hour = input('end_hour', 0);
|
||||
$end_minute = input('end_minute', 0);
|
||||
$end_second = input('end_second', 0);
|
||||
|
||||
$data = [
|
||||
'site_id' => $this->site_id,
|
||||
'name' => input('name', ''),
|
||||
'seckill_start_time' => $start_hour * 3600 + $start_minute * 60 + $start_second,
|
||||
'seckill_end_time' => $end_hour * 3600 + $end_minute * 60 + $end_second,
|
||||
'create_time' => time(),
|
||||
];
|
||||
$seckill_model = new SeckillModel();
|
||||
return $seckill_model->addSeckillTime($data);
|
||||
} else {
|
||||
return $this->fetch("seckill/add");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑秒杀时间段
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$seckill_model = new SeckillModel();
|
||||
if (request()->isJson()) {
|
||||
$start_hour = input('start_hour', 0);
|
||||
$start_minute = input('start_minute', 0);
|
||||
$start_second = input('start_second', 0);
|
||||
|
||||
$end_hour = input('end_hour', 0);
|
||||
$end_minute = input('end_minute', 0);
|
||||
$end_second = input('end_second', 0);
|
||||
|
||||
$data = [
|
||||
'name' => input('name', ''),
|
||||
'seckill_start_time' => $start_hour * 3600 + $start_minute * 60 + $start_second,
|
||||
'seckill_end_time' => $end_hour * 3600 + $end_minute * 60 + $end_second,
|
||||
'create_time' => time(),
|
||||
'id' => input('id', 0),
|
||||
];
|
||||
return $seckill_model->editSeckillTime($data, $this->site_id);
|
||||
} else {
|
||||
$id = input('id', 0);
|
||||
$this->assign('id', $id);
|
||||
|
||||
//秒杀详情
|
||||
$time_info = $seckill_model->getSeckillTimeInfo([ [ 'id', '=', $id ] ]);
|
||||
if (!empty($time_info[ 'data' ])) {
|
||||
$time_info[ 'data' ] = $seckill_model->transformSeckillTime($time_info[ 'data' ]);
|
||||
}
|
||||
$this->assign('time_info', $time_info[ 'data' ]);
|
||||
|
||||
return $this->fetch("seckill/edit");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除秒杀时间段
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$seckill_time_id = input('id', 0);
|
||||
$seckill_model = new SeckillModel();
|
||||
return $seckill_model->deleteSeckillTime($seckill_time_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加秒杀商品
|
||||
*/
|
||||
public function addGoods()
|
||||
{
|
||||
$seckill_model = new SeckillModel();
|
||||
if (request()->isJson()) {
|
||||
$data = [
|
||||
'site_id' => $this->site_id,
|
||||
'seckill_name' => input('seckill_name', ''),
|
||||
'remark' => input('remark', ''),
|
||||
'seckill_time_id' => input('seckill_time_id', ''),
|
||||
'start_time' => strtotime(input('start_time', '')),
|
||||
'end_time' => strtotime(input('end_time', '')),
|
||||
'goods_data' => input('goods_data', ''),
|
||||
'goods_ids' => input('goods_ids', ''),
|
||||
'sort' => input('sort', '')
|
||||
];
|
||||
$res = $seckill_model->addSeckillGoods($data);
|
||||
return $res;
|
||||
} else {
|
||||
return $this->fetch("seckill/editgoods");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品(秒杀价格)
|
||||
*/
|
||||
public function updateGoods()
|
||||
{
|
||||
$seckill_model = new SeckillModel();
|
||||
if (request()->isJson()) {
|
||||
$data = [
|
||||
'site_id' => $this->site_id,
|
||||
'id' => input('id', ''),
|
||||
'seckill_name' => input('seckill_name', ''),
|
||||
'remark' => input('remark', ''),
|
||||
'seckill_time_id' => input('seckill_time_id', ''),
|
||||
'start_time' => strtotime(input('start_time', '')),
|
||||
'end_time' => strtotime(input('end_time', '')),
|
||||
'sku_list' => input('sku_list', ''),
|
||||
'goods_ids' => input('goods_ids', ''),
|
||||
'sort' => input('sort', ''),
|
||||
];
|
||||
$res = $seckill_model->editSeckillGoods($data);
|
||||
return $res;
|
||||
} else {
|
||||
$seckill_id = input('id', '');
|
||||
if (empty($seckill_id)) {
|
||||
$this->error('缺少参数id');
|
||||
}
|
||||
$seckill_info = $seckill_model->getSeckillDetail([ [ 'id', '=', $seckill_id ] ])[ 'data' ];
|
||||
|
||||
$seckill_time_id = trim($seckill_info[ 'seckill_time_id' ], ',');
|
||||
$time_list = $seckill_model->getSeckillTimeList([ [ 'id', 'in', $seckill_time_id ] ])[ 'data' ];
|
||||
|
||||
$this->assign('seckill_info', $seckill_info);
|
||||
$this->assign('time_list', $time_list);
|
||||
|
||||
return $this->fetch("seckill/editgoods");
|
||||
}
|
||||
}
|
||||
|
||||
public function seckillSort()
|
||||
{
|
||||
$sort = input('sort', 0);
|
||||
$id = input('id', 0);
|
||||
$seckill_model = new SeckillModel();
|
||||
return $seckill_model->seckillSort($id, $sort);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除商品
|
||||
*/
|
||||
public function deleteGoods()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$seckill_id = input('id', 0);
|
||||
$site_id = $this->site_id;
|
||||
|
||||
$seckill_model = new SeckillModel();
|
||||
return $seckill_model->deleteSeckillGoods($seckill_id, $site_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀商品
|
||||
*/
|
||||
public function goodslist()
|
||||
{
|
||||
$seckill_time_id = input('seckill_time_id', '');
|
||||
if (request()->isJson()) {
|
||||
$page = input('page', 1);
|
||||
$page_size = input('page_size', PAGE_LIST_ROWS);
|
||||
$goods_name = input('goods_name', '');
|
||||
$status = input('status', '');
|
||||
$link_sort = input('order', 'start_time');
|
||||
$sort = input('sort', 'desc');
|
||||
|
||||
$condition = [];
|
||||
$condition[] = [ 'site_id', '=', $this->site_id ];
|
||||
$condition[] = [ 'goods_name', 'like', '%' . $goods_name . '%' ];
|
||||
|
||||
if ($status !== '') $condition[] = [ 'status', '=', $status ];
|
||||
//排序
|
||||
if ($link_sort == 'sort') {
|
||||
$order_by = $link_sort . ' ' . $sort;
|
||||
} else {
|
||||
$order_by = $link_sort . ' ' . $sort . ',sort desc';
|
||||
}
|
||||
|
||||
if (!empty($seckill_time_id)) {
|
||||
$condition[] = [ '', 'exp', \think\facade\Db::raw("FIND_IN_SET({$seckill_time_id},seckill_time_id)") ];
|
||||
}
|
||||
|
||||
$start_time = input('start_time', '');
|
||||
$end_time = input('end_time', '');
|
||||
|
||||
if ($start_time && !$end_time) {
|
||||
$condition[] = [ 'end_time', '>=', date_to_time($start_time) ];
|
||||
} elseif (!$start_time && $end_time) {
|
||||
$condition[] = [ 'start_time', '<=', date_to_time($end_time) ];
|
||||
} elseif ($start_time && $end_time) {
|
||||
$start_timestamp = date_to_time($start_time);
|
||||
$end_timestamp = date_to_time($end_time);
|
||||
$sql = "start_time between {$start_timestamp} and {$end_timestamp}";
|
||||
$sql .= " or end_time between {$start_timestamp} and {$end_timestamp}";
|
||||
$sql .= " or (start_time <= {$start_timestamp} and end_time >= {$end_timestamp})";
|
||||
$condition[] = [ '', 'exp', \think\facade\Db::raw($sql) ];
|
||||
}
|
||||
|
||||
$seckill_model = new SeckillModel();
|
||||
$seckill_list = $seckill_model->getSeckillPageList($condition, $page, $page_size, $order_by);
|
||||
|
||||
$seckill_condition[] = [ 'site_id', '=', $this->site_id ];
|
||||
|
||||
$time_list = $seckill_model->getSeckillTimeList($seckill_condition);
|
||||
foreach ($seckill_list[ 'data' ][ 'list' ] as $k => $v) {
|
||||
$seckill_list[ 'data' ][ 'list' ][ $k ][ 'time_list' ] = [];
|
||||
foreach ($time_list[ 'data' ] as $index => $item) {
|
||||
if (strpos(',' . $v[ 'seckill_time_id' ] . ',', ',' . $item[ 'id' ] . ',') !== false) {
|
||||
$seckill_list[ 'data' ][ 'list' ][ $k ][ 'time_list' ][] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $seckill_list;
|
||||
} else {
|
||||
|
||||
$condition[] = [ 'site_id', '=', $this->site_id ];
|
||||
$order = 'seckill_start_time asc';
|
||||
$field = '*';
|
||||
|
||||
$seckill_model = new SeckillModel();
|
||||
$res = $seckill_model->getSeckillTimeList($condition, $field, $order, null);
|
||||
$this->assign('seckill_time_id', $seckill_time_id);
|
||||
$this->assign('res', $res[ 'data' ]);
|
||||
return $this->fetch("seckill/goodslist");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀时段
|
||||
*/
|
||||
public function seckilltimeselect()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$condition[] = [ 'site_id', '=', $this->site_id ];
|
||||
$order = 'seckill_start_time asc';
|
||||
$field = '*';
|
||||
|
||||
$seckill_model = new SeckillModel();
|
||||
$res = $seckill_model->getSeckillTimeList($condition, $field, $order, null);
|
||||
foreach ($res[ 'data' ] as $key => $val) {
|
||||
$val = $seckill_model->transformSeckillTime($val);
|
||||
$res[ 'data' ][ $key ][ 'seckill_start_time_show' ] = "{$val['start_hour']}:{$val['start_minute']}:{$val['start_second']}";
|
||||
$res[ 'data' ][ $key ][ 'seckill_end_time_show' ] = "{$val['end_hour']}:{$val['end_minute']}:{$val['end_second']}";
|
||||
}
|
||||
return $res;
|
||||
} else {
|
||||
|
||||
return $this->fetch("seckill/seckilltimeselect");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品列表
|
||||
* @return array
|
||||
*/
|
||||
public function getSkuList()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$seckill_model = new SeckillModel();
|
||||
$seckill_id = input('seckill_id', '');
|
||||
$goods_list = $seckill_model->getSeckillGoodsList($seckill_id);
|
||||
return $goods_list;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动关闭秒杀
|
||||
* @return array
|
||||
*/
|
||||
public function closeSeckill()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$seckill_model = new SeckillModel();
|
||||
$seckill_id = input('seckill_id', '');
|
||||
$goods_list = $seckill_model->closeSeckill($seckill_id);
|
||||
return $goods_list;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀推广
|
||||
*/
|
||||
public function seckillUrl()
|
||||
{
|
||||
$seckill_id = input('seckill_id', '');
|
||||
$app_type = input('app_type', 'all');
|
||||
$seckill_model = new SeckillModel();
|
||||
|
||||
$res = $seckill_model->urlQrcode('/pages_promotion/seckill/detail', [ 'id' => $seckill_id ], 'seckill', $app_type, $this->site_id);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除商品
|
||||
*/
|
||||
public function deleteGoodsAll()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$seckill_id = input('seckill_id', 0);
|
||||
|
||||
$seckill_model = new SeckillModel();
|
||||
foreach ($seckill_id as $k => $v){
|
||||
$res = $seckill_model->deleteSeckillGoods($v, $this->site_id);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量关闭秒杀
|
||||
* @return array
|
||||
*/
|
||||
public function closeSeckillAll()
|
||||
{
|
||||
if (request()->isJson()) {
|
||||
$seckill_model = new SeckillModel();
|
||||
$seckill_id = input('seckill_id', '');
|
||||
|
||||
foreach ($seckill_id as $k => $v){
|
||||
$res = $seckill_model->closeSeckill($v);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
95
addon/seckill/shop/view/public/css/goods.css
Executable file
@@ -0,0 +1,95 @@
|
||||
.layui-form-item .layui-input-inline.end-time {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.layui-form-item .layui-input-inline.end-time {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.time-label {
|
||||
display: inline-block;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
padding: 0 15px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #e9e9e9;
|
||||
background: #f7f7f7;
|
||||
font-size: 12px;
|
||||
vertical-align: middle;
|
||||
opacity: 1;
|
||||
margin: 4px 8px 4px 0;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.time-label span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.time-label i {
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
-webkit-border-radius: 10px;
|
||||
-moz-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.seckill-box .layui-table-col-special {
|
||||
padding: 5px 0 !important;
|
||||
}
|
||||
|
||||
.layui-table-body {
|
||||
max-height: 480px !important;
|
||||
}
|
||||
|
||||
.goods-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.goods-title .goods-img {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.goods-title .goods-img img {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.goods-title .goods-name {
|
||||
flex: 1;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.forbidden {
|
||||
cursor: not-allowed;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.form-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layui-carousel {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 1325px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.goods_num {
|
||||
padding-left: 20px;
|
||||
}
|
||||
BIN
addon/seckill/shop/view/public/img/zone_preview.png
Executable file
|
After Width: | Height: | Size: 116 KiB |
650
addon/seckill/shop/view/public/js/goods.js
Executable file
@@ -0,0 +1,650 @@
|
||||
var selectedSkuId = [], sku_list = [], time_list = [], form, laydate, timeTable, minDate, currentDate = new Date(),
|
||||
repeat_flag = false; //防重复标识;
|
||||
|
||||
layui.use(['form', 'laydate'], function () {
|
||||
form = layui.form;
|
||||
laydate = layui.laydate;
|
||||
minDate = "";
|
||||
form.render();
|
||||
|
||||
currentDate.setDate(currentDate.getDate() + 30);
|
||||
|
||||
if ($("input[name='id']").val()) {
|
||||
time_list = JSON.parse($('input[name="time_list"]').val());
|
||||
sku_list = JSON.parse($('input[name="sku_list"]').val());
|
||||
|
||||
laydate.render({
|
||||
elem: '#start_time',
|
||||
type: 'datetime',
|
||||
done: function (value) {
|
||||
minDate = value;
|
||||
reRender();
|
||||
}
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#end_time',
|
||||
type: 'datetime'
|
||||
});
|
||||
} else {
|
||||
laydate.render({
|
||||
elem: '#start_time',
|
||||
type: 'datetime',
|
||||
value: new Date(),
|
||||
done: function (value) {
|
||||
minDate = value;
|
||||
reRender();
|
||||
}
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#end_time',
|
||||
type: 'datetime',
|
||||
value: new Date(currentDate)
|
||||
});
|
||||
}
|
||||
|
||||
renderTimeTable();
|
||||
initTimeList();
|
||||
renderTable();
|
||||
|
||||
form.on('submit(save)', function (data) {
|
||||
if (verify()) {
|
||||
var goods_data = [];
|
||||
if (data.field.id) {
|
||||
for (var i in sku_list) {
|
||||
if (sku_list[i]['is_select'] == 1) {
|
||||
goods_data.push(sku_list[i]);
|
||||
}
|
||||
}
|
||||
data.field.sku_list = goods_data;
|
||||
} else {
|
||||
for (var i in sku_list) {
|
||||
var goods = {};
|
||||
goods.goods_id = sku_list[i]['goods_id'];
|
||||
if (goods_data.length == 0) {
|
||||
goods_data.push(goods);
|
||||
} else {
|
||||
$.each(goods_data, function (index, event) {
|
||||
if (goods_data.length == index + 1 && event.goods_id != goods.goods_id) {
|
||||
goods_data.push(goods);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
$.each(goods_data, function (i, e) {
|
||||
goods_data[i]['sku_list'] = [];
|
||||
$.each(sku_list, function (index, event) {
|
||||
if (event.goods_id == e.goods_id) {
|
||||
goods_data[i]['sku_list'].push(event);
|
||||
}
|
||||
})
|
||||
});
|
||||
data.field.goods_data = goods_data;
|
||||
}
|
||||
|
||||
var goods_ids = [];
|
||||
goods_data.forEach(function (item) {
|
||||
goods_ids.push(item.goods_id);
|
||||
});
|
||||
data.field.goods_ids = goods_ids.toString();
|
||||
|
||||
if (repeat_flag) return;
|
||||
repeat_flag = true;
|
||||
|
||||
$.ajax({
|
||||
url: data.field.id ? ns.url("seckill://shop/seckill/updateGoods") : ns.url("seckill://shop/seckill/addGoods"),
|
||||
data: data.field,
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function (res) {
|
||||
repeat_flag = false;
|
||||
|
||||
if (res.code == 0) {
|
||||
layer.confirm(data.field.id ? '编辑成功' : '添加成功', {
|
||||
title: '操作提示',
|
||||
btn: ['返回列表', data.field.id ? '继续操作' : '继续添加'],
|
||||
closeBtn: 0,
|
||||
yes: function (index, layero) {
|
||||
location.hash = ns.hash("seckill://shop/seckill/goodslist")
|
||||
layer.close(index);
|
||||
},
|
||||
btn2: function (index, layero) {
|
||||
listenerHash(); // 刷新页面
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
form.verify({
|
||||
time: function (value) {
|
||||
var now_time = (new Date()).getTime();
|
||||
var start_time = (new Date($("#start_time").val())).getTime();
|
||||
var end_time = (new Date(value)).getTime();
|
||||
var old_end_time = $("#old_end_time").val();
|
||||
if (now_time > end_time) {
|
||||
return '结束时间不能小于当前时间!'
|
||||
}
|
||||
if (start_time > end_time) {
|
||||
return '结束时间不能小于开始时间!';
|
||||
}
|
||||
if (old_end_time && old_end_time > end_time) {
|
||||
return '结束时间不能小于之前设置的结束时间!';
|
||||
}
|
||||
},
|
||||
seckilltime: function (value, item) {
|
||||
if (value == "" || value == 0) {
|
||||
return '请选择时间段';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("body").off("click", ".no-participation").on("click", ".no-participation", function () {
|
||||
$(this).text("参与");
|
||||
$(this).parents("tr").find("input").each(function (index, item) {
|
||||
$(item).attr("readonly", true);
|
||||
$(item).attr("disabled", true);
|
||||
$(item).addClass("forbidden");
|
||||
$(item).attr("lay-verify", "");
|
||||
});
|
||||
|
||||
$(this).addClass("participation").removeClass("no-participation");
|
||||
sku_list[$(this).parents("tr").attr("data-index")].is_select = 0;
|
||||
});
|
||||
|
||||
$("body").off("click", ".participation").on("click", ".participation", function () {
|
||||
$(this).text("不参与");
|
||||
$(this).parents("tr").find("input").each(function (index, item) {
|
||||
$(item).attr("readonly", false);
|
||||
$(item).attr("disabled", false);
|
||||
$(item).removeClass("forbidden");
|
||||
});
|
||||
|
||||
$(this).removeClass("participation").addClass("no-participation");
|
||||
sku_list[$(this).parents("tr").attr("data-index")].is_select = 1;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// 重新渲染结束时间
|
||||
function reRender() {
|
||||
$("#end_time").remove();
|
||||
$(".end-time").html('<input type="text" id="end_time" name="end_time" placeholder="请输入结束时间" lay-verify="required|time" class = "layui-input len-mid" autocomplete="off"> ');
|
||||
laydate.render({
|
||||
elem: '#end_time',
|
||||
type: 'datetime',
|
||||
min: minDate
|
||||
});
|
||||
}
|
||||
|
||||
function verify() {
|
||||
|
||||
if ($('input[name="seckill_time_id"]').val() == '') {
|
||||
layer.msg('请选择场次', {icon: 5, anim: 6});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sku_list.length == 0) {
|
||||
layer.msg('请选择商品', {icon: 5, anim: 6});
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i in sku_list) {
|
||||
if (sku_list[i]['max_buy'] < 0) {
|
||||
layer.msg('商品限购不可小于0', {icon: 5, anim: 6});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sku_list[i]['seckill_price'] <= 0) {
|
||||
layer.msg('秒杀价不可小于等于0', {icon: 5, anim: 6});
|
||||
return false;
|
||||
}
|
||||
if (sku_list[i]['seckill_stock'] > sku_list[i]['stock']) {
|
||||
layer.msg('秒杀库存不能大于商品库存', {icon: 5, anim: 6});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function delGoods(obj, id) {
|
||||
var sku_ids = [];
|
||||
for (let i = 0; i < sku_list.length; i++) {
|
||||
if (sku_list[i].sku_id == parseInt(id)) {
|
||||
sku_list.splice(i, 1);
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < sku_list.length; i++) {
|
||||
sku_ids.push(sku_list[i].sku_id);
|
||||
}
|
||||
$(obj).parents("tr").remove();
|
||||
$("#goods_num").html(sku_list.length);
|
||||
selectedSkuId = sku_ids.toString();
|
||||
}
|
||||
|
||||
// 表格渲染
|
||||
function renderTable() {
|
||||
//展示已知数据
|
||||
table = new Table({
|
||||
elem: '#selected_goods_list',
|
||||
page: false,
|
||||
limit: Number.MAX_VALUE,
|
||||
cols: [
|
||||
[
|
||||
{
|
||||
width: "3%",
|
||||
type: 'checkbox',
|
||||
unresize: 'false'
|
||||
},
|
||||
{
|
||||
field: 'sku_name',
|
||||
title: '商品名称',
|
||||
width: '22%',
|
||||
unresize: 'false',
|
||||
templet: function (data) {
|
||||
var html = '';
|
||||
html += `
|
||||
<div class="goods-title">
|
||||
<div class="goods-img">
|
||||
<img src="${ns.img(data.sku_image)}" alt="">
|
||||
</div>
|
||||
<p class="multi-line-hiding goods-name" data-goods_id="${data.goods_id}" data-sku_id="${data.sku_id}" title="${data.sku_name}">${data.sku_name}</p>
|
||||
</div>
|
||||
`;
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
field: 'price',
|
||||
title: '原价',
|
||||
unresize: 'false',
|
||||
align: 'left',
|
||||
width: '14%',
|
||||
templet: function (data) {
|
||||
return '<p class="line-hiding" title="' + data.price + '">¥<span>' + data.price + '</span></p>';
|
||||
}
|
||||
}, {
|
||||
field: 'stock',
|
||||
title: '库存',
|
||||
unresize: 'false',
|
||||
width: '9%',
|
||||
templet: function (data) {
|
||||
return '<p class="stock">' + data.stock + '</p>';
|
||||
}
|
||||
}, {
|
||||
field: 'max_buy',
|
||||
title: '<span>限购(0为不限购)</span>',
|
||||
unresize: 'false',
|
||||
width: '14%',
|
||||
templet: '#maxBuy'
|
||||
}, {
|
||||
title: '<span title="秒杀价">秒杀价</span>',
|
||||
unresize: 'false',
|
||||
width: '15%',
|
||||
templet: '#seckillPrice'
|
||||
}, {
|
||||
title: '<span title="秒杀库存">秒杀库存</span>',
|
||||
unresize: 'false',
|
||||
width: '12%',
|
||||
templet: '#seckillStock'
|
||||
}, {
|
||||
title: '操作',
|
||||
toolbar: '#operation',
|
||||
unresize: 'false',
|
||||
}]
|
||||
],
|
||||
data: sku_list,
|
||||
toolbar: '#toolbarOperation'
|
||||
});
|
||||
|
||||
table.toolbar(function (obj) {
|
||||
if (obj.data.length < 1) {
|
||||
layer.msg('请选择要操作的数据');
|
||||
return;
|
||||
}
|
||||
switch (obj.event) {
|
||||
case "seckill-purchase":
|
||||
editInput(0, obj);
|
||||
break;
|
||||
case "seckill-price":
|
||||
editInput(1, obj);
|
||||
break;
|
||||
case "seckill-stock":
|
||||
editInput(2, obj);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function editInput(textIndex = 0, data) {
|
||||
var text = [{
|
||||
name: '限购',
|
||||
value: 'max_buy'
|
||||
}, {
|
||||
name: '秒杀价',
|
||||
value: 'seckill_price'
|
||||
}, {
|
||||
name: '秒杀库存',
|
||||
value: 'seckill_stock'
|
||||
}];
|
||||
|
||||
console.log(text[textIndex].value)
|
||||
if(text[textIndex].value == 'seckill_price'){
|
||||
var html =`
|
||||
<div class="layui-form form-wrap">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><span class="required">*</span>优惠方式:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="seckill_type" value="1" class="seckill_type_input" onclick="switch_type(1)" title="固定价格" lay-filter="seckill_type" checked>
|
||||
<input type="radio" name="seckill_type" value="2" class="seckill_type_input" onclick="switch_type(2)" title="打折" lay-filter="seckill_type">
|
||||
<input type="radio" name="seckill_type" value="3" class="seckill_type_input" onclick="switch_type(3)" title="减价" lay-filter="seckill_type">
|
||||
</div>
|
||||
<label class="layui-form-label seckill-title"><span class="required">*</span>固定价格:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="bargain_edit_input" lay-verify="required" autocomplete="off" class="layui-input len-mid" placeholder="请输入固定价格">
|
||||
</div>
|
||||
<div class="word-aux seckill-word"></div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}else{
|
||||
var html =`<div class="layui-form-item">
|
||||
<label class="layui-form-label"><span class="required">*</span>${text[textIndex].name}:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="bargain_edit_input" lay-verify="required" autocomplete="off" class="layui-input len-mid" placeholder="请输入${text[textIndex].name}">
|
||||
</div>
|
||||
</div> `
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "修改" + text[textIndex].name,
|
||||
area: ['600px'],
|
||||
btn: ["保存", "返回"],
|
||||
content:html,
|
||||
success:function(layero, index){
|
||||
form.on('radio(seckill_type)', function(data){
|
||||
switch_type(data.value)
|
||||
});
|
||||
form.render();
|
||||
},
|
||||
yes: function (index, layero) {
|
||||
var val = $("input[name='bargain_edit_input']").val();
|
||||
if (!val) {
|
||||
layer.msg("请输入" + text[textIndex].name);
|
||||
return false;
|
||||
}
|
||||
var type = $("input[name='seckill_type']:checked").val();
|
||||
if(type == 1 && val<= 0){
|
||||
layer.msg("固定价格需大于0")
|
||||
return false;
|
||||
}
|
||||
if(type == 2 && (val <= 0 || val > 10)){
|
||||
layer.msg("折扣率需大于0且小于等于10,可保留两位小数")
|
||||
return false;
|
||||
}
|
||||
if(type == 3 && val< 0){
|
||||
layer.msg("减价金额需大于等于0")
|
||||
return false;
|
||||
}
|
||||
var error_info = '';
|
||||
data.data.forEach(function (item, index) {
|
||||
sku_list.forEach(function (skuItem, skuIndex) {
|
||||
if (item.sku_id == skuItem.sku_id) {
|
||||
if(text[textIndex].value == 'seckill_price'){
|
||||
var new_val = 0;
|
||||
switch (type) {
|
||||
case '1': //固定价格
|
||||
new_val = val;
|
||||
break;
|
||||
case '2'://打折
|
||||
new_val = (sku_list[skuIndex]['price'] * 0.1 * val).toFixed(2)
|
||||
break;
|
||||
case '3': //减价
|
||||
new_val= (sku_list[skuIndex]['price'] -val).toFixed(2);
|
||||
break;
|
||||
}
|
||||
if(new_val <=0){
|
||||
console.log(sku_list[skuIndex])
|
||||
error_info = sku_list[skuIndex]['sku_name']+'设置后秒杀价为0元,请检查';
|
||||
return false;
|
||||
}
|
||||
sku_list[skuIndex][text[textIndex].value] = new_val;
|
||||
}else{
|
||||
sku_list[skuIndex][text[textIndex].value] = val;
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if(error_info){
|
||||
layer.msg(error_info)
|
||||
return
|
||||
}
|
||||
|
||||
renderTable();
|
||||
layer.closeAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function switch_type(obj){
|
||||
$(".seckill-word").text("")
|
||||
switch (obj) {
|
||||
case '1':
|
||||
$(".seckill-title").html("<span class=\"required\">*</span>固定价格:")
|
||||
$("input[name='bargain_edit_input']").attr("placeholder",'请输入固定价格')
|
||||
break;
|
||||
case '2':
|
||||
$(".seckill-title").html("<span class=\"required\">*</span>折扣率:")
|
||||
$("input[name='bargain_edit_input']").attr("placeholder",'请输入折扣率')
|
||||
$(".seckill-word").text("折扣率需大于0且小于等于10,可保留两位小数")
|
||||
break;
|
||||
case '3':
|
||||
$(".seckill-title").html("<span class=\"required\">*</span>优惠金额:")
|
||||
$("input[name='bargain_edit_input']").attr("placeholder",'请输入优惠金额')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 商品 */
|
||||
function addGoods() {
|
||||
goodsSelect(function (data) {
|
||||
|
||||
sku_list = [];
|
||||
|
||||
var sku_ids = [];
|
||||
for (var key in data) {
|
||||
for (var sku in data[key].selected_sku_list) {
|
||||
var item = data[key].selected_sku_list[sku];
|
||||
item.seckill_price = item.price;
|
||||
item.max_buy = 1;
|
||||
item.seckill_stock = item.stock;
|
||||
sku_ids.push(item.sku_id);
|
||||
sku_list.push(item);
|
||||
}
|
||||
}
|
||||
renderTable();
|
||||
selectedSkuId = sku_ids;
|
||||
$("#goods_num").html(sku_list.length)
|
||||
}, selectedSkuId, {mode: "sku"});
|
||||
}
|
||||
|
||||
function setGoodsSku(type, sku_id, obj) {
|
||||
$.each(sku_list, function (i, e) {
|
||||
if (sku_id == e.sku_id) {
|
||||
sku_list[i][type] = $(obj).val();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function addSeckillTime() {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "场次选择",
|
||||
area: ['900px', '620px'],
|
||||
btn: ['保存', '返回'],
|
||||
content: $('#seckillTime').html(),
|
||||
success: function (layero) {
|
||||
renderTimeTable();
|
||||
},
|
||||
yes: function (index, layero) {
|
||||
var select_time_id = [];
|
||||
time_list = [];
|
||||
$('div[lay-id="seckill_time_list"] .time-select').each(function (i, e) {
|
||||
if ($(e).is(":checked")) {
|
||||
let time = {};
|
||||
time.start_time = $(e).attr('data-time-start');
|
||||
time.end_time = $(e).attr('data-time-end');
|
||||
time.id = $(e).attr('data-time-id');
|
||||
time.name = $(e).attr('data-name');
|
||||
|
||||
select_time_id.push($(e).attr('data-time-id'));
|
||||
time_list.push(time);
|
||||
}
|
||||
});
|
||||
$('input[name="seckill_time_id"]').val(select_time_id.toString());
|
||||
refreshTimeList();
|
||||
layer.closeAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refreshTimeList() {
|
||||
var html = '';
|
||||
for (let i in time_list) {
|
||||
let start_time = transformSeckillTime(time_list[i]['start_time']);
|
||||
let end_time = transformSeckillTime(time_list[i]['end_time']);
|
||||
let name = time_list[i]['name'];
|
||||
let id = time_list[i]['id'];
|
||||
html += `
|
||||
<li class="time-label" title="${start_time} - ${end_time}">
|
||||
<span>${name}</span>
|
||||
<i class="layui-icon layui-icon-close" onclick="delTime(${id}, this)"></i>
|
||||
</li>
|
||||
`;
|
||||
}
|
||||
$('.time-label-list ul').html(html);
|
||||
}
|
||||
|
||||
function transformSeckillTime(time) {
|
||||
time = parseFloat(time);
|
||||
var hour = parseInt(time / 3600);
|
||||
var minute = parseInt((time % 3600) / 60);
|
||||
var second = parseInt(time % 60);
|
||||
|
||||
if (hour < 10) hour = '0' + hour;
|
||||
if (minute < 10) minute = '0' + minute;
|
||||
if (second < 10) second = '0' + second;
|
||||
|
||||
return hour + ':' + minute + ':' + second;
|
||||
}
|
||||
|
||||
function delTime(id, obj) {
|
||||
time_list.splice(time_list.indexOf(id), 1);
|
||||
let time = [];
|
||||
for (let i in time_list) {
|
||||
if (time_list[i]['id'] != id) {
|
||||
time.push(time_list[i]['id']);
|
||||
}
|
||||
}
|
||||
$('input[name="seckill_time_id"]').val(time.toString());
|
||||
$(obj).parents('li').remove();
|
||||
}
|
||||
|
||||
// 场次渲染
|
||||
function renderTimeTable() {
|
||||
$.ajax({
|
||||
url: ns.url("seckill://shop/seckill/lists"),
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function (res) {
|
||||
if (res.code < 0) {
|
||||
layer.msg(res.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
var time_data = res.data;
|
||||
for (let i in time_data) {
|
||||
time_data[i]['is_select'] = 0;
|
||||
for (let j in time_list) {
|
||||
if (time_list[j]['id'] == time_data[i]['id']) {
|
||||
time_data[i]['is_select'] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
timeTable = new Table({
|
||||
elem: '#seckill_time_list',
|
||||
page: false,
|
||||
height: 380,
|
||||
limit: Number.MAX_VALUE,
|
||||
cols: [
|
||||
[{
|
||||
title: '<input type="checkbox" name="time_checkbox_all" lay-skin="primary" lay-filter="time_checkbox_all">',
|
||||
unresize: 'false',
|
||||
width: '10%',
|
||||
templet: '#timecheckbox',
|
||||
}, {
|
||||
field: 'name',
|
||||
title: '场次名称',
|
||||
unresize: 'false',
|
||||
align: 'left',
|
||||
width: '30%'
|
||||
}, {
|
||||
field: 'seckill_start_time_show',
|
||||
title: '开始时间',
|
||||
unresize: 'false',
|
||||
width: '25%'
|
||||
}, {
|
||||
field: 'seckill_end_time_show',
|
||||
title: '结束时间',
|
||||
unresize: 'false',
|
||||
width: '25%'
|
||||
}]
|
||||
],
|
||||
data: time_data
|
||||
});
|
||||
|
||||
// 勾选商品
|
||||
form.on('checkbox(time_checkbox_all)', function (data) {
|
||||
var all_checked = data.elem.checked;
|
||||
$("input[name='time_checkbox']").each(function () {
|
||||
var checked = $(this).prop('checked');
|
||||
if (all_checked != checked) {
|
||||
$(this).next().click();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function initTimeList() {
|
||||
var html = '';
|
||||
for (let i in time_list) {
|
||||
let start_time = transformSeckillTime(time_list[i]['seckill_start_time']);
|
||||
let end_time = transformSeckillTime(time_list[i]['seckill_end_time']);
|
||||
let name = time_list[i]['name'];
|
||||
let id = time_list[i]['id'];
|
||||
html += `
|
||||
<li class="time-label" title="${start_time} - ${end_time}">
|
||||
<span>${name}</span>
|
||||
<i class="layui-icon layui-icon-close" onclick="delTime(${id}, this)"></i>
|
||||
</li>
|
||||
`;
|
||||
}
|
||||
$('.time-label-list ul').html(html);
|
||||
|
||||
}
|
||||
|
||||
function backSeckillGoodsList() {
|
||||
location.hash = ns.hash("seckill://shop/seckill/goodslist");
|
||||
}
|
||||
126
addon/seckill/shop/view/seckill/add.html
Executable file
@@ -0,0 +1,126 @@
|
||||
<div class="layui-form form-wrap">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><span class="required">*</span>秒杀场次名称:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" id="name" name="name" lay-verify="required" autocomplete="off" class="layui-input len-long">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>秒杀时间段:</label>
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="add_start_time" value="00:00:00" lay-verify="required" class="layui-input">
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
<span class="layui-form-mid">-</span>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="add_end_time" value="00:00:00" lay-verify="required" class="layui-input">
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="word-aux">
|
||||
<p>每个场次的时间段不能重叠</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
|
||||
<button class="layui-btn layui-btn-primary" onclick="backSeckillList()">返回</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
layui.use(['form','laydate'], function() {
|
||||
var form = layui.form,
|
||||
laydate = layui.laydate;
|
||||
repeat_flag = false; //防重复标识
|
||||
form.render();
|
||||
|
||||
// 表单提交监听
|
||||
form.on('submit(save)', function(data) {
|
||||
|
||||
data.name = $('#name').val();
|
||||
if (!data.name) {
|
||||
layer.msg("秒杀场次名称不能为空");
|
||||
return false;
|
||||
}
|
||||
if (!$('#add_start_time').val()) {
|
||||
layer.msg("开始时间不能为空");
|
||||
return false;
|
||||
}
|
||||
if (!$('#add_end_time').val()) {
|
||||
layer.msg("结束时间不能为空");
|
||||
return false;
|
||||
}
|
||||
if($('#add_end_time').val() <= $('#add_start_time').val()){
|
||||
layer.msg("结束时间必须大于开始时间");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (repeat_flag) return;
|
||||
repeat_flag = true;
|
||||
data.field.start_hour = $('#add_start_time').val().split(":")[0];
|
||||
data.field.start_minute = $('#add_start_time').val().split(":")[1];
|
||||
data.field.start_second = $('#add_start_time').val().split(":")[2];
|
||||
|
||||
data.field.end_hour = $('#add_end_time').val().split(":")[0];
|
||||
data.field.end_minute = $('#add_end_time').val().split(":")[1];
|
||||
data.field.end_second = $('#add_end_time').val().split(":")[2];
|
||||
|
||||
$.ajax({
|
||||
url: ns.url("seckill://shop/seckill/add"),
|
||||
data: data.field,
|
||||
type: "post",
|
||||
dataType: "JSON",
|
||||
success: function(res) {
|
||||
repeat_flag = false;
|
||||
if (res.code == 0) {
|
||||
layer.confirm('添加成功', {
|
||||
title:'操作提示',
|
||||
btn: ['返回列表', '继续添加'],
|
||||
closeBtn: 0,
|
||||
yes: function(index, layero){
|
||||
location.hash = ns.hash("seckill://shop/seckill/lists");
|
||||
layer.close(index);
|
||||
},
|
||||
btn2: function(index, layero) {
|
||||
listenerHash(); // 刷新页面
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
layer.msg(res.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
form.verify({
|
||||
timeHour: function(value) {
|
||||
if (!new RegExp("^0|[1-9]|1[0-9]|2[0-3]$").test(value)) {
|
||||
return '时段范围为0-23,且只能是整数';
|
||||
}
|
||||
},
|
||||
timeMinSend: function(value) {
|
||||
if (!new RegExp("^(?:0|[0-5][0-9]?)$").test(value)) {
|
||||
return '分秒范围为0-59,且只能是整数';
|
||||
}
|
||||
}
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#add_end_time',
|
||||
type: 'time'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#add_start_time',
|
||||
type: 'time'
|
||||
});
|
||||
});
|
||||
|
||||
function backSeckillList() {
|
||||
location.hash = ns.hash("seckill://shop/seckill/lists");
|
||||
}
|
||||
</script>
|
||||
121
addon/seckill/shop/view/seckill/edit.html
Executable file
@@ -0,0 +1,121 @@
|
||||
<div class="layui-form form-wrap">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><span class="required">*</span>秒杀场次名称:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" id="name" name="name" lay-verify="required" value="{$time_info.name}" autocomplete="off" class="layui-input len-long">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>秒杀时间段:</label>
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="add_start_time" value="{$time_info.start_hour}:{$time_info.start_minute}:{$time_info.start_second}" lay-verify="required" class="layui-input">
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
<span class="layui-form-mid">-</span>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="add_end_time" value="{$time_info.end_hour}:{$time_info.end_minute}:{$time_info.end_second}" lay-verify="required" class="layui-input">
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="word-aux">
|
||||
<p>每个场次的时间段不能重叠</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
|
||||
<button class="layui-btn layui-btn-primary" onclick="backSeckillList()">返回</button>
|
||||
</div>
|
||||
<input type="hidden" name="id" value="{$time_info.id}" />
|
||||
</div>
|
||||
|
||||
<script>
|
||||
layui.use(['form','laydate'], function() {
|
||||
var form = layui.form,
|
||||
laydate = layui.laydate;
|
||||
repeat_flag = false; //防重复标识
|
||||
form.render();
|
||||
|
||||
// 表单提交监听
|
||||
form.on('submit(save)', function(data) {
|
||||
if (repeat_flag) return;
|
||||
repeat_flag = true;
|
||||
data.field.name = $('#name').val();
|
||||
if (!data.field.name) {
|
||||
layer.msg("秒杀场次名称不能为空");
|
||||
return false;
|
||||
}
|
||||
if (!$('#add_start_time').val()) {
|
||||
layer.msg("开始时间不能为空");
|
||||
return false;
|
||||
}
|
||||
if (!$('#add_end_time').val()) {
|
||||
layer.msg("结束时间不能为空");
|
||||
return false;
|
||||
}
|
||||
if($('#add_end_time').val() <= $('#add_start_time').val()){
|
||||
layer.msg("结束时间必须大于开始时间");
|
||||
return false;
|
||||
}
|
||||
data.field.start_hour = $('#add_start_time').val().split(":")[0];
|
||||
data.field.start_minute = $('#add_start_time').val().split(":")[1];
|
||||
data.field.start_second = $('#add_start_time').val().split(":")[2];
|
||||
|
||||
data.field.end_hour = $('#add_end_time').val().split(":")[0];
|
||||
data.field.end_minute = $('#add_end_time').val().split(":")[1];
|
||||
data.field.end_second = $('#add_end_time').val().split(":")[2];
|
||||
$.ajax({
|
||||
url: ns.url("seckill://shop/seckill/edit"),
|
||||
data: data.field,
|
||||
type: "post",
|
||||
dataType: "JSON",
|
||||
success: function(res) {
|
||||
repeat_flag = false;
|
||||
if (res.code == 0) {
|
||||
layer.confirm('编辑成功', {
|
||||
title: '操作提示',
|
||||
btn: ['返回列表', '继续操作'],
|
||||
yes: function(index, layero) {
|
||||
location.hash = ns.hash("seckill://shop/seckill/lists");
|
||||
layer.close(index);
|
||||
},
|
||||
btn2: function(index, layero) {
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
form.verify({
|
||||
timeHour: function(value) {
|
||||
if (!new RegExp("^0|[1-9]|1[0-9]|2[0-3]$").test(value)) {
|
||||
return '时段范围为0-23,且只能是整数';
|
||||
}
|
||||
},
|
||||
timeMinSend: function(value) {
|
||||
if (!new RegExp("^(?:0|[0-5][0-9]?)$").test(value)) {
|
||||
return '分秒范围为0-59,且只能是整数';
|
||||
}
|
||||
}
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#add_end_time',
|
||||
type: 'time'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#add_start_time',
|
||||
type: 'time'
|
||||
});
|
||||
});
|
||||
|
||||
function backSeckillList() {
|
||||
location.hash = ns.hash("seckill://shop/seckill/lists");
|
||||
}
|
||||
</script>
|
||||
186
addon/seckill/shop/view/seckill/editgoods.html
Executable file
@@ -0,0 +1,186 @@
|
||||
<link rel="stylesheet" type="text/css" href="SECKILL_CSS/goods.css"/>
|
||||
|
||||
<div class="layui-form form-wrap main-form">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><span class="required">*</span>活动名称:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="seckill_name" value="{$seckill_info['seckill_name']??''}" lay-verify="required" placeholder="请输入活动名称" autocomplete="off" class="layui-input len-long" maxlength="40">
|
||||
</div>
|
||||
<div class="word-aux">
|
||||
<p>活动名称将显示在列表中展示,方便商家管理使用</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">活动规则说明:</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="remark" class="layui-textarea len-long" maxlength="300" placeholder="请输入活动规则说明">{$seckill_info['remark']??''}</textarea>
|
||||
</div>
|
||||
<div class="word-aux">
|
||||
<p>商家对秒杀的补充说明文字,非必填选项</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><span class="required">*</span>活动时间:</label>
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline len-mid">
|
||||
<input type="text" id="start_time" name="start_time" {notempty name="$seckill_info"}value="{:date('Y-m-d H:i:s', $seckill_info.start_time)}"{/notempty} lay-verify="required" autocomplete="off" class="layui-input" readonly>
|
||||
<i class="iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
<span class="layui-form-mid">-</span>
|
||||
<div class="layui-input-inline len-mid end-time">
|
||||
<input type="text" id="end_time" name="end_time" lay-verify="required|time" {notempty name="$seckill_info"}value="{:date('Y-m-d H:i:s', $seckill_info.end_time)}"{/notempty} autocomplete="off" class="layui-input" readonly>
|
||||
<input type="hidden" value="{$seckill_info.end_time??''}" id="old_end_time">
|
||||
<i class="iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="word-aux">
|
||||
<p>商品只会在活动时间段内的指定场次进行展示</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">排序:</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="number" name="sort" value="{$seckill_info['sort']??''}" class="layui-input len-short" placeholder="0" autocomplete="off">
|
||||
</div>
|
||||
<div class="word-aux">商品默认排序号为0,数字越大,排序越靠前,数字重复,则最新添加的靠前。</div>
|
||||
</div>
|
||||
|
||||
<div class="seckill-goods-list">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label"><span class="required">*</span>参与场次:</label>
|
||||
<div class="layui-input-block time-label-list">
|
||||
<a href="javascript:addSeckillTime();" class="text-color js-add-time">选择场次</a>
|
||||
<ul></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item goods_list">
|
||||
<label class="layui-form-label"><span class="required">*</span>商品选择:</label>
|
||||
<div class="layui-input-block">
|
||||
<table id="selected_goods_list" lay-filter="selected_goods_list"></table>
|
||||
{if empty($seckill_info) }
|
||||
<button class="layui-btn" onclick="addGoods()">选择商品</button>
|
||||
<span class="goods_num">已选商品(<span id="goods_num" class="text-color">0</span>)</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="id" value="{$seckill_info.id??''}">
|
||||
<input type="hidden" name="seckill_time_id" value="{$seckill_info['seckill_time_id']??''}">
|
||||
{notempty name="$time_list"}
|
||||
<input type="hidden" name="time_list" value='{:json_encode($time_list, JSON_UNESCAPED_UNICODE)}'>
|
||||
{/notempty}
|
||||
{notempty name="$seckill_info"}
|
||||
<input type="hidden" name="sku_list" value='{:json_encode($seckill_info.goods_sku, JSON_UNESCAPED_UNICODE)}'>
|
||||
{/notempty}
|
||||
|
||||
<div class="form-row">
|
||||
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
|
||||
<button class="layui-btn layui-btn-primary" onclick="backSeckillGoodsList()">返回</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 操作 -->
|
||||
<script type="text/html" id="operation">
|
||||
<div class="table-btn">
|
||||
{if !empty($seckill_info) }
|
||||
{{# if (d.is_select == 1){ }}
|
||||
<a class="layui-btn no-participation">不参与</a>
|
||||
{{# }else{ }}
|
||||
<a class="layui-btn participation">参与</a>
|
||||
{{# } }}
|
||||
{else/}
|
||||
<a class="layui-btn" onclick="delGoods(this,{{d.sku_id}})">删除</a>
|
||||
{/if}
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- 价格设置 -->
|
||||
<script type="text/html" id="seckillPrice">
|
||||
{{# if (d.is_select == 1){ }}
|
||||
<input type="number" class="layui-input len-input " value="{{d.seckill_price}}" onchange="setGoodsSku('seckill_price', {{d.sku_id}}, this)" min="0"/>
|
||||
{{# }else{ }}
|
||||
<input type="number" class="layui-input len-input" value="{{d.seckill_price}}" onchange="setGoodsSku('seckill_price', {{d.sku_id}}, this)" min="0"/>
|
||||
{{# } }}
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="toolbarOperation">
|
||||
<button class="layui-btn layui-btn-primary" lay-event="seckill-purchase">限购</button>
|
||||
<button class="layui-btn layui-btn-primary" lay-event="seckill-price">秒杀价</button>
|
||||
<button class="layui-btn layui-btn-primary" lay-event="seckill-stock">秒杀库存</button>
|
||||
</script>
|
||||
|
||||
<!-- 库存设置 -->
|
||||
<script type="text/html" id="seckillStock">
|
||||
|
||||
{{# if (d.is_select == 1){ }}
|
||||
<input type="number" class="layui-input len-input seckill_stock" value="{{d.seckill_stock}}" onchange="setGoodsSku('seckill_stock', {{d.sku_id}}, this)" min="0.00"/>
|
||||
{{# }else{ }}
|
||||
<input type="number" class="layui-input len-input seckill_stock" value="{{d.seckill_stock}}" onchange="setGoodsSku('seckill_stock', {{d.sku_id}}, this)" min="0.00"/>
|
||||
{{# } }}
|
||||
|
||||
</script>
|
||||
|
||||
<!-- 限购设置 -->
|
||||
<script type="text/html" id="maxBuy">
|
||||
|
||||
{{# if (d.is_select == 1){ }}
|
||||
<input type="number" class="layui-input len-input max_buy" value="{{d.max_buy}}" onchange="setGoodsSku('max_buy', {{d.sku_id}}, this)" min="0"/>
|
||||
{{# }else{ }}
|
||||
<input type="number" class="layui-input len-input max_buy" value="{{d.max_buy}}" onchange="setGoodsSku('max_buy', {{d.sku_id}}, this)" min="0"/>
|
||||
{{# } }}
|
||||
|
||||
</script>
|
||||
|
||||
<!--选择场次弹出-->
|
||||
<script type="text/html" id="seckillTime">
|
||||
<div class="seckill-box">
|
||||
<table id="seckill_time_list" lay-filter="seckill_time_list"></table>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="timecheckbox">
|
||||
{{# if (d.is_select == 1){ }}
|
||||
<input type="checkbox" name="time_checkbox" data-name="{{d.name}}" data-time-start="{{d.seckill_start_time}}" checked data-time-end="{{d.seckill_end_time}}" data-time-id="{{d.id}}" class="time-select" lay-skin="primary" lay-filter="goods_checkbox">
|
||||
{{# }else{ }}
|
||||
<input type="checkbox" name="time_checkbox" data-name="{{d.name}}" data-time-start="{{d.seckill_start_time}}" data-time-end="{{d.seckill_end_time}}" data-time-id="{{d.id}}" class="time-select" lay-skin="primary" lay-filter="goods_checkbox">
|
||||
{{# } }}
|
||||
</script>
|
||||
|
||||
<!-- 添加场次 -->
|
||||
<script type="text/html" id="addTime">
|
||||
<div class="layui-form ">
|
||||
<div class="layui-form-item len-mid">
|
||||
<label class="layui-form-label"><span class="required">*</span>秒杀场次名称:</label>
|
||||
<div class="layui-input-block">
|
||||
{{# if(d.name){ }}
|
||||
<input type="text" id="add_time_name" value="{{d.name}}" lay-verify="required" autocomplete="off" class="layui-input len-mid">
|
||||
{{# }else{ }}
|
||||
<input type="text" id="add_time_name" value="" lay-verify="required" autocomplete="off" class="layui-input len-mid">
|
||||
{{# } }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item ">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>秒杀时间段:</label>
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="add_start_time" value="{{d.seckill_start_time_show ? d.seckill_start_time_show : ''}}" lay-verify="required" class="layui-input">
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
<span class="layui-form-mid">-</span>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="add_end_time" value="{{d.seckill_end_time_show ? d.seckill_end_time_show :''}}" lay-verify="required" class="layui-input">
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script src="SECKILL_JS/goods.js?time=20250103"></script>
|
||||
652
addon/seckill/shop/view/seckill/goodslist.html
Executable file
@@ -0,0 +1,652 @@
|
||||
<style>
|
||||
.contraction span{cursor: pointer;display: inline-block;width: 17px;height: 17px;text-align: center;line-height: 14px;user-select: none;}
|
||||
.sku-list{overflow: hidden;padding: 0 45px;max-width: 100%;}
|
||||
.sku-list li .img-wrap{vertical-align: middle;margin-right: 8px;width: 20%;height: 80px;text-align: center;line-height: 70px;}
|
||||
.sku-list li .img-wrap img{max-width: 100%;max-height: 100%;}
|
||||
.sku-list li .info-wrap span.sku-name{-webkit-line-clamp: 2;margin-bottom: 5px;}
|
||||
.sku-list li .info-wrap span{display: -webkit-box;margin-bottom: 5px;overflow: hidden;text-overflow: ellipsis;white-space: normal;word-break: break-all;-webkit-box-orient: vertical;-webkit-line-clamp: 1;}
|
||||
.sku-list li{float: left;display: flex;padding: 10px;margin-right: 10px;margin-bottom: 10px;border: 1px solid #EFEFEF;width: 294px;height: 180px;align-items: center;}
|
||||
#time_label_dl span{margin: 3px 5px 3px 0;color: white;padding: 0 5px;border-radius: 5px;line-height: 25px;}
|
||||
#time_label_dl{display: flex;flex-wrap: wrap;}
|
||||
.layui-layout-admin .layui-form-item .layui-input-inline{background-color: #fff;}
|
||||
.layui-layout-admin .table-tab .layui-tab-title{margin-bottom: 15px;}
|
||||
</style>
|
||||
|
||||
<div class="single-filter-box">
|
||||
<button class="layui-btn" onclick="clickAdd()">添加秒杀商品</button>
|
||||
</div>
|
||||
<div class="screen layui-collapse" lay-filter="selection_panel">
|
||||
<div class="layui-colla-item">
|
||||
<form class="layui-colla-content layui-form layui-show">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">商品名称:</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="goods_name" placeholder="请输入商品名称" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">参与场次:</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="seckill_time_id">
|
||||
<option value="">全部</option>
|
||||
{foreach $res as $k => $v}
|
||||
<option value="{$v['id']}" {if $v['id'] == $seckill_time_id}selected{/if}>{$v['name']}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">秒杀时间:</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" class="layui-input" name="start_time" placeholder="开始时间" id="start_time" readonly>
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
<div class="layui-form-mid">-</div>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" class="layui-input" name="end_time" placeholder="结束时间" id="end_time" readonly>
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<button type="button" class="layui-btn" lay-filter="search" lay-submit>筛选</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-tab table-tab" lay-filter="bargain_tab">
|
||||
<ul class="layui-tab-title">
|
||||
<li class="layui-this" data-status="">全部</li>
|
||||
<li data-status="0">未开始</li>
|
||||
<li data-status="1">进行中</li>
|
||||
<li data-status="2">已结束</li>
|
||||
<li data-status="-1">已关闭</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<!-- 列表 -->
|
||||
<table id="good_list" lay-filter="good_list"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--价格-->
|
||||
<script type="text/html" id="price">
|
||||
<div class="layui-elip">{{d.seckill_price}}</div>
|
||||
</script>
|
||||
|
||||
<!-- 推广 -->
|
||||
{include file="app/shop/view/component/promote_show.html"}
|
||||
|
||||
<!--时间-->
|
||||
<script type="text/html" id="time">
|
||||
<div class="layui-elip">开始时间:{{ns.time_to_date(d.start_time)}}</div>
|
||||
<div class="layui-elip">结束时间:{{ns.time_to_date(d.end_time)}}</div>
|
||||
</script>
|
||||
|
||||
<!--操作-->
|
||||
<script type="text/html" id="operation">
|
||||
<div class="operation-wrap" data-seckill-id="{{d.id}}">
|
||||
<div class="popup-qrcode-wrap" style="display: none"><img class="popup-qrcode-loadimg" src="__STATIC__/loading/loading.gif"/></div>
|
||||
<div class="table-btn">
|
||||
{{# if(d.status == 1){ }}
|
||||
<a class="layui-btn text-color" lay-event="select">推广</a>
|
||||
{{# } }}
|
||||
<a class="layui-btn" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn" lay-event="delete">删除</a>
|
||||
|
||||
{{# if(d.status == 1){ }}
|
||||
<a class="layui-btn" lay-event="close">关闭</a>
|
||||
{{# } }}
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- 批量操作 -->
|
||||
<script type="text/html" id="toolbarAction">
|
||||
<button class="layui-btn layui-btn-primary" lay-event="delete">批量删除</button>
|
||||
<button class="layui-btn layui-btn-primary" lay-event="invalid">批量关闭</button>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="goods_name">
|
||||
<div class="table-title">
|
||||
|
||||
<div class="contraction" data-id="{{d.id}}" data-open="0">
|
||||
<span>+</span>
|
||||
</div>
|
||||
|
||||
<div class="title-pic">
|
||||
{{# if(d.goods_image){ }}
|
||||
<img layer-src="{{ns.img(d.goods_image.split(',')[0],'big')}}" src="{{ns.img(d.goods_image.split(',')[0],'small')}}" />
|
||||
{{# } }}
|
||||
</div>
|
||||
<div class="title-content">
|
||||
<a href="javascript:;" class="multi-line-hiding text-color-sub" title="{{d.goods_name}}">{{d.goods_name}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="skuList">
|
||||
<tr class="js-list-{{d.index}}" id="sku_img_{{d.index}}">
|
||||
<td colspan="10">
|
||||
<ul class="sku-list">
|
||||
{{# for(var i=0; i<d.list.length; i++){ }}
|
||||
<li>
|
||||
<div class="img-wrap">
|
||||
<img layer-src src="{{ns.img(d.list[i].sku_image)}}">
|
||||
</div>
|
||||
<div class="info-wrap">
|
||||
<span class="sku-name" title="{{d.list[i].sku_name}}">{{d.list[i].sku_name}}</span>
|
||||
<span class="price">商品价格:¥{{d.list[i].price}}</span>
|
||||
<span class="sale_num">秒杀价:{{d.list[i].seckill_price}}</span>
|
||||
<span class="price">库存:{{d.list[i].stock}}</span>
|
||||
</div>
|
||||
</li>
|
||||
{{# } }}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<!-- 场次 -->
|
||||
<script id="time_label" type="text/html">
|
||||
{{# if (d.time_list != []) { }}
|
||||
<div id="time_label_dl">
|
||||
{{# for (var index in d.time_list) { }}
|
||||
{{'<span class="bg-color">' + d.time_list[index]['name'] + '</span>'}}
|
||||
{{# } }}
|
||||
</div>
|
||||
{{# } }}
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="addTime">
|
||||
<div class="layui-form">
|
||||
<div class="layui-form-item len-mid">
|
||||
<label class="layui-form-label"><span class="required">*</span>秒杀场次名称:</label>
|
||||
<div class="layui-input-block">
|
||||
{{# if(d.name){ }}
|
||||
<input type="text" id="add_time_name" value="{{d.name}}" lay-verify="required" autocomplete="off" class="layui-input len-mid">
|
||||
{{# }else{ }}
|
||||
<input type="text" id="add_time_name" value="" lay-verify="required" autocomplete="off" class="layui-input len-mid">
|
||||
{{# } }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item ">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label"><span class="required">*</span>秒杀时间段:</label>
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="add_start_time" value="{{d.seckill_start_time_show}}" lay-verify="required" class="layui-input">
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
<span class="layui-form-mid">-</span>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" id="add_end_time" value="{{d.seckill_end_time_show}}" lay-verify="required" class="layui-input">
|
||||
<i class=" iconrili iconfont calendar"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- 编辑排序 -->
|
||||
<script type="text/html" id="editSort">
|
||||
<input name="sort" type="number" onchange="editSort({{d.id}}, this)" value="{{d.sort}}" class="layui-input edit-sort len-short">
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var form, table, laytpl,
|
||||
repeat_flag = false, //防重复标识
|
||||
arr_id_good = [];
|
||||
$("body").off("click", ".contraction").on("click", ".contraction", function() {
|
||||
|
||||
var seckill_id = $(this).attr("data-id");
|
||||
var open = $(this).attr("data-open");
|
||||
var tr = $(this).parent().parent().parent().parent();
|
||||
var index = tr.attr("data-index");
|
||||
if (open == 1) {
|
||||
$(this).children("span").text("+");
|
||||
$(".js-list-" + index).remove();
|
||||
} else {
|
||||
$(this).children("span").text("-");
|
||||
$.ajax({
|
||||
url: ns.url("seckill://shop/seckill/getSkuList"),
|
||||
data: {
|
||||
seckill_id: seckill_id
|
||||
},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
async: false,
|
||||
success: function(res) {
|
||||
var sku_list = $("#skuList").html();
|
||||
var data = {
|
||||
list: res.data,
|
||||
index: index
|
||||
};
|
||||
laytpl(sku_list).render(data, function(html) {
|
||||
tr.after(html);
|
||||
});
|
||||
layer.photos({
|
||||
photos: '.img-wrap',
|
||||
anim: 5
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
$(this).attr("data-open", (open == 0 ? 1 : 0));
|
||||
});
|
||||
|
||||
layui.use(['form', 'laytpl','laydate', 'element'], function() {
|
||||
form = layui.form;
|
||||
element = layui.element;
|
||||
laytpl = layui.laytpl;
|
||||
laydate = layui.laydate;
|
||||
form.render();
|
||||
element.on('tab(bargain_tab)', function(data) {
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: {
|
||||
'status': this.getAttribute('data-status')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
table = new Table({
|
||||
elem: '#good_list',
|
||||
url: '{:addon_url("seckill://shop/seckill/goodslist")}',
|
||||
async: false,
|
||||
parseData: function(res) {
|
||||
arr_id_good = [];
|
||||
for (var i in res.data.list) {
|
||||
arr_id_good.push(res.data.list[i].sku_id);
|
||||
}
|
||||
return {
|
||||
"code": res.code,
|
||||
"msg": res.message,
|
||||
"count": res.data.count,
|
||||
"data": res.data.list,
|
||||
};
|
||||
},
|
||||
where:{"seckill_time_id" : "{$seckill_time_id}"},
|
||||
cols: [
|
||||
[{
|
||||
type: 'checkbox',
|
||||
width: '3%',
|
||||
},{
|
||||
title: '商品',
|
||||
unresize: 'false',
|
||||
width: '18%',
|
||||
templet: '#goods_name'
|
||||
}, {
|
||||
title: '秒杀时间',
|
||||
unresize: 'false',
|
||||
width: '16%',
|
||||
templet: '#time'
|
||||
}, {
|
||||
title: '参与场次',
|
||||
unresize: 'false',
|
||||
align:"left",
|
||||
width: '18%',
|
||||
templet: '#time_label'
|
||||
}, {
|
||||
title: '秒杀价',
|
||||
unresize: 'false',
|
||||
width: '7%',
|
||||
templet: '#price'
|
||||
}, {
|
||||
title: '库存',
|
||||
unresize: 'false',
|
||||
width: '6%',
|
||||
field: 'goods_stock'
|
||||
}, {
|
||||
title: '销量',
|
||||
unresize: 'false',
|
||||
width: '6%',
|
||||
field: 'sale_num'
|
||||
}, {
|
||||
field: 'sort',
|
||||
unresize:'false',
|
||||
title: `排序<i class="iconfont iconwenhao1 required growth" style="color:#000;" title="后台商品默认排序为排序号正序排列(即排序号越小越靠前),如果序号相同,那么按照添加顺序排列,越新添加的越靠前"></i>`,
|
||||
width: '9%',
|
||||
align: 'center',
|
||||
templet: '#editSort',
|
||||
sort: true
|
||||
}, {
|
||||
title: '状态',
|
||||
unresize: 'false',
|
||||
width: '10%',
|
||||
templet: function (data) {
|
||||
if(data.status == 1){
|
||||
return '进行中'
|
||||
}else if(data.status == 0){
|
||||
return '未开始'
|
||||
}else if(data.status == 2){
|
||||
return '已过期'
|
||||
}else if(data.status == -1){
|
||||
return '已关闭(手动)'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
title: '操作',
|
||||
toolbar: '#operation',
|
||||
unresize: 'false',
|
||||
align:'right'
|
||||
}]
|
||||
],
|
||||
toolbar: '#toolbarAction'
|
||||
});
|
||||
|
||||
table.on("sort",function (obj) {
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: {
|
||||
order:obj.field,
|
||||
sort:obj.type
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//开始时间
|
||||
laydate.render({
|
||||
elem: '#start_time', //指定元素
|
||||
type: 'datetime'
|
||||
});
|
||||
//结束时间
|
||||
laydate.render({
|
||||
elem: '#end_time', //指定元素
|
||||
type: 'datetime'
|
||||
});
|
||||
|
||||
/**
|
||||
* 搜索功能
|
||||
*/
|
||||
form.on('submit(search)', function(data) {
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
where: data.field
|
||||
});
|
||||
});
|
||||
|
||||
// 监听工具栏操作
|
||||
table.toolbar(function (obj) {
|
||||
var data = obj.data;
|
||||
if(data.length <= 0) return;
|
||||
var seckillIdAll = [];
|
||||
for (var i in data){
|
||||
seckillIdAll.push(data[i].id);
|
||||
}
|
||||
|
||||
switch (obj.event) {
|
||||
case 'delete':
|
||||
deleteSeckillAll(seckillIdAll)
|
||||
break;
|
||||
case 'invalid':
|
||||
closeSeckillAll(seckillIdAll)
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
||||
//批量删除
|
||||
function deleteSeckillAll(data){
|
||||
if (repeat_flag) return false;
|
||||
repeat_flag = true;
|
||||
|
||||
layer.confirm('确定要删除商品吗?', function(index) {
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: '{:addon_url("seckill://shop/seckill/deleteGoodsAll")}',
|
||||
data: {
|
||||
"seckill_id": data
|
||||
},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
layer.msg(res.message);
|
||||
repeat_flag = false;
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}, function() {
|
||||
layer.close();
|
||||
repeat_flag = false;
|
||||
});
|
||||
}
|
||||
|
||||
//批量关闭
|
||||
function closeSeckillAll(data)
|
||||
{
|
||||
if (repeat_flag) return false;
|
||||
repeat_flag = true;
|
||||
|
||||
layer.confirm('确定要关闭商品吗?', function(index) {
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: '{:addon_url("seckill://shop/seckill/closeSeckillAll")}',
|
||||
data: {
|
||||
"seckill_id": data
|
||||
},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
layer.msg(res.message);
|
||||
repeat_flag = false;
|
||||
table.reload();
|
||||
}
|
||||
});
|
||||
}, function() {
|
||||
layer.close();
|
||||
repeat_flag = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听工具栏操作
|
||||
*/
|
||||
table.tool(function(obj) {
|
||||
var data = obj.data;
|
||||
switch (obj.event) {
|
||||
case 'delete': //查看
|
||||
delSeckill(data.id);
|
||||
break;
|
||||
case 'edit': //查看
|
||||
location.hash = ns.hash("seckill://shop/seckill/updateGoods?id=" + data.id);
|
||||
break;
|
||||
case 'select': //推广
|
||||
seckillUrl(data);
|
||||
break;
|
||||
case 'close': //关闭
|
||||
closeSeckill(data.id);
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
function delSeckill(seckill_id) {
|
||||
|
||||
if (repeat_flag) return false;
|
||||
repeat_flag = true;
|
||||
|
||||
layer.confirm('确定要删除该商品吗?', function(index) {
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: '{:addon_url("seckill://shop/seckill/deleteGoods")}',
|
||||
data: {
|
||||
"id": seckill_id
|
||||
},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
layer.msg(res.message);
|
||||
repeat_flag = false;
|
||||
|
||||
if (res.code == 0) {
|
||||
table.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, function() {
|
||||
layer.close();
|
||||
repeat_flag = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭
|
||||
*/
|
||||
function closeSeckill(seckill_id) {
|
||||
|
||||
if (repeat_flag) return false;
|
||||
repeat_flag = true;
|
||||
|
||||
layer.confirm('确定要关闭该商品吗?', function(index) {
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: '{:addon_url("seckill://shop/seckill/closeSeckill")}',
|
||||
data: {
|
||||
"seckill_id": seckill_id
|
||||
},
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
layer.msg(res.message);
|
||||
repeat_flag = false;
|
||||
|
||||
if (res.code == 0) {
|
||||
table.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, function() {
|
||||
layer.close();
|
||||
repeat_flag = false;
|
||||
});
|
||||
}
|
||||
|
||||
function seckillUrl(data){
|
||||
new PromoteShow({
|
||||
url:ns.url("seckill://shop/seckill/seckillUrl"),
|
||||
param:{seckill_id:data.id},
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
function clickAdd() {
|
||||
location.hash = ns.hash("seckill://shop/seckill/addGoods");
|
||||
}
|
||||
|
||||
function clickAddTime() {
|
||||
var data = {};
|
||||
laytpl($('#addTime').html()).render(data, function(html) {
|
||||
var index = layer.open({
|
||||
type: 1,
|
||||
title: "场次添加",
|
||||
area: ['700px', '300px'],
|
||||
btn: ['保存', '返回'],
|
||||
content: html,
|
||||
yes: function(index, layero) {
|
||||
var data = {};
|
||||
data.name = $('#add_time_name').val();
|
||||
if (!data.name) {
|
||||
layer.msg("秒杀场次名称不能为空");
|
||||
return false;
|
||||
}
|
||||
if (!$('#add_start_time').val()) {
|
||||
layer.msg("开始时间不能为空");
|
||||
return false;
|
||||
}
|
||||
if (!$('#add_end_time').val()) {
|
||||
layer.msg("结束时间不能为空");
|
||||
return false;
|
||||
}
|
||||
data.start_hour = $('#add_start_time').val().split(":")[0];
|
||||
data.start_minute = $('#add_start_time').val().split(":")[1];
|
||||
data.start_second = $('#add_start_time').val().split(":")[2];
|
||||
|
||||
data.end_hour = $('#add_end_time').val().split(":")[0];
|
||||
data.end_minute = $('#add_end_time').val().split(":")[1];
|
||||
data.end_second = $('#add_end_time').val().split(":")[2];
|
||||
|
||||
if (repeat_flag) return;
|
||||
repeat_flag = true;
|
||||
$.ajax({
|
||||
url: ns.url("seckill://shop/seckill/add"),
|
||||
data: data,
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
repeat_flag = false;
|
||||
if (res.code == 0) {
|
||||
layer.msg(res.message, {}, function() {
|
||||
layer.close(index);
|
||||
});
|
||||
} else {
|
||||
layer.msg(res.message);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#add_end_time',
|
||||
type: 'time'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#add_start_time',
|
||||
type: 'time'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 监听单元格编辑
|
||||
function editSort(id, event){
|
||||
var data = $(event).val();
|
||||
|
||||
if (data == '') {
|
||||
$(event).val(0);
|
||||
data = 0;
|
||||
}
|
||||
|
||||
if(!new RegExp("^-?[0-9]\\d*$").test(data)){
|
||||
layer.msg("排序号只能是整数");
|
||||
return ;
|
||||
}
|
||||
if(data<0){
|
||||
layer.msg("排序号必须大于0");
|
||||
return ;
|
||||
}
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: ns.url("seckill://shop/seckill/seckillSort"),
|
||||
data: {
|
||||
sort: data,
|
||||
id: id
|
||||
},
|
||||
dataType: 'JSON',
|
||||
success: function(res) {
|
||||
layer.msg(res.message);
|
||||
if(res.code==0){
|
||||
table.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
104
addon/seckill/shop/view/seckill/lists.html
Executable file
@@ -0,0 +1,104 @@
|
||||
<div class="single-filter-box">
|
||||
<button class="layui-btn" onclick="clickAdd()">添加秒杀场次</button>
|
||||
</div>
|
||||
|
||||
<table id="seckill_list" lay-filter="seckill_list"></table>
|
||||
|
||||
<!-- 操作 -->
|
||||
<script type="text/html" id="operation">
|
||||
<div class="table-btn">
|
||||
<a class="layui-btn" lay-event="check">查看商品</a>
|
||||
<a class="layui-btn" lay-event="edit">编辑</a>
|
||||
<a class="layui-btn" lay-event="delete">删除</a>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
layui.use('form', function() {
|
||||
var repeat_flag = false; //防重复标识
|
||||
|
||||
var table = new Table({
|
||||
elem: '#seckill_list',
|
||||
url: ns.url("seckill://shop/seckill/lists"),
|
||||
parseData: function(res) { //res 即为原始返回的数据
|
||||
return {
|
||||
"code": res.code, //解析接口状态
|
||||
"msg": res.message,
|
||||
"data": res.data
|
||||
};
|
||||
},
|
||||
cols: [
|
||||
[{
|
||||
field: 'name',
|
||||
title: '时段名称',
|
||||
unresize: 'false',
|
||||
width: '20%'
|
||||
}, {
|
||||
field: 'seckill_start_time_show',
|
||||
title: '开始时间',
|
||||
unresize: 'false',
|
||||
width: '20%'
|
||||
}, {
|
||||
field: 'seckill_end_time_show',
|
||||
title: '结束时间',
|
||||
unresize: 'false',
|
||||
width: '20%'
|
||||
},{
|
||||
field: 'goods_num',
|
||||
title: '商品数量',
|
||||
unresize: 'false',
|
||||
width: '20%',
|
||||
}, {
|
||||
title: '操作',
|
||||
toolbar: '#operation',
|
||||
unresize: 'false',
|
||||
align:'right'
|
||||
}]
|
||||
],
|
||||
page: false
|
||||
});
|
||||
|
||||
/**
|
||||
* 监听工具栏操作
|
||||
*/
|
||||
table.tool(function(obj) {
|
||||
var data = obj.data;
|
||||
switch (obj.event) {
|
||||
case 'check': //查看
|
||||
location.hash = ns.hash("seckill://shop/seckill/goodslist?seckill_time_id=" + data.id);
|
||||
break;
|
||||
case 'delete': //删除
|
||||
layer.confirm('确定要删除该场次吗?', function(index) {
|
||||
if (repeat_flag) return false;
|
||||
repeat_flag = true;
|
||||
layer.close(index);
|
||||
$.ajax({
|
||||
url: ns.url("seckill://shop/seckill/delete?id=" + data.id),
|
||||
data: data,
|
||||
dataType: 'JSON',
|
||||
type: 'POST',
|
||||
success: function(res) {
|
||||
layer.msg(res.message);
|
||||
repeat_flag = false;
|
||||
if (res.code == 0) {
|
||||
table.reload({
|
||||
page: {
|
||||
curr: 1
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'edit': //编辑
|
||||
location.hash = ns.hash("seckill://shop/seckill/edit?id=" + data.id);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function clickAdd() {
|
||||
location.hash = ns.hash("seckill://shop/seckill/add");
|
||||
}
|
||||
</script>
|
||||