From acf4ef12eceaca21cf7a2f3072b19acb406638d2 Mon Sep 17 00:00:00 2001 From: xiaji Date: Wed, 3 Dec 2025 17:17:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A2=84=E7=AE=97=E8=A1=A8?= =?UTF-8?q?=E7=9A=84=E6=98=BE=E7=A4=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fzjgact/db.sqlite3 | Bin 438272 -> 471040 bytes .../huodong/__pycache__/admin.cpython-311.pyc | Bin 12160 -> 17149 bytes .../__pycache__/models.cpython-311.pyc | Bin 12246 -> 22295 bytes .../huodong/__pycache__/urls.cpython-311.pyc | Bin 1969 -> 2117 bytes .../huodong/__pycache__/views.cpython-311.pyc | Bin 20408 -> 28189 bytes fzjgact/huodong/admin.py | 481 ++++++++++------- ...et_equipmentbudget_infrastructurebudget.py | 64 +++ ...template_templateequipmentitem_and_more.py | 60 +++ ...0032_remove_budget_activity_budget_name.py | 23 + ...udget_infrastructurebudget.cpython-311.pyc | Bin 0 -> 4195 bytes ...lateequipmentitem_and_more.cpython-311.pyc | Bin 0 -> 3643 bytes ...udget_activity_budget_name.cpython-311.pyc | Bin 0 -> 1050 bytes fzjgact/huodong/models.py | 509 +++++++++++------- fzjgact/huodong/templates/branch_detail.html | 119 ++++ fzjgact/huodong/urls.py | 43 +- fzjgact/huodong/views.py | 157 +++++- 16 files changed, 1058 insertions(+), 398 deletions(-) create mode 100644 fzjgact/huodong/migrations/0030_budget_equipmentbudget_infrastructurebudget.py create mode 100644 fzjgact/huodong/migrations/0031_budgettemplate_templateequipmentitem_and_more.py create mode 100644 fzjgact/huodong/migrations/0032_remove_budget_activity_budget_name.py create mode 100644 fzjgact/huodong/migrations/__pycache__/0030_budget_equipmentbudget_infrastructurebudget.cpython-311.pyc create mode 100644 fzjgact/huodong/migrations/__pycache__/0031_budgettemplate_templateequipmentitem_and_more.cpython-311.pyc create mode 100644 fzjgact/huodong/migrations/__pycache__/0032_remove_budget_activity_budget_name.cpython-311.pyc diff --git a/fzjgact/db.sqlite3 b/fzjgact/db.sqlite3 index aef337ef7bc94f36be1e46d45191acc6a1f12fc5..0df05bce2e550cd088f4653d27cce4907b578ab1 100644 GIT binary patch delta 7460 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 x*5Phsg&Q-7m{<+Atri#ix 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 K*OBnwOaB3x7Oar~ diff --git a/fzjgact/huodong/__pycache__/models.cpython-311.pyc b/fzjgact/huodong/__pycache__/models.cpython-311.pyc index 5d5f33f7234c6ae5b133988852b3a14e356b8711..3b2962fca4503e77fb1505cf83ca74f1ac27f0d3 100644 GIT binary patch literal 22295 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 delta 2539 zcma)7drXs86z77JM<4r2q0mBGp3?Ff%6Q07r$ZM6D+)Rt8?}Q@yYVo$t(zShUk{LvcE&-ipW?7c(5BJAj-IkceufmcgCd-n|f3|z>S4Mesv1xz(zH`q# z_dI^*+`%#OolP~ORK|v}&-PW<_Woh$S0#nJ$rUptvgU-kFpJiED7-M7c;MQyb0!T_ zqbdd)Jqm{Yq03_5u)nA8!QnHOaH{coBEKSPBPyjZ@GaZyaNB7rY>6@_ajBU}trj)S zK$T2{Ea;6|PIPcRs!^YW0s{i-(QE|Cn71H0mk^`(g_s&b(qJUEjFiB=*i>^V)3JpA zDPwdXC7_Q1>Z_6$&~xvBy9<{C$_EZ@o>c zB?(qbJbp$z-8KDj_x)RAv?fS%;QY*cU39Y~i9^lq>-VQl_>Xn@PhFlF9Gm%Qh+3Ig zs`W`wg#6lzj-h&i-oId zn=xdbw=-QU+}6dzLv!TDy1UWI(pMsf#Ho3yN81qy>k*I~^jU;T1YQjt9FNN@$i?@^ zs74j)Re7i55{Q)jDwh4v;fwf{q!|8+A4%qhLl9{)p^_7+1d6rUJ3|J!mz~jo=d45E zHRh3xs)9*{YfDB36WStENIG%D4IoQAFZtiV{Qp+}60_D3(@gEJJKOfSo}@PRUQg`| zVMT%!eos;)H{*d0gvDiy*RAG(mBLY-E_9c;;D*keH5U+dqPYeA)Q+-th|!;x9BlVq z(*I3l#VBrsPg0D+ZhYK^phhT%A5&76&k`?ag_Be~c4qqEO@D9i^sRBa6_O2^Dcls_ z%8fLl5u9WeLN(A}=oT>4Mt|=6n5=)k1>Z^G8YY50$pWM|%9ga4e`@lX&fVJ?JNl#i}$h16k?LBC~QV$eh)q_`z7VWOobm@->-ZSub@l9`-!KPJ~?ukI~K; zHtm3{%&#S~b$~5K=M}PkCY?M95me$Gsv$*aIRnnC>9Nnm^GBrNN4GF(eULanH(^#; z>^Uh;P5K9~&kRnm#J-G{(3~_zPfqwxjQ_XzrnCqVg-LKQyH<&0v_#A@@m{t`y_kf8 zxjI0?0drpH1fOE2h6B@6=$z|AOI&bLnUYUczhT?vD(ku$Tm7!u4RuQo8g!J?QR#Nj zR%e^NC76)7+JbNx;RwRKp%gcJqvJ{+2k5u_D%GKn-)RFm8p6ivaPBJkT)URTZ@G1G z7uW`tmAN}d16%TTol`)Dw z@*4#0`4p9oCTFX?Wuw#4((H?LHMLWz7kyDp?X9h>5oiwV%TLtvs22>mvuNuqoXfwX z;AOyft3?GD>I!T4h0l-WvzpIC-npEtJX3u8e3Or&D_Yx|JuQwk^eQt(*w6JP@vg1E PO;llWQt=RhUnc(oMgk}F diff --git a/fzjgact/huodong/__pycache__/urls.cpython-311.pyc b/fzjgact/huodong/__pycache__/urls.cpython-311.pyc index 80f766f95c1ec68ed590b2d9a926193bf302f270..4073f153c84948a0ff295f1ceb6eb996a95198e3 100644 GIT binary patch delta 254 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 delta 4031 zcma)9eQX>@72iGI?VWue{T$W zXB1Ve?tVA(=FOX#H^2AZ-s)ZcogeX`w}Qa}4xTT3xKI1i=(SMTwZ>m-?^xkE#ih7) zpOG)-8wFy4;TQcN;}nk`FoI&x2#F!4Bj_%pP%LC)UcJaD7K>Tir!n7S zSjO4~dbv>{Rv49Hr4bgxAaf~xuu&yevGIUjZPbWz4eJE;TBA;^W9^V$FV@2b3iSq~ zQEX(gBE89oh!NH<)|-tMvBijrQKMCCHQK~BCNI(3jhGlSI>e3*JA1@EYR$r4I>pzl zbh@|+PAR*}Ddj4^5Jy+w^OHP|dmFyaBkp5b6`)o5Ia*yzD-2pypQE*3slLjI-AWB$ z&ncxAehw&gfW1mRV4u>532)1x}TbR{!OC`21O%#pT;|kaY>glU0b&KVm#AM}RLvF3&fnO8 zrjP*`vkN5I(v~z!Q%!OR1-=czCCA>DDcdWjQJGkpyprfuYOTI&tt7lwyLYX+ecdk<3hNxem5EP7T%hE&wmUWZ zZdJbTANasOaK}Bs2q7Z}Hy=C}yP(DbxS+1wql#bW7Z+zk*}`m5wj^7cEmO*`2k7q` zhXmW5k_?r4nm&shgjr`}F6ZDy;JAdP8EPV-nW;rxkLAH7HAY%n7>y2tuI-W2izzGS zvR&~mHp@hoG&YhbU5Lc_XXy7MFY#?O(mW=hGsz%bXg<(9fl~t;4q+A?TJPXC{cUpx zFVT;i!w#<}XhF+h1Ql-Zwo6lPxX27z;iat=(f(O_JsRQX=*un54ai)GQ9)DS04XA} zx#TqbJoqm>)M#$4A?I-xTX)CeDElG}L>u{6XlFDG2Y|(EnZolpmH>FlvXs6XZ7yNU z25g^mJR}W$6y5J4A{}U5?L^nvUUga47lE`#u$QN+DRKr{q?mP6>5H}}L$s7d`L@z| z^fM{J5znkffZA?dGA+h+GKOPEaZFf}bl|V;Q-J+i3dnv8$9xEk@q?)4f!LaZs8E+d z%XGM3OOB(`EX}r6hc(nHl5{<>>vjlzqphkOuZ_$h%p+hhkZ0)aw)%zzY`%b?BcQ8^ zfsjH-(?I(Hevyv0$N5Q`X^&Q8GPLu@Sfr2YI(ZTL|jBd2h4O10c|pghLHOZfllldI4fzX*)(|x2HvJ$ zk9YHJxnIRi*TfnrRs7fO{@*BsAghWH_6Yz%AdGgq`wfi z(tYrcdF~&8i1K}{LPnX5kX3qM$o78+WaPUD-=kH-^}I|E4%Y?W1p$P%jB=SKha&8H=MhL0|BDWfumG1 z4hfpn;Dl;~282e0dISul9hHXN6nc%kiBOABhfqb&kMtKY!u<^UHxX{p*GKw_-@qpG zqg#b z7qi2PR7`ksTZOpJ5riPXF8X6t+eLq;&Y^e&Duj6f8uYWV1YFMfqpL1{nEvZ{Q}{iQ z+U|@rr!t3vMLY$0mUfNrNnXPy<2IvkC+Zeuh&roUP^pQk<3Y$_)M8F6#n#^t$`Q%{ z?0n!<0_~elu4DW5Iw5eMqqoLeI@k=hEMvSErtKs=VU-qPGWU4=qdbABzDXaR_(d1y zW~f3QNQ_#>_G+f0&1q1VoFb8z)RZUk^?N6yyh;CYatyLc_f*{VAxD!_V@-}7XOExbmXE{mR%;=g$Dqw@o3k-9UlM3j~>53KR z2naz?utS?g13X0}!y(>7oce7XF4#!Qa2oO{N|^`#i7n=_r@eOsHnx|**CO&5bmx!- zM**&I_sVN?$4(u_K)rf;)wRNE^gYnA-PWayO0e2(73u`OCfGp;BST9`dV*=Z0va)% zxWHV@Yv*qcf-`VxXtU3hO_t{DpsDJrjMPU9cG*@pNnbzHU%u_XEwYhm`tg~#$hdU` z>@up^p|i)&Oi!K~ol2ZN|LpM@CldS)qgX!mz@~_R;03VVavDnRG|taMA#%xyJUML z1HpVLvuHYLay#kO(`#Dw%2vj-U1`&a_*OI!n8po12mgj)aL`lz6^>o!fyYXuI*%5ZA#Ets}6P?f(HsmC&yM diff --git a/fzjgact/huodong/admin.py b/fzjgact/huodong/admin.py index 5118c28..35d55a9 100644 --- a/fzjgact/huodong/admin.py +++ b/fzjgact/huodong/admin.py @@ -1,194 +1,287 @@ -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'] +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, Budget, EquipmentBudget, InfrastructureBudget, BudgetTemplate, TemplateEquipmentItem, TemplateInfrastructureItem +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'] + + +# 预算相关Admin配置 + +# 设备预算内联 +class EquipmentBudgetInline(admin.TabularInline): + model = EquipmentBudget + extra = 1 + fields = ('project', 'model', 'unit_price', 'procurement_method', 'quantity', 'subtotal') + readonly_fields = ('subtotal',) # 小计自动计算,设为只读 + +# 基础设施预算内联 +class InfrastructureBudgetInline(admin.TabularInline): + model = InfrastructureBudget + extra = 1 + fields = ('name', 'remarks', 'unit_price', 'unit', 'quantity', 'subtotal', 'description') + readonly_fields = ('subtotal',) # 小计自动计算,设为只读 + +# 预算Admin +@admin.register(Budget) +class BudgetAdmin(ModelAdmin): + list_display = ('branch', 'name', 'total_budget', 'created_at') + list_filter = ('branch',) + search_fields = ('branch__name', 'name') + autocomplete_fields = ['branch'] + readonly_fields = ('total_budget',) # 总预算自动计算,设为只读 + inlines = [EquipmentBudgetInline, InfrastructureBudgetInline] + + def save_model(self, request, obj, form, change): + super().save_model(request, obj, form, change) + # 保存后重新计算总预算 + obj.update_total_budget() + +# 设备预算Admin(如果需要单独管理) +@admin.register(EquipmentBudget) +class EquipmentBudgetAdmin(ModelAdmin): + list_display = ('budget', 'project', 'model', 'unit_price', 'procurement_method', 'quantity', 'subtotal') + list_filter = ('budget__branch', 'project', 'procurement_method') + search_fields = ('budget__branch__name', 'project', 'model') + autocomplete_fields = ['budget'] + readonly_fields = ('subtotal',) + +# 基础设施预算Admin(如果需要单独管理) +@admin.register(InfrastructureBudget) +class InfrastructureBudgetAdmin(ModelAdmin): + list_display = ('budget', 'name', 'unit_price', 'unit', 'quantity', 'subtotal') + list_filter = ('budget__branch', 'name') + search_fields = ('budget__branch__name', 'name', 'description') + autocomplete_fields = ['budget'] + readonly_fields = ('subtotal',) + + +# 预算模板相关Admin配置 + +# 模板设备项内联 +class TemplateEquipmentItemInline(admin.TabularInline): + model = TemplateEquipmentItem + extra = 1 + +# 模板基础设施项内联 +class TemplateInfrastructureItemInline(admin.TabularInline): + model = TemplateInfrastructureItem + extra = 1 + +# 模板设备项Admin(如果需要单独管理) +@admin.register(TemplateEquipmentItem) +class TemplateEquipmentItemAdmin(ModelAdmin): + list_display = ('template', 'project', 'model', 'unit_price', 'procurement_method') + list_filter = ('template', 'project', 'procurement_method') + search_fields = ('template__name', 'project', 'model') + autocomplete_fields = ['template'] + +# 模板基础设施项Admin(如果需要单独管理) +@admin.register(TemplateInfrastructureItem) +class TemplateInfrastructureItemAdmin(ModelAdmin): + list_display = ('template', 'name', 'unit_price', 'unit') + list_filter = ('template', 'unit') + search_fields = ('template__name', 'name', 'description') + autocomplete_fields = ['template'] + +# 预算模板Admin +@admin.register(BudgetTemplate) +class BudgetTemplateAdmin(ModelAdmin): + list_display = ('name', 'description', 'is_default', 'created_at') + list_filter = ('is_default',) + search_fields = ('name', 'description') + inlines = [TemplateEquipmentItemInline, TemplateInfrastructureItemInline] + + def save_model(self, request, obj, form, change): + # 如果设置为默认模板,将其他模板的默认状态取消 + if obj.is_default: + BudgetTemplate.objects.exclude(id=obj.id).update(is_default=False) + super().save_model(request, obj, form, change) diff --git a/fzjgact/huodong/migrations/0030_budget_equipmentbudget_infrastructurebudget.py b/fzjgact/huodong/migrations/0030_budget_equipmentbudget_infrastructurebudget.py new file mode 100644 index 0000000..7ea59f3 --- /dev/null +++ b/fzjgact/huodong/migrations/0030_budget_equipmentbudget_infrastructurebudget.py @@ -0,0 +1,64 @@ +# Generated by Django 5.0.6 on 2025-12-03 07:44 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0029_alter_activity_end_time_alter_activity_start_time_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='Budget', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ('total_budget', models.DecimalField(decimal_places=2, default=0, max_digits=15, verbose_name='总预算')), + ('activity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='huodong.activity', verbose_name='活动')), + ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='huodong.branch', verbose_name='分支机构')), + ], + options={ + 'verbose_name': '预算主表', + 'verbose_name_plural': '预算主表', + }, + ), + migrations.CreateModel( + name='EquipmentBudget', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('project', models.CharField(max_length=255, verbose_name='项目')), + ('model', models.CharField(max_length=255, verbose_name='型号')), + ('unit_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='单价')), + ('procurement_method', models.CharField(choices=[('本地询价采购', '本地询价采购'), ('订单采购', '订单采购'), ('按照总部配置要求本地询价采购', '按照总部配置要求本地询价采购'), ('本地询价采购或订单采购', '本地询价采购或订单采购')], max_length=50, verbose_name='采购方式')), + ('quantity', models.IntegerField(default=1, verbose_name='数量')), + ('subtotal', models.DecimalField(decimal_places=2, default=0, max_digits=12, verbose_name='小计')), + ('budget', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='equipment_budgets', to='huodong.budget', verbose_name='预算主表')), + ], + options={ + 'verbose_name': '设备预算明细', + 'verbose_name_plural': '设备预算明细', + }, + ), + migrations.CreateModel( + name='InfrastructureBudget', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='名称')), + ('remarks', models.TextField(blank=True, verbose_name='备注')), + ('unit_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='单价')), + ('unit', models.CharField(max_length=20, verbose_name='单位')), + ('description', models.TextField(blank=True, verbose_name='说明')), + ('quantity', models.IntegerField(default=1, verbose_name='数量')), + ('subtotal', models.DecimalField(decimal_places=2, default=0, max_digits=12, verbose_name='小计')), + ('budget', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='infrastructure_budgets', to='huodong.budget', verbose_name='预算主表')), + ], + options={ + 'verbose_name': '基础设施预算明细', + 'verbose_name_plural': '基础设施预算明细', + }, + ), + ] diff --git a/fzjgact/huodong/migrations/0031_budgettemplate_templateequipmentitem_and_more.py b/fzjgact/huodong/migrations/0031_budgettemplate_templateequipmentitem_and_more.py new file mode 100644 index 0000000..1d438b0 --- /dev/null +++ b/fzjgact/huodong/migrations/0031_budgettemplate_templateequipmentitem_and_more.py @@ -0,0 +1,60 @@ +# Generated by Django 5.0.6 on 2025-12-03 08:16 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0030_budget_equipmentbudget_infrastructurebudget'), + ] + + operations = [ + migrations.CreateModel( + name='BudgetTemplate', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, 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='更新时间')), + ('is_default', models.BooleanField(default=False, verbose_name='是否默认模板')), + ], + options={ + 'verbose_name': '预算模板', + 'verbose_name_plural': '预算模板', + }, + ), + migrations.CreateModel( + name='TemplateEquipmentItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('project', models.CharField(max_length=255, verbose_name='项目')), + ('model', models.CharField(max_length=255, verbose_name='型号')), + ('unit_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='参考单价')), + ('procurement_method', models.CharField(choices=[('本地询价采购', '本地询价采购'), ('订单采购', '订单采购'), ('按照总部配置要求本地询价采购', '按照总部配置要求本地询价采购'), ('本地询价采购或订单采购', '本地询价采购或订单采购')], max_length=50, verbose_name='采购方式')), + ('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='equipment_items', to='huodong.budgettemplate', verbose_name='模板')), + ], + options={ + 'verbose_name': '模板设备项', + 'verbose_name_plural': '模板设备项', + }, + ), + migrations.CreateModel( + name='TemplateInfrastructureItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='名称')), + ('remarks', models.TextField(blank=True, verbose_name='备注')), + ('unit_price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='参考单价')), + ('unit', models.CharField(max_length=20, verbose_name='单位')), + ('description', models.TextField(blank=True, verbose_name='说明')), + ('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='infrastructure_items', to='huodong.budgettemplate', verbose_name='模板')), + ], + options={ + 'verbose_name': '模板基础设施项', + 'verbose_name_plural': '模板基础设施项', + }, + ), + ] diff --git a/fzjgact/huodong/migrations/0032_remove_budget_activity_budget_name.py b/fzjgact/huodong/migrations/0032_remove_budget_activity_budget_name.py new file mode 100644 index 0000000..e191601 --- /dev/null +++ b/fzjgact/huodong/migrations/0032_remove_budget_activity_budget_name.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.6 on 2025-12-03 09:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('huodong', '0031_budgettemplate_templateequipmentitem_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='budget', + name='activity', + ), + migrations.AddField( + model_name='budget', + name='name', + field=models.CharField(default=1, max_length=255, verbose_name='预算名称'), + preserve_default=False, + ), + ] diff --git a/fzjgact/huodong/migrations/__pycache__/0030_budget_equipmentbudget_infrastructurebudget.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0030_budget_equipmentbudget_infrastructurebudget.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46ca2887d012a2e2f968388efa308001e093c4cb GIT binary patch literal 4195 zcmd56<)1=kYvCT#$bW4kZT8v5KR0NN|GkQ;Qu&apg*Cc+eLRRR+d(HcSQ}E zPMy}V-5=L}sBJp-q_!txyAuV|DQ&QcJ3R8#xtiGr%|3OemOy=y$IeS%+H>zp0xU9d zGJWVSI=lDW^LM{-?u*?Alna?oDBACMk9p<)~VLpMMaSd9LshctaaeO`>)+mavLV-`Ji9)s@-{*-$;)-s^0lVYM&tvl8jeUju0$ zjS*_fxKJbVC$^Me_^lGDt!qeaqf#r8egQQlwy%yAa0#ro7GhBIEfabXwIp6Dk!_{2 zu3~&UP+Q{VlK6I(cy^&(X!ja9-a{q7NseDZ?WjKS?PsedWJeuve|1(~{Tf+$Z8buW zmDkt6`#V(1UBt$M-blPzg3a@0<*jFYcA~v&`0Oh2*}aC(|DUYw`;x3V(0;hr$Xdue zScMKi7d)stjuyHfw8FBHcnrm)kp5;{+s+P-kEnvo@j+D_6V-7}kPxSeQQ=v>qVlqu zp8=6*Ocr$8-Z%;gs?LgNV86~D>JC`+az3ucxS%ZXs(|!$qp}#~<#FzWFs?fkK^FOl zI3eieV}d*!Qv^=pqk`_ti*vjhCygq7{#ttOLFVdTvsY&zV8f&o`w7P*B$FMkJL98> zI4EdjuFYhwOcyomGziczq|4Qq%15|i8f}&|UYU?AF%>7fJac+3d+W^N)KyqOB@%)V zbA%g>@IgV*%aCxKk4IGagz%?0B!)y)G0fTvpiQ{)khT^$anfZoGjr)*-3^#^M@-`2 zizBFl&Z;p(*)}ZmQgCFVvY={=^XosG`Q5$D^#_@c&QOLC+@smKrJHvHtYKioN(dp? zxXeeumxUr~J1z79 zEHolWA$7!XWu+fXDwO`{*XfI&0sfMxa**7hkR>h1n7eTK(cEVNvs?=t*+U3TRu#Ak z#$|zc=c0l-5<>w?fc>HhBr?|%>Fd)=_ilk^_T0IpnNQ_rV8bjagr%ul=?j;YhC*!=N!nVnph!Rcu<>~CXi;$#E%Th{wm{wqxtjU0C z`r^{mP2Facr0y09*~u5FvZ5|%)dnnbJt*ttvJjz#Ptq)V3qIlm%cZHmr9VDr)JkUZ zw~KRU_3A^?ahX?CIUZCY14iy;UonhJ7Z&eK>t&D|UOu51p?!QV^Jl0s-8vlMr4z`r!qA9TJqFEYcFA{H1#{;8?E_S9vY0DNZ0s|KY*n&C?KS=E}pBp}rH? zpxZgx4>(SDa?oK=JR-n*ImZFa5wc)1Lc%EYC_xH}kP33()7N#;ZgZ5J>SS{G(#!XX zp-$*S`^hfQE4l%(0qAMQu)N#Y;Ks5i@uUe4P%B&kA3$d4QY!YMUxE;cIU&zXN@oFr1NZ!G=g zOyGR7Q-RKrW$0x!e=psY;wlK7OZXIfC+trrGk}DRBQ9;~l#0_Ta=(tQu zk`i)QRmuUK)5SYyV;tW%<;-lg?eyC@C*$y)cWU;{DYxez?v1#%`O=tH+dOMo*op@^ zEXlZ5N!BV_t%6-@%H4o{yC%mp->&&;JTQ!X!K5#!`GVMmR?N)~;NBl$AD8rTnvcV- zAE(?t?B9K(M)U8U?_4;E-vh(r*guiLuF6l;lMEm5pvY|iZftZNwmo>bFoE3o#s2-ZNJ5|Z1pjCIpBX*NDR(gq)4S(Ku(v1a?a{nF*wy=$ST7sx15Hm)($k}P z49(5BvF(OUYiyfVA-9eF$;N)I(a0^7@BbXzp8=@**zXbu5i3({6^gAwu~jIxDx2Hj z1Z+1k{?}4Xohz`dcN1)ZJS8O8W!hC`JAIhka&MtM1Z=v;XiBYUxYhUvxwX&&oD1JOewkK)LdI1lZmHm%+eVC3q4@kB>(^b literal 0 HcmV?d00001 diff --git a/fzjgact/huodong/migrations/__pycache__/0031_budgettemplate_templateequipmentitem_and_more.cpython-311.pyc b/fzjgact/huodong/migrations/__pycache__/0031_budgettemplate_templateequipmentitem_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b8c5a6f7700fc9c49f66bd899092eb385e157a9 GIT binary patch literal 3643 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