karlos3098/laravel-primevue-table-service

通过引入简单的分页、过滤和排序功能,简化PrimeVue表格集成的服务。

0.0.12 2024-07-11 23:37 UTC

This package is auto-updated.

Last update: 2024-09-21 18:37:58 UTC


README

作者: Let's Code IT - Karol Sójka

image1.png

安装

安装包

composer require karlos3098/laravel-primevue-table-service

发布vue组件

php artisan vendor:publish --provider="Karlos3098\\LaravelPrimevueTableService\\Providers\\LaravelPrimevueTableServiceProvider"

警告

现在是最困难的一步,但非常重要

为了使我们的包正常工作,我们需要用PrimeVue中的DataTable.vue文件中的一个文件替换。这个文件对于每个Vue版本都不同。我们已经为PrimeVue版本准备了文件。

  • 3.46.0

然后,使用列表中的适当版本,覆盖您app.js文件中DataTable组件的导入。

import DataTable from '@/karlos3098/laravel-primevue-table-service/src/Assets/PrimeVue/3.46.0/DataTable.vue';

现在,您还需要将这两个主要组件添加到app.js文件中。

import AdvanceTable from '@advance-table/Components/AdvanceTable.vue';
import AdvanceColumn from '@advance-table/Components/AdvanceColumn.vue';

别忘了初始化它们!

app
.component('AdvanceTable', AdvanceTable)
.component('AdvanceColumn', AdvanceColumn)

现在是时候创建第一个表格了。

我们建议使用Laravel中服务的方法。您的文件可能看起来像这样

<?php

namespace App\Services;

use App\Http\Resources\MessageResource;
use App\Models\Message;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Karlos3098\LaravelPrimevueTableService\Enum\TableCalendarDateFormat;
use Karlos3098\LaravelPrimevueTableService\Services\BaseService;
use Karlos3098\LaravelPrimevueTableService\Services\Columns\TableCalendarColumn;
use Karlos3098\LaravelPrimevueTableService\Services\Columns\TableTextColumn;
use Karlos3098\LaravelPrimevueTableService\Services\TableService;

final class MessageService extends BaseService
{
    public function __construct(
        protected Message $messageModel,
    ) {
    }

    /**
     * @throws \Exception
     */
    public function findAll(): AnonymousResourceCollection
    {
        return $this->fetchData(
            MessageResource::class,
            $this->messageModel,
            new TableService(
                globalFilterColumns: ['text'],
                columns: [
                    'text' => new TableTextColumn(
                        placeholder: 'Search by text'
                    ),
                    'contact' => new TableTextColumn(
                        placeholder: 'Message contact name',
                        queryPaths: [
                            'senderPhoneNumber.phone_number', 'senderContact.name',
                            'receivers.phoneNumber.phone_number', 'receivers.contact.name',
                        ],
                    ),
                    'date' => new TableCalendarColumn(
                        format: TableCalendarDateFormat::YMD,
                        placeholder: 'Search by created at',
                        sortable: true,
                        queryPaths: ['created_at'],
                        sortPath: 'created_at',
                    ),
                    'type' => new TableDropdownColumn(
                        placeholder: 'Select Message Type',
                        options: [
                            new TableDropdownOptionTag(
                                label: 'Incomming',
                                query: fn ($query) => $query->where('incomming', true),
                                severity: TagSeverity::SUCCESS
                            ),
                            new TableDropdownOptionTag(
                                label: 'Outgoing',
                                query: fn ($query) => $query->where('incomming', false),
                                severity: TagSeverity::INFO
                            ),
                        ]
                    ),
                ],
                rowsPerPage: [30, 100],
                propName: 'messages',
            )
        );
    }
}

然后控制器可能如下所示

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Services\MessageService;
use Illuminate\Http\Request;
use Inertia\Inertia;

class MessageController extends Controller
{
    public function __construct(
        protected MessageService $messageService,
    ) {
    }

    public function index()
    {
        return Inertia::render('Messages/Index', [
            'messages' => $this->messageService->findAll(),
        ]);
    }
}

现在,我们需要在前端显示表格。

<script setup lang="ts">
    import { MessageResource } from './MessageResource';

    type Data = {
        data: MessageResource;
    };
</script>

<template>
    <MessagesTemplate>
        <AdvanceTable
            prop-name="messages"
        >
            <template #header="{ globalFilterValue, globalFilterUpdated }">
                <div class="flex justify-content-end">
                    <InputText
                        :value="globalFilterValue"
                        @update:model-value="globalFilterUpdated"
                        placeholder="Search"
                    />
                </div>
            </template>


            <AdvanceColumn field="contact" style="min-width: 4rem">
                <template #body="{ data }: Data">
                    <div class="flex align-items-center md:justify-content-start">
                        <img
                            class="w-2rem h-2rem border-circle m-0"
                            :src="data.first_receiver.phone_number.avatar"
                            alt=""
                        />
                        <div class="flex flex-column mx-3">
                                <span class="block text-900 font-semibold">{{
                                data.first_receiver.phone_number.name
                            }}</span>
                        </div>
                    </div>
                </template>
            </AdvanceColumn>

            <AdvanceColumn field="text"></AdvanceColumn>

            <AdvanceColumn field="date" dataType="date">
                <template #body="{ data }: Data">
                    <div :style="{ minWidth: '10rem' }">
                        <div class="flex justify-content-end w-full px-0">
                            <span ref="dateRef" class="date-text text-700 font-semibold white-space-nowrap">
                                {{ data.created_at }}
                            </span>
                        </div>
                    </div>
                </template>
            </AdvanceColumn>

            <AdvanceColumn field="type"></AdvanceColumn>
            
        </AdvanceTable>
    </MessagesTemplate>
</template>

让我们从'globalFilterColumns'开始。这是一个列表,在表格头模板中,全局搜索引擎应该在这些字段中搜索。

在上面的例子中,我们显示了3列,这些列是我们管理的

  • 联系
  • 文本
  • 日期

最简单的例子是文本列。这是一个常规的文本列,我们可以简单地通过短语搜索。

第二个有趣的是'联系'。这个名称既不用于资源,也不作为模型中的字段。这是Vue和后端之间的正确名称。'queryPaths'在这里很重要。我们可以提供一个字段列表(如您所见,也包括关系),过滤应在这些字段上执行。如果没有提供,网站将自动尝试在不存在的'联系'列中搜索。

另一个例子是'日期'列。在这种情况下,我将其声明为'created_at'列,并在此处进行过滤,但我们也有排序。

最后一个例子是'type',我们可以通过从列表中选择选项来搜索。

在列声明下,您还会找到'rowsPerPage'。它告诉您表格中每页可用的分页数。

还要记得提供正确的'propName',即您在inertiajs中传递表格的prop。如果名称不正确,则排序和分页不会有反应。

总结

该项目旨在应用于我自己的多个项目中,但我决定分享它。我愿意合作并扩展它。在不久的将来,我也想使用PrimeVue提供的数字范围进行一些过滤,但我没有时间。

为了让项目工作,我必须在DataTable.vue文件中替换一个导入,但DataTable的每个版本都不同。

尽管如此,我提供的这个解决方案将从3.46版开始,以及大约十多个版本向上工作,但您可能需要将其他版本放入项目中以便方便。