Backend.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. <?php
  2. /**
  3. * ----------------------------------------------------------------------------
  4. * 行到水穷处,坐看云起时
  5. * 开发软件,找贵阳云起信息科技,官网地址:https://www.56q7.com/
  6. * ----------------------------------------------------------------------------
  7. * Author: 老成
  8. * email:85556713@qq.com
  9. */
  10. declare(strict_types=1);
  11. namespace app\common\controller;
  12. use app\admin\service\AdminAuthService;
  13. use app\common\listener\WriteLog;
  14. use app\common\service\LangService;
  15. use think\exception\HttpResponseException;
  16. use think\facade\Config;
  17. use think\facade\View;
  18. use think\facade\Cookie;
  19. use think\Response;
  20. /**
  21. * 后台控制器基类
  22. */
  23. class Backend extends BaseController
  24. {
  25. /**
  26. * 当前登录用户
  27. * @var \app\admin\service\AdminAuthService
  28. */
  29. protected $auth;
  30. /**
  31. * 应用配置参数
  32. * @var array
  33. */
  34. protected $config = [];
  35. /**
  36. * 无需登录的方法,同时也就不需要鉴权了
  37. * @var array
  38. */
  39. protected $noNeedLogin = [];
  40. /**
  41. * 无需鉴权的方法,但需要登录
  42. * @var array
  43. */
  44. protected $noNeedRight = [];
  45. /**
  46. * 模型对象
  47. * @var \think\Model;
  48. */
  49. protected $model;
  50. /**
  51. * 初始化方法
  52. * @return void
  53. */
  54. protected function _initialize()
  55. {
  56. $modulename=app('http')->getName();
  57. $modulealis=get_module_alis($modulename);
  58. $controllername = 'app\\'.$modulename.'\\controller\\'.str_replace('.','\\',$this->request->controller());
  59. $actionname = $this->request->action();
  60. $this->auth = AdminAuthService::newInstance(compact('modulealis','modulename','controllername','actionname'));
  61. $noNeed=$this->getNoNeedLoginOrRight();
  62. $noNeedLogin = in_array('*',$noNeed['login']) || in_array($actionname,$noNeed['login']);
  63. $elementUi=Config::get('yunqi.elementUi');
  64. $elementUi['language_list']=Config::get('yunqi.language_list');
  65. $elementUi['language']=Config::get('yunqi.language');
  66. if(!$noNeedLogin){
  67. if ($this->auth->isLogin()) {
  68. $elementUi=$this->auth->getElementUi($elementUi);
  69. event('write_log','管理员访问-ID:'.$this->auth->id.',昵称:'.$this->auth->nickname);
  70. $noNeedRight=in_array('*',$noNeed['right']) || in_array($actionname,$noNeed['right']);
  71. if(!$noNeedRight && !$this->auth->check($controllername,$actionname)){
  72. $response = Response::create(__('没有操作权限!'), 'html', 401);
  73. event('write_log','没有操作权限');
  74. event('write_log',WriteLog::END);
  75. throw new HttpResponseException($response);
  76. }
  77. }else{
  78. event('write_log','未登陆跳转');
  79. event('write_log',WriteLog::END);
  80. $url=url('/'.$modulealis.'/login')->build();
  81. redirect($url)->send();
  82. exit;
  83. }
  84. }else{
  85. event('write_log','游客访问');
  86. }
  87. event('write_log',WriteLog::ADMIN);
  88. //加载当前控制器语言包
  89. LangService::newInstance()->load($elementUi['language']);
  90. // 配置信息
  91. $route=[$modulename,$this->getShortControllerName(),$actionname];
  92. $version=Config::get('app.app_debug')?time():site_config("basic.version");
  93. $this->config = [
  94. 'version' => $version,
  95. 'controller' => $controllername,
  96. 'action' => $actionname,
  97. 'url' => request()->url(true),
  98. 'query' => $this->request->get(),
  99. 'baseUrl' => $this->request->domain().'/'.$this->auth->getRoute('modulealis').'/',
  100. 'upload' => Config::get('yunqi.upload'),
  101. 'elementUi' => $elementUi,
  102. 'locale' => LangService::newInstance()->all()
  103. ];
  104. //渲染配置信息
  105. $this->assign('config', $this->config);
  106. //渲染权限对象
  107. $this->assign('auth', $this->auth);
  108. }
  109. /**
  110. * 获取table中filter的值
  111. * @param string $filterstr
  112. * @return array|mixed|string
  113. */
  114. protected function filter(string $filterstr='')
  115. {
  116. $filterarr = $this->request->post("filter/a", []);
  117. if(!$filterstr){
  118. return $filterarr;
  119. }
  120. foreach ($filterarr as $value){
  121. if($value['field']==$filterstr){
  122. return $value['value'];
  123. }
  124. }
  125. return '';
  126. }
  127. protected function fetch(string $template = '', array $vars = [], bool $isVue=true)
  128. {
  129. $controllername = $this->getShortControllerName();
  130. $actionname=$this->request->action();
  131. if(empty($template)){
  132. $template = $controllername.DS.$actionname;
  133. }
  134. if($isVue){
  135. View::layout('layout'.DS.'vue');
  136. }
  137. return View::fetch($template,$vars);
  138. }
  139. /**
  140. * 构造下拉分页
  141. * @return array
  142. */
  143. protected function selectpage(array $where=[])
  144. {
  145. $sort=$this->model->getPk()??'id';
  146. $order='desc';
  147. $limit=[
  148. 'page' => $this->request->post('page/d',1),
  149. 'list_rows' => $this->request->post('limit/d',7)
  150. ];
  151. $keyField=$this->request->post('keyField');
  152. $labelField=$this->request->post('labelField');
  153. $keyValue=$this->request->post('keyValue');
  154. $labelValue=$this->request->post('labelValue');
  155. if($keyValue && is_string($keyValue)){
  156. $where[]=[$keyField,'in',explode(',',$keyValue)];
  157. }
  158. if($keyValue && is_array($keyValue)){
  159. $where[]=[$keyField,'in',$keyValue];
  160. }
  161. if($labelValue){
  162. $where[]=[$labelField,'like','%'.$labelValue.'%'];
  163. }
  164. $where = function ($query) use ($where) {
  165. foreach ($where as $v) {
  166. if(count($v)==1){
  167. $query->where($v[0]);
  168. }
  169. if(count($v)==2){
  170. $query->where($v[0],$v[1]);
  171. }
  172. if(count($v)==3){
  173. $query->where($v[0],$v[1],$v[2]);
  174. }
  175. }
  176. };
  177. $list = $this->model
  178. ->field($keyField.','.$labelField)
  179. ->where($where)
  180. ->order($sort, $order)
  181. ->paginate($limit);
  182. $rows=$list->items();
  183. foreach ($rows as &$row){
  184. $row[$keyField]=(string)$row[$keyField];
  185. }
  186. $result = ['total' => $list->total(), 'rows' => $rows];
  187. return json($result);
  188. }
  189. /**
  190. * 生成查询所需要的条件,排序方式
  191. * @param array $where 二维数组,默认的查询条件
  192. * @param string $alias 主表别名
  193. * @return array
  194. */
  195. protected function buildparams(array $where=[]):array
  196. {
  197. $limit=[
  198. 'page' => $this->request->post('page/d',1),
  199. 'list_rows' => $this->request->post('limit/d',10)
  200. ];
  201. $filter = $this->request->post("filter/a", []);
  202. if(isset($this->relationField)){
  203. $with=is_null($this->relationField)?[]:(is_array($this->relationField)?$this->relationField:explode(',',$this->relationField));
  204. }else{
  205. $with=[];
  206. }
  207. $search=$this->getBuildSearch();
  208. if($search){
  209. $where[]=$search;
  210. }
  211. foreach ($filter as $filterone) {
  212. $wh=$this->getBuildWhere($this->model->getTable(),$filterone);
  213. if($wh){
  214. $where[]=$wh;
  215. }
  216. if(strpos($filterone['field'],'.')!==false){
  217. $with=$this->getBuildWith($filterone,$with);
  218. }
  219. }
  220. /* @var \think\db\Query $query */
  221. $where = function ($query) use ($where) {
  222. foreach ($where as $v) {
  223. if(count($v)==1){
  224. $query->where($v[0]);
  225. }
  226. if(count($v)==2){
  227. $query->where($v[0],$v[1]);
  228. }
  229. if(count($v)==3){
  230. $query->where($v[0],$v[1],$v[2]);
  231. }
  232. }
  233. };
  234. $order=$this->getBuildSort();
  235. return [$where,$order,$limit,$with];
  236. }
  237. private function getBuildSort()
  238. {
  239. $sort=$this->request->post('sort','id');
  240. $order=$this->request->post('order','desc');
  241. $sort=explode(',',$sort);
  242. $order=explode(',',$order);
  243. $orderSort=[];
  244. foreach ($sort as $key=>$value){
  245. $orderSort[]=$value.' '.$order[$key];
  246. }
  247. $orderSort=implode(',',$orderSort);
  248. return $orderSort;
  249. }
  250. private function getBuildSearch()
  251. {
  252. $search=$this->request->post('search');
  253. $searchValue=$this->request->post('searchValue');
  254. if($search && $searchValue){
  255. $searcharr = is_array($search) ? $search : explode(',', $search);
  256. return [implode("|", $searcharr), "LIKE", "%{$searchValue}%"];
  257. }
  258. return false;
  259. }
  260. private function getBuildWith(array $filterone,array $with)
  261. {
  262. if(strpos($filterone['field'],'.')!==false){
  263. $sv=explode('.',$filterone['field']);
  264. if(in_array($sv[0],$with)){
  265. $filterone['field']=$sv[1];
  266. $where=$this->getBuildWhere('',$filterone);
  267. if($where){
  268. $key=array_search($sv[0],$with);
  269. unset($with[$key]);
  270. $with[$sv[0]]=function ($query) use ($where){
  271. if(count($where)==1){
  272. $query->where($where[0]);
  273. }
  274. if(count($where)==2){
  275. $query->where($where[0],$where[1]);
  276. }
  277. if(count($where)==3){
  278. $query->where($where[0],$where[1],$where[2]);
  279. }
  280. };
  281. }
  282. return $with;
  283. }
  284. }
  285. return $with;
  286. }
  287. private function getBuildWhere(string $table,array $filterone)
  288. {
  289. $where='';
  290. $sym=$filterone['op'];
  291. if(!$sym){
  292. return $where;
  293. }
  294. $sym=strtoupper($sym);
  295. if(strpos($filterone['field'],'.')!==false){
  296. return $where;
  297. }
  298. $field=$table?$table.'.'.$filterone['field']: $filterone['field'];
  299. $value=$filterone['value'];
  300. switch ($sym) {
  301. case '=':
  302. case '<>':
  303. case '!=':
  304. case '>':
  305. case '>=':
  306. case '<':
  307. case '<=':
  308. case '> TIME':
  309. case '>= TIME':
  310. case '< TIME':
  311. case '<= TIME':
  312. $where = [$field, $sym, $value];
  313. break;
  314. case 'LIKE':
  315. case 'NOT LIKE':
  316. $where = [$field, $sym, "%{$value}%"];
  317. break;
  318. case 'FIND_IN_SET':
  319. case 'NOT FIND_IN_SET':
  320. if(is_array($value)){
  321. $inset=[];
  322. foreach ($value as $v){
  323. $inset[]=$sym."('{$v}',{$field})";
  324. }
  325. $where = [implode(' and ',$inset)];
  326. }else{
  327. $where = [$sym."('{$value}',{$field})"];
  328. }
  329. break;
  330. case 'IN':
  331. case 'NOT IN':
  332. if(!is_array($value)){
  333. $this->error(__('IN与NOT IN参数必须是数组'));
  334. }
  335. $where = [$field, $sym, $value];
  336. break;
  337. case 'BETWEEN':
  338. case 'NOT BETWEEN':
  339. case 'BETWEEN TIME':
  340. case 'NOT BETWEEN TIME':
  341. if(!is_array($value)){
  342. $this->error(__('BETWEEN与NOT BETWEEN参数必须是数组'));
  343. }
  344. if(count($value)!=2){
  345. $this->error(__('BETWEEN与NOT BETWEEN参数必须为数组且有两个值'));
  346. }
  347. if($value[0]==='' && $value[1]===''){
  348. return false;
  349. }
  350. //当出现一边为空时改变操作符
  351. if ($value[0] === '') {
  352. if($sym == 'BETWEEN'){
  353. $sym ='<=';
  354. }
  355. if($sym == 'NOT BETWEEN'){
  356. $sym ='>';
  357. }
  358. $value = $value[1];
  359. } elseif ($value[1] === '') {
  360. if($sym == 'BETWEEN'){
  361. $sym ='>=';
  362. }
  363. if($sym == 'NOT BETWEEN'){
  364. $sym ='<';
  365. }
  366. $value = $value[0];
  367. }
  368. $where = [$field, $sym, $value];
  369. break;
  370. case 'IS NULL':
  371. case 'IS NOT NULL':
  372. $where = [$field.' '.$sym];
  373. break;
  374. default:
  375. break;
  376. }
  377. return $where;
  378. }
  379. private function getShortControllerName():string
  380. {
  381. $controllername=$this->auth->getRoute('controllername');
  382. $shortController=str_replace('.','/',substr($controllername,strpos($controllername,'\\controller\\')+12));
  383. $shortController=str_replace('\\','/',$shortController);
  384. $shortController=strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $shortController));
  385. return $shortController;
  386. }
  387. private function getNoNeedLoginOrRight()
  388. {
  389. $login=$this->noNeedLogin;
  390. $login=is_string($login)?[$login]:$login;
  391. $right=$this->noNeedRight;
  392. $right=is_string($right)?[$right]:$right;
  393. return compact('login','right');
  394. }
  395. }