diff --git a/app/Admin/Components.php b/app/Admin/Components.php
index 7c2f50b..ebfab98 100644
--- a/app/Admin/Components.php
+++ b/app/Admin/Components.php
@@ -78,10 +78,14 @@ class Components extends BaseRenderer {
* 图片上传,带裁剪
*/
public function cropImageControl($name, $label, $aspectRatio = null){
- return amis()->ImageControl($name, $label)->joinValues(false)
- ->crop([
- 'aspectRatio' => $aspectRatio ?? 1
- ])->autoUpload(true);
+ $cropImage = amis()->ImageControl($name, $label)->joinValues(false);
+ // if($aspectRatio){
+ $cropImage->crop([
+ 'aspectRatio' => $aspectRatio ?? 1
+ ]);
+ // }
+ $cropImage->autoUpload(true);
+ return $cropImage;
}
/**
@@ -90,7 +94,6 @@ class Components extends BaseRenderer {
public function fileControl($name, $label, $accept = '.txt', $multiple = false){
return amis()->FileControl($name, $label ?? __('admin.components.files'))
->multiple($multiple)
- // ->receiver()
->joinValues(false)
->useChunk(false)
->maxSize(20*1024*1024)
diff --git a/app/Admin/Controllers/AdController.php b/app/Admin/Controllers/AdController.php
new file mode 100644
index 0000000..a67ac73
--- /dev/null
+++ b/app/Admin/Controllers/AdController.php
@@ -0,0 +1,79 @@
+baseCRUD()->tableLayout('fixed')
+ ->headerToolbar([
+ $this->createButton(),
+ ...$this->baseHeaderToolBar(),
+ ])
+ ->filter($this->baseFilter()->body())
+ ->columns([
+ amis()->TableColumn('id', __('admin.ads.id'))->width('50px')->sortable(),
+ amis()->TableColumn('address', __('admin.ads.address'))->type('mapping')
+ ->map(Keyword::allChildrenOfKey('banner_address')->pluck('name', 'key')->toArray())
+ ->itemSchema(amis()->Tag()->label('${item}')->color(Admin::setting()->get('system_theme_setting')['theme_color'] ?? '#1677ff')),
+ amis()->TableColumn('sort', __('admin.ads.sort')),
+ amis()->TableColumn('resource', __('admin.ads.resource'))->type('image')->height('50px')->width('150px')->enlargeAble(true),
+ amis()->TableColumn('remark', __('admin.ads.remark')),
+ amis()->TableColumn('published_at', __('admin.ads.published_at'))->remark(__('admin.ads.published_at_remark')),
+ amis()->TableColumn('is_enable', __('admin.ads.is_enable'))->type('switch'),
+ amis()->TableColumn('created_at', __('admin.created_at'))->type('datetime')->sortable(true),
+ Operation::make()->label(__('admin.actions'))->buttons([
+ $this->rowEditButton(),
+ $this->rowDeleteButton(),
+ ])
+ ]);
+
+ return $this->baseList($crud);
+ }
+
+ public function form($isEdit = false): Form
+ {
+ return $this->baseForm()->body([
+ Components::make()->parentControl(admin_url('api/keywords/tree-list?parent_name=banner_address&has_owner=0'), 'address', __('admin.ads.address'), 'name', 'key')->required(true),
+ Components::make()->imageControl('resource', __('admin.ads.resource'))->required(true),
+ amis()->TextControl('remark', __('admin.ads.remark')),
+ Components::make()->sortControl('sort', __('admin.ads.sort')),
+ amis()->DateTimeControl('published_at', __('admin.ads.published_at'))->format('YYYY-MM-DD HH:mm:ss')->description(__('admin.ads.published_at_remark')),
+ amis()->SwitchControl('is_enable', __('admin.ads.is_enable'))->value(false),
+ amis()->RadiosControl('jump_type', __('admin.ads.jump_type'))->selectFirst(true)->options(Ad::jumpTypeMap())->required(true),
+ amis()->TextControl('jump_config.web_link', __('admin.ads.jump_config_arr.web_link'))->visibleOn('this.jump_type == '.Ad::TYPE_WEB)->required(true),
+ amis()->TextControl('jump_config.app_link', __('admin.ads.jump_config_arr.app_link'))->visibleOn('this.jump_type == '.Ad::TYPE_APP)->required(true),
+ amis()->GroupControl()->body([
+ amis()->TextControl('jump_config.mini_id', __('admin.ads.jump_config_arr.mini_id'))->visibleOn('this.jump_type == '.Ad::TYPE_MINI)->required(true),
+ amis()->TextControl('jump_config.mini_link', __('admin.ads.jump_config_arr.mini_link'))->visibleOn('this.jump_type == '.Ad::TYPE_MINI)->required(true),
+ ]),
+ ]);
+ }
+
+ public function detail(): Form
+ {
+ return $this->baseDetail()->body([
+ amis()->TextControl('id', 'ID')->static(),
+ amis()->TextControl('created_at', __('admin.created_at'))->static(),
+ amis()->TextControl('updated_at', __('admin.updated_at'))->static()
+ ]);
+ }
+}
diff --git a/app/Admin/Controllers/ArticleController.php b/app/Admin/Controllers/ArticleController.php
index 85b245c..eec3fa1 100644
--- a/app/Admin/Controllers/ArticleController.php
+++ b/app/Admin/Controllers/ArticleController.php
@@ -23,7 +23,7 @@ class ArticleController extends AdminController
...$this->baseHeaderToolBar(),
])
->filter($this->baseFilter()->body())
- ->itemBadge([
+ ->itemBadge([//行角标
'text' => __('admin.articles.is_recommend'),
'mode' => 'ribbon',
'position' => 'top-left',
@@ -32,7 +32,7 @@ class ArticleController extends AdminController
'size' => 15
])
->columns([
- amis()->TableColumn('id', __('admin.id')),
+ amis()->TableColumn('id', __('admin.id'))->sortable(true),
amis()->TableColumn('title', __('admin.articles.title'))->width('300px'),
amis()->TableColumn('category', __('admin.articles.category'))->type('mapping')
->map(Keyword::allChildrenOfKey('article_category')->pluck('name', 'key')->toArray())
@@ -42,7 +42,7 @@ class ArticleController extends AdminController
amis()->TableColumn('published_at', __('admin.articles.published_at'))->remark(__('admin.articles.published_at_remark')),
amis()->TableColumn('is_enable', __('admin.articles.is_enable'))->type('switch'),
amis()->TableColumn('is_recommend', __('admin.articles.is_recommend'))->type('switch'),
- amis()->TableColumn('created_at', __('admin.created_at')),
+ amis()->TableColumn('created_at', __('admin.created_at'))->type('datetime')->sortable(true),
amis()->Operation()->label(__('admin.actions'))->buttons([
$this->rowEditButton(),
$this->rowDeleteButton(),
@@ -65,7 +65,7 @@ class ArticleController extends AdminController
amis()->DateTimeControl('published_at', __('admin.articles.published_at'))->format('YYYY-MM-DD HH:mm:ss')->description(__('admin.articles.published_at_remark')),
amis()->SwitchControl('is_enable', __('admin.articles.is_enable'))->value(false),
amis()->SwitchControl('is_recommend', __('admin.articles.is_recommend'))->value(false),
- Components::make()->fileControl('appendixes', __('admin.articles.appendixes'), '.xsl,.xlsx,.txt,.doc,.docx,.pdf,.pptx'),
+ Components::make()->fileControl('appendixes', __('admin.articles.appendixes'), '.xsl,.xlsx,.txt,.doc,.docx,.pdf,.pptx', true),
])->md(4),
amis()->Wrapper()->body([
Components::make()->fuEditorControl('content', __('admin.articles.content')),
diff --git a/app/Admin/routes.php b/app/Admin/routes.php
index faf3ff0..e53cb36 100644
--- a/app/Admin/routes.php
+++ b/app/Admin/routes.php
@@ -30,6 +30,8 @@ Route::group([
$router->resource('articles', \App\Admin\Controllers\ArticleController::class);
+ $router->resource('ads', \App\Admin\Controllers\AdController::class);
+
//修改上传
$router->post('upload_file', [\App\Admin\Controllers\IndexController::class, 'uploadFile']);
$router->post('upload_image', [\App\Admin\Controllers\IndexController::class, 'uploadImage']);
diff --git a/app/Models/Ad.php b/app/Models/Ad.php
new file mode 100644
index 0000000..6be8487
--- /dev/null
+++ b/app/Models/Ad.php
@@ -0,0 +1,86 @@
+format('Y-m-d H:i:s');
+ }
+
+ protected $casts = [
+ 'created_at' => 'datetime',
+ 'updated_at' => 'datetime',
+ 'published_at' => 'datetime',
+ 'is_enable' => 'boolean',
+ 'resource' => Storage::class,
+ 'jump_config' => 'array',
+ ];
+
+ protected $fillable = [
+ 'resource',
+ 'address',
+ 'remark',
+ 'published_at',
+ 'is_enable',
+ 'sort',
+ 'jump_type',
+ 'jump_config',
+ ];
+
+ public static function jumpTypeMap() :array
+ {
+ return [
+ self::TYPE_WEB => '网页跳转',
+ self::TYPE_APP => '应用跳转',
+ self::TYPE_MINI => '小程序跳转',
+ self::TYPE_OFF => '无跳转',
+ ];
+ }
+
+ public static function jumpTypeMapLabel()
+ {
+ return [
+ self::TYPE_OFF => "无跳转",
+ self::TYPE_WEB => "网页跳转",
+ self::TYPE_APP => "应用跳转",
+ self::TYPE_MINI => "小程序跳转",
+ '*'=>'其他:${jump_type}'
+ ];
+ }
+
+ public static function typeMapLabel()
+ {
+ return [
+ self::TYPE_IN => "入住缴费",
+ self::TYPE_CONTINUE => "续住缴费",
+ self::TYPE_EXIT => "离开结算",
+ '*'=>'其他:${live_in}'
+ ];
+ }
+
+ public function scopeShow(){
+ $q->where('is_enable', true)->where('published_at', '>=', now());
+ }
+
+ public function scopeSort($q)
+ {
+ $q->orderBy('sort', 'asc')
+ ->orderBy('published_at', 'desc')
+ ->orderBy('created_at', 'desc');
+ }
+}
diff --git a/app/Models/Filters/AdFilter.php b/app/Models/Filters/AdFilter.php
new file mode 100644
index 0000000..b7e8c68
--- /dev/null
+++ b/app/Models/Filters/AdFilter.php
@@ -0,0 +1,16 @@
+where('name','like', '%'.$name.'%');
+ }
+}
diff --git a/app/Services/Admin/AdService.php b/app/Services/Admin/AdService.php
new file mode 100644
index 0000000..c1feaf6
--- /dev/null
+++ b/app/Services/Admin/AdService.php
@@ -0,0 +1,112 @@
+getTableColumns();
+ $model = $this->getModel();
+
+ $isEnable = Arr::get($data, 'is_enabled');
+ $publishedAt = Arr::get($data, 'published_at');
+ if ($isEnable && empty($publishedAt)) {
+ $data['published_at'] = now();
+ }
+
+ $data['resource'] = $this->saveImage('resource', 'ads/resource')[0];
+
+ //处理跳转配置
+ $jumpType = Arr::get($data, 'jump_type');
+ if($jumpType !== null){
+ switch($jumpType){
+ case Ad::TYPE_OFF:
+ $data['jump_config'] = null;
+ break;
+ case Ad::TYPE_WEB:
+ $data['jump_config'] = Arr::only($data['jump_config'], 'web_link');
+ break;
+ case Ad::TYPE_APP:
+ $data['jump_config'] = Arr::only($data['jump_config'], 'app_link');;
+ break;
+ case Ad::TYPE_MINI:
+ $data['jump_config'] = Arr::only($data['jump_config'], ['mini_id', 'mini_link']);;
+ break;
+ }
+ }
+
+ foreach ($data as $k => $v) {
+ if (!in_array($k, $columns)) {
+ continue;
+ }
+
+ $model->setAttribute($k, $v);
+ }
+
+ return $model->save();
+ }
+
+ public function update($primaryKey, $data): bool
+ {
+ $columns = $this->getTableColumns();
+ $model = $this->query()->whereKey($primaryKey)->first();
+
+ $isEnable = Arr::get($data, 'is_enable');
+ $publishedAt = Arr::get($data, 'published_at');
+
+ if ($isEnable && empty($publishedAt) && empty($model->published_at)) {
+ $data['published_at'] = now();
+ }
+
+ if(isset($data['resource'])){
+ $data['resource'] = $this->saveImage('resource', 'ads/resource')[0];
+ }
+
+ //处理跳转配置
+ $jumpType = Arr::get($data, 'jump_type');
+ if($jumpType !== null){
+ switch($jumpType){
+ case Ad::TYPE_OFF:
+ $data['jump_config'] = null;
+ break;
+ case Ad::TYPE_WEB:
+ $data['jump_config'] = Arr::only($data['jump_config'], 'web_link');
+ break;
+ case Ad::TYPE_APP:
+ $data['jump_config'] = Arr::only($data['jump_config'], 'app_link');;
+ break;
+ case Ad::TYPE_MINI:
+ $data['jump_config'] = Arr::only($data['jump_config'], ['mini_id', 'mini_link']);;
+ break;
+ }
+ }
+
+ foreach ($data as $k => $v) {
+ if (!in_array($k, $columns)) {
+ continue;
+ }
+
+ $model->setAttribute($k, $v);
+ }
+
+ return $model->save();
+ }
+}
\ No newline at end of file
diff --git a/app/Services/Admin/AdminUserService.php b/app/Services/Admin/AdminUserService.php
index 86935da..eeca23e 100644
--- a/app/Services/Admin/AdminUserService.php
+++ b/app/Services/Admin/AdminUserService.php
@@ -128,6 +128,8 @@ class AdminUserService extends BaseService
$query->where('username', 'like', "%{$keyword}%")->orWhere('name', 'like', "%{$keyword}%");
});
+ $this->sortable($query);
+
$items = (clone $query)->paginate(request()->input('perPage', 20))->items();
$total = (clone $query)->count();
diff --git a/app/Services/Admin/ArticleService.php b/app/Services/Admin/ArticleService.php
index 01e2190..69682d2 100644
--- a/app/Services/Admin/ArticleService.php
+++ b/app/Services/Admin/ArticleService.php
@@ -19,6 +19,8 @@ class ArticleService extends BaseService
protected string $modelFilterName = ArticleFilter::class;
+ protected bool $modelSortAble = true;
+
public function store($data): bool
{
$columns = $this->getTableColumns();
@@ -55,9 +57,13 @@ class ArticleService extends BaseService
if ($isEnable && empty($publishedAt) && empty($model->published_at)) {
$data['published_at'] = now();
}
+ if(isset($data['cover'])){
+ $data['cover'] = $this->saveImage('cover', 'articles/cover')[0];
+ }
- $data['cover'] = $this->saveImage('cover', 'articles/cover')[0];
- $data['appendixes'] = $this->saveFile('appendixes', 'articles/appendixes');
+ if(isset($data['appendixes'])){
+ $data['appendixes'] = $this->saveFile('appendixes', 'articles/appendixes');
+ }
foreach ($data as $k => $v) {
if (!in_array($k, $columns)) {
diff --git a/app/Services/Admin/BaseService.php b/app/Services/Admin/BaseService.php
index a9ec1eb..4fa0ecd 100644
--- a/app/Services/Admin/BaseService.php
+++ b/app/Services/Admin/BaseService.php
@@ -14,6 +14,8 @@ class BaseService extends AdminService
protected string $modelFilterName = '';
+ protected bool $modelSortAble = false;
+
public function getTree()
{
$list = $this->query()->orderByDesc('sort')->get();
@@ -40,7 +42,13 @@ class BaseService extends AdminService
$query->filter(request()->input(), $filter);
}
- return $query->orderByDesc($model->getUpdatedAtColumn() ?? $model->getKeyName());
+ if($this->modelSortAble){
+ $query->sort();
+ }
+
+ $this->sortable($query);
+
+ return $query;
}
public function getDetail($id)
diff --git a/app/Services/Admin/KeywordService.php b/app/Services/Admin/KeywordService.php
index 5143832..7e28bc1 100644
--- a/app/Services/Admin/KeywordService.php
+++ b/app/Services/Admin/KeywordService.php
@@ -19,7 +19,7 @@ class KeywordService extends BaseService
{
$list = $this->query()->filter(request()->all(), $this->modelFilterName)->orderByDesc('sort')->get();
$minNum = $list->min('parent_id');
- return array2tree($list->toArray(), $minNum);
+ return !$list->isEmpty() ? array2tree($list->toArray(), $minNum) :[];
}
public function parentIsChild($id, $pid): bool
diff --git a/database/migrations/2023_12_18_162317_create_ads_table.php b/database/migrations/2023_12_18_162317_create_ads_table.php
new file mode 100644
index 0000000..4b8e06a
--- /dev/null
+++ b/database/migrations/2023_12_18_162317_create_ads_table.php
@@ -0,0 +1,35 @@
+id();
+ $table->string('address')->comment('位置');
+ $table->string('resource')->comment('资源');
+ $table->string('remark')->nullable()->comment('备注');
+ $table->timestamp('published_at')->nullable()->comment('发布时间');
+ $table->unsignedTinyInteger('is_enable')->default(1)->comment('显示开关');
+ $table->unsignedInteger('sort')->default(0)->comment('排序');
+ $table->unsignedTinyInteger('jump_type')->default(0)->comment('跳转,0:不跳转。1:网页跳转;2应用跳转;3微信小程序跳转');
+ $table->text('jump_config')->nullable()->comment('跳转配置');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('ads');
+ }
+};
diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php
index fd9e456..64d4d73 100644
--- a/database/seeders/AdminMenuSeeder.php
+++ b/database/seeders/AdminMenuSeeder.php
@@ -33,7 +33,7 @@ class AdminMenuSeeder extends Seeder
['title' => 'web_content', 'icon' => 'ic:outline-collections-bookmark', 'url' => '', 'order'=>3,
'children' =>[
['title'=>'articles', 'icon'=>'ic:outline-article','url'=>'/articles', 'order'=>1],
- ['title'=>'banners', 'icon'=>'lets-icons:img-box','url'=>'/banners', 'order'=>2],
+ ['title'=>'ads', 'icon'=>'lets-icons:img-box','url'=>'/ads', 'order'=>2],
]
]
];
diff --git a/lang/zh_CN/admin.php b/lang/zh_CN/admin.php
index facb7c5..9632312 100644
--- a/lang/zh_CN/admin.php
+++ b/lang/zh_CN/admin.php
@@ -60,7 +60,7 @@ return [
'cancel' => '取消',
'please_login' => '请先登录',
'unauthorized' => '无权访问',
- 'id' => '主键',
+ 'id' => 'ID',
'components' => [
'content' => '内容',
@@ -274,7 +274,7 @@ return [
'parent_keyword' => '父级关键字',
],
'articles' => [
- 'id' => '主键',
+ 'id' => 'ID',
'title' => '标题',
'content' => '内容',
'cover' =>'封面',
@@ -288,5 +288,24 @@ return [
'sort' => '排序',
'appendixes' => '附件',
'published_at_remark' => '*若未设置发布时间且操作设置为显示,则默认生成发布时间'
+ ],
+ 'ads' => [
+ 'id' => 'ID',
+ 'address' => '位置',
+ 'resource' =>'内容',
+ 'published_at' => '定时发布',
+ 'published_at_g' => '发布时间',
+ 'is_enable' => '显示',
+ 'remark' => '备注',
+ 'sort' => '排序',
+ 'published_at_remark' => '*若未设置发布时间且操作设置为显示,则默认生成发布时间',
+ 'jump_type' => '跳转类型',
+ 'jump_config'=>'跳转配置',
+ 'jump_config_arr'=>[
+ 'web_link' => '网页地址',
+ 'app_link' => '应用路径',
+ 'mini_id' => '小程序ID',
+ 'mini_link'=> '小程序路径'
+ ],
]
];
diff --git a/lang/zh_CN/menu.php b/lang/zh_CN/menu.php
index 83d4469..dbedcd6 100644
--- a/lang/zh_CN/menu.php
+++ b/lang/zh_CN/menu.php
@@ -12,5 +12,5 @@ return [
'keywords' => '数据字典',
'web_content' => '内容管理',
'articles' => '文章管理',
- 'banners' => '广告管理',
+ 'ads' => '广告管理',
];