commit f0cbf2c2ec211de804c50b80bcabc106e85b1577 Author: XIAJI-NEW\qax Date: Tue Nov 11 11:09:01 2025 +0800 分支机构的项目管理,基于Django diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..359bb53 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml diff --git a/.idea/CopilotChatHistory.xml b/.idea/CopilotChatHistory.xml new file mode 100644 index 0000000..5fb759b --- /dev/null +++ b/.idea/CopilotChatHistory.xml @@ -0,0 +1,3816 @@ + + + + + + \ No newline at end of file diff --git a/.idea/fzjg-activation.iml b/.idea/fzjg-activation.iml new file mode 100644 index 0000000..d0876a7 --- /dev/null +++ b/.idea/fzjg-activation.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..49ada17 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,27 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..b2d336e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..5b07bcd --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/count_lines.py b/count_lines.py new file mode 100644 index 0000000..9acbdc8 --- /dev/null +++ b/count_lines.py @@ -0,0 +1,66 @@ +import os +import sys + +def count_lines_in_file(file_path): + """统计单个文件的行数""" + try: + with open(file_path, 'r', encoding='utf-8') as file: + return sum(1 for _ in file) + except UnicodeDecodeError: + try: + with open(file_path, 'r', encoding='gbk') as file: + return sum(1 for _ in file) + except UnicodeDecodeError: + print(f"无法解码文件: {file_path}") + return 0 + except Exception as e: + print(f"读取文件 {file_path} 时出错: {e}") + return 0 + +def count_lines_in_directory(directory, extensions): + """统计目录中特定扩展名文件的总行数""" + total_lines = 0 + file_count = 0 + + for root, dirs, files in os.walk(directory): + # 跳过__pycache__目录 + if '__pycache__' in root: + continue + + for file in files: + if any(file.endswith(ext) for ext in extensions): + file_path = os.path.join(root, file) + lines = count_lines_in_file(file_path) + total_lines += lines + file_count += 1 + print(f"{file_path}: {lines} 行") + + return total_lines, file_count + +def main(): + project_dir = os.path.dirname(os.path.abspath(__file__)) + + # 统计Python文件 + print("=== Python文件行数统计 ===") + py_lines, py_files = count_lines_in_directory(project_dir, ['.py']) + print(f"\nPython文件总数: {py_files}") + print(f"Python文件总行数: {py_lines}") + + # 统计前端文件 (HTML, CSS, JS) + print("\n=== 前端文件行数统计 ===") + frontend_extensions = ['.html', '.css', '.js'] + frontend_lines, frontend_files = count_lines_in_directory(project_dir, frontend_extensions) + print(f"\n前端文件总数: {frontend_files}") + print(f"前端文件总行数: {frontend_lines}") + + # 总计 + total_files = py_files + frontend_files + total_lines = py_lines + frontend_lines + print("\n=== 项目总计 ===") + print(f"文件总数: {total_files}") + print(f"代码总行数: {total_lines}") + print(f"Python文件占比: {py_lines/total_lines*100:.2f}%") + print(f"前端文件占比: {frontend_lines/total_lines*100:.2f}%") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/fzjgact/db.sqlite3 b/fzjgact/db.sqlite3 new file mode 100644 index 0000000..6d28c7f Binary files /dev/null and b/fzjgact/db.sqlite3 differ diff --git a/fzjgact/fzjgact/__init__.py b/fzjgact/fzjgact/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fzjgact/fzjgact/__pycache__/__init__.cpython-311.pyc b/fzjgact/fzjgact/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..83090e0 Binary files /dev/null and b/fzjgact/fzjgact/__pycache__/__init__.cpython-311.pyc differ diff --git a/fzjgact/fzjgact/__pycache__/settings.cpython-311.pyc b/fzjgact/fzjgact/__pycache__/settings.cpython-311.pyc new file mode 100644 index 0000000..0f99beb Binary files /dev/null and b/fzjgact/fzjgact/__pycache__/settings.cpython-311.pyc differ diff --git a/fzjgact/fzjgact/__pycache__/urls.cpython-311.pyc b/fzjgact/fzjgact/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000..375fb96 Binary files /dev/null and b/fzjgact/fzjgact/__pycache__/urls.cpython-311.pyc differ diff --git a/fzjgact/fzjgact/__pycache__/wsgi.cpython-311.pyc b/fzjgact/fzjgact/__pycache__/wsgi.cpython-311.pyc new file mode 100644 index 0000000..5c247c6 Binary files /dev/null and b/fzjgact/fzjgact/__pycache__/wsgi.cpython-311.pyc differ diff --git a/fzjgact/fzjgact/asgi.py b/fzjgact/fzjgact/asgi.py new file mode 100644 index 0000000..b2b4059 --- /dev/null +++ b/fzjgact/fzjgact/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for fzjgact project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'fzjgact.settings') + +application = get_asgi_application() diff --git a/fzjgact/fzjgact/settings.py b/fzjgact/fzjgact/settings.py new file mode 100644 index 0000000..b1d95f4 --- /dev/null +++ b/fzjgact/fzjgact/settings.py @@ -0,0 +1,136 @@ +""" +Django settings for fzjgact project. + +Generated by 'django-admin startproject' using Django 5.0.6. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.0/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-y_ky#j@s(-ayj+5yo)02&f%w-(flx5p)2sv3yl5j_az4$&c)ih' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['10.124.107.72', '127.0.0.1', 'localhost'] + + +# Application definition + +INSTALLED_APPS = [ + "unfold", # before django.contrib.admin + "unfold.contrib.filters", # optional, if special filters are needed + "unfold.contrib.forms", # optional, if special form elements are needed + "unfold.contrib.inlines", # optional, if special inlines are needed + "unfold.contrib.import_export", # optional, if django-import-export package is used + "unfold.contrib.guardian", # optional, if django-guardian package is used + "unfold.contrib.simple_history", # optional, if django-simple-history package is used + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'huodong', + 'rest_framework', + 'django_select2', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'fzjgact.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'fzjgact.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.0/topics/i18n/ + +LANGUAGE_CODE = 'zh-hans' +TIME_ZONE = 'Asia/Shanghai' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.0/howto/static-files/ + +STATIC_URL = 'static/' + +# 媒体文件配置 +MEDIA_URL = '/media/' +MEDIA_ROOT = BASE_DIR / 'media' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/fzjgact/fzjgact/urls.py b/fzjgact/fzjgact/urls.py new file mode 100644 index 0000000..9315f4a --- /dev/null +++ b/fzjgact/fzjgact/urls.py @@ -0,0 +1,25 @@ +""" +URL configuration for fzjgact project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include +from django.conf import settings +from django.conf.urls.static import static + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include("huodong.urls")), +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/fzjgact/fzjgact/wsgi.py b/fzjgact/fzjgact/wsgi.py new file mode 100644 index 0000000..3eec88e --- /dev/null +++ b/fzjgact/fzjgact/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for fzjgact project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'fzjgact.settings') + +application = get_wsgi_application() diff --git a/fzjgact/huodong/__init__.py b/fzjgact/huodong/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fzjgact/huodong/__pycache__/__init__.cpython-311.pyc b/fzjgact/huodong/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..d1eed66 Binary files /dev/null and b/fzjgact/huodong/__pycache__/__init__.cpython-311.pyc differ diff --git a/fzjgact/huodong/__pycache__/admin.cpython-311.pyc b/fzjgact/huodong/__pycache__/admin.cpython-311.pyc new file mode 100644 index 0000000..4558fb1 Binary files /dev/null and b/fzjgact/huodong/__pycache__/admin.cpython-311.pyc differ diff --git a/fzjgact/huodong/__pycache__/apps.cpython-311.pyc b/fzjgact/huodong/__pycache__/apps.cpython-311.pyc new file mode 100644 index 0000000..2601cc9 Binary files /dev/null and b/fzjgact/huodong/__pycache__/apps.cpython-311.pyc differ diff --git a/fzjgact/huodong/__pycache__/models.cpython-311.pyc b/fzjgact/huodong/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000..5d5f33f Binary files /dev/null and b/fzjgact/huodong/__pycache__/models.cpython-311.pyc differ diff --git a/fzjgact/huodong/__pycache__/serializers.cpython-311.pyc b/fzjgact/huodong/__pycache__/serializers.cpython-311.pyc new file mode 100644 index 0000000..336eb2c Binary files /dev/null and b/fzjgact/huodong/__pycache__/serializers.cpython-311.pyc differ diff --git a/fzjgact/huodong/__pycache__/urls.cpython-311.pyc b/fzjgact/huodong/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000..80f766f Binary files /dev/null and b/fzjgact/huodong/__pycache__/urls.cpython-311.pyc differ diff --git a/fzjgact/huodong/__pycache__/views.cpython-311.pyc b/fzjgact/huodong/__pycache__/views.cpython-311.pyc new file mode 100644 index 0000000..98f91c7 Binary files /dev/null and b/fzjgact/huodong/__pycache__/views.cpython-311.pyc differ diff --git a/fzjgact/huodong/admin.py b/fzjgact/huodong/admin.py new file mode 100644 index 0000000..5118c28 --- /dev/null +++ b/fzjgact/huodong/admin.py @@ -0,0 +1,194 @@ +from django.contrib import admin +from django.contrib.admin.actions import delete_selected +from django.urls import reverse +from django.utils.html import format_html +from .models import Branch, EquipmentImage, Drawing, PublicScreen +from .models import Activity, Branch, Event, Contact, VideoTerminal +from django_select2.forms import Select2Widget +from unfold.admin import ModelAdmin +from django.contrib.admin import AdminSite +from django.contrib.auth.models import User, Group +from django.contrib.auth.admin import UserAdmin as BaseUserAdmin +from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin +from django.db.models import Count, Q + +from django.utils.html import format_html +from django.urls import reverse +from django import forms + + +# 定义Activity的内联admin类 +class ActivityInline(admin.TabularInline): # 改为更紧凑的表格形式内联(原StackedInline为堆叠形式) + model = Activity + extra = 1 # 在Branch表单中默认显示1个额外的Activity表单(可根据需求调整数值) + fields = ('name', 'scope', 'start_time', 'end_time') # 限制内联表单显示的字段 + readonly_fields = ('start_time',) # 可选:将开始时间设为只读字段(避免误修改) + # 可选:添加帮助文本提示 + help_texts = { + 'name': '请输入活动名称(必填)', + 'scope': '选择活动范围(内部/外部)' + } + + +admin.site.unregister(User) +admin.site.unregister(Group) + + +@admin.register(User) +class UserAdmin(BaseUserAdmin, ModelAdmin): + pass + + +@admin.register(Group) +class GroupAdmin(BaseGroupAdmin, ModelAdmin): + pass + + +@admin.register(Branch) +class BranchAdmin(ModelAdmin): + inlines = [ActivityInline] + list_display = ('name', 'location', 'category', 'display_mature_status', 'background_color') + search_fields = ['name', 'location'] + fieldsets = ( + (None, { + 'fields': ('name', 'location', 'contact_info', 'description', 'category', 'is_mature', 'background_color') + }), + ) + + def display_mature_status(self, obj): + return '💼' if obj.is_mature else '📒' + display_mature_status.short_description = '是否成熟' + + def activity_count(self, obj): + return obj.activity_set.count() + + activity_count.short_description = '活动数量' + + def get_queryset(self, request): + queryset = super().get_queryset(request) + queryset = queryset.annotate( + inspection_person_count=Count('contact', filter=Q(contact__category='机房/设备间巡检人'))) + return queryset + + actions = ['set_branches_to_type_b'] + + def set_branches_to_type_b(self, request, queryset): + queryset.update(category='B型') + + set_branches_to_type_b.short_description = '将选中的分支机构统一改为B型' + + +# 注册Activity模型(如果需要的话,虽然在这个示例中我们主要关注Branch) +@admin.register(Activity) +class ActivityAdmin(ModelAdmin): + list_display = ('branch', 'scope', 'name', 'start_time', 'end_time') + search_fields = ["branch__name"] # 改为关联Branch模型的name字段 + add_form_template = 'admin/huodong/add_form.html' + + autocomplete_fields = ['branch'] + + +@admin.register(Event) +class EventAdmin(ModelAdmin): + list_display = ('name', 'start_time', 'end_time', 'description') + filter_horizontal = ('branches',) + + +class ContactAdminForm(forms.ModelForm): + class Meta: + model = Contact + fields = '__all__' + widgets = { + # 使用复选框实现多选 + 'category': forms.CheckboxSelectMultiple(choices=Contact.CATEGORY_CHOICES) + } + + +class EquipmentImageAdmin(admin.ModelAdmin): + def bulk_delete_selected(self, request, queryset): + count = queryset.count() + queryset.delete() + self.message_user(request, f'已成功删除{count}条设备图片记录') + bulk_delete_selected.short_description = '批量删除选中的设备图片' + actions = ['bulk_delete_selected'] + list_display = ['id', 'branch', 'uploaded_at', 'delete_link'] + + def delete_link(self, obj): + url = reverse('admin:huodong_equipmentimage_delete', args=[obj.id]) + return format_html('删除', url) + delete_link.short_description = '操作' + list_filter = ['branch'] + search_fields = ['branch__name'] + + autocomplete_fields = ['branch'] + + def get_form(self, request, obj=None, **kwargs): + form = super().get_form(request, obj, **kwargs) + # 设置默认分支机构为最后一个设备间图片的分支机构 + try: + latest_image = EquipmentImage.objects.latest('uploaded_at') + form.base_fields['branch'].initial = latest_image.branch_id + except EquipmentImage.DoesNotExist: + pass + return form + + def save_model(self, request, obj, form, change): + super().save_model(request, obj, form, change) + # Count images for the current branch + count = EquipmentImage.objects.filter(branch=obj.branch).count() + self.message_user(request, f"【{obj.branch.name}】已经有{count}张设备间图片。") + +admin.site.register(EquipmentImage, EquipmentImageAdmin) + +class DrawingAdmin(admin.ModelAdmin): + def bulk_delete_selected(self, request, queryset): + count = queryset.count() + queryset.delete() + self.message_user(request, f'已成功删除{count}条图纸记录') + bulk_delete_selected.short_description = '批量删除选中的图纸' + actions = ['bulk_delete_selected'] + list_display = ('id', 'branch', 'uploaded_at', 'delete_link') + + def delete_link(self, obj): + url = reverse('admin:huodong_drawing_delete', args=[obj.id]) + return format_html('删除', url) + delete_link.short_description = '操作' + list_filter = ('branch', 'uploaded_at') + search_fields = ('branch__name',) + autocomplete_fields = ['branch'] + +admin.site.register(Drawing, DrawingAdmin) + +class PublicScreenAdmin(ModelAdmin): + def delete_link(self, obj): + if obj.id: + delete_url = reverse('admin:huodong_publicscreen_delete', args=[obj.id]) + return format_html('删除', delete_url) + return '-' + delete_link.short_description = '操作' + + def bulk_delete_selected(self, request, queryset): + count = queryset.count() + queryset.delete() + self.message_user(request, f'已成功删除{count}条公共电子屏记录') + bulk_delete_selected.short_description = '批量删除选中的公共电子屏' + + list_display = ('id', 'branch', 'screen_type', 'last_drill', 'delete_link') + list_filter = ['branch', 'screen_type'] + autocomplete_fields = ['branch'] + actions = ['bulk_delete_selected'] + +admin.site.register(PublicScreen, PublicScreenAdmin) +@admin.register(Contact) +class ContactAdmin(ModelAdmin): + form = ContactAdminForm # 指定自定义表单 + list_display = ('branch', 'category', 'name', 'phone', 'email') # 可选:显示分类字段 + + autocomplete_fields = ['branch'] + +@admin.register(VideoTerminal) +class VideoTerminalAdmin(ModelAdmin): + list_display = ('branch', 'terminal_type', 'description', 'created_at') + list_filter = ('terminal_type', 'branch') + search_fields = ('branch__name', 'description') + autocomplete_fields = ['branch'] diff --git a/fzjgact/huodong/apps.py b/fzjgact/huodong/apps.py new file mode 100644 index 0000000..c99c5ea --- /dev/null +++ b/fzjgact/huodong/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + +class HuodongConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'huodong' + verbose_name = '运营活动' diff --git a/fzjgact/huodong/management/__init__.py b/fzjgact/huodong/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fzjgact/huodong/management/__pycache__/__init__.cpython-311.pyc b/fzjgact/huodong/management/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..9911255 Binary files /dev/null and b/fzjgact/huodong/management/__pycache__/__init__.cpython-311.pyc differ diff --git a/fzjgact/huodong/management/commands/__init__.py b/fzjgact/huodong/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fzjgact/huodong/management/commands/__pycache__/__init__.cpython-311.pyc b/fzjgact/huodong/management/commands/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..feef253 Binary files /dev/null and b/fzjgact/huodong/management/commands/__pycache__/__init__.cpython-311.pyc differ diff --git a/fzjgact/huodong/management/commands/__pycache__/randomize_background_color.cpython-311.pyc b/fzjgact/huodong/management/commands/__pycache__/randomize_background_color.cpython-311.pyc new file mode 100644 index 0000000..d896588 Binary files /dev/null and b/fzjgact/huodong/management/commands/__pycache__/randomize_background_color.cpython-311.pyc differ diff --git a/fzjgact/huodong/management/commands/_private.py.py b/fzjgact/huodong/management/commands/_private.py.py new file mode 100644 index 0000000..e69de29 diff --git a/fzjgact/huodong/management/commands/randomize_background_color.py b/fzjgact/huodong/management/commands/randomize_background_color.py new file mode 100644 index 0000000..0e383cb --- /dev/null +++ b/fzjgact/huodong/management/commands/randomize_background_color.py @@ -0,0 +1,26 @@ +import random +from django.core.management.base import BaseCommand +from huodong.models import Branch + + +class Command(BaseCommand): + help = '随机修改所有branch实例的背景色' + + def handle(self, *args, **kwargs): + colors = ['#f8fafc', '#f1f5f9', '#f9fafb', '#f3f4f6', '#fafafa', + '#f4f4f5', '#fafafa', '#f5f5f5', '#fafaf9', '#f5f5f4', + '#fef2f2', '#fee2e2', '#fff7ed', '#ffedd5', '#fffbeb', + '#fef3c7', '#fefce8', '#fef9c3', '#f7fee7', '#ecfccb', + '#f0fdf4', '#dcfce7', '#ecfdf5', '#d1fae5', '#f0fdfa', + '#ccfbf1', '#ecfeff', '#cffafe', '#f0f9ff', '#e0f2fe', + '#eff6ff', '#dbeafe', '#eef2ff', '#e0e7ff', '#f5f3ff', + '#ede9fe', '#faf5ff', '#f3e8ff', '#fdf4ff', '#fae8ff', + '#fff1f2', '#ffe4e6'] + branches = Branch.objects.all() + for branch in branches: + branch.background_color = random.choice(colors) + branch.save() + self.stdout.write(self.style.SUCCESS('已成功修改所有branch实例的背景色')) + +# 在终端运行此命令 +# python manage.py your_command_name diff --git a/fzjgact/huodong/migrations/0001_initial.py b/fzjgact/huodong/migrations/0001_initial.py new file mode 100644 index 0000000..eaf26b0 --- /dev/null +++ b/fzjgact/huodong/migrations/0001_initial.py @@ -0,0 +1,50 @@ +# Generated by Django 5.0.6 on 2024-07-09 06:35 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Branch', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('location', models.CharField(max_length=255)), + ('contact_info', models.CharField(max_length=255)), + ('description', models.TextField()), + ], + ), + migrations.CreateModel( + name='Activity', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('scope', models.CharField(max_length=255)), + ('start_time', models.DateTimeField()), + ('end_time', models.DateTimeField()), + ('location', models.CharField(max_length=255)), + ('description', models.TextField()), + ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='huodong.branch')), + ], + ), + migrations.CreateModel( + name='Evaluation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('score', models.DecimalField(decimal_places=2, max_digits=4)), + ('comment', models.TextField()), + ('file_path', models.CharField(blank=True, max_length=255, null=True)), + ('status', models.CharField(choices=[('pending', '待审核'), ('approved', '已通过'), ('rejected', '已拒绝')], default='pending', max_length=20)), + ('activity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='huodong.activity')), + ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='huodong.branch')), + ], + ), + ] diff --git a/fzjgact/huodong/migrations/0002_alter_activity_end_time.py b/fzjgact/huodong/migrations/0002_alter_activity_end_time.py new file mode 100644 index 0000000..7914e39 --- /dev/null +++ b/fzjgact/huodong/migrations/0002_alter_activity_end_time.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2024-07-17 09:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='end_time', + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/fzjgact/huodong/migrations/0003_alter_activity_scope.py b/fzjgact/huodong/migrations/0003_alter_activity_scope.py new file mode 100644 index 0000000..3ecd939 --- /dev/null +++ b/fzjgact/huodong/migrations/0003_alter_activity_scope.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2024-07-24 02:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0002_alter_activity_end_time'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='scope', + field=models.CharField(choices=[('新建', '新建'), ('搬迁', '搬迁'), ('装修', '装修'), ('其他技术问题', '其他技术问题')], max_length=255), + ), + ] diff --git a/fzjgact/huodong/migrations/0004_alter_activity_scope.py b/fzjgact/huodong/migrations/0004_alter_activity_scope.py new file mode 100644 index 0000000..2c1dcfd --- /dev/null +++ b/fzjgact/huodong/migrations/0004_alter_activity_scope.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2024-07-24 09:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0003_alter_activity_scope'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='scope', + field=models.CharField(choices=[('新建', '新建'), ('搬迁', '搬迁'), ('原址装修', '原址装修'), ('其他技术问题', '其他技术问题')], max_length=255), + ), + ] diff --git a/fzjgact/huodong/migrations/0005_event.py b/fzjgact/huodong/migrations/0005_event.py new file mode 100644 index 0000000..70e9cb5 --- /dev/null +++ b/fzjgact/huodong/migrations/0005_event.py @@ -0,0 +1,24 @@ +# Generated by Django 5.0.6 on 2024-07-30 08:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0004_alter_activity_scope'), + ] + + operations = [ + migrations.CreateModel( + name='Event', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('start_time', models.DateTimeField()), + ('end_time', models.DateTimeField(blank=True, null=True)), + ('description', models.TextField()), + ('branches', models.ManyToManyField(to='huodong.branch')), + ], + ), + ] diff --git a/fzjgact/huodong/migrations/0006_alter_activity_options_alter_branch_options_and_more.py b/fzjgact/huodong/migrations/0006_alter_activity_options_alter_branch_options_and_more.py new file mode 100644 index 0000000..f8056d9 --- /dev/null +++ b/fzjgact/huodong/migrations/0006_alter_activity_options_alter_branch_options_and_more.py @@ -0,0 +1,41 @@ +# Generated by Django 5.0.6 on 2024-09-09 09:26 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0005_event'), + ] + + operations = [ + migrations.AlterModelOptions( + name='activity', + options={'verbose_name': '运营活动内容', 'verbose_name_plural': '运营活动内容(新建搬迁装修和技术)'}, + ), + migrations.AlterModelOptions( + name='branch', + options={'verbose_name': '分支机构', 'verbose_name_plural': '分支机构(基础信息)'}, + ), + migrations.AlterModelOptions( + name='event', + options={'verbose_name': '运营事件', 'verbose_name_plural': '运营事件(其它)'}, + ), + migrations.CreateModel( + name='Contact', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('category', models.CharField(choices=[('信息安全联系人', '信息安全联系人'), ('巡检人', '巡检人')], max_length=50)), + ('name', models.CharField(max_length=255)), + ('phone', models.CharField(max_length=20)), + ('email', models.EmailField(blank=True, max_length=254)), + ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='huodong.branch')), + ], + options={ + 'verbose_name': '联系人群', + 'verbose_name_plural': '联系人群', + }, + ), + ] diff --git a/fzjgact/huodong/migrations/0007_alter_branch_name.py b/fzjgact/huodong/migrations/0007_alter_branch_name.py new file mode 100644 index 0000000..013b40a --- /dev/null +++ b/fzjgact/huodong/migrations/0007_alter_branch_name.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2024-09-10 01:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0006_alter_activity_options_alter_branch_options_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='branch', + name='name', + field=models.CharField(max_length=255, unique=True), + ), + ] diff --git a/fzjgact/huodong/migrations/0008_contact_description_alter_contact_category.py b/fzjgact/huodong/migrations/0008_contact_description_alter_contact_category.py new file mode 100644 index 0000000..530c4b6 --- /dev/null +++ b/fzjgact/huodong/migrations/0008_contact_description_alter_contact_category.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.6 on 2024-09-10 02:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0007_alter_branch_name'), + ] + + operations = [ + migrations.AddField( + model_name='contact', + name='description', + field=models.TextField(blank=True), + ), + migrations.AlterField( + model_name='contact', + name='category', + field=models.CharField(choices=[('机房/设备间巡检人', '机房/设备间巡检人'), ('信息安全联系人', '信息安全联系人')], max_length=50), + ), + ] diff --git a/fzjgact/huodong/migrations/0009_alter_contact_description_alter_contact_email_and_more.py b/fzjgact/huodong/migrations/0009_alter_contact_description_alter_contact_email_and_more.py new file mode 100644 index 0000000..dcfeef5 --- /dev/null +++ b/fzjgact/huodong/migrations/0009_alter_contact_description_alter_contact_email_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 5.0.6 on 2024-09-10 02:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0008_contact_description_alter_contact_category'), + ] + + operations = [ + migrations.AlterField( + model_name='contact', + name='description', + field=models.TextField(blank=True, verbose_name='描述,可不填'), + ), + migrations.AlterField( + model_name='contact', + name='email', + field=models.EmailField(blank=True, max_length=254, verbose_name='邮箱,可不填'), + ), + migrations.AlterField( + model_name='contact', + name='name', + field=models.CharField(max_length=255, verbose_name='姓名'), + ), + migrations.AlterField( + model_name='contact', + name='phone', + field=models.CharField(max_length=20, verbose_name='电话'), + ), + ] diff --git a/fzjgact/huodong/migrations/0010_alter_branch_contact_info_alter_branch_description_and_more.py b/fzjgact/huodong/migrations/0010_alter_branch_contact_info_alter_branch_description_and_more.py new file mode 100644 index 0000000..2f1d0d9 --- /dev/null +++ b/fzjgact/huodong/migrations/0010_alter_branch_contact_info_alter_branch_description_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 5.0.6 on 2024-09-10 02:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0009_alter_contact_description_alter_contact_email_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='branch', + name='contact_info', + field=models.CharField(max_length=255, verbose_name='主要人的联系方式'), + ), + migrations.AlterField( + model_name='branch', + name='description', + field=models.TextField(blank=True, verbose_name='备注,可不填'), + ), + migrations.AlterField( + model_name='branch', + name='location', + field=models.CharField(max_length=255, verbose_name='所在省份'), + ), + migrations.AlterField( + model_name='branch', + name='name', + field=models.CharField(max_length=255, unique=True, verbose_name='分支机构名称'), + ), + ] diff --git a/fzjgact/huodong/migrations/0011_alter_branch_contact_info_alter_branch_description.py b/fzjgact/huodong/migrations/0011_alter_branch_contact_info_alter_branch_description.py new file mode 100644 index 0000000..cf9ed07 --- /dev/null +++ b/fzjgact/huodong/migrations/0011_alter_branch_contact_info_alter_branch_description.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.6 on 2024-09-10 02:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0010_alter_branch_contact_info_alter_branch_description_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='branch', + name='contact_info', + field=models.CharField(max_length=255, verbose_name='主要联系人'), + ), + migrations.AlterField( + model_name='branch', + name='description', + field=models.TextField(blank=True, verbose_name='备注'), + ), + ] diff --git a/fzjgact/huodong/migrations/0012_alter_activity_branch_alter_activity_description_and_more.py b/fzjgact/huodong/migrations/0012_alter_activity_branch_alter_activity_description_and_more.py new file mode 100644 index 0000000..127af82 --- /dev/null +++ b/fzjgact/huodong/migrations/0012_alter_activity_branch_alter_activity_description_and_more.py @@ -0,0 +1,79 @@ +# Generated by Django 5.0.6 on 2024-09-10 07:41 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0011_alter_branch_contact_info_alter_branch_description'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='branch', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='huodong.branch', verbose_name='分支机构'), + ), + migrations.AlterField( + model_name='activity', + name='description', + field=models.TextField(verbose_name='其它内容'), + ), + migrations.AlterField( + model_name='activity', + name='end_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='结束日期'), + ), + migrations.AlterField( + model_name='activity', + name='location', + field=models.CharField(max_length=255, verbose_name='所在地点'), + ), + migrations.AlterField( + model_name='activity', + name='name', + field=models.CharField(max_length=255, verbose_name='活动名称'), + ), + migrations.AlterField( + model_name='activity', + name='start_time', + field=models.DateTimeField(verbose_name='开始日期'), + ), + migrations.AlterField( + model_name='contact', + name='branch', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='huodong.branch', verbose_name='分支机构'), + ), + migrations.AlterField( + model_name='contact', + name='category', + field=models.CharField(choices=[('机房/设备间巡检人', '机房/设备间巡检人'), ('信息安全联系人', '信息安全联系人')], max_length=50, verbose_name='联系人分类'), + ), + migrations.AlterField( + model_name='event', + name='branches', + field=models.ManyToManyField(to='huodong.branch', verbose_name='分支机构'), + ), + migrations.AlterField( + model_name='event', + name='description', + field=models.TextField(verbose_name='事件描述'), + ), + migrations.AlterField( + model_name='event', + name='end_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='结束时间'), + ), + migrations.AlterField( + model_name='event', + name='name', + field=models.CharField(max_length=255, verbose_name='事件名称'), + ), + migrations.AlterField( + model_name='event', + name='start_time', + field=models.DateTimeField(verbose_name='开始时间'), + ), + ] diff --git a/fzjgact/huodong/migrations/0013_branch_background_color.py b/fzjgact/huodong/migrations/0013_branch_background_color.py new file mode 100644 index 0000000..05a7bbf --- /dev/null +++ b/fzjgact/huodong/migrations/0013_branch_background_color.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2024-09-20 02:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0012_alter_activity_branch_alter_activity_description_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='branch', + name='background_color', + field=models.CharField(default='#EFF6FF', help_text='使用#RRGGBB格式的颜色代码', max_length=7, verbose_name='背景色'), + ), + ] diff --git a/fzjgact/huodong/migrations/0014_branch_category.py b/fzjgact/huodong/migrations/0014_branch_category.py new file mode 100644 index 0000000..7c0c538 --- /dev/null +++ b/fzjgact/huodong/migrations/0014_branch_category.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2024-09-23 07:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0013_branch_background_color'), + ] + + operations = [ + migrations.AddField( + model_name='branch', + name='category', + field=models.CharField(choices=[('A型', 'A型'), ('B型', 'B型'), ('C型', 'C型'), ('不适用', '不适用')], default='C型', max_length=10, verbose_name='分类'), + ), + ] diff --git a/fzjgact/huodong/migrations/0015_alter_activity_scope.py b/fzjgact/huodong/migrations/0015_alter_activity_scope.py new file mode 100644 index 0000000..cc134df --- /dev/null +++ b/fzjgact/huodong/migrations/0015_alter_activity_scope.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2024-10-28 05:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0014_branch_category'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='scope', + field=models.CharField(choices=[('新建', '新建'), ('搬迁', '搬迁'), ('原址装修', '原址装修'), ('撤销', '撤销'), ('其他技术问题', '其他技术问题')], max_length=255), + ), + ] diff --git a/fzjgact/huodong/migrations/0016_alter_contact_category.py b/fzjgact/huodong/migrations/0016_alter_contact_category.py new file mode 100644 index 0000000..7fd3271 --- /dev/null +++ b/fzjgact/huodong/migrations/0016_alter_contact_category.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2025-06-10 05:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0015_alter_activity_scope'), + ] + + operations = [ + migrations.AlterField( + model_name='contact', + name='category', + field=models.CharField(choices=[('机房/设备间巡检人', '机房/设备间巡检人'), ('信息安全联系人', '信息安全联系人'), ('兼岗', '兼岗'), ('安全员', '安全员')], help_text='按住 Ctrl/Command 键多选(值将以逗号分隔存储)', max_length=255, verbose_name='联系人分类'), + ), + ] diff --git a/fzjgact/huodong/migrations/0017_branch_equipment_image.py b/fzjgact/huodong/migrations/0017_branch_equipment_image.py new file mode 100644 index 0000000..f6e2d5b --- /dev/null +++ b/fzjgact/huodong/migrations/0017_branch_equipment_image.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2025-06-12 09:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0016_alter_contact_category'), + ] + + operations = [ + migrations.AddField( + model_name='branch', + name='equipment_image', + field=models.ImageField(blank=True, null=True, upload_to='equipment_room_images/', verbose_name='设备间图片'), + ), + ] diff --git a/fzjgact/huodong/migrations/0018_alter_branch_equipment_image.py b/fzjgact/huodong/migrations/0018_alter_branch_equipment_image.py new file mode 100644 index 0000000..0991d83 --- /dev/null +++ b/fzjgact/huodong/migrations/0018_alter_branch_equipment_image.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2025-06-12 09:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0017_branch_equipment_image'), + ] + + operations = [ + migrations.AlterField( + model_name='branch', + name='equipment_image', + field=models.ImageField(blank=True, default=None, null=True, upload_to='equipment_room_images/', verbose_name='设备间图片'), + ), + ] diff --git a/fzjgact/huodong/migrations/0019_remove_branch_equipment_image_equipmentimage.py b/fzjgact/huodong/migrations/0019_remove_branch_equipment_image_equipmentimage.py new file mode 100644 index 0000000..8456cf4 --- /dev/null +++ b/fzjgact/huodong/migrations/0019_remove_branch_equipment_image_equipmentimage.py @@ -0,0 +1,27 @@ +# Generated by Django 5.0.6 on 2025-06-13 06:43 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0018_alter_branch_equipment_image'), + ] + + operations = [ + migrations.RemoveField( + model_name='branch', + name='equipment_image', + ), + migrations.CreateModel( + name='EquipmentImage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image', models.ImageField(upload_to='equipment_room_images/')), + ('uploaded_at', models.DateTimeField(auto_now_add=True)), + ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='equipment_images', to='huodong.branch')), + ], + ), + ] diff --git a/fzjgact/huodong/migrations/0020_alter_equipmentimage_options_drawing.py b/fzjgact/huodong/migrations/0020_alter_equipmentimage_options_drawing.py new file mode 100644 index 0000000..704cf95 --- /dev/null +++ b/fzjgact/huodong/migrations/0020_alter_equipmentimage_options_drawing.py @@ -0,0 +1,31 @@ +# Generated by Django 5.0.6 on 2025-06-13 09:40 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0019_remove_branch_equipment_image_equipmentimage'), + ] + + operations = [ + migrations.AlterModelOptions( + name='equipmentimage', + options={'verbose_name': '设备间图', 'verbose_name_plural': '设备间图'}, + ), + migrations.CreateModel( + name='Drawing', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image', models.ImageField(upload_to='drawings/')), + ('uploaded_at', models.DateTimeField(auto_now_add=True)), + ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='drawings', to='huodong.branch')), + ], + options={ + 'verbose_name': '图纸', + 'verbose_name_plural': '图纸', + }, + ), + ] diff --git a/fzjgact/huodong/migrations/0021_publicscreen.py b/fzjgact/huodong/migrations/0021_publicscreen.py new file mode 100644 index 0000000..5622fc3 --- /dev/null +++ b/fzjgact/huodong/migrations/0021_publicscreen.py @@ -0,0 +1,27 @@ +# Generated by Django 5.0.6 on 2025-06-18 06:29 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0020_alter_equipmentimage_options_drawing'), + ] + + operations = [ + migrations.CreateModel( + name='PublicScreen', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image', models.ImageField(upload_to='public_screen_images/')), + ('screen_type', models.CharField(choices=[('marquee', '跑马灯'), ('advertisement', '广告屏'), ('information', '信息发布屏')], max_length=20, verbose_name='功能类型')), + ('description', models.TextField(blank=True, null=True, verbose_name='功能描述')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='public_screens', to='huodong.branch')), + ('last_drill', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='public_screens', to='huodong.event', verbose_name='最后演练事件')), + ], + ), + ] diff --git a/fzjgact/huodong/migrations/0022_remove_publicscreen_created_at.py b/fzjgact/huodong/migrations/0022_remove_publicscreen_created_at.py new file mode 100644 index 0000000..9eae14e --- /dev/null +++ b/fzjgact/huodong/migrations/0022_remove_publicscreen_created_at.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.6 on 2025-06-18 07:53 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0021_publicscreen'), + ] + + operations = [ + migrations.RemoveField( + model_name='publicscreen', + name='created_at', + ), + ] diff --git a/fzjgact/huodong/migrations/0023_publicscreen_created_at.py b/fzjgact/huodong/migrations/0023_publicscreen_created_at.py new file mode 100644 index 0000000..9701fc2 --- /dev/null +++ b/fzjgact/huodong/migrations/0023_publicscreen_created_at.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0.6 on 2025-06-18 08:43 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0022_remove_publicscreen_created_at'), + ] + + operations = [ + migrations.AddField( + model_name='publicscreen', + name='created_at', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/fzjgact/huodong/migrations/0024_alter_event_branches.py b/fzjgact/huodong/migrations/0024_alter_event_branches.py new file mode 100644 index 0000000..3aca350 --- /dev/null +++ b/fzjgact/huodong/migrations/0024_alter_event_branches.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2025-06-19 08:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0023_publicscreen_created_at'), + ] + + operations = [ + migrations.AlterField( + model_name='event', + name='branches', + field=models.ManyToManyField(related_name='events', to='huodong.branch', verbose_name='分支机构'), + ), + ] diff --git a/fzjgact/huodong/migrations/0025_videoterminal.py b/fzjgact/huodong/migrations/0025_videoterminal.py new file mode 100644 index 0000000..271769a --- /dev/null +++ b/fzjgact/huodong/migrations/0025_videoterminal.py @@ -0,0 +1,29 @@ +# Generated by Django 5.0.6 on 2025-06-25 06:37 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0024_alter_event_branches'), + ] + + operations = [ + migrations.CreateModel( + name='VideoTerminal', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('terminal_type', models.CharField(choices=[('polycom', '宝利通终端'), ('zte', '中兴终端'), ('logitech', '罗技摄像头'), ('laptop_tv', '笔记本加电视'), ('laptop_projector', '笔记本加投影仪'), ('other', '其它')], max_length=20, verbose_name='设备类型')), + ('description', models.TextField(blank=True, verbose_name='设备描述')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='video_terminals', to='huodong.branch', verbose_name='分支机构')), + ], + options={ + 'verbose_name': '视频设备终端', + 'verbose_name_plural': '视频设备终端', + }, + ), + ] diff --git a/fzjgact/huodong/migrations/0026_alter_activity_scope.py b/fzjgact/huodong/migrations/0026_alter_activity_scope.py new file mode 100644 index 0000000..2996c1e --- /dev/null +++ b/fzjgact/huodong/migrations/0026_alter_activity_scope.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2025-06-25 07:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0025_videoterminal'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='scope', + field=models.CharField(choices=[('新建', '新建'), ('搬迁', '搬迁'), ('原址装修', '原址装修'), ('撤销', '撤销'), ('其他技术问题', '其他技术问题')], max_length=255, verbose_name='活动类型'), + ), + ] diff --git a/fzjgact/huodong/migrations/0027_alter_publicscreen_options_branch_is_mature.py b/fzjgact/huodong/migrations/0027_alter_publicscreen_options_branch_is_mature.py new file mode 100644 index 0000000..636d820 --- /dev/null +++ b/fzjgact/huodong/migrations/0027_alter_publicscreen_options_branch_is_mature.py @@ -0,0 +1,22 @@ +# Generated by Django 5.0.6 on 2025-06-27 09:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0026_alter_activity_scope'), + ] + + operations = [ + migrations.AlterModelOptions( + name='publicscreen', + options={'verbose_name': '公共电子屏', 'verbose_name_plural': '公共电子屏'}, + ), + migrations.AddField( + model_name='branch', + name='is_mature', + field=models.BooleanField(default=False, verbose_name='是否成熟'), + ), + ] diff --git a/fzjgact/huodong/migrations/0028_alter_publicscreen_image_and_more.py b/fzjgact/huodong/migrations/0028_alter_publicscreen_image_and_more.py new file mode 100644 index 0000000..a893b0d --- /dev/null +++ b/fzjgact/huodong/migrations/0028_alter_publicscreen_image_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.6 on 2025-07-02 07:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0027_alter_publicscreen_options_branch_is_mature'), + ] + + operations = [ + migrations.AlterField( + model_name='publicscreen', + name='image', + field=models.ImageField(blank=True, null=True, upload_to='public_screen_images/'), + ), + migrations.AlterField( + model_name='publicscreen', + name='screen_type', + field=models.CharField(blank=True, choices=[('marquee', '跑马灯'), ('advertisement', '广告屏'), ('information', '信息发布屏')], max_length=20, null=True, verbose_name='功能类型'), + ), + ] diff --git a/fzjgact/huodong/migrations/0029_alter_activity_end_time_alter_activity_start_time_and_more.py b/fzjgact/huodong/migrations/0029_alter_activity_end_time_alter_activity_start_time_and_more.py new file mode 100644 index 0000000..162f13a --- /dev/null +++ b/fzjgact/huodong/migrations/0029_alter_activity_end_time_alter_activity_start_time_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 5.0.6 on 2025-09-01 06:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0028_alter_publicscreen_image_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='activity', + name='end_time', + field=models.DateField(blank=True, null=True, verbose_name='结束日期'), + ), + migrations.AlterField( + model_name='activity', + name='start_time', + field=models.DateField(verbose_name='开始日期'), + ), + migrations.AlterField( + model_name='event', + name='end_time', + field=models.DateField(blank=True, null=True, verbose_name='结束时间'), + ), + migrations.AlterField( + model_name='event', + name='start_time', + field=models.DateField(verbose_name='开始时间'), + ), + ] diff --git a/fzjgact/huodong/migrations/__init__.py b/fzjgact/huodong/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fzjgact/huodong/migrations/__pycache__/0001_initial.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..5c5bc55 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0002_alter_activity_end_time.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0002_alter_activity_end_time.cpython-311.pyc new file mode 100644 index 0000000..7fcce3b Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0002_alter_activity_end_time.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0003_alter_activity_scope.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0003_alter_activity_scope.cpython-311.pyc new file mode 100644 index 0000000..7aae69c Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0003_alter_activity_scope.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0004_alter_activity_scope.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0004_alter_activity_scope.cpython-311.pyc new file mode 100644 index 0000000..ca4517f Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0004_alter_activity_scope.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0005_event.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0005_event.cpython-311.pyc new file mode 100644 index 0000000..0c0a577 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0005_event.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0006_alter_activity_options_alter_branch_options_and_more.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0006_alter_activity_options_alter_branch_options_and_more.cpython-311.pyc new file mode 100644 index 0000000..71e03d7 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0006_alter_activity_options_alter_branch_options_and_more.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0007_alter_branch_name.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0007_alter_branch_name.cpython-311.pyc new file mode 100644 index 0000000..b918486 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0007_alter_branch_name.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0008_contact_description_alter_contact_category.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0008_contact_description_alter_contact_category.cpython-311.pyc new file mode 100644 index 0000000..793f856 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0008_contact_description_alter_contact_category.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0009_alter_contact_description_alter_contact_email_and_more.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0009_alter_contact_description_alter_contact_email_and_more.cpython-311.pyc new file mode 100644 index 0000000..224870a Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0009_alter_contact_description_alter_contact_email_and_more.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0010_alter_branch_contact_info_alter_branch_description_and_more.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0010_alter_branch_contact_info_alter_branch_description_and_more.cpython-311.pyc new file mode 100644 index 0000000..38d6874 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0010_alter_branch_contact_info_alter_branch_description_and_more.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0011_alter_branch_contact_info_alter_branch_description.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0011_alter_branch_contact_info_alter_branch_description.cpython-311.pyc new file mode 100644 index 0000000..f96e956 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0011_alter_branch_contact_info_alter_branch_description.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0012_alter_activity_branch_alter_activity_description_and_more.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0012_alter_activity_branch_alter_activity_description_and_more.cpython-311.pyc new file mode 100644 index 0000000..77390e7 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0012_alter_activity_branch_alter_activity_description_and_more.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0013_branch_background_color.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0013_branch_background_color.cpython-311.pyc new file mode 100644 index 0000000..7485b00 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0013_branch_background_color.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0014_branch_category.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0014_branch_category.cpython-311.pyc new file mode 100644 index 0000000..15cb049 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0014_branch_category.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0015_alter_activity_scope.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0015_alter_activity_scope.cpython-311.pyc new file mode 100644 index 0000000..81b3ef3 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0015_alter_activity_scope.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0016_alter_contact_category.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0016_alter_contact_category.cpython-311.pyc new file mode 100644 index 0000000..9df73cd Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0016_alter_contact_category.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0017_branch_equipment_image.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0017_branch_equipment_image.cpython-311.pyc new file mode 100644 index 0000000..d2b6d93 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0017_branch_equipment_image.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0018_alter_branch_equipment_image.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0018_alter_branch_equipment_image.cpython-311.pyc new file mode 100644 index 0000000..d818682 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0018_alter_branch_equipment_image.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0019_remove_branch_equipment_image_equipmentimage.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0019_remove_branch_equipment_image_equipmentimage.cpython-311.pyc new file mode 100644 index 0000000..4d62ca2 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0019_remove_branch_equipment_image_equipmentimage.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0020_alter_equipmentimage_options_drawing.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0020_alter_equipmentimage_options_drawing.cpython-311.pyc new file mode 100644 index 0000000..9084b3c Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0020_alter_equipmentimage_options_drawing.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0021_publicscreen.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0021_publicscreen.cpython-311.pyc new file mode 100644 index 0000000..cdfd44a Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0021_publicscreen.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0022_remove_publicscreen_created_at.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0022_remove_publicscreen_created_at.cpython-311.pyc new file mode 100644 index 0000000..b777915 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0022_remove_publicscreen_created_at.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0023_publicscreen_created_at.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0023_publicscreen_created_at.cpython-311.pyc new file mode 100644 index 0000000..e9346fa Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0023_publicscreen_created_at.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0024_alter_event_branches.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0024_alter_event_branches.cpython-311.pyc new file mode 100644 index 0000000..b8b734f Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0024_alter_event_branches.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0025_videoterminal.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0025_videoterminal.cpython-311.pyc new file mode 100644 index 0000000..27399f9 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0025_videoterminal.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0026_alter_activity_scope.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0026_alter_activity_scope.cpython-311.pyc new file mode 100644 index 0000000..aa11f36 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0026_alter_activity_scope.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0027_alter_publicscreen_options_branch_is_mature.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0027_alter_publicscreen_options_branch_is_mature.cpython-311.pyc new file mode 100644 index 0000000..2ee3697 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0027_alter_publicscreen_options_branch_is_mature.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0028_alter_publicscreen_image_and_more.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0028_alter_publicscreen_image_and_more.cpython-311.pyc new file mode 100644 index 0000000..793ced8 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0028_alter_publicscreen_image_and_more.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/0029_alter_activity_end_time_alter_activity_start_time_and_more.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0029_alter_activity_end_time_alter_activity_start_time_and_more.cpython-311.pyc new file mode 100644 index 0000000..c7e9911 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/0029_alter_activity_end_time_alter_activity_start_time_and_more.cpython-311.pyc differ diff --git a/fzjgact/huodong/migrations/__pycache__/__init__.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..fcd8062 Binary files /dev/null and b/fzjgact/huodong/migrations/__pycache__/__init__.cpython-311.pyc differ diff --git a/fzjgact/huodong/models.py b/fzjgact/huodong/models.py new file mode 100644 index 0000000..afbec58 --- /dev/null +++ b/fzjgact/huodong/models.py @@ -0,0 +1,182 @@ +from django.db import models +from django.utils import timezone + + +class Branch(models.Model): + CATEGORY_CHOICES = ( + ('A型', 'A型'), + ('B型', 'B型'), + ('C型', 'C型'), + ('不适用', '不适用'), + ) + name = models.CharField(max_length=255, unique=True, verbose_name='分支机构名称') + location = models.CharField(max_length=255, verbose_name='所在省份') + contact_info = models.CharField(max_length=255, verbose_name='主要联系人') + description = models.TextField(blank=True, verbose_name='备注') + background_color = models.CharField(max_length=7, default='#EFF6FF', verbose_name='背景色', + help_text='使用#RRGGBB格式的颜色代码') + category = models.CharField(max_length=10, choices=CATEGORY_CHOICES, default='C型', verbose_name='分类') + is_mature = models.BooleanField(default=False, verbose_name='是否成熟') + + + def __str__(self): + return f'{self.name} 💼' if self.is_mature else self.name + + class Meta: + verbose_name = '分支机构' + verbose_name_plural = '分支机构(基础信息)' + + +class Contact(models.Model): + branch = models.ForeignKey(Branch, on_delete=models.CASCADE, verbose_name='分支机构') + CATEGORY_CHOICES = [ + ('机房/设备间巡检人', '机房/设备间巡检人'), + ('信息安全联系人', '信息安全联系人'), + ('兼岗', '兼岗'), + ('安全员', '安全员') + # 可以添加更多类别 + ] + # 修改为支持多选的 CharField + category = models.CharField( + max_length=255, # 增大长度(原50可能不足) + choices=CATEGORY_CHOICES, + verbose_name='联系人分类', + help_text='按住 Ctrl/Command 键多选(值将以逗号分隔存储)' + ) + name = models.CharField(max_length=255, verbose_name='姓名') + phone = models.CharField(max_length=20, verbose_name='电话') + email = models.EmailField(blank=True, verbose_name='邮箱,可不填') + description = models.TextField(blank=True, verbose_name='描述,可不填') + + def __str__(self): + return self.name + + class Meta: + verbose_name = '联系人群' + verbose_name_plural = '联系人群' + + +class Activity(models.Model): + branch = models.ForeignKey(Branch, on_delete=models.CASCADE, verbose_name='分支机构') + name = models.CharField(max_length=255, verbose_name='活动名称') + scope = models.CharField(max_length=255, choices=( + ('新建', '新建'), + ('搬迁', '搬迁'), + ('原址装修', '原址装修'), + ('撤销', '撤销'), + ('其他技术问题', '其他技术问题') + + ), verbose_name='活动类型') + start_time = models.DateField(verbose_name='开始日期') + end_time = models.DateField(blank=True, null=True, verbose_name='结束日期') # 可以为空,表示活动尚未结束 + location = models.CharField(max_length=255, verbose_name='所在地点') + description = models.TextField(verbose_name='其它内容') + + def __str__(self): + return self.name + + class Meta: + verbose_name = '运营活动内容' + verbose_name_plural = '运营活动内容(新建搬迁装修和技术)' + + +class EquipmentImage(models.Model): + branch = models.ForeignKey(Branch, related_name='equipment_images', on_delete=models.CASCADE) + image = models.ImageField(upload_to='equipment_room_images/') + uploaded_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"设备间图片 {self.id} - {self.branch.name}" + + class Meta: + verbose_name = '设备间图' + verbose_name_plural = '设备间图' + + +# 图纸的类 +class Drawing(models.Model): + branch = models.ForeignKey(Branch, related_name='drawings', on_delete=models.CASCADE) + image = models.ImageField(upload_to='drawings/') + uploaded_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"图纸 {self.id} - {self.branch.name}" + + class Meta: + verbose_name = '图纸' + verbose_name_plural = '图纸' + + +# 公共电子屏 +class PublicScreen(models.Model): + SCREEN_TYPES = ( + ('marquee', '跑马灯'), + ('advertisement', '广告屏'), + ('information', '信息发布屏'), + ) + branch = models.ForeignKey(Branch, on_delete=models.CASCADE, related_name='public_screens') + image = models.ImageField(upload_to='public_screen_images/', null=True, blank=True) + screen_type = models.CharField(max_length=20, choices=SCREEN_TYPES, verbose_name='功能类型', null=True, blank=True) + description = models.TextField(blank=True, null=True, verbose_name='功能描述') + last_drill = models.ForeignKey('Event', on_delete=models.SET_NULL, blank=True, null=True, related_name='public_screens', verbose_name='最后演练事件') + created_at = models.DateTimeField(default=timezone.now) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return f'{self.branch.name} - {self.get_screen_type_display()} {self.id}' + + class Meta: + verbose_name = '公共电子屏' + verbose_name_plural = '公共电子屏' + + +class Event(models.Model): + branches = models.ManyToManyField(Branch, related_name='events', verbose_name='分支机构') + name = models.CharField(max_length=255, verbose_name='事件名称') + start_time = models.DateField(verbose_name='开始时间') + end_time = models.DateField(blank=True, null=True, verbose_name='结束时间') # 可以为空,表示活动尚未结束 + description = models.TextField(verbose_name='事件描述') + + def __str__(self): + return self.name + + class Meta: + verbose_name = '运营事件' + verbose_name_plural = '运营事件(其它)' + + +class VideoTerminal(models.Model): + TERMINAL_TYPES = ( + ('polycom', '宝利通终端'), + ('zte', '中兴终端'), + ('logitech', '罗技摄像头'), + ('laptop_tv', '笔记本加电视'), + ('laptop_projector', '笔记本加投影仪'), + ('other', '其它'), + ) + branch = models.ForeignKey(Branch, on_delete=models.CASCADE, related_name='video_terminals', verbose_name='分支机构') + terminal_type = models.CharField(max_length=20, choices=TERMINAL_TYPES, verbose_name='设备类型') + description = models.TextField(blank=True, verbose_name='设备描述') + created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') + updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间') + + def __str__(self): + return f"{self.branch.name} - {self.get_terminal_type_display()}" + + class Meta: + verbose_name = '视频设备终端' + verbose_name_plural = '视频设备终端' + + +class Evaluation(models.Model): + activity = models.ForeignKey(Activity, on_delete=models.CASCADE) + branch = models.ForeignKey(Branch, on_delete=models.CASCADE) + score = models.DecimalField(max_digits=4, decimal_places=2) + comment = models.TextField() + file_path = models.CharField(max_length=255, blank=True, null=True) + status = models.CharField(max_length=20, + choices=(('pending', '待审核'), ('approved', '已通过'), ('rejected', '已拒绝')), + default='pending') + + def __str__(self): + return f"{self.activity.name} - {self.branch.name}" diff --git a/fzjgact/huodong/serializers.py b/fzjgact/huodong/serializers.py new file mode 100644 index 0000000..452fd7a --- /dev/null +++ b/fzjgact/huodong/serializers.py @@ -0,0 +1,20 @@ +from rest_framework import serializers +from .models import Branch, Activity, Evaluation + + +class BranchSerializer(serializers.ModelSerializer): + class Meta: + model = Branch + fields = '__all__' + + +class ActivitySerializer(serializers.ModelSerializer): + class Meta: + model = Activity + fields = '__all__' + + +class EvaluationSerializer(serializers.ModelSerializer): + class Meta: + model = Evaluation + fields = '__all__' diff --git a/fzjgact/huodong/static/huodong/input.css b/fzjgact/huodong/static/huodong/input.css new file mode 100644 index 0000000..bd6213e --- /dev/null +++ b/fzjgact/huodong/static/huodong/input.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/fzjgact/huodong/static/huodong/output.css b/fzjgact/huodong/static/huodong/output.css new file mode 100644 index 0000000..7fe32b9 --- /dev/null +++ b/fzjgact/huodong/static/huodong/output.css @@ -0,0 +1,1976 @@ +/* +! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ + -webkit-tap-highlight-color: transparent; + /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-feature-settings: normal; + /* 2 */ + font-variation-settings: normal; + /* 3 */ + font-size: 1em; + /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-feature-settings: inherit; + /* 1 */ + font-variation-settings: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + letter-spacing: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden] { + display: none; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +.\!container { + width: 100% !important; +} + +.container { + width: 100%; +} + +@media (min-width: 640px) { + .\!container { + max-width: 640px !important; + } + + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .\!container { + max-width: 768px !important; + } + + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .\!container { + max-width: 1024px !important; + } + + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .\!container { + max-width: 1280px !important; + } + + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .\!container { + max-width: 1536px !important; + } + + .container { + max-width: 1536px; + } +} + +.visible { + visibility: visible; +} + +.collapse { + visibility: collapse; +} + +.static { + position: static; +} + +.fixed { + position: fixed; +} + +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.inset-0 { + inset: 0px; +} + +.-bottom-8 { + bottom: -2rem; +} + +.-top-10 { + top: -2.5rem; +} + +.left-0 { + left: 0px; +} + +.left-2 { + left: 0.5rem; +} + +.right-0 { + right: 0px; +} + +.right-2 { + right: 0.5rem; +} + +.right-3 { + right: 0.75rem; +} + +.right-4 { + right: 1rem; +} + +.top-1 { + top: 0.25rem; +} + +.top-1\/2 { + top: 50%; +} + +.top-2 { + top: 0.5rem; +} + +.top-4 { + top: 1rem; +} + +.z-10 { + z-index: 10; +} + +.z-20 { + z-index: 20; +} + +.z-50 { + z-index: 50; +} + +.col-span-full { + grid-column: 1 / -1; +} + +.mx-1 { + margin-left: 0.25rem; + margin-right: 0.25rem; +} + +.mx-4 { + margin-left: 1rem; + margin-right: 1rem; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.my-8 { + margin-top: 2rem; + margin-bottom: 2rem; +} + +.mx-2 { + margin-left: 0.5rem; + margin-right: 0.5rem; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mb-3 { + margin-bottom: 0.75rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.mb-6 { + margin-bottom: 1.5rem; +} + +.mb-8 { + margin-bottom: 2rem; +} + +.ml-2 { + margin-left: 0.5rem; +} + +.mr-1 { + margin-right: 0.25rem; +} + +.mr-1\.5 { + margin-right: 0.375rem; +} + +.mt-1 { + margin-top: 0.25rem; +} + +.mt-10 { + margin-top: 2.5rem; +} + +.mt-3 { + margin-top: 0.75rem; +} + +.mt-4 { + margin-top: 1rem; +} + +.block { + display: block; +} + +.flex { + display: flex; +} + +.inline-flex { + display: inline-flex; +} + +.table { + display: table; +} + +.grid { + display: grid; +} + +.contents { + display: contents; +} + +.hidden { + display: none; +} + +.h-0 { + height: 0px; +} + +.h-0\.5 { + height: 0.125rem; +} + +.h-2 { + height: 0.5rem; +} + +.h-2\.5 { + height: 0.625rem; +} + +.h-3 { + height: 0.75rem; +} + +.h-4 { + height: 1rem; +} + +.h-48 { + height: 12rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-\[100px\] { + height: 100px; +} + +.h-\[150px\] { + height: 150px; +} + +.h-full { + height: 100%; +} + +.h-px { + height: 1px; +} + +.max-h-60 { + max-height: 15rem; +} + +.max-h-\[90vh\] { + max-height: 90vh; +} + +.min-h-screen { + min-height: 100vh; +} + +.w-1 { + width: 0.25rem; +} + +.w-1\/3 { + width: 33.333333%; +} + +.w-2 { + width: 0.5rem; +} + +.w-2\.5 { + width: 0.625rem; +} + +.w-3 { + width: 0.75rem; +} + +.w-4 { + width: 1rem; +} + +.w-48 { + width: 12rem; +} + +.w-6 { + width: 1.5rem; +} + +.w-\[calc\(50\%-2rem\)\] { + width: calc(50% - 2rem); +} + +.w-auto { + width: auto; +} + +.w-full { + width: 100%; +} + +.min-w-full { + min-width: 100%; +} + +.max-w-2xl { + max-width: 42rem; +} + +.max-w-4xl { + max-width: 56rem; +} + +.max-w-\[90\%\] { + max-width: 90%; +} + +.max-w-full { + max-width: 100%; +} + +.max-w-md { + max-width: 28rem; +} + +.flex-1 { + flex: 1 1 0%; +} + +.flex-none { + flex: none; +} + +.flex-grow { + flex-grow: 1; +} + +.border-collapse { + border-collapse: collapse; +} + +.-translate-y-1 { + --tw-translate-y: -0.25rem; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.-translate-y-1\/2 { + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.rotate-180 { + --tw-rotate: 180deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.transform { + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.cursor-pointer { + cursor: pointer; +} + +.resize { + resize: both; +} + +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + +.grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + +.grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); +} + +.flex-row { + flex-direction: row; +} + +.flex-col { + flex-direction: column; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.flex-nowrap { + flex-wrap: nowrap; +} + +.items-end { + align-items: flex-end; +} + +.items-center { + align-items: center; +} + +.justify-end { + justify-content: flex-end; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.gap-2 { + gap: 0.5rem; +} + +.gap-4 { + gap: 1rem; +} + +.gap-6 { + gap: 1.5rem; +} + +.space-y-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); +} + +.space-y-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(2rem * var(--tw-space-y-reverse)); +} + +.space-y-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); +} + +.divide-y > :not([hidden]) ~ :not([hidden]) { + --tw-divide-y-reverse: 0; + border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); + border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); +} + +.divide-gray-200 > :not([hidden]) ~ :not([hidden]) { + --tw-divide-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-divide-opacity)); +} + +.divide-gray-700 > :not([hidden]) ~ :not([hidden]) { + --tw-divide-opacity: 1; + border-color: rgb(55 65 81 / var(--tw-divide-opacity)); +} + +.self-end { + align-self: flex-end; +} + +.overflow-hidden { + overflow: hidden; +} + +.overflow-x-auto { + overflow-x: auto; +} + +.overflow-y-auto { + overflow-y: auto; +} + +.whitespace-nowrap { + white-space: nowrap; +} + +.rounded { + border-radius: 0.25rem; +} + +.rounded-full { + border-radius: 9999px; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.rounded-xl { + border-radius: 0.75rem; +} + +.rounded-l-md { + border-top-left-radius: 0.375rem; + border-bottom-left-radius: 0.375rem; +} + +.rounded-r-md { + border-top-right-radius: 0.375rem; + border-bottom-right-radius: 0.375rem; +} + +.border { + border-width: 1px; +} + +.border-0 { + border-width: 0px; +} + +.border-4 { + border-width: 4px; +} + +.border-b { + border-bottom-width: 1px; +} + +.border-l-0 { + border-left-width: 0px; +} + +.border-l-4 { + border-left-width: 4px; +} + +.border-r-0 { + border-right-width: 0px; +} + +.border-t { + border-top-width: 1px; +} + +.border-solid { + border-style: solid; +} + +.border-black { + --tw-border-opacity: 1; + border-color: rgb(0 0 0 / var(--tw-border-opacity)); +} + +.border-blue-500 { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + +.border-gray-100 { + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); +} + +.border-gray-200 { + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); +} + +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} + +.border-gray-700 { + --tw-border-opacity: 1; + border-color: rgb(55 65 81 / var(--tw-border-opacity)); +} + +.border-white { + --tw-border-opacity: 1; + border-color: rgb(255 255 255 / var(--tw-border-opacity)); +} + +.border-gray-800 { + --tw-border-opacity: 1; + border-color: rgb(31 41 55 / var(--tw-border-opacity)); +} + +.bg-black { + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); +} + +.bg-blue-100 { + --tw-bg-opacity: 1; + background-color: rgb(219 234 254 / var(--tw-bg-opacity)); +} + +.bg-blue-200 { + --tw-bg-opacity: 1; + background-color: rgb(191 219 254 / var(--tw-bg-opacity)); +} + +.bg-blue-50 { + --tw-bg-opacity: 1; + background-color: rgb(239 246 255 / var(--tw-bg-opacity)); +} + +.bg-blue-500 { + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); +} + +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + +.bg-gray-300 { + --tw-bg-opacity: 1; + background-color: rgb(209 213 219 / var(--tw-bg-opacity)); +} + +.bg-gray-50 { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); +} + +.bg-gray-700 { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); +} + +.bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); +} + +.bg-red-500 { + --tw-bg-opacity: 1; + background-color: rgb(239 68 68 / var(--tw-bg-opacity)); +} + +.bg-red-700 { + --tw-bg-opacity: 1; + background-color: rgb(185 28 28 / var(--tw-bg-opacity)); +} + +.bg-transparent { + background-color: transparent; +} + +.bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.bg-blue-900 { + --tw-bg-opacity: 1; + background-color: rgb(30 58 138 / var(--tw-bg-opacity)); +} + +.bg-gray-900 { + --tw-bg-opacity: 1; + background-color: rgb(17 24 39 / var(--tw-bg-opacity)); +} + +.bg-opacity-50 { + --tw-bg-opacity: 0.5; +} + +.bg-opacity-75 { + --tw-bg-opacity: 0.75; +} + +.bg-opacity-80 { + --tw-bg-opacity: 0.8; +} + +.bg-gradient-to-r { + background-image: linear-gradient(to right, var(--tw-gradient-stops)); +} + +.from-blue-50 { + --tw-gradient-from: #eff6ff var(--tw-gradient-from-position); + --tw-gradient-to: rgb(239 246 255 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.from-purple-50 { + --tw-gradient-from: #faf5ff var(--tw-gradient-from-position); + --tw-gradient-to: rgb(250 245 255 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.to-indigo-50 { + --tw-gradient-to: #eef2ff var(--tw-gradient-to-position); +} + +.to-pink-50 { + --tw-gradient-to: #fdf2f8 var(--tw-gradient-to-position); +} + +.object-cover { + -o-object-fit: cover; + object-fit: cover; +} + +.p-2 { + padding: 0.5rem; +} + +.p-3 { + padding: 0.75rem; +} + +.p-4 { + padding: 1rem; +} + +.p-5 { + padding: 1.25rem; +} + +.p-6 { + padding: 1.5rem; +} + +.p-8 { + padding: 2rem; +} + +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.py-10 { + padding-top: 2.5rem; + padding-bottom: 2.5rem; +} + +.py-12 { + padding-top: 3rem; + padding-bottom: 3rem; +} + +.py-16 { + padding-top: 4rem; + padding-bottom: 4rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-2\.5 { + padding-top: 0.625rem; + padding-bottom: 0.625rem; +} + +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.py-8 { + padding-top: 2rem; + padding-bottom: 2rem; +} + +.pl-4 { + padding-left: 1rem; +} + +.pr-10 { + padding-right: 2.5rem; +} + +.text-left { + text-align: left; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +.align-middle { + vertical-align: middle; +} + +.font-sans { + font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} + +.text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; +} + +.text-\[clamp\(1\.5rem\2c 3vw\2c 2\.5rem\)\] { + font-size: clamp(1.5rem,3vw,2.5rem); +} + +.text-base { + font-size: 1rem; + line-height: 1.5rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-bold { + font-weight: 700; +} + +.font-medium { + font-weight: 500; +} + +.font-normal { + font-weight: 400; +} + +.font-semibold { + font-weight: 600; +} + +.uppercase { + text-transform: uppercase; +} + +.italic { + font-style: italic; +} + +.ordinal { + --tw-ordinal: ordinal; + font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction); +} + +.leading-none { + line-height: 1; +} + +.leading-relaxed { + line-height: 1.625; +} + +.leading-tight { + line-height: 1.25; +} + +.tracking-wider { + letter-spacing: 0.05em; +} + +.text-blue-300 { + --tw-text-opacity: 1; + color: rgb(147 197 253 / var(--tw-text-opacity)); +} + +.text-blue-500 { + --tw-text-opacity: 1; + color: rgb(59 130 246 / var(--tw-text-opacity)); +} + +.text-blue-600 { + --tw-text-opacity: 1; + color: rgb(37 99 235 / var(--tw-text-opacity)); +} + +.text-blue-700 { + --tw-text-opacity: 1; + color: rgb(29 78 216 / var(--tw-text-opacity)); +} + +.text-blue-800 { + --tw-text-opacity: 1; + color: rgb(30 64 175 / var(--tw-text-opacity)); +} + +.text-blue-900 { + --tw-text-opacity: 1; + color: rgb(30 58 138 / var(--tw-text-opacity)); +} + +.text-gray-400 { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} + +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.text-gray-600 { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); +} + +.text-gray-700 { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} + +.text-gray-800 { + --tw-text-opacity: 1; + color: rgb(31 41 55 / var(--tw-text-opacity)); +} + +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + +.text-indigo-600 { + --tw-text-opacity: 1; + color: rgb(79 70 229 / var(--tw-text-opacity)); +} + +.text-indigo-700 { + --tw-text-opacity: 1; + color: rgb(67 56 202 / var(--tw-text-opacity)); +} + +.text-purple-600 { + --tw-text-opacity: 1; + color: rgb(147 51 234 / var(--tw-text-opacity)); +} + +.text-purple-700 { + --tw-text-opacity: 1; + color: rgb(126 34 206 / var(--tw-text-opacity)); +} + +.text-red-900 { + --tw-text-opacity: 1; + color: rgb(127 29 29 / var(--tw-text-opacity)); +} + +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.text-yellow-500 { + --tw-text-opacity: 1; + color: rgb(234 179 8 / var(--tw-text-opacity)); +} + +.text-gray-300 { + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); +} + +.text-blue-200 { + --tw-text-opacity: 1; + color: rgb(191 219 254 / var(--tw-text-opacity)); +} + +.text-blue-400 { + --tw-text-opacity: 1; + color: rgb(96 165 250 / var(--tw-text-opacity)); +} + +.text-gray-200 { + --tw-text-opacity: 1; + color: rgb(229 231 235 / var(--tw-text-opacity)); +} + +.text-indigo-400 { + --tw-text-opacity: 1; + color: rgb(129 140 248 / var(--tw-text-opacity)); +} + +.underline { + text-decoration-line: underline; +} + +.shadow { + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-lg { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-md { + --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-sm { + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.outline-none { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.outline { + outline-style: solid; +} + +.filter { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + +.transition { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-all { + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-shadow { + transition-property: box-shadow; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.transition-transform { + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.duration-200 { + transition-duration: 200ms; +} + +.duration-300 { + transition-duration: 300ms; +} + +.hover\:bg-blue-600:hover { + --tw-bg-opacity: 1; + background-color: rgb(37 99 235 / var(--tw-bg-opacity)); +} + +.hover\:bg-blue-700:hover { + --tw-bg-opacity: 1; + background-color: rgb(29 78 216 / var(--tw-bg-opacity)); +} + +.hover\:bg-blue-900:hover { + --tw-bg-opacity: 1; + background-color: rgb(30 58 138 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-50:hover { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); +} + +.hover\:text-blue-800:hover { + --tw-text-opacity: 1; + color: rgb(30 64 175 / var(--tw-text-opacity)); +} + +.hover\:text-gray-300:hover { + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); +} + +.hover\:text-white:hover { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.hover\:shadow-lg:hover { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.hover\:shadow-xl:hover { + --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.focus\:border-blue-500:focus { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.focus\:ring-1:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus\:ring-2:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus\:ring-blue-300:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(147 197 253 / var(--tw-ring-opacity)); +} + +.focus\:ring-blue-500:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity)); +} + +@media (min-width: 640px) { + .sm\:flex { + display: flex; + } + + .sm\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .sm\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} + +@media (min-width: 768px) { + .md\:h-\[150px\] { + height: 150px; + } + + .md\:w-1\/3 { + width: 33.333333%; + } + + .md\:w-48 { + width: 12rem; + } + + .md\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .md\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .md\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .md\:flex-row { + flex-direction: row; + } +} + +@media (min-width: 1024px) { + .lg\:h-\[200px\] { + height: 200px; + } + + .lg\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .lg\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } +} + +@media (prefers-color-scheme: dark) { + .dark\:divide-gray-700 > :not([hidden]) ~ :not([hidden]) { + --tw-divide-opacity: 1; + border-color: rgb(55 65 81 / var(--tw-divide-opacity)); + } + + .dark\:border-gray-700 { + --tw-border-opacity: 1; + border-color: rgb(55 65 81 / var(--tw-border-opacity)); + } + + .dark\:border-gray-800 { + --tw-border-opacity: 1; + border-color: rgb(31 41 55 / var(--tw-border-opacity)); + } + + .dark\:bg-gray-700 { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); + } + + .dark\:bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); + } + + .dark\:bg-red-700 { + --tw-bg-opacity: 1; + background-color: rgb(185 28 28 / var(--tw-bg-opacity)); + } + + .dark\:bg-blue-900 { + --tw-bg-opacity: 1; + background-color: rgb(30 58 138 / var(--tw-bg-opacity)); + } + + .dark\:bg-gray-900 { + --tw-bg-opacity: 1; + background-color: rgb(17 24 39 / var(--tw-bg-opacity)); + } + + .dark\:text-blue-300 { + --tw-text-opacity: 1; + color: rgb(147 197 253 / var(--tw-text-opacity)); + } + + .dark\:text-gray-400 { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); + } + + .dark\:text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); + } + + .dark\:text-blue-200 { + --tw-text-opacity: 1; + color: rgb(191 219 254 / var(--tw-text-opacity)); + } + + .dark\:text-blue-400 { + --tw-text-opacity: 1; + color: rgb(96 165 250 / var(--tw-text-opacity)); + } + + .dark\:text-gray-200 { + --tw-text-opacity: 1; + color: rgb(229 231 235 / var(--tw-text-opacity)); + } + + .dark\:text-gray-300 { + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); + } + + .dark\:text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); + } + + .dark\:text-gray-600 { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); + } + + .dark\:text-indigo-400 { + --tw-text-opacity: 1; + color: rgb(129 140 248 / var(--tw-text-opacity)); + } + + .dark\:hover\:bg-gray-700:hover { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); + } +} \ No newline at end of file diff --git a/fzjgact/huodong/templates/admin/huodong/add_form.html b/fzjgact/huodong/templates/admin/huodong/add_form.html new file mode 100644 index 0000000..b4a0fd7 --- /dev/null +++ b/fzjgact/huodong/templates/admin/huodong/add_form.html @@ -0,0 +1,12 @@ +{% extends "admin/change_form.html" %} +{% load i18n admin_urls static admin_modify %} + +{% block extrahead %} + {{ block.super }} + +{% endblock %} + +{% block content %} +

