feat: 合并1.3.1的内容

This commit is contained in:
奔跑的面条 2024-03-14 12:07:41 +08:00
parent 5588205d8d
commit a4cd1f31b5
12 changed files with 756 additions and 509 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "go-view", "name": "go-view",
"version": "1.3.0", "version": "1.3.1",
"engines": { "engines": {
"node": ">=12.0" "node": ">=12.0"
}, },

View File

@ -16,8 +16,7 @@ export enum ThemeEnum {
MACARON = 'macaron', MACARON = 'macaron',
BLUE = 'blue', BLUE = 'blue',
DARKBLUE = 'darkblue', DARKBLUE = 'darkblue',
WINE = 'wine', WINE = 'wine'
WEIXIN = 'tileLayer'
} }
export enum LangEnum { export enum LangEnum {
@ -31,6 +30,11 @@ export enum ViewModeEnum {
STEREOSCOPIC = '3D' STEREOSCOPIC = '3D'
} }
export const ShowHideEnum = {
SHOW: true,
HIDE: false
}
export enum FeaturesEnum { export enum FeaturesEnum {
BG = 'bg', BG = 'bg',
POINT = 'point', POINT = 'point',
@ -71,6 +75,25 @@ export const option = {
}, },
mapMarkerType: MarkerEnum.CIRCLE_MARKER, mapMarkerType: MarkerEnum.CIRCLE_MARKER,
viewMode: ViewModeEnum.PLANE, viewMode: ViewModeEnum.PLANE,
showLabel: ShowHideEnum.SHOW,
satelliteTileLayer: {
show: ShowHideEnum.HIDE,
zIndex: 1,
opacity: 1,
zooms: [3, 18]
},
roadNetTileLayer: {
show: ShowHideEnum.HIDE,
zIndex: 2,
opacity: 1,
zooms: [3, 18]
},
trafficTileLayer: {
show: ShowHideEnum.HIDE,
zIndex: 3,
opacity: 1,
zooms: [3, 18]
},
lang: LangEnum.ZH_CN, lang: LangEnum.ZH_CN,
features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING] features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING]
} }

View File

