Browse Source

Merge branch 'refs/heads/master_verify'

# Conflicts:
#	lang/en/global.php
#	lang/zh_CN/global.php
moshaorui 1 month ago
parent
commit
7cff8378c5

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

@@ -0,0 +1,34 @@
+<?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  admin_trans_label('product_audit');
+    }
+
+
+    public function render()
+    {
+        $form = ProductAuditForm::make()->payload(['id' => $this->getKey(),'review_reply'=>$this->row->review_reply]);
+        // 实例化表单类
+        return Modal::make()
+            ->lg()
+            ->title($this->title)
+            ->body($form)
+            ->button($this->title());
+    }
+
+
+
+
+}

+ 0 - 4
app/Admin/Actions/Tools/InquiryHandle.php

@@ -48,15 +48,11 @@ class InquiryHandle extends AbstractTool
         $keys = $request->input('_key');
         if (is_array($keys) && count($keys) > 0) {
             $result = DistInquiry::distSetStatusProcessed($keys);
-            if ($result === false) {
-                return $this->response()->error('Failed to process!')->refresh();
-            }
             return $this->response()->success(admin_trans_label('update_success'))->refresh();
         } else {
             return $this->response()->error('No data selected!')->refresh();
         }
         // 你的代码逻辑
-
     }
 
 

+ 1 - 0
app/Admin/Controllers/BaseProductController.php

@@ -70,6 +70,7 @@ class BaseProductController extends AdminController
             });
             //排序
             $grid->model()->orderBy('created_at','desc');
+            $grid->disableViewButton();
         });
     }
 

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

@@ -0,0 +1,171 @@
+<?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\Admin;
+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 => 'danger',
+                0 => 'gray',
+                1 => 'orange1',
+                2 => 'success',
+            ])->display(function($status) {
+                if ($this->status == -1) {
+                    return '<span  class="status-popover" data-container="body" data-toggle="popover" data-placement="top" data-content="'.$this->review_reply.'">'.$status.'</span>';
+                }
+                return $status;
+            });
+            $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) {
+                if ($this->status == 1) {
+                    $actions->append(new ProductAudit());
+                }
+            });
+            //按钮
+            //$grid->disableViewButton();
+            $grid->disableDeleteButton();
+            $grid->disableEditButton();
+            $grid->disableBatchDelete();
+            $this->addGridJS();
+        });
+    }
+
+
+    /**
+     * 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();
+        });
+    }
+
+    private function addGridJS()
+    {
+        Admin::script(
+            <<<JS
+ $('.status-popover').popover({
+    container: 'body',
+     trigger: 'hover'
+  })
+JS
+        );
+    }
+}

+ 12 - 6
app/Admin/Forms/AceLeft.php

@@ -7,19 +7,25 @@ use App\Models\DistAdminDistributor;
 use Symfony\Component\HttpFoundation\Response;
 use Dcat\Admin\Widgets\Form;
 use App\Admin\Repositories\DistAppearance;
+use App\Admin\Repositories\DistAdminDistributor as DistAdminDistributorRepository;
 
 class AceLeft extends Form
 {
     public function form()
     {
         //供应商选择
-        $this->selectTable('dist_id', 'Select Distributor')
+//        $this->selectTable('dist_id', 'Select Distributor')
+//            ->width(12,12)
+//            ->setLabelClass('d-flex')
+//            ->title('Select Distributor')
+//            ->placeholder('Select Distributor')
+//            ->model(DistAdminDistributor::class, 'id', 'client_code')
+//            ->from(DistDistributorTable::make());
+
+        $this->select('dist_id', 'Select Distributor')
+            ->options(DistAdminDistributorRepository::selectOptionsNew(1000))
             ->width(12,12)
-            ->setLabelClass('d-flex')
-            ->title('Select Distributor')
-            ->placeholder('Select Distributor')
-            ->model(DistAdminDistributor::class, 'id', 'client_code')
-            ->from(DistDistributorTable::make());
+            ->setLabelClass('d-flex');
 
         //主题选择
         $this->select('appearance_id','Select Appearance')

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

@@ -0,0 +1,52 @@
+<?php
+
+namespace App\Admin\Forms;
+use App\Admin\Repositories\BaseProductCategory;
+use App\Admin\Repositories\DistProduct;
+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
+{
+
+
+
+    /**
+     * Handle the form request.
+     *
+     * @param array $input
+     *
+     * @return mixed
+     */
+    public function handle(array $input)
+    {
+        $id = $this->payload['id'] ?? null;
+
+        $reviewReply = $input['review_reply'] ?? '';
+        $status = $input['status'] ?? null;
+        if (empty($status) || empty($id)) {
+            return $this->response()->error('参数错误');
+        }
+        DistProduct::auditProduct($id, $status, $reviewReply);
+        return $this
+            ->response()
+            ->success('审批成功')
+            ->refresh();
+    }
+
+
+    /**
+     * Build a form here.
+     */
+    public function form()
+    {
+        $review_reply = $this->payload['review_reply'] ?? null;
+        // 设置隐藏表单,传递用户id
+        $this->radio('status')->options(['2' => admin_trans_label('audit_success'), '-1'=> admin_trans_label('approval_failed')])->default('2');
+        $this->textarea('review_reply')->default($review_reply);
+    }
+
+}

