Files
fzjg_local/fzjgact/huodong/views.py

609 lines
23 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from rest_framework import viewsets
from .models import Branch, Activity, Evaluation, Event, VideoTerminal, Budget, EquipmentBudget, InfrastructureBudget, BudgetTemplate, TemplateEquipmentItem, TemplateInfrastructureItem
from .serializers import BranchSerializer, ActivitySerializer, EvaluationSerializer
from django.shortcuts import render, redirect
from .models import PublicScreen
from collections import defaultdict
from datetime import datetime
from django.db.models import Q
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import Contact
from django.template.defaulttags import register
from django.http import HttpResponse
import openpyxl
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
import os
@register.filter
def get_item(dictionary, key):
return dictionary.get(key)
class BranchViewSet(viewsets.ModelViewSet):
queryset = Branch.objects.all()
serializer_class = BranchSerializer
class ActivityViewSet(viewsets.ModelViewSet):
queryset = Activity.objects.all()
serializer_class = ActivitySerializer
class EvaluationViewSet(viewsets.ModelViewSet):
queryset = Evaluation.objects.all()
serializer_class = EvaluationSerializer
# 在页面上显示id为branch的详细信息
def branch_detail(request, branch_id):
# 获取分支机构及其所有关联数据
branch = Branch.objects.get(pk=branch_id)
# 获取并分组活动
activities = Activity.objects.filter(branch=branch).order_by('start_time')
grouped_activities = defaultdict(list)
for activity in activities:
grouped_activities[activity.scope].append(activity)
grouped_activities = dict(grouped_activities)
# 获取其他关联数据
events = branch.events.all().order_by('-start_time')
equipment_images = branch.equipment_images.all()
public_screens = branch.public_screens.all()
# 获取预算数据
budgets = Budget.objects.filter(branch=branch).prefetch_related('equipment_budgets', 'infrastructure_budgets').order_by('-created_at')
# 获取预算模板
budget_templates = BudgetTemplate.objects.all()
# 准备上下文数据
context = {
'branch': branch,
'grouped_activities': grouped_activities,
'events': events,
'equipment_images': equipment_images,
'public_screens': public_screens,
'budgets': budgets,
'activities': activities,
'budget_templates': budget_templates,
}
return render(request, 'branch_detail.html', context)
def import_budget_template(request, branch_id):
"""从模板导入预算"""
if request.method == 'POST':
template_id = request.POST.get('template')
budget_name = request.POST.get('budget_name', '导入预算')
if template_id:
try:
# 获取模板和分支机构
template = BudgetTemplate.objects.get(pk=template_id)
branch = Branch.objects.get(pk=branch_id)
# 创建预算
budget = Budget.objects.create(
branch=branch,
name=budget_name
)
# 导入设备预算项
for equipment_item in template.equipment_items.all():
EquipmentBudget.objects.create(
budget=budget,
project=equipment_item.project,
model=equipment_item.model,
unit_price=equipment_item.unit_price,
procurement_method=equipment_item.procurement_method,
quantity=1 # 默认数量为1
)
# 导入基础设施预算项
for infrastructure_item in template.infrastructure_items.all():
InfrastructureBudget.objects.create(
budget=budget,
name=infrastructure_item.name,
remarks=infrastructure_item.remarks,
unit_price=infrastructure_item.unit_price,
unit=infrastructure_item.unit,
description=infrastructure_item.description,
quantity=1 # 默认数量为1
)
# 更新总预算
budget.update_total_budget()
except Exception as e:
print(f"导入预算模板失败: {e}")
return redirect('branch-detail', branch_id=branch_id)
# 在页面上显示所有的branch以及active的数量首页显示
def BranchAll(request):
branches = Branch.objects.exclude(activity__isnull=True).order_by('name')
branches_with_counts = [{'branch': branch,
'total_count': Activity.objects.filter(branch=branch).count(),
'onging_count': Activity.objects.filter(branch=branch, end_time__isnull=True).count()}
for branch in branches]
# 返回总数
total_branch_count = len(branches_with_counts)
# 获取所有分支机构总数(包括没有活动的)
all_branch_count = Branch.objects.count()
# 比如说end_time()的year是2024年但是now()是2025年的2月fileter出来但是如果now()是2025年3月则不显示
now = datetime.now()
print(f"当前月份是{now.month},年是{now.year}")
if now.month <= 2:
two_months_ago_year = now.year - 1
activities = Activity.objects.filter(
Q(start_time__year=now.year) | Q(start_time__year=two_months_ago_year)).order_by('branch')
else:
activities = Activity.objects.filter(start_time__year=now.year).order_by('branch')
# 返回起止时间
earliest_act = activities.order_by('start_time').first()
print(earliest_act)
latest_act = activities.order_by('start_time').last()
print(latest_act)
# 确保earliest_act和latest_act不为None时才使用
# 按activities按照scope分组
grouped_activities = defaultdict(lambda: {'activities': [], 'branch_count': 0})
for activity in activities:
grouped_activities[activity.scope]['activities'].append(activity)
# 计算每个scope的分支机构数量
for scope_data in grouped_activities.values():
activity_ids = [a.id for a in scope_data['activities']]
scope_data['branch_count'] = Activity.objects.filter(id__in=activity_ids).values('branch').distinct().count()
# 转换为普通字典以便模板遍历
grouped_activities = dict(grouped_activities)
# 统计活动中的事件即end_time为空的活动
ongoing_activities = Activity.objects.filter(end_time__isnull=True).order_by('branch','start_time')
# 统计活动的总的数量
total_activities = Activity.objects.count()
# 统计活动中的事件的总数
ongoing_activities_count = ongoing_activities.count()
branch_count = activities.values('branch').distinct().count()
# 事件的展示
ongoing_events = Event.objects.all().order_by('start_time')
# 获取历年活动数据
historical_years = []
historical_grouped_activities = {}
# 获取最早的年份
earliest_activity = Activity.objects.order_by('start_time').first()
if earliest_activity:
earliest_year = earliest_activity.start_time.year
current_year = datetime.now().year
# 从去年开始,逐年递减,直到最早的年份
for year in range(current_year - 1, earliest_year - 1, -1):
# 获取该年份的活动
year_activities = Activity.objects.filter(start_time__year=year).order_by('branch')
# 如果该年份有活动数据
if year_activities.exists():
historical_years.append(year)
# 按照scope分组
year_grouped_activities = defaultdict(lambda: {'activities': [], 'branch_count': 0})
for activity in year_activities:
year_grouped_activities[activity.scope]['activities'].append(activity)
# 计算每个scope的分支机构数量
for scope_data in year_grouped_activities.values():
activity_ids = [a.id for a in scope_data['activities']]
scope_data['branch_count'] = Activity.objects.filter(id__in=activity_ids).values('branch').distinct().count()
# 转换为普通字典
historical_grouped_activities[year] = dict(year_grouped_activities)
# 把带有活动数量的branches字典列表传递给模板
context = {'branches': branches_with_counts,
'grouped_activities': grouped_activities,
'earliest_act': earliest_act,
'latest_act': latest_act,
'total_branch_count':total_branch_count,
'all_branch_count': all_branch_count,
'branch_count': branch_count,
'ongoing_activities': ongoing_activities,
'total_activities': total_activities,
'ongoing_activities_count': ongoing_activities_count,
'ongoing_events': ongoing_events,
'historical_years': historical_years,
'historical_grouped_activities': historical_grouped_activities
}
return render(request, 'branch_all.html', context)
# 生成branchinfo的视图
def Branchinfo(request):
branches = Branch.objects.all()
# 统计A型、B型、C型分支机构的数量
type_a_count = branches.filter(category='A型').count()
type_b_count = branches.filter(category='B型').count()
type_c_count = branches.filter(category='C型').count()
context = {
'branches': branches,
'type_a_count': type_a_count,
'type_b_count': type_b_count,
'type_c_count': type_c_count,
}
return render(request, 'branch_info.html', context)
def Statistics(request):
# 默认筛选条件2024年、全部分支机构、完成状态end_time不为空
selected_year = request.GET.get('year', '2025')
selected_branch = request.GET.get('branch', 'all') # 'all'表示全部分支机构
selected_status = request.GET.get('status', 'completed') # 'completed'表示完成状态
# 构建查询条件
filters = Q()
# 年份筛选
if selected_year != 'all':
filters &= Q(start_time__year=selected_year)
# 分支机构筛选
if selected_branch != 'all':
filters &= Q(branch_id=selected_branch)
# 状态筛选完成状态end_time不为空未完成end_time为空
if selected_status == 'completed':
filters &= ~Q(end_time__isnull=True)
else:
filters &= Q(end_time__isnull=True)
# 获取符合条件的活动
activities = Activity.objects.filter(filters).order_by('start_time')
# 获取所有分支机构用于下拉选择
branches = Branch.objects.all()
context = {
'activities': activities,
'branches': branches,
'selected_year': selected_year,
'selected_branch': selected_branch,
'selected_status': selected_status
}
return render(request, 'statistics.html', context)
# 导出分支机构信息为XLS文件
def export_branches_xls(request):
# 创建一个工作簿
workbook = openpyxl.Workbook()
worksheet = workbook.active
worksheet.title = "分支机构信息"
# 添加表头
headers = ['分支机构名称', '信息系统类别']
for col_num, header in enumerate(headers, 1):
worksheet.cell(row=1, column=col_num, value=header)
# 获取所有分支机构数据
branches = Branch.objects.all()
# 填充数据
for row_num, branch in enumerate(branches, 2):
worksheet.cell(row=row_num, column=1, value=branch.name)
worksheet.cell(row=row_num, column=2, value=branch.category)
# 设置响应
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="branches_info.xls"'
# 保存工作簿到响应
workbook.save(response)
return response
# 导出分支机构信息为PDF文件
def export_branches_pdf(request):
# 创建响应对象
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="branches_info.pdf"'
# 注册中文字体
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
# 尝试注册系统中文字体这里使用Windows系统自带的中文字体
try:
# 尝试注册微软雅黑字体
pdfmetrics.registerFont(TTFont('MSYaHei', 'C:/Windows/Fonts/msyh.ttc'))
chinese_font = 'MSYaHei'
except:
try:
# 如果微软雅黑不存在,尝试注册宋体
pdfmetrics.registerFont(TTFont('SimSun', 'C:/Windows/Fonts/simsun.ttc'))
chinese_font = 'SimSun'
except:
# 如果都找不到,使用默认字体(可能仍会有乱码)
chinese_font = 'Helvetica'
# 创建PDF文档
doc = SimpleDocTemplate(response, pagesize=letter)
elements = []
# 添加标题
styles = getSampleStyleSheet()
# 复制Title样式并修改字体
title_style = ParagraphStyle(
'ChineseTitle',
parent=styles['Title'],
fontName=chinese_font,
fontSize=18,
spaceAfter=30,
alignment=1 # 1表示居中
)
title = Paragraph("分支机构信息", title_style)
elements.append(title)
# 获取所有分支机构数据
branches = Branch.objects.all()
# 准备表格数据
data = [['分支机构名称', '信息系统类别']] # 表头
for branch in branches:
data.append([branch.name, branch.category])
# 创建表格
table = Table(data)
# 设置表格样式
style = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), chinese_font), # 使用中文字体
('FONTSIZE', (0, 0), (-1, 0), 14),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
('FONTNAME', (0, 1), (-1, -1), chinese_font), # 使用中文字体
('GRID', (0, 0), (-1, -1), 1, colors.black)
])
table.setStyle(style)
# 添加表格到文档
elements.append(table)
# 构建PDF
doc.build(elements)
return response
def public_screens(request):
branches = Branch.objects.all()
public_screens = PublicScreen.objects.all().order_by('-created_at')
return render(request, 'public_screens.html', {
'branches': branches,
'public_screens': public_screens,
})
def equipment_images(request):
# 获取搜索参数
search_query = request.GET.get('search', '')
# 根据搜索参数筛选分支机构
if search_query:
branches_with_images = Branch.objects.prefetch_related('equipment_images', 'drawings').filter(name__icontains=search_query)
else:
branches_with_images = Branch.objects.prefetch_related('equipment_images', 'drawings').all()
# 分页处理每页显示12个分支机构
paginator = Paginator(branches_with_images, 12)
page = request.GET.get('page')
try:
branches = paginator.page(page)
except PageNotAnInteger:
# 如果页码不是整数,返回第一页
branches = paginator.page(1)
except EmptyPage:
# 如果页码超出范围,返回最后一页
branches = paginator.page(paginator.num_pages)
context = {
'branches': branches,
'total_count': branches_with_images.count(),
'search_query': search_query
}
return render(request, 'equipment_images.html', context)
def contact_list(request):
# 获取筛选参数
branches_param = request.GET.get('branches') # 支持多机构选择使用逗号分隔的ID字符串
category = request.GET.get('category')
contact_name = request.GET.get('contact_name')
# 构建查询条件
filters = Q()
# 分支机构筛选(支持多选)
if branches_param:
# 将逗号分隔的字符串转换为ID列表
branch_ids = [bid.strip() for bid in branches_param.split(',') if bid.strip().isdigit()]
if branch_ids:
filters &= Q(branch_id__in=branch_ids)
# 联系人类别筛选
if category:
filters &= Q(category__contains=category)
# 联系人姓名筛选
if contact_name:
filters &= Q(name__icontains=contact_name)
# 获取筛选后的联系人
contacts = Contact.objects.filter(filters)
# 获取所有分支机构和联系人类别用于下拉选择
branches = Branch.objects.all()
categories = [choice[0] for choice in Contact.CATEGORY_CHOICES]
context = {
'contacts': contacts,
'branches': branches,
'categories': categories,
'selected_branches': branches_param, # 传递选中的机构ID字符串
'selected_category': category,
'selected_contact_name': contact_name
}
return render(request, 'contact_list.html', context)
def video_terminal_list(request):
# 获取筛选参数
selected_branch = request.GET.get('branch', '')
selected_type = request.GET.get('type', '')
# 获取选中项的名称用于前端显示
selected_branch_name = ''
if selected_branch:
try:
selected_branch_name = Branch.objects.get(id=selected_branch).name
except Branch.DoesNotExist:
pass
selected_type_name = ''
if selected_type:
for code, name in VideoTerminal.TERMINAL_TYPE_CHOICES:
if code == selected_type:
selected_type_name = name
break
# 基础查询集
terminals = VideoTerminal.objects.all().order_by('branch__name', 'terminal_type')
# 应用筛选条件
if selected_branch:
terminals = terminals.filter(branch_id=selected_branch)
if selected_type:
terminals = terminals.filter(terminal_type=selected_type)
# 获取所有分支机构和终端类型用于筛选下拉框
branches = Branch.objects.all()
terminal_types = VideoTerminal.TERMINAL_TYPES
context = {
'terminals': terminals,
'branches': branches,
'terminal_types': terminal_types,
'selected_branch': selected_branch,
'selected_type': selected_type,
'selected_branch_name': selected_branch_name,
'selected_type_name': selected_type_name,
}
return render(request, 'video_terminals.html', context)
# 预算相关视图
def create_budget(request, branch_id):
branch = Branch.objects.get(pk=branch_id)
activities = Activity.objects.filter(branch=branch)
if request.method == 'POST':
activity_id = request.POST.get('activity')
if activity_id:
activity = Activity.objects.get(pk=activity_id)
budget = Budget.objects.create(branch=branch, activity=activity)
return redirect('budget_detail', branch_id=branch_id, budget_id=budget.id)
context = {
'branch': branch,
'activities': activities,
}
return render(request, 'create_budget.html', context)
def budget_detail(request, branch_id, budget_id):
branch = Branch.objects.get(pk=branch_id)
budget = Budget.objects.get(pk=budget_id, branch=branch)
context = {
'branch': branch,
'budget': budget,
}
return render(request, 'budget_detail.html', context)
def add_equipment_budget(request, branch_id, budget_id):
branch = Branch.objects.get(pk=branch_id)
budget = Budget.objects.get(pk=budget_id, branch=branch)
if request.method == 'POST':
project = request.POST.get('project')
model = request.POST.get('model')
unit_price = request.POST.get('unit_price')
procurement_method = request.POST.get('procurement_method')
quantity = request.POST.get('quantity', 1)
if project and model and unit_price and procurement_method:
EquipmentBudget.objects.create(
budget=budget,
project=project,
model=model,
unit_price=unit_price,
procurement_method=procurement_method,
quantity=quantity
)
return redirect('budget_detail', branch_id=branch_id, budget_id=budget_id)
def add_infrastructure_budget(request, branch_id, budget_id):
branch = Branch.objects.get(pk=branch_id)
budget = Budget.objects.get(pk=budget_id, branch=branch)
if request.method == 'POST':
name = request.POST.get('name')
remarks = request.POST.get('remarks')
unit_price = request.POST.get('unit_price')
unit = request.POST.get('unit')
description = request.POST.get('description')
quantity = request.POST.get('quantity', 1)
if name and unit_price and unit:
InfrastructureBudget.objects.create(
budget=budget,
name=name,
remarks=remarks,
unit_price=unit_price,
unit=unit,
description=description,
quantity=quantity
)
return redirect('budget_detail', branch_id=branch_id, budget_id=budget_id)
def delete_equipment_budget(request, branch_id, budget_id, equipment_budget_id):
branch = Branch.objects.get(pk=branch_id)
budget = Budget.objects.get(pk=budget_id, branch=branch)
equipment_budget = EquipmentBudget.objects.get(pk=equipment_budget_id, budget=budget)
equipment_budget.delete()
return redirect('budget_detail', branch_id=branch_id, budget_id=budget_id)
def delete_infrastructure_budget(request, branch_id, budget_id, infrastructure_budget_id):
branch = Branch.objects.get(pk=branch_id)
budget = Budget.objects.get(pk=budget_id, branch=branch)
infrastructure_budget = InfrastructureBudget.objects.get(pk=infrastructure_budget_id, budget=budget)
infrastructure_budget.delete()
return redirect('budget_detail', branch_id=branch_id, budget_id=budget_id)