Browse Source

增加审核

moshaorui 1 month ago
parent
commit
94d2a18cd8

+ 33 - 0
app/Admin/Actions/Grid/ProductAudit.php

@@ -0,0 +1,33 @@
+<?php
+namespace App\Admin\Actions\Grid;
+
+
+use App\Admin\Forms\ProductAudit as ProductAuditForm;
+use Dcat\Admin\Grid\BatchAction;
+use Dcat\Admin\Grid\RowAction;
+use Dcat\Admin\Widgets\Modal;
+
+class ProductAudit extends RowAction
+{
+
+
+    public function title()
+    {
+        return '<i class="feather icon-check-square"></i> '. admin_trans_label('audit');
+    }
+
+
+    public function render()
+    {
+        $form = ProductAuditForm::make()->payload(['id' => $this->getKey()]);
+        // 实例化表单类
+        return Modal::make()
+            ->lg()
+            ->title($this->title)
+            ->body($form)
+            // 因为此处使用了表单异步加载功能,所以一定要用 onLoad 方法
+            ->button($this->title());
+    }
+
+
+}

+ 153 - 0
app/Admin/Controllers/DistProductAuditController.php

@@ -0,0 +1,153 @@
+<?php
+
+namespace App\Admin\Controllers;
+
+use App\Admin\Actions\Grid\AppearanceImport;
+use App\Admin\Actions\Grid\ProductAudit;
+use App\Admin\Repositories\DistAdminDistributor;
+use App\Admin\Repositories\DistAppearance;
+use App\Admin\Repositories\DistProduct;
+use App\Admin\Repositories\DistProductCategory;
+use App\Libraries\CommonHelper;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Http\Controllers\AdminController;
+use Dcat\Admin\Layout\Content;
+use Dcat\Admin\Show;
+
+class DistProductAuditController extends AdminController
+{
+
+    protected function title()
+    {
+        return admin_trans('admin.product');
+    }
+    /**
+     * page index
+     */
+    public function index(Content $content)
+    {
+        return $content
+            ->header(admin_trans( 'admin.products_list'))
+            ->description(admin_trans('admin.all'))
+            ->description('')
+            //->breadcrumb(['text'=>'Product Management','url'=>''])
+            ->body($this->grid());
+    }
+
+
+    /**
+     * Make a grid builder.
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+
+        return Grid::make(DistProduct::with(['distProductCategory','images']), function (Grid $grid)  {
+            //默认分页条数
+            $grid->paginate(config('admin.per_page'));
+            //$grid->model()->where('dist_id', getDistributorId());
+            $grid->column('id')->display(function () {
+                return $this->_index+1;
+            });
+            $grid->column('title');
+            $grid->column('sku');
+            $grid->column('dist_product_category.name',admin_trans_label('category_name'));
+            $grid->column('images')->display(function ($images) {
+                $images = $images->toArray();
+                $dataImages = array_column($images, 'image_url');
+                // 限制最多显示1个缩略图
+                $dataImages = array_slice($dataImages, 0, 1);
+                return CommonHelper::displayImage($dataImages,100);
+            });
+
+            $grid->column('dist_id',admin_trans_label('distributor_name')) ->display(function () {
+                return DistAdminDistributor::getClientCodeById($this->dist_id);
+            });
+
+            $grid->column('status')->using(admin_trans_array(config('dictionary.dist_product_status')))->label([
+                -1 => 'warning',
+                0 => 'default',
+                1 => 'blue',
+                2 => 'success',
+            ]);
+            $grid->column('created_at')->sortable();
+            //$grid->column('updated_at')->sortable();
+            // 筛选
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->panel();
+                $filter->expand();
+                $filter->like('title')->width(2);
+                $filter->equal('sku')->width(2);
+                $filter->equal('status')->select(admin_trans_array(config('dictionary.dist_product_status')))->width(2);
+                $filter->equal('dist_id',admin_trans_label('distributor_name'))->select(DistAdminDistributor::selectOptionsNew(300))->width(3);
+            });
+            //排序
+            $grid->model()->orderBy('created_at', 'desc')->orderBy('id', 'desc');
+            //操作
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->append(new ProductAudit());
+            });
+            //按钮
+            //$grid->disableViewButton();
+            $grid->disableDeleteButton();
+            $grid->disableEditButton();
+            $grid->disableBatchDelete();
+        });
+    }
+
+
+    /**
+     * Make a show builder.
+     *
+     * @param mixed $id
+     *
+     * @return Show
+     */
+    protected function detail($id)
+    {
+
+        return Show::make($id, DistProduct::with(['distProductCategory','images']), function (Show $show) {
+            $show->field('title');
+            $show->field('sku');
+            $show->field('dist_product_category.name',admin_trans_label('category_name'));
+            $show->field('keywords');
+            $show->field('description');
+            $show->field('issuance_date');
+            $show->field('parameters',admin_trans_label('attribute_name'))->as(function ($items) {
+                if (is_array($items)) {
+                    // 创建表格的表头
+                    $table = '<table class="table table-bordered table-condensed">';
+                    // 遍历数组并将数据填充到表格中
+                    foreach ($items as $item) {
+                        $table .= '<tr>';
+                        $table .= '<td style="vertical-align: middle !important;width: 20%">' . $item['key'] . '</td>';    // 商品名称
+                        $table .= '<td style="vertical-align: middle !important;">' . $item['value'] . '</td>'; // 数量
+                        $table .= '</tr>';
+                    }
+                    $table .= '</table>';
+                    return $table;
+                }
+                return ''; // 当没有数组数据时
+            })->unescape();
+            $show->field('images')->as(function ($images) {
+                // 开始生成 HTML
+                $dataImages = array_column($images, 'image_url');
+                return CommonHelper::displayImage($dataImages,150);
+            })->unescape();
+            $show->field('content')->unescape();
+            $show->field('seo_title');
+            $show->field('seo_keywords');
+            $show->field('seo_description');
+            $show->field('order');
+            $show->field('enabled')->using(admin_trans_array(config('dictionary.enabled')));
+            $show->field('created_at');
+            $show->field('updated_at');
+            $show->disableEditButton();
+            $show->disableDeleteButton();
+        });
+    }
+
+
+}

