Browse Source

feat:版本

super-yimizi 2 months ago
parent
commit
ad0a04cb67

+ 1 - 1
addons/betterform/config.php

@@ -65,7 +65,7 @@ return [
         'title' => '弹窗宽高',
         'title' => '弹窗宽高',
         'type' => 'string',
         'type' => 'string',
         'content' => [],
         'content' => [],
-        'value' => '["60%", "100%"]',
+        'value' => '["90%", "90%"]',
         'rule' => 'required',
         'rule' => 'required',
         'msg' => '',
         'msg' => '',
         'tip' => '',
         'tip' => '',

+ 36 - 0
addons/shop/config.php

@@ -14,6 +14,42 @@ return [
         'extend'  => '',
         'extend'  => '',
     ],
     ],
     [
     [
+        'name'    => 'workinghours',
+        'title'   => '工作时间',
+        'type'    => 'string',
+        'content' => [],
+        'value'   => '9:00-18:00',
+        'rule'    => 'required',
+        'msg'     => '',
+        'tip'     => '',
+        'ok'      => '',
+        'extend'  => '',
+    ],
+    [
+        'name'    => 'email',
+        'title'   => '客服邮箱',
+        'type'    => 'string',
+        'content' => [],
+        'value'   => '1234567890@qq.com',
+        'rule'    => 'required',
+        'msg'     => '',
+        'tip'     => '',
+        'ok'      => '',
+        'extend'  => '',
+    ],
+    [
+        'name'    => 'company',
+        'title'   => '公司名称',
+        'type'    => 'string',
+        'content' => [],
+        'value'   => '公司名称',
+        'rule'    => 'required',
+        'msg'     => '',
+        'tip'     => '',
+        'ok'      => '',
+        'extend'  => '',
+    ],
+    [
         'name'    => 'icpbeian',
         'name'    => 'icpbeian',
         'title'   => 'ICP备案号',
         'title'   => 'ICP备案号',
         'type'    => 'string',
         'type'    => 'string',

+ 155 - 3
application/admin/controller/marketing/Discount.php

@@ -3,7 +3,11 @@
 namespace app\admin\controller\marketing;
 namespace app\admin\controller\marketing;
 
 
 use app\common\controller\Backend;
 use app\common\controller\Backend;
-
+use think\Db;
+use Exception;
+use think\exception\DbException;
+use think\exception\PDOException;
+use think\exception\ValidateException;
 /**
 /**
  * 营销活动表(整体活动)
  * 营销活动表(整体活动)
  *
  *
@@ -21,11 +25,70 @@ class Discount extends Backend
     public function _initialize()
     public function _initialize()
     {
     {
         parent::_initialize();
         parent::_initialize();
-        $this->model = new \app\admin\model\marketing\Discount;
+        $this->model = new \app\admin\model\marketing\discount\Discount;
 
 
     }
     }
 
 
-
+    /**
+     * 规格折扣设置
+     */
+    public function spec_discount()
+    {
+        $goods_id = $this->request->get('goods_id');
+        if (!$goods_id) {
+            $this->error('参数错误');
+        }
+        
+        if ($this->request->isAjax()) {
+            // 处理提交的数据
+            $specs = $this->request->post('specs', []);
+            if ($specs) {
+                $result = [
+                    'goodsId' => $goods_id,
+                    'specs' => $specs
+                ];
+                $this->success('设置成功', null, $result);
+            }
+            $this->error('提交数据失败');
+        }
+        
+        // 获取商品信息
+        $goods = Db::name('shop_goods')->where('id', $goods_id)->find();
+        if (!$goods) {
+            $this->error('商品不存在');
+        }
+        
+        // 获取规格信息
+        $goods_skus = Db::name('shop_goods_sku')
+            ->where('goods_id', $goods_id)
+            ->select();
+            
+        // 获取规格属性名称和值
+        $sku_specs = [];
+        foreach ($goods_skus as &$sku) {
+            $sku_id_arr = explode(',', $sku['sku_id']);
+            
+            // 查询规格名称和值
+            $spec_values = Db::name('shop_goods_sku_spec')
+                ->alias('p')
+                ->field('p.*, sp.name as spec_name, sv.value as spec_value')
+                ->join('shop_spec sp', 'sp.id=p.spec_id', 'LEFT')
+                ->join('shop_spec_value sv', 'sv.id=p.spec_value_id', 'LEFT')
+                ->where('p.id', 'in', $sku_id_arr)
+                ->select();
+                
+            $specs_text = [];
+            foreach ($spec_values as $spec) {
+                $specs_text[] = $spec['spec_name'] . ':' . $spec['spec_value'];
+            }
+            $sku['specs_text'] = implode(' | ', $specs_text);
+        }
+        
+        $this->view->assign('goods', $goods);
+        $this->view->assign('skus', $goods_skus);
+        
+        return $this->view->fetch();
+    }
 
 
     /**
     /**
      * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
      * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
@@ -33,5 +96,94 @@ class Discount extends Backend
      * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
      * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
      */
      */
 
 
+       /**
+     * 添加
+     *
+     * @return string
+     * @throws \think\Exception
+     */
+    public function add()
+    {
+        if (false === $this->request->isPost()) {
+            return $this->view->fetch();
+        }
+        $params = $this->request->post('row/a');
+        if (empty($params)) {
+            $this->error(__('Parameter %s can not be empty', ''));
+        }
+        $params = $this->preExcludeFields($params);
+
+        if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
+            $params[$this->dataLimitField] = $this->auth->id;
+        }
+        $result = false;
+        Db::startTrans();
+        try {
+            //是否采用模型验证
+            if ($this->modelValidate) {
+                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
+                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
+                $this->model->validateFailException()->validate($validate);
+            }
+            $result = $this->model->allowField(true)->save($params);
+            Db::commit();
+        } catch (ValidateException|PDOException|Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result === false) {
+            $this->error(__('No rows were inserted'));
+        }
+        $this->success();
+    }
+
+    /**
+     * 编辑
+     *
+     * @param $ids
+     * @return string
+     * @throws DbException
+     * @throws \think\Exception
+     */
+    public function edit($ids = null)
+    {
+        $row = $this->model->get($ids);
+        if (!$row) {
+            $this->error(__('No Results were found'));
+        }
+        $adminIds = $this->getDataLimitAdminIds();
+        if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
+            $this->error(__('You have no permission'));
+        }
+        if (false === $this->request->isPost()) {
+            $this->view->assign('row', $row);
+            return $this->view->fetch();
+        }
+        $params = $this->request->post('row/a');
+        if (empty($params)) {
+            $this->error(__('Parameter %s can not be empty', ''));
+        }
+        $params = $this->preExcludeFields($params);
+        $result = false;
+        Db::startTrans();
+        try {
+            //是否采用模型验证
+            if ($this->modelValidate) {
+                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
+                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
+                $row->validateFailException()->validate($validate);
+            }
+            $result = $row->allowField(true)->save($params);
+            Db::commit();
+        } catch (ValidateException|PDOException|Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if (false === $result) {
+            $this->error(__('No rows were updated'));
+        }
+        $this->success();
+    }
+
 
 
 }
 }

+ 25 - 0
application/admin/controller/shop/Goods.php

