value('dept_id'); return (int) ($deptId ?: 0); } /** * @param array $creatorIds * @return array{0: array, 1: array} */ protected static function loadAdminDeptMap(array $creatorIds): array { $creatorIds = array_values(array_unique(array_filter(array_map('intval', $creatorIds)))); if ($creatorIds === []) { return [[], []]; } $rows = AdminDept::whereIn('admin_id', $creatorIds) ->field('admin_id, dept_id') ->select() ->toArray(); $adminToDeptId = []; foreach ($rows as $row) { $adminId = (int) ($row['admin_id'] ?? 0); $deptId = (int) ($row['dept_id'] ?? 0); if ($adminId <= 0 || $deptId <= 0) { continue; } if (!isset($adminToDeptId[$adminId])) { $adminToDeptId[$adminId] = $deptId; } } $deptNameMap = []; $deptIds = array_values(array_unique($adminToDeptId)); if ($deptIds !== []) { $deptNameMap = Dept::whereIn('id', $deptIds) ->column('name', 'id'); } return [$adminToDeptId, $deptNameMap]; } /** * @param array> $rows * @return array> */ protected static function attachDeptInfoToRows(array $rows): array { if ($rows === []) { return $rows; } $creatorIds = array_map(static fn (array $row): int => (int) ($row['creator_id'] ?? 0), $rows); [$adminToDeptId, $deptNameMap] = self::loadAdminDeptMap($creatorIds); foreach ($rows as &$row) { $creatorId = (int) ($row['creator_id'] ?? 0); $deptId = $adminToDeptId[$creatorId] ?? 0; $row['dept_id'] = $deptId; $row['dept_name'] = $deptId > 0 ? (string) ($deptNameMap[$deptId] ?? '') : ''; } unset($row); return $rows; } /** * 根据 dept_id(包含其子部门)收窄可见 admin id 集合。 * 与 visibleAdminIds 取交集。 * * @param array|null $visibleAdminIds null 表示不限 * @return array|null 返回 null 表示外部条件无需附加;返回 [] 表示无可见 admin */ protected static function intersectVisibleByDept(?array $visibleAdminIds, int $deptId): ?array { if ($deptId <= 0) { return $visibleAdminIds; } $deptIds = DeptLogic::getSelfAndDescendantIds($deptId); if ($deptIds === []) { $deptIds = [$deptId]; } $adminIds = AdminDept::whereIn('dept_id', $deptIds)->column('admin_id'); $adminIds = array_values(array_unique(array_filter(array_map('intval', $adminIds), static fn (int $v): bool => $v > 0))); if ($visibleAdminIds === null) { return $adminIds; } return array_values(array_intersect($visibleAdminIds, $adminIds)); } protected static function normalizeMediaSource(string $mediaSource): string { return trim($mediaSource); } /** * 与 project.self_input_stats_view_all_roles 一致:超管或白名单角色可见全部录入人数据。 */ protected static function canViewAllSelfInputStats(array $adminInfo): bool { if ((int) ($adminInfo['root'] ?? 0) === 1) { return true; } $allow = Config::get('project.self_input_stats_view_all_roles', []); $allow = array_map('intval', is_array($allow) ? $allow : []); if ($allow === []) { return false; } $myRoles = array_map('intval', $adminInfo['role_id'] ?? []); return count(array_intersect($myRoles, $allow)) > 0; } /** * @return array|null null=全部录入人;[]=无可见;int[]=可见 creator_id 集合 */ protected static function getVisibleCreatorIds(int $adminId, array $adminInfo): ?array { if (self::canViewAllSelfInputStats($adminInfo)) { return null; } return DataScopeService::getVisibleAdminIds($adminId, $adminInfo); } protected static function assertRecordVisible(int $adminId, array $adminInfo, int $creatorId): bool { $visibleIds = self::getVisibleCreatorIds($adminId, $adminInfo); if ($visibleIds === null) { return true; } return in_array($creatorId, $visibleIds, true); } protected static function isYejiDuplicate(int $creatorId, string $yejiDate, string $mediaSource, int $excludeId = 0): bool { $query = PersonalYeji::where('creator_id', $creatorId) ->where('yeji_date', $yejiDate) ->where('media_source', $mediaSource); if ($excludeId > 0) { $query->where('id', '<>', $excludeId); } return $query->count() > 0; } protected static function isCostDuplicate(int $creatorId, string $costDate, string $mediaSource, int $excludeId = 0): bool { $query = PersonalAccountCost::where('creator_id', $creatorId) ->where('cost_date', $costDate) ->where('media_source', $mediaSource); if ($excludeId > 0) { $query->where('id', '<>', $excludeId); } return $query->count() > 0; } }