Files
certd/packages/ui/certd-client/src/components/plugins/common/remote-select.vue
T

183 lines
4.5 KiB
Vue
Raw Normal View History

<template>
<div class="remote-select">
<div class="flex flex-row">
<a-select class="remote-select-input" show-search :filter-option="filterOption" :options="optionsRef" :value="value" v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)">
<template #dropdownRender="{ menuNode: menu }">
<template v-if="search">
<div class="flex w-full" style="padding: 4px 8px">
<a-input ref="inputRef" v-model:value="searchKeyRef" class="flex-1" allow-clear placeholder="查询关键字" @keydown.enter="doSearch" />
<a-button class="ml-2" :loading="loading" type="text" @click="doSearch">
<template #icon>
<search-outlined />
</template>
查询
</a-button>
</div>
<div v-if="hasError" class="helper p-2" :class="{ error: hasError }">
{{ message }}
</div>
<a-divider style="margin: 4px 0" />
</template>
<v-nodes :vnodes="menu" />
</template>
</a-select>
<div class="ml-5">
2024-10-24 12:10:20 +08:00
<fs-button :loading="loading" title="刷新选项" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
</div>
</div>
2024-10-24 12:10:20 +08:00
<div class="helper" :class="{ error: hasError }">
{{ message }}
</div>
</div>
</template>
2024-09-27 02:15:41 +08:00
<script setup lang="ts">
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
import { defineComponent, inject, ref, useAttrs, watch } from "vue";
2024-10-25 16:51:36 +08:00
import { PluginDefine } from "@certd/pipeline";
2024-09-27 02:15:41 +08:00
defineOptions({
2025-03-26 12:05:28 +08:00
name: "RemoteSelect",
});
const VNodes = defineComponent({
props: {
vnodes: {
type: Object,
required: true,
},
},
render() {
return this.vnodes;
},
});
2024-09-27 02:15:41 +08:00
const props = defineProps<
{
watches: string[];
search: boolean;
2024-09-27 02:15:41 +08:00
} & ComponentPropsType
>();
const emit = defineEmits<{
"update:value": any;
}>();
const attrs = useAttrs();
2024-10-25 16:51:36 +08:00
const getCurrentPluginDefine: any = inject("getCurrentPluginDefine");
2024-11-25 11:35:16 +08:00
const getScope: any = inject("get:scope");
const getPluginType: any = inject("get:plugin:type");
const searchKeyRef = ref("");
2024-09-27 02:15:41 +08:00
const optionsRef = ref([]);
2024-10-03 01:29:12 +08:00
const message = ref("");
2024-10-24 12:10:20 +08:00
const hasError = ref(false);
const loading = ref(false);
2024-09-27 02:15:41 +08:00
const getOptions = async () => {
2024-10-25 16:51:36 +08:00
if (loading.value) {
return;
}
if (!getCurrentPluginDefine) {
return;
}
const define: PluginDefine = getCurrentPluginDefine()?.value;
if (!define) {
return;
}
2025-04-29 18:40:13 +08:00
const pluginType = getPluginType();
const { form } = getScope();
const input = pluginType === "plugin" ? form.input : form;
2024-10-25 16:51:36 +08:00
for (let key in define.input) {
const inWatches = props.watches.includes(key);
const inputDefine = define.input[key];
if (inWatches && inputDefine.required) {
2025-04-29 18:40:13 +08:00
const value = input[key];
2024-10-25 16:51:36 +08:00
if (value == null || value === "") {
console.log("remote-select required", key);
return;
}
}
}
2024-10-22 18:46:29 +08:00
message.value = "";
2024-10-24 12:10:20 +08:00
hasError.value = false;
loading.value = true;
2024-10-25 16:51:36 +08:00
optionsRef.value = [];
2024-11-25 11:35:16 +08:00
2024-10-24 12:10:20 +08:00
try {
const res = await doRequest(
{
2024-11-25 11:35:16 +08:00
type: pluginType,
typeName: form.type,
2024-10-24 12:10:20 +08:00
action: props.action,
2025-04-29 18:40:13 +08:00
input,
data: {
searchKey: props.search ? searchKeyRef.value : "",
},
2024-10-22 18:46:29 +08:00
},
2024-10-24 12:10:20 +08:00
{
onError(err: any) {
hasError.value = true;
message.value = `获取选项出错:${err.message}`;
},
2025-03-26 12:05:28 +08:00
showErrorNotify: false,
2024-10-24 12:10:20 +08:00
}
);
if (res && res.length > 0) {
message.value = "获取数据成功,请从下拉框中选择";
2024-10-03 01:29:12 +08:00
}
2024-10-25 16:51:36 +08:00
optionsRef.value = res;
2024-10-24 12:10:20 +08:00
return res;
} finally {
loading.value = false;
}
2024-09-27 02:15:41 +08:00
};
2024-09-30 18:00:51 +08:00
const filterOption = (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 || String(option.value).toLowerCase().indexOf(input.toLowerCase());
};
async function onClick() {
2024-10-25 16:51:36 +08:00
if (optionsRef.value?.length === 0) {
await refreshOptions();
2024-09-30 18:00:51 +08:00
}
}
async function refreshOptions() {
2024-10-25 16:51:36 +08:00
await getOptions();
2024-09-30 18:00:51 +08:00
}
async function doSearch() {
await refreshOptions();
}
2024-09-27 02:15:41 +08:00
watch(
() => {
const values = [];
2025-04-29 18:40:13 +08:00
const pluginType = getPluginType();
const { form } = getScope();
const input = pluginType === "plugin" ? form.input : form;
2024-09-27 02:15:41 +08:00
for (const item of props.watches) {
2025-04-29 18:40:13 +08:00
values.push(input[item]);
2024-09-27 02:15:41 +08:00
}
return {
2025-04-29 18:40:13 +08:00
form: input,
2025-03-26 12:05:28 +08:00
watched: values,
2024-09-27 02:15:41 +08:00
};
},
async () => {
2024-10-25 16:51:36 +08:00
await getOptions();
},
{
2025-03-26 12:05:28 +08:00
immediate: true,
2024-09-30 18:00:51 +08:00
}
2024-09-27 02:15:41 +08:00
);
</script>
<style lang="less"></style>