+ 61 - 0
app/Admin/Forms/ProductAudit.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace App\Admin\Forms;
+use App\Admin\Repositories\BaseProductCategory;
+use App\Admin\Repositories\RpcAlbum;
+use App\Libraries\CommonHelper;
+use App\Models\BaseProduct;
+use App\Models\BaseProductImage;
+use Dcat\Admin\Widgets\Form;
+
+class ProductAudit extends Form
+{
+
+
+    public function title()
+    {
+        return 'Copy';
+    }
+
+
+    /**
+     * Handle the form request.
+     *
+     * @param array $input
+     *
+     * @return mixed
+     */
+    public function handle(array $input)
+    {
+        $id = $this->payload['id'] ?? null;
+        
+        return $this
+            ->response()
+            ->success('导入成功')
+            ->refresh();
+    }
+
+
+
+    /**
+     * Build a form here.
+     */
+    public function form()
+    {
+        // 设置隐藏表单,传递用户id
+        $this->select('category_id', admin_trans_label('category_name'))
+            ->options(BaseProductCategory::selectOptions())
+            ->required();
+        $this->hidden('album_ids')->attribute('id', 'album_ids');
+    }
+
+    /**
+     * The data of the form.
+     *
+     * @return array
+     */
+    public function default()
+    {
+        return [];
+    }
+}

+ 7 - 0
app/Admin/Repositories/DistAdminDistributor.php

@@ -21,6 +21,11 @@ class DistAdminDistributor extends EloquentRepository
      */
     protected $eloquentClass = Model::class;
 
+    public static function  getClientCodeById($id)
+    {
+        return Model::where('id', $id)->value('client_code');
+    }
+
     /*
      * 查找最新的N个标签
      */