+ 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');
     }
 
+
+
     /*
      * 清缓存
      */

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

@@ -0,0 +1,73 @@
+<?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();
+    }
+
+    /*
+     * 审核产品
+     */
+    public static function auditProduct($id , $status , $reviewReply) {
+        $product = Model::find($id);
+        if ($product) {
+            $product->status = $status;
+            $product->review_reply = $reviewReply;
+            $product->save();
+        }
+        return true;
+    }
+}

+ 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');
 });
 
 /*

+ 2 - 2
app/Distributor/Controllers/DistInquiryController.php

@@ -69,10 +69,10 @@ class DistInquiryController extends AdminDistController
             $grid->disableDeleteButton();
             $grid->disableBatchDelete();
             $grid->showViewButton();
-            if ($status == 1) {
+          //  if ($status == 1) {
                 //批量操作
                 $grid->tools([new InquiryHandle()]);
-            }
+          //  }
             //权限与排序
             $grid->model()->where('dist_id', getDistributorId())->where('status','>',0)->orderBy("id",'desc');
         });

+ 78 - 11
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,19 @@ 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 => 'danger',
+                0 => 'gray',
+                1 => 'orange1',
+                2 => 'success',
+            ])->display(function($status) {
+                if ($this->status == -1) {
+                    return '<span  class="status-popover" data-container="body" data-toggle="popover" data-placement="top" data-content="'.$this->review_reply.'">'.$status.'</span>';
+                }
+                return $status;
+            });
             $grid->column('created_at')->sortable();
-            $grid->column('updated_at')->sortable();
+            //$grid->column('updated_at')->sortable();
             // 筛选
             $grid->filter(function (Grid\Filter $filter) {
                 $filter->panel();
@@ -84,7 +96,9 @@ class DistProductController extends AdminDistController
                 new DistProductImport(),
             ]);
             //按钮
-            $grid->disableCreateButton();
+            //$grid->disableCreateButton();
+            $grid->disableViewButton();
+            $this->addGridJS();
         });
 
     }
@@ -152,7 +166,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();
@@ -195,13 +208,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 != '') {
@@ -218,18 +236,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型式返回产品参数
      */
@@ -251,6 +286,38 @@ 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
+        );
+    }
+    private function addGridJS()
+    {
+        Admin::script(
+<<<JS
+ $('.status-popover').popover({
+    container: 'body',
+     trigger: 'hover'
+  })
 JS
         );
     }

+ 2 - 2
app/Distributor/Forms/ImportProduct.php

@@ -48,8 +48,6 @@ class ImportProduct extends Form
 // 获取 base_product_image 表中与当前 base_product 相关的图片记录
                 $baseProductImages = BaseProductImage::where('product_id', $baseProduct->id)->get();
 
-
-
                 // 创建新的 DistProduct 记录
                 $distProduct = DistProduct::create([
                     'category_id' => $categoryId,
@@ -66,6 +64,8 @@ class ImportProduct extends Form
                     'dist_id' => getDistributorId(),
                     'created_at' => now(), // 自动填充创建时间
                     'updated_at' => now(), // 自动填充更新时间
+                    'status' => 2,
+                    'review_reply' => '',
                 ]);
                 DistProduct::where('id', $distProduct->id)->update(['slug' => $distProduct->id]);
                 // 遍历 base_product_image 表中的记录,并插入到 dist_product_image 表中

