Tablemake.php 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. <?php
  2. namespace app\admin\controller;
  3. use app\common\controller\Backend;
  4. use think\Db;
  5. use think\Config;
  6. use think\Exception;
  7. //use think\Config;
  8. /**
  9. * 自建表管理
  10. *
  11. * @icon fa fa-circle-o
  12. */
  13. class Tablemake extends Backend {
  14. /**
  15. * Test模型对象
  16. * @var \app\admin\model\Test
  17. */
  18. protected $ModelOnline = null;
  19. protected $ModelFields = null;
  20. protected $searchFields = false;//关闭快捷搜索
  21. protected $db_name = '';
  22. protected $db_prefix = '';
  23. public function _initialize() {
  24. parent::_initialize();
  25. $this->ModelOnline = model('TableMakeTables');
  26. $this->ModelFields = model('TableMakeFields');
  27. $dictionary_url = url("tablemake/dictionary", [], true, true);
  28. $this->view->assign("dictionary_url", $dictionary_url);
  29. }
  30. /*
  31. * 数据表列表
  32. */
  33. public function index() {
  34. $this->searchFields = "name,table,desc";
  35. if ($this->request->isAjax()) {
  36. $prefix = Config::get('database.prefix');
  37. $this->model = $this->ModelOnline;
  38. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  39. $list = $this->model
  40. ->where($where)
  41. ->order($sort, $order)
  42. ->paginate($limit);
  43. $result = array("total" => $list->total(), "rows" => $list->items(), "prefix" => $prefix);
  44. return json($result);
  45. }
  46. return $this->view->fetch();
  47. }
  48. /*
  49. * 创建数据表
  50. */
  51. public function add() {
  52. if ($this->request->isPost()) {
  53. $params = $this->request->post("row/a");
  54. if ($params) {
  55. if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
  56. $params[$this->dataLimitField] = $this->auth->id;
  57. }
  58. try {
  59. //是否采用模型验证
  60. if ($this->modelValidate) {
  61. $name = str_replace("\\model\\", "\\validate\\", get_class($this->ModelOnline));
  62. $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
  63. $this->ModelOnline->validate($validate);
  64. }
  65. $params['createtime'] = time();
  66. $params['updatetime'] = time();
  67. $result = $this->ModelOnline->allowField(true)->save($params);
  68. $prefix = Config::get('database.prefix');
  69. if ($result !== false) {
  70. //在此执行创建表的操作
  71. $sql = "CREATE TABLE IF NOT EXISTS `{$prefix}" . $params['table'] . "` (
  72. `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  73. PRIMARY KEY (`id`)
  74. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='" . $params['name'] . "';";
  75. $res = \think\Db::execute($sql);
  76. //var_export($res);
  77. $this->success();
  78. } else {
  79. $this->error($this->ModelOnline->getError());
  80. }
  81. } catch (\think\exception\PDOException $e) {
  82. $this->error($e->getMessage());
  83. } catch (\think\Exception $e) {
  84. $this->error($e->getMessage());
  85. }
  86. }
  87. $this->error(__('Parameter %s can not be empty', ''));
  88. }
  89. $prefix = Config::get('database.prefix');
  90. $this->view->assign("prefix", $prefix);
  91. return $this->view->fetch();
  92. }
  93. /*
  94. * 编辑数据表
  95. */
  96. public function edit($ids = NULL) {
  97. $row = $this->ModelOnline->get($ids);
  98. if (!$row)
  99. $this->error(__('No Results were found'));
  100. $adminIds = $this->getDataLimitAdminIds();
  101. if (is_array($adminIds)) {
  102. if (!in_array($row[$this->dataLimitField], $adminIds)) {
  103. $this->error(__('You have no permission'));
  104. }
  105. }
  106. if ($this->request->isPost()) {
  107. $params = $this->request->post("row/a");
  108. if ($params) {
  109. try {
  110. //是否采用模型验证
  111. if ($this->modelValidate) {
  112. $name = basename(str_replace('\\', '/', get_class($this->ModelOnline)));
  113. $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate;
  114. $row->validate($validate);
  115. }
  116. $params['updatetime'] = time();
  117. $result = $row->allowField(true)->save($params);
  118. if ($result !== false) {
  119. $prefix = Config::get('database.prefix');
  120. $sql = "ALTER TABLE `{$prefix}" . $row['table'] . "` COMMENT='" . $row['name'] . "';";
  121. $res = \think\Db::execute($sql);
  122. $this->success();
  123. } else {
  124. $this->error($row->getError());
  125. }
  126. } catch (\think\exception\PDOException $e) {
  127. $this->error($e->getMessage());
  128. } catch (\think\Exception $e) {
  129. $this->error($e->getMessage());
  130. }
  131. }
  132. $this->error(__('Parameter %s can not be empty', ''));
  133. }
  134. $prefix = Config::get('database.prefix');
  135. $this->view->assign("row", $row);
  136. $this->view->assign("prefix", $prefix);
  137. return $this->view->fetch();
  138. }
  139. /*
  140. * 删除模块
  141. */
  142. public function del($ids = NULL) {
  143. if ($ids) {
  144. $pk = $this->ModelOnline->getPk();
  145. $adminIds = $this->getDataLimitAdminIds();
  146. if (is_array($adminIds)) {
  147. $count = $this->ModelOnline->where($this->dataLimitField, 'in', $adminIds);
  148. }
  149. $list = $this->ModelOnline->where($pk, 'in', $ids)->select();
  150. $prefix = Config::get('database.prefix');
  151. $count = 0;
  152. foreach ($list as $k => $v) {
  153. $sql = "DROP TABLE IF EXISTS `{$prefix}" . $v->table . "`;";
  154. try {
  155. $res = \think\Db::execute($sql);
  156. $this->ModelFields->where("mid", '=', $v->id)->delete();
  157. $count += $v->delete();
  158. if ($count) {
  159. $this->success(__('删除成功!'), null, __('删除成功!'));
  160. } else {
  161. $this->error(__('No rows were deleted'));
  162. }
  163. } catch (Exception $ex) {
  164. $this->error(__('No rows were deleted'));
  165. }
  166. }
  167. }
  168. $this->error(__('Parameter %s can not be empty', 'ids'));
  169. }
  170. /*
  171. * 验证重名
  172. */
  173. public function check($table = null, $name = null) {
  174. if ($table == null && $name == null) {
  175. if ($this->request->isAjax()) {
  176. $table = $this->request->request('table');
  177. $name = $this->request->request('name');
  178. }
  179. }
  180. if ($table && $name) {
  181. $sql = "describe `{$table}` `{$name}`";
  182. $res = \think\Db::query($sql);
  183. if ($res) {
  184. return true;
  185. } else {
  186. return false;
  187. }
  188. } else {
  189. return false;
  190. }
  191. }
  192. /*
  193. * 字段列表
  194. */
  195. public function fields($ids = NULL) {
  196. $this->searchFields = "name,title,comment";
  197. if ($ids == NULL) {
  198. $ids = intval($this->request->request('ids'));
  199. }
  200. $model = $this->ModelOnline->get($ids);
  201. if (!$model) {
  202. $this->error(__('No Results were found'));
  203. }
  204. if ($this->request->isAjax()) {
  205. $prefix = Config::get('database.prefix');
  206. $this->model = $this->ModelFields;
  207. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  208. $list = $this->model
  209. ->where("mid", '=', $ids)
  210. ->where($where)
  211. ->order($sort, $order)
  212. ->paginate($limit);
  213. $result = array("total" => $list->total(), "rows" => $list->items(), "prefix" => $prefix);
  214. return json($result);
  215. // $list = $this->ModelFields->where("mid", '=', $ids)->order('id desc')->select();
  216. // $total = count($list);
  217. // $prefix = Config::get('database.prefix');
  218. // $result = array("total" => $total, "rows" => $list, "prefix" => $prefix);
  219. // return json($result);
  220. }
  221. $this->view->assign("ids", $ids);
  222. return $this->view->fetch();
  223. }
  224. /*
  225. * 添加字段
  226. */
  227. public function field_add($mid = NULL) {
  228. $mod_table = $this->ModelOnline->get($mid);
  229. if (!$mod_table)
  230. $this->error(__('No Results were found'));
  231. if ($this->request->isPost()) {
  232. $params = $this->request->post("row/a");
  233. if ($params) {
  234. try {
  235. //是否采用模型验证
  236. if ($this->modelValidate) {
  237. $name = str_replace("\\model\\", "\\validate\\", get_class($this->ModelFields));
  238. $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
  239. $this->ModelFields->validate($validate);
  240. }
  241. $prefix = Config::get('database.prefix');
  242. $field = array();
  243. $fieldData = array();
  244. switch ($params['category']) {
  245. case "1":
  246. $allow = array(
  247. "text" => array("suffix" => "text", "type" => "varchar", "length" => 200),
  248. "number" => array("suffix" => "number", "type" => "bigint", "length" => 11),
  249. "time" => array("suffix" => "time", "type" => "bigint", "length" => 11),
  250. "image" => array("suffix" => "image", "type" => "varchar", "length" => 255),
  251. "images" => array("suffix" => "images", "type" => "varchar", "length" => 2000),
  252. "file" => array("suffix" => "file", "type" => "varchar", "length" => 255),
  253. "files" => array("suffix" => "files", "type" => "varchar", "length" => 2000),
  254. "avatar" => array("suffix" => "avatar", "type" => "varchar", "length" => 255),
  255. "avatars" => array("suffix" => "avatars", "type" => "varchar", "length" => 2000),
  256. "content" => array("suffix" => "content", "type" => "text", "length" => 0),
  257. "_id" => array("suffix" => "_id", "type" => "bigint", "length" => 11),
  258. "_ids" => array("suffix" => "_ids", "type" => "varchar", "length" => 255),
  259. "list-enum" => array("suffix" => "list", "type" => "enum", "length" => 0),
  260. "list-set" => array("suffix" => "list", "type" => "set", "length" => 0),
  261. "data-enum" => array("suffix" => "data", "type" => "enum", "length" => 0),
  262. "data-set" => array("suffix" => "data", "type" => "set", "length" => 0),
  263. "json" => array("suffix" => "json", "type" => "varchar", "length" => 2000),
  264. "switch" => array("suffix" => "switch", "type" => "tinyint", "length" => 1),
  265. );
  266. if (isset($allow[$params['suffix']]) && is_array($allow[$params['suffix']])) {
  267. $fieldData['special'] = "";
  268. $fieldData['suffix'] = $params['suffix'];
  269. //$field['name'] = $params['name'] . $allow[$params['suffix']]['suffix']; //字段名
  270. $field['name'] = $params['name']; //字段名
  271. $field['field'] = $params['name'] . $allow[$params['suffix']]['suffix']; //字段名
  272. $field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['suffix']]['length']; //字段长度
  273. $field['type'] = $allow[$params['suffix']]['type']; //字段类型
  274. $field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值
  275. if ($allow[$params['suffix']]['type'] == "enum" || $allow[$params['suffix']]['type'] == "set") {
  276. $comment = \GuzzleHttp\json_decode($params['comment'], true);
  277. $field['comment'] = $params['title'] . ":"; //备注
  278. $field['length2'] = "";
  279. $str = "";
  280. $default_optional = array();
  281. foreach ($comment as $k => $v) {
  282. $default_optional[] = $k;
  283. $field['comment'] .= $str . $k . "=" . $v;
  284. $field['length2'] .= $str . "'" . $k . "'";
  285. $str = ",";
  286. }
  287. if (!in_array($field['default'], $default_optional)) {
  288. $field['default'] = $default_optional[0];
  289. }
  290. } else {
  291. $params['comment'] = "";
  292. $field['comment'] = $params['title']; //备注
  293. }
  294. } else {
  295. $this->error(__('特殊字段类型不正确!'));
  296. }
  297. break;
  298. case "2":
  299. $allow = array(
  300. "varchar" => array("type" => "varchar", "length" => 255),
  301. "int" => array("type" => "bigint", "length" => 11),
  302. "enum" => array("type" => "enum", "length" => 0),
  303. "set" => array("type" => "set", "length" => 0),
  304. "float" => array("type" => "float", "length" => "10,2"),
  305. "text" => array("type" => "text", "length" => 0),
  306. "datetime" => array("type" => "datetime", "length" => 11),
  307. "date" => array("type" => "date", "length" => 11),
  308. "year" => array("type" => "year", "length" => 4),
  309. "timestamp" => array("type" => "timestamp", "length" => 11),
  310. );
  311. if (isset($allow[$params['type']]) && is_array($allow[$params['type']])) {
  312. $fieldData['special'] = "";
  313. $fieldData['suffix'] = "";
  314. $params['suffix'] = "";
  315. $field['name'] = $params['name']; //字段名
  316. $field['field'] = $params['name']; //字段名
  317. if ($params['type'] == "float") {
  318. $field['length'] = $field['length2'] = isset($params['length']) && $params['length'] ? $params['length'] : $allow[$params['type']]['length']; //字段长度
  319. } else {
  320. $field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['type']]['length']; //字段长度
  321. }
  322. $field['type'] = $allow[$params['type']]['type']; //字段类型
  323. $field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值
  324. if ($allow[$params['type']]['type'] == "enum" || $allow[$params['type']]['type'] == "set") {
  325. $comment = \GuzzleHttp\json_decode($params['comment'], true);
  326. $field['comment'] = $params['title'] . ":"; //备注
  327. $field['length2'] = "";
  328. $str = "";
  329. $default_optional = array();
  330. foreach ($comment as $k => $v) {
  331. $default_optional[] = $k;
  332. $field['comment'] .= $str . $k . "=" . $v;
  333. $field['length2'] .= $str . "'" . $k . "'";
  334. $str = ",";
  335. }
  336. if (!in_array($field['default'], $default_optional)) {
  337. $field['default'] = $default_optional[0];
  338. }
  339. } else {
  340. $params['comment'] = "";
  341. $field['comment'] = $params['title']; //备注
  342. }
  343. } else {
  344. $this->error(__('特殊字段类型不正确!'));
  345. }
  346. break;
  347. case "3":
  348. $allow = array(
  349. "user_id" => array("title" => "会员ID(单选)", "type" => "bigint", "length" => 11),
  350. "category_id" => array("title" => "分类ID(单选)", "type" => "bigint", "length" => 11),
  351. "category_ids" => array("title" => "分类ID(多选)", "type" => "varchar", "length" => 200),
  352. "weigh" => array("title" => "权重", "type" => "bigint", "length" => 11),
  353. "status" => array("title" => "状态", "type" => "enum", "length" => 0),
  354. "createtime" => array("title" => "创建时间", "type" => "bigint", "length" => 11),
  355. "updatetime" => array("title" => "更新时间", "type" => "bigint", "length" => 11),
  356. "deletetime" => array("title" => "删除时间", "type" => "bigint", "length" => 11),
  357. );
  358. if (isset($allow[$params['special']]) && is_array($allow[$params['special']])) {
  359. $fieldData['special'] = $params['special'];
  360. $fieldData['suffix'] = "";
  361. //$params['title'] = $allow[$params['special']]['title'];
  362. // $params['comment'] = $params['suffix'] = "";
  363. $field['name'] = $params['special']; //字段名
  364. $field['field'] = $params['special']; //字段名
  365. $field['length'] = $field['length2'] = $allow[$params['special']]['length']; //字段长度
  366. // $field['comment'] = $params['title']; //备注
  367. $field['type'] = $allow[$params['special']]['type']; //字段类型
  368. $field['default'] = $field['type'] == "varchar" ? "" : "0"; //默认值
  369. if ($params['special'] == "status") {
  370. $comment = \GuzzleHttp\json_decode($params['comment'], true);
  371. $field['comment'] = $params['title'] . ":"; //备注
  372. $field['length2'] = "";
  373. $str = "";
  374. $default_optional = array();
  375. foreach ($comment as $k => $v) {
  376. $default_optional[] = $k;
  377. $field['comment'] .= $str . $k . "=" . $v;
  378. $field['length2'] .= $str . "'" . $k . "'";
  379. $str = ",";
  380. }
  381. if (!in_array($field['default'], $default_optional)) {
  382. $field['default'] = $default_optional[0];
  383. }
  384. } else {
  385. $params['comment'] = "";
  386. $field['comment'] = $params['title']; //备注
  387. }
  388. } else {
  389. $this->error(__('特殊字段类型不正确!'));
  390. }
  391. break;
  392. default :
  393. $this->error(__('No Results were found'));
  394. break;
  395. }
  396. if ($this->check($prefix . $mod_table['table'], $field['name'])) {
  397. $this->error(__('字段已经存在!'));
  398. }
  399. $fieldData['mid'] = $params['mid'];
  400. $fieldData['category'] = $params['category'];
  401. $fieldData['title'] = $params['title'];
  402. $fieldData['name'] = $field['name'];
  403. $fieldData['field'] = $field['field'];
  404. $fieldData['type'] = $field['type'];
  405. $fieldData['length'] = $field['length'];
  406. $fieldData['default'] = $field['default'];
  407. $fieldData['comment'] = $field['comment'];
  408. $fieldData['desc'] = $params['desc'];
  409. $fieldData['createtime'] = time();
  410. $fieldData['updatetime'] = time();
  411. if ($fieldData['type'] == "text") {
  412. $fieldData['default'] = "";
  413. }
  414. if ($field['type'] == "bigint" || $field['type'] == "int") {
  415. $field['default'] = intval($field['default']);
  416. } elseif ($field['type'] == "tinyint") {
  417. $field['default'] = in_array($field['default'], [0, 1]) ? $field['default'] : 0;
  418. } elseif ($field['type'] == "float") {
  419. $field['default'] = is_float($field['default']) ? $field['default'] : 0;
  420. }
  421. \think\Db::startTrans();
  422. try {
  423. $result = $this->ModelFields->allowField(true)->save($fieldData);
  424. if ($result !== false) {
  425. //在此执行添加字段的操作
  426. if (in_array($field['type'], ["text", "datetime", "date", "year", "timestamp"])) {
  427. $sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` ADD COLUMN `{$field['field']}` {$field['type']} NOT NULL COMMENT '{$field['comment']}';";
  428. } else {
  429. $sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` ADD COLUMN `{$field['field']}` {$field['type']}({$field['length2']}) NOT NULL DEFAULT '{$field['default']}' COMMENT '{$field['comment']}';";
  430. }
  431. try {
  432. $res = \think\Db::execute($sql);
  433. } catch (Exception $ex) {
  434. new Exception('参数错误,请检查字段名,字段长度或者默认值等输入参数是否合法');
  435. }
  436. } else {
  437. new Exception($this->ModelFields->getError());
  438. }
  439. \think\Db::commit();
  440. } catch (Exception $e) {
  441. \think\Db::rollback();
  442. $this->error($e->getMessage());
  443. }
  444. $this->success();
  445. } catch (\think\exception\PDOException $e) {
  446. $this->error($e->getMessage());
  447. } catch (\think\Exception $e) {
  448. $this->error($e->getMessage());
  449. }
  450. }
  451. $this->error(__('Parameter %s can not be empty', ''));
  452. }
  453. $prefix = Config::get('database.prefix');
  454. $this->view->assign("prefix", $prefix);
  455. $this->view->assign("mid", $mid);
  456. return $this->view->fetch();
  457. }
  458. /*
  459. * 修改字段
  460. */
  461. public function field_edit($ids = NULL) {
  462. //$oldField_info = $this->ModelFields->get($ids);
  463. $field_info = $this->ModelFields->get($ids);
  464. $oldField_info = $field_info->toArray();
  465. //var_dump($field_info);
  466. if (!$field_info)
  467. $this->error(__('No Results were found'));
  468. $mod_table = $this->ModelOnline->get($field_info['mid']);
  469. if (!$mod_table)
  470. $this->error(__('No Results were found'));
  471. if ($this->request->isPost()) {
  472. $params = $this->request->post("row/a");
  473. if ($params) {
  474. try {
  475. //是否采用模型验证
  476. if ($this->modelValidate) {
  477. $name = str_replace("\\model\\", "\\validate\\", get_class($this->ModelFields));
  478. $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate;
  479. $this->ModelFields->validate($validate);
  480. }
  481. $prefix = Config::get('database.prefix');
  482. $field = array();
  483. $fieldData = array();
  484. switch ($field_info['category']) {
  485. case "1":
  486. $allow = array(
  487. "text" => array("suffix" => "text", "type" => "varchar", "length" => 200),
  488. "number" => array("suffix" => "number", "type" => "bigint", "length" => 11),
  489. "time" => array("suffix" => "time", "type" => "bigint", "length" => 11),
  490. "image" => array("suffix" => "image", "type" => "varchar", "length" => 255),
  491. "images" => array("suffix" => "images", "type" => "varchar", "length" => 2000),
  492. "file" => array("suffix" => "file", "type" => "varchar", "length" => 255),
  493. "files" => array("suffix" => "files", "type" => "varchar", "length" => 2000),
  494. "avatar" => array("suffix" => "avatar", "type" => "varchar", "length" => 255),
  495. "avatars" => array("suffix" => "avatars", "type" => "varchar", "length" => 2000),
  496. "content" => array("suffix" => "content", "type" => "text", "length" => 0),
  497. "_id" => array("suffix" => "_id", "type" => "bigint", "length" => 11),
  498. "_ids" => array("suffix" => "_ids", "type" => "varchar", "length" => 255),
  499. "list-enum" => array("suffix" => "list", "type" => "enum", "length" => 0),
  500. "list-set" => array("suffix" => "list", "type" => "set", "length" => 0),
  501. "data-enum" => array("suffix" => "data", "type" => "enum", "length" => 0),
  502. "data-set" => array("suffix" => "data", "type" => "set", "length" => 0),
  503. "json" => array("suffix" => "json", "type" => "varchar", "length" => 2000),
  504. "switch" => array("suffix" => "switch", "type" => "tinyint", "length" => 1),
  505. );
  506. if (isset($allow[$params['suffix']]) && is_array($allow[$params['suffix']])) {
  507. $fieldData['special'] = "";
  508. $fieldData['suffix'] = $params['suffix'];
  509. $field['name'] = $params['name']; //字段名
  510. $field['field'] = $params['name'] . $allow[$params['suffix']]['suffix']; //字段名
  511. $field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['suffix']]['length']; //字段长度
  512. $field['type'] = $allow[$params['suffix']]['type']; //字段类型
  513. $field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值
  514. if ($allow[$params['suffix']]['type'] == "enum" || $allow[$params['suffix']]['type'] == "set") {
  515. $comment = \GuzzleHttp\json_decode($params['comment'], true);
  516. $field['comment'] = $params['title'] . ":"; //备注
  517. $field['length2'] = "";
  518. $str = "";
  519. $default_optional = array();
  520. foreach ($comment as $k => $v) {
  521. $default_optional[] = $k;
  522. $field['comment'] .= $str . $k . "=" . $v;
  523. $field['length2'] .= $str . "'" . $k . "'";
  524. $str = ",";
  525. }
  526. if (!in_array($field['default'], $default_optional)) {
  527. $field['default'] = $default_optional[0];
  528. }
  529. } else {
  530. $params['comment'] = "";
  531. $field['comment'] = $params['title']; //备注
  532. }
  533. } else {
  534. $this->error(__('特殊字段类型不正确!'));
  535. }
  536. break;
  537. case "2":
  538. $allow = array(
  539. "varchar" => array("type" => "varchar", "length" => 255),
  540. "int" => array("type" => "bigint", "length" => 11),
  541. "enum" => array("type" => "enum", "length" => 0),
  542. "set" => array("type" => "set", "length" => 0),
  543. "float" => array("type" => "float", "length" => "10,2"),
  544. "text" => array("type" => "text", "length" => 0),
  545. "datetime" => array("type" => "datetime", "length" => 11),
  546. "date" => array("type" => "date", "length" => 11),
  547. "year" => array("type" => "year", "length" => 4),
  548. "timestamp" => array("type" => "timestamp", "length" => 11),
  549. );
  550. if (isset($allow[$params['type']]) && is_array($allow[$params['type']])) {
  551. $fieldData['special'] = "";
  552. $fieldData['suffix'] = "";
  553. $params['suffix'] = "";
  554. $field['name'] = $params['name']; //字段名
  555. $field['field'] = $params['name']; //字段名
  556. if ($params['type'] == "float") {
  557. $field['length'] = $field['length2'] = isset($params['length']) && $params['length'] ? $params['length'] : $allow[$params['type']]['length']; //字段长度
  558. } else {
  559. $field['length'] = $field['length2'] = isset($params['length']) && intval($params['length']) ? intval($params['length']) : $allow[$params['type']]['length']; //字段长度
  560. }
  561. $field['type'] = $allow[$params['type']]['type']; //字段类型
  562. $field['default'] = isset($params['default']) ? $params['default'] : ""; //默认值
  563. if ($allow[$params['type']]['type'] == "enum" || $allow[$params['type']]['type'] == "set") {
  564. $comment = \GuzzleHttp\json_decode($params['comment'], true);
  565. $field['comment'] = $params['title'] . ":"; //备注
  566. $field['length2'] = "";
  567. $str = "";
  568. $default_optional = array();
  569. foreach ($comment as $k => $v) {
  570. $default_optional[] = $k;
  571. $field['comment'] .= $str . $k . "=" . $v;
  572. $field['length2'] .= $str . "'" . $k . "'";
  573. $str = ",";
  574. }
  575. if (!in_array($field['default'], $default_optional)) {
  576. $field['default'] = $default_optional[0];
  577. }
  578. } else {
  579. $params['comment'] = "";
  580. $field['comment'] = $params['title']; //备注
  581. }
  582. } else {
  583. $this->error(__('特殊字段类型不正确!'));
  584. }
  585. break;
  586. case "3":
  587. $allow = array(
  588. "user_id" => array("title" => "会员ID(单选)", "type" => "bigint", "length" => 11),
  589. "category_id" => array("title" => "分类ID(单选)", "type" => "bigint", "length" => 11),
  590. "category_ids" => array("title" => "分类ID(多选)", "type" => "varchar", "length" => 200),
  591. "weigh" => array("title" => "权重", "type" => "bigint", "length" => 11),
  592. "status" => array("title" => "状态", "type" => "enum", "length" => 0),
  593. "createtime" => array("title" => "创建时间", "type" => "bigint", "length" => 11),
  594. "updatetime" => array("title" => "更新时间", "type" => "bigint", "length" => 11),
  595. "deletetime" => array("title" => "删除时间", "type" => "bigint", "length" => 11),
  596. );
  597. if (isset($allow[$params['special']]) && is_array($allow[$params['special']])) {
  598. $fieldData['special'] = $params['special'];
  599. $fieldData['suffix'] = "";
  600. // $params['title'] = $allow[$params['special']]['title'];
  601. // if ($params['special'] != "status") {
  602. // $params['comment'] = "";
  603. // }
  604. // $params['comment'] =
  605. $params['suffix'] = "";
  606. $field['name'] = $params['special']; //字段名
  607. $field['field'] = $params['special']; //字段名
  608. $field['length'] = $field['length2'] = $allow[$params['special']]['length']; //字段长度
  609. // $field['comment'] = $params['title']; //备注
  610. $field['type'] = $allow[$params['special']]['type']; //字段类型
  611. $field['default'] = $field['type'] == "varchar" ? "" : "0"; //默认值
  612. if ($params['special'] == "status") {
  613. $comment = \GuzzleHttp\json_decode($params['comment'], true);
  614. $field['comment'] = $params['title'] . ":"; //备注
  615. $field['length2'] = "";
  616. $str = "";
  617. $default_optional = array();
  618. foreach ($comment as $k => $v) {
  619. $default_optional[] = $k;
  620. $field['comment'] .= $str . $k . "=" . $v;
  621. $field['length2'] .= $str . "'" . $k . "'";
  622. $str = ",";
  623. }
  624. if (!in_array($field['default'], $default_optional)) {
  625. $field['default'] = $default_optional[0];
  626. }
  627. } else {
  628. $params['comment'] = "";
  629. $field['comment'] = $params['title']; //备注
  630. }
  631. } else {
  632. $this->error(__('特殊字段类型不正确!'));
  633. }
  634. break;
  635. default :
  636. $this->error(__('No Results were found'));
  637. break;
  638. }
  639. /*
  640. if ($this->check($prefix . $mod_table['table'], $field['name'])) {
  641. $this->error(__('字段已经存在!'));
  642. } */
  643. $fieldData['mid'] = $params['mid'];
  644. //$fieldData['category'] = $params['category'];
  645. $fieldData['title'] = $params['title'];
  646. $fieldData['name'] = $field['name'];
  647. $fieldData['field'] = $field['field'];
  648. $fieldData['type'] = $field['type'];
  649. $fieldData['length'] = $field['length'];
  650. $fieldData['default'] = $field['default'];
  651. $fieldData['comment'] = $field['comment'];
  652. $fieldData['desc'] = $params['desc'];
  653. $fieldData['updatetime'] = time();
  654. if ($fieldData['type'] == "text") {
  655. $fieldData['default'] = "";
  656. }
  657. if ($field['type'] == "bigint" || $field['type'] == "int") {
  658. $field['default'] = intval($field['default']);
  659. } elseif ($field['type'] == "tinyint") {
  660. $field['default'] = in_array($field['default'], [0, 1]) ? $field['default'] : 0;
  661. } elseif ($field['type'] == "float") {
  662. $field['default'] = is_float($field['default']) ? $field['default'] : 0;
  663. }
  664. \think\Db::startTrans();
  665. try {
  666. $result = $field_info->save($fieldData);
  667. if ($result !== false) {
  668. //在此执行添加字段的操作
  669. if (in_array($field['type'], ["text", "datetime", "date", "year", "timestamp"])) {
  670. $sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` CHANGE COLUMN `{$oldField_info['field']}` `{$field['field']}` {$field['type']} NOT NULL COMMENT '{$field['comment']}' ;";
  671. } else {
  672. $sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` CHANGE COLUMN `{$oldField_info['field']}` `{$field['field']}` {$field['type']}({$field['length2']}) NOT NULL DEFAULT '{$field['default']}' COMMENT '{$field['comment']}' ;";
  673. }
  674. try {
  675. $res = \think\Db::execute($sql);
  676. } catch (Exception $ex) {
  677. // $field_info->save($oldField_info);
  678. throw new Exception('参数错误,请检查字段名,字段长度或者默认值等输入参数是否合法');
  679. }
  680. } else {
  681. throw new Exception($this->ModelFields->getError());
  682. }
  683. \think\Db::commit();
  684. } catch (Exception $e) {
  685. \think\Db::rollback();
  686. $this->error($e->getMessage());
  687. }
  688. $this->success();
  689. } catch (\think\exception\PDOException $e) {
  690. $field_info->save($oldField_info);
  691. $this->error($e->getMessage());
  692. } catch (\think\Exception $e) {
  693. $field_info->save($oldField_info);
  694. $this->error($e->getMessage());
  695. }
  696. }
  697. $this->error(__('Parameter %s can not be empty', ''));
  698. }
  699. $comment = "";
  700. if ($field_info['type'] == "enum" || $field_info['type'] == "set") {
  701. //echo $field_info['comment'];
  702. $commentStr = substr($field_info['comment'], strpos($field_info['comment'], ":") + 1);
  703. $commentArr = [];
  704. foreach (explode(",", $commentStr) as $k => $v) {
  705. list($key, $val) = explode("=", $v);
  706. $commentArr[$key] = $val;
  707. }
  708. $comment = \json_encode($commentArr);
  709. }
  710. $prefix = Config::get('database.prefix');
  711. $this->view->assign("field_info", $field_info);
  712. $this->view->assign("row", $field_info);
  713. $this->view->assign("prefix", $prefix);
  714. $this->view->assign("comment", $comment);
  715. $this->view->assign("mid", $field_info['mid']);
  716. return $this->view->fetch();
  717. }
  718. public function field_del($ids = NULL) {
  719. if ($ids) {
  720. $pk = $this->ModelFields->getPk();
  721. $adminIds = $this->getDataLimitAdminIds();
  722. if (is_array($adminIds)) {
  723. $count = $this->ModelFields->where($this->dataLimitField, 'in', $adminIds);
  724. }
  725. $list = $this->ModelFields->where($pk, 'in', $ids)->select();
  726. $prefix = Config::get('database.prefix');
  727. $count = 0;
  728. foreach ($list as $k => $v) {
  729. $mod_table = $this->ModelOnline->get($v['mid']);
  730. $sql = "ALTER TABLE `{$prefix}{$mod_table['table']}` DROP `{$v['field']}` ";
  731. try {
  732. $res = \think\Db::execute($sql);
  733. $count += $v->delete();
  734. if ($count) {
  735. $this->success();
  736. } else {
  737. $this->error(__('No rows were deleted'));
  738. }
  739. } catch (Exception $ex) {
  740. $this->error(__('No rows were deleted'));
  741. }
  742. }
  743. }
  744. $this->error(__('Parameter %s can not be empty', 'ids'));
  745. }
  746. public function dictionary() {
  747. $this->db_name = \config("database.database");
  748. $this->db_prefix = \config("database.prefix");
  749. $this->view->assign('db_name', $this->db_name);
  750. $this->view->assign('db_prefix', $this->db_prefix);
  751. $dictionary = [
  752. 'make' => [],
  753. 'system' => [],
  754. 'other' => [],
  755. ];
  756. //读取所有表
  757. $tables_res = Db::table("information_schema.TABLES")->field("TABLE_NAME")->where(['TABLE_SCHEMA' => $this->db_name,])->select();
  758. $tables_all = array_column($tables_res, 'TABLE_NAME');
  759. //已经获取到数据字典的表
  760. $tables_isset = [];
  761. //声明系统表 获取系统表的数据字典
  762. $tables_system = ['admin', 'admin_log', 'attachment', 'area', 'auth_group', 'auth_group_access', 'auth_rule', 'category', 'config', 'ems', 'sms', 'user', 'user_group', 'user_money_log', 'user_rule', 'user_score_log', 'user_token', 'version'];
  763. foreach ($tables_system as $k => $v) {
  764. $table_name = $this->db_prefix . $v;
  765. $dictionary['system'][] = $this->getSystemTableInfo($table_name);
  766. $tables_isset[] = $table_name;
  767. }
  768. //读取自建表 获取自建表数据字典
  769. $tables_make = \app\admin\model\TableMakeTables::all(function ($query) {
  770. $query->order("weigh desc,id desc");
  771. });
  772. foreach ($tables_make as $k => $v) {
  773. $table_name = $this->db_prefix . $v['table'];
  774. $dictionary['make'][] = $this->getMakeTableInfo($table_name, $v);
  775. $tables_isset[] = $table_name;
  776. }
  777. //获取其他表数据字典 求差集,计算出其他表
  778. $tables_other = array_diff($tables_all, $tables_isset);
  779. foreach ($tables_other as $k => $v) {
  780. $table_name = $v;
  781. $dictionary['other'][] = $this->getOtherTableInfo($table_name);
  782. $tables_isset[] = $table_name;
  783. }
  784. $this->view->assign('dictionary', $dictionary);
  785. $this->view->engine->layout(false);
  786. return $this->view->fetch();
  787. }
  788. /**
  789. * 根据表名获取系统表的数据字典数据
  790. * @param $table_name 表名
  791. * @return array
  792. */
  793. protected function getSystemTableInfo($table_name) {
  794. return $this->getOtherTableInfo($table_name);
  795. }
  796. /**
  797. * 根据表名获取非自建表的数据字典信息
  798. * @param $table_name
  799. * @return array
  800. */
  801. protected function getOtherTableInfo($table_name) {
  802. $table_info = $this->getTableInfo($table_name);
  803. $result = [
  804. 'name' => $table_info['table_info']['TABLE_COMMENT'] ? $table_info['table_info']['TABLE_COMMENT'] : $table_name,
  805. 'table' => preg_replace('/^(' . $this->db_prefix . ').*?/is', '', $table_name),//表名去前缀
  806. 'table_name' => $table_name,
  807. 'desc' => $table_info['table_info']['TABLE_COMMENT'],
  808. 'engine' => $table_info['table_info']['ENGINE'],
  809. 'table_comment' => $table_info['table_info']['TABLE_COMMENT'],
  810. 'table_collation' => $table_info['table_info']['TABLE_COLLATION'],
  811. 'create_time' => $table_info['table_info']['CREATE_TIME'],
  812. 'update_time' => $table_info['table_info']['UPDATE_TIME'],
  813. 'fields' => $this->getTableFields($table_info['table_fields']),
  814. ];
  815. return $result;
  816. }
  817. /**
  818. * 根据表名、自建表信息数据,获取自建表的数据字典信息
  819. * @param $table_name 表名
  820. * @param $table
  821. * @return array
  822. * @throws \think\exception\DbException
  823. */
  824. protected function getMakeTableInfo($table_name, $table) {
  825. $model_fields = \app\admin\model\TableMakeFields::all(function ($query) use ($table) {
  826. $query->where(['mid' => $table['id']]);
  827. $query->order("weigh desc,id desc");
  828. });
  829. $result = $this->getOtherTableInfo($table_name);
  830. $result['name'] = $table['name'];
  831. $result['table'] = $table['table'];
  832. $result['desc'] = $table['desc'];
  833. $result['create_time'] = date("Y-m-d H:i:s", $table['createtime']);
  834. $result['update_time'] = date("Y-m-d H:i:s", $table['updatetime']);
  835. $result['fields'] = $this->getTableFieldsByMake($result['fields'], $model_fields);
  836. return $result;
  837. }
  838. /**
  839. * 结合表的字段备注 自建表存储的信息,生成自建表的字段数据字典
  840. * @param $fields
  841. * @param array $make_fields
  842. * @return array
  843. */
  844. protected function getTableFieldsByMake($fields, $make_fields = []) {
  845. $result = [];
  846. $field_list = [];
  847. foreach ($fields as $k => $v) {
  848. $field_list[$v['field_name']] = $v;
  849. }
  850. $result[] = $field_list['id'];
  851. foreach ($make_fields as $k => $v) {
  852. $result[] = [
  853. "field_title" => $v['title'],
  854. "field_name" => $v['field'],
  855. "character" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['character'] : NULL,
  856. "field_collation" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['field_collation'] : NULL,
  857. "data_type" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['data_type'] : NULL,//字段类型
  858. "column_type" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['column_type'] : NULL,//列类型
  859. "is_nullable" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['is_nullable'] : NULL,//是否能为空
  860. "length" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['length'] : NULL,//字符串长度
  861. "column_comment" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['column_comment'] : NULL,//字段备注
  862. "default" => isset($field_list[$v['field']]) ? $field_list[$v['field']]['default'] : NULL,//字段默认值
  863. "desc" => $v['desc'],
  864. ];
  865. }
  866. return $result;
  867. }
  868. /**
  869. * 根据表的字段备注,生成字段数据字典
  870. * @param $fields
  871. * @return array
  872. */
  873. protected function getTableFields($fields) {
  874. $result = [];
  875. foreach ($fields as $k => $v) {
  876. $column_type = preg_replace('/(unsigned).*?/is', '(无符号)', $v['COLUMN_TYPE']);
  877. list($field_name) = explode(":", $v['COLUMN_COMMENT']);
  878. $result[] = [
  879. "field_title" => $field_name ? $field_name : $v['COLUMN_NAME'],
  880. "field_name" => $v['COLUMN_NAME'],
  881. "character" => $v['CHARACTER_SET_NAME'],
  882. "field_collation" => $v['COLLATION_NAME'],
  883. "data_type" => $v['DATA_TYPE'],//字段类型
  884. "column_type" => $column_type,//列类型
  885. "is_nullable" => $v['IS_NULLABLE'],//是否能为空
  886. "length" => $v['CHARACTER_MAXIMUM_LENGTH'],//字符串长度
  887. "column_comment" => $v['COLUMN_COMMENT'],//字段备注
  888. "default" => $v['COLUMN_DEFAULT'],//字段默认值
  889. "desc" => "",//字段默认值
  890. ];
  891. }
  892. return $result;
  893. }
  894. /**
  895. * 获取指定表的基本信息
  896. * @param $table_name
  897. * @return array
  898. * @throws \think\db\exception\DataNotFoundException
  899. * @throws \think\db\exception\ModelNotFoundException
  900. * @throws \think\exception\DbException
  901. */
  902. protected function getTableInfo($table_name) {
  903. // //读取表信息
  904. // $sql = "SELECT * FROM information_schema.TABLES WHERE table_schema = '{$db_name}' and TABLE_NAME='{$table_name}'";
  905. // $res = Db::query($sql);
  906. // //读取表结构
  907. // $sql = "SELECT * FROM information_schema.COLUMNS where table_schema ='{$db_name}' and TABLE_NAME = '{$table_name}'";
  908. // $res = Db::query($sql);
  909. //读取表信息
  910. $table_info = Db::table("information_schema.TABLES")->field("*")->where(['TABLE_SCHEMA' => $this->db_name, 'TABLE_NAME' => $table_name])->find();
  911. //读取表结构
  912. $table_fields = Db::table("information_schema.COLUMNS")->field("*")->where(['TABLE_SCHEMA' => $this->db_name, 'TABLE_NAME' => $table_name])->select();
  913. return [
  914. 'table_info' => $table_info,
  915. 'table_fields' => $table_fields,
  916. ];
  917. }
  918. }