@@ -331,5 +331,30 @@ class Goods extends Backend
         return $this->view->fetch();
         return $this->view->fetch();
     }
     }
 
 
+    /**
+     * 根据ID批量获取商品信息
+     */
+    public function get_goods_by_ids()
+    {
+        $ids = $this->request->request('ids');
+        if (!$ids) {
+            $this->error('请选择商品');
+        }
+        
+        $ids = explode(',', $ids);
+        $list = $this->model
+            ->with(['Category'])
+            ->where('id', 'in', $ids)
+            ->select();
+            
+        // 处理图片URL
+        foreach ($list as &$item) {
+            if ($item['image']) {
+                $item['image'] = cdnurl($item['image'], true);
+            }
+        }
+        
+        return json($list);
+    }
 
 
 }
 }

+ 2 - 2
application/admin/model/marketing/Discount.php → application/admin/model/marketing/discount/Discount.php

@@ -1,6 +1,6 @@
 <?php
 <?php
 
 
-namespace app\admin\model\marketing;
+namespace app\admin\model\marketing\discount;
 
 
 use think\Model;
 use think\Model;
 use traits\model\SoftDelete;
 use traits\model\SoftDelete;
@@ -13,7 +13,7 @@ class Discount extends Model
     
     
 
 
     // 表名
     // 表名
-    protected $table = 'shop_activity';
+    protected $table = 'shop_discount';
     
     
     // 自动写入时间戳字段
     // 自动写入时间戳字段
     protected $autoWriteTimestamp = 'integer';
     protected $autoWriteTimestamp = 'integer';

+ 9 - 1
application/admin/view/marketing/discount/add.html

@@ -59,7 +59,7 @@
             <div id="selected-goods-container" class="margin-top-10"></div>
             <div id="selected-goods-container" class="margin-top-10"></div>
             <input type="hidden" name="row[goods_ids]" id="goods-ids" value="">
             <input type="hidden" name="row[goods_ids]" id="goods-ids" value="">
             <input type="hidden" name="row[discount_data]" id="discount-data" value="">
             <input type="hidden" name="row[discount_data]" id="discount-data" value="">
-            <p class="help-block">提示:秒杀价格将按照设置的折扣计算,折扣范围0.1~10折</p>
+            <p class="help-block">提示:折扣价格将按照设置的折扣计算,折扣范围0.1~10折</p>
         </div>
         </div>
     </div>
     </div>
     <div class="panel panel-default" style="margin-bottom: 20px;">
     <div class="panel panel-default" style="margin-bottom: 20px;">
@@ -129,3 +129,11 @@
     </div>
     </div>
 </form>
 </form>
 
 
+<!-- 商品表格模板 -->
+<script id="goodsTableTpl" type="text/html">
+    <div class="table-responsive">
+        <table id="selected-goods-table" class="table table-striped table-bordered table-hover">
+        </table>
+    </div>
+</script>
+

+ 94 - 85
application/admin/view/marketing/discount/edit.html

@@ -1,131 +1,140 @@
 <form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
 <form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
 
 
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name|htmlentities}">
-        </div>
-    </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-title" data-rule="required" class="form-control" name="row[title]" type="text" value="{$row.title|htmlentities}">
-        </div>
-    </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Desc')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <textarea id="c-desc" class="form-control " rows="5" name="row[desc]" cols="50">{$row.desc|htmlentities}</textarea>
+    <div class="panel panel-default" style="margin-bottom: 20px;">
+        <div class="panel-heading" style="padding: 10px 15px; border-left: 4px solid #18bc9c;">
+            <h3 class="panel-title" style="font-size: 14px; font-weight: bold;">基本信息</h3>
         </div>
         </div>
     </div>
     </div>
+
     <div class="form-group">
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">{:__('活动名称')}:</label>
         <div class="col-xs-12 col-sm-8">
         <div class="col-xs-12 col-sm-8">
             <div class="input-group">
             <div class="input-group">
-                <input id="c-image" data-rule="required" class="form-control" size="50" name="row[image]" type="text" value="{$row.image|htmlentities}">
-                <div class="input-group-addon no-border no-padding">
-                    <span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
-                    <span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
-                </div>
-                <span class="msg-box n-right" for="c-image"></span>
+                <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name|htmlentities}" maxlength="20">
+                <span class="input-group-addon" id="name-count">0/20</span>
+                <span class="msg-box n-right" for="c-name" style="position:absolute;display:inline-block;margin-top:5px;"></span>
             </div>
             </div>
-            <ul class="row list-inline faupload-preview" id="p-image"></ul>
-        </div>
-    </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-type" data-rule="required" class="form-control" name="row[type]" type="text" value="{$row.type|htmlentities}">
-        </div>
-    </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Goods_type')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-goods_type" data-rule="required" class="form-control" name="row[goods_type]" type="text" value="{$row.goods_type|htmlentities}">
-        </div>
-    </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Goods_info')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <textarea id="c-goods_info" class="form-control " rows="5" name="row[goods_info]" cols="50">{$row.goods_info|htmlentities}</textarea>
-        </div>
-    </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Class')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-class" data-rule="required" class="form-control" name="row[class]" type="text" value="{$row.class|htmlentities}">
-        </div>
-    </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Class_category')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-class_category" data-rule="required" class="form-control" name="row[class_category]" type="text" value="{$row.class_category|htmlentities}">
         </div>
         </div>
     </div>
     </div>
+
     <div class="form-group">
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Relate_member')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">{:__('活动期限')}:</label>
         <div class="col-xs-12 col-sm-8">
         <div class="col-xs-12 col-sm-8">
-            <input id="c-relate_member" data-rule="required" class="form-control" name="row[relate_member]" type="text" value="{$row.relate_member|htmlentities}">
+            <div class="input-group">
+                <input id="c-start_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[start_time]" type="text" value="{:$row.start_time?datetime($row.start_time):''}" placeholder="开始时间">
+                <span class="input-group-addon">~</span>
+                <input id="c-end_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[end_time]" type="text" value="{:$row.end_time?datetime($row.end_time):''}" placeholder="结束时间">
+            </div>
         </div>
         </div>
     </div>
     </div>
