Merge branch 'dev' into master-fetch-dev

This commit is contained in:
奔跑的面条 2023-09-13 10:44:28 +08:00
commit 87aa938e60
15 changed files with 202 additions and 110 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ dist
dist-ssr dist-ssr
*.local *.local
.vscode .vscode
.idea

View File

@ -41,7 +41,7 @@
"three": "^0.145.0", "three": "^0.145.0",
"vue": "^3.2.31", "vue": "^3.2.31",
"vue-demi": "^0.13.1", "vue-demi": "^0.13.1",
"vue-i18n": "^9.2.2", "vue-i18n": "9.2.2",
"vue-router": "4.0.12", "vue-router": "4.0.12",
"vue3-lazyload": "^0.2.5-beta", "vue3-lazyload": "^0.2.5-beta",
"vue3-sketch-ruler": "^1.3.3", "vue3-sketch-ruler": "^1.3.3",

View File

@ -9,7 +9,8 @@ export const includes = []
// 关系图布局 // 关系图布局
export const GraphLayout = [ export const GraphLayout = [
{ label: '无', value: 'none' }, { label: '无', value: 'none' },
{ label: '环形', value: 'circular' } { label: '环形', value: 'circular' },
{ label: '力引导', value: 'force' }
] ]
// 标签开关 // 标签开关
@ -24,44 +25,57 @@ export const LabelPosition = [
{ label: '右侧', value: 'right' }, { label: '右侧', value: 'right' },
{ label: '顶部', value: 'top' }, { label: '顶部', value: 'top' },
{ label: '底部', value: 'bottom' }, { label: '底部', value: 'bottom' },
{ label: '内部', value: 'inside' }, { label: '内部', value: 'inside' }
]
// 图-迭代动画
export const LayoutAnimation = [
{ label: '开启', value: 1 },
{ label: '关闭', value: 0 }
] ]
export const option = { export const option = {
dataset: { ...dataJson }, dataset: { ...dataJson },
tooltip: {}, tooltip: {},
legend:{ legend: {
show:true, show: true,
textStyle:{ textStyle: {
color:"#eee", color: '#eee',
fontSize: 14 , fontSize: 14
},
data: dataJson.categories.map(function (a) {
return a.name;
})
}, },
series: [ data: dataJson.categories.map(function (a) {
{ return a.name
type: 'graph', })
layout: 'none', // none circular环形布局 },
data: dataJson.nodes, series: [
links: dataJson.links, {
categories: dataJson.categories, type: 'graph',
label: { // 标签 layout: 'none', // none circular环形布局
show: 1, data: dataJson.nodes,
position: 'right', links: dataJson.links,
formatter: '{b}' categories: dataJson.categories,
}, label: {
labelLayout: { show: 1,
hideOverlap: true position: 'right',
}, formatter: '{b}'
lineStyle: { },
color: 'source', // 线条颜色 labelLayout: {
curveness: 0.2 // 线条卷曲程度 hideOverlap: true
} },
lineStyle: {
color: 'source', // 线条颜色
curveness: 0.2 // 线条卷曲程度
},
force: {
repulsion: 100,
gravity: 0.1,
edgeLength: 30,
layoutAnimation: 1,
friction: 0.6
} }
] }
}; ]
}
export default class Config extends PublicConfigClass implements CreateComponentType { export default class Config extends PublicConfigClass implements CreateComponentType {
public key = GraphConfig.key public key = GraphConfig.key

View File

@ -16,14 +16,14 @@
</SettingItemBox> </SettingItemBox>
<SettingItemBox name="线条"> <SettingItemBox name="线条">
<SettingItem name="弧线"> <SettingItem name="弧线">
<!-- 需要输入两位的小数才会变化 --> <!-- 需要输入两位的小数才会变化 -->
<n-input-number <n-input-number
v-model:value="optionData.series[0].lineStyle.curveness" v-model:value="optionData.series[0].lineStyle.curveness"
:min="0" :min="0"
:step="0.01" :step="0.01"
placeholder="弯曲程度" placeholder="弯曲程度"
size="small" size="small"
></n-input-number> ></n-input-number>
</SettingItem> </SettingItem>
</SettingItemBox> </SettingItemBox>
<SettingItemBox name="图例"> <SettingItemBox name="图例">
@ -32,10 +32,61 @@
size="small" size="small"
:modes="['hex']" :modes="['hex']"
v-model:value="optionData.legend.textStyle.color" v-model:value="optionData.legend.textStyle.color"
></n-color-picker> ></n-color-picker>
</SettingItem> </SettingItem>
<SettingItem name="文本"> <SettingItem name="文本">
<n-input-number v-model:value="optionData.legend.textStyle.fontSize" :min="0" :step="1" size="small" placeholder="文字大小"> <n-input-number
v-model:value="optionData.legend.textStyle.fontSize"
:min="0"
:step="1"
size="small"
placeholder="文字大小"
>
</n-input-number>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="力引导" v-if="optionData.series[0].force && graphConfig.layout == 'force'">
<SettingItem name="斥力因子" v-if="optionData.series[0].force.repulsion">
<n-input-number
v-model:value="optionData.series[0].force.repulsion"
:min="0"
:step="1"
size="small"
placeholder="斥力因子大小"
>
</n-input-number>
</SettingItem>
<SettingItem name="引力因子" v-if="optionData.series[0].force.gravity">
<n-input-number
v-model:value="optionData.series[0].force.gravity"
:min="0"
:step="0.1"
size="small"
placeholder="引力因子"
>
</n-input-number>
</SettingItem>
<SettingItem name="节点距离">
<n-input-number
v-model:value="optionData.series[0].force.edgeLength"
:min="0"
:step="1"
size="small"
placeholder="节点距离"
>
</n-input-number>
</SettingItem>
<SettingItem name="迭代动画">
<n-select v-model:value="graphConfig.force.layoutAnimation" :options="LayoutAnimation" size="small" />
</SettingItem>
<SettingItem name="节点速度">
<n-input-number
v-model:value="optionData.series[0].force.friction"
:min="0"
:step="0.1"
size="small"
placeholder="节点速度"
>
</n-input-number> </n-input-number>
</SettingItem> </SettingItem>
</SettingItemBox> </SettingItemBox>
@ -46,7 +97,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { PropType, computed } from 'vue' import { PropType, computed } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option, GraphLayout, LabelSwitch, LabelPosition } from './config' import { option, GraphLayout, LabelSwitch, LabelPosition, LayoutAnimation } from './config'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index' import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
const props = defineProps({ const props = defineProps({
@ -56,7 +107,7 @@ const props = defineProps({
} }
}) })
const graphConfig = computed<typeof option.series[0]>(() => { const graphConfig = computed<(typeof option.series)[0]>(() => {
return props.optionData.series[0] return props.optionData.series[0]
}) })
</script> </script>

View File

@ -1,5 +1,12 @@
<template> <template>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()" autoresize></v-chart> <v-chart
ref="vChartRef"
:init-options="initOptions"
:theme="themeColor"
:option="option"
:manual-update="isPreview()"
autoresize
></v-chart>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">

View File

@ -8,4 +8,14 @@ import { DialConfig } from './Dial/index'
import { SankeyConfig } from './Sankey/index' import { SankeyConfig } from './Sankey/index'
import { GraphConfig } from './Graph/index' import { GraphConfig } from './Graph/index'
export default [ProcessConfig, RadarConfig, FunnelConfig, HeatmapConfig, WaterPoloConfig, TreeMapConfig, GraphConfig, SankeyConfig, DialConfig] export default [
ProcessConfig,
RadarConfig,
FunnelConfig,
HeatmapConfig,
WaterPoloConfig,
TreeMapConfig,
GraphConfig,
SankeyConfig,
DialConfig
]

View File

@ -26,6 +26,16 @@ export let packagesList: PackagesType = {
[PackagesCategoryEnum.ICONS]: IconList [PackagesCategoryEnum.ICONS]: IconList
} }
// 组件缓存, 可以大幅度提升组件加载速度
const componentCacheMap = new Map<string, any>()
const loadConfig = (packageName: string, categoryName: string, keyName: string) => {
const key = packageName + categoryName + keyName
if (!componentCacheMap.has(key)) {
componentCacheMap.set(key, import(`./components/${packageName}/${categoryName}/${keyName}/config.ts`))
}
return componentCacheMap.get(key)
}
/** /**
* * * *
* @param targetData * @param targetData
@ -35,10 +45,10 @@ export const createComponent = async (targetData: ConfigType) => {
// redirectComponent 是给图片组件库和图标组件库使用的 // redirectComponent 是给图片组件库和图标组件库使用的
if (redirectComponent) { if (redirectComponent) {
const [packageName, categoryName, keyName] = redirectComponent.split('/') const [packageName, categoryName, keyName] = redirectComponent.split('/')
const redirectChart = await import(`./components/${packageName}/${categoryName}/${keyName}/config.ts`) const redirectChart = await loadConfig(packageName, categoryName, keyName)
return new redirectChart.default() return new redirectChart.default()
} }
const chart = await import(`./components/${targetData.package}/${category}/${key}/config.ts`) const chart = await loadConfig(targetData.package, category, key)
return new chart.default() return new chart.default()
} }
@ -84,7 +94,7 @@ export const fetchImages = async (targetData?: ConfigType) => {
// 正则判断图片是否为 url是则直接返回该 url // 正则判断图片是否为 url是则直接返回该 url
if (/^(http|https):\/\/([\w.]+\/?)\S*/.test(targetData.image)) return targetData.image if (/^(http|https):\/\/([\w.]+\/?)\S*/.test(targetData.image)) return targetData.image
// 新数据动态处理 // 新数据动态处理
const { image, package: targetDataPackage } = targetData const { image } = targetData
// 兼容旧数据 // 兼容旧数据
if (image.includes('@') || image.includes('base64')) return image if (image.includes('@') || image.includes('base64')) return image