自定义的添加表单

+ {{ block.super }} +{% endblock %} diff --git a/fzjgact/huodong/templates/admin/huodong/drawing/change_list.html b/fzjgact/huodong/templates/admin/huodong/drawing/change_list.html new file mode 100644 index 0000000..f0a2479 --- /dev/null +++ b/fzjgact/huodong/templates/admin/huodong/drawing/change_list.html @@ -0,0 +1,6 @@ +{% extends "admin/change_list.html" %} + +{% block actions %} +{{ block.super }} + +{% endblock %} \ No newline at end of file diff --git a/fzjgact/huodong/templates/admin/huodong/equipmentimage/change_list.html b/fzjgact/huodong/templates/admin/huodong/equipmentimage/change_list.html new file mode 100644 index 0000000..0dfb597 --- /dev/null +++ b/fzjgact/huodong/templates/admin/huodong/equipmentimage/change_list.html @@ -0,0 +1,6 @@ +{% extends "admin/change_list.html" %} + +{% block actions %} +{{ block.super }} + +{% endblock %} \ No newline at end of file diff --git a/fzjgact/huodong/templates/admin/huodong/publicscreen/change_list.html b/fzjgact/huodong/templates/admin/huodong/publicscreen/change_list.html new file mode 100644 index 0000000..2005d37 --- /dev/null +++ b/fzjgact/huodong/templates/admin/huodong/publicscreen/change_list.html @@ -0,0 +1,6 @@ +{% extends "admin/change_list.html" %} + +{% block actions %} +{{ block.super }} + +{% endblock %} \ No newline at end of file diff --git a/fzjgact/huodong/templates/base.html b/fzjgact/huodong/templates/base.html new file mode 100644 index 0000000..aa6d4a7 --- /dev/null +++ b/fzjgact/huodong/templates/base.html @@ -0,0 +1,101 @@ + +{% load static %} +{% load custom_filters %} + + + + + + 分支机构活动管理 + + + + + +
+ 分支机构活动管理 +
+ 2025年 +
+ + +
+ + + + +
+ {% block content %} + {% endblock %} +
+ + + + +
+ + + + + + \ No newline at end of file diff --git a/fzjgact/huodong/templates/branch_all.html b/fzjgact/huodong/templates/branch_all.html new file mode 100644 index 0000000..380735e --- /dev/null +++ b/fzjgact/huodong/templates/branch_all.html @@ -0,0 +1,292 @@ +{% extends 'base.html' %} +{% load custom_filters %} + +{% block content %} +
+
+ +
+ +
+ +
+
+
+
最初活动
+

