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,33 @@
<?php
namespace Leantime\Domain\Tickets\Repositories;
use Illuminate\Database\ConnectionInterface;
use Leantime\Core\Db\Db as DbCore;
class TicketHistory
{
private ConnectionInterface $db;
/**
* __construct - get database connection
*/
public function __construct(DbCore $db)
{
$this->db = $db->getConnection();
}
public function getRecentTicketHistory(\DateTime $startingFrom, int $ticketId): array
{
$query = $this->db->table('zp_tickethistory')
->where('dateModified', '>=', $startingFrom->format('Y-m-d'));
if ($ticketId !== null) {
$query->where('ticketId', $ticketId);
}
$results = $query->orderBy('dateModified', 'desc')->get();
return array_map(fn ($item) => (array) $item, $results->toArray());
}
}

View File

@@ -0,0 +1,111 @@
<?php
namespace Leantime\Domain\Tickets\Repositories;
use Illuminate\Database\ConnectionInterface;
use Leantime\Core\Db\Db as DbCore;
use Leantime\Core\Support\EntityRelationshipEnum;
/**
* 待办事项(ticket/milestone) ↔ 资源关联层。
*
* 复用多态表 zp_entity_relationship零建表
* entityA = ticket idtask 或 milestone共用 zp_tickets.id 序列)
* entityAType = 'Ticket'
* entityB = 资源 id
* entityBType = 资源类型bom | process | tooling | file | wiki
* relationship = EntityRelationshipEnum::LinkedResource->value
*
* 幂等在服务层事务 + lockForUpdate 实现(仿 Goalcanvas::addGoalMilestoneLink
*/
class TicketResource
{
private ConnectionInterface $db;
public function __construct(DbCore $db)
{
$this->db = $db->getConnection();
}
/**
* 关联一个资源(幂等:已存在则返回 true
*/
public function addLink(int $ticketId, string $resourceType, int $resourceId, int $userId): bool
{
if ($ticketId <= 0 || $resourceId <= 0 || $resourceType === '') {
return false;
}
return $this->db->transaction(function () use ($ticketId, $resourceType, $resourceId, $userId): bool {
$exists = $this->db->table('zp_entity_relationship')
->where('entityA', $ticketId)
->where('entityAType', 'Ticket')
->where('entityB', $resourceId)
->where('entityBType', $resourceType)
->where('relationship', EntityRelationshipEnum::LinkedResource->value)
->lockForUpdate()
->exists();
if ($exists) {
return true;
}
$this->db->table('zp_entity_relationship')->insert([
'entityA' => $ticketId,
'entityAType' => 'Ticket',
'entityB' => $resourceId,
'entityBType' => $resourceType,
'relationship' => EntityRelationshipEnum::LinkedResource->value,
'createdOn' => now(),
'createdBy' => $userId > 0 ? $userId : null,
]);
return true;
});
}
/**
* 解除单个资源关联。
*/
public function removeLink(int $ticketId, string $resourceType, int $resourceId): bool
{
return $this->db->table('zp_entity_relationship')
->where('entityA', $ticketId)
->where('entityAType', 'Ticket')
->where('entityB', $resourceId)
->where('entityBType', $resourceType)
->where('relationship', EntityRelationshipEnum::LinkedResource->value)
->delete() > 0;
}
/**
* 解除 ticket 的全部资源关联(删除 ticket 时级联清理)。
*/
public function removeAllLinks(int $ticketId): bool
{
return $this->db->table('zp_entity_relationship')
->where('entityA', $ticketId)
->where('entityAType', 'Ticket')
->where('relationship', EntityRelationshipEnum::LinkedResource->value)
->delete() > 0;
}
/**
* 某 ticket 已关联的资源(去重后的 [resourceType, resourceId] 列表)。
*
* @return array<int, array{type:string,id:int}>
*/
public function getLinks(int $ticketId): array
{
return $this->db->table('zp_entity_relationship')
->where('entityA', $ticketId)
->where('entityAType', 'Ticket')
->where('relationship', EntityRelationshipEnum::LinkedResource->value)
->orderBy('id')
->get(['entityBType', 'entityB'])
->map(fn ($row) => ['type' => (string) $row->entityBType, 'id' => (int) $row->entityB])
->unique(fn ($item) => $item['type'].':'.$item['id'])
->values()
->all();
}
}

File diff suppressed because it is too large Load Diff