新增 产品选择关键字搜索

This commit is contained in:
yf 2025-10-14 08:33:40 +08:00
parent ef41c1b22b
commit 88d5a41f5c
5 changed files with 219 additions and 0 deletions

View File

@ -0,0 +1,24 @@
import request from '@/config/axios'
// 关键字 API
export const KeywordApi = {
/**
*
* @param filter
* @param type AbsBaseKeywordSearchHandler bean名称
* @param keyword
* @param maxCount
*/
list: async (filter: string, type: string, keyword: string, maxCount = 10) => {
return await request.get({
url: `/oms/base/keyword/list/${type}/${maxCount}`,
params: {
filter: filter,
keyword: keyword,
}
})
},
}

View File

@ -10,6 +10,7 @@ const props = defineProps({
title: propTypes.string.def('Dialog'),
fullscreen: propTypes.bool.def(false),
width: propTypes.oneOfType([String, Number]).def('40%'),
top: propTypes.oneOfType([String]).def('2%'),
scroll: propTypes.bool.def(false), // maxHeight
maxHeight: propTypes.oneOfType([String, Number]).def('400px')
})
@ -63,6 +64,7 @@ const dialogStyle = computed(() => {
:close-on-click-modal="true"
:fullscreen="isFullscreen"
:width="width"
:top="top"
destroy-on-close
lock-scroll
draggable

View File

@ -29,8 +29,26 @@
<Search
:schema="allSchemas.searchSchema"
:is-col="false"
:expandField="['code','name']"
@search="setSearchParams"
@reset="setSearchParams">
<template #code="{data}">
<div>
<KeywordSearch
v-model="data.code"
:type="'productInfoCode'"
:count="15"/>
</div>
</template>
<template #name="{data}">
<div>
<KeywordSearch
v-model="data.name"
:type="'productInfoName'"
:count="15"/>
</div>
</template>
<!-- 新增等操作按钮 -->
<template #actionMore>
<el-button

View File

@ -0,0 +1,173 @@
<template>
<el-autocomplete
v-model="inputValue"
:fetch-suggestions="querySearch"
@change="changeInput"
clearable
v-bind="attr"
>
<template #default="{item}">
<div>
<span v-html="toHighlightText(item.value,inputValue)"></span>
</div>
</template>
</el-autocomplete>
</template>
<script lang="ts" setup name="KeywordSearch">
//@ts-nocheck
import {KeywordApi} from "@/api/base/keyword";
import {computed} from "vue";
/** 稿件图片库 */
defineOptions({name: 'ProductInfoList'})
const emit = defineEmits(['update:modelValue', 'update:visible', 'submit']) // success
const {t} = useI18n() //
const $attrs = useAttrs();
const props = defineProps({
modelValue: {
type: [String],
required: true
},
type: {
type: String,
default: 'productInfoCode'
},
count: {
type: Number,
default: 15
},
filter: { //
type: [Object,String] ,
default: () => ""
}
})
const attr = computed(() => {
return {
placeholder: t("common.keywordPlaceholder"),
width: '100%',
...$attrs
}
})
const changeInput = (val) => {
emit('update:modelValue', val)
}
const inputValue = computed({
get() {
return props.modelValue
},
set(val) {
emit('update:modelValue', val)
}
})
const that = reactive({
codeKeywordList: [],
})
const keys = [];
const querySearch = (queryString: string, cb: any) => {
let results = getResult(queryString);
if (!results || results.length === 0) {
console.log(444)
//
getList(queryString, props.count).then(res => {
results = getResult(queryString);
cb(results)
});
} else {
console.log("results", results)
cb(results)
}
}
const getResult = (queryString) => {
return queryString
? that.codeKeywordList.filter((item) => {
return `${item.value}`.toUpperCase().indexOf(queryString.toUpperCase()) != -1
})
: that.codeKeywordList
}
let preFilter = computed(()=>{
if(props.filter && typeof props.filter === 'object'){
return JSON.stringify(props.filter)
}
return props.filter || ""
})
const getList = (queryString: string, count: number) => {
return new Promise((resolve, reject) => {
KeywordApi.list(preFilter.value,props.type, queryString, count).then(res => {
if (res.length > 0) {
for (let i = 0; i < res.length; i++) {
const item = res[i];
if (!keys.includes(item.value)) {
keys.push(item.value);
that.codeKeywordList.push({
value: item.value,
label: item.label,
})
}
}
resolve(that.codeKeywordList);
} else {
resolve(that.codeKeywordList);
}
}).catch((err) => {
reject(err);
})
})
}
const toHighlightText = (originalText: string, keyword: string) => {
if (originalText && keyword) {
const keyArray = parseKeywordList(keyword)
if (keyArray.length > 0) {
const arr = originalText.split("")
let highlightedText = ""
arr.forEach(s => {
// @ts-ignore
if (s && keyArray.includes(s.toUpperCase())) {
highlightedText += `<span style="color: #ff0000">${s}</span>`
} else {
highlightedText += `${s}`;
}
})
// HTML
return highlightedText;
}
}
return originalText;
}
const parseKeywordList = (keyword: string): [] => {
//@ts-ignore
const arr = []
if (keyword) {
//
keyword = keyword.replace(/\s/g, '')
const strings = keyword.toUpperCase().split('')
strings.forEach(s => {
//@ts-ignore
if (!arr.includes(s)) {
arr.push(s)
}
})
}
//@ts-ignore
return arr
}
/** 初始化 **/
onMounted(() => {
getList("", props.count * 2)
})
</script>
<style lang="scss" scoped>
</style>

View File

@ -10,6 +10,7 @@ const props = defineProps({
title: propTypes.string.def('Dialog'),
fullscreen: propTypes.bool.def(false),
width: propTypes.oneOfType([String, Number]).def('40%'),
top: propTypes.oneOfType([String]).def('2%'),
scroll: propTypes.bool.def(false), // maxHeight
maxHeight: propTypes.oneOfType([String, Number]).def('400px')
})
@ -63,6 +64,7 @@ const dialogStyle = computed(() => {
:close-on-click-modal="true"
:fullscreen="isFullscreen"
:width="width"
:top="top"
destroy-on-close
lock-scroll
draggable