Merge branch 'dev' into dev-commet

This commit is contained in:
tnt group 2023-05-10 11:33:48 +08:00
commit 01be79ee9a
18 changed files with 776 additions and 761 deletions

View File

@ -20,7 +20,7 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
### 🤯 后端项目 ### 🤯 后端项目
后端项目gitee地址[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve) 后端项目 gitee 地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)
接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb) 接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)
@ -53,7 +53,7 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
| 名称 | 版本 | 名称 | 版本 | | 名称 | 版本 | 名称 | 版本 |
| ------------------- | ----- | ----------- | ------ | | ------------------- | ----- | ----------- | ------ |
| Vue | 3.2.x | TypeScript4 | 4.6.x | | Vue | 3.2.x | TypeScript4 | 4.6.x |
| Vite | 2.9.x | NaiveUI | 2.27.x | | Vite | 4.2.x | NaiveUI | 2.34.x |
| ECharts | 5.3.x | Pinia | 2.0.x | | ECharts | 5.3.x | Pinia | 2.0.x |
| 详见 `package.json` | 😁 | 🥰 | 🤗 | | 详见 `package.json` | 😁 | 🥰 | 🤗 |
@ -61,7 +61,7 @@ GoView 是一个高效的拖拽式低代码数据可视化开发平台,将图
| 名称 | 版本 | 名称 | 版本 | | 名称 | 版本 | 名称 | 版本 |
| ---- | ------- | ------- | ----- | | ---- | ------- | ------- | ----- |
| node | 16.14.x | npm | 8.5.x | | node | 16.16.x | npm | 8.5.x |
| pnpm | 7.1.x | windows | 11 | | pnpm | 7.1.x | windows | 11 |
已完成图表: 已完成图表:

View File

@ -21,7 +21,7 @@ axiosInstance.interceptors.request.use(
axiosInstance.interceptors.response.use( axiosInstance.interceptors.response.use(
(res: AxiosResponse) => { (res: AxiosResponse) => {
const { code } = res.data as { code: number } const { code } = res.data as { code: number }
if (code === undefined || code === null) return Promise.resolve(res) if (code === undefined || code === null) return Promise.resolve(res.data)
if (code === ResultEnum.DATA_SUCCESS) return Promise.resolve(res.data) if (code === ResultEnum.DATA_SUCCESS) return Promise.resolve(res.data)
// 重定向 // 重定向
if (ErrorPageNameMap.get(code)) redirectErrorPage(code) if (ErrorPageNameMap.get(code)) redirectErrorPage(code)

View File

@ -1,122 +1,123 @@
import { ref, toRefs, toRaw, watch } from 'vue' import { ref, toRefs, toRaw, watch } from 'vue'
import type VChart from 'vue-echarts' import type VChart from 'vue-echarts'
import { customizeHttp } from '@/api/http' import { customizeHttp } from '@/api/http'
import { useChartDataPondFetch } from '@/hooks/' import { useChartDataPondFetch } from '@/hooks/'
import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d' import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { RequestDataTypeEnum } from '@/enums/httpEnum' import { RequestDataTypeEnum } from '@/enums/httpEnum'
import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils' import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils'
import { setOption } from '@/packages/public/chart' import { setOption } from '@/packages/public/chart'
// 获取类型 // 获取类型
type ChartEditStoreType = typeof useChartEditStore type ChartEditStoreType = typeof useChartEditStore
/** /**
* setdata * setdata
* @param targetComponent * @param targetComponent
* @param useChartEditStore * @param useChartEditStore
* @param updateCallback * @param updateCallback
*/ */
export const useChartDataFetch = ( export const useChartDataFetch = (
targetComponent: CreateComponentType, targetComponent: CreateComponentType,
useChartEditStore: ChartEditStoreType, useChartEditStore: ChartEditStoreType,
updateCallback?: (...args: any) => any updateCallback?: (...args: any) => any
) => { ) => {
const vChartRef = ref<typeof VChart | null>(null) const vChartRef = ref<typeof VChart | null>(null)
let fetchInterval: any = 0 let fetchInterval: any = 0
// 数据池 // 数据池
const { addGlobalDataInterface } = useChartDataPondFetch() const { addGlobalDataInterface } = useChartDataPondFetch()
// 组件类型 // 组件类型
const { chartFrame } = targetComponent.chartConfig const { chartFrame } = targetComponent.chartConfig
// eCharts 组件配合 vChart 库更新方式 // eCharts 组件配合 vChart 库更新方式
const echartsUpdateHandle = (dataset: any) => { const echartsUpdateHandle = (dataset: any) => {
if (chartFrame === ChartFrameEnum.ECHARTS) { if (chartFrame === ChartFrameEnum.ECHARTS) {
if (vChartRef.value) { if (vChartRef.value) {
setOption(vChartRef.value, { dataset: dataset }) setOption(vChartRef.value, { dataset: dataset })
} }
} }
} }
const requestIntervalFn = () => { const requestIntervalFn = () => {
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
// 全局数据 // 全局数据
const { const {
requestOriginUrl, requestOriginUrl,
requestIntervalUnit: globalUnit, requestIntervalUnit: globalUnit,
requestInterval: globalRequestInterval requestInterval: globalRequestInterval
} = toRefs(chartEditStore.getRequestGlobalConfig) } = toRefs(chartEditStore.getRequestGlobalConfig)
// 目标组件 // 目标组件
const { const {
requestDataType, requestDataType,
requestUrl, requestUrl,
requestIntervalUnit: targetUnit, requestIntervalUnit: targetUnit,
requestInterval: targetInterval requestInterval: targetInterval
} = toRefs(targetComponent.request) } = toRefs(targetComponent.request)
// 非请求类型 // 非请求类型
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
try { try {
// 处理地址 // 处理地址
// @ts-ignore // @ts-ignore
if (requestUrl?.value) { if (requestUrl?.value) {
// requestOriginUrl 允许为空 // requestOriginUrl 允许为空
const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
if (!completePath) return if (!completePath) return
clearInterval(fetchInterval) clearInterval(fetchInterval)
const fetchFn = async () => { const fetchFn = async () => {
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig)) const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig))
if (res) { if (res) {
try { try {
const filter = targetComponent.filter const filter = targetComponent.filter
echartsUpdateHandle(newFunctionHandle(res?.data, res, filter)) const { data } = res
// 更新回调函数 echartsUpdateHandle(newFunctionHandle(data, res, filter))
if (updateCallback) { // 更新回调函数
updateCallback(newFunctionHandle(res?.data, res, filter)) if (updateCallback) {
} updateCallback(newFunctionHandle(data, res, filter))
} catch (error) { }
console.error(error) } catch (error) {
} console.error(error)
} }
} }
}
// 普通初始化与组件交互处理监听
watch( // 普通初始化与组件交互处理监听
() => targetComponent.request, watch(
() => { () => targetComponent.request,
fetchFn() () => {
}, fetchFn()
{ },
immediate: true, {
deep: true immediate: true,
} deep: true
) }
)
// 定时时间
const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value // 定时时间
// 单位 const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value
const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value // 单位
// 开启轮询 const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit)) // 开启轮询
} if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
// eslint-disable-next-line no-empty }
} catch (error) { // eslint-disable-next-line no-empty
console.log(error) } catch (error) {
} console.log(error)
} }
}
if (isPreview()) {
// 判断是否是数据池类型 if (isPreview()) {
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond // 判断是否是数据池类型
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle) targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
: requestIntervalFn() ? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
} : requestIntervalFn()
return { vChartRef } }
} return { vChartRef }
}

