376 lines
13 KiB
JavaScript
376 lines
13 KiB
JavaScript
const mysql = require('mysql2/promise');
|
||
|
||
// 資料庫配置
|
||
const dbConfig = {
|
||
host: process.env.DB_HOST || 'localhost',
|
||
user: process.env.DB_USER || 'root',
|
||
password: process.env.DB_PASSWORD || '',
|
||
database: process.env.DB_NAME || 'ai_scoring_app',
|
||
timezone: '+08:00',
|
||
};
|
||
|
||
// AI JSON 結果 (從終端輸出中提取)
|
||
const aiEvaluationResult = {
|
||
"projectTitle": "ITBU_人咧 PeoplePing 智能出勤系統",
|
||
"overallScore": 78.5,
|
||
"totalPossible": 100,
|
||
"grade": "A-",
|
||
"performanceStatus": "表現良好",
|
||
"recommendedStars": 4,
|
||
"analysisDate": "2024-10-27",
|
||
"criteria": [
|
||
{
|
||
"name": "應用實務性",
|
||
"score": 8,
|
||
"maxScore": 10,
|
||
"weight": 30,
|
||
"weightedScore": 24,
|
||
"feedback": "系統設計貼近實際需求,解決了主管和員工的痛點,具備可行性。",
|
||
"strengths": [
|
||
"明確指出解決了主管無法即時掌握團隊出勤狀況和員工查詢流程繁瑣的問題",
|
||
"提供了 Dify Chat Flow 和 Web Dashboard 兩個使用者介面",
|
||
"簡潔明瞭地說明了系統架構和流程"
|
||
],
|
||
"improvements": [
|
||
"可以加入更多實際案例或數據,例如導入前的數據和導入後的對比數據",
|
||
"更詳細地說明系統的安全性及數據隱私保護措施"
|
||
]
|
||
},
|
||
{
|
||
"name": "創新性",
|
||
"score": 6,
|
||
"maxScore": 10,
|
||
"weight": 15,
|
||
"weightedScore": 9,
|
||
"feedback": "利用 Dify Chat Flow 整合自然語言處理,提升使用者體驗,但整體創新性不算高。",
|
||
"strengths": [
|
||
"結合 Dify Chat Flow 和 Web Dashboard,提供了多樣化的使用方式",
|
||
"利用自然語言處理,讓使用者能以更自然的方式進行出勤登記"
|
||
],
|
||
"improvements": [
|
||
"可以探索更多創新應用,例如結合生物識別技術、位置服務等",
|
||
"進一步提升自然語言理解能力,處理更多複雜的出勤場景"
|
||
]
|
||
},
|
||
{
|
||
"name": "成效與效益",
|
||
"score": 9,
|
||
"maxScore": 10,
|
||
"weight": 25,
|
||
"weightedScore": 22.5,
|
||
"feedback": "量化了系統帶來的效率提升,數據明確,具有說服力。",
|
||
"strengths": [
|
||
"使用數據明確地呈現了系統帶來的效率提升,例如出勤登錄時間縮短 83%,月報彙整時間縮減 99%",
|
||
"系統錯誤率控制在 1% 以下,展現了系統的穩定性"
|
||
],
|
||
"improvements": [
|
||
"可以更詳細地說明數據的計算方法和資料來源"
|
||
]
|
||
},
|
||
{
|
||
"name": "擴散與可複用性",
|
||
"score": 7,
|
||
"maxScore": 10,
|
||
"weight": 20,
|
||
"weightedScore": 14,
|
||
"feedback": "系統架構清晰,模組化設計良好,具備一定程度的可複用性。",
|
||
"strengths": [
|
||
"系統架構清晰,各模組功能明確",
|
||
"後續優化與應用擴展規劃合理,展現了系統的擴展性"
|
||
],
|
||
"improvements": [
|
||
"可以更詳細地說明系統的模組化設計,以及如何方便地複製到其他部門"
|
||
]
|
||
},
|
||
{
|
||
"name": "簡報與表達",
|
||
"score": 8,
|
||
"maxScore": 10,
|
||
"weight": 10,
|
||
"weightedScore": 8,
|
||
"feedback": "簡報內容結構清晰,表達流暢,但部分幻燈片內容略顯簡潔。",
|
||
"strengths": [
|
||
"簡報目錄清晰,結構合理",
|
||
"圖表使用恰當,數據呈現清晰"
|
||
],
|
||
"improvements": [
|
||
"某些幻燈片可以添加更多圖表或說明,使內容更豐富完整",
|
||
"幻燈片 5 的「人咧~聊天流程展示」需要更具體的內容"
|
||
]
|
||
}
|
||
],
|
||
"overview": {
|
||
"excellentItems": 1,
|
||
"improvementItems": 0,
|
||
"overallPerformance": 78.5
|
||
},
|
||
"detailedAnalysis": {
|
||
"summary": "整體而言,此專案具備良好的應用實務性、成效與效益,以及擴散與可複用性。創新性方面尚有提升空間,簡報表達也需進一步完善。",
|
||
"keyFindings": [
|
||
"系統有效解決了實際問題,並量化了效益提升",
|
||
"系統架構清晰,具備一定程度的可複用性",
|
||
"創新性方面仍有提升空間,可以探索更多創新應用"
|
||
]
|
||
},
|
||
"improvementSuggestions": {
|
||
"overallSuggestions": "整體而言,專案表現良好,建議著重提升創新性,並補充更多數據和案例,以增强說服力。",
|
||
"maintainStrengths": [
|
||
{
|
||
"title": "數據驅動的效益呈現",
|
||
"description": "有效地利用數據量化了系統帶來的效率提升,這部分是專案的優勢,應該持續保持。"
|
||
}
|
||
],
|
||
"keyImprovements": [
|
||
{
|
||
"title": "提升創新性",
|
||
"description": "探索更多創新應用,例如結合生物識別技術、位置服務等,提升系統的競爭力。",
|
||
"suggestions": [
|
||
"研究市場上最新的技術,尋求更多創新點",
|
||
"考慮與其他系統整合,擴展系統功能"
|
||
]
|
||
},
|
||
{
|
||
"title": "完善數據說明和案例",
|
||
"description": "提供更詳細的數據計算方法和資料來源,並添加更多實際案例,以增强簡報的說服力。",
|
||
"suggestions": [
|
||
"提供導入前後的數據對比",
|
||
"加入更多使用者反饋和成功案例"
|
||
]
|
||
}
|
||
],
|
||
"actionPlan": [
|
||
{
|
||
"phase": "短期目標(1-2週)",
|
||
"description": "完善數據說明和案例,補充更多細節。"
|
||
},
|
||
{
|
||
"phase": "中期目標(1個月)",
|
||
"description": "研究新的技術和應用場景,探討系統的創新升級。"
|
||
},
|
||
{
|
||
"phase": "長期目標(3個月)",
|
||
"description": "完成系統的創新升級,並將其應用到更多部門。"
|
||
}
|
||
]
|
||
}
|
||
};
|
||
|
||
// 評分項目名稱對應到 criteria_items 表的 ID
|
||
// 這些 ID 需要根據實際資料庫中的 criteria_items 來調整
|
||
const criteriaNameToId = {
|
||
"應用實務性": 52,
|
||
"創新性": 53,
|
||
"成效與效益": 54,
|
||
"擴散與可複用性": 55,
|
||
"簡報與表達": 56
|
||
};
|
||
|
||
async function parseAndUploadEvaluation() {
|
||
let connection;
|
||
|
||
try {
|
||
console.log('🔗 連接到資料庫...');
|
||
connection = await mysql.createConnection(dbConfig);
|
||
console.log('✅ 資料庫連接成功');
|
||
|
||
// 假設專案 ID 為 1,實際使用時需要根據實際情況調整
|
||
const projectId = 1;
|
||
|
||
// 1. 創建 evaluations 記錄
|
||
console.log('📝 創建 evaluations 記錄...');
|
||
const evaluationData = {
|
||
project_id: projectId,
|
||
overall_score: aiEvaluationResult.overallScore,
|
||
max_possible_score: aiEvaluationResult.totalPossible,
|
||
grade: aiEvaluationResult.grade,
|
||
analysis_duration: null, // 可以從實際分析時間計算
|
||
ai_model_version: 'gemini-1.5-pro',
|
||
status: 'completed',
|
||
error_message: null
|
||
};
|
||
|
||
const evaluationSql = `
|
||
INSERT INTO evaluations (project_id, overall_score, max_possible_score, grade, analysis_duration, ai_model_version, status, error_message)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||
`;
|
||
|
||
const [evaluationResult] = await connection.execute(evaluationSql, [
|
||
evaluationData.project_id,
|
||
evaluationData.overall_score,
|
||
evaluationData.max_possible_score,
|
||
evaluationData.grade,
|
||
evaluationData.analysis_duration,
|
||
evaluationData.ai_model_version,
|
||
evaluationData.status,
|
||
evaluationData.error_message
|
||
]);
|
||
|
||
const evaluationId = evaluationResult.insertId;
|
||
console.log(`✅ 創建 evaluations 記錄成功,ID: ${evaluationId}`);
|
||
|
||
// 2. 創建 evaluation_scores 記錄
|
||
console.log('📊 創建 evaluation_scores 記錄...');
|
||
const evaluationScoresData = aiEvaluationResult.criteria.map(criteria => ({
|
||
evaluation_id: evaluationId,
|
||
criteria_item_id: criteriaNameToId[criteria.name],
|
||
score: criteria.score,
|
||
max_score: criteria.maxScore,
|
||
weight: criteria.weight,
|
||
weighted_score: criteria.weightedScore,
|
||
percentage: (criteria.score / criteria.maxScore) * 100
|
||
}));
|
||
|
||
for (const scoreData of evaluationScoresData) {
|
||
const scoreSql = `
|
||
INSERT INTO evaluation_scores (evaluation_id, criteria_item_id, score, max_score, weight, weighted_score, percentage)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||
`;
|
||
|
||
await connection.execute(scoreSql, [
|
||
scoreData.evaluation_id,
|
||
scoreData.criteria_item_id,
|
||
scoreData.score,
|
||
scoreData.max_score,
|
||
scoreData.weight,
|
||
scoreData.weighted_score,
|
||
scoreData.percentage
|
||
]);
|
||
}
|
||
console.log(`✅ 創建 ${evaluationScoresData.length} 筆 evaluation_scores 記錄成功`);
|
||
|
||
// 3. 創建 evaluation_feedback 記錄
|
||
console.log('💬 創建 evaluation_feedback 記錄...');
|
||
const feedbackData = [];
|
||
|
||
// 3.1 整體反饋
|
||
feedbackData.push({
|
||
evaluation_id: evaluationId,
|
||
criteria_item_id: null,
|
||
feedback_type: 'overall',
|
||
content: aiEvaluationResult.detailedAnalysis.summary,
|
||
sort_order: 1
|
||
});
|
||
|
||
// 3.2 各項標準的反饋
|
||
aiEvaluationResult.criteria.forEach((criteria, index) => {
|
||
// 標準反饋
|
||
feedbackData.push({
|
||
evaluation_id: evaluationId,
|
||
criteria_item_id: criteriaNameToId[criteria.name],
|
||
feedback_type: 'criteria',
|
||
content: criteria.feedback,
|
||
sort_order: index + 2
|
||
});
|
||
|
||
// 優點反饋
|
||
criteria.strengths.forEach((strength, strengthIndex) => {
|
||
feedbackData.push({
|
||
evaluation_id: evaluationId,
|
||
criteria_item_id: criteriaNameToId[criteria.name],
|
||
feedback_type: 'strength',
|
||
content: strength,
|
||
sort_order: (index + 2) * 100 + strengthIndex + 1
|
||
});
|
||
});
|
||
|
||
// 改進建議反饋
|
||
criteria.improvements.forEach((improvement, improvementIndex) => {
|
||
feedbackData.push({
|
||
evaluation_id: evaluationId,
|
||
criteria_item_id: criteriaNameToId[criteria.name],
|
||
feedback_type: 'improvement',
|
||
content: improvement,
|
||
sort_order: (index + 2) * 100 + improvementIndex + 50
|
||
});
|
||
});
|
||
});
|
||
|
||
// 3.3 改進建議的整體建議
|
||
feedbackData.push({
|
||
evaluation_id: evaluationId,
|
||
criteria_item_id: null,
|
||
feedback_type: 'improvement',
|
||
content: aiEvaluationResult.improvementSuggestions.overallSuggestions,
|
||
sort_order: 1000
|
||
});
|
||
|
||
// 3.4 保持優勢
|
||
aiEvaluationResult.improvementSuggestions.maintainStrengths.forEach((strength, index) => {
|
||
feedbackData.push({
|
||
evaluation_id: evaluationId,
|
||
criteria_item_id: null,
|
||
feedback_type: 'strength',
|
||
content: `${strength.title}: ${strength.description}`,
|
||
sort_order: 1001 + index
|
||
});
|
||
});
|
||
|
||
// 3.5 關鍵改進建議
|
||
aiEvaluationResult.improvementSuggestions.keyImprovements.forEach((improvement, index) => {
|
||
feedbackData.push({
|
||
evaluation_id: evaluationId,
|
||
criteria_item_id: null,
|
||
feedback_type: 'improvement',
|
||
content: `${improvement.title}: ${improvement.description}`,
|
||
sort_order: 2000 + index
|
||
});
|
||
});
|
||
|
||
// 3.6 行動計劃
|
||
aiEvaluationResult.improvementSuggestions.actionPlan.forEach((plan, index) => {
|
||
feedbackData.push({
|
||
evaluation_id: evaluationId,
|
||
criteria_item_id: null,
|
||
feedback_type: 'improvement',
|
||
content: `${plan.phase}: ${plan.description}`,
|
||
sort_order: 3000 + index
|
||
});
|
||
});
|
||
|
||
// 插入所有反饋資料
|
||
for (const feedback of feedbackData) {
|
||
const feedbackSql = `
|
||
INSERT INTO evaluation_feedback (evaluation_id, criteria_item_id, feedback_type, content, sort_order)
|
||
VALUES (?, ?, ?, ?, ?)
|
||
`;
|
||
|
||
await connection.execute(feedbackSql, [
|
||
feedback.evaluation_id,
|
||
feedback.criteria_item_id,
|
||
feedback.feedback_type,
|
||
feedback.content,
|
||
feedback.sort_order
|
||
]);
|
||
}
|
||
console.log(`✅ 創建 ${feedbackData.length} 筆 evaluation_feedback 記錄成功`);
|
||
|
||
console.log('🎉 所有資料上傳完成!');
|
||
console.log(`📊 評分結果: ${aiEvaluationResult.overallScore}/${aiEvaluationResult.totalPossible} (${aiEvaluationResult.grade})`);
|
||
console.log(`📝 專案: ${aiEvaluationResult.projectTitle}`);
|
||
|
||
} catch (error) {
|
||
console.error('❌ 處理過程中發生錯誤:', error);
|
||
throw error;
|
||
} finally {
|
||
if (connection) {
|
||
await connection.end();
|
||
console.log('🔌 資料庫連接已關閉');
|
||
}
|
||
}
|
||
}
|
||
|
||
// 執行解析和上傳
|
||
if (require.main === module) {
|
||
parseAndUploadEvaluation()
|
||
.then(() => {
|
||
console.log('✅ 腳本執行完成');
|
||
process.exit(0);
|
||
})
|
||
.catch((error) => {
|
||
console.error('❌ 腳本執行失敗:', error);
|
||
process.exit(1);
|
||
});
|
||
}
|
||
|
||
module.exports = { parseAndUploadEvaluation, aiEvaluationResult, criteriaNameToId };
|