This commit is contained in:
parent
cdaa6a63d2
commit
5253a74f06
|
@ -2,10 +2,8 @@
|
||||||
<el-input
|
<el-input
|
||||||
class="ag_input"
|
class="ag_input"
|
||||||
:style="{ width }"
|
:style="{ width }"
|
||||||
:value="value"
|
|
||||||
:size="size"
|
|
||||||
v-on="inputListeners"
|
v-on="inputListeners"
|
||||||
v-bind="[$attrs]"
|
v-bind="attrs"
|
||||||
>
|
>
|
||||||
<slot name="append" slot="append" />
|
<slot name="append" slot="append" />
|
||||||
<slot name="prefix" slot="prefix" />
|
<slot name="prefix" slot="prefix" />
|
||||||
|
@ -26,20 +24,19 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
size: {
|
|
||||||
type: String,
|
|
||||||
default: "small",
|
|
||||||
},
|
|
||||||
value: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
toUpperCase: {
|
toUpperCase: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
attrs() {
|
||||||
|
return {
|
||||||
|
size: "small",
|
||||||
|
clearable: true, // 默认清空
|
||||||
|
...this.$attrs,
|
||||||
|
};
|
||||||
|
},
|
||||||
// 所有父级事件
|
// 所有父级事件
|
||||||
inputListeners() {
|
inputListeners() {
|
||||||
return Object.assign(
|
return Object.assign(
|
||||||
|
|
|
@ -1,102 +1,217 @@
|
||||||
<template>
|
<template>
|
||||||
<el-select
|
<div
|
||||||
class="ag_select"
|
@mousedown="
|
||||||
:style="{ width }"
|
(e) => {
|
||||||
:value="value"
|
e.preventDefault();
|
||||||
:size="size"
|
selectOpen = true;
|
||||||
v-on="inputListeners"
|
}
|
||||||
v-bind="attrs"
|
"
|
||||||
|
ref="main"
|
||||||
>
|
>
|
||||||
<el-option
|
<a-select
|
||||||
v-for="(item, index) in options"
|
class="t_select"
|
||||||
:key="index"
|
v-model="childSelectedValue"
|
||||||
:label="item.label"
|
:style="{ width: width || '100%' }"
|
||||||
:value="item.value"
|
:placeholder="placeholder"
|
||||||
></el-option>
|
:open="selectOpen"
|
||||||
<!-- <slot name="options" slot="options" /> -->
|
@select="handleSelect"
|
||||||
</el-select>
|
v-bind="attrs"
|
||||||
|
v-on="$listeners"
|
||||||
|
:mode="mode"
|
||||||
|
>
|
||||||
|
<template v-for="(index, name) in $slots" v-slot:[name]>
|
||||||
|
<slot :name="name" />
|
||||||
|
</template>
|
||||||
|
<template v-for="(index, name) in $scopedSlots" v-slot:[name]="data">
|
||||||
|
<slot :name="name" v-bind="data"></slot>
|
||||||
|
</template>
|
||||||
|
<div slot="dropdownRender" slot-scope="menu">
|
||||||
|
<a-checkbox
|
||||||
|
v-if="mode && !isShowPagination"
|
||||||
|
:checked="selectChecked"
|
||||||
|
@change="selectAll"
|
||||||
|
class="all_checkbox"
|
||||||
|
>全选</a-checkbox
|
||||||
|
>
|
||||||
|
<v-nodes :vnodes="menu" />
|
||||||
|
<div class="t_select__pagination" v-if="isShowPagination">
|
||||||
|
<a-pagination
|
||||||
|
:page-size.sync="paginationOption.pageSize"
|
||||||
|
v-model="paginationOption.current"
|
||||||
|
:total="paginationOption.total"
|
||||||
|
@change="currentChange"
|
||||||
|
v-bind="{
|
||||||
|
size: 'small',
|
||||||
|
'hide-on-single-page': true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
...$attrs,
|
||||||
|
...paginationOption.bind,
|
||||||
|
}"
|
||||||
|
v-on="$listeners"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a-select-option
|
||||||
|
v-for="(item, index) in optionSource"
|
||||||
|
:key="index"
|
||||||
|
:value="item[valueKey]"
|
||||||
|
>{{
|
||||||
|
customLabel ? customLabelHandler(item) : item[labelKey]
|
||||||
|
}}</a-select-option
|
||||||
|
>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import cloneDeep from "../../../src/utils/cloneDeep";
|
|
||||||
export default {
|
export default {
|
||||||
name: "agSelect",
|
name: "TAntdSelect",
|
||||||
|
components: {
|
||||||
|
VNodes: {
|
||||||
|
functional: true,
|
||||||
|
render: (h, ctx) => ctx.props.vnodes,
|
||||||
|
},
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
|
value: {
|
||||||
|
type: [String, Number, Array, Boolean, Object],
|
||||||
|
},
|
||||||
|
// 多选 'multiple'
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: "请选择",
|
||||||
|
},
|
||||||
|
// 选择框宽度
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
|
||||||
},
|
},
|
||||||
value: {
|
// 是否自定义设置下拉label
|
||||||
|
customLabel: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
|
||||||
},
|
},
|
||||||
size: {
|
// 传入的option数组中,要作为最终选择项的键值key
|
||||||
|
valueKey: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "small",
|
default: "key",
|
||||||
|
},
|
||||||
|
// 传入的option数组中,要作为显示项的键值名称
|
||||||
|
labelKey: {
|
||||||
|
type: String,
|
||||||
|
default: "label",
|
||||||
|
},
|
||||||
|
// 下拉框组件数据源
|
||||||
|
optionSource: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
// 是否显示分页
|
||||||
|
isShowPagination: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
// 分页配置项
|
||||||
|
paginationOption: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
pageSize: 6, // 每页显示条数
|
||||||
|
current: 1, // 当前页
|
||||||
|
total: 0, // 总条数
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
model: "",
|
selectOpen: false,
|
||||||
options: [],
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
childSelectedValue: {
|
||||||
|
get() {
|
||||||
|
return this.value || undefined;
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit("input", val);
|
||||||
|
},
|
||||||
|
},
|
||||||
attrs() {
|
attrs() {
|
||||||
if (this.$attrs["remote-method"]) {
|
return {
|
||||||
let obj = cloneDeep(this.$attrs);
|
allowClear: true,
|
||||||
Reflect.deleteProperty(obj, "remote-method");
|
showSearch: true,
|
||||||
return { ...obj, clearable: true, filterable: true, remote: true };
|
...this.$attrs,
|
||||||
}
|
};
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
// 所有父级事件
|
selectChecked: {
|
||||||
inputListeners() {
|
get() {
|
||||||
return Object.assign(
|
return this.childSelectedValue?.length === this.optionSource?.length;
|
||||||
{},
|
|
||||||
// 我们从父级添加所有的监听器
|
|
||||||
this.$listeners,
|
|
||||||
// 然后我们添加自定义监听器,
|
|
||||||
// 或覆写一些监听器的行为
|
|
||||||
{
|
|
||||||
// 这里确保组件配合 `v-model` 的工作
|
|
||||||
input: (value) => {
|
|
||||||
this.$emit("input", this.toUpperCase ? value.toUpperCase() : value);
|
|
||||||
},
|
},
|
||||||
blur: (e) => {
|
set(val) {
|
||||||
let value = e.target.value
|
// console.log('set', val)
|
||||||
.trim()
|
this.$emit("input", val);
|
||||||
.replace(/\s/g, (match) =>
|
|
||||||
match.charCodeAt(0) === 12288 ? String.fromCharCode(32) : match
|
|
||||||
);
|
|
||||||
// 失去焦点自动首位去空格
|
|
||||||
this.$emit("input", value);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
value: {
|
|
||||||
immediate: true,
|
|
||||||
handler(newVal) {
|
|
||||||
this.removeMethod(newVal);
|
|
||||||
this.model = newVal;
|
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
document.addEventListener("click", this.bodyCloseMenus);
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
document.removeEventListener("click", this.bodyCloseMenus);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async removeMethod(keywords) {
|
// 点击空白区域
|
||||||
if (this.$attrs["remote-method"]) {
|
bodyCloseMenus(e) {
|
||||||
let opts = await this.$attrs["remote-method"](keywords);
|
if (this.$refs.main && !this.$refs.main.contains(e.target)) {
|
||||||
this.options = opts;
|
if (this.selectOpen == true) {
|
||||||
|
this.selectOpen = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleChange(value) {
|
// 点击全选
|
||||||
this.$emit("input", value);
|
selectAll(val) {
|
||||||
|
const options = JSON.parse(JSON.stringify(this.optionSource));
|
||||||
|
if (val.target.checked) {
|
||||||
|
this.childSelectedValue = options?.map((item) => {
|
||||||
|
return item[this.valueKey];
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$emit("change", this.childSelectedValue);
|
||||||
|
}, 0);
|
||||||
|
} else {
|
||||||
|
this.childSelectedValue = null;
|
||||||
|
}
|
||||||
|
this.selectOpen = false;
|
||||||
|
},
|
||||||
|
handleSelect(value, option) {
|
||||||
|
if (value) {
|
||||||
|
this.selectOpen = false;
|
||||||
|
}
|
||||||
|
this.$emit("select", value, option);
|
||||||
|
},
|
||||||
|
// 切换分页
|
||||||
|
currentChange(val) {
|
||||||
|
// console.log('切换分页', val)
|
||||||
|
if (!this.mode) {
|
||||||
|
this.childSelectedValue = null;
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
this.selectOpen = true;
|
||||||
|
}, 0);
|
||||||
|
this.$emit("current-change", val);
|
||||||
|
},
|
||||||
|
// 自定义label显示
|
||||||
|
customLabelHandler() {
|
||||||
|
// eslint-disable-next-line no-eval
|
||||||
|
return eval(this.customLabel);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
<style >
|
||||||
|
.all_checkbox {
|
||||||
|
margin-left: 12px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
|
||||||
|
|
58
src/App.vue
58
src/App.vue
|
@ -1,22 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<agSelect
|
<agSelect ref="ref_Pedestal" :value="value" @input="changeInput">
|
||||||
ref="ref_Pedestal"
|
|
||||||
v-model="value"
|
|
||||||
@input="changeInput"
|
|
||||||
:width="'180px'"
|
|
||||||
>
|
|
||||||
<!-- <template #operate="">
|
|
||||||
<el-button
|
|
||||||
class="excel"
|
|
||||||
type="success"
|
|
||||||
icon="el-icon-download"
|
|
||||||
size="small"
|
|
||||||
plain
|
|
||||||
@click="excel()"
|
|
||||||
>导出</el-button
|
|
||||||
>
|
|
||||||
</template> -->
|
|
||||||
</agSelect>
|
</agSelect>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -28,32 +12,34 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
value: "",
|
value: "",
|
||||||
options: {
|
options: [{
|
||||||
fnSearch: this.fnSearch,
|
value: '选项1',
|
||||||
formItemAttrs: {
|
label: '黄金糕'
|
||||||
order_sn: {
|
}, {
|
||||||
type: "input",
|
value: '选项2',
|
||||||
label: "订单号",
|
label: '双皮奶'
|
||||||
placeholder: "请输入订单号",
|
}, {
|
||||||
},
|
value: '选项3',
|
||||||
product_category_id: {
|
label: '蚵仔煎'
|
||||||
type: "select",
|
}, {
|
||||||
label: "商品分类",
|
value: '选项4',
|
||||||
multiple: false,
|
label: '龙须面'
|
||||||
selectOpts: [{ label: "全部", value: "" }],
|
}, {
|
||||||
placeholder: "选择商品分类",
|
value: '选项5',
|
||||||
},
|
label: '北京烤鸭'
|
||||||
},
|
}],
|
||||||
},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changeInput() {
|
changeInput() {
|
||||||
console.log(this.value);
|
// console.log(this.value);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang='scss'>
|
<style>
|
||||||
|
body {
|
||||||
|
background: #918d8d;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue