Compare commits

...

42 Commits

Author SHA1 Message Date
奔跑的面条
0816f3fcbf Merge branch 'master-fetch-dev' into master-fetch 2023-07-09 15:55:11 +08:00
奔跑的面条
6843f24263 Merge branch 'dev' into master-fetch-dev 2023-07-09 15:54:55 +08:00
奔跑的面条
7076c4deb7 feat: 新增预览拖拽 2023-07-09 15:54:01 +08:00
奔跑的面条
59bfc78f0a Merge branch 'master-fetch-dev' into master-fetch 2023-07-08 22:03:58 +08:00
奔跑的面条
4064339848 build: 升级到版本 2.2.4 2023-07-08 22:03:27 +08:00
奔跑的面条
d2af67d6ad Merge branch 'dev' into master-fetch-dev 2023-07-08 22:01:54 +08:00
奔跑的面条
e979149cfb feat: 不符合接口格式时添加拦截 2023-07-08 21:59:41 +08:00
奔跑的面条
d0d031d1bb feat: 还原修改成组旋转的问题,优化预览放大的交互 2023-07-08 21:33:50 +08:00
奔跑的面条
9127e6f44c feat: 新增预览放大功能 2023-07-08 21:18:37 +08:00
xlys999
bb610ff7ae update src/views/chart/ContentEdit/components/EditRule/index.vue.
坐标尺刻度错位问题

Signed-off-by: xlys999 <xlys998@163.com>
2023-07-08 18:45:03 +08:00
奔跑的面条
c575cff727 perf: 优化滤镜预设展示 2023-07-08 18:36:36 +08:00
奔跑的面条
5443c9647b !176 新增预设滤镜功能
Merge pull request !176 from 张江胜/dev_feat
2023-07-08 10:35:31 +00:00
张江胜
271a02ff12 feat: 增加预设滤镜功能
1.滤镜变换:新增了快捷预设滤镜
2023-06-29 18:45:59 +08:00
张江胜
f747fd3506 fix: 解决单个组件旋转后,再组合分组渲染预览会错位的问题
1.解决单个组件旋转后,和其他组件组合分组后再次旋转,进行预览后该分组会错位的问题
2.解决TS类型报错
2023-06-29 17:39:17 +08:00
奔跑的面条
b59c28b8ae fix: 解决 TS 类型错误问题 2023-06-27 18:11:37 +08:00
奔跑的面条
b1a0e7b5e2 fix: 修改 axios 类型错误 2023-06-27 17:54:17 +08:00
奔跑的面条
0d762f7d30 style: 优化 pr_173 的问题 2023-06-27 17:48:08 +08:00
奔跑的面条
cc156a0a6b !173 1.时间选择器增加默认值类型选项
Merge pull request !173 from dingxs/dingxs
2023-06-27 09:47:39 +00:00
奔跑的面条
a77f4d6bf4 !174 feat: 为 naive-ui 组件配置感知、属性提示、自动完成功能
Merge pull request !174 from dodu/dev-commet
2023-06-25 01:32:43 +00:00
tnt group
9e5676e5ed feat: 为 naive-ui 组件提供感知能力 2023-06-23 11:54:52 +08:00
dingxs
bc79e2f01f fix:用in判断对象是否具有某个特定的key,而不是value,解决当value为null时永远得不到修改 2023-06-19 14:39:00 +08:00
dingxs
80f06afa02 feat:时间选择器增加默认值类型选项 2023-06-19 14:35:17 +08:00
奔跑的面条
3da84b2fa2 Merge branch 'dev' into master-fetch-dev 2023-06-15 19:56:44 +08:00
奔跑的面条
58ab3dee6d !172 环形饼图增加轨道宽度设置,并优化数字显示(如无小数位,则不强制显示小数位)
Merge pull request !172 from dodu/dev-commet
2023-06-15 11:52:47 +00:00
奔跑的面条
d7a3bb7ba0 !169 feat:标签选择器增加默认值选项
Merge pull request !169 from h5coder/dev-h5coder
2023-06-15 19:50:27 +08:00
奔跑的面条
2ad2af97e6 !169 feat:标签选择器增加默认值选项
Merge pull request !169 from h5coder/dev-h5coder
2023-06-15 11:49:54 +00:00
奔跑的面条
5387a7ad90 !171 fix: 修复旧版本没有legend配置导致报settting color错误
Merge pull request !171 from h5coder/h5coder-fix
2023-06-15 19:46:13 +08:00
奔跑的面条
291a7bbc61 !171 fix: 修复旧版本没有legend配置导致报settting color错误
Merge pull request !171 from h5coder/h5coder-fix
2023-06-15 11:45:41 +00:00
tnt group
fe37435f79 chore: 设置选择框size 2023-06-14 07:54:36 +08:00
tnt group
1ef6d9797a feat: 环形饼图增加轨道宽度设置,并优化数字显示 2023-06-13 10:27:08 +08:00
lyx
27e2e2c68d fix: 修复旧版本没有legend配置导致报settting color错误 2023-06-09 10:56:36 +08:00
奔跑的面条
c70d54c622 style: 删除冗余代码 2023-06-08 16:39:18 +08:00
Ming
d74645d7b0 feat: 组件交互对公共api支持配置页 2023-06-07 15:13:48 +08:00
Ming
86910de3b2 fix: 数据初始化 2023-06-07 15:08:52 +08:00
Ming
47636ee680 feat: 支持对公共api进行交互 2023-06-07 15:06:51 +08:00
Ming
9485931f5d feat: 更新公共api对组件动态绑定交互 2023-06-07 15:03:59 +08:00
Ming
20fa9e4afe fix: declare module '@iconify/vue' 2023-06-07 15:00:28 +08:00
Ming
cbd629d7f8 feat: 更新交互组件更新方式 2023-06-07 15:00:06 +08:00
lyx
18e0729e54 fix:标签选择器去除多余的代码 2023-06-05 18:06:57 +08:00
lyx
d6afc50ac5 feat:标签选择器增加默认值选项 2023-06-02 17:29:18 +08:00
奔跑的面条
37676176e7 fix: 去除定时存储数据的逻辑 2023-05-30 09:34:54 +08:00
Ming
1551aa9ded fix: 语言转换为英文后,创建按钮的英文拼写错误 2023-05-29 10:29:44 +08:00
32 changed files with 1035 additions and 508 deletions

View File

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

View File

