Browse Source

✨ feat: 新增文件处理相关接口

Pchen. 2 months ago
parent
commit
22277de9a0
5 changed files with 299 additions and 1 deletions
  1. 44 0
      apis/AI/GetFileSummary.js
  2. 1 1
      apis/AI/SummaryCommit.js
  3. 67 0
      apis/AI/SummaryFile.js
  4. 78 0
      apis/Repos/GetFileDetail.js
  5. 109 0
      apis/Repos/GetFiles.js

+ 44 - 0
apis/AI/GetFileSummary.js

@@ -0,0 +1,44 @@
+const API = require("../../lib/API")
+const db = require("../../plugin/DataBase/db")
+const AccessControl = require("../../lib/AccessControl")
+const { BaseStdResponse } = require("../../BaseStdResponse")
+
+class GetFileSummary extends API {
+    constructor() {
+        super()
+
+        this.setPath('/AI/GetFileSummary')
+        this.setMethod('GET')
+    }
+
+    async onRequest(req, res) {
+        let {uuid, session, id, hash, filePath } = req.query
+        if ([uuid, session, id, hash, filePath].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        let sql = 'SELECT create_time, start_time, end_time, result, repo_hash FROM file_summary_tasks WHERE create_user = ? AND repo_id = ? AND repo_hash = ?'
+        let rows = await db.query(sql, [uuid, id, hash])
+
+        if (!rows || rows.length === 0)
+            return res.json({
+                ...BaseStdResponse.OK,
+                data: []
+            })
+
+        res.json({
+            ...BaseStdResponse.OK,
+            data: rows
+        })
+
+    }
+}
+
+module.exports.GetFileSummary = GetFileSummary

+ 1 - 1
apis/AI/SummaryCommit.js

@@ -59,7 +59,7 @@ class SummaryCommit extends API {
             let endpoint = core_url + '/ai/summaryCommit'
             await axios.post(endpoint, { uuid, repo_url: rows[0].url, task_id: String(r.insertId) })
         } catch (error) {
-            this.logger.error('获取仓库历史失败!' + error.stack)
+            this.logger.error('添加AI分析任务失败!' + error.stack)
         }
     }
 }

+ 67 - 0
apis/AI/SummaryFile.js

@@ -0,0 +1,67 @@
+const API = require("../../lib/API")
+const AccessControl = require("../../lib/AccessControl")
+const { BaseStdResponse } = require("../../BaseStdResponse")
+const db = require("../../plugin/DataBase/db")
+const axios = require('axios')
+const { core_url } = require('../../config.json')
+
+class SummaryFile extends API {
+    constructor() {
+        super()
+
+        this.setMethod("GET")
+        this.setPath("/AI/SummaryFile")
+    }
+
+    async onRequest(req, res) {
+        let { uuid, session, id, hash, filePath } = req.query
+
+        if ([uuid, session, id, hash, filePath].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        let sql = 'SELECT state, path, url FROM repos WHERE create_user = ? AND id = ?'
+        let rows = await db.query(sql, [uuid, id])
+        if (!rows || rows.length === 0)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '未找到仓库'
+            })
+
+        if (rows[0].state !== 1 || !rows[0].path)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '仓库未成功克隆!'
+            })
+
+        try {
+            const time = new Date().getTime()
+            sql = 'INSERT INTO file_summary_tasks (repo_id, create_time, create_user, repo_hash, filepath) VALUES (?, ?, ?, ?, ?)'
+            let r = await db.query(sql, [id, time, uuid, hash, filePath])
+
+            if (!r || r.affectedRows !== 1)
+                return res.json({
+                    ...BaseStdResponse.ERR,
+                    msg: '扫描任务添加失败!'
+                })
+
+            res.json({
+                ...BaseStdResponse.OK
+            })
+
+            let endpoint = core_url + '/ai/summaryFile'
+            await axios.post(endpoint, { uuid, repo_url: rows[0].url, task_id: String(r.insertId), file_path: filePath })
+        } catch (error) {
+            this.logger.error('添加AI分析任务失败!' + error.stack)
+        }
+    }
+}
+
+module.exports.SummaryFile = SummaryFile

+ 78 - 0
apis/Repos/GetFileDetail.js

