Field.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 海豚PHP框架 [ DolphinPHP ]
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://dolphinphp.com
  8. // +----------------------------------------------------------------------
  9. // | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
  10. // +----------------------------------------------------------------------
  11. namespace app\cms\admin;
  12. use app\admin\controller\Admin;
  13. use app\common\builder\ZBuilder;
  14. use app\cms\model\Model;
  15. use app\cms\model\Field as FieldModel;
  16. use think\Db;
  17. /**
  18. * 字段管理控制器
  19. * @package app\cms\admin
  20. */
  21. class Field extends Admin
  22. {
  23. /**
  24. * 字段列表
  25. * @param null $id 文档模型id
  26. * @author 蔡伟明 <314013107@qq.com>
  27. */
  28. public function index($id = null)
  29. {
  30. $id === null && $this->error('参数错误');
  31. cookie('__forward__', $_SERVER['REQUEST_URI']);
  32. // 查询
  33. $map = $this->getMap();
  34. $map['model'] = $id;
  35. // 数据列表
  36. $data_list = FieldModel::where($map)->order('id desc')->paginate();
  37. // 使用ZBuilder快速创建数据表格
  38. return ZBuilder::make('table')
  39. ->setSearch(['name' => '名称', 'title' => '标题']) // 设置搜索框
  40. ->setPageTips('【显示】表示新增或编辑文档时是否显示该字段<br>【启用】表示前台是否显示')
  41. ->addColumns([ // 批量添加数据列
  42. ['id', 'ID'],
  43. ['name', '名称'],
  44. ['title', '标题'],
  45. ['type', '类型', 'text', '', config('form_item_type')],
  46. ['create_time', '创建时间', 'datetime'],
  47. ['sort', '排序', 'text.edit'],
  48. ['show', '显示', 'switch'],
  49. ['status', '启用', 'switch'],
  50. ['right_button', '操作', 'btn']
  51. ])
  52. ->addTopButton('back', ['href' => url('model/index')]) // 批量添加顶部按钮
  53. ->addTopButton('add', ['href' => url('add', ['model' => $id])]) // 添加顶部按钮
  54. ->addTopButtons('enable,disable') // 批量添加顶部按钮
  55. ->addRightButtons('edit,delete') // 批量添加右侧按钮
  56. ->replaceRightButton(['fixed' => 1], '<button class="btn btn-danger btn-xs" type="button" disabled>固定字段禁止操作</button>')
  57. ->setRowList($data_list) // 设置表格数据
  58. ->fetch(); // 渲染模板
  59. }
  60. /**
  61. * 新增字段
  62. * @param string $model 文档模型id
  63. * @author 蔡伟明 <314013107@qq.com>
  64. * @return mixed
  65. */
  66. public function add($model = '')
  67. {
  68. // 内容模型类别[0-系统,1-普通,2-独立]
  69. $model_type = get_model_type($model);
  70. if ($this->request->isPost()) {
  71. // 表单数据
  72. $data = $this->request->post();
  73. // 非独立模型需验证字段名称是否为aid
  74. if ($model_type != 2) {
  75. // 非独立模型需验证新增的字段是否被系统占用
  76. if ($data['name'] == 'aid' || is_default_field($data['name'])) {
  77. $this->error('字段名称已存在');
  78. }
  79. }
  80. $result = $this->validate($data, 'Field');
  81. if(true !== $result) $this->error($result);
  82. // 如果是快速联动
  83. switch ($data['type']) {
  84. case 'linkages':
  85. $data['key'] = $data['key'] == '' ? 'id' : $data['key'];
  86. $data['pid'] = $data['pid'] == '' ? 'pid' : $data['pid'];
  87. $data['level'] = $data['level'] == '' ? '2' : $data['level'];
  88. $data['option'] = $data['option'] == '' ? 'name' : $data['option'];
  89. break;
  90. case 'number':
  91. $data['type'] = 'text';
  92. break;
  93. case 'bmap':
  94. $data['level'] = !$data['level'] ? 12 : $data['level'];
  95. break;
  96. }
  97. if ($field = FieldModel::create($data)) {
  98. $FieldModel = new FieldModel();
  99. // 添加字段
  100. if ($FieldModel->newField($data)) {
  101. // 记录行为
  102. $details = '详情:文档模型('.get_model_title($data['model']).')、字段名称('.$data['name'].')、字段标题('.$data['title'].')、字段类型('.$data['type'].')';
  103. action_log('field_add', 'cms_field', $field['id'], UID, $details);
  104. // 清除缓存
  105. cache('cms_system_fields', null);
  106. $this->success('新增成功', cookie('__forward__'));
  107. } else {
  108. // 添加失败,删除新增的数据
  109. FieldModel::destroy($field['id']);
  110. $this->error($FieldModel->getError());
  111. }
  112. } else {
  113. $this->error('新增失败');
  114. }
  115. }
  116. if ($model_type != 2) {
  117. $field_exist = Db::name('cms_field')->where('model', 'in', [0, $model])->column('name');
  118. $field_exist[] = 'aid';
  119. } else {
  120. $field_exist = ['id','cid','uid','title','model','create_time','update_time','sort','status','view','trash'];
  121. }
  122. // 显示添加页面
  123. return ZBuilder::make('form')
  124. ->setPageTips('以下字段名称已存在,请不要建立同名的字段:<br>'. implode('、', $field_exist))
  125. ->addFormItems([
  126. ['hidden', 'model', $model],
  127. ['text', 'name', '字段名称', '由小写英文字母和下划线组成'],
  128. ['text', 'title', '字段标题', '可填写中文'],
  129. ['select', 'type', '字段类型', '', config('form_item_type')],
  130. ['text', 'define', '字段定义', '可根据实际需求自行填写或修改,但必须是正确的sql语法'],
  131. ['text', 'value', '字段默认值'],
  132. ['textarea', 'options', '额外选项', '用于单选、多选、下拉、联动等类型'],
  133. ['text', 'ajax_url', '异步请求地址', "如请求的地址是 <code>url('ajax/getCity')</code>,那么只需填写 <code>ajax/getCity</code>,或者直接填写以 <code>http</code>开头的url地址"],
  134. ['text', 'next_items', '下一级联动下拉框的表单名', "与当前有关联的下级联动下拉框名,多个用逗号隔开,如:area,other"],
  135. ['text', 'param', '请求参数名', "联动下拉框请求参数名,默认为配置名称"],
  136. ['text', 'level', '级别', '如果类型为【快速联动下拉框】则表示需要显示的级别数量,默认为2。如果类型为【百度地图】,则表示地图默认缩放级别,建议设置为12', 2],
  137. ['text', 'table', '表名', '要查询的表,里面必须含有id、name、pid三个字段,其中id和name字段可在下面重新定义'],
  138. ['text', 'pid', '父级id字段名', '即表中的父级ID字段名,如果表中的主键字段名为pid则可不填写'],
  139. ['text', 'key', '键字段名', '即表中的主键字段名,如果表中的主键字段名为id则可不填写'],
  140. ['text', 'option', '值字段名', '下拉菜单显示的字段名,如果表中的该字段名为name则可不填写'],
  141. ['text', 'ak', 'APPKEY', '百度编辑器APPKEY'],
  142. ['text', 'format', '格式'],
  143. ['textarea', 'tips', '字段说明', '字段补充说明'],
  144. ['radio', 'fixed', '是否为固定字段', '如果为 <code>固定字段</code> 则添加后不可修改', ['否', '是'], 0],
  145. ['radio', 'show', '是否显示', '新增或编辑时是否显示该字段', ['否', '是'], 1],
  146. ['radio', 'status', '立即启用', '', ['否', '是'], 1],
  147. ['text', 'sort', '排序', '', 100],
  148. ])
  149. ->setTrigger('type', 'linkage', 'ajax_url,next_items,param')
  150. ->setTrigger('type', 'linkages', 'table,pid,key,option')
  151. ->setTrigger('type', 'bmap', 'ak')
  152. ->setTrigger('type', 'linkages,bmap', 'level')
  153. ->setTrigger('type', 'masked,date,time,datetime', 'format')
  154. ->setTrigger('type', 'checkbox,radio,array,select,linkage,linkages', 'options')
  155. ->js('field')
  156. ->fetch();
  157. }
  158. /**
  159. * 编辑字段
  160. * @param null $id 字段id
  161. * @author 蔡伟明 <314013107@qq.com>
  162. * @return mixed
  163. */
  164. public function edit($id = null)
  165. {
  166. if ($id === null) $this->error('参数错误');
  167. // 保存数据
  168. if ($this->request->isPost()) {
  169. // 表单数据
  170. $data = $this->request->post();
  171. // 验证
  172. $result = $this->validate($data, 'Field');
  173. if(true !== $result) $this->error($result);
  174. // 如果是快速联动
  175. if ($data['type'] == 'linkages') {
  176. $data['key'] = $data['key'] == '' ? 'id' : $data['key'];
  177. $data['pid'] = $data['pid'] == '' ? 'pid' : $data['pid'];
  178. $data['level'] = $data['level'] == '' ? '2' : $data['level'];
  179. $data['option'] = $data['option'] == '' ? 'name' : $data['option'];
  180. }
  181. // 如果是百度地图
  182. if ($data['type'] == 'bmap') {
  183. $data['level'] = !$data['level'] ? 12 : $data['level'];
  184. }
  185. // 更新字段信息
  186. $FieldModel = new FieldModel();
  187. if ($FieldModel->updateField($data)) {
  188. if ($FieldModel->isUpdate(true)->save($data)) {
  189. // 记录行为
  190. action_log('field_edit', 'cms_field', $id, UID, $data['name']);
  191. $this->success('字段更新成功', cookie('__forward__'));
  192. }
  193. }
  194. $this->error('字段更新失败');
  195. }
  196. // 获取数据
  197. $info = FieldModel::get($id);
  198. // 显示编辑页面
  199. return ZBuilder::make('form')
  200. ->addFormItems([
  201. ['hidden', 'id'],
  202. ['hidden', 'model'],
  203. ['text', 'name', '字段名称', '由小写英文字母和下划线组成'],
  204. ['text', 'title', '字段标题', '可填写中文'],
  205. ['select', 'type', '字段类型', '', config('form_item_type')],
  206. ['text', 'define', '字段定义', '可根据实际需求自行填写或修改,但必须是正确的sql语法'],
  207. ['text', 'value', '字段默认值'],
  208. ['textarea', 'options', '额外选项', '用于单选、多选、下拉、联动等类型'],
  209. ['text', 'ajax_url', '异步请求地址', "如请求的地址是 <code>url('ajax/getCity')</code>,那么只需填写 <code>ajax/getCity</code>,或者直接填写以 <code>http</code>开头的url地址"],
  210. ['text', 'next_items', '下一级联动下拉框的表单名', "与当前有关联的下级联动下拉框名,多个用逗号隔开,如:area,other"],
  211. ['text', 'param', '请求参数名', "联动下拉框请求参数名,默认为配置名称"],
  212. ['text', 'level', '级别', '如果类型为【快速联动下拉框】则表示需要显示的级别数量,默认为2。如果类型为【百度地图】,则表示地图默认缩放级别,建议设置为12'],
  213. ['text', 'table', '表名', '要查询的表,里面必须含有id、name、pid三个字段,其中id和name字段可在下面重新定义'],
  214. ['text', 'pid', '父级id字段名', '即表中的父级ID字段名,如果表中的主键字段名为pid则可不填写'],
  215. ['text', 'key', '键字段名', '即表中的主键字段名,如果表中的主键字段名为id则可不填写'],
  216. ['text', 'option', '值字段名', '下拉菜单显示的字段名,如果表中的该字段名为name则可不填写'],
  217. ['text', 'ak', 'APPKEY', '百度编辑器APPKEY'],
  218. ['text', 'format', '格式'],
  219. ['textarea', 'tips', '字段说明', '字段补充说明'],
  220. ['radio', 'show', '是否显示', '新增或编辑时是否显示该字段', ['否', '是']],
  221. ['radio', 'status', '立即启用', '', ['否', '是']],
  222. ['text', 'sort', '排序'],
  223. ])
  224. ->setTrigger('type', 'linkage', 'ajax_url,next_items,param')
  225. ->setTrigger('type', 'linkages', 'table,pid,key,option')
  226. ->setTrigger('type', 'bmap', 'ak')
  227. ->setTrigger('type', 'linkages,bmap', 'level')
  228. ->setTrigger('type', 'masked,date,time,datetime', 'format')
  229. ->setTrigger('type', 'checkbox,radio,array,select,linkage,linkages', 'options')
  230. ->js('field')
  231. ->setFormData($info)
  232. ->fetch();
  233. }
  234. /**
  235. * 删除字段
  236. * @param null $ids 字段id
  237. * @author 蔡伟明 <314013107@qq.com>
  238. * @return mixed
  239. */
  240. public function delete($ids = null)
  241. {
  242. if ($ids === null) $this->error('参数错误');
  243. $FieldModel = new FieldModel();
  244. $field = $FieldModel->where('id', $ids)->find();
  245. if ($FieldModel->deleteField($field)) {
  246. if ($FieldModel->where('id', $ids)->delete()) {
  247. // 记录行为
  248. $details = '详情:文档模型('.get_model_title($field['model']).')、字段名称('.$field['name'].')、字段标题('.$field['title'].')、字段类型('.$field['type'].')';
  249. action_log('field_delete', 'cms_field', $ids, UID, $details);
  250. $this->success('删除成功', cookie('__forward__'));
  251. }
  252. }
  253. return $this->error('删除失败');
  254. }
  255. /**
  256. * 启用字段
  257. * @param array $record 行为日志
  258. * @author 蔡伟明 <314013107@qq.com>
  259. * @return mixed
  260. */
  261. public function enable($record = [])
  262. {
  263. return $this->setStatus('enable');
  264. }
  265. /**
  266. * 禁用字段
  267. * @param array $record 行为日志
  268. * @author 蔡伟明 <314013107@qq.com>
  269. * @return mixed
  270. */
  271. public function disable($record = [])
  272. {
  273. return $this->setStatus('disable');
  274. }
  275. /**
  276. * 设置字段状态:删除、禁用、启用
  277. * @param string $type 类型:enable/disable
  278. * @param array $record
  279. * @author 蔡伟明 <314013107@qq.com>
  280. * @return mixed
  281. */
  282. public function setStatus($type = '', $record = [])
  283. {
  284. $ids = $this->request->isPost() ? input('post.ids/a') : input('param.ids');
  285. $field_delete = is_array($ids) ? '' : $ids;
  286. $field_names = FieldModel::where('id', 'in', $ids)->column('name');
  287. return parent::setStatus($type, ['field_'.$type, 'cms_field', $field_delete, UID, implode('、', $field_names)]);
  288. }
  289. /**
  290. * 快速编辑
  291. * @param array $record 行为日志
  292. * @author 蔡伟明 <314013107@qq.com>
  293. * @return mixed
  294. */
  295. public function quickEdit($record = [])
  296. {
  297. $id = input('post.pk', '');
  298. $field = input('post.name', '');
  299. $value = input('post.value', '');
  300. $config = FieldModel::where('id', $id)->value($field);
  301. $details = '字段(' . $field . '),原值(' . $config . '),新值:(' . $value . ')';
  302. return parent::quickEdit(['field_edit', 'cms_field', $id, UID, $details]);
  303. }
  304. }