123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- <template>
- <a-select
- :value="valueV"
- :mode="multiple ? 'multiple' : 'combobox'"
- :allowClear="allowClear"
- :showSearch="showSearch"
- :disabled="disabled"
- :placeholder="placeholder"
- :default-active-first-option="false"
- :notFoundContent="notFoundContent"
- :options="data"
- :filterOption="showSearch && filterDirectly ? filterOption : false"
- @update:value="handleChange"
- @search="handleSearch"
- v-bind="customProps"
- style="min-width: 150px"
- >
- <template v-if="renderOption" #option="data">
- <VNodeRenderer :render="renderOption" :data="data" />
- </template>
- <a-select-option v-if="showNull" :value="null">(空)</a-select-option>
- </a-select>
- </template>
- <script lang="ts">
- import VNodeRenderer from "@/components/VNodeRenderer.vue";
- import { type SelectProps } from "ant-design-vue";
- import { defineComponent, markRaw, type PropType, type VNode } from "vue";
- import { debounce } from 'lodash-es';
- import type { DropdownValues, LoadDataFun } from "./IdAsValueDropdown";
- import type { DataModel } from "@imengyu/js-request-transform";
- import CommonUtils from "@/common/utils/CommonUtils";
- /**
- * IdAsValueDropdown 的公共接口
- */
- export interface IdAsValueDropdownInterface {
- /**
- * 获取某个ID的Lablel
- * @param value 要获取的ID
- */
- getLableByValue(value: number): string;
- /**
- * 重新加载数据
- * @param clearValue 是否需要清除选中数据,默认否
- */
- reload(clearValue?: boolean): void;
- }
- /**
- * IdAsValueDropdown 的公共接口
- */
- export interface IdAsValueDropdownProps<T extends DataModel> {
- /**
- * 允许清除
- */
- allowClear?: boolean,
- /**
- * 显示空?
- */
- showNull?: boolean,
- /**
- * 禁用
- */
- disabled?: boolean,
- /**
- * 多选?
- */
- multiple?: boolean,
- /**
- * 允许搜索
- */
- showSearch?: boolean,
- placeholder?: string,
- /**
- * 未找到数据时的文案
- */
- notFoundContent?: string,
- /**
- * 初始化时加载数据
- */
- loadAtStart?: boolean,
- /**
- * 不使用后端筛选数据而是前端直接筛选
- */
- filterDirectly?: boolean,
- /**
- * 初始化时的搜索数据
- */
- intitialSearchValue?: Record<string, unknown>,
- /**
- * 加载数据回调
- */
- loadData: LoadDataFun<T>,
- /**
- * a-select 其他自定义参数
- */
- customProps?: SelectProps,
- /**
- * 是否自定义渲染option插槽
- */
- renderOption?: RenderOption<T>;
- }
- type RenderOption<T> = (data: {
- value: unknown,
- label: string,
- raw: T
- }) => VNode;
- /**
- * 使用数据的ID作为value的下拉框包装
- */
- export default defineComponent({
- name: "IdAsValueDropdown",
- data() {
- return {
- valueV: null,
- data: [] as DropdownValues<DataModel>[],
- lastLoadValue: null,
- handleSearch: markRaw(debounce((val: string) => {
- if (!this.filterDirectly)
- this.doLoadData(val);
- }, 500)),
- };
- },
- emits: [
- "update:value",
- "change",
- "loaded",
- ],
- props: {
- showNull: {
- default: false,
- type: Boolean
- },
- renderOption: {
- default: null,
- type: Function as PropType<RenderOption<DataModel>>
- },
- allowClear: {
- default: false,
- type: Boolean
- },
- multiple: {
- default: false,
- type: Boolean
- },
- disabled: {
- default: false,
- type: Boolean
- },
- showSearch: {
- default: true,
- type: Boolean
- },
- placeholder: {
- default: "输入可进行搜索",
- type: String
- },
- notFoundContent: {
- default: "未找到数据,请换个搜索词再试",
- type: String
- },
- loadAtStart: {
- default: true,
- type: Boolean
- },
- filterDirectly: {
- default: true,
- type: Boolean
- },
- value: {
- default: null,
- },
- intitialSearchValue: {
- default: null,
- type: String
- },
- loadData: {
- type: Function as PropType<LoadDataFun<DataModel>>,
- default: null,
- },
- /**
- * a-select 其他自定义参数
- */
- customProps: {
- type: Object as PropType<SelectProps>,
- default: null,
- },
- },
- methods: {
- handleChange(value: unknown) {
- this.$emit("change", value);
- this.$emit("update:value", value);
- },
- doLoadData(val: string | null) {
- if (typeof this.loadData === "function") {
- const oldValue = this.valueV;
- this.valueV = null;
- (this.loadData as LoadDataFun<DataModel>)(val).then((d) => {
- this.data = d;
- setTimeout(() => {
- this.valueV = oldValue;
- this.$emit("loaded");
- }, 30);
- });
- }
- },
- filterOption(input: string, option: {
- label: string;
- }) {
- return !this.filterDirectly || option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
- },
- getLableByValue(value: number) {
- for (let i = 0; i < this.data.length; i++) {
- if (this.data[i].value == value) {
- return this.data[i].label;
- }
- }
- return "";
- },
- reload(clearValue = false) {
- if (clearValue) {
- this.valueV = null;
- this.handleChange(null);
- }
- this.data = [];
- this.doLoadData(this.intitialSearchValue as string);
- },
- },
- watch: {
- loadData() {
- this.doLoadData(this.intitialSearchValue);
- },
- intitialSearchValue(v) {
- if (!this.filterDirectly && !CommonUtils.isNullOrEmpty(v)) {
- this.doLoadData(v);
- }
- },
- value(v) {
- this.valueV = v;
- },
- },
- mounted() {
- this.valueV = this.value;
- setTimeout(() => {
- if (this.loadAtStart) {
- this.doLoadData(this.intitialSearchValue as string);
- }
- }, 300);
- },
- components: { VNodeRenderer }
- });
- </script>
|