Files
klp-oa/klp-ui/src/components/MemoInput/index.vue
砂糖 54fe3496fa feat(发货单): 新增发货单打印功能及明细管理
refactor(组件): 重构发货单明细表格为独立组件
feat(组件): 添加发货单打印预览组件
fix(登录页): 移除默认用户名和密码
style(钢卷面板): 添加显示控制属性并优化布局
chore: 添加vitest测试配置和依赖
2025-11-28 11:02:19 +08:00

178 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-autocomplete class="inline-input" v-model="inputValue" :fetch-suggestions="querySearch" :placeholder="placeholder"
:trigger-on-focus="triggerMode === 'focus'" @select="handleSelect" @change="handleInputChange"
clearable></el-autocomplete>
</template>
<script>
export default {
name: 'LocalStorageAutocomplete',
props: {
// localStorage 存储键名,必填
value: {
type: String,
default: ''
},
storageKey: {
type: String,
required: true,
validator: (value) => value.trim() !== '' // 校验非空
},
// 输入框占位符,默认“请输入内容”
placeholder: {
type: String,
default: '请输入内容'
},
// // 当localstorage中不存在缓存时自动创建一个数组作为默认值
// autoCreateDefault: {
// type: Array,
// default: () => []
// },
// 最大缓存数量默认100条
maxCacheCount: {
type: Number,
default: 100,
validator: (value) => value > 0 // 校验正整数
},
// 匹配规则start-前缀匹配contain-包含匹配,默认前缀匹配
matchRule: {
type: String,
default: 'start',
validator: (value) => ['start', 'contain'].includes(value)
},
// 触发模式focus-激活即列出input-输入后匹配默认focus
triggerMode: {
type: String,
default: 'focus',
validator: (value) => ['focus', 'input'].includes(value)
}
},
data() {
return {
inputValue: '',
// 缓存历史列表(格式:[{value: 'xxx'}, ...]
historyList: []
};
},
computed: {
innerKey() {
if (!this.storageKey) {
throw new Error('storageKey is required');
}
return 'mono-' + this.storageKey;
}
},
watch: {
value: {
handler(newVal, oldVal) {
if (newVal !== oldVal) {
this.inputValue = newVal;
}
},
immediate: true
}
},
mounted() {
// 初始化时从localStorage读取历史记录
this.initHistoryList();
},
methods: {
/**
* 从localStorage初始化历史列表
*/
initHistoryList() {
const storedData = localStorage.getItem(this.innerKey);
this.historyList = storedData ? JSON.parse(storedData) : [];
},
/**
* 搜索查询方法Element UI autocomplete 要求的格式)
* @param {string} queryString - 输入的查询字符串
* @param {function} cb - 回调函数,返回匹配结果
*/
querySearch(queryString, cb) {
let results = [...this.historyList]; // 深拷贝避免修改原数组
// 根据查询字符串过滤结果
if (queryString) {
const lowerQuery = queryString.toLowerCase();
results = results.filter(item => {
const lowerValue = item.value.toLowerCase();
// 前缀匹配或包含匹配
return this.matchRule === 'start'
? lowerValue.indexOf(lowerQuery) === 0
: lowerValue.includes(lowerQuery);
});
}
cb(results); // 回调返回匹配结果
},
/**
* 选中建议项时的处理
* @param {object} item - 选中的项 {value: 'xxx'}
*/
handleSelect(item) {
this.cacheInputValue(item.value);
this.inputValue = item.value;
// 触发自定义事件,通知父组件选中结果
this.$emit('input', item.value);
},
/**
* 输入框内容变化时的处理(比如手动输入后回车/失焦)
* @param {string} value - 输入框的值
*/
handleInputChange(value) {
if (value && value.trim() !== '') {
this.cacheInputValue(value.trim());
// 触发自定义事件,通知父组件输入结果
this.$emit('input', value.trim());
}
},
/**
* 缓存输入值到localStorage
* @param {string} value - 要缓存的值
*/
cacheInputValue(value) {
// 去重:如果已存在则移除原记录(保证最新输入在最前面)
this.historyList = this.historyList.filter(item => item.value !== value);
// 添加新记录到头部
this.historyList.unshift({ value });
// 限制最大缓存数量
if (this.historyList.length > this.maxCacheCount) {
this.historyList = this.historyList.slice(0, this.maxCacheCount);
}
// 保存到localStorage
localStorage.setItem(this.innerKey, JSON.stringify(this.historyList));
},
/**
* 清空历史记录(提供给父组件调用的方法)
*/
clearHistory() {
this.historyList = [];
localStorage.removeItem(this.innerKey);
this.inputValue = '';
this.$emit('clear');
}
}
};
</script>
<style scoped>
.demo-autocomplete {
margin-bottom: 20px;
}
.sub-title {
margin-bottom: 10px;
color: #666;
font-size: 14px;
}
.inline-input {
width: 100%;
}
</style>