Skip to content

Feat/counseling platform - #1015

Closed
wang97x wants to merge 9 commits into
xerrors:mainfrom
wang97x:feat/counseling-platform
Closed

Feat/counseling platform#1015
wang97x wants to merge 9 commits into
xerrors:mainfrom
wang97x:feat/counseling-platform

Conversation

@wang97x

@wang97x wang97x commented Sep 12, 2026

Copy link
Copy Markdown

变更说明

请说明本 PR 解决的问题、主要改动及影响范围。

  • 任务类型:feature / bug-fix / simplification / architecture / process / testing
  • 目标与非目标:
  • substantial / trivial 判断:

工程主张与 Owner

  • 受影响的工程主张:请用自然语言逐条说明本 PR 改变或依赖的外部结果、状态或边界;不使用中央 claim ID。
  • Owner / commit point / 观察边界:请说明事实由哪段代码、数据约束或契约拥有,何时提交、何处可观察。
  • 决策记录:请链接新增或更新的 decision record;trivial 变更请说明为何免除。

验证情况

每条验收主张单独一组,字段与决策记录的证据矩阵一致(主张、失败面、语义 Owner、证据、负向案例、结果)。结果词只使用 PassedInspectedNot runInferred;除 Passed 外不得写成测试通过。不适用的字段写「不适用」,不要留空。

<验收主张>

  • 失败面:
  • 语义 Owner:
  • 直接证据 / 命令:
  • 负向案例:
  • 结果:<Passed / Inspected / Not run / Inferred>

涉及 Run、FIFO、SSE、沙盒、恢复或其他高风险 assembled path 时,请附 deterministic E2E 结果;真实 provider/browser 未执行时明确写 Not run 和风险。

简化 / 删除验收

simplification 必填:说明 keep/narrow/replace/remove 的取舍;列出 consumer、registration/export、配置/manifest、durable/wire/migration、测试、文档和依赖的负向搜索;写明“旧能力不存在”的证据与重新引入条件。其他类型填“不涉及”。

独立语义 Review

请记录全新上下文 Reviewer 实际覆盖的需求、完整 diff 与测试范围、结论和未解决项;不粘贴推理流水账。Review 结论不能替代验证证据。

未验证范围与风险

请明确列出未执行的检查、无法复现的环境、外部 provider/浏览器/部署差异,以及对应风险。不要把未执行写成已通过。

事故反馈

若本变更修复达到门槛的高影响逃逸缺陷,请链接 postmortem 及已落地的 reproducer/guard/gate;未达到门槛请说明原因。

界面变更

如涉及界面或交互调整,请提供截图或录屏;不涉及请填写“不涉及”。

关联事项

如有关联 Issue,请填写 Closes #<issue-number> 或相关链接;无关联事项请填写“无”。

补充说明

请说明兼容性、配置、数据迁移或其他需要评审者关注的内容;无补充说明请填写“无”。

Copilot AI lite review requested due to automatic review settings September 12, 2026 07:22
@wang97x wang97x closed this Sep 12, 2026
@wang97x
wang97x deleted the feat/counseling-platform branch September 12, 2026 07:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical and moderate findings remain, including stale student data, counseling integrity handling, and department-deletion behavior.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds counseling student records and role-based personal/team knowledge access across the FastAPI, PostgreSQL, and Vue platform.

Changes:

  • Adds business roles, department-scoped student records, ownership, APIs, and migrations.
  • Adds personal/team knowledge permissions and frontend workflows.
  • Updates tests, documentation, branding, and WSL development support.
File summaries
File Reviewed change Final review comments
web/test/unit/teamKnowledge.test.js Team knowledge frontend coverage
web/test/unit/personalKnowledge.test.js Personal knowledge frontend coverage
web/src/views/StudentRecordsView.vue Student list, detail, assignment, and editing UI critical (3 votes; L67): discard stale responses after student navigation.
nit (1 vote; L128): add route, permission, and late-response tests.
web/src/views/LoginView.vue Login branding
web/src/views/ExtensionsView.vue Role-based extension visibility
web/src/views/DataBaseView.vue Team/personal knowledge views
web/src/views/DataBaseInfoView.vue Knowledge permissions and controls
web/src/utils/shareConfig.js Share-scope classification
web/src/utils/databaseCreateForm.js Personal knowledge request construction
web/src/stores/user.js Business-role session state moderate (1 vote; L35): map legacy admin to business_admin.
moderate (1 vote; L189): use the complete mapping during refresh.
web/src/stores/database.js Knowledge-base request and cache state moderate (1 vote; L164): invalidate stale detail responses.
moderate (1 vote; L688): prevent late query-parameter responses from mutating cleared state.
web/src/router/index.js Student and knowledge route guards
web/src/layouts/AppLayout.vue Student-record navigation
web/src/components/knowledge/DatabaseCreateFlowModal.vue Personal/team creation flow moderate (1 vote; L202): hide or disable sharing controls in personal mode.
web/src/components/FileUploadModal.vue Role-based upload options
web/src/components/EmbeddingModelSelector.vue Embedding model selection UI
web/src/components/AgentChatComponent.vue Agent chat UI
web/src/apis/knowledge_api.js Knowledge API client updates
web/src/apis/counseling_api.js Counseling API client
web/index.html Web entry and branding metadata
web/eslint.config.js Frontend lint configuration
docs/mechanisms/knowledge-base.md Knowledge-base mechanism documentation
docs/develop-guides/roadmap.md Counseling roadmap status nit (3 votes; L5): distinguish delivered scope from remaining work.
docs/develop-guides/decisions/proposed/2026-09-12-counseling-minimal-release.md Counseling release proposal
docs/develop-guides/decisions/implemented/2026-09-12-team-knowledge-entry.md Team knowledge decision record
docs/develop-guides/decisions/implemented/2026-09-12-student-record-pages.md Student UI decision record
docs/develop-guides/decisions/implemented/2026-09-12-personal-knowledge.md Personal knowledge decision record
docs/develop-guides/decisions/implemented/2026-09-12-minimal-student-record.md Student-record decision record
docs/develop-guides/decisions/implemented/2026-09-11-wsl-vscode-development.md WSL development decision record
docs/develop-guides/contributing.md Contribution guidance
docker-compose.wsl.yml WSL Compose support
backend/test/unit/services/test_storage_migration.py Storage migration unit coverage
backend/test/unit/services/test_oidc_service.py OIDC service unit coverage
backend/test/unit/routers/test_knowledge_workspace_import.py Workspace import router coverage
backend/test/unit/routers/test_knowledge_router_cleanup.py Knowledge router cleanup coverage
backend/test/unit/permissions/test_resource_permission.py Resource permission unit coverage
backend/test/unit/permissions/test_business_roles.py Business-role unit coverage
backend/test/unit/knowledge/test_kb_utils.py Knowledge utility unit coverage
backend/test/integration/services/test_schema_migration_version.py Schema migration integration coverage
backend/test/integration/api/test_team_knowledge_api.py Team knowledge API coverage
backend/test/integration/api/test_personal_knowledge_api.py Personal knowledge API coverage
backend/test/integration/api/test_counseling_student_api.py Counseling student API coverage nit (1 vote; L46): add a null-department business-admin rejection case with no created row.
backend/test/integration/api/test_business_roles_api.py Business-role API coverage
backend/server/utils/knowledge_permissions.py Knowledge permission dependencies
backend/server/routers/workspace_router.py Workspace routes
backend/server/routers/knowledge_router.py Knowledge authorization and routes
backend/server/routers/knowledge_eval_router.py Knowledge evaluation routes
backend/server/routers/counseling_router.py Counseling HTTP routes
backend/server/routers/auth_router.py Business-role identity handling
backend/server/routers/__init__.py Router registration
backend/package/yuxi/storage/postgres/models_counseling.py Student-record schema moderate (1 vote; L30): address department deletion behavior for referenced student records and add integration coverage.
backend/package/yuxi/storage/postgres/models_business.py Business-role model fields
backend/package/yuxi/storage/postgres/manager.py Schema version and migrations
backend/package/yuxi/storage_migration.py Migration orchestration
backend/package/yuxi/services/oidc_service.py OIDC service
backend/package/yuxi/services/identity_admin_service.py Identity administration
backend/package/yuxi/services/counseling.py Student-record business logic moderate (2 votes; L38): reject missing departments before persistence.
moderate (1 vote; L48): only map the department/code unique violation to 409; re-raise other integrity errors.
backend/package/yuxi/repositories/counseling.py Department and counselor isolation
backend/package/yuxi/permissions/resource_permission.py Resource authorization
backend/package/yuxi/permissions/business_roles.py Business roles and capabilities
backend/package/yuxi/permissions/__init__.py Permission exports
backend/package/yuxi/knowledge/utils/kb_utils.py Knowledge utilities
backend/package/yuxi/knowledge/manager.py Knowledge management
backend/package/yuxi/config/static/info.template.yaml Static configuration template
ARCHITECTURE.md Architecture and route documentation
.vscode/tasks.json WSL development tasks
.gitignore Repository ignore rules
.gitattributes Repository attributes
Review details

Suppressed comments (9)

