返回 AiToEarn
publish-record.repository.ts
根目录 / project / aitoearn-backend / libs / mongodb / src / repositories / publish-record.repository.ts
1 /*
2 * @Author: nevin
3 * @Date: 2024-06-17 19:19:15
4 * @LastEditTime: 2024-09-05 15:19:25
5 * @LastEditors: nevin
6 * @Description: PublishRecord
7 */
8 import { Injectable } from '@nestjs/common'
9 import { InjectModel } from '@nestjs/mongoose'
10 import { AccountType, POST_DATA_UNAVAILABLE_WORK_STATUSES, WorkStatus } from '@yikart/common'
11 import { Model, RootFilterQuery, UpdateQuery } from 'mongoose'
12 import { PublishRecordSource, PublishStatus, PublishType } from '../enums'
13 import { PublishDayInfo, PublishInfo, PublishRecord } from '../schemas'
14 import { BaseRepository } from './base.repository'
15
16 export interface PublishRecordPostDataCrawlerMonitorItem {
17 publishRecordId: string
18 materialGroupId?: string
19 dataId: string
20 taskId?: string
21 accountType: AccountType
22 accountId?: string
23 uid?: string
24 workLink?: string
25 originalWorkLink?: string
26 publishTime?: Date
27 status: PublishStatus
28 workStatus?: WorkStatus
29 errorMessage?: string
30 createdAt?: Date
31 updatedAt?: Date
32 }
33
34 @Injectable()
35 export class PublishRecordRepository extends BaseRepository<PublishRecord> {
36 constructor(
37 @InjectModel(PublishRecord.name)
38 private readonly publishRecordModel: Model<PublishRecord>,
39 @InjectModel(PublishInfo.name)
40 private readonly publishInfoModel: Model<PublishInfo>,
41 @InjectModel(PublishDayInfo.name)
42 private readonly publishDayInfoModel: Model<PublishDayInfo>,
43 ) {
44 super(publishRecordModel)
45 }
46
47 /**
48 * 创建
49 * @param data
50 * @returns
51 */
52 override async create(data: Partial<PublishRecord>) {
53 const res = await this.publishRecordModel.create(data)
54 return res
55 }
56
57 /**
58 * 获取发布记录列表
59 * @param query
60 * @returns
61 */
62 async getPublishRecordList(
63 query: {
64 userId: string
65 accountId?: string
66 accountType?: AccountType
67 status?: PublishStatus
68 type?: PublishType
69 source?: PublishRecordSource
70 time?: [Date, Date]
71 uid?: string
72 },
73 ): Promise<PublishRecord[]> {
74 const filters: RootFilterQuery<PublishRecord> = {
75 userId: query.userId,
76 source: query.source ?? { $nin: [PublishRecordSource.TaskLink, PublishRecordSource.OfflineQr] },
77 ...(query.accountId !== undefined && { accountId: query.accountId }),
78 ...(query.accountType !== undefined && {
79 accountType: query.accountType,
80 }),
81 ...(query.status !== undefined && {
82 status: query.status,
83 }),
84 ...(query.type !== undefined && { type: query.type }),
85 ...(query.time !== undefined
86 && query.time.length === 2 && {
87 publishTime: { $gte: query.time[0], $lte: query.time[1] },
88 }),
89 ...(query.uid !== undefined && { uid: query.uid }),
90 }
91 const db = this.publishRecordModel.find(filters).sort({
92 createdAt: -1,
93 }).lean({ virtuals: true })
94 const list = await db.exec()
95
96 return list
97 }
98
99 async getQueuedPublishRecords(query: {
100 userId: string
101 accountId?: string
102 accountType?: AccountType
103 source?: PublishRecordSource
104 time?: [Date, Date]
105 }): Promise<PublishRecord[]> {
106 // status not equal published
107 const filters: RootFilterQuery<PublishRecord> = {
108 status: { $ne: PublishStatus.Published },
109 userId: query.userId,
110 source: query.source ?? { $nin: [PublishRecordSource.TaskLink, PublishRecordSource.OfflineQr] },
111 }
112 if (query.accountId) {
113 filters.accountId = query.accountId
114 }
115 if (query.accountType) {
116 filters.accountType = query.accountType
117 }
118 if (query.time && query.time.length === 2) {
119 filters.publishTime = { $gte: query.time[0], $lte: query.time[1] }
120 }
121 return this.publishRecordModel.find(filters).sort({
122 createdAt: -1,
123 }).lean({ virtuals: true })
124 }
125
126 async countPublishRecords(filter: RootFilterQuery<PublishRecord>) {
127 return this.publishRecordModel.countDocuments(filter).exec()
128 }
129
130 async groupPublishRecords(
131 filter: RootFilterQuery<PublishRecord>,
132 field: keyof PublishRecord,
133 ) {
134 return this.publishRecordModel.aggregate<{ _id: string | number | null, count: number }>([
135 { $match: filter },
136 { $group: { _id: `$${String(field)}`, count: { $sum: 1 } } },
137 { $sort: { count: -1 } },
138 ]).exec()
139 }
140
141 async getPublishRecordTrend(filter: RootFilterQuery<PublishRecord>) {
142 return this.publishRecordModel.aggregate<{ _id: string, count: number }>([
143 { $match: filter },
144 {
145 $group: {
146 _id: {
147 $dateToString: {
148 format: '%Y-%m-%d',
149 date: '$publishTime',
150 timezone: 'Asia/Shanghai',
151 },
152 },
153 count: { $sum: 1 },
154 },
155 },
156 { $sort: { _id: 1 } },
157 ]).exec()
158 }
159
160 async getAdminPublishRecordList(
161 filter: RootFilterQuery<PublishRecord>,
162 page: number,
163 pageSize: number,
164 ) {
165 return this.publishRecordModel
166 .find(filter)
167 .sort({ publishTime: -1, createdAt: -1 })
168 .skip((page - 1) * pageSize)
169 .limit(pageSize)
170 .lean({ virtuals: true })
171 .exec()
172 }
173
174 // 获取发布记录信息
175 async getPublishRecordInfo(id: string) {
176 return this.publishRecordModel.findOne({ _id: id }).lean({ virtuals: true })
177 }
178
179 async getByAccountTypeAndPlatformWorkId(accountType: AccountType, platformWorkId: string) {
180 return this.publishRecordModel.findOne({ accountType, platformWorkId }).lean({ virtuals: true }).exec()
181 }
182
183 async getByAccountTypeAndDataId(accountType: AccountType, dataId: string) {
184 return this.publishRecordModel.findOne({ accountType, dataId }).lean({ virtuals: true }).exec()
185 }
186
187 // 删除发布记录
188 async deletePublishRecordById(id: string): Promise<boolean> {
189 const res = await this.publishRecordModel.deleteOne({ _id: id })
190 return res.deletedCount > 0
191 }
192
193 // 更新
194 async updatePublishRecord(
195 filter: RootFilterQuery<PublishRecord>,
196 data: Partial<PublishRecord>,
197 ) {
198 const res = await this.publishRecordModel.updateOne(filter, { $set: data })
199 return res.modifiedCount > 0
200 }
201
202 async updateByIdAndStatuses(
203 id: string,
204 statuses: readonly PublishStatus[],
205 update: UpdateQuery<PublishRecord>,
206 ): Promise<PublishRecord | null> {
207 return this.publishRecordModel
208 .findOneAndUpdate(
209 { _id: id, status: { $in: statuses } },
210 update,
211 { new: true },
212 )
213 .lean({ virtuals: true })
214 .exec()
215 }
216
217 /**
218 * 创建
219 * @param data
220 * @returns
221 */
222 async createPublishInfo(data: Partial<PublishInfo>) {
223 const res = await this.publishInfoModel.create(data)
224 return res
225 }
226
227 /**
228 * change day publish info
229 * if data had publish record, update it
230 * @param data
231 */
232 async upDayPublishInfo(data: Pick<PublishRecord, 'userId'>) {
233 const today = new Date()
234 return this.publishDayInfoModel
235 .findOneAndUpdate(
236 {
237 userId: data.userId,
238 createdAt: {
239 $gte: new Date(
240 today.getFullYear(),
241 today.getMonth(),
242 today.getDate(),
243 ),
244 $lt: new Date(
245 today.getFullYear(),
246 today.getMonth(),
247 today.getDate() + 1,
248 ),
249 },
250 },
251 {
252 $inc: { publishTotal: 1 },
253 },
254 {
255 upsert: true,
256 new: true,
257 },
258 )
259 .lean({ virtuals: true })
260 .exec()
261 }
262
263 /**
264 * 获取发布每日信息列表
265 * @param inFilter
266 * @param pageInfo
267 * @returns
268 */
269 async getPublishDayInfoList(
270 inFilter: {
271 userId: string
272 time?: [Date, Date]
273 },
274 pageInfo: {
275 pageNo: number
276 pageSize: number
277 },
278 ) {
279 const { pageNo, pageSize } = pageInfo
280 const filter: RootFilterQuery<PublishDayInfo> = {
281 userId: inFilter.userId,
282 ...(inFilter.time && {
283 createdAt: { $gte: inFilter.time[0], $lte: inFilter.time[1] },
284 }),
285 }
286
287 const total = await this.publishDayInfoModel.countDocuments(filter)
288 const list = await this.publishDayInfoModel
289 .find(filter)
290 .sort({ createdAt: -1 })
291 .skip((pageNo! - 1) * pageSize)
292 .limit(pageSize)
293 .lean({ virtuals: true })
294
295 return {
296 total,
297 list,
298 }
299 }
300
301 // 发放发布奖励
302 async getUserRecordInfo(userId: string) {
303 // 1. 查询发放状态
304 const recordInfo = await this.publishInfoModel.findOne({
305 userId,
306 }).lean({ virtuals: true })
307 return recordInfo
308 }
309
310 // 获取发布信息数据
311 async getPublishInfoData(userId: string) {
312 const res = await this.publishInfoModel.findOne({ userId }).lean({ virtuals: true })
313 return res
314 }
315
316 async updateUserPublishInfo(userId: string, data: Partial<PublishInfo>) {
317 const res = await this.publishInfoModel.updateOne({ userId }, {
318 $set: data,
319 })
320 return res
321 }
322
323 // 根据获取发布记录信息
324 async getPublishRecordByDataId(accountType: AccountType, dataId: string) {
325 const res = await this.publishInfoModel.findOne({ accountType, dataId }).lean({ virtuals: true })
326 return res
327 }
328
329 async getPublishRecordDetail(data: {
330 flowId: string
331 userId: string
332 }) {
333 const publishRecord = await this.publishRecordModel.findOne({
334 flowId: data.flowId,
335 userId: data.userId,
336 }).lean({ virtuals: true })
337 return publishRecord
338 }
339
340 async getPublishRecordByTaskId(taskId: string, userId: string) {
341 const res = await this.publishRecordModel
342 .findOne({ taskId, userId })
343 .sort({ createdAt: -1 })
344 .lean({ virtuals: true })
345 return res
346 }
347
348 async listPublishedByTaskId(
349 taskId: string,
350 query?: {
351 accountType?: AccountType
352 },
353 ): Promise<PublishRecord[]> {
354 return this.publishRecordModel
355 .find({
356 taskId,
357 status: PublishStatus.Published,
358 ...(query?.accountType && { accountType: query.accountType }),
359 })
360 .sort({ createdAt: -1 })
361 .lean({ virtuals: true })
362 .exec()
363 }
364
365 async getPublishedByTaskIdAndDataId(taskId: string, dataId: string): Promise<PublishRecord | null> {
366 return this.publishRecordModel
367 .findOne({
368 taskId,
369 dataId,
370 status: PublishStatus.Published,
371 })
372 .sort({ createdAt: -1 })
373 .lean({ virtuals: true })
374 .exec()
375 }
376
377 async listPublishedByPublishTimeRangeForCrawlerMonitor(
378 startDate: Date,
379 endDate: Date,
380 taskId?: string,
381 accountType?: string,
382 ): Promise<PublishRecordPostDataCrawlerMonitorItem[]> {
383 return this.publishRecordModel.aggregate<PublishRecordPostDataCrawlerMonitorItem>([
384 {
385 $match: {
386 status: PublishStatus.Published,
387 publishTime: { $gte: startDate, $lt: endDate },
388 source: { $nin: [PublishRecordSource.TaskLink, PublishRecordSource.OfflineQr] },
389 dataId: { $exists: true, $nin: [null, ''] },
390 workStatus: { $nin: POST_DATA_UNAVAILABLE_WORK_STATUSES },
391 workLink: { $exists: true, $nin: [null, ''] },
392 ...(taskId && { taskId }),
393 ...(accountType && { accountType }),
394 },
395 },
396 { $sort: { publishTime: -1, createdAt: -1 } },
397 {
398 $group: {
399 _id: {
400 accountType: '$accountType',
401 dataId: '$dataId',
402 },
403 publishRecordId: { $first: { $toString: '$_id' } },
404 materialGroupId: { $first: '$materialGroupId' },
405 dataId: { $first: '$dataId' },
406 taskId: { $first: '$taskId' },
407 accountType: { $first: '$accountType' },
408 accountId: { $first: '$accountId' },
409 uid: { $first: '$uid' },
410 workLink: { $first: '$workLink' },
411 originalWorkLink: { $first: '$originalWorkLink' },
412 publishTime: { $first: '$publishTime' },
413 status: { $first: '$status' },
414 workStatus: { $first: '$workStatus' },
415 errorMessage: { $first: '$errorMsg' },
416 createdAt: { $first: '$createdAt' },
417 updatedAt: { $first: '$updatedAt' },
418 },
419 },
420 {
421 $project: {
422 _id: 0,
423 publishRecordId: 1,
424 materialGroupId: 1,
425 dataId: 1,
426 taskId: 1,
427 accountType: 1,
428 accountId: 1,
429 uid: 1,
430 workLink: 1,
431 originalWorkLink: 1,
432 publishTime: 1,
433 status: 1,
434 workStatus: 1,
435 errorMessage: 1,
436 createdAt: 1,
437 updatedAt: 1,
438 },
439 },
440 { $sort: { publishTime: -1 } },
441 ]).exec()
442 }
443
444 async listOfflineQrPublishedByCreatedAtRangeForCrawlerMonitor(
445 startDate: Date,
446 endDate: Date,
447 accountType?: string,
448 ): Promise<PublishRecordPostDataCrawlerMonitorItem[]> {
449 return this.publishRecordModel.aggregate<PublishRecordPostDataCrawlerMonitorItem>([
450 {
451 $match: {
452 status: PublishStatus.Published,
453 source: PublishRecordSource.OfflineQr,
454 createdAt: { $gte: startDate, $lt: endDate },
455 dataId: { $exists: true, $nin: [null, ''] },
456 workStatus: { $nin: POST_DATA_UNAVAILABLE_WORK_STATUSES },
457 isDeleted: { $ne: true },
458 ...(accountType && { accountType }),
459 },
460 },
461 { $sort: { createdAt: -1, publishTime: -1 } },
462 {
463 $group: {
464 _id: {
465 accountType: '$accountType',
466 uid: '$uid',
467 dataId: '$dataId',
468 },
469 publishRecordId: { $first: { $toString: '$_id' } },
470 materialGroupId: { $first: '$materialGroupId' },
471 dataId: { $first: '$dataId' },
472 taskId: { $first: '$taskId' },
473 accountType: { $first: '$accountType' },
474 accountId: { $first: '$accountId' },
475 uid: { $first: '$uid' },
476 workLink: { $first: '$workLink' },
477 originalWorkLink: { $first: '$originalWorkLink' },
478 publishTime: { $first: '$publishTime' },
479 status: { $first: '$status' },
480 workStatus: { $first: '$workStatus' },
481 errorMessage: { $first: '$errorMsg' },
482 createdAt: { $first: '$createdAt' },
483 updatedAt: { $first: '$updatedAt' },
484 },
485 },
486 {
487 $project: {
488 _id: 0,
489 publishRecordId: 1,
490 materialGroupId: 1,
491 dataId: 1,
492 taskId: 1,
493 accountType: 1,
494 accountId: 1,
495 uid: 1,
496 workLink: 1,
497 originalWorkLink: 1,
498 publishTime: 1,
499 status: 1,
500 workStatus: 1,
501 errorMessage: 1,
502 createdAt: 1,
503 updatedAt: 1,
504 },
505 },
506 { $sort: { createdAt: -1 } },
507 ]).exec()
508 }
509
510 async listPublishedByTaskIdAndDataId(taskId: string, dataId: string): Promise<PublishRecord[]> {
511 return this.publishRecordModel
512 .find({
513 taskId,
514 dataId,
515 status: PublishStatus.Published,
516 })
517 .sort({ createdAt: -1 })
518 .lean({ virtuals: true })
519 .exec()
520 }
521
522 async getPublishRecordByDataIdAndUid(uid: string, dataId: string) {
523 const res = await this.publishRecordModel
524 .findOne({ uid, dataId })
525 .sort({ createdAt: -1 })
526 .lean({ virtuals: true })
527 return res
528 }
529
530 async updateWorkStatusById(id: string, workStatus: WorkStatus) {
531 return await this.updateById(id, {
532 $set: {
533 workStatus,
534 },
535 })
536 }
537
538 // 完成发布
539 async donePublishRecord(
540 filter: { dataId: string, uid: string },
541 data: {
542 workLink?: string
543 dataOption?: unknown
544 },
545 ) {
546 const res = await this.publishRecordModel.findOneAndUpdate({ ...filter, status: PublishStatus.Publishing }, {
547 $set: {
548 status: PublishStatus.Published,
549 ...data,
550 },
551 }).lean({ virtuals: true })
552 return res
553 }
554
555 // 发布失败
556 async failPublishRecordByData(
557 filter: { dataId: string, uid: string },
558 errorMsg: string,
559 ) {
560 const res = await this.publishRecordModel.findOneAndUpdate({ ...filter, status: PublishStatus.Publishing }, {
561 $set: {
562 status: PublishStatus.Failed,
563 errorMsg,
564 queued: false,
565 inQueue: false,
566 },
567 }).lean({ virtuals: true })
568 return res
569 }
570
571 async getActiveUserTotal(startDate: Date, endDate: Date): Promise<number> {
572 const res = await this.publishRecordModel.distinct('userId', {
573 createdAt: { $gte: startDate, $lte: endDate },
574 })
575 return res.length
576 }
577
578 /**
579 * 根据草稿箱ID获取发布记录列表
580 * @param materialGroupId 草稿箱ID
581 * @param query 查询条件
582 * @returns 发布记录列表和总数
583 */
584 async getPublishRecordListByMaterialGroupId(
585 materialGroupId: string,
586 query?: {
587 status?: PublishStatus
588 accountType?: AccountType
589 pageNo?: number
590 pageSize?: number
591 },
592 ): Promise<{ records: PublishRecord[], total: number }> {
593 const filters: RootFilterQuery<PublishRecord> = {
594 materialGroupId,
595 ...(query?.status !== undefined && { status: query.status }),
596 ...(query?.accountType !== undefined && { accountType: query.accountType }),
597 }
598
599 const pageNo = query?.pageNo || 1
600 const pageSize = query?.pageSize || 20
601
602 const total = await this.publishRecordModel.countDocuments(filters)
603 const records = await this.publishRecordModel
604 .find(filters)
605 .sort({ createdAt: -1 })
606 .skip((pageNo - 1) * pageSize)
607 .limit(pageSize)
608 .lean({ virtuals: true })
609 .exec()
610
611 return { records, total }
612 }
613
614 /**
615 * 根据素材组ID获取已发布的记录列表(用于统计数据融合)
616 * 仅返回 status=PUBLISHED 且 dataId 非空的记录
617 * @param materialGroupId 素材组ID
618 * @param query 查询条件
619 * @returns 发布记录列表和总数
620 */
621 async listPublishedByMaterialGroupIdWithPagination(
622 materialGroupId: string,
623 query?: {
624 accountType?: AccountType
625 source?: PublishRecordSource
626 pageNo?: number
627 pageSize?: number
628 },
629 ): Promise<{ records: PublishRecord[], total: number }> {
630 const filters: RootFilterQuery<PublishRecord> = {
631 materialGroupId,
632 status: PublishStatus.Published,
633 dataId: { $exists: true, $ne: '' },
634 workLink: { $exists: true, $nin: ['', null] },
635 source: query?.source ?? { $nin: [PublishRecordSource.TaskLink, PublishRecordSource.OfflineQr] },
636 ...(query?.accountType !== undefined && { accountType: query.accountType }),
637 }
638
639 const pageNo = query?.pageNo || 1
640 const pageSize = query?.pageSize || 20
641
642 const total = await this.publishRecordModel.countDocuments(filters)
643 const records = await this.publishRecordModel
644 .find(filters)
645 .sort({ createdAt: -1 })
646 .skip((pageNo - 1) * pageSize)
647 .limit(pageSize)
648 .lean({ virtuals: true })
649 .exec()
650
651 return { records, total }
652 }
653
654 async listPublishedByMaterialGroupId(
655 materialGroupId: string,
656 query?: {
657 accountType?: AccountType
658 source?: PublishRecordSource
659 },
660 ): Promise<PublishRecord[]> {
661 const filters: RootFilterQuery<PublishRecord> = {
662 materialGroupId,
663 status: PublishStatus.Published,
664 dataId: { $exists: true, $ne: '' },
665 workLink: { $exists: true, $nin: ['', null] },
666 source: query?.source ?? { $nin: [PublishRecordSource.TaskLink, PublishRecordSource.OfflineQr] },
667 ...(query?.accountType !== undefined && { accountType: query.accountType }),
668 }
669
670 return this.publishRecordModel
671 .find(filters)
672 .sort({ createdAt: -1 })
673 .lean({ virtuals: true })
674 .exec()
675 }
676
677 // ----- 迁移 ----
678 async add(publishTask: Partial<PublishRecord>) {
679 return await this.publishRecordModel.create(publishTask)
680 }
681
682 async updateQueueId(taskId: string, queueId: string, queued?: boolean) {
683 return await this.publishRecordModel.updateOne({ id: taskId }, { queueId, inQueue: queued === undefined ? undefined : queued }).exec()
684 }
685
686 async findOneById(id: string) {
687 return await this.publishRecordModel.findOne({ _id: id }).lean({ virtuals: true }).exec()
688 }
689
690 async findOneByFlowId(flowId: string) {
691 return await this.publishRecordModel.findOne({ flowId }).lean({ virtuals: true }).exec()
692 }
693
694 async findOneByData(dataId: string, uid: string) {
695 return await this.publishRecordModel.findOne({ dataId, uid }).lean({ virtuals: true }).exec()
696 }
697
698 async findOneByDataId(dataId: string, accountType: AccountType) {
699 return await this.publishRecordModel.findOne({ dataId, accountType }).lean({ virtuals: true }).exec()
700 }
701
702 async complete(id: string, dataId: string, data?: {
703 workLink: string
704 dataOption?: Record<string, any>
705 }) {
706 return await this.publishRecordModel.updateOne(
707 { _id: id },
708 {
709 status: PublishStatus.Published,
710 errorMsg: '',
711 dataId,
712 workLink: data?.workLink,
713 publishTime: new Date(),
714 queued: false,
715 inQueue: false,
716 },
717 ).exec()
718 }
719
720 async fail(id: string, errMsg: string) {
721 return await this.publishRecordModel.updateOne(
722 { _id: id },
723 { status: PublishStatus.Failed, errorMsg: errMsg },
724 ).exec()
725 }
726
727 async updateStatus(id: string, status: PublishStatus, msg?: string) {
728 return await this.publishRecordModel.updateOne(
729 { _id: id },
730 { $set: { status, errorMsg: msg } },
731 ).exec()
732 }
733
734 async getPublishTaskListByTime(end: Date): Promise<PublishRecord[]> {
735 const filters: RootFilterQuery<PublishRecord> = {
736 publishTime: { $lte: end },
737 status: PublishStatus.WaitingForPublish,
738 }
739 const list = await this.publishRecordModel.find(filters).sort({
740 publishTime: 1,
741 }).lean({ virtuals: true })
742
743 return list
744 }
745
746 async getStalePublishingTasks(cutoffTime: Date, limit: number): Promise<PublishRecord[]> {
747 const filters: RootFilterQuery<PublishRecord> = {
748 status: PublishStatus.Publishing,
749 updatedAt: { $lte: cutoffTime },
750 }
751 return await this.publishRecordModel
752 .find(filters)
753 .sort({ updatedAt: 1 })
754 .limit(limit)
755 .lean({ virtuals: true })
756 .exec()
757 }
758
759 async listByFilter(query: any): Promise<PublishRecord[]> {
760 const filters: RootFilterQuery<PublishRecord> = {
761 userId: query.userId,
762 source: query.source ?? { $nin: [PublishRecordSource.TaskLink, PublishRecordSource.OfflineQr] },
763 ...(query.flowId !== undefined && { flowId: query.flowId }),
764 ...(query.accountId !== undefined && { accountId: query.accountId }),
765 ...(query.accountType !== undefined && {
766 accountType: query.accountType,
767 }),
768 ...(query.status !== undefined && {
769 status: query.status,
770 }),
771 ...(query.type !== undefined && { type: query.type }),
772 ...(query.time !== undefined
773 && query.time.length === 2 && {
774 publishTime: { $gte: query.time[0], $lte: query.time[1] },
775 }),
776 ...(query.uid !== undefined && { uid: query.uid }),
777 }
778 const db = this.publishRecordModel.find(filters).sort({
779 createdAt: -1,
780 }).lean({ virtuals: true })
781 const list = await db.exec()
782
783 return list
784 }
785
786 async getLatestPublishedByUserIdAndWorkIdentity(query: {
787 userId: string
788 accountType: AccountType
789 accountId?: string
790 platformWorkId: string
791 }): Promise<PublishRecord | null> {
792 const filters: RootFilterQuery<PublishRecord> = {
793 userId: query.userId,
794 accountType: query.accountType,
795 status: PublishStatus.Published,
796 $or: [
797 { platformWorkId: query.platformWorkId },
798 { dataId: query.platformWorkId },
799 { uniqueId: query.platformWorkId },
800 { uniqueId: `${query.accountType}_${query.platformWorkId}` },
801 { workLink: query.platformWorkId },
802 { originalWorkLink: query.platformWorkId },
803 ],
804 }
805 if (query.accountId) {
806 filters.accountId = query.accountId
807 }
808
809 return this.publishRecordModel
810 .findOne(filters)
811 .sort({ updatedAt: -1, createdAt: -1 })
812 .lean({ virtuals: true })
813 .exec()
814 }
815
816 async listQueuedByFilter(query: {
817 userId: string
818 accountId?: string
819 accountType?: AccountType
820 time?: [Date?, Date?, ...unknown[]]
821 }): Promise<PublishRecord[]> {
822 const filters: RootFilterQuery<PublishRecord> = {
823 status: { $in: [PublishStatus.WaitingForPublish, PublishStatus.Queued] },
824 userId: query.userId,
825 source: { $nin: [PublishRecordSource.TaskLink, PublishRecordSource.OfflineQr] },
826 }
827 if (query.accountId) {
828 filters.accountId = query.accountId
829 }
830 if (query.accountType) {
831 filters.accountType = query.accountType
832 }
833 if (query.time && query.time.length === 2) {
834 filters.publishTime = { $gte: query.time[0], $lte: query.time[1] }
835 }
836 return this.publishRecordModel.find(filters).sort({
837 createdAt: -1,
838 }).lean({ virtuals: true })
839 }
840
841 async listPublishedByFilter(query: {
842 userId: string
843 accountId?: string
844 accountType?: AccountType
845 time?: [Date?, Date?, ...unknown[]]
846 }): Promise<PublishRecord[]> {
847 const filters: RootFilterQuery<PublishRecord> = {
848 status: PublishStatus.Published,
849 userId: query.userId,
850 source: { $nin: [PublishRecordSource.TaskLink, PublishRecordSource.OfflineQr] },
851 }
852 if (query.accountId) {
853 filters.accountId = query.accountId
854 }
855 if (query.accountType) {
856 filters.accountType = query.accountType
857 }
858 if (query.time && query.time.length === 2) {
859 filters.publishTime = { $gte: query.time[0], $lte: query.time[1] }
860 }
861 return this.publishRecordModel.find(filters).sort({
862 createdAt: -1,
863 }).lean({ virtuals: true })
864 }
865
866 async listPublishedTaskLinkRecords(query: {
867 userId: string
868 accountId?: string
869 accountType?: AccountType
870 flowId?: string
871 time?: [Date?, Date?, ...unknown[]]
872 }): Promise<PublishRecord[]> {
873 const filters: RootFilterQuery<PublishRecord> = {
874 status: PublishStatus.Published,
875 userId: query.userId,
876 source: PublishRecordSource.TaskLink,
877 }
878 if (query.accountId) {
879 filters.accountId = query.accountId
880 }
881 if (query.accountType) {
882 filters.accountType = query.accountType
883 }
884 if (query.flowId) {
885 filters.flowId = query.flowId
886 }
887 if (query.time && query.time.length === 2) {
888 filters.publishTime = { $gte: query.time[0], $lte: query.time[1] }
889 }
890
891 return this.publishRecordModel.find(filters).sort({
892 createdAt: -1,
893 }).lean({ virtuals: true })
894 }
895
896 async listByFlowId(
897 flowId: string,
898 ): Promise<PublishRecord[]> {
899 const filters: RootFilterQuery<PublishRecord> = {
900 flowId,
901 }
902 const list = await this.publishRecordModel.find(filters).sort({
903 publishTime: 1,
904 }).lean({ virtuals: true })
905 return list
906 }
907
908 async listByFlowIdAndUserId(flowId: string, userId: string): Promise<PublishRecord[]> {
909 return this.publishRecordModel.find({ flowId, userId }).sort({
910 publishTime: 1,
911 }).lean({ virtuals: true })
912 }
913
914 async updatePublishTaskStatus(
915 id: string,
916 newData: {
917 errorMsg?: string
918 errorData?: {
919 type: string
920 code: string
921 message: string
922 originalData?: Record<string, unknown>
923 }
924 status: PublishStatus
925 publishTime?: Date
926 queued?: boolean
927 inQueue?: boolean
928 },
929 ): Promise<boolean> {
930 const res = await this.publishRecordModel.updateOne({ _id: id }, newData)
931 return res.modifiedCount > 0
932 }
933
934 async updateAsPublishing(id: string, dataId: string, workLink?: string): Promise<boolean> {
935 const res = await this.publishRecordModel.updateOne(
936 { _id: id },
937 { $set: { status: PublishStatus.Publishing, dataId, workLink, errorMsg: '', inQueue: false, queued: false } },
938 ).exec()
939 return res.modifiedCount > 0
940 }
941
942 async deleteByIdAndUserId(id: string, userId: string): Promise<boolean> {
943 const res = await this.publishRecordModel.deleteOne({ _id: id, userId })
944 return res.deletedCount > 0
945 }
946
947 async delById(id: string): Promise<boolean> {
948 const res = await this.publishRecordModel.deleteOne({ _id: id })
949 return res.deletedCount > 0
950 }
951
952 async getByFlowIdAndUserId(flowId: string, userId: string) {
953 return await this.publishRecordModel.findOne({ flowId, userId }).lean({ virtuals: true }).exec()
954 }
955
956 async getByIdAndUserId(id: string, userId: string) {
957 return await this.publishRecordModel.findOne({ _id: id, userId }).lean({ virtuals: true }).exec()
958 }
959 }
960
960 lines TYPESCRIPT