GeneratorLogic.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | likeadmin快速开发前后端分离管理后台(PHP版)
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | 开源版本可自由商用,可去除界面版权logo
  7. // | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
  8. // | github下载:https://github.com/likeshop-github/likeadmin
  9. // | 访问官网:https://www.likeadmin.cn
  10. // | likeadmin团队 版权所有 拥有最终解释权
  11. // +----------------------------------------------------------------------
  12. // | author: likeadminTeam
  13. // +----------------------------------------------------------------------
  14. namespace app\adminapi\logic\tools;
  15. use app\common\enum\GeneratorEnum;
  16. use app\common\logic\BaseLogic;
  17. use app\common\model\tools\GenerateColumn;
  18. use app\common\model\tools\GenerateTable;
  19. use app\common\service\generator\GenerateService;
  20. use think\facade\Db;
  21. /**
  22. * 生成器逻辑
  23. * Class GeneratorLogic
  24. * @package app\adminapi\logic\tools
  25. */
  26. class GeneratorLogic extends BaseLogic
  27. {
  28. /**
  29. * @notes 表详情
  30. * @param $params
  31. * @return array
  32. * @author 段誉
  33. * @date 2022/6/20 10:45
  34. */
  35. public static function getTableDetail($params): array
  36. {
  37. $detail = GenerateTable::with('table_column')
  38. ->findOrEmpty((int)$params['id'])
  39. ->toArray();
  40. $options = self::formatConfigByTableData($detail);
  41. $detail['menu'] = $options['menu'];
  42. $detail['delete'] = $options['delete'];
  43. $detail['tree'] = $options['tree'];
  44. $detail['relations'] = $options['relations'];
  45. return $detail;
  46. }
  47. /**
  48. * @notes 选择数据表
  49. * @param $params
  50. * @param $adminId
  51. * @return bool
  52. * @author 段誉
  53. * @date 2022/6/20 10:44
  54. */
  55. public static function selectTable($params, $adminId)
  56. {
  57. Db::startTrans();
  58. try {
  59. foreach ($params['table'] as $item) {
  60. // 添加主表基础信息
  61. $generateTable = self::initTable($item, $adminId);
  62. // 获取数据表字段信息
  63. $column = self::getTableColumn($item['name']);
  64. // 添加表字段信息
  65. self::initTableColumn($column, $generateTable['id']);
  66. }
  67. Db::commit();
  68. return true;
  69. } catch (\Exception $e) {
  70. Db::rollback();
  71. self::$error = $e->getMessage();
  72. return false;
  73. }
  74. }
  75. /**
  76. * @notes 编辑表信息
  77. * @param $params
  78. * @return bool
  79. * @author 段誉
  80. * @date 2022/6/20 10:44
  81. */
  82. public static function editTable($params)
  83. {
  84. Db::startTrans();
  85. try {
  86. // 格式化配置
  87. $options = self::formatConfigByTableData($params);
  88. // 更新主表-数据表信息
  89. GenerateTable::update([
  90. 'id' => $params['id'],
  91. 'table_name' => $params['table_name'],
  92. 'table_comment' => $params['table_comment'],
  93. 'template_type' => $params['template_type'],
  94. 'author' => $params['author'] ?? '',
  95. 'remark' => $params['remark'] ?? '',
  96. 'generate_type' => $params['generate_type'],
  97. 'module_name' => $params['module_name'],
  98. 'class_dir' => $params['class_dir'] ?? '',
  99. 'class_comment' => $params['class_comment'] ?? '',
  100. 'menu' => $options['menu'],
  101. 'delete' => $options['delete'],
  102. 'tree' => $options['tree'],
  103. 'relations' => $options['relations'],
  104. ]);
  105. // 更新从表-数据表字段信息
  106. foreach ($params['table_column'] as $item) {
  107. GenerateColumn::update([
  108. 'id' => $item['id'],
  109. 'column_comment' => $item['column_comment'] ?? '',
  110. 'is_required' => $item['is_required'] ?? 0,
  111. 'is_insert' => $item['is_insert'] ?? 0,
  112. 'is_update' => $item['is_update'] ?? 0,
  113. 'is_lists' => $item['is_lists'] ?? 0,
  114. 'is_query' => $item['is_query'] ?? 0,
  115. 'query_type' => $item['query_type'],
  116. 'view_type' => $item['view_type'],
  117. 'dict_type' => $item['dict_type'] ?? '',
  118. ]);
  119. }
  120. Db::commit();
  121. return true;
  122. } catch (\Exception $e) {
  123. Db::rollback();
  124. self::$error = $e->getMessage();
  125. return false;
  126. }
  127. }
  128. /**
  129. * @notes 删除表相关信息
  130. * @param $params
  131. * @return bool
  132. * @author 段誉
  133. * @date 2022/6/16 9:30
  134. */
  135. public static function deleteTable($params)
  136. {
  137. Db::startTrans();
  138. try {
  139. GenerateTable::whereIn('id', $params['id'])->delete();
  140. GenerateColumn::whereIn('table_id', $params['id'])->delete();
  141. Db::commit();
  142. return true;
  143. } catch (\Exception $e) {
  144. Db::rollback();
  145. self::$error = $e->getMessage();
  146. return false;
  147. }
  148. }
  149. /**
  150. * @notes 同步表字段
  151. * @param $params
  152. * @return bool
  153. * @author 段誉
  154. * @date 2022/6/23 16:28
  155. */
  156. public static function syncColumn($params)
  157. {
  158. Db::startTrans();
  159. try {
  160. // table 信息
  161. $table = GenerateTable::findOrEmpty($params['id']);
  162. // 删除旧字段
  163. GenerateColumn::whereIn('table_id', $table['id'])->delete();
  164. // 获取当前数据表字段信息
  165. $column = self::getTableColumn($table['table_name']);
  166. // 创建新字段数据
  167. self::initTableColumn($column, $table['id']);
  168. Db::commit();
  169. return true;
  170. } catch (\Exception $e) {
  171. Db::rollback();
  172. self::$error = $e->getMessage();
  173. return false;
  174. }
  175. }
  176. /**
  177. * @notes 生成代码
  178. * @param $params
  179. * @return false|int[]
  180. * @author 段誉
  181. * @date 2022/6/24 9:43
  182. */
  183. public static function generate($params)
  184. {
  185. try {
  186. // 获取数据表信息
  187. $tables = GenerateTable::with(['table_column'])
  188. ->whereIn('id', $params['id'])
  189. ->select()->toArray();
  190. $generator = app()->make(GenerateService::class);
  191. $generator->delGenerateDirContent();
  192. $flag = array_unique(array_column($tables, 'table_name'));
  193. $flag = implode(',', $flag);
  194. $generator->setGenerateFlag(md5($flag . time()), false);
  195. // 循环生成
  196. foreach ($tables as $table) {
  197. $generator->generate($table);
  198. }
  199. $zipFile = '';
  200. // 生成压缩包
  201. if ($generator->getGenerateFlag()) {
  202. $generator->zipFile();
  203. $generator->delGenerateFlag();
  204. $zipFile = $generator->getDownloadUrl();
  205. }
  206. return ['file' => $zipFile];
  207. } catch (\Exception $e) {
  208. self::$error = $e->getMessage();
  209. return false;
  210. }
  211. }
  212. /**
  213. * @notes 预览
  214. * @param $params
  215. * @return false
  216. * @author 段誉
  217. * @date 2022/6/23 16:27
  218. */
  219. public static function preview($params)
  220. {
  221. try {
  222. // 获取数据表信息
  223. $table = GenerateTable::with(['table_column'])
  224. ->whereIn('id', $params['id'])
  225. ->findOrEmpty()->toArray();
  226. return app()->make(GenerateService::class)->preview($table);
  227. } catch (\Exception $e) {
  228. self::$error = $e->getMessage();
  229. return false;
  230. }
  231. }
  232. /**
  233. * @notes 获取表字段信息
  234. * @param $tableName
  235. * @return array
  236. * @author 段誉
  237. * @date 2022/6/23 16:28
  238. */
  239. public static function getTableColumn($tableName)
  240. {
  241. $tableName = get_no_prefix_table_name($tableName);
  242. return Db::name($tableName)->getFields();
  243. }
  244. /**
  245. * @notes 初始化代码生成数据表信息
  246. * @param $tableData
  247. * @param $adminId
  248. * @return GenerateTable|\think\Model
  249. * @author 段誉
  250. * @date 2022/6/23 16:28
  251. */
  252. public static function initTable($tableData, $adminId)
  253. {
  254. return GenerateTable::create([
  255. 'table_name' => $tableData['name'],
  256. 'table_comment' => $tableData['comment'],
  257. 'template_type' => GeneratorEnum::TEMPLATE_TYPE_SINGLE,
  258. 'generate_type' => GeneratorEnum::GENERATE_TYPE_ZIP,
  259. 'module_name' => 'adminapi',
  260. 'admin_id' => $adminId,
  261. // 菜单配置
  262. 'menu' => [
  263. 'pid' => 0, // 父级菜单id
  264. 'type' => GeneratorEnum::GEN_SELF, // 构建方式 0-手动添加 1-自动构建
  265. 'name' => $tableData['comment'], // 菜单名称
  266. ],
  267. // 删除配置
  268. 'delete' => [
  269. 'type' => GeneratorEnum::DELETE_TRUE, // 删除类型
  270. 'name' => GeneratorEnum::DELETE_NAME, // 默认删除字段名
  271. ],
  272. // 关联配置
  273. 'relations' => [],
  274. // 树形crud
  275. 'tree' => []
  276. ]);
  277. }
  278. /**
  279. * @notes 初始化代码生成字段信息
  280. * @param $column
  281. * @param $tableId
  282. * @throws \Exception
  283. * @author 段誉
  284. * @date 2022/6/23 16:28
  285. */
  286. public static function initTableColumn($column, $tableId)
  287. {
  288. $defaultColumn = ['id', 'create_time', 'update_time', 'delete_time'];
  289. $insertColumn = [];
  290. foreach ($column as $value) {
  291. $required = 0;
  292. if ($value['notnull'] && !$value['primary'] && !in_array($value['name'], $defaultColumn)) {
  293. $required = 1;
  294. }
  295. $columnData = [
  296. 'table_id' => $tableId,
  297. 'column_name' => $value['name'],
  298. 'column_comment' => $value['comment'],
  299. 'column_type' => self::getDbFieldType($value['type']),
  300. 'is_required' => $required,
  301. 'is_pk' => $value['primary'] ? 1 : 0,
  302. ];
  303. if (!in_array($value['name'], $defaultColumn)) {
  304. $columnData['is_insert'] = 1;
  305. $columnData['is_update'] = 1;
  306. $columnData['is_lists'] = 1;
  307. $columnData['is_query'] = 1;
  308. }
  309. $insertColumn[] = $columnData;
  310. }
  311. (new GenerateColumn())->saveAll($insertColumn);
  312. }
  313. /**
  314. * @notes 下载文件
  315. * @param $fileName
  316. * @return false|string
  317. * @author 段誉
  318. * @date 2022/6/24 9:51
  319. */
  320. public static function download(string $fileName)
  321. {
  322. $cacheFileName = cache('curd_file_name' . $fileName);
  323. if (empty($cacheFileName)) {
  324. self::$error = '请重新生成代码';
  325. return false;
  326. }
  327. $path = root_path() . 'runtime/generate/' . $fileName;
  328. if (!file_exists($path)) {
  329. self::$error = '下载失败';
  330. return false;
  331. }
  332. cache('curd_file_name' . $fileName, null);
  333. return $path;
  334. }
  335. /**
  336. * @notes 获取数据表字段类型
  337. * @param string $type
  338. * @return string
  339. * @author 段誉
  340. * @date 2022/6/15 10:11
  341. */
  342. public static function getDbFieldType(string $type): string
  343. {
  344. if (0 === strpos($type, 'set') || 0 === strpos($type, 'enum')) {
  345. $result = 'string';
  346. } elseif (preg_match('/(double|float|decimal|real|numeric)/is', $type)) {
  347. $result = 'float';
  348. } elseif (preg_match('/(int|serial|bit)/is', $type)) {
  349. $result = 'int';
  350. } elseif (preg_match('/bool/is', $type)) {
  351. $result = 'bool';
  352. } elseif (0 === strpos($type, 'timestamp')) {
  353. $result = 'timestamp';
  354. } elseif (0 === strpos($type, 'datetime')) {
  355. $result = 'datetime';
  356. } elseif (0 === strpos($type, 'date')) {
  357. $result = 'date';
  358. } else {
  359. $result = 'string';
  360. }
  361. return $result;
  362. }
  363. /**
  364. * @notes
  365. * @param $options
  366. * @param $tableComment
  367. * @return array
  368. * @author 段誉
  369. * @date 2022/12/13 18:23
  370. */
  371. public static function formatConfigByTableData($options)
  372. {
  373. // 菜单配置
  374. $menuConfig = $options['menu'] ?? [];
  375. // 删除配置
  376. $deleteConfig = $options['delete'] ?? [];
  377. // 关联配置
  378. $relationsConfig = $options['relations'] ?? [];
  379. // 树表crud配置
  380. $treeConfig = $options['tree'] ?? [];
  381. $relations = [];
  382. foreach ($relationsConfig as $relation) {
  383. $relations[] = [
  384. 'name' => $relation['name'] ?? '',
  385. 'model' => $relation['model'] ?? '',
  386. 'type' => $relation['type'] ?? GeneratorEnum::RELATION_HAS_ONE,
  387. 'local_key' => $relation['local_key'] ?? 'id',
  388. 'foreign_key' => $relation['foreign_key'] ?? 'id',
  389. ];
  390. }
  391. $options['menu'] = [
  392. 'pid' => intval($menuConfig['pid'] ?? 0),
  393. 'type' => intval($menuConfig['type'] ?? GeneratorEnum::GEN_SELF),
  394. 'name' => !empty($menuConfig['name']) ? $menuConfig['name'] : $options['table_comment'],
  395. ];
  396. $options['delete'] = [
  397. 'type' => intval($deleteConfig['type'] ?? GeneratorEnum::DELETE_TRUE),
  398. 'name' => !empty($deleteConfig['name']) ? $deleteConfig['name'] : GeneratorEnum::DELETE_NAME,
  399. ];
  400. $options['relations'] = $relations;
  401. $options['tree'] = [
  402. 'tree_id' => $treeConfig['tree_id'] ?? "",
  403. 'tree_pid' =>$treeConfig['tree_pid'] ?? "",
  404. 'tree_name' => $treeConfig['tree_name'] ?? '',
  405. ];
  406. return $options;
  407. }
  408. /**
  409. * @notes 获取所有模型
  410. * @param string $module
  411. * @return array
  412. * @author 段誉
  413. * @date 2022/12/14 11:04
  414. */
  415. public static function getAllModels($module = 'common')
  416. {
  417. if(empty($module)) {
  418. return [];
  419. }
  420. $modulePath = base_path() . $module . '/model/';
  421. if(!is_dir($modulePath)) {
  422. return [];
  423. }
  424. $modulefiles = glob($modulePath . '*');
  425. $targetFiles = [];
  426. foreach ($modulefiles as $file) {
  427. $fileBaseName = basename($file, '.php');
  428. if (is_dir($file)) {
  429. $file = glob($file . '/*');
  430. foreach ($file as $item) {
  431. if (is_dir($item)) {
  432. continue;
  433. }
  434. $targetFiles[] = sprintf(
  435. "\\app\\" . $module . "\\model\\%s\\%s",
  436. $fileBaseName,
  437. basename($item, '.php')
  438. );
  439. }
  440. } else {
  441. if ($fileBaseName == 'BaseModel') {
  442. continue;
  443. }
  444. $targetFiles[] = sprintf(
  445. "\\app\\" . $module . "\\model\\%s",
  446. basename($file, '.php')
  447. );
  448. }
  449. }
  450. return $targetFiles;
  451. }
  452. }