检测到的重复键:' x'。这可能会导致更新错误。在VUEJS数据级搜索中

发布于 2025-01-30 18:07:31 字数 22161 浏览 0 评论 0 原文

在我的Laravel Vue应用程序中,我在vue组件(Department-user-list.vue)中使用一些过滤器进行了遵循数据。

<template>
    <div>
        <cs-card
            :cardButton="false"
            :title="`Team members`"
        >
            <template slot="header-action">
                <div class="inline-block mr-4" direction-from="top">
                    <open-overlay identifier="corporateInviteEmployeeToDepartmentModal">
                        <cs-button size="small" variant="secondary">
                            Invite team member
                        </cs-button>
                    </open-overlay>
                </div>
                <div class="inline-block" direction-from="top">
                    <cs-button @click="redirectToAssignation" size="small">
                        Assign team member
                    </cs-button>
                </div>
            </template>
            <Datatable
                v-model="selectedForAction"
                :data="dataset"
                :headers="headers"
                :is-loading="isLoading"
                :has-action-bar-column="true"
                :key-id="`id`"
                :search-panel="{placeholder: 'Search team member...'}"
                @change="handlePaginationChange"
                @paginate="loadDepartmentEmployees"
            >
                <!--Filter Slot-->
                <template v-slot:filters>
                    <!--Nationality filter-->
                    <div class="w-2/12 pl-4 h-auto">
                        <cs-multiple-select
                            v-model="nationalitiesFilter"
                            :options="countries"
                            key-id="id"
                            label="name"
                            name="nationality"
                            placeholder="Nationality"
                        >
                        </cs-multiple-select>
                    </div>
                    <!--Certificate Status filter-->
                    <div class="w-6/12 pl-4 h-auto">
                        <cs-multiple-select
                            v-model="certificateStatusFilter"
                            :options="certificateStatus"
                            name="certificateStatusFilter"
                            placeholder="Qualification status"
                            @input="loadDepartmentEmployees"
                        />
                    </div>
                    <!--Matrix Status filter-->
                    <div class="w-4/12 pl-4 h-auto">
                        <cs-multiple-select
                            v-model="matrixStatusFilter"
                            :options="matrixStatus"
                            key-id="value"
                            label="label"
                            name="matrixStatusFilter"
                            placeholder="Matrix status"
                            @input="loadDepartmentEmployees"
                        />
                    </div>
                     <!--Employee Type  filter-->
                        <div class="w-4/12 pl-4 h-auto">
                            <cs-multiple-select
                                v-model="selectedEmployeeTypes"
                                :options="employeeType"
                                key-id="value"
                                label="label"
                                name="selectedEmployeeTypes"
                                placeholder="Employee type"
                                @input="loadDepartmentEmployees"
                            >
                            </cs-multiple-select>
                        </div>
                </template>

                <!--Table Header-->
                <template v-slot:header.country="{ header}">
                    <span class="material-icons-outlined">language</span>
                </template>

                <!--Table Body-->
                <template v-slot:item.name="{ item }">
                    <div class="flex items-center cursor-pointer">
                        <div class="rounded-full w-8 h-8 mr-4 overflow-hidden">
                            <img :src="item.profile_image[0].url" alt=""
                                 class="w-full h-full object-cover">
                        </div>
                        <a :href="employeeDetailRoute(item)">
                            <span class="text-certstyle-titles font-bold leading-loose">{{ item.name }}</span>
                        </a>
                        <span
                            v-if="item.is_subcontractor && item.company_name"
                            :title="item.company_name"
                            class="text-certstyle-text-light bg-certstyle-background flex font-semibold cursor-help  text-xs rounded mx-2 py-1 px-2"
                        >
                            {{ item.company_name.substring(0,10) }}
                             <span v-if="item.company_name.length > 10">...</span>
                        </span>
                    </div>
                </template>
                <template v-slot:item.job_title="{ item }">
                    {{ item.current_jobtitle || item.department_jobtitle }}
                </template>
                <template v-slot:item.country="{ item }">
                <span v-if="item.country" class="font-normal">
                    <country-flag width="w-5" :country-code="item.country.country_code"></country-flag>
                </span>
                </template>
                <template v-slot:item.certificate_status="{ item }">
                    <div class="status--summary--component inline-block mr-2 relative"
                         @click="getValidityStatus(item.certificate_matrix) !== 'all valid' &&
                            getValidityStatus(item.certificate_matrix) !== '-'
                             ? openCertificatesModal(item) : null
                         ">
                        <label :class="getValidityStatusClass(item.certificate_matrix)" class="badge">
                            {{ getValidityStatus(item.certificate_matrix) }}
                        </label>
                    </div>
                </template>
                <template v-slot:item.matrix_status="{ item }">
                    <div class="status--summary--component inline-block mr-2 relative"
                         @click="getMatrixStatus(item.certificate_matrix) === 'non compliant'
                            ? openCertificatesModal(item)
                            : null
                         ">
                        <label :class="getMatrixStatusClass(item.certificate_matrix)" class="badge">
                            {{ getMatrixStatus(item.certificate_matrix) }}
                        </label>
                    </div>
                </template>
                <template v-slot:actionItems="slotProps">
                    <DatatableActionbarItem
                        :slot-props="slotProps"
                        identifier="removeConfirmationModal"
                        label="Remove"
                        variant="danger"
                    />
                </template>
                <template v-slot:rowActionItems="slotProps">
                    <DatatableActionbarItem
                        icon=""
                        label="Contact details"
                        @click.native="openContactDetailsModal(slotProps.item)"
                        :slot-props="slotProps"
                    />
                </template>
            </Datatable>


            <modal-md
                v-if="selectedEmployee !== null"
                :options="{ useDefaultContentStyling: false }"
                      :identifier="`statusSummaryComponent`">
                <template slot="modal_title">
                    Qualifications
                    <span v-if="selectedEmployee !== null && selectedEmployee !== undefined">
                            {{ selectedEmployee.name }}
                        </span>
                </template>


                <div class="bg-white" slot="modal_content">
                    <div
                        class="flex items-center justify-between text-certstyle-text-light bg-white border-certstyle-border border-b text-sm py-2 px-10">
                        <cs-dashboard-table-header-item-unstyled :item="`statusSummaryCertificateTitle`">
                            <p>Qualification</p>
                        </cs-dashboard-table-header-item-unstyled>

                        <cs-dashboard-table-header-item-unstyled :item="`statusSummaryCertificateStatus`">
                            <p>Validity Status</p>
                        </cs-dashboard-table-header-item-unstyled>

                        <cs-dashboard-table-header-item-unstyled :item="`statusSummaryMatrixStatus`">
                            <p>Matrix Status</p>
                        </cs-dashboard-table-header-item-unstyled>

                    </div>

                    <!--Certificates-->
                    <div class="text-certstyle-titles">
                        <div v-for="certificate in selectedEmployee.certificate_matrix"
                             v-if="selectedEmployee.certificate_matrix.length > 0"
                             class="table--row flex items-center justify-between border-certstyle-border last:border-b-0 border-b px-10 py-4">
                            <!-- Title -->
                            <cs-dashboard-table-item-unstyled
                                class="w-1/2"
                                :item="`statusSummaryCertificateTitle`">
                                <p :title="certificate.title" class=" ">
                                    {{ certificate.title | limitString(30, '...') }}
                                </p>
                            </cs-dashboard-table-item-unstyled>

                            <cs-dashboard-table-item-unstyled class="w-32" :item="`statusSummaryCertificateStatus`">
                                <div class="flex items-center justify-start w-full">
                                    <!--Expired styling-->
                                    <label v-if="certificate.matrix_status === 0"
                                           class="badge badge-danger">
                                        -
                                    </label>

                                    <!--Expires styling-->
                                    <label v-if="certificate.matrix_status &&  certificate.expired === 1"
                                           class="badge badge-danger">
                                        expired
                                    </label>
                                    <!--Expires styling-->
                                    <label v-if="certificate.matrix_status &&  certificate.expire_soon === 1"
                                           class="badge badge-danger">
                                        expires soon
                                    </label>

                                    <!--Active styling-->
                                    <label
                                        v-if="certificate.matrix_status &&  certificate.expire_soon === 0 && certificate.expired === 0"
                                        class="badge badge-success">
                                        active
                                    </label>
                                </div>
                            </cs-dashboard-table-item-unstyled>

                            <cs-dashboard-table-item-unstyled
                                class="w-32"
                                :item="`statusSummaryMatrixStatus`">
                                <!--Active styling-->
                                <label v-if="certificate.matrix_status"
                                       class="badge badge-success">
                                    compliant
                                </label>
                                <label v-else
                                       class="badge badge-danger">
                                    non-compliant
                                </label>
                            </cs-dashboard-table-item-unstyled>
                        </div>
                        <div v-else
                             class="table--row flex items-center justify-between border-certstyle-border last:border-b-0 border-b px-10 py-4">
                            <cs-dashboard-table-item-unstyled
                                class="w-1/2"
                                :item="`statusSummaryCertificateTitle`">
                                No certificates found
                            </cs-dashboard-table-item-unstyled>
                            <cs-dashboard-table-item-unstyled class="w-32"
                                                              :item="`statusSummaryCertificateStatus`">
                            </cs-dashboard-table-item-unstyled>
                            <cs-dashboard-table-item-unstyled
                                class="w-32"
                                :item="`statusSummaryMatrixStatus`">
                            </cs-dashboard-table-item-unstyled>
                        </div>
                    </div>
                </div>
            </modal-md>
        </cs-card>

        <contact-details
            v-if="userToShowContactDetails"
            :user="userToShowContactDetails"
        />

        <add-employee-modal
            :countries="countries"
            :identifier="`addEmployeeModal`"
            :invite-modal-title="`Invite to department`"
            :suggestion-url="userSuggestionApiURL"
            :title="`Assign to ${department ? department.name: ''}`"
            @inviteEmployees="handleInvitedEmployees"
            @selectEmployee="addEmployeeToDepartment"
            @removeEmployee="handleRemoveEmployee"
        />

        <cs-confirmation-modal
            v-if="checkRole(['admin', 'planner'])"
            @proceed="handleRemoveEmployee"
            identifier="removeConfirmationModal">
            <div class="text-certstyle-titles font-normal" slot="content">
                Removing employees from this department can not be undo.
            </div>

            <div slot="cancelButton"
                 class="cursor-pointer hover:bg-certstyle-background border border-certstyle-border rounded px-6 py-2 text-certstyle-text-light mr-4">
                Cancel
            </div>

            <cs-button slot="proceedButton">
                Remove
            </cs-button>
        </cs-confirmation-modal>
    </div>

