count(enabled 不限) */ public function assignedCountMap(array $libraryIds): array { $libraryIds = array_values(array_unique(array_filter(array_map('intval', $libraryIds)))); if (empty($libraryIds)) { return []; } $map = []; try { $rows = Db::name('content_library_assign') ->whereIn('libraryId', $libraryIds) ->field('libraryId, COUNT(*) as cnt') ->group('libraryId') ->select(); foreach ($rows ?: [] as $r) { $map[(int) $r['libraryId']] = (int) $r['cnt']; } } catch (\Throwable $e) { // 迁移未执行时返回空 } return $map; } /** 单库的分配明细(含项目名 + 各项目 enabled) */ public function assignments(int $libraryId): array { $rows = Db::name('content_library_assign')->alias('a') ->leftJoin('company c', 'c.companyId = a.companyId') ->where('a.libraryId', $libraryId) ->field('a.id, a.libraryId, a.companyId, a.enabled, a.sort, c.name as projectName, c.id as projectId') ->order('a.sort', 'asc')->order('a.id', 'asc') ->select(); $list = []; foreach ($rows ?: [] as $r) { $list[] = [ 'id' => (int) $r['id'], 'libraryId' => (int) $r['libraryId'], 'companyId' => (int) $r['companyId'], 'projectId' => (int) ($r['projectId'] ?? 0), 'projectName' => $r['projectName'] ?: ('项目#' . (int) $r['companyId']), 'enabled' => (int) $r['enabled'], ]; } return $list; } /** * 批量分配:libraryIds × targets[{companyId, enabled}] * upsert(唯一键 libraryId+companyId) */ public function assign(array $libraryIds, array $targets): array { $libraryIds = array_values(array_unique(array_filter(array_map('intval', $libraryIds)))); if (empty($libraryIds)) { throw new \Exception('缺少 libraryIds', 400); } if (empty($targets)) { throw new \Exception('缺少目标项目', 400); } $now = time(); $affected = 0; foreach ($libraryIds as $libId) { foreach ($targets as $t) { $companyId = (int) ($t['companyId'] ?? 0); if ($companyId <= 0) { continue; } $enabled = (int) (($t['enabled'] ?? 1) ? 1 : 0); $exists = Db::name('content_library_assign') ->where('libraryId', $libId)->where('companyId', $companyId)->find(); if ($exists) { Db::name('content_library_assign')->where('id', $exists['id']) ->update(['enabled' => $enabled, 'updateTime' => $now]); } else { Db::name('content_library_assign')->insert([ 'libraryId' => $libId, 'companyId' => $companyId, 'enabled' => $enabled, 'sort' => 0, 'createTime' => $now, 'updateTime' => $now, ]); } $affected++; } } return ['affected' => $affected, 'libraryIds' => $libraryIds, 'targetCount' => count($targets)]; } /** 单条分配启停 */ public function toggle(int $assignId, int $enabled): array { $row = Db::name('content_library_assign')->where('id', $assignId)->find(); if (!$row) { throw new \Exception('分配记录不存在', 404); } Db::name('content_library_assign')->where('id', $assignId) ->update(['enabled' => $enabled ? 1 : 0, 'updateTime' => time()]); return ['id' => $assignId, 'enabled' => $enabled ? 1 : 0]; } /** 从 JSON / 逗号分隔的 url 字段取第一个 */ protected function firstUrl($raw): string { $raw = (string) $raw; if ($raw === '') { return ''; } $decoded = json_decode($raw, true); if (is_array($decoded)) { foreach ($decoded as $v) { if (is_string($v) && $v !== '') { return $v; } } return ''; } $parts = preg_split('/[,\s]+/', $raw); return $parts[0] ?? ''; } /** 库内素材预览(分页) */ public function materials(int $libraryId, int $page = 1, int $limit = 20): array { $page = max(1, $page); $limit = min(100, max(1, $limit)); $lib = Db::name('content_library')->where('id', $libraryId)->where('isDel', 0)->find(); if (!$lib) { throw new \Exception('内容库不存在', 404); } $base = Db::name('content_item')->where('libraryId', $libraryId)->where('isDel', 0); $total = (clone $base)->count(); $rows = $base->order('id', 'desc') ->page($page, $limit) ->select(); $items = []; foreach ($rows ?: [] as $r) { $title = trim((string) ($r['title'] ?? '')); if ($title === '') { $title = mb_substr(strip_tags((string) ($r['content'] ?? '')), 0, 30); } $thumb = (string) ($r['coverImage'] ?? ''); if ($thumb === '') { $thumb = $this->firstUrl($r['ossUrls'] ?? '') ?: $this->firstUrl($r['urls'] ?? '') ?: $this->firstUrl($r['resUrls'] ?? ''); } $items[] = [ 'id' => (int) $r['id'], 'title' => $title !== '' ? $title : ('素材#' . (int) $r['id']), 'type' => $r['type'] ?? ($r['contentType'] ?? ''), 'thumb' => $thumb, 'updateTime' => !empty($r['updateTime']) ? date('Y-m-d H:i:s', (int) $r['updateTime']) : (!empty($r['createTime']) ? date('Y-m-d H:i:s', (int) $r['createTime']) : ''), ]; } return [ 'libraryId' => $libraryId, 'libraryName' => $lib['name'] ?? '', 'total' => $total, 'page' => $page, 'limit' => $limit, 'items' => $items, ]; } }