forked from yoone/API
96 lines
3.7 KiB
TypeScript
96 lines
3.7 KiB
TypeScript
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||
import { Repository, Like, In } from 'typeorm';
|
||
import { Site } from '../entity/site.entity';
|
||
import { WpSite } from '../interface';
|
||
import { UpdateSiteDTO } from '../dto/site.dto';
|
||
|
||
@Provide()
|
||
@Scope(ScopeEnum.Singleton)
|
||
export class SiteService {
|
||
@InjectEntityModel(Site)
|
||
siteModel: Repository<Site>;
|
||
|
||
async syncFromConfig(sites: WpSite[] = []) {
|
||
// 将配置中的 WpSite 同步到数据库 Site 表(用于一次性导入或初始化)
|
||
for (const siteConfig of sites) {
|
||
// 按站点名称查询是否已存在记录
|
||
const exist = await this.siteModel.findOne({ where: { siteName: siteConfig.siteName } });
|
||
// 将 WpSite 字段映射为 Site 实体字段
|
||
const payload: Partial<Site> = {
|
||
siteName: siteConfig.siteName,
|
||
apiUrl: (siteConfig as any).wpApiUrl,
|
||
consumerKey: (siteConfig as any).consumerKey,
|
||
consumerSecret: (siteConfig as any).consumerSecret,
|
||
type: 'woocommerce',
|
||
};
|
||
// 存在则更新,不存在则插入新记录
|
||
if (exist) await this.siteModel.update({ id: exist.id }, payload);
|
||
else await this.siteModel.insert(payload as Site);
|
||
}
|
||
}
|
||
|
||
async create(data: Partial<Site>) {
|
||
// 创建新的站点记录
|
||
await this.siteModel.insert(data as Site);
|
||
return true;
|
||
}
|
||
|
||
async update(id: string | number, data: UpdateSiteDTO) {
|
||
// 更新指定站点记录,将布尔 isDisabled 转换为数值 0/1
|
||
const payload: Partial<Site> = {
|
||
...data,
|
||
isDisabled:
|
||
data.isDisabled === undefined // 未传入则不更新该字段
|
||
? undefined
|
||
: data.isDisabled // true -> 1, false -> 0
|
||
? 1
|
||
: 0,
|
||
} as any;
|
||
await this.siteModel.update({ id: Number(id) }, payload);
|
||
return true;
|
||
}
|
||
|
||
async get(id: string | number, includeSecret = false) {
|
||
// 根据主键获取站点;includeSecret 为 true 时返回密钥字段
|
||
const site = await this.siteModel.findOne({ where: { id: Number(id) } });
|
||
if (!site) return null;
|
||
if (includeSecret) return site;
|
||
// 默认不返回密钥,进行字段脱敏
|
||
const { ...rest } = site;
|
||
return rest;
|
||
}
|
||
|
||
async list(param: { current?: number; pageSize?: number; keyword?: string; isDisabled?: boolean; ids?: string }, includeSecret = false) {
|
||
// 分页查询站点列表,支持关键字、禁用状态与 ID 列表过滤
|
||
const { current = 1, pageSize = 10, keyword, isDisabled, ids } = (param || {}) as any;
|
||
const where: any = {};
|
||
// 按名称模糊查询
|
||
if (keyword) where.siteName = Like(`%${keyword}%`);
|
||
// 按禁用状态过滤(布尔转数值)
|
||
if (typeof isDisabled === 'boolean') where.isDisabled = isDisabled ? 1 : 0;
|
||
if (ids) {
|
||
// 解析逗号分隔的 ID 字符串为数字数组,并过滤非法值
|
||
const numIds = String(ids)
|
||
.split(',')
|
||
.filter(Boolean)
|
||
.map((i) => Number(i))
|
||
.filter((v) => !Number.isNaN(v));
|
||
if (numIds.length > 0) where.id = In(numIds);
|
||
}
|
||
// 进行分页查询(skip/take)并返回总条数
|
||
const [items, total] = await this.siteModel.findAndCount({ where, skip: (current - 1) * pageSize, take: pageSize });
|
||
// 根据 includeSecret 决定是否脱敏返回密钥字段
|
||
const data = includeSecret ? items : items.map((item: any) => {
|
||
const { consumerKey, consumerSecret, ...rest } = item;
|
||
return rest;
|
||
});
|
||
return { items: data, total, current, pageSize };
|
||
}
|
||
|
||
async disable(id: string | number, disabled: boolean) {
|
||
// 设置站点禁用状态(true -> 1, false -> 0)
|
||
await this.siteModel.update({ id: Number(id) }, { isDisabled: disabled ? 1 : 0 });
|
||
return true;
|
||
}
|
||
} |