</template>

此列表和过滤器正常工作,但是当我尝试通过键入名称来搜索用户时,它一直给我带来以下错误,

检测到的重复键:'1025'。这可能会导致更新错误。

中找到

----&gt;在Resources/js/组件/可重复使用/datatable/datatable.vue 在Resources/js/组件/可重复使用/cscard.vue中 在Resources/JS/组件/仪表板/社区/部门/单部/部门 - 用户list.vue

但是,当我尝试通过其他一些参数过滤列表时,它们会被过滤而不会出错。

我正在努力在这里找到我做错了什么。...

更新

以下是我的未过滤的JSON数据,用于单个用户

 {
      "id": 1038,
      "unique_id": "0a3938c1-07d5-3884-9df0-a8fe3201a3e5",
      "first_name": "Mango",
      "last_name": "F1",
      "job_title": null,
      "email": "[email protected]",
      "phone_number": null,
      "phone_country_calling_code": null,
      "country_id": null,
      "company_name": null,
      "is_subcontractor": 0,
      "current_jobtitle": "Deck Foreman",
      "department_jobtitle": "Rigging Engineers",
      "language": "en",
      "email_verified_at": "2022-04-12T12:47:55.000000Z",
      "gender": null,
      "state": null,
      "postal_code": null,
      "house_number": null,
      "street": null,
      "city": null,
      "date_of_birth": null,
      "city_of_birth": null,
      "emergency_number": null,
      "opt_in": null,
      "created_at": "2022-04-12T12:46:34.000000Z",
      "updated_at": "2022-04-12T12:47:55.000000Z",
      "emergency_number_country_calling_code": null,
      "deleted_at": null,
      "has_ip_restriction": 0,
      "address": null,
      "latitude": null,
      "longitude": null,
      "place_id": null,
      "bouwpas_worker_id": null,
      "bouwpas_certificate_id": null,
      "certificate_matrix": [
        {
          "id": 463,
          .....
        }
      ]
    },

