Skip to content

Commit

Permalink
feat: opt ticket management (#924)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ehco1996 authored Jan 10, 2024
1 parent c4d6b53 commit fe08fba
Show file tree
Hide file tree
Showing 17 changed files with 284 additions and 202 deletions.
31 changes: 31 additions & 0 deletions apps/proxy/migrations/0025_alter_occupancyconfig_color.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Generated by Django 4.2.6 on 2024-01-10 01:44

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("proxy", "0024_occupancyconfig_color_occupancyconfig_remark_and_more"),
]

operations = [
migrations.AlterField(
model_name="occupancyconfig",
name="color",
field=models.CharField(
blank=True,
choices=[
("", "empty"),
("is-info", "is-info"),
("is-link", "is-link"),
("is-primary", "is-primary"),
("is-danger", "is-danger"),
("is-warning", "is-warning"),
("is-success", "is-success"),
],
default="",
max_length=32,
verbose_name="颜色",
),
),
]
21 changes: 17 additions & 4 deletions apps/sspanel/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,25 @@ class RebateRecordAdmin(admin.ModelAdmin):
search_fields = ["user_id", "consumer_id"]


class TicketAdmin(admin.ModelAdmin):
list_display = ["user", "title", "status", "updated_at"]
search_fields = ["title", "user__id"]
class TicketMessageInline(admin.TabularInline):
model = models.TicketMessage
verbose_name = "回复"
fields = [
"user",
"message",
"created_at",
]
readonly_fields = [
"updated_at",
"created_at",
]
extra = 0


class TicketAdmin(admin.ModelAdmin):
inlines = [TicketMessageInline]
list_display = ["user", "title", "status_with_message_count", "updated_at"]
search_fields = ["title", "user"]
readonly_fields = ["updated_at"]


# Register your models here.
Expand Down
24 changes: 0 additions & 24 deletions apps/sspanel/admin_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
InviteCode,
MoneyCode,
PurchaseHistory,
Ticket,
User,
UserCheckInLog,
)
Expand Down Expand Up @@ -97,29 +96,6 @@ def get(self, request):
return render(request, "my_admin/purchasehistory.html", context=context)


class TicketsView(StaffRequiredMixin, View):
def get(self, request):
ticket = Ticket.objects.filter(status=1)
context = {"ticket": ticket}
return render(request, "my_admin/tickets.html", context=context)


class TicketDetailView(StaffRequiredMixin, View):
def get(self, request, pk):
ticket = Ticket.objects.get(pk=pk)
context = {"ticket": ticket}
return render(request, "my_admin/ticket_detail.html", context=context)

def post(self, request, pk):
ticket = Ticket.objects.get(pk=pk)
ticket.title = request.POST.get("title", "")
ticket.body = request.POST.get("body", "")
ticket.status = request.POST.get("status", 1)
ticket.save()
messages.success(request, "数据更新成功", extra_tags="修改成功")
return HttpResponseRedirect(reverse("sspanel:admin_tickets"))


class GoodsView(StaffRequiredMixin, View):
def get(self, request):
goods = Goods.objects.all()
Expand Down
56 changes: 56 additions & 0 deletions apps/sspanel/migrations/0020_ticketmessage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Generated by Django 4.2.6 on 2024-01-10 01:44

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("sspanel", "0019_rename_ss_password_user_proxy_password_and_more"),
]

operations = [
migrations.CreateModel(
name="TicketMessage",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("message", models.TextField(verbose_name="内容主体")),
(
"created_at",
models.DateTimeField(auto_now_add=True, verbose_name="时间"),
),
(
"ticket",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="messages",
to="sspanel.ticket",
verbose_name="工单",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
verbose_name="用户",
),
),
],
options={
"verbose_name": "工单回复",
"verbose_name_plural": "工单回复",
"ordering": ("ticket", "-created_at"),
"index_together": {("ticket", "created_at")},
},
),
]
44 changes: 44 additions & 0 deletions apps/sspanel/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,10 @@ class Ticket(models.Model):
def __str__(self):
return self.title

@property
def status_with_message_count(self):
return f"{self.get_status_display()} (回复数量:{self.messages.count()})"

class Meta:
verbose_name = "工单"
verbose_name_plural = "工单"
Expand All @@ -1029,6 +1033,46 @@ def close_stale_tickets(cls):
t.status = -1
t.save()

