Browse Source

feat:版本

super-yimizi 2 months ago
parent
commit
a5961abbe8

+ 71 - 0
application/admin/controller/Feedback.php

@@ -0,0 +1,71 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\common\controller\Backend;
+use app\common\Enum\StatusEnum;
+use app\common\Enum\FeedbackEnum;
+/**
+ * 意见反馈
+ *
+ * @icon fa fa-circle-o
+ */
+class Feedback extends Backend
+{
+
+    protected $relationSearch = true;
+    protected $searchFields = 'id,phone,content';
+
+    /**
+     * Feedback模型对象
+     * @var \app\common\model\Feedback
+     */
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = new \app\common\model\Feedback;
+        $this->view->assign("statusList",StatusEnum::getMap());
+        $this->assignconfig('statusSearchList',json_encode(StatusEnum::getMap()));
+        $this->view->assign("processStatusList",FeedbackEnum::getProcessStatusMap());
+        $this->assignconfig('processStatusSearchList',json_encode(FeedbackEnum::getProcessStatusMap()));
+        $this->view->assign("feedbackTypeList",FeedbackEnum::getFeedbackTypeMap());
+        $this->assignconfig('feedbackTypeSearchList',json_encode(FeedbackEnum::getFeedbackTypeMap()));
+
+    }
+
+
+
+    /**
+     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
+     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
+     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
+     */
+     /**
+     * 查看
+     */
+    public function index()
+    {
+        //设置过滤方法
+        $this->request->filter(['strip_tags', 'trim']);
+        if ($this->request->isAjax()) {
+            //如果发送的来源是Selectpage,则转发到Selectpage
+            if ($this->request->request('keyField')) {
+                return $this->selectpage();
+            }
+            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
+            $list = $this->model
+                ->with('user')
+                ->where($where)
+                ->order($sort, $order)
+                ->paginate($limit);
+            $result = array("total" => $list->total(), "rows" => $list->items());
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+
+}

+ 37 - 0
application/admin/controller/marketing/Discount.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace app\admin\controller\marketing;
+
+use app\common\controller\Backend;
+
+/**
+ * 营销活动表(整体活动)
+ *
+ * @icon fa fa-circle-o
+ */
+class Discount extends Backend
+{
+
+    /**
+     * Discount模型对象
+     * @var \app\admin\model\marketing\Discount
+     */
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = new \app\admin\model\marketing\Discount;
+
+    }
+
+
+
+    /**
+     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
+     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
+     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
+     */
+
+
+}

+ 15 - 0
application/admin/lang/zh-cn/feedback.php

@@ -0,0 +1,15 @@
+<?php
+
+return [
+    'User_id'        => '反馈用户',
+    'Type'           => '反馈类型',
+    'Content'        => '反馈内容',
+    'Images'         => '图片',
+    'Phone'          => '联系电话',
+    'Process_status' => '处理状态',
+    'Remark'         => '系统备注',
+    'Status'         => '启用状态',
+    'Createtime'     => '创建时间',
+    'Updatetime'     => '更新时间',
+    'Deletetime'     => '删除时间'
+];

+ 27 - 0
application/admin/lang/zh-cn/marketing/discount.php

@@ -0,0 +1,27 @@
+<?php
+
+return [
+    'Id'                 => '活动id',
+    'Name'               => '活动名称',
+    'Title'              => '优惠标题',
+    'Desc'               => '活动说明',
+    'Image'              => '活动图',
+    'Type'               => '活动类型:1:限时折扣2:第N件N折3:满减满折4:满送5:活动边框6:活动背景',
+    'Goods_type'         => '商品活动类型(单品,独立商品,店铺整体商品)',
+    'Goods_info'         => '参与活动商品信息',
+    'Class'              => '活动类别',
+    'Class_category'     => '活动类别子分类(活动管理)',
+    'Relate_member'      => '参与会员条件(默认全部)',
+    'Active_value'       => '活动扩展信息数据',
+    'Start_time'         => '活动开始时间',
+    'End_time'           => '活动结束时间',
+    'Activity_status'    => '活动状态',
+    'Active_order_money' => '活动累计金额',
+    'Active_order_num'   => '活动累计订单数',
+    'Active_member_num'  => '活动参与会员数',
+    'Active_success_num' => '活动成功参与会员数',
+    'Is_del'             => '是否删除',
+    'Createtime'         => '创建时间',
+    'Updatetime'         => '更新时间',
+    'Deletetime'         => '删除时间'
+];