View File

@ -182,20 +182,16 @@ export const useChartEditStore = defineStore({
}, },
getComponentList(): Array<CreateComponentType | CreateComponentGroupType> { getComponentList(): Array<CreateComponentType | CreateComponentGroupType> {
return this.componentList return this.componentList
}, }
// 获取需要存储的数据项 },
actions: {
// * 获取需要存储的数据项
getStorageInfo(): ChartEditStorage { getStorageInfo(): ChartEditStorage {
return { return {
[ChartEditStoreEnum.EDIT_CANVAS_CONFIG]: this.getEditCanvasConfig, [ChartEditStoreEnum.EDIT_CANVAS_CONFIG]: this.getEditCanvasConfig,
[ChartEditStoreEnum.COMPONENT_LIST]: this.getComponentList, [ChartEditStoreEnum.COMPONENT_LIST]: this.getComponentList,
[ChartEditStoreEnum.REQUEST_GLOBAL_CONFIG]: this.getRequestGlobalConfig [ChartEditStoreEnum.REQUEST_GLOBAL_CONFIG]: this.getRequestGlobalConfig
} }
}
},
actions: {
// * 设置 peojectInfo 数据项
setProjectInfo<T extends keyof ProjectInfoType, K extends ProjectInfoType[T]>(key: T, value: K) {
this.projectInfo[key] = value
}, },
// * 设置 editCanvas 数据项 // * 设置 editCanvas 数据项
setEditCanvas<T extends keyof EditCanvasType, K extends EditCanvasType[T]>(key: T, value: K) { setEditCanvas<T extends keyof EditCanvasType, K extends EditCanvasType[T]>(key: T, value: K) {

View File

@ -20,14 +20,14 @@ export const syncData = () => {
onPositiveCallback: async () => { onPositiveCallback: async () => {
window['$message'].success('正在同步编辑器...') window['$message'].success('正在同步编辑器...')
dataSyncUpdate && (await dataSyncUpdate()) dataSyncUpdate && (await dataSyncUpdate())
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo })) dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo() }))
} }
}) })
} }
// 同步数据到预览页 // 同步数据到预览页
export const syncDataToPreview = () => { export const syncDataToPreview = () => {
dispatchEvent(new CustomEvent(SavePageEnum.CHART_TO_PREVIEW, { detail: chartEditStore.getStorageInfo })) dispatchEvent(new CustomEvent(SavePageEnum.CHART_TO_PREVIEW, { detail: chartEditStore.getStorageInfo() }))
} }
// 侦听器更新 // 侦听器更新

