新增多级联动下拉示例

master
RuoYi 4 years ago committed by Limy
parent b9a80f0633
commit 7cb4d5d1ab

@ -0,0 +1,406 @@
/*!
* jQuery cxSelect
* @name jquery.cxselect.js
* @version 1.4.2
* @date 2017-09-26
* @author ciaoca
* @email ciaoca@gmail.com
* @site https://github.com/ciaoca/cxSelect
* @license Released under the MIT license
*/
(function(factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else {
factory(window.jQuery || window.Zepto || window.$);
};
}(function($) {
var cxSelect = function() {
var self = this;
var dom, settings, callback;
// 分配参数
for (var i = 0, l = arguments.length; i < l; i++) {
if (cxSelect.isJquery(arguments[i]) || cxSelect.isZepto(arguments[i])) {
dom = arguments[i];
} else if (cxSelect.isElement(arguments[i])) {
dom = $(arguments[i]);
} else if (typeof arguments[i] === 'function') {
callback = arguments[i];
} else if (typeof arguments[i] === 'object') {
settings = arguments[i];
};
};
var api = new cxSelect.init(dom, settings);
if (typeof callback === 'function') {
callback(api);
};
return api;
};
cxSelect.isElement = function(o){
if (o && (typeof HTMLElement === 'function' || typeof HTMLElement === 'object') && o instanceof HTMLElement) {
return true;
} else {
return (o && o.nodeType && o.nodeType === 1) ? true : false;
};
};
cxSelect.isJquery = function(o){
return (o && o.length && (typeof jQuery === 'function' || typeof jQuery === 'object') && o instanceof jQuery) ? true : false;
};
cxSelect.isZepto = function(o){
return (o && o.length && (typeof Zepto === 'function' || typeof Zepto === 'object') && Zepto.zepto.isZ(o)) ? true : false;
};
cxSelect.getIndex = function(n, required) {
return required ? n : n - 1;
};
cxSelect.getData = function(data, space) {
if (typeof space === 'string' && space.length) {
space = space.split('.');
for (var i = 0, l = space.length; i < l; i++) {
data = data[space[i]];
};
};
return data;
};
cxSelect.init = function(dom, settings) {
var self = this;
if (!cxSelect.isJquery(dom) && !cxSelect.isZepto(dom)) {return};
var theSelect = {
dom: {
box: dom
}
};
self.attach = cxSelect.attach.bind(theSelect);
self.detach = cxSelect.detach.bind(theSelect);
self.setOptions = cxSelect.setOptions.bind(theSelect);
self.clear = cxSelect.clear.bind(theSelect);
theSelect.changeEvent = function() {
cxSelect.selectChange.call(theSelect, this.className);
};
theSelect.settings = $.extend({}, $.cxSelect.defaults, settings, {
url: theSelect.dom.box.data('url'),
emptyStyle: theSelect.dom.box.data('emptyStyle'),
required: theSelect.dom.box.data('required'),
firstTitle: theSelect.dom.box.data('firstTitle'),
firstValue: theSelect.dom.box.data('firstValue'),
jsonSpace: theSelect.dom.box.data('jsonSpace'),
jsonName: theSelect.dom.box.data('jsonName'),
jsonValue: theSelect.dom.box.data('jsonValue'),
jsonSub: theSelect.dom.box.data('jsonSub')
});
var _dataSelects = theSelect.dom.box.data('selects');
if (typeof _dataSelects === 'string' && _dataSelects.length) {
theSelect.settings.selects = _dataSelects.split(',');
};
self.setOptions();
self.attach();
// 使用独立接口获取数据
if (!theSelect.settings.url && !theSelect.settings.data) {
cxSelect.start.apply(theSelect);
// 设置自定义数据
} else if ($.isArray(theSelect.settings.data)) {
cxSelect.start.call(theSelect, theSelect.settings.data);
// 设置 URL通过 Ajax 获取数据
} else if (typeof theSelect.settings.url === 'string' && theSelect.settings.url.length) {
$.getJSON(theSelect.settings.url, function(json) {
cxSelect.start.call(theSelect, json);
});
};
};
// 设置参数
cxSelect.setOptions = function(opts) {
var self = this;
if (opts) {
$.extend(self.settings, opts);
};
// 初次或重设选择器组
if (!$.isArray(self.selectArray) || !self.selectArray.length || (opts && opts.selects)) {
self.selectArray = [];
if ($.isArray(self.settings.selects) && self.settings.selects.length) {
var _tempSelect;
for (var i = 0, l = self.settings.selects.length; i < l; i++) {
_tempSelect = self.dom.box.find('select.' + self.settings.selects[i]);
if (!_tempSelect || !_tempSelect.length) {break};
self.selectArray.push(_tempSelect);
};
};
};
if (opts) {
if (!$.isArray(opts.data) && typeof opts.url === 'string' && opts.url.length) {
$.getJSON(self.settings.url, function(json) {
cxSelect.start.call(self, json);
});
} else {
cxSelect.start.call(self, opts.data);
};
};
};
// 绑定
cxSelect.attach = function() {
var self = this;
if (!self.attachStatus) {
self.dom.box.on('change', 'select', self.changeEvent);
};
if (typeof self.attachStatus === 'boolean') {
cxSelect.start.call(self);
};
self.attachStatus = true;
};
// 移除绑定
cxSelect.detach = function() {
var self = this;
self.dom.box.off('change', 'select', self.changeEvent);
self.attachStatus = false;
};
// 清空选项
cxSelect.clear = function(index) {
var self = this;
var _style = {
display: '',
visibility: ''
};
index = isNaN(index) ? 0 : index;
// 清空后面的 select
for (var i = index, l = self.selectArray.length; i < l; i++) {
self.selectArray[i].empty().prop('disabled', true);
if (self.settings.emptyStyle === 'none') {
_style.display = 'none';
} else if (self.settings.emptyStyle === 'hidden') {
_style.visibility = 'hidden';
};
self.selectArray[i].css(_style);
};
};
cxSelect.start = function(data) {
var self = this;
if ($.isArray(data)) {
self.settings.data = cxSelect.getData(data, self.settings.jsonSpace);
};
if (!self.selectArray.length) {return};
// 保存默认值
for (var i = 0, l = self.selectArray.length; i < l; i++) {
if (typeof self.selectArray[i].attr('data-value') !== 'string' && self.selectArray[i][0].options.length) {
self.selectArray[i].attr('data-value', self.selectArray[i].val());
};
};
if (self.settings.data || (typeof self.selectArray[0].data('url') === 'string' && self.selectArray[0].data('url').length)) {
cxSelect.getOptionData.call(self, 0);
} else if (self.selectArray[0][0].options.length && typeof self.selectArray[0].attr('data-value') === 'string' && self.selectArray[0].attr('data-value').length) {
self.selectArray[0].val(self.selectArray[0].attr('data-value'));
cxSelect.getOptionData.call(self, 1);
} else {
self.selectArray[0].prop('disabled', false).css({
'display': '',
'visibility': ''
});
};
};
// 获取选项数据
cxSelect.getOptionData = function(index) {
var self = this;
if (typeof index !== 'number' || isNaN(index) || index < 0 || index >= self.selectArray.length) {return};
var _indexPrev = index - 1;
var _select = self.selectArray[index];
var _selectData;
var _valueIndex;
var _dataUrl = _select.data('url');
var _jsonSpace = typeof _select.data('jsonSpace') === 'undefined' ? self.settings.jsonSpace : _select.data('jsonSpace');
var _query = {};
var _queryName;
var _selectName;
var _selectValue;
cxSelect.clear.call(self, index);
// 使用独立接口
if (typeof _dataUrl === 'string' && _dataUrl.length) {
if (index > 0) {
for (var i = 0, j = 1; i < index; i++, j++) {
_queryName = self.selectArray[j].data('queryName');
_selectName = self.selectArray[i].attr('name');
_selectValue = self.selectArray[i].val();
if (typeof _queryName === 'string' && _queryName.length) {
_query[_queryName] = _selectValue;
} else if (typeof _selectName === 'string' && _selectName.length) {
_query[_selectName] = _selectValue;
};
};
};
$.getJSON(_dataUrl, _query, function(json) {
_selectData = cxSelect.getData(json, _jsonSpace);
cxSelect.buildOption.call(self, index, _selectData);
});
// 使用整合数据
} else if (self.settings.data && typeof self.settings.data === 'object') {
_selectData = self.settings.data;
for (var i = 0; i < index; i++) {
_valueIndex = cxSelect.getIndex(self.selectArray[i][0].selectedIndex, typeof self.selectArray[i].data('required') === 'boolean' ? self.selectArray[i].data('required') : self.settings.required);
if (typeof _selectData[_valueIndex] === 'object' && $.isArray(_selectData[_valueIndex][self.settings.jsonSub]) && _selectData[_valueIndex][self.settings.jsonSub].length) {
_selectData = _selectData[_valueIndex][self.settings.jsonSub];
} else {
_selectData = null;
break;
};
};
cxSelect.buildOption.call(self, index, _selectData);
};
};
// 构建选项列表
cxSelect.buildOption = function(index, data) {
var self = this;
var _select = self.selectArray[index];
var _required = typeof _select.data('required') === 'boolean' ? _select.data('required') : self.settings.required;
var _firstTitle = typeof _select.data('firstTitle') === 'undefined' ? self.settings.firstTitle : _select.data('firstTitle');
var _firstValue = typeof _select.data('firstValue') === 'undefined' ? self.settings.firstValue : _select.data('firstValue');
var _jsonName = typeof _select.data('jsonName') === 'undefined' ? self.settings.jsonName : _select.data('jsonName');
var _jsonValue = typeof _select.data('jsonValue') === 'undefined' ? self.settings.jsonValue : _select.data('jsonValue');
if (!$.isArray(data)) {return};
var _html = !_required ? '<option value="' + String(_firstValue) + '">' + String(_firstTitle) + '</option>' : '';
// 区分标题、值的数据
if (typeof _jsonName === 'string' && _jsonName.length) {
// 无值字段时使用标题作为值
if (typeof _jsonValue !== 'string' || !_jsonValue.length) {
_jsonValue = _jsonName;
};
for (var i = 0, l = data.length; i < l; i++) {
_html += '<option value="' + String(data[i][_jsonValue]) + '">' + String(data[i][_jsonName]) + '</option>';
};
// 数组即为值的数据
} else {
for (var i = 0, l = data.length; i < l; i++) {
_html += '<option value="' + String(data[i]) + '">' + String(data[i]) + '</option>';
};
};
_select.html(_html).prop('disabled', false).css({
'display': '',
'visibility': ''
});
// 初次加载设置默认值
if (typeof _select.attr('data-value') === 'string') {
_select.val(String(_select.attr('data-value'))).removeAttr('data-value');
if (_select[0].selectedIndex < 0) {
_select[0].options[0].selected = true;
};
};
if (_required || _select[0].selectedIndex > 0) {
_select.trigger('change');
};
};
// 改变选择时的处理
cxSelect.selectChange = function(name) {
var self = this;
if (typeof name !== 'string' || !name.length) {return};
var index;
name = name.replace(/\s+/g, ',');
name = ',' + name + ',';
// 获取当前 select 位置
for (var i = 0, l = self.selectArray.length; i < l; i++) {
if (name.indexOf(',' + self.settings.selects[i] + ',') > -1) {
index = i;
break;
};
};
if (typeof index === 'number' && index > -1) {
index += 1;
cxSelect.getOptionData.call(self, index);
};
};
$.cxSelect = function() {
return cxSelect.apply(this, arguments);
};
// 默认值
$.cxSelect.defaults = {
selects: [], // 下拉选框组
url: null, // 列表数据文件路径URL或数组数据
data: null, // 自定义数据
emptyStyle: null, // 无数据状态显示方式
required: false, // 是否为必选
firstTitle: '请选择', // 第一个选项的标题
firstValue: '', // 第一个选项的值
jsonSpace: '', // 数据命名空间
jsonName: 'n', // 数据标题字段名称
jsonValue: '', // 数据值字段名称
jsonSub: 's' // 子集数据字段名称
};
$.fn.cxSelect = function(settings, callback) {
this.each(function(i) {
$.cxSelect(this, settings, callback);
});
return this;
};
}));

