hookehuyr

refactor(PersonPickerField): 适配新后端人员类型数据格式优化处理逻辑

补充缺失的Vue组合式API导入,修复computed未导入的bug
重写人员类型归一化函数,适配后端返回的带title/value字段的新数据格式
移除硬编码的人员类型标签映射表,改为动态查找允许的类型选项
调整默认搜索类型逻辑,多类型场景默认显示全部类型并向后端传空字符串
修复搜索参数构建的代码bug,优化人员过滤的类型判断逻辑
简化整体代码结构,提升可维护性
......@@ -126,7 +126,7 @@
</template>
<script setup>
import { inject, ref } from 'vue';
import { computed, inject, onMounted, ref } from 'vue';
import { useRoute } from 'vue-router';
import { useCustomFieldValue } from '@vant/use';
import Cookies from 'js-cookie';
......@@ -204,15 +204,21 @@ const normalizeStoredPersonList = (value) => {
};
/**
* 后端现在明确返回 person_types 数组,这里只做去重和空值过滤
* 后端返回的人员类型配置已经自带 title/value,这里只做结构清洗和按 value 去重
*
* @param {string[]} personTypes 人员类型数组
* @returns {string[]}
* @param {Array} personTypes 人员类型配置
* @returns {{ title: string, value: string }[]}
*/
const normalizePersonTypes = (personTypes = []) => {
return _.uniq(personTypes
.map((item) => String(item || '').trim())
.filter(Boolean));
return _.uniqBy(
personTypes
.map((item) => ({
title: String(item?.title || '').trim(),
value: String(item?.value || '').trim(),
}))
.filter((item) => item.title && item.value),
'value',
);
};
/**
......@@ -223,16 +229,16 @@ const syncFieldValue = () => {
props.value = fieldValue.value;
};
/**
* 人员类型的中文展示统一收口在这里,接口和筛选值仍保持英文原值。
*/
const PERSON_TYPE_LABEL_MAP = {
volunteer: '义工',
contact: '联系人',
const findPersonTypeOption = (type) => {
if (!type) {
return null;
}
return allowedPersonTypes.value.find((item) => item.value === type) || null;
};
const formatPersonType = (type) => {
return PERSON_TYPE_LABEL_MAP[type] || type || '人员';
return findPersonTypeOption(type)?.title || type || '人员';
};
const formatPersonTitle = (person) => {
......@@ -254,10 +260,10 @@ const allowedPersonTypes = computed(() => {
});
/**
* 当只允许一种人员类型时,默认锁定这个筛选值
* 多类型字段默认停在“全部类型”,发请求时显式传空字符串给后端
*/
const defaultSearchType = computed(() => {
return allowedPersonTypes.value.length === 1 ? allowedPersonTypes.value[0] : '';
return '';
});
/**
......@@ -268,9 +274,9 @@ const typeFilterOptions = computed(() => {
return [];
}
const allowedOptions = allowedPersonTypes.value.map((type) => ({
text: formatPersonType(type),
value: type,
const allowedOptions = allowedPersonTypes.value.map((typeOption) => ({
text: typeOption.title,
value: typeOption.value,
}));
if (allowedOptions.length === 1) {
......@@ -281,7 +287,7 @@ const typeFilterOptions = computed(() => {
});
const getSearchType = () => {
return defaultSearchType.value || selectedTypeFilter.value || '';
return selectedTypeFilter.value || defaultSearchType.value || '';
};
/**
......@@ -294,7 +300,9 @@ const filterPersonListByType = (personList) => {
const searchType = getSearchType();
return personList.filter((person) => {
if (allowedPersonTypes.value.length && !allowedPersonTypes.value.includes(person.type)) {
const allowedTypeValues = allowedPersonTypes.value.map((item) => item.value);
if (allowedTypeValues.length && !allowedTypeValues.includes(person.type)) {
return false;
}
......@@ -412,6 +420,7 @@ const onSelectSearchType = async (action) => {
* 组装人员搜索接口参数。
*
* @param {number} page 页码,从 0 开始
* @param {string} searchType 本次请求对应的人员类型
* @returns {{ form_code: string, field_name: string, keyword: string, page: number, limit: number, type?: string, force_back?: string }}
*/
const buildSearchParams = (page) => {
......@@ -421,12 +430,8 @@ const buildSearchParams = (page) => {
keyword: searchKeyword.value.trim(),
page,
limit: searchLimit.value,
type: getSearchType(),
};
const searchType = getSearchType();
if (searchType) {
params.type = searchType;
}
if ($route.query.force_back) {
params.force_back = $route.query.force_back;
}
......