+ 4 - 0
app/Models/DistProduct.php

@@ -45,6 +45,8 @@ class DistProduct extends Model
         'seo_keywords',
         'seo_description',
         'slug',
+        'status',
+        'review_reply'
     ];
 
 
@@ -59,4 +61,6 @@ class DistProduct extends Model
         return $this->hasMany(DistProductImage::class, 'product_id')->orderBy('order', 'asc')->orderBy('id', 'asc');
     }
 
+
+
 }

+ 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',
+    ],
 ];

+ 32 - 0
database/migrations/2025_02_08_030746_update_table_v001_1.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        //供应商增加新建产品增加审核
+        Schema::table('dist_product', function (Blueprint $table) {
+            $table->tinyInteger('status')->default('1')->comment('状态 0待审核 1审核中 2正常 -1审核失败 ');
+            $table->string('review_reply', 100)->nullable()->comment('审核回复');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        //
+    }
+};

+ 1 - 0
lang/en/global.php

@@ -105,6 +105,7 @@ return [
         'pdf_title'             => 'PDF Title',
         'pdf_src'               => 'PDF Src',
         'video_src'             => 'Video Src',
+        'review_reply'          => 'Review Reply',
         'title_en'              => 'Title',
     ],
     'labels' => [

+ 1 - 0
lang/zh_CN/admin.php

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

+ 1 - 0
lang/zh_CN/global.php

@@ -111,6 +111,7 @@ return [
         'pdf_title'             => 'PDF标题',
         'pdf_src'               => 'PDF文件',
         'video_src'             => '视频文件',
+        'review_reply'          => '回复',
         'title_en'              => '标题',
     ],
     'labels' => [

+ 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>

+ 11 - 10
resources/views/admin/pages-custom/ace.blade.php

@@ -282,7 +282,7 @@
 
         var changeIframeUrl = function() {
             appearance_id = $('select[name="appearance_id"]').val();
-            dist_id = $('input[name="dist_id"]').val();
+            dist_id = $('select[name="dist_id"]').val();
             var iframeUrl = '/prime-control/dist-template-var?templateCode=' + fileId + '&appearanceId=' + appearance_id+'&distId=' + dist_id;
             $('#iframeModal iframe').attr('src', iframeUrl);
         }
@@ -302,7 +302,7 @@
                     shade: [0.5, '#000'] // 设置遮罩层
                 });
                 var appearance_id = $('select[name="appearance_id"]').val();
-                var dist_id = $('input[name="dist_id"]').val();
+                var dist_id = $('select[name="dist_id"]').val();
                 fileId = $(this).attr('file_id');
                 //得到文件名
                 fileName = $(this).html();
