Explorar o código

fix: rewards表child_id字段允许NULL,修复模板奖励插入失败问题

User hai 5 meses
pai
achega
0251d9b449

+ 45 - 29
zxyj-backend/src/main/java/com/zxyj/config/DatabaseInitializer.java

@@ -144,23 +144,23 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_child_id (child_id)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 奖励表
-            "CREATE TABLE IF NOT EXISTS rewards (" +
-            "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
-            "family_id BIGINT NOT NULL, " +
-            "child_id BIGINT NOT NULL, " +
-            "title VARCHAR(100) NOT NULL, " +
-            "points_required INT NOT NULL, " +
-            "category VARCHAR(32), " +
-            "status ENUM('available','pending','exchanged','rejected') DEFAULT 'available', " +
-            "exchange_approved TINYINT, " +
-            "exchanged_at DATETIME, " +
-            "is_template TINYINT DEFAULT 0, " +
-            "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
-            "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
-            "INDEX idx_child_id_status (child_id, status), " +
-            "INDEX idx_is_template (is_template)" +
-            ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
+// 奖励表
+"CREATE TABLE IF NOT EXISTS rewards (" +
+"id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+"family_id BIGINT NOT NULL, " +
+"child_id BIGINT NULL COMMENT '孩子ID,模板奖励为NULL', " +
+"title VARCHAR(100) NOT NULL, " +
+"points_required INT NOT NULL, " +
+"category VARCHAR(32), " +
+"status ENUM(\'available\',\'pending\',\'exchanged\',\'rejected\') DEFAULT \'available\', " +
+"exchange_approved TINYINT, " +
+"exchanged_at DATETIME, " +
+"is_template TINYINT DEFAULT 0, " +
+"created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+"updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
+"INDEX idx_child_id_status (child_id, status), " +
+"INDEX idx_is_template (is_template)" +
+") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
             // 奖励分类表
             "CREATE TABLE IF NOT EXISTS reward_categories (" +
@@ -633,7 +633,23 @@ public class DatabaseInitializer implements CommandLineRunner {
             // 表已存在,忽略错误
         }
 
