first commit

This commit is contained in:
Your Name
2026-01-19 14:19:22 +08:00
commit fe2d9c1868
4777 changed files with 665503 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service;
use app\common\model\Config;
class ConfigService
{
/**
* @notes 设置配置值
* @param $type
* @param $name
* @param $value
* @return mixed
* @author 段誉
* @date 2021/12/27 15:00
*/
public static function set(string $type, string $name, $value)
{
$original = $value;
if (is_array($value)) {
$value = json_encode($value, JSON_UNESCAPED_UNICODE);
}
$data = Config::where(['type' => $type, 'name' => $name])->findOrEmpty();
if ($data->isEmpty()) {
Config::create([
'type' => $type,
'name' => $name,
'value' => $value,
]);
} else {
$data->value = $value;
$data->save();
}
// 返回原始值
return $original;
}
/**
* @notes 获取配置值
* @param $type
* @param string $name
* @param null $default_value
* @return array|int|mixed|string
* @author Tab
* @date 2021/7/15 15:16
*/
public static function get(string $type, string $name = '', $default_value = null)
{
if (!empty($name)) {
$value = Config::where(['type' => $type, 'name' => $name])->value('value');
if (!is_null($value)) {
$json = json_decode($value, true);
$value = json_last_error() === JSON_ERROR_NONE ? $json : $value;
}
if ($value) {
return $value;
}
// 返回特殊值 0 '0'
if ($value === 0 || $value === '0') {
return $value;
}
// 返回默认值
if ($default_value !== null) {
return $default_value;
}
// 返回本地配置文件中的值
return config('project.' . $type . '.' . $name);
}
// 取某个类型下的所有name的值
$data = Config::where(['type' => $type])->column('value', 'name');
foreach ($data as $k => $v) {
$json = json_decode($v, true);
if (json_last_error() === JSON_ERROR_NONE) {
$data[$k] = $json;
}
}
if ($data) {
return $data;
}
}
}

View File

@@ -0,0 +1,116 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service;
use think\facade\Cache;
class FileService
{
/**
* @notes 补全路径
* @param string $uri
* @param string $type
* @return string
* @author 段誉
* @date 2021/12/28 15:19
* @remark
* 场景一:补全域名路径,仅传参$uri;
* 例: FileService::getFileUrl('uploads/img.png');
* 返回 http://www.likeadmin.localhost/uploads/img.png
*
* 场景二:补全获取web根目录路径, 传参$uri 和 $type = public_path;
* 例: FileService::getFileUrl('uploads/img.png', 'public_path');
* 返回 /project-services/likeadmin/server/public/uploads/img.png
*
* 场景三:获取当前储存方式的域名
* 例: FileService::getFileUrl();
* 返回 http://www.likeadmin.localhost/
*/
public static function getFileUrl(string $uri = '', string $type = '') : string
{
if (strstr($uri, 'http://')) return $uri;
if (strstr($uri, 'https://')) return $uri;
$default = Cache::get('STORAGE_DEFAULT');
if (!$default) {
$default = ConfigService::get('storage', 'default', 'local');
Cache::set('STORAGE_DEFAULT', $default);
}
if ($default === 'local') {
if($type == 'public_path') {
return public_path(). $uri;
}
$domain = request()->domain();
} else {
$storage = Cache::get('STORAGE_ENGINE');
if (!$storage) {
$storage = ConfigService::get('storage', $default);
Cache::set('STORAGE_ENGINE', $storage);
}
$domain = $storage ? $storage['domain'] : '';
}
return self::format($domain, $uri);
}
/**
* @notes 转相对路径
* @param $uri
* @return mixed
* @author 张无忌
* @date 2021/7/28 15:09
*/
public static function setFileUrl($uri)
{
$default = ConfigService::get('storage', 'default', 'local');
if ($default === 'local') {
$domain = request()->domain();
return str_replace($domain.'/', '', $uri);
} else {
$storage = ConfigService::get('storage', $default);
return str_replace($storage['domain'].'/', '', $uri);
}
}
/**
* @notes 格式化url
* @param $domain
* @param $uri
* @return string
* @author 段誉
* @date 2022/7/11 10:36
*/
public static function format($domain, $uri)
{
// 处理域名
$domainLen = strlen($domain);
$domainRight = substr($domain, $domainLen -1, 1);
if ('/' == $domainRight) {
$domain = substr_replace($domain,'',$domainLen -1, 1);
}
// 处理uri
$uriLeft = substr($uri, 0, 1);
if('/' == $uriLeft) {
$uri = substr_replace($uri,'',0, 1);
}
return trim($domain) . '/' . trim($uri);
}
}

View File

@@ -0,0 +1,144 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service;
use app\common\enum\ExportEnum;
use app\common\lists\BaseDataLists;
use app\common\lists\ListsExcelInterface;
use app\common\lists\ListsExtendInterface;
use think\Response;
use think\response\Json;
use think\exception\HttpResponseException;
class JsonService
{
/**
* @notes 接口操作成功,返回信息
* @param string $msg
* @param array $data
* @param int $code
* @param int $show
* @return Json
* @author 段誉
* @date 2021/12/24 18:28
*/
public static function success(string $msg = 'success', array $data = [], int $code = 1, int $show = 1): Json
{
return self::result($code, $show, $msg, $data);
}
/**
* @notes 接口操作失败,返回信息
* @param string $msg
* @param array $data
* @param int $code
* @param int $show
* @return Json
* @author 段誉
* @date 2021/12/24 18:28
*/
public static function fail(string $msg = 'fail', array $data = [], int $code = 0, int $show = 1): Json
{
return self::result($code, $show, $msg, $data);
}
/**
* @notes 接口返回数据
* @param $data
* @return Json
* @author 段誉
* @date 2021/12/24 18:29
*/
public static function data($data): Json
{
return self::success('', $data, 1, 0);
}
/**
* @notes 接口返回信息
* @param int $code
* @param int $show
* @param string $msg
* @param array $data
* @param int $httpStatus
* @return Json
* @author 段誉
* @date 2021/12/24 18:29
*/
private static function result(int $code, int $show, string $msg = 'OK', array $data = [], int $httpStatus = 200): Json
{
$result = compact('code', 'show', 'msg', 'data');
return json($result, $httpStatus);
}
/**
* @notes 抛出异常json
* @param string $msg
* @param array $data
* @param int $code
* @param int $show
* @return Json
* @author 段誉
* @date 2021/12/24 18:29
*/
public static function throw(string $msg = 'fail', array $data = [], int $code = 0, int $show = 1): Json
{
$data = compact('code', 'show', 'msg', 'data');
$response = Response::create($data, 'json', 200);
throw new HttpResponseException($response);
}
/**
* @notes 数据列表
* @param \app\common\lists\BaseDataLists $lists
* @return \think\response\Json
* @author 令狐冲
* @date 2021/7/28 11:15
*/
public static function dataLists(BaseDataLists $lists): Json
{
//获取导出信息
if ($lists->export == ExportEnum::INFO && $lists instanceof ListsExcelInterface) {
return self::data($lists->excelInfo());
}
//获取导出文件的下载链接
if ($lists->export == ExportEnum::EXPORT && $lists instanceof ListsExcelInterface) {
$exportDownloadUrl = $lists->createExcel($lists->setExcelFields(), $lists->lists());
return self::success('', ['url' => $exportDownloadUrl], 2);
}
$data = [
'lists' => $lists->lists(),
'count' => $lists->count(),
'page_no' => $lists->pageNo,
'page_size' => $lists->pageSize,
];
$data['extend'] = [];
if ($lists instanceof ListsExtendInterface) {
$data['extend'] = $lists->extend();
}
return self::success('', $data, 1, 0);
}
}

View File