{{ earliest_act.branch }}{{ earliest_act.name }}

+

+ {{ earliest_act.description }} +

+
+
+ + + + + {{ earliest_act.start_time|format_chinese_full_date }} + +
+
+
+ + +
+ + + +
+ + +
+
+
+
最后活动
+

{{ latest_act.branch }}{{ latest_act.name }}

+

+ {{ latest_act.description }} +

+
+
+ + + + + {{ latest_act.start_time|format_chinese_full_date }} +
+
+
+
+ + +
+
+
+
+ + + + + + + + + + + + {% for item in branches %} + + + + + + + + {% endfor %} + + + + + + + +
+ 分支机构名称 +
+ 新建-搬迁-装修 +
+ 活动的总数量 + + 活动进行中的数量 +
+ + {{ item.branch.name }} + + + {{ item.total_count }} + + {{ item.onging_count }} +
+ 总计: {{ total_branch_count }} + + {{ total_activities }} + + {{ ongoing_activities_count }} +
+ +
+ + + +
+ +
    + {% for event in ongoing_events %} +
  1. +
    +
    + + + + + 开始时间 {{ event.start_time| date:"Y年m月d日" }} + +
    + + {% if not event.end_time %} + + {{ event.name }}-未完成 + + {% else %} + + {{ event.name }} + + {% endif %} + +
    +
    + {{ event.description }} +
    + + + + + 结束时间 {{ event.end_time| date:"Y年m月d日" }} + +
    +
    + +
  2. + {% endfor %} +