遵循我的控制器函数,

public function index($locale, Company $company, Department $department, Request $request)
    {
        $this->authorize('viewUsers', [Department::class, $company, $department]);

        $users = $department->usersWithSubcontractors()
            //            ->notApiUser()
            ->select(
                'users.id',
                'unique_id',
                'first_name',
                'last_name',
                'job_title',
                'email',
                'phone_number',
                'unique_id',
                'phone_country_calling_code',
                'country_id',
                'company_name',
                'is_subcontractor',
            )->addSelect([
                'current_jobtitle' => JobTitle::selectRaw('IFNULL(project_specific_job_titles.title, job_titles.title)')
                    ->join('project_track_records', 'project_track_records.user_id', 'users.id', 'inner')
                    ->join('project_specific_job_titles', 'project_track_records.project_specific_job_title_id', 'project_specific_job_titles.id', 'inner')
                    ->whereColumn('job_titles.id', 'project_specific_job_titles.job_title_id')
                    ->whereDate('project_track_records.start_date', '<=', Carbon::now())
                    ->whereDate('project_track_records.end_date', '>=', Carbon::now())
                    ->limit(1),
                'department_jobtitle' => JobTitle::selectRaw('title')->whereColumn('job_titles.id', 'department_user.job_title_id'),
            ])->when(request('q'), function ($q) {
                $q->where(function ($q) {
                    $q->whereRaw("CONCAT_WS(' ', `first_name`, `last_name`) like '%" . request('q') . "%'");
                });
            })->when($request->get('employeeType'), function ($q) use ($request) {
                $q->whereIn('users.is_subcontractor', $request->get('employeeType'));
            })->paginate(\request('per_page', config('repository.pagination.limit')));

        $users->load('country');
        $users->append(['profile_image']);
        $users->makeVisible(['unique_id']);

        $users->map(fn ($item) => $item->certificate_matrix = (new GetCertificationMatrixQueryAction())->execute($item->id, $department->id));

        if ($request->filled('certificateStatus')) {
            $valid = in_array('valid', $request->get('certificateStatus'));
            $expire_soon = in_array('expire soon', $request->get('certificateStatus'));
            $expired = in_array('expired', $request->get('certificateStatus'));

            if ($valid) $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status && !$certificate->expire_soon && !$certificate->expired)->count() === $item->certificate_matrix->count())->values());
            if ($expire_soon && !$expired) $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status && $certificate->expire_soon)->count() > 0)->values());
            if ($expired && !$expire_soon) $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status && $certificate->expired)->count() > 0)->values());
        }

        if ($request->filled('matrixStatus')) {
            $compliant = in_array('compliant', $request->get('matrixStatus'));
            $non_compliant = in_array('non-compliant', $request->get('matrixStatus'));

            if ($non_compliant && !$compliant)
                $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status === 0 || $certificate->expire_soon || !$certificate->expired)->count() > 0)->values());

            if ($compliant && !$non_compliant)
                $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status && !$certificate->expire_soon && !$certificate->expired)->count() == $item->certificate_matrix->count())->values());
        }
        return response()->json($users);
    }

