@finema/finework-layer 0.2.50 → 0.2.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.playground/app/pages/layout-admin/test/[id]/index.vue +286 -0
- package/.playground/app/pages/layout-admin.vue +2 -2
- package/@finema finework-layer - LLM Documentation Guide.md +566 -0
- package/API_REFERENCE.md +780 -0
- package/ARCHITECTURE.md +592 -0
- package/CHANGELOG.md +6 -0
- package/COMPONENT_EXAMPLES.md +893 -0
- package/DOCUMENTATION_INDEX.md +354 -0
- package/EXAMPLES.md +597 -0
- package/QUICK_START.md +678 -0
- package/README.md +199 -33
- package/TROUBLESHOOTING.md +646 -0
- package/app/components/Button/Back.vue +1 -1
- package/app/components/Layout/Admin/Sidebar.vue +10 -3
- package/app/components/Layout/Admin/index.vue +9 -13
- package/package.json +1 -1
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
# Troubleshooting Guide
|
|
2
|
+
|
|
3
|
+
## 🔧 Common Issues & Solutions
|
|
4
|
+
|
|
5
|
+
### Authentication Issues
|
|
6
|
+
|
|
7
|
+
#### Issue: "Token not found" or "Unauthorized"
|
|
8
|
+
|
|
9
|
+
**Symptoms:**
|
|
10
|
+
- Redirected to login page repeatedly
|
|
11
|
+
- API requests return 401 errors
|
|
12
|
+
- `auth.token.value` is undefined
|
|
13
|
+
|
|
14
|
+
**Solutions:**
|
|
15
|
+
|
|
16
|
+
1. **Check Cookie Configuration**
|
|
17
|
+
```typescript
|
|
18
|
+
// Verify cookie is being set correctly
|
|
19
|
+
const token = useCookie('token', {
|
|
20
|
+
path: '/',
|
|
21
|
+
maxAge: 60 * 60 * 24 * 365
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
console.log('Token:', token.value)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
2. **Verify API Response**
|
|
28
|
+
- Backend must set the cookie with correct domain
|
|
29
|
+
- Cookie must be HttpOnly and Secure in production
|
|
30
|
+
- Check browser DevTools > Application > Cookies
|
|
31
|
+
|
|
32
|
+
3. **Check CORS Settings**
|
|
33
|
+
```typescript
|
|
34
|
+
// Backend must allow credentials
|
|
35
|
+
Access-Control-Allow-Credentials: true
|
|
36
|
+
Access-Control-Allow-Origin: https://your-domain.com
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
4. **Clear Browser Cookies**
|
|
40
|
+
```javascript
|
|
41
|
+
// In browser console
|
|
42
|
+
document.cookie.split(";").forEach(c => {
|
|
43
|
+
document.cookie = c.replace(/^ +/, "").replace(/=.*/, "=;expires=" + new Date().toUTCString() + ";path=/");
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
#### Issue: User data not loading
|
|
50
|
+
|
|
51
|
+
**Symptoms:**
|
|
52
|
+
- `auth.me.value` is null
|
|
53
|
+
- Page shows loading state indefinitely
|
|
54
|
+
|
|
55
|
+
**Solutions:**
|
|
56
|
+
|
|
57
|
+
1. **Check API Endpoint**
|
|
58
|
+
```typescript
|
|
59
|
+
const auth = useAuth()
|
|
60
|
+
|
|
61
|
+
// Manually trigger fetch
|
|
62
|
+
await auth.fetchMe.run()
|
|
63
|
+
|
|
64
|
+
// Check status
|
|
65
|
+
console.log('Status:', auth.fetchMe.status.value)
|
|
66
|
+
console.log('Error:', auth.fetchMe.status.value.errorData)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
2. **Verify Middleware Order**
|
|
70
|
+
```typescript
|
|
71
|
+
// Correct order
|
|
72
|
+
definePageMeta({
|
|
73
|
+
middleware: ['common', 'auth', 'permissions']
|
|
74
|
+
})
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
3. **Check Cache Timing**
|
|
78
|
+
```typescript
|
|
79
|
+
// Force refresh
|
|
80
|
+
auth.me.setTimestamp(null)
|
|
81
|
+
await auth.fetchMe.run()
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### Permission Issues
|
|
87
|
+
|
|
88
|
+
#### Issue: "Access Denied" or 403 errors
|
|
89
|
+
|
|
90
|
+
**Symptoms:**
|
|
91
|
+
- User redirected to error page
|
|
92
|
+
- Cannot access certain routes
|
|
93
|
+
- Features hidden unexpectedly
|
|
94
|
+
|
|
95
|
+
**Solutions:**
|
|
96
|
+
|
|
97
|
+
1. **Verify User Permissions**
|
|
98
|
+
```typescript
|
|
99
|
+
const auth = useAuth()
|
|
100
|
+
|
|
101
|
+
console.log('Access Level:', auth.me.value?.access_level)
|
|
102
|
+
console.log('Has PMO Admin:', auth.hasPermission(UserModule.PMO, Permission.ADMIN))
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
2. **Check Route Configuration**
|
|
106
|
+
```typescript
|
|
107
|
+
definePageMeta({
|
|
108
|
+
middleware: ['auth', 'permissions'],
|
|
109
|
+
accessGuard: {
|
|
110
|
+
permissions: ['pmo:USER', 'pmo:ADMIN'], // OR logic
|
|
111
|
+
redirectTo: '/unauthorized'
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
3. **Debug Permission Check**
|
|
117
|
+
```typescript
|
|
118
|
+
const canAccess = computed(() => {
|
|
119
|
+
const result = auth.hasPermission(UserModule.PMO, Permission.ADMIN)
|
|
120
|
+
console.log('Can Access:', result)
|
|
121
|
+
console.log('User Module:', auth.me.value?.access_level?.pmo)
|
|
122
|
+
return result
|
|
123
|
+
})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### Data Loading Issues
|
|
129
|
+
|
|
130
|
+
#### Issue: Data not loading or infinite loading
|
|
131
|
+
|
|
132
|
+
**Symptoms:**
|
|
133
|
+
- StatusBox shows loading spinner forever
|
|
134
|
+
- `loader.data.value` is null
|
|
135
|
+
- No error messages
|
|
136
|
+
|
|
137
|
+
**Solutions:**
|
|
138
|
+
|
|
139
|
+
1. **Check Loader Configuration**
|
|
140
|
+
```typescript
|
|
141
|
+
const loader = useObjectLoader({
|
|
142
|
+
method: 'GET',
|
|
143
|
+
url: '/api/data',
|
|
144
|
+
getRequestOptions: useRequestOptions().auth // Make sure this is correct
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
// Verify it's being called
|
|
148
|
+
onMounted(() => {
|
|
149
|
+
console.log('Loading data...')
|
|
150
|
+
loader.run()
|
|
151
|
+
})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
2. **Check API Response**
|
|
155
|
+
```typescript
|
|
156
|
+
// Add error handling
|
|
157
|
+
watch(() => loader.status.value, (status) => {
|
|
158
|
+
console.log('Loading:', status.isLoading)
|
|
159
|
+
console.log('Success:', status.isSuccess)
|
|
160
|
+
console.log('Error:', status.isError)
|
|
161
|
+
|
|
162
|
+
if (status.isError) {
|
|
163
|
+
console.error('Error Data:', status.errorData)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (status.isSuccess) {
|
|
167
|
+
console.log('Data:', loader.data.value)
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
3. **Verify API Endpoint**
|
|
173
|
+
```typescript
|
|
174
|
+
// Check full URL
|
|
175
|
+
const config = useRuntimeConfig()
|
|
176
|
+
console.log('Base URL:', config.public.baseAPI)
|
|
177
|
+
console.log('Full URL:', config.public.baseAPI + '/api/data')
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
4. **Check Network Tab**
|
|
181
|
+
- Open DevTools > Network
|
|
182
|
+
- Look for failed requests
|
|
183
|
+
- Check request headers (Authorization)
|
|
184
|
+
- Verify response status and body
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
#### Issue: Data loads but StatusBox shows error
|
|
189
|
+
|
|
190
|
+
**Symptoms:**
|
|
191
|
+
- Network request succeeds
|
|
192
|
+
- Data is in response
|
|
193
|
+
- StatusBox shows error state
|
|
194
|
+
|
|
195
|
+
**Solutions:**
|
|
196
|
+
|
|
197
|
+
1. **Check Data Structure**
|
|
198
|
+
```typescript
|
|
199
|
+
// StatusBox expects data to be truthy
|
|
200
|
+
// If API returns { data: null }, StatusBox will show error
|
|
201
|
+
|
|
202
|
+
// Solution: Transform response
|
|
203
|
+
const loader = useObjectLoader({
|
|
204
|
+
method: 'GET',
|
|
205
|
+
url: '/api/data',
|
|
206
|
+
getRequestOptions: useRequestOptions().auth
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
const transformedData = computed(() => {
|
|
210
|
+
return loader.data.value?.data || loader.data.value
|
|
211
|
+
})
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
2. **Check Status Object**
|
|
215
|
+
```typescript
|
|
216
|
+
// Ensure status is properly structured
|
|
217
|
+
console.log('Status:', loader.status.value)
|
|
218
|
+
// Should have: isLoading, isSuccess, isError
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Component Issues
|
|
224
|
+
|
|
225
|
+
#### Issue: Component not found
|
|
226
|
+
|
|
227
|
+
**Symptoms:**
|
|
228
|
+
- "Component not found" error
|
|
229
|
+
- Component doesn't render
|
|
230
|
+
- Import errors
|
|
231
|
+
|
|
232
|
+
**Solutions:**
|
|
233
|
+
|
|
234
|
+
1. **Check Component Location**
|
|
235
|
+
```
|
|
236
|
+
app/components/
|
|
237
|
+
├── MyComponent.vue ✅ Auto-imported
|
|
238
|
+
├── Button/
|
|
239
|
+
│ └── Custom.vue ✅ Auto-imported as ButtonCustom
|
|
240
|
+
└── nested/
|
|
241
|
+
└── Deep.vue ✅ Auto-imported as NestedDeep
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
2. **Verify Component Name**
|
|
245
|
+
```vue
|
|
246
|
+
<!-- Correct -->
|
|
247
|
+
<MyComponent />
|
|
248
|
+
<ButtonCustom />
|
|
249
|
+
<NestedDeep />
|
|
250
|
+
|
|
251
|
+
<!-- Incorrect -->
|
|
252
|
+
<my-component /> ❌
|
|
253
|
+
<Custom /> ❌
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
3. **Restart Dev Server**
|
|
257
|
+
```bash
|
|
258
|
+
# Sometimes auto-import needs refresh
|
|
259
|
+
pnpm dev
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
4. **Check nuxt.config.ts**
|
|
263
|
+
```typescript
|
|
264
|
+
export default defineNuxtConfig({
|
|
265
|
+
components: true // Should be enabled
|
|
266
|
+
})
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
#### Issue: Props not working
|
|
272
|
+
|
|
273
|
+
**Symptoms:**
|
|
274
|
+
- Props are undefined
|
|
275
|
+
- Type errors
|
|
276
|
+
- Default values not applied
|
|
277
|
+
|
|
278
|
+
**Solutions:**
|
|
279
|
+
|
|
280
|
+
1. **Check Prop Definition**
|
|
281
|
+
```vue
|
|
282
|
+
<script setup lang="ts">
|
|
283
|
+
// ✅ Correct
|
|
284
|
+
interface Props {
|
|
285
|
+
title: string
|
|
286
|
+
count?: number
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const props = defineProps<Props>()
|
|
290
|
+
|
|
291
|
+
// ✅ With defaults
|
|
292
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
293
|
+
count: 0
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
// ❌ Incorrect
|
|
297
|
+
const props = defineProps(['title', 'count']) // No types
|
|
298
|
+
</script>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
2. **Check Prop Passing**
|
|
302
|
+
```vue
|
|
303
|
+
<!-- ✅ Correct -->
|
|
304
|
+
<MyComponent :title="myTitle" :count="42" />
|
|
305
|
+
|
|
306
|
+
<!-- ❌ Incorrect -->
|
|
307
|
+
<MyComponent title="myTitle" count="42" /> <!-- Strings, not reactive -->
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
### Routing Issues
|
|
313
|
+
|
|
314
|
+
#### Issue: Route not found or 404
|
|
315
|
+
|
|
316
|
+
**Symptoms:**
|
|
317
|
+
- Page shows 404
|
|
318
|
+
- Navigation doesn't work
|
|
319
|
+
- Route constants undefined
|
|
320
|
+
|
|
321
|
+
**Solutions:**
|
|
322
|
+
|
|
323
|
+
1. **Check File Structure**
|
|
324
|
+
```
|
|
325
|
+
pages/
|
|
326
|
+
├── index.vue → /
|
|
327
|
+
├── about.vue → /about
|
|
328
|
+
├── projects/
|
|
329
|
+
│ ├── index.vue → /projects
|
|
330
|
+
│ ├── [id].vue → /projects/:id
|
|
331
|
+
│ └── new.vue → /projects/new
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
2. **Verify Route Constant**
|
|
335
|
+
```typescript
|
|
336
|
+
// Check if route exists
|
|
337
|
+
console.log('Routes:', routes)
|
|
338
|
+
console.log('PMO Route:', routes.pmo.project.projects.to)
|
|
339
|
+
|
|
340
|
+
// Use correct path
|
|
341
|
+
navigateTo(routes.pmo.project.projects.to) // ✅
|
|
342
|
+
navigateTo('/pmo/projects') // ✅
|
|
343
|
+
navigateTo(routes.pmo.projects.to) // ❌ Wrong path
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
3. **Check Middleware**
|
|
347
|
+
```typescript
|
|
348
|
+
// Middleware might be blocking
|
|
349
|
+
definePageMeta({
|
|
350
|
+
middleware: ['auth'] // Remove temporarily to test
|
|
351
|
+
})
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
### Build Issues
|
|
357
|
+
|
|
358
|
+
#### Issue: Build fails with type errors
|
|
359
|
+
|
|
360
|
+
**Symptoms:**
|
|
361
|
+
- `pnpm build` fails
|
|
362
|
+
- TypeScript errors
|
|
363
|
+
- Module not found errors
|
|
364
|
+
|
|
365
|
+
**Solutions:**
|
|
366
|
+
|
|
367
|
+
1. **Check TypeScript Config**
|
|
368
|
+
```bash
|
|
369
|
+
# Regenerate types
|
|
370
|
+
pnpm dev:prepare
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
2. **Clear Cache**
|
|
374
|
+
```bash
|
|
375
|
+
# Remove generated files
|
|
376
|
+
rm -rf .nuxt node_modules/.cache
|
|
377
|
+
|
|
378
|
+
# Reinstall
|
|
379
|
+
pnpm install
|
|
380
|
+
|
|
381
|
+
# Rebuild
|
|
382
|
+
pnpm build
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
3. **Check Imports**
|
|
386
|
+
```typescript
|
|
387
|
+
// ✅ Correct - auto-imported
|
|
388
|
+
const auth = useAuth()
|
|
389
|
+
|
|
390
|
+
// ❌ Incorrect - manual import
|
|
391
|
+
import { useAuth } from '~/composables/useAuth'
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
### Styling Issues
|
|
397
|
+
|
|
398
|
+
#### Issue: Tailwind classes not working
|
|
399
|
+
|
|
400
|
+
**Symptoms:**
|
|
401
|
+
- Classes have no effect
|
|
402
|
+
- Styles not applied
|
|
403
|
+
- Custom colors not working
|
|
404
|
+
|
|
405
|
+
**Solutions:**
|
|
406
|
+
|
|
407
|
+
1. **Check CSS Import**
|
|
408
|
+
```typescript
|
|
409
|
+
// nuxt.config.ts
|
|
410
|
+
export default defineNuxtConfig({
|
|
411
|
+
css: ['~/assets/css/main.css']
|
|
412
|
+
})
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
```css
|
|
416
|
+
/* assets/css/main.css */
|
|
417
|
+
@import "tailwindcss";
|
|
418
|
+
@import "@nuxt/ui";
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
2. **Check Class Names**
|
|
422
|
+
```vue
|
|
423
|
+
<!-- ✅ Correct -->
|
|
424
|
+
<div class="flex items-center gap-4">
|
|
425
|
+
|
|
426
|
+
<!-- ❌ Incorrect -->
|
|
427
|
+
<div class="flex items-center gap-4px"> <!-- Invalid unit -->
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
3. **Purge Configuration**
|
|
431
|
+
```typescript
|
|
432
|
+
// If using custom Tailwind config
|
|
433
|
+
export default {
|
|
434
|
+
content: [
|
|
435
|
+
'./components/**/*.{vue,js,ts}',
|
|
436
|
+
'./layouts/**/*.vue',
|
|
437
|
+
'./pages/**/*.vue',
|
|
438
|
+
'./app.vue'
|
|
439
|
+
]
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
### Performance Issues
|
|
446
|
+
|
|
447
|
+
#### Issue: Slow page load or navigation
|
|
448
|
+
|
|
449
|
+
**Symptoms:**
|
|
450
|
+
- Pages take long to load
|
|
451
|
+
- Navigation is sluggish
|
|
452
|
+
- High memory usage
|
|
453
|
+
|
|
454
|
+
**Solutions:**
|
|
455
|
+
|
|
456
|
+
1. **Check Data Fetching**
|
|
457
|
+
```typescript
|
|
458
|
+
// ❌ Bad - Multiple sequential requests
|
|
459
|
+
await loader1.run()
|
|
460
|
+
await loader2.run()
|
|
461
|
+
await loader3.run()
|
|
462
|
+
|
|
463
|
+
// ✅ Good - Parallel requests
|
|
464
|
+
await Promise.all([
|
|
465
|
+
loader1.run(),
|
|
466
|
+
loader2.run(),
|
|
467
|
+
loader3.run()
|
|
468
|
+
])
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
2. **Implement Lazy Loading**
|
|
472
|
+
```typescript
|
|
473
|
+
// Lazy load heavy components
|
|
474
|
+
const HeavyChart = defineAsyncComponent(() =>
|
|
475
|
+
import('~/components/HeavyChart.vue')
|
|
476
|
+
)
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
3. **Check Cache Settings**
|
|
480
|
+
```typescript
|
|
481
|
+
// Increase cache time if appropriate
|
|
482
|
+
const me = defineStore('auth.me', () => {
|
|
483
|
+
const isShouldFetch = () => {
|
|
484
|
+
// Cache for 5 minutes instead of 1
|
|
485
|
+
return Date.now() - timestamp.value > 1000 * 60 * 5
|
|
486
|
+
}
|
|
487
|
+
})
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
4. **Use Pagination**
|
|
491
|
+
```typescript
|
|
492
|
+
// Don't load all data at once
|
|
493
|
+
const loader = useListLoader({
|
|
494
|
+
method: 'GET',
|
|
495
|
+
url: '/api/data',
|
|
496
|
+
getRequestOptions: useRequestOptions().auth
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
loader.run({
|
|
500
|
+
params: {
|
|
501
|
+
page: 1,
|
|
502
|
+
per_page: 20 // Limit results
|
|
503
|
+
}
|
|
504
|
+
})
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## 🐛 Debugging Tools
|
|
510
|
+
|
|
511
|
+
### 1. Vue DevTools
|
|
512
|
+
|
|
513
|
+
```bash
|
|
514
|
+
# Install browser extension
|
|
515
|
+
# Chrome: https://chrome.google.com/webstore/detail/vuejs-devtools
|
|
516
|
+
# Firefox: https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
**Features:**
|
|
520
|
+
- Inspect component tree
|
|
521
|
+
- View component props and state
|
|
522
|
+
- Track events
|
|
523
|
+
- Inspect Pinia stores
|
|
524
|
+
|
|
525
|
+
### 2. Nuxt DevTools
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
// Enable in nuxt.config.ts
|
|
529
|
+
export default defineNuxtConfig({
|
|
530
|
+
devtools: {
|
|
531
|
+
enabled: true
|
|
532
|
+
}
|
|
533
|
+
})
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**Features:**
|
|
537
|
+
- Component inspector
|
|
538
|
+
- Route analyzer
|
|
539
|
+
- Module inspector
|
|
540
|
+
- Performance metrics
|
|
541
|
+
|
|
542
|
+
### 3. Console Debugging
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
// Add strategic console logs
|
|
546
|
+
console.log('🔍 Debug:', {
|
|
547
|
+
user: auth.me.value,
|
|
548
|
+
token: auth.token.value,
|
|
549
|
+
permissions: auth.me.value?.access_level
|
|
550
|
+
})
|
|
551
|
+
|
|
552
|
+
// Use console.table for arrays
|
|
553
|
+
console.table(projects.data.value)
|
|
554
|
+
|
|
555
|
+
// Use console.group for organization
|
|
556
|
+
console.group('Data Loading')
|
|
557
|
+
console.log('Status:', loader.status.value)
|
|
558
|
+
console.log('Data:', loader.data.value)
|
|
559
|
+
console.groupEnd()
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
### 4. Network Debugging
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
// Log all requests
|
|
566
|
+
const loader = useObjectLoader({
|
|
567
|
+
method: 'GET',
|
|
568
|
+
url: '/api/data',
|
|
569
|
+
getRequestOptions: () => {
|
|
570
|
+
const options = useRequestOptions().auth()
|
|
571
|
+
console.log('Request:', options)
|
|
572
|
+
return options
|
|
573
|
+
}
|
|
574
|
+
})
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
## 📞 Getting Help
|
|
580
|
+
|
|
581
|
+
### Before Asking for Help
|
|
582
|
+
|
|
583
|
+
1. ✅ Check this troubleshooting guide
|
|
584
|
+
2. ✅ Review error messages carefully
|
|
585
|
+
3. ✅ Check browser console for errors
|
|
586
|
+
4. ✅ Verify network requests in DevTools
|
|
587
|
+
5. ✅ Try clearing cache and rebuilding
|
|
588
|
+
6. ✅ Check if issue exists in fresh install
|
|
589
|
+
|
|
590
|
+
### When Reporting Issues
|
|
591
|
+
|
|
592
|
+
Include:
|
|
593
|
+
- Error message (full stack trace)
|
|
594
|
+
- Code snippet (minimal reproduction)
|
|
595
|
+
- Steps to reproduce
|
|
596
|
+
- Expected vs actual behavior
|
|
597
|
+
- Environment (Node version, OS, browser)
|
|
598
|
+
- Screenshots if applicable
|
|
599
|
+
|
|
600
|
+
---
|
|
601
|
+
|
|
602
|
+
## 🔍 Common Error Messages
|
|
603
|
+
|
|
604
|
+
### "Cannot read property 'value' of undefined"
|
|
605
|
+
|
|
606
|
+
**Cause:** Accessing reactive ref before initialization
|
|
607
|
+
|
|
608
|
+
**Solution:**
|
|
609
|
+
```typescript
|
|
610
|
+
// ❌ Bad
|
|
611
|
+
const data = loader.data.value.items // loader might be undefined
|
|
612
|
+
|
|
613
|
+
// ✅ Good
|
|
614
|
+
const data = computed(() => loader.data.value?.items || [])
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### "Module not found"
|
|
618
|
+
|
|
619
|
+
**Cause:** Import path incorrect or module not installed
|
|
620
|
+
|
|
621
|
+
**Solution:**
|
|
622
|
+
```bash
|
|
623
|
+
# Check if module is installed
|
|
624
|
+
pnpm list @finema/finework-layer
|
|
625
|
+
|
|
626
|
+
# Reinstall if needed
|
|
627
|
+
pnpm install
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
### "Hydration mismatch"
|
|
631
|
+
|
|
632
|
+
**Cause:** Server and client render different content
|
|
633
|
+
|
|
634
|
+
**Solution:**
|
|
635
|
+
```vue
|
|
636
|
+
<!-- Use ClientOnly for client-specific content -->
|
|
637
|
+
<ClientOnly>
|
|
638
|
+
<div>{{ new Date().toLocaleString() }}</div>
|
|
639
|
+
</ClientOnly>
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
**Last Updated:** 2025-11-07
|
|
645
|
+
**Need more help? Check the other documentation files!**
|
|
646
|
+
|
|
@@ -230,10 +230,17 @@ const mappedItems = (items: NavigationMenuItem[]): NavigationMenuItem[] => {
|
|
|
230
230
|
(p) => normalizePath(route.path) === normalizePath(p),
|
|
231
231
|
)
|
|
232
232
|
|
|
233
|
+
const basePath = item.to ? normalizePath(String(item.to)) : ''
|
|
234
|
+
const currentPath = normalizePath(route.path)
|
|
233
235
|
const selfIsActive = item.to
|
|
234
|
-
?
|
|
235
|
-
|
|
236
|
-
|
|
236
|
+
? (
|
|
237
|
+
currentPath === basePath
|
|
238
|
+
|| (
|
|
239
|
+
currentPath.startsWith(`${basePath}/`)
|
|
240
|
+
&& !currentPath.slice(basePath.length + 1).includes('/')
|
|
241
|
+
&& !hasExactMatch
|
|
242
|
+
)
|
|
243
|
+
)
|
|
237
244
|
: false
|
|
238
245
|
|
|
239
246
|
const itemIsActive = selfIsActive || isAnyChildActive
|
|
@@ -173,6 +173,7 @@ const props = withDefaults(
|
|
|
173
173
|
sidebarItems: NavigationMenuItem[]
|
|
174
174
|
isSidebarGroup?: boolean
|
|
175
175
|
fullScreen?: boolean
|
|
176
|
+
rootAppPath: string
|
|
176
177
|
}>(),
|
|
177
178
|
{
|
|
178
179
|
fullScreen: true,
|
|
@@ -207,18 +208,13 @@ const breadcrumbsItems = computed(() => {
|
|
|
207
208
|
const list = app.pageMeta.breadcrumbs || []
|
|
208
209
|
if (!list.length) return []
|
|
209
210
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
...item,
|
|
219
|
-
icon: '',
|
|
220
|
-
}))
|
|
221
|
-
|
|
222
|
-
return [home, ...extra]
|
|
211
|
+
return [
|
|
212
|
+
{
|
|
213
|
+
label: '',
|
|
214
|
+
icon: 'ph:house-line',
|
|
215
|
+
to: props.rootAppPath || '/',
|
|
216
|
+
},
|
|
217
|
+
...list,
|
|
218
|
+
]
|
|
223
219
|
})
|
|
224
220
|
</script>
|