@@ -0,0 +1,78 @@
+const API = require("../../lib/API")
+const AccessControl = require("../../lib/AccessControl")
+const { BaseStdResponse } = require("../../BaseStdResponse")
+const db = require("../../plugin/DataBase/db")
+
+const simpleGit = require('simple-git')
+
+class GetFileDetail extends API {
+    constructor() {
+        super()
+
+        this.setMethod("GET")
+        this.setPath("/Repos/GetFileDetail")
+    }
+
+    async onRequest(req, res) {
+        let { uuid, session, id, filePath } = req.query
+
+        if ([uuid, session, id].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        let sql = 'SELECT name, logo, create_time, update_time, state, path, url FROM repos WHERE create_user = ? AND id = ?'
+        let r = await db.query(sql, [uuid, id])
+        if (!r || r.length === 0)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '未找到仓库'
+            })
+
+        if (r[0].state !== 1 || !r[0].path)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '仓库未成功克隆!'
+            })
+
+        try {
+            const git = simpleGit()
+            await git.cwd(r[0].path)
+            const log = await git.log({
+                file: filePath,
+                n: 1,
+                format: {
+                    hash: '%H',
+                    abbrevHash: '%h',
+                    title: '%s',
+                    message: '%B',
+                    author_name: '%aN',
+                    email: '%aE',
+                    date: '%ad',
+                }
+            })
+
+            const content = await git.show([`HEAD:${filePath}`])
+            res.json({
+                ...BaseStdResponse.OK,
+                commit: log,
+                content: btoa(encodeURI(content))
+            })
+        } catch (error) {
+            this.logger.error('获取文件详情失败!' + error.stack)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '获取文件详情失败!'
+            })
+        }
+
+    }
+}
+
+module.exports.GetFileDetail = GetFileDetail

+ 109 - 0
apis/Repos/GetFiles.js

@@ -0,0 +1,109 @@
+const API = require("../../lib/API")
+const AccessControl = require("../../lib/AccessControl")
+const { BaseStdResponse } = require("../../BaseStdResponse")
+const db = require("../../plugin/DataBase/db")
+const simpleGit = require('simple-git')
+
+class GetFiles extends API {
+    constructor() {
+        super()
+
+        this.setMethod("GET")
+        this.setPath("/Repos/GetFiles")
+    }
+
+    buildTreeStructure(paths) {
+        const root = []
+
+        paths.forEach(filePath => {
+            const parts = filePath.split('/')
+            let currentLevel = root
+
+            parts.forEach((part, index) => {
+                const existingNode = currentLevel.find(node => node.title === part)
+
+                // 如果存在节点,则继续深入
+                if (existingNode) {
+                    currentLevel = existingNode.children
+                } else {
+                    // 判断是否为文件
+                    const isFile = index === parts.length - 1
+
+                    // 新增节点
+                    const newNode = {
+                        title: part,
+                        key: filePath,
+                        type: isFile ? 'file' : 'folder',
+                        children: []
+                    }
+
+                    // 判断是否为叶子节点
+                    if (index === parts.length - 1) {
+                        newNode.icon = () => h(IconDriveFile)
+                        newNode.children = undefined
+                    }
+
+                    currentLevel.push(newNode)
+                    currentLevel = newNode.children
+                }
+            })
+        })
+
+        return root
+    }
+
+    async onRequest(req, res) {
+        let { uuid, session, id } = req.query
+
+        if ([uuid, session, id].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        let sql = 'SELECT name, logo, create_time, update_time, state, path, url FROM repos WHERE create_user = ? AND id = ?'
+        let r = await db.query(sql, [uuid, id])
+        if (!r || r.length === 0)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '未找到仓库'
+            })
+
+        if (r[0].state !== 1 || !r[0].path)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '仓库未成功克隆!'
+            })
+
+        try {
+            const git = simpleGit()
+            await git.cwd(r[0].path)
+            const treeResult = await git.raw(['ls-tree', '-r', '--name-only', 'HEAD'])
+
+            const filePaths = treeResult.split('\n').filter(path => path) // 去掉空行
+
+            // 构建树结构
+            const treeStructure = this.buildTreeStructure(filePaths)
+
+            res.json({
+                ...BaseStdResponse.OK,
+                data: treeStructure
+            })
+
+        } catch (error) {
+            this.logger.error('获取文件列表失败!' + error.stack)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '获取文件列表失败!'
+            })
+        }
+
+    }
+}
+
+module.exports.GetFiles = GetFiles