ai-query对接新版freesun-agent接口的分支
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

181 lines
6.7 KiB

'use strict';
const { TEMP_POSITION_BASE } = require('./constants');
const { hasOwn, toInt, ensureObjectPayload } = require('./helpers');
const { ensureChapter, ensureBlock, ensureInstance } = require('./repository');
const { normalizeBlockConfigForStorage } = require('./dataSourceQuery');
const { resolveBlockPayload } = require('./blockPayloadResolver');
const {
reorderBlockSiblingsWithInsert,
reorderBlockSiblings,
} = require('./ordering');
const resolveInstanceBlockStoragePayload = async (
ctx,
instanceId,
blockType,
config,
contentSnapshot,
transaction
) => {
const normalizedBlockType = String(blockType || 'text').trim().toLowerCase();
const instance = await ensureInstance(ctx, instanceId, transaction);
const dataSourceId = toInt(instance.dataSourceId);
if (!dataSourceId && ['chart', 'table', 'kpi'].includes(normalizedBlockType)) {
throw '报表实例未绑定数据源';
}
const normalizedConfig = ['chart', 'table'].includes(normalizedBlockType)
? await normalizeBlockConfigForStorage(
ctx,
instanceId,
normalizedBlockType,
config || {},
transaction
)
: ensureObjectPayload(config || {}, 'config');
return resolveBlockPayload(ctx, {
blockType: normalizedBlockType,
dataSourceId,
config: normalizedConfig,
contentSnapshot: contentSnapshot || null,
transaction,
});
};
module.exports.createBlock = async (ctx, next) => {
const transaction = await ctx.app.fs.dc.orm.transaction();
try {
const { models } = ctx.app.fs.dc;
const instanceId = toInt(ctx.params.instanceId);
const chapterId = toInt(ctx.params.chapterId);
if (!instanceId || !chapterId) throw '缺少参数';
await ensureChapter(ctx, instanceId, chapterId, transaction);
const { blockType, position, config, contentSnapshot } = ctx.request.body || {};
const normalizedBlockType = String(blockType || 'text').trim().toLowerCase();
const storagePayload = await resolveInstanceBlockStoragePayload(
ctx,
instanceId,
normalizedBlockType,
config || {},
contentSnapshot || null,
transaction
);
const created = await models.ReportBlock.create({
instanceId,
chapterId,
blockType: normalizedBlockType,
position: TEMP_POSITION_BASE - 1,
config: storagePayload.config,
contentSnapshot: storagePayload.contentSnapshot,
updatedAt: new Date(),
}, {
transaction,
returning: true,
});
await reorderBlockSiblingsWithInsert(ctx, chapterId, created.id, position, transaction);
const fresh = await models.ReportBlock.findByPk(created.id, { transaction });
await transaction.commit();
ctx.body = fresh;
ctx.status = 200;
} catch (error) {
await transaction.rollback();
ctx.logger.log(error);
ctx.status = 400;
ctx.body = { message: typeof error === 'string' ? error : '创建内容块失败' };
}
};
module.exports.updateBlock = async (ctx, next) => {
const transaction = await ctx.app.fs.dc.orm.transaction();
try {
const { models } = ctx.app.fs.dc;
const instanceId = toInt(ctx.params.instanceId);
const blockId = toInt(ctx.params.blockId);
if (!instanceId || !blockId) throw '缺少参数';
const block = await ensureBlock(ctx, instanceId, blockId, transaction);
const body = ctx.request.body || {};
const updateData = {};
if (hasOwn(body, 'blockType')) {
updateData.blockType = String(body.blockType || 'text').trim().toLowerCase();
}
updateData.updatedAt = new Date();
if (hasOwn(body, 'config') || hasOwn(body, 'blockType')) {
const finalBlockType = hasOwn(body, 'blockType') ? updateData.blockType : block.blockType;
const finalConfig = hasOwn(body, 'config') ? (body.config || {}) : (block.config || {});
const finalContentSnapshot = hasOwn(body, 'contentSnapshot')
? body.contentSnapshot
: block.contentSnapshot;
const storagePayload = await resolveInstanceBlockStoragePayload(
ctx,
instanceId,
finalBlockType,
finalConfig,
finalContentSnapshot,
transaction
);
updateData.config = storagePayload.config;
updateData.contentSnapshot = storagePayload.contentSnapshot;
} else if (hasOwn(body, 'contentSnapshot')) {
updateData.contentSnapshot = body.contentSnapshot || null;
}
const oldChapterId = block.chapterId;
const nextChapterId = hasOwn(body, 'chapterId') ? toInt(body.chapterId) : block.chapterId;
if (!nextChapterId) throw '参数错误: chapterId';
await ensureChapter(ctx, instanceId, nextChapterId, transaction);
const needMove = hasOwn(body, 'chapterId') || hasOwn(body, 'position');
if (!needMove) {
await models.ReportBlock.update(updateData, { where: { id: blockId }, transaction });
await transaction.commit();
ctx.status = 204;
return;
}
updateData.chapterId = nextChapterId;
updateData.position = TEMP_POSITION_BASE - 1;
await models.ReportBlock.update(updateData, { where: { id: blockId }, transaction });
if (oldChapterId !== nextChapterId) {
await reorderBlockSiblings(ctx, oldChapterId, transaction);
}
const targetPosition = hasOwn(body, 'position')
? body.position
: (oldChapterId === nextChapterId ? block.position : undefined);
await reorderBlockSiblingsWithInsert(ctx, nextChapterId, blockId, targetPosition, transaction);
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.logger.log(error);
ctx.status = 400;
ctx.body = { message: typeof error === 'string' ? error : '更新内容块失败' };
}
};
module.exports.deleteBlock = async (ctx, next) => {
const transaction = await ctx.app.fs.dc.orm.transaction();
try {
const { models } = ctx.app.fs.dc;
const instanceId = toInt(ctx.params.instanceId);
const blockId = toInt(ctx.params.blockId);
if (!instanceId || !blockId) throw '缺少参数';
const block = await ensureBlock(ctx, instanceId, blockId, transaction);
await models.ReportBlock.destroy({
where: { id: blockId, instanceId },
transaction,
});
await reorderBlockSiblings(ctx, block.chapterId, transaction);
await transaction.commit();
ctx.status = 204;
} catch (error) {
await transaction.rollback();
ctx.logger.log(error);
ctx.status = 400;
ctx.body = { message: typeof error === 'string' ? error : '删除内容块失败' };
}
};