@@ -29,6 +34,8 @@ class DistAdminDistributor extends EloquentRepository
         return Model::orderBy('created_at', 'desc')->limit($limit)->pluck('client_code', 'id');
     }
 
+
+
     /*
      * 清缓存
      */

+ 60 - 0
app/Admin/Repositories/DistProduct.php

@@ -0,0 +1,60 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Traits\DistSlugTrait;
+use Dcat\Admin\Form;
+use App\Models\DistProduct as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class DistProduct extends EloquentRepository
+{
+    use DistSlugTrait;
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+
+    public function delete(Form $form, array $originalData)
+    {
+        collect(explode(',', $form->getKey()))->filter()->each(function ($id) {
+
+            $product = Model::find($id);
+            if ($product) {
+                // 验证 dist_id
+                if ($product->dist_id !== getDistributorId()) {
+                    throw new \Exception('Unable to modify the product because the distributor ID does not match.');
+                    return;
+                }
+                Model::find($id)->images()->delete();
+                Model::find($id)->delete();
+            }
+        });
+        return true;
+    }
+
+    public static function findById($id)
+    {
+        return Model::find($id); // 查找并返回相应的记录
+    }
+
+
+    /*
+     * 查找最新的N个产品
+     */
+    public static function selectOptionsNew($limit=30)
+    {
+        return Model::where('dist_id', getDistributorId())->where('enabled', 1)->orderBy('created_at', 'desc')->limit($limit)->pluck('title', 'id');
+    }
+
+
+    /*
+     * 获取一个标签
+     */
+    public static function getOneById($id)
+    {
+        return Model::where('id', $id)->where('dist_id', getDistributorId())->first();
+    }
+}

+ 129 - 0
app/Admin/Repositories/DistProductCategory.php

@@ -0,0 +1,129 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\DistProductCategory as Model;
+
+use App\Models\DistProductParameter;
+use App\Traits\DistSlugTrait;
+use Dcat\Admin\Repositories\EloquentRepository;
+use Illuminate\Support\Facades\Session;
+use function Symfony\Component\Translation\t;
+
+class DistProductCategory extends EloquentRepository
+{
+    use DistSlugTrait;
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+
+    public function __construct()
+    {
+
+    }
+
+    // 调用模型方法
+    public static function selectMainOptions(\Closure $closure = null)
+    {
+        // 获取当前登录的分销商/经销商
+        $distributor=Session::get('distributor');
+
+        // 过滤分销商
+        if (!$distributor)
+        {
+            return false;
+        }
+
+        $query = Model::query();
+
+        //通过传入条件限制
+        if ($closure) {
+            $closure($query);
+        }
+
+        // 确保查询构造器不为空
+        if (!$query) {
+            return [];
+        }
+
+        // 过滤分销商
+        $query->where('dist_id', getDistributorId());
+
+        // 返回键值对数组,并按 'name' 和 'order' 字段排序
+        $results = $query->orderBy('order', 'desc')->orderBy('id', 'desc')->pluck('name', 'id');
+
+        // 在每个 name 前面加上 '├─'
+        $results = $results->map(function ($name) {
+            return '├─' . $name;
+        });
+
+        $all = array_replace([0 => admin_trans_label('root')],$results->all());
+        return $all;
+    }
+
+    // 调用模型方法
+    public static function selectOptions(\Closure $closure = null)
+    {
+        if (!$closure) {
+            $closure = function ($query) {
+                $query = $query->where('dist_id', getDistributorId());
+                $query = $query->where('enabled', 1);
+                $query =  $query->orderBy('order', 'desc')->orderBy('id', 'desc');
+                return $query;
+            };
+        }
+
+        $selectOptions = Model::class::selectOptions($closure);
+        return $selectOptions;
+    }
+
+
+    public static function getParameter($categoryId)
+    {
+        $categoryRow =  Model::Class::find($categoryId);
+        if ($categoryRow->baseProductParameter) {
+            return $categoryRow->baseProductParameter->content;
+        } else {
+            return "[]";
+        }
+    }
+
+    /**
+     * @param Grid\Model|\Dcat\Admin\Grid\Model $model
+     * @return array
+     */
+    public function get(Grid\Model|\Dcat\Admin\Grid\Model $model)
+    {
+
+        // 获取模型对象
+        $obj = $this->model();
+
+        $obj = $obj->where('dist_id', getDistributorId())->orderBy('order', 'desc')->orderBy('id', 'desc');
+
+        // 获取数据
+        $tree = $obj->get();
+
+        // 构建树形结构
+        $data=buildTree($tree->toArray());
+        // 转换成一维数组
+        $data=flattenTree($data);
+
+        return $model->makePaginator(
+            count($data), // 传入总记录数
+            $data // 传入数据二维数组
+        );
+    }
+
+
+
+    /*
+     * 获取一个分类
+     */
+    public static function getOneById($id)
+    {
+        return Model::where('id', $id)->where('dist_id', getDistributorId())->first();
+    }
+}

