```
feat(background): 添加删除应用功能 - 添加DELETE /apps/:id API端点用于删除指定应用 - 实现deleteApp函数,支持文件和数据的完整删除 - 在getApps函数中增加文件存在性验证,自动清理无效应用记录 - 优化appsMutex使用,确保并发安全的数据操作 - 添加文件路径验证和错误处理机制 feat(frontend): 实现前端删除应用交互功能 - 将deleteApp函数改为异步处理,支持API调用 - 添加确认对话框提升用户体验 - 实现DELETE请求发送和响应处理 - 添加错误处理和用户反馈提示 - 删除成功后自动刷新应用列表 ```
This commit is contained in:
@@ -129,6 +129,7 @@ func main() {
|
|||||||
{
|
{
|
||||||
api.GET("/apps", getApps)
|
api.GET("/apps", getApps)
|
||||||
api.POST("/apps", uploadApp)
|
api.POST("/apps", uploadApp)
|
||||||
|
api.DELETE("/apps/:id", deleteApp) // 添加删除应用的API端点
|
||||||
api.GET("/apps/:id", downloadApp)
|
api.GET("/apps/:id", downloadApp)
|
||||||
api.GET("/apps/:id/", downloadApp) // 处理以/结尾的URL
|
api.GET("/apps/:id/", downloadApp) // 处理以/结尾的URL
|
||||||
api.GET("/docs", getDocs) // 新增获取文档的API端点
|
api.GET("/docs", getDocs) // 新增获取文档的API端点
|
||||||
@@ -143,8 +144,33 @@ func main() {
|
|||||||
|
|
||||||
// 获取App列表
|
// 获取App列表
|
||||||
func getApps(c *gin.Context) {
|
func getApps(c *gin.Context) {
|
||||||
appsMutex.RLock()
|
appsMutex.Lock()
|
||||||
defer appsMutex.RUnlock()
|
defer appsMutex.Unlock()
|
||||||
|
|
||||||
|
// 验证文件是否存在,如果不存在则从切片中删除
|
||||||
|
appsToKeep := []App{}
|
||||||
|
appsChanged := false
|
||||||
|
|
||||||
|
for _, app := range apps {
|
||||||
|
filePath := filepath.Join(filesDir, app.FilePath)
|
||||||
|
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||||
|
// 文件不存在,跳过这个app(即从逻辑上删除它)
|
||||||
|
appsChanged = true
|
||||||
|
fmt.Printf("文件不存在,从列表中移除: %s, 文件路径: %s\n", app.Name, filePath)
|
||||||
|
} else {
|
||||||
|
// 文件存在,保留这个app
|
||||||
|
appsToKeep = append(appsToKeep, app)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if appsChanged {
|
||||||
|
// 更新apps切片
|
||||||
|
apps = appsToKeep
|
||||||
|
// 保存到文件
|
||||||
|
if err := saveApps(); err != nil {
|
||||||
|
fmt.Printf("保存apps.json失败: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, apps)
|
c.JSON(http.StatusOK, apps)
|
||||||
}
|
}
|
||||||
@@ -242,6 +268,57 @@ func downloadApp(c *gin.Context) {
|
|||||||
c.FileAttachment(filePath, targetApp.FileName)
|
c.FileAttachment(filePath, targetApp.FileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除指定App
|
||||||
|
func deleteApp(c *gin.Context) {
|
||||||
|
// 获取ID
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
// 查找App
|
||||||
|
appsMutex.Lock()
|
||||||
|
var targetApp *App
|
||||||
|
targetIndex := -1
|
||||||
|
for i := range apps {
|
||||||
|
if apps[i].ID == id {
|
||||||
|
targetApp = &apps[i]
|
||||||
|
targetIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appsMutex.Unlock()
|
||||||
|
|
||||||
|
if targetApp == nil {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{"success": false, "message": "App不存在"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建文件路径
|
||||||
|
filePath := filepath.Join(filesDir, targetApp.FilePath)
|
||||||
|
|
||||||
|
// 删除文件
|
||||||
|
if err := os.Remove(filePath); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
// 文件不存在,可能已经被删除,继续执行
|
||||||
|
fmt.Printf("文件已经不存在: %s\n", filePath)
|
||||||
|
} else {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "message": "删除文件失败: " + err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从apps切片中删除该应用
|
||||||
|
appsMutex.Lock()
|
||||||
|
apps = append(apps[:targetIndex], apps[targetIndex+1:]...)
|
||||||
|
appsMutex.Unlock()
|
||||||
|
|
||||||
|
// 保存到文件
|
||||||
|
if err := saveApps(); err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "message": "保存数据失败: " + err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{"success": true, "message": "删除成功"})
|
||||||
|
}
|
||||||
|
|
||||||
// 读取文档内容
|
// 读取文档内容
|
||||||
func readDocFile(docName string) (string, error) {
|
func readDocFile(docName string) (string, error) {
|
||||||
filePath := filepath.Join(docsDir, docName+".txt")
|
filePath := filepath.Join(docsDir, docName+".txt")
|
||||||
|
|||||||
34
script.js
34
script.js
@@ -238,11 +238,39 @@ async function uploadApp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除App函数
|
// 删除App函数
|
||||||
function deleteApp(appId) {
|
async function deleteApp(appId) {
|
||||||
// 显示确认对话框,包含特殊问题验证
|
// 显示确认对话框
|
||||||
if (!confirm('如果确定删除此APP,请将矩阵 A = [[3,1,0],[1,2,1],[0,1,1]]的特征值、特征向量,并验证A是正定矩阵的解题步骤做出来,然后我也没做')) {
|
if (!confirm('确定要删除这个应用吗?此操作不可撤销!')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 发送DELETE请求删除App
|
||||||
|
const response = await fetch(`${API_BASE_URL}/apps/${appId}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP错误!状态:${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await response.json(); // 解析响应数据
|
||||||
|
|
||||||
|
// 处理删除结果
|
||||||
|
if (result.success) {
|
||||||
|
alert('删除成功!');
|
||||||
|
loadAppList(); // 重新加载App列表
|
||||||
|
} else {
|
||||||
|
alert('删除失败:' + (result.message || '未知错误'));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('删除失败:', error);
|
||||||
|
alert('删除失败:' + error.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下载App函数
|
// 下载App函数
|
||||||
|
|||||||
Reference in New Issue
Block a user