first
This commit is contained in:
11
modules/.gitignore
vendored
Normal file
11
modules/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
*
|
||||
!.gitignore
|
||||
!pull-all.sh
|
||||
!README.md
|
||||
!Cms
|
||||
!Configuration
|
||||
!Mall
|
||||
!Payment
|
||||
!Storage
|
||||
!Task
|
||||
!User
|
||||
4
modules/Cms/.gitignore
vendored
Normal file
4
modules/Cms/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.idea
|
||||
vendor
|
||||
.DS_Store
|
||||
composer.lock
|
||||
88
modules/Cms/Cms.php
Normal file
88
modules/Cms/Cms.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms;
|
||||
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class Cms extends Facade
|
||||
{
|
||||
|
||||
protected static string $mainTitle = '内容管理';
|
||||
|
||||
/**
|
||||
* Notes : 模块初始化要做的一些操作
|
||||
* @Date : 2021/3/12 11:34 上午
|
||||
* @Author : < Jason.C >
|
||||
*/
|
||||
public static function install()
|
||||
{
|
||||
Artisan::call('migrate', [
|
||||
'--path' => 'modules/Cms/Database/Migrations',
|
||||
]);
|
||||
|
||||
self::createAdminMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 卸载模块的一些操作
|
||||
* @Date : 2021/3/12 11:35 上午
|
||||
* @Author : < Jason.C >
|
||||
*/
|
||||
public static function uninstall()
|
||||
{
|
||||
$menu = config('admin.database.menu_model');
|
||||
|
||||
$mains = $menu::where('title', self::$mainTitle)->get();
|
||||
|
||||
foreach ($mains as $main) {
|
||||
$main->delete();
|
||||
}
|
||||
}
|
||||
|
||||
protected static function createAdminMenu()
|
||||
{
|
||||
$menu = config('admin.database.menu_model');
|
||||
|
||||
$main = $menu::create([
|
||||
'parent_id' => 0,
|
||||
'order' => 15,
|
||||
'title' => self::$mainTitle,
|
||||
'icon' => 'fa-wordpress',
|
||||
]);
|
||||
|
||||
$main->children()->createMany([
|
||||
[
|
||||
'order' => 1,
|
||||
'title' => '文章管理',
|
||||
'icon' => 'fa-bars',
|
||||
'uri' => 'cms/articles',
|
||||
],
|
||||
[
|
||||
'order' => 2,
|
||||
'title' => '单页管理',
|
||||
'icon' => 'fa-newspaper-o',
|
||||
'uri' => 'cms/pages',
|
||||
],
|
||||
[
|
||||
'order' => 3,
|
||||
'title' => '分类管理',
|
||||
'icon' => 'fa-indent',
|
||||
'uri' => 'cms/categories',
|
||||
],
|
||||
[
|
||||
'order' => 4,
|
||||
'title' => '标签管理',
|
||||
'icon' => 'fa-tags',
|
||||
'uri' => 'cms/tags',
|
||||
],
|
||||
[
|
||||
'order' => 5,
|
||||
'title' => '素材管理',
|
||||
'icon' => 'fa-adjust',
|
||||
'uri' => 'cms/storages',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
10
modules/Cms/Config/config.php
Normal file
10
modules/Cms/Config/config.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 模块名称
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'name' => 'Cms',
|
||||
];
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateCmsArticleCategoryTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cms_article_category', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('article_id');
|
||||
$table->unsignedBigInteger('category_id');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cms_article_category');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateCmsArticlesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cms_articles', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('slug')->index()->nullable()->comment('唯一的别名');
|
||||
$table->string('title');
|
||||
$table->string('sub_title')->nullable()->comment('副标题');
|
||||
$table->string('description')->nullable();
|
||||
$table->string('cover')->nullable();
|
||||
$table->json('pictures')->nullable();
|
||||
$table->text('content');
|
||||
$table->json('attachments')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->unsignedInteger('clicks')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cms_articles');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateCmsCategoriesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cms_categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('parent_id')->index()->default(0);
|
||||
$table->string('title');
|
||||
$table->string('slug')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->string('cover')->nullable();
|
||||
$table->json('pictures')->nullable();
|
||||
$table->text('content')->nullable();
|
||||
$table->integer('order')->default(0);
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cms_categories');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateCmsPagesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cms_pages', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('slug')->index()->nullable()->comment('唯一的别名');
|
||||
$table->string('title');
|
||||
$table->string('sub_title')->nullable()->comment('副标题');
|
||||
$table->string('description')->nullable();
|
||||
$table->string('cover')->nullable();
|
||||
$table->json('pictures')->nullable();
|
||||
$table->text('content');
|
||||
$table->json('attachments')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->unsignedInteger('clicks')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cms_pages');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateCmsTaggableTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cms_taggable', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('tag_id')->index();
|
||||
$table->morphs('taggable');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cms_taggable');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateCmsTagsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cms_tags', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->comment('定位名称');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cms_tags');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateCmsStoragesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cms_storages', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('url')->nullable();
|
||||
$table->string('cover');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cms_storages');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateCmsLogsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('cms_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->unsignedBigInteger('article_id')->index();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('cms_logs');
|
||||
}
|
||||
}
|
||||
136
modules/Cms/Http/Controllers/Admin/ArticleController.php
Normal file
136
modules/Cms/Http/Controllers/Admin/ArticleController.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Illuminate\Support\Arr;
|
||||
use Modules\Cms\Models\Article;
|
||||
use Modules\Cms\Models\Category;
|
||||
use Modules\Cms\Models\Tag;
|
||||
|
||||
class ArticleController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads;
|
||||
|
||||
protected $title = '文章管理';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Article());
|
||||
|
||||
$grid->model()->with('categories')->withCount('versions');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('trashed', '回收站')->onlyTrashed();
|
||||
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('title', '文章标题');
|
||||
$filter->like('slug', 'SLUG');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('categories.title', '所属分类');
|
||||
$filter->like('tags.name', '标签');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('status', '状态')->select(Article::getStatusMap());
|
||||
});
|
||||
});
|
||||
|
||||
$grid->column('id', '#ID#');
|
||||
$grid->column('categories', '所属分类')->display(function ($categories) {
|
||||
return Arr::pluck($categories, 'title');
|
||||
})->label();
|
||||
// $grid->column('tags')->pluck('name')->label('warning');
|
||||
$grid->column('title', '文章标题');
|
||||
// $grid->column('slug', 'SLUG');
|
||||
$grid->column('status', '状态')->bool();
|
||||
$grid->column('clicks', '浏览量');
|
||||
$grid->column('versions_count', '历史版本')->link(function () {
|
||||
return route('admin.cms.versions', [
|
||||
'model' => get_class($this),
|
||||
'key' => $this->id,
|
||||
]);
|
||||
}, '_self');
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 内容表单
|
||||
* @Date : 2021/3/15 5:21 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Encore\Admin\Form
|
||||
*/
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Article());
|
||||
|
||||
$form->text('title', '文章标题')
|
||||
->rules([
|
||||
'required',
|
||||
'max:255',
|
||||
], [
|
||||
'max' => '标题最大长度不能超过 :max 个字符',
|
||||
])
|
||||
->required();
|
||||
// $form->text('sub_title', '副标题')
|
||||
// ->rules([
|
||||
// 'nullable',
|
||||
// 'max:255',
|
||||
// ], [
|
||||
// 'max' => '标题最大长度不能超过 :max 个字符',
|
||||
// ]);
|
||||
// $form->text('slug', '英文别名')
|
||||
// ->rules([
|
||||
// 'nullable',
|
||||
// 'alpha_dash',
|
||||
// ], [
|
||||
// 'alpha_dash' => '别名中包含非法字符',
|
||||
// ])
|
||||
// ->help('字母、数字、下划线组成,用来展示简短的URL');
|
||||
|
||||
$form->multipleSelect('categories', '所属分类')
|
||||
->options(Category::selectOptions(function ($model) {
|
||||
return $model->where('status', 1);
|
||||
}, '请选择文章分类'))
|
||||
->required();
|
||||
|
||||
// $form->multipleSelect('tags', '内容标签')
|
||||
// ->options(function () {
|
||||
// return Tag::pluck('name', 'id');
|
||||
// });
|
||||
|
||||
$this->cover($form);
|
||||
|
||||
// $this->pictures($form);
|
||||
|
||||
$form->textarea('description', '文章简介')
|
||||
->rules([
|
||||
'nullable',
|
||||
'max:255',
|
||||
], [
|
||||
'max' => '标题最大长度不能超过 :max 个字符',
|
||||
]);
|
||||
|
||||
$form->ueditor('content', '文章内容')
|
||||
->rules([
|
||||
'required',
|
||||
], [
|
||||
'required' => '文章内容不能为空',
|
||||
])
|
||||
->required();
|
||||
|
||||
$this->attachments($form);
|
||||
|
||||
$form->switch('status', '状态')
|
||||
->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
98
modules/Cms/Http/Controllers/Admin/CategoryController.php
Normal file
98
modules/Cms/Http/Controllers/Admin/CategoryController.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Closure;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Layout\Column;
|
||||
use Encore\Admin\Layout\Row;
|
||||
use Encore\Admin\Tree;
|
||||
use Encore\Admin\Widgets\Box;
|
||||
use Encore\Admin\Widgets\Form as WidgetsForm;
|
||||
use Modules\Cms\Models\Category;
|
||||
|
||||
class CategoryController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads;
|
||||
|
||||
protected $title = '分类管理';
|
||||
|
||||
public function grid(): Closure
|
||||
{
|
||||
return function (Row $row) {
|
||||
$row->column(6, $this->treeView());
|
||||
|
||||
$row->column(6, function (Column $column) {
|
||||
$form = new WidgetsForm();
|
||||
$this->formData($form, true);
|
||||
$form->action(route('admin.cms.categories.store'));
|
||||
$column->append((new Box('新增分类', $form))->style('success'));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
protected function treeView(): Tree
|
||||
{
|
||||
return Category::tree(function (Tree $tree) {
|
||||
$tree->disableCreate();
|
||||
$tree->branch(function ($branch) {
|
||||
if ($branch['status'] == 1) {
|
||||
$payload = "<i class='fa fa-eye text-primary'></i> ";
|
||||
} else {
|
||||
$payload = "<i class='fa fa-eye text-gray'></i> ";
|
||||
}
|
||||
|
||||
$payload .= " [ID:{$branch['id']}] - ";
|
||||
$payload .= " <strong>{$branch['title']}</strong> ";
|
||||
|
||||
return $payload;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected function form(): Form
|
||||
{
|
||||
$form = new Form(new Category);
|
||||
|
||||
$this->formData($form);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
private function formData($form, $hideContent = false)
|
||||
{
|
||||
$form->select('parent_id', '上级分类')
|
||||
->options(Category::selectOptions(function ($model) {
|
||||
return $model->where('status', 1);
|
||||
}, '一级分类'))
|
||||
->required();
|
||||
$form->text('title', '分类名称')
|
||||
->rules('required');
|
||||
$form->text('slug', '英文别名')
|
||||
->rules([
|
||||
'nullable',
|
||||
'alpha_dash',
|
||||
], [
|
||||
'alpha_dash' => '别名中包含非法字符',
|
||||
])
|
||||
->help('字母、数字、下划线组成,用来展示简短的URL');
|
||||
$form->textarea('description', '分类简介')
|
||||
->rules('nullable');
|
||||
|
||||
$this->cover($form);
|
||||
|
||||
$this->pictures($form);
|
||||
|
||||
$form->number('order', '排序')->default(0);
|
||||
|
||||
if (!$hideContent) {
|
||||
$form->ueditor('content', '分类内容');
|
||||
}
|
||||
|
||||
$form->switch('status', '状态')->default(1);
|
||||
}
|
||||
|
||||
}
|
||||
124
modules/Cms/Http/Controllers/Admin/PageController.php
Normal file
124
modules/Cms/Http/Controllers/Admin/PageController.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Cms\Models\Page;
|
||||
use Modules\Cms\Models\Tag;
|
||||
|
||||
class PageController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads;
|
||||
|
||||
protected $title = '单页管理';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Page());
|
||||
|
||||
$grid->model()->withCount('versions');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('trashed', '回收站')->onlyTrashed();
|
||||
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('title', '页面标题');
|
||||
$filter->like('tags.name', '标签');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->like('slug', 'SLUG');
|
||||
});
|
||||
$filter->column(1 / 3, function (Grid\Filter $filter) {
|
||||
$filter->equal('status', '状态')->select(Page::getStatusMap());
|
||||
});
|
||||
});
|
||||
|
||||
$grid->column('id', '#ID#');
|
||||
$grid->column('title', '页面标题');
|
||||
$grid->column('tags')->pluck('name')->label('warning');
|
||||
$grid->column('slug', '英文别名');
|
||||
$grid->column('status', '状态')->bool();
|
||||
$grid->column('clicks', '浏览量');
|
||||
$grid->column('versions_count', '历史版本')->link(function () {
|
||||
return route('admin.cms.versions', [
|
||||
'model' => get_class($this),
|
||||
'key' => $this->id,
|
||||
]);
|
||||
}, '_self');
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 内容表单
|
||||
* @Date : 2021/3/15 5:21 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Encore\Admin\Form
|
||||
*/
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Page());
|
||||
|
||||
$form->text('title', '页面标题')
|
||||
->rules([
|
||||
'required',
|
||||
'max:255',
|
||||
], [
|
||||
'max' => '标题最大长度不能超过 :max 个字符',
|
||||
])
|
||||
->required();
|
||||
$form->text('sub_title', '副标题')
|
||||
->rules([
|
||||
'nullable',
|
||||
'max:255',
|
||||
], [
|
||||
'max' => '标题最大长度不能超过 :max 个字符',
|
||||
]);
|
||||
$form->text('slug', '英文别名')
|
||||
->rules([
|
||||
'nullable',
|
||||
'alpha_dash',
|
||||
], [
|
||||
'alpha_dash' => '别名中包含非法字符',
|
||||
])
|
||||
->help('字母、数字、下划线组成,用来展示简短的URL');
|
||||
|
||||
$form->multipleSelect('tags', '页面标签')
|
||||
->options(function () {
|
||||
return Tag::pluck('name', 'id');
|
||||
});
|
||||
|
||||
$this->cover($form);
|
||||
|
||||
$this->pictures($form);
|
||||
|
||||
$form->textarea('description', '页面简介')
|
||||
->rules([
|
||||
'nullable',
|
||||
'max:255',
|
||||
], [
|
||||
'max' => '标题最大长度不能超过 :max 个字符',
|
||||
]);
|
||||
|
||||
$form->ueditor('content', '页面内容')
|
||||
->rules([
|
||||
'required',
|
||||
], [
|
||||
'required' => '页面内容不能为空',
|
||||
])
|
||||
->required();
|
||||
|
||||
$this->attachments($form);
|
||||
|
||||
$form->switch('status', '状态')
|
||||
->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
49
modules/Cms/Http/Controllers/Admin/StorageController.php
Normal file
49
modules/Cms/Http/Controllers/Admin/StorageController.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Admin;
|
||||
|
||||
use App\Admin\Traits\WithUploads;
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Cms\Models\Storage;
|
||||
|
||||
class StorageController extends AdminController
|
||||
{
|
||||
|
||||
use WithUploads;
|
||||
|
||||
protected $title = '素材管理';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Storage());
|
||||
|
||||
$grid->column('id', '#ID#');
|
||||
$grid->column('name', '素材标题');
|
||||
$grid->column('地址')->display(function () {
|
||||
return $this->cover_text;
|
||||
});
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Storage());
|
||||
|
||||
$form->text('name', '素材标题')
|
||||
->rules([
|
||||
'required',
|
||||
'max:255',
|
||||
], [
|
||||
'max' => '标题最大长度不能超过 :max 个字符',
|
||||
])
|
||||
->required();
|
||||
$this->cover($form);
|
||||
$form->url('url', '素材地址');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
48
modules/Cms/Http/Controllers/Admin/TagController.php
Normal file
48
modules/Cms/Http/Controllers/Admin/TagController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Cms\Models\Tag;
|
||||
|
||||
class TagController extends AdminController
|
||||
{
|
||||
|
||||
protected $title = '标签管理';
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Tag());
|
||||
|
||||
$grid->model()
|
||||
->withCount(['articles', 'pages'])
|
||||
->orderByDesc('id');
|
||||
|
||||
$grid->filter(function (Grid\Filter $filter) {
|
||||
$filter->scope('trashed', '回收站')->onlyTrashed();
|
||||
|
||||
$filter->column(1 / 2, function (Grid\Filter $filter) {
|
||||
$filter->like('name', '标签名称');
|
||||
});
|
||||
});
|
||||
|
||||
$grid->column('name', '标签名称');
|
||||
$grid->column('articles_count');
|
||||
$grid->column('pages_count');
|
||||
$grid->column('created_at', '创建时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Tag());
|
||||
|
||||
$form->text('name', '标签名称');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
68
modules/Cms/Http/Controllers/Admin/VersionController.php
Normal file
68
modules/Cms/Http/Controllers/Admin/VersionController.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Admin;
|
||||
|
||||
use Encore\Admin\Auth\Database\Administrator;
|
||||
use Encore\Admin\Grid;
|
||||
use Encore\Admin\Layout\Content;
|
||||
use Encore\Admin\Widgets\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Overtrue\LaravelVersionable\Version;
|
||||
|
||||
class VersionController extends Controller
|
||||
{
|
||||
|
||||
public function index(Content $content, $model, $key): Content
|
||||
{
|
||||
return $content
|
||||
->header($model . ' => ' . $key)
|
||||
->description('数据操作日志')
|
||||
->body($this->grid($model, $key));
|
||||
}
|
||||
|
||||
public function grid($model, $key): Grid
|
||||
{
|
||||
$grid = new Grid(new Version());
|
||||
|
||||
$grid->disableCreateButton();
|
||||
$grid->disableActions();
|
||||
$grid->disableTools();
|
||||
|
||||
$grid->model()->whereHasMorph(
|
||||
'versionable',
|
||||
$model,
|
||||
function (Builder $query) use ($key) {
|
||||
$query->where('id', $key);
|
||||
}
|
||||
)->orderByDesc('id');
|
||||
|
||||
$grid->column('操作用户')->display(function () {
|
||||
if ($this->user_id < config('mall.administrator_max_id')) {
|
||||
config(['versionable.user_model' => Administrator::class]);
|
||||
|
||||
return '[Admin] ' . ($this->user->name ?? '--SYSTEM--');
|
||||
} else {
|
||||
return '[USER] ' . ($this->user->username ?? '--USER--');
|
||||
}
|
||||
});
|
||||
$grid->column('versionable_type', '数据变动')->expand(function () {
|
||||
$data = [];
|
||||
foreach ($this->contents as $key => $item) {
|
||||
$data[] = [
|
||||
$key,
|
||||
is_array($item) ? json_encode($item, JSON_UNESCAPED_UNICODE) : $item,
|
||||
];
|
||||
}
|
||||
|
||||
return new Table(['字段名称', '变更值'], $data);
|
||||
});
|
||||
|
||||
$grid->column('操作时间')->display(function () {
|
||||
return $this->created_at->toDateTimeString();
|
||||
});
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
}
|
||||
113
modules/Cms/Http/Controllers/Api/ArticleController.php
Normal file
113
modules/Cms/Http/Controllers/Api/ArticleController.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Api;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Jason\Api\Api;
|
||||
use Modules\Cms\Http\Resources\ArticleCollection;
|
||||
use Modules\Cms\Http\Resources\ArticleResource;
|
||||
use Modules\Cms\Models\Article;
|
||||
|
||||
class ArticleController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 文章列表
|
||||
*
|
||||
* @Date : 2021/4/16 10:45 上午
|
||||
* @Author : < Jason.C >
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$categoryId = $request->category_id;
|
||||
$title = $request->title;
|
||||
$subTitle = $request->sub_title;
|
||||
$slug = $request->slug;
|
||||
$tagId = $request->tag_id;
|
||||
|
||||
$result = Article::query()
|
||||
->when($title, function ($query) use ($title) {
|
||||
$query->where('title', 'like', "%{$title}%");
|
||||
})
|
||||
->when($subTitle, function ($query) use ($subTitle) {
|
||||
$query->where('sub_title', 'like', "%{$subTitle}%");
|
||||
})
|
||||
->when($slug, function ($query) use ($slug) {
|
||||
$query->where('slug', 'like', "%{$slug}%");
|
||||
})
|
||||
->when($categoryId, function ($query) use ($categoryId) {
|
||||
$query->whereHas('categories', function ($cate) use ($categoryId) {
|
||||
$cate->where('category_id', $categoryId);
|
||||
});
|
||||
})
|
||||
->when($tagId, function ($query) use ($tagId) {
|
||||
$query->whereHas('tags', function ($tag) use ($tagId) {
|
||||
$tag->where('tag_id', $tagId);
|
||||
});
|
||||
})
|
||||
->where('status', 1)
|
||||
->with(['categories', 'tags'])
|
||||
->paginate(10);
|
||||
|
||||
return $this->success(new ArticleCollection($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 文章详情
|
||||
*
|
||||
* @Date : 2021/4/16 10:45 上午
|
||||
* @Author : < Jason.C >
|
||||
* @param Article $article
|
||||
* @return mixed
|
||||
*/
|
||||
public function show(Article $article)
|
||||
{
|
||||
$article->read(Api::userId());
|
||||
|
||||
return $this->success(new ArticleResource($article));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 收藏/取消收藏
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/10/11 9:59
|
||||
*/
|
||||
public function favorite(Article $article): JsonResponse
|
||||
{
|
||||
$user = Api::user();
|
||||
|
||||
$user->toggleFavorite($article);
|
||||
|
||||
return $this->success([
|
||||
'count' => $article->favorites()->count(),
|
||||
'favorite' => $user->hasFavorited($article),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 点赞/取消点赞
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/10/11 10:18
|
||||
* @param Article $article
|
||||
* @return JsonResponse
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function subscribe(Article $article): JsonResponse
|
||||
{
|
||||
$user = Api::user();
|
||||
|
||||
$user->toggleSubscribe($article);
|
||||
|
||||
return $this->success([
|
||||
'count' => $article->subscribers()->count(),
|
||||
'subscribed' => $user->hasSubscribed($article),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
50
modules/Cms/Http/Controllers/Api/CategoryController.php
Normal file
50
modules/Cms/Http/Controllers/Api/CategoryController.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Api;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Cms\Http\Resources\CategoryCollection;
|
||||
use Modules\Cms\Http\Resources\CategoryResource;
|
||||
use Modules\Cms\Models\Category;
|
||||
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 分类首页
|
||||
* @Date : 2021/4/19 9:29 上午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$parentId = $request->get('parent_id', 0);
|
||||
|
||||
if (!is_integer($parentId)) {
|
||||
return $this->failed('The param must be integer');
|
||||
}
|
||||
|
||||
$result = Category::where('parent_id', $parentId)
|
||||
->where('status', 1)
|
||||
->orderBy('order', 'asc')
|
||||
->get();
|
||||
|
||||
return $this->success(new CategoryCollection($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 分类的详情
|
||||
* @Date : 2021/4/19 9:29 上午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Modules\Cms\Models\Category $category
|
||||
* @return mixed
|
||||
*/
|
||||
public function show(Category $category)
|
||||
{
|
||||
|
||||
return $this->success(new CategoryResource($category));
|
||||
}
|
||||
|
||||
}
|
||||
90
modules/Cms/Http/Controllers/Api/PageController.php
Normal file
90
modules/Cms/Http/Controllers/Api/PageController.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Api;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Cms\Http\Resources\PageCollection;
|
||||
use Modules\Cms\Http\Resources\PageResource;
|
||||
use Modules\Cms\Models\Page;
|
||||
|
||||
class PageController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 单页列表
|
||||
*
|
||||
* @Date : 2021/4/16 10:45 上午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$title = $request->title;
|
||||
$subTitle = $request->sub_title;
|
||||
$slug = $request->slug;
|
||||
$tagId = $request->tag_id;
|
||||
|
||||
$result = Page::when($title, function ($query) use ($title) {
|
||||
$query->where('title', 'like', "%{$title}%");
|
||||
})->when($subTitle, function ($query) use ($subTitle) {
|
||||
$query->where('sub_title', 'like', "%{$subTitle}%");
|
||||
})->when($slug, function ($query) use ($slug) {
|
||||
$query->where('slug', 'like', "%{$slug}%");
|
||||
})->when($tagId, function ($query) use ($tagId) {
|
||||
$query->whereHas('tags', function ($tag) use ($tagId) {
|
||||
$tag->where('tag_id', $tagId);
|
||||
});
|
||||
})->where('status', 1)->with(['tags'])->paginate();
|
||||
|
||||
$result = new PageCollection($result);
|
||||
|
||||
return $this->success($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 单页详情
|
||||
*
|
||||
* @Date : 2021/4/16 11:25 上午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Modules\Cms\Models\Page $page
|
||||
* @return mixed
|
||||
*/
|
||||
public function show(Page $page)
|
||||
{
|
||||
$page->incrementClicks();
|
||||
|
||||
return $this->success(new PageResource($page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 隐私条款
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/8/29 11:59
|
||||
*/
|
||||
public function secret()
|
||||
{
|
||||
$info = Page::where('slug', 'secret')->first();
|
||||
$info->incrementClicks();
|
||||
|
||||
return $this->success(new PageResource($info));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 服务协议
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/8/29 12:00
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function protocol()
|
||||
{
|
||||
$info = Page::where('slug', 'protocol')->first();
|
||||
$info->incrementClicks();
|
||||
|
||||
return $this->success(new PageResource($info));
|
||||
}
|
||||
|
||||
}
|
||||
37
modules/Cms/Http/Controllers/Api/TagController.php
Normal file
37
modules/Cms/Http/Controllers/Api/TagController.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Controllers\Api;
|
||||
|
||||
use App\Api\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Cms\Http\Resources\TagCollection;
|
||||
use Modules\Cms\Http\Resources\TagResource;
|
||||
use Modules\Cms\Models\Tag;
|
||||
|
||||
class TagController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 标签列表
|
||||
* @Date : 2021/4/25 1:31 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$name = $request->name;
|
||||
|
||||
$tags = Tag::when($name, function ($query) use ($name) {
|
||||
$query->where('name', 'like', "%{$name}%");
|
||||
})->orderByDesc('id')->paginate();
|
||||
|
||||
return $this->success(new TagCollection($tags));
|
||||
}
|
||||
|
||||
public function show(Tag $tag)
|
||||
{
|
||||
return $this->success(new TagResource($tag));
|
||||
}
|
||||
|
||||
}
|
||||
29
modules/Cms/Http/Resources/ArticleBaseResource.php
Normal file
29
modules/Cms/Http/Resources/ArticleBaseResource.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class ArticleBaseResource extends JsonResource
|
||||
{
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'article_id' => $this->id,
|
||||
'title' => $this->title,
|
||||
// 'sub_title' => $this->sub_title,
|
||||
'description' => $this->description,
|
||||
// 'slug' => $this->slug,
|
||||
'categories' => CategoryBaseResource::collection($this->categories),
|
||||
'tags' => TagResource::collection($this->tags),
|
||||
'cover' => $this->cover_url,
|
||||
'pictures' => $this->pictures_url,
|
||||
'clicks' => $this->clicks,
|
||||
'favorites' => $this->favorites()->count(),
|
||||
'subscribes' => $this->subscribers()->count(),
|
||||
'created_at' => (string) $this->created_at,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
31
modules/Cms/Http/Resources/ArticleCollection.php
Normal file
31
modules/Cms/Http/Resources/ArticleCollection.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class ArticleCollection extends ResourceCollection
|
||||
{
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection->map(function ($article) {
|
||||
return new ArticleBaseResource($article);
|
||||
}),
|
||||
'page' => $this->page(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function page(): array
|
||||
{
|
||||
return [
|
||||
'current' => $this->currentPage(),
|
||||
'total_page' => $this->lastPage(),
|
||||
'per_page' => $this->perPage(),
|
||||
'has_more' => $this->hasMorePages(),
|
||||
'total' => $this->total(),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
36
modules/Cms/Http/Resources/ArticleResource.php
Normal file
36
modules/Cms/Http/Resources/ArticleResource.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Jason\Api\Api;
|
||||
|
||||
class ArticleResource extends JsonResource
|
||||
{
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
$user = Api::user();
|
||||
|
||||
return [
|
||||
'article_id' => $this->id,
|
||||
'title' => $this->title,
|
||||
// 'sub_title' => $this->sub_title,
|
||||
'description' => $this->description,
|
||||
// 'slug' => $this->slug,
|
||||
'categories' => CategoryBaseResource::collection($this->categories),
|
||||
'tags' => TagResource::collection($this->tags),
|
||||
'cover' => $this->cover_url,
|
||||
'pictures' => $this->pictures_url,
|
||||
'clicks' => $this->clicks,
|
||||
'favorites' => $this->favorites()->count(),
|
||||
'subscribes' => $this->subscribers()->count(),
|
||||
'isFavorite' => $user && $this->isFavoritedBy($user),
|
||||
'isSubscribed' => $user && $this->isSubscribedBy($user),
|
||||
'content' => $this->content,
|
||||
'attachments' => $this->attachments,
|
||||
'created_at' => (string) $this->created_at,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
19
modules/Cms/Http/Resources/CategoryBaseResource.php
Normal file
19
modules/Cms/Http/Resources/CategoryBaseResource.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class CategoryBaseResource extends JsonResource
|
||||
{
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'category_id' => $this->id,
|
||||
'title' => $this->title,
|
||||
'slug' => $this->slug,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
33
modules/Cms/Http/Resources/CategoryCollection.php
Normal file
33
modules/Cms/Http/Resources/CategoryCollection.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class CategoryCollection extends ResourceCollection
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes :
|
||||
* @Date : 2021/4/25 1:32 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return $this->collection->map(function ($category) {
|
||||
return [
|
||||
'category_id' => $category->id,
|
||||
'title' => $category->title,
|
||||
'slug' => $category->slug,
|
||||
'description' => $category->description,
|
||||
'cover' => $category->cover_url,
|
||||
'pictures' => $category->pictures_url,
|
||||
'created_at' => (string) $category->created_at,
|
||||
'children' => new self($category->children),
|
||||
];
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
}
|
||||
25
modules/Cms/Http/Resources/CategoryResource.php
Normal file
25
modules/Cms/Http/Resources/CategoryResource.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class CategoryResource extends JsonResource
|
||||
{
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'category_id' => $this->id,
|
||||
'parent' => new self($this->parent),
|
||||
'title' => $this->title,
|
||||
'slug' => $this->slug,
|
||||
'description' => $this->description,
|
||||
'cover' => $this->cover_url,
|
||||
'pictures' => $this->pictures_url,
|
||||
'content' => $this->content,
|
||||
'created_at' => (string) $this->created_at,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
42
modules/Cms/Http/Resources/PageCollection.php
Normal file
42
modules/Cms/Http/Resources/PageCollection.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class PageCollection extends ResourceCollection
|
||||
{
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection->map(function ($page) {
|
||||
return [
|
||||
'page_id' => $page->id,
|
||||
'title' => $page->title,
|
||||
'sub_title' => $page->sub_title,
|
||||
'tags' => TagResource::collection($page->tags),
|
||||
'description' => $page->description,
|
||||
'slug' => $page->slug,
|
||||
'cover' => $page->cover_url,
|
||||
'pictures' => $page->pictures_url,
|
||||
'clicks' => $page->clicks,
|
||||
'created_at' => (string) $page->created_at,
|
||||
];
|
||||
}),
|
||||
'page' => $this->page(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function page(): array
|
||||
{
|
||||
return [
|
||||
'current' => $this->currentPage(),
|
||||
'total_page' => $this->lastPage(),
|
||||
'per_page' => $this->perPage(),
|
||||
'has_more' => $this->hasMorePages(),
|
||||
'total' => $this->total(),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
28
modules/Cms/Http/Resources/PageResource.php
Normal file
28
modules/Cms/Http/Resources/PageResource.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PageResource extends JsonResource
|
||||
{
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'page_id' => $this->id,
|
||||
'title' => $this->title,
|
||||
'sub_title' => $this->sub_title,
|
||||
'tags' => TagResource::collection($this->tags),
|
||||
'description' => $this->description,
|
||||
'slug' => $this->slug,
|
||||
'cover' => $this->cover_url,
|
||||
'pictures' => $this->pictures_url,
|
||||
'clicks' => $this->clicks,
|
||||
'content' => $this->content,
|
||||
'attachments' => $this->attachments_url,
|
||||
'created_at' => (string) $this->created_at,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
31
modules/Cms/Http/Resources/TagCollection.php
Normal file
31
modules/Cms/Http/Resources/TagCollection.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class TagCollection extends ResourceCollection
|
||||
{
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection->map(function ($tag) {
|
||||
return new TagResource($tag);
|
||||
}),
|
||||
'page' => $this->page(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function page(): array
|
||||
{
|
||||
return [
|
||||
'current' => $this->currentPage(),
|
||||
'total_page' => $this->lastPage(),
|
||||
'per_page' => $this->perPage(),
|
||||
'has_more' => $this->hasMorePages(),
|
||||
'total' => $this->total(),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
18
modules/Cms/Http/Resources/TagResource.php
Normal file
18
modules/Cms/Http/Resources/TagResource.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TagResource extends JsonResource
|
||||
{
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'tag_id' => $this->id,
|
||||
'name' => $this->name,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
123
modules/Cms/Models/Article.php
Normal file
123
modules/Cms/Models/Article.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use App\Traits\HasClicks;
|
||||
use App\Traits\HasCovers;
|
||||
use App\Traits\HasStatus;
|
||||
use App\Traits\OrderByIdDesc;
|
||||
use Encore\Admin\Traits\Resizable;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Modules\Cms\Traits\HasTags;
|
||||
use Modules\Task\Facades\TaskFacade;
|
||||
use Modules\Task\Models\Task;
|
||||
use Overtrue\LaravelFavorite\Traits\Favoriteable;
|
||||
use Overtrue\LaravelSubscribe\Traits\Subscribable;
|
||||
use Overtrue\LaravelVersionable\Versionable;
|
||||
|
||||
class Article extends Model
|
||||
{
|
||||
|
||||
use Cachable,
|
||||
HasClicks,
|
||||
HasCovers,
|
||||
HasTags,
|
||||
Subscribable,
|
||||
Favoriteable,
|
||||
HasStatus,
|
||||
OrderByIdDesc,
|
||||
Resizable,
|
||||
Versionable,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'cms_articles';
|
||||
|
||||
protected $casts = [
|
||||
'pictures' => 'json',
|
||||
'attachments' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* 不参与版本记录的字段
|
||||
*
|
||||
* @var array|string[]
|
||||
*/
|
||||
protected array $dontVersionable = ['clicks', 'updated_at'];
|
||||
|
||||
/**
|
||||
* Notes: 阅读记录
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/10/20 9:57
|
||||
* @return HasMany
|
||||
*/
|
||||
public function logs(): HasMany
|
||||
{
|
||||
return $this->hasMany(Log::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 阅读
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/10/20 9:57
|
||||
* @param int $user_id
|
||||
*/
|
||||
public function read($user_id = '')
|
||||
{
|
||||
$this->incrementClicks();
|
||||
if ($user_id) {
|
||||
$this->logs()->create([
|
||||
'user_id' => $user_id
|
||||
]);
|
||||
|
||||
if (Task::query()->shown()->where('key', 'tour_article')->first()) {
|
||||
# todo 阅读得水滴
|
||||
TaskFacade::do('tour_article', $user_id);
|
||||
}
|
||||
|
||||
if (Task::query()->shown()->where('key',
|
||||
'read_article')->first() && $this->categories()->Health()->first()) {
|
||||
# todo 阅读100次得水滴
|
||||
TaskFacade::do('read_article', $user_id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 文章所属分类
|
||||
*
|
||||
* @Date : 2021/4/15 12:44 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function categories(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Category::class, 'cms_article_category')
|
||||
->using(ArticleCategory::class)
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 获取附件的下载地址
|
||||
*
|
||||
* @Date : 2021/4/16 12:01 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAttachmentsUrlAttribute(): Collection
|
||||
{
|
||||
return collect($this->attachments)->map(function ($item) {
|
||||
return Storage::url($item);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
14
modules/Cms/Models/ArticleCategory.php
Normal file
14
modules/Cms/Models/ArticleCategory.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
|
||||
class ArticleCategory extends Pivot
|
||||
{
|
||||
|
||||
public $incrementing = true;
|
||||
|
||||
public $table = 'cms_article_category';
|
||||
|
||||
}
|
||||
69
modules/Cms/Models/Category.php
Normal file
69
modules/Cms/Models/Category.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use App\Traits\HasCovers;
|
||||
use Encore\Admin\Traits\AdminBuilder;
|
||||
use Encore\Admin\Traits\ModelTree;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Overtrue\LaravelVersionable\Versionable;
|
||||
|
||||
class Category extends Model
|
||||
{
|
||||
|
||||
use AdminBuilder,
|
||||
Cachable,
|
||||
HasCovers,
|
||||
ModelTree,
|
||||
Versionable,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'cms_categories';
|
||||
|
||||
protected $casts = [
|
||||
'pictures' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* 不参与版本记录的字段
|
||||
*
|
||||
* @var array|string[]
|
||||
*/
|
||||
protected array $dontVersionable = ['updated_at'];
|
||||
|
||||
public function children(): HasMany
|
||||
{
|
||||
return $this->hasMany(self::class, 'parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 分类下的文章
|
||||
*
|
||||
* @Date : 2021/4/15 12:47 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function articles(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Article::class, (new ArticleCategory())->getTable())
|
||||
->using(ArticleCategory::class)
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: 健康文章
|
||||
*
|
||||
* @Author: 玄尘
|
||||
* @Date: 2022/10/31 10:05
|
||||
*/
|
||||
public function scopeHealth(Builder $query): Builder
|
||||
{
|
||||
return $query->where('slug', 'HEALTH');
|
||||
}
|
||||
|
||||
}
|
||||
15
modules/Cms/Models/Log.php
Normal file
15
modules/Cms/Models/Log.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Models;
|
||||
|
||||
|
||||
use App\Models\Model;
|
||||
use Modules\User\Traits\BelongsToUser;
|
||||
|
||||
class Log extends Model
|
||||
{
|
||||
use BelongsToUser;
|
||||
|
||||
protected $table = 'cms_logs';
|
||||
|
||||
}
|
||||
55
modules/Cms/Models/Page.php
Normal file
55
modules/Cms/Models/Page.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use App\Traits\HasClicks;
|
||||
use App\Traits\HasCovers;
|
||||
use App\Traits\HasStatus;
|
||||
use App\Traits\OrderByIdDesc;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Modules\Cms\Traits\HasTags;
|
||||
use Overtrue\LaravelVersionable\Versionable;
|
||||
|
||||
class Page extends Model
|
||||
{
|
||||
|
||||
use Cachable,
|
||||
HasClicks,
|
||||
HasCovers,
|
||||
HasTags,
|
||||
HasStatus,
|
||||
OrderByIdDesc,
|
||||
Versionable,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'cms_pages';
|
||||
|
||||
protected $casts = [
|
||||
'pictures' => 'json',
|
||||
'attachments' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* 不参与版本记录的字段
|
||||
* @var array|string[]
|
||||
*/
|
||||
protected array $dontVersionable = ['updated_at'];
|
||||
|
||||
/**
|
||||
* Notes : 获取附件的下载地址
|
||||
* @Date : 2021/4/16 12:01 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getAttachmentsUrlAttribute(): Collection
|
||||
{
|
||||
return collect($this->attachments)->map(function ($item) {
|
||||
return Storage::url($item);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
24
modules/Cms/Models/Storage.php
Normal file
24
modules/Cms/Models/Storage.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use App\Traits\HasCovers;
|
||||
|
||||
class Storage extends Model
|
||||
{
|
||||
|
||||
use HasCovers;
|
||||
|
||||
protected $table = 'cms_storages';
|
||||
|
||||
public function getCoverTextAttribute()
|
||||
{
|
||||
if ($this->url) {
|
||||
return $this->url . '/' . $this->cover;
|
||||
} else {
|
||||
return $this->cover_url;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
34
modules/Cms/Models/Tag.php
Normal file
34
modules/Cms/Models/Tag.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Tag extends Model
|
||||
{
|
||||
|
||||
use Cachable,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'cms_tags';
|
||||
|
||||
/**
|
||||
* 不参与版本记录的字段
|
||||
* @var array|string[]
|
||||
*/
|
||||
protected array $dontVersionable = ['updated_at'];
|
||||
|
||||
public function articles(): MorphToMany
|
||||
{
|
||||
return $this->morphedByMany(Article::class, 'taggable', 'cms_taggable');
|
||||
}
|
||||
|
||||
public function pages(): MorphToMany
|
||||
{
|
||||
return $this->morphedByMany(Page::class, 'taggable', 'cms_taggable');
|
||||
}
|
||||
|
||||
}
|
||||
14
modules/Cms/Models/Taggable.php
Normal file
14
modules/Cms/Models/Taggable.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\MorphPivot;
|
||||
|
||||
class Taggable extends MorphPivot
|
||||
{
|
||||
|
||||
public $incrementing = true;
|
||||
|
||||
protected $table = 'cms_taggable';
|
||||
|
||||
}
|
||||
63
modules/Cms/Providers/CmsServiceProvider.php
Normal file
63
modules/Cms/Providers/CmsServiceProvider.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class CmsServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string $moduleName
|
||||
*/
|
||||
protected string $moduleName = 'Cms';
|
||||
|
||||
/**
|
||||
* @var string $moduleNameLower
|
||||
*/
|
||||
protected string $moduleNameLower = 'cms';
|
||||
|
||||
/**
|
||||
* Boot the application events.
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->loadMigrationsFrom(module_path($this->moduleName, 'Database/Migrations'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->registerConfig();
|
||||
|
||||
$this->app->register(RouteServiceProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register config.
|
||||
* @return void
|
||||
*/
|
||||
protected function registerConfig()
|
||||
{
|
||||
$this->publishes([
|
||||
module_path($this->moduleName, 'Config/config.php') => config_path($this->moduleNameLower . '.php'),
|
||||
], 'config');
|
||||
$this->mergeConfigFrom(
|
||||
module_path($this->moduleName, 'Config/config.php'), $this->moduleNameLower
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
* @return array
|
||||
*/
|
||||
public function provides(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
62
modules/Cms/Providers/RouteServiceProvider.php
Normal file
62
modules/Cms/Providers/RouteServiceProvider.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string $moduleName
|
||||
*/
|
||||
protected string $moduleName = 'Cms';
|
||||
|
||||
/**
|
||||
* The module namespace to assume when generating URLs to actions.
|
||||
* @var string
|
||||
*/
|
||||
protected string $moduleNamespace = 'Modules\Cms\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Called before routes are registered.
|
||||
* Register any model bindings or pattern based filters.
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
* @return void
|
||||
*/
|
||||
public function map()
|
||||
{
|
||||
$this->mapAdminRoutes();
|
||||
$this->mapApiRoutes();
|
||||
}
|
||||
|
||||
protected function mapApiRoutes()
|
||||
{
|
||||
Route::as(config('api.route.as'))
|
||||
->domain(config('api.route.domain'))
|
||||
->middleware(config('api.route.middleware'))
|
||||
->namespace($this->moduleNamespace)
|
||||
->prefix(config('api.route.prefix'))
|
||||
->group(module_path($this->moduleName, 'Routes/api.php'));
|
||||
}
|
||||
|
||||
protected function mapAdminRoutes()
|
||||
{
|
||||
Route::as(config('admin.route.as'))
|
||||
->domain(config('admin.route.domain'))
|
||||
->middleware(config('admin.route.middleware'))
|
||||
->namespace($this->moduleNamespace)
|
||||
->prefix(config('admin.route.prefix'))
|
||||
->group(module_path($this->moduleName, 'Routes/admin.php'));
|
||||
}
|
||||
|
||||
}
|
||||
49
modules/Cms/README.md
Normal file
49
modules/Cms/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# CMS
|
||||
|
||||
## 安装
|
||||
|
||||
```shell
|
||||
composer require overtrue/laravel-versionable
|
||||
```
|
||||
|
||||
## 接口文档
|
||||
|
||||
### 1. 文章
|
||||
|
||||
#### 1. 文章列表
|
||||
|
||||
> GET: /api/cms/articles
|
||||
|
||||
#### 2. 文章详情
|
||||
|
||||
> GET: /api/cms/articles/{article_id}
|
||||
|
||||
### 2. 单页
|
||||
|
||||
#### 1. 单页列表
|
||||
|
||||
> GET: /api/cms/pages
|
||||
|
||||
#### 2. 单页详情
|
||||
|
||||
> GET: /api/cms/pages/{page_id}
|
||||
|
||||
### 3. 分类
|
||||
|
||||
#### 1. 分类列表
|
||||
|
||||
> GET: /api/cms/categories
|
||||
|
||||
#### 2. 分类详情
|
||||
|
||||
> GET: /api/cms/categories/{category_id}
|
||||
|
||||
### 4. 标签
|
||||
|
||||
#### 1. 标签列表
|
||||
|
||||
> GET: /api/cms/tags
|
||||
|
||||
#### 2. 标签详情
|
||||
|
||||
> GET: /api/cms/tags/{tag_id}
|
||||
17
modules/Cms/Routes/admin.php
Normal file
17
modules/Cms/Routes/admin.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::group([
|
||||
'prefix' => 'cms',
|
||||
'namespace' => 'Admin',
|
||||
'as' => 'cms.',
|
||||
], function (Router $router) {
|
||||
$router->resource('articles', 'ArticleController');
|
||||
$router->resource('pages', 'PageController');
|
||||
$router->resource('categories', 'CategoryController');
|
||||
$router->resource('tags', 'TagController');
|
||||
$router->resource('storages', 'StorageController');
|
||||
$router->get('versions/{model}/{key}', 'VersionController@index')->name('versions');
|
||||
});
|
||||
34
modules/Cms/Routes/api.php
Normal file
34
modules/Cms/Routes/api.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::group([
|
||||
'prefix' => 'cms',
|
||||
'namespace' => 'Api',
|
||||
'middleware' => config('api.route.middleware_guess'),
|
||||
], function (Router $router) {
|
||||
$router->get('articles', 'ArticleController@index');
|
||||
$router->get('articles/{article}', 'ArticleController@show');
|
||||
|
||||
$router->get('pages', 'PageController@index');
|
||||
$router->get('pages/secret', 'PageController@secret');
|
||||
$router->get('pages/protocol', 'PageController@protocol');
|
||||
$router->get('pages/{page}', 'PageController@show');
|
||||
|
||||
$router->get('categories', 'CategoryController@index');
|
||||
$router->get('categories/{category}', 'CategoryController@show');
|
||||
|
||||
$router->get('tags', 'TagController@index');
|
||||
$router->get('tags/{tag}', 'TagController@show');
|
||||
});
|
||||
|
||||
Route::group([
|
||||
'prefix' => 'cms',
|
||||
'namespace' => 'Api',
|
||||
'middleware' => config('api.route.middleware_auth'),
|
||||
], function (Router $router) {
|
||||
$router->get('articles/favorite/{article}', 'ArticleController@favorite');//收藏、取消收藏
|
||||
$router->get('articles/subscribe/{article}', 'ArticleController@subscribe');//点赞、取消点赞
|
||||
|
||||
});
|
||||
25
modules/Cms/Traits/HasTags.php
Normal file
25
modules/Cms/Traits/HasTags.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Cms\Traits;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Modules\Cms\Models\Tag;
|
||||
use Modules\Cms\Models\Taggable;
|
||||
|
||||
trait HasTags
|
||||
{
|
||||
|
||||
/**
|
||||
* Notes : 拥有内容标签
|
||||
* @Date : 2021/4/25 12:58 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
*/
|
||||
public function tags(): MorphToMany
|
||||
{
|
||||
return $this->morphToMany(Tag::class, 'taggable', 'cms_taggable')
|
||||
->using(Taggable::class)
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
}
|
||||
34
modules/Cms/composer.json
Normal file
34
modules/Cms/composer.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "uztech/cms-module",
|
||||
"description": "内容模块",
|
||||
"type": "laravel-module",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jason.Chen",
|
||||
"email": "chenjxlg@163.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"encore/laravel-admin": "^1.8",
|
||||
"genealabs/laravel-model-caching": "^0.11.3",
|
||||
"jasonc/api": "^5.0.0",
|
||||
"joshbrw/laravel-module-installer": "^2.0",
|
||||
"laravel/framework": "^8.5",
|
||||
"nwidart/laravel-modules": "^8.2",
|
||||
"overtrue/laravel-versionable": "^2.6"
|
||||
},
|
||||
"extra": {
|
||||
"module-dir": "modules",
|
||||
"laravel": {
|
||||
"providers": [],
|
||||
"aliases": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\Cms\\": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
15
modules/Cms/module.json
Normal file
15
modules/Cms/module.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Cms",
|
||||
"alias": "cms",
|
||||
"description": "内容管理模块",
|
||||
"keywords": [],
|
||||
"priority": 0,
|
||||
"providers": [
|
||||
"Modules\\Cms\\Providers\\CmsServiceProvider"
|
||||
],
|
||||
"aliases": {},
|
||||
"files": [],
|
||||
"requires": [],
|
||||
"version": "1.0.0",
|
||||
"author": "Jason.Chen"
|
||||
}
|
||||
4
modules/Configuration/.gitignore
vendored
Normal file
4
modules/Configuration/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.idea
|
||||
vendor
|
||||
.DS_Store
|
||||
composer.lock
|
||||
44
modules/Configuration/Actions/UpdateSource.php
Normal file
44
modules/Configuration/Actions/UpdateSource.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Configuration\Actions;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Configuration\Models\Configuration;
|
||||
|
||||
class UpdateSource extends RowAction
|
||||
{
|
||||
|
||||
public $name = '更改配置项';
|
||||
|
||||
public function handle(Configuration $model, Request $request): Response
|
||||
{
|
||||
try {
|
||||
$source = $request->source;
|
||||
$array = explode("\r\n", $source);
|
||||
$data = [];
|
||||
foreach ($array as $value) {
|
||||
$key = explode("|", $value)[0];
|
||||
$params = explode("|", $value)[1];
|
||||
$data[$key] = $params;
|
||||
}
|
||||
$model->source = $data;
|
||||
$model->paramsValue = '';
|
||||
$model->save();
|
||||
|
||||
return $this->response()->success('更改成功')->refresh();
|
||||
} catch (Exception $e) {
|
||||
return $this->response()->error($e->getMessage())->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public function form()
|
||||
{
|
||||
$this->textarea('source', '配置项')->required();
|
||||
$this->textarea('示例')->disable()->value("key|value\r\nkey|value\r\n非必要请不要随意更改");
|
||||
$this->confirm('确认改变当前配置项?(删除值)');
|
||||
}
|
||||
|
||||
}
|
||||
36
modules/Configuration/Actions/UpdateType.php
Normal file
36
modules/Configuration/Actions/UpdateType.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Configuration\Actions;
|
||||
|
||||
use Encore\Admin\Actions\Response;
|
||||
use Encore\Admin\Actions\RowAction;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\Configuration\Models\Configuration;
|
||||
|
||||
class UpdateType extends RowAction
|
||||
{
|
||||
|
||||
public $name = '改变类型';
|
||||
|
||||
public function handle(Configuration $model, Request $request): Response
|
||||
{
|
||||
try {
|
||||
$model->type = $request->type;
|
||||
$model->source = [];
|
||||
$model->paramsValue = '';
|
||||
$model->save();
|
||||
|
||||
return $this->response()->success('更改成功')->refresh();
|
||||
} catch (Exception $e) {
|
||||
return $this->response()->error($e->getMessage())->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public function form()
|
||||
{
|
||||
$this->select('type', '配置类型')->options(Configuration::TYPES);
|
||||
$this->confirm('确认改变当前类型?(删除配置项与值)');
|
||||
}
|
||||
|
||||
}
|
||||
73
modules/Configuration/Configuration.php
Normal file
73
modules/Configuration/Configuration.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Configuration;
|
||||
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Nwidart\Modules\Facades\Module as ModuleManager;
|
||||
|
||||
class Configuration
|
||||
{
|
||||
protected static string $mainTitle = '参数配置管理';
|
||||
|
||||
/**
|
||||
* Notes : 模块初始化要做的一些操作
|
||||
*/
|
||||
public static function install()
|
||||
{
|
||||
Artisan::call('migrate', [
|
||||
'--path' => 'modules/Configuration/Database/Migrations',
|
||||
]);
|
||||
|
||||
self::createAdminMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 卸载模块的一些操作
|
||||
*/
|
||||
public static function uninstall()
|
||||
{
|
||||
$menu = config('admin.database.menu_model');
|
||||
|
||||
$main = $menu::where('title', self::$mainTitle)->first();
|
||||
|
||||
$main->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模块配置情况创建是否需要配置菜单
|
||||
*/
|
||||
protected static function createAdminMenu()
|
||||
{
|
||||
$menu = config('admin.database.menu_model');
|
||||
|
||||
$main = $menu::create([
|
||||
'parent_id' => 0,
|
||||
'order' => 50,
|
||||
'title' => self::$mainTitle,
|
||||
'icon' => 'fa-bars',
|
||||
]);
|
||||
$modules = ModuleManager::toCollection();
|
||||
$data = [];
|
||||
$i = 1;
|
||||
foreach ($modules as $module) {
|
||||
$need = $module->get('config', false);
|
||||
if ($need) {
|
||||
$name = $module->get('configName', '');
|
||||
if (! $name) {
|
||||
$name = $module->getName();
|
||||
}
|
||||
$alias = $module->getAlias();
|
||||
$data[] = [
|
||||
'order' => $i,
|
||||
'title' => $name.'配置',
|
||||
'icon' => 'fa-bars',
|
||||
'uri' => 'configurations/'.$alias,
|
||||
];
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
if (count($data) > 0) {
|
||||
$main->children()->createMany($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateConfigurationsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('configurations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('module', 100)->comment('所属模块');
|
||||
$table->string('title', 100)->comment('配置项名称');
|
||||
$table->string('keyValue', 100)->comment('配置键值');
|
||||
$table->string('paramsValue', 100)->nullable()->comment('值');
|
||||
$table->string('type', 100)->comment('类型');
|
||||
$table->json('source')->nullable()->comment('其他数据源');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('configurations');
|
||||
}
|
||||
|
||||
}
|
||||
135
modules/Configuration/Http/Controllers/IndexController.php
Normal file
135
modules/Configuration/Http/Controllers/IndexController.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Configuration\Http\Controllers;
|
||||
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Encore\Admin\Layout\Content;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Modules\Configuration\Actions\UpdateSource;
|
||||
use Modules\Configuration\Actions\UpdateType;
|
||||
use Modules\Configuration\Models\Configuration;
|
||||
|
||||
class IndexController extends Controller
|
||||
{
|
||||
|
||||
public function index(string $module): Content
|
||||
{
|
||||
$moduleName = app('modules')->findByAlias($module);
|
||||
$content = new Content();
|
||||
return $content
|
||||
->title($moduleName->get('configName', $moduleName->getName()).'参数配置')
|
||||
->body($this->grid($module));
|
||||
}
|
||||
|
||||
public function grid(string $module): Grid
|
||||
{
|
||||
$grid = new Grid(new Configuration());
|
||||
$grid->model()->where('module', $module);
|
||||
|
||||
$grid->actions(function (Grid\Displayers\Actions $actions) {
|
||||
$actions->disableDelete();
|
||||
$actions->disableView();
|
||||
$actions->add(new UpdateType());
|
||||
if (in_array($actions->row->type, [
|
||||
Configuration::TYPE_SELECT,
|
||||
Configuration::TYPE_CHECKBOX,
|
||||
])) {
|
||||
$actions->add(new UpdateSource());
|
||||
}
|
||||
});
|
||||
$grid->column('keyValue', '关键字');
|
||||
$grid->column('title', '配置项名称');
|
||||
$grid->column('type', '类型')->using(Configuration::TYPES);
|
||||
$grid->column('值')->display(function () {
|
||||
return $this->params_text;
|
||||
});
|
||||
$grid->column('source', '参数')->display(function () {
|
||||
$str = '';
|
||||
foreach ($this->source ?? [] as $key => $value) {
|
||||
$str .= $key.' = '.$value.'<br>';
|
||||
}
|
||||
|
||||
return $str;
|
||||
});
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function create(string $module): Content
|
||||
{
|
||||
$moduleName = app('modules')->findByAlias($module);
|
||||
$content = new Content();
|
||||
return $content
|
||||
->title($moduleName->get('configName', $moduleName->getName()).'参数新增')
|
||||
->body($this->form($module));
|
||||
}
|
||||
|
||||
public function store(string $module)
|
||||
{
|
||||
return $this->form($module)->store();
|
||||
}
|
||||
|
||||
public function edit(string $module, $id): Content
|
||||
{
|
||||
$moduleName = app('modules')->findByAlias($module);
|
||||
|
||||
$content = new Content();
|
||||
return $content
|
||||
->title($moduleName->get('configName', $moduleName->getName()).'参数修改')
|
||||
->body($this->form($module, $id)->edit($id));
|
||||
}
|
||||
|
||||
public function update(string $module, $id)
|
||||
{
|
||||
return $this->form($module, $id)->update($id);
|
||||
}
|
||||
|
||||
public function form(string $module, $id = ''): Form
|
||||
{
|
||||
$form = new Form(new Configuration());
|
||||
$form->hidden('module')->default($module);
|
||||
|
||||
$form->tools(function (Form\Tools $tools) {
|
||||
$tools->disableDelete();
|
||||
$tools->disableView();
|
||||
});
|
||||
|
||||
if (! $id) {
|
||||
$form->text('keyValue', '关键字')->required();
|
||||
$form->text('title', '配置项名称')->required();
|
||||
$form->select('type', '类型')->options(Configuration::TYPES)->required();
|
||||
} else {
|
||||
$form->text('keyValue', '关键字')->disable();
|
||||
$form->text('title', '配置项名称')->disable();
|
||||
$config = Configuration::find($id);
|
||||
switch ($config->type) {
|
||||
case Configuration::TYPE_SELECT:
|
||||
$form->select('paramsValue', '值')
|
||||
->options($config->source)
|
||||
->required();
|
||||
break;
|
||||
case Configuration::TYPE_CHECKBOX:
|
||||
$form->checkbox('paramsValue', '值')
|
||||
->options($config->source)
|
||||
->required();
|
||||
break;
|
||||
case Configuration::TYPE_NUMBER:
|
||||
$form->number('paramsValue', '值')
|
||||
->required();
|
||||
break;
|
||||
case Configuration::TYPE_RATE:
|
||||
$form->rate('paramsValue', '值')
|
||||
->required();
|
||||
break;
|
||||
case Configuration::TYPE_TEXT:
|
||||
default:
|
||||
$form->text('paramsValue', '值')
|
||||
->required();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
82
modules/Configuration/Models/Configuration.php
Normal file
82
modules/Configuration/Models/Configuration.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Configuration\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
|
||||
class Configuration extends Model
|
||||
{
|
||||
use Cachable;
|
||||
|
||||
const TYPE_TEXT = 'text';
|
||||
const TYPE_IMG = 'image';
|
||||
const TYPE_SELECT = 'select';
|
||||
const TYPE_CHECKBOX = 'checkbox';
|
||||
const TYPE_NUMBER = 'number';
|
||||
const TYPE_RATE = 'rate';
|
||||
const TYPES = [
|
||||
self::TYPE_TEXT => '文本',
|
||||
self::TYPE_IMG => '图片',
|
||||
self::TYPE_SELECT => '下拉列表',
|
||||
self::TYPE_CHECKBOX => '多选框',
|
||||
self::TYPE_NUMBER => '数值',
|
||||
self::TYPE_RATE => '比例',
|
||||
];
|
||||
protected $casts = [
|
||||
'source' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* Notes : 获取当前模块下的参数配置
|
||||
*
|
||||
* @Date : 2021/12/1 13:18
|
||||
* @Author : Mr.wang
|
||||
* @param $module
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getModule($module)
|
||||
{
|
||||
return self::where('module', $module)
|
||||
->get()
|
||||
->pluck('paramsValue', 'keyValue');
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 获取参数值
|
||||
*
|
||||
* @Date : 2021/12/1 11:43
|
||||
* @Author : Mr.wang
|
||||
* @param string $key
|
||||
* @param string $default
|
||||
* @return string
|
||||
*/
|
||||
public static function getValue(string $key = '', $default = ''): string
|
||||
{
|
||||
$config = self::where('keyValue', $key)->first();
|
||||
if (! $config) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $config->paramsValue ?? $default;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 获取参数
|
||||
*
|
||||
* @Date : 2021/12/1 11:42
|
||||
* @Author : Mr.wang
|
||||
* @return string
|
||||
*/
|
||||
public function getParamsTextAttribute(): string
|
||||
{
|
||||
if (in_array($this->type, [
|
||||
'select', 'checkbox', 'radio',
|
||||
])) {
|
||||
return $this->source[$this->paramsValue] ?? '';
|
||||
} else {
|
||||
return $this->paramsValue ?? '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Configuration\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Modules\Configuration\Models\Configuration;
|
||||
use Nwidart\Modules\Facades\Module as ModuleManager;
|
||||
|
||||
class ConfigurationServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* @var string $moduleName
|
||||
*/
|
||||
protected string $moduleName = 'Configuration';
|
||||
|
||||
/**
|
||||
* @var string $moduleNameLower
|
||||
*/
|
||||
protected string $moduleNameLower = 'configuration';
|
||||
|
||||
/**
|
||||
* Boot the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->loadMigrationsFrom(module_path($this->moduleName, 'Database/Migrations'));
|
||||
|
||||
$modules = ModuleManager::toCollection();
|
||||
foreach ($modules as $module) {
|
||||
if ($module->get('config', false)) {
|
||||
$alias = $module->getAlias();
|
||||
$this->app->bind('Conf_'.$alias, function () use ($alias) {
|
||||
return Configuration::getModule($alias);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->register(RouteServiceProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
52
modules/Configuration/Providers/RouteServiceProvider.php
Normal file
52
modules/Configuration/Providers/RouteServiceProvider.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Configuration\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* @var string $moduleName
|
||||
*/
|
||||
protected string $moduleName = 'Configuration';
|
||||
|
||||
/**
|
||||
* The module namespace to assume when generating URLs to actions.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected string $moduleNamespace = 'Modules\Configuration\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Called before routes are registered.
|
||||
* Register any model bindings or pattern based filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function map()
|
||||
{
|
||||
$this->mapAdminRoutes();
|
||||
}
|
||||
|
||||
protected function mapAdminRoutes()
|
||||
{
|
||||
Route::as(config('admin.route.as'))
|
||||
->domain(config('admin.route.domain'))
|
||||
->middleware(config('admin.route.middleware'))
|
||||
->namespace($this->moduleNamespace)
|
||||
->prefix(config('admin.route.prefix'))
|
||||
->group(module_path($this->moduleName, 'Routes/admin.php'));
|
||||
}
|
||||
}
|
||||
6
modules/Configuration/README.md
Normal file
6
modules/Configuration/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# laravel-configuration-module
|
||||
|
||||
# 参数配置模块
|
||||
|
||||
## 需要config的模块配置
|
||||
|
||||
19
modules/Configuration/Routes/admin.php
Normal file
19
modules/Configuration/Routes/admin.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::group([
|
||||
'as' => 'configurations.',
|
||||
], function (Router $router) {
|
||||
$router->get('configurations/{module}', 'IndexController@index')
|
||||
->where(['module' => '[a-z-_]+']);
|
||||
$router->post('configurations/{module}', 'IndexController@store')
|
||||
->where(['module' => '[a-z-_]+']);
|
||||
$router->get('configurations/{module}/create', 'IndexController@create')
|
||||
->where(['module' => '[a-z-_]+']);
|
||||
$router->get('configurations/{module}/{id}/edit', 'IndexController@edit')
|
||||
->where(['module' => '[a-z-_]+', 'id' => '[0-9]+']);
|
||||
$router->put('configurations/{module}/{id}', 'IndexController@update')
|
||||
->where(['module' => '[a-z-_]+', 'id' => '[0-9]+']);
|
||||
});
|
||||
22
modules/Configuration/composer.json
Normal file
22
modules/Configuration/composer.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "uztech/configuration-module",
|
||||
"description": "",
|
||||
"type": "laravel-module",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Yz-Leady",
|
||||
"email": "149307205@qq.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"genealabs/laravel-model-caching": "^0.11.3"
|
||||
},
|
||||
"extra": {
|
||||
"module-dir": "modules"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\Configuration\\": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
18
modules/Configuration/module.json
Normal file
18
modules/Configuration/module.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "Configuration",
|
||||
"alias": "configuration",
|
||||
"description": "模块参数配置管理",
|
||||
"keywords": [
|
||||
"Leady",
|
||||
"参数配置"
|
||||
],
|
||||
"priority": 0,
|
||||
"providers": [
|
||||
"Modules\\Configuration\\Providers\\ConfigurationServiceProvider"
|
||||
],
|
||||
"aliases": {},
|
||||
"files": [],
|
||||
"requires": [],
|
||||
"version": "1.0.0",
|
||||
"author": "Leady"
|
||||
}
|
||||
4
modules/Linker/.gitignore
vendored
Normal file
4
modules/Linker/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.idea
|
||||
vendor
|
||||
.DS_Store
|
||||
composer.lock
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateLinkerRelationsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('linker_relations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('linker_id')->index();
|
||||
$table->morphs('model');
|
||||
$table->enum('mode', ['replace', 'append', 'override'])->default('override');
|
||||
$table->json('params')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('linker_relations');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateLinkersTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('linkers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title')->comment('链接标题');
|
||||
$table->string('type', 50)->comment('链接类型');
|
||||
$table->string('url')->comment('链接地址');
|
||||
$table->json('params')->nullable()->comment('默认参数');
|
||||
$table->boolean('status')->default(0)->comment('状态');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('linkers');
|
||||
}
|
||||
|
||||
}
|
||||
51
modules/Linker/Http/Controllers/IndexController.php
Normal file
51
modules/Linker/Http/Controllers/IndexController.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Linker\Http\Controllers;
|
||||
|
||||
use Encore\Admin\Controllers\AdminController;
|
||||
use Encore\Admin\Form;
|
||||
use Encore\Admin\Grid;
|
||||
use Modules\Linker\Models\Linker;
|
||||
|
||||
class IndexController extends AdminController
|
||||
{
|
||||
|
||||
protected $title = '链接管理';
|
||||
|
||||
protected array $status = [
|
||||
'on' => ['value' => 1, 'text' => '启用', 'color' => 'success'],
|
||||
'off' => ['value' => 0, 'text' => '禁用', 'color' => 'danger'],
|
||||
];
|
||||
|
||||
public function grid(): Grid
|
||||
{
|
||||
$grid = new Grid(new Linker());
|
||||
|
||||
$grid->column('title', '标题');
|
||||
$grid->column('type', '类型')->using(Linker::TYPES);
|
||||
$grid->column('url', '目标地址');
|
||||
$grid->column('params', '附加参数');
|
||||
$grid->column('status', '状态')->switch($this->status);
|
||||
$grid->column('created_at', '创建时间');
|
||||
$grid->column('updated_at', '更新时间');
|
||||
|
||||
return $grid;
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
$form = new Form(new Linker());
|
||||
$form->text('title', '链接标题')->required();
|
||||
$form->select('type', '链接类型')
|
||||
->options(Linker::TYPES)
|
||||
->required();
|
||||
$form->text('url', '目标地址')->required();
|
||||
$form->keyValue('params', '附加参数');
|
||||
$form->switch('status', '状态')
|
||||
->states($this->status)
|
||||
->default(1);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
66
modules/Linker/Linker.php
Normal file
66
modules/Linker/Linker.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Linker;
|
||||
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class Linker
|
||||
{
|
||||
|
||||
protected static string $mainTitle = '链接管理';
|
||||
|
||||
/**
|
||||
* Notes : 模块初始化要做的一些操作
|
||||
* @Date : 2021/3/12 11:34 上午
|
||||
* @Author : < Jason.C >
|
||||
*/
|
||||
public static function install()
|
||||
{
|
||||
Artisan::call('migrate', [
|
||||
'--path' => 'modules/Linker/Database/Migrations',
|
||||
]);
|
||||
|
||||
self::createAdminMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 卸载模块的一些操作
|
||||
* @Date : 2021/3/12 11:35 上午
|
||||
* @Author : < Jason.C >
|
||||
*/
|
||||
public static function uninstall()
|
||||
{
|
||||
$menu = config('admin.database.menu_model');
|
||||
|
||||
$main = $menu::where('title', self::$mainTitle)->first();
|
||||
|
||||
$main->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 创建后台菜单
|
||||
* @Date : 2021/3/17 9:48 上午
|
||||
* @Author : < Jason.C >
|
||||
*/
|
||||
protected static function createAdminMenu()
|
||||
{
|
||||
$menu = config('admin.database.menu_model');
|
||||
|
||||
$main = $menu::create([
|
||||
'parent_id' => 0,
|
||||
'order' => 45,
|
||||
'title' => self::$mainTitle,
|
||||
'icon' => 'fa-bars',
|
||||
]);
|
||||
|
||||
$main->children()->createMany([
|
||||
[
|
||||
'order' => 0,
|
||||
'title' => '链接管理',
|
||||
'icon' => 'fa-bars',
|
||||
'uri' => 'linkers',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
102
modules/Linker/Models/Linker.php
Normal file
102
modules/Linker/Models/Linker.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Linker\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Linker extends Model
|
||||
{
|
||||
|
||||
use Cachable,
|
||||
SoftDeletes;
|
||||
|
||||
protected $table = 'linkers';
|
||||
|
||||
protected $casts = [
|
||||
'params' => 'json',
|
||||
];
|
||||
|
||||
const TYPE_WEB = 'web';
|
||||
const TYPE_MINI = 'mini';
|
||||
const TYPE_APP_NAVIGATE_TO = 'navigateTo';
|
||||
const TYPE_APP_REDIRECT_TO = 'redirectTo';
|
||||
const TYPE_APP_RE_LAUNCH = 'reLaunch';
|
||||
const TYPE_APP_SWITCH_TAB = 'switchTab';
|
||||
const TYPE_APP_NAVIGATE_BACK = 'navigateBack';
|
||||
|
||||
const TYPES = [
|
||||
self::TYPE_WEB => '网页连接(web)',
|
||||
self::TYPE_MINI => '小程序中跳转',
|
||||
self::TYPE_APP_NAVIGATE_TO => 'APP内部页面转跳',
|
||||
self::TYPE_APP_REDIRECT_TO => '跳转内部页面(关闭当前页)',
|
||||
self::TYPE_APP_RE_LAUNCH => '跳转内部页面(关闭所有页面)',
|
||||
self::TYPE_APP_SWITCH_TAB => 'TAB跳转(关闭所有非TAB页面)',
|
||||
self::TYPE_APP_NAVIGATE_BACK => 'APP页面返回',
|
||||
];
|
||||
|
||||
const MODE_APPEND = 'append';
|
||||
const MODE_REPLACE = 'replace';
|
||||
const MODE_OVERRIDE = 'override';
|
||||
|
||||
const MODES = [
|
||||
self::MODE_APPEND => '追加',
|
||||
self::MODE_REPLACE => '替换',
|
||||
self::MODE_OVERRIDE => '覆盖',
|
||||
];
|
||||
|
||||
/**
|
||||
* Notes : 转换链接到实际输出
|
||||
* @Date : 2021/6/21 4:03 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param \Modules\Linker\Models\LinkerRelation $relation
|
||||
* @return array
|
||||
*/
|
||||
public function getResource(LinkerRelation $relation): array
|
||||
{
|
||||
$params = '';
|
||||
|
||||
if (is_array($this->params)) {
|
||||
if ($relation->params) {
|
||||
switch ($relation->mode) {
|
||||
case self::MODE_APPEND:
|
||||
$this->params = array_merge($this->params, $relation->params);
|
||||
break;
|
||||
case self::MODE_REPLACE:
|
||||
$this->params = array_replace($this->params, $relation->params);
|
||||
break;
|
||||
case self::MODE_OVERRIDE;
|
||||
$this->params = $relation->params;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$params = http_build_query($this->params);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'path' => $this->url,
|
||||
'openType' => $this->type,
|
||||
'url' => $this->url,
|
||||
'params' => $params,
|
||||
];
|
||||
switch ($data['openType']) {
|
||||
case self::TYPE_WEB:
|
||||
$data['path'] = '';
|
||||
$data['url'] .= '?' . $data['params'];
|
||||
$data['params'] = '';
|
||||
break;
|
||||
case self::TYPE_APP_NAVIGATE_BACK:
|
||||
$data['path'] = '';
|
||||
$data['url'] = '';
|
||||
$data['params'] = '';
|
||||
break;
|
||||
default:
|
||||
$data['url'] = '';
|
||||
break;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
40
modules/Linker/Models/LinkerRelation.php
Normal file
40
modules/Linker/Models/LinkerRelation.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Linker\Models;
|
||||
|
||||
use App\Models\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
class LinkerRelation extends Model
|
||||
{
|
||||
|
||||
protected $table = 'linker_relations';
|
||||
|
||||
protected $casts = [
|
||||
'params' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* Notes : 隶属链接
|
||||
* @Date : 2021/6/18 4:47 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function linker(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Linker::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 链接对应的模型
|
||||
* @Date : 2021/6/22 2:11 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function model(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
}
|
||||
47
modules/Linker/Providers/LinkerServiceProvider.php
Normal file
47
modules/Linker/Providers/LinkerServiceProvider.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Linker\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class LinkerServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string $moduleName
|
||||
*/
|
||||
protected string $moduleName = 'Linker';
|
||||
|
||||
/**
|
||||
* @var string $moduleNameLower
|
||||
*/
|
||||
protected string $moduleNameLower = 'linker';
|
||||
|
||||
/**
|
||||
* Boot the application events.
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->loadMigrationsFrom(module_path($this->moduleName, 'Database/Migrations'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->register(RouteServiceProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
* @return array
|
||||
*/
|
||||
public function provides(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
51
modules/Linker/Providers/RouteServiceProvider.php
Normal file
51
modules/Linker/Providers/RouteServiceProvider.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Linker\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string $moduleName
|
||||
*/
|
||||
protected string $moduleName = 'Linker';
|
||||
|
||||
/**
|
||||
* The module namespace to assume when generating URLs to actions.
|
||||
* @var string
|
||||
*/
|
||||
protected string $moduleNamespace = 'Modules\Linker\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Called before routes are registered.
|
||||
* Register any model bindings or pattern based filters.
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
* @return void
|
||||
*/
|
||||
public function map()
|
||||
{
|
||||
$this->mapAdminRoutes();
|
||||
}
|
||||
|
||||
protected function mapAdminRoutes()
|
||||
{
|
||||
Route::as(config('admin.route.as'))
|
||||
->domain(config('admin.route.domain'))
|
||||
->middleware(config('admin.route.middleware'))
|
||||
->namespace($this->moduleNamespace)
|
||||
->prefix(config('admin.route.prefix'))
|
||||
->group(module_path($this->moduleName, 'Routes/admin.php'));
|
||||
}
|
||||
|
||||
}
|
||||
22
modules/Linker/README.md
Normal file
22
modules/Linker/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# 链接模块
|
||||
|
||||
## 1. 使用
|
||||
|
||||
### 1. 模型 Trait
|
||||
|
||||
```php
|
||||
use Modules\Linker\Traits\HasLinker;
|
||||
```
|
||||
|
||||
### 2. laravel-admin
|
||||
|
||||
自动增加三个字段,
|
||||
1. 选择链接地址
|
||||
2. 替换链接地址里的参数
|
||||
3. 参数替换模式
|
||||
|
||||
```php
|
||||
use Modules\Linker\Traits\WithLinker;
|
||||
|
||||
$this->withUrl($form,'字段名称');
|
||||
```
|
||||
10
modules/Linker/Routes/admin.php
Normal file
10
modules/Linker/Routes/admin.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Routing\Router;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::group([
|
||||
'as' => 'linker.',
|
||||
], function (Router $router) {
|
||||
$router->resource('linkers', 'IndexController');
|
||||
});
|
||||
123
modules/Linker/Traits/HasLinker.php
Normal file
123
modules/Linker/Traits/HasLinker.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Linker\Traits;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Modules\Linker\Models\LinkerRelation;
|
||||
|
||||
trait HasLinker
|
||||
{
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
public $linker_id;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
public $linker_params;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public ?string $linker_mode;
|
||||
|
||||
/**
|
||||
* 处理对应模型中关于链接数据的处理
|
||||
* 模型请 use HasLinker
|
||||
*/
|
||||
public static function bootHasLinker()
|
||||
{
|
||||
self::saving(function ($model) {
|
||||
unset($model->attributes['linker_id']);
|
||||
unset($model->attributes['linker_params']);
|
||||
unset($model->attributes['linker_mode']);
|
||||
});
|
||||
self::saved(function ($model) {
|
||||
$model->saveWithUrl();
|
||||
});
|
||||
// 这里要注意,如果模型使用了缓存 (use GeneaLabs\LaravelModelCaching\Traits\Cachable)
|
||||
// 在表单实例化模型的时候 要使用 (new Model())->disableModelCaching()
|
||||
self::retrieved(function ($model) {
|
||||
if ($relation = $model->hasLinker()) {
|
||||
$model->attributes['linker_id'] = $relation->linker_id;
|
||||
$model->attributes['linker_params'] = $relation->params;
|
||||
$model->attributes['linker_mode'] = $relation->mode;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 处理当前模型多余的三个字段
|
||||
* @Date : 2021/6/22 2:10 下午
|
||||
* @Author : < Jason.C >
|
||||
* @param $value
|
||||
*/
|
||||
public function setLinkerIdAttribute($value)
|
||||
{
|
||||
$this->linker_id = $value;
|
||||
}
|
||||
|
||||
public function setLinkerParamsAttribute($value)
|
||||
{
|
||||
$this->linker_params = $value;
|
||||
}
|
||||
|
||||
public function setLinkerModeAttribute($value)
|
||||
{
|
||||
$this->linker_mode = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 外链入库
|
||||
* 在BOOT中触发
|
||||
*/
|
||||
public function saveWithUrl(): void
|
||||
{
|
||||
if ($this->linker_id) {
|
||||
LinkerRelation::updateOrCreate([
|
||||
'model_type' => get_class($this),
|
||||
'model_id' => $this->getKey(),
|
||||
], [
|
||||
'linker_id' => $this->linker_id,
|
||||
'mode' => $this->linker_mode,
|
||||
'params' => $this->linker_params,
|
||||
]);
|
||||
} elseif (!$this->linker_id && $this->hasLinker()) {
|
||||
$this->hasLinker()->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前模型的链接配置
|
||||
* @return null|LinkerRelation
|
||||
*/
|
||||
public function hasLinker(): ?LinkerRelation
|
||||
{
|
||||
return LinkerRelation::whereHasMorph(
|
||||
'model',
|
||||
[get_class($this)],
|
||||
function (Builder $query) {
|
||||
$query->where($this->getKeyName(), $this->getKey());
|
||||
}
|
||||
)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes : 返回该模型的链接数组
|
||||
* @Date : 2021/6/22 2:08 下午
|
||||
* @Author : < Jason.C >
|
||||
* @return array|null
|
||||
*/
|
||||
public function getLinkerAttribute(): ?array
|
||||
{
|
||||
$relation = $this->hasLinker();
|
||||
if ($relation && $relation->linker && $relation->linker->status) {
|
||||
return $relation->linker->getResource($relation);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
31
modules/Linker/Traits/WithLinker.php
Normal file
31
modules/Linker/Traits/WithLinker.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Linker\Traits;
|
||||
|
||||
use Encore\Admin\Form;
|
||||
use Exception;
|
||||
use Modules\Linker\Models\Linker;
|
||||
|
||||
trait WithLinker
|
||||
{
|
||||
|
||||
public function withUrl(Form $form, string $label = '链接地址'): Form
|
||||
{
|
||||
try {
|
||||
$links = Linker::pluck('title', 'id');
|
||||
} catch (Exception $e) {
|
||||
$links = [0 => '无链接'];
|
||||
}
|
||||
|
||||
$form->divider('链接设置');
|
||||
$form->select('linker_id', $label)
|
||||
->options($links);
|
||||
$form->select('linker_mode', '参数模式')
|
||||
->options(Linker::MODES)
|
||||
->default(Linker::MODE_OVERRIDE);
|
||||
$form->keyValue('linker_params', '替换参数');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
||||
28
modules/Linker/composer.json
Normal file
28
modules/Linker/composer.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "uztech/linker-module",
|
||||
"description": "",
|
||||
"type": "laravel-module",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Yz-Leady",
|
||||
"email": "149307205@qq.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"encore/laravel-admin": "^1.8",
|
||||
"jasonc/api": "^5.0.0",
|
||||
"genealabs/laravel-model-caching": "^0.11.3",
|
||||
"joshbrw/laravel-module-installer": "^2.0",
|
||||
"laravel/framework": "^8.5",
|
||||
"nwidart/laravel-modules": "^8.2"
|
||||
},
|
||||
"extra": {
|
||||
"module-dir": "modules"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\Linker\\": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
15
modules/Linker/module.json
Normal file
15
modules/Linker/module.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Linker",
|
||||
"alias": "linker",
|
||||
"description": "链接管理模块(重构版本)",
|
||||
"keywords": [],
|
||||
"priority": 0,
|
||||
"providers": [
|
||||
"Modules\\Linker\\Providers\\LinkerServiceProvider"
|
||||
],
|
||||
"aliases": {},
|
||||
"files": [],
|
||||
"requires": [],
|
||||
"version": "1.0.0",
|
||||
"author": "Leady"
|
||||
}
|
||||
4
modules/Mall/.gitignore
vendored
Normal file
4
modules/Mall/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.idea
|
||||
vendor
|
||||
.DS_Store
|
||||
composer.lock
|
||||
168
modules/Mall/Config/config.php
Normal file
168
modules/Mall/Config/config.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 模块名称
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'name' => 'Mall',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 订单编号计数器位数,取值范围 6 - 16
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'order_no_counter_length' => 8,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 退款单编号前缀
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'refund_no_counter_prefix' => 'RF',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 退款单编号计数器位数,取值范围 6 - 16 - 退款编号前缀位数
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'refund_no_counter_length' => 6,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| 商品规格的扩展属性
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'sku_extends_attributes' => [
|
||||
'market_fee' => '平台手续费',
|
||||
],
|
||||
|
||||
'administrator_max_id' => 10000,
|
||||
|
||||
'workflow' => [
|
||||
'orders' => [
|
||||
'type' => 'state_machine',
|
||||
'marking_store' => [
|
||||
'type' => 'single_state',
|
||||
'property' => 'currentState',
|
||||
],
|
||||
'supports' => [Modules\Mall\Models\Order::class],
|
||||
'places' => [
|
||||
'INIT',
|
||||
'CANCEL',
|
||||
'PAID',
|
||||
'DELIVERED',
|
||||
'SIGNED',
|
||||
'COMPLETED',
|
||||
'REFUND_APPLY',
|
||||
'REFUND_AGREE',
|
||||
'REFUND_REFUSE',
|
||||
'REFUND_DELIVER',
|
||||
'REFUND_DELIVERD',
|
||||
'REFUND_PROCESS',
|
||||
'REFUND_COMPLETED',
|
||||
],
|
||||
'transitions' => [
|
||||
'cancel' => [
|
||||
'from' => ['INIT', 'PAID'],
|
||||
'to' => 'CANCEL',
|
||||
],
|
||||
'pay' => [
|
||||
'from' => 'INIT',
|
||||
'to' => 'PAID',
|
||||
],
|
||||
'deliver' => [
|
||||
'from' => 'PAID',
|
||||
'to' => 'DELIVERED',
|
||||
],
|
||||
'sign' => [
|
||||
'from' => 'DELIVERED',
|
||||
'to' => 'SIGNED',
|
||||
],
|
||||
'complete' => [
|
||||
'from' => 'SIGNED',
|
||||
'to' => 'COMPLETED',
|
||||
],
|
||||
'refund' => [
|
||||
'from' => ['PAID', 'SIGNED'],
|
||||
'to' => 'REFUND_APPLY',
|
||||
],
|
||||
'agree' => [
|
||||
'from' => ['PAID', 'SIGNED', 'REFUND_APPLY'],
|
||||
'to' => 'REFUND_AGREE',
|
||||
],
|
||||
'refuse' => [
|
||||
'from' => 'REFUND_APPLY',
|
||||
'to' => 'REFUND_REFUSE',
|
||||
],
|
||||
'user_deliver' => [
|
||||
'from' => 'REFUND_AGREE',
|
||||
'to' => 'REFUND_DELIVER',
|
||||
],
|
||||
'user_deliverd' => [
|
||||
'from' => 'REFUND_DELIVER',
|
||||
'to' => 'REFUND_DELIVERD',
|
||||
],
|
||||
'process' => [
|
||||
'from' => ['REFUND_AGREE', 'REFUND_DELIVERD'],
|
||||
'to' => 'REFUND_PROCESS',
|
||||
],
|
||||
'completed' => [
|
||||
'from' => ['PAID', 'DELIVERED', 'SIGNED', 'REFUND_PROCESS', 'REFUND_DELIVERD'],
|
||||
'to' => 'REFUND_COMPLETED',
|
||||
],
|
||||
],
|
||||
],
|
||||
'refunds' => [
|
||||
'type' => 'state_machine',
|
||||
'marking_store' => [
|
||||
'type' => 'single_state',
|
||||
'property' => 'currentState',
|
||||
],
|
||||
'supports' => [Modules\Mall\Models\Refund::class],
|
||||
'places' => [
|
||||
'REFUND_APPLY',
|
||||
'REFUND_AGREE',
|
||||
'REFUND_REFUSE',
|
||||
'REFUND_PROCESS',
|
||||
'REFUND_DELIVER',
|
||||
'REFUND_DELIVERED',
|
||||
'REFUND_SIGNED',
|
||||
'REFUND_COMPLETED',
|
||||
],
|
||||
'transitions' => [
|
||||
'agree' => [
|
||||
'from' => 'REFUND_APPLY',
|
||||
'to' => 'REFUND_AGREE',
|
||||
],
|
||||
'refuse' => [
|
||||
'from' => 'REFUND_APPLY',
|
||||
'to' => 'REFUND_REFUSE',
|
||||
],
|
||||
'deliver' => [
|
||||
'from' => 'REFUND_AGREE',
|
||||
'to' => 'REFUND_DELIVER',
|
||||
],
|
||||
'delivered' => [
|
||||
'from' => 'REFUND_DELIVER',
|
||||
'to' => 'REFUND_DELIVERED',
|
||||
],
|
||||
'sign' => [
|
||||
'from' => 'REFUND_DELIVERED',
|
||||
'to' => 'REFUND_SIGNED',
|
||||
],
|
||||
'process' => [
|
||||
'from' => ['REFUND_AGREE', 'REFUND_SIGNED'],
|
||||
'to' => 'REFUND_PROCESS',
|
||||
],
|
||||
'completed' => [
|
||||
'from' => 'REFUND_PROCESS',
|
||||
'to' => 'REFUND_COMPLETED',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallAddressesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_addresses', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedInteger('user_id')->index();
|
||||
$table->string('name', 32);
|
||||
$table->string('mobile', 32);
|
||||
$table->unsignedInteger('province_id');
|
||||
$table->unsignedInteger('city_id');
|
||||
$table->unsignedInteger('district_id');
|
||||
$table->string('address');
|
||||
$table->boolean('is_default')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_addresses');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallBannersTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_banners', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->default(0)->index()->comment('所属店铺');
|
||||
$table->string('title');
|
||||
$table->string('cover');
|
||||
$table->integer('position')->unsigned();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_banners');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallBrandsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_brands', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->string('name');
|
||||
$table->string('cover')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_brands');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallCartsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_carts', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->unsignedBigInteger('sku_id')->comment('加入购物车的商品条目');
|
||||
$table->unsignedInteger('qty')->default(1)->comment('数量');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_carts');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallCategoriesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('parent_id')->default(0)->index()->comment('父级id');
|
||||
$table->string('name');
|
||||
$table->string('slug')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->string('cover')->nullable();
|
||||
$table->integer('order')->default(0);
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_categories');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallDeliveriesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_deliveries', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->string('name')->comment('模板名称');
|
||||
$table->unsignedTinyInteger('type')->comment('计费方式:1按件数 2按重量');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_deliveries');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateMallDeliveryRulesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_delivery_rules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->integer('delivery_id')->comment('配送模板id');
|
||||
$table->json('regions')->nullable()->comment('可配送区域(城市id集)');
|
||||
$table->decimal('first', 8, 2)->default(0)->comment('首件(个)/首重(Kg)');
|
||||
$table->decimal('first_fee', 8, 2)->default(0)->comment('运费(元)');
|
||||
|
||||
$table->decimal('additional', 8, 2)->default(0)->comment('续件/续重');
|
||||
$table->decimal('additional_fee', 8, 2)->default(0)->comment('续费(元)');
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_delivery_rules');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Modules\Mall\Database\Seeders\ExpressSeeder;
|
||||
|
||||
class CreateMallExpressesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_expresses', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('slug')->nullable()->comment('简称');
|
||||
$table->string('cover')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
|
||||
Artisan::call('db:seed', [
|
||||
'--class' => ExpressSeeder::class,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_expresses');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsSkusTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods_skus', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('goods_id')->index();
|
||||
$table->string('unit')->nullable()->comment('商品单元编号');
|
||||
$table->string('cover')->nullable();
|
||||
$table->decimal('price');
|
||||
$table->decimal('score')->comment('积分/原石');
|
||||
$table->decimal('assets', 8, 2)->comment('资产');
|
||||
$table->integer('stock')->default(0);
|
||||
$table->decimal('weight')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods_skus');
|
||||
Schema::dropIfExists('mall_goods_sku_spec');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsSpecValuesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods_spec_values', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('spec_id')->index();
|
||||
$table->string('value');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods_spec_values');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsSpecsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods_specs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('goods_id')->index();
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods_specs');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('category_id')->index()->comment('分类');
|
||||
$table->unsignedBigInteger('brand_id')->nullable()->index()->comment('品牌ID');
|
||||
$table->unsignedBigInteger('delivery_id')->nullable()->comment('物流模板');
|
||||
$table->unsignedTinyInteger('type')->default(1)->comment('规格类型');
|
||||
$table->unsignedTinyInteger('pay_type')->default(1)->comment('支付方式');
|
||||
$table->unsignedTinyInteger('deduct_stock_type')->default(1)->comment('库存扣减方式');
|
||||
$table->unsignedTinyInteger('channel')->default(1)->comment('商品类型');
|
||||
$table->boolean('status')->default(0);
|
||||
$table->boolean('is_post_sale')->default(1)->comment('是否可以申请售后');
|
||||
$table->unsignedInteger('clicks')->default(0)->comment('浏览量');
|
||||
$table->unsignedInteger('sales')->default(0)->comment('总销量');
|
||||
$table->decimal('original_price', 10, 2)->default(0)->comment('商品显示的原价');
|
||||
$table->string('name');
|
||||
$table->string('cover')->nullable();
|
||||
$table->json('pictures')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->text('content')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallGoodsTagTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_goods_tag', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('goods_id')->index();
|
||||
$table->unsignedBigInteger('tag_id')->index();
|
||||
$table->timestamps();
|
||||
|
||||
$table->primary(['goods_id', 'tag_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_goods_tag');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallJobsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_jobs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->unsignedBigInteger('shop_id')->index();
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_jobs');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallOrderExpressesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_order_expresses', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('order_id')->index();
|
||||
|
||||
$table->string('name', 32)->nullable();
|
||||
$table->string('mobile', 32)->nullable();
|
||||
$table->unsignedInteger('province_id')->index()->nullable();
|
||||
$table->unsignedInteger('city_id')->index()->nullable();
|
||||
$table->unsignedInteger('district_id')->index()->nullable();
|
||||
$table->string('address')->nullable();
|
||||
|
||||
$table->unsignedBigInteger('express_id')->nullable()->comment('物流公司');
|
||||
$table->string('express_no', 32)->nullable()->comment('物流单号');
|
||||
$table->dateTime('deliver_at')->nullable()->comment('发货时间');
|
||||
$table->dateTime('receive_at')->nullable()->comment('签收时间');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_order_expresses');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallOrderItemsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_order_items', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('order_id')->index('order_id');
|
||||
$table->morphs('item');
|
||||
$table->unsignedInteger('qty')->comment('数量');
|
||||
$table->unsignedDecimal('price', 20, 2)->comment('单价');
|
||||
$table->json('source')->nullable();
|
||||
$table->timestamp('created_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_order_items');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallOrdersTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_orders', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->string('order_no', 32)->unique()->comment('订单编号');
|
||||
$table->unsignedInteger('user_id')->index()->comment('下单用户');
|
||||
|
||||
$table->unsignedDecimal('amount', 20, 2)->comment('订单金额');
|
||||
$table->unsignedDecimal('freight', 10, 2)->default(0)->comment('运费');
|
||||
|
||||
$table->timestamp('expired_at')->nullable()->comment('订单过期时间');
|
||||
$table->timestamp('paid_at')->nullable()->comment('支付时间');
|
||||
|
||||
$table->string('state', 16)->comment('状态')->nullable();
|
||||
$table->boolean('type')->comment('订单类型:1 正常 2试用');
|
||||
$table->string('remark')->nullable()->comment('用户留言');
|
||||
$table->string('description')->nullable()->comment('备注');
|
||||
|
||||
$table->json('source')->comment('附加数据')->nullable();
|
||||
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_orders');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallReasonsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_reasons', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->boolean('status')->default(0);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('reasons');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallRefundExpressesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_refund_expresses', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('refund_id')->index()->comment('所属退款单');
|
||||
$table->string('company')->nullable()->comment('退款物流');
|
||||
$table->string('number')->nullable()->comment('退款单号');
|
||||
$table->timestamp('deliver_at')->nullable()->comment('寄回时间');
|
||||
$table->timestamp('receive_at')->nullable()->comment('收到时间');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_refund_expresses');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallRefundItemsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_refund_items', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('refund_id')->index()->comment('所属退款单');
|
||||
$table->unsignedBigInteger('order_id')->comment('所属订单');
|
||||
$table->unsignedBigInteger('order_item_id')->comment('详情ID');
|
||||
$table->unsignedInteger('qty')->comment('数量');
|
||||
$table->unsignedDecimal('price', 20, 2)->comment('单价');
|
||||
$table->json('source')->nullable();
|
||||
$table->timestamp('created_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_refund_items');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallRefundLogsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_refund_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('refund_id');
|
||||
$table->morphs('userable');
|
||||
$table->string('pictures')->nullable()->comment('图片');
|
||||
$table->string('title')->nullable()->comment('原因');
|
||||
$table->string('remark')->nullable()->comment('备注');
|
||||
$table->string('state', 16)->comment('状态')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_tags');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateMallRefundsTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('mall_refunds', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('shop_id')->index()->comment('所属店铺');
|
||||
$table->unsignedBigInteger('order_id')->index()->comment('所属订单');
|
||||
$table->string('refund_no', 32)->comment('退款单号');
|
||||
$table->unsignedBigInteger('user_id')->comment('下单用户');
|
||||
$table->unsignedDecimal('refund_total', 20, 2)->comment('申请退款金额');
|
||||
$table->unsignedDecimal('actual_total', 20, 2)->comment('实退金额');
|
||||
$table->string('state', 16)->comment('状态')->nullable();
|
||||
$table->string('remark')->nullable()->comment('备注');
|
||||
$table->timestamp('refunded_at')->nullable()->comment('退款时间');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('mall_refunds');
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user