Commit d8bc3b9a4b4fc3d86829678883971ef41112b238

Authored by fengtao
Committed by xp.Huang
1 parent a19d97cb

feat(src/views/chart): 新增部分小组件

Showing 34 changed files with 2703 additions and 157 deletions
  1 +
  2 +
  3 +// 动画时间函数枚举
  4 +export enum AnimationTimingFunctionNameEnum {
  5 + // 动画从头到尾的速度是相同的
  6 + LINEAR = '匀速',
  7 + // 默认值:动画以低速开始,然后加快,在结束前变慢。
  8 + EASE = '缓速',
  9 + // 动画以低速开始。
  10 + EASEIN = '低速开始',
  11 + // 动画以低速结束。
  12 + EASEOUT = '低速结束',
  13 + // 动画以低速开始和结束。
  14 + EASEINOUT = '低速开始和结束'
  15 +}
  16 +
  17 +export enum AnimationTimingFunctionEnum {
  18 + // 动画从头到尾的速度是相同的
  19 + LINEAR = 'linear',
  20 + // 默认值:动画以低速开始,然后加快,在结束前变慢。
  21 + EASE = 'ease',
  22 + // 动画以低速开始。
  23 + EASEIN = 'ease-in',
  24 + // 动画以低速结束。
  25 + EASEOUT = 'ease-out',
  26 + // 动画以低速开始和结束。
  27 + EASEINOUT = 'ease-in-out'
  28 +}
  29 +
  30 +// 动画执行状态枚举
  31 +export enum AnimationPlayStateNameEnum {
  32 + // 暂停
  33 + PAUSED = '暂停',
  34 + // 运行
  35 + RUNNING = '运行'
  36 +}
  37 +
  38 +export enum AnimationPlayStateEnum {
  39 + // 暂停
  40 + PAUSED = 'paused',
  41 + // 运行
  42 + RUNNING = 'running'
  43 +}
  44 +
  45 +// 动画执行次数枚举
  46 +export enum AnimationIterationCountNameEnum {
  47 + // 暂停
  48 + ITERATIONCOUNT = '无限次',
  49 +}
  50 +
  51 +export enum AnimationIterationCountEnum {
  52 + // 暂停
  53 + ITERATIONCOUNT = 'infinite',
  54 +}
