chore: src/modules/knowledge/service/film.ts
This commit is contained in:
@@ -0,0 +1,127 @@
|
|||||||
|
import { KnowledgeFilmEntity } from './../entity/film';
|
||||||
|
import { Inject, Provide } from '@midwayjs/core';
|
||||||
|
import { BaseService } from '@cool-midway/core';
|
||||||
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
import { escapeObject } from '../utils/xss';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 知识库模块-电影信息
|
||||||
|
*/
|
||||||
|
@Provide()
|
||||||
|
export class KnowledgeFilmService extends BaseService {
|
||||||
|
@InjectEntityModel(KnowledgeFilmEntity)
|
||||||
|
knowledgeFilmEntity: Repository<KnowledgeFilmEntity>;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
ctx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增电影
|
||||||
|
* - 业务层查重:检查同名电影是否已存在
|
||||||
|
* - 对用户输入进行 XSS 过滤,防止存储型 XSS 攻击
|
||||||
|
* - 排除 posters 字段(JSON数组,不需要转义)
|
||||||
|
* @param params 电影数据
|
||||||
|
*/
|
||||||
|
async add(params: any) {
|
||||||
|
// 业务层查重:检查同名电影是否已存在
|
||||||
|
if (params.name) {
|
||||||
|
const exist = await this.knowledgeFilmEntity.findOne({
|
||||||
|
where: { name: params.name }
|
||||||
|
});
|
||||||
|
if (exist) {
|
||||||
|
throw new Error(`电影"${params.name}"已存在,请勿重复添加`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// XSS 过滤 - 排除 posters 字段(JSON 数组)
|
||||||
|
const safeParams = escapeObject(params, ['posters']);
|
||||||
|
return super.add(safeParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新电影
|
||||||
|
* - 对用户输入进行 XSS 过滤,防止存储型 XSS 攻击
|
||||||
|
* - 排除 posters 字段(JSON数组,不需要转义)
|
||||||
|
* @param params 电影数据
|
||||||
|
*/
|
||||||
|
async update(params: any) {
|
||||||
|
// XSS 过滤 - 排除 posters 字段(JSON 数组)
|
||||||
|
const safeParams = escapeObject(params, ['posters']);
|
||||||
|
return super.update(safeParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API: importFilms - 批量导入电影数据
|
||||||
|
* - 业务层查重:检查同名电影是否已存在,已存在则跳过
|
||||||
|
* - 将 Excel 导入的数据逐条插入数据库
|
||||||
|
* - 跳过名称为空的记录
|
||||||
|
* - 对文本字段进行 XSS 过滤
|
||||||
|
* @param films 电影数据数组(来自 Excel 解析)
|
||||||
|
* @returns 导入结果统计
|
||||||
|
*/
|
||||||
|
async importFilms(films: any[]) {
|
||||||
|
const successList: string[] = [];
|
||||||
|
const failList: { name: string; error: string }[] = [];
|
||||||
|
const skipList: string[] = [];
|
||||||
|
|
||||||
|
for (const film of films) {
|
||||||
|
// 跳过名称为空的记录
|
||||||
|
if (!film.name) {
|
||||||
|
failList.push({ name: film.name || '(空)', error: '名称不能为空' });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 业务层查重:检查同名电影是否已存在
|
||||||
|
const exist = await this.knowledgeFilmEntity.findOne({
|
||||||
|
where: { name: film.name }
|
||||||
|
});
|
||||||
|
if (exist) {
|
||||||
|
skipList.push(film.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 映射 Excel 列名到数据库字段
|
||||||
|
const filmData = {
|
||||||
|
name: film.name || '',
|
||||||
|
director: film.director || film['导演'] || film['导演/作者'] || '',
|
||||||
|
year: film.year || film['年份'] || null,
|
||||||
|
country: film.country || film['国家'] || '',
|
||||||
|
language: film.language || film['语言'] || '',
|
||||||
|
mainCharacters: film.mainCharacters || film['主要人物'] || '',
|
||||||
|
synopsis: film.synopsis || film['内容简介'] || '',
|
||||||
|
backgroundStory: film.backgroundStory || film['背景故事'] || '',
|
||||||
|
posters: film.posters || film['海报链接']
|
||||||
|
? [film.posters || film['海报链接']]
|
||||||
|
: [],
|
||||||
|
categoryId: film.categoryId ?? film['分类ID'] ?? film['分类'] ?? 45,
|
||||||
|
quality: film.quality || film['质量'] || film['质量评级'] || 'C',
|
||||||
|
watched: film.watched || film['是否已看'] || false,
|
||||||
|
doubanRating: film.doubanRating || film['豆瓣评分'] || null,
|
||||||
|
tmdbRating: film.tmdbRating || film['TMDB评分'] || null,
|
||||||
|
link: film.link || film['链接'] || '',
|
||||||
|
honors: film.honors || film['荣誉'] || '',
|
||||||
|
highlights: film.highlights || film['亮点所在'] || '',
|
||||||
|
whyWorthWatching: film.whyWorthWatching || film['为什么值得一看'] || ''
|
||||||
|
};
|
||||||
|
|
||||||
|
// XSS 过滤
|
||||||
|
const safeData = escapeObject(filmData, ['posters']);
|
||||||
|
await this.knowledgeFilmEntity.insert(safeData);
|
||||||
|
successList.push(filmData.name);
|
||||||
|
} catch (e: any) {
|
||||||
|
failList.push({ name: film.name, error: e.message || '导入失败' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: films.length,
|
||||||
|
success: successList.length,
|
||||||
|
fail: failList.length,
|
||||||
|
skip: skipList.length,
|
||||||
|
successList,
|
||||||
|
failList,
|
||||||
|
skipList
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user