调整表结构

dev
vine_liutk 2022-10-21 17:39:06 +08:00
parent 31874831f7
commit 3653cad347
20 changed files with 330 additions and 69 deletions

View File

@ -0,0 +1,9 @@
<?php
namespace App\Enums;
enum BaseType: int
{
case Base = 1; // 基地
case Town = 2; // 城镇
}

View File

@ -2,12 +2,13 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Enums\BaseType;
use App\Helpers\Paginator; use App\Helpers\Paginator;
use Illuminate\Http\Request;
use App\Models\AgriculturalBase;
use Illuminate\Support\Facades\DB;
use App\Http\Requestes\AgriculturalBaseRequest; use App\Http\Requestes\AgriculturalBaseRequest;
use App\Http\Resources\AgriculturalBaseResource; use App\Http\Resources\AgriculturalBaseResource;
use App\Models\AgriculturalBase;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AgriculturalBaseController extends Controller class AgriculturalBaseController extends Controller
{ {
@ -28,6 +29,12 @@ class AgriculturalBaseController extends Controller
public function store(AgriculturalBaseRequest $request) public function store(AgriculturalBaseRequest $request)
{ {
$cropsIds = $request->input('crops_ids', []); $cropsIds = $request->input('crops_ids', []);
// $type = $request->input('type');
// //已添加区域无法变更类型
// if($type == BaseType::Town->value) {
// return $this->error('无法添加城镇');
// }
try { try {
DB::beginTransaction(); DB::beginTransaction();
//添加基地信息 //添加基地信息
@ -53,6 +60,11 @@ class AgriculturalBaseController extends Controller
public function update(AgriculturalBase $agriculturalBasic, AgriculturalBaseRequest $request) public function update(AgriculturalBase $agriculturalBasic, AgriculturalBaseRequest $request)
{ {
$cropsIds = $request->input('crops_ids', []); $cropsIds = $request->input('crops_ids', []);
$type = $request->input('type');
//已添加区域无法变更类型
if($type !== $agriculturalBasic->type->value) {
return $this->error('无法变更类型');
}
try { try {
DB::beginTransaction(); DB::beginTransaction();
//添加基地信息 //添加基地信息

View File

@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers;
use App\Models\Crop;
use App\Models\CropYield;
use Illuminate\Http\Request;
use App\Http\Requestes\CropRequest;
use App\Http\Resources\CropResource;
class CropController extends Controller
{
public function index(Request $request)
{
$query = Crop::filter($request->input());
$list = $query->sort()->get();
return $this->json(CropResource::collection($list));
}
public function store(CropRequest $request)
{
$input = $request->input();
//如果有上级录入path
if($input['parent_id'] ?? 0){
$parent = Crop::findOrFail($input['parent_id']);
$input['path'] = ($parent?->path ?? '').$parent?->id.'-';
}
Crop::create($input);
return $this->success('添加成功');
}
public function show(Crop $crop)
{
return $this->json(CropResource::make($crop));
}
public function update(Crop $crop, CropRequest $request)
{
//如果原本是结点,不允许修改为非节点
//如果原本非结点,且有子节点,同样无法修改;
$input = $request->input();
if($input['is_end'] != $crop->is_end){
if($crop->is_end || Crop::where(['parent_id', $crop->id])->exists()){
return $this->error('无法修改结点状态');
}
}
$crop->update(array_merge($request->input()));
return $this->success('修改成功');
}
public function destroy(Crop $crop)
{
//如果有关联数据,无法删除
if(CropYield::where('crop_id', $crop->id)->exists()){
return $this->error('该结点有关联产量数据, 无法删除');
}
//如果有子节点,无法删除
if(Crop::where(['parent_id', $crop->id])->exists()){
return $this->error('该结点有关联产量数据, 无法删除');
}
$crop->delete();
return $this->success('删除成功');
}
}

View File

@ -26,18 +26,7 @@ class CropYieldController extends Controller
public function store(CropYieldRequest $request) public function store(CropYieldRequest $request)
{ {
$yields = $request->input('yields'); //-todo
CropYield::insert(array_map(function ($item) use ($request) {
return array_merge($item, [
'time_year' => $request->input('time_year'),
'crop_id' => $request->input('crop_id'),
'created_by' => auth('api')->user()?->id ?? 0,
'updated_by' => auth('api')->user()?->id ?? 0,
'created_at' => now(),
'updated_at' => now(),
]);
}, $yields));
return $this->success('添加成功'); return $this->success('添加成功');
} }
@ -50,10 +39,7 @@ class CropYieldController extends Controller
public function update(CropYield $cropYield, CropYieldUpdateRequest $request) public function update(CropYield $cropYield, CropYieldUpdateRequest $request)
{ {
$cropYield->update(array_merge($request->input(), //-todo
['updated_by' => auth('api')->user()?->id ?? 0]
));
return $this->success('修改成功'); return $this->success('修改成功');
} }

View File

@ -8,17 +8,17 @@ use Peidikeji\Keywords\Models\Keywords;
class KeywordController extends Controller class KeywordController extends Controller
{ {
/** // /**
* 农作物 // * 农作物
* // *
* @return void // * @return void
*/ // */
public function crops(Request $request) // public function crops(Request $request)
{ // {
$list = Keywords::filter($request->all())->where('type_key', 'like', 'crops-cate-%')->get(); // $list = Keywords::filter($request->all())->where('type_key', 'like', 'crops-cate-%')->get();
return $this->json(KeywordResource::collection($list)); // return $this->json(KeywordResource::collection($list));
} // }
/** /**
* 农作物产业分类 * 农作物产业分类
@ -27,18 +27,8 @@ class KeywordController extends Controller
*/ */
public function cropsCate(Request $request) public function cropsCate(Request $request)
{ {
$cropsId = $request->input('crops_id', 0);
$crops = null;
if ($cropsId) {
$crops = Keywords::find($cropsId);
}
$query = Keywords::filter($request->all())->where('type_key', 'crops-category'); $query = Keywords::filter($request->all())->where('type_key', 'crops-category');
if ($crops) {
$query->where('id', $crops->parent_id);
}
$list = $query->get(); $list = $query->get();
return $this->json(KeywordResource::collection($list)); return $this->json(KeywordResource::collection($list));

View File

@ -2,8 +2,10 @@
namespace App\Http\Requestes; namespace App\Http\Requestes;
use Illuminate\Contracts\Validation\Validator; use App\Enums\BaseType;
use Illuminate\Validation\Rules\Enum;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException; use Illuminate\Http\Exceptions\HttpResponseException;
class AgriculturalBaseRequest extends FormRequest class AgriculturalBaseRequest extends FormRequest
@ -16,9 +18,10 @@ class AgriculturalBaseRequest extends FormRequest
public function rules() public function rules()
{ {
return [ return [
'type' => ['required', new Enum(BaseType::class)],
'name' => 'required|string|max:100', 'name' => 'required|string|max:100',
'description' => 'nullable|string', 'description' => 'nullable|string',
'person' => 'required|string|max:100', 'person' => 'required_if:type,1|string|max:100',
'crops_ids' => 'required|array|min:1', 'crops_ids' => 'required|array|min:1',
'areas' => 'required|regex:/^\d+(\.\d{1,2})?$/', 'areas' => 'required|regex:/^\d+(\.\d{1,2})?$/',
'workforce' => 'required|integer|min:0', 'workforce' => 'required|integer|min:0',
@ -31,20 +34,19 @@ class AgriculturalBaseRequest extends FormRequest
public function messages() public function messages()
{ {
$messages = [ $messages = [
'name.required' => '请填写基地名称', 'type' => '请选择区域类别',
'name.max' => '基地名称不能超过100字', 'name.required' => '请填写名称',
'description.string' => '请正确填写基地介绍', 'name.max' => '名称不能超过100字',
'person.required' => '请填写基地负责人名称', 'description.string' => '请正确填写介绍',
'person.max' => '基地负责人名称不能超过100字', 'person.required_if' => '请填写负责人名称',
'person.max' => '负责人名称不能超过100字',
'crops_ids.required' => '请选择农作物', 'crops_ids.required' => '请选择农作物',
'crops_ids.min' => '至少选择一种农作物', 'crops_ids.min' => '至少选择一种农作物',
'areas.required' => '请填写基地面积', 'areas.required' => '请填写面积',
'areas.regex' => '请正确填写基地面积', 'areas.regex' => '请正确填写面积',
'workforce.required' => '请填写就业人数', 'workforce.required' => '请填写人数',
'workforce.min' => '就业人数最小为0', 'workforce.min' => '人数最小为0',
'address.string' => '请正确填写基地地址', 'address.string' => '请正确填写地址',
'address_lat.regex' => '请正确填写经度',
'address_lng.regex' => '请正确填写纬度',
]; ];
return $messages; return $messages;

View File

@ -0,0 +1,50 @@
<?php
namespace App\Http\Requestes;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
class CropRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'category_id' => 'required',
'parent_id' => 'nullable|integer',
'name' => 'required|string|max:100',
'is_end' => 'required|boolean',
'unit' => 'required|string|max:100',
'extends' => 'nullable|array',
'extends.*' => 'required_array_keys:name,unit',
'sort' => 'integer',
];
}
public function messages()
{
$messages = [
'category_id' => '请选择所属业',
'parent_id' => '请选择上级',
'name' => '请填写名称',
'is_end' => '请选择是否结点',
'unit' => '请填写单位',
'extends' => '请正确填写扩展字段',
'sort' => '请正确填写排序'
];
return $messages;
}
protected function failedValidation(Validator $validator)
{
$error = $validator->errors()->all();
throw new HttpResponseException(response()->json(['data' => [], 'code' => 400, 'message' => $error[0]]));
}
}

View File

@ -17,9 +17,12 @@ class CropYieldRequest extends FormRequest
{ {
return [ return [
'time_year' => 'required|date_format:Y', 'time_year' => 'required|date_format:Y',
'quarter' => 'required|integer|min:1|max:4',
'crop_id' => 'required|integer|min:0', 'crop_id' => 'required|integer|min:0',
'yields' => 'required|array|min:1', 'base_id' => 'required|integer|min:0',
'yields.*' => 'required_array_keys:base_id,yield,cultivated,output', 'yield' => 'required|integer|min:0',
'cultivated' => 'required|regex:/^\d+(\.\d{1,2})?$/',
'output' => 'required|regex:/^\d+(\.\d{1,2})?$/',
]; ];
} }
@ -27,9 +30,12 @@ class CropYieldRequest extends FormRequest
{ {
$messages = [ $messages = [
'time_year' => '请选择年份', 'time_year' => '请选择年份',
'quarter' => '请选择季度',
'crop_id' => '请选择农作物', 'crop_id' => '请选择农作物',
'yields' => '请填写基地以及产值信息', 'base_id' => '请选择地区',
'yields.*.required_array_keys' => '请填写完整基地以及产值信息', 'yield' => '请填写产量',
'cultivated' => '请填写种养殖面积',
'output' => '请填写产值',
]; ];
return $messages; return $messages;

View File

@ -25,7 +25,6 @@ class AgriculturalBaseResource extends JsonResource
'map' => $this->map ?? '', 'map' => $this->map ?? '',
'areas' => ($this->areas ?? 0.00).' 亩', 'areas' => ($this->areas ?? 0.00).' 亩',
'workforce' => $this->workforce ?? 0, 'workforce' => $this->workforce ?? 0,
'crops' => KeywordResource::collection($this->whenLoaded('crops')),
]; ];
} }
} }

View File

@ -0,0 +1,24 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class CropResource 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,
'parent_id' => $this->parent_id,
'name' => $this->name,
'is_end' => $this->is_end,
];
}
}

View File

@ -6,4 +6,7 @@ use EloquentFilter\ModelFilter;
class AgriculturalBaseFilter extends ModelFilter class AgriculturalBaseFilter extends ModelFilter
{ {
public function type($type){
return $this->where('type', $type);
}
} }

View File

@ -0,0 +1,28 @@
<?php
namespace App\ModelFilters;
use EloquentFilter\ModelFilter;
class CropFilter extends ModelFilter
{
public function categoryId($categoryId)
{
return $this->where('category_id', $categoryId);
}
public function type($type)
{
$q = $this;
switch ($type) {
case "top":
$q->whereNull('parent_id');
break;
case 'all':
break;
default:
break;
}
return $q;
}
}

View File

@ -2,6 +2,7 @@
namespace App\Models; namespace App\Models;
use App\Enums\BaseType;
use EloquentFilter\Filterable; use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Peidikeji\Keywords\Models\Keywords; use Peidikeji\Keywords\Models\Keywords;
@ -10,11 +11,24 @@ class AgriculturalBase extends Model
{ {
use Filterable; use Filterable;
protected $casts = [
'type' => BaseType::class,
];
protected $fillable = [ protected $fillable = [
'type',
'name', 'person', 'address', 'address_lat', 'address_lng', 'name', 'person', 'address', 'address_lat', 'address_lng',
'description', 'map', 'areas', 'workforce', 'description', 'map', 'areas', 'workforce',
]; ];
public function scopeBase($q){
return $q->where('type', BaseType::Base);
}
public function scopeTown($q){
return $q->where('type', BaseType::Town);
}
public function scopeSort($q) public function scopeSort($q)
{ {
return $q->orderBy('created_at', 'desc'); return $q->orderBy('created_at', 'desc');

View File

@ -0,0 +1,23 @@
<?php
namespace App\Models;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
class Crop extends Model
{
use Filterable;
public function scopeSort($q){
return $q->orderBy('sort', 'desc')->orderBy('created_at', 'desc');
}
protected $fillable = [
'category_id',
'name', 'parent_id',
'path', 'is_end',
'sort',
'extends'
];
}

View File

@ -22,7 +22,7 @@ class CropFlow extends Model
*/ */
public function crop() public function crop()
{ {
return $this->belongsTo(Keywords::class, 'crop_id'); return $this->belongsTo(Crop::class, 'crop_id');
} }
public function createdBy() public function createdBy()

View File

@ -32,7 +32,7 @@ class CropYield extends Model
*/ */
public function crop() public function crop()
{ {
return $this->belongsTo(Keywords::class, 'crop_id'); return $this->belongsTo(Crop::class, 'crop_id');
} }
public function createdBy() public function createdBy()

View File

@ -15,27 +15,28 @@ return new class extends Migration
{ {
Schema::create('agricultural_bases', function (Blueprint $table) { Schema::create('agricultural_bases', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('name')->comment('基地名称'); $table->string('name')->comment('名称');
$table->string('person')->comment('基地负责人'); $table->unsignedTinyInteger('type')->default(1)->comment('类别1基地2城镇');
$table->string('address')->nullable()->comment('基地地址'); $table->string('person')->nullable()->comment('负责人');
$table->string('address')->nullable()->comment('地址');
$table->string('address_lat')->nullable()->comment('地址经度'); $table->string('address_lat')->nullable()->comment('地址经度');
$table->string('address_lng')->nullable()->comment('地址维度'); $table->string('address_lng')->nullable()->comment('地址维度');
$table->text('description')->nullable()->comment('基地描述'); $table->text('description')->nullable()->comment('基地描述');
$table->string('map')->nullable()->comment('基地地图'); $table->string('map')->nullable()->comment('基地地图');
$table->decimal('areas', 12, 2)->nullable()->comment('基地面积'); $table->decimal('areas', 12, 2)->nullable()->comment('基地面积');
$table->unsignedInteger('workforce')->nullable()->comment('职工数量'); $table->unsignedInteger('workforce')->nullable()->comment('人员数量');
$table->timestamps(); $table->timestamps();
$table->comment('地数据表'); $table->comment('数据表');
}); });
Schema::create('base_crops', function (Blueprint $table) { Schema::create('base_crops', function (Blueprint $table) {
$table->id(); $table->id();
$table->unsignedBigInteger('base_id')->comment('地ID'); $table->unsignedBigInteger('base_id')->comment('ID');
$table->unsignedBigInteger('crop_id')->comment('农作物ID'); $table->unsignedBigInteger('crop_id')->comment('农作物ID');
$table->comment('地农作物表'); $table->comment('农作物表');
}); });
} }

View File

@ -15,12 +15,14 @@ return new class extends Migration
{ {
Schema::create('crop_yields', function (Blueprint $table) { Schema::create('crop_yields', function (Blueprint $table) {
$table->id(); $table->id();
$table->unsignedBigInteger('base_id')->comment('地ID'); $table->unsignedBigInteger('base_id')->comment('ID');
$table->unsignedBigInteger('crop_id')->comment('农产品ID'); $table->unsignedBigInteger('crop_id')->comment('农产品ID');
$table->unsignedInteger('time_year')->comment('年份'); $table->unsignedInteger('time_year')->comment('年份');
$table->unsignedDecimal('yield', 12, 2)->comment('产量(斤)'); $table->unsignedInteger('quarter')->nullable()->comment('季度');
$table->unsignedDecimal('yield', 12, 2)->comment('产量');
$table->unsignedDecimal('cultivated', 12, 2)->comment('耕地面积(亩)'); $table->unsignedDecimal('cultivated', 12, 2)->comment('耕地面积(亩)');
$table->unsignedDecimal('output', 12, 2)->comment('产值(元)'); $table->unsignedDecimal('output', 12, 2)->comment('产值(元)');
$table->text('extends')->nullable()->comment('扩展数据');
$table->unsignedBigInteger('created_by')->comment('创建人ID'); $table->unsignedBigInteger('created_by')->comment('创建人ID');
$table->unsignedBigInteger('updated_by')->comment('修改人ID'); $table->unsignedBigInteger('updated_by')->comment('修改人ID');
$table->timestamps(); $table->timestamps();

View File

@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('crops', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('category_id')->comment('行业ID');
$table->unsignedBigInteger('parent_id')->nullable()->comment('父级ID');
$table->string('name')->comment('名称');
$table->string('path')->nullable()->comment('路径');
$table->unsignedTinyInteger('is_end')->default(0)->comment('是否结点');
$table->string('unit')->nullable()->comment('单位');
$table->unsignedInteger('sort')->default(0)->comment('排序');
$table->text('extends')->nullable()->comment('扩展字段');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('crop_cates');
}
};

View File

@ -28,6 +28,9 @@ Route::group(['middleware' => 'auth:sanctum'], function () {
Route::get('citydata-statistics', [CityDataController::class, 'statistics'])->name('citydata_statistics.index'); Route::get('citydata-statistics', [CityDataController::class, 'statistics'])->name('citydata_statistics.index');
//基地数据 //基地数据
Route::apiResource('agricultural-basic', AgriculturalBaseController::class)->names('agricultural_basic'); Route::apiResource('agricultural-basic', AgriculturalBaseController::class)->names('agricultural_basic');
//农作物
Route::apiResource('crops', CropController::class)->names('crops');
//农业结构 //农业结构
Route::apiResource('crop-structures', CropStructureController::class)->names('crops_build'); Route::apiResource('crop-structures', CropStructureController::class)->names('crops_build');
//产量 //产量