Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

View File

@@ -0,0 +1,215 @@
# 评分标准JSON结构化重构方案
## 问题分析
**当前设计缺陷:**
1. **UI层**:使用结构化对象 `[{min_score, max_score, description}]`
2. **数据库层**:使用 `\n` 分隔的字符串存储在 `instructions` 字段
3. **数据丢失**`min_score``max_score` 等结构化信息在保存时完全丢失
## 解决方案
### 方案一:使用现有 `scoring_criteria` 字段(推荐)
#### 1. 数据库结构调整
```sql
-- 第一步:将 scoring_criteria 字段改为 JSONB 类型(如果不是的话)
ALTER TABLE public.ak_training_projects
ALTER COLUMN scoring_criteria TYPE JSONB USING scoring_criteria::jsonb;
```
#### 2. 新的JSON数据结构
```json
{
"criteria": [
{
"min_score": 90,
"max_score": 100,
"description": "优秀:动作标准,节奏控制完美,表现卓越"
},
{
"min_score": 80,
"max_score": 89,
"description": "良好:动作较为标准,节奏控制良好"
},
{
"min_score": 70,
"max_score": 79,
"description": "及格:基本掌握动作要领,需要改进"
},
{
"min_score": 0,
"max_score": 69,
"description": "不及格:动作不标准,需要重新练习"
}
],
"scoring_method": "comprehensive", // 综合评分方式
"weight_distribution": {
"technique": 0.4, // 技术动作权重 40%
"effort": 0.3, // 努力程度权重 30%
"improvement": 0.3 // 进步幅度权重 30%
}
}
```
#### 3. 前端代码重构
**加载数据时:**
```typescript
// 修改 loadProjectData 函数
function loadProjectData() {
// ...现有代码...
// 处理评分标准 - 使用新的JSON结构
let scoringCriteria: Array<UTSJSONObject> = []
const criteriaData = safeGet(projectData, 'scoring_criteria', null)
if (criteriaData && typeof criteriaData === 'object') {
// 新的JSON格式
const criteria = safeGet(criteriaData, 'criteria', [])
if (criteria instanceof Array) {
scoringCriteria = criteria.map((item: any) => ({
min_score: item.min_score?.toString() || '',
max_score: item.max_score?.toString() || '',
description: item.description || ''
} as UTSJSONObject))
}
} else if (typeof criteriaData === 'string') {
// 兼容旧的 \n 分隔格式
const instructionSteps = criteriaData.split('\n').filter((step: string) => step.trim().length > 0)
scoringCriteria = instructionSteps.map((step: string, index: number) => ({
min_score: (index * 20).toString(),
max_score: ((index + 1) * 20).toString(),
description: step.trim()
} as UTSJSONObject))
}
if (scoringCriteria.length === 0) {
scoringCriteria = [{ min_score: '', max_score: '', description: '' } as UTSJSONObject]
}
// ...其他代码...
}
```
**保存数据时:**
```typescript
// 修改 updateProject 和 saveDraft 函数
function updateProject() {
// ...现有代码...
const scoringCriteria = getScoringCriteria()
const scoringCriteriaJson = {
criteria: scoringCriteria.map((criteria: UTSJSONObject) => ({
min_score: parseInt(safeGet(criteria, 'min_score', '0')),
max_score: parseInt(safeGet(criteria, 'max_score', '100')),
description: safeGet(criteria, 'description', '')
})).filter(item => item.description.trim().length > 0),
scoring_method: "comprehensive",
weight_distribution: {
technique: 0.4,
effort: 0.3,
improvement: 0.3
}
}
const { data, error } = await supaClient
.from('ak_training_projects')
.update({
// ...其他字段...
scoring_criteria: scoringCriteriaJson,
instructions: '', // 清空旧的instructions字段避免混淆
updated_at: new Date().toISOString()
})
.eq('id', projectId.value)
.execute()
// ...其他代码...
}
```
### 方案二:添加新字段(备选方案)
如果不想修改现有字段,可以添加新字段:
```sql
-- 添加新的JSONB字段
ALTER TABLE public.ak_training_projects
ADD COLUMN scoring_criteria_json JSONB;
-- 创建索引以提高查询性能
CREATE INDEX idx_ak_training_projects_scoring_criteria
ON public.ak_training_projects USING GIN (scoring_criteria_json);
```
## 数据迁移脚本
### 第一步:备份现有数据
```sql
-- 创建备份表
CREATE TABLE ak_training_projects_backup AS
SELECT * FROM ak_training_projects;
```
### 第二步:迁移现有数据
```sql
-- 将现有的 instructions 数据转换为 JSON 格式
UPDATE ak_training_projects
SET scoring_criteria = jsonb_build_object(
'criteria',
ARRAY(
SELECT jsonb_build_object(
'min_score', (ROW_NUMBER() OVER () - 1) * 20,
'max_score', ROW_NUMBER() OVER () * 20,
'description', trim(instruction)
)
FROM unnest(string_to_array(instructions, E'\n')) AS instruction
WHERE trim(instruction) != ''
),
'scoring_method', 'comprehensive',
'weight_distribution', jsonb_build_object(
'technique', 0.4,
'effort', 0.3,
'improvement', 0.3
)
)
WHERE instructions IS NOT NULL AND instructions != '';
```
### 第三步:验证迁移结果
```sql
-- 验证JSON结构
SELECT
id,
title,
scoring_criteria->'criteria' as criteria_array,
jsonb_array_length(scoring_criteria->'criteria') as criteria_count
FROM ak_training_projects
WHERE scoring_criteria IS NOT NULL
LIMIT 5;
```
## 优势对比
| 特性 | 旧方案 (\n分隔) | 新方案 (JSON) |
|------|-----------------|---------------|
| 数据结构 | 平铺字符串 | 结构化对象 |
| 分数范围 | ❌ 丢失 | ✅ 保留 |
| 查询能力 | ❌ 有限 | ✅ 强大 |
| 扩展性 | ❌ 困难 | ✅ 容易 |
| 数据完整性 | ❌ 差 | ✅ 优秀 |
| AI分析支持 | ❌ 不支持 | ✅ 原生支持 |
## 实施建议
1. **测试环境先行**:在测试环境完成迁移和测试
2. **渐进式部署**:保持向后兼容,支持新旧两种格式
3. **数据校验**:迁移后进行全面的数据完整性检查
4. **性能优化**为JSONB字段创建合适的索引
## 长期收益
1. **更好的数据查询**:可以直接查询特定分数范围的标准
2. **AI集成友好**结构化数据更容易被AI系统理解和处理
3. **扩展性强**:未来可以轻松添加新的评分维度
4. **数据一致性**避免了UI和数据库层的数据结构不匹配问题