Merge branch 'dev'

This commit is contained in:
奔跑的面条 2023-07-08 21:48:53 +08:00
commit 084441d365
25 changed files with 808 additions and 417 deletions

View File

@ -1,4 +1,4 @@
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios' import axios, { AxiosResponse, InternalAxiosRequestConfig, AxiosError } from 'axios'
import { ResultEnum } from "@/enums/httpEnum" import { ResultEnum } from "@/enums/httpEnum"
import { ErrorPageNameMap } from "@/enums/pageEnum" import { ErrorPageNameMap } from "@/enums/pageEnum"
import { redirectErrorPage } from '@/utils' import { redirectErrorPage } from '@/utils'
@ -9,10 +9,10 @@ const axiosInstance = axios.create({
}) })
axiosInstance.interceptors.request.use( axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => { (config: InternalAxiosRequestConfig) => {
return config return config
}, },
(error: AxiosRequestConfig) => { (error: AxiosError) => {
Promise.reject(error) Promise.reject(error)
} }
) )

View File

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

View File

@ -391,7 +391,11 @@ const visualMap = computed(() => {
// legend colortype = scroll // legend colortype = scroll
watch(() => legend.value && legend.value.textStyle.color, (newVal) => { watch(() => legend.value && legend.value.textStyle.color, (newVal) => {
if (legend.value && 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, immediate: true,

View File

@ -69,6 +69,22 @@
</setting-item> </setting-item>
</setting-item-box> </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"> <setting-item-box v-if="!isCanvas" :alone="true">
<template #name> <template #name>
@ -149,10 +165,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from 'vue' import { ref, PropType } from 'vue'
import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d' import { PickCreateComponentType, BlendModeEnumList } from '@/packages/index.d'
import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting' import { SettingItemBox, SettingItem, CollapseItem } from '@/components/Pages/ChartItemSetting'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import logoImg from '@/assets/logo.png'
import { useDesignStore } from '@/store/modules/designStore/designStore'
const props = defineProps({ const props = defineProps({
isGroup: { isGroup: {
@ -175,10 +193,48 @@ const { HelpOutlineIcon } = icon.ionicons5
const sliderFormatTooltip = (v: string) => { const sliderFormatTooltip = (v: string) => {
return `${(parseFloat(v) * 100).toFixed(0)}%` return `${(parseFloat(v) * 100).toFixed(0)}%`
} }
// //
const degFormatTooltip = (v: string) => { const degFormatTooltip = (v: string) => {
return `${v}deg` 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> </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( watch(
() => targetComponent.request, () => targetComponent.request.requestParams,
() => { () => {
fetchFn() fetchFn()
}, },
{ {
immediate: true, immediate: false,
deep: true deep: true
} }
) )
@ -105,7 +105,11 @@ export const useChartDataFetch = (
// 单位 // 单位
const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value
// 开启轮询 // 开启轮询
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit)) if (time) {
fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
} else {
fetchFn()
}
} }
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
} catch (error) { } catch (error) {
@ -114,10 +118,11 @@ export const useChartDataFetch = (
} }
if (isPreview()) { if (isPreview()) {
// 判断是否是数据池类型
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle) ? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
: requestIntervalFn() : requestIntervalFn()
} else {
requestIntervalFn()
} }
return { vChartRef } 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 { customizeHttp } from '@/api/http'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@ -20,7 +20,7 @@ const mittDataPondMap = new Map<string, DataPondMapType[]>()
// 创建单个数据项轮询接口 // 创建单个数据项轮询接口
const newPondItemInterval = ( const newPondItemInterval = (
requestGlobalConfig: RequestGlobalConfigType, requestGlobalConfig: RequestGlobalConfigType,
requestDataPondItem: RequestDataPondItemType, requestDataPondItem: ComputedRef<RequestDataPondItemType>,
dataPondMapItem?: DataPondMapType[] dataPondMapItem?: DataPondMapType[]
) => { ) => {
if (!dataPondMapItem) return if (!dataPondMapItem) return
@ -31,8 +31,7 @@ const newPondItemInterval = (
// 请求 // 请求
const fetchFn = async () => { const fetchFn = async () => {
try { try {
const res = await customizeHttp(toRaw(requestDataPondItem.dataPondRequestConfig), toRaw(requestGlobalConfig)) const res = await customizeHttp(toRaw(requestDataPondItem.value.dataPondRequestConfig), toRaw(requestGlobalConfig))
if (res) { if (res) {
try { try {
// 遍历更新回调函数 // 遍历更新回调函数
@ -49,19 +48,32 @@ const newPondItemInterval = (
} }
} }
watch(
() => requestDataPondItem.value.dataPondRequestConfig.requestParams.Params,
() => {
fetchFn()
},
{
immediate: false,
deep: true
}
)
// 立即调用 // 立即调用
fetchFn() 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 globalRequestInterval = requestGlobalConfig.requestInterval
const globalUnit = requestGlobalConfig.requestIntervalUnit 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)) if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
} }
@ -96,13 +108,16 @@ export const useChartDataPondFetch = () => {
} }
// 初始化数据池 // 初始化数据池
const initDataPond = (requestGlobalConfig: RequestGlobalConfigType) => { const initDataPond = (useChartEditStore: ChartEditStoreType) => {
const { requestDataPond } = requestGlobalConfig const { requestGlobalConfig } = useChartEditStore()
const chartEditStore = useChartEditStore()
// 根据 mapId 查找对应的数据池配置 // 根据 mapId 查找对应的数据池配置
for (let pondKey of mittDataPondMap.keys()) { 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) { 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 { toRefs } from 'vue'
import { isPreview } from '@/utils'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@ -12,6 +13,7 @@ export const useChartInteract = (
param: { [T: string]: any }, param: { [T: string]: any },
interactEventOn: string interactEventOn: string
) => { ) => {
if (!isPreview()) return
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const { interactEvents } = chartConfig.events const { interactEvents } = chartConfig.events
const fnOnEvent = interactEvents.filter(item => { const fnOnEvent = interactEvents.filter(item => {
@ -20,20 +22,37 @@ export const useChartInteract = (
if (fnOnEvent.length === 0) return if (fnOnEvent.length === 0) return
fnOnEvent.forEach(item => { fnOnEvent.forEach(item => {
const index = chartEditStore.fetchTargetIndex(item.interactComponentId)
if (index === -1) return const globalConfigPindAprndex = chartEditStore.requestGlobalConfig.requestDataPond.findIndex(cItem =>
const { Params, Header } = toRefs(chartEditStore.componentList[index].request.requestParams) cItem.dataPondId === item.interactComponentId
Object.keys(item.interactFn).forEach(key => { )
if (Params.value[key]) { if (globalConfigPindAprndex !== -1) {
Params.value[key] = param[item.interactFn[key]] const { Params, Header } = toRefs(chartEditStore.requestGlobalConfig.requestDataPond[globalConfigPindAprndex].dataPondRequestConfig.requestParams)
}
if (Header.value[key]) { Object.keys(item.interactFn).forEach(key => {
Header.value[key] = param[item.interactFn[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 变更时,清除当前绑定内容 // 联动事件触发的 type 变更时,清除当前绑定内容
export const clearInteractEvent = (chartConfig: CreateComponentType) => { export const clearInteractEvent = (chartConfig: CreateComponentType) => {

View File

@ -54,7 +54,7 @@ export const usePreviewFitScale = (
window.addEventListener('resize', resize) window.addEventListener('resize', resize)
} }
// * 改变窗口大小重新绘制 // * 卸载监听
const unWindowResize = () => { const unWindowResize = () => {
window.removeEventListener('resize', resize) window.removeEventListener('resize', resize)
} }
@ -106,7 +106,7 @@ export const usePreviewScrollYScale = (
window.addEventListener('resize', resize) window.addEventListener('resize', resize)
} }
// * 改变窗口大小重新绘制 // * 卸载监听
const unWindowResize = () => { const unWindowResize = () => {
window.removeEventListener('resize', resize) window.removeEventListener('resize', resize)
} }
@ -158,7 +158,7 @@ export const usePreviewScrollXScale = (
window.addEventListener('resize', resize) window.addEventListener('resize', resize)
} }
// * 改变窗口大小重新绘制 // * 卸载监听
const unWindowResize = () => { const unWindowResize = () => {
window.removeEventListener('resize', resize) window.removeEventListener('resize', resize)
} }
@ -205,7 +205,7 @@ export const usePreviewFullScale = (
window.addEventListener('resize', resize) window.addEventListener('resize', resize)
} }
// * 改变窗口大小重新绘制 // * 卸载监听
const unWindowResize = () => { const unWindowResize = () => {
window.removeEventListener('resize', resize) window.removeEventListener('resize', resize)
} }

View File

@ -1,5 +1,5 @@
export default { export default {
create_btn: 'Creat', create_btn: 'Create',
create_tip: 'Please select a content for development', create_tip: 'Please select a content for development',
project: 'Project', project: 'Project',
my: 'My', my: 'My',

View File

@ -7,6 +7,22 @@
</n-input-number> </n-input-number>
</SettingItem> </SettingItem>
</SettingItemBox> </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 全局设置 --> <!-- Echarts 全局设置 -->
<SettingItemBox name="进度条"> <SettingItemBox name="进度条">
<SettingItem name="颜色"> <SettingItem name="颜色">
@ -31,24 +47,8 @@
></n-color-picker> ></n-color-picker>
</SettingItem> </SettingItem>
</SettingItemBox> </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="颜色"> <SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.data[1].itemStyle.color"></n-color-picker> <n-color-picker size="small" :modes="['hex']" v-model:value="item.data[1].itemStyle.color"></n-color-picker>
</SettingItem> </SettingItem>
@ -69,6 +69,18 @@
v-model:value="item.data[1].itemStyle.shadowColor" v-model:value="item.data[1].itemStyle.shadowColor"
></n-color-picker> ></n-color-picker>
</SettingItem> </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> </SettingItemBox>
</CollapseItem> </CollapseItem>
</template> </template>

View File

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

View File

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

View File

@ -4,7 +4,7 @@ import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { chartInitConfig } from '@/settings/designSetting' import { chartInitConfig } from '@/settings/designSetting'
import { COMPONENT_INTERACT_EVENT_KET } from '@/enums/eventEnum' import { COMPONENT_INTERACT_EVENT_KET } from '@/enums/eventEnum'
import { interactActions, ComponentInteractEventEnum } from './interact' import { interactActions, ComponentInteractEventEnum, DefaultTypeEnum, DifferUnitEnum } from './interact'
import { InputsDateConfig } from './index' import { InputsDateConfig } from './index'
export const option = { export const option = {
@ -12,9 +12,14 @@ export const option = {
[COMPONENT_INTERACT_EVENT_KET]: ComponentInteractEventEnum.DATE, [COMPONENT_INTERACT_EVENT_KET]: ComponentInteractEventEnum.DATE,
// 下拉展示 // 下拉展示
isPanel: 0, 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 { export default class Config extends PublicConfigClass implements CreateComponentType {

View File

@ -8,39 +8,67 @@
<collapse-item name="时间配置" :expanded="true"> <collapse-item name="时间配置" :expanded="true">
<setting-item-box name="基础"> <setting-item-box name="基础">
<setting-item 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>
</setting-item-box> </setting-item-box>
<setting-item-box name="默认值" :alone="true"> <setting-item-box name="默认值">
<n-date-picker size="small" v-model:value="optionData.dataset" :type="optionData.componentInteractEventKey" /> <setting-item name="类型">
</setting-item-box> <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> <template #name>
<n-text>动态</n-text> <n-text></n-text>
<n-tooltip trigger="hover"> <n-tooltip trigger="hover">
<template #trigger> <template #trigger>
<n-icon size="21" :depth="3"> <n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon> <help-outline-icon></help-outline-icon>
</n-icon> </n-icon>
</template> </template>
<n-text>动态值不为0时默认值:取当天时间相加当前值</n-text> <span>打开页面时浏览器操作系统的系统时间+偏移量(单位)</span>
</n-tooltip> </n-tooltip>
</template> </template>
<n-input-number v-model:value="optionData.differValue" class="input-num-width" size="small" :min="-40" :max="40"> <setting-item :name="differValueName">
<template #suffix> </template> <n-input-number v-model:value="optionData.differValue[0]" class="input-num-width" size="small">
</n-input-number> <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> </setting-item-box>
</collapse-item> </collapse-item>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { PropType } from 'vue' import { PropType, computed } from 'vue'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { option } from './config' import { option } from './config'
import { ComponentInteractEventEnum } from './interact' import { ComponentInteractEventEnum, DefaultTypeEnum, DifferUnitEnum, DifferUnitObject } from './interact'
import dayjs from "dayjs";
const { HelpOutlineIcon } = icon.ionicons5 const { HelpOutlineIcon } = icon.ionicons5
@ -100,4 +128,87 @@ const datePickerTypeOptions = [
value: ComponentInteractEventEnum.QUARTER_RANGE 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> </script>

View File

@ -1,6 +1,7 @@
<template> <template>
<n-date-picker <n-date-picker
v-model:value="option.dataset" v-model:value="option.dataset"
clearable
:panel="!!chartConfig.option.isPanel" :panel="!!chartConfig.option.isPanel"
:type="chartConfig.option.componentInteractEventKey" :type="chartConfig.option.componentInteractEventKey"
:style="`width:${w}px;`" :style="`width:${w}px;`"
@ -9,13 +10,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, toRefs, ref, shallowReactive, watch } from 'vue' import { computed, PropType, ref, shallowReactive, toRefs, watch } from 'vue'
import dayjs from 'dayjs'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useChartInteract } from '@/hooks' import { useChartInteract } from '@/hooks'
import { InteractEventOn } from '@/enums/eventEnum' 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({ const props = defineProps({
chartConfig: { chartConfig: {
@ -31,61 +34,107 @@ const option = shallowReactive({
dataset: props.chartConfig.option.dataset dataset: props.chartConfig.option.dataset
}) })
const isRange = computed(() => {
return props.chartConfig.option.componentInteractEventKey.endsWith('range')
})
// //
const onChange = (v: number | number[]) => { const onChange = (v: number | number[] | null) => {
if (v instanceof Array) { 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( useChartInteract(
props.chartConfig, props.chartConfig,
useChartEditStore, useChartEditStore,
{ {
[ComponentInteractParamsEnum.DATE_START]: v[0] || dayjs().valueOf(), [ComponentInteractParamsEnum.DATE_START]: dateStart,
[ComponentInteractParamsEnum.DATE_END]: v[1] || dayjs().valueOf(), [ComponentInteractParamsEnum.DATE_END]: dateEnd,
[ComponentInteractParamsEnum.DATE_RANGE]: `${v[0] || dayjs().valueOf()}-${v[1] || dayjs().valueOf()}` [ComponentInteractParamsEnum.DATE_RANGE]: daterange
}, },
InteractEventOn.CHANGE InteractEventOn.CHANGE
) )
} else { } else {
// //
useChartInteract( useChartInteract(
props.chartConfig, props.chartConfig,
useChartEditStore, useChartEditStore,
{ [ComponentInteractParamsEnum.DATE]: v || dayjs().valueOf() }, { [ComponentInteractParamsEnum.DATE]: v },
InteractEventOn.CHANGE InteractEventOn.CHANGE
) )
} }
} }
watch( const getDiffDate = (type: ComponentInteractEventEnum, date: dayjs.Dayjs) => {
() => props.chartConfig.option.dataset, // quarterOfYear
(newData: number | number[]) => { dayjs.extend(quarterOfYear)
option.dataset = newData switch (type) {
// case ComponentInteractEventEnum.DATE:
onChange(newData) case ComponentInteractEventEnum.DATE_RANGE:
}, date = date.startOf('day')
{ break
immediate: true 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( watch(
() => props.chartConfig.option.differValue, () => {
(newData: number) => { return {
if (props.chartConfig.option.differValue === 0) return type: props.chartConfig.option.componentInteractEventKey as ComponentInteractEventEnum,
if (typeof option.dataset === 'object') { defaultType: props.chartConfig.option.defaultType as string,
option.dataset[0] = dayjs().add(newData, 'day').valueOf() differValue: props.chartConfig.option.differValue as number[],
option.dataset[1] = dayjs().add(newData, 'day').valueOf() differUnit: props.chartConfig.option.differUnit as ManipulateType[],
} else { dataset: props.chartConfig.option.dataset as number | number[] | null,
option.dataset = dayjs().add(newData, 'day').valueOf() };
},
(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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -22,6 +22,37 @@ export enum ComponentInteractParamsEnum {
DATE_RANGE = 'daterange' 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 = [ const time = [
{ {
value: ComponentInteractParamsEnum.DATE, value: ComponentInteractParamsEnum.DATE,

View File

@ -1,8 +1,11 @@
<template> <template>
<collapse-item name="标签页配置" :expanded="true"> <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" /> <n-select size="small" v-model:value="optionData.tabType" :options="tabTypeOptions" />
</setting-item-box> </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> </collapse-item>
</template> </template>

View File

@ -1,5 +1,5 @@
<template> <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-tab v-for="(item, index) in option.value.dataset" :name="item.label" :key="index"> {{ item.label }} </n-tab>
</n-tabs> </n-tabs>
</template> </template>

View File

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

View File

@ -74,7 +74,7 @@ const themeColor = computed(() => {
// //
clearMittDataPondMap() clearMittDataPondMap()
onMounted(() => { onMounted(() => {
initDataPond(chartEditStore.requestGlobalConfig) initDataPond(useChartEditStore)
}) })
</script> </script>

View File

@ -12,7 +12,33 @@ export const useScale = (localStorageInfo: ChartEditStorageType) => {
const height = ref(localStorageInfo.editCanvasConfig.height) const height = ref(localStorageInfo.editCanvasConfig.height)
const scaleRef = ref({ width: 1, height: 1 }) 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 fitDom = document.querySelector(".go-preview.fit") as HTMLElement
if (fitDom) fitDom.style.overflow = 'auto'
const transform = previewRef.value.style.transform
// 使用正则解析 scale(1, 1) 中的两个数值
const regRes = transform.match(/scale\((\d+\.?\d*)*/) as RegExpMatchArray
const width = regRes[1]
if (e.wheelDelta > 0) {
previewRef.value.style.transform = `scale(${parseFloat(Number(width).toFixed(2)) + 0.1})`
} else {
previewRef.value.style.transform = `scale(${parseFloat(Number(width).toFixed(2)) - 0.1})`
}
}
},
{ passive: false }
)
}
const updateScaleRef = (scale: { width: number; height: number }) => { const updateScaleRef = (scale: { width: number; height: number }) => {
// 这里需要解构保证赋值给scaleRef的为一个新对象 // 这里需要解构保证赋值给scaleRef的为一个新对象
@ -23,74 +49,82 @@ export const useScale = (localStorageInfo: ChartEditStorageType) => {
// 屏幕适配 // 屏幕适配
onMounted(() => { onMounted(() => {
switch (localStorageInfo.editCanvasConfig.previewScaleType) { switch (localStorageInfo.editCanvasConfig.previewScaleType) {
case PreviewScaleEnum.FIT: (() => { case PreviewScaleEnum.FIT:
const { calcRate, windowResize, unWindowResize } = usePreviewFitScale( ;(() => {
width.value as number, const { calcRate, windowResize, unWindowResize } = usePreviewFitScale(
height.value as number, width.value as number,
previewRef.value, height.value as number,
updateScaleRef previewRef.value,
) updateScaleRef
calcRate() )
windowResize() calcRate()
onUnmounted(() => { windowResize()
unWindowResize() useAddWheelHandle(unWindowResize)
}) onUnmounted(() => {
})() unWindowResize()
break; })
case PreviewScaleEnum.SCROLL_Y: (() => { })()
const { calcRate, windowResize, unWindowResize } = usePreviewScrollYScale( break
width.value as number, case PreviewScaleEnum.SCROLL_Y:
height.value as number, ;(() => {
previewRef.value, const { calcRate, windowResize, unWindowResize } = usePreviewScrollYScale(
(scale) => { width.value as number,
const dom = entityRef.value height.value as number,
dom.style.width = `${width.value * scale.width}px` previewRef.value,
dom.style.height = `${height.value * scale.height}px` scale => {
updateScaleRef(scale) const dom = entityRef.value
} dom.style.width = `${width.value * scale.width}px`
) dom.style.height = `${height.value * scale.height}px`
calcRate() updateScaleRef(scale)
windowResize() }
onUnmounted(() => { )
unWindowResize() calcRate()
}) windowResize()
})() useAddWheelHandle(unWindowResize)
onUnmounted(() => {
unWindowResize()
})
})()
break; break
case PreviewScaleEnum.SCROLL_X: (() => { case PreviewScaleEnum.SCROLL_X:
const { calcRate, windowResize, unWindowResize } = usePreviewScrollXScale( ;(() => {
width.value as number, const { calcRate, windowResize, unWindowResize } = usePreviewScrollXScale(
height.value as number, width.value as number,
previewRef.value, height.value as number,
(scale) => { previewRef.value,
const dom = entityRef.value scale => {
dom.style.width = `${width.value * scale.width}px` const dom = entityRef.value
dom.style.height = `${height.value * scale.height}px` dom.style.width = `${width.value * scale.width}px`
updateScaleRef(scale) dom.style.height = `${height.value * scale.height}px`
} updateScaleRef(scale)
) }
calcRate() )
windowResize() calcRate()
onUnmounted(() => { windowResize()
unWindowResize() useAddWheelHandle(unWindowResize)
}) onUnmounted(() => {
})() unWindowResize()
})
})()
break; break
case PreviewScaleEnum.FULL: (() => { case PreviewScaleEnum.FULL:
const { calcRate, windowResize, unWindowResize } = usePreviewFullScale( ;(() => {
width.value as number, const { calcRate, windowResize, unWindowResize } = usePreviewFullScale(
height.value as number, width.value as number,
previewRef.value, height.value as number,
updateScaleRef previewRef.value,
) updateScaleRef
calcRate() )
windowResize() calcRate()
onUnmounted(() => { windowResize()
unWindowResize() useAddWheelHandle(unWindowResize)
}) onUnmounted(() => {
})() unWindowResize()
break; })
})()
break
} }
}) })

View File

@ -30,7 +30,7 @@
import { computed } from 'vue' import { computed } from 'vue'
import { PreviewRenderList } from './components/PreviewRenderList' import { PreviewRenderList } from './components/PreviewRenderList'
import { getFilterStyle, setTitle } from '@/utils' import { getFilterStyle, setTitle } from '@/utils'
import { getEditCanvasConfigStyle, getSessionStorageInfo } from './utils' import { getEditCanvasConfigStyle, getSessionStorageInfo, keyRecordHandle } from './utils'
import { useComInstall } from './hooks/useComInstall.hook' import { useComInstall } from './hooks/useComInstall.hook'
import { useScale } from './hooks/useScale.hook' import { useScale } from './hooks/useScale.hook'
import { useStore } from './hooks/useStore.hook' import { useStore } from './hooks/useStore.hook'
@ -60,6 +60,9 @@ const showEntity = computed(() => {
useStore(chartEditStore) useStore(chartEditStore)
const { entityRef, previewRef } = useScale(chartEditStore) const { entityRef, previewRef } = useScale(chartEditStore)
const { show } = useComInstall(chartEditStore) const { show } = useComInstall(chartEditStore)
//
keyRecordHandle()
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

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

View File

@ -0,0 +1,32 @@
// 处理键盘记录
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; 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
}
}
}
}

View File

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