mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-05-11 18:09:50 +08:00
366 lines
11 KiB
TypeScript
366 lines
11 KiB
TypeScript
import { DataSource, Raw } from "typeorm";
|
|
import { BossActiveStatusRecord } from "./entity/BossActiveStatusRecord";
|
|
import { BossInfo } from "./entity/BossInfo";
|
|
import { CompanyInfo } from "./entity/CompanyInfo";
|
|
import { JobInfo } from "./entity/JobInfo";
|
|
import { parseCompanyScale, parseSalary } from "./utils/parser";
|
|
import { ChatStartupLog } from "./entity/ChatStartupLog";
|
|
import { BossInfoChangeLog } from "./entity/BossInfoChangeLog";
|
|
import { CompanyInfoChangeLog } from "./entity/CompanyInfoChangeLog";
|
|
import { JobInfoChangeLog } from "./entity/JobInfoChangeLog";
|
|
import { MarkAsNotSuitLog } from "./entity/MarkAsNotSuitLog";
|
|
import { ChatMessageRecord } from "./entity/ChatMessageRecord";
|
|
import { LlmModelUsageRecord } from "./entity/LlmModelUsageRecord";
|
|
|
|
function getBossInfoIfIsEqual (savedOne, currentOne) {
|
|
if (savedOne === currentOne) {
|
|
return true
|
|
}
|
|
if ((savedOne !== null && currentOne === null) ||
|
|
(savedOne === null && currentOne !== null)) {
|
|
return false;
|
|
}
|
|
if (
|
|
['__ggr_encryptBrandId', 'brandName', 'title', 'name'].some(key => savedOne[key] !== currentOne[key])
|
|
) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
function getCompanyInfoIfIsEqual (savedOne, currentOne) {
|
|
if (savedOne === currentOne) {
|
|
return true
|
|
}
|
|
if (
|
|
(savedOne !== null && currentOne === null) ||
|
|
(savedOne === null && currentOne !== null)
|
|
) {
|
|
return false;
|
|
}
|
|
if (['brandName', 'stage', 'scale', 'industry', 'introduce'].some(key => savedOne[key] !== currentOne[key])) {
|
|
return false;
|
|
}
|
|
if (
|
|
[...currentOne.labels ?? []].sort().join('-') !==
|
|
[...savedOne.labels ?? []].sort().join('-')
|
|
) {
|
|
return false
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function cleanMultiLineTextForCompare (input: string) {
|
|
return input
|
|
// 去掉连续空行
|
|
.replace(/\n\s*\n+/g, '\n')
|
|
// 去掉连续的空白字符
|
|
.replace(/\s+/g, ' ')
|
|
// 去掉每行开头、结尾的空白字符
|
|
.replace(/^\s+|\s+$/gm, '');
|
|
}
|
|
function getJobInfoIfIsEqual (savedOne, currentOne) {
|
|
if (savedOne === currentOne) {
|
|
return true
|
|
}
|
|
if (
|
|
(savedOne !== null && currentOne === null) ||
|
|
(savedOne === null && currentOne !== null)
|
|
) {
|
|
return false;
|
|
}
|
|
if ([
|
|
'encryptUserId',
|
|
'invalidStatus',
|
|
'jobName',
|
|
'positionName',
|
|
'locationName',
|
|
'experienceName',
|
|
'degreeName',
|
|
'salaryDesc',
|
|
'payTypeDesc',
|
|
'address',
|
|
'jobStatusDesc'
|
|
].some(key => savedOne[key] !== currentOne[key])) {
|
|
return false;
|
|
}
|
|
if (
|
|
cleanMultiLineTextForCompare(savedOne.postDescription?.trim() ?? '') !==
|
|
cleanMultiLineTextForCompare(currentOne.postDescription?.trim() ?? '')
|
|
) {
|
|
return false
|
|
}
|
|
if (
|
|
[...currentOne.showSkills ?? []].sort().join('-') !==
|
|
[...savedOne.showSkills ?? []].sort().join('-')
|
|
) {
|
|
return false
|
|
}
|
|
return true;
|
|
}
|
|
|
|
export async function saveJobInfoFromRecommendPage(ds: DataSource, _jobInfo) {
|
|
const { bossInfo, brandComInfo, jobInfo } = _jobInfo;
|
|
|
|
bossInfo['__ggr_encryptBrandId'] = brandComInfo.encryptBrandId
|
|
bossInfo['__ggr_encryptBossId'] = jobInfo.encryptUserId
|
|
//#region boss
|
|
// get origin
|
|
const bossInfoChangeLogRepository = ds.getRepository(BossInfoChangeLog)
|
|
let lastSavedBossInfo
|
|
try {
|
|
lastSavedBossInfo = JSON.parse((await bossInfoChangeLogRepository.findOne({
|
|
where: { encryptBossId: jobInfo.encryptUserId },
|
|
order: { updateTime: "DESC" },
|
|
})).dataAsJson);
|
|
} catch {
|
|
lastSavedBossInfo = null
|
|
}
|
|
const isBossInfoEqual = getBossInfoIfIsEqual(lastSavedBossInfo, bossInfo)
|
|
if (!isBossInfoEqual) {
|
|
const changeLog = new BossInfoChangeLog()
|
|
changeLog.dataAsJson = JSON.stringify(bossInfo)
|
|
changeLog.encryptBossId = jobInfo.encryptUserId
|
|
changeLog.updateTime = new Date()
|
|
await bossInfoChangeLogRepository.save(changeLog)
|
|
}
|
|
const boss = new BossInfo();
|
|
boss.encryptBossId = jobInfo.encryptUserId;
|
|
boss.encryptCompanyId = brandComInfo.encryptBrandId;
|
|
boss.name = bossInfo.name;
|
|
boss.title = bossInfo.title;
|
|
boss.date = new Date();
|
|
const bossInfoRepository = ds.getRepository(BossInfo);
|
|
await bossInfoRepository.save(boss);
|
|
//#endregion
|
|
|
|
//#region company
|
|
// get origin
|
|
const companyInfoChangeLogRepository = ds.getRepository(CompanyInfoChangeLog)
|
|
let lastSavedCompanyInfo
|
|
try {
|
|
lastSavedCompanyInfo = JSON.parse((await companyInfoChangeLogRepository.findOne({
|
|
where: { encryptCompanyId: brandComInfo.encryptBrandId },
|
|
order: { updateTime: "DESC" },
|
|
})).dataAsJson);
|
|
} catch {
|
|
lastSavedCompanyInfo = null
|
|
}
|
|
const isCompanyInfoEqual = getCompanyInfoIfIsEqual(lastSavedCompanyInfo, brandComInfo)
|
|
if (!isCompanyInfoEqual) {
|
|
const changeLog = new CompanyInfoChangeLog()
|
|
changeLog.dataAsJson = JSON.stringify(brandComInfo)
|
|
changeLog.encryptCompanyId = brandComInfo.encryptBrandId
|
|
changeLog.updateTime = new Date()
|
|
await companyInfoChangeLogRepository.save(changeLog)
|
|
}
|
|
|
|
const company = new CompanyInfo();
|
|
company.encryptCompanyId = brandComInfo.encryptBrandId;
|
|
company.brandName = brandComInfo.brandName;
|
|
company.name = brandComInfo.customerBrandName;
|
|
company.industryName = brandComInfo.industryName;
|
|
company.stageName = brandComInfo.stageName;
|
|
const companyScale = parseCompanyScale(brandComInfo.scaleName);
|
|
company.scaleLow = companyScale[0];
|
|
company.scaleHigh = companyScale[1];
|
|
|
|
const companyInfoRepository = ds.getRepository(CompanyInfo);
|
|
await companyInfoRepository.save(company);
|
|
//#endregion
|
|
|
|
//#region job
|
|
const jobInfoChangeLogRepository = ds.getRepository(JobInfoChangeLog);
|
|
let lastSavedJobInfo
|
|
try {
|
|
lastSavedJobInfo = JSON.parse((await jobInfoChangeLogRepository.findOne({
|
|
where: { encryptJobId: jobInfo.encryptId },
|
|
order: { updateTime: "DESC" },
|
|
})).dataAsJson);
|
|
} catch {
|
|
lastSavedJobInfo = null
|
|
}
|
|
const isJobInfoEqual = getJobInfoIfIsEqual(lastSavedJobInfo, jobInfo)
|
|
if (!isJobInfoEqual) {
|
|
const changeLog = new JobInfoChangeLog()
|
|
changeLog.dataAsJson = JSON.stringify(jobInfo)
|
|
changeLog.encryptJobId = jobInfo.encryptId
|
|
changeLog.updateTime = new Date()
|
|
await jobInfoChangeLogRepository.save(changeLog)
|
|
}
|
|
|
|
const job = new JobInfo();
|
|
const jobSalary = parseSalary(jobInfo.salaryDesc);
|
|
const jobUpdatePayload: JobInfo = {
|
|
address: jobInfo.address,
|
|
degreeName: jobInfo.degreeName,
|
|
description: jobInfo.postDescription,
|
|
encryptBossId: jobInfo.encryptUserId,
|
|
encryptCompanyId: brandComInfo.encryptBrandId,
|
|
encryptJobId: jobInfo.encryptId,
|
|
jobName: jobInfo.jobName,
|
|
positionName: jobInfo.positionName,
|
|
experienceName: jobInfo.experienceName,
|
|
salaryHigh: jobSalary.high,
|
|
salaryLow: jobSalary.low,
|
|
salaryMonth: jobSalary.month,
|
|
};
|
|
|
|
Object.assign(job, jobUpdatePayload);
|
|
|
|
const jobInfoRepository = ds.getRepository(JobInfo);
|
|
await jobInfoRepository.save(job);
|
|
//#endregion
|
|
|
|
//#region save boss active status
|
|
// look up if the lastActiveStatus of the newest one is equal to the current one.
|
|
// if equal, just update the updateDate
|
|
// else insert a new record
|
|
|
|
const bossActiveStatusRecord = new BossActiveStatusRecord();
|
|
bossActiveStatusRecord.encryptBossId = boss.encryptBossId;
|
|
bossActiveStatusRecord.updateTime = new Date();
|
|
bossActiveStatusRecord.lastActiveStatus = bossInfo.activeTimeDesc;
|
|
|
|
const bossActiveStatusRecordRepository = ds.getRepository(
|
|
BossActiveStatusRecord
|
|
);
|
|
const existNewestRecordByBossId =
|
|
await bossActiveStatusRecordRepository.findOne({
|
|
where: { encryptBossId: boss.encryptBossId },
|
|
order: { updateTime: "DESC" },
|
|
});
|
|
if (
|
|
existNewestRecordByBossId &&
|
|
existNewestRecordByBossId.lastActiveStatus === bossInfo.activeTimeDesc
|
|
) {
|
|
bossActiveStatusRecord.id = existNewestRecordByBossId.id;
|
|
}
|
|
await bossActiveStatusRecordRepository.save(bossActiveStatusRecord);
|
|
//#endregion
|
|
return;
|
|
}
|
|
|
|
export async function saveChatStartupRecord(
|
|
ds: DataSource,
|
|
_jobInfo,
|
|
{ encryptUserId },
|
|
{ autoStartupChatRecordId = undefined, chatStartupFrom = undefined } = {}
|
|
) {
|
|
const { jobInfo } = _jobInfo;
|
|
|
|
//#region chat-startup-log
|
|
const chatStartupLog = new ChatStartupLog()
|
|
const chatStartupLogPayload: Partial<ChatStartupLog> = {
|
|
date: new Date(),
|
|
encryptCurrentUserId: encryptUserId,
|
|
encryptJobId: jobInfo.encryptId,
|
|
autoStartupChatRecordId,
|
|
chatStartupFrom
|
|
}
|
|
Object.assign(chatStartupLog, chatStartupLogPayload)
|
|
|
|
const chatStartupLogRepository = ds.getRepository(ChatStartupLog);
|
|
await chatStartupLogRepository.save(chatStartupLog);
|
|
//#endregion
|
|
return
|
|
}
|
|
|
|
export async function saveMarkAsNotSuitRecord(
|
|
ds: DataSource,
|
|
_jobInfo,
|
|
{ encryptUserId },
|
|
{ autoStartupChatRecordId = undefined, markFrom = undefined, extInfo = undefined, markReason = undefined, markOp = undefined } = {}
|
|
) {
|
|
const { jobInfo } = _jobInfo;
|
|
|
|
//#region mark-as-not-suit-log
|
|
const markAsNotSuitLog = new MarkAsNotSuitLog()
|
|
const markAsNotSuitLogPayload: Partial<MarkAsNotSuitLog> = {
|
|
date: new Date(),
|
|
encryptCurrentUserId: encryptUserId,
|
|
encryptJobId: jobInfo.encryptId,
|
|
autoStartupChatRecordId,
|
|
markFrom,
|
|
markReason,
|
|
extInfo: extInfo ? JSON.stringify(extInfo) : undefined,
|
|
markOp
|
|
}
|
|
Object.assign(markAsNotSuitLog, markAsNotSuitLogPayload)
|
|
|
|
const markAsNotSuitLogRepository = ds.getRepository(MarkAsNotSuitLog);
|
|
await markAsNotSuitLogRepository.save(markAsNotSuitLog);
|
|
//#endregion
|
|
return
|
|
}
|
|
|
|
export async function saveChatMessageRecord(
|
|
ds: DataSource,
|
|
records: ChatMessageRecord[]
|
|
) {
|
|
//#region mark-as-not-suit-log
|
|
const chatMessageRecordList = records.map(it => {
|
|
const o = new ChatMessageRecord()
|
|
Object.assign(o, it)
|
|
return o
|
|
})
|
|
const chatMessageRecordRepository = ds.getRepository(ChatMessageRecord);
|
|
await chatMessageRecordRepository.save(chatMessageRecordList);
|
|
//#endregion
|
|
return
|
|
}
|
|
|
|
export async function saveGptCompletionRequestRecord(
|
|
ds: DataSource,
|
|
records: LlmModelUsageRecord[]
|
|
) {
|
|
//#region mark-as-not-suit-log
|
|
const list = records.map(it => {
|
|
const o = new LlmModelUsageRecord()
|
|
for (const k of Object.keys(it)) {
|
|
o[k] = it[k]
|
|
}
|
|
return o
|
|
})
|
|
const chatMessageRecordRepository = ds.getRepository(LlmModelUsageRecord);
|
|
await chatMessageRecordRepository.save(list);
|
|
//#endregion
|
|
return
|
|
}
|
|
|
|
export async function getNotSuitMarkRecordsInLastSomeDays (ds: DataSource, days = 0) {
|
|
const repo = ds.getRepository(MarkAsNotSuitLog)
|
|
const result = await repo.findBy({
|
|
date: Raw(alias => `DATE(${alias}) >= DATE('${
|
|
new Date(
|
|
Number(new Date()) - days * 24 * 60 * 60 * 1000
|
|
).toISOString()
|
|
}')`)
|
|
})
|
|
return result
|
|
}
|
|
|
|
export async function getChatStartupRecordsInLastSomeDays (ds: DataSource, days = 0) {
|
|
const repo = ds.getRepository(ChatStartupLog)
|
|
const result = await repo.findBy({
|
|
date: Raw(alias => `DATE(${alias}) >= DATE('${
|
|
new Date(
|
|
Number(new Date()) - days * 24 * 60 * 60 * 1000
|
|
).toISOString()
|
|
}')`)
|
|
})
|
|
return result
|
|
}
|
|
|
|
export async function getBossIdsByJobIds (ds: DataSource, jobIds: string[] = []) {
|
|
const repo = ds.getRepository(JobInfo)
|
|
const result = await repo.find({
|
|
where: jobIds.map(
|
|
id => ({
|
|
encryptJobId: id
|
|
})
|
|
)
|
|
})
|
|
return result
|
|
}
|