def add_message(self, user, message):
return TicketMessage.create_message(user, self, message)

def list_messages(self):
return self.messages.all()


class TicketMessage(models.Model):
"""工单回复"""

user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用户")
ticket = models.ForeignKey(
Ticket,
on_delete=models.CASCADE,
verbose_name="工单",
db_index=True,
related_name="messages",
)
message = models.TextField(verbose_name="内容主体")
created_at = models.DateTimeField(
verbose_name="时间", editable=False, auto_now_add=True
)

class Meta:
verbose_name = "工单回复"
verbose_name_plural = "工单回复"
ordering = ("ticket", "created_at")
index_together = ["ticket", "created_at"]

@classmethod
def create_message(cls, user, ticket, message):
return cls.objects.create(user=user, ticket=ticket, message=message)

@property
def is_staff(self):
return self.user.is_staff

def __str__(self) -> str:
return f"{self.id}"


class EmailSendLog(models.Model):
"""邮件发送记录"""
Expand Down
13 changes: 3 additions & 10 deletions apps/sspanel/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
# 公告
path("announcement/", views.AnnouncementView.as_view(), name="announcement"),
# 工单
path("tickets/", views.TicketsView.as_view(), name="tickets"),
path("tickets/(<int:pk>)/", views.TicketDetailView.as_view(), name="ticket_detail"),
path("tickets/", views.TicketListView.as_view(), name="ticket_list"),
path("tickets/<int:pk>/", views.TicketDetailView.as_view(), name="ticket_detail"),
path("ticket_create/", views.TicketCreateView.as_view(), name="ticket_create"),
path(
"ticket_delete/<int:pk>)/",
"ticket_delete/<int:pk>/",
views.TicketDeleteView.as_view(),
name="ticket_delete",
),
Expand Down Expand Up @@ -95,11 +95,4 @@
admin_views.AnnouncementCreateView.as_view(),
name="announcement_create",
),
# 工单相关
path("my_admin/tickets/", admin_views.TicketsView.as_view(), name="admin_tickets"),
path(
"my_admin/tickets/<int:pk>/",
admin_views.TicketDetailView.as_view(),
name="admin_ticket_detail",
),
]
31 changes: 20 additions & 11 deletions apps/sspanel/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
User,
UserSocialProfile,
)
from apps.utils import traffic_format
from apps.utils import get_current_datetime, traffic_format


class IndexView(View):
Expand Down Expand Up @@ -300,12 +300,13 @@ def get(self, request):
return render(request, "web/announcement.html", {"anno": anno})


class TicketsView(LoginRequiredMixin, View):
class TicketListView(LoginRequiredMixin, View):
def get(self, request):
"""工单系统"""
# TODO paginate
ticket = Ticket.objects.filter(user=request.user)
context = {"ticket": ticket}
return render(request, "web/ticket.html", context=context)
return render(request, "web/ticket_list.html", context=context)


class TicketCreateView(LoginRequiredMixin, View):
Expand All @@ -318,35 +319,43 @@ def post(self, request):
body = request.POST.get("body", "")
Ticket.objects.create(user=request.user, title=title, body=body)
messages.success(request, "数据更新成功!", extra_tags="添加成功")
return HttpResponseRedirect(reverse("sspanel:tickets"))
return HttpResponseRedirect(reverse("sspanel:ticket_list"))


class TicketDetailView(LoginRequiredMixin, View):
def get(self, request, pk):
"""工单编辑"""
ticket = Ticket.objects.get(pk=pk)
context = {"ticket": ticket}
context = {
"ticket": ticket,
"ticket_messages": ticket.list_messages(),
"ticket_body_line_count": ticket.body.count("\n") + 2,
}
return render(request, "web/ticket_edit.html", context=context)

def post(self, request, pk):
"""添加回复"""
ticket = Ticket.objects.get(pk=pk)
ticket.title = request.POST.get("title", "")
ticket.body = request.POST.get("body", "")
ticket.updated_at = get_current_datetime()
ticket.save()
messages.success(request, "数据更新成功", extra_tags="修改成功")
return HttpResponseRedirect(reverse("sspanel:tickets"))
message = request.POST.get("message", "")
if not message:
messages.error(request, "回复内容不能为空", extra_tags="回复失败")
else:
ticket.add_message(request.user, message)
messages.success(request, "数据更新成功", extra_tags="修改成功")
return HttpResponseRedirect(reverse("sspanel:ticket_detail", args=(pk,)))