In my laravel vue application I have following datatable with some filters in a vue component(department-user-list.vue).

<template>
    <div>
        <cs-card
            :cardButton="false"
            :title="`Team members`"
        >
            <template slot="header-action">
                <div class="inline-block mr-4" direction-from="top">
                    <open-overlay identifier="corporateInviteEmployeeToDepartmentModal">
                        <cs-button size="small" variant="secondary">
                            Invite team member
                        </cs-button>
                    </open-overlay>
                </div>
                <div class="inline-block" direction-from="top">
                    <cs-button @click="redirectToAssignation" size="small">
                        Assign team member
                    </cs-button>
                </div>
            </template>
            <Datatable
                v-model="selectedForAction"
                :data="dataset"
                :headers="headers"
                :is-loading="isLoading"
                :has-action-bar-column="true"
                :key-id="`id`"
                :search-panel="{placeholder: 'Search team member...'}"
                @change="handlePaginationChange"
                @paginate="loadDepartmentEmployees"
            >
                <!--Filter Slot-->
                <template v-slot:filters>
                    <!--Nationality filter-->
                    <div class="w-2/12 pl-4 h-auto">
                        <cs-multiple-select
                            v-model="nationalitiesFilter"
                            :options="countries"
                            key-id="id"
                            label="name"
                            name="nationality"
                            placeholder="Nationality"
                        >
                        </cs-multiple-select>
                    </div>
                    <!--Certificate Status filter-->
                    <div class="w-6/12 pl-4 h-auto">
                        <cs-multiple-select
                            v-model="certificateStatusFilter"
                            :options="certificateStatus"
                            name="certificateStatusFilter"
                            placeholder="Qualification status"
                            @input="loadDepartmentEmployees"
                        />
                    </div>
                    <!--Matrix Status filter-->
                    <div class="w-4/12 pl-4 h-auto">
                        <cs-multiple-select
                            v-model="matrixStatusFilter"
                            :options="matrixStatus"
                            key-id="value"
                            label="label"
                            name="matrixStatusFilter"
                            placeholder="Matrix status"
                            @input="loadDepartmentEmployees"
                        />
                    </div>
                     <!--Employee Type  filter-->
                        <div class="w-4/12 pl-4 h-auto">
                            <cs-multiple-select
                                v-model="selectedEmployeeTypes"
                                :options="employeeType"
                                key-id="value"
                                label="label"
                                name="selectedEmployeeTypes"
                                placeholder="Employee type"
                                @input="loadDepartmentEmployees"
                            >
                            </cs-multiple-select>
                        </div>
                </template>

                <!--Table Header-->
                <template v-slot:header.country="{ header}">
                    <span class="material-icons-outlined">language</span>
                </template>

                <!--Table Body-->
                <template v-slot:item.name="{ item }">
                    <div class="flex items-center cursor-pointer">
                        <div class="rounded-full w-8 h-8 mr-4 overflow-hidden">
                            <img :src="item.profile_image[0].url" alt=""
                                 class="w-full h-full object-cover">
                        </div>
                        <a :href="employeeDetailRoute(item)">
                            <span class="text-certstyle-titles font-bold leading-loose">{{ item.name }}</span>
                        </a>
                        <span
                            v-if="item.is_subcontractor && item.company_name"
                            :title="item.company_name"
                            class="text-certstyle-text-light bg-certstyle-background flex font-semibold cursor-help  text-xs rounded mx-2 py-1 px-2"
                        >
                            {{ item.company_name.substring(0,10) }}
                             <span v-if="item.company_name.length > 10">...</span>
                        </span>
                    </div>
                </template>
                <template v-slot:item.job_title="{ item }">
                    {{ item.current_jobtitle || item.department_jobtitle }}
                </template>
                <template v-slot:item.country="{ item }">
                <span v-if="item.country" class="font-normal">
                    <country-flag width="w-5" :country-code="item.country.country_code"></country-flag>
                </span>
                </template>
                <template v-slot:item.certificate_status="{ item }">
                    <div class="status--summary--component inline-block mr-2 relative"
                         @click="getValidityStatus(item.certificate_matrix) !== 'all valid' &&
                            getValidityStatus(item.certificate_matrix) !== '-'
                             ? openCertificatesModal(item) : null
                         ">
                        <label :class="getValidityStatusClass(item.certificate_matrix)" class="badge">
                            {{ getValidityStatus(item.certificate_matrix) }}
                        </label>
                    </div>
                </template>
                <template v-slot:item.matrix_status="{ item }">
                    <div class="status--summary--component inline-block mr-2 relative"
                         @click="getMatrixStatus(item.certificate_matrix) === 'non compliant'
                            ? openCertificatesModal(item)
                            : null
                         ">
                        <label :class="getMatrixStatusClass(item.certificate_matrix)" class="badge">
                            {{ getMatrixStatus(item.certificate_matrix) }}
                        </label>
                    </div>
                </template>
                <template v-slot:actionItems="slotProps">
                    <DatatableActionbarItem
                        :slot-props="slotProps"
                        identifier="removeConfirmationModal"
                        label="Remove"
                        variant="danger"
                    />
                </template>
                <template v-slot:rowActionItems="slotProps">
                    <DatatableActionbarItem
                        icon=""
                        label="Contact details"
                        @click.native="openContactDetailsModal(slotProps.item)"
                        :slot-props="slotProps"
                    />
                </template>
            </Datatable>


            <modal-md
                v-if="selectedEmployee !== null"
                :options="{ useDefaultContentStyling: false }"
                      :identifier="`statusSummaryComponent`">
                <template slot="modal_title">
                    Qualifications
                    <span v-if="selectedEmployee !== null && selectedEmployee !== undefined">
                            {{ selectedEmployee.name }}
                        </span>
                </template>


                <div class="bg-white" slot="modal_content">
                    <div
                        class="flex items-center justify-between text-certstyle-text-light bg-white border-certstyle-border border-b text-sm py-2 px-10">
                        <cs-dashboard-table-header-item-unstyled :item="`statusSummaryCertificateTitle`">
                            <p>Qualification</p>
                        </cs-dashboard-table-header-item-unstyled>

                        <cs-dashboard-table-header-item-unstyled :item="`statusSummaryCertificateStatus`">
                            <p>Validity Status</p>
                        </cs-dashboard-table-header-item-unstyled>

                        <cs-dashboard-table-header-item-unstyled :item="`statusSummaryMatrixStatus`">
                            <p>Matrix Status</p>
                        </cs-dashboard-table-header-item-unstyled>

                    </div>

                    <!--Certificates-->
                    <div class="text-certstyle-titles">
                        <div v-for="certificate in selectedEmployee.certificate_matrix"
                             v-if="selectedEmployee.certificate_matrix.length > 0"
                             class="table--row flex items-center justify-between border-certstyle-border last:border-b-0 border-b px-10 py-4">
                            <!-- Title -->
                            <cs-dashboard-table-item-unstyled
                                class="w-1/2"
                                :item="`statusSummaryCertificateTitle`">
                                <p :title="certificate.title" class=" ">
                                    {{ certificate.title | limitString(30, '...') }}
                                </p>
                            </cs-dashboard-table-item-unstyled>

                            <cs-dashboard-table-item-unstyled class="w-32" :item="`statusSummaryCertificateStatus`">
                                <div class="flex items-center justify-start w-full">
                                    <!--Expired styling-->
                                    <label v-if="certificate.matrix_status === 0"
                                           class="badge badge-danger">
                                        -
                                    </label>

                                    <!--Expires styling-->
                                    <label v-if="certificate.matrix_status &&  certificate.expired === 1"
                                           class="badge badge-danger">
                                        expired
                                    </label>
                                    <!--Expires styling-->
                                    <label v-if="certificate.matrix_status &&  certificate.expire_soon === 1"
                                           class="badge badge-danger">
                                        expires soon
                                    </label>

                                    <!--Active styling-->
                                    <label
                                        v-if="certificate.matrix_status &&  certificate.expire_soon === 0 && certificate.expired === 0"
                                        class="badge badge-success">
                                        active
                                    </label>
                                </div>
                            </cs-dashboard-table-item-unstyled>

                            <cs-dashboard-table-item-unstyled
                                class="w-32"
                                :item="`statusSummaryMatrixStatus`">
                                <!--Active styling-->
                                <label v-if="certificate.matrix_status"
                                       class="badge badge-success">
                                    compliant
                                </label>
                                <label v-else
                                       class="badge badge-danger">
                                    non-compliant
                                </label>
                            </cs-dashboard-table-item-unstyled>
                        </div>
                        <div v-else
                             class="table--row flex items-center justify-between border-certstyle-border last:border-b-0 border-b px-10 py-4">
                            <cs-dashboard-table-item-unstyled
                                class="w-1/2"
                                :item="`statusSummaryCertificateTitle`">
                                No certificates found
                            </cs-dashboard-table-item-unstyled>
                            <cs-dashboard-table-item-unstyled class="w-32"
                                                              :item="`statusSummaryCertificateStatus`">
                            </cs-dashboard-table-item-unstyled>
                            <cs-dashboard-table-item-unstyled
                                class="w-32"
                                :item="`statusSummaryMatrixStatus`">
                            </cs-dashboard-table-item-unstyled>
                        </div>
                    </div>
                </div>
            </modal-md>
        </cs-card>

        <contact-details
            v-if="userToShowContactDetails"
            :user="userToShowContactDetails"
        />

        <add-employee-modal
            :countries="countries"
            :identifier="`addEmployeeModal`"
            :invite-modal-title="`Invite to department`"
            :suggestion-url="userSuggestionApiURL"
            :title="`Assign to ${department ? department.name: ''}`"
            @inviteEmployees="handleInvitedEmployees"
            @selectEmployee="addEmployeeToDepartment"
            @removeEmployee="handleRemoveEmployee"
        />

        <cs-confirmation-modal
            v-if="checkRole(['admin', 'planner'])"
            @proceed="handleRemoveEmployee"
            identifier="removeConfirmationModal">
            <div class="text-certstyle-titles font-normal" slot="content">
                Removing employees from this department can not be undo.
            </div>

            <div slot="cancelButton"
                 class="cursor-pointer hover:bg-certstyle-background border border-certstyle-border rounded px-6 py-2 text-certstyle-text-light mr-4">
                Cancel
            </div>

            <cs-button slot="proceedButton">
                Remove
            </cs-button>
        </cs-confirmation-modal>
    </div>