+ 55 - 0
app/Admin/Repositories/DistProductImage.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Admin\Repositories;
+
+use App\Models\DistProductImage as Model;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+class DistProductImage extends EloquentRepository
+{
+    /**
+     * Model.
+     *
+     * @var string
+     */
+    protected $eloquentClass = Model::class;
+
+    //格式化数据,用于多图上传
+    public static function formatData($productId, $images)
+    {
+        $existingImages = Model::where('product_id', $productId)->get();
+        // 用于存储结果的数组
+        $result = [];
+        // 处理条件1:如果数据在 base_product_image 中有,但在 $images 上无
+        foreach ($existingImages as $existingImage) {
+            if (!in_array($existingImage->image_url, $images)) {
+                $result[] = [
+                    'id' => $existingImage->id,
+                    'image_url' => $existingImage->image_url,
+                    '_remove_' => 1,
+                ];
+            }
+        }
+        // 处理条件2:如果数据在 base_product_image 中无,但在 $images 有
+        $i = 1;
+        foreach ($images as $image) {
+            $found = $existingImages->firstWhere('image_url', $image);
+            if (!$found) {
+                $result[] = [
+                    'id' => 0,
+                    'image_url' => $image,
+                    'order' => $i,
+                ];
+            }
+            //更新库中排序
+            foreach ($existingImages as $existingImage) {
+                if ($existingImage->image_url == $image) {
+                    $existingImage->order = $i;
+                    $existingImage->save();
+                }
+            }
+            $i++;
+        }
+        return $result;
+    }
+}

+ 4 - 0
app/Admin/routes.php

