Parcourir la source

refactor: 全局UI文案套餐→任务模板重命名

- 前端UI:导航标题、按钮、表单标签、确认对话框、面包屑等
- 后端:Swagger @Tag/@Operation注解、DTO校验消息、entity字段注释、service javadoc
- 数据库schema.sql:表注释、列注释
- 测试文件:测试数据fixture名称
- 会员档位选择(membership/upgrade.vue)→'档位选择'避免与任务模板混淆
- 测评类型'bundle'标签:'套餐'→'组合'(与任务模板区分)
- 未改动:API URL路径、Java类名、数据库表/列名、CSS类名
- 验证:mvn clean compile通过 + npm run build通过
Xiaogang Liao il y a 2 mois
Parent
commit
bbee87ce75
70 fichiers modifiés avec 561 ajouts et 412 suppressions
  1. 96 12
      cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java
  2. 11 11
      cfc-backend/src/main/java/com/etotem/cfc/controller/MarketController.java
  3. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/controller/MembershipController.java
  4. 4 4
      cfc-backend/src/main/java/com/etotem/cfc/controller/PackagePaymentController.java
  5. 132 132
      cfc-backend/src/main/java/com/etotem/cfc/controller/TaskTemplatePackageController.java
  6. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminController.java
  7. 3 3
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminPackageController.java
  8. 7 7
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/PackageTemplateController.java
  9. 8 8
      cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideManagementController.java
  10. 14 14
      cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuidePackageController.java
  11. 7 7
      cfc-backend/src/main/java/com/etotem/cfc/controller/guide/PackagePurchaseController.java
  12. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/dto/AddGuidePackageDTO.java
  13. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/dto/AdminCreateGuidePackageDTO.java
  14. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/dto/AssessmentCreateOrderDTO.java
  15. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/dto/GuidePackageUpdateDTO.java
  16. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/dto/PackageCreateOrderDTO.java
  17. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/PackagePurchaseDTO.java
  18. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/entity/AssessmentProduct.java
  19. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/PackageOrder.java
  20. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/entity/TaskPlanInstance.java
  21. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/entity/TaskTemplateItem.java
  22. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/entity/TaskTemplatePackage.java
  23. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/mapper/GuidePackageMapper.java
  24. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java
  25. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/service/DataMigrationService.java
  26. 10 10
      cfc-backend/src/main/java/com/etotem/cfc/service/GuidePackageService.java
  27. 3 3
      cfc-backend/src/main/java/com/etotem/cfc/service/PackagePaymentService.java
  28. 8 8
      cfc-backend/src/main/java/com/etotem/cfc/service/PackagePurchaseService.java
  29. 3 3
      cfc-backend/src/main/java/com/etotem/cfc/service/TaskPlanService.java
  30. 9 9
      cfc-backend/src/main/java/com/etotem/cfc/service/TaskTemplatePackageService.java
  31. 93 28
      cfc-backend/src/main/resources/schema.sql
  32. 1 1
      cfc-backend/src/test/java/com/etotem/cfc/controller/GuideOrderControllerTest.java
  33. 1 1
      cfc-backend/src/test/java/com/etotem/cfc/controller/GuideRolePermissionTest.java
  34. 5 5
      cfc-backend/src/test/java/com/etotem/cfc/controller/PaymentControllerTest.java
  35. 7 7
      cfc-backend/src/test/java/com/etotem/cfc/controller/ProductControllerTest.java
  36. 2 2
      cfc-backend/src/test/java/com/etotem/cfc/controller/ProductOrderControllerTest.java
  37. 1 1
      cfc-backend/src/test/java/com/etotem/cfc/integration/GrowthRecordSyncFlowTest.java
  38. 3 3
      cfc-backend/src/test/java/com/etotem/cfc/integration/GuideModuleIntegrationTest.java
  39. 2 2
      cfc-backend/src/test/java/com/etotem/cfc/service/GuidePackageServiceTest.java
  40. 2 2
      cfc-backend/src/test/java/com/etotem/cfc/service/GuidePackageTemplateServiceTest.java
  41. 6 6
      cfc-frontend/pages.json
  42. 1 1
      cfc-frontend/pages/assessment/order.vue
  43. 12 12
      cfc-frontend/pages/assessment/purchase.vue
  44. 2 2
      cfc-frontend/pages/assessment/quota.vue
  45. 3 3
      cfc-frontend/pages/guide/packages/create.vue
  46. 1 1
      cfc-frontend/pages/guide/packages/detail.vue
  47. 4 4
      cfc-frontend/pages/guide/packages/index.vue
  48. 3 3
      cfc-frontend/pages/guide/packages/share.vue
  49. 3 3
      cfc-frontend/pages/membership/upgrade.vue
  50. 2 2
      cfc-frontend/pages/parent/market/detail.vue
  51. 3 3
      cfc-frontend/pages/parent/market/index.vue
  52. 1 1
      cfc-frontend/pages/parent/plans/index.vue
  53. 1 1
      cfc-frontend/pages/promotion/commission.vue
  54. 2 2
      cfc-frontend/pages/teacher/teacher-home.vue
  55. 10 10
      cfc-frontend/utils/api.js
  56. 1 1
      cfc-web/src/__tests__/api/guide.test.js
  57. 1 1
      cfc-web/src/__tests__/api/guidePackage.test.js
  58. 5 5
      cfc-web/src/api/guidePackage.js
  59. 3 3
      cfc-web/src/api/package.js
  60. 2 2
      cfc-web/src/router/index.js
  61. 2 2
      cfc-web/src/views/Dashboard.vue
  62. 12 12
      cfc-web/src/views/GuidePackages.vue
  63. 1 1
      cfc-web/src/views/Layout.vue
  64. 1 1
      cfc-web/src/views/TeacherDashboard.vue
  65. 2 2
      cfc-web/src/views/admin/AssessmentProducts.vue
  66. 1 1
      cfc-web/src/views/admin/Dashboard.vue
  67. 1 1
      cfc-web/src/views/admin/ProductEdit.vue
  68. 2 2
      cfc-web/src/views/admin/ReviewCenter.vue
  69. 3 3
      cfc-web/src/views/teacher/TeacherOrders.vue
  70. 18 18
      cfc-web/src/views/teacher/TeacherPackages.vue

+ 96 - 12
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -701,7 +701,7 @@ log.info("已添加template_id列到tasks表");
             log.warn("Migration skipped (already exists): {}", e.getMessage());
         }
         try {
-            jdbcTemplate.execute("ALTER TABLE assessment_appointments ADD COLUMN package_id BIGINT COMMENT '套餐ID'");
+            jdbcTemplate.execute("ALTER TABLE assessment_appointments ADD COLUMN package_id BIGINT COMMENT '任务模板ID'");
         } catch (Exception e) {
             log.warn("Migration skipped (already exists): {}", e.getMessage());
         }
@@ -3123,7 +3123,7 @@ log.info("已添加template_id列到tasks表");
         // guide_service_logs.notes
         modifyColumnToText("guide_service_logs", "notes", "服务记录");
         // guide_packages.description
-        modifyColumnToText("guide_packages", "description", "套餐说明");
+        modifyColumnToText("guide_packages", "description", "任务模板说明");
         // guide_package_templates.description
         modifyColumnToText("guide_package_templates", "description", "说明");
         // service_types.description
@@ -3560,7 +3560,7 @@ try {
             log.warn("创建service_contents表失败: {}", e.getMessage());
         }
 
