|
@@ -0,0 +1,300 @@
|
|
|
+<!--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"
|
|
|
+ :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 style="float: right; color: #8492a6; font-size: 13px">{{ item[option] }}</span>
|
|
|
+ </template>
|
|
|
+ </el-option>
|
|
|
+ <el-option v-if="totalPage > 1"
|
|
|
+ label="搜索更多"
|
|
|
+ value=""
|
|
|
+ disabled />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import request from '@/utils/request'
|
|
|
+export default {
|
|
|
+ props: {
|
|
|
+ dictCode: null, // 当传入dictCode时,可以不用传递url
|
|
|
+ url: null,
|
|
|
+ method: null,
|
|
|
+ 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: false,
|
|
|
+ },
|
|
|
+ // 禁用的下拉选项
|
|
|
+ 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.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: {
|
|
|
+ value: function (val, oldVal) {
|
|
|
+ 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 = ''
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ var currentOptionVal = option[this.option]
|
|
|
+ return this.disabledOptions.indexOf(currentOptionVal) >= 0
|
|
|
+ },
|
|
|
+ change (value) {
|
|
|
+ if (value === '') {
|
|
|
+ value = null
|
|
|
+ }
|
|
|
+ this.$emit('input', value)
|
|
|
+
|
|
|
+ // 根据当前值,找出对应的选项
|
|
|
+ var 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]
|
|
|
+ }
|
|
|
+ var reg = /\$\{[a-zA-Z0-9]*\}/g
|
|
|
+ var list = label.match(reg)
|
|
|
+ // ["${id}", "${text}"]
|
|
|
+ var result = label
|
|
|
+ for (var i = 0; i < list.length; i++) {
|
|
|
+ var sub = list[i]
|
|
|
+ var key = sub.replace('${', '').replace('}', '')
|
|
|
+ result = result.replace(sub, item[key])
|
|
|
+ }
|
|
|
+ return result
|
|
|
+ },
|
|
|
+ // 从本地localStorage取 gaeaDict
|
|
|
+ getOptionsFromLocalStorage () {
|
|
|
+ var dicts = JSON.parse(localStorage.getItem('gaeaDict'))
|
|
|
+ var options = []
|
|
|
+ if (!dicts.hasOwnProperty(this.dictCode)) {
|
|
|
+ return []
|
|
|
+ }
|
|
|
+ var dictItems = dicts[this.dictCode]
|
|
|
+ for (var i = 0; i < dictItems.length; i++) {
|
|
|
+ var dictItem = dictItems[i]
|
|
|
+ options.push({ id: dictItem.id, text: dictItem.text })
|
|
|
+ }
|
|
|
+ return options
|
|
|
+ },
|
|
|
+ queryData () {
|
|
|
+ // 所有从本地localStorage取,因为在App.vue中已经请求远程保存到本地了
|
|
|
+ var 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) {
|
|
|
+ var 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) {
|
|
|
+ var 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
|
|
|
+ // resData.records
|
|
|
+ // resData.total
|
|
|
+ // resData.size
|
|
|
+ // resData.current
|
|
|
+ this.options = resData.records
|
|
|
+ },
|
|
|
+ remoteQuery (keyword) {
|
|
|
+ if (this.isBlank(keyword)) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ setTimeout(() => {
|
|
|
+ if (this.method != null && this.method.toLocaleLowerCase().trim() == 'post') {
|
|
|
+ this.queryDataByPost(keyword)
|
|
|
+ } else {
|
|
|
+ this.queryDataByGet(keyword)
|
|
|
+ }
|
|
|
+ }, 200)
|
|
|
+ },
|
|
|
+ },
|
|
|
+}
|
|
|
+</script>
|