@ -22,13 +22,21 @@
<n-select size="small" v-model:value="optionData.mapOptions.amapStyleKey" :options="themeOptions" /> <n-select size="small" v-model:value="optionData.mapOptions.amapStyleKey" :options="themeOptions" />
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
<setting-item-box name="内容" :alone="true"> <setting-item-box name="显示要素" :alone="true">
<n-checkbox-group v-model:value="optionData.mapOptions.features"> <n-checkbox-group v-model:value="optionData.mapOptions.features">
<n-space item-style="display: flex;"> <n-space item-style="display: flex;">
<n-checkbox :value="item.value" :label="item.label" v-for="(item, index) in featuresOptions" :key="index" /> <n-checkbox :value="item.value" :label="item.label" v-for="(item, index) in featuresOptions" :key="index" />
</n-space> </n-space>
</n-checkbox-group> </n-checkbox-group>
</setting-item-box> </setting-item-box>
<setting-item-box name="文字标注" :alone="true">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.mapOptions.showLabel" size="small" />
<n-text>是否显示</n-text>
</n-space>
</setting-item>
</setting-item-box>
<setting-item-box name="位置"> <setting-item-box name="位置">
<setting-item name="经度"> <setting-item name="经度">
<n-input-number v-model:value="optionData.mapOptions.amapLon" :show-button="false" size="small"> <n-input-number v-model:value="optionData.mapOptions.amapLon" :show-button="false" size="small">
@ -76,11 +84,94 @@
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
</collapse-item> </collapse-item>
<collapse-item name="图层" :expanded="true">
<setting-item-box name="卫星图层">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.mapOptions.satelliteTileLayer.show" size="small" />
<n-text>是否显示</n-text>
</n-space>
</setting-item>
<setting-item name="叠加顺序值">
<n-input-number
v-model:value="optionData.mapOptions.satelliteTileLayer.zIndex"
:min="0"
size="small"
></n-input-number>
</setting-item>
<setting-item name="透明度">
<n-input-number
v-model:value="optionData.mapOptions.satelliteTileLayer.opacity"
:min="0"
:max="1"
step="0.1"
size="small"
></n-input-number>
</setting-item>
<setting-item name="缩放级别范围">
<n-slider v-model:value="optionData.mapOptions.satelliteTileLayer.zooms" range :step="1" :max="18" :min="3" />
</setting-item>
</setting-item-box>
<setting-item-box name="路网图层">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.mapOptions.roadNetTileLayer.show" size="small" />
<n-text>是否显示</n-text>
</n-space>
</setting-item>
<setting-item name="叠加顺序值">
<n-input-number
v-model:value="optionData.mapOptions.roadNetTileLayer.zIndex"
:min="0"
size="small"
></n-input-number>
</setting-item>
<setting-item name="透明度">
<n-input-number
v-model:value="optionData.mapOptions.roadNetTileLayer.opacity"
:min="0"
:max="1"
step="0.1"
size="small"
></n-input-number>
</setting-item>
<setting-item name="缩放级别范围">
<n-slider v-model:value="optionData.mapOptions.roadNetTileLayer.zooms" range :step="1" :max="18" :min="3" />
</setting-item>
</setting-item-box>
<setting-item-box name="实时交通">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.mapOptions.trafficTileLayer.show" size="small" />
<n-text>是否显示</n-text>
</n-space>
</setting-item>
<setting-item name="叠加顺序值">
<n-input-number
v-model:value="optionData.mapOptions.trafficTileLayer.zIndex"
:min="0"
size="small"
></n-input-number>
</setting-item>
<setting-item name="透明度">
<n-input-number
v-model:value="optionData.mapOptions.trafficTileLayer.opacity"
:min="0"
:max="1"
step="0.1"
size="small"
></n-input-number>
</setting-item>
<setting-item name="缩放级别范围">
<n-slider v-model:value="optionData.mapOptions.trafficTileLayer.zooms" range :step="1" :max="18" :min="3" />
</setting-item>
</setting-item-box>
</collapse-item>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from 'vue' import { PropType } from 'vue'
import { option, MarkerEnum, ThemeEnum, LangEnum, ViewModeEnum, FeaturesEnum } from './config' import { option, MarkerEnum, ThemeEnum, LangEnum, ViewModeEnum, ShowHideEnum, FeaturesEnum } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
defineProps({ defineProps({
@ -134,10 +225,6 @@ const themeOptions = [
{ {
value: ThemeEnum.WINE, value: ThemeEnum.WINE,
label: '酱籽' label: '酱籽'
},
{
value: ThemeEnum.WEIXIN,
label: '卫星'
} }
] ]
@ -170,19 +257,19 @@ const viewModeOptions = [
const featuresOptions = [ const featuresOptions = [
{ {
value: FeaturesEnum.BG, value: FeaturesEnum.BG,
label: '显示地图背景' label: '区域面'
}, },
{ {
value: FeaturesEnum.POINT, value: FeaturesEnum.POINT,
label: '显示标识' label: '标注'
}, },
{ {
value: FeaturesEnum.ROAD, value: FeaturesEnum.ROAD,
label: '显示道路' label: '道路'
}, },
{ {
value: FeaturesEnum.BUILDING, value: FeaturesEnum.BUILDING,
label: '显示建筑' label: '建筑'
} }
] ]

View File

@ -28,9 +28,13 @@ let {
amapStyleKeyCustom, amapStyleKeyCustom,
features, features,
viewMode, viewMode,
showLabel,
pitch, pitch,
skyColor, skyColor,
marker marker,
satelliteTileLayer,
roadNetTileLayer,
trafficTileLayer
} = toRefs(props.chartConfig.option.mapOptions) } = toRefs(props.chartConfig.option.mapOptions)
let mapIns: any = null let mapIns: any = null
@ -42,7 +46,7 @@ const initMap = (newData: any) => {
// //
AMapLoader.load({ AMapLoader.load({
key: amapKey.value, //apikey--public使 key: amapKey.value, //apikey--public使
version: '1.4.8', // JSAPI 1.4.15 version: '1.4.15', // JSAPI 1.4.15
plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 使 plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 使
}) })
.then(AMap => { .then(AMap => {
@ -56,17 +60,40 @@ const initMap = (newData: any) => {
pitch: pitch.value, // 0 - 83 pitch: pitch.value, // 0 - 83
skyColor: skyColor.value, skyColor: skyColor.value,
viewMode: viewMode.value, // viewMode: viewMode.value, //
showLabel: showLabel.value, //
willReadFrequently: true willReadFrequently: true
}) })
dataHandle(props.chartConfig.option.dataset) dataHandle(props.chartConfig.option.dataset)
let satellite = new AMap.TileLayer.Satellite()
let roadNet = new AMap.TileLayer.RoadNet() let satelliteLayer = new AMap.TileLayer.Satellite({
if (newData.amapStyleKey === ThemeEnum.WEIXIN) { zIndex: satelliteTileLayer.value.zIndex,
mapIns.add([satellite, roadNet]) opacity: satelliteTileLayer.value.opacity,
} else { zooms: satelliteTileLayer.value.zooms
mapIns.remove([satellite, roadNet]) })
mapIns.setMapStyle(`amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}`) let roadNetLayer = new AMap.TileLayer.RoadNet({
zIndex: roadNetTileLayer.value.zIndex,
opacity: roadNetTileLayer.value.opacity,
zooms: roadNetTileLayer.value.zooms
})
let trafficLayer = new AMap.TileLayer.Traffic({
zIndex: trafficTileLayer.value.zIndex,
opacity: trafficTileLayer.value.opacity,
zooms: trafficTileLayer.value.zooms
})
mapIns.remove([satelliteLayer, roadNetLayer, trafficLayer])
if (satelliteTileLayer.value.show) {
mapIns.add([satelliteLayer])
} }
if (roadNetTileLayer.value.show) {
mapIns.add([roadNetLayer])
}
if (trafficTileLayer.value.show) {
mapIns.add([trafficLayer])
}
mapIns.setMapStyle(
`amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}`
)
}) })
.catch(e => {}) .catch(e => {})
} }

View File

