1
0
Fork 0

处理冲突

develop
vine_liutk 2023-05-10 21:37:55 +08:00
commit ce8ee04df9
18 changed files with 322 additions and 39 deletions

View File

@ -51,12 +51,13 @@ class Components extends BaseRenderer {
->options([
"menubar" => false,
"min_height" => 500,
"toolbar" => "undo redo | bold italic underline strikethrough | fontfamily fontsize blocks | alignleft aligncenter alignright alignjustify | image link | outdent indent | numlist bullist | forecolor backcolor removeformat | charmap emoticons",
"plugins" => 'image link table lists charmap emoticons code table fullscreen',
"toolbar" => "undo redo | bold italic underline strikethrough | fontfamily fontsize blocks | alignleft aligncenter alignright alignjustify | image link | outdent indent | numlist bullist table | forecolor backcolor removeformat | charmap emoticons | code fullscreen",
"toolbar_mode" => "wrap",
"help_tabs" => [],
"convert_urls" => false,
"quickbars_selection_toolbar" => "fontsize forecolor backcolor",
"toolbar_mode" => "wrap",
"quickbars_insert_toolbar" => false,
// "quickbars_selection_toolbar" => "fontsize forecolor backcolor",
// "quickbars_insert_toolbar" => false,
])
->receiver(admin_url('upload_rich'))
->name($name)

View File

@ -0,0 +1,51 @@
<?php
namespace App\Casts;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage as StorageFacades;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
/**
* 转换文件存储路径
*
* get: 返回全路径
* set: 原样保存
*/
class Storage implements CastsAttributes
{
protected $disk;
function __construct($disk = 'public')
{
$this->disk = $disk;
}
/**
* Cast the given value.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return array
*/
public function get($model, $key, $value, $attributes)
{
return $value ? (Str::startsWith($value, ['http://', 'https://']) ? $value : StorageFacades::disk($this->disk)->url($value)) : '';
}
/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param array $value
* @param array $attributes
* @return string
*/
public function set($model, $key, $value, $attributes)
{
return $value;
}
}

View File

@ -44,6 +44,7 @@ class Handler extends ExceptionHandler
*/
public function register()
{
// Laravel9.x 无法捕获 ModelNotFoundException, 在父类 prepareException 方法中被转换为 Symfony\Component\HttpKernel\Exception\NotFoundHttpException
$this->renderable(function (\Illuminate\Database\Eloquent\ModelNotFoundException $e, Request $request) {
if ($request->acceptsJson()) {
return response()->json(['status' => 404, 'msg' => '资源不存在', 'data' => null], 200);

View File

@ -32,6 +32,8 @@ class ArticleController extends Controller
$list = $query->paginate($request->input('per_page'));
return $this->json(ArticleResource::collection($list));
}

View File

@ -0,0 +1,64 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\{Region, RegionCategory};
use App\Http\Resources\{RegionResource, RegionCategoryResource, RegionPlantResource, PlantHarvestResource};
use App\Filters\Admin\RegionFilter;
class RegionController extends Controller
{
public function category(Request $request)
{
$list = RegionCategory::query()->show()->sort()->get();
return $this->json(RegionCategoryResource::collection($list));
}
public function index(Request $request)
{
$query = Region::with(['currentPlant'])->filter($request->all(), RegionFilter::class)->sort()->show();
$list = $query->paginate($request->input('per_page'));
return $this->json(RegionResource::collection($list));
}
public function show($id)
{
$info = Region::with(['currentPlant'])->show()->findOrFail($id);
return $this->json(RegionResource::make($info));
}
public function plants($id, Request $request)
{
$info = Region::show()->findOrFail($id);
$query = $info->plants();
$per = $request->input('per_page');
if ($per == -1) {
$list = $query->get();
} else {
$list = $query->paginate($per);
}
return $this->json(RegionPlantResource::collection($list));
}
public function harvests($id, Request $request)
{
$info = Region::show()->findOrFail($id);
$query = $info->harvests();
$per = $request->input('per_page');
if ($per == -1) {
$list = $query->get();
} else {
$list = $query->paginate($per);
}
return $this->json(PlantHarvestResource::collection($list));
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class PlantHarvestResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $this->id,
'plant_id' => $this->plant_id,
'region_id' => $this->region_id,
'director' => $this->director,
'area' => $this->area,
'output' => $this->output,
'harvest_at' => $this->harvest_at ? $this->harvest_at->timestamp : null,
];
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class RegionCategoryResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'icon' => $this->icon,
'description' => $this->description,
];
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class RegionPlantResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $this->id,
'plant_name' => $this->plant_name,
'director' => $this->director,
'area' => $this->area,
'start_at' => $this->start_at ? $this->start_at->timestamp : null,
'end_at' => $this->end_at ? $this->end_at->timestamp : null,
'plant_state' => $this->plant_state,
];
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class RegionResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'cover' => $this->cover,
'director' => $this->director,
'area' => $this->area,
'description' => $this->description,
'category_id' => $this->category_id,
'category' => RegionCategoryResource::make($this->whenLoaded('category')),
'current_plant' => RegionPlantResource::make($this->whenLoaded('currentPlant')),
];
}
}

