mirror of
https://gitee.com/devlive-community/datacap.git
synced 2024-11-30 19:17:46 +08:00
[Core] [Visual] Set to dialog
This commit is contained in:
parent
00641f2749
commit
8b81125e68
@ -83,6 +83,7 @@ export default {
|
||||
visualConfigureDataBreakpointContinuous: 'Continuous',
|
||||
visualConfigureDataBreakpointZero: 'Zero',
|
||||
visualConfigureDataBreakpointIgnore: 'Ignore',
|
||||
visualConfigureGeneralGroup: 'General Configure',
|
||||
columnExpressionMax: 'Maximum',
|
||||
columnExpressionMin: 'Minimum',
|
||||
columnExpressionSum: 'Sum',
|
||||
|
@ -83,6 +83,7 @@ export default {
|
||||
visualConfigureDataBreakpointContinuous: '连续',
|
||||
visualConfigureDataBreakpointZero: '补 0',
|
||||
visualConfigureDataBreakpointIgnore: '忽略',
|
||||
visualConfigureGeneralGroup: '通用配置',
|
||||
columnExpressionMax: '最大值',
|
||||
columnExpressionMin: '最小值',
|
||||
columnExpressionSum: '总和',
|
||||
|
@ -4,8 +4,7 @@
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle class="border-b -mt-4 pb-2">SQL</AlertDialogTitle>
|
||||
</AlertDialogHeader>
|
||||
<VAceEditor v-if="configure" lang="mysql" :theme="configure.theme" :style="{height: '200px', fontSize: configure.fontSize + 'px'}" :value="localContent"
|
||||
:options="editorOptions"/>
|
||||
<AceEditor :value="content as string" read-only/>
|
||||
<AlertDialogFooter class="-mb-4 border-t pt-2">
|
||||
<Button @click="handlerCancel">{{ $t('common.cancel') }}</Button>
|
||||
</AlertDialogFooter>
|
||||
@ -26,18 +25,15 @@ import {
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger
|
||||
} from '@/components/ui/alert-dialog'
|
||||
import CommonUtils from '@/views/components/echarts/utils/CommonUtils'
|
||||
import { UserEditor } from '@/model/user'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { VAceEditor } from 'vue3-ace-editor'
|
||||
import '@/ace-editor-theme'
|
||||
import AceEditor from '@/views/components/editor/AceEditor.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SqlInfo',
|
||||
components: {
|
||||
AceEditor,
|
||||
Button,
|
||||
AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger,
|
||||
VAceEditor
|
||||
AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger
|
||||
},
|
||||
props: {
|
||||
isVisible: {
|
||||
@ -48,25 +44,7 @@ export default defineComponent({
|
||||
type: String as PropType<string | null>
|
||||
}
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
localContent: this.content as string,
|
||||
configure: null as UserEditor | null,
|
||||
editorOptions: {readOnly: true}
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
const localEditorConfigure = localStorage.getItem(CommonUtils.userEditorConfigure)
|
||||
const defaultEditorConfigure: UserEditor = {fontSize: 12, theme: 'chrome'}
|
||||
this.configure = localEditorConfigure ? JSON.parse(localEditorConfigure) : defaultEditorConfigure
|
||||
},
|
||||
handlerCancel()
|
||||
{
|
||||
this.visible = false
|
||||
|
@ -36,6 +36,12 @@ export interface IChart
|
||||
endAngle?: number[]
|
||||
}
|
||||
|
||||
export interface ChartFieldGroup
|
||||
{
|
||||
label?: string
|
||||
fields?: ChartField[]
|
||||
}
|
||||
|
||||
export interface ChartField
|
||||
{
|
||||
label?: string
|
||||
|
@ -169,13 +169,15 @@
|
||||
<Card body-class="p-2">
|
||||
<template #title>{{ $t('dataset.common.visualConfigure') }}</template>
|
||||
<CircularLoading v-if="loading" :show="loading"/>
|
||||
<div v-else-if="configuration">
|
||||
<div v-else-if="configuration" class="flex items-center justify-center">
|
||||
<Alert v-if="configuration.type === Type.TABLE" :title="$t('dataset.common.visualConfigureNotSpecified')"/>
|
||||
<VisualConfigure v-else :configuration="configuration" :fields="forwardFiled(configuration.type)" @change="configuration.chartConfigure = $event"/>
|
||||
<Button v-else size="sm" class="w-[80%]" @click="configureVisible = true">{{ $t('common.configure') }}</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<VisualConfigure v-if="configureVisible && configuration" :is-visible="configureVisible" :configuration="configuration" :field-group="forwardFiled(configuration.type)"
|
||||
@close="configureVisible = $event" @change="configuration.chartConfigure = $event"/>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Type } from '@/views/components/visual/Type'
|
||||
@ -183,7 +185,7 @@ import VisualWordCloud from '@/views/components/visual/components/VisualWordClou
|
||||
import VisualHistogram from '@/views/components/visual/components/VisualHistogram.vue'
|
||||
import VisualPie from '@/views/components/visual/components/VisualPie.vue'
|
||||
import VisualArea from '@/views/components/visual/components/VisualArea.vue'
|
||||
import { ChartField, Configuration } from './Configuration'
|
||||
import { ChartField, ChartFieldGroup, Configuration } from './Configuration'
|
||||
import VisualBar from '@/views/components/visual/components/VisualBar.vue'
|
||||
import VisualLine from '@/views/components/visual/components/VisualLine.vue'
|
||||
import VisualTable from '@/views/components/visual/components/VisualTable.vue'
|
||||
@ -200,6 +202,7 @@ import VisualConfigure from '@/views/components/visual/components/VisualConfigur
|
||||
import VisualRadar from '@/views/components/visual/components/VisualRadar.vue'
|
||||
import VisualFunnel from '@/views/components/visual/components/VisualFunnel.vue'
|
||||
import VisualGauge from '@/views/components/visual/components/VisualGauge.vue'
|
||||
import Button from '@/views/ui/button'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VisualEditor',
|
||||
@ -210,11 +213,7 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
components: {
|
||||
VisualGauge,
|
||||
VisualFunnel,
|
||||
VisualRadar,
|
||||
VisualConfigure,
|
||||
VisualScatter,
|
||||
VisualGauge, VisualFunnel, VisualRadar, VisualConfigure, VisualScatter,
|
||||
Card,
|
||||
Tooltip,
|
||||
RadioGroup, RadioGroupItem,
|
||||
@ -222,6 +221,7 @@ export default defineComponent({
|
||||
Table,
|
||||
CircularLoading,
|
||||
Alert,
|
||||
Button,
|
||||
VisualWordCloud, VisualHistogram, VisualPie, VisualArea, VisualBar, VisualLine, VisualTable
|
||||
},
|
||||
props: {
|
||||
@ -233,14 +233,20 @@ export default defineComponent({
|
||||
type: Object as PropType<Configuration | null>
|
||||
}
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
configureVisible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlerCommit(value: any)
|
||||
{
|
||||
this.$emit('commitOptions', value)
|
||||
},
|
||||
forwardFiled(type: Type): ChartField[]
|
||||
forwardFiled(type: Type): ChartFieldGroup[]
|
||||
{
|
||||
const fields: Array<ChartField> = new Array<ChartField>()
|
||||
const fieldGroups: Array<ChartFieldGroup> = new Array<ChartFieldGroup>()
|
||||
const categoryField: ChartField = { label: this.$t('dataset.common.visualConfigureCategoryField'), field: 'xAxis' }
|
||||
const valueField: ChartField = { label: this.$t('dataset.common.visualConfigureValueField'), field: 'yAxis' }
|
||||
const seriesField: ChartField = { label: this.$t('dataset.common.visualConfigureSeriesField'), field: 'series' }
|
||||
@ -261,33 +267,43 @@ export default defineComponent({
|
||||
}
|
||||
const leftField: ChartField = { label: this.$t('dataset.common.visualConfigureCategoryLeftField'), field: 'leftField' }
|
||||
const rightField: ChartField = { label: this.$t('dataset.common.visualConfigureCategoryRightField'), field: 'rightField' }
|
||||
switch (type) {
|
||||
case Type.RADAR:
|
||||
case Type.BAR:
|
||||
case Type.AREA:
|
||||
case Type.SCATTER:
|
||||
fields.push(categoryField, valueField)
|
||||
break
|
||||
case Type.FUNNEL:
|
||||
fields.push(categoryField, valueField, showLegend)
|
||||
break
|
||||
case Type.GAUGE:
|
||||
fields.push(categoryField, valueField, outerRadius, innerRadius, startAngle, endAngle)
|
||||
break
|
||||
case Type.PIE:
|
||||
fields.push(categoryField, valueField, outerRadius)
|
||||
break
|
||||
case Type.LINE:
|
||||
fields.push(categoryField, valueField, seriesField, dataBreakpoint)
|
||||
break
|
||||
case Type.HISTOGRAM:
|
||||
fields.push(leftField, rightField, valueField)
|
||||
break
|
||||
case Type.WORDCLOUD:
|
||||
fields.push(categoryField, valueField, seriesField)
|
||||
break
|
||||
|
||||
if (type === Type.AREA || type === Type.BAR || type === Type.RADAR || type === Type.SCATTER) {
|
||||
const fields: Array<ChartField> = [categoryField, valueField]
|
||||
const generalField: ChartFieldGroup = { label: this.$t('dataset.common.visualConfigureGeneralGroup'), fields: fields }
|
||||
fieldGroups.push(generalField)
|
||||
}
|
||||
return fields
|
||||
else if (type === Type.FUNNEL) {
|
||||
const fields: Array<ChartField> = [categoryField, valueField, showLegend]
|
||||
const generalField: ChartFieldGroup = { label: this.$t('dataset.common.visualConfigureGeneralGroup'), fields: fields }
|
||||
fieldGroups.push(generalField)
|
||||
}
|
||||
else if (type === Type.GAUGE) {
|
||||
const fields: Array<ChartField> = [categoryField, valueField, outerRadius, innerRadius, startAngle, endAngle]
|
||||
const generalField: ChartFieldGroup = { label: this.$t('dataset.common.visualConfigureGeneralGroup'), fields: fields }
|
||||
fieldGroups.push(generalField)
|
||||
}
|
||||
else if (type === Type.PIE) {
|
||||
const fields: Array<ChartField> = [categoryField, valueField, outerRadius]
|
||||
const generalField: ChartFieldGroup = { label: this.$t('dataset.common.visualConfigureGeneralGroup'), fields: fields }
|
||||
fieldGroups.push(generalField)
|
||||
}
|
||||
else if (type === Type.LINE) {
|
||||
const fields: Array<ChartField> = [categoryField, valueField, seriesField, dataBreakpoint]
|
||||
const generalField: ChartFieldGroup = { label: this.$t('dataset.common.visualConfigureGeneralGroup'), fields: fields }
|
||||
fieldGroups.push(generalField)
|
||||
}
|
||||
else if (type === Type.HISTOGRAM) {
|
||||
const fields: Array<ChartField> = [leftField, rightField, valueField]
|
||||
const generalField: ChartFieldGroup = { label: this.$t('dataset.common.visualConfigureGeneralGroup'), fields: fields }
|
||||
fieldGroups.push(generalField)
|
||||
}
|
||||
else if (type === Type.WORDCLOUD) {
|
||||
const fields: Array<ChartField> = [categoryField, valueField, seriesField]
|
||||
const generalField: ChartFieldGroup = { label: this.$t('dataset.common.visualConfigureGeneralGroup'), fields: fields }
|
||||
fieldGroups.push(generalField)
|
||||
}
|
||||
return fieldGroups
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -1,67 +1,103 @@
|
||||
<template>
|
||||
<div v-if="configuration && formState" class="space-y-2">
|
||||
<FormField v-for="item in fields" :name="item.field as string">
|
||||
<FormItem>
|
||||
<FormLabel>{{ item.label }}</FormLabel>
|
||||
<FormControl>
|
||||
<Switch v-if="item.type === 'SWITCH'" class="ml-2" :default-checked="formState[item.field as keyof IChart] as any"
|
||||
@update:checked="formState[item.field as keyof IChart] = $event as any"/>
|
||||
<Tooltip v-else-if="item.type === 'SLIDER'" :content="formState[item.field as keyof IChart] ? formState[item.field as keyof IChart] : [item.value] as any">
|
||||
<Slider v-model="formState[item.field as keyof IChart] as any" class="ml-2 w-[95%]" :default-value="[item.value]" :min="item.min" :max="item.max" :step="item.step"
|
||||
@update:modelValue="formState[item.field as keyof IChart] = $event as any"/>
|
||||
</Tooltip>
|
||||
<Select v-else v-model="formState[item.field as keyof IChart] as string" :disabled="configuration.headers.length === 0">
|
||||
<SelectTrigger class="w-full">
|
||||
<SelectValue :placeholder="`Select ${item.label}`"/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-if="item.values" class="cursor-pointer" v-for="data in item.values" :value="data.value as string">{{ data.label }}</SelectItem>
|
||||
<SelectItem v-else v-for="item in configuration.headers" class="cursor-pointer" :value="item as string">{{ item }}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</div>
|
||||
<Dialog :is-visible="visible" :title="$t('common.configure')" width="40%" @close="handlerCancel">
|
||||
<div v-if="configuration && formState" class="space-y-2 pl-3 pr-3">
|
||||
<Tabs v-model="activeGroup">
|
||||
<TabsList class="grid w-full grid-cols-2">
|
||||
<TabsTrigger v-for="group in fieldGroup" :key="group.label" :value="group.label as string">{{ group.label }}</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent :value="activeGroup as any" class="grid grid-cols-3 gap-4">
|
||||
<FormField v-for="item in fieldGroup.find(value => value.label === activeGroup)?.fields" :name="item.field as string">
|
||||
<FormItem>
|
||||
<FormLabel>{{ item.label }}</FormLabel>
|
||||
<FormControl>
|
||||
<Switch v-if="item.type === 'SWITCH'" class="ml-2" :default-checked="formState[item.field as keyof IChart] as any"
|
||||
@update:checked="formState[item.field as keyof IChart] = $event as any"/>
|
||||
<Tooltip v-else-if="item.type === 'SLIDER'" :content="formState[item.field as keyof IChart] ? formState[item.field as keyof IChart] : [item.value] as any">
|
||||
<Slider v-model="formState[item.field as keyof IChart] as any" class="ml-2 w-[95%]" :default-value="[item.value]" :min="item.min" :max="item.max"
|
||||
:step="item.step"
|
||||
@update:modelValue="formState[item.field as keyof IChart] = $event as any"/>
|
||||
</Tooltip>
|
||||
<Select v-else v-model="formState[item.field as keyof IChart] as string" :disabled="configuration.headers.length === 0">
|
||||
<SelectTrigger class="w-full">
|
||||
<SelectValue :placeholder="`Select ${item.label}`"/>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-if="item.values" class="cursor-pointer" v-for="data in item.values" :value="data.value as string">{{ data.label }}</SelectItem>
|
||||
<SelectItem v-else v-for="item in configuration.headers" class="cursor-pointer" :value="item as string">{{ item }}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="space-x-5">
|
||||
<Button variant="outline" size="sm" @click="handlerCancel">
|
||||
{{ $t('common.cancel') }}
|
||||
</Button>
|
||||
<Button size="sm" @click="handlerSubmit">
|
||||
{{ $t('common.apply') }}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel } from '@/components/ui/form'
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@/components/ui/select'
|
||||
import { ChartField, Configuration, IChart } from '@/views/components/visual/Configuration.ts'
|
||||
import { ChartFieldGroup, Configuration, IChart } from '@/views/components/visual/Configuration.ts'
|
||||
import { cloneDeep, keys } from 'lodash'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { Slider } from '@/components/ui/slider'
|
||||
import Tooltip from '@/views/ui/tooltip'
|
||||
import Dialog from '@/views/ui/dialog'
|
||||
import Button from '@/views/ui/button'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VisualConfigure',
|
||||
components: {
|
||||
Tabs, TabsTrigger, TabsList, TabsContent,
|
||||
Button,
|
||||
Dialog,
|
||||
Slider,
|
||||
Switch,
|
||||
SelectGroup, SelectTrigger, SelectContent, SelectItem, Select, SelectLabel, SelectValue,
|
||||
FormDescription, FormControl, FormLabel, FormField, FormItem,
|
||||
Tooltip
|
||||
},
|
||||
computed: {
|
||||
visible: {
|
||||
get(): boolean
|
||||
{
|
||||
return this.isVisible
|
||||
},
|
||||
set(value: boolean)
|
||||
{
|
||||
this.$emit('close', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
configuration: {
|
||||
type: Object as () => Configuration
|
||||
},
|
||||
fields: {
|
||||
type: Array as () => ChartField[],
|
||||
fieldGroup: {
|
||||
type: Array as () => ChartFieldGroup[],
|
||||
default: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
formState: {
|
||||
handler: 'handlerCommit',
|
||||
deep: true
|
||||
},
|
||||
isVisible: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
activeGroup: this.fieldGroup[0]?.label,
|
||||
formState: null as IChart | null
|
||||
}
|
||||
},
|
||||
@ -72,18 +108,25 @@ export default defineComponent({
|
||||
}
|
||||
else {
|
||||
const obj = {} as any
|
||||
this.fields.forEach(field => {
|
||||
if (field.field) {
|
||||
obj[field.field] = undefined
|
||||
}
|
||||
this.fieldGroup.forEach(group => {
|
||||
group?.fields?.forEach(field => {
|
||||
if (field.field) {
|
||||
obj[field.field] = undefined
|
||||
}
|
||||
})
|
||||
})
|
||||
this.formState = obj
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlerCommit()
|
||||
handlerCancel()
|
||||
{
|
||||
this.visible = false
|
||||
},
|
||||
handlerSubmit()
|
||||
{
|
||||
this.$emit('change', this.formState)
|
||||
this.handlerCancel()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="w-full">
|
||||
<Loader2 v-if="loading" class="w-full justify-center animate-spin mt-10"/>
|
||||
<DashboardView v-else-if="data" :layouts="JSON.parse(data.configure as string)"/>
|
||||
<Alert v-else type="error" :title="$t('dashboard.tip.notFound').replace('$VALUE', $router.currentRoute?.value?.params['code'])"/>
|
||||
<Alert v-else type="error" :title="$t('dashboard.tip.notFound').replace('$VALUE', $router.currentRoute?.value?.params['code'] as string)"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user