Compare commits
10 Commits
4b6153f971
...
3a736d15c2
| Author | SHA1 | Date |
|---|---|---|
|
|
3a736d15c2 | |
|
|
9013fd4fa4 | |
|
|
70fbbf1198 | |
|
|
2872d54f6f | |
|
|
038427493c | |
|
|
c5249c2a3f | |
|
|
0168489311 | |
|
|
64ff120a9e | |
|
|
32a95b96d7 | |
|
|
851f453bf8 |
|
|
@ -70,6 +70,7 @@ class Components extends BaseRenderer {
|
|||
*/
|
||||
public function imageControl($name, $label){
|
||||
return amis()->ImageControl($name, $label)
|
||||
->joinValues(false)
|
||||
->autoUpload(true)->maxSize('5*1024*1024');//不能大于5M
|
||||
}
|
||||
|
||||
|
|
@ -77,10 +78,37 @@ class Components extends BaseRenderer {
|
|||
* 图片上传,带裁剪
|
||||
*/
|
||||
public function cropImageControl($name, $label, $aspectRatio = null){
|
||||
return amis()->ImageControl($name, $label)
|
||||
->crop([
|
||||
$cropImage = amis()->ImageControl($name, $label)->joinValues(false);
|
||||
// if($aspectRatio){
|
||||
$cropImage->crop([
|
||||
'aspectRatio' => $aspectRatio ?? 1
|
||||
])->autoUpload(true);
|
||||
]);
|
||||
// }
|
||||
$cropImage->autoUpload(true);
|
||||
return $cropImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通文件上传
|
||||
*/
|
||||
public function fileControl($name, $label, $accept = '.txt', $multiple = false){
|
||||
return amis()->FileControl($name, $label ?? __('admin.components.files'))
|
||||
->multiple($multiple)
|
||||
->joinValues(false)
|
||||
->useChunk(false)
|
||||
->maxSize(20*1024*1024)
|
||||
->accept($accept);
|
||||
}
|
||||
|
||||
public function chunkFileControl($name, $label, $accept = '*', $multiple = false){
|
||||
return amis()->FileControl($name, $label ?? __('admin.components.files'))
|
||||
->multiple($multiple)
|
||||
->joinValues(false)
|
||||
->useChunk(true)
|
||||
->accept($accept)
|
||||
->startChunkApi(admin_url('start_chunk_upload_file'))
|
||||
->chunkApi(admin_url('save_chunk_upload_file'))
|
||||
->finishChunkApi(admin_url('finish_chunk_upload_file'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use Slowlyo\OwlAdmin\Admin;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use Slowlyo\OwlAdmin\Renderers\Operation;
|
||||
use App\Services\Admin\AdService;
|
||||
use App\Admin\Components;
|
||||
use App\Models\Keyword;
|
||||
use App\Models\Ad;
|
||||
|
||||
/**
|
||||
* 广告管理
|
||||
*
|
||||
* @property AdService $service
|
||||
*/
|
||||
class AdController extends AdminController
|
||||
{
|
||||
protected string $serviceName = AdService::class;
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()->tableLayout('fixed')
|
||||
->headerToolbar([
|
||||
$this->createButton(),
|
||||
...$this->baseHeaderToolBar(),
|
||||
])
|
||||
->filter($this->baseFilter()->labelWidth('80px')->body([
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amis()->TextControl('id', __('admin.ads.id'))
|
||||
->placeholder(__('admin.id')),
|
||||
amis()->TextControl('remark', __('admin.ads.remark'))
|
||||
->placeholder(__('admin.ads.remark')),
|
||||
Components::make()->parentControl(admin_url('api/keywords/tree-list?parent_name=banner_address&has_owner=0'), 'address', __('admin.ads.address'), 'name', 'key'),
|
||||
amis()->SelectControl('enable', __('admin.ads.is_enable'))
|
||||
->options([
|
||||
1=>'开启',0=>'关闭'
|
||||
]),
|
||||
]),
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amis()->InputDatetimeRange()->label(__('admin.ads.published_at'))->name('published_at'),
|
||||
amis()->InputDatetimeRange()->label(__('admin.created_at'))->name('created_at'),
|
||||
]),
|
||||
]))
|
||||
->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'))->quickEdit(
|
||||
amis()->NumberControl()->min(0)->saveImmediately(true)
|
||||
),
|
||||
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()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,8 +22,33 @@ class ArticleController extends AdminController
|
|||
$this->createButton(),
|
||||
...$this->baseHeaderToolBar(),
|
||||
])
|
||||
->filter($this->baseFilter()->body())
|
||||
->itemBadge([
|
||||
->filter($this->baseFilter()->body([
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amis()->TextControl('id', __('admin.articles.id'))
|
||||
->placeholder(__('admin.id')),
|
||||
amis()->TextControl('title', __('admin.articles.title'))
|
||||
->placeholder(__('admin.articles.title')),
|
||||
Components::make()->parentControl(admin_url('api/keywords/tree-list?parent_name=article_category&has_owner=0'), 'category', __('admin.articles.category'), 'name', 'key'),
|
||||
Components::make()->keywordsTagControl('t_ids', __('admin.articles.tags'), 'article_tag'),
|
||||
]),
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amis()->SelectControl('enable', __('admin.articles.is_enable'))
|
||||
->columnRatio(3)
|
||||
->options([
|
||||
1=>'开启',0=>'关闭'
|
||||
]),
|
||||
amis()->SelectControl('recommend', __('admin.articles.is_recommend'))
|
||||
->columnRatio(3)
|
||||
->options([
|
||||
1=>'开启',0=>'关闭'
|
||||
]),
|
||||
amis()->InputDatetimeRange()->label(__('admin.articles.published_at'))->name('published_at'),
|
||||
]),
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amis()->InputDatetimeRange()->label(__('admin.created_at'))->name('created_at')->columnRatio(6),
|
||||
]),
|
||||
]))
|
||||
->itemBadge([//行角标
|
||||
'text' => __('admin.articles.is_recommend'),
|
||||
'mode' => 'ribbon',
|
||||
'position' => 'top-left',
|
||||
|
|
@ -32,17 +57,17 @@ 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())
|
||||
->itemSchema(amis()->Tag()->label('${item}')->color(Admin::setting()->get('system_theme_setting')['theme_color'] ?? '#1677ff')),
|
||||
amis()->TableColumn('tags', __('admin.articles.tags'))->type('mapping')->map(Keyword::tagsMap('article_tag')),
|
||||
amis()->TableColumn('cover', __('admin.articles.cover'))->type('image')->height('50px')->width('50px')->enlargeAble(true),
|
||||
amis()->TableColumn('published_at', __('admin.articles.published_at'))->remark('若无发布时间操作显示,则会自动生成当前发布时间'),
|
||||
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(),
|
||||
|
|
@ -62,9 +87,10 @@ class ArticleController extends AdminController
|
|||
Components::make()->keywordsTagControl('t_ids', __('admin.articles.tags'), 'article_tag'),
|
||||
Components::make()->cropImageControl('cover', __('admin.articles.cover')),
|
||||
Components::make()->sortControl('sort', __('admin.articles.sort')),
|
||||
amis()->DateTimeControl('published_at', __('admin.articles.published_at'))->format('YYYY-MM-DD HH:mm:ss')->description('*若创建时设置显示且未填写,则默认为创建时间'),
|
||||
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'),
|
||||
])->md(4),
|
||||
amis()->Wrapper()->body([
|
||||
Components::make()->fuEditorControl('content', __('admin.articles.content')),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use App\Traits\UploadTrait;
|
||||
|
||||
class IndexController extends AdminController
|
||||
{
|
||||
use UploadTrait;
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Http\Request;
|
||||
use Slowlyo\OwlAdmin\Renderers\Tab;
|
||||
use Slowlyo\OwlAdmin\Renderers\Tabs;
|
||||
|
|
@ -15,7 +16,6 @@ class SettingController extends AdminController
|
|||
public function index()
|
||||
{
|
||||
$page = $this->basePage()->body([
|
||||
Alert::make()->showIcon(true)->body("此处内容仅供演示, 设置项无实际意义,实际开发中请根据实际情况进行修改。"),
|
||||
$this->form(),
|
||||
]);
|
||||
|
||||
|
|
@ -25,18 +25,22 @@ class SettingController extends AdminController
|
|||
public function form()
|
||||
{
|
||||
return $this->baseForm(false)
|
||||
->redirect('')
|
||||
->redirect('')->labelWidth('200px')
|
||||
->api($this->getStorePath())
|
||||
->data(settings()->all())
|
||||
->body(
|
||||
Tabs::make()->tabs([
|
||||
Tab::make()->title('基本设置')->body([
|
||||
TextControl::make()->label('网站名称')->name('site_name'),
|
||||
InputKV::make()->label('附加配置')->name('addition_config'),
|
||||
]),
|
||||
Tab::make()->title('上传设置')->body([
|
||||
TextControl::make()->label('上传域名')->name('upload_domain'),
|
||||
TextControl::make()->label('上传路径')->name('upload_path'),
|
||||
amis()->RadiosControl('upload_disk', '上传驱动')->options([
|
||||
'public'=>'本地存储',
|
||||
'oss' => '阿里云OSS',
|
||||
])->value('public')->required(true),
|
||||
amis()->TextControl('oss_config.access_key_id', '阿里云AccessKeyId')->required(true)->size('lg')->visibleOn('${upload_disk == "oss"}'),
|
||||
amis()->TextControl('oss_config.access_key_secret', '阿里云AccessKeySecret')->required(true)->size('lg')->visibleOn('${upload_disk == "oss"}'),
|
||||
amis()->TextControl('oss_config.bucket', '对象存储Bucket')->required(true)->size('lg')->visibleOn('${upload_disk == "oss"}')->remark('示例: my-bucket'),
|
||||
amis()->TextControl('oss_config.endpoint', '对象存储endpoint')->required(true)->size('lg')->visibleOn('${upload_disk == "oss"}')->remark('示例: oss-cn-shanghai.aliyuncs.com'),
|
||||
amis()->TextControl('oss_config.domain', '自有域名')->size('lg')->visibleOn('${upload_disk == "oss"}')->remark('填写即启用 示例: my-domain.com'),
|
||||
amis()->SwitchControl('oss_config.use_ssl', '开启SSL')->value(false)->visibleOn('${upload_disk == "oss"}'),
|
||||
]),
|
||||
])
|
||||
);
|
||||
|
|
@ -45,12 +49,43 @@ class SettingController extends AdminController
|
|||
public function store(Request $request)
|
||||
{
|
||||
$data = $request->only([
|
||||
'site_name',
|
||||
'addition_config',
|
||||
'upload_domain',
|
||||
'upload_path',
|
||||
'upload_disk',
|
||||
'oss_config'
|
||||
]);
|
||||
|
||||
//上传设置-修改env文件内配置;
|
||||
if(!empty($data['upload_disk'])){
|
||||
$envData['FILESYSTEM_DISK'] = $data['upload_disk'];
|
||||
if($envData['FILESYSTEM_DISK'] == 'oss'){//如果设置为OSS驱动,则配置env变量
|
||||
$envData['OSS_ACCESS_KEY_ID'] = Arr::get($data['oss_config'], 'access_key_id');
|
||||
$envData['OSS_ACCESS_KEY_SECRET'] = Arr::get($data['oss_config'], 'access_key_secret');
|
||||
$envData['OSS_BUCKET'] = Arr::get($data['oss_config'], 'bucket');
|
||||
$envData['OSS_ENDPOINT'] = Arr::get($data['oss_config'], 'endpoint');
|
||||
$envData['OSS_DOMAIN'] = Arr::get($data['oss_config'], 'domain');
|
||||
if(!empty($envData['OSS_DOMAIN'])){
|
||||
$envData['OSS_CNAME'] = 'true';
|
||||
}else{
|
||||
$envData['OSS_CNAME'] = 'false';
|
||||
}
|
||||
$envData['OSS_SSL'] = Arr::get($data['oss_config'], 'use_ssl') ? 'true':'false';
|
||||
}
|
||||
$envPath = base_path() . DIRECTORY_SEPARATOR . '.env';
|
||||
$contentArray = collect(file($envPath, FILE_IGNORE_NEW_LINES));
|
||||
$contentArray->transform(function ($item) use ($envData){
|
||||
foreach ($envData as $key => $value){
|
||||
if(str_contains($item, $key)){
|
||||
|
||||
return $key . '=' . $value;
|
||||
}
|
||||
}
|
||||
return $item;
|
||||
});
|
||||
|
||||
$content = implode("\n", $contentArray->toArray());
|
||||
\File::put($envPath, $content);
|
||||
}
|
||||
|
||||
|
||||
return settings()->adminSetMany($data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,4 +29,15 @@ Route::group([
|
|||
$router->resource('system/keywords', \App\Admin\Controllers\KeywordController::class);
|
||||
|
||||
$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']);
|
||||
$router->post('upload_rich', [\App\Admin\Controllers\IndexController::class, 'uploadRich']);
|
||||
|
||||
$router->post('start_chunk_upload_file', [\App\Admin\Controllers\IndexController::class, 'startChunk']);
|
||||
$router->post('save_chunk_upload_file', [\App\Admin\Controllers\IndexController::class, 'saveChunk']);
|
||||
$router->post('finish_chunk_upload_file', [\App\Admin\Controllers\IndexController::class, 'finishChunk']);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use EloquentFilter\Filterable;
|
||||
use App\Casts\Storage;
|
||||
|
||||
class Ad extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Filterable;
|
||||
|
||||
public const TYPE_OFF = 0; //无跳转
|
||||
public const TYPE_WEB = 1; //网页跳转
|
||||
public const TYPE_APP = 2; //应用跳转
|
||||
public const TYPE_MINI = 3;//小程序跳转
|
||||
|
||||
protected function serializeDate(\DateTimeInterface $date)
|
||||
{
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
protected $casts = [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'published_at' => 'datetime',
|
||||
'is_enable' => 'boolean',
|
||||
'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 => "<span class='label'>无跳转</span>",
|
||||
self::TYPE_WEB => "<span class='label label-info'>网页跳转</span>",
|
||||
self::TYPE_APP => "<span class='label label-warning'>应用跳转</span>",
|
||||
self::TYPE_MINI => "<span class='label label-green'>小程序跳转</span>",
|
||||
'*'=>'其他:${jump_type}'
|
||||
];
|
||||
}
|
||||
|
||||
public static function typeMapLabel()
|
||||
{
|
||||
return [
|
||||
self::TYPE_IN => "<span class='label label-info'>入住缴费</span>",
|
||||
self::TYPE_CONTINUE => "<span class='label label-warning'>续住缴费</span>",
|
||||
self::TYPE_EXIT => "<span class='label label-danger'>离开结算</span>",
|
||||
'*'=>'其他:${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');
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ class Article extends Model
|
|||
'published_at' => 'datetime:Y-m-d H:i:s',
|
||||
'is_enable' => 'boolean',
|
||||
'is_recommend' => 'boolean',
|
||||
'cover' => Storage::class,
|
||||
'appendixes' => 'array',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
|
|
@ -42,6 +42,10 @@ class Article extends Model
|
|||
'appendixes',
|
||||
];
|
||||
|
||||
public function scopeShow(){
|
||||
$q->where('is_enable', true)->where('published_at', '>=', now());
|
||||
}
|
||||
|
||||
public function scopeSort($q)
|
||||
{
|
||||
$q->orderBy('is_recommend', 'desc')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Filters;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use EloquentFilter\ModelFilter;
|
||||
|
||||
class AdFilter extends ModelFilter
|
||||
{
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
public function id($id)
|
||||
{
|
||||
return $this->where('id', $id);
|
||||
}
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
public function remark($remark)
|
||||
{
|
||||
return $this->where('remark','like', '%'.$remark.'%');
|
||||
}
|
||||
|
||||
/**
|
||||
* 位置
|
||||
*/
|
||||
public function address($address)
|
||||
{
|
||||
return $this->where('address', $address);
|
||||
}
|
||||
public function publishedAt($publishedAt){
|
||||
$publishedAt = explode(',',$publishedAt);
|
||||
return $this->where(function($q) use ($publishedAt) {
|
||||
$startAt = Arr::get($publishedAt, 0) ?? null;
|
||||
$endAt = Arr::get($publishedAt, 1) ?? null;
|
||||
if(!empty($startAt)){
|
||||
$q->where('published_at', '>=', $startAt);
|
||||
}
|
||||
if(!empty($endAt)){
|
||||
$q->where('published_at', '<=', $endAt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function createdAt($createdAt){
|
||||
$createdAt = explode(',',$createdAt);
|
||||
return $this->where(function($q) use ($createdAt) {
|
||||
$startAt = Arr::get($createdAt, 0) ?? null;
|
||||
$endAt = Arr::get($createdAt, 1) ?? null;
|
||||
if(!empty($startAt)){
|
||||
$q->where('created_at', '>=', $startAt);
|
||||
}
|
||||
if(!empty($endAt)){
|
||||
$q->where('created_at', '<=', $endAt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function enable($enable){
|
||||
return $this->where('is_enable', $enable);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,17 @@
|
|||
namespace App\Models\Filters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class ArticleFilter extends ModelFilter
|
||||
{
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
public function id($id)
|
||||
{
|
||||
return $this->where('id', $id);
|
||||
}
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
|
|
@ -13,4 +21,60 @@ class ArticleFilter extends ModelFilter
|
|||
{
|
||||
return $this->where('title','like', '%'.$title.'%');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分类下的文章
|
||||
*/
|
||||
public function category($category)
|
||||
{
|
||||
return $this->where('category', $category);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询带有标签的文章
|
||||
*/
|
||||
public function tIds($tIds){
|
||||
$tIds = explode(',',$tIds);
|
||||
return $this->where(function($q) use ($tIds) {
|
||||
foreach ($tIds as $tId) {
|
||||
$q->whereRaw("FIND_IN_SET('".$tId."',t_ids)");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function publishedAt($publishedAt){
|
||||
$publishedAt = explode(',',$publishedAt);
|
||||
return $this->where(function($q) use ($publishedAt) {
|
||||
$startAt = Arr::get($publishedAt, 0) ?? null;
|
||||
$endAt = Arr::get($publishedAt, 1) ?? null;
|
||||
if(!empty($startAt)){
|
||||
$q->where('published_at', '>=', $startAt);
|
||||
}
|
||||
if(!empty($endAt)){
|
||||
$q->where('published_at', '<=', $endAt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function createdAt($createdAt){
|
||||
$createdAt = explode(',',$createdAt);
|
||||
return $this->where(function($q) use ($createdAt) {
|
||||
$startAt = Arr::get($createdAt, 0) ?? null;
|
||||
$endAt = Arr::get($createdAt, 1) ?? null;
|
||||
if(!empty($startAt)){
|
||||
$q->where('created_at', '>=', $startAt);
|
||||
}
|
||||
if(!empty($endAt)){
|
||||
$q->where('created_at', '<=', $endAt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function enable($enable){
|
||||
return $this->where('is_enable', $enable);
|
||||
}
|
||||
|
||||
public function recommend($recommend){
|
||||
return $this->where('is_recommend', $recommend);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class Keyword extends Model
|
|||
{
|
||||
parent::boot();
|
||||
// 监听 Keyword 的创建事件,用于初始化 path 和 lv 字段值
|
||||
static::creating(function ($keyword) {
|
||||
static::saving(function ($keyword) {
|
||||
// 如果创建的是一个根类目
|
||||
if (! $keyword->parent_id) {
|
||||
// 将层级设为 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Admin;
|
||||
|
||||
use App\Models\Ad;
|
||||
use App\Models\Filters\AdFilter;
|
||||
use App\Traits\UploadTrait;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
/**
|
||||
* @method Ad getModel()
|
||||
* @method Ad|\Illuminate\Database\Query\Builder query()
|
||||
*/
|
||||
class AdService extends BaseService
|
||||
{
|
||||
use UploadTrait;
|
||||
|
||||
protected string $modelName = Ad::class;
|
||||
|
||||
protected string $modelFilterName = AdFilter::class;
|
||||
|
||||
protected bool $modelSortAble = true;
|
||||
|
||||
public function store($data): bool
|
||||
{
|
||||
$columns = $this->getTableColumns();
|
||||
$model = $this->getModel();
|
||||
|
||||
$isEnable = Arr::get($data, 'is_enabled');
|
||||
$publishedAt = Arr::get($data, 'published_at');
|
||||
if ($isEnable && empty($publishedAt)) {
|
||||
$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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Services\Admin;
|
|||
|
||||
use App\Models\Article;
|
||||
use App\Models\Filters\ArticleFilter;
|
||||
use App\Traits\UploadTrait;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
/**
|
||||
|
|
@ -12,10 +13,14 @@ use Illuminate\Support\Arr;
|
|||
*/
|
||||
class ArticleService extends BaseService
|
||||
{
|
||||
use UploadTrait;
|
||||
|
||||
protected string $modelName = Article::class;
|
||||
|
||||
protected string $modelFilterName = ArticleFilter::class;
|
||||
|
||||
protected bool $modelSortAble = true;
|
||||
|
||||
public function store($data): bool
|
||||
{
|
||||
$columns = $this->getTableColumns();
|
||||
|
|
@ -27,6 +32,9 @@ class ArticleService extends BaseService
|
|||
$data['published_at'] = now();
|
||||
}
|
||||
|
||||
$data['cover'] = $this->saveImage('cover', 'articles/cover')[0] ?? '';
|
||||
$data['appendixes'] = $this->saveFile('appendixes', 'articles/appendixes');
|
||||
|
||||
foreach ($data as $k => $v) {
|
||||
if (!in_array($k, $columns)) {
|
||||
continue;
|
||||
|
|
@ -50,6 +58,14 @@ class ArticleService extends BaseService
|
|||
$data['published_at'] = now();
|
||||
}
|
||||
|
||||
if(isset($data['cover'])){
|
||||
$data['cover'] = $this->saveImage('cover', 'articles/cover')[0] ?? '';
|
||||
}
|
||||
|
||||
if(isset($data['appendixes'])){
|
||||
$data['appendixes'] = $this->saveFile('appendixes', 'articles/appendixes');
|
||||
}
|
||||
|
||||
foreach ($data as $k => $v) {
|
||||
if (!in_array($k, $columns)) {
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,210 @@
|
|||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use Slowlyo\OwlAdmin\Admin;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
trait UploadTrait
|
||||
{
|
||||
public function uploadImage()
|
||||
{
|
||||
return $this->upload('image');
|
||||
}
|
||||
|
||||
public function uploadFile()
|
||||
{
|
||||
return $this->upload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 富文本内文件上传
|
||||
*/
|
||||
public function uploadRich()
|
||||
{
|
||||
$fromWangEditor = false;
|
||||
$file = request()->file('file');
|
||||
|
||||
if (!$file) {
|
||||
$fromWangEditor = true;
|
||||
$file = request()->file('wangeditor-uploaded-image');
|
||||
if (!$file) {
|
||||
$file = request()->file('wangeditor-uploaded-video');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$file) {
|
||||
return $this->response()->additional(['errno' => 1])->fail(__('admin.upload_file_error'));
|
||||
}
|
||||
|
||||
$path = $file->store(Admin::config('admin.upload.directory.rich'), Admin::config('admin.upload.disk'));
|
||||
|
||||
$link = Storage::disk(Admin::config('admin.upload.disk'))->url($path);
|
||||
|
||||
if ($fromWangEditor) {
|
||||
return $this->response()->additional(['errno' => 0])->success(['url' => $link]);
|
||||
}
|
||||
|
||||
return $this->response()->additional(compact('link'))->success(compact('link'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 存放临时文件目录,按日期区分;
|
||||
*/
|
||||
protected function upload($type = 'file')
|
||||
{
|
||||
$file = request()->file('file');
|
||||
|
||||
if (!$file) {
|
||||
return $this->response()->fail(__('admin.upload_file_error'));
|
||||
}
|
||||
|
||||
$path = $file->store(Admin::config('admin.upload.tem_directory.' . $type).'/'.date('Y-m-d'), Admin::config('admin.upload.disk'));
|
||||
|
||||
return $this->response()->success(['value' => $path]);
|
||||
}
|
||||
|
||||
public function saveImage($field = 'image', $path)
|
||||
{
|
||||
return $this->saveFile($field, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单提交时,转存实际目录,并保留上传时文件名称;文件保存全路径
|
||||
*/
|
||||
public function saveFile($field = 'file', $path)
|
||||
{
|
||||
$file = request()->file($field);
|
||||
|
||||
if (!$file) {
|
||||
$file = request()->get($field);
|
||||
}
|
||||
|
||||
$fileArr = [];
|
||||
//判断是否多个文件;
|
||||
if(is_string($file) || isset($file['id'])){
|
||||
$files = [$file];
|
||||
}else{
|
||||
$files = $file;
|
||||
}
|
||||
|
||||
if($files){
|
||||
foreach($files as $file){
|
||||
if(is_array($file) && isset($file['state'])){
|
||||
switch($file['state']){
|
||||
case 'init':
|
||||
if(strpos($file['value'], 'temporary') !== false){
|
||||
$filePath = $path.'/'.$file['name'];
|
||||
Storage::disk(Admin::config('admin.upload.disk'))->move($file['value'], $filePath);
|
||||
$fileArr[] = Storage::disk(Admin::config('admin.upload.disk'))->url($filePath);
|
||||
}else{
|
||||
$fileArr[] = $file['value'];
|
||||
}
|
||||
break;
|
||||
case 'uploaded':
|
||||
if(isset($file['name'])){
|
||||
$filePath = $path.'/'.$file['name'];
|
||||
if(Str::startsWith($file['value'], ['http://', 'https://'])){
|
||||
$fileUrl = parse_url($file['value']);
|
||||
$fileValue = ltrim($fileUrl['path'], '/');
|
||||
}else{
|
||||
$fileValue = $file['value'];
|
||||
}
|
||||
Storage::disk(Admin::config('admin.upload.disk'))->move($file['value'], $filePath);
|
||||
$fileArr[] = Storage::disk(Admin::config('admin.upload.disk'))->url($filePath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
$fileArr[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $fileArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始分片上传, 生成唯一ID
|
||||
*/
|
||||
public function startChunk()
|
||||
{
|
||||
$type = 'file';
|
||||
$fileName = request()->get('filename', '');
|
||||
$uploadId = md5(time().$fileName);
|
||||
|
||||
//创建临时文件夹
|
||||
if ( Storage::disk(Admin::config('admin.upload.disk'))->exists(Admin::config('admin.upload.tem_directory.' . $type).'/'.$uploadId) === false ) {
|
||||
if ( Storage::disk(Admin::config('admin.upload.disk'))->makeDirectory(Admin::config('admin.upload.tem_directory.' . $type).'/'.$uploadId) === false ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->response()->success(['uploadId' => $uploadId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存分片
|
||||
*/
|
||||
public function saveChunk()
|
||||
{
|
||||
$type = 'file';
|
||||
|
||||
$file = request()->file('file');
|
||||
$uploadId = request()->get('uploadId');
|
||||
$partNumber = request()->get('partNumber');
|
||||
$partSize = request()->get('partSize');
|
||||
// dd($file);
|
||||
$fileName = $file->getClientOriginalName();
|
||||
|
||||
//判断该分片是否已存在,
|
||||
$dirPath = Admin::config('admin.upload.tem_directory.' . $type).'/'.$uploadId;
|
||||
if(Storage::disk(Admin::config('admin.upload.disk'))->exists($dirPath . '/'.$fileName.'_'.$partNumber)){
|
||||
return $this->response()->fail(__('admin.upload_file_error'));
|
||||
}else{
|
||||
//验证分片大小-todo
|
||||
$path = $file->storeAs($dirPath, $fileName.'_'.$partNumber, Admin::config('admin.upload.disk'));
|
||||
$realPath = Storage::disk(Admin::config('admin.upload.disk'))->url($path);
|
||||
$eTag = md5_file($realPath);
|
||||
return $this->response()->success(['eTag' => $eTag]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成分片
|
||||
*/
|
||||
public function finishChunk()
|
||||
{
|
||||
$type = 'file';
|
||||
//合并文件
|
||||
$fileName = request()->get('filename', '');
|
||||
$uploadId = request()->get('uploadId', '');
|
||||
$partList = request()->get('partList', []);
|
||||
|
||||
$basePath = Admin::config('admin.upload.tem_directory.' . $type).'/'.$uploadId;
|
||||
$realPath = 'chunk/'.$fileName;
|
||||
|
||||
//获取分片列表中序号,查看分片是否都完成上传
|
||||
$partNumberList = Arr::pluck($partList, 'partNumber');
|
||||
|
||||
if(max($partNumberList) === count($partNumberList)){
|
||||
//判断是否已存在同名文件,进行删除
|
||||
if(Storage::disk(Admin::config('admin.upload.disk'))->exists($realPath)){
|
||||
$realPath = 'chunk/(1)'.$fileName;
|
||||
}
|
||||
for($i = 1; $i<=count($partNumberList); $i++){
|
||||
$_file = Storage::disk(Admin::config('admin.upload.disk'))->get($basePath.'/'.$fileName.'_'.$i);
|
||||
Storage::disk(Admin::config('admin.upload.disk'))->append($realPath, $_file, null);
|
||||
}
|
||||
//删除分片文件夹
|
||||
Storage::disk(Admin::config('admin.upload.disk'))->deleteDirectory($basePath);
|
||||
|
||||
$value = Storage::disk(Admin::config('admin.upload.disk'))->url($realPath);
|
||||
|
||||
return $this->response()->success(['value'=>$value]);
|
||||
}else{
|
||||
return $this->response()->fail(__('admin.upload_file_error'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"alphasnow/aliyun-oss-laravel": "^4.7",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"laravel/framework": "^10.10",
|
||||
"laravel/sanctum": "^3.3",
|
||||
|
|
|
|||
|
|
@ -4,8 +4,143 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "ec2cedc62465f8a6d60ba0b0f78581dd",
|
||||
"content-hash": "b2333ae7a977ba073ff6ef0f01f5de43",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aliyuncs/oss-sdk-php",
|
||||
"version": "v2.6.0",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/aliyuncs/oss-sdk-php/v2.6.0/aliyuncs-oss-sdk-php-v2.6.0.zip",
|
||||
"reference": "572d0f8e099e8630ae7139ed3fdedb926c7a760f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "*",
|
||||
"satooshi/php-coveralls": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"OSS\\": "src/OSS"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Aliyuncs",
|
||||
"homepage": "http://www.aliyun.com"
|
||||
}
|
||||
],
|
||||
"description": "Aliyun OSS SDK for PHP",
|
||||
"homepage": "http://www.aliyun.com/product/oss/",
|
||||
"time": "2022-08-03T08:06:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "alphasnow/aliyun-oss-flysystem",
|
||||
"version": "3.3.3",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/alphasnow/aliyun-oss-flysystem/3.3.3/alphasnow-aliyun-oss-flysystem-3.3.3.zip",
|
||||
"reference": "ac62f862cb743ca76f7c3c146ffdd8d52af86153",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"aliyuncs/oss-sdk-php": "^2.5",
|
||||
"league/flysystem": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.6",
|
||||
"mockery/mockery": "^1.5",
|
||||
"php-coveralls/php-coveralls": "*",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"vlucas/phpdotenv": "^5.4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"AlphaSnow\\Flysystem\\Aliyun\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alpha Snow",
|
||||
"email": "wind91@foxmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Flysystem adapter for the Aliyun storage",
|
||||
"homepage": "https://alphasnow.github.io/aliyun-oss-flysystem/",
|
||||
"keywords": [
|
||||
"adapter",
|
||||
"aliyun",
|
||||
"filesystem",
|
||||
"oss"
|
||||
],
|
||||
"time": "2023-06-29T08:45:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "alphasnow/aliyun-oss-laravel",
|
||||
"version": "4.7.1",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/alphasnow/aliyun-oss-laravel/4.7.1/alphasnow-aliyun-oss-laravel-4.7.1.zip",
|
||||
"reference": "d4f5885bcff8c7a5c43be118e749a85fe5eb6a99",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"alphasnow/aliyun-oss-flysystem": "^3.3",
|
||||
"php": "^8.0.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.12",
|
||||
"mockery/mockery": "^1.5",
|
||||
"orchestra/testbench": "^7.13",
|
||||
"php-coveralls/php-coveralls": "*",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"AlphaSnow\\LaravelFilesystem\\Aliyun\\AliyunServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"AlphaSnow\\LaravelFilesystem\\Aliyun\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "alphasnow",
|
||||
"email": "wind91@foxmail.com"
|
||||
}
|
||||
],
|
||||
"description": "alibaba cloud object storage service for laravel",
|
||||
"homepage": "https://alphasnow.github.io/aliyun-oss-laravel/",
|
||||
"keywords": [
|
||||
"aliyun",
|
||||
"filesystems",
|
||||
"laravel",
|
||||
"oss",
|
||||
"storage"
|
||||
],
|
||||
"time": "2022-12-03T14:27:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.11.0",
|
||||
|
|
|
|||
|
|
@ -54,13 +54,19 @@ return [
|
|||
],
|
||||
|
||||
'upload' => [
|
||||
'disk' => 'public',
|
||||
'disk' => env("FILESYSTEM_DISK", 'public'),
|
||||
// 文件上传目录
|
||||
'directory' => [
|
||||
'image' => 'images',
|
||||
'file' => 'files',
|
||||
'rich' => 'rich',
|
||||
],
|
||||
// 临时目录
|
||||
'tem_directory' => [
|
||||
'image' => 'temporary/images',
|
||||
'file' => 'temporary/file',
|
||||
'rich' => 'temporary/rich',
|
||||
]
|
||||
],
|
||||
|
||||
'https' => env('ADMIN_HTTPS', false),
|
||||
|
|
|
|||
|
|
@ -56,6 +56,22 @@ return [
|
|||
'throw' => false,
|
||||
],
|
||||
|
||||
"oss" => [
|
||||
"driver" => "oss",
|
||||
"access_key_id" => env("OSS_ACCESS_KEY_ID"), // 必填, 阿里云的AccessKeyId
|
||||
"access_key_secret" => env("OSS_ACCESS_KEY_SECRET"), // 必填, 阿里云的AccessKeySecret
|
||||
"bucket" => env("OSS_BUCKET"), // 必填, 对象存储的Bucket, 示例: my-bucket
|
||||
"endpoint" => env("OSS_ENDPOINT"), // 必填, 对象存储的Endpoint, 示例: oss-cn-shanghai.aliyuncs.com
|
||||
"internal" => env("OSS_INTERNAL", null), // 选填, 内网上传地址,填写即启用 示例: oss-cn-shanghai-internal.aliyuncs.com
|
||||
"domain" => env("OSS_DOMAIN", null), // 选填, 绑定域名,填写即启用 示例: oss.my-domain.com
|
||||
"is_cname" => env("OSS_CNAME", false), // 选填, 若Endpoint为自定义域名,此项要为true,见:https://github.com/aliyun/aliyun-oss-php-sdk/blob/572d0f8e099e8630ae7139ed3fdedb926c7a760f/src/OSS/OssClient.php#L113C1-L122C78
|
||||
"prefix" => env("OSS_PREFIX", ""), // 选填, 统一存储地址前缀
|
||||
"use_ssl" => env("OSS_SSL", false), // 选填, 是否使用HTTPS
|
||||
"reverse_proxy" => env("OSS_REVERSE_PROXY", false), // 选填, 域名是否使用NGINX代理绑定
|
||||
"throw" => env("OSS_THROW", true), // 选填, 是否抛出引起错误的异常,默认出现错误时,不抛出异常仅返回false
|
||||
"options" => [], // 选填, 添加全局配置参数, 示例: [\OSS\OssClient::OSS_CHECK_MD5 => false]
|
||||
"macros" => [] // 选填, 添加自定义Macro, 示例: [\App\Macros\ListBuckets::class, \App\Macros\CreateBucket::class]
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('ads', function (Blueprint $table) {
|
||||
$table->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');
|
||||
}
|
||||
};
|
||||
|
|
@ -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],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class KeywordSeeder extends Seeder
|
|||
['key' => 'article_category', 'name' => '文章分类', 'list' => [
|
||||
|
||||
]],
|
||||
['key' => 'article_tag', 'name' => '文章标签', 'list' => [
|
||||
['key' => 'article_tag', 'name' => '文章标签', 'list' => [//标签value填写色号,指定标签颜色
|
||||
|
||||
]],
|
||||
['key' => 'banner_address', 'name' => '广告位置', 'list' => [
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ return [
|
|||
'cancel' => '取消',
|
||||
'please_login' => '请先登录',
|
||||
'unauthorized' => '无权访问',
|
||||
'id' => '主键',
|
||||
'id' => 'ID',
|
||||
|
||||
'components' => [
|
||||
'content' => '内容',
|
||||
|
|
@ -72,7 +72,8 @@ return [
|
|||
'enabled' => '已启用',
|
||||
'disabled' => '已禁用',
|
||||
],
|
||||
'tag' => '标签'
|
||||
'tag' => '标签',
|
||||
'files' => '文件'
|
||||
],
|
||||
|
||||
'code_generators' => [
|
||||
|
|
@ -273,7 +274,7 @@ return [
|
|||
'parent_keyword' => '父级关键字',
|
||||
],
|
||||
'articles' => [
|
||||
'id' => '主键',
|
||||
'id' => '主键ID',
|
||||
'title' => '标题',
|
||||
'content' => '内容',
|
||||
'cover' =>'封面',
|
||||
|
|
@ -285,6 +286,26 @@ return [
|
|||
'is_enable' => '显示',
|
||||
'is_recommend' => '推荐',
|
||||
'sort' => '排序',
|
||||
'appendixes' => '附件'
|
||||
'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'=> '小程序路径'
|
||||
],
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -12,5 +12,5 @@ return [
|
|||
'keywords' => '数据字典',
|
||||
'web_content' => '内容管理',
|
||||
'articles' => '文章管理',
|
||||
'banners' => '广告管理',
|
||||
'ads' => '广告管理',
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in New Issue