v1.0.0: 希姆计算资产管理系统正式版

This commit is contained in:
cnbugs
2026-04-25 08:29:01 +08:00
parent a40a0137cf
commit 855547d70f
11 changed files with 279 additions and 18 deletions
+17 -8
View File
@@ -13,6 +13,7 @@ EXPORT_COLUMNS = [
('category', '设备分类', 12),
('brand', '品牌', 12),
('model', '型号', 20),
('asset_value', '资产面值', 12),
('serial_number', '序列号', 25),
('location', '设备位置', 20),
('cabinet', '机柜', 10),
@@ -23,6 +24,8 @@ EXPORT_COLUMNS = [
('warranty_expire', '质保到期', 12),
('supplier', '供应商', 15),
('responsible_person', '负责人', 10),
('department', '使用部门', 15),
('user', '使用人', 10),
('status', '状态', 8),
('remark', '备注', 30),
]
@@ -100,8 +103,8 @@ def generate_import_template():
# 示例数据行
example_data = [
'IT-2024-0001', '测试服务器', '服务器', 'Dell', 'PowerEdge R740',
'ABC123456', '3楼机房A区', 'A01', 'U10-U15', '192.168.1.200',
'192.168.1.100', '2024-01-15', '2027-01-15', '戴尔科技', '张三', '在用', '测试备注'
'50000.00', 'ABC123456', '3楼机房A区', 'A01', 'U10-U15', '192.168.1.200',
'192.168.1.100', '2024-01-15', '2027-01-15', '戴尔科技', '张三', '研发部', '李四', '在用', '测试备注'
]
for col_idx, value in enumerate(example_data, 1):
cell = ws.cell(row=2, column=col_idx, value=value)
@@ -147,12 +150,6 @@ def import_assets_from_excel(ws, category_map, operator=None):
results['errors'].append(f'{row_idx}行: 缺少资产编号')
continue
# 检查重复
if Asset.objects.filter(asset_number=asset_number).exists():
results['skipped'] += 1
results['errors'].append(f'{row_idx}行: 资产编号 {asset_number} 已存在')
continue
# 处理分类 - 不存在则自动创建
category_name = data.get('category', '').strip()
category = category_map.get(category_name)
@@ -187,12 +184,22 @@ def import_assets_from_excel(ws, category_map, operator=None):
bmc_address = data.get('bmc_address') or None
ip_address = data.get('ip_address') or None
# 处理资产面值
from decimal import Decimal, InvalidOperation
asset_value = None
if data.get('asset_value'):
try:
asset_value = Decimal(str(data['asset_value']).replace(',', ''))
except (InvalidOperation, ValueError):
pass
asset = Asset.objects.create(
asset_number=asset_number,
name=data.get('name', ''),
category=category,
brand=data.get('brand', ''),
model=data.get('model', ''),
asset_value=asset_value,
serial_number=data.get('serial_number', ''),
location=data.get('location', ''),
cabinet=data.get('cabinet', ''),
@@ -203,6 +210,8 @@ def import_assets_from_excel(ws, category_map, operator=None):
warranty_expire=warranty_expire,
supplier=data.get('supplier', ''),
responsible_person=data.get('responsible_person', ''),
department=data.get('department', ''),
user=data.get('user', ''),
status=status,
remark=data.get('remark', ''),
created_by=operator,
+2 -2
View File
@@ -6,10 +6,10 @@ class AssetForm(forms.ModelForm):
class Meta:
model = Asset
fields = [
'asset_number', 'name', 'category', 'brand', 'model', 'serial_number',
'asset_number', 'name', 'category', 'brand', 'model', 'asset_value', 'serial_number',
'location', 'cabinet', 'cabinet_position', 'bmc_address', 'ip_address',
'purchase_date', 'warranty_expire', 'supplier',
'responsible_person', 'status', 'remark',
'responsible_person', 'department', 'user', 'status', 'remark',
]
widgets = {
'purchase_date': forms.DateInput(attrs={'type': 'date'}),
@@ -0,0 +1,18 @@
# Generated by Django 5.2.13 on 2026-04-25 00:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assetapp', '0002_asset_bmc_address'),
]
operations = [
migrations.AlterField(
model_name='asset',
name='asset_number',
field=models.CharField(db_index=True, max_length=50, verbose_name='资产编号'),
),
]
@@ -0,0 +1,23 @@
# Generated by Django 5.2.13 on 2026-04-25 00:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assetapp', '0003_alter_asset_asset_number'),
]
operations = [
migrations.AddField(
model_name='asset',
name='department',
field=models.CharField(blank=True, default='', max_length=100, verbose_name='使用部门'),
),
migrations.AddField(
model_name='asset',
name='user',
field=models.CharField(blank=True, default='', max_length=50, verbose_name='使用人'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.2.13 on 2026-04-25 00:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assetapp', '0004_asset_department_asset_user'),
]
operations = [
migrations.AddField(
model_name='asset',
name='asset_value',
field=models.DecimalField(blank=True, decimal_places=2, max_digits=12, null=True, verbose_name='资产面值'),
),
]
+4 -1
View File
@@ -29,13 +29,14 @@ class Asset(models.Model):
]
# 基本信息
asset_number = models.CharField('资产编号', max_length=50, unique=True, db_index=True)
asset_number = models.CharField('资产编号', max_length=50, db_index=True)
name = models.CharField('设备名称', max_length=100)
category = models.ForeignKey(Category, on_delete=models.PROTECT, verbose_name='设备分类', related_name='assets')
# 硬件信息
brand = models.CharField('品牌', max_length=50, blank=True, default='')
model = models.CharField('型号', max_length=100, blank=True, default='')
asset_value = models.DecimalField('资产面值', max_digits=12, decimal_places=2, blank=True, null=True)
serial_number = models.CharField('序列号', max_length=100, blank=True, default='', db_index=True)
# 位置信息
@@ -54,6 +55,8 @@ class Asset(models.Model):
# 管理信息
responsible_person = models.CharField('负责人', max_length=50, blank=True, default='')
department = models.CharField('使用部门', max_length=100, blank=True, default='')
user = models.CharField('使用人', max_length=50, blank=True, default='')
status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='in_use')
remark = models.TextField('备注', blank=True, default='')
+5 -3
View File
@@ -99,7 +99,9 @@ def asset_list(request):
Q(brand__icontains=search) |
Q(model__icontains=search) |
Q(location__icontains=search) |
Q(responsible_person__icontains=search)
Q(responsible_person__icontains=search) |
Q(department__icontains=search) |
Q(user__icontains=search)
)
# 筛选
@@ -116,8 +118,8 @@ def asset_list(request):
queryset = queryset.filter(location__icontains=location)
# 排序
sort = request.GET.get('sort', '-created_at')
valid_sorts = ['asset_number', '-asset_number', 'name', '-name',
sort = request.GET.get('sort', 'id')
valid_sorts = ['id', '-id', 'asset_number', '-asset_number', 'name', '-name',
'created_at', '-created_at', 'updated_at', '-updated_at',
'purchase_date', '-purchase_date']
if sort not in valid_sorts: