DataScopeBaseModel.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <?php
  2. namespace App\Model;
  3. use Illuminate\Database\Eloquent\Model;
  4. class DataScopeBaseModel extends Model
  5. {
  6. //人员id字段 创建人
  7. const employee_column = '';
  8. //有权限的人的表
  9. const table_column = '';
  10. //有权限的人的表关联id
  11. const table_id_column = '';
  12. //明细表
  13. const detail_table_column = '';
  14. public function __construct(array $attributes = [])
  15. {
  16. parent::__construct($attributes);
  17. }
  18. //根据公司过滤
  19. public function scopeTopClear($query, $user, $search)
  20. {
  21. $top_depart_id = "top_depart_id";
  22. // 获取当前查询的表名或别名(这样无论你起什么别名 i 还是 item_details 都能自适应)
  23. $table = $query->getQuery()->from;
  24. // 如果 $table 里包含 " as ",说明有别名,截取别名部分
  25. if (strpos($table, ' as ') !== false) {
  26. $segments = explode(' as ', $table);
  27. $table = trim(end($segments));
  28. $top_depart_id = $table . '.top_depart_id';
  29. }
  30. $query->where($top_depart_id, $user['top_depart_id']);
  31. return $query;
  32. $query->where('top_depart_id', $user['top_depart_id']);
  33. return $query;
  34. }
  35. //数据权限中 人员 部门 所有 (在公司的基础上)
  36. public function scopeClear1($query, $user, $search)
  37. {
  38. //权限范围内的部门
  39. $depart_range = $user['depart_id'] ?? [];
  40. //个人 部门 所有
  41. $auth_type = $this->getQx($search,$user);
  42. // 获取模型的实例
  43. $model = $query->getModel();
  44. // 获取模型类名
  45. $className = get_class($model);
  46. // 人员字段
  47. $column = defined($className . '::employee_column') ? constant($className . '::employee_column') : '';
  48. $this->makeModel($query, $auth_type, $user, $depart_range,$column);
  49. }
  50. private function makeModel1(&$query, $auth_type, $user, $depart_range, $column){
  51. $query->where('top_depart_id', $user['top_depart_id']);
  52. if(empty($column)) return;
  53. if($auth_type == Employee::AUTH_ONE){
  54. //我创建的
  55. $query->where($column,$user['id']);
  56. }elseif ($auth_type == Employee::AUTH_TWO){
  57. if (empty($depart_range)) {
  58. $query->whereRaw('1 = 0');
  59. } else {
  60. $query->whereExists(function ($q) use ($column, $depart_range) {
  61. $q->from('employee_depart_permission')
  62. ->whereColumn('employee_depart_permission.employee_id', $column)
  63. ->whereIn('employee_depart_permission.depart_id', $depart_range);
  64. });
  65. }
  66. }elseif ($auth_type == Employee::AUTH_THREE){
  67. //所有
  68. }
  69. }
  70. public function scopeClear($query, $user, $search)
  71. {
  72. // 权限范围内的部门
  73. $depart_range = $user['depart_id'] ?? [];
  74. // 个人 部门 所有
  75. $auth_type = $this->getQx($search, $user);
  76. // 获取模型的实例
  77. $model = $query->getModel();
  78. // 获取模型类名
  79. $className = get_class($model);
  80. // 🆕 核心修复 1:动态获取当前主表的表名,用来给字段加前缀防止别名冲突
  81. $tableName = $model->getTable();
  82. // 人员字段
  83. $column = defined($className . '::employee_column') ? constant($className . '::employee_column') : '';
  84. // 🆕 核心修复 2:如果定义了人员字段,且没有带表前缀,自动加上主表前缀
  85. if (!empty($column) && strpos($column, '.') === false) {
  86. $column = $tableName . '.' . $column;
  87. }
  88. $this->makeModel($query, $auth_type, $user, $depart_range, $column, $tableName);
  89. }
  90. private function makeModel(&$query, $auth_type, $user, $depart_range, $column, $tableName) {
  91. // 🆕 核心修复 3:给 top_depart_id 加上主表名前缀,防止关联表也有该字段导致冲突
  92. $query->where($tableName . '.top_depart_id', $user['top_depart_id']);
  93. if (empty($column)) return;
  94. if ($auth_type == Employee::AUTH_ONE) {
  95. // 我创建的 (此时 $column 已经是 "table_name.field" 格式)
  96. $query->where($column, $user['id']);
  97. } elseif ($auth_type == Employee::AUTH_TWO) {
  98. if (empty($depart_range)) {
  99. $query->whereRaw('1 = 0');
  100. } else {
  101. $query->whereExists(function ($q) use ($column, $depart_range) {
  102. $q->from('employee_depart_permission')
  103. ->whereColumn('employee_depart_permission.employee_id', $column) // 这里的 $column 带有表前缀,whereColumn 完美识别
  104. ->whereIn('employee_depart_permission.depart_id', $depart_range);
  105. });
  106. }
  107. } elseif ($auth_type == Employee::AUTH_THREE) {
  108. // 所有
  109. }
  110. }
  111. //根据公司过滤 加人员
  112. public function scopeTopAndEmployeeClear1($query, $user, $search)
  113. {
  114. $top_depart_id = "top_depart_id";
  115. $table = $query->getQuery()->from;
  116. $alias = $table; // 默认为原表名
  117. // 如果 $table 里包含 " as ",说明有别名,截取别名部分
  118. if (strpos($table, ' as ') !== false) {
  119. $segments = explode(' as ', $table);
  120. $table = trim(end($segments));
  121. $top_depart_id = $table . '.top_depart_id';
  122. }
  123. $query->where($top_depart_id, $user['top_depart_id']);
  124. // 获取模型的实例
  125. $model = $query->getModel();
  126. // 获取模型类名
  127. $className = get_class($model);
  128. $relationTable = defined($className . '::table_column') ? constant($className . '::table_column') : '';
  129. $relationTableId = defined($className . '::table_id_column') ? constant($className . '::table_id_column') : '';
  130. if($user['is_admin'] != Employee::IS_ADMIN_TWO){
  131. if (! empty($relationTable) && ! empty($relationTableId)) {
  132. $query->whereExists(function ($subQuery) use ($relationTable, $user, $alias, $relationTableId) {
  133. $subQuery->from($relationTable)
  134. ->whereColumn($relationTable . ".{$relationTableId}", $alias . '.id') // 关联主表的 ID
  135. ->where($relationTable . '.data_id', $user['id']) // 过滤当前操作人
  136. ->where($relationTable . '.del_time', 0) // 排除已删除的关联记录
  137. ->where($relationTable . '.top_depart_id', $user['top_depart_id']);
  138. });
  139. }
  140. }
  141. return $query;
  142. }
  143. public function scopeTopAndEmployeeClear($query, $user, $search)
  144. {
  145. $top_depart_id = "top_depart_id";
  146. $table = $query->getQuery()->from;
  147. $alias = $table; // 默认为原表名
  148. // 如果 $table 里包含 " as ",说明有别名,截取别名部分
  149. if (strpos($table, ' as ') !== false) {
  150. $segments = explode(' as ', $table);
  151. $table = trim(end($segments));
  152. $top_depart_id = $table . '.top_depart_id';
  153. }
  154. $query->where($top_depart_id, $user['top_depart_id']);
  155. // 如果是超级管理员,直接返回,拥有最高权限
  156. if ($user['is_admin'] == Employee::IS_ADMIN_TWO) {
  157. return $query;
  158. }
  159. // 获取模型的实例与类名
  160. $model = $query->getModel();
  161. $className = get_class($model);
  162. // 1. 负责人表配置
  163. $relationTable = defined($className . '::table_column') ? constant($className . '::table_column') : '';
  164. $relationTableId = defined($className . '::table_id_column') ? constant($className . '::table_id_column') : '';
  165. // 2. 新增:成员表配置
  166. $detailTable = defined($className . '::detail_table_column') ? constant($className . '::detail_table_column') : '';
  167. // 使用一个闭包将“负责人”或“成员”的权限求并集(OR 关系)
  168. $query->where(function ($groupQuery) use ($relationTable, $relationTableId, $detailTable, $user, $alias) {
  169. // 逻辑 A:负责人层级判定(原逻辑:项目/节点/任务负责人及上级负责人穿透)
  170. $groupQuery->whereExists(function ($subQuery) use ($relationTable, $relationTableId, $user, $alias) {
  171. $subQuery->from($relationTable)
  172. ->whereColumn($relationTable . ".{$relationTableId}", $alias . '.id')
  173. ->where($relationTable . '.data_id', $user['id'])
  174. ->where($relationTable . '.del_time', 0)
  175. ->where($relationTable . '.top_depart_id', $user['top_depart_id']);
  176. });
  177. // 逻辑 B:成员判定(新逻辑:仅当前层级成员可见,无向下穿透性)
  178. // 直接用 orWhereExists,只要定义了成员表就必然生效
  179. if (!empty($detailTable)) {
  180. $groupQuery->orWhereExists(function ($subQuery) use ($detailTable, $relationTableId, $user, $alias) {
  181. $subQuery->from($detailTable)
  182. ->whereColumn($detailTable . ".{$relationTableId}", $alias . '.id') // 同样关联主表 ID
  183. ->where($detailTable . '.data_id', $user['id'])
  184. ->where($detailTable . '.type', 1) // 严格限制:只看“1人”,排除“2设备”
  185. ->where($detailTable . '.del_time', 0)
  186. ->where($detailTable . '.top_depart_id', $user['top_depart_id']);
  187. });
  188. }
  189. });
  190. return $query;
  191. }
  192. public function getQx($data, $user){
  193. if(empty($data['menu_id'])) return Employee::AUTH_ONE; // 我的
  194. if($user['is_admin'] == Employee::IS_ADMIN_TWO) return Employee::AUTH_THREE; // 全部
  195. if(! empty($user['menu_permissions'][$data['menu_id']])) {
  196. //指定菜单 显示对应权限
  197. return $user['menu_permissions'][$data['menu_id']];
  198. }else{
  199. return Employee::AUTH_ONE; // 我的
  200. }
  201. }
  202. function hasMethod($class, $methodName)
  203. {
  204. $reflection = new \ReflectionClass($class);
  205. return $reflection->hasMethod($methodName);
  206. }
  207. }