diff --git a/views/admin/ticket_index.php b/views/admin/ticket_index.php new file mode 100644 index 0000000..a7f8b81 --- /dev/null +++ b/views/admin/ticket_index.php @@ -0,0 +1,127 @@ +title = '工单支持管理'; +$this->params['breadcrumbs'][] = $this->title; +FontAwesomeAsset::register($this); +?> +
+ +

title) ?>

+ + + + + + $dataProvider, + 'filterModel' => $searchModel, + 'columns' => [ + [ + 'attribute' => 'id', + 'label' => '工单ID', + ], + [ + 'attribute' => 'user_id', + 'label' => '用户', + 'format' => 'html', + 'value' => function (Tickets $model) { + return $model->user->username . '
(ID: ' . $model->user->id . ')'; + } + ], + [ + 'attribute' => 'title', + 'label' => '标题', + 'format' => 'raw', // 使用 raw 格式,这样 Yii2 不会对 value 的返回值进行 HTML 编码 + 'value' => function (Tickets $model) { + return Html::a($model->title, ['ticket-view', 'id' => $model->id]); + }, + ], + [ + 'attribute' => 'created_at', + 'label' => '创建时间', + 'filter' => false + ], + [ + 'attribute' => 'updated_at', + 'label' => '最近更新时间', + 'value' => function (Tickets $model) { + return Yii::$app->formatter->asRelativeTime(new DateTime($model->updated_at, new DateTimeZone('GMT+8'))); + }, + 'filter' => false + ], + [ + 'attribute' => 'status', + 'label' => '状态', + 'format' => 'raw', + 'value' => function (Tickets $model) { + return match ($model->status) { + Tickets::STATUS_OPEN => '工单已开启', + Tickets::STATUS_ADMIN_REPLY => '管理员已回复', + Tickets::STATUS_USER_REPLY => '用户已回复', + Tickets::STATUS_CLOSED => '工单已关闭', + default => '未知状态', + }; + }, + 'filter' => [ + Tickets::STATUS_OPEN => '工单已开启', + Tickets::STATUS_ADMIN_REPLY => '管理员已回复', + Tickets::STATUS_USER_REPLY => '用户已回复', + Tickets::STATUS_CLOSED => '工单已关闭', + ] + ], + [ + 'class' => ActionColumn::class, + 'template' => '{view} {delete}', + 'buttons' => [ + 'view' => function ($url, $model, $key) { + return Html::a('', ['ticket-view', 'id' => $model->id], [ + 'title' => '查看工单', + 'data-pjax' => '0', + ]); + }, + 'delete' => function ($url, $model, $key) { + if ($model->status !== Tickets::STATUS_CLOSED) { + return Html::a('', ['ticket-delete', 'id' => $model->id, 'from' => 'index'], [ + 'title' => '关闭工单', + 'data-pjax' => '0', + 'data-confirm' => '你确定要关闭这个工单吗?', + 'data-method' => 'post', + ]); + } else { + return Html::tag('i', '', [ + 'class' => 'fa-solid fa-xmark', + 'style' => 'color: gray;', + 'title' => '工单已关闭', + ]); + } + }, + ], + 'urlCreator' => function ($action, Tickets $model, $key, $index, $column) { + return Url::toRoute([$action, 'id' => $model->id]); + }, + ], + ], + ]); ?> + + + +
diff --git a/views/admin/ticket_view.php b/views/admin/ticket_view.php new file mode 100644 index 0000000..22c2c5e --- /dev/null +++ b/views/admin/ticket_view.php @@ -0,0 +1,170 @@ +title = '工单: ' . $model->title; +$this->params['breadcrumbs'][] = ['label' => '工单支持管理', 'url' => ['ticket-manage']]; +$this->params['breadcrumbs'][] = '工单ID ' . $model->id; +YiiAsset::register($this); +QuillAsset::register($this); +FontAwesomeAsset::register($this); +$this->registerCssFile('@web/css/tickets.css'); +?> +
+ +

title) ?>

+
+ +
+
+ + $model, + 'attributes' => [ + 'id', + [ + 'attribute' => 'status', + 'label' => '状态', + 'format' => 'raw', + 'value' => function (Tickets $model) { + return match ($model->status) { + Tickets::STATUS_OPEN => '工单已开启', + Tickets::STATUS_ADMIN_REPLY => '管理员已回复', + Tickets::STATUS_USER_REPLY => '用户已回复', + Tickets::STATUS_CLOSED => '工单已关闭', + default => '未知状态', + }; + } + ], + [ + 'attribute' => 'user_id', + 'label' => '用户', + 'format' => 'html', + 'value' => function (Tickets $model) { + return $model->user->username . '
(ID: ' . $model->user->id . ')'; + } + ], + [ + 'attribute' => 'ip', + 'label' => '用户IP', + ], + [ + 'attribute' => 'created_at', + 'label' => '创建时间', + 'format' => 'raw', // 使用 raw 格式,这样 Yii2 不会对 value 的返回值进行 HTML 编码 + 'value' => function (Tickets $model) { + $dateTime = new DateTime($model->created_at, new DateTimeZone('GMT+8')); + return $model->created_at . '
(' . Yii::$app->formatter->asRelativeTime($dateTime) . ')'; + } + ], + [ + 'attribute' => 'updated_at', + 'label' => '最近更新时间', + 'format' => 'raw', // 使用 raw 格式,这样 Yii2 不会对 value 的返回值进行 HTML 编码 + 'value' => function (Tickets $model) { + $dateTime = new DateTime($model->updated_at, new DateTimeZone('GMT+8')); + return $model->updated_at . '
(' . Yii::$app->formatter->asRelativeTime($dateTime) . ')'; + } + ] + ], + ]) ?> +

+ status === Tickets::STATUS_CLOSED) ? '' : Html::a('关闭工单', ['ticket-delete', 'id' => $model->id], ['class' => 'btn btn-danger', + 'data' => ['confirm' => '您确定要关闭这个工单吗?', + 'method' => 'post',],]) ?> +

+
+
+ +
+
+ +
+ 'btn btn-primary', 'id' => 'send']) ?> +
+
+
+
+
+
+ +
+user->username; +$core_js = <<id; // 你需要在这里设置正确的工单ID + + $.ajax({ + url: 'index.php?r=admin%2Fticket-reply', + type: 'POST', + data: { + ticketId: ticketId, + content: JSON.stringify(content) + }, + success: function(response) { + // 处理服务器的响应 + console.log(response); + // 如果服务器返回的状态是成功,刷新页面 + if (response.status === 'success') { + location.reload(); + } + }, + error: function(jqXHR, textStatus, errorThrown) { + // 处理错误 + console.error(textStatus, errorThrown); + } + }); + }); + function quillGetHTML(inputDelta,skipParse=false) { + var delta = skipParse?inputDelta:JSON.parse(inputDelta); + var tempQuill=new Quill(document.createElement("div")); + tempQuill.setContents(delta); + return tempQuill.root.innerHTML; + } + function generateReply(user, message, date,ip) { + return '
'+user+'
用户
'+date+' ('+ip+')'+'
'+message+'
'; + } + function generateAdminReply(user, message, date,ip) { + return '
'+user+'
管理员
'+date+' ('+ip+')'+'
'+message+'
'; + } + var ticketContent = $model->description; + var ticketContentElement = $('#ticket-content'); + ticketContentElement.append(generateReply('$user_name', quillGetHTML(ticketContent,true), '$model->created_at','$model->ip')); + var TicketReplies = $ticketReplies; + for (let i = 0; i < TicketReplies.length; i++) { + let reply = TicketReplies[i]; + let message = quillGetHTML(reply.message); + let date = reply.created_at; + let ip = reply.ip; + if (reply.is_admin !== 1) { + ticketContentElement.append(generateReply(reply.name, message, date,ip)); + } else { + ticketContentElement.append(generateAdminReply(reply.name, message, date,ip)); + } + } + +JS; + +$this->registerJs($core_js); +?> \ No newline at end of file