@@ -54,6 +54,10 @@ Route::group([
     //产品导入
     $router->get('import-product', 'ImportProductController@index');
     $router->get('import-product/{id}', 'ImportProductController@show');
+
+    //产品审核
+    $router->get('dist-product-audit', 'DistProductAuditController@index');
+    $router->get('dist-product-audit/{id}', 'DistProductAuditController@show');
 });
 
 /*

+ 59 - 10
app/Distributor/Controllers/DistProductController.php

@@ -56,6 +56,7 @@ class DistProductController extends AdminDistController
             });
             $grid->column('title');
             $grid->column('sku');
+
             $grid->column('dist_product_category.name',admin_trans_label('category_name'));
             $grid->column('images')->display(function ($images) {
                 $images = $images->toArray();
@@ -66,8 +67,14 @@ class DistProductController extends AdminDistController
             });
             $grid->column('order')->sortable();
             $grid->column('enabled')->switch();
+            $grid->column('status')->using(admin_trans_array(config('dictionary.dist_product_status')))->label([
+                -1 => 'warning',
+                0 => 'default',
+                1 => 'blue',
+                2 => 'success',
+            ]);
             $grid->column('created_at')->sortable();
-            $grid->column('updated_at')->sortable();
+            //$grid->column('updated_at')->sortable();
             // 筛选
             $grid->filter(function (Grid\Filter $filter) {
                 $filter->panel();
@@ -153,7 +160,6 @@ class DistProductController extends AdminDistController
     protected function form()
     {
         return Form::make(DistProduct::with('images'), function (Form $form) {
-            //$form->display('id');
             $form->select('category_id', admin_trans_label('category_name'))
                 ->options(DistProductCategory::selectOptions())
                 ->required();
@@ -196,13 +202,18 @@ class DistProductController extends AdminDistController
             $form->switch('enabled')->default(1);
             //隐藏字段
             $form->hidden('dist_id'); // 隐藏dist_id字段,用于保存
+            $form->hidden('status');
+            $form->hidden('review_reply');
+            $form->hidden('action');
+
+            $form->ignore(['action']);
+
             //插入JS
             $this->addParametersJs();
             //提交前
             // 在保存时进行验证
             $form->saving(function (Form $form) {
                 $form->dist_id =getDistributorId();//保存时直接写死dist_id
-
                 $id = $form->getKey();
                 //slug配置是否重复
                 if ($form->slug != '') {
@@ -219,18 +230,35 @@ class DistProductController extends AdminDistController
                 if ($form->seo_title == '') {
                     $form->seo_title = $form->title;
                 }
+                //增加审核状态
+                $action = isset($_POST['action']) ? $_POST['action'] : '';
+                if ($form->isCreating()) {
+                    if ($action == 'save') {
+                        $form->status = 0;//待审核
+                    } else {
+                        $form->status = 1;//审核中
+                    }
+                } else {
+                    if (($form->status == 0 || $form->status == -1) && $action == 'submit') {
+                        $form->status = 1;//审核中
+                    }
+                }
             });
+            //页面底部自定义
+            $status = $form->model()->status ?? 0;
+            $isCreating = $form->isCreating() ? 0 : 1;
+            $form->builder()->footer()->view('distributor.form_custom.review-footer',['status'=>$status,'isCreating'=>$isCreating]);
+            //插入JS
+            $this->addReviewJS();
+            //禁用按钮
+            $form->disableViewCheck();
+            $form->disableEditingCheck();
+            $form->disableViewButton();
         });
-    }
 
-    /*
-     * 禁用新增
-     */
-    public function store()
-    {
-        abort(404);
     }
 
+
     /*
      * 以json型式返回产品参数
      */
@@ -252,6 +280,27 @@ class DistProductController extends AdminDistController
             <<<JS
 
 
+JS
+        );
+    }
+
+    /*
+     * 用于点击按钮时,将按钮的 value 值设置到隐藏 input[name="action"] 的值,并提交表单
+     */
+    private function addReviewJS()
+    {
+        Admin::script(
+            <<<JS
+  $('.submit').click(function(e) {
+    // 阻止默认提交行为(可选,视需求而定)
+    e.preventDefault();
+    // 获取当前按钮的 value
+    var value = $(this).val();
+    // 将 value 设置为隐藏 input[name="action"] 的值
+    $('input[name="action"]').val(value);
+    // 提交表单
+    $(this).closest('form').trigger('submit');
+  });
 JS
         );
     }

+ 2 - 0
app/Models/DistProduct.php

@@ -61,4 +61,6 @@ class DistProduct extends Model
         return $this->hasMany(DistProductImage::class, 'product_id')->orderBy('order', 'asc')->orderBy('id', 'asc');
     }
 
+
+
 }

+ 1 - 1
config/admin.php

