- Update jumpUtil test expectations to match renamed event→alarm route
names and add point source coverage.
- Fix thing-model-flow paths (PointAddForm→PointEditForm, etc.) after
the form consolidation refactor.
- Exclude .spec.ts files from the focused/disabled-test guardrail since
Playwright e2e specs use conditional first-argument-guarded skips.
- Polyfill localStorage / sessionStorage in vitest setup for Node ≥ 22
where the native globals are gated behind --localstorage-file.
- Add client-side pagination (10/20/50 per page) to Point Attributes,
Related Commands, and Related Events tables via the matrix-toolbar
trailing slot. Filter changes reset to page 1.
- Remove redundant descriptions from table rows: drop the defaultValue
column in Driver Attributes (placeholder already shows the default)
and replace two-line name+code cells with single-line names and
hover tooltips.
- Unify table CSS class names (matrix-table, matrix-cell, matrix-cell__meta)
across all four config tabs and let Element Plus defaults drive cell
padding / row height instead of hard-coded overrides.
- Make input fields fill the cell width in Driver Attributes.
- Rename Profile Edit tabs (Point/Command/Event Config → Related
Points/Commands/Events) to match the detail-page convention.
- Consolidate settings detail routes in operate.ts under a single
/settings Layout wrapper with relative child paths so they never
compete with the nested settings list routes.
- Add settingsAbout to SETTINGS_FALLBACK_SIDEBAR and ensureDirectItem so
it appears even when the menu API is unreachable.
- Add ensureCommandGroup to match Alarm/Model/Event group handling.
- Fix settingsLabel insert-before references.
- PointCard now respects the embedded prop from parent context,
hiding action buttons in detail read-only views while keeping
them visible in edit / standalone contexts.
- Update stale event→alarm route references in Layout FALLBACK_ICON,
Home dashboard cards, jumpUtil, Overview, and zh locale i18n keys
that were missed in the earlier rename commits.
Replace inline config toolbars and forms in device/profile edit pages
with reusable InfoCard and MatrixToolbar components. Remove redundant
form refs and manual validation delegation to the new components.
Move breadcrumb outside el-scrollbar so it stays fixed at the top.
For settings routes, bypass the Layout-level el-scrollbar entirely and
use a fixed-viewport flex container instead, allowing the sidebar menu
and main content to scroll independently.
Replace the rigid el-steps sequential wizard with el-tabs, matching the
detail page pattern. Remove the "Complete" step, prev/next navigation,
and return buttons. Each tab now has its own toolbar with Reset/Save.
Device config form uses a 3-column grid layout. Use BaseCard wrapper
for consistent tab spacing with detail pages.
Extend formRuleUtil with reusable rule builders (authNameRules,
decimalRules, byteRules, requiredStringRule/requiredSelectRule,
positiveIntegerRules) plus matching patterns, and migrate every edit
form to consume them. Forms now share a consistent maxlength/show-word-
limit contract, point/device numeric attributes validate against typed
ranges with proper error messages on the offending control, and the
device edit page swaps its inline matrix status selector for the new
shared MatrixStatusSegmented component.
Introduce a MatrixStatusSegmented component for the device-edit thing-model
matrices and an `includeAll` prop on EnableFlagSegmented so search/tool
panels no longer hand-roll the "All / Enable / Disable" option list.
Adopt the shared components across every Tool.vue and the alarm notify
page, dropping the redundant `enableFilterOptions` plumbing. Field-level
JSON validation in the alarm form moves into the form rules so errors
attach to the offending control instead of firing a generic toast.
Add an optional request handler so usePagedList can drive both
client-side filtering and server-paginated tables. Migrate the settings
list views (api, group, label, role, user, command, event) to consume
the composable, removing duplicated pagination/sort/search boilerplate.
- Add required validation for command type, call type, timeout, event type/level, menu type/level, temperature range
- Add phone (11-digit) and email format validation on user form
- Centralize NAME_PATTERN, AUTH_NAME_PATTERN, PHONE_PATTERN, EMAIL_PATTERN into formRuleUtil and align with backend patterns
- Apply centralized patterns across all settings edit forms (group, label, menu, resource, role, user, command, event, model config)
- Move `submitting = true` before `await validate()` in CommandEditForm,
EventEditForm, ProviderEditForm, and ModelConfigEditForm to close the
race window where two rapid clicks both pass validation and cause
duplicate-entry R500 errors.
- Add per-row inline validation for paramName (regex: 2-32 chars) and
paramCode (required) on command/event param tables, with red border
and tooltip error instead of only a console toast.
tests/views/ goes from a single AlarmNotify file to twenty — every
route-level list page (Device / Driver / Profile / Point / PointValue
plus the eleven Settings pages) now has a smoke test that mounts the
page with mocked APIs and asserts that the canonical list endpoint
fires once on setup.
Adds device-edit.test.ts for the matrix wizard: locks in the load
chain (getDeviceById → getDriverById/getProfileById) and the
profile-driven listPoint/listCommand/listEvent triple — the regression
spot the new thing-model-flow guardrail tries to catch statically.
A `tests/views/_helpers.ts` mountListPage helper folds the shared
boilerplate (i18n, memory router, fresh Pinia, layoutStubs +
ElButton/ElForm/ElPagination + a v-loading no-op directive) so each
file can stay focused on its own apiMocks block. Bumps testTimeout
to 30s globally — list-page transforms+imports compete with the
component pool under parallel execution and were flaking the default
5s on PointValue.
api-contracts.test.ts now covers command/event modules and routes them
through crud* shorthand mocks. sampleArgs becomes an explicit registry
(with the heuristic kept as a fallback) so newly added wrappers can pin
their argument shape without waiting for a regex collision to surface.
Adds two AI guardrails: (1) src/api/** is forbidden from declaring
`getXxxList*` collections, locking in the rename from the previous
commit; (2) toBeTruthy/toBeFalsy are flagged across `*.test.ts` and
`*.spec.ts` so the e2e suite can't silently slip in weak assertions —
destructive-delete migrates to the equivalent `not.toBe('')` form.
Picks up the previously untested `prettyJson` helper and broadens
thing-model-format-util tests to cover the new alarm formatters.
package.json gets `type-check` and `test:coverage` aliases that the
new guardrail expects.
CLAUDE.md §"API verb convention" reserves get* for single-record fetches
and list* for collections. Renames the seven offenders that survived the
prior pass:
getResourceListByRoleId → listResourceByRoleId
getResourceListByUserId → listResourceByUserId
getRoleListByResourceId → listRoleByResourceId
getRoleResourceList → listRoleResource
getRoleListByUserId → listRoleByUserId
getUserListByRoleId → listUserByRoleId
getRoleUserList → listRoleUser
getPointByIds → listPointByIds
All eight were collection-returning under a single-record verb, which
churned every call site whenever they were touched. URLs are unchanged.
Also lifts EventTable's local alarmType / alarmLevel formatters into
thingModelFormatUtil so EventHistory and EventList can reuse them
(replacing their previous render-the-raw-flag fallback). The alarm enum
is distinct from EventType — kept under separate names per the
backend's AlarmTypeFlagEnum.
Driver-bound device editing now refetches points/commands/events from the
profile when the user picks a different one — `listPointByDeviceId` was
returning the wrong scope, and `changeProfile()` was missing the point
sibling alongside command/event refresh. Drop the user-input commandCode /
eventCode form fields since the backend generates them from the name.
Adds a thing-model-flow guardrail that asserts the import shape (not raw
substrings) and the absence of `<el-form-item prop="*Code">` declarations,
so a future rename or refactor can't quietly bypass either constraint.
- Extend inline attribute matrix pattern from points to commands and events
with search, status filter, dirty tracking, and batch save
- Add command/event attribute and attribute-config REST API wrappers
- Introduce CommandInfoForm/EventInfoForm types and configSnapshot fields
- Replace embedded CommandList/EventList with native matrix tables in
DeviceEdit wizard steps 3-4
- Format JSON fields in history detail drawers with styled <pre> blocks
- Replace point config card picker with inline editable table (matrix)
supporting batch edit, dirty tracking, status filter, and bulk save
- Increase card grid density from 3 to 4 columns on large screens
- Refactor DriverCard status display with computed tag type and label
- Add custom icon images for command and event cards
- Hide status tag on embedded cards to reduce visual noise
- Replace table views with CommandCard/EventCard card components and drawer-based detail panels
- Simplify navigation: merge event-definition sub-menu into event group, remove standalone detail pages
- Migrate device from multi-profile (profileIds[]) to single-profile (profileId) model
- Add command/event tabs and wizard steps to device and profile detail/edit pages
- Support pre/next navigation in embedded tool components for wizard-style editing
- Add thingModelFormatUtil utility for model value formatting
- Update flag field types to accept string|number for flexible value handling
Sort imports alphabetically across all source files, reorder Vue
template attributes for consistency, clean up markdown table alignment,
merge adjacent type-only imports, and fix HTML indentation.
Aligns with the iot-dc3 backend rename: dc3_rule_state.event_id and
dc3_notify_history.event_id now ship as alarm_id, and the corresponding
JSON keys / TypeScript types follow.
- AlarmDetail: rule-state and notify-history detail panels now show
the field as "Alarm ID" with prop="alarmId".
- alarm.ts: RuleStateRecord.eventId / NotifyHistoryRecord.eventId →
alarmId.
- EventTable: add a Level column rendering dc3_entity_alarm.alarm_level_flag
(P0/P1/P2/P3) — the column already existed on the backend but the
dashboard never surfaced it. Tag color leans danger->success as the
level number grows so P0 lights up red.
- i18n: add settings.event.alarmLevel ("Level" / "级别") for the new column.
Extend AlertSource from 'device' | 'driver' to 'point' | 'device' | 'driver'
across all dashboard cards, event tables, and entity name resolution. Add
settingsPointEvent route, PointEvent.vue wrapper, and i18n translations.
Replace local nameMap/resolveNames with useEntityNames composable.
Remove the challenge-response double MD5 (MD5(MD5(password) + salt))
in favor of sending MD5(password) directly. The backend now verifies
with bcrypt instead of the old MD5 challenge-response protocol.
Use Loading/CircleCheck icons instead of the pulsing dot for the
thinking state. Add a white shimmer sweep effect on the Thinking
label while streaming, which stops when the response completes.
The component imports listRule/listNotify/listMessage/etc instead of
the old getXxxList names, but the test's hoisted vi.mock map still
declared the old function keys, so vitest auto-mock returned undefined
for every list spy. Rename the mock keys and the alarmMocks references
in expectations to match the renamed alarm.ts exports.
The contract snapshots embed the exact HTTP path each function calls.
After the get/list rename in commits cf97020 and dd13007, every
selectById -> getById and tree -> listTree path moved, so the snapshots
need a one-shot regeneration. 212 contract tests now pass.
Pin the get/list cardinality convention so frontend changes after this
refactor stay aligned with the backend (iot-dc3 AGENTS.md). Adds the
'API verb convention' section under Project Conventions with positive
and negative examples for src/api/* function names and HTTP paths.