From af9ab0f4ab4110216d0a1ace30339e7af2421a23 Mon Sep 17 00:00:00 2001 From: jsasg <735273025@qq.com> Date: Fri, 21 Feb 2025 15:28:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=99=84=E4=BB=B6?= =?UTF-8?q?=EF=BC=88=E4=B8=8B=E8=BD=BD=E7=AE=A1=E7=90=86=EF=BC=89=E5=88=86?= =?UTF-8?q?=E9=A1=B5/=E8=AF=A6=E6=83=85/=E6=96=B0=E5=A2=9E/=E6=9B=B4?= =?UTF-8?q?=E6=96=B0/=E8=AE=BE=E7=BD=AE=E6=8E=92=E5=BA=8F=E5=80=BC/?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/v1/Attachment.php | 189 ++++++++++++++++++ app/admin/model/v1/AttachmentModel.php | 71 +++++++ app/admin/route/v1.php | 21 ++ app/admin/validate/v1/AttachmentValidate.php | 87 ++++++++ app/common/model/AttachmentBaseModel.php | 40 ++++ .../20241220094223_create_attachment.php | 2 +- 6 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 app/admin/controller/v1/Attachment.php create mode 100644 app/admin/model/v1/AttachmentModel.php create mode 100644 app/admin/validate/v1/AttachmentValidate.php create mode 100644 app/common/model/AttachmentBaseModel.php diff --git a/app/admin/controller/v1/Attachment.php b/app/admin/controller/v1/Attachment.php new file mode 100644 index 00000000..a3cd0c1e --- /dev/null +++ b/app/admin/controller/v1/Attachment.php @@ -0,0 +1,189 @@ +param([ + 'name', + 'category_id', + 'created_at', + 'page/d' => 1, + 'size/d' => 10 + ]); + + $attachments = AttachmentModel::field([ + 'id', + 'image', + 'name', + 'category_id', + 'sort', + 'recommend', + 'status', + 'created_at' + ]) + ->with(['category' => function ($query) { + $query->field(['id', 'name' => 'category_name']); + }]) + ->withSearch(['name', 'created_at'], [ + 'name' => $params['name']??null, + 'created_at' => !empty($params['created_at']) ? explode(',', $params['created_at']) : null + ]) + ->language(request()->lang_id) + ->categoryId($params['category_id']??null) + ->order(['sort' => 'asc', 'id' => 'desc']) + ->paginate([ + 'list_rows' => $params['size'], + 'page' => $params['page'] + ]) + ->bindAttr('category', ['category_name']) + ->hidden(['category_id', 'category']); + + return success('获取成功', $attachments); + } + + /** + * 附件详情 + */ + public function read() + { + $id = request()->param('id'); + + $attachment = AttachmentModel::withoutField([ + 'language_id', + 'created_at', + 'updated_at', + 'deleted_at' + ]) + ->bypk($id) + ->find(); + if (empty($attachment)) { + return error('附件不存在'); + } + + return success('获取成功', $attachment); + } + + /** + * 附件添加 + */ + public function save() + { + $post = request()->post([ + 'name', + 'category_id', + 'sort', + 'recommend', + 'image', + 'aplicable_to', + 'support_platform', + 'attach', + 'seo_title', + 'seo_keywords', + 'seo_desc' + ]); + $data = array_merge($post, ['language_id' => request()->lang_id]); + + $validate = new AttachmentValidate; + if (!$validate->scene('create')->check($data)) { + return error($validate->getError()); + } + + $attachment = AttachmentModel::create($data); + if ($attachment->isEmpty()) { + return error('操作失败'); + } + return success('操作成功'); + } + + /** + * 附件更新 + */ + public function update() + { + $id = request()->param('id'); + $put = request()->put([ + 'name', + 'category_id', + 'sort', + 'recommend', + 'image', + 'aplicable_to', + 'support_platform', + 'attach', + 'seo_title', + 'seo_keywords', + 'seo_desc' + ]); + + $validate = new AttachmentValidate; + if (!$validate->scene('update')->check(array_merge($put, ['id' => $id]))) { + return error($validate->getError()); + } + + $attachment = AttachmentModel::bypk($id)->find(); + if (empty($attachment)) { + return error('请确认操作对象是否存在'); + } + + if (!$attachment->save($put)) { + return error('操作失败'); + } + return success('操作成功'); + } + + /** + * 设置排序值 + */ + public function sort() + { + $id = request()->param('id'); + $sort = request()->post('sort'); + + $validate = new AttachmentValidate; + if (!$validate->scene('sort')->check(['sort' => $sort])) { + return error($validate->getError()); + } + + $attachment = AttachmentModel::bypk($id)->find(); + if (empty($attachment)) { + return error('请确认操作对象是否存在'); + } + + $attachment->sort = $sort; + if (!$attachment->save()) { + return error('操作失败'); + } + return success('操作成功'); + } + + /** + * 附件删除 + */ + public function delete() + { + $id = request()->param('id'); + + $attachment = AttachmentModel::bypk($id)->find(); + if (empty($attachment)) { + return error('请确认操作对象是否存在'); + } + + if (!$attachment->delete()) { + return error('操作失败'); + } + return success('操作成功'); + } +} diff --git a/app/admin/model/v1/AttachmentModel.php b/app/admin/model/v1/AttachmentModel.php new file mode 100644 index 00000000..82ad7076 --- /dev/null +++ b/app/admin/model/v1/AttachmentModel.php @@ -0,0 +1,71 @@ +file_path' => 'string', + 'attach[*]->file_ext' => 'string', + 'attach[*]->btn_name' => 'string', + ]; + + // 关联附件分类模型 + public function category() + { + return $this->belongsTo(AttachmentCategoryModel::class, 'category_id', 'id'); + } + + // 名称搜索 + public function searchNameAttr($query, $value) + { + if (empty($value)) return; + $query->where('name', 'like', '%' . $value . '%'); + } + + // 新增时间搜索 + public function searchCreatedAtAttr($query, $value) + { + if (empty($value)) return; + if (is_array($value)) { + if (count($value) > 1) { + $query->whereBetweenTime('created_at', $value[0], $value[1]); + } else { + $query->whereTime('created_at', '>=', $value[0]); + } + } + } + + // 语言查询 + public function scopeLanguage($query, $value) + { + $query->where('language_id', '=', $value); + } + + // 分类查询 + public function scopeCategoryId($query, $value) + { + if (empty($value)) return; + $query->where('category_id', '=', $value); + } +} diff --git a/app/admin/route/v1.php b/app/admin/route/v1.php index b604667b..31a6f0de 100644 --- a/app/admin/route/v1.php +++ b/app/admin/route/v1.php @@ -273,6 +273,27 @@ Route::group('v1', function () { // 产品回收站删除 Route::delete('delete/:id', 'ProductTrash/delete'); }); + + // 附件(下载管理) + Route::group('attachment', function () { + // 附件(下载管理)列表 + Route::get('index', 'Attachment/index'); + + // 附件(下载管理)详情 + Route::get('read/:id', 'Attachment/read'); + + // 附件(下载管理)新增 + Route::post('save', 'Attachment/save'); + + // 附件(下载管理)更新 + Route::put('update/:id', 'Attachment/update'); + + // 附件(下载管理)设置排序值 + Route::get('sort/:id', 'Attachment/sort'); + + // 附件(下载管理)删除 + Route::delete('delete/:id', 'Attachment/delete'); + }); }); })->prefix('v1.'); diff --git a/app/admin/validate/v1/AttachmentValidate.php b/app/admin/validate/v1/AttachmentValidate.php new file mode 100644 index 00000000..afae070f --- /dev/null +++ b/app/admin/validate/v1/AttachmentValidate.php @@ -0,0 +1,87 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => 'require|integer', + 'language_id' => 'require|integer', + 'category_id' => 'require|integer', + 'name' => 'require|max:64', + 'desc' => 'max:255', + 'image' => 'max:255', + 'applicable_to' => 'max:255', + 'support_platform' => 'max:255', + 'attach.*.filepath' => 'string', + 'attach.*.ext' => 'string', + 'attach.*.btn_name' => 'string', + 'sort' => 'integer', + 'recommend' => 'in:0,1', + 'seo_title' => 'max:255', + 'seo_keywords' => 'max:255', + 'seo_desc' => 'max:255', + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = [ + 'id.require' => 'ID不能为空', + 'id.integer' => 'ID必须是整数', + 'language_id.require' => '语言ID不能为空', + 'language_id.integer' => '语言ID必须是整数', + 'category_id.require' => '分类ID不能为空', + 'category_id.integer' => '分类ID必须是整数', + 'name.require' => '名称不能为空', + 'name.max' => '名称不能超过64个字符', + 'desc.max' => '描述不能超过255个字符', + 'image.max' => '图片不能超过255个字符', + 'applicable_to.max' => '适用对象不能超过255个字符', + 'support_platform.max' => '支持平台不能超过255个字符', + 'attach.*.file_path.string' => '附件路径必须是字符串', + 'attach.*.file_ext.string' => '附件扩展名必须是字符串', + 'attach.*.btn_name.string' => '附件按钮名必须是字符串', + 'sort.integer' => '排序必须是整数', + 'recommend.in' => '推荐状态必须是0或1', + 'seo_title.max' => 'SEO标题不能超过255个字符', + 'seo_keywords.max' => 'SEO关键字不能超过255个字符', + 'seo_desc.max' => 'SEO描述不能超过255个字符', + ]; + + /** + * 新增场景 + */ + public function sceneCreate() + { + return $this->remove('id', 'require|integer'); + } + + /** + * 更新场景 + */ + public function sceneUpdate() + { + return $this->remove('language_id', 'require|integer'); + } + + /** + * 排序场景 + */ + public function sceneSort() + { + return $this->only(['sort']); + } +} diff --git a/app/common/model/AttachmentBaseModel.php b/app/common/model/AttachmentBaseModel.php new file mode 100644 index 00000000..0034c35c --- /dev/null +++ b/app/common/model/AttachmentBaseModel.php @@ -0,0 +1,40 @@ + 'int', + 'language_id' => 'int', + 'category_id' => 'int', + 'name' => 'string', + 'desc' => 'string', + 'image' => 'string', + 'applicable_to' => 'string', + 'support_platform' => 'string', + 'attach' => 'string', + 'sort' => 'int', + 'recommend' => 'int', + 'seo_title' => 'string', + 'seo_keywords' => 'string', + 'seo_desc' => 'string', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; +} diff --git a/database/migrations/20241220094223_create_attachment.php b/database/migrations/20241220094223_create_attachment.php index be37bc88..73a0de2a 100644 --- a/database/migrations/20241220094223_create_attachment.php +++ b/database/migrations/20241220094223_create_attachment.php @@ -35,7 +35,7 @@ class CreateAttachment extends Migrator ->addColumn('image', 'string', ['limit' => 255, 'default' => null, 'comment' => '图片地址']) ->addColumn('applicable_to', 'string', ['limit' => 255, 'default' => null, 'comment' => '适用于(型号),多个以英文逗号分隔']) ->addColumn('support_platform', 'string', ['limit' => 255, 'default' => null, 'comment' => '支持平台,多个以英文逗号分隔']) - ->addColumn('attach', 'json', ['null' => false, 'comment' => '附件地址: $[*].url为附件地址, $[*].ext为文件格式, $[*].btn_name为下载按钮名称']) + ->addColumn('attach', 'json', ['null' => false, 'comment' => '附件地址: $[*].file_path为附件地址, $[*].file_ext为文件格式, $[*].btn_name为下载按钮名称']) ->addColumn('sort', 'integer', ['null' => false, 'default' => 0, 'comment' => '排序']) ->addColumn('recommend', 'boolean', ['null' => false, 'default' => 0, 'comment' => '是否推荐:1是,0否']) ->addColumn('seo_title', 'string', ['limit' => 255, 'default' => null, 'comment' => 'SEO标题'])