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.
 
 
 

229 lines
8.9 KiB

'use strict';
const { hasOwn, toInt, parsePagination, ensureCreatedBy, normalizeNullableInt } = require('./helpers');
const {
ensureDataSource,
ensureInstance,
ensureTemplate,
resolveSchemaVersion,
getInstanceChapterTree,
createChapterTreeFromPayload,
} = require('./repository');
const {
ensureHttpUrl,
downloadDocxFile,
convertDocxToHtml,
parseDocxHtmlToChapters,
} = require('./docxImport');
const { buildDocxImportChapterPayload } = require('./tree');
module.exports.getInstances = async (ctx, next) => {
try {
const { models, ORM: { Op } } = ctx.app.fs.dc;
const { offset, limit } = parsePagination(ctx.request.query);
const where = {};
const name = String(ctx.request.query.name || '').trim();
const type = String(ctx.request.query.type || '').trim();
const createdBy = String(ctx.request.query.createdBy || '').trim();
const templateId = toInt(ctx.request.query.templateId);
const departmentId = normalizeNullableInt(ctx.request.query.departmentId, 'departmentId');
if (name) where.name = { [Op.like]: `%${name}%` };
if (type) where.type = type;
if (createdBy) where.createdBy = createdBy;
if (templateId) where.templateId = templateId;
if (departmentId) where.departmentId = departmentId;
const list = await models.ReportInstance.findAndCountAll({
where,
order: [['id', 'DESC']],
include: [
{ model: models.ReportTemplate, required: false },
{ model: models.ReportDataSource, required: false },
{ model: models.ReportSchemaVersion, required: false },
],
offset,
limit,
});
ctx.body = { count: list.count, rows: list.rows };
ctx.status = 200;
} catch (error) {
ctx.logger.log(error);
ctx.status = 400;
ctx.body = { message: typeof error === 'string' ? error : '获取报表实例列表失败' };
}
};
module.exports.createInstance = async (ctx, next) => {
const transaction = await ctx.app.fs.dc.orm.transaction();
try {
const { models } = ctx.app.fs.dc;
const body = ctx.request.body || {};
const { name, dataSourceId, schemaVersionId, type, templateId, chapters } = body;
const createdBy = ensureCreatedBy(body);
const departmentId = normalizeNullableInt(body.departmentId, 'departmentId');
if (!String(name || '').trim()) throw '缺少参数: name';
await ensureDataSource(ctx, dataSourceId, transaction);
const schemaVersion = await resolveSchemaVersion(ctx, schemaVersionId, transaction);
let parsedTemplateId = null;
if (templateId !== null && templateId !== undefined && templateId !== '') {
const template = await ensureTemplate(ctx, templateId, transaction);
parsedTemplateId = template.id;
}
const created = await models.ReportInstance.create({
templateId: parsedTemplateId,
schemaVersionId: schemaVersion.id,
name: String(name).trim(),
type: String(type || 'general'),
dataSourceId: toInt(dataSourceId),
createdBy,
departmentId,
}, {
transaction,
returning: true,
});
if (Array.isArray(chapters) && chapters.length) {
await createChapterTreeFromPayload(ctx, created.id, null, chapters, transaction);
}
const chapterTree = await getInstanceChapterTree(ctx, created.id, transaction);
await transaction.commit();
ctx.body = {
...created.toJSON(),
chapters: chapterTree,
};
ctx.status = 200;
} catch (error) {
await transaction.rollback();
ctx.logger.log(error);
ctx.status = 400;
ctx.body = { message: typeof error === 'string' ? error : '创建报表实例失败' };
}
};
module.exports.importInstanceFromDocx = async (ctx, next) => {
const transaction = await ctx.app.fs.dc.orm.transaction();
try {
const { models } = ctx.app.fs.dc;
const body = ctx.request.body || {};
const { name, dataSourceId, schemaVersionId, type, sourceFileUrl } = body;
const createdBy = ensureCreatedBy(body);
const departmentId = normalizeNullableInt(body.departmentId, 'departmentId');
if (!String(name || '').trim()) throw 'missing param: name';
const normalizedSourceFileUrl = ensureHttpUrl(sourceFileUrl, 'sourceFileUrl');
await ensureDataSource(ctx, dataSourceId, transaction);
const schemaVersion = await resolveSchemaVersion(ctx, schemaVersionId, transaction);
const downloadedFile = await downloadDocxFile(normalizedSourceFileUrl);
const sourceFileName = String(downloadedFile.sourceFileName || '').trim() || 'import.docx';
const html = await convertDocxToHtml(ctx, downloadedFile.fileBuffer);
const chapterNodes = parseDocxHtmlToChapters(html);
const chapterPayload = buildDocxImportChapterPayload(
chapterNodes,
normalizedSourceFileUrl,
sourceFileName
);
const created = await models.ReportInstance.create({
templateId: null,
schemaVersionId: schemaVersion.id,
name: String(name).trim(),
type: String(type || 'general'),
dataSourceId: toInt(dataSourceId),
createdBy,
departmentId,
sourceFileUrl: normalizedSourceFileUrl,
sourceFileName,
}, {
transaction,
returning: true,
});
await createChapterTreeFromPayload(ctx, created.id, null, chapterPayload, transaction);
const chapters = await getInstanceChapterTree(ctx, created.id, transaction);
await transaction.commit();
ctx.body = {
...created.toJSON(),
chapters,
};
ctx.status = 200;
} catch (error) {
await transaction.rollback();
ctx.logger.log(error);
ctx.status = 400;
ctx.body = {
message: typeof error === 'string'
? error
: (error?.message || 'failed to import report instance from docx'),
};
}
};
module.exports.getInstanceDetail = async (ctx, next) => {
try {
const { models } = ctx.app.fs.dc;
const instanceId = toInt(ctx.params.instanceId);
if (!instanceId) throw '缺少参数: instanceId';
const instance = await models.ReportInstance.findByPk(instanceId, {
include: [
{ model: models.ReportTemplate, required: false },
{ model: models.ReportDataSource, required: false },
{ model: models.ReportSchemaVersion, required: false },
],
});
if (!instance) throw '报表实例不存在';
const chapters = await getInstanceChapterTree(ctx, instanceId);
ctx.body = {
...instance.toJSON(),
chapters,
};
ctx.status = 200;
} catch (error) {
ctx.logger.log(error);
ctx.status = 400;
ctx.body = { message: typeof error === 'string' ? error : '获取报表实例详情失败' };
}
};
module.exports.updateInstance = async (ctx, next) => {
try {
const { models } = ctx.app.fs.dc;
const instanceId = toInt(ctx.params.instanceId);
if (!instanceId) throw '缺少参数: instanceId';
await ensureInstance(ctx, instanceId);
const body = ctx.request.body || {};
const updateData = {};
if (hasOwn(body, 'name')) updateData.name = body.name ? String(body.name).trim() : '';
if (hasOwn(body, 'type')) updateData.type = body.type ? String(body.type).trim() : 'general';
if (hasOwn(body, 'templateId')) updateData.templateId = body.templateId ? toInt(body.templateId) : null;
if (hasOwn(body, 'exportedAt')) updateData.exportedAt = body.exportedAt ? new Date(body.exportedAt) : null;
if (hasOwn(body, 'dataSourceId')) {
await ensureDataSource(ctx, body.dataSourceId);
updateData.dataSourceId = toInt(body.dataSourceId);
}
if (hasOwn(body, 'departmentId')) updateData.departmentId = normalizeNullableInt(body.departmentId, 'departmentId');
if (hasOwn(body, 'schemaVersionId')) {
const schemaVersion = await resolveSchemaVersion(ctx, body.schemaVersionId);
updateData.schemaVersionId = schemaVersion.id;
}
await models.ReportInstance.update(updateData, { where: { id: instanceId } });
ctx.status = 204;
} catch (error) {
ctx.logger.log(error);
ctx.status = 400;
ctx.body = { message: typeof error === 'string' ? error : '更新报表实例失败' };
}
};
module.exports.deleteInstance = async (ctx, next) => {
try {
const { models } = ctx.app.fs.dc;
const instanceId = toInt(ctx.params.instanceId);
if (!instanceId) throw '缺少参数: instanceId';
await ensureInstance(ctx, instanceId);
await models.ReportInstance.destroy({ where: { id: instanceId } });
ctx.status = 204;
} catch (error) {
ctx.logger.log(error);
ctx.status = 400;
ctx.body = { message: typeof error === 'string' ? error : '删除报表实例失败' };
}
};