View File

@ -158,7 +158,7 @@ const editHandle = () => {
// SessionStorage 便 // SessionStorage 便
const updateToSession = (id: string) => { const updateToSession = (id: string) => {
const storageInfo = chartEditStore.getStorageInfo const storageInfo = chartEditStore.getStorageInfo()
const sessionStorageInfo = getLocalStorage(StorageEnum.GO_CHART_STORAGE_LIST) || [] const sessionStorageInfo = getLocalStorage(StorageEnum.GO_CHART_STORAGE_LIST) || []
if (sessionStorageInfo?.length) { if (sessionStorageInfo?.length) {

View File

@ -1,41 +1,41 @@
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { canvasCut, downloadTextFile, JSONStringify } from '@/utils' import { canvasCut, downloadTextFile, JSONStringify } from '@/utils'
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
// 导出 // 导出
export const exportHandle = () => { export const exportHandle = () => {
// 取消选中 // 取消选中
chartEditStore.setTargetSelectChart(undefined) chartEditStore.setTargetSelectChart(undefined)
// 导出数据 // 导出数据
downloadTextFile( downloadTextFile(
JSONStringify(chartEditStore.getStorageInfo || []), JSONStringify(chartEditStore.getStorageInfo() || []),
undefined, undefined,
'json' 'json'
) )
// 导出图片 // 导出图片
const range = document.querySelector('.go-edit-range') as HTMLElement const range = document.querySelector('.go-edit-range') as HTMLElement
const watermark = document.getElementById('go-edit-watermark') const watermark = document.getElementById('go-edit-watermark')
// 隐藏边距线 // 隐藏边距线
if (!range || !watermark) { if (!range || !watermark) {
window['$message'].error('导出失败!') window['$message'].error('导出失败!')
return return
} }
// 记录缩放比例 // 记录缩放比例
const scaleTemp = chartEditStore.getEditCanvas.scale const scaleTemp = chartEditStore.getEditCanvas.scale
// 百分百展示页面 // 百分百展示页面
chartEditStore.setScale(1, true) chartEditStore.setScale(1, true)
// 展示水印 // 展示水印
watermark.style.display = 'block' watermark.style.display = 'block'
setTimeout(() => { setTimeout(() => {
canvasCut(range, () => { canvasCut(range, () => {
// 隐藏水印 // 隐藏水印
if (watermark) watermark.style.display = 'none' if (watermark) watermark.style.display = 'none'
// 还原页面大小 // 还原页面大小
chartEditStore.setScale(scaleTemp, true) chartEditStore.setScale(scaleTemp, true)
}) })
}, 600) }, 600)
} }

View File

@ -94,7 +94,7 @@ const previewHandle = () => {
const { id } = routerParamsInfo.params const { id } = routerParamsInfo.params
// id // id
const previewId = typeof id === 'string' ? id : id[0] const previewId = typeof id === 'string' ? id : id[0]
const storageInfo = chartEditStore.getStorageInfo const storageInfo = chartEditStore.getStorageInfo()
const sessionStorageInfo = getLocalStorage(StorageEnum.GO_CHART_STORAGE_LIST) || [] const sessionStorageInfo = getLocalStorage(StorageEnum.GO_CHART_STORAGE_LIST) || []
if (sessionStorageInfo?.length) { if (sessionStorageInfo?.length) {

View File

@ -209,9 +209,7 @@ export const useSync = () => {
chartHistoryStore.clearForwardStack() chartHistoryStore.clearForwardStack()
} }
} }
} else { } else if (key === ChartEditStoreEnum.EDIT_CANVAS_CONFIG || key === ChartEditStoreEnum.REQUEST_GLOBAL_CONFIG) {
// 非组件(顺便排除脏数据)
if (key !== 'editCanvasConfig' && key !== 'requestGlobalConfig') return
componentMerge(chartEditStore[key], projectData[key], true) componentMerge(chartEditStore[key], projectData[key], true)
} }
} }

View File

@ -6,8 +6,8 @@
:key="item.id" :key="item.id"
:style="{ :style="{
...getComponentAttrStyle(item.attr, groupIndex), ...getComponentAttrStyle(item.attr, groupIndex),
...getFilterStyle(item.styles), ...getFilterStyle(groupData.styles),
...getTransformStyle(item.styles), ...getTransformStyle(groupData.styles),
...getStatusStyle(item.status), ...getStatusStyle(item.status),
...getPreviewConfigStyle(item.preview), ...getPreviewConfigStyle(item.preview),
...getBlendModeStyle(item.styles) as any ...getBlendModeStyle(item.styles) as any
@ -19,7 +19,11 @@
:chartConfig="item" :chartConfig="item"
:themeSetting="themeSetting" :themeSetting="themeSetting"
:themeColor="themeColor" :themeColor="themeColor"
:style="{ ...getSizeStyle(item.attr) }" :style="{
...getSizeStyle(item.attr),
...getFilterStyle(item.styles),
...getTransformStyle(item.styles)
}"
v-on="useLifeHandler(item)" v-on="useLifeHandler(item)"
></component> ></component>
</div> </div>

View File

@ -47,6 +47,7 @@ setTitle(`预览-${chartEditStore.editCanvasConfig.projectName}`)
const previewRefStyle = computed(() => { const previewRefStyle = computed(() => {
return { return {
overflow: 'hidden',
...getEditCanvasConfigStyle(chartEditStore.editCanvasConfig), ...getEditCanvasConfigStyle(chartEditStore.editCanvasConfig),
...getFilterStyle(chartEditStore.editCanvasConfig) ...getFilterStyle(chartEditStore.editCanvasConfig)
} }