feat: 新增数据mock,数据字段映射

This commit is contained in:
奔跑的面条 2024-12-22 12:51:02 +08:00
parent 152786c652
commit 3ae9aac2d9
11 changed files with 153 additions and 108 deletions

View File

@ -1,4 +1,5 @@
import test from './test.mock' import test from './test.mock'
import vchart from './vchart.mock'
import { MockMethod } from 'vite-plugin-mock' import { MockMethod } from 'vite-plugin-mock'
import { RequestHttpEnum } from '@/enums/httpEnum' import { RequestHttpEnum } from '@/enums/httpEnum'
@ -22,6 +23,8 @@ export const threeEarth01Url = '/mock/threeEarth01Data'
export const sankeyUrl = '/mock/sankey' export const sankeyUrl = '/mock/sankey'
export const graphUrl = '/mock/graphData' export const graphUrl = '/mock/graphData'
export const vchartBarDataUrl = '/mock/vchart/barDataUrl'
const mockObject: MockMethod[] = [ const mockObject: MockMethod[] = [
{ {
// 正则 // 正则
@ -115,6 +118,11 @@ const mockObject: MockMethod[] = [
method: RequestHttpEnum.GET, method: RequestHttpEnum.GET,
response: () => test.graphData response: () => test.graphData
}, },
{
url: vchartBarDataUrl,
method: RequestHttpEnum.GET,
response: () => vchart.bar
}
] ]
export default mockObject export default mockObject

View File

@ -0,0 +1,10 @@
import bar from './vchart/bar.json'
export default {
bar: {
code: 0,
status: 200,
msg: '请求成功',
data: bar
}
}

View File

@ -0,0 +1,16 @@
{
"values": [
{ "type": "Nail polish", "year": "Africa", "value|100-900": 3 },
{ "type": "Nail polish", "year": "EU", "value|100-900": 3 },
{ "type": "Nail polish", "year": "China", "value|100-900": 3 },
{ "type": "Nail polish", "year": "USA", "value|100-900": 3 },
{ "type": "Eyebrow pencil", "year": "Africa", "value|100-900": 3 },
{ "type": "Eyebrow pencil", "year": "EU", "value|100-900": 3 },
{ "type": "Eyebrow pencil", "year": "China", "value|100-900": 3 },
{ "type": "Eyebrow pencil", "year": "USA", "value|100-900": 3 },
{ "type": "Rouge", "year": "Africa", "value|100-900": 3 },
{ "type": "Rouge", "year": "EU", "value|100-900": 3 },
{ "type": "Rouge", "year": "China", "value|100-900": 3 },
{ "type": "Rouge", "year": "USA", "value|100-900": 3 }
]
}

View File

@ -2,13 +2,13 @@
<div <div
ref="vChartRef" ref="vChartRef"
v-on="{ v-on="{
...Object.fromEntries(event.map(eventName => [eventName, (eventData: MouseEvent) => eventHandlers(eventData, eventName)])) ...Object.fromEntries(event.map((eventName: string) => [eventName, (eventData: MouseEvent) => eventHandlers(eventData, eventName)]))
}" }"
></div> ></div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, PropType, watch, onMounted, onBeforeUnmount, nextTick } from 'vue' import { ref, PropType, watch, onBeforeUnmount, nextTick, toRaw } from 'vue'
import { VChart, type IVChart, type IInitOption, type ISpec } from '@visactor/vchart' import { VChart, type IVChart, type IInitOption, type ISpec } from '@visactor/vchart'
import { transformHandler } from './transformProps' import { transformHandler } from './transformProps'
import { IOption } from '@/packages/components/VChart/index.d' import { IOption } from '@/packages/components/VChart/index.d'
@ -136,7 +136,7 @@ const emit = defineEmits([
const props = defineProps({ const props = defineProps({
option: { option: {
type: Object as PropType< type: Object as PropType<
ISpec & { IOption & {
dataset: any dataset: any
} }
>, >,
@ -160,7 +160,7 @@ let chart: IVChart
watch( watch(
() => ({ () => ({
...props.option, ...props.option,
data: undefined dataset: undefined
}), }),
() => { () => {
nextTick(() => { nextTick(() => {
@ -173,22 +173,6 @@ watch(
} }
) )
//
watch(
() => props.option.dataset,
() => {
if (vChartRef.value) {
nextTick(() => {
createOrUpdateChart(props.option)
})
}
},
{
deep: false,
immediate: false
}
)
// //
const createOrUpdateChart = ( const createOrUpdateChart = (
chartProps: IOption & { chartProps: IOption & {
@ -208,7 +192,7 @@ const createOrUpdateChart = (
return true return true
} else if (chart) { } else if (chart) {
const spec = transformHandler[chartProps.category](chartProps) const spec = transformHandler[chartProps.category](chartProps)
chart.updateSpec({ ...spec, data: chartProps.dataset }) chart.updateSpec({ ...spec, data: toRaw(chartProps.dataset), dataset: undefined })
return true return true
} }
return false return false
@ -217,7 +201,6 @@ const createOrUpdateChart = (
// //
const refresh = () => { const refresh = () => {
if (chart) { if (chart) {
chart.release()
chart.renderSync() chart.renderSync()
} }
} }

View File

@ -14,7 +14,7 @@ export const option: IBarOption & { dataset?: any } = {
dataset: data, dataset: data,
stack: true, stack: true,
xField: ['year', 'type'], xField: ['year', 'type'],
yField: 'value', yField: ['value'],
seriesField: 'type', seriesField: 'type',
// 业务配置后续会被转换为图表spec) // 业务配置后续会被转换为图表spec)
category: VChartBarCommonConfig.category, category: VChartBarCommonConfig.category,

View File

@ -10,6 +10,7 @@
{ "type": "Autocracies", "year": "2000", "value": 89 }, { "type": "Autocracies", "year": "2000", "value": 89 },
{ "type": "Autocracies", "year": "2010", "value": 80 }, { "type": "Autocracies", "year": "2010", "value": 80 },
{ "type": "Autocracies", "year": "2018", "value": 80 }, { "type": "Autocracies", "year": "2018", "value": 80 },
{ "type": "Democracies", "year": "1930", "value": 22 }, { "type": "Democracies", "year": "1930", "value": 22 },
{ "type": "Democracies", "year": "1940", "value": 13 }, { "type": "Democracies", "year": "1940", "value": 13 },
{ "type": "Democracies", "year": "1950", "value": 25 }, { "type": "Democracies", "year": "1950", "value": 25 },

View File

@ -12,9 +12,9 @@ export const option: IBarOption & { dataset?: any } = {
// 图表配置 // 图表配置
type: 'bar', type: 'bar',
dataset: data, dataset: data,
xField: 'State', xField: ['type'],
yField: 'Population', yField: ['value'],
seriesField: 'Age', seriesField: 'year',
stack: true, stack: true,
// 业务配置后续会被转换为图表spec) // 业务配置后续会被转换为图表spec)
category: VChartBarStackConfig.category, category: VChartBarStackConfig.category,

View File

@ -1,79 +1,16 @@
{ {
"values": [ "values": [
{ { "type": "Nail polish", "year": "Africa", "value": 590 },
"State": "WY", { "type": "Nail polish", "year": "EU", "value": 450 },
"Age": "Under 5 Years", { "type": "Nail polish", "year": "China", "value": 474 },
"Population": 25635 { "type": "Nail polish", "year": "USA", "value": 459 },
}, { "type": "Eyebrow pencil", "year": "Africa", "value": 746 },
{ { "type": "Eyebrow pencil", "year": "EU", "value": 176 },
"State": "WY", { "type": "Eyebrow pencil", "year": "China", "value": 210 },
"Age": "5 to 13 Years", { "type": "Eyebrow pencil", "year": "USA", "value": 775 },
"Population": 1890 { "type": "Rouge", "year": "Africa", "value": 896 },
}, { "type": "Rouge", "year": "EU", "value": 784 },
{ { "type": "Rouge", "year": "China", "value": 866 },
"State": "WY", { "type": "Rouge", "year": "USA", "value": 899 }
"Age": "14 to 17 Years",
"Population": 9314
},
{
"State": "DC",
"Age": "Under 5 Years",
"Population": 30352
},
{
"State": "DC",
"Age": "5 to 13 Years",
"Population": 20439
},
{
"State": "DC",
"Age": "14 to 17 Years",
"Population": 10225
},
{
"State": "VT",
"Age": "Under 5 Years",
"Population": 38253
},
{
"State": "VT",
"Age": "5 to 13 Years",
"Population": 42538
},
{
"State": "VT",
"Age": "14 to 17 Years",
"Population": 15757
},
{
"State": "ND",
"Age": "Under 5 Years",
"Population": 51896
},
{
"State": "ND",
"Age": "5 to 13 Years",
"Population": 67358
},
{
"State": "ND",
"Age": "14 to 17 Years",
"Population": 18794
},
{
"State": "AK",
"Age": "Under 5 Years",
"Population": 72083
},
{
"State": "AK",
"Age": "5 to 13 Years",
"Population": 85640
},
{
"State": "AK",
"Age": "14 to 17 Years",
"Population": 22153
}
] ]
} }

View File

@ -1,6 +1,7 @@
<template> <template>
<n-timeline class="go-chart-configurations-timeline"> <n-timeline class="go-chart-configurations-timeline">
<n-timeline-item v-show="isCharts && dimensionsAndSource" type="info" :title="TimelineTitleEnum.MAPPING"> <!-- 处理 echarts 的数据映射 -->
<n-timeline-item v-if="isCharts && dimensionsAndSource" type="info" :title="TimelineTitleEnum.MAPPING">
<n-table striped> <n-table striped>
<thead> <thead>
<tr> <tr>
@ -25,6 +26,47 @@
</tbody> </tbody>
</n-table> </n-table>
</n-timeline-item> </n-timeline-item>
<!-- 处理 vcharts 的数据映射 -->
<n-timeline-item v-if="isVChart" type="info" :title="TimelineTitleEnum.MAPPING">
<n-table striped>
<thead>
<tr>
<th v-for="item in vchartTableTitle" :key="item">{{ item }}</th>
</tr>
</thead>
<tbody>
<tr v-for="item in fieldList" :key="item.field">
<td>
<n-ellipsis style="width: 70px; max-width: 240px">
{{ item.field }}
</n-ellipsis>
</td>
<td v-if="isArray(item.mapping)">
<n-space :size="4" vertical>
<n-input
v-for="(mappingItem, index) in item.mapping"
:key="index"
v-model:value="item.mapping[index]"
type="tiny"
size="small"
placeholder="输入字段"
@change="() => (item.result = matchingHandle(item.mapping[index]))"
/>
</n-space>
</td>
<td v-else>
<n-input v-model:value="item.mapping" type="text" size="small" placeholder="小" />
</td>
<!-- <td>
<n-space style="width: 70px" :size="4">
<n-badge dot :type="item.result === 1 ? 'success' : 'error'"></n-badge>
<n-text>匹配{{ item.result === 1 ? '成功' : '失败' }}</n-text>
</n-space>
</td> -->
</tr>
</tbody>
</n-table>
</n-timeline-item>
<n-timeline-item v-show="filterShow" color="#97846c" :title="TimelineTitleEnum.FILTER"> <n-timeline-item v-show="filterShow" color="#97846c" :title="TimelineTitleEnum.FILTER">
<n-space :size="18" vertical> <n-space :size="18" vertical>
<n-text depth="3">过滤器默认处理接口返回值的data字段</n-text> <n-text depth="3">过滤器默认处理接口返回值的data字段</n-text>
@ -66,7 +108,7 @@
<help-outline-icon></help-outline-icon> <help-outline-icon></help-outline-icon>
</n-icon> </n-icon>
</template> </template>
<n-text depth="3">点击下载查看完整数据</n-text> <span>点击下载查看完整数据</span>
</n-tooltip> </n-tooltip>
</div> </div>
</n-space> </n-space>
@ -87,11 +129,10 @@ import { DataResultEnum, TimelineTitleEnum } from '../../index.d'
import { ChartDataMonacoEditor } from '../ChartDataMonacoEditor' import { ChartDataMonacoEditor } from '../ChartDataMonacoEditor'
import { useFile } from '../../hooks/useFile.hooks' import { useFile } from '../../hooks/useFile.hooks'
import { useTargetData } from '../../../hooks/useTargetData.hook' import { useTargetData } from '../../../hooks/useTargetData.hook'
import isObject from 'lodash/isObject'
import { toString, isArray } from '@/utils' import { toString, isArray } from '@/utils'
const { targetData } = useTargetData() const { targetData } = useTargetData()
const props = defineProps({ defineProps({
show: { show: {
type: Boolean, type: Boolean,
required: false required: false
@ -104,6 +145,7 @@ const props = defineProps({
// //
const tableTitle = ['字段', '映射', '状态'] const tableTitle = ['字段', '映射', '状态']
const vchartTableTitle = ['字段', '接口映射字段']
const { HelpOutlineIcon } = icon.ionicons5 const { HelpOutlineIcon } = icon.ionicons5
const { DocumentAddIcon, DocumentDownloadIcon } = icon.carbon const { DocumentAddIcon, DocumentDownloadIcon } = icon.carbon
@ -113,6 +155,15 @@ const dimensions = ref()
const dimensionsAndSource = ref() const dimensionsAndSource = ref()
const noData = ref(false) const noData = ref(false)
// , mapping
const fieldList = ref<
Array<{
field: string
mapping: string[]
result: DataResultEnum
}>
>([])
const { uploadFileListRef, customRequest, beforeUpload, download } = useFile(targetData) const { uploadFileListRef, customRequest, beforeUpload, download } = useFile(targetData)
// //
@ -124,6 +175,10 @@ const filterShow = computed(() => {
const isCharts = computed(() => { const isCharts = computed(() => {
return targetData.value.chartConfig.chartFrame === ChartFrameEnum.ECHARTS return targetData.value.chartConfig.chartFrame === ChartFrameEnum.ECHARTS
}) })
// vchart
const isVChart = computed(() => {
return targetData.value.chartConfig.chartFrame === ChartFrameEnum.VCHART
})
// //
const matchingHandle = (mapping: string) => { const matchingHandle = (mapping: string) => {
@ -162,6 +217,33 @@ const dimensionsAndSourceHandle = () => {
} }
} }
// vchart
const initFieldListHandle = () => {
if (targetData.value?.option) {
fieldList.value = []
// Field key
for (const key in targetData.value.option) {
if (key.endsWith('Field')) {
const value = targetData.value.option[key]
if (!isArray(value)) {
targetData.value.option[key] = [value]
}
const item = {
field: key,
mapping: value,
result: DataResultEnum.SUCCESS
}
if (item.mapping === undefined) {
item.result = DataResultEnum.FAILURE
} else if (!isArray(item.mapping)) {
item.mapping = [item.mapping]
}
fieldList.value.push(item)
}
}
}
}
watch( watch(
() => targetData.value?.option?.dataset, () => targetData.value?.option?.dataset,
( (
@ -178,9 +260,13 @@ watch(
dimensions.value = newData.dimensions dimensions.value = newData.dimensions
dimensionsAndSource.value = dimensionsAndSourceHandle() dimensionsAndSource.value = dimensionsAndSourceHandle()
} }
} else if (newData && targetData?.value?.chartConfig?.chartFrame === ChartFrameEnum.VCHART) {
source.value = newData
initFieldListHandle()
} else if (newData !== undefined && newData !== null) { } else if (newData !== undefined && newData !== null) {
dimensionsAndSource.value = null dimensionsAndSource.value = null
source.value = newData source.value = newData
fieldList.value = []
} else { } else {
noData.value = true noData.value = true
source.value = '此组件无数据源' source.value = '此组件无数据源'

View File

@ -82,7 +82,8 @@ import {
wordCloudUrl, wordCloudUrl,
treemapUrl, treemapUrl,
threeEarth01Url, threeEarth01Url,
sankeyUrl sankeyUrl,
vchartBarDataUrl
} from '@/api/mock' } from '@/api/mock'
const props = defineProps({ const props = defineProps({
@ -150,7 +151,10 @@ const apiList = [
}, },
{ {
value: `【关系图】${graphUrl}` value: `【关系图】${graphUrl}`
} },
{
value: `【vchart 柱状图】${vchartBarDataUrl}`
},
] ]
</script> </script>

View File

@ -20,6 +20,6 @@
// "strictNullChecks": true, //使null // "strictNullChecks": true, //使null
"noImplicitThis": true //this "noImplicitThis": true //this
}, },
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "types/**/*"], "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "types/**/*", "src/api/mock/vchart/bar.js"],
"exclude": ["node_modules", "dist", "**/*.js"] "exclude": ["node_modules", "dist", "**/*.js"]
} }