[update] 市场法规清单联调

This commit is contained in:
lideqin
2024-07-02 12:07:17 +08:00
parent 8cc3afa17f
commit 7eff7ddf7a
7 changed files with 159 additions and 78 deletions
+2 -1
View File
@@ -132,7 +132,8 @@ const getFileInfo = (params) => getAction('/sys/oss/file/queryById', params)
// 标准选择框,分页查询标准数据
const getStandardList = (params) => getAction('/laws/standard/common/getManyStandardSelectionBox', params)
// 市场法规清单选择框,分页查询数据(无权限) TODO 暂时用列表接口
// 市场法规清单选择框,分页查询数据(无权限)
// todo 需要换没权限的
const getMarketRegulationsList = (params) => getAction('/laws/marketStandard/page', params)
// 内部工作组,左侧树查询
-3
View File
@@ -138,8 +138,6 @@ const editStandardMasterPlan = (params) => postAction('/laws/StandardMasterPlan/
const getMarketRegulationListById = (params) => getAction('/laws/marketStandard/detail', params)
// 市场法规清单-根据id查询-无权限
const getMarketRegulationListByIdNoPerm = (params) => getAction('', params)
// 市场法规清单-根据ids获取多个清单的清单列表-用于复制
const getMarketRegulationListByIds = (params) => getAction('', params)
// 市场法规清单-新增
const marketRegulationListAdd = (params) => postAction('/laws/marketStandard/add', params)
// 市场法规清单-编辑
@@ -227,7 +225,6 @@ export {
// 市场法规清单
getMarketRegulationListById,
getMarketRegulationListByIdNoPerm,
getMarketRegulationListByIds,
marketRegulationListAdd,
marketRegulationListEdit,
marketRegulationListHistoryList
@@ -70,7 +70,9 @@ module.exports = {
securityClass: 'Security class',
listDeclaration: 'Manifest declaration',
templateName: 'Market regulation list import template',
historicalVersion: 'Historical version'
historicalVersion: 'Historical version',
standardExist: 'The standard already exists',
haveStandardExist: 'Some standards already exist'
},
// 市场清单详情列表字段
marketListField: {
@@ -71,7 +71,9 @@ module.exports = {
securityClass: '密级',
listDeclaration: '清单说明',
templateName: '市场法规清单导入模版',
historicalVersion: '历史版本'
historicalVersion: '历史版本',
standardExist: '标准已经存在',
haveStandardExist: '部分标准已存在'
},
// 市场清单详情列表字段
marketListField: {
@@ -97,6 +97,14 @@
<!--</a-tooltip>-->
</template>
<!-- 清单版本 -->
<template v-slot:manifestVersion="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? ('V' + text + '.0') : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? ('V' + text + '.0') : global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</div>
@@ -200,7 +208,7 @@ export default {
align: 'center',
width: 180,
dataIndex: 'manifestVersion',
scopedSlots: { customRender: 'text' }
scopedSlots: { customRender: 'manifestVersion' }
},
{ // 发布时间
title: this.$t('standardRegulationLibrary.marketRegulationsList.releaseTime'),
@@ -22,7 +22,7 @@
</a-form-item>
</a-col>
<!-- 清单编号 -->
<a-col :span="12" v-if="model.id">
<a-col :span="12" v-if="model.manifest.id">
<a-form-item :label="$t('standardRegulationLibrary.marketRegulationsList.listNumber')"
:labelCol="labelCol"
:wrapperCol="wrapperCol">
@@ -32,8 +32,6 @@
v-decorator="['manifestNo', validatorRules.manifestNo]" />
</a-form-item>
</a-col>
</a-row>
<a-row>
<!-- 自定义名称 -->
<a-col :span="12">
<a-form-item :label="$t('standardRegulationLibrary.marketRegulationsList.customName')"
@@ -54,15 +52,17 @@
:placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketRegulationsList.drivingPosition')" />
</a-form-item>
</a-col>
<!-- 密级 -->
<a-col :span="12">
<a-form-item :labelCol="labelCol"
:wrapperCol="wrapperCol"
:label="$t('standardRegulationLibrary.marketRegulationsList.securityClass')">
<j-dict-select-tag v-decorator="['securityLevel']"
dict-code="security_class"
:placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketRegulationsList.securityClass')" />
</a-form-item>
</a-col>
</a-row>
<!-- 密级 -->
<a-form-item :labelCol="lineLabelCol"
:wrapperCol="lineWrapperCol"
:label="$t('standardRegulationLibrary.marketRegulationsList.securityClass')">
<j-dict-select-tag v-decorator="['securityLevel']"
dict-code="security_class"
:placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketRegulationsList.securityClass')" />
</a-form-item>
<!-- 清单说明 -->
<a-form-item :labelCol="lineLabelCol"
:wrapperCol="lineWrapperCol"
@@ -70,13 +70,13 @@
<a-textarea :placeholder="$t('pleaseEnter') + $t('standardRegulationLibrary.marketRegulationsList.listDeclaration')"
:maxLength="500"
:auto-size="{ minRows: 3, maxRows: 6 }"
v-decorator="['listDeclaration']"></a-textarea>
v-decorator="['manifestDesc']"></a-textarea>
</a-form-item>
<!-- 附件 -->
<a-form-item :labelCol="lineLabelCol"
:wrapperCol="lineWrapperCol"
:label="$t('attach')">
<j-upload v-decorator="['attach']"
<j-upload v-decorator="['file']"
return-id
multiple />
</a-form-item>
@@ -87,7 +87,7 @@
<a-button type="primary" ghost :loading="loading" @click="handleNext">{{ $t('next') }}</a-button>
</div>
<template v-if="showList || model.id">
<template v-if="showList || model.manifest.id">
<!-- 市场法规清单 -->
<div class="process-part-title">{{ $t('marketRegulationsList') }}</div>
@@ -98,18 +98,18 @@
<!-- 标准编号 -->
<a-col :md="6" :sm="12">
<a-form-item :label="$t('standardNumber')">
<j-input
<a-input
:placeholder="$t('pleaseEnter') + $t('standardNumber')"
v-model="queryParam.standardNumber"></j-input>
v-model="queryParam.standardNumber"></a-input>
</a-form-item>
</a-col>
<!-- 标准名称 -->
<a-col :md="6" :sm="8">
<a-form-item :label="$t('standardName')">
<j-input
<a-input
:placeholder="$t('pleaseEnter') + $t('standardName')"
v-model="queryParam.standardName"></j-input>
v-model="queryParam.standardName"></a-input>
</a-form-item>
</a-col>
@@ -268,7 +268,7 @@ export default {
StandardSource,
loading: false,
form: this.$form.createForm(this),
model: {},
model: { manifest: {}, lists: [] },
queryParam: {},
countryOptions: [], // 国家下拉选择
labelCol: {
@@ -377,14 +377,14 @@ export default {
title: this.$t('standardRegulationLibrary.marketListField.applicableVehicleType'),
align: 'center',
width: 180,
dataIndex: 'applicableVehicle',
dataIndex: 'applicableVehicle_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 认证对象
title: this.$t('standardRegulationLibrary.marketListField.authenticationObject'),
align: 'center',
width: 180,
dataIndex: 'authenticationObject',
dataIndex: 'authenticationObject_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 认证交付物
@@ -398,63 +398,63 @@ export default {
title: this.$t('standardRegulationLibrary.marketListField.type'),
align: 'center',
width: 180,
dataIndex: 'stanardClass',
dataIndex: 'stanardClass_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 动力类型
title: this.$t('standardRegulationLibrary.marketListField.dynamicType'),
align: 'center',
width: 180,
dataIndex: 'dynamicType',
dataIndex: 'dynamicType_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 主控部门
title: this.$t('standardRegulationLibrary.marketListField.mainControlDepartment'),
align: 'center',
width: 180,
dataIndex: 'mainDept',
dataIndex: 'mainDept_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 主控部门专业模块
title: this.$t('standardRegulationLibrary.marketListField.masterControlDepartmentProfessionalModule'),
align: 'center',
width: 180,
dataIndex: 'mainDeptProfMode',
dataIndex: 'mainDeptProfMode_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 关联部门
title: this.$t('standardRegulationLibrary.marketListField.relatedDepartment'),
align: 'center',
width: 180,
dataIndex: 'associateDept',
dataIndex: 'associateDept_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 关联部门专业模块
title: this.$t('standardRegulationLibrary.marketListField.associateDepartmentSpecializedModules'),
align: 'center',
width: 180,
dataIndex: 'associateDeptProfMode',
dataIndex: 'associateDeptProfMode_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 批量限制
title: this.$t('standardRegulationLibrary.marketListField.batchRestriction'),
align: 'center',
width: 180,
dataIndex: 'batchLimit',
dataIndex: 'batchLimit_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 自动驾驶等级
title: this.$t('standardRegulationLibrary.marketListField.automaticDrivingLevel'),
align: 'center',
width: 180,
dataIndex: 'autopilotLevel',
dataIndex: 'autopilotLevel_dictText',
scopedSlots: { customRender: 'text' }
},
{ // 要求类型
title: this.$t('standardRegulationLibrary.marketListField.requirementType'),
align: 'center',
width: 180,
dataIndex: 'requireType',
dataIndex: 'requireType_dictText',
scopedSlots: { customRender: 'text' }
},
{
@@ -489,10 +489,6 @@ export default {
}
},
mounted () {
// 暂时给固定的清单编号
this.$nextTick(() => {
this.form.setFieldsValue(pick({ manifestNo: '111' }, 'manifestNo'))
})
this.getCountryOption()
if (this.$route.query.id) {
this.initData(this.$route.query.id)
@@ -508,17 +504,19 @@ export default {
},
initData (id) {
this.loading = true
getMarketRegulationListById({ manifestId: id }).then(res => {
const param = {}
param.manifestId = id
getMarketRegulationListById(param).then(res => {
if (res.success) {
this.model = Object.assign({}, res.result)
this.dataSource = JSON.parse(JSON.stringify(this.model.data.map(item => {
this.dataSource = JSON.parse(JSON.stringify(this.model.lists.map(item => {
return { ...item, uid: uidGenerator() }
})))
this.dataList = JSON.parse(JSON.stringify(this.model.data.map(item => {
this.dataList = JSON.parse(JSON.stringify(this.model.lists.map(item => {
return { ...item, uid: uidGenerator() }
})))
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model, 'country', 'manifestNo', 'customName', 'drivePosition', 'securityLevel', 'listDeclaration', 'attach'))
this.form.setFieldsValue(pick(this.model.manifest, 'country', 'manifestNo', 'customName', 'drivePosition', 'securityLevel', 'manifestDesc', 'file'))
})
}
}).finally(() => {
@@ -531,17 +529,18 @@ export default {
},
// 查询
searchQuery () {
console.log('-----this.queryParam', this.queryParam)
if (this.queryParam.standardNumber && this.queryParam.standardName) {
this.dataSource = this.dataList.filter(item => {
return item.standardNumber.indexOf(this.queryParam.standardNumber) && item.standardName.indexOf(this.queryParam.standardName)
return item.standardNumber.indexOf(this.queryParam.standardNumber) !== -1 && item.standardName.indexOf(this.queryParam.standardName) !== -1
})
} else if (this.queryParam.standardNumber) {
this.dataSource = this.dataList.filter(item => {
return item.standardNumber.indexOf(this.queryParam.standardNumber)
return item.standardNumber.indexOf(this.queryParam.standardNumber) !== -1
})
} else if (this.queryParam.standardName) {
this.dataSource = this.dataList.filter(item => {
return item.standardName.indexOf(this.queryParam.standardName)
return item.standardName.indexOf(this.queryParam.standardName) !== -1
})
} else {
this.dataSource = JSON.parse(JSON.stringify(this.dataList))
@@ -573,8 +572,8 @@ export default {
content: this.$t('deleteAData'),
onOk: () => {
this.loading = true
this.dataList.filter(item => !this.selectedRowKeys.includes(item.uid))
this.dataSource.filter(item => !this.selectedRowKeys.includes(item.uid))
this.dataList = this.dataList.filter(item => !this.selectedRowKeys.includes(item.uid))
this.dataSource = this.dataSource.filter(item => !this.selectedRowKeys.includes(item.uid))
this.reCalculatePage(this.selectedRowKeys.length)
this.onClearSelected()
this.loading = false
@@ -711,10 +710,13 @@ export default {
modalFormOk (value) {
if (!value.uid) {
// 是新增完成
if (!this.dataList.includes(i => i.standardNumber === value.standardNumber)) {
if (!this.dataList.find(i => i.standardNumber === value.standardNumber)) {
// 列表中还没有该标准
this.dataSource.unshift({ ...value, uid: uidGenerator() })
this.dataList.unshift({ ...value, uid: uidGenerator() })
} else {
// 提示标准已存在
this.$message.warning(this.$t('standardRegulationLibrary.marketRegulationsList.standardExist'))
}
} else {
// 是编辑完成
@@ -727,9 +729,12 @@ export default {
// 调取完成
async transferOk (list) {
this.loading = true
let repeatNum = 0
console.log('---list', list)
// 已经有的标准去掉,调取不重复的
for (const item of list) {
if (!this.dataList.includes(i => i.standardNumber === item.standardNumber)) {
console.log('------item', item)
if (!this.dataList.find(i => i.standardNumber === item.standardNumber)) {
// 列表中还没有该标准,获取标准数据到表格中
await getForeignStandardDocumentInfo({ id: item.id, type: '2' }).then(res => {
if (res.success) {
@@ -738,19 +743,24 @@ export default {
result.standardName = result.standard_name // 标准名称
result.standardEnglishName = result.standard_english_name // 标准英文名称
result.stanardClass = result.standard_class // 标准类型
result.stanardClass_dictText = result.standard_class_dictText // 标准类型
result.newProductImplDate = result.new_product_impl_date // 新生产车实施日期
result.newAuthImplDate = result.new_auth_impl_date // 新认证车实施日期
result.registrationDate = result.registration_date // 注册日期
result.applicableCountryRegion = result.applicable_market ? (result.applicable_market.split(',').map(item => {
return { value: item }
})) : [] // 适用国家/地区
result.applicableCountryRegion = result.applicable_market // 适用国家/地区
result.applicableCountryRegion_dictText = result.applicable_market_dictText // 适用国家/地区
result.mainDept = result.main_dept // 主控部门
result.mainDept_dictText = result.main_dept_dictText // 主控部门
result.mainDeptProfMode = result.main_dept_prof_mode || undefined // 主控部门专业模块
result.mainDeptProfMode_dictText = result.main_dept_prof_mode_dictText // 主控部门专业模块
result.associateDept = result.associate_dept // 关联部门
result.associateDept_dictText = result.associate_dept_dictText // 关联部门
result.associateDeptProfMode = result.associate_dept_prof_mode || undefined // 关联部门专业模块
result.associateDeptProfMode_dictText = result.associate_dept_prof_mode_dictText // 关联部门专业模块
result.applicableVehicle = result.applicable_vehicle // 适用车型
result.applicableVehicle_dictText = result.applicable_vehicle_dictText // 适用车型
result.dynamicType = result.dynamic_type // 动力类型
result.dynamicType_dictText = result.dynamic_type_dictText // 动力类型
this.dataSource.unshift({
...result,
uid: uidGenerator()
@@ -761,24 +771,42 @@ export default {
})
}
})
} else {
repeatNum++
}
}
if (repeatNum > 0) {
// 提示部分标准已存在
this.$message.warning(this.$t('standardRegulationLibrary.marketRegulationsList.haveStandardExist'))
}
this.loading = false
},
// 复制完成
copyOk (ids) {
async copyOk (ids) {
this.loading = true
// 根据选中的清单,获取清单列表,并且表格中不存在的添加到表格中
getMarketRegulationListByIds({ ids }).then(res => {
if (res.success) {
for (const item of res.result) {
if (!this.dataList.includes(i => i.standardNumber === item.standardNumber)) {
// 列表中还没有该标准
this.dataSource.unshift({ ...item, uid: uidGenerator() })
this.dataList.unshift({ ...item, uid: uidGenerator() })
const idArr = ids.split(',')
let repeatNum = 0
for (const id of idArr) {
await getMarketRegulationListById({ manifestId: id }).then(res => {
if (res.success) {
for (const item of res.result.lists) {
if (!this.dataList.find(i => i.standardNumber === item.standardNumber)) {
// 列表中还没有该标准
this.dataSource.unshift({ ...item, uid: uidGenerator() })
this.dataList.unshift({ ...item, uid: uidGenerator() })
} else {
repeatNum++
}
}
}
}
})
})
}
if (repeatNum > 0) {
// 提示部分标准已存在
this.$message.warning(this.$t('standardRegulationLibrary.marketRegulationsList.haveStandardExist'))
}
this.loading = false
},
toDetail (record) {
let path = ''
@@ -805,13 +833,9 @@ export default {
this.$confirm({
title: this.$t('confirmDeletion'),
content: this.$t('areYouSure'),
onOk: function () {
// 判断当前删除的数据是否是最后一页的最后一条数据,如果是的话页码减一
if (this.ipagination.current > 1 && ((this.ipagination.current - 1) * this.ipagination.pageSize) + 1 === this.ipagination.total) {
this.ipagination.current -= 1
}
this.dataList.filter(item => item.uid !== uid)
this.dataSource.filter(item => item.uid !== uid)
onOk: () => {
this.dataList = this.dataList.filter(item => item.uid !== uid)
this.dataSource = this.dataSource.filter(item => item.uid !== uid)
}
})
},
@@ -853,6 +877,11 @@ export default {
this.model = {}
this.dataSource = []
this.dataList = []
let timer = setTimeout(() => {
clearTimeout(timer)
timer = null
this.$router.go(-1)
}, 700)
}
}
}
@@ -64,12 +64,15 @@
:tree-data="countryOptions"
tree-checkable
treeCheckStrictly
@change="applicableCountryRegionChange"
:placeholder="$t('pleaseSelect')+$t('standardRegulationLibrary.marketListField.applicableCountryRegion')" />
</a-form-item>
<!-- 认证对象 -->
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" :label="$t('standardRegulationLibrary.marketListField.authenticationObject')">
<j-dict-select-tag :placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketListField.authenticationObject')"
<j-dict-select-tag ref="authenticationObject"
:placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketListField.authenticationObject')"
dict-code="authentication_object"
@change="authenticationObjectChange"
v-decorator.trim="[ 'authenticationObject', validatorRules.authenticationObject ]" />
</a-form-item>
<!-- 认证交付物 -->
@@ -116,21 +119,27 @@
</a-form-item>
<!-- 批量限制 -->
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" :label="$t('standardRegulationLibrary.marketListField.batchRestriction')">
<j-multi-select-tag :placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketListField.batchRestriction')"
<j-multi-select-tag ref="batchLimit"
:placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketListField.batchRestriction')"
dict-code="batch_restriction"
@change="batchLimitChange"
v-decorator.trim="[ 'batchLimit', validatorRules.batchLimit ]" />
</a-form-item>
<!-- 自动驾驶等级 -->
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" :label="$t('standardRegulationLibrary.marketListField.automaticDrivingLevel')">
<j-multi-select-tag :placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketListField.automaticDrivingLevel')"
<j-multi-select-tag ref="autopilotLevel"
:placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketListField.automaticDrivingLevel')"
dict-code="automatic_driving_level"
@change="autopilotLevelChange"
v-decorator.trim="[ 'autopilotLevel', validatorRules.autopilotLevel ]" />
</a-form-item>
<!-- 要求类型 -->
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" :label="$t('standardRegulationLibrary.marketListField.requirementType')">
<j-dict-select-tag :placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketListField.requirementType')"
dict-code="requirement_type"
v-decorator.trim="[ 'requireType', validatorRules.requireType ]" />
<j-dict-select-tag ref="requireType"
:placeholder="$t('pleaseSelect') + $t('standardRegulationLibrary.marketListField.requirementType')"
dict-code="requirement_type"
@change="requireTypeChange"
v-decorator.trim="[ 'requireType', validatorRules.requireType ]" />
</a-form-item>
</a-form>
</a-spin>
@@ -306,6 +315,7 @@ export default {
result.standardName = result.standard_name // 标准名称
result.standardEnglishName = result.standard_english_name // 标准英文名称
result.stanardClass = result.standard_class // 标准类型
result.stanardClass_dictText = result.standard_class_dictText // 标准类型
result.newProductImplDate = result.new_product_impl_date // 新生产车实施日期
result.newAuthImplDate = result.new_auth_impl_date // 新认证车实施日期
result.registrationDate = result.registration_date // 注册日期
@@ -314,11 +324,17 @@ export default {
})) : [] // 适用国家/地区
result.applicableCountryRegion_dictText = result.applicable_market_dictText // 适用国家/地区
result.mainDept = result.main_dept // 主控部门
result.mainDept_dictText = result.main_dept_dictText // 主控部门
result.mainDeptProfMode = result.main_dept_prof_mode || undefined // 主控部门专业模块
result.mainDeptProfMode_dictText = result.main_dept_prof_mode_dictText // 主控部门专业模块
result.associateDept = result.associate_dept // 关联部门
result.associateDept_dictText = result.associate_dept_dictText // 关联部门
result.associateDeptProfMode = result.associate_dept_prof_mode || undefined // 关联部门专业模块
result.associateDeptProfMode_dictText = result.associate_dept_prof_mode_dictText // 关联部门专业模块
result.applicableVehicle = result.applicable_vehicle // 适用车型
result.applicableVehicle_dictText = result.applicable_vehicle_dictText // 适用车型
result.dynamicType = result.dynamic_type // 动力类型
result.dynamicType_dictText = result.dynamic_type_dictText // 动力类型
this.model = Object.assign({}, result)
this.$nextTick(() => {
this.form.setFieldsValue(pick(result, 'standardName', 'standardEnglishName',
@@ -330,6 +346,32 @@ export default {
this.loading = false
})
},
// 适用国家/地区改变
applicableCountryRegionChange (value) {
this.model.applicableCountryRegion_dictText = value.map(item => item.label).join(',')
},
// 认证对象改变
authenticationObjectChange (value) {
const obj = this.$refs.authenticationObject.dictOptions.find(item => item.value === value)
this.model.authenticationObject_dictText = obj.title
},
// 批量限制改变
batchLimitChange (value) {
const valueArr = value.split(this.$refs.batchLimit.spliter)
const arr = this.$refs.batchLimit.dictOptions.filter(item => valueArr.includes(item.value))
this.model.batchLimit_dictText = arr.map(item => item.title).join(',')
},
// 自动驾驶等级改变
autopilotLevelChange (value) {
const valueArr = value.split(this.$refs.autopilotLevel.spliter)
const arr = this.$refs.autopilotLevel.dictOptions.filter(item => valueArr.includes(item.value))
this.model.autopilotLevel_dictText = arr.map(item => item.title).join(',')
},
// 要求类型改变
requireTypeChange (value) {
const obj = this.$refs.requireType.dictOptions.find(item => item.value === value)
this.model.requireType_dictText = obj.title
},
handleOk () {
if (this.confirmLoading) return
this.form.validateFields((err, values) => {