+
+ +
+ + +
+ +
    + {% for huodong in ongoing_activities %} +
  1. +
    +
    + + + + + 开始时间 {{ huodong.start_time| date:"Y年m月d日" }} + +
    + + {% if not huodong.end_time %} + + + {{ huodong.branch }} + + {{ huodong.name }}-未完成 + + {% endif %} + +
    +
    + {{ huodong.description }} +
    +
    +
    +
  2. + {% endfor %} +
+
+ +
+ +{% for scope, scope_data in grouped_activities.items %} +
+ +
    + {% for activity in scope_data.activities %} +
  1. +
    +
    + + + + + 开始时间 {{ activity.start_time| date:"Y年m月d日" }} + +
    + + {% if not activity.end_time %} + + + {{ activity.branch }} + + {{ activity.name }}-未完成 + + {% else %} + + + {{ activity.branch }} + + {{ activity.name }} + + {% endif %} + +
    +
    + {{ activity.description }} +
    + + + 结束时间 {{ activity.end_time| date:"Y年m月d日" }} + +
    +
    +
  2. + {% endfor %} +
+
+
+{% endfor %} + + +
+ + +{% for year in historical_years %} +{% with year_data=historical_grouped_activities|get_item:year %} +{% if year_data %} + +
+{% endif %} +{% endwith %} +{% endfor %} + + +{% endblock %} diff --git a/fzjgact/huodong/templates/branch_detail.html b/fzjgact/huodong/templates/branch_detail.html new file mode 100644 index 0000000..98e42da --- /dev/null +++ b/fzjgact/huodong/templates/branch_detail.html @@ -0,0 +1,145 @@ +{% extends 'base.html' %} + +{% block content %} + + +

