Commit Graph

116 Commits

Author SHA1 Message Date
weli 5e0207b224 remove workflows 2026-05-03 10:51:14 +08:00
weli 29db1b75ff fix: FullCalendar getApi null 引用保护
Frontend CI / build (push) Failing after 14m22s
draw()/redraw()/freeze() 在组件卸载后可能被异步触发,
添加 calendar.value null 检查防止 TypeError。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 10:35:51 +08:00
weli 398ee9acfc fix: landscape toolbar date range style matches regular toolbar
Replaces bold centered date with nav arrows in landscape matrix view
with the same view-toolbar__nav + view-toolbar__range pattern used
by the regular toolbar (lighter font, wrapping text, consistent sizing).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 10:35:37 +08:00
weli 766f511e11 fix: SUPERVISOR 角色打卡查询未设置 teacher_id,添加 debug 日志
- daka store query() SUPERVISOR 与 TEACHER 同等处理
- 添加 console.debug 日志便于 vConsole 排查

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 10:33:06 +08:00
weli 78c89cd2cc fix: 主管教师首页改为 /teacher/home,非 /supervisor/subsidiaries
主管教师与教师共享 tabbar,首页应为本机构正常工作台,
而非"我的下属老师"页面。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 09:48:54 +08:00
weli 1bca764beb fix: vConsole 异步加载 tags 后不显示的问题
getTags() 在 setCurrentUser() 之后异步执行,原 watch 无 deep:true
导致 store.current.tags 被 mutation 后不触发可见性更新。

- 原 watch 添加 deep:true
- 提取 updateVConsoleVisibility 函数
- 新增独立 watch 监听 store.current.tags 变化

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 09:44:03 +08:00
weli 3373c29506 perf: cache last query range, parallelize API calls to reduce loading latency
- Add lastQueryKey to skip redundant API calls when same date range is re-queried
- Run query / query_repeats / subsidiary queries in parallel with Promise.all
- Force-refresh cache after CUD operations via search(true)
- Update searchForSubsidiaries to accept params for independent invocation

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 09:22:37 +08:00
weli 4dafdf0bb1 fix: change calendar v-show to v-if to prevent FC layout break on view switch
FC mis-calculates column widths when switching from hidden (v-show: none)
to visible. Using v-if forces full remount with correct container dimensions.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 09:18:14 +08:00
weli df66e768f3 fix: merge nav into single toolbar for both views, hide FC headerToolbar
- Remove FC headerToolbar and its customButtons (prev/today/next/createClazz)
- Add calendar navigation (navGoPrev/Today/Next) reading FC api
- Unified .view-toolbar with nav + range for both calendar and matrix
- calendarDateRange ref updated in datesSet, weekRange computed dispatches per view
- Remove dead FC button CSS

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 09:14:27 +08:00
weli e93f844a61 fix: move matrix nav/range into own toolbar below view-toolbar, matching calendar layout
- .view-toolbar now only has view toggle (and orient button for matrix)
- Matrix nav buttons (‹ 本周 ›) and date range moved to .matrix-toolbar inside matrix-page
- Calender keeps FC's built-in headerToolbar — both views now share same layout pattern

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 09:09:23 +08:00
weli fc8d7de10b fix: style FullCalendar buttons as white-outlined to match matrix view
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 08:59:36 +08:00
weli 80f4d4af46 fix: calendar button focus shadow, date range wrapping, calendar reload on view switch
- Remove FullCalendar button focus shadow to match matrix view buttons
- Allow date range text to wrap to 2 lines with smaller font
- Reload calendar data when switching back from matrix view

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 08:42:49 +08:00
weli ecdf15e26f fix: load matrix data on view switch, align matrix week to Mon-Sun
- Call triggerMatrixSearch() when switching from calendar to matrix view
- Add datesSet early-return in matrix mode to prevent state overwrite
- Add initial mount check for matrix mode
- Align matrix week start to Monday (was Sunday) to match calendar view

The matrix view was not loading data because triggerMatrixSearch was
not called in setViewMode, and FullCalendar's datesSet callback was
overwriting the state date range when switching views. Also the week
started on Sunday vs the calendar's Monday, causing the two views to
display different weeks.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 08:36:25 +08:00
weli e2c9f41fd7 fix(read): handle sudo2 failure gracefully in read()
When sudo2() fails (e.g. CI user whose login JWT lacks current_org_id),
fall back to using the auth token as the sudo token instead of propagating
the error. This prevents the route guard from aborting org/department
loading, allowing subsequent API calls (loadMyDepartments, etc.) to proceed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 23:26:31 +08:00
weli 513f52fcb3 fix: fit all landscape matrix slots without scrolling
Co-authored-by: Cursor <cursoragent@cursor.com>
progress-matrix-landscape-fit-slots-20260502-2307
2026-05-02 23:08:58 +08:00
weli c44d763e63 fix: adapt portrait matrix row heights without drift
Co-authored-by: Cursor <cursoragent@cursor.com>
progress-matrix-portrait-adaptive-20260502-2246
2026-05-02 22:46:42 +08:00
weli 8d4ed8099c fix: align portrait matrix sidebar with slots
Co-authored-by: Cursor <cursoragent@cursor.com>
progress-matrix-portrait-align-20260502-2239
2026-05-02 22:40:05 +08:00
weli b02fa37350 fix: enable natural touch scroll in matrix landscape
Co-authored-by: Cursor <cursoragent@cursor.com>
progress-matrix-landscape-scroll-20260502-2232
2026-05-02 22:33:20 +08:00
weli 2fb4e12ad5 fix: remove unrotated matrix landscape header
Co-authored-by: Cursor <cursoragent@cursor.com>
progress-matrix-landscape-20260502-2220
2026-05-02 22:21:24 +08:00
weli bae33085ce fix: restore matrix landscape 90° rotation with ml-* CSS and overflow fix
Restores 0910774 rotation structure (external day header + rotated
stage with ml-* layout) and adds missing ml-* CSS rules. Changes
landscape-stage overflow from hidden to visible so viewport can
handle scrolling of time slot content.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
matrix-landscape-v1
2026-05-02 21:44:45 +08:00
weli ea8aff1803 fix: matrix landscape 90° rotation with transposed layout for correct scrolling
Matrix landscape now stays in the rotated stage (same as calendar), but the
internal layout is transposed: time slots are columns (overflow-x: auto) and
days are reversed rows, so after 90° rotation the visual result has days
left-to-right across the top and time slots scrollable vertically.

Header (landscape-matrix-header) stays outside rotation for natural fixed
positioning at the top of the landscape viewport.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 21:20:45 +08:00
weli adbf73891a router guard: wrap in try/catch, add single-department auto-selection
- Wrap entire beforeEach guard in try/catch to prevent crashes from
  breaking navigation and leaving a blank page
- Add missing next() at end of try block so all code paths resolve
- Integrate switchDepartment() after loadMyDepartments() when exactly
  1 department is available, enabling transparent single-dept flow

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 18:29:54 +08:00
weli ce0ee5ee40 fix: use ml-* layout for matrix landscape (no rotation)
Revert matrix landscape to use the native ml-* template which has the
correct layout (time slots = rows, days = columns, header fixed, body
scrollable). This avoids the scroll-direction issues caused by 90° CSS
rotation. Calendar landscape retains rotation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 17:16:12 +08:00
weli 55ae961b2b feat: add department context with single-department transparent support
- Add Department type to types.ts
- Add loadMyDepartments / switchDepartment to store/org.ts
- Auto-load departments after org switch in main.ts
- Single-department orgs auto-select default department
- localStorage persistence for CurrentDepartmentId
2026-05-02 16:37:32 +08:00
weli 7f44a2a401 fix: enable matrix landscape scrolling through time slots
- Override --clazz-landscape-body-height for matrix to subtract header
  height, eliminating white space when scrolling
- Set overflow: visible on landscape-stage for matrix so ml-body content
  can overflow the stage
- Add min-width: max-content on matrix container so content overflows
  in X direction → becomes vertical scroll after 90° rotation
- ml-body disabled internal scrolling when inside rotated viewport

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 16:35:54 +08:00
weli 0910774a2f fix: matrix landscape 90° rotation with fixed header outside rotation
Matrix landscape now uses the same landscape-stage 90° CSS rotation as
the calendar view. The weekday header (ml-header) is rendered outside
the rotated container so it stays fixed at the top. Matrix body
(ml-body) is inside the rotation and scrollable.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 16:17:17 +08:00
weli a9d5e0844e fix: standardize terminology — 排课 (clazz) not 课程 (course)
"排课" = scheduled class instance, "课程" = course content/curriculum.
All 21 instances of incorrect usage were in clazz/tongzhi/user-settings
contexts where the underlying data is a clazz (clazz_id, clazz_name,
is_repeat), not a course.