-        log.info("数据库迁移完成");
+// 迁移13: admin_task_templates表添加teacher_id字段
+try {
+jdbcTemplate.execute("ALTER TABLE admin_task_templates ADD COLUMN teacher_id BIGINT COMMENT \'指导师ID\'");
+log.info("已添加teacher_id列到admin_task_templates表");
+} catch (Exception e) {
+// 列已存在,忽略错误
+}
+
+// 迁移14: rewards表child_id字段允许NULL(模板奖励不需要child_id)
+try {
+jdbcTemplate.execute("ALTER TABLE rewards MODIFY COLUMN child_id BIGINT NULL COMMENT \'孩子ID,模板奖励为NULL\'");
+log.info("已修改rewards.child_id字段允许NULL");
+} catch (Exception e) {
+// 修改失败,忽略错误
+}
+
+log.info("数据库迁移完成");
     }
 
     private void initializeDefaultData() {
@@ -643,17 +659,17 @@ public class DatabaseInitializer implements CommandLineRunner {
             Integer count = jdbcTemplate.queryForObject(
                 "SELECT COUNT(*) FROM rewards WHERE is_template = 1", Integer.class);
             
-            if (count == null || count == 0) {
-                // 插入预设奖励模板
-                jdbcTemplate.execute("INSERT INTO rewards (family_id, child_id, title, points_required, category, is_template) VALUES " +
-                    "(0, 0, '看动画片30分钟', 30, '精神类', 1), " +
-                    "(0, 0, '玩平板游戏30分钟', 40, '特权类', 1), " +
-                    "(0, 0, '去游乐场', 100, '物质类', 1), " +
-                    "(0, 0, '买玩具', 150, '物质类', 1), " +
-                    "(0, 0, '吃冰淇淋', 20, '物质类', 1), " +
-                    "(0, 0, '选择晚餐', 25, '特权类', 1)");
-                log.info("预设奖励模板已初始化");
-            }
+if (count == null || count == 0) {
+// 插入预设奖励模板(child_id为NULL表示模板)
+jdbcTemplate.execute("INSERT INTO rewards (family_id, child_id, title, points_required, category, is_template) VALUES " +
+"(0, NULL, \'看动画片30分钟\', 30, \'精神类\', 1), " +
+"(0, NULL, \'玩平板游戏30分钟\', 40, \'特权类\', 1), " +
+"(0, NULL, \'去游乐场\', 100, \'物质类\', 1), " +
+"(0, NULL, \'买玩具\', 150, \'物质类\', 1), " +
+"(0, NULL, \'吃冰淇淋\', 20, \'物质类\', 1), " +
+"(0, NULL, \'选择晚餐\', 25, \'特权类\', 1)");
+log.info("预设奖励模板已初始化");
+}
         } catch (Exception e) {
             log.warn("初始化预设奖励失败: {}", e.getMessage());
         }

+ 22 - 22
zxyj-backend/src/main/resources/schema.sql

@@ -106,21 +106,21 @@ CREATE TABLE IF NOT EXISTS points_reset_log (
 
 -- 奖励表
 CREATE TABLE IF NOT EXISTS rewards (
-    id BIGINT AUTO_INCREMENT PRIMARY KEY,
-    family_id BIGINT NOT NULL COMMENT '家庭 ID,所有奖励必须关联家庭',
-    child_id BIGINT NOT NULL COMMENT '孩子 ID',
-    title VARCHAR(100) NOT NULL,
-    points_required INT NOT NULL,
-    category VARCHAR(32),
-    status ENUM('available', 'pending', 'exchanged', 'rejected') DEFAULT 'available',
-    exchange_approved TINYINT COMMENT '是否审批通过',
-    exchanged_at DATETIME,
-    is_template TINYINT DEFAULT 0 COMMENT '是否为预设模板',
-    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
-    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    INDEX idx_family_id (family_id),
-    INDEX idx_child_id_status (child_id, status),
-    INDEX idx_is_template (is_template)
+id BIGINT AUTO_INCREMENT PRIMARY KEY,
+family_id BIGINT NOT NULL COMMENT '家庭 ID,所有奖励必须关联家庭',
+child_id BIGINT NULL COMMENT '孩子 ID,模板奖励为NULL',
+title VARCHAR(100) NOT NULL,
+points_required INT NOT NULL,
+category VARCHAR(32),
+status ENUM('available', 'pending', 'exchanged', 'rejected') DEFAULT 'available',
+exchange_approved TINYINT COMMENT '是否审批通过',
+exchanged_at DATETIME,
+is_template TINYINT DEFAULT 0 COMMENT '是否为预设模板',
+created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+INDEX idx_family_id (family_id),
+INDEX idx_child_id_status (child_id, status),
+INDEX idx_is_template (is_template)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='奖励表,所有奖励必须关联到具体家庭';
 
 -- 奖励分类表
@@ -134,14 +134,14 @@ CREATE TABLE IF NOT EXISTS reward_categories (
     INDEX idx_family_id (family_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
--- 预设奖励模板数据
+-- 预设奖励模板数据(child_id为NULL表示模板)
 INSERT IGNORE INTO rewards (family_id, child_id, title, points_required, category, is_template) VALUES
-(0, 0, '看动画片30分钟', 30, '精神奖励', 1),
-(0, 0, '玩平板游戏30分钟', 40, '特权奖励', 1),
-(0, 0, '去游乐场', 100, '物质奖励', 1),
-(0, 0, '买玩具', 150, '物质奖励', 1),
-(0, 0, '吃冰淇淋', 20, '物质奖励', 1),
-(0, 0, '选择晚餐', 25, '特权奖励', 1);
+(0, NULL, '看动画片30分钟', 30, '精神奖励', 1),
+(0, NULL, '玩平板游戏30分钟', 40, '特权奖励', 1),
+(0, NULL, '去游乐场', 100, '物质奖励', 1),
+(0, NULL, '买玩具', 150, '物质奖励', 1),
+(0, NULL, '吃冰淇淋', 20, '物质奖励', 1),
+(0, NULL, '选择晚餐', 25, '特权奖励', 1);
 
 -- 默认奖励分类
 INSERT IGNORE INTO reward_categories (family_id, name, icon, sort_order) VALUES

+ 5 - 0
zxyj-backend/src/test/java/com/zxyj/controller/GuideFamilyTaskControllerTest.java

@@ -2,10 +2,12 @@ package com.zxyj.controller;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.zxyj.common.Result;
+import com.zxyj.controller.guide.GuideFamilyTaskController;
 import com.zxyj.entity.User;
 import com.zxyj.service.TaskService;
 import com.zxyj.mapper.ChildMapper;
 import com.zxyj.mapper.UserMapper;
+import com.zxyj.mapper.TaskMapper;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -35,6 +37,9 @@ public class GuideFamilyTaskControllerTest {
     @MockBean
     private UserMapper userMapper;
 
+    @MockBean
+    private TaskMapper taskMapper;
+
     @Autowired
     private ObjectMapper objectMapper;
 

+ 15 - 10
zxyj-frontend/pages/login/login.vue

@@ -204,13 +204,11 @@ export default {
           userId: res.data.userId
         })
 
-        uni.showToast({ title: '登录成功', icon: 'success' })
+uni.showToast({ title: '登录成功', icon: 'success' })
 
-        // 直接跳转到首页(根据后端返回的角色自动适配)
+        // 根据角色跳转到对应首页
         setTimeout(() => {
-          uni.reLaunch({
-            url: '/pages/index/index'
-          })
+          this.navigateToHome(res.data.role)
         }, 1000)
       } catch (e) {
         uni.showToast({ title: e.message || '登录失败', icon: 'none' })
@@ -267,18 +265,25 @@ export default {
 
           uni.showToast({ title: '登录成功', icon: 'success' })
 
-          // 直接跳转到首页
+          // 根据角色跳转到对应首页
           setTimeout(() => {
-            uni.reLaunch({
-              url: '/pages/index/index'
-            })
+            this.navigateToHome(res.data.role)
           }, 1000)
         } catch (e) {
           uni.showToast({ title: e.message || '登录失败', icon: 'none' })
         } finally {
           this.loading = false
         }
-}
+    }
+    },
+    navigateToHome(role) {
+      if (role === 'parent') {
+        uni.reLaunch({ url: '/pages/index/parent-index' })
+      } else if (role === 'child') {
+        uni.reLaunch({ url: '/pages/index/child-index' })
+      } else {
+        uni.reLaunch({ url: '/pages/teacher/index' })
+      }
     }
   }
 }