2.1.3 大屏版本发布

This commit is contained in:
zhangdaihao
2019-12-25 13:25:10 +08:00
parent ea5ef384f2
commit 9c44ffaa8e
60 changed files with 2970 additions and 806 deletions

View File

@ -2,7 +2,7 @@
<a-modal
centered
:title="name + '选择'"
:width="900"
:width="width"
:visible="visible"
@ok="handleOk"
@cancel="close"
@ -17,7 +17,7 @@
<a-col :span="14">
<a-form-item :label="(queryParamText||name)">
<a-input :placeholder="'请输入' + (queryParamText||name)" v-model="queryParam[valueKey]"></a-input>
<a-input v-model="queryParam[queryParamCode||valueKey]" :placeholder="'请输入' + (queryParamText||name)" @pressEnter="searchQuery"/>
</a-form-item>
</a-col>
<a-col :span="8">
@ -34,8 +34,8 @@
<a-table
size="small"
bordered
rowKey="id"
:columns="columns"
:rowKey="rowKey"
:columns="innerColumns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
@ -49,7 +49,7 @@
<a-col :span="8">
<a-card :title="'已选' + name" :bordered="false" :head-style="{padding:0}" :body-style="{padding:0}">
<a-table rowKey="id" size="small" bordered v-bind="selectedTable">
<a-table size="small" :rowKey="rowKey" bordered v-bind="selectedTable">
<span slot="action" slot-scope="text, record, index">
<a @click="handleDeleteSelected(record, index)">删除</a>
</span>
@ -62,7 +62,9 @@
</template>
<script>
import { getAction } from '@/api/manage'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import { cloneObject, pushIfNotExist } from '@/utils/util'
export default {
name: 'JSelectBizComponentModal',
@ -84,6 +86,10 @@
type: Boolean,
default: true
},
width: {
type: Number,
default: 900
},
name: {
type: String,
@ -94,60 +100,110 @@
required: true,
default: ''
},
// 根据 value 获取显示文本的地址,例如存的是 username可以通过该地址获取到 realname
valueUrl: {
type: String,
default: ''
},
displayKey: {
type: String,
default: null
},
propColumns: {
columns: {
type: Array,
required: true,
default: () => []
},
// 查询条件Code
queryParamCode: {
type: String,
default: null
},
// 查询条件文字
queryParamText: {
type: String,
default: null
},
rowKey: {
type: String,
default: 'id'
},
},
data() {
return {
innerValue: [],
// 表头
columns: this.propColumns,
innerColumns: this.columns,
// 已选择列表
selectedTable: {
pagination: false,
scroll: { y: 240 },
columns: [
this.propColumns[0],
{
...this.columns[0],
width: this.columns[0].widthRight || this.columns[0].width,
},
{ title: '操作', dataIndex: 'action', align: 'center', width: 60, scopedSlots: { customRender: 'action' }, }
],
dataSource: [],
},
url: { list: this.listUrl }
url: { list: this.listUrl },
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' 共' + total + '条'
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
options: [],
dataSourceMap: {},
}
},
watch: {
value: {
deep: true,
immediate: true,
handler(val) {
this.innerValue = cloneObject(val)
this.selectedRowKeys = []
this.valueWatchHandler(val)
this.queryOptionsByValue(val)
}
},
dataSource: {
deep: true,
handler(val) {
let options = val.map(data => ({ label: data[this.displayKey || this.valueKey], value: data[this.valueKey] }))
this.$emit('ok', options)
this.valueWatchHandler(this.value)
this.emitOptions(val)
this.valueWatchHandler(this.innerValue)
}
},
selectionRows: {
selectedRowKeys: {
immediate: true,
deep: true,
handler(val) {
this.selectedTable.dataSource = val
this.selectedTable.dataSource = val.map(key => {
for (let data of this.dataSource) {
if (data[this.rowKey] === key) {
pushIfNotExist(this.innerValue, data[this.valueKey])
return data
}
}
for (let data of this.selectedTable.dataSource) {
if (data[this.rowKey] === key) {
pushIfNotExist(this.innerValue, data[this.valueKey])
return data
}
}
console.warn('未找到选择的行信息key' + key)
return {}
})
},
},
}
},
methods: {
@ -158,18 +214,63 @@
},
valueWatchHandler(val) {
let dataSource = []
let selectedRowKeys = []
val.forEach(item => {
this.dataSource.forEach(data => {
this.dataSource.concat(this.selectedTable.dataSource).forEach(data => {
if (data[this.valueKey] === item) {
dataSource.push(data)
selectedRowKeys.push(data.id)
pushIfNotExist(this.selectedRowKeys, data[this.rowKey])
}
})
})
this.selectedTable.dataSource = dataSource
this.selectedRowKeys = selectedRowKeys
},
queryOptionsByValue(value) {
if (!value || value.length === 0) {
return
}
// 判断options是否存在value如果已存在数据就不再请求后台了
let notExist = false
for (let val of value) {
let find = false
for (let option of this.options) {
if (val === option.value) {
find = true
break
}
}
if (!find) {
notExist = true
break
}
}
if (!notExist) return
getAction(this.valueUrl || this.listUrl, {
// 这里最后加一个 , 的原因是因为无论如何都要使用 in 查询,防止后台进行了模糊匹配,导致查询结果不准确
[this.valueKey]: value.join(',') + ',',
pageNo: 1,
pageSize: value.length
}).then((res) => {
if (res.success) {
let dataSource = res.result
if (!(dataSource instanceof Array)) {
dataSource = res.result.records
}
this.emitOptions(dataSource, (data) => {
pushIfNotExist(this.innerValue, data[this.valueKey])
pushIfNotExist(this.selectedRowKeys, data[this.rowKey])
pushIfNotExist(this.selectedTable.dataSource, data, this.rowKey)
})
}
})
},
emitOptions(dataSource, callback) {
dataSource.forEach(data => {
let key = data[this.valueKey]
this.dataSourceMap[key] = data
pushIfNotExist(this.options, { label: data[this.displayKey || this.valueKey], value: key }, 'value')
typeof callback === 'function' ? callback(data) : ''
})
this.$emit('options', this.options, this.dataSourceMap)
},
/** 完成选择 */
@ -181,22 +282,30 @@
/** 删除已选择的 */
handleDeleteSelected(record, index) {
this.selectedRowKeys.splice(this.selectedRowKeys.indexOf(record.id), 1)
this.selectedRowKeys.splice(this.selectedRowKeys.indexOf(record[this.rowKey]), 1)
this.selectedTable.dataSource.splice(index, 1)
},
customRowFn(record) {
if (!this.multiple) {
return {
on: {
click: () => {
this.selectedRowKeys = [record.id]
return {
on: {
click: () => {
let key = record[this.rowKey]
if (!this.multiple) {
this.selectedRowKeys = [key]
this.selectedTable.dataSource = [record]
} else {
let index = this.selectedRowKeys.indexOf(key)
if (index === -1) {
this.selectedRowKeys.push(key)
this.selectedTable.dataSource.push(record)
} else {
this.handleDeleteSelected(record, index)
}
}
}
}
}
return {}
},
}

View File

@ -16,11 +16,21 @@ export default {
### 配置参数
- `name`:`String` 显示名字,例如选择部门就填写'部门'
- `listUrl`:`String` 数据请求地址,必须是封装了分页的地址
- `displayKey`:`String` 显示在标签上的字段 key
- `returnKeys`:`Array` v-model 绑定的 keys是个数组默认使用第二项当配置了 `returnId=true` 就返回第一项
- `returnId`:`Boolean` 返回ID设为true后将返回配置的 `returnKeys` 中的第一项
- `selectButtonText`:`String` 选择按钮的文字
- `queryParamText`:`String` 查询条件显示文字
- `columns`:`Array` 列配置项与a-table的列配置项相同会将第一项配置成已选择的列表
| 参数名 | 类型 | 必填 | 默认值 | 备注 |
|-----------------------|---------|------|--------------|--------------------------------------------------------------------------------------|
| rowKey | String | | "id" | 唯一标识的字段名 |
| value(v-model) | String | | "" | 默认选择的数据,多个用半角逗号分割 |
| name | String | | "" | 显示名字,例如选择用户就填写"用户" |
| listUrl | String | 是 | | 数据请求地址,必须是封装了分页的地址 |
| valueUrl | String | | "" | 获取显示文本的地址,例如存的是 username可以通过该地址获取到 realname |
| displayKey | String | | null | 显示在标签上的字段 key ,不传则直接显示数据 |
| returnKeys | Array | | ['id', 'id'] | v-model 绑定的 keys是个数组默认使用第二项当配置了 `returnId=true` 就返回第一项 |
| returnId | Boolean | | false | 返回ID设为true后将返回配置的 `returnKeys` 中的第一项 |
| selectButtonText | String | | "选择" | 选择按钮的文字 |
| queryParamText | String | | null | 查询条件显示文字,不传则使用 `name` |
| columns | Array | 是 | | 列配置项与antd的table的配置完全一致。列的第一项会被配置成右侧已选择的列表上 |
| columns[0].widthRight | Array | | null | 仅列的第一项可以应用此配置,表示右侧已选择列表的宽度,建议 `70%`,不传则应用`width` |
| placeholder | String | | "请选择" | 占位符 |
| disabled | Boolean | | false | 是否禁用 |
| multiple | Boolean | | false | 是否可多选 |
| buttons | Boolean | | true | 是否显示"选择"按钮,如果不显示,可以直接点击文本框打开选择界面 |

View File

@ -1,17 +1,19 @@
<template>
<a-row class="j-select-biz-component-box" type="flex" :gutter="8">
<a-col class="left" :class="{'full': !buttons}">
<a-select
mode="multiple"
:placeholder="placeholder"
v-model="selectValue"
:options="selectOptions"
allowClear
:disabled="disabled"
:open="false"
style="width: 100%;"
@click.native="visible=(buttons?visible:true)"
/>
<slot name="left">
<a-select
mode="multiple"
:placeholder="placeholder"
v-model="selectValue"
:options="selectOptions"
allowClear
:disabled="disabled"
:open="false"
style="width: 100%;"
@click.native="visible=(buttons?visible:true)"
/>
</slot>
</a-col>
<a-col v-if="buttons" class="right">
@ -20,11 +22,9 @@
<j-select-biz-component-modal
v-model="selectValue"
:name="name" :listUrl="listUrl" :returnKeys="returnKeys" :displayKey="displayKey"
:propColumns="columns" :queryParamText="queryParamText" :multiple="multiple"
:visible.sync="visible"
:valueKey="valueKey"
@ok="selectOptions=$event"
v-bind="modalProps"
@options="handleOptions"
/>
</a-row>
</template>
@ -63,20 +63,6 @@
type: Boolean,
default: true
},
/* 可复用属性 */
// 被选择的名字,例如选择部门就填写'部门'
name: {
type: String,
default: ''
},
// list 接口地址
listUrl: {
type: String,
required: true,
default: ''
},
// 显示的 Key
displayKey: {
type: String,
@ -92,29 +78,28 @@
type: String,
default: '选择'
},
// 查询条件文字
queryParamText: {
type: String,
default: null
},
// columns
columns: {
type: Array,
default: () => []
}
},
data() {
return {
selectValue: [],
selectOptions: [],
dataSourceMap: {},
visible: false
}
},
computed: {
valueKey() {
return this.returnId ? this.returnKeys[0] : this.returnKeys[1]
}
},
modalProps() {
return Object.assign({
valueKey: this.valueKey,
multiple: this.multiple,
returnKeys: this.returnKeys,
displayKey: this.displayKey || this.valueKey
}, this.$attrs)
},
},
watch: {
value: {
@ -130,23 +115,23 @@
selectValue: {
deep: true,
handler(val) {
const data = val.join(',')
let rows = val.map(key => this.dataSourceMap[key])
this.$emit('select', rows)
let data = val.join(',')
this.$emit('input', data)
this.$emit('change', data)
}
}
},
methods: {}
methods: {
handleOptions(options, dataSourceMap) {
this.selectOptions = options
this.dataSourceMap = dataSourceMap
},
}
}
</script>
<style lang="scss">
.j-select-biz-component-box {
.ant-select-search__field {
display: none !important;
}
}
</style>
<style lang="scss" scoped>
.j-select-biz-component-box {
@ -163,5 +148,11 @@
.full {
width: 100%;
}
/deep/ {
.ant-select-search__field {
display: none !important;
}
}
}
</style>

View File

@ -1,16 +1,11 @@
<template>
<!-- 定义在这里的参数都是不可在外部覆盖的防止出现问题 -->
<j-select-biz-component
:value="value"
name="用户"
displayKey="realname"
:listUrl="url.list"
:columns="columns"
queryParamText="账号"
v-on="$listeners"
v-bind="$attrs"
v-bind="attrs"
/>
</template>
@ -25,22 +20,24 @@
return {
url: { list: '/sys/user/list' },
columns: [
{ title: '姓名', align: 'center', width: 100, dataIndex: 'realname' },
{ title: '账号', align: 'center', width: 100, dataIndex: 'username' },
{ title: '电话', align: 'center', width: 100, dataIndex: 'phone' },
{ title: '出生日期', align: 'center', width: 100, dataIndex: 'birthday' }
]
{ title: '姓名', align: 'center', width: '20%', widthRight: '70%', dataIndex: 'realname' },
{ title: '账号', align: 'center', width: '20%', dataIndex: 'username' },
{ title: '电话', align: 'center', width: '23%', dataIndex: 'phone' },
{ title: '出生日期', align: 'center', width: '23%', dataIndex: 'birthday' }
],
// 定义在这里的参数都是可以在外部传递覆盖的,可以更灵活的定制化使用的组件
default: {
name: '用户',
width: 1000,
displayKey: 'realname',
returnKeys: ['id', 'username'],
queryParamText: '账号',
}
}
},
watch: {
$attrs: {
deep: true,
immediate: true,
handler(val) {
if (!val.returnKeys) {
val.returnKeys = ['id', 'username']
}
}
computed: {
attrs() {
return Object.assign(this.default, this.$attrs)
}
}
}

View File

@ -1,5 +1,5 @@
<template>
<j-select-biz-component v-bind="configs" v-on="$listeners"/>
<j-select-biz-component :width="1000" v-bind="configs" v-on="$listeners"/>
</template>
<script>
@ -16,11 +16,12 @@
displayKey: 'name',
returnKeys: ['id', 'code'],
listUrl: '/sys/position/list',
queryParamText: '职务编码',
queryParamCode: 'name',
queryParamText: '职务名称',
columns: [
{ title: '职务名称', dataIndex: 'name', align: 'center', width: 100 },
{ title: '职务编码', dataIndex: 'code', align: 'center', width: 100 },
{ title: '职级', dataIndex: 'rank_dictText', align: 'center', width: 100 }
{ title: '职务名称', dataIndex: 'name', align: 'center', width: '30%', widthRight: '70%' },
{ title: '职务编码', dataIndex: 'code', align: 'center', width: '35%' },
{ title: '职级', dataIndex: 'rank_dictText', align: 'center', width: '25%' }
]
}
}

View File

@ -75,11 +75,6 @@
align: 'center',
dataIndex: 'realname'
},
{
title: '角色名称',
align: 'center',
dataIndex: 'roleName'
},
{
title: '性别',
align: 'center',
@ -167,6 +162,9 @@
names = names.substring(1)
}
this.$emit("initComp", names)
}else{
// JSelectUserByDep组件bug issues/I16634
this.$emit("initComp", "")
}
},
async loadData(arg) {