add 树形分页的字典单选

This commit is contained in:
赵霄
2023-11-02 16:18:17 +08:00
parent 04f4aee416
commit f9d04eba17
8 changed files with 422 additions and 6 deletions
+3
View File
@@ -68,6 +68,8 @@ const editDictItem = (params) => postAction('/sys/dictItem/edit', params)
const getDictTreeList = (params) => getAction('/sys/dictItem/treeList', params)
// 获取能在form中使用的数据字典树形格式数据
const getFormDictTreeList = (params) => getAction('/sys/dictItem/treeListOption', params)
// 通过code值获取字典数据
const getDictByCode = (params) => getAction('/sys/dictItem/listByCodes', params)
// 字典标签专用(通过code获取字典数组)
export const ajaxGetDictItems = (code, params) => getAction(`/sys/dict/getDictItems/${code}`, params)
@@ -182,6 +184,7 @@ export {
editDictItem,
getDictTreeList,
getFormDictTreeList,
getDictByCode,
doReleaseData,
doReovkeData,
getLoginfo,
+5
View File
@@ -595,6 +595,11 @@ module.exports = {
downTemplate: '点击下载模板',
noFileMsg: '请选择一个文件'
},
// 树选择弹框
treeSelection: {
primaryNodeName: '一级节点名称',
selectedData: '已选数据'
},
// 系统管理
system,
// 个人中心
+11 -1
View File
@@ -125,6 +125,15 @@
:tree-data="optionsData[item.dbFieldName]"
:label-in-value="false"
:placeholder="$t('pleaseSelect')+item.dbFieldTxt" />
<!--16树形弹框选择-->
<tree-selection v-else-if="item.fieldShowType === FieldType.TREE_MODAL_SELECT.value"
:placeholder="$t('pleaseSelect')+item.dbFieldTxt"
v-model="formInline[item.dbFieldName]"
:filedName="item.dbFieldName"
type="radio"
:nameStr="formInline[item.dbFieldName + '_dictText']"
:dict-id="item.dictId"
:disabled="disabled || disabledFieldList.includes(item.dbFieldName)"/>
</a-form-model-item>
</div>
</template>
@@ -146,10 +155,11 @@ import JMultipleDatePicker from '../JMultipleDatePicker'
import UserSelection from '../selection/UserSelection'
import { getAction } from '../../api/manage.js'
import { getFormDictTreeList } from '../../api/api.js'
import TreeSelection from '../selection/TreeSelection'
export default {
name: 'AddForm',
components: { UserSelection, JMultipleDatePicker, StandardSelection, JDictSelectTag, JMultiSelectTag, UploadFile },
components: { UserSelection, JMultipleDatePicker, StandardSelection, JDictSelectTag, JMultiSelectTag, UploadFile, TreeSelection },
props: {
url: {
type: Object,
@@ -0,0 +1,287 @@
<template>
<j-modal
:title="$t('userSelect.select')"
:width="width"
:visible="visible"
switchFullscreen
:maskClosable="false"
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel">
<div class="modal-search-wrapper table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :span="10">
<a-form-item :label="$t('treeSelection.primaryNodeName')" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input :placeholder="$t('pleaseEnter') + $t('treeSelection.primaryNodeName')" v-model="queryParam.name" />
</a-form-item>
</a-col>
<a-col :span="8">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchReset" icon="reload" ghost>{{ $t('reset') }}</a-button>
<a-button type="primary" @click="searchQuery" icon="search" style="margin-left: 8px">
{{ $t('query') }}
</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<div class="modal-content">
<a-table
:columns="columns"
rowKey="itemValue"
bordered
:scroll="{x: '100%'}"
:data-source="dataSource"
:pagination="ipagination"
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange, type: type }"
:loading="confirmLoading"
@change="handleTableChange">
<template slot="text" slot-scope="text">
<a-tooltip overlay-class-name="tooltip-style">
<template slot="title">{{ text || text === 0 ? text : global.emptyLine }}</template>
<div class="table-text">{{ text || text === 0 ? text : global.emptyLine }}</div>
</a-tooltip>
</template>
</a-table>
</div>
<p class="modal-content-title">{{ $t('treeSelection.selectedData') }}</p>
<div v-if="dataSourceRight && dataSourceRight.length > 0" class="name-content">
<div v-for="(item, index) in dataSourceRight" :key="item.itemValue" class="name-div">
{{ item.itemText }}
<a-icon type="close" @click="handleDelete(item, index)" />
</div>
</div>
<a-empty v-else />
</j-modal>
</template>
<script>
import { getAction } from '../../api/manage'
import { getDictTreeList, getDictByCode } from '../../api/api'
export default {
name: 'TreeSelectModal',
props: {
dictId: {
type: String,
required: false,
default: ''
},
type: {
type: String,
required: false,
default: 'checkbox'
},
// 是否校验必选
checkRequired: {
type: Boolean,
required: false,
default: false
}
},
data () {
return {
width: 800,
visible: false,
confirmLoading: false,
queryParam: {},
labelCol: {
span: 8
},
wrapperCol: {
span: 16
},
dataSourceRight: [],
filters: {},
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + total + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
columns: [
{
title: this.$t('system.tag.name'),
dataIndex: 'itemText'
}
],
dataSource: [],
selectedRowKeys: []
}
},
methods: {
open (values) {
this.visible = true
this.filters.dictId = this.dictId
this.selectedRowKeys = values.split(',')
this.loadData()
this.getSelectedList(values)
},
handleCancel () {
this.visible = false
},
close () {
this.visible = false
this.visible = false
this.dataSourceRight = []
this.selectedRowKeys = []
this.queryParam = {}
this.ipagination = {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30', '100', '200'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' ' + this.$t('total') + ' ' + total + ' ' + this.$t('strip')
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
}
},
searchQuery () {
this.loadData(1)
},
searchReset () {
this.queryParam = {}
this.loadData(1)
},
loadData () {
this.confirmLoading = true
const params = Object.assign({}, this.queryParam, this.filters)
params.pageNo = this.ipagination.current
params.pageSize = this.ipagination.pageSize
getDictTreeList(params).then(res => {
if (res.success) {
this.dataSource = res.result.records || res.result
if (res.result.total) {
this.ipagination.total = res.result.total
} else {
this.ipagination.total = 0
}
}
}).finally(() => {
this.confirmLoading = false
})
},
onSelectChange (selectedRowKeys, selectedRows) {
this.selectedRowKeys = selectedRowKeys
if (this.type === 'checkbox') {
if (selectedRowKeys.length > this.dataSourceRight.length) {
// 说明是增加了数据
for (const rowIndex in selectedRows) {
if (!this.dataSourceRight.find(item => item.itemValue === selectedRows[rowIndex].itemValue)) {
// 右侧不存在,追加到右侧表格
this.dataSourceRight.push(selectedRows[rowIndex])
}
}
} else {
// 说明是删除了数据
if (selectedRowKeys && selectedRowKeys.length > 0) {
// 没有选中数据,说明这一页没有选中数据了
for (let i = 0; i < this.dataSourceRight.length; i++) {
if (!selectedRowKeys.find(item => item === this.dataSourceRight[i].itemValue)) {
// 表格选中中没有找到这一条数据,说明已经被删了
this.dataSourceRight.splice(i, 1)
i--
}
}
} else {
this.dataSourceRight = []
}
}
} else {
this.dataSourceRight = selectedRows
}
},
handleTableChange (pagination) {
this.ipagination = pagination
this.loadData()
},
// 名字列表的删除
handleDelete (record, index) {
this.dataSourceRight.splice(index, 1)
this.selectedRowKeys = this.selectedRowKeys.filter(item => item !== record.itemValue)
},
handleOk () {
if (this.checkRequired && (!this.selectedRowKeys || this.selectedRowKeys.length === 0)) {
this.$message.warning(this.$t('selectLeastOne'))
return
}
this.$emit('nameChange', this.dataSourceRight.map(item => item.name).join(','))
this.$emit('change', this.selectedRowKeys.join(','))
this.close()
},
getSelectedList (codes) {
getDictByCode({ codes }).then(res => {
if (res.success) {
this.dataSourceRight = res.result || []
}
})
}
}
}
</script>
<style scoped lang="less">
.modal-content {
width: 100%;
display: flex;
justify-content: space-between;
&-left {
width: 58%;
}
&-right {
width: 40%;
}
&-title-div {
display: flex;
align-items: center;
height: 28px;
margin: 20px 0;
.modal-content-title {
color: #1D2129;
font-weight: 500;
margin-right: 12px;
margin-bottom: 0;
}
}
}
.name-content {
display: flex;
flex-wrap: wrap;
.name-div {
width: auto;
padding: 5px 16px;
margin-right: 12px;
margin-top: 8px;
background: rgba(213, 44, 38, 0.08);
border-radius: 4px 4px 4px 4px;
opacity: 1;
color: @primary-color;
white-space: nowrap;
/deep/ .anticon {
margin-left: 4px;
}
}
}
/deep/ .ant-form-item-label {
min-width: 70px !important;
}
</style>
+102
View File
@@ -0,0 +1,102 @@
<template>
<div class="user-organ-wrap">
<a-input
type="text"
v-bind="$attrs"
disabled
class="user-input"
:value="checkedValue"
@click="selectClick"
:title="checkedValue">
</a-input>
<a-button type="primary" class="button-box" @click="selectClick" :disabled="disabled">
{{ $t('userSelect.select') }}
</a-button>
<tree-select-modal ref="selectModal" v-bind="$attrs" @change="selectChange" @nameChange="nameChange"/>
</div>
</template>
<script>
import TreeSelectModal from './TreeSelectModal'
import UserSelectModal from './UserSelectModal'
export default {
name: 'TreeSelection',
components: { UserSelectModal, TreeSelectModal },
props: {
disabled: {
type: Boolean,
required: false,
default: false
},
// 名字字符串
nameStr: {
type: String,
default: ''
},
value: {
type: String,
default: () => {
return ''
}
},
},
watch: {
nameStr: {
immediate: true,
handler (val) {
this.checkedValue = val
}
}
},
data () {
return {
checkedValue: null
}
},
methods: {
selectClick () {
console.log(this.value)
this.$refs.selectModal.open(this.value)
},
selectChange (value) {
this.$emit('change', value)
},
nameChange (value) {
this.checkedValue = value
this.$emit('nameChange', value)
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped lang="less">
.user-organ-wrap {
width: 100%;
position: relative;
display: flex;
align-items: center;
//height: 39.98px;
.user-input {
resize: none;
width: calc(100% - 70px);
}
// 因为需要加title,所以不能把鼠标事件去掉
/deep/ .ant-input-disabled {
background: #fff;
color: rgba(0, 0, 0, 0.65);
cursor: default;
}
.button-box {
margin-left: 5px;
}
}
</style>
+2 -1
View File
@@ -22,7 +22,8 @@ export const FieldType = {
TREE: { text: '树形结构(多选)', value: '12' },
// TEXT_LINK: { text: '输入框(链接)', value: '13' },
YEAR_PICKER: { text: '年份选择', value: '14' },
TREE_SINGLE: { text: '树形结构(单选)', value: '15' }
TREE_SINGLE: { text: '树形结构(单选)', value: '15' },
TREE_MODAL_SELECT: { text: '树形弹框', value: '16' }
}
export const TagsTypeEnums = new EsEnums({
@@ -431,7 +431,7 @@ export default {
val = val + ''
// this.contentFlag=val
// 树形结构
if (val === FieldType.TREE.value || val === FieldType.TREE_SINGLE.value) {
if (val === FieldType.TREE.value || val === FieldType.TREE_SINGLE.value || FieldType.TREE_MODAL_SELECT.value) {
this.contentOption = [...this.contentOptionTree]
this.isTagContent = true
} else if (val === FieldType.OPTION_SINGLE.value || val === FieldType.OPTION_MORE.value) {
@@ -31,7 +31,9 @@
/>
</a-form-model-item>
<!--父级名称 只有树形结构时显示 TODO 中英文的限制需要做显示的判断-->
<a-form-model-item :label="$t('system.tag.parentName')" prop="parentId" v-if="attributeType === TagsAttributeTypeEnums.TREE.value">
<a-form-model-item :label="$t('system.tag.parentName')"
prop="parentId"
v-if="attributeType === TagsAttributeTypeEnums.TREE.value">
<a-tree-select
style="width:100%"
:dropdownStyle="{ maxHeight: '200px', overflow: 'auto' }"
@@ -107,7 +109,11 @@ export default {
// 名称
itemText: [{ required: true, message: this.$t('pleaseEnter') + this.$t('system.tag.name'), trigger: 'blur' }],
// 英文名称
enName: [{ required: true, message: this.$t('pleaseEnter') + this.$t('system.tag.attributeNameEnglish'), trigger: 'blur' }],
enName: [{
required: true,
message: this.$t('pleaseEnter') + this.$t('system.tag.attributeNameEnglish'),
trigger: 'blur'
}],
// 数据值
itemValue: [
{ required: true, message: this.$t('pleaseEnter') + this.$t('system.tag.dataValue'), trigger: 'blur' },
@@ -227,7 +233,9 @@ export default {
// 获取所有的树形结构
const params = {
dictId: this.dictId,
isTagDict: 1
isTagDict: 1,
pageNo: 1,
pageSize: 10
}
getDictTreeList(params).then(res => {
if (res.success) {