Commit 2c8eff3d62acd6f85f3313c954ad88f9438c39c3

Authored by xp.Huang
2 parents 4a33f5dd e9dd4d1c

Merge branch 'merge' into 'main'

update: 升级至V1.2.2 / V2.1.9(2023/03/04)版本

See merge request yunteng/thingskit-view!9
Showing 82 changed files with 2113 additions and 224 deletions
@@ -2,20 +2,20 @@ module.exports = { @@ -2,20 +2,20 @@ module.exports = {
2 root: true, 2 root: true,
3 parser: 'vue-eslint-parser', 3 parser: 'vue-eslint-parser',
4 globals: { 4 globals: {
5 - postMessage: true, 5 + postMessage: true
6 }, 6 },
7 parserOptions: { 7 parserOptions: {
8 parser: '@typescript-eslint/parser', 8 parser: '@typescript-eslint/parser',
9 sourceType: 'module', 9 sourceType: 'module',
10 ecmaFeatures: { 10 ecmaFeatures: {
11 jsx: true, 11 jsx: true,
12 - tsx: true,  
13 - }, 12 + tsx: true
  13 + }
14 }, 14 },
15 env: { 15 env: {
16 - 'node': true, 16 + node: true,
17 // The Follow config only works with eslint-plugin-vue v8.0.0+ 17 // The Follow config only works with eslint-plugin-vue v8.0.0+
18 - 'vue/setup-compiler-macros': true, 18 + 'vue/setup-compiler-macros': true
19 }, 19 },
20 extends: [ 20 extends: [
21 'plugin:vue/vue3-essential', 21 'plugin:vue/vue3-essential',
@@ -4,4 +4,3 @@ dist @@ -4,4 +4,3 @@ dist
4 dist-ssr 4 dist-ssr
5 *.local 5 *.local
6 .vscode 6 .vscode
7 -src/packages/components/Decorates/Mores/external/Icon/SvgBorder.vue  
  1 +#!/usr/bin/env sh
  2 +. "$(dirname -- "$0")/_/husky.sh"
  3 +
  4 +npx --no-install commitlint -e
  1 +version: '1.0'
  2 +name: branch-pipeline
  3 +displayName: BranchPipeline
  4 +stages:
  5 + - stage:
  6 + name: compile
  7 + displayName: 编译
  8 + steps:
  9 + - step: build@nodejs
  10 + name: build_nodejs
  11 + displayName: Nodejs 构建
  12 + # 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
  13 + nodeVersion: 14.16.0
  14 + # 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
  15 + commands:
  16 + - npm install && rm -rf ./dist && npm run build
  17 + # 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
  18 + artifacts:
  19 + # 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
  20 + - name: BUILD_ARTIFACT
  21 + # 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
  22 + path:
  23 + - ./dist
  24 + - step: publish@general_artifacts
  25 + name: publish_general_artifacts
  26 + displayName: 上传制品
  27 + # 上游构建任务定义的产物名,默认BUILD_ARTIFACT
  28 + dependArtifact: BUILD_ARTIFACT
  29 + # 上传到制品库时的制品命名,默认output
  30 + artifactName: output
  31 + dependsOn: build_nodejs
  32 + - stage:
  33 + name: release
  34 + displayName: 发布
  35 + steps:
  36 + - step: publish@release_artifacts
  37 + name: publish_release_artifacts
  38 + displayName: '发布'
  39 + # 上游上传制品任务的产出
  40 + dependArtifact: output
  41 + # 发布制品版本号
  42 + version: '1.0.0.0'
  43 + # 是否开启版本号自增,默认开启
  44 + autoIncrement: true
  45 +triggers:
  46 + push:
  47 + branches:
  48 + exclude:
  49 + - master
  50 + include:
  51 + - .*
  1 +version: '1.0'
  2 +name: master-pipeline
  3 +displayName: MasterPipeline
  4 +stages:
  5 + - stage:
  6 + name: compile
  7 + displayName: 编译
  8 + steps:
  9 + - step: build@nodejs
  10 + name: build_nodejs
  11 + displayName: Nodejs 构建
  12 + # 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
  13 + nodeVersion: 14.16.0
  14 + # 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
  15 + commands:
  16 + - npm install && rm -rf ./dist && npm run build
  17 + # 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
  18 + artifacts:
  19 + # 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
  20 + - name: BUILD_ARTIFACT
  21 + # 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
  22 + path:
  23 + - ./dist
  24 + - step: publish@general_artifacts
  25 + name: publish_general_artifacts
  26 + displayName: 上传制品
  27 + # 上游构建任务定义的产物名,默认BUILD_ARTIFACT
  28 + dependArtifact: BUILD_ARTIFACT
  29 + # 上传到制品库时的制品命名,默认output
  30 + artifactName: output
  31 + dependsOn: build_nodejs
  32 + - stage:
  33 + name: release
  34 + displayName: 发布
  35 + steps:
  36 + - step: publish@release_artifacts
  37 + name: publish_release_artifacts
  38 + displayName: '发布'
  39 + # 上游上传制品任务的产出
  40 + dependArtifact: output
  41 + # 发布制品版本号
  42 + version: '1.0.0.0'
  43 + # 是否开启版本号自增,默认开启
  44 + autoIncrement: true
  45 +triggers:
  46 + push:
  47 + branches:
  48 + include:
  49 + - master
  1 +version: '1.0'
  2 +name: pr-pipeline
  3 +displayName: PRPipeline
  4 +stages:
  5 + - stage:
  6 + name: compile
  7 + displayName: 编译
  8 + steps:
  9 + - step: build@nodejs
  10 + name: build_nodejs
  11 + displayName: Nodejs 构建
  12 + # 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
  13 + nodeVersion: 14.16.0
  14 + # 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
  15 + commands:
  16 + - npm install && rm -rf ./dist && npm run build
  17 + # 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
  18 + artifacts:
  19 + # 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
  20 + - name: BUILD_ARTIFACT
  21 + # 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
  22 + path:
  23 + - ./dist
  24 + - step: publish@general_artifacts
  25 + name: publish_general_artifacts
  26 + displayName: 上传制品
  27 + # 上游构建任务定义的产物名,默认BUILD_ARTIFACT
  28 + dependArtifact: BUILD_ARTIFACT
  29 + # 上传到制品库时的制品命名,默认output
  30 + artifactName: output
  31 + dependsOn: build_nodejs
  32 +triggers:
  33 + pr:
  34 + branches:
  35 + include:
  36 + - master
  1 +/**
  2 + * Get the configuration file variable name
  3 + * @param env
  4 + */
  5 +export const getConfigFileName = (env: Record<string, any>) => {
  6 + return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`
  7 + .toUpperCase()
  8 + .replace(/\s/g, '');
  9 +};
@@ -172,7 +172,9 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req @@ -172,7 +172,9 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
172 172
173 case RequestBodyEnum.JSON: 173 case RequestBodyEnum.JSON:
174 headers['Content-Type'] = ContentTypeEnum.JSON 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 // json 赋值给 data 178 // json 赋值给 data
177 break 179 break
178 180
1 <template> 1 <template>
2 - <n-dropdown trigger="hover" @select="handleSelect" :show-arrow="true" :options="options"> 2 + <n-dropdown
  3 + trigger="hover"
  4 + @select="handleSelect"
  5 + :show-arrow="true"
  6 + :options="options"
  7 + >
3 <div class="user-info-box"> 8 <div class="user-info-box">
4 <person-icon v-if="fallback"></person-icon> 9 <person-icon v-if="fallback"></person-icon>
5 - <n-avatar v-if="!fallback" round object-fit="cover" size="medium" :src="Person" @error="errorHandle"></n-avatar> 10 + <n-avatar
  11 + v-if="!fallback"
  12 + round
  13 + object-fit="cover"
  14 + size="medium"
  15 + :src="Person"
  16 + @error="errorHandle"
  17 + ></n-avatar>
6 </div> 18 </div>
7 </n-dropdown> 19 </n-dropdown>
8 20
@@ -25,6 +37,7 @@ import { icon } from '@/plugins' @@ -25,6 +37,7 @@ import { icon } from '@/plugins'
25 import { useUserStore } from '@/store/external/module/user' 37 import { useUserStore } from '@/store/external/module/user'
26 const { ChatboxEllipsesIcon, PersonIcon, LogOutOutlineIcon, SettingsSharpIcon } = icon.ionicons5 38 const { ChatboxEllipsesIcon, PersonIcon, LogOutOutlineIcon, SettingsSharpIcon } = icon.ionicons5
27 39
  40 +
28 const t = window['$t'] 41 const t = window['$t']
29 42
30 const modelShowInfo = ref(false) 43 const modelShowInfo = ref(false)
@@ -46,7 +59,11 @@ const renderUserInfo = () => { @@ -46,7 +59,11 @@ const renderUserInfo = () => {
46 style: 'margin-right: 12px;', 59 style: 'margin-right: 12px;',
47 src: Person 60 src: Person
48 }), 61 }),
  62 + h('div', null, [
  63 + h('div', null, [
49 h('div', null, [h('div', null, [h(NText, { depth: 2 }, { default: () => '奔跑的面条' })])]) 64 h('div', null, [h('div', null, [h(NText, { depth: 2 }, { default: () => '奔跑的面条' })])])
  65 + ])
  66 + ])
50 ] 67 ]
51 ) 68 )
52 } 69 }
@@ -12,7 +12,8 @@ export enum DragKeyEnum { @@ -12,7 +12,8 @@ export enum DragKeyEnum {
12 // 不同页面保存操作 12 // 不同页面保存操作
13 export enum SavePageEnum { 13 export enum SavePageEnum {
14 CHART = 'SaveChart', 14 CHART = 'SaveChart',
15 - JSON = 'SaveJSON' 15 + JSON = 'SaveJSON',
  16 + CLOSE = 'close'
16 } 17 }
17 18
18 // 操作枚举 19 // 操作枚举
@@ -28,4 +28,9 @@ export const excludeParseEventKeyList = [ @@ -28,4 +28,9 @@ export const excludeParseEventKeyList = [
28 BaseEvent.ON_MOUSE_LEAVE, 28 BaseEvent.ON_MOUSE_LEAVE,
29 //过滤器 29 //过滤器
30 'filter' 30 'filter'
31 -]  
  31 +]
  32 +// 内置字符串函数键值列表
  33 +export const excludeParseEventValueList = [
  34 + // 请求里的函数语句
  35 + 'javascript:'
  36 +]
@@ -29,6 +29,7 @@ export enum PageEnum { @@ -29,6 +29,7 @@ export enum PageEnum {
29 RELOAD = '/reload', 29 RELOAD = '/reload',
30 RELOAD_NAME = 'Reload', 30 RELOAD_NAME = 'Reload',
31 31
  32 +
32 // 首页 33 // 首页
33 BASE_HOME = '/project', 34 BASE_HOME = '/project',
34 BASE_HOME_NAME = 'Project', 35 BASE_HOME_NAME = 'Project',
1 <template> 1 <template>
2 <n-layout-header bordered class="go-header"> 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 <div class="header-item left"> 4 <div class="header-item left">
5 <n-space> 5 <n-space>
6 <slot name="left"></slot> 6 <slot name="left"></slot>
@@ -23,17 +23,29 @@ @@ -23,17 +23,29 @@
23 </template> 23 </template>
24 24
25 <script setup lang="ts"> 25 <script setup lang="ts">
  26 +import { computed } from 'vue'
  27 +import { useRoute } from 'vue-router'
26 import { GoThemeSelect } from '@/components/GoThemeSelect' 28 import { GoThemeSelect } from '@/components/GoThemeSelect'
27 import { GoLangSelect } from '@/components/GoLangSelect' 29 import { GoLangSelect } from '@/components/GoLangSelect'
28 import { ThemeColorSelect } from '@/components/Pages/ThemeColorSelect' 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 </script> 38 </script>
30 39
31 <style lang="scss" scoped> 40 <style lang="scss" scoped>
32 -$min-width: 400px; 41 +$min-width: 520px;
33 @include go(header) { 42 @include go(header) {
34 &-box { 43 &-box {
35 display: grid; 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 .header-item { 49 .header-item {
38 display: flex; 50 display: flex;
39 align-items: center; 51 align-items: center;
@@ -49,7 +61,7 @@ $min-width: 400px; @@ -49,7 +61,7 @@ $min-width: 400px;
49 } 61 }
50 } 62 }
51 height: $--header-height; 63 height: $--header-height;
52 - padding: 0 60px; 64 + padding: 0 20px 0 60px;
53 } 65 }
54 } 66 }
55 </style> 67 </style>
1 import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public' 1 import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
2 import { LineCommonConfig } from './index' 2 import { LineCommonConfig } from './index'
3 import { CreateComponentType } from '@/packages/index.d' 3 import { CreateComponentType } from '@/packages/index.d'
4 -import { defaultTheme, chartColorsSearch } from '@/settings/chartThemes/index'  
5 import cloneDeep from 'lodash/cloneDeep' 4 import cloneDeep from 'lodash/cloneDeep'
6 import dataJson from './data.json' 5 import dataJson from './data.json'
7 6
@@ -15,7 +15,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore @@ -15,7 +15,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
15 import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index' 15 import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index'
16 import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components' 16 import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
17 import { useChartDataFetch } from '@/hooks' 17 import { useChartDataFetch } from '@/hooks'
18 -import { isPreview } from '@/utils' 18 +import { isPreview, colorGradientCustomMerge} from '@/utils'
19 19
20 const props = defineProps({ 20 const props = defineProps({
21 themeSetting: { 21 themeSetting: {
@@ -45,7 +45,9 @@ watch( @@ -45,7 +45,9 @@ watch(
45 (newColor: keyof typeof chartColorsSearch) => { 45 (newColor: keyof typeof chartColorsSearch) => {
46 try { 46 try {
47 if (!isPreview()) { 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 props.chartConfig.option.series.forEach((value: any, index: number) => { 51 props.chartConfig.option.series.forEach((value: any, index: number) => {
50 value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [ 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,7 +14,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
14 import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index' 14 import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index'
15 import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components' 15 import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
16 import { useChartDataFetch } from '@/hooks' 16 import { useChartDataFetch } from '@/hooks'
17 -import { isPreview } from '@/utils' 17 +import { isPreview, colorGradientCustomMerge} from '@/utils'
18 18
19 const props = defineProps({ 19 const props = defineProps({
20 themeSetting: { 20 themeSetting: {
@@ -44,7 +44,9 @@ watch( @@ -44,7 +44,9 @@ watch(
44 (newColor: keyof typeof chartColorsSearch) => { 44 (newColor: keyof typeof chartColorsSearch) => {
45 try { 45 try {
46 if (!isPreview()) { 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 props.chartConfig.option.series.forEach((value: any, index: number) => { 50 props.chartConfig.option.series.forEach((value: any, index: number) => {
49 value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [ 51 value.areaStyle.color = new graphic.LinearGradient(0, 0, 0, 1, [
50 { 52 {
@@ -15,7 +15,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore @@ -15,7 +15,7 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
15 import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index' 15 import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index'
16 import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components' 16 import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
17 import { useChartDataFetch } from '@/hooks' 17 import { useChartDataFetch } from '@/hooks'
18 -import { isPreview } from '@/utils' 18 +import { isPreview, colorGradientCustomMerge } from '@/utils'
19 19
20 const props = defineProps({ 20 const props = defineProps({
21 themeSetting: { 21 themeSetting: {
@@ -45,7 +45,9 @@ watch( @@ -45,7 +45,9 @@ watch(
45 (newColor: keyof typeof chartColorsSearch) => { 45 (newColor: keyof typeof chartColorsSearch) => {
46 try { 46 try {
47 if (!isPreview()) { 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 props.chartConfig.option.series.forEach((value: any) => { 51 props.chartConfig.option.series.forEach((value: any) => {
50 value.lineStyle.shadowColor = themeColor[2] 52 value.lineStyle.shadowColor = themeColor[2]
51 value.lineStyle.color.colorStops.forEach((v: { color: string }, i: number) => { 53 value.lineStyle.color.colorStops.forEach((v: { color: string }, i: number) => {
@@ -59,13 +59,14 @@ const getGeojson = (regionId: string) => { @@ -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 // 进行更换初始化地图 如果为china 单独处理 64 // 进行更换初始化地图 如果为china 单独处理
65 const registerMapInitAsync = async () => { 65 const registerMapInitAsync = async () => {
66 await nextTick() 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 } else { 70 } else {
70 await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands) 71 await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands)
71 } 72 }
@@ -127,7 +128,7 @@ watch( @@ -127,7 +128,7 @@ watch(
127 128
128 //监听地图展示区域发生变化 129 //监听地图展示区域发生变化
129 watch( 130 watch(
130 - () => props.chartConfig.option.mapRegion.adcode, 131 + () => `${props.chartConfig.option.mapRegion.adcode}`,
131 async newData => { 132 async newData => {
132 try { 133 try {
133 await getGeojson(newData) 134 await getGeojson(newData)
@@ -10,7 +10,7 @@ import 'echarts-liquidfill/src/liquidFill.js' @@ -10,7 +10,7 @@ import 'echarts-liquidfill/src/liquidFill.js'
10 import { CanvasRenderer } from 'echarts/renderers' 10 import { CanvasRenderer } from 'echarts/renderers'
11 import { GridComponent } from 'echarts/components' 11 import { GridComponent } from 'echarts/components'
12 import config from './config' 12 import config from './config'
13 -import { isPreview, isString, isNumber } from '@/utils' 13 +import { isPreview, isString, isNumber, colorGradientCustomMerge } from '@/utils'
14 import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index' 14 import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index'
15 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 15 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
16 import { useChartDataFetch } from '@/hooks' 16 import { useChartDataFetch } from '@/hooks'
@@ -44,7 +44,9 @@ watch( @@ -44,7 +44,9 @@ watch(
44 (newColor: keyof typeof chartColorsSearch) => { 44 (newColor: keyof typeof chartColorsSearch) => {
45 try { 45 try {
46 if (!isPreview()) { 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 props.chartConfig.option.series[0].backgroundStyle.color = themeColor[2] 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>
  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 import { ImageConfig } from './Image/index' 1 import { ImageConfig } from './Image/index'
  2 +import { ImageCarouselConfig } from './ImageCarousel/index'
2 import { IframeConfig } from './Iframe/index' 3 import { IframeConfig } from './Iframe/index'
3 import { VideoConfig } from './Video/index' 4 import { VideoConfig } from './Video/index'
4 import { WordCloudConfig } from './WordCloud/index' 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,7 +149,7 @@ export enum PackagesCategoryEnum {
149 CHARTS = 'Charts', 149 CHARTS = 'Charts',
150 TABLES = 'Tables', 150 TABLES = 'Tables',
151 INFORMATIONS = 'Informations', 151 INFORMATIONS = 'Informations',
152 - DECORATES = 'Decorates', 152 + DECORATES = 'Decorates'
153 } 153 }
154 154
155 // 包分类名称 155 // 包分类名称
@@ -157,7 +157,7 @@ export enum PackagesCategoryName { @@ -157,7 +157,7 @@ export enum PackagesCategoryName {
157 CHARTS = '图表', 157 CHARTS = '图表',
158 TABLES = '列表', 158 TABLES = '列表',
159 INFORMATIONS = '信息', 159 INFORMATIONS = '信息',
160 - DECORATES = '小组件', 160 + DECORATES = '小组件'
161 } 161 }
162 162
163 // 获取组件 163 // 获取组件
1 import { 1 import {
  2 + Add as AddIcon,
2 Close as CloseIcon, 3 Close as CloseIcon,
3 Remove as RemoveIcon, 4 Remove as RemoveIcon,
4 Resize as ResizeIcon, 5 Resize as ResizeIcon,
@@ -52,6 +53,7 @@ import { @@ -52,6 +53,7 @@ import {
52 ColorWand as ColorWandIcon, 53 ColorWand as ColorWandIcon,
53 ArrowBack as ArrowBackIcon, 54 ArrowBack as ArrowBackIcon,
54 ArrowForward as ArrowForwardIcon, 55 ArrowForward as ArrowForwardIcon,
  56 + ArrowDown as ArrowDownIcon,
55 Planet as PawIcon, 57 Planet as PawIcon,
56 Search as SearchIcon, 58 Search as SearchIcon,
57 ChevronUpOutline as ChevronUpOutlineIcon, 59 ChevronUpOutline as ChevronUpOutlineIcon,
@@ -64,7 +66,9 @@ import { @@ -64,7 +66,9 @@ import {
64 List as ListIcon, 66 List as ListIcon,
65 EyeOutline as EyeOutlineIcon, 67 EyeOutline as EyeOutlineIcon,
66 EyeOffOutline as EyeOffOutlineIcon, 68 EyeOffOutline as EyeOffOutlineIcon,
67 - Albums as AlbumsIcon 69 + Albums as AlbumsIcon,
  70 + Analytics as AnalyticsIcon,
  71 + SaveOutline as SaveIcon
68 } from '@vicons/ionicons5' 72 } from '@vicons/ionicons5'
69 73
70 import { 74 import {
@@ -97,12 +101,12 @@ import { @@ -97,12 +101,12 @@ import {
97 Carbon3DSoftware as Carbon3DSoftwareIcon, 101 Carbon3DSoftware as Carbon3DSoftwareIcon,
98 Filter as FilterIcon, 102 Filter as FilterIcon,
99 FilterEdit as FilterEditIcon, 103 FilterEdit as FilterEditIcon,
100 - Laptop as LaptopIcon,  
101 - // THINGS_KIT  
102 - Save as SaveIcon 104 + Laptop as LaptopIcon
103 } from '@vicons/carbon' 105 } from '@vicons/carbon'
104 106
105 const ionicons5 = { 107 const ionicons5 = {
  108 + // 新增
  109 + AddIcon,
106 // 帮助(问号) 110 // 帮助(问号)
107 HelpOutlineIcon, 111 HelpOutlineIcon,
108 // 添加 112 // 添加
@@ -208,6 +212,8 @@ const ionicons5 = { @@ -208,6 +212,8 @@ const ionicons5 = {
208 ArrowBackIcon, 212 ArrowBackIcon,
209 // 前进 213 // 前进
210 ArrowForwardIcon, 214 ArrowForwardIcon,
  215 + // 向下
  216 + ArrowDownIcon,
211 // 狗爪 217 // 狗爪
212 PawIcon, 218 PawIcon,
213 // 搜索(放大镜) 219 // 搜索(放大镜)
@@ -233,8 +239,10 @@ const ionicons5 = { @@ -233,8 +239,10 @@ const ionicons5 = {
233 // 眼睛 239 // 眼睛
234 EyeOutlineIcon, 240 EyeOutlineIcon,
235 EyeOffOutlineIcon, 241 EyeOffOutlineIcon,
236 - // 图表列表  
237 - AlbumsIcon 242 + // 图表列表
  243 + AlbumsIcon,
  244 + // 分析
  245 + AnalyticsIcon
238 } 246 }
239 247
240 const carbon = { 248 const carbon = {
@@ -57,6 +57,7 @@ import { @@ -57,6 +57,7 @@ import {
57 NProgress, 57 NProgress,
58 NDatePicker, 58 NDatePicker,
59 NGrid, 59 NGrid,
  60 + NGi,
60 NGridItem, 61 NGridItem,
61 NList, 62 NList,
62 NListItem, 63 NListItem,
@@ -160,6 +161,7 @@ const naive = create({ @@ -160,6 +161,7 @@ const naive = create({
160 NProgress, 161 NProgress,
161 NDatePicker, 162 NDatePicker,
162 NGrid, 163 NGrid,
  164 + NGi,
163 NGridItem, 165 NGridItem,
164 NList, 166 NList,
165 NListItem, 167 NListItem,
@@ -31,38 +31,20 @@ export const chartColors = { @@ -31,38 +31,20 @@ export const chartColors = {
31 // 默认主题 31 // 默认主题
32 export const defaultTheme = 'dark' 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 // 渐变主题色列表(主色1、主色2、阴影、渐变1、渐变2) 48 // 渐变主题色列表(主色1、主色2、阴影、渐变1、渐变2)
67 export const chartColorsSearch = { 49 export const chartColorsSearch = {
68 dark: ['#4992ff', '#7cffb2', 'rgba(68, 181, 226, 0.3)', 'rgba(73, 146, 255, 0.5)', 'rgba(124, 255, 178, 0.5)'], 50 dark: ['#4992ff', '#7cffb2', 'rgba(68, 181, 226, 0.3)', 'rgba(73, 146, 255, 0.5)', 'rgba(124, 255, 178, 0.5)'],
@@ -8,5 +8,6 @@ @@ -8,5 +8,6 @@
8 "#d4a4eb", 8 "#d4a4eb",
9 "#d2f5a6", 9 "#d2f5a6",
10 "#76f2f2" 10 "#76f2f2"
11 - ] 11 + ],
  12 + "name": "粉青"
12 } 13 }
@@ -9,5 +9,6 @@ @@ -9,5 +9,6 @@
9 "#fc8452", 9 "#fc8452",
10 "#9a60b4", 10 "#9a60b4",
11 "#ea7ccc" 11 "#ea7ccc"
12 - ] 12 + ],
  13 + "name": "暗淡"
13 } 14 }
@@ -9,5 +9,6 @@ @@ -9,5 +9,6 @@
9 "#ff8a45", 9 "#ff8a45",
10 "#8d48e3", 10 "#8d48e3",
11 "#dd79ff" 11 "#dd79ff"
12 - ] 12 + ],
  13 + "name": "明亮"
13 } 14 }
@@ -6,5 +6,6 @@ @@ -6,5 +6,6 @@
6 "#ffb248", 6 "#ffb248",
7 "#f2d643", 7 "#f2d643",
8 "#ebdba4" 8 "#ebdba4"
9 - ] 9 + ],
  10 + "name": "橘红"
10 } 11 }
@@ -20,5 +20,6 @@ @@ -20,5 +20,6 @@
20 "#7eb00a", 20 "#7eb00a",
21 "#6f5553", 21 "#6f5553",
22 "#c14089" 22 "#c14089"
23 - ] 23 + ],
  24 + "name": "马卡龙"
24 } 25 }
@@ -6,5 +6,6 @@ @@ -6,5 +6,6 @@
6 "#71669e", 6 "#71669e",
7 "#cc70af", 7 "#cc70af",
8 "#7cb4cc" 8 "#7cb4cc"
9 - ] 9 + ],
  10 + "name": "深紫"
10 } 11 }
@@ -20,5 +20,6 @@ @@ -20,5 +20,6 @@
20 "#3cb371", 20 "#3cb371",
21 "#d5b158", 21 "#d5b158",
22 "#38b6b6" 22 "#38b6b6"
23 - ] 23 + ],
  24 + "name": "罗马红"
24 } 25 }
@@ -8,5 +8,6 @@ @@ -8,5 +8,6 @@
8 "#339ca8", 8 "#339ca8",
9 "#cda819", 9 "#cda819",
10 "#32a487" 10 "#32a487"
11 - ] 11 + ],
  12 + "name": "深色"
12 } 13 }
@@ -10,5 +10,6 @@ @@ -10,5 +10,6 @@
10 "#cc7e63", 10 "#cc7e63",
11 "#724e58", 11 "#724e58",
12 "#4b565b" 12 "#4b565b"
13 - ]  
14 -}  
  13 + ],
  14 + "name": "复古"
  15 +}
@@ -6,5 +6,6 @@ @@ -6,5 +6,6 @@
6 "#a0a7e6", 6 "#a0a7e6",
7 "#c4ebad", 7 "#c4ebad",
8 "#96dee8" 8 "#96dee8"
9 - ]  
10 -}  
  9 + ],
  10 + "name": "蓝绿"
  11 +}
@@ -6,5 +6,6 @@ @@ -6,5 +6,6 @@
6 "#93b7e3", 6 "#93b7e3",
7 "#a5e7f0", 7 "#a5e7f0",
8 "#cbb0e3" 8 "#cbb0e3"
9 - ]  
10 -}  
  9 + ],
  10 + "name": "灰粉"
  11 +}
@@ -6,5 +6,6 @@ @@ -6,5 +6,6 @@
6 "#d0648a", 6 "#d0648a",
7 "#f58db2", 7 "#f58db2",
8 "#f2b3c9" 8 "#f2b3c9"
9 - ] 9 + ],
  10 + "name": "青草"
10 } 11 }
@@ -10,7 +10,7 @@ import { @@ -10,7 +10,7 @@ import {
10 RequestParamsObjType 10 RequestParamsObjType
11 } from '@/enums/httpEnum' 11 } from '@/enums/httpEnum'
12 import { PreviewScaleEnum } from '@/enums/styleEnum' 12 import { PreviewScaleEnum } from '@/enums/styleEnum'
13 -import type { ChartColorsNameType, GlobalThemeJsonType } from '@/settings/chartThemes/index' 13 +import type { ChartColorsNameType, CustomColorsType, GlobalThemeJsonType } from '@/settings/chartThemes/index'
14 14
15 // 编辑画布属性 15 // 编辑画布属性
16 export enum EditCanvasTypeEnum { 16 export enum EditCanvasTypeEnum {
@@ -22,7 +22,8 @@ export enum EditCanvasTypeEnum { @@ -22,7 +22,8 @@ export enum EditCanvasTypeEnum {
22 LOCK_SCALE = 'lockScale', 22 LOCK_SCALE = 'lockScale',
23 IS_CREATE = 'isCreate', 23 IS_CREATE = 'isCreate',
24 IS_DRAG = 'isDrag', 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,6 +45,8 @@ export type EditCanvasType = {
44 [EditCanvasTypeEnum.IS_DRAG]: boolean 45 [EditCanvasTypeEnum.IS_DRAG]: boolean
45 // 框选中 46 // 框选中
46 [EditCanvasTypeEnum.IS_SELECT]: boolean 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,6 +55,7 @@ export enum EditCanvasConfigEnum {
52 WIDTH = 'width', 55 WIDTH = 'width',
53 HEIGHT = 'height', 56 HEIGHT = 'height',
54 CHART_THEME_COLOR = 'chartThemeColor', 57 CHART_THEME_COLOR = 'chartThemeColor',
  58 + CHART_CUSTOM_THEME_COLOR_INFO = 'chartCustomThemeColorInfo',
55 CHART_THEME_SETTING = 'chartThemeSetting', 59 CHART_THEME_SETTING = 'chartThemeSetting',
56 BACKGROUND = 'background', 60 BACKGROUND = 'background',
57 BACKGROUND_IMAGE = 'backgroundImage', 61 BACKGROUND_IMAGE = 'backgroundImage',
@@ -87,9 +91,12 @@ export interface EditCanvasConfigType { @@ -87,9 +91,12 @@ export interface EditCanvasConfigType {
87 [EditCanvasConfigEnum.HEIGHT]: number 91 [EditCanvasConfigEnum.HEIGHT]: number
88 // 背景色 92 // 背景色
89 [EditCanvasConfigEnum.BACKGROUND]?: string 93 [EditCanvasConfigEnum.BACKGROUND]?: string
  94 + // 背景图片
90 [EditCanvasConfigEnum.BACKGROUND_IMAGE]?: string | null 95 [EditCanvasConfigEnum.BACKGROUND_IMAGE]?: string | null
91 // 图表主题颜色 96 // 图表主题颜色
92 [EditCanvasConfigEnum.CHART_THEME_COLOR]: ChartColorsNameType 97 [EditCanvasConfigEnum.CHART_THEME_COLOR]: ChartColorsNameType
  98 + // 自定义图表主题颜色
  99 + [EditCanvasConfigEnum.CHART_CUSTOM_THEME_COLOR_INFO]?: CustomColorsType[]
93 // 图表全局配置 100 // 图表全局配置
94 [EditCanvasConfigEnum.CHART_THEME_SETTING]: GlobalThemeJsonType 101 [EditCanvasConfigEnum.CHART_THEME_SETTING]: GlobalThemeJsonType
95 // 图表主题颜色 102 // 图表主题颜色
@@ -54,7 +54,9 @@ export const useChartEditStore = defineStore({ @@ -54,7 +54,9 @@ export const useChartEditStore = defineStore({
54 // 拖拽中 54 // 拖拽中
55 isDrag: false, 55 isDrag: false,
56 // 框选中 56 // 框选中
57 - isSelect: false 57 + isSelect: false,
  58 + // 代码编辑中
  59 + isCodeEdit: false
58 }, 60 },
59 // 右键菜单 61 // 右键菜单
60 rightMenuShow: false, 62 rightMenuShow: false,
@@ -108,6 +110,8 @@ export const useChartEditStore = defineStore({ @@ -108,6 +110,8 @@ export const useChartEditStore = defineStore({
108 selectColor: true, 110 selectColor: true,
109 // chart 主题色 111 // chart 主题色
110 chartThemeColor: defaultTheme || 'dark', 112 chartThemeColor: defaultTheme || 'dark',
  113 + // 自定义颜色列表
  114 + chartCustomThemeColorInfo: undefined,
111 // 全局配置 115 // 全局配置
112 chartThemeSetting: globalThemeJson, 116 chartThemeSetting: globalThemeJson,
113 // 适配方式 117 // 适配方式
@@ -185,7 +189,7 @@ export const useChartEditStore = defineStore({ @@ -185,7 +189,7 @@ export const useChartEditStore = defineStore({
185 this.targetChart.hoverId = hoverId 189 this.targetChart.hoverId = hoverId
186 }, 190 },
187 // * 设置目标数据 select 191 // * 设置目标数据 select
188 - setTargetSelectChart(selectId?: string | string[], push = false) { 192 + setTargetSelectChart(selectId?: string | string[], push: boolean = false) {
189 // 重复选中 193 // 重复选中
190 if (this.targetChart.selectId.find((e: string) => e === selectId)) return 194 if (this.targetChart.selectId.find((e: string) => e === selectId)) return
191 195
@@ -538,7 +542,7 @@ export const useChartEditStore = defineStore({ @@ -538,7 +542,7 @@ export const useChartEditStore = defineStore({
538 this.setTargetSelectChart() 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 if (isArray(historyData)) { 546 if (isArray(historyData)) {
543 // 选中目标元素,支持多个 547 // 选中目标元素,支持多个
544 historyData.forEach((item: CreateComponentType | CreateComponentGroupType) => { 548 historyData.forEach((item: CreateComponentType | CreateComponentGroupType) => {
@@ -835,7 +839,7 @@ export const useChartEditStore = defineStore({ @@ -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 try { 843 try {
840 // 暂不支持多选 844 // 暂不支持多选
841 if (this.getTargetChart.selectId.length > 1) return 845 if (this.getTargetChart.selectId.length > 1) return
@@ -864,11 +868,11 @@ export const useChartEditStore = defineStore({ @@ -864,11 +868,11 @@ export const useChartEditStore = defineStore({
864 } 868 }
865 }, 869 },
866 // * 解除锁定 870 // * 解除锁定
867 - setUnLock(isHistory = true) { 871 + setUnLock(isHistory: boolean = true) {
868 this.setLock(false, isHistory) 872 this.setLock(false, isHistory)
869 }, 873 },
870 // * 隐藏 874 // * 隐藏
871 - setHide(status = true, isHistory = true) { 875 + setHide(status: boolean = true, isHistory: boolean = true) {
872 try { 876 try {
873 // 暂不支持多选 877 // 暂不支持多选
874 if (this.getTargetChart.selectId.length > 1) return 878 if (this.getTargetChart.selectId.length > 1) return
@@ -897,7 +901,7 @@ export const useChartEditStore = defineStore({ @@ -897,7 +901,7 @@ export const useChartEditStore = defineStore({
897 } 901 }
898 }, 902 },
899 // * 显示 903 // * 显示
900 - setShow(isHistory = true) { 904 + setShow(isHistory: boolean = true) {
901 this.setHide(false, isHistory) 905 this.setHide(false, isHistory)
902 }, 906 },
903 // ---------------- 907 // ----------------
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 } 17 }
18 18
19 @mixin deep() { 19 @mixin deep() {
20 - :deep(*) { 20 + :deep() {
21 @content; 21 @content;
22 } 22 }
23 } 23 }
@@ -4,8 +4,8 @@ import { AsyncLoading, AsyncSkeletonLoading } from '@/components/GoLoading' @@ -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 window['$vue'].component(key, node) 9 window['$vue'].component(key, node)
10 } 10 }
11 } 11 }
@@ -21,7 +21,7 @@ export const loadAsyncComponent = (loader: AsyncComponentLoader<any>) => @@ -21,7 +21,7 @@ export const loadAsyncComponent = (loader: AsyncComponentLoader<any>) =>
21 loadingComponent: AsyncLoading, 21 loadingComponent: AsyncLoading,
22 delay: 20, 22 delay: 20,
23 }) 23 })
24 - 24 +
25 export const loadSkeletonAsyncComponent = (loader: AsyncComponentLoader<any>) => 25 export const loadSkeletonAsyncComponent = (loader: AsyncComponentLoader<any>) =>
26 defineAsyncComponent({ 26 defineAsyncComponent({
27 loader, 27 loader,
@@ -2,6 +2,7 @@ import Color from 'color' @@ -2,6 +2,7 @@ import Color from 'color'
2 import { useDesignStore } from '@/store/modules/designStore/designStore' 2 import { useDesignStore } from '@/store/modules/designStore/designStore'
3 import { PickCreateComponentType } from '@/packages/index.d' 3 import { PickCreateComponentType } from '@/packages/index.d'
4 import { EditCanvasConfigType } from '@/store/modules/chartEditStore/chartEditStore.d' 4 import { EditCanvasConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
  5 +import { chartColors, chartColorsSearch, CustomColorsType } from '@/settings/chartThemes/index'
5 6
6 type AttrType = PickCreateComponentType<'attr'> 7 type AttrType = PickCreateComponentType<'attr'>
7 type StylesType = PickCreateComponentType<'styles'> 8 type StylesType = PickCreateComponentType<'styles'>
@@ -87,6 +88,21 @@ export function darken(color: string, concentration: number) { @@ -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 * @param themeName 主题名称 107 * @param themeName 主题名称
92 * @returns 108 * @returns
@@ -100,3 +116,48 @@ export const setHtmlTheme = (themeName?: string) => { @@ -100,3 +116,48 @@ export const setHtmlTheme = (themeName?: string) => {
100 const designStore = useDesignStore() 116 const designStore = useDesignStore()
101 e.setAttribute('data-theme', designStore.themeName) 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,7 +10,7 @@ import cloneDeep from 'lodash/cloneDeep'
10 import { WinKeyboard } from '@/enums/editPageEnum' 10 import { WinKeyboard } from '@/enums/editPageEnum'
11 import { RequestHttpIntervalEnum, RequestParamsObjType } from '@/enums/httpEnum' 11 import { RequestHttpIntervalEnum, RequestParamsObjType } from '@/enums/httpEnum'
12 import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' 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,10 +320,17 @@ export const JSONStringify = <T>(data: T) => {
320 */ 320 */
321 export const JSONParse = (data: string) => { 321 export const JSONParse = (data: string) => {
322 return JSON.parse(data, (k, v) => { 322 return JSON.parse(data, (k, v) => {
  323 + // 过滤函数字符串
323 if (excludeParseEventKeyList.includes(k)) return v 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 if (typeof v === 'string' && v.indexOf && (v.indexOf('function') > -1 || v.indexOf('=>') > -1)) { 331 if (typeof v === 'string' && v.indexOf && (v.indexOf('function') > -1 || v.indexOf('=>') > -1)) {
325 return eval(`(function(){return ${v}})()`) 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 const baseLeftIndex = v.indexOf('(') 334 const baseLeftIndex = v.indexOf('(')
328 if (baseLeftIndex > -1) { 335 if (baseLeftIndex > -1) {
329 const newFn = `function ${v.substring(baseLeftIndex)}` 336 const newFn = `function ${v.substring(baseLeftIndex)}`
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 class="go-content-charts-item-box" 5 class="go-content-charts-item-box"
6 :class="[chartMode === ChartModeEnum.DOUBLE ? 'double' : 'single']" 6 :class="[chartMode === ChartModeEnum.DOUBLE ? 'double' : 'single']"
7 > 7 >
8 - <!-- 每一项组件的渲染 --> 8 + <!-- 每一项组件的渲染 -->
9 <div 9 <div
10 class="item-box" 10 class="item-box"
11 v-for="(item, index) in menuOptions" 11 v-for="(item, index) in menuOptions"
@@ -5,7 +5,6 @@ @@ -5,7 +5,6 @@
5 v-show="hidePackageOneCategory" 5 v-show="hidePackageOneCategory"
6 class="chart-menu-width" 6 class="chart-menu-width"
7 v-model:value="selectValue" 7 v-model:value="selectValue"
8 - style="width: 80px"  
9 :options="packages.menuOptions" 8 :options="packages.menuOptions"
10 :icon-size="16" 9 :icon-size="16"
11 :indent="18" 10 :indent="18"
1 <template> 1 <template>
2 <div class="go-chart-theme-color"> 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 <n-card 12 <n-card
4 - v-for="(value, key) in chartColors" 13 + v-for="(value, key) in comChartColors"
5 :key="key" 14 :key="key"
6 class="card-box" 15 class="card-box"
7 :class="{ selected: key === selectName }" 16 :class="{ selected: key === selectName }"
@@ -11,41 +20,51 @@ @@ -11,41 +20,51 @@
11 @click="selectTheme(key)" 20 @click="selectTheme(key)"
12 > 21 >
13 <div class="go-flex-items-center"> 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 <span 24 <span
16 class="theme-color-item" 25 class="theme-color-item"
17 v-for="colorItem in fetchShowColors(value.color)" 26 v-for="colorItem in fetchShowColors(value.color)"
18 :key="colorItem" 27 :key="colorItem"
19 :style="{ backgroundColor: colorItem }" 28 :style="{ backgroundColor: colorItem }"
20 - ></span> 29 + ></span>
21 </div> 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 </n-card> 32 </n-card>
  33 + <!-- 自定义颜色 modal -->
  34 + <create-color v-model:modelShow="createColorModelShow"></create-color>
27 </div> 35 </div>
28 </template> 36 </template>
29 37
30 <script setup lang="ts"> 38 <script setup lang="ts">
31 -import { computed } from 'vue' 39 +import { ref, computed } from 'vue'
  40 +import cloneDeep from 'lodash/cloneDeep'
32 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 41 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
33 import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' 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 import { useDesignStore } from '@/store/modules/designStore/designStore' 44 import { useDesignStore } from '@/store/modules/designStore/designStore'
41 -import cloneDeep from 'lodash/cloneDeep' 45 +import { loadAsyncComponent, colorCustomMerge } from '@/utils'
42 import { icon } from '@/plugins' 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 const chartEditStore = useChartEditStore() 58 const chartEditStore = useChartEditStore()
46 59
47 // 全局颜色 60 // 全局颜色
48 const designStore = useDesignStore() 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 const themeColor = computed(() => { 70 const themeColor = computed(() => {
@@ -57,6 +76,16 @@ const selectName = computed(() => { @@ -57,6 +76,16 @@ const selectName = computed(() => {
57 return chartEditStore.getEditCanvasConfig.chartThemeColor 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 const fetchShowColors = (colors: Array<string>) => { 90 const fetchShowColors = (colors: Array<string>) => {
62 return cloneDeep(colors).splice(0, 6) 91 return cloneDeep(colors).splice(0, 6)
@@ -69,36 +98,34 @@ const selectTheme = (theme: ChartColorsNameType) => { @@ -69,36 +98,34 @@ const selectTheme = (theme: ChartColorsNameType) => {
69 </script> 98 </script>
70 99
71 <style lang="scss" scoped> 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 .card-box { 105 .card-box {
75 cursor: pointer; 106 cursor: pointer;
76 margin-top: 15px; 107 margin-top: 15px;
77 padding: 0; 108 padding: 0;
78 @include fetch-bg-color('background-color4-shallow'); 109 @include fetch-bg-color('background-color4-shallow');
79 - border-radius: 23px; 110 + border-radius: $radius;
80 overflow: hidden; 111 overflow: hidden;
81 - @include deep() {  
82 - .n-card__content {  
83 - padding-top: 5px;  
84 - padding-bottom: 10px;  
85 - }  
86 - } 112 +
87 &.selected { 113 &.selected {
88 - border: 1px solid v-bind('themeColor'); 114 + border: 2px solid v-bind('themeColor');
89 border-bottom: 1px solid rgba(0, 0, 0, 0); 115 border-bottom: 1px solid rgba(0, 0, 0, 0);
90 } 116 }
91 &:first-child { 117 &:first-child {
92 - margin-top: 0; 118 + margin-top: 5px;
93 } 119 }
94 .go-flex-items-center { 120 .go-flex-items-center {
95 justify-content: space-between; 121 justify-content: space-between;
  122 + margin-top: -4px;
96 } 123 }
97 .theme-color-item { 124 .theme-color-item {
98 display: inline-block; 125 display: inline-block;
99 width: 20px; 126 width: 20px;
100 height: 20px; 127 height: 20px;
101 - border-radius: 50%; 128 + border-radius: $itemRadius;
102 } 129 }
103 .theme-bottom { 130 .theme-bottom {
104 position: absolute; 131 position: absolute;
@@ -106,7 +133,6 @@ const selectTheme = (theme: ChartColorsNameType) => { @@ -106,7 +133,6 @@ const selectTheme = (theme: ChartColorsNameType) => {
106 bottom: 0px; 133 bottom: 0px;
107 width: 100%; 134 width: 100%;
108 height: 3px; 135 height: 3px;
109 - background-image: linear-gradient(to right, #e0c3fc 0%, #8ec5fc 100%);  
110 } 136 }
111 } 137 }
112 } 138 }
  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>
  1 +import CreateColorRender from './index.vue'
  2 +
  3 +export { CreateColorRender }
  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 +import CreateColorRenderChart from './index.vue'
  2 +
  3 +export { CreateColorRenderChart }
  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>
  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,7 +21,8 @@
21 ></n-input-number> 21 ></n-input-number>
22 </n-form-item> 22 </n-form-item>
23 </n-form> 23 </n-form>
24 - <n-card class="upload-box"> 24 +
  25 + <div class="upload-box">
25 <n-upload 26 <n-upload
26 v-model:file-list="uploadFileListRef" 27 v-model:file-list="uploadFileListRef"
27 :show-file-list="false" 28 :show-file-list="false"
@@ -38,7 +39,7 @@ @@ -38,7 +39,7 @@
38 </div> 39 </div>
39 </n-upload-dragger> 40 </n-upload-dragger>
40 </n-upload> 41 </n-upload>
41 - </n-card> 42 + </div>
42 <n-space vertical :size="12"> 43 <n-space vertical :size="12">
43 <n-space> 44 <n-space>
44 <n-text>背景选择</n-text> 45 <n-text>背景选择</n-text>
@@ -138,11 +139,12 @@ @@ -138,11 +139,12 @@
138 <script setup lang="ts"> 139 <script setup lang="ts">
139 import { ref, nextTick, watch } from 'vue' 140 import { ref, nextTick, watch } from 'vue'
140 import { backgroundImageSize } from '@/settings/designSetting' 141 import { backgroundImageSize } from '@/settings/designSetting'
  142 +import { swatchesColors } from '@/settings/chartThemes/index'
141 import { FileTypeEnum } from '@/enums/fileTypeEnum' 143 import { FileTypeEnum } from '@/enums/fileTypeEnum'
142 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 144 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
143 import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' 145 import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
144 import { StylesSetting } from '@/components/Pages/ChartItemSetting' 146 import { StylesSetting } from '@/components/Pages/ChartItemSetting'
145 -import { UploadCustomRequestOptions, SelectOption } from 'naive-ui' 147 +import { UploadCustomRequestOptions } from 'naive-ui'
146 import { fileToUrl, loadAsyncComponent } from '@/utils' 148 import { fileToUrl, loadAsyncComponent } from '@/utils'
147 import { PreviewScaleEnum } from '@/enums/styleEnum' 149 import { PreviewScaleEnum } from '@/enums/styleEnum'
148 import { icon } from '@/plugins' 150 import { icon } from '@/plugins'
@@ -187,9 +189,6 @@ const selectColorOptions = [ @@ -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 const globalTabList = [ 192 const globalTabList = [
194 { 193 {
195 key: 'ChartTheme', 194 key: 'ChartTheme',
@@ -317,7 +316,7 @@ const selectPreviewType = (key: PreviewScaleEnum) => { @@ -317,7 +316,7 @@ const selectPreviewType = (key: PreviewScaleEnum) => {
317 </script> 316 </script>
318 317
319 <style lang="scss" scoped> 318 <style lang="scss" scoped>
320 -$uploadWidth: 280px; 319 +$uploadWidth: 326px;
321 $uploadHeight: 193px; 320 $uploadHeight: 193px;
322 @include go(canvas-setting) { 321 @include go(canvas-setting) {
323 padding-top: 20px; 322 padding-top: 20px;
@@ -325,13 +324,10 @@ $uploadHeight: 193px; @@ -325,13 +324,10 @@ $uploadHeight: 193px;
325 cursor: pointer; 324 cursor: pointer;
326 margin-bottom: 20px; 325 margin-bottom: 20px;
327 @include deep() { 326 @include deep() {
328 - .n-card__content {  
329 - padding: 0;  
330 - overflow: hidden;  
331 - }  
332 .n-upload-dragger { 327 .n-upload-dragger {
333 padding: 5px; 328 padding: 5px;
334 width: $uploadWidth; 329 width: $uploadWidth;
  330 + background-color: rgba(0, 0, 0, 0);
335 } 331 }
336 } 332 }
337 .upload-show { 333 .upload-show {
1 <template> 1 <template>
2 <div class="go-chart-data-pond-list"> 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 <n-timeline-item type="info"> </n-timeline-item> 4 <n-timeline-item type="info"> </n-timeline-item>
5 <n-timeline-item type="success"></n-timeline-item> 5 <n-timeline-item type="success"></n-timeline-item>
6 </n-timeline> 6 </n-timeline>
@@ -115,11 +115,9 @@ $textSize: 10px; @@ -115,11 +115,9 @@ $textSize: 10px;
115 padding-bottom: 5px; 115 padding-bottom: 5px;
116 margin-right: 5px; 116 margin-right: 5px;
117 display: flex; 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 .pond-item-box { 123 .pond-item-box {
@@ -56,7 +56,7 @@ import { MenuEnum } from '@/enums/editPageEnum' @@ -56,7 +56,7 @@ import { MenuEnum } from '@/enums/editPageEnum'
56 import { chartColors } from '@/settings/chartThemes/index' 56 import { chartColors } from '@/settings/chartThemes/index'
57 import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' 57 import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
58 import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d' 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 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 60 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
61 import { useContextMenu, divider } from '@/views/chart/hooks/useContextMenu.hook' 61 import { useContextMenu, divider } from '@/views/chart/hooks/useContextMenu.hook'
62 import { useMouseHandle } from '../../hooks/useDrag.hook' 62 import { useMouseHandle } from '../../hooks/useDrag.hook'
@@ -117,8 +117,8 @@ const optionsHandle = ( @@ -117,8 +117,8 @@ const optionsHandle = (
117 117
118 // 配置项 118 // 配置项
119 const themeColor = computed(() => { 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,7 +55,7 @@ const rangeModelStyle = computed(() => {
55 position: relative; 55 position: relative;
56 transform-origin: left top; 56 transform-origin: left top;
57 background-size: cover; 57 background-size: cover;
58 - border-radius: 20px; 58 + border-radius: 10px;
59 overflow: hidden; 59 overflow: hidden;
60 @include fetch-border-color('hover-border-color'); 60 @include fetch-border-color('hover-border-color');
61 @include fetch-bg-color('background-color2'); 61 @include fetch-bg-color('background-color2');
1 import { watch } from 'vue' 1 import { watch } from 'vue'
2 import { useRoute } from 'vue-router' 2 import { useRoute } from 'vue-router'
  3 +import throttle from 'lodash/throttle'
3 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 4 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  5 +import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
4 import { useSync } from '@/views/chart/hooks/useSync.hook' 6 import { useSync } from '@/views/chart/hooks/useSync.hook'
5 import { ChartEnum } from '@/enums/pageEnum' 7 import { ChartEnum } from '@/enums/pageEnum'
6 import { SavePageEnum } from '@/enums/editPageEnum' 8 import { SavePageEnum } from '@/enums/editPageEnum'
7 import { editToJsonInterval } from '@/settings/designSetting' 9 import { editToJsonInterval } from '@/settings/designSetting'
  10 +import { goDialog } from '@/utils'
8 11
9 const { updateComponent } = useSync() 12 const { updateComponent } = useSync()
10 const chartEditStore = useChartEditStore() 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 const useSyncUpdateHandle = () => { 28 const useSyncUpdateHandle = () => {
14 // 定义侦听器变量 29 // 定义侦听器变量
15 let timer: any 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 const use = () => { 44 const use = () => {
23 - // // 1、定时同步数据 45 + // 定时同步数据(暂不开启)
24 // timer = setInterval(() => { 46 // timer = setInterval(() => {
25 // // 窗口激活并且处于工作台 47 // // 窗口激活并且处于工作台
26 // document.hasFocus() && syncData() 48 // document.hasFocus() && syncData()
27 // }, editToJsonInterval) 49 // }, editToJsonInterval)
  50 +
28 // 2、失焦同步数据 51 // 2、失焦同步数据
29 addEventListener('blur', syncData) 52 addEventListener('blur', syncData)
30 53
31 // 【监听JSON代码 刷新工作台图表】 54 // 【监听JSON代码 刷新工作台图表】
32 addEventListener(SavePageEnum.JSON, updateFn) 55 addEventListener(SavePageEnum.JSON, updateFn)
  56 +
  57 + // 监听编辑页关闭
  58 + addEventListener(SavePageEnum.CLOSE, throttle(closeFn, 1000))
33 } 59 }
34 60
35 // 关闭侦听 61 // 关闭侦听
36 const unUse = () => { 62 const unUse = () => {
37 // clearInterval(timer) 63 // clearInterval(timer)
  64 + // removeEventListener('blur', syncData)
38 removeEventListener(SavePageEnum.JSON, updateFn) 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,7 +66,14 @@ import { ref, computed } from 'vue'
66 import { useSettingStore } from '@/store/modules/settingStore/settingStore' 66 import { useSettingStore } from '@/store/modules/settingStore/settingStore'
67 import { ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d' 67 import { ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
68 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 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 import { EditEnum } from '@/enums/pageEnum' 77 import { EditEnum } from '@/enums/pageEnum'
71 import { StorageEnum } from '@/enums/storageEnum' 78 import { StorageEnum } from '@/enums/storageEnum'
72 import { useRoute } from 'vue-router' 79 import { useRoute } from 'vue-router'
@@ -81,8 +88,10 @@ const { DownloadIcon, ShareIcon, PawIcon, SettingsSharpIcon, CreateIcon } = icon @@ -81,8 +88,10 @@ const { DownloadIcon, ShareIcon, PawIcon, SettingsSharpIcon, CreateIcon } = icon
81 const settingStore = useSettingStore() 88 const settingStore = useSettingStore()
82 const chartEditStore = useChartEditStore() 89 const chartEditStore = useChartEditStore()
83 const routerParamsInfo = useRoute() 90 const routerParamsInfo = useRoute()
  91 +
  92 +/// THINGS_KIT 关闭监听页面失焦数据同步数据
84 // 初始化编辑 JSON 模块 93 // 初始化编辑 JSON 模块
85 -useSyncUpdate() 94 +// useSyncUpdate()
86 95
87 // 鼠标悬停定时器 96 // 鼠标悬停定时器
88 let mouseTime: any = null 97 let mouseTime: any = null
@@ -137,8 +146,8 @@ const toolsMouseoutHandle = () => { @@ -137,8 +146,8 @@ const toolsMouseoutHandle = () => {
137 146
138 // 编辑处理 147 // 编辑处理
139 const editHandle = () => { 148 const editHandle = () => {
140 - window['$message'].warning('将开启失焦更新!')  
141 -// window['$message'].warning('将开启失焦更新与 5 秒同步更新!') 149 + window['$message'].warning('请通过顶部【同步内容】按钮同步最新数据!')
  150 + chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CODE_EDIT, true)
142 setTimeout(() => { 151 setTimeout(() => {
143 // 获取id路径 152 // 获取id路径
144 const path = fetchPathByName(EditEnum.CHART_EDIT_NAME, 'href') 153 const path = fetchPathByName(EditEnum.CHART_EDIT_NAME, 'href')
@@ -146,7 +155,7 @@ const editHandle = () => { @@ -146,7 +155,7 @@ const editHandle = () => {
146 const id = fetchRouteParamsLocation() 155 const id = fetchRouteParamsLocation()
147 updateToSession(id) 156 updateToSession(id)
148 routerTurnByPath(path, [id], undefined, true) 157 routerTurnByPath(path, [id], undefined, true)
149 - }, 1000) 158 + }, 2000)
150 } 159 }
151 160
152 // 把内存中的数据同步到SessionStorage 便于传递给新窗口初始化数据 161 // 把内存中的数据同步到SessionStorage 便于传递给新窗口初始化数据
@@ -57,7 +57,7 @@ import { onMounted, computed } from 'vue' @@ -57,7 +57,7 @@ import { onMounted, computed } from 'vue'
57 import { chartColors } from '@/settings/chartThemes/index' 57 import { chartColors } from '@/settings/chartThemes/index'
58 import { MenuEnum } from '@/enums/editPageEnum' 58 import { MenuEnum } from '@/enums/editPageEnum'
59 import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' 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 import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook' 61 import { useContextMenu } from '@/views/chart/hooks/useContextMenu.hook'
62 import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d' 62 import { MenuOptionsItemType } from '@/views/chart/hooks/useContextMenu.hook.d'
63 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 63 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@@ -120,8 +120,8 @@ const themeSetting = computed(() => { @@ -120,8 +120,8 @@ const themeSetting = computed(() => {
120 120
121 // 配置项 121 // 配置项
122 const themeColor = computed(() => { 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,6 +120,7 @@ const historyList = reactive<ItemType<HistoryStackEnum>[]>([
120 } 120 }
121 ]) 121 ])
122 122
  123 +
123 // store 描述的是展示的值,所以和 ContentConfigurations 的 collapsed 是相反的 124 // store 描述的是展示的值,所以和 ContentConfigurations 的 collapsed 是相反的
124 const styleHandle = (item: ItemType<ChartLayoutStoreEnum>) => { 125 const styleHandle = (item: ItemType<ChartLayoutStoreEnum>) => {
125 if (item.key === ChartLayoutStoreEnum.DETAILS) { 126 if (item.key === ChartLayoutStoreEnum.DETAILS) {
1 <template> 1 <template>
2 <n-space class="go-mt-0"> 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 <template #icon> 4 <template #icon>
5 <component :is="item.icon"></component> 5 <component :is="item.icon"></component>
6 </template> 6 </template>
@@ -10,16 +10,17 @@ @@ -10,16 +10,17 @@
10 </template> 10 </template>
11 11
12 <script setup lang="ts"> 12 <script setup lang="ts">
13 -import { shallowReactive } from 'vue' 13 +import { computed, shallowReactive } from 'vue'
14 import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils' 14 import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
15 import { PreviewEnum } from '@/enums/pageEnum' 15 import { PreviewEnum } from '@/enums/pageEnum'
16 import { StorageEnum } from '@/enums/storageEnum' 16 import { StorageEnum } from '@/enums/storageEnum'
17 import { useRoute } from 'vue-router' 17 import { useRoute } from 'vue-router'
18 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 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 import { icon } from '@/plugins' 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 const chartEditStore = useChartEditStore() 24 const chartEditStore = useChartEditStore()
24 25
25 const routerParamsInfo = useRoute() 26 const routerParamsInfo = useRoute()
@@ -42,7 +43,8 @@ const previewHandle = () => { @@ -42,7 +43,8 @@ const previewHandle = () => {
42 setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo) 43 setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
43 } else { 44 } else {
44 sessionStorageInfo.push({ 45 sessionStorageInfo.push({
45 - id: previewId, ...storageInfo 46 + id: previewId,
  47 + ...storageInfo
46 }) 48 })
47 setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo) 49 setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
48 } 50 }
@@ -66,6 +68,13 @@ const sendHandle = () => { @@ -66,6 +68,13 @@ const sendHandle = () => {
66 const btnList = shallowReactive([ 68 const btnList = shallowReactive([
67 { 69 {
68 select: true, 70 select: true,
  71 + title: '同步内容',
  72 + type: 'primary',
  73 + icon: renderIcon(AnalyticsIcon),
  74 + event: syncData
  75 + },
  76 + {
  77 + select: true,
69 title: '预览', 78 title: '预览',
70 icon: renderIcon(BrowsersOutlineIcon), 79 icon: renderIcon(BrowsersOutlineIcon),
71 event: previewHandle 80 event: previewHandle
@@ -78,7 +87,16 @@ const btnList = shallowReactive([ @@ -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 </script> 98 </script>
  99 +
82 <style lang="scss" scoped> 100 <style lang="scss" scoped>
83 .align-center { 101 .align-center {
84 margin-top: -4px; 102 margin-top: -4px;
@@ -5,15 +5,25 @@ @@ -5,15 +5,25 @@
5 </n-icon> 5 </n-icon>
6 <n-text @click="handleFocus"> 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 <span class="title"> 9 <span class="title">
10 {{ comTitle }} 10 {{ comTitle }}
11 </span> 11 </span>
12 </n-button> 12 </n-button>
13 </n-text> 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 </n-space> 27 </n-space>
18 </template> 28 </template>
19 29
@@ -63,6 +73,8 @@ const handleBlur = () => { @@ -63,6 +73,8 @@ const handleBlur = () => {
63 </script> 73 </script>
64 <style lang="scss" scoped> 74 <style lang="scss" scoped>
65 .title { 75 .title {
  76 + padding-left: 5px;
  77 + padding-right: 5px;
66 font-size: 15px; 78 font-size: 15px;
67 } 79 }
68 </style> 80 </style>
@@ -14,8 +14,17 @@ @@ -14,8 +14,17 @@
14 </n-button> 14 </n-button>
15 </div> 15 </div>
16 <n-space> 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 </n-space> 28 </n-space>
20 </n-layout-header> 29 </n-layout-header>
21 <n-layout-content> 30 <n-layout-content>
@@ -26,28 +35,31 @@ @@ -26,28 +35,31 @@
26 lineNumbers: 'on', 35 lineNumbers: 'on',
27 minimap: { enabled: true } 36 minimap: { enabled: true }
28 }" 37 }"
29 - /> 38 + />
30 </n-layout-content> 39 </n-layout-content>
31 </n-layout> 40 </n-layout>
32 </div> 41 </div>
33 </template> 42 </template>
34 43
35 <script setup lang="ts"> 44 <script setup lang="ts">
36 -import { computed, ref, watch } from 'vue' 45 +import { ref } from 'vue'
37 import { MonacoEditor } from '@/components/Pages/MonacoEditor' 46 import { MonacoEditor } from '@/components/Pages/MonacoEditor'
38 import { SavePageEnum } from '@/enums/editPageEnum' 47 import { SavePageEnum } from '@/enums/editPageEnum'
39 import { getSessionStorageInfo } from '../preview/utils' 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 import { StorageEnum } from '@/enums/storageEnum' 50 import { StorageEnum } from '@/enums/storageEnum'
43 import { icon } from '@/plugins' 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 const showOpenFilePicker: Function = (window as any).showOpenFilePicker 55 const showOpenFilePicker: Function = (window as any).showOpenFilePicker
47 const content = ref('') 56 const content = ref('')
  57 +
  58 +window['$message'].warning('请不要刷新此窗口!')
  59 +
48 // 从sessionStorage 获取数据 60 // 从sessionStorage 获取数据
49 async function getDataBySession() { 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 setTitle(`编辑-${localStorageInfo.editCanvasConfig.projectName}`) 63 setTitle(`编辑-${localStorageInfo.editCanvasConfig.projectName}`)
52 content.value = JSONStringify(localStorageInfo) 64 content.value = JSONStringify(localStorageInfo)
53 } 65 }
@@ -60,44 +72,75 @@ function back() { @@ -60,44 +72,75 @@ function back() {
60 } 72 }
61 73
62 // 导入json文本 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 window.opener.addEventListener(SavePageEnum.CHART, (e: any) => { 99 window.opener.addEventListener(SavePageEnum.CHART, (e: any) => {
  100 + window['$message'].success('正在进行更新...')
75 setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [e.detail]) 101 setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [e.detail])
76 content.value = JSONStringify(e.detail) 102 content.value = JSONStringify(e.detail)
77 }) 103 })
78 104
79 -// 窗口失焦 + 保存 => 同步数据 105 +// 保存按钮同步数据
80 document.addEventListener('keydown', function (e) { 106 document.addEventListener('keydown', function (e) {
81 if (e.keyCode == 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) { 107 if (e.keyCode == 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
82 e.preventDefault() 108 e.preventDefault()
83 updateSync() 109 updateSync()
84 } 110 }
85 }) 111 })
86 -addEventListener('blur', updateSync) 112 +
  113 +// 失焦保存(暂时关闭)
  114 +// addEventListener('blur', updateSync)
87 115
88 // 同步更新 116 // 同步更新
89 async function updateSync() { 117 async function updateSync() {
90 if (!window.opener) { 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 </script> 146 </script>
@@ -24,9 +24,18 @@ @@ -24,9 +24,18 @@
24 </layout-header> 24 </layout-header>
25 <div class="go-login"> 25 <div class="go-login">
26 <div class="go-login-carousel"> 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 </n-carousel> 39 </n-carousel>
31 </div> 40 </div>
32 <div class="login-account"> 41 <div class="login-account">
@@ -34,11 +43,24 @@ @@ -34,11 +43,24 @@
34 <n-collapse-transition :appear="true" :show="show"> 43 <n-collapse-transition :appear="true" :show="show">
35 <n-card class="login-account-card" :title="$t('login.desc')"> 44 <n-card class="login-account-card" :title="$t('login.desc')">
36 <div class="login-account-top"> 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 </div> 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 <n-form-item path="username"> 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 <template #prefix> 64 <template #prefix>
43 <n-icon size="18"> 65 <n-icon size="18">
44 <PersonOutlineIcon></PersonOutlineIcon> 66 <PersonOutlineIcon></PersonOutlineIcon>
@@ -47,8 +69,12 @@ @@ -47,8 +69,12 @@
47 </n-input> 69 </n-input>
48 </n-form-item> 70 </n-form-item>
49 <n-form-item path="password"> 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 <template #prefix> 78 <template #prefix>
53 <n-icon size="18"> 79 <n-icon size="18">
54 <LockClosedOutlineIcon></LockClosedOutlineIcon> 80 <LockClosedOutlineIcon></LockClosedOutlineIcon>
@@ -208,12 +234,10 @@ $carousel-image-height: 60vh; @@ -208,12 +234,10 @@ $carousel-image-height: 60vh;
208 * { 234 * {
209 box-sizing: border-box; 235 box-sizing: border-box;
210 } 236 }
211 -  
212 @include go(login-box) { 237 @include go(login-box) {
213 height: $go-login-height; 238 height: $go-login-height;
214 overflow: hidden; 239 overflow: hidden;
215 @include background-image('background-image'); 240 @include background-image('background-image');
216 -  
217 &-header { 241 &-header {
218 display: flex; 242 display: flex;
219 justify-content: space-between; 243 justify-content: space-between;
@@ -221,7 +245,6 @@ $carousel-image-height: 60vh; @@ -221,7 +245,6 @@ $carousel-image-height: 60vh;
221 padding: 0 40px; 245 padding: 0 40px;
222 height: $--header-height; 246 height: $--header-height;
223 } 247 }
224 -  
225 &-divider { 248 &-divider {
226 margin: 0; 249 margin: 0;
227 padding-top: 0; 250 padding-top: 0;
@@ -43,12 +43,14 @@ import { ChartEditStorageType } from '../../index.d' @@ -43,12 +43,14 @@ import { ChartEditStorageType } from '../../index.d'
43 import { PreviewRenderGroup } from '../PreviewRenderGroup/index' 43 import { PreviewRenderGroup } from '../PreviewRenderGroup/index'
44 import { CreateComponentGroupType } from '@/packages/index.d' 44 import { CreateComponentGroupType } from '@/packages/index.d'
45 import { chartColors } from '@/settings/chartThemes/index' 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 import { getSizeStyle, getComponentAttrStyle, getStatusStyle, getPreviewConfigStyle } from '../../utils' 48 import { getSizeStyle, getComponentAttrStyle, getStatusStyle, getPreviewConfigStyle } from '../../utils'
48 import { useLifeHandler } from '@/hooks' 49 import { useLifeHandler } from '@/hooks'
49 50
50 // 初始化数据池 51 // 初始化数据池
51 const { initDataPond, clearMittDataPondMap } = useChartDataPondFetch() 52 const { initDataPond, clearMittDataPondMap } = useChartDataPondFetch()
  53 +const chartEditStore = useChartEditStore()
52 54
53 const props = defineProps({ 55 const props = defineProps({
54 localStorageInfo: { 56 localStorageInfo: {
@@ -63,10 +65,11 @@ const themeSetting = computed(() => { @@ -63,10 +65,11 @@ const themeSetting = computed(() => {
63 return chartThemeSetting 65 return chartThemeSetting
64 }) 66 })
65 67
  68 +
66 // 配置项 69 // 配置项
67 const themeColor = computed(() => { 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,7 +26,7 @@
26 </div> 26 </div>
27 </template> 27 </template>
28 28
29 -<script setup lang="ts" > 29 +<script setup lang="ts">
30 import { computed } from 'vue' 30 import { computed } from 'vue'
31 import { PreviewRenderList } from './components/PreviewRenderList' 31 import { PreviewRenderList } from './components/PreviewRenderList'
32 import { getFilterStyle, setTitle } from '@/utils' 32 import { getFilterStyle, setTitle } from '@/utils'
@@ -68,19 +68,16 @@ const { show } = useComInstall(localStorageInfo) @@ -68,19 +68,16 @@ const { show } = useComInstall(localStorageInfo)
68 height: 100vh; 68 height: 100vh;
69 width: 100vw; 69 width: 100vw;
70 @include background-image('background-image'); 70 @include background-image('background-image');
71 -  
72 &.fit, 71 &.fit,
73 &.full { 72 &.full {
74 display: flex; 73 display: flex;
75 align-items: center; 74 align-items: center;
76 justify-content: center; 75 justify-content: center;
77 overflow: hidden; 76 overflow: hidden;
78 -  
79 .go-preview-scale { 77 .go-preview-scale {
80 transform-origin: center center; 78 transform-origin: center center;
81 } 79 }
82 } 80 }
83 -  
84 &.scrollY { 81 &.scrollY {
85 overflow-x: hidden; 82 overflow-x: hidden;
86 83
@@ -27,8 +27,8 @@ @@ -27,8 +27,8 @@
27 </div> 27 </div>
28 <template #action> 28 <template #action>
29 <div class="go-flex-items-center list-footer" justify="space-between"> 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 </n-text> 32 </n-text>
33 <!-- 工具 --> 33 <!-- 工具 -->
34 <div class="go-flex-items-center list-footer-ri"> 34 <div class="go-flex-items-center list-footer-ri">
@@ -37,12 +37,12 @@ @@ -37,12 +37,12 @@
37 <n-badge 37 <n-badge
38 class="go-animation-twinkle" 38 class="go-animation-twinkle"
39 dot 39 dot
40 - :color="cardData.state===0 ? '#34c749' : '#fcbc40'" 40 + :color="cardData.release ? '#34c749' : '#fcbc40'"
41 ></n-badge> 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 </n-text> 47 </n-text>
48 48
@@ -6,7 +6,7 @@ import { ChartList } from '../../..' @@ -6,7 +6,7 @@ import { ChartList } from '../../..'
6 export const useDataListInit = () => { 6 export const useDataListInit = () => {
7 const list = ref<ChartList>([ 7 const list = ref<ChartList>([
8 { 8 {
9 - id: 1, 9 + id: 1,
10 title: '物料1-假数据不可用', 10 title: '物料1-假数据不可用',
11 release: true, 11 release: true,
12 label: '官方案例' 12 label: '官方案例'
@@ -12,3 +12,5 @@ interface Window { @@ -12,3 +12,5 @@ interface Window {
12 // 编辑 JSON 的存储对象 12 // 编辑 JSON 的存储对象
13 opener: any 13 opener: any
14 } 14 }
  15 +
  16 +declare type Recordable<T = any> = Record<string, T>
1 /// <reference types="vite/client" /> 1 /// <reference types="vite/client" />
2 2
3 -declare interface GlobEnvConfig { 3 +interface ImportMetaEnv {
4 // 标题 4 // 标题
5 VITE_GLOB_APP_TITLE: string; 5 VITE_GLOB_APP_TITLE: string;
6 // 公共路径 6 // 公共路径