+ 61 - 0
application/admin/model/marketing/Discount.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace app\admin\model\marketing;
+
+use think\Model;
+use traits\model\SoftDelete;
+
+class Discount extends Model
+{
+
+    use SoftDelete;
+
+    
+
+    // 表名
+    protected $table = 'shop_activity';
+    
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = 'integer';
+
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+    protected $deleteTime = 'deletetime';
+
+    // 追加属性
+    protected $append = [
+        'start_time_text',
+        'end_time_text'
+    ];
+    
+
+    
+
+
+
+    public function getStartTimeTextAttr($value, $data)
+    {
+        $value = $value ?: ($data['start_time'] ?? '');
+        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
+    }
+
+
+    public function getEndTimeTextAttr($value, $data)
+    {
+        $value = $value ?: ($data['end_time'] ?? '');
+        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
+    }
+
+    protected function setStartTimeAttr($value)
+    {
+        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
+    }
+
+    protected function setEndTimeAttr($value)
+    {
+        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
+    }
+
+
+}

+ 27 - 0
application/admin/validate/marketing/Discount.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace app\admin\validate\marketing;
+
+use think\Validate;
+
+class Discount extends Validate
+{
+    /**
+     * 验证规则
+     */
+    protected $rule = [
+    ];
+    /**
+     * 提示消息
+     */
+    protected $message = [
+    ];
+    /**
+     * 验证场景
+     */
+    protected $scene = [
+        'add'  => [],
+        'edit' => [],
+    ];
+    
+}

+ 77 - 0
application/admin/view/feedback/add.html