@@ -163,7 +163,6 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
params = translateStr(params)
// form 类型处理
let formData: FormData = new FormData()
formData.set('default', 'defaultData')
// 类型处理
switch (requestParamsBodyType) {

View File

@@ -391,8 +391,12 @@ const visualMap = computed(() => {
// 监听legend color颜色改变type = scroll的颜色
watch(() => legend.value && legend.value.textStyle.color, (newVal) => {
if (legend.value && newVal) {
legend.value.pageTextStyle.color = newVal
}
if (!legend.value.pageTextStyle) {
legend.value.pageTextStyle = { color: newVal }
} else {
legend.value.pageTextStyle.color = newVal
}
}
}, {
immediate: true,
deep: true,

View File

@@ -69,6 +69,22 @@
</setting-item>
</setting-item-box>
<!-- 预设滤镜 -->
<div v-if="presetImageList.length" class="preset-filter">
<n-image
class="preset-img"
width="46"
preview-disabled
object-fit="scale-down"
v-for="(item, index) in presetImageList"
:key="index"
:class="{ 'active-preset': item.hueRotate === chartStyles.hueRotate }"
:style="{ filter: `hue-rotate(${item.hueRotate}deg)` }"
:src="item.src"
@click="() => (chartStyles.hueRotate = item.hueRotate)"
></n-image>
</div>
<!-- 混合模式 -->
<setting-item-box v-if="!isCanvas" :alone="true">
<template #name>
@@ -149,10 +165,12 @@
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { ref, PropType } from 'vue'
import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d'
import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting'
import { icon } from '@/plugins'
import logoImg from '@/assets/logo.png'
import { useDesignStore } from '@/store/modules/designStore/designStore'
const props = defineProps({
isGroup: {
@@ -175,10 +193,48 @@ const { HelpOutlineIcon } = icon.ionicons5
const sliderFormatTooltip = (v: string) => {
return `${(parseFloat(v) * 100).toFixed(0)}%`
}
// 角度格式化
const degFormatTooltip = (v: string) => {
return `${v}deg`
}
// 预设滤镜
interface presetImageData {
index: number
src: string
hueRotate: number
}
const presetImageList = ref([] as presetImageData[])
for (let i = 1; i <= 12; i++) {
presetImageList.value.push({
index: i,
src: logoImg,
hueRotate: i * 30
})
}
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
// 预设滤镜
.preset-filter {
margin: 20px 0 10px 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.preset-img {
margin-bottom: 10px;
padding: 2px;
border-radius: 6px;
transition: 0.2s all;
cursor: pointer;
&:hover {
box-shadow: 0 0 0 2px #66a9c9;
}
}
.active-preset {
box-shadow: 0 0 0 2px #66a9c9;
}
}
</style>

View File

@@ -90,12 +90,12 @@ export const useChartDataFetch = (
// 普通初始化与组件交互处理监听
watch(
() => targetComponent.request,
() => targetComponent.request.requestParams,
() => {
fetchFn()
},
{
immediate: true,
immediate: false,
deep: true
}
)
@@ -105,7 +105,11 @@ export const useChartDataFetch = (
// 单位
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))
} else {
fetchFn()
}
}
// eslint-disable-next-line no-empty
} catch (error) {
@@ -114,10 +118,11 @@ export const useChartDataFetch = (
}
if (isPreview()) {
// 判断是否是数据池类型
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
: requestIntervalFn()
} else {
requestIntervalFn()
}
return { vChartRef }
}

View File

@@ -1,4 +1,4 @@
import { toRaw } from 'vue'
import { toRaw, watch, computed, ComputedRef } from 'vue'
import { customizeHttp } from '@/api/http'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@@ -20,7 +20,7 @@ const mittDataPondMap = new Map<string, DataPondMapType[]>()
// 创建单个数据项轮询接口
const newPondItemInterval = (
requestGlobalConfig: RequestGlobalConfigType,
requestDataPondItem: RequestDataPondItemType,
requestDataPondItem: ComputedRef<RequestDataPondItemType>,
dataPondMapItem?: DataPondMapType[]
) => {
if (!dataPondMapItem) return
@@ -31,8 +31,7 @@ const newPondItemInterval = (
// 请求
const fetchFn = async () => {
try {
const res = await customizeHttp(toRaw(requestDataPondItem.dataPondRequestConfig), toRaw(requestGlobalConfig))
const res = await customizeHttp(toRaw(requestDataPondItem.value.dataPondRequestConfig), toRaw(requestGlobalConfig))
if (res) {
try {
// 遍历更新回调函数
@@ -49,19 +48,32 @@ const newPondItemInterval = (
}
}
watch(
() => requestDataPondItem.value.dataPondRequestConfig.requestParams.Params,
() => {
fetchFn()
},
{
immediate: false,
deep: true
}
)
// 立即调用
fetchFn()
const targetInterval = requestDataPondItem.dataPondRequestConfig.requestInterval
const targetUnit = requestDataPondItem.dataPondRequestConfig.requestIntervalUnit
const targetInterval = requestDataPondItem.value.dataPondRequestConfig.requestInterval
const targetUnit = requestDataPondItem.value.dataPondRequestConfig.requestIntervalUnit
const globalRequestInterval = requestGlobalConfig.requestInterval
const globalUnit = requestGlobalConfig.requestIntervalUnit
// 定时时间
const time = targetInterval ? targetInterval : globalRequestInterval
const time = targetInterval ? targetInterval : globalRequestInterval
// 单位
const unit = targetInterval ? targetUnit : globalUnit
const unit = targetInterval ? targetUnit : globalUnit
// 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
}
@@ -96,13 +108,16 @@ export const useChartDataPondFetch = () => {
}
// 初始化数据池
const initDataPond = (requestGlobalConfig: RequestGlobalConfigType) => {
const { requestDataPond } = requestGlobalConfig
const initDataPond = (useChartEditStore: ChartEditStoreType) => {
const { requestGlobalConfig } = useChartEditStore()
const chartEditStore = useChartEditStore()
// 根据 mapId 查找对应的数据池配置
for (let pondKey of mittDataPondMap.keys()) {
const requestDataPondItem = requestDataPond.find(item => item.dataPondId === pondKey)
const requestDataPondItem = computed(() => {
return requestGlobalConfig.requestDataPond.find(item => item.dataPondId === pondKey)
}) as ComputedRef<RequestDataPondItemType>
if (requestDataPondItem) {
newPondItemInterval(requestGlobalConfig, requestDataPondItem, mittDataPondMap.get(pondKey))
newPondItemInterval(chartEditStore.requestGlobalConfig, requestDataPondItem, mittDataPondMap.get(pondKey))
}
}
}

View File

@@ -1,4 +1,5 @@
import { toRefs } from 'vue'
import { isPreview } from '@/utils'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@@ -12,6 +13,7 @@ export const useChartInteract = (
param: { [T: string]: any },
interactEventOn: string
) => {
if (!isPreview()) return
const chartEditStore = useChartEditStore()
const { interactEvents } = chartConfig.events
const fnOnEvent = interactEvents.filter(item => {
@@ -20,20 +22,37 @@ export const useChartInteract = (
if (fnOnEvent.length === 0) return
fnOnEvent.forEach(item => {
const index = chartEditStore.fetchTargetIndex(item.interactComponentId)
if (index === -1) return
const { Params, Header } = toRefs(chartEditStore.componentList[index].request.requestParams)
Object.keys(item.interactFn).forEach(key => {
if (Params.value[key]) {
Params.value[key] = param[item.interactFn[key]]
}
if (Header.value[key]) {
Header.value[key] = param[item.interactFn[key]]
}
})
const globalConfigPindAprndex = chartEditStore.requestGlobalConfig.requestDataPond.findIndex(cItem =>
cItem.dataPondId === item.interactComponentId
)
if (globalConfigPindAprndex !== -1) {
const { Params, Header } = toRefs(chartEditStore.requestGlobalConfig.requestDataPond[globalConfigPindAprndex].dataPondRequestConfig.requestParams)
Object.keys(item.interactFn).forEach(key => {
if (key in Params.value) {
Params.value[key] = param[item.interactFn[key]]
}
if (key in Header.value) {
Header.value[key] = param[item.interactFn[key]]
}
})
} else {
const index = chartEditStore.fetchTargetIndex(item.interactComponentId)
if (index === -1) return
const { Params, Header } = toRefs(chartEditStore.componentList[index].request.requestParams)
Object.keys(item.interactFn).forEach(key => {
if (key in Params.value) {
Params.value[key] = param[item.interactFn[key]]
}
if (key in Header.value) {
Header.value[key] = param[item.interactFn[key]]
}
})
}
})
}
// 联动事件触发的 type 变更时,清除当前绑定内容
export const clearInteractEvent = (chartConfig: CreateComponentType) => {

View File

@@ -1,218 +1,218 @@
import throttle from 'lodash/throttle'
// 拆出来是为了更好的分离单独复用
// * 屏幕缩放适配(两边留白)
export const usePreviewFitScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
// 当前屏幕宽高比
const currentRate = parseFloat(
(window.innerWidth / window.innerHeight).toFixed(5)
)
if (scaleDom) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
} else {
// 表示更高
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
}
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 改变窗口大小重新绘制
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * X轴撑满Y轴滚动条
export const usePreviewScrollYScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 改变窗口大小重新绘制
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * Y轴撑满X轴滚动条
export const usePreviewScrollXScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
height: 1,
width: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 改变窗口大小重新绘制
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * 变形内容,宽高铺满
export const usePreviewFullScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat((window.innerWidth / width).toFixed(5))
scale.height = parseFloat((window.innerHeight / height).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 改变窗口大小重新绘制
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
import throttle from 'lodash/throttle'
// 拆出来是为了更好的分离单独复用
// * 屏幕缩放适配(两边留白)
export const usePreviewFitScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
// 当前屏幕宽高比
const currentRate = parseFloat(
(window.innerWidth / window.innerHeight).toFixed(5)
)
if (scaleDom) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
} else {
// 表示更高
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
}
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * X轴撑满Y轴滚动条
export const usePreviewScrollYScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.height = parseFloat(((window.innerWidth / baseProportion) / baseHeight).toFixed(5))
scale.width = parseFloat((window.innerWidth / baseWidth).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * Y轴撑满X轴滚动条
export const usePreviewScrollXScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 画布尺寸px
const baseWidth = width
const baseHeight = height
// * 默认缩放值
const scale = {
height: 1,
width: 1,
}
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat(((window.innerHeight * baseProportion) / baseWidth).toFixed(5))
scale.height = parseFloat((window.innerHeight / baseHeight).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}
// * 变形内容,宽高铺满
export const usePreviewFullScale = (
width: number,
height: number,
scaleDom: HTMLElement | null,
callback?: (scale: {
width: number;
height: number;
}) => void
) => {
// * 默认缩放值
const scale = {
width: 1,
height: 1,
}
const calcRate = () => {
if (scaleDom) {
scale.width = parseFloat((window.innerWidth / width).toFixed(5))
scale.height = parseFloat((window.innerHeight / height).toFixed(5))
scaleDom.style.transform = `scale(${scale.width}, ${scale.height})`
if (callback) callback(scale)
}
}
const resize = throttle(() => {
calcRate()
}, 200)
// * 改变窗口大小重新绘制
const windowResize = () => {
window.addEventListener('resize', resize)
}
// * 卸载监听
const unWindowResize = () => {
window.removeEventListener('resize', resize)
}
return {
calcRate,
windowResize,
unWindowResize,
}
}

View File

@@ -7,6 +7,22 @@
</n-input-number>
</SettingItem>
</SettingItemBox>
<!-- 中心标题 -->
<SettingItemBox v-if="config.title" name="标题">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="config.title.textStyle.color"></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="config.title.textStyle.fontSize"
:min="0"
:step="1"
size="small"
placeholder="字体大小"
>
</n-input-number>
</SettingItem>
</SettingItemBox>
<!-- Echarts 全局设置 -->
<SettingItemBox name="进度条">
<SettingItem name="颜色">
@@ -31,24 +47,8 @@
></n-color-picker>
</SettingItem>
</SettingItemBox>
<!-- 中心标题 -->
<SettingItemBox v-if="config.title" name="标题">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="config.title.textStyle.color"></n-color-picker>
</SettingItem>
<SettingItem name="字体大小">
<n-input-number
v-model:value="config.title.textStyle.fontSize"
:min="0"
:step="1"
size="small"
placeholder="字体大小"
>
</n-input-number>
</SettingItem>
</SettingItemBox>
<!-- 其他样式 -->
<SettingItemBox name="轨道样式">
<SettingItemBox name="轨道">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.data[1].itemStyle.color"></n-color-picker>
</SettingItem>
@@ -69,6 +69,18 @@
v-model:value="item.data[1].itemStyle.shadowColor"
></n-color-picker>
</SettingItem>
<SettingItem name="轨道宽度">
<n-select
v-model:value="item.radius[0]"
size="small"
:options="[
{ label: '窄', value: '75%' },
{ label: '中', value: '60%' },
{ label: '宽', value: '45%' },
{ label: '更宽', value: '30%' }
]"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>

View File

@@ -41,7 +41,7 @@ const option = reactive({
const dataHandle = (newData: any) => {
const d = parseFloat(`${newData}`) * 100
let config = props.chartConfig.option
config.title.text = d.toFixed(2) + '%'
config.title.text = `${+d.toFixed(2)}%`
config.series[0].data[0].value[0] = d
config.series[0].data[1].value[0] = 100 - d
option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
@@ -68,7 +68,7 @@ watch(
useChartDataFetch(props.chartConfig, useChartEditStore, (resData: number) => {
let d = parseFloat(`${resData}`) * 100
// @ts-ignore
option.value.title.text = d.toFixed(2) + '%'
option.value.title.text = `${+d.toFixed(2)}%`
// @ts-ignore
option.value.series[0].data[0].value[0] = d
// @ts-ignore

View File

@@ -63,7 +63,7 @@ watch(
() => props.chartConfig.option,
newVal => {
try {
updateDatasetHandler((newVal as OptionType).dataset)
updateDatasetHandler((newVal as any as OptionType).dataset)
} catch (error) {
console.log(error)
}

View File

@@ -4,7 +4,7 @@ import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { chartInitConfig } from '@/settings/designSetting'
import { COMPONENT_INTERACT_EVENT_KET } from '@/enums/eventEnum'
import { interactActions, ComponentInteractEventEnum } from './interact'
import { interactActions, ComponentInteractEventEnum, DefaultTypeEnum, DifferUnitEnum } from './interact'
import { InputsDateConfig } from './index'
export const option = {
@@ -12,9 +12,14 @@ export const option = {
[COMPONENT_INTERACT_EVENT_KET]: ComponentInteractEventEnum.DATE,
// 下拉展示
isPanel: 0,
dataset: dayjs().valueOf(),
differValue: 0
// 默认值
dataset: dayjs().valueOf() as number | number[] | null,
// 默认值类型
defaultType: DefaultTypeEnum.STATIC,
// 动态默认值偏移单位
differUnit: [DifferUnitEnum.DAY, DifferUnitEnum.DAY],
// 动态默认值偏移值
differValue: [0, 0]
}
export default class Config extends PublicConfigClass implements CreateComponentType {

View File

@@ -8,39 +8,67 @@
<collapse-item name="时间配置" :expanded="true">
<setting-item-box name="基础">
<setting-item name="类型">
<n-select v-model:value="optionData.componentInteractEventKey" size="small" :options="datePickerTypeOptions" />
<n-select v-model:value="optionData.componentInteractEventKey" size="small" :options="datePickerTypeOptions"
@update:value="datePickerTypeUpdate"/>
</setting-item>
</setting-item-box>
<setting-item-box name="默认值" :alone="true">
<n-date-picker size="small" v-model:value="optionData.dataset" :type="optionData.componentInteractEventKey" />
</setting-item-box>
<setting-item-box name="默认值">
<setting-item name="类型">
<n-select v-model:value="optionData.defaultType" size="small" :options="defaultTypeOptions"
@update:value="defaultTypeUpdate" />
</setting-item>
<setting-item-box :alone="true">
</setting-item-box>
<setting-item-box v-if="optionData.defaultType === DefaultTypeEnum.STATIC" :alone="true">
<setting-item name="静态默认值">
<n-date-picker size="small" clearable v-model:value="optionData.dataset" :type="optionData.componentInteractEventKey" />
</setting-item>
</setting-item-box>
<setting-item-box v-if="optionData.defaultType === DefaultTypeEnum.DYNAMIC" >
<template #name>
<n-text>动态</n-text>
<n-text></n-text>
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
<n-text>动态值不为0时默认值:取当天时间相加当前值</n-text>
<span>打开页面时浏览器操作系统的系统时间+偏移量(单位)</span>
</n-tooltip>
</template>
<n-input-number v-model:value="optionData.differValue" class="input-num-width" size="small" :min="-40" :max="40">
<template #suffix> </template>
</n-input-number>
<setting-item :name="differValueName">
<n-input-number v-model:value="optionData.differValue[0]" class="input-num-width" size="small">
<template #suffix>
{{DifferUnitObject[optionData.differUnit[0]]}}
</template>
</n-input-number>
</setting-item>
<setting-item :name="differUnitName">
<n-select v-model:value="optionData.differUnit[0]" size="small" :options="differUnitOptions" />
</setting-item>
<setting-item v-if="isRange" name="结束值动态偏移量">
<n-input-number v-model:value="optionData.differValue[1]" class="input-num-width" size="small">
<template #suffix>
{{DifferUnitObject[optionData.differUnit[1]]}}
</template>
</n-input-number>
</setting-item>
<setting-item v-if="isRange" name="结束值偏移单位">
<n-select v-model:value="optionData.differUnit[1]" size="small" :options="differUnitOptions" />
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script lang="ts" setup>
import { PropType } from 'vue'
import { PropType, computed } from 'vue'
import { icon } from '@/plugins'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option } from './config'
import { ComponentInteractEventEnum } from './interact'
import { ComponentInteractEventEnum, DefaultTypeEnum, DifferUnitEnum, DifferUnitObject } from './interact'
import dayjs from "dayjs";
const { HelpOutlineIcon } = icon.ionicons5
@@ -100,4 +128,87 @@ const datePickerTypeOptions = [
value: ComponentInteractEventEnum.QUARTER_RANGE
}
]
const defaultTypeOptions = [
{
label: '静态',
value: DefaultTypeEnum.STATIC
},
{
label: '动态',
value: DefaultTypeEnum.DYNAMIC
},
{
label: '无',
value: DefaultTypeEnum.NONE
}
]
const differUnitOptions = [
// ManipulateType
{
value: DifferUnitEnum.DAY,
label: DifferUnitObject[DifferUnitEnum.DAY]
},
{
value: DifferUnitEnum.WEEK,
label: DifferUnitObject[DifferUnitEnum.WEEK]
},
{
value: DifferUnitEnum.MONTH,
label: DifferUnitObject[DifferUnitEnum.MONTH]
},
{
value: DifferUnitEnum.QUARTER,
label: DifferUnitObject[DifferUnitEnum.QUARTER]
},
{
value: DifferUnitEnum.YEAR,
label: DifferUnitObject[DifferUnitEnum.YEAR]
},
{
value: DifferUnitEnum.HOUR,
label: DifferUnitObject[DifferUnitEnum.HOUR]
},
{
value: DifferUnitEnum.MINUTE,
label: DifferUnitObject[DifferUnitEnum.MINUTE]
},
{
value: DifferUnitEnum.SECOND,
label: DifferUnitObject[DifferUnitEnum.SECOND]
},
{
value: DifferUnitEnum.MILLISECOND,
label: DifferUnitObject[DifferUnitEnum.MILLISECOND]
}
]
const isRange = computed(() => {
return props.optionData.componentInteractEventKey.endsWith('range')
})
const differValueName = computed(() => {
return isRange.value ? '开始值动态偏移量' : '动态偏移量'
})
const differUnitName = computed(() => {
return isRange.value ? '开始值偏移单位' : '偏移单位'
})
const datePickerTypeUpdate = () => {
props.optionData.dataset = isRange.value ? [dayjs().valueOf(), dayjs().valueOf()] : dayjs().valueOf()
}
const defaultTypeUpdate = (v: string) => {
if (v === DefaultTypeEnum.STATIC) {
datePickerTypeUpdate()
} else {
// DefaultTypeEnum.
props.optionData.dataset = null
}
}
</script>

View File

@@ -1,6 +1,7 @@
<template>
<n-date-picker
v-model:value="option.dataset"
clearable
:panel="!!chartConfig.option.isPanel"
:type="chartConfig.option.componentInteractEventKey"
:style="`width:${w}px;`"
@@ -9,13 +10,15 @@
</template>
<script setup lang="ts">
import { PropType, toRefs, ref, shallowReactive, watch } from 'vue'
import dayjs from 'dayjs'
import { computed, PropType, ref, shallowReactive, toRefs, watch } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useChartInteract } from '@/hooks'
import { InteractEventOn } from '@/enums/eventEnum'
import { ComponentInteractParamsEnum } from './interact'
import {ComponentInteractEventEnum, ComponentInteractParamsEnum, DefaultTypeEnum} from './interact'
import dayjs, {ManipulateType} from 'dayjs'
import quarterOfYear from 'dayjs/plugin/quarterOfYear';
const props = defineProps({
chartConfig: {
@@ -31,61 +34,107 @@ const option = shallowReactive({
dataset: props.chartConfig.option.dataset
})
const isRange = computed(() => {
return props.chartConfig.option.componentInteractEventKey.endsWith('range')
})
// 监听事件改变
const onChange = (v: number | number[]) => {
if (v instanceof Array) {
const onChange = (v: number | number[] | null) => {
if (isRange.value) {
let dateStart = null
let dateEnd = null
let daterange = null
if(v instanceof Array){
dateStart = v[0]
dateEnd = v[1]
daterange = `${v[0]}-${v[1]}`
}
// 存储到联动数据
useChartInteract(
props.chartConfig,
useChartEditStore,
{
[ComponentInteractParamsEnum.DATE_START]: v[0] || dayjs().valueOf(),
[ComponentInteractParamsEnum.DATE_END]: v[1] || dayjs().valueOf(),
[ComponentInteractParamsEnum.DATE_RANGE]: `${v[0] || dayjs().valueOf()}-${v[1] || dayjs().valueOf()}`
},
InteractEventOn.CHANGE
props.chartConfig,
useChartEditStore,
{
[ComponentInteractParamsEnum.DATE_START]: dateStart,
[ComponentInteractParamsEnum.DATE_END]: dateEnd,
[ComponentInteractParamsEnum.DATE_RANGE]: daterange
},
InteractEventOn.CHANGE
)
} else {
// 存储到联动数据
useChartInteract(
props.chartConfig,
useChartEditStore,
{ [ComponentInteractParamsEnum.DATE]: v || dayjs().valueOf() },
InteractEventOn.CHANGE
props.chartConfig,
useChartEditStore,
{ [ComponentInteractParamsEnum.DATE]: v },
InteractEventOn.CHANGE
)
}
}
watch(
() => props.chartConfig.option.dataset,
(newData: number | number[]) => {
option.dataset = newData
// 关联目标组件首次请求带上默认内容
onChange(newData)
},
{
immediate: true
const getDiffDate = (type: ComponentInteractEventEnum, date: dayjs.Dayjs) => {
// 注册 quarterOfYear 插件
dayjs.extend(quarterOfYear)
switch (type) {
case ComponentInteractEventEnum.DATE:
case ComponentInteractEventEnum.DATE_RANGE:
date = date.startOf('day')
break
case ComponentInteractEventEnum.MONTH:
case ComponentInteractEventEnum.MONTH_RANGE:
date = date.startOf('month')
break
case ComponentInteractEventEnum.YEAR:
case ComponentInteractEventEnum.YEAR_RANGE:
date = date.startOf('year')
break
case ComponentInteractEventEnum.QUARTER:
case ComponentInteractEventEnum.QUARTER_RANGE:
date = date.startOf('quarter')
break
default:
break
}
)
return date
}
// 手动更新
watch(
() => props.chartConfig.option.differValue,
(newData: number) => {
if (props.chartConfig.option.differValue === 0) return
if (typeof option.dataset === 'object') {
option.dataset[0] = dayjs().add(newData, 'day').valueOf()
option.dataset[1] = dayjs().add(newData, 'day').valueOf()
} else {
option.dataset = dayjs().add(newData, 'day').valueOf()
() => {
return {
type: props.chartConfig.option.componentInteractEventKey as ComponentInteractEventEnum,
defaultType: props.chartConfig.option.defaultType as string,
differValue: props.chartConfig.option.differValue as number[],
differUnit: props.chartConfig.option.differUnit as ManipulateType[],
dataset: props.chartConfig.option.dataset as number | number[] | null,
};
},
(newData, oldData) => {
const hasTypeChanged = newData.type !== oldData?.type;
const hasDefaultTypeChanged = newData.defaultType !== oldData?.defaultType;
const hasDifferValueChanged = newData.differValue !== oldData?.differValue;
const hasDifferUnitChanged = newData.differUnit !== oldData?.differUnit;
if (hasTypeChanged || hasDefaultTypeChanged || hasDifferValueChanged || hasDifferUnitChanged) {
if (newData.defaultType === DefaultTypeEnum.NONE) {
props.chartConfig.option.dataset = null;
} else if (newData.defaultType === DefaultTypeEnum.DYNAMIC) {
let date = dayjs();
if (isRange.value) {
props.chartConfig.option.dataset = [
getDiffDate(newData.type,date.add(newData.differValue[0], newData.differUnit[0])).valueOf(),
getDiffDate(newData.type,date.add(newData.differValue[1], newData.differUnit[1])).valueOf(),
];
} else {
props.chartConfig.option.dataset = getDiffDate(newData.type,date.add(newData.differValue[0], newData.differUnit[0])).valueOf()
}
}
}
option.dataset = props.chartConfig.option.dataset;
onChange(option.dataset);
},
{
immediate: true,
}
// 关联目标组件首次请求带上默认内容
onChange(newData)
},
{
immediate: true
}
)
);
</script>
<style lang="scss" scoped>

View File

@@ -22,6 +22,37 @@ export enum ComponentInteractParamsEnum {
DATE_RANGE = 'daterange'
}
export enum DefaultTypeEnum {
NONE = "none",
STATIC = "static",
DYNAMIC = "dynamic"
}
export enum DifferUnitEnum {
DAY = 'd',
WEEK = 'w',
MONTH = 'M',
QUARTER = 'Q',
YEAR = 'y',
HOUR = 'h',
MINUTE = 'm',
SECOND = 's',
MILLISECOND = 'ms',
}
export const DifferUnitObject = {
// https://day.js.org/docs/en/manipulate/add
[DifferUnitEnum.DAY]: '天',
[DifferUnitEnum.WEEK]: '周',
[DifferUnitEnum.MONTH]: '月',
[DifferUnitEnum.QUARTER]: '季度',
[DifferUnitEnum.YEAR]: '年',
[DifferUnitEnum.HOUR]: '小时',
[DifferUnitEnum.MINUTE]: '分钟',
[DifferUnitEnum.SECOND]: '秒',
[DifferUnitEnum.MILLISECOND]: '毫秒',
}
const time = [
{
value: ComponentInteractParamsEnum.DATE,

View File

@@ -1,8 +1,11 @@
<template>
<collapse-item name="标签页配置" :expanded="true">
<setting-item-box name="默认值" :alone="true">
<setting-item-box name="标签类型" :alone="true">
<n-select size="small" v-model:value="optionData.tabType" :options="tabTypeOptions" />
</setting-item-box>
<setting-item-box name="默认值" :alone="true">
<n-select size="small" v-model:value="optionData.tabLabel" value-field="label" :options="optionData.dataset" />
</setting-item-box>
</collapse-item>
</template>

View File

@@ -1,5 +1,5 @@
<template>
<n-tabs :type="option.value.tabType" @update:value="onChange">
<n-tabs :type="option.value.tabType" @update:value="onChange" :default-value="option.value.tabLabel">
<n-tab v-for="(item, index) in option.value.dataset" :name="item.label" :key="index"> {{ item.label }} </n-tab>
</n-tabs>
</template>

View File

@@ -1,78 +1,84 @@
@import './config.scss';
@import './function.scss';
@import '../theme.scss';
@mixin go($block) {
$B: $namespace + '-' + $block;
.#{$B} {
@content;
}
}
@mixin goId($block) {
$B: $namespace + '-' + $block;
##{$B} {
@content;
}
}
@mixin deep() {
:deep() {
@content;
}
}
@mixin when($state) {
@at-root {
&.#{$state-prefix + $state} {
@content;
}
}
}
@mixin themeify {
@each $theme-name, $theme-map in $themes {
$theme-map: $theme-map !global;
[data-theme='#{$theme-name}'] & {
@content;
}
}
}
@mixin fetch-theme($param) {
@include themeify {
#{$param}: themed($param);
}
}
@mixin fetch-theme-custom ($key, $value) {
@include themeify {
#{$key}: themed($value);
}
}
//获取背景颜色
@mixin fetch-bg-color($target) {
@include themeify {
background-color: themed($target);
}
}
//获取背景渐变颜色
@mixin background-image($target) {
@include themeify {
background-image: themed($target);
}
}
//设置边框颜色
@mixin fetch-border-color($target) {
@include themeify {
border-color: themed($target);
}
}
@mixin hover-border-color($target) {
@include themeify {
border: 1px solid themed($target);
}
}
@import './config.scss';
@import './function.scss';
@import '../theme.scss';
@mixin go($block) {
$B: $namespace + '-' + $block;
.#{$B} {
@content;
}
}
@mixin dark {
[data-theme='dark'] {
@content;
}
}
@mixin goId($block) {
$B: $namespace + '-' + $block;
##{$B} {
@content;
}
}
@mixin deep() {
:deep() {
@content;
}
}
@mixin when($state) {
@at-root {
&.#{$state-prefix + $state} {
@content;
}
}
}
@mixin themeify {
@each $theme-name, $theme-map in $themes {
$theme-map: $theme-map !global;
[data-theme='#{$theme-name}'] & {
@content;
}
}
}
@mixin fetch-theme($param) {
@include themeify {
#{$param}: themed($param);
}
}
@mixin fetch-theme-custom ($key, $value) {
@include themeify {
#{$key}: themed($value);
}
}
//获取背景颜色
@mixin fetch-bg-color($target) {
@include themeify {
background-color: themed($target);
}
}
//获取背景渐变颜色
@mixin background-image($target) {
@include themeify {
background-image: themed($target);
}
}
//设置边框颜色
@mixin fetch-border-color($target) {
@include themeify {
border-color: themed($target);
}
}
@mixin hover-border-color($target) {
@include themeify {
border: 1px solid themed($target);
}
}

View File

@@ -1,9 +1,15 @@
// 页面全局样式
// 去除高德地图 logo
.amap-logo {
display: none !important;
opacity: 0 !important;
}
.amap-copyright {
opacity: 0 !important;
}
// 页面全局样式
// 去除高德地图 logo
.amap-logo {
display: none !important;
opacity: 0 !important;
}
.amap-copyright {
opacity: 0 !important;
}
[data-theme='dark'] {
body {
background-color: #18181c;
}
}

View File

@@ -330,3 +330,23 @@ export const JSONParse = (data: string) => {
export const setTitle = (title?: string) => {
title && (document.title = title)
}
/**
* 处理网页关闭事件
*/
export const addWindowUnload = () => {
// 关闭网页出现离开提示
window.onbeforeunload = function (e) {
e = e || window.event
// 兼容IE8和Firefox 4之前的版本
if (e) {
e.returnValue = '您确定要离开当前页面吗?请确认是否保存数据!'
}
// Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
return '您确定要离开当前页面吗?请确认是否保存数据!'
}
// 返回销毁事件函数
return () => {
window.onbeforeunload = null
}
}

View File

@@ -131,7 +131,11 @@ const sendHandle = async () => {
loading.value = false
if (res) {
const { data } = res
if (!data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
if (!data && !targetData.value.filter) {
window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
showMatching.value = true
return
}
targetData.value.option.dataset = newFunctionHandle(data, res, targetData.value.filter)
showMatching.value = true
return

View File

@@ -117,7 +117,11 @@ const sendHandle = async () => {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
loading.value = false
if (res) {
if (!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
if (!res?.data && !targetData.value.filter) {
window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
showMatching.value = true
return
}
targetData.value.option.dataset = newFunctionHandle(res?.data, res, targetData.value.filter)
showMatching.value = true
return

View File

@@ -58,7 +58,7 @@
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
<n-text>不支持静态组件</n-text>
<n-text>不支持静态组件支持组件公共APi</n-text>
</n-tooltip>
</template>
<n-select
@@ -89,7 +89,7 @@
</n-table>
</setting-item-box>
<n-tag :bordered="false" type="primary"> 关联目标组件请求参数 </n-tag>
<n-tag :bordered="false" type="primary"> 关联目标请求参数 </n-tag>
<setting-item-box
:name="requestParamsItem"
@@ -125,7 +125,7 @@ import { VNodeChild, computed } from 'vue'
import { SelectOption, SelectGroupOption } from 'naive-ui'
import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting'
import { CreateComponentType, CreateComponentGroupType, ChartFrameEnum } from '@/packages/index.d'
import { RequestParamsTypeEnum } from '@/enums/httpEnum'
import { RequestParamsTypeEnum, RequestDataTypeEnum } from '@/enums/httpEnum'
import { InteractEventOn, COMPONENT_INTERACT_EVENT_KET } from '@/enums/eventEnum'
import { icon } from '@/plugins'
import noData from '@/assets/images/canvas/noData.png'
@@ -154,6 +154,11 @@ const option = computed(() => {
// 绑定组件数据 request
const fnGetRequest = (id: string | undefined, key: RequestParamsTypeEnum) => {
if (!id) return {}
const globalConfigPindApr = chartEditStore.requestGlobalConfig.requestDataPond.find(item => {
return item.dataPondId === id
})?.dataPondRequestConfig.requestParams
if (globalConfigPindApr) return globalConfigPindApr[key]
return chartEditStore.componentList[chartEditStore.fetchTargetIndex(id)]?.request.requestParams[key]
}
@@ -178,12 +183,10 @@ const fnEventsOptions = (): Array<SelectOption | SelectGroupOption> => {
iter: Array<CreateComponentType | CreateComponentGroupType>,
val: CreateComponentType | CreateComponentGroupType
) => {
if (val.groupList && val.groupList.length > 0) {
iter.push(val)
} else {
if (!val.groupList && val.request.requestDataType === RequestDataTypeEnum.AJAX && val.request.requestUrl) {
iter.push(val)
}
return val.groupList ? [...iter, ...fnFlattern(val.groupList)] : iter
return val.groupList && val.groupList.length > 0 ? [...iter, ...fnFlattern(val.groupList)] : iter
},
[]
)
@@ -203,18 +206,26 @@ const fnEventsOptions = (): Array<SelectOption | SelectGroupOption> => {
const mapOptionList = filterOptionList.map(item => ({
id: item.id,
title: item.chartConfig.title,
disabled: false
disabled: false,
type: 'componentList'
}))
const requestDataPond = chartEditStore.requestGlobalConfig.requestDataPond.map(item => ({
id: item.dataPondId,
title: item.dataPondName,
disabled: false,
type: 'requestDataPond'
}))
const tarArr = requestDataPond.concat(mapOptionList)
targetData.value.events.interactEvents?.forEach(iaItem => {
mapOptionList.forEach(optionItem => {
tarArr.forEach(optionItem => {
if (optionItem.id === iaItem.interactComponentId) {
optionItem.disabled = true
}
})
})
return mapOptionList
return tarArr
}
// 新增模块

View File

@@ -159,9 +159,11 @@ const dragCanvas = (e: any) => {
const canvasBox = () => {
const layoutDom = document.getElementById('go-chart-edit-layout')
if (layoutDom) {
// 此处减去滚动条的宽度和高度
const scrollW = 20
return {
height: layoutDom.clientHeight - 25,
width: layoutDom.clientWidth
height: layoutDom.clientHeight - scrollW,
width: layoutDom.clientWidth - scrollW
}
}
return {

View File

@@ -87,7 +87,14 @@ import { onMounted, computed, provide } from 'vue'
import { chartColors } from '@/settings/chartThemes/index'
import { MenuEnum } from '@/enums/editPageEnum'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle, colorCustomMerge } from '@/utils'
import {
animationsClass,
getFilterStyle,
getTransformStyle,
getBlendModeStyle,
colorCustomMerge,
addWindowUnload
} from '@/utils'
import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook'
import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@@ -110,6 +117,9 @@ const chartEditStore = useChartEditStore()
const { handleContextMenu } = useContextMenu()
const { dataSyncFetch, intervalDataSyncUpdate } = useSync()
// 加入网页关闭提示
addWindowUnload()
// 编辑时注入scale变量消除警告
provide(SCALE_KEY, null)
@@ -186,7 +196,7 @@ onMounted(() => {
// 获取数据
dataSyncFetch()
// 定时更新数据
intervalDataSyncUpdate()
// intervalDataSyncUpdate()
})
</script>

View File

@@ -74,7 +74,7 @@ const themeColor = computed(() => {
// 组件渲染结束初始化数据池
clearMittDataPondMap()
onMounted(() => {
initDataPond(chartEditStore.requestGlobalConfig)
initDataPond(useChartEditStore)
})
</script>

View File

@@ -13,7 +13,44 @@ export const useScale = (localStorageInfo: ChartEditStorageType) => {
const height = ref(localStorageInfo.editCanvasConfig.height)
const scaleRef = ref({ width: 1, height: 1 })
provide(SCALE_KEY, scaleRef);
provide(SCALE_KEY, scaleRef)
// 监听鼠标滚轮 +ctrl 键
const useAddWheelHandle = (removeEvent: Function) => {
addEventListener(
'wheel',
(e: any) => {
if (window?.$KeyboardActive?.ctrl) {
e.preventDefault()
e.stopPropagation()
removeEvent()
const transform = previewRef.value?.style.transform
const regRes = transform.match(/scale\((\d+\.?\d*)*/) as RegExpMatchArray
const width = regRes[1]
const previewBoxDom = document.querySelector('.go-preview') as HTMLElement
const entityDom = document.querySelector('.go-preview-entity') as HTMLElement
if (previewBoxDom) {
previewBoxDom.style.overflow = 'unset'
previewBoxDom.style.position = 'absolute'
previewBoxDom.style.top = '10px'
previewBoxDom.style.left = '20px'
}
if (entityDom) {
entityDom.style.overflow = 'unset'
}
if (e.wheelDelta > 0) {
const resNum = parseFloat(Number(width).toFixed(2))
previewRef.value.style.transform = `scale(${resNum > 5 ? 5 : resNum + 0.1})`
} else {
const resNum = parseFloat(Number(width).toFixed(2))
previewRef.value.style.transform = `scale(${resNum < 0.2 ? 0.2 : resNum - 0.1})`
}
}
},
{ passive: false }
)
}
const updateScaleRef = (scale: { width: number; height: number }) => {
// 这里需要解构保证赋值给scaleRef的为一个新对象
@@ -24,74 +61,82 @@ export const useScale = (localStorageInfo: ChartEditStorageType) => {
// 屏幕适配
onMounted(() => {
switch (localStorageInfo.editCanvasConfig.previewScaleType) {
case PreviewScaleEnum.FIT: (() => {
const { calcRate, windowResize, unWindowResize } = usePreviewFitScale(
width.value as number,
height.value as number,
previewRef.value,
updateScaleRef
)
calcRate()
windowResize()
onUnmounted(() => {
unWindowResize()
})
})()
break;
case PreviewScaleEnum.SCROLL_Y: (() => {
const { calcRate, windowResize, unWindowResize } = usePreviewScrollYScale(
width.value as number,
height.value as number,
previewRef.value,
(scale) => {
const dom = entityRef.value
dom.style.width = `${width.value * scale.width}px`
dom.style.height = `${height.value * scale.height}px`
updateScaleRef(scale)
}
)
calcRate()
windowResize()
onUnmounted(() => {
unWindowResize()
})
})()
case PreviewScaleEnum.FIT:
;(() => {
const { calcRate, windowResize, unWindowResize } = usePreviewFitScale(
width.value as number,
height.value as number,
previewRef.value,
updateScaleRef
)
calcRate()
windowResize()
useAddWheelHandle(unWindowResize)
onUnmounted(() => {
unWindowResize()
})
})()
break
case PreviewScaleEnum.SCROLL_Y:
;(() => {
const { calcRate, windowResize, unWindowResize } = usePreviewScrollYScale(
width.value as number,
height.value as number,
previewRef.value,
scale => {
const dom = entityRef.value
dom.style.width = `${width.value * scale.width}px`
dom.style.height = `${height.value * scale.height}px`
updateScaleRef(scale)
}
)
calcRate()
windowResize()
useAddWheelHandle(unWindowResize)
onUnmounted(() => {
unWindowResize()
})
})()
break;
case PreviewScaleEnum.SCROLL_X: (() => {
const { calcRate, windowResize, unWindowResize } = usePreviewScrollXScale(
width.value as number,
height.value as number,
previewRef.value,
(scale) => {
const dom = entityRef.value
dom.style.width = `${width.value * scale.width}px`
dom.style.height = `${height.value * scale.height}px`
updateScaleRef(scale)
}
)
calcRate()
windowResize()
onUnmounted(() => {
unWindowResize()
})
})()
break
case PreviewScaleEnum.SCROLL_X:
;(() => {
const { calcRate, windowResize, unWindowResize } = usePreviewScrollXScale(
width.value as number,
height.value as number,
previewRef.value,
scale => {
const dom = entityRef.value
dom.style.width = `${width.value * scale.width}px`
dom.style.height = `${height.value * scale.height}px`
updateScaleRef(scale)
}
)
calcRate()
windowResize()
useAddWheelHandle(unWindowResize)
onUnmounted(() => {
unWindowResize()
})
})()
break;
case PreviewScaleEnum.FULL: (() => {
const { calcRate, windowResize, unWindowResize } = usePreviewFullScale(
width.value as number,
height.value as number,
previewRef.value,
updateScaleRef
)
calcRate()
windowResize()
onUnmounted(() => {
unWindowResize()
})
})()
break;
break
case PreviewScaleEnum.FULL:
;(() => {
const { calcRate, windowResize, unWindowResize } = usePreviewFullScale(
width.value as number,
height.value as number,
previewRef.value,
updateScaleRef
)
calcRate()
windowResize()
useAddWheelHandle(unWindowResize)
onUnmounted(() => {
unWindowResize()
})
})()
break
}
})

View File

@@ -1,5 +1,5 @@
<template>
<div :class="`go-preview ${chartEditStore.editCanvasConfig.previewScaleType}`">
<div :class="`go-preview ${chartEditStore.editCanvasConfig.previewScaleType}`" @mousedown="dragCanvas">
<template v-if="showEntity">
<!-- 实体区域 -->
<div ref="entityRef" class="go-preview-entity">
@@ -30,7 +30,7 @@
import { computed } from 'vue'
import { PreviewRenderList } from './components/PreviewRenderList'
import { getFilterStyle, setTitle } from '@/utils'
import { getEditCanvasConfigStyle, getSessionStorageInfo } from './utils'
import { getEditCanvasConfigStyle, getSessionStorageInfo, keyRecordHandle, dragCanvas } from './utils'
import { useComInstall } from './hooks/useComInstall.hook'
import { useScale } from './hooks/useScale.hook'
import { useStore } from './hooks/useStore.hook'
@@ -60,6 +60,9 @@ const showEntity = computed(() => {
useStore(chartEditStore)
const { entityRef, previewRef } = useScale(chartEditStore)
const { show } = useComInstall(chartEditStore)
// 开启键盘监听
keyRecordHandle()
</script>
<style lang="scss" scoped>

View File

@@ -0,0 +1,55 @@
import { listen } from 'dom-helpers'
import throttle from 'lodash/throttle'
let prevMoveXValue = [0, 0]
let prevMoveYValue = [0, 0]
// 拖拽处理
export const dragCanvas = (e: MouseEvent) => {
const previewBoxDom = document.querySelector('.go-preview') as HTMLElement
if (!previewBoxDom || previewBoxDom.style.position !== 'absolute') return
if (!window.$KeyboardActive?.space) return
e.preventDefault()
e.stopPropagation()
// @ts-ignore
document.activeElement?.blur()
const startX = e.screenX
const startY = e.screenY
const listenMousemove = listen(
window,
'mousemove',
throttle((moveEvent: MouseEvent) => {
const nx = moveEvent.screenX - startX
const ny = moveEvent.screenY - startY
const [prevMoveX1, prevMoveX2] = prevMoveXValue
const [prevMoveY1, prevMoveY2] = prevMoveYValue
prevMoveXValue = [prevMoveX2, nx]
prevMoveYValue = [prevMoveY2, ny]
// 去除小数部分
if (previewBoxDom) {
const oldLeft = previewBoxDom.style.left ? Number(previewBoxDom.style.left.split('px')[0]) : 0
const oldTop = previewBoxDom.style.top ? Number(previewBoxDom.style.top.split('px')[0]) : 0
previewBoxDom.style.left =
oldLeft +
(prevMoveX2 > prevMoveX1 ? Math.abs(prevMoveX2 - prevMoveX1) : -Math.abs(prevMoveX2 - prevMoveX1)) +
'px'
previewBoxDom.style.top =
oldTop +
(prevMoveY2 > prevMoveY1 ? Math.abs(prevMoveY2 - prevMoveY1) : -Math.abs(prevMoveY2 - prevMoveY1)) +
'px'
}
}, 20)
)
const listenMouseup = listen(window, 'mouseup', () => {
prevMoveXValue = [0, 0]
prevMoveYValue = [0, 0]
listenMousemove()
listenMouseup()
})
}

View File

@@ -1,2 +1,4 @@
export * from './style'
export * from './storage'
export * from './style'
export * from './storage'
export * from './keyboard'
export * from './drag'

View File

@@ -0,0 +1,49 @@
// 处理键盘记录
export const keyRecordHandle = () => {
// 默认赋值
window.$KeyboardActive = {
ctrl: false,
space: false
}
document.onkeydown = (e: KeyboardEvent) => {
const { keyCode } = e
if (keyCode == 32 && e.target == document.body) e.preventDefault()
if ([17, 32].includes(keyCode) && window.$KeyboardActive) {
switch (keyCode) {
case 17:
window.$KeyboardActive.ctrl = true
break
case 32:
window.$KeyboardActive.space = true
const previewBoxDom = document.querySelector('.go-preview') as HTMLElement
if (previewBoxDom && previewBoxDom.style.position === 'absolute') {
previewBoxDom.style.cursor = 'move'
}
break
}
}
}
document.onkeyup = (e: KeyboardEvent) => {
const { keyCode } = e
if (keyCode == 32 && e.target == document.body) e.preventDefault()
if ([17, 32].includes(keyCode) && window.$KeyboardActive) {
switch (keyCode) {
case 17:
window.$KeyboardActive.ctrl = false
break
case 32:
window.$KeyboardActive.space = false
break
}
}
const previewBoxDom = document.querySelector('.go-preview') as HTMLElement
if (previewBoxDom) {
previewBoxDom.style.cursor = 'default'
}
}
}

View File

@@ -5,4 +5,5 @@ declare module '*.vue' {
}
declare module 'lodash/*'
declare module 'dom-helpers'
declare module 'dom-helpers'
declare module '@iconify/vue'