@ -171,7 +171,19 @@ const backLevel = () => {
// //
const checkOrMap = async (newData: string) => { const checkOrMap = async (newData: string) => {
await getGeojson(newData) if (newData === 'china') {
if (props.chartConfig.option.mapRegion.showHainanIsLands) {
//
hainanLandsHandle(true)
vEchartsSetOption()
} else {
//
hainanLandsHandle(false)
vEchartsSetOption()
}
} else {
await getGeojson(newData)
}
props.chartConfig.option.geo.map = newData props.chartConfig.option.geo.map = newData
props.chartConfig.option.series.forEach((item: any) => { props.chartConfig.option.series.forEach((item: any) => {
if (item.type === 'map') item.map = newData if (item.type === 'map') item.map = newData

View File

@ -1,81 +1,80 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public' import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { ScatterCommonConfig } from './index' import { ScatterCommonConfig } from './index'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json' import dataJson from './data.json'
export const includes = ['legend', 'xAxis', 'yAxis', 'grid'] export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
export const seriesItem = { export const seriesItem = {
type: 'scatter', type: 'scatter',
emphasis: { emphasis: {
focus: 'series' focus: 'series'
}, },
symbolSize: 12, symbolSize: 12,
markArea: { markArea: {
silent: true, silent: true,
itemStyle: { itemStyle: {
color: 'transparent', color: 'transparent',
borderWidth: 1, borderWidth: 1,
borderType: 'dashed' borderType: 'dashed'
}, },
data: [ data: [
[ [
{ {
xAxis: 'min', xAxis: 'min',
yAxis: 'min' yAxis: 'min'
}, },
{ {
xAxis: 'max', xAxis: 'max',
yAxis: 'max' yAxis: 'max'
} }
] ]
] ]
}, },
markPoint: { markPoint: {
symbol: 'pin', symbol: 'pin',
symbolSize: 50, symbolSize: 50,
data: [ data: [
{ type: 'max', name: 'Max' }, { type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' } { type: 'min', name: 'Min' }
] ]
} }
} }
export const option = { export const option = {
dataset: dataJson, dataset: dataJson,
tooltip: { tooltip: {
showDelay: 0, showDelay: 0,
formatter: (params: { value: string | any[]; seriesName: string; name: string }) => { formatter: (params: { value: string | any[]; seriesName: string; name: string }) => {
// console.log(params) return params.value.length > 1
return params.value.length > 1 ? `${params.seriesName}<br />${params.value[0]} ${params.value[1]}`
? `${params.seriesName}<br />${params.value[0]} ${params.value[1]}` : `${params.name} ${params.value}`
: `${params.seriesName}<br />${params.name} ${params.value}` },
}, axisPointer: {
axisPointer: { show: true,
show: true, type: 'cross',
type: 'cross', lineStyle: {
lineStyle: { type: 'dashed',
type: 'dashed', width: 1
width: 1 }
} }
} },
}, xAxis: {
xAxis: { scale: true
scale: true },
}, yAxis: {
yAxis: { scale: true
scale: true },
}, series: dataJson.map((item, index) => ({
series: dataJson.map((item, index) => ({ ...seriesItem,
...seriesItem, datasetIndex: index
datasetIndex: index }))
})) }
}
export default class Config extends PublicConfigClass implements CreateComponentType {
export default class Config extends PublicConfigClass implements CreateComponentType { public key = ScatterCommonConfig.key
public key = ScatterCommonConfig.key public chartConfig = cloneDeep(ScatterCommonConfig)
public chartConfig = cloneDeep(ScatterCommonConfig) // 图表配置项
// 图表配置项 public option = echartOptionProfixHandle(option, includes)
public option = echartOptionProfixHandle(option, includes) }
}

View File

@ -35,7 +35,7 @@
<!-- 弹窗 --> <!-- 弹窗 -->
<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: 1200px; height: 700px"> <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>
@ -49,12 +49,12 @@
<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="660px" height="500px" 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: 580px" /> <n-divider vertical style="height: 480px" />
<n-scrollbar style="max-height: 580px"> <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>

View File

@ -1,5 +1,5 @@
<template> <template>
<n-modal class="go-chart-data-pond-control" v-model:show="modelShowRef" :mask-closable="false"> <n-modal class="go-chart-data-pond-control" v-model:show="modelShowRef" :mask-closable="false" :close-on-esc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 900px; height: 650px"> <n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 900px; height: 650px">
<template #header></template> <template #header></template>
<template #header-extra> </template> <template #header-extra> </template>

View File

@ -1,392 +1,392 @@
import { toRaw } from 'vue' import { toRaw } from 'vue'
import { DragKeyEnum, MouseEventButton } from '@/enums/editPageEnum' import { DragKeyEnum, MouseEventButton } from '@/enums/editPageEnum'
import { createComponent } from '@/packages' import { createComponent } from '@/packages'
import { ConfigType } from '@/packages/index.d' import { ConfigType } from '@/packages/index.d'
import { CreateComponentType, CreateComponentGroupType, PickCreateComponentType } from '@/packages/index.d' import { CreateComponentType, CreateComponentGroupType, PickCreateComponentType } from '@/packages/index.d'
import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook' import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { loadingStart, loadingFinish, loadingError, setComponentPosition, JSONParse } from '@/utils' import { loadingStart, loadingFinish, loadingError, setComponentPosition, JSONParse } from '@/utils'
import { throttle, cloneDeep } from 'lodash' import { throttle, cloneDeep } from 'lodash'
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const { onClickOutSide } = useContextMenu() const { onClickOutSide } = useContextMenu()
// * 拖拽到编辑区域里 // * 拖拽到编辑区域里
export const dragHandle = async (e: DragEvent) => { export const dragHandle = async (e: DragEvent) => {
e.preventDefault() e.preventDefault()
try { try {
loadingStart() loadingStart()
// 获取拖拽数据 // 获取拖拽数据
const drayDataString = e!.dataTransfer!.getData(DragKeyEnum.DRAG_KEY) const drayDataString = e!.dataTransfer!.getData(DragKeyEnum.DRAG_KEY)
if (!drayDataString) { if (!drayDataString) {
loadingFinish() loadingFinish()
return return
} }
// 修改状态 // 修改状态
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CREATE, false) chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CREATE, false)
const dropData: Exclude<ConfigType, ['image']> = JSONParse(drayDataString) const dropData: Exclude<ConfigType, ['image']> = JSONParse(drayDataString)
if (dropData.disabled) return if (dropData.disabled) return
// 创建新图表组件 // 创建新图表组件
let newComponent: CreateComponentType = await createComponent(dropData) let newComponent: CreateComponentType = await createComponent(dropData)
if (dropData.redirectComponent) { if (dropData.redirectComponent) {
dropData.dataset && (newComponent.option.dataset = dropData.dataset) dropData.dataset && (newComponent.option.dataset = dropData.dataset)
newComponent.chartConfig.title = dropData.title newComponent.chartConfig.title = dropData.title
newComponent.chartConfig.chartFrame = dropData.chartFrame newComponent.chartConfig.chartFrame = dropData.chartFrame
} }
setComponentPosition(newComponent, e.offsetX - newComponent.attr.w / 2, e.offsetY - newComponent.attr.h / 2) setComponentPosition(newComponent, e.offsetX - newComponent.attr.w / 2, e.offsetY - newComponent.attr.h / 2)
chartEditStore.addComponentList(newComponent, false, true) chartEditStore.addComponentList(newComponent, false, true)
chartEditStore.setTargetSelectChart(newComponent.id) chartEditStore.setTargetSelectChart(newComponent.id)
loadingFinish() loadingFinish()
} catch (error) { } catch (error) {
loadingError() loadingError()
window['$message'].warning(`图表正在研发中, 敬请期待...`) window['$message'].warning(`图表正在研发中, 敬请期待...`)
} }
} }
// * 进入拖拽区域 // * 进入拖拽区域
export const dragoverHandle = (e: DragEvent) => { export const dragoverHandle = (e: DragEvent) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy' if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy'
} }
// * 不拦截默认行为点击 // * 不拦截默认行为点击
export const mousedownHandleUnStop = (e: MouseEvent, item?: CreateComponentType | CreateComponentGroupType) => { export const mousedownHandleUnStop = (e: MouseEvent, item?: CreateComponentType | CreateComponentGroupType) => {
if (item) { if (item) {
chartEditStore.setTargetSelectChart(item.id) chartEditStore.setTargetSelectChart(item.id)
return return
} }
chartEditStore.setTargetSelectChart(undefined) chartEditStore.setTargetSelectChart(undefined)
} }
// * 框选 // * 框选
export const mousedownBoxSelect = (e: MouseEvent, item?: CreateComponentType | CreateComponentGroupType) => { export const mousedownBoxSelect = (e: MouseEvent, item?: CreateComponentType | CreateComponentGroupType) => {
if (e.which == 2) return if (e.which == 2) return
if (window.$KeyboardActive?.space) return if (window.$KeyboardActive?.space) return
mousedownHandleUnStop(e) mousedownHandleUnStop(e)
// 记录点击初始位置 // 记录点击初始位置
const startOffsetX = e.offsetX const startOffsetX = e.offsetX
const startOffsetY = e.offsetY const startOffsetY = e.offsetY
const startScreenX = e.screenX const startScreenX = e.screenX
const startScreenY = e.screenY const startScreenY = e.screenY
// 记录缩放 // 记录缩放
const scale = chartEditStore.getEditCanvas.scale const scale = chartEditStore.getEditCanvas.scale
chartEditStore.setMousePosition(undefined, undefined, startOffsetX, startOffsetY) chartEditStore.setMousePosition(undefined, undefined, startOffsetX, startOffsetY)
// 移动框选 // 移动框选
const mousemove = throttle((moveEvent: MouseEvent) => { const mousemove = throttle((moveEvent: MouseEvent) => {
// 取消当前选中 // 取消当前选中
chartEditStore.setTargetSelectChart() chartEditStore.setTargetSelectChart()
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_SELECT, true) chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_SELECT, true)
// 这里先把相对值算好,不然组件无法获取 startScreenX 和 startScreenY 的值 // 这里先把相对值算好,不然组件无法获取 startScreenX 和 startScreenY 的值
const currX = startOffsetX + moveEvent.screenX - startScreenX const currX = startOffsetX + moveEvent.screenX - startScreenX
const currY = startOffsetY + moveEvent.screenY - startScreenY const currY = startOffsetY + moveEvent.screenY - startScreenY
chartEditStore.setMousePosition(currX, currY) chartEditStore.setMousePosition(currX, currY)
// 计算框选的左上角和右下角 // 计算框选的左上角和右下角
const selectAttr = { const selectAttr = {
// 左上角 // 左上角
x1: 0, x1: 0,
y1: 0, y1: 0,
// 右下角 // 右下角
x2: 0, x2: 0,
y2: 0 y2: 0
} }
if (currX > startOffsetX && currY > startOffsetY) { if (currX > startOffsetX && currY > startOffsetY) {
// 右下方向 // 右下方向
selectAttr.x1 = startOffsetX selectAttr.x1 = startOffsetX
selectAttr.y1 = startOffsetY selectAttr.y1 = startOffsetY
selectAttr.x2 = Math.round(startOffsetX + (moveEvent.screenX - startScreenX) / scale) selectAttr.x2 = Math.round(startOffsetX + (moveEvent.screenX - startScreenX) / scale)
selectAttr.y2 = Math.round(startOffsetY + (moveEvent.screenY - startScreenY) / scale) selectAttr.y2 = Math.round(startOffsetY + (moveEvent.screenY - startScreenY) / scale)
} else if (currX > startOffsetX && currY < startOffsetY) { } else if (currX > startOffsetX && currY < startOffsetY) {
// 右上方向 // 右上方向
selectAttr.x1 = startOffsetX selectAttr.x1 = startOffsetX
selectAttr.y1 = Math.round(startOffsetY - (startScreenY - moveEvent.screenY) / scale) selectAttr.y1 = Math.round(startOffsetY - (startScreenY - moveEvent.screenY) / scale)
selectAttr.x2 = Math.round(startOffsetX + (moveEvent.screenX - startScreenX) / scale) selectAttr.x2 = Math.round(startOffsetX + (moveEvent.screenX - startScreenX) / scale)
selectAttr.y2 = startOffsetY selectAttr.y2 = startOffsetY
} else if (currX < startOffsetX && currY > startOffsetY) { } else if (currX < startOffsetX && currY > startOffsetY) {
selectAttr.x1 = Math.round(startOffsetX - (startScreenX - moveEvent.screenX) / scale) selectAttr.x1 = Math.round(startOffsetX - (startScreenX - moveEvent.screenX) / scale)
selectAttr.y1 = startOffsetY selectAttr.y1 = startOffsetY
selectAttr.x2 = startOffsetX selectAttr.x2 = startOffsetX
selectAttr.y2 = Math.round(startOffsetY + (moveEvent.screenY - startScreenY) / scale) selectAttr.y2 = Math.round(startOffsetY + (moveEvent.screenY - startScreenY) / scale)
// 左下方向 // 左下方向
} else { } else {
// 左上方向 // 左上方向
selectAttr.x1 = Math.round(startOffsetX - (startScreenX - moveEvent.screenX) / scale) selectAttr.x1 = Math.round(startOffsetX - (startScreenX - moveEvent.screenX) / scale)
selectAttr.y1 = Math.round(startOffsetY - (startScreenY - moveEvent.screenY) / scale) selectAttr.y1 = Math.round(startOffsetY - (startScreenY - moveEvent.screenY) / scale)
selectAttr.x2 = startOffsetX selectAttr.x2 = startOffsetX
selectAttr.y2 = startOffsetY selectAttr.y2 = startOffsetY
} }
// 遍历组件 // 遍历组件
chartEditStore.getComponentList.forEach(item => { chartEditStore.getComponentList.forEach(item => {
if (!chartEditStore.getTargetChart.selectId.includes(item.id)) { if (!chartEditStore.getTargetChart.selectId.includes(item.id)) {
// 处理左上角 // 处理左上角
let isSelect = false let isSelect = false
const { x, y, w, h } = item.attr const { x, y, w, h } = item.attr
const targetAttr = { const targetAttr = {
// 左上角 // 左上角
x1: x, x1: x,
y1: y, y1: y,
// 右下角 // 右下角
x2: x + w, x2: x + w,
y2: y + h y2: y + h
} }
// 全包含则选中 // 全包含则选中
if ( if (
targetAttr.x1 - selectAttr.x1 >= 0 && targetAttr.x1 - selectAttr.x1 >= 0 &&
targetAttr.y1 - selectAttr.y1 >= 0 && targetAttr.y1 - selectAttr.y1 >= 0 &&
targetAttr.x2 - selectAttr.x2 <= 0 && targetAttr.x2 - selectAttr.x2 <= 0 &&
targetAttr.y2 - selectAttr.y2 <= 0 && targetAttr.y2 - selectAttr.y2 <= 0 &&
!item.status.lock && !item.status.lock &&
!item.status.hide !item.status.hide
) { ) {
isSelect = true isSelect = true
chartEditStore.setTargetSelectChart(item.id, true) chartEditStore.setTargetSelectChart(item.id, true)
} }
} }
}) })
}, 30) }, 30)
// 鼠标抬起 // 鼠标抬起
const mouseup = () => { const mouseup = () => {
// 鼠标抬起时结束mousemove的节流函数避免选框不消失问题 // 鼠标抬起时结束mousemove的节流函数避免选框不消失问题
mousemove.cancel() mousemove.cancel()
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_SELECT, false) chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_SELECT, false)
chartEditStore.setMousePosition(0, 0, 0, 0) chartEditStore.setMousePosition(0, 0, 0, 0)
document.removeEventListener('mousemove', mousemove) document.removeEventListener('mousemove', mousemove)
document.removeEventListener('mouseup', mouseup) document.removeEventListener('mouseup', mouseup)
} }
document.addEventListener('mousemove', mousemove) document.addEventListener('mousemove', mousemove)
document.addEventListener('mouseup', mouseup) document.addEventListener('mouseup', mouseup)
} }
// * 鼠标事件 // * 鼠标事件
export const useMouseHandle = () => { export const useMouseHandle = () => {
// * Click 事件, 松开鼠标触发 // * Click 事件, 松开鼠标触发
const mouseClickHandle = (e: MouseEvent, item: CreateComponentType | CreateComponentGroupType) => { const mouseClickHandle = (e: MouseEvent, item: CreateComponentType | CreateComponentGroupType) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
if (item.status.lock) return if (item.status.lock) return
// 若此时按下了 CTRL, 表示多选 // 若此时按下了 CTRL, 表示多选
if (window.$KeyboardActive?.ctrl) { if (window.$KeyboardActive?.ctrl) {
// 若已选中,则去除 // 若已选中,则去除
if (chartEditStore.targetChart.selectId.includes(item.id)) { if (chartEditStore.targetChart.selectId.includes(item.id)) {
const exList = chartEditStore.targetChart.selectId.filter(e => e !== item.id) const exList = chartEditStore.targetChart.selectId.filter(e => e !== item.id)
chartEditStore.setTargetSelectChart(exList) chartEditStore.setTargetSelectChart(exList)
} else { } else {
chartEditStore.setTargetSelectChart(item.id, true) chartEditStore.setTargetSelectChart(item.id, true)
} }
} }
} }
// * 按下事件(包含移动事件) // * 按下事件(包含移动事件)
const mousedownHandle = (e: MouseEvent, item: CreateComponentType | CreateComponentGroupType) => { const mousedownHandle = (e: MouseEvent, item: CreateComponentType | CreateComponentGroupType) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
if (item.status.lock) return if (item.status.lock) return
onClickOutSide() onClickOutSide()
// 按下左键 + CTRL // 按下左键 + CTRL
if (e.buttons === MouseEventButton.LEFT && window.$KeyboardActive?.ctrl) return if (e.buttons === MouseEventButton.LEFT && window.$KeyboardActive?.ctrl) return
// 按下右键 + 选中多个 + 目标元素是多选子元素 // 按下右键 + 选中多个 + 目标元素是多选子元素
const selectId = chartEditStore.getTargetChart.selectId const selectId = chartEditStore.getTargetChart.selectId
if (e.buttons === MouseEventButton.RIGHT && selectId.length > 1 && selectId.includes(item.id)) return if (e.buttons === MouseEventButton.RIGHT && selectId.length > 1 && selectId.includes(item.id)) return
// 选中当前目标组件 // 选中当前目标组件
chartEditStore.setTargetSelectChart(item.id) chartEditStore.setTargetSelectChart(item.id)
// 按下右键 // 按下右键
if (e.buttons === MouseEventButton.RIGHT) return if (e.buttons === MouseEventButton.RIGHT) return
const scale = chartEditStore.getEditCanvas.scale const scale = chartEditStore.getEditCanvas.scale
const canvasWidth = chartEditStore.getEditCanvasConfig.width const canvasWidth = chartEditStore.getEditCanvasConfig.width
const canvasHeight = chartEditStore.getEditCanvasConfig.height const canvasHeight = chartEditStore.getEditCanvasConfig.height
// 记录图表初始位置和大小 // 记录图表初始位置和大小
const targetMap = new Map() const targetMap = new Map()
chartEditStore.getTargetChart.selectId.forEach(id => { chartEditStore.getTargetChart.selectId.forEach(id => {
const index = chartEditStore.fetchTargetIndex(id) const index = chartEditStore.fetchTargetIndex(id)
if (index !== -1) { if (index !== -1) {
const { x, y, w, h } = toRaw(chartEditStore.getComponentList[index]).attr const { x, y, w, h } = toRaw(chartEditStore.getComponentList[index]).attr
targetMap.set(id, { x, y, w, h }) targetMap.set(id, { x, y, w, h })
} }
}) })
// 记录点击初始位置 // 记录点击初始位置
const startX = e.screenX const startX = e.screenX
const startY = e.screenY const startY = e.screenY
// 记录历史位置 // 记录历史位置
let prevComponentInstance: Array<CreateComponentType | CreateComponentGroupType> = [] let prevComponentInstance: Array<CreateComponentType | CreateComponentGroupType> = []
chartEditStore.getTargetChart.selectId.forEach(id => { chartEditStore.getTargetChart.selectId.forEach(id => {
if (!targetMap.has(id)) return if (!targetMap.has(id)) return
const index = chartEditStore.fetchTargetIndex(id) const index = chartEditStore.fetchTargetIndex(id)
// 拿到初始位置数据 // 拿到初始位置数据
prevComponentInstance.push(cloneDeep(chartEditStore.getComponentList[index])) prevComponentInstance.push(cloneDeep(chartEditStore.getComponentList[index]))
}) })
// 记录初始位置 // 记录初始位置
chartEditStore.setMousePosition(undefined, undefined, startX, startY) chartEditStore.setMousePosition(undefined, undefined, startX, startY)
// 移动-计算偏移量 // 移动-计算偏移量
const mousemove = throttle((moveEvent: MouseEvent) => { const mousemove = throttle((moveEvent: MouseEvent) => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, true) chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, true)
chartEditStore.setMousePosition(moveEvent.screenX, moveEvent.screenY) chartEditStore.setMousePosition(moveEvent.screenX, moveEvent.screenY)
// 当前偏移量,处理 scale 比例问题 // 当前偏移量,处理 scale 比例问题
let offsetX = (moveEvent.screenX - startX) / scale let offsetX = (moveEvent.screenX - startX) / scale
let offsetY = (moveEvent.screenY - startY) / scale let offsetY = (moveEvent.screenY - startY) / scale
chartEditStore.getTargetChart.selectId.forEach(id => { chartEditStore.getTargetChart.selectId.forEach(id => {
if (!targetMap.has(id)) return if (!targetMap.has(id)) return
const index = chartEditStore.fetchTargetIndex(id) const index = chartEditStore.fetchTargetIndex(id)
// 拿到初始位置数据 // 拿到初始位置数据
const { x, y, w, h } = targetMap.get(id) const { x, y, w, h } = targetMap.get(id)
const componentInstance = chartEditStore.getComponentList[index] const componentInstance = chartEditStore.getComponentList[index]
let currX = Math.round(x + offsetX) let currX = Math.round(x + offsetX)
let currY = Math.round(y + offsetY) let currY = Math.round(y + offsetY)
// 要预留的距离 // 要预留的距离
const distance = 50 const distance = 50
// 基于左上角位置检测 // 基于左上角位置检测
currX = currX < -w + distance ? -w + distance : currX currX = currX < -w + distance ? -w + distance : currX
currY = currY < -h + distance ? -h + distance : currY currY = currY < -h + distance ? -h + distance : currY
// 基于右下角位置检测 // 基于右下角位置检测
currX = currX > canvasWidth - distance ? canvasWidth - distance : currX currX = currX > canvasWidth - distance ? canvasWidth - distance : currX
currY = currY > canvasHeight - distance ? canvasHeight - distance : currY currY = currY > canvasHeight - distance ? canvasHeight - distance : currY
if (componentInstance) { if (componentInstance) {
componentInstance.attr = Object.assign(componentInstance.attr, { componentInstance.attr = Object.assign(componentInstance.attr, {
x: currX, x: currX,
y: currY y: currY
}) })
} }
}) })
return return
}, 20) }, 20)
const mouseup = () => { const mouseup = () => {
try { try {
chartEditStore.setMousePosition(0, 0, 0, 0) chartEditStore.setMousePosition(0, 0, 0, 0)
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, false) chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, false)
// 加入历史栈 // 加入历史栈
if (prevComponentInstance.length) { if (prevComponentInstance.length) {
chartEditStore.getTargetChart.selectId.forEach(id => { chartEditStore.getTargetChart.selectId.forEach(id => {
if (!targetMap.has(id)) return if (!targetMap.has(id)) return
const index = chartEditStore.fetchTargetIndex(id) const index = chartEditStore.fetchTargetIndex(id)
const curComponentInstance = chartEditStore.getComponentList[index] const curComponentInstance = chartEditStore.getComponentList[index]
// 找到记录的所选组件 // 找到记录的所选组件
prevComponentInstance.forEach(preItem => { prevComponentInstance.forEach(preItem => {
if (preItem.id === id) { if (preItem.id === id) {
preItem.attr = Object.assign(preItem.attr, { preItem.attr = Object.assign(preItem.attr, {
offsetX: curComponentInstance.attr.x - preItem.attr.x, offsetX: curComponentInstance.attr.x - preItem.attr.x,
offsetY: curComponentInstance.attr.y - preItem.attr.y offsetY: curComponentInstance.attr.y - preItem.attr.y
}) })
} }
}) })
}) })
const moveComponentInstance = prevComponentInstance.filter( const moveComponentInstance = prevComponentInstance.filter(
item => item.attr.offsetX !== 0 && item.attr.offsetY !== 0 item => item.attr.offsetX !== 0 && item.attr.offsetY !== 0
) )
moveComponentInstance.length && chartEditStore.moveComponentList(moveComponentInstance) moveComponentInstance.length && chartEditStore.moveComponentList(moveComponentInstance)
} }
document.removeEventListener('mousemove', mousemove) document.removeEventListener('mousemove', mousemove)
document.removeEventListener('mouseup', mouseup) document.removeEventListener('mouseup', mouseup)
} catch (err) { } catch (err) {
console.log(err) console.log(err)
} }
} }
document.addEventListener('mousemove', mousemove) document.addEventListener('mousemove', mousemove)
document.addEventListener('mouseup', mouseup) document.addEventListener('mouseup', mouseup)
} }
// * 进入事件 // * 进入事件
const mouseenterHandle = (e: MouseEvent, item: CreateComponentType | CreateComponentGroupType) => { const mouseenterHandle = (e: MouseEvent, item: CreateComponentType | CreateComponentGroupType) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
if (!chartEditStore.getEditCanvas.isSelect) { if (!chartEditStore.getEditCanvas.isSelect) {
chartEditStore.setTargetHoverChart(item.id) chartEditStore.setTargetHoverChart(item.id)
} }
} }
// * 移出事件 // * 移出事件
const mouseleaveHandle = (e: MouseEvent, item: CreateComponentType | CreateComponentGroupType) => { const mouseleaveHandle = (e: MouseEvent, item: CreateComponentType | CreateComponentGroupType) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, false) chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, false)
chartEditStore.setTargetHoverChart(undefined) chartEditStore.setTargetHoverChart(undefined)
} }
return { mouseClickHandle, mousedownHandle, mouseenterHandle, mouseleaveHandle } return { mouseClickHandle, mousedownHandle, mouseenterHandle, mouseleaveHandle }
} }
// * 移动锚点 // * 移动锚点
export const useMousePointHandle = (e: MouseEvent, point: string, attr: PickCreateComponentType<'attr'>) => { export const useMousePointHandle = (e: MouseEvent, point: string, attr: PickCreateComponentType<'attr'>) => {
e.stopPropagation() e.stopPropagation()
e.preventDefault() e.preventDefault()
// 设置拖拽状态 // 设置拖拽状态
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, true) chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, true)
const scale = chartEditStore.getEditCanvas.scale const scale = chartEditStore.getEditCanvas.scale
const itemAttrX = attr.x const itemAttrX = attr.x
const itemAttrY = attr.y const itemAttrY = attr.y
const itemAttrW = attr.w const itemAttrW = attr.w
const itemAttrH = attr.h const itemAttrH = attr.h
// 记录点击初始位置 // 记录点击初始位置
const startX = e.screenX const startX = e.screenX
const startY = e.screenY const startY = e.screenY
// 记录初始位置 // 记录初始位置
chartEditStore.setMousePosition(startX, startY) chartEditStore.setMousePosition(startX, startY)
const mousemove = throttle((moveEvent: MouseEvent) => { const mousemove = throttle((moveEvent: MouseEvent) => {
chartEditStore.setMousePosition(moveEvent.screenX, moveEvent.screenY) chartEditStore.setMousePosition(moveEvent.screenX, moveEvent.screenY)
let currX = Math.round((moveEvent.screenX - startX) / scale) let currX = Math.round((moveEvent.screenX - startX) / scale)
let currY = Math.round((moveEvent.screenY - startY) / scale) let currY = Math.round((moveEvent.screenY - startY) / scale)
const isTop = /t/.test(point) const isTop = /t/.test(point)
const isBottom = /b/.test(point) const isBottom = /b/.test(point)
const isLeft = /l/.test(point) const isLeft = /l/.test(point)
const isRight = /r/.test(point) const isRight = /r/.test(point)
const newHeight = itemAttrH + (isTop ? -currY : isBottom ? currY : 0) const newHeight = itemAttrH + (isTop ? -currY : isBottom ? currY : 0)
const newWidth = itemAttrW + (isLeft ? -currX : isRight ? currX : 0) const newWidth = itemAttrW + (isLeft ? -currX : isRight ? currX : 0)
attr.h = newHeight > 0 ? newHeight : 0 attr.h = newHeight > 0 ? newHeight : 0
attr.w = newWidth > 0 ? newWidth : 0 attr.w = newWidth > 0 ? newWidth : 0
attr.x = itemAttrX + (isLeft ? currX : 0) attr.x = itemAttrX + (isLeft ? currX : 0)
attr.y = itemAttrY + (isTop ? currY : 0) attr.y = itemAttrY + (isTop ? currY : 0)
}, 50) }, 50)
const mouseup = () => { const mouseup = () => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, false) chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_DRAG, false)
chartEditStore.setMousePosition(0, 0, 0, 0) chartEditStore.setMousePosition(0, 0, 0, 0)
document.removeEventListener('mousemove', mousemove) document.removeEventListener('mousemove', mousemove)
document.removeEventListener('mouseup', mouseup) document.removeEventListener('mouseup', mouseup)
} }
document.addEventListener('mousemove', mousemove) document.addEventListener('mousemove', mousemove)
document.addEventListener('mouseup', mouseup) document.addEventListener('mouseup', mouseup)
} }

