You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tanghe-report/report-ui/src/components/AnjiPlus/anji-select.vue

361 lines
9.0 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--element下拉列表封装
使用
<hyb-select ref="hybSelect"
url="/v1/orgs"
v-model="search.orgId" option="orgId" label="orgName"
placeholder multiple localOptions></hyb-select>
1.url:要显示的下拉列表数据来源
规范:返回的数据要符合(JSON中对应的字段必须label和value,不能其他)
[
{label:'显示1',value:'值1'},
{label:'显示2',value:'值2'},
{label:'显示3',value:'值3'},
...
]
2.v-model数据的双向绑定,绑定父组件中的字段
3.option自定义select的value对应的字段
4.label自定义select的label对应的字段
5.placeholder下拉列表提示
6.multiple是否是多选
7.localOptions使用本地的数据,不用请求远程数据,注意使用该属性时Url属性不能要,不然无效
-->
<template>
<div>
<el-select
v-model="selectValue"
:clearable="clearable"
:allow-create="!!allowCreate"
:default-first-option="!!allowCreate"
:collapse-tags="collapseTags"
filterable
class="filter-item"
:placeholder="placeholder"
:disabled="disabled"
:multiple="multiple == null ? false : true"
:remote="remoteFilter"
:remote-method="remoteQuery"
@change="change"
>
<el-option
v-for="(item, index) in options"
:key="index"
:label="getItemLabel(item, label)"
:value="item[option] + ''"
:disabled="isDisabledOption(item)"
>
<template v-if="mergeLabel">
<span style="float: left">{{ getItemLabel(item, label) }}</span>
<span
v-if="!dictCode && !localOptions"
style="float: right; color: #8492a6; font-size: 13px"
>{{ item[option] }}</span
>
</template>
</el-option>
<el-option v-if="totalPage >= 1" value="" disabled
>输入关键词搜索更多</el-option
>
</el-select>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
props: {
dictCode: null, // 当传入dictCode时可以不用传递url
url: null,
allowCreate: {
type: Boolean,
default: false
},
method: {
type: String,
default: "get"
},
queryParam: {
type: Object,
default: () => {
return {};
}
},
value: null,
placeholder: null,
label: {
type: String,
default: "text"
},
option: {
type: String,
default: "id"
},
multiple: null,
localOptions: null,
disabled: null,
clearable: {
type: Boolean,
default: true
},
collapseTags: {
type: Boolean,
default: false
},
mergeLabel: {
type: Boolean,
default: true
},
// 禁用的下拉选项
disabledOptions: {
type: String,
default: () => {
return "";
}
},
// 使用远程搜索
remoteFilter: {
type: Boolean,
default: false
}
},
data() {
return {
options: null,
selectValue: null,
// 如果是分页的,
totalPage: 0
};
},
computed: {
// 根据dictCode和url拼出最终的请求url
requestUrl() {
if (this.localOptions) {
return null;
}
if (this.url != null && this.url.trim() != "") {
if (this.url.indexOf("?") > 0) {
if (this.option == null) {
// console.log('url-' + this.url.substring(this.url.indexOf('?')))
}
if (this.label == null) {
}
}
return this.url;
}
if (this.dictCode != null && this.dictCode.trim() != "") {
return `/meta/gaeaDict/select/${this.dictCode}`;
}
return null;
}
},
watch: {
dictCode(val) {
if (val) {
this.queryData();
}
},
// 监听接口地址变化时,触发刷新请求
localOptions(val) {
this.options = val;
},
value: {
handler(val) {
if (
typeof val == "string" &&
this.url != null &&
this.url.trim() != ""
) {
this.remoteQuery(val);
}
if (this.multiple != null) {
if (!this.value) {
this.selectValue = [];
} else {
this.selectValue = this.value;
}
} else {
if (this.value != null && this.value != undefined) {
this.selectValue = this.value + "";
} else {
this.selectValue = "";
}
}
},
immediate: true
},
url() {
setTimeout(() => {
this.queryData();
}, 500);
}
},
created() {
if (this.multiple != null) {
this.selectValue = this.value;
} else {
if (this.value != null) {
this.selectValue = this.value + "";
}
}
},
mounted() {
if (this.requestUrl == null) {
this.options = this.localOptions;
return;
}
this.queryData();
},
methods: {
// 判断选择是否已经禁用
isDisabledOption(option) {
if (
option == null ||
this.disabledOptions == null ||
this.disabledOptions.length == 0
) {
return false;
}
let currentOptionVal = option[this.option];
return this.disabledOptions.indexOf(currentOptionVal) >= 0;
},
change(value) {
if (value === "") {
value = "";
}
this.$emit("input", value);
// 根据当前值,找出对应的选项
let optionItem = this.options.find(item => item[this.option] == value);
this.$emit("change", value, optionItem);
},
// 根据用户配置的label生成对应的标签
getItemLabel(item, label) {
if (label.indexOf("${") < 0 && label.indexOf("}" < 0)) {
return item[label];
}
let reg = /\$\{[a-zA-Z0-9]*\}/g;
let list = label.match(reg);
// ["${id}", "${text}"]
let result = label;
for (let i = 0; i < list.length; i++) {
let sub = list[i];
let key = sub.replace("${", "").replace("}", "");
result = result.replace(sub, item[key]);
}
return result;
},
// 从本地localStorage取 gaeaDict
getOptionsFromLocalStorage() {
let dicts = JSON.parse(localStorage.getItem("gaeaDict"));
let options = [];
if (!dicts.hasOwnProperty(this.dictCode)) {
return [];
}
let dictItems = dicts[this.dictCode];
for (let i = 0; i < dictItems.length; i++) {
let dictItem = dictItems[i];
options.push({
id: dictItem.id.toString(),
text: dictItem.text,
extend: dictItem.extend
});
}
return options;
},
queryData() {
// 所有从本地localStorage取因为在App.vue中已经请求远程保存到本地了
let options = this.getOptionsFromLocalStorage();
if (this.isNotBlank(options)) {
this.options = options;
return;
}
// 本地localStorage取不到再从远程接口取
if (this.requestUrl == null) {
return;
}
if (
this.method != null &&
this.method.toLocaleLowerCase().trim() == "post"
) {
this.queryDataByPost();
} else {
this.queryDataByGet();
}
},
queryDataByGet(keyword) {
let param = this.deepClone(this.queryParam);
if (this.isNotBlank(keyword)) {
param["keyword"] = keyword;
}
param["multiple"] = this.multiple == null ? null : 1;
request({
url: this.requestUrl,
headers: { noPrompt: true },
params: param
}).then(response => {
this.setOptions(response.data);
});
},
queryDataByPost(keyword) {
let param = this.deepClone(this.queryParam);
if (this.isNotBlank(keyword)) {
param["keyword"] = keyword;
}
request({
url: this.requestUrl,
method: "post",
headers: { noPrompt: true },
data: param
}).then(response => {
this.setOptions(response.data);
});
},
setOptions(resData) {
if (resData == null || resData.length == 0) {
this.options = [];
this.totalPage = 0;
return;
}
if (this.isArray(resData)) {
this.options = resData;
this.totalPage = 1;
return;
}
if (
resData.records == null ||
resData.total == null ||
resData.pages == null
) {
this.options = [];
return;
}
this.totalPage = resData.pages;
this.options = resData.records;
},
remoteQuery(keyword) {
setTimeout(() => {
if (
this.method != null &&
this.method.toLocaleLowerCase().trim() == "post"
) {
this.queryDataByPost(keyword);
} else {
this.queryDataByGet(keyword);
}
}, 200);
}
}
};
</script>
<style lang="scss" scoped>
.el-select {
width: 100%;
}
.el-select-dropdown__item.selected {
text-align: center;
}
.el-select-dropdown__item.is-disabled {
text-align: center;
}
</style>