forked from yoone/API
206 lines
7.5 KiB
TypeScript
206 lines
7.5 KiB
TypeScript
import { Provide } from '@midwayjs/core';
|
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
|
import { Repository, Like } from 'typeorm';
|
|
import { Dict } from '../entity/dict.entity';
|
|
import { DictItem } from '../entity/dict_item.entity';
|
|
import { CreateDictDTO, UpdateDictDTO } from '../dto/dict.dto';
|
|
import { CreateDictItemDTO, UpdateDictItemDTO } from '../dto/dict.dto';
|
|
import * as xlsx from 'xlsx';
|
|
|
|
@Provide()
|
|
export class DictService {
|
|
|
|
@InjectEntityModel(Dict)
|
|
dictModel: Repository<Dict>;
|
|
|
|
@InjectEntityModel(DictItem)
|
|
dictItemModel: Repository<DictItem>;
|
|
|
|
// 格式化名称为 kebab-case
|
|
private formatName(name: string): string {
|
|
// 只替换空格和下划线
|
|
return String(name).replace(/[_\s]+/g, '-').toLowerCase();
|
|
}
|
|
|
|
// 生成并返回字典的XLSX模板
|
|
getDictXLSXTemplate() {
|
|
// 定义表头
|
|
const headers = ['name', 'title'];
|
|
// 创建一个新的工作表
|
|
const ws = xlsx.utils.aoa_to_sheet([headers]);
|
|
// 创建一个新的工作簿
|
|
const wb = xlsx.utils.book_new();
|
|
// 将工作表添加到工作簿
|
|
xlsx.utils.book_append_sheet(wb, ws, 'Dicts');
|
|
// 将工作簿写入缓冲区
|
|
return xlsx.write(wb, { type: 'buffer', bookType: 'xlsx' });
|
|
}
|
|
|
|
// 从XLSX文件导入字典
|
|
async importDictsFromXLSX(buffer: Buffer) {
|
|
// 读取缓冲区中的工作簿
|
|
const wb = xlsx.read(buffer, { type: 'buffer' });
|
|
// 获取第一个工作表的名称
|
|
const wsname = wb.SheetNames[0];
|
|
// 获取第一个工作表
|
|
const ws = wb.Sheets[wsname];
|
|
// 将工作表转换为JSON对象数组
|
|
const data = xlsx.utils.sheet_to_json(ws, { header: ['name', 'title'] }).slice(1);
|
|
// 创建要保存的字典实体数组
|
|
const dicts = data.map((row: any) => {
|
|
const dict = new Dict();
|
|
dict.name = this.formatName(row.name);
|
|
dict.title = row.title;
|
|
return dict;
|
|
});
|
|
// 保存字典实体数组到数据库
|
|
await this.dictModel.save(dicts);
|
|
// 返回成功导入的记录数
|
|
return { success: true, count: dicts.length };
|
|
}
|
|
|
|
// 生成并返回字典项的XLSX模板
|
|
getDictItemXLSXTemplate() {
|
|
const headers = ['name', 'title', 'titleCN', 'value', 'sort', 'image', 'shortName'];
|
|
const ws = xlsx.utils.aoa_to_sheet([headers]);
|
|
const wb = xlsx.utils.book_new();
|
|
xlsx.utils.book_append_sheet(wb, ws, 'DictItems');
|
|
return xlsx.write(wb, { type: 'buffer', bookType: 'xlsx' });
|
|
}
|
|
|
|
// 从XLSX文件导入字典项
|
|
async importDictItemsFromXLSX(buffer: Buffer, dictId: number) {
|
|
const dict = await this.dictModel.findOneBy({ id: dictId });
|
|
if (!dict) {
|
|
throw new Error('指定的字典不存在');
|
|
}
|
|
const wb = xlsx.read(buffer, { type: 'buffer' });
|
|
const wsname = wb.SheetNames[0];
|
|
const ws = wb.Sheets[wsname];
|
|
// 支持titleCN字段的导入
|
|
const data = xlsx.utils.sheet_to_json(ws, { header: ['name', 'title', 'titleCN', 'value', 'sort', 'image', 'shortName'] }).slice(1);
|
|
|
|
const items = data.map((row: any) => {
|
|
const item = new DictItem();
|
|
item.name = this.formatName(row.name);
|
|
item.title = row.title;
|
|
item.titleCN = row.titleCN; // 保存中文名称
|
|
item.value = row.value;
|
|
item.image = row.image;
|
|
item.shortName = row.shortName;
|
|
item.sort = row.sort || 0;
|
|
item.dict = dict;
|
|
return item;
|
|
});
|
|
|
|
await this.dictItemModel.save(items);
|
|
return { success: true, count: items.length };
|
|
}
|
|
getDict(where: { name?: string; id?: number; }, relations: string[]) {
|
|
if (!where.name && !where.id) {
|
|
throw new Error('必须提供 name 或 id');
|
|
}
|
|
return this.dictModel.findOne({ where, relations });
|
|
}
|
|
// 获取字典列表,支持按标题搜索
|
|
async getDicts(options: { title?: string; name?: string; }) {
|
|
const where = {
|
|
title: options.title ? Like(`%${options.title}%`) : undefined,
|
|
name: options.name ? Like(`%${options.name}%`) : undefined,
|
|
}
|
|
return this.dictModel.find({ where });
|
|
}
|
|
|
|
// 创建新字典
|
|
async createDict(createDictDTO: CreateDictDTO) {
|
|
const dict = new Dict();
|
|
dict.name = this.formatName(createDictDTO.name);
|
|
dict.title = createDictDTO.title;
|
|
return this.dictModel.save(dict);
|
|
}
|
|
|
|
// 更新字典
|
|
async updateDict(id: number, updateDictDTO: UpdateDictDTO) {
|
|
if (updateDictDTO.name) {
|
|
updateDictDTO.name = this.formatName(updateDictDTO.name);
|
|
}
|
|
await this.dictModel.update(id, updateDictDTO);
|
|
return this.dictModel.findOneBy({ id });
|
|
}
|
|
|
|
// 删除字典及其所有字典项
|
|
async deleteDict(id: number) {
|
|
// 首先删除该字典下的所有字典项
|
|
await this.dictItemModel.delete({ dict: { id } });
|
|
// 然后删除字典本身
|
|
const result = await this.dictModel.delete(id);
|
|
return result.affected > 0;
|
|
}
|
|
|
|
// 获取字典项列表,支持按 dictId 过滤
|
|
async getDictItems(params: { dictId?: number; name?: string; title?: string; }) {
|
|
const { dictId, name, title } = params;
|
|
const where: any = {};
|
|
|
|
if (dictId) {
|
|
where.dict = { id: dictId };
|
|
}
|
|
if (name) {
|
|
where.name = Like(`%${name}%`);
|
|
}
|
|
if (title) {
|
|
where.title = Like(`%${title}%`);
|
|
}
|
|
|
|
// 如果提供了 dictId,则只返回该字典下的项
|
|
if (params.dictId) {
|
|
return this.dictItemModel.find({ where });
|
|
}
|
|
// 否则,返回所有字典项
|
|
return this.dictItemModel.find();
|
|
}
|
|
|
|
// 创建新字典项
|
|
async createDictItem(createDictItemDTO: CreateDictItemDTO) {
|
|
const dict = await this.dictModel.findOneBy({ id: createDictItemDTO.dictId });
|
|
if (!dict) {
|
|
throw new Error(`创建新字典项,指定的字典ID为${createDictItemDTO.dictId},但不存在`);
|
|
}
|
|
const item = new DictItem();
|
|
item.name = this.formatName(createDictItemDTO.name);
|
|
item.title = createDictItemDTO.title;
|
|
item.titleCN = createDictItemDTO.titleCN; // 保存中文名称
|
|
item.image = createDictItemDTO.image;
|
|
item.shortName = createDictItemDTO.shortName;
|
|
item.dict = dict;
|
|
return this.dictItemModel.save(item);
|
|
}
|
|
|
|
// 更新字典项
|
|
async updateDictItem(id: number, updateDictItemDTO: UpdateDictItemDTO) {
|
|
if (updateDictItemDTO.name) {
|
|
updateDictItemDTO.name = this.formatName(updateDictItemDTO.name);
|
|
}
|
|
await this.dictItemModel.update(id, updateDictItemDTO);
|
|
return this.dictItemModel.findOneBy({ id });
|
|
}
|
|
|
|
// 删除字典项
|
|
async deleteDictItem(id: number) {
|
|
const result = await this.dictItemModel.delete(id);
|
|
return result.affected > 0;
|
|
}
|
|
|
|
// 根据字典名称获取字典项列表
|
|
async getDictItemsByDictName(dictName: string) {
|
|
// 查找字典
|
|
const dict = await this.dictModel.findOne({ where: { name: dictName } });
|
|
// 如果字典不存在,则返回空数组
|
|
if (!dict) {
|
|
return [];
|
|
}
|
|
// 返回该字典下的所有字典项
|
|
return this.dictItemModel.find({ where: { dict: { id: dict.id } } });
|
|
}
|
|
}
|