Split maintenance into host and battery types with separate forms
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ups_management/ups_manager/__pycache__/forms.cpython-311.pyc
Normal file
BIN
ups_management/ups_manager/__pycache__/forms.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.6 on 2026-05-18 03:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ups_manager', '0003_alter_upshost_brand'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='maintenancerecord',
|
||||
name='maintenance_type',
|
||||
field=models.CharField(choices=[('host', '主机维修'), ('battery', '电池维修')], default='host', max_length=20, verbose_name='维修类型'),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
@@ -90,6 +90,12 @@ class Battery(models.Model):
|
||||
|
||||
|
||||
class MaintenanceRecord(models.Model):
|
||||
MAINTENANCE_TYPE_CHOICES = [
|
||||
('host', '主机维修'),
|
||||
('battery', '电池维修'),
|
||||
]
|
||||
|
||||
maintenance_type = models.CharField(max_length=20, choices=MAINTENANCE_TYPE_CHOICES, default='host', verbose_name='维修类型')
|
||||
ups_host = models.ForeignKey(UPSHost, on_delete=models.CASCADE, verbose_name='UPS主机')
|
||||
battery = models.ForeignKey(Battery, on_delete=models.SET_NULL, blank=True, null=True, verbose_name='电池')
|
||||
supplier = models.ForeignKey(Supplier, on_delete=models.SET_NULL, blank=True, null=True, verbose_name='维保供应商')
|
||||
@@ -99,7 +105,7 @@ class MaintenanceRecord(models.Model):
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.ups_host} - {self.maintenance_date}'
|
||||
return f'{self.get_maintenance_type_display()} - {self.ups_host} - {self.maintenance_date}'
|
||||
|
||||
class Meta:
|
||||
verbose_name = '维修记录'
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
{% extends 'ups_manager/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h2 class="mb-0">添加电池维修记录</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.ups_host.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.ups_host.label }} <span class="text-danger">*</span>
|
||||
</label>
|
||||
{{ form.ups_host }}
|
||||
{% if form.ups_host.errors %}
|
||||
{% for error in form.ups_host.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.battery.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.battery.label }} <span class="text-danger">*</span>
|
||||
</label>
|
||||
{{ form.battery }}
|
||||
{% if form.battery.errors %}
|
||||
{% for error in form.battery.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.supplier.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.supplier.label }}
|
||||
</label>
|
||||
{{ form.supplier }}
|
||||
{% if form.supplier.errors %}
|
||||
{% for error in form.supplier.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.maintenance_date.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.maintenance_date.label }} <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
id="{{ form.maintenance_date.id_for_label }}"
|
||||
name="{{ form.maintenance_date.name }}"
|
||||
class="form-control datepicker"
|
||||
value="{{ form.maintenance_date.value|date:'Y-m-d' }}"
|
||||
placeholder="选择日期">
|
||||
{% if form.maintenance_date.errors %}
|
||||
{% for error in form.maintenance_date.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.technician.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.technician.label }} <span class="text-danger">*</span>
|
||||
</label>
|
||||
{{ form.technician }}
|
||||
{% if form.technician.errors %}
|
||||
{% for error in form.technician.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.content.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.content.label }} <span class="text-danger">*</span>
|
||||
</label>
|
||||
{{ form.content }}
|
||||
{% if form.content.errors %}
|
||||
{% for error in form.content.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 d-flex justify-content-end gap-3">
|
||||
<a href="{% url 'maintenance_list' %}" class="btn btn-secondary px-6">
|
||||
<i class="fas fa-arrow-left mr-2"></i>取消
|
||||
</a>
|
||||
<button type="submit" class="btn btn-success px-6">
|
||||
<i class="fas fa-save mr-2"></i>保存
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
flatpickr('.datepicker', {
|
||||
dateFormat: 'Y-m-d',
|
||||
locale: 'zh',
|
||||
allowInput: true,
|
||||
todayButton: true,
|
||||
clearButton: true,
|
||||
minDate: '1900-01-01',
|
||||
maxDate: new Date()
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.form-control:focus {
|
||||
border-color: #198754;
|
||||
box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25);
|
||||
}
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
}
|
||||
.card-header {
|
||||
border-radius: 12px 12px 0 0 !important;
|
||||
}
|
||||
.font-weight-semibold {
|
||||
font-weight: 600;
|
||||
}
|
||||
.flatpickr-calendar {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 40px rgba(0,0,0,0.15);
|
||||
}
|
||||
</style>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,141 @@
|
||||
{% extends 'ups_manager/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h2 class="mb-0">添加主机维修记录</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.ups_host.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.ups_host.label }} <span class="text-danger">*</span>
|
||||
</label>
|
||||
{{ form.ups_host }}
|
||||
{% if form.ups_host.errors %}
|
||||
{% for error in form.ups_host.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.supplier.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.supplier.label }}
|
||||
</label>
|
||||
{{ form.supplier }}
|
||||
{% if form.supplier.errors %}
|
||||
{% for error in form.supplier.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.maintenance_date.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.maintenance_date.label }} <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
id="{{ form.maintenance_date.id_for_label }}"
|
||||
name="{{ form.maintenance_date.name }}"
|
||||
class="form-control datepicker"
|
||||
value="{{ form.maintenance_date.value|date:'Y-m-d' }}"
|
||||
placeholder="选择日期">
|
||||
{% if form.maintenance_date.errors %}
|
||||
{% for error in form.maintenance_date.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.technician.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.technician.label }} <span class="text-danger">*</span>
|
||||
</label>
|
||||
{{ form.technician }}
|
||||
{% if form.technician.errors %}
|
||||
{% for error in form.technician.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.content.id_for_label }}" class="form-label font-weight-semibold">
|
||||
{{ form.content.label }} <span class="text-danger">*</span>
|
||||
</label>
|
||||
{{ form.content }}
|
||||
{% if form.content.errors %}
|
||||
{% for error in form.content.errors %}
|
||||
<div class="invalid-feedback d-block">{{ error }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 d-flex justify-content-end gap-3">
|
||||
<a href="{% url 'maintenance_list' %}" class="btn btn-secondary px-6">
|
||||
<i class="fas fa-arrow-left mr-2"></i>取消
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary px-6">
|
||||
<i class="fas fa-save mr-2"></i>保存
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
flatpickr('.datepicker', {
|
||||
dateFormat: 'Y-m-d',
|
||||
locale: 'zh',
|
||||
allowInput: true,
|
||||
todayButton: true,
|
||||
clearButton: true,
|
||||
minDate: '1900-01-01',
|
||||
maxDate: new Date()
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.form-control:focus {
|
||||
border-color: #0d6efd;
|
||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
}
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
}
|
||||
.card-header {
|
||||
border-radius: 12px 12px 0 0 !important;
|
||||
}
|
||||
.font-weight-semibold {
|
||||
font-weight: 600;
|
||||
}
|
||||
.flatpickr-calendar {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 40px rgba(0,0,0,0.15);
|
||||
}
|
||||
</style>
|
||||
|
||||
{% endblock %}
|
||||
@@ -6,18 +6,22 @@
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<form method="get" class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<input type="text" name="ups_model" class="form-control" placeholder="UPS型号" value="{{ request.GET.ups_model }}">
|
||||
<div class="col-md-3">
|
||||
<input type="text" name="ups_host" class="form-control" placeholder="UPS型号" value="{{ request.GET.ups_host }}">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-3">
|
||||
<input type="text" name="technician" class="form-control" placeholder="维修人员" value="{{ request.GET.technician }}">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" name="supplier" class="form-control" placeholder="维保供应商" value="{{ request.GET.supplier }}">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-6 d-flex gap-2 align-items-end">
|
||||
<button type="submit" class="btn btn-primary">搜索</button>
|
||||
<a href="{% url 'maintenance_add' %}" class="btn btn-success float-end">添加维修记录</a>
|
||||
<div class="ms-auto">
|
||||
<a href="{% url 'host_maintenance_add' %}" class="btn btn-primary">
|
||||
<i class="fas fa-server me-1"></i>添加主机维修
|
||||
</a>
|
||||
<a href="{% url 'battery_maintenance_add' %}" class="btn btn-success ms-2">
|
||||
<i class="fas fa-battery-full me-1"></i>添加电池维修
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -26,18 +30,26 @@
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="100">维修类型</th>
|
||||
<th>UPS主机</th>
|
||||
<th>电池</th>
|
||||
<th>维保供应商</th>
|
||||
<th>维修日期</th>
|
||||
<th>维修内容</th>
|
||||
<th>维修人员</th>
|
||||
<th>操作</th>
|
||||
<th width="120">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for record in maintenance_list %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if record.maintenance_type == 'host' %}
|
||||
<span class="badge bg-primary">主机维修</span>
|
||||
{% else %}
|
||||
<span class="badge bg-success">电池维修</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ record.ups_host }}</td>
|
||||
<td>{{ record.battery|default:"-" }}</td>
|
||||
<td>{{ record.supplier|default:"-" }}</td>
|
||||
@@ -51,7 +63,7 @@
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="7" class="text-center text-muted">暂无维修记录</td>
|
||||
<td colspan="8" class="text-center text-muted">暂无维修记录</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
@@ -25,7 +25,8 @@ urlpatterns = [
|
||||
path('supplier/<int:pk>/delete/', views.SupplierDeleteView.as_view(), name='supplier_delete'),
|
||||
|
||||
path('maintenance/', views.MaintenanceListView.as_view(), name='maintenance_list'),
|
||||
path('maintenance/add/', views.MaintenanceCreateView.as_view(), name='maintenance_add'),
|
||||
path('maintenance/host/add/', views.HostMaintenanceCreateView.as_view(), name='host_maintenance_add'),
|
||||
path('maintenance/battery/add/', views.BatteryMaintenanceCreateView.as_view(), name='battery_maintenance_add'),
|
||||
path('maintenance/<int:pk>/edit/', views.MaintenanceUpdateView.as_view(), name='maintenance_edit'),
|
||||
path('maintenance/<int:pk>/delete/', views.MaintenanceDeleteView.as_view(), name='maintenance_delete'),
|
||||
]
|
||||
|
||||
@@ -285,17 +285,32 @@ class MaintenanceListView(ListView):
|
||||
return queryset.order_by('-maintenance_date')
|
||||
|
||||
|
||||
class MaintenanceCreateView(CreateView):
|
||||
class HostMaintenanceCreateView(CreateView):
|
||||
model = MaintenanceRecord
|
||||
template_name = 'ups_manager/maintenance_form.html'
|
||||
template_name = 'ups_manager/host_maintenance_form.html'
|
||||
fields = ['ups_host', 'supplier', 'maintenance_date', 'technician', 'content']
|
||||
success_url = reverse_lazy('maintenance_list')
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.maintenance_type = 'host'
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class BatteryMaintenanceCreateView(CreateView):
|
||||
model = MaintenanceRecord
|
||||
template_name = 'ups_manager/battery_maintenance_form.html'
|
||||
fields = ['ups_host', 'battery', 'supplier', 'maintenance_date', 'technician', 'content']
|
||||
success_url = reverse_lazy('maintenance_list')
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.maintenance_type = 'battery'
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class MaintenanceUpdateView(UpdateView):
|
||||
model = MaintenanceRecord
|
||||
template_name = 'ups_manager/maintenance_form.html'
|
||||
fields = ['ups_host', 'supplier', 'maintenance_date', 'technician', 'content']
|
||||
fields = ['ups_host', 'battery', 'supplier', 'maintenance_date', 'technician', 'content']
|
||||
success_url = reverse_lazy('maintenance_list')
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user