File diff suppressed because one or more lines are too long

@ -0,0 +1,161 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<th:block th:include="include :: header('多级联动下拉')" />
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>多级联动下拉<small>https://github.com/ciaoca/cxSelect</small></h5>
</div>
<div class="ibox-content">
<p>简单联动示例。</p>
<div id="element" class="row">
<div class="col-sm-2">
<select class="type form-control m-b" data-first-title="请选择">
<option value="">请选择</option>
</select>
</div>
<div class="col-sm-2">
<select class="router form-control m-b" data-first-title="请选择">
<option value="">请选择</option>
</select>
</div>
</div>
<hr>
<p>国内省市区联动。</p>
<div id="element1" class="row">
<div class="col-sm-2">
<select class="province form-control m-b" data-first-title="选择省">
<option value="">请选择</option>
<option value="广东省" selected>广东省</option>
</select>
</div>
<div class="col-sm-2">
<select class="city form-control m-b" data-first-title="选择市">
<option value="">请选择</option>
<option value="深圳市" selected>深圳市</option>
</select>
</div>
<div class="col-sm-2">
<select class="area form-control m-b" data-first-title="选择地区">
<option value="">请选择</option>
<option value="南山区" selected>南山区</option>
</select>
</div>
</div>
<hr>
<p>自定义选项。</p>
<div id="element2" class="row">
<div class="col-sm-2">
<select class="first form-control m-b"></select>
</div>
<div class="col-sm-2">
<select class="second form-control m-b"></select>
</div>
<div class="col-sm-2">
<select class="third form-control m-b"></select>
</div>
<div class="col-sm-2">
<select class="fourth form-control m-b"></select>
</div>
<div class="col-sm-2">
<select class="fifth form-control m-b"></select>
</div>
</div>
<hr>
<div class="form-group">
<label class="font-noraml">相关参数详细信息</label>
<div><a href="http://doc.ruoyi.vip/ruoyi/document/zjwd.html#cxselect" target="_blank">http://doc.ruoyi.vip/ruoyi/document/zjwd.html#cxselect</a></div>
</div>
</div>
</div>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: cxselect-js" />
<script th:inline="javascript">
// 直接返回获取
var data = [[${data}]];
$('#element').cxSelect({
selects: ['type', 'router'],
jsonValue: 'v',
data: data
});
// 通过默认url获取
var urlChina = 'cityData';
$.cxSelect.defaults.url = urlChina;
$('#element1').cxSelect({
selects: ['province', 'city', 'area'],
nodata: 'none'
});
// 固定值获取
$('#element2').cxSelect({
selects: ['first', 'second', 'third', 'fourth', 'fifth'],
required: true,
jsonValue: 'v',
data: [
{'v': '1', 'n': '第一级 >', 's': [
{'v': '2', 'n': '第二级 >', 's': [
{'v': '3', 'n': '第三级 >', 's': [
{'v': '4', 'n': '第四级 >', 's': [
{'v': '5', 'n': '第五级 >', 's': [
{'v': '6', 'n': '第六级 >'}
]}
]}
]}
]}
]},
{'v': 'test number', 'n': '测试数字', 's': [
{'v': 'text', 'n': '文本类型', 's': [
{'v': '4', 'n': '4'},
{'v': '5', 'n': '5'},
{'v': '6', 'n': '6'},
{'v': '7', 'n': '7'},
{'v': '8', 'n': '8'},
{'v': '9', 'n': '9'},
{'v': '10', 'n': '10'}
]},
{'v': 'number', 'n': '数值类型', 's': [
{'v': 11, 'n': 11},
{'v': 12, 'n': 12},
{'v': 13, 'n': 13},
{'v': 14, 'n': 14},
{'v': 15, 'n': 15},
{'v': 16, 'n': 16},
{'v': 17, 'n': 17}
]}
]},
{'v': 'test boolean','n': '测试 Boolean 类型', 's': [
{'v': true ,'n': true},
{'v': false ,'n': false}
]},
{v: 'test quotes', n: '测试属性不加引号', s: [
{v: 'quotes', n: '引号'}
]},
{v: 'test other', n: '测试奇怪的值', s: [
{v: '[]', n: '数组(空)'},
{v: [1,2,3], n: '数组(数值)'},
{v: ['a','b','c'], n: '数组(文字)'},
{v: new Date(), n: '日期'},
{v: new RegExp('\\d+'), n: '正则对象'},
{v: /\d+/, n: '正则直接量'},
{v: {}, n: '对象'},
{v: document.getElementById('custom_data'), n: 'DOM'},
{v: null, n: 'Null'},
{n: '未设置 value'}
]},
{'v': '' , 'n': '无子级'}
]
});
</script>
</body>
</html>

