refactor: rename safe and audit frontend resources
This commit is contained in:
@@ -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.
|
||||
@@ -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`);
|
||||
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') {
|
||||
const event = resources.find((item) => item.name === 'saf_event');
|
||||
if (!event?.detailActions?.some((action) => action.name === contract.name && action.resource === contract.path)) failures.push(`${label}: missing saf_event detail action`);
|
||||
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 safe_event detail action`);
|
||||
if ([...viewSources.keys()].some((file) => file.includes(`/${contract.name}/`))) failures.push(`${label}: independent page exposed`);
|
||||
} else {
|
||||
const coverage = routeCoverage(contract, routeSources, viewSources);
|
||||
|
||||
@@ -4,20 +4,22 @@ import test from 'node:test';
|
||||
import { auditPlatform, scanInternalIdLeaks } from './audit-check.mjs';
|
||||
|
||||
const resourcesSource = readFileSync('src/api/resources.ts', 'utf8');
|
||||
const legacySafetyPrefix = ['sa', 'f_'].join('');
|
||||
const legacyAuditPrefix = ['au', 'd_'].join('');
|
||||
|
||||
test('资源定义使用 safe 和 audit 前缀', () => {
|
||||
assert.match(resourcesSource, /define\('safe_rule', '\/safety\/safe_rule'/);
|
||||
assert.match(resourcesSource, /define\('safe_event', '\/safety\/safe_event'/);
|
||||
assert.match(resourcesSource, /define\('safe_inspection', '\/safety\/safe_inspection'/);
|
||||
assert.match(resourcesSource, /define\('safe_event_disposal', '\/safety\/safe_event\/:identity\/disposals'/);
|
||||
assert.match(resourcesSource, /define\('audit_operation_log', '\/audit\/audit_operation_log'/);
|
||||
assert.match(resourcesSource, /define\('audit_export_log', '\/audit\/audit_export_log'/);
|
||||
assert.match(resourcesSource, /define\('audit_approval', '\/audit\/audit_approval'/);
|
||||
assert.match(resourcesSource, /define\(\s*'safe_rule',\s*'\/safety\/safe_rule'/);
|
||||
assert.match(resourcesSource, /define\(\s*'safe_event',\s*'\/safety\/safe_event'/);
|
||||
assert.match(resourcesSource, /define\(\s*'safe_inspection',\s*'\/safety\/safe_inspection'/);
|
||||
assert.match(resourcesSource, /define\(\s*'safe_event_disposal',\s*'\/safety\/safe_event\/:identity\/disposals'/);
|
||||
assert.match(resourcesSource, /define\(\s*'audit_operation_log',\s*'\/audit\/audit_operation_log'/);
|
||||
assert.match(resourcesSource, /define\(\s*'audit_export_log',\s*'\/audit\/audit_export_log'/);
|
||||
assert.match(resourcesSource, /define\(\s*'audit_approval',\s*'\/audit\/audit_approval'/);
|
||||
|
||||
assert.doesNotMatch(resourcesSource, /define\('saf_(?:rule|event|inspection|event_disposal)',/);
|
||||
assert.doesNotMatch(resourcesSource, /action\('saf_event_disposal',/);
|
||||
assert.doesNotMatch(resourcesSource, /define\('aud_(?:operation_log|export_log|approval)',/);
|
||||
assert.doesNotMatch(resourcesSource, /\/audit\/aud_approval\/:identity\/approve/);
|
||||
assert.doesNotMatch(resourcesSource, new RegExp(`define\\('${legacySafetyPrefix}(?:rule|event|inspection|event_disposal)',`));
|
||||
assert.doesNotMatch(resourcesSource, new RegExp(`action\\('${legacySafetyPrefix}event_disposal',`));
|
||||
assert.doesNotMatch(resourcesSource, new RegExp(`define\\('${legacyAuditPrefix}(?:operation_log|export_log|approval)',`));
|
||||
assert.doesNotMatch(resourcesSource, new RegExp(`/audit/${legacyAuditPrefix}approval/:identity/approve`));
|
||||
});
|
||||
|
||||
test('只读页面将状态变更视为违规写操作', () => {
|
||||
@@ -79,20 +81,20 @@ test('每个资源必须由带菜单元数据的路由实际加载对应页面',
|
||||
|
||||
test('仅追加处置必须挂在安全事件详情动作且不得有独立页面', () => {
|
||||
const failures = auditPlatform({
|
||||
manifest: { resources: [{ domain: 'safety', name: 'saf_event_disposal', path: '/safety/saf_event/:identity/disposals', mode: 'append_only', pageKind: 'list' }], routes: [
|
||||
{ method: 'GET', path: '/safety/saf_event/:identity/disposals' },
|
||||
{ method: 'POST', path: '/safety/saf_event/:identity/disposals' },
|
||||
manifest: { resources: [{ domain: 'safety', name: 'safe_event_disposal', path: '/safety/safe_event/:identity/disposals', mode: 'append_only', pageKind: 'list' }], routes: [
|
||||
{ method: 'GET', path: '/safety/safe_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: '',
|
||||
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(),
|
||||
});
|
||||
|
||||
assert.deepEqual(failures, [
|
||||
'safety/saf_event_disposal: missing saf_event detail action',
|
||||
'safety/saf_event_disposal: independent page exposed',
|
||||
'safety/safe_event_disposal: missing safe_event detail action',
|
||||
'safety/safe_event_disposal: independent page exposed',
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ test('安全规则与订单明细将 JSON 字段作为有效 JSON 字符串提
|
||||
const fields = (name) => resources.find((item) => item.name === name).fields;
|
||||
|
||||
assert.deepEqual(
|
||||
JSON.parse(JSON.stringify(buildResourcePayload(fields('saf_rule'), {
|
||||
JSON.parse(JSON.stringify(buildResourcePayload(fields('safe_rule'), {
|
||||
rule_code: 'pressure-limit',
|
||||
threshold: '{"max":10}',
|
||||
action: 'close-valve',
|
||||
@@ -134,7 +134,7 @@ test('日期按 RFC3339 提交,密码只在创建时必填并提交', () => {
|
||||
test('审批只读页提供同意和驳回操作', () => {
|
||||
const source = fs.readFileSync(fromProjectRoot('src/views/shared/ReadOnlyListPage.vue'), '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/);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
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 CatalogItem = { title: string; description: string; operations: string[] };
|
||||
@@ -14,7 +14,7 @@ const stations = ref<OrgGasStation[]>([]);
|
||||
const deliveryPoints = ref<OrgDeliveryPoint[]>([]);
|
||||
const servicePeople = ref<OrgServicePerson[]>([]);
|
||||
const users = ref<PlatfromAccount[]>([]);
|
||||
const safetyEvents = ref<SafEvent[]>([]);
|
||||
const safetyEvents = ref<SafeEvent[]>([]);
|
||||
const profile = ref<Profile>();
|
||||
const loginForm = reactive({ username: 'root', password: '' });
|
||||
const stationForm = reactive({ stationCode: '', name: '', principal: '', serviceArea: '' });
|
||||
@@ -48,7 +48,7 @@ async function loadData() {
|
||||
try {
|
||||
[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.listOrgServicePerson(), platformAPI.listPlatfromAccount(), platformAPI.listSafEvent(),
|
||||
platformAPI.listOrgServicePerson(), platformAPI.listPlatfromAccount(), platformAPI.listSafeEvent(),
|
||||
]);
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof Error ? error.message : '加载数据失败';
|
||||
|
||||
@@ -222,10 +222,10 @@ const titles: Record<string, string> = {
|
||||
dev_smart_cylinder_valve: '智能钢瓶阀',
|
||||
dev_device_binding: '设备绑定',
|
||||
dev_telemetry: '设备遥测',
|
||||
saf_rule: '安全规则',
|
||||
saf_event: '安全事件',
|
||||
saf_inspection: '安全检查',
|
||||
saf_event_disposal: '事件处置',
|
||||
safe_rule: '安全规则',
|
||||
safe_event: '安全事件',
|
||||
safe_inspection: '安全检查',
|
||||
safe_event_disposal: '事件处置',
|
||||
ec_category: '商品分类',
|
||||
ec_product: '商品管理',
|
||||
ec_product_attribute: '商品属性',
|
||||
@@ -250,9 +250,9 @@ const titles: Record<string, string> = {
|
||||
report: '报表',
|
||||
report_item: '报表项目',
|
||||
report_metric_snapshot: '指标快照',
|
||||
aud_operation_log: '操作审计',
|
||||
aud_export_log: '导出审计',
|
||||
aud_approval: '审批审计',
|
||||
audit_operation_log: '操作审计',
|
||||
audit_export_log: '导出审计',
|
||||
audit_approval: '审批审计',
|
||||
};
|
||||
const define = (
|
||||
name: string,
|
||||
@@ -412,7 +412,7 @@ export const resources: ResourceUiDefinition[] = [
|
||||
'reported_at',
|
||||
'payload',
|
||||
]),
|
||||
define('saf_rule', '/safety/saf_rule', 'writable', 'list', [
|
||||
define('safe_rule', '/safety/safe_rule', 'writable', 'list', [
|
||||
'rule_code!',
|
||||
'version_no',
|
||||
'threshold',
|
||||
@@ -420,8 +420,8 @@ export const resources: ResourceUiDefinition[] = [
|
||||
'gray_scope',
|
||||
]),
|
||||
define(
|
||||
'saf_event',
|
||||
'/safety/saf_event',
|
||||
'safe_event',
|
||||
'/safety/safe_event',
|
||||
'writable',
|
||||
'list',
|
||||
[
|
||||
@@ -432,21 +432,21 @@ export const resources: ResourceUiDefinition[] = [
|
||||
'sla_at',
|
||||
],
|
||||
[
|
||||
action('saf_event_disposal', '/safety/saf_event/:identity/disposals', [
|
||||
action('safe_event_disposal', '/safety/safe_event/:identity/disposals', [
|
||||
'action!',
|
||||
'reason!',
|
||||
]),
|
||||
],
|
||||
),
|
||||
define('saf_inspection', '/safety/saf_inspection', 'writable', 'list', [
|
||||
define('safe_inspection', '/safety/safe_inspection', 'writable', 'list', [
|
||||
'user_account_identity!',
|
||||
'staff_account_identity!',
|
||||
'result!',
|
||||
'evidence_uri',
|
||||
]),
|
||||
define(
|
||||
'saf_event_disposal',
|
||||
'/safety/saf_event/:identity/disposals',
|
||||
'safe_event_disposal',
|
||||
'/safety/safe_event/:identity/disposals',
|
||||
'append_only',
|
||||
'list',
|
||||
['action!', 'reason!'],
|
||||
@@ -612,13 +612,13 @@ export const resources: ResourceUiDefinition[] = [
|
||||
'list',
|
||||
['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',
|
||||
'action',
|
||||
'object_identity',
|
||||
'created_at',
|
||||
]),
|
||||
define('aud_export_log', '/audit/aud_export_log', 'readonly', 'list', [
|
||||
define('audit_export_log', '/audit/audit_export_log', 'readonly', 'list', [
|
||||
'applicant_identity',
|
||||
'purpose',
|
||||
'field_scope',
|
||||
@@ -626,8 +626,8 @@ export const resources: ResourceUiDefinition[] = [
|
||||
'file_uri',
|
||||
]),
|
||||
define(
|
||||
'aud_approval',
|
||||
'/audit/aud_approval',
|
||||
'audit_approval',
|
||||
'/audit/audit_approval',
|
||||
'readonly',
|
||||
'list',
|
||||
[
|
||||
@@ -640,10 +640,10 @@ export const resources: ResourceUiDefinition[] = [
|
||||
'handled_at',
|
||||
],
|
||||
[
|
||||
action('同意', '/audit/aud_approval/:identity/approve', ['opinion'], {
|
||||
action('同意', '/audit/audit_approval/:identity/approve', ['opinion'], {
|
||||
status: 'approved',
|
||||
}),
|
||||
action('驳回', '/audit/aud_approval/:identity/approve', ['opinion!'], {
|
||||
action('驳回', '/audit/audit_approval/:identity/approve', ['opinion!'], {
|
||||
status: 'rejected',
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -4,9 +4,9 @@ const routes: AppRouteRecordRaw[] = [{
|
||||
path: '/audit', name: 'audit', component: DEFAULT_LAYOUT,
|
||||
meta: { locale: 'menu.platform.audit', requiresAuth: true, icon: 'icon-apps', order: 22 },
|
||||
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: '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: '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-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: '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: '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;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
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: [
|
||||
{ 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: '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: '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-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: '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: '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;
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
<script setup lang="ts">
|
||||
import ReadOnlyListPage from '@/views/shared/ReadOnlyListPage.vue';
|
||||
import { getResource } from '@/api/resources';
|
||||
const definition = getResource('/audit/aud_approval');
|
||||
const definition = getResource('/audit/audit_approval');
|
||||
</script>
|
||||
@@ -2,5 +2,5 @@
|
||||
<script setup lang="ts">
|
||||
import ReadOnlyListPage from '@/views/shared/ReadOnlyListPage.vue';
|
||||
import { getResource } from '@/api/resources';
|
||||
const definition = getResource('/audit/aud_export_log');
|
||||
const definition = getResource('/audit/audit_export_log');
|
||||
</script>
|
||||
@@ -2,5 +2,5 @@
|
||||
<script setup lang="ts">
|
||||
import ReadOnlyListPage from '@/views/shared/ReadOnlyListPage.vue';
|
||||
import { getResource } from '@/api/resources';
|
||||
const definition = getResource('/audit/aud_operation_log');
|
||||
const definition = getResource('/audit/audit_operation_log');
|
||||
</script>
|
||||
@@ -2,5 +2,5 @@
|
||||
<script setup lang="ts">
|
||||
import CrudListPage from '@/views/shared/CrudListPage.vue';
|
||||
import { getResource } from '@/api/resources';
|
||||
const definition = getResource('/safety/saf_event');
|
||||
const definition = getResource('/safety/safe_event');
|
||||
</script>
|
||||
@@ -2,5 +2,5 @@
|
||||
<script setup lang="ts">
|
||||
import CrudListPage from '@/views/shared/CrudListPage.vue';
|
||||
import { getResource } from '@/api/resources';
|
||||
const definition = getResource('/safety/saf_inspection');
|
||||
const definition = getResource('/safety/safe_inspection');
|
||||
</script>
|
||||
@@ -2,5 +2,5 @@
|
||||
<script setup lang="ts">
|
||||
import CrudListPage from '@/views/shared/CrudListPage.vue';
|
||||
import { getResource } from '@/api/resources';
|
||||
const definition = getResource('/safety/saf_rule');
|
||||
const definition = getResource('/safety/safe_rule');
|
||||
</script>
|
||||
Reference in New Issue
Block a user