+ + + {{ branch.name }} + + +

+ +
+

基本信息

+
+
+

信息系统分类: {{ branch.category|default:"暂无" }}

+

联系人: {{ branch.contact_person|default:"暂无" }}

+

联系电话: {{ branch.contact_phone|default:"暂无" }}

+
+
+

地址: {{ branch.address|default:"暂无" }}

+

成立时间: {{ branch.established_date|date:"Y-m-d"|default:"暂无" }}

+
+
+
+ + +
+

关联事件

+ {% if events %} +
+ {% for event in events %} +
+

{{ event.name }}

+

+ {{ event.start_time|date:"Y-m-d H:i" }} - {{ event.end_time|date:"Y-m-d H:i"|default:"进行中" }} +

+

{{ event.description|truncatechars:100 }}

+
+ {% endfor %} +
+ {% else %} +

暂无事件记录

+ {% endif %} +
+ + +
+

设备间图片

+ {% if equipment_images %} +
+ {% for image in equipment_images %} +
+ 设备间图片 +
+

{{ image.description|default:"无描述" }}

+

{{ image.upload_date|date:"Y-m-d" }}

+
+
+ {% endfor %} +
+ {% else %} +

暂无设备间图片

+ {% endif %} +
+ + +
+

公共电子屏

+ {% if public_screens %} +
+ + + + + + + + + + + {% for screen in public_screens %} + + + + + + + {% endfor %} + +
类型描述最后演练更新时间
{{ screen.get_screen_type_display }}{{ screen.description|default:"无" }}{{ screen.last_drill.date|date:"Y-m-d"|default:"未演练" }}{{ screen.updated_at|date:"Y-m-d H:i" }}
+
+ {% else %} +

暂无公共电子屏信息

+ {% endif %} +
+{% for scope, activities in grouped_activities.items %} + +
+ +
    + {% for huodong in activities %} +
  1. +
    +
    + + + + + 开始时间 {{ huodong.start_time| date:"Y年m月d日" }} + +
    + + {% if not huodong.end_time %} + + {{ huodong.name }}-未完成 + + {% else %} + + {{ huodong.name }} + + {% endif %} + +
    +
    + {{ huodong.description }} +
    + + + 结束时间 {{ huodong.end_time| date:"Y年m月d日" }} + +
    +
    +
  2. + {% endfor %} +