+
     <div class="form-group">
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Active_value')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <textarea id="c-active_value" class="form-control " rows="5" name="row[active_value]" cols="50">{$row.active_value|htmlentities}</textarea>
+        <label class="control-label col-xs-12 col-sm-2">{:__('活动渠道')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <label class="checkbox-inline">
+                <input type="checkbox" name="row[channels][]" value="wechat" {in name="'wechat'|explode($row.channels)" value="wechat"}checked{/in}> 微信公众号
+            </label>
+            <label class="checkbox-inline">
+                <input type="checkbox" name="row[channels][]" value="miniapp" {in name="'miniapp'|explode($row.channels)" value="miniapp"}checked{/in}> 微信小程序
+            </label>
+            <label class="checkbox-inline">
+                <input type="checkbox" name="row[channels][]" value="h5" {in name="'h5'|explode($row.channels)" value="h5"}checked{/in}> 手机浏览器H5
+            </label>
+            <label class="checkbox-inline">
+                <input type="checkbox" name="row[channels][]" value="tiktok" {in name="'tiktok'|explode($row.channels)" value="tiktok"}checked{/in}> 头条/抖音小程序
+            </label>
+            <label class="checkbox-inline">
+                <input type="checkbox" name="row[channels][]" value="app" {in name="'app'|explode($row.channels)" value="app"}checked{/in}> APP
+            </label>
+            <label class="checkbox-inline">
+                <input type="checkbox" name="row[channels][]" value="pc" {in name="'pc'|explode($row.channels)" value="pc"}checked{/in}> PC版
+            </label>
         </div>
         </div>
     </div>
     </div>
+
     <div class="form-group">
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Start_time')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">{:__('选择商品')}:</label>
         <div class="col-xs-12 col-sm-8">
         <div class="col-xs-12 col-sm-8">
-            <input id="c-start_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[start_time]" type="text" value="{:$row.start_time?datetime($row.start_time):''}">
+            <button type="button" id="select-goods" class="btn btn-primary">选择商品</button>
+            <div id="selected-goods-container" class="margin-top-10"></div>
+            <input type="hidden" name="row[goods_ids]" id="goods-ids" value="{$row.goods_ids|htmlentities}">
+            <input type="hidden" name="row[discount_data]" id="discount-data" value="{$row.discount_data|htmlentities}">
+            <p class="help-block">提示:折扣价格将按照设置的折扣计算,折扣范围0.1~10折</p>
         </div>
         </div>
     </div>
     </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('End_time')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-end_time" data-rule="required" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[end_time]" type="text" value="{:$row.end_time?datetime($row.end_time):''}">
+    
+    <div class="panel panel-default" style="margin-bottom: 20px;">
+        <div class="panel-heading" style="padding: 10px 15px; border-left: 4px solid #18bc9c;">
+            <h3 class="panel-title" style="font-size: 14px; font-weight: bold;">规则设置</h3>
         </div>
         </div>
     </div>
     </div>
     <div class="form-group">
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Activity_status')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">{:__('活动主图')}:</label>
         <div class="col-xs-12 col-sm-8">
         <div class="col-xs-12 col-sm-8">
-            <input id="c-activity_status" data-rule="required" class="form-control" name="row[activity_status]" type="text" value="{$row.activity_status|htmlentities}">
+            <div class="input-group">
+                <input id="c-image" data-rule="required" class="form-control" size="50" name="row[image]" type="text" value="{$row.image|htmlentities}">
+                <div class="input-group-addon no-border no-padding">
+                    <span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+                    <span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
+                </div>
+                <span class="msg-box n-right" for="c-image"></span>
+            </div>
+            <ul class="row list-inline faupload-preview" id="p-image"></ul>
+            <p class="help-block">活动落地页的顶部图片,建议尺寸750px*340px</p>
         </div>
         </div>
     </div>
     </div>
+
     <div class="form-group">
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Active_order_money')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">{:__('限购次数')}:</label>
         <div class="col-xs-12 col-sm-8">
         <div class="col-xs-12 col-sm-8">
-            <input id="c-active_order_money" data-rule="required" class="form-control" step="0.01" name="row[active_order_money]" type="number" value="{$row.active_order_money|htmlentities}">
+            <div style="margin-bottom: 15px;">
+                <label class="radio-inline" style="margin-right: 20px;">
+                    <input type="radio" name="row[purchase_limit_type]" value="0" {eq name="row.purchase_limit_type" value="0"}checked{/eq}> 不限制
+                </label>
         </div>
         </div>
-    </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Active_order_num')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-active_order_num" data-rule="required" class="form-control" name="row[active_order_num]" type="number" value="{$row.active_order_num|htmlentities}">
+            
+            <div style="margin-bottom: 15px; display: flex; align-items: center;">
+                <label class="radio-inline" style="margin-right: 20px; min-width: 220px;">
+                    <input type="radio" name="row[purchase_limit_type]" value="1" {eq name="row.purchase_limit_type" value="1"}checked{/eq}> 活动期内每人最多购买
+                </label>
+                <div style="display: flex; align-items: center;">
+                    <input type="number" class="form-control" name="row[purchase_limit_total]" placeholder="请输入" min="1" {eq name="row.purchase_limit_type" value="1"}{else}disabled{/eq} style="width: 300px;" value="{$row.purchase_limit_total|default=''}">
+                    <span style="margin-left: 10px;">件</span>
         </div>
         </div>
     </div>
     </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Active_member_num')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-active_member_num" data-rule="required" class="form-control" name="row[active_member_num]" type="number" value="{$row.active_member_num|htmlentities}">
+            
+            <div style="margin-bottom: 15px; display: flex; align-items: center;">
+                <label class="radio-inline" style="margin-right: 20px; min-width: 220px;">
+                    <input type="radio" name="row[purchase_limit_type]" value="2" {eq name="row.purchase_limit_type" value="2"}checked{/eq}> 活动期内每人每天最多购买
+                </label>
+                <div style="display: flex; align-items: center;">
+                    <input type="number" class="form-control" name="row[purchase_limit_daily]" placeholder="请输入" min="1" {eq name="row.purchase_limit_type" value="2"}{else}disabled{/eq} style="width: 300px;" value="{$row.purchase_limit_daily|default=''}">
+                    <span style="margin-left: 10px;">件</span>
         </div>
         </div>
     </div>
     </div>
-    <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Active_success_num')}:</label>
-        <div class="col-xs-12 col-sm-8">
-            <input id="c-active_success_num" data-rule="required" class="form-control" name="row[active_success_num]" type="number" value="{$row.active_success_num|htmlentities}">
         </div>
         </div>
     </div>
     </div>
     <div class="form-group">
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Is_del')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">{:__('活动描述')}:</label>
         <div class="col-xs-12 col-sm-8">
         <div class="col-xs-12 col-sm-8">
-            <input id="c-is_del" data-rule="required" class="form-control" name="row[is_del]" type="number" value="{$row.is_del|htmlentities}">
+            <textarea id="c-desc" class="form-control editor" rows="5" name="row[desc]" cols="50">{$row.desc|htmlentities}</textarea>
         </div>
         </div>
     </div>
     </div>
+
     <div class="form-group layer-footer">
     <div class="form-group layer-footer">
         <label class="control-label col-xs-12 col-sm-2"></label>
         <label class="control-label col-xs-12 col-sm-2"></label>
         <div class="col-xs-12 col-sm-8">
         <div class="col-xs-12 col-sm-8">
-            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+            <button type="submit" class="btn btn-primary btn-embossed">{:__('提交')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('重置')}</button>
         </div>
         </div>
     </div>
     </div>
 </form>
 </form>
+
+<!-- 商品表格模板 -->
+<script id="goodsTableTpl" type="text/html">
+    <div class="table-responsive">
+        <table id="selected-goods-table" class="table table-striped table-bordered table-hover">
+        </table>
+    </div>
+</script>
+

+ 97 - 0
application/admin/view/marketing/discount/spec_discount.html

@@ -0,0 +1,97 @@
+<div class="panel panel-default panel-intro">
+    <div class="panel-heading">
+        <div class="panel-lead"><em>{:__('规格折扣设置')}</em></div>
+    </div>
+    <div class="panel-body">
+        <div class="row">
+            <div class="col-md-12">
+                <div class="box box-success">
+                    <div class="box-header with-border">
+                        <h3 class="box-title">{$goods.title}</h3>
+                    </div>
+                    <div class="box-body">
+                        <div class="alert alert-info">
+                            <p>设置多规格商品的每个规格的折扣,折扣范围为0.1~10折</p>
+                            <!-- <p>原价:<strong>¥{$goods.price}</strong> | 库存:<strong>{$goods.stocks}</strong></p> -->
+                        </div>
+
+                        <div class="batch-setting-box" style="background: #f9f9f9; padding: 15px; margin-bottom: 20px; border-radius: 5px;">
+                            <div class="row">
+                                <div class="col-md-12">
+                                    <h4 style="margin-top: 0; margin-bottom: 15px;">批量设置:</h4>
+                                </div>
+                            </div>
+                            <div class="row">
+                                <div class="col-md-3">
+                                    <label>
+                                        <input type="checkbox" id="batch-participate" value="1"> 参与折扣
+                                    </label>
+                                </div>
+                                <div class="col-md-5">
+                                    <div class="input-group">
+                                        <input type="number" class="form-control" id="batch-discount" value="9" min="0.1" max="10" step="0.1">
+                                        <span class="input-group-addon">折</span>
+                                        <span class="input-group-btn">
+                                            <button class="btn btn-info" type="button" id="apply-batch">应用</button>
+                                        </span>
+                                    </div>
+                                </div>
+                                <div class="col-md-4">
+                                    <div class="batch-price-info" style="line-height: 34px;"></div>
+                                </div>
+                            </div>
+                        </div>
+
+                        <form id="spec-discount-form" class="form-horizontal" role="form">
+                            <table class="table table-striped table-hover">
+                                <thead>
+                                    <tr>
+                                        <th width="15%">规格</th>
+                                        <th width="20%">销售价</th>
+                                        <th width="15%">库存</th>
+                                        <th width="15%">参与折扣</th>
+                                        <th width="10%">折扣</th>
+                                        <th width="10%">折后价</th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    {foreach $skus as $sku}
+                                    <tr data-id="{$sku.id}" data-price="{$sku.price}" data-stocks="{$sku.stocks}">
+                                        <td style="vertical-align: middle;">{$sku.specs_text}</td>
+                                        <td style="vertical-align: middle;">¥{$sku.price}</td>
+                                        <td style="vertical-align: middle;">{$sku.stocks}</td>
+                                        <td>
+                                            <input type="checkbox" class="participate-checkbox" name="specs[{$sku.id}][participate]" value="1">
+                                        </td>
+                                        <td>
+                                            <div class="input-group">
+                                                <input type="number" class="form-control sku-discount" name="specs[{$sku.id}][discount]" value="9" min="0.1" max="10" step="0.1" data-price="{$sku.price}" disabled>
+                                                <span class="input-group-addon">折</span>
+                                            </div>
+                                        </td>
+                                        <td>
+                                            <span class="discount-price">¥{:number_format($sku.price * 0.9, 2)}</span>
+                                        </td>
+                                    </tr>
+                                    {/foreach}
+                                </tbody>
+                            </table>
+                        </form>
+                    </div>
+                    <div class="box-footer">
+                        <div class="col-md-offset-2">
+                            <button type="button" class="btn btn-primary btn-embossed btn-confirm">{:__('确认')}</button>
+                            <button type="reset" class="btn btn-default btn-embossed">{:__('重置')}</button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    require(['backend/marketing/discount'], function (Controller) {
+        Controller.spec_discount();
+    });
+</script> 

+ 11 - 6
application/admin/view/shop/goods/select.html

@@ -1,9 +1,5 @@
 <div class="panel panel-default panel-intro">
 <div class="panel panel-default panel-intro">
-
- 
-
-
-    <div class="panel-body">
+    <div class="panel-body" style="padding: 0;">
         <div id="myTabContent" class="tab-content">
         <div id="myTabContent" class="tab-content">
             <div class="tab-pane fade active in" id="one">
             <div class="tab-pane fade active in" id="one">
                 <div class="widget-body no-padding">
                 <div class="widget-body no-padding">
@@ -21,7 +17,7 @@
                     <div class="form-group layer-footer">
                     <div class="form-group layer-footer">
                         <label class="control-label col-xs-12 col-sm-2"></label>
                         <label class="control-label col-xs-12 col-sm-2"></label>
                         <div class="col-xs-12 col-sm-8">
                         <div class="col-xs-12 col-sm-8">
-                            <button type="submit" class="btn btn-success btn-goods-select btn-embossed">{:__('OK')}</button>
+                            <button type="button" class="btn btn-success btn-goods-select btn-embossed">{:__('确认选择')}</button>
                             <!-- <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> -->
                             <!-- <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> -->
                         </div>
                         </div>
                     </div>
                     </div>
@@ -31,3 +27,12 @@
         </div>
         </div>
     </div>
     </div>
 </div>
 </div>
+
+<style>
+.bootstrap-table .fixed-table-container {
+    height: calc(100vh - 180px);
+}
+.panel-body {
+    padding: 0 !important;
+}
+</style>

+ 31 - 17
application/api/controller/Common.php

@@ -17,7 +17,8 @@ use app\common\model\Block;
 use app\common\model\Category;
 use app\common\model\Category;
 use app\common\model\SearchLog;
 use app\common\model\SearchLog;
 use app\common\Enum\StatusEnum;
 use app\common\Enum\StatusEnum;
-
+use app\common\Enum\FeedbackEnum;
+use app\common\Enum\UserEnum;
 /**
 /**
  * 公共接口
  * 公共接口
  */
  */
@@ -124,36 +125,49 @@ class Common extends Api
             'defaultpaytype' => $defaultPaytype,
             'defaultpaytype' => $defaultPaytype,
             '__token__'      => $this->request->token()
             '__token__'      => $this->request->token()
         ];
         ];