-        // 套餐模板表
+        // 任务模板模板表
         try {
             jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS guide_package_templates (" +
                 "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
@@ -3577,7 +3577,7 @@ try {
             log.warn("创建guide_package_templates表失败: {}", e.getMessage());
         }
 
-        // 套餐模板服务项表
+        // 任务模板模板服务项表
         try {
             jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS package_template_services (" +
                 "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
@@ -3590,16 +3590,16 @@ try {
             log.warn("创建package_template_services表失败: {}", e.getMessage());
         }
 
-        // 成长规划师套餐
+        // 成长规划师任务模板
         try {
             jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS guide_packages (" +
                 "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
                 "teacher_id BIGINT NOT NULL COMMENT '成长规划师ID', " +
                 "template_id BIGINT COMMENT '关联模板', " +
-                "name VARCHAR(100) NOT NULL COMMENT '套餐名称', " +
+                "name VARCHAR(100) NOT NULL COMMENT '任务模板名称', " +
                 "price INT NOT NULL COMMENT '销售价格(分)', " +
                 "validity_months INT COMMENT '有效期(月)', " +
-                "description VARCHAR(500) COMMENT '套餐说明', " +
+                "description VARCHAR(500) COMMENT '任务模板说明', " +
                 "status VARCHAR(20) DEFAULT 'DRAFT' COMMENT '状态:DRAFT/PUBLISHED/PAUSED', " +
                 "sales_count INT DEFAULT 0 COMMENT '销量', " +
                 "share_code VARCHAR(50) COMMENT '分享码', " +
@@ -3643,7 +3643,7 @@ try {
 
         // 迁移:guide_packages 表添加 level 列(GuidePackage 实体需要)
         try {
-            jdbcTemplate.execute("ALTER TABLE guide_packages ADD COLUMN level VARCHAR(20) COMMENT '套餐等级' AFTER name");
+            jdbcTemplate.execute("ALTER TABLE guide_packages ADD COLUMN level VARCHAR(20) COMMENT '任务模板等级' AFTER name");
         } catch (Exception e) {
             log.warn("Migration skipped (already exists): {}", e.getMessage());
         }
@@ -3662,11 +3662,11 @@ try {
             log.warn("Migration skipped (already exists): {}", e.getMessage());
         }
 
-        // 成长规划师套餐服务项表
+        // 成长规划师任务模板服务项表
         try {
             jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS guide_package_services (" +
                 "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
-                "package_id BIGINT NOT NULL COMMENT '关联套餐', " +
+                "package_id BIGINT NOT NULL COMMENT '关联任务模板', " +
                 "content_id BIGINT NOT NULL COMMENT '关联服务内容', " +
                 "quantity INT DEFAULT 1 COMMENT '数量', " +
                 "unit VARCHAR(20) COMMENT '单位' " +
@@ -3682,7 +3682,7 @@ try {
                 "order_no VARCHAR(50) NOT NULL COMMENT '订单号', " +
                 "teacher_id BIGINT NOT NULL COMMENT '成长规划师ID', " +
                 "family_id BIGINT NOT NULL COMMENT '家庭ID', " +
-                "package_id BIGINT NOT NULL COMMENT '套餐ID', " +
+                "package_id BIGINT NOT NULL COMMENT '任务模板ID', " +
                 "amount INT NOT NULL COMMENT '金额(分)', " +
                 "status VARCHAR(20) DEFAULT 'PENDING' COMMENT '状态:PENDING/PAID/COMPLETED/REFUNDED', " +
                 "pay_time DATETIME COMMENT '支付时间', " +
@@ -4931,7 +4931,7 @@ try {
             jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS assessment_products (" +
                 "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
                 "product_id BIGINT NOT NULL COMMENT '关联products表', " +
-                "assessment_type VARCHAR(20) NOT NULL COMMENT 'single=单包, bundle=套餐', " +
+                "assessment_type VARCHAR(20) NOT NULL COMMENT 'single=单包, bundle=任务模板', " +
                 "total_sessions INT NOT NULL DEFAULT 1 COMMENT '包含测评次数', " +
                 "validity_days INT NOT NULL DEFAULT 365 COMMENT '有效期(天)', " +
                 "guide_scope VARCHAR(50) DEFAULT 'all' COMMENT '规划师范围: all/assigned/auto', " +
@@ -5285,6 +5285,7 @@ try {
         runMigration89();
         runMigration90();
         runMigration91();
+        runMigration92();
     }
 
     private void runMigration81() {
@@ -5798,4 +5799,87 @@ try {
         ensureColumn("users", "nutritionist_reject_reason", "VARCHAR(500) DEFAULT NULL COMMENT '营养师审核拒绝原因'");
         log.info("已添加nutritionist_status和nutritionist_reject_reason列到users表");
     }
+
+    private void runMigration92() {
+        // 迁移 92: 创建dan_assessment_executions表(DAN测评服务执行记录)
+        try {
+            jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS `dan_assessment_executions` (" +
+                    "`id` BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+                    "`assessment_execution_id` BIGINT NOT NULL COMMENT '执行记录ID', " +
+                    "`assessment_order_id` BIGINT NOT NULL COMMENT '订单ID', " +
+                    "`child_id` BIGINT NOT NULL COMMENT '孩子ID', " +
+                    "`family_id` BIGINT NOT NULL COMMENT '家庭ID', " +
+                    "`quota_id` BIGINT COMMENT '额度ID', " +
+                    "`assessor_id` BIGINT NOT NULL COMMENT '测评师userId', " +
+                    "`assessor_status` ENUM('pending','completed','rejected') DEFAULT 'pending' COMMENT '测评师状态', " +
+                    "`assessor_completed_at` DATETIME COMMENT '测评师完成时间', " +
+                    "`assessor_notes` VARCHAR(200) COMMENT '测评摘要/服务备注', " +
+                    "`planner_id` BIGINT COMMENT '规划师userId', " +
+                    "`planner_status` ENUM('pending','completed','rejected') DEFAULT 'pending' COMMENT '规划师状态', " +
+                    "`planner_completed_at` DATETIME COMMENT '规划师完成时间', " +
+                    "`planner_notes` VARCHAR(200) COMMENT '规划服务备注', " +
+                    "`user_confirmed` TINYINT(1) DEFAULT 0 COMMENT '用户确认:0未确认,1已确认', " +
+                    "`user_confirmed_at` DATETIME COMMENT '用户确认时间', " +
+                    "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+                    "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
+                    "KEY `idx_assessment_execution_id` (`assessment_execution_id`), " +
+                    "KEY `idx_assessment_order_id` (`assessment_order_id`), " +
+                    "KEY `idx_assessor_id` (`assessor_id`), " +
+                    "KEY `idx_planner_id` (`planner_id`), " +
+                    "KEY `idx_child_id` (`child_id`), " +
+                    "KEY `idx_family_id` (`family_id`)" +
+                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DAN测评服务执行记录'");
+            log.info("已创建dan_assessment_executions表");
+        } catch (Exception e) {
+            // 表已存在,忽略错误
+        }
+
+        // 迁移 92: 创建service_ratings表(服务评分记录)
+        try {
+            jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS `service_ratings` (" +
+                    "`id` BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+                    "`execution_id` BIGINT NOT NULL COMMENT '执行记录ID', " +
+                    "`assessment_order_id` BIGINT NOT NULL COMMENT '订单ID', " +
+                    "`user_id` BIGINT NOT NULL COMMENT '评分用户ID', " +
+                    "`assessor_id` BIGINT NOT NULL COMMENT '测评师userId', " +
+                    "`assessor_rating` TINYINT DEFAULT 0 COMMENT '测评师评分 1-5', " +
+                    "`assessor_comment` VARCHAR(500) COMMENT '评价内容', " +
+                    "`planner_id` BIGINT COMMENT '规划师userId', " +
+                    "`planner_rating` TINYINT COMMENT '规划师评分 1-5', " +
+                    "`planner_comment` VARCHAR(500) COMMENT '评价内容', " +
+                    "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+                    "UNIQUE KEY `uniq_execution_user` (`execution_id`, `user_id`)," +
+                    "KEY `idx_assessor_id` (`assessor_id`)," +
+                    "KEY `idx_planner_id` (`planner_id`)" +
+                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务评分记录'");
+            log.info("已创建service_ratings表");
+        } catch (Exception e) {
+            // 表已存在,忽略错误
+        }
+
+        // 迁移 92: 创建service_settlements表(服务结算记录)
+        try {
+            jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS `service_settlements` (" +
+                    "`id` BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+                    "`execution_id` BIGINT NOT NULL COMMENT '执行记录ID', " +
+                    "`assessment_order_id` BIGINT NOT NULL COMMENT '订单ID', " +
+                    "`provider_id` BIGINT NOT NULL COMMENT '服务提供方userId', " +
+                    "`provider_type` ENUM('assessor','planner') NOT NULL COMMENT '服务方类型', " +
+                    "`service_fee` BIGINT DEFAULT 0 COMMENT '服务费用(分)', " +
+                    "`commission_rate` INT COMMENT '佣金比例(bps)', " +
+                    "`commission_amount` BIGINT DEFAULT 0 COMMENT '结算金额(分)', " +
+                    "`status` ENUM('pending','settled','failed') DEFAULT 'pending' COMMENT '结算状态', " +
+                    "`settled_at` DATETIME COMMENT '结算时间', " +
+                    "`transaction_id` VARCHAR(100) COMMENT '转账交易ID', " +
+                    "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+                    "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
+                    "KEY `idx_execution_id` (`execution_id`), " +
+                    "KEY `idx_provider_id` (`provider_id`), " +
+                    "KEY `idx_status` (`status`)" +
+                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务结算记录'");
+            log.info("已创建service_settlements表");
+        } catch (Exception e) {
+            // 表已存在,忽略错误
+        }
+    }
 }

+ 11 - 11
cfc-backend/src/main/java/com/etotem/cfc/controller/MarketController.java

@@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.*;
 import java.util.List;
 import java.util.Map;
 
-@Tag(name = "套餐市场", description = "家长浏览、购买、应用套餐等接口")
+@Tag(name = "任务模板市场", description = "家长浏览、购买、应用任务模板等接口")
 @RestController
 @RequestMapping("/api/market")
 public class MarketController {
@@ -30,9 +30,9 @@ public class MarketController {
     private TaskPlanService planService;
 
     /**
-     * 获取公开套餐列表 (市场)
+     * 获取公开任务模板列表 (市场)
      */
-    @Operation(summary = "获取公开套餐列表")
+    @Operation(summary = "获取公开任务模板列表")
     @PostMapping("/packages")
     public Result<List<TaskTemplatePackage>> getPublicPackages(@RequestBody(required = false) Map<String, Object> params) {
         String category = params != null && params.get("category") != null ? params.get("category").toString() : null;
@@ -41,9 +41,9 @@ public class MarketController {
     }
 
     /**
-     * 获取套餐详情
+     * 获取任务模板详情
      */
-    @Operation(summary = "获取套餐详情")
+    @Operation(summary = "获取任务模板详情")
     @PostMapping("/packages/{id}")
     public Result<TaskTemplatePackage> getPackageDetail(@PathVariable Long id) {
         TaskTemplatePackage pkg = packageService.getPackageById(id);
@@ -51,9 +51,9 @@ public class MarketController {
     }
 
     /**
-     * 获取套餐的任务项列表
+     * 获取任务模板的任务项列表
      */
-    @Operation(summary = "获取套餐任务项列表")
+    @Operation(summary = "获取任务模板任务项列表")
     @PostMapping("/packages/{id}/items")
     public Result<List<TaskTemplateItem>> getPackageItems(@PathVariable Long id) {
         List<TaskTemplateItem> items = packageService.getPackageItems(id);
@@ -61,9 +61,9 @@ public class MarketController {
     }
 
     /**
-     * 通过分享码获取套餐
+     * 通过分享码获取任务模板
      */
-    @Operation(summary = "通过分享码获取套餐")
+    @Operation(summary = "通过分享码获取任务模板")
     @PostMapping("/share/{code}")
     public Result<TaskTemplatePackage> getPackageByShareCode(@PathVariable String code) {
         TaskTemplatePackage pkg = packageService.getPackageByShareCode(code);
@@ -74,9 +74,9 @@ public class MarketController {
     }
 
     /**
-     * 购买并应用套餐
+     * 购买并应用任务模板
      */
-    @Operation(summary = "购买并应用套餐")
+    @Operation(summary = "购买并应用任务模板")
     @PostMapping("/packages/{id}/purchase")
     public Result<TaskPlanInstance> purchasePackage(
             @PathVariable Long id,

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/MembershipController.java

@@ -219,9 +219,9 @@ public class MembershipController {
     }
 
     /**
-     * 获取套餐价格列表
+     * 获取任务模板价格列表
      */
-    @Operation(summary = "获取套餐价格")
+    @Operation(summary = "获取任务模板价格")
     @PostMapping("/plans")
     public Result<List<Map<String, Object>>> getPricingPlans() {
         List<MembershipLevelDTO> levels = membershipService.getAllLevels();

+ 4 - 4
cfc-backend/src/main/java/com/etotem/cfc/controller/PackagePaymentController.java

@@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.*;
 
 import java.util.Map;
 
-@Tag(name = "套餐支付", description = "套餐购买支付接口")
+@Tag(name = "任务模板支付", description = "任务模板购买支付接口")
 @RestController
 @RequestMapping("/api/payment")
 public class PackagePaymentController {
@@ -79,9 +79,9 @@ public class PackagePaymentController {
     }
 
     /**
-     * 支付成功后应用套餐
+     * 支付成功后应用任务模板
      */
-    @Operation(summary = "支付成功后应用套餐")
+    @Operation(summary = "支付成功后应用任务模板")
     @PostMapping("/apply")
     public Result<TaskPlanInstance> applyAfterPayment(@RequestBody Map<String, Object> params) {
         Long orderId = Long.valueOf(params.get("orderId").toString());
@@ -99,7 +99,7 @@ public class PackagePaymentController {
             return Result.error("订单未支付");
         }
 
-        // 应用套餐
+        // 应用任务模板
         com.etotem.cfc.dto.ApplyPackageDTO dto = new com.etotem.cfc.dto.ApplyPackageDTO();
         dto.setPackageId(order.getPackageId());
         dto.setChildId(childId);

+ 132 - 132
cfc-backend/src/main/java/com/etotem/cfc/controller/TaskTemplatePackageController.java

@@ -1,132 +1,132 @@
-package com.etotem.cfc.controller;
-
-import com.etotem.cfc.common.Result;
-import com.etotem.cfc.dto.CreatePackageDTO;
-import com.etotem.cfc.dto.CreatePackageItemDTO;
-import com.etotem.cfc.entity.TaskTemplatePackage;
-import com.etotem.cfc.entity.TaskTemplateItem;
-import com.etotem.cfc.service.TaskTemplatePackageService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-
-import java.util.List;
-import java.util.Map;
-
-@Tag(name = "任务模板套餐", description = "套餐创建、审核、发布等接口")
-@RestController
-@RequestMapping("/api/packages")
-public class TaskTemplatePackageController {
-
-    @Resource
-    private TaskTemplatePackageService packageService;
-
-    /**
-     * 创建套餐
-     */
-    @Operation(summary = "创建套餐")
-    @PostMapping("/create")
-    public Result<Long> createPackage(@RequestAttribute("userId") Long userId,
-                                       @RequestBody CreatePackageDTO dto) {
-        TaskTemplatePackage pkg = packageService.createPackage(dto, userId);
-        return Result.success(pkg.getId());
-    }
-
-    /**
-     * 更新套餐
-     */
-    @Operation(summary = "更新套餐")
-    @PostMapping("/{id}/update")
-    public Result<Boolean> updatePackage(@PathVariable Long id,
-                                          @RequestBody CreatePackageDTO dto) {
-        boolean success = packageService.updatePackage(id, dto);
-        return Result.success(success);
-    }
-
-    /**
-     * 获取套餐详情
-     */
-    @Operation(summary = "获取套餐详情")
-    @PostMapping("/{id}")
-    public Result<TaskTemplatePackage> getPackage(@PathVariable Long id) {
-        TaskTemplatePackage pkg = packageService.getPackageById(id);
-        return Result.success(pkg);
-    }
-
-    /**
-     * 获取我的套餐列表
-     */
-    @Operation(summary = "获取我的套餐列表")
-    @PostMapping("/my")
-    public Result<List<TaskTemplatePackage>> getMyPackages(@RequestAttribute("userId") Long userId) {
-        List<TaskTemplatePackage> packages = packageService.getMyPackages(userId);
-        return Result.success(packages);
-    }
-
-    /**
-     * 提交审核
-     */
-    @Operation(summary = "提交审核")
-    @PostMapping("/{id}/submit")
-    public Result<Boolean> submitForReview(@PathVariable Long id) {
-        boolean success = packageService.submitForReview(id);
-        return Result.success(success);
-    }
-
-    /**
-     * 发布/下架
-     */
-    @Operation(summary = "发布/下架")
-    @PostMapping("/{id}/publish")
-    public Result<Boolean> publishPackage(@PathVariable Long id,
-                                           @RequestBody Map<String, Object> params) {
-        boolean publish = params.get("publish") != null && Boolean.parseBoolean(params.get("publish").toString());
-        boolean success = packageService.publishPackage(id, publish);
-        return Result.success(success);
-    }
-
-    /**
-     * 添加任务项
-     */
-    @Operation(summary = "添加任务项")
-    @PostMapping("/{id}/items")
-    public Result<Long> addItem(@PathVariable Long id,
-                                  @RequestBody CreatePackageItemDTO dto) {
-        dto.setPackageId(id);
-        TaskTemplateItem item = packageService.addItem(dto);
-        return Result.success(item.getId());
-    }
-
-    /**
-     * 更新任务项
-     */
-    @Operation(summary = "更新任务项")
-    @PostMapping("/items/{itemId}")
-    public Result<Boolean> updateItem(@PathVariable Long itemId,
-                                        @RequestBody CreatePackageItemDTO dto) {
-        boolean success = packageService.updateItem(itemId, dto);
-        return Result.success(success);
-    }
-
-    /**
-     * 删除任务项
-     */
-    @Operation(summary = "删除任务项")
-    @PostMapping("/items/{itemId}/delete")
-    public Result<Boolean> deleteItem(@PathVariable Long itemId) {
-        boolean success = packageService.deleteItem(itemId);
-        return Result.success(success);
-    }
-
-    /**
-     * 获取套餐的任务项列表
-     */
-    @Operation(summary = "获取套餐的任务项列表")
-    @PostMapping("/{id}/item-list")
-    public Result<List<TaskTemplateItem>> getPackageItems(@PathVariable Long id) {
-        List<TaskTemplateItem> items = packageService.getPackageItems(id);
-        return Result.success(items);
-    }
-}
+package com.etotem.cfc.controller;
+
+import com.etotem.cfc.common.Result;
+import com.etotem.cfc.dto.CreatePackageDTO;
+import com.etotem.cfc.dto.CreatePackageItemDTO;
+import com.etotem.cfc.entity.TaskTemplatePackage;
+import com.etotem.cfc.entity.TaskTemplateItem;
+import com.etotem.cfc.service.TaskTemplatePackageService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+import java.util.List;
+import java.util.Map;
+
+@Tag(name = "任务模板任务模板", description = "任务模板创建、审核、发布等接口")
+@RestController
+@RequestMapping("/api/packages")
+public class TaskTemplatePackageController {
+
+    @Resource
+    private TaskTemplatePackageService packageService;
+
+    /**
+     * 创建任务模板
+     */
+    @Operation(summary = "创建任务模板")
+    @PostMapping("/create")
+    public Result<Long> createPackage(@RequestAttribute("userId") Long userId,
+                                       @RequestBody CreatePackageDTO dto) {
+        TaskTemplatePackage pkg = packageService.createPackage(dto, userId);
+        return Result.success(pkg.getId());
+    }
+
+    /**
+     * 更新任务模板
+     */
+    @Operation(summary = "更新任务模板")
+    @PostMapping("/{id}/update")
+    public Result<Boolean> updatePackage(@PathVariable Long id,
+                                          @RequestBody CreatePackageDTO dto) {
+        boolean success = packageService.updatePackage(id, dto);
+        return Result.success(success);
+    }
+
+    /**
+     * 获取任务模板详情
+     */
+    @Operation(summary = "获取任务模板详情")
+    @PostMapping("/{id}")
+    public Result<TaskTemplatePackage> getPackage(@PathVariable Long id) {
+        TaskTemplatePackage pkg = packageService.getPackageById(id);
+        return Result.success(pkg);
+    }
+
+    /**
+     * 获取我的任务模板列表
+     */
+    @Operation(summary = "获取我的任务模板列表")
+    @PostMapping("/my")
+    public Result<List<TaskTemplatePackage>> getMyPackages(@RequestAttribute("userId") Long userId) {
+        List<TaskTemplatePackage> packages = packageService.getMyPackages(userId);
+        return Result.success(packages);
+    }
+
+    /**
+     * 提交审核
+     */
+    @Operation(summary = "提交审核")
+    @PostMapping("/{id}/submit")
+    public Result<Boolean> submitForReview(@PathVariable Long id) {
+        boolean success = packageService.submitForReview(id);
+        return Result.success(success);
+    }
+
+    /**
+     * 发布/下架
+     */
+    @Operation(summary = "发布/下架")
+    @PostMapping("/{id}/publish")
+    public Result<Boolean> publishPackage(@PathVariable Long id,
+                                           @RequestBody Map<String, Object> params) {
+        boolean publish = params.get("publish") != null && Boolean.parseBoolean(params.get("publish").toString());
+        boolean success = packageService.publishPackage(id, publish);
+        return Result.success(success);
+    }
+
+    /**
+     * 添加任务项
+     */
+    @Operation(summary = "添加任务项")
+    @PostMapping("/{id}/items")
+    public Result<Long> addItem(@PathVariable Long id,
+                                  @RequestBody CreatePackageItemDTO dto) {
+        dto.setPackageId(id);
+        TaskTemplateItem item = packageService.addItem(dto);
+        return Result.success(item.getId());
+    }
+
+    /**
+     * 更新任务项
+     */
+    @Operation(summary = "更新任务项")
+    @PostMapping("/items/{itemId}")
+    public Result<Boolean> updateItem(@PathVariable Long itemId,
+                                        @RequestBody CreatePackageItemDTO dto) {
+        boolean success = packageService.updateItem(itemId, dto);
+        return Result.success(success);
+    }
+
+    /**
+     * 删除任务项
+     */
+    @Operation(summary = "删除任务项")
+    @PostMapping("/items/{itemId}/delete")
+    public Result<Boolean> deleteItem(@PathVariable Long itemId) {
+        boolean success = packageService.deleteItem(itemId);
+        return Result.success(success);
+    }
+
+    /**
+     * 获取任务模板的任务项列表
+     */
+    @Operation(summary = "获取任务模板的任务项列表")
+    @PostMapping("/{id}/item-list")
+    public Result<List<TaskTemplateItem>> getPackageItems(@PathVariable Long id) {
+        List<TaskTemplateItem> items = packageService.getPackageItems(id);
+        return Result.success(items);
+    }
+}

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminController.java

@@ -667,9 +667,9 @@ public class AdminController {
     }
 
     /**
-     * 获取待审核套餐数量
+     * 获取待审核任务模板数量
      */
-    @Operation(summary = "获取待审核套餐数量")
+    @Operation(summary = "获取待审核任务模板数量")
     @PostMapping("/package/pending-count")
     public Result<Map<String, Object>> getPendingPackageCount() {
         Long count = guidePackageMapper.selectCount(new LambdaQueryWrapper<com.etotem.cfc.entity.GuidePackage>()

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminPackageController.java

@@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
-@Tag(name = "管理端-套餐审核", description = "套餐审核管理接口")
+@Tag(name = "管理端-任务模板审核", description = "任务模板审核管理接口")
 @RestController
 @RequestMapping("/api/admin/packages")
 public class AdminPackageController {
@@ -19,9 +19,9 @@ public class AdminPackageController {
     private TaskTemplatePackageService packageService;
 
     /**
-     * 获取待审核的套餐列表
+     * 获取待审核的任务模板列表
      */
-    @Operation(summary = "获取待审核套餐列表")
+    @Operation(summary = "获取待审核任务模板列表")
     @PostMapping("/pending")
     public Result<List<TaskTemplatePackage>> getPendingPackages() {
         List<TaskTemplatePackage> packages = packageService.getPendingPackages();

+ 7 - 7
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/PackageTemplateController.java

@@ -11,7 +11,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 
-@Tag(name = "套餐模板管理", description = "系统套餐模板CRUD")
+@Tag(name = "任务模板模板管理", description = "系统任务模板模板CRUD")
 @RestController
 @RequestMapping("/api/admin/package-templates")
 public class PackageTemplateController {
@@ -20,28 +20,28 @@ public class PackageTemplateController {
     private GuidePackageTemplateService templateService;
 
     @PostMapping("/list")
-    @Operation(summary = "获取套餐模板列表")
+    @Operation(summary = "获取任务模板模板列表")
     public Result<List<GuidePackageTemplate>> list() {
         List<GuidePackageTemplate> list = templateService.getActiveTemplates();
         return Result.success(list);
     }
 
     @PostMapping("/all")
-    @Operation(summary = "获取所有套餐模板(含停用)")
+    @Operation(summary = "获取所有任务模板模板(含停用)")
     public Result<List<GuidePackageTemplate>> listAll() {
         List<GuidePackageTemplate> list = templateService.list();
         return Result.success(list);
     }
 
     @PostMapping("/{id}")
-    @Operation(summary = "获取套餐模板详情")
+    @Operation(summary = "获取任务模板模板详情")
     public Result<GuidePackageTemplate> getById(@PathVariable Long id) {
         GuidePackageTemplate template = templateService.getTemplateById(id);
         return template != null ? Result.success(template) : Result.error("不存在");
     }
 
     @PostMapping("/create")
-    @Operation(summary = "创建套餐模板")
+    @Operation(summary = "创建任务模板模板")
     public Result<GuidePackageTemplate> create(@RequestBody GuidePackageTemplate template) {
         template.setStatus("ACTIVE");
         template.setCreatedAt(new Date());
@@ -51,7 +51,7 @@ public class PackageTemplateController {
     }
 
     @PostMapping("/{id}/update")
-    @Operation(summary = "更新套餐模板")
+    @Operation(summary = "更新任务模板模板")
     public Result<GuidePackageTemplate> update(@PathVariable Long id, @RequestBody GuidePackageTemplate template) {
         template.setId(id);
         template.setUpdatedAt(new Date());
@@ -60,7 +60,7 @@ public class PackageTemplateController {
     }
 
     @PostMapping("/{id}/delete")
-    @Operation(summary = "删除套餐模板")
+    @Operation(summary = "删除任务模板模板")
     public Result<Void> delete(@PathVariable Long id) {
         boolean success = templateService.deleteTemplate(id);
         return success ? Result.success(null) : Result.error("删除失败");

+ 8 - 8
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideManagementController.java

@@ -266,9 +266,9 @@ public class GuideManagementController {
     }
 
     /**
-     * 添加成长规划师套餐
+     * 添加成长规划师任务模板
      */
-    @Operation(summary = "添加成长规划师套餐")
+    @Operation(summary = "添加成长规划师任务模板")
     @PostMapping("/package/add")
     public Result<Boolean> addGuidePackage(@RequestAttribute("userId") Long userId,
                                           @RequestBody Map<String, Object> params) {
@@ -283,9 +283,9 @@ public class GuideManagementController {
     }
 
     /**
-     * 获取成长规划师对特定套餐的定价
+     * 获取成长规划师对特定任务模板的定价
      */
-    @Operation(summary = "获取成长规划师套餐定价")
+    @Operation(summary = "获取成长规划师任务模板定价")
     @PostMapping("/package/{packageId}")
     public Result<GuidePackage> getGuidePackage(@RequestAttribute("userId") Long userId,
                                                @PathVariable Long packageId) {
@@ -294,9 +294,9 @@ public class GuideManagementController {
     }
 
     /**
-     * 更新成长规划师套餐价格
+     * 更新成长规划师任务模板价格
      */
-    @Operation(summary = "更新成长规划师套餐价格")
+    @Operation(summary = "更新成长规划师任务模板价格")
     @PostMapping("/package/{packageId}/update")
     public Result<Boolean> updateGuidePackage(@RequestAttribute("userId") Long userId,
                                                @PathVariable Long packageId,
@@ -307,9 +307,9 @@ public class GuideManagementController {
     }
 
     /**
-     * 删除成长规划师套餐
+     * 删除成长规划师任务模板
      */
-    @Operation(summary = "删除成长规划师套餐")
+    @Operation(summary = "删除成长规划师任务模板")
     @PostMapping("/package/{packageId}/delete")
     public Result<Boolean> deleteGuidePackage(@RequestAttribute("userId") Long userId,
                                                @PathVariable Long packageId) {

+ 14 - 14
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuidePackageController.java

@@ -14,7 +14,7 @@ import javax.annotation.Resource;
 import java.util.List;
 import java.util.Map;
 
-@Tag(name = "成长规划师套餐", description = "成长规划师套餐管理接口")
+@Tag(name = "成长规划师任务模板", description = "成长规划师任务模板管理接口")
 @RestController
 @RequestMapping("/api/guide/packages")
 public class GuidePackageController {
@@ -26,32 +26,32 @@ public class GuidePackageController {
     private GuidePackageTemplateService guidePackageTemplateService;
 
     @PostMapping("/my")
-    @Operation(summary = "获取我的套餐")
+    @Operation(summary = "获取我的任务模板")
     public Result<List<GuidePackage>> getMyPackagesAlias(@RequestAttribute("userId") Long guideId) {
         List<GuidePackage> packages = guidePackageService.getGuidePackages(guideId);
         return Result.success(packages);
     }
 
     @PostMapping("/list")
-    @Operation(summary = "获取我的套餐列表")
+    @Operation(summary = "获取我的任务模板列表")
     public Result<List<GuidePackage>> getMyPackages(@RequestAttribute("userId") Long guideId) {
         List<GuidePackage> packages = guidePackageService.getGuidePackages(guideId);
         return Result.success(packages);
     }
 
     @PostMapping("/detail")
-    @Operation(summary = "获取套餐详情")
+    @Operation(summary = "获取任务模板详情")
     public Result<GuidePackage> getPackageDetail(@RequestBody Map<String, Object> params) {
         Long id = Long.valueOf(params.get("id").toString());
         GuidePackage pkg = guidePackageService.getById(id);
         if (pkg == null) {
-            return Result.error("套餐不存在");
+            return Result.error("任务模板不存在");
         }
         return Result.success(pkg);
     }
 
     @PostMapping("/create")
-    @Operation(summary = "创建套餐")
+    @Operation(summary = "创建任务模板")
     public Result<GuidePackage> createPackage(@RequestAttribute("userId") Long guideId,
                                                @RequestBody GuidePackageDTO dto) {
         GuidePackage pkg = new GuidePackage();
@@ -72,13 +72,13 @@ public class GuidePackageController {
     }
 
     @PostMapping("/update")
-    @Operation(summary = "更新套餐")
+    @Operation(summary = "更新任务模板")
     public Result<GuidePackage> updatePackage(@RequestAttribute("userId") Long guideId,
                                                @RequestBody Map<String, Object> params) {
         Long id = Long.valueOf(params.get("id").toString());
         GuidePackage existing = guidePackageService.getById(id);
         if (existing == null) {
-            return Result.error("套餐不存在");
+            return Result.error("任务模板不存在");
         }
         if (params.get("name") != null) {
             existing.setName(params.get("name").toString());
@@ -91,14 +91,14 @@ public class GuidePackageController {
     }
 
     @PostMapping("/update-status")
-    @Operation(summary = "更新套餐状态")
+    @Operation(summary = "更新任务模板状态")
     public Result<Boolean> updateStatus(@RequestAttribute("userId") Long guideId,
                                         @RequestBody Map<String, Object> params) {
         Long id = Long.valueOf(params.get("id").toString());
         String status = params.get("status").toString();
         GuidePackage existing = guidePackageService.getById(id);
         if (existing == null) {
-            return Result.error("套餐不存在");
+            return Result.error("任务模板不存在");
         }
         if (!"DRAFT".equals(status) && !"PUBLISHED".equals(status) && !"PAUSED".equals(status)) {
             return Result.error("无效状态");
@@ -109,13 +109,13 @@ public class GuidePackageController {
     }
 
     @PostMapping("/delete")
-    @Operation(summary = "删除套餐")
+    @Operation(summary = "删除任务模板")
     public Result<Boolean> deletePackage(@RequestAttribute("userId") Long guideId,
                                          @RequestBody Map<String, Object> params) {
         Long id = Long.valueOf(params.get("id").toString());
         GuidePackage existing = guidePackageService.getById(id);
         if (existing == null) {
-            return Result.error("套餐不存在");
+            return Result.error("任务模板不存在");
         }
         existing.setStatus("DELETED");
         guidePackageService.updateById(existing);
@@ -123,7 +123,7 @@ public class GuidePackageController {
     }
 
     @PostMapping("/templates")
-    @Operation(summary = "获取套餐模板列表")
+    @Operation(summary = "获取任务模板模板列表")
     public Result<List<GuidePackageTemplate>> getTemplates() {
         List<GuidePackageTemplate> templates = guidePackageTemplateService.list();
         return Result.success(templates);
@@ -141,7 +141,7 @@ public class GuidePackageController {
     }
 
     @PostMapping("/increment-sales")
-    @Operation(summary = "增加套餐销量")
+    @Operation(summary = "增加任务模板销量")
     public Result<Boolean> incrementSales(@RequestBody Map<String, Object> params) {
         Long id = Long.valueOf(params.get("id").toString());
         boolean success = guidePackageService.incrementSalesCount(id);

+ 7 - 7
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/PackagePurchaseController.java

@@ -13,9 +13,9 @@ import java.util.List;
 import java.util.Map;
 
 /**
- * 套餐购买控制器
+ * 任务模板购买控制器
  */
-@Tag(name = "套餐购买", description = "套餐购买、价格查询等接口")
+@Tag(name = "任务模板购买", description = "任务模板购买、价格查询等接口")
 @RestController
 @RequestMapping("/api/package")
 public class PackagePurchaseController {
@@ -24,9 +24,9 @@ public class PackagePurchaseController {
     private PackagePurchaseService packagePurchaseService;
 
     /**
-     * 获取套餐价格
+     * 获取任务模板价格
      */
-    @Operation(summary = "获取套餐价格")
+    @Operation(summary = "获取任务模板价格")
     @PostMapping("/price")
     public Result<Map<String, Object>> getPackagePrice(@RequestParam Long packageId,
                                                         @RequestParam(required = false) Long guideId,
@@ -34,7 +34,7 @@ public class PackagePurchaseController {
         Map<String, Object> priceInfo = packagePurchaseService.getPackagePrice(packageId, guideId, inviteCode);
         
         if (priceInfo == null) {
-            return Result.error("套餐不存在");
+            return Result.error("任务模板不存在");
         }
         
         return Result.success(priceInfo);
@@ -51,9 +51,9 @@ public class PackagePurchaseController {
     }
 
     /**
-     * 创建套餐订单
+     * 创建任务模板订单
      */
-    @Operation(summary = "创建套餐订单")
+    @Operation(summary = "创建任务模板订单")
     @PostMapping("/order/create")
     public Result<PackageOrder> createOrder(@RequestBody PackagePurchaseDTO dto) {
         PackageOrder order = packagePurchaseService.createOrder(dto);

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/dto/AddGuidePackageDTO.java

@@ -7,7 +7,7 @@ import javax.validation.constraints.NotNull;
 
 @Data
 public class AddGuidePackageDTO {
-    @NotNull(message = "套餐ID不能为空")
+    @NotNull(message = "任务模板ID不能为空")
     private Long packageId;
 
     @NotNull(message = "价格不能为空")

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/dto/AdminCreateGuidePackageDTO.java

@@ -8,7 +8,7 @@ import javax.validation.constraints.NotNull;
 @Data
 public class AdminCreateGuidePackageDTO {
 
-    @NotBlank(message = "套餐名称不能为空")
+    @NotBlank(message = "任务模板名称不能为空")
     private String name;
 
     private String level;

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/dto/AssessmentCreateOrderDTO.java

@@ -19,7 +19,7 @@ public class AssessmentCreateOrderDTO {
     @NotNull(message = "规划师ID不能为空")
     private Long guideId;
 
-    @NotNull(message = "套餐ID不能为空")
+    @NotNull(message = "任务模板ID不能为空")
     private Long packageId;
 
     private String guideName;

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/dto/GuidePackageUpdateDTO.java

@@ -6,7 +6,7 @@ import javax.validation.constraints.NotNull;
 
 @Data
 public class GuidePackageUpdateDTO {
-    @NotNull(message = "套餐ID不能为空")
+    @NotNull(message = "任务模板ID不能为空")
     private Long id;
 
     private String name;

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/dto/PackageCreateOrderDTO.java

@@ -6,7 +6,7 @@ import javax.validation.constraints.NotNull;
 
 @Data
 public class PackageCreateOrderDTO {
-    @NotNull(message = "套餐ID不能为空")
+    @NotNull(message = "任务模板ID不能为空")
     private Long packageId;
 
     private String payMethod = "wechat";

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/PackagePurchaseDTO.java

@@ -5,7 +5,7 @@ import lombok.Data;
 import java.io.Serializable;
 
 /**
- * 套餐购买 DTO
+ * 任务模板购买 DTO
  */
 @Data
 public class PackagePurchaseDTO implements Serializable {
@@ -21,7 +21,7 @@ public class PackagePurchaseDTO implements Serializable {
     private Long familyId;
 
     /**
-     * 套餐ID
+     * 任务模板ID
      */
     private Long packageId;
 

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/entity/AssessmentProduct.java

@@ -17,7 +17,7 @@ public class AssessmentProduct implements Serializable {
 
     private Long productId;
 
-    private String assessmentType;   // single=单包, bundle=套餐
+    private String assessmentType;   // single=单包, bundle=任务模板
 
     private Integer totalSessions;   // 包含测评次数
 

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/PackageOrder.java

@@ -21,9 +21,9 @@ public class PackageOrder implements Serializable {
 
     private Long familyId;        // 家庭ID
 
-    private Long packageId;       // 套餐ID
+    private Long packageId;       // 任务模板ID
 
-    private String packageName;   // 套餐名称
+    private String packageName;   // 任务模板名称
 
     private Integer price;      // 支付金额(分)
 

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/entity/TaskPlanInstance.java

@@ -15,7 +15,7 @@ public class TaskPlanInstance implements Serializable {
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    private Long packageId;     // 来源套餐ID
+    private Long packageId;     // 来源任务模板ID
 
     private Long familyId;       // 所属家庭
 

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/entity/TaskTemplateItem.java

@@ -15,7 +15,7 @@ public class TaskTemplateItem implements Serializable {
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    private Long packageId;     // 所属套餐ID
+    private Long packageId;     // 所属任务模板ID
 
     private String taskName;     // 任务名称
 

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/entity/TaskTemplatePackage.java

@@ -17,7 +17,7 @@ public class TaskTemplatePackage implements Serializable {
 
     private Long creatorId;      // 创建者成长规划师ID
 
-    private String name;         // 套餐名称,如"21天养成学习习惯"
+    private String name;         // 任务模板名称,如"21天养成学习习惯"
 
     private String description;  // 详细介绍
 

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/mapper/GuidePackageMapper.java

@@ -5,7 +5,7 @@ import com.etotem.cfc.entity.GuidePackage;
 import org.apache.ibatis.annotations.Mapper;
 
 /**
- * 成长规划师套餐 Mapper
+ * 成长规划师任务模板 Mapper
  */
 @Mapper
 public interface GuidePackageMapper extends BaseMapper<GuidePackage> {

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java

@@ -269,7 +269,7 @@ public class CommissionService {
                         commissionType = "member";
                     }
                 } else {
-                    // 没有productId的非会员订单(如评估、套餐
+                    // 没有productId的非会员订单(如评估、任务模板
                     if (isFamily) {
                         int serviceRateBps = getRateBps("commission_service_rate", 1000);
                         l1Amount = orderAmount * serviceRateBps / 10000;

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/service/DataMigrationService.java

@@ -480,7 +480,7 @@ public class DataMigrationService implements DataMigrationServiceInterface {
                     order.setOrderNo((String) row.get("order_no"));
                     order.setUserId(userId);
                     order.setFamilyId(familyId);
-                    order.setPackageName("测评套餐");
+                    order.setPackageName("测评任务模板");
                     order.setPrice(fee);
                     order.setStatus(status);
                     if (row.get("create_time") != null) {

+ 10 - 10
cfc-backend/src/main/java/com/etotem/cfc/service/GuidePackageService.java

@@ -14,7 +14,7 @@ import org.springframework.stereotype.Service;
 import java.util.List;
 
 /**
- * 指导师套餐服务
+ * 指导师任务模板服务
  */
 @Service
 public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePackage> implements GuidePackageServiceInterface {
@@ -23,7 +23,7 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
     private TaskTemplatePackageMapper taskTemplatePackageMapper;
 
     /**
-     * 添加指导师套餐
+     * 添加指导师任务模板
      */
     public boolean addGuidePackage(Long guideId, Long packageId, Integer price, Integer commissionRate) {
         // 检查是否已经存在
@@ -35,7 +35,7 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
             return false; // 已经存在
         }
         
-        // 获取套餐信息
+        // 获取任务模板信息
         TaskTemplatePackage taskPackage = taskTemplatePackageMapper.selectById(packageId);
         if (taskPackage == null) {
             return false;
@@ -53,7 +53,7 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
     }
 
     /**
-     * 获取指导师的套餐列表
+     * 获取指导师的任务模板列表
      */
     public List<GuidePackage> getGuidePackages(Long guideId) {
         LambdaQueryWrapper<GuidePackage> wrapper = new LambdaQueryWrapper<>();
@@ -65,7 +65,7 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
     }
 
     /**
-     * 获取指导师对特定套餐的定价
+     * 获取指导师对特定任务模板的定价
      */
     public GuidePackage getGuidePackage(Long guideId, Long packageId) {
         LambdaQueryWrapper<GuidePackage> wrapper = new LambdaQueryWrapper<>();
@@ -75,7 +75,7 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
     }
 
     /**
-     * 更新指导师套餐价格
+     * 更新指导师任务模板价格
      */
     public boolean updateGuidePackagePrice(Long guideId, Long packageId, Integer price) {
         GuidePackage guidePackage = getGuidePackage(guideId, packageId);
@@ -88,7 +88,7 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
     }
 
 /**
-     * 删除指导师套餐
+     * 删除指导师任务模板
      */
     public boolean deleteGuidePackage(Long guideId, Long packageId) {
         GuidePackage guidePackage = getGuidePackage(guideId, packageId);
@@ -101,14 +101,14 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
     }
 
     /**
-     * 增加套餐销量 - 暂不实现
+     * 增加任务模板销量 - 暂不实现
      */
     public boolean incrementSalesCount(Long packageId) {
         return true;
     }
 
     /**
-     * 获取所有有效套餐
+     * 获取所有有效任务模板
      */
     public List<GuidePackage> getActivePackages() {
         LambdaQueryWrapper<GuidePackage> wrapper = new LambdaQueryWrapper<>();
@@ -118,7 +118,7 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
     }
 
     /**
-     * 根据等级获取套餐
+     * 根据等级获取任务模板
      */
     public List<GuidePackage> getPackagesByLevel(String level) {
         LambdaQueryWrapper<GuidePackage> wrapper = new LambdaQueryWrapper<>();

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/PackagePaymentService.java

@@ -55,13 +55,13 @@ public class PackagePaymentService implements PackagePaymentServiceInterface {
      * 创建支付订单
      */
     public PackageOrder createOrder(Long userId, Long familyId, Long packageId, String payMethod, Long userCouponId) {
-        // 获取套餐信息
+        // 获取任务模板信息
         TaskTemplatePackage pkg = packageService.getPackageById(packageId);
         if (pkg == null) {
-            throw new RuntimeException("套餐不存在");
+            throw new RuntimeException("任务模板不存在");
         }
 
-        // 如果套餐免费,直接创建并返回
+        // 如果任务模板免费,直接创建并返回
         if (pkg.getPrice() == null || pkg.getPrice() <= 0) {
             PackageOrder order = new PackageOrder();
             order.setOrderNo(generateOrderNo());

+ 8 - 8
cfc-backend/src/main/java/com/etotem/cfc/service/PackagePurchaseService.java

@@ -21,7 +21,7 @@ import java.util.*;
 import java.util.stream.Collectors;
 
 /**
- * 套餐购买服务
+ * 任务模板购买服务
  */
 @Service
 public class PackagePurchaseService implements PackagePurchaseServiceInterface {
@@ -45,10 +45,10 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
     private FamilyMapper familyMapper;
 
     /**
-     * 获取套餐价格(含指导师定价)
+     * 获取任务模板价格(含指导师定价)
      */
     public Map<String, Object> getPackagePrice(Long packageId, Long guideId, String inviteCode) {
-        // 获取套餐基础信息
+        // 获取任务模板基础信息
         TaskTemplatePackage taskPackage = taskTemplatePackageMapper.selectById(packageId);
         if (taskPackage == null) {
             return null;
@@ -75,7 +75,7 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
                     result.put("guideAvatar", guide.getAvatar());
                 }
             } else {
-                // 指导师没有设置该套餐的价格,使用基础价格
+                // 指导师没有设置该任务模板的价格,使用基础价格
                 result.put("guidePrice", taskPackage.getPrice());
                 result.put("commissionRate", 1000); // 10% in bps
                 result.put("totalPrice", taskPackage.getPrice());
@@ -98,7 +98,7 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
                         result.put("guideAvatar", guide.getAvatar());
                     }
                 } else {
-                    // 指导师没有设置该套餐的价格,使用基础价格
+                    // 指导师没有设置该任务模板的价格,使用基础价格
                     result.put("guidePrice", taskPackage.getPrice());
                     result.put("commissionRate", 1000); // 10% in bps
                     result.put("totalPrice", taskPackage.getPrice());
@@ -121,7 +121,7 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
     }
 
 /**
-     * 获取可用的指导师列表(针对特定套餐
+     * 获取可用的指导师列表(针对特定任务模板
      */
     public List<Map<String, Object>> getAvailableGuides(Long packageId) {
         List<Map<String, Object>> result = new ArrayList<>();
@@ -152,10 +152,10 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
     }
 
     /**
-     * 创建套餐订单
+     * 创建任务模板订单
      */
     public PackageOrder createOrder(PackagePurchaseDTO dto) {
-        // 获取套餐价格信息
+        // 获取任务模板价格信息
         Map<String, Object> priceInfo = getPackagePrice(dto.getPackageId(), dto.getGuideId(), dto.getInviteCode());
         
         if (priceInfo == null) {

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/TaskPlanService.java

@@ -35,14 +35,14 @@ public class TaskPlanService implements TaskPlanServiceInterface {
     private TaskTemplatePackageService packageService;
 
     /**
-     * 家长应用套餐 - 创建任务计划实例
+     * 家长应用任务模板 - 创建任务计划实例
      */
     @Transactional
     public TaskPlanInstance applyPackage(ApplyPackageDTO dto, Long familyId) {
-        // 获取套餐信息
+        // 获取任务模板信息
         TaskTemplatePackage pkg = packageService.getPackageById(dto.getPackageId());
         if (pkg == null) {
-            throw new RuntimeException("套餐不存在");
+            throw new RuntimeException("任务模板不存在");
         }
 
         // 获取选中的任务项

+ 9 - 9
cfc-backend/src/main/java/com/etotem/cfc/service/TaskTemplatePackageService.java

@@ -27,7 +27,7 @@ public class TaskTemplatePackageService {
     private TaskTemplateItemMapper itemMapper;
 
     /**
-     * 创建套餐
+     * 创建任务模板
      */
     @Transactional
     public TaskTemplatePackage createPackage(CreatePackageDTO dto, Long creatorId) {
@@ -55,7 +55,7 @@ public class TaskTemplatePackageService {
     }
 
     /**
-     * 更新套餐
+     * 更新任务模板
      */
     public boolean updatePackage(Long id, CreatePackageDTO dto) {
         TaskTemplatePackage pkg = packageMapper.selectById(id);
@@ -78,14 +78,14 @@ public class TaskTemplatePackageService {
     }
 
     /**
-     * 获取套餐详情
+     * 获取任务模板详情
      */
     public TaskTemplatePackage getPackageById(Long id) {
         return packageMapper.selectById(id);
     }
 
     /**
-     * 获取我的套餐列表
+     * 获取我的任务模板列表
      */
     public List<TaskTemplatePackage> getMyPackages(Long creatorId) {
         return packageMapper.selectList(
@@ -96,7 +96,7 @@ public class TaskTemplatePackageService {
     }
 
     /**
-     * 获取公开套餐列表 (市场)
+     * 获取公开任务模板列表 (市场)
      */
     public List<TaskTemplatePackage> getPublicPackages(String category) {
         com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<TaskTemplatePackage> wrapper = new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<TaskTemplatePackage>()
@@ -112,7 +112,7 @@ public class TaskTemplatePackageService {
     }
 
     /**
-     * 通过分享码获取套餐
+     * 通过分享码获取任务模板
      */
     public TaskTemplatePackage getPackageByShareCode(String shareCode) {
         return packageMapper.selectOne(
@@ -178,7 +178,7 @@ public class TaskTemplatePackageService {
         return packageMapper.updateById(pkg) > 0;
     }
 
-    // ========== 套餐任务项管理 ==========
+    // ========== 任务模板任务项管理 ==========
 
     /**
      * 添加任务项
@@ -227,7 +227,7 @@ public class TaskTemplatePackageService {
     }
 
     /**
-     * 获取套餐的任务项列表
+     * 获取任务模板的任务项列表
      */
     public List<TaskTemplateItem> getPackageItems(Long packageId) {
         return itemMapper.selectList(
@@ -238,7 +238,7 @@ public class TaskTemplatePackageService {
     }
 
     /**
-     * 获取待审核的套餐列表
+     * 获取待审核的任务模板列表
      */
     public List<TaskTemplatePackage> getPendingPackages() {
         return packageMapper.selectList(

+ 93 - 28
cfc-backend/src/main/resources/schema.sql

@@ -296,7 +296,7 @@ CREATE TABLE IF NOT EXISTS guides (
     level VARCHAR(20) NOT NULL DEFAULT 'junior' COMMENT '等级: junior-初级, intermediate-中级, senior-高级',
     status VARCHAR(20) NOT NULL DEFAULT 'active' COMMENT '状态: active-活跃, inactive-停用',
     service_count INT DEFAULT 0 COMMENT '当前服务家庭数',
-    package_id BIGINT COMMENT '购买套餐ID',
+    package_id BIGINT COMMENT '购买任务模板ID',
     nickname VARCHAR(100) COMMENT '申请昵称',
     phone VARCHAR(20) COMMENT '联系电话',
     intro TEXT COMMENT '个人介绍',
@@ -325,7 +325,7 @@ CREATE TABLE IF NOT EXISTS assessment_appointments (
     child_id BIGINT COMMENT '孩子ID',
     teacher_id BIGINT COMMENT '教师ID',
     guide_id BIGINT COMMENT '规划师ID',
-    package_id BIGINT COMMENT '套餐ID',
+    package_id BIGINT COMMENT '任务模板ID',
     appointment_date VARCHAR(20) COMMENT '预约日期 yyyy-MM-dd',
     appointment_time VARCHAR(20) COMMENT '预约时间 HH:mm',
     duration_minutes INT COMMENT '测评时长',
@@ -501,7 +501,7 @@ CREATE TABLE IF NOT EXISTS reward_wishlists (
 -- 4. 更新任务状态枚举(如果需要支持更多状态)
 -- ALTER TABLE tasks MODIFY COLUMN status ENUM('pending', 'completed', 'overdue', 'cancelled', 'parent_pending', 'parent_completed') DEFAULT 'pending';
 
--- ===================== 任务模板套餐功能 =====================
+-- ===================== 任务模板任务模板功能 =====================
 
 -- 成长规划师-家庭关系表
 CREATE TABLE IF NOT EXISTS guide_families (
@@ -520,11 +520,11 @@ CREATE TABLE IF NOT EXISTS guide_families (
     INDEX idx_family_id (family_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
--- 任务模板套餐
+-- 任务模板任务模板
 CREATE TABLE IF NOT EXISTS task_template_packages (
     id BIGINT AUTO_INCREMENT PRIMARY KEY,
     creator_id BIGINT NOT NULL COMMENT '创建者成长规划师ID',
-    name VARCHAR(100) NOT NULL COMMENT '套餐名称',
+    name VARCHAR(100) NOT NULL COMMENT '任务模板名称',
     description TEXT COMMENT '详细介绍',
     cycle_days INT NOT NULL COMMENT '周期天数',
     category VARCHAR(50) COMMENT '分类',
@@ -545,10 +545,10 @@ CREATE TABLE IF NOT EXISTS task_template_packages (
     INDEX idx_is_public (is_public)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
--- 套餐内任务项
+-- 任务模板内任务项
 CREATE TABLE IF NOT EXISTS task_template_items (
     id BIGINT AUTO_INCREMENT PRIMARY KEY,
-    package_id BIGINT NOT NULL COMMENT '所属套餐ID',
+    package_id BIGINT NOT NULL COMMENT '所属任务模板ID',
     task_name VARCHAR(100) NOT NULL,
     description TEXT,
     points INT DEFAULT 0,
@@ -561,7 +561,7 @@ CREATE TABLE IF NOT EXISTS task_template_items (
     INDEX idx_package_id (package_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
--- 套餐应用实例
+-- 任务模板应用实例
 CREATE TABLE IF NOT EXISTS task_plan_instances (
     id BIGINT AUTO_INCREMENT PRIMARY KEY,
     package_id BIGINT NOT NULL,
@@ -595,14 +595,14 @@ CREATE TABLE IF NOT EXISTS task_plan_items (
     INDEX idx_instance_id (instance_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
--- 套餐购买订单
+-- 任务模板购买订单
 CREATE TABLE IF NOT EXISTS package_orders (
     id BIGINT AUTO_INCREMENT PRIMARY KEY,
     order_no VARCHAR(32) UNIQUE NOT NULL,
     user_id BIGINT NOT NULL COMMENT '购买者用户ID',
     family_id BIGINT NOT NULL COMMENT '家庭ID',
-    package_id BIGINT NOT NULL COMMENT '套餐ID',
-    package_name VARCHAR(100) COMMENT '套餐名称',
+    package_id BIGINT NOT NULL COMMENT '任务模板ID',
+    package_name VARCHAR(100) COMMENT '任务模板名称',
     price INT NOT NULL COMMENT '支付金额(分)',
     platform_fee INT DEFAULT 0 COMMENT '平台服务费(分)',
     user_coupon_id BIGINT COMMENT '使用的用户优惠券ID',
@@ -856,10 +856,10 @@ CREATE TABLE IF NOT EXISTS assessment_orders (
     user_id BIGINT NOT NULL COMMENT '用户ID',
     child_id BIGINT COMMENT '孩子ID',
     guide_id BIGINT NOT NULL COMMENT '成长规划师ID',
-    package_id BIGINT NOT NULL COMMENT '套餐ID',
+    package_id BIGINT NOT NULL COMMENT '任务模板ID',
     appointment_id BIGINT COMMENT '关联预约ID',
     guide_name VARCHAR(50) COMMENT '规划师名称',
-    package_name VARCHAR(100) COMMENT '套餐名称',
+    package_name VARCHAR(100) COMMENT '任务模板名称',
     total_price BIGINT DEFAULT 0 COMMENT '总价(分)',
     discount_amount BIGINT DEFAULT 0 COMMENT '优惠金额(分)',
     actual_price BIGINT DEFAULT 0 COMMENT '实付金额(分)',
@@ -885,7 +885,7 @@ CREATE TABLE IF NOT EXISTS guide_applications (
     type VARCHAR(20) NOT NULL DEFAULT 'new_apply' COMMENT '申请类型: new_apply-新注册, upgrade-升级',
     target_level VARCHAR(20) NOT NULL COMMENT '目标等级: junior-初级, intermediate-中级, senior-高级',
     current_level VARCHAR(20) DEFAULT NULL COMMENT '当前等级(升级时填写)',
-    package_id BIGINT COMMENT '申请的套餐ID',
+    package_id BIGINT COMMENT '申请的任务模板ID',
     payment_proof VARCHAR(500) COMMENT '付款凭证URL',
     payment_amount INT COMMENT '付款金额(分)',
     address VARCHAR(500) COMMENT '地址',
@@ -1333,7 +1333,7 @@ CREATE TABLE IF NOT EXISTS service_contents (
     updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务内容表';
 
--- 套餐模板表
+-- 任务模板模板表
 CREATE TABLE IF NOT EXISTS guide_package_templates (
     id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
     name VARCHAR(100) NOT NULL COMMENT '模板名称',
@@ -1344,18 +1344,18 @@ CREATE TABLE IF NOT EXISTS guide_package_templates (
     status VARCHAR(20) DEFAULT 'ACTIVE' COMMENT '状态: ACTIVE/DISABLED',
     created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='套餐模板表';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='任务模板模板表';
 
--- 套餐模板服务项表
+-- 任务模板模板服务项表
 CREATE TABLE IF NOT EXISTS package_template_services (
     id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
     template_id BIGINT NOT NULL COMMENT '关联模板',
     content_id BIGINT NOT NULL COMMENT '关联服务内容',
     quantity INT DEFAULT 1 COMMENT '数量',
     unit VARCHAR(20) COMMENT '单位'
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='套餐模板服务项表';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='任务模板模板服务项表';
 
--- 成长规划师套餐
+-- 成长规划师任务模板
 CREATE TABLE IF NOT EXISTS guide_packages (
     id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
     guide_id BIGINT COMMENT '成长规划师ID',
@@ -1363,28 +1363,28 @@ CREATE TABLE IF NOT EXISTS guide_packages (
     commission_rate INT COMMENT '佣金比例(基点,1000=10%)',
     teacher_id BIGINT COMMENT '成长规划师ID(旧字段)',
     template_id BIGINT COMMENT '关联模板(旧字段)',
-    name VARCHAR(100) NOT NULL COMMENT '套餐名称',
-    level VARCHAR(20) COMMENT '套餐等级',
+    name VARCHAR(100) NOT NULL COMMENT '任务模板名称',
+    level VARCHAR(20) COMMENT '任务模板等级',
     price INT NOT NULL COMMENT '销售价格(分)',
     validity_months INT COMMENT '有效期(月)',
     validity_days INT DEFAULT 0 COMMENT '有效期天数',
-    description TEXT COMMENT '套餐说明',
+    description TEXT COMMENT '任务模板说明',
     status VARCHAR(20) DEFAULT 'DRAFT' COMMENT '状态: DRAFT/PUBLISHED/PAUSED',
     sort_order INT DEFAULT 0 COMMENT '排序',
     sales_count INT DEFAULT 0 COMMENT '销量',
     share_code VARCHAR(50) COMMENT '分享码',
     created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='成长规划师套餐表';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='成长规划师任务模板表';
 
--- 成长规划师套餐服务项表
+-- 成长规划师任务模板服务项表
 CREATE TABLE IF NOT EXISTS guide_package_services (
     id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
-    package_id BIGINT NOT NULL COMMENT '关联套餐',
+    package_id BIGINT NOT NULL COMMENT '关联任务模板',
     content_id BIGINT NOT NULL COMMENT '关联服务内容',
     quantity INT DEFAULT 1 COMMENT '数量',
     unit VARCHAR(20) COMMENT '单位'
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='成长规划师套餐服务项表';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='成长规划师任务模板服务项表';
 
 -- 成长规划师订单表
 CREATE TABLE IF NOT EXISTS guide_orders (
@@ -1392,7 +1392,7 @@ CREATE TABLE IF NOT EXISTS guide_orders (
     order_no VARCHAR(50) NOT NULL COMMENT '订单号',
     teacher_id BIGINT NOT NULL COMMENT '成长规划师ID',
     family_id BIGINT NOT NULL COMMENT '家庭ID',
-    package_id BIGINT NOT NULL COMMENT '套餐ID',
+    package_id BIGINT NOT NULL COMMENT '任务模板ID',
     amount INT NOT NULL COMMENT '金额(分)',
     status VARCHAR(20) DEFAULT 'PENDING' COMMENT '状态: PENDING/PAID/COMPLETED/REFUNDED',
     pay_time DATETIME COMMENT '支付时间',
@@ -2432,7 +2432,7 @@ CREATE TABLE IF NOT EXISTS product_ppoint (
 CREATE TABLE IF NOT EXISTS assessment_products (
     id BIGINT AUTO_INCREMENT PRIMARY KEY,
     product_id BIGINT NOT NULL COMMENT '关联products表',
-    assessment_type VARCHAR(20) NOT NULL COMMENT 'single=单包, bundle=套餐',
+    assessment_type VARCHAR(20) NOT NULL COMMENT 'single=单包, bundle=任务模板',
     total_sessions INT NOT NULL DEFAULT 1 COMMENT '包含测评次数',
     validity_days INT NOT NULL DEFAULT 365 COMMENT '有效期(天)',
     guide_scope VARCHAR(50) DEFAULT 'all' COMMENT '规划师范围: all/assigned/auto',
@@ -3904,3 +3904,68 @@ CREATE TABLE IF NOT EXISTS rebate_commission_config (
     created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
     updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='佣金返利配置';
+
+-- DAN测评服务闭环表
+
+CREATE TABLE IF NOT EXISTS `dan_assessment_executions` (
+    `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
+    `assessment_execution_id` BIGINT NOT NULL COMMENT '执行记录ID',
+    `assessment_order_id` BIGINT NOT NULL COMMENT '订单ID',
+    `child_id` BIGINT NOT NULL COMMENT '孩子ID',
+    `family_id` BIGINT NOT NULL COMMENT '家庭ID',
+    `quota_id` BIGINT COMMENT '额度ID',
+    `assessor_id` BIGINT NOT NULL COMMENT '测评师userId',
+    `assessor_status` ENUM('pending','completed','rejected') DEFAULT 'pending' COMMENT '测评师状态',
+    `assessor_completed_at` DATETIME COMMENT '测评师完成时间',
+    `assessor_notes` VARCHAR(200) COMMENT '测评摘要/服务备注',
+    `planner_id` BIGINT COMMENT '规划师userId',
+    `planner_status` ENUM('pending','completed','rejected') DEFAULT 'pending' COMMENT '规划师状态',
+    `planner_completed_at` DATETIME COMMENT '规划师完成时间',
+    `planner_notes` VARCHAR(200) COMMENT '规划服务备注',
+    `user_confirmed` TINYINT(1) DEFAULT 0 COMMENT '用户确认:0未确认,1已确认',
+    `user_confirmed_at` DATETIME COMMENT '用户确认时间',
+    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
+    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    KEY `idx_assessment_execution_id` (`assessment_execution_id`),
+    KEY `idx_assessment_order_id` (`assessment_order_id`),
+    KEY `idx_assessor_id` (`assessor_id`),
+    KEY `idx_planner_id` (`planner_id`),
+    KEY `idx_child_id` (`child_id`),
+    KEY `idx_family_id` (`family_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DAN测评服务执行记录';
+
+CREATE TABLE IF NOT EXISTS `service_ratings` (
+    `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
+    `execution_id` BIGINT NOT NULL COMMENT '执行记录ID',
+    `assessment_order_id` BIGINT NOT NULL COMMENT '订单ID',
+    `user_id` BIGINT NOT NULL COMMENT '评分用户ID',
+    `assessor_id` BIGINT NOT NULL COMMENT '测评师userId',
+    `assessor_rating` TINYINT DEFAULT 0 COMMENT '测评师评分 1-5',
+    `assessor_comment` VARCHAR(500) COMMENT '评价内容',
+    `planner_id` BIGINT COMMENT '规划师userId',
+    `planner_rating` TINYINT COMMENT '规划师评分 1-5',
+    `planner_comment` VARCHAR(500) COMMENT '评价内容',
+    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
+    UNIQUE KEY `uniq_execution_user` (`execution_id`, `user_id`),
+    KEY `idx_assessor_id` (`assessor_id`),
+    KEY `idx_planner_id` (`planner_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务评分记录';
+
+CREATE TABLE IF NOT EXISTS `service_settlements` (
+    `id` BIGINT AUTO_INCREMENT PRIMARY KEY,
+    `execution_id` BIGINT NOT NULL COMMENT '执行记录ID',
+    `assessment_order_id` BIGINT NOT NULL COMMENT '订单ID',
+    `provider_id` BIGINT NOT NULL COMMENT '服务提供方userId',
+    `provider_type` ENUM('assessor','planner') NOT NULL COMMENT '服务方类型',
+    `service_fee` BIGINT DEFAULT 0 COMMENT '服务费用(分)',
+    `commission_rate` INT COMMENT '佣金比例(bps)',
+    `commission_amount` BIGINT DEFAULT 0 COMMENT '结算金额(分)',
+    `status` ENUM('pending','settled','failed') DEFAULT 'pending' COMMENT '结算状态',
+    `settled_at` DATETIME COMMENT '结算时间',
+    `transaction_id` VARCHAR(100) COMMENT '转账交易ID',
+    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
+    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    KEY `idx_execution_id` (`execution_id`),
+    KEY `idx_provider_id` (`provider_id`),
+    KEY `idx_status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务结算记录';

+ 1 - 1
cfc-backend/src/test/java/com/etotem/cfc/controller/GuideOrderControllerTest.java

@@ -33,7 +33,7 @@ public class GuideOrderControllerTest {
         order.setUserId(100L);
         order.setFamilyId(200L);
         order.setPackageId(300L);
-        order.setPackageName("测试套餐");
+        order.setPackageName("测试任务模板");
         order.setPrice(19900);
         order.setGuideId(guideId);
         order.setStatus(status);

+ 1 - 1
cfc-backend/src/test/java/com/etotem/cfc/controller/GuideRolePermissionTest.java

@@ -27,7 +27,7 @@ import static org.mockito.Mockito.*;
  * 成长规划师 (teacher/planner) 角色权限边界测试
  *
  * 角色说明: role = 'teacher', vendorType = 'planner'
- * 规划师核心能力: 绑定家庭/下发任务/审核任务/管理套餐/邀请码/测评配置/订单查看
+ * 规划师核心能力: 绑定家庭/下发任务/审核任务/管理任务模板/邀请码/测评配置/订单查看
  * 权限边界: 非 teacher 角色调用指导师接口应被拒绝
  *
  * 覆盖控制器:

+ 5 - 5
cfc-backend/src/test/java/com/etotem/cfc/controller/PaymentControllerTest.java

@@ -42,7 +42,7 @@ public class PaymentControllerTest {
     public void createWechatPayOrder_Success() {
         Map<String, Object> params = new HashMap<>();
         params.put("orderNo", "ORD20260622001");
-        params.put("description", "DAN测评套餐");
+        params.put("description", "DAN测评任务模板");
         params.put("amount", 19800);
 
         Map<String, Object> mockResult = new HashMap<>();
@@ -55,7 +55,7 @@ public class PaymentControllerTest {
         mockResult.put("signType", "MD5");
         mockResult.put("paySign", "mock_sign");
 
-        when(paymentService.createWechatPayOrder("ORD20260622001", "DAN测评套餐", 19800))
+        when(paymentService.createWechatPayOrder("ORD20260622001", "DAN测评任务模板", 19800))
                 .thenReturn(mockResult);
 
         Result<Map<String, Object>> result = controller.createWechatPayOrder(params);
@@ -71,7 +71,7 @@ public class PaymentControllerTest {
     public void createWechatPayOrder_ReturnMapNotNull() {
         Map<String, Object> params = new HashMap<>();
         params.put("orderNo", "ORD20260622002");
-        params.put("description", "年度套餐");
+        params.put("description", "年度任务模板");
         params.put("amount", 36500);
 
         when(paymentService.createWechatPayOrder(anyString(), anyString(), anyInt()))
@@ -277,10 +277,10 @@ public class PaymentControllerTest {
     public void createWechatPayOrder_AmountIsZero() {
         Map<String, Object> params = new HashMap<>();
         params.put("orderNo", "ORD000");
-        params.put("description", "免费套餐");
+        params.put("description", "免费任务模板");
         params.put("amount", 0);
 
-        when(paymentService.createWechatPayOrder("ORD000", "免费套餐", 0))
+        when(paymentService.createWechatPayOrder("ORD000", "免费任务模板", 0))
                 .thenReturn(new HashMap<String, Object>() {{
                     put("orderNo", "ORD000");
                     put("prepayId", null);

+ 7 - 7
cfc-backend/src/test/java/com/etotem/cfc/controller/ProductControllerTest.java

@@ -41,8 +41,8 @@ public class ProductControllerTest {
 
         Map<String, Object> mockResult = new LinkedHashMap<>();
         List<ProductDTO> products = Arrays.asList(
-                createProductDTO(1L, "DAN测评套餐", 19800, "published"),
-                createProductDTO(2L, "年度咨询套餐", 36500, "published")
+                createProductDTO(1L, "DAN测评任务模板", 19800, "published"),
+                createProductDTO(2L, "年度咨询任务模板", 36500, "published")
         );
         mockResult.put("records", products);
         mockResult.put("total", 2L);
@@ -70,7 +70,7 @@ public class ProductControllerTest {
 
         Map<String, Object> mockResult = new LinkedHashMap<>();
         mockResult.put("records", Collections.singletonList(
-                createProductDTO(3L, "体检套餐", 50000, "published")
+                createProductDTO(3L, "体检任务模板", 50000, "published")
         ));
         mockResult.put("total", 1L);
         mockResult.put("page", 1);
@@ -96,7 +96,7 @@ public class ProductControllerTest {
 
         Map<String, Object> mockResult = new LinkedHashMap<>();
         mockResult.put("records", Collections.singletonList(
-                createProductDTO(1L, "DAN测评套餐", 19800, "published")
+                createProductDTO(1L, "DAN测评任务模板", 19800, "published")
         ));
         mockResult.put("total", 1L);
 
@@ -140,7 +140,7 @@ public class ProductControllerTest {
         Map<String, Object> params = new HashMap<>();
         params.put("id", 1L);
 
-        ProductDTO mockProduct = createProductDTO(1L, "DAN测评套餐", 19800, "published");
+        ProductDTO mockProduct = createProductDTO(1L, "DAN测评任务模板", 19800, "published");
         mockProduct.setDescription("全面评估孩子发展水平");
         mockProduct.setStock(100);
         mockProduct.setSalesCount(58);
@@ -151,7 +151,7 @@ public class ProductControllerTest {
 
         assertEquals(200, result.getCode());
         assertNotNull(result.getData());
-        assertEquals("DAN测评套餐", result.getData().getName());
+        assertEquals("DAN测评任务模板", result.getData().getName());
         assertEquals(19800, result.getData().getPrice());
     }
 
@@ -172,7 +172,7 @@ public class ProductControllerTest {
         Map<String, Object> params = new HashMap<>();
         params.put("id", 10L);
 
-        ProductDTO mockProduct = createProductDTO(10L, "待发布套餐", 9800, "draft");
+        ProductDTO mockProduct = createProductDTO(10L, "待发布任务模板", 9800, "draft");
         mockProduct.setStock(0);
 
         when(productService.detail(10L)).thenReturn(Result.success(mockProduct));

+ 2 - 2
cfc-backend/src/test/java/com/etotem/cfc/controller/ProductOrderControllerTest.java

@@ -243,7 +243,7 @@ public class ProductOrderControllerTest {
         params.put("orderNo", "PRD20260622001");
 
         ProductOrderDTO order = createOrder(1L, "PRD20260622001", 1L, "paid");
-        order.setProductName("DAN测评套餐");
+        order.setProductName("DAN测评任务模板");
 
         when(orderService.detail("PRD20260622001", 1L))
                 .thenReturn(Result.success(order));
@@ -252,7 +252,7 @@ public class ProductOrderControllerTest {
 
         assertEquals(200, result.getCode());
         assertEquals("PRD20260622001", result.getData().getOrderNo());
-        assertEquals("DAN测评套餐", result.getData().getProductName());
+        assertEquals("DAN测评任务模板", result.getData().getProductName());
     }
 
     @Test

+ 1 - 1
cfc-backend/src/test/java/com/etotem/cfc/integration/GrowthRecordSyncFlowTest.java

@@ -138,7 +138,7 @@ public class GrowthRecordSyncFlowTest {
      * 触发条件:勾选"同时购买测评"选项
      */
     @Test
-    @DisplayName("[场景2] 创建档案并购买测评套餐 - 期望档案和订单同时创建")
+    @DisplayName("[场景2] 创建档案并购买测评任务模板 - 期望档案和订单同时创建")
     void parentCreatesRecordWithOrder_Success() {
         // === Given:家长填写档案信息并选择同时购买测评 ===
         Map<String, Object> request = new HashMap<>();

+ 3 - 3
cfc-backend/src/test/java/com/etotem/cfc/integration/GuideModuleIntegrationTest.java

@@ -14,7 +14,7 @@ import static org.junit.jupiter.api.Assertions.*;
 
 /**
  * 成长规划师模块集成测试
- * 覆盖场景:成长规划师创建套餐 -> 家庭购买 -> 订单生成 -> 佣金计算
+ * 覆盖场景:成长规划师创建任务模板 -> 家庭购买 -> 订单生成 -> 佣金计算
  */
 @SpringBootTest
 public class GuideModuleIntegrationTest {
@@ -118,7 +118,7 @@ public class GuideModuleIntegrationTest {
 
     @Test
     public void testTemplatePriceValidation() {
-        // 测试套餐模板价格逻辑
+        // 测试任务模板模板价格逻辑
         GuidePackageTemplate template = new GuidePackageTemplate();
         template.setName("测试模板");
         template.setValidityMonths(3);
@@ -137,7 +137,7 @@ public class GuideModuleIntegrationTest {
 
         int invalidPrice = 20000;
         assertFalse(invalidPrice >= template.getMinPrice());
-        System.out.println("套餐模板价格验证测试通过");
+        System.out.println("任务模板模板价格验证测试通过");
     }
 
     @Test

+ 2 - 2
cfc-backend/src/test/java/com/etotem/cfc/service/GuidePackageServiceTest.java

@@ -33,7 +33,7 @@ public class GuidePackageServiceTest {
         gp.setId(id);
         gp.setGuideId(guideId);
         gp.setPackageId(packageId);
-        gp.setName("测试套餐");
+        gp.setName("测试任务模板");
         gp.setPrice(19900);
         gp.setCommissionRate(10);
         gp.setStatus(status);
@@ -45,7 +45,7 @@ public class GuidePackageServiceTest {
     private TaskTemplatePackage createTaskPackage(Long id) {
         TaskTemplatePackage tp = new TaskTemplatePackage();
         tp.setId(id);
-        tp.setName("模板套餐");
+        tp.setName("模板任务模板");
         tp.setPrice(29900);
         return tp;
     }

+ 2 - 2
cfc-backend/src/test/java/com/etotem/cfc/service/GuidePackageTemplateServiceTest.java

@@ -36,7 +36,7 @@ public class GuidePackageTemplateServiceTest {
     @Test
     public void testCreateTemplate() {
         GuidePackageTemplate template = new GuidePackageTemplate();
-        template.setName("测试套餐模板");
+        template.setName("测试任务模板模板");
         template.setValidityMonths(6);
         template.setReferencePrice(99900);
         template.setMinPrice(66600);
@@ -45,7 +45,7 @@ public class GuidePackageTemplateServiceTest {
 
         GuidePackageTemplate created = templateService.createTemplate(template);
         assertNotNull(created.getId());
-        assertEquals("测试套餐模板", created.getName());
+        assertEquals("测试任务模板模板", created.getName());
         assertTrue(created.getReferencePrice() > created.getMinPrice());
     }
 

+ 6 - 6
cfc-frontend/pages.json

@@ -246,25 +246,25 @@
         {
           "path": "packages/index",
           "style": {
-            "navigationBarTitleText": "我的套餐"
+            "navigationBarTitleText": "我的任务模板"
           }
         },
         {
           "path": "packages/create",
           "style": {
-            "navigationBarTitleText": "创建套餐"
+            "navigationBarTitleText": "创建任务模板"
           }
         },
         {
           "path": "packages/detail",
           "style": {
-            "navigationBarTitleText": "套餐详情"
+            "navigationBarTitleText": "任务模板详情"
           }
         },
         {
           "path": "packages/share",
           "style": {
-            "navigationBarTitleText": "分享套餐"
+            "navigationBarTitleText": "分享任务模板"
           }
         },
         {
@@ -335,13 +335,13 @@
         {
           "path": "market/index",
           "style": {
-            "navigationBarTitleText": "套餐市场"
+            "navigationBarTitleText": "任务模板市场"
           }
         },
         {
           "path": "market/detail",
           "style": {
-            "navigationBarTitleText": "套餐详情"
+            "navigationBarTitleText": "任务模板详情"
           }
         },
         {

+ 1 - 1
cfc-frontend/pages/assessment/order.vue

@@ -9,7 +9,7 @@
     <view class="section">
       <view class="section-title">订单详情</view>
       <view class="info-row">
-        <text class="info-label">套餐名称</text>
+        <text class="info-label">任务模板名称</text>
         <text class="info-value">{{ packageName }}</text>
       </view>
       <view class="info-row">

+ 12 - 12
cfc-frontend/pages/assessment/purchase.vue

@@ -1,8 +1,8 @@
 <template>
   <view class="container">
     <view class="header">
-      <text class="title">选择测评套餐</text>
-      <text class="subtitle">选择适合孩子的测评套餐</text>
+      <text class="title">选择测评任务模板</text>
+      <text class="subtitle">选择适合孩子的测评任务模板</text>
     </view>
 
     <!-- 成长规划师选择 -->
@@ -26,9 +26,9 @@
       </view>
     </view>
 
-    <!-- 套餐列表 -->
+    <!-- 任务模板列表 -->
     <view class="section">
-      <view class="section-title">测评套餐</view>
+      <view class="section-title">测评任务模板</view>
       <view class="package-list">
         <view 
           class="package-item" 
@@ -61,7 +61,7 @@
       <view class="section-title">费用明细</view>
       <view class="price-breakdown">
         <view class="price-row">
-          <text class="price-label">套餐价格</text>
+          <text class="price-label">任务模板价格</text>
           <text class="price-value">{{ formatPriceWithSymbol(selectedPackage.price) }}</text>
         </view>
         <view class="price-row" v-if="selectedGuideId">
@@ -122,12 +122,12 @@ export default {
   methods: {
     async loadPackages() {
       try {
-        // TODO: 从后端获取套餐列表
+        // TODO: 从后端获取任务模板列表
         // 这里简化处理,使用模拟数据
         this.packages = [
           {
             id: 1,
-            name: '基础测评套餐',
+            name: '基础测评任务模板',
             description: '包含注意力、专注力、记忆力三项基础测评',
             price: 299,
             originalPrice: 399,
@@ -135,7 +135,7 @@ export default {
           },
           {
             id: 2,
-            name: '全面测评套餐',
+            name: '全面测评任务模板',
             description: '包含五项全面测评,提供详细分析报告',
             price: 499,
             originalPrice: 699,
@@ -143,8 +143,8 @@ export default {
           },
           {
             id: 3,
-            name: '高级测评套餐',
-            name: '高级测评套餐',
+            name: '高级测评任务模板',
+            name: '高级测评任务模板',
             description: '包含所有测评项目,提供专家一对一解读',
             price: 799,
             originalPrice: 999,
@@ -152,7 +152,7 @@ export default {
           }
         ]
       } catch (e) {
-        console.error('获取套餐列表失败', e)
+        console.error('获取任务模板列表失败', e)
       }
     },
 
@@ -243,7 +243,7 @@ export default {
 
     async submit() {
       if (!this.selectedPackageId) {
-        uni.showToast({ title: '请选择套餐', icon: 'none' })
+        uni.showToast({ title: '请选择任务模板', icon: 'none' })
         return
       }
 

+ 2 - 2
cfc-frontend/pages/assessment/quota.vue

@@ -2,7 +2,7 @@
   <view class="container">
     <view class="header">
       <text class="title">我的测评额度</text>
-      <text class="subtitle">购买测评套餐后获得可使用次数</text>
+      <text class="subtitle">购买测评任务模板后获得可使用次数</text>
     </view>
 
     <view class="quota-list" v-if="quotas.length > 0">
@@ -41,7 +41,7 @@
     <view class="empty" v-else>
       <text class="empty-icon">📋</text>
       <text class="empty-text">暂无可用的测评额度</text>
-      <button class="btn-buy" @click="goBuy">去购买测评套餐</button>
+      <button class="btn-buy" @click="goBuy">去购买任务模板</button>
     </view>
   </view>
 </template>

+ 3 - 3
cfc-frontend/pages/guide/packages/create.vue

@@ -2,13 +2,13 @@
   <view class="container">
     <view class="form">
       <view class="form-item">
-        <text class="label">套餐名称</text>
+        <text class="label">任务模板名称</text>
         <input class="input" v-model="form.name" placeholder="如:21天养成学习习惯" />
       </view>
 
       <view class="form-item">
         <text class="label">详细介绍</text>
-        <textarea class="textarea" v-model="form.description" placeholder="描述套餐的内容和目标" />
+        <textarea class="textarea" v-model="form.description" placeholder="描述任务模板的内容和目标" />
       </view>
 
       <view class="form-item">
@@ -84,7 +84,7 @@ export default {
     },
     async submit() {
       if (!this.form.name) {
-        uni.showToast({ title: '请输入套餐名称', icon: 'none' })
+        uni.showToast({ title: '请输入任务模板名称', icon: 'none' })
         return
       }
       if (!this.form.cycleDays) {

+ 1 - 1
cfc-frontend/pages/guide/packages/detail.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="container">
-    <!-- 套餐信息 -->
+    <!-- 任务模板信息 -->
     <view class="package-info">
       <view class="info-header">
         <text class="name">{{ pkg.name }}</text>

+ 4 - 4
cfc-frontend/pages/guide/packages/index.vue

@@ -2,11 +2,11 @@
   <view class="container">
     <!-- 头部 -->
     <view class="header">
-      <text class="title">我的套餐</text>
-      <button class="btn-create" @click="goToCreate">创建套餐</button>
+      <text class="title">我的任务模板</text>
+      <button class="btn-create" @click="goToCreate">创建任务模板</button>
     </view>
 
-    <!-- 套餐列表 -->
+    <!-- 任务模板列表 -->
     <view class="package-list" v-if="packages.length > 0">
       <view 
         class="package-card" 
@@ -40,7 +40,7 @@
 
     <!-- 空状态 -->
     <view class="empty" v-else>
-      <text class="empty-text">暂无套餐,快去创建一个吧</text>
+      <text class="empty-text">暂无任务模板,快去创建一个吧</text>
     </view>
   </view>
 </template>

+ 3 - 3
cfc-frontend/pages/guide/packages/share.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="container">
-    <!-- 套餐信息卡片 -->
+    <!-- 任务模板信息卡片 -->
     <view class="package-card">
       <image class="cover" :src="pkg.coverImage || '/static/default-cover.png'" mode="aspectFill" />
       <view class="package-info">
@@ -91,7 +91,7 @@ export default {
       // 标题
       ctx.setFillStyle('#333333')
       ctx.setFontSize(32)
-      ctx.fillText(this.pkg.name || '套餐名称', 30, 350)
+      ctx.fillText(this.pkg.name || '任务模板名称', 30, 350)
       
       // 描述
       ctx.setFillStyle('#666666')
@@ -118,7 +118,7 @@ export default {
       // 提示文字
       ctx.setFillStyle('#999999')
       ctx.setFontSize(20)
-      ctx.fillText('微信扫码或输入分享码查看套餐', 30, 640)
+      ctx.fillText('微信扫码或输入分享码查看任务模板', 30, 640)
       
       // 品牌标识
       ctx.setFillStyle('#cccccc')

+ 3 - 3
cfc-frontend/pages/membership/upgrade.vue

@@ -31,7 +31,7 @@
           <text class="upgrade-title">家庭会员</text>
           <text class="upgrade-subtitle">FAMILY</text>
         </view>
-        <!-- 套餐选择 -->
+        <!-- 档位选择 -->
         <view class="period-tabs">
           <view 
             class="period-tab" 
@@ -71,7 +71,7 @@
           <text class="upgrade-title">续费会员</text>
           <text class="upgrade-subtitle">保持权益不中断</text>
         </view>
-        <!-- 套餐选择 -->
+        <!-- 档位选择 -->
         <view class="period-tabs">
           <view 
             class="period-tab" 
@@ -784,7 +784,7 @@ export default {
   border: none;
 }
 
-/* ===== 套餐选择 ===== */
+/* ===== 档位选择 ===== */
 .period-tabs {
   display: flex;
   justify-content: space-between;

+ 2 - 2
cfc-frontend/pages/parent/market/detail.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="container">
-    <!-- 套餐信息 -->
+    <!-- 任务模板信息 -->
     <view class="package-header">
       <image class="cover" :src="pkg.coverImage || '/static/default-cover.png'" mode="aspectFill" />
       <view class="header-content">
@@ -15,7 +15,7 @@
 
     <!-- 描述 -->
     <view class="section">
-      <text class="section-title">套餐介绍</text>
+      <text class="section-title">任务模板介绍</text>
       <text class="description">{{ pkg.description || '暂无介绍' }}</text>
     </view>
 

+ 3 - 3
cfc-frontend/pages/parent/market/index.vue

@@ -3,7 +3,7 @@
     <!-- 搜索/分类 -->
     <view class="filter-bar">
       <view class="search-box">
-        <input class="search-input" v-model="keyword" placeholder="搜索套餐" @confirm="search" />
+        <input class="search-input" v-model="keyword" placeholder="搜索任务模板" @confirm="search" />
       </view>
       <view class="categories">
         <text 
@@ -21,7 +21,7 @@
       </view>
     </view>
 
-    <!-- 套餐列表 -->
+    <!-- 任务模板列表 -->
     <view class="package-list">
       <view 
         class="package-card" 
@@ -44,7 +44,7 @@
 
     <!-- 空状态 -->
     <view class="empty" v-if="packages.length === 0">
-      <text>暂无套餐</text>
+      <text>暂无任务模板</text>
     </view>
   </view>
 </template>

+ 1 - 1
cfc-frontend/pages/parent/plans/index.vue

@@ -31,7 +31,7 @@
 
     <!-- 空状态 -->
     <view class="empty" v-else>
-      <text class="empty-text">暂无计划,快去应用套餐吧</text>
+      <text class="empty-text">暂无计划,快去应用任务模板吧</text>
       <button class="btn-go" @click="goToMarket">去市场</button>
     </view>
   </view>

+ 1 - 1
cfc-frontend/pages/promotion/commission.vue

@@ -129,7 +129,7 @@ export default {
         membership: '会员',
         product: '商品',
         assessment: '测评',
-        package: '套餐'
+        package: '任务模板'
       }
       return (typeMap[item.orderType] || item.orderType) + '订单 #' + item.orderId
     },

+ 2 - 2
cfc-frontend/pages/teacher/teacher-home.vue

@@ -87,7 +87,7 @@
           </view>
           <view class="menu-item" @click="goTo('packages')">
             <view class="menu-icon gold">📦</view>
-            <text class="menu-label">套餐管理</text>
+            <text class="menu-label">任务模板管理</text>
           </view>
           <view class="menu-item" @click="goTo('team')">
             <view class="menu-icon purple">👥</view>
@@ -116,7 +116,7 @@
           </view>
           <view class="menu-item">
             <view class="menu-icon gold disabled-icon">📦</view>
-            <text class="menu-label disabled-label">套餐管理</text>
+            <text class="menu-label disabled-label">任务模板管理</text>
           </view>
           <view class="menu-item">
             <view class="menu-icon purple disabled-icon">👥</view>

+ 10 - 10
cfc-frontend/utils/api.js

@@ -447,7 +447,7 @@ export const cancelWish = (id, reason) => {
 }
 
 // =============================================
-// 成长规划师/套餐模块
+// 成长规划师/任务模板模块
 // =============================================
 // 生成绑定邀请
 export const generateBindInvite = () => {
@@ -469,22 +469,22 @@ export const unbindFamily = (id) => {
   return request(`/api/guide/bind/${id}`, 'DELETE')
 }
 
-// 创建套餐
+// 创建任务模板
 export const createPackage = (data) => {
   return request('/api/packages', 'POST', data)
 }
 
-// 更新套餐
+// 更新任务模板
 export const updatePackage = (id, data) => {
   return request(`/api/packages/${id}`, 'PUT', data)
 }
 
-// 获取套餐详情
+// 获取任务模板详情
 export const getPackage = (id) => {
   return request(`/api/packages/${id}`, 'POST')
 }
 
-// 获取我的套餐列表
+// 获取我的任务模板列表
 export const getMyPackages = () => {
   return request('/api/packages', 'POST')
 }
@@ -514,22 +514,22 @@ export const deletePackageItem = (itemId) => {
   return request(`/api/packages/items/${itemId}`, 'DELETE')
 }
 
-// 获取套餐任务项
+// 获取任务模板任务项
 export const getPackageItems = (packageId) => {
   return request(`/api/packages/${packageId}/items`, 'POST')
 }
 
-// 获取公开套餐列表
+// 获取公开任务模板列表
 export const getPublicPackages = (category) => {
   return request('/api/market/packages', 'POST', { category })
 }
 
-// 通过分享码获取套餐
+// 通过分享码获取任务模板
 export const getPackageByShareCode = (code) => {
   return request(`/api/market/share/${code}`, 'POST')
 }
 
-// 购买并应用套餐
+// 购买并应用任务模板
 export const purchasePackage = (packageId, data) => {
   return request(`/api/market/packages/${packageId}/purchase`, 'POST', data)
 }
@@ -673,7 +673,7 @@ export const deleteActivity = (activityId) => {
   return request('/api/guide/activities/delete', 'POST', { activityId })
 }
 
-// 添加成长规划师套餐
+// 添加成长规划师任务模板
 export const addGuidePackage = (guideId, packageId, price, commissionRate) => {
   return request('/api/guide/package/add', 'POST', { guideId, packageId, price, commissionRate })
 }

+ 1 - 1
cfc-web/src/__tests__/api/guide.test.js

@@ -114,7 +114,7 @@ describe('guide API', () => {
 
   test('createPackage sends POST with data', async () => {
     mock.onPost('/api/admin/guide/packages').reply(200, { code: 200, data: { id: 1 } })
-    const res = await createPackage({ name: '套餐A' })
+    const res = await createPackage({ name: '任务模板A' })
     expect(res.data.id).toBe(1)
   })
 

+ 1 - 1
cfc-web/src/__tests__/api/guidePackage.test.js

@@ -44,7 +44,7 @@ describe('guidePackage API', () => {
 
   test('createPackage sends POST with data', async () => {
     mock.onPost('/api/packages/create').reply(200, { code: 200, data: { id: 1 } })
-    const res = await createPackage({ name: '套餐' })
+    const res = await createPackage({ name: '任务模板' })
     expect(res.data.id).toBe(1)
   })
 

+ 5 - 5
cfc-web/src/api/guidePackage.js

@@ -1,6 +1,6 @@
 import request from '@/utils/request'
 
-// 获取我的套餐列表
+// 获取我的任务模板列表
 export function getMyPackages() {
   return request({
     url: '/api/packages/my',
@@ -8,7 +8,7 @@ export function getMyPackages() {
   })
 }
 
-// 获取套餐详情
+// 获取任务模板详情
 export function getGuidePackage(id) {
   return request({
     url: `/api/packages/${id}`,
@@ -16,7 +16,7 @@ export function getGuidePackage(id) {
   })
 }
 
-// 获取套餐任务项
+// 获取任务模板任务项
 export function getGuidePackageItems(packageId) {
   return request({
     url: `/api/packages/${packageId}/item-list`,
@@ -24,7 +24,7 @@ export function getGuidePackageItems(packageId) {
   })
 }
 
-// 创建套餐
+// 创建任务模板
 export function createPackage(data) {
   return request({
     url: '/api/packages/create',
@@ -33,7 +33,7 @@ export function createPackage(data) {
   })
 }
 
-// 更新套餐
+// 更新任务模板
 export function updatePackage(id, data) {
   return request({
     url: `/api/packages/${id}`,

+ 3 - 3
cfc-web/src/api/package.js

@@ -1,6 +1,6 @@
 import request from '@/utils/request'
 
-// 获取待审核套餐列表
+// 获取待审核任务模板列表
 export function getPendingPackages() {
   return request({
     url: '/api/admin/packages/pending',
@@ -8,7 +8,7 @@ export function getPendingPackages() {
   })
 }
 
-// 获取我的套餐列表
+// 获取我的任务模板列表
 export function getMyPackages() {
   return request({
     url: '/api/packages/my',
@@ -16,7 +16,7 @@ export function getMyPackages() {
   })
 }
 
-// 获取套餐详情
+// 获取任务模板详情
 export function getPackage(id) {
   return request({
     url: `/api/packages/${id}`,

+ 2 - 2
cfc-web/src/router/index.js

@@ -109,7 +109,7 @@ const routes = [
         path: 'guide-packages',
         name: 'GuidePackages',
         component: () => import('@/views/GuidePackages.vue'),
-        meta: { title: '成长规划师套餐', requiresTeacher: true, perm: 'biz:packages' }
+        meta: { title: '成长规划师任务模板', requiresTeacher: true, perm: 'biz:packages' }
       },
       {
         path: 'guide-family-task',
@@ -140,7 +140,7 @@ const routes = [
         path: 'teacher-packages',
         name: 'TeacherPackages',
         component: () => import('@/views/teacher/TeacherPackages.vue'),
-        meta: { title: '套餐管理', requiresTeacher: true, perm: 'biz:packages' }
+        meta: { title: '任务模板管理', requiresTeacher: true, perm: 'biz:packages' }
       },
       {
         path: 'teacher-orders',

+ 2 - 2
cfc-web/src/views/Dashboard.vue

@@ -81,7 +81,7 @@
       </div>
       <div class="stat-info">
         <div class="stat-value">{{ stats.pendingPackageCount }}</div>
-        <div class="stat-label">待审核套餐</div>
+        <div class="stat-label">待审核任务模板</div>
         <div class="stat-trend" :class="stats.pendingPackageCount > 0 ? '' : 'disabled'">
           {{ stats.pendingPackageCount > 0 ? '点击前往审核' : '暂无待审核' }}
         </div>
@@ -278,7 +278,7 @@
           <div class="action-icon action-icon--package">
             <i class="el-icon-goods"></i>
           </div>
-          <div class="action-label">套餐审核</div>
+          <div class="action-label">任务模板审核</div>
         </div>
         <div class="action-card" @click="$router.push('/rewards')">
           <div class="action-icon action-icon--reward">

+ 12 - 12
cfc-web/src/views/GuidePackages.vue

@@ -2,9 +2,9 @@
   <div class="page-container">
     <el-card>
       <div slot="header">
-        <span>套餐管理</span>
+        <span>任务模板管理</span>
         <el-button style="float: right" type="primary" size="small" icon="el-icon-plus" @click="handleCreate">
-          创建套餐
+          创建任务模板
         </el-button>
       </div>
 
@@ -25,11 +25,11 @@
         </el-form-item>
       </el-form>
 
-      <!-- 套餐列表 -->
+      <!-- 任务模板列表 -->
       <div style="overflow:auto;max-height:calc(100vh - 300px);">
 <el-table style="max-height:calc(100vh - 300px);" :data="tableData" border v-loading="loading">
         <el-table-column prop="id" label="ID" width="60"></el-table-column>
-        <el-table-column prop="name" label="套餐名称" min-width="150"></el-table-column>
+        <el-table-column prop="name" label="任务模板名称" min-width="150"></el-table-column>
         <el-table-column prop="cycleDays" label="周期" width="80">
           <template slot-scope="{ row }">{{ row.cycleDays }}天</template>
         </el-table-column>
@@ -74,7 +74,7 @@
     <!-- 编辑弹窗 -->
     <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px" @closed="handleDialogClosed">
       <el-form ref="form" :model="form" :rules="rules" label-width="100px">
-        <el-form-item label="套餐名称" prop="name">
+        <el-form-item label="任务模板名称" prop="name">
           <el-input v-model="form.name" placeholder="如:21天养成学习习惯"></el-input>
         </el-form-item>
         <el-form-item label="周期天数" prop="cycleDays">
@@ -95,7 +95,7 @@
         </el-form-item>
         <el-form-item label="是否公开">
           <el-switch v-model="form.isPublic"></el-switch>
-          <span style="margin-left: 10px; color: #999">公开后将显示在套餐市场</span>
+          <span style="margin-left: 10px; color: #999">公开后将显示在任务模板市场</span>
         </el-form-item>
         <el-form-item label="封面图">
           <el-upload
@@ -179,10 +179,10 @@
     </el-dialog>
 
     <!-- 分享弹窗 -->
-    <el-dialog title="分享套餐" :visible.sync="shareDialogVisible" width="400px">
+    <el-dialog title="分享任务模板" :visible.sync="shareDialogVisible" width="400px">
       <div v-if="currentRow" style="text-align: center">
         <p style="margin-bottom: 20px">分享码: <strong>{{ currentRow.shareCode }}</strong></p>
-        <p style="color: #999; font-size: 12px">家长可通过分享码或链接查看您的套餐</p>
+        <p style="color: #999; font-size: 12px">家长可通过分享码或链接查看您的任务模板</p>
         <el-button type="primary" @click="copyShareCode">复制分享码</el-button>
       </div>
     </el-dialog>
@@ -201,7 +201,7 @@ export default {
       tableData: [],
       searchForm: { status: '' },
       dialogVisible: false,
-      dialogTitle: '创建套餐',
+        dialogTitle: '创建任务模板',
       form: {
         id: null,
         name: '',
@@ -213,7 +213,7 @@ export default {
         description: ''
       },
       rules: {
-        name: [{ required: true, message: '请输入套餐名称', trigger: 'blur' }],
+          name: [{ required: true, message: '请输入任务模板名称', trigger: 'blur' }],
         cycleDays: [{ required: true, message: '请输入周期天数', trigger: 'blur' }]
       },
       itemsDialogVisible: false,
@@ -289,12 +289,12 @@ export default {
         coverImage: '',
         description: ''
       }
-      this.dialogTitle = '创建套餐'
+        this.dialogTitle = '创建任务模板'
       this.dialogVisible = true
     },
     handleEdit(row) {
       this.form = { ...row, isPublic: row.isPublic === 1 }
-      this.dialogTitle = '编辑套餐'
+        this.dialogTitle = '编辑任务模板'
       this.dialogVisible = true
     },
     handleView(row) {

+ 1 - 1
cfc-web/src/views/Layout.vue

@@ -232,7 +232,7 @@ export default {
           ]},
         { title: '业务管理', icon: 'el-icon-s-marketing', perm: 'biz:*',
           children: [
-            { path: '/teacher-packages', label: '套餐管理', icon: 'el-icon-s-goods', perm: 'biz:packages' },
+            { path: '/teacher-packages', label: '任务模板管理', icon: 'el-icon-s-goods', perm: 'biz:packages' },
             { path: '/teacher-orders', label: '订单佣金', icon: 'el-icon-s-order', perm: 'biz:orders' },
           ]},
         { title: '测评咨询', icon: 'el-icon-edit', perm: 'assessment:*',

+ 1 - 1
cfc-web/src/views/TeacherDashboard.vue

@@ -191,7 +191,7 @@
                 <div class="td-family-cell"><i class="el-icon-house"></i> {{ scope.row.familyName }}</div>
               </template>
             </el-table-column>
-            <el-table-column prop="packageName" label="套餐">
+            <el-table-column prop="packageName" label="任务模板">
               <template slot-scope="scope">
                 <el-tag size="small" effect="plain">{{ scope.row.packageName }}</el-tag>
               </template>

+ 2 - 2
cfc-web/src/views/admin/AssessmentProducts.vue

@@ -39,7 +39,7 @@
         <el-table-column label="测评类型" width="90">
           <template slot-scope="{ row }">
             <el-tag :type="row.assessmentType === 'bundle' ? 'warning' : 'primary'" size="mini">
-              {{ row.assessmentType === 'bundle' ? '套餐' : '单包' }}
+              {{ row.assessmentType === 'bundle' ? '组合' : '单包' }}
             </el-tag>
           </template>
         </el-table-column>
@@ -84,7 +84,7 @@
         <el-descriptions-item label="商品ID">{{ detail.id }}</el-descriptions-item>
         <el-descriptions-item label="商品名称">{{ detail.name }}</el-descriptions-item>
         <el-descriptions-item label="商品类型">{{ detail.productType }}</el-descriptions-item>
-        <el-descriptions-item label="测评类型">{{ detail.assessmentType === 'bundle' ? '套餐' : '单包' }}</el-descriptions-item>
+        <el-descriptions-item label="测评类型">{{ detail.assessmentType === 'bundle' ? '组合' : '单包' }}</el-descriptions-item>
         <el-descriptions-item label="测评次数">{{ detail.totalSessions }}</el-descriptions-item>
         <el-descriptions-item label="有效期(天)">{{ detail.validityDays }}</el-descriptions-item>
         <el-descriptions-item label="规划师范围">{{ detail.guideScope }}</el-descriptions-item>

+ 1 - 1
cfc-web/src/views/admin/Dashboard.vue

@@ -96,7 +96,7 @@ export default {
         { label: '孩子总数', value: '-', icon: 'el-icon-s-custom', color: 'cyan' },
         { label: '规划师总数', value: '-', icon: 'el-icon-school', color: 'green' },
         { label: '待审核规划师', value: '-', icon: 'el-icon-time', color: 'red' },
-        { label: '待审核套餐', value: '-', icon: 'el-icon-document', color: 'purple' },
+        { label: '待审核任务模板', value: '-', icon: 'el-icon-document', color: 'purple' },
         { label: '待退款审核', value: '-', icon: 'el-icon-warning', color: 'orange' }
       ],
       revenueCards: [

+ 1 - 1
cfc-web/src/views/admin/ProductEdit.vue

@@ -27,7 +27,7 @@
           <el-form-item label="测评类型">
             <el-select v-model="form.assessmentType" placeholder="请选择测评类型" style="width: 200px;">
               <el-option label="单包" value="single" />
-              <el-option label="套餐" value="bundle" />
+              <el-option label="组合" value="bundle" />
             </el-select>
           </el-form-item>
           <el-row :gutter="20">

+ 2 - 2
cfc-web/src/views/admin/ReviewCenter.vue

@@ -34,7 +34,7 @@
         <el-tab-pane label="管家审核" name="butler">
           <butler-audit ref="butler" />
         </el-tab-pane>
-        <el-tab-pane label="套餐审核" name="package">
+        <el-tab-pane label="任务模板审核" name="package">
           <package-audit ref="package" />
         </el-tab-pane>
         <el-tab-pane label="活动审核" name="activity">
@@ -85,7 +85,7 @@ export default {
         { key: 'guide', label: '规划师审核', icon: '👤', count: 0 },
         { key: 'vendor', label: '服务商审核', icon: '🏪', count: 0 },
         { key: 'butler', label: '管家审核', icon: '🤵', count: 0 },
-        { key: 'package', label: '套餐审核', icon: '📋', count: 0 },
+        { key: 'package', label: '任务模板审核', icon: '📋', count: 0 },
         { key: 'activity', label: '活动审核', icon: '🎯', count: 0 },
         { key: 'activityRegistration', label: '报名审核', icon: '📝', count: 0 },
         { key: 'withdraw', label: '提现审核', icon: '💰', count: 0 },

+ 3 - 3
cfc-web/src/views/teacher/TeacherOrders.vue

@@ -116,7 +116,7 @@
             </div>
           </template>
         </el-table-column>
-        <el-table-column prop="packageName" label="套餐" width="150">
+        <el-table-column prop="packageName" label="任务模板" width="150">
           <template slot-scope="scope">
             <el-tag size="small" effect="plain" type="warning">{{ scope.row.packageName }}</el-tag>
           </template>
@@ -204,9 +204,9 @@
           <span class="detail-value">{{ currentOrder.familyName }}</span>
         </div>
 
-        <el-divider content-position="left">套餐信息</el-divider>
+        <el-divider content-position="left">任务模板信息</el-divider>
         <div class="detail-row">
-          <span class="detail-label">套餐名称</span>
+          <span class="detail-label">任务模板名称</span>
           <span class="detail-value">{{ currentOrder.packageName }}</span>
         </div>
       </div>

+ 18 - 18
cfc-web/src/views/teacher/TeacherPackages.vue

@@ -3,13 +3,13 @@
     <!-- 页面标题区 -->
     <div class="page-header">
       <div class="header-left">
-        <h2 class="page-title">我的套餐</h2>
-        <span class="page-desc">管理您的服务套餐</span>
+        <h2 class="page-title">我的任务模板</h2>
+        <span class="page-desc">管理您的服务任务模板</span>
       </div>
       <div class="header-actions">
-        <el-input v-model="keyword" placeholder="搜索套餐..." prefix-icon="el-icon-search" style="width:200px; margin-right:12px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
+        <el-input v-model="keyword" placeholder="搜索任务模板..." prefix-icon="el-icon-search" style="width:200px; margin-right:12px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
         <el-button type="primary" class="primary-btn" @click="handleCreate">
-          <i class="el-icon-plus"></i> 创建套餐
+          <i class="el-icon-plus"></i> 创建任务模板
         </el-button>
       </div>
     </div>
@@ -23,7 +23,7 @@
           </div>
           <div class="stat-info">
             <div class="stat-value">{{ stats.totalPackages }}</div>
-            <div class="stat-label">在售套餐</div>
+            <div class="stat-label">在售任务模板</div>
           </div>
         </div>
       </el-col>
@@ -56,17 +56,17 @@
           </div>
           <div class="stat-info">
             <div class="stat-value">{{ formatPriceWithSymbol(stats.totalRevenue) }}</div>
-            <div class="stat-label">套餐收入</div>
+            <div class="stat-label">任务模板收入</div>
           </div>
         </div>
       </el-col>
     </el-row>
 
-    <!-- 套餐列表 -->
+    <!-- 任务模板列表 -->
     <el-card class="table-card">
         <div style="overflow:auto;max-height:calc(100vh - 300px);">
         <el-table :data="filteredPackages" stripe style="width: 100%;max-height:calc(100vh - 300px);" v-loading="loading">
-        <el-table-column label="套餐信息" min-width="200">
+        <el-table-column label="任务模板信息" min-width="200">
           <template slot-scope="scope">
             <div class="package-cell">
               <div class="package-icon">
@@ -127,11 +127,11 @@
         </div>
     </el-card>
 
-    <!-- 创建/编辑套餐弹窗 -->
-    <el-dialog :visible.sync="dialogVisible" :title="isEdit ? '编辑套餐' : '创建套餐'" width="560px" class="package-dialog">
+    <!-- 创建/编辑任务模板弹窗 -->
+    <el-dialog :visible.sync="dialogVisible" :title="isEdit ? '编辑任务模板' : '创建任务模板'" width="560px" class="package-dialog">
       <el-form :model="form" label-width="100px" class="package-form">
         <el-form-item label="选择模板">
-          <el-select v-model="form.packageId" placeholder="请选择套餐模板" @change="handleTemplateChange" class="full-width">
+          <el-select v-model="form.packageId" placeholder="请选择任务模板" @change="handleTemplateChange" class="full-width">
             <el-option v-for="t in templates" :key="t.id" :label="t.name" :value="t.id">
               <span style="display: flex; justify-content: space-between">
                 <span>{{ t.name }}</span>
@@ -140,9 +140,9 @@
             </el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="套餐名称">
-          <el-input v-model="form.packageName" placeholder="请输入套餐名称" class="full-width"></el-input>
-        </el-form-item>
+          <el-form-item label="任务模板名称">
+            <el-input v-model="form.packageName" placeholder="请输入任务模板名称" class="full-width"></el-input>
+          </el-form-item>
         <el-form-item label="等级">
           <el-select v-model="form.level" placeholder="选择等级" class="full-width">
             <el-option label="初级" value="junior"></el-option>
@@ -166,9 +166,9 @@
             <i class="el-icon-info"></i> 系统建议最低价: {{ formatPriceWithSymbol(selectedTemplate.minPrice) }}
           </div>
         </el-form-item>
-        <el-form-item label="套餐描述">
-          <el-input type="textarea" v-model="form.description" :rows="3" placeholder="请输入套餐描述" class="full-width"></el-input>
-        </el-form-item>
+          <el-form-item label="任务模板描述">
+            <el-input type="textarea" v-model="form.description" :rows="3" placeholder="请输入任务模板描述" class="full-width"></el-input>
+          </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button @click="dialogVisible = false">取消</el-button>
@@ -314,7 +314,7 @@ export default {
       switch (cmd) {
         case 'duplicate': this.handleDuplicate(row); break
         case 'edit': this.handleEdit(row); break
-        case 'delete': this.$confirm('确认删除该套餐吗?', '提示', { type: 'warning' }).then(() => {}).catch(() => {}); break
+        case           'delete': this.$confirm('确认删除该任务模板吗?', '提示', { type: 'warning' }).then(() => {}).catch(() => {}); break
       }
     },
     async toggleStatus(row) {