@@ -0,0 +1,168 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service;
use app\common\enum\FileEnum;
use app\common\model\file\File;
use app\common\service\storage\Driver as StorageDriver;
use Exception;
class UploadService
{
/**
* @notes 上传图片
* @param $cid
* @param int $user_id
* @param string $saveDir
* @return array
* @throws Exception
* @author 段誉
* @date 2021/12/29 16:30
*/
public static function image($cid, int $sourceId = 0, int $source = FileEnum::SOURCE_ADMIN, string $saveDir = 'uploads/images')
{
try {
$config = [
'default' => ConfigService::get('storage', 'default', 'local'),
'engine' => ConfigService::get('storage') ?? ['local'=>[]],
];
// 2、执行文件上传
$StorageDriver = new StorageDriver($config);
$StorageDriver->setUploadFile('file');
$fileName = $StorageDriver->getFileName();
$fileInfo = $StorageDriver->getFileInfo();
// 校验上传文件后缀
if (!in_array(strtolower($fileInfo['ext']), config('project.file_image'))) {
throw new Exception("上传图片不允许上传". $fileInfo['ext'] . "文件");
}
// 上传文件
if($source == 1){
$saveDir = $saveDir . '/user/' . date('Ymd');
}else{
$saveDir = $saveDir . '/' . date('Ymd');
}
if (!$StorageDriver->upload($saveDir)) {
throw new Exception($StorageDriver->getError());
}
// 3、处理文件名称
if (strlen($fileInfo['name']) > 128) {
$name = substr($fileInfo['name'], 0, 123);
$nameEnd = substr($fileInfo['name'], strlen($fileInfo['name'])-5, strlen($fileInfo['name']));
$fileInfo['name'] = $name . $nameEnd;
}
// 4、写入数据库中
$file = File::create([
'cid' => $cid,
'type' => FileEnum::IMAGE_TYPE,
'name' => $fileInfo['name'],
'uri' => $saveDir . '/' . str_replace("\\","/", $fileName),
'source' => $source,
'source_id' => $sourceId,
'create_time' => time(),
]);
// 5、返回结果
return [
'id' => $file['id'],
'cid' => $file['cid'],
'type' => $file['type'],
'name' => $file['name'],
'uri' => FileService::getFileUrl($file['uri']),
'url' => $file['uri']
];
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
/**
* @notes 视频上传
* @param $cid
* @param int $user_id
* @param string $saveDir
* @return array
* @throws Exception
* @author 段誉
* @date 2021/12/29 16:32
*/
public static function video($cid, int $sourceId = 0, int $source = FileEnum::SOURCE_ADMIN, string $saveDir = 'uploads/video')
{
try {
$config = [
'default' => ConfigService::get('storage', 'default', 'local'),
'engine' => ConfigService::get('storage') ?? ['local'=>[]],
];
// 2、执行文件上传
$StorageDriver = new StorageDriver($config);
$StorageDriver->setUploadFile('file');
$fileName = $StorageDriver->getFileName();
$fileInfo = $StorageDriver->getFileInfo();
// 校验上传文件后缀
if (!in_array(strtolower($fileInfo['ext']), config('project.file_video'))) {
throw new Exception("上传视频不允许上传". $fileInfo['ext'] . "文件");
}
// 上传文件
$saveDir = $saveDir . '/' . date('Ymd');
if (!$StorageDriver->upload($saveDir)) {
throw new Exception($StorageDriver->getError());
}
// 3、处理文件名称
if (strlen($fileInfo['name']) > 128) {
$name = substr($fileInfo['name'], 0, 123);
$nameEnd = substr($fileInfo['name'], strlen($fileInfo['name'])-5, strlen($fileInfo['name']));
$fileInfo['name'] = $name . $nameEnd;
}
// 4、写入数据库中
$file = File::create([
'cid' => $cid,
'type' => FileEnum::VIDEO_TYPE,
'name' => $fileInfo['name'],
'uri' => $saveDir . '/' . str_replace("\\","/", $fileName),
'source' => $source,
'source_id' => $sourceId,
'create_time' => time(),
]);
// 5、返回结果
return [
'id' => $file['id'],
'cid' => $file['cid'],
'type' => $file['type'],
'name' => $file['name'],
'uri' => FileService::getFileUrl($file['uri']),
'url' => $file['uri']
];
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,230 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service\generator;
use app\common\service\generator\core\ControllerGenerator;
use app\common\service\generator\core\ListsGenerator;
use app\common\service\generator\core\LogicGenerator;
use app\common\service\generator\core\ModelGenerator;
use app\common\service\generator\core\SqlGenerator;
use app\common\service\generator\core\ValidateGenerator;
use app\common\service\generator\core\VueApiGenerator;
use app\common\service\generator\core\VueEditGenerator;
use app\common\service\generator\core\VueIndexGenerator;
/**
* 生成器
* Class GenerateService
* @package app\common\service\generator
*/
class GenerateService
{
// 标记
protected $flag;
// 生成文件路径
protected $generatePath;
// runtime目录
protected $runtimePath;
// 压缩包名称
protected $zipTempName;
// 压缩包临时路径
protected $zipTempPath;
public function __construct()
{
$this->generatePath = root_path() . 'runtime/generate/';
$this->runtimePath = root_path() . 'runtime/';
}
/**
* @notes 删除生成文件夹内容
* @author 段誉
* @date 2022/6/23 18:52
*/
public function delGenerateDirContent()
{
// 删除runtime目录制定文件夹
!is_dir($this->generatePath) && mkdir($this->generatePath, 0755, true);
del_target_dir($this->generatePath, false);
}
/**
* @notes 设置生成状态
* @param $name
* @param false $status
* @author 段誉
* @date 2022/6/23 18:53
*/
public function setGenerateFlag($name, $status = false)
{
$this->flag = $name;
cache($name, (int)$status, 3600);
}
/**
* @notes 获取生成状态标记
* @return mixed|object|\think\App
* @author 段誉
* @date 2022/6/23 18:53
*/
public function getGenerateFlag()
{
return cache($this->flag);
}
/**
* @notes 删除标记时间
* @author 段誉
* @date 2022/6/23 18:53
*/
public function delGenerateFlag()
{
cache($this->flag, null);
}
/**
* @notes 生成器相关类
* @return string[]
* @author 段誉
* @date 2022/6/23 17:17
*/
public function getGeneratorClass()
{
return [
ControllerGenerator::class,
ListsGenerator::class,
ModelGenerator::class,
ValidateGenerator::class,
LogicGenerator::class,
VueApiGenerator::class,
VueIndexGenerator::class,
VueEditGenerator::class,
SqlGenerator::class,
];
}
/**
* @notes 生成文件
* @param array $tableData
* @author 段誉
* @date 2022/6/23 18:52
*/
public function generate(array $tableData)
{
foreach ($this->getGeneratorClass() as $item) {
$generator = app()->make($item);
$generator->initGenerateData($tableData);
$generator->generate();
// 是否为压缩包下载
if ($generator->isGenerateTypeZip()) {
$this->setGenerateFlag($this->flag, true);
}
// 是否构建菜单
if ($item == 'app\common\service\generator\core\SqlGenerator') {
$generator->isBuildMenu() && $generator->buildMenuHandle();
}
}
}
/**
* @notes 预览文件
* @param array $tableData
* @return array
* @author 段誉
* @date 2022/6/23 18:52
*/
public function preview(array $tableData)
{
$data = [];
foreach ($this->getGeneratorClass() as $item) {
$generator = app()->make($item);
$generator->initGenerateData($tableData);
$data[] = $generator->fileInfo();
}
return $data;
}
/**
* @notes 压缩文件
* @author 段誉
* @date 2022/6/23 19:02
*/
public function zipFile()
{
$fileName = 'curd-' . date('YmdHis') . '.zip';
$this->zipTempName = $fileName;
$this->zipTempPath = $this->generatePath . $fileName;
$zip = new \ZipArchive();
$zip->open($this->zipTempPath, \ZipArchive::CREATE);
$this->addFileZip($this->runtimePath, 'generate', $zip);
$zip->close();
}
/**
* @notes 往压缩包写入文件
* @param $basePath
* @param $dirName
* @param $zip
* @author 段誉
* @date 2022/6/23 19:02
*/
public function addFileZip($basePath, $dirName, $zip)
{
$handler = opendir($basePath . $dirName);
while (($filename = readdir($handler)) !== false) {
if ($filename != '.' && $filename != '..') {
if (is_dir($basePath . $dirName . '/' . $filename)) {
// 当前路径是文件夹
$this->addFileZip($basePath, $dirName . '/' . $filename, $zip);
} else {
// 写入文件到压缩包
$zip->addFile($basePath . $dirName . '/' . $filename, $dirName . '/' . $filename);
}
}
}
closedir($handler);
}
/**
* @notes 返回压缩包临时路径
* @return mixed
* @author 段誉
* @date 2022/6/24 9:41
*/
public function getDownloadUrl()
{
$vars = ['file' => $this->zipTempName];
cache('curd_file_name' . $this->zipTempName, $this->zipTempName, 3600);
return (string)url("adminapi/tools.generator/download", $vars, false, true);
}
}

View File

@@ -0,0 +1,483 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
use think\helper\Str;
use app\common\enum\GeneratorEnum;
/**
* 生成器基类
* Class BaseGenerator
* @package app\common\service\generator\core
*/
abstract class BaseGenerator
{
/**
* 模板文件夹
* @var string
*/
protected $templateDir;
/**
* 模块名
* @var string
*/
protected $moduleName;
/**
* 类目录
* @var string
*/
protected $classDir;
/**
* 表信息
* @var array
*/
protected $tableData;
/**
* 表字段信息
* @var array
*/
protected $tableColumn;
/**
* 文件内容
* @var string
*/
protected $content;
/**
* basePath
* @var string
*/
protected $basePath;
/**
* rootPath
* @var string
*/
protected $rootPath;
/**
* 生成的文件夹
* @var string
*/
protected $generatorDir;
/**
* 删除配置
* @var array
*/
protected $deleteConfig;
/**
* 菜单配置
* @var array
*/
protected $menuConfig;
/**
* 模型关联配置
* @var array
*/
protected $relationConfig;
/**
* 树表配置
* @var array
*/
protected $treeConfig;
public function __construct()
{
$this->basePath = base_path();
$this->rootPath = root_path();
$this->templateDir = $this->basePath . 'common/service/generator/stub/';
$this->generatorDir = $this->rootPath . 'runtime/generate/';
$this->checkDir($this->generatorDir);
}
/**
* @notes 初始化表表数据
* @param array $tableData
* @author 段誉
* @date 2022/6/22 18:03
*/
public function initGenerateData(array $tableData)
{
// 设置当前表信息
$this->setTableData($tableData);
// 设置模块名
$this->setModuleName($tableData['module_name']);
// 设置类目录
$this->setClassDir($tableData['class_dir'] ?? '');
// 替换模板变量
$this->replaceVariables();
}
/**
* @notes 菜单配置
* @author 段誉
* @date 2022/12/13 15:14
*/
public function setMenuConfig()
{
$this->menuConfig = [
'pid' => $this->tableData['menu']['pid'] ?? 0,
'type' => $this->tableData['menu']['type'] ?? GeneratorEnum::DELETE_TRUE,
'name' => $this->tableData['menu']['name'] ?? $this->tableData['table_comment']
];
}
/**
* @notes 删除配置
* @return array
* @author 段誉
* @date 2022/12/13 15:09
*/
public function setDeleteConfig()
{
$this->deleteConfig = [
'type' => $this->tableData['delete']['type'] ?? GeneratorEnum::DELETE_TRUE,
'name' => $this->tableData['delete']['name'] ?? GeneratorEnum::DELETE_NAME,
];
}
/**
* @notes 关联模型配置
* @author 段誉
* @date 2022/12/14 11:28
*/
public function setRelationConfig()
{
$this->relationConfig = empty($this->tableData['relations']) ? [] : $this->tableData['relations'];
}
/**
* @notes 设置树表配置
* @author 段誉
* @date 2022/12/20 14:30
*/
public function setTreeConfig()
{
$this->treeConfig = [
'tree_id' => $this->tableData['tree']['tree_id'] ?? '',
'tree_pid' => $this->tableData['tree']['tree_pid'] ?? '',
'tree_name' => $this->tableData['tree']['tree_name'] ?? '',
];
}
/**
* @notes 生成文件到模块或runtime目录
* @author 段誉
* @date 2022/6/22 18:03
*/
public function generate()
{
//生成方式 0-压缩包下载 1-生成到模块
if ($this->tableData['generate_type']) {
// 生成路径
$path = $this->getModuleGenerateDir() . $this->getGenerateName();
} else {
// 生成到runtime目录
$path = $this->getRuntimeGenerateDir() . $this->getGenerateName();
}
// 写入内容
file_put_contents($path, $this->content);
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return mixed
* @author 段誉
* @date 2022/6/22 18:05
*/
abstract public function getModuleGenerateDir();
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return mixed
* @author 段誉
* @date 2022/6/22 18:05
*/
abstract public function getRuntimeGenerateDir();
/**
* @notes 替换模板变量
* @return mixed
* @author 段誉
* @date 2022/6/22 18:06
*/
abstract public function replaceVariables();
/**
* @notes 生成文件名
* @return mixed
* @author 段誉
* @date 2022/6/22 18:17
*/
abstract public function getGenerateName();
/**
* @notes 文件夹不存在则创建
* @param string $path
* @author 段誉
* @date 2022/6/22 18:07
*/
public function checkDir(string $path)
{
!is_dir($path) && mkdir($path, 0755, true);
}
/**
* @notes 设置表信息
* @param $tableData
* @author 段誉
* @date 2022/6/22 18:07
*/
public function setTableData($tableData)
{
$this->tableData = !empty($tableData) ? $tableData : [];
$this->tableColumn = $tableData['table_column'] ?? [];
// 菜单配置
$this->setMenuConfig();
// 删除配置
$this->setDeleteConfig();
// 关联模型配置
$this->setRelationConfig();
// 设置树表配置
$this->setTreeConfig();
}
/**
* @notes 设置模块名
* @param string $moduleName
* @author 段誉
* @date 2022/6/22 18:07
*/
public function setModuleName(string $moduleName): void
{
$this->moduleName = strtolower($moduleName);
}
/**
* @notes 设置类目录
* @param string $classDir
* @author 段誉
* @date 2022/6/22 18:08
*/
public function setClassDir(string $classDir): void
{
$this->classDir = $classDir;
}
/**
* @notes 设置生成文件内容
* @param string $content
* @author 段誉
* @date 2022/6/22 18:08
*/
public function setContent(string $content): void
{
$this->content = $content;
}
/**
* @notes 获取模板路径
* @param string $templateName
* @return string
* @author 段誉
* @date 2022/6/22 18:09
*/
public function getTemplatePath(string $templateName): string
{
return $this->templateDir . $templateName . '.stub';
}
/**
* @notes 小驼峰命名
* @return string
* @author 段誉
* @date 2022/6/27 18:44
*/
public function getLowerCamelName()
{
return Str::camel($this->getTableName());
}
/**
* @notes 大驼峰命名
* @return string
* @author 段誉
* @date 2022/6/22 18:09
*/
public function getUpperCamelName()
{
return Str::studly($this->getTableName());
}
/**
* @notes 表名小写
* @return string
* @author 段誉
* @date 2022/7/12 10:41
*/
public function getLowerTableName()
{
return Str::lower($this->getTableName());
}
/**
* @notes 获取表名
* @return array|string|string[]
* @author 段誉
* @date 2022/6/22 18:09
*/
public function getTableName()
{
return get_no_prefix_table_name($this->tableData['table_name']);
}
/**
* @notes 获取表主键
* @return mixed|string
* @author 段誉
* @date 2022/6/22 18:09
*/
public function getPkContent()
{
$pk = 'id';
if (empty($this->tableColumn)) {
return $pk;
}
foreach ($this->tableColumn as $item) {
if ($item['is_pk']) {
$pk = $item['column_name'];
}
}
return $pk;
}
/**
* @notes 获取作者信息
* @return mixed|string
* @author 段誉
* @date 2022/6/24 10:18
*/
public function getAuthorContent()
{
return empty($this->tableData['author']) ? 'likeadmin' : $this->tableData['author'];
}
/**
* @notes 代码生成备注时间
* @return false|string
* @author 段誉
* @date 2022/6/24 10:28
*/
public function getNoteDateContent()
{
return date('Y/m/d H:i');
}
/**
* @notes 设置空额占位符
* @param $content
* @param $blankpace
* @return string
* @author 段誉
* @date 2022/6/22 18:09
*/
public function setBlankSpace($content, $blankpace)
{
$content = explode(PHP_EOL, $content);
foreach ($content as $line => $text) {
$content[$line] = $blankpace . $text;
}
return (implode(PHP_EOL, $content));
}
/**
* @notes 替换内容
* @param $needReplace
* @param $waitReplace
* @param $template
* @return array|false|string|string[]
* @author 段誉
* @date 2022/6/23 9:52
*/
public function replaceFileData($needReplace, $waitReplace, $template)
{
return str_replace($needReplace, $waitReplace, file_get_contents($template));
}
/**
* @notes 生成方式是否为压缩包
* @return bool
* @author 段誉
* @date 2022/6/23 17:02
*/
public function isGenerateTypeZip()
{
return $this->tableData['generate_type'] == GeneratorEnum::GENERATE_TYPE_ZIP;
}
/**
* @notes 是否为树表crud
* @return bool
* @author 段誉
* @date 2022/12/23 11:25
*/
public function isTreeCrud()
{
return $this->tableData['template_type'] == GeneratorEnum::TEMPLATE_TYPE_TREE;
}
}

View File

@@ -0,0 +1,223 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
/**
* 控制器生成器
* Class ControllerGenerator
* @package app\common\service\generator\core
*/
class ControllerGenerator extends BaseGenerator implements GenerateInterface
{
/**
* @notes 替换变量
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:09
*/
public function replaceVariables()
{
// 需要替换的变量
$needReplace = [
'{NAMESPACE}',
'{USE}',
'{CLASS_COMMENT}',
'{UPPER_CAMEL_NAME}',
'{MODULE_NAME}',
'{PACKAGE_NAME}',
'{EXTENDS_CONTROLLER}',
'{NOTES}',
'{AUTHOR}',
'{DATE}'
];
// 等待替换的内容
$waitReplace = [
$this->getNameSpaceContent(),
$this->getUseContent(),
$this->getClassCommentContent(),
$this->getUpperCamelName(),
$this->moduleName,
$this->getPackageNameContent(),
$this->getExtendsControllerContent(),
$this->tableData['class_comment'],
$this->getAuthorContent(),
$this->getNoteDateContent(),
];
$templatePath = $this->getTemplatePath('php/controller');
// 替换内容
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
$this->setContent($content);
}
/**
* @notes 获取命名空间内容
* @return string
* @author 段誉
* @date 2022/6/22 18:10
*/
public function getNameSpaceContent()
{
if (!empty($this->classDir)) {
return "namespace app\\" . $this->moduleName . "\\controller\\" . $this->classDir . ';';
}
return "namespace app\\" . $this->moduleName . "\\controller;";
}
/**
* @notes 获取use模板内容
* @return string
* @author 段誉
* @date 2022/6/22 18:10
*/
public function getUseContent()
{
if ($this->moduleName == 'adminapi') {
$tpl = "use app\\" . $this->moduleName . "\\controller\\BaseAdminController;" . PHP_EOL;
} else {
$tpl = "use app\\common\\controller\\BaseLikeAdminController;" . PHP_EOL;
}
if (!empty($this->classDir)) {
$tpl .= "use app\\" . $this->moduleName . "\\lists\\" . $this->classDir . "\\" . $this->getUpperCamelName() . "Lists;" . PHP_EOL .
"use app\\" . $this->moduleName . "\\logic\\" . $this->classDir . "\\" . $this->getUpperCamelName() . "Logic;" . PHP_EOL .
"use app\\" . $this->moduleName . "\\validate\\" . $this->classDir . "\\" . $this->getUpperCamelName() . "Validate;";
} else {
$tpl .= "use app\\" . $this->moduleName . "\\lists\\" . $this->getUpperCamelName() . "Lists;" . PHP_EOL .
"use app\\" . $this->moduleName . "\\logic\\" . $this->getUpperCamelName() . "Logic;" . PHP_EOL .
"use app\\" . $this->moduleName . "\\validate\\" . $this->getUpperCamelName() . "Validate;";
}
return $tpl;
}
/**
* @notes 获取类描述内容
* @return string
* @author 段誉
* @date 2022/6/22 18:10
*/
public function getClassCommentContent()
{
if (!empty($this->tableData['class_comment'])) {
$tpl = $this->tableData['class_comment'] . '控制器';
} else {
$tpl = $this->getUpperCamelName() . '控制器';
}
return $tpl;
}
/**
* @notes 获取包名
* @return string
* @author 段誉
* @date 2022/6/22 18:10
*/
public function getPackageNameContent()
{
return !empty($this->classDir) ? '\\' . $this->classDir : '';
}
/**
* @notes 获取继承控制器
* @return string
* @author 段誉
* @date 2022/6/22 18:10
*/
public function getExtendsControllerContent()
{
$tpl = 'BaseAdminController';
if ($this->moduleName != 'adminapi') {
$tpl = 'BaseLikeAdminController';
}
return $tpl;
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:10
*/
public function getModuleGenerateDir()
{
$dir = $this->basePath . $this->moduleName . '/controller/';
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:11
*/
public function getRuntimeGenerateDir()
{
$dir = $this->generatorDir . 'php/app/' . $this->moduleName . '/controller/';
$this->checkDir($dir);
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 生成文件名
* @return string
* @author 段誉
* @date 2022/6/22 18:11
*/
public function getGenerateName()
{
return $this->getUpperCamelName() . 'Controller.php';
}
/**
* @notes 文件信息
* @return array
* @author 段誉
* @date 2022/6/23 15:57
*/
public function fileInfo(): array
{
return [
'name' => $this->getGenerateName(),
'type' => 'php',
'content' => $this->content
];
}
}

View File

@@ -0,0 +1,23 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service\generator\core;
interface GenerateInterface
{
public function generate();
public function fileInfo();
}

View File

@@ -0,0 +1,338 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
use app\common\enum\GeneratorEnum;
/**
* 列表生成器
* Class ListsGenerator
* @package app\common\service\generator\core
*/
class ListsGenerator extends BaseGenerator implements GenerateInterface
{
/**
* @notes 替换变量
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:12
*/
public function replaceVariables()
{
// 需要替换的变量
$needReplace = [
'{NAMESPACE}',
'{USE}',
'{CLASS_COMMENT}',
'{UPPER_CAMEL_NAME}',
'{MODULE_NAME}',
'{PACKAGE_NAME}',
'{EXTENDS_LISTS}',
'{PK}',
'{QUERY_CONDITION}',
'{FIELD_DATA}',
'{NOTES}',
'{AUTHOR}',
'{DATE}',
];
// 等待替换的内容
$waitReplace = [
$this->getNameSpaceContent(),
$this->getUseContent(),
$this->getClassCommentContent(),
$this->getUpperCamelName(),
$this->moduleName,
$this->getPackageNameContent(),
$this->getExtendsListsContent(),
$this->getPkContent(),
$this->getQueryConditionContent(),
$this->getFieldDataContent(),
$this->tableData['class_comment'],
$this->getAuthorContent(),
$this->getNoteDateContent(),
];
$templatePath = $this->getTemplatePath('php/lists');
if ($this->isTreeCrud()) {
// 插入树表相关
array_push($needReplace, '{TREE_ID}', '{TREE_PID}');
array_push($waitReplace, $this->treeConfig['tree_id'], $this->treeConfig['tree_pid']);
$templatePath = $this->getTemplatePath('php/tree_lists');
}
// 替换内容
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
$this->setContent($content);
}
/**
* @notes 获取命名空间内容
* @return string
* @author 段誉
* @date 2022/6/22 18:12
*/
public function getNameSpaceContent()
{
if (!empty($this->classDir)) {
return "namespace app\\" . $this->moduleName . "\\lists\\" . $this->classDir . ';';
}
return "namespace app\\" . $this->moduleName . "\\lists;";
}
/**
* @notes 获取use内容
* @return string
* @author 段誉
* @date 2022/6/22 18:12
*/
public function getUseContent()
{
if ($this->moduleName == 'adminapi') {
$tpl = "use app\\" . $this->moduleName . "\\lists\\BaseAdminDataLists;" . PHP_EOL;
} else {
$tpl = "use app\\common\\lists\\BaseDataLists;" . PHP_EOL;
}
if (!empty($this->classDir)) {
$tpl .= "use app\\common\\model\\" . $this->classDir . "\\" . $this->getUpperCamelName() . ';';
} else {
$tpl .= "use app\\common\\model\\" . $this->getUpperCamelName() . ';';
}
return $tpl;
}
/**
* @notes 获取类描述
* @return string
* @author 段誉
* @date 2022/6/22 18:12
*/
public function getClassCommentContent()
{
if (!empty($this->tableData['class_comment'])) {
$tpl = $this->tableData['class_comment'] . '列表';
} else {
$tpl = $this->getUpperCamelName() . '列表';
}
return $tpl;
}
/**
* @notes 获取包名
* @return string
* @author 段誉
* @date 2022/6/22 18:12
*/
public function getPackageNameContent()
{
return !empty($this->classDir) ? $this->classDir : '';
}
/**
* @notes 获取继承控制器
* @return string
* @author 段誉
* @date 2022/6/22 18:12
*/
public function getExtendsListsContent()
{
$tpl = 'BaseAdminDataLists';
if ($this->moduleName != 'adminapi') {
$tpl = 'BaseDataLists';
}
return $tpl;
}
/**
* @notes 获取查询条件内容
* @return string
* @author 段誉
* @date 2022/6/22 18:12
*/
public function getQueryConditionContent()
{
$columnQuery = array_column($this->tableColumn, 'query_type');
$query = array_unique($columnQuery);
$conditon = '';
$specQueryHandle = ['between', 'like'];
foreach ($query as $queryName) {
$columnValue = '';
foreach ($this->tableColumn as $column) {
if (empty($column['query_type']) || $column['is_pk']) {
continue;
}
if ($queryName == $column['query_type'] && $column['is_query'] && !in_array($queryName, $specQueryHandle)) {
$columnValue .= "'" . $column['column_name'] . "', ";
}
}
if (!empty($columnValue)) {
$columnValue = substr($columnValue, 0, -2);
$conditon .= "'$queryName' => [" . trim($columnValue) . "]," . PHP_EOL;
}
}
$likeColumn = '';
$betweenColumn = '';
$betweenTimeColumn = '';
// 另外处理between,like 等查询条件
foreach ($this->tableColumn as $item) {
if (!$item['is_query']) {
continue;
}
// like
if ($item['query_type'] == 'like') {
$likeColumn .= "'" . $item['column_name'] . "', ";
continue;
}
// between
if ($item['query_type'] == 'between') {
if ($item['view_type'] == 'datetime') {
$betweenTimeColumn .= "'" . $item['column_name'] . "', ";
} else {
$betweenColumn .= "'" . $item['column_name'] . "', ";
}
}
}
if (!empty($likeColumn)) {
$likeColumn = substr($likeColumn, 0, -2);
$conditon .= "'%like%' => " . "[" . trim($likeColumn) . "]," . PHP_EOL;
}
if (!empty($betweenColumn)) {
$betweenColumn = substr($betweenColumn, 0, -2);
$conditon .= "'between' => " . "[" . trim($betweenColumn) . "]," . PHP_EOL;
}
if (!empty($betweenTimeColumn)) {
$betweenTimeColumn = substr($betweenTimeColumn, 0, -2);
$conditon .= "'between_time' => " . "[" . trim($betweenTimeColumn) . "]," . PHP_EOL;
}
$content = substr($conditon, 0, -1);
return $this->setBlankSpace($content, " ");
}
/**
* @notes 获取查询字段
* @return false|string
* @author 段誉
* @date 2022/6/22 18:13
*/
public function getFieldDataContent()
{
$content = "'" . $this->getPkContent() . "', ";
$isExist = [$this->getPkContent()];
foreach ($this->tableColumn as $column) {
if ($column['is_lists'] && !in_array($column['column_name'], $isExist)) {
$content .= "'" . $column['column_name'] . "', ";
$isExist[] = $column['column_name'];
}
if ($this->isTreeCrud() && !in_array($column['column_name'], $isExist)
&& in_array($column['column_name'], [$this->treeConfig['tree_id'], $this->treeConfig['tree_pid']])
) {
$content .= "'" . $column['column_name'] . "', ";
}
}
return substr($content, 0, -2);
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:13
*/
public function getModuleGenerateDir()
{
$dir = $this->basePath . $this->moduleName . '/lists/';
$this->checkDir($dir);
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:13
*/
public function getRuntimeGenerateDir()
{
$dir = $this->generatorDir . 'php/app/' . $this->moduleName . '/lists/';
$this->checkDir($dir);
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 生成的文件名
* @return string
* @author 段誉
* @date 2022/6/22 18:13
*/
public function getGenerateName()
{
return $this->getUpperCamelName() . 'Lists.php';
}
/**
* @notes 文件信息
* @return array
* @author 段誉
* @date 2022/6/23 15:57
*/
public function fileInfo(): array
{
return [
'name' => $this->getGenerateName(),
'type' => 'php',
'content' => $this->content
];
}
}

View File

@@ -0,0 +1,268 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
/**
* 逻辑生成器
* Class LogicGenerator
* @package app\common\service\generator\core
*/
class LogicGenerator extends BaseGenerator implements GenerateInterface
{
/**
* @notes 替换变量
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:14
*/
public function replaceVariables()
{
// 需要替换的变量
$needReplace = [
'{NAMESPACE}',
'{USE}',
'{CLASS_COMMENT}',
'{UPPER_CAMEL_NAME}',
'{MODULE_NAME}',
'{PACKAGE_NAME}',
'{PK}',
'{CREATE_DATA}',
'{UPDATE_DATA}',
'{NOTES}',
'{AUTHOR}',
'{DATE}'
];
// 等待替换的内容
$waitReplace = [
$this->getNameSpaceContent(),
$this->getUseContent(),
$this->getClassCommentContent(),
$this->getUpperCamelName(),
$this->moduleName,
$this->getPackageNameContent(),
$this->getPkContent(),
$this->getCreateDataContent(),
$this->getUpdateDataContent(),
$this->tableData['class_comment'],
$this->getAuthorContent(),
$this->getNoteDateContent(),
];
$templatePath = $this->getTemplatePath('php/logic');
// 替换内容
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
$this->setContent($content);
}
/**
* @notes 添加内容
* @return string
* @author 段誉
* @date 2022/6/22 18:14
*/
public function getCreateDataContent()
{
$content = '';
foreach ($this->tableColumn as $column) {
if (!$column['is_insert']) {
continue;
}
$content .= $this->addEditColumn($column);
}
if (empty($content)) {
return $content;
}
$content = substr($content, 0, -2);
return $this->setBlankSpace($content, " ");
}
/**
* @notes 编辑内容
* @return string
* @author 段誉
* @date 2022/6/22 18:14
*/
public function getUpdateDataContent()
{
$columnContent = '';
foreach ($this->tableColumn as $column) {
if (!$column['is_update']) {
continue;
}
$columnContent .= $this->addEditColumn($column);
}
if (empty($columnContent)) {
return $columnContent;
}
$columnContent = substr($columnContent, 0, -2);
$content = $columnContent;
return $this->setBlankSpace($content, " ");
}
/**
* @notes 添加编辑字段内容
* @param $column
* @return mixed
* @author 段誉
* @date 2022/6/27 15:37
*/
public function addEditColumn($column)
{
if ($column['column_type'] == 'int' && $column['view_type'] == 'datetime') {
// 物理类型为int显示类型选择日期的情况
$content = "'" . $column['column_name'] . "' => " . 'strtotime($params[' . "'" . $column['column_name'] . "'" . ']),' . PHP_EOL;
} else {
$content = "'" . $column['column_name'] . "' => " . '$params[' . "'" . $column['column_name'] . "'" . '],' . PHP_EOL;
}
return $content;
}
/**
* @notes 获取命名空间内容
* @return string
* @author 段誉
* @date 2022/6/22 18:14
*/
public function getNameSpaceContent()
{
if (!empty($this->classDir)) {
return "namespace app\\" . $this->moduleName . "\\logic\\" . $this->classDir . ';';
}
return "namespace app\\" . $this->moduleName . "\\logic;";
}
/**
* @notes 获取use内容
* @return string
* @author 段誉
* @date 2022/6/22 18:14
*/
public function getUseContent()
{
$tpl = "use app\\common\\model\\" . $this->getUpperCamelName() . ';';
if (!empty($this->classDir)) {
$tpl = "use app\\common\\model\\" . $this->classDir . "\\" . $this->getUpperCamelName() . ';';
}
return $tpl;
}
/**
* @notes 获取类描述
* @return string
* @author 段誉
* @date 2022/6/22 18:14
*/
public function getClassCommentContent()
{
if (!empty($this->tableData['class_comment'])) {
$tpl = $this->tableData['class_comment'] . '逻辑';
} else {
$tpl = $this->getUpperCamelName() . '逻辑';
}
return $tpl;
}
/**
* @notes 获取包名
* @return string
* @author 段誉
* @date 2022/6/22 18:14
*/
public function getPackageNameContent()
{
return !empty($this->classDir) ? '\\' . $this->classDir : '';
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:15
*/
public function getModuleGenerateDir()
{
$dir = $this->basePath . $this->moduleName . '/logic/';
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:15
*/
public function getRuntimeGenerateDir()
{
$dir = $this->generatorDir . 'php/app/' . $this->moduleName . '/logic/';
$this->checkDir($dir);
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 生成的文件名
* @return string
* @author 段誉
* @date 2022/6/22 18:15
*/
public function getGenerateName()
{
return $this->getUpperCamelName() . 'Logic.php';
}
/**
* @notes 文件信息
* @return array
* @author 段誉
* @date 2022/6/23 15:57
*/
public function fileInfo(): array
{
return [
'name' => $this->getGenerateName(),
'type' => 'php',
'content' => $this->content
];
}
}

View File

@@ -0,0 +1,275 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
/**
* 模型生成器
* Class ModelGenerator
* @package app\common\service\generator\core
*/
class ModelGenerator extends BaseGenerator implements GenerateInterface
{
/**
* @notes 替换变量
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:16
*/
public function replaceVariables()
{
// 需要替换的变量
$needReplace = [
'{NAMESPACE}',
'{CLASS_COMMENT}',
'{UPPER_CAMEL_NAME}',
'{PACKAGE_NAME}',
'{TABLE_NAME}',
'{USE}',
'{DELETE_USE}',
'{DELETE_TIME}',
'{RELATION_MODEL}',
];
// 等待替换的内容
$waitReplace = [
$this->getNameSpaceContent(),
$this->getClassCommentContent(),
$this->getUpperCamelName(),
$this->getPackageNameContent(),
$this->getTableName(),
$this->getUseContent(),
$this->getDeleteUseContent(),
$this->getDeleteTimeContent(),
$this->getRelationModel(),
];
$templatePath = $this->getTemplatePath('php/model');
// 替换内容
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
$this->setContent($content);
}
/**
* @notes 获取命名空间模板内容
* @return string
* @author 段誉
* @date 2022/6/22 18:16
*/
public function getNameSpaceContent()
{
if (!empty($this->classDir)) {
return "namespace app\\common\\model\\" . $this->classDir . ';';
}
return "namespace app\\common\\model;";
}
/**
* @notes 获取类描述
* @return string
* @author 段誉
* @date 2022/6/22 18:16
*/
public function getClassCommentContent()
{
if (!empty($this->tableData['class_comment'])) {
$tpl = $this->tableData['class_comment'] . '模型';
} else {
$tpl = $this->getUpperCamelName() . '模型';
}
return $tpl;
}
/**
* @notes 获取包名
* @return string
* @author 段誉
* @date 2022/6/22 18:16
*/
public function getPackageNameContent()
{
return !empty($this->classDir) ? '\\' . $this->classDir : '';
}
/**
* @notes 引用内容
* @return string
* @author 段誉
* @date 2022/12/12 17:32
*/
public function getUseContent()
{
$tpl = "";
if ($this->deleteConfig['type']) {
$tpl = "use think\\model\\concern\\SoftDelete;";
}
return $tpl;
}
/**
* @notes 软删除引用
* @return string
* @author 段誉
* @date 2022/12/12 17:34
*/
public function getDeleteUseContent()
{
$tpl = "";
if ($this->deleteConfig['type']) {
$tpl = "use SoftDelete;";
}
return $tpl;
}
/**
* @notes 软删除时间字段定义
* @return string
* @author 段誉
* @date 2022/12/12 17:38
*/
public function getDeleteTimeContent()
{
$tpl = "";
if ($this->deleteConfig['type']) {
$deleteTime = $this->deleteConfig['name'];
$tpl = 'protected $deleteTime = ' . "'". $deleteTime ."';";
}
return $tpl;
}
/**
* @notes 关联模型
* @return string
* @author 段誉
* @date 2022/12/14 14:46
*/
public function getRelationModel()
{
$tpl = '';
if (empty($this->relationConfig)) {
return $tpl;
}
// 遍历关联配置
foreach ($this->relationConfig as $config) {
if (empty($config) || empty($config['name']) || empty($config['model'])) {
continue;
}
$needReplace = [
'{RELATION_NAME}',
'{AUTHOR}',
'{DATE}',
'{RELATION_MODEL}',
'{FOREIGN_KEY}',
'{LOCAL_KEY}',
];
$waitReplace = [
$config['name'],
$this->getAuthorContent(),
$this->getNoteDateContent(),
$config['model'],
$config['foreign_key'],
$config['local_key'],
];
$templatePath = $this->getTemplatePath('php/model/' . $config['type']);
if (!file_exists($templatePath)) {
continue;
}
$tpl .= $this->replaceFileData($needReplace, $waitReplace, $templatePath) . PHP_EOL;
}
return $tpl;
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:16
*/
public function getModuleGenerateDir()
{
$dir = $this->basePath . 'common/model/';
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:17
*/
public function getRuntimeGenerateDir()
{
$dir = $this->generatorDir . 'php/app/common/model/';
$this->checkDir($dir);
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 生成的文件名
* @return string
* @author 段誉
* @date 2022/6/22 18:17
*/
public function getGenerateName()
{
return $this->getUpperCamelName() . '.php';
}
/**
* @notes 文件信息
* @return array
* @author 段誉
* @date 2022/6/23 15:57
*/
public function fileInfo(): array
{
return [
'name' => $this->getGenerateName(),
'type' => 'php',
'content' => $this->content
];
}
}

View File

@@ -0,0 +1,191 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
use app\common\enum\GeneratorEnum;
use think\facade\Db;
use think\helper\Str;
/**
* sql文件生成器
* Class SqlGenerator
* @package app\common\service\generator\core
*/
class SqlGenerator extends BaseGenerator implements GenerateInterface
{
/**
* @notes 替换变量
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:19
*/
public function replaceVariables()
{
// 需要替换的变量
$needReplace = [
'{MENU_TABLE}',
'{PARTNER_ID}',
'{LISTS_NAME}',
'{PERMS_NAME}',
'{PATHS_NAME}',
'{COMPONENT_NAME}',
'{CREATE_TIME}',
'{UPDATE_TIME}'
];
// 等待替换的内容
$waitReplace = [
$this->getMenuTableNameContent(),
$this->menuConfig['pid'],
$this->menuConfig['name'],
$this->getPermsNameContent(),
$this->getLowerTableName(),
$this->getLowerTableName(),
time(),
time()
];
$templatePath = $this->getTemplatePath('sql/sql');
// 替换内容
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
$this->setContent($content);
}
/**
* @notes 路由权限内容
* @return string
* @author 段誉
* @date 2022/8/11 17:18
*/
public function getPermsNameContent()
{
if (!empty($this->classDir)) {
return $this->classDir . '.' . Str::lower($this->getTableName());
}
return Str::lower($this->getTableName());
}
/**
* @notes 获取菜单表内容
* @return string
* @author 段誉
* @date 2022/7/7 15:57
*/
public function getMenuTableNameContent()
{
$tablePrefix = config('database.connections.mysql.prefix');
return $tablePrefix . 'system_menu';
}
/**
* @notes 是否构建菜单
* @return bool
* @author 段誉
* @date 2022/7/8 14:24
*/
public function isBuildMenu()
{
return $this->menuConfig['type'] == GeneratorEnum::GEN_AUTO;
}
/**
* @notes 构建菜单
* @return bool
* @author 段誉
* @date 2022/7/8 15:27
*/
public function buildMenuHandle()
{
if (empty($this->content)) {
return false;
}
$sqls = explode(';', trim($this->content));
//执行sql
foreach ($sqls as $sql) {
if (!empty(trim($sql))) {
Db::execute($sql . ';');
}
}
return true;
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:19
*/
public function getModuleGenerateDir()
{
$dir = $this->generatorDir . 'sql/';
$this->checkDir($dir);
return $dir;
}
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:20
*/
public function getRuntimeGenerateDir()
{
$dir = $this->generatorDir . 'sql/';
$this->checkDir($dir);
return $dir;
}
/**
* @notes 生成的文件名
* @return string
* @author 段誉
* @date 2022/6/22 18:20
*/
public function getGenerateName()
{
return 'menu.sql';
}
/**
* @notes 文件信息
* @return array
* @author 段誉
* @date 2022/6/23 15:57
*/
public function fileInfo(): array
{
return [
'name' => $this->getGenerateName(),
'type' => 'sql',
'content' => $this->content
];
}
}

View File

@@ -0,0 +1,278 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
/**
* 验证器生成器
* Class ValidateGenerator
* @package app\common\service\generator\core
*/
class ValidateGenerator extends BaseGenerator implements GenerateInterface
{
/**
* @notes 替换变量
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:18
*/
public function replaceVariables()
{
// 需要替换的变量
$needReplace = [
'{NAMESPACE}',
'{CLASS_COMMENT}',
'{UPPER_CAMEL_NAME}',
'{MODULE_NAME}',
'{PACKAGE_NAME}',
'{PK}',
'{RULE}',
'{NOTES}',
'{AUTHOR}',
'{DATE}',
'{ADD_PARAMS}',
'{EDIT_PARAMS}',
'{FIELD}',
];
// 等待替换的内容
$waitReplace = [
$this->getNameSpaceContent(),
$this->getClassCommentContent(),
$this->getUpperCamelName(),
$this->moduleName,
$this->getPackageNameContent(),
$this->getPkContent(),
$this->getRuleContent(),
$this->tableData['class_comment'],
$this->getAuthorContent(),
$this->getNoteDateContent(),
$this->getAddParamsContent(),
$this->getEditParamsContent(),
$this->getFiledContent(),
];
$templatePath = $this->getTemplatePath('php/validate');
// 替换内容
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
$this->setContent($content);
}
/**
* @notes 验证规则
* @return mixed|string
* @author 段誉
* @date 2022/6/22 18:18
*/
public function getRuleContent()
{
$content = "'" . $this->getPkContent() . "' => 'require'," . PHP_EOL;
foreach ($this->tableColumn as $column) {
if ($column['is_required'] == 1) {
$content .= "'" . $column['column_name'] . "' => 'require'," . PHP_EOL;
}
}
$content = substr($content, 0, -1);
return $this->setBlankSpace($content, " ");
}
/**
* @notes 添加场景验证参数
* @return string
* @author 段誉
* @date 2022/12/7 15:26
*/
public function getAddParamsContent()
{
$content = "";
foreach ($this->tableColumn as $column) {
if ($column['is_required'] == 1 && $column['column_name'] != $this->getPkContent()) {
$content .= "'" . $column['column_name'] . "',";
}
}
$content = substr($content, 0, -1);
// 若无设置添加场景校验字段时, 排除主键
if (!empty($content)) {
$content = 'return $this->only([' . $content . ']);';
} else {
$content = 'return $this->remove(' . "'". $this->getPkContent() . "'" . ', true);';
}
return $this->setBlankSpace($content, "");
}
/**
* @notes 编辑场景验证参数
* @return string
* @author 段誉
* @date 2022/12/7 15:20
*/
public function getEditParamsContent()
{
$content = "'" . $this->getPkContent() . "'," ;
foreach ($this->tableColumn as $column) {
if ($column['is_required'] == 1) {
$content .= "'" . $column['column_name'] . "',";
}
}
$content = substr($content, 0, -1);
if (!empty($content)) {
$content = 'return $this->only([' . $content . ']);';
}
return $this->setBlankSpace($content, "");
}
/**
* @notes 验证字段描述
* @return string
* @author 段誉
* @date 2022/12/9 15:09
*/
public function getFiledContent()
{
$content = "'" . $this->getPkContent() . "' => '" . $this->getPkContent() . "'," . PHP_EOL;
foreach ($this->tableColumn as $column) {
if ($column['is_required'] == 1) {
$columnComment = $column['column_comment'];
if (empty($column['column_comment'])) {
$columnComment = $column['column_name'];
}
$content .= "'" . $column['column_name'] . "' => '" . $columnComment . "'," . PHP_EOL;
}
}
$content = substr($content, 0, -1);
return $this->setBlankSpace($content, " ");
}
/**
* @notes 获取命名空间模板内容
* @return string
* @author 段誉
* @date 2022/6/22 18:18
*/
public function getNameSpaceContent()
{
if (!empty($this->classDir)) {
return "namespace app\\" . $this->moduleName . "\\validate\\" . $this->classDir . ';';
}
return "namespace app\\" . $this->moduleName . "\\validate;";
}
/**
* @notes 获取类描述
* @return string
* @author 段誉
* @date 2022/6/22 18:18
*/
public function getClassCommentContent()
{
if (!empty($this->tableData['class_comment'])) {
$tpl = $this->tableData['class_comment'] . '验证器';
} else {
$tpl = $this->getUpperCamelName() . '验证器';
}
return $tpl;
}
/**
* @notes 获取包名
* @return string
* @author 段誉
* @date 2022/6/22 18:18
*/
public function getPackageNameContent()
{
return !empty($this->classDir) ? '\\' . $this->classDir : '';
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:18
*/
public function getModuleGenerateDir()
{
$dir = $this->basePath . $this->moduleName . '/validate/';
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:18
*/
public function getRuntimeGenerateDir()
{
$dir = $this->generatorDir . 'php/app/' . $this->moduleName . '/validate/';
$this->checkDir($dir);
if (!empty($this->classDir)) {
$dir .= $this->classDir . '/';
$this->checkDir($dir);
}
return $dir;
}
/**
* @notes 生成的文件名
* @return string
* @author 段誉
* @date 2022/6/22 18:19
*/
public function getGenerateName()
{
return $this->getUpperCamelName() . 'Validate.php';
}
/**
* @notes 文件信息
* @return array
* @author 段誉
* @date 2022/6/23 15:57
*/
public function fileInfo(): array
{
return [
'name' => $this->getGenerateName(),
'type' => 'php',
'content' => $this->content
];
}
}

View File

@@ -0,0 +1,144 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
use think\helper\Str;
/**
* vue-api生成器
* Class VueApiGenerator
* @package app\common\service\generator\core
*/
class VueApiGenerator extends BaseGenerator implements GenerateInterface
{
/**
* @notes 替换变量
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:19
*/
public function replaceVariables()
{
// 需要替换的变量
$needReplace = [
'{COMMENT}',
'{UPPER_CAMEL_NAME}',
'{ROUTE}'
];
// 等待替换的内容
$waitReplace = [
$this->getCommentContent(),
$this->getUpperCamelName(),
$this->getRouteContent(),
];
$templatePath = $this->getTemplatePath('vue/api');
// 替换内容
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
$this->setContent($content);
}
/**
* @notes 描述
* @return mixed
* @author 段誉
* @date 2022/6/22 18:19
*/
public function getCommentContent()
{
return $this->tableData['table_comment'];
}
/**
* @notes 路由名称
* @return array|string|string[]
* @author 段誉
* @date 2022/6/22 18:19
*/
public function getRouteContent()
{
$content = $this->getTableName();
if (!empty($this->classDir)) {
$content = $this->classDir . '.' . $this->getTableName();
}
return Str::lower($content);
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:19
*/
public function getModuleGenerateDir()
{
$dir = dirname(app()->getRootPath()) . '/admin/src/api/';
$this->checkDir($dir);
return $dir;
}
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:20
*/
public function getRuntimeGenerateDir()
{
$dir = $this->generatorDir . 'vue/src/api/';
$this->checkDir($dir);
return $dir;
}
/**
* @notes 生成的文件名
* @return string
* @author 段誉
* @date 2022/6/22 18:20
*/
public function getGenerateName()
{
return $this->getLowerTableName() . '.ts';
}
/**
* @notes 文件信息
* @return array
* @author 段誉
* @date 2022/6/23 15:57
*/
public function fileInfo(): array
{
return [
'name' => $this->getGenerateName(),
'type' => 'ts',
'content' => $this->content
];
}
}

View File

@@ -0,0 +1,493 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
use app\common\enum\GeneratorEnum;
/**
* vue-edit生成器
* Class VueEditGenerator
* @package app\common\service\generator\core
*/
class VueEditGenerator extends BaseGenerator implements GenerateInterface
{
/**
* @notes 替换变量
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:19
*/
public function replaceVariables()
{
// 需要替换的变量
$needReplace = [
'{FORM_VIEW}',
'{UPPER_CAMEL_NAME}',
'{DICT_DATA}',
'{DICT_DATA_API}',
'{FORM_DATA}',
'{FORM_VALIDATE}',
'{TABLE_COMMENT}',
'{PK}',
'{API_DIR}',
'{CHECKBOX_JOIN}',
'{CHECKBOX_SPLIT}',
'{FORM_DATE}',
'{SETUP_NAME}',
'{IMPORT_LISTS}',
'{TREE_CONST}',
'{GET_TREE_LISTS}'
];
// 等待替换的内容
$waitReplace = [
$this->getFormViewContent(),
$this->getUpperCamelName(),
$this->getDictDataContent(),
$this->getDictDataApiContent(),
$this->getFormDataContent(),
$this->getFormValidateContent(),
$this->tableData['table_comment'],
$this->getPkContent(),
$this->getTableName(),
$this->getCheckBoxJoinContent(),
$this->getCheckBoxSplitContent(),
$this->getFormDateContent(),
$this->getLowerCamelName(),
$this->getImportListsContent(),
$this->getTreeConstContent(),
$this->getTreeListsContent(),
];
$templatePath = $this->getTemplatePath('vue/edit');
// 替换内容
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
$this->setContent($content);
}
/**
* @notes 复选框处理
* @return string
* @author 段誉
* @date 2022/6/24 19:30
*/
public function getCheckBoxJoinContent()
{
$content = '';
foreach ($this->tableColumn as $column) {
if (empty($column['view_type']) || $column['is_pk']) {
continue;
}
if ($column['view_type'] != 'checkbox') {
continue;
}
$content .= $column['column_name'] . ': formData.' . $column['column_name'] . '.join(",")' . PHP_EOL;
}
if (!empty($content)) {
$content = substr($content, 0, -1);
}
return $content;
}
/**
* @notes 复选框处理
* @return string
* @author 段誉
* @date 2022/6/24 19:30
*/
public function getCheckBoxSplitContent()
{
$content = '';
foreach ($this->tableColumn as $column) {
if (empty($column['view_type']) || $column['is_pk']) {
continue;
}
if ($column['view_type'] != 'checkbox') {
continue;
}
$content .= '//@ts-ignore' . PHP_EOL;
$content .= 'data.' . $column['column_name'] . ' && ' .'(formData.' . $column['column_name'] . ' = String(data.' . $column['column_name'] . ').split(","))' . PHP_EOL;
}
if (!empty($content)) {
$content = substr($content, 0, -1);
}
return $this->setBlankSpace($content, ' ');
}
/**
* @notes 树表contst
* @return string
* @author 段誉
* @date 2022/12/22 18:19
*/
public function getTreeConstContent()
{
$content = "";
if ($this->isTreeCrud()) {
$content = file_get_contents($this->getTemplatePath('vue/other_item/editTreeConst'));
}
return $content;
}
/**
* @notes 获取树表列表
* @return string
* @author 段誉
* @date 2022/12/22 18:26
*/
public function getTreeListsContent()
{
$content = '';
if (!$this->isTreeCrud()) {
return $content;
}
$needReplace = [
'{TREE_ID}',
'{TREE_NAME}',
'{UPPER_CAMEL_NAME}',
];
$waitReplace = [
$this->treeConfig['tree_id'],
$this->treeConfig['tree_name'],
$this->getUpperCamelName(),
];
$templatePath = $this->getTemplatePath('vue/other_item/editTreeLists');
if (file_exists($templatePath)) {
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
}
return $content;
}
/**
* @notes 表单日期处理
* @return string
* @author 段誉
* @date 2022/6/27 16:45
*/
public function getFormDateContent()
{
$content = '';
foreach ($this->tableColumn as $column) {
if (empty($column['view_type']) || $column['is_pk']) {
continue;
}
if ($column['view_type'] != 'datetime' || $column['column_type'] != 'int') {
continue;
}
$content .= '//@ts-ignore' . PHP_EOL;
$content .= 'formData.' . $column['column_name'] . ' = timeFormat(formData.' . $column['column_name'] . ','."'yyyy-mm-dd hh:MM:ss'".') ' . PHP_EOL;
}
if (!empty($content)) {
$content = substr($content, 0, -1);
}
return $this->setBlankSpace($content, ' ');
}
/**
* @notes 获取表单内容
* @return string
* @author 段誉
* @date 2022/6/23 11:57
*/
public function getFormViewContent()
{
$content = '';
foreach ($this->tableColumn as $column) {
if (!$column['is_insert'] || !$column['is_update'] || $column['is_pk']) {
continue;
}
$needReplace = [
'{COLUMN_COMMENT}',
'{COLUMN_NAME}',
'{DICT_TYPE}',
];
$waitReplace = [
$column['column_comment'],
$column['column_name'],
$column['dict_type'],
];
$viewType = $column['view_type'];
// 树表,树状结构下拉框
if ($this->isTreeCrud() && $column['column_name'] == $this->treeConfig['tree_pid']) {
$viewType = 'treeSelect';
array_push($needReplace, '{TREE_ID}', '{TREE_NAME}');
array_push($waitReplace, $this->treeConfig['tree_id'], $this->treeConfig['tree_name']);
}
$templatePath = $this->getTemplatePath('vue/form_item/' . $viewType);
if (!file_exists($templatePath)) {
continue;
}
// 单选框值处理
if ($column['view_type'] == 'radio' || $column['view_type'] == 'select') {
$stubItemValue = 'item.value';
$intFieldValue = ['tinyint', 'smallint', 'mediumint', 'int', 'integer', 'bigint'];
if (in_array($column['column_type'], $intFieldValue)) {
$stubItemValue = 'parseInt(item.value)';
}
array_push($needReplace, '{ITEM_VALUE}');
array_push($waitReplace, $stubItemValue);
}
$content .= $this->replaceFileData($needReplace, $waitReplace, $templatePath) . PHP_EOL;
}
if (!empty($content)) {
$content = substr($content, 0, -1);
}
$content = $this->setBlankSpace($content, ' ');
return $content;
}
/**
* @notes 获取字典数据内容
* @return string
* @author 段誉
* @date 2022/6/23 11:58
*/
public function getDictDataContent()
{
$content = '';
$isExist = [];
foreach ($this->tableColumn as $column) {
if (empty($column['dict_type']) || $column['is_pk']) {
continue;
}
if (in_array($column['dict_type'], $isExist)) {
continue;
}
$content .= $column['dict_type'] . ': ' . "[]," . PHP_EOL;
$isExist[] = $column['dict_type'];
}
if (!empty($content)) {
$content = substr($content, 0, -1);
}
return $this->setBlankSpace($content, ' ');
}
/**
* @notes 获取字典数据api内容
* @return false|string
* @author 段誉
* @date 2022/6/23 11:58
*/
public function getDictDataApiContent()
{
$content = '';
$isExist = [];
foreach ($this->tableColumn as $column) {
if (empty($column['dict_type']) || $column['is_pk']) {
continue;
}
if (in_array($column['dict_type'], $isExist)) {
continue;
}
$needReplace = [
'{UPPER_CAMEL_NAME}',
'{DICT_TYPE}',
];
$waitReplace = [
$this->getUpperCamelName(),
$column['dict_type'],
];
$templatePath = $this->getTemplatePath('vue/other_item/dictDataApi');
if (!file_exists($templatePath)) {
continue;
}
$content .= $this->replaceFileData($needReplace, $waitReplace, $templatePath) . '' . PHP_EOL;
$isExist[] = $column['dict_type'];
}
$content = substr($content, 0, -1);
return $content;
}
/**
* @notes 获取表单默认字段内容
* @return string
* @author 段誉
* @date 2022/6/23 15:15
*/
public function getFormDataContent()
{
$content = '';
$isExist = [];
foreach ($this->tableColumn as $column) {
if (!$column['is_insert'] || !$column['is_update'] || $column['is_pk']) {
continue;
}
if (in_array($column['column_name'], $isExist)) {
continue;
}
// 复选框类型返回数组
if ($column['view_type'] == 'checkbox') {
$content .= $column['column_name'] . ': ' . "[]," . PHP_EOL;
} else {
$content .= $column['column_name'] . ': ' . "''," . PHP_EOL;
}
$isExist[] = $column['column_name'];
}
if (!empty($content)) {
$content = substr($content, 0, -1);
}
return $this->setBlankSpace($content, ' ');
}
/**
* @notes 表单验证内容
* @return false|string
* @author 段誉
* @date 2022/6/23 15:16
*/
public function getFormValidateContent()
{
$content = '';
$isExist = [];
$specDictType = ['input', 'textarea', 'editor'];
foreach ($this->tableColumn as $column) {
if (!$column['is_required'] || $column['is_pk']) {
continue;
}
if (in_array($column['column_name'], $isExist)) {
continue;
}
$validateMsg = in_array($column['view_type'], $specDictType) ? '请输入' : '请选择';
$validateMsg .= $column['column_comment'];
$needReplace = [
'{COLUMN_NAME}',
'{VALIDATE_MSG}',
];
$waitReplace = [
$column['column_name'],
$validateMsg,
];
$templatePath = $this->getTemplatePath('vue/other_item/formValidate');
if (!file_exists($templatePath)) {
continue;
}
$content .= $this->replaceFileData($needReplace, $waitReplace, $templatePath) . ',' . PHP_EOL;
$isExist[] = $column['column_name'];
}
$content = substr($content, 0, -2);
return $content;
}
/**
* @notes 树表时导入列表
* @author 段誉
* @date 2022/12/23 9:56
*/
public function getImportListsContent()
{
$content = "";
if ($this->isTreeCrud()) {
$content = "api". $this->getUpperCamelName(). 'Lists,';
}
if (empty($content)) {
return $content;
}
return $this->setBlankSpace($content, ' ');
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:19
*/
public function getModuleGenerateDir()
{
$dir = dirname(app()->getRootPath()) . '/admin/src/views/' . $this->getTableName() . '/';
$this->checkDir($dir);
return $dir;
}
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:20
*/
public function getRuntimeGenerateDir()
{
$dir = $this->generatorDir . 'vue/src/views/' . $this->getTableName() . '/';
$this->checkDir($dir);
return $dir;
}
/**
* @notes 生成的文件名
* @return string
* @author 段誉
* @date 2022/6/22 18:20
*/
public function getGenerateName()
{
return 'edit.vue';
}
/**
* @notes 文件信息
* @return array
* @author 段誉
* @date 2022/6/23 15:57
*/
public function fileInfo(): array
{
return [
'name' => $this->getGenerateName(),
'type' => 'vue',
'content' => $this->content
];
}
}

View File

@@ -0,0 +1,308 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace app\common\service\generator\core;
use app\common\enum\GeneratorEnum;
/**
* vue-index生成器
* Class VueIndexGenerator
* @package app\common\service\generator\core
*/
class VueIndexGenerator extends BaseGenerator implements GenerateInterface
{
/**
* @notes 替换变量
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:19
*/
public function replaceVariables()
{
// 需要替换的变量
$needReplace = [
'{SEARCH_VIEW}',
'{LISTS_VIEW}',
'{UPPER_CAMEL_NAME}',
'{QUERY_PARAMS}',
'{DICT_DATA}',
'{PK}',
'{API_DIR}',
'{PERMS_ADD}',
'{PERMS_EDIT}',
'{PERMS_DELETE}',
'{SETUP_NAME}'
];
// 等待替换的内容
$waitReplace = [
$this->getSearchViewContent(),
$this->getListsViewContent(),
$this->getUpperCamelName(),
$this->getQueryParamsContent(),
$this->getDictDataContent(),
$this->getPkContent(),
$this->getTableName(),
$this->getPermsContent(),
$this->getPermsContent('edit'),
$this->getPermsContent('delete'),
$this->getLowerCamelName()
];
$templatePath = $this->getTemplatePath('vue/index');
if ($this->isTreeCrud()) {
// 插入树表相关
array_push($needReplace, '{TREE_ID}', '{TREE_PID}');
array_push($waitReplace, $this->treeConfig['tree_id'], $this->treeConfig['tree_pid']);
$templatePath = $this->getTemplatePath('vue/index-tree');
}
// 替换内容
$content = $this->replaceFileData($needReplace, $waitReplace, $templatePath);
$this->setContent($content);
}
/**
* @notes 获取搜索内容
* @return string
* @author 段誉
* @date 2022/6/23 11:57
*/
public function getSearchViewContent()
{
$content = '';
foreach ($this->tableColumn as $column) {
if (!$column['is_query'] || $column['is_pk']) {
continue;
}
$needReplace = [
'{COLUMN_COMMENT}',
'{COLUMN_NAME}',
'{DICT_TYPE}',
];
$waitReplace = [
$column['column_comment'],
$column['column_name'],
$column['dict_type'],
];
$searchStubType = $column['view_type'];
if ($column['view_type'] == 'radio') {
$searchStubType = 'select';
}
$templatePath = $this->getTemplatePath('vue/search_item/' . $searchStubType);
if (!file_exists($templatePath)) {
continue;
}
$content .= $this->replaceFileData($needReplace, $waitReplace, $templatePath) . PHP_EOL;
}
if (!empty($content)) {
$content = substr($content, 0, -1);
}
$content = $this->setBlankSpace($content, ' ');
return $content;
}
/**
* @notes 获取列表内容
* @return string
* @author 段誉
* @date 2022/6/23 11:57
*/
public function getListsViewContent()
{
$content = '';
foreach ($this->tableColumn as $column) {
if (!$column['is_lists']) {
continue;
}
$needReplace = [
'{COLUMN_COMMENT}',
'{COLUMN_NAME}',
'{DICT_TYPE}',
];
$waitReplace = [
$column['column_comment'],
$column['column_name'],
$column['dict_type'],
];
$templatePath = $this->getTemplatePath('vue/table_item/default');
if ($column['view_type'] == 'imageSelect') {
$templatePath = $this->getTemplatePath('vue/table_item/image');
}
if (in_array($column['view_type'], ['select', 'radio', 'checkbox'])) {
$templatePath = $this->getTemplatePath('vue/table_item/options');
}
if ($column['column_type'] == 'int' && $column['view_type'] == 'datetime') {
$templatePath = $this->getTemplatePath('vue/table_item/datetime');
}
if (!file_exists($templatePath)) {
continue;
}
$content .= $this->replaceFileData($needReplace, $waitReplace, $templatePath) . PHP_EOL;
}
if (!empty($content)) {
$content = substr($content, 0, -1);
}
return $this->setBlankSpace($content, ' ');
}
/**
* @notes 获取查询条件内容
* @return string
* @author 段誉
* @date 2022/6/23 11:57
*/
public function getQueryParamsContent()
{
$content = '';
$queryDate = false;
foreach ($this->tableColumn as $column) {
if (!$column['is_query'] || $column['is_pk']) {
continue;
}
$content .= $column['column_name'] . ": ''," . PHP_EOL;
if ($column['query_type'] == 'between' && $column['view_type'] == 'datetime') {
$queryDate = true;
}
}
if ($queryDate) {
$content .= "start_time: ''," . PHP_EOL;
$content .= "end_time: ''," . PHP_EOL;
}
$content = substr($content, 0, -2);
return $this->setBlankSpace($content, ' ');
}
/**
* @notes 获取字典数据内容
* @return string
* @author 段誉
* @date 2022/6/23 11:58
*/
public function getDictDataContent()
{
$content = '';
$isExist = [];
foreach ($this->tableColumn as $column) {
if (empty($column['dict_type']) || $column['is_pk']) {
continue;
}
if (in_array($column['dict_type'], $isExist)) {
continue;
}
$content .= $column['dict_type'] .",";
$isExist[] = $column['dict_type'];
}
if (!empty($content)) {
$content = substr($content, 0, -1);
}
return $this->setBlankSpace($content, '');
}
/**
* @notes 权限规则
* @param string $type
* @return string
* @author 段誉
* @date 2022/7/7 9:47
*/
public function getPermsContent($type = 'add')
{
if (!empty($this->classDir)) {
$classDir = $this->classDir . '.';
} else {
$classDir = '';
}
return trim($classDir . $this->getLowerTableName() . '/' . $type);
}
/**
* @notes 获取文件生成到模块的文件夹路径
* @return mixed|void
* @author 段誉
* @date 2022/6/22 18:19
*/
public function getModuleGenerateDir()
{
$dir = dirname(app()->getRootPath()) . '/admin/src/views/' . $this->getLowerTableName() . '/';
$this->checkDir($dir);
return $dir;
}
/**
* @notes 获取文件生成到runtime的文件夹路径
* @return string
* @author 段誉
* @date 2022/6/22 18:20
*/
public function getRuntimeGenerateDir()
{
$dir = $this->generatorDir . 'vue/src/views/' . $this->getLowerTableName() . '/';
$this->checkDir($dir);
return $dir;
}
/**
* @notes 生成的文件名
* @return string
* @author 段誉
* @date 2022/6/22 18:20
*/
public function getGenerateName()
{
return 'index.vue';
}
/**
* @notes 文件信息
* @return array
* @author 段誉
* @date 2022/6/23 15:57
*/
public function fileInfo(): array
{
return [
'name' => $this->getGenerateName(),
'type' => 'vue',
'content' => $this->content
];
}
}

View File

@@ -0,0 +1,91 @@
<?php
{NAMESPACE}
{USE}
/**
* {CLASS_COMMENT}
* Class {UPPER_CAMEL_NAME}Controller
* @package app\{MODULE_NAME}\controller{PACKAGE_NAME}
*/
class {UPPER_CAMEL_NAME}Controller extends {EXTENDS_CONTROLLER}
{
/**
* @notes 获取{NOTES}列表
* @return \think\response\Json
* @author {AUTHOR}
* @date {DATE}
*/
public function lists()
{
return $this->dataLists(new {UPPER_CAMEL_NAME}Lists());
}
/**
* @notes 添加{NOTES}
* @return \think\response\Json
* @author {AUTHOR}
* @date {DATE}
*/
public function add()
{
$params = (new {UPPER_CAMEL_NAME}Validate())->post()->goCheck('add');
$result = {UPPER_CAMEL_NAME}Logic::add($params);
if (true === $result) {
return $this->success('添加成功', [], 1, 1);
}
return $this->fail({UPPER_CAMEL_NAME}Logic::getError());
}
/**
* @notes 编辑{NOTES}
* @return \think\response\Json
* @author {AUTHOR}
* @date {DATE}
*/
public function edit()
{
$params = (new {UPPER_CAMEL_NAME}Validate())->post()->goCheck('edit');
$result = {UPPER_CAMEL_NAME}Logic::edit($params);
if (true === $result) {
return $this->success('编辑成功', [], 1, 1);
}
return $this->fail({UPPER_CAMEL_NAME}Logic::getError());
}
/**
* @notes 删除{NOTES}
* @return \think\response\Json
* @author {AUTHOR}
* @date {DATE}
*/
public function delete()
{
$params = (new {UPPER_CAMEL_NAME}Validate())->post()->goCheck('delete');
{UPPER_CAMEL_NAME}Logic::delete($params);
return $this->success('删除成功', [], 1, 1);
}
/**
* @notes 获取{NOTES}详情
* @return \think\response\Json
* @author {AUTHOR}
* @date {DATE}
*/
public function detail()
{
$params = (new {UPPER_CAMEL_NAME}Validate())->goCheck('detail');
$result = {UPPER_CAMEL_NAME}Logic::detail($params);
return $this->data($result);
}
}

View File

@@ -0,0 +1,63 @@
<?php
{NAMESPACE}
{USE}
use app\common\lists\ListsSearchInterface;
/**
* {CLASS_COMMENT}
* Class {UPPER_CAMEL_NAME}Lists
* @package app\{MODULE_NAME}\lists{PACKAGE_NAME}
*/
class {UPPER_CAMEL_NAME}Lists extends {EXTENDS_LISTS} implements ListsSearchInterface
{
/**
* @notes 设置搜索条件
* @return \string[][]
* @author {AUTHOR}
* @date {DATE}
*/
public function setSearch(): array
{
return [
{QUERY_CONDITION}
];
}
/**
* @notes 获取{NOTES}列表
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author {AUTHOR}
* @date {DATE}
*/
public function lists(): array
{
return {UPPER_CAMEL_NAME}::where($this->searchWhere)
->field([{FIELD_DATA}])
->limit($this->limitOffset, $this->limitLength)
->order(['{PK}' => 'desc'])
->select()
->toArray();
}
/**
* @notes 获取{NOTES}数量
* @return int
* @author {AUTHOR}
* @date {DATE}
*/
public function count(): int
{
return {UPPER_CAMEL_NAME}::where($this->searchWhere)->count();
}
}

View File

@@ -0,0 +1,93 @@
<?php
{NAMESPACE}
{USE}
use app\common\logic\BaseLogic;
use think\facade\Db;
/**
* {CLASS_COMMENT}
* Class {UPPER_CAMEL_NAME}Logic
* @package app\{MODULE_NAME}\logic{PACKAGE_NAME}
*/
class {UPPER_CAMEL_NAME}Logic extends BaseLogic
{
/**
* @notes 添加{NOTES}
* @param array $params
* @return bool
* @author {AUTHOR}
* @date {DATE}
*/
public static function add(array $params): bool
{
Db::startTrans();
try {
{UPPER_CAMEL_NAME}::create([
{CREATE_DATA}
]);
Db::commit();
return true;
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 编辑{NOTES}
* @param array $params
* @return bool
* @author {AUTHOR}
* @date {DATE}
*/
public static function edit(array $params): bool
{
Db::startTrans();
try {
{UPPER_CAMEL_NAME}::where('{PK}', $params['{PK}'])->update([
{UPDATE_DATA}
]);
Db::commit();
return true;
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 删除{NOTES}
* @param array $params
* @return bool
* @author {AUTHOR}
* @date {DATE}
*/
public static function delete(array $params): bool
{
return {UPPER_CAMEL_NAME}::destroy($params['{PK}']);
}
/**
* @notes 获取{NOTES}详情
* @param $params
* @return array
* @author {AUTHOR}
* @date {DATE}
*/
public static function detail($params): array
{
return {UPPER_CAMEL_NAME}::findOrEmpty($params['{PK}'])->toArray();
}
}

View File

@@ -0,0 +1,21 @@
<?php
{NAMESPACE}
use app\common\model\BaseModel;
{USE}
/**
* {CLASS_COMMENT}
* Class {UPPER_CAMEL_NAME}
* @package app\common\model{PACKAGE_NAME}
*/
class {UPPER_CAMEL_NAME} extends BaseModel
{
{DELETE_USE}
protected $name = '{TABLE_NAME}';
{DELETE_TIME}
{RELATION_MODEL}
}

View File

@@ -0,0 +1,11 @@
/**
* @notes 关联{RELATION_NAME}
* @return \think\model\relation\HasMany
* @author {AUTHOR}
* @date {DATE}
*/
public function {RELATION_NAME}()
{
return $this->hasMany({RELATION_MODEL}::class, '{FOREIGN_KEY}', '{LOCAL_KEY}');
}

View File

@@ -0,0 +1,11 @@
/**
* @notes 关联{RELATION_NAME}
* @return \think\model\relation\HasOne
* @author {AUTHOR}
* @date {DATE}
*/
public function {RELATION_NAME}()
{
return $this->hasOne({RELATION_MODEL}::class, '{FOREIGN_KEY}', '{LOCAL_KEY}');
}

View File

@@ -0,0 +1,64 @@
<?php
{NAMESPACE}
{USE}
use app\common\lists\ListsSearchInterface;
/**
* {CLASS_COMMENT}
* Class {UPPER_CAMEL_NAME}Lists
* @package app\{MODULE_NAME}\lists{PACKAGE_NAME}
*/
class {UPPER_CAMEL_NAME}Lists extends {EXTENDS_LISTS} implements ListsSearchInterface
{
/**
* @notes 设置搜索条件
* @return \string[][]
* @author {AUTHOR}
* @date {DATE}
*/
public function setSearch(): array
{
return [
{QUERY_CONDITION}
];
}
/**
* @notes 获取{NOTES}列表
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author {AUTHOR}
* @date {DATE}
*/
public function lists(): array
{
$lists = {UPPER_CAMEL_NAME}::where($this->searchWhere)
->field([{FIELD_DATA}])
->order(['{PK}' => 'desc'])
->select()
->toArray();
return linear_to_tree($lists, 'children', '{TREE_ID}', '{TREE_PID}');
}
/**
* @notes 获取{NOTES}数量
* @return int
* @author {AUTHOR}
* @date {DATE}
*/
public function count(): int
{
return {UPPER_CAMEL_NAME}::where($this->searchWhere)->count();
}
}

View File

@@ -0,0 +1,81 @@
<?php
{NAMESPACE}
use app\common\validate\BaseValidate;
/**
* {CLASS_COMMENT}
* Class {UPPER_CAMEL_NAME}Validate
* @package app\{MODULE_NAME}\validate{PACKAGE_NAME}
*/
class {UPPER_CAMEL_NAME}Validate extends BaseValidate
{
/**
* 设置校验规则
* @var string[]
*/
protected $rule = [
{RULE}
];
/**
* 参数描述
* @var string[]
*/
protected $field = [
{FIELD}
];
/**
* @notes 添加场景
* @return {UPPER_CAMEL_NAME}Validate
* @author {AUTHOR}
* @date {DATE}
*/
public function sceneAdd()
{
{ADD_PARAMS}
}
/**
* @notes 编辑场景
* @return {UPPER_CAMEL_NAME}Validate
* @author {AUTHOR}
* @date {DATE}
*/
public function sceneEdit()
{
{EDIT_PARAMS}
}
/**
* @notes 删除场景
* @return {UPPER_CAMEL_NAME}Validate
* @author {AUTHOR}
* @date {DATE}
*/
public function sceneDelete()
{
return $this->only(['{PK}']);
}
/**
* @notes 详情场景
* @return {UPPER_CAMEL_NAME}Validate
* @author {AUTHOR}
* @date {DATE}
*/
public function sceneDetail()
{
return $this->only(['{PK}']);
}
}

View File

@@ -0,0 +1,13 @@
INSERT INTO `{MENU_TABLE}`(`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
VALUES ({PARTNER_ID}, 'C', '{LISTS_NAME}', '', 1, '{PERMS_NAME}/lists', '{PATHS_NAME}', '{COMPONENT_NAME}/index', '', '', 0, 1, 0, {CREATE_TIME}, {UPDATE_TIME});
SELECT @pid := LAST_INSERT_ID();
INSERT INTO `{MENU_TABLE}`(`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
VALUES (@pid, 'A', '添加', '', 1, '{PERMS_NAME}/add', '', '', '', '', 0, 1, 0, {CREATE_TIME}, {UPDATE_TIME});
INSERT INTO `{MENU_TABLE}`(`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
VALUES (@pid, 'A', '编辑', '', 1, '{PERMS_NAME}/edit', '', '', '', '', 0, 1, 0, {CREATE_TIME}, {UPDATE_TIME});
INSERT INTO `{MENU_TABLE}`(`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
VALUES (@pid, 'A', '删除', '', 1, '{PERMS_NAME}/delete', '', '', '', '', 0, 1, 0, {CREATE_TIME}, {UPDATE_TIME});

View File

@@ -0,0 +1,26 @@
import request from '@/utils/request'
// {COMMENT}列表
export function api{UPPER_CAMEL_NAME}Lists(params: any) {
return request.get({ url: '/{ROUTE}/lists', params })
}
// 添加{COMMENT}
export function api{UPPER_CAMEL_NAME}Add(params: any) {
return request.post({ url: '/{ROUTE}/add', params })
}
// 编辑{COMMENT}
export function api{UPPER_CAMEL_NAME}Edit(params: any) {
return request.post({ url: '/{ROUTE}/edit', params })
}
// 删除{COMMENT}
export function api{UPPER_CAMEL_NAME}Delete(params: any) {
return request.post({ url: '/{ROUTE}/delete', params })
}
// {COMMENT}详情
export function api{UPPER_CAMEL_NAME}Detail(params: any) {
return request.get({ url: '/{ROUTE}/detail', params })
}

View File

@@ -0,0 +1,103 @@
<template>
<div class="edit-popup">
<popup
ref="popupRef"
:title="popupTitle"
:async="true"
width="550px"
@confirm="handleSubmit"
@close="handleClose"
>
<el-form ref="formRef" :model="formData" label-width="90px" :rules="formRules">
{FORM_VIEW}
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup name="{SETUP_NAME}Edit">
import type { FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import {{IMPORT_LISTS} api{UPPER_CAMEL_NAME}Add, api{UPPER_CAMEL_NAME}Edit, api{UPPER_CAMEL_NAME}Detail } from '@/api/{API_DIR}'
import { timeFormat } from '@/utils/util'
import type { PropType } from 'vue'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
}
})
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
{TREE_CONST}
// 弹窗标题
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑{TABLE_COMMENT}' : '新增{TABLE_COMMENT}'
})
// 表单数据
const formData = reactive({
{PK}: '',
{FORM_DATA}
})
// 表单验证
const formRules = reactive<any>({
{FORM_VALIDATE}
})
// 获取详情
const setFormData = async (data: Record<any, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
{CHECKBOX_SPLIT}
{FORM_DATE}
}
const getDetail = async (row: Record<string, any>) => {
const data = await api{UPPER_CAMEL_NAME}Detail({
{PK}: row.{PK}
})
setFormData(data)
}
// 提交按钮
const handleSubmit = async () => {
await formRef.value?.validate()
const data = { ...formData, {CHECKBOX_JOIN} }
mode.value == 'edit'
? await api{UPPER_CAMEL_NAME}Edit(data)
: await api{UPPER_CAMEL_NAME}Add(data)
popupRef.value?.close()
emit('success')
}
//打开弹窗
const open = (type = 'add') => {
mode.value = type
popupRef.value?.open()
}
// 关闭回调
const handleClose = () => {
emit('close')
}
{GET_TREE_LISTS}
defineExpose({
open,
setFormData,
getDetail
})
</script>

View File

@@ -0,0 +1,11 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<el-checkbox-group v-model="formData.{COLUMN_NAME}" placeholder="请选择{COLUMN_COMMENT}">
<el-checkbox
v-for="(item, index) in dictData.{DICT_TYPE}"
:key="index"
:label="item.value"
>
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>

View File

@@ -0,0 +1,10 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<el-date-picker
class="flex-1 !flex"
v-model="formData.{COLUMN_NAME}"
clearable
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择{COLUMN_COMMENT}">
</el-date-picker>
</el-form-item>

View File

@@ -0,0 +1,6 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<daterange-picker
v-model:startTime="formData.start_{COLUMN_NAME}"
v-model:endTime="formData.end_{COLUMN_NAME}"
/>
</el-form-item>

View File

@@ -0,0 +1,3 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<editor class="flex-1" v-model="formData.{COLUMN_NAME}" :height="500" />
</el-form-item>

View File

@@ -0,0 +1,3 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<material-picker v-model="formData.{COLUMN_NAME}" />
</el-form-item>

View File

@@ -0,0 +1,3 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<el-input v-model="formData.{COLUMN_NAME}" clearable placeholder="请输入{COLUMN_COMMENT}" />
</el-form-item>

View File

@@ -0,0 +1,11 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<el-radio-group v-model="formData.{COLUMN_NAME}" placeholder="请选择{COLUMN_COMMENT}">
<el-radio
v-for="(item, index) in dictData.{DICT_TYPE}"
:key="index"
:label="{ITEM_VALUE}"
>
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>

View File

@@ -0,0 +1,10 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<el-select class="flex-1" v-model="formData.{COLUMN_NAME}" clearable placeholder="请选择{COLUMN_COMMENT}">
<el-option
v-for="(item, index) in dictData.{DICT_TYPE}"
:key="index"
:label="item.name"
:value="{ITEM_VALUE}"
/>
</el-select>
</el-form-item>

View File

@@ -0,0 +1,3 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<el-input class="flex-1" v-model="formData.{COLUMN_NAME}" type="textarea" rows="4" clearable placeholder="请输入{COLUMN_COMMENT}" />
</el-form-item>

View File

@@ -0,0 +1,13 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<el-tree-select
class="flex-1"
v-model="formData.{COLUMN_NAME}"
:data="treeList"
clearable
node-key="{TREE_ID}"
:props="{ label: '{TREE_NAME}', value: '{TREE_ID}', children: 'children' }"
:default-expand-all="true"
placeholder="请选择{COLUMN_COMMENT}"
check-strictly
/>
</el-form-item>

View File

@@ -0,0 +1,167 @@
<template>
<div>
<el-card class="!border-none mb-4" shadow="never">
<el-form
ref="formRef"
class="mb-[-16px]"
:model="queryParams"
inline
>
{SEARCH_VIEW}
<el-form-item>
<el-button type="primary" @click="getLists">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none" shadow="never">
<div>
<el-button v-perms="['{PERMS_ADD}']" type="primary" @click="handleAdd()">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
<el-button @click="handleExpand"> 展开/折叠 </el-button>
</div>
<div class="mt-4">
<el-table
v-loading="loading"
ref="tableRef"
class="mt-4"
size="large"
:data="lists"
row-key="{TREE_ID}"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
{LISTS_VIEW}
<el-table-column label="操作" width="160" fixed="right">
<template #default="{ row }">
<el-button
v-perms="['{PERMS_ADD}']"
type="primary"
link
@click="handleAdd(row.{TREE_ID})"
>
新增
</el-button>
<el-button
v-perms="['{PERMS_EDIT}']"
type="primary"
link
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
v-perms="['{PERMS_DELETE}']"
type="danger"
link
@click="handleDelete(row.{PK})"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" :dict-data="dictData" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="{SETUP_NAME}Lists">
import { timeFormat } from '@/utils/util'
import { useDictData } from '@/hooks/useDictOptions'
import { api{UPPER_CAMEL_NAME}Lists, api{UPPER_CAMEL_NAME}Delete } from '@/api/{API_DIR}'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
import type { ElTable, FormInstance } from 'element-plus'
const tableRef = shallowRef<InstanceType<typeof ElTable>>()
const formRef = shallowRef<FormInstance>()
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
let isExpand = false
// 是否显示编辑框
const showEdit = ref(false)
const loading = ref(false)
const lists = ref<any[]>([])
// 查询条件
const queryParams = reactive({
{QUERY_PARAMS}
})
const resetParams = () => {
formRef.value?.resetFields()
getLists()
}
const getLists = async () => {
loading.value = true
try {
const data = await api{UPPER_CAMEL_NAME}Lists(queryParams)
lists.value = data.lists
loading.value = false
} catch (error) {
loading.value = false
}
}
// 选中数据
const selectData = ref<any[]>([])
// 表格选择后回调事件
const handleSelectionChange = (val: any[]) => {
selectData.value = val.map(({ {PK} }) => {PK})
}
// 获取字典数据
const { dictData } = useDictData('{DICT_DATA}')
// 添加
const handleAdd = async ({TREE_ID}?: number) => {
showEdit.value = true
await nextTick()
if ({TREE_ID}) {
editRef.value?.setFormData({
{TREE_PID}: {TREE_ID}
})
}
editRef.value?.open('add')
}
// 编辑
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.setFormData(data)
}
// 删除
const handleDelete = async ({PK}: number | any[]) => {
await feedback.confirm('确定要删除?')
await api{UPPER_CAMEL_NAME}Delete({ {PK} })
getLists()
}
const handleExpand = () => {
isExpand = !isExpand
toggleExpand(lists.value, isExpand)
}
const toggleExpand = (children: any[], unfold = true) => {
for (const key in children) {
tableRef.value?.toggleRowExpansion(children[key], unfold)
if (children[key].children) {
toggleExpand(children[key].children!, unfold)
}
}
}
getLists()
</script>

View File

@@ -0,0 +1,123 @@
<template>
<div>
<el-card class="!border-none mb-4" shadow="never">
<el-form
class="mb-[-16px]"
:model="queryParams"
inline
>
{SEARCH_VIEW}
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none" v-loading="pager.loading" shadow="never">
<el-button v-perms="['{PERMS_ADD}']" type="primary" @click="handleAdd">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
<el-button
v-perms="['{PERMS_DELETE}']"
:disabled="!selectData.length"
@click="handleDelete(selectData)"
>
删除
</el-button>
<div class="mt-4">
<el-table :data="pager.lists" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
{LISTS_VIEW}
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button
v-perms="['{PERMS_EDIT}']"
type="primary"
link
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
v-perms="['{PERMS_DELETE}']"
type="danger"
link
@click="handleDelete(row.{PK})"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex mt-4 justify-end">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" :dict-data="dictData" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="{SETUP_NAME}Lists">
import { usePaging } from '@/hooks/usePaging'
import { useDictData } from '@/hooks/useDictOptions'
import { api{UPPER_CAMEL_NAME}Lists, api{UPPER_CAMEL_NAME}Delete } from '@/api/{API_DIR}'
import { timeFormat } from '@/utils/util'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
// 是否显示编辑框
const showEdit = ref(false)
// 查询条件
const queryParams = reactive({
{QUERY_PARAMS}
})
// 选中数据
const selectData = ref<any[]>([])
// 表格选择后回调事件
const handleSelectionChange = (val: any[]) => {
selectData.value = val.map(({ {PK} }) => {PK})
}
// 获取字典数据
const { dictData } = useDictData('{DICT_DATA}')
// 分页相关
const { pager, getLists, resetParams, resetPage } = usePaging({
fetchFun: api{UPPER_CAMEL_NAME}Lists,
params: queryParams
})
// 添加
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
}
// 编辑
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.setFormData(data)
}
// 删除
const handleDelete = async ({PK}: number | any[]) => {
await feedback.confirm('确定要删除?')
await api{UPPER_CAMEL_NAME}Delete({ {PK} })
getLists()
}
getLists()
</script>

View File

@@ -0,0 +1,6 @@
dictDataLists({
type_value: '{DICT_TYPE}',
page_type: 0
}).then((res: any) => {
dictData.{DICT_TYPE} = res.lists
})

View File

@@ -0,0 +1 @@
const treeList = ref<any[]>([])

View File

@@ -0,0 +1,8 @@
const getLists = async () => {
const data: any = await api{UPPER_CAMEL_NAME}Lists()
const item = { {TREE_ID}: 0, {TREE_NAME}: '顶级', children: [] }
item.children = data.lists
treeList.value.push(item)
}
getLists()

View File

@@ -0,0 +1,5 @@
{COLUMN_NAME}: [{
required: true,
message: '{VALIDATE_MSG}',
trigger: ['blur']
}]

View File

@@ -0,0 +1,6 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<daterange-picker
v-model:startTime="queryParams.start_time"
v-model:endTime="queryParams.end_time"
/>
</el-form-item>

View File

@@ -0,0 +1,3 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<el-input class="w-[280px]" v-model="queryParams.{COLUMN_NAME}" clearable placeholder="请输入{COLUMN_COMMENT}" />
</el-form-item>

View File

@@ -0,0 +1,11 @@
<el-form-item label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<el-select class="w-[280px]" v-model="queryParams.{COLUMN_NAME}" clearable placeholder="请选择{COLUMN_COMMENT}">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in dictData.{DICT_TYPE}"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>

View File

@@ -0,0 +1,5 @@
<el-table-column label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<template #default="{ row }">
<span>{{ row.{COLUMN_NAME} ? timeFormat(row.{COLUMN_NAME}, 'yyyy-mm-dd hh:MM:ss') : '' }}</span>
</template>
</el-table-column>

View File

@@ -0,0 +1 @@
<el-table-column label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}" show-overflow-tooltip />

View File

@@ -0,0 +1,5 @@
<el-table-column label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<template #default="{ row }">
<el-image style="width:50px;height:50px;" :src="row.{COLUMN_NAME}" />
</template>
</el-table-column>

View File

@@ -0,0 +1,5 @@
<el-table-column label="{COLUMN_COMMENT}" prop="{COLUMN_NAME}">
<template #default="{ row }">
<dict-value :options="dictData.{DICT_TYPE}" :value="row.{COLUMN_NAME}" />
</template>
</el-table-column>

View File

@@ -0,0 +1,221 @@
<?php
// +----------------------------------------------------------------------
// | likeshop100%开源免费商用商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | 商业版本务必购买商业授权,以免引起法律纠纷
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | // +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
namespace app\common\service\sms;
use app\common\enum\notice\NoticeEnum;
use app\common\enum\notice\SmsEnum;
use app\common\enum\YesNoEnum;
use app\common\model\Notice;
use app\common\model\notice\SmsLog;
use app\common\service\ConfigService;
/**
* 短信驱动
* Class SmsDriver
* @package app\common\service\sms
*/
class SmsDriver
{
/**
* 错误信息
* @var
*/
protected $error = null;
/**
* 默认短信引擎
* @var
*/
protected $defaultEngine;
/**
* 短信引擎
* @var
*/
protected $engine;
/**
* 架构方法
* SmsDriver constructor.
*/
public function __construct()
{
// 初始化
$this->initialize();
}
/**
* @notes 初始化
* @return bool
* @author 段誉
* @date 2022/9/15 16:29
*/
public function initialize()
{
try {
$defaultEngine = ConfigService::get('sms', 'engine', false);
if($defaultEngine === false) {
throw new \Exception('network.networkAnomaly');//请开启短信配置
}
$this->defaultEngine = $defaultEngine;
$classSpace = __NAMESPACE__ . '\\engine\\' . ucfirst(strtolower($defaultEngine)) . 'Sms';
if (!class_exists($classSpace)) {
throw new \Exception('network.networkAnomaly');//没有相应的短信驱动类
}
$engineConfig = ConfigService::get('sms', strtolower($defaultEngine), false);
if($engineConfig === false) {
throw new \Exception('network.networkAnomaly');//$defaultEngine . '未配置'
}
if ($engineConfig['status'] != 1) {
throw new \Exception('network.networkAnomaly');//短信服务未开启
}
$this->engine = new $classSpace($engineConfig);
if(!is_null($this->engine->getError())) {
throw new \Exception($this->engine->getError());
}
return true;
} catch (\Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* @notes 获取错误信息
* @return null
* @author 段誉
* @date 2022/9/15 16:29
*/
public function getError()
{
return $this->error;
}
/**
* @notes 发送短信
* @param $mobile
* @param $data
* @return false
* @author 段誉
* @date 2022/9/15 16:29
*/
public function send($mobile, $data)
{
try {
// 发送频率限制
$this->sendLimit($mobile);
// 开始发送
$result = $this->engine
->setMobile($mobile)
->setTemplateId($data['template_id'])
->setTemplateParams($data['params'])
->setSceneContent($data['scene_content'])
->setCountryCode($data['country_code'])
->send();
if(false === $result) {
throw new \Exception($this->engine->getError());
}
return $result;
} catch(\Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* @notes 发送频率限制
* @param $mobile
* @throws \Exception
* @author 段誉
* @date 2022/9/15 16:29
*/
public function sendLimit($mobile)
{
$smsLog = SmsLog::where([
['mobile', '=', $mobile],
['send_status', '=', SmsEnum::SEND_SUCCESS],
['scene_id', 'in', NoticeEnum::SMS_SCENE],
])
->order('send_time', 'desc')
->findOrEmpty()
->toArray();
if(!empty($smsLog) && ($smsLog['send_time'] > time() - 60)) {
throw new \Exception('captcha.sendLimit');
}
}
/**
* @notes 校验手机验证码
* @param $mobile
* @param $code
* @return bool
* @author 段誉
* @date 2022/9/15 16:29
*/
public function verify($mobile, $code, $sceneId = 0)
{
$where = [
['mobile', '=', $mobile],
['send_status', '=', SmsEnum::SEND_SUCCESS],
['scene_id', 'in', NoticeEnum::SMS_SCENE],
['is_verify', '=', YesNoEnum::NO],
];
if (!empty($sceneId)) {
$where[] = ['scene_id', '=', $sceneId];
}
$smsLog = SmsLog::where($where)
->order('send_time', 'desc')
->findOrEmpty();
// 没有验证码 或 最新验证码已校验 或 已过期(有效期5分钟)
if($smsLog->isEmpty() || $smsLog->is_verify || ($smsLog->send_time < time() - 5 * 60) ) {
return false;
}
// 更新校验状态
if($smsLog->code == $code) {
$smsLog->check_num = $smsLog->check_num + 1;
$smsLog->is_verify = YesNoEnum::YES;
$smsLog->save();
return true;
}
// 更新验证次数
$smsLog->check_num = $smsLog->check_num + 1;
$smsLog->save();
return false;
}
}

View File

@@ -0,0 +1,207 @@
<?php
// +----------------------------------------------------------------------
// | likeshop100%开源免费商用商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | 商业版本务必购买商业授权,以免引起法律纠纷
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | // +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
namespace app\common\service\sms;
use app\common\enum\notice\NoticeEnum;
use app\common\enum\notice\SmsEnum;
use app\common\logic\NoticeLogic;
use app\common\model\notice\NoticeSetting;
use app\common\model\notice\SmsLog;
use app\common\service\ConfigService;
/**
* 短信服务
* Class SmsMessageService
* @package app\common\service
*/
class SmsMessageService
{
protected $notice;
protected $smsLog;
public function send($params)
{
try {
// 通知设置
$noticeSetting = NoticeSetting::where('scene_id', $params['scene_id'])->findOrEmpty()->toArray();
//非+86则短信内容为英文
if(isset($params['params']['country_code']) && '+86' != $params['params']['country_code']){
$noticeSetting['sms_notice']['content'] = $noticeSetting['sms_notice']['content_en'];
}
// 添加短信记录
$content = $this->contentFormat($noticeSetting, $params);
$this->smsLog = $this->addSmsLog($params, $content);
// 添加通知记录
$this->notice = NoticeLogic::addNotice($params, $noticeSetting, NoticeEnum::SMS, $content);
// 发送短信
$smsDriver = new SmsDriver();
if(!is_null($smsDriver->getError())) {
throw new \Exception($smsDriver->getError());
}
$result = $smsDriver->send($params['params']['mobile'], [
'template_id' => $noticeSetting['sms_notice']['template_id'],
'params' => $this->setSmsParams($noticeSetting, $params),
'scene_content' => $content,
'country_code' => $params['params']['country_code']
]);
if ($result === false) {
// 发送失败更新短信记录
$this->updateSmsLog($this->smsLog['id'], SmsEnum::SEND_FAIL, $smsDriver->getError());
throw new \Exception($smsDriver->getError());
}
$result = true;
// 发送成功更新短信记录
$this->updateSmsLog($this->smsLog['id'], SmsEnum::SEND_SUCCESS, $result);
return true;
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
/**
* @notes 格式化消息内容
* @param $noticeSetting
* @param $params
* @return array|mixed|string|string[]
* @author 段誉
* @date 2022/9/15 16:24
*/
public function contentFormat($noticeSetting, $params)
{
$content = $noticeSetting['sms_notice']['content'];
foreach($params['params'] as $k => $v) {
$search = '${' . $k . '}';
$content = str_replace($search, $v, $content);
}
return $content;
}
/**
* @notes 添加短信记录
* @param $params
* @param $content
* @return SmsLog|\think\Model
* @author 段誉
* @date 2022/9/15 16:24
*/
public function addSmsLog($params, $content)
{
$data = [
'scene_id' => $params['scene_id'],
'mobile' => $params['params']['mobile'],
'content' => $content,
'code' => $params['params']['code'] ?? '',
'send_status' => SmsEnum::SEND_ING,
'send_time' => time(),
];
return SmsLog::create($data);
}
/**
* @notes 处理腾讯云短信参数
* @param $noticeSetting
* @param $params
* @return array|mixed
* @author 段誉
* @date 2022/9/15 16:25
*/
public function setSmsParams($noticeSetting, $params)
{
$defaultEngine = ConfigService::get('sms', 'engine', false);
// 阿里云 且是 验证码类型
if($defaultEngine != 'TENCENT' && in_array($params['scene_id'], NoticeEnum::SMS_SCENE)) {
return ['code' => $params['params']['code']];
}
if($defaultEngine != 'TENCENT') {
return $params['params'];
}
//腾讯云特殊处理
$arr = [];
$content = $noticeSetting['sms_notice']['content'];
foreach ($params['params'] as $item => $val) {
$search = '${' . $item . '}';
if(strpos($content, $search) !== false && !in_array($item, $arr)) {
//arr => 获的数组[nickname, order_sn] //顺序可能是乱的
$arr[] = $item;
}
}
//arr2 => 获得数组[nickname, order_sn] //调整好顺序的变量名数组
$arr2 = [];
if (!empty($arr)) {
foreach ($arr as $v) {
$key = strpos($content, $v);
$arr2[$key] = $v;
}
}
//格式化 arr2 => 以小到大的排序的数组
ksort($arr2);
$arr3 = array_values($arr2);
//arr4 => 获取到变量数组的对应的值 [mofung, 123456789]
$arr4 = [];
foreach ($arr3 as $v2) {
if(isset($params['params'][$v2])) {
$arr4[] = $params['params'][$v2] . "";
}
}
return $arr4;
}
/**
* @notes 更新短信记录
* @param $id
* @param $status
* @param $result
* @author 段誉
* @date 2022/9/15 16:25
*/
public function updateSmsLog($id, $status, $result)
{
SmsLog::update([
'id' => $id,
'send_status' => $status,
'results' => json_encode($result, JSON_UNESCAPED_UNICODE)
]);
}
}

View File

@@ -0,0 +1,161 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service\sms\engine;
use AlibabaCloud\Client\AlibabaCloud;
/**
* 阿里云短信
* Class AliSms
* @package app\common\service\sms\engine
*/
class AliSms
{
protected $error = null;
protected $config;
protected $mobile;
protected $templateId;
protected $templateParams;
public function __construct($config)
{
if(empty($config)) {
$this->error = '请联系管理员配置参数';
return false;
}
$this->config = $config;
}
/**
* @notes 设置手机号
* @param $mobile
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setMobile($mobile)
{
$this->mobile = $mobile;
return $this;
}
/**
* @notes 设置模板id
* @param $templateId
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setTemplateId($templateId)
{
$this->templateId = $templateId;
return $this;
}
/**
* @notes 设置模板参数
* @param $templateParams
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setTemplateParams($templateParams)
{
$this->templateParams = json_encode($templateParams, JSON_UNESCAPED_UNICODE);
return $this;
}
/**
* @notes 短信内容
* @param $sceneContent
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setSceneContent($sceneContent)
{
$this->sceneContent = $sceneContent;
return $this;
}
/**
* @notes 国家区号
* @param $sceneContent
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setCountryCode($countryCode)
{
$this->countryCode = $countryCode;
return $this;
}
/**
* @notes 错误信息
* @return string|null
* @author 段誉
* @date 2022/9/15 16:27
*/
public function getError()
{
return $this->error;
}
/**
* @notes 发送短信
* @return array|false
* @author 段誉
* @date 2022/9/15 16:27
*/
public function send()
{
try {
AlibabaCloud::accessKeyClient($this->config['app_key'], $this->config['secret_key'])
->regionId('cn-hangzhou')
->asDefaultClient();
$result = AlibabaCloud::rpcRequest()
->product('Dysmsapi')
->host('dysmsapi.aliyuncs.com')
->version('2017-05-25')
->action('SendSms')
->method('POST')
->options([
'query' => [
'PhoneNumbers' => $this->mobile, //发送手机号
'SignName' => $this->config['sign'], //短信签名
'TemplateCode' => $this->templateId, //短信模板CODE
'TemplateParam' => $this->templateParams, //自定义随机数
],
])
->request();
$res = $result->toArray();
if (isset($res['Code']) && $res['Code'] == 'OK') {
return $res;
}
$message = $res['Message'] ?? $res;
throw new \Exception('阿里云短信错误:' . $message);
} catch(\Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,162 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service\sms\engine;
/**
* 短信宝短信
* Class SmsbaoSms
* @package app\common\service\sms\engine
*/
class SmsbaoSms
{
protected $error = null;
protected $config;
protected $mobile;
protected $templateId;
protected $templateParams;
public function __construct($config)
{
if(empty($config)) {
$this->error = '请联系管理员配置参数';
return false;
}
$this->config = $config;
}
/**
* @notes 设置手机号
* @param $mobile
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setMobile($mobile)
{
$this->mobile = $mobile;
return $this;
}
/**
* @notes 设置模板id
* @param $templateId
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setTemplateId($templateId)
{
$this->templateId = $templateId;
return $this;
}
/**
* @notes 设置模板参数
* @param $templateParams
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setTemplateParams($templateParams)
{
$this->templateParams = json_encode($templateParams, JSON_UNESCAPED_UNICODE);
return $this;
}
/**
* @notes 短信内容
* @param $sceneContent
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setSceneContent($sceneContent)
{
$this->sceneContent = $sceneContent;
return $this;
}
/**
* @notes 国家区号
* @param $sceneContent
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setCountryCode($countryCode)
{
$this->countryCode = $countryCode;
return $this;
}
/**
* @notes 错误信息
* @return string|null
* @author 段誉
* @date 2022/9/15 16:27
*/
public function getError()
{
return $this->error;
}
/**
* @notes 发送短信
* @return array|false
* @author 段誉
* @date 2022/9/15 16:27
*/
public function send()
{
try {
$smsapi = $this->config['url_cn'];
$user = $this->config['username']; //短信平台帐号
$pass = md5($this->config['api_key']); //短信平台密码
$content = $this->sceneContent;//要发送的短信内容
$sendPhone = urlencode($this->mobile);//要发送短信的手机号码
$countryCode = $this->countryCode;//国家区号
if('+86' != $countryCode){
$sendPhone = urlencode($this->countryCode.$this->mobile);
$smsapi = $this->config['url_go'];
}
$sendurl = $smsapi."?u=".$user."&p=".$pass."&m=".$sendPhone."&c=".urlencode($content);
$result = file_get_contents($sendurl);
if($result !=0){
if($result ==51){
throw new \Exception('pwd.mobileError');
}else{
throw new \Exception('network.networkAnomaly');
}
}
} catch(\Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,164 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service\sms\engine;
use TencentCloud\Sms\V20190711\SmsClient;
use TencentCloud\Sms\V20190711\Models\SendSmsRequest;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;
/**
* 腾讯云短信
* Class TencentSms
* @package app\common\service\sms\engine
*/
class TencentSms
{
protected $error = null;
protected $config;
protected $mobile;
protected $templateId;
protected $templateParams;
public function __construct($config)
{
if(empty($config)) {
$this->error = '请联系管理员配置参数';
return false;
}
$this->config = $config;
}
/**
* @notes 设置手机号
* @param $mobile
* @return $this
* @author 段誉
* @date 2022/9/15 16:26
*/
public function setMobile($mobile)
{
$this->mobile = $mobile;
return $this;
}
/**
* @notes 设置模板id
* @param $templateId
* @return $this
* @author 段誉
* @date 2022/9/15 16:26
*/
public function setTemplateId($templateId)
{
$this->templateId = $templateId;
return $this;
}
/**
* @notes 设置模板参数
* @param $templateParams
* @return $this
* @author 段誉
* @date 2022/9/15 16:27
*/
public function setTemplateParams($templateParams)
{
$this->templateParams = $templateParams;
return $this;
}
/**
* @notes 短信内容
* @param $sceneContent
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setSceneContent($sceneContent)
{
$this->sceneContent = $sceneContent;
return $this;
}
/**
* @notes 国家区号
* @param $sceneContent
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setCountryCode($countryCode)
{
$this->countryCode = $countryCode;
return $this;
}
/**
* @notes 获取错误信息
* @return string|null
* @author 段誉
* @date 2022/9/15 16:27
*/
public function getError()
{
return $this->error;
}
/**
* @notes 发送短信
* @return false|mixed
* @author 段誉
* @date 2022/9/15 16:27
*/
public function send()
{
try {
$cred = new Credential($this->config['secret_id'], $this->config['secret_key']);
$httpProfile = new HttpProfile();
$httpProfile->setEndpoint("sms.tencentcloudapi.com");
$clientProfile = new ClientProfile();
$clientProfile->setHttpProfile($httpProfile);
$client = new SmsClient($cred, 'ap-guangzhou', $clientProfile);
$params = [
'PhoneNumberSet' => ['+86' . $this->mobile],
'TemplateID' => $this->templateId,
'Sign' => $this->config['sign'],
'TemplateParamSet' => $this->templateParams,
'SmsSdkAppid' => $this->config['app_id'],
];
$req = new SendSmsRequest();
$req->fromJsonString(json_encode($params));
$resp = json_decode($client->SendSms($req)->toJsonString(), true);
if (isset($resp['SendStatusSet']) && $resp['SendStatusSet'][0]['Code'] == 'Ok') {
return $resp;
} else {
$message = $res['SendStatusSet'][0]['Message'] ?? json_encode($resp);
throw new \Exception('腾讯云短信错误:' . $message);
}
} catch(\Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace app\common\service\storage;
use think\Exception;
/**
* 存储模块驱动
* Class driver
* @package app\common\library\storage
*/
class Driver
{
private $config; // upload 配置
private $engine; // 当前存储引擎类
/**
* 构造方法
* Driver constructor.
* @param $config
* @param null|string $storage 指定存储方式,如不指定则为系统默认
* @throws Exception
*/
public function __construct($config, $storage = null)
{
$this->config = $config;
$this->engine = $this->getEngineClass($storage);
}
/**
* 设置上传的文件信息
* @param string $name
* @return mixed
*/
public function setUploadFile($name = 'iFile')
{
return $this->engine->setUploadFile($name);
}
/**
* 设置上传的文件信息
* @param string $filePath
* @return mixed
*/
public function setUploadFileByReal($filePath)
{
return $this->engine->setUploadFileByReal($filePath);
}
/**
* 执行文件上传
* @param $save_dir (保存路径)
* @return mixed
*/
public function upload($save_dir)
{
return $this->engine->upload($save_dir);
}
/**
* Notes: 抓取网络资源
* @param $url
* @param $key
* @author 张无忌(2021/3/2 14:16)
* @return mixed
*/
public function fetch($url, $key) {
return $this->engine->fetch($url, $key);
}
/**
* 执行文件删除
* @param $fileName
* @return mixed
*/
public function delete($fileName)
{
return $this->engine->delete($fileName);
}
/**
* 获取错误信息
* @return mixed
*/
public function getError()
{
return $this->engine->getError();
}
/**
* 获取文件路径
* @return mixed
*/
public function getFileName()
{
return $this->engine->getFileName();
}
/**
* 返回文件信息
* @return mixed
*/
public function getFileInfo()
{
return $this->engine->getFileInfo();
}
/**
* 获取当前的存储引擎
* @param null|string $storage 指定存储方式,如不指定则为系统默认
* @return mixed
* @throws Exception
*/
private function getEngineClass($storage = null)
{
$engineName = is_null($storage) ? $this->config['default'] : $storage;
$classSpace = __NAMESPACE__ . '\\engine\\' . ucfirst($engineName);
if (!class_exists($classSpace)) {
throw new Exception('未找到存储引擎类: ' . $engineName);
}
if($engineName == 'local') {
return new $classSpace();
}
return new $classSpace($this->config['engine'][$engineName]);
}
}

View File

@@ -0,0 +1,115 @@
<?php
namespace app\common\service\storage\engine;
use OSS\OssClient;
use OSS\Core\OssException;
/**
* 阿里云存储引擎 (OSS)
* Class Qiniu
* @package app\common\library\storage\engine
*/
class Aliyun extends Server
{
private $config;
/**
* 构造方法
* Aliyun constructor.
* @param $config
*/
public function __construct($config)
{
parent::__construct();
$this->config = $config;
}
/**
* 执行上传
* @param $save_dir (保存路径)
* @return bool|mixed
*/
public function upload($save_dir)
{
try {
$ossClient = new OssClient(
$this->config['access_key'],
$this->config['secret_key'],
$this->config['domain'],
true
);
$ossClient->uploadFile(
$this->config['bucket'],
$save_dir . '/' . $this->fileName,
$this->getRealPath()
);
} catch (OssException $e) {
$this->error = $e->getMessage();
return false;
}
return true;
}
/**
* Notes: 抓取远程资源
* @param $url
* @param null $key
* @return mixed|void
* @author 张无忌(2021/3/2 14:36)
*/
public function fetch($url, $key = null)
{
try {
$ossClient = new OssClient(
$this->config['access_key'],
$this->config['secret_key'],
$this->config['domain'],
true
);
$content = file_get_contents($url);
$ossClient->putObject(
$this->config['bucket'],
$key,
$content
);
} catch (OssException $e) {
$this->error = $e->getMessage();
return false;
}
return true;
}
/**
* 删除文件
* @param $fileName
* @return bool|mixed
*/
public function delete($fileName)
{
try {
$ossClient = new OssClient(
$this->config['access_key'],
$this->config['access_key'],
$this->config['domain'],
true
);
$ossClient->deleteObject($this->config['bucket'], $fileName);
} catch (OssException $e) {
$this->error = $e->getMessage();
return false;
}
return true;
}
/**
* 返回文件路径
* @return mixed
*/
public function getFileName()
{
return $this->fileName;
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace app\common\service\storage\engine;
/**
* 本地文件驱动
* Class Local
* @package app\common\library\storage\drivers
*/
class Local extends Server
{
public function __construct()
{
parent::__construct();
}
/**
* 上传
* @param $save_dir (保存路径)
* @return bool
*/
public function upload($save_dir)
{
// 验证文件并上传
$info = $this->file->move($save_dir, $this->fileName);
if (empty($info)) {
$this->error = $this->file->getError();
return false;
}
return true;
}
public function fetch($url, $key=null) {}
/**
* 删除文件
* @param $fileName
* @return bool|mixed
*/
public function delete($fileName)
{
$check = strpos($fileName, '/');
if ($check !== false && $check == 0) {
// 文件所在目录
$fileName = substr_replace($fileName,"",0,1);
}
$filePath = public_path() . "{$fileName}";
return !file_exists($filePath) ?: unlink($filePath);
}
/**
* 返回文件路径
* @return mixed
*/
public function getFileName()
{
return $this->fileName;
}
}

View File

@@ -0,0 +1,116 @@
<?php
namespace app\common\service\storage\engine;
use Exception;
use Qcloud\Cos\Client;
/**
* 腾讯云存储引擎 (COS)
* Class Qiniu
* @package app\common\library\storage\engine
*/
class Qcloud extends Server
{
private $config;
private $cosClient;
/**
* 构造方法
* Qcloud constructor.
* @param $config
*/
public function __construct($config)
{
parent::__construct();
$this->config = $config;
// 创建COS控制类
$this->createCosClient();
}
/**
* 创建COS控制类
*/
private function createCosClient()
{
$this->cosClient = new Client([
'region' => $this->config['region'],
'credentials' => [
'secretId' => $this->config['access_key'],
'secretKey' => $this->config['secret_key'],
],
]);
}
/**
* 执行上传
* @param $save_dir (保存路径)
* @return bool|mixed
*/
public function upload($save_dir)
{
// 上传文件
// putObject(上传接口最大支持上传5G文件)
try {
$result = $this->cosClient->putObject([
'Bucket' => $this->config['bucket'],
'Key' => $save_dir . '/' . $this->fileName,
'Body' => fopen($this->getRealPath(), 'rb')
]);
return true;
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* notes: 抓取远程资源(最大支持上传5G文件)
* @param $url
* @param null $key
* @author 张无忌(2021/3/2 14:36)
* @return mixed|void
*/
public function fetch($url, $key=null) {
try {
$this->cosClient->putObject([
'Bucket' => $this->config['bucket'],
'Key' => $key,
'Body' => fopen($url, 'rb')
]);
return true;
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* 删除文件
* @param $fileName
* @return bool|mixed
*/
public function delete($fileName)
{
try {
$this->cosClient->deleteObject(array(
'Bucket' => $this->config['bucket'],
'Key' => $fileName
));
return true;
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* 返回文件路径
* @return mixed
*/
public function getFileName()
{
return $this->fileName;
}
}

View File

@@ -0,0 +1,136 @@
<?php
namespace app\common\service\storage\engine;
use Exception;
use Qiniu\Auth;
use Qiniu\Storage\UploadManager;
use Qiniu\Storage\BucketManager;
/**
* 七牛云存储引擎
* Class Qiniu
* @package app\common\library\storage\engine
*/
class Qiniu extends Server
{
private $config;
/**
* 构造方法
* Qiniu constructor.
* @param $config
*/
public function __construct($config)
{
parent::__construct();
$this->config = $config;
}
/**
* @notes 执行上传
* @param $save_dir
* @return bool|mixed
* @author 张无忌
* @date 2021/7/27 16:02
*/
public function upload($save_dir)
{
// 要上传图片的本地路径
$realPath = $this->getRealPath();
// 构建鉴权对象
$auth = new Auth($this->config['access_key'], $this->config['secret_key']);
// 要上传的空间
$token = $auth->uploadToken($this->config['bucket']);
// 初始化 UploadManager 对象并进行文件的上传
$uploadMgr = new UploadManager();
try {
// 调用 UploadManager 的 putFile 方法进行文件的上传
$key = $save_dir . '/' . $this->fileName;
list(, $error) = $uploadMgr->putFile($token, $key, $realPath);
if ($error !== null) {
$this->error = $error->message();
return false;
}
return true;
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* @notes 抓取远程资源
* @param $url
* @param null $key
* @return bool|mixed
* @author 张无忌
* @date 2021/7/27 16:02
*/
public function fetch($url, $key=null)
{
try {
if (substr($url, 0, 1) !== '/' || strstr($url, 'http://') || strstr($url, 'https://')) {
$auth = new Auth($this->config['access_key'], $this->config['secret_key']);
$bucketManager = new BucketManager($auth);
list(, $err) = $bucketManager->fetch($url, $this->config['bucket'], $key);
} else {
$auth = new Auth($this->config['access_key'], $this->config['secret_key']);
$token = $auth->uploadToken($this->config['bucket']);
$uploadMgr = new UploadManager();
list(, $err) = $uploadMgr->putFile($token, $key, $url);
}
if ($err !== null) {
$this->error = $err->message();
return false;
}
return true;
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* @notes 删除文件
* @param $fileName
* @return bool|mixed
* @author 张无忌
* @date 2021/7/27 16:02
*/
public function delete($fileName)
{
// 构建鉴权对象
$auth = new Auth($this->config['access_key'], $this->config['secret_key']);
// 初始化 UploadManager 对象并进行文件的上传
$bucketMgr = new BucketManager($auth);
try {
list($res, $error) = $bucketMgr->delete($this->config['bucket'], $fileName);
if ($error !== null) {
$this->error = $error->message();
return false;
}
return true;
} catch (Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* 返回文件路径
* @return mixed
*/
public function getFileName()
{
return $this->fileName;
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace app\common\service\storage\engine;
use think\Request;
use think\Exception;
/**
* 存储引擎抽象类
* Class server
* @package app\common\library\storage\drivers
*/
abstract class Server
{
protected $file;
protected $error;
protected $fileName;
protected $fileInfo;
// 是否为内部上传
protected $isInternal = false;
/**
* 构造函数
* Server constructor.
*/
protected function __construct()
{
}
/**
* 设置上传的文件信息
* @param string $name
* @throws Exception
*/
public function setUploadFile($name)
{
// 接收上传的文件
$this->file = request()->file($name);
if (empty($this->file)) {
throw new Exception('未找到上传文件的信息');
}
// 校验上传文件后缀
$limit = array_merge(config('project.file_image'), config('project.file_video'));
if (!in_array(strtolower($this->file->extension()), $limit)) {
throw new Exception('不允许上传' . $this->file->extension() . '后缀文件');
}
// 文件信息
$this->fileInfo = [
'ext' => $this->file->extension(),
'size' => $this->file->getSize(),
'mime' => $this->file->getMime(),
'name' => $this->file->getOriginalName(),
'realPath' => $this->file->getRealPath(),
];
// 生成保存文件名
$this->fileName = $this->buildSaveName();
}
/**
* 设置上传的文件信息
* @param string $filePath
*/
public function setUploadFileByReal($filePath)
{
// 设置为系统内部上传
$this->isInternal = true;
// 文件信息
$this->fileInfo = [
'name' => basename($filePath),
'size' => filesize($filePath),
'tmp_name' => $filePath,
'error' => 0,
];
// 生成保存文件名
$this->fileName = $this->buildSaveName();
}
/**
* Notes: 抓取网络资源
* @param $url
* @param $key
* @author 张无忌(2021/3/2 14:15)
* @return mixed
*/
abstract protected function fetch($url, $key);
/**
* 文件上传
* @param $save_dir (保存路径)
* @return mixed
*/
abstract protected function upload($save_dir);
/**
* 文件删除
* @param $fileName
* @return mixed
*/
abstract protected function delete($fileName);
/**
* 返回上传后文件路径
* @return mixed
*/
abstract public function getFileName();
/**
* 返回文件信息
* @return mixed
*/
public function getFileInfo()
{
return $this->fileInfo;
}
protected function getRealPath()
{
return $this->fileInfo['realPath'];
}
/**
* 返回错误信息
* @return mixed
*/
public function getError()
{
return $this->error;
}
/**
* 生成保存文件名
*/
private function buildSaveName()
{
// 要上传图片的本地路径
$realPath = $this->getRealPath();
// 扩展名
$ext = pathinfo($this->getFileInfo()['name'], PATHINFO_EXTENSION);
// 自动生成文件名
return date('YmdHis') . substr(md5($realPath), 0, 5)
. str_pad(rand(0, 9999), 4, '0', STR_PAD_LEFT) . ".{$ext}";
}
}