+
+
+{% endfor %} + +{% endblock %} diff --git a/fzjgact/huodong/templates/branch_info.html b/fzjgact/huodong/templates/branch_info.html new file mode 100644 index 0000000..39a61c6 --- /dev/null +++ b/fzjgact/huodong/templates/branch_info.html @@ -0,0 +1,59 @@ +{% extends 'base.html' %} + + +{% block content %} + + + + + + + + + + {% for item in branches %} + + + + + + + {% endfor %} + + + + + + +
+ 分支机构名称 +
+ 基础信息 +
+ 信息系统类别 +
+ + {{ item.name }} + + + {{ item.category }} +
+ +
+ +
+{% endblock %} \ No newline at end of file diff --git a/fzjgact/huodong/templates/contact_list.html b/fzjgact/huodong/templates/contact_list.html new file mode 100644 index 0000000..cb1d4a3 --- /dev/null +++ b/fzjgact/huodong/templates/contact_list.html @@ -0,0 +1,310 @@ +{% extends "base.html" %} + +{% block content %} +
+

联系人信息

+ + +
+
+ +
+ +
+ +
+ + + + + + +
+ + + +
+
+ + +
+ +
+
+ + + + + +
+ + +
+
+ + +
+ + +
+ +
+ +
+
+
+ + + + + + + + + + + + + {% for contact in contacts %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
分支机构分类姓名电话邮箱
{{ contact.branch.name }}{{ contact.category|default:"" }}{{ contact.name|default:"" }}{{ contact.phone|default:"" }}{{ contact.email|default:"" }}
没有找到匹配的联系人
+
+ + +{% endblock %} \ No newline at end of file diff --git a/fzjgact/huodong/templates/equipment_images.html b/fzjgact/huodong/templates/equipment_images.html new file mode 100644 index 0000000..13dc392 --- /dev/null +++ b/fzjgact/huodong/templates/equipment_images.html @@ -0,0 +1,174 @@ +{% extends 'base.html' %} + +{% block content %} +
+

分支机构设备间图片列表

+
+
+
+ + +
+
+
+

共 {{ total_count }} 个分支机构

+ + {% if branches %} +
+ {% for branch in branches %} +
+
+

{{ branch.name }}

+ + 查看分支机构详情 → + +
+
+ {% if branch.equipment_images.exists %} +
+ {% for image in branch.equipment_images.all %} + {{ branch.name }}设备间图片 + {% endfor %} +
+ {% else %} +
+ 无图片 +
+ {% endif %} +
+ + +
+

图纸

+ {% if branch.drawings.exists %} +
+ {% for drawing in branch.drawings.all %} + {{ branch.name }}图纸 + {% endfor %} +
+ {% else %} +
+ 无图纸 +
+ {% endif %} +
+ + + + + + +
+ {% endfor %} +
+ + +
+ +
+ {% else %} +
+

暂无分支机构设备间图片数据

+
+ {% endif %} +
+{% endblock %} \ No newline at end of file diff --git a/fzjgact/huodong/templates/public_screens.html b/fzjgact/huodong/templates/public_screens.html new file mode 100644 index 0000000..47013cf --- /dev/null +++ b/fzjgact/huodong/templates/public_screens.html @@ -0,0 +1,94 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} +
+

公共电子屏列表

+ + +
+
+
+ + +
+
+ + +
+
+ + {% if request.GET.branch or request.GET.screen_type %} + 清除筛选 + {% endif %} +
+
+
+ + +
+ {% for screen in public_screens %} +
+
+ {{ screen.get_screen_type_display }} +
+ {{ screen.get_screen_type_display }} +
+
+
+

{{ screen.branch.name }}

+ {% if screen.description %} +

{{ screen.description|truncatechars:100 }}

+ {% endif %} +
+ {% if screen.last_drill %} +

最后演练: {{ screen.last_drill.date|date:"Y-m-d H:i" }}

+ {% else %} +

暂无演练记录

+ {% endif %} +

更新时间: {{ screen.updated_at|date:"Y-m-d H:i" }}

+
+
+
+ {% empty %} +
+

暂无公共电子屏记录

+
+ {% endfor %} +
+
+ + + + + +{% endblock %} \ No newline at end of file diff --git a/fzjgact/huodong/templates/searchable-select.html b/fzjgact/huodong/templates/searchable-select.html new file mode 100644 index 0000000..1669a88 --- /dev/null +++ b/fzjgact/huodong/templates/searchable-select.html @@ -0,0 +1,238 @@ + + + + + + 带搜索功能的下拉选择框 + + + + + + + + + + + + +
+

带搜索功能的下拉选择框

+ +
+
+ + +
+ +
+ + + + +
+ + + +
+ + + +
+ +
+

点击选择框,开始输入城市名称进行搜索

+
+
+
+ + + + \ No newline at end of file diff --git a/fzjgact/huodong/templates/statistics.html b/fzjgact/huodong/templates/statistics.html new file mode 100644 index 0000000..203b326 --- /dev/null +++ b/fzjgact/huodong/templates/statistics.html @@ -0,0 +1,79 @@ +{% extends "base.html" %} +{% load custom_filters %} + +{% block content %} +
+ +
+
+ +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+ + +
+

活动统计结果(共{{ activities.count }}条)

+ + + + + + + + + + + + {% for activity in activities %} + + + + + + + + {% empty %} + + + + {% endfor %} + +
活动名称分支机构活动分类开始时间结束时间
{{ activity.name }}{{ activity.branch.name }}{{ activity.scope }}{{ activity.start_time|format_chinese_full_date }}{{ activity.end_time|format_chinese_full_date|default:"未结束" }}
无符合条件的活动记录
+
+
+{% endblock %} \ No newline at end of file diff --git a/fzjgact/huodong/templates/video_terminals.html b/fzjgact/huodong/templates/video_terminals.html new file mode 100644 index 0000000..2e44dcf --- /dev/null +++ b/fzjgact/huodong/templates/video_terminals.html @@ -0,0 +1,94 @@ +{% extends "base.html" %} + +{% block content %} +
+

视频设备终端列表