View File

@ -2,7 +2,7 @@
<collapse-item name="信息" :expanded="true"> <collapse-item name="信息" :expanded="true">
<setting-item-box name="文字" :alone="true"> <setting-item-box name="文字" :alone="true">
<setting-item> <setting-item>
<n-input v-model:value="optionData.dataset" size="small"></n-input> <n-input v-model:value="optionData.dataset" type="textarea" size="small"></n-input>
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="链接" :alone="true"> <setting-item-box name="链接" :alone="true">
@ -30,11 +30,7 @@
<n-input-number v-model:value="optionData.fontSize" size="small" placeholder="字体大小"></n-input-number> <n-input-number v-model:value="optionData.fontSize" size="small" placeholder="字体大小"></n-input-number>
</setting-item> </setting-item>
<setting-item name="字体粗细"> <setting-item name="字体粗细">
<n-select <n-select v-model:value="optionData.fontWeight" size="small" :options="fontWeightOptions" />
v-model:value="optionData.fontWeight"
size="small"
:options="fontWeightOptions"
/>
</setting-item> </setting-item>
<setting-item name="X轴内边距"> <setting-item name="X轴内边距">
<n-input-number v-model:value="optionData.paddingX" size="small" placeholder="输入内边距"></n-input-number> <n-input-number v-model:value="optionData.paddingX" size="small" placeholder="输入内边距"></n-input-number>
@ -87,9 +83,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from 'vue' import { PropType } from 'vue'
import { option, WritingModeEnum, WritingModeObject, import { option, WritingModeEnum, WritingModeObject, FontWeightEnum, FontWeightObject } from './config'
FontWeightEnum,
FontWeightObject, } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
const props = defineProps({ const props = defineProps({
optionData: { optionData: {
@ -117,13 +111,13 @@ const verticalOptions = [
const fontWeightOptions = [ const fontWeightOptions = [
{ {
label: FontWeightEnum.NORMAL, label: FontWeightEnum.NORMAL,
value: FontWeightObject[FontWeightEnum.NORMAL], value: FontWeightObject[FontWeightEnum.NORMAL]
}, },
{ {
label: FontWeightEnum.BOLD, label: FontWeightEnum.BOLD,
value: FontWeightObject[FontWeightEnum.BOLD], value: FontWeightObject[FontWeightEnum.BOLD]
}, }
]; ]
const handleLinkClick = () => { const handleLinkClick = () => {
window.open(props.optionData.linkHead + props.optionData.link) window.open(props.optionData.linkHead + props.optionData.link)
} }

View File

@ -1,8 +1,8 @@
<template> <template>
<div class="go-text-box"> <div class="go-text-box">
<div class="content"> <div class="content">
<span style="cursor: pointer" v-if="link" @click="click">{{ option.dataset }}</span> <span style="cursor: pointer; white-space: pre-wrap" v-if="link" @click="click"></span>
<span v-else>{{ option.dataset }}</span> <span style="white-space: pre-wrap" v-else>{{ option.dataset }}</span>
</div> </div>
</div> </div>
</template> </template>
@ -82,7 +82,7 @@ const click = () => {
border-width: v-bind('borderWidth + "px"'); border-width: v-bind('borderWidth + "px"');
border-radius: v-bind('borderRadius + "px"'); border-radius: v-bind('borderRadius + "px"');
border-color: v-bind('borderColor'); border-color: v-bind('borderColor');
background-color: v-bind('backgroundColor'); background-color: v-bind('backgroundColor');
} }
} }

View File

@ -140,6 +140,7 @@ export interface CreateComponentType extends PublicConfigType, requestConfig {
key: string key: string
chartConfig: ConfigType chartConfig: ConfigType
option: GlobalThemeJsonType option: GlobalThemeJsonType
groupList?: Array<CreateComponentType>
} }
// 组件成组实例类 // 组件成组实例类

View File

@ -2212,9 +2212,9 @@
"pinyin": "tengluozi" "pinyin": "tengluozi"
}, },
{ {
"CMYK": [57, 62, 16, 2], "CMYK": [34, 39, 0, 24],
"RGB": [128, 109, 158], "RGB": [128, 118, 195],
"hex": "#806d9e", "hex": "#8076c3",
"name": "槿紫", "name": "槿紫",
"pinyin": "jinzi" "pinyin": "jinzi"
}, },

View File

@ -1,77 +1,83 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ChartLayoutType, LayerModeEnum, ChartModeEnum } from './chartLayoutStore.d' import { ChartLayoutType, LayerModeEnum, ChartModeEnum } from './chartLayoutStore.d'
import { setLocalStorage, getLocalStorage } from '@/utils' import { setLocalStorage, getLocalStorage } from '@/utils'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const { GO_CHART_LAYOUT_STORE } = StorageEnum const { GO_CHART_LAYOUT_STORE } = StorageEnum
const storageChartLayout: Partial<ChartLayoutType> = getLocalStorage(GO_CHART_LAYOUT_STORE) const storageChartLayout: Partial<ChartLayoutType> = getLocalStorage(GO_CHART_LAYOUT_STORE)
// 编辑区域布局和静态设置 // 编辑区域布局和静态设置
export const useChartLayoutStore = defineStore({ export const useChartLayoutStore = defineStore({
id: 'useChartLayoutStore', id: 'useChartLayoutStore',
state: (): ChartLayoutType => ({ state: (): ChartLayoutType => ({
// 图层控制 // 图层控制
layers: true, layers: true,
// 图表组件 // 图表组件
charts: true, charts: true,
// 详情设置收缩为true // 详情设置收缩为true
details: false, details: false,
// 组件列表展示类型(默认单列) // 组件列表展示类型(默认单列)
chartType: ChartModeEnum.SINGLE, chartType: ChartModeEnum.SINGLE,
// 图层类型(默认图片) // 图层类型(默认图片)
layerType: LayerModeEnum.THUMBNAIL, layerType: LayerModeEnum.THUMBNAIL,
// 当前加载数量 // 当前加载数量
percentage: 0, percentage: 0,
// 是否重置当前画布位置 // 是否重置当前画布位置
rePositionCanvas: false, rePositionCanvas: false,
// 防止值不存在 // 防止值不存在
...storageChartLayout ...storageChartLayout
}), }),
getters: { getters: {
getLayers(): boolean { getLayers(): boolean {
return this.layers return this.layers
}, },
getCharts(): boolean { getCharts(): boolean {
return this.charts return this.charts
}, },
getDetails(): boolean { getDetails(): boolean {
return this.details return this.details
}, },
getChartType(): ChartModeEnum { getChartType(): ChartModeEnum {
return this.chartType return this.chartType
}, },
getLayerType(): LayerModeEnum { getLayerType(): LayerModeEnum {
return this.layerType return this.layerType
}, },
getPercentage(): number { getPercentage(): number {
return this.percentage return this.percentage
}, },
getRePositionCanvas(): boolean { getRePositionCanvas(): boolean {
return this.rePositionCanvas return this.rePositionCanvas
} }
}, },
actions: { actions: {
setItem<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(key: T, value: K): void { setItem<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(
this.$patch(state => { key: T,
state[key] = value value: K,
}) computedScale = true
// 存储本地 ): void {
setLocalStorage(GO_CHART_LAYOUT_STORE, this.$state) this.$patch(state => {
// 这里需要标记重置画布位置 state[key] = value
this.rePositionCanvas = true; })
// 重新计算拖拽区域缩放比例 // 存储本地
setTimeout(() => { setLocalStorage(GO_CHART_LAYOUT_STORE, this.$state)
chartEditStore.computedScale() // 这里需要标记重置画布位置
}, 500) this.rePositionCanvas = true;
}, // 重新计算拖拽区域缩放比例
setItemUnHandle<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(key: T, value: K): void { if (computedScale) {
this.$patch(state => { setTimeout(() => {
state[key] = value chartEditStore.computedScale()
}) }, 500)
} }
} },
}) setItemUnHandle<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(key: T, value: K): void {
this.$patch(state => {
state[key] = value
})
}
}
})