Affected files: clazz/index.vue (10), tongzhi/index.vue (4),
tongzhi/detail.vue (3), store/clazz.ts (3), user-settings.vue (1).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 11:53:34 +08:00
weli e40dfe0835 fix: show 排课 tab for SUPERVISOR role in bottom navigation
The 排课 and 打卡 tabs were hidden behind v-if="is_teacher",
excluding the SUPERVISOR role from accessing the clazz page.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 11:35:56 +08:00
weli eaec80f24f fix: allow SUPERVISOR role to see own courses in query filter
The query() function in clazz store only filtered for TEACHER and
STUDENT roles, causing SUPERVISOR role to always get an empty list.
Added SUPERVISOR alongside TEACHER to show supervisor's own courses.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 10:49:36 +08:00
weli 14f2c277c3 fix: restrict vconsole to sudoer-only (SYS_CAN_SUDO tag), remove SYS_TESTER
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 10:49:33 +08:00
weli 76100e4ab8 fix: also show vconsole for users with SYS_CAN_SUDO tag (root users)
Previously vConsole was only shown to users with a role carrying the
SYS_TESTER label. Extend visibility to users who have the SYS_CAN_SUDO
tag (the "root tag"), since those users also need debug access during
E2E testing and general troubleshooting.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 10:36:54 +08:00
weli 962fca7847 fix: use Date format (not DateTime) in clazz datesSet callback
The datesSet callback was formatting dates as "YYYY-MM-DD HH:mm:ss"
but the by_hty_id backend endpoints now use string_to_date which
only accepts "YYYY-MM-DD" format. Caused "trailing input" errors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 10:34:50 +08:00
weli bb19834725 fix: supervisor role check for subsidiary data + color passthrough in matrix view
Subsidiary courses now only appear in SUPERVISOR mode, not TEACHER mode.
Matrix view shows each subsidiary teacher's courses with a distinct color.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 10:22:22 +08:00
weli ba05fc1b3a fix: hide admin buttons when viewing course package via 试看 preview
"试看" (preview) from the storefront should show a read-only view without
admin operations (编辑, 删除, 发布上架, 下架). Add preview=1 query param
to distinguish preview from direct management navigation. Also limit
previewable sections to first one in preview mode, consistent with
non-owner experience.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 09:32:33 +08:00
weli 18548cc1a4 fix: sticky day sidebar + fixed-width scrollable columns
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 09:29:51 +08:00
weli f54705dd5b fix: dynamic time slot columns from events + detailed event blocks
- Only show columns for time slots that have actual courses
- Event blocks show: lesson period, time range, teacher, students
- Horizontal scroll when many slot columns

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 09:24:25 +08:00
weli 0fa623b73c fix: rewrite matrix view as weekly timetable grid (days × slots)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 09:14:09 +08:00
weli 4843e3839e fix: restructure matrix view layout - X=date+time header, Y=event blocks
- Remove Y-axis time slot rows (was wrong)
- X-axis: hierarchical header (weekday + date | time slot name)
- Body: lane-packed event blocks in each date×slot column
- Show teacher name and student names in each block
- Empty slots show clickable '+' placeholder

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 08:58:53 +08:00
weli 8a33f35c87 fix: matrix view full-screen fill + show teacher/student names
- Add flex column layout for landscape full-screen fill
- Show teacher name and student names in matrix event blocks
- Refactor useClazzViewModel with makeEvent() helper
- Fix CSS nesting for .slot-row

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 08:54:11 +08:00
weli 30a845d7d3 feat: add wide-screen matrix view for clazz scheduling
Add dual-view mode to /clazz page — users can toggle between:
- Existing calendar view (portrait, FullCalendar timeGridWeek)
- New matrix view (landscape, X=date×timeSlot, Y=parallel lanes)

Includes:
- constants.ts: fixed time slot templates (08:40, 10:10, 14:00, 15:30)
- useClazzViewModel.ts: normalized event model composable
- ClazzMatrixView.vue: matrix component with lane packing algorithm
- index.vue: view toggle, matrix navigation, cell/block interactions

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 08:39:09 +08:00
weli d3df324b8b feat: add 创建排课 button to calendar; fix 操作记录 spacing
- Add "创建排课" custom button in FullCalendar header toolbar, defaults
  to current date/time + 45min duration, guarded by is_teacher check
- Add margin-bottom to 操作记录 cell so it doesn't crowd the footer buttons

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 22:17:49 +08:00
weli c96830c301 feat: add lesson statistics pages and audit log viewer
- Add student lesson records page (/student/lessons)
- Add teacher lesson statistics page (/teacher/stats)
- Add supervisor statistics page (/supervisor/stats)
- Add navigation entries in student/teacher/supervisor profiles
- Add audit log viewer in clazz detail modal
- Add getAuditLog, queryStudentLessons, queryTeacherDetailStats store methods
- Register new routes

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 19:46:00 +08:00
weli 53989e5731 fix: course package detail page - permission gate, status logic, preview lock 2026-05-01 10:50:56 +08:00
weli 6e4ef03e07 fix: show placeholder when cover_image_url is null
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 10:10:46 +08:00
weli c511cc318c feat: load all public packages without org_id for guest storefront
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 10:01:37 +08:00
weli ddaa862582 fix: handle empty org_id gracefully in course-package-store + index.vue
- CoursePackageStore: don't show error when no orgId and unauth,
  just show empty state
- index.vue: only render CoursePackageStore when org_id is available
  in URL, otherwise show original login prompt

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 08:43:13 +08:00
weli b8dca18ea4 fix: support org_id from URL query param in course-package-store
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 08:17:31 +08:00
weli f033e303ce feat: add course package storefront for unauth and home pages
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 08:08:01 +08:00
weli e65ef12cfc fix: redirect teacherless students to teacher-select page
When a student has no claimed teachers, redirect them to the
teacher-select page instead of silently landing on the home page
with no teacher. The teacher-select page falls back to showing
available valid teachers when the student's teacher list is empty.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 01:56:28 +08:00
weli 09653ae15b fix: remove org-unaware teacher claiming page from index.vue
- Remove the "请选择您的老师" page (v-else-if block) that showed teachers
  from all orgs
- Remove the mine.length === 0 guard in watchEffect - students with no
  teachers now redirect to home page normally
- Teacher selection moves to profile page /student/teacher-select
- Remove unused code (getAllTeachers, teachers computed, chooseTeacher)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 01:22:58 +08:00