-
-        //焦点图
-        // $bannerList = [];
-        // $list = Block::getBlockListByName('uniappfocus', 5);
-        // foreach ($list as $index => $item) {
-        //     $bannerList[] = ['image' => cdnurl($item['image'], true), 'url' => $item['url'], 'title' => $item['title']];
-        // }
-        // $config['swiper'] = $bannerList;
-
         $config['order_timeout'] = Config::get('shop.order_timeout');
         $config['order_timeout'] = Config::get('shop.order_timeout');
         $config['sitename'] = Config::get('shop.sitename');
         $config['sitename'] = Config::get('shop.sitename');
+        // 公告
         $config['notice'] = Config::get('shop.notice');
         $config['notice'] = Config::get('shop.notice');
+        // 手机号 
         $config['phone'] = Config::get('shop.phone');
         $config['phone'] = Config::get('shop.phone');
+        // 工作时间
+        $config['workinghours'] = Config::get('shop.workinghours');
+        // 客服邮箱
+        $config['email'] = Config::get('shop.email');
+        // 公司名称
+        $config['company'] = Config::get('shop.company');
+        // 站点logo
+        $config['sitelogo'] = cdnurl(Config::get('shop.sitelogo'), true);
+        // 公安备案
+        $config['gwabeian'] = Config::get('shop.gwabeian');
+        // icp备案
+        $config['icpbeian'] = Config::get('shop.icpbeian');
+        // 物流类型
         $config['logisticstype'] = Config::get('shop.logisticstype');
         $config['logisticstype'] = Config::get('shop.logisticstype');