+ + +
+
+ +
+ +
+ +
+
全部分支机构
+
+
+ +
+
+ + +
+ +
+ +
+
全部类型
+
+
+ +
+
+ +
+ +
+
+
+ + + + + + + + + + + + + {% for terminal in terminals %} + + + + + + + {% empty %} + + + + {% endfor %} + +
分支机构设备类型设备描述创建时间
{{ terminal.branch.name }}{{ terminal.get_terminal_type_display }}{{ terminal.description|default:"" }}{{ terminal.created_at|date:"Y-m-d H:i" }}
没有找到匹配的视频设备终端
+
+{% endblock %} \ No newline at end of file diff --git a/fzjgact/huodong/templatetags/__init__.py b/fzjgact/huodong/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fzjgact/huodong/templatetags/__pycache__/__init__.cpython-311.pyc b/fzjgact/huodong/templatetags/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..13f53cd Binary files /dev/null and b/fzjgact/huodong/templatetags/__pycache__/__init__.cpython-311.pyc differ diff --git a/fzjgact/huodong/templatetags/__pycache__/custom_filters.cpython-311.pyc b/fzjgact/huodong/templatetags/__pycache__/custom_filters.cpython-311.pyc new file mode 100644 index 0000000..d7b3198 Binary files /dev/null and b/fzjgact/huodong/templatetags/__pycache__/custom_filters.cpython-311.pyc differ diff --git a/fzjgact/huodong/templatetags/custom_filters.py b/fzjgact/huodong/templatetags/custom_filters.py new file mode 100644 index 0000000..57f568c --- /dev/null +++ b/fzjgact/huodong/templatetags/custom_filters.py @@ -0,0 +1,30 @@ +from datetime import datetime + +from django import template + +register = template.Library() + + +@register.filter +def format_chinese_full_date(value): + if not value: + return "" + + # 确保传入的是datetime对象 + if isinstance(value, datetime): + return value.strftime("%Y年%m月%d日") + + if isinstance(value, str): + try: + # 尝试将字符串转换为 datetime 对象 + # 假设字符串格式为 'YYYY-MM-DD',可按需调整 + value = datetime.strptime(value, '%Y-%m-%d') + except ValueError: + value_str = value + + # 现在传入的值都是date类型 + value_str = value.strftime('%Y年%m月%d日') + date_obj = value + weekdays = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"] + weekday = weekdays[date_obj.weekday()] + return f"{date_obj.year}年{date_obj.month}月{date_obj.day}日 {weekday}" diff --git a/fzjgact/huodong/tests.py b/fzjgact/huodong/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/fzjgact/huodong/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/fzjgact/huodong/urls.py b/fzjgact/huodong/urls.py new file mode 100644 index 0000000..37f4164 --- /dev/null +++ b/fzjgact/huodong/urls.py @@ -0,0 +1,22 @@ +from django.urls import path, include +from rest_framework.routers import DefaultRouter +from . import views + +router = DefaultRouter() +router.register(r'branches', views.BranchViewSet, basename='branches') +router.register(r'activities', views.ActivityViewSet, basename='activities') +router.register(r'evaluations', views.EvaluationViewSet, basename='evaluations') + +urlpatterns = [ + path('api/', include(router.urls)), + path('', views.BranchAll, name='branch-all'), + path('branch//', views.branch_detail, name='branch-detail'), + path('branch/info/', views.Branchinfo, name='branchinfo'), + path('statistics/', views.Statistics, name='statistics'), + path('contact/', views.contact_list, name='contact-list'), + path('equipment-images/', views.equipment_images, name='equipment-images'), + path('public-screens/', views.public_screens, name='public-screens'), + path('video-terminals/', views.video_terminal_list, name='video-terminals'), + path('export/xls/', views.export_branches_xls, name='export-branches-xls'), + path('export/pdf/', views.export_branches_pdf, name='export-branches-pdf'), +] \ No newline at end of file diff --git a/fzjgact/huodong/views.py b/fzjgact/huodong/views.py new file mode 100644 index 0000000..ba50a67 --- /dev/null +++ b/fzjgact/huodong/views.py @@ -0,0 +1,438 @@ +from rest_framework import viewsets +from .models import Branch, Activity, Evaluation, Event, VideoTerminal +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() + + # 准备上下文数据 + context = { + 'branch': branch, + 'grouped_activities': grouped_activities, + 'events': events, + 'equipment_images': equipment_images, + 'public_screens': public_screens, + } + return render(request, 'branch_detail.html', context) + + +# 在页面上显示所有的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) + # 比如说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, + '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 + context = {'branches': branches, } + 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): + # 获取筛选参数 + branch_id = request.GET.get('branch') + category = request.GET.get('category') + contact_name = request.GET.get('contact_name') + + # 构建查询条件 + filters = Q() + + # 分支机构筛选 + if branch_id: + filters &= Q(branch_id=branch_id) + + # 联系人类别筛选 + 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_branch': branch_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) diff --git a/fzjgact/manage.py b/fzjgact/manage.py new file mode 100644 index 0000000..4ab46fa --- /dev/null +++ b/fzjgact/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'fzjgact.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/fzjgact/media/equipment_room_images/1.jpg b/fzjgact/media/equipment_room_images/1.jpg new file mode 100644 index 0000000..4ffe46f Binary files /dev/null and b/fzjgact/media/equipment_room_images/1.jpg differ diff --git a/fzjgact/media/equipment_room_images/2.jpg b/fzjgact/media/equipment_room_images/2.jpg new file mode 100644 index 0000000..9909316 Binary files /dev/null and b/fzjgact/media/equipment_room_images/2.jpg differ diff --git a/fzjgact/media/equipment_room_images/202405066.jpg b/fzjgact/media/equipment_room_images/202405066.jpg new file mode 100644 index 0000000..57ce5bb Binary files /dev/null and b/fzjgact/media/equipment_room_images/202405066.jpg differ diff --git a/fzjgact/media/equipment_room_images/20240506_1.jpg b/fzjgact/media/equipment_room_images/20240506_1.jpg new file mode 100644 index 0000000..76fc22c Binary files /dev/null and b/fzjgact/media/equipment_room_images/20240506_1.jpg differ diff --git a/fzjgact/media/equipment_room_images/20240506_2.jpg b/fzjgact/media/equipment_room_images/20240506_2.jpg new file mode 100644 index 0000000..c2bc916 Binary files /dev/null and b/fzjgact/media/equipment_room_images/20240506_2.jpg differ diff --git a/fzjgact/media/equipment_room_images/20240506_3.jpg b/fzjgact/media/equipment_room_images/20240506_3.jpg new file mode 100644 index 0000000..7902fb1 Binary files /dev/null and b/fzjgact/media/equipment_room_images/20240506_3.jpg differ diff --git a/fzjgact/media/equipment_room_images/20240506_4.jpg b/fzjgact/media/equipment_room_images/20240506_4.jpg new file mode 100644 index 0000000..caeb539 Binary files /dev/null and b/fzjgact/media/equipment_room_images/20240506_4.jpg differ diff --git a/fzjgact/media/equipment_room_images/20240506_5.jpg b/fzjgact/media/equipment_room_images/20240506_5.jpg new file mode 100644 index 0000000..2434566 Binary files /dev/null and b/fzjgact/media/equipment_room_images/20240506_5.jpg differ diff --git a/fzjgact/media/equipment_room_images/3.jpg b/fzjgact/media/equipment_room_images/3.jpg new file mode 100644 index 0000000..df08d54 Binary files /dev/null and b/fzjgact/media/equipment_room_images/3.jpg differ diff --git a/fzjgact/media/equipment_room_images/4.jpg b/fzjgact/media/equipment_room_images/4.jpg new file mode 100644 index 0000000..2128871 Binary files /dev/null and b/fzjgact/media/equipment_room_images/4.jpg differ diff --git a/fzjgact/media/equipment_room_images/5.jpg b/fzjgact/media/equipment_room_images/5.jpg new file mode 100644 index 0000000..59c0217 Binary files /dev/null and b/fzjgact/media/equipment_room_images/5.jpg differ diff --git a/fzjgact/media/equipment_room_images/6.jpg b/fzjgact/media/equipment_room_images/6.jpg new file mode 100644 index 0000000..ffba65a Binary files /dev/null and b/fzjgact/media/equipment_room_images/6.jpg differ diff --git a/fzjgact/media/equipment_room_images/IMG_20240423_101341.jpg b/fzjgact/media/equipment_room_images/IMG_20240423_101341.jpg new file mode 100644 index 0000000..5c0c9c7 Binary files /dev/null and b/fzjgact/media/equipment_room_images/IMG_20240423_101341.jpg differ diff --git a/fzjgact/media/equipment_room_images/IMG_20240423_101408.jpg b/fzjgact/media/equipment_room_images/IMG_20240423_101408.jpg new file mode 100644 index 0000000..e917bc2 Binary files /dev/null and b/fzjgact/media/equipment_room_images/IMG_20240423_101408.jpg differ diff --git a/fzjgact/media/equipment_room_images/UPS.jpg b/fzjgact/media/equipment_room_images/UPS.jpg new file mode 100644 index 0000000..7b71598 Binary files /dev/null and b/fzjgact/media/equipment_room_images/UPS.jpg differ diff --git a/fzjgact/media/equipment_room_images/UPS配电箱.jpg b/fzjgact/media/equipment_room_images/UPS配电箱.jpg new file mode 100644 index 0000000..8544cce Binary files /dev/null and b/fzjgact/media/equipment_room_images/UPS配电箱.jpg differ diff --git a/fzjgact/media/equipment_room_images/UPS间-1.jpg b/fzjgact/media/equipment_room_images/UPS间-1.jpg new file mode 100644 index 0000000..802fe2a Binary files /dev/null and b/fzjgact/media/equipment_room_images/UPS间-1.jpg differ diff --git a/fzjgact/media/equipment_room_images/UPS间-2.jpg b/fzjgact/media/equipment_room_images/UPS间-2.jpg new file mode 100644 index 0000000..2baf9d3 Binary files /dev/null and b/fzjgact/media/equipment_room_images/UPS间-2.jpg differ diff --git a/fzjgact/media/equipment_room_images/UPS间-3.jpg b/fzjgact/media/equipment_room_images/UPS间-3.jpg new file mode 100644 index 0000000..63b8ca1 Binary files /dev/null and b/fzjgact/media/equipment_room_images/UPS间-3.jpg differ diff --git a/fzjgact/media/equipment_room_images/UPS间1.jpg b/fzjgact/media/equipment_room_images/UPS间1.jpg new file mode 100644 index 0000000..17849ef Binary files /dev/null and b/fzjgact/media/equipment_room_images/UPS间1.jpg differ diff --git a/fzjgact/media/equipment_room_images/UPS间2.jpg b/fzjgact/media/equipment_room_images/UPS间2.jpg new file mode 100644 index 0000000..2e90062 Binary files /dev/null and b/fzjgact/media/equipment_room_images/UPS间2.jpg differ diff --git a/fzjgact/media/equipment_room_images/UPS间3.jpg b/fzjgact/media/equipment_room_images/UPS间3.jpg new file mode 100644 index 0000000..e0ae555 Binary files /dev/null and b/fzjgact/media/equipment_room_images/UPS间3.jpg differ diff --git a/fzjgact/media/equipment_room_images/东兴证券福州长乐郑和中路证券营业部机房机柜照片.jpg b/fzjgact/media/equipment_room_images/东兴证券福州长乐郑和中路证券营业部机房机柜照片.jpg new file mode 100644 index 0000000..0fac2cc Binary files /dev/null and b/fzjgact/media/equipment_room_images/东兴证券福州长乐郑和中路证券营业部机房机柜照片.jpg differ diff --git a/fzjgact/media/equipment_room_images/东兴证券福州长乐郑和中路证券营业部机房照片1.jpg b/fzjgact/media/equipment_room_images/东兴证券福州长乐郑和中路证券营业部机房照片1.jpg new file mode 100644 index 0000000..5297d77 Binary files /dev/null and b/fzjgact/media/equipment_room_images/东兴证券福州长乐郑和中路证券营业部机房照片1.jpg differ diff --git a/fzjgact/media/equipment_room_images/东兴证券福州长乐郑和中路证券营业部机房照片2.jpg b/fzjgact/media/equipment_room_images/东兴证券福州长乐郑和中路证券营业部机房照片2.jpg new file mode 100644 index 0000000..ef47958 Binary files /dev/null and b/fzjgact/media/equipment_room_images/东兴证券福州长乐郑和中路证券营业部机房照片2.jpg differ diff --git a/fzjgact/media/equipment_room_images/二层交换机.jpg b/fzjgact/media/equipment_room_images/二层交换机.jpg new file mode 100644 index 0000000..68cdedb Binary files /dev/null and b/fzjgact/media/equipment_room_images/二层交换机.jpg differ diff --git a/fzjgact/media/equipment_room_images/二层交换机监控交换机.jpg b/fzjgact/media/equipment_room_images/二层交换机监控交换机.jpg new file mode 100644 index 0000000..939561d Binary files /dev/null and b/fzjgact/media/equipment_room_images/二层交换机监控交换机.jpg differ diff --git a/fzjgact/media/equipment_room_images/佛山汾江南路设备间全景.jpg b/fzjgact/media/equipment_room_images/佛山汾江南路设备间全景.jpg new file mode 100644 index 0000000..6dca452 Binary files /dev/null and b/fzjgact/media/equipment_room_images/佛山汾江南路设备间全景.jpg differ diff --git a/fzjgact/media/equipment_room_images/佛山汾江南路设备间接线示意图.jpg b/fzjgact/media/equipment_room_images/佛山汾江南路设备间接线示意图.jpg new file mode 100644 index 0000000..c929d8b Binary files /dev/null and b/fzjgact/media/equipment_room_images/佛山汾江南路设备间接线示意图.jpg differ diff --git a/fzjgact/media/equipment_room_images/全景.jpg b/fzjgact/media/equipment_room_images/全景.jpg new file mode 100644 index 0000000..524aac5 Binary files /dev/null and b/fzjgact/media/equipment_room_images/全景.jpg differ diff --git a/fzjgact/media/equipment_room_images/全景1.jpg b/fzjgact/media/equipment_room_images/全景1.jpg new file mode 100644 index 0000000..3453197 Binary files /dev/null and b/fzjgact/media/equipment_room_images/全景1.jpg differ diff --git a/fzjgact/media/equipment_room_images/公司机柜上.jpg b/fzjgact/media/equipment_room_images/公司机柜上.jpg new file mode 100644 index 0000000..0fcc834 Binary files /dev/null and b/fzjgact/media/equipment_room_images/公司机柜上.jpg differ diff --git a/fzjgact/media/equipment_room_images/公司机柜下.jpg b/fzjgact/media/equipment_room_images/公司机柜下.jpg new file mode 100644 index 0000000..b7b8ec4 Binary files /dev/null and b/fzjgact/media/equipment_room_images/公司机柜下.jpg differ diff --git a/fzjgact/media/equipment_room_images/墙壁.jpg b/fzjgact/media/equipment_room_images/墙壁.jpg new file mode 100644 index 0000000..75d274b Binary files /dev/null and b/fzjgact/media/equipment_room_images/墙壁.jpg differ diff --git a/fzjgact/media/equipment_room_images/天花板.jpg b/fzjgact/media/equipment_room_images/天花板.jpg new file mode 100644 index 0000000..d342575 Binary files /dev/null and b/fzjgact/media/equipment_room_images/天花板.jpg differ diff --git a/fzjgact/media/equipment_room_images/布线.jpg b/fzjgact/media/equipment_room_images/布线.jpg new file mode 100644 index 0000000..a4c918c Binary files /dev/null and b/fzjgact/media/equipment_room_images/布线.jpg differ diff --git a/fzjgact/media/equipment_room_images/广州体育西路营业部机房图1.jpg b/fzjgact/media/equipment_room_images/广州体育西路营业部机房图1.jpg new file mode 100644 index 0000000..a49c4d5 Binary files /dev/null and b/fzjgact/media/equipment_room_images/广州体育西路营业部机房图1.jpg differ diff --git a/fzjgact/media/equipment_room_images/广州体育西路营业部机房图2.jpg b/fzjgact/media/equipment_room_images/广州体育西路营业部机房图2.jpg new file mode 100644 index 0000000..9ce2c7e Binary files /dev/null and b/fzjgact/media/equipment_room_images/广州体育西路营业部机房图2.jpg differ diff --git a/fzjgact/media/equipment_room_images/强电配电箱1.jpg b/fzjgact/media/equipment_room_images/强电配电箱1.jpg new file mode 100644 index 0000000..7a2f1f2 Binary files /dev/null and b/fzjgact/media/equipment_room_images/强电配电箱1.jpg differ diff --git a/fzjgact/media/equipment_room_images/强电配电箱2.jpg b/fzjgact/media/equipment_room_images/强电配电箱2.jpg new file mode 100644 index 0000000..15ab16e Binary files /dev/null and b/fzjgact/media/equipment_room_images/强电配电箱2.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240429154307.jpg b/fzjgact/media/equipment_room_images/微信图片_20240429154307.jpg new file mode 100644 index 0000000..86accfa Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240429154307.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240429154311.jpg b/fzjgact/media/equipment_room_images/微信图片_20240429154311.jpg new file mode 100644 index 0000000..db0feb2 Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240429154311.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240429154315.jpg b/fzjgact/media/equipment_room_images/微信图片_20240429154315.jpg new file mode 100644 index 0000000..b0a4018 Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240429154315.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240429154319.jpg b/fzjgact/media/equipment_room_images/微信图片_20240429154319.jpg new file mode 100644 index 0000000..b3d704b Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240429154319.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240430162240.jpg b/fzjgact/media/equipment_room_images/微信图片_20240430162240.jpg new file mode 100644 index 0000000..2885eeb Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240430162240.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240430162256.jpg b/fzjgact/media/equipment_room_images/微信图片_20240430162256.jpg new file mode 100644 index 0000000..0b9f274 Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240430162256.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240430162303.jpg b/fzjgact/media/equipment_room_images/微信图片_20240430162303.jpg new file mode 100644 index 0000000..f121a8a Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240430162303.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240430162303_mCwUzjp.jpg b/fzjgact/media/equipment_room_images/微信图片_20240430162303_mCwUzjp.jpg new file mode 100644 index 0000000..f121a8a Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240430162303_mCwUzjp.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240430162317.jpg b/fzjgact/media/equipment_room_images/微信图片_20240430162317.jpg new file mode 100644 index 0000000..1a038d0 Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240430162317.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240510152948.jpg b/fzjgact/media/equipment_room_images/微信图片_20240510152948.jpg new file mode 100644 index 0000000..c91b4f6 Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240510152948.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240510152949.jpg b/fzjgact/media/equipment_room_images/微信图片_20240510152949.jpg new file mode 100644 index 0000000..78e6c48 Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240510152949.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240510152950.jpg b/fzjgact/media/equipment_room_images/微信图片_20240510152950.jpg new file mode 100644 index 0000000..5e120e4 Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240510152950.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_20240510152951.jpg b/fzjgact/media/equipment_room_images/微信图片_20240510152951.jpg new file mode 100644 index 0000000..2af34a3 Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_20240510152951.jpg differ diff --git a/fzjgact/media/equipment_room_images/微信图片_202405101529511.jpg b/fzjgact/media/equipment_room_images/微信图片_202405101529511.jpg new file mode 100644 index 0000000..d694ddd Binary files /dev/null and b/fzjgact/media/equipment_room_images/微信图片_202405101529511.jpg differ diff --git a/fzjgact/media/equipment_room_images/接线示意图-济南.jpg b/fzjgact/media/equipment_room_images/接线示意图-济南.jpg new file mode 100644 index 0000000..3a90af4 Binary files /dev/null and b/fzjgact/media/equipment_room_images/接线示意图-济南.jpg differ diff --git a/fzjgact/media/equipment_room_images/接线示意图.jpg b/fzjgact/media/equipment_room_images/接线示意图.jpg new file mode 100644 index 0000000..79c8abb Binary files /dev/null and b/fzjgact/media/equipment_room_images/接线示意图.jpg differ diff --git a/fzjgact/media/equipment_room_images/接线示意图_pjc6JYm.jpg b/fzjgact/media/equipment_room_images/接线示意图_pjc6JYm.jpg new file mode 100644 index 0000000..6757405 Binary files /dev/null and b/fzjgact/media/equipment_room_images/接线示意图_pjc6JYm.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房.jpg b/fzjgact/media/equipment_room_images/机房.jpg new file mode 100644 index 0000000..4879549 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房1.jpg b/fzjgact/media/equipment_room_images/机房1.jpg new file mode 100644 index 0000000..6d19157 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房1.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房1_7OFMAft.jpg b/fzjgact/media/equipment_room_images/机房1_7OFMAft.jpg new file mode 100644 index 0000000..6d19157 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房1_7OFMAft.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房1_GKXXac8.jpg b/fzjgact/media/equipment_room_images/机房1_GKXXac8.jpg new file mode 100644 index 0000000..6d19157 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房1_GKXXac8.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房1_IK7iZid.jpg b/fzjgact/media/equipment_room_images/机房1_IK7iZid.jpg new file mode 100644 index 0000000..6d19157 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房1_IK7iZid.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房1_QOr2eaO.jpg b/fzjgact/media/equipment_room_images/机房1_QOr2eaO.jpg new file mode 100644 index 0000000..6d19157 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房1_QOr2eaO.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房1_Tal0Tae.jpg b/fzjgact/media/equipment_room_images/机房1_Tal0Tae.jpg new file mode 100644 index 0000000..3d11745 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房1_Tal0Tae.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房1_XnossLL.jpg b/fzjgact/media/equipment_room_images/机房1_XnossLL.jpg new file mode 100644 index 0000000..6d19157 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房1_XnossLL.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房2.jpg b/fzjgact/media/equipment_room_images/机房2.jpg new file mode 100644 index 0000000..4d26232 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房2.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房3.jpg b/fzjgact/media/equipment_room_images/机房3.jpg new file mode 100644 index 0000000..f11ed04 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房3.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房4.jpg b/fzjgact/media/equipment_room_images/机房4.jpg new file mode 100644 index 0000000..bdb0b0b Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房4.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房交换机1.jpg b/fzjgact/media/equipment_room_images/机房交换机1.jpg new file mode 100644 index 0000000..553ca40 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房交换机1.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房交换机2.jpg b/fzjgact/media/equipment_room_images/机房交换机2.jpg new file mode 100644 index 0000000..bd6b02f Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房交换机2.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房全景图1.jpg b/fzjgact/media/equipment_room_images/机房全景图1.jpg new file mode 100644 index 0000000..a4af03d Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房全景图1.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房全景图2.jpg b/fzjgact/media/equipment_room_images/机房全景图2.jpg new file mode 100644 index 0000000..eef9d7c Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房全景图2.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房办公区1.jpg b/fzjgact/media/equipment_room_images/机房办公区1.jpg new file mode 100644 index 0000000..5e52e40 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房办公区1.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房办公区2.jpg b/fzjgact/media/equipment_room_images/机房办公区2.jpg new file mode 100644 index 0000000..cb44b06 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房办公区2.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房天花板图.jpg b/fzjgact/media/equipment_room_images/机房天花板图.jpg new file mode 100644 index 0000000..641b265 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房天花板图.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房深信服防火墙2台互备.jpg b/fzjgact/media/equipment_room_images/机房深信服防火墙2台互备.jpg new file mode 100644 index 0000000..b6204c1 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房深信服防火墙2台互备.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房照片1.JPG b/fzjgact/media/equipment_room_images/机房照片1.JPG new file mode 100644 index 0000000..5a12d40 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片1.JPG differ diff --git a/fzjgact/media/equipment_room_images/机房照片1_Wwy4mG7.jpg b/fzjgact/media/equipment_room_images/机房照片1_Wwy4mG7.jpg new file mode 100644 index 0000000..544cacb Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片1_Wwy4mG7.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房照片1_uZytLd2.jpg b/fzjgact/media/equipment_room_images/机房照片1_uZytLd2.jpg new file mode 100644 index 0000000..19b39e3 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片1_uZytLd2.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房照片2.JPG b/fzjgact/media/equipment_room_images/机房照片2.JPG new file mode 100644 index 0000000..5953820 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片2.JPG differ diff --git a/fzjgact/media/equipment_room_images/机房照片2_8o9mgix.jpg b/fzjgact/media/equipment_room_images/机房照片2_8o9mgix.jpg new file mode 100644 index 0000000..dd81d86 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片2_8o9mgix.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房照片2_vgWCMEi.jpg b/fzjgact/media/equipment_room_images/机房照片2_vgWCMEi.jpg new file mode 100644 index 0000000..73b79af Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片2_vgWCMEi.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房照片3.JPG b/fzjgact/media/equipment_room_images/机房照片3.JPG new file mode 100644 index 0000000..84d85cf Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片3.JPG differ diff --git a/fzjgact/media/equipment_room_images/机房照片3_8EblJT3.jpg b/fzjgact/media/equipment_room_images/机房照片3_8EblJT3.jpg new file mode 100644 index 0000000..dc32e2c Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片3_8EblJT3.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房照片3_HalbMrH.jpg b/fzjgact/media/equipment_room_images/机房照片3_HalbMrH.jpg new file mode 100644 index 0000000..77b8833 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片3_HalbMrH.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房照片4.jpg b/fzjgact/media/equipment_room_images/机房照片4.jpg new file mode 100644 index 0000000..ea867ec Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片4.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房照片5.jpg b/fzjgact/media/equipment_room_images/机房照片5.jpg new file mode 100644 index 0000000..f748867 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房照片5.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房背面图.jpg b/fzjgact/media/equipment_room_images/机房背面图.jpg new file mode 100644 index 0000000..508d739 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房背面图.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房设备间1.jpg b/fzjgact/media/equipment_room_images/机房设备间1.jpg new file mode 100644 index 0000000..1a8e0e0 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房设备间1.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房设备间2.jpg b/fzjgact/media/equipment_room_images/机房设备间2.jpg new file mode 100644 index 0000000..6c2c150 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房设备间2.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房设备间全景-济南.jpg b/fzjgact/media/equipment_room_images/机房设备间全景-济南.jpg new file mode 100644 index 0000000..46147c4 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房设备间全景-济南.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房设备间全景1.jpg b/fzjgact/media/equipment_room_images/机房设备间全景1.jpg new file mode 100644 index 0000000..9dc20c5 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房设备间全景1.jpg differ diff --git a/fzjgact/media/equipment_room_images/机房设备间全景2.jpg b/fzjgact/media/equipment_room_images/机房设备间全景2.jpg new file mode 100644 index 0000000..7b544b5 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机房设备间全景2.jpg differ diff --git a/fzjgact/media/equipment_room_images/机架.jpg b/fzjgact/media/equipment_room_images/机架.jpg new file mode 100644 index 0000000..f7b7a5a Binary files /dev/null and b/fzjgact/media/equipment_room_images/机架.jpg differ diff --git a/fzjgact/media/equipment_room_images/机柜.jpg b/fzjgact/media/equipment_room_images/机柜.jpg new file mode 100644 index 0000000..e0fd9d1 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机柜.jpg differ diff --git a/fzjgact/media/equipment_room_images/机柜内部图.jpg b/fzjgact/media/equipment_room_images/机柜内部图.jpg new file mode 100644 index 0000000..d326936 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机柜内部图.jpg differ diff --git a/fzjgact/media/equipment_room_images/机柜图片.jpg b/fzjgact/media/equipment_room_images/机柜图片.jpg new file mode 100644 index 0000000..109c87f Binary files /dev/null and b/fzjgact/media/equipment_room_images/机柜图片.jpg differ diff --git a/fzjgact/media/equipment_room_images/机柜图片_amPPVM0.jpg b/fzjgact/media/equipment_room_images/机柜图片_amPPVM0.jpg new file mode 100644 index 0000000..109c87f Binary files /dev/null and b/fzjgact/media/equipment_room_images/机柜图片_amPPVM0.jpg differ diff --git a/fzjgact/media/equipment_room_images/机柜图片_lnvb8l6.jpg b/fzjgact/media/equipment_room_images/机柜图片_lnvb8l6.jpg new file mode 100644 index 0000000..109c87f Binary files /dev/null and b/fzjgact/media/equipment_room_images/机柜图片_lnvb8l6.jpg differ diff --git a/fzjgact/media/equipment_room_images/机柜接线图.png b/fzjgact/media/equipment_room_images/机柜接线图.png new file mode 100644 index 0000000..819cea7 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机柜接线图.png differ diff --git a/fzjgact/media/equipment_room_images/机柜整体图.jpg b/fzjgact/media/equipment_room_images/机柜整体图.jpg new file mode 100644 index 0000000..2661265 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机柜整体图.jpg differ diff --git a/fzjgact/media/equipment_room_images/机柜正面.jpg b/fzjgact/media/equipment_room_images/机柜正面.jpg new file mode 100644 index 0000000..4a5eb73 Binary files /dev/null and b/fzjgact/media/equipment_room_images/机柜正面.jpg differ diff --git a/fzjgact/media/equipment_room_images/柜图1.jpg b/fzjgact/media/equipment_room_images/柜图1.jpg new file mode 100644 index 0000000..b0e53fc Binary files /dev/null and b/fzjgact/media/equipment_room_images/柜图1.jpg differ diff --git a/fzjgact/media/equipment_room_images/柜图2.jpg b/fzjgact/media/equipment_room_images/柜图2.jpg new file mode 100644 index 0000000..cefff5d Binary files /dev/null and b/fzjgact/media/equipment_room_images/柜图2.jpg differ diff --git a/fzjgact/media/equipment_room_images/永春机柜图.jpg b/fzjgact/media/equipment_room_images/永春机柜图.jpg new file mode 100644 index 0000000..bd49dda Binary files /dev/null and b/fzjgact/media/equipment_room_images/永春机柜图.jpg differ diff --git a/fzjgact/media/equipment_room_images/永春机柜图_2.jpg b/fzjgact/media/equipment_room_images/永春机柜图_2.jpg new file mode 100644 index 0000000..c43c44a Binary files /dev/null and b/fzjgact/media/equipment_room_images/永春机柜图_2.jpg differ diff --git a/fzjgact/media/equipment_room_images/电脑设备间照片1.jpg b/fzjgact/media/equipment_room_images/电脑设备间照片1.jpg new file mode 100644 index 0000000..e088576 Binary files /dev/null and b/fzjgact/media/equipment_room_images/电脑设备间照片1.jpg differ diff --git a/fzjgact/media/equipment_room_images/电脑设备间照片2.jpg b/fzjgact/media/equipment_room_images/电脑设备间照片2.jpg new file mode 100644 index 0000000..0ea5e00 Binary files /dev/null and b/fzjgact/media/equipment_room_images/电脑设备间照片2.jpg differ diff --git a/fzjgact/media/equipment_room_images/监控老恒生设备.jpg b/fzjgact/media/equipment_room_images/监控老恒生设备.jpg new file mode 100644 index 0000000..83bd4cf Binary files /dev/null and b/fzjgact/media/equipment_room_images/监控老恒生设备.jpg differ diff --git a/fzjgact/media/equipment_room_images/石家庄营业部设备间_1.jpg b/fzjgact/media/equipment_room_images/石家庄营业部设备间_1.jpg new file mode 100644 index 0000000..515735b Binary files /dev/null and b/fzjgact/media/equipment_room_images/石家庄营业部设备间_1.jpg differ diff --git a/fzjgact/media/equipment_room_images/石家庄营业部设备间_2.jpg b/fzjgact/media/equipment_room_images/石家庄营业部设备间_2.jpg new file mode 100644 index 0000000..210b170 Binary files /dev/null and b/fzjgact/media/equipment_room_images/石家庄营业部设备间_2.jpg differ diff --git a/fzjgact/media/equipment_room_images/石家庄营业部设备间_3.jpg b/fzjgact/media/equipment_room_images/石家庄营业部设备间_3.jpg new file mode 100644 index 0000000..171456e Binary files /dev/null and b/fzjgact/media/equipment_room_images/石家庄营业部设备间_3.jpg differ diff --git a/fzjgact/media/equipment_room_images/石家庄营业部设备间_4.jpg b/fzjgact/media/equipment_room_images/石家庄营业部设备间_4.jpg new file mode 100644 index 0000000..4a9ac62 Binary files /dev/null and b/fzjgact/media/equipment_room_images/石家庄营业部设备间_4.jpg differ diff --git a/fzjgact/media/equipment_room_images/石家庄营业部设备间_5.jpg b/fzjgact/media/equipment_room_images/石家庄营业部设备间_5.jpg new file mode 100644 index 0000000..08e0273 Binary files /dev/null and b/fzjgact/media/equipment_room_images/石家庄营业部设备间_5.jpg differ diff --git a/fzjgact/media/equipment_room_images/空调.jpg b/fzjgact/media/equipment_room_images/空调.jpg new file mode 100644 index 0000000..2ec11b7 Binary files /dev/null and b/fzjgact/media/equipment_room_images/空调.jpg differ diff --git a/fzjgact/media/equipment_room_images/线路图.jpg b/fzjgact/media/equipment_room_images/线路图.jpg new file mode 100644 index 0000000..6816f52 Binary files /dev/null and b/fzjgact/media/equipment_room_images/线路图.jpg differ diff --git a/fzjgact/media/equipment_room_images/联通机柜.jpg b/fzjgact/media/equipment_room_images/联通机柜.jpg new file mode 100644 index 0000000..eda5e9b Binary files /dev/null and b/fzjgact/media/equipment_room_images/联通机柜.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备柜.jpg b/fzjgact/media/equipment_room_images/设备柜.jpg new file mode 100644 index 0000000..315c9db Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备柜.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间-全局.jpg b/fzjgact/media/equipment_room_images/设备间-全局.jpg new file mode 100644 index 0000000..0318c4a Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间-全局.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间-机柜1.jpg b/fzjgact/media/equipment_room_images/设备间-机柜1.jpg new file mode 100644 index 0000000..1c08254 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间-机柜1.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间-机柜2.jpg b/fzjgact/media/equipment_room_images/设备间-机柜2.jpg new file mode 100644 index 0000000..0efca5e Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间-机柜2.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间-机柜3.jpg b/fzjgact/media/equipment_room_images/设备间-机柜3.jpg new file mode 100644 index 0000000..a248597 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间-机柜3.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间-机柜全局.jpg b/fzjgact/media/equipment_room_images/设备间-机柜全局.jpg new file mode 100644 index 0000000..d9bd7d9 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间-机柜全局.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间-灭火器.jpg b/fzjgact/media/equipment_room_images/设备间-灭火器.jpg new file mode 100644 index 0000000..9be32c2 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间-灭火器.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间-空调1.jpg b/fzjgact/media/equipment_room_images/设备间-空调1.jpg new file mode 100644 index 0000000..c0fb085 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间-空调1.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间-空调2.jpg b/fzjgact/media/equipment_room_images/设备间-空调2.jpg new file mode 100644 index 0000000..a03839b Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间-空调2.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间-配电箱.jpg b/fzjgact/media/equipment_room_images/设备间-配电箱.jpg new file mode 100644 index 0000000..ec5e211 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间-配电箱.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间.jpg b/fzjgact/media/equipment_room_images/设备间.jpg new file mode 100644 index 0000000..0969928 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间1.jpg b/fzjgact/media/equipment_room_images/设备间1.jpg new file mode 100644 index 0000000..e3bde35 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间1.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间1_S6jJDip.jpg b/fzjgact/media/equipment_room_images/设备间1_S6jJDip.jpg new file mode 100644 index 0000000..d8ccc14 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间1_S6jJDip.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间2.jpg b/fzjgact/media/equipment_room_images/设备间2.jpg new file mode 100644 index 0000000..9067f22 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间2.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间3.jpg b/fzjgact/media/equipment_room_images/设备间3.jpg new file mode 100644 index 0000000..c298400 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间3.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间4.jpg b/fzjgact/media/equipment_room_images/设备间4.jpg new file mode 100644 index 0000000..38dd6bf Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间4.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间5.jpg b/fzjgact/media/equipment_room_images/设备间5.jpg new file mode 100644 index 0000000..5e44168 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间5.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间_81dmbDS.jpg b/fzjgact/media/equipment_room_images/设备间_81dmbDS.jpg new file mode 100644 index 0000000..65e25e5 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间_81dmbDS.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间_EkVgmVw.jpg b/fzjgact/media/equipment_room_images/设备间_EkVgmVw.jpg new file mode 100644 index 0000000..251eb7b Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间_EkVgmVw.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间全景图.jpg b/fzjgact/media/equipment_room_images/设备间全景图.jpg new file mode 100644 index 0000000..6ed2a53 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间全景图.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间全景图_TkJjiBu.jpg b/fzjgact/media/equipment_room_images/设备间全景图_TkJjiBu.jpg new file mode 100644 index 0000000..b6ab0cb Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间全景图_TkJjiBu.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间全景图_UWail8r.jpg b/fzjgact/media/equipment_room_images/设备间全景图_UWail8r.jpg new file mode 100644 index 0000000..c22b6e5 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间全景图_UWail8r.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间图片.jpg b/fzjgact/media/equipment_room_images/设备间图片.jpg new file mode 100644 index 0000000..da113ba Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间图片.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间接线示意图.jpg b/fzjgact/media/equipment_room_images/设备间接线示意图.jpg new file mode 100644 index 0000000..550f511 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间接线示意图.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间接线示意图一.jpg b/fzjgact/media/equipment_room_images/设备间接线示意图一.jpg new file mode 100644 index 0000000..691c0c5 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间接线示意图一.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间接线示意图二.jpg b/fzjgact/media/equipment_room_images/设备间接线示意图二.jpg new file mode 100644 index 0000000..dd56e62 Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间接线示意图二.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间照片.jpg b/fzjgact/media/equipment_room_images/设备间照片.jpg new file mode 100644 index 0000000..52e656d Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间照片.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间照片1.jpg b/fzjgact/media/equipment_room_images/设备间照片1.jpg new file mode 100644 index 0000000..12b67de Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间照片1.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间照片2.jpg b/fzjgact/media/equipment_room_images/设备间照片2.jpg new file mode 100644 index 0000000..adcb9db Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间照片2.jpg differ diff --git a/fzjgact/media/equipment_room_images/设备间照片3.jpg b/fzjgact/media/equipment_room_images/设备间照片3.jpg new file mode 100644 index 0000000..91d77ae Binary files /dev/null and b/fzjgact/media/equipment_room_images/设备间照片3.jpg differ diff --git a/fzjgact/media/equipment_room_images/货架1.jpg b/fzjgact/media/equipment_room_images/货架1.jpg new file mode 100644 index 0000000..5904436 Binary files /dev/null and b/fzjgact/media/equipment_room_images/货架1.jpg differ diff --git a/fzjgact/media/equipment_room_images/货架2.jpg b/fzjgact/media/equipment_room_images/货架2.jpg new file mode 100644 index 0000000..f314e28 Binary files /dev/null and b/fzjgact/media/equipment_room_images/货架2.jpg differ diff --git a/fzjgact/media/equipment_room_images/配电柜.jpg b/fzjgact/media/equipment_room_images/配电柜.jpg new file mode 100644 index 0000000..7670c29 Binary files /dev/null and b/fzjgact/media/equipment_room_images/配电柜.jpg differ diff --git a/fzjgact/media/equipment_room_images/防火墙和主干交换机.jpg b/fzjgact/media/equipment_room_images/防火墙和主干交换机.jpg new file mode 100644 index 0000000..b29e130 Binary files /dev/null and b/fzjgact/media/equipment_room_images/防火墙和主干交换机.jpg differ diff --git a/fzjgact/media/equipment_room_images/龙海营业部设备间照片_1.jpg b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_1.jpg new file mode 100644 index 0000000..c602abd Binary files /dev/null and b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_1.jpg differ diff --git a/fzjgact/media/equipment_room_images/龙海营业部设备间照片_2.jpg b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_2.jpg new file mode 100644 index 0000000..a7b675e Binary files /dev/null and b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_2.jpg differ diff --git a/fzjgact/media/equipment_room_images/龙海营业部设备间照片_3.jpg b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_3.jpg new file mode 100644 index 0000000..9a319cf Binary files /dev/null and b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_3.jpg differ diff --git a/fzjgact/media/equipment_room_images/龙海营业部设备间照片_4.jpg b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_4.jpg new file mode 100644 index 0000000..883b08d Binary files /dev/null and b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_4.jpg differ diff --git a/fzjgact/media/equipment_room_images/龙海营业部设备间照片_5.jpg b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_5.jpg new file mode 100644 index 0000000..14b0374 Binary files /dev/null and b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_5.jpg differ diff --git a/fzjgact/media/equipment_room_images/龙海营业部设备间照片_6.jpg b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_6.jpg new file mode 100644 index 0000000..da4d0ce Binary files /dev/null and b/fzjgact/media/equipment_room_images/龙海营业部设备间照片_6.jpg differ diff --git a/fzjgact/result.txt b/fzjgact/result.txt new file mode 100644 index 0000000..90db39e --- /dev/null +++ b/fzjgact/result.txt @@ -0,0 +1,2 @@ +日期时间:2024-08-28 15:10:29 +统计的总行数:640 \ No newline at end of file diff --git a/fzjgact/tailwind.config.js b/fzjgact/tailwind.config.js new file mode 100644 index 0000000..45b71ca --- /dev/null +++ b/fzjgact/tailwind.config.js @@ -0,0 +1,13 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + 'huodong/**/*.html', + 'huodong/**/*.css' +], + theme: { + extend: {}, + }, + prefix: '', + plugins: [], +} + diff --git a/fzjgact/tailwindcss-windows-x64.exe b/fzjgact/tailwindcss-windows-x64.exe new file mode 100644 index 0000000..cec5bd1 Binary files /dev/null and b/fzjgact/tailwindcss-windows-x64.exe differ diff --git a/fzjgact/tailwind启动.bat b/fzjgact/tailwind启动.bat new file mode 100644 index 0000000..d04904f --- /dev/null +++ b/fzjgact/tailwind启动.bat @@ -0,0 +1 @@ +tailwindcss-windows-x64.exe --input huodong/static/huodong/input.css --output huodong/static/huodong/output.css --watch \ No newline at end of file diff --git a/fzjgact/启动分支机构项目.bat b/fzjgact/启动分支机构项目.bat new file mode 100644 index 0000000..0efca0c --- /dev/null +++ b/fzjgact/启动分支机构项目.bat @@ -0,0 +1,2 @@ +python manage.py runserver 0.0.0.0:9000 + diff --git a/fzjgact/统计python行数.py b/fzjgact/统计python行数.py new file mode 100644 index 0000000..3998be3 --- /dev/null +++ b/fzjgact/统计python行数.py @@ -0,0 +1,28 @@ +from pathlib import Path +import datetime + +def count_lines_of_code(directory): + total_lines = 0 + directory_path = Path(directory) + for file_path in directory_path.rglob('*.py'): + with file_path.open('r', encoding='utf-8') as f: + lines = f.readlines() + total_lines += len(lines) + return total_lines + +if __name__ == '__main__': + directory = input('请输入要统计的Python代码所在的目录:') + total_lines = count_lines_of_code(directory) + + # 获取当前日期时间 + now = datetime.datetime.now() + date_time_str = now.strftime('%Y-%m-%d %H:%M:%S') + + # 将日期时间和总行数格式化为字符串 + result_str = f'\r\n日期时间:{date_time_str}\n统计的总行数:{total_lines}' + + # 将结果写入result.txt文件 + with open('result.txt', 'a', encoding='utf-8') as result_file: + result_file.write(result_str) + + print('统计结果已写入result.txt文件。')