初始化-安装依赖
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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user