View File

@ -11,7 +11,7 @@
@update:value="clickItemHandle" @update:value="clickItemHandle"
></n-menu> ></n-menu>
<div class="chart-content-list"> <div class="chart-content-list">
<n-scrollbar> <n-scrollbar trigger="none">
<charts-item-box :menuOptions="packages.selectOptions"></charts-item-box> <charts-item-box :menuOptions="packages.selectOptions"></charts-item-box>
</n-scrollbar> </n-scrollbar>
</div> </div>
@ -119,6 +119,7 @@ $menuWidth: 65px;
@include fetch-bg-color('background-color2-shallow'); @include fetch-bg-color('background-color2-shallow');
} }
.chart-content-list { .chart-content-list {
width: 200px;
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -1,92 +1,92 @@
import { shallowReactive, ref } from 'vue' import { shallowReactive, ref } from 'vue'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { renderLang, renderIcon } from '@/utils' import { renderLang, renderIcon } from '@/utils'
import { themeColor, setItem, getCharts } from './useLayout.hook' import { themeColor, setItem, getCharts } from './useLayout.hook'
import { PackagesCategoryEnum, PackagesCategoryName, PackagesType } from '@/packages/index.d' import { PackagesCategoryEnum, PackagesCategoryName, PackagesType } from '@/packages/index.d'
// 图表 // 图表
import { usePackagesStore } from '@/store/modules/packagesStore/packagesStore' import { usePackagesStore } from '@/store/modules/packagesStore/packagesStore'
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d' import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
// 图标 // 图标
const { BarChartIcon } = icon.ionicons5 const { BarChartIcon } = icon.ionicons5
const { const {
TableSplitIcon, TableSplitIcon,
RoadmapIcon, RoadmapIcon,
SpellCheckIcon, SpellCheckIcon,
GraphicalDataFlowIcon, GraphicalDataFlowIcon,
} = icon.carbon } = icon.carbon
// 图表 // 图表
export type MenuOptionsType = { export type MenuOptionsType = {
key: string key: string
icon: ReturnType<typeof renderIcon> icon: ReturnType<typeof renderIcon>
label: ReturnType<typeof renderLang> label: ReturnType<typeof renderLang>
list: PackagesType list: PackagesType
} }
const { getPackagesList } = usePackagesStore() const { getPackagesList } = usePackagesStore()
const menuOptions: MenuOptionsType[] = [] const menuOptions: MenuOptionsType[] = []
const packagesListObj = { const packagesListObj = {
[PackagesCategoryEnum.CHARTS]: { [PackagesCategoryEnum.CHARTS]: {
icon: renderIcon(RoadmapIcon), icon: renderIcon(RoadmapIcon),
label: PackagesCategoryName.CHARTS, label: PackagesCategoryName.CHARTS,
}, },
[PackagesCategoryEnum.INFORMATIONS]: { [PackagesCategoryEnum.INFORMATIONS]: {
icon: renderIcon(SpellCheckIcon), icon: renderIcon(SpellCheckIcon),
label: PackagesCategoryName.INFORMATIONS, label: PackagesCategoryName.INFORMATIONS,
}, },
[PackagesCategoryEnum.TABLES]: { [PackagesCategoryEnum.TABLES]: {
icon: renderIcon(TableSplitIcon), icon: renderIcon(TableSplitIcon),
label: PackagesCategoryName.TABLES, label: PackagesCategoryName.TABLES,
}, },
[PackagesCategoryEnum.DECORATES]: { [PackagesCategoryEnum.DECORATES]: {
icon: renderIcon(GraphicalDataFlowIcon), icon: renderIcon(GraphicalDataFlowIcon),
label: PackagesCategoryName.DECORATES, label: PackagesCategoryName.DECORATES,
}, },
} }
// 处理列表 // 处理列表
const handlePackagesList = () => { const handlePackagesList = () => {
for (const val in getPackagesList) { for (const val in getPackagesList) {
menuOptions.push({ menuOptions.push({
key: val, key: val,
// @ts-ignore // @ts-ignore
icon: packagesListObj[val].icon, icon: packagesListObj[val].icon,
// @ts-ignore // @ts-ignore
label: packagesListObj[val].label, label: packagesListObj[val].label,
// @ts-ignore // @ts-ignore
list: getPackagesList[val], list: getPackagesList[val],
}) })
} }
} }
handlePackagesList() handlePackagesList()
// 记录选中值 // 记录选中值
let beforeSelect: string = menuOptions[0]['key'] let beforeSelect: string = menuOptions[0]['key']
const selectValue = ref<string>(menuOptions[0]['key']) const selectValue = ref<string>(menuOptions[0]['key'])
// 选中的对象值 // 选中的对象值
const selectOptions = ref(menuOptions[0]) const selectOptions = ref(menuOptions[0])
// 点击 item // 点击 item
const clickItemHandle = (key: string, item: any) => { const clickItemHandle = (key: string, item: any) => {
selectOptions.value = item selectOptions.value = item
// 处理折叠 // 处理折叠
if (beforeSelect === key) { if (beforeSelect === key) {
setItem(ChartLayoutStoreEnum.CHARTS, !getCharts.value) setItem(ChartLayoutStoreEnum.CHARTS, !getCharts.value, false)
} else { } else {
setItem(ChartLayoutStoreEnum.CHARTS, true) setItem(ChartLayoutStoreEnum.CHARTS, true, false)
} }
beforeSelect = key beforeSelect = key
} }
export { export {
getCharts, getCharts,
BarChartIcon, BarChartIcon,
themeColor, themeColor,
selectOptions, selectOptions,
selectValue, selectValue,
clickItemHandle, clickItemHandle,
menuOptions, menuOptions,
} }

View File

@ -1,196 +1,197 @@
<template> <template>
<div class="go-chart-configurations-data-ajax"> <div class="go-chart-configurations-data-ajax">
<n-card class="n-card-shallow"> <n-card class="n-card-shallow">
<setting-item-box name="请求配置"> <setting-item-box name="请求配置">
<setting-item name="类型"> <setting-item name="类型">
<n-tag :bordered="false" type="primary" style="border-radius: 5px"> <n-tag :bordered="false" type="primary" style="border-radius: 5px">
{{ targetData.request.requestContentType === RequestContentTypeEnum.DEFAULT ? '普通请求' : 'SQL请求' }} {{ targetData.request.requestContentType === RequestContentTypeEnum.DEFAULT ? '普通请求' : 'SQL请求' }}
</n-tag> </n-tag>
</setting-item> </setting-item>
<setting-item name="方式"> <setting-item name="方式">
<n-input size="small" :placeholder="targetData.request.requestHttpType || '暂无'" :disabled="true"></n-input> <n-input size="small" :placeholder="targetData.request.requestHttpType || '暂无'" :disabled="true"></n-input>
</setting-item> </setting-item>
<setting-item name="组件间隔"> <setting-item name="组件间隔">
<n-input size="small" :placeholder="`${targetData.request.requestInterval || '暂无'}`" :disabled="true"> <n-input size="small" :placeholder="`${targetData.request.requestInterval || '暂无'}`" :disabled="true">
<template #suffix> {{ SelectHttpTimeNameObj[targetData.request.requestIntervalUnit] }} </template> <template #suffix> {{ SelectHttpTimeNameObj[targetData.request.requestIntervalUnit] }} </template>
</n-input> </n-input>
</setting-item> </setting-item>
<setting-item name="全局间隔(默认)"> <setting-item name="全局间隔(默认)">
<n-input size="small" :placeholder="`${GlobalRequestInterval || '暂无'} `" :disabled="true"> <n-input size="small" :placeholder="`${GlobalRequestInterval || '暂无'} `" :disabled="true">
<template #suffix> {{ SelectHttpTimeNameObj[GlobalRequestIntervalUnit] }} </template> <template #suffix> {{ SelectHttpTimeNameObj[GlobalRequestIntervalUnit] }} </template>
</n-input> </n-input>
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="源地址" :alone="true"> <setting-item-box name="源地址" :alone="true">
<n-input size="small" :placeholder="requestOriginUrl || '暂无'" :disabled="true"> <n-input size="small" :placeholder="requestOriginUrl || '暂无'" :disabled="true">
<template #prefix> <template #prefix>
<n-icon :component="PulseIcon" /> <n-icon :component="PulseIcon" />
</template> </template>
</n-input> </n-input>
</setting-item-box> </setting-item-box>
<setting-item-box name="组件地址" :alone="true"> <setting-item-box name="组件地址" :alone="true">
<n-input size="small" :placeholder="targetData.request.requestUrl || '暂无'" :disabled="true"> <n-input size="small" :placeholder="targetData.request.requestUrl || '暂无'" :disabled="true">
<template #prefix> <template #prefix>
<n-icon :component="FlashIcon" /> <n-icon :component="FlashIcon" />
</template> </template>
</n-input> </n-input>
</setting-item-box> </setting-item-box>
<div class="edit-text" @click="requestModelHandle"> <div class="edit-text" @click="requestModelHandle">
<div class="go-absolute-center"> <div class="go-absolute-center">
<n-button type="primary" secondary>编辑配置</n-button> <n-button type="primary" secondary>编辑配置</n-button>
</div> </div>
</div> </div>
</n-card> </n-card>
<setting-item-box :alone="true"> <setting-item-box :alone="true">
<template #name> <template #name>
测试 测试
<n-tooltip trigger="hover"> <n-tooltip trigger="hover">
<template #trigger> <template #trigger>
<n-icon size="21" :depth="3"> <n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon> <help-outline-icon></help-outline-icon>
</n-icon> </n-icon>
</template> </template>
默认赋值给 dataset 字段 默认赋值给 dataset 字段
</n-tooltip> </n-tooltip>
</template> </template>
<n-button type="primary" ghost @click="sendHandle"> <n-button type="primary" ghost @click="sendHandle">
<template #icon> <template #icon>
<n-icon> <n-icon>
<flash-icon /> <flash-icon />
</n-icon> </n-icon>
</template> </template>
发送请求 发送请求
</n-button> </n-button>
</setting-item-box> </setting-item-box>
<!-- 底部数据展示 --> <!-- 底部数据展示 -->
<chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show> <chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show>
<!-- 骨架图 --> <!-- 骨架图 -->
<go-skeleton :load="loading" :repeat="3"></go-skeleton> <go-skeleton :load="loading" :repeat="3"></go-skeleton>
<!-- 请求配置model --> <!-- 请求配置model -->
<chart-data-request <chart-data-request
v-model:modelShow="requestShow" v-model:modelShow="requestShow"
:targetData="targetData" :targetData="targetData"
@sendHandle="sendHandle" @sendHandle="sendHandle"
></chart-data-request> ></chart-data-request>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, toRefs, computed, onBeforeUnmount, watchEffect, toRaw } from 'vue' import { ref, toRefs, computed, onBeforeUnmount, watchEffect, toRaw } from 'vue'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { useDesignStore } from '@/store/modules/designStore/designStore' import { useDesignStore } from '@/store/modules/designStore/designStore'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { ChartDataRequest } from '../ChartDataRequest/index' import { ChartDataRequest } from '../ChartDataRequest/index'
import { RequestHttpEnum, ResultEnum, SelectHttpTimeNameObj, RequestContentTypeEnum } from '@/enums/httpEnum' import { RequestHttpEnum, ResultEnum, SelectHttpTimeNameObj, RequestContentTypeEnum } from '@/enums/httpEnum'
import { chartDataUrl, rankListUrl, scrollBoardUrl, numberFloatUrl, numberIntUrl, textUrl, imageUrl } from '@/api/mock' import { chartDataUrl, rankListUrl, scrollBoardUrl, numberFloatUrl, numberIntUrl, textUrl, imageUrl } from '@/api/mock'
import { http, customizeHttp } from '@/api/http' import { http, customizeHttp } from '@/api/http'
import { SelectHttpType } from '../../index.d' import { SelectHttpType } from '../../index.d'
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow' import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
import { useTargetData } from '../../../hooks/useTargetData.hook' import { useTargetData } from '../../../hooks/useTargetData.hook'
import { newFunctionHandle } from '@/utils' import { newFunctionHandle } from '@/utils'
const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5 const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData() const { targetData, chartEditStore } = useTargetData()
const { const {
requestOriginUrl, requestOriginUrl,
requestInterval: GlobalRequestInterval, requestInterval: GlobalRequestInterval,
requestIntervalUnit: GlobalRequestIntervalUnit requestIntervalUnit: GlobalRequestIntervalUnit
} = toRefs(chartEditStore.getRequestGlobalConfig) } = toRefs(chartEditStore.getRequestGlobalConfig)
const designStore = useDesignStore() const designStore = useDesignStore()
// //
const loading = ref(false) const loading = ref(false)
const requestShow = ref(false) const requestShow = ref(false)
const showMatching = ref(false) const showMatching = ref(false)
let firstFocus = 0 let firstFocus = 0
let lastFilter: any = undefined let lastFilter: any = undefined
// model // model
const requestModelHandle = () => { const requestModelHandle = () => {
requestShow.value = true requestShow.value = true
} }
// //
const sendHandle = async () => { const sendHandle = async () => {
if (!targetData.value?.request) return if (!targetData.value?.request) return
loading.value = true loading.value = true
try { try {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig)) const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
loading.value = false loading.value = false
if (res) { if (res) {
if (!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!') const { data } = res
targetData.value.option.dataset = newFunctionHandle(res?.data, res, targetData.value.filter) if (!data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
showMatching.value = true targetData.value.option.dataset = newFunctionHandle(data, res, targetData.value.filter)
return showMatching.value = true
} return
window['$message'].warning('没有拿到返回值,请检查接口!') }
} catch (error) { window['$message'].warning('没有拿到返回值,请检查接口!')
console.error(error); } catch (error) {
loading.value = false console.error(error);
window['$message'].warning('数据异常,请检查参数!') loading.value = false
} window['$message'].warning('数据异常,请检查参数!')
} }
}
//
const themeColor = computed(() => { //
return designStore.getAppTheme const themeColor = computed(() => {
}) return designStore.getAppTheme
})
watchEffect(() => {
const filter = targetData.value?.filter watchEffect(() => {
if (lastFilter !== filter && firstFocus) { const filter = targetData.value?.filter
lastFilter = filter if (lastFilter !== filter && firstFocus) {
sendHandle() lastFilter = filter
} sendHandle()
firstFocus++ }
}) firstFocus++
})
onBeforeUnmount(() => {
lastFilter = null onBeforeUnmount(() => {
}) lastFilter = null
</script> })
</script>
<style lang="scss" scoped>
@include go('chart-configurations-data-ajax') { <style lang="scss" scoped>
.n-card-shallow { @include go('chart-configurations-data-ajax') {
&.n-card { .n-card-shallow {
@extend .go-background-filter; &.n-card {
@include deep() { @extend .go-background-filter;
.n-card__content { @include deep() {
padding: 10px; .n-card__content {
} padding: 10px;
} }
} }
.edit-text { }
position: absolute; .edit-text {
top: 0px; position: absolute;
left: 0px; top: 0px;
width: 325px; left: 0px;
height: 270px; width: 325px;
cursor: pointer; height: 270px;
opacity: 0; cursor: pointer;
transition: all 0.3s; opacity: 0;
@extend .go-background-filter; transition: all 0.3s;
backdrop-filter: blur(2px) !important; @extend .go-background-filter;
} backdrop-filter: blur(2px) !important;
&:hover { }
border-color: v-bind('themeColor'); &:hover {
.edit-text { border-color: v-bind('themeColor');
opacity: 1; .edit-text {
} opacity: 1;
} }
} }
} }
</style> }
</style>

View File

@ -1,215 +1,215 @@
<template> <template>
<template v-if="targetData.filter"> <template v-if="targetData.filter">
<n-card> <n-card>
<p><span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{</p> <p><span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{</p>
<!-- 函数体 --> <!-- 函数体 -->
<div class="go-ml-4"> <div class="go-ml-4">
<n-code :code="targetData.filter" language="typescript"></n-code> <n-code :code="targetData.filter" language="typescript"></n-code>
</div> </div>
<p>}</p> <p>}</p>
<template #footer> <template #footer>
<n-space justify="end"> <n-space justify="end">
<n-button type="primary" tertiary size="small" @click="addFilter"> <n-button type="primary" tertiary size="small" @click="addFilter">
<template #icon> <template #icon>
<n-icon> <n-icon>
<filter-edit-icon /> <filter-edit-icon />
</n-icon> </n-icon>
</template> </template>
编辑 编辑
</n-button> </n-button>
<n-button tertiary size="small" @click="delFilter"> 删除 </n-button> <n-button tertiary size="small" @click="delFilter"> 删除 </n-button>
</n-space> </n-space>
</template> </template>
</n-card> </n-card>
</template> </template>
<template v-else> <template v-else>
<n-button class="go-ml-3" @click="addFilter"> <n-button class="go-ml-3" @click="addFilter">
<template #icon> <template #icon>
<n-icon> <n-icon>
<filter-icon /> <filter-icon />
</n-icon> </n-icon>
</template> </template>
新增过滤器 新增过滤器
</n-button> </n-button>
</template> </template>
<!-- 弹窗 --> <!-- 弹窗 -->
<n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false" :closeOnEsc="false"> <n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 600px"> <n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 600px">
<template #header> <template #header>
<n-space> <n-space>
<n-text>过滤器函数编辑器</n-text> <n-text>过滤器函数编辑器</n-text>
</n-space> </n-space>
</template> </template>
<template #header-extra> </template> <template #header-extra> </template>
<n-space size="small" vertical> <n-space size="small" vertical>
<n-space justify="space-between"> <n-space justify="space-between">
<div> <div>
<n-space vertical> <n-space vertical>
<n-tag type="info"> <n-tag type="info">
<span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{ <span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{
</n-tag> </n-tag>
<monaco-editor v-model:modelValue="filter" width="460px" height="380px" language="javascript" /> <monaco-editor v-model:modelValue="filter" width="460px" height="380px" language="javascript" />
<n-tag type="info">}</n-tag> <n-tag type="info">}</n-tag>
</n-space> </n-space>
</div> </div>
<n-divider vertical style="height: 480px" /> <n-divider vertical style="height: 480px" />
<n-scrollbar style="max-height: 480px"> <n-scrollbar style="max-height: 480px">
<n-space :size="15" vertical> <n-space :size="15" vertical>
<div class="editor-data-show"> <div class="editor-data-show">
<n-space> <n-space>
<n-text depth="3">默认过滤数据(data)</n-text> <n-text depth="3">默认过滤数据(data)</n-text>
<n-code :code="toString(sourceData?.data) || '暂无'" language="json" :word-wrap="true"></n-code> <n-code :code="toString(sourceData?.data) || '暂无'" language="json" :word-wrap="true"></n-code>
</n-space> </n-space>
</div> </div>
<div class="editor-data-show"> <div class="editor-data-show">
<n-space> <n-space>
<n-text depth="3">接口返回数据(res)</n-text> <n-text depth="3">接口返回数据(res)</n-text>
<n-code :code="toString(sourceData) || '暂无'" language="json" :word-wrap="true"></n-code> <n-code :code="toString(sourceData) || '暂无'" language="json" :word-wrap="true"></n-code>
</n-space> </n-space>
</div> </div>
<div class="editor-data-show"> <div class="editor-data-show">
<n-space> <n-space>
<n-text depth="3">过滤器结果</n-text> <n-text depth="3">过滤器结果</n-text>
<n-code :code="filterRes || '暂无'" language="json" :word-wrap="true"></n-code> <n-code :code="filterRes || '暂无'" language="json" :word-wrap="true"></n-code>
</n-space> </n-space>
</div> </div>
</n-space> </n-space>
</n-scrollbar> </n-scrollbar>
</n-space> </n-space>
</n-space> </n-space>
<template #action> <template #action>
<n-space justify="space-between"> <n-space justify="space-between">
<div class="go-flex-items-center"> <div class="go-flex-items-center">
<n-tag :bordered="false" type="primary"> <n-tag :bordered="false" type="primary">
<template #icon> <template #icon>
<n-icon :component="DocumentTextIcon" /> <n-icon :component="DocumentTextIcon" />
</template> </template>
规则 规则
</n-tag> </n-tag>
<n-text class="go-ml-2" depth="2">过滤器默认处理接口返回值的data字段</n-text> <n-text class="go-ml-2" depth="2">过滤器默认处理接口返回值的data字段</n-text>
</div> </div>
<n-space> <n-space>
<n-button size="medium" @click="closeFilter">取消</n-button> <n-button size="medium" @click="closeFilter">取消</n-button>
<n-button size="medium" type="primary" @click="saveFilter">保存</n-button> <n-button size="medium" type="primary" @click="saveFilter">保存</n-button>
</n-space> </n-space>
</n-space> </n-space>
</template> </template>
</n-card> </n-card>
</n-modal> </n-modal>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed, watch, toRef, toRefs, toRaw, reactive } from 'vue' import { ref, computed, watch, toRef, toRefs, toRaw, reactive } from 'vue'
import { useTargetData } from '../../../hooks/useTargetData.hook' import { useTargetData } from '../../../hooks/useTargetData.hook'
import { MonacoEditor } from '@/components/Pages/MonacoEditor' import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { goDialog, toString } from '@/utils' import { goDialog, toString } from '@/utils'
import { customizeHttp } from '@/api/http' import { customizeHttp } from '@/api/http'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
const { DocumentTextIcon } = icon.ionicons5 const { DocumentTextIcon } = icon.ionicons5
const { FilterIcon, FilterEditIcon } = icon.carbon const { FilterIcon, FilterEditIcon } = icon.carbon
const { targetData, chartEditStore } = useTargetData() const { targetData, chartEditStore } = useTargetData()
const { requestDataType } = toRefs(targetData.value.request) const { requestDataType } = toRefs(targetData.value.request)
const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig) const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig)
// //
const showModal = ref(false) const showModal = ref(false)
// filter // filter
const filter = ref(targetData.value.filter || `return data`) const filter = ref(targetData.value.filter || `return data`)
// //
const errorFlag = ref(false) const errorFlag = ref(false)
// / // /
const sourceData = ref<any>('') const sourceData = ref<any>('')
// //
const fetchTargetData = async () => { const fetchTargetData = async () => {
try { try {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig)) const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
if (res) { if (res) {
sourceData.value = res sourceData.value = res
return return
} }
window['$message'].warning('没有拿到返回值,请检查接口!') window['$message'].warning('没有拿到返回值,请检查接口!')
} catch (error) { } catch (error) {
console.error(error); console.error(error);
window['$message'].warning('数据异常,请检查参数!') window['$message'].warning('数据异常,请检查参数!')
} }
} }
// //
const filterRes = computed(() => { const filterRes = computed(() => {
try { try {
const fn = new Function('data', 'res', filter.value) const fn = new Function('data', 'res', filter.value)
const response = cloneDeep(sourceData.value) const response = cloneDeep(sourceData.value)
const res = fn(response?.data, response) const res = fn(response?.data, response)
// eslint-disable-next-line vue/no-side-effects-in-computed-properties // eslint-disable-next-line vue/no-side-effects-in-computed-properties
errorFlag.value = false errorFlag.value = false
return toString(res) return toString(res)
} catch (error) { } catch (error) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties // eslint-disable-next-line vue/no-side-effects-in-computed-properties
errorFlag.value = true errorFlag.value = true
return `过滤函数错误,日志:${error}` return `过滤函数错误,日志:${error}`
} }
}) })
// //
const addFilter = () => { const addFilter = () => {
showModal.value = true showModal.value = true
} }
// //
const delFilter = () => { const delFilter = () => {
goDialog({ goDialog({
message: '是否删除过滤器', message: '是否删除过滤器',
onPositiveCallback: () => { onPositiveCallback: () => {
targetData.value.filter = undefined targetData.value.filter = undefined
} }
}) })
} }
// //
const closeFilter = () => { const closeFilter = () => {
showModal.value = false showModal.value = false
} }
// //
const saveFilter = () => { const saveFilter = () => {
if (errorFlag.value) { if (errorFlag.value) {
window['$message'].error('过滤函数错误,无法进行保存') window['$message'].error('过滤函数错误,无法进行保存')
return return
} }
targetData.value.filter = filter.value targetData.value.filter = filter.value
closeFilter() closeFilter()
} }
watch( watch(
() => showModal.value, () => showModal.value,
(newData: boolean) => { (newData: boolean) => {
if (newData) { if (newData) {
fetchTargetData() fetchTargetData()
filter.value = targetData.value.filter || `return data` filter.value = targetData.value.filter || `return data`
} }
} }
) )
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.func-keyword { .func-keyword {
color: #b478cf; color: #b478cf;
} }
@include go('chart-data-monaco-editor') { @include go('chart-data-monaco-editor') {
&.n-card.n-modal, &.n-card.n-modal,
.n-card { .n-card {
@extend .go-background-filter; @extend .go-background-filter;
} }
.editor-data-show { .editor-data-show {
@include fetch-bg-color('filter-color'); @include fetch-bg-color('filter-color');
width: 420px; width: 420px;
padding: 20px; padding: 20px;
border-radius: 5px; border-radius: 5px;
} }
} }
</style> </style>