class TicketDeleteView(LoginRequiredMixin, View):
def get(self, request, pk):
"""删除指定"""
ticket = Ticket.objects.filter(pk=pk, user=request.user).first()
if ticket:
ticket.delete()
messages.success(request, "该工单已经删除", extra_tags="删除成功")
else:
messages.error(request, "该工单不存在", extra_tags="删除失败")
return HttpResponseRedirect(reverse("sspanel:tickets"))
return HttpResponseRedirect(reverse("sspanel:ticket_list"))


class ProxyNodeOccupancyView(LoginRequiredMixin, View):
Expand Down
4 changes: 0 additions & 4 deletions templates/adminbase.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
<a class="navbar-item" href="{% url 'sspanel:admin_user_status' %}">用户分析</a>
<a class="navbar-item" href="{% url 'sspanel:admin_invite' %}">邀请相关</a>
<a class="navbar-item" href="{% url 'sspanel:admin_announcements' %}">公告管理</a>
<a class="navbar-item" href="{% url 'sspanel:admin_tickets' %}">工单管理</a>
<a class="navbar-item is-active">交易管理</a>
<a class="navbar-item" href="{% url 'sspanel:admin_charge' %}">充值管理</a>
<a class="navbar-item" href="{% url 'sspanel:admin_goods' %}">商品管理</a>
Expand Down Expand Up @@ -112,9 +111,6 @@ <h2 class="subtitle">
<li>
<a href="{% url 'sspanel:admin_announcements' %}">公告管理</a>
</li>
<li>
<a href="{% url 'sspanel:admin_tickets' %}">工单管理</a>
</li>
</ul>
<p class="menu-label">
交易管理
Expand Down
4 changes: 2 additions & 2 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
<a class="navbar-item" href="{% url 'sspanel:aff_invite' %}">邀请返利</a>
<a class="navbar-item is-active">公告交流</a>
<a class="navbar-item" href="{% url 'sspanel:announcement' %}">历史公告</a>
<a class="navbar-item" href="{% url 'sspanel:tickets' %}">联系站长</a>
<a class="navbar-item" href="{% url 'sspanel:ticket_list' %}">联系站长</a>
{% if perms.sspanel %}
<a class="navbar-item is-active">管理面板</a>
<a class="navbar-item" href="/admin">数据后台</a>
Expand Down Expand Up @@ -143,7 +143,7 @@ <h2 class="subtitle">
<a href="{% url 'sspanel:announcement' %}">历史公告</a>
</li>
<li>
<a href="{% url 'sspanel:tickets' %}">联系站长</a>
<a href="{% url 'sspanel:ticket_list' %}">联系站长</a>
</li>
</ul>

Expand Down
2 changes: 0 additions & 2 deletions templates/basehead.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
<link rel="stylesheet" href="{% static 'sspanel/css/sspanel.css'%}">

{% if not simple_extra_static or user.is_authenticated %}
<link rel="stylesheet" href="https://cdn.staticfile.org/simplemde/1.11.2/simplemde.min.css">
<link rel="stylesheet" href="https://cdn.staticfile.org/flag-icon-css/3.5.0/css/flag-icon.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bulma-extensions.min.css">
Expand All @@ -28,7 +27,6 @@
<script src="https://cdn.staticfile.org/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdn.staticfile.org/clipboard.js/1.7.1/clipboard.min.js"></script>
<script src="https://cdn.staticfile.org/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
<script src="https://cdn.staticfile.org/simplemde/1.11.2/simplemde.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bulma-extensions.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@fortawesome/[email protected]/js/all.min.js"></script>
Expand Down
4 changes: 1 addition & 3 deletions templates/my_admin/announcement_create.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,4 @@ <h2 class="subtitle">
</form>
</div>
</div>
<script>
var simplemde = new SimpleMDE({ spellChecker: false, element: $("#id-markdown-body")[0] });
</script> {% endblock main %}
{% endblock main %}
4 changes: 1 addition & 3 deletions templates/my_admin/announcement_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,4 @@ <h2 class="subtitle">
</form>
</div>
</div>
<script>
var simplemde = new SimpleMDE({ spellChecker: false,element: $("#id-markdown-body")[0] });
</script> {% endblock main %}
{% endblock main %}
Loading

0 comments on commit fe08fba

Please sign in to comment.