注:开窗功能实现,具体可看本人文章:EKP其它/EKPSQL工具_Liquid-Li的博客-优快云博客
1、实现效果
2、具体实现 - 配置xml扩展(WebContent/WEB-INF/KmssConfig/xp/xform/plugin.xml)
<?xml version="1.0" encoding="UTF-8"?>
<plugin
xmlns="http://www.example.org/plugin-config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/plugin-config ../../plugin.xsd ">
<extension point="com.landray.kmss.sys.xform.base.service.controls" model="*">
<!-- xp选择框 -->
<item name="control">
<param name="class" value="com.landray.kmss.xp.xform.base.service.controls.relationchoose.XpSysFormTemplateRelationChooseControl" />
<param name="file" value="/xp/xform/designer/relation_choose/relation_choose.js" />
</item>
</plugin>
2、具体实现 - 前端
WebContent/xp/xform/designer/relation_choose/relation_choose.js
/* 1、菜单栏配置 */
Designer_Config.operations['xpRelationChoose'] = {
lab : "5",
imgIndex : 58,// sys/xform/designer/style/css/editor-icon-m_z.png中从上往下数的索引位置,用于菜单的图标展示
title : "XP选择框",// 菜单图标名称
run : function(designer) {// 点击菜单控件图标时执行的方法,一般类似这样写即可
designer.toolBar.selectButton('xpRelationChoose');
},
type : 'cmd',
order: 1001,// 页签里面的排序顺序,小前大后,可为小数
shortcut : '',
select : true,
line_splits_font: true,
cursorImg : 'style/cursor/relationChoose.cur'// 鼠标点击菜单图标之后的鼠标手势加图标的展示
};
Designer_Config.buttons.form.push("xpRelationChoose");// 放入菜单选项卡(control为"扩展"选项卡)
Designer_Menus.tool.menu['xpRelationChoose'] = Designer_Config.operations['xpRelationChoose'];// 放入右键菜单
/* 2、控件属性配置 */
Designer_Config.controls["xpRelationChoose"] = {
type : "xpRelationChoose",// 和service配置解析类型一致
storeType : 'field',
inherit : 'base',
container : false,
onDraw : _Designer_Control_XpRelationChoose_OnDraw,// 拖动控件到表单中展示js方法
drawMobile : _Designer_Control_RelationChoose_DrawMobile,
drawXML : _Designer_Control_XpRelationChoose_DrawXML,// 控件值xml
onInitialize : _Designer_Control_XpRelationChoose_OnInitialize,
onInitializeDict : _Designer_Control_DisplayText_OnInitializeDict,
initDefaultValueAfterPaste :_Designer_Control_XpRelationChoose_initDefaultValueAfterPaste,// 粘贴后初始化默认值
implementDetailsTable : true,// 是否允许在明细表中展示
resizeMode : 'onlyWidth', // 尺寸调整模式(onlyWidth, onlyHeight, all, no)
info : {
name : "XP选择框",// 双击控件开窗时上方的标题
//preview : "mutiTab.png"
},
attrs : {// 双击控件弹出的属性框参数
label : Designer_Config.attrs.label,
required: {
text: Designer_Lang.controlAttrRequired,
value: "true",
type: 'checkbox',
checked: false,
show: true
},
width : {
text: Designer_Lang.controlAttrWidth,
value: "120",
type: 'text',
show: true,
validator: Designer_Control_Attr_Width_Validator,// 修改参数的校验方法
checkout: Designer_Control_Attr_Width_Checkout// 提交时候的校验方法
},
summary: {
text: Designer_Lang.controlAttrSummary,
value: "true",
type: 'checkbox',
checked: false,
synchronous: true,//多表单是否同步
show: true
},
encrypt : Designer_Config.attrs.encrypt,
/* 以下为新增的参数 */
freeEdit: {
text: "自由编辑",
value: "true",
type: 'checkbox',
checked: false,
show: true
},
editCallbackFunName: {
text : "编辑回调",
hint:"回调参数(obj, flagid, value)",
value : 'editCallback_' + new Date().getTime(),
type : 'text',
required: false,
show : true
},
openWinFunName: {
text : "开窗函数",
hint: "函数参数(obj)",
value : 'openWinFun_' + new Date().getTime(),
type : 'text',
required: true,
// lang: true,// 值是否加入多语言
show : true,
convertor: function (name, attr, value, values) {
if (!value) {
return 'openWinFun_' + new Date().getTime();
}
return value;
}
},
clearCallbackFunName: {
text : "清空回调",
hint: "回调参数(obj, flagid)",
value : 'clearCallback_' + new Date().getTime(),
type : 'text',
required: false,
show : true
},
clearFieldId: {
text : "联动清空",
hint: "1、栏位ID,分号分隔 2、明细表栏位:明细表ID.栏位ID",
value : '',
type : 'textarea',
show : true
},
notNullCheck: {
text : "非空检查",
hint: "1、栏位ID,分号分隔 2、明细表栏位:明细表ID.栏位ID",
value : '',
type : 'textarea',
show : true
},
}
};
function _Designer_Control_XpRelationChoose_OnInitialize(){
this.onInitializeDict();
}
function _Designer_Control_XpRelationChoose_initDefaultValueAfterPaste(values){
// values.openWinFunName = "";
return values;
}
function _Designer_Control_XpRelationChoose_OnDraw(parentNode, childNode) {
var values = this.options.values;
if (this.options.values.id == null){
this.options.values.id = "fd_" + Designer.generateID();
}
var domElement = _CreateDesignElement('div', this, parentNode, childNode);
domElement.className="xform_relation_choose";
domElement.style.display="inline";
var values = this.options.values;
var inputDom = document.createElement('input');
inputDom.className="inputsgl";
inputDom.label = _Get_Designer_Control_Label(this.options.values, this);
domElement.style._widthUnit = "px";
if (this.options.values.width ) {
if( this.options.values.width.toString().indexOf('%') > -1){
inputDom.style.width = this.options.values.width;
domElement.style._widthUnit = "%";
}
else{
inputDom.style.width = this.options.values.width+"px";
}
}
else{
values.width = "120";
inputDom.style.width=values.width+"px";
}
domElement.style._width = $(inputDom).width();
domElement.appendChild(inputDom);
if(values.required == 'true') {
$(domElement).append('<span class=txtstrong>*</span>');
}
$(domElement).append(' ');
inputDom.id = this.options.values.id;
if (values.required == "true") {
$(inputDom).attr("required", "true");
$(inputDom).attr("_required", "true");
} else {
$(inputDom).attr("required", "false");
$(inputDom).attr("_required", "false");
}
if(values.summary == "true"){
$(inputDom).attr("summary", "true");
}else{
$(inputDom).attr("summary", "false");
}
if (values.width) {
$(inputDom).attr("width", values.width);
}
/* 以下为新增的参数 */
if (values.freeEdit) {
$(inputDom).attr("freeEdit" , values.freeEdit);
}
if (values.editCallbackFunName) {
$(inputDom).attr("editCallbackFunName" , values.editCallbackFunName);
}
if (values.openWinFunName) {
$(inputDom).attr("openWinFunName" , values.openWinFunName);
}
if (values.clearCallbackFunName) {
$(inputDom).attr("clearCallbackFunName" , values.clearCallbackFunName);
}
if (values.clearFieldId) {
$(inputDom).attr("clearFieldId" , values.clearFieldId);
}
if (values.notNullCheck) {
$(inputDom).attr("notNullCheck" , values.notNullCheck);
}
var a = document.createElement("a");
a.innerText = Designer_Lang.relation_choose_button + "(xp)";
domElement.appendChild(a);
}
function _Designer_Control_XpRelationChoose_DrawXML() {
var values = this.options.values;
// 如果一个控件对应多个值,需要补充这两个属性,用于流程文档提交业务处理
var customElementProperties = {};
customElementProperties.isMultiVal = "true";
customElementProperties.controlId = values.id;
buf=[];
buf.push( '<extendSimpleProperty ');
buf.push('name="', values.id, '" ');
buf.push('label="', values.label, '" ');
buf.push('type="', values.dataType ? values.dataType : 'String', '" ');
// 控件类型
buf.push('businessType="', this.type, '" ');
if (values.formula != '' && values.formula != null) {
buf.push('formula="true" ');
buf.push('defaultValue="', values.formula, '" ');
if (values.reCalculate == 'true') {
buf.push('recalculateOnSave="true" ');
}
} else if (values.defaultValue != '' && values.defaultValue != null) {
buf.push('defaultValue="', values.defaultValue, '" ');
}
buf.push('customElementProperties="', Designer.HtmlEscape(JSON.stringify(customElementProperties)), '" ');
// 字段是否需要加密
if (values.encrypt == 'true') {
buf.push('encrypt="true" ');
buf.push('encryptionMethod="AES" ');
}
buf.push('/>\r\n');
buf.push(_Designer_Control_RelationChoose_DrawXML_HiddenPropertyTemp(values.id+"_text",values.label + Designer_Lang.controlDisplayValueMessage,this.type,customElementProperties,values));
return buf.join('');
}
function _Designer_Control_RelationChoose_DrawXML_HiddenPropertyTemp(name,label,businessType,customElementProperties,values,isStore){
var buf = [];
customElementProperties.isShow = 'false';
buf.push( '<extendSimpleProperty ');
buf.push('name="', name, '" ');
buf.push('label="',label , '" ');
buf.push('type="', values.dataType ? values.dataType : 'String', '" ');
buf.push('businessType="', businessType, '" ');
if(isStore){
buf.push('store="',isStore,'" ');
buf.push('canDisplay="',isStore,'" ');//如果是不需要映射的值则不显示在列表中
}
buf.push('customElementProperties="', Designer.HtmlEscape(JSON.stringify(customElementProperties)), '" ');
// 字段是否需要加密
if (values.encrypt == 'true') {
buf.push('encrypt="true" ');
buf.push('encryptionMethod="AES" ');
}
if(name.indexOf('_text') > 0 && values.summary == 'true'){
//摘要汇总
buf.push('summary="true" ');
}
buf.push('/>\r\n');
return buf.join('');
}
WebContent/xp/xform/designer/relation_choose/relation_choose_display.jsp
<%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<%@ include file="/sys/ui/jsp/common.jsp" %>
<body>
<div class="relationChoose_content" style="${param.style} display:table">
<div class="relationChoose_textShow ${param.parentClass}" parentClass ="${param.parentClass}"></div>
<xform:xtext property="extendDataFormInfo.value(${param.fdControlId }_text)" showStatus="edit" style="display:none;" subject="${param.subject }" htmlElementProperties="validator='true'" onValueChange="__xformDispatch(this.value, this);"></xform:xtext>
<xform:editShow>
<xform:xtext property="extendDataFormInfo.value(${param.fdControlId })" style="display:none;" subject="${param.subject }" required="${param.required }" htmlElementProperties="validator='true'"></xform:xtext>
</xform:editShow>
<xform:viewShow>
<xform:xtext property="extendDataFormInfo.value(${param.fdControlId })" showStatus="noShow"></xform:xtext>
</xform:viewShow>
<%-- 编辑、选择、清空 --%>
<xform:editShow>
<div class="relationChoose_operation" params="${param.params}">
<%--编辑--%>
<c:if test="${param.params.contains('quot;freeEditquot;:quot;truequot;')}">
<a onclick='xpRelationChoose_freeEdit(this);'>Edit</a>
</c:if>
<%--选择--%>
<div style='display:inline-block;cursor:pointer;'
textId="${param.fdControlId }_text"
bindEvent='${param.bindEvent}'
mytype='relation_choose'
myid='extendDataFormInfo.value(${param.fdControlId})'
onclick='xpRelationChoose_sqlOpenWin(this);'>
<bean:message bundle="sys-xform-base" key="Designer_Lang.relation_choose_button" />
</div>
<%--清空--%>
<a class='com_btn_link' onclick='xpRelationChoose_clearValue(this);'>
<bean:message bundle="sys-xform-base" key="Designer_Lang.relation_choose_clear" />
</a>
</div>
<%-- 公用js --%>
<script>Com_IncludeFile('relation_run.js','../sys/xform/designer/relation/');</script>
<script>Com_IncludeFile('relation_event_run.js','../sys/xform/designer/relation_event/');</script>
<script>Com_IncludeFile("xpUtil/publicMethod.js");</script>
<script>Com_IncludeFile('designerUtil.js','../xp/xform/designer/');</script>
<script>Com_IncludeFile('relation_choose_script.js','../xp/xform/designer/relation_choose/');</script>
</xform:editShow>
</div>
<script>
Com_IncludeFile('relation_choose_run.js','../sys/xform/designer/relation_choose/');
//使用Com_IncludeCSSFiles追加到head中,不知道为什么谷歌好想也有link样式表个数的限制,具体原因未知
var urlArr = [];
urlArr.push('${LUI_ContextPath}/xp/xform/designer/relation_choose/style/css/relation_choose.css');
Com_IncludeCSSFiles(urlArr);
</script>
</body>
WebContent/xp/xform/designer/relation_choose/relation_choose_script.js
/**
* 点击"选择"时触发
* @author liquid
* @date 2023年4月5日
* @param {object} obj "选择"按钮的dom
* @return {void}
*/
function xpRelationChoose_sqlOpenWin(obj) {
// liquid 2023年4月5日16:46:38
let paramsStr = $(obj).closest(".relationChoose_operation").attr("params").replace(/quot;/g, "\"");
let params = JSON.parse(paramsStr);
let openWinFunName = params["openWinFunName"];
let openWinFun = window[openWinFunName];
let notNullCheckIds = params["notNullCheck"];
if (typeof openWinFun === "function" &&
xpDesigner_notNullCheckBeforeOpen(notNullCheckIds, obj)) {
openWinFun(obj);
} else if (typeof openWinFun !== "function"){
alert(xp_lang("0022_key") + openWinFunName );
}
}
/**
* 点击"清空"时触发
* @author liquid
* @date 2023年4月5日
* @param {object} obj "清空"按钮的dom
* @return {void}
*/
function xpRelationChoose_clearValue(obj) {
// liquid 2023年4月5日16:46:38
let flagid = $(obj).closest("xformflag").attr("flagid");
if (isNotEmpty(flagid)) {
clearField(flagid);
exeValueChange(flagid);// 执行自身值变化事件
// 执行一次校验
// var myid = $(obj).closest("xformflag").attr("property");
// var validation = $GetFormValidation(document.forms[0]);
// if(myid && validation && $("input[name='"+myid+"']").length > 0){
// validation.validateElement($("input[name='"+myid+"']")[0]);
// }
}
// 联动清空
let paramsStr = $(obj).closest(".relationChoose_operation").attr("params").replace(/quot;/g, "\"");
let params = JSON.parse(paramsStr);
let clearFieldId = params["clearFieldId"];
if (isNotEmpty(clearFieldId)) {
let relativeFlagidArr = clearFieldId.split(";");
for (const relativeFlagid of relativeFlagidArr) {
if (isEmpty(relativeFlagid)) {
continue;
}
// 明细表中的控件
if (relativeFlagid.includes(".")) {
xpRelationChoose_clearInDetailList(relativeFlagid, obj);
continue;
}
// 非明细表控件
clearField(relativeFlagid);
}
}
// 清空后回调
let clearCallbackFunName = params["clearCallbackFunName"];
let clearCallbackFun = window[clearCallbackFunName];
if (typeof clearCallbackFun === "function") {
clearCallbackFun(obj, flagid);
}
}
/**
* 联动清空明细表栏位
* @author liquid
* @date 2023年4月5日
* @param {string} flagId 栏位ID(明细表ID.栏位ID)
* @param {object} obj "清空"按钮的dom
* @return {void}
* @private
*/
function xpRelationChoose_clearInDetailList(flagId, obj) {
let dotIndex = flagId.indexOf(".");
let detailListId = flagId.substring(0, dotIndex);
let detailObj = getDetailObj(detailListId);
let fieldId = flagId.substring(dotIndex + 1);
/* 选择框与flagId在同一明细表 */
let tableId = $(obj).closest("table").attr("id");
if (isNotEmpty(tableId) && tableId.includes(detailListId)) {
let rowIndex = detailObj.getRowIndexByDom(obj);
detailObj.clearSingle(rowIndex, fieldId);
exeValueChange(detailObj.getFlagidInDetailList(rowIndex, fieldId));
return;
}
/* 选择框与flagId不在同一明细表 */
detailObj.clearColumn(fieldId);
for (let i = 0; i < detailObj.getRowLength(); i++) {
exeValueChange(detailObj.getFlagidInDetailList(i, fieldId));
}
}
/**
* 点击"编辑"时触发
* @author liquid
* @date 2023年4月5日
* @param {object} obj "编辑"按钮的dom
* @return {void}
*/
function xpRelationChoose_freeEdit(obj) {
let flagid = $(obj).closest("xformflag").attr("flagid");
let value = `${window.prompt()}`;
let paramsStr = $(obj).closest(".relationChoose_operation").attr("params").replace(/quot;/g, "\"");
let params = JSON.parse(paramsStr);
if (isNotEmpty(value)) {
setValueById(flagid, value);
const editCallbackFunName = params["editCallbackFunName"];
const editCallbackFun = window[editCallbackFunName];
if (typeof editCallbackFun === "function") {
editCallbackFun(obj, flagid, value);
}
}
}
WebContent/xp/xform/designer/designerUtil.js
/**
* 某些栏位的非空检查
* @author liquid
* @date 2023年4月5日
* @param {string} notNullCheckIds 需判空的栏位ID字符串
* @param {object} obj 触发元素的dom
* @return {boolean} 是否全部非空
* @private
*/
function xpDesigner_notNullCheckBeforeOpen(notNullCheckIds, obj) {
let notNullCheckIdArr = notNullCheckIds.split(";");
for (const notNullCheckId of notNullCheckIdArr) {
if (isEmpty(notNullCheckId)) {
continue;
}
let xformLabel = getXFormLabel(notNullCheckId);
let dotIndex = notNullCheckId.indexOf(".");
/* 待判断的栏位在明细表 */
if (dotIndex > -1) {
let detailListId = notNullCheckId.substring(0, dotIndex);
let detailObj = getDetailObj(detailListId);
let fieldId = notNullCheckId.substring(dotIndex + 1);
// 选择框与flagId在同一明细表
let tableId = $(obj).closest("table").attr("id");
if (isNotEmpty(tableId) && tableId.includes(detailListId)) {
let rowIndex = detailObj.getRowIndexByDom(obj);
let value = detailObj.getDataSingle(rowIndex, fieldId);
if (xpDesigner_isNull(value)) {
alert(xp_lang("0023_key") + xformLabel);
return false;
}
} else {// 选择框与flagId不在同一明细表
let dataArr = detailObj.getDataByColumnId(fieldId);
if (xpDesigner_isArrNull(dataArr)) {
alert(xp_lang("0024_key") + xformLabel);
return false;
}
}
}
/* 待判断的栏位不在明细表 */
if (dotIndex < 0) {
let value = getValueById(notNullCheckId);
if (xpDesigner_isNull(value)) {
alert(xp_lang("0023_key") + xformLabel);
return false;
}
}
}
return true;
}
function xpDesigner_isNull(var1) {
return isEmpty(var1) || "{};[];[\"\"];[\"\",\"\"];[null];[null,null]".includes(JSON.stringify(var1));
}
function xpDesigner_isArrNull(varArr1) {
for (const var1 of varArr1) {
if (xpDesigner_isNull(var1)) {
return true;
}
}
return false;
}
2、具体实现 - 前端(开窗)
<!doctype html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>资料选择器 Select Data</title>
<link rel="stylesheet" href="sql_openwin.css">
<script src="/xpwebframe/node_modules/_jquery@3.6.0@jquery/dist/jquery.min.js"></script>
<script src="/xpwebframe/node_modules/_vue@2.6.14@vue/dist/vue.min.js"></script>
<script src="/resource/js/xpUtil/array.js"></script>
<script src="/resource/js/xpUtil/ajaxUtil.js"></script>
<script src="/resource/js/xpUtil/page.js"></script>
<script src="/resource/js/xpUtil/string.js"></script>
<script src="/resource/js/xpUtil/errorHandle.js"></script>
<script src="/resource/js/xpUtil/date.js"></script>
<script src="/resource/js/xpUtil/download.js"></script>
<script src="/resource/js/xpUtil/excel.js"></script>
<script src="/resource/js/xpUtil/kmReviewMainUtil.js"></script>
<script src="sql_openwin_selfCallback.js"></script>
<script src="sql_openwin_rightMenuCallback.js"></script>
<script src="sql_openwin_inParams.js"></script>
</head>
<body>
<div id="outer_div" v-on:keydown="outerDivKeydown($event)">
<!---------------------------查询区---------------------------->
<div id="query_outer_div">
<!--查询输入框-->
<table>
<tr v-for="(i_value, i) in search">
<td class="query_td" v-for="(j_value, j) in i_value">
<span style="display: flex;flex-wrap: nowrap">
<div class="query_label_div">
<label class="query_label"
v-if="!isEmpty(j_value)" v-html="j_value.title">
</label>
</div>
<div class="query_input_div">
<!--单行输入框-->
<input type="text" class="query_input"
v-bind:placeholder="j_value.placeholder"
v-bind:value="j_value.default"
v-if="!isEmpty(j_value) && j_value.type === 'text'"
v-bind:name="j_value.name">
<!--日期选择-->
<input type="date" class="query_input" style="height: 20px;"
v-if="!isEmpty(j_value) && j_value.type === 'date'"
v-bind:value="getTodayStr(j_value.default)"
v-bind:name="j_value.name">
<!--下拉菜单-->
<select type="dropdown" class="query_input" style="height: 24px;"
v-if="!isEmpty(j_value) && j_value.type === 'dropdown'"
v-bind:value="j_value.default"
v-bind:name="j_value.name"
v-on:change="dropdownChange($event)">
<option v-for="(k_value, k) in j_value.items"
v-bind:value="getSelectTrueValue(k_value)">
{{getSelectDisplayValue(k_value)}}
</option>
</select>
<!--单选按钮-->
<span v-if="!isEmpty(j_value) && j_value.type==='radio'">
<span v-for="(p_value, p) in j_value.items">
<input class="radio_input" v-bind:value="getSelectTrueValue(p_value)"
v-bind:id="j_value.name + '_' + p"
v-bind:name="j_value.name"
v-bind:type="j_value.type"
v-bind:checked="j_value.default===getSelectTrueValue(p_value)"
v-bind:data-index="p"
v-on:click="radioClick($event)">
{{getSelectDisplayValue(p_value)}}
</span>
</span>
<!--多选按钮-->
<span v-if="!isEmpty(j_value) && j_value.type==='checkbox'">
<span v-for="(p_value, p) in j_value.items">
<input class="checkbox_input" v-bind:value="getSelectTrueValue(p_value)"
v-bind:id="j_value.name + '_' + p"
v-bind:name="j_value.name"
v-bind:type="j_value.type"
v-bind:checked="j_value.default.includes(getSelectTrueValue(p_value))"
v-on:click="checkboxClick($event)">
{{getSelectDisplayValue(p_value)}}
</span>
</span>
</div>
</span>
</td>
</tr>
</table>
<!--查询按钮-->
<div id="right_button_div">
<button class="query_reset" v-on:click="queryClick()">{{lang === 'ZH-CN' ? '查询' : 'QUERY'}}</button>
<button class="query_reset" v-on:click="resetClick()">{{lang === 'ZH-CN' ? '重置' : 'RESET'}}</button>
<button class="query_reset" v-if="winType==='multiple'" v-on:click="confirmClick()">
{{lang === 'ZH-CN' ? '确定' : 'CONFIRM'}}
</button>
</div>
</div>
<!------------------------------------------------------------>
<!---------------------------数据区---------------------------->
<div id="data_div" v-bind:style="{height: data_div_height + 'px'}">
<!--无数据提示-->
<div class="request_no_data_tip" style="margin-top:25px" v-if="nowData.length <= 0 && noDataShow">
<div class="no_data_tip_icon"></div>
<div class="no_data_tip_text">
<span>查无数据</span>
</div>
</div>
<table id="tab" v-if="nowData.length > 0" v-bind:style="totalWidth()">
<!--标题-->
<tr style="position:sticky;top:0">
<td id="multiple_choose_all" v-if="winType==='multiple'">
<input type="checkbox" v-bind:checked="isAllSelected()"
v-on:click="multipleChooseAll()"/>
</td>
<td class="title_td"
v-for="(i_value, i) in titles"
v-if="!hideColumn(i)"
v-bind:style="(i_value.width.includes('%') ? 'width:' : 'min-width:') + i_value.width"
v-html="i_value.label">
</td>
</tr>
<!--数据-->
<tr class="data_tr" v-bind:title="showDetail(i_value)" v-for="(i_value, i) in nowData"
v-bind:class="dataRowClass(i)">
<td class="multiple_choose_single" v-if="winType==='multiple'"
v-on:click="dataRowClick(i_value, i, $event)">
<input type="checkbox"
v-bind:checked="isSelected(i_value)"
v-on:click="multipleChooseSingleClick(i)"/>
</td>
<td class="data_td" v-if="!hideColumn(j)" v-for="(j_value, j) in i_value"
v-on:click="dataRowClick(i_value, i, $event)"
v-on:contextmenu="dataRowRightClick(i_value, i, $event)"
v-html="j_value">
</td>
<!---------------------------右键菜单------------------------->
<div class="rightMenu_outer_div"
v-if="rightMenu_itemArr.length!==0"
v-show="rightMenu.visible"
v-bind:style="{left: rightMenu.left + 'px', top: rightMenu.top + 'px'}">
<div class="rightMenu_item_outer">
<div class="rightMenu_item" v-for="(k_value, k) in rightMenu_itemArr"
v-on:click="rightMenu_callback(k)"
v-html="k_value.itemName"></div>
</div>
</div>
<!------------------------------------------------------------>
</tr>
<!---------------------------已选数据区------------------------->
<tr class="data_tr" style="background-color: #dcdcdc;color: #ff0000" v-bind:title="showDetail(i_value)"
v-for="(i_value, i) in multipleSelectedData">
<td class="selected_data_cancel"
v-if="winType==='multiple'"
v-on:click="cancelSelectedData(i_value, i, $event)">×
</td>
<td class="data_td" v-if="!hideColumn(j)" v-for="(j_value, j) in i_value"
v-html="j_value" v-on:click="cancelSelectedData(i_value, i, $event)"
v-on:contextmenu="dataRowRightClick(i_value, i, $event)">
</td>
<!---------------------------右键菜单------------------------->
<div class="rightMenu_outer_div"
v-if="rightMenu_itemArr.length!==0"
v-show="rightMenu.visible"
v-bind:style="{left: rightMenu.left + 'px', top: rightMenu.top + 'px'}">
<div class="rightMenu_item_outer">
<div class="rightMenu_item" v-for="(k_value, k) in rightMenu_itemArr"
v-on:click="rightMenu_callback(k)"
v-html="k_value.itemName"></div>
</div>
</div>
<!------------------------------------------------------------>
</tr>
<!------------------------------------------------------------>
</table>
</div>
<!------------------------------------------------------------>
<!---------------------------分页区---------------------------->
<div id="paging_outer_div">
<!--数据数量-->
<div id="count_div">
<label v-if="lang==='ZH-CN'">共 {{total}} 条记录 | 第 {{nowPage}} 页</label>
<label v-if="lang==='EN-US'">Record Quantity: {{total}} | Page No: {{nowPage}} </label>
</div>
<!-转开窗-->
<img class="page_win_btn" src="/xpicon/static/openwin01.png" v-on:click="changeToWin()">
<!--分页操作-->
<div id="page_operation">
<button class="page_move_btn" v-on:click="exportData()">{{lang === 'ZH-CN' ? '导出' : 'Export'}}</button>
<button class="page_move_btn" v-if="total===0" v-on:click="firstPageClick()">
{{lang === 'ZH-CN' ? '最前页(0)' : 'First Page(0)'}}
</button>
<button class="page_move_btn" v-else v-on:click="firstPageClick()">
{{lang === 'ZH-CN' ? '最前页(1)' : 'First Page(1)'}}
</button>
<button class="page_move_btn" v-on:click="pageUpClick()">{{lang === 'ZH-CN' ? '上一页' : 'Page Up'}}
</button>
<button class="page_move_btn" v-on:click="pageDownCLick()">{{lang === 'ZH-CN' ? '下一页' : 'Page Down'}}
</button>
<button class="page_move_btn" v-on:click="lastPageClick()">
{{lang === 'ZH-CN' ? '最后页(' + lastPageIndex + ')' : 'Last Page(' + lastPageIndex + ')'}}
</button>
</div>
</div>
<!------------------------------------------------------------>
<div id="white_cover" v-if="nowData===undefined"></div>
<div id="goto_sqlDefinition" v-on:click="gotoSqlDefinition()"></div>
</div>
<div id="loading_div">
<img src="/xpicon/gif/loading1.gif" style="height:70px;width:70px;"/>
</div>
</body>
<script src="sql_openwin.js"></script>
</html>
window.Com_Parameter = pageParent()["Com_Parameter"];
let vue_outer_div;
const pageParams = getPageParams();
console.log({pageParams});
let firstResult = 0;
let maxResults = Number(pageParams["maxResults"] || 20);// 默认每页20条记录
let lang = pageParams["lang"] || getLang();
let firstQuery = pageParams["firstQuery"] || "1";// 窗口打开后是否自动执行查询
let mainCallbackName = pageParams["mainCallbackName"] || "";
let inParamsWithSearch = pageParent(window)[pageParams["inParamsWithSearchKey"]] || {};// 搜索框传入动态默认参数
pageParent(window)[pageParams["inParamsWithSearchKey"]] = undefined;
let inParamsNotWithSearch = pageParent(window)[pageParams["inParamsNotWithSearchKey"]] || {};// 搜索框传入动态默认参数
pageParent(window)[pageParams["inParamsNotWithSearchKey"]] = undefined;
const parentCallback = pageParams["parentCallback"];// 待回调的父页面函数名(点击行、点击确定)
lang = lang.toUpperCase();
let sqlDefinitionFdId = "";
let sqlKey = pageParams["sqlKey"];
let winType = pageParams["winType"];// 窗口类型(single单、multiple多选)
let selectedData = pageParent(window)[pageParams["selectedDataKey"]] || [];// 已选择的数据
pageParent(window)[pageParams["selectedDataKey"]] = undefined;
let selectedData_copy = JSON.parse(JSON.stringify(selectedData));
let searchValue;
let search;
let search_copy;
let titles;
let winTitle;
let rightMenu_itemArr;
let historyData = {ekp: {}}
let rowData4RightMenu;
/* 对传入参数进行处理 */
let inParamsFunc = inParams[sqlKey];
if (inParamsFunc) {
if (!inParamsWithSearch || JSON.stringify(inParamsWithSearch) === "{}") {
let func = inParamsFunc["withSearch"];
if (typeof func === "function") {
inParamsWithSearch = func() || {};
}
}
if (!inParamsNotWithSearch || JSON.stringify(inParamsNotWithSearch) === "{}") {
let func = inParamsFunc["notWithSearch"];
if (typeof func === "function") {
inParamsNotWithSearch = func() || {};
}
}
}
/* 页面初始化 */
$(() => {
initConfig();// 设置开窗配置
vue_outer_div = new Vue({
el: '#outer_div',
data: {
lang: lang,
search: search[lang],
titles: titles[lang],
nowData: [],
total: 999,
nowPage: 1,
lastPageIndex: 0,
winType: winType,
multipleSelectedData: selectedData,// 多选状态下:已选数据
rightMenu: {// 右键菜单数据对象
visible: false,
top: 0,
left: 0,
},
rightMenu_itemArr: rightMenu_itemArr[lang],
data_div_height: 0,
noDataShow: false,
},
methods: {
isEmpty: isEmpty,
isNotEmpty: isNotEmpty,
dataRowClass: dataRowClass,
getSelectDisplayValue: getSelectDisplayValue,
getSelectTrueValue: getSelectTrueValue,
getTodayStr: getTodayStr,
hideColumn: hideColumn,
totalWidth : totalWidth
},
computed: {},
watch: {
rightMenu(value) {
if (value.visible) {
document.body.addEventListener('click', closeRightMenu)
} else {
document.body.removeEventListener('click', closeRightMenu)
}
}
}
});
// 执行查询
if (firstQuery === "1") {
searchData(true, 0);
}
// 设置数据区高度
let interval_setDivHeight = setInterval(() => {
let pagingOuterDiv_top = $("#paging_outer_div")[0].offsetTop;
let dataDiv_top = $("#data_div")[0].offsetTop;
if (pagingOuterDiv_top !== 0) {
vue_outer_div.$data.data_div_height = pagingOuterDiv_top - dataDiv_top - 5;
clearInterval(interval_setDivHeight);
}
}, 200)
})
/**
* 初始化配置
* @author liquid
* @date 2022年11月15日
*/
function initConfig() {
const _path_in = "xp/modeling/app/it/actions/XpEkpSqlDefinitionAction.do?method=getOpenWinConfigJson";
const _data_in = {key: sqlKey}
let openWinConfigJson;
ajaxAction(_path_in, _data_in, false, {
success: (res)=>{
if (res.status !== "success") {
errorHandler(res); return;
}
// 业务逻辑
sqlDefinitionFdId = res["fdId"];
openWinConfigJson = JSON.parse(res["openWinConfigJson"]);
console.log("openWinConfigJson",openWinConfigJson);
},
error: (error)=>{
errorHandler(error);
}
})
search = setDefaultParams(openWinConfigJson.search || {});
search_copy = JSON.parse(JSON.stringify(search));
// 列标题
titles = openWinConfigJson.titles || {"ZH-CN":[], "EN-US":[]};
// 窗口标题 - 移动端
winTitle = openWinConfigJson.winTitle;
document.title = winTitle[lang];
// 窗口标题 - pc端
let setTitle = window.parent["setWinCenterWithMaskTitle"];
if (typeof setTitle === "function") {
setTitle(winTitle[lang]);
}
// 右键菜单
rightMenu_itemArr = openWinConfigJson.rightMenu_itemArr || {"ZH-CN":[], "EN-US":[]};
// search = {
// "ZH-CN": [
// [
// {
// "name": "id",
// "title": "ID",
// "type": "text",
// "items": [],
// "default": "",
// "placeholder": "组织架构对象ID",
// "fuzzy": "Y"
// },
// {
// "name": "org_type",
// "title": "类型",
// "type": "dropdown",
// "items": [
// "机构|1",
// "部门|2",
// "岗位|4",
// "人员|8",
// "群组|16",
// "通用岗位|32"
// ],
// "default": "8",
// "placeholder": "",
// "fuzzy": "N"
// }
// ],
// [
// {
// "name": "name",
// "title": "名称",
// "type": "text",
// "items": [],
// "default": "",
// "placeholder": "",
// "fuzzy": "Y"
// },
// {
// "name": "name_pinyin",
// "title": "名称拼音",
// "type": "text",
// "items": [],
// "default": "",
// "placeholder": "",
// "fuzzy": "Y"
// }
// ]
// ],
// "EN-US": [
// [
// {
// "name": "id",
// "title": "ID",
// "type": "text",
// "items": [],
// "default": "",
// "placeholder": "Organization ID",
// "fuzzy": "Y"
// },
// {
// "name": "org_type",
// "title": "Type",
// "type": "dropdown",
// "items": [
// "Company|1",
// "Dept.|2",
// "Post|4",
// "Personnel|8",
// "Group|16",
// "Universal Post|32"
// ],
// "default": "8",
// "placeholder": "",
// "fuzzy": "N"
// }
// ],
// [
// {
// "name": "name",
// "title": "Name",
// "type": "text",
// "items": [],
// "default": "",
// "placeholder": "",
// "fuzzy": "Y"
// },
// {
// "name": "name_pinyin",
// "title": "Name Pinyin",
// "type": "text",
// "items": [],
// "default": "",
// "placeholder": "",
// "fuzzy": "Y"
// }
// ]
// ]
// };
// search_copy = JSON.parse(JSON.stringify(search));
// titles = {
// "ZH-CN": [
// {
// "label": "ID",
// "width": "25%"
// },
// {
// "label": "类型",
// "width": "5%"
// },
// {
// "label": "名称",
// "width": "25%"
// },
// {
// "label": "名称拼音",
// "width": "45%"
// }
// ],
// "EN-US": [
// {
// "label": "ID",
// "width": "25%"
// },
// {
// "label": "Type",
// "width": "5%"
// },
// {
// "label": "Name",
// "width": "25%"
// },
// {
// "label": "Name Pinyin",
// "width": "45%"
// }
// ]
// }
// rightMenu_itemArr = {
// "ZH-CN": [
// {
// title: "选项1"
// },
// {
// title: "选项2"
// },
// {
// title: "选项3"
// }
// ],
// "EN-US": [
// {
// title: "item-1"
// },
// {
// title: "item-2"
// },
// {
// title: "item-3"
// }
// ],
// };
}
/**
* 计算数据区外层宽度
* @author zengwenfu
* @date 2022年12月14日
* @returns {string}
*/
function totalWidth(){
let mWidth = 0;
if (titles["ZH-CN"][0].width.indexOf("px") > -1) {
for (var i = 0; i < titles["ZH-CN"].length; i++) {
mWidth += parseInt(titles["ZH-CN"][i].width);
}
return "width:"+mWidth+"px";
}
return "width:100%";
}
/**
* 斑马线
* @author liquid
* @date 2022年11月18日
* @param {number}index 行下标
* @returns {string}
*/
function dataRowClass(index){
return index % 2 === 0 ? "data_tr_0" : "data_tr_1";
}
/**
* 行点击事件
* @author liquid
* @date 2022年11月18日
* @param {array}rowData 触发行的数据
* @param {number}rowIndex 触发行的行下标
* @param event 触发事件对象
*/
function dataRowClick(rowData, rowIndex, event) {
let selectTxt = window.getSelection().toString();
if (isNotEmpty(selectTxt)) {// 避免选择文本时也触发点击事件的逻辑
return;
}
const targetClassName= event.target.className;
if (isEmpty(targetClassName) ||
!"multiple_choose_single;data_td".includes(targetClassName)) {
// 只有点击行的时候,才执行以下代码,避免在多选状态下点击checkbox时也触发
return;
}
const rtnData = makeRowData(rowData);
/* 单选 */
if (winType === "single") {
let isCloseWin = rowConfirm_callback(rtnData, "rowClick");
if (!isCloseWin) {// 不关闭开窗,以下回调不执行
return;
}
if(window.opener){
window.opener.postMessage(rtnData);
}
let mainCallBack = window.parent[mainCallbackName];
if (mainCallBack) {
mainCallBack(rtnData.sqlData);
}
closeWin();
}
/* 多选 */
if (winType === "multiple") {
const check = $(".multiple_choose_single > input")[rowIndex];
setChecked([rowIndex], !check.checked);
// 回调
let isCloseWin = rowConfirm_callback(rtnData, "rowClick");
if (isCloseWin) {
closeWin();
}
}
}
/**
* 构造被点击行的数据
* @author liquid
* @date 2022年12月14日
* @param rowData
*/
function makeRowData(rowData) {
const json = {};
for (let i = 0; i < rowData.length; i++) {
json[titles["ZH-CN"][i].valueKey] = rowData[i];
}
return {
"sqlData": {
arr: rowData,
json: json
},
}
}
/**
* 行鼠标右键事件
* @author liquid
* @date 2022年12月14日
* @param {array}rowData 触发行的数据
* @param {number}rowIndex 触发行的行下标
* @param event 触发事件对象
*/
function dataRowRightClick(rowData, rowIndex, event) {
rowData4RightMenu = makeRowData(rowData);
event.preventDefault();
openRightMenu(event);
}
/**
* 显示数据细节
* @author zengwenfu
* @param rowData
* @returns {string}
*/
function showDetail(rowData){
let str = "";
for(let i = 0;i < rowData.length; i++){
let data = rowData[i] ? rowData[i] : "";
str += titles[lang][i].label + " :" + data + "\n";
}
return str;
}
/**
* 打开自定义右键菜单
* @author liquid
* @date 2022年12月14日
* @param event 触发事件对象
*/
function openRightMenu(event) {
vue_outer_div.$data.rightMenu = {
left: event.clientX,
top: event.clientY,
visible: true
};
}
/**
* 关闭自定义右键菜单
* @author liquid
* @date 2022年12月14日
*/
function closeRightMenu() {
vue_outer_div.$data.rightMenu = {
visible: false
}
}
/**
* [多选]选中或取消选中之后执行一些操作
* @author liquid
* @date 2022年11月22日
* @param indexes 选中或取消选中的下标数组
* @param checked 选中(true),取消选中(false)
*/
function setChecked(indexes, checked) {
for (const index of indexes) {
const checkbox = $(".multiple_choose_single > input")[index];
$(checkbox).prop("checked", checked);
const addData = JSON.parse(JSON.stringify(vue_outer_div.nowData[index]));
if (checked && !JSON.stringify(vue_outer_div.multipleSelectedData).includes(JSON.stringify(addData))) {// 是选中
vue_outer_div.multipleSelectedData.push(addData);
}
else if (!checked){// 取消选中
vue_outer_div.multipleSelectedData = delElement(vue_outer_div.multipleSelectedData, addData);
}
}
}
/**
* 获取下拉菜单、单选按钮、多选按钮的显示值
* @author liquid
* @date 2022年11月18日
* @param {string}str
* @returns {*}
*/
function getSelectDisplayValue(str) {
return str.includes("|") ? str.substring(0, str.indexOf('|')) : str;
}
/**
* 获取下拉菜单、单选按钮、多选按钮的实际值
* @author liquid
* @date 2022年11月18日
* @param {string}str
* @returns {*}
*/
function getSelectTrueValue(str) {
return str.includes("|") ? str.substring(str.indexOf('|') + 1) : str;
}
/**
* 获取今日日期字符串
* @author liquid
* @date 2022年11月18日
* @param {string}date 传入"today"获取的是今日的格式化日期字符串
* @returns {null|string|*}
*/
function getTodayStr(date) {
if (isEmpty(date)) {
return null;
}
return date === "today" ? xp_formatDateTime(new Date(), "Y-M-D") : date;
}
/**
* 下拉菜单值变化事件
* @author liquid
* @date 2023年2月19日
* @param event
*/
function dropdownChange(event) {
queryClick();
}
/**
* 单选按钮点击事件
* @author liquid
* @date 2022年11月18日
* @param event
*/
function radioClick(event) {
const elements = $("[name=" + event.target.name + "]");
for (let i = 0; i < elements.length; i++) {
if (i !== Number(event.target.dataset.index)) {
$(elements[i]).attr("checked", false);
}
}
queryClick();
}
/**
* 多选按钮点击事件
* @author liquid
* @date 2023年2月19日
* @param event
*/
function checkboxClick(event) {
queryClick();
}
/**
* 若url传入搜索框默认值,则重设搜索框默认值
* @author liquid
* @date 2022年11月14日
*/
function setDefaultParams(search) {
const searchTemp = JSON.parse(JSON.stringify(search));
for (const e1 of searchTemp[lang]) {
for (const e2 of e1) {
const value = inParamsWithSearch[e2.name];
e2.default = isNotEmpty(value) ? value : e2.default;
}
}
return searchTemp;
}
/**
* 获取搜索框中的输入值(包括隐藏的搜索参数)
* @author liquid
* @date 2022年11月14日
*/
function getSearchValue() {
const searchConfig = search[lang];
const rtn = {};
for(const i_value of searchConfig) {
for (const j_value of i_value) {
if ("text;dropdown;date".includes(j_value.type)) {
let value = $("[name='"+ j_value.name +"']").val();
value = isEmpty(value) ? "" : value;
rtn[j_value.name] = j_value.fuzzy === "Y" ? "%" + value + "%" : value;
j_value.default = value;
}
else if (j_value.type === "radio") {
let value = $("input:radio[name='" + j_value.name + "']:checked").val();
value = isEmpty(value) ? "" : value;
rtn[j_value.name] = j_value.fuzzy === "Y" ? "%" + value + "%" : value;
j_value.default = value;
}
else if (j_value.type === "checkbox") {
const values = [undefined];// 放一个空值,防止传入空数组导致接口调用失败
const checkboxes = $("input:checkbox[name='"+ j_value.name +"']:checked");
for (const e of checkboxes) {
values.push($(e).val())
}
rtn[j_value.name] = values;
j_value.default = values.join(";");
}
}
}
for (const key in inParamsNotWithSearch) {
rtn[key] = inParamsNotWithSearch[key];
}
return rtn;
}
/**
* 搜索区域键入事件
* @author liquid
* @date 2022年11月18日
* @param event
*/
function outerDivKeydown(event) {
if (event.key === "Enter") {
searchData(true, 0);
}
}
/**
* 查询点击事件
* @author liquid
* @date 2022年11月18日
*/
function queryClick() {
searchData(true, 0);
}
/**
* 重置点击事件
* @author liquid
* @date 2022年11月18日
*/
function resetClick() {
// 清空本次的历史数据
for (const key in historyData) {
historyData[key] = {};
}
search = JSON.parse(JSON.stringify(search_copy));
vue_outer_div.search = search[lang];
vue_outer_div.multipleSelectedData = JSON.parse(JSON.stringify(selectedData_copy));
setTimeout(function() {// 延迟搜索,避免数据还没渲染完就去拿值
searchData(true, 0);
}, 200)
}
/**
* 确定点击事件
* @author liquid
* @date 2022年11月18日
*/
function confirmClick() {
/* 非多选,不执行 */
if (winType !== "multiple") {
return;
}
const sqlData = {arr: vue_outer_div.multipleSelectedData, json: {}, arr_str: [], json_str: {}, json_arr: []};
/* sqlData.json & sqlData.json_str & json_arr */
const titlesArr = titles["ZH-CN"];
for (let i = 0; i < sqlData.arr.length; i++) {
for (let j = 0; j < titlesArr.length; j++) {
const valueKey = titlesArr[j].valueKey;
const arr = sqlData.json[valueKey] || [];
arr.push(sqlData.arr[i][j]);
sqlData.json[valueKey] = arr;
sqlData.json_str[valueKey] = arr.join(";");
}
}
// sqlData.arr_str
for (let i = 0; i < sqlData.arr.length; i++) {
for (let j = 0; j < sqlData.arr[i].length; j++) {
sqlData.arr_str[j] = (sqlData.arr_str[j] || "") + sqlData.arr[i][j] + ";";
}
}
for (let i = 0; i < sqlData.arr.length; i++) {
sqlData.arr_str[i] = delLastChar(sqlData.arr_str[i], 1);
}
// json_arr
let json_arr = [];
for (let i = 0; i < sqlData.arr.length; i++) {
let tempArr = sqlData.arr[i];
let tempJson = {};
for (let j = 0; j < tempArr.length; j++) {
const valueKey = titlesArr[j].valueKey;
tempJson[valueKey] = tempArr[j];
}
json_arr.push(tempJson);
}
sqlData.json_arr = json_arr;
/* 回传数据 */
const rtnData = {
sqlData: sqlData
}
/* 回调 */
let isCloseWin = rowConfirm_callback(rtnData, "confirmClick");
if (!isCloseWin) {// 不关闭开窗,以下回调不执行
return;
}
if(window.opener){
window.opener.postMessage(rtnData);
}
let mainCallBack = window.parent[mainCallbackName];
if (mainCallBack) {
mainCallBack(rtnData.sqlData);
}
closeWin();
}
/**
* 集中处理各类型回调函数
* @author liquid
* @date 2022年12月9日
* @param rtnData 回传数据
* @param clickType 点击类型(rowClick点击行\confirmClick点击确定)
* @return {boolean} 开窗是否可关闭
*/
function rowConfirm_callback(rtnData, clickType) {
const func1 = window.opener ? window.opener[parentCallback] || "" : "";
let func2 = selfCallback[sqlKey] || "";
func2 = func2 ? func2[clickType] : "";
const canBeClosed = (winType === "single" && clickType === "rowClick") ||
(winType === "multiple" && clickType === "confirmClick");
// 回调(函数在父页面)
if (typeof func1 == "function") {
const rtn1 = func1(rtnData);
if (rtn1.code === 0) {
if (isNotEmpty(rtn1.msg)) alert(rtn1.msg);
}
else if (canBeClosed){
return true;
}
}
else if (typeof func2 == "function") {// 回调(函数在开窗页面)
const bool = func2(rtnData);
if (bool && canBeClosed) {
return true;
}
}
else if (canBeClosed) {
return true;
}
return false;
}
/**
* 右键菜单回调
* @author liquid
* @date 2022年12月14日
*/
function rightMenu_callback(callbackIndex) {
const funcArr = rightMenuCallback[sqlKey] || [];
let callbackRtn = false;
if (funcArr[callbackIndex]) {
callbackRtn = funcArr[callbackIndex](rowData4RightMenu || []);
}
else {
alert("未配置该选项的回调函数");
}
if (callbackRtn) {
closeWin();
}
}
/**
* 多选取消已选
* @param data
* @param rowIndex
* @param event
*/
function cancelSelectedData(data, rowIndex, event) {
let selectTxt = window.getSelection().toString();
if (isNotEmpty(selectTxt)) {// 避免选择文本时也触发点击事件的逻辑
return;
}
vue_outer_div.multipleSelectedData = delElement(vue_outer_div.multipleSelectedData, data);
}
/**
* 关闭开窗
* @author liquid
* @date 2023年2月19日
*/
function closeWin() {
// 移动端
window.close();
// pc端
let closeFunc = window.parent.closeWinCenterWithMask;
if (typeof closeFunc === "function") {
closeFunc();
}
}
function changeToWin() {
window.open(document.location.href);
window.onmessage = function(e) {
const sqlData = e.data.sqlData;
console.log(sqlData);
if (sqlData !== null && sqlData !== undefined) {
vue_outer_div.$data.multipleSelectedData = sqlData.arr;
}
}
}
/**
* 导出开窗数据(查询条件下的全部数据)
* @author zengwenfu
* @date 2022年12月13日
*/
function exportData() {
let searchStr = getSearchValue();
let exportTitle = [];
for (let i = 0; i < titles[lang].length; i++) {
exportTitle.push(titles[lang][i].label);
}
// 调接口拿数据
loading(true);
ajaxActionPms("xp/modeling/app/it/actions/XpEkpSqlAction.do?method=executeQuery", {
key: sqlKey,
params: searchStr
}).then((res)=>{
if (res.status !== "success") { errorHandler(res); return; }
// 成功回调
export2Excel(res.queryData, exportTitle, winTitle[lang]);
loading(false);
}).catch((error)=>{errorHandler(error);})
}
/**
* 获取第一页数据
* @author liquid
* @date 2022年11月14日
*/
function firstPageClick() {
searchData(true, 0);
}
/**
* 获取上一页数据
* @author liquid
* @date 2022年11月14日
*/
function pageUpClick() {
const index = firstResult - maxResults;
if (index >= 0) {
searchData(false, index);
}
}
/**
* 获取下一页数据
* @author liquid
* @date 2022年11月14日
*/
function pageDownCLick() {
const index = firstResult + maxResults;
if (index < vue_outer_div.total) {
searchData(false, index);
}
}
/**
* 获取最后一页数据
* @author liquid
* @date 2022年11月14日
*/
function lastPageClick() {
const lastLeft = vue_outer_div.total % maxResults;
let index = vue_outer_div.total - (lastLeft === 0 ? maxResults : lastLeft);
searchData(false, index);
}
/**
* 多选时点击[全选]触发事件
* @author liquid
* @date 2022年11月21日
*/
function multipleChooseAll() {
const multipleCheck = $("#multiple_choose_all > input:checked");
setChecked(new Array(maxResults).keys(), multipleCheck.length > 0);
}
/**
* 判断是否需要隐藏列
* @author liquid
* @date 2022年11月18日
*/
function hideColumn(index) {
const width = titles["ZH-CN"][index].width;
return "0;0px;0PX;0px;0Px;0pX;0vw;0VW;0Vw;0vW;0%".includes(width);
}
/**
* 判断是否已全选
* @author liquid
* @date 2022年11月22日
* @returns {boolean} 是否已全选
*/
function isAllSelected() {
let isAllSelected = true;
const selectedDataStr = JSON.stringify(vue_outer_div.multipleSelectedData);
for (let i = 0; i < vue_outer_div.nowData.length && isAllSelected; i++) {
const nowDataRowStr = JSON.stringify(vue_outer_div.nowData[i]);
isAllSelected = selectedDataStr.includes(nowDataRowStr);
}
return vue_outer_div.multipleSelectedData.length !== 0 && isAllSelected;
}
/**
* 判断本行是否已选
* @author liquid
* @date 2022年11月22日
* @param value 本行数据
* @returns {boolean} 是否已选
*/
function isSelected(value) {
return JSON.stringify(vue_outer_div.multipleSelectedData).includes(JSON.stringify(value));
}
/**
* (多选)左边checkbox的点击事件
* @author liquid
* @date 2022年11月22日
* @param rowIndex
*/
function multipleChooseSingleClick(rowIndex) {
const checked = $(".multiple_choose_single > input")[rowIndex].checked;
setChecked([rowIndex], checked);
}
/**
* 执行搜索
* @author liquid
* @date 2022年11月15日
* @param renewSearch 是否重新以搜索框值作为条件值
* @param index 从第index个记录开始返回
*/
function searchData(renewSearch = true, index = 0) {
let queryData;// 查询结果集
let queryMaxCount;// 查询结果最大记录数
// 重新以搜索框值作为条件值
if (renewSearch) {
index = 0;
searchValue = getSearchValue();
}
firstResult = index;
searchValue._fixed = {
firstResult: firstResult,// 从第firstResult条记录开始查询
maxResults: maxResults// 限制查询pageRowCount个结果
}
console.log("查询参数", searchValue);
// 执行查询
// 若存在历史记录则直接返回
const paramsStr = JSON.stringify(searchValue);
if (historyData.ekp[paramsStr]) {
const data = historyData.ekp[paramsStr];
renewData(data.queryData, data.queryMaxCount);
return;
}
// 无历史记录则向后台查询
loading(true);
ajaxActionPms("xp/modeling/app/it/actions/XpEkpSqlAction.do?method=executeQuery", {
key: sqlKey,
params: searchValue
}).then((res)=>{
console.log({res})
if (res.status !== "success") { errorHandler(res); return; }
// 成功回调
queryData = res.queryData;
queryMaxCount = res.queryMaxCount;
renewData(queryData, queryMaxCount);
historyData.ekp[JSON.stringify(searchValue)] = res;// 保存历史记录
loading(false);
}).catch((error)=>{errorHandler(error);})
}
/**
* 重新选择页面数据
* @author liquid
* @date 2022年11月18日
* @param queryData
* @param queryMaxCount
*/
function renewData(queryData, queryMaxCount) {
// 重新渲染页面数据
vue_outer_div.nowData = queryData;
vue_outer_div.total = queryMaxCount;
vue_outer_div.nowPage = queryMaxCount === 0 ? 0 : Math.ceil((firstResult + 1) / maxResults);
vue_outer_div.lastPageIndex = Math.ceil(queryMaxCount / maxResults);
}
/**
* 转圈圈
* @author liquid
* @date 2022年11月18日
* @param {boolean}open 是否转圈圈
* @return {void}
*/
function loading(open) {
if (open) {
vue_outer_div.noDataShow = false;
$("#loading_div").css("display", "flex")
} else {
vue_outer_div.noDataShow = true;
$("#loading_div").hide();
}
}
/**
* 前往sql定义
* @author liquid
* @date 2023年4月17日
* @return {void}
*/
function gotoSqlDefinition() {
if (isEmpty(sqlDefinitionFdId)) {
return;
}
let url = Com_Parameter.ContextPath +
"sys/modeling/main/modelingAppSimpleMain.do?method=edit" +
"&fdId=" + sqlDefinitionFdId;
window.open(url);
}
function getLang(){
let langStr = window.opener == null ? parent.window.Com_Parameter.Lang : window.opener.Com_Parameter.Lang;
return langStr.toUpperCase();
}
3、具体实现 - 后端
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.landray.kmss.xp.xform.base.service.controls.relationchoose;
import com.landray.kmss.sys.xform.base.service.ISysFormTemplateControl;
import com.landray.kmss.sys.xform.base.service.ISysFormTemplateDetailsTableControl;
import com.landray.kmss.sys.xform.base.service.controls.FilterAction;
import com.landray.kmss.sys.xform.base.service.controls.LoopAction;
import com.landray.kmss.sys.xform.base.service.controls.TagNodeUtils;
import com.landray.kmss.util.StringUtil;
import org.htmlparser.Node;
import org.htmlparser.lexer.Lexer;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.tags.InputTag;
import org.htmlparser.util.ParserException;
import java.util.List;
public class XpSysFormTemplateRelationChooseControl implements ISysFormTemplateControl, FilterAction, ISysFormTemplateDetailsTableControl {
private String parentClass;
public XpSysFormTemplateRelationChooseControl() {
}
public boolean parse(Node node, Lexer lexer, StringBuilder jsp, List<ISysFormTemplateControl> controls) throws Exception {
if (node instanceof TagNode) {
TagNode tagNode = (TagNode)node;
if (TagNodeUtils.isType("xpRelationChoose", tagNode)) {
TagNodeUtils.fixRequired(tagNode);
TagNodeUtils.filterNode(tagNode, lexer, jsp, this);
return true;
}
}
return false;
}
private void doParse(Node node, StringBuilder jsp) throws ParserException {
if (node instanceof InputTag) {
TagNode tagNode = (TagNode)node;
String id = tagNode.getAttribute("id");
String bindEvent = "click";
String required = tagNode.getAttribute("_required");
String style = tagNode.getAttribute("style");
String freeEdit = tagNode.getAttribute("freeEdit");
String editCallbackFunName = tagNode.getAttribute("editCallbackFunName");
String openWinFunName = tagNode.getAttribute("openWinFunName");
String notNullCheck = tagNode.getAttribute("notNullCheck");
String clearCallbackFunName = tagNode.getAttribute("clearCallbackFunName");
String clearFieldId = tagNode.getAttribute("clearFieldId");
String params = "{" +
"'freeEdit':'" + freeEdit + "'," +
"'editCallbackFunName':'" + editCallbackFunName + "'," +
"'openWinFunName':'" + openWinFunName + "'," +
"'clearCallbackFunName':'" + clearCallbackFunName + "'," +
"'clearFieldId':'" + clearFieldId + "'," +
"'notNullCheck':'" + notNullCheck + "'" +
"}";
params = params.replaceAll("'", "quot;");
jsp.append("\r\n").append(TagNodeUtils.getElementTab()).append(TagNodeUtils.buildControlWrapHTMLBegin(tagNode.getAttribute("id"), "xform_relation_choose", "relationChoose"));
jsp.append("\r\n").append(TagNodeUtils.getElementTab()).append("<div ");
String canApplyClass = tagNode.getAttribute("parent_class");
if (StringUtil.isNull(canApplyClass)) {
canApplyClass = this.parentClass;
}
TagNodeUtils.setAttribute(jsp, "class", canApplyClass);
jsp.append(">");
jsp.append("<c:import url='/xp/xform/designer/relation_choose/relation_choose_display.jsp' charEncoding='UTF-8'>").
append("<c:param name='fdControlId' value='").append(id).append("'></c:param>").
append("<c:param name='required' value='").append(required).append("'></c:param>").
append("<c:param name='style' value='").append(style).append("'></c:param>").
append("<c:param name='bindEvent' value='").append(bindEvent).append("'></c:param>").
append("<c:param name='subject' value='${xform:subject(\"").append(id).append("\",\"label\")}'></c:param>").
append("<c:param name='parentClass' value='").append(canApplyClass).append("'></c:param>").
append("<c:param name='params' value='").append(params).append("'></c:param>");
jsp.append("</c:import>");
jsp.append("</div>");
jsp.append(TagNodeUtils.buildControlWrapHTMLEnd());
jsp.append(TagNodeUtils.getElementTab());
}
}
public void end(Node node, StringBuilder jsp) throws ParserException {
this.doParse(node, jsp);
}
public void filter(Node node, StringBuilder jsp) throws ParserException {
this.doParse(node, jsp);
}
public void start(Node node, StringBuilder jsp) throws ParserException {
if (node instanceof TagNode) {
TagNode tempNode = (TagNode)node;
this.parentClass = tempNode.getAttribute("class");
}
this.doParse(node, jsp);
}
public boolean parseDetailsTable(Node node, Lexer lexer, StringBuilder templateJsp, final String idPrefix, List<ISysFormTemplateControl> controls) throws Exception {
if (node instanceof TagNode) {
TagNode tagNode = (TagNode)node;
if (TagNodeUtils.isType("xpRelationChoose", tagNode)) {
TagNodeUtils.loopForDetailsTable(this, tagNode, lexer, templateJsp, idPrefix, controls, new LoopAction() {
public boolean action(Node aTagNode, Lexer lexer, StringBuilder jsp, List<ISysFormTemplateControl> controls) throws Exception {
if (aTagNode instanceof TagNode) {
TagNode tagNode = (TagNode)aTagNode;
TagNodeUtils.setDetailsTableId(idPrefix, tagNode);
if (!(tagNode instanceof InputTag)) {
return false;
} else {
XpSysFormTemplateRelationChooseControl.this.doParse(tagNode, jsp);
return true;
}
} else {
return false;
}
}
});
return true;
}
}
return false;
}
}