first commit

This commit is contained in:
2024-04-01 10:37:33 +08:00
parent c4a761681e
commit 86b8709481
842 changed files with 322001 additions and 59 deletions
+107
View File
@@ -0,0 +1,107 @@
<template>
<a-radio-group v-if="tagType==='radio'" @change="handleInput" :value="getValueSting" :disabled="disabled">
<a-radio v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio>
</a-radio-group>
<a-radio-group v-else-if="tagType==='radioButton'" buttonStyle="solid" @change="handleInput" :value="getValueSting" :disabled="disabled">
<a-radio-button v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio-button>
</a-radio-group>
<a-select v-else-if="tagType==='select'" :getPopupContainer = "getPopupContainer" :placeholder="placeholder" :disabled="disabled" :value="getValueSting" @change="handleInput">
<a-select-option :value="undefined">请选择</a-select-option>
<a-select-option v-for="(item, key) in dictOptions" :key="key" :value="item.value">
<span style="display: inline-block;width: 100%" :title=" item.text || item.label ">
{{ item.text || item.label }}
</span>
</a-select-option>
</a-select>
</template>
<script>
import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
export default {
name: 'JDictSelectTag',
props: {
dictCode: String,
placeholder: String,
disabled: Boolean,
value: [String, Number],
type: String,
getPopupContainer: {
type: Function,
default: (node) => node.parentNode
}
},
data () {
return {
dictOptions: [],
tagType: ''
}
},
watch: {
dictCode: {
immediate: true,
handler () {
this.initDictData()
}
}
},
created () {
if (!this.type || this.type === 'list') {
this.tagType = 'select'
} else {
this.tagType = this.type
}
},
computed: {
getValueSting () {
// update-begin author:wangshuai date:20200601 for: 不显示placeholder的文字 ------
// 当有null或“” placeholder不显示
return this.value != null ? this.value.toString() : undefined
// update-end author:wangshuai date:20200601 for: 不显示placeholder的文字 ------
}
},
methods: {
initDictData () {
// 优先从缓存中读取字典配置
if (getDictItemsFromCache(this.dictCode)) {
this.dictOptions = getDictItemsFromCache(this.dictCode)
return
}
// 根据字典Code, 初始化字典数组
ajaxGetDictItems(this.dictCode, null).then((res) => {
if (res.success) {
this.dictOptions = res.result
}
})
},
handleInput (e = '') {
let val
if (Object.keys(e).includes('target')) {
val = e.target.value
} else {
val = e
}
console.log(val)
this.$emit('change', val)
// 解决数据规则,选择自定义SQL 规则值无法输入空格
this.$emit('input', val)
},
setCurrentDictOptions (dictOptions) {
this.dictOptions = dictOptions
},
getCurrentDictOptions () {
return this.dictOptions
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped>
</style>
+146
View File
@@ -0,0 +1,146 @@
/**
* 字典 util
* author: scott
* date: 20190109
*/
import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
// import { getAction } from '@/api/manage'
/**
* 获取字典数组
* @param dictCode 字典Code
* @return List<Map>
*/
export async function initDictOptions (dictCode) {
if (!dictCode) {
return '字典Code不能为空!'
}
// 优先从缓存中读取字典配置
if (getDictItemsFromCache(dictCode)) {
const res = {}
res.result = getDictItemsFromCache(dictCode)
res.success = true
return res
}
// 获取字典数组
return (await ajaxGetDictItems(dictCode))
}
/**
* 字典值替换文本通用方法
* @param dictOptions 字典数组
* @param text 字典值
* @return String
*/
export function filterDictText (dictOptions, text) {
// --update-begin----author:sunjianlei---date:20200323------for: 字典翻译 text 允许逗号分隔 ---
if (text != null && Array.isArray(dictOptions)) {
const result = []
// 允许多个逗号分隔,允许传数组对象
let splitText
if (Array.isArray(text)) {
splitText = text
} else {
splitText = text.toString().trim().split(',')
}
for (const txt of splitText) {
let dictText = txt
for (const dictItem of dictOptions) {
if (txt.toString() === dictItem.value.toString()) {
dictText = (dictItem.text || dictItem.title || dictItem.label)
break
}
}
result.push(dictText)
}
return result.join(',')
}
return text
// --update-end----author:sunjianlei---date:20200323------for: 字典翻译 text 允许逗号分隔 ---
}
/**
* 字典值替换文本通用方法(多选)
* @param dictOptions 字典数组
* @param text 字典值
* @return String
*/
export function filterMultiDictText (dictOptions, text) {
// js “!text” 认为0为空,所以做提前处理
if (text === 0 || text === '0') {
if (dictOptions) {
for (const dictItem of dictOptions) {
if ((text + '') === (dictItem.value + '')) {
return dictItem.text
}
}
}
}
if (!text || text === 'null' || !dictOptions || dictOptions.length === 0) {
return ''
}
let re = ''
text = text.toString()
const arr = text.split(',')
dictOptions.forEach(function (option) {
if (option) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] === option.value) {
re += option.text + ','
break
}
}
}
})
if (re === '') {
return text
}
return re.substring(0, re.length - 1)
}
/**
* 翻译字段值对应的文本
* @returns string
* @param dictCode
* @param key
*/
export function filterDictTextByCache (dictCode, key) {
if (key === null || key === undefined || key.length === 0) {
return ''
}
if (!dictCode) {
return '字典Code不能为空!'
}
// 优先从缓存中读取字典配置
if (getDictItemsFromCache(dictCode)) {
const item = getDictItemsFromCache(dictCode).filter(t => t.value + '' === key + '')
if (item && item.length > 0) {
return item[0].text
}
}
}
/** 通过code获取字典数组 */
export async function getDictItems (dictCode, params) {
// 优先从缓存中读取字典配置
if (getDictItemsFromCache(dictCode)) {
return getDictItemsFromCache(dictCode).map(item => ({ ...item, label: item.text }))
}
// 缓存中没有,就请求后台
return await ajaxGetDictItems(dictCode, params).then(({ success, result }) => {
if (success) {
const res = result.map(item => ({ ...item, label: item.text }))
console.log('------- 从DB中获取到了字典-------dictCode : ', dictCode, res)
return Promise.resolve(res)
} else {
console.error('getDictItems error: : ', result)
return Promise.resolve([])
}
}).catch((res) => {
console.error('getDictItems error: ', res)
return Promise.resolve([])
})
}
+121
View File
@@ -0,0 +1,121 @@
<template>
<a-checkbox-group v-if="tagType==='checkbox'" @change="onChange" :value="arrayValue" :disabled="disabled">
<a-checkbox v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text || item.label }}</a-checkbox>
</a-checkbox-group>
<a-select
v-else-if="tagType==='select'"
:value="arrayValue"
@change="onChange"
:disabled="disabled"
mode="multiple"
:placeholder="placeholder"
:getPopupContainer="getParentContainer"
optionFilterProp="children"
:filterOption="filterOption"
allowClear
:options="dictOptions">
</a-select>
</template>
<script>
import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
export default {
name: 'JMultiSelectTag',
props: {
dictCode: String,
placeholder: String,
disabled: Boolean,
value: String,
type: String,
options: Array,
spliter: {
type: String,
required: false,
default: ','
},
popContainer: {
type: String,
default: '',
required: false
}
},
data () {
return {
dictOptions: [],
tagType: '',
arrayValue: !this.value ? [] : this.value.split(this.spliter)
}
},
created () {
if (!this.type || this.type === 'list_multi') {
this.tagType = 'select'
} else {
this.tagType = this.type
}
// 获取字典数据
// this.initDictData();
},
watch: {
options (val) {
val.forEach((item, index) => {
this.$set(this.dictOptions, index, item)
})
},
dictCode: {
immediate: true,
handler () {
this.initDictData()
}
},
value (val) {
if (!val) {
this.arrayValue = []
} else {
this.arrayValue = this.value.split(this.spliter)
}
}
},
methods: {
initDictData () {
if (this.options && this.options.length > 0) {
this.dictOptions = [...this.options]
} else {
// 优先从缓存中读取字典配置
const cacheOption = getDictItemsFromCache(this.dictCode)
if (cacheOption && cacheOption.length > 0) {
this.dictOptions = cacheOption
return
}
// 根据字典Code, 初始化字典数组
ajaxGetDictItems(this.dictCode, null).then((res) => {
if (res.success) {
this.dictOptions = res.result
}
})
}
},
onChange (selectedValue) {
this.arrayValue = selectedValue
this.$emit('change', selectedValue.join(this.spliter))
},
getParentContainer (node) {
if (!this.popContainer) {
return node.parentNode
} else {
return document.querySelector(this.popContainer)
}
},
// update--begin--autor:lvdandan-----date:20201120------forLOWCOD-1086 下拉多选框,搜索时只字典code进行搜索不能通过字典text搜索
filterOption (input, option) {
return option.componentOptions.children[0].children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
// update--end--autor:lvdandan-----date:20201120------forLOWCOD-1086 下拉多选框,搜索时只字典code进行搜索不能通过字典text搜索
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
+254
View File
@@ -0,0 +1,254 @@
<template>
<a-select
v-if="async"
showSearch
labelInValue
:disabled="disabled"
:getPopupContainer="getParentContainer"
@search="loadData"
:placeholder="placeholder"
v-model="selectedAsyncValue"
style="width: 100%"
:filterOption="false"
@change="handleAsyncChange"
allowClear
:notFoundContent="loading ? undefined : null"
>
<a-spin v-if="loading" slot="notFoundContent" size="small"/>
<a-select-option v-for="d in options" :key="d.value" :value="d.value">{{ d.text }}</a-select-option>
</a-select>
<a-select
v-else
:getPopupContainer="getParentContainer"
showSearch
:disabled="disabled"
:placeholder="placeholder"
optionFilterProp="children"
style="width: 100%"
@change="handleChange"
:filterOption="filterOption"
v-model="selectedValue"
allowClear
:notFoundContent="loading ? undefined : null">
<a-spin v-if="loading" slot="notFoundContent" size="small"/>
<a-select-option v-for="d in options" :key="d.value" :value="d.value">{{ d.text }}</a-select-option>
</a-select>
</template>
<script>
import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
import debounce from 'lodash/debounce'
import { getAction } from '@api/manage'
export default {
name: 'JSearchSelectTag',
props: {
disabled: Boolean,
value: [String, Number],
dict: String,
dictOptions: Array,
async: Boolean,
placeholder: {
type: String,
default: '请选择',
required: false
},
popContainer: {
type: String,
default: '',
required: false
},
pageSize: {
type: Number,
default: 10,
required: false
},
getPopupContainer: {
type: Function,
default: null
}
},
data () {
this.loadData = debounce(this.loadData, 800)// 消抖
this.lastLoad = 0
return {
loading: false,
selectedValue: [],
selectedAsyncValue: [],
options: []
}
},
created () {
this.initDictData()
},
watch: {
value: {
immediate: true,
handler (val) {
if (!val) {
if (val === 0) {
this.initSelectValue()
} else {
this.selectedValue = []
this.selectedAsyncValue = []
}
} else {
this.initSelectValue()
}
}
},
dict: {
handler () {
this.initDictData()
}
},
dictOptions: {
deep: true,
handler (val) {
if (val && val.length > 0) {
this.options = [...val]
}
}
}
},
methods: {
initSelectValue () {
if (this.async) {
if (!this.selectedAsyncValue || !this.selectedAsyncValue.key || (this.selectedAsyncValue.key + '') !== (this.value + '')) {
console.log('这才请求后台')
getAction(`/sys/dict/loadDictItem/${this.dict}`, { key: this.value }).then(res => {
if (res.success) {
const obj = {
key: this.value,
label: res.result
}
this.selectedAsyncValue = { ...obj }
}
})
}
} else {
this.selectedValue = this.value.toString()
}
},
loadData (value) {
console.log('数据加载', value)
this.lastLoad += 1
const currentLoad = this.lastLoad
this.options = []
this.loading = true
// 字典code格式:table,text,code
getAction(`/sys/dict/loadDict/${this.dict}`, { keyword: value, pageSize: this.pageSize }).then(res => {
this.loading = false
if (res.success) {
if (currentLoad !== this.lastLoad) {
return
}
this.options = res.result
console.log('我是第一个', res)
} else {
this.$message.warning(res.message)
}
})
},
initDictData () {
if (!this.async) {
// 如果字典项集合有数据
if (this.dictOptions && this.dictOptions.length > 0) {
this.options = [...this.dictOptions]
} else {
// 根据字典Code, 初始化字典数组
let dictStr = ''
if (this.dict) {
const arr = this.dict.split(',')
if (arr[0].indexOf('where') > 0) {
const 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) {
// 优先从缓存中读取字典配置
if (getDictItemsFromCache(this.dictCode)) {
this.options = getDictItemsFromCache(this.dictCode)
return
}
}
ajaxGetDictItems(dictStr, null).then((res) => {
if (res.success) {
this.options = res.result
}
})
}
}
} else {
if (!this.dict) {
console.error('搜索组件未配置字典项')
} else {
// 异步一开始也加载一点数据
this.loading = true
getAction(`/sys/dict/loadDict/${this.dict}`, { pageSize: this.pageSize, keyword: '' }).then(res => {
this.loading = false
if (res.success) {
this.options = res.result
} else {
this.$message.warning(res.message)
}
})
}
}
},
filterOption (input, option) {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
handleChange (selectedValue) {
console.log('selectedValue', selectedValue)
this.selectedValue = selectedValue
this.callback()
},
handleAsyncChange (selectedObj) {
// update-begin-author:scott date:20201222 for:【搜索】搜索查询组件,删除条件,默认下拉还是上次的缓存数据,不好 JT-191
if (selectedObj) {
this.selectedAsyncValue = selectedObj
this.selectedValue = selectedObj.key
} else {
this.selectedAsyncValue = null
this.selectedValue = null
this.options = null
this.loadData('')
}
this.callback()
// update-end-author:scott date:20201222 for:【搜索】搜索查询组件,删除条件,默认下拉还是上次的缓存数据,不好 JT-191
},
callback () {
this.$emit('change', this.selectedValue)
},
setCurrentDictOptions (dictOptions) {
this.options = dictOptions
},
getCurrentDictOptions () {
return this.options
},
getParentContainer (node) {
if (typeof this.getPopupContainer === 'function') {
return this.getPopupContainer(node)
} else if (!this.popContainer) {
return node.parentNode
} else {
return document.querySelector(this.popContainer)
}
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped>
</style>
+181
View File
@@ -0,0 +1,181 @@
# JDictSelectTag 组件用法
----
- 从字典表获取数据,dictCode格式说明: 字典code
```html
<j-dict-select-tag v-model="queryParam.sex" placeholder="请输入用户性别"
dictCode="sex"/>
```
v-decorator用法:
```html
<j-dict-select-tag v-decorator="['sex', {}]" :triggerChange="true" placeholder="请输入用户性别"
dictCode="sex"/>
```
- 从数据库表获取字典数据,dictCode格式说明: 表名,文本字段,取值字段
```html
<j-dict-select-tag v-model="queryParam.username" placeholder="请选择用户名称"
dictCode="sys_user,realname,id"/>
```
# JDictSelectUtil.js 列表字典函数用法
----
- 第一步: 引入依赖方法
```html
import {initDictOptions, filterDictText} from '@/components/dict/JDictSelectUtil'
```
- 第二步: 在created()初始化方法执行字典配置方法
```html
//初始化字典配置
this.initDictConfig();
```
- 第三步: 实现initDictConfig方法,加载列表所需要的字典(列表上有多个字典项,就执行多次initDictOptions方法)
```html
initDictConfig() {
//初始化字典 - 性别
initDictOptions('sex').then((res) => {
if (res.success) {
this.sexDictOptions = res.result;
}
});
},
```
- 第四步: 实现字段的customRender方法
```html
customRender: (text, record, index) => {
//字典值替换通用方法
return filterDictText(this.sexDictOptions, text);
}
```
# JMultiSelectTag 多选组件
下拉/checkbox
## 参数配置
| 参数 | 类型 | 必填 |说明|
|--------------|---------|----|---------|
| placeholder |string | | placeholder |
| disabled |Boolean | | 是否禁用 |
| type |string | | 多选类型 select/checkbox 默认是select |
| dictCode |string | | 数据字典编码或者表名,显示字段名,存储字段名拼接而成的字符串,如果提供了options参数 则此参数可不填|
| options |Array | | 多选项,如果dictCode参数未提供,可以设置此参数加载多选项 |
使用示例
----
```vue
<template>
<a-form>
<a-form-item label="下拉多选" style="width: 300px">
<j-multi-select-tag
v-model="selectValue"
:options="dictOptions"
placeholder="请做出你的选择">
</j-multi-select-tag>
{{ selectValue }}
</a-form-item>
<a-form-item label="checkbox">
<j-multi-select-tag
v-model="checkboxValue"
:options="dictOptions"
type="checkbox">
</j-multi-select-tag>
{{ checkboxValue }}
</a-form-item>
</a-form >
</template>
<script>
import JMultiSelectTag from '@/components/dict/JMultiSelectTag'
export default {
components: {JMultiSelectTag},
data() {
return {
selectValue:"",
checkboxValue:"",
dictOptions:[{
label:"选项一",
value:"1"
},{
label:"选项二",
value:"2"
},{
label:"选项三",
value:"3"
}]
}
}
}
</script>
```
# JSearchSelectTag 字典表的搜索组件
下拉搜索组件,支持异步加载,异步加载用于大数据量的字典表
## 参数配置
| 参数 | 类型 | 必填 |说明|
|--------------|---------|----|---------|
| placeholder |string | | placeholder |
| disabled |Boolean | | 是否禁用 |
| dict |string | | 表名,显示字段名,存储字段名拼接而成的字符串,如果提供了dictOptions参数 则此参数可不填|
| dictOptions |Array | | 多选项,如果dict参数未提供,可以设置此参数加载多选项 |
| async |Boolean | | 是否支持异步加载,设置成true,则通过输入的内容加载远程数据,否则在本地过滤数据,默认false|
使用示例
----
```vue
<template>
<a-form>
<a-form-item label="下拉搜索" style="width: 300px">
<j-search-select-tag
placeholder="请做出你的选择"
v-model="selectValue"
:dictOptions="dictOptions">
</j-search-select-tag>
{{ selectValue }}
</a-form-item>
<a-form-item label="异步加载" style="width: 300px">
<j-search-select-tag
placeholder="请做出你的选择"
v-model="asyncSelectValue"
dict="sys_depart,depart_name,id"
:async="true">
</j-search-select-tag>
{{ asyncSelectValue }}
</a-form-item>
</a-form >
</template>
<script>
import JSearchSelectTag from '@/components/dict/JSearchSelectTag'
export default {
components: {JSearchSelectTag},
data() {
return {
selectValue:"",
asyncSelectValue:"",
dictOptions:[{
text:"选项一",
value:"1"
},{
text:"选项二",
value:"2"
},{
text:"选项三",
value:"3"
}]
}
}
}
</script>
```
+16
View File
@@ -0,0 +1,16 @@
import JDictSelectTag from './JDictSelectTag.vue'
import JMultiSelectTag from './JMultiSelectTag.vue'
import JSearchSelectTag from './JSearchSelectTag.vue'
import { filterMultiDictText, filterDictText, initDictOptions, filterDictTextByCache } from './JDictSelectUtil'
export default {
install: function (Vue) {
Vue.component('JDictSelectTag', JDictSelectTag)
Vue.component('JMultiSelectTag', JMultiSelectTag)
Vue.component('JSearchSelectTag', JSearchSelectTag)
Vue.prototype.$initDictOptions = (dictCode) => initDictOptions(dictCode)
Vue.prototype.$filterMultiDictText = (dictOptions, text) => filterMultiDictText(dictOptions, text)
Vue.prototype.$filterDictText = (dictOptions, text) => filterDictText(dictOptions, text)
Vue.prototype.$filterDictTextByCache = (...param) => filterDictTextByCache(...param)
}
}