View File

@ -55,6 +55,110 @@ const previewHandle = () => {
routerTurnByPath(path, [previewId], undefined, true) routerTurnByPath(path, [previewId], undefined, true)
} }
//
const sendHandle = () => {
goDialog({
message: '想体验发布功能,请前往 master-fetch 分支查看: https://gitee.com/MTrun/go-view/tree/master-fetch',
positiveText: '了然',
closeNegativeText: true,
onPositiveCallback: () => {}
})
}
const btnList = [
{
select: true,
title: '同步内容',
type: 'primary',
icon: renderIcon(AnalyticsIcon),
event: syncData
},
{
select: true,
title: '预览',
icon: renderIcon(BrowsersOutlineIcon),
event: previewHandle
},
{
select: true,
title: '发布',
icon: renderIcon(SendIcon),
event: sendHandle
}
]
const comBtnList = computed(() => {
if (chartEditStore.getEditCanvas.isCodeEdit) {
return btnList
}
const cloneList = cloneDeep(btnList)
cloneList.shift()
return cloneList
})
</script>
<style lang="scss" scoped>
.align-center {
margin-top: -4px;
}
</style>
<template>
<n-space class="go-mt-0">
<n-button v-for="item in comBtnList" :key="item.title" :type="item.type" ghost @click="item.event">
<template #icon>
<component :is="item.icon"></component>
</template>
<span>{{ item.title }}</span>
</n-button>
</n-space>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
import { PreviewEnum } from '@/enums/pageEnum'
import { StorageEnum } from '@/enums/storageEnum'
import { useRoute } from 'vue-router'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { syncData } from '../../ContentEdit/components/EditTools/hooks/useSyncUpdate.hook'
import { icon } from '@/plugins'
import { cloneDeep } from 'lodash'
const { BrowsersOutlineIcon, SendIcon, AnalyticsIcon } = icon.ionicons5
const chartEditStore = useChartEditStore()
const routerParamsInfo = useRoute()
//
const previewHandle = () => {
const path = fetchPathByName(PreviewEnum.CHART_PREVIEW_NAME, 'href')
if (!path) return
const { id } = routerParamsInfo.params
// id
const previewId = typeof id === 'string' ? id : id[0]
const storageInfo = chartEditStore.getStorageInfo()
const sessionStorageInfo = getLocalStorage(StorageEnum.GO_CHART_STORAGE_LIST) || []
if (sessionStorageInfo?.length) {
const repeateIndex = sessionStorageInfo.findIndex((e: { id: string }) => e.id === previewId)
//
if (repeateIndex !== -1) {
sessionStorageInfo.splice(repeateIndex, 1, { id: previewId, ...storageInfo })
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
} else {
sessionStorageInfo.push({
id: previewId,
...storageInfo
})
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
}
} else {
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [{ id: previewId, ...storageInfo }])
}
//
routerTurnByPath(path, [previewId], undefined, true)
}
// //
const sendHandle = () => { const sendHandle = () => {
goDialog({ goDialog({

View File

@ -15,13 +15,7 @@
</transition-group> </transition-group>
</aside> </aside>
</div> </div>
<layout-header> <layout-header></layout-header>
<template #left></template>
<template #right>
<go-lang-select></go-lang-select>
<go-theme-select></go-theme-select>
</template>
</layout-header>
<div class="go-login"> <div class="go-login">
<div class="go-login-carousel"> <div class="go-login-carousel">
<n-carousel <n-carousel

View File

@ -5,4 +5,5 @@ declare module '*.vue' {
} }
declare module 'lodash/*' declare module 'lodash/*'
declare module 'dom-helpers' declare module 'dom-helpers'
declare module 'vue3-sketch-ruler';