View File

@ -58,7 +58,7 @@
<help-outline-icon></help-outline-icon> <help-outline-icon></help-outline-icon>
</n-icon> </n-icon>
</template> </template>
<n-text>不支持静态组件分组</n-text> <n-text>不支持静态组件</n-text>
</n-tooltip> </n-tooltip>
</template> </template>
<n-select <n-select
@ -169,7 +169,27 @@ const fnDimensionsAndSource = (interactOn: InteractEventOn | undefined) => {
// //
const fnEventsOptions = (): Array<SelectOption | SelectGroupOption> => { const fnEventsOptions = (): Array<SelectOption | SelectGroupOption> => {
const filterOptionList = chartEditStore.componentList.filter(item => { //
const fnFlattern = (
data: Array<CreateComponentType | CreateComponentGroupType>
): Array<CreateComponentType | CreateComponentGroupType> => {
return data.reduce(
(
iter: Array<CreateComponentType | CreateComponentGroupType>,
val: CreateComponentType | CreateComponentGroupType
) => {
if (val.groupList && val.groupList.length > 0) {
iter.push(val)
} else {
iter.push(val)
}
return val.groupList ? [...iter, ...fnFlattern(val.groupList)] : iter
},
[]
)
}
const filterOptionList = fnFlattern(chartEditStore.componentList).filter(item => {
// //
const isNotSelf = item.id !== targetData.value.id const isNotSelf = item.id !== targetData.value.id
// //

View File

@ -23,6 +23,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, PropType } from 'vue' import { computed, PropType } from 'vue'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useDesignStore } from '@/store/modules/designStore/designStore' import { useDesignStore } from '@/store/modules/designStore/designStore'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { useSizeStyle, usePointStyle } from '../../hooks/useStyle.hook' import { useSizeStyle, usePointStyle } from '../../hooks/useStyle.hook'
@ -55,6 +57,9 @@ const themeColor = computed(() => {
// //
const hover = computed(() => { const hover = computed(() => {
const isDrag = chartEditStore.getEditCanvas[EditCanvasTypeEnum.IS_DRAG]
if (isDrag) return false
if (props.item.status.lock) return false if (props.item.status.lock) return false
return props.item.id === chartEditStore.getTargetChart.hoverId return props.item.id === chartEditStore.getTargetChart.hoverId
}) })

View File

@ -5,8 +5,9 @@ import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStor
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
// 布局处理 // 布局处理
export const useLayout = () => { export const useLayout = (fn: () => Promise<void>) => {
onMounted(() => { let removeScale: Function = () => { }
onMounted(async () => {
// 设置 Dom 值(ref 不生效先用 document) // 设置 Dom 值(ref 不生效先用 document)
chartEditStore.setEditCanvas( chartEditStore.setEditCanvas(
EditCanvasTypeEnum.EDIT_LAYOUT_DOM, EditCanvasTypeEnum.EDIT_LAYOUT_DOM,
@ -17,13 +18,16 @@ export const useLayout = () => {
document.getElementById('go-chart-edit-content') document.getElementById('go-chart-edit-content')
) )
// 获取数据
await fn()
// 监听初始化 // 监听初始化
const removeScale = chartEditStore.listenerScale() removeScale = chartEditStore.listenerScale()
onUnmounted(() => { })
chartEditStore.setEditCanvas(EditCanvasTypeEnum.EDIT_LAYOUT_DOM, null)
chartEditStore.setEditCanvas(EditCanvasTypeEnum.EDIT_CONTENT_DOM, null) onUnmounted(() => {
removeScale() chartEditStore.setEditCanvas(EditCanvasTypeEnum.EDIT_LAYOUT_DOM, null)
}) chartEditStore.setEditCanvas(EditCanvasTypeEnum.EDIT_CONTENT_DOM, null)
removeScale()
}) })
} }

View File

@ -109,10 +109,10 @@ const chartEditStore = useChartEditStore()
const { handleContextMenu } = useContextMenu() const { handleContextMenu } = useContextMenu()
// scale // scale
provide(SCALE_KEY, null); provide(SCALE_KEY, null)
// //
useLayout() useLayout(async () => {})
// //
const { mouseenterHandle, mouseleaveHandle, mousedownHandle, mouseClickHandle } = useMouseHandle() const { mouseenterHandle, mouseleaveHandle, mousedownHandle, mouseClickHandle } = useMouseHandle()

View File

@ -185,6 +185,11 @@ export const useSync = () => {
} else { } else {
await create(comItem as CreateComponentType) await create(comItem as CreateComponentType)
} }
if (percentage === 100) {
// 清除历史记录
chartHistoryStore.clearBackStack()
chartHistoryStore.clearForwardStack()
}
} }
} else { } else {
// 非组件(顺便排除脏数据) // 非组件(顺便排除脏数据)

View File

@ -131,20 +131,6 @@ const selectOptions = ref([
key: 'preview', key: 'preview',
icon: renderIcon(BrowsersOutlineIcon) icon: renderIcon(BrowsersOutlineIcon)
}, },
{
label: renderLang('global.r_copy'),
key: 'copy',
icon: renderIcon(CopyIcon)
},
{
label: renderLang('global.r_rename'),
key: 'rename',
icon: renderIcon(PencilIcon)
},
{
type: 'divider',
key: 'd1'
},
{ {
label: props.cardData?.release label: props.cardData?.release
? renderLang('global.r_unpublish') ? renderLang('global.r_unpublish')
@ -152,15 +138,6 @@ const selectOptions = ref([
key: 'send', key: 'send',
icon: renderIcon(SendIcon) icon: renderIcon(SendIcon)
}, },
{
label: renderLang('global.r_download'),
key: 'download',
icon: renderIcon(DownloadIcon)
},
{
type: 'divider',
key: 'd2'
},
{ {
label: renderLang('global.r_delete'), label: renderLang('global.r_delete'),
key: 'delete', key: 'delete',