<template> <div class="d-form-field d-select"> <van-field readonly :value="displayValue" :label="label" :name="name" :class="{ 'field-border': border, 'field-large': size == 'large', 'field-small': size == 'small', }" :placeholder="placeholder" right-icon="arrow" :required="_required" :sfield="sfield" :disabled="disabled" :rules="rules" @click="showPicker = !disabled && true" /> <van-popup :get-container="getContainer" round position="bottom" v-model="showPicker"> <van-picker show-toolbar :title="'选择' + label" :columns="columns" :value-key="valueKey" @confirm="confirm" @cancel="showPicker = false" /> </van-popup> </div> </template> <script lang="ts"> import { Component, Vue, Prop, Watch } from "vue-property-decorator"; import DictService from "@/services/dict.service"; /** * @Description 下拉选择器 * @Author ZPFly * @Date 2021/11/3 10:19 */ @Component({ name: "DSelect", }) export default class DSelect extends Vue { @Prop({ default: "" }) value: string | undefined; // 当前选择器的值 @Prop({ default: "" }) label: string | undefined; // 输入框左侧文本 @Prop({ default: "" }) sfield: string | undefined; // 下拉框选择 @Prop({ default: "" }) placeholder: string | undefined; // 输入框占位提示文字 @Prop({ default: "" }) name: string | undefined; // 名称,提交表单的标识符 @Prop({ default: "" }) size: string | undefined; // 大小,可选值为 large small @Prop({ default: false }) disabled: boolean | undefined; //是否禁用输入框 @Prop({ default: false }) required: boolean | undefined; //是否显示表单必填星号 @Prop({ default: true }) isLink: boolean | undefined; //是否展示右侧箭头并开启点击反馈 // @Prop({ default: () => [] }) columns: any[] | undefined; //选项列表 @Prop({ default: () => [] }) options!: any[]; //选项列表 @Prop({ default: "text" }) valueKey: string | undefined; //选项对象中,选项文字对应的键名 @Prop({ default: false }) border: false | undefined; // 显示边框 @Prop({ default: () => [] }) rules: any[] | undefined; // 校验规则 @Prop({ default: ""}) getContainer: string | undefined; // 校验规则 _value: any = ""; // 选择器的值 _valueKey: any = ""; // 选项对象中,选项文字对应的键名 showPicker = false; // 显示选择器 displayValue = ""; // 选中对象的文字 columns:any[] = this.options;// //选项列表 tmpIndex = 0; // 是否必输项 get _required() { const rules = this.rules || []; let required = this.required || false; for (const item in rules) { required = required || rules[item].required; } return required; } /** * @Description 获取表单展示文本 * @Author ZPFly * @Date 2021/11/3 9:38 */ upDateDisplayValue() { const cols: any = this.columns; if (cols.length) { if (typeof cols[0] == "string") { this.displayValue = this._value; } else { // 根据选项值,找到选项 const obj = this.columns?.find((item) => { return item.value == this._value; }); this.displayValue = obj ? obj[this._valueKey] : ""; } } else { this.displayValue = ""; } } @Watch("columns") updateDisplay() { this.upDateDisplayValue(); } @Watch("value") reBuildvalue(val:String) { this.setValue(val); } /** * @Description 生命周期 * @Author ZPFly * @Date 2021/11/3 9:57 */ mounted() { this._value = this.value; this._valueKey = this.valueKey; this.upDateDisplayValue(); if (this.sfield && this.sfield != "") { this.initOptions(); } } setValue(value: any) { const opts = this.columns || []; if (value == '') { this.displayValue = ''; return; } for (let i = 0; i < opts.length; i++) { if (this.value == opts[i].value) { this.displayValue = opts[i].text; this.tmpIndex = i; return; } } } //数据字典 // @Watch("sfield") initOptions() { if (this.sfield && this.sfield != "") { this.sfield = this.sfield + ""; const options = DictService.getOptions(this.sfield); console.log(options); this.columns = options; // if (!this.options) { // var me = this, // dataDics = me.dataDics.getOptions(me.sfield); // console.log(dataDics); // me.columns = dataDics[me.sfield] || dataDics; // } else { // this.columns = this.options; // } this.setValue(this.value); } } /** * @Description 点击完成按钮时触发 * @Author ZPFly * @Date 2021/11/3 9:57 */ confirm(val: any) { if (typeof val == "object") { this.displayValue = val[this._valueKey]; this.$emit("input", val.value); } else { this.displayValue = val; this.$emit("input", val); } this.showPicker = false; } /** * @Description 根据索引获取选项 * @Author ZPFly * @Date 2021/11/3 9:54 */ getItemByIndex(index: number) { const columns = this.columns || []; return columns.length > index ? columns[index] : null; } } </script> <style scoped lang="scss"></style>