</template>

This list and the filters works fine but when I try to search a user by typing their names, it kept giving me following error,

Duplicate keys detected: '1025'. This may cause an update error.

found in

---> at resources/js/components/reusable/datatable/Datatable.vue
at resources/js/components/reusable/csCard.vue
at resources/js/components/dashboard/communities/department/one-departments/department-user-list.vue

But when I try to filter the list by some other param, they get filtered without any error.

I'm struggling to find what I'm doing wrong here....

UPDATE

following is my non-filtered json data for a single user

 {
      "id": 1038,
      "unique_id": "0a3938c1-07d5-3884-9df0-a8fe3201a3e5",
      "first_name": "Mango",
      "last_name": "F1",
      "job_title": null,
      "email": "[email protected]",
      "phone_number": null,
      "phone_country_calling_code": null,
      "country_id": null,
      "company_name": null,
      "is_subcontractor": 0,
      "current_jobtitle": "Deck Foreman",
      "department_jobtitle": "Rigging Engineers",
      "language": "en",
      "email_verified_at": "2022-04-12T12:47:55.000000Z",
      "gender": null,
      "state": null,
      "postal_code": null,
      "house_number": null,
      "street": null,
      "city": null,
      "date_of_birth": null,
      "city_of_birth": null,
      "emergency_number": null,
      "opt_in": null,
      "created_at": "2022-04-12T12:46:34.000000Z",
      "updated_at": "2022-04-12T12:47:55.000000Z",
      "emergency_number_country_calling_code": null,
      "deleted_at": null,
      "has_ip_restriction": 0,
      "address": null,
      "latitude": null,
      "longitude": null,
      "place_id": null,
      "bouwpas_worker_id": null,
      "bouwpas_certificate_id": null,
      "certificate_matrix": [
        {
          "id": 463,
          .....
        }
      ]
    },