@ -62,6 +62,29 @@
</form>
</div>
<div class="col-sm-12 search-collapse">
<p class="select-title">多级联动下拉查询</p>
<form id="select-form">
<div class="select-list">
<ul id="element">
<li>
商户编号:<input type="text" name="userId"/>
</li>
<li>
充值类型:<select class="type"></select>
</li>
<li>
充值路由:<select class="router"></select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('select-form')"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="col-sm-12 search-collapse">
<p class="select-title">下拉多选条件查询</p>
<form id="select-form">
@ -164,5 +187,16 @@
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: bootstrap-select-js" />
<th:block th:include="include :: cxselect-js" />
<script th:inline="javascript">
// 直接返回获取
var data = [{"v":"taobao","n":"淘宝","s":[{"v":"tm","n":"天猫"},{"v":"jhs","n":"聚划算"}]},{"v":"jd","n":"京东","s":[{"v":"jdcs","n":"京东超市"},{"v":"jdsx","n":"京东生鲜"}]}];
$('#element').cxSelect({
selects: ['type', 'router'],
jsonValue: 'v',
data: data
});
</script>
</body>
</html>

@ -139,6 +139,11 @@
<script th:src="@{/ajax/libs/typeahead/bootstrap3-typeahead.min.js}"></script>
</div>
<!-- 多级联动下拉 -->
<div th:fragment="cxselect-js">
<script th:src="@{/ajax/libs/cxselect/jquery.cxselect.min.js}"></script>
</div>
<!-- jsonview格式化和语法高亮JSON格式数据查看插件 -->
<div th:fragment="jsonview-css">
<link th:href="@{/ajax/libs/jsonview/jquery.jsonview.css}" rel="stylesheet"/>