@@ -213,7 +213,7 @@ return [
     |--------------------------------------------------------------------------
     */
     'helpers' => [
-        'enable' => false,
+        'enable' => true,
     ],
 
     /*

+ 6 - 0
config/dictionary.php

@@ -97,4 +97,10 @@ return [
     'landing_page_contact_us_template' => 'pages_sp_contact.liquid',
 
 
+    'dist_product_status' => [
+        -1 => 'approval_failed',
+        0 => 'draft',
+        1 => 'pending_approval',
+        2 => 'published',
+    ],
 ];

+ 1 - 1
database/migrations/2025_02_08_030746_update_table_v001_1.php

@@ -15,7 +15,7 @@ return new class extends Migration
     {
         //供应商增加新建产品增加审核
         Schema::table('dist_product', function (Blueprint $table) {
-            $table->tinyInteger('status')->default('2')->comment('状态 0待审核 1审核中 2正常 3审核失败');
+            $table->tinyInteger('status')->default('1')->comment('状态 0待审核 1审核中 2正常 -1审核失败 ');
             $table->string('review_reply', 100)->nullable()->comment('审核回复');
         });
     }

+ 3 - 0
lang/en/global.php

@@ -202,6 +202,9 @@ return [
         'top_menu'              => 'Top Menu',
         'bottom_menu'           => 'Bottom Menu',
         'album_folder'          => 'Album Folder',
+        'approval_failed'       => 'Approval Failed',
+        'pending_approval'      => 'Pending Approval',
+        'audit'                 => 'Audit',
     ],
     'options' => [
         //

+ 1 - 0
lang/zh_CN/admin.php

@@ -260,4 +260,5 @@ return [
     'messages' => '消息',
     'crop_the_image' => '裁剪图片',
     'promotional_materials' => '宣传资料',
+    'save' => '保存',
 ];

+ 4 - 0
lang/zh_CN/global.php

@@ -211,6 +211,10 @@ return [
         'top_menu'              => '顶部菜单',
         'bottom_menu'           => '底部菜单',
         'album_folder'          => '相册分类',
+        'approval_failed'       => '审批失败',
+        'pending_approval'      => '待审批',
+        'distributor_name'    => "分销商名称",
+        'audit' => '审核',
     ],
     'options' => [
         //

+ 1 - 0
lang/zh_CN/menu.php

@@ -54,5 +54,6 @@ return [
         'messages' => '消息',
         'banner'  =>'轮播图',
         'promotional_materials'  =>'宣传资料',
+        'product_audit'  =>'产品审核',
     ],
 ];

+ 1 - 1
resources/views/admin/form/footer.blade.php

@@ -21,4 +21,4 @@
         </div>
         @endif
     </div>
-</div>
+</div>

+ 1 - 1
resources/views/distributor/form/footer.blade.php

@@ -21,4 +21,4 @@
         </div>
         @endif
     </div>
-</div>
+</div>

+ 35 - 0
resources/views/distributor/form_custom/review-footer.blade.php

@@ -0,0 +1,35 @@
+<div class="box-footer">
+
+    <div class="col-md-{{$width['label']}} d-md-block" style="display: none"></div>
+
+    <div class="col-md-{{$width['field']}}">
+
+        @if(! empty($buttons['submit']))
+            <div class="pull-right">
+                @if ($isCreating == 0)
+                <button  class="btn btn-primary submit" name="action" value="save" ><i class="feather icon-save"></i> {{ trans('admin.save') }}</button>
+
+                <button  class="btn btn-success submit" style="margin-left: 10px" name="action" value="submit" ><i class="feather icon-chevron-right"></i> {{ trans('admin.submit') }}</button>
+                @else
+                    @if ($status != 1)
+                    <button  class="btn btn-primary submit" name="action" value="save" ><i class="feather icon-save"></i> {{ trans('admin.save') }}</button>
+                    @endif
+                    @if ($status == 0 || $status == -1)
+                        <button  class="btn btn-success submit" style="margin-left: 10px" name="action" value="submit" ><i class="feather icon-chevron-right"></i> {{ trans('admin.submit') }}</button>
+                    @endif
+                @endif
+            </div>
+
+            @if($checkboxes)
+                <div class="pull-right d-md-flex" style="margin:10px 15px 0 0;display: none">{!! $checkboxes !!}</div>
+            @endif
+
+        @endif
+
+        @if(! empty($buttons['reset']))
+        <div class="btn-group pull-left">
+            <button type="reset" class="btn btn-white"><i class="feather icon-rotate-ccw"></i> {{ trans('admin.reset') }}</button>
+        </div>
+        @endif
+    </div>
+</div>