|
@@ -0,0 +1,370 @@
|
|
|
+<template>
|
|
|
+ <div class="AdvancedQuery">
|
|
|
+ <div class="AdvancedQuery_from">
|
|
|
+ <el-form ref="paramsForm" class="query-params" :model="paramsForm" :rules="paramsForm.validateRules">
|
|
|
+ <el-row class="query-params-wrapper">
|
|
|
+ <el-col v-for="(row, rowIndex) in paramsForm.params" class="query-params-wrapper-list flex-wrap" :key="rowIndex" :span="24">
|
|
|
+ <el-form-item v-for="(col, colIndex) in paramsTableCols" :key="colIndex" :prop="'params.' + rowIndex + '.' + col.prop" :rules="paramsForm.validateRules[col.prop]">
|
|
|
+ <template v-if="
|
|
|
+ col.prop === 'comparisonOperator' ||
|
|
|
+ col.inputType[rowIndex] === 'select'
|
|
|
+ ">
|
|
|
+ <el-select style="width: 120px;" v-model="row[col.prop]" placeholder="请选择" @change="
|
|
|
+ value => {
|
|
|
+ selectChangeHandler(value, rowIndex, colIndex)
|
|
|
+ }
|
|
|
+ ">
|
|
|
+ <el-option v-for="(option, i) in col.options[rowIndex]" :key="i" :value="option.value" :label="option.label" />
|
|
|
+ </el-select>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="col.inputType === 'select'">
|
|
|
+ <el-select v-model="row[col.prop]" placeholder="请选择" @change="
|
|
|
+ value => {
|
|
|
+ selectChangeHandler(value, rowIndex, colIndex)
|
|
|
+ }
|
|
|
+ ">
|
|
|
+ <el-option v-for="(option, i) in col.options" :key="i" :value="option.value" :label="option.label" />
|
|
|
+ </el-select>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="
|
|
|
+ ['varchar', 'text', 'longtext'].includes(
|
|
|
+ col.inputType[rowIndex]
|
|
|
+ )
|
|
|
+ ">
|
|
|
+ <el-input v-model="row[col.prop]" placeholder="请输入" :disabled="
|
|
|
+ col.prop === 'paramValue' && paramsForm.disabled[rowIndex]
|
|
|
+ " />
|
|
|
+ </template>
|
|
|
+ <template v-else-if="col.inputType[rowIndex] === 'number'">
|
|
|
+ <el-input v-model="row[col.prop]" placeholder="请输入" :disabled="
|
|
|
+ col.prop === 'paramValue' && paramsForm.disabled[rowIndex]
|
|
|
+ " @keydown.native="inputHold(row[col.prop])" @input="inputLimit(row[col.prop], rowIndex)" @blur="inputFix(row[col.prop], rowIndex)" />
|
|
|
+ </template>
|
|
|
+ <template v-else-if="col.inputType[rowIndex] === 'date'">
|
|
|
+ <el-date-picker v-model="row[col.prop]" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" placeholder="请选择" :clearable="false" />
|
|
|
+ </template>
|
|
|
+ <template v-else-if="col.inputType[rowIndex] === 'datetime'">
|
|
|
+ <el-date-picker v-model="row[col.prop]" type="datetime" format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择" :clearable="false" />
|
|
|
+ </template>
|
|
|
+ <template v-else-if="col.inputType === 'delete'">
|
|
|
+ <i class="clickable-delete el-icon-error" @click="deleteParam(rowIndex)" />
|
|
|
+ </template>
|
|
|
+ <template v-else-if="col.inputType === 'connector'">
|
|
|
+ <div v-if="row.connector" class="clickable-toggle" @click="toggle(rowIndex)">
|
|
|
+ {{ row.connector === 'and' ? '并且' : '或者' }}
|
|
|
+ </div>
|
|
|
+ <div v-else class="clickable-add" @click="addParamsHandler">
|
|
|
+ <span class="el-icon-circle-plus-outline"></span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ <div class="AdvancedQuery_list"></div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { parseTime } from '@/utils/index'
|
|
|
+const comparisonOperatorOptions = [
|
|
|
+ {
|
|
|
+ label: '小于等于',
|
|
|
+ value: '<=',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '大于等于',
|
|
|
+ value: '>=',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '小于',
|
|
|
+ value: '<',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '大于',
|
|
|
+ value: '>',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '等于',
|
|
|
+ value: '=',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '不等于',
|
|
|
+ value: '!=',
|
|
|
+ },
|
|
|
+ // {
|
|
|
+ // label: '为空',
|
|
|
+ // value: 'is Null',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // label: '不为空',
|
|
|
+ // value: 'is not Null',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // label: '包含',
|
|
|
+ // value: 'like',
|
|
|
+ // },
|
|
|
+]
|
|
|
+export default {
|
|
|
+ name: 'AdvancedQueryForm',
|
|
|
+ data () {
|
|
|
+ return {
|
|
|
+ queryContent: [],
|
|
|
+ flightDate: new Array(2).fill(parseTime(new Date(), '{y}-{m}-{d}')),
|
|
|
+ paramsForm: {
|
|
|
+ params: [],
|
|
|
+ validateRules: {
|
|
|
+ paramKey: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请选择项',
|
|
|
+ trigger: ['change', 'blur'],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ paramValue: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '请选择或输入值',
|
|
|
+ trigger: ['change', 'blur'],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ disabled: [],
|
|
|
+ },
|
|
|
+ checkValue: '',
|
|
|
+ paramsTableCols: [
|
|
|
+ {
|
|
|
+ prop: 'paramKey',
|
|
|
+ // label: '项',
|
|
|
+ inputType: 'select',
|
|
|
+ options: [],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'comparisonOperator',
|
|
|
+ // label: '比较符',
|
|
|
+ inputType: 'select',
|
|
|
+ options: new Array(2).fill(
|
|
|
+ comparisonOperatorOptions.slice(0, 5).reverse()
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'paramValue',
|
|
|
+ // label: '值',
|
|
|
+ inputType: [],
|
|
|
+ options: [],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'delete',
|
|
|
+ inputType: 'delete',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'connector',
|
|
|
+ // label: '连接',
|
|
|
+ inputType: 'connector',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ columnSet: {},
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted () {
|
|
|
+ this.addParamsHandler()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ advancedQueryHandler () {
|
|
|
+ try {
|
|
|
+ this.$refs['paramsForm'].validate(valid => {
|
|
|
+ if (!valid) {
|
|
|
+ throw new Error()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const queryContent = []
|
|
|
+ const params = this.paramsForm.params
|
|
|
+ const len = params.length
|
|
|
+ for (let i = 0; i < len; i++) {
|
|
|
+ const prev = params[i - 1]
|
|
|
+ const current = params[i]
|
|
|
+ const next = params[i + 1]
|
|
|
+ const value = ['is Null', 'is not Null'].includes(
|
|
|
+ current.comparisonOperator
|
|
|
+ )
|
|
|
+ ? ''
|
|
|
+ : current.paramValue
|
|
|
+ const obj = {
|
|
|
+ column: current.paramKey,
|
|
|
+ comparator: current.comparisonOperator,
|
|
|
+ value,
|
|
|
+ connector: current.connector,
|
|
|
+ }
|
|
|
+ if (
|
|
|
+ !prev ||
|
|
|
+ prev.connector === 'and' ||
|
|
|
+ (prev.paramKey && prev.paramKey !== current.paramKey)
|
|
|
+ ) {
|
|
|
+ obj.left = '('
|
|
|
+ } else {
|
|
|
+ obj.left = ''
|
|
|
+ }
|
|
|
+ if (
|
|
|
+ !next ||
|
|
|
+ current.connector === 'and' ||
|
|
|
+ (next.paramKey && next.paramKey !== current.paramKey)
|
|
|
+ ) {
|
|
|
+ obj.right = ')'
|
|
|
+ } else {
|
|
|
+ obj.right = ''
|
|
|
+ }
|
|
|
+ queryContent.push(obj)
|
|
|
+ }
|
|
|
+ this.queryContent = queryContent
|
|
|
+ this.sendColData()
|
|
|
+ } catch (error) {
|
|
|
+ error.message && this.$message.error(error.message)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ sendColData () {
|
|
|
+ this.$emit('getAdvancedQueryData', this.queryContent)
|
|
|
+ },
|
|
|
+ addParamsHandler () {
|
|
|
+ this.paramsTableCols[2].inputType.push('text')
|
|
|
+ this.paramsForm.params.push({
|
|
|
+ paramKey: '',
|
|
|
+ comparisonOperator: '',
|
|
|
+ paramValue: '',
|
|
|
+ connector: '',
|
|
|
+ })
|
|
|
+ },
|
|
|
+ selectChangeHandler (value, rowIndex, colIndex) {
|
|
|
+ if (colIndex === 0) {
|
|
|
+ // const datas = this.tableColMunt.filter(item => item.columnName == value)
|
|
|
+ const { dataType, options } = this.columnSet[value]
|
|
|
+ // const { dataType, options } = datas[0]
|
|
|
+ // 下拉框发生改变清空之前的数据
|
|
|
+ this.paramsForm.params[rowIndex].paramValue = ''
|
|
|
+ if (dataType === 'date') {
|
|
|
+ this.paramsTableCols[1].options[rowIndex] = comparisonOperatorOptions
|
|
|
+ .slice(0, 5)
|
|
|
+ .reverse()
|
|
|
+ this.paramsTableCols[2].inputType[rowIndex] = 'date'
|
|
|
+ } else if (dataType === 'datetime') {
|
|
|
+ this.paramsTableCols[1].options[rowIndex] = comparisonOperatorOptions
|
|
|
+ .slice(0, 5)
|
|
|
+ .reverse()
|
|
|
+ this.paramsTableCols[2].inputType[rowIndex] = 'datetime'
|
|
|
+ } else if (options) {
|
|
|
+ this.paramsTableCols[1].options[rowIndex] =
|
|
|
+ comparisonOperatorOptions.slice(4, 5)
|
|
|
+ this.paramsTableCols[2].inputType[rowIndex] = 'select'
|
|
|
+ this.paramsTableCols[2].options[rowIndex] = options
|
|
|
+ this.paramsForm.params[rowIndex].paramValue = ''
|
|
|
+ } else if (dataType === 'number') {
|
|
|
+ this.paramsTableCols[1].options[rowIndex] = comparisonOperatorOptions
|
|
|
+ .slice(0, 5)
|
|
|
+ .reverse()
|
|
|
+ this.paramsTableCols[2].inputType[rowIndex] = 'number'
|
|
|
+ this.paramsForm.params[rowIndex].paramValue = ''
|
|
|
+ } else {
|
|
|
+ this.paramsTableCols[1].options[rowIndex] =
|
|
|
+ comparisonOperatorOptions.slice(4)
|
|
|
+ this.paramsTableCols[2].inputType[rowIndex] = 'text'
|
|
|
+ }
|
|
|
+ this.paramsForm.params[rowIndex].comparisonOperator =
|
|
|
+ this.paramsTableCols[1].options[rowIndex][0].value
|
|
|
+ } else if (colIndex === 1) {
|
|
|
+ if (['is Null', 'is not Null'].includes(value)) {
|
|
|
+ this.paramsForm.params[rowIndex].paramValue = ' '
|
|
|
+ this.paramsForm.disabled[rowIndex] = true
|
|
|
+ } else {
|
|
|
+ this.paramsForm.disabled[rowIndex] = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ inputHold (value) {
|
|
|
+ this.checkValue = value
|
|
|
+ },
|
|
|
+ inputLimit (value, rowIndex) {
|
|
|
+ if (!/^[\-|\+]?((([1-9][0-9]*)|0)(\.[0-9]{0,2})?)?$/.test(value)) {
|
|
|
+ this.paramsForm.params[rowIndex].paramValue = this.checkValue
|
|
|
+ }
|
|
|
+ },
|
|
|
+ inputFix (value, rowIndex) {
|
|
|
+ if (value?.at(-1) === '.') {
|
|
|
+ this.paramsForm.params[rowIndex].paramValue = value.slice(0, -1)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ deleteParam (rowIndex) {
|
|
|
+ this.paramsTableCols[2].inputType.splice(rowIndex, 1)
|
|
|
+ this.paramsForm.params.splice(rowIndex, 1)
|
|
|
+ this.paramsForm.disabled.splice(rowIndex, 1)
|
|
|
+ },
|
|
|
+ toggle (rowIndex) {
|
|
|
+ const { connector } = this.paramsForm.params[rowIndex]
|
|
|
+ this.paramsForm.params[rowIndex].connector =
|
|
|
+ connector === 'and' ? 'or' : 'and'
|
|
|
+ },
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.AdvancedQuery {
|
|
|
+ height: 100%;
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
+ &_from {
|
|
|
+ height: 65%;
|
|
|
+ }
|
|
|
+ .query-params-wrapper-list {
|
|
|
+ .el-form-item {
|
|
|
+ margin-right: 10px;
|
|
|
+ &:nth-child(3) {
|
|
|
+ margin-right: 0;
|
|
|
+ }
|
|
|
+ &:last-child {
|
|
|
+ margin-right: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .clickable-delete {
|
|
|
+ width: 39px;
|
|
|
+ height: 40px;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 40px;
|
|
|
+ font-size: 20px;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-left: none;
|
|
|
+ border-top-left-radius: 0;
|
|
|
+ border-bottom-left-radius: 0;
|
|
|
+ border-radius: 2px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .clickable-toggle {
|
|
|
+ font-size: 14px;
|
|
|
+ font-family: Microsoft YaHei;
|
|
|
+ text-decoration: underline;
|
|
|
+ color: #409eff;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .clickable-add {
|
|
|
+ height: 40px;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 20px;
|
|
|
+ cursor: pointer;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ .clickable-wrapper {
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ line-height: 28px;
|
|
|
+ border-radius: 50%;
|
|
|
+ border: 1px solid #409eff;
|
|
|
+ color: #409eff;
|
|
|
+ }
|
|
|
+ &:hover .clickable-wrapper {
|
|
|
+ background-color: #409eff;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|