-
+        // 分类模式
         $config['category_mode'] = (int)Config::get('shop.category_mode');
         $config['category_mode'] = (int)Config::get('shop.category_mode');
+        // 积分
         $config['money_score'] = Config::get('shop.money_score');
         $config['money_score'] = Config::get('shop.money_score');
+        // 评论积分
         $config['comment_score'] = Config::get('shop.comment_score');
         $config['comment_score'] = Config::get('shop.comment_score');
-
+        // 默认商品图片 
         $config['default_goods_img'] = cdnurl(Config::get('shop.default_goods_img'), true);
         $config['default_goods_img'] = cdnurl(Config::get('shop.default_goods_img'), true);
+        // 默认分类图片
         $config['default_category_img'] = cdnurl(Config::get('shop.default_category_img'), true);
         $config['default_category_img'] = cdnurl(Config::get('shop.default_category_img'), true);
+        // 热门搜索关键词
+        $config['hot_keyword'] = SearchLog::order('nums desc')->limit(10)->column('keywords');
+
 
 
-        $config['navigate'] = Navigation::tableList();
-        $config['brands'] = \addons\shop\model\Brand::field('id,name')->order('weigh desc')->select();
+        // $config['navigate'] = Navigation::tableList();
+        // $config['brands'] = \addons\shop\model\Brand::field('id,name')->order('weigh desc')->select();
 
 
         //消息订阅模板id
         //消息订阅模板id
         $config['tpl_ids'] = \addons\shop\model\TemplateMsg::getTplIds();
         $config['tpl_ids'] = \addons\shop\model\TemplateMsg::getTplIds();
-
-        //热门搜索关键词
-        $config['hot_keyword'] = SearchLog::order('nums desc')->limit(10)->column('keywords');
+        // 反馈类型
+        $config['feedback_type'] = FeedbackEnum::getFeedbackTypeMap();
+        // 性别
+        $config['gender'] = UserEnum::getGenderMap();
 
 
         //合并主题样式,判断是否预览模式
         //合并主题样式,判断是否预览模式
         $isPreview = stripos($this->request->SERVER("HTTP_REFERER"), "mode=preview") !== false;
         $isPreview = stripos($this->request->SERVER("HTTP_REFERER"), "mode=preview") !== false;

+ 477 - 63
public/assets/js/backend/marketing/discount.js

