import { assert } from 'oak-domain/lib/utils/assert'; import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid'; import { OakPreConditionUnsetException } from 'oak-domain/lib/types'; import { uniq } from 'oak-domain/lib/utils/lodash'; import { DATA_SUBSCRIBER_KEYS } from '../config/constants'; const triggers = [ { name: '在创建文章分类时,查询文章分类是否重名', entity: 'articleMenu', action: 'create', when: 'before', fn: async (event, context) => { const { operation: { data }, } = event; assert(!(data instanceof Array)); // 不可能是成组创建 if (data.name) { const { entity, entityId } = data; const [articleMenu] = await context.select('articleMenu', { data: { id: 1, name: 1, parentId: 1, }, filter: { entity, entityId, name: data.name, parentId: data.parentId ? data.parentId : { $exists: false, }, }, }, {}); if (articleMenu) { throw new OakPreConditionUnsetException(`父分类的同一子集中存在同名分类【${data.name}】,请重新输入`); } } return 0; }, }, { name: '在创建文章分类时,文章分类的父节点的【isLeaf】置为【true】', entity: 'articleMenu', action: 'create', when: 'after', fn: async (event, context) => { const { operation: { data, filter }, } = event; assert(!(data instanceof Array)); const { id } = data; const [articleMenu] = await context.select('articleMenu', { data: { id: 1, name: 1, parentId: 1, parent: { id: 1, isLeaf: 1, }, }, filter: { id, }, }, {}); if (articleMenu && articleMenu.parent && !articleMenu.parent.isLeaf) { await context.operate('articleMenu', { id: await generateNewIdAsync(), action: 'update', data: { isLeaf: true, }, filter: { id: articleMenu.parentId, }, }, { blockTrigger: true, }); } return 0; }, }, { name: '在删除文章分类前,将文章分类的父节点的【isLeaf】置为【false】', entity: 'articleMenu', action: 'remove', when: 'before', fn: async (event, context) => { const { operation: { data, filter }, } = event; const [articleMenu] = await context.select('articleMenu', { data: { id: 1, name: 1, parentId: 1, parent: { id: 1, isLeaf: 1, }, }, filter, }, {}); if (articleMenu && articleMenu.parentId) { const articleMenus = await context.select('articleMenu', { data: { id: 1, }, filter: { parentId: articleMenu.parentId, id: { $ne: articleMenu.id, }, }, }, {}); if (articleMenus.length === 0) { await context.operate('articleMenu', { id: await generateNewIdAsync(), action: 'update', data: { isLeaf: false, }, filter: { id: articleMenu.parentId, }, }, {}); } } return 0; }, }, { name: '在更新文章分类时,查询文章分类是否重名', entity: 'articleMenu', action: 'update', when: 'before', fn: async (event, context) => { const { operation: { data, filter }, } = event; assert(!(data instanceof Array)); // 不可能是成组创建 if (data.name) { const [articleMenu] = await context.select('articleMenu', { data: { id: 1, name: 1, parentId: 1, entity: 1, entityId: 1, }, filter, }, {}); if (articleMenu) { const [articleMenu2] = await context.select('articleMenu', { data: { id: 1, name: 1, parentId: 1, }, filter: { entity: articleMenu.entity, entityId: articleMenu.entityId, name: data.name, parentId: articleMenu.parentId ? articleMenu.parentId : { $exists: false, }, id: { $ne: articleMenu.id } }, }, {}); if (articleMenu2) { throw new OakPreConditionUnsetException(`父分类的同一子集中存在同名分类【${data.name}】,请重新输入`); } } } return 1; }, }, { name: '文章分类创建时,更新其最近编辑时间', entity: 'articleMenu', action: 'create', when: 'before', priority: 99, fn: async ({ operation }, context, option) => { const { id, data } = operation; data.latestAt = Date.now(); return 1; }, }, { name: '文章分类更新时,更新其最近编辑时间', entity: 'articleMenu', action: 'update', when: 'before', attributes: ['$$updateAt$$'], check: (operation) => { const { data } = operation; return typeof data.$$updateAt$$ === 'number' && data.$$updateAt$$ > 0; }, priority: 99, asRoot: true, fn: async ({ operation }, context, option) => { const { data, filter } = operation; data.latestAt = data.$$updateAt$$; return 1; }, }, { name: '文章分类的最近编辑时间更新时,更新其parent的最近编辑时间', entity: 'articleMenu', action: 'update', when: 'after', attributes: ['latestAt'], check: (operation) => { const { data } = operation; return typeof data.latestAt === 'number' && data.latestAt > 0; }, priority: 99, asRoot: true, fn: async ({ operation }, context, option) => { const { data, filter } = operation; const articleMenus = await context.select('articleMenu', { data: { id: 1, parentId: 1, }, filter, }, { forUpdate: true }); let count = 0; if (articleMenus && articleMenus.length > 0) { const parentIds = uniq(articleMenus.map((ele) => ele.parentId)); for (const parentId of parentIds) { if (parentId) { await context.operate('articleMenu', { id: await generateNewIdAsync(), action: 'update', data: { latestAt: data.latestAt, }, filter: { id: parentId, }, }, {}); count++; } } } return count; }, }, { name: '在删除文章分类前,更新其parent的最近编辑时间', entity: 'articleMenu', action: 'remove', when: 'before', priority: 99, asRoot: true, fn: async ({ operation }, context, option) => { const { data, filter } = operation; const articleMenus = await context.select('articleMenu', { data: { id: 1, parentId: 1, }, filter, }, { forUpdate: true }); let count = 0; if (articleMenus && articleMenus.length > 0) { const now = Date.now(); const parentIds = uniq(articleMenus.map((ele) => ele.parentId)); for (const parentId of parentIds) { if (parentId) { await context.operate('articleMenu', { id: await generateNewIdAsync(), action: 'update', data: { latestAt: now, }, filter: { id: parentId, }, }, {}); count++; } } } return count; } }, { name: '当articleMenu的isArticle更新时,通知相应的事件订阅', entity: 'articleMenu', action: 'update', when: 'before', attributes: ['isArticle'], check: (operation) => { const { data } = operation; return typeof data.isArticle === 'boolean'; }, fn: async ({ operation }, context, option) => { const { id, filter } = operation; const articleMenus = await context.select('articleMenu', { data: { id: 1, entityId: 1, }, filter, }, { forUpdate: true }); const entityIds = articleMenus.map((ele) => ele.entityId); let count = 0; if (entityIds && entityIds.length) { for (const entityId of entityIds) { context.saveOperationToEvent(id, `${DATA_SUBSCRIBER_KEYS.articleMenuUpdate}-${entityId}`); count++; } } return count; } }, ]; export default triggers;