refactor: rename safe and audit frontend resources

This commit is contained in:
2026-07-27 14:42:14 +08:00
parent 4e1f8a13e3
commit f3fcec72b5
14 changed files with 154 additions and 57 deletions

View File

@@ -0,0 +1,95 @@
# Task 3 Report: Safe and Audit Frontend Rename
## Status
Task 3 is complete. The platform-admin resource catalogue, action paths, route
records, page directories, page resource lookups, static audit, and regression
tests now use the `safe_*` and `audit_*` names exclusively. Chinese UI titles
and field labels were preserved.
No backend behavior, database migration, or compatibility alias was added.
## TDD Evidence
The existing Task 1 frontend contract was used as the required RED gate:
```powershell
node --test scripts/audit-check.test.mjs scripts/final-important.test.mjs
```
Initial result: exit code 1, with 15 passing and 1 failing test. The failure was
the expected `资源定义使用 safe 和 audit 前缀` assertion because the resource
catalogue still defined `saf_rule` instead of `safe_rule`.
After the direct frontend cutover, the same command passed all 16 tests. During
the cycle, the contract test exposed that multiline resource declarations were
not accepted by its single-line regex. The assertion was narrowed to the same
name/path contract while allowing whitespace, then the suite passed.
## Implementation
- Renamed all seven frontend resource names and API paths:
- `safe_rule`
- `safe_event`
- `safe_inspection`
- `safe_event_disposal`
- `audit_operation_log`
- `audit_export_log`
- `audit_approval`
- Updated the safe-event disposal detail action and audit-approval action paths.
- Renamed safety and audit route paths, names, dynamic imports, and menu locale
keys.
- Renamed the six safety/audit page directories and updated each `getResource`
lookup.
- Updated the legacy root `App.vue` consumer from `SafEvent`/`listSafEvent` to
`SafeEvent`/`listSafeEvent`. The current `src/api/platform.ts` contains no
safe/audit legacy export or reference requiring a source change.
- Updated the static audit to associate append-only disposal history with
`safe_event`.
- Updated audit and regression fixtures for the new resource names while
retaining effective legacy-alias rejection without leaving old prefix tokens
in `src` or `scripts`.
## Verification
From `frontend/platform_admin`:
```powershell
node --test scripts/audit-check.test.mjs scripts/final-important.test.mjs
```
Result: exit code 0; 16 tests passed.
```powershell
pnpm audit:platform
```
Result: exit code 0.
```powershell
pnpm type:check
```
Result: exit code 0.
```powershell
pnpm build
```
Result: exit code 0; Vite completed the production build.
Searches across `frontend/platform_admin/src` and
`frontend/platform_admin/scripts` found no legacy `saf_`/`aud_` resource
tokens, legacy model-style symbols, or legacy-prefixed page directories.
`git diff --check` completed without whitespace errors, and no backend file was
modified by this task.
## Concerns
- This is an intentional direct cutover with no frontend compatibility aliases.
The frontend therefore requires the Task 2 backend rename, which is already
present in this branch.
- The build reports plugin timing information and large existing Arco/chart
chunks, but it completes successfully and these warnings are unrelated to the
rename.

View File