Following is my controller function,

public function index($locale, Company $company, Department $department, Request $request)
    {
        $this->authorize('viewUsers', [Department::class, $company, $department]);

        $users = $department->usersWithSubcontractors()
            //            ->notApiUser()
            ->select(
                'users.id',
                'unique_id',
                'first_name',
                'last_name',
                'job_title',
                'email',
                'phone_number',
                'unique_id',
                'phone_country_calling_code',
                'country_id',
                'company_name',
                'is_subcontractor',
            )->addSelect([
                'current_jobtitle' => JobTitle::selectRaw('IFNULL(project_specific_job_titles.title, job_titles.title)')
                    ->join('project_track_records', 'project_track_records.user_id', 'users.id', 'inner')
                    ->join('project_specific_job_titles', 'project_track_records.project_specific_job_title_id', 'project_specific_job_titles.id', 'inner')
                    ->whereColumn('job_titles.id', 'project_specific_job_titles.job_title_id')
                    ->whereDate('project_track_records.start_date', '<=', Carbon::now())
                    ->whereDate('project_track_records.end_date', '>=', Carbon::now())
                    ->limit(1),
                'department_jobtitle' => JobTitle::selectRaw('title')->whereColumn('job_titles.id', 'department_user.job_title_id'),
            ])->when(request('q'), function ($q) {
                $q->where(function ($q) {
                    $q->whereRaw("CONCAT_WS(' ', `first_name`, `last_name`) like '%" . request('q') . "%'");
                });
            })->when($request->get('employeeType'), function ($q) use ($request) {
                $q->whereIn('users.is_subcontractor', $request->get('employeeType'));
            })->paginate(\request('per_page', config('repository.pagination.limit')));

        $users->load('country');
        $users->append(['profile_image']);
        $users->makeVisible(['unique_id']);

        $users->map(fn ($item) => $item->certificate_matrix = (new GetCertificationMatrixQueryAction())->execute($item->id, $department->id));

        if ($request->filled('certificateStatus')) {
            $valid = in_array('valid', $request->get('certificateStatus'));
            $expire_soon = in_array('expire soon', $request->get('certificateStatus'));
            $expired = in_array('expired', $request->get('certificateStatus'));

            if ($valid) $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status && !$certificate->expire_soon && !$certificate->expired)->count() === $item->certificate_matrix->count())->values());
            if ($expire_soon && !$expired) $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status && $certificate->expire_soon)->count() > 0)->values());
            if ($expired && !$expire_soon) $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status && $certificate->expired)->count() > 0)->values());
        }

        if ($request->filled('matrixStatus')) {
            $compliant = in_array('compliant', $request->get('matrixStatus'));
            $non_compliant = in_array('non-compliant', $request->get('matrixStatus'));

            if ($non_compliant && !$compliant)
                $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status === 0 || $certificate->expire_soon || !$certificate->expired)->count() > 0)->values());

            if ($compliant && !$non_compliant)
                $users->setCollection($users->filter(fn ($item) => $item->certificate_matrix->filter(fn ($certificate) => $certificate->matrix_status && !$certificate->expire_soon && !$certificate->expired)->count() == $item->certificate_matrix->count())->values());
        }
        return response()->json($users);
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

