数据库

This commit is contained in:
zhangzhe 2026-02-04 10:37:04 +08:00
parent 59932bcf29
commit 1dec197293
2 changed files with 503 additions and 20 deletions

View File

@ -2,27 +2,60 @@
本文档定义了 MiAssessment 项目的开发规范和编码标准,所有开发工作必须遵循这些规范。
## 项目概述
学业邑规划是一个基于多元智能理论的学业规划测评系统,包含微信小程序和后台管理系统。
### 相关文档
- 需求文档: `docs/需求文档.md`
- 数据库设计: `docs/数据库设计文档.md`
- 开发文档: `docs/开发文档.md`
- 题库资料: `docs/题库和结论/`
- UI 设计图: `docs/设计图/`
- UI 切图: `docs/切图/`
## 一、技术栈
| 层级 | 技术 |
|---|---|
|------|------|
| 后端框架 | .NET 10 Web API (C#) |
| 数据库 | SQL Server 2022 |
| ORM | Entity Framework Core |
| 缓存 | Redis |
| 接口风格 | RPC 风格(仅 GET / POST 请求) |
| 前端 | UniApp + Vue 3 + TypeScript |
| 小程序前端 | UniApp + Vue 3 + TypeScript |
| 后台管理前端 | Vue 3 + TypeScript + Vite |
## 二、项目结构
### 整体结构
```
mi-assessment/
├── docs/ # 文档资料
│ ├── 需求文档.md
│ ├── 数据库设计文档.md
│ ├── 开发文档.md
│ ├── 开发规范/ # 详细编码规范
│ ├── 设计图/ # UI 设计图
│ ├── 切图/ # UI 切图资源
│ └── 题库和结论/ # 测评题库与报告模板
├── server/MiAssessment/ # 后端服务
└── uniapp/ # 小程序前端
```
### 后端项目结构
```
server/MiAssessment/src/
├── MiAssessment.Api/ # 小程序 API 接口
├── MiAssessment.Admin/ # 后台管理系统基础模块
├── MiAssessment.Admin.Business/ # 后台业务模块(主要开发区域)
├── MiAssessment.Core/ # 核心业务逻辑
├── MiAssessment.Infrastructure/ # 基础设施
└── MiAssessment.Model/ # 数据模型
├── MiAssessment.Api/ # 小程序 API 接口
├── MiAssessment.Admin/ # 后台管理系统基础模块
│ └── admin-web/ # 后台管理前端 (Vue 3)
├── MiAssessment.Admin.Business/ # 后台业务模块(主要开发区域)
├── MiAssessment.Core/ # 核心业务逻辑
├── MiAssessment.Infrastructure/ # 基础设施
└── MiAssessment.Model/ # 数据模型
```
### Admin.Business 项目结构
@ -45,7 +78,7 @@ MiAssessment.Admin.Business/
### 3.1 数据库命名
| 类型 | 规范 | 示例 |
|---|---|---|
|------|------|------|
| 表名 | snake_case小写下划线 | `users`, `assessment_records` |
| 字段名 | PascalCase | `UserId`, `CreateTime` |
| 主键 | `Id` (bigint 自增) | `Id` |
@ -57,7 +90,7 @@ MiAssessment.Admin.Business/
### 3.2 C# 代码命名
| 类型 | 规范 | 示例 |
|---|---|---|
|------|------|------|
| 命名空间 | PascalCase | `MiAssessment.Admin.Business.Services` |
| 类名 | PascalCase | `UserService`, `OrderController` |
| 接口 | I + PascalCase | `IUserService`, `IOrderService` |
@ -70,13 +103,25 @@ MiAssessment.Admin.Business/
### 3.3 文件命名
| 类型 | 规范 | 示例 |
|---|---|---|
|------|------|------|
| 实体类 | 单数形式 | `User.cs`, `Order.cs` |
| 服务接口 | I + 服务名 | `IUserService.cs` |
| 服务实现 | 服务名 | `UserService.cs` |
| 控制器 | 模块名 + Controller | `UserController.cs` |
| DTO 模型 | 功能 + Request/Dto | `CreateUserRequest.cs`, `UserDto.cs` |
### 3.4 前端命名 (Vue/TypeScript)
| 类型 | 规范 | 示例 |
|------|------|------|
| 组件文件 | PascalCase | `UserList.vue`, `OrderDetail.vue` |
| 组合式函数 | use + camelCase | `useUserList.ts`, `useAuth.ts` |
| 工具函数 | camelCase | `formatDate.ts`, `request.ts` |
| 类型定义 | PascalCase | `UserInfo`, `OrderStatus` |
| 变量/函数 | camelCase | `userList`, `handleSubmit` |
| 常量 | UPPER_SNAKE_CASE | `API_BASE_URL`, `MAX_PAGE_SIZE` |
| CSS 类名 | kebab-case | `user-list`, `order-card` |
## 四、代码规范
### 4.1 实体类规范
@ -263,11 +308,12 @@ public class UserController : BusinessControllerBase
### 5.2 路由规范
```
/api/admin/{module}/{action}
小程序 API: /api/{module}/{action}
后台管理 API: /api/admin/{module}/{action}
```
| 操作 | 方法 | 路由示例 |
|---|---|---|
|------|------|----------|
| 获取列表 | GET | `/api/admin/user/getList` |
| 获取详情 | GET | `/api/admin/user/getDetail?id=1` |
| 创建 | POST | `/api/admin/user/create` |
@ -309,7 +355,7 @@ public class UserController : BusinessControllerBase
## 六、错误码规范
| 范围 | 说明 |
|---|---|
|------|------|
| 0 | 成功 |
| 1000-1999 | 通用错误 |
| 2000-2999 | 业务错误 |
@ -324,7 +370,7 @@ public class UserController : BusinessControllerBase
## 七、注释规范
### 7.1 XML 注释
### 7.1 XML 注释 (C#)
所有公开的类、方法、属性必须有 XML 注释:
@ -337,7 +383,20 @@ public class UserController : BusinessControllerBase
public async Task<PagedResult<UserDto>> GetUserListAsync(UserQueryRequest request)
```
### 7.2 代码注释
### 7.2 JSDoc 注释 (TypeScript)
```typescript
/**
* 获取用户列表
* @param params 查询参数
* @returns 分页用户列表
*/
export async function getUserList(params: UserQueryParams): Promise<PagedResult<UserDto>> {
// ...
}
```
### 7.3 代码注释
- 使用中文注释
- 复杂逻辑需要添加说明注释
@ -387,14 +446,14 @@ await _dbContext.SaveChangesAsync();
### 9.1 通用状态
| 值 | 说明 |
|---|---|
|----|------|
| 0 | 禁用/下线 |
| 1 | 启用/正常 |
### 9.2 订单状态
| 值 | 说明 |
|---|---|
|----|------|
| 1 | 待支付 |
| 2 | 已支付 |
| 3 | 已完成 |
@ -405,7 +464,7 @@ await _dbContext.SaveChangesAsync();
### 9.3 用户等级
| 值 | 说明 |
|---|---|
|----|------|
| 1 | 普通用户 |
| 2 | 合伙人 |
| 3 | 渠道合伙人 |
@ -456,7 +515,7 @@ public Property PaginationReturnsCorrectCount()
### 11.2 Type 类型
| Type | 说明 |
|---|---|
|------|------|
| feat | 新功能 |
| fix | 修复 bug |
| docs | 文档更新 |
@ -474,3 +533,106 @@ feat(user): 添加用户列表分页查询功能
- 支持按手机号、昵称筛选
- 添加分页参数验证
```
## 十二、前端开发规范
### 12.1 Vue 组件规范
```vue
<script setup lang="ts">
/**
* 用户列表组件
*/
import { ref, onMounted } from 'vue'
import type { UserDto } from '@/types/user'
import { getUserList } from '@/api/user'
// Props
const props = defineProps<{
status?: number
}>()
// Emits
const emit = defineEmits<{
select: [user: UserDto]
}>()
// State
const loading = ref(false)
const userList = ref<UserDto[]>([])
// Methods
async function fetchData() {
loading.value = true
try {
const res = await getUserList({ status: props.status })
userList.value = res.data.items
} finally {
loading.value = false
}
}
// Lifecycle
onMounted(() => {
fetchData()
})
</script>
<template>
<div class="user-list">
<!-- 内容 -->
</div>
</template>
<style scoped>
.user-list {
/* 样式 */
}
</style>
```
### 12.2 API 请求规范
```typescript
// api/user.ts
import request from '@/utils/request'
import type { UserDto, UserQueryParams, PagedResult } from '@/types'
/**
* 获取用户列表
*/
export function getUserList(params: UserQueryParams) {
return request.get<PagedResult<UserDto>>('/api/admin/user/getList', { params })
}
/**
* 更新用户状态
*/
export function updateUserStatus(id: number, status: number) {
return request.post('/api/admin/user/updateStatus', { id, status })
}
```
### 12.3 类型定义规范
```typescript
// types/user.ts
/** 用户信息 */
export interface UserDto {
id: number
uid: string
nickname: string
phone: string
status: number
createTime: string
}
/** 用户查询参数 */
export interface UserQueryParams {
page?: number
pageSize?: number
phone?: string
status?: number
}
```

View File

@ -0,0 +1,321 @@
-- =============================================
-- Business Module Menus Seed Script
-- 学业邑规划 - MiAssessment
--
-- This script inserts business module menus
-- into the Admin database menus table
--
-- Database: SQL Server 2022
-- Run after: init_admin_db.sql, seed_business_permissions.sql
-- =============================================
USE [MiAssessment_Admin];
GO
PRINT N'Seeding business module menus...';
-- =============================================
-- Get max menu ID to avoid conflicts
-- =============================================
DECLARE @maxMenuId INT;
SELECT @maxMenuId = ISNULL(MAX([Id]), 0) FROM [dbo].[menus];
PRINT N'Current max menu ID: ' + CAST(@maxMenuId AS NVARCHAR(10));
-- =============================================
-- 1. 数据统计 (Dashboard)
-- =============================================
IF NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/dashboard')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (0, N'数据统计', '/dashboard', 'dashboard/index', 'dashboard', 2, 'dashboard:view', 0, 1, GETDATE());
PRINT N'Inserted menu: 数据统计';
END
-- =============================================
-- 2. 测评管理 (Assessment)
-- =============================================
DECLARE @assessmentMenuId BIGINT;
IF NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/assessment')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (0, N'测评管理', '/assessment', 'Layout', 'education', 1, NULL, 3, 1, GETDATE());
SET @assessmentMenuId = SCOPE_IDENTITY();
PRINT N'Inserted menu: 测评管理';
END
ELSE
BEGIN
SELECT @assessmentMenuId = [Id] FROM [dbo].[menus] WHERE [Path] = '/assessment';
END
-- 测评类型
IF @assessmentMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/assessment/type')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@assessmentMenuId, N'测评类型', '/assessment/type', 'assessment/type/index', 'list', 2, 'assessment:view', 1, 1, GETDATE());
PRINT N'Inserted menu: 测评类型';
END
-- 题库管理
IF @assessmentMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/assessment/question')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@assessmentMenuId, N'题库管理', '/assessment/question', 'assessment/question/index', 'edit-pen', 2, 'assessment:view', 2, 1, GETDATE());
PRINT N'Inserted menu: 题库管理';
END
-- 报告分类
IF @assessmentMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/assessment/category')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@assessmentMenuId, N'报告分类', '/assessment/category', 'assessment/category/index', 'tree', 2, 'assessment:view', 3, 1, GETDATE());
PRINT N'Inserted menu: 报告分类';
END
-- 报告结论
IF @assessmentMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/assessment/conclusion')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@assessmentMenuId, N'报告结论', '/assessment/conclusion', 'assessment/conclusion/index', 'document', 2, 'assessment:view', 4, 1, GETDATE());
PRINT N'Inserted menu: 报告结论';
END
-- 测评记录
IF @assessmentMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/assessment/record')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@assessmentMenuId, N'测评记录', '/assessment/record', 'assessment/record/index', 'tickets', 2, 'assessment:view', 5, 1, GETDATE());
PRINT N'Inserted menu: 测评记录';
END
-- =============================================
-- 3. 订单管理 (Order)
-- =============================================
DECLARE @orderMenuId BIGINT;
IF NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/order')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (0, N'订单管理', '/order', 'Layout', 'shopping-cart', 1, NULL, 4, 1, GETDATE());
SET @orderMenuId = SCOPE_IDENTITY();
PRINT N'Inserted menu: 订单管理';
END
ELSE
BEGIN
SELECT @orderMenuId = [Id] FROM [dbo].[menus] WHERE [Path] = '/order';
END
-- 订单列表
IF @orderMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/order/list')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@orderMenuId, N'订单列表', '/order/list', 'order/list/index', 'list', 2, 'order:view', 1, 1, GETDATE());
PRINT N'Inserted menu: 订单列表';
END
-- 退款管理
IF @orderMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/order/refund')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@orderMenuId, N'退款管理', '/order/refund', 'order/refund/index', 'money', 2, 'order:view', 2, 1, GETDATE());
PRINT N'Inserted menu: 退款管理';
END
-- =============================================
-- 4. 规划师管理 (Planner)
-- =============================================
DECLARE @plannerMenuId BIGINT;
IF NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/planner')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (0, N'规划师管理', '/planner', 'Layout', 'avatar', 1, NULL, 5, 1, GETDATE());
SET @plannerMenuId = SCOPE_IDENTITY();
PRINT N'Inserted menu: 规划师管理';
END
ELSE
BEGIN
SELECT @plannerMenuId = [Id] FROM [dbo].[menus] WHERE [Path] = '/planner';
END
-- 规划师列表
IF @plannerMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/planner/list')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@plannerMenuId, N'规划师列表', '/planner/list', 'planner/list/index', 'user', 2, 'planner:view', 1, 1, GETDATE());
PRINT N'Inserted menu: 规划师列表';
END
-- 预约记录
IF @plannerMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/planner/booking')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@plannerMenuId, N'预约记录', '/planner/booking', 'planner/booking/index', 'calendar', 2, 'planner:view', 2, 1, GETDATE());
PRINT N'Inserted menu: 预约记录';
END
-- =============================================
-- 5. 分销管理 (Distribution)
-- =============================================
DECLARE @distributionMenuId BIGINT;
IF NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/distribution')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (0, N'分销管理', '/distribution', 'Layout', 'share', 1, NULL, 6, 1, GETDATE());
SET @distributionMenuId = SCOPE_IDENTITY();
PRINT N'Inserted menu: 分销管理';
END
ELSE
BEGIN
SELECT @distributionMenuId = [Id] FROM [dbo].[menus] WHERE [Path] = '/distribution';
END
-- 邀请码管理
IF @distributionMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/distribution/invite-code')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@distributionMenuId, N'邀请码管理', '/distribution/invite-code', 'distribution/invite-code/index', 'ticket', 2, 'distribution:view', 1, 1, GETDATE());
PRINT N'Inserted menu: 邀请码管理';
END
-- 佣金记录
IF @distributionMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/distribution/commission')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@distributionMenuId, N'佣金记录', '/distribution/commission', 'distribution/commission/index', 'coin', 2, 'distribution:view', 2, 1, GETDATE());
PRINT N'Inserted menu: 佣金记录';
END
-- 提现管理
IF @distributionMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/distribution/withdrawal')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@distributionMenuId, N'提现管理', '/distribution/withdrawal', 'distribution/withdrawal/index', 'wallet', 2, 'distribution:view', 3, 1, GETDATE());
PRINT N'Inserted menu: 提现管理';
END
-- =============================================
-- 6. 内容管理 (Content)
-- =============================================
DECLARE @contentMenuId BIGINT;
IF NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/content')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (0, N'内容管理', '/content', 'Layout', 'picture', 1, NULL, 7, 1, GETDATE());
SET @contentMenuId = SCOPE_IDENTITY();
PRINT N'Inserted menu: 内容管理';
END
ELSE
BEGIN
SELECT @contentMenuId = [Id] FROM [dbo].[menus] WHERE [Path] = '/content';
END
-- 轮播图管理
IF @contentMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/content/banner')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@contentMenuId, N'轮播图管理', '/content/banner', 'content/banner/index', 'picture', 2, 'content:view', 1, 1, GETDATE());
PRINT N'Inserted menu: 轮播图管理';
END
-- 宣传图管理
IF @contentMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/content/promotion')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@contentMenuId, N'宣传图管理', '/content/promotion', 'content/promotion/index', 'picture-filled', 2, 'content:view', 2, 1, GETDATE());
PRINT N'Inserted menu: 宣传图管理';
END
-- =============================================
-- 7. 系统配置 (Config) - 业务配置
-- =============================================
DECLARE @configMenuId BIGINT;
IF NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/config')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (0, N'业务配置', '/config', 'Layout', 'setting', 1, NULL, 8, 1, GETDATE());
SET @configMenuId = SCOPE_IDENTITY();
PRINT N'Inserted menu: 业务配置';
END
ELSE
BEGIN
SELECT @configMenuId = [Id] FROM [dbo].[menus] WHERE [Path] = '/config';
END
-- 基础配置
IF @configMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/config/basic')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@configMenuId, N'基础配置', '/config/basic', 'config/basic/index', 'tools', 2, 'config:view', 1, 1, GETDATE());
PRINT N'Inserted menu: 基础配置';
END
-- 支付配置
IF @configMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/config/payment')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@configMenuId, N'支付配置', '/config/payment', 'config/payment/index', 'credit-card', 2, 'config:view', 2, 1, GETDATE());
PRINT N'Inserted menu: 支付配置';
END
-- 分销配置
IF @configMenuId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM [dbo].[menus] WHERE [Path] = '/config/distribution')
BEGIN
INSERT INTO [dbo].[menus] ([ParentId], [Name], [Path], [Component], [Icon], [MenuType], [Permission], [SortOrder], [Status], [CreatedAt])
VALUES (@configMenuId, N'分销配置', '/config/distribution', 'config/distribution/index', 'share', 2, 'config:view', 3, 1, GETDATE());
PRINT N'Inserted menu: 分销配置';
END
-- =============================================
-- 8. Assign new menus to Super Admin Role (RoleId = 1)
-- =============================================
PRINT N'Assigning new menus to super_admin role...';
INSERT INTO [dbo].[role_menus] ([RoleId], [MenuId])
SELECT 1, m.[Id]
FROM [dbo].[menus] m
WHERE NOT EXISTS (
SELECT 1 FROM [dbo].[role_menus] rm
WHERE rm.[RoleId] = 1 AND rm.[MenuId] = m.[Id]
);
PRINT N'New menus assigned to super_admin role';
GO
-- =============================================
-- Verify inserted menus
-- =============================================
PRINT N'';
PRINT N'Business module menus seeded successfully!';
PRINT N'';
SELECT
m.[Id],
m.[ParentId],
m.[Name],
m.[Path],
m.[Component],
m.[Icon],
CASE m.[MenuType]
WHEN 1 THEN N'目录'
WHEN 2 THEN N'菜单'
WHEN 3 THEN N'按钮'
END AS [MenuType],
m.[Permission],
m.[SortOrder],
m.[Status]
FROM [dbo].[menus] m
WHERE m.[Path] IN (
'/dashboard',
'/assessment', '/assessment/type', '/assessment/question', '/assessment/category', '/assessment/conclusion', '/assessment/record',
'/order', '/order/list', '/order/refund',
'/planner', '/planner/list', '/planner/booking',
'/distribution', '/distribution/invite-code', '/distribution/commission', '/distribution/withdrawal',
'/content', '/content/banner', '/content/promotion',
'/config', '/config/basic', '/config/payment', '/config/distribution'
)
ORDER BY m.[SortOrder], m.[ParentId], m.[Id];
GO