Rule.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. namespace app\admin\controller\auth;
  3. use ba\Tree;
  4. use Throwable;
  5. use app\admin\model\AdminRule;
  6. use app\admin\model\AdminGroup;
  7. use app\common\controller\Backend;
  8. class Rule extends Backend
  9. {
  10. protected string|array $preExcludeFields = ['create_time', 'update_time'];
  11. protected string|array $quickSearchField = 'title';
  12. /**
  13. * @var object
  14. * @phpstan-var AdminRule
  15. */
  16. protected object $model;
  17. /**
  18. * @var Tree
  19. */
  20. protected Tree $tree;
  21. /**
  22. * 远程select初始化传值
  23. * @var array
  24. */
  25. protected array $initValue;
  26. /**
  27. * 搜索关键词
  28. * @var string
  29. */
  30. protected string $keyword;
  31. /**
  32. * 是否组装Tree
  33. * @var bool
  34. */
  35. protected bool $assembleTree;
  36. /**
  37. * 开启模型验证
  38. * @var bool
  39. */
  40. protected bool $modelValidate = false;
  41. public function initialize(): void
  42. {
  43. parent::initialize();
  44. $this->model = new AdminRule();
  45. $this->tree = Tree::instance();
  46. $isTree = $this->request->param('isTree', true);
  47. $this->initValue = $this->request->get('initValue/a', []);
  48. $this->initValue = array_filter($this->initValue);
  49. $this->keyword = $this->request->request('quickSearch', '');
  50. // 有初始化值时不组装树状(初始化出来的值更好看)
  51. $this->assembleTree = $isTree && !$this->initValue;
  52. }
  53. public function index(): void
  54. {
  55. if ($this->request->param('select')) {
  56. $this->select();
  57. }
  58. $list = $this->getMenus();
  59. foreach ($list as $k=>$v)
  60. {
  61. $this->makeData($v['children']);
  62. foreach ($v as $key=>$value)
  63. {
  64. $list[$k][strtolower($key)] = $value;
  65. unset($list[$k][strtoupper($key)]);
  66. }
  67. }
  68. $this->success('', [
  69. 'list' => $list,
  70. 'remark' => get_route_remark(),
  71. ]);
  72. }
  73. public function makeData(&$data)
  74. {
  75. if(!empty($data)){
  76. foreach ($data as $k=>$v){
  77. if(!empty($v['children'])){
  78. $this->makeData($v['children']);
  79. }
  80. foreach ($v as $k2=>$v2){
  81. $data[$k][strtolower($k2)] = $v2;
  82. unset($data[$k][strtoupper($k2)]);
  83. }
  84. }
  85. }
  86. }
  87. /**
  88. * 添加
  89. */
  90. public function add(): void
  91. {
  92. if ($this->request->isPost()) {
  93. $data = $this->request->post();
  94. if (!$data) {
  95. $this->error(__('Parameter %s can not be empty', ['']));
  96. }
  97. $data = $this->excludeFields($data);
  98. if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
  99. $data[$this->dataLimitField] = $this->auth->id;
  100. }
  101. $result = false;
  102. $this->model->startTrans();
  103. try {
  104. // 模型验证
  105. if ($this->modelValidate) {
  106. $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
  107. if (class_exists($validate)) {
  108. $validate = new $validate();
  109. if ($this->modelSceneValidate) $validate->scene('add');
  110. $validate->check($data);
  111. }
  112. }
  113. $result = $this->model->save($data);
  114. // 检查所有非超管的分组是否应该拥有此权限
  115. if (!empty($data['pid'])) {
  116. $groups = AdminGroup::where('rules', '<>', '*')->select();
  117. foreach ($groups as $group) {
  118. $rules = explode(',', $group->rules);
  119. if (in_array($data['pid'], $rules) && !in_array($this->model->id, $rules)) {
  120. $rules[] = $this->model->id;
  121. $group->rules = implode(',', $rules);
  122. $group->save();
  123. }
  124. }
  125. }
  126. $this->model->commit();
  127. } catch (Throwable $e) {
  128. $this->model->rollback();
  129. $this->error($e->getMessage());
  130. }
  131. if ($result !== false) {
  132. $this->success(__('Added successfully'));
  133. } else {
  134. $this->error(__('No rows were added'));
  135. }
  136. }
  137. $this->error(__('Parameter error'));
  138. }
  139. /**
  140. * 编辑
  141. * @throws Throwable
  142. */
  143. public function edit(): void
  144. {
  145. $id = $this->request->param($this->model->getPk());
  146. $row = $this->model->find($id);
  147. if (!$row) {
  148. $this->error(__('Record not found'));
  149. }
  150. $dataLimitAdminIds = $this->getDataLimitAdminIds();
  151. if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
  152. $this->error(__('You have no permission'));
  153. }
  154. if ($this->request->isPost()) {
  155. $data = $this->request->post();
  156. if (!$data) {
  157. $this->error(__('Parameter %s can not be empty', ['']));
  158. }
  159. $data = $this->excludeFields($data);
  160. $result = false;
  161. $this->model->startTrans();
  162. try {
  163. // 模型验证
  164. if ($this->modelValidate) {
  165. $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
  166. if (class_exists($validate)) {
  167. $validate = new $validate();
  168. if ($this->modelSceneValidate) $validate->scene('edit');
  169. $validate->check($data);
  170. }
  171. }
  172. if (isset($data['pid']) && $data['pid'] > 0) {
  173. // 满足意图并消除副作用
  174. $parent = $this->model->where('id', $data['pid'])->find();
  175. if ($parent['pid'] == $row['id']) {
  176. $parent->pid = 0;
  177. $parent->save();
  178. }
  179. }
  180. $result = $row->save($data);
  181. $this->model->commit();
  182. } catch (Throwable $e) {
  183. $this->model->rollback();
  184. $this->error($e->getMessage());
  185. }
  186. if ($result !== false) {
  187. $this->success(__('Update successful'));
  188. } else {
  189. $this->error(__('No rows updated'));
  190. }
  191. }
  192. $row = $row->toArray();
  193. foreach ($row as $k => $value) {
  194. $row[strtolower($k)] = $value;
  195. unset($row[$k]);
  196. }
  197. $this->success('', [
  198. 'row' => $row
  199. ]);
  200. }
  201. /**
  202. * 删除
  203. * @param array $ids
  204. * @throws Throwable
  205. */
  206. public function del(array $ids = []): void
  207. {
  208. if (!$this->request->isDelete() || !$ids) {
  209. $this->error(__('Parameter error'));
  210. }
  211. // 子级元素检查
  212. $subData = $this->model->where('pid', 'in', $ids)->column('pid', 'id');
  213. foreach ($subData as $key => $subDatum) {
  214. if (!in_array($key, $ids)) {
  215. $this->error(__('Please delete the child element first, or use batch deletion'));
  216. }
  217. }
  218. parent::del($ids);
  219. }
  220. /**
  221. * 重写select方法
  222. * @throws Throwable
  223. */
  224. public function select(): void
  225. {
  226. $data = $this->getMenus([['type', 'in', ['menu_dir', 'menu']], ['status', '=', '1']]);
  227. if ($this->assembleTree) {
  228. $data = $this->tree->assembleTree($this->tree->getTreeArray($data, 'title'));
  229. }
  230. foreach ($data as $k => $v) {
  231. foreach ($v as $k1 => $v1) {
  232. $data[$k][strtolower($k1)] = $v1;
  233. unset($data[$k][strtoupper($k1)]);
  234. }
  235. }
  236. $this->success('', [
  237. 'options' => $data
  238. ]);
  239. }
  240. /**
  241. * 获取菜单列表
  242. * @throws Throwable
  243. */
  244. protected function getMenus($where = []): array
  245. {
  246. $pk = $this->model->getPk();
  247. $initKey = $this->request->get("initKey/s", $pk);
  248. $ids = $this->auth->getRuleIds();
  249. // 如果没有 * 则只获取用户拥有的规则
  250. if (!in_array('*', $ids)) {
  251. $where[] = ['id', 'in', $ids];
  252. }
  253. if ($this->keyword) {
  254. $keyword = explode(' ', $this->keyword);
  255. foreach ($keyword as $item) {
  256. $where[] = [$this->quickSearchField, 'like', '%' . $item . '%'];
  257. }
  258. }
  259. if ($this->initValue) {
  260. $where[] = [$initKey, 'in', $this->initValue];
  261. }
  262. // 读取用户组所有权限规则
  263. $rules = $this->model
  264. ->where($where)
  265. ->order('weigh desc,id asc')
  266. ->select()->toArray();
  267. // 如果要求树状,此处先组装好 children
  268. return $this->assembleTree ? $this->tree->assembleChild($rules) : $rules;
  269. }
  270. }