diff --git a/app/Admin/Controllers/ArticleController.php b/app/Admin/Controllers/ArticleController.php index a33e904..277d0f3 100644 --- a/app/Admin/Controllers/ArticleController.php +++ b/app/Admin/Controllers/ArticleController.php @@ -29,7 +29,7 @@ class ArticleController extends AdminController ->columns([ amisMake()->TableColumn()->name('id')->label(__('article.id'))->sortable(true), amisMake()->TableColumn()->name('title')->label(__('article.title')), - amisMake()->TableColumn()->name('category.name')->label(__('article.category_id'))->className('text-primary'), + amisMake()->TableColumn()->name('category.name')->label(__('article.category_id')), amisMake()->Image()->name('cover')->label(__('article.cover'))->width(100), amisMake()->TableColumn()->name('sort')->label(__('article.sort'))->align('center')->quickEdit(Components::make()->sortControl('sort', __('article.sort'))->saveImmediately(true)), Components::make()->switchControl('table')->name('is_enable')->label(__('article.is_enable')), diff --git a/app/Admin/Controllers/PartyCateController.php b/app/Admin/Controllers/PartyCateController.php new file mode 100644 index 0000000..ed390b8 --- /dev/null +++ b/app/Admin/Controllers/PartyCateController.php @@ -0,0 +1,82 @@ +baseCRUD() + ->filterTogglable(false) + ->columnsTogglable(false) + ->headerToolbar([ + $this->createButton(true), + ]) + ->filter($this->baseFilter()->actions([])->body([ + amisMake()->TextControl()->name('name')->label(__('party_cate.name'))->size('md')->clearable(), + amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'), + ])) + ->columns([ + amisMake()->TableColumn()->name('id')->label(__('party_cate.id')), + amisMake()->TableColumn()->name('name')->label(__('party_cate.name')), + amisMake()->TableColumn()->name('master.name')->label(__('party_cate.master_id')), + amisMake()->TableColumn()->name('plan.name')->label(__('party_cate.plan_id')), + amisMake()->TableColumn()->name('score')->label(__('party_cate.score')), + amisMake()->TableColumn()->name('remarks')->label(__('party_cate.remarks')), + $this->rowActions([ + $this->rowShowButton(), + $this->rowEditButton(true), + $this->rowDeleteButton(), + ]), + ]); + + return $this->baseList($crud); + } + + public function form(): Form + { + return $this->baseForm()->title('')->body([ + amisMake()->TextControl()->name('name')->label(__('party_cate.name'))->required(), + amisMake()->SelectControl()->name('master_id')->label(__('party_cate.master_id'))->options($this->getUserOptions()), + amisMake()->SelectControl()->name('plan_id')->label(__('party_cate.plan_id'))->options($this->getUserOptions()), + amisMake()->TextControl()->name('remarks')->label(__('party_cate.remarks')), + ]); + } + + public function detail(): Form + { + return $this->baseDetail()->title('')->body([ + amisMake()->TextControl()->name('id')->label(__('party_cate.id'))->static(), + amisMake()->TextControl()->name('name')->label(__('party_cate.name'))->static(), + amisMake()->TextControl()->name('master.name')->label(__('party_cate.master_id'))->static(), + amisMake()->TextControl()->name('plan.name')->label(__('party_cate.plan_id'))->static(), + amisMake()->TextControl()->name('remarks')->label(__('party_cate.remarks'))->static(), + amisMake()->TextControl()->name('score')->label(__('party_cate.score'))->static(), + amisMake()->TextControl()->name('scores')->label(__('party_cate.scores'))->static()->staticSchema(amisMake()->Json()), + amisMake()->TextControl()->name('created_at')->label(__('party_cate.created_at'))->static(), + ]); + } + + public function getUserOptions() + { + if (!$this->userOptions) { + $this->userOptions = PartyUser::select(['id as value', 'name as label'])->get(); + } + + return $this->userOptions; + } +} diff --git a/app/Admin/Controllers/PartyUserController.php b/app/Admin/Controllers/PartyUserController.php new file mode 100644 index 0000000..d33829d --- /dev/null +++ b/app/Admin/Controllers/PartyUserController.php @@ -0,0 +1,84 @@ +baseCRUD() + ->filterTogglable(false) + ->columnsTogglable(false) + ->headerToolbar([ + $this->createButton(true), + ]) + ->filter($this->baseFilter()->actions([])->body([ + amisMake()->TextControl()->name('name')->label(__('party_user.name'))->size('md')->clearable(), + amisMake()->SelectControl()->name('cate_id')->label(__('party_user.cate_id'))->options($this->getCateOptions())->size('md')->clearable(), + amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'), + ])) + ->columns([ + amisMake()->TableColumn()->name('id')->label(__('party_user.id')), + amisMake()->TableColumn()->name('name')->label(__('party_user.name')), + amisMake()->TableColumn()->type('avatar')->src('${avatar}')->name('avatar')->label(__('party_user.avatar')), + amisMake()->TableColumn()->name('cate.name')->label(__('party_user.cate_id')), + amisMake()->TableColumn()->name('score')->label(__('party_user.score')), + $this->rowActions([ + $this->rowShowButton(), + $this->rowEditButton(true), + $this->rowDeleteButton(), + ]), + ]); + + return $this->baseList($crud); + } + + public function form($edit): Form + { + return $this->baseForm()->title('')->body([ + amisMake()->SelectControl()->name('cate_id')->label(__('party_user.cate_id'))->options($this->getCateOptions()), + amisMake()->TextControl()->name('name')->label(__('party_user.name'))->required(), + amisMake()->ImageControl()->name('avatar')->label(__('party_user.avatar')), + amisMake()->TextControl()->name('username')->label(__('party_user.username'))->required(), + amisMake()->TextControl()->set('type', 'input-password')->name('password')->label(__('party_user.password'))->required(!$edit), + amisMake()->TextControl()->name('remarks')->label(__('party_cate.remarks')), + ]); + } + + public function detail(): Form + { + return $this->baseDetail()->title('')->body([ + amisMake()->TextControl()->name('id')->label(__('party_user.id'))->static(), + amisMake()->TextControl()->name('username')->label(__('party_user.username'))->static(), + amisMake()->TextControl()->name('name')->label(__('party_user.name'))->static(), + amisMake()->TextControl()->name('avatar')->label(__('party_user.avatar'))->static()->staticSchema(amisMake()->Image()), + amisMake()->TextControl()->name('cate.name')->label(__('party_user.cate_id'))->static(), + amisMake()->TextControl()->name('score')->label(__('party_cate.score'))->static(), + amisMake()->TextControl()->name('scores')->label(__('party_cate.scores'))->static()->staticSchema(amisMake()->Json()), + amisMake()->TextControl()->name('remarks')->label(__('party_cate.remarks'))->static(), + amisMake()->TextControl()->name('created_at')->label(__('party_user.created_at'))->static(), + ]); + } + + public function getCateOptions() + { + if (!$this->cateOptions) { + $this->cateOptions = PartyCate::select(['id as value', 'name as label'])->get(); + } + + return $this->cateOptions; + } +} diff --git a/app/Admin/Controllers/UserScoreController.php b/app/Admin/Controllers/UserScoreController.php new file mode 100644 index 0000000..2ef4312 --- /dev/null +++ b/app/Admin/Controllers/UserScoreController.php @@ -0,0 +1,156 @@ +baseCRUD() + ->filterTogglable(false) + ->columnsTogglable(false) + ->headerToolbar([ + $this->createButton(true), + ]) + ->filter($this->baseFilter()->actions([])->body([ + amisMake()->SelectControl()->name('type_id')->label(__('user_score.type_id'))->options($this->getTypeOptions())->clearable()->size('md'), + amisMake()->SelectControl()->name('user_id')->label(__('user_score.user_id'))->options($this->getUserOptions())->clearable()->size('md'), + amisMake()->TextControl()->name('title')->label(__('user_score.title'))->clearable()->size('md'), + amisMake()->SelectControl()->name('check_status')->label(__('user_score.check_status'))->options(CheckStatus::options())->clearable()->size('md'), + amisMake()->Component()->setType('submit')->label(__('admin.search'))->level('primary'), + ])) + ->columns([ + amisMake()->TableColumn()->name('id')->label(__('user_score.id')), + amisMake()->TableColumn()->name('type_id')->label(__('user_score.type_id')), + amisMake()->TableColumn()->name('user.name')->label(__('user_score.user_id')), + amisMake()->TableColumn()->name('title')->label(__('user_score.title')), + amisMake()->TableColumn()->name('check_status_text')->label(__('user_score.check_status')), + amisMake()->TableColumn()->name('score')->label(__('user_score.score')), + amisMake()->TableColumn()->name('created_at')->label(__('user_score.created_at')), + $this->rowActions([ + $this->rowShowButton(), + $this->rowEditButton(true), + $this->rowDeleteButton(), + ]), + ]); + + return $this->baseList($crud); + } + + public function form($edit): Form + { + return $this->baseForm()->title('')->body([ + amisMake()->SelectControl()->name('type_id')->label(__('user_score.type_id'))->options($this->getTypeOptions())->required(), + amisMake()->SelectControl()->name('user_id')->label(__('user_score.user_id'))->options($this->getUserOptions())->required(), + amisMake()->TextControl()->name('title')->label(__('user_score.title'))->required(), + amisMake()->TextareaControl()->name('content')->label(__('user_score.content')), + amisMake()->ImageControl()->name('images')->label(__('user_score.images'))->multiple()->receiver(admin_url('upload_image') . '?full-url=1')->autoUpload(), + amisMake()->FileControl()->name('file')->label(__('user_score.file'))->autoUpload() + ]); + } + + public function show($id) + { + if ($this->actionOfGetData()) { + return $this->response()->success($this->service->getDetail($id)); + } + $info = UserScore::findOrFail($id); + $detail = amisMake() + ->Card() + ->className('base-form') + ->header(['title' => __('admin.detail')]) + ->body($this->detail()) + ->toolbar([ + amisMake()->Button() + ->visible($info->check_status != CheckStatus::Success) + ->label('审核') + ->level('danger') + ->className('mr-1') + ->actionType('dialog') + ->dialog(amisMake()->Dialog()->title('审核')->body(amisMake()->Form()->api("/user-score/$id/check")->body([ + amisMake()->RadiosControl()->name('check_status')->label(__('user_score.check_status'))->options([ + CheckStatus::Success->value => CheckStatus::Success->text(), + CheckStatus::Fail->value => CheckStatus::Fail->text(), + ])->value(CheckStatus::Success->value)->required(), + amisMake()->NumberControl()->name('score')->label(__('user_score.score')), + amisMake()->TextControl()->name('check_remarks')->label(__('user_score.check_remarks')), + ])->onEvent([ + 'submitSucc' => [ + 'actions' => [ + ['actionType' => 'custom', 'script' => 'window.$owl.refreshAmisPage()',] + ] + ] + ]))), + $this->backButton(), + ]); + + $page = $this->basePage()->body($detail); + + return $this->response()->success($page); + } + + public function detail(): Form + { + return $this->baseDetail()->title('')->body([ + amisMake()->TextControl()->name('id')->label(__('user_score.id'))->static(), + amisMake()->TextControl()->name('type.name')->label(__('user_score.type_id'))->static(), + amisMake()->TextControl()->name('user.name')->label(__('user_score.user_id'))->static(), + amisMake()->TextControl()->name('title')->label(__('user_score.title'))->static(), + amisMake()->TextareaControl()->name('content')->label(__('user_score.content'))->static(), + amisMake()->TextControl()->name('images')->label(__('user_score.images'))->static()->staticSchema(amisMake()->Images()), + amisMake()->TextControl()->name('file')->label(__('user_score.file'))->static()->staticSchema(amisMake()->Link()->blank()), + amisMake()->TextControl()->name('check_status_text')->label(__('user_score.check_status'))->static(), + amisMake()->TextControl()->name('check_user.name')->label(__('user_score.check_user_id'))->static(), + amisMake()->TextControl()->name('check_remarks')->label(__('user_score.check_remarks'))->static(), + amisMake()->TextControl()->name('check_at')->label(__('user_score.check_at'))->static(), + amisMake()->TextControl()->name('score')->label(__('user_score.score'))->static(), + amisMake()->TextControl()->name('created_at')->label(__('user_score.created_at'))->static(), + ]); + } + + public function check($id, Request $request) + { + $info = UserScore::findOrFail($id); + try { + $this->service->check($info, $request->all()); + return $this->response()->success(); + } catch (BaseException $e) { + return $this->response()->fail($e->getMessage()); + } + } + + public function getTypeOptions() + { + if (!$this->typeOptions) { + $this->typeOptions = UserScore::getTypeList()->map(fn($item) => ['value' => $item->id, 'label' => $item->name]); + } + + return $this->typeOptions; + } + + public function getUserOptions() + { + if (!$this->userOptions) { + $this->userOptions = PartyUser::select(['id as value', 'name as label'])->get(); + } + + return $this->userOptions; + } +} diff --git a/app/Admin/Services/ArticleService.php b/app/Admin/Services/ArticleService.php index 1a9623e..51a70d5 100644 --- a/app/Admin/Services/ArticleService.php +++ b/app/Admin/Services/ArticleService.php @@ -32,7 +32,7 @@ class ArticleService extends BaseService return $query->sort(); } - public function resloveData($data) + public function resloveData($data, $model = null) { $cid = data_get($data, 'category_id'); if ($cid && $category = Keyword::find($cid)) { @@ -48,6 +48,7 @@ class ArticleService extends BaseService public function validate($data, $model = null) { $createRules = [ + 'title' => 'required', ]; $updateRules = [ ]; diff --git a/app/Admin/Services/BaseService.php b/app/Admin/Services/BaseService.php index 760fe42..56ff18f 100644 --- a/app/Admin/Services/BaseService.php +++ b/app/Admin/Services/BaseService.php @@ -19,7 +19,7 @@ class BaseService extends AdminService public function getTree() { - $list = $this->query()->orderByDesc('sort')->get()->toArray(); + $list = $this->query()->get()->toArray(); return array2tree($list); } @@ -79,8 +79,8 @@ class BaseService extends AdminService public function update($primaryKey, $data): bool { - $data = $this->resloveData($data); $model = $this->query()->whereKey($primaryKey)->firstOrFail(); + $data = $this->resloveData($data, $model); $validate = $this->validate($data, $model); if ($validate !== true) { $this->setError($validate); @@ -105,9 +105,10 @@ class BaseService extends AdminService * 处理表单数据 * * @param array $data + * @param Model $model 空 : 添加, 非空: 修改 * @return array */ - public function resloveData($data) + public function resloveData($data, $model = null) { return $data; } @@ -121,6 +122,19 @@ class BaseService extends AdminService */ public function validate($data, $model = null) { + // $createRules = [ + // 'key' => ['required', Rule::unique('keywords', 'key')], + // 'name' => ['required'], + // ]; + // $updateRules = [ + // 'key' => [Rule::unique('keywords', 'key')->ignore($model->id)] + // ]; + // $validator = Validator::make($data, $model ? $updateRules : $createRules, [ + // 'key.unique' => ':input 已经存在' + // ]); + // if ($validator->fails()) { + // return $validator->errors()->first(); + // } return true; } diff --git a/app/Admin/Services/KeywordService.php b/app/Admin/Services/KeywordService.php index ecd2b23..bc75736 100644 --- a/app/Admin/Services/KeywordService.php +++ b/app/Admin/Services/KeywordService.php @@ -56,7 +56,7 @@ class KeywordService extends BaseService 'name' => ['required'], ]; $updateRules = [ - 'key' => [Rule::unique('keywords', 'key')->ignore($model->id)] + 'key' => [Rule::unique('keywords', 'key')->ignore($model?->id)] ]; $validator = Validator::make($data, $model ? $updateRules : $createRules, [ 'key.unique' => ':input 已经存在' @@ -67,7 +67,7 @@ class KeywordService extends BaseService return true; } - public function resloveData($data) + public function resloveData($data, $model = null) { $parent_id = data_get($data, 'parent_id'); if (!is_null($parent_id)) { diff --git a/app/Admin/Services/PartyCateService.php b/app/Admin/Services/PartyCateService.php new file mode 100644 index 0000000..eaf9632 --- /dev/null +++ b/app/Admin/Services/PartyCateService.php @@ -0,0 +1,53 @@ +pluck('id'); + // 删除支部下面的党员记录 + PartyUser::whereIn('cate_id', $ids)->delete(); + // 删除党员下面的审核记录 + UserScore::whereIn('user_id', $userIds)->delete(); + return true; + } + + public function resloveData($data, $model = null) + { + if (!$model) { + $list = UserScore::getTypeList(); + $scores = []; + foreach ($list as $item) { + $scores[$item->key] = 0; + } + $data['scores'] = $scores; + } + return $data; + } + + public function incrementScore(PartyCate $info, $type, $score) + { + $scores = $info->scores; + if (isset($scores[$type])) { + $scores[$type] += $score; + } + $info->update([ + 'score' => $info->score + $score, + 'scores' => $scores, + ]); + } +} diff --git a/app/Admin/Services/PartyUserService.php b/app/Admin/Services/PartyUserService.php new file mode 100644 index 0000000..deea48a --- /dev/null +++ b/app/Admin/Services/PartyUserService.php @@ -0,0 +1,70 @@ + ['required', Rule::unique('party_users', 'username')], + 'password' => ['required'], + 'name' => ['required'], + ]; + $updateRules = [ + 'username' => [Rule::unique('party_users', 'username')->ignore($model?->id)] + ]; + $validator = Validator::make($data, $model ? $updateRules : $createRules, [ + 'username.required' => __('party_user.username') . '必填', + 'password.required' => __('party_user.password') . '必填', + 'name.required' => __('party_user.name') . '必填', + 'username.unique' => ':input 已经存在', + ]); + if ($validator->fails()) { + return $validator->errors()->first(); + } + return true; + } + + public function resloveData($data, $model = null) + { + if (!$model) { + $list = UserScore::getTypeList(); + $scores = []; + foreach ($list as $item) { + $scores[$item->key] = 0; + } + $data['scores'] = $scores; + } + return $data; + } + + public function incrementScore(PartyUser $user, $type, $score) + { + $scores = $user->scores; + if (isset($scores[$type])) { + $scores[$type] += $score; + } + $user->update([ + 'score' => $user->score + $score, + 'scores' => $scores, + ]); + + if ($user->cate) { + PartyCateService::make()->incrementScore($user->cate, $type, $score); + } + } +} diff --git a/app/Admin/Services/UserScoreService.php b/app/Admin/Services/UserScoreService.php new file mode 100644 index 0000000..f534ed9 --- /dev/null +++ b/app/Admin/Services/UserScoreService.php @@ -0,0 +1,42 @@ +check_status == CheckStatus::Success) { + throw new BaseException('已经审核过了'); + } + $status = data_get($options, 'check_status'); + $attributes = [ + 'check_status' => $status, + 'check_remarks' => data_get($options, 'check_remarks'), + 'check_user_id' => data_get($options, 'check_user_id', Admin::user()->id), + 'check_at' => now(), + ]; + if ($status == CheckStatus::Success->value) { + $attributes['score'] = data_get($options, 'score', 0); + if ($attributes['score'] <= 0) { + throw new BaseException('得分必填'); + } + + PartyUserService::make()->incrementScore($info->user, $info->type?->key, $attributes['score']); + } + + $info->update($attributes); + } +} diff --git a/app/Admin/routes.php b/app/Admin/routes.php index 9ae2794..a3456f5 100644 --- a/app/Admin/routes.php +++ b/app/Admin/routes.php @@ -29,6 +29,15 @@ Route::group([ // 字典表 $router->resource('keywords', \App\Admin\Controllers\KeywordsController::class)->names('admin.keywords'); - $router->resource('articles', \App\Admin\Controllers\ArticleController::class); + // 文章 + $router->resource('articles', \App\Admin\Controllers\ArticleController::class)->names('admin.article'); $router->post('quick-edit/article/{article}', [\App\Admin\Controllers\ArticleController::class, 'update']); + + // 党支部 + $router->resource('party-cate', \App\Admin\Controllers\PartyCateController::class)->names('admin.party_cate'); + // 党员 + $router->resource('party-user', \App\Admin\Controllers\PartyUserController::class)->names('admin.party_user'); + // 评议审核 + $router->post('user-score/{id}/check', [\App\Admin\Controllers\UserScoreController::class, 'check']); + $router->resource('user-score', \App\Admin\Controllers\UserScoreController::class)->names('admin.user_score'); }); diff --git a/app/Enums/CheckStatus.php b/app/Enums/CheckStatus.php new file mode 100644 index 0000000..da6b270 --- /dev/null +++ b/app/Enums/CheckStatus.php @@ -0,0 +1,33 @@ +value => '待审核', + self::Success->value => '通过', + self::Fail->value => '不通过', + ]; + } + + public static function options() + { + $list = []; + foreach (static::map() as $key => $value) { + array_push($list, ['label' => $value, 'value' => $key]); + } + return $list; + } + + public function text() + { + return data_get(self::map(), $this->value); + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 77ec359..ba86f94 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -5,8 +5,14 @@ namespace App\Http\Controllers; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; +use Slowlyo\OwlAdmin\Admin; class Controller extends BaseController { use AuthorizesRequests, ValidatesRequests; + + protected function response() + { + return Admin::response(); + } } diff --git a/app/Http/Controllers/WebController.php b/app/Http/Controllers/WebController.php new file mode 100644 index 0000000..3e1ca42 --- /dev/null +++ b/app/Http/Controllers/WebController.php @@ -0,0 +1,63 @@ +input('path', 'uploads').'/'.date('Y-m-d'); + $result = []; + + $disk = $this->getDisk(); + + // file 文件 + $files = $request->except('path'); + foreach ($files as $key => $fileData) { + $item = null; + if (is_array($fileData)) { + foreach ($fileData as $file) { + $item[] = $disk->url($this->saveFile($disk, $path, $file)); + } + } else { + $item = $disk->url($this->saveFile($disk, $path, $fileData)); + } + $result[$key] = $item; + } + + return $this->response()->success($result); + } + + protected function saveFile($disk, $path, $file = null) + { + $filePath = ''; + if ($file instanceof UploadedFile) { + //限制文件类型: + if(in_array($file->getClientOriginalExtension(), [ + 'jpeg', 'jpg', 'gif', 'bmp', 'png', //图片 + 'mp4', //视频 + 'mp3', //音频 + ])){ + $filePath = $disk->putFile($path, $file); + } + } elseif (preg_match('/^(data:\s*image\/(\w+);base64,)/', $file, $result)) { + $type = $result[2]; + if (in_array($type, ['jpeg', 'jpg', 'gif', 'bmp', 'png'])) { + $filePath = $path.'/'.uniqid().'.'.$type; + $disk->put($filePath, base64_decode(str_replace($result[1], '', $file))); + } + } + + return $filePath; + } + + protected function getDisk($disk = null): Filesystem + { + return Storage::disk($disk); + } +} diff --git a/app/ModelFilters/PartyCateFilter.php b/app/ModelFilters/PartyCateFilter.php new file mode 100644 index 0000000..be23e96 --- /dev/null +++ b/app/ModelFilters/PartyCateFilter.php @@ -0,0 +1,21 @@ + [input_key1, input_key2]]. + * + * @var array + */ + public $relations = []; + + public function name($name) + { + $this->whereLike('name', $name); + } +} diff --git a/app/ModelFilters/PartyUserFilter.php b/app/ModelFilters/PartyUserFilter.php new file mode 100644 index 0000000..aa4ad2a --- /dev/null +++ b/app/ModelFilters/PartyUserFilter.php @@ -0,0 +1,26 @@ + [input_key1, input_key2]]. + * + * @var array + */ + public $relations = []; + + public function name($name) + { + $this->whereLike('name', $name); + } + + public function cate($id) + { + $this->where('cate_id', $id); + } +} diff --git a/app/ModelFilters/UserScoreFilter.php b/app/ModelFilters/UserScoreFilter.php new file mode 100644 index 0000000..4f66f36 --- /dev/null +++ b/app/ModelFilters/UserScoreFilter.php @@ -0,0 +1,36 @@ + [input_key1, input_key2]]. + * + * @var array + */ + public $relations = []; + + public function user($id) + { + $this->where('user_id', $id); + } + + public function type($id) + { + $this->where('type_id', $id); + } + + public function checkStatus($id) + { + $this->where('check_status', $id); + } + + public function title($key) + { + $this->whereLike('title', $key); + } +} diff --git a/app/Models/PartyCate.php b/app/Models/PartyCate.php new file mode 100644 index 0000000..b7de7b5 --- /dev/null +++ b/app/Models/PartyCate.php @@ -0,0 +1,36 @@ + 'array' + ]; + + public function master() + { + return $this->belongsTo(PartyUser::class, 'master_id'); + } + + public function plan() + { + return $this->belongsTo(PartyUser::class, 'plan_id'); + } + + public function users() + { + return $this->hasMany(PartyUser::class, 'cate_id'); + } +} diff --git a/app/Models/PartyUser.php b/app/Models/PartyUser.php new file mode 100644 index 0000000..0cddcfb --- /dev/null +++ b/app/Models/PartyUser.php @@ -0,0 +1,32 @@ + 'encrypted', + 'avatar' => StorageFile::class, + 'scores' => 'array', + ]; + + public function cate() + { + return $this->belongsTo(PartyCate::class, 'cate_id'); + } +} diff --git a/app/Models/UserScore.php b/app/Models/UserScore.php new file mode 100644 index 0000000..4c99a6a --- /dev/null +++ b/app/Models/UserScore.php @@ -0,0 +1,66 @@ + 'array', + 'file' => StorageFile::class, + 'check_status' => CheckStatus::class, + 'check_at' => 'datetime', + ]; + + protected $attributes = [ + 'check_status' => CheckStatus::None, + ]; + + protected $appends = ['check_status_text']; + + public static function getTypeList() + { + return Keyword::where('key', 'like', 'score_cate_%')->get(); + } + + public function type() + { + return $this->belongsTo(Keyword::class, 'type_id'); + } + + public function user() + { + return $this->belongsTo(PartyUser::class, 'user_id'); + } + + public function checkUser() + { + return $this->belongsTo(AdminUser::class, 'check_user_id'); + } + + protected function checkStatusText(): Attribute + { + return new Attribute( + get: fn () => $this->check_status ? $this->check_status->text() : '', + ); + } + + public function scopeSort($q) + { + return $this->orderBy('check_status')->latest('id'); + } +} diff --git a/config/admin.php b/config/admin.php index 401379d..f0a5fae 100644 --- a/config/admin.php +++ b/config/admin.php @@ -31,7 +31,7 @@ return [ // 是否开启验证码 'login_captcha' => env('ADMIN_LOGIN_CAPTCHA', true), // 是否开启鉴权 - 'enable' => false, + 'enable' => true, // 用户模型 'model' => \Slowlyo\OwlAdmin\Models\AdminUser::class, 'controller' => \Slowlyo\OwlAdmin\Controllers\AuthController::class, diff --git a/config/auth.php b/config/auth.php index 9548c15..518dcc5 100644 --- a/config/auth.php +++ b/config/auth.php @@ -40,6 +40,10 @@ return [ 'driver' => 'session', 'provider' => 'users', ], + 'api' => [ + 'driver' => 'sanctum', + 'provider' => 'party' + ] ], /* @@ -64,6 +68,10 @@ return [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], + 'party' => [ + 'driver' => 'eloquent', + 'model' => App\Models\PartyUser::class, + ] // 'users' => [ // 'driver' => 'database', diff --git a/database/migrations/2023_12_01_122729_create_party_users_table.php b/database/migrations/2023_12_01_122729_create_party_users_table.php new file mode 100644 index 0000000..c843cb1 --- /dev/null +++ b/database/migrations/2023_12_01_122729_create_party_users_table.php @@ -0,0 +1,46 @@ +id(); + $table->string('name')->comment('党支部名称'); + $table->unsignedBigInteger('master_id')->nullable()->comment('党支部书记'); + $table->unsignedBigInteger('plan_id')->nullable()->comment('组织委员'); + $table->string('remarks')->nullable()->comment('备注'); + $table->timestamps(); + + $table->comment('党支部'); + }); + Schema::create('party_users', function (Blueprint $table) { + $table->id(); + $table->string('username')->unique()->comment('登录账户'); + $table->string('password')->comment('登录密码'); + $table->string('name')->comment('姓名'); + $table->string('avatar')->nullable()->comment('头像'); + $table->unsignedBigInteger('cate_id')->nullable()->comment('党支部id'); + $table->string('remarks')->nullable()->comment('备注'); + $table->timestamps(); + + $table->comment('党员'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('party_cates'); + Schema::dropIfExists('party_users'); + } +}; diff --git a/database/migrations/2023_12_01_140938_create_user_scores_table.php b/database/migrations/2023_12_01_140938_create_user_scores_table.php new file mode 100644 index 0000000..a8bf5e2 --- /dev/null +++ b/database/migrations/2023_12_01_140938_create_user_scores_table.php @@ -0,0 +1,55 @@ +id(); + $table->unsignedBigInteger('type_id')->comment('类别, keywords.id, score_cate'); + $table->unsignedBigInteger('user_id')->comment('提交人, party_user.id'); + $table->string('title')->nullable()->comment('主题'); + $table->text('content')->nullable()->comment('内容'); + $table->json('images')->nullable()->comment('图片'); + $table->string('file')->nullable()->comment('附件'); + + $table->unsignedTinyInteger('check_status')->default(0)->comment('审核状态(0: 待审核, 1: 审核通过, 2: 审核不通过)'); + $table->unsignedBigInteger('check_user_id')->nullable()->comment('审核人'); + $table->timestamp('check_at')->nullable()->comment('审核时间'); + $table->string('check_remarks')->nullable()->comment('审核备注'); + $table->unsignedInteger('score')->default(0)->comment('得分'); + $table->timestamps(); + }); + + Schema::table('party_users', function (Blueprint $table) { + $table->unsignedInteger('score')->default(0)->comment('累计得分'); + $table->json('scores')->nullable()->comment('每项得分{score_cate_1: 10}'); + }); + + Schema::table('party_cates', function (Blueprint $table) { + $table->unsignedInteger('score')->default(0)->comment('累计得分'); + $table->json('scores')->nullable()->comment('每项得分{score_cate_1: 10}'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('user_scores'); + Schema::table('party_users', function (Blueprint $table) { + $table->dropColumn(['score', 'scores']); + }); + Schema::table('party_cates', function (Blueprint $table) { + $table->dropColumn(['score', 'scores']); + }); + } +}; diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php index f15d344..847a093 100644 --- a/database/seeders/AdminMenuSeeder.php +++ b/database/seeders/AdminMenuSeeder.php @@ -19,6 +19,9 @@ class AdminMenuSeeder extends Seeder // 图标: https://iconpark.oceanengine.com/official $menus = [ ['title' => '主页', 'icon' => 'icon-park:home-two', 'url' => '/dashboard', 'is_home' => 1], + ['title' => '支部管理', 'icon' => 'icon-park:flag', 'url' => '/party-cate'], + ['title' => '党员管理', 'icon' => 'icon-park:every-user', 'url' => '/party-user'], + ['title' => '审核评定', 'icon' => 'icon-park:internal-data', 'url' => '/user-score'], ['title' => '文章管理', 'icon' => 'icon-park:web-page', 'url' => '/articles'], ['title' => '系统管理', 'icon' => 'icon-park:setting', 'url' => '/system', 'children' => [ ['title' => '用户管理', 'icon' => 'icon-park:people-plus', 'url' => '/system/admin_users'], diff --git a/database/seeders/KeywordSeeder.php b/database/seeders/KeywordSeeder.php index 167939c..24db1ef 100644 --- a/database/seeders/KeywordSeeder.php +++ b/database/seeders/KeywordSeeder.php @@ -17,30 +17,12 @@ class KeywordSeeder extends Seeder Keyword::truncate(); $list = [ - ['key' => 'product_category', 'name' => '商品分类', 'children' => [ - ['name' => '家用电器', 'children' => [ - ['name' => '电视'], - ['name' => '冰箱'], - ['name' => '洗衣机'], - ]], - ['name' => '手机数码', 'children' => [ - ['name' => '手机'], - ['name' => '手机配件'], - ['name' => '摄影摄像'], - ]], - ['name' => '电脑办公', 'children' => [ - ['name' => '电脑整机'], - ['name' => '外设产品'], - ['name' => '网络产品'], - ]] - ]], - ['key' => 'article_category', 'name' => '文章分类', 'children' => [ - ['name' => '后端'], - ['name' => '前端'], - ['name' => 'Android'], - ['name' => 'IOS'], - ['name' => '开发工具'], - ['name' => '人工智能'], + ['key' => 'score_cate', 'name' => '考核指标', 'children' => [ + ['key' => 'score_cate_1', 'name' => '政治忠诚'], + ['key' => 'score_cate_2', 'name' => '政治定力'], + ['key' => 'score_cate_3', 'name' => '政治担当'], + ['key' => 'score_cate_4', 'name' => '政治能力'], + ['key' => 'score_cate_5', 'name' => '政治自律'], ]] ]; @@ -51,9 +33,9 @@ class KeywordSeeder extends Seeder { foreach ($list as $index => $item) { $params = Arr::except($item, ['children']); - $params['sort'] = $index; + $params['sort'] = $index + 1; $params['parent_id'] = $parent ? $parent->id : 0; - $params['key'] = data_get($item, 'key', data_get($parent, 'key') . '_' . $index); + $params['key'] = data_get($item, 'key', data_get($parent, 'key') . '_' . $params['sort']); $model = Keyword::create($params); if ($children = data_get($item, 'children')) { diff --git a/lang/zh_CN/keywords.php b/lang/zh_CN/keywords.php index 2ac53bc..7bedf33 100644 --- a/lang/zh_CN/keywords.php +++ b/lang/zh_CN/keywords.php @@ -8,7 +8,7 @@ return [ 'parent_id' => '上级', 'type_key' => '上级', 'path' => '上级', - 'sort' => '排序(倒序)', + 'sort' => '排序(正序)', 'level' => '层级', 'options' => '扩展', 'image' => '图片', diff --git a/lang/zh_CN/party_cate.php b/lang/zh_CN/party_cate.php new file mode 100644 index 0000000..553ec2d --- /dev/null +++ b/lang/zh_CN/party_cate.php @@ -0,0 +1,14 @@ + 'ID', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + + 'name' => '名称', + 'master_id' => '书记', + 'plan_id' => '组织委员', + 'remarks' => '备注', + 'score' => '累计得分', + 'scores' => '五星维度', +]; diff --git a/lang/zh_CN/party_user.php b/lang/zh_CN/party_user.php new file mode 100644 index 0000000..5007199 --- /dev/null +++ b/lang/zh_CN/party_user.php @@ -0,0 +1,16 @@ + 'ID', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + + 'username' => '登录名', + 'password' => '登录密码', + 'name' => '姓名', + 'avatar' => '头像', + 'cate_id' => '党支部', + 'remarks' => '备注', + 'score' => '累计得分', + 'scores' => '五星维度', +]; diff --git a/lang/zh_CN/user_score.php b/lang/zh_CN/user_score.php new file mode 100644 index 0000000..e214f25 --- /dev/null +++ b/lang/zh_CN/user_score.php @@ -0,0 +1,19 @@ + 'ID', + 'created_at' => '提交时间', + 'updated_at' => '更新时间', + + 'type_id' => '分类', + 'user_id' => '党员', + 'title' => '主题', + 'content' => '内容', + 'images' => '图片', + 'file' => '附件', + 'check_status' => '状态', + 'check_user_id' => '审核人', + 'check_remarks' => '未通过原因', + 'check_at' => '审核时间', + 'score' => '得分', +]; diff --git a/routes/api.php b/routes/api.php index 889937e..7039220 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,6 +14,4 @@ use Illuminate\Support\Facades\Route; | */ -Route::middleware('auth:sanctum')->get('/user', function (Request $request) { - return $request->user(); -}); +Route::post('web/upload', [\App\Http\Controllers\WebController::class, 'upload']);