ModelFields.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. <?php
  2. namespace app\common\model\base\models;
  3. /**
  4. * @title : 模型字段管理
  5. * @desc :
  6. * @Author : Rock
  7. * @Date : 2023-04-11 20:02:23
  8. */
  9. use app\common\model\Common;
  10. use think\facade\Db;
  11. use think\model\concern\SoftDelete;
  12. class ModelFields extends Common
  13. {
  14. // use SoftDelete;
  15. protected $name = "system_auto_model_field";
  16. protected $pk = "field_id";
  17. protected $json = ['content'];
  18. protected $jsonAssoc = true;
  19. protected $append = ['field_type_txt','show_in_table_txt','search_type_txt','status_txt','content_txt','extra_rule_txt','test_value'];
  20. protected $schema = [
  21. 'field_id'=>'int',
  22. 'model_name'=>'varchar',
  23. 'model_title'=>'varchar',
  24. 'title'=>'varchar',
  25. 'field'=>'varchar',
  26. 'field_type'=>'enum',
  27. 'db_type'=>'varchar',
  28. 'len'=>'int',
  29. 'show_in_table'=>'tinyint',
  30. 'search_type'=>'enum',
  31. 'status'=>'tinyint',
  32. 'weigh'=>'int',
  33. 'rule'=>'varchar',
  34. 'content'=>'varchar',
  35. 'create_at'=>'datetime',
  36. 'update_at'=>'datetime',
  37. 'delete_at'=>'datetime',
  38. 'default_value'=>'varchar',
  39. 'extra_rule'=>'text',
  40. 'is_relation'=>'tinyint',
  41. 'relation_model'=>'varchar',
  42. 'relation_field'=>'varchar',
  43. 'relation_show'=>'varchar',
  44. 'relation_dic_group'=>'varchar',
  45. 'auto_methods'=>'text',
  46. ];
  47. static public function fieldTypeList()
  48. {
  49. return [
  50. 'string' => '单行文本',
  51. 'text' => '多行文本',
  52. 'editor' => '编辑器',
  53. 'number' => '数字',
  54. 'year' => '年度',
  55. 'month' => '月份',
  56. 'date' => '日期',
  57. 'time' => '时间',
  58. 'datetime' => '日期时间',
  59. 'datetimerange' => '日期时间区间',
  60. 'select' => '列表',
  61. 'selects' => '列表(多选)',
  62. 'image' => '单图',
  63. 'images' => '多图',
  64. 'file' => '单文件',
  65. 'files' => '多文件',
  66. 'switch' => '开关',
  67. 'checkbox' => '复选',
  68. 'radio' => '单选',
  69. 'color' => '颜色',
  70. 'json' => 'JSON数组',
  71. 'slider' => '滑块',
  72. 'relate_self'=>'关联自身',
  73. 'relate_dic'=>'关联字典',
  74. 'relate_single'=>'关联单选',
  75. 'relate_multiple'=>'关联多选',
  76. 'user_auto'=>'用户(自动)',
  77. 'org_auto'=>'组织(自动)',
  78. 'user_select'=>'用户(选择)',
  79. 'org_select'=>'组织(选择)',
  80. ];
  81. }
  82. public function getTestValueAttr($value,$row)
  83. {
  84. $extra_rule = !empty($row['extra_rule'])?json_decode($row['extra_rule'],true):[];
  85. $extra_rule = array_column($extra_rule,'value','key');
  86. if(in_array($row['field_type'],['selects','checkbox','images','files','relate_multiple'])){
  87. return [];
  88. }elseif(in_array($row['field_type'],['user_select','org_select','relate_dic']) && isset($extra_rule['multiple']) && ($extra_rule['multiple']==='true' || $extra_rule['multiple']===true)){
  89. return [];
  90. }elseif(in_array($row['db_type'],['tinyint','smallint','mediumint','int','bigint','double','float','decimal','timestamp'])){
  91. return 0;
  92. }else{
  93. return '';
  94. }
  95. }
  96. public function getFieldTypeTxtAttr($value,$row)
  97. {
  98. $fieldTypeList = self::fieldTypeList();
  99. return $fieldTypeList[$value ?? $row['field_type']] ?? '';
  100. }
  101. static public function dbTypeList()
  102. {
  103. return [
  104. 'tinyint','smallint','mediumint','int','bigint','double','float','decimal','char','varchar','date','time','year','timestamp','datetime','text','longtext','enum','set','json'
  105. ];
  106. }
  107. static public function showInTableList()
  108. {
  109. return [1=>'显示',2=>'不显示'];
  110. }
  111. public function getShowInTableTxtAttr($value,$row)
  112. {
  113. $showInTableList = self::showInTableList();
  114. return $showInTableList[$value ?? $row['show_in_table']] ?? '';
  115. }
  116. static public function searchTypeList()
  117. {
  118. return ['none'=>'无搜索','list'=>'下拉列表','keyword'=>'关键字','year'=>'年度','month'=>'月份','date'=>'日期','daterange'=>'日期范围','datetime'=>'日期时间','datetimerange'=>'日期时间范围','relation'=>'关联筛选'];
  119. }
  120. public function getSearchTypeTxtAttr($value,$row)
  121. {
  122. $searchTypeList = self::searchTypeList();
  123. return $searchTypeList[$value ?? $row['search_type']] ?? '';
  124. }
  125. static public function statusList()
  126. {
  127. return [1=>'启用',2=>'停用'];
  128. }
  129. public function getStatusTxtAttr($value,$row)
  130. {
  131. $statusList = self::statusList();
  132. return $statusList[$value ?? $row['status']] ?? '';
  133. }
  134. public function setModelTitleAttr($value,$row)
  135. {
  136. $title = ModelManage::where('name',$row['model_name'])->value('title');
  137. return $title;
  138. }
  139. // 配置选项content文本获取器
  140. public function getContentTxtAttr($value,$data)
  141. {
  142. if(!empty($data['content'])){
  143. $contentAry = [];
  144. foreach($data['content'] as $content){
  145. $contentAry[] = $content['key'].'|'.$content['value'];
  146. }
  147. return implode("\n",$contentAry);
  148. }
  149. return $value;
  150. }
  151. // 配置选项content修改器
  152. public function setContentAttr($value,$data)
  153. {
  154. if(!empty($data['content_txt'])){
  155. $contentAry = explode("\n",$data['content_txt']);
  156. $contentAry = array_filter($contentAry);
  157. $newContent = [];
  158. foreach($contentAry as $item){
  159. $itemAry = explode('|',$item);
  160. $key = $itemAry[0];
  161. $value = $itemAry[1];
  162. $newContent[] = ['key'=>$key,'value'=>$value];
  163. }
  164. return json_encode($newContent);
  165. }
  166. return $value;
  167. }
  168. // 组件属性修改器
  169. public function setExtraRuleAttr($value,$data)
  170. {
  171. if(!empty($data['extra_rule_txt'])){
  172. $contentAry = explode("\n",$data['extra_rule_txt']);
  173. $contentAry = array_filter($contentAry);
  174. $newContent = [];
  175. foreach($contentAry as $item){
  176. $itemAry = explode('|',$item);
  177. $key = $itemAry[0];
  178. $value = $itemAry[1]??'';
  179. $newContent[] = ['key'=>$key,'value'=>$value];
  180. }
  181. $value = json_encode($newContent);
  182. }else{
  183. $value = null;
  184. }
  185. return $value;
  186. }
  187. // 组件属性获取器
  188. public function getExtraRuleAttr($value,$data)
  189. {
  190. $value = $value??$data['extra_rule']??[];
  191. $value = is_string($value)?json_decode($value,true):$value;
  192. $res = [];
  193. foreach($value as $item){
  194. if($item['value']=='true'){
  195. $val = true;
  196. }elseif($item['value']=='false'){
  197. $val = false;
  198. }elseif(in_array($item['key'],['min','max','step'])){
  199. $val = floatval($item['value']);
  200. }else{
  201. $val = $item['value'];
  202. }
  203. $res[$item['key']] = $val;
  204. }
  205. return $res;
  206. }
  207. // 组件属性文本获取器
  208. public function getExtraRuleTxtAttr($value,$data)
  209. {
  210. if(!empty($data['extra_rule'])){
  211. $contentAry = [];
  212. $extra_rule = is_string($data['extra_rule'])?json_decode($data['extra_rule'],true):$data['extra_rule'];
  213. foreach($extra_rule as $content){
  214. $contentAry[] = $content['key'].'|'.$content['value'];
  215. }
  216. return implode("\n",$contentAry);
  217. }
  218. return $value;
  219. }
  220. // 规则修改器
  221. public function setRuleAttr($value,$data)
  222. {
  223. $value = $value??$data['rule']??'';
  224. return empty($value)||$value=='null'?'':$value;
  225. }
  226. //触发自动关联的方法修改器
  227. public function setAutoMethodsAttr($value,$data)
  228. {
  229. $value = $value??$data['auto_methods']??[];
  230. $value = array_filter($value);
  231. return implode(',',$value);
  232. }
  233. //触发自动关联的方法获取器
  234. public function getAutoMethodsAttr($value,$data)
  235. {
  236. $value = $value??$data['auto_methods']??'';
  237. $res = explode(',',$value);
  238. return array_filter($res);
  239. }
  240. /**
  241. * @title: 添加字段
  242. * @desc: 描述
  243. * @param {string} $tblName
  244. * @param {int} $id
  245. * @return {*}
  246. * @author: Rock
  247. * @method: POST
  248. * @Date: 2023-04-17 14:14:06
  249. */
  250. static public function addField(int $id)
  251. {
  252. $info = self::find($id);
  253. $tblName = $info->getAttr('model_name');
  254. $field = $info->getAttr('field');
  255. $title = $info->getAttr('title');
  256. $dbType = $info->getAttr('db_type');
  257. $len = $info->getAttr('len');
  258. $defaultVal = $info->getAttr('default_value')??NULL;
  259. if($dbType=='enum'){
  260. $len = "'".implode('\',\'',array_column($info->content,'key'))."'";
  261. if(!empty($defaultVal)){
  262. $sql = "ALTER TABLE $tblName ADD $field $dbType($len) DEFAULT '$defaultVal' COMMENT '$title'";
  263. }else{
  264. $sql = "ALTER TABLE $tblName ADD $field $dbType($len) COMMENT '$title'";
  265. }
  266. }elseif(in_array($dbType,['date','datetime','year'])){
  267. if(!empty($defaultVal)){
  268. $sql = "ALTER TABLE $tblName ADD $field $dbType DEFAULT '$defaultVal' COMMENT '$title'";
  269. }else{
  270. $sql = "ALTER TABLE $tblName ADD $field $dbType DEFAULT NULL COMMENT '$title'";
  271. }
  272. }elseif(!in_array($dbType,['text','blob','json','geometry'])){
  273. $sql = "ALTER TABLE $tblName ADD $field $dbType($len) DEFAULT '$defaultVal' COMMENT '$title'";
  274. }else{
  275. $sql = "ALTER TABLE $tblName ADD $field $dbType($len) COMMENT '$title'";
  276. }
  277. $res = Db::execute($sql);
  278. return $res;
  279. }
  280. /**
  281. * @title: 添加为数据表多个字段
  282. * @desc: 描述
  283. * @param {string} {tblName} {} {数据表名}
  284. * @param {array} {fields} {} {字段数组}
  285. * @return {*}
  286. * @author: Rock
  287. * @method: POST
  288. * @Date: 2023-08-29 16:53:23
  289. */
  290. static public function addFields(string $tblName,array $fields)
  291. {
  292. $list = self::where('model_name',$tblName)->where('field','IN',$fields)->select();
  293. $sql = "ALTER TABLE $tblName ";
  294. $fieldList = [];
  295. foreach($list as $item){
  296. $field = $item->getAttr('field');
  297. $title = $item->getAttr('title');
  298. $dbType = $item->getAttr('db_type');
  299. $len = $item->getAttr('len');
  300. $defaultVal = $item->getAttr('default_value')??NULL;
  301. if($dbType=='enum'){
  302. $len = "'".implode('\',\'',array_column($item->content,'key'))."'";
  303. if(!empty($defaultVal)){
  304. $fieldList[] = "ADD $field $dbType($len) DEFAULT '$defaultVal' COMMENT '$title'";
  305. }else{
  306. $fieldList[] = "ADD $field $dbType($len) COMMENT '$title'";
  307. }
  308. }elseif(in_array($dbType,['date','datetime','year'])){
  309. if(!empty($defaultVal)){
  310. $fieldList[] = "ADD $field $dbType DEFAULT '$defaultVal' COMMENT '$title'";
  311. }else{
  312. $fieldList[] = "ADD $field $dbType DEFAULT NULL COMMENT '$title'";
  313. }
  314. }elseif(!in_array($dbType,['text','blob','json','geometry'])){
  315. $fieldList[] = "ADD $field $dbType($len) DEFAULT '$defaultVal' COMMENT '$title'";
  316. }else{
  317. $fieldList[] = "ADD $field $dbType($len) COMMENT '$title'";
  318. }
  319. }
  320. $sql .= implode(',',$fieldList);
  321. $res = Db::execute($sql);
  322. return $res;
  323. }
  324. /**
  325. * @title: 修改信息
  326. * @desc: 描述
  327. * @param {int} {id} {} {模型字段ID(field_id)}
  328. * @param {string} {oldFeild} {} {原字段名}
  329. * @return {*}
  330. * @author: Rock
  331. * @method: POST
  332. * @Date: 2023-04-17 19:52:48
  333. */
  334. static public function updateField(int $id,string $oldField)
  335. {
  336. $info = self::find($id);
  337. $tblName = $info->getAttr('model_name');
  338. $field = $info->getAttr('field');
  339. $dbType = $info->getAttr('db_type');
  340. $len = $info->getAttr('len');
  341. $title = $info->getAttr('title');
  342. $defaultVal = $info->getAttr('default_value');
  343. // 检查旧字段是否存在
  344. $sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='$tblName' AND column_name='$oldField'";
  345. $res = Db::query($sql);
  346. if(!$res || count($res)==0){
  347. return self::addField($id);
  348. }
  349. if($dbType=='enum'){
  350. $len = "'".implode('\',\'',array_column($info->content,'key'))."'";
  351. if(!empty($defaultVal)){
  352. $sql = "ALTER TABLE $tblName CHANGE $oldField $field $dbType($len) DEFAULT '$defaultVal' COMMENT '$title'";
  353. }else{
  354. $sql = "ALTER TABLE $tblName CHANGE $oldField $field $dbType($len) COMMENT '$title'";
  355. }
  356. }elseif(in_array($dbType,['date','datetime','year'])){
  357. if(!empty($defaultVal)){
  358. $sql = "ALTER TABLE $tblName CHANGE $oldField $field $dbType DEFAULT '$defaultVal' COMMENT '$title'";
  359. }else{
  360. $sql = "ALTER TABLE $tblName CHANGE $oldField $field $dbType DEFAULT NULL COMMENT '$title'";
  361. }
  362. }elseif(!in_array($dbType,['text','blob','json','geometry'])){
  363. $sql = "ALTER TABLE $tblName CHANGE $oldField $field $dbType($len) DEFAULT '$defaultVal' COMMENT '$title'";
  364. }else{
  365. $sql = "ALTER TABLE $tblName CHANGE $oldField $field $dbType($len) COMMENT '$title'";
  366. }
  367. $res = Db::execute($sql);
  368. return $res;
  369. }
  370. /**
  371. * @title: 删除字段
  372. * @desc: 描述
  373. * @param {int} {id} {} {模型字段ID(field_id)}
  374. * @return {*}
  375. * @author: Rock
  376. * @method: POST
  377. * @Date: 2023-04-17 20:37:53
  378. */
  379. static public function deleteField(int $id)
  380. {
  381. $info = self::find($id);
  382. $tblName = $info->getAttr('model_name');
  383. $field = $info->getAttr('field');
  384. // 检查旧字段是否存在
  385. $sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='$tblName' AND column_name='$field'";
  386. $res = Db::query($sql);
  387. if($res && count($res)>0){
  388. $sql = "ALTER TABLE $tblName DROP COLUMN $field";
  389. $res = Db::execute($sql);
  390. }
  391. return $res;
  392. }
  393. /**
  394. * @title: 删除多个字段
  395. * @desc: 描述
  396. * @param {string} {model_name} {} {模型字段ID数组}
  397. * @param {array} {fields} {} {模型字段数组}
  398. * @return {*}
  399. * @author: Rock
  400. * @method: POST
  401. * @Date: 2023-08-29 15:46:49
  402. */
  403. static public function deleteFields(string $model_name,array $fields)
  404. {
  405. // 查询已存在的字段
  406. $oldSql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='$model_name' AND column_name IN ('".implode('\',\'',$fields)."');";
  407. $res = Db::query($oldSql);
  408. $oldList = array_column($res,'COLUMN_NAME');
  409. $sql = "ALTER TABLE $model_name ";
  410. $dropList = [];
  411. foreach($fields as $field){
  412. if(in_array($field,$oldList)){
  413. $dropList[] = "DROP COLUMN $field";
  414. }
  415. }
  416. if(!empty($dropList)){
  417. $sql .= implode(',',$dropList);
  418. $sql .= ";";
  419. $res = Db::execute($sql);
  420. return $res;
  421. }
  422. return true;
  423. }
  424. }