feat: 导入导出错误信息 Markdown 渲染升级
Phase 1: 共用类型定义 - apps/server/src/common/import-result.types.ts — ImportRowError + ImportResult<T> - apps/admin/src/types/import.ts — 前端对应类型 + ImportDisplayConfig Phase 2: 后端增强 - students.service.ts — batchImport/matchImport 改为 ImportResult 格式 · 每行跳过时收集 ImportRowError(code + reason) · reason 支持 markdown 标记(**字段名** / `值`) - archive.service.ts — batchImportArchive 统一用 ImportResult 格式 · 各 Sheet 错误使用标准 error code - archive.controller.ts — 日志使用新的 success 字段 Phase 3: 前端基础 - 安装 react-markdown - ImportResultModal 组件(共用导入结果弹窗) · Statistic 成功统计 + Table 错误明细 · 原因列支持 react-markdown 渲染(粗体字段名、等宽代码值) · 错误类型用 Tag 颜色区分 - api/index.ts — 403 错误从 console.warn 改为 message.warning 用户可见 Phase 4: 前端集成 - Students/index.tsx — 替换硬编码导入结果弹窗 · 删除'后端只返回统计汇总'注释和跳过原因 hardcode · 新格式自动使用 ImportResultModal,旧格式兼容 - StudentProfileContent/index.tsx — 替换内联导入 Modal 为 ImportResultModal
This commit is contained in:
44
.agents/skills/subagent-driven-development/scripts/review-package
Executable file
44
.agents/skills/subagent-driven-development/scripts/review-package
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Generate a review package: commit list, stat summary, and the net
|
||||
# diff with extended context, written to a file the reviewer reads in one
|
||||
# call. Using the recorded per-task BASE (not HEAD~1) keeps multi-commit
|
||||
# tasks intact.
|
||||
#
|
||||
# Usage: review-package BASE HEAD [OUTFILE]
|
||||
# Default OUTFILE: <repo-root>/.superpowers/sdd/review-<base7>..<head7>.diff
|
||||
# (named per range, so a re-review after fixes gets a distinct fresh file).
|
||||
set -euo pipefail
|
||||
|
||||
if [ $# -lt 2 ] || [ $# -gt 3 ]; then
|
||||
echo "usage: review-package BASE HEAD [OUTFILE]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
base=$1
|
||||
head=$2
|
||||
|
||||
git rev-parse --verify --quiet "$base" >/dev/null || { echo "bad BASE: $base" >&2; exit 2; }
|
||||
git rev-parse --verify --quiet "$head" >/dev/null || { echo "bad HEAD: $head" >&2; exit 2; }
|
||||
|
||||
if [ $# -eq 3 ]; then
|
||||
out=$3
|
||||
else
|
||||
dir=$("$(cd "$(dirname "$0")" && pwd)/sdd-workspace")
|
||||
out="$dir/review-$(git rev-parse --short "$base")..$(git rev-parse --short "$head").diff"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "# Review package: ${base}..${head}"
|
||||
echo
|
||||
echo "## Commits"
|
||||
git log --oneline "${base}..${head}"
|
||||
echo
|
||||
echo "## Files changed"
|
||||
git diff --stat "${base}..${head}"
|
||||
echo
|
||||
echo "## Diff"
|
||||
git diff -U10 "${base}..${head}"
|
||||
} > "$out"
|
||||
|
||||
commits=$(git rev-list --count "${base}..${head}")
|
||||
echo "wrote ${out}: ${commits} commit(s), $(wc -c < "$out" | tr -d ' ') bytes"
|
||||
22
.agents/skills/subagent-driven-development/scripts/sdd-workspace
Executable file
22
.agents/skills/subagent-driven-development/scripts/sdd-workspace
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
# Resolve and ensure the working-tree directory SDD uses for its short-lived
|
||||
# artifacts: task briefs, implementer reports, review packages, and the
|
||||
# progress ledger. Print the directory's absolute path.
|
||||
#
|
||||
# The workspace lives in the working tree (not under .git/) because Claude Code
|
||||
# treats .git/ as a protected path and denies agent writes there — which blocks
|
||||
# an implementer subagent from writing its report file. A self-ignoring
|
||||
# .gitignore keeps the workspace out of `git status` and out of accidental
|
||||
# commits without modifying any tracked file.
|
||||
#
|
||||
# Single source of truth for the workspace location, so task-brief and
|
||||
# review-package cannot drift to different directories.
|
||||
#
|
||||
# Usage: sdd-workspace
|
||||
set -euo pipefail
|
||||
|
||||
root=$(git rev-parse --show-toplevel)
|
||||
dir="$root/.superpowers/sdd"
|
||||
mkdir -p "$dir"
|
||||
printf '*\n' > "$dir/.gitignore"
|
||||
cd "$dir" && pwd
|
||||
40
.agents/skills/subagent-driven-development/scripts/task-brief
Executable file
40
.agents/skills/subagent-driven-development/scripts/task-brief
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
# Extract one task's full text from an implementation plan into a file the
|
||||
# implementer reads in one call, so the task text never has to be pasted
|
||||
# through the controller's context.
|
||||
#
|
||||
# Usage: task-brief PLAN_FILE TASK_NUMBER [OUTFILE]
|
||||
# Default OUTFILE: <repo-root>/.superpowers/sdd/task-<N>-brief.md
|
||||
# (per worktree; concurrent runs in the same working tree share it).
|
||||
set -euo pipefail
|
||||
|
||||
if [ $# -lt 2 ] || [ $# -gt 3 ]; then
|
||||
echo "usage: task-brief PLAN_FILE TASK_NUMBER [OUTFILE]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
plan=$1
|
||||
n=$2
|
||||
[ -f "$plan" ] || { echo "no such plan file: $plan" >&2; exit 2; }
|
||||
|
||||
if [ $# -eq 3 ]; then
|
||||
out=$3
|
||||
else
|
||||
dir=$("$(cd "$(dirname "$0")" && pwd)/sdd-workspace")
|
||||
out="$dir/task-${n}-brief.md"
|
||||
fi
|
||||
|
||||
awk -v n="$n" '
|
||||
/^```/ { infence = !infence }
|
||||
!infence && /^#+[ \t]+Task[ \t]+[0-9]+/ {
|
||||
intask = ($0 ~ ("^#+[ \t]+Task[ \t]+" n "([^0-9]|$)"))
|
||||
}
|
||||
intask { print }
|
||||
' "$plan" > "$out"
|
||||
|
||||
if [ ! -s "$out" ]; then
|
||||
echo "task ${n} not found in ${plan} (no heading matching 'Task ${n}')" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
echo "wrote ${out}: $(wc -l < "$out" | tr -d ' ') lines"
|
||||
Reference in New Issue
Block a user