FieldService.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. <?php
  2. namespace app\admin\service\sys_manage;
  3. use app\common\Util;
  4. use app\model\SysField;
  5. use Illuminate\Database\Schema\Blueprint;
  6. use Illuminate\Support\Facades\Schema;
  7. use support\Db;
  8. use support\Log;
  9. use support\Request;
  10. class FieldService
  11. {
  12. /**
  13. * @Desc 字段列表
  14. * @Author Gorden
  15. * @Date 2024/2/22 14:49
  16. *
  17. * @param $page
  18. * @param $limit
  19. * @param $keywords
  20. * @return \support\Response
  21. */
  22. public static function fieldList(Request $request)
  23. {
  24. $page = $request->get('page', 1);
  25. $pageSize = $request->get('pageSize', 10);
  26. $fieldName = $request->get('field_name', '');
  27. $tableName = $request->get('table_name', '');
  28. $fieldCategory = $request->get('field_category', '');
  29. $rows = SysField::select('*')
  30. ->when($fieldName != '', function ($query) use ($fieldName) {
  31. $query->where('field_name', 'like', '%' . $fieldName . '%');
  32. })->when($tableName != '', function ($query) use ($tableName) {
  33. $query->where('field_table', 'like', '%' . $tableName . '%');
  34. })->when($fieldCategory != '', function ($query) use ($fieldCategory) {
  35. $query->where('field_category', $fieldCategory);
  36. })->orderBy('field_addtimes', 'DESC')
  37. ->forPage($page, $pageSize)
  38. ->get()
  39. ->toArray();
  40. $total = SysField::when($fieldName != '', function ($query) use ($fieldName) {
  41. $query->where('field_name', 'like', '%' . $fieldName . '%');
  42. })->when($tableName != '', function ($query) use ($tableName) {
  43. $query->where('field_table', 'like', '%' . $tableName . '%');
  44. })->count();
  45. foreach ($rows as &$row) {
  46. $row['field_refer_json'] = json_decode($row['field_refer_json']);
  47. }
  48. return json_success('', compact('rows', 'page', 'pageSize', 'total'));
  49. }
  50. /**
  51. * @Desc 字段详情
  52. * @Author Gorden
  53. * @Date 2024/2/22 14:55
  54. *
  55. * @param $id
  56. * @return \support\Response
  57. */
  58. public static function fieldInfo($id)
  59. {
  60. $field = SysField::where('field_id', $id)->first();
  61. if (!$field) {
  62. return json_fail('字段不存在');
  63. }
  64. return json_success('', $field->toArray());
  65. }
  66. /**
  67. * @Desc 新建字段
  68. * @Author Gorden
  69. * @Date 2024/2/22 14:31
  70. *
  71. * @param $params
  72. * @return \support\Response
  73. */
  74. public static function addField($params)
  75. {
  76. if (!empty($params['field_refer_json']['key'])) {
  77. $params['field_refer_json']['val'] = $params['field_refer_json']['key'];
  78. }
  79. Db::beginTransaction();
  80. try {
  81. $data = [
  82. 'field_status' => $params['field_status'],
  83. 'field_category' => $params['field_category'],
  84. 'field_name' => $params['field_name'],
  85. 'field_table' => $params['field_table'] ?? '',
  86. 'field_column_key' => $params['field_column_key'] ?? '',
  87. 'field_column_datatype' => $params['field_column_datatype'] ?? '',
  88. 'field_column_default' => $params['field_column_default'] ?? '',
  89. 'field_form_key' => $params['field_form_key'] ?? '',
  90. 'field_form_type' => $params['field_form_type'] ?? '',
  91. 'field_form_default' => $params['field_form_default'] ?? '',
  92. 'field_refer_json' => !empty($params['field_refer_json']) ? json_encode($params['field_refer_json']) : '[]',
  93. 'field_remark' => $params['field_remark'] ?? '',
  94. 'field_extend_json' => !empty($params['field_extend_json']) ? $params['field_extend_json'] : '[]',
  95. 'field_addtimes' => time()
  96. ];
  97. // 入库
  98. SysField::insert($data);
  99. if (!empty($params['field_table'])) {
  100. // 字段设置
  101. $column = [
  102. 'type' => self::$column[$params['field_column_datatype']],
  103. 'field' => $params['field_column_key'],
  104. 'primary_key' => false,
  105. 'nullable' => true,
  106. 'default' => $params['field_column_default'],
  107. 'auto_increment' => false,
  108. 'comment' => $params['field_name']
  109. ];
  110. $defaultLength = Util::fieldDefaultLength();
  111. if (isset($defaultLength[$column['type']])) {
  112. $column['length'] = $defaultLength[$column['type']];
  113. }
  114. // 写入字段
  115. Util::schema()->table($params['field_table'], function (Blueprint $table) use ($column) {
  116. self::createColumn($table, $column);
  117. });
  118. }
  119. Db::commit();
  120. } catch (\Exception $e) {
  121. Db::rollBack();
  122. Log::error("创建字段失败", ['msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
  123. return json_fail('创建字段失败');
  124. }
  125. return json_success('创建字段成功');
  126. }
  127. /**
  128. * @Desc 修改字段
  129. * @Author Gorden
  130. * @Date 2024/2/22 14:40
  131. *
  132. * @param $id
  133. * @param $params
  134. * @return \support\Response
  135. */
  136. public static function updateField($id, $params)
  137. {
  138. Db::beginTransaction();
  139. try {
  140. $field = SysField::where('field_id', $id)->first();
  141. $data = [
  142. 'field_category' => $params['field_category'],
  143. 'field_name' => $params['field_name'],
  144. 'field_table' => $params['field_table'],
  145. 'field_column_key' => $params['field_column_key'],
  146. 'field_column_datatype' => $params['field_column_datatype'],
  147. 'field_column_default' => $params['field_column_default'],
  148. 'field_form_key' => $params['field_form_key'],
  149. 'field_form_type' => $params['field_form_type'],
  150. 'field_form_default' => $params['field_form_default'],
  151. 'field_refer_json' => !empty($params['field_refer_json']) ? json_encode($params['field_refer_json']) : '[]',
  152. 'field_remark' => $params['field_remark'],
  153. // 'field_extend_json' => !empty($params['field_extend_json']) ? $params['field_extend_json'] : '[]'
  154. ];
  155. // 更新
  156. SysField::where('field_id', $id)->update($data);
  157. if (!empty($params['field_table'])) {
  158. // 字段设置
  159. $column = [
  160. 'type' => self::$column[$params['field_column_datatype']],
  161. 'field' => $params['field_column_key'],
  162. 'old_field' => $field->field_column_key,
  163. 'primary_key' => false,
  164. 'nullable' => true,
  165. 'default' => $params['field_column_default'],
  166. 'auto_increment' => false,
  167. 'comment' => $params['field_name']
  168. ];
  169. // 设置字段长度
  170. $defaultLength = Util::fieldDefaultLength();
  171. if (isset($defaultLength[$column['type']])) {
  172. $column['length'] = $defaultLength[$column['type']];
  173. }
  174. // 表变动
  175. if ($field->field_table != $params['field_table']) {
  176. if (!empty($field->field_table)) {
  177. // 删原表字段
  178. Util::db()->statement("ALTER TABLE " . getenv('DB_PREFIX') . $field->field_table . " DROP COLUMN `$field->field_column_key`");
  179. }
  180. // 在新表创建
  181. Util::schema()->table($params['field_table'], function (Blueprint $table) use ($column) {
  182. self::createColumn($table, $column);
  183. });
  184. } else {
  185. // 表没变,改就行
  186. self::modifyColumn($params['field_table'], $column);
  187. }
  188. }
  189. Db::commit();
  190. } catch (\Exception $e) {
  191. Db::rollBack();
  192. dump($e->getMessage());
  193. return json_fail('修改字段失败');
  194. }
  195. return json_success('修改字段成功');
  196. }
  197. /**
  198. * @Desc 修改字段状态
  199. * @Author Gorden
  200. * @Date 2024/2/22 15:06
  201. *
  202. * @param $id
  203. * @param $params
  204. * @return \support\Response
  205. */
  206. public static function updateStatus($id, $params)
  207. {
  208. try {
  209. SysField::where('field_id', $id)->update(['field_status' => $params['field_status']]);
  210. } catch (\Exception $e) {
  211. return json_fail('字段状态修改失败');
  212. }
  213. return json_success('字段状态修改成功');
  214. }
  215. /**
  216. * @Desc 删除字段
  217. * @Author Gorden
  218. * @Date 2024/2/22 15:08
  219. *
  220. * @param $id
  221. * @return \support\Response
  222. */
  223. public static function delField($ids)
  224. {
  225. Db::beginTransaction();
  226. try {
  227. if (!is_array($ids)) {
  228. $ids = [$ids];
  229. }
  230. foreach ($ids as $id) {
  231. $field = SysField::where('field_id', $id)->first();
  232. // 删除表记录
  233. $field->delete();
  234. // 删除表字段
  235. Util::db()->statement("ALTER TABLE " . getenv('DB_PREFIX') . $field->field_table . " DROP COLUMN `$field->field_column_key`");
  236. }
  237. // 提交事务
  238. Db::commit();
  239. } catch (\Exception $e) {
  240. // 回滚
  241. Db::rollBack();
  242. return json_fail('字段删除失败');
  243. }
  244. return json_success('字段删除成功');
  245. }
  246. public static function checkTableExist($table)
  247. {
  248. if (empty($table)) {
  249. return true;
  250. }
  251. try {
  252. // $table = $table;
  253. $desc = (new SysField)->getConnection()->select("desc `$table`");
  254. if ($desc) {
  255. return true;
  256. }
  257. } catch (\Exception $e) {
  258. return false;
  259. }
  260. }
  261. /**
  262. * @Desc 验证表字段是否存在
  263. * @Author Gorden
  264. * @Date 2024/2/23 11:49
  265. *
  266. * @param $table
  267. * @param $field
  268. * @return bool
  269. */
  270. public static function checkFieldExist($table, $field)
  271. {
  272. if (empty($table)) {
  273. return false;
  274. }
  275. return SysField::where('field_table', $table)
  276. ->where('field_column_key', $field)
  277. ->exists();
  278. }
  279. /**
  280. * 创建字段
  281. * @param $column
  282. * @param Blueprint $table
  283. * @return mixed
  284. * @throws \Exception
  285. */
  286. public static function createColumn(Blueprint $table, $column)
  287. {
  288. $method = $column['type'];
  289. $args = [$column['field']];
  290. $type_method_map = Util::methodControlMap();
  291. if (!isset($column['type'])) {
  292. throw new \Exception("请为{$column['field']}选择类型");
  293. }
  294. if (!isset($type_method_map[$column['type']])) {
  295. throw new \Exception("不支持的类型{$column['type']}");
  296. }
  297. if (stripos($method, 'int') !== false) {
  298. // auto_increment 会自动成为主键
  299. if ($column['auto_increment']) {
  300. $column['nullable'] = false;
  301. $column['default'] = null;
  302. $args[] = true;
  303. }
  304. } elseif (in_array($method, ['string', 'char']) || stripos($method, 'time') !== false) {
  305. if ($column['length']) {
  306. $args[] = $column['length'];
  307. }
  308. } elseif ($method === 'enum') {
  309. $args[] = array_map('trim', explode(',', $column['length']));
  310. } elseif (in_array($method, ['float', 'decimal', 'double'])) {
  311. if ($column['length']) {
  312. $args = array_merge($args, array_map('trim', explode(',', $column['length'])));
  313. }
  314. } else {
  315. $column['auto_increment'] = false;
  316. }
  317. $column_def = call_user_func_array([$table, $method], $args);
  318. if (!empty($column['comment'])) {
  319. $column_def = $column_def->comment($column['comment']);
  320. }
  321. if (!$column['auto_increment'] && $column['primary_key']) {
  322. $column_def = $column_def->primary(true);
  323. }
  324. if ($column['auto_increment'] && !$column['primary_key']) {
  325. $column_def = $column_def->primary(false);
  326. }
  327. $column_def = $column_def->nullable($column['nullable']);
  328. if ($column['primary_key']) {
  329. $column_def = $column_def->nullable(false);
  330. }
  331. if ($method != 'text' && $column['default'] !== null) {
  332. $column_def->default($column['default']);
  333. }
  334. return $column_def;
  335. }
  336. /**
  337. * 更改字段
  338. * @param $column
  339. * @param $table
  340. * @return mixed
  341. * @throws \Exception
  342. */
  343. protected static function modifyColumn($table, $column)
  344. {
  345. $method = $column['type'];
  346. $field = $column['field'];
  347. $old_field = $column['old_field'] ?? null;
  348. $nullable = $column['nullable'];
  349. $default = $column['default'] !== null ? Util::pdoQuote($column['default']) : null;
  350. $comment = Util::pdoQuote($column['comment']);
  351. $auto_increment = $column['auto_increment'];
  352. $length = (int)$column['length'];
  353. if ($column['primary_key']) {
  354. $default = null;
  355. }
  356. if ($old_field && $old_field !== $field) {
  357. $sql = "ALTER TABLE `$table` CHANGE COLUMN `$old_field` `$field` ";
  358. } else {
  359. $sql = "ALTER TABLE `$table` MODIFY `$field` ";
  360. }
  361. if (stripos($method, 'integer') !== false) {
  362. $type = str_ireplace('integer', 'int', $method);
  363. if (stripos($method, 'unsigned') !== false) {
  364. $type = str_ireplace('unsigned', '', $type);
  365. $sql .= "$type ";
  366. $sql .= 'unsigned ';
  367. } else {
  368. $sql .= "$type ";
  369. }
  370. if ($auto_increment) {
  371. $column['nullable'] = false;
  372. $column['default'] = null;
  373. $sql .= 'AUTO_INCREMENT ';
  374. }
  375. } else {
  376. switch ($method) {
  377. case 'string':
  378. $length = $length ?: 255;
  379. $sql .= "varchar($length) ";
  380. break;
  381. case 'char':
  382. case 'time':
  383. $sql .= $length ? "$method($length) " : "$method ";
  384. break;
  385. case 'enum':
  386. $args = array_map('trim', explode(',', (string)$column['length']));
  387. foreach ($args as $key => $value) {
  388. $args[$key] = Util::pdoQuote($value);
  389. }
  390. $sql .= 'enum(' . implode(',', $args) . ') ';
  391. break;
  392. case 'double':
  393. case 'float':
  394. case 'decimal':
  395. if (trim($column['length'])) {
  396. $args = array_map('intval', explode(',', $column['length']));
  397. $args[1] = $args[1] ?? $args[0];
  398. $sql .= "$method($args[0], $args[1]) ";
  399. break;
  400. }
  401. $sql .= "$method ";
  402. break;
  403. default :
  404. $sql .= "$method ";
  405. }
  406. }
  407. if (!$nullable) {
  408. $sql .= "NOT NULL ";
  409. }
  410. if ($method != 'text' && $default !== null) {
  411. $sql .= "DEFAULT $default ";
  412. }
  413. if ($comment !== null) {
  414. $sql .= "COMMENT $comment ";
  415. }
  416. echo "$sql\n";
  417. Util::db()->statement($sql);
  418. }
  419. public static $column = [
  420. 'VARCHAR' => 'string',
  421. 'DATETIME' => 'dateTime',
  422. 'INT' => 'integer',
  423. 'DECIMAL' => 'decimal'
  424. ];
  425. public static $formType = [
  426. 'TEXT' => '单行文本',
  427. 'TEXTAREA' => '多行文本',
  428. 'RADIO' => '单选',
  429. 'CHECKBOX' => '多选',
  430. 'SELECT' => '下拉选择',
  431. 'DATE' => '日期'
  432. ];
  433. }