This commit is contained in:
mkm 2023-09-20 13:54:09 +08:00
parent 609dee44a5
commit 4e2cb898e7
82 changed files with 7081 additions and 1957 deletions

View File

@ -58,29 +58,29 @@ abstract class BaseController
*/
protected function validate(array $data, $validate, array $message = [], bool $batch = false)
{
if (is_array($validate)) {
$v = new Validate();
$v->rule($validate);
} else {
if (strpos($validate, '.')) {
// 支持场景
[$validate, $scene] = explode('.', $validate);
}
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
$v = new $class();
if (!empty($scene)) {
$v->scene($scene);
}
}
// if (is_array($validate)) {
// $v = new Validate();
// $v->rule($validate);
// } else {
// if (strpos($validate, '.')) {
// // 支持场景
// [$validate, $scene] = explode('.', $validate);
// }
// $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
// $v = new $class();
// if (!empty($scene)) {
// $v->scene($scene);
// }
// }
$v->message($message);
// $v->message($message);
// 是否批量验证
if ($batch || $this->batchValidate) {
$v->batch(true);
}
// // 是否批量验证
// if ($batch || $this->batchValidate) {
// $v->batch(true);
// }
return $v->failException(true)->check($data);
// return $v->failException(true)->check($data);
}

View File

@ -9,8 +9,6 @@ use app\common\lists\BaseDataLists;
class BaseAdminController extends BaseLikeAdminController
{
public $notNeedLogin = [];
protected $adminId = 0;
protected $adminInfo = [];

View File

@ -0,0 +1,208 @@
<?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\admin\controller\tools;
use app\admin\controller\BaseAdminController;
use app\admin\lists\tools\DataTableLists;
use app\admin\lists\tools\GenerateTableLists;
use app\admin\logic\tools\GeneratorLogic;
use app\admin\validate\tools\EditTableValidate;
use app\admin\validate\tools\GenerateTableValidate;
/**
* 代码生成器控制器
* Class GeneratorController
* @package app\admin\controller\article
*/
class GeneratorController extends BaseAdminController
{
// public array $notNeedLogin = ['download'];
/**
* @notes 获取数据库中所有数据表信息
* @return \think\response\Json
* @author 段誉
* @date 2022/6/14 10:57
*/
public function dataTable()
{
return $this->dataLists(new DataTableLists());
}
/**
* @notes 获取已选择的数据表
* @return \think\response\Json
* @author 段誉
* @date 2022/6/14 10:57
*/
public function generateTable()
{
return $this->dataLists(new GenerateTableLists());
}
/**
* @notes 选择数据表
* @return \think\response\Json
* @author 段誉
* @date 2022/6/15 10:09
*/
public function selectTable()
{
$params = (new GenerateTableValidate())->post()->goCheck('select');
$result = GeneratorLogic::selectTable($params, $this->adminId);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(GeneratorLogic::getError());
}
/**
* @notes 生成代码
* @return \think\response\Json
* @author 段誉
* @date 2022/6/23 19:08
*/
public function generate()
{
$params = (new GenerateTableValidate())->post()->goCheck('id');
$result = GeneratorLogic::generate($params);
if (false === $result) {
return $this->fail(GeneratorLogic::getError());
}
return $this->success('操作成功', $result, 1, 1);
}
/**
* @notes 下载文件
* @return \think\response\File|\think\response\Json
* @author 段誉
* @date 2022/6/24 9:51
*/
public function download()
{
$params = (new GenerateTableValidate())->goCheck('download');
$result = GeneratorLogic::download($params['file']);
if (false === $result) {
return $this->fail(GeneratorLogic::getError() ?: '下载失败');
}
return download($result, 'likeadmin-curd.zip');
}
/**
* @notes 预览代码
* @return \think\response\Json
* @author 段誉
* @date 2022/6/23 19:07
*/
public function preview()
{
$params = (new GenerateTableValidate())->post()->goCheck('id');
$result = GeneratorLogic::preview($params);
if (false === $result) {
return $this->fail(GeneratorLogic::getError());
}
return $this->data($result);
}
/**
* @notes 同步字段
* @return \think\response\Json
* @author 段誉
* @date 2022/6/17 15:22
*/
public function syncColumn()
{
$params = (new GenerateTableValidate())->post()->goCheck('id');
$result = GeneratorLogic::syncColumn($params);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(GeneratorLogic::getError());
}
/**
* @notes 编辑表信息
* @return \think\response\Json
* @author 段誉
* @date 2022/6/20 10:44
*/
public function edit()
{
$params = (new EditTableValidate())->post()->goCheck();
$result = GeneratorLogic::editTable($params);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(GeneratorLogic::getError());
}
/**
* @notes 获取已选择的数据表详情
* @return \think\response\Json
* @author 段誉
* @date 2022/6/15 19:00
*/
public function detail()
{
$params = (new GenerateTableValidate())->goCheck('id');
$result = GeneratorLogic::getTableDetail($params);
return $this->success('', $result);
}
/**
* @notes 删除已选择的数据表信息
* @return \think\response\Json
* @author 段誉
* @date 2022/6/15 19:00
*/
public function delete()
{
$params = (new GenerateTableValidate())->post()->goCheck('id');
$result = GeneratorLogic::deleteTable($params);
if (true === $result) {
return $this->success('操作成功', [], 1, 1);
}
return $this->fail(GeneratorLogic::getError());
}
/**
* @notes 获取模型
* @return \think\response\Json
* @author 段誉
* @date 2022/12/14 11:07
*/
public function getModels()
{
$result = GeneratorLogic::getAllModels();
return $this->success('', $result, 1, 1);
}
}

View File

@ -0,0 +1,74 @@
<?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\admin\lists\tools;
use app\admin\lists\BaseAdminDataLists;
use think\facade\Db;
/**
* 数据表列表
* Class GeneratorLists
* @package app\admin\lists\tools
*/
class DataTableLists extends BaseAdminDataLists
{
/**
* @notes 查询结果
* @return mixed
* @author 段誉
* @date 2022/6/13 18:54
*/
public function queryResult()
{
$sql = 'SHOW TABLE STATUS WHERE 1=1 ';
if (!empty($this->params['name'])) {
$sql .= "AND name LIKE '%" . $this->params['name'] . "%'";
}
if (!empty($this->params['comment'])) {
$sql .= "AND comment LIKE '%" . $this->params['comment'] . "%'";
}
return Db::query($sql);
}
/**
* @notes 处理列表
* @return array
* @author 段誉
* @date 2022/6/13 18:54
*/
public function lists(): array
{
$lists = array_map("array_change_key_case", $this->queryResult());
$offset = max(0, ($this->pageNo - 1) * $this->pageSize);
$lists = array_slice($lists, $offset, $this->pageSize, true);
return array_values($lists);
}
/**
* @notes 获取数量
* @return int
* @author 段誉
* @date 2022/6/13 18:54
*/
public function count(): int
{
return count($this->queryResult());
}
}

View File

@ -0,0 +1,75 @@
<?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\admin\lists\tools;
use app\admin\lists\BaseAdminDataLists;
use app\common\lists\ListsSearchInterface;
use app\common\model\tools\GenerateTable;
/**
* 代码生成所选数据表列表
* Class GenerateTableLists
* @package app\admin\lists\tools
*/
class GenerateTableLists extends BaseAdminDataLists implements ListsSearchInterface
{
/**
* @notes 设置搜索条件
* @return \string[][]
* @author 段誉
* @date 2022/6/14 10:55
*/
public function setSearch(): array
{
return [
'%like%' => ['table_name', 'table_comment']
];
}
/**
* @notes 查询列表
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/6/14 10:55
*/
public function lists(): array
{
return GenerateTable::where($this->searchWhere)
->order(['id' => 'desc'])
->append(['template_type_desc'])
->limit($this->limitOffset, $this->limitLength)
->select()
->toArray();
}
/**
* @notes 获取数量
* @return int
* @author 段誉
* @date 2022/6/14 10:55
*/
public function count(): int
{
return GenerateTable::count();
}
}

View File

@ -46,7 +46,6 @@ class LoginLogic extends BaseLogic
$admin->login_time = $time;
$admin->login_ip = request()->getLocalIp();
$admin->save();
//设置token
$adminInfo = AdminTokenService::setToken($admin->id, $params['terminal'], $admin->multipoint_login);

View File

@ -19,6 +19,8 @@ use app\common\logic\BaseLogic;
use app\common\model\tools\GenerateColumn;
use app\common\model\tools\GenerateTable;
use app\common\service\generator\GenerateService;
use support\Cache;
use support\Container;
use think\facade\Db;
@ -205,8 +207,7 @@ class GeneratorLogic extends BaseLogic
$tables = GenerateTable::with(['table_column'])
->whereIn('id', $params['id'])
->select()->toArray();
$generator = app()->make(GenerateService::class);
$generator= Container::get(GenerateService::class);
$generator->delGenerateDirContent();
$flag = array_unique(array_column($tables, 'table_name'));
$flag = implode(',', $flag);
@ -224,7 +225,6 @@ class GeneratorLogic extends BaseLogic
$generator->delGenerateFlag();
$zipFile = $generator->getDownloadUrl();
}
return ['file' => $zipFile];
} catch (\Exception $e) {
@ -249,7 +249,7 @@ class GeneratorLogic extends BaseLogic
->whereIn('id', $params['id'])
->findOrEmpty()->toArray();
return app()->make(GenerateService::class)->preview($table);
return Container::get(GenerateService::class)->preview($table);
} catch (\Exception $e) {
self::$error = $e->getMessage();
@ -358,19 +358,17 @@ class GeneratorLogic extends BaseLogic
*/
public static function download(string $fileName)
{
$cacheFileName = cache('curd_file_name' . $fileName);
$cacheFileName = Cache::get('curd_file_name' . $fileName);
if (empty($cacheFileName)) {
self::$error = '请重新生成代码';
return false;
}
$path = root_path() . 'runtime/generate/' . $fileName;
$path = base_path() . '/runtime/generate/' . $fileName;
if (!file_exists($path)) {
self::$error = '下载失败';
return false;
}
cache('curd_file_name' . $fileName, null);
Cache::delete('curd_file_name' . $fileName);
return $path;
}

View File

@ -72,8 +72,8 @@ class LoginValidate extends BaseValidate
$adminAccountSafeCache->record();
return '账号不存在';
}
if (!password_verify($password,$adminInfo['password'])) {
$passwordSalt = Config::get('project.unique_identification');
if ($adminInfo['password'] !== create_password($password, $passwordSalt)) {
$adminAccountSafeCache->record();
return '密码错误';
}

View File

@ -0,0 +1,98 @@
<?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\admin\validate\tools;
use app\common\model\tools\GenerateTable;
use app\common\validate\BaseValidate;
/**
* 编辑表验证
* Class EditTableValidate
* @package app\admin\validate\tools
*/
class EditTableValidate extends BaseValidate
{
protected $rule = [
'id' => 'require|checkTableData',
'table_name' => 'require',
'table_comment' => 'require',
'template_type' => 'require|in:0,1',
'generate_type' => 'require|in:0,1',
'module_name' => 'require',
'table_column' => 'require|array|checkColumn',
];
protected $message = [
'id.require' => '表id缺失',
'table_name.require' => '请填写表名称',
'table_comment.require' => '请填写表描述',
'template_type.require' => '请选择模板类型',
'template_type.in' => '模板类型参数错误',
'generate_type.require' => '请选择生成方式',
'generate_type.in' => '生成方式类型错误',
'module_name.require' => '请填写模块名称',
'table_column.require' => '表字段信息缺失',
'table_column.array' => '表字段信息类型错误',
];
/**
* @notes 校验当前数据表是否存在
* @param $value
* @param $rule
* @param $data
* @return bool|string
* @author 段誉
* @date 2022/6/15 18:58
*/
protected function checkTableData($value, $rule, $data)
{
$table = GenerateTable::findOrEmpty($value);
if ($table->isEmpty()) {
return '信息不存在';
}
return true;
}
/**
* @notes 校验表字段参数
* @param $value
* @param $rule
* @param $data
* @return bool|string
* @author 段誉
* @date 2022/6/20 10:42
*/
protected function checkColumn($value, $rule, $data)
{
foreach ($value as $item) {
if (!isset($item['id'])) {
return '表字段id参数缺失';
}
if (!isset($item['query_type'])) {
return '请选择查询方式';
}
if (!isset($item['view_type'])) {
return '请选择显示类型';
}
}
return true;
}
}

View File

@ -0,0 +1,131 @@
<?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\admin\validate\tools;
use app\common\model\tools\GenerateTable;
use app\common\validate\BaseValidate;
use think\facade\Db;
/**
* 代码生成选择表验证
* Class SelectTableValidate
* @package app\admin\validate\tools
*/
class GenerateTableValidate extends BaseValidate
{
protected $rule = [
'id' => 'require|checkTableData',
'table' => 'require|array|checkTable',
'file' => 'require'
];
protected $message = [
'id.require' => '参数缺失',
'table.require' => '参数缺失',
'table.array' => '参数类型错误',
'file.require' => '下载失败',
];
/**
* @notes 选择数据表场景
* @return GenerateTableValidate
* @author 段誉
* @date 2022/6/15 18:58
*/
public function sceneSelect()
{
return $this->only(['table']);
}
/**
* @notes 需要校验id的场景
* @return GenerateTableValidate
* @author 段誉
* @date 2022/6/15 18:58
*/
public function sceneId()
{
return $this->only(['id']);
}
/**
* @notes 下载场景
* @return GenerateTableValidate
* @author 段誉
* @date 2022/6/24 10:02
*/
public function sceneDownload()
{
return $this->only(['file']);
}
/**
* @notes 校验选择的数据表信息
* @param $value
* @param $rule
* @param $data
* @return bool|string
* @author 段誉
* @date 2022/6/15 18:58
*/
protected function checkTable($value, $rule, $data)
{
foreach ($value as $item) {
if (!isset($item['name']) || !isset($item['comment'])) {
return '参数缺失';
}
$exist = Db::query("SHOW TABLES LIKE'" . $item['name'] . "'");
if (empty($exist)) {
return '当前数据库不存在' . $item['name'] . '表';
}
}
return true;
}
/**
* @notes 校验当前数据表是否存在
* @param $value
* @param $rule
* @param $data
* @return bool|string
* @author 段誉
* @date 2022/6/15 18:58
*/
protected function checkTableData($value, $rule, $data)
{
if (!is_array($value)) {
$value = [$value];
}
foreach ($value as $item) {
$table = GenerateTable::findOrEmpty($item);
if ($table->isEmpty()) {
return '信息不存在';
}
}
return true;
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace app\api\controller;
use WebSocket\Client;
class IndexController{
public function index(){
}
}

View File

@ -3,8 +3,7 @@
namespace app\common\cache;
use think\facade\Cache;
use support\Cache;
class AdminAccountSafeCache extends BaseCache
{
@ -28,7 +27,7 @@ class AdminAccountSafeCache extends BaseCache
{
if (Cache::get($this->key)) {
//缓存存在,记录错误次数
Cache::inc($this->key, 1);
Cache::set($this->key, Cache::get($this->key) + 1);
} else {
//缓存不存在,第一次设置缓存
Cache::set($this->key, 1, $this->minute * 60);

View File

@ -5,7 +5,7 @@ namespace app\common\cache;
use app\admin\logic\auth\AuthLogic;
use think\facade\Cache;
use support\Cache;
class AdminAuthCache extends BaseCache
{

View File

@ -8,7 +8,7 @@ use app\common\model\auth\Admin;
use app\common\model\auth\AdminSession;
use app\common\model\auth\SystemRole;
use app\common\model\BaseModel;
use think\facade\Cache;
use support\Cache;
class AdminTokenCache extends BaseCache
{
@ -82,7 +82,7 @@ class AdminTokenCache extends BaseCache
'terminal' => $adminSession->terminal,
'expire_time' => $adminSession->expire_time,
];
Cache::set($this->prefix . $token, $adminInfo, new \DateTime(Date('Y-m-d H:i:s', $adminSession->expire_time)));
Cache::set($this->prefix . $token, $adminInfo);
return $this->getAdminInfo($token);
}

View File

@ -3,7 +3,7 @@
namespace app\common\cache;
use think\facade\Cache;
use support\Cache;
class BaseCache
{
@ -30,7 +30,7 @@ class BaseCache
*/
public function set($key, $value, $ttl = null): bool
{
return Cache::store()->tag($this->tagName)->set($key, $value, $ttl);
return Cache::set($key, $value, $ttl);
}
@ -42,6 +42,6 @@ class BaseCache
*/
public function deleteTag(): bool
{
return Cache::tag($this->tagName)->clear();
return Cache::delete($this->tagName);
}
}

View File

@ -14,9 +14,7 @@
namespace app\common\cache;
use think\facade\Cache;
use support\Cache;
class ExportCache extends BaseCache
{

View File

@ -48,7 +48,7 @@ class BaseLikeAdminController extends BaseController
protected function dataLists(BaseDataLists $lists = null)
{
//列表类和控制器一一对应,"app/应用/controller/控制器的方法" =》"app\应用\lists\"目录下
//(例如:"app/adminapi/controller/auth/AdminController.php的lists()方法" =》 "app/adminapi/lists/auth/AminLists.php")
//(例如:"app/admin/controller/auth/AdminController.php的lists()方法" =》 "app/admin/lists/auth/AminLists.php")
//当对象为空时,自动创建列表对象
if (is_null($lists)) {
// $listName = str_replace('.', '\\', App::getNamespace() . '\\lists\\' . $this->request->controller() . ucwords($this->request->action()));

View File

@ -0,0 +1,63 @@
<?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\enum;
class GeneratorEnum
{
// 模板类型
const TEMPLATE_TYPE_SINGLE = 0;// 单表
const TEMPLATE_TYPE_TREE = 1; // 树表
// 生成方式
const GENERATE_TYPE_ZIP = 0; // 压缩包下载
const GENERATE_TYPE_MODULE = 1; // 生成到模块
// 删除方式
const DELETE_TRUE = 0; // 真实删除
const DELETE_SOFT = 1; // 软删除
// 删除字段名 (默认名称)
const DELETE_NAME = 'delete_time';
// 菜单创建类型
const GEN_SELF = 0; // 手动添加
const GEN_AUTO = 1; // 自动添加
// 关联模型类型relations
const RELATION_HAS_ONE = 'has_one';
const RELATION_HAS_MANY = 'has_many';
/**
* @notes 获取模板类型描述
* @param bool $value
* @return string|string[]
* @author 段誉
* @date 2022/6/14 11:24
*/
public static function getTemplateTypeDesc($value = true)
{
$data = [
self::TEMPLATE_TYPE_SINGLE => '单表(增删改查)',
self::TEMPLATE_TYPE_TREE => '树表(增删改查)',
];
if ($value === true) {
return $data;
}
return $data[$value] ?? '';
}
}

View File

@ -0,0 +1,39 @@
<?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\model\tools;
use app\common\model\BaseModel;
/**
* 代码生成器-数据表字段信息模型
* Class GenerateColumn
* @package app\common\model\tools
*/
class GenerateColumn extends BaseModel
{
/**
* @notes 关联table表
* @return \think\model\relation\BelongsTo
* @author 段誉
* @date 2022/6/15 18:59
*/
public function generateTable()
{
return $this->belongsTo(GenerateTable::class, 'id', 'table_id');
}
}

View File

@ -0,0 +1,59 @@
<?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\model\tools;
use app\common\enum\GeneratorEnum;
use app\common\model\BaseModel;
/**
* 代码生成器-数据表信息模型
* Class GenerateTable
* @package app\common\model\tools
*/
class GenerateTable extends BaseModel
{
protected $json = ['menu', 'tree', 'relations', 'delete'];
protected $jsonAssoc = true;
/**
* @notes 关联数据表字段
* @return \think\model\relation\HasMany
* @author 段誉
* @date 2022/6/15 10:46
*/
public function tableColumn()
{
return $this->hasMany(GenerateColumn::class, 'table_id', 'id');
}
/**
* @notes 模板类型描述
* @param $value
* @param $data
* @return string|string[]
* @author 段誉
* @date 2022/6/14 11:25
*/
public function getTemplateTypeDescAttr($value, $data)
{
return GeneratorEnum::getTemplateTypeDesc($data['template_type']);
}
}

View File

@ -4,7 +4,7 @@
namespace app\common\service;
use think\facade\Cache;
use support\Cache;
class FileService
{

View File

@ -0,0 +1,236 @@
<?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;
use support\Cache;
use support\Container;
use support\Log;
use function DI\env;
use function DI\value;
/**
* 生成器
* 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 = base_path() . '/runtime/generate/';
$this->runtimePath = base_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::set($name, (int)$status, 3600);
}
/**
* @notes 获取生成状态标记
* @return mixed|object|\think\App
* @author 段誉
* @date 2022/6/23 18:53
*/
public function getGenerateFlag()
{
return Cache::get($this->flag);
}
/**
* @notes 删除标记时间
* @author 段誉
* @date 2022/6/23 18:53
*/
public function delGenerateFlag()
{
Cache::delete($this->flag);
}
/**
* @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 = Container::get($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 = Container::get($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::set('curd_file_name' . $this->zipTempName, $this->zipTempName, 3600);
return "admin/tools/generator/download?file=".$this->zipTempName;
}
}

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 = app_path().'/';
$this->templateDir = app_path() . '/common/service/generator/stub/';
$this->generatorDir = $this->basePath . '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,222 @@
<?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 == 'admin') {
$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 != 'admin') {
$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 == 'admin') {
$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 != 'admin') {
$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_path()) . '/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_path()) . '/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,105 @@
<?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}
{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,76 @@
<?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}
{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,106 @@
<?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}
{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,34 @@
<?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}
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,77 @@
<?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}
{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,94 @@
<?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}
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

@ -2,6 +2,10 @@
/**
* Here is your custom functions.
*/
use support\Response;
use support\Request;
if(!function_exists('substr_symbol_behind')){
/**
* @notes 截取某字符字符串
@ -59,6 +63,19 @@ function create_token(string $extra = '') : string
return md5($extra . time());
}
/**
* @notes 生成密码加密密钥
* @param string $plaintext
* @param string $salt
* @return string
* @author 段誉
* @date 2021/12/28 18:24
*/
function create_password(string $plaintext, string $salt) : string
{
return md5($salt . md5($plaintext . $salt));
}
/**
* 多级线性结构排序
* 转换前:
@ -107,3 +124,76 @@ function createDir($path){
}
return mkdir($path);
}
if (!function_exists('download')) {
/**
* 获取\think\response\Download对象实例
* @param string $filename 要下载的文件
* @param string $name 显示文件名
* @param bool $content 是否为内容
* @param int $expire 有效期(秒)
* @return \think\response\File
*/
function download(string $filename, string $name = '', bool $content = false, int $expire = 180)
{
return response()->download($filename,$name);
}
}
/**
* @notes 删除目标目录
* @param $path
* @param $delDir
* @return bool|void
* @author 段誉
* @date 2022/4/8 16:30
*/
function del_target_dir($path, $delDir)
{
//没找到,不处理
if (!file_exists($path)) {
return false;
}
//打开目录句柄
$handle = opendir($path);
if ($handle) {
while (false !== ($item = readdir($handle))) {
if ($item != "." && $item != "..") {
if (is_dir("$path/$item")) {
del_target_dir("$path/$item", $delDir);
} else {
unlink("$path/$item");
}
}
}
closedir($handle);
if ($delDir) {
return rmdir($path);
}
} else {
if (file_exists($path)) {
return unlink($path);
}
return false;
}
}
/**
* @notes 获取无前缀数据表名
* @param $tableName
* @return mixed|string
* @author 段誉
* @date 2022/12/12 15:23
*/
function get_no_prefix_table_name($tableName)
{
$tablePrefix = config('database.connections.mysql.prefix');
$prefixIndex = strpos($tableName, $tablePrefix);
if ($prefixIndex !== 0 || $prefixIndex === false) {
return $tableName;
}
$tableName = substr_replace($tableName, '', 0, strlen($tablePrefix));
return trim($tableName);
}

View File

@ -30,18 +30,22 @@
"webman/think-orm": "^1.0",
"vlucas/phpdotenv": "^5.4",
"psr/container": "^1.1.1",
"webman/think-cache": "^1.0",
"ext-json": "*",
"phpoffice/phpspreadsheet": "^1.19",
"aliyuncs/oss-sdk-php": "^2.6",
"tencentcloud/tencentcloud-sdk-php": "^3.0",
"webman/console": "^1.2.12",
"qiniu/php-sdk": "7.4",
"qcloud/cos-sdk-v5": "^2.6",
"dragonmantank/cron-expression": "^3.3",
"tinywan/storage": "^0.3.4",
"webman/log": "^1.1",
"taoser/webman-validate": "^1.7"
"taoser/webman-validate": "^1.7",
"php-di/php-di": "^6",
"doctrine/annotations": "^1.14",
"illuminate/redis": "^10.22",
"symfony/cache": "^5.4",
"max/var-dumper": "^0.1.1",
"textalk/websocket": "^1.5"
},
"suggest": {
"ext-event": "For better performance. "

3088
composer.lock generated

File diff suppressed because it is too large Load Diff

BIN
composer.phar Executable file

Binary file not shown.

View File

@ -16,5 +16,4 @@ return [
support\bootstrap\Session::class,
support\bootstrap\LaravelDb::class,
Webman\ThinkOrm\ThinkOrm::class,
Webman\ThinkCache\ThinkCache::class,
];

View File

@ -1,15 +1,24 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return [];
use function DI\env;
return [
// 默认数据库
'default' => 'mysql',
// 各种数据库配置
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST'),
'port' => 3306,
'database' => env('DB_DATABASE'),
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'unix_socket' => '',
'prefix' => 'la_',
'strict' => true,
'engine' => null,
],
],
];

View File

@ -0,0 +1,12 @@
<?php
return [
'enable' => true,
'exception' => [
// 是否记录异常到日志
'enable' => true,
// 不会记录到日志的异常类
'dontReport' => [
support\exception\BusinessException::class
]
]
];

View File

@ -0,0 +1,21 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use Webman\Log\Middleware;
return [
'' => [
Middleware::class
]
];

View File

@ -1,22 +0,0 @@
<?php
return [
'default' => 'redis',
'stores' => [
'file' => [
'type' => 'File',
// 缓存保存目录
'path' => runtime_path() . '/cache/',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
],
'redis' => [
'type' => 'redis',
'host' => '127.0.0.1',
'port' => 6379,
'prefix' => '',
'expire' => 0,
],
],
];

View File

@ -23,7 +23,7 @@ return [
// 断线重连
'break_reconnect' => true,
// 关闭SQL监听日志
'trigger_sql' => false,
'trigger_sql' => true,
// 自定义分页类
'bootstrap' => ''
],

View File

@ -0,0 +1,147 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 核心中文语言包
return [
// 系统错误提示
'Undefined variable' => '未定义变量',
'Undefined index' => '未定义数组索引',
'Undefined offset' => '未定义数组下标',
'Parse error' => '语法解析错误',
'Type error' => '类型错误',
'Fatal error' => '致命错误',
'syntax error' => '语法错误',
// 框架核心错误提示
'dispatch type not support' => '不支持的调度类型',
'method param miss' => '方法参数错误',
'method not exists' => '方法不存在',
'function not exists' => '函数不存在',
'app not exists' => '应用不存在',
'controller not exists' => '控制器不存在',
'class not exists' => '类不存在',
'property not exists' => '类的属性不存在',
'template not exists' => '模板文件不存在',
'illegal controller name' => '非法的控制器名称',
'illegal action name' => '非法的操作名称',
'url suffix deny' => '禁止的URL后缀访问',
'Undefined cache config' => '缓存配置未定义',
'Route Not Found' => '当前访问路由未定义或不匹配',
'Undefined db config' => '数据库配置未定义',
'Undefined log config' => '日志配置未定义',
'Undefined db type' => '未定义数据库类型',
'variable type error' => '变量类型错误',
'PSR-4 error' => 'PSR-4 规范错误',
'not support type' => '不支持的分页索引字段类型',
'not support total' => '简洁模式下不能获取数据总数',
'not support last' => '简洁模式下不能获取最后一页',
'error session handler' => '错误的SESSION处理器类',
'not allow php tag' => '模板不允许使用PHP语法',
'not support' => '不支持',
'database config error' => '数据库配置信息错误',
'redisd master' => 'Redisd 主服务器错误',
'redisd slave' => 'Redisd 从服务器错误',
'must run at sae' => '必须在SAE运行',
'memcache init error' => '未开通Memcache服务请在SAE管理平台初始化Memcache服务',
'KVDB init error' => '没有初始化KVDB请在SAE管理平台初始化KVDB服务',
'fields not exists' => '数据表字段不存在',
'where express error' => '查询表达式错误',
'no data to update' => '没有任何数据需要更新',
'miss data to insert' => '缺少需要写入的数据',
'miss complex primary data' => '缺少复合主键数据',
'miss update condition' => '缺少更新条件',
'model data Not Found' => '模型数据不存在',
'table data not Found' => '表数据不存在',
'delete without condition' => '没有条件不会执行删除操作',
'miss relation data' => '缺少关联表数据',
'tag attr must' => '模板标签属性必须',
'tag error' => '模板标签错误',
'cache write error' => '缓存写入失败',
'sae mc write error' => 'SAE mc 写入错误',
'route name not exists' => '路由标识不存在(或参数不够)',
'invalid request' => '非法请求',
'bind attr has exists' => '模型的属性已经存在',
'relation data not exists' => '关联数据不存在',
'relation not support' => '关联不支持',
'chunk not support order' => 'Chunk不支持调用order方法',
'route pattern error' => '路由变量规则定义错误',
'route behavior will not support' => '路由行为废弃(使用中间件替代)',
'closure not support cache(true)' => '使用闭包查询不支持cache(true)请指定缓存Key',
// 上传错误信息
'unknown upload error' => '未知上传错误!',
'file write error' => '文件写入失败!',
'upload temp dir not found' => '找不到临时文件夹!',
'no file to uploaded' => '没有文件被上传!',
'only the portion of file is uploaded' => '文件只有部分被上传!',
'upload File size exceeds the maximum value' => '上传文件大小超过了最大值!',
'upload write error' => '文件上传保存错误!',
'has the same filename: {:filename}' => '存在同名文件:{:filename}',
'upload illegal files' => '非法上传文件',
'illegal image files' => '非法图片文件',
'extensions to upload is not allowed' => '上传文件后缀不允许',
'mimetype to upload is not allowed' => '上传文件MIME类型不允许',
'filesize not match' => '上传文件大小不符!',
'directory {:path} creation failed' => '目录 {:path} 创建失败!',
'The middleware must return Response instance' => '中间件方法必须返回Response对象实例',
'The queue was exhausted, with no response returned' => '中间件队列为空',
// Validate Error Message
':attribute require' => ':attribute不能为空',
':attribute must' => ':attribute必须',
':attribute must be numeric' => ':attribute必须是数字',
':attribute must be integer' => ':attribute必须是整数',
':attribute must be float' => ':attribute必须是浮点数',
':attribute must be bool' => ':attribute必须是布尔值',
':attribute not a valid email address' => ':attribute格式不符',
':attribute not a valid mobile' => ':attribute格式不符',
':attribute must be a array' => ':attribute必须是数组',
':attribute must be yes,on or 1' => ':attribute必须是yes、on或者1',
':attribute not a valid datetime' => ':attribute不是一个有效的日期或时间格式',
':attribute not a valid file' => ':attribute不是有效的上传文件',
':attribute not a valid image' => ':attribute不是有效的图像文件',
':attribute must be alpha' => ':attribute只能是字母',
':attribute must be alpha-numeric' => ':attribute只能是字母和数字',
':attribute must be alpha-numeric, dash, underscore' => ':attribute只能是字母、数字和下划线_及破折号-',
':attribute not a valid domain or ip' => ':attribute不是有效的域名或者IP',
':attribute must be chinese' => ':attribute只能是汉字',
':attribute must be chinese or alpha' => ':attribute只能是汉字、字母',
':attribute must be chinese,alpha-numeric' => ':attribute只能是汉字、字母和数字',
':attribute must be chinese,alpha-numeric,underscore, dash' => ':attribute只能是汉字、字母、数字和下划线_及破折号-',
':attribute not a valid url' => ':attribute不是有效的URL地址',
':attribute not a valid ip' => ':attribute不是有效的IP地址',
':attribute must be dateFormat of :rule' => ':attribute必须使用日期格式 :rule',
':attribute must be in :rule' => ':attribute必须在 :rule 范围内',
':attribute be notin :rule' => ':attribute不能在 :rule 范围内',
':attribute must between :1 - :2' => ':attribute只能在 :1 - :2 之间',
':attribute not between :1 - :2' => ':attribute不能在 :1 - :2 之间',
'size of :attribute must be :rule' => ':attribute长度不符合要求 :rule',
'max size of :attribute must be :rule' => ':attribute长度不能超过 :rule',
'min size of :attribute must be :rule' => ':attribute长度不能小于 :rule',
':attribute cannot be less than :rule' => ':attribute日期不能小于 :rule',
':attribute cannot exceed :rule' => ':attribute日期不能超过 :rule',
':attribute not within :rule' => '不在有效期内 :rule',
'access IP is not allowed' => '不允许的IP访问',
'access IP denied' => '禁止的IP访问',
':attribute out of accord with :2' => ':attribute和确认字段:2不一致',
':attribute cannot be same with :2' => ':attribute和比较字段:2不能相同',
':attribute must greater than or equal :rule' => ':attribute必须大于等于 :rule',
':attribute must greater than :rule' => ':attribute必须大于 :rule',
':attribute must less than or equal :rule' => ':attribute必须小于等于 :rule',
':attribute must less than :rule' => ':attribute必须小于 :rule',
':attribute must equal :rule' => ':attribute必须等于 :rule',
':attribute has exists' => ':attribute已存在',
':attribute not conform to the rules' => ':attribute不符合指定规则',
'invalid Request method' => '无效的请求类型',
'invalid token' => '令牌数据无效',
'not conform to the rules' => '规则错误',
'record has update' => '记录已经被更新了',
];

View File

@ -0,0 +1,147 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 核心中文语言包
return [
// 系统错误提示
'Undefined variable' => '未定义变量',
'Undefined index' => '未定义数组索引',
'Undefined offset' => '未定义数组下标',
'Parse error' => '语法解析错误',
'Type error' => '类型错误',
'Fatal error' => '致命错误',
'syntax error' => '语法错误',
// 框架核心错误提示
'dispatch type not support' => '不支持的调度类型',
'method param miss' => '方法参数错误',
'method not exists' => '方法不存在',
'function not exists' => '函数不存在',
'app not exists' => '应用不存在',
'controller not exists' => '控制器不存在',
'class not exists' => '类不存在',
'property not exists' => '类的属性不存在',
'template not exists' => '模板文件不存在',
'illegal controller name' => '非法的控制器名称',
'illegal action name' => '非法的操作名称',
'url suffix deny' => '禁止的URL后缀访问',
'Undefined cache config' => '缓存配置未定义',
'Route Not Found' => '当前访问路由未定义或不匹配',
'Undefined db config' => '数据库配置未定义',
'Undefined log config' => '日志配置未定义',
'Undefined db type' => '未定义数据库类型',
'variable type error' => '变量类型错误',
'PSR-4 error' => 'PSR-4 规范错误',
'not support type' => '不支持的分页索引字段类型',
'not support total' => '简洁模式下不能获取数据总数',
'not support last' => '简洁模式下不能获取最后一页',
'error session handler' => '错误的SESSION处理器类',
'not allow php tag' => '模板不允许使用PHP语法',
'not support' => '不支持',
'database config error' => '数据库配置信息错误',
'redisd master' => 'Redisd 主服务器错误',
'redisd slave' => 'Redisd 从服务器错误',
'must run at sae' => '必须在SAE运行',
'memcache init error' => '未开通Memcache服务请在SAE管理平台初始化Memcache服务',
'KVDB init error' => '没有初始化KVDB请在SAE管理平台初始化KVDB服务',
'fields not exists' => '数据表字段不存在',
'where express error' => '查询表达式错误',
'no data to update' => '没有任何数据需要更新',
'miss data to insert' => '缺少需要写入的数据',
'miss complex primary data' => '缺少复合主键数据',
'miss update condition' => '缺少更新条件',
'model data Not Found' => '模型数据不存在',
'table data not Found' => '表数据不存在',
'delete without condition' => '没有条件不会执行删除操作',
'miss relation data' => '缺少关联表数据',
'tag attr must' => '模板标签属性必须',
'tag error' => '模板标签错误',
'cache write error' => '缓存写入失败',
'sae mc write error' => 'SAE mc 写入错误',
'route name not exists' => '路由标识不存在(或参数不够)',
'invalid request' => '非法请求',
'bind attr has exists' => '模型的属性已经存在',
'relation data not exists' => '关联数据不存在',
'relation not support' => '关联不支持',
'chunk not support order' => 'Chunk不支持调用order方法',
'route pattern error' => '路由变量规则定义错误',
'route behavior will not support' => '路由行为废弃(使用中间件替代)',
'closure not support cache(true)' => '使用闭包查询不支持cache(true)请指定缓存Key',
// 上传错误信息
'unknown upload error' => '未知上传错误!',
'file write error' => '文件写入失败!',
'upload temp dir not found' => '找不到临时文件夹!',
'no file to uploaded' => '没有文件被上传!',
'only the portion of file is uploaded' => '文件只有部分被上传!',
'upload File size exceeds the maximum value' => '上传文件大小超过了最大值!',
'upload write error' => '文件上传保存错误!',
'has the same filename: {:filename}' => '存在同名文件:{:filename}',
'upload illegal files' => '非法上传文件',
'illegal image files' => '非法图片文件',
'extensions to upload is not allowed' => '上传文件后缀不允许',
'mimetype to upload is not allowed' => '上传文件MIME类型不允许',
'filesize not match' => '上传文件大小不符!',
'directory {:path} creation failed' => '目录 {:path} 创建失败!',
'The middleware must return Response instance' => '中间件方法必须返回Response对象实例',
'The queue was exhausted, with no response returned' => '中间件队列为空',
// Validate Error Message
':attribute require' => ':attribute不能为空',
':attribute must' => ':attribute必须',
':attribute must be numeric' => ':attribute必须是数字',
':attribute must be integer' => ':attribute必须是整数',
':attribute must be float' => ':attribute必须是浮点数',
':attribute must be bool' => ':attribute必须是布尔值',
':attribute not a valid email address' => ':attribute格式不符',
':attribute not a valid mobile' => ':attribute格式不符',
':attribute must be a array' => ':attribute必须是数组',
':attribute must be yes,on or 1' => ':attribute必须是yes、on或者1',
':attribute not a valid datetime' => ':attribute不是一个有效的日期或时间格式',
':attribute not a valid file' => ':attribute不是有效的上传文件',
':attribute not a valid image' => ':attribute不是有效的图像文件',
':attribute must be alpha' => ':attribute只能是字母',
':attribute must be alpha-numeric' => ':attribute只能是字母和数字',
':attribute must be alpha-numeric, dash, underscore' => ':attribute只能是字母、数字和下划线_及破折号-',
':attribute not a valid domain or ip' => ':attribute不是有效的域名或者IP',
':attribute must be chinese' => ':attribute只能是汉字',
':attribute must be chinese or alpha' => ':attribute只能是汉字、字母',
':attribute must be chinese,alpha-numeric' => ':attribute只能是汉字、字母和数字',
':attribute must be chinese,alpha-numeric,underscore, dash' => ':attribute只能是汉字、字母、数字和下划线_及破折号-',
':attribute not a valid url' => ':attribute不是有效的URL地址',
':attribute not a valid ip' => ':attribute不是有效的IP地址',
':attribute must be dateFormat of :rule' => ':attribute必须使用日期格式 :rule',
':attribute must be in :rule' => ':attribute必须在 :rule 范围内',
':attribute be notin :rule' => ':attribute不能在 :rule 范围内',
':attribute must between :1 - :2' => ':attribute只能在 :1 - :2 之间',
':attribute not between :1 - :2' => ':attribute不能在 :1 - :2 之间',
'size of :attribute must be :rule' => ':attribute长度不符合要求 :rule',
'max size of :attribute must be :rule' => ':attribute长度不能超过 :rule',
'min size of :attribute must be :rule' => ':attribute长度不能小于 :rule',
':attribute cannot be less than :rule' => ':attribute日期不能小于 :rule',
':attribute cannot exceed :rule' => ':attribute日期不能超过 :rule',
':attribute not within :rule' => '不在有效期内 :rule',
'access IP is not allowed' => '不允许的IP访问',
'access IP denied' => '禁止的IP访问',
':attribute out of accord with :2' => ':attribute和确认字段:2不一致',
':attribute cannot be same with :2' => ':attribute和比较字段:2不能相同',
':attribute must greater than or equal :rule' => ':attribute必须大于等于 :rule',
':attribute must greater than :rule' => ':attribute必须大于 :rule',
':attribute must less than or equal :rule' => ':attribute必须小于等于 :rule',
':attribute must less than :rule' => ':attribute必须小于 :rule',
':attribute must equal :rule' => ':attribute必须等于 :rule',
':attribute has exists' => ':attribute已存在',
':attribute not conform to the rules' => ':attribute不符合指定规则',
'invalid Request method' => '无效的请求类型',
'invalid token' => '令牌数据无效',
'not conform to the rules' => '规则错误',
'record has update' => '记录已经被更新了',
];

View File

@ -16,8 +16,8 @@ use Dotenv\Dotenv;
use support\Log;
use Webman\Bootstrap;
use Webman\Config;
use Webman\Route;
use Webman\Middleware;
use Webman\Route;
use Webman\Util;
$worker = $worker ?? null;
@ -29,18 +29,18 @@ set_error_handler(function ($level, $message, $file = '', $line = 0) {
});
if ($worker) {
register_shutdown_function(function ($start_time) {
if (time() - $start_time <= 1) {
register_shutdown_function(function ($startTime) {
if (time() - $startTime <= 0.1) {
sleep(1);
}
}, time());
}
if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
Dotenv::createUnsafeImmutable(base_path())->load();
if (class_exists('Dotenv\Dotenv') && file_exists(base_path(false) . '/.env')) {
if (method_exists('Dotenv\Dotenv', 'createUnsafeMutable')) {
Dotenv::createUnsafeMutable(base_path(false))->load();
} else {
Dotenv::createMutable(base_path())->load();
Dotenv::createMutable(base_path(false))->load();
}
}
@ -67,30 +67,30 @@ foreach (config('plugin', []) as $firm => $projects) {
}
}
Middleware::load(config('middleware', []), '');
Middleware::load(config('middleware', []));
foreach (config('plugin', []) as $firm => $projects) {
foreach ($projects as $name => $project) {
if (!is_array($project) || $name === 'static') {
continue;
}
Middleware::load($project['middleware'] ?? [], '');
Middleware::load($project['middleware'] ?? []);
}
Middleware::load($projects['middleware'] ?? [], $firm);
if ($static_middlewares = config("plugin.$firm.static.middleware")) {
Middleware::load(['__static__' => $static_middlewares], $firm);
if ($staticMiddlewares = config("plugin.$firm.static.middleware")) {
Middleware::load(['__static__' => $staticMiddlewares], $firm);
}
}
Middleware::load(['__static__' => config('static.middleware', [])], '');
Middleware::load(['__static__' => config('static.middleware', [])]);
foreach (config('bootstrap', []) as $class_name) {
if (!class_exists($class_name)) {
$log = "Warning: Class $class_name setting in config/bootstrap.php not found\r\n";
foreach (config('bootstrap', []) as $className) {
if (!class_exists($className)) {
$log = "Warning: Class $className setting in config/bootstrap.php not found\r\n";
echo $log;
Log::error($log);
continue;
}
/** @var Bootstrap $class_name */
$class_name::start($worker);
/** @var Bootstrap $className */
$className::start($worker);
}
foreach (config('plugin', []) as $firm => $projects) {
@ -98,26 +98,27 @@ foreach (config('plugin', []) as $firm => $projects) {
if (!is_array($project)) {
continue;
}
foreach ($project['bootstrap'] ?? [] as $class_name) {
if (!class_exists($class_name)) {
$log = "Warning: Class $class_name setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
foreach ($project['bootstrap'] ?? [] as $className) {
if (!class_exists($className)) {
$log = "Warning: Class $className setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
echo $log;
Log::error($log);
continue;
}
/** @var Bootstrap $class_name */
$class_name::start($worker);
/** @var Bootstrap $className */
$className::start($worker);
}
}
foreach ($projects['bootstrap'] ?? [] as $class_name) {
if (!class_exists($class_name)) {
$log = "Warning: Class $class_name setting in plugin/$firm/config/bootstrap.php not found\r\n";
foreach ($projects['bootstrap'] ?? [] as $className) {
/** @var string $className */
if (!class_exists($className)) {
$log = "Warning: Class $className setting in plugin/$firm/config/bootstrap.php not found\r\n";
echo $log;
Log::error($log);
continue;
}
/** @var Bootstrap $class_name */
$class_name::start($worker);
/** @var Bootstrap $className */
$className::start($worker);
}
}

View File

@ -17,17 +17,17 @@ use support\Container;
use support\Request;
use support\Response;
use support\Translation;
use support\view\Raw;
use support\view\Blade;
use support\view\Raw;
use support\view\ThinkPHP;
use support\view\Twig;
use Workerman\Worker;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Webman\App;
use Webman\Config;
use Webman\Route;
// Webman version
const WEBMAN_VERSION = '1.4';
use Workerman\Worker;
// Project base path
define('BASE_PATH', dirname(__DIR__));
@ -39,11 +39,11 @@ define('BASE_PATH', dirname(__DIR__));
*/
function run_path(string $path = ''): string
{
static $run_path = '';
if (!$run_path) {
$run_path = \is_phar() ? \dirname(\Phar::running(false)) : BASE_PATH;
static $runPath = '';
if (!$runPath) {
$runPath = is_phar() ? dirname(Phar::running(false)) : BASE_PATH;
}
return \path_combine($run_path, $path);
return path_combine($runPath, $path);
}
/**
@ -54,9 +54,9 @@ function run_path(string $path = ''): string
function base_path($path = ''): string
{
if (false === $path) {
return \run_path();
return run_path();
}
return \path_combine(BASE_PATH, $path);
return path_combine(BASE_PATH, $path);
}
/**
@ -66,7 +66,7 @@ function base_path($path = ''): string
*/
function app_path(string $path = ''): string
{
return \path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
}
/**
@ -76,11 +76,11 @@ function app_path(string $path = ''): string
*/
function public_path(string $path = ''): string
{
static $public_path = '';
if (!$public_path) {
$public_path = \config('app.public_path') ? : \run_path('public');
static $publicPath = '';
if (!$publicPath) {
$publicPath = \config('app.public_path') ?: run_path('public');
}
return \path_combine($public_path, $path);
return path_combine($publicPath, $path);
}
/**
@ -90,7 +90,7 @@ function public_path(string $path = ''): string
*/
function config_path(string $path = ''): string
{
return \path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
}
/**
@ -100,11 +100,11 @@ function config_path(string $path = ''): string
*/
function runtime_path(string $path = ''): string
{
static $runtime_path = '';
if (!$runtime_path) {
$runtime_path = \config('app.runtime_path') ? : \run_path('runtime');
static $runtimePath = '';
if (!$runtimePath) {
$runtimePath = \config('app.runtime_path') ?: run_path('runtime');
}
return \path_combine($runtime_path, $path);
return path_combine($runtimePath, $path);
}
/**
@ -138,7 +138,7 @@ function response(string $body = '', int $status = 200, array $headers = []): Re
*/
function json($data, int $options = JSON_UNESCAPED_UNICODE): Response
{
return new Response(200, ['Content-Type' => 'application/json'], \json_encode($data, $options));
return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
}
/**
@ -157,15 +157,15 @@ function xml($xml): Response
/**
* Jsonp response
* @param $data
* @param string $callback_name
* @param string $callbackName
* @return Response
*/
function jsonp($data, string $callback_name = 'callback'): Response
function jsonp($data, string $callbackName = 'callback'): Response
{
if (!\is_scalar($data) && null !== $data) {
$data = \json_encode($data);
if (!is_scalar($data) && null !== $data) {
$data = json_encode($data);
}
return new Response(200, [], "$callback_name($data)");
return new Response(200, [], "$callbackName($data)");
}
/**
@ -189,14 +189,15 @@ function redirect(string $location, int $status = 302, array $headers = []): Res
* @param string $template
* @param array $vars
* @param string|null $app
* @param string|null $plugin
* @return Response
*/
function view(string $template, array $vars = [], string $app = null): Response
function view(string $template, array $vars = [], string $app = null, string $plugin = null): Response
{
$request = \request();
$plugin = $request->plugin ?? '';
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
return new Response(200, [], $handler::render($template, $vars, $app));
return new Response(200, [], $handler::render($template, $vars, $app, $plugin));
}
/**
@ -242,6 +243,9 @@ function think_view(string $template, array $vars = [], string $app = null): Res
* @param array $vars
* @param string|null $app
* @return Response
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
function twig_view(string $template, array $vars = [], string $app = null): Response
{
@ -285,8 +289,8 @@ function route(string $name, ...$parameters): string
return $route->url();
}
if (\is_array(\current($parameters))) {
$parameters = \current($parameters);
if (is_array(current($parameters))) {
$parameters = current($parameters);
}
return $route->url($parameters);
@ -304,14 +308,14 @@ function session($key = null, $default = null)
if (null === $key) {
return $session;
}
if (\is_array($key)) {
if (is_array($key)) {
$session->put($key);
return null;
}
if (\strpos($key, '.')) {
$key_array = \explode('.', $key);
if (strpos($key, '.')) {
$keyArray = explode('.', $key);
$value = $session->all();
foreach ($key_array as $index) {
foreach ($keyArray as $index) {
if (!isset($value[$index])) {
return $default;
}
@ -339,7 +343,7 @@ function trans(string $id, array $parameters = [], string $domain = null, string
/**
* Locale
* @param string|null $locale
* @return void
* @return string
*/
function locale(string $locale = null): string
{
@ -347,6 +351,7 @@ function locale(string $locale = null): string
return Translation::getLocale();
}
Translation::setLocale($locale);
return $locale;
}
/**
@ -355,7 +360,7 @@ function locale(string $locale = null): string
*/
function not_found(): Response
{
return new Response(404, [], \file_get_contents(public_path() . '/404.html'));
return new Response(404, [], file_get_contents(public_path() . '/404.html'));
}
/**
@ -367,18 +372,18 @@ function not_found(): Response
*/
function copy_dir(string $source, string $dest, bool $overwrite = false)
{
if (\is_dir($source)) {
if (is_dir($source)) {
if (!is_dir($dest)) {
\mkdir($dest);
mkdir($dest);
}
$files = \scandir($source);
$files = scandir($source);
foreach ($files as $file) {
if ($file !== "." && $file !== "..") {
\copy_dir("$source/$file", "$dest/$file");
copy_dir("$source/$file", "$dest/$file");
}
}
} else if (\file_exists($source) && ($overwrite || !\file_exists($dest))) {
\copy($source, $dest);
} else if (file_exists($source) && ($overwrite || !file_exists($dest))) {
copy($source, $dest);
}
}
@ -389,14 +394,14 @@ function copy_dir(string $source, string $dest, bool $overwrite = false)
*/
function remove_dir(string $dir): bool
{
if (\is_link($dir) || \is_file($dir)) {
return \unlink($dir);
if (is_link($dir) || is_file($dir)) {
return unlink($dir);
}
$files = \array_diff(\scandir($dir), array('.', '..'));
$files = array_diff(scandir($dir), array('.', '..'));
foreach ($files as $file) {
(\is_dir("$dir/$file") && !\is_link($dir)) ? \remove_dir("$dir/$file") : \unlink("$dir/$file");
(is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file");
}
return \rmdir($dir);
return rmdir($dir);
}
/**
@ -406,7 +411,7 @@ function remove_dir(string $dir): bool
*/
function worker_bind($worker, $class)
{
$callback_map = [
$callbackMap = [
'onConnect',
'onMessage',
'onClose',
@ -414,28 +419,29 @@ function worker_bind($worker, $class)
'onBufferFull',
'onBufferDrain',
'onWorkerStop',
'onWebSocketConnect'
'onWebSocketConnect',
'onWorkerReload'
];
foreach ($callback_map as $name) {
if (\method_exists($class, $name)) {
foreach ($callbackMap as $name) {
if (method_exists($class, $name)) {
$worker->$name = [$class, $name];
}
}
if (\method_exists($class, 'onWorkerStart')) {
\call_user_func([$class, 'onWorkerStart'], $worker);
if (method_exists($class, 'onWorkerStart')) {
call_user_func([$class, 'onWorkerStart'], $worker);
}
}
/**
* Start worker
* @param $process_name
* @param $processName
* @param $config
* @return void
*/
function worker_start($process_name, $config)
function worker_start($processName, $config)
{
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
$property_map = [
$propertyMap = [
'count',
'user',
'group',
@ -444,53 +450,38 @@ function worker_start($process_name, $config)
'transport',
'protocol',
];
$worker->name = $process_name;
foreach ($property_map as $property) {
$worker->name = $processName;
foreach ($propertyMap as $property) {
if (isset($config[$property])) {
$worker->$property = $config[$property];
}
}
$worker->onWorkerStart = function ($worker) use ($config) {
require_once \base_path() . '/support/bootstrap.php';
foreach ($config['services'] ?? [] as $server) {
if (!\class_exists($server['handler'])) {
echo "process error: class {$server['handler']} not exists\r\n";
continue;
}
$listen = new Worker($server['listen'] ?? null, $server['context'] ?? []);
if (isset($server['listen'])) {
echo "listen: {$server['listen']}\n";
}
$instance = Container::make($server['handler'], $server['constructor'] ?? []);
\worker_bind($listen, $instance);
$listen->listen();
}
require_once base_path('/support/bootstrap.php');
if (isset($config['handler'])) {
if (!\class_exists($config['handler'])) {
if (!class_exists($config['handler'])) {
echo "process error: class {$config['handler']} not exists\r\n";
return;
}
$instance = Container::make($config['handler'], $config['constructor'] ?? []);
\worker_bind($worker, $instance);
worker_bind($worker, $instance);
}
};
}
/**
* Get realpath
* @param string $file_path
* @param string $filePath
* @return string
*/
function get_realpath(string $file_path): string
function get_realpath(string $filePath): string
{
if (\strpos($file_path, 'phar://') === 0) {
return $file_path;
if (strpos($filePath, 'phar://') === 0) {
return $filePath;
} else {
return \realpath($file_path);
return realpath($filePath);
}
}
@ -500,7 +491,7 @@ function get_realpath(string $file_path): string
*/
function is_phar(): bool
{
return \class_exists(\Phar::class, false) && Phar::running();
return class_exists(Phar::class, false) && Phar::running();
}
/**
@ -510,15 +501,15 @@ function is_phar(): bool
function cpu_count(): int
{
// Windows does not support the number of processes setting.
if (\DIRECTORY_SEPARATOR === '\\') {
if (DIRECTORY_SEPARATOR === '\\') {
return 1;
}
$count = 4;
if (\is_callable('shell_exec')) {
if (\strtolower(PHP_OS) === 'darwin') {
$count = (int)\shell_exec('sysctl -n machdep.cpu.core_count');
if (is_callable('shell_exec')) {
if (strtolower(PHP_OS) === 'darwin') {
$count = (int)shell_exec('sysctl -n machdep.cpu.core_count');
} else {
$count = (int)\shell_exec('nproc');
$count = (int)shell_exec('nproc');
}
}
return $count > 0 ? $count : 4;

View File

@ -4,9 +4,9 @@
*/
require_once __DIR__ . '/vendor/autoload.php';
use Dotenv\Dotenv;
use process\Monitor;
use support\App;
use Dotenv\Dotenv;
use Workerman\Worker;
ini_set('display_errors', 'on');
@ -22,20 +22,20 @@ if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
App::loadAllConfig(['route']);
$error_reporting = config('app.error_reporting');
if (isset($error_reporting)) {
error_reporting($error_reporting);
$errorReporting = config('app.error_reporting');
if (isset($errorReporting)) {
error_reporting($errorReporting);
}
$runtime_process_path = runtime_path() . DIRECTORY_SEPARATOR . '/windows';
if (!is_dir($runtime_process_path)) {
mkdir($runtime_process_path);
$runtimeProcessPath = runtime_path() . DIRECTORY_SEPARATOR . '/windows';
if (!is_dir($runtimeProcessPath)) {
mkdir($runtimeProcessPath);
}
$process_files = [
$processFiles = [
__DIR__ . DIRECTORY_SEPARATOR . 'start.php'
];
foreach (config('process', []) as $process_name => $config) {
$process_files[] = write_process_file($runtime_process_path, $process_name, '');
foreach (config('process', []) as $processName => $config) {
$processFiles[] = write_process_file($runtimeProcessPath, $processName, '');
}
foreach (config('plugin', []) as $firm => $projects) {
@ -43,20 +43,20 @@ foreach (config('plugin', []) as $firm => $projects) {
if (!is_array($project)) {
continue;
}
foreach ($project['process'] ?? [] as $process_name => $config) {
$process_files[] = write_process_file($runtime_process_path, $process_name, "$firm.$name");
foreach ($project['process'] ?? [] as $processName => $config) {
$processFiles[] = write_process_file($runtimeProcessPath, $processName, "$firm.$name");
}
}
foreach ($projects['process'] ?? [] as $process_name => $config) {
$process_files[] = write_process_file($runtime_process_path, $process_name, $firm);
foreach ($projects['process'] ?? [] as $processName => $config) {
$processFiles[] = write_process_file($runtimeProcessPath, $processName, $firm);
}
}
function write_process_file($runtime_process_path, $process_name, $firm)
function write_process_file($runtimeProcessPath, $processName, $firm): string
{
$process_param = $firm ? "plugin.$firm.$process_name" : $process_name;
$config_param = $firm ? "config('plugin.$firm.process')['$process_name']" : "config('process')['$process_name']";
$file_content = <<<EOF
$processParam = $firm ? "plugin.$firm.$processName" : $processName;
$configParam = $firm ? "config('plugin.$firm.process')['$processName']" : "config('process')['$processName']";
$fileContent = <<<EOF
<?php
require_once __DIR__ . '/../../vendor/autoload.php';
@ -73,7 +73,7 @@ if (is_callable('opcache_reset')) {
App::loadAllConfig(['route']);
worker_start('$process_param', $config_param);
worker_start('$processParam', $configParam);
if (DIRECTORY_SEPARATOR != "/") {
Worker::\$logFile = config('server')['log_file'] ?? Worker::\$logFile;
@ -82,27 +82,27 @@ if (DIRECTORY_SEPARATOR != "/") {
Worker::runAll();
EOF;
$process_file = $runtime_process_path . DIRECTORY_SEPARATOR . "start_$process_param.php";
file_put_contents($process_file, $file_content);
return $process_file;
$processFile = $runtimeProcessPath . DIRECTORY_SEPARATOR . "start_$processParam.php";
file_put_contents($processFile, $fileContent);
return $processFile;
}
if ($monitor_config = config('process.monitor.constructor')) {
$monitor = new Monitor(...array_values($monitor_config));
if ($monitorConfig = config('process.monitor.constructor')) {
$monitor = new Monitor(...array_values($monitorConfig));
}
function popen_processes($process_files)
function popen_processes($processFiles)
{
$cmd = "php " . implode(' ', $process_files);
$cmd = '"' . PHP_BINARY . '" ' . implode(' ', $processFiles);
$descriptorspec = [STDIN, STDOUT, STDOUT];
$resource = proc_open($cmd, $descriptorspec, $pipes);
$resource = proc_open($cmd, $descriptorspec, $pipes, null, null, ['bypass_shell' => true]);
if (!$resource) {
exit("Can not execute $cmd\r\n");
}
return $resource;
}
$resource = popen_processes($process_files);
$resource = popen_processes($processFiles);
echo "\r\n";
while (1) {
sleep(1);
@ -111,6 +111,6 @@ while (1) {
$pid = $status['pid'];
shell_exec("taskkill /F /T /PID $pid");
proc_close($resource);
$resource = popen_processes($process_files);
$resource = popen_processes($processFiles);
}
}