import { defineComponent, ref, computed, type PropType, useModel } from "vue";
|
import { useConfig, useCore } from "../../hooks";
|
import { parsePx } from "../../utils";
|
import { debounce } from "lodash-es";
|
|
export default defineComponent({
|
name: "cl-search-key",
|
|
props: {
|
// 绑定值
|
modelValue: String,
|
// 选中字段
|
field: {
|
type: String,
|
default: "keyWord"
|
},
|
// 字段列表
|
fieldList: {
|
type: Array as PropType<Array<{ label: string; value: string }>>,
|
default: () => []
|
},
|
// 搜索时的钩子
|
onSearch: Function,
|
// 输入框占位内容
|
placeholder: String,
|
// 宽度
|
width: {
|
type: [String, Number],
|
default: 280
|
},
|
// 是否实时刷新
|
refreshOnInput: Boolean
|
},
|
|
emits: ["update:modelValue", "change", "field-change"],
|
|
setup(props, { emit, expose }) {
|
const { crud } = useCore();
|
const { style } = useConfig();
|
|
// 选中字段
|
const selectField = ref(props.field);
|
|
// 加载状态
|
const loading = ref(false);
|
|
// 文字提示
|
const placeholder = computed(() => {
|
if (props.placeholder) {
|
return props.placeholder;
|
} else {
|
const item = props.fieldList.find((e) => e.value == selectField.value);
|
|
if (item) {
|
return crud.dict.label.placeholder + item.label;
|
} else {
|
return crud.dict.label.searchKey;
|
}
|
}
|
});
|
|
// 搜索内容
|
const value = useModel(props, "modelValue");
|
|
// 锁
|
let lock = false;
|
|
// 搜索
|
function search() {
|
if (!lock) {
|
const params: obj = {};
|
|
props.fieldList.forEach((e) => {
|
params[e.value] = undefined;
|
});
|
|
async function next(newParams?: obj) {
|
loading.value = true;
|
|
await crud.refresh({
|
page: 1,
|
...params,
|
[selectField.value]: value.value || undefined,
|
...newParams
|
})
|
.catch(err => {
|
console.error(err);
|
})
|
|
loading.value = false;
|
}
|
|
if (props.onSearch) {
|
props.onSearch(params, { next });
|
} else {
|
next();
|
}
|
}
|
}
|
|
// 回车搜索
|
function onKeydown({ key }: KeyboardEvent) {
|
if (key === "Enter") {
|
search();
|
}
|
}
|
|
// 监听变化
|
function onChange(val: string) {
|
if (!props.refreshOnInput) {
|
search();
|
lock = true;
|
|
setTimeout(() => {
|
lock = false;
|
}, 300);
|
|
emit("change", val);
|
}
|
}
|
|
// 监听输入
|
const onInput = debounce((val: string) => {
|
emit("change", val);
|
|
if (props.refreshOnInput) {
|
search();
|
}
|
}, 300);
|
|
// 监听字段选择
|
function onFieldChange() {
|
emit("field-change", selectField.value);
|
value.value = undefined;
|
}
|
|
expose({
|
search
|
});
|
|
return () => {
|
return (
|
<div class="cl-search-key">
|
<el-select
|
class="cl-search-key__select"
|
size={style.size}
|
v-model={selectField.value}
|
v-show={props.fieldList.length > 0}
|
onChange={onFieldChange}>
|
{props.fieldList.map((e, i) => (
|
<el-option key={i} label={e.label} value={e.value} />
|
))}
|
</el-select>
|
|
<div class="cl-search-key__wrap" style={{ width: parsePx(props.width) }}>
|
<el-input
|
v-model={value.value}
|
size={style.size}
|
placeholder={placeholder.value}
|
onKeydown={onKeydown}
|
onChange={onChange}
|
onInput={onInput}
|
clearable
|
/>
|
|
<el-button
|
size={style.size}
|
type="primary"
|
loading={loading.value}
|
onClick={search}>
|
{crud.dict.label.search}
|
</el-button>
|
</div>
|
</div>
|
);
|
};
|
}
|
});
|