forked from github/dataease
feat(数据集): V2 数据集计算字段支持设置参数,跟过滤组件绑定
This commit is contained in:
parent
ca1b268c22
commit
9c4939a20a
1
core/core-frontend/src/assets/svg/caculate.svg
Normal file
1
core/core-frontend/src/assets/svg/caculate.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723085278911" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1923" id="mx_n_1723085278912" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M256 0H153.6v153.6H0v102.4h153.6v153.6h102.4V256h153.6V153.6H256V0zM313.344 637.952L204.8 747.008l-108.544-109.056-72.704 72.704L132.608 819.2 23.552 927.744l72.704 72.704L204.8 891.392l108.544 109.056 72.704-72.704L276.992 819.2l109.056-108.544-72.704-72.704zM614.4 153.6h409.6v102.4h-409.6zM614.4 768h409.6v102.4h-409.6z" p-id="1924"></path><path d="M819.2 972.8m-51.2 0a51.2 51.2 0 1 0 102.4 0 51.2 51.2 0 1 0-102.4 0Z" p-id="1925"></path><path d="M819.2 665.6m-51.2 0a51.2 51.2 0 1 0 102.4 0 51.2 51.2 0 1 0-102.4 0Z" p-id="1926"></path></svg>
|
After Width: | Height: | Size: 904 B |
@ -3,6 +3,7 @@ import { computed } from 'vue'
|
|||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
|
||||||
import _401 from '@/assets/svg/401.svg'
|
import _401 from '@/assets/svg/401.svg'
|
||||||
|
import caculate from '@/assets/svg/caculate.svg'
|
||||||
import _403 from '@/assets/svg/403.svg'
|
import _403 from '@/assets/svg/403.svg'
|
||||||
import APIDs from '@/assets/svg/API-ds.svg'
|
import APIDs from '@/assets/svg/API-ds.svg'
|
||||||
import Apache_Hive from '@/assets/svg/Apache Hive.svg'
|
import Apache_Hive from '@/assets/svg/Apache Hive.svg'
|
||||||
@ -1330,6 +1331,7 @@ const iconMap = {
|
|||||||
'word-cloud-dark': wordCloudDark,
|
'word-cloud-dark': wordCloudDark,
|
||||||
'word-cloud-origin': wordCloudOrigin,
|
'word-cloud-origin': wordCloudOrigin,
|
||||||
'word-cloud': wordCloud,
|
'word-cloud': wordCloud,
|
||||||
|
caculate,
|
||||||
'icon_file-doc_colorful': icon_file_doc_colorful
|
'icon_file-doc_colorful': icon_file_doc_colorful
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, reactive, onMounted, onBeforeUnmount, watch } from 'vue'
|
import { ref, reactive, onMounted, onBeforeUnmount, watch, unref, computed, nextTick } from 'vue'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import CodeMirror from './CodeMirror.vue'
|
import CodeMirror from './CodeMirror.vue'
|
||||||
import { getFunction } from '@/api/dataset'
|
import { getFunction } from '@/api/dataset'
|
||||||
import { fieldType } from '@/utils/attr'
|
import { fieldType } from '@/utils/attr'
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
import { guid } from './util'
|
||||||
export interface CalcFieldType {
|
export interface CalcFieldType {
|
||||||
id?: string
|
id?: string
|
||||||
datasourceId?: string // 数据源id
|
datasourceId?: string // 数据源id
|
||||||
@ -15,6 +16,7 @@ export interface CalcFieldType {
|
|||||||
dataeaseName?: string // 字段别名
|
dataeaseName?: string // 字段别名
|
||||||
groupType: 'd' | 'q' // d=维度,q=指标
|
groupType: 'd' | 'q' // d=维度,q=指标
|
||||||
type: string
|
type: string
|
||||||
|
params?: Array<{ id: string; name: string; value: number }>
|
||||||
checked: boolean
|
checked: boolean
|
||||||
deType: number // 字段类型
|
deType: number // 字段类型
|
||||||
deExtractType?: number // 字段原始类型
|
deExtractType?: number // 字段原始类型
|
||||||
@ -65,6 +67,60 @@ const state = reactive({
|
|||||||
quotaList: [],
|
quotaList: [],
|
||||||
quotaData: []
|
quotaData: []
|
||||||
})
|
})
|
||||||
|
const formQuotaRef = ref()
|
||||||
|
const formQuota = reactive({
|
||||||
|
id: null,
|
||||||
|
name: '',
|
||||||
|
value: null
|
||||||
|
})
|
||||||
|
const dialogFormVisible = ref(false)
|
||||||
|
const formQuotaRules = {
|
||||||
|
name: [
|
||||||
|
{ required: true, message: '请输入参数名称', trigger: 'blur' },
|
||||||
|
{ min: 1, max: 50, message: '请输入1-50个字符', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
value: [{ required: true, message: '请输入参数默认值', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
const formQuotaClose = () => {
|
||||||
|
formQuotaRef.value.resetFields()
|
||||||
|
dialogFormVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const formQuotaConfirm = () => {
|
||||||
|
formQuotaRef.value.validate(val => {
|
||||||
|
if (val) {
|
||||||
|
if (!formQuota.id) {
|
||||||
|
formQuota.id = `params_${guid()}`
|
||||||
|
}
|
||||||
|
const q = cloneDeep(unref(formQuota))
|
||||||
|
fieldForm.params = [q]
|
||||||
|
const i = state.quotaData.find(ele => ele.id === formQuota.id)
|
||||||
|
const j = state.quotaList.find(ele => ele.id === formQuota.id)
|
||||||
|
if (i && j) {
|
||||||
|
const str = mirror.value.state.doc.toString()
|
||||||
|
const name2Auto = []
|
||||||
|
fieldForm.originName = setNameIdTrans('name', 'id', str, name2Auto)
|
||||||
|
Object.assign(i, cloneDeep(unref(formQuota)))
|
||||||
|
Object.assign(j, cloneDeep(unref(formQuota)))
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
mirror.value.dispatch({
|
||||||
|
changes: {
|
||||||
|
from: 0,
|
||||||
|
to: mirror.value.viewState.state.doc.length,
|
||||||
|
insert: setNameIdTrans('id', 'name', fieldForm.originName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
state.quotaData.push(q)
|
||||||
|
state.quotaList.push(q)
|
||||||
|
}
|
||||||
|
formQuotaClose()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const fieldForm = reactive<CalcFieldType>({ ...(defaultForm as CalcFieldType) })
|
const fieldForm = reactive<CalcFieldType>({ ...(defaultForm as CalcFieldType) })
|
||||||
|
|
||||||
@ -98,8 +154,8 @@ let dimensionDataList = []
|
|||||||
const initEdit = (obj, dimensionData, quotaData) => {
|
const initEdit = (obj, dimensionData, quotaData) => {
|
||||||
Object.assign(fieldForm, { ...defaultForm, ...obj })
|
Object.assign(fieldForm, { ...defaultForm, ...obj })
|
||||||
state.dimensionData = dimensionData
|
state.dimensionData = dimensionData
|
||||||
state.quotaData = quotaData
|
state.quotaData = quotaData.concat(fieldForm.params || [])
|
||||||
quotaDataList = cloneDeep(quotaData)
|
quotaDataList = cloneDeep(quotaData.concat(fieldForm.params || []))
|
||||||
dimensionDataList = cloneDeep(dimensionData)
|
dimensionDataList = cloneDeep(dimensionData)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
formField.value.clearValidate()
|
formField.value.clearValidate()
|
||||||
@ -114,12 +170,14 @@ const initEdit = (obj, dimensionData, quotaData) => {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mirror.value.dispatch({
|
nextTick(() => {
|
||||||
changes: {
|
mirror.value.dispatch({
|
||||||
from: 0,
|
changes: {
|
||||||
to: mirror.value.viewState.state.doc.length,
|
from: 0,
|
||||||
insert: setNameIdTrans('id', 'name', obj.originName)
|
to: mirror.value.viewState.state.doc.length,
|
||||||
}
|
insert: setNameIdTrans('id', 'name', obj.originName)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,6 +264,40 @@ defineExpose({
|
|||||||
formField
|
formField
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const addParmasToQuota = () => {
|
||||||
|
if (disableCaParams.value) return
|
||||||
|
if (!fieldForm.params) {
|
||||||
|
fieldForm.params = []
|
||||||
|
}
|
||||||
|
dialogFormVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateParmasToQuota = () => {
|
||||||
|
const [o] = fieldForm.params
|
||||||
|
Object.assign(formQuota, o || {})
|
||||||
|
dialogFormVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const disableCaParams = computed(() => {
|
||||||
|
return !!fieldForm.params?.length
|
||||||
|
})
|
||||||
|
|
||||||
|
const delParmasToQuota = () => {
|
||||||
|
const [o] = fieldForm.params
|
||||||
|
fieldForm.params = []
|
||||||
|
const str = mirror.value.state.doc.toString()
|
||||||
|
const name2Auto = []
|
||||||
|
fieldForm.originName = setNameIdTrans('name', 'id', str, name2Auto).replaceAll(`[${o.id}]`, '')
|
||||||
|
state.quotaData = state.quotaData.filter(ele => ele.id !== o.id)
|
||||||
|
state.quotaList = state.quotaList.filter(ele => ele.id !== o.id)
|
||||||
|
mirror.value.dispatch({
|
||||||
|
changes: {
|
||||||
|
from: 0,
|
||||||
|
to: mirror.value.viewState.state.doc.length,
|
||||||
|
insert: setNameIdTrans('id', 'name', fieldForm.originName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
initFunction()
|
initFunction()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -358,7 +450,21 @@ initFunction()
|
|||||||
<div v-else class="class-na">{{ t('dataset.na') }}</div>
|
<div v-else class="class-na">{{ t('dataset.na') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-height">
|
<div class="field-height">
|
||||||
<span>{{ t('chart.quota') }}</span>
|
<div style="display: flex; align-items: center; justify-content: space-between">
|
||||||
|
<span>{{ t('chart.quota') }}</span>
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
:content="disableCaParams ? '仅支持添加一个计算参数。' : '添加计算参数'"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<el-icon class="hover-icon_quota" @click="addParmasToQuota">
|
||||||
|
<Icon
|
||||||
|
:class="[`field-icon-${fieldType[0]}`, disableCaParams && 'not-allow']"
|
||||||
|
name="caculate"
|
||||||
|
></Icon>
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
<div v-if="state.quotaData.length" class="field-list">
|
<div v-if="state.quotaData.length" class="field-list">
|
||||||
<span
|
<span
|
||||||
v-for="item in state.quotaData"
|
v-for="item in state.quotaData"
|
||||||
@ -367,13 +473,24 @@ initFunction()
|
|||||||
:title="item.name"
|
:title="item.name"
|
||||||
@click="insertFieldToCodeMirror('[' + item.name + ']')"
|
@click="insertFieldToCodeMirror('[' + item.name + ']')"
|
||||||
>
|
>
|
||||||
<el-icon>
|
<el-icon v-if="!item.groupType">
|
||||||
|
<Icon name="caculate"></Icon>
|
||||||
|
</el-icon>
|
||||||
|
<el-icon v-else>
|
||||||
<Icon
|
<Icon
|
||||||
:name="`field_${fieldType[item.deType]}`"
|
:name="`field_${fieldType[item.deType]}`"
|
||||||
:className="`field-icon-${fieldType[item.deType]}`"
|
:className="`field-icon-${fieldType[item.deType]}`"
|
||||||
></Icon>
|
></Icon>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
|
<div v-if="!item.groupType" class="icon-right">
|
||||||
|
<el-icon @click.stop="updateParmasToQuota" class="hover-icon">
|
||||||
|
<Icon name="icon_edit_outlined"></Icon>
|
||||||
|
</el-icon>
|
||||||
|
<el-icon @click.stop="delParmasToQuota" class="hover-icon">
|
||||||
|
<Icon name="icon_delete-trash_outlined"></Icon>
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="class-na">{{ t('dataset.na') }}</div>
|
<div v-else class="class-na">{{ t('dataset.na') }}</div>
|
||||||
@ -440,6 +557,32 @@ initFunction()
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<el-dialog
|
||||||
|
:before-close="formQuotaClose"
|
||||||
|
v-model="dialogFormVisible"
|
||||||
|
title="添加计算参数"
|
||||||
|
width="500"
|
||||||
|
>
|
||||||
|
<el-form label-position="top" ref="formQuotaRef" :model="formQuota" :rules="formQuotaRules">
|
||||||
|
<el-form-item label="参数名称" prop="name">
|
||||||
|
<el-input style="width: 100%" v-model="formQuota.name" placeholder="请输入1-50个字符" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="参数默认值" prop="value">
|
||||||
|
<el-input-number
|
||||||
|
style="width: 100%"
|
||||||
|
v-model="formQuota.value"
|
||||||
|
placeholder="请输入一个数字"
|
||||||
|
controls-position="right"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="formQuotaClose">取消</el-button>
|
||||||
|
<el-button type="primary" @click="formQuotaConfirm"> 确认 </el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -537,6 +680,30 @@ initFunction()
|
|||||||
& > :nth-child(1) {
|
& > :nth-child(1) {
|
||||||
color: #1f2329;
|
color: #1f2329;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover-icon_quota {
|
||||||
|
cursor: pointer;
|
||||||
|
height: 20px !important;
|
||||||
|
width: 20px !important;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
&[aria-expanded='true'] {
|
||||||
|
background: rgba(31, 35, 41, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(31, 35, 41, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: rgba(31, 35, 41, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.not-allow {
|
||||||
|
cursor: not-allowed;
|
||||||
|
color: #bbbfc4 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.item-dimension,
|
.item-dimension,
|
||||||
.item-quota {
|
.item-quota {
|
||||||
@ -553,6 +720,15 @@ initFunction()
|
|||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
||||||
|
.icon-right {
|
||||||
|
display: none;
|
||||||
|
margin-left: auto;
|
||||||
|
align-items: center;
|
||||||
|
.ed-icon {
|
||||||
|
margin: 0 0 0 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-dimension:hover {
|
.item-dimension:hover {
|
||||||
@ -571,6 +747,9 @@ initFunction()
|
|||||||
background: rgba(4, 180, 156, 0.1);
|
background: rgba(4, 180, 156, 0.1);
|
||||||
border-color: #04b49c;
|
border-color: #04b49c;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
.icon-right {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.function-style {
|
.function-style {
|
||||||
|
@ -1462,7 +1462,7 @@ const getDsIconName = data => {
|
|||||||
:itemSize="40"
|
:itemSize="40"
|
||||||
:data="datasourceTableData"
|
:data="datasourceTableData"
|
||||||
:total="datasourceTableData.length"
|
:total="datasourceTableData.length"
|
||||||
:width="LeftWidth - 7"
|
:width="LeftWidth - 17"
|
||||||
:height="height - 305"
|
:height="height - 305"
|
||||||
:scrollbarAlwaysOn="false"
|
:scrollbarAlwaysOn="false"
|
||||||
class-name="el-select-dropdown__list"
|
class-name="el-select-dropdown__list"
|
||||||
|
Loading…
Reference in New Issue
Block a user