@@ -1,4 +1,4 @@
-define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) {
 
 
     var Controller = {
     var Controller = {
         index: function () {
         index: function () {
@@ -117,86 +117,147 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
 
 
         add: function () {
         add: function () {
             Controller.api.bindevent();
             Controller.api.bindevent();
-            
             // 选择商品功能
             // 选择商品功能
             $('#select-goods').on('click', function() {
             $('#select-goods').on('click', function() {
                 Fast.api.open('shop/goods/select', '选择商品', {
                 Fast.api.open('shop/goods/select', '选择商品', {
+                    area: ['95%', '90%'],
                     callback: function(data) {
                     callback: function(data) {
                         if (data && data.length > 0) {
                         if (data && data.length > 0) {
                             var goodsIds = [];
                             var goodsIds = [];
                             
                             
-                            // 清空容器
-                            $('#selected-goods-container').empty();
-                            
-                            // 创建表格结构
-                            var tableHtml = 
-                                '<table class="table table-striped table-bordered table-hover">' +
-                                '<thead>' +
-                                '<tr>' +
-                                '<th width="30%">商品</th>' +
-                                '<th width="10%">价格</th>' +
-                                '<th width="10%">现库存</th>' +
-                                '<th width="15%">折扣</th>' +
-                                '<th>折后价</th>' +
-                                '<th width="10%">操作</th>' +
-                                '</tr>' +
-                                '</thead>' +
-                                '<tbody>';
-                                
-                            // 添加商品行
+                            // 收集商品ID
                             $.each(data, function(index, item) {
                             $.each(data, function(index, item) {
                                 goodsIds.push(item.id);
                                 goodsIds.push(item.id);
-                                var specTypeText = item.spectype == 0 ? "单规格" : "多规格";
-                                
-                                // 计算默认折扣价(默认9折)
-                                var defaultDiscount = 9;
-                                var discountPrice = (item.price * defaultDiscount / 10).toFixed(2);
-                                
-                                tableHtml += '<tr data-id="' + item.id + '" data-spectype="' + item.spectype + '">' +
-                                    '<td>' +
-                                    '<div class="goods-item">' +
-                                    '<img src="' + item.image + '" style="width:60px;height:60px;margin-right:10px;" class="pull-left img-thumbnail">' +
-                                    '<div style="margin-left:70px;">' +
-                                    '<h5 style="margin-top:0;">' + item.title + '</h5>' +
-                                    '<p class="text-muted">分类:' + (item.category ? item.category.name : '') + ' | 规格:' + specTypeText + '</p>' +
-                                    '</div>' +
-                                    '</div>' +
-                                    '</td>' +
-                                    '<td>¥' + item.price + '</td>' +
-                                    '<td>' + item.stocks + '</td>' +
-                                    '<td>' +
-                                    '<div class="input-group">' +
-                                    '<input type="number" class="form-control discount-input" value="' + defaultDiscount + '" min="0.1" max="10" step="0.1" data-price="' + item.price + '" style="width:60px;">' +
-                                    '<span class="input-group-addon">折</span>' +
-                                    '</div>' +
-                                    (item.spectype == 1 ? '<a href="javascript:;" class="btn btn-xs btn-info btn-spec-discount" data-id="' + item.id + '" style="margin-top:5px;">规格折扣设置</a>' : '') +
-                                    '</td>' +
-                                    '<td><span class="discount-price">¥' + discountPrice + '</span></td>' +
-                                    '<td><a href="javascript:;" class="btn btn-xs btn-danger remove-goods" data-id="' + item.id + '">删除</a></td>' +
-                                    '</tr>';
                             });
                             });
                             
                             
-                            tableHtml += '</tbody></table>';
+                            // 默认折扣值
+                            var defaultDiscount = 9;
+                            
+                            // 使用模板渲染表格
+                            var html = Template('goodsTableTpl', {
+                                list: data,
+                                discount: defaultDiscount
+                            });
+                            
+                            // 清空容器并显示表格
+                            $('#selected-goods-container').empty().append(html);
                             
                             
-                            // 显示表格
-                            $('#selected-goods-container').append(tableHtml);
+                            // 初始化分页表格
+                            $('#selected-goods-table').bootstrapTable({
+                                data: data,
+                                pagination: true,
+                                pageSize: 5,
+                                pageList: [5, 10, 20],
+                                sortable: true,
+                                search: false,
+                                columns: [
+                                    {
+                                        field: 'goods',
+                                        title: '商品',
+                                        width: '30%',
+                                        formatter: function(value, row) {
+                                            return '<div class="goods-item">' +
+                                                   '<img src="' + Fast.api.cdnurl(row.image) + '" style="width:60px;height:60px;margin-right:10px;" class="pull-left img-thumbnail">' +
+                                                   '<div style="margin-left:70px;">' +
+                                                   '<h5 style="margin-top:0;">' + row.title + '</h5>' +
+                                                   '<p class="text-muted">分类:' + (row.category ? row.category.name : '') + ' | 规格:' + (row.spectype == 0 ? '单规格' : '多规格') + '</p>' +
+                                                   '</div>' +
+                                                   '</div>'
+                                        }
+                                    },
+                                    {
+                                        field: 'price',
+                                        title: '价格',
+                                        width: '10%',
+                                        formatter: function(value, row) {
+                                            return '¥' + row.price;
+                                        }
+                                    },
+                                    {
+                                        field: 'stocks',
+                                        title: '现库存',
+                                        width: '10%'
+                                    },
+                                    {
+                                        field: 'discount',
+                                        title: '折扣',
+                                        width: '15%',
+                                        formatter: function(value, row) {
+                                            if(row.spectype == 1) {
+                                                var discountData = $('#discount-data').val() ? JSON.parse($('#discount-data').val()) : {};
+                                                var hasSpec = discountData[row.id] && discountData[row.id].specs;
+                                                var specBtnText = hasSpec ? '规格折扣设置 <span class="label label-success">已设置</span>' : '规格折扣设置';
+                                                var html = '<a href="javascript:;" class="btn btn-info btn-spec-discount" data-id="' + row.id + '">' + specBtnText + '</a>' +
+                                                       '<span class="text-muted" style="margin-left:10px;">请点击设置各规格折扣</span>';
+                                                
+                                                // 如果已设置规格折扣,显示汇总信息
+                                                if (hasSpec && discountData[row.id].summary) {
+                                                    var summary = discountData[row.id].summary;
+                                                    var infoText = '已设置' + summary.participate_count + '个规格,平均' + summary.avg_discount + '折,共' + summary.total_stocks + '件';
+                                                    html += '<div class="spec-discount-info text-muted" style="margin-top:5px;">' + infoText + '</div>';
+                                                }
+                                                
+                                                return html;
+                                            } else {
+                                                return '<div class="input-group">' +
+                                                       '<input type="number" class="form-control discount-input" value="' + defaultDiscount + '" min="0.1" max="10" step="0.1" data-price="' + row.price + '" data-id="' + row.id + '">' +
+                                                       '<span class="input-group-addon">折</span>' +
+                                                       '</div>';
+                                            }
+                                        }
+                                    },
+                                    {
+                                        field: 'discount_price',
+                                        title: '折后价',
+                                        width: '20%',
+                                        formatter: function(value, row) {
+                                            if(row.spectype == 0) {
+                                                return '<span class="discount-price" id="discount-price-' + row.id + '">¥' + (row.price * defaultDiscount / 10).toFixed(2) + '</span>';
+                                            } else {
+                                                return '';
+                                            }
+                                        }
+                                    },
+                                    {
+                                        field: 'operate',
+                                        title: '操作',
+                                        width: '15%',
+                                        formatter: function(value, row) {
+                                            return '<a href="javascript:;" class="btn btn-xs btn-danger remove-goods" data-id="' + row.id + '">删除</a>';
+                                        }
+                                    }
+                                ]
+                            });
                             
                             
                             // 更新隐藏字段
                             // 更新隐藏字段
                             $('#goods-ids').val(goodsIds.join(','));
                             $('#goods-ids').val(goodsIds.join(','));
                             
                             
+                            // 初始化折扣数据
+                            var discountData = {};
+                            $.each(data, function(index, item) {
+                                if (item.spectype == 0) { // 单规格商品
+                                    discountData[item.id] = {
+                                        id: item.id,
+                                        discount: defaultDiscount,
+                                        discount_price: (item.price * defaultDiscount / 10).toFixed(2)
+                                    };
+                                }
+                            });
+                            $('#discount-data').val(JSON.stringify(discountData));
+                            
                             // 绑定折扣输入事件
                             // 绑定折扣输入事件
-                            $('.discount-input').on('input', function() {
+                            $(document).on('input', '.discount-input', function() {
                                 var discount = parseFloat($(this).val()) || 0;
                                 var discount = parseFloat($(this).val()) || 0;
                                 if(discount < 0.1) discount = 0.1;
                                 if(discount < 0.1) discount = 0.1;
                                 if(discount > 10) discount = 10;
                                 if(discount > 10) discount = 10;
                                 
                                 
                                 var price = parseFloat($(this).data('price')) || 0;
                                 var price = parseFloat($(this).data('price')) || 0;
+                                var goodsId = $(this).data('id');
                                 var discountPrice = (price * discount / 10).toFixed(2);
                                 var discountPrice = (price * discount / 10).toFixed(2);
                                 
                                 
-                                $(this).closest('tr').find('.discount-price').text('¥' + discountPrice);
+                                $('#discount-price-' + goodsId).text('¥' + discountPrice);
                                 
                                 
                                 // 更新商品折扣数据
                                 // 更新商品折扣数据
-                                var goodsId = $(this).closest('tr').data('id');
                                 var goodsDiscount = {
                                 var goodsDiscount = {
                                     id: goodsId,
                                     id: goodsId,
                                     discount: discount,
                                     discount: discount,
@@ -209,24 +270,100 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                                 $('#discount-data').val(JSON.stringify(discountData));
                                 $('#discount-data').val(JSON.stringify(discountData));
                             });
                             });
                             
                             
-                            // 绑定规格折扣按钮点击事件
-                            $('.btn-spec-discount').on('click', function() {
+                            // 处理规格设置按钮点击事件
+                            $(document).on('click', '.btn-spec-discount', function() {
                                 var goodsId = $(this).data('id');
                                 var goodsId = $(this).data('id');
-                                Fast.api.open('marketing/discount/spec_discount?goods_id=' + goodsId, '规格折扣设置');
+                                var $row = $(this).closest('tr');
+                                var hasDiscountSetting = $row.data('has-discount-setting');
+                                var specData = '';
+                                
+                                // 如果已经有设置,则传递已有的数据
+                                if (hasDiscountSetting && $row.data('discount-data')) {
+                                    specData = encodeURIComponent(JSON.stringify($row.data('discount-data')));
+                                }
+                                
+                                Fast.api.open('marketing/discount/spec_discount?goods_id=' + goodsId + '&spec_data=' + specData, '规格折扣设置', {
+                                    area: ['90%', '90%'],
+                                    callback: function(data) {
+                                        if (data && data.goodsId && data.specs) {
+                                            // 保存数据到行属性
+                                            $row.data('discount-data', data);
+                                            $row.data('has-discount-setting', true);
+                                            
+                                            // 更新按钮文字
+                                            $row.find('.btn-spec-discount').text('已设置(可点击修改)');
+                                            
+                                            // 更新状态和折扣显示
+                                            $row.find('.discount-status').text('已设置');
+                                            
+                                            // 计算平均折扣
+                                            var totalDiscount = 0;
+                                            var count = 0;
+                                            $.each(data.specs, function(id, item) {
+                                                if (item.participate) {
+                                                    totalDiscount += parseFloat(item.discount);
+                                                    count++;
+                                                }
+                                            });
+                                            
+                                            var avgDiscount = count > 0 ? (totalDiscount / count).toFixed(1) : '-';
+                                            $row.find('.discount-value').text(avgDiscount + '折');
+                                            
+                                            // 将折扣数据保存到隐藏字段
+                                            updateDiscountData();
+                                        }
+                                    }
+                                });
                             });
                             });
                         }
                         }
                     }
                     }
                 });
                 });
             });
             });
             
             
+            // 更新所有折扣数据到隐藏字段
+            function updateDiscountData() {
+                var discountData = {};
+                $('#selected-goods-table tr[data-id]').each(function() {
+                    var $row = $(this);
+                    var goodsId = $row.data('id');
+                    if ($row.data('has-discount-setting') && $row.data('discount-data')) {
+                        discountData[goodsId] = $row.data('discount-data').specs;
+                    }
+                });
+                
+                $('#discount-data').val(JSON.stringify(discountData));
+            }
+            
             // 删除已选商品
             // 删除已选商品
-            $(document).on('click', '.remove-goods', function() {
+            $(document).on('click', '.btn-remove', function() {
                 var id = $(this).data('id');
                 var id = $(this).data('id');
-                $(this).closest('tr').remove();
                 
                 
-                // 如果表格为空,则移除整个表格
-                if($('#selected-goods-container tbody tr').length === 0) {
-                    $('#selected-goods-container').empty();
+                // 从表格中移除该行
+                var $table = $('#selected-goods-table');
+                if($table.length > 0) {
+                    // 如果使用了bootstrap-table
+                    var rows = $table.bootstrapTable('getData');
+                    var newRows = [];
+                    
+                    for(var i = 0; i < rows.length; i++) {
+                        if(rows[i].id != id) {
+                            newRows.push(rows[i]);
+                        }
+                    }
+                    
+                    if(newRows.length === 0) {
+                        $('#selected-goods-container').empty();
+                    } else {
+                        $table.bootstrapTable('load', newRows);
+                    }
+                } else {
+                    // 如果使用了传统表格
+                    $(this).closest('tr').remove();
+                    
+                    // 如果表格为空,则移除整个表格
+                    if($('#selected-goods-container tbody tr').length === 0) {
+                        $('#selected-goods-container').empty();
+                    }
                 }
                 }
                 
                 
                 // 更新隐藏字段
                 // 更新隐藏字段
@@ -250,9 +387,268 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
         edit: function () {
         edit: function () {
             Controller.api.bindevent();
             Controller.api.bindevent();
             
             
+            // 初始化已选择的商品
+            var goodsIds = $('#goods-ids').val();
+            var discountData = $('#discount-data').val() ? JSON.parse($('#discount-data').val()) : {};
+            
+            if(goodsIds) {
+                // 加载已选择的商品数据
+                Fast.api.ajax({
+                    url: 'shop/goods/get_goods_by_ids',
+                    data: {ids: goodsIds}
+                }, function(data) {
+                    if(data && data.length > 0) {
+                        // 使用模板渲染表格
+                        var html = Template('goodsTableTpl', {
+                            list: data
+                        });
+                        
+                        // 清空容器并显示表格
+                        $('#selected-goods-container').empty().append(html);
+                        
+                        // 初始化分页表格
+                        $('#selected-goods-table').bootstrapTable({
+                            data: data,
+                            pagination: true,
+                            pageSize: 5,
+                            pageList: [5, 10, 20],
+                            sortable: true,
+                            search: false,
+                            columns: [
+                                {
+                                    field: 'goods',
+                                    title: '商品',
+                                    width: '30%',
+                                    formatter: function(value, row) {
+                                        return '<div class="goods-item">' +
+                                               '<img src="' + Fast.api.cdnurl(row.image) + '" style="width:60px;height:60px;margin-right:10px;" class="pull-left img-thumbnail">' +
+                                               '<div style="margin-left:70px;">' +
+                                               '<h5 style="margin-top:0;">' + row.title + '</h5>' +
+                                               '<p class="text-muted">分类:' + (row.category ? row.category.name : '') + ' | 规格:' + (row.spectype == 0 ? '单规格' : '多规格') + '</p>' +
+                                               '</div>' +
+                                               '</div>'
+                                    }
+                                },
+                                {
+                                    field: 'price',
+                                    title: '价格',
+                                    width: '10%',
+                                    formatter: function(value, row) {
+                                        return '¥' + row.price;
+                                    }
+                                },
+                                {
+                                    field: 'stocks',
+                                    title: '现库存',
+                                    width: '10%'
+                                },
+                                {
+                                    field: 'discount',
+                                    title: '折扣',
+                                    width: '15%',
+                                    formatter: function(value, row) {
+                                        if(row.spectype == 1) {
+                                            var hasSpec = discountData[row.id] && discountData[row.id].specs;
+                                            var specBtnText = hasSpec ? '规格折扣设置 <span class="label label-success">已设置</span>' : '规格折扣设置';
+                                            var html = '<a href="javascript:;" class="btn btn-info btn-spec-discount" data-id="' + row.id + '">' + specBtnText + '</a>' +
+                                                   '<span class="text-muted" style="margin-left:10px;">请点击设置各规格折扣</span>';
+                                            
+                                            // 如果已设置规格折扣,显示汇总信息
+                                            if (hasSpec && discountData[row.id].summary) {
+                                                var summary = discountData[row.id].summary;
+                                                var infoText = '已设置' + summary.participate_count + '个规格,平均' + summary.avg_discount + '折,共' + summary.total_stocks + '件';
+                                                html += '<div class="spec-discount-info text-muted" style="margin-top:5px;">' + infoText + '</div>';
+                                            }
+                                            
+                                            return html;
+                                        } else {
+                                            var discount = (discountData[row.id] && discountData[row.id].discount) ? discountData[row.id].discount : 9;
+                                            return '<div class="input-group">' +
+                                                   '<input type="number" class="form-control discount-input" value="' + discount + '" min="0.1" max="10" step="0.1" data-price="' + row.price + '" data-id="' + row.id + '">' +
+                                                   '<span class="input-group-addon">折</span>' +
+                                                   '</div>';
+                                        }
+                                    }
+                                },
+                                {
+                                    field: 'discount_price',
+                                    title: '折后价',
+                                    width: '20%',
+                                    formatter: function(value, row) {
+                                        if(row.spectype == 0) {
+                                            var discount = (discountData[row.id] && discountData[row.id].discount) ? discountData[row.id].discount : 9;
+                                            var discountPrice = (row.price * discount / 10).toFixed(2);
+                                            return '<span class="discount-price" id="discount-price-' + row.id + '">¥' + discountPrice + '</span>';
+                                        } else {
+                                            return '';
+                                        }
+                                    }
+                                },
+                                {
+                                    field: 'operate',
+                                    title: '操作',
+                                    width: '15%',
+                                    formatter: function(value, row) {
+                                        return '<a href="javascript:;" class="btn btn-xs btn-danger remove-goods" data-id="' + row.id + '">删除</a>';
+                                    }
+                                }
+                            ]
+                        });
+                    }
+                    return false;
+                });
+            }
+            
             // 选择商品功能和删除商品功能,与add方法相同
             // 选择商品功能和删除商品功能,与add方法相同
             Controller.add();
             Controller.add();
         },
         },
+        
+        // 规格折扣设置页面
+        spec_discount: function () {
+            // 获取URL参数中的goods_id和spec_data
+            var goodsId = Fast.api.query('goods_id');
+            var specData = Fast.api.query('spec_data');
+            
+            // 如果有规格数据,则进行回显
+            if (specData) {
+                try {
+                    var data = JSON.parse(decodeURIComponent(specData));
+                    if (data && data.specs) {
+                        $.each(data.specs, function(id, item) {
+                            var $row = $('tr[data-id="' + id + '"]');
+                            if ($row.length > 0) {
+                                // 设置参与折扣
+                                if (item.participate) {
+                                    $row.find('.participate-checkbox').prop('checked', true).trigger('change');
+                                }
+                                
+                                // 设置折扣库存
+                                if (item.stocks) {
+                                    $row.find('.sku-stocks').val(item.stocks);
+                                }
+                                
+                                // 设置折扣
+                                if (item.discount) {
+                                    $row.find('.sku-discount').val(item.discount).trigger('input');
+                                }
+                            }
+                        });
+                    }
+                } catch (e) {
+                    console.error('解析规格数据失败', e);
+                }
+            }
+            
+            // 参与折扣复选框事件
+            $('.participate-checkbox').on('change', function() {
+                var checked = $(this).prop('checked');
+                var $row = $(this).closest('tr');
+                
+                // 启用/禁用库存和折扣输入框
+                $row.find('.sku-stocks').prop('disabled', !checked);
+                $row.find('.sku-discount').prop('disabled', !checked);
+                
+                // 如果勾选,设置默认值
+                if (checked) {
+                    var stocks = $row.data('stocks');
+                    $row.find('.sku-stocks').val(stocks);
+                    $row.find('.sku-discount').trigger('input');
+                }
+            });
+            
+            // 批量参与复选框事件
+            $('#batch-participate').on('change', function() {
+                var checked = $(this).prop('checked');
+                $('.participate-checkbox').prop('checked', checked).trigger('change');
+            });
+            
+            // 批量折扣变化事件
+            $('#batch-discount').on('input', function() {
+                var discount = parseFloat($(this).val()) || 0;
+                if (discount < 0.1) discount = 0.1;
+                if (discount > 10) discount = 10;
+                
+                $(this).val(discount);
+                
+                // 更新批量价格信息
+                Controller.api.updateBatchPriceInfo();
+            });
+            
+            // 初始化批量价格信息
+            Controller.api.updateBatchPriceInfo();
+            
+            // 应用批量设置按钮事件
+            $('#apply-batch').on('click', function() {
+                var discount = parseFloat($('#batch-discount').val()) || 9;
+                
+                // 应用到所有已勾选的行
+                $('.participate-checkbox:checked').each(function() {
+                    var $row = $(this).closest('tr');
+                    $row.find('.sku-discount').val(discount).trigger('input');
+                });
+            });
+            
+            // 折扣输入事件
+            $('.sku-discount').on('input', function() {
+                var discount = parseFloat($(this).val()) || 0;
+                if(discount < 0.1) discount = 0.1;
+                if(discount > 10) discount = 10;
+                
+                $(this).val(discount);
+                
+                var price = parseFloat($(this).data('price')) || 0;
+                var discountPrice = (price * discount / 10).toFixed(2);
+                
+                $(this).closest('tr').find('.discount-price').text('¥' + discountPrice);
+            });
+            
+            // 库存输入验证
+            $('.sku-stocks').on('input', function() {
+                var stocks = parseInt($(this).val()) || 0;
+                var maxStocks = parseInt($(this).closest('tr').data('stocks')) || 0;
+                
+                if (stocks < 0) stocks = 0;
+                if (stocks > maxStocks) stocks = maxStocks;
+                
+                $(this).val(stocks);
+            });
+            
+            // 确认按钮事件
+            $('.btn-confirm').on('click', function() {
+                var specs = {};
+                var hasParticipate = false;
+                
+                // 收集所有参与的规格数据
+                $('.participate-checkbox:checked').each(function() {
+                    var $row = $(this).closest('tr');
+                    var id = $row.data('id');
+                    var price = $row.data('price');
+                    var discount = parseFloat($row.find('.sku-discount').val());
+                    var stocks = parseInt($row.find('.sku-stocks').val());
+                    var discountPrice = (price * discount / 10).toFixed(2);
+                    
+                    specs[id] = {
+                        id: id,
+                        participate: true,
+                        discount: discount,
+                        price: price,
+                        stocks: stocks,
+                        discount_price: discountPrice
+                    };
+                    
+                    hasParticipate = true;
+                });
+                
+                // 验证是否有选择参与的规格
+                if (!hasParticipate) {
+                    Layer.alert('请至少选择一个参与折扣的规格', {icon: 2});
+                    return;
+                }
+                
+                // 返回数据到add.html页面
+                Fast.api.close({goodsId: goodsId, specs: specs});
+            });
+        },
         api: {
         api: {
             bindevent: function () {
             bindevent: function () {
                 Form.api.bindevent($("form[role=form]"));
                 Form.api.bindevent($("form[role=form]"));
@@ -294,6 +690,24 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                         $('input[name="row[purchase_limit_daily]"]').prop('disabled', false).focus();
                         $('input[name="row[purchase_limit_daily]"]').prop('disabled', false).focus();
                     }
                     }
                 });
                 });
+            },
+            
+            // 更新批量价格信息
+            updateBatchPriceInfo: function() {
+                var discount = parseFloat($('#batch-discount').val()) || 0;
+                var totalPrice = 0;
+                var totalCount = 0;
+                
+                $('tr[data-price]').each(function() {
+                    var price = parseFloat($(this).data('price')) || 0;
+                    totalPrice += price;
+                    totalCount++;
+                });
+                
+                var avgPrice = totalCount > 0 ? totalPrice / totalCount : 0;
+                var discountPrice = (avgPrice * discount / 10).toFixed(2);
+                
+                $('.batch-price-info').text('平均折后价:¥' + discountPrice);
             }
             }
         }
         }
     };
     };

+ 6 - 14
public/assets/js/backend/shop/goods.js

@@ -146,27 +146,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                     ]
                     ]
                 ]
                 ]
             });
             });
-            //选中商品
+            
+            // 确认按钮绑定事件
             $(document).on('click', '.btn-goods-select', function () {
             $(document).on('click', '.btn-goods-select', function () {
-                let goods_ids = Table.api.selectedids(table);
-                if (goods_ids.length == 0) {
+                var selectedRows = table.bootstrapTable('getSelections');
+                if (selectedRows.length === 0) {
                     Layer.alert('请选择商品');
                     Layer.alert('请选择商品');
                     return;
                     return;
                 }
                 }
                 
                 
-                // 获取选中的商品数据
-                var selectedRows = [];
-                $.each(table.bootstrapTable('getSelections'), function(index, row) {
-                    selectedRows.push(row);
-                });
-                
                 // 调用父窗口回调函数
                 // 调用父窗口回调函数
-                var callback = parent.Fast.api.callback;
-                if (typeof callback === 'function') {
-                    callback.call(undefined, selectedRows);
-                    parent.Layer.close(parent.Layer.getFrameIndex(window.name));
-                }
+                Fast.api.close(selectedRows);
             });
             });
+            
             // 为表格绑定事件
             // 为表格绑定事件
             Table.api.bindevent(table);
             Table.api.bindevent(table);
         },
         },