分支机构的项目管理,基于Django
This commit is contained in:
12
fzjgact/huodong/templates/admin/huodong/add_form.html
Normal file
12
fzjgact/huodong/templates/admin/huodong/add_form.html
Normal file
@@ -0,0 +1,12 @@
|
||||
{% extends "admin/change_form.html" %}
|
||||
{% load i18n admin_urls static admin_modify %}
|
||||
|
||||
{% block extrahead %}
|
||||
{{ block.super }}
|
||||
<script src="{% static 'admin/js/custom.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>自定义的添加表单</h1>
|
||||
{{ block.super }}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% extends "admin/change_list.html" %}
|
||||
|
||||
{% block actions %}
|
||||
{{ block.super }}
|
||||
<button type="submit" name="action" value="bulk_delete_selected" class="button" onclick="return confirm('确定要删除选中的图纸吗?')">执行批量删除</button>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% extends "admin/change_list.html" %}
|
||||
|
||||
{% block actions %}
|
||||
{{ block.super }}
|
||||
<button type="submit" name="action" value="bulk_delete_selected" class="button" onclick="return confirm('确定要删除选中的设备图片吗?')">执行批量删除</button>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% extends "admin/change_list.html" %}
|
||||
|
||||
{% block actions %}
|
||||
{{ block.super }}
|
||||
<button type="submit" name="action" value="bulk_delete_selected" class="button" onclick="return confirm('确定要删除选中的公共电子屏吗?')">执行批量删除</button>
|
||||
{% endblock %}
|
||||
101
fzjgact/huodong/templates/base.html
Normal file
101
fzjgact/huodong/templates/base.html
Normal file
@@ -0,0 +1,101 @@
|
||||
<!DOCTYPE html>
|
||||
{% load static %}
|
||||
{% load custom_filters %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{% static 'huodong/output.css' %}">
|
||||
<title>分支机构活动管理</title>
|
||||
<script src="https://unpkg.com/alpinejs@3.14.1/dist/cdn.min.js" defer></script>
|
||||
</head>
|
||||
<body class="font-sans text-gray-900">
|
||||
|
||||
<!-- 顶部标题 -->
|
||||
<header class="bg-gray-50 dark:bg-gray-800 dark:border-gray-700 p-4 text-center text-xl font-bold">
|
||||
分支机构活动管理
|
||||
<br>
|
||||
2025年
|
||||
</header>
|
||||
|
||||
<!-- 主体内容:左右两侧栏布局 -->
|
||||
<div class="flex">
|
||||
<!-- 左侧边栏 -->
|
||||
<aside class="w-27 bg-gray-300 p-4 ">
|
||||
{% block sidebar %}
|
||||
<ul class="flex flex-col space-y-8 text-lg">
|
||||
{% if request.resolver_match.view_name != 'branch-all' %}
|
||||
<li>
|
||||
<a href="{% url 'branch-all' %}" class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
返回首页
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{% url 'branchinfo' %}" class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
系统类型
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'statistics' %}" class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
活动的统计数据
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'contact-list' %}" class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
联系人信息
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'equipment-images' %}" class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
设备间图片列表
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'public-screens' %}" class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
公共电子屏列表
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'video-terminals' %}" class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
视频设备终端
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/admin/" class="bg-gradient-to-r from-gray-700 to-gray-900 hover:from-gray-800 hover:to-black text-white p-3 rounded-md font-medium shadow-lg transition-all duration-300 flex items-center justify-between border-l-4 border-amber-500" target="_blank">
|
||||
<div class="flex items-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3 text-amber-400" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path d="M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3zM6 8a2 2 0 11-4 0 2 2 0 014 0zM16 18v-3a5.972 5.972 0 00-.75-2.906A3.005 3.005 0 0119 15v3h-3zM4.75 12.094A5.973 5.973 0 004 15v3H1v-3a3 3 0 013.75-2.906z" />
|
||||
</svg>
|
||||
<span>后台管理</span>
|
||||
</div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-amber-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
</aside>
|
||||
|
||||
<!-- 主要内容区域 -->
|
||||
<main class="flex-1 bg-white p-4">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
|
||||
<!-- 右侧边栏 -->
|
||||
<!-- 注意:如果需要右侧边栏,请取消下方注释,并相应调整主内容区域的宽度 -->
|
||||
<!-- <aside class="w-1/3 bg-gray-300 p-4">
|
||||
Right Sidebar
|
||||
</aside> -->
|
||||
</div>
|
||||
|
||||
<!-- 页脚 -->
|
||||
<footer class="bg-gray-200 p-4 text-center mt-4">
|
||||
© 2025 My Website. All rights reserved.
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
292
fzjgact/huodong/templates/branch_all.html
Normal file
292
fzjgact/huodong/templates/branch_all.html
Normal file
@@ -0,0 +1,292 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load custom_filters %}
|
||||
|
||||
{% block content %}
|
||||
<div class="w-full max-w-4xl mx-auto p-6">
|
||||
<div class="relative">
|
||||
<!-- 时间线 -->
|
||||
<div class="absolute top-1/2 left-0 right-0 h-0.5 bg-blue-500 transform -translate-y-1/2"></div>
|
||||
|
||||
<div class="relative z-10 flex justify-between items-center">
|
||||
<!-- 第一个卡片 -->
|
||||
<div class="w-[calc(50%-2rem)] bg-white rounded-lg shadow-lg overflow-hidden transition-all duration-300 hover:shadow-xl">
|
||||
<div class="p-6 flex flex-col h-full">
|
||||
<div class="flex-grow">
|
||||
<div class="text-xs font-semibold text-blue-600 mb-2">最初活动</div>
|
||||
<h3 class="text-xl font-bold mb-3 text-gray-800">{{ earliest_act.branch }}{{ earliest_act.name }}</h3>
|
||||
<p class="text-sm text-gray-600 mb-4">
|
||||
{{ earliest_act.description }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
<span class="inline-flex items-center rounded-full bg-blue-100 px-3 py-1 text-xs font-medium text-blue-800 whitespace-nowrap">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="mr-1.5 h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
{{ earliest_act.start_time|format_chinese_full_date }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 中间的箭头 -->
|
||||
<div class="bg-white rounded-full p-3 shadow-md z-20">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- 第二个卡片 -->
|
||||
<div class="w-[calc(50%-2rem)] bg-white rounded-lg shadow-lg overflow-hidden transition-all duration-300 hover:shadow-xl">
|
||||
<div class="p-6 flex flex-col h-full">
|
||||
<div class="flex-grow">
|
||||
<div class="text-xs font-semibold text-blue-600 mb-2">最后活动</div>
|
||||
<h3 class="text-xl font-bold mb-3 text-gray-800">{{ latest_act.branch }}{{ latest_act.name }}</h3>
|
||||
<p class="text-sm text-gray-600 mb-4">
|
||||
{{ latest_act.description }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
<span class="inline-flex items-center rounded-full bg-blue-100 px-3 py-1 text-xs font-medium text-blue-800 whitespace-nowrap">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="mr-1.5 h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
{{ latest_act.start_time|format_chinese_full_date }} </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 装饰元素 -->
|
||||
<div class="absolute top-1/2 left-0 w-4 h-4 bg-blue-500 rounded-full transform -translate-y-1/2 border-4 border-white"></div>
|
||||
<div class="absolute top-1/2 right-0 w-4 h-4 bg-blue-500 rounded-full transform -translate-y-1/2 border-4 border-white"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<table class="items-center bg-transparent w-full border-collapse ">
|
||||
<thead>
|
||||
<tr class="bg-gray-100">
|
||||
<th class="px-6 bg-blueGray-50 text-blueGray-500 align-middle border border-solid border-blueGray-100 py-3 text-base uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left">
|
||||
分支机构名称
|
||||
<br>
|
||||
新建-搬迁-装修
|
||||
</th>
|
||||
<th class="px-6 bg-blueGray-50 text-blueGray-500 align-middle border border-solid border-blueGray-100 py-3 text-base uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-right">
|
||||
活动的总数量
|
||||
</th>
|
||||
<th class="px-6 bg-blueGray-50 text-blueGray-500 align-middle border border-solid border-blueGray-100 py-3 text-base uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-right">
|
||||
活动进行中的数量
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in branches %}
|
||||
<!-- 这里是其他行的处理逻辑 -->
|
||||
<tr class="{% if forloop.counter|divisibleby:2 %}bg-gray-100{% else %}bg-white{% endif %}">
|
||||
<td class="px-6 py-4 whitespace-no-wrap text-left border-b border-gray-200">
|
||||
<a href="{% url 'branch-detail' item.branch.pk %}"
|
||||
class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
{{ item.branch.name }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 text-right">
|
||||
{{ item.total_count }}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 text-right">
|
||||
{{ item.onging_count }}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<!-- 这里是最后一行的处理逻辑 -->
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-no-wrap text-left border-b border-gray-200 font-bold text-center">
|
||||
总计: {{ total_branch_count }}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 text-right">
|
||||
{{ total_activities }}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 text-right">
|
||||
{{ ongoing_activities_count }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<hr class="h-px my-8 bg-red-500 border-1 dark:bg-red-700">
|
||||
|
||||
|
||||
<!--插入事件-->
|
||||
<div class="p-5 border border-gray-100 rounded-lg bg-gray-50 dark:bg-gray-800 dark:border-gray-700">
|
||||
<time class="text-lg font-semibold text-gray-900 dark:text-white">事件</time>
|
||||
<ol class="mt-3 divide-y divider-gray-200 dark:divide-gray-700">
|
||||
{% for event in ongoing_events %}
|
||||
<li>
|
||||
<div href="#" class="items-center block p-3 sm:flex hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
<div class="text-gray-600 dark:text-gray-400">
|
||||
<span class="inline-flex items-center text-xs font-normal text-gray-400 dark:text-gray-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||
class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9"/>
|
||||
</svg>
|
||||
开始时间 {{ event.start_time| date:"Y年m月d日" }}
|
||||
</span>
|
||||
<div class="text-base font-normal">
|
||||
<span class="font-medium text-gray-900 dark:text-white">
|
||||
{% if not event.end_time %}
|
||||
<span class="text-lg font-semibold text-red-900 dark:text-white">
|
||||
{{ event.name }}-未完成
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="text-lg font-semibold text-blue-900 dark:text-white">
|
||||
{{ event.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-sm font-normal">
|
||||
{{ event.description }}
|
||||
</div>
|
||||
<span class="inline-flex items-center text-xs font-normal text-gray-400 dark:text-gray-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||
class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9"/>
|
||||
</svg>
|
||||
结束时间 {{ event.end_time| date:"Y年m月d日" }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<hr class="h-px my-8 bg-red-500 border-1 dark:bg-red-700">
|
||||
|
||||
|
||||
<div class="p-5 border border-gray-100 rounded-lg bg-gray-50 dark:bg-gray-800 dark:border-gray-700">
|
||||
<time class="text-lg font-semibold text-gray-900 dark:text-white">活动中的</time>
|
||||
<ol class="mt-3 divide-y divider-gray-200 dark:divide-gray-700">
|
||||
{% for huodong in ongoing_activities %}
|
||||
<li>
|
||||
<div href="#" class="items-center block p-3 sm:flex hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
<div class="text-gray-600 dark:text-gray-400">
|
||||
<span class="inline-flex items-center text-xs font-normal text-gray-400 dark:text-gray-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||
class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9"/>
|
||||
</svg>
|
||||
开始时间 {{ huodong.start_time| date:"Y年m月d日" }}
|
||||
</span>
|
||||
<div class="text-base font-normal">
|
||||
<span class="font-medium text-gray-900 dark:text-white">
|
||||
{% if not huodong.end_time %}
|
||||
<span class="text-lg font-semibold text-red-900 dark:text-white">
|
||||
<a href="{% url 'branch-detail' huodong.branch.pk %}"
|
||||
class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
{{ huodong.branch }}
|
||||
</a>
|
||||
{{ huodong.name }}-未完成
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-sm font-normal">
|
||||
{{ huodong.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<hr class="h-px my-8 bg-gray-200 border-0 dark:bg-gray-700">
|
||||
|
||||
{% for scope, scope_data in grouped_activities.items %}
|
||||
<div class="p-5 border border-gray-100 rounded-lg dark:bg-gray-800 dark:border-gray-700">
|
||||
<time class="text-lg font-semibold text-gray-900 dark:text-white">今年的{{ scope }}(共{{ scope_data.branch_count }}个分支机构)</time>
|
||||
<ol class="mt-3 divide-y divider-gray-200 dark:divide-gray-700">
|
||||
{% for activity in scope_data.activities %}
|
||||
<li style= "background-color: {{ activity.branch.background_color }};" >
|
||||
<div class="items-center block p-3 sm:flex hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
<div class="text-gray-600 dark:text-gray-400">
|
||||
<span class="inline-flex items-center text-xs font-normal text-gray-400 dark:text-gray-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9"/>
|
||||
</svg>
|
||||
开始时间 {{ activity.start_time| date:"Y年m月d日" }}
|
||||
</span>
|
||||
<div class="text-base font-normal">
|
||||
<span class="font-medium text-gray-900 dark:text-white">
|
||||
{% if not activity.end_time %}
|
||||
<span class="text-lg font-semibold text-red-900 dark:text-white">
|
||||
<a href="{% url 'branch-detail' activity.branch.pk %}"
|
||||
class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
{{ activity.branch }}
|
||||
</a>
|
||||
{{ activity.name }}-未完成
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="text-lg font-semibold text-gray-900 dark:text-white">
|
||||
<a href="{% url 'branch-detail' activity.branch.pk %}"
|
||||
class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
{{ activity.branch }}
|
||||
</a>
|
||||
{{ activity.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-sm font-normal">
|
||||
{{ activity.description }}
|
||||
</div>
|
||||
<span class="inline-flex items-center text-xs font-normal text-gray-400 dark:text-gray-400">
|
||||
<svg class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/>
|
||||
</svg>
|
||||
结束时间 {{ activity.end_time| date:"Y年m月d日" }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
<hr class="h-px my-8 bg-gray-200 border-0 dark:bg-gray-700">
|
||||
{% endfor %}
|
||||
|
||||
<time class="text-lg font-semibold text-gray-900 dark:text-white">
|
||||
今年的
|
||||
{% for scope, scope_data in grouped_activities.items %}
|
||||
{{ scope }}{{ scope_data.branch_count }}个{% if forloop.last %}。{% else %},{% endif %}
|
||||
{% endfor %}
|
||||
</time>
|
||||
<hr class="h-px my-8 bg-gray-200 border-0 dark:bg-gray-700">
|
||||
|
||||
<!-- 历年活动统计 -->
|
||||
{% for year in historical_years %}
|
||||
{% with year_data=historical_grouped_activities|get_item:year %}
|
||||
{% if year_data %}
|
||||
<time class="text-lg font-semibold text-gray-900 dark:text-white">
|
||||
{{ year }}年的
|
||||
{% for scope, scope_data in year_data.items %}
|
||||
{{ scope }}{{ scope_data.branch_count }}个{% if forloop.last %}。{% else %},{% endif %}
|
||||
{% endfor %}
|
||||
</time>
|
||||
<hr class="h-px my-8 bg-gray-200 border-0 dark:bg-gray-700">
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
145
fzjgact/huodong/templates/branch_detail.html
Normal file
145
fzjgact/huodong/templates/branch_detail.html
Normal file
@@ -0,0 +1,145 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<!-- Component starts here -->
|
||||
<h2 class="flex flex-row flex-nowrap items-center my-8">
|
||||
<span class="flex-grow block border-t border-black" aria-hidden="true" role="presentation"></span>
|
||||
<span class="flex-none block mx-4 px-4 py-2.5 text-base leading-none font-medium uppercase bg-black text-white">
|
||||
{{ branch.name }}
|
||||
</span>
|
||||
<span class="flex-grow block border-t border-black" aria-hidden="true" role="presentation"></span>
|
||||
</h2>
|
||||
<!-- Component ends here -->
|
||||
<div class="bg-white rounded-lg shadow-md p-4 mb-6">
|
||||
<h2 class="text-2xl font-bold mb-4">基本信息</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p class="text-gray-700"><strong>信息系统分类:</strong> {{ branch.category|default:"暂无" }}</p>
|
||||
<p class="text-gray-700"><strong>联系人:</strong> {{ branch.contact_person|default:"暂无" }}</p>
|
||||
<p class="text-gray-700"><strong>联系电话:</strong> {{ branch.contact_phone|default:"暂无" }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-gray-700"><strong>地址:</strong> {{ branch.address|default:"暂无" }}</p>
|
||||
<p class="text-gray-700"><strong>成立时间:</strong> {{ branch.established_date|date:"Y-m-d"|default:"暂无" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 事件信息 -->
|
||||
<div class="bg-white rounded-lg shadow-md p-4 mb-6">
|
||||
<h2 class="text-2xl font-bold mb-4">关联事件</h2>
|
||||
{% if events %}
|
||||
<div class="space-y-3">
|
||||
{% for event in events %}
|
||||
<div class="border-l-4 border-blue-500 pl-4 py-2 bg-blue-50 rounded">
|
||||
<h3 class="font-semibold text-lg">{{ event.name }}</h3>
|
||||
<p class="text-sm text-gray-600">
|
||||
{{ event.start_time|date:"Y-m-d H:i" }} - {{ event.end_time|date:"Y-m-d H:i"|default:"进行中" }}
|
||||
</p>
|
||||
<p class="mt-1 text-gray-700">{{ event.description|truncatechars:100 }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-gray-500 italic">暂无事件记录</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- 设备间图片 -->
|
||||
<div class="bg-white rounded-lg shadow-md p-4 mb-6">
|
||||
<h2 class="text-2xl font-bold mb-4">设备间图片</h2>
|
||||
{% if equipment_images %}
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
|
||||
{% for image in equipment_images %}
|
||||
<div class="overflow-hidden rounded-lg shadow">
|
||||
<img src="{{ image.image.url }}" alt="设备间图片" class="w-full h-48 object-cover">
|
||||
<div class="p-2 bg-gray-50">
|
||||
<p class="text-sm text-gray-700">{{ image.description|default:"无描述" }}</p>
|
||||
<p class="text-xs text-gray-500 mt-1">{{ image.upload_date|date:"Y-m-d" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-gray-500 italic">暂无设备间图片</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- 公共电子屏 -->
|
||||
<div class="bg-white rounded-lg shadow-md p-4 mb-6">
|
||||
<h2 class="text-2xl font-bold mb-4">公共电子屏</h2>
|
||||
{% if public_screens %}
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">类型</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">描述</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">最后演练</th>
|
||||
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">更新时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-200">
|
||||
{% for screen in public_screens %}
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ screen.get_screen_type_display }}</td>
|
||||
<td class="px-6 py-4">{{ screen.description|default:"无" }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ screen.last_drill.date|date:"Y-m-d"|default:"未演练" }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ screen.updated_at|date:"Y-m-d H:i" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-gray-500 italic">暂无公共电子屏信息</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% for scope, activities in grouped_activities.items %}
|
||||
|
||||
<div class="p-5 border border-gray-100 rounded-lg bg-gray-50 dark:bg-gray-800 dark:border-gray-700">
|
||||
<time class="text-lg font-semibold text-gray-900 dark:text-white">{{ scope }}</time>
|
||||
<ol class="mt-3 divide-y divider-gray-200 dark:divide-gray-700">
|
||||
{% for huodong in activities %}
|
||||
<li style="background-color: {{ huodong.branch.background_color }};">
|
||||
<div class="items-center block p-3 sm:flex hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||
<div class="text-gray-600 dark:text-gray-400">
|
||||
<span class="inline-flex items-center text-xs font-normal text-gray-400 dark:text-gray-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9" />
|
||||
</svg>
|
||||
开始时间 {{ huodong.start_time| date:"Y年m月d日" }}
|
||||
</span>
|
||||
<div class="text-base font-normal">
|
||||
<span class="font-medium text-gray-900 dark:text-white">
|
||||
{% if not huodong.end_time %}
|
||||
<span class="text-lg font-semibold text-red-900 dark:text-white">
|
||||
{{ huodong.name }}-未完成
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="text-lg font-semibold text-gray-900 dark:text-white">
|
||||
{{ huodong.name }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-sm font-normal">
|
||||
{{ huodong.description }}
|
||||
</div>
|
||||
<span class="inline-flex items-center text-xs font-normal text-gray-400 dark:text-gray-400">
|
||||
<svg class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/>
|
||||
</svg>
|
||||
结束时间 {{ huodong.end_time| date:"Y年m月d日" }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
<hr class="h-px my-8 bg-gray-200 border-0 dark:bg-gray-700">
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
59
fzjgact/huodong/templates/branch_info.html
Normal file
59
fzjgact/huodong/templates/branch_info.html
Normal file
@@ -0,0 +1,59 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<table class="items-center bg-transparent w-full border-collapse ">
|
||||
<thead>
|
||||
<tr class="bg-gray-100">
|
||||
<th class="px-6 bg-blueGray-50 text-blueGray-500 align-middle border border-solid border-blueGray-100 py-3 text-base uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left">
|
||||
分支机构名称
|
||||
<br>
|
||||
基础信息
|
||||
</th>
|
||||
<th class="px-6 bg-blueGray-50 text-blueGray-500 align-middle border border-solid border-blueGray-100 py-3 text-base uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left">
|
||||
信息系统类别
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in branches %}
|
||||
<!-- 这里是其他行的处理逻辑 -->
|
||||
<tr class="{% if forloop.counter|divisibleby:2 %}bg-gray-100{% else %}bg-white{% endif %}">
|
||||
<td class="px-6 py-4 whitespace-no-wrap text-left border-b border-gray-200">
|
||||
<a href="{% url 'branch-detail' item.pk %}"
|
||||
class="bg-transparent hover:bg-blue-900 hover:text-white p-2 rounded-md">
|
||||
{{ item.name }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-no-wrap text-left border-b border-gray-200">
|
||||
{{ item.category }}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="bg-gray-50">
|
||||
<td colspan="2" class="px-6 py-4 text-right border-b border-gray-200">
|
||||
<div class="flex justify-end space-x-3">
|
||||
<a href="{% url 'export-branches-xls' %}" class="inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-black font-medium rounded-lg shadow-md transition duration-150 ease-in-out transform hover:scale-105">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
导出为XLS
|
||||
</a>
|
||||
<a href="{% url 'export-branches-pdf' %}" class="inline-flex items-center px-4 py-2 bg-purple-600 hover:bg-purple-800 text-black font-medium rounded-lg shadow-md transition duration-300 ease-in-out transform hover:scale-105 hover:shadow-lg">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
导出为PDF
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<hr class="h-px my-8 bg-red-500 border-1 dark:bg-red-700">
|
||||
{% endblock %}
|
||||
310
fzjgact/huodong/templates/contact_list.html
Normal file
310
fzjgact/huodong/templates/contact_list.html
Normal file
@@ -0,0 +1,310 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mx-auto p-4">
|
||||
<h2 class="text-xl font-bold mb-4">联系人信息</h2>
|
||||
|
||||
<!-- 新增筛选表单 -->
|
||||
<form method="GET" class="mb-4 p-4 bg-gray-100 rounded-lg" id="filterForm">
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<!-- 分支机构筛选(带搜索的下拉框) -->
|
||||
<div class="flex flex-col w-full md:w-1/3">
|
||||
<label class="text-sm font-medium">分支机构</label>
|
||||
<div class="relative" id="branchSelectContainer">
|
||||
<!-- 选择框主体 -->
|
||||
<div class="relative">
|
||||
<input
|
||||
type="text"
|
||||
id="branchSearchInput"
|
||||
class="w-full pl-4 pr-10 py-2.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-300 focus:border-blue-500 outline-none text-sm"
|
||||
placeholder="输入分支机构名称搜索..."
|
||||
readonly
|
||||
onclick="toggleBranchDropdown()"
|
||||
>
|
||||
<span class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 transition-transform duration-200" id="branchArrowIcon">
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</span>
|
||||
<!-- 隐藏的分支机构ID输入框(用于表单提交) -->
|
||||
<input type="hidden" name="branch" id="selectedBranchId">
|
||||
</div>
|
||||
|
||||
<!-- 下拉内容 -->
|
||||
<div id="branchDropdownContent" class="absolute z-10 mt-1 w-full bg-white rounded-lg shadow-md overflow-hidden hidden">
|
||||
<!-- 搜索输入框 -->
|
||||
<div class="p-2 border-b border-gray-100">
|
||||
<input
|
||||
type="text"
|
||||
id="branchFilterInput"
|
||||
class="w-full px-3 py-2 border border-gray-200 rounded-lg focus:ring-1 focus:ring-blue-300 focus:border-blue-500 outline-none text-sm"
|
||||
placeholder="搜索分支机构..."
|
||||
oninput="filterBranchOptions()"
|
||||
autofocus
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- 选项列表 -->
|
||||
<div id="branchOptionsList" class="max-h-60 overflow-y-auto">
|
||||
<ul>
|
||||
{% for branch in branches %}
|
||||
<li class="branch-option px-4 py-2.5 hover:bg-gray-100 cursor-pointer text-sm transition-colors"
|
||||
data-id="{{ branch.id }}"
|
||||
data-name="{{ branch.name }}">
|
||||
{{ branch.name }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 无结果提示 -->
|
||||
<div id="branchNoResult" class="px-4 py-4 text-center text-gray-500 text-sm hidden">
|
||||
没有找到匹配的分支机构
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 联系人类别筛选(改为带搜索的下拉框) -->
|
||||
<div class="flex flex-col w-full md:w-1/3">
|
||||
<label class="text-sm font-medium">联系人类别</label>
|
||||
<div class="relative" id="categorySelectContainer">
|
||||
<div class="relative">
|
||||
<input
|
||||
type="text"
|
||||
id="categorySearchInput"
|
||||
class="w-full pl-4 pr-10 py-2.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-300 focus:border-blue-500 outline-none text-sm"
|
||||
placeholder="输入类别名称搜索..."
|
||||
readonly
|
||||
onclick="toggleCategoryDropdown()"
|
||||
value="{{ selected_category|default:'' }}"
|
||||
>
|
||||
<span class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 transition-transform duration-200" id="categoryArrowIcon">
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</span>
|
||||
<input type="hidden" name="category" id="selectedCategory">
|
||||
</div>
|
||||
|
||||
<div id="categoryDropdownContent" class="absolute z-10 mt-1 w-full bg-white rounded-lg shadow-md overflow-hidden hidden">
|
||||
<div class="p-2 border-b border-gray-100">
|
||||
<input
|
||||
type="text"
|
||||
id="categoryFilterInput"
|
||||
class="w-full px-3 py-2 border border-gray-200 rounded-lg focus:ring-1 focus:ring-blue-300 focus:border-blue-500 outline-none text-sm"
|
||||
placeholder="搜索联系人类别..."
|
||||
oninput="filterCategoryOptions()"
|
||||
autofocus
|
||||
>
|
||||
</div>
|
||||
|
||||
<div id="categoryOptionsList" class="max-h-60 overflow-y-auto">
|
||||
<ul>
|
||||
{% for cat in categories %}
|
||||
<li class="category-option px-4 py-2.5 hover:bg-gray-100 cursor-pointer text-sm transition-colors"
|
||||
data-value="{{ cat }}">
|
||||
{{ cat }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="categoryNoResult" class="px-4 py-4 text-center text-gray-500 text-sm hidden">
|
||||
没有找到匹配的类别
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 联系人姓名筛选(保持原结构) -->
|
||||
<div class="flex flex-col w-full md:w-1/3">
|
||||
<label class="text-sm font-medium">联系人姓名</label>
|
||||
<input type="text" name="contact_name" class="mt-1 p-2 border rounded" placeholder="输入联系人姓名筛选" value="{{ selected_contact_name|default:'' }}">
|
||||
</div>
|
||||
|
||||
<div class="flex items-end">
|
||||
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">筛选</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="min-w-full border-collapse border border-gray-300">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">分支机构</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">分类</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">姓名</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">电话</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">邮箱</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for contact in contacts %}
|
||||
<tr class="{% cycle 'bg-white' 'bg-gray-50' %}">
|
||||
<td class="p-2 border border-gray-300">{{ contact.branch.name }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ contact.category|default:"" }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ contact.name|default:"" }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ contact.phone|default:"" }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ contact.email|default:"" }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="5" class="p-4 text-center text-gray-500">没有找到匹配的联系人</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 控制分支机构下拉框显示/隐藏
|
||||
function toggleBranchDropdown() {
|
||||
const dropdown = document.getElementById('branchDropdownContent');
|
||||
const arrow = document.getElementById('branchArrowIcon');
|
||||
if (dropdown.classList.contains('hidden')) {
|
||||
dropdown.classList.remove('hidden');
|
||||
arrow.classList.add('rotate-180');
|
||||
document.getElementById('branchFilterInput').focus();
|
||||
document.addEventListener('click', handleBranchOutsideClick);
|
||||
} else {
|
||||
closeBranchDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭分支机构下拉框
|
||||
function closeBranchDropdown() {
|
||||
const dropdown = document.getElementById('branchDropdownContent');
|
||||
const arrow = document.getElementById('branchArrowIcon');
|
||||
dropdown.classList.add('hidden');
|
||||
arrow.classList.remove('rotate-180');
|
||||
document.removeEventListener('click', handleBranchOutsideClick);
|
||||
}
|
||||
|
||||
// 点击外部关闭下拉框
|
||||
function handleBranchOutsideClick(event) {
|
||||
const container = document.getElementById('branchSelectContainer');
|
||||
if (!container.contains(event.target)) {
|
||||
closeBranchDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
// 筛选分支机构选项
|
||||
function filterBranchOptions() {
|
||||
const searchText = document.getElementById('branchFilterInput').value.toLowerCase();
|
||||
const options = document.querySelectorAll('.branch-option');
|
||||
const noResult = document.getElementById('branchNoResult');
|
||||
let hasMatch = false;
|
||||
|
||||
let firstMatch = null;
|
||||
options.forEach(option => {
|
||||
const name = option.dataset.name.toLowerCase();
|
||||
if (name.includes(searchText)) {
|
||||
option.style.display = 'block';
|
||||
hasMatch = true;
|
||||
if (!firstMatch) firstMatch = option;
|
||||
} else {
|
||||
option.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
noResult.classList.toggle('hidden', hasMatch);
|
||||
// 自动滚动到第一个匹配项
|
||||
if (firstMatch) {
|
||||
firstMatch.scrollIntoView({block: 'nearest'});
|
||||
firstMatch.classList.add('bg-blue-50');
|
||||
setTimeout(() => firstMatch.classList.remove('bg-blue-50'), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// 选择分支机构选项
|
||||
document.querySelectorAll('.branch-option').forEach(option => {
|
||||
option.addEventListener('click', function() {
|
||||
const name = this.dataset.name;
|
||||
const id = this.dataset.id;
|
||||
document.getElementById('branchSearchInput').value = name;
|
||||
document.getElementById('selectedBranchId').value = id;
|
||||
closeBranchDropdown();
|
||||
});
|
||||
});
|
||||
|
||||
// 键盘导航(可选)
|
||||
document.getElementById('branchFilterInput').addEventListener('keydown', function(e) {
|
||||
const options = document.querySelectorAll('.branch-option:not([style*="display: "])');
|
||||
const active = document.querySelector('.branch-option.bg-gray-100');
|
||||
let index = -1;
|
||||
|
||||
if (active) index = Array.from(options).indexOf(active);
|
||||
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
if (active) active.classList.remove('bg-gray-100');
|
||||
const next = (index + 1) % options.length;
|
||||
options[next]?.classList.add('bg-gray-100');
|
||||
options[next]?.scrollIntoView({ block: 'nearest' });
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
if (active) active.classList.remove('bg-gray-100');
|
||||
const prev = index > 0 ? index - 1 : options.length - 1;
|
||||
options[prev]?.classList.add('bg-gray-100');
|
||||
options[prev]?.scrollIntoView({ block: 'nearest' });
|
||||
} else if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
active?.click();
|
||||
}
|
||||
});
|
||||
|
||||
// 新增联系人类别下拉框控制函数
|
||||
function toggleCategoryDropdown() {
|
||||
const dropdown = document.getElementById('categoryDropdownContent');
|
||||
const arrow = document.getElementById('categoryArrowIcon');
|
||||
if (dropdown.classList.contains('hidden')) {
|
||||
dropdown.classList.remove('hidden');
|
||||
arrow.classList.add('rotate-180');
|
||||
document.getElementById('categoryFilterInput').focus();
|
||||
document.addEventListener('click', handleCategoryOutsideClick);
|
||||
} else {
|
||||
closeCategoryDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
function closeCategoryDropdown() {
|
||||
const dropdown = document.getElementById('categoryDropdownContent');
|
||||
const arrow = document.getElementById('categoryArrowIcon');
|
||||
dropdown.classList.add('hidden');
|
||||
arrow.classList.remove('rotate-180');
|
||||
document.removeEventListener('click', handleCategoryOutsideClick);
|
||||
}
|
||||
|
||||
function handleCategoryOutsideClick(event) {
|
||||
const container = document.getElementById('categorySelectContainer');
|
||||
if (!container.contains(event.target)) {
|
||||
closeCategoryDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
function filterCategoryOptions() {
|
||||
const searchText = document.getElementById('categoryFilterInput').value.toLowerCase();
|
||||
const options = document.querySelectorAll('.category-option');
|
||||
const noResult = document.getElementById('categoryNoResult');
|
||||
let hasMatch = false;
|
||||
|
||||
options.forEach(option => {
|
||||
const value = option.dataset.value.toLowerCase();
|
||||
if (value.includes(searchText)) {
|
||||
option.style.display = 'block';
|
||||
hasMatch = true;
|
||||
} else {
|
||||
option.style.display = '';
|
||||
}
|
||||
});
|
||||
|
||||
noResult.classList.toggle('hidden', hasMatch || !searchText);
|
||||
}
|
||||
|
||||
document.querySelectorAll('.category-option').forEach(option => {
|
||||
option.addEventListener('click', function() {
|
||||
const value = this.dataset.value;
|
||||
document.getElementById('categorySearchInput').value = value;
|
||||
document.getElementById('selectedCategory').value = value;
|
||||
closeCategoryDropdown();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
174
fzjgact/huodong/templates/equipment_images.html
Normal file
174
fzjgact/huodong/templates/equipment_images.html
Normal file
@@ -0,0 +1,174 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<h1 class="text-3xl font-bold mb-8 text-center">分支机构设备间图片列表</h1>
|
||||
<div class="flex justify-center mb-6">
|
||||
<form method="get" action="" class="w-full max-w-md">
|
||||
<div class="flex">
|
||||
<input type="text" name="search" placeholder="搜索分支机构名称..." value="{{ request.GET.search }}"
|
||||
class="flex-1 px-4 py-2 border border-gray-300 rounded-l-md focus:outline-none focus:ring-2 focus:ring-blue-500">
|
||||
<button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded-r-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
||||
搜索
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<p class="text-gray-600 mb-6 text-center">共 {{ total_count }} 个分支机构</p>
|
||||
|
||||
{% if branches %}
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
||||
{% for branch in branches %}
|
||||
<div class="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow duration-300">
|
||||
<div class="p-4">
|
||||
<h2 class="text-xl font-semibold text-gray-900 mb-1">{{ branch.name }}</h2>
|
||||
<a href="{% url 'branch-detail' branch.id %}" class="text-blue-600 hover:text-blue-800 text-sm font-medium">
|
||||
查看分支机构详情 →
|
||||
</a>
|
||||
</div>
|
||||
<div class="bg-gray-100 p-2">
|
||||
{% if branch.equipment_images.exists %}
|
||||
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2">
|
||||
{% for image in branch.equipment_images.all %}
|
||||
<img src="{{ image.image.url }}" alt="{{ branch.name }}设备间图片"
|
||||
class="h-[100px] md:h-[150px] lg:h-[200px] w-auto object-cover cursor-pointer"
|
||||
data-branch-id="{{ branch.id }}" data-image-type="equipment" data-index="{{ forloop.counter0 }}"
|
||||
onclick="openImageModal(this)">
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="flex items-center justify-center h-48 bg-gray-200">
|
||||
<span class="text-gray-400 text-sm">无图片</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- 图纸显示区域 -->
|
||||
<div class="bg-gray-100 p-2 mt-4">
|
||||
<h3 class="text-lg font-semibold mb-2">图纸</h3>
|
||||
{% if branch.drawings.exists %}
|
||||
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2">
|
||||
{% for drawing in branch.drawings.all %}
|
||||
<img src="{{ drawing.image.url }}" alt="{{ branch.name }}图纸"
|
||||
class="h-[100px] md:h-[150px] lg:h-[200px] w-auto object-cover cursor-pointer"
|
||||
data-branch-id="{{ branch.id }}" data-image-type="drawings" data-index="{{ forloop.counter0 }}"
|
||||
onclick="openImageModal(this)">
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="flex items-center justify-center h-48 bg-gray-200">
|
||||
<span class="text-gray-400 text-sm">无图纸</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- 图片查看模态框 -->
|
||||
<div id="imageModal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden">
|
||||
<div class="relative">
|
||||
<button id="prevBtn" onclick="navigateImage(-1)" class="absolute left-2 top-1/2 transform -translate-y-1/2 text-white text-4xl font-bold focus:outline-none hover:text-gray-300 z-10 bg-black bg-opacity-50 px-2 py-1 rounded">👈</button>
|
||||
<button onclick="closeImageModal()" class="absolute -top-10 right-0 text-white text-2xl font-bold">×</button>
|
||||
<img id="modalImage" src="" alt="大图预览" class="max-w-full max-h-[90vh]">
|
||||
<div id="imageCounter" class="absolute -bottom-8 left-0 right-0 text-center text-white text-lg"></div>
|
||||
<button id="nextBtn" onclick="navigateImage(1)" class="absolute right-2 top-1/2 transform -translate-y-1/2 text-white text-4xl font-bold focus:outline-none hover:text-gray-300 z-10 bg-black bg-opacity-50 px-2 py-1 rounded">👉</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.branchImages = {};
|
||||
{% for branch in branches %}
|
||||
window.branchImages[{{ branch.id }}] = {
|
||||
equipment: [{% for img in branch.equipment_images.all %}"{{ img.image.url|escapejs }}"{% if not forloop.last %},{% endif %}{% endfor %}],
|
||||
drawings: [{% for img in branch.drawings.all %}"{{ img.image.url|escapejs }}"{% if not forloop.last %},{% endif %}{% endfor %}]
|
||||
};
|
||||
{% endfor %}
|
||||
|
||||
var currentImages = [];
|
||||
var currentIndex = 0;
|
||||
|
||||
function openImageModal(element) {
|
||||
const branchId = element.dataset.branchId;
|
||||
const imageType = element.dataset.imageType;
|
||||
currentIndex = parseInt(element.dataset.index);
|
||||
currentImages = window.branchImages[branchId][imageType];
|
||||
|
||||
document.getElementById('modalImage').src = currentImages[currentIndex];
|
||||
updateNavigationButtons();
|
||||
updateImageCounter();
|
||||
|
||||
document.getElementById('imageModal').classList.remove('hidden');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function navigateImage(direction) {
|
||||
currentIndex += direction;
|
||||
if (currentIndex < 0) currentIndex = 0;
|
||||
if (currentIndex >= currentImages.length) currentIndex = currentImages.length - 1;
|
||||
|
||||
document.getElementById('modalImage').src = currentImages[currentIndex];
|
||||
updateNavigationButtons();
|
||||
updateImageCounter();
|
||||
}
|
||||
|
||||
function updateNavigationButtons() {
|
||||
const prevBtn = document.getElementById('prevBtn');
|
||||
const nextBtn = document.getElementById('nextBtn');
|
||||
|
||||
prevBtn.style.display = currentIndex === 0 ? 'none' : 'block';
|
||||
nextBtn.style.display = currentIndex === currentImages.length - 1 ? 'none' : 'block';
|
||||
}
|
||||
|
||||
function updateImageCounter() {
|
||||
document.getElementById('imageCounter').textContent =
|
||||
`${currentIndex + 1}/${currentImages.length}`;
|
||||
}
|
||||
|
||||
function closeImageModal() {
|
||||
document.getElementById('imageModal').classList.add('hidden');
|
||||
document.body.style.overflow = 'auto'; // 恢复背景滚动
|
||||
}
|
||||
|
||||
// 点击模态框背景也可关闭
|
||||
document.getElementById('imageModal').addEventListener('click', function(e) {
|
||||
if (e.target === this) {
|
||||
closeImageModal();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- 分页控件 -->
|
||||
<div class="mt-10 flex justify-center">
|
||||
<nav class="inline-flex rounded-md shadow">
|
||||
{% if branches.has_previous %}
|
||||
<a href="?page=1" class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
|
||||
首页
|
||||
</a>
|
||||
<a href="?page={{ branches.previous_page_number }}" class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
|
||||
上一页
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<span class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-blue-50 text-sm font-medium text-blue-700">
|
||||
第 {{ branches.number }} 页,共 {{ branches.paginator.num_pages }} 页
|
||||
</span>
|
||||
|
||||
{% if branches.has_next %}
|
||||
<a href="?page={{ branches.next_page_number }}" class="relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
|
||||
下一页
|
||||
</a>
|
||||
<a href="?page={{ branches.paginator.num_pages }}" class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50">
|
||||
末页
|
||||
</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-12 bg-gray-50 rounded-lg">
|
||||
<p class="text-gray-500 text-lg">暂无分支机构设备间图片数据</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
94
fzjgact/huodong/templates/public_screens.html
Normal file
94
fzjgact/huodong/templates/public_screens.html
Normal file
@@ -0,0 +1,94 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mx-auto p-4">
|
||||
<h1 class="text-2xl font-bold mb-6">公共电子屏列表</h1>
|
||||
|
||||
<!-- 筛选区域 -->
|
||||
<div class="bg-gray-100 p-4 rounded-lg mb-6">
|
||||
<form method="get" class="flex flex-col md:flex-row gap-4">
|
||||
<div>
|
||||
<label class="block mb-2">分支机构</label>
|
||||
<select name="branch" class="border rounded p-2 w-full md:w-48">
|
||||
<option value="">所有分支机构</option>
|
||||
{% for branch in branches %}
|
||||
<option value="{{ branch.id }}" {% if request.GET.branch == branch.id|stringformat:"i" %}selected{% endif %}>{{ branch.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block mb-2">屏幕类型</label>
|
||||
<select name="screen_type" class="border rounded p-2 w-full md:w-48">
|
||||
<option value="">所有类型</option>
|
||||
<option value="marquee" {% if request.GET.screen_type == 'marquee' %}selected{% endif %}>跑马灯</option>
|
||||
<option value="advertisement" {% if request.GET.screen_type == 'advertisement' %}selected{% endif %}>广告屏</option>
|
||||
<option value="information" {% if request.GET.screen_type == 'information' %}selected{% endif %}>信息发布屏</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="self-end">
|
||||
<button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded">筛选</button>
|
||||
{% if request.GET.branch or request.GET.screen_type %}
|
||||
<a href="{% url 'public-screens' %}" class="ml-2 text-gray-600">清除筛选</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 电子屏列表 -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{% for screen in public_screens %}
|
||||
<div class="border rounded-lg overflow-hidden shadow-md hover:shadow-lg transition-shadow">
|
||||
<div class="relative">
|
||||
<img src="{{ screen.image.url }}" alt="{{ screen.get_screen_type_display }}" class="w-full h-[150px] object-cover cursor-pointer" onclick="openModal('{{ screen.image.url }}')">
|
||||
<div class="absolute top-2 right-2 bg-black bg-opacity-50 text-white px-2 py-1 rounded text-sm">
|
||||
{{ screen.get_screen_type_display }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<h3 class="font-semibold text-lg mb-2">{{ screen.branch.name }}</h3>
|
||||
{% if screen.description %}
|
||||
<p class="text-gray-700 mb-2">{{ screen.description|truncatechars:100 }}</p>
|
||||
{% endif %}
|
||||
<div class="text-sm text-gray-500">
|
||||
{% if screen.last_drill %}
|
||||
<p>最后演练: {{ screen.last_drill.date|date:"Y-m-d H:i" }}</p>
|
||||
{% else %}
|
||||
<p class="text-yellow-500">暂无演练记录</p>
|
||||
{% endif %}
|
||||
<p>更新时间: {{ screen.updated_at|date:"Y-m-d H:i" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-span-full text-center py-10">
|
||||
<p class="text-gray-500">暂无公共电子屏记录</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 图片预览模态框 -->
|
||||
<div id="imageModal" class="fixed inset-0 bg-black bg-opacity-80 flex items-center justify-center hidden z-50">
|
||||
<button onclick="closeModal()" class="absolute top-4 right-4 text-white text-2xl">×</button>
|
||||
<img id="modalImage" src="" alt="大图预览" class="max-w-[90%] max-h-[90vh]">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function openModal(imageUrl) {
|
||||
document.getElementById('modalImage').src = imageUrl;
|
||||
document.getElementById('imageModal').classList.remove('hidden');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
document.getElementById('imageModal').classList.add('hidden');
|
||||
document.body.style.overflow = 'auto';
|
||||
}
|
||||
|
||||
// 点击模态框背景关闭
|
||||
document.getElementById('imageModal').addEventListener('click', function(e) {
|
||||
if (e.target === this) closeModal();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
238
fzjgact/huodong/templates/searchable-select.html
Normal file
238
fzjgact/huodong/templates/searchable-select.html
Normal file
@@ -0,0 +1,238 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>带搜索功能的下拉选择框</title>
|
||||
<!-- 引入 Tailwind CSS -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<!-- 引入 Font Awesome -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
|
||||
<!-- 配置 Tailwind 自定义颜色 -->
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: '#3B82F6',
|
||||
secondary: '#64748B',
|
||||
neutral: '#F1F5F9',
|
||||
},
|
||||
fontFamily: {
|
||||
inter: ['Inter', 'sans-serif'],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- 自定义工具类 -->
|
||||
<style type="text/tailwindcss">
|
||||
@layer utilities {
|
||||
.content-auto {
|
||||
content-visibility: auto;
|
||||
}
|
||||
.dropdown-shadow {
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
.transition-custom {
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-50 min-h-screen font-inter text-gray-800">
|
||||
<div class="container mx-auto px-4 py-16 max-w-2xl">
|
||||
<h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-gray-900 mb-8 text-center">带搜索功能的下拉选择框</h1>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-lg p-8">
|
||||
<div class="mb-8">
|
||||
<label for="searchSelect" class="block text-sm font-medium text-gray-700 mb-2">请选择城市</label>
|
||||
<!-- 搜索选择框容器 -->
|
||||
<div class="relative" id="searchSelectContainer">
|
||||
<!-- 选择框主体 -->
|
||||
<div class="relative">
|
||||
<input
|
||||
type="text"
|
||||
id="searchSelect"
|
||||
class="w-full pl-4 pr-10 py-2.5 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary/30 focus:border-primary outline-none transition-all text-sm"
|
||||
placeholder="输入城市名称搜索..."
|
||||
readonly
|
||||
onclick="toggleDropdown()"
|
||||
>
|
||||
<span class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 transition-transform duration-200" id="arrowIcon">
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 下拉内容 -->
|
||||
<div id="dropdownContent" class="absolute z-10 mt-1 w-full bg-white rounded-lg dropdown-shadow overflow-hidden hidden">
|
||||
<!-- 搜索输入框 -->
|
||||
<div class="p-2 border-b border-gray-100">
|
||||
<input
|
||||
type="text"
|
||||
id="searchInput"
|
||||
class="w-full px-3 py-2 border border-gray-200 rounded-lg focus:ring-1 focus:ring-primary focus:border-primary outline-none text-sm"
|
||||
placeholder="搜索城市..."
|
||||
oninput="filterOptions()"
|
||||
autofocus
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- 选项列表 -->
|
||||
<div id="optionsList" class="max-h-60 overflow-y-auto">
|
||||
<ul>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="beijing">北京</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="shanghai">上海</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="guangzhou">广州</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="shenzhen">深圳</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="hangzhou">杭州</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="nanjing">南京</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="chengdu">成都</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="chongqing">重庆</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="wuhan">武汉</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="xian">西安</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="suzhou">苏州</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="tianjin">天津</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="qingdao">青岛</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="xiamen">厦门</li>
|
||||
<li class="option px-4 py-2.5 hover:bg-neutral cursor-pointer text-sm transition-custom" data-value="sanya">三亚</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 无结果提示 -->
|
||||
<div id="noResult" class="px-4 py-4 text-center text-gray-500 text-sm hidden">
|
||||
没有找到匹配的城市
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 选择结果显示 -->
|
||||
<div id="selectedResult" class="mt-4 text-sm text-gray-600 hidden">
|
||||
<p>你选择的城市是:<span id="selectedValue" class="font-medium text-primary"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center">
|
||||
<p class="text-gray-500 text-sm">点击选择框,开始输入城市名称进行搜索</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 控制下拉框显示/隐藏
|
||||
function toggleDropdown() {
|
||||
const dropdownContent = document.getElementById('dropdownContent');
|
||||
const arrowIcon = document.getElementById('arrowIcon');
|
||||
|
||||
if (dropdownContent.classList.contains('hidden')) {
|
||||
dropdownContent.classList.remove('hidden');
|
||||
arrowIcon.classList.add('rotate-180');
|
||||
document.getElementById('searchInput').focus();
|
||||
// 点击外部关闭下拉框
|
||||
document.addEventListener('click', handleOutsideClick);
|
||||
} else {
|
||||
closeDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭下拉框
|
||||
function closeDropdown() {
|
||||
const dropdownContent = document.getElementById('dropdownContent');
|
||||
const arrowIcon = document.getElementById('arrowIcon');
|
||||
|
||||
dropdownContent.classList.add('hidden');
|
||||
arrowIcon.classList.remove('rotate-180');
|
||||
document.removeEventListener('click', handleOutsideClick);
|
||||
}
|
||||
|
||||
// 点击外部关闭下拉框
|
||||
function handleOutsideClick(event) {
|
||||
const container = document.getElementById('searchSelectContainer');
|
||||
if (!container.contains(event.target)) {
|
||||
closeDropdown();
|
||||
}
|
||||
}
|
||||
|
||||
// 筛选选项
|
||||
function filterOptions() {
|
||||
const searchText = document.getElementById('searchInput').value.toLowerCase();
|
||||
const options = document.querySelectorAll('.option');
|
||||
const noResult = document.getElementById('noResult');
|
||||
let hasMatch = false;
|
||||
|
||||
options.forEach(option => {
|
||||
const text = option.textContent.toLowerCase();
|
||||
if (text.includes(searchText)) {
|
||||
option.style.display = 'block';
|
||||
hasMatch = true;
|
||||
} else {
|
||||
option.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// 显示或隐藏无结果提示
|
||||
if (searchText && !hasMatch) {
|
||||
noResult.classList.remove('hidden');
|
||||
} else {
|
||||
noResult.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// 选择选项
|
||||
document.querySelectorAll('.option').forEach(option => {
|
||||
option.addEventListener('click', function() {
|
||||
const value = this.textContent;
|
||||
document.getElementById('searchSelect').value = value;
|
||||
document.getElementById('selectedValue').textContent = value;
|
||||
document.getElementById('selectedResult').classList.remove('hidden');
|
||||
closeDropdown();
|
||||
});
|
||||
});
|
||||
|
||||
// 键盘导航
|
||||
document.getElementById('searchInput').addEventListener('keydown', function(e) {
|
||||
const options = document.querySelectorAll('.option:not([style*="display: none"])');
|
||||
const activeOption = document.querySelector('.option.bg-neutral');
|
||||
let index = -1;
|
||||
|
||||
if (activeOption) {
|
||||
index = Array.from(options).indexOf(activeOption);
|
||||
}
|
||||
|
||||
// 向下箭头
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
if (activeOption) {
|
||||
activeOption.classList.remove('bg-neutral');
|
||||
}
|
||||
const nextIndex = (index + 1) % options.length;
|
||||
if (options[nextIndex]) {
|
||||
options[nextIndex].classList.add('bg-neutral');
|
||||
options[nextIndex].scrollIntoView({ block: 'nearest' });
|
||||
}
|
||||
}
|
||||
// 向上箭头
|
||||
else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
if (activeOption) {
|
||||
activeOption.classList.remove('bg-neutral');
|
||||
}
|
||||
const prevIndex = index > 0 ? index - 1 : options.length - 1;
|
||||
if (options[prevIndex]) {
|
||||
options[prevIndex].classList.add('bg-neutral');
|
||||
options[prevIndex].scrollIntoView({ block: 'nearest' });
|
||||
}
|
||||
}
|
||||
// 回车键
|
||||
else if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
if (activeOption) {
|
||||
activeOption.click();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
79
fzjgact/huodong/templates/statistics.html
Normal file
79
fzjgact/huodong/templates/statistics.html
Normal file
@@ -0,0 +1,79 @@
|
||||
{% extends "base.html" %}
|
||||
{% load custom_filters %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mx-auto p-4">
|
||||
<!-- 筛选表单 -->
|
||||
<form method="GET" class="mb-8 p-4 bg-gray-100 rounded-lg">
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<!-- 年份选择 -->
|
||||
<div class="flex flex-col">
|
||||
<label class="text-sm font-medium">选择年份</label>
|
||||
<select name="year" class="mt-1 p-2 border rounded">
|
||||
<option value="all">全部年份</option>
|
||||
<option value="2023" {% if selected_year == '2023' %}selected{% endif %}>2023年</option>
|
||||
<option value="2024" {% if selected_year == '2024' %}selected{% endif %}>2024年</option>
|
||||
<option value="2025" {% if selected_year == '2025' %}selected{% endif %}>2025年</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 分支机构选择 -->
|
||||
<div class="flex flex-col">
|
||||
<label class="text-sm font-medium">分支机构</label>
|
||||
<select name="branch" class="mt-1 p-2 border rounded">
|
||||
<option value="all" {% if selected_branch == 'all' %}selected{% endif %}>全部分支机构</option>
|
||||
{% for branch in branches %}
|
||||
<option value="{{ branch.id }}" {% if selected_branch == branch.id|stringformat:"s" %}selected{% endif %}>
|
||||
{{ branch.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 状态选择 -->
|
||||
<div class="flex flex-col">
|
||||
<label class="text-sm font-medium">活动状态</label>
|
||||
<select name="status" class="mt-1 p-2 border rounded">
|
||||
<option value="completed" {% if selected_status == 'completed' %}selected{% endif %}>已完成</option>
|
||||
<option value="ongoing" {% if selected_status == 'ongoing' %}selected{% endif %}>未完成</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="self-end px-4 py-2 bg-blue-200 text-white rounded hover:bg-blue-700">
|
||||
筛选
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- 统计结果展示 -->
|
||||
<div class="mt-4">
|
||||
<h2 class="text-xl font-bold mb-4">活动统计结果(共{{ activities.count }}条)</h2>
|
||||
<table class="min-w-full border-collapse border border-gray-300">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">活动名称</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">分支机构</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">活动分类</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">开始时间</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">结束时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for activity in activities %}
|
||||
<tr>
|
||||
<td class="p-2 border border-gray-300">{{ activity.name }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ activity.branch.name }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ activity.scope }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ activity.start_time|format_chinese_full_date }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ activity.end_time|format_chinese_full_date|default:"未结束" }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td class="p-2 border border-gray-300 text-center" colspan="4">无符合条件的活动记录</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
94
fzjgact/huodong/templates/video_terminals.html
Normal file
94
fzjgact/huodong/templates/video_terminals.html
Normal file
@@ -0,0 +1,94 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mx-auto p-4">
|
||||
<h2 class="text-xl font-bold mb-4">视频设备终端列表</h2>
|
||||
|
||||
<!-- 筛选表单 -->
|
||||
<form method="GET" class="mb-4 p-4 bg-gray-100 rounded-lg">
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<!-- 分支机构筛选 -->
|
||||
<div class="flex flex-col w-full md:w-1/3">
|
||||
<label class="text-sm font-medium">分支机构</label>
|
||||
<div x-data="{ open: false, search: '{{ selected_branch_name|default:'' }}', selectedId: '{{ selected_branch|default:'' }}', branches: [{% for branch in branches %}{id: {{ branch.id }}, name: '{{ branch.name }}'}{% if not forloop.last %},{% endif %}{% endfor %}] }" class="relative">
|
||||
<input type="text"
|
||||
x-model="search"
|
||||
@focus="open = true"
|
||||
@input.debounce.300ms="open = true"
|
||||
@click.away="open = false"
|
||||
placeholder="搜索分支机构..."
|
||||
class="mt-1 p-2 border rounded w-full"
|
||||
x-on:keydown.backspace="if (!search) selectedId = ''; search = ''"
|
||||
>
|
||||
<div x-show="open" class="absolute z-10 mt-1 w-full bg-white border rounded shadow-lg max-h-60 overflow-y-auto">
|
||||
<div @click="selectedId = ''; search = ''; open = false" class="p-2 hover:bg-gray-100 cursor-pointer">全部分支机构</div>
|
||||
<div x-for="branch in branches.filter(b => b.name.toLowerCase().includes(search.toLowerCase()))"
|
||||
:key="branch.id"
|
||||
@click="selectedId = branch.id; search = branch.name; open = false"
|
||||
class="p-2 hover:bg-gray-100 cursor-pointer"
|
||||
x-text="branch.name"
|
||||
></div>
|
||||
</div>
|
||||
<input type="hidden" name="branch" x-model="selectedId">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 设备类型筛选 -->
|
||||
<div class="flex flex-col w-full md:w-1/3">
|
||||
<label class="text-sm font-medium">设备类型</label>
|
||||
<div x-data="{ open: false, search: '{{ selected_type_name|default:'' }}', selectedCode: '{{ selected_type|default:'' }}', types: [{% for type_code, type_name in terminal_types %}{code: '{{ type_code }}', name: '{{ type_name }}'}{% if not forloop.last %},{% endif %}{% endfor %}] }" class="relative">
|
||||
<input type="text"
|
||||
x-model="search"
|
||||
@focus="open = true"
|
||||
@input.debounce.300ms="open = true"
|
||||
@click.away="open = false"
|
||||
placeholder="搜索设备类型..."
|
||||
class="mt-1 p-2 border rounded w-full"
|
||||
x-on:keydown.backspace="if (!search) selectedCode = ''; search = ''"
|
||||
>
|
||||
<div x-show="open" class="absolute z-10 mt-1 w-full bg-white border rounded shadow-lg max-h-60 overflow-y-auto">
|
||||
<div @click="selectedCode = ''; search = ''; open = false" class="p-2 hover:bg-gray-100 cursor-pointer">全部类型</div>
|
||||
<div x-for="type in types.filter(t => t.name.toLowerCase().includes(search.toLowerCase()))"
|
||||
:key="type.code"
|
||||
@click="selectedCode = type.code; search = type.name; open = false"
|
||||
class="p-2 hover:bg-gray-100 cursor-pointer"
|
||||
x-text="type.name"
|
||||
></div>
|
||||
</div>
|
||||
<input type="hidden" name="type" x-model="selectedCode">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-end">
|
||||
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">筛选</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- 终端列表表格 -->
|
||||
<table class="min-w-full border-collapse border border-gray-300">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">分支机构</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">设备类型</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">设备描述</th>
|
||||
<th class="p-2 border border-gray-300 bg-gray-100">创建时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for terminal in terminals %}
|
||||
<tr class="{% cycle 'bg-white' 'bg-gray-50' %}">
|
||||
<td class="p-2 border border-gray-300">{{ terminal.branch.name }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ terminal.get_terminal_type_display }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ terminal.description|default:"" }}</td>
|
||||
<td class="p-2 border border-gray-300">{{ terminal.created_at|date:"Y-m-d H:i" }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="4" class="p-4 text-center text-gray-500">没有找到匹配的视频设备终端</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user