262 lines
6.8 KiB
JavaScript
262 lines
6.8 KiB
JavaScript
|
import debounce from 'lodash/debounce'
|
|||
|
import { getAction } from '@/api/manage'
|
|||
|
import { cloneObject } from '@/utils/util'
|
|||
|
import { filterDictText } from '@/components/dict/JDictSelectUtil'
|
|||
|
import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
|
|||
|
import JVxeCellMixins, { dispatchEvent } from '@/components/jeecg/JVxeTable/mixins/JVxeCellMixins'
|
|||
|
|
|||
|
/** 公共资源 */
|
|||
|
const common = {
|
|||
|
/** value - label map,防止重复查询(刷新清空缓存) */
|
|||
|
labelMap: new Map(),
|
|||
|
|
|||
|
/** 公共data */
|
|||
|
data() {
|
|||
|
return {
|
|||
|
loading: false,
|
|||
|
innerSelectValue: null,
|
|||
|
innerOptions: [],
|
|||
|
}
|
|||
|
},
|
|||
|
/** 公共计算属性 */
|
|||
|
computed: {
|
|||
|
dict() {
|
|||
|
return this.originColumn.dict
|
|||
|
},
|
|||
|
options() {
|
|||
|
if (this.isAsync) {
|
|||
|
return this.innerOptions
|
|||
|
} else {
|
|||
|
return this.originColumn.options || []
|
|||
|
}
|
|||
|
},
|
|||
|
// 是否是异步模式
|
|||
|
isAsync() {
|
|||
|
let isAsync = this.originColumn.async
|
|||
|
return (isAsync != null && isAsync !== '') ? !!isAsync : true
|
|||
|
},
|
|||
|
},
|
|||
|
/** 公共属性监听 */
|
|||
|
watch: {
|
|||
|
innerValue: {
|
|||
|
immediate: true,
|
|||
|
handler(value) {
|
|||
|
if (value == null || value === '') {
|
|||
|
this.innerSelectValue = null
|
|||
|
} else {
|
|||
|
this.loadDataByValue(value)
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
dict() {
|
|||
|
this.loadDataByDict()
|
|||
|
}
|
|||
|
},
|
|||
|
/** 公共方法 */
|
|||
|
methods: {
|
|||
|
|
|||
|
// 根据 value 查询数据,用于回显
|
|||
|
async loadDataByValue(value) {
|
|||
|
if (this.isAsync) {
|
|||
|
if (this.innerSelectValue !== value) {
|
|||
|
if (common.labelMap.has(value)) {
|
|||
|
this.innerOptions = cloneObject(common.labelMap.get(value))
|
|||
|
} else {
|
|||
|
let {success, result} = await getAction(`/sys/dict/loadDictItem/${this.dict}`, {key: value})
|
|||
|
if (success && result && result.length > 0) {
|
|||
|
this.innerOptions = [{value: value, text: result[0]}]
|
|||
|
common.labelMap.set(value, cloneObject(this.innerOptions))
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
this.innerSelectValue = (value || '').toString()
|
|||
|
},
|
|||
|
|
|||
|
// 初始化字典
|
|||
|
async loadDataByDict() {
|
|||
|
if (!this.isAsync) {
|
|||
|
// 如果字典项集合有数据
|
|||
|
if (!this.originColumn.options || this.originColumn.options.length === 0) {
|
|||
|
// 根据字典Code, 初始化字典数组
|
|||
|
let dictStr = ''
|
|||
|
if (this.dict) {
|
|||
|
let arr = this.dict.split(',')
|
|||
|
if (arr[0].indexOf('where') > 0) {
|
|||
|
let tbInfo = arr[0].split('where')
|
|||
|
dictStr = tbInfo[0].trim() + ',' + arr[1] + ',' + arr[2] + ',' + encodeURIComponent(tbInfo[1])
|
|||
|
} else {
|
|||
|
dictStr = this.dict
|
|||
|
}
|
|||
|
if (this.dict.indexOf(',') === -1) {
|
|||
|
//优先从缓存中读取字典配置
|
|||
|
let cache = getDictItemsFromCache(this.dict)
|
|||
|
if (cache) {
|
|||
|
this.innerOptions = cache
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
let {success, result} = await ajaxGetDictItems(dictStr, null)
|
|||
|
if (success) {
|
|||
|
this.innerOptions = result
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
},
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// 显示组件,自带翻译
|
|||
|
export const DictSearchSpanCell = {
|
|||
|
name: 'JVxeSelectSearchSpanCell',
|
|||
|
mixins: [JVxeCellMixins],
|
|||
|
data() {
|
|||
|
return {
|
|||
|
...common.data.apply(this),
|
|||
|
}
|
|||
|
},
|
|||
|
computed: {
|
|||
|
...common.computed,
|
|||
|
},
|
|||
|
watch: {
|
|||
|
...common.watch,
|
|||
|
},
|
|||
|
methods: {
|
|||
|
...common.methods,
|
|||
|
},
|
|||
|
render(h) {
|
|||
|
return h('span', {}, [
|
|||
|
filterDictText(this.innerOptions, this.innerSelectValue || this.innerValue)
|
|||
|
])
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
// 请求id
|
|||
|
let requestId = 0
|
|||
|
|
|||
|
// 输入选择组件
|
|||
|
export const DictSearchInputCell = {
|
|||
|
name: 'JVxeSelectSearchInputCell',
|
|||
|
mixins: [JVxeCellMixins],
|
|||
|
data() {
|
|||
|
return {
|
|||
|
...common.data.apply(this),
|
|||
|
|
|||
|
hasRequest: false,
|
|||
|
scopedSlots: {
|
|||
|
notFoundContent: () => {
|
|||
|
if (this.loading) {
|
|||
|
return <a-spin size="small"/>
|
|||
|
} else if (this.hasRequest) {
|
|||
|
return <div>没有查询到任何数据</div>
|
|||
|
} else {
|
|||
|
return <div>{this.tipsContent}</div>
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
computed: {
|
|||
|
...common.computed,
|
|||
|
tipsContent() {
|
|||
|
return this.originColumn.tipsContent || '请输入搜索内容'
|
|||
|
},
|
|||
|
filterOption() {
|
|||
|
if (this.isAsync) {
|
|||
|
return null
|
|||
|
}
|
|||
|
return (input, option) => option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|||
|
},
|
|||
|
},
|
|||
|
watch: {
|
|||
|
...common.watch,
|
|||
|
},
|
|||
|
created() {
|
|||
|
this.loadData = debounce(this.loadData, 300)//消抖
|
|||
|
},
|
|||
|
methods: {
|
|||
|
...common.methods,
|
|||
|
|
|||
|
loadData(value) {
|
|||
|
const currentRequestId = ++requestId
|
|||
|
this.loading = true
|
|||
|
this.innerOptions = []
|
|||
|
if (value == null || value.trim() === '') {
|
|||
|
this.loading = false
|
|||
|
this.hasRequest = false
|
|||
|
return
|
|||
|
}
|
|||
|
// 字典code格式:table,text,code
|
|||
|
this.hasRequest = true
|
|||
|
getAction(`/sys/dict/loadDict/${this.dict}`, {keyword: value}).then(res => {
|
|||
|
if (currentRequestId !== requestId) {
|
|||
|
return
|
|||
|
}
|
|||
|
let {success, result, message} = res
|
|||
|
if (success) {
|
|||
|
this.innerOptions = result
|
|||
|
result.forEach((item) => {
|
|||
|
common.labelMap.set(item.value, [item])
|
|||
|
})
|
|||
|
} else {
|
|||
|
this.$message.warning(message)
|
|||
|
}
|
|||
|
}).finally(() => {
|
|||
|
this.loading = false
|
|||
|
})
|
|||
|
},
|
|||
|
|
|||
|
handleChange(selectedValue) {
|
|||
|
this.innerSelectValue = selectedValue
|
|||
|
this.handleChangeCommon(this.innerSelectValue)
|
|||
|
},
|
|||
|
handleSearch(value) {
|
|||
|
if (this.isAsync) {
|
|||
|
// 在输入时也应该开启加载,因为loadData加了消抖,所以会有800ms的用户主观上认为的卡顿时间
|
|||
|
this.loading = true
|
|||
|
if (this.innerOptions.length > 0) {
|
|||
|
this.innerOptions = []
|
|||
|
}
|
|||
|
this.loadData(value)
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
renderOptionItem() {
|
|||
|
let options = []
|
|||
|
this.options.forEach(({value, text, label, title, disabled}) => {
|
|||
|
options.push(
|
|||
|
<a-select-option key={value} value={value} disabled={disabled}>{text || label || title}</a-select-option>
|
|||
|
)
|
|||
|
})
|
|||
|
return options
|
|||
|
},
|
|||
|
},
|
|||
|
render() {
|
|||
|
return (
|
|||
|
<a-select
|
|||
|
showSearch
|
|||
|
allowClear
|
|||
|
value={this.innerSelectValue}
|
|||
|
filterOption={this.filterOption}
|
|||
|
style="width: 100%"
|
|||
|
{...this.cellProps}
|
|||
|
onSearch={this.handleSearch}
|
|||
|
onChange={this.handleChange}
|
|||
|
scopedSlots={this.scopedSlots}
|
|||
|
>
|
|||
|
{this.renderOptionItem()}
|
|||
|
</a-select>
|
|||
|
)
|
|||
|
},
|
|||
|
// 【组件增强】注释详见:JVxeCellMixins.js
|
|||
|
enhanced: {
|
|||
|
aopEvents: {
|
|||
|
editActived(event) {
|
|||
|
dispatchEvent.call(this, event, 'ant-select')
|
|||
|
},
|
|||
|
},
|
|||
|
}
|
|||
|
}
|