唠甜嗑 2025-02-06 18:07:31

单用户的示例数据具有重复的 ID cetide> cetidud_matrix 数组(第二和第11个记录均为443)中的值,

这可能会在中引起问题。 v-for 循环(在其中没有任何:key 实际上)

<!--Certificates-->
<div class="text-certstyle-titles">
    <div v-for="certificate in selectedEmployee.certificate_matrix"
         v-if="selectedEmployee.certificate_matrix.length > 0"
         class="table--row flex items-center justify-between border-certstyle-border last:border-b-0 border-b px-10 py-4">

或在其他任何位置 certifs_matrix 记录都在

使用复合键合并 而循环播放两个字段的值生成唯一的钥匙

来尝试确保前端上唯一键的方法是将组合(有点像复合键索引)作为 $ {id} - $ {matrix_status} 如果那样组合是保持独特的。

使用循环迭代索引作为复合后缀来生成唯一密钥

如果没有其他字段值可以组合以确保 unique 键 keys vor ,则 代码> $ {id} - $ {index} 可用于生成唯一键 - eg:

<div v-for="(certificate, index) in selectedEmployee.certificate_matrix"
     :key="`${certificate.id}-${index}`" //To ensure uniqueness of key
     v-if="selectedEmployee.certificate_matrix.length > 0"
     class="table--row flex items-center justify-between border-certstyle-border last:border-b-0 border-b px-10 py-4">