@@ -337,7 +337,7 @@
         // 加载代码树
         var postData = function () {
             var appearance_id = $('select[name="appearance_id"]').val();
-            var dist_id = $('input[name="dist_id"]').val();
+            var dist_id = $('select[name="dist_id"]').val();
             //改变iframe的url
             changeIframeUrl();
             $.ajax({
@@ -373,7 +373,7 @@
             postData();
         });
         //分销商选择
-        $('input[name="dist_id"]').change(function() {
+        $('select[name="dist_id"]').change(function() {
             //console.log('-------0-----')
             loadingIndex = layer.load(1, {
                 shade: [0.5, '#000'] // 设置遮罩层
@@ -413,7 +413,8 @@
         // 模版编辑保存
         $("#save-btn").click(function() {
             var appearance_id = $('select[name="appearance_id"]').val();
-            var dist_id = $('input[name="dist_id"]').val();
+            var dist_id = $('select[name="dist_id"]').val();
+            // console.log(dist_id);
             var template_id = $("#template_id").val();
             var content = editor.getValue();
             if (template_id == '') {
@@ -452,7 +453,7 @@
         // 模版发布
         $("#publish-btn").click(function() {
             var appearance_id = $('select[name="appearance_id"]').val();
-            var dist_id = $('input[name="dist_id"]').val();
+            var dist_id = $('select[name="dist_id"]').val();
 
             if (appearance_id == '') {
                 Dcat.error('操作失败:请先选择主题');
@@ -516,7 +517,7 @@
             var filePathName = $('#file_path_name').val();
             var fileInputName = $('#file_name_input').val();
             var appearanceId = $('select[name="appearance_id"]').val();
-            var distId = $('input[name="dist_id"]').val();
+            var distId = $('select[name="dist_id"]').val();
             if (fileInputName == '') {
                 Dcat.error('文件名不能为空');
                 return false;
@@ -533,7 +534,7 @@
                     var filePathName = "";
                     var fileInputName = "";
                     var appearanceId = $('select[name="appearance_id"]').val();
-                    var distId = $('input[name="dist_id"]').val();
+                    var distId = $('select[name="dist_id"]').val();
                     var fileId = $(this).attr('file_id');
                     var fileName = $(this).attr('file_name');
                     msg = '确定要删除'+fileName+'吗?';
@@ -551,7 +552,7 @@
                 shade: [0.5, '#000'] // 设置遮罩层
             });
             var appearanceId = $('select[name="appearance_id"]').val();
-            var distId = $('input[name="dist_id"]').val();
+            var distId = $('select[name="dist_id"]').val();
             if (fileId == '') {
                 Dcat.error('操作失败:请先选择模板');
                 return false;
@@ -604,7 +605,7 @@
             //
             var logId = $(this).attr('log_id');
             var appearanceId = $('select[name="appearance_id"]').val();
-            var distId = $('input[name="dist_id"]').val();
+            var distId = $('select[name="dist_id"]').val();
             $.ajax({
                 url: '/prime-control/dist-template/ace',
                 method: 'POST',

+ 51 - 37
resources/views/admin/pages/login.blade.php

@@ -12,6 +12,7 @@
     .login-btn {
         padding-left: 2rem!important;;
         padding-right: 1.5rem!important;
+        width: 100%;
     }
     .content {
         overflow-x: hidden;
@@ -19,6 +20,18 @@
     .form-group .control-label {
         text-align: left;
     }
+    .justify-content-between {
+        margin-top: 1rem;
+    }
+    #captcha {
+        width: 185px;
+        float: left;
+    }
+    .captcha-img {
+        float: right;
+        width: 110px;
+        height: 34px;
+    }
 </style>
 
 <div class="login-page bg-40">
@@ -28,7 +41,7 @@
         </div>
         <div class="card">
             <div class="card-body login-card-body shadow-100">
-{{--                <p class="login-box-msg mt-1 mb-1">{{ __('admin.welcome_back') }}</p>--}}
+                {{--                <p class="login-box-msg mt-1 mb-1">{{ __('admin.welcome_back') }}</p>--}}
 
                 <form id="login-form" method="POST" action="{{ admin_url('auth/login') }}">
 
@@ -36,13 +49,13 @@
 
                     <fieldset class="form-label-group form-group position-relative has-icon-left">
                         <input
-                                type="text"
-                                class="form-control {{ $errors->has('username') ? 'is-invalid' : '' }}"
-                                name="username"
-                                placeholder="{{ trans('admin.username') }}"
-                                value="{{ old('username') }}"
-                                required
-                                autofocus
+                            type="text"
+                            class="form-control {{ $errors->has('username') ? 'is-invalid' : '' }}"
+                            name="username"
+                            placeholder="{{ trans('admin.username') }}"
+                            value="{{ old('username') }}"
+                            required
+                            autofocus
                         >
 
                         <div class="form-control-position">
@@ -63,15 +76,15 @@
 
                     <fieldset class="form-label-group form-group position-relative has-icon-left">
                         <input
-                                minlength="5"
-                                maxlength="20"
-                                id="password"
-                                type="password"
-                                class="form-control {{ $errors->has('password') ? 'is-invalid' : '' }}"
-                                name="password"
-                                placeholder="{{ trans('admin.password') }}"
-                                required
-                                autocomplete="current-password"
+                            minlength="5"
+                            maxlength="20"
+                            id="password"
+                            type="password"
+                            class="form-control {{ $errors->has('password') ? 'is-invalid' : '' }}"
+                            name="password"
+                            placeholder="{{ trans('admin.password') }}"
+                            required
+                            autocomplete="current-password"
                         >
 
                         <div class="form-control-position">
@@ -100,6 +113,7 @@
                             placeholder="{{ trans('admin.captcha') }}"
                             required
                         >
+                        <img src="/prime-control/captcha?{{ time() }}" alt="captcha" class="captcha-img" onclick="this.src='/prime-control/captcha?'+Math.random()">
 
                         <div class="form-control-position">
                             <i class="feather icon-image"></i>
@@ -114,39 +128,39 @@
                                 @endforeach
                             </span>
                         @endif
-                        <img src="/prime-control/captcha?{{ time() }}" alt="captcha" class="captcha-img" onclick="this.src='/prime-control/captcha?'+Math.random()">
+
                     </fieldset>
 
+                    <button type="submit" class="btn btn-primary float-letf login-btn">
+                        {{ __('admin.login') }}
+                        <i class="feather icon-arrow-right"></i>
+                    </button>
+
                     <div class="form-group d-flex justify-content-between align-items-center">
                         <div class="text-left">
                             @if(config('admin.auth.remember'))
-                            <fieldset class="checkbox">
-                                <div class="vs-checkbox-con vs-checkbox-primary">
-                                    <input id="remember" name="remember"  value="1" type="checkbox" {{ old('remember') ? 'checked' : '' }}>
-                                    <span class="vs-checkbox">
+                                <fieldset class="checkbox">
+                                    <div class="vs-checkbox-con vs-checkbox-primary">
+                                        <input id="remember" name="remember"  value="1" type="checkbox" {{ old('remember') ? 'checked' : '' }}>
+                                        <span class="vs-checkbox">
                                                         <span class="vs-checkbox--check">
                                                           <i class="vs-icon feather icon-check"></i>
                                                         </span>
                                                     </span>
-                                    <span> {{ trans('admin.remember_me') }}</span>
-                                </div>
-                            </fieldset>
+                                        <span> {{ trans('admin.remember_me') }}</span>
+                                    </div>
+                                </fieldset>
                             @endif
                         </div>
                     </div>
+
                     <div class="form-group d-flex justify-content-between align-items-center">
                         <div class="text-left">
                             <a class="lang-item" href="javascript:void(0);" data-lang="en">English</a>
-                           / <a class="lang-item" href="javascript:void(0);" data-lang="zh_CN">中文</a>
+                            / <a class="lang-item" href="javascript:void(0);" data-lang="zh_CN">中文</a>
                         </div>
                     </div>
 
-                    <button type="submit" class="btn btn-primary float-right login-btn">
-
-                        {{ __('admin.login') }}
-                        &nbsp;
-                        <i class="feather icon-arrow-right"></i>
-                    </button>
                 </form>
 
             </div>
@@ -155,12 +169,12 @@
 </div>
 
 <script>
-Dcat.ready(function () {
-    // ajax表单提交
-    $('#login-form').form({
-        validate: true,
+    Dcat.ready(function () {
+        // ajax表单提交
+        $('#login-form').form({
+            validate: true,
+        });
     });
-});
 </script>
 <script>
     document.querySelectorAll('.lang-item').forEach(item => {

+ 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>

+ 51 - 38
resources/views/distributor/pages/login.blade.php

@@ -12,6 +12,7 @@
     .login-btn {
         padding-left: 2rem!important;;
         padding-right: 1.5rem!important;
+        width: 100%;
     }
     .content {
         overflow-x: hidden;
@@ -19,6 +20,18 @@
     .form-group .control-label {
         text-align: left;
     }
+    .justify-content-between {
+        margin-top: 1rem;
+    }
+    #captcha {
+        width: 185px;
+        float: left;
+    }
+    .captcha-img {
+        float: right;
+        width: 110px;
+        height: 34px;
+    }
 </style>
 
 <div class="login-page bg-40">
@@ -28,7 +41,7 @@
         </div>
         <div class="card">
             <div class="card-body login-card-body shadow-100">
-{{--                <p class="login-box-msg mt-1 mb-1">{{ __('admin.welcome_back') }}</p>--}}
+                {{--                <p class="login-box-msg mt-1 mb-1">{{ __('admin.welcome_back') }}</p>--}}
 
                 <form id="login-form" method="POST" action="{{ admin_url('auth/login') }}">
 
@@ -36,13 +49,13 @@
 
                     <fieldset class="form-label-group form-group position-relative has-icon-left">
                         <input
-                                type="text"
-                                class="form-control {{ $errors->has('username') ? 'is-invalid' : '' }}"
-                                name="username"
-                                placeholder="{{ trans('admin.username') }}"
-                                value="{{ old('username') }}"
-                                required
-                                autofocus
+                            type="text"
+                            class="form-control {{ $errors->has('username') ? 'is-invalid' : '' }}"
+                            name="username"
+                            placeholder="{{ trans('admin.username') }}"
+                            value="{{ old('username') }}"
+                            required
+                            autofocus
                         >
 
                         <div class="form-control-position">
@@ -63,15 +76,15 @@
 
                     <fieldset class="form-label-group form-group position-relative has-icon-left">
                         <input
-                                minlength="5"
-                                maxlength="20"
-                                id="password"
-                                type="password"
-                                class="form-control {{ $errors->has('password') ? 'is-invalid' : '' }}"
-                                name="password"
-                                placeholder="{{ trans('admin.password') }}"
-                                required
-                                autocomplete="current-password"
+                            minlength="5"
+                            maxlength="20"
+                            id="password"
+                            type="password"
+                            class="form-control {{ $errors->has('password') ? 'is-invalid' : '' }}"
+                            name="password"
+                            placeholder="{{ trans('admin.password') }}"
+                            required
+                            autocomplete="current-password"
                         >
 
                         <div class="form-control-position">
@@ -89,7 +102,6 @@
                         @endif
 
                     </fieldset>
-
                     <fieldset class="form-label-group form-group position-relative has-icon-left">
                         <input
                             minlength="6"
@@ -101,6 +113,7 @@
                             placeholder="{{ trans('admin.captcha') }}"
                             required
                         >
+                        <img src="/dist/captcha?{{ time() }}" alt="captcha" class="captcha-img" onclick="this.src='/dist/captcha?'+Math.random()">
 
                         <div class="form-control-position">
                             <i class="feather icon-image"></i>
@@ -115,38 +128,39 @@
                                 @endforeach
                             </span>
                         @endif
-                        <img src="/dist/captcha?{{ time() }}" alt="captcha" class="captcha-img" onclick="this.src='/dist/captcha?'+Math.random()">
+
                     </fieldset>
 
-              <div class="form-group d-flex justify-content-between align-items-center">
+                    <button type="submit" class="btn btn-primary float-letf login-btn">
+                        {{ __('admin.login') }}
+                        <i class="feather icon-arrow-right"></i>
+                    </button>
+
+                    <div class="form-group d-flex justify-content-between align-items-center">
                         <div class="text-left">
                             @if(config('admin.auth.remember'))
-                            <fieldset class="checkbox">
-                                <div class="vs-checkbox-con vs-checkbox-primary">
-                                    <input id="remember" name="remember"  value="1" type="checkbox" {{ old('remember') ? 'checked' : '' }}>
-                                    <span class="vs-checkbox">
+                                <fieldset class="checkbox">
+                                    <div class="vs-checkbox-con vs-checkbox-primary">
+                                        <input id="remember" name="remember"  value="1" type="checkbox" {{ old('remember') ? 'checked' : '' }}>
+                                        <span class="vs-checkbox">
                                                         <span class="vs-checkbox--check">
                                                           <i class="vs-icon feather icon-check"></i>
                                                         </span>
                                                     </span>
-                                    <span> {{ trans('admin.remember_me') }}</span>
-                                </div>
-                            </fieldset>
+                                        <span> {{ trans('admin.remember_me') }}</span>
+                                    </div>
+                                </fieldset>
                             @endif
                         </div>
                     </div>
+
                     <div class="form-group d-flex justify-content-between align-items-center">
                         <div class="text-left">
                             <a class="lang-item" href="javascript:void(0);" data-lang="en">English</a>
                             / <a class="lang-item" href="javascript:void(0);" data-lang="zh_CN">中文</a>
                         </div>
                     </div>
-                    <button type="submit" class="btn btn-primary float-right login-btn">
 
-                        {{ __('admin.login') }}
-                        &nbsp;
-                        <i class="feather icon-arrow-right"></i>
-                    </button>
                 </form>
 
             </div>
@@ -155,14 +169,13 @@
 </div>
 
 <script>
-Dcat.ready(function () {
-    // ajax表单提交
-    $('#login-form').form({
-        validate: true,
+    Dcat.ready(function () {
+        // ajax表单提交
+        $('#login-form').form({
+            validate: true,
+        });
     });
-});
 </script>
-
 <script>
     document.querySelectorAll('.lang-item').forEach(item => {
         item.addEventListener('click', function() {