DataScopeBaseModel.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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. $table = $query->getQuery()->from;
  146. $alias = $table; // 默认别名就是全表名
  147. // 如果包含 " as ",说明有别名,直接截取最后的别名部分即可
  148. if (strpos($table, ' as ') !== false) {
  149. $segments = explode(' as ', $table);
  150. $alias = trim(end($segments)); // 真正的别名:i
  151. }
  152. // 统一使用别名进行公司隔离
  153. $query->where($alias . '.top_depart_id', $user['top_depart_id']);
  154. // 如果是超级管理员,直接放行
  155. if ($user['is_admin'] == Employee::IS_ADMIN_TWO) {
  156. return $query;
  157. }
  158. // 获取模型的实例与类名
  159. $model = $query->getModel();
  160. $className = get_class($model);
  161. // 1. 负责人表配置
  162. $relationTable = defined($className . '::table_column') ? constant($className . '::table_column') : '';
  163. $relationTableId = defined($className . '::table_id_column') ? constant($className . '::table_id_column') : '';
  164. // 2. 成员表配置
  165. $detailTable = defined($className . '::detail_table_column') ? constant($className . '::detail_table_column') : '';
  166. // 负责人 or 成员 权限并集
  167. $query->where(function ($groupQuery) use ($relationTable, $relationTableId, $detailTable, $user, $alias) {
  168. // 逻辑 A:负责人层级判定
  169. $groupQuery->whereExists(function ($subQuery) use ($relationTable, $relationTableId, $user, $alias) {
  170. $subQuery->from($relationTable)
  171. ->whereColumn($relationTable . ".{$relationTableId}", $alias . '.id')
  172. ->where($relationTable . '.data_id', $user['id'])
  173. ->where($relationTable . '.del_time', 0)
  174. ->where($relationTable . '.top_depart_id', $user['top_depart_id']);
  175. });
  176. // 逻辑 B:成员判定
  177. if (!empty($detailTable)) {
  178. $groupQuery->orWhereExists(function ($subQuery) use ($detailTable, $relationTableId, $user, $alias) {
  179. $subQuery->from($detailTable)
  180. ->whereColumn($detailTable . ".{$relationTableId}", $alias . '.id')
  181. ->where($detailTable . '.data_id', $user['id'])
  182. ->where($detailTable . '.type', 1)
  183. ->where($detailTable . '.del_time', 0)
  184. ->where($detailTable . '.top_depart_id', $user['top_depart_id']);
  185. });
  186. }
  187. });
  188. return $query;
  189. }
  190. public function getQx($data, $user){
  191. if(empty($data['menu_id'])) return Employee::AUTH_ONE; // 我的
  192. if($user['is_admin'] == Employee::IS_ADMIN_TWO) return Employee::AUTH_THREE; // 全部
  193. if(! empty($user['menu_permissions'][$data['menu_id']])) {
  194. //指定菜单 显示对应权限
  195. return $user['menu_permissions'][$data['menu_id']];
  196. }else{
  197. return Employee::AUTH_ONE; // 我的
  198. }
  199. }
  200. function hasMethod($class, $methodName)
  201. {
  202. $reflection = new \ReflectionClass($class);
  203. return $reflection->hasMethod($methodName);
  204. }
  205. }