@@ -0,0 +1,77 @@
+<form id="add-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">{:__('User_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-user_id" data-rule="required" data-source="user/user/index" data-field="nickname" class="form-control selectpage" name="row[user_id]" type="text" value="">
+        </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="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-content" class="form-control" name="row[content]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Images')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="input-group">
+                <input id="c-images" class="form-control" size="50" name="row[images]" type="text">
+                <div class="input-group-addon no-border no-padding">
+                    <span><button type="button" id="faupload-images" class="btn btn-danger faupload" data-input-id="c-images" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="true" data-preview-id="p-images"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+                    <span><button type="button" id="fachoose-images" class="btn btn-primary fachoose" data-input-id="c-images" data-mimetype="image/*" data-multiple="true"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
+                </div>
+                <span class="msg-box n-right" for="c-images"></span>
+            </div>
+            <ul class="row list-inline faupload-preview" id="p-images"></ul>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Phone')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-phone" class="form-control" name="row[phone]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Process_status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+
+            <div class="radio">
+            {foreach name="processStatusList" item="vo"}
+            <label for="row[process_status]-{$key|htmlentities}"><input id="row[process_status]-{$key|htmlentities}" name="row[process_status]" type="radio" value="{$key|htmlentities}" {in name="key" value="1"}checked{/in} /> {$vo|htmlentities}</label>
+            {/foreach}
+            </div>
+
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-remark" class="form-control" name="row[remark]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+
+            <div class="radio">
+            {foreach name="statusList" item="vo"}
+            <label for="row[status]-{$key|htmlentities}"><input id="row[status]-{$key|htmlentities}" name="row[status]" type="radio" value="{$key|htmlentities}" {in name="key" value="1"}checked{/in} /> {$vo|htmlentities}</label>
+            {/foreach}
+            </div>
+
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 103 - 0
application/admin/view/feedback/edit.html

@@ -0,0 +1,103 @@
+<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">{:__('User_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="user-info" style="display:flex;align-items:center;">
+                <img src="{$row.user.avatar|default='/assets/img/avatar.png'}" style="width:40px;height:40px;border-radius:50%;margin-right:10px;" />
+                <span style="color:#a55bff;">{$row.user.username|default='游客'|htmlentities}</span>
+            </div>
+            <!-- <input id="c-user_id" data-rule="required" data-source="user/user/index" data-field="username" class="form-control selectpage" name="row[user_id]" type="hidden" value="{$row.user_id|htmlentities}"> -->
+             <input id="c-user_id" data-rule="required"  class="form-control" name="row[user_id]" type="hidden" value="{$row.user_id|htmlentities}">
+        </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">
+            <div class="form-control-static">
+                {$row.type_text|htmlentities}
+            </div>
+            <input id="c-type" data-rule="required" class="form-control" name="row[type]" type="hidden" value="{$row.type|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="form-control-static">
+                {$row.content|htmlentities}
+            </div>
+            <input id="c-content" class="form-control" name="row[content]" type="hidden" value="{$row.content|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Images')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="form-control-static">
+                <ul class="row list-inline">
+                    {php}
+                    $images = is_array($row['images']) ? $row['images'] : json_decode($row['images'], true);
+                    if (!$images) {
+                        $images = $row['images'] ? explode(',', $row['images']) : [];
+                    }
+                    {/php}
+                    
+                    {foreach name="images" item="image"}
+                    <li class="col-xs-3">
+                        <a href="{$image|cdnurl}" target="_blank" class="thumbnail">
+                            <img src="{$image|cdnurl}" class="img-responsive">
+                        </a>
+                    </li>
+                    {/foreach}
+                </ul>
+            </div>
+            <input id="c-images" class="form-control" name="row[images]" type="hidden" value="{$row.images|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Phone')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="form-control-static">
+                {$row.phone|htmlentities}
+            </div>
+            <input id="c-phone" class="form-control" name="row[phone]" type="hidden" value="{$row.phone|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Process_status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="radio">
+                {foreach name="processStatusList" item="vo"}
+                <label for="row[process_status]-{$key|htmlentities}"><input id="row[process_status]-{$key|htmlentities}" name="row[process_status]"
+                        type="radio" value="{$key|htmlentities}" {in name="key" value="$row.process_status" }checked{/in} />
+                    {$vo|htmlentities}</label>
+                {/foreach}
+            </div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-remark" class="form-control" name="row[remark]" type="text" value="{$row.remark|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+
+            <div class="radio">
+                {foreach name="statusList" item="vo"}
+                <label for="row[status]-{$key|htmlentities}"><input id="row[status]-{$key|htmlentities}" name="row[status]"
+                        type="radio" value="{$key|htmlentities}" {in name="key" value="$row.status" }checked{/in} />
+                    {$vo|htmlentities}</label>
+                {/foreach}
+            </div>
+
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 29 - 0
application/admin/view/feedback/index.html

@@ -0,0 +1,29 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
+                        <!-- <a href="javascript:;" class="btn btn-success btn-add {:$auth->check('feedback/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a> -->
+                        <!-- <a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('feedback/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a> -->
+                        <a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('feedback/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
+                        
+
+                        
+
+                        <a class="btn btn-success btn-recyclebin btn-dialog {:$auth->check('feedback/recyclebin')?'':'hide'}" href="feedback/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover table-nowrap"
+                           data-operate-edit="{:$auth->check('feedback/edit')}"
+                           data-operate-del="{:$auth->check('feedback/del')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 25 - 0
application/admin/view/feedback/recyclebin.html

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar('refresh')}
+                        <a class="btn btn-info btn-multi btn-disabled disabled {:$auth->check('feedback/restore')?'':'hide'}" href="javascript:;" data-url="feedback/restore" data-action="restore"><i class="fa fa-rotate-left"></i> {:__('Restore')}</a>
+                        <a class="btn btn-danger btn-multi btn-disabled disabled {:$auth->check('feedback/destroy')?'':'hide'}" href="javascript:;" data-url="feedback/destroy" data-action="destroy"><i class="fa fa-times"></i> {:__('Destroy')}</a>
+                        <a class="btn btn-success btn-restoreall {:$auth->check('feedback/restore')?'':'hide'}" href="javascript:;" data-url="feedback/restore" title="{:__('Restore all')}"><i class="fa fa-rotate-left"></i> {:__('Restore all')}</a>
+                        <a class="btn btn-danger btn-destroyall {:$auth->check('feedback/destroy')?'':'hide'}" href="javascript:;" data-url="feedback/destroy" title="{:__('Destroy all')}"><i class="fa fa-times"></i> {:__('Destroy all')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover"
+                           data-operate-restore="{:$auth->check('feedback/restore')}"
+                           data-operate-destroy="{:$auth->check('feedback/destroy')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 131 - 0
application/admin/view/marketing/discount/add.html

@@ -0,0 +1,131 @@
+<form id="add-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="">
+        </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="">
+        </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"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="input-group">
+                <input id="c-image" data-rule="required" class="form-control" size="50" name="row[image]" type="text" value="">
+                <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>
+        </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="">
+        </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="">
+        </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"></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="">
+        </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="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Relate_member')}:</label>
+        <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="">
+        </div>
+    </div>
+    <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"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Start_time')}:</label>
+        <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="{:date('Y-m-d H:i:s')}">
+        </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="{:date('Y-m-d H:i:s')}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Activity_status')}:</label>
+        <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="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Active_order_money')}:</label>
+        <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="0.00">
+        </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="0">
+        </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="0">
+        </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="0">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Is_del')}:</label>
+        <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="0">
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 131 - 0
application/admin/view/marketing/discount/edit.html

@@ -0,0 +1,131 @@
+<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>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <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>
+        </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 class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Relate_member')}:</label>
+        <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>
+    </div>
+    <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>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Start_time')}:</label>
+        <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):''}">
+        </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>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Activity_status')}:</label>
+        <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>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Active_order_money')}:</label>
+        <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>
+    </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>
+    </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>
+    </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 class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Is_del')}:</label>
+        <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}">
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 29 - 0
application/admin/view/marketing/discount/index.html

@@ -0,0 +1,29 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
+                        <a href="javascript:;" class="btn btn-success btn-add {:$auth->check('marketing/discount/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
+                        <a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('marketing/discount/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
+                        <a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('marketing/discount/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
+                        
+
+                        
+
+                        <a class="btn btn-success btn-recyclebin btn-dialog {:$auth->check('marketing/discount/recyclebin')?'':'hide'}" href="marketing/discount/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover table-nowrap"
+                           data-operate-edit="{:$auth->check('marketing/discount/edit')}"
+                           data-operate-del="{:$auth->check('marketing/discount/del')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 25 - 0
application/admin/view/marketing/discount/recyclebin.html

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar('refresh')}
+                        <a class="btn btn-info btn-multi btn-disabled disabled {:$auth->check('marketing/discount/restore')?'':'hide'}" href="javascript:;" data-url="marketing/discount/restore" data-action="restore"><i class="fa fa-rotate-left"></i> {:__('Restore')}</a>
+                        <a class="btn btn-danger btn-multi btn-disabled disabled {:$auth->check('marketing/discount/destroy')?'':'hide'}" href="javascript:;" data-url="marketing/discount/destroy" data-action="destroy"><i class="fa fa-times"></i> {:__('Destroy')}</a>
+                        <a class="btn btn-success btn-restoreall {:$auth->check('marketing/discount/restore')?'':'hide'}" href="javascript:;" data-url="marketing/discount/restore" title="{:__('Restore all')}"><i class="fa fa-rotate-left"></i> {:__('Restore all')}</a>
+                        <a class="btn btn-danger btn-destroyall {:$auth->check('marketing/discount/destroy')?'':'hide'}" href="javascript:;" data-url="marketing/discount/destroy" title="{:__('Destroy all')}"><i class="fa fa-times"></i> {:__('Destroy all')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover"
+                           data-operate-restore="{:$auth->check('marketing/discount/restore')}"
+                           data-operate-destroy="{:$auth->check('marketing/discount/destroy')}"
+                           width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 22 - 2
application/api/controller/Index.php

@@ -3,13 +3,14 @@
 namespace app\api\controller;
 
 use app\common\controller\Api;
-
+use app\common\model\Feedback;
+use app\api\validate\Feedback as FeedbackValidate;
 /**
  * 首页接口
  */
 class Index extends Api
 {
-    protected $noNeedLogin = ['*'];
+    protected $noNeedLogin = ['index'];
     protected $noNeedRight = ['*'];
 
     /**
@@ -20,4 +21,23 @@ class Index extends Api
     {
         $this->success(__('User Center'));
     }
+
+
+    public function feedback()
+    {
+        $user = $this->auth->getUser();
+        $params = $this->request->only(['type', 'content', 'images', 'phone']);
+        // 使用验证器
+        $validate = new FeedbackValidate();
+        if (!$validate->check($params)) {
+            $this->error($validate->getError());
+        }        
+        if ($user) {
+            $params['user_id'] = $user->id;
+        }
+        $result = Feedback::create($params);
+        if ($result) {
+            $this->success('感谢您的反馈');
+        }
+    }
 }

+ 46 - 0
application/api/validate/Feedback.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace app\api\validate;
+
+use think\Validate;
+use app\common\Enum\FeedbackEnum;
+
+class Feedback extends Validate
+{
+    /**
+     * 验证规则
+     */
+    protected $rule = [
+        //'type'    => 'require|in:产品功能反馈,产品bug反馈,其他反馈',
+        'content' => 'require|max:2000',
+        'images'  => 'array|length:0,3',
+        'phone'   => 'mobile',
+    ];
+
+    /**
+     * 提示消息
+     */
+    protected $message = [
+        'type.require'   => '请选择反馈类型',
+        'type.in'        => '反馈类型不正确',
+        'content.require' => '请输入反馈内容',
+        'content.max'    => '反馈内容不能超过2000字符',
+        'images.array'   => '图片必须是数组格式',
+        'images.length'  => '最多上传3张图片',
+        'phone.mobile'   => '手机号格式不正确',
+    ];
+
+    /**
+     * 验证场景
+     */
+    protected $scene = [
+        'add' => ['type', 'content', 'images', 'phone'],
+    ];
+
+    public function __construct(array $rules = [], $message = [], $field = [])
+    {
+        // 动态设置枚举值
+        $this->rule['type'] = 'require|in:' . implode(',', FeedbackEnum::FEEDBACK_TYPE_LIST);
+        parent::__construct($rules, $message, $field);
+    }
+} 

+ 66 - 0
application/common/Enum/FeedbackEnum.php

@@ -0,0 +1,66 @@
+<?php
+namespace app\common\Enum;
+
+/**
+ * 全局状态枚举
+ */
+class FeedbackEnum
+{
+    const PRODUCT_FUNCTION_FEEDBACK = 'PRODUCT_FUNCTION_FEEDBACK'; // 产品功能反馈
+    const PRODUCT_BUG_FEEDBACK = 'PRODUCT_BUG_FEEDBACK'; // 产品bug反馈
+    const OTHER_FEEDBACK = 'OTHER_FEEDBACK'; // 其他反馈
+
+    // 反馈类型列表
+    const FEEDBACK_TYPE_LIST = [
+        self::PRODUCT_FUNCTION_FEEDBACK,
+        self::PRODUCT_BUG_FEEDBACK,
+        self::OTHER_FEEDBACK,
+    ];
+
+    const PROCESS_STATUS_UNPROCESSED = 1; // 未处理
+    const PROCESS_STATUS_PROCESSED = 2; // 已处理
+
+    const PROCESS_STATUS_LIST = [
+        self::PROCESS_STATUS_UNPROCESSED,
+        self::PROCESS_STATUS_PROCESSED,
+    ];          
+
+    /**
+     * 获取状态描述
+     * @param int $status
+     * @return string
+     */
+    public static function getFeedbackTypeText($status)
+    {
+        $map = self::getFeedbackTypeMap();
+        return $map[$status] ?? '未知';
+    }
+    /**
+     * 获取状态映射
+     * @return array
+     */
+    public static function getFeedbackTypeMap()
+    {
+        return [
+            self::PRODUCT_FUNCTION_FEEDBACK => '产品功能反馈',
+            self::PRODUCT_BUG_FEEDBACK => '产品bug反馈',
+            self::OTHER_FEEDBACK => '其他反馈',
+        ];
+    }
+    /**
+     * 获取处理状态映射
+     * @return array
+     */
+    public static function getProcessStatusMap()
+    {
+        return [
+            self::PROCESS_STATUS_UNPROCESSED => '未处理',
+            self::PROCESS_STATUS_PROCESSED => '已处理',
+        ];
+    }
+    public static function getProcessStatusText($status)
+    {
+        $map = self::getProcessStatusMap();
+        return $map[$status] ?? '未知';
+    }
+} 

+ 52 - 0
application/common/model/Feedback.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace app\common\model;
+
+use think\Model;
+use traits\model\SoftDelete;
+use app\common\Enum\FeedbackEnum;
+class Feedback extends Model
+{
+
+    use SoftDelete;
+
+    
+
+    // 表名
+    protected $table = 'shop_feedback';
+    
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = 'integer';
+
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+    protected $deleteTime = 'deletetime';
+
+    // 追加属性
+    protected $append = [
+
+    ];
+    
+    public function user()
+    {
+        return $this->belongsTo('User', 'user_id', 'id');
+    }
+
+    public function getTypeTextAttr($value, $data)
+    {
+        return FeedbackEnum::getFeedbackTypeText($data['type']);
+    }
+     
+    public function getImageTextAttr($value, $data){
+        return  json_decode($data['images'], true);
+    }
+    
+
+
+
+
+
+
+
+}

+ 27 - 0
application/common/validate/Feedback.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace app\common\validate;
+
+use think\Validate;
+
+class Feedback extends Validate
+{
+    /**
+     * 验证规则
+     */
+    protected $rule = [
+    ];
+    /**
+     * 提示消息
+     */
+    protected $message = [
+    ];
+    /**
+     * 验证场景
+     */
+    protected $scene = [
+        'add'  => [],
+        'edit' => [],
+    ];
+    
+}

+ 166 - 0
public/assets/js/backend/feedback.js

@@ -0,0 +1,166 @@
+define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+
+    var feedbackTypeList = {};
+    var processStatusList = {};
+    var statusList = {};
+    var Controller = {
+        index: function () {
+            // 初始化表格参数配置
+            Table.api.init({
+                extend: {
+                    index_url: 'feedback/index' + location.search,
+                    add_url: 'feedback/add',
+                    edit_url: 'feedback/edit',
+                    del_url: 'feedback/del',
+                    multi_url: 'feedback/multi',
+                    import_url: 'feedback/import',
+                    table: 'shop_feedback',
+                }
+            });
+
+            var table = $("#table");
+            feedbackTypeList = JSON.parse(Config.feedbackTypeSearchList);
+            processStatusList = JSON.parse(Config.processStatusSearchList);
+            statusList = JSON.parse(Config.statusSearchList);
+            console.log(feedbackTypeList);
+            console.log(processStatusList);
+            console.log(statusList);
+            // 初始化表格
+            table.bootstrapTable({
+                url: $.fn.bootstrapTable.defaults.extend.index_url,
+                pk: 'id',
+                sortName: 'id',
+                fixedColumns: true,
+                fixedRightNumber: 1,
+                columns: [
+                    [
+                        {checkbox: true},
+                        {field: 'id', title: __('Id')},
+                        {
+                            field: 'user.username', title: __('User_id'), operate: false,
+                            formatter: function (value, row, index) {
+                                // 显示用户头像和用户名
+                                var avatar = row.user && row.user.avatar ? row.user.avatar : '/assets/img/avatar.png';
+                                var username = row.user && row.user.username ? row.user.username : '游客';
+                                
+                                return '<div style="display:flex;align-items:center;">' + 
+                                       '<img src="' + avatar + '" style="width:40px;height:40px;border-radius:50%;margin-right:10px;" />' +
+                                       '<span style="color:#a55bff;">' + username + '</span>' +
+                                       '</div>';
+                            }
+                        },
+                        {field: 'type', title: __('Type'), searchList: feedbackTypeList,formatter: Controller.api.formatter.type},
+                        {field: 'content', title: __('Content'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'images', title: __('Images'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.images},
+                        {field: 'phone', title: __('Phone'), operate: 'LIKE'},
+                        {field: 'process_status', title: __('Process_status'), searchList: processStatusList,formatter:Controller.api.formatter.process_status},
+                        {field: 'remark', title: __('Remark'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.remark},
+                        {field: 'status', title: __('Status'), searchList: statusList, formatter:Table.api.formatter.status},
+                        {field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
+                        {field: 'updatetime', title: __('Updatetime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
+                        {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
+                    ]
+                ]
+            });
+
+            // 为表格绑定事件
+            Table.api.bindevent(table);
+        },
+        recyclebin: function () {
+            // 初始化表格参数配置
+            Table.api.init({
+                extend: {
+                    'dragsort_url': ''
+                }
+            });
+
+            var table = $("#table");
+
+            // 初始化表格
+            table.bootstrapTable({
+                url: 'feedback/recyclebin' + location.search,
+                pk: 'id',
+                sortName: 'id',
+                columns: [
+                    [
+                        {checkbox: true},
+                        {field: 'id', title: __('Id')},
+                        {
+                            field: 'deletetime',
+                            title: __('Deletetime'),
+                            operate: 'RANGE',
+                            addclass: 'datetimerange',
+                            formatter: Table.api.formatter.datetime
+                        },
+                        {
+                            field: 'operate',
+                            width: '140px',
+                            title: __('Operate'),
+                            table: table,
+                            events: Table.api.events.operate,
+                            buttons: [
+                                {
+                                    name: 'Restore',
+                                    text: __('Restore'),
+                                    classname: 'btn btn-xs btn-info btn-ajax btn-restoreit',
+                                    icon: 'fa fa-rotate-left',
+                                    url: 'feedback/restore',
+                                    refresh: true
+                                },
+                                {
+                                    name: 'Destroy',
+                                    text: __('Destroy'),
+                                    classname: 'btn btn-xs btn-danger btn-ajax btn-destroyit',
+                                    icon: 'fa fa-times',
+                                    url: 'feedback/destroy',
+                                    refresh: true
+                                }
+                            ],
+                            formatter: Table.api.formatter.operate
+                        }
+                    ]
+                ]
+            });
+
+            // 为表格绑定事件
+            Table.api.bindevent(table);
+        },
+
+        add: function () {
+
+            Controller.api.bindevent();
+        },
+        edit: function () {
+            Controller.api.bindevent();
+        },
+        api: {
+            bindevent: function () {
+                Form.api.bindevent($("form[role=form]"));
+            },
+            formatter: {
+                type: function(value, row, index) {
+                    var type = feedbackTypeList[value] || value;
+                    var cssClass = '';
+                    
+                    // 根据不同类型设置不同的样式
+                    if (value === 'PRODUCT_FUNCTION_FEEDBACK') {
+                        cssClass = 'success'; // 绿色
+                    } else if (value === 'PRODUCT_BUG_FEEDBACK') {
+                        cssClass = 'danger';  // 红色
+                    } else if (value === 'OTHER_FEEDBACK') {
+                        cssClass = 'info';    // 蓝色
+                    }
+                    
+                    return '<span class="label label-' + cssClass + '">' + type + '</span>';
+                },
+                process_status: function(value, row, index) {
+                    var processStatus = processStatusList[value] || value;
+                    var cssClass = value == 1 ? 'warning' : 'success';
+                    
+                    return '<span class="label label-' + cssClass + '">' + processStatus + '</span>';
+                }
+            }
+        }
+    };
+    return Controller;
+});

+ 131 - 0
public/assets/js/backend/marketing/discount.js

@@ -0,0 +1,131 @@
+define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+
+    var Controller = {
+        index: function () {
+            // 初始化表格参数配置
+            Table.api.init({
+                extend: {
+                    index_url: 'marketing/discount/index' + location.search,
+                    add_url: 'marketing/discount/add',
+                    edit_url: 'marketing/discount/edit',
+                    del_url: 'marketing/discount/del',
+                    multi_url: 'marketing/discount/multi',
+                    import_url: 'marketing/discount/import',
+                    table: 'shop_activity',
+                }
+            });
+
+            var table = $("#table");
+
+            // 初始化表格
+            table.bootstrapTable({
+                url: $.fn.bootstrapTable.defaults.extend.index_url,
+                pk: 'id',
+                sortName: 'id',
+                fixedColumns: true,
+                fixedRightNumber: 1,
+                columns: [
+                    [
+                        {checkbox: true},
+                        {field: 'id', title: __('Id')},
+                        {field: 'name', title: __('Name'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'title', title: __('Title'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'image', title: __('Image'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.image},
+                        {field: 'type', title: __('Type'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'goods_type', title: __('Goods_type'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'class', title: __('Class'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'class_category', title: __('Class_category'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'relate_member', title: __('Relate_member'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'start_time', title: __('Start_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
+                        {field: 'end_time', title: __('End_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
+                        {field: 'activity_status', title: __('Activity_status'), operate: 'LIKE', formatter: Table.api.formatter.status},
+                        {field: 'active_order_money', title: __('Active_order_money'), operate:'BETWEEN'},
+                        {field: 'active_order_num', title: __('Active_order_num')},
+                        {field: 'active_member_num', title: __('Active_member_num')},
+                        {field: 'active_success_num', title: __('Active_success_num')},
+                        {field: 'is_del', title: __('Is_del')},
+                        {field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
+                        {field: 'updatetime', title: __('Updatetime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
+                        {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
+                    ]
+                ]
+            });
+
+            // 为表格绑定事件
+            Table.api.bindevent(table);
+        },
+        recyclebin: function () {
+            // 初始化表格参数配置
+            Table.api.init({
+                extend: {
+                    'dragsort_url': ''
+                }
+            });
+
+            var table = $("#table");
+
+            // 初始化表格
+            table.bootstrapTable({
+                url: 'marketing/discount/recyclebin' + location.search,
+                pk: 'id',
+                sortName: 'id',
+                columns: [
+                    [
+                        {checkbox: true},
+                        {field: 'id', title: __('Id')},
+                        {field: 'title', title: __('Title'), align: 'left'},
+                        {
+                            field: 'deletetime',
+                            title: __('Deletetime'),
+                            operate: 'RANGE',
+                            addclass: 'datetimerange',
+                            formatter: Table.api.formatter.datetime
+                        },
+                        {
+                            field: 'operate',
+                            width: '140px',
+                            title: __('Operate'),
+                            table: table,
+                            events: Table.api.events.operate,
+                            buttons: [
+                                {
+                                    name: 'Restore',
+                                    text: __('Restore'),
+                                    classname: 'btn btn-xs btn-info btn-ajax btn-restoreit',
+                                    icon: 'fa fa-rotate-left',
+                                    url: 'marketing/discount/restore',
+                                    refresh: true
+                                },
+                                {
+                                    name: 'Destroy',
+                                    text: __('Destroy'),
+                                    classname: 'btn btn-xs btn-danger btn-ajax btn-destroyit',
+                                    icon: 'fa fa-times',
+                                    url: 'marketing/discount/destroy',
+                                    refresh: true
+                                }
+                            ],
+                            formatter: Table.api.formatter.operate
+                        }
+                    ]
+                ]
+            });
+
+            // 为表格绑定事件
+            Table.api.bindevent(table);
+        },
+
+        add: function () {
+            Controller.api.bindevent();
+        },
+        edit: function () {
+            Controller.api.bindevent();
+        },
+        api: {
+            bindevent: function () {
+                Form.api.bindevent($("form[role=form]"));
+            }
+        }
+    };
+    return Controller;
+});