@ -95,6 +95,7 @@
<li><a class="menuItem" th:href="@{/demo/form/summernote}">富文本编辑器</a></li>
<li><a class="menuItem" th:href="@{/demo/form/duallistbox}">左右互选组件</a></li>
<li><a class="menuItem" th:href="@{/demo/form/autocomplete}">搜索自动补全</a></li>
<li><a class="menuItem" th:href="@{/demo/form/cxselect}">多级联动下拉</a></li>
</ul>
</li>
<li> <a>表格<span class="fa arrow"></span></a>

@ -0,0 +1,69 @@
package com.ruoyi.common.core.domain;
import java.io.Serializable;
import java.util.List;
/**
* CxSelect
*
* @author ruoyi
*/
public class CxSelect implements Serializable
{
private static final long serialVersionUID = 1L;
/**
*
*/
private String v;
/**
*
*/
private String n;
/**
*
*/
private List<CxSelect> s;
public CxSelect()
{
}
public CxSelect(String v, String n)
{
this.v = v;
this.n = n;
}
public List<CxSelect> getS()
{
return s;
}
public void setN(String n)
{
this.n = n;
}
public String getN()
{
return n;
}
public void setS(List<CxSelect> s)
{
this.s = s;
}
public String getV()
{
return v;
}
public void setV(String v)
{
this.v = v;
}
}
Loading…
Cancel
Save