OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)

This commit is contained in:
wangruiguo
2026-09-03 18:49:20 +08:00
commit d647428529
3501 changed files with 1988906 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
<?php
namespace Leantime\Domain\Menu\Composers;
use Illuminate\Contracts\Container\BindingResolutionException;
use Leantime\Core\Controller\Composer;
use Leantime\Core\Controller\Frontcontroller as FrontcontrollerCore;
use Leantime\Core\UI\Theme;
use Leantime\Domain\Auth\Services\Auth as AuthService;
use Leantime\Domain\Help\Services\Helper;
use Leantime\Domain\Menu\Repositories\Menu as MenuRepo;
use Leantime\Domain\Notifications\Services\Notifications as NotificationService;
use Leantime\Domain\Timesheets\Services\Timesheets as TimesheetService;
use Leantime\Domain\Users\Services\Users as UserService;
class HeadMenu extends Composer
{
public static array $views = [
'menu::headMenu',
];
private NotificationService $notificationService;
private TimesheetService $timesheets;
private UserService $userService;
private AuthService $authService;
private Helper $helperService;
private Theme $themeCore;
private MenuRepo $menuRepo;
public function init(
NotificationService $notificationService,
TimesheetService $timesheets,
UserService $userService,
AuthService $authService,
Helper $helperService,
MenuRepo $menuRepo,
Theme $themeCore
): void {
$this->notificationService = $notificationService;
$this->timesheets = $timesheets;
$this->userService = $userService;
$this->authService = $authService;
$this->helperService = $helperService;
$this->menuRepo = $menuRepo;
$this->themeCore = $themeCore;
}
/**
* @throws BindingResolutionException
*/
public function with(): array
{
// Fetch all notifications once, then filter for unread in PHP
// instead of making two separate DB queries
$notifications = [];
if (session()->exists('userdata')) {
$notifications = $this->notificationService->getAllNotifications(session('userdata.id'));
}
$nCount = is_array($notifications) ? count(array_filter($notifications, fn ($n) => ($n['read'] ?? 1) == 0)) : 0;
$totalNotificationCount =
$totalMentionCount =
$totalNewMentions =
$totalNewNotifications = 0;
$menuType = $this->menuRepo->getSectionMenuType(FrontcontrollerCore::getCurrentRoute(), 'project');
foreach ($notifications as $notif) {
if ($notif['type'] == 'mention') {
$totalMentionCount++;
if ($notif['read'] == 0) {
$totalNewMentions++;
}
} else {
$totalNotificationCount++;
if ($notif['read'] == 0) {
$totalNewNotifications++;
}
}
}
$user = false;
if (session()->exists('userdata')) {
$user = $this->userService->getUser(session('userdata.id'));
}
if (! $user) {
$this->authService->logout();
FrontcontrollerCore::redirect(BASE_URL.'/auth/login');
}
$modal = $this->helperService->getHelperModalByRoute(FrontcontrollerCore::getCurrentRoute());
if (! session()->exists('companysettings.logoPath')) {
session(['companysettings.logoPath' => $this->themeCore->getLogoUrl()]);
}
return [
'newNotificationCount' => $nCount,
'totalNotificationCount' => $totalNotificationCount,
'totalMentionCount' => $totalMentionCount,
'totalNewMentions' => $totalNewMentions,
'totalNewNotifications' => $totalNewNotifications,
'menuType' => $menuType,
'notifications' => $notifications,
'onTheClock' => session()->exists('userdata') ? $this->timesheets->isClocked(session('userdata.id')) : false,
'activePath' => FrontcontrollerCore::getCurrentRoute(),
'action' => FrontcontrollerCore::getActionName(),
'module' => FrontcontrollerCore::getModuleName(),
'user' => $user,
'modal' => $modal,
];
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace Leantime\Domain\Menu\Composers;
use Illuminate\Contracts\Container\BindingResolutionException;
use Leantime\Core\Controller\Composer;
use Leantime\Core\Controller\Frontcontroller as FrontcontrollerCore;
use Leantime\Core\Events\DispatchesEvents;
use Leantime\Core\Http\IncomingRequest as IncomingRequestCore;
use Leantime\Domain\Menu\Repositories\Menu as MenuRepository;
class Menu extends Composer
{
use DispatchesEvents;
public static array $views = [
'menu::menu',
];
private MenuRepository $menuRepo;
private IncomingRequestCore $incomingRequest;
private \Leantime\Domain\Menu\Services\Menu $menuService;
public function init(
MenuRepository $menuRepo,
\Leantime\Domain\Menu\Services\Menu $menuService,
IncomingRequestCore $request
): void {
$this->menuRepo = $menuRepo;
$this->menuService = $menuService;
$this->incomingRequest = $request;
}
/**
* @throws BindingResolutionException
*/
public function with(): array
{
$allAssignedprojects = $showSettingsIndicator = false;
$allAvailableProjects =
$recentProjects =
$favoriteProjects =
$clients =
$allAvailableProjectsHierarchy =
$allAssignedprojectsHierarchy = [];
$currentClient = '';
$currentProject = '';
$projectType = '';
$menuType = 'default';
$projectSelectFilter = session('usersettings.projectSelectFilter') ?? [
'groupBy' => 'structure',
'client' => null,
];
if (session()->exists('userdata')) {
// Getting all projects (ignoring client filter, clients are filtered on the frontend)
$projectVars = $this->menuService->getUserProjectList(session('userdata.id'), $projectSelectFilter['client']);
$allAssignedprojects = $projectVars['assignedProjects'];
$allAvailableProjects = $projectVars['availableProjects'];
$allAvailableProjectsHierarchy = $projectVars['availableProjectsHierarchy'];
$allAssignedprojectsHierarchy = $projectVars['assignedHierarchy'];
$currentClient = $projectVars['currentClient'];
$menuType = $projectVars['menuType'];
$projectType = $projectVars['projectType'];
$recentProjects = $projectVars['recentProjects'];
$favoriteProjects = $projectVars['favoriteProjects'];
$clients = $projectVars['clients'];
$currentProject = $projectVars['currentProject'];
}
$menuType = $this->menuRepo->getSectionMenuType(FrontcontrollerCore::getCurrentRoute(), $menuType);
if (str_contains($redirectUrl = $this->incomingRequest->getRequestUri(), 'showProject')) {
$redirectUrl = '/dashboard/show';
}
$projectTypeAvatars = $this->menuService->getProjectTypeAvatars();
$projectSelectGroupOptions = $this->menuService->getProjectSelectorGroupingOptions();
$settingsLink = [
'label' => '',
'module' => '',
'action' => '',
'settingsIcon' => '',
'settingsTooltip' => '',
];
if ($menuType == 'project' || $menuType == 'default') {
$settingsLink = [
'label' => __('menu.project_settings'),
'module' => 'projects',
'action' => 'showProject',
'settingsIcon' => __('menu.project_settings_icon'),
'settingsTooltip' => __('menu.project_settings_tooltip'),
];
}
$settingsLink = self::dispatch_filter('settingsLink', $settingsLink, ['type' => $menuType]);
$newProjectUrl = self::dispatch_filter('startSomething', BASE_URL.'/projects/newProject');
return [
'currentClient' => $currentClient,
'module' => FrontcontrollerCore::getModuleName(),
'action' => FrontcontrollerCore::getActionName(),
'currentProjectType' => $projectType,
'allAssignedProjects' => $allAssignedprojects,
'allAvailableProjects' => $allAvailableProjects,
'allAvailableProjectsHierarchy' => $allAvailableProjectsHierarchy,
'projectHierarchy' => $allAssignedprojectsHierarchy,
'recentProjects' => $recentProjects,
'currentProject' => $currentProject,
'menuStructure' => $this->menuRepo->getMenuStructure($menuType ?? ''),
'menuType' => $menuType,
'settingsLink' => $settingsLink,
'redirectUrl' => $redirectUrl,
'projectTypeAvatars' => $projectTypeAvatars,
'favoriteProjects' => $favoriteProjects,
'projectSelectGroupOptions' => $projectSelectGroupOptions,
'projectSelectFilter' => $projectSelectFilter,
'clients' => $clients,
'startSomethingUrl' => $newProjectUrl,
];
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace Leantime\Domain\Menu\Composers;
use Illuminate\Contracts\Container\BindingResolutionException;
use Leantime\Core\Controller\Composer;
use Leantime\Core\Controller\Frontcontroller as FrontcontrollerCore;
use Leantime\Core\Events\DispatchesEvents;
use Leantime\Core\Http\IncomingRequest as IncomingRequestCore;
class ProjectSelector extends Composer
{
use DispatchesEvents;
public static array $views = [
'menu::projectSelector',
];
private IncomingRequestCore $incomingRequest;
private \Leantime\Domain\Menu\Services\Menu $menuService;
public function init(
\Leantime\Domain\Menu\Services\Menu $menuService,
IncomingRequestCore $request
): void {
$this->menuService = $menuService;
$this->incomingRequest = $request;
}
/**
* @throws BindingResolutionException
*/
public function with(): array
{
$allAssignedprojects =
$allAvailableProjects =
$recentProjects =
$favoriteProjects =
$clients =
$allAvailableProjectsHierarchy =
$allAssignedprojectsHierarchy = [];
$currentClient = '';
$currentProject = '';
$projectType = '';
$menuType = 'default';
$projectSelectFilter = session('usersettings.projectSelectFilter', [
'groupBy' => 'structure',
'client' => null,
]);
if (session()->exists('userdata')) {
// Getting all projects (ignoring client filter, clients are filtered on the frontend)
$projectVars = $this->menuService->getUserProjectList(session('userdata.id'), $projectSelectFilter['client']);
$allAssignedprojects = $projectVars['assignedProjects'];
$allAvailableProjects = $projectVars['availableProjects'];
$allAvailableProjectsHierarchy = $projectVars['availableProjectsHierarchy'];
$allAssignedprojectsHierarchy = $projectVars['assignedHierarchy'];
$currentClient = $projectVars['currentClient'];
$projectType = $projectVars['projectType'];
$recentProjects = $projectVars['recentProjects'];
$favoriteProjects = $projectVars['favoriteProjects'];
$clients = $projectVars['clients'];
$currentProject = $projectVars['currentProject'];
}
if (str_contains($redirectUrl = $this->incomingRequest->getRequestUri(), 'showProject')) {
$redirectUrl = '/dashboard/show';
}
$projectTypeAvatars = $this->menuService->getProjectTypeAvatars();
$projectSelectGroupOptions = $this->menuService->getProjectSelectorGroupingOptions();
$newProjectUrl = self::dispatch_filter('startSomething', BASE_URL.'/projects/newProject');
return [
'currentClient' => $currentClient,
'module' => FrontcontrollerCore::getModuleName(),
'action' => FrontcontrollerCore::getActionName(),
'currentProjectType' => $projectType,
'allAssignedProjects' => $allAssignedprojects,
'allAvailableProjects' => $allAvailableProjects,
'allAvailableProjectsHierarchy' => $allAvailableProjectsHierarchy,
'projectHierarchy' => $allAssignedprojectsHierarchy,
'recentProjects' => $recentProjects,
'currentProject' => $currentProject,
'settingsLink' => [
'label' => __('menu.project_settings'),
'module' => 'projects',
'action' => 'showProject',
'settingsIcon' => __('menu.project_settings_icon'),
'settingsTooltip' => __('menu.project_settings_tooltip'),
],
'redirectUrl' => $redirectUrl,
'projectTypeAvatars' => $projectTypeAvatars,
'favoriteProjects' => $favoriteProjects,
'projectSelectGroupOptions' => $projectSelectGroupOptions,
'projectSelectFilter' => $projectSelectFilter,
'clients' => $clients,
'startSomethingUrl' => $newProjectUrl,
];
}
}