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,152 @@
<?php
namespace Leantime\Domain\Bom\Services;
use Leantime\Core\Domains\BaseService;
use Leantime\Domain\Bom\Permissions\BomPermissions;
use Leantime\Domain\Bom\Repositories\Bom as BomRepository;
use Leantime\Domain\Bom\Repositories\MasterRef as MasterRefRepository;
/**
* 项目 ↔ 全局主数据BOM/工艺文件/工具清单)引用服务。
*
* 单向引用:项目引用主数据后追加的项目级列/值只存引用层,绝不写回全局主数据。
*/
class MasterRef extends BaseService
{
public function __construct(
protected MasterRefRepository $repo,
protected BomRepository $bomRepo,
) {}
/**
* 项目已引用的主数据列表。
*/
public function getRefs(int $projectId): array
{
return $this->repo->getRefsByProject($projectId);
}
/**
* 项目引用一个主数据(幂等:已引用则返回已有 refId
*/
public function link(int $projectId, int $masterId): int
{
$this->authorize(BomPermissions::EDIT, $projectId);
$master = $this->bomRepo->getBom($masterId);
if ($master === false) {
return 0;
}
$existing = $this->repo->findRef($projectId, $masterId);
if ($existing !== false) {
return (int) $existing['id'];
}
return $this->repo->createRef([
'projectId' => $projectId,
'masterId' => $masterId,
'createdOn' => now(),
]);
}
public function unlink(int $refId): bool
{
$ref = $this->repo->getRef($refId);
if ($ref === false) {
return false;
}
$this->authorize(BomPermissions::EDIT, (int) $ref['projectId']);
return $this->repo->deleteRef($refId);
}
/**
* 项目级引用详情:主数据明细 + 项目级追加列 + 项目级追加值。
*/
public function getRefDetail(int $refId): array|false
{
$ref = $this->repo->getRef($refId);
if ($ref === false) {
return false;
}
$this->authorize(BomPermissions::VIEW, (int) $ref['projectId']);
$columns = $this->repo->getColumns($refId);
$values = $this->repo->getValues($refId);
// 值按 itemId -> [columnId -> value] 组织
$valueMap = [];
foreach ($values as $v) {
$valueMap[(int) $v['itemId']][(int) $v['columnId']] = (string) $v['value'];
}
return [
'ref' => $ref,
'columns' => $columns,
'values' => $valueMap,
];
}
/**
* 项目级追加列。
*/
public function addColumn(int $refId, string $key, string $label): int
{
$ref = $this->repo->getRef($refId);
if ($ref === false) {
return 0;
}
$this->authorize(BomPermissions::EDIT, (int) $ref['projectId']);
$key = trim(str_replace([' ', '/', '\\'], '_', $key));
if ($key === '') {
return 0;
}
foreach ($this->repo->getColumns($refId) as $col) {
if ($col['key'] === $key) {
return (int) $col['id'];
}
}
$maxSort = 0;
foreach ($this->repo->getColumns($refId) as $col) {
$maxSort = max($maxSort, (int) $col['sortOrder']);
}
return $this->repo->addColumn([
'refId' => $refId,
'key' => $key,
'label' => trim($label) ?: $key,
'sortOrder' => $maxSort + 1,
]);
}
public function deleteColumn(int $columnId): bool
{
// 按 columnId 找 refId 以完成鉴权
$ref = $this->repo->getRefByColumnId($columnId);
if ($ref === false) {
return false;
}
$this->authorize(BomPermissions::EDIT, (int) $ref['projectId']);
return $this->repo->deleteColumn($columnId);
}
/**
* 保存项目级追加值(不影响全局主数据)。
*/
public function saveValue(int $refId, int $columnId, int $itemId, string $value): bool
{
$ref = $this->repo->getRef($refId);
if ($ref === false) {
return false;
}
$this->authorize(BomPermissions::EDIT, (int) $ref['projectId']);
return $this->repo->setValue($refId, $columnId, $itemId, $value);
}
}