backend/package/yuxi/services/counseling.py:50

  • This catches every IntegrityError as a duplicate-code conflict, including foreign-key, NOT NULL, and check-constraint failures. Those failures are not 409 conflicts and the current mapping hides the real cause; only translate the department/code unique-constraint violation and re-raise other integrity errors for the route's generic handling.
    except IntegrityError as exc:
        await db.rollback()
        raise FileExistsError("本部门学生编号已存在") from exc

backend/package/yuxi/storage/postgres/models_counseling.py:30

  • 这个外键使用默认的 NO ACTION,而现有 DELETE /api/departments/{id} 会先迁移用户再直接删除部门;一旦部门已有学生档案,该删除会因 counseling_students.department_id 仍引用部门而抛出未处理的 IntegrityError(500),破坏现有部门删除流程。请在部门删除流程中明确阻止并返回可理解的 4xx,或定义档案迁移/归档策略,并补充该场景的集成测试。
    department_id = Column(Integer, ForeignKey("departments.id"), nullable=False)

backend/test/integration/api/test_counseling_student_api.py:51

  • The integration coverage exercises cross-department and role denial, but not a business_admin whose department_id is NULL. That path currently reaches the database NOT NULL constraint and can be returned as a duplicate-code conflict; add a negative HTTP case asserting the intended rejection and that no row is created.
        manager_id, manager = await actor(departments[0], "admin", '["business_admin"]')
        owner_id, owner = await actor(departments[0], "user", '["counselor"]')
        other_id, other = await actor(departments[0], "user", '["counselor"]')
        tech_id, tech = await actor(departments[0], "superadmin", '["technical_admin"]')
        _, foreign_manager = await actor(departments[1], "admin", '["business_admin"]')
        _, no_role = await actor(departments[0], "user", "[]")

web/src/components/knowledge/DatabaseCreateFlowModal.vue:202

  • 管理员也可以从“我的”分类打开该弹窗,但这里仍渲染可编辑的 ShareConfigFormhandleCreate 在个人模式下无条件使用 createPersonalShareConfig(),因此管理员填写的共享范围会被静默丢弃。个人模式应隐藏或禁用该表单,避免用户以为设置会生效。
    web/src/stores/database.js:164
  • The kbId.value && guard is false after leaving a detail route, because the account-switch watcher resets kbId to null. A response from the old getDatabaseInfo() request can therefore repopulate database after resetFileBrowser()/navigation, leaving stale knowledge-base metadata in the shared store. Invalidate the request on selection reset (or use a generation token) before committing the response; the same identity rule must also cover the nested query-parameter load.
    web/src/stores/database.js:688
  • This duplicate conditional also accepts a late query-parameter response when kbId.value has been cleared to null. It then mutates queryParams and meta for no selected database, and those values can leak into the next detail view. Apply the same request invalidation used for database details before mutating shared state.
    web/src/stores/user.js:190
  • getCurrentUser() repeats the incomplete legacy fallback, so a refresh can clear an existing legacy admin's business_admin capability and hide /students while the backend continues to authorize it. Use the same full platform-role mapping as the login path rather than falling back to [] for admin.
    web/src/stores/user.js:35
  • This compatibility fallback only maps the legacy user platform role. The backend maps a legacy admin to business_admin (backend/package/yuxi/permissions/business_roles.py:52-56), so an older login response without business_roles leaves the frontend with no business capabilities: the student-record navigation/guard and team-management controls disappear even though the backend still grants the role. Mirror the complete legacy mapping here (and in the refresh path below).
    web/src/views/StudentRecordsView.vue:132
  • The new student-record page has no web test covering its route-driven list/detail flow or permission-gated create/edit actions. The repository does maintain related frontend unit tests (for example web/test/unit/database_store.test.js and web/test/unit/knowledge_detail_layout.test.js), so add a focused test for this page, including the late response after changing studentId; otherwise the race and UI authorization regressions are not protected.
  • Files reviewed: 68/69 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +67 to +82
async function loadDetail(id) {
loading.value = true
error.value = ''
detail.value = null
try {
detail.value = await counselingApi.getStudent(id)
editForm.value = {
background_summary: detail.value.background_summary,
status: detail.value.status
}
} catch (cause) {
error.value = cause.message || '加载档案详情失败'
} finally {
loading.value = false
}
}
Comment on lines +38 to +40
if BusinessCapability.ASSIGN_STUDENTS not in resolve_business_capabilities(actor):
raise PermissionError("需要学生分配权限")
repository = StudentRepository(db)

## 知伴二次开发方向

知伴最小业务版继续补学生档案页面、团队与个人知识库及会话背景关联,真实模型联调安排在业务版验收之后。范围、取舍和分批验收见[实施提案](./decisions/proposed/2026-09-12-counseling-minimal-release.md)。当前已有基础品牌展示、可兼任的业务角色与学生档案存储和接口;辅导对话、档案页面与知识库业务流程仍待实现。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants