1
0
mirror of https://github.com/cjango/dcat-vue.git synced 2025-12-06 14:20:03 +08:00

first commit

This commit is contained in:
weiwait
2022-06-03 16:51:16 +08:00
commit e421e967a0
19 changed files with 2073 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
.DS_Store
phpunit.phar
/vendor
composer.phar
composer.lock
*.project
.idea/

55
README.md Normal file
View File

@@ -0,0 +1,55 @@
# Dcat Admin Extension
##### 此扩展为大合一扩展以后使用vue3构建的组件都将合并在一起
### 演示地址
[demo: http://dcat.weiwait.cn (admin:admin)](http://dcat.weiwait.cn/admin/demo-settings 'user: admin psw: admin')
### 依赖扩展
[freyo/flysystem-qcloud-cos-v5](https://github.com/freyo/flysystem-qcloud-cos-v5)
[overtrue/laravel-filesystem-qiniu](https://github.com/overtrue/laravel-filesystem-qiniu)
[iiDestiny/laravel-filesystem-oss](https://github.com/iiDestiny/laravel-filesystem-oss)
### 通过 composer 安装扩展
```shell
composer require weiwait/dcat-vue
```
### 通过选项卡使用
```php
public function index(Content $content): Content
{
$tab = Tab::make();
$tab->add('文件存储', new \Weiwait\DcatVue\Forms\FilesystemConfig());
return $content->title('配置')
->body($tab->withCard());
}
```
### 通过一级菜单使用
![](https://github.com/weiwait/images/blob/main/dcat-smtp-menu.png?raw=true)
### 示例图片
![示例图片](https://raw.githubusercontent.com/weiwait/images/main/dcat-filesystem-config.png)
### 直传表单组件
```php
// 默认替换了原有的组件
$form->file('file');
$form->mutipleFile('files');
```
[comment]: <> (### Donate)
[comment]: <> (![示例图片]&#40;https://github.com/weiwait/images/blob/main/donate.png?raw=true&#41;)
### Dcat-admin 扩展列表
1. [单图裁剪](https://github.com/weiwait/dcat-cropper)
2. [区划级联+坐标拾取](https://github.com/weiwait/dcat-distpicker)
3. [smtp快速便捷配置](https://github.com/weiwait/dcat-smtp)
4. [sms channel 快速便捷配置](https://github.com/weiwait/dcat-easy-sms)

35
composer.json Normal file
View File

@@ -0,0 +1,35 @@
{
"name": "weiwait/dcat-vue",
"alias": "",
"description": "基于vue3构建的综合型扩展",
"type": "library",
"keywords": ["dcat-admin", "extension", "filesystem", "file-upload"],
"homepage": "https://github.com/weiwait/dcat-vue",
"license": "MIT",
"authors": [
{
"name": "weiwait",
"email": "mail@weiwait.cn"
}
],
"require": {
"php": ">=8.0",
"dcat/laravel-admin": "~2.0",
"iidestiny/laravel-filesystem-oss": "^3.1",
"overtrue/laravel-filesystem-qiniu": "^2.1",
"freyo/flysystem-qcloud-cos-v5": "^2.0"
},
"autoload": {
"psr-4": {
"Weiwait\\DcatVue\\": "src/"
}
},
"extra": {
"dcat-admin": "Weiwait\\DcatVue\\DcatVueServiceProvider",
"laravel": {
"providers": [
"Weiwait\\DcatVue\\DcatVueServiceProvider"
]
}
}
}

View File

@@ -0,0 +1 @@
.file-list-wrap[data-v-04125442]{margin-top:2px!important}

1235
resources/assets/js/index.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
@php($id = $column . random_int(123456, 987654))
<div class="{{$viewClass['form-group']}}" >
<label class="{{$viewClass['label']}} control-label pt-0">{!! $label !!}</label>
<div class="{{$viewClass['field']}}" id="{{ $id }}">
</div>
</div>
<script type="module" id="{{$column}}">
import app from '/vendor/dcat-admin-extensions/weiwait/dcat-vue/js/index.js';
const App = app()
App.provide('provides', @json($provides, true))
App.mount('#{{ $id }}')
</script>

View File

@@ -0,0 +1,95 @@
<?php
namespace Weiwait\DcatVue;
use Dcat\Admin\Extend\ServiceProvider;
use Dcat\Admin\Admin;
use Dcat\Admin\Form;
use Illuminate\Support\Facades\Event;
use Weiwait\DcatVue\Field\File;
use Weiwait\DcatVue\Field\MultipleFile;
use Weiwait\DcatVue\Field\Vue;
use Weiwait\DcatVue\Models\FilesystemConfig;
class DcatVueServiceProvider extends ServiceProvider
{
protected $js = [
'js/index.js',
];
protected $css = [
'css/index.css',
];
public function register()
{
//
}
public function init()
{
parent::init();
$this->hackConfigs();
// Form::extend('vue', Vue::class);
Form::extend('file', File::class);
Form::extend('multipleFile', MultipleFile::class);
Admin::asset()->css(Admin::asset()->getAlias('@weiwait.dcat-vue')['css']);
$this->publishable();
}
public function settingForm()
{
return new Setting($this);
}
protected function hackConfigs()
{
app()->booted(function () {
config()->set('filesystems.disks.oss', [
'access_key' => FilesystemConfig::get('oss_access_key'),
'secret_key' => FilesystemConfig::get('oss_secret_key'),
'endpoint' => FilesystemConfig::get('oss_endpoint'),
'bucket' => FilesystemConfig::get('oss_bucket'),
'driver' => 'oss',
'root' => '',
'isCName' => false,
]);
config()->set('filesystems.disks.qiniu', [
'access_key' => FilesystemConfig::get('qiniu_access_key'),
'secret_key' => FilesystemConfig::get('qiniu_secret_key'),
'domain' => FilesystemConfig::get('qiniu_domain'),
'bucket' => FilesystemConfig::get('qiniu_bucket'),
'driver' => 'qiniu',
]);
config()->set('filesystems.disks.cosv5', [
'driver' => 'cosv5',
'region' => FilesystemConfig::get('cos_region'),
'credentials' => [
'appId' => FilesystemConfig::get('cos_app_id'),
'secretId' => FilesystemConfig::get('cos_secret_id'),
'secretKey' => FilesystemConfig::get('cos_secret_key'),
'token' => null,
],
'timeout' => 60,
'connect_timeout' => 60,
'bucket' => FilesystemConfig::get('cos_bucket'),
'cdn' => FilesystemConfig::get('cos_cdn'),
'scheme' => config('admin.https') ? 'https' : 'http',
'read_from_cdn' => false,
'cdn_key' => null,
'encrypt' => false,
]);
config()->set('filesystems.default', FilesystemConfig::get('disk', config('filesystems.default')));
});
Event::listen('admin:booted', function () {
config()->set('admin.upload.disk', FilesystemConfig::get('disk', config('admin.upload.disk')));
});
}
}

66
src/Field/File.php Normal file
View File

@@ -0,0 +1,66 @@
<?php
namespace Weiwait\DcatVue\Field;
use Dcat\Admin\Form\Field;
use Weiwait\DcatVue\Models\WeiwaitUpload;
class File extends Field\File
{
protected $view = 'weiwait.dcat-vue::file';
protected string $disk;
protected function prepareInputValue($file)
{
WeiwaitUpload::query()->whereIn('name', (array) $file)->delete();
return parent::prepareInputValue($file);
}
public function render()
{
if (!$this->shouldRender()) {
return '';
}
$this->setDefaultClass();
$this->callComposing();
$this->withScript();
$this->withProvides();
$this->addVariables([
'provides' => $this->variables(),
]);
return view($this->view(), $this->variables());
}
protected function formatAttributes()
{
return $this->attributes;
}
protected function withProvides()
{
$disk = config('admin.upload.disk', config('filesystems.default'));
$this->addVariables([
'component' => 'File',
'multiple' => false,
'disk' => $this->disk ?? $disk,
'dir' => $this->getDirectory(),
'uploaded_url' => route('dcat.admin.weiwait.file.uploaded'),
'obs_config_url' => route('dcat.admin.weiwait.file.obs-config'),
]);
}
public function disk($disk): self
{
$this->disk = $disk;
return parent::disk($disk);
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace Weiwait\DcatVue\Field;
use Dcat\Admin\Form\Field;
use Weiwait\DcatVue\Models\WeiwaitUpload;
class MultipleFile extends Field\MultipleFile
{
protected $view = 'weiwait.dcat-vue::file';
protected string $disk;
protected function prepareInputValue($file): array
{
WeiwaitUpload::query()->whereIn('name', (array) $file)->delete();
return parent::prepareInputValue($file);
}
public function render()
{
if (!$this->shouldRender()) {
return '';
}
$this->setDefaultClass();
$this->callComposing();
$this->withScript();
$this->withProvides();
$this->addVariables([
'provides' => $this->variables(),
]);
return view($this->view(), $this->variables());
}
protected function formatAttributes()
{
return $this->attributes;
}
protected function withProvides()
{
$disk = config('admin.upload.disk', config('filesystems.default'));
$this->addVariables([
'component' => 'File',
'multiple' => true,
'disk' => $this->disk ?? $disk,
'dir' => $this->getDirectory(),
'uploaded_url' => route('dcat.admin.weiwait.file.uploaded'),
'obs_config_url' => route('dcat.admin.weiwait.file.obs-config'),
]);
}
public function disk($disk): self
{
$this->disk = $disk;
return parent::disk($disk);
}
}

100
src/Field/Vue.php Normal file
View File

@@ -0,0 +1,100 @@
<?php
namespace Weiwait\DcatVue\Field;
use Dcat\Admin\Form\Field;
use Dcat\Admin\Support\Helper;
use Dcat\Admin\Widgets\Checkbox as WidgetCheckbox;
class Vue extends Field\Checkbox
{
protected $view = 'weiwait.dcat-vue::index';
protected array $watch = [];
public function render()
{
$this->checkboxRender();
$this->selectRender();
if (! $this->shouldRender()) {
return '';
}
$this->setDefaultClass();
$this->callComposing();
$this->withScript();
$this->addVariables([
'checked' => $this->checked,
'watch' => $this->watch,
]);
$this->addVariables([
'provides' => $this->variables(),
]);
return view($this->view(), $this->variables());
}
protected function formatAttributes()
{
return $this->attributes;
}
public function disabled($disabled): Vue
{
$this->addVariables([
'disabled' => (array) $disabled
]);
return $this;
}
public function watch($column, $handler): Vue
{
$this->watch[] = [
'type' => "$column:change",
'handler' => $handler,
];
return $this;
}
protected function checkboxRender()
{
if ($this->options instanceof \Closure) {
$this->options(
$this->options->call($this->values(), $this->value(), $this)
);
}
$this->addCascadeScript();
}
protected function selectRender()
{
$this->addDefaultConfig([
'allowClear' => true,
'placeholder' => [
'id' => '',
'text' => $this->placeholder(),
],
]);
$this->formatOptions();
$this->addVariables([
'options' => $this->options,
'groups' => $this->groups,
'configs' => $this->config,
'cascadeScript' => $this->getCascadeScript(),
]);
$this->initSize();
$this->attribute('data-value', implode(',', Helper::array($this->value())));
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace Weiwait\DcatVue\Forms;
use Dcat\Admin\Widgets\Form;
use Weiwait\DcatVue\Models\FilesystemConfig as Model;
class FilesystemConfig extends Form
{
/**
* Handle the form request.
*
* @param array $input
*
* @return mixed
*/
public function handle(array $input)
{
return Model::adminFormHandle($this, $input);
}
/**
* Build a form here.
*/
public function form()
{
$this->radio('disk', '存储位置')
->options(['public' => '本地', 'oss' => '阿里云', 'cosv5' => '腾讯云', 'qiniu' => '七牛云'])
->default('public')
->when('oss', function (Form $form) {
$form->text('oss_access_key', 'AccessKey');
$form->text('oss_secret_key', 'SecretKey');
$form->text('oss_bucket', 'Bucket');
$form->text('oss_endpoint', 'Endpoint');
})
->when('cosv5', function (Form $form) {
$form->text('cos_app_id', 'Appid');
$form->text('cos_secret_id', 'SecretId');
$form->text('cos_secret_key', 'SecretKey');
$form->text('cos_region', 'Region');
$form->text('cos_bucket', 'Bucket');
$form->text('cos_cdn', 'CDN');
})
->when('qiniu', function (Form $form) {
$form->text('qiniu_access_key', 'AccessKey');
$form->text('qiniu_secret_key', 'SecretKey');
$form->text('qiniu_bucket', 'Bucket');
$form->text('qiniu_domain', '域名');
});
}
/**
* The data of the form.
*
* @return array
*/
public function default(): array
{
return Model::get([
'disk',
'oss_access_key',
'oss_secret_key',
'oss_endpoint',
'oss_bucket',
'qiniu_access_key',
'qiniu_secret_key',
'qiniu_bucket',
'qiniu_domain',
'cos_app_id',
'cos_secret_id',
'cos_secret_key',
'cos_region',
'cos_bucket',
'cos_cdn',
]);
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Weiwait\DcatVue\Http\Controllers;
use Dcat\Admin\Layout\Content;
use Dcat\Admin\Admin;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Storage;
use Qiniu\Config;
use Weiwait\DcatVue\Forms\FilesystemConfig;
use Weiwait\DcatVue\Models\WeiwaitUpload;
class DcatVueController extends Controller
{
public function index(Content $content)
{
return $content
->title('Title')
->description('Description')
->body(Admin::view('weiwait.dcat-vue::index'));
}
public function uploaded(Request $request)
{
WeiwaitUpload::clearUnusedFiles();
WeiwaitUpload::query()
->insert(array_map(fn($item) => ['name' => $item, 'created_at' => now(), 'disk' => $request['disk']],
(array)$request['files']
));
}
public function obsConfig(Request $request)
{
switch ($request['disk']) {
case 'oss':
return json_decode(
Storage::disk('oss')->getAdapter()->signatureConfig(prefix: config('admin.upload.directory.file'), expire: 3600),
true
);
case 'qiniu':
$url = (new Config())->getUpHost(
config('filesystems.disks.qiniu.access_key'),
config('filesystems.disks.qiniu.bucket')
);
return [
'token' => Storage::disk('qiniu')->getAdapter()->getUploadToken($request['filename'], 3600),
'host' => $url,
];
case 'cos':
case 'cosv5':
$url = parse_url(Storage::disk('cosv5')->url(''));
return [
'auth' => Storage::disk('cosv5')->getFederationTokenV3($request['filename']),
'host' => $url['scheme'] . '://' . $url['host'] . '/' . $request['filename'],
];
default:
return [
'host' => route('dcat.admin.weiwait.file.upload'),
];
}
}
public function upload(Request $request)
{
if ($file = $request->file('file')) {
$name = basename($request['key']);
$path = dirname($request['key']);
Storage::disk()->putFileAs($path, $file, $name);
return [
'key' => $request['key']
];
}
return response($request->all(), 400);
}
public function filesystem(Content $content): Content
{
return $content
->body(new FilesystemConfig());
}
}

16
src/Http/routes.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
use Weiwait\DcatVue\Http\Controllers;
use Illuminate\Support\Facades\Route;
// 文件存储配置表单
Route::get('dcat-filesystem-config', [Controllers\DcatVueController::class, 'filesystem']);
// 各个驱动直传配置
Route::get('weiwait/file/obs-config', [Controllers\DcatVueController::class, 'obsConfig'])
->name('weiwait.file.obs-config');
// 文件上传后回调
Route::post('weiwait/file/uploaded', [Controllers\DcatVueController::class, 'uploaded'])
->name('weiwait.file.uploaded');
// 本地上传
Route::post('weiwait/file/upload', [Controllers\DcatVueController::class, 'upload'])
->name('weiwait.file.upload');

View File

@@ -0,0 +1,64 @@
<?php
namespace Weiwait\DcatVue\Models;
use Dcat\Admin\Widgets\Form;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
class FilesystemConfig extends Model
{
const INDEPENDENT = "independent";
protected $guarded = [];
/**
* key 或者数组 keys 获取配置
*/
public static function get($keys, $default = '')
{
if (is_array($keys)) {
$data = [];
foreach ($keys as $key) {
$data[$key] = self::get($key);
}
return $data;
}
if (null == $value = Cache::get('setting.wechat.config.' . $keys)) {
$value = self::query()->where('key', $keys)->value('value');
Cache::put('setting.wechat.config.' . $keys, $value, now()->addDay());
}
return $value ?? $default;
}
/**
* 设置配置项
*/
public static function set(array $settings)
{
foreach ($settings as $key => $value) {
self::query()->updateOrCreate(['key' => $key], ['value' => $value ?? '']);
Cache::put('setting.wechat.config.' . $key, $value, now()->addDay());
}
}
public static function adminFormHandle(Form $form, array $input): \Dcat\Admin\Http\JsonResponse
{
try {
self::set($input);
} catch (\Exception $exception) {
return $form
->response()
->error($exception->getMessage());
}
return $form
->response()
->success('修改成功');
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Weiwait\DcatVue\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class WeiwaitUpload extends Model
{
protected $fillable = [
'name'
];
public static function clearUnusedFiles()
{
self::query()->where('created_at', '<', now()->subDay())
->get()
->map(function (self $file) {
$file->delete();
Storage::disk($file->disk)->delete($file->name);
});
}
}

45
src/Setting.php Normal file
View File

@@ -0,0 +1,45 @@
<?php
namespace Weiwait\DcatVue;
use Dcat\Admin\Extend\Setting as Form;
use Dcat\Admin\Models\Menu;
class Setting extends Form
{
public function form()
{
$this->switch('independent', '独立菜单')
->default(FilesystemConfig::get(FilesystemConfig::INDEPENDENT, false));
$this->text('menu_name', '菜单名称')->default(__('文件存储'));
}
public function handle(array $input): \Dcat\Admin\Http\JsonResponse
{
FilesystemConfig::set(['independent' => (boolean)$input['independent']]);
/** @var Menu $menu */
$menu = config('admin.database.menu_model');
if ($input['independent']) {
$res = $menu::query()->updateOrCreate(
['uri' => 'dcat-filesystem-config'],
[
'title' => $input['menu_name'],
'show' => 1,
'icon' => 'fa-envelope',
]
);
FilesystemConfig::set(['independent_menu_id' => $res->getKey()]);
return $this->response()->success('菜单已生成')->refresh();
} else {
if ($menu = $menu::query()->find(FilesystemConfig::get('independent_menu_id'))) {
$menu->delete();
}
return $this->response()->success('菜单已删除')->refresh();
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFielsystemConfigTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('filesystem_configs', function (Blueprint $table) {
$table->id();
$table->string('key', 50)->unique()->comment('配置key');
$table->string('name')->default('')->comment('配置名称');
$table->text('value')->comment('配置值');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('filesystem_configs');
}
}

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateWeiwaitUpload extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (!Schema::hasTable('weiwait_uploads')) {
Schema::create('weiwait_uploads', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->comment('文件');
$table->string('disk')->nullable()->comment('磁盘');
$table->timestamps();
});
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('weiwait_uploads');
}
}

12
version.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
return [
'1.0.0' => [
'Initialize extension.',
],
'1.1.0' => [
'增加文件直传表单组件',
'create_weiwait_uploads_table.php',
'create_filesystem_configs_table.php',
]
];