refactor(PersonPickerField): 适配新后端人员类型数据格式优化处理逻辑
补充缺失的Vue组合式API导入,修复computed未导入的bug 重写人员类型归一化函数,适配后端返回的带title/value字段的新数据格式 移除硬编码的人员类型标签映射表,改为动态查找允许的类型选项 调整默认搜索类型逻辑,多类型场景默认显示全部类型并向后端传空字符串 修复搜索参数构建的代码bug,优化人员过滤的类型判断逻辑 简化整体代码结构,提升可维护性
Showing
1 changed file
with
31 additions
and
26 deletions
| ... | @@ -126,7 +126,7 @@ | ... | @@ -126,7 +126,7 @@ |
| 126 | </template> | 126 | </template> |
| 127 | 127 | ||
| 128 | <script setup> | 128 | <script setup> |
| 129 | -import { inject, ref } from 'vue'; | 129 | +import { computed, inject, onMounted, ref } from 'vue'; |
| 130 | import { useRoute } from 'vue-router'; | 130 | import { useRoute } from 'vue-router'; |
| 131 | import { useCustomFieldValue } from '@vant/use'; | 131 | import { useCustomFieldValue } from '@vant/use'; |
| 132 | import Cookies from 'js-cookie'; | 132 | import Cookies from 'js-cookie'; |
| ... | @@ -204,15 +204,21 @@ const normalizeStoredPersonList = (value) => { | ... | @@ -204,15 +204,21 @@ const normalizeStoredPersonList = (value) => { |
| 204 | }; | 204 | }; |
| 205 | 205 | ||
| 206 | /** | 206 | /** |
| 207 | - * 后端现在明确返回 person_types 数组,这里只做去重和空值过滤。 | 207 | + * 后端返回的人员类型配置已经自带 title/value,这里只做结构清洗和按 value 去重。 |
| 208 | * | 208 | * |
| 209 | - * @param {string[]} personTypes 人员类型数组 | 209 | + * @param {Array} personTypes 人员类型配置 |
| 210 | - * @returns {string[]} | 210 | + * @returns {{ title: string, value: string }[]} |
| 211 | */ | 211 | */ |
| 212 | const normalizePersonTypes = (personTypes = []) => { | 212 | const normalizePersonTypes = (personTypes = []) => { |
| 213 | - return _.uniq(personTypes | 213 | + return _.uniqBy( |
| 214 | - .map((item) => String(item || '').trim()) | 214 | + personTypes |
| 215 | - .filter(Boolean)); | 215 | + .map((item) => ({ |
| 216 | + title: String(item?.title || '').trim(), | ||
| 217 | + value: String(item?.value || '').trim(), | ||
| 218 | + })) | ||
| 219 | + .filter((item) => item.title && item.value), | ||
| 220 | + 'value', | ||
| 221 | + ); | ||
| 216 | }; | 222 | }; |
| 217 | 223 | ||
| 218 | /** | 224 | /** |
| ... | @@ -223,16 +229,16 @@ const syncFieldValue = () => { | ... | @@ -223,16 +229,16 @@ const syncFieldValue = () => { |
| 223 | props.value = fieldValue.value; | 229 | props.value = fieldValue.value; |
| 224 | }; | 230 | }; |
| 225 | 231 | ||
| 226 | -/** | 232 | +const findPersonTypeOption = (type) => { |
| 227 | - * 人员类型的中文展示统一收口在这里,接口和筛选值仍保持英文原值。 | 233 | + if (!type) { |
| 228 | - */ | 234 | + return null; |
| 229 | -const PERSON_TYPE_LABEL_MAP = { | 235 | + } |
| 230 | - volunteer: '义工', | 236 | + |
| 231 | - contact: '联系人', | 237 | + return allowedPersonTypes.value.find((item) => item.value === type) || null; |
| 232 | }; | 238 | }; |
| 233 | 239 | ||
| 234 | const formatPersonType = (type) => { | 240 | const formatPersonType = (type) => { |
| 235 | - return PERSON_TYPE_LABEL_MAP[type] || type || '人员'; | 241 | + return findPersonTypeOption(type)?.title || type || '人员'; |
| 236 | }; | 242 | }; |
| 237 | 243 | ||
| 238 | const formatPersonTitle = (person) => { | 244 | const formatPersonTitle = (person) => { |
| ... | @@ -254,10 +260,10 @@ const allowedPersonTypes = computed(() => { | ... | @@ -254,10 +260,10 @@ const allowedPersonTypes = computed(() => { |
| 254 | }); | 260 | }); |
| 255 | 261 | ||
| 256 | /** | 262 | /** |
| 257 | - * 当只允许一种人员类型时,默认锁定这个筛选值。 | 263 | + * 多类型字段默认停在“全部类型”,发请求时显式传空字符串给后端。 |
| 258 | */ | 264 | */ |
| 259 | const defaultSearchType = computed(() => { | 265 | const defaultSearchType = computed(() => { |
| 260 | - return allowedPersonTypes.value.length === 1 ? allowedPersonTypes.value[0] : ''; | 266 | + return ''; |
| 261 | }); | 267 | }); |
| 262 | 268 | ||
| 263 | /** | 269 | /** |
| ... | @@ -268,9 +274,9 @@ const typeFilterOptions = computed(() => { | ... | @@ -268,9 +274,9 @@ const typeFilterOptions = computed(() => { |
| 268 | return []; | 274 | return []; |
| 269 | } | 275 | } |
| 270 | 276 | ||
| 271 | - const allowedOptions = allowedPersonTypes.value.map((type) => ({ | 277 | + const allowedOptions = allowedPersonTypes.value.map((typeOption) => ({ |
| 272 | - text: formatPersonType(type), | 278 | + text: typeOption.title, |
| 273 | - value: type, | 279 | + value: typeOption.value, |
| 274 | })); | 280 | })); |
| 275 | 281 | ||
| 276 | if (allowedOptions.length === 1) { | 282 | if (allowedOptions.length === 1) { |
| ... | @@ -281,7 +287,7 @@ const typeFilterOptions = computed(() => { | ... | @@ -281,7 +287,7 @@ const typeFilterOptions = computed(() => { |
| 281 | }); | 287 | }); |
| 282 | 288 | ||
| 283 | const getSearchType = () => { | 289 | const getSearchType = () => { |
| 284 | - return defaultSearchType.value || selectedTypeFilter.value || ''; | 290 | + return selectedTypeFilter.value || defaultSearchType.value || ''; |
| 285 | }; | 291 | }; |
| 286 | 292 | ||
| 287 | /** | 293 | /** |
| ... | @@ -294,7 +300,9 @@ const filterPersonListByType = (personList) => { | ... | @@ -294,7 +300,9 @@ const filterPersonListByType = (personList) => { |
| 294 | const searchType = getSearchType(); | 300 | const searchType = getSearchType(); |
| 295 | 301 | ||
| 296 | return personList.filter((person) => { | 302 | return personList.filter((person) => { |
| 297 | - if (allowedPersonTypes.value.length && !allowedPersonTypes.value.includes(person.type)) { | 303 | + const allowedTypeValues = allowedPersonTypes.value.map((item) => item.value); |
| 304 | + | ||
| 305 | + if (allowedTypeValues.length && !allowedTypeValues.includes(person.type)) { | ||
| 298 | return false; | 306 | return false; |
| 299 | } | 307 | } |
| 300 | 308 | ||
| ... | @@ -412,6 +420,7 @@ const onSelectSearchType = async (action) => { | ... | @@ -412,6 +420,7 @@ const onSelectSearchType = async (action) => { |
| 412 | * 组装人员搜索接口参数。 | 420 | * 组装人员搜索接口参数。 |
| 413 | * | 421 | * |
| 414 | * @param {number} page 页码,从 0 开始 | 422 | * @param {number} page 页码,从 0 开始 |
| 423 | + * @param {string} searchType 本次请求对应的人员类型 | ||
| 415 | * @returns {{ form_code: string, field_name: string, keyword: string, page: number, limit: number, type?: string, force_back?: string }} | 424 | * @returns {{ form_code: string, field_name: string, keyword: string, page: number, limit: number, type?: string, force_back?: string }} |
| 416 | */ | 425 | */ |
| 417 | const buildSearchParams = (page) => { | 426 | const buildSearchParams = (page) => { |
| ... | @@ -421,12 +430,8 @@ const buildSearchParams = (page) => { | ... | @@ -421,12 +430,8 @@ const buildSearchParams = (page) => { |
| 421 | keyword: searchKeyword.value.trim(), | 430 | keyword: searchKeyword.value.trim(), |
| 422 | page, | 431 | page, |
| 423 | limit: searchLimit.value, | 432 | limit: searchLimit.value, |
| 433 | + type: getSearchType(), | ||
| 424 | }; | 434 | }; |
| 425 | - | ||
| 426 | - const searchType = getSearchType(); | ||
| 427 | - if (searchType) { | ||
| 428 | - params.type = searchType; | ||
| 429 | - } | ||
| 430 | if ($route.query.force_back) { | 435 | if ($route.query.force_back) { |
| 431 | params.force_back = $route.query.force_back; | 436 | params.force_back = $route.query.force_back; |
| 432 | } | 437 | } | ... | ... |
-
Please register or login to post a comment