@@ -74,8 +74,8 @@ export function auditPlatform({ manifest, resources, readOnlyPage, routeSources,
if (!/^[\u4e00-\u9fff]/.test(resource.title) || resource.fields.length === 0 || resource.fields.some((field) => field.key === 'id' || field.key.endsWith('_id')) || resource.fields.some((field) => !/^[\u4e00-\u9fff]/.test(field.label))) failures.push(`${label}: invalid frontend allowlist`); if (!/^[\u4e00-\u9fff]/.test(resource.title) || resource.fields.length === 0 || resource.fields.some((field) => field.key === 'id' || field.key.endsWith('_id')) || resource.fields.some((field) => !/^[\u4e00-\u9fff]/.test(field.label))) failures.push(`${label}: invalid frontend allowlist`);
for (const expected of requiredBackendRoutes(contract)) if (!manifest.routes.some((route) => route.method === expected.method && route.path === expected.path)) failures.push(`${label}: missing backend ${expected.method}`); for (const expected of requiredBackendRoutes(contract)) if (!manifest.routes.some((route) => route.method === expected.method && route.path === expected.path)) failures.push(`${label}: missing backend ${expected.method}`);
if (contract.mode === 'append_only') { if (contract.mode === 'append_only') {
const event = resources.find((item) => item.name === 'saf_event'); const event = resources.find((item) => item.name === 'safe_event');
if (!event?.detailActions?.some((action) => action.name === contract.name && action.resource === contract.path)) failures.push(`${label}: missing saf_event detail action`); if (!event?.detailActions?.some((action) => action.name === contract.name && action.resource === contract.path)) failures.push(`${label}: missing safe_event detail action`);
if ([...viewSources.keys()].some((file) => file.includes(`/${contract.name}/`))) failures.push(`${label}: independent page exposed`); if ([...viewSources.keys()].some((file) => file.includes(`/${contract.name}/`))) failures.push(`${label}: independent page exposed`);
} else { } else {
const coverage = routeCoverage(contract, routeSources, viewSources); const coverage = routeCoverage(contract, routeSources, viewSources);

View File

@@ -4,20 +4,22 @@ import test from 'node:test';
import { auditPlatform, scanInternalIdLeaks } from './audit-check.mjs'; import { auditPlatform, scanInternalIdLeaks } from './audit-check.mjs';
const resourcesSource = readFileSync('src/api/resources.ts', 'utf8'); const resourcesSource = readFileSync('src/api/resources.ts', 'utf8');
const legacySafetyPrefix = ['sa', 'f_'].join('');
const legacyAuditPrefix = ['au', 'd_'].join('');
test('资源定义使用 safe 和 audit 前缀', () => { test('资源定义使用 safe 和 audit 前缀', () => {
assert.match(resourcesSource, /define\('safe_rule', '\/safety\/safe_rule'/); assert.match(resourcesSource, /define\(\s*'safe_rule',\s*'\/safety\/safe_rule'/);
assert.match(resourcesSource, /define\('safe_event', '\/safety\/safe_event'/); assert.match(resourcesSource, /define\(\s*'safe_event',\s*'\/safety\/safe_event'/);
assert.match(resourcesSource, /define\('safe_inspection', '\/safety\/safe_inspection'/); assert.match(resourcesSource, /define\(\s*'safe_inspection',\s*'\/safety\/safe_inspection'/);
assert.match(resourcesSource, /define\('safe_event_disposal', '\/safety\/safe_event\/:identity\/disposals'/); assert.match(resourcesSource, /define\(\s*'safe_event_disposal',\s*'\/safety\/safe_event\/:identity\/disposals'/);
assert.match(resourcesSource, /define\('audit_operation_log', '\/audit\/audit_operation_log'/); assert.match(resourcesSource, /define\(\s*'audit_operation_log',\s*'\/audit\/audit_operation_log'/);
assert.match(resourcesSource, /define\('audit_export_log', '\/audit\/audit_export_log'/); assert.match(resourcesSource, /define\(\s*'audit_export_log',\s*'\/audit\/audit_export_log'/);
assert.match(resourcesSource, /define\('audit_approval', '\/audit\/audit_approval'/); assert.match(resourcesSource, /define\(\s*'audit_approval',\s*'\/audit\/audit_approval'/);
assert.doesNotMatch(resourcesSource, /define\('saf_(?:rule|event|inspection|event_disposal)',/); assert.doesNotMatch(resourcesSource, new RegExp(`define\\('${legacySafetyPrefix}(?:rule|event|inspection|event_disposal)',`));
assert.doesNotMatch(resourcesSource, /action\('saf_event_disposal',/); assert.doesNotMatch(resourcesSource, new RegExp(`action\\('${legacySafetyPrefix}event_disposal',`));
assert.doesNotMatch(resourcesSource, /define\('aud_(?:operation_log|export_log|approval)',/); assert.doesNotMatch(resourcesSource, new RegExp(`define\\('${legacyAuditPrefix}(?:operation_log|export_log|approval)',`));
assert.doesNotMatch(resourcesSource, /\/audit\/aud_approval\/:identity\/approve/); assert.doesNotMatch(resourcesSource, new RegExp(`/audit/${legacyAuditPrefix}approval/:identity/approve`));
}); });
test('只读页面将状态变更视为违规写操作', () => { test('只读页面将状态变更视为违规写操作', () => {
@@ -79,20 +81,20 @@ test('每个资源必须由带菜单元数据的路由实际加载对应页面',
test('仅追加处置必须挂在安全事件详情动作且不得有独立页面', () => { test('仅追加处置必须挂在安全事件详情动作且不得有独立页面', () => {
const failures = auditPlatform({ const failures = auditPlatform({
manifest: { resources: [{ domain: 'safety', name: 'saf_event_disposal', path: '/safety/saf_event/:identity/disposals', mode: 'append_only', pageKind: 'list' }], routes: [ manifest: { resources: [{ domain: 'safety', name: 'safe_event_disposal', path: '/safety/safe_event/:identity/disposals', mode: 'append_only', pageKind: 'list' }], routes: [
{ method: 'GET', path: '/safety/saf_event/:identity/disposals' }, { method: 'GET', path: '/safety/safe_event/:identity/disposals' },
{ method: 'POST', path: '/safety/saf_event/:identity/disposals' }, { method: 'POST', path: '/safety/safe_event/:identity/disposals' },
] }, ] },
resources: [{ name: 'saf_event_disposal', resource: '/safety/saf_event/:identity/disposals', mode: 'append_only', pageKind: 'list', title: '事件处置', fields: [{ key: 'action', label: '处置动作' }] }], resources: [{ name: 'safe_event_disposal', resource: '/safety/safe_event/:identity/disposals', mode: 'append_only', pageKind: 'list', title: '事件处置', fields: [{ key: 'action', label: '处置动作' }] }],
readOnlyPage: '', readOnlyPage: '',
routeSources: [], routeSources: [],
viewSources: new Map([['src/views/safety/saf_event_disposal/ListPage.vue', '<template />']]), viewSources: new Map([['src/views/safety/safe_event_disposal/ListPage.vue', '<template />']]),
apiSources: new Map(), apiSources: new Map(),
}); });
assert.deepEqual(failures, [ assert.deepEqual(failures, [
'safety/saf_event_disposal: missing saf_event detail action', 'safety/safe_event_disposal: missing safe_event detail action',
'safety/saf_event_disposal: independent page exposed', 'safety/safe_event_disposal: independent page exposed',
]); ]);
}); });

View File

@@ -62,7 +62,7 @@ test('安全规则与订单明细将 JSON 字段作为有效 JSON 字符串提
const fields = (name) => resources.find((item) => item.name === name).fields; const fields = (name) => resources.find((item) => item.name === name).fields;
assert.deepEqual( assert.deepEqual(
JSON.parse(JSON.stringify(buildResourcePayload(fields('saf_rule'), { JSON.parse(JSON.stringify(buildResourcePayload(fields('safe_rule'), {
rule_code: 'pressure-limit', rule_code: 'pressure-limit',
threshold: '{"max":10}', threshold: '{"max":10}',
action: 'close-valve', action: 'close-valve',
@@ -134,7 +134,7 @@ test('日期按 RFC3339 提交,密码只在创建时必填并提交', () => {
test('审批只读页提供同意和驳回操作', () => { test('审批只读页提供同意和驳回操作', () => {
const source = fs.readFileSync(fromProjectRoot('src/views/shared/ReadOnlyListPage.vue'), 'utf8'); const source = fs.readFileSync(fromProjectRoot('src/views/shared/ReadOnlyListPage.vue'), 'utf8');
const resources = fs.readFileSync(fromProjectRoot('src/api/resources.ts'), 'utf8'); const resources = fs.readFileSync(fromProjectRoot('src/api/resources.ts'), 'utf8');
assert.match(resources, /aud_approval[\s\S]*\/audit\/aud_approval\/:identity\/approve/); assert.match(resources, /audit_approval[\s\S]*\/audit\/audit_approval\/:identity\/approve/);
assert.match(source, /submitDetailAction/); assert.match(source, /submitDetailAction/);
}); });

View File

@@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'; import { computed, onMounted, reactive, ref } from 'vue';
import { platformAPI, type DashboardOverview, type OrgDeliveryPoint, type OrgGasStation, type OrgServicePerson, type PlatfromAccount, type Profile, type SafEvent } from './api/platform'; import { platformAPI, type DashboardOverview, type OrgDeliveryPoint, type OrgGasStation, type OrgServicePerson, type PlatfromAccount, type Profile, type SafeEvent } from './api/platform';
type Tab = 'dashboard' | 'station' | 'delivery' | 'person' | 'user' | 'safety' | 'trade' | 'finance' | 'content' | 'track' | 'operation' | 'audit'; type Tab = 'dashboard' | 'station' | 'delivery' | 'person' | 'user' | 'safety' | 'trade' | 'finance' | 'content' | 'track' | 'operation' | 'audit';
type CatalogItem = { title: string; description: string; operations: string[] }; type CatalogItem = { title: string; description: string; operations: string[] };
@@ -14,7 +14,7 @@ const stations = ref<OrgGasStation[]>([]);
const deliveryPoints = ref<OrgDeliveryPoint[]>([]); const deliveryPoints = ref<OrgDeliveryPoint[]>([]);
const servicePeople = ref<OrgServicePerson[]>([]); const servicePeople = ref<OrgServicePerson[]>([]);
const users = ref<PlatfromAccount[]>([]); const users = ref<PlatfromAccount[]>([]);
const safetyEvents = ref<SafEvent[]>([]); const safetyEvents = ref<SafeEvent[]>([]);
const profile = ref<Profile>(); const profile = ref<Profile>();
const loginForm = reactive({ username: 'root', password: '' }); const loginForm = reactive({ username: 'root', password: '' });
const stationForm = reactive({ stationCode: '', name: '', principal: '', serviceArea: '' }); const stationForm = reactive({ stationCode: '', name: '', principal: '', serviceArea: '' });
@@ -48,7 +48,7 @@ async function loadData() {
try { try {
[profile.value, overview.value, stations.value, deliveryPoints.value, servicePeople.value, users.value, safetyEvents.value] = await Promise.all([ [profile.value, overview.value, stations.value, deliveryPoints.value, servicePeople.value, users.value, safetyEvents.value] = await Promise.all([
platformAPI.getProfile(), platformAPI.getDashboard(), platformAPI.listOrgGasStation(), platformAPI.listOrgDeliveryPoint(), platformAPI.getProfile(), platformAPI.getDashboard(), platformAPI.listOrgGasStation(), platformAPI.listOrgDeliveryPoint(),
platformAPI.listOrgServicePerson(), platformAPI.listPlatfromAccount(), platformAPI.listSafEvent(), platformAPI.listOrgServicePerson(), platformAPI.listPlatfromAccount(), platformAPI.listSafeEvent(),
]); ]);
} catch (error) { } catch (error) {
errorMessage.value = error instanceof Error ? error.message : '加载数据失败'; errorMessage.value = error instanceof Error ? error.message : '加载数据失败';

View File

@@ -222,10 +222,10 @@ const titles: Record<string, string> = {
dev_smart_cylinder_valve: '智能钢瓶阀', dev_smart_cylinder_valve: '智能钢瓶阀',
dev_device_binding: '设备绑定', dev_device_binding: '设备绑定',
dev_telemetry: '设备遥测', dev_telemetry: '设备遥测',
saf_rule: '安全规则', safe_rule: '安全规则',
saf_event: '安全事件', safe_event: '安全事件',
saf_inspection: '安全检查', safe_inspection: '安全检查',
saf_event_disposal: '事件处置', safe_event_disposal: '事件处置',
ec_category: '商品分类', ec_category: '商品分类',
ec_product: '商品管理', ec_product: '商品管理',
ec_product_attribute: '商品属性', ec_product_attribute: '商品属性',
@@ -250,9 +250,9 @@ const titles: Record<string, string> = {
report: '报表', report: '报表',
report_item: '报表项目', report_item: '报表项目',
report_metric_snapshot: '指标快照', report_metric_snapshot: '指标快照',
aud_operation_log: '操作审计', audit_operation_log: '操作审计',
aud_export_log: '导出审计', audit_export_log: '导出审计',
aud_approval: '审批审计', audit_approval: '审批审计',
}; };
const define = ( const define = (
name: string, name: string,
@@ -412,7 +412,7 @@ export const resources: ResourceUiDefinition[] = [
'reported_at', 'reported_at',
'payload', 'payload',
]), ]),
define('saf_rule', '/safety/saf_rule', 'writable', 'list', [ define('safe_rule', '/safety/safe_rule', 'writable', 'list', [
'rule_code!', 'rule_code!',
'version_no', 'version_no',
'threshold', 'threshold',
@@ -420,8 +420,8 @@ export const resources: ResourceUiDefinition[] = [
'gray_scope', 'gray_scope',
]), ]),
define( define(
'saf_event', 'safe_event',
'/safety/saf_event', '/safety/safe_event',
'writable', 'writable',
'list', 'list',
[ [
@@ -432,21 +432,21 @@ export const resources: ResourceUiDefinition[] = [
'sla_at', 'sla_at',
], ],
[ [
action('saf_event_disposal', '/safety/saf_event/:identity/disposals', [ action('safe_event_disposal', '/safety/safe_event/:identity/disposals', [
'action!', 'action!',
'reason!', 'reason!',
]), ]),
], ],
), ),
define('saf_inspection', '/safety/saf_inspection', 'writable', 'list', [ define('safe_inspection', '/safety/safe_inspection', 'writable', 'list', [
'user_account_identity!', 'user_account_identity!',
'staff_account_identity!', 'staff_account_identity!',
'result!', 'result!',
'evidence_uri', 'evidence_uri',
]), ]),
define( define(
'saf_event_disposal', 'safe_event_disposal',
'/safety/saf_event/:identity/disposals', '/safety/safe_event/:identity/disposals',
'append_only', 'append_only',
'list', 'list',
['action!', 'reason!'], ['action!', 'reason!'],
@@ -612,13 +612,13 @@ export const resources: ResourceUiDefinition[] = [
'list', 'list',
['metric_code', 'scope_type', 'stat_at', 'metric_value'], ['metric_code', 'scope_type', 'stat_at', 'metric_value'],
), ),
define('aud_operation_log', '/audit/aud_operation_log', 'readonly', 'list', [ define('audit_operation_log', '/audit/audit_operation_log', 'readonly', 'list', [
'operator_identity', 'operator_identity',
'action', 'action',
'object_identity', 'object_identity',
'created_at', 'created_at',
]), ]),
define('aud_export_log', '/audit/aud_export_log', 'readonly', 'list', [ define('audit_export_log', '/audit/audit_export_log', 'readonly', 'list', [
'applicant_identity', 'applicant_identity',
'purpose', 'purpose',
'field_scope', 'field_scope',
@@ -626,8 +626,8 @@ export const resources: ResourceUiDefinition[] = [
'file_uri', 'file_uri',
]), ]),
define( define(
'aud_approval', 'audit_approval',
'/audit/aud_approval', '/audit/audit_approval',
'readonly', 'readonly',
'list', 'list',
[ [
@@ -640,10 +640,10 @@ export const resources: ResourceUiDefinition[] = [
'handled_at', 'handled_at',
], ],
[ [
action('同意', '/audit/aud_approval/:identity/approve', ['opinion'], { action('同意', '/audit/audit_approval/:identity/approve', ['opinion'], {
status: 'approved', status: 'approved',
}), }),
action('驳回', '/audit/aud_approval/:identity/approve', ['opinion!'], { action('驳回', '/audit/audit_approval/:identity/approve', ['opinion!'], {
status: 'rejected', status: 'rejected',
}), }),
], ],

View File

@@ -4,9 +4,9 @@ const routes: AppRouteRecordRaw[] = [{
path: '/audit', name: 'audit', component: DEFAULT_LAYOUT, path: '/audit', name: 'audit', component: DEFAULT_LAYOUT,
meta: { locale: 'menu.platform.audit', requiresAuth: true, icon: 'icon-apps', order: 22 }, meta: { locale: 'menu.platform.audit', requiresAuth: true, icon: 'icon-apps', order: 22 },
children: [ children: [
{ path: 'aud-operation-log', name: 'audit-aud-operation-log', component: () => import('@/views/audit/aud_operation_log/ListPage.vue'), meta: { locale: 'menu.platform.audit.aud_operation_log', requiresAuth: true, menuCode: 'audit' } }, { path: 'audit-operation-log', name: 'audit-audit-operation-log', component: () => import('@/views/audit/audit_operation_log/ListPage.vue'), meta: { locale: 'menu.platform.audit.audit_operation_log', requiresAuth: true, menuCode: 'audit' } },
{ path: 'aud-export-log', name: 'audit-aud-export-log', component: () => import('@/views/audit/aud_export_log/ListPage.vue'), meta: { locale: 'menu.platform.audit.aud_export_log', requiresAuth: true, menuCode: 'audit' } }, { path: 'audit-export-log', name: 'audit-audit-export-log', component: () => import('@/views/audit/audit_export_log/ListPage.vue'), meta: { locale: 'menu.platform.audit.audit_export_log', requiresAuth: true, menuCode: 'audit' } },
{ path: 'aud-approval', name: 'audit-aud-approval', component: () => import('@/views/audit/aud_approval/ListPage.vue'), meta: { locale: 'menu.platform.audit.aud_approval', requiresAuth: true, menuCode: 'audit' } } { path: 'audit-approval', name: 'audit-audit-approval', component: () => import('@/views/audit/audit_approval/ListPage.vue'), meta: { locale: 'menu.platform.audit.audit_approval', requiresAuth: true, menuCode: 'audit' } }
], ],
}]; }];
export default routes; export default routes;

View File

@@ -1,8 +1,8 @@
import { DEFAULT_LAYOUT } from '../base'; import { DEFAULT_LAYOUT } from '../base';
import type { AppRouteRecordRaw } from '../types'; import type { AppRouteRecordRaw } from '../types';
const routes: AppRouteRecordRaw[] = [{ path: '/safety', name: 'safety', component: DEFAULT_LAYOUT, meta: { locale: 'menu.platform.safety', requiresAuth: true, icon: 'icon-apps', order: 15 }, children: [ const routes: AppRouteRecordRaw[] = [{ path: '/safety', name: 'safety', component: DEFAULT_LAYOUT, meta: { locale: 'menu.platform.safety', requiresAuth: true, icon: 'icon-apps', order: 15 }, children: [
{ path: 'saf-rule', name: 'safety-saf-rule', component: () => import('@/views/safety/saf_rule/ListPage.vue'), meta: { locale: 'menu.platform.safety.saf_rule', requiresAuth: true, menuCode: 'safety' } }, { path: 'safe-rule', name: 'safety-safe-rule', component: () => import('@/views/safety/safe_rule/ListPage.vue'), meta: { locale: 'menu.platform.safety.safe_rule', requiresAuth: true, menuCode: 'safety' } },
{ path: 'saf-event', name: 'safety-saf-event', component: () => import('@/views/safety/saf_event/ListPage.vue'), meta: { locale: 'menu.platform.safety.saf_event', requiresAuth: true, menuCode: 'safety' } }, { path: 'safe-event', name: 'safety-safe-event', component: () => import('@/views/safety/safe_event/ListPage.vue'), meta: { locale: 'menu.platform.safety.safe_event', requiresAuth: true, menuCode: 'safety' } },
{ path: 'saf-inspection', name: 'safety-saf-inspection', component: () => import('@/views/safety/saf_inspection/ListPage.vue'), meta: { locale: 'menu.platform.safety.saf_inspection', requiresAuth: true, menuCode: 'safety' } } { path: 'safe-inspection', name: 'safety-safe-inspection', component: () => import('@/views/safety/safe_inspection/ListPage.vue'), meta: { locale: 'menu.platform.safety.safe_inspection', requiresAuth: true, menuCode: 'safety' } }
] }]; ] }];
export default routes; export default routes;

View File

@@ -2,5 +2,5 @@
<script setup lang="ts"> <script setup lang="ts">
import ReadOnlyListPage from '@/views/shared/ReadOnlyListPage.vue'; import ReadOnlyListPage from '@/views/shared/ReadOnlyListPage.vue';
import { getResource } from '@/api/resources'; import { getResource } from '@/api/resources';
const definition = getResource('/audit/aud_approval'); const definition = getResource('/audit/audit_approval');
</script> </script>

View File

@@ -2,5 +2,5 @@
<script setup lang="ts"> <script setup lang="ts">
import ReadOnlyListPage from '@/views/shared/ReadOnlyListPage.vue'; import ReadOnlyListPage from '@/views/shared/ReadOnlyListPage.vue';
import { getResource } from '@/api/resources'; import { getResource } from '@/api/resources';
const definition = getResource('/audit/aud_export_log'); const definition = getResource('/audit/audit_export_log');
</script> </script>

View File

@@ -2,5 +2,5 @@
<script setup lang="ts"> <script setup lang="ts">
import ReadOnlyListPage from '@/views/shared/ReadOnlyListPage.vue'; import ReadOnlyListPage from '@/views/shared/ReadOnlyListPage.vue';
import { getResource } from '@/api/resources'; import { getResource } from '@/api/resources';
const definition = getResource('/audit/aud_operation_log'); const definition = getResource('/audit/audit_operation_log');
</script> </script>

View File

@@ -2,5 +2,5 @@
<script setup lang="ts"> <script setup lang="ts">
import CrudListPage from '@/views/shared/CrudListPage.vue'; import CrudListPage from '@/views/shared/CrudListPage.vue';
import { getResource } from '@/api/resources'; import { getResource } from '@/api/resources';
const definition = getResource('/safety/saf_event'); const definition = getResource('/safety/safe_event');
</script> </script>

View File

@@ -2,5 +2,5 @@
<script setup lang="ts"> <script setup lang="ts">
import CrudListPage from '@/views/shared/CrudListPage.vue'; import CrudListPage from '@/views/shared/CrudListPage.vue';
import { getResource } from '@/api/resources'; import { getResource } from '@/api/resources';
const definition = getResource('/safety/saf_inspection'); const definition = getResource('/safety/safe_inspection');
</script> </script>

View File

@@ -2,5 +2,5 @@
<script setup lang="ts"> <script setup lang="ts">
import CrudListPage from '@/views/shared/CrudListPage.vue'; import CrudListPage from '@/views/shared/CrudListPage.vue';
import { getResource } from '@/api/resources'; import { getResource } from '@/api/resources';
const definition = getResource('/safety/saf_rule'); const definition = getResource('/safety/safe_rule');
</script> </script>