7 Commits
v2.6 ... v2.6.1

Author SHA1 Message Date
JaguarJack
fb579a5771 update:新增选择数据权限默认选项#gitee#issueI3NNH1 2021-04-24 20:35:33 +08:00
JaguarJack
4e1e040936 add:新增导入导出公共接口 2021-04-24 20:32:36 +08:00
JaguarJack
38e10896d4 update:新增模型导入方法 2021-04-24 20:32:05 +08:00
JaguarJack
ba1595f75f update:新增本地上传方法 2021-04-24 20:31:45 +08:00
JaguarJack
566514f729 delete:transtrait 2021-04-24 20:31:19 +08:00
JaguarJack
48c41f7948 add:新增excel的导入导出组件 2021-04-24 20:30:28 +08:00
JaguarJack
f67a4f33d5 add:新增导入组件 2021-04-24 20:29:33 +08:00
15 changed files with 586 additions and 55 deletions

View File

@@ -0,0 +1,47 @@
<?php
namespace catchAdmin\cms\table;
use catcher\CatchTable;
use catcher\library\table\Actions;
use catcher\library\table\HeaderItem;
use catcher\library\table\Search;
class Category extends CatchTable
{
public function table()
{
// TODO: Implement table() method.
return $this->getTable('category')
->header([
HeaderItem::label('分类名称')->prop('name'),
HeaderItem::label('自定义链接')->prop('url'),
HeaderItem::label('栏目类型')->prop('type')->component('type'),
HeaderItem::label('投稿')->prop('is_can_contribute')->withSwitchComponent(),
HeaderItem::label('评论')->prop('is_can_comment')->withSwitchComponent(),
HeaderItem::label('状态')->prop('status')->withSwitchComponent(),
HeaderItem::label('权重')->prop('weight')->withEditNumberComponent(),
HeaderItem::label('创建时间')->prop('created_at'),
HeaderItem::label('操作')->actions([
Actions::update(),
Actions::delete()
])
])
->withActions([
Actions::create()
])
->withSearch([
Search::label('分类名称')->name('请输入分类名称'),
Search::label('状态')->name('请选择状态'),
])
->toTreeTable()
->render();
}
public function form()
{
// TODO: Implement form() method.
}
}

View File

@@ -41,7 +41,8 @@ class Role extends Form
self::select('data_range', '数据权限') self::select('data_range', '数据权限')
->placeholder('请选择数据权限') ->placeholder('请选择数据权限')
->options( ->options(
self::options()->add('全部数据权限', Roles::ALL_DATA) self::options()->add('请选择数据权限', 0)
->add('全部数据权限', Roles::ALL_DATA)
->add('自定义数据权限', Roles::SELF_CHOOSE) ->add('自定义数据权限', Roles::SELF_CHOOSE)
->add('仅本人数据权限', Roles::SELF_DATA) ->add('仅本人数据权限', Roles::SELF_DATA)
->add('本部门数据权限', Roles::DEPARTMENT_DATA) ->add('本部门数据权限', Roles::DEPARTMENT_DATA)

View File

@@ -0,0 +1,105 @@
<?php
namespace catchAdmin\system\controller;
use catcher\base\CatchController;
use catcher\CatchResponse;
use think\Request;
class Excel extends CatchController
{
/**
* 导出
*
* @time 2021年04月22日
* @param Request $request
* @return \think\response\Json
*/
public function export(Request $request): \think\response\Json
{
$fields = $this->resetFields(\json_decode($request->post('fields'), true));
$excel = app()->make($request->post('model'))
->field(array_column($fields, 'field'))
->select()
->each(function (&$item, $key) use ($fields) {
foreach ($fields as $field) {
if (isset($field['options']) && count($field['options'])) {
$options = $this->valueToLabel($field['options']);
$item[$field['field']] = $options[$item[$field['field']]] ?? '';
}
}
})->export(array_column($fields, 'name'));
return CatchResponse::success($excel);
}
/**
* 导入
*
* @time 2021年04月23日
* @param Request $request
* @return \think\response\Json
*/
public function import(Request $request): \think\response\Json
{
return CatchResponse::success(app()->make($request->post('model'))
->import(
\json_decode($request->post('fields'), 'field'),
$request->file('file')
));
}
/**
* value => label
*
* @time 2021年04月22日
* @param array $options
* @return array
*/
protected function valueToLabel(array $options): array
{
$p = [];
foreach ($options as $option) {
$p[$option['value']] = $option['label'];
}
return $p;
}
/**
*label => value
*
* @time 2021年04月22日
* @param array $options
* @return array
*/
protected function labelToValue(array $options): array
{
$p = [];
foreach ($options as $option) {
$p[$option['label']] = $option['value'];
}
return $p;
}
/**
* 重组 fields
*
* @time 2021年04月22日
* @param array $fields
* @return array
*/
protected function resetFields(array $fields): array
{
$f = [];
foreach ($fields as $field) {
$f[$field['field']] = $field;
}
return $f;
}
}

View File

@@ -48,6 +48,11 @@ $router->group(function () use ($router) {
$router->put('modules/<module>', '\catchAdmin\system\controller\Module@disOrEnable'); $router->put('modules/<module>', '\catchAdmin\system\controller\Module@disOrEnable');
$router->put('cache/modules', '\catchAdmin\system\controller\Module@cache'); $router->put('cache/modules', '\catchAdmin\system\controller\Module@cache');
$router->delete('clear/modules', '\catchAdmin\system\controller\Module@clear'); $router->delete('clear/modules', '\catchAdmin\system\controller\Module@clear');
// excel 导入&导出通用
$router->post('excel/export', '\catchAdmin\system\controller\Excel@export');
$router->post('excel/import', '\catchAdmin\system\controller\Excel@import');
})->middleware('auth'); })->middleware('auth');
// 获取 table // 获取 table

