BuildCurd.php 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575
  1. <?php
  2. namespace app\admin\service\curd;
  3. use app\admin\service\curd\exceptions\TableException;
  4. use app\admin\service\tool\CommonTool;
  5. use Exception;
  6. use think\exception\FileException;
  7. use think\facade\Db;
  8. /**
  9. * 快速构建系统CURD
  10. * Class BuildCurd
  11. * @package EasyAdmin\curd
  12. */
  13. class BuildCurd
  14. {
  15. /**
  16. * 当前目录
  17. * @var string
  18. */
  19. protected string $dir;
  20. /**
  21. * 应用目录
  22. * @var string
  23. */
  24. protected string $rootDir;
  25. /**
  26. * 分隔符
  27. * @var string
  28. */
  29. protected string $DS = DIRECTORY_SEPARATOR;
  30. /**
  31. * 数据库名
  32. * @var string
  33. */
  34. protected mixed $dbName;
  35. /**
  36. * 表前缀
  37. * @var string
  38. */
  39. protected mixed $tablePrefix = 'ea';
  40. /**
  41. * 主表
  42. * @var string
  43. */
  44. protected string $table;
  45. /**
  46. * 表注释名
  47. * @var string
  48. */
  49. protected string $tableComment;
  50. /**
  51. * 主表列信息
  52. * @var array
  53. */
  54. protected array $tableColumns;
  55. /**
  56. * 数据列表可见字段
  57. * @var string
  58. */
  59. protected string $fields;
  60. /**
  61. * 是否软删除模式
  62. * @var bool
  63. */
  64. protected bool $delete = false;
  65. /**
  66. * 是否强制覆盖
  67. * @var bool
  68. */
  69. protected bool $force = false;
  70. /**
  71. * 关联模型
  72. * @var array
  73. */
  74. protected array $relationArray = [];
  75. /**
  76. * 控制器对应的URL
  77. * @var string
  78. */
  79. protected string $controllerUrl;
  80. /**
  81. * 生成的控制器名
  82. * @var string
  83. */
  84. protected string $controllerFilename;
  85. /**
  86. * 控制器命名
  87. * @var string
  88. */
  89. protected string $controllerName;
  90. /**
  91. * 控制器命名空间
  92. * @var string
  93. */
  94. protected string $controllerNamespace;
  95. /**
  96. * 视图名
  97. * @var string
  98. */
  99. protected string $viewFilename;
  100. /**
  101. * js文件名
  102. * @var string
  103. */
  104. protected string $jsFilename;
  105. /**
  106. * 生成的模型文件名
  107. * @var string
  108. */
  109. protected string $modelFilename;
  110. /**
  111. * 主表模型命名
  112. * @var string
  113. */
  114. protected string $modelName;
  115. /**
  116. * 复选框字段后缀
  117. * @var array
  118. */
  119. protected array $checkboxFieldSuffix = ['checkbox'];
  120. /**
  121. * 单选框字段后缀
  122. * @var array
  123. */
  124. protected array $radioFieldSuffix = ['radio'];
  125. /**
  126. * 下拉字段后缀
  127. * @var array
  128. */
  129. protected array $selectFieldSuffix = ['select'];
  130. /**
  131. * 单图片字段后缀
  132. * @var array
  133. */
  134. protected array $imageFieldSuffix = ['image', 'logo', 'photo', 'icon'];
  135. /**
  136. * 多图片字段后缀
  137. * @var array
  138. */
  139. protected array $imagesFieldSuffix = ['images', 'photos', 'icons'];
  140. /**
  141. * 单文件字段后缀
  142. * @var array
  143. */
  144. protected array $fileFieldSuffix = ['file'];
  145. /**
  146. * 多文件字段后缀
  147. * @var array
  148. */
  149. protected array $filesFieldSuffix = ['files'];
  150. /**
  151. * 日期字段后缀
  152. * @var array
  153. */
  154. protected array $dateFieldSuffix = ['date', 'time'];
  155. /**
  156. * 日期时间字段后缀
  157. * @var array
  158. */
  159. protected array $datetimeFieldSuffix = ['datetime'];
  160. /**
  161. * 开关组件字段
  162. * @var array
  163. */
  164. protected array $switchFields = [];
  165. /**
  166. * 下拉选择字段
  167. * @var array
  168. */
  169. protected array $selectFields = ['select'];
  170. /**
  171. * 单选字段
  172. * @var array
  173. */
  174. protected array $radioFields = ['radio'];
  175. /**
  176. * 复选字段
  177. * @var array
  178. */
  179. protected array $checkboxFields = ['checkbox'];
  180. /**
  181. * 富文本字段
  182. * @var array
  183. */
  184. protected array $editorFields = [];
  185. /**
  186. * 排序字段
  187. * @var array
  188. */
  189. protected array $sortFields = [];
  190. /**
  191. * 忽略字段
  192. * @var array
  193. */
  194. protected array $ignoreFields = ['update_time', 'delete_time'];
  195. /**
  196. * 外键字段
  197. * @var array
  198. */
  199. protected array $foreignKeyFields = [];
  200. /**
  201. * 相关生成文件
  202. * @var array
  203. */
  204. protected array $fileList = [];
  205. /**
  206. * 表单类型
  207. * @var array
  208. */
  209. protected array $formTypeArray = ['text', 'image', 'images', 'file', 'files', 'select', 'switch', 'date', 'editor', 'textarea', 'checkbox', 'radio'];
  210. /**
  211. * 初始化
  212. * BuildCurd constructor.
  213. */
  214. public function __construct()
  215. {
  216. $this->tablePrefix = config('database.connections.mysql.prefix');
  217. $this->dbName = config('database.connections.mysql.database');
  218. $this->dir = __DIR__;
  219. $this->rootDir = root_path();
  220. return $this;
  221. }
  222. public function setTablePrefix($prefix): static
  223. {
  224. $this->tablePrefix = $prefix;
  225. return $this;
  226. }
  227. /**
  228. * 设置主表
  229. * @param $table
  230. * @return $this
  231. * @throws TableException
  232. */
  233. public function setTable($table): static
  234. {
  235. $this->table = $table;
  236. try {
  237. // 获取表列注释
  238. $columns = Db::query("SHOW FULL COLUMNS FROM {$this->tablePrefix}{$this->table}");
  239. foreach ($columns as $vo) {
  240. $colum = [
  241. 'type' => $vo['Type'],
  242. 'comment' => !empty($vo['Comment']) ? $vo['Comment'] : $vo['Field'],
  243. 'required' => $vo['Null'] == "NO",
  244. 'default' => $vo['Default'],
  245. ];
  246. // 格式化列数据
  247. $this->buildColum($colum);
  248. $this->tableColumns[$vo['Field']] = $colum;
  249. if ($vo['Field'] == 'delete_time') {
  250. $this->delete = true;
  251. }
  252. }
  253. $this->tableComment = $this->table;
  254. } catch (Exception $e) {
  255. throw new TableException($e->getMessage());
  256. }
  257. // 初始化默认控制器名
  258. $nodeArray = explode('_', $this->table);
  259. if (count($nodeArray) == 1) {
  260. $this->controllerFilename = ucfirst($nodeArray[0]);
  261. } else {
  262. foreach ($nodeArray as $k => $v) {
  263. if ($k == 0) {
  264. $this->controllerFilename = "{$v}{$this->DS}";
  265. } else {
  266. $this->controllerFilename .= ucfirst($v);
  267. }
  268. }
  269. }
  270. // 初始化默认模型名
  271. $this->modelFilename = ucfirst(CommonTool::lineToHump($this->table));
  272. $this->buildViewJsUrl();
  273. // 构建数据
  274. $this->buildStructure();
  275. return $this;
  276. }
  277. /**
  278. * 设置关联表
  279. * @param $relationTable
  280. * @param $foreignKey
  281. * @param null $primaryKey
  282. * @param null $modelFilename
  283. * @param array $onlyShowFields
  284. * @param null $bindSelectField
  285. * @return $this
  286. * @throws TableException
  287. */
  288. public function setRelation($relationTable, $foreignKey, $primaryKey = null, $modelFilename = null, array $onlyShowFields = [], $bindSelectField = null): static
  289. {
  290. if (!isset($this->tableColumns[$foreignKey])) {
  291. throw new TableException("主表不存在外键字段:{$foreignKey}");
  292. }
  293. if (!empty($modelFilename)) {
  294. $modelFilename = str_replace('/', $this->DS, $modelFilename);
  295. }
  296. try {
  297. $columns = Db::query("SHOW FULL COLUMNS FROM {$this->tablePrefix}{$relationTable}");
  298. $formatColumns = [];
  299. $delete = false;
  300. if (!empty($bindSelectField) && !in_array($bindSelectField, array_column($columns, 'Field'))) {
  301. throw new TableException("关联表{$relationTable}不存在该字段: {$bindSelectField}");
  302. }
  303. $onlyFields = [];
  304. foreach ($columns as $vo) {
  305. if (empty($primaryKey) && $vo['Key'] == 'PRI') {
  306. $primaryKey = $vo['Field'];
  307. }
  308. if (!empty($onlyShowFields) && !in_array($vo['Field'], $onlyShowFields)) {
  309. continue;
  310. }
  311. if (!empty($onlyShowFields)) $onlyFields[] = $vo['Field'];
  312. $colum = [
  313. 'type' => $vo['Type'],
  314. 'comment' => $vo['Comment'],
  315. 'default' => $vo['Default'],
  316. ];
  317. $this->buildColum($colum);
  318. $formatColumns[$vo['Field']] = $colum;
  319. if ($vo['Field'] == 'delete_time') {
  320. $delete = true;
  321. }
  322. }
  323. $modelFilename = empty($modelFilename) ? ucfirst(CommonTool::lineToHump($relationTable)) : $modelFilename;
  324. $modelArray = explode($this->DS, $modelFilename);
  325. $modelName = array_pop($modelArray);
  326. $relation = [
  327. 'modelFilename' => $modelFilename,
  328. 'modelName' => $modelName,
  329. 'foreignKey' => $foreignKey,
  330. 'primaryKey' => $primaryKey,
  331. 'bindSelectField' => $bindSelectField,
  332. 'delete' => $delete,
  333. 'tableColumns' => $formatColumns,
  334. 'onlyFields' => $onlyFields,
  335. ];
  336. if (!empty($bindSelectField)) {
  337. $relationArray = explode('\\', $modelFilename);
  338. $this->tableColumns[$foreignKey]['bindSelectField'] = $bindSelectField;
  339. $this->tableColumns[$foreignKey]['bindRelation'] = lcfirst(end($relationArray)) . ucfirst($bindSelectField);
  340. }
  341. $this->relationArray[$relationTable] = $relation;
  342. $this->selectFields[] = $foreignKey;
  343. } catch (Exception $e) {
  344. throw new TableException($e->getMessage());
  345. }
  346. return $this;
  347. }
  348. /**
  349. * 设置控制器名
  350. * @param $controllerFilename
  351. * @return $this
  352. */
  353. public function setControllerFilename($controllerFilename): static
  354. {
  355. $this->controllerFilename = str_replace('/', $this->DS, $controllerFilename);
  356. $this->buildViewJsUrl();
  357. return $this;
  358. }
  359. /**
  360. * 设置模型名
  361. * @param $modelFilename
  362. * @return $this
  363. */
  364. public function setModelFilename($modelFilename): static
  365. {
  366. $this->modelFilename = str_replace('/', $this->DS, $modelFilename);
  367. $this->buildViewJsUrl();
  368. return $this;
  369. }
  370. /**
  371. * 设置显示字段
  372. * @param $fields
  373. * @return $this
  374. */
  375. public function setFields($fields): static
  376. {
  377. $this->fields = $fields;
  378. return $this;
  379. }
  380. /**
  381. * 设置删除模式
  382. * @param $delete
  383. * @return $this
  384. */
  385. public function setDelete($delete): static
  386. {
  387. $this->delete = $delete;
  388. return $this;
  389. }
  390. /**
  391. * 设置是否强制替换
  392. * @param $force
  393. * @return $this
  394. */
  395. public function setForce($force): static
  396. {
  397. $this->force = $force;
  398. return $this;
  399. }
  400. /**
  401. * 设置复选框字段后缀
  402. * @param $array
  403. * @return $this
  404. */
  405. public function setCheckboxFieldSuffix($array, $replace = false): static
  406. {
  407. $this->checkboxFieldSuffix = $replace ? $array : array_merge($this->checkboxFieldSuffix, $array);
  408. return $this;
  409. }
  410. /**
  411. * 设置单选框字段后缀
  412. * @param $array
  413. * @return $this
  414. */
  415. public function setRadioFieldSuffix($array, $replace = false): static
  416. {
  417. $this->radioFieldSuffix = $replace ? $array : array_merge($this->radioFieldSuffix, $array);
  418. return $this;
  419. }
  420. /**
  421. * 设置单图片字段后缀
  422. * @param $array
  423. * @return $this
  424. */
  425. public function setImageFieldSuffix($array, $replace = false): static
  426. {
  427. $this->imageFieldSuffix = $replace ? $array : array_merge($this->imageFieldSuffix, $array);
  428. return $this;
  429. }
  430. /**
  431. * 设置多图片字段后缀
  432. * @param $array
  433. * @return $this
  434. */
  435. public function setImagesFieldSuffix($array, $replace = false): static
  436. {
  437. $this->imagesFieldSuffix = $replace ? $array : array_merge($this->imagesFieldSuffix, $array);
  438. return $this;
  439. }
  440. /**
  441. * 设置单文件字段后缀
  442. * @param $array
  443. * @return $this
  444. */
  445. public function setFileFieldSuffix($array, $replace = false): static
  446. {
  447. $this->fileFieldSuffix = $replace ? $array : array_merge($this->fileFieldSuffix, $array);
  448. return $this;
  449. }
  450. /**
  451. * 设置多文件字段后缀
  452. * @param $array
  453. * @return $this
  454. */
  455. public function setFilesFieldSuffix($array, $replace = false): static
  456. {
  457. $this->filesFieldSuffix = $replace ? $array : array_merge($this->filesFieldSuffix, $array);
  458. return $this;
  459. }
  460. /**
  461. * 设置日期字段后缀
  462. * @param $array
  463. * @return $this
  464. */
  465. public function setDateFieldSuffix($array, $replace = false): static
  466. {
  467. $this->dateFieldSuffix = $replace ? $array : array_merge($this->dateFieldSuffix, $array);
  468. return $this;
  469. }
  470. /**
  471. * 设置日期时间字段后缀
  472. * @param $array
  473. * @return $this
  474. */
  475. public function setDatetimeFieldSuffix($array, $replace = false): static
  476. {
  477. $this->datetimeFieldSuffix = $replace ? $array : array_merge($this->datetimeFieldSuffix, $array);
  478. return $this;
  479. }
  480. /**
  481. * 设置开关字段
  482. * @param $array
  483. * @return $this
  484. */
  485. public function setSwitchFields($array, $replace = false): static
  486. {
  487. $this->switchFields = $replace ? $array : array_merge($this->switchFields, $array);
  488. return $this;
  489. }
  490. /**
  491. * 设置下拉选择字段
  492. * @param $array
  493. * @return $this
  494. */
  495. public function setSelectFields($array, $replace = false): static
  496. {
  497. $this->selectFields = $replace ? $array : array_merge($this->selectFields, $array);
  498. return $this;
  499. }
  500. /**
  501. * 设置排序字段
  502. * @param $array
  503. * @return $this
  504. */
  505. public function setSortFields($array, $replace = false): static
  506. {
  507. $this->sortFields = $replace ? $array : array_merge($this->sortFields, $array);
  508. return $this;
  509. }
  510. /**
  511. * 设置忽略字段
  512. * @param $array
  513. * @return $this
  514. */
  515. public function setIgnoreFields($array, $replace = false): static
  516. {
  517. $this->ignoreFields = $replace ? $array : array_merge($this->ignoreFields, $array);
  518. return $this;
  519. }
  520. public function setEditorFields($array, $replace = false): static
  521. {
  522. $this->editorFields = $replace ? $array : array_merge($this->editorFields, $array);
  523. return $this;
  524. }
  525. /**
  526. * 获取相关的文件
  527. * @return array
  528. */
  529. public function getFileList(): array
  530. {
  531. return $this->fileList;
  532. }
  533. /**
  534. * 构建基础视图、JS、URL
  535. * @return $this
  536. */
  537. protected function buildViewJsUrl(): static
  538. {
  539. $nodeArray = explode($this->DS, $this->controllerFilename);
  540. $formatArray = [];
  541. foreach ($nodeArray as $vo) {
  542. $formatArray[] = CommonTool::humpToLine(lcfirst($vo));
  543. }
  544. $this->controllerUrl = implode('.', $formatArray);
  545. $this->viewFilename = implode($this->DS, $formatArray);
  546. $this->jsFilename = $this->viewFilename;
  547. // 控制器命名空间
  548. $namespaceArray = $nodeArray;
  549. $this->controllerName = array_pop($namespaceArray);
  550. $namespaceSuffix = implode('\\', $namespaceArray);
  551. $this->controllerNamespace = empty($namespaceSuffix) ? "app\admin\controller" : "app\admin\controller\\{$namespaceSuffix}";
  552. // 主表模型命名
  553. $modelArray = explode($this->DS, $this->modelFilename);
  554. $this->modelName = array_pop($modelArray);
  555. return $this;
  556. }
  557. /**
  558. * 构建字段
  559. * @return $this
  560. */
  561. protected function buildStructure(): static
  562. {
  563. foreach ($this->tableColumns as $key => $val) {
  564. // 排序
  565. if ($key == 'sort') {
  566. $this->sortFields[] = $key;
  567. }
  568. // 富文本
  569. if (in_array($key, ['describe', 'content', 'details'])) {
  570. $this->editorFields[] = $key;
  571. }
  572. }
  573. return $this;
  574. }
  575. /**
  576. * 构建必填
  577. * @param $require
  578. * @return string
  579. */
  580. protected function buildRequiredHtml($require): string
  581. {
  582. return $require ? 'lay-verify="required"' : "";
  583. }
  584. /**
  585. * 构建初始化字段信息
  586. * @param $colum
  587. * @return array
  588. */
  589. protected function buildColum(&$colum): array
  590. {
  591. $string = $colum['comment'];
  592. $colum['define'] = json_encode([1 => '系统自动生成A', 2 => '请自行修改B'], JSON_UNESCAPED_UNICODE);
  593. // 处理定义类型
  594. preg_match('/{[\s\S]*?}/i', $string, $formTypeMatch);
  595. if (!empty($formTypeMatch) && isset($formTypeMatch[0])) {
  596. $colum['comment'] = str_replace($formTypeMatch[0], '', $colum['comment']);
  597. $formType = trim(str_replace('}', '', str_replace('{', '', $formTypeMatch[0])));
  598. $_formType = $this->checkCommentFormType($formType);
  599. if ($_formType) {
  600. $colum['formType'] = $_formType;
  601. }
  602. }
  603. // 处理默认定义
  604. preg_match('/\([\s\S]*?\)/i', $string, $defineMatch);
  605. if (!empty($formTypeMatch) && isset($defineMatch[0])) {
  606. $colum['comment'] = str_replace($defineMatch[0], '', $colum['comment']);
  607. if (isset($colum['formType']) && in_array($colum['formType'], ['images', 'files', 'select', 'switch', 'radio', 'checkbox', 'date'])) {
  608. $define = str_replace(')', '', str_replace('(', '', $defineMatch[0]));
  609. if (in_array($colum['formType'], ['select', 'switch', 'radio', 'checkbox'])) {
  610. $formatDefine = [];
  611. $explodeArray = explode(',', $define);
  612. foreach ($explodeArray as $vo) {
  613. $voExplodeArray = explode(':', $vo);
  614. if (count($voExplodeArray) == 2) {
  615. $formatDefine[trim($voExplodeArray[0])] = trim($voExplodeArray[1]);
  616. }
  617. }
  618. !empty($formatDefine) && $colum['define'] = $formatDefine;
  619. } else {
  620. $colum['define'] = $define;
  621. }
  622. }
  623. }
  624. $colum['comment'] = trim($colum['comment']);
  625. return $colum;
  626. }
  627. /**
  628. * 构建下拉控制器
  629. * @param $field
  630. * @return mixed
  631. */
  632. protected function buildSelectController($field): mixed
  633. {
  634. $field = CommonTool::lineToHump(ucfirst($field));
  635. $name = "get{$field}List";
  636. $selectCode = CommonTool::replaceTemplate(
  637. $this->getTemplate("controller{$this->DS}select"),
  638. [
  639. 'name' => $name,
  640. ]
  641. );
  642. return $selectCode;
  643. }
  644. /**
  645. * 构架下拉模型
  646. * @param $field
  647. * @param $array
  648. * @return mixed
  649. */
  650. protected function buildSelectModel($field, $array): mixed
  651. {
  652. $field = CommonTool::lineToHump(ucfirst($field));
  653. $name = "get{$field}List";
  654. $values = '[';
  655. foreach ($array as $k => $v) {
  656. $values .= "'{$k}'=>'{$v}',";
  657. }
  658. $values .= ']';
  659. $selectCode = CommonTool::replaceTemplate(
  660. $this->getTemplate("model{$this->DS}select"),
  661. [
  662. 'name' => $name,
  663. 'values' => $values,
  664. ]
  665. );
  666. return $selectCode;
  667. }
  668. /**
  669. * 构架关联下拉模型
  670. * @param $relation
  671. * @param $filed
  672. * @return mixed
  673. */
  674. protected function buildRelationSelectModel($relation, $field): mixed
  675. {
  676. $relationArray = explode('\\', $relation);
  677. $name = end($relationArray);
  678. $name = "get{$name}List";
  679. $selectCode = CommonTool::replaceTemplate(
  680. $this->getTemplate("model{$this->DS}relationSelect"),
  681. [
  682. 'name' => "notes['$field']",
  683. 'relation' => $relation,
  684. 'values' => $field,
  685. ]
  686. );
  687. return $selectCode;
  688. }
  689. /**
  690. * 构建下拉框视图
  691. * @param $field
  692. * @param string $select
  693. * @return mixed
  694. */
  695. protected function buildOptionView($field, string $select = '')
  696. {
  697. // $field = CommonTool::lineToHump(ucfirst($field));
  698. // $name = "get{$field}List";
  699. return CommonTool::replaceTemplate(
  700. $this->getTemplate("view{$this->DS}module{$this->DS}option"),
  701. [
  702. 'name' => "notes['$field']",
  703. 'select' => $select,
  704. ]
  705. );
  706. }
  707. /**
  708. * 构建单选框视图
  709. * @param $field
  710. * @param string $select
  711. * @return mixed
  712. */
  713. protected function buildRadioView($field, string $select = ''): mixed
  714. {
  715. // $formatField = CommonTool::lineToHump(ucfirst($field));
  716. // $name = "get{$formatField}List";
  717. return CommonTool::replaceTemplate(
  718. $this->getTemplate("view{$this->DS}module{$this->DS}radioInput"),
  719. [
  720. 'field' => $field,
  721. 'name' => "notes['$field']",
  722. 'select' => $select,
  723. ]
  724. );
  725. }
  726. /**
  727. * 构建多选框视图
  728. * @param $field
  729. * @param string $select
  730. * @return mixed
  731. */
  732. protected function buildCheckboxView($field, string $select = ''): mixed
  733. {
  734. // $formatField = CommonTool::lineToHump(ucfirst($field));
  735. // $name = "get{$formatField}List";
  736. return CommonTool::replaceTemplate(
  737. $this->getTemplate("view{$this->DS}module{$this->DS}checkboxInput"),
  738. [
  739. 'field' => $field,
  740. 'name' => "notes['$field']",
  741. 'select' => $select,
  742. ]
  743. );
  744. }
  745. /**
  746. * 初始化
  747. * @return $this
  748. */
  749. public function render(): static
  750. {
  751. // 初始化数据
  752. $this->renderData();
  753. // 控制器
  754. $this->renderController();
  755. // 模型
  756. $this->renderModel();
  757. // 视图
  758. $this->renderView();
  759. // JS
  760. $this->renderJs();
  761. return $this;
  762. }
  763. /**
  764. * 初始化数据
  765. * @return $this
  766. */
  767. protected function renderData(): static
  768. {
  769. // 主表
  770. foreach ($this->tableColumns as $field => $val) {
  771. // 过滤字段
  772. if (in_array($field, $this->ignoreFields)) {
  773. unset($this->tableColumns[$field]);
  774. continue;
  775. }
  776. $this->tableColumns[$field]['formType'] = $this->tableColumns[$field]['formType'] ?? 'text';
  777. // 判断图片
  778. if ($this->checkContain($field, $this->imageFieldSuffix)) {
  779. $this->tableColumns[$field]['formType'] = 'image';
  780. continue;
  781. }
  782. if ($this->checkContain($field, $this->imagesFieldSuffix)) {
  783. $this->tableColumns[$field]['formType'] = 'images';
  784. continue;
  785. }
  786. // 判断文件
  787. if ($this->checkContain($field, $this->fileFieldSuffix)) {
  788. $this->tableColumns[$field]['formType'] = 'file';
  789. continue;
  790. }
  791. if ($this->checkContain($field, $this->filesFieldSuffix)) {
  792. $this->tableColumns[$field]['formType'] = 'files';
  793. continue;
  794. }
  795. // 判断日期
  796. if ($this->checkContain($field, $this->dateFieldSuffix)) {
  797. $this->tableColumns[$field]['formType'] = 'date';
  798. continue;
  799. }
  800. // 判断日期时间
  801. if ($this->checkContain($field, $this->datetimeFieldSuffix)) {
  802. $this->tableColumns[$field]['formType'] = 'datetime';
  803. continue;
  804. }
  805. if (in_array($field, $this->radioFields) || $this->checkContain($field, $this->radioFieldSuffix)) {
  806. $this->tableColumns[$field]['formType'] = 'radio';
  807. continue;
  808. }
  809. if (in_array($field, $this->checkboxFields) || $this->checkContain($field, $this->checkboxFieldSuffix)) {
  810. $this->tableColumns[$field]['formType'] = 'checkbox';
  811. continue;
  812. }
  813. // 判断开关
  814. if (in_array($field, $this->switchFields)) {
  815. $this->tableColumns[$field]['formType'] = 'switch';
  816. continue;
  817. }
  818. // 判断富文本
  819. if (in_array($field, $this->editorFields) || in_array($val['type'], ['text', 'tinytext', 'mediumtext', 'longtext'])) {
  820. $this->tableColumns[$field]['formType'] = 'editor';
  821. continue;
  822. }
  823. // 判断排序
  824. if (in_array($field, $this->sortFields)) {
  825. $this->tableColumns[$field]['formType'] = 'sort';
  826. continue;
  827. }
  828. // 判断下拉选择
  829. if (in_array($field, $this->selectFields)) {
  830. $this->tableColumns[$field]['formType'] = 'select';
  831. continue;
  832. }
  833. }
  834. // 关联表
  835. foreach ($this->relationArray as $table => $tableVal) {
  836. foreach ($tableVal['tableColumns'] as $field => $val) {
  837. // 过滤字段
  838. if (in_array($field, $this->ignoreFields)) {
  839. unset($this->relationArray[$table]['tableColumns'][$field]);
  840. continue;
  841. }
  842. // 判断是否已初始化
  843. if (isset($this->relationArray[$table]['tableColumns'][$field]['formType'])) {
  844. continue;
  845. }
  846. // 判断图片
  847. if ($this->checkContain($field, $this->imageFieldSuffix)) {
  848. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'image';
  849. continue;
  850. }
  851. if ($this->checkContain($field, $this->imagesFieldSuffix)) {
  852. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'images';
  853. continue;
  854. }
  855. // 判断文件
  856. if ($this->checkContain($field, $this->fileFieldSuffix)) {
  857. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'file';
  858. continue;
  859. }
  860. if ($this->checkContain($field, $this->filesFieldSuffix)) {
  861. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'files';
  862. continue;
  863. }
  864. // 判断时间
  865. if ($this->checkContain($field, $this->dateFieldSuffix)) {
  866. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'date';
  867. continue;
  868. }
  869. // 判断开关
  870. if (in_array($field, $this->switchFields)) {
  871. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'switch';
  872. continue;
  873. }
  874. // 判断富文本
  875. if (in_array($field, $this->editorFields) || in_array($val['type'], ['text', 'tinytext', 'mediumtext', 'longtext'])) {
  876. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'editor';
  877. continue;
  878. }
  879. // 判断排序
  880. if (in_array($field, $this->sortFields)) {
  881. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'sort';
  882. continue;
  883. }
  884. // 判断下拉选择
  885. if (in_array($field, $this->selectFields)) {
  886. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'select';
  887. continue;
  888. }
  889. $this->relationArray[$table]['tableColumns'][$field]['formType'] = 'text';
  890. }
  891. }
  892. return $this;
  893. }
  894. /**
  895. * 初始化控制器
  896. * @return $this
  897. */
  898. protected function renderController(): static
  899. {
  900. $controllerFile = "{$this->rootDir}app{$this->DS}admin{$this->DS}controller{$this->DS}{$this->controllerFilename}.php";
  901. $constructRelation = '';
  902. if (empty($this->relationArray)) {
  903. $controllerIndexMethod = '';
  904. } else {
  905. $relationCode = '';
  906. foreach ($this->relationArray as $key => $val) {
  907. $relation = CommonTool::lineToHump($key);
  908. $relationCode = "withJoin('{$relation}', 'LEFT')";
  909. if (!empty($val['bindSelectField']) && !empty($val['primaryKey'])) {
  910. $constructRelation = '$notes["' . lcfirst($val['foreignKey']) . '"] = \app\admin\model\\' . $val['modelFilename'] . '::column("' . $val['bindSelectField'] . '", "' . $val['primaryKey'] . '");';
  911. }
  912. }
  913. $controllerIndexMethod = CommonTool::replaceTemplate(
  914. $this->getTemplate("controller{$this->DS}indexMethod"),
  915. [
  916. 'relationIndexMethod' => $relationCode,
  917. ]
  918. );
  919. }
  920. $selectList = '';
  921. // foreach ($this->relationArray as $relation) {
  922. // if (!empty($relation['bindSelectField'])) {
  923. // $relationArray = explode('\\', $relation['modelFilename']);
  924. // $selectList .= $this->buildSelectController(end($relationArray));
  925. // }
  926. // }
  927. // foreach ($this->tableColumns as $field => $val) {
  928. // if (isset($val['formType']) && in_array($val['formType'], ['select', 'switch', 'radio', 'checkbox']) && isset($val['define'])) {
  929. // $selectList .= $this->buildSelectController($field);
  930. // }
  931. // }
  932. $modelFilenameExtend = str_replace($this->DS, '\\', $this->modelFilename);
  933. $controllerValue = CommonTool::replaceTemplate(
  934. $this->getTemplate("controller{$this->DS}controller"),
  935. [
  936. 'controllerName' => $this->controllerName,
  937. 'controllerNamespace' => $this->controllerNamespace,
  938. 'controllerAnnotation' => $this->tableComment,
  939. 'modelFilename' => "\app\admin\model\\{$modelFilenameExtend}",
  940. 'indexMethod' => $controllerIndexMethod,
  941. 'selectList' => $selectList,
  942. 'constructRelation' => $constructRelation,
  943. ]
  944. );
  945. $this->fileList[$controllerFile] = $controllerValue;
  946. return $this;
  947. }
  948. /**
  949. * 初始化模型
  950. * @return $this
  951. */
  952. protected function renderModel(): static
  953. {
  954. // 主表模型
  955. $modelFile = "{$this->rootDir}app{$this->DS}admin{$this->DS}model{$this->DS}{$this->modelFilename}.php";
  956. $relationList = '';
  957. if (!empty($this->relationArray)) {
  958. foreach ($this->relationArray as $key => $val) {
  959. $relation = CommonTool::lineToHump($key);
  960. $relationCode = CommonTool::replaceTemplate(
  961. $this->getTemplate("model{$this->DS}relation"),
  962. [
  963. 'relationMethod' => $relation,
  964. 'relationModel' => "{$val['modelFilename']}::class",
  965. 'foreignKey' => $val['foreignKey'],
  966. 'primaryKey' => $val['primaryKey'],
  967. 'relationFields' => empty($val['onlyFields']) ? "" : "->field('{$val['primaryKey']}," . implode(',', $val['onlyFields']) . "')",
  968. ]);
  969. $relationList .= $relationCode;
  970. }
  971. }
  972. $selectList = '';
  973. foreach ($this->relationArray as $relation) {
  974. if (!empty($relation['bindSelectField'])) {
  975. $selectList .= $this->buildRelationSelectModel($relation['modelFilename'], $relation['bindSelectField']);
  976. }
  977. }
  978. $selectArrays = [];
  979. foreach ($this->tableColumns as $field => $val) {
  980. if (isset($val['formType']) && in_array($val['formType'], ['select', 'switch', 'radio', 'checkbox']) && isset($val['define'])) {
  981. $selectArrays += [$field => is_array($val['define']) ? $val['define'] : json_decode($val['define'], true)];
  982. }
  983. }
  984. $extendNamespaceArray = explode($this->DS, $this->modelFilename);
  985. $extendNamespace = null;
  986. if (count($extendNamespaceArray) > 1) {
  987. array_pop($extendNamespaceArray);
  988. $extendNamespace = '\\' . implode('\\', $extendNamespaceArray);
  989. }
  990. $modelValue = CommonTool::replaceTemplate(
  991. $this->getTemplate("model{$this->DS}model"),
  992. [
  993. 'modelName' => $this->modelName,
  994. 'modelNamespace' => "app\admin\model{$extendNamespace}",
  995. 'prefix_table' => $this->tablePrefix == config('database.connections.mysql.prefix') ? "" : $this->tablePrefix . $this->table,
  996. 'table' => $this->table,
  997. 'deleteTime' => $this->delete ? '"delete_time"' : 'false',
  998. 'relationList' => $relationList,
  999. // 'selectList' => $selectList,
  1000. 'selectArrays' => CommonTool::replaceArrayString(var_export($selectArrays, true)),
  1001. ]
  1002. );
  1003. $this->fileList[$modelFile] = $modelValue;
  1004. // 关联模型
  1005. foreach ($this->relationArray as $key => $val) {
  1006. $relationModelFile = "{$this->rootDir}app{$this->DS}admin{$this->DS}model{$this->DS}{$val['modelFilename']}.php";
  1007. // todo 判断关联模型文件是否存在, 存在就不重新生成文件, 防止关联模型文件被覆盖
  1008. $relationModelClass = "\\app\\admin\\model\\{$val['modelFilename']}";
  1009. if (class_exists($relationModelClass) && method_exists(new $relationModelClass, 'getName')) {
  1010. $tableName = (new $relationModelClass)->getName();
  1011. if (CommonTool::humpToLine(lcfirst($tableName)) == CommonTool::humpToLine(lcfirst($key))) {
  1012. continue;
  1013. }
  1014. }
  1015. $extendNamespaceArray = explode($this->DS, $val['modelFilename']);
  1016. $extendNamespace = null;
  1017. if (count($extendNamespaceArray) > 1) {
  1018. array_pop($extendNamespaceArray);
  1019. $extendNamespace = '\\' . implode('\\', $extendNamespaceArray);
  1020. }
  1021. $relationModelValue = CommonTool::replaceTemplate(
  1022. $this->getTemplate("model{$this->DS}model"),
  1023. [
  1024. 'modelName' => $val['modelName'],
  1025. 'modelNamespace' => "app\admin\model{$extendNamespace}",
  1026. 'prefix_table' => $this->tablePrefix == config('database.connections.mysql.prefix') ? "" : $this->tablePrefix . $this->table,
  1027. 'table' => $key,
  1028. 'deleteTime' => $val['delete'] ? '"delete_time"' : 'false',
  1029. 'relationList' => '',
  1030. 'selectList' => '',
  1031. 'selectArrays' => "[]",
  1032. ]
  1033. );
  1034. $this->fileList[$relationModelFile] = $relationModelValue;
  1035. }
  1036. return $this;
  1037. }
  1038. /**
  1039. * 初始化视图
  1040. * @return $this
  1041. */
  1042. protected function renderView(): static
  1043. {
  1044. // 列表页面
  1045. $viewIndexFile = "{$this->rootDir}app{$this->DS}admin{$this->DS}view{$this->DS}{$this->viewFilename}{$this->DS}index.html";
  1046. $viewIndexValue = CommonTool::replaceTemplate(
  1047. $this->getTemplate("view{$this->DS}index"),
  1048. [
  1049. 'controllerUrl' => $this->controllerUrl,
  1050. 'notesScript' => $this->formatNotesScript(),
  1051. ]
  1052. );
  1053. $this->fileList[$viewIndexFile] = $viewIndexValue;
  1054. // 添加页面
  1055. $viewAddFile = "{$this->rootDir}app{$this->DS}admin{$this->DS}view{$this->DS}{$this->viewFilename}{$this->DS}add.html";
  1056. $addFormList = '';
  1057. foreach ($this->tableColumns as $field => $val) {
  1058. if (in_array($field, ['id', 'create_time'])) {
  1059. continue;
  1060. }
  1061. $templateFile = "view{$this->DS}module{$this->DS}input";
  1062. $define = '';
  1063. // 根据formType去获取具体模板
  1064. if ($val['formType'] == 'image') {
  1065. $templateFile = "view{$this->DS}module{$this->DS}image";
  1066. } elseif ($val['formType'] == 'images') {
  1067. $templateFile = "view{$this->DS}module{$this->DS}images";
  1068. $define = $val['define'] ?? '|';
  1069. if (strlen($define) > 5) $define = '|';
  1070. } elseif ($val['formType'] == 'file') {
  1071. $templateFile = "view{$this->DS}module{$this->DS}file";
  1072. } elseif ($val['formType'] == 'files') {
  1073. $templateFile = "view{$this->DS}module{$this->DS}files";
  1074. $define = $val['define'] ?? '|';
  1075. } elseif ($val['formType'] == 'editor') {
  1076. $templateFile = "view{$this->DS}module{$this->DS}editor";
  1077. $val['default'] = '""';
  1078. } elseif ($val['formType'] == 'date') {
  1079. $templateFile = "view{$this->DS}module{$this->DS}date";
  1080. $define = 'date';
  1081. } elseif ($val['formType'] == 'datetime') {
  1082. $templateFile = "view{$this->DS}module{$this->DS}date";
  1083. $define = 'datetime';
  1084. } elseif ($val['formType'] == 'radio') {
  1085. $templateFile = "view{$this->DS}module{$this->DS}radio";
  1086. if (!empty($val['define'])) {
  1087. $define = $this->buildRadioView($field, '');
  1088. }
  1089. } elseif ($val['formType'] == 'checkbox') {
  1090. $templateFile = "view{$this->DS}module{$this->DS}checkbox";
  1091. if (!empty($val['define'])) {
  1092. $define = $this->buildCheckboxView($field, '');
  1093. }
  1094. } elseif ($val['formType'] == 'select') {
  1095. $templateFile = "view{$this->DS}module{$this->DS}select";
  1096. if (isset($val['bindRelation'])) {
  1097. $define = $this->buildOptionView($field);
  1098. } elseif (!empty($val['define'])) {
  1099. $define = $this->buildOptionView($field);
  1100. }
  1101. } elseif ($field == 'remark' || $val['formType'] == 'textarea') {
  1102. $templateFile = "view{$this->DS}module{$this->DS}textarea";
  1103. } elseif ($field == 'sort') {
  1104. $templateFile = "view{$this->DS}module{$this->DS}sort";
  1105. }
  1106. $addFormList .= CommonTool::replaceTemplate(
  1107. $this->getTemplate($templateFile),
  1108. [
  1109. 'comment' => $val['comment'],
  1110. 'field' => $field,
  1111. 'required' => $this->buildRequiredHtml($val['required']),
  1112. 'value' => $val['default'],
  1113. 'define' => $define,
  1114. ]
  1115. );
  1116. }
  1117. $viewAddValue = CommonTool::replaceTemplate(
  1118. $this->getTemplate("view{$this->DS}form"),
  1119. [
  1120. 'formList' => $addFormList,
  1121. ]
  1122. );
  1123. $this->fileList[$viewAddFile] = $viewAddValue;
  1124. // 编辑页面
  1125. $viewEditFile = "{$this->rootDir}app{$this->DS}admin{$this->DS}view{$this->DS}{$this->viewFilename}{$this->DS}edit.html";
  1126. $editFormList = '';
  1127. foreach ($this->tableColumns as $field => $val) {
  1128. if (in_array($field, ['id', 'create_time'])) {
  1129. continue;
  1130. }
  1131. $templateFile = "view{$this->DS}module{$this->DS}input";
  1132. $define = '';
  1133. $value = '{$row.' . $field . '|default=\'\'}';
  1134. // 根据formType去获取具体模板
  1135. if ($val['formType'] == 'image') {
  1136. $templateFile = "view{$this->DS}module{$this->DS}image";
  1137. } elseif ($val['formType'] == 'images') {
  1138. $templateFile = "view{$this->DS}module{$this->DS}images";
  1139. } elseif ($val['formType'] == 'file') {
  1140. $templateFile = "view{$this->DS}module{$this->DS}file";
  1141. } elseif ($val['formType'] == 'files') {
  1142. $templateFile = "view{$this->DS}module{$this->DS}files";
  1143. } elseif ($val['formType'] == 'editor') {
  1144. $templateFile = "view{$this->DS}module{$this->DS}editor";
  1145. $value = '$row["' . $field . '"]';
  1146. } elseif ($val['formType'] == 'date') {
  1147. $templateFile = "view{$this->DS}module{$this->DS}date";
  1148. $define = 'date';
  1149. } elseif ($val['formType'] == 'datetime') {
  1150. $templateFile = "view{$this->DS}module{$this->DS}date";
  1151. $define = 'datetime';
  1152. } elseif ($val['formType'] == 'radio') {
  1153. $templateFile = "view{$this->DS}module{$this->DS}radio";
  1154. if (!empty($val['define'])) {
  1155. $define = $this->buildRadioView($field, '{if $row.' . $field . '==$k}checked{/if}');
  1156. }
  1157. } elseif ($val['formType'] == 'checkbox') {
  1158. $templateFile = "view{$this->DS}module{$this->DS}checkbox";
  1159. if (!empty($val['define'])) {
  1160. $define = $this->buildCheckboxView($field, '{if $row.' . $field . '==$k}checked{/if}');
  1161. }
  1162. } elseif ($val['formType'] == 'select') {
  1163. $templateFile = "view{$this->DS}module{$this->DS}select";
  1164. if (isset($val['bindRelation'])) {
  1165. $define = $this->buildOptionView($field, '{if $row.' . $field . '==$k}selected{/if}');
  1166. } elseif (!empty($val['define'])) {
  1167. $define = $this->buildOptionView($field, '{if $row.' . $field . '==$k}selected{/if}');
  1168. }
  1169. } elseif ($field == 'remark' || $val['formType'] == 'textarea') {
  1170. $templateFile = "view{$this->DS}module{$this->DS}textarea";
  1171. $value = '{$row.' . $field . '|raw|default=\'\'}';
  1172. } elseif ($field == 'sort') {
  1173. $templateFile = "view{$this->DS}module{$this->DS}sort";
  1174. }
  1175. $editFormList .= CommonTool::replaceTemplate(
  1176. $this->getTemplate($templateFile),
  1177. [
  1178. 'comment' => $val['comment'],
  1179. 'field' => $field,
  1180. 'required' => $this->buildRequiredHtml($val['required']),
  1181. 'value' => $value,
  1182. 'define' => $define,
  1183. ]
  1184. );
  1185. }
  1186. $viewEditValue = CommonTool::replaceTemplate(
  1187. $this->getTemplate("view{$this->DS}form"),
  1188. [
  1189. 'formList' => $editFormList,
  1190. ]
  1191. );
  1192. $this->fileList[$viewEditFile] = $viewEditValue;
  1193. $viewRecycleFile = "{$this->rootDir}app{$this->DS}admin{$this->DS}view{$this->DS}{$this->viewFilename}{$this->DS}recycle.html";
  1194. $viewRecycleValue = CommonTool::replaceTemplate(
  1195. $this->getTemplate("view{$this->DS}recycle"),
  1196. [
  1197. 'controllerUrl' => $this->controllerUrl,
  1198. 'notesScript' => $this->formatNotesScript(),
  1199. ]
  1200. );
  1201. $this->fileList[$viewRecycleFile] = $viewRecycleValue;
  1202. return $this;
  1203. }
  1204. /**
  1205. * 初始化JS
  1206. * @return $this
  1207. */
  1208. protected function renderJs(): static
  1209. {
  1210. $jsFile = "{$this->rootDir}public{$this->DS}static{$this->DS}admin{$this->DS}js{$this->DS}{$this->jsFilename}.js";
  1211. $indexCols = " {type: 'checkbox'},\r";
  1212. // 主表字段
  1213. foreach ($this->tableColumns as $field => $val) {
  1214. if ($val['formType'] == 'image') {
  1215. $templateValue = "{field: '{$field}', title: '{$val['comment']}', templet: ea.table.image}";
  1216. } elseif ($val['formType'] == 'datetime') {
  1217. $templateValue = "{field: '{$field}', search: 'range', title: '{$val['comment']}'}";
  1218. } elseif ($val['formType'] == 'images') {
  1219. continue;
  1220. } elseif ($val['formType'] == 'file') {
  1221. $templateValue = "{field: '{$field}', title: '{$val['comment']}', templet: ea.table.url}";
  1222. } elseif ($val['formType'] == 'files') {
  1223. continue;
  1224. } elseif ($val['formType'] == 'editor') {
  1225. continue;
  1226. } elseif (in_array($field, $this->switchFields)) {
  1227. if (!empty($val['define'])) {
  1228. $templateValue = "{field: '{$field}', search: 'select', selectList: notes?.{$field} || {}, title: '{$val['comment']}', templet: ea.table.switch}";
  1229. } else {
  1230. $templateValue = "{field: '{$field}', title: '{$val['comment']}', templet: ea.table.switch}";
  1231. }
  1232. } elseif (in_array($val['formType'], ['select', 'checkbox', 'radio', 'switch'])) {
  1233. if (!empty($val['define'])) {
  1234. $templateValue = "{field: '{$field}', search: 'select', selectList: notes?.{$field} || {}, title: '{$val['comment']}'}";
  1235. } else {
  1236. $templateValue = "{field: '{$field}', title: '{$val['comment']}'}";
  1237. }
  1238. } elseif ($field == 'remark') {
  1239. $templateValue = "{field: '{$field}', title: '{$val['comment']}', templet: ea.table.text}";
  1240. } elseif (in_array($field, $this->sortFields)) {
  1241. $templateValue = "{field: '{$field}', title: '{$val['comment']}', edit: 'text'}";
  1242. } else {
  1243. $templateValue = "{field: '{$field}', title: '{$val['comment']}'}";
  1244. }
  1245. $indexCols .= $this->formatColsRow("{$templateValue},\r");
  1246. }
  1247. // 关联表
  1248. foreach ($this->relationArray as $table => $tableVal) {
  1249. $table = CommonTool::humpToLine($table);
  1250. foreach ($tableVal['tableColumns'] as $field => $val) {
  1251. if ($val['formType'] == 'image') {
  1252. $templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}', templet: ea.table.image}";
  1253. } elseif ($val['formType'] == 'images') {
  1254. continue;
  1255. } elseif ($val['formType'] == 'file') {
  1256. $templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}', templet: ea.table.url}";
  1257. } elseif ($val['formType'] == 'files') {
  1258. continue;
  1259. } elseif ($val['formType'] == 'editor') {
  1260. continue;
  1261. } elseif ($val['formType'] == 'select') {
  1262. $templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}'}";
  1263. } elseif ($field == 'remark') {
  1264. $templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}', templet: ea.table.text}";
  1265. } elseif (in_array($field, $this->switchFields)) {
  1266. $templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}', templet: ea.table.switch}";
  1267. } elseif (in_array($field, $this->sortFields)) {
  1268. $templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}', edit: 'text'}";
  1269. } else {
  1270. $templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}'}";
  1271. }
  1272. if ($templateValue) $indexCols .= $this->formatColsRow("{$templateValue},\r");
  1273. }
  1274. }
  1275. $recycleCols = $indexCols;
  1276. $indexCols .= $this->formatColsRow("{width: 250, title: '操作', templet: ea.table.tool},\r");
  1277. $jsValue = CommonTool::replaceTemplate(
  1278. $this->getTemplate("static{$this->DS}js"),
  1279. [
  1280. 'controllerUrl' => $this->controllerUrl,
  1281. 'indexCols' => $indexCols,
  1282. 'recycleCols' => $recycleCols,
  1283. ]
  1284. );
  1285. $this->fileList[$jsFile] = $jsValue;
  1286. return $this;
  1287. }
  1288. /**
  1289. * 检测文件
  1290. * @return $this
  1291. */
  1292. protected function check(): static
  1293. {
  1294. // 是否强制性
  1295. if ($this->force) {
  1296. return $this;
  1297. }
  1298. foreach ($this->fileList as $key => $val) {
  1299. if (is_file($key)) {
  1300. throw new FileException("文件已存在:{$key}");
  1301. }
  1302. }
  1303. return $this;
  1304. }
  1305. /**
  1306. * 开始生成
  1307. * @return array
  1308. */
  1309. public function create(): array
  1310. {
  1311. $this->check();
  1312. foreach ($this->fileList as $key => $val) {
  1313. // 判断文件夹是否存在,不存在就创建
  1314. $fileArray = explode($this->DS, $key);
  1315. array_pop($fileArray);
  1316. $fileDir = implode($this->DS, $fileArray);
  1317. if (!is_dir($fileDir)) {
  1318. mkdir($fileDir, 0775, true);
  1319. }
  1320. // 写入
  1321. file_put_contents($key, $val);
  1322. }
  1323. return array_keys($this->fileList);
  1324. }
  1325. /**
  1326. * 开始删除
  1327. * @return array
  1328. */
  1329. public function delete(): array
  1330. {
  1331. $deleteFile = [];
  1332. foreach ($this->fileList as $key => $val) {
  1333. if (is_file($key)) {
  1334. unlink($key);
  1335. $deleteFile[] = $key;
  1336. }
  1337. }
  1338. return $deleteFile;
  1339. }
  1340. /**
  1341. * 检测字段后缀
  1342. * @param $string
  1343. * @param $array
  1344. * @return bool
  1345. */
  1346. protected function checkContain($string, $array): bool
  1347. {
  1348. foreach ($array as $vo) {
  1349. if (str_starts_with($vo, $string)) {
  1350. return true;
  1351. }
  1352. if (str_ends_with($vo, $string)) {
  1353. return true;
  1354. }
  1355. }
  1356. return false;
  1357. }
  1358. /**
  1359. * 格式化表单行
  1360. * @param $value
  1361. * @return string
  1362. */
  1363. protected function formatColsRow($value): string
  1364. {
  1365. return " {$value}";
  1366. }
  1367. /**
  1368. * 获取对应的模板信息
  1369. * @param $name
  1370. * @return false|string
  1371. */
  1372. protected function getTemplate($name): bool|string
  1373. {
  1374. return file_get_contents("{$this->dir}{$this->DS}templates{$this->DS}{$name}.code");
  1375. }
  1376. /**
  1377. * 检测字段注释归类的类型
  1378. * @param string $formType
  1379. * @return string|null
  1380. */
  1381. protected function checkCommentFormType(string $formType = ''): ?string
  1382. {
  1383. $classProperties = get_class_vars(get_class($this));
  1384. foreach ($classProperties as $property => $classProperty) {
  1385. if (empty($property)) continue;
  1386. if (str_ends_with($property, 'FieldSuffix')) {
  1387. if (in_array($formType, $this->$property)) {
  1388. return $this->$property[0] ?? '';
  1389. }
  1390. }
  1391. }
  1392. return '';
  1393. }
  1394. protected function formatNotesScript(): string
  1395. {
  1396. return ' let notes = JSON.parse(\'{$notes|json_encode=256|raw}\');';
  1397. }
  1398. }