View File

@ -2,12 +2,10 @@
namespace App\Models;
use Illuminate\Support\Str;
use App\Casts\Storage;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
/**
* 文章
*/
@ -23,15 +21,9 @@ class Article extends Model
'published_at' => 'datetime:Y-m-d H:i:s',
'is_enable' => 'boolean',
'is_recommend' => 'boolean',
'cover' => Storage::class,
];
protected function cover(): Attribute
{
return Attribute::make(
get: fn($value) => $value ? (Str::startsWith($value, ['http://', 'https://']) ? $value : Storage::url($value)) : '',
);
}
public function category()
{
return $this->belongsTo(ArticleCategory::class, 'category_id');

View File

@ -2,13 +2,11 @@
namespace App\Models;
use App\Casts\Storage;
use Illuminate\Support\Str;
use App\Filters\BannerFilter;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
/**
* 广告图
@ -25,15 +23,9 @@ class Banner extends Model
'published_at' => 'datetime:Y-m-d H:i:s',
'is_enable' => 'boolean',
'link_config' => 'json',
'picture' => Storage::class,
];
protected function picture(): Attribute
{
return Attribute::make(
get: fn($value) => $value ? (Str::startsWith($value, ['http://', 'https://']) ? $value : Storage::url($value)) : '',
);
}
public function place()
{
return $this->belongsTo(BannerPlace::class, 'place_id');

View File

@ -2,9 +2,14 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Casts\Storage;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
/**
* 实验田
*/
class Region extends Model
{
use Filterable;
@ -14,11 +19,27 @@ class Region extends Model
'sort', 'is_recommend','is_enable'
];
protected $casts = [
'cover' => Storage::class,
];
protected function serializeDate(\DateTimeInterface $date){
return $date->format('Y-m-d H:i:s');
}
public function category(){
public function scopeShow($q)
{
return $q->where('is_enable', 1);
}
public function scopeSort($q)
{
return $q->orderBy('sort', 'desc')->latest('id');
}
// 试验田分类
public function category()
{
return $this->belongsTo(RegionCategory::class, 'category_id');
}
@ -26,6 +47,23 @@ class Region extends Model
return $this->belongsToMany(MonitorMode::class, RegionMonitor::class, 'region_id', 'monitor_id')->withTimestamps();
}
// 种植记录
public function plants()
{
return $this->hasMany(RegionPlantLog::class, 'region_id')->orderBy('start_at', 'desc');
}
// 当前种植
public function currentPlant()
{
return $this->hasOne(RegionPlantLog::class, 'region_id')->orderBy('start_at', 'desc');
}
// 收货记录
public function harvests()
{
return $this->hasMany(PlantHarvestLog::class, 'region_id')->orderBy('harvest_at', 'desc');
}
public static function regionTabConfig($region = null){
$tabs = [

View File

@ -5,13 +5,21 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use EloquentFilter\Filterable;
use App\Casts\Storage;
/**
* 区域分类
*/
class RegionCategory extends Model
{
use HasFactory;
use Filterable;
protected $fillable = ['name', 'icon', 'description', 'parent_id', 'level', 'sort', 'path', 'is_enable'];
protected $casts = [
'icon' => Storage::class,
];
protected function serializeDate(\DateTimeInterface $date){
return $date->format('Y-m-d H:i:s');
@ -41,4 +49,14 @@ class RegionCategory extends Model
{
return $this->belongsTo(self::class, 'parent_id');
}
public function scopeShow($q)
{
return $q->where('is_enable', 1);
}
public function scopeSort($q)
{
return $q->orderBy('sort', 'desc')->latest('id');
}
}

View File

@ -6,6 +6,9 @@ use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
/**
* 种植记录
*/
class RegionPlantLog extends Model
{
use Filterable;
@ -19,13 +22,15 @@ class RegionPlantLog extends Model
//1进行中2已结束
protected function plantState():Attribute
{
{
return Attribute::make(
get:fn($value, $attributes) => $attributes['end_at'] ? 2:1,
get: fn($value) => $this->end_at ? 2 : 1,
);
}
public function harvestes(){
// 收获记录
public function harvestes()
{
return $this->hasMany(PlantHarvestLog::class, 'plant_id');
}
}

View File

@ -2,7 +2,7 @@
namespace App\Services\Admin;
use App\Models\PlantHarvestLog;
use App\Models\{PlantHarvestLog, RegionPlantLog};
use App\Filters\Admin\PlantHarvestLogFilter;
use Illuminate\Support\Arr;
use Throwable;
@ -21,7 +21,7 @@ class CropHarvestService extends BaseService
public function store($data): bool
{
$columns = $this->getTableColumns();
$model = $this->getModel();
$model = $this->getModel();
foreach ($data as $k => $v) {
if (!in_array($k, $columns)) {
@ -29,6 +29,9 @@ class CropHarvestService extends BaseService
}
$model->setAttribute($k, $v);
}
if ($model->plant_id) {
$model->region_id = RegionPlantLog::where('id', $model->plant_id)->value('region_id');
}
try{
DB::beginTransaction();

View File

@ -15,6 +15,7 @@ return new class extends Migration
{
Schema::create('plant_harvest_logs', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('region_id');
$table->unsignedBigInteger('plant_id');
$table->string('director')->nullable()->comment('负责人');
$table->decimal('area')->default(0.00)->comment('面积/平米');

View File

@ -20,5 +20,6 @@ class DatabaseSeeder extends Seeder
$this->call(KeywordSeeder::class);
$this->call(BannerSeeder::class);
$this->call(SettingSeeder::class);
$this->call(RegionCategorySeeder::class);
}
}

View File

@ -2,6 +2,7 @@
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\{BannerController, AdminNoticeController, ArticleController, RegionController};
/*
|--------------------------------------------------------------------------
@ -14,12 +15,18 @@ use Illuminate\Support\Facades\Route;
|
*/
Route::get('banner', [\App\Http\Controllers\Api\BannerController::class, 'index']);
Route::get('banner', [BannerController::class, 'index']);
Route::get('notice', [\App\Http\Controllers\Api\AdminNoticeController::class, 'index']);
Route::get('notice/{id}', [\App\Http\Controllers\Api\AdminNoticeController::class, 'show']);
Route::get('notice', [AdminNoticeController::class, 'index']);
Route::get('notice/{id}', [AdminNoticeController::class, 'show']);
Route::get('article/category', [\App\Http\Controllers\Api\ArticleController::class, 'category']);
Route::get('article/tree', [\App\Http\Controllers\Api\ArticleController::class, 'tree']);
Route::get('article', [\App\Http\Controllers\Api\ArticleController::class, 'index']);
Route::get('article/{id}', [\App\Http\Controllers\Api\ArticleController::class, 'show']);
Route::get('article/category', [ArticleController::class, 'category']);
Route::get('article/tree', [ArticleController::class, 'tree']);
Route::get('article', [ArticleController::class, 'index']);
Route::get('article/{id}', [ArticleController::class, 'show']);
Route::get('region/category', [RegionController::class, 'category']);
Route::get('region', [RegionController::class, 'index']);
Route::get('region/{id}', [RegionController::class, 'show']);
Route::get('region/{id}/plants', [RegionController::class, 'plants']);
Route::get('region/{id}/harvests', [RegionController::class, 'harvests']);