set up new view for skeleton hiearchi
This commit is contained in:
131
app/composables/useComponentModels.js
Normal file
131
app/composables/useComponentModels.js
Normal file
@@ -0,0 +1,131 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { useApi } from './useApi'
|
||||
import { useToast } from './useToast'
|
||||
|
||||
const componentModelsBuckets = ref({})
|
||||
const loadingComponentModels = ref(false)
|
||||
|
||||
export function useComponentModels() {
|
||||
const { get, post, patch, delete: del } = useApi()
|
||||
const { showSuccess, showError } = useToast()
|
||||
|
||||
const loadComponentModels = async (typeComposantId) => {
|
||||
loadingComponentModels.value = true
|
||||
try {
|
||||
const query = typeComposantId ? `?typeComposantId=${encodeURIComponent(typeComposantId)}` : ''
|
||||
const result = await get(`/types/composants/models${query}`)
|
||||
if (result.success) {
|
||||
const key = typeComposantId || '__all__'
|
||||
componentModelsBuckets.value = {
|
||||
...componentModelsBuckets.value,
|
||||
[key]: result.data,
|
||||
}
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Impossible de charger les modèles de composant: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingComponentModels.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const createComponentModel = async (payload) => {
|
||||
loadingComponentModels.value = true
|
||||
try {
|
||||
const result = await post('/types/composants/models', payload)
|
||||
if (result.success) {
|
||||
const key = result.data?.typeComposantId || '__all__'
|
||||
const bucket = componentModelsBuckets.value[key] || []
|
||||
componentModelsBuckets.value = {
|
||||
...componentModelsBuckets.value,
|
||||
[key]: [...bucket, result.data],
|
||||
}
|
||||
showSuccess(`Modèle de composant "${result.data.name}" créé`)
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la création du modèle de composant: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingComponentModels.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const updateComponentModel = async (id, payload) => {
|
||||
loadingComponentModels.value = true
|
||||
try {
|
||||
const result = await patch(`/types/composants/models/${id}`, payload)
|
||||
if (result.success) {
|
||||
const key = result.data?.typeComposantId || '__all__'
|
||||
const bucket = componentModelsBuckets.value[key] || []
|
||||
const updatedBucket = bucket.map((model) =>
|
||||
model.id === id ? result.data : model
|
||||
)
|
||||
componentModelsBuckets.value = {
|
||||
...componentModelsBuckets.value,
|
||||
[key]: updatedBucket,
|
||||
}
|
||||
showSuccess(`Modèle de composant "${result.data.name}" mis à jour`)
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la mise à jour du modèle de composant: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingComponentModels.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const deleteComponentModel = async (id) => {
|
||||
loadingComponentModels.value = true
|
||||
try {
|
||||
const result = await del(`/types/composants/models/${id}`)
|
||||
if (result.success) {
|
||||
const updatedBuckets = {}
|
||||
for (const [key, bucket] of Object.entries(componentModelsBuckets.value)) {
|
||||
updatedBuckets[key] = bucket.filter((model) => model.id !== id)
|
||||
}
|
||||
componentModelsBuckets.value = updatedBuckets
|
||||
showSuccess('Modèle de composant supprimé')
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la suppression du modèle de composant: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingComponentModels.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const allComponentModels = computed(() => {
|
||||
return Object.values(componentModelsBuckets.value).reduce((acc, bucket) => {
|
||||
bucket.forEach((model) => {
|
||||
if (!acc.find((existing) => existing.id === model.id)) {
|
||||
acc.push(model)
|
||||
}
|
||||
})
|
||||
return acc
|
||||
}, [])
|
||||
})
|
||||
|
||||
const getComponentModelsForType = (typeComposantId) => {
|
||||
return componentModelsBuckets.value[typeComposantId] || []
|
||||
}
|
||||
|
||||
const getComponentModels = () => allComponentModels.value
|
||||
const isComponentModelLoading = () => loadingComponentModels.value
|
||||
|
||||
return {
|
||||
componentModels: allComponentModels,
|
||||
componentModelsBuckets,
|
||||
loadingComponentModels,
|
||||
loadComponentModels,
|
||||
createComponentModel,
|
||||
updateComponentModel,
|
||||
deleteComponentModel,
|
||||
getComponentModels,
|
||||
getComponentModelsForType,
|
||||
isComponentModelLoading,
|
||||
}
|
||||
}
|
||||
95
app/composables/useComponentTypes.js
Normal file
95
app/composables/useComponentTypes.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import { ref } from 'vue'
|
||||
import { useApi } from './useApi'
|
||||
import { useToast } from './useToast'
|
||||
|
||||
const componentTypes = ref([])
|
||||
const loadingComponentTypes = ref(false)
|
||||
|
||||
export function useComponentTypes() {
|
||||
const { get, post, patch, delete: del } = useApi()
|
||||
const { showSuccess, showError } = useToast()
|
||||
|
||||
const loadComponentTypes = async () => {
|
||||
loadingComponentTypes.value = true
|
||||
try {
|
||||
const result = await get('/types/composants')
|
||||
if (result.success) {
|
||||
componentTypes.value = result.data
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Impossible de charger les types de composant: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingComponentTypes.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const createComponentType = async (payload) => {
|
||||
loadingComponentTypes.value = true
|
||||
try {
|
||||
const result = await post('/types/composants', payload)
|
||||
if (result.success) {
|
||||
componentTypes.value.push(result.data)
|
||||
showSuccess(`Type de composant "${result.data.name}" créé`)
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la création du type de composant: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingComponentTypes.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const updateComponentType = async (id, payload) => {
|
||||
loadingComponentTypes.value = true
|
||||
try {
|
||||
const result = await patch(`/types/composants/${id}`, payload)
|
||||
if (result.success) {
|
||||
const index = componentTypes.value.findIndex((type) => type.id === id)
|
||||
if (index !== -1) {
|
||||
componentTypes.value[index] = result.data
|
||||
}
|
||||
showSuccess(`Type de composant "${result.data.name}" mis à jour`)
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la mise à jour du type de composant: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingComponentTypes.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const deleteComponentType = async (id) => {
|
||||
loadingComponentTypes.value = true
|
||||
try {
|
||||
const result = await del(`/types/composants/${id}`)
|
||||
if (result.success) {
|
||||
componentTypes.value = componentTypes.value.filter((type) => type.id !== id)
|
||||
showSuccess('Type de composant supprimé')
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la suppression du type de composant: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingComponentTypes.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const getComponentTypes = () => componentTypes.value
|
||||
const isComponentTypeLoading = () => loadingComponentTypes.value
|
||||
|
||||
return {
|
||||
componentTypes,
|
||||
loadingComponentTypes,
|
||||
loadComponentTypes,
|
||||
createComponentType,
|
||||
updateComponentType,
|
||||
deleteComponentType,
|
||||
getComponentTypes,
|
||||
isComponentTypeLoading,
|
||||
}
|
||||
}
|
||||
@@ -1,654 +0,0 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
// Types de machines prédéfinis avec structure hiérarchique
|
||||
const machineTypes = ref([
|
||||
// Machines de production
|
||||
{
|
||||
id: 1,
|
||||
name: 'Presse hydraulique',
|
||||
category: 'Production',
|
||||
description: 'Machine de formage par compression hydraulique',
|
||||
maintenanceFrequency: 'Mensuelle',
|
||||
components: [
|
||||
{
|
||||
name: 'Système hydraulique',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Pompe hydraulique',
|
||||
subComponents: [
|
||||
{ name: 'Rotor' },
|
||||
{ name: 'Stator' },
|
||||
{ name: 'Joint d\'étanchéité' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Cylindre principal',
|
||||
subComponents: [
|
||||
{ name: 'Piston' },
|
||||
{ name: 'Tige' },
|
||||
{ name: 'Joint de piston' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Soupapes de sécurité',
|
||||
subComponents: [
|
||||
{ name: 'Soupape de surpression' },
|
||||
{ name: 'Soupape de décharge' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système mécanique',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Banc de machine',
|
||||
subComponents: [
|
||||
{ name: 'Poutre supérieure' },
|
||||
{ name: 'Poutre inférieure' },
|
||||
{ name: 'Colonnes' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système de guidage',
|
||||
subComponents: [
|
||||
{ name: 'Rails de guidage' },
|
||||
{ name: 'Patins' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Pompe hydraulique', 'Cylindre principal', 'Soupapes de sécurité'],
|
||||
specifications: {
|
||||
force: '100-5000 tonnes',
|
||||
course: '100-800 mm',
|
||||
vitesse: '5-50 mm/s'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Convoyeur à bande',
|
||||
category: 'Production',
|
||||
description: 'Système de transport continu de matériaux',
|
||||
maintenanceFrequency: 'Hebdomadaire',
|
||||
components: [
|
||||
{
|
||||
name: 'Système de transport',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Bande transporteuse',
|
||||
subComponents: [
|
||||
{ name: 'Carcasse' },
|
||||
{ name: 'Revêtement' },
|
||||
{ name: 'Armature' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Rouleaux',
|
||||
subComponents: [
|
||||
{ name: 'Rouleaux porteurs' },
|
||||
{ name: 'Rouleaux de retour' },
|
||||
{ name: 'Rouleaux d\'impact' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système d\'entraînement',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Moteur d\'entraînement',
|
||||
subComponents: [
|
||||
{ name: 'Rotor' },
|
||||
{ name: 'Stator' },
|
||||
{ name: 'Roulements' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Réducteur',
|
||||
subComponents: [
|
||||
{ name: 'Engrenages' },
|
||||
{ name: 'Arbre de sortie' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Bande transporteuse', 'Rouleaux', 'Moteur d\'entraînement'],
|
||||
specifications: {
|
||||
longueur: '5-100 m',
|
||||
largeur: '400-2000 mm',
|
||||
vitesse: '0.5-3 m/s'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Robot de soudage',
|
||||
category: 'Production',
|
||||
description: 'Robot industriel pour opérations de soudage automatisé',
|
||||
maintenanceFrequency: 'Trimestrielle',
|
||||
components: [
|
||||
{
|
||||
name: 'Bras robotique',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Base rotative',
|
||||
subComponents: [
|
||||
{ name: 'Moteur de rotation' },
|
||||
{ name: 'Réducteur' },
|
||||
{ name: 'Capteur de position' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Bras articulé',
|
||||
subComponents: [
|
||||
{ name: 'Joint 1' },
|
||||
{ name: 'Joint 2' },
|
||||
{ name: 'Joint 3' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système de soudage',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Torche de soudage',
|
||||
subComponents: [
|
||||
{ name: 'Électrode' },
|
||||
{ name: 'Gainage' },
|
||||
{ name: 'Conduit de gaz' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Alimentation électrique',
|
||||
subComponents: [
|
||||
{ name: 'Transformateur' },
|
||||
{ name: 'Régulateur de courant' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Bras robotique', 'Torche de soudage', 'Contrôleur'],
|
||||
specifications: {
|
||||
portée: '1.5-3 m',
|
||||
charge: '5-200 kg',
|
||||
précision: '±0.1 mm'
|
||||
}
|
||||
},
|
||||
|
||||
// Machines de transformation
|
||||
{
|
||||
id: 4,
|
||||
name: 'Tour CNC',
|
||||
category: 'Transformation',
|
||||
description: 'Machine-outil pour usinage de pièces cylindriques',
|
||||
maintenanceFrequency: 'Mensuelle',
|
||||
components: [
|
||||
{
|
||||
name: 'Banc de machine',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Banc principal',
|
||||
subComponents: [
|
||||
{ name: 'Poutre' },
|
||||
{ name: 'Guidages' },
|
||||
{ name: 'Vis à billes' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système de broche',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Broche principale',
|
||||
subComponents: [
|
||||
{ name: 'Arbre de broche' },
|
||||
{ name: 'Roulements' },
|
||||
{ name: 'Moteur de broche' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Contre-pointe',
|
||||
subComponents: [
|
||||
{ name: 'Pointe' },
|
||||
{ name: 'Cylindre' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Banc de machine', 'Broche', 'Contre-pointe'],
|
||||
specifications: {
|
||||
diamètre: '200-1000 mm',
|
||||
longueur: '500-3000 mm',
|
||||
puissance: '5-50 kW'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Fraiseuse',
|
||||
category: 'Transformation',
|
||||
description: 'Machine-outil pour usinage par enlèvement de copeaux',
|
||||
maintenanceFrequency: 'Mensuelle',
|
||||
components: [
|
||||
{
|
||||
name: 'Table de travail',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Table X',
|
||||
subComponents: [
|
||||
{ name: 'Guidages X' },
|
||||
{ name: 'Vis à billes X' },
|
||||
{ name: 'Moteur X' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Table Y',
|
||||
subComponents: [
|
||||
{ name: 'Guidages Y' },
|
||||
{ name: 'Vis à billes Y' },
|
||||
{ name: 'Moteur Y' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système de broche',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Broche verticale',
|
||||
subComponents: [
|
||||
{ name: 'Arbre de broche' },
|
||||
{ name: 'Roulements' },
|
||||
{ name: 'Moteur de broche' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Table de travail', 'Broche', 'Guidages'],
|
||||
specifications: {
|
||||
courseX: '400-2000 mm',
|
||||
courseY: '300-1500 mm',
|
||||
courseZ: '200-800 mm'
|
||||
}
|
||||
},
|
||||
|
||||
// Machines de manutention
|
||||
{
|
||||
id: 6,
|
||||
name: 'Pont roulant',
|
||||
category: 'Manutention',
|
||||
description: 'Système de levage et transport de charges lourdes',
|
||||
maintenanceFrequency: 'Mensuelle',
|
||||
components: [
|
||||
{
|
||||
name: 'Poutre principale',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Poutre de roulement',
|
||||
subComponents: [
|
||||
{ name: 'Profilé principal' },
|
||||
{ name: 'Rails de roulement' },
|
||||
{ name: 'Renforts' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système de palans',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Palans',
|
||||
subComponents: [
|
||||
{ name: 'Moteur de levage' },
|
||||
{ name: 'Treuil' },
|
||||
{ name: 'Crochet' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système de translation',
|
||||
subComponents: [
|
||||
{ name: 'Moteur de translation' },
|
||||
{ name: 'Roues de roulement' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Poutre principale', 'Palans', 'Rails de guidage'],
|
||||
specifications: {
|
||||
capacité: '1-500 tonnes',
|
||||
portée: '5-50 m',
|
||||
hauteur: '3-20 m'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Chariot élévateur',
|
||||
category: 'Manutention',
|
||||
description: 'Véhicule de manutention pour charges palettisées',
|
||||
maintenanceFrequency: 'Hebdomadaire',
|
||||
components: [
|
||||
{
|
||||
name: 'Système de levage',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Mast',
|
||||
subComponents: [
|
||||
{ name: 'Mât extérieur' },
|
||||
{ name: 'Mât intérieur' },
|
||||
{ name: 'Cylindres de levage' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Fourches',
|
||||
subComponents: [
|
||||
{ name: 'Fourche gauche' },
|
||||
{ name: 'Fourche droite' },
|
||||
{ name: 'Système de réglage' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Groupe motopropulseur',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Moteur',
|
||||
subComponents: [
|
||||
{ name: 'Bloc moteur' },
|
||||
{ name: 'Système d\'injection' },
|
||||
{ name: 'Système de refroidissement' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Transmission',
|
||||
subComponents: [
|
||||
{ name: 'Boîte de vitesses' },
|
||||
{ name: 'Arbre de transmission' },
|
||||
{ name: 'Pont arrière' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Mast', 'Fourches', 'Moteur'],
|
||||
specifications: {
|
||||
capacité: '1-10 tonnes',
|
||||
hauteur: '3-6 m',
|
||||
type: 'Électrique/Diesel/Gaz'
|
||||
}
|
||||
},
|
||||
|
||||
// Machines de traitement
|
||||
{
|
||||
id: 8,
|
||||
name: 'Compresseur d\'air',
|
||||
category: 'Traitement',
|
||||
description: 'Générateur d\'air comprimé pour applications industrielles',
|
||||
maintenanceFrequency: 'Hebdomadaire',
|
||||
components: [
|
||||
{
|
||||
name: 'Système de compression',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Compresseur',
|
||||
subComponents: [
|
||||
{ name: 'Pistons' },
|
||||
{ name: 'Cylindres' },
|
||||
{ name: 'Soupapes' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Réservoir',
|
||||
subComponents: [
|
||||
{ name: 'Cuve' },
|
||||
{ name: 'Soupape de sécurité' },
|
||||
{ name: 'Manomètre' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système de filtration',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Filtres',
|
||||
subComponents: [
|
||||
{ name: 'Filtre à air' },
|
||||
{ name: 'Filtre à huile' },
|
||||
{ name: 'Séparateur d\'eau' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Compresseur', 'Réservoir', 'Filtres'],
|
||||
specifications: {
|
||||
débit: '100-10000 L/min',
|
||||
pression: '7-10 bar',
|
||||
puissance: '5-500 kW'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: 'Pompe hydraulique',
|
||||
category: 'Traitement',
|
||||
description: 'Pompe pour circuits hydrauliques industriels',
|
||||
maintenanceFrequency: 'Mensuelle',
|
||||
components: [
|
||||
{
|
||||
name: 'Système de pompage',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Rotor',
|
||||
subComponents: [
|
||||
{ name: 'Ailettes' },
|
||||
{ name: 'Arbre' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Stator',
|
||||
subComponents: [
|
||||
{ name: 'Corps' },
|
||||
{ name: 'Chambres' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système d\'étanchéité',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Joint d\'étanchéité',
|
||||
subComponents: [
|
||||
{ name: 'Joint radial' },
|
||||
{ name: 'Joint axial' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Rotor', 'Stator', 'Joint d\'étanchéité'],
|
||||
specifications: {
|
||||
débit: '10-500 L/min',
|
||||
pression: '50-350 bar',
|
||||
type: 'Piston/Palette/Engrenage'
|
||||
}
|
||||
},
|
||||
|
||||
// Machines de contrôle
|
||||
{
|
||||
id: 10,
|
||||
name: 'Capteur de température',
|
||||
category: 'Contrôle',
|
||||
description: 'Instrument de mesure de température industrielle',
|
||||
maintenanceFrequency: 'Annuelle',
|
||||
components: [
|
||||
{
|
||||
name: 'Système de mesure',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Élément sensible',
|
||||
subComponents: [
|
||||
{ name: 'Fil de platine' },
|
||||
{ name: 'Isolation' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Câblage',
|
||||
subComponents: [
|
||||
{ name: 'Fils de connexion' },
|
||||
{ name: 'Gaine de protection' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système de transmission',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Transmetteur',
|
||||
subComponents: [
|
||||
{ name: 'Circuit électronique' },
|
||||
{ name: 'Affichage' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Élément sensible', 'Câblage', 'Transmetteur'],
|
||||
specifications: {
|
||||
plage: '-50 à +500°C',
|
||||
précision: '±0.5°C',
|
||||
type: 'PT100/PT1000/Thermocouple'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: 'Manomètre',
|
||||
category: 'Contrôle',
|
||||
description: 'Instrument de mesure de pression',
|
||||
maintenanceFrequency: 'Annuelle',
|
||||
components: [
|
||||
{
|
||||
name: 'Système de mesure',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Tube de Bourdon',
|
||||
subComponents: [
|
||||
{ name: 'Tube' },
|
||||
{ name: 'Extrémité fixe' },
|
||||
{ name: 'Extrémité mobile' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Cadran',
|
||||
subComponents: [
|
||||
{ name: 'Échelle' },
|
||||
{ name: 'Aiguille' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Système de connexion',
|
||||
subComponents: [
|
||||
{
|
||||
name: 'Joint',
|
||||
subComponents: [
|
||||
{ name: 'Joint d\'étanchéité' },
|
||||
{ name: 'Filetage' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
criticalParts: ['Tube de Bourdon', 'Cadran', 'Joint'],
|
||||
specifications: {
|
||||
plage: '0-600 bar',
|
||||
précision: '±1%',
|
||||
type: 'Analogique/Numérique'
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
// Catégories disponibles
|
||||
const categories = ref([
|
||||
'Production',
|
||||
'Transformation',
|
||||
'Manutention',
|
||||
'Traitement',
|
||||
'Contrôle'
|
||||
])
|
||||
|
||||
export function useMachineTypes() {
|
||||
const getTypes = () => machineTypes.value
|
||||
|
||||
const getTypeById = (id) => {
|
||||
return machineTypes.value.find(type => type.id === id)
|
||||
}
|
||||
|
||||
const getTypesByCategory = (category) => {
|
||||
return machineTypes.value.filter(type => type.category === category)
|
||||
}
|
||||
|
||||
const getCategories = () => categories.value
|
||||
|
||||
const addType = (newType) => {
|
||||
const id = Math.max(...machineTypes.value.map(t => t.id)) + 1
|
||||
machineTypes.value.push({
|
||||
id,
|
||||
...newType
|
||||
})
|
||||
}
|
||||
|
||||
const updateType = (id, updatedType) => {
|
||||
const index = machineTypes.value.findIndex(type => type.id === id)
|
||||
if (index !== -1) {
|
||||
machineTypes.value[index] = { ...machineTypes.value[index], ...updatedType }
|
||||
}
|
||||
}
|
||||
|
||||
const deleteType = (id) => {
|
||||
const index = machineTypes.value.findIndex(type => type.id === id)
|
||||
if (index !== -1) {
|
||||
machineTypes.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// Méthodes pour la hiérarchie
|
||||
const flattenComponents = (components, level = 0) => {
|
||||
let flat = []
|
||||
components.forEach(comp => {
|
||||
flat.push({ ...comp, level })
|
||||
if (comp.subComponents && comp.subComponents.length > 0) {
|
||||
flat = flat.concat(flattenComponents(comp.subComponents, level + 1))
|
||||
}
|
||||
})
|
||||
return flat
|
||||
}
|
||||
|
||||
const getComponentHierarchy = (typeId) => {
|
||||
const type = getTypeById(typeId)
|
||||
if (!type || !type.components) return []
|
||||
return flattenComponents(type.components)
|
||||
}
|
||||
|
||||
return {
|
||||
getTypes,
|
||||
getTypeById,
|
||||
getTypesByCategory,
|
||||
getCategories,
|
||||
addType,
|
||||
updateType,
|
||||
deleteType,
|
||||
flattenComponents,
|
||||
getComponentHierarchy
|
||||
}
|
||||
}
|
||||
131
app/composables/usePieceModels.js
Normal file
131
app/composables/usePieceModels.js
Normal file
@@ -0,0 +1,131 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { useApi } from './useApi'
|
||||
import { useToast } from './useToast'
|
||||
|
||||
const pieceModelsBuckets = ref({})
|
||||
const loadingPieceModels = ref(false)
|
||||
|
||||
export function usePieceModels() {
|
||||
const { get, post, patch, delete: del } = useApi()
|
||||
const { showSuccess, showError } = useToast()
|
||||
|
||||
const loadPieceModels = async (typePieceId) => {
|
||||
loadingPieceModels.value = true
|
||||
try {
|
||||
const query = typePieceId ? `?typePieceId=${encodeURIComponent(typePieceId)}` : ''
|
||||
const result = await get(`/types/pieces/models${query}`)
|
||||
if (result.success) {
|
||||
const key = typePieceId || '__all__'
|
||||
pieceModelsBuckets.value = {
|
||||
...pieceModelsBuckets.value,
|
||||
[key]: result.data,
|
||||
}
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Impossible de charger les modèles de pièce: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingPieceModels.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const createPieceModel = async (payload) => {
|
||||
loadingPieceModels.value = true
|
||||
try {
|
||||
const result = await post('/types/pieces/models', payload)
|
||||
if (result.success) {
|
||||
const key = result.data?.typePieceId || '__all__'
|
||||
const bucket = pieceModelsBuckets.value[key] || []
|
||||
pieceModelsBuckets.value = {
|
||||
...pieceModelsBuckets.value,
|
||||
[key]: [...bucket, result.data],
|
||||
}
|
||||
showSuccess(`Modèle de pièce "${result.data.name}" créé`)
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la création du modèle de pièce: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingPieceModels.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const updatePieceModel = async (id, payload) => {
|
||||
loadingPieceModels.value = true
|
||||
try {
|
||||
const result = await patch(`/types/pieces/models/${id}`, payload)
|
||||
if (result.success) {
|
||||
const key = result.data?.typePieceId || '__all__'
|
||||
const bucket = pieceModelsBuckets.value[key] || []
|
||||
const updatedBucket = bucket.map((model) =>
|
||||
model.id === id ? result.data : model
|
||||
)
|
||||
pieceModelsBuckets.value = {
|
||||
...pieceModelsBuckets.value,
|
||||
[key]: updatedBucket,
|
||||
}
|
||||
showSuccess(`Modèle de pièce "${result.data.name}" mis à jour`)
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la mise à jour du modèle de pièce: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingPieceModels.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const deletePieceModel = async (id) => {
|
||||
loadingPieceModels.value = true
|
||||
try {
|
||||
const result = await del(`/types/pieces/models/${id}`)
|
||||
if (result.success) {
|
||||
const updatedBuckets = {}
|
||||
for (const [key, bucket] of Object.entries(pieceModelsBuckets.value)) {
|
||||
updatedBuckets[key] = bucket.filter((model) => model.id !== id)
|
||||
}
|
||||
pieceModelsBuckets.value = updatedBuckets
|
||||
showSuccess('Modèle de pièce supprimé')
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la suppression du modèle de pièce: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingPieceModels.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const allPieceModels = computed(() => {
|
||||
return Object.values(pieceModelsBuckets.value).reduce((acc, bucket) => {
|
||||
bucket.forEach((model) => {
|
||||
if (!acc.find((existing) => existing.id === model.id)) {
|
||||
acc.push(model)
|
||||
}
|
||||
})
|
||||
return acc
|
||||
}, [])
|
||||
})
|
||||
|
||||
const getPieceModelsForType = (typePieceId) => {
|
||||
return pieceModelsBuckets.value[typePieceId] || []
|
||||
}
|
||||
|
||||
const getPieceModels = () => allPieceModels.value
|
||||
const isPieceModelLoading = () => loadingPieceModels.value
|
||||
|
||||
return {
|
||||
pieceModels: allPieceModels,
|
||||
pieceModelsBuckets,
|
||||
loadingPieceModels,
|
||||
loadPieceModels,
|
||||
createPieceModel,
|
||||
updatePieceModel,
|
||||
deletePieceModel,
|
||||
getPieceModels,
|
||||
getPieceModelsForType,
|
||||
isPieceModelLoading,
|
||||
}
|
||||
}
|
||||
95
app/composables/usePieceTypes.js
Normal file
95
app/composables/usePieceTypes.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import { ref } from 'vue'
|
||||
import { useApi } from './useApi'
|
||||
import { useToast } from './useToast'
|
||||
|
||||
const pieceTypes = ref([])
|
||||
const loadingPieceTypes = ref(false)
|
||||
|
||||
export function usePieceTypes() {
|
||||
const { get, post, patch, delete: del } = useApi()
|
||||
const { showSuccess, showError } = useToast()
|
||||
|
||||
const loadPieceTypes = async () => {
|
||||
loadingPieceTypes.value = true
|
||||
try {
|
||||
const result = await get('/types/pieces')
|
||||
if (result.success) {
|
||||
pieceTypes.value = result.data
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Impossible de charger les types de pièce: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingPieceTypes.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const createPieceType = async (payload) => {
|
||||
loadingPieceTypes.value = true
|
||||
try {
|
||||
const result = await post('/types/pieces', payload)
|
||||
if (result.success) {
|
||||
pieceTypes.value.push(result.data)
|
||||
showSuccess(`Type de pièce "${result.data.name}" créé`)
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la création du type de pièce: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingPieceTypes.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const updatePieceType = async (id, payload) => {
|
||||
loadingPieceTypes.value = true
|
||||
try {
|
||||
const result = await patch(`/types/pieces/${id}`, payload)
|
||||
if (result.success) {
|
||||
const index = pieceTypes.value.findIndex((type) => type.id === id)
|
||||
if (index !== -1) {
|
||||
pieceTypes.value[index] = result.data
|
||||
}
|
||||
showSuccess(`Type de pièce "${result.data.name}" mis à jour`)
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la mise à jour du type de pièce: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingPieceTypes.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const deletePieceType = async (id) => {
|
||||
loadingPieceTypes.value = true
|
||||
try {
|
||||
const result = await del(`/types/pieces/${id}`)
|
||||
if (result.success) {
|
||||
pieceTypes.value = pieceTypes.value.filter((type) => type.id !== id)
|
||||
showSuccess('Type de pièce supprimé')
|
||||
}
|
||||
return result
|
||||
} catch (error) {
|
||||
showError(`Erreur lors de la suppression du type de pièce: ${error.message}`)
|
||||
return { success: false, error: error.message }
|
||||
} finally {
|
||||
loadingPieceTypes.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const getPieceTypes = () => pieceTypes.value
|
||||
const isPieceTypeLoading = () => loadingPieceTypes.value
|
||||
|
||||
return {
|
||||
pieceTypes,
|
||||
loadingPieceTypes,
|
||||
loadPieceTypes,
|
||||
createPieceType,
|
||||
updatePieceType,
|
||||
deletePieceType,
|
||||
getPieceTypes,
|
||||
isPieceTypeLoading,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user