View File

@@ -84,6 +84,21 @@ class CatchUpload
} }
} }
/**
* 上传到 Local
*
* @time 2021年04月21日
* @param $file
* @return string
*/
public function toLocal($file): string
{
$path = Filesystem::disk(self::LOCAL)->putFile($this->getPath(), $file);
return public_path() . $this->getLocalPath($path);
}
/** /**
* 本地路径 * 本地路径
* *
@@ -91,7 +106,7 @@ class CatchUpload
* @param $path * @param $path
* @return string * @return string
*/ */
protected function getLocalPath($path) protected function getLocalPath($path): string
{ {
if ($this->getDriver() === self::LOCAL) { if ($this->getDriver() === self::LOCAL) {

View File

@@ -18,7 +18,7 @@ use catcher\traits\db\ScopeTrait;
*/ */
abstract class CatchModel extends \think\Model abstract class CatchModel extends \think\Model
{ {
use SoftDelete, TransTrait, BaseOptionsTrait, ScopeTrait, RewriteTrait; use SoftDelete, BaseOptionsTrait, ScopeTrait, RewriteTrait;
protected $createTime = 'created_at'; protected $createTime = 'created_at';

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace catcher\library\excel\reader;
use catcher\exceptions\FailedException;
use PhpOffice\PhpSpreadsheet\Reader\Csv;
use PhpOffice\PhpSpreadsheet\Reader\Ods;
use PhpOffice\PhpSpreadsheet\Reader\Slk;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xml;
class Factory
{
/**
* make reader
*
* @time 2021年04月01日
* @param $filename
* @return mixed
*/
public static function make($filename)
{
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (isset(self::readers()[$ext])) {
return app()->make(self::readers()[$ext]);
}
throw new FailedException('Dont Support The File Extension');
}
/**
* readers
*
* @time 2021年04月01日
* @return string[]
*/
protected static function readers(): array
{
return [
'xlsx' => Xlsx::class,
'xml' => Xml::class,
'ods' => Ods::class,
'slk' => Slk::class,
'csv' => Csv::class,
];
}
}

View File

@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
namespace catcher\library\excel\reader;
trait Macro
{
/**
* 移除不需要的列
*
* @time 2021年04月21日
* @param ...$indexes
* @return mixed
*/
public function remove(...$indexes)
{
foreach ($indexes as $index) {
unset($this->sheets[$index]);
}
return $this;
}
/**
* 设置 memory
*
* @time 2021年04月21日
* @param int $memory
* @return mixed
*/
public function memory(int $memory)
{
ini_set('memory_limit', $memory . 'M');
return $this;
}
/**
* 处理
*
* @time 2021年04月23日
* @return array
*/
protected function dealWith(): array
{
$headers = $this->headers();
$data = [];
foreach ($this->sheets as &$sheet) {
$d = [];
foreach ($headers as $k => $header) {
$d[$header] = method_exists($this, 'deal' . ucfirst($header)) ?
$this->{'deal' . ucfirst($header)}($sheet) : $sheet[$k];
}
$data[] = $d;
}
return $data;
}
}

View File

@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
namespace catcher\library\excel\reader;
use catcher\CatchUpload;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
abstract class Reader
{
use Macro;
/**
* 当前的 sheet
*
* false 代表获取全部 sheets
*
* @var bool
*/
protected $active = true;
protected $sheets;
/**
* 导入
*
* @time 2021年04月21日
* @param $file
* @return Reader
*/
public function import($file): Reader
{
$file = (new CatchUpload)->setPath('excel')->toLocal($file);
$reader = Factory::make($file);
// 设置只读
$reader->setReadDataOnly(true);
/* @var $spreadsheet Spreadsheet */
$spreadsheet = $reader->load($file);
if ($this->active) {
$this->sheets = $spreadsheet->getActiveSheet()->toArray();
} else {
foreach ($spreadsheet->getAllSheets() as $sheet) {
$this->sheets[] = $sheet->toArray();
}
}
return $this;
}
/**
* 必须实现的方法
*
* @time 2021年04月21日
* @return mixed
*/
abstract public function headers();
/**
* 数据处理
*
* @time 2021年04月23日
* @param callable $callback
* @return mixed
*/
public function then(callable $callback)
{
return $callback($this->dealWith());
}
}

View File

@@ -30,9 +30,9 @@ trait ComponentsTrait
* @param null $updateFields * @param null $updateFields
* @return HeaderItem * @return HeaderItem
*/ */
public function withSwitchComponent($updateFields = null): HeaderItem public function withSwitchComponent(array $options = [], $updateFields = null): HeaderItem
{ {
return $this->component('switch_', $updateFields ? : $this->attributes['prop']); return $this->component('switch_', $updateFields ? : $this->attributes['prop'], $options);
} }
/** /**

View File

@@ -0,0 +1,109 @@
<?php
namespace catcher\library\table;
/**
*
* @time 2021年04月21日
*/
class Excel
{
protected static $label;
protected $sheets = [];
/**
* name
*
* @time 2021年04月21日
* @param string $name
* @return $this
*/
public function prop(string $name): Excel
{
$this->sheets['prop'] = $name;
return $this;
}
/**
* label
*
* @time 2021年04月21日
* @param string $label
* @return $this
*/
protected function label(string $label): Excel
{
$this->sheets['label'] = $label;
return $this;
}
/**
* options
*
* @time 2021年04月21日
* @param array $options
* @return $this
*/
public function options(array $options): Excel
{
$this->sheets['options'] = $options;
return $this;
}
/**
* 导入
*
* @time 2021年04月22日
* @param bool $import
* @return $this
*/
public function import(bool $import = true): Excel
{
$this->sheets['import'] = $import;
return $this;
}
/**
* 导出
*
* @time 2021年04月22日
* @param bool $export
* @return $this
*/
public function export(bool $export = true): Excel
{
$this->sheets['export'] = $export;
return $this;
}
/**
* 渲染
*
* @time 2021年04月21日
* @return array
*/
public function render(): array
{
return $this->sheets;
}
/**
* 静态访问
*
* @time 2021年04月21日
* @param $method
* @param $params
* @return false|mixed
*/
public static function __callStatic($method, $params)
{
return call_user_func_array([new self(), $method], $params);
}
}

View File

@@ -73,6 +73,31 @@ class HeaderItem
return $this->width(50)->type('selection'); return $this->width(50)->type('selection');
} }
/**
* dont export
*
* @time 2021年04月22日
* @return $this
*/
public function dontExport(): HeaderItem
{
$this->attributes['export'] = false;
return $this;
}
/**
* dont import
*
* @time 2021年04月22日
* @return $this
*/
public function dontImport(): HeaderItem
{
$this->attributes['import'] = false;
return $this;
}
/** /**
* 动态访问 * 动态访问

View File

@@ -98,6 +98,21 @@ class Table
*/ */
protected $forceUpdate = false; protected $forceUpdate = false;
/**
* @var array
*/
protected $excel = [];
/**
* 导出 excel 所使用 model
*
* @var string
*/
protected $usedModel;
/** /**
* Table constructor. * Table constructor.
* @param string $ref * @param string $ref
@@ -167,6 +182,25 @@ class Table
return $this; return $this;
} }
/**
* excel 信息
*
* @time 2021年04月21日
* @param array $excel
* @param string $usedModel
* @return $this
*/
public function withUsedModelAndExcel(string $usedModel, array $excel): Table
{
foreach ($excel as $e) {
$this->excel[] = $e->render();
}
$this->usedModel = $usedModel;
return $this;
}
/** /**
* set * set
* *

View File

@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace catcher\traits\db; namespace catcher\traits\db;
use catcher\library\excel\reader\Reader;
use catcher\Utils; use catcher\Utils;
trait BaseOptionsTrait trait BaseOptionsTrait
@@ -221,4 +222,55 @@ trait BaseOptionsTrait
return $data; return $data;
} }
public function import($fields, $file)
{
$excel = new class(array_column($fields, 'field')) extends Reader {
protected $fields;
public function __construct($fields)
{
$this->fields = $fields;
}
public function headers()
{
// TODO: Implement headers() method.
return $this->fields;
}
};
$options = [];
foreach ($fields as $field) {
$p = [];
if (isset($field['options']) && count($field['options'])) {
foreach ($field['options'] as $op) {
$p[$op['label']] = $op['value'];
}
$options[$field['field']] = $p;
}
}
$creatorId = request()->user()->id;
$excel->import($file)->remove(0)->then(function ($data) use ($options, $creatorId){
foreach ($data as &$d) {
foreach ($d as $field => &$v) {
if (isset($options[$field])) {
$v = $options[$field][$v];
}
}
$d['creator_id'] = $creatorId;
$this->createBy($d);
}
});
return true;
}
} }

View File

@@ -1,50 +0,0 @@
<?php
declare(strict_types=1);
namespace catcher\traits\db;
use think\facade\Db;
trait TransTrait
{
/**
*
* @time 2019年12月03日
* @return void
*/
public function startTrans()
{
Db::startTrans();
}
/**
*
* @time 2019年12月03日
* @return void
*/
public function commit()
{
Db::commit();
}
/**
*
* @time 2019年12月03日
* @return void
*/
public function rollback()
{
Db::rollback();
}
/**
*
* @time 2019年12月03日
* @param \Closure $function
* @return void
*/
public function transaction(\Closure $function)
{
Db::transaction($function());
}
}