... ...
... ... @@ -16,19 +16,19 @@ export const enum areaEnum {
16 16 }
17 17
18 18 export interface regionInfo {
19   - provinceValue:string
20   - cityValue: string|null
21   - countyValue: string|null
22   - levelStr:areaEnum
  19 + provinceValue: string
  20 + cityValue: string | null
  21 + countyValue: string | null
  22 + levelStr: areaEnum
23 23 }
24 24
25 25 type itemOption = {
26   - label:string
27   - value:string
  26 + label: string
  27 + value: string
28 28 }
29   -export interface regionOption{
30   - provinceOptions: itemOption[],
31   - cityOptions: itemOption[],
  29 +export interface regionOption {
  30 + provinceOptions: itemOption[]
  31 + cityOptions: itemOption[]
32 32 countryOptions: itemOption[]
33 33 }
34 34
... ... @@ -38,9 +38,9 @@ export interface historyParentType {
38 38 level: string
39 39 }
40 40
41   -export interface backMapLevel{
42   - (levelStr:string): boolean
43   - (level:string): boolean
  41 +export interface backMapLevel {
  42 + (levelStr: string): boolean
  43 + (level: string): boolean
44 44 (): void
45 45 (): void
46 46 }
... ... @@ -68,6 +68,50 @@ export const option = {
68 68 iconDistanceTop: 20,
69 69 drillingIn: false,
70 70 dataset: dataMaps,
  71 + dataConfig: {
  72 + map3D: [
  73 + {
  74 + name: '四川省',
  75 + value: [104.10068024609373, 30.580525329665175, 20000],
  76 + adcode: 510000,
  77 + height: 5,
  78 + itemStyle: {
  79 + color: '#E41717FF',
  80 + opacity: 1,
  81 + borderWidth: 0.4,
  82 + borderColor: '#5F9EA0'
  83 + }
  84 + }
  85 + ],
  86 + scatter3D: [
  87 + {
  88 + name: '广东省',
  89 + value: [113.2592945, 23.1301964, 20000],
  90 + adcode: 440000,
  91 + height: 5,
  92 + itemStyle: {
  93 + color: '#E41717FF',
  94 + opacity: 1,
  95 + borderWidth: 0.4,
  96 + borderColor: '#5F9EA0'
  97 + }
  98 + }
  99 + ],
  100 + bar3D: [
  101 + {
  102 + name: '安徽省',
  103 + value: [114.878463, 29.395191, 20000],
  104 + adcode: 340000,
  105 + height: 5,
  106 + itemStyle: {
  107 + color: '#E41717FF',
  108 + opacity: 1,
  109 + borderWidth: 0.4,
  110 + borderColor: '#5F9EA0'
  111 + }
  112 + }
  113 + ]
  114 + },
71 115 saveClickRegion: {
72 116 level: ''
73 117 },
... ... @@ -76,9 +120,9 @@ export const option = {
76 120 showHainanIsLands: true,
77 121 saveSelect: {
78 122 levelStr: areaEnum.COUNTRY,
79   - cityValue:null,
80   - countyValue:null,
81   - provinceValue:'china'
  123 + cityValue: null,
  124 + countyValue: null,
  125 + provinceValue: 'china'
82 126 }
83 127 },
84 128 tooltip: {
... ... @@ -122,11 +166,30 @@ export const option = {
122 166 }
123 167 },
124 168 itemStyle: {
125   - color: 'green',
  169 + color: 'orange', //背景颜色
  170 + opacity: 1,
126 171 borderWidth: 0.8,
127   - borderColor: 'blue'
  172 + borderColor: 'rgb(62,215,213)'
  173 + },
  174 + emphasis: {
  175 + // 鼠标hover 高亮时图形和标签的样式 (当鼠标放上去时 label和itemStyle 的样式)
  176 + label: {
  177 + // label高亮时的配置
  178 + show: true,
  179 + textStyle: {
  180 + color: 'green',
  181 + fontSize: 14
  182 + }
  183 + },
  184 + itemStyle: {
  185 + color: 'red'
  186 + }
  187 + },
  188 + data: [],
  189 + viewControl: {
  190 + projection: 'perspective', // 先设置为这个perspective
  191 + // distance: 1000 //默认缩放比例
128 192 },
129   - data: []
130 193 },
131 194 {
132 195 name: 'scatter3D',
... ... @@ -135,7 +198,21 @@ export const option = {
135 198 symbol: 'circle',
136 199 symbolSize: 20,
137 200 animation: true,
138   - data: dataMaps
  201 + data: []
  202 + },
  203 + {
  204 + name: 'bar3D',
  205 + type: 'bar3D',
  206 + coordinateSystem: 'geo3D',
  207 + // // 倒角尺寸
  208 + bevelSize: 0,
  209 + minHeight: 12,
  210 + shading: 'lambert',
  211 + barSize: 2,
  212 + itemStyle: {
  213 + color: '#51e0f9'
  214 + },
  215 + data: []
139 216 }
140 217 ]
141 218 }
... ...
... ... @@ -41,7 +41,7 @@
41 41 :drillingIn="optionData.drillingIn"
42 42 @submit="onHandleSelectValues"
43 43 />
44   - <SettingItemBox name="颜色">
  44 + <SettingItemBox name="区块配置">
45 45 <SettingItem name="区域颜色">
46 46 <n-color-picker size="small" :modes="['hex']" v-model:value="seriesList[0].itemStyle.color"></n-color-picker>
47 47 </SettingItem>
... ... @@ -60,6 +60,14 @@
60 60 placeholder="请输入"
61 61 ></n-input-number>
62 62 </SettingItem>
  63 + <SettingItem name="透明度">
  64 + <n-input-number
  65 + v-model:value="seriesList[0].itemStyle.opacity"
  66 + :min="0"
  67 + size="small"
  68 + placeholder="请输入"
  69 + ></n-input-number>
  70 + </SettingItem>
63 71 <SettingItem name="厚度">
64 72 <n-input-number
65 73 v-model:value="seriesList[0].regionHeight"
... ... @@ -69,7 +77,7 @@
69 77 ></n-input-number>
70 78 </SettingItem>
71 79 </SettingItemBox>
72   - <SettingItemBox name="标题">
  80 + <SettingItemBox name="标题配置">
73 81 <SettingItem name="是否显示">
74 82 <n-switch v-model:value="seriesList[0].label.show" size="small"></n-switch>
75 83 </SettingItem>
... ... @@ -89,20 +97,20 @@
89 97 ></n-input-number>
90 98 </SettingItem>
91 99 </SettingItemBox>
92   - <SettingItemBox name="高亮">
  100 + <SettingItemBox name="高亮配置">
93 101 <SettingItem name="标题显示">
94   - <n-switch v-model:value="optionData.geo3D.emphasis.label.show" size="small"></n-switch>
  102 + <n-switch v-model:value="seriesList[0].emphasis.label.show" size="small"></n-switch>
95 103 </SettingItem>
96 104 <SettingItem name="颜色">
97 105 <n-color-picker
98 106 size="small"
99 107 :modes="['hex']"
100   - v-model:value="optionData.geo3D.emphasis.label.textStyle.color"
  108 + v-model:value="seriesList[0].emphasis.label.textStyle.color"
101 109 ></n-color-picker>
102 110 </SettingItem>
103 111 <SettingItem name="大小">
104 112 <n-input-number
105   - v-model:value="optionData.geo3D.emphasis.label.textStyle.fontSize"
  113 + v-model:value="seriesList[0].emphasis.label.textStyle.fontSize"
106 114 :min="0"
107 115 size="small"
108 116 placeholder="请输入"
... ... @@ -112,16 +120,16 @@
112 120 <n-color-picker
113 121 size="small"
114 122 :modes="['hex']"
115   - v-model:value="optionData.geo3D.emphasis.itemStyle.color"
  123 + v-model:value="seriesList[0].emphasis.itemStyle.color"
116 124 ></n-color-picker>
117 125 </SettingItem>
118 126 </SettingItemBox>
119   - <SettingItemBox name="标记">
  127 + <SettingItemBox name="散点配置">
120 128 <SettingItem name="大小">
121 129 <n-input-number
122 130 v-model:value="seriesList[1].symbolSize"
123 131 :min="0"
124   - :step="10"
  132 + :step="1"
125 133 size="small"
126 134 placeholder="请输入"
127 135 ></n-input-number>
... ... @@ -130,6 +138,142 @@
130 138 <n-select :options="symbolOption" v-model:value="seriesList[1].symbol"></n-select>
131 139 </SettingItem>
132 140 </SettingItemBox>
  141 + <SettingItemBox name="柱状配置">
  142 + <SettingItem name="最小高度">
  143 + <n-input-number
  144 + v-model:value="seriesList[2].minHeight"
  145 + :min="0"
  146 + :step="1"
  147 + size="small"
  148 + placeholder="请输入"
  149 + ></n-input-number>
  150 + </SettingItem>
  151 + <SettingItem name="大小">
  152 + <n-input-number
  153 + v-model:value="seriesList[2].barSize"
  154 + :min="0"
  155 + :step="1"
  156 + size="small"
  157 + placeholder="请输入"
  158 + ></n-input-number>
  159 + </SettingItem>
  160 + <SettingItem name="倒角尺寸">
  161 + <n-input-number
  162 + v-model:value="seriesList[2].bevelSize"
  163 + :min="0"
  164 + :max="1"
  165 + :step="0.1"
  166 + size="small"
  167 + placeholder="请输入"
  168 + ></n-input-number>
  169 + </SettingItem>
  170 + </SettingItemBox>
  171 + <SettingItemBox name="区块配置">
  172 + <template v-for="(item, map3DIndex) in optionData.dataConfig.map3D" :key="map3DIndex">
  173 + <setting-item name="地区名称">
  174 + <n-input v-model:value="item.name"> </n-input>
  175 + </setting-item>
  176 + <setting-item name="地区代码">
  177 + <n-input-number v-model:value="item.adcode"> </n-input-number>
  178 + </setting-item>
  179 + <setting-item name="离地高度">
  180 + <n-input-number v-model:value="item.height"> </n-input-number>
  181 + </setting-item>
  182 + <setting-item name="经度">
  183 + <n-input-number v-model:value="item.value[0]"> </n-input-number>
  184 + </setting-item>
  185 + <setting-item name="纬度">
  186 + <n-input-number v-model:value="item.value[1]"> </n-input-number>
  187 + </setting-item>
  188 + <setting-item name="区块颜色">
  189 + <n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color"></n-color-picker>
  190 + </setting-item>
  191 + <setting-item name="区块透明度">
  192 + <n-input-number v-model:value="item.itemStyle.opacity"> </n-input-number>
  193 + </setting-item>
  194 + <setting-item>
  195 + <n-button size="small" @click="optionData.dataConfig.map3D.splice(map3DIndex, 1)"> - </n-button>
  196 + </setting-item>
  197 + </template>
  198 + <n-button
  199 + style="float: right"
  200 + size="small"
  201 + @click="optionData.dataConfig.map3D.push(cloneDeep(STATIC_SCATTER_CONFIG))"
  202 + >
  203 + +
  204 + </n-button>
  205 + </SettingItemBox>
  206 + <SettingItemBox name="散点配置">
  207 + <template v-for="(item, scatterIndex) in optionData.dataConfig.scatter3D" :key="scatterIndex">
  208 + <setting-item name="地区名称">
  209 + <n-input v-model:value="item.name"> </n-input>
  210 + </setting-item>
  211 + <setting-item name="地区代码">
  212 + <n-input-number v-model:value="item.adcode"> </n-input-number>
  213 + </setting-item>
  214 + <setting-item name="离地高度">
  215 + <n-input-number v-model:value="item.height"> </n-input-number>
  216 + </setting-item>
  217 + <setting-item name="经度">
  218 + <n-input-number v-model:value="item.value[0]"> </n-input-number>
  219 + </setting-item>
  220 + <setting-item name="纬度">
  221 + <n-input-number v-model:value="item.value[1]"> </n-input-number>
  222 + </setting-item>
  223 + <setting-item name="散点颜色">
  224 + <n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color"></n-color-picker>
  225 + </setting-item>
  226 + <setting-item name="散点透明度">
  227 + <n-input-number v-model:value="item.itemStyle.opacity"> </n-input-number>
  228 + </setting-item>
  229 + <setting-item> </setting-item>
  230 + <setting-item>
  231 + <n-button size="small" @click="optionData.dataConfig.scatter3D.splice(scatterIndex, 1)"> - </n-button>
  232 + </setting-item>
  233 + </template>
  234 + <n-button
  235 + style="float: right"
  236 + size="small"
  237 + @click="optionData.dataConfig.scatter3D.push(cloneDeep(STATIC_SCATTER_CONFIG))"
  238 + >
  239 + +
  240 + </n-button>
  241 + </SettingItemBox>
  242 + <SettingItemBox name="柱状配置">
  243 + <template v-for="(item, barIndex) in optionData.dataConfig.bar3D" :key="barIndex">
  244 + <setting-item name="地区名称">
  245 + <n-input v-model:value="item.name"> </n-input>
  246 + </setting-item>
  247 + <setting-item name="地区代码">
  248 + <n-input-number v-model:value="item.adcode"> </n-input-number>
  249 + </setting-item>
  250 + <setting-item name="离地高度">
  251 + <n-input-number v-model:value="item.height"> </n-input-number>
  252 + </setting-item>
  253 + <setting-item name="经度">
  254 + <n-input-number v-model:value="item.value[0]"> </n-input-number>
  255 + </setting-item>
  256 + <setting-item name="纬度">
  257 + <n-input-number v-model:value="item.value[1]"> </n-input-number>
  258 + </setting-item>
  259 + <setting-item name="柱状颜色">
  260 + <n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color"></n-color-picker>
  261 + </setting-item>
  262 + <setting-item name="柱状透明度">
  263 + <n-input-number v-model:value="item.itemStyle.opacity"> </n-input-number>
  264 + </setting-item>
  265 + <setting-item>
  266 + <n-button size="small" @click="optionData.dataConfig.bar3D.splice(barIndex, 1)"> - </n-button>
  267 + </setting-item>
  268 + </template>
  269 + <n-button
  270 + style="float: right"
  271 + size="small"
  272 + @click="optionData.dataConfig.bar3D.push(cloneDeep(STATIC_SCATTER_CONFIG))"
  273 + >
  274 + +
  275 + </n-button>
  276 + </SettingItemBox>
133 277 </CollapseItem>
134 278 </template>
135 279
... ... @@ -140,6 +284,7 @@ import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
140 284 import { GlobalSetting } from '@/components/Pages/ChartItemSetting'
141 285 import SelectCity from './components/SelectCity.vue'
142 286 import { regionInfo } from './config'
  287 +import { cloneDeep } from 'lodash'
143 288
144 289 const props = defineProps({
145 290 optionData: {
... ... @@ -152,6 +297,17 @@ const seriesList = computed(() => {
152 297 return props.optionData.series
153 298 })
154 299
  300 +const STATIC_SCATTER_CONFIG = {
  301 + name: '',
  302 + value: [0, 0, 0],
  303 + adcode: 0,
  304 + height: 0,
  305 + itemStyle: {
  306 + color: '',
  307 + opacity: 1
  308 + }
  309 +}
  310 +
155 311 const symbolOption = ref([
156 312 {
157 313 label: 'circle',
... ...
1   -[
2   - {
3   - "name": "四川省",
4   - "value": [104.10068024609373, 30.580525329665175, 20000],
5   - "adcode": 510000,
6   - "height": 5,
7   - "itemStyle": {
8   - "color": "pink",
9   - "opacity": 1,
10   - "borderWidth": 0.4,
11   - "borderColor": "#5F9EA0"
  1 +{
  2 + "map3D": [
  3 + {
  4 + "name": "四川省",
  5 + "value": [
  6 + 104.10068024609373,
  7 + 30.580525329665175,
  8 + 20000
  9 + ],
  10 + "adcode": 510000,
  11 + "height": 5,
  12 + "itemStyle": {
  13 + "color": "green",
  14 + "opacity": 1,
  15 + "borderWidth": 0.4,
  16 + "borderColor": "#5F9EA0"
  17 + }
12 18 }
13   - },
14   - {
15   - "name": "湖南省",
16   - "value": [111.73068512890623, 27.86754509366569, 20000],
17   - "adcode": 430000,
18   - "height": 4,
19   - "itemStyle": {
20   - "color": "blue",
21   - "opacity": 1,
22   - "borderWidth": 0.4,
23   - "borderColor": "#5F9EA0"
  19 + ],
  20 + "scatter3D": [
  21 + {
  22 + "name": "广东省",
  23 + "value": [
  24 + 113.2592945,
  25 + 23.1301964,
  26 + 20000
  27 + ],
  28 + "adcode": 440000,
  29 + "height": 5,
  30 + "itemStyle": {
  31 + "color": "blue",
  32 + "opacity": 1,
  33 + "borderWidth": 0.4,
  34 + "borderColor": "#5F9EA0"
  35 + }
24 36 }
25   - },
26   - {
27   - "name": "吉林省",
28   - "value": [126.45236481640623, 43.7943407914815, 20000],
29   - "adcode": 220000,
30   - "height": 5,
31   - "itemStyle": {
32   - "color": "yellow",
33   - "opacity": 1,
34   - "borderWidth": 0.4,
35   - "borderColor": "#5F9EA0"
  37 + ],
  38 + "bar3D": [
  39 + {
  40 + "name": "安徽省",
  41 + "value": [
  42 + 114.878463,
  43 + 29.395191,
  44 + 20000
  45 + ],
  46 + "adcode": 340000,
  47 + "height": 5,
  48 + "itemStyle": {
  49 + "color": "red",
  50 + "opacity": 1,
  51 + "borderWidth": 0.4,
  52 + "borderColor": "#5F9EA0"
  53 + }
36 54 }
37   - },
38   - {
39   - "name": "山东省",
40   - "value": [118.67404450390623, 36.16387465872037, 20000],
41   - "adcode": 370000,
42   - "height": 6,
43   - "itemStyle": {
44   - "color": "orange",
45   - "opacity": 1,
46   - "borderWidth": 0.4,
47   - "borderColor": "#5F9EA0"
48   - }
49   - }
50   -]
  55 + ]
  56 +}
\ No newline at end of file
... ...
... ... @@ -14,7 +14,6 @@ import { registerMap } from 'echarts/core'
14 14 import 'echarts-gl'
15 15 import config, { areaEnum, dataPointI, optionType, historyParentType, backMapLevel } from './config'
16 16 import { getGeoJsonMap } from '@/api/external/common'
17   -import dataMaps from './data.json'
18 17
19 18 const props = defineProps({
20 19 chartConfig: {
... ... @@ -23,7 +22,8 @@ const props = defineProps({
23 22 }
24 23 })
25 24
26   -const backIcon = 'path://M853.333333 245.333333H245.333333l93.866667-93.866666c12.8-12.8 12.8-34.133333 0-46.933334-12.8-12.8-34.133333-12.8-46.933333 0l-145.066667 145.066667c-12.8 12.8-12.8 34.133333 0 46.933333l145.066667 145.066667c6.4 6.4 14.933333 10.666667 23.466666 10.666667s17.066667-4.266667 23.466667-10.666667c12.8-12.8 12.8-34.133333 0-46.933333L256 311.466667h597.333333c6.4 0 10.666667 4.266667 10.666667 10.666666v426.666667c0 6.4-4.266667 10.666667-10.666667 10.666667H170.666667c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h682.666666c40.533333 0 74.666667-34.133333 74.666667-74.666667V320c0-40.533333-34.133333-74.666667-74.666667-74.666667z'
  25 +const backIcon =
  26 + 'path://M853.333333 245.333333H245.333333l93.866667-93.866666c12.8-12.8 12.8-34.133333 0-46.933334-12.8-12.8-34.133333-12.8-46.933333 0l-145.066667 145.066667c-12.8 12.8-12.8 34.133333 0 46.933333l145.066667 145.066667c6.4 6.4 14.933333 10.666667 23.466666 10.666667s17.066667-4.266667 23.466667-10.666667c12.8-12.8 12.8-34.133333 0-46.933333L256 311.466667h597.333333c6.4 0 10.666667 4.266667 10.666667 10.666666v426.666667c0 6.4-4.266667 10.666667-10.666667 10.666667H170.666667c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h682.666666c40.533333 0 74.666667-34.133333 74.666667-74.666667V320c0-40.533333-34.133333-74.666667-74.666667-74.666667z'
27 27
28 28 const { w, h } = toRefs(props.chartConfig.attr)
29 29
... ... @@ -50,38 +50,39 @@ const toolBoxOption = ref({
50 50 }
51 51 })
52 52
53   -const excludeCountryLevels = ['PROVINCE','CITY'] //如果从右侧配置选择全中国
  53 +const excludeCountryLevels = ['PROVINCE', 'CITY'] //如果从右侧配置选择全中国
54 54
55 55 const includeCityLevels = ['CITY'] //如果从右侧配置选择省份
56 56
57 57 //元组 优化if elseif else分支 隐藏返回图标
58   -const backIconMappingLevels: any[][] =[
  58 +const backIconMappingLevels: any[][] = [
59 59 [
60   - (levelStr:string)=>levelStr===areaEnum.COUNTRY,
61   - (level:string)=>excludeCountryLevels.includes(level),
62   - ()=>toolBoxOption.value.feature.myFullButton.show=true,
63   - ()=>toolBoxOption.value.feature.myFullButton.show=false
  60 + (levelStr: string) => levelStr === areaEnum.COUNTRY,
  61 + (level: string) => excludeCountryLevels.includes(level),
  62 + () => (toolBoxOption.value.feature.myFullButton.show = true),
  63 + () => (toolBoxOption.value.feature.myFullButton.show = false)
64 64 ],
65 65 [
66   - (levelStr:string)=>levelStr===areaEnum.PROVINCE,
67   - (level:string)=>includeCityLevels.includes(level),
68   - ()=>toolBoxOption.value.feature.myFullButton.show=true,
69   - ()=>toolBoxOption.value.feature.myFullButton.show=false
70   - ],
  66 + (levelStr: string) => levelStr === areaEnum.PROVINCE,
  67 + (level: string) => includeCityLevels.includes(level),
  68 + () => (toolBoxOption.value.feature.myFullButton.show = true),
  69 + () => (toolBoxOption.value.feature.myFullButton.show = false)
  70 + ]
71 71 ]
72 72
73   -
74 73 watch(
75 74 () => props.chartConfig.option,
76   - (newData:optionType) => {
  75 + (newData: optionType) => {
77 76 const { iconColor, iconDistanceRight, iconDistanceTop, mapRegion } = newData
78   - const { saveSelect }=mapRegion
79   - const { levelStr }=saveSelect
80   - const findBackLevel = backIconMappingLevels.find((backLevelItem: backMapLevel[])=>backLevelItem[0](levelStr)) as backMapLevel[]
81   - if(findBackLevel){
82   - if(findBackLevel[0]){
  77 + const { saveSelect } = mapRegion
  78 + const { levelStr } = saveSelect
  79 + const findBackLevel = backIconMappingLevels.find((backLevelItem: backMapLevel[]) =>
  80 + backLevelItem[0](levelStr)
  81 + ) as backMapLevel[]
  82 + if (findBackLevel) {
  83 + if (findBackLevel[0]) {
83 84 const findLevel = findBackLevel[1](saveLevelStr.level)
84   - if(findLevel)findBackLevel[2]()
  85 + if (findLevel) findBackLevel[2]()
85 86 else findBackLevel[3]()
86 87 }
87 88 }
... ... @@ -161,7 +162,7 @@ const saveGeojson: Recordable = ref({}) // 保存geojson
161 162
162 163 const chinaDefaultRegionId = ref(100000) //如果是china则adcode为100000
163 164
164   -const saveLevelStr = reactive<{level:historyParentType["level"]}>({
  165 +const saveLevelStr = reactive<{ level: historyParentType['level'] }>({
165 166 // 地区级别
166 167 level: ''
167 168 })
... ... @@ -180,7 +181,7 @@ const getGeojson = (regionId: number | string) => {
180 181 const { geoJson, name, code, level } = res.data
181 182 const geoJsonFile = JSON.parse(geoJson)
182 183 if (!geoJsonFile) return
183   - saveGeojson.value = geoJsonFile//保存一份服务端返回的geojson
  184 + saveGeojson.value = geoJsonFile //保存一份服务端返回的geojson
184 185 const nameChina = name === '中国' ? 'china' : name
185 186 registerMap(level === areaEnum.COUNTRY ? nameChina : code, { geoJSON: geoJsonFile, specialAreas: {} })
186 187 show.value = false
... ... @@ -209,16 +210,6 @@ const getParentAdcode = (adcode: number) => {
209 210 return adcodeNum
210 211 }
211 212
212   -watch(
213   - () => w.value,
214   - (value: number) => {
215   - chartInstance.value.resize({
216   - width: value + 'px',
217   - height: h.value + 'px'
218   - })
219   - }
220   -)
221   -
222 213 const initMap = async () => {
223 214 chartInstance.value = echarts.init(map3DRef.value)
224 215 await nextTick()
... ... @@ -246,20 +237,41 @@ onMounted(() => {
246 237 initMap()
247 238 })
248 239
  240 +watch(
  241 + () => [w.value, h.value],
  242 + async (newValue: number[]) => {
  243 + await nextTick()
  244 + chartInstance.value.resize({
  245 + width: newValue.at(-2) + 'px',
  246 + height: newValue.at(-1) + 'px'
  247 + })
  248 + }
  249 +)
  250 +
249 251 //处理数据标点
250 252 const handleDataPoint = (newData: string | number) => {
251 253 if (newData === 'china') {
252   - props.chartConfig.option.dataset = dataMaps
  254 + props.chartConfig.option.dataset = props.chartConfig.option.dataConfig
253 255 props.chartConfig.option.series.forEach((item: Recordable) => {
254 256 if (item.type === 'scatter3D') {
255   - item.data = dataMaps
  257 + item.data = props.chartConfig.option.dataConfig['scatter3D']
  258 + }
  259 + if (item.type === 'bar3D') {
  260 + item.data = props.chartConfig.option.dataConfig['bar3D']
256 261 }
257 262 })
258 263 } else {
259   - props.chartConfig.option.dataset = dataMaps.filter((item: dataPointI) => item.adcode === newData)
  264 + props.chartConfig.option.dataset = props.chartConfig.option.dataConfig['map3D'].filter(
  265 + (item: dataPointI) => item.adcode === newData
  266 + )
260 267 props.chartConfig.option.series.forEach((item: Recordable) => {
261 268 if (item.type === 'scatter3D') {
262   - item.data = dataMaps.filter((item: dataPointI) => item.adcode === newData)
  269 + item.data = props.chartConfig.option.dataConfig['scatter3D'].filter(
  270 + (item: dataPointI) => item.adcode === newData
  271 + )
  272 + }
  273 + if (item.type === 'bar3D') {
  274 + item.data = props.chartConfig.option.dataConfig['bar3D'].filter((item: dataPointI) => item.adcode === newData)
263 275 }
264 276 })
265 277 }
... ... @@ -275,7 +287,7 @@ watch(
275 287 props.chartConfig.option.series.forEach((item: Recordable) => {
276 288 if (item.type === 'map3D') {
277 289 item.map = newData
278   - item.data = props.chartConfig.option.dataset
  290 + item.data = props.chartConfig.option.dataset['map3D']
279 291 }
280 292 })
281 293 handleSetOption(chartInstance.value, props.chartConfig.option)
... ... @@ -311,7 +323,7 @@ watch(
311 323 try {
312 324 props.chartConfig.option.series.forEach((item: Recordable) => {
313 325 if (item.type === 'map3D') {
314   - item.data = newData
  326 + item.data = newData['map3D']
315 327 }
316 328 })
317 329 handleSetOption(chartInstance.value, props.chartConfig.option)
... ...
  1 +<template>
  2 + <!-- 原生方式,没有使用vue-echarts -->
  3 + <n-space vertical>
  4 + <n-spin :show="show">
  5 + <div :style="`width:${w}px;height:${h}px;`" ref="map3DRef"></div>
  6 + </n-spin>
  7 + </n-space>
  8 +</template>
  9 +
  10 +<script setup lang="ts">
  11 +import { onMounted, ref, nextTick, PropType, toRefs, watch, reactive } from 'vue'
  12 +import * as echarts from 'echarts'
  13 +import { registerMap } from 'echarts/core'
  14 +import 'echarts-gl'
  15 +import config, { areaEnum, dataPointI, optionType, historyParentType, backMapLevel } from './config'
  16 +import { getGeoJsonMap } from '@/api/external/common'
  17 +
  18 +const props = defineProps({
  19 + chartConfig: {
  20 + type: Object as PropType<config>,
  21 + required: true
  22 + }
  23 +})
  24 +
  25 +const backIcon =
  26 + 'path://M853.333333 245.333333H245.333333l93.866667-93.866666c12.8-12.8 12.8-34.133333 0-46.933334-12.8-12.8-34.133333-12.8-46.933333 0l-145.066667 145.066667c-12.8 12.8-12.8 34.133333 0 46.933333l145.066667 145.066667c6.4 6.4 14.933333 10.666667 23.466666 10.666667s17.066667-4.266667 23.466667-10.666667c12.8-12.8 12.8-34.133333 0-46.933333L256 311.466667h597.333333c6.4 0 10.666667 4.266667 10.666667 10.666666v426.666667c0 6.4-4.266667 10.666667-10.666667 10.666667H170.666667c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h682.666666c40.533333 0 74.666667-34.133333 74.666667-74.666667V320c0-40.533333-34.133333-74.666667-74.666667-74.666667z'
  27 +
  28 +const { w, h } = toRefs(props.chartConfig.attr)
  29 +
  30 +const map3DRef = ref()
  31 +
  32 +const show = ref(true)
  33 +
  34 +const chartInstance = ref()
  35 +
  36 +const toolBoxOption = ref({
  37 + show: true,
  38 + right: 110,
  39 + top: 20,
  40 + feature: {
  41 + myFullButton: {
  42 + show: false,
  43 + title: '返回',
  44 + icon: backIcon,
  45 + iconStyle: {
  46 + color: ''
  47 + },
  48 + onclick: () => handleBack()
  49 + }
  50 + }
  51 +})
  52 +
  53 +const excludeCountryLevels = ['PROVINCE', 'CITY'] //如果从右侧配置选择全中国
  54 +
  55 +const includeCityLevels = ['CITY'] //如果从右侧配置选择省份
  56 +
  57 +//元组 优化if elseif else分支 隐藏返回图标
  58 +const backIconMappingLevels: any[][] = [
  59 + [
  60 + (levelStr: string) => levelStr === areaEnum.COUNTRY,
  61 + (level: string) => excludeCountryLevels.includes(level),
  62 + () => (toolBoxOption.value.feature.myFullButton.show = true),
  63 + () => (toolBoxOption.value.feature.myFullButton.show = false)
  64 + ],
  65 + [
  66 + (levelStr: string) => levelStr === areaEnum.PROVINCE,
  67 + (level: string) => includeCityLevels.includes(level),
  68 + () => (toolBoxOption.value.feature.myFullButton.show = true),
  69 + () => (toolBoxOption.value.feature.myFullButton.show = false)
  70 + ]
  71 +]
  72 +
  73 +watch(
  74 + () => props.chartConfig.option,
  75 + (newData: optionType) => {
  76 + const { iconColor, iconDistanceRight, iconDistanceTop, mapRegion } = newData
  77 + const { saveSelect } = mapRegion
  78 + const { levelStr } = saveSelect
  79 + const findBackLevel = backIconMappingLevels.find((backLevelItem: backMapLevel[]) =>
  80 + backLevelItem[0](levelStr)
  81 + ) as backMapLevel[]
  82 + if (findBackLevel) {
  83 + if (findBackLevel[0]) {
  84 + const findLevel = findBackLevel[1](saveLevelStr.level)
  85 + if (findLevel) findBackLevel[2]()
  86 + else findBackLevel[3]()
  87 + }
  88 + }
  89 + toolBoxOption.value.feature.myFullButton.iconStyle.color = iconColor //返回图标颜色
  90 + toolBoxOption.value.right = iconDistanceRight
  91 + toolBoxOption.value.top = iconDistanceTop
  92 + },
  93 + {
  94 + deep: true
  95 + }
  96 +)
  97 +
  98 +//追加echarts右上角自带toolbox
  99 +props.chartConfig.option = {
  100 + ...props.chartConfig.option,
  101 + ...{ toolbox: toolBoxOption.value }
  102 +}
  103 +
  104 +//地图点击返回
  105 +const handleBack = async () => {
  106 + stopWatch()
  107 + if (props.chartConfig.option.drillingIn) {
  108 + //如果是从右边配置里设置的,比如点击四川省,然后点击返回
  109 + const savePopParent = saveHistoryParent.value.pop()
  110 + let saveAdcode = savePopParent?.adcode as string | number
  111 + saveLevelStr.level = savePopParent?.level as string
  112 + if (!savePopParent) {
  113 + saveAdcode = getParentAdcode(props.chartConfig.option.mapRegion.adcode)
  114 + saveLevelStr.level = (regionMapParentArea as Recordable)[props.chartConfig.option.mapRegion.saveSelect.levelStr]
  115 + }
  116 + if (saveAdcode === 0) {
  117 + saveAdcode = 'china'
  118 + saveLevelStr.level = areaEnum.COUNTRY
  119 + }
  120 + const exist = await getGeojson(saveAdcode)
  121 + const adcode = saveAdcode === 100000 ? 'china' : saveAdcode
  122 + props.chartConfig.option.saveClickRegion.level = saveLevelStr.level
  123 + if (exist) {
  124 + //fix解决点击下钻返回后页面为空问题
  125 + props.chartConfig.option.mapRegion.adcode = adcode
  126 + }
  127 + }
  128 +}
  129 +
  130 +//地区上级对应配置
  131 +const regionMapParentArea = {
  132 + PROVINCE: areaEnum.COUNTRY, //省份的上一级 中国
  133 + CITY: areaEnum.PROVINCE, //城市的上一级 省份
  134 + COUNTY: areaEnum.CITY, //县或者区的上一级 城市
  135 + TOWN: areaEnum.COUNTY //镇的上一级 县或者区
  136 +}
  137 +
  138 +//地图点击
  139 +const handleMap3DClick = async (params: Recordable) => {
  140 + if (props.chartConfig.option.drillingIn) {
  141 + const { name } = params
  142 + saveGeojson.value?.features.forEach((item: Recordable) => {
  143 + if (item.properties.name === name) {
  144 + const level = item.properties.level.toUpperCase()
  145 + const adcode = item.properties.adcode
  146 + if (level === 'DISTRICT') return //下钻暂且不支持地区
  147 + if (String(adcode).startsWith('15') && level === areaEnum.CITY) return //特殊处理地区码15开头的
  148 + props.chartConfig.option.mapRegion.adcode = adcode
  149 + props.chartConfig.option.saveClickRegion.level = level
  150 + saveLevelStr.level = level
  151 + handleDataPoint(adcode)
  152 + saveHistoryParent.value.push({
  153 + adcode: item.properties.parent.adcode,
  154 + level: (regionMapParentArea as Recordable)[level]
  155 + })
  156 + }
  157 + })
  158 + }
  159 +}
  160 +
  161 +const saveGeojson: Recordable = ref({}) // 保存geojson
  162 +
  163 +const chinaDefaultRegionId = ref(100000) //如果是china则adcode为100000
  164 +
  165 +const saveLevelStr = reactive<{ level: historyParentType['level'] }>({
  166 + // 地区级别
  167 + level: ''
  168 +})
  169 +
  170 +const saveHistoryParent = ref<historyParentType[]>([])
  171 +
  172 +//动态注册地图
  173 +const getGeojson = (regionId: number | string) => {
  174 + try {
  175 + return new Promise<boolean>(resolve => {
  176 + const { levelStr } = props.chartConfig.option.mapRegion.saveSelect //右侧配置项获取的行政级别
  177 + getGeoJsonMap(
  178 + regionId === 'china' ? chinaDefaultRegionId.value : regionId,
  179 + !saveLevelStr.level ? levelStr : saveLevelStr.level //没有则获取右侧配置的行政级别
  180 + ).then(res => {
  181 + const { geoJson, name, code, level } = res.data
  182 + const geoJsonFile = JSON.parse(geoJson)
  183 + if (!geoJsonFile) return
  184 + saveGeojson.value = geoJsonFile //保存一份服务端返回的geojson
  185 + const nameChina = name === '中国' ? 'china' : name
  186 + registerMap(level === areaEnum.COUNTRY ? nameChina : code, { geoJSON: geoJsonFile, specialAreas: {} })
  187 + show.value = false
  188 + resolve(true)
  189 + })
  190 + })
  191 + } catch (error) {
  192 + show.value = false
  193 + console.error('注册地图出错', error)
  194 + //注册出错则注册空的,不然在选择正确的adcode,则视图无法更新
  195 + registerMap(props.chartConfig.option.mapRegion.adcode, { geoJSON: {} as any, specialAreas: {} })
  196 + }
  197 +}
  198 +
  199 +//异步时先注册空的 保证初始化不报错
  200 +registerMap(props.chartConfig.option.mapRegion.adcode, { geoJSON: {} as any, specialAreas: {} })
  201 +
  202 +//传adcode 获取上级
  203 +const getParentAdcode = (adcode: number) => {
  204 + let adcodeNum = 100000
  205 + saveGeojson.value?.features.forEach((item: Recordable) => {
  206 + if (item.properties.adcode === adcode) {
  207 + adcodeNum = item.properties.parent.adcode
  208 + }
  209 + })
  210 + return adcodeNum
  211 +}
  212 +
  213 +const initMap = async () => {
  214 + chartInstance.value = echarts.init(map3DRef.value)
  215 + await nextTick()
  216 + await getGeojson(props.chartConfig.option.mapRegion.adcode)
  217 + await nextTick().then(() => {
  218 + handleSetOption(chartInstance.value, props.chartConfig.option)
  219 + })
  220 + chartInstance.value.on('click', (e: Recordable) => {
  221 + handleMap3DClick(e)
  222 + })
  223 +}
  224 +
  225 +// 手动触发渲染
  226 +const handleSetOption = (instance: any, option: Recordable) => {
  227 + if (!instance) return
  228 + try {
  229 + instance.clear()
  230 + instance.setOption(option)
  231 + } catch (error) {
  232 + console.error('触发渲染出错', error)
  233 + }
  234 +}
  235 +
  236 +onMounted(() => {
  237 + initMap()
  238 +})
  239 +
  240 +watch(
  241 + () => [w.value, h.value],
  242 + async (newValue: number[]) => {
  243 + await nextTick()
  244 + chartInstance.value.resize({
  245 + width: newValue.at(-2) + 'px',
  246 + height: newValue.at(-1) + 'px'
  247 + })
  248 + }
  249 +)
  250 +
  251 +//处理数据标点
  252 +const handleDataPoint = (newData: string | number) => {
  253 + if (newData === 'china') {
  254 + props.chartConfig.option.dataset = props.chartConfig.option.dataConfig
  255 + props.chartConfig.option.series.forEach((item: Recordable) => {
  256 + if (item.type === 'scatter3D') {
  257 + item.data = props.chartConfig.option.dataConfig['scatter3D']
  258 + }
  259 + if (item.type === 'bar3D') {
  260 + item.data = props.chartConfig.option.dataConfig['bar3D']
  261 + }
  262 + })
  263 + } else {
  264 + props.chartConfig.option.dataset = props.chartConfig.option.dataConfig['map3D'].filter(
  265 + (item: dataPointI) => item.adcode === newData
  266 + )
  267 + props.chartConfig.option.series.forEach((item: Recordable) => {
  268 + if (item.type === 'scatter3D') {
  269 + item.data = props.chartConfig.option.dataConfig['scatter3D'].filter(
  270 + (item: dataPointI) => item.adcode === newData
  271 + )
  272 + }
  273 + if (item.type === 'bar3D') {
  274 + item.data = props.chartConfig.option.dataConfig['bar3D'].filter((item: dataPointI) => item.adcode === newData)
  275 + }
  276 + })
  277 + }
  278 +}
  279 +
  280 +//监听地图展示区域发生变化
  281 +watch(
  282 + () => `${props.chartConfig.option.mapRegion.adcode}`,
  283 + async (newData: string | number) => {
  284 + try {
  285 + await getGeojson(newData)
  286 + props.chartConfig.option.geo3D.map = newData
  287 + props.chartConfig.option.series.forEach((item: Recordable) => {
  288 + if (item.type === 'map3D') {
  289 + item.map = newData
  290 + item.data = props.chartConfig.option.dataset['map3D']
  291 + }
  292 + })
  293 + handleSetOption(chartInstance.value, props.chartConfig.option)
  294 + handleDataPoint(newData)
  295 + } catch (error) {
  296 + console.log('展示区域发生变化出错', error)
  297 + }
  298 + },
  299 + {
  300 + immediate: true
  301 + }
  302 +)
  303 +
  304 +// 监听地图右侧配置项变化
  305 +const stopWatch = watch(
  306 + props.chartConfig.option,
  307 + async newData => {
  308 + try {
  309 + handleSetOption(chartInstance.value, newData)
  310 + } catch (error) {
  311 + console.log(error)
  312 + }
  313 + },
  314 + {
  315 + deep: true
  316 + }
  317 +)
  318 +
  319 +// 监听地图dataset配置项变化
  320 +watch(
  321 + () => props.chartConfig.option.dataset,
  322 + newData => {
  323 + try {
  324 + props.chartConfig.option.series.forEach((item: Recordable) => {
  325 + if (item.type === 'map3D') {
  326 + item.data = newData['map3D']
  327 + }
  328 + })
  329 + handleSetOption(chartInstance.value, props.chartConfig.option)
  330 + } catch (error) {
  331 + console.log(error)
  332 + }
  333 + },
  334 + {
  335 + deep: true
  336 + }
  337 +)
  338 +</script>
... ...
... ... @@ -27,7 +27,6 @@ import { getDeviceActiveTime } from '@/api/external/common/index'
27 27 import dayjs from 'dayjs'
28 28 import DeviceLatestTable from './components/DeviceLatestTable.vue'
29 29 import { getDeviceLatest, getProfileAttrs } from '@/api/external/common'
30   -import { NButton } from 'naive-ui'
31 30
32 31 const props = defineProps({
33 32 chartConfig: {
... ...
... ... @@ -8,7 +8,6 @@ export const option = {
8 8 dataset: '',
9 9 attribute: {
10 10 bgColor1:'#00e0db',
11   - bgColor2:'#66ffff',
12 11 }
13 12 }
14 13
... ...
... ... @@ -8,14 +8,6 @@
8 8 <n-button size="small" @click="optionData.attribute.bgColor1 = '#00e0db'"> 恢复默认 </n-button>
9 9 </SettingItem>
10 10 </SettingItemBox>
11   - <SettingItemBox :name="`装饰2`">
12   - <SettingItem name="颜色">
13   - <n-color-picker size="small" :modes="['hex']" v-model:value="optionData.attribute.bgColor2"></n-color-picker>
14   - </SettingItem>
15   - <SettingItem>
16   - <n-button size="small" @click="optionData.attribute.bgColor2 = '#66ffff'"> 恢复默认 </n-button>
17   - </SettingItem>
18   - </SettingItemBox>
19 11 </CollapseItem>
20 12 </template>
21 13
... ...
... ... @@ -32,7 +32,6 @@
32 32 <path
33 33 id="矩形"
34 34 fill-rule="evenodd"
35   - :style="{fill: attribute.bgColor2}"
36 35 opacity="0"
37 36 d="M0 87.26L87.26 87.26L87.26 0L0 0L0 87.26Z"
38 37 />
... ...
  1 +import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
  2 +import { Decorates13Config } from './index'
  3 +import { CreateComponentType } from '@/packages/index.d'
  4 +import cloneDeep from 'lodash/cloneDeep'
  5 +
  6 +export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
  7 +
  8 +export const option = {
  9 + dataset: 66,
  10 + unitStr: '人',
  11 + grid: {
  12 + top: 200,
  13 + bottom: 300
  14 + },
  15 + xAxis: {
  16 + data: [],
  17 + axisTick: {
  18 + show: false
  19 + },
  20 + axisLine: {
  21 + show: false
  22 + }
  23 + },
  24 + yAxis: {
  25 + splitLine: {
  26 + show: false
  27 + },
  28 + axisTick: {
  29 + show: false
  30 + },
  31 + axisLine: {
  32 + show: false
  33 + },
  34 + axisLabel: {
  35 + show: false
  36 + }
  37 + },
  38 + series: [
  39 + {
  40 + name: '',
  41 + type: 'pictorialBar',
  42 + symbolSize: [100, 45],
  43 + symbolOffset: [-10, -20],
  44 + z: 12,
  45 + data: [
  46 + {
  47 + name: '',
  48 + value: 66,
  49 + symbolPosition: 'end',
  50 + itemStyle: {
  51 + normal: {
  52 + color: 'rgba(2, 163, 243,0.5)' //圆柱顶部颜色
  53 + }
  54 + }
  55 + }
  56 + ]
  57 + },
  58 + {
  59 + name: '',
  60 + type: 'pictorialBar',
  61 + symbolSize: [100, 45],
  62 + symbolOffset: [-10, 24],
  63 + z: 12,
  64 + data: [
  65 + {
  66 + name: '',
  67 + value: 66,
  68 + itemStyle: {
  69 + normal: {
  70 + color: 'rgba(2, 163, 243, 1)' //圆柱底部颜色
  71 + }
  72 + }
  73 + }
  74 + ]
  75 + },
  76 + {
  77 + type: 'bar',
  78 + barWidth: 100,
  79 + data: [
  80 + {
  81 + name: '',
  82 + value: 66,
  83 + label: {
  84 + normal: {
  85 + show: true,
  86 + formatter: '{c}' + '人',
  87 + position: 'top',
  88 + textStyle: {
  89 + color: 'rgba(2, 163, 243, 1)', //柱子对应数值颜色
  90 + fontSize: 40,
  91 + fontWeight: 600
  92 + }
  93 + }
  94 + },
  95 + itemStyle: {
  96 + normal: {
  97 + color: {
  98 + x: 0,
  99 + y: 0,
  100 + x2: 0,
  101 + y2: 1,
  102 + type: 'linear',
  103 + global: false,
  104 + colorStops: [
  105 + {
  106 + offset: 0,
  107 + color: 'rgba(18, 246, 255, 0)'
  108 + },
  109 + {
  110 + offset: 1,
  111 + color: 'rgba(2, 163, 243, 1)' //底部渐变颜色
  112 + }
  113 + ]
  114 + }
  115 + }
  116 + }
  117 + }
  118 + ]
  119 + },
  120 + //往上是内部柱状图
  121 + //往下是外部柱状图
  122 + {
  123 + name: '',
  124 + type: 'pictorialBar',
  125 + symbolSize: [340, 45],
  126 + symbolOffset: [-10, -20],
  127 + z: 12,
  128 + data: [
  129 + {
  130 + name: '',
  131 + value: '100',
  132 + symbolPosition: 'end',
  133 + itemStyle: {
  134 + normal: {
  135 + color: 'rgba(0, 255, 136, 0)' //圆柱顶部颜色
  136 + }
  137 + }
  138 + }
  139 + ]
  140 + },
  141 + {
  142 + name: '',
  143 + type: 'pictorialBar',
  144 + symbolSize: [150, 75],
  145 + symbolOffset: [-10, 41],
  146 + z: 12,
  147 + data: [
  148 + {
  149 + name: '',
  150 + value: '100',
  151 + itemStyle: {
  152 + normal: {
  153 + color: 'rgba(2, 163, 243, .1)' //圆柱底部颜色
  154 + }
  155 + }
  156 + }
  157 + ]
  158 + },
  159 + {
  160 + name: '',
  161 + type: 'pictorialBar',
  162 + symbolSize: [150, 75],
  163 + symbolOffset: [-10, 55],
  164 + z: 11,
  165 + data: [
  166 + {
  167 + name: '',
  168 + value: '100',
  169 + itemStyle: {
  170 + normal: {
  171 + color: 'transparent',
  172 + borderColor: 'rgba(2, 163, 243, 1)', //底部内圆圈颜色
  173 + borderWidth: 30
  174 + }
  175 + }
  176 + }
  177 + ]
  178 + },
  179 + {
  180 + name: '',
  181 + type: 'pictorialBar',
  182 + symbolSize: [200, 100],
  183 + symbolOffset: [-10, 62],
  184 + z: 10,
  185 + data: [
  186 + {
  187 + name: '关井数',
  188 + value: '100',
  189 + itemStyle: {
  190 + normal: {
  191 + color: 'transparent',
  192 + borderColor: 'rgba(2, 163, 243, 1)', //底部外圆圈颜色
  193 + borderType: 'dashed',
  194 + borderWidth: 2
  195 + }
  196 + }
  197 + }
  198 + ]
  199 + },
  200 + {
  201 + type: 'bar',
  202 + silent: true,
  203 + barWidth: 140,
  204 + barGap: '-120%',
  205 + data: [
  206 + {
  207 + name: '',
  208 + value: '100',
  209 + label: {
  210 + normal: {
  211 + show: false
  212 + }
  213 + },
  214 + itemStyle: {
  215 + normal: {
  216 + color: {
  217 + x: 1,
  218 + y: 1,
  219 + x2: 1,
  220 + y2: 0,
  221 + type: 'linear',
  222 + global: false,
  223 + colorStops: [
  224 + {
  225 + offset: 0,
  226 + color: 'rgba(0, 255, 136, 0)'
  227 + },
  228 + {
  229 + offset: 0.3,
  230 + color: 'rgba(0, 255, 136, .1)'
  231 + },
  232 + {
  233 + offset: 0.5,
  234 + color: 'rgba(0, 255, 136, .1)'
  235 + },
  236 + {
  237 + offset: 0.8,
  238 + color: 'rgba(0, 255, 136, .1)'
  239 + },
  240 + {
  241 + offset: 1,
  242 + color: 'rgba(0, 255, 136, 0)' //底部渐变颜色
  243 + }
  244 + ]
  245 + }
  246 + }
  247 + }
  248 + }
  249 + ]
  250 + }
  251 + ]
  252 +}
  253 +
  254 +export default class Config extends PublicConfigClass implements CreateComponentType {
  255 + public key: string = Decorates13Config.key
  256 + public chartConfig = cloneDeep(Decorates13Config)
  257 + // 图表配置项
  258 + public option = echartOptionProfixHandle(option, includes)
  259 +}
... ...
  1 +<template>
  2 + <!-- Echarts 全局设置 -->
  3 + <global-setting :optionData="optionData"></global-setting>
  4 + <CollapseItem name="配置" :expanded="true">
  5 + <setting-item-box name="数据点配置">
  6 + <setting-item name="数据">
  7 + <n-input-number v-model:value="optionData.dataset"></n-input-number>
  8 + </setting-item>
  9 + <setting-item name="单位">
  10 + <n-input v-model:value="optionData.unitStr"></n-input>
  11 + </setting-item>
  12 + </setting-item-box>
  13 + <setting-item-box name="grid配置">
  14 + <setting-item name="顶部">
  15 + <n-input-number v-model:value="optionData.grid.top"></n-input-number>
  16 + </setting-item>
  17 + <setting-item name="底部">
  18 + <n-input-number v-model:value="optionData.grid.bottom"></n-input-number>
  19 + </setting-item>
  20 + </setting-item-box>
  21 + <setting-item-box name="内部圆柱">
  22 + <setting-item name="顶部颜色">
  23 + <n-color-picker size="small" v-model:value="seriesList[0].data[0].itemStyle.normal.color"></n-color-picker>
  24 + </setting-item>
  25 + <setting-item name="底部颜色">
  26 + <n-color-picker size="small" v-model:value="seriesList[1].data[0].itemStyle.normal.color"></n-color-picker>
  27 + </setting-item>
  28 + <setting-item name="数字颜色">
  29 + <n-color-picker
  30 + size="small"
  31 + v-model:value="seriesList[2].data[0].label.normal.textStyle.color"
  32 + ></n-color-picker>
  33 + </setting-item>
  34 + <setting-item name="底部渐变色1">
  35 + <n-color-picker
  36 + size="small"
  37 + v-model:value="seriesList[2].data[0].itemStyle.normal.color.colorStops[0].color"
  38 + ></n-color-picker>
  39 + </setting-item>
  40 + <setting-item name="底部渐变色1">
  41 + <n-color-picker
  42 + size="small"
  43 + v-model:value="seriesList[2].data[0].itemStyle.normal.color.colorStops[1].color"
  44 + ></n-color-picker>
  45 + </setting-item>
  46 + </setting-item-box>
  47 + <setting-item-box name="外部圆柱">
  48 + <setting-item name="顶部颜色">
  49 + <n-color-picker size="small" v-model:value="seriesList[3].data[0].itemStyle.normal.color"></n-color-picker>
  50 + </setting-item>
  51 + <setting-item name="底部颜色">
  52 + <n-color-picker size="small" v-model:value="seriesList[4].data[0].itemStyle.normal.color"></n-color-picker>
  53 + </setting-item>
  54 + <setting-item name="底部内圆圈颜色">
  55 + <n-color-picker
  56 + size="small"
  57 + v-model:value="seriesList[5].data[0].itemStyle.normal.borderColor"
  58 + ></n-color-picker>
  59 + </setting-item>
  60 + <setting-item name="底部外圆圈颜色">
  61 + <n-color-picker
  62 + size="small"
  63 + v-model:value="seriesList[6].data[0].itemStyle.normal.borderColor"
  64 + ></n-color-picker>
  65 + </setting-item>
  66 + <setting-item name="底部渐变色1">
  67 + <n-color-picker
  68 + size="small"
  69 + v-model:value="seriesList[7].data[0].itemStyle.normal.color.colorStops[0].color"
  70 + ></n-color-picker>
  71 + </setting-item>
  72 + <setting-item name="底部渐变色2">
  73 + <n-color-picker
  74 + size="small"
  75 + v-model:value="seriesList[7].data[0].itemStyle.normal.color.colorStops[1].color"
  76 + ></n-color-picker>
  77 + </setting-item>
  78 + <setting-item name="底部渐变色3">
  79 + <n-color-picker
  80 + size="small"
  81 + v-model:value="seriesList[7].data[0].itemStyle.normal.color.colorStops[2].color"
  82 + ></n-color-picker>
  83 + </setting-item>
  84 + <setting-item name="底部渐变色4">
  85 + <n-color-picker
  86 + size="small"
  87 + v-model:value="seriesList[7].data[0].itemStyle.normal.color.colorStops[3].color"
  88 + ></n-color-picker>
  89 + </setting-item>
  90 + <setting-item name="底部渐变色5">
  91 + <n-color-picker
  92 + size="small"
  93 + v-model:value="seriesList[7].data[0].itemStyle.normal.color.colorStops[4].color"
  94 + ></n-color-picker>
  95 + </setting-item>
  96 + </setting-item-box>
  97 + </CollapseItem>
  98 +</template>
  99 +
  100 +<script setup lang="ts">
  101 +import { PropType, computed } from 'vue'
  102 +import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
  103 +import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
  104 +
  105 +const props = defineProps({
  106 + optionData: {
  107 + type: Object as PropType<GlobalThemeJsonType> & PropType<any>,
  108 + required: true
  109 + }
  110 +})
  111 +
  112 +const seriesList = computed(() => {
  113 + return props.optionData.series
  114 +})
  115 +</script>
... ...
  1 +import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
  2 +import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
  3 +import { useWidgetKey } from '@/packages/external/useWidgetKey'
  4 +
  5 +const { key, chartKey, conKey } = useWidgetKey('Decorates13',true)
  6 +
  7 +export const Decorates13Config: ConfigType = {
  8 + key,
  9 + chartKey,
  10 + conKey,
  11 + title: '装饰13',
  12 + category: ChatCategoryEnum.DECORATE,
  13 + categoryName: ChatCategoryEnumName.DECORATE,
  14 + package: PackagesCategoryEnum.DECORATES,
  15 + chartFrame: ChartFrameEnum.COMMON,
  16 + image: 'decorates13.png',
  17 +}
... ...
  1 +<template>
  2 + <v-chart :theme="themeColor" :init-options="initOptions" :option="option.value" autoresize> </v-chart>
  3 +</template>
  4 +
  5 +<script setup lang="ts">
  6 +import { PropType, watch, reactive } from 'vue'
  7 +import VChart from 'vue-echarts'
  8 +import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
  9 +import { use } from 'echarts/core'
  10 +import { CanvasRenderer } from 'echarts/renderers'
  11 +import { LineChart } from 'echarts/charts'
  12 +import config, { includes } from './config'
  13 +import { mergeTheme } from '@/packages/public/chart'
  14 +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  15 +import { useChartDataFetch } from '@/hooks'
  16 +import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
  17 +
  18 +const props = defineProps({
  19 + themeSetting: {
  20 + type: Object,
  21 + required: true
  22 + },
  23 + themeColor: {
  24 + type: Object,
  25 + required: true
  26 + },
  27 + chartConfig: {
  28 + type: Object as PropType<config>,
  29 + required: true
  30 + }
  31 +})
  32 +
  33 +const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
  34 +
  35 +use([DatasetComponent, CanvasRenderer, LineChart, GridComponent, TooltipComponent, LegendComponent])
  36 +
  37 +const option = reactive({
  38 + value: {}
  39 +})
  40 +
  41 +const dataHandle = (newData: number) => {
  42 + let config = props.chartConfig.option
  43 + config.series[2].data[0].value = newData
  44 + config.series[2].data[0].label.normal.formatter = '{c}' + config.unitStr
  45 + option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
  46 + option.value = { ...props.chartConfig.option, ...config }
  47 +}
  48 +
  49 +// 配置时
  50 +watch(
  51 + () => props.chartConfig.option.dataset,
  52 + (newData: number) => {
  53 + try {
  54 + dataHandle(newData)
  55 + } catch (error) {
  56 + console.log(error)
  57 + }
  58 + },
  59 + {
  60 + immediate: true,
  61 + }
  62 +)
  63 +// 预览时
  64 +useChartDataFetch(props.chartConfig, useChartEditStore, (resData: number) => {
  65 + // @ts-ignore
  66 + option.value.series[2].data[0].value = resData
  67 +})
  68 +</script>
... ...
  1 +import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
  2 +import { Decorates14Config } from './index'
  3 +import { CreateComponentType } from '@/packages/index.d'
  4 +import cloneDeep from 'lodash/cloneDeep'
  5 +
  6 +export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
  7 +
  8 +const ydata = ['A2'] //y轴
  9 +
  10 +export const option = {
  11 + dataset: 60,
  12 + backgroundColor: 'rgba(0,0,0,1)',
  13 + grid: {
  14 + left: '10%',
  15 + top: 10,
  16 + bottom: 10
  17 + },
  18 + tooltip: {
  19 + show: false
  20 + },
  21 + xAxis: {
  22 + max: 100,
  23 + splitLine: {
  24 + show: false
  25 + },
  26 + axisLine: {
  27 + show: false
  28 + },
  29 + axisLabel: {
  30 + show: false
  31 + },
  32 + axisTick: {
  33 + show: false
  34 + }
  35 + },
  36 + yAxis: [
  37 + {
  38 + type: 'category',
  39 + inverse: false,
  40 + data: ydata,
  41 + axisLine: {
  42 + show: false
  43 + },
  44 + axisTick: {
  45 + show: false
  46 + },
  47 + axisLabel: {
  48 + show: false
  49 + }
  50 + }
  51 + ],
  52 + series: [
  53 + {
  54 + //内
  55 + type: 'bar',
  56 + barWidth: 60,
  57 + legendHoverLink: false,
  58 + silent: true,
  59 + itemStyle: {
  60 + color: {
  61 + type: 'linear',
  62 + x: 0,
  63 + y: 0,
  64 + x2: 1,
  65 + y2: 0,
  66 + colorStops: [
  67 + {
  68 + offset: 0,
  69 + color: 'rgba(156,224,99,1)' // 0% 处的颜色
  70 + },
  71 + {
  72 + offset: 1,
  73 + color: 'rgba(12,245,243,1)' // 100% 处的颜色
  74 + }
  75 + ],
  76 + globalCoord: false // 缺省为 false
  77 + } //底色
  78 + },
  79 + label: {
  80 + normal: {
  81 + show: true,
  82 + textStyle: {
  83 + color: '#fff',
  84 + fontSize: 20
  85 + },
  86 + position: 'right',
  87 + formatter: function (params: Recordable) {
  88 + return '{white|' + params.value + '}'
  89 + },
  90 + verticalAlign: 'bottom',
  91 + rich: {
  92 + white: {
  93 + // backgroundColor: {
  94 + // image:
  95 + // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADYAAAAZCAYAAAB6v90+AAAA2klEQVRYhe2YMUoDQRhG32zAwsKkyRGCHmE9hE3uuSkNSqogaOEBcgzXDVg+i2xhEdKYn2GWefDX33vlDCjoCu3QHrXQ68eGFUpC74EPYME0+ALahHbAOrfNldkktAfucptcmWNCzW0RQZNbIIoaVho1rDRqWGnUsNKoYaUx6bDv3BIBHBtgl9sigNeEPgDvTOsF/dgAB6AFNsCQVel/DJwaWuDA+JkTcTfo9sLnS4fOwvYDw0Bv0f2ZqJcxPG47OAx0jn7+iXobg0N306kunCXwDPwAT0AfPfgLAvYRIEVmrDQAAAAASUVORK5CYII='
  96 + // },
  97 + padding: [5, 0, 5, 5],
  98 + align: 'center',
  99 + fontSize: 16,
  100 + color: 'black'
  101 + }
  102 + }
  103 + }
  104 + },
  105 + data: [60],
  106 + z: 100
  107 + },
  108 + {
  109 + //外
  110 + type: 'bar',
  111 + barWidth: 61,
  112 + barGap: '-100%',
  113 + label: {
  114 + normal: {
  115 + show: false
  116 + }
  117 + },
  118 + legendHoverLink: false,
  119 + silent: true,
  120 + data: [100],
  121 + itemStyle: {
  122 + color: 'rgba(45, 46, 48,0.5)',
  123 + borderWidth: 1,
  124 + borderColor: '#fff'
  125 + },
  126 + z: 98
  127 + },
  128 + {
  129 + //分隔
  130 + type: 'pictorialBar',
  131 + animationDuration: 0,
  132 + itemStyle: {
  133 + color: 'rgba(0,0,0,0.7)'
  134 + },
  135 + symbolRepeat: 'fixed',
  136 + symbolMargin: '8',
  137 + symbol: 'rect',
  138 + symbolClip: true,
  139 + symbolSize: [4, 60],
  140 + symbolPosition: 'start',
  141 + symbolOffset: [0, 0],
  142 + data: [60],
  143 + z: 101
  144 + }
  145 + ]
  146 +}
  147 +
  148 +export default class Config extends PublicConfigClass implements CreateComponentType {
  149 + public key: string = Decorates14Config.key
  150 + public chartConfig = cloneDeep(Decorates14Config)
  151 + // 图表配置项
  152 + public option = echartOptionProfixHandle(option, includes)
  153 +}
... ...
  1 +<template>
  2 + <!-- Echarts 全局设置 -->
  3 + <global-setting :optionData="optionData"></global-setting>
  4 + <CollapseItem name="配置" :expanded="true">
  5 + <setting-item-box name="数据点配置">
  6 + <setting-item name="数据">
  7 + <n-input-number v-model:value="optionData.dataset"></n-input-number>
  8 + </setting-item>
  9 + </setting-item-box>
  10 + <setting-item-box name="grid配置">
  11 + <setting-item name="顶部">
  12 + <n-input-number v-model:value="optionData.grid.top"></n-input-number>
  13 + </setting-item>
  14 + <setting-item name="底部">
  15 + <n-input-number v-model:value="optionData.grid.bottom"></n-input-number>
  16 + </setting-item>
  17 + </setting-item-box>
  18 + <setting-item-box name="内外bar和中间分隔高度">
  19 + <setting-item name="内">
  20 + <n-input-number v-model:value="seriesList[0].barWidth"></n-input-number>
  21 + </setting-item>
  22 + <setting-item name="外">
  23 + <n-input-number v-model:value="seriesList[1].barWidth"></n-input-number>
  24 + </setting-item>
  25 + <setting-item name="分隔">
  26 + <n-input-number v-model:value="seriesList[2].symbolSize[1]"></n-input-number>
  27 + </setting-item>
  28 + </setting-item-box>
  29 + <setting-item-box name="数值">
  30 + <setting-item name="颜色">
  31 + <n-color-picker v-model:value="seriesList[0].label.normal.rich.white.color"></n-color-picker>
  32 + </setting-item>
  33 + <setting-item name="大小">
  34 + <n-input-number v-model:value="seriesList[0].label.normal.rich.white.fontSize"></n-input-number>
  35 + </setting-item>
  36 + </setting-item-box>
  37 + <setting-item-box name="内部bar">
  38 + <setting-item name="渐变色1">
  39 + <n-color-picker size="small" v-model:value="seriesList[0].itemStyle.color.colorStops[0].color"></n-color-picker>
  40 + </setting-item>
  41 + <setting-item name="渐变色2">
  42 + <n-color-picker size="small" v-model:value="seriesList[0].itemStyle.color.colorStops[1].color"></n-color-picker>
  43 + </setting-item>
  44 + </setting-item-box>
  45 + <setting-item-box name="外部bar">
  46 + <setting-item name="颜色">
  47 + <n-color-picker size="small" v-model:value="seriesList[1].itemStyle.color"></n-color-picker>
  48 + </setting-item>
  49 + </setting-item-box>
  50 + <setting-item-box name="分隔">
  51 + <setting-item name="颜色">
  52 + <n-color-picker size="small" v-model:value="seriesList[2].itemStyle.color"></n-color-picker>
  53 + </setting-item>
  54 + </setting-item-box>
  55 + </CollapseItem>
  56 +</template>
  57 +
  58 +<script setup lang="ts">
  59 +import { PropType, computed } from 'vue'
  60 +import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
  61 +import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
  62 +
  63 +const props = defineProps({
  64 + optionData: {
  65 + type: Object as PropType<GlobalThemeJsonType> & PropType<any>,
  66 + required: true
  67 + }
  68 +})
  69 +
  70 +const seriesList = computed(() => {
  71 + return props.optionData.series
  72 +})
  73 +</script>
... ...
  1 +import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
  2 +import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
  3 +import { useWidgetKey } from '@/packages/external/useWidgetKey'
  4 +
  5 +const { key, chartKey, conKey } = useWidgetKey('Decorates14',true)
  6 +
  7 +export const Decorates14Config: ConfigType = {
  8 + key,
  9 + chartKey,
  10 + conKey,
  11 + title: '装饰14',
  12 + category: ChatCategoryEnum.DECORATE,
  13 + categoryName: ChatCategoryEnumName.DECORATE,
  14 + package: PackagesCategoryEnum.DECORATES,
  15 + chartFrame: ChartFrameEnum.COMMON,
  16 + image: 'decorates13.png',
  17 +}
... ...
  1 +<template>
  2 + <v-chart :theme="themeColor" :init-options="initOptions" :option="option.value" autoresize> </v-chart>
  3 +</template>
  4 +
  5 +<script setup lang="ts">
  6 +import { PropType, watch, reactive, onMounted } from 'vue'
  7 +import VChart from 'vue-echarts'
  8 +import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
  9 +import { use } from 'echarts/core'
  10 +import { CanvasRenderer } from 'echarts/renderers'
  11 +import { LineChart } from 'echarts/charts'
  12 +import config, { includes } from './config'
  13 +import { mergeTheme } from '@/packages/public/chart'
  14 +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  15 +import { useChartDataFetch } from '@/hooks'
  16 +import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
  17 +
  18 +const props = defineProps({
  19 + themeSetting: {
  20 + type: Object,
  21 + required: true
  22 + },
  23 + themeColor: {
  24 + type: Object,
  25 + required: true
  26 + },
  27 + chartConfig: {
  28 + type: Object as PropType<config>,
  29 + required: true
  30 + }
  31 +})
  32 +
  33 +const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
  34 +
  35 +use([DatasetComponent, CanvasRenderer, LineChart, GridComponent, TooltipComponent, LegendComponent])
  36 +
  37 +const option = reactive<{ value: Recordable }>({
  38 + value: {}
  39 +})
  40 +
  41 +onMounted(() => {
  42 + option.value = { ...props.chartConfig.option }
  43 +})
  44 +
  45 +const dataHandle = (newData: number) => {
  46 + let config = props.chartConfig.option
  47 + config.series[0].data = [newData]
  48 + config.series[2].data = [newData]
  49 + option.value = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
  50 + option.value = { ...props.chartConfig.option, ...config }
  51 +}
  52 +
  53 +// 配置时
  54 +watch(
  55 + () => props.chartConfig.option.dataset,
  56 + (newData: number) => {
  57 + try {
  58 + dataHandle(newData)
  59 + } catch (error) {
  60 + console.log(error)
  61 + }
  62 + },
  63 + {
  64 + immediate: true
  65 + }
  66 +)
  67 +// 预览时
  68 +useChartDataFetch(props.chartConfig, useChartEditStore, (resData: number) => {
  69 + option.value.series[0].data = [resData]
  70 + option.value.series[2].data = [resData]
  71 +})
  72 +</script>
... ...
  1 +import { PublicConfigClass } from '@/packages/public'
  2 +import { Decorates15Config } from './index'
  3 +import { CreateComponentType } from '@/packages/index.d'
  4 +import cloneDeep from 'lodash/cloneDeep'
  5 +import { chartInitConfig } from '@/settings/designSetting'
  6 +export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
  7 +
  8 +export const option = {
  9 + styleConfig: {
  10 + scale: 1
  11 + }
  12 +}
  13 +
  14 +export default class Config extends PublicConfigClass implements CreateComponentType {
  15 + public key = Decorates15Config.key
  16 + public attr = { ...chartInitConfig, w: 300, h: 300, zIndex: -1 }
  17 + public chartConfig = cloneDeep(Decorates15Config)
  18 + public option = cloneDeep(option)
  19 +}
... ...
  1 +<template>
  2 + <!-- Echarts 全局设置 -->
  3 + <global-setting :optionData="optionData"></global-setting>
  4 + <CollapseItem name="配置" :expanded="true">
  5 + <setting-item-box name="样式配置">
  6 + <setting-item name="缩放">
  7 + <n-input-number :min="0" v-model:value="optionData.styleConfig.scale"></n-input-number>
  8 + </setting-item>
  9 + </setting-item-box>
  10 + </CollapseItem>
  11 +</template>
  12 +
  13 +<script setup lang="ts">
  14 +import { PropType } from 'vue'
  15 +import { option } from './config'
  16 +import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
  17 +
  18 +defineProps({
  19 + optionData: {
  20 + type: Object as PropType<typeof option>,
  21 + required: true
  22 + }
  23 +})
  24 +</script>
... ...
  1 +import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
  2 +import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
  3 +import { useWidgetKey } from '@/packages/external/useWidgetKey'
  4 +
  5 +const { key, chartKey, conKey } = useWidgetKey('Decorates15',true)
  6 +
  7 +export const Decorates15Config: ConfigType = {
  8 + key,
  9 + chartKey,
  10 + conKey,
  11 + title: '装饰15',
  12 + category: ChatCategoryEnum.DECORATE,
  13 + categoryName: ChatCategoryEnumName.DECORATE,
  14 + package: PackagesCategoryEnum.DECORATES,
  15 + chartFrame: ChartFrameEnum.COMMON,
  16 + image: 'decorates13.png',
  17 +}
... ...
  1 +<template>
  2 + <div style="position: fixed" :style="{ width: `${w}px`, height: `${h}px` }">
  3 + <div :style="{ transform: `scale(${styleConfig.scale})` }" class="arc_reactor">
  4 + <div class="case_container">
  5 + <div class="e7">
  6 + <div class="semi_arc_3 e5_1">
  7 + <div class="semi_arc_3 e5_2">
  8 + <div class="semi_arc_3 e5_3">
  9 + <div class="semi_arc_3 e5_4"></div>
  10 + </div>
  11 + </div>
  12 + </div>
  13 + <div class="core2"></div>
  14 + </div>
  15 + <ul class="marks">
  16 + <li></li>
  17 + <li></li>
  18 + <li></li>
  19 + <li></li>
  20 + <li></li>
  21 + <li></li>
  22 + <li></li>
  23 + <li></li>
  24 + <li></li>
  25 + <li></li>
  26 + <li></li>
  27 + <li></li>
  28 + <li></li>
  29 + <li></li>
  30 + <li></li>
  31 + <li></li>
  32 + <li></li>
  33 + <li></li>
  34 + <li></li>
  35 + <li></li>
  36 + <li></li>
  37 + <li></li>
  38 + <li></li>
  39 + <li></li>
  40 + <li></li>
  41 + <li></li>
  42 + <li></li>
  43 + <li></li>
  44 + <li></li>
  45 + <li></li>
  46 + <li></li>
  47 + <li></li>
  48 + <li></li>
  49 + <li></li>
  50 + <li></li>
  51 + <li></li>
  52 + <li></li>
  53 + <li></li>
  54 + <li></li>
  55 + <li></li>
  56 + <li></li>
  57 + <li></li>
  58 + <li></li>
  59 + <li></li>
  60 + <li></li>
  61 + <li></li>
  62 + <li></li>
  63 + <li></li>
  64 + <li></li>
  65 + <li></li>
  66 + <li></li>
  67 + <li></li>
  68 + <li></li>
  69 + <li></li>
  70 + <li></li>
  71 + <li></li>
  72 + <li></li>
  73 + <li></li>
  74 + <li></li>
  75 + <li></li>
  76 + </ul>
  77 + </div>
  78 + </div>
  79 + </div>
  80 +</template>
  81 +
  82 +<script setup lang="ts">
  83 +import { PropType, toRefs, watch } from 'vue'
  84 +import { CreateComponentType } from '@/packages/index.d'
  85 +import { option } from './config'
  86 +
  87 +const props = defineProps({
  88 + chartConfig: {
  89 + type: Object as PropType<CreateComponentType & typeof option>,
  90 + required: true
  91 + }
  92 +})
  93 +const { w, h } = toRefs(props.chartConfig.attr)
  94 +
  95 +const { styleConfig } = toRefs(props.chartConfig.option)
  96 +
  97 +watch(
  98 + () => styleConfig.value,
  99 + (newValue: Recordable) => {
  100 + styleConfig.value.scale = newValue.scale
  101 + console.log(styleConfig.value.scale)
  102 + },
  103 + {
  104 + immediate: true,
  105 + deep: true
  106 + }
  107 +)
  108 +</script>
  109 +
  110 +<style scoped>
  111 +body {
  112 + color: #02feff;
  113 + overflow: hidden;
  114 +}
  115 +
  116 +.core2 {
  117 + background: #cedce0;
  118 + width: 100px;
  119 + height: 100px;
  120 + -moz-border-radius: 50%;
  121 + -webkit-border-radius: 50%;
  122 + border-radius: 50%;
  123 + border: 10px rgba(2, 255, 255, 0.15) solid;
  124 + animation: flicker2 0.2s infinite;
  125 + margin-left: auto;
  126 + margin-right: auto;
  127 + margin-top: 40px;
  128 +}
  129 +
  130 +.big_core {
  131 + background: #cedce0;
  132 + width: 200px;
  133 + height: 200px;
  134 + -moz-border-radius: 50%;
  135 + -webkit-border-radius: 50%;
  136 + border-radius: 50%;
  137 + border: 10px rgba(2, 255, 255, 0.15) solid;
  138 + animation: big_flicker 0.2s infinite;
  139 +}
  140 +
  141 +.c_ease {
  142 + animation: colour_ease 3s infinite ease-in-out;
  143 +}
  144 +
  145 +.counterspin5 {
  146 + animation: rotate_anti 5s linear infinite;
  147 +}
  148 +
  149 +.counterspin4 {
  150 + animation: rotate_anti 4s linear infinite;
  151 +}
  152 +
  153 +.semi_arc {
  154 + width: 100px;
  155 + height: 100px;
  156 + border: 6px solid #02feff;
  157 + background: rgba(2, 254, 255, 0.2);
  158 + -moz-border-radius: 50%;
  159 + -webkit-border-radius: 50%;
  160 + border-radius: 50%;
  161 + transform: rotateZ(0deg);
  162 + transition: box-shadow 3s ease;
  163 + text-align: center;
  164 + line-height: 100px;
  165 +}
  166 +
  167 +.semi_arc:hover {
  168 + box-shadow: 0px 0px 30px rgba(2, 254, 255, 0.8);
  169 + transition: 0.3s;
  170 +}
  171 +
  172 +.semi_arc_2 {
  173 + content: '';
  174 + position: absolute;
  175 + width: 94%;
  176 + height: 94%;
  177 + left: 3%;
  178 + top: 3%;
  179 + border: 5px solid #02feff;
  180 + -moz-border-radius: 50%;
  181 + -webkit-border-radius: 50%;
  182 + border-radius: 50%;
  183 + -moz-box-sizing: border-box;
  184 + -webkit-box-sizing: border-box;
  185 + box-sizing: border-box;
  186 + animation: rotate 4s linear infinite;
  187 + text-align: center;
  188 + line-height: 129px;
  189 +}
  190 +
  191 +.semi_arc_2:after {
  192 + content: '';
  193 + position: absolute;
  194 + width: 94%;
  195 + height: 94%;
  196 + left: 3%;
  197 + top: 3%;
  198 + border: 4px solid #02feff;
  199 + -moz-border-radius: 50%;
  200 + -webkit-border-radius: 50%;
  201 + border-radius: 50%;
  202 + -moz-box-sizing: border-box;
  203 + -webkit-box-sizing: border-box;
  204 + box-sizing: border-box;
  205 + animation: rotate_anti 2s linear infinite;
  206 +}
  207 +
  208 +.semi_arc_3 {
  209 + content: '';
  210 + position: absolute;
  211 + width: 94%;
  212 + height: 94%;
  213 + left: 3%;
  214 + top: 3%;
  215 + border: 5px solid #02feff;
  216 + -moz-border-radius: 50%;
  217 + -webkit-border-radius: 50%;
  218 + border-radius: 50%;
  219 + -moz-box-sizing: border-box;
  220 + -webkit-box-sizing: border-box;
  221 + box-sizing: border-box;
  222 + animation: rotate 4s linear infinite;
  223 + text-align: center;
  224 + line-height: 129px;
  225 +}
  226 +
  227 +.arc {
  228 + width: 100px;
  229 + height: 100px;
  230 + border: 6px solid #02feff;
  231 + background: rgba(2, 254, 255, 0.2);
  232 + -moz-border-radius: 50%;
  233 + -webkit-border-radius: 50%;
  234 + border-radius: 50%;
  235 + -moz-transform: rotateY(-30deg) translateZ(-200px);
  236 + -ms-transform: rotateY(-30deg) translateZ(-200px);
  237 + -webkit-transform: rotateY(-30deg) translateZ(-200px);
  238 + transform: rotateY(-30deg) translateZ(-200px);
  239 + transform: rotateZ(0deg);
  240 + transition: box-shadow 3s ease;
  241 + text-align: center;
  242 + line-height: 100px;
  243 +}
  244 +
  245 +.arc:hover {
  246 + box-shadow: 0px 0px 30px rgba(2, 254, 255, 0.8);
  247 + transition: 0.3s;
  248 +}
  249 +
  250 +.arc:after {
  251 + content: '';
  252 + position: absolute;
  253 + width: 94%;
  254 + height: 94%;
  255 + left: 3%;
  256 + top: 3%;
  257 + border: 4px solid #02feff;
  258 + -moz-border-radius: 50%;
  259 + -webkit-border-radius: 50%;
  260 + border-radius: 50%;
  261 + -moz-box-sizing: border-box;
  262 + -webkit-box-sizing: border-box;
  263 + box-sizing: border-box;
  264 + animation: rotate 4s linear infinite;
  265 +}
  266 +
  267 +.e1:after {
  268 + border-color: rgba(2, 255, 255, 0.6);
  269 + border-left: 5px solid transparent;
  270 + border-right: 5px solid transparent;
  271 +}
  272 +
  273 +.e2:after {
  274 + border-color: rgba(2, 255, 255, 0.6);
  275 + border-left: 5px solid transparent;
  276 + border-right: 5px solid transparent;
  277 + border-bottom: 5px solid transparent;
  278 +}
  279 +
  280 +.e3 {
  281 + border-left: 6px solid transparent;
  282 + border-right: 6px solid transparent;
  283 + animation: rotate 5s linear infinite;
  284 +}
  285 +
  286 +.e3:after {
  287 + border-color: rgba(2, 255, 255, 0.6);
  288 + border-top: 5px solid transparent;
  289 + border-bottom: 5px solid transparent;
  290 +}
  291 +
  292 +.e4 {
  293 + width: 150px;
  294 + height: 150px;
  295 +}
  296 +
  297 +.e4_1 {
  298 + border-color: rgba(2, 255, 255, 0.3);
  299 + border-left: 5px solid transparent;
  300 + border-right: 5px solid transparent;
  301 +}
  302 +
  303 +.e4_1:after {
  304 + border-color: rgba(2, 255, 255, 0.6);
  305 + border-top: 4px solid transparent;
  306 + border-bottom: 4px solid transparent;
  307 +}
  308 +
  309 +.e5 {
  310 + width: 200px;
  311 + height: 200px;
  312 +}
  313 +
  314 +.e5_1 {
  315 + color: rgba(2, 255, 255, 0.15);
  316 + border: 2px solid;
  317 + border-left: 2px solid transparent;
  318 + animation: rotate 5s linear infinite;
  319 +}
  320 +
  321 +.e5_2 {
  322 + color: rgba(2, 255, 255, 0.7);
  323 + border: 4px solid;
  324 + border-left: 4px solid transparent;
  325 + border-right: 4px solid transparent;
  326 + animation: rotate_anti 4s linear infinite;
  327 +}
  328 +
  329 +.e5_3 {
  330 + color: rgba(2, 255, 255, 0.5);
  331 + border: 2px solid;
  332 + border-left: 2px solid transparent;
  333 + border-right: 2px solid transparent;
  334 + animation: rotate 3s linear infinite;
  335 +}
  336 +
  337 +.e5_4 {
  338 + color: rgba(2, 255, 255, 0.15);
  339 + border: 4px solid;
  340 + border-left: 4px solid transparent;
  341 + border-right: 4px solid transparent;
  342 + border-bottom: 4px solid transparent;
  343 + animation: rotate_anti 2s linear infinite;
  344 +}
  345 +
  346 +.e6 {
  347 + border-color: transparent;
  348 + background: rgba(255, 255, 255, 0);
  349 + width: 200px;
  350 + height: 200px;
  351 +}
  352 +
  353 +@keyframes rotate {
  354 + 0% {
  355 + transform: rotateZ(0deg);
  356 + }
  357 + 100% {
  358 + transform: rotateZ(360deg);
  359 + }
  360 +}
  361 +@keyframes rotate_anti {
  362 + 0% {
  363 + transform: rotateZ(360deg);
  364 + }
  365 + 100% {
  366 + transform: rotateZ(0deg);
  367 + }
  368 +}
  369 +@keyframes colour_ease {
  370 + 0% {
  371 + border-color: #02feff;
  372 + }
  373 + 50% {
  374 + border-color: rgba(2, 254, 255, 0.5);
  375 + }
  376 + 100% {
  377 + border-color: #02feff;
  378 + }
  379 +}
  380 +@keyframes flicker {
  381 + 0% {
  382 + box-shadow: 0px 0px 16px 8px rgba(150, 255, 255, 0.5), inset 0px 1px 4px 2px rgba(21, 211, 233, 0.3);
  383 + }
  384 + 40% {
  385 + box-shadow: 0px 0px 16px 8px rgba(150, 255, 255, 0.5), inset 0px 1px 4px 2px rgba(21, 211, 233, 0.3);
  386 + }
  387 + 50% {
  388 + box-shadow: 0px 0px 16px 6px rgba(150, 255, 255, 0.5), inset 0px 1px 100px 2px rgba(21, 211, 233, 0.3);
  389 + }
  390 + 60% {
  391 + box-shadow: 0px 0px 16px 8px rgba(150, 255, 255, 0.5), inset 0px 1px 4px 2px rgba(21, 211, 233, 0.3);
  392 + }
  393 + 100% {
  394 + box-shadow: 0px 0px 16px 8px rgba(150, 255, 255, 0.5), inset 0px 1px 4px 2px rgba(21, 211, 233, 0.3);
  395 + }
  396 +}
  397 +@keyframes flicker2 {
  398 + 0% {
  399 + box-shadow: 0px 0px 60px 25px rgba(150, 255, 255, 0.5), inset 0px 1px 4px 2px rgba(21, 211, 233, 0.3);
  400 + }
  401 + 40% {
  402 + box-shadow: 0px 0px 60px 25px rgba(150, 255, 255, 0.5), inset 0px 1px 4px 2px rgba(21, 211, 233, 0.3);
  403 + }
  404 + 50% {
  405 + box-shadow: 0px 0px 50px 17px rgba(150, 255, 255, 0.5), inset 0px 1px 100px 2px rgba(21, 211, 233, 0.3);
  406 + }
  407 + 60% {
  408 + box-shadow: 0px 0px 60px 25px rgba(150, 255, 255, 0.5), inset 0px 1px 4px 2px rgba(21, 211, 233, 0.3);
  409 + }
  410 + 100% {
  411 + box-shadow: 0px 0px 60px 25px rgba(150, 255, 255, 0.5), inset 0px 1px 4px 2px rgba(21, 211, 233, 0.3);
  412 + }
  413 +}
  414 +@keyframes big_flicker {
  415 + 0% {
  416 + box-shadow: 0px 0px 40px 20px rgba(150, 255, 255, 0.5), inset 0px 1px 30px 15px rgba(21, 211, 233, 0.3);
  417 + }
  418 + 40% {
  419 + box-shadow: 0px 0px 40px 20px rgba(150, 255, 255, 0.5), inset 0px 1px 30px 15px rgba(21, 211, 233, 0.3);
  420 + }
  421 + 50% {
  422 + box-shadow: 0px 0px 35px 17px rgba(150, 255, 255, 0.5), inset 0px 1px 50px 40px rgba(21, 211, 233, 0.3);
  423 + }
  424 + 60% {
  425 + box-shadow: 0px 0px 40px 20px rgba(150, 255, 255, 0.5), inset 0px 1px 30px 15px rgba(21, 211, 233, 0.3);
  426 + }
  427 + 100% {
  428 + box-shadow: 0px 0px 40px 20px rgba(150, 255, 255, 0.5), inset 0px 1px 30px 15px rgba(21, 211, 233, 0.3);
  429 + }
  430 +}
  431 +html,
  432 +body {
  433 + height: 100%;
  434 +}
  435 +
  436 +ul {
  437 + list-style: none;
  438 + margin: 0;
  439 + padding: 0;
  440 +}
  441 +
  442 +.arc_reactor {
  443 + position: relative;
  444 + top: 50%;
  445 + margin-top: -125px;
  446 + margin-left: auto;
  447 + margin-right: auto;
  448 + width: 250px;
  449 + height: 250px;
  450 + border-radius: 50%;
  451 + box-shadow: 0px 0px 50px 15px rgba(2, 255, 255, 0.3), inset 0px 0px 50px 15px rgba(2, 255, 255, 0.3);
  452 +}
  453 +
  454 +.core2 {
  455 + background: #cedce0;
  456 + width: 110px;
  457 + height: 110px;
  458 + -moz-border-radius: 50%;
  459 + -webkit-border-radius: 50%;
  460 + border-radius: 50%;
  461 + border: 5px solid rgba(2, 255, 255, 0.15);
  462 + animation: flicker2 0.2s infinite;
  463 + margin-left: auto;
  464 + margin-right: auto;
  465 + margin-top: 40px;
  466 +}
  467 +
  468 +.e7 {
  469 + width: 95.25%;
  470 + height: 95.25%;
  471 + left: 2.5475%;
  472 + right: 2.5475%;
  473 + border: 6px solid transparent;
  474 + background: transparent;
  475 + -moz-border-radius: 50%;
  476 + -webkit-border-radius: 50%;
  477 + border-radius: 50%;
  478 + transform: rotateZ(0deg);
  479 + transition: box-shadow 3s ease;
  480 + text-align: center;
  481 + line-height: 100px;
  482 +}
  483 +
  484 +.case_container {
  485 + width: 210px;
  486 + height: 210px;
  487 + border-radius: 50%;
  488 + position: absolute;
  489 + margin-left: 20px;
  490 + margin-top: 20px;
  491 +}
  492 +
  493 +.marks li {
  494 + display: block;
  495 + width: 3px;
  496 + height: 11px;
  497 + background: rgba(2, 254, 255, 0.8);
  498 + position: absolute;
  499 + margin-left: 105px;
  500 + margin-top: -110px;
  501 + animation: colour_ease2 3s infinite ease-in-out;
  502 +}
  503 +
  504 +@keyframes colour_ease2 {
  505 + 0% {
  506 + background: #02feff;
  507 + }
  508 + 50% {
  509 + background: rgba(2, 254, 255, 0.3);
  510 + }
  511 + 100% {
  512 + background: #02feff;
  513 + }
  514 +}
  515 +.marks li:first-child {
  516 + transform: rotate(6deg) translateY(125px);
  517 +}
  518 +
  519 +.marks li:nth-child(2) {
  520 + transform: rotate(12deg) translateY(125px);
  521 +}
  522 +
  523 +.marks li:nth-child(3) {
  524 + transform: rotate(18deg) translateY(125px);
  525 +}
  526 +
  527 +.marks li:nth-child(4) {
  528 + transform: rotate(24deg) translateY(125px);
  529 +}
  530 +
  531 +.marks li:nth-child(5) {
  532 + transform: rotate(30deg) translateY(125px);
  533 +}
  534 +
  535 +.marks li:nth-child(6) {
  536 + transform: rotate(36deg) translateY(125px);
  537 +}
  538 +
  539 +.marks li:nth-child(7) {
  540 + transform: rotate(42deg) translateY(125px);
  541 +}
  542 +
  543 +.marks li:nth-child(8) {
  544 + transform: rotate(48deg) translateY(125px);
  545 +}
  546 +
  547 +.marks li:nth-child(9) {
  548 + transform: rotate(54deg) translateY(125px);
  549 +}
  550 +
  551 +.marks li:nth-child(10) {
  552 + transform: rotate(60deg) translateY(125px);
  553 +}
  554 +
  555 +.marks li:nth-child(11) {
  556 + transform: rotate(66deg) translateY(125px);
  557 +}
  558 +
  559 +.marks li:nth-child(12) {
  560 + transform: rotate(72deg) translateY(125px);
  561 +}
  562 +
  563 +.marks li:nth-child(13) {
  564 + transform: rotate(78deg) translateY(125px);
  565 +}
  566 +
  567 +.marks li:nth-child(14) {
  568 + transform: rotate(84deg) translateY(125px);
  569 +}
  570 +
  571 +.marks li:nth-child(15) {
  572 + transform: rotate(90deg) translateY(125px);
  573 +}
  574 +
  575 +.marks li:nth-child(16) {
  576 + transform: rotate(96deg) translateY(125px);
  577 +}
  578 +
  579 +.marks li:nth-child(17) {
  580 + transform: rotate(102deg) translateY(125px);
  581 +}
  582 +
  583 +.marks li:nth-child(18) {
  584 + transform: rotate(108deg) translateY(125px);
  585 +}
  586 +
  587 +.marks li:nth-child(19) {
  588 + transform: rotate(114deg) translateY(125px);
  589 +}
  590 +
  591 +.marks li:nth-child(20) {
  592 + transform: rotate(120deg) translateY(125px);
  593 +}
  594 +
  595 +.marks li:nth-child(21) {
  596 + transform: rotate(126deg) translateY(125px);
  597 +}
  598 +
  599 +.marks li:nth-child(22) {
  600 + transform: rotate(132deg) translateY(125px);
  601 +}
  602 +
  603 +.marks li:nth-child(23) {
  604 + transform: rotate(138deg) translateY(125px);
  605 +}
  606 +
  607 +.marks li:nth-child(24) {
  608 + transform: rotate(144deg) translateY(125px);
  609 +}
  610 +
  611 +.marks li:nth-child(25) {
  612 + transform: rotate(150deg) translateY(125px);
  613 +}
  614 +
  615 +.marks li:nth-child(26) {
  616 + transform: rotate(156deg) translateY(125px);
  617 +}
  618 +
  619 +.marks li:nth-child(27) {
  620 + transform: rotate(162deg) translateY(125px);
  621 +}
  622 +
  623 +.marks li:nth-child(28) {
  624 + transform: rotate(168deg) translateY(125px);
  625 +}
  626 +
  627 +.marks li:nth-child(29) {
  628 + transform: rotate(174deg) translateY(125px);
  629 +}
  630 +
  631 +.marks li:nth-child(30) {
  632 + transform: rotate(180deg) translateY(125px);
  633 +}
  634 +
  635 +.marks li:nth-child(31) {
  636 + transform: rotate(186deg) translateY(125px);
  637 +}
  638 +
  639 +.marks li:nth-child(32) {
  640 + transform: rotate(192deg) translateY(125px);
  641 +}
  642 +
  643 +.marks li:nth-child(33) {
  644 + transform: rotate(198deg) translateY(125px);
  645 +}
  646 +
  647 +.marks li:nth-child(34) {
  648 + transform: rotate(204deg) translateY(125px);
  649 +}
  650 +
  651 +.marks li:nth-child(35) {
  652 + transform: rotate(210deg) translateY(125px);
  653 +}
  654 +
  655 +.marks li:nth-child(36) {
  656 + transform: rotate(216deg) translateY(125px);
  657 +}
  658 +
  659 +.marks li:nth-child(37) {
  660 + transform: rotate(222deg) translateY(125px);
  661 +}
  662 +
  663 +.marks li:nth-child(38) {
  664 + transform: rotate(228deg) translateY(125px);
  665 +}
  666 +
  667 +.marks li:nth-child(39) {
  668 + transform: rotate(234deg) translateY(125px);
  669 +}
  670 +
  671 +.marks li:nth-child(40) {
  672 + transform: rotate(240deg) translateY(125px);
  673 +}
  674 +
  675 +.marks li:nth-child(41) {
  676 + transform: rotate(246deg) translateY(125px);
  677 +}
  678 +
  679 +.marks li:nth-child(42) {
  680 + transform: rotate(252deg) translateY(125px);
  681 +}
  682 +
  683 +.marks li:nth-child(43) {
  684 + transform: rotate(258deg) translateY(125px);
  685 +}
  686 +
  687 +.marks li:nth-child(44) {
  688 + transform: rotate(264deg) translateY(125px);
  689 +}
  690 +
  691 +.marks li:nth-child(45) {
  692 + transform: rotate(270deg) translateY(125px);
  693 +}
  694 +
  695 +.marks li:nth-child(46) {
  696 + transform: rotate(276deg) translateY(125px);
  697 +}
  698 +
  699 +.marks li:nth-child(47) {
  700 + transform: rotate(282deg) translateY(125px);
  701 +}
  702 +
  703 +.marks li:nth-child(48) {
  704 + transform: rotate(288deg) translateY(125px);
  705 +}
  706 +
  707 +.marks li:nth-child(49) {
  708 + transform: rotate(294deg) translateY(125px);
  709 +}
  710 +
  711 +.marks li:nth-child(50) {
  712 + transform: rotate(300deg) translateY(125px);
  713 +}
  714 +
  715 +.marks li:nth-child(51) {
  716 + transform: rotate(306deg) translateY(125px);
  717 +}
  718 +
  719 +.marks li:nth-child(52) {
  720 + transform: rotate(312deg) translateY(125px);
  721 +}
  722 +
  723 +.marks li:nth-child(53) {
  724 + transform: rotate(318deg) translateY(125px);
  725 +}
  726 +
  727 +.marks li:nth-child(54) {
  728 + transform: rotate(324deg) translateY(125px);
  729 +}
  730 +
  731 +.marks li:nth-child(55) {
  732 + transform: rotate(330deg) translateY(125px);
  733 +}
  734 +
  735 +.marks li:nth-child(56) {
  736 + transform: rotate(336deg) translateY(125px);
  737 +}
  738 +
  739 +.marks li:nth-child(57) {
  740 + transform: rotate(342deg) translateY(125px);
  741 +}
  742 +
  743 +.marks li:nth-child(58) {
  744 + transform: rotate(348deg) translateY(125px);
  745 +}
  746 +
  747 +.marks li:nth-child(59) {
  748 + transform: rotate(354deg) translateY(125px);
  749 +}
  750 +
  751 +.marks li:nth-child(60) {
  752 + transform: rotate(360deg) translateY(125px);
  753 +}
  754 +</style>
... ...
  1 +import { PublicConfigClass } from '@/packages/public'
  2 +import { Decorates16Config } from './index'
  3 +import { CreateComponentType } from '@/packages/index.d'
  4 +import cloneDeep from 'lodash/cloneDeep'
  5 +import { chartInitConfig } from '@/settings/designSetting'
  6 +export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
  7 +
  8 +export const option = {
  9 + dataset: 20,
  10 + unit: '台',
  11 + mainCicleColor: '#03A6E0CC',
  12 + subCicleColor: '#03A6E07F',
  13 + textColor:'green'
  14 +}
  15 +
  16 +export default class Config extends PublicConfigClass implements CreateComponentType {
  17 + public key = Decorates16Config.key
  18 + public attr = { ...chartInitConfig, w: 150, h: 120, zIndex: -1 }
  19 + public chartConfig = cloneDeep(Decorates16Config)
  20 + public option = cloneDeep(option)
  21 +}
... ...
  1 +<template>
  2 + <!-- Echarts 全局设置 -->
  3 + <global-setting :optionData="optionData"></global-setting>
  4 + <CollapseItem name="配置" :expanded="true">
  5 + <setting-item-box name="数据">
  6 + <setting-item name="数据源">
  7 + <n-input-number :min="0" v-model:value="optionData.dataset"></n-input-number>
  8 + </setting-item>
  9 + <setting-item name="单位">
  10 + <n-input v-model:value="optionData.unit"></n-input>
  11 + </setting-item>
  12 + </setting-item-box>
  13 + <setting-item-box name="颜色">
  14 + <setting-item name="颜色1">
  15 + <n-color-picker v-model:value="optionData.mainCicleColor"></n-color-picker>
  16 + </setting-item>
  17 + <setting-item name="颜色2">
  18 + <n-color-picker v-model:value="optionData.subCicleColor"></n-color-picker>
  19 + </setting-item>
  20 + <setting-item name="文字颜色">
  21 + <n-color-picker v-model:value="optionData.textColor"></n-color-picker>
  22 + </setting-item>
  23 + </setting-item-box>
  24 + </CollapseItem>
  25 +</template>
  26 +
  27 +<script setup lang="ts">
  28 +import { PropType } from 'vue'
  29 +import { option } from './config'
  30 +import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
  31 +
  32 +defineProps({
  33 + optionData: {
  34 + type: Object as PropType<typeof option>,
  35 + required: true
  36 + }
  37 +})
  38 +</script>
... ...
  1 +import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
  2 +import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
  3 +import { useWidgetKey } from '@/packages/external/useWidgetKey'
  4 +
  5 +const { key, chartKey, conKey } = useWidgetKey('Decorates16',true)
  6 +
  7 +export const Decorates16Config: ConfigType = {
  8 + key,
  9 + chartKey,
  10 + conKey,
  11 + title: '装饰16',
  12 + category: ChatCategoryEnum.DECORATE,
  13 + categoryName: ChatCategoryEnumName.DECORATE,
  14 + package: PackagesCategoryEnum.DECORATES,
  15 + chartFrame: ChartFrameEnum.COMMON,
  16 + image: 'decorates13.png',
  17 +}
... ...
  1 +<template>
  2 + <div class="go-content-box">
  3 + <svg
  4 + xmlns="http://www.w3.org/2000/svg"
  5 + xmlns:xlink="http://www.w3.org/1999/xlink"
  6 + :width="w"
  7 + :height="h"
  8 + viewBox="0 0 180 180"
  9 + >
  10 + <g opacity="0.6" transform="translate(11 14) scale(1.6)">
  11 + <defs>
  12 + <polygon :id="polygonId" points="15, 46.5, 21, 47.5, 21, 52.5, 15, 53.5" />
  13 + </defs>
  14 + <circle
  15 + cx="50"
  16 + cy="50"
  17 + r="45"
  18 + fill="transparent"
  19 + :stroke="mainCicleColor || defaultColor[0]"
  20 + stroke-width="10"
  21 + stroke-dasharray="80, 100, 30, 100"
  22 + >
  23 + <animateTransform
  24 + attributeName="transform"
  25 + type="rotate"
  26 + values="0 50 50;360 50 50"
  27 + :dur="`${dur}s`"
  28 + repeatCount="indefinite"
  29 + />
  30 + </circle>
  31 + <circle
  32 + cx="50"
  33 + cy="50"
  34 + r="45"
  35 + fill="transparent"
  36 + :stroke="subCicleColor || defaultColor[1]"
  37 + stroke-width="6"
  38 + stroke-dasharray="50, 66, 100, 66"
  39 + >
  40 + <animateTransform
  41 + attributeName="transform"
  42 + type="rotate"
  43 + values="0 50 50;-360 50 50"
  44 + :dur="`${dur}s`"
  45 + repeatCount="indefinite"
  46 + />
  47 + </circle>
  48 + <circle
  49 + cx="50"
  50 + cy="50"
  51 + r="38"
  52 + fill="transparent"
  53 + :stroke="subCicleColor || defaultColor[1]"
  54 + stroke-width="1"
  55 + stroke-dasharray="5, 1"
  56 + />
  57 + <use
  58 + v-for="(foo, i) in new Array(20).fill(0)"
  59 + :key="i"
  60 + :xlink:href="`#${polygonId}`"
  61 + :stroke="mainCicleColor || defaultColor[0]"
  62 + :fill="Math.random() > 0.4 ? 'transparent' : mainCicleColor"
  63 + >
  64 + <animateTransform
  65 + attributeName="transform"
  66 + type="rotate"
  67 + values="0 50 50;360 50 50"
  68 + :dur="`${dur}s`"
  69 + :begin="`${(i * dur) / 20}s`"
  70 + repeatCount="indefinite"
  71 + />
  72 + </use>
  73 + <circle
  74 + cx="50"
  75 + cy="50"
  76 + r="26"
  77 + fill="transparent"
  78 + :stroke="subCicleColor || defaultColor[1]"
  79 + stroke-width="1"
  80 + stroke-dasharray="5, 1"
  81 + />
  82 + <text x="50" y="55" text-anchor="middle" :style="{ fill: textColor, opacity: 1 }" font-size="14">
  83 + {{ dataset + unit }}
  84 + </text>
  85 + </g>
  86 + </svg>
  87 + </div>
  88 +</template>
  89 +<script setup lang="ts">
  90 +import { PropType, toRefs, ref } from 'vue'
  91 +import { CreateComponentType } from '@/packages/index.d'
  92 +import { option } from './config'
  93 +
  94 +const props = defineProps({
  95 + chartConfig: {
  96 + type: Object as PropType<CreateComponentType & typeof option>,
  97 + required: true
  98 + }
  99 +})
  100 +const { w, h } = toRefs(props.chartConfig.attr)
  101 +
  102 +const { mainCicleColor, subCicleColor, dataset, unit, textColor } = toRefs(props.chartConfig.option)
  103 +
  104 +const id = Number(Math.random().toString().substring(2, 10) + Date.now()).toString(36)
  105 +
  106 +const dur = ref(3)
  107 +
  108 +const polygonId = ref(`decoration-9-polygon-${id}`)
  109 +
  110 +const defaultColor = ref(['rgba(3, 166, 224, 0.8)', 'rgba(3, 166, 224, 0.5)'])
  111 +</script>
  112 +
  113 +<style lang="scss" scoped>
  114 +.go-content-box {
  115 + width: v-bind('w+"px"');
  116 + height: v-bind('h+"px"');
  117 + display: flex;
  118 + align-items: center;
  119 + justify-content: center;
  120 +}
  121 +</style>
... ...
... ... @@ -54,6 +54,10 @@ import { Decorates09Config } from '@/packages/components/external/Decorates/Deco
54 54 import { Decorates10Config } from '@/packages/components/external/Decorates/Decorates/Decorates10'
55 55 import { Decorates11Config } from '@/packages/components/external/Decorates/Decorates/Decorates11'
56 56 import { Decorates12Config } from '@/packages/components/external/Decorates/Decorates/Decorates12'
  57 +import { Decorates13Config } from '@/packages/components/external/Decorates/Decorates/Decorates13'
  58 +import { Decorates14Config } from '@/packages/components/external/Decorates/Decorates/Decorates14'
  59 +import { Decorates15Config } from '@/packages/components/external/Decorates/Decorates/Decorates15'
  60 +import { Decorates16Config } from '@/packages/components/external/Decorates/Decorates/Decorates16'
57 61 import { OverrideTableScrollBoardConfig } from '@/packages/components/external/Tables/Tables/OverrideTableScrollBoard'
58 62
59 63
... ... @@ -86,6 +90,10 @@ export function useInjectLib(packagesList: EPackagesType) {
86 90 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Decorates10Config)//新增装饰10
87 91 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Decorates11Config)//新增装饰11
88 92 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Decorates12Config)//新增装饰12
  93 + addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Decorates13Config)//新增装饰13
  94 + addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Decorates14Config)//新增装饰14
  95 + addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Decorates15Config)//新增装饰15
  96 + addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Decorates16Config)//新增装饰16
89 97 //
90 98
91 99 //信息
... ...
... ... @@ -110,6 +110,28 @@ export const BlendModeEnumList = [
110 110 { label: '亮度', value: 'luminosity' }
111 111 ]
112 112
  113 +// // 动画时间函数枚举
  114 +// export enum AnimationTimingFunctionEnum {
  115 +// // 动画从头到尾的速度是相同的
  116 +// LINEAR = 'linear',
  117 +// // 默认值:动画以低速开始,然后加快,在结束前变慢。
  118 +// EASE = 'ease',
  119 +// // 动画以低速开始。
  120 +// EASEIN = 'ease-in',
  121 +// // 动画以低速结束。
  122 +// EASEOUT = 'ease-out',
  123 +// // 动画以低速开始和结束。
  124 +// EASEINOUT = 'ease-in-out'
  125 +// }
  126 +
  127 +// // 动画执行状态枚举
  128 +// export enum AnimationPlayStateEnum {
  129 +// // 运行
  130 +// PAUSED = 'paused',
  131 +// // 暂停
  132 +// RUNNING = 'running'
  133 +// }
  134 +
113 135 // 组件实例类
114 136 export interface PublicConfigType {
115 137 id: string
... ... @@ -132,6 +154,14 @@ export interface PublicConfigType {
132 154 [FilterEnum.BLEND_MODE]: string
133 155 // 动画
134 156 animations: string[]
  157 + // 动画配置(时长、时间函数、动画延迟、动画执行的次数、动画的执行状态)
  158 + animationsStyleConfig: {
  159 + animationPlayState: string
  160 + animationTimingFunction: string
  161 + animationDuration: number
  162 + animationDelay: number
  163 + animationIterationCount: number | string //动画执行的次数,具体数值或者infinite
  164 + }
135 165 }
136 166 preview?: {
137 167 // 预览超出隐藏
... ... @@ -160,7 +190,7 @@ export interface CreateComponentType extends PublicConfigType, requestConfig {
160 190 chartConfig: ConfigType
161 191 option: GlobalThemeJsonType
162 192 groupList?: Array<CreateComponentType>
163   - saveHistoryInput?:string // THINGS_KIT 新增一个接口字段 saveHistoryInput,用于记录当前组件id和输入框的内容,这里不能重写,有很多地方引用到的,这里升级版本有冲突
  193 + saveHistoryInput?: string // THINGS_KIT 新增一个接口字段 saveHistoryInput,用于记录当前组件id和输入框的内容,这里不能重写,有很多地方引用到的,这里升级版本有冲突
164 194 }
165 195
166 196 // 组件成组实例类
... ...
... ... @@ -9,22 +9,17 @@ import {
9 9 RequestContentTypeEnum,
10 10 RequestBodyEnum
11 11 } from '@/enums/httpEnum'
12   -import {
13   - ChartFrameEnum,
14   - PublicConfigType,
15   - CreateComponentType,
16   - CreateComponentGroupType
17   -} from '@/packages/index.d'
  12 +import { ChartFrameEnum, PublicConfigType, CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
18 13 import { chartInitConfig } from '@/settings/designSetting'
19 14 import cloneDeep from 'lodash/cloneDeep'
20 15
21 16 /**
22   - * 这里更新版本有冲突
23   - * ft 修改在公共接口下拉框里默认选择公共接口,不选择静态
24   - * 修改后的代码在注释之间,并标注好源代码和修改后代码,方便回溯
25   - * 源代码 requestDataType: RequestDataTypeEnum.STATIC,
26   - * 修改后的代码 requestDataType: RequestDataTypeEnum.Pond,
27   - */
  17 + * 这里更新版本有冲突
  18 + * ft 修改在公共接口下拉框里默认选择公共接口,不选择静态
  19 + * 修改后的代码在注释之间,并标注好源代码和修改后代码,方便回溯
  20 + * 源代码 requestDataType: RequestDataTypeEnum.STATIC,
  21 + * 修改后的代码 requestDataType: RequestDataTypeEnum.Pond,
  22 + */
28 23 // 请求基础属性
29 24 export const requestConfig: RequestConfigType = {
30 25 requestDataType: RequestDataTypeEnum.Pond,
... ... @@ -83,7 +78,15 @@ export class PublicConfigClass implements PublicConfigType {
83 78 blendMode: 'normal',
84 79
85 80 // 动画
86   - animations: []
  81 + animations: [],
  82 + // 动画配置
  83 + animationsStyleConfig: {
  84 + animationPlayState: 'paused',
  85 + animationTimingFunction: 'ease',
  86 + animationDuration: 0,
  87 + animationDelay: 0,
  88 + animationIterationCount: 'infinite'
  89 + }
87 90 }
88 91 // 预览
89 92 public preview = {
... ...
1 1 <template>
2 2 <div class="go-chart-configurations-animations" v-if="targetData">
3   - <n-button
4   - class="clear-btn go-my-2"
5   - :disabled="!targetData.styles.animations.length"
6   - @click="clearAnimation"
7   - >
  3 + <SettingItemBox name="动画配置">
  4 + <SettingItem name="是否开启动画">
  5 + <n-select
  6 + clearable
  7 + v-model:value="targetData.styles.animationsStyleConfig.animationPlayState"
  8 + size="small"
  9 + :options="animationPlayStateOption"
  10 + ></n-select>
  11 + </SettingItem>
  12 + <SettingItem name="动画时间函数">
  13 + <n-select
  14 + clearable
  15 + v-model:value="targetData.styles.animationsStyleConfig.animationTimingFunction"
  16 + size="small"
  17 + :options="animationTimingFunctionOption"
  18 + ></n-select>
  19 + </SettingItem>
  20 + <SettingItem name="动画时长">
  21 + <n-input-number
  22 + :min="0"
  23 + v-model:value="targetData.styles.animationsStyleConfig.animationDuration"
  24 + ></n-input-number>
  25 + </SettingItem>
  26 + <SettingItem name="动画延迟">
  27 + <n-input-number
  28 + :min="0"
  29 + v-model:value="targetData.styles.animationsStyleConfig.animationDelay"
  30 + size="small"
  31 + :options="animationTimingFunctionOption"
  32 + ></n-input-number>
  33 + </SettingItem>
  34 + <SettingItem name="动画执行次数">
  35 + <n-select
  36 + clearable
  37 + v-model:value="targetData.styles.animationsStyleConfig.animationIterationCount"
  38 + size="small"
  39 + :options="animationIterationCountOption"
  40 + ></n-select>
  41 + </SettingItem>
  42 + </SettingItemBox>
  43 + <n-button class="clear-btn go-my-2" :disabled="!targetData.styles.animations.length" @click="clearAnimation">
8 44 清除动画
9 45 </n-button>
10   - <collapse-item
11   - v-for="(item, index) in animations"
12   - :key="index"
13   - :name="item.label"
14   - :expanded="true"
15   - >
  46 + <collapse-item v-for="(item, index) in animations" :key="index" :name="item.label" :expanded="true">
16 47 <n-grid :x-gap="6" :y-gap="10" :cols="3">
17 48 <n-grid-item
18 49 class="animation-item go-transition-quick"
19 50 :class="[
20 51 activeIndex(childrenItem.value) && 'active',
21   - hoverPreviewAnimate === childrenItem.value &&
22   - `animate__animated animate__${childrenItem.value}`
  52 + hoverPreviewAnimate === childrenItem.value && `animate__animated animate__${childrenItem.value}`
23 53 ]"
24 54 v-for="(childrenItem, index) in item.children"
25 55 :key="index"
... ... @@ -39,6 +69,16 @@ import { animations } from '@/settings/animations/index'
39 69 import { CollapseItem } from '@/components/Pages/ChartItemSetting'
40 70 import { useDesignStore } from '@/store/modules/designStore/designStore'
41 71 import { useTargetData } from '../hooks/useTargetData.hook'
  72 +import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
  73 +import type { SelectOption } from 'naive-ui'
  74 +import {
  75 + AnimationPlayStateEnum,
  76 + AnimationTimingFunctionEnum,
  77 + AnimationTimingFunctionNameEnum,
  78 + AnimationPlayStateNameEnum,
  79 + AnimationIterationCountNameEnum,
  80 + AnimationIterationCountEnum
  81 +} from '@/enums/external/animationEnum'
42 82
43 83 // 全局颜色
44 84 const designStore = useDesignStore()
... ... @@ -68,6 +108,50 @@ const clearAnimation = () => {
68 108 const addAnimation = (item: { label: string; value: string }) => {
69 109 targetData.value.styles.animations = [item.value]
70 110 }
  111 +
  112 +//动画运行状态配置
  113 +const animationPlayStateOption: SelectOption[] = [
  114 + {
  115 + label: AnimationPlayStateNameEnum.RUNNING,
  116 + value: AnimationPlayStateEnum.RUNNING
  117 + },
  118 + {
  119 + label: AnimationPlayStateNameEnum.PAUSED,
  120 + value: AnimationPlayStateEnum.PAUSED
  121 + }
  122 +]
  123 +
  124 +//动画运行时间函数配置
  125 +const animationTimingFunctionOption: SelectOption[] = [
  126 + {
  127 + label: AnimationTimingFunctionNameEnum.LINEAR,
  128 + value: AnimationTimingFunctionEnum.LINEAR
  129 + },
  130 + {
  131 + label: AnimationTimingFunctionNameEnum.EASE,
  132 + value: AnimationTimingFunctionEnum.EASE
  133 + },
  134 + {
  135 + label: AnimationTimingFunctionNameEnum.EASEIN,
  136 + value: AnimationTimingFunctionEnum.EASEIN
  137 + },
  138 + {
  139 + label: AnimationTimingFunctionNameEnum.EASEOUT,
  140 + value: AnimationTimingFunctionEnum.EASEOUT
  141 + },
  142 + {
  143 + label: AnimationTimingFunctionNameEnum.EASEINOUT,
  144 + value: AnimationTimingFunctionEnum.EASEINOUT
  145 + }
  146 +]
  147 +
  148 +//动画执行次数
  149 +const animationIterationCountOption: SelectOption[] = [
  150 + {
  151 + label: AnimationIterationCountNameEnum.ITERATIONCOUNT,
  152 + value: AnimationIterationCountEnum.ITERATIONCOUNT
  153 + }
  154 +]
71 155 </script>
72 156
73 157 <style lang="scss" scoped>
... ...
... ... @@ -42,7 +42,8 @@
42 42 :style="{
43 43 ...useSizeStyle(item.attr),
44 44 ...getFilterStyle(item.styles),
45   - ...getTransformStyle(item.styles)
  45 + ...getTransformStyle(item.styles),
  46 + ...item.styles.animationsStyleConfig,
46 47 }"
47 48 ></component>
48 49 </edit-shape-box>
... ...
... ... @@ -31,7 +31,8 @@
31 31 :themeColor="themeColor" :style="{
32 32 ...useSizeStyle(item.attr),
33 33 ...getFilterStyle(item.styles),
34   - ...getTransformStyle(item.styles)
  34 + ...getTransformStyle(item.styles),
  35 + ...item.styles.animationsStyleConfig,
35 36 }"></component>
36 37 </edit-shape-box>
37 38 </div>
... ...
... ... @@ -15,7 +15,8 @@
15 15 ...getComponentAttrStyle(item.attr, groupIndex),
16 16 ...getStatusStyle(item.status),
17 17 ...getPreviewConfigStyle(item.preview),
18   - ...getBlendModeStyle(item.styles) as any
  18 + ...getBlendModeStyle(item.styles) as any,
  19 + ...item.styles.animationsStyleConfig,
19 20 }"
20 21 >
21 22 <component
... ...
... ... @@ -10,7 +10,8 @@
10 10 ...getStatusStyle(item.status),
11 11 ...getPreviewConfigStyle(item.preview),
12 12 ...getBlendModeStyle(item.styles) as any,
13   - ...getSizeStyle(item.attr)
  13 + ...getSizeStyle(item.attr),
  14 + ...item.styles.animationsStyleConfig,
14 15 }"
15 16 >
16 17 <!-- 分组 -->
... ... @@ -32,7 +33,7 @@
32 33 :themeColor="themeColor"
33 34 :style="{
34 35 ...getSizeStyle(item.attr),
35   - ...getFilterStyle(item.styles)
  36 + ...getFilterStyle(item.styles),
36 37 }"
37 38 v-on="useLifeHandler(item)"
38 39 ></component>
... ...