feat: AIHR 智能人力资源管理系统初始提交

- 员工花名册管理(加密存储、导入导出)
- 薪酬管理(发薪批次、薪酬模版、加班费计算、工资条)
- 社保公积金(多城市配置、版本管理、基数调整)
- 解聘管理(6步流程、证据链、工作交接)
- AI 助手(合同审查、风险预测、RAG 知识库)
- Dashboard 仪表盘
- 设置与通知
This commit is contained in:
selfrelease
2026-07-24 13:53:11 +08:00
commit 0df8aa77d9
109 changed files with 38190 additions and 0 deletions
+195
View File
@@ -0,0 +1,195 @@
import OpenAI from 'openai'
import { searchKnowledge } from './rag.service'
const apiKey = process.env.DASHSCOPE_API_KEY || ''
const baseURL = 'https://dashscope.aliyuncs.com/compatible-mode/v1'
const client = new OpenAI({ apiKey, baseURL, timeout: 30 * 1000, maxRetries: 1 })
const SYSTEM_PROMPT = `你是一个专业的劳动用工合规顾问,精通中国劳动法、劳动合同法、社会保险法等相关法律法规。
你的职责:
1. 回答用户关于劳动用工的合规问题
2. 基于企业实际数据给出针对性建议
3. 引用具体法律条文作为依据
4. 用通俗易懂的语言解释法律问题
回答要求:
- 先给出直接结论,再展开解释
- 引用法律条文时标注具体法律名称和条款号
- 涉及金额时给出计算过程
- 如有关联的企业数据,在回答中提及
- 回答简洁有力,避免冗长`
export async function chat(messages: { role: 'user' | 'assistant'; content: string }[], orgContext?: string) {
const lastUserMsg = messages.filter(m => m.role === 'user').pop()
let ragContext = ''
if (lastUserMsg) {
try {
const knowledge = await searchKnowledge(lastUserMsg.content, 3)
if (knowledge.length > 0) {
ragContext = `\n\n相关法律条文(RAG检索结果):\n${knowledge.join('\n\n')}`
}
} catch { /* RAG not available, continue without */ }
}
const systemMessage = orgContext
? `${SYSTEM_PROMPT}\n\n当前企业数据概览:\n${orgContext}${ragContext}`
: `${SYSTEM_PROMPT}${ragContext}`
const response = await client.chat.completions.create({
model: 'qwen-plus',
messages: [
{ role: 'system', content: systemMessage },
...messages,
],
temperature: 0.7,
max_tokens: 2000,
})
return response.choices[0]?.message?.content || ''
}
export async function* chatStream(messages: { role: 'user' | 'assistant'; content: string }[], orgContext?: string) {
const lastUserMsg = messages.filter(m => m.role === 'user').pop()
let ragContext = ''
if (lastUserMsg) {
try {
const knowledge = await searchKnowledge(lastUserMsg.content, 3)
if (knowledge.length > 0) {
ragContext = `\n\n相关法律条文(RAG检索结果):\n${knowledge.join('\n\n')}`
}
} catch { /* RAG not available, continue without */ }
}
const systemMessage = orgContext
? `${SYSTEM_PROMPT}\n\n当前企业数据概览:\n${orgContext}${ragContext}`
: `${SYSTEM_PROMPT}${ragContext}`
const stream = await client.chat.completions.create({
model: 'qwen-plus',
messages: [
{ role: 'system', content: systemMessage },
...messages,
],
temperature: 0.7,
max_tokens: 2000,
stream: true,
})
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content
if (delta) yield delta
}
}
export async function reviewContract(contractText: string): Promise<{ text: string; structured: { riskItems: { level: string; title: string; description: string; suggestion: string }[]; score: number; summary: string } }> {
const prompt = `请审查以下劳动合同文本的合法性,逐条检查并标注风险等级(红/黄/绿),给出修改建议,最后给出合规评分(0-100分)。
合同文本:
${contractText}
请按以下格式输出:
【风险项】
🔴/🟡/🟢 [问题标题] - [说明] - [修改建议]
【合规评分】XX/100
【总体建议】
一段话总结`
const response = await client.chat.completions.create({
model: 'qwen-max',
messages: [
{ role: 'system', content: '你是劳动法合同审查专家,精通劳动合同法。' },
{ role: 'user', content: prompt },
],
temperature: 0.3,
max_tokens: 3000,
})
const text = response.choices[0]?.message?.content || ''
// 解析结构化数据
const riskItems: { level: string; title: string; description: string; suggestion: string }[] = []
const riskRegex = /(🔴|🟡|🟢)\s*\[([^\]]+)\]\s*-\s*\[([^\]]+)\]\s*-\s*\[([^\]]+)\]/g
let match
while ((match = riskRegex.exec(text)) !== null) {
riskItems.push({
level: match[1] === '🔴' ? 'RED' : match[1] === '🟡' ? 'YELLOW' : 'GREEN',
title: match[2],
description: match[3],
suggestion: match[4],
})
}
const scoreMatch = text.match(/【合规评分】\s*(\d+)\s*\/\s*100/)
const score = scoreMatch ? parseInt(scoreMatch[1]) : 0
const summaryMatch = text.match(/【总体建议】\s*([\s\S]*?)(?:$|$)/)
const summary = summaryMatch ? summaryMatch[1].trim() : ''
return { text, structured: { riskItems, score, summary } }
}
export async function matchCase(scenario: string) {
const prompt = `作为一个劳动法案例匹配专家,请分析以下劳动争议情形,匹配相似的仲裁/诉讼案例,评估败诉风险。
争议情形:
${scenario}
请按以下格式输出:
【相似案例】
案例1[案例标题]
- 情形:[简要描述]
- 结果:[判决结果]
- 赔偿金额:[金额]
- 相似度:XX%
案例2...
【败诉风险评估】
风险等级:高/中/低(XX%
原因:[分析]
【建议】
[降低风险的具体建议]`
const response = await client.chat.completions.create({
model: 'qwen-max',
messages: [
{ role: 'system', content: '你是劳动法案例分析专家,熟悉劳动仲裁和诉讼案例。' },
{ role: 'user', content: prompt },
],
temperature: 0.3,
max_tokens: 3000,
})
return response.choices[0]?.message?.content || ''
}
export async function predictRisks(orgContext: string) {
const prompt = `基于以下企业用工数据,预测未来30天可能出现的合规风险,并给出优先级建议。
企业数据:
${orgContext}
请按以下格式输出:
【未来30天预计风险】
- [员工姓名/风险描述] → [建议措施]
【优先级建议】
[先处理什么,再处理什么]`
const response = await client.chat.completions.create({
model: 'qwen-plus',
messages: [
{ role: 'system', content: '你是劳动用工风险预测专家,能基于企业数据分析未来风险趋势。' },
{ role: 'user', content: prompt },
],
temperature: 0.5,
max_tokens: 1500,
})
return response.choices[0]?.message?.content || ''
}