Auto-sync 2026-04-15 21:10

This commit is contained in:
root 2026-04-15 21:10:01 +02:00
parent 1fb2552b3f
commit 70d82f5670
3 changed files with 70 additions and 10 deletions

View File

@ -13,11 +13,11 @@ const app = new Vue({
windowWidth: window.innerWidth,
posFields: [
{ field: 'npc', label: 'NPC Position', hasHeading: true },
{ field: 'spawn', label: 'Spawn Position (Fahrzeug erscheint)',hasHeading: true },
{ field: 'spawn', label: 'Spawn Position (Fahrzeug erscheint)', hasHeading: true },
{ field: 'park', label: 'Einpark-Zone (Marker am Boden)', hasHeading: false },
{ field: 'showcar', label: 'Vorschau-Fahrzeug Position', hasHeading: true },
{ field: 'cam', label: 'Kamera Position', hasHeading: false },
],
jobVehicles: [], // Fahrzeuge für die aktuelle Jobgarage
newJobVehicle: '', // Eingabe: neues Modell
},
computed: {
@ -107,9 +107,18 @@ const app = new Vue({
});
},
newGarage() {
this.editingGarage = { _isNew: true, id:'', label:'', type:'normal', access:'none', gang:'none', npc_model:'a_m_m_prolhost_01', blip_show:1, blip_show_bool:true, blip_type:357, blip_colour:3, npc_x:0,npc_y:0,npc_z:0,npc_heading:0, spawn_x:0,spawn_y:0,spawn_z:0,spawn_heading:0, park_x:0,park_y:0,park_z:0,park_heading:0, showcar_x:null,showcar_y:null,showcar_z:null,showcar_heading:0, cam_x:null,cam_y:null,cam_z:null,cam_rot_z:-20 };
this.editingGarage = { _isNew: true, id:'', label:'', type:'normal', access:'none', gang:'none', npc_model:'a_m_m_prolhost_01', blip_show:1, blip_show_bool:true, blip_type:357, blip_colour:3, npc_x:0,npc_y:0,npc_z:0,npc_heading:0, spawn_x:0,spawn_y:0,spawn_z:0,spawn_heading:0, park_x:0,park_y:0,park_z:0,park_heading:0 };
this.jobVehicles = [];
},
editGarage(g) {
this.editingGarage = Object.assign({ _isNew: false, blip_show_bool: g.blip_show == 1 }, g);
// Job-Fahrzeuge laden falls Jobgarage
if (g.type === 'jobgarage') {
this.jobVehicles = g.job_vehicles ? [...g.job_vehicles] : [];
} else {
this.jobVehicles = [];
}
},
editGarage(g) { this.editingGarage = Object.assign({ _isNew: false, blip_show_bool: g.blip_show == 1 }, g); },
confirmDelete(id) { this.deleteConfirmId = id; },
deleteGarage() {
if (!this.deleteConfirmId) return;
@ -118,6 +127,18 @@ const app = new Vue({
if (this.editingGarage && this.editingGarage.id === this.deleteConfirmId) this.editingGarage = null;
this.deleteConfirmId = null;
},
// Job-Fahrzeug hinzufügen
addJobVehicle() {
const model = this.newJobVehicle.trim().toLowerCase();
if (!model) return;
if (!this.jobVehicles.find(v => v.model === model)) {
this.jobVehicles.push({ model, label: model.toUpperCase() });
}
this.newJobVehicle = '';
},
removeJobVehicle(index) {
this.jobVehicles.splice(index, 1);
},
saveGarage() {
const g = this.editingGarage;
if (!g) return;
@ -127,6 +148,9 @@ const app = new Vue({
const payload = Object.assign({}, g);
delete payload._isNew; delete payload.blip_show_bool;
payload.blip_show = g.blip_show_bool ? 1 : 0;
if (g.type === 'jobgarage') {
payload.job_vehicles = this.jobVehicles;
}
$.post(`https://${GetParentResourceName()}/adminSaveGarage`, JSON.stringify(payload));
const i = this.adminGarages.findIndex(x => x.id === payload.id);
if (i >= 0) this.adminGarages.splice(i, 1, payload); else this.adminGarages.push(payload);
@ -139,7 +163,7 @@ const app = new Vue({
$.post(`https://${GetParentResourceName()}/startCapture`, JSON.stringify({ field }));
},
getFieldLabel(field) {
const l = { npc:'NPC Position', spawn:'Spawn Position', park:'Einpark-Zone', showcar:'Vorschau-Fahrzeug', cam:'Kamera' };
const l = { npc:'NPC Position', spawn:'Spawn Position', park:'Einpark-Zone' };
return l[field] || field;
},
getTypeIcon(type) {

View File

@ -507,3 +507,33 @@ kbd {
}
.mv-parkin-btn:hover { background: rgba(232,131,10,0.28); }
.mv-parkin-btn:active { transform: scale(0.98); }
/* Job-Fahrzeuge Admin */
.mv-job-vehicle-list {
display: flex; flex-direction: column; gap: 6px;
margin-bottom: 10px;
}
.mv-job-vehicle-item {
display: flex; align-items: center; justify-content: space-between;
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 6px; padding: 8px 12px;
}
.mv-job-vehicle-name {
font-size: 13px; color: var(--text-secondary);
}
.mv-job-vehicle-name i { color: var(--accent); margin-right: 6px; }
.mv-job-vehicle-empty {
font-size: 12px; color: var(--text-muted);
padding: 8px; text-align: center;
}
.mv-job-vehicle-add {
display: flex; gap: 8px; align-items: center;
}
.mv-job-input {
flex: 1; padding: 8px 12px;
background: var(--bg-input); border: 1px solid var(--border);
border-radius: 8px; color: var(--text-secondary);
font-size: 13px; font-family: inherit; outline: none;
}
.mv-job-input:focus { border-color: var(--accent); }

View File

@ -375,9 +375,9 @@ RegisterNetEvent('mercyv-garage:getVehicles', function(garageId)
Config.ServerNotification(src, Config.Notify.NO_ACCESS, "error")
return
end
-- Job-Fahrzeuge aus Config.JobVehicles
-- Job-Fahrzeuge: erst aus GaragesData (admin-gesetzt), dann Config.JobVehicles
local jobCars = {}
local jobList = Config.JobVehicles and Config.JobVehicles[g.access] or {}
local jobList = (Config.JobVehicles and Config.JobVehicles[g.access]) or {}
for i, car in ipairs(jobList) do
table.insert(jobCars, {
plate = car.model,
@ -601,6 +601,12 @@ RegisterNetEvent('mercyv-garage:admin:saveGarage', function(data)
showcar_x=data.showcar_x,showcar_y=data.showcar_y,showcar_z=data.showcar_z,showcar_heading=data.showcar_heading or 0,
cam_x=data.cam_x,cam_y=data.cam_y,cam_z=data.cam_z,cam_rot_z=data.cam_rot_z or -20,
})
-- Job-Fahrzeuge in Config aktualisieren
if data.type == 'jobgarage' and data.job_vehicles then
if not Config.JobVehicles then Config.JobVehicles = {} end
Config.JobVehicles[data.access] = data.job_vehicles
end
BroadcastGarages()
Config.ServerNotification(src, Config.Notify.ADMIN_SAVED, "success")
end)