初始化-安装依赖
This commit is contained in:
209
server/plugin/saiadmin/app/logic/system/DatabaseLogic.php
Normal file
209
server/plugin/saiadmin/app/logic/system/DatabaseLogic.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use support\think\Db;
|
||||
|
||||
/**
|
||||
* 数据表维护逻辑层
|
||||
*/
|
||||
class DatabaseLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 获取数据源
|
||||
* @return array
|
||||
*/
|
||||
public function getDbSource(): array
|
||||
{
|
||||
$data = config('think-orm.connections');
|
||||
$list = [];
|
||||
foreach ($data as $k => $v) {
|
||||
$list[] = $k;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据列表
|
||||
* @param $query
|
||||
* @return mixed
|
||||
*/
|
||||
public function getList($query): mixed
|
||||
{
|
||||
$request = request();
|
||||
$page = $request ? ($request->input('page') ?: 1) : 1;
|
||||
$limit = $request ? ($request->input('limit') ?: 10) : 10;
|
||||
|
||||
return self::getTableList($query, $page, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库表数据
|
||||
*/
|
||||
public function getTableList($query, $current_page = 1, $per_page = 10): array
|
||||
{
|
||||
if (!empty($query['source'])) {
|
||||
if (!empty($query['name'])) {
|
||||
$sql = 'show table status where name=:name ';
|
||||
$list = Db::connect($query['source'])->query($sql, ['name' => $query['name']]);
|
||||
} else {
|
||||
$list = Db::connect($query['source'])->query('show table status');
|
||||
}
|
||||
} else {
|
||||
if (!empty($query['name'])) {
|
||||
$sql = 'show table status where name=:name ';
|
||||
$list = Db::query($sql, ['name' => $query['name']]);
|
||||
} else {
|
||||
$list = Db::query('show table status');
|
||||
}
|
||||
}
|
||||
|
||||
$data = [];
|
||||
foreach ($list as $item) {
|
||||
$data[] = [
|
||||
'name' => $item['Name'],
|
||||
'engine' => $item['Engine'],
|
||||
'rows' => $item['Rows'],
|
||||
'data_free' => $item['Data_free'],
|
||||
'data_length' => $item['Data_length'],
|
||||
'index_length' => $item['Index_length'],
|
||||
'collation' => $item['Collation'],
|
||||
'create_time' => $item['Create_time'],
|
||||
'update_time' => $item['Update_time'],
|
||||
'comment' => $item['Comment'],
|
||||
];
|
||||
}
|
||||
$total = count($data);
|
||||
$last_page = ceil($total / $per_page);
|
||||
$startIndex = ($current_page - 1) * $per_page;
|
||||
$pageData = array_slice($data, $startIndex, $per_page);
|
||||
return [
|
||||
'data' => $pageData,
|
||||
'total' => $total,
|
||||
'current_page' => $current_page,
|
||||
'per_page' => $per_page,
|
||||
'last_page' => $last_page,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列信息
|
||||
*/
|
||||
public function getColumnList($table, $source): array
|
||||
{
|
||||
$columnList = [];
|
||||
if (preg_match("/^[a-zA-Z0-9_]+$/", $table)) {
|
||||
if (!empty($source)) {
|
||||
$list = Db::connect($source)->query('SHOW FULL COLUMNS FROM `' . $table . '`');
|
||||
} else {
|
||||
$list = Db::query('SHOW FULL COLUMNS FROM `' . $table . '`');
|
||||
}
|
||||
foreach ($list as $column) {
|
||||
preg_match('/^\w+/', $column['Type'], $matches);
|
||||
$columnList[] = [
|
||||
'column_key' => $column['Key'],
|
||||
'column_name' => $column['Field'],
|
||||
'column_type' => $matches[0],
|
||||
'column_comment' => trim(preg_replace("/\([^()]*\)/", "", $column['Comment'])),
|
||||
'extra' => $column['Extra'],
|
||||
'default_value' => $column['Default'],
|
||||
'is_nullable' => $column['Null'],
|
||||
];
|
||||
}
|
||||
}
|
||||
return $columnList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 优化表
|
||||
*/
|
||||
public function optimizeTable($tables)
|
||||
{
|
||||
foreach ($tables as $table) {
|
||||
if (preg_match("/^[a-zA-Z0-9_]+$/", $table)) {
|
||||
Db::execute('OPTIMIZE TABLE `' . $table . '`');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理表碎片
|
||||
*/
|
||||
public function fragmentTable($tables)
|
||||
{
|
||||
foreach ($tables as $table) {
|
||||
if (preg_match("/^[a-zA-Z0-9_]+$/", $table)) {
|
||||
Db::execute('ANALYZE TABLE `' . $table . '`');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取回收站数据
|
||||
*/
|
||||
public function recycleData($table)
|
||||
{
|
||||
if (preg_match("/^[a-zA-Z0-9_]+$/", $table)) {
|
||||
// 查询表字段
|
||||
$sql = 'SHOW COLUMNS FROM `' . $table . '` where Field = "delete_time"';
|
||||
$columns = Db::query($sql);
|
||||
$isDeleteTime = false;
|
||||
if (count($columns) > 0) {
|
||||
$isDeleteTime = true;
|
||||
}
|
||||
if (!$isDeleteTime) {
|
||||
throw new ApiException('当前表不支持回收站功能');
|
||||
}
|
||||
// 查询软删除数据
|
||||
$request = request();
|
||||
$limit = $request ? ($request->input('limit') ?: 10) : 10;
|
||||
return Db::table($table)->whereNotNull('delete_time')
|
||||
->order('delete_time', 'desc')
|
||||
->paginate($limit)
|
||||
->toArray();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
* @param $table
|
||||
* @param $ids
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($table, $ids)
|
||||
{
|
||||
if (preg_match("/^[a-zA-Z0-9_]+$/", $table)) {
|
||||
$count = Db::table($table)->whereIn('id', $ids)->delete($ids);
|
||||
return $count > 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复数据
|
||||
* @param $table
|
||||
* @param $ids
|
||||
* @return bool
|
||||
*/
|
||||
public function recovery($table, $ids)
|
||||
{
|
||||
if (preg_match("/^[a-zA-Z0-9_]+$/", $table)) {
|
||||
$count = Db::table($table)
|
||||
->where('id', 'in', $ids)
|
||||
->update(['delete_time' => null]);
|
||||
return $count > 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use Exception;
|
||||
use plugin\saiadmin\app\model\system\SystemAttachment;
|
||||
use plugin\saiadmin\app\model\system\SystemCategory;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\service\storage\ChunkUploadService;
|
||||
use plugin\saiadmin\service\storage\UploadService;
|
||||
use plugin\saiadmin\utils\Arr;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
|
||||
/**
|
||||
* 附件逻辑层
|
||||
*/
|
||||
class SystemAttachmentLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemAttachment();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $category_id
|
||||
* @param $ids
|
||||
* @return mixed
|
||||
*/
|
||||
public function move($category_id, $ids): mixed
|
||||
{
|
||||
$category = SystemCategory::where('id', $category_id)->findOrEmpty();
|
||||
if ($category->isEmpty()) {
|
||||
throw new ApiException('目标分类不存在');
|
||||
}
|
||||
return $this->model->whereIn('id', $ids)->update(['category_id' => $category_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存网络图片
|
||||
* @param $url
|
||||
* @param $config
|
||||
* @return array
|
||||
* @throws ApiException|Exception
|
||||
*/
|
||||
public function saveNetworkImage($url, $config): array
|
||||
{
|
||||
$image_data = file_get_contents($url);
|
||||
if ($image_data === false) {
|
||||
throw new ApiException('获取文件资源失败');
|
||||
}
|
||||
$image_resource = imagecreatefromstring($image_data);
|
||||
if (!$image_resource) {
|
||||
throw new ApiException('创建图片资源失败');
|
||||
}
|
||||
$filename = basename($url);
|
||||
$file_extension = pathinfo($filename, PATHINFO_EXTENSION);
|
||||
$full_dir = runtime_path() . '/resource/';
|
||||
if (!is_dir($full_dir)) {
|
||||
mkdir($full_dir, 0777, true);
|
||||
}
|
||||
$save_path = $full_dir . $filename;
|
||||
$mime_type = 'image/';
|
||||
switch ($file_extension) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
$mime_type = 'image/jpeg';
|
||||
$result = imagejpeg($image_resource, $save_path);
|
||||
break;
|
||||
case 'png':
|
||||
$mime_type = 'image/png';
|
||||
$result = imagepng($image_resource, $save_path);
|
||||
break;
|
||||
case 'gif':
|
||||
$mime_type = 'image/gif';
|
||||
$result = imagegif($image_resource, $save_path);
|
||||
break;
|
||||
default:
|
||||
imagedestroy($image_resource);
|
||||
throw new ApiException('文件格式错误');
|
||||
}
|
||||
imagedestroy($image_resource);
|
||||
if (!$result) {
|
||||
throw new ApiException('文件保存失败');
|
||||
}
|
||||
|
||||
$hash = md5_file($save_path);
|
||||
$size = filesize($save_path);
|
||||
|
||||
$model = $this->model->where('hash', $hash)->find();
|
||||
if ($model) {
|
||||
unlink($save_path);
|
||||
return $model->toArray();
|
||||
} else {
|
||||
|
||||
$logic = new SystemConfigLogic();
|
||||
$uploadConfig = $logic->getGroup('upload_config');
|
||||
|
||||
$root = Arr::getConfigValue($uploadConfig, 'local_root');
|
||||
|
||||
$folder = date('Ymd');
|
||||
$full_dir = base_path() . DIRECTORY_SEPARATOR . $root . $folder . DIRECTORY_SEPARATOR;
|
||||
if (!is_dir($full_dir)) {
|
||||
mkdir($full_dir, 0777, true);
|
||||
}
|
||||
$object_name = bin2hex(pack('Nn', time(), random_int(1, 65535))) . ".$file_extension";
|
||||
$newPath = $full_dir . $object_name;
|
||||
|
||||
copy($save_path, $newPath);
|
||||
unlink($save_path);
|
||||
$domain = Arr::getConfigValue($uploadConfig, 'local_domain');
|
||||
$uri = Arr::getConfigValue($uploadConfig, 'local_uri');
|
||||
$baseUrl = $domain . $uri . $folder . '/';
|
||||
|
||||
$info['storage_mode'] = 1;
|
||||
$info['category_id'] = request()->input('category_id', 1);
|
||||
$info['origin_name'] = $filename;
|
||||
$info['object_name'] = $object_name;
|
||||
$info['hash'] = $hash;
|
||||
$info['mime_type'] = $mime_type;
|
||||
$info['storage_path'] = $root . $folder . '/' . $object_name;
|
||||
$info['suffix'] = $file_extension;
|
||||
$info['size_byte'] = $size;
|
||||
$info['size_info'] = formatBytes($size);
|
||||
$info['url'] = $baseUrl . $object_name;
|
||||
$this->model->save($info);
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param string $upload
|
||||
* @param bool $local
|
||||
* @return array
|
||||
*/
|
||||
public function uploadBase(string $upload = 'image', bool $local = false): array
|
||||
{
|
||||
$logic = new SystemConfigLogic();
|
||||
$uploadConfig = $logic->getGroup('upload_config');
|
||||
$type = Arr::getConfigValue($uploadConfig, 'upload_mode');
|
||||
if ($local === true) {
|
||||
$type = 1;
|
||||
}
|
||||
$result = UploadService::disk($type, $upload)->uploadFile();
|
||||
$data = $result[0];
|
||||
$hash = $data['unique_id'];
|
||||
$hash_check = config('plugin.saiadmin.saithink.file_hash', false);
|
||||
if ($hash_check) {
|
||||
$model = $this->model->where('hash', $hash)->findOrEmpty();
|
||||
if (!$model->isEmpty()) {
|
||||
return $model->toArray();
|
||||
}
|
||||
}
|
||||
$url = str_replace('\\', '/', $data['url']);
|
||||
$savePath = str_replace('\\', '/', $data['save_path']);
|
||||
$info['storage_mode'] = $type;
|
||||
$info['category_id'] = request()->input('category_id', 1);
|
||||
$info['origin_name'] = $data['origin_name'];
|
||||
$info['object_name'] = $data['save_name'];
|
||||
$info['hash'] = $data['unique_id'];
|
||||
$info['mime_type'] = $data['mime_type'];
|
||||
$info['storage_path'] = $savePath;
|
||||
$info['suffix'] = $data['extension'];
|
||||
$info['size_byte'] = $data['size'];
|
||||
$info['size_info'] = formatBytes($data['size']);
|
||||
$info['url'] = $url;
|
||||
$this->model->save($info);
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切片上传
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public function chunkUpload($data): array
|
||||
{
|
||||
$chunkService = new ChunkUploadService();
|
||||
if ($data['index'] == 0) {
|
||||
$model = $this->model->where('hash', $data['hash'])->findOrEmpty();
|
||||
if (!$model->isEmpty()) {
|
||||
return $model->toArray();
|
||||
} else {
|
||||
return $chunkService->checkChunk($data);
|
||||
}
|
||||
} else {
|
||||
return $chunkService->uploadChunk($data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
101
server/plugin/saiadmin/app/logic/system/SystemCategoryLogic.php
Normal file
101
server/plugin/saiadmin/app/logic/system/SystemCategoryLogic.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\app\model\system\SystemCategory;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use plugin\saiadmin\utils\Arr;
|
||||
|
||||
/**
|
||||
* 附件分类逻辑层
|
||||
*/
|
||||
class SystemCategoryLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemCategory();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据
|
||||
*/
|
||||
public function add($data): bool
|
||||
{
|
||||
$data = $this->handleData($data);
|
||||
return $this->model->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据
|
||||
*/
|
||||
public function edit($id, $data): bool
|
||||
{
|
||||
$data = $this->handleData($data);
|
||||
if ($data['parent_id'] == $id) {
|
||||
throw new ApiException('上级分类和当前分类不能相同');
|
||||
}
|
||||
if (in_array($id, explode(',', $data['level']))) {
|
||||
throw new ApiException('不能将上级分类设置为当前分类的子分类');
|
||||
}
|
||||
$model = $this->model->findOrEmpty($id);
|
||||
if ($model->isEmpty()) {
|
||||
throw new ApiException('数据不存在');
|
||||
}
|
||||
return $model->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据删除
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
{
|
||||
$num = $this->model->where('parent_id', 'in', $ids)->count();
|
||||
if ($num > 0) {
|
||||
throw new ApiException('该部门下存在子分类,请先删除子分类');
|
||||
} else {
|
||||
return $this->model->destroy($ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据处理
|
||||
*/
|
||||
protected function handleData($data)
|
||||
{
|
||||
if (empty($data['parent_id']) || $data['parent_id'] == 0) {
|
||||
$data['level'] = '0';
|
||||
$data['parent_id'] = 0;
|
||||
} else {
|
||||
$parentMenu = SystemCategory::findOrEmpty($data['parent_id']);
|
||||
$data['level'] = $parentMenu['level'] . $parentMenu['id'] . ',';
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据树形化
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function tree(array $where = []): array
|
||||
{
|
||||
$query = $this->search($where);
|
||||
$request = request();
|
||||
if ($request && $request->input('tree', 'false') === 'true') {
|
||||
$query->field('id, id as value, category_name as label, parent_id, category_name, sort');
|
||||
}
|
||||
$query->order('sort', 'desc');
|
||||
$data = $this->getAll($query);
|
||||
return Helper::makeTree($data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\app\cache\ConfigCache;
|
||||
use plugin\saiadmin\app\model\system\SystemConfigGroup;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\app\model\system\SystemConfig;
|
||||
use support\think\Db;
|
||||
|
||||
/**
|
||||
* 参数配置分组逻辑层
|
||||
*/
|
||||
class SystemConfigGroupLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemConfigGroup();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除配置信息
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
{
|
||||
$id = $ids[0];
|
||||
$model = $this->model->where('id', $id)->findOrEmpty();
|
||||
if ($model->isEmpty()) {
|
||||
throw new ApiException('配置数据未找到');
|
||||
}
|
||||
if (in_array(intval($id), [1, 2, 3])) {
|
||||
throw new ApiException('系统默认分组,无法删除');
|
||||
}
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 删除配置组
|
||||
$model->delete();
|
||||
// 删除配置组数据
|
||||
$typeIds = SystemConfig::where('group_id', $id)->column('id');
|
||||
SystemConfig::destroy($typeIds);
|
||||
ConfigCache::clearConfig($model->code);
|
||||
Db::commit();
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
throw new ApiException('删除数据异常,请检查');
|
||||
}
|
||||
}
|
||||
}
|
||||
107
server/plugin/saiadmin/app/logic/system/SystemConfigLogic.php
Normal file
107
server/plugin/saiadmin/app/logic/system/SystemConfigLogic.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\app\cache\ConfigCache;
|
||||
use plugin\saiadmin\app\model\system\SystemConfig;
|
||||
use plugin\saiadmin\app\model\system\SystemConfigGroup;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
|
||||
/**
|
||||
* 参数配置逻辑层
|
||||
*/
|
||||
class SystemConfigLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据
|
||||
* @param mixed $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function add($data): mixed
|
||||
{
|
||||
$result = $this->model->create($data);
|
||||
$group = SystemConfigGroup::find($data['group_id']);
|
||||
ConfigCache::clearConfig($group->code);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
* @param mixed $id
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
public function edit($id, $data): bool
|
||||
{
|
||||
$result = parent::edit($id, $data);
|
||||
$group = SystemConfigGroup::find($data['group_id']);
|
||||
ConfigCache::clearConfig($group->code);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新
|
||||
* @param mixed $group_id
|
||||
* @param mixed $config
|
||||
* @return bool
|
||||
*/
|
||||
public function batchUpdate($group_id, $config): bool
|
||||
{
|
||||
$group = SystemConfigGroup::find($group_id);
|
||||
if (!$group) {
|
||||
throw new ApiException('配置组未找到');
|
||||
}
|
||||
$saveData = [];
|
||||
foreach ($config as $key => $value) {
|
||||
$saveData[] = [
|
||||
'id' => $value['id'],
|
||||
'group_id' => $group_id,
|
||||
'name' => $value['name'],
|
||||
'key' => $value['key'],
|
||||
'value' => $value['value']
|
||||
];
|
||||
}
|
||||
// upsert: 根据 id 更新,如果不存在则插入
|
||||
$this->model->saveAll($saveData);
|
||||
ConfigCache::clearConfig($group->code);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置数据
|
||||
* @param mixed $code
|
||||
* @return array
|
||||
*/
|
||||
public function getData($code): array
|
||||
{
|
||||
$group = SystemConfigGroup::where('code', $code)->findOrEmpty();
|
||||
if (empty($group)) {
|
||||
return [];
|
||||
}
|
||||
$config = SystemConfig::where('group_id', $group['id'])->select()->toArray();
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置组
|
||||
*/
|
||||
public function getGroup($config): array
|
||||
{
|
||||
return ConfigCache::getConfig($config);
|
||||
}
|
||||
|
||||
}
|
||||
127
server/plugin/saiadmin/app/logic/system/SystemDeptLogic.php
Normal file
127
server/plugin/saiadmin/app/logic/system/SystemDeptLogic.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\app\model\system\SystemDept;
|
||||
use plugin\saiadmin\app\model\system\SystemUser;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use plugin\saiadmin\utils\Arr;
|
||||
|
||||
/**
|
||||
* 部门逻辑层
|
||||
*/
|
||||
class SystemDeptLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemDept();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据
|
||||
*/
|
||||
public function add($data): mixed
|
||||
{
|
||||
$data = $this->handleData($data);
|
||||
$this->model->save($data);
|
||||
return $this->model->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据
|
||||
*/
|
||||
public function edit($id, $data): mixed
|
||||
{
|
||||
$oldLevel = $data['level'] . $id . ',';
|
||||
$data = $this->handleData($data);
|
||||
if ($data['parent_id'] == $id) {
|
||||
throw new ApiException('上级部门和当前部门不能相同');
|
||||
}
|
||||
if (in_array($id, explode(',', $data['level']))) {
|
||||
throw new ApiException('不能将上级部门设置为当前部门的子部门');
|
||||
}
|
||||
$newLevel = $data['level'] . $id . ',';
|
||||
$deptIds = $this->model->where('level', 'like', $oldLevel . '%')->column('id');
|
||||
|
||||
return $this->transaction(function () use ($deptIds, $oldLevel, $newLevel, $data, $id) {
|
||||
$this->model->whereIn('id', $deptIds)->exp('level', "REPLACE(level, '$oldLevel', '$newLevel')")->update([]);
|
||||
return $this->model->update($data, ['id' => $id]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据删除
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
{
|
||||
$num = $this->model->where('parent_id', 'in', $ids)->count();
|
||||
if ($num > 0) {
|
||||
throw new ApiException('该部门下存在子部门,请先删除子部门');
|
||||
} else {
|
||||
$count = SystemUser::where('dept_id', 'in', $ids)->count();
|
||||
if ($count > 0) {
|
||||
throw new ApiException('该部门下存在用户,请先删除或者转移用户');
|
||||
}
|
||||
return $this->model->destroy($ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据处理
|
||||
*/
|
||||
protected function handleData($data)
|
||||
{
|
||||
// 处理上级部门
|
||||
if (empty($data['parent_id']) || $data['parent_id'] == 0) {
|
||||
$data['level'] = '0';
|
||||
$data['parent_id'] = 0;
|
||||
} else {
|
||||
$parentMenu = SystemDept::findOrEmpty($data['parent_id']);
|
||||
$data['level'] = $parentMenu['level'] . $parentMenu['id'] . ',';
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据树形化
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function tree(array $where = []): array
|
||||
{
|
||||
$query = $this->search($where);
|
||||
$request = request();
|
||||
if ($request && $request->input('tree', 'false') === 'true') {
|
||||
$query->field('id, id as value, name as label, parent_id');
|
||||
}
|
||||
$query->order('sort', 'desc');
|
||||
$query->with(['leader']);
|
||||
$data = $this->getAll($query);
|
||||
return Helper::makeTree($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 可操作部门
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function accessDept(array $where = []): array
|
||||
{
|
||||
$query = $this->search($where);
|
||||
$query->auth($this->adminInfo['deptList']);
|
||||
$query->field('id, id as value, name as label, parent_id');
|
||||
$query->order('sort', 'desc');
|
||||
$data = $this->getAll($query);
|
||||
return Helper::makeTree($data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\app\model\system\SystemDictData;
|
||||
use plugin\saiadmin\app\model\system\SystemDictType;
|
||||
use plugin\saiadmin\app\cache\DictCache;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
|
||||
/**
|
||||
* 字典类型逻辑层
|
||||
*/
|
||||
class SystemDictDataLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemDictData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function add($data): mixed
|
||||
{
|
||||
$type = SystemDictType::where('id', $data['type_id'])->findOrEmpty();
|
||||
if ($type->isEmpty()) {
|
||||
throw new ApiException('字典类型不存在');
|
||||
}
|
||||
$data['code'] = $type->code;
|
||||
$model = $this->model->create($data);
|
||||
DictCache::clear();
|
||||
return $model->getKey();
|
||||
}
|
||||
|
||||
}
|
||||
116
server/plugin/saiadmin/app/logic/system/SystemDictTypeLogic.php
Normal file
116
server/plugin/saiadmin/app/logic/system/SystemDictTypeLogic.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\app\model\system\SystemDictType;
|
||||
use plugin\saiadmin\app\model\system\SystemDictData;
|
||||
use support\think\Db;
|
||||
|
||||
/**
|
||||
* 字典类型逻辑层
|
||||
*/
|
||||
class SystemDictTypeLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemDictType();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据
|
||||
*/
|
||||
public function add($data): mixed
|
||||
{
|
||||
$model = $this->model->where('code', $data['code'])->findOrEmpty();
|
||||
if (!$model->isEmpty()) {
|
||||
throw new ApiException('该字典标识已存在');
|
||||
}
|
||||
return $this->model->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据更新
|
||||
*/
|
||||
public function edit($id, $data): mixed
|
||||
{
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 修改数据字典类型
|
||||
$result = $this->model->update($data, ['id' => $id]);
|
||||
// 更新数据字典数据
|
||||
SystemDictData::update(['code' => $data['code']], ['type_id' => $id]);
|
||||
Db::commit();
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
throw new ApiException('修改数据异常,请检查');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据删除
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
{
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 删除数据字典类型
|
||||
$result = $this->model->destroy($ids);
|
||||
// 删除数据字典数据
|
||||
$typeIds = SystemDictData::where('type_id', 'in', $ids)->column('id');
|
||||
SystemDictData::destroy($typeIds);
|
||||
Db::commit();
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
throw new ApiException('删除数据异常,请检查');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部字典
|
||||
* @return array
|
||||
*/
|
||||
public function getDictAll(): array
|
||||
{
|
||||
$data = $this->model->where('status', 1)->field('id, name, code, remark')
|
||||
->with([
|
||||
'dicts' => function ($query) {
|
||||
$query->where('status', 1)->field('id, type_id, label, value, color, code, sort')->order('sort', 'desc');
|
||||
}
|
||||
])->select()->toArray();
|
||||
return $this->packageDict($data, 'code');
|
||||
}
|
||||
|
||||
/**
|
||||
* 组合数据
|
||||
* @param $array
|
||||
* @param $field
|
||||
* @return array
|
||||
*/
|
||||
private function packageDict($array, $field): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($array as $item) {
|
||||
if (isset($item[$field])) {
|
||||
if (isset($result[$item[$field]])) {
|
||||
$result[$item[$field]] = [($result[$item[$field]])];
|
||||
$result[$item[$field]][] = $item['dicts'];
|
||||
} else {
|
||||
$result[$item[$field]] = $item['dicts'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\app\model\system\SystemLoginLog;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use support\think\Db;
|
||||
|
||||
/**
|
||||
* 登录日志逻辑层
|
||||
*/
|
||||
class SystemLoginLogLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemLoginLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录统计图表
|
||||
* @return array
|
||||
*/
|
||||
public function loginChart(): array
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
d.date AS login_date,
|
||||
COUNT(l.login_time) AS login_count
|
||||
FROM
|
||||
(SELECT CURDATE() - INTERVAL (a.N) DAY AS date
|
||||
FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
|
||||
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
|
||||
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
|
||||
) d
|
||||
LEFT JOIN sa_system_login_log l
|
||||
ON DATE(l.login_time) = d.date
|
||||
GROUP BY d.date
|
||||
ORDER BY d.date ASC;
|
||||
";
|
||||
$data = Db::query($sql);
|
||||
return [
|
||||
'login_count' => array_column($data, 'login_count'),
|
||||
'login_date' => array_column($data, 'login_date'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录统计图表
|
||||
* @return array
|
||||
*/
|
||||
public function loginBarChart(): array
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
-- 拼接成 YYYY-MM 格式,例如 2023-01
|
||||
CONCAT(LPAD(m.month_num, 2, '0'), '月') AS login_month,
|
||||
COUNT(l.login_time) AS login_count
|
||||
FROM
|
||||
-- 生成 1 到 12 的月份数字
|
||||
(SELECT 1 AS month_num UNION ALL SELECT 2 UNION ALL SELECT 3
|
||||
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
|
||||
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
|
||||
UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12) m
|
||||
LEFT JOIN sa_system_login_log l
|
||||
-- 关联条件:年份等于今年 且 月份等于生成的数字
|
||||
ON YEAR(l.login_time) = YEAR(CURDATE())
|
||||
AND MONTH(l.login_time) = m.month_num
|
||||
GROUP BY
|
||||
m.month_num
|
||||
ORDER BY
|
||||
m.month_num ASC;
|
||||
";
|
||||
$data = Db::query($sql);
|
||||
return [
|
||||
'login_count' => array_column($data, 'login_count'),
|
||||
'login_month' => array_column($data, 'login_month'),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
26
server/plugin/saiadmin/app/logic/system/SystemMailLogic.php
Normal file
26
server/plugin/saiadmin/app/logic/system/SystemMailLogic.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\app\model\system\SystemMail;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
|
||||
/**
|
||||
* 邮件模型逻辑层
|
||||
*/
|
||||
class SystemMailLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemMail();
|
||||
}
|
||||
|
||||
}
|
||||
189
server/plugin/saiadmin/app/logic/system/SystemMenuLogic.php
Normal file
189
server/plugin/saiadmin/app/logic/system/SystemMenuLogic.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\app\model\system\SystemMenu;
|
||||
use plugin\saiadmin\app\model\system\SystemRoleMenu;
|
||||
use plugin\saiadmin\app\model\system\SystemUserRole;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Arr;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
|
||||
/**
|
||||
* 菜单逻辑层
|
||||
*/
|
||||
class SystemMenuLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据添加
|
||||
*/
|
||||
public function add($data): mixed
|
||||
{
|
||||
$data = $this->handleData($data);
|
||||
return $this->model->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据修改
|
||||
*/
|
||||
public function edit($id, $data): mixed
|
||||
{
|
||||
$data = $this->handleData($data);
|
||||
if ($data['parent_id'] == $id) {
|
||||
throw new ApiException('不能设置父级为自身');
|
||||
}
|
||||
return $this->model->update($data, ['id' => $id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据删除
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
{
|
||||
$num = $this->model->where('parent_id', 'in', $ids)->count();
|
||||
if ($num > 0) {
|
||||
throw new ApiException('该菜单下存在子菜单,请先删除子菜单');
|
||||
} else {
|
||||
return $this->model->destroy($ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据处理
|
||||
*/
|
||||
protected function handleData($data)
|
||||
{
|
||||
// 处理上级菜单
|
||||
if (empty($data['parent_id']) || $data['parent_id'] == 0) {
|
||||
$data['level'] = '0';
|
||||
$data['parent_id'] = 0;
|
||||
} else {
|
||||
$parentMenu = $this->model->findOrEmpty($data['parent_id']);
|
||||
$data['level'] = $parentMenu['level'] . $parentMenu['id'] . ',';
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据树形化
|
||||
* @param $where
|
||||
* @return array
|
||||
*/
|
||||
public function tree($where = []): array
|
||||
{
|
||||
$query = $this->search($where);
|
||||
$request = request();
|
||||
if ($request && $request->input('tree', 'false') === 'true') {
|
||||
$query->field('id, id as value, name as label, parent_id, type');
|
||||
}
|
||||
$query->order('sort', 'desc');
|
||||
$data = $this->getAll($query);
|
||||
return Helper::makeTree($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限菜单
|
||||
* @return array
|
||||
*/
|
||||
public function auth(): array
|
||||
{
|
||||
$roleLogic = new SystemRoleLogic();
|
||||
$role_ids = Arr::getArrayColumn($this->adminInfo['roleList'], 'id');
|
||||
$roles = $roleLogic->getMenuIdsByRoleIds($role_ids);
|
||||
$ids = $this->filterMenuIds($roles);
|
||||
$query = $this->model
|
||||
->field('id, id as value, name as label, parent_id, type')
|
||||
->where('status', 1)
|
||||
->where('id', 'in', $ids)
|
||||
->order('sort', 'desc');
|
||||
$data = $this->getAll($query);
|
||||
return Helper::makeTree($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部菜单
|
||||
*/
|
||||
public function getAllMenus(): array
|
||||
{
|
||||
$query = $this->search(['status' => 1, 'type' => [1, 2, 4]])->order('sort', 'desc');
|
||||
$data = $this->getAll($query);
|
||||
return Helper::makeArtdMenus($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部权限
|
||||
* @return array
|
||||
*/
|
||||
public function getAllAuth(): array
|
||||
{
|
||||
return SystemMenu::where('type', 3)
|
||||
->where('status', 1)
|
||||
->column('slug');
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色获取权限
|
||||
* @param $roleIds
|
||||
* @return array
|
||||
*/
|
||||
public function getAuthByRole($roleIds): array
|
||||
{
|
||||
$menuId = SystemRoleMenu::whereIn('role_id', $roleIds)->column('menu_id');
|
||||
|
||||
return SystemMenu::distinct(true)
|
||||
->where('type', 3)
|
||||
->where('status', 1)
|
||||
->where('id', 'in', array_unique($menuId))
|
||||
->column('slug');
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色获取菜单
|
||||
* @param $roleIds
|
||||
* @return array
|
||||
*/
|
||||
public function getMenuByRole($roleIds): array
|
||||
{
|
||||
$menuId = SystemRoleMenu::whereIn('role_id', $roleIds)->column('menu_id');
|
||||
|
||||
$data = SystemMenu::distinct(true)
|
||||
->where('status', 1)
|
||||
->where('type', 'in', [1, 2, 4])
|
||||
->where('id', 'in', array_unique($menuId))
|
||||
->order('sort', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
return Helper::makeArtdMenus($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤通过角色查询出来的菜单id列表,并去重
|
||||
* @param array $roleData
|
||||
* @return array
|
||||
*/
|
||||
public function filterMenuIds(array &$roleData): array
|
||||
{
|
||||
$ids = [];
|
||||
foreach ($roleData as $val) {
|
||||
foreach ($val['menus'] as $menu) {
|
||||
$ids[] = $menu['id'];
|
||||
}
|
||||
}
|
||||
unset($roleData);
|
||||
return array_unique($ids);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\app\model\system\SystemOperLog;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
|
||||
/**
|
||||
* 操作日志逻辑层
|
||||
*/
|
||||
class SystemOperLogLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemOperLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自己的操作日志
|
||||
* @param mixed $where
|
||||
* @return array
|
||||
*/
|
||||
public function getOwnOperLogList($where): array
|
||||
{
|
||||
$query = $this->search($where);
|
||||
$query->field('id, username, method, router, service_name, ip, ip_location, create_time');
|
||||
return $this->getList($query);
|
||||
}
|
||||
|
||||
}
|
||||
95
server/plugin/saiadmin/app/logic/system/SystemPostLogic.php
Normal file
95
server/plugin/saiadmin/app/logic/system/SystemPostLogic.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\app\model\system\SystemPost;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\service\OpenSpoutWriter;
|
||||
use OpenSpout\Reader\XLSX\Reader;
|
||||
|
||||
/**
|
||||
* 岗位管理逻辑层
|
||||
*/
|
||||
class SystemPostLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemPost();
|
||||
}
|
||||
|
||||
/**
|
||||
* 可操作岗位
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function accessPost(array $where = []): array
|
||||
{
|
||||
$query = $this->search($where);
|
||||
$query->field('id, id as value, name as label, name, code');
|
||||
return $this->getAll($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
*/
|
||||
public function import($file)
|
||||
{
|
||||
$path = $this->getImport($file);
|
||||
$reader = new Reader();
|
||||
try {
|
||||
$reader->open($path);
|
||||
$data = [];
|
||||
foreach ($reader->getSheetIterator() as $sheet) {
|
||||
$isHeader = true;
|
||||
foreach ($sheet->getRowIterator() as $row) {
|
||||
if ($isHeader) {
|
||||
$isHeader = false;
|
||||
continue;
|
||||
}
|
||||
$cells = $row->getCells();
|
||||
$data[] = [
|
||||
'name' => $cells[0]->getValue(),
|
||||
'code' => $cells[1]->getValue(),
|
||||
'sort' => $cells[2]->getValue(),
|
||||
'status' => $cells[3]->getValue(),
|
||||
];
|
||||
}
|
||||
}
|
||||
$this->saveAll($data);
|
||||
} catch (\Exception $e) {
|
||||
throw new ApiException('导入文件错误,请上传正确的文件格式xlsx');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
*/
|
||||
public function export($where = [])
|
||||
{
|
||||
$query = $this->search($where)->field('id,name,code,sort,status,create_time');
|
||||
$data = $this->getAll($query);
|
||||
$file_name = '岗位数据.xlsx';
|
||||
$header = ['编号', '岗位名称', '岗位标识', '排序', '状态', '创建时间'];
|
||||
$filter = [
|
||||
'status' => [
|
||||
['value' => 1, 'label' => '正常'],
|
||||
['value' => 2, 'label' => '禁用']
|
||||
]
|
||||
];
|
||||
$writer = new OpenSpoutWriter($file_name);
|
||||
$writer->setWidth([15, 15, 20, 15, 15, 25]);
|
||||
$writer->setHeader($header);
|
||||
$writer->setData($data, null, $filter);
|
||||
$file_path = $writer->returnFile();
|
||||
return response()->download($file_path, urlencode($file_name));
|
||||
}
|
||||
|
||||
}
|
||||
156
server/plugin/saiadmin/app/logic/system/SystemRoleLogic.php
Normal file
156
server/plugin/saiadmin/app/logic/system/SystemRoleLogic.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\app\cache\UserMenuCache;
|
||||
use plugin\saiadmin\app\model\system\SystemRole;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use support\think\Cache;
|
||||
use support\think\Db;
|
||||
|
||||
/**
|
||||
* 角色逻辑层
|
||||
*/
|
||||
class SystemRoleLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemRole();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据
|
||||
*/
|
||||
public function add($data): bool
|
||||
{
|
||||
$data = $this->handleData($data);
|
||||
return $this->model->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据
|
||||
*/
|
||||
public function edit($id, $data): bool
|
||||
{
|
||||
$model = $this->model->findOrEmpty($id);
|
||||
if ($model->isEmpty()) {
|
||||
throw new ApiException('数据不存在');
|
||||
}
|
||||
$data = $this->handleData($data);
|
||||
return $model->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
{
|
||||
// 越权保护
|
||||
$levelArr = array_column($this->adminInfo['roleList'], 'level');
|
||||
$maxLevel = max($levelArr);
|
||||
|
||||
$num = SystemRole::where('level', '>=', $maxLevel)->whereIn('id', $ids)->count();
|
||||
if ($num > 0) {
|
||||
throw new ApiException('不能操作比当前账户职级高的角色');
|
||||
} else {
|
||||
return $this->model->destroy($ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据处理
|
||||
*/
|
||||
protected function handleData($data)
|
||||
{
|
||||
// 越权保护
|
||||
$levelArr = array_column($this->adminInfo['roleList'], 'level');
|
||||
$maxLevel = max($levelArr);
|
||||
if ($data['level'] >= $maxLevel) {
|
||||
throw new ApiException('不能操作比当前账户职级高的角色');
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 可操作角色
|
||||
* @param array $where
|
||||
* @return array
|
||||
*/
|
||||
public function accessRole(array $where = []): array
|
||||
{
|
||||
$query = $this->search($where);
|
||||
// 越权保护
|
||||
$levelArr = array_column($this->adminInfo['roleList'], 'level');
|
||||
$maxLevel = max($levelArr);
|
||||
$query->where('level', '<', $maxLevel);
|
||||
$query->order('sort', 'desc');
|
||||
return $this->getAll($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色数组获取菜单
|
||||
* @param $ids
|
||||
* @return array
|
||||
*/
|
||||
public function getMenuIdsByRoleIds($ids): array
|
||||
{
|
||||
if (empty($ids))
|
||||
return [];
|
||||
return $this->model->where('id', 'in', $ids)->with([
|
||||
'menus' => function ($query) {
|
||||
$query->where('status', 1)->order('sort', 'desc');
|
||||
}
|
||||
])->select()->toArray();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据角色获取菜单
|
||||
* @param $id
|
||||
* @return array
|
||||
*/
|
||||
public function getMenuByRole($id): array
|
||||
{
|
||||
$role = $this->model->findOrEmpty($id);
|
||||
$menus = $role->menus ?: [];
|
||||
return [
|
||||
'id' => $id,
|
||||
'menus' => $menus
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存菜单权限
|
||||
* @param $id
|
||||
* @param $menu_ids
|
||||
* @return mixed
|
||||
*/
|
||||
public function saveMenuPermission($id, $menu_ids): mixed
|
||||
{
|
||||
return $this->transaction(function () use ($id, $menu_ids) {
|
||||
$role = $this->model->findOrEmpty($id);
|
||||
if ($role) {
|
||||
$role->menus()->detach();
|
||||
$data = array_map(function ($menu_id) use ($id) {
|
||||
return ['menu_id' => $menu_id, 'role_id' => $id];
|
||||
}, $menu_ids);
|
||||
Db::name('sa_system_role_menu')->limit(100)->insertAll($data);
|
||||
}
|
||||
$cache = config('plugin.saiadmin.saithink.button_cache');
|
||||
$tag = $cache['role'] . $id;
|
||||
Cache::tag($tag)->clear(); // 清理权限缓存-角色TAG
|
||||
UserMenuCache::clearMenuCache(); // 清理菜单缓存
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
336
server/plugin/saiadmin/app/logic/system/SystemUserLogic.php
Normal file
336
server/plugin/saiadmin/app/logic/system/SystemUserLogic.php
Normal file
@@ -0,0 +1,336 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\system;
|
||||
|
||||
use plugin\saiadmin\app\cache\UserAuthCache;
|
||||
use plugin\saiadmin\app\cache\UserInfoCache;
|
||||
use plugin\saiadmin\app\cache\UserMenuCache;
|
||||
use plugin\saiadmin\app\model\system\SystemDept;
|
||||
use plugin\saiadmin\app\model\system\SystemRole;
|
||||
use plugin\saiadmin\app\model\system\SystemUser;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use Webman\Event\Event;
|
||||
use Tinywan\Jwt\JwtToken;
|
||||
|
||||
/**
|
||||
* 用户信息逻辑层
|
||||
*/
|
||||
class SystemUserLogic extends BaseLogic
|
||||
{
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new SystemUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页数据列表
|
||||
* @param mixed $where
|
||||
* @return array
|
||||
*/
|
||||
public function indexList($where): array
|
||||
{
|
||||
$query = $this->search($where);
|
||||
$query->with(['depts']);
|
||||
$query->auth($this->adminInfo['deptList']);
|
||||
return $this->getList($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户列表数据
|
||||
* @param mixed $where
|
||||
* @return array
|
||||
*/
|
||||
public function openUserList($where): array
|
||||
{
|
||||
$query = $this->search($where);
|
||||
$query->field('id, username, realname, avatar, phone, email');
|
||||
return $this->getList($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取用户信息
|
||||
* @param mixed $id
|
||||
* @return array
|
||||
*/
|
||||
public function getUser($id): array
|
||||
{
|
||||
$admin = $this->model->findOrEmpty($id);
|
||||
$data = $admin->hidden(['password'])->toArray();
|
||||
$data['roleList'] = $admin->roles->toArray() ?: [];
|
||||
$data['postList'] = $admin->posts->toArray() ?: [];
|
||||
$data['deptList'] = $admin->depts ? $admin->depts->toArray() : [];
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取数据
|
||||
* @param $id
|
||||
* @return array
|
||||
*/
|
||||
public function read($id): array
|
||||
{
|
||||
$data = $this->getUser($id);
|
||||
if ($this->adminInfo['id'] > 1) {
|
||||
// 部门保护
|
||||
if (!$this->deptProtect($this->adminInfo['deptList'], $data['dept_id'])) {
|
||||
throw new ApiException('没有权限操作该部门数据');
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function add($data): mixed
|
||||
{
|
||||
$data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
|
||||
return $this->transaction(function () use ($data) {
|
||||
$role_ids = $data['role_ids'] ?? [];
|
||||
$post_ids = $data['post_ids'] ?? [];
|
||||
if ($this->adminInfo['id'] > 1) {
|
||||
// 部门保护
|
||||
if (!$this->deptProtect($this->adminInfo['deptList'], $data['dept_id'])) {
|
||||
throw new ApiException('没有权限操作该部门数据');
|
||||
}
|
||||
// 越权保护
|
||||
if (!$this->roleProtect($this->adminInfo['roleList'], $role_ids)) {
|
||||
throw new ApiException('没有权限操作该角色数据');
|
||||
}
|
||||
}
|
||||
$user = SystemUser::create($data);
|
||||
$user->roles()->detach();
|
||||
$user->posts()->detach();
|
||||
$user->roles()->saveAll($role_ids);
|
||||
if (!empty($post_ids)) {
|
||||
$user->posts()->save($post_ids);
|
||||
}
|
||||
return $user;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据
|
||||
* @param $id
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function edit($id, $data): mixed
|
||||
{
|
||||
unset($data['password']);
|
||||
return $this->transaction(function () use ($data, $id) {
|
||||
$role_ids = $data['role_ids'] ?? [];
|
||||
$post_ids = $data['post_ids'] ?? [];
|
||||
// 仅可修改当前部门和子部门的用户
|
||||
$query = $this->model->where('id', $id);
|
||||
$query->auth($this->adminInfo['deptList']);
|
||||
$user = $query->findOrEmpty();
|
||||
if ($user->isEmpty()) {
|
||||
throw new ApiException('没有权限操作该数据');
|
||||
}
|
||||
if ($this->adminInfo['id'] > 1) {
|
||||
// 部门保护
|
||||
if (!$this->deptProtect($this->adminInfo['deptList'], $data['dept_id'])) {
|
||||
throw new ApiException('没有权限操作该部门数据');
|
||||
}
|
||||
// 越权保护
|
||||
if (!$this->roleProtect($this->adminInfo['roleList'], $role_ids)) {
|
||||
throw new ApiException('没有权限操作该角色数据');
|
||||
}
|
||||
}
|
||||
$result = parent::edit($id, $data);
|
||||
if ($result) {
|
||||
$user->roles()->detach();
|
||||
$user->posts()->detach();
|
||||
$user->roles()->saveAll($role_ids);
|
||||
if (!empty($post_ids)) {
|
||||
$user->posts()->save($post_ids);
|
||||
}
|
||||
UserInfoCache::clearUserInfo($id);
|
||||
UserAuthCache::clearUserAuth($id);
|
||||
UserMenuCache::clearUserMenu($id);
|
||||
}
|
||||
return $result;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
* @param $ids
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
{
|
||||
if (is_array($ids)) {
|
||||
if (count($ids) > 1) {
|
||||
throw new ApiException('禁止批量删除操作');
|
||||
}
|
||||
$ids = $ids[0];
|
||||
}
|
||||
if ($ids == 1) {
|
||||
throw new ApiException('超级管理员禁止删除');
|
||||
}
|
||||
$query = $this->model->where('id', $ids);
|
||||
$query->auth($this->adminInfo['deptList']);
|
||||
$user = $query->findOrEmpty();
|
||||
if ($user->isEmpty()) {
|
||||
throw new ApiException('没有权限操作该数据');
|
||||
}
|
||||
if ($this->adminInfo['id'] > 1) {
|
||||
$role_ids = $user->roles->toArray() ?: [];
|
||||
if (!empty($role_ids)) {
|
||||
// 越权保护
|
||||
if (!$this->roleProtect($this->adminInfo['roleList'], array_column($role_ids, 'id'))) {
|
||||
throw new ApiException('没有权限操作该角色数据');
|
||||
}
|
||||
}
|
||||
}
|
||||
UserInfoCache::clearUserInfo($ids);
|
||||
UserAuthCache::clearUserAuth($ids);
|
||||
UserMenuCache::clearUserMenu($ids);
|
||||
return parent::destroy($ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
public function login(string $username, string $password, string $type): array
|
||||
{
|
||||
$adminInfo = $this->model->where('username', $username)->findOrEmpty();
|
||||
$status = 1;
|
||||
$message = '登录成功';
|
||||
if ($adminInfo->isEmpty()) {
|
||||
$message = '账号或密码错误,请重新输入!';
|
||||
throw new ApiException($message);
|
||||
}
|
||||
if ($adminInfo->status === 2) {
|
||||
$status = 0;
|
||||
$message = '您已被禁止登录!';
|
||||
}
|
||||
if (!password_verify($password, $adminInfo->password)) {
|
||||
$status = 0;
|
||||
$message = '账号或密码错误,请重新输入!';
|
||||
}
|
||||
if ($status === 0) {
|
||||
// 登录事件
|
||||
Event::emit('user.login', compact('username', 'status', 'message'));
|
||||
throw new ApiException($message);
|
||||
}
|
||||
$adminInfo->login_time = date('Y-m-d H:i:s');
|
||||
$adminInfo->login_ip = request()->getRealIp();
|
||||
$adminInfo->save();
|
||||
|
||||
$access_exp = config('plugin.saiadmin.saithink.access_exp', 3 * 3600);
|
||||
$token = JwtToken::generateToken([
|
||||
'access_exp' => $access_exp,
|
||||
'id' => $adminInfo->id,
|
||||
'username' => $adminInfo->username,
|
||||
'type' => $type,
|
||||
'plat' => 'saiadmin',
|
||||
]);
|
||||
// 登录事件
|
||||
$admin_id = $adminInfo->id;
|
||||
Event::emit('user.login', compact('username', 'status', 'message', 'admin_id'));
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新资料
|
||||
* @param mixed $id
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
public function updateInfo($id, $data): bool
|
||||
{
|
||||
$this->model->update($data, ['id' => $id], ['realname', 'gender', 'phone', 'email', 'avatar', 'signed']);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码修改
|
||||
* @param $adminId
|
||||
* @param $oldPassword
|
||||
* @param $newPassword
|
||||
* @return bool
|
||||
*/
|
||||
public function modifyPassword($adminId, $oldPassword, $newPassword): bool
|
||||
{
|
||||
$model = $this->model->findOrEmpty($adminId);
|
||||
if (password_verify($oldPassword, $model->password)) {
|
||||
$model->password = password_hash($newPassword, PASSWORD_DEFAULT);
|
||||
return $model->save();
|
||||
} else {
|
||||
throw new ApiException('原密码错误');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据
|
||||
*/
|
||||
public function authEdit($id, $data)
|
||||
{
|
||||
if ($this->adminInfo['id'] > 1) {
|
||||
// 判断用户是否可以操作
|
||||
$query = SystemUser::where('id', $id);
|
||||
$query->auth($this->adminInfo['deptList']);
|
||||
$user = $query->findOrEmpty();
|
||||
if ($user->isEmpty()) {
|
||||
throw new ApiException('没有权限操作该数据');
|
||||
}
|
||||
}
|
||||
parent::edit($id, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门保护
|
||||
* @param $dept
|
||||
* @param $dept_id
|
||||
* @return bool
|
||||
*/
|
||||
public function deptProtect($dept, $dept_id): bool
|
||||
{
|
||||
// 部门保护
|
||||
$deptIds = [$dept['id']];
|
||||
$deptLevel = $dept['level'] . $dept['id'] . ',';
|
||||
$dept_ids = SystemDept::whereLike('level', $deptLevel . '%')->column('id');
|
||||
$deptIds = array_merge($deptIds, $dept_ids);
|
||||
if (!in_array($dept_id, $deptIds)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 越权保护
|
||||
* @param $roleList
|
||||
* @param $role_ids
|
||||
* @return bool
|
||||
*/
|
||||
public function roleProtect($roleList, $role_ids): bool
|
||||
{
|
||||
// 越权保护
|
||||
$levelArr = array_column($roleList, 'level');
|
||||
$maxLevel = max($levelArr);
|
||||
$currentLevel = SystemRole::whereIn('id', $role_ids)->max('level');
|
||||
if ($currentLevel >= $maxLevel) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
25
server/plugin/saiadmin/app/logic/tool/CrontabLogLogic.php
Normal file
25
server/plugin/saiadmin/app/logic/tool/CrontabLogLogic.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\tool;
|
||||
|
||||
use plugin\saiadmin\app\model\tool\CrontabLog;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
|
||||
/**
|
||||
* 定时任务日志逻辑层
|
||||
*/
|
||||
class CrontabLogLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new CrontabLog();
|
||||
}
|
||||
|
||||
}
|
||||
247
server/plugin/saiadmin/app/logic/tool/CrontabLogic.php
Normal file
247
server/plugin/saiadmin/app/logic/tool/CrontabLogic.php
Normal file
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\tool;
|
||||
|
||||
use Exception;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Webman\Channel\Client as ChannelClient;
|
||||
use plugin\saiadmin\app\model\tool\Crontab;
|
||||
use plugin\saiadmin\app\model\tool\CrontabLog;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
|
||||
/**
|
||||
* 定时任务逻辑层
|
||||
*/
|
||||
class CrontabLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new Crontab();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加任务
|
||||
*/
|
||||
public function add($data): bool
|
||||
{
|
||||
$second = $data['second'];
|
||||
$minute = $data['minute'];
|
||||
$hour = $data['hour'];
|
||||
$week = $data['week'];
|
||||
$day = $data['day'];
|
||||
$month = $data['month'];
|
||||
|
||||
// 规则处理
|
||||
$rule = match ($data['task_style']) {
|
||||
1 => "0 {$minute} {$hour} * * *",
|
||||
2 => "0 {$minute} * * * *",
|
||||
3 => "0 {$minute} */{$hour} * * *",
|
||||
4 => "0 */{$minute} * * * *",
|
||||
5 => "*/{$second} * * * * *",
|
||||
6 => "0 {$minute} {$hour} * * {$week}",
|
||||
7 => "0 {$minute} {$hour} {$day} * *",
|
||||
8 => "0 {$minute} {$hour} {$day} {$month} *",
|
||||
default => throw new ApiException("任务类型异常"),
|
||||
};
|
||||
|
||||
// 定时任务模型新增
|
||||
$model = Crontab::create([
|
||||
'name' => $data['name'],
|
||||
'type' => $data['type'],
|
||||
'task_style' => $data['task_style'],
|
||||
'rule' => $rule,
|
||||
'target' => $data['target'],
|
||||
'parameter' => $data['parameter'],
|
||||
'status' => $data['status'],
|
||||
'remark' => $data['remark'],
|
||||
]);
|
||||
|
||||
$id = $model->getKey();
|
||||
// 连接到Channel服务
|
||||
ChannelClient::connect();
|
||||
ChannelClient::publish('crontab', ['args' => $id]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改任务
|
||||
*/
|
||||
public function edit($id, $data): bool
|
||||
{
|
||||
$second = $data['second'];
|
||||
$minute = $data['minute'];
|
||||
$hour = $data['hour'];
|
||||
$week = $data['week'];
|
||||
$day = $data['day'];
|
||||
$month = $data['month'];
|
||||
|
||||
// 规则处理
|
||||
$rule = match ($data['task_style']) {
|
||||
1 => "0 {$minute} {$hour} * * *",
|
||||
2 => "0 {$minute} * * * *",
|
||||
3 => "0 {$minute} */{$hour} * * *",
|
||||
4 => "0 */{$minute} * * * *",
|
||||
5 => "*/{$second} * * * * *",
|
||||
6 => "0 {$minute} {$hour} * * {$week}",
|
||||
7 => "0 {$minute} {$hour} {$day} * *",
|
||||
8 => "0 {$minute} {$hour} {$day} {$month} *",
|
||||
default => throw new ApiException("任务类型异常"),
|
||||
};
|
||||
|
||||
// 查询任务数据
|
||||
$model = $this->model->findOrEmpty($id);
|
||||
if ($model->isEmpty()) {
|
||||
throw new ApiException('数据不存在');
|
||||
}
|
||||
|
||||
$result = $model->save([
|
||||
'name' => $data['name'],
|
||||
'type' => $data['type'],
|
||||
'task_style' => $data['task_style'],
|
||||
'rule' => $rule,
|
||||
'target' => $data['target'],
|
||||
'parameter' => $data['parameter'],
|
||||
'status' => $data['status'],
|
||||
'remark' => $data['remark'],
|
||||
]);
|
||||
if ($result) {
|
||||
// 连接到Channel服务
|
||||
ChannelClient::connect();
|
||||
ChannelClient::publish('crontab', ['args' => $id]);
|
||||
}
|
||||
|
||||
// 修改任务数据
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除定时任务
|
||||
* @param $ids
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
{
|
||||
if (is_array($ids)) {
|
||||
if (count($ids) > 1) {
|
||||
throw new ApiException('禁止批量删除操作');
|
||||
}
|
||||
$ids = $ids[0];
|
||||
}
|
||||
$result = parent::destroy($ids);
|
||||
if ($result) {
|
||||
// 连接到Channel服务
|
||||
ChannelClient::connect();
|
||||
ChannelClient::publish('crontab', ['args' => $ids]);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改状态
|
||||
* @param $id
|
||||
* @param $status
|
||||
* @return bool
|
||||
*/
|
||||
public function changeStatus($id, $status): bool
|
||||
{
|
||||
$model = $this->model->findOrEmpty($id);
|
||||
if ($model->isEmpty()) {
|
||||
throw new ApiException('数据不存在');
|
||||
}
|
||||
$result = $model->save(['status' => $status]);
|
||||
if ($result) {
|
||||
// 连接到Channel服务
|
||||
ChannelClient::connect();
|
||||
ChannelClient::publish('crontab', ['args' => $id]);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行定时任务
|
||||
* @param $id
|
||||
* @return bool
|
||||
*/
|
||||
public function run($id): bool
|
||||
{
|
||||
$info = $this->model->where('status', 1)->findOrEmpty($id);
|
||||
if ($info->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
$data['crontab_id'] = $info->id;
|
||||
$data['name'] = $info->name;
|
||||
$data['target'] = $info->target;
|
||||
$data['parameter'] = $info->parameter;
|
||||
switch ($info->type) {
|
||||
case 1:
|
||||
// URL任务GET
|
||||
$httpClient = new Client([
|
||||
'timeout' => 5,
|
||||
'verify' => false,
|
||||
]);
|
||||
try {
|
||||
$httpClient->request('GET', $info->target);
|
||||
$data['status'] = 1;
|
||||
CrontabLog::create($data);
|
||||
return true;
|
||||
} catch (GuzzleException $e) {
|
||||
$data['status'] = 2;
|
||||
$data['exception_info'] = $e->getMessage();
|
||||
CrontabLog::create($data);
|
||||
return false;
|
||||
}
|
||||
case 2:
|
||||
// URL任务POST
|
||||
$httpClient = new Client([
|
||||
'timeout' => 5,
|
||||
'verify' => false,
|
||||
]);
|
||||
try {
|
||||
$res = $httpClient->request('POST', $info->target, [
|
||||
'form_params' => json_decode($info->parameter ?? '', true)
|
||||
]);
|
||||
$data['status'] = 1;
|
||||
$data['exception_info'] = $res->getBody();
|
||||
CrontabLog::create($data);
|
||||
return true;
|
||||
} catch (GuzzleException $e) {
|
||||
$data['status'] = 2;
|
||||
$data['exception_info'] = $e->getMessage();
|
||||
CrontabLog::create($data);
|
||||
return false;
|
||||
}
|
||||
case 3:
|
||||
// 类任务
|
||||
$class_name = $info->target;
|
||||
$method_name = 'run';
|
||||
$class = new $class_name;
|
||||
if (method_exists($class, $method_name)) {
|
||||
$return = $class->$method_name($info->parameter);
|
||||
$data['status'] = 1;
|
||||
$data['exception_info'] = $return;
|
||||
CrontabLog::create($data);
|
||||
return true;
|
||||
} else {
|
||||
$data['status'] = 2;
|
||||
$data['exception_info'] = '类:' . $class_name . ',方法:run,未找到';
|
||||
CrontabLog::create($data);
|
||||
return false;
|
||||
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
213
server/plugin/saiadmin/app/logic/tool/GenerateColumnsLogic.php
Normal file
213
server/plugin/saiadmin/app/logic/tool/GenerateColumnsLogic.php
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\tool;
|
||||
|
||||
use plugin\saiadmin\app\model\tool\GenerateColumns;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
|
||||
/**
|
||||
* 代码生成业务字段逻辑层
|
||||
*/
|
||||
class GenerateColumnsLogic extends BaseLogic
|
||||
{
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new GenerateColumns();
|
||||
}
|
||||
|
||||
public function saveExtra($data)
|
||||
{
|
||||
$default_column = ['create_time', 'update_time', 'created_by', 'updated_by', 'delete_time', 'remark'];
|
||||
// 组装数据
|
||||
foreach ($data as $k => $item) {
|
||||
|
||||
if ($item['column_name'] == 'delete_time') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$column = [
|
||||
'table_id' => $item['table_id'],
|
||||
'column_name' => $item['column_name'],
|
||||
'column_comment' => $item['column_comment'],
|
||||
'column_type' => $item['column_type'],
|
||||
'default_value' => $item['default_value'],
|
||||
'is_pk' => ($item['column_key'] == 'PRI') ? 2 : 1,
|
||||
'is_required' => $item['is_nullable'] == 'NO' ? 2 : 1,
|
||||
'query_type' => 'eq',
|
||||
'view_type' => 'input',
|
||||
'sort' => count($data) - $k,
|
||||
'options' => $item['options'] ?? null
|
||||
];
|
||||
|
||||
// 设置默认选项
|
||||
if (!in_array($item['column_name'], $default_column) && empty($item['column_key'])) {
|
||||
$column = array_merge(
|
||||
$column,
|
||||
[
|
||||
'is_insert' => 2,
|
||||
'is_edit' => 2,
|
||||
'is_list' => 2,
|
||||
'is_query' => 1,
|
||||
'is_sort' => 1,
|
||||
]
|
||||
);
|
||||
}
|
||||
$keyList = [
|
||||
'column_comment',
|
||||
'column_type',
|
||||
'default_value',
|
||||
'is_pk',
|
||||
'is_required',
|
||||
'is_insert',
|
||||
'is_edit',
|
||||
'is_list',
|
||||
'is_query',
|
||||
'is_sort',
|
||||
'query_type',
|
||||
'view_type',
|
||||
'dict_type',
|
||||
'options',
|
||||
'sort',
|
||||
'is_cover'
|
||||
];
|
||||
foreach ($keyList as $key) {
|
||||
if (isset($item[$key]))
|
||||
$column[$key] = $item[$key];
|
||||
}
|
||||
GenerateColumns::create($this->fieldDispose($column));
|
||||
}
|
||||
}
|
||||
|
||||
public function update($data, $where)
|
||||
{
|
||||
$data['is_insert'] = $data['is_insert'] ? 2 : 1;
|
||||
$data['is_edit'] = $data['is_edit'] ? 2 : 1;
|
||||
$data['is_list'] = $data['is_list'] ? 2 : 1;
|
||||
$data['is_query'] = $data['is_query'] ? 2 : 1;
|
||||
$data['is_sort'] = $data['is_sort'] ? 2 : 1;
|
||||
$data['is_required'] = $data['is_required'] ? 2 : 1;
|
||||
$this->model->update($data, $where);
|
||||
}
|
||||
|
||||
private function fieldDispose(array $column): array
|
||||
{
|
||||
$object = new class {
|
||||
public function viewTypeDispose(&$column): void
|
||||
{
|
||||
switch ($column['column_type']) {
|
||||
case 'varchar':
|
||||
$column['view_type'] = 'input';
|
||||
break;
|
||||
// 富文本
|
||||
case 'text':
|
||||
case 'longtext':
|
||||
$column['is_list'] = 1;
|
||||
$column['is_query'] = 1;
|
||||
$column['view_type'] = 'editor';
|
||||
$options = [
|
||||
'height' => 400,
|
||||
];
|
||||
$column['options'] = $options;
|
||||
break;
|
||||
// 日期字段
|
||||
case 'datetime':
|
||||
$column['view_type'] = 'date';
|
||||
$options = [
|
||||
'mode' => 'datetime'
|
||||
];
|
||||
$column['options'] = $options;
|
||||
$column['query_type'] = 'between';
|
||||
break;
|
||||
case 'date':
|
||||
$column['view_type'] = 'date';
|
||||
$options = [
|
||||
'mode' => 'date'
|
||||
];
|
||||
$column['options'] = $options;
|
||||
$column['query_type'] = 'between';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function columnName(&$column): void
|
||||
{
|
||||
if (stristr($column['column_name'], 'name')) {
|
||||
$column['is_query'] = 2;
|
||||
$column['is_required'] = 2;
|
||||
$column['query_type'] = 'like';
|
||||
}
|
||||
|
||||
if (stristr($column['column_name'], 'title')) {
|
||||
$column['is_query'] = 2;
|
||||
$column['is_required'] = 2;
|
||||
$column['query_type'] = 'like';
|
||||
}
|
||||
|
||||
if (stristr($column['column_name'], 'type')) {
|
||||
$column['is_query'] = 2;
|
||||
$column['is_required'] = 2;
|
||||
$column['query_type'] = 'eq';
|
||||
}
|
||||
|
||||
if (stristr($column['column_name'], 'image')) {
|
||||
$column['is_query'] = 1;
|
||||
$column['view_type'] = 'uploadImage';
|
||||
$options = [
|
||||
'multiple' => false,
|
||||
'limit' => 1,
|
||||
];
|
||||
$column['options'] = $options;
|
||||
}
|
||||
|
||||
if (stristr($column['column_name'], 'file')) {
|
||||
$column['is_query'] = 1;
|
||||
$column['view_type'] = 'uploadFile';
|
||||
$options = [
|
||||
'multiple' => false,
|
||||
'limit' => 1,
|
||||
];
|
||||
$column['options'] = $options;
|
||||
}
|
||||
|
||||
if (stristr($column['column_name'], 'attach')) {
|
||||
$column['is_query'] = 1;
|
||||
$column['view_type'] = 'uploadFile';
|
||||
$options = [
|
||||
'multiple' => false,
|
||||
'limit' => 1,
|
||||
];
|
||||
$column['options'] = $options;
|
||||
}
|
||||
|
||||
if ($column['column_name'] === 'sort') {
|
||||
$column['view_type'] = 'inputNumber';
|
||||
}
|
||||
|
||||
if ($column['column_name'] === 'status') {
|
||||
$column['view_type'] = 'radio';
|
||||
$column['dict_type'] = 'data_status';
|
||||
}
|
||||
|
||||
if (stristr($column['column_name'], 'is_')) {
|
||||
$column['view_type'] = 'radio';
|
||||
$column['dict_type'] = 'yes_or_no';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!$column['is_cover']) {
|
||||
$object->viewTypeDispose($column);
|
||||
$object->columnName($column);
|
||||
}
|
||||
$column['options'] = json_encode($column['options'], JSON_UNESCAPED_UNICODE);
|
||||
return $column;
|
||||
}
|
||||
}
|
||||
478
server/plugin/saiadmin/app/logic/tool/GenerateTablesLogic.php
Normal file
478
server/plugin/saiadmin/app/logic/tool/GenerateTablesLogic.php
Normal file
@@ -0,0 +1,478 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | saiadmin [ saiadmin快速开发框架 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: sai <1430792918@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace plugin\saiadmin\app\logic\tool;
|
||||
|
||||
use plugin\saiadmin\app\cache\UserMenuCache;
|
||||
use plugin\saiadmin\app\logic\system\DatabaseLogic;
|
||||
use plugin\saiadmin\app\model\system\SystemMenu;
|
||||
use plugin\saiadmin\app\model\tool\GenerateTables;
|
||||
use plugin\saiadmin\app\model\tool\GenerateColumns;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use plugin\saiadmin\basic\think\BaseLogic;
|
||||
use plugin\saiadmin\utils\Helper;
|
||||
use plugin\saiadmin\utils\code\CodeZip;
|
||||
use plugin\saiadmin\utils\code\CodeEngine;
|
||||
|
||||
/**
|
||||
* 代码生成业务逻辑层
|
||||
*/
|
||||
class GenerateTablesLogic extends BaseLogic
|
||||
{
|
||||
protected $columnLogic = null;
|
||||
|
||||
protected $dataLogic = null;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->model = new GenerateTables();
|
||||
$this->columnLogic = new GenerateColumnsLogic();
|
||||
$this->dataLogic = new DatabaseLogic();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除表和字段信息
|
||||
* @param $ids
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy($ids): bool
|
||||
{
|
||||
return $this->transaction(function () use ($ids) {
|
||||
parent::destroy($ids);
|
||||
GenerateColumns::destroy(function ($query) use ($ids) {
|
||||
$query->where('table_id', 'in', $ids);
|
||||
});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 装载表信息
|
||||
* @param $names
|
||||
* @param $source
|
||||
* @return void
|
||||
*/
|
||||
public function loadTable($names, $source): void
|
||||
{
|
||||
$data = config('think-orm.connections');
|
||||
$config = $data[$source];
|
||||
if (!$config) {
|
||||
throw new ApiException('数据库配置读取失败');
|
||||
}
|
||||
|
||||
$prefix = $config['prefix'] ?? '';
|
||||
foreach ($names as $item) {
|
||||
$class_name = $item['name'];
|
||||
if (!empty($prefix)) {
|
||||
$class_name = Helper::str_replace_once($prefix, '', $class_name);
|
||||
}
|
||||
$class_name = Helper::camel($class_name);
|
||||
$tableInfo = [
|
||||
'table_name' => $item['name'],
|
||||
'table_comment' => $item['comment'],
|
||||
'class_name' => $class_name,
|
||||
'business_name' => Helper::get_business($item['name']),
|
||||
'belong_menu_id' => 80,
|
||||
'menu_name' => $item['comment'],
|
||||
'tpl_category' => 'single',
|
||||
'template' => 'app',
|
||||
'stub' => 'think',
|
||||
'namespace' => '',
|
||||
'package_name' => '',
|
||||
'source' => $source,
|
||||
'generate_menus' => 'index,save,update,read,destroy',
|
||||
];
|
||||
$model = GenerateTables::create($tableInfo);
|
||||
$columns = $this->dataLogic->getColumnList($item['name'], $source);
|
||||
foreach ($columns as &$column) {
|
||||
$column['table_id'] = $model->id;
|
||||
$column['is_cover'] = false;
|
||||
}
|
||||
$this->columnLogic->saveExtra($columns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步表字段信息
|
||||
* @param $id
|
||||
* @return void
|
||||
*/
|
||||
public function sync($id)
|
||||
{
|
||||
$model = $this->model->findOrEmpty($id);
|
||||
// 拉取已有数据表信息
|
||||
$queryModel = $this->columnLogic->model->where('table_id', $id);
|
||||
$columnLogicData = $this->columnLogic->getAll($queryModel);
|
||||
$columnLogicList = [];
|
||||
foreach ($columnLogicData as $item) {
|
||||
$columnLogicList[$item['column_name']] = $item;
|
||||
}
|
||||
GenerateColumns::destroy(function ($query) use ($id) {
|
||||
$query->where('table_id', $id);
|
||||
});
|
||||
$columns = $this->dataLogic->getColumnList($model->table_name, $model->source ?? '');
|
||||
foreach ($columns as &$column) {
|
||||
$column['table_id'] = $model->id;
|
||||
$column['is_cover'] = false;
|
||||
if (isset($columnLogicList[$column['column_name']])) {
|
||||
// 存在历史信息的情况
|
||||
$getcolumnLogicItem = $columnLogicList[$column['column_name']];
|
||||
if ($getcolumnLogicItem['column_type'] == $column['column_type']) {
|
||||
$column['is_cover'] = true;
|
||||
foreach ($getcolumnLogicItem as $key => $item) {
|
||||
$array = [
|
||||
'column_comment',
|
||||
'column_type',
|
||||
'default_value',
|
||||
'is_pk',
|
||||
'is_required',
|
||||
'is_insert',
|
||||
'is_edit',
|
||||
'is_list',
|
||||
'is_query',
|
||||
'is_sort',
|
||||
'query_type',
|
||||
'view_type',
|
||||
'dict_type',
|
||||
'options',
|
||||
'sort',
|
||||
'is_cover'
|
||||
];
|
||||
if (in_array($key, $array)) {
|
||||
$column[$key] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->columnLogic->saveExtra($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代码预览
|
||||
* @param $id
|
||||
* @return array
|
||||
*/
|
||||
public function preview($id): array
|
||||
{
|
||||
$data = $this->renderData($id);
|
||||
|
||||
$codeEngine = new CodeEngine($data);
|
||||
$controllerContent = $codeEngine->renderContent('php', 'controller.stub');
|
||||
$logicContent = $codeEngine->renderContent('php', 'logic.stub');
|
||||
$modelContent = $codeEngine->renderContent('php', 'model.stub');
|
||||
$validateContent = $codeEngine->renderContent('php', 'validate.stub');
|
||||
$sqlContent = $codeEngine->renderContent('sql', 'sql.stub');
|
||||
$indexContent = $codeEngine->renderContent('vue', 'index.stub');
|
||||
$editContent = $codeEngine->renderContent('vue', 'edit-dialog.stub');
|
||||
$searchContent = $codeEngine->renderContent('vue', 'table-search.stub');
|
||||
$apiContent = $codeEngine->renderContent('ts', 'api.stub');
|
||||
|
||||
// 返回生成内容
|
||||
return [
|
||||
[
|
||||
'tab_name' => 'controller.php',
|
||||
'name' => 'controller',
|
||||
'lang' => 'php',
|
||||
'code' => $controllerContent
|
||||
],
|
||||
[
|
||||
'tab_name' => 'logic.php',
|
||||
'name' => 'logic',
|
||||
'lang' => 'php',
|
||||
'code' => $logicContent
|
||||
],
|
||||
[
|
||||
'tab_name' => 'model.php',
|
||||
'name' => 'model',
|
||||
'lang' => 'php',
|
||||
'code' => $modelContent
|
||||
],
|
||||
[
|
||||
'tab_name' => 'validate.php',
|
||||
'name' => 'validate',
|
||||
'lang' => 'php',
|
||||
'code' => $validateContent
|
||||
],
|
||||
[
|
||||
'tab_name' => 'sql.sql',
|
||||
'name' => 'sql',
|
||||
'lang' => 'sql',
|
||||
'code' => $sqlContent
|
||||
],
|
||||
[
|
||||
'tab_name' => 'index.vue',
|
||||
'name' => 'index',
|
||||
'lang' => 'html',
|
||||
'code' => $indexContent
|
||||
],
|
||||
[
|
||||
'tab_name' => 'edit-dialog.vue',
|
||||
'name' => 'edit-dialog',
|
||||
'lang' => 'html',
|
||||
'code' => $editContent
|
||||
],
|
||||
[
|
||||
'tab_name' => 'table-search.vue',
|
||||
'name' => 'table-search',
|
||||
'lang' => 'html',
|
||||
'code' => $searchContent
|
||||
],
|
||||
[
|
||||
'tab_name' => 'api.ts',
|
||||
'name' => 'api',
|
||||
'lang' => 'javascript',
|
||||
'code' => $apiContent
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成到模块
|
||||
* @param $id
|
||||
*/
|
||||
public function genModule($id)
|
||||
{
|
||||
$data = $this->renderData($id);
|
||||
|
||||
// 生成文件到模块
|
||||
$codeEngine = new CodeEngine($data);
|
||||
$codeEngine->generateBackend('controller', $codeEngine->renderContent('php', 'controller.stub'));
|
||||
$codeEngine->generateBackend('logic', $codeEngine->renderContent('php', 'logic.stub'));
|
||||
$codeEngine->generateBackend('model', $codeEngine->renderContent('php', 'model.stub'));
|
||||
$codeEngine->generateBackend('validate', $codeEngine->renderContent('php', 'validate.stub'));
|
||||
$codeEngine->generateFrontend('index', $codeEngine->renderContent('vue', 'index.stub'));
|
||||
$codeEngine->generateFrontend('edit-dialog', $codeEngine->renderContent('vue', 'edit-dialog.stub'));
|
||||
$codeEngine->generateFrontend('table-search', $codeEngine->renderContent('vue', 'table-search.stub'));
|
||||
$codeEngine->generateFrontend('api', $codeEngine->renderContent('ts', 'api.stub'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据
|
||||
* @param $id
|
||||
* @return array
|
||||
*/
|
||||
protected function renderData($id): array
|
||||
{
|
||||
$table = $this->model->findOrEmpty($id);
|
||||
if (!in_array($table['template'], ["plugin", "app"])) {
|
||||
throw new ApiException('应用类型必须为plugin或者app');
|
||||
}
|
||||
if (empty($table['namespace'])) {
|
||||
throw new ApiException('请先设置应用名称');
|
||||
}
|
||||
|
||||
$columns = $this->columnLogic->where('table_id', $id)
|
||||
->order('sort', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
$pk = 'id';
|
||||
foreach ($columns as &$column) {
|
||||
if ($column['is_pk'] == 2) {
|
||||
$pk = $column['column_name'];
|
||||
}
|
||||
if ($column['column_name'] == 'delete_time') {
|
||||
unset($column['column_name']);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理特殊变量
|
||||
if ($table['template'] == 'plugin') {
|
||||
$namespace_start = "plugin\\" . $table['namespace'] . "\\app\\admin\\";
|
||||
$namespace_start_model = "plugin\\" . $table['namespace'] . "\\app\\";
|
||||
$namespace_end = "\\" . $table['package_name'];
|
||||
$url_path = 'app/' . $table['namespace'] . '/admin/' . $table['package_name'] . '/' . $table['class_name'];
|
||||
$route = 'app/';
|
||||
} else {
|
||||
$namespace_start = "app\\" . $table['namespace'] . "\\";
|
||||
$namespace_start_model = "app\\" . $table['namespace'] . "\\";
|
||||
$namespace_end = "\\" . $table['package_name'];
|
||||
$url_path = $table['namespace'] . '/' . $table['package_name'] . '/' . $table['class_name'];
|
||||
$route = '';
|
||||
}
|
||||
|
||||
$config = config('think-orm');
|
||||
|
||||
$data = $table->toArray();
|
||||
$data['pk'] = $pk;
|
||||
$data['namespace_start'] = $namespace_start;
|
||||
$data['namespace_start_model'] = $namespace_start_model;
|
||||
$data['namespace_end'] = $namespace_end;
|
||||
$data['url_path'] = $url_path;
|
||||
$data['route'] = $route;
|
||||
$data['tables'] = [$data];
|
||||
$data['columns'] = $columns;
|
||||
$data['db_source'] = $config['default'] ?? 'mysql';
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成到模块
|
||||
*/
|
||||
public function generateFile($id)
|
||||
{
|
||||
$table = $this->model->where('id', $id)->findOrEmpty();
|
||||
if ($table->isEmpty()) {
|
||||
throw new ApiException('请选择要生成的表');
|
||||
}
|
||||
$debug = config('app.debug', true);
|
||||
if (!$debug) {
|
||||
throw new ApiException('非调试模式下,不允许生成文件');
|
||||
}
|
||||
$this->updateMenu($table);
|
||||
$this->genModule($id);
|
||||
UserMenuCache::clearMenuCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* 代码生成下载
|
||||
*/
|
||||
public function generate($idsArr): array
|
||||
{
|
||||
$zip = new CodeZip();
|
||||
$tables = $this->model->where('id', 'in', $idsArr)->select()->toArray();
|
||||
foreach ($idsArr as $table_id) {
|
||||
$data = $this->renderData($table_id);
|
||||
$data['tables'] = $tables;
|
||||
$codeEngine = new CodeEngine($data);
|
||||
$codeEngine->generateTemp();
|
||||
}
|
||||
|
||||
$filename = 'saiadmin.zip';
|
||||
$download = $zip->compress();
|
||||
|
||||
return compact('filename', 'download');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理菜单列表
|
||||
* @param $tables
|
||||
*/
|
||||
public function updateMenu($tables)
|
||||
{
|
||||
/*不存在的情况下进行新建操作*/
|
||||
$url_path = $tables['namespace'] . ":" . $tables['package_name'] . ':' . $tables['business_name'];
|
||||
$code = $tables['namespace'] . "/" . $tables['package_name'] . '/' . $tables['business_name'];
|
||||
$path = $tables['package_name'] . '/' . $tables['business_name'];
|
||||
$component = $tables['namespace'] . "/" . $tables['package_name'] . '/' . $tables['business_name'];
|
||||
|
||||
/*先获取一下已有的路由中是否包含当前ID的路由的核心信息*/
|
||||
$model = new SystemMenu();
|
||||
$tableMenu = $model->where('generate_id', $tables['id'])->findOrEmpty();
|
||||
$fistMenu = [
|
||||
'parent_id' => $tables['belong_menu_id'],
|
||||
'name' => $tables['menu_name'],
|
||||
'code' => $code,
|
||||
'path' => $path,
|
||||
'icon' => 'ri:home-2-line',
|
||||
'component' => "/plugin/$component/index",
|
||||
'type' => 2,
|
||||
'sort' => 100,
|
||||
'is_iframe' => 2,
|
||||
'is_keep_alive' => 2,
|
||||
'is_hidden' => 2,
|
||||
'is_fixed_tab' => 2,
|
||||
'is_full_page' => 2,
|
||||
'generate_id' => $tables['id']
|
||||
];
|
||||
if ($tableMenu->isEmpty()) {
|
||||
$temp = SystemMenu::create($fistMenu);
|
||||
$fistMenuId = $temp->id;
|
||||
} else {
|
||||
$fistMenu['id'] = $tableMenu['id'];
|
||||
$tableMenu->save($fistMenu);
|
||||
$fistMenuId = $tableMenu['id'];
|
||||
}
|
||||
/*开始进行子权限的判定操作*/
|
||||
$childNodes = [
|
||||
['name' => '列表', 'key' => 'index'],
|
||||
['name' => '保存', 'key' => 'save'],
|
||||
['name' => '更新', 'key' => 'update'],
|
||||
['name' => '读取', 'key' => 'read'],
|
||||
['name' => '删除', 'key' => 'destroy'],
|
||||
];
|
||||
|
||||
foreach ($childNodes as $node) {
|
||||
$nodeData = $model->where('parent_id', $fistMenuId)->where('generate_key', $node['key'])->findOrEmpty();
|
||||
$childNodeData = [
|
||||
'parent_id' => $fistMenuId,
|
||||
'name' => $node['name'],
|
||||
'slug' => "$url_path:{$node['key']}",
|
||||
'type' => 3,
|
||||
'sort' => 100,
|
||||
'is_iframe' => 2,
|
||||
'is_keep_alive' => 2,
|
||||
'is_hidden' => 2,
|
||||
'is_fixed_tab' => 2,
|
||||
'is_full_page' => 2,
|
||||
'generate_key' => $node['key']
|
||||
];
|
||||
if (!empty($nodeData)) {
|
||||
$childNodeData['id'] = $nodeData['id'];
|
||||
$nodeData->save($childNodeData);
|
||||
} else {
|
||||
$menuModel = new SystemMenu();
|
||||
$menuModel->save($childNodeData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据表字段信息
|
||||
* @param $table_id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTableColumns($table_id): mixed
|
||||
{
|
||||
$query = $this->columnLogic->where('table_id', $table_id);
|
||||
return $this->columnLogic->getAll($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据
|
||||
* @param $id
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function edit($id, $data): mixed
|
||||
{
|
||||
$columns = $data['columns'];
|
||||
|
||||
unset($data['columns']);
|
||||
|
||||
if (!empty($data['belong_menu_id'])) {
|
||||
$data['belong_menu_id'] = is_array($data['belong_menu_id']) ? array_pop($data['belong_menu_id']) : $data['belong_menu_id'];
|
||||
} else {
|
||||
$data['belong_menu_id'] = 0;
|
||||
}
|
||||
|
||||
$data['generate_menus'] = implode(',', $data['generate_menus']);
|
||||
|
||||
if (empty($data['options'])) {
|
||||
unset($data['options']);
|
||||
}
|
||||
|
||||
$data['options'] = json_encode($data['options'], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
// 更新业务表
|
||||
$this->update($data, ['id' => $id]);
|
||||
|
||||
// 更新业务字段表
|
||||
foreach ($columns as $column) {
|
||||
if ($column['options']) {
|
||||
$column['options'] = json_encode($column['options'], JSON_NUMERIC_CHECK);
|
||||
}
|
||||
$this->columnLogic->update($column, ['id' => $column['id']]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user