将uuid用作唯一密钥,

另一种方法是在数据库表和数据库表和然后,将 uuid 用作&lt; dataTable/&gt; 组件标记中的键,其中包括子组件,其中:key :key-id>:key-id> 使用。

Laravel使通过(String)str :: drounduuid(); 以及具有 $ table-&gt; uuid('uId') - &gt; index非常容易地生成uuid v4-uuids-uuids str :: string :: ()迁移文件的列类型。

当创建/persisted

// In any model class which has a uuid column
public static function booted()
{
    static::creating(function ($model) {
        $model->uid = Str::orderedUuid()->toString();
    });
}

laravel docs -hersers -str订购uuid

laravel docs-迁移 - UUID列类型

更新

基于反馈通过评论

感谢您的回答,我已使用正确的后端控制器更新了问题。 ID重复的原因是一个用户可以拥有多个部门。因此,我的雄辩给了我一些结果,并带有多个用户ID的结果。当我尝试按User.id将结果分组时,它给了我500个错误,并且我需要将用户iD作为密钥而不是传递UUID,因为ID已用于其他功能,例如用户删除和所有功能。 ..任何方法可以将后端的结果分组以仅获得唯一的用户ID?

为了确保通过控制器的响应发送 unique 用户记录,请通过 $ users 通过 unique> unique> unique()方法过滤出重复记录。在 Collection

//...method code
$users->setCollection($users->unique('id')->values());

return response()->json($users);

The sample data for single user has duplicate id values in certificate_matrix array (2nd and 11th record both have id of 443)

This would probably be causing an issue in the v-for loop at (where you do not have any :key actually)

<!--Certificates-->
<div class="text-certstyle-titles">
    <div v-for="certificate in selectedEmployee.certificate_matrix"
         v-if="selectedEmployee.certificate_matrix.length > 0"
         class="table--row flex items-center justify-between border-certstyle-border last:border-b-0 border-b px-10 py-4">

Or at any other place where certificate_matrix records are being looped over

Using composite key combining value of two fields to generate unique key

One way to try to ensure unique keys on frontend is to have a combination (kind of like composite key index) as ${id}-${matrix_status} if that combination is to remain unique.

Using loop iteration index as composite suffix to generate unique key

If there is no other field value which can be combined to ensure unique keys for child nodes within v-for then the ${id}-${index} can be used to generate unique keys - eg:

<div v-for="(certificate, index) in selectedEmployee.certificate_matrix"
     :key="`${certificate.id}-${index}`" //To ensure uniqueness of key
     v-if="selectedEmployee.certificate_matrix.length > 0"
     class="table--row flex items-center justify-between border-certstyle-border last:border-b-0 border-b px-10 py-4">
Using uuid as unique key

Another way is to add a uuid column on the database tables and then use the uuid as key in the <DataTable /> component markup including subcomponents where :key or :key-id are used.

Laravel makes it very easy to generate Uuid v4 - uuids via (string) Str::orderedUuid(); And also has $table->uuid('uid')->index() column type for migration files.

Can even have uid stored when a new model record is being created/persisted

// In any model class which has a uuid column
public static function booted()
{
    static::creating(function ($model) {
        $model->uid = Str::orderedUuid()->toString();
    });
}

Laravel Docs - Helpers - Str Ordered Uuid

Laravel Docs - Migrations - Uuid Column Type

Laravel Docs - Uuid - Validation Rule

Update

Based on feedback via comment

Thank you for your answer, I have updated the question with the correct backend controller. The reason for id duplication is one user can have multiple departments. Because of that my eloquent gives me results with multiple user id's for some results. When I tried to group the results by user.id, it gives me an 500 error, and I need to pass the user.id as the key rather than passing uuid since the id has used for other functions, like user deletion and all... Any way to group the result from the backend to get only unique user ids?

To ensure only unique user records being sent via response from the controller, filter out duplicate records for the $users collection via unique() method available on Collection

//...method code
$users->setCollection($users->unique('id')->values());

return response()->json($users);
北风几吹夏 2025-02-06 18:07:31

错误消息告诉您您有重复的内容,并且当用户的 ID 唯一时,您对获取此类错误消息的原因感到困惑(可能是主键 )。但是,重要的是要注意,您将用户加入部门,如果用户有多个部门,那么您将多次获得该用户。您可以将结果分组以解决问题。

The error message tells you that you have duplicates and you are confused about the reason of getting such an error message, when the id of the user is unique (probably a primary key). However, it is important to note that you load your users with departments and if a user has multiple departments, then you will get that user multiple times. You can group the results to solve the issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文