ABP +VUE Elment 通用高级查询(右键菜单)设计+LINQ通用类Expression
1、 目前需要用VUE实现源cs系统报表的右键菜单所有和自定义查询功能。
1.1 CS端的右键菜单效果如下图
经分析得知, 当用户鼠标选择不同类型的列下拉框中关系操作符不同, 如下所示:
1.2 高级查询根据选择的字段在关系操作符显示不同的关系操作
- 时间日期格式类型:
- 金额数字类型:
- 字符串类型:
2、vue下实现右键菜单效果
2.1、安装v-contextmenu
# npm install v-contextmenu --save-dev
2.2、简单示例
// main.js
import contentmenu from 'v-contextmenu'
import 'v-contextmenu/dist/index.css'
Vue.use(contentmenu)
<div ref="box" :class="['box', theme]">
<v-contextmenu ref="contextmenu" :theme="theme">
<v-contextmenu-item @click="selectRecordhandleClick">按选定内容筛选</v-contextmenu-item>
<v-contextmenu-item @click="uSelectRecordhandleClick">排除当前选定内容</v-contextmenu-item>
<v-contextmenu-item @click="uselectRowhandleClick">排除当前行</v-contextmenu-item>
<v-contextmenu-item divider />
<v-contextmenu-item @click="showAdvanceForm">自定义筛选条件</v-contextmenu-item>
<div class="flag">
<span><i class="fa fa-star" /></span>
</div>
</v-contextmenu>
</div>
2.3、在表格中右击事件关联
<el-table
ref="elTable"
v-contextmenu:contextmenu
v-loading="listLoading"
:data="list"
border
fit
stripe
highlight-current-row
:header-cell-style="{background:'#eef1f6',color:'#606266'}"
@row-contextmenu="rightClick"
@cell-click="cellclick"
>
2.4 右键点击事件实现
右键点击事件
rightClick(row, column, event) {
console.log('000000000000000rightClicky000000');
this.selectForm.captionID = column.property;
this.selectForm.caption = column.label;
this.selectForm.currentfildCaption = column.label;
this.selectForm.fieldNameValue = row[column.property];
this.selectForm.fieldName = column.property;
this.selectForm.field_cvoucH_IDValue = row['cvoucH_ID'];
var str = this.selectForm.fieldName;
if (str.indexOf('NUM') >= 0 || str.indexOf('Rate') >= 0 || str.indexOf('Amount') >= 0 || str.indexOf('Quantity') >= 0) {
this.selectForm.dataType = 1;
} else if (str.indexOf('Date') >= 0 || str.indexOf('time') >= 0) {
this.selectForm.dataType = 2;
} else {
this.selectForm.dataType = 0;
}
console.log('column.property==' + str + ' this.selectForm.dataType=');
console.log(this.selectForm.dataType);
console.log(column.label);
console.log(column.property);
console.log(row[column.property]);
this.setCurrent(row);
},
setCurrent(row) {
console.log('高亮' + row);
this.$refs.elTable.setCurrentRow(row);
}
}
}
2.5 加载不同关系表达式和操作符
<div v-if="searchForm.dataType == '0'"> 字符串类型
<div v-if="searchForm.dataType == '1'"> 数字、金额类型
<div v-if="searchForm.dataType == '2'"> 日期类型
// 查询条件
queryFilterOptions: {
fields: [
{ label: '单据号', value: 'cvoucH_ID' },
{ label: '摘要', value: 'cdigest' }
],
operators: [
{ label: ' ', value: ' ' },
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'neq' },
{ label: '包含', value: 'con' },
{ label: '不包含', value: 'ncon' }
],
operatorsNUM: [
{ label: ' ', value: ' ' },
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'neq' },
{ label: '>', value: 'greater' },
{ label: '<', value: 'less' },
{ label: '>=', value: 'greaterEqual' },
{ label: '<=', value: 'lessEqual' }
],
operatorsDate: [
{ label: ' ', value: ' ' },
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'neq' },
{ label: '始于', value: 'greaterEqual' },
{ label: '止于', value: 'lessEqual' }
],
logics: [
{ label: '且', value: 'and' },
{ label: '或', value: 'or' }
]
}
2.6 效果图
2.5、 完整的前端代码
<!-- 独立弹出式的高级查询界面,不建议使用,建议使用折叠条件方式处理复杂条件 -->
<template>
<el-dialog
id="hy-three-query"
v-el-drag-dialog
v-dialogDrag
title="高级查询"
:visible.sync="isVisible"
:append-to-body="true"
:before-close="handleClose"
:close-on-click-modal="false"
>
<el-form ref="searchForm" :rules="rules" :model="searchForm" size="small" :inline="true" label-width="50px" label-position="top">
<el-row :gutter="50" class="el-row">
<el-form-item :label="reciveData.caption" />
</el-row>
<el-row :gutter="50" class="el-row">
<el-col :span="50">
<el-form-item prop="relationalOperator1">
<div v-if="searchForm.dataType == '0'">
<el-select v-model="searchForm.relationalOperator1" placeholder="请选择">
<!-- this.reciveData.currentfildCaption -->
<el-option
v-for="item in queryFilterOptions.operators"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div v-else-if="searchForm.dataType == '1'">
<el-select v-model="searchForm.relationalOperator1" placeholder="请选择">
<!-- this.reciveData.currentfildCaption -->
<el-option
v-for="item in queryFilterOptions.operatorsNUM"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div v-else-if="searchForm.dataType == '2'">
<el-select v-model="searchForm.relationalOperator1" placeholder="请选择">
<!-- this.reciveData.currentfildCaption -->
<el-option
v-for="item in queryFilterOptions.operatorsDate"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</el-form-item>
</el-col>
<el-col :span="50">
<el-form-item prop="value1">
<el-input v-model="searchForm.value1" placeholder="请输入内容" style="width: 138px" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="50" class="el-row">
<el-col :span="100">
<el-form-item prop="logicOperator">
<div class="block">
<el-radio v-model="searchForm.logicOperator" label="AND">并且(AND)</el-radio>
<el-radio v-model="searchForm.logicOperator" label="OR">或者(OR)</el-radio>
</div></el-form-item>
</el-col>
</el-row>
<el-row :gutter="50" class="el-row">
<el-col :span="50">
<el-form-item prop="relationalOperator2">
<div v-if="searchForm.dataType == '0'">
<el-select v-model="searchForm.relationalOperator2" placeholder="请选择">
<!-- this.reciveData.currentfildCaption -->
<el-option
v-for="item in queryFilterOptions.operators"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div v-if="searchForm.dataType == '1'">
<el-select v-model="searchForm.relationalOperator2" placeholder="请选择">
<!-- this.reciveData.currentfildCaption -->
<el-option
v-for="item in queryFilterOptions.operatorsNUM"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div v-if="searchForm.dataType == '2'">
<el-select v-model="searchForm.relationalOperator2" placeholder="请选择">
<!-- this.reciveData.currentfildCaption -->
<el-option
v-for="item in queryFilterOptions.operatorsDate"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</el-form-item>
</el-col>
<el-col :span="50">
<el-form-item prop="value2">
<el-input v-model="searchForm.value2" placeholder="请输入内容" style="width: 138px" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" size="mini" @click="handleSearch()">查询</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetSeachForm('searchForm')">重置</el-button>
<el-button size="mini" @click="handleClose()">关闭</el-button>
</div>
</el-dialog>
</template>
<script>
import { pickerOptions } from '@/utils/constantOptions.js' // 导入快速时间选择设置
import { string } from 'clipboard';
export default {
props: {
reciveData: {
type: Object,
default: () => ({
caption: [string],
captionID: [string],
currentfildCaption: [string], // 用于设置默认选中项,
dataType: [string]// 过滤条件中的操作的字段的类型
})
}
},
data() {
return {
listLoading: true, // 列表加载状态
searchForm: { // 查询表单
fieldName: '',
relationalOperator1: '',
relationalOperator2: '',
value1: '',
value2: '',
logicOperator: 'AND',
dataType: ''// 过滤条件中的操作的字段的类型
},
isVisible: false,
pickerOptions: pickerOptions, // 日期快速选择项目
radio: '1',
value1: '',
value2: '',
userinput1: '',
userinput2: '',
rules: {// 数据校验规则
value1: [
{ required: true, message: '不能为空', trigger: 'blur' }
],
relationalOperator1: [
{ required: true, message: '关系不能为空', trigger: 'blur' }
]
},
// 查询条件
queryFilterOptions: {
fields: [
{ label: '单据号', value: 'cvoucH_ID' },
{ label: '摘要', value: 'cdigest' }
],
operators: [
{ label: ' ', value: ' ' },
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'neq' },
{ label: '包含', value: 'con' },
{ label: '不包含', value: 'ncon' }
],
operatorsNUM: [
{ label: ' ', value: ' ' },
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'neq' },
{ label: '>', value: 'greater' },
{ label: '<', value: 'less' },
{ label: '>=', value: 'greaterEqual' },
{ label: '<=', value: 'lessEqual' }
],
operatorsDate: [
{ label: ' ', value: ' ' },
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'neq' },
{ label: '始于', value: 'greaterEqual' },
{ label: '止于', value: 'lessEqual' }
],
logics: [
{ label: '且', value: 'and' },
{ label: '或', value: 'or' }
]
}
}
},
watch: { // 监听
isVisible(newValue, oldValue) {
this.isVisible = newValue;
}
},
created() { // 页面加载后,加载树列表+列表数据
},
methods: {
show() { /* 打开对话框 */
this.isVisible = true
console.log('打开对话框@@')
console.log(this.reciveData);
console.log(this.reciveData);
this.currentfildCaption = this.reciveData.caption;
this.searchForm.fieldName = this.reciveData.captionID;
this.searchForm.dataType = this.reciveData.dataType;
console.log('打开对话框' + this.reciveData.currentfildCaption);
console.log('打开对话框' + this.reciveData.dataType);
},
handleClose() { // 关闭页面
this.isVisible = false;
this.$emit('close')
},
async handleSearch() { // 表单提交
this.$refs['searchForm'].validate(valid => {
if (valid) {
this.isVisible = false;
console.log(this.searchForm);
this.$emit('search', this.searchForm);
}
})
},
resetSeachForm(formName) { // 重置查询条件处理
this.$refs[formName].resetFields();
console.log(this.$refs[formName]);
}
}
}
</script>
<!--界面样式 -->
<style>
.ele-upload-file-uploader {
margin-bottom: 5px;
}
.el-tag + .el-tag {
margin-left: 10px;margin-bottom: 10px;
}
input[disabled],input:disabled,input.disabled{
color: #333;
-webkit-text-fill-color:#333;
-webkit-opacity:1;
opacity: 1;
}
textarea[disabled],textarea:disabled,textarea.disabled{
color: #333;
-webkit-text-fill-color:#333;
-webkit-opacity:1;
opacity: 1;
}
.border-radius{
border-radius:4px 4px 0 0;border:1px solid hsla(0,0%,100%,.6);box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1)
}
.el-dialog{
margin:0!important;
display:flex;
flex-direction:column;
}
.el-dialog__body{
transform: translate3d(0,0,0);
overflow:auto;
}
.el-dialog__header {
padding: 20px 20px 20px 20px!important;
border-bottom: 1px solid #f4f4f4;
}
.el-dialog__footer {
text-align: center!important;
padding: 12px 20px 12px 20px!important;
border-top: 1px solid #f4f4f4;
}
.el-dialog__headerbtn {
position: absolute;
top: 20px;
right: 20px;
padding: 0;
background: 0 0;
border: none;
outline: 0;
cursor: pointer;
font-size: 24px!important;
}
.el-dialog__wrapper {
display:flex;
justify-content: center;
align-items:center;
}
.dialog-footer{
float: right;
}
</style>
3、API实现
3.1、 要点概述
- 因为需要做出一个通用查询功能,用户选择任意一张报表只要把报表信息给到你就能实现上述查询功能。
- 还有一点就是我们使用linq表达式查询, 主要就是获取条件表达式,故使用泛型,然后通过反射取获取用户选择的查询列,然后去构造Expression表达式。
Expression<Func<TFields, bool>> GetAdvanceQueryCondition<TFields, TParaInput>(TFields tableFields, TParaInput paraInput)
- 专门设计一个方法取将传入的参数结构化到一个字典中
Dictionary<string, object> GetInputPara<TParaInput>(TParaInput paraInput)
public Class FilterMode
{
/// <summary>
/// 上下文菜单前三个查询条件选中列对应的字段值
/// 1-按选定内容筛选
/// 2-排除当前选定内容
/// 3-排除当前行
/// </summary>
public string fieldNameValue { get; set; }
public string field_cvoucH_IDValue { get; set; }
//以下是高级查询的信息结构
/// <summary>
/// 过滤条件中使用的数据列
/// </summary>
public string fieldName { get; set; }
/// <summary>
/// 过滤条件中的关系操作符:==、!=等
/// </summary>
public string relationalOperator1 { get; set; }
/// <summary>
/// 过滤条件中的关系操作符:==、!=等
/// </summary>
public string relationalOperator2 { get; set; }
/// <summary>
/// 过滤条件中的操作的值
/// </summary>
public string value1 { get; set; }
/// <summary>
/// 过滤条件中的操作的值
/// </summary>
public string value2 { get; set; }
/// <summary>
/// 过滤条件之间的逻辑关系:AND和OR
/// </summary>
public string logicOperator { get; set; }
/// <summary>
/// 过滤条件中的操作的字段的类型
/// 0-字符,1-数字,2-日期
/// </summary>
public string dataType { get; set; }
}
3.2、 完整代码
- 完整代码如下:
/// <summary>
/// 报表通用高级查询(右键菜单)通用类
/// 遍历对象属性构造查询条件
/// 1.输入的参数
/// 2,返回表格的属性信息集合
/// </summary>
/// <typeparam name="T"></typeparam>
public class ReportAdvanceQueryUtility//<TFields, TParaInput>
{
/// <summary>
/// 遍历对象属性构造查询条件
/// </summary>
/// <typeparam name="TFields">表格的属性列</typeparam>
/// <typeparam name="TParaInput">输入的参数</typeparam>
/// <param name="tableFields">表格的属性列对象</param>
/// <param name="paraInput"></param>
public static Expression<Func<TFields, bool>> GetAdvanceQueryCondition<TFields, TParaInput>(TFields tableFields, TParaInput paraInput)
{
string[] relationalOperator = new string[2];
string logicOperator = "";
Expression<Func<TFields, bool>> linqFilterExpressionLeft = null;
Dictionary<string, object> dicFieldValue = GetInputPara(paraInput);
Type t = tableFields.GetType();
PropertyInfo[] PropertyList = t.GetProperties();
foreach (PropertyInfo item in PropertyList)
{
string name = item.Name;
object value = item.GetValue(tableFields, null);
string usetSelectedFieldName = dicFieldValue["fieldName"].ToString();
if (item.Name == usetSelectedFieldName)
{
if ("0" == dicFieldValue["dataType"].ToString())//0 - 字符,1 - 数字,2 - 日期
{
if ("eq" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "=";
}
else if ("neq" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "!=";
}
else if ("con" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "%";
}
else if ("ncon" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "!=";
}
if (!string.IsNullOrEmpty(dicFieldValue["value2"].ToString()))
{
if ("eq" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "=";
}
else if ("neq" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "!=";
}
else if ("con" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "%";
}
else if ("ncon" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "!=";
}
logicOperator = dicFieldValue["logicOperator"].ToString();
linqFilterExpressionLeft = GetAndLambdaExpression_0<TFields>(new string[] { item.Name, item.Name }, new string[] { dicFieldValue["value1"].ToString(), dicFieldValue["value2"].ToString() }, relationalOperator, logicOperator);
}
else
{
linqFilterExpressionLeft = GetAndLambdaExpression_0<TFields>(new string[] { item.Name }, new string[] { dicFieldValue["value1"].ToString() }, relationalOperator, logicOperator);
}
}
else if ("1" == dicFieldValue["dataType"].ToString())//0 - 字符,1 - 数字,2 - 日期
{
if ("eq" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "=";
}
else if ("neq" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "!=";
}
else if ("greater" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = ">";
}
else if ("less" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "<";
}
else if ("greaterEqual" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = ">=";
}
else if ("lessEqual" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "<=";
}
if (!string.IsNullOrEmpty(dicFieldValue["value2"].ToString()))
{
logicOperator = dicFieldValue["logicOperator"].ToString();
if ("eq" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "=";
}
else if ("neq" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "!=";
}
else if ("greater" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = ">";
}
else if ("less" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "<";
}
else if ("greaterEqual" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = ">=";
}
else if ("lessEqual" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "<=";
}
linqFilterExpressionLeft = GetAndLambdaExpression_1<TFields>(new string[] { item.Name, item.Name }, new string[] { dicFieldValue["value1"].ToString(), dicFieldValue["value2"].ToString() }, relationalOperator, logicOperator);
}
else
{
linqFilterExpressionLeft = GetAndLambdaExpression_1<TFields>(new string[] { item.Name }, new string[] { dicFieldValue["value1"].ToString() }, relationalOperator, logicOperator);
}
}
else if ("2" == dicFieldValue["dataType"].ToString())//0 - 字符,1 - 数字,2 - 日期
{
if ("eq" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "=";
}
else if ("neq" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "!=";
}
else if ("greater" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = ">";
}
else if ("less" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "<";
}
else if ("greaterEqual" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = ">=";
}
else if ("lessEqual" == dicFieldValue["relationalOperator1"].ToString())
{
relationalOperator[0] = "<=";
}
if (!string.IsNullOrEmpty(dicFieldValue["value2"].ToString()))
{
logicOperator = dicFieldValue["logicOperator"].ToString();
if ("eq" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "=";
}
else if ("neq" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "!=";
}
else if ("greater" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = ">";
}
else if ("less" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "<";
}
else if ("greaterEqual" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = ">=";
}
else if ("lessEqual" == dicFieldValue["relationalOperator2"].ToString())
{
relationalOperator[1] = "<=";
}
linqFilterExpressionLeft = GetAndLambdaExpression_2<TFields>(new string[] { item.Name, item.Name }, new string[] { dicFieldValue["value1"].ToString(), dicFieldValue["value2"].ToString() }, relationalOperator, logicOperator);
}
else
{
linqFilterExpressionLeft = GetAndLambdaExpression_2<TFields>(new string[] { item.Name }, new string[] { dicFieldValue["value1"].ToString() }, relationalOperator, logicOperator);
}
}
break;
}
}
return linqFilterExpressionLeft;
}
/// <summary>
/// 遍历对象属性构造查询条件适用于上下文菜单的前两项(按选定内容筛选 ==1,排除当前选定内容==2)
/// </summary>
/// <typeparam name="TFields"></typeparam>
/// <typeparam name="TParaInput"></typeparam>
/// <param name="tableFields"></param>
/// <param name="paraInput"></param>
/// <returns></returns>
public static Expression<Func<TFields, bool>> GetAdvanceQueryCondition2<TFields, TParaInput>(TFields tableFields, TParaInput paraInput)
{
string[] relationalOperator = new string[2];
string logicOperator = "";
Expression<Func<TFields, bool>> linqFilterExpression = null;
Expression<Func<TFields, bool>> linqFilterExpressionLeft = null;
Expression<Func<TFields, bool>> linqFilterExpressionRight = null;
Dictionary<string, object> dicFieldValue = GetInputPara(paraInput);
Type t = tableFields.GetType();
PropertyInfo[] PropertyList = t.GetProperties();
foreach (PropertyInfo item in PropertyList)
{
string name = item.Name;
object value = item.GetValue(tableFields, null);
string usetSelectedFieldName = dicFieldValue["fieldName"].ToString();
if (item.Name == usetSelectedFieldName)
{
if ("0" == dicFieldValue["dataType"].ToString())//0 - 字符,1 - 数字,2 - 日期
{
if ("1" == dicFieldValue["QueryTypContextmenu"].ToString())//按选定内容筛选 ==1
{
relationalOperator[0] = "=";
}
else if ("2" == dicFieldValue["QueryTypContextmenu"].ToString())//排除当前选定内容 ==2
{
relationalOperator[0] = "!=";
}
if (dicFieldValue["fieldNameValue"]==null)
{
linqFilterExpressionLeft = GetAndLambdaExpression_0<TFields>(new string[] { item.Name }, new string[] {"" }, relationalOperator, logicOperator);
}
else
linqFilterExpressionLeft = GetAndLambdaExpression_0<TFields>(new string[] { item.Name }, new string[] { dicFieldValue["fieldNameValue"].ToString()}, relationalOperator, logicOperator);
}
else if ("1" == dicFieldValue["dataType"].ToString())//0 - 字符,1 - 数字,2 - 日期
{
if ("1" == dicFieldValue["QueryTypContextmenu"].ToString())//按选定内容筛选 ==1
{
relationalOperator[0] = "=";
}
else if ("2" == dicFieldValue["QueryTypContextmenu"].ToString())//排除当前选定内容 ==2
{
relationalOperator[0] = "!=";
}
linqFilterExpressionLeft = GetAndLambdaExpression_1<TFields>(new string[] { item.Name }, new string[] { dicFieldValue["fieldNameValue"].ToString() }, relationalOperator, logicOperator);
}
else if ("2" == dicFieldValue["dataType"].ToString())//0 - 字符,1 - 数字,2 - 日期
{
if ("1" == dicFieldValue["QueryTypContextmenu"].ToString())//按选定内容筛选 ==1
{
relationalOperator[0] = "=";
}
else if ("2" == dicFieldValue["QueryTypContextmenu"].ToString())//排除当前选定内容 ==2
{
relationalOperator[0] = "!=";
}
linqFilterExpressionLeft = GetAndLambdaExpression_2<TFields>(new string[] { item.Name }, new string[] { dicFieldValue["fieldNameValue"].ToString() }, relationalOperator, logicOperator);
}
break;
}
}
return linqFilterExpressionLeft;
}
/// <summary>
/// 获取输入参数和值
/// </summary>
/// <typeparam name="TParaInput"></typeparam>
/// <param name="paraInput"></param>
/// <returns></returns>
private static Dictionary<string, object> GetInputPara<TParaInput>(TParaInput paraInput)
{
Dictionary<string, object> dic = new Dictionary<string, object>();
Type t = paraInput.GetType();
PropertyInfo[] PropertyList1 = t.GetProperties();
foreach (PropertyInfo item in PropertyList1)
{
string name = item.Name;
object value = item.GetValue(paraInput, null);
if (item.PropertyType.IsGenericType && item.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// If it is NULLABLE, then get the underlying type. eg if "Nullable<int>" then this will return just "int"
var columnType = item.PropertyType.GetGenericArguments()[0];
}
else
{
//前端传过来的查询字段
if (item.Name == "fieldName")
{
dic.Add(name, value);
}
if (item.Name == "relationalOperator1")
{
dic.Add(name, value);
}
if (item.Name == "relationalOperator2")
{
dic.Add(name, value);
}
if (item.Name == "logicOperator")
{
dic.Add(name, value);
}
if (item.Name == "value1")
{
dic.Add(name, value);
}
if (item.Name == "value2")
{
dic.Add(name, value);
}
if (item.Name == "dataType")
{
dic.Add(name, value);
}
if (item.Name == "QueryTypContextmenu")
{
dic.Add(name, value);
}
if (item.Name == "fieldNameValue")
{
dic.Add(name, value);
}
if (item.Name == "field_cvoucH_IDValue")
{
dic.Add(name, value);
}
Console.WriteLine(item.PropertyType.Name);
}
}
return dic;
}
/// <summary>
/// 0 - 字符条件拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="keys"></param>
/// <param name="values"></param>
/// <param name="methons"></param>
/// <param name="logicOperator"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> GetAndLambdaExpression_0<T>(string[] keys, object[] values, string[]? methons,string? logicOperator)
{
Expression expression_return = Expression.Constant(true);
Type TType = typeof(T);
ParameterExpression expression_param = Expression.Parameter(TType, "p");
Expression temp;
for (int i = 0; i < keys.Length; i++)
{
switch (methons[i])
{
case "=":
temp = Expression.Equal(Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
TType.GetMethod("ToString")),
Expression.Constant(values[i]));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else
expression_return = Expression.And(expression_return, temp);
break;
case "!=":
temp = Expression.NotEqual(Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
TType.GetMethod("ToString")),
Expression.Constant(values[i]));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else
expression_return = Expression.And(expression_return, temp);
break;
case "%":
temp = Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
typeof(string).GetMethod("Contains", new[] { typeof(string) }),
Expression.Constant(values[i], typeof(string)));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else
expression_return = Expression.And(expression_return, temp);
break;
case "in":
string[] strarr = values[i].ToString().Split(',');
Expression or_return = Expression.Constant(false);
for (int k = 0; k < strarr.Length; k++)
{
temp = Expression.Equal(Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
TType.GetMethod("ToString")),
Expression.Constant(strarr[k]));
or_return = Expression.Or(or_return, temp);
}
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, or_return);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, or_return);
}
}
else
expression_return = Expression.And(expression_return, or_return);
break;
}
}
return (Expression<Func<T, bool>>)Expression.Lambda<Func<T, bool>>(expression_return, new ParameterExpression[] { expression_param });
}
/// <summary>
/// 1 - 数字(金额 统一设置成decimal)条件拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="keys"></param>
/// <param name="values"></param>
/// <param name="methons"></param>
/// <param name="logicOperator"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> GetAndLambdaExpression_1<T>(string[] keys, object[] values, string[] methons,string logicOperator)
{
Expression expression_return = Expression.Constant(true);
Type TType = typeof(T);
ParameterExpression expression_param = Expression.Parameter(TType, "p");
Expression temp;
for (int i = 0; i < keys.Length; i++)
{
switch (methons[i])
{
case "=":
temp = Expression.Equal(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDecimal(values[i])));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else expression_return = Expression.And(expression_return, temp);
break;
case "!=":
temp = Expression.NotEqual(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDecimal(values[i])));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else expression_return = Expression.And(expression_return, temp);
break;
case "%":
temp = Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
typeof(string).GetMethod("Contains", new[] { typeof(string) }),
Expression.Constant(values[i], typeof(string)));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else expression_return = Expression.And(expression_return, temp);
break;
case ">":
temp = Expression.GreaterThan(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDecimal(values[i])));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else expression_return = Expression.And(expression_return, temp);
break;
case "<":
temp = Expression.LessThan(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDecimal(values[i])));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else expression_return = Expression.And(expression_return, temp);
break;
case ">=":
temp = Expression.GreaterThanOrEqual(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDecimal(values[i])));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else expression_return = Expression.And(expression_return, temp);
break;
case "<=":
temp = Expression.LessThanOrEqual(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDecimal(values[i])));
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, temp);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, temp);
}
}
else expression_return = Expression.And(expression_return, temp);
break;
case "in":
string[] strarr = values[i].ToString().Split(',');
Expression or_return = Expression.Constant(false);
for (int k = 0; k < strarr.Length; k++)
{
temp = Expression.Equal(Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
TType.GetMethod("ToString")),
Expression.Constant(strarr[k]));
or_return = Expression.Or(or_return, temp);
}
if (!string.IsNullOrEmpty(logicOperator) && i == 1)
{
if ("OR" == logicOperator)
{
expression_return = Expression.Or(expression_return, or_return);
}
else if ("AND" == logicOperator)
{
expression_return = Expression.Add(expression_return, or_return);
}
}
else expression_return = Expression.And(expression_return, or_return);
break;
}
}
return (Expression<Func<T, bool>>)Expression.Lambda<Func<T, bool>>(expression_return, new ParameterExpression[] { expression_param });
}
/// <summary>
/// 2 - 日期条件拼接
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="keys"></param>
/// <param name="values"></param>
/// <param name="methons"></param>
/// <param name="logicOperator"></param>
/// <param name="logicOperator"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> GetAndLambdaExpression_2<T>(string[] keys, object[] values, string[] methons, string logicOperator)
{
Expression expression_return = Expression.Constant(true);
Type TType = typeof(T);
ParameterExpression expression_param = Expression.Parameter(TType, "p");
Expression temp;
for (int i = 0; i < keys.Length; i++)
{
string dt = values[i].ToString();
if (string.IsNullOrEmpty(dt))
{
values[i] = DateTime.MinValue.ToString();
}
switch (methons[i])
{
case "=":
temp = Expression.Equal(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDateTime(values[i])));
expression_return = Expression.And(expression_return, temp);
break;
case "!=":
temp = Expression.NotEqual(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDateTime(values[i])));
expression_return = Expression.And(expression_return, temp);
break;
case ">=":
temp = Expression.GreaterThanOrEqual(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDateTime(values[i])));
expression_return = Expression.And(expression_return, temp);
break;
case "<=":
temp = Expression.LessThanOrEqual(Expression.Property(expression_param, TType.GetProperty(keys[i])), Expression.Constant(Convert.ToDateTime(values[i])));
expression_return = Expression.And(expression_return, temp);
break;
}
}
return (Expression<Func<T, bool>>)Expression.Lambda<Func<T, bool>>(expression_return, new ParameterExpression[] { expression_param });
}
/// <summary>
/// 通过Linq表达式获取成员属性
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="instance"></param>
/// <param name="expression"></param>
/// <returns></returns>
public static Tuple<string, string> GetPropertyValue<T>(T instance, Expression<Func<T, string>> expression)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
string propertyName = memberExpression.Member.Name;
string attributeName = (memberExpression.Member.GetCustomAttributes(false)[0] as DescriptionAttribute).Description;
var property = typeof(T).GetProperties().Where(l => l.Name == propertyName).First();
return new Tuple<string, string>(attributeName, property.GetValue(instance).ToString());
}
//public static Expression<Func<T, bool>> ContainsExp<T>(string propertyName, string contains)
//{
// //first, get the type of your property
// var propertyType = typeof(T).GetProperty(propertyName).PropertyType;
// //no change
// var parameterExp = Expression.Parameter(typeof(T), "type");
// Expression propertyExp = Expression.Property(parameterExp, propertyName);
// //if property's type is int
// if (propertyType == typeof(int))
// {
// //convert your Expression to a nullable double (or nullable decimal),
// //so that you can use SqlFunctions.StringConvert
// propertyExp = Expression.Convert(propertyExp, typeof(double?));
// //get the SqlFunctions.StringConvert method for nullable double
// var stringConvertMethod = typeof(Functions).GetMethod("StringConvert", new[] { typeof(double?) });
// //call StringConvert on your converted expression
// propertyExp = Expression.Call(stringConvertMethod, propertyExp);
// }
// //no change
// var method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
// var someValue = Expression.Constant(contains, typeof(string));
// var containsMethodExp = Expression.Call(propertyExp, method, someValue);
// return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
//}
public static bool IsSameProperty<TSourceA, TSourceB, TPropertyA, TPropertyB>(
Expression<Func<TSourceA, TPropertyA>> expA,
Expression<Func<TSourceB, TPropertyB>> expB)
{
MemberExpression memExpA = expA.Body as MemberExpression;
MemberExpression memExpB = expB.Body as MemberExpression;
if (memExpA == null || memExpB == null)
return false;
PropertyInfo propA = memExpA.Member as PropertyInfo;
PropertyInfo propB = memExpB.Member as PropertyInfo;
if (propA == null || propB == null)
return false;
return propA.Equals(propB);
}
}