Showing
72 changed files
with
1934 additions
and
211 deletions
... | ... | @@ -172,7 +172,9 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req |
172 | 172 | |
173 | 173 | case RequestBodyEnum.JSON: |
174 | 174 | headers['Content-Type'] = ContentTypeEnum.JSON |
175 | - data = translateStr(JSON.parse(targetRequestParams.Body['json'])) | |
175 | + //json对象也能使用'javasctipt:'来动态拼接参数 | |
176 | + data = translateStr(targetRequestParams.Body['json']) | |
177 | + if(typeof data === 'string') data = JSON.parse(data) | |
176 | 178 | // json 赋值给 data |
177 | 179 | break |
178 | 180 | ... | ... |
15.3 KB
... | ... | @@ -25,6 +25,7 @@ import { icon } from '@/plugins' |
25 | 25 | import { useUserStore } from '@/store/external/module/user' |
26 | 26 | const { ChatboxEllipsesIcon, PersonIcon, LogOutOutlineIcon, SettingsSharpIcon } = icon.ionicons5 |
27 | 27 | |
28 | + | |
28 | 29 | const t = window['$t'] |
29 | 30 | |
30 | 31 | const modelShowInfo = ref(false) |
... | ... | @@ -46,7 +47,11 @@ const renderUserInfo = () => { |
46 | 47 | style: 'margin-right: 12px;', |
47 | 48 | src: Person |
48 | 49 | }), |
50 | + h('div', null, [ | |
51 | + h('div', null, [ | |
49 | 52 | h('div', null, [h('div', null, [h(NText, { depth: 2 }, { default: () => '奔跑的面条' })])]) |
53 | + ]) | |
54 | + ]) | |
50 | 55 | ] |
51 | 56 | ) |
52 | 57 | } | ... | ... |
1 | 1 | <template> |
2 | 2 | <n-layout-header bordered class="go-header"> |
3 | - <header class="go-header-box"> | |
3 | + <header class="go-header-box" :class="{ 'is-project': isProject }"> | |
4 | 4 | <div class="header-item left"> |
5 | 5 | <n-space> |
6 | 6 | <slot name="left"></slot> |
... | ... | @@ -23,17 +23,29 @@ |
23 | 23 | </template> |
24 | 24 | |
25 | 25 | <script setup lang="ts"> |
26 | +import { computed } from 'vue' | |
27 | +import { useRoute } from 'vue-router' | |
26 | 28 | import { GoThemeSelect } from '@/components/GoThemeSelect' |
27 | 29 | import { GoLangSelect } from '@/components/GoLangSelect' |
28 | 30 | import { ThemeColorSelect } from '@/components/Pages/ThemeColorSelect' |
31 | +import { PageEnum } from '@/enums/pageEnum' | |
32 | + | |
33 | +const route = useRoute() | |
34 | + | |
35 | +const isProject = computed(() => { | |
36 | + return route.fullPath === PageEnum.BASE_HOME_ITEMS | |
37 | +}) | |
29 | 38 | </script> |
30 | 39 | |
31 | 40 | <style lang="scss" scoped> |
32 | -$min-width: 400px; | |
41 | +$min-width: 520px; | |
33 | 42 | @include go(header) { |
34 | 43 | &-box { |
35 | 44 | display: grid; |
36 | - grid-template-columns: repeat(3, 33.33%); | |
45 | + grid-template-columns: repeat(3, 33%); | |
46 | + &.is-project { | |
47 | + grid-template-columns: none; | |
48 | + } | |
37 | 49 | .header-item { |
38 | 50 | display: flex; |
39 | 51 | align-items: center; |
... | ... | @@ -49,7 +61,7 @@ $min-width: 400px; |
49 | 61 | } |
50 | 62 | } |
51 | 63 | height: $--header-height; |
52 | - padding: 0 60px; | |
64 | + padding: 0 20px 0 60px; | |
53 | 65 | } |
54 | 66 | } |
55 | 67 | </style> | ... | ... |
1 | 1 | import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public' |
2 | 2 | import { LineCommonConfig } from './index' |
3 | 3 | import { CreateComponentType } from '@/packages/index.d' |
4 | -import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index' | |
5 | 4 | import cloneDeep from 'lodash/cloneDeep' |
6 | 5 | import dataJson from './data.json' |
7 | 6 | ... | ... |
... | ... | @@ -15,7 +15,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore |
15 | 15 | import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index' |
16 | 16 | import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components' |
17 | 17 | import { useChartDataFetch } from '@/hooks' |
18 | -import { isPreview } from '@/utils' | |
18 | +import { isPreview, colorGradientCustomMerge} from '@/utils' | |
19 | 19 | |
20 | 20 | const props = defineProps({ |
21 | 21 | themeSetting: { |
... | ... | @@ -45,7 +45,9 @@ watch( |
45 | 45 | (newColor: keyof typeof chartColorsSearch) => { |
46 | 46 | try { |
47 | 47 | if (!isPreview()) { |
48 | - const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme] | |
48 | + const themeColor = | |
49 | + colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[newColor] || | |
50 | + colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[defaultTheme] | |
49 | 51 | props.chartConfig.option.series.forEach((value: any, index: number) => { |
50 | 52 | value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [ |
51 | 53 | { | ... | ... |
... | ... | @@ -14,7 +14,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore |
14 | 14 | import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index' |
15 | 15 | import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components' |
16 | 16 | import { useChartDataFetch } from '@/hooks' |
17 | -import { isPreview } from '@/utils' | |
17 | +import { isPreview, colorGradientCustomMerge} from '@/utils' | |
18 | 18 | |
19 | 19 | const props = defineProps({ |
20 | 20 | themeSetting: { |
... | ... | @@ -43,8 +43,9 @@ watch( |
43 | 43 | () => chartEditStore.getEditCanvasConfig.chartThemeColor, |
44 | 44 | (newColor: keyof typeof chartColorsSearch) => { |
45 | 45 | try { |
46 | - if (!isPreview()) { | |
46 | + if (!isPreview()) { | |
47 | 47 | const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme] |
48 | + colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[defaultTheme] | |
48 | 49 | props.chartConfig.option.series.forEach((value: any, index: number) => { |
49 | 50 | value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [ |
50 | 51 | { | ... | ... |
... | ... | @@ -15,7 +15,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore |
15 | 15 | import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index' |
16 | 16 | import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components' |
17 | 17 | import { useChartDataFetch } from '@/hooks' |
18 | -import { isPreview } from '@/utils' | |
18 | +import { isPreview, colorGradientCustomMerge } from '@/utils' | |
19 | 19 | |
20 | 20 | const props = defineProps({ |
21 | 21 | themeSetting: { |
... | ... | @@ -45,7 +45,9 @@ watch( |
45 | 45 | (newColor: keyof typeof chartColorsSearch) => { |
46 | 46 | try { |
47 | 47 | if (!isPreview()) { |
48 | - const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme] | |
48 | + const themeColor = | |
49 | + colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[newColor] || | |
50 | + colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[defaultTheme] | |
49 | 51 | props.chartConfig.option.series.forEach((value: any) => { |
50 | 52 | value.lineStyle.shadowColor = themeColor[2] |
51 | 53 | value.lineStyle.color.colorStops.forEach((v: { color: string }, i: number) => { | ... | ... |
... | ... | @@ -59,13 +59,14 @@ const getGeojson = (regionId: string) => { |
59 | 59 | } |
60 | 60 | |
61 | 61 | //异步时先注册空的 保证初始化不报错 |
62 | -registerMap(props.chartConfig.option.mapRegion.adcode, { geoJSON: {} as any, specialAreas: {} }) | |
62 | +registerMap(`${props.chartConfig.option.mapRegion.adcode}`, { geoJSON: {} as any, specialAreas: {} }) | |
63 | 63 | |
64 | 64 | // 进行更换初始化地图 如果为china 单独处理 |
65 | 65 | const registerMapInitAsync = async () => { |
66 | 66 | await nextTick() |
67 | - if (props.chartConfig.option.mapRegion.adcode != 'china') { | |
68 | - await getGeojson(props.chartConfig.option.mapRegion.adcode) | |
67 | + const adCode = `${props.chartConfig.option.mapRegion.adcode}`; | |
68 | + if (adCode !== 'china') { | |
69 | + await getGeojson(adCode) | |
69 | 70 | } else { |
70 | 71 | await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands) |
71 | 72 | } |
... | ... | @@ -127,7 +128,7 @@ watch( |
127 | 128 | |
128 | 129 | //监听地图展示区域发生变化 |
129 | 130 | watch( |
130 | - () => props.chartConfig.option.mapRegion.adcode, | |
131 | + () => `${props.chartConfig.option.mapRegion.adcode}`, | |
131 | 132 | async newData => { |
132 | 133 | try { |
133 | 134 | await getGeojson(newData) | ... | ... |
... | ... | @@ -10,7 +10,7 @@ import 'echarts-liquidfill/src/liquidFill.js' |
10 | 10 | import { CanvasRenderer } from 'echarts/renderers' |
11 | 11 | import { GridComponent } from 'echarts/components' |
12 | 12 | import config from './config' |
13 | -import { isPreview, isString, isNumber } from '@/utils' | |
13 | +import { isPreview, isString, isNumber, colorGradientCustomMerge } from '@/utils' | |
14 | 14 | import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index' |
15 | 15 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
16 | 16 | import { useChartDataFetch } from '@/hooks' |
... | ... | @@ -44,7 +44,9 @@ watch( |
44 | 44 | (newColor: keyof typeof chartColorsSearch) => { |
45 | 45 | try { |
46 | 46 | if (!isPreview()) { |
47 | - const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme] | |
47 | + const themeColor = | |
48 | + colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[newColor] || | |
49 | + colorGradientCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo)[defaultTheme] | |
48 | 50 | // 背景颜色 |
49 | 51 | props.chartConfig.option.series[0].backgroundStyle.color = themeColor[2] |
50 | 52 | // 水球颜色 | ... | ... |
1 | +import { PublicConfigClass } from '@/packages/public' | |
2 | +import { CreateComponentType } from '@/packages/index.d' | |
3 | +import { CarouselConfig } from './index' | |
4 | +import cloneDeep from 'lodash/cloneDeep' | |
5 | +import logo from '@/assets/logo.png' | |
6 | + | |
7 | +// 示例图片资源 | |
8 | +const modules = import.meta.globEager("./images/*"); | |
9 | +const dataset = [logo] | |
10 | +for (var item in modules) { | |
11 | + dataset.push(modules[item].default) | |
12 | +} | |
13 | + | |
14 | +export const option = { | |
15 | + // 图片资源列表 | |
16 | + dataset: dataset, | |
17 | + // 自动播放 | |
18 | + autoplay: true, | |
19 | + // 自动播放的间隔(ms) | |
20 | + interval: 5000, | |
21 | + // 每页显示的图片数量 | |
22 | + slidesPerview: 1, | |
23 | + // 轮播方向 | |
24 | + direction: "horizontal", | |
25 | + // 拖曳切换 | |
26 | + draggable: true, | |
27 | + // 居中显示 | |
28 | + centeredSlides: false, | |
29 | + // 过渡效果 | |
30 | + effect: "slide", | |
31 | + // 是否显示指示点 | |
32 | + showDots: true, | |
33 | + // 指示器样式 | |
34 | + dotType: "dot", | |
35 | + // 指示器位置 | |
36 | + dotPlacement: "bottom", | |
37 | + // 显示箭头 | |
38 | + showArrow: false, | |
39 | + // 图片样式 | |
40 | + fit: "contain", | |
41 | +} | |
42 | + | |
43 | +export default class Config extends PublicConfigClass implements CreateComponentType { | |
44 | + public key = CarouselConfig.key | |
45 | + public chartConfig = cloneDeep(CarouselConfig) | |
46 | + public option = cloneDeep(option) | |
47 | +} | ... | ... |
1 | +<template> | |
2 | + <collapse-item name="属性" :expanded="true"> | |
3 | + <setting-item-box name="路径" :alone="true"> | |
4 | + <setting-item v-for="item, index in optionData.dataset" :key="index"> | |
5 | + <n-input-group> | |
6 | + <n-input v-model:value="optionData.dataset[index]" size="small" placeholder="请输入图片地址"></n-input> | |
7 | + <n-button ghost @click="optionData.dataset.splice(index, 1)"> | |
8 | + - | |
9 | + </n-button> | |
10 | + </n-input-group> | |
11 | + </setting-item> | |
12 | + <setting-item> | |
13 | + <n-button size="small" @click="optionData.dataset.push('')"> | |
14 | + + | |
15 | + </n-button> | |
16 | + </setting-item> | |
17 | + </setting-item-box> | |
18 | + <setting-item-box name="播放器"> | |
19 | + <setting-item> | |
20 | + <n-space> | |
21 | + <n-switch v-model:value="optionData.autoplay" size="small" /> | |
22 | + <n-text>自动播放</n-text> | |
23 | + </n-space> | |
24 | + </setting-item> | |
25 | + <!-- 开启自动播放时,设置间隔时间 --> | |
26 | + <setting-item name="间隔时间"> | |
27 | + <n-input-number v-model:value="optionData.interval" size="small" placeholder=""></n-input-number> | |
28 | + </setting-item> | |
29 | + <setting-item name="轮播方向"> | |
30 | + <n-select v-model:value="optionData.direction" :options="directions" placeholder="选择方向" /> | |
31 | + </setting-item> | |
32 | + <setting-item name="过渡效果"> | |
33 | + <n-select v-model:value="optionData.effect" :options="effects" placeholder="效果" /> | |
34 | + </setting-item> | |
35 | + <setting-item name="每页数量"> | |
36 | + <n-input-number v-model:value="optionData.slidesPerview" size="small" placeholder=""></n-input-number> | |
37 | + </setting-item> | |
38 | + <setting-item> | |
39 | + <n-space> | |
40 | + <n-switch v-model:value="optionData.centeredSlides" size="small" /> | |
41 | + <n-text>居中显示</n-text> | |
42 | + </n-space> | |
43 | + </setting-item> | |
44 | + <setting-item name="图片样式"> | |
45 | + <n-select v-model:value="optionData.fit" :options="fitList" placeholder="样式" /> | |
46 | + </setting-item> | |
47 | + </setting-item-box> | |
48 | + | |
49 | + <setting-item-box name="指示器"> | |
50 | + <setting-item name="样式"> | |
51 | + <n-select v-model:value="optionData.dotType" :options="dotTypes" placeholder="选择样式" /> | |
52 | + </setting-item> | |
53 | + <setting-item name="位置"> | |
54 | + <n-select v-model:value="optionData.dotPlacement" :options="dotPlacements" placeholder="选择位置" /> | |
55 | + </setting-item> | |
56 | + <setting-item> | |
57 | + <n-space> | |
58 | + <n-switch v-model:value="optionData.showDots" size="small" /> | |
59 | + <n-text>显示</n-text> | |
60 | + </n-space> | |
61 | + </setting-item> | |
62 | + <setting-item> | |
63 | + <n-space> | |
64 | + <n-switch v-model:value="optionData.showArrow" size="small" /> | |
65 | + <n-text>箭头</n-text> | |
66 | + </n-space> | |
67 | + </setting-item> | |
68 | + <setting-item> | |
69 | + <n-space> | |
70 | + <n-switch v-model:value="optionData.draggable" size="small" /> | |
71 | + <n-text>拖曳切换</n-text> | |
72 | + </n-space> | |
73 | + </setting-item> | |
74 | + </setting-item-box> | |
75 | + | |
76 | + </collapse-item> | |
77 | +</template> | |
78 | + | |
79 | +<script setup lang="ts"> | |
80 | +import { PropType } from 'vue' | |
81 | +import { option } from './config' | |
82 | +import { | |
83 | + CollapseItem, | |
84 | + SettingItemBox, | |
85 | + SettingItem | |
86 | +} from '@/components/Pages/ChartItemSetting' | |
87 | + | |
88 | +const props = defineProps({ | |
89 | + optionData: { | |
90 | + type: Object as PropType<typeof option>, | |
91 | + required: true | |
92 | + } | |
93 | +}) | |
94 | + | |
95 | +// 字典 | |
96 | +const dotTypes = [ | |
97 | + { | |
98 | + label: "点", | |
99 | + value: "dot" | |
100 | + }, | |
101 | + { | |
102 | + label: "线", | |
103 | + value: "line" | |
104 | + } | |
105 | +] | |
106 | +const directions = [ | |
107 | + { | |
108 | + label: "水平方向", | |
109 | + value: "horizontal" | |
110 | + }, | |
111 | + { | |
112 | + label: "垂直方向", | |
113 | + value: "vertical" | |
114 | + } | |
115 | +] | |
116 | +const effects = [ | |
117 | + { | |
118 | + label: "slide", | |
119 | + value: "slide" | |
120 | + }, | |
121 | + { | |
122 | + label: "fade", | |
123 | + value: "fade" | |
124 | + }, | |
125 | + { | |
126 | + label: "card", | |
127 | + value: "card" | |
128 | + }, | |
129 | + { | |
130 | + label: "custom", | |
131 | + value: "custom" | |
132 | + } | |
133 | +] | |
134 | +const dotPlacements = [ | |
135 | + { | |
136 | + label: "上边", | |
137 | + value: "top" | |
138 | + }, | |
139 | + { | |
140 | + label: "下边", | |
141 | + value: "bottom" | |
142 | + }, | |
143 | + { | |
144 | + label: "左边", | |
145 | + value: "left" | |
146 | + }, | |
147 | + { | |
148 | + label: "右边", | |
149 | + value: "right" | |
150 | + } | |
151 | +] | |
152 | + | |
153 | +// 适应类型 | |
154 | +const fitList = [ | |
155 | + { | |
156 | + value: 'fill', | |
157 | + label: 'fill' | |
158 | + }, | |
159 | + { | |
160 | + value: 'contain', | |
161 | + label: 'contain' | |
162 | + }, | |
163 | + { | |
164 | + value: 'cover', | |
165 | + label: 'cover' | |
166 | + }, | |
167 | + { | |
168 | + value: 'scale-down', | |
169 | + label: 'scale-down' | |
170 | + }, | |
171 | + { | |
172 | + value: 'none', | |
173 | + label: 'none' | |
174 | + }, | |
175 | +] | |
176 | +</script> | ... | ... |
12.1 KB
1 | +import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d' | |
2 | +import { ChatCategoryEnum,ChatCategoryEnumName } from '../../index.d' | |
3 | + | |
4 | +export const CarouselConfig: ConfigType = { | |
5 | + key: 'Carousel', | |
6 | + chartKey: 'VCarousel', | |
7 | + conKey: 'VCCarousel', | |
8 | + title: '轮播图', | |
9 | + category: ChatCategoryEnum.MORE, | |
10 | + categoryName: ChatCategoryEnumName.MORE, | |
11 | + package: PackagesCategoryEnum.INFORMATIONS, | |
12 | + chartFrame: ChartFrameEnum.NAIVE_UI, | |
13 | + image: 'photo.png' | |
14 | +} | ... | ... |
1 | +<template> | |
2 | + <div> | |
3 | + <n-carousel :autoplay="autoplay" :interval="interval" :centered-slides="centeredSlides" :direction="direction" | |
4 | + :dot-placement="dotPlacement" :dot-type="dotType" :draggable="draggable" :effect="effect" | |
5 | + :slides-per-view="slidesPerview" :show-arrow="showArrow" :show-dots="showDots"> | |
6 | + <n-image v-for="url in option.dataset" :object-fit="fit" preview-disabled :src="url" | |
7 | + :fallback-src="requireErrorImg()" :width="w" :height="h"></n-image> | |
8 | + </n-carousel> | |
9 | + </div> | |
10 | +</template> | |
11 | +<script setup lang="ts"> | |
12 | +import { PropType, toRefs, shallowReactive, watch } from 'vue' | |
13 | +import { CreateComponentType } from '@/packages/index.d' | |
14 | +import { requireErrorImg } from '@/utils' | |
15 | +import { useChartDataFetch } from '@/hooks' | |
16 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
17 | +import { option as configOption } from './config' | |
18 | + | |
19 | +const props = defineProps({ | |
20 | + chartConfig: { | |
21 | + type: Object as PropType<CreateComponentType>, | |
22 | + required: true | |
23 | + } | |
24 | +}) | |
25 | + | |
26 | +const option = shallowReactive({ | |
27 | + dataset: configOption.dataset | |
28 | +}) | |
29 | + | |
30 | +const { w, h } = toRefs(props.chartConfig.attr) | |
31 | +const { autoplay, interval, slidesPerview, direction, draggable, centeredSlides, effect, dotType, dotPlacement, showArrow, showDots, fit } = toRefs(props.chartConfig.option) | |
32 | + | |
33 | +watch( | |
34 | + () => props.chartConfig.option.dataset, | |
35 | + (newData: any) => { | |
36 | + option.dataset = newData | |
37 | + }, | |
38 | + { | |
39 | + immediate: true, | |
40 | + deep: false | |
41 | + } | |
42 | +) | |
43 | + | |
44 | +useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => { | |
45 | + option.dataset = newData | |
46 | +}) | |
47 | +</script> | ... | ... |
1 | +import { PublicConfigClass } from '@/packages/public' | |
2 | +import { CreateComponentType } from '@/packages/index.d' | |
3 | +import { ImageCarouselConfig } from './index' | |
4 | +import cloneDeep from 'lodash/cloneDeep' | |
5 | +import logo from '@/assets/logo.png' | |
6 | + | |
7 | +export const option = { | |
8 | + // 图片资源列表 | |
9 | + dataset: [ | |
10 | + 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg', | |
11 | + 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg', | |
12 | + 'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg', | |
13 | + ], | |
14 | + // 自动播放 | |
15 | + autoplay: true, | |
16 | + // 自动播放的间隔(豪秒) | |
17 | + interval: 5000, | |
18 | + // 每页显示的图片数量 | |
19 | + slidesPerview: 1, | |
20 | + // 轮播方向 | |
21 | + direction: "horizontal", | |
22 | + // 拖曳切换 | |
23 | + draggable: true, | |
24 | + // 居中显示 | |
25 | + centeredSlides: false, | |
26 | + // 过渡效果 | |
27 | + effect: "slide", | |
28 | + // 是否显示指示点 | |
29 | + showDots: true, | |
30 | + // 指示器样式 | |
31 | + dotType: "dot", | |
32 | + // 指示器位置 | |
33 | + dotPlacement: "bottom", | |
34 | + // 显示箭头 | |
35 | + showArrow: false, | |
36 | + // 图片样式 | |
37 | + fit: "contain", | |
38 | +} | |
39 | + | |
40 | +export default class Config extends PublicConfigClass implements CreateComponentType { | |
41 | + public key = ImageCarouselConfig.key | |
42 | + public chartConfig = cloneDeep(ImageCarouselConfig) | |
43 | + public option = cloneDeep(option) | |
44 | +} | ... | ... |
1 | +<template> | |
2 | + <collapse-item name="路径" :expanded="true"> | |
3 | + <setting-item v-for="(item, index) in optionData.dataset" :key="index"> | |
4 | + <n-input-group> | |
5 | + <n-input v-model:value="optionData.dataset[index]" size="small" placeholder="请输入图片地址"></n-input> | |
6 | + <n-button ghost @click="optionData.dataset.splice(index, 1)"> - </n-button> | |
7 | + </n-input-group> | |
8 | + </setting-item> | |
9 | + <setting-item> | |
10 | + <n-button size="small" @click="optionData.dataset.push('')"> + 新增</n-button> | |
11 | + </setting-item> | |
12 | + </collapse-item> | |
13 | + <collapse-item name="轮播属性" :expanded="true"> | |
14 | + <setting-item-box name="播放器"> | |
15 | + <setting-item> | |
16 | + <n-space> | |
17 | + <n-switch v-model:value="optionData.autoplay" size="small" /> | |
18 | + <n-text>自动播放</n-text> | |
19 | + </n-space> | |
20 | + </setting-item> | |
21 | + <!-- 开启自动播放时,设置间隔时间 --> | |
22 | + <setting-item name="间隔时间"> | |
23 | + <n-input-number v-model:value="optionData.interval" size="small" placeholder=""> | |
24 | + <template #suffix> 毫秒 </template> | |
25 | + </n-input-number> | |
26 | + </setting-item> | |
27 | + <setting-item name="轮播方向"> | |
28 | + <n-select v-model:value="optionData.direction" :options="directions" placeholder="选择方向" /> | |
29 | + </setting-item> | |
30 | + <setting-item name="过渡效果"> | |
31 | + <n-select v-model:value="optionData.effect" :options="effects" placeholder="效果" /> | |
32 | + </setting-item> | |
33 | + <setting-item name="每页数量"> | |
34 | + <n-input-number v-model:value="optionData.slidesPerview" size="small" placeholder=""></n-input-number> | |
35 | + </setting-item> | |
36 | + <setting-item> | |
37 | + <n-space> | |
38 | + <n-switch v-model:value="optionData.centeredSlides" size="small" /> | |
39 | + <n-text>居中显示</n-text> | |
40 | + </n-space> | |
41 | + </setting-item> | |
42 | + <setting-item name="图片样式"> | |
43 | + <n-select v-model:value="optionData.fit" :options="fitList" placeholder="样式" /> | |
44 | + </setting-item> | |
45 | + </setting-item-box> | |
46 | + <setting-item-box name="指示器"> | |
47 | + <setting-item name="样式"> | |
48 | + <n-select v-model:value="optionData.dotType" :options="dotTypes" placeholder="选择样式" /> | |
49 | + </setting-item> | |
50 | + <setting-item name="位置"> | |
51 | + <n-select v-model:value="optionData.dotPlacement" :options="dotPlacements" placeholder="选择位置" /> | |
52 | + </setting-item> | |
53 | + <setting-item> | |
54 | + <n-space> | |
55 | + <n-switch v-model:value="optionData.showDots" size="small" /> | |
56 | + <n-text>显示</n-text> | |
57 | + </n-space> | |
58 | + </setting-item> | |
59 | + <setting-item> | |
60 | + <n-space> | |
61 | + <n-switch v-model:value="optionData.showArrow" size="small" /> | |
62 | + <n-text>箭头</n-text> | |
63 | + </n-space> | |
64 | + </setting-item> | |
65 | + <setting-item> | |
66 | + <n-space> | |
67 | + <n-switch v-model:value="optionData.draggable" size="small" /> | |
68 | + <n-text>拖曳切换</n-text> | |
69 | + </n-space> | |
70 | + </setting-item> | |
71 | + </setting-item-box> | |
72 | + </collapse-item> | |
73 | +</template> | |
74 | + | |
75 | +<script setup lang="ts"> | |
76 | +import { PropType } from 'vue' | |
77 | +import { option } from './config' | |
78 | +import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' | |
79 | + | |
80 | +const props = defineProps({ | |
81 | + optionData: { | |
82 | + type: Object as PropType<typeof option>, | |
83 | + required: true | |
84 | + } | |
85 | +}) | |
86 | + | |
87 | +// 字典 | |
88 | +const dotTypes = [ | |
89 | + { | |
90 | + label: '点', | |
91 | + value: 'dot' | |
92 | + }, | |
93 | + { | |
94 | + label: '线', | |
95 | + value: 'line' | |
96 | + } | |
97 | +] | |
98 | +const directions = [ | |
99 | + { | |
100 | + label: '水平方向', | |
101 | + value: 'horizontal' | |
102 | + }, | |
103 | + { | |
104 | + label: '垂直方向', | |
105 | + value: 'vertical' | |
106 | + } | |
107 | +] | |
108 | +const effects = [ | |
109 | + { | |
110 | + label: 'slide', | |
111 | + value: 'slide' | |
112 | + }, | |
113 | + { | |
114 | + label: 'fade', | |
115 | + value: 'fade' | |
116 | + }, | |
117 | + { | |
118 | + label: 'card', | |
119 | + value: 'card' | |
120 | + }, | |
121 | + { | |
122 | + label: 'custom', | |
123 | + value: 'custom' | |
124 | + } | |
125 | +] | |
126 | +const dotPlacements = [ | |
127 | + { | |
128 | + label: '上边', | |
129 | + value: 'top' | |
130 | + }, | |
131 | + { | |
132 | + label: '下边', | |
133 | + value: 'bottom' | |
134 | + }, | |
135 | + { | |
136 | + label: '左边', | |
137 | + value: 'left' | |
138 | + }, | |
139 | + { | |
140 | + label: '右边', | |
141 | + value: 'right' | |
142 | + } | |
143 | +] | |
144 | + | |
145 | +// 适应类型 | |
146 | +const fitList = [ | |
147 | + { | |
148 | + value: 'fill', | |
149 | + label: 'fill' | |
150 | + }, | |
151 | + { | |
152 | + value: 'contain', | |
153 | + label: 'contain' | |
154 | + }, | |
155 | + { | |
156 | + value: 'cover', | |
157 | + label: 'cover' | |
158 | + }, | |
159 | + { | |
160 | + value: 'scale-down', | |
161 | + label: 'scale-down' | |
162 | + }, | |
163 | + { | |
164 | + value: 'none', | |
165 | + label: 'none' | |
166 | + } | |
167 | +] | |
168 | +</script> | ... | ... |
1 | +import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d' | |
2 | +import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d' | |
3 | + | |
4 | +export const ImageCarouselConfig: ConfigType = { | |
5 | + key: 'ImageCarousel', | |
6 | + chartKey: 'VImageCarousel', | |
7 | + conKey: 'VCImageCarousel', | |
8 | + title: '轮播图', | |
9 | + category: ChatCategoryEnum.MORE, | |
10 | + categoryName: ChatCategoryEnumName.MORE, | |
11 | + package: PackagesCategoryEnum.INFORMATIONS, | |
12 | + chartFrame: ChartFrameEnum.NAIVE_UI, | |
13 | + image: 'photo_carousel.png' | |
14 | +} | ... | ... |
1 | +<template> | |
2 | + <div> | |
3 | + <n-carousel | |
4 | + :autoplay="autoplay" | |
5 | + :interval="interval" | |
6 | + :centered-slides="centeredSlides" | |
7 | + :direction="direction" | |
8 | + :dot-placement="dotPlacement" | |
9 | + :dot-type="dotType" | |
10 | + :draggable="draggable" | |
11 | + :effect="effect" | |
12 | + :slides-per-view="slidesPerview" | |
13 | + :show-arrow="showArrow" | |
14 | + :show-dots="showDots" | |
15 | + > | |
16 | + <n-image | |
17 | + v-for="(url, index) in option.dataset" | |
18 | + preview-disabled | |
19 | + :key="index" | |
20 | + :object-fit="fit" | |
21 | + :src="url" | |
22 | + :fallback-src="requireErrorImg()" | |
23 | + :width="w" | |
24 | + :height="h" | |
25 | + ></n-image> | |
26 | + </n-carousel> | |
27 | + </div> | |
28 | +</template> | |
29 | +<script setup lang="ts"> | |
30 | +import { PropType, toRefs, shallowReactive, watch } from 'vue' | |
31 | +import { CreateComponentType } from '@/packages/index.d' | |
32 | +import { requireErrorImg } from '@/utils' | |
33 | +import { useChartDataFetch } from '@/hooks' | |
34 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
35 | +import { option as configOption } from './config' | |
36 | + | |
37 | +const props = defineProps({ | |
38 | + chartConfig: { | |
39 | + type: Object as PropType<CreateComponentType>, | |
40 | + required: true | |
41 | + } | |
42 | +}) | |
43 | + | |
44 | +const option = shallowReactive({ | |
45 | + dataset: configOption.dataset | |
46 | +}) | |
47 | + | |
48 | +const { w, h } = toRefs(props.chartConfig.attr) | |
49 | +const { | |
50 | + autoplay, | |
51 | + interval, | |
52 | + slidesPerview, | |
53 | + direction, | |
54 | + draggable, | |
55 | + centeredSlides, | |
56 | + effect, | |
57 | + dotType, | |
58 | + dotPlacement, | |
59 | + showArrow, | |
60 | + showDots, | |
61 | + fit | |
62 | +} = toRefs(props.chartConfig.option) | |
63 | + | |
64 | +watch( | |
65 | + () => props.chartConfig.option.dataset, | |
66 | + (newData: any) => { | |
67 | + option.dataset = newData | |
68 | + }, | |
69 | + { | |
70 | + immediate: true, | |
71 | + deep: false | |
72 | + } | |
73 | +) | |
74 | + | |
75 | +useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => { | |
76 | + option.dataset = newData | |
77 | +}) | |
78 | +</script> | ... | ... |
1 | 1 | import { ImageConfig } from './Image/index' |
2 | +import { ImageCarouselConfig } from './ImageCarousel/index' | |
2 | 3 | import { IframeConfig } from './Iframe/index' |
3 | 4 | import { VideoConfig } from './Video/index' |
4 | 5 | import { WordCloudConfig } from './WordCloud/index' |
6 | +import { CarouselConfig } from './Carousel/index' | |
5 | 7 | |
6 | -export default [WordCloudConfig, ImageConfig, VideoConfig, IframeConfig] | |
8 | +export default [ImageConfig, ImageCarouselConfig, VideoConfig, IframeConfig, WordCloudConfig] | ... | ... |
... | ... | @@ -149,7 +149,7 @@ export enum PackagesCategoryEnum { |
149 | 149 | CHARTS = 'Charts', |
150 | 150 | TABLES = 'Tables', |
151 | 151 | INFORMATIONS = 'Informations', |
152 | - DECORATES = 'Decorates', | |
152 | + DECORATES = 'Decorates' | |
153 | 153 | } |
154 | 154 | |
155 | 155 | // 包分类名称 |
... | ... | @@ -157,7 +157,7 @@ export enum PackagesCategoryName { |
157 | 157 | CHARTS = '图表', |
158 | 158 | TABLES = '列表', |
159 | 159 | INFORMATIONS = '信息', |
160 | - DECORATES = '小组件', | |
160 | + DECORATES = '小组件' | |
161 | 161 | } |
162 | 162 | |
163 | 163 | // 获取组件 | ... | ... |
1 | 1 | import { |
2 | + Add as AddIcon, | |
2 | 3 | Close as CloseIcon, |
3 | 4 | Remove as RemoveIcon, |
4 | 5 | Resize as ResizeIcon, |
... | ... | @@ -52,6 +53,7 @@ import { |
52 | 53 | ColorWand as ColorWandIcon, |
53 | 54 | ArrowBack as ArrowBackIcon, |
54 | 55 | ArrowForward as ArrowForwardIcon, |
56 | + ArrowDown as ArrowDownIcon, | |
55 | 57 | Planet as PawIcon, |
56 | 58 | Search as SearchIcon, |
57 | 59 | ChevronUpOutline as ChevronUpOutlineIcon, |
... | ... | @@ -64,7 +66,9 @@ import { |
64 | 66 | List as ListIcon, |
65 | 67 | EyeOutline as EyeOutlineIcon, |
66 | 68 | EyeOffOutline as EyeOffOutlineIcon, |
67 | - Albums as AlbumsIcon | |
69 | + Albums as AlbumsIcon, | |
70 | + Analytics as AnalyticsIcon, | |
71 | + SaveOutline as SaveIcon | |
68 | 72 | } from '@vicons/ionicons5' |
69 | 73 | |
70 | 74 | import { |
... | ... | @@ -97,12 +101,12 @@ import { |
97 | 101 | Carbon3DSoftware as Carbon3DSoftwareIcon, |
98 | 102 | Filter as FilterIcon, |
99 | 103 | FilterEdit as FilterEditIcon, |
100 | - Laptop as LaptopIcon, | |
101 | - // THINGS_KIT | |
102 | - Save as SaveIcon | |
104 | + Laptop as LaptopIcon | |
103 | 105 | } from '@vicons/carbon' |
104 | 106 | |
105 | 107 | const ionicons5 = { |
108 | + // 新增 | |
109 | + AddIcon, | |
106 | 110 | // 帮助(问号) |
107 | 111 | HelpOutlineIcon, |
108 | 112 | // 添加 |
... | ... | @@ -208,6 +212,8 @@ const ionicons5 = { |
208 | 212 | ArrowBackIcon, |
209 | 213 | // 前进 |
210 | 214 | ArrowForwardIcon, |
215 | + // 向下 | |
216 | + ArrowDownIcon, | |
211 | 217 | // 狗爪 |
212 | 218 | PawIcon, |
213 | 219 | // 搜索(放大镜) |
... | ... | @@ -233,8 +239,10 @@ const ionicons5 = { |
233 | 239 | // 眼睛 |
234 | 240 | EyeOutlineIcon, |
235 | 241 | EyeOffOutlineIcon, |
236 | - // 图表列表 | |
237 | - AlbumsIcon | |
242 | + // 图表列表 | |
243 | + AlbumsIcon, | |
244 | + // 分析 | |
245 | + AnalyticsIcon | |
238 | 246 | } |
239 | 247 | |
240 | 248 | const carbon = { | ... | ... |
... | ... | @@ -57,6 +57,7 @@ import { |
57 | 57 | NProgress, |
58 | 58 | NDatePicker, |
59 | 59 | NGrid, |
60 | + NGi, | |
60 | 61 | NGridItem, |
61 | 62 | NList, |
62 | 63 | NListItem, |
... | ... | @@ -160,6 +161,7 @@ const naive = create({ |
160 | 161 | NProgress, |
161 | 162 | NDatePicker, |
162 | 163 | NGrid, |
164 | + NGi, | |
163 | 165 | NGridItem, |
164 | 166 | NList, |
165 | 167 | NListItem, | ... | ... |
... | ... | @@ -31,38 +31,20 @@ export const chartColors = { |
31 | 31 | // 默认主题 |
32 | 32 | export const defaultTheme = 'dark' |
33 | 33 | |
34 | -// 主题色列表 | |
35 | -export type ChartColorsNameType = keyof typeof chartColorsName | |
36 | -export const chartColorsName = { | |
37 | - dark: '明亮', | |
38 | - customed: '暗淡', | |
39 | - macarons: '马卡龙', | |
40 | - walden: '蓝绿', | |
41 | - purplePassion: '深紫', | |
42 | - vintage: '复古', | |
43 | - chalk: '粉青', | |
44 | - westeros: '灰粉', | |
45 | - wonderland: '青草', | |
46 | - essos: '橘红', | |
47 | - shine: '深色', | |
48 | - roma: '罗马红' | |
49 | -} | |
34 | +// 默认展示的选择器颜色列表 | |
35 | +export const swatchesColors = ['#232324', '#2a2a2b', '#313132', '#373739', '#757575', '#e0e0e0', '#eeeeee', '#fafafa'] | |
50 | 36 | |
51 | -// 主题色列表 | |
52 | -export const chartColorsshow = { | |
53 | - dark: 'linear-gradient(to right, #4992ff 0%, #7cffb2 100%)', | |
54 | - customed: 'linear-gradient(to right, #5470c6 0%, #91cc75 100%)', | |
55 | - macarons: 'linear-gradient(to right, #2ec7c9 0%, #b6a2de 100%)', | |
56 | - walden: 'linear-gradient(to right, #3fb1e3 0%, #6be6c1 100%)', | |
57 | - purplePassion: 'linear-gradient(to right, #9b8bba 0%, #e098c7 100%)', | |
58 | - vintage: 'linear-gradient(to right, #d87c7c 0%, #919e8b 100%)', | |
59 | - chalk: 'linear-gradient(to right, #fc97af 0%, #87f7cf 100%)', | |
60 | - westeros: 'linear-gradient(to right, #516b91 0%, #edafda 100%)', | |
61 | - wonderland: 'linear-gradient(to right, #4ea397 0%, #22c3aa 100%)', | |
62 | - essos: 'linear-gradient(to right, #893448 0%, #d95850 100%)', | |
63 | - shine: 'linear-gradient(to right, #c12e34 0%, #0098d9 100%)', | |
64 | - roma: 'linear-gradient(to right, #e01f54 0%, #5e4ea5 100%)' | |
37 | +// 自定义颜色 | |
38 | +export type CustomColorsType = { | |
39 | + id: string, | |
40 | + name: string, | |
41 | + color: string[] | |
65 | 42 | } |
43 | + | |
44 | +// 主题色列表, 自定义的颜色使用的是 UUID 作为标识,因为两者数据结构不一致 | |
45 | +export type ChartColorsNameType = keyof typeof chartColors | |
46 | + | |
47 | + | |
66 | 48 | // 渐变主题色列表(主色1、主色2、阴影、渐变1、渐变2) |
67 | 49 | export const chartColorsSearch = { |
68 | 50 | dark: ['#4992ff', '#7cffb2', 'rgba(68, 181, 226, 0.3)', 'rgba(73, 146, 255, 0.5)', 'rgba(124, 255, 178, 0.5)'], | ... | ... |
... | ... | @@ -22,7 +22,8 @@ export enum EditCanvasTypeEnum { |
22 | 22 | LOCK_SCALE = 'lockScale', |
23 | 23 | IS_CREATE = 'isCreate', |
24 | 24 | IS_DRAG = 'isDrag', |
25 | - IS_SELECT = 'isSelect' | |
25 | + IS_SELECT = 'isSelect', | |
26 | + IS_CODE_EDIT="isCodeEdit" | |
26 | 27 | } |
27 | 28 | |
28 | 29 | // 编辑区域 |
... | ... | @@ -44,6 +45,8 @@ export type EditCanvasType = { |
44 | 45 | [EditCanvasTypeEnum.IS_DRAG]: boolean |
45 | 46 | // 框选中 |
46 | 47 | [EditCanvasTypeEnum.IS_SELECT]: boolean |
48 | + // 代码编辑中 | |
49 | + [EditCanvasTypeEnum.IS_CODE_EDIT]: boolean | |
47 | 50 | } |
48 | 51 | |
49 | 52 | // 滤镜/背景色/宽高主题等 |
... | ... | @@ -52,6 +55,7 @@ export enum EditCanvasConfigEnum { |
52 | 55 | WIDTH = 'width', |
53 | 56 | HEIGHT = 'height', |
54 | 57 | CHART_THEME_COLOR = 'chartThemeColor', |
58 | + CHART_CUSTOM_THEME_COLOR_INFO = 'chartCustomThemeColorInfo', | |
55 | 59 | CHART_THEME_SETTING = 'chartThemeSetting', |
56 | 60 | BACKGROUND = 'background', |
57 | 61 | BACKGROUND_IMAGE = 'backgroundImage', |
... | ... | @@ -87,9 +91,12 @@ export interface EditCanvasConfigType { |
87 | 91 | [EditCanvasConfigEnum.HEIGHT]: number |
88 | 92 | // 背景色 |
89 | 93 | [EditCanvasConfigEnum.BACKGROUND]?: string |
94 | + // 背景图片 | |
90 | 95 | [EditCanvasConfigEnum.BACKGROUND_IMAGE]?: string | null |
91 | 96 | // 图表主题颜色 |
92 | 97 | [EditCanvasConfigEnum.CHART_THEME_COLOR]: ChartColorsNameType |
98 | + // 自定义图表主题颜色 | |
99 | + [EditCanvasConfigEnum.CHART_CUSTOM_THEME_COLOR_INFO]?: CustomColorsType[] | |
93 | 100 | // 图表全局配置 |
94 | 101 | [EditCanvasConfigEnum.CHART_THEME_SETTING]: GlobalThemeJsonType |
95 | 102 | // 图表主题颜色 | ... | ... |
... | ... | @@ -54,7 +54,9 @@ export const useChartEditStore = defineStore({ |
54 | 54 | // 拖拽中 |
55 | 55 | isDrag: false, |
56 | 56 | // 框选中 |
57 | - isSelect: false | |
57 | + isSelect: false, | |
58 | + // 代码编辑中 | |
59 | + isCodeEdit: false | |
58 | 60 | }, |
59 | 61 | // 右键菜单 |
60 | 62 | rightMenuShow: false, |
... | ... | @@ -108,6 +110,8 @@ export const useChartEditStore = defineStore({ |
108 | 110 | selectColor: true, |
109 | 111 | // chart 主题色 |
110 | 112 | chartThemeColor: defaultTheme || 'dark', |
113 | + // 自定义颜色列表 | |
114 | + chartCustomThemeColorInfo: undefined, | |
111 | 115 | // 全局配置 |
112 | 116 | chartThemeSetting: globalThemeJson, |
113 | 117 | // 适配方式 |
... | ... | @@ -185,7 +189,7 @@ export const useChartEditStore = defineStore({ |
185 | 189 | this.targetChart.hoverId = hoverId |
186 | 190 | }, |
187 | 191 | // * 设置目标数据 select |
188 | - setTargetSelectChart(selectId?: string | string[], push = false) { | |
192 | + setTargetSelectChart(selectId?: string | string[], push: boolean = false) { | |
189 | 193 | // 重复选中 |
190 | 194 | if (this.targetChart.selectId.find((e: string) => e === selectId)) return |
191 | 195 | |
... | ... | @@ -538,7 +542,7 @@ export const useChartEditStore = defineStore({ |
538 | 542 | this.setTargetSelectChart() |
539 | 543 | |
540 | 544 | // 重新选中 |
541 | - const historyData = HistoryItem.historyData as Array<CreateComponentType | CreateComponentGroupType> | |
545 | + let historyData = HistoryItem.historyData as Array<CreateComponentType | CreateComponentGroupType> | |
542 | 546 | if (isArray(historyData)) { |
543 | 547 | // 选中目标元素,支持多个 |
544 | 548 | historyData.forEach((item: CreateComponentType | CreateComponentGroupType) => { |
... | ... | @@ -835,7 +839,7 @@ export const useChartEditStore = defineStore({ |
835 | 839 | } |
836 | 840 | }, |
837 | 841 | // * 锁定 |
838 | - setLock(status = true, isHistory = true) { | |
842 | + setLock(status: boolean = true, isHistory: boolean = true) { | |
839 | 843 | try { |
840 | 844 | // 暂不支持多选 |
841 | 845 | if (this.getTargetChart.selectId.length > 1) return |
... | ... | @@ -864,11 +868,11 @@ export const useChartEditStore = defineStore({ |
864 | 868 | } |
865 | 869 | }, |
866 | 870 | // * 解除锁定 |
867 | - setUnLock(isHistory = true) { | |
871 | + setUnLock(isHistory: boolean = true) { | |
868 | 872 | this.setLock(false, isHistory) |
869 | 873 | }, |
870 | 874 | // * 隐藏 |
871 | - setHide(status = true, isHistory = true) { | |
875 | + setHide(status: boolean = true, isHistory: boolean = true) { | |
872 | 876 | try { |
873 | 877 | // 暂不支持多选 |
874 | 878 | if (this.getTargetChart.selectId.length > 1) return | ... | ... |
... | ... | @@ -4,8 +4,8 @@ import { AsyncLoading, AsyncSkeletonLoading } from '@/components/GoLoading' |
4 | 4 | /** |
5 | 5 | * * 动态注册组件 |
6 | 6 | */ |
7 | -export const componentInstall = <T>(key: string, node: T) => { | |
8 | - if (!window['$vue'].component(key) && node) { | |
7 | +export const componentInstall = <T> (key:string, node: T) => { | |
8 | + if(!window['$vue'].component(key) && node) { | |
9 | 9 | window['$vue'].component(key, node) |
10 | 10 | } |
11 | 11 | } | ... | ... |
... | ... | @@ -2,6 +2,7 @@ import Color from 'color' |
2 | 2 | import { useDesignStore } from '@/store/modules/designStore/designStore' |
3 | 3 | import { PickCreateComponentType } from '@/packages/index.d' |
4 | 4 | import { EditCanvasConfigType } from '@/store/modules/chartEditStore/chartEditStore.d' |
5 | +import { chartColors, chartColorsSearch, CustomColorsType } from '@/settings/chartThemes/index' | |
5 | 6 | |
6 | 7 | type AttrType = PickCreateComponentType<'attr'> |
7 | 8 | type StylesType = PickCreateComponentType<'styles'> |
... | ... | @@ -87,6 +88,21 @@ export function darken(color: string, concentration: number) { |
87 | 88 | } |
88 | 89 | |
89 | 90 | /** |
91 | + * * hsl 转成16进制 | |
92 | + * @param hsl | |
93 | + * @returns | |
94 | + */ | |
95 | +export function hslToHexa(hslString: string): string { | |
96 | + const color = Color(hslString) | |
97 | + return color.hexa() | |
98 | +} | |
99 | + | |
100 | +export function hslToHex(hslString: string): string { | |
101 | + const color = Color(hslString) | |
102 | + return color.hex() | |
103 | +} | |
104 | + | |
105 | +/** | |
90 | 106 | * * 修改主题色 |
91 | 107 | * @param themeName 主题名称 |
92 | 108 | * @returns |
... | ... | @@ -100,3 +116,48 @@ export const setHtmlTheme = (themeName?: string) => { |
100 | 116 | const designStore = useDesignStore() |
101 | 117 | e.setAttribute('data-theme', designStore.themeName) |
102 | 118 | } |
119 | + | |
120 | +/** | |
121 | + * * 合并基础颜色和自定义颜色 | |
122 | + * @param chartDefaultColors | |
123 | + * @param customColor | |
124 | + * @returns | |
125 | + */ | |
126 | +export const colorCustomMerge = (customColor?: CustomColorsType[]) => { | |
127 | + type FormateCustomColorType = { | |
128 | + [T: string]: { | |
129 | + color: string[] | |
130 | + name: string | |
131 | + } | |
132 | + } | |
133 | + const formateCustomColor: FormateCustomColorType = {} | |
134 | + customColor?.forEach(item => { | |
135 | + formateCustomColor[item.id] = { | |
136 | + color: item.color, | |
137 | + name: item.name | |
138 | + } | |
139 | + }) | |
140 | + return { ...formateCustomColor, ...chartColors } | |
141 | +} | |
142 | + | |
143 | +/** | |
144 | + * * 合并基础渐变颜色和自定义渐变颜色 | |
145 | + * @param customColor | |
146 | + */ | |
147 | +export const colorGradientCustomMerge = (customColor?: CustomColorsType[]) => { | |
148 | + type FormateGradientCustomColorType = { | |
149 | + [T: string]: string[] | |
150 | + } | |
151 | + const formateGradientCustomColor: FormateGradientCustomColorType = {} | |
152 | + customColor?.forEach(item => { | |
153 | + formateGradientCustomColor[item.id] = [ | |
154 | + item.color[0], | |
155 | + item.color[1], | |
156 | + fade(item.color[0], 0.3), | |
157 | + fade(item.color[0], 0.5), | |
158 | + fade(item.color[1], 0.5) | |
159 | + ] | |
160 | + }) | |
161 | + | |
162 | + return { ...formateGradientCustomColor, ...chartColorsSearch } | |
163 | +} | ... | ... |
... | ... | @@ -10,7 +10,7 @@ import cloneDeep from 'lodash/cloneDeep' |
10 | 10 | import { WinKeyboard } from '@/enums/editPageEnum' |
11 | 11 | import { RequestHttpIntervalEnum, RequestParamsObjType } from '@/enums/httpEnum' |
12 | 12 | import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' |
13 | -import { excludeParseEventKeyList } from '@/enums/eventEnum' | |
13 | +import { excludeParseEventKeyList, excludeParseEventValueList } from '@/enums/eventEnum' | |
14 | 14 | |
15 | 15 | /** |
16 | 16 | * * 判断是否是开发环境 |
... | ... | @@ -320,10 +320,17 @@ export const JSONStringify = <T>(data: T) => { |
320 | 320 | */ |
321 | 321 | export const JSONParse = (data: string) => { |
322 | 322 | return JSON.parse(data, (k, v) => { |
323 | + // 过滤函数字符串 | |
323 | 324 | if (excludeParseEventKeyList.includes(k)) return v |
325 | + // 过滤函数值表达式 | |
326 | + if (typeof v === 'string') { | |
327 | + const someValue = excludeParseEventValueList.some(excludeValue => v.indexOf(excludeValue) > -1) | |
328 | + if (someValue) return v | |
329 | + } | |
330 | + // 还原函数值 | |
324 | 331 | if (typeof v === 'string' && v.indexOf && (v.indexOf('function') > -1 || v.indexOf('=>') > -1)) { |
325 | 332 | return eval(`(function(){return ${v}})()`) |
326 | - } else if (typeof v === 'string' && v.indexOf && (v.indexOf('return ') > -1)) { | |
333 | + } else if (typeof v === 'string' && v.indexOf && v.indexOf('return ') > -1) { | |
327 | 334 | const baseLeftIndex = v.indexOf('(') |
328 | 335 | if (baseLeftIndex > -1) { |
329 | 336 | const newFn = `function ${v.substring(baseLeftIndex)}` | ... | ... |
1 | 1 | <template> |
2 | 2 | <div class="go-chart-theme-color"> |
3 | + <n-card class="card-box" size="small" hoverable embedded @click="createColorHandle"> | |
4 | + <n-text class="go-flex-items-center"> | |
5 | + <span>自定义颜色</span> | |
6 | + <n-icon size="16"> | |
7 | + <add-icon></add-icon> | |
8 | + </n-icon> | |
9 | + </n-text> | |
10 | + </n-card> | |
11 | + | |
3 | 12 | <n-card |
4 | - v-for="(value, key) in chartColors" | |
13 | + v-for="(value, key) in comChartColors" | |
5 | 14 | :key="key" |
6 | 15 | class="card-box" |
7 | 16 | :class="{ selected: key === selectName }" |
... | ... | @@ -11,41 +20,51 @@ |
11 | 20 | @click="selectTheme(key)" |
12 | 21 | > |
13 | 22 | <div class="go-flex-items-center"> |
14 | - <n-text>{{ chartColorsName[key] }}</n-text> | |
23 | + <n-ellipsis style="text-align: left; width: 60px">{{ value.name }} </n-ellipsis> | |
15 | 24 | <span |
16 | 25 | class="theme-color-item" |
17 | 26 | v-for="colorItem in fetchShowColors(value.color)" |
18 | 27 | :key="colorItem" |
19 | 28 | :style="{ backgroundColor: colorItem }" |
20 | - ></span> | |
29 | + ></span> | |
21 | 30 | </div> |
22 | - <div | |
23 | - class="theme-bottom" | |
24 | - :style="{ backgroundImage: chartColorsshow[key] }" | |
25 | - ></div> | |
31 | + <div class="theme-bottom" :style="{ backgroundImage: colorBackgroundImage(value) }"></div> | |
26 | 32 | </n-card> |
33 | + <!-- 自定义颜色 modal --> | |
34 | + <create-color v-model:modelShow="createColorModelShow"></create-color> | |
27 | 35 | </div> |
28 | 36 | </template> |
29 | 37 | |
30 | 38 | <script setup lang="ts"> |
31 | -import { computed } from 'vue' | |
39 | +import { ref, computed } from 'vue' | |
40 | +import cloneDeep from 'lodash/cloneDeep' | |
32 | 41 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
33 | 42 | import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' |
34 | -import { | |
35 | - chartColors, | |
36 | - chartColorsName, | |
37 | - chartColorsshow, | |
38 | - ChartColorsNameType | |
39 | -} from '@/settings/chartThemes/index' | |
43 | +import { chartColors, ChartColorsNameType } from '@/settings/chartThemes/index' | |
40 | 44 | import { useDesignStore } from '@/store/modules/designStore/designStore' |
41 | -import cloneDeep from 'lodash/cloneDeep' | |
45 | +import { loadAsyncComponent, colorCustomMerge } from '@/utils' | |
42 | 46 | import { icon } from '@/plugins' |
43 | 47 | |
44 | -const { SquareIcon } = icon.ionicons5 | |
48 | +type FormateCustomColorType = { | |
49 | + [T: string]: { | |
50 | + color: string[] | |
51 | + name: string | |
52 | + } | |
53 | +} | |
54 | + | |
55 | +const CreateColor = loadAsyncComponent(() => import('../CreateColor/index.vue')) | |
56 | + | |
57 | +const { SquareIcon, AddIcon } = icon.ionicons5 | |
45 | 58 | const chartEditStore = useChartEditStore() |
46 | 59 | |
47 | 60 | // 全局颜色 |
48 | 61 | const designStore = useDesignStore() |
62 | +const createColorModelShow = ref(false) | |
63 | + | |
64 | +// 合并默认颜色和自定义颜色 | |
65 | +const comChartColors = computed(() => { | |
66 | + return colorCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo) | |
67 | +}) | |
49 | 68 | |
50 | 69 | // 颜色 |
51 | 70 | const themeColor = computed(() => { |
... | ... | @@ -57,6 +76,16 @@ const selectName = computed(() => { |
57 | 76 | return chartEditStore.getEditCanvasConfig.chartThemeColor |
58 | 77 | }) |
59 | 78 | |
79 | +// 创建颜色 | |
80 | +const createColorHandle = () => { | |
81 | + createColorModelShow.value = true | |
82 | +} | |
83 | + | |
84 | +// 底色 | |
85 | +const colorBackgroundImage = (item: { color: string[] }) => { | |
86 | + return `linear-gradient(to right, ${item.color[0]} 0%, ${item.color[5]} 100%)` | |
87 | +} | |
88 | + | |
60 | 89 | // 获取用来展示的色号 |
61 | 90 | const fetchShowColors = (colors: Array<string>) => { |
62 | 91 | return cloneDeep(colors).splice(0, 6) |
... | ... | @@ -69,36 +98,34 @@ const selectTheme = (theme: ChartColorsNameType) => { |
69 | 98 | </script> |
70 | 99 | |
71 | 100 | <style lang="scss" scoped> |
72 | -@include go(chart-theme-color) { | |
73 | - padding-top: 20px; | |
101 | +$radius: 10px; | |
102 | +$itemRadius: 6px; | |
103 | + | |
104 | +@include go('chart-theme-color') { | |
74 | 105 | .card-box { |
75 | 106 | cursor: pointer; |
76 | 107 | margin-top: 15px; |
77 | 108 | padding: 0; |
78 | 109 | @include fetch-bg-color('background-color4-shallow'); |
79 | - border-radius: 23px; | |
110 | + border-radius: $radius; | |
80 | 111 | overflow: hidden; |
81 | - @include deep() { | |
82 | - .n-card__content { | |
83 | - padding-top: 5px; | |
84 | - padding-bottom: 10px; | |
85 | - } | |
86 | - } | |
112 | + | |
87 | 113 | &.selected { |
88 | - border: 1px solid v-bind('themeColor'); | |
114 | + border: 2px solid v-bind('themeColor'); | |
89 | 115 | border-bottom: 1px solid rgba(0, 0, 0, 0); |
90 | 116 | } |
91 | 117 | &:first-child { |
92 | - margin-top: 0; | |
118 | + margin-top: 5px; | |
93 | 119 | } |
94 | 120 | .go-flex-items-center { |
95 | 121 | justify-content: space-between; |
122 | + margin-top: -4px; | |
96 | 123 | } |
97 | 124 | .theme-color-item { |
98 | 125 | display: inline-block; |
99 | 126 | width: 20px; |
100 | 127 | height: 20px; |
101 | - border-radius: 50%; | |
128 | + border-radius: $itemRadius; | |
102 | 129 | } |
103 | 130 | .theme-bottom { |
104 | 131 | position: absolute; |
... | ... | @@ -106,7 +133,6 @@ const selectTheme = (theme: ChartColorsNameType) => { |
106 | 133 | bottom: 0px; |
107 | 134 | width: 100%; |
108 | 135 | height: 3px; |
109 | - background-image: linear-gradient(to right, #e0c3fc 0%, #8ec5fc 100%); | |
110 | 136 | } |
111 | 137 | } |
112 | 138 | } | ... | ... |
src/views/chart/ContentConfigurations/components/CanvasPage/components/CreateColor/index.vue
0 → 100644
1 | +<template> | |
2 | + <n-modal class="go-chart-create-color" v-model:show="modelShowRef" :mask-closable="false" :closeOnEsc="false"> | |
3 | + <n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 900px; height: 720px"> | |
4 | + <template #header></template> | |
5 | + <template #header-extra> </template> | |
6 | + <div class="create-content"> | |
7 | + <div class="create-color-setting-box"> | |
8 | + <create-color-render | |
9 | + v-if="selectColorId" | |
10 | + :selectColor="selectColor.selectInfo" | |
11 | + @updateColor="updateColorHandle" | |
12 | + ></create-color-render> | |
13 | + <!-- 无数据 --> | |
14 | + <div v-else class="no-data go-flex-center"> | |
15 | + <img :src="noData" alt="暂无数据" /> | |
16 | + <n-text :depth="3">暂未选择自定义颜色</n-text> | |
17 | + </div> | |
18 | + </div> | |
19 | + <div class="color-list-box"> | |
20 | + <n-timeline class="pond-item-timeline" style="width: 20px"> | |
21 | + <n-timeline-item type="info"> </n-timeline-item> | |
22 | + <n-timeline-item type="success"></n-timeline-item> | |
23 | + </n-timeline> | |
24 | + <div class="color-list"> | |
25 | + <n-space> | |
26 | + <!-- 新增 --> | |
27 | + <n-button | |
28 | + class="create-btn" | |
29 | + :class="{ 'is-full': !!!selectColorId }" | |
30 | + type="primary" | |
31 | + :ghost="!!!selectColorId" | |
32 | + :secondary="!!selectColorId" | |
33 | + @click="createColor" | |
34 | + > | |
35 | + <span> 创建 </span> | |
36 | + <template #icon> | |
37 | + <n-icon> | |
38 | + <duplicate-outline-icon></duplicate-outline-icon> | |
39 | + </n-icon> | |
40 | + </template> | |
41 | + </n-button> | |
42 | + <n-badge v-if="selectColorId" :show="updateColor !== undefined" dot> | |
43 | + <n-button class="create-btn" type="info" secondary @click="saveHandle"> | |
44 | + <span> 应用数据 </span> | |
45 | + <template #icon> | |
46 | + <n-icon> | |
47 | + <arrow-down-icon></arrow-down-icon> | |
48 | + </n-icon> | |
49 | + </template> | |
50 | + </n-button> | |
51 | + </n-badge> | |
52 | + </n-space> | |
53 | + <n-divider style="margin: 10px 0"></n-divider> | |
54 | + <n-text v-if="!selectColorId" class="not-data-text" :depth="3"> | |
55 | + 暂无自定义颜色, | |
56 | + <n-a @click="createColor">立即创建</n-a> | |
57 | + </n-text> | |
58 | + <!-- 列表 --> | |
59 | + <div class="color-card-box" v-for="(item, index) in colorList" :key="index"> | |
60 | + <n-card | |
61 | + class="color-card" | |
62 | + :class="{ selected: item.id === selectColorId }" | |
63 | + size="small" | |
64 | + hoverable | |
65 | + embedded | |
66 | + @click="selectHandle(item)" | |
67 | + > | |
68 | + <div class="go-flex-items-center"> | |
69 | + <n-ellipsis style="text-align: left; width: 70px">{{ item.name }} </n-ellipsis> | |
70 | + <span | |
71 | + class="theme-color-item" | |
72 | + v-for="(colorItem, index) in item.color" | |
73 | + :key="index" | |
74 | + :style="{ backgroundColor: colorItem }" | |
75 | + ></span> | |
76 | + </div> | |
77 | + <div class="theme-bottom" :style="{ backgroundImage: colorBackgroundImage(item) }"></div> | |
78 | + </n-card> | |
79 | + <n-tooltip trigger="hover"> | |
80 | + <template #trigger> | |
81 | + <n-button text :disabled="item.id === selectThemeColor" @click="deleteHandle(index)"> | |
82 | + <n-icon class="go-ml-1 go-cursor-pointer" size="16" :depth="3"> | |
83 | + <trash-icon></trash-icon> | |
84 | + </n-icon> | |
85 | + </n-button> | |
86 | + </template> | |
87 | + 删除自定义颜色 | |
88 | + </n-tooltip> | |
89 | + </div> | |
90 | + </div> | |
91 | + </div> | |
92 | + </div> | |
93 | + <!-- 底部 --> | |
94 | + <template #action> | |
95 | + <n-space justify="end"> | |
96 | + <n-button @click="closeHandle">操作完成</n-button> | |
97 | + </n-space> | |
98 | + </template> | |
99 | + </n-card> | |
100 | + </n-modal> | |
101 | +</template> | |
102 | + | |
103 | +<script setup lang="ts"> | |
104 | +import { ref, watch, computed, reactive, nextTick, onMounted } from 'vue' | |
105 | +import cloneDeep from 'lodash/cloneDeep' | |
106 | +import noData from '@/assets/images/canvas/noData.png' | |
107 | +import { getUUID, goDialog } from '@/utils' | |
108 | +import { icon } from '@/plugins' | |
109 | +import { UvIndex } from '@vicons/carbon' | |
110 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
111 | +import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' | |
112 | +import { CreateColorRender } from '../CreateColorRender/index' | |
113 | + | |
114 | +const props = defineProps({ | |
115 | + modelShow: Boolean | |
116 | +}) | |
117 | +const emit = defineEmits(['update:modelShow', 'editSaveHandle']) | |
118 | +const { DuplicateOutlineIcon, TrashIcon, ArrowDownIcon } = icon.ionicons5 | |
119 | + | |
120 | +type ColorType = { | |
121 | + id: string | |
122 | + name: string | |
123 | + color: string[] | |
124 | +} | |
125 | + | |
126 | +// 默认颜色组 | |
127 | +const defaultColor: ColorType = { | |
128 | + id: getUUID(), | |
129 | + name: '未命名', | |
130 | + color: ['#6ae5bb', '#69e3de', '#5ac5ee', '#5ac4ee', '#4498ec', '#3c7ddf'] | |
131 | +} | |
132 | +const chartEditStore = useChartEditStore() | |
133 | +const modelShowRef = ref(false) | |
134 | +// 颜色列表 | |
135 | +let colorList = reactive<Array<ColorType>>(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo || []) | |
136 | +// 子组件更新过的数据 | |
137 | +const updateColor = ref<ColorType | undefined>(undefined) | |
138 | +// 所选颜色 | |
139 | +const selectColor = reactive<{ | |
140 | + selectInfo: ColorType | undefined | |
141 | +}>({ | |
142 | + selectInfo: colorList[0] | |
143 | +}) | |
144 | + | |
145 | +watch( | |
146 | + () => props.modelShow, | |
147 | + newValue => { | |
148 | + modelShowRef.value = newValue | |
149 | + if (newValue) { | |
150 | + // 默认选中 | |
151 | + if (colorList.length) selectColor.selectInfo = colorList[0] | |
152 | + } | |
153 | + } | |
154 | +) | |
155 | + | |
156 | +// 当前选中的 ID | |
157 | +const selectColorId = computed(() => selectColor?.selectInfo?.id) | |
158 | + | |
159 | +// 全局选择的主题 | |
160 | +const selectThemeColor = computed(() => chartEditStore.getEditCanvasConfig.chartThemeColor) | |
161 | + | |
162 | +// 选择 | |
163 | +const selectHandle = (item: ColorType) => { | |
164 | + if (item.id === selectColorId.value) return | |
165 | + if (updateColor.value !== undefined) { | |
166 | + goDialog({ | |
167 | + message: '当前有变动未保存,是否直接放弃修改?', | |
168 | + onPositiveCallback: () => { | |
169 | + updateColor.value = undefined | |
170 | + selectColor.selectInfo = item | |
171 | + } | |
172 | + }) | |
173 | + } else { | |
174 | + selectColor.selectInfo = item | |
175 | + } | |
176 | +} | |
177 | + | |
178 | +// 创建 | |
179 | +const createColor = () => { | |
180 | + const positiveHandle = () => { | |
181 | + const newData = { ...cloneDeep(defaultColor), id: getUUID() } | |
182 | + selectColor.selectInfo = newData | |
183 | + colorList.push(newData) | |
184 | + selectHandle(newData) | |
185 | + updateColor.value = newData | |
186 | + saveHandle(false) | |
187 | + } | |
188 | + if (updateColor.value !== undefined) { | |
189 | + goDialog({ | |
190 | + message: '当前有变动未保存,是否直接放弃修改?', | |
191 | + onPositiveCallback: () => { | |
192 | + updateColor.value = undefined | |
193 | + positiveHandle() | |
194 | + } | |
195 | + }) | |
196 | + } else { | |
197 | + positiveHandle() | |
198 | + } | |
199 | +} | |
200 | + | |
201 | +// 删除 | |
202 | +const deleteHandle = (index: number) => { | |
203 | + const positiveHandle = () => { | |
204 | + colorList.splice(index, 1) | |
205 | + chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.CHART_CUSTOM_THEME_COLOR_INFO, cloneDeep(colorList)) | |
206 | + nextTick(() => { | |
207 | + if (colorList.length) { | |
208 | + selectHandle(colorList[index - 1 > -1 ? index - 1 : index]) | |
209 | + } else { | |
210 | + // 已清空 | |
211 | + selectColor.selectInfo = undefined | |
212 | + } | |
213 | + }) | |
214 | + } | |
215 | + if (updateColor.value !== undefined) { | |
216 | + goDialog({ | |
217 | + message: '当前有变动未保存,是否直接放弃修改?', | |
218 | + onPositiveCallback: () => { | |
219 | + updateColor.value = undefined | |
220 | + positiveHandle() | |
221 | + } | |
222 | + }) | |
223 | + } else { | |
224 | + goDialog({ | |
225 | + message: `是否删除此颜色?`, | |
226 | + onPositiveCallback: () => { | |
227 | + positiveHandle() | |
228 | + } | |
229 | + }) | |
230 | + } | |
231 | +} | |
232 | + | |
233 | +// 存储更新数据的值 | |
234 | +const updateColorHandle = (newColor: ColorType) => { | |
235 | + updateColor.value = newColor | |
236 | +} | |
237 | + | |
238 | +// 保存数据 | |
239 | +const saveHandle = (onMessage = true) => { | |
240 | + if (!updateColor.value) return | |
241 | + const index = colorList.findIndex(item => item.id === updateColor.value?.id) | |
242 | + if (index !== -1) { | |
243 | + onMessage && window.$message.success('数据应用成功!') | |
244 | + const updateColorPrefix = cloneDeep({ ...updateColor.value, name: updateColor.value.name || '未定义' }) | |
245 | + colorList.splice(index, 1, updateColorPrefix) | |
246 | + updateColor.value = undefined | |
247 | + const selectTheme = chartEditStore.getEditCanvasConfig.chartThemeColor | |
248 | + // 变换主题强制渐变色更新 | |
249 | + chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.CHART_THEME_COLOR, 'dark') | |
250 | + // 存储到全局数据中 | |
251 | + nextTick(() => { | |
252 | + chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.CHART_CUSTOM_THEME_COLOR_INFO, cloneDeep(colorList)) | |
253 | + chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.CHART_THEME_COLOR, selectTheme) | |
254 | + }) | |
255 | + } else { | |
256 | + window.$message.error('数据应用失败!') | |
257 | + } | |
258 | +} | |
259 | + | |
260 | +// 关闭 | |
261 | +const closeHandle = () => { | |
262 | + const positiveHandle = () => { | |
263 | + updateColor.value = undefined | |
264 | + selectColor.selectInfo = undefined | |
265 | + emit('update:modelShow', false) | |
266 | + } | |
267 | + | |
268 | + if (updateColor.value !== undefined) { | |
269 | + goDialog({ | |
270 | + message: '当前有变动未保存,是否直接放弃修改?', | |
271 | + onPositiveCallback: () => { | |
272 | + positiveHandle() | |
273 | + } | |
274 | + }) | |
275 | + } else { | |
276 | + positiveHandle() | |
277 | + } | |
278 | +} | |
279 | + | |
280 | +// 底色 | |
281 | +const colorBackgroundImage = (item: ColorType) => { | |
282 | + return `linear-gradient(to right, ${item.color[0]} 0%, ${item.color[5]} 100%)` | |
283 | +} | |
284 | +</script> | |
285 | + | |
286 | +<style scoped lang="scss"> | |
287 | +$height: 600px; | |
288 | +$listWidth: 280px; | |
289 | +$color-radius: 8px; | |
290 | +$color-item-radius: 4px; | |
291 | + | |
292 | +@include go('chart-create-color') { | |
293 | + .create-content { | |
294 | + display: flex; | |
295 | + /* 左侧 */ | |
296 | + .create-color-setting-box { | |
297 | + flex: 1; | |
298 | + .no-data { | |
299 | + flex-direction: column; | |
300 | + width: 100%; | |
301 | + height: 100%; | |
302 | + img { | |
303 | + width: 200px; | |
304 | + } | |
305 | + } | |
306 | + } | |
307 | + /* 列表 */ | |
308 | + .color-list-box { | |
309 | + display: flex; | |
310 | + padding-top: 10px; | |
311 | + margin-right: 5px; | |
312 | + .pond-item-timeline > .n-timeline-item { | |
313 | + &:first-child { | |
314 | + height: $height; | |
315 | + } | |
316 | + } | |
317 | + .color-list { | |
318 | + width: $listWidth; | |
319 | + position: relative; | |
320 | + padding-right: 8px; | |
321 | + .create-btn { | |
322 | + width: 133px; | |
323 | + &.is-full { | |
324 | + width: 280px; | |
325 | + } | |
326 | + } | |
327 | + .not-data-text { | |
328 | + display: block; | |
329 | + text-align: center; | |
330 | + } | |
331 | + .color-card-box { | |
332 | + display: flex; | |
333 | + align-items: center; | |
334 | + justify-content: space-between; | |
335 | + margin-top: 15px; | |
336 | + &:first-child { | |
337 | + margin-top: 0; | |
338 | + } | |
339 | + .color-card { | |
340 | + overflow: hidden; | |
341 | + cursor: pointer; | |
342 | + border-radius: $color-radius; | |
343 | + border: 2px solid rgba(0, 0, 0, 0); | |
344 | + border-bottom: 1px solid rgba(0, 0, 0, 0); | |
345 | + @include fetch-bg-color('background-color4-shallow'); | |
346 | + | |
347 | + @include deep() { | |
348 | + & > .n-card__content { | |
349 | + padding: 7px; | |
350 | + padding-top: 10px; | |
351 | + padding-bottom: 10px; | |
352 | + } | |
353 | + } | |
354 | + &.selected { | |
355 | + border: 2px solid var(--n-color-target); | |
356 | + border-bottom: 1px solid rgba(0, 0, 0, 0); | |
357 | + } | |
358 | + .go-flex-items-center { | |
359 | + justify-content: space-between; | |
360 | + margin-top: -4px; | |
361 | + } | |
362 | + .theme-color-item { | |
363 | + display: inline-block; | |
364 | + width: 16px; | |
365 | + height: 16px; | |
366 | + border-radius: $color-item-radius; | |
367 | + } | |
368 | + .theme-bottom { | |
369 | + position: absolute; | |
370 | + left: 0; | |
371 | + bottom: 0px; | |
372 | + width: 100%; | |
373 | + height: 3px; | |
374 | + } | |
375 | + } | |
376 | + } | |
377 | + } | |
378 | + } | |
379 | + } | |
380 | + &.n-card.n-modal, | |
381 | + .n-card { | |
382 | + @extend .go-background-filter; | |
383 | + } | |
384 | + .n-card-shallow { | |
385 | + background-color: rgba(0, 0, 0, 0) !important; | |
386 | + } | |
387 | + @include deep() { | |
388 | + & > .n-card__content { | |
389 | + padding-right: 0; | |
390 | + } | |
391 | + } | |
392 | +} | |
393 | +</style> | ... | ... |
src/views/chart/ContentConfigurations/components/CanvasPage/components/CreateColorRender/index.vue
0 → 100644
1 | +<template> | |
2 | + <div class="create-color-setting" v-if="editColor"> | |
3 | + <n-card :bordered="false" role="dialog" size="small" aria-modal="true"> | |
4 | + <n-space justify="space-between"> | |
5 | + <!-- 名称 --> | |
6 | + <n-input-group> | |
7 | + <n-input-group-label>名称:</n-input-group-label> | |
8 | + <n-input | |
9 | + class="create-color-name" | |
10 | + v-model:value.trim="editColor.name" | |
11 | + maxlength="8" | |
12 | + show-count | |
13 | + clearable | |
14 | + @change="titleChangeHandle" | |
15 | + /> | |
16 | + </n-input-group> | |
17 | + <n-tag type="warning">底部图表仅展示 7 条数据</n-tag> | |
18 | + </n-space> | |
19 | + <!-- 颜色 --> | |
20 | + <n-scrollbar style="max-height: 132px"> | |
21 | + <div class="color-list-box go-mt-3" :x-gap="12" :y-gap="12" :cols="4"> | |
22 | + <div class="color-list-item" v-for="(item, index) in editColor.color" :key="index"> | |
23 | + <div class="go-flex-items-center" :class="{ select: index === targetColor.index }"> | |
24 | + <n-color-picker | |
25 | + style="width: 95px" | |
26 | + v-model:value="editColor.color[index]" | |
27 | + :show-preview="true" | |
28 | + :modes="['hex']" | |
29 | + @complete="completeHandle($event, index)" | |
30 | + @update:show="selectHandle(item, index)" | |
31 | + /> | |
32 | + <div v-show="index > 5"> | |
33 | + <n-tooltip trigger="hover"> | |
34 | + <template #trigger> | |
35 | + <n-icon class="go-ml-1 go-cursor-pointer" size="16" :depth="3" @click="deleteColor(index)"> | |
36 | + <trash-icon></trash-icon> | |
37 | + </n-icon> | |
38 | + </template> | |
39 | + 删除颜色 | |
40 | + </n-tooltip> | |
41 | + </div> | |
42 | + </div> | |
43 | + </div> | |
44 | + <div> | |
45 | + <n-button type="primary" secondary @click="addColor"> | |
46 | + <div class="go-flex-items-center"> | |
47 | + <span class="go-mr-4">添加</span> | |
48 | + <n-icon size="16"> | |
49 | + <add-icon></add-icon> | |
50 | + </n-icon> | |
51 | + </div> | |
52 | + </n-button> | |
53 | + </div> | |
54 | + </div> | |
55 | + </n-scrollbar> | |
56 | + </n-card> | |
57 | + | |
58 | + <!-- 扩展色 --> | |
59 | + <div class="expend-color-box"> | |
60 | + <n-card class="go-mt-3 expend-color" :bordered="false" role="dialog" size="small" aria-modal="true"> | |
61 | + <n-text>默认扩展色:</n-text> | |
62 | + <n-divider style="margin: 10px 0"></n-divider> | |
63 | + <n-space :size="[4, 0]" justify="center"> | |
64 | + <div | |
65 | + class="color-computed-item" | |
66 | + v-for="(item, index) in expandColorList.default" | |
67 | + :key="index" | |
68 | + @click="selectExpandColor(item, false)" | |
69 | + > | |
70 | + <div class="n-color-picker-checkboard"></div> | |
71 | + <div :style="getRenderBackgroundColor(item)"></div> | |
72 | + </div> | |
73 | + </n-space> | |
74 | + </n-card> | |
75 | + <n-card class="go-mt-3 expend-color" :bordered="false" role="dialog" size="small" aria-modal="true"> | |
76 | + <n-text>透明扩展色:</n-text> | |
77 | + <n-divider style="margin: 10px 0"></n-divider> | |
78 | + <n-space :size="[4, 0]" justify="center"> | |
79 | + <div | |
80 | + class="color-computed-item" | |
81 | + v-for="(item, index) in expandColorList.fade" | |
82 | + :key="index" | |
83 | + @click="selectExpandColor(item, true)" | |
84 | + > | |
85 | + <div class="n-color-picker-checkboard"></div> | |
86 | + <div :style="getRenderBackgroundColor(item)"></div> | |
87 | + </div> | |
88 | + </n-space> | |
89 | + </n-card> | |
90 | + </div> | |
91 | + | |
92 | + <!-- 展示图表 --> | |
93 | + <create-color-render-chart :color="cloneDeep(editColor.color).splice(0, 7)"></create-color-render-chart> | |
94 | + </div> | |
95 | +</template> | |
96 | + | |
97 | +<script setup lang="ts"> | |
98 | +import { PropType, ref, watch, computed, reactive, nextTick } from 'vue' | |
99 | +import cloneDeep from 'lodash/cloneDeep' | |
100 | +import { darken, lighten, fade, hslToHex, hslToHexa, loadAsyncComponent } from '@/utils' | |
101 | +import { icon } from '@/plugins' | |
102 | + | |
103 | +type ColorType = { | |
104 | + id: string | |
105 | + name: string | |
106 | + color: string[] | |
107 | +} | |
108 | + | |
109 | +const props = defineProps({ | |
110 | + selectColor: Object as PropType<ColorType> | |
111 | +}) | |
112 | + | |
113 | +const emit = defineEmits(['updateColor']) | |
114 | + | |
115 | +const { AddIcon, TrashIcon } = icon.ionicons5 | |
116 | +const CreateColorRenderChart = loadAsyncComponent(() => import('../CreateColorRenderChart/index.vue')) | |
117 | + | |
118 | +// 拷贝的一份数据 | |
119 | +const editColor = ref<ColorType | undefined>() | |
120 | +// 目标颜色 | |
121 | +const targetColor = reactive<{ | |
122 | + index: number | |
123 | + color?: string | |
124 | +}>({ | |
125 | + // -1 表示无选中元素 | |
126 | + index: -1, | |
127 | + color: '' | |
128 | +}) | |
129 | + | |
130 | +// 监听值 | |
131 | +watch( | |
132 | + () => props.selectColor?.id, | |
133 | + () => { | |
134 | + editColor.value = cloneDeep(props.selectColor) | |
135 | + targetColor.index = 0 | |
136 | + targetColor.color = editColor.value?.color[0] | |
137 | + }, | |
138 | + { | |
139 | + immediate: true, | |
140 | + deep: false | |
141 | + } | |
142 | +) | |
143 | + | |
144 | +// 扩展色 | |
145 | +const expandColorList = computed(() => { | |
146 | + return computedColorList(targetColor.color) | |
147 | +}) | |
148 | + | |
149 | +// 计算背景色 | |
150 | +const computedColorList = (color?: string) => { | |
151 | + if (!color) | |
152 | + return { | |
153 | + default: [], | |
154 | + fade: [] | |
155 | + } | |
156 | + const num: number = 36 | |
157 | + const comDarkenArr: string[] = [] | |
158 | + const comLightenArr: string[] = [] | |
159 | + const comDarkenFadeArr: string[] = [] | |
160 | + | |
161 | + for (let i = 0; i < num; i++) { | |
162 | + comLightenArr.unshift(lighten(color, (1 / 100) * (i + 1))) | |
163 | + comDarkenArr.push(darken(color, (3.5 / 100) * (i + 1))) | |
164 | + } | |
165 | + | |
166 | + // 透明 | |
167 | + comDarkenArr.forEach((item, i) => { | |
168 | + comDarkenFadeArr.unshift(fade(item, (1 / 100) * (i + 1))) | |
169 | + }) | |
170 | + | |
171 | + return { | |
172 | + default: [ | |
173 | + ...comLightenArr.reverse().splice(0, parseInt(`${num / 2}`) - 9), | |
174 | + ...comDarkenArr.splice(0, parseInt(`${num / 2}`)) | |
175 | + ], | |
176 | + fade: comDarkenFadeArr.reverse().splice(0, 27) | |
177 | + } | |
178 | +} | |
179 | + | |
180 | +// 渲染背景色 | |
181 | +const getRenderBackgroundColor = (color?: string) => { | |
182 | + return { | |
183 | + backgroundColor: color | |
184 | + } | |
185 | +} | |
186 | + | |
187 | +// 点击颜色 | |
188 | +const selectHandle = (color: string, index: number) => { | |
189 | + targetColor.color = color | |
190 | + targetColor.index = index | |
191 | +} | |
192 | + | |
193 | +// 顶部改变颜色 | |
194 | +const completeHandle = (color?: string, index?: number) => { | |
195 | + color && (targetColor.color = color) | |
196 | + index && (targetColor.index = index) | |
197 | + nextTick(() => { | |
198 | + emit('updateColor', editColor.value) | |
199 | + }) | |
200 | +} | |
201 | + | |
202 | +// 选择扩展色 | |
203 | +const selectExpandColor = (color: string, isHexa: boolean) => { | |
204 | + const hexColor = isHexa ? hslToHexa(color) : hslToHex(color) | |
205 | + editColor.value && (editColor.value.color[targetColor.index] = hexColor) | |
206 | + nextTick(() => { | |
207 | + emit('updateColor', editColor.value) | |
208 | + }) | |
209 | +} | |
210 | + | |
211 | +// 新增颜色 | |
212 | +const addColor = () => { | |
213 | + const lastData = editColor.value?.color[editColor.value?.color.length - 1] || '#2c2c31' | |
214 | + editColor.value?.color.push(lastData) | |
215 | + nextTick(() => { | |
216 | + emit('updateColor', editColor.value) | |
217 | + }) | |
218 | +} | |
219 | + | |
220 | +// 删除颜色 | |
221 | +const deleteColor = (index: number) => { | |
222 | + editColor.value?.color.splice(index, 1) | |
223 | + if (index === targetColor.index) { | |
224 | + completeHandle(editColor.value?.color[index - 1], index - 1) | |
225 | + } | |
226 | +} | |
227 | + | |
228 | +// 修改名称 | |
229 | +const titleChangeHandle = () => { | |
230 | + nextTick(() => { | |
231 | + emit('updateColor', editColor.value) | |
232 | + }) | |
233 | +} | |
234 | +</script> | |
235 | + | |
236 | +<style scoped lang="scss"> | |
237 | +.create-color-setting { | |
238 | + display: flex; | |
239 | + flex-direction: column; | |
240 | + justify-content: space-between; | |
241 | + height: 100%; | |
242 | + padding-right: 10px; | |
243 | + .create-color-name { | |
244 | + width: 200px; | |
245 | + } | |
246 | + .color-list-box { | |
247 | + display: flex; | |
248 | + flex-wrap: wrap; | |
249 | + row-gap: 8px; | |
250 | + .color-list-item { | |
251 | + width: calc(100% / 4); | |
252 | + .select { | |
253 | + .n-color-picker { | |
254 | + border: 2px solid v-bind('targetColor.color'); | |
255 | + border-radius: 5px; | |
256 | + } | |
257 | + } | |
258 | + } | |
259 | + } | |
260 | + .expend-color-box { | |
261 | + display: flex; | |
262 | + justify-content: space-between; | |
263 | + align-items: center; | |
264 | + .expend-color { | |
265 | + width: calc(50% - 5px); | |
266 | + .color-computed-item { | |
267 | + position: relative; | |
268 | + display: inline-block; | |
269 | + height: 22px; | |
270 | + width: 22px; | |
271 | + cursor: pointer; | |
272 | + overflow: hidden; | |
273 | + border-radius: 4px; | |
274 | + & div { | |
275 | + position: absolute; | |
276 | + display: inline-block; | |
277 | + height: 22px; | |
278 | + width: 22px; | |
279 | + } | |
280 | + } | |
281 | + } | |
282 | + } | |
283 | +} | |
284 | +</style> | ... | ... |
1 | +import { echartOptionProfixHandle } from '@/packages/public' | |
2 | + | |
3 | +export const includes = ['legend', 'xAxis', 'yAxis', 'grid'] | |
4 | + | |
5 | +const seriesHandle = (color: string[]) => { | |
6 | + const numHandle = (numsi: number, i: number) => parseInt(`${numsi * Math.random()}`, 10) * 2 | |
7 | + const nums = [260, 251, 200, 334, 366, 256, 253] | |
8 | + | |
9 | + return color.map((item, index) => ({ | |
10 | + name: `data${index + 1}`, | |
11 | + type: 'bar', | |
12 | + data: nums.map((numsItem, numsi) => numHandle(numsItem, index)) | |
13 | + })) | |
14 | +} | |
15 | + | |
16 | +export const option = (color: string[]) => { | |
17 | + return echartOptionProfixHandle( | |
18 | + { | |
19 | + tooltip: { | |
20 | + trigger: 'axis', | |
21 | + showContent: false, | |
22 | + axisPointer: { | |
23 | + type: 'shadow' | |
24 | + } | |
25 | + }, | |
26 | + grid: { | |
27 | + left: '3%', | |
28 | + right: '4%', | |
29 | + bottom: '3%', | |
30 | + containLabel: true | |
31 | + }, | |
32 | + xAxis: { | |
33 | + type: 'category', | |
34 | + data: color.map((e, i) => `data${i + 1}`), | |
35 | + axisTick: { | |
36 | + alignWithLabel: true | |
37 | + } | |
38 | + }, | |
39 | + yAxis: { | |
40 | + show: true, | |
41 | + type: 'value' | |
42 | + }, | |
43 | + series: seriesHandle(color || []) | |
44 | + }, | |
45 | + includes | |
46 | + ) | |
47 | +} | ... | ... |
1 | +<template> | |
2 | + <n-space> | |
3 | + <n-card v-if="barOption" class="go-mt-3" :bordered="false" role="dialog" size="small" aria-modal="true"> | |
4 | + <n-tabs type="segment" size="small" animated> | |
5 | + <n-tab-pane name="柱状图" tab="柱状图"> | |
6 | + <v-chart | |
7 | + ref="vChartRefBar" | |
8 | + :theme="{ color }" | |
9 | + :option="barOption" | |
10 | + :manual-update="true" | |
11 | + autoresize | |
12 | + :style="chartStyle" | |
13 | + ></v-chart> | |
14 | + </n-tab-pane> | |
15 | + <n-tab-pane name="折线图" tab="折线图"> | |
16 | + <v-chart | |
17 | + ref="vChartRefLine" | |
18 | + :theme="{ color }" | |
19 | + :option="lineOption" | |
20 | + :manual-update="true" | |
21 | + autoresize | |
22 | + :style="chartStyle" | |
23 | + ></v-chart> | |
24 | + </n-tab-pane> | |
25 | + </n-tabs> | |
26 | + </n-card> | |
27 | + </n-space> | |
28 | +</template> | |
29 | + | |
30 | +<script setup lang="ts"> | |
31 | +import { ref, watch, PropType } from 'vue' | |
32 | +import VChart from 'vue-echarts' | |
33 | +import { CanvasRenderer } from 'echarts/renderers' | |
34 | +import { BarChart, LineChart } from 'echarts/charts' | |
35 | +import { use } from 'echarts/core' | |
36 | +import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components' | |
37 | +import { option as barOptions } from './barOptions' | |
38 | +import { option as lineOptions } from './lineOptions' | |
39 | + | |
40 | +const props = defineProps({ | |
41 | + color: { | |
42 | + type: Array as PropType<string[]>, | |
43 | + required: true | |
44 | + } | |
45 | +}) | |
46 | +use([DatasetComponent, CanvasRenderer, BarChart, LineChart, GridComponent, TooltipComponent, LegendComponent]) | |
47 | + | |
48 | +const barOption = ref() | |
49 | +const lineOption = ref() | |
50 | + | |
51 | +const chartStyle = { | |
52 | + width: '528px', | |
53 | + height: '200px' | |
54 | +} | |
55 | + | |
56 | +watch( | |
57 | + () => props.color, | |
58 | + (newData: string[]) => { | |
59 | + barOption.value = barOptions(newData) | |
60 | + lineOption.value = lineOptions(newData) | |
61 | + }, | |
62 | + { | |
63 | + immediate: true, | |
64 | + deep: true | |
65 | + } | |
66 | +) | |
67 | +</script> | |
\ No newline at end of file | ... | ... |
1 | +import { echartOptionProfixHandle } from '@/packages/public' | |
2 | +import { graphic } from 'echarts/core' | |
3 | +import { fade, hslToHex } from '@/utils' | |
4 | + | |
5 | +export const includes = ['legend', 'xAxis', 'yAxis', 'grid'] | |
6 | + | |
7 | +const seriesHandle = (color: string[]) => { | |
8 | + const numHandle = (numsi: number, i: number) => parseInt(`${numsi * Math.random()}`, 10) * 2 | |
9 | + const nums = [130, 251, 200, 334, 366, 456, 223] | |
10 | + | |
11 | + return color.map((item, index) => ({ | |
12 | + name: `data${index + 1}`, | |
13 | + type: 'line', | |
14 | + smooth: true, | |
15 | + lineStyle: { | |
16 | + width: 1, | |
17 | + type: 'solid' | |
18 | + }, | |
19 | + emphasis: { | |
20 | + focus: 'series' | |
21 | + }, | |
22 | + areaStyle: { | |
23 | + opacity: 0.8, | |
24 | + color: new graphic.LinearGradient(0, 0, 0, 1, [ | |
25 | + { | |
26 | + offset: 1, | |
27 | + color: item | |
28 | + }, | |
29 | + { | |
30 | + offset: 0, | |
31 | + color: item | |
32 | + } | |
33 | + ]) | |
34 | + }, | |
35 | + showSymbol: false, | |
36 | + data: nums.reverse().map((numsItem, numsi) => numHandle(numsItem, index)) | |
37 | + })) | |
38 | +} | |
39 | + | |
40 | +export const option = (color: string[]) => { | |
41 | + return echartOptionProfixHandle( | |
42 | + { | |
43 | + tooltip: { | |
44 | + trigger: 'axis', | |
45 | + showContent: false, | |
46 | + axisPointer: { | |
47 | + type: 'shadow' | |
48 | + } | |
49 | + }, | |
50 | + grid: { | |
51 | + left: '3%', | |
52 | + right: '4%', | |
53 | + bottom: '3%', | |
54 | + containLabel: true | |
55 | + }, | |
56 | + xAxis: { | |
57 | + type: 'category', | |
58 | + boundaryGap: false, | |
59 | + data: color.map((e, i) => `data${i + 1}`), | |
60 | + axisTick: { | |
61 | + alignWithLabel: true | |
62 | + } | |
63 | + }, | |
64 | + yAxis: { | |
65 | + show: true, | |
66 | + type: 'value' | |
67 | + }, | |
68 | + series: seriesHandle(color || []) | |
69 | + }, | |
70 | + includes | |
71 | + ) | |
72 | +} | ... | ... |
... | ... | @@ -21,7 +21,8 @@ |
21 | 21 | ></n-input-number> |
22 | 22 | </n-form-item> |
23 | 23 | </n-form> |
24 | - <n-card class="upload-box"> | |
24 | + | |
25 | + <div class="upload-box"> | |
25 | 26 | <n-upload |
26 | 27 | v-model:file-list="uploadFileListRef" |
27 | 28 | :show-file-list="false" |
... | ... | @@ -38,7 +39,7 @@ |
38 | 39 | </div> |
39 | 40 | </n-upload-dragger> |
40 | 41 | </n-upload> |
41 | - </n-card> | |
42 | + </div> | |
42 | 43 | <n-space vertical :size="12"> |
43 | 44 | <n-space> |
44 | 45 | <n-text>背景选择</n-text> |
... | ... | @@ -138,11 +139,12 @@ |
138 | 139 | <script setup lang="ts"> |
139 | 140 | import { ref, nextTick, watch } from 'vue' |
140 | 141 | import { backgroundImageSize } from '@/settings/designSetting' |
142 | +import { swatchesColors } from '@/settings/chartThemes/index' | |
141 | 143 | import { FileTypeEnum } from '@/enums/fileTypeEnum' |
142 | 144 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
143 | 145 | import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' |
144 | 146 | import { StylesSetting } from '@/components/Pages/ChartItemSetting' |
145 | -import { UploadCustomRequestOptions, SelectOption } from 'naive-ui' | |
147 | +import { UploadCustomRequestOptions } from 'naive-ui' | |
146 | 148 | import { fileToUrl, loadAsyncComponent } from '@/utils' |
147 | 149 | import { PreviewScaleEnum } from '@/enums/styleEnum' |
148 | 150 | import { icon } from '@/plugins' |
... | ... | @@ -187,9 +189,6 @@ const selectColorOptions = [ |
187 | 189 | } |
188 | 190 | ] |
189 | 191 | |
190 | -// 默认展示颜色列表 | |
191 | -const swatchesColors = ['#232324', '#2a2a2b', '#313132', '#373739', '#757575', '#e0e0e0', '#eeeeee', '#fafafa'] | |
192 | - | |
193 | 192 | const globalTabList = [ |
194 | 193 | { |
195 | 194 | key: 'ChartTheme', |
... | ... | @@ -317,7 +316,7 @@ const selectPreviewType = (key: PreviewScaleEnum) => { |
317 | 316 | </script> |
318 | 317 | |
319 | 318 | <style lang="scss" scoped> |
320 | -$uploadWidth: 280px; | |
319 | +$uploadWidth: 326px; | |
321 | 320 | $uploadHeight: 193px; |
322 | 321 | @include go(canvas-setting) { |
323 | 322 | padding-top: 20px; |
... | ... | @@ -325,13 +324,10 @@ $uploadHeight: 193px; |
325 | 324 | cursor: pointer; |
326 | 325 | margin-bottom: 20px; |
327 | 326 | @include deep() { |
328 | - .n-card__content { | |
329 | - padding: 0; | |
330 | - overflow: hidden; | |
331 | - } | |
332 | 327 | .n-upload-dragger { |
333 | 328 | padding: 5px; |
334 | 329 | width: $uploadWidth; |
330 | + background-color: rgba(0, 0, 0, 0); | |
335 | 331 | } |
336 | 332 | } |
337 | 333 | .upload-show { | ... | ... |
1 | 1 | <template> |
2 | 2 | <div class="go-chart-data-pond-list"> |
3 | - <n-timeline style="width: 20px"> | |
3 | + <n-timeline class="pond-item-timeline" style="width: 20px"> | |
4 | 4 | <n-timeline-item type="info"> </n-timeline-item> |
5 | 5 | <n-timeline-item type="success"></n-timeline-item> |
6 | 6 | </n-timeline> |
... | ... | @@ -115,11 +115,9 @@ $textSize: 10px; |
115 | 115 | padding-bottom: 5px; |
116 | 116 | margin-right: 5px; |
117 | 117 | display: flex; |
118 | - @include deep() { | |
119 | - .n-timeline > .n-timeline-item { | |
120 | - &:first-child { | |
121 | - height: $height; | |
122 | - } | |
118 | + .pond-item-timeline > .n-timeline-item { | |
119 | + &:first-child { | |
120 | + height: $height; | |
123 | 121 | } |
124 | 122 | } |
125 | 123 | .pond-item-box { | ... | ... |
... | ... | @@ -56,7 +56,7 @@ import { MenuEnum } from '@/enums/editPageEnum' |
56 | 56 | import { chartColors } from '@/settings/chartThemes/index' |
57 | 57 | import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' |
58 | 58 | import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d' |
59 | -import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle } from '@/utils' | |
59 | +import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle, colorCustomMerge } from '@/utils' | |
60 | 60 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
61 | 61 | import { useContextMenu, divider } from '@/views/chart/hooks/useContextMenu.hook' |
62 | 62 | import { useMouseHandle } from '../../hooks/useDrag.hook' |
... | ... | @@ -117,8 +117,8 @@ const optionsHandle = ( |
117 | 117 | |
118 | 118 | // 配置项 |
119 | 119 | const themeColor = computed(() => { |
120 | - const chartThemeColor = chartEditStore.getEditCanvasConfig.chartThemeColor | |
121 | - return chartColors[chartThemeColor] | |
120 | + const colorCustomMergeData = colorCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo) | |
121 | + return colorCustomMergeData[chartEditStore.getEditCanvasConfig.chartThemeColor] | |
122 | 122 | }) |
123 | 123 | |
124 | 124 | // 主题色 | ... | ... |
... | ... | @@ -55,7 +55,7 @@ const rangeModelStyle = computed(() => { |
55 | 55 | position: relative; |
56 | 56 | transform-origin: left top; |
57 | 57 | background-size: cover; |
58 | - border-radius: 20px; | |
58 | + border-radius: 10px; | |
59 | 59 | overflow: hidden; |
60 | 60 | @include fetch-border-color('hover-border-color'); |
61 | 61 | @include fetch-bg-color('background-color2'); | ... | ... |
1 | 1 | import { watch } from 'vue' |
2 | 2 | import { useRoute } from 'vue-router' |
3 | +import throttle from 'lodash/throttle' | |
3 | 4 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
5 | +import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d' | |
4 | 6 | import { useSync } from '@/views/chart/hooks/useSync.hook' |
5 | 7 | import { ChartEnum } from '@/enums/pageEnum' |
6 | 8 | import { SavePageEnum } from '@/enums/editPageEnum' |
7 | 9 | import { editToJsonInterval } from '@/settings/designSetting' |
10 | +import { goDialog } from '@/utils' | |
8 | 11 | |
9 | 12 | const { updateComponent } = useSync() |
10 | 13 | const chartEditStore = useChartEditStore() |
11 | 14 | |
15 | +export const syncData = () => { | |
16 | + goDialog({ | |
17 | + message: '是否覆盖源视图内容,此操作不可撤回?', | |
18 | + isMaskClosable: true, | |
19 | + transformOrigin: 'center', | |
20 | + onPositiveCallback: () => { | |
21 | + window['$message'].success('正在同步编辑器...') | |
22 | + dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo })) | |
23 | + } | |
24 | + }) | |
25 | +} | |
26 | + | |
12 | 27 | // 侦听器更新 |
13 | 28 | const useSyncUpdateHandle = () => { |
14 | 29 | // 定义侦听器变量 |
15 | 30 | let timer: any |
16 | - const updateFn = (e: any) => updateComponent(e!.detail, true, false) | |
17 | - const syncData = async () => { | |
18 | - dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo })) | |
31 | + | |
32 | + // 更新处理 | |
33 | + const updateFn = (e: any) => { | |
34 | + window['$message'].success('正在进行更新...') | |
35 | + updateComponent(e!.detail, true) | |
36 | + } | |
37 | + | |
38 | + // 页面关闭处理 | |
39 | + const closeFn = () => { | |
40 | + chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CODE_EDIT, false) | |
19 | 41 | } |
20 | 42 | |
21 | 43 | // 开启侦听 |
22 | 44 | const use = () => { |
23 | - // // 1、定时同步数据 | |
45 | + // 定时同步数据(暂不开启) | |
24 | 46 | // timer = setInterval(() => { |
25 | 47 | // // 窗口激活并且处于工作台 |
26 | 48 | // document.hasFocus() && syncData() |
27 | 49 | // }, editToJsonInterval) |
50 | + | |
28 | 51 | // 2、失焦同步数据 |
29 | 52 | addEventListener('blur', syncData) |
30 | 53 | |
31 | 54 | // 【监听JSON代码 刷新工作台图表】 |
32 | 55 | addEventListener(SavePageEnum.JSON, updateFn) |
56 | + | |
57 | + // 监听编辑页关闭 | |
58 | + addEventListener(SavePageEnum.CLOSE, throttle(closeFn, 1000)) | |
33 | 59 | } |
34 | 60 | |
35 | 61 | // 关闭侦听 |
36 | 62 | const unUse = () => { |
37 | 63 | // clearInterval(timer) |
64 | + // removeEventListener('blur', syncData) | |
38 | 65 | removeEventListener(SavePageEnum.JSON, updateFn) |
39 | - removeEventListener('blur', syncData) | |
40 | 66 | } |
41 | 67 | |
42 | 68 | // 路由变更时处理 | ... | ... |
... | ... | @@ -66,7 +66,14 @@ import { ref, computed } from 'vue' |
66 | 66 | import { useSettingStore } from '@/store/modules/settingStore/settingStore' |
67 | 67 | import { ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d' |
68 | 68 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
69 | -import { fetchRouteParamsLocation, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils' | |
69 | +import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d' | |
70 | +import { | |
71 | + fetchRouteParamsLocation, | |
72 | + fetchPathByName, | |
73 | + routerTurnByPath, | |
74 | + setSessionStorage, | |
75 | + getLocalStorage | |
76 | +} from '@/utils' | |
70 | 77 | import { EditEnum } from '@/enums/pageEnum' |
71 | 78 | import { StorageEnum } from '@/enums/storageEnum' |
72 | 79 | import { useRoute } from 'vue-router' |
... | ... | @@ -137,8 +144,8 @@ const toolsMouseoutHandle = () => { |
137 | 144 | |
138 | 145 | // 编辑处理 |
139 | 146 | const editHandle = () => { |
140 | - window['$message'].warning('将开启失焦更新!') | |
141 | -// window['$message'].warning('将开启失焦更新与 5 秒同步更新!') | |
147 | + window['$message'].warning('请通过顶部【同步内容】按钮同步最新数据!') | |
148 | + chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CODE_EDIT, true) | |
142 | 149 | setTimeout(() => { |
143 | 150 | // 获取id路径 |
144 | 151 | const path = fetchPathByName(EditEnum.CHART_EDIT_NAME, 'href') |
... | ... | @@ -146,7 +153,7 @@ const editHandle = () => { |
146 | 153 | const id = fetchRouteParamsLocation() |
147 | 154 | updateToSession(id) |
148 | 155 | routerTurnByPath(path, [id], undefined, true) |
149 | - }, 1000) | |
156 | + }, 2000) | |
150 | 157 | } |
151 | 158 | |
152 | 159 | // 把内存中的数据同步到SessionStorage 便于传递给新窗口初始化数据 | ... | ... |
... | ... | @@ -57,7 +57,7 @@ import { onMounted, computed } from 'vue' |
57 | 57 | import { chartColors } from '@/settings/chartThemes/index' |
58 | 58 | import { MenuEnum } from '@/enums/editPageEnum' |
59 | 59 | import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' |
60 | -import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle } from '@/utils' | |
60 | +import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle, colorCustomMerge } from '@/utils' | |
61 | 61 | import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook' |
62 | 62 | import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d' |
63 | 63 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
... | ... | @@ -120,8 +120,8 @@ const themeSetting = computed(() => { |
120 | 120 | |
121 | 121 | // 配置项 |
122 | 122 | const themeColor = computed(() => { |
123 | - const chartThemeColor = chartEditStore.getEditCanvasConfig.chartThemeColor | |
124 | - return chartColors[chartThemeColor] | |
123 | + const colorCustomMergeData = colorCustomMerge(chartEditStore.getEditCanvasConfig.chartCustomThemeColorInfo) | |
124 | + return colorCustomMergeData[chartEditStore.getEditCanvasConfig.chartThemeColor] | |
125 | 125 | }) |
126 | 126 | |
127 | 127 | // 是否展示渲染 | ... | ... |
... | ... | @@ -120,6 +120,7 @@ const historyList = reactive<ItemType<HistoryStackEnum>[]>([ |
120 | 120 | } |
121 | 121 | ]) |
122 | 122 | |
123 | + | |
123 | 124 | // store 描述的是展示的值,所以和 ContentConfigurations 的 collapsed 是相反的 |
124 | 125 | const styleHandle = (item: ItemType<ChartLayoutStoreEnum>) => { |
125 | 126 | if (item.key === ChartLayoutStoreEnum.DETAILS) { | ... | ... |
1 | 1 | <template> |
2 | 2 | <n-space class="go-mt-0"> |
3 | - <n-button v-for="item in btnList" :key="item.title" ghost @click="item.event"> | |
3 | + <n-button v-for="item in comBtnList" :key="item.title" :type="item.type" ghost @click="item.event"> | |
4 | 4 | <template #icon> |
5 | 5 | <component :is="item.icon"></component> |
6 | 6 | </template> |
... | ... | @@ -10,16 +10,17 @@ |
10 | 10 | </template> |
11 | 11 | |
12 | 12 | <script setup lang="ts"> |
13 | -import { shallowReactive } from 'vue' | |
13 | +import { computed, shallowReactive } from 'vue' | |
14 | 14 | import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils' |
15 | 15 | import { PreviewEnum } from '@/enums/pageEnum' |
16 | 16 | import { StorageEnum } from '@/enums/storageEnum' |
17 | 17 | import { useRoute } from 'vue-router' |
18 | 18 | import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' |
19 | -import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d' | |
19 | +import { syncData } from '../../ContentEdit/components/EditTools/hooks/useSyncUpdate.hook' | |
20 | 20 | import { icon } from '@/plugins' |
21 | +import { cloneDeep } from 'lodash' | |
21 | 22 | |
22 | -const { BrowsersOutlineIcon, SendIcon } = icon.ionicons5 | |
23 | +const { BrowsersOutlineIcon, SendIcon, AnalyticsIcon } = icon.ionicons5 | |
23 | 24 | const chartEditStore = useChartEditStore() |
24 | 25 | |
25 | 26 | const routerParamsInfo = useRoute() |
... | ... | @@ -42,7 +43,8 @@ const previewHandle = () => { |
42 | 43 | setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo) |
43 | 44 | } else { |
44 | 45 | sessionStorageInfo.push({ |
45 | - id: previewId, ...storageInfo | |
46 | + id: previewId, | |
47 | + ...storageInfo | |
46 | 48 | }) |
47 | 49 | setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo) |
48 | 50 | } |
... | ... | @@ -66,6 +68,13 @@ const sendHandle = () => { |
66 | 68 | const btnList = shallowReactive([ |
67 | 69 | { |
68 | 70 | select: true, |
71 | + title: '同步内容', | |
72 | + type: 'primary', | |
73 | + icon: renderIcon(AnalyticsIcon), | |
74 | + event: syncData | |
75 | + }, | |
76 | + { | |
77 | + select: true, | |
69 | 78 | title: '预览', |
70 | 79 | icon: renderIcon(BrowsersOutlineIcon), |
71 | 80 | event: previewHandle |
... | ... | @@ -78,7 +87,16 @@ const btnList = shallowReactive([ |
78 | 87 | } |
79 | 88 | ]) |
80 | 89 | |
90 | +const comBtnList = computed(() => { | |
91 | + if (chartEditStore.getEditCanvas.isCodeEdit) { | |
92 | + return btnList | |
93 | + } | |
94 | + const cloneList = cloneDeep(btnList) | |
95 | + cloneList.shift() | |
96 | + return cloneList | |
97 | +}) | |
81 | 98 | </script> |
99 | + | |
82 | 100 | <style lang="scss" scoped> |
83 | 101 | .align-center { |
84 | 102 | margin-top: -4px; | ... | ... |
... | ... | @@ -5,15 +5,25 @@ |
5 | 5 | </n-icon> |
6 | 6 | <n-text @click="handleFocus"> |
7 | 7 | 工作空间 - |
8 | - <n-button v-show="!focus" secondary round size="tiny"> | |
8 | + <n-button v-show="!focus" secondary size="tiny"> | |
9 | 9 | <span class="title"> |
10 | 10 | {{ comTitle }} |
11 | 11 | </span> |
12 | 12 | </n-button> |
13 | 13 | </n-text> |
14 | 14 | |
15 | - <n-input v-show="focus" ref="inputInstRef" size="small" type="text" maxlength="16" show-count round | |
16 | - placeholder="请输入项目名称" v-model:value.trim="title" @keyup.enter="handleBlur" @blur="handleBlur"></n-input> | |
15 | + <n-input | |
16 | + v-show="focus" | |
17 | + ref="inputInstRef" | |
18 | + size="small" | |
19 | + type="text" | |
20 | + maxlength="16" | |
21 | + show-count | |
22 | + placeholder="请输入项目名称" | |
23 | + v-model:value.trim="title" | |
24 | + @keyup.enter="handleBlur" | |
25 | + @blur="handleBlur" | |
26 | + ></n-input> | |
17 | 27 | </n-space> |
18 | 28 | </template> |
19 | 29 | |
... | ... | @@ -63,6 +73,8 @@ const handleBlur = () => { |
63 | 73 | </script> |
64 | 74 | <style lang="scss" scoped> |
65 | 75 | .title { |
76 | + padding-left: 5px; | |
77 | + padding-right: 5px; | |
66 | 78 | font-size: 15px; |
67 | 79 | } |
68 | 80 | </style> | ... | ... |
... | ... | @@ -14,8 +14,17 @@ |
14 | 14 | </n-button> |
15 | 15 | </div> |
16 | 16 | <n-space> |
17 | - <n-tag :bordered="false" type="warning"> 「页面失焦保存」 </n-tag> | |
18 | - <n-tag :bordered="false" type="warning"> 「ctrl + s 保存」 </n-tag> | |
17 | + <!-- 暂时关闭 --> | |
18 | + <!-- <n-tag :bordered="false" type="warning"> 「页面失焦保存」 </n-tag> --> | |
19 | + <n-tag :bordered="false" type="warning"> 「Ctrl + S 更新视图」 </n-tag> | |
20 | + <n-button v-if="showOpenFilePicker" class="go-mr-3" size="medium" @click="updateSync"> | |
21 | + <template #icon> | |
22 | + <n-icon> | |
23 | + <analytics-icon></analytics-icon> | |
24 | + </n-icon> | |
25 | + </template> | |
26 | + 保存 | |
27 | + </n-button> | |
19 | 28 | </n-space> |
20 | 29 | </n-layout-header> |
21 | 30 | <n-layout-content> |
... | ... | @@ -26,28 +35,31 @@ |
26 | 35 | lineNumbers: 'on', |
27 | 36 | minimap: { enabled: true } |
28 | 37 | }" |
29 | - /> | |
38 | + /> | |
30 | 39 | </n-layout-content> |
31 | 40 | </n-layout> |
32 | 41 | </div> |
33 | 42 | </template> |
34 | 43 | |
35 | 44 | <script setup lang="ts"> |
36 | -import { computed, ref, watch } from 'vue' | |
45 | +import { ref } from 'vue' | |
37 | 46 | import { MonacoEditor } from '@/components/Pages/MonacoEditor' |
38 | 47 | import { SavePageEnum } from '@/enums/editPageEnum' |
39 | 48 | import { getSessionStorageInfo } from '../preview/utils' |
40 | -import type { ChartEditStorageType } from '../preview/index.d' | |
41 | -import { setSessionStorage, JSONStringify, JSONParse, setTitle } from '@/utils' | |
49 | +import { setSessionStorage, JSONStringify, JSONParse, setTitle, goDialog } from '@/utils' | |
42 | 50 | import { StorageEnum } from '@/enums/storageEnum' |
43 | 51 | import { icon } from '@/plugins' |
52 | +import type { ChartEditStorageType } from '../preview/index.d' | |
44 | 53 | |
45 | -const { ChevronBackOutlineIcon, DownloadIcon } = icon.ionicons5 | |
54 | +const { ChevronBackOutlineIcon, DownloadIcon, AnalyticsIcon } = icon.ionicons5 | |
46 | 55 | const showOpenFilePicker: Function = (window as any).showOpenFilePicker |
47 | 56 | const content = ref('') |
57 | + | |
58 | +window['$message'].warning('请不要刷新此窗口!') | |
59 | + | |
48 | 60 | // 从sessionStorage 获取数据 |
49 | 61 | async function getDataBySession() { |
50 | - const localStorageInfo: ChartEditStorageType = await getSessionStorageInfo() as unknown as ChartEditStorageType | |
62 | + const localStorageInfo: ChartEditStorageType = (await getSessionStorageInfo()) as unknown as ChartEditStorageType | |
51 | 63 | setTitle(`编辑-${localStorageInfo.editCanvasConfig.projectName}`) |
52 | 64 | content.value = JSONStringify(localStorageInfo) |
53 | 65 | } |
... | ... | @@ -60,44 +72,75 @@ function back() { |
60 | 72 | } |
61 | 73 | |
62 | 74 | // 导入json文本 |
63 | -async function importJSON() { | |
64 | - const files = await showOpenFilePicker() | |
65 | - const file = await files[0].getFile() | |
66 | - const fr = new FileReader() | |
67 | - fr.readAsText(file) | |
68 | - fr.onloadend = () => { | |
69 | - content.value = (fr.result || '').toString() | |
70 | - } | |
75 | +function importJSON() { | |
76 | + goDialog({ | |
77 | + message: '导入数据将覆盖内容,此操作不可撤回,是否继续?', | |
78 | + isMaskClosable: true, | |
79 | + transformOrigin: 'center', | |
80 | + onPositiveCallback: async () => { | |
81 | + try { | |
82 | + const files = await showOpenFilePicker() | |
83 | + const file = await files[0].getFile() | |
84 | + const fr = new FileReader() | |
85 | + fr.readAsText(file) | |
86 | + fr.onloadend = () => { | |
87 | + content.value = (fr.result || '').toString() | |
88 | + } | |
89 | + window['$message'].success('导入成功!') | |
90 | + } catch (error) { | |
91 | + window['$message'].error('导入失败,请检查文件是否损坏!') | |
92 | + console.log(error) | |
93 | + } | |
94 | + } | |
95 | + }) | |
71 | 96 | } |
72 | 97 | |
73 | -// 同步 [画布页失去焦点时同步数据到JSON页,JSON页Ctrl+S 时同步数据到画布页] | |
98 | +// 同步数据编辑页 | |
74 | 99 | window.opener.addEventListener(SavePageEnum.CHART, (e: any) => { |
100 | + window['$message'].success('正在进行更新...') | |
75 | 101 | setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [e.detail]) |
76 | 102 | content.value = JSONStringify(e.detail) |
77 | 103 | }) |
78 | 104 | |
79 | -// 窗口失焦 + 保存 => 同步数据 | |
105 | +// 保存按钮同步数据 | |
80 | 106 | document.addEventListener('keydown', function (e) { |
81 | 107 | if (e.keyCode == 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) { |
82 | 108 | e.preventDefault() |
83 | 109 | updateSync() |
84 | 110 | } |
85 | 111 | }) |
86 | -addEventListener('blur', updateSync) | |
112 | + | |
113 | +// 失焦保存(暂时关闭) | |
114 | +// addEventListener('blur', updateSync) | |
87 | 115 | |
88 | 116 | // 同步更新 |
89 | 117 | async function updateSync() { |
90 | 118 | if (!window.opener) { |
91 | - return window['$message'].error('源窗口已关闭,视图同步失败') | |
119 | + return window['$message'].error('源窗口已关闭,视图同步失败!') | |
92 | 120 | } |
93 | - try { | |
94 | - const detail = JSONParse(content.value) | |
95 | - delete detail.id | |
96 | - // 保持id不变 | |
97 | - window.opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail })) | |
98 | - } catch (e) { | |
99 | - window['$message'].error('内容格式有误') | |
100 | - console.log(e) | |
121 | + goDialog({ | |
122 | + message: '是否覆盖源视图内容? 此操作不可撤!', | |
123 | + isMaskClosable: true, | |
124 | + transformOrigin: 'center', | |
125 | + onPositiveCallback: () => { | |
126 | + try { | |
127 | + const detail = JSONParse(content.value) | |
128 | + delete detail.id | |
129 | + // 保持id不变 | |
130 | + window.opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail })) | |
131 | + window['$message'].success('正在同步内容...') | |
132 | + } catch (e) { | |
133 | + window['$message'].error('内容格式有误') | |
134 | + console.log(e) | |
135 | + } | |
136 | + } | |
137 | + }) | |
138 | +} | |
139 | + | |
140 | +// 关闭页面发送关闭事件 | |
141 | +window.onbeforeunload = () => { | |
142 | + if (window.opener) { | |
143 | + window.opener.dispatchEvent(new CustomEvent(SavePageEnum.CLOSE)) | |
101 | 144 | } |
102 | 145 | } |
103 | 146 | </script> | ... | ... |
... | ... | @@ -24,9 +24,18 @@ |
24 | 24 | </layout-header> |
25 | 25 | <div class="go-login"> |
26 | 26 | <div class="go-login-carousel"> |
27 | - <n-carousel autoplay dot-type="line" :interval="Number(carouselInterval)"> | |
28 | - <img v-for="(item, i) in carouselImgList" :key="i" class="go-login-carousel-img" | |
29 | - :src="getImageUrl(item, 'login')" alt="image" /> | |
27 | + <n-carousel | |
28 | + autoplay | |
29 | + dot-type="line" | |
30 | + :interval="Number(carouselInterval)" | |
31 | + > | |
32 | + <img | |
33 | + v-for="(item, i) in carouselImgList" | |
34 | + :key="i" | |
35 | + class="go-login-carousel-img" | |
36 | + :src="getImageUrl(item, 'login')" | |
37 | + alt="image" | |
38 | + /> | |
30 | 39 | </n-carousel> |
31 | 40 | </div> |
32 | 41 | <div class="login-account"> |
... | ... | @@ -34,11 +43,24 @@ |
34 | 43 | <n-collapse-transition :appear="true" :show="show"> |
35 | 44 | <n-card class="login-account-card" :title="$t('login.desc')"> |
36 | 45 | <div class="login-account-top"> |
37 | - <img class="login-account-top-logo" src="~@/assets/images/login/input.png" alt="展示图片" /> | |
46 | + <img | |
47 | + class="login-account-top-logo" | |
48 | + src="~@/assets/images/login/input.png" | |
49 | + alt="展示图片" | |
50 | + /> | |
38 | 51 | </div> |
39 | - <n-form ref="formRef" label-placement="left" size="large" :model="formInline" :rules="rules"> | |
52 | + <n-form | |
53 | + ref="formRef" | |
54 | + label-placement="left" | |
55 | + size="large" | |
56 | + :model="formInline" | |
57 | + :rules="rules" | |
58 | + > | |
40 | 59 | <n-form-item path="username"> |
41 | - <n-input v-model:value="formInline.username" :placeholder="$t('global.form_account')"> | |
60 | + <n-input | |
61 | + v-model:value="formInline.username" | |
62 | + :placeholder="$t('global.form_account')" | |
63 | + > | |
42 | 64 | <template #prefix> |
43 | 65 | <n-icon size="18"> |
44 | 66 | <PersonOutlineIcon></PersonOutlineIcon> |
... | ... | @@ -47,8 +69,12 @@ |
47 | 69 | </n-input> |
48 | 70 | </n-form-item> |
49 | 71 | <n-form-item path="password"> |
50 | - <n-input v-model:value="formInline.password" type="password" show-password-on="click" | |
51 | - :placeholder="$t('global.form_password')"> | |
72 | + <n-input | |
73 | + v-model:value="formInline.password" | |
74 | + type="password" | |
75 | + show-password-on="click" | |
76 | + :placeholder="$t('global.form_password')" | |
77 | + > | |
52 | 78 | <template #prefix> |
53 | 79 | <n-icon size="18"> |
54 | 80 | <LockClosedOutlineIcon></LockClosedOutlineIcon> |
... | ... | @@ -208,12 +234,10 @@ $carousel-image-height: 60vh; |
208 | 234 | * { |
209 | 235 | box-sizing: border-box; |
210 | 236 | } |
211 | - | |
212 | 237 | @include go(login-box) { |
213 | 238 | height: $go-login-height; |
214 | 239 | overflow: hidden; |
215 | 240 | @include background-image('background-image'); |
216 | - | |
217 | 241 | &-header { |
218 | 242 | display: flex; |
219 | 243 | justify-content: space-between; |
... | ... | @@ -221,7 +245,6 @@ $carousel-image-height: 60vh; |
221 | 245 | padding: 0 40px; |
222 | 246 | height: $--header-height; |
223 | 247 | } |
224 | - | |
225 | 248 | &-divider { |
226 | 249 | margin: 0; |
227 | 250 | padding-top: 0; | ... | ... |
... | ... | @@ -43,12 +43,14 @@ import { ChartEditStorageType } from '../../index.d' |
43 | 43 | import { PreviewRenderGroup } from '../PreviewRenderGroup/index' |
44 | 44 | import { CreateComponentGroupType } from '@/packages/index.d' |
45 | 45 | import { chartColors } from '@/settings/chartThemes/index' |
46 | -import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle } from '@/utils' | |
46 | +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
47 | +import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle, colorCustomMerge } from '@/utils' | |
47 | 48 | import { getSizeStyle, getComponentAttrStyle, getStatusStyle, getPreviewConfigStyle } from '../../utils' |
48 | 49 | import { useLifeHandler } from '@/hooks' |
49 | 50 | |
50 | 51 | // 初始化数据池 |
51 | 52 | const { initDataPond, clearMittDataPondMap } = useChartDataPondFetch() |
53 | +const chartEditStore = useChartEditStore() | |
52 | 54 | |
53 | 55 | const props = defineProps({ |
54 | 56 | localStorageInfo: { |
... | ... | @@ -63,10 +65,11 @@ const themeSetting = computed(() => { |
63 | 65 | return chartThemeSetting |
64 | 66 | }) |
65 | 67 | |
68 | + | |
66 | 69 | // 配置项 |
67 | 70 | const themeColor = computed(() => { |
68 | - const chartThemeColor = props.localStorageInfo.editCanvasConfig.chartThemeColor | |
69 | - return chartColors[chartThemeColor] | |
71 | + const colorCustomMergeData = colorCustomMerge(props.localStorageInfo.editCanvasConfig.chartCustomThemeColorInfo) | |
72 | + return colorCustomMergeData[props.localStorageInfo.editCanvasConfig.chartThemeColor] | |
70 | 73 | }) |
71 | 74 | |
72 | 75 | // 组件渲染结束初始化数据池 | ... | ... |
... | ... | @@ -26,7 +26,7 @@ |
26 | 26 | </div> |
27 | 27 | </template> |
28 | 28 | |
29 | -<script setup lang="ts" > | |
29 | +<script setup lang="ts"> | |
30 | 30 | import { computed } from 'vue' |
31 | 31 | import { PreviewRenderList } from './components/PreviewRenderList' |
32 | 32 | import { getFilterStyle, setTitle } from '@/utils' |
... | ... | @@ -68,19 +68,16 @@ const { show } = useComInstall(localStorageInfo) |
68 | 68 | height: 100vh; |
69 | 69 | width: 100vw; |
70 | 70 | @include background-image('background-image'); |
71 | - | |
72 | 71 | &.fit, |
73 | 72 | &.full { |
74 | 73 | display: flex; |
75 | 74 | align-items: center; |
76 | 75 | justify-content: center; |
77 | 76 | overflow: hidden; |
78 | - | |
79 | 77 | .go-preview-scale { |
80 | 78 | transform-origin: center center; |
81 | 79 | } |
82 | 80 | } |
83 | - | |
84 | 81 | &.scrollY { |
85 | 82 | overflow-x: hidden; |
86 | 83 | ... | ... |
... | ... | @@ -27,8 +27,8 @@ |
27 | 27 | </div> |
28 | 28 | <template #action> |
29 | 29 | <div class="go-flex-items-center list-footer" justify="space-between"> |
30 | - <n-text class="go-ellipsis-1" :title="cardData.name"> | |
31 | - {{ cardData.name || '' }} | |
30 | + <n-text class="go-ellipsis-1" :title="cardData.title"> | |
31 | + {{ cardData.title || '' }} | |
32 | 32 | </n-text> |
33 | 33 | <!-- 工具 --> |
34 | 34 | <div class="go-flex-items-center list-footer-ri"> |
... | ... | @@ -37,12 +37,12 @@ |
37 | 37 | <n-badge |
38 | 38 | class="go-animation-twinkle" |
39 | 39 | dot |
40 | - :color="cardData.state===0 ? '#34c749' : '#fcbc40'" | |
40 | + :color="cardData.release ? '#34c749' : '#fcbc40'" | |
41 | 41 | ></n-badge> |
42 | 42 | {{ |
43 | - cardData.state===0 | |
44 | - ?'未发布' | |
45 | - : '已发布' | |
43 | + cardData.release | |
44 | + ? $t('project.release') | |
45 | + : $t('project.unreleased') | |
46 | 46 | }} |
47 | 47 | </n-text> |
48 | 48 | ... | ... |