检测到的重复键:' x'。这可能会导致更新错误。在VUEJS数据级搜索中
在我的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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
单用户的示例数据具有重复的
ID
cetide> cetidud_matrix
数组(第二和第11个记录均为443)中的值,这可能会在
中引起问题。 v-for
循环(在其中没有任何:key
实际上)或在其他任何位置
certifs_matrix
记录都在使用复合键合并 而循环播放两个字段的值生成唯一的钥匙
来尝试确保前端上唯一键的方法是将组合(有点像复合键索引)作为
$ {id} - $ {matrix_status}
如果那样组合是保持独特的。使用循环迭代索引作为复合后缀来生成唯一密钥
如果没有其他字段值可以组合以确保 unique 键 keys
vor
,则 代码> $ {id} - $ {index} 可用于生成唯一键 - eg:将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
laravel docs -hersers -str订购uuid
laravel docs-迁移 - UUID列类型
更新
基于反馈通过评论
为了确保通过控制器的响应发送 unique 用户记录,请通过
$ users
通过unique> unique> unique()
方法过滤出重复记录。在Collection
上The sample data for single user has duplicate
id
values incertificate_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)Or at any other place where
certificate_matrix
records are being looped overUsing 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:Using uuid as unique key
Another way is to add a
uuid
column on the database tables and then use theuuid
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/persistedLaravel Docs - Helpers - Str Ordered Uuid
Laravel Docs - Migrations - Uuid Column Type
Laravel Docs - Uuid - Validation Rule
Update
Based on feedback via comment
To ensure only unique user records being sent via response from the controller, filter out duplicate records for the
$users
collection viaunique()
method available onCollection
错误消息告诉您您有重复的内容,并且当用户的
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 aprimary 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.