Merge branch 'dev' into dev-commet

This commit is contained in:
tnt group
2022-11-01 08:28:43 +08:00
73 changed files with 2122 additions and 224 deletions
@@ -3,12 +3,6 @@
<global-setting :optionData="optionData"></global-setting>
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`柱状图-${index + 1}`" :expanded="true">
<SettingItemBox name="图形">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color"></n-color-picker>
</SettingItem>
<SettingItem>
<n-button size="small" @click="item.itemStyle.color = null"> 恢复默认 </n-button>
</SettingItem>
<SettingItem name="宽度">
<n-input-number
v-model:value="item.barWidth"
@@ -3,12 +3,6 @@
<global-setting :optionData="optionData"></global-setting>
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`柱状图-${index+1}`" :expanded="true">
<SettingItemBox name="图形">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color"></n-color-picker>
</SettingItem>
<SettingItem>
<n-button size="small" @click="item.itemStyle.color = null">恢复默认</n-button>
</SettingItem>
<SettingItem name="宽度">
<n-input-number
v-model:value="item.barWidth"
@@ -0,0 +1,25 @@
import { PublicConfigClass } from '@/packages/public'
import { CapsuleChartConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import { chartInitConfig } from '@/settings/designSetting'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const option = {
dataset: dataJson,
colors: ['#c4ebad', '#6be6c1', '#a0a7e6', '#96dee8', '#3fb1e3' ],
unit: '',
itemHeight: 10,
valueFontSize: 16,
paddingRight: 50,
paddingLeft: 50,
showValue: true
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = CapsuleChartConfig.key
public attr = { ...chartInitConfig, zIndex: -1 }
public chartConfig = cloneDeep(CapsuleChartConfig)
public option = cloneDeep(option)
}
@@ -0,0 +1,53 @@
<template>
<!-- Echarts 全局设置 -->
<global-setting :optionData="optionData"> </global-setting>
<!-- 胶囊柱图 -->
<collapse-item name="胶囊柱图" expanded>
<SettingItemBox name="布局">
<setting-item name="左侧边距">
<n-input-number v-model:value="optionData.paddingLeft" :min="10" :step="1" size="small"></n-input-number>
</setting-item>
<setting-item name="右侧边距">
<n-input-number v-model:value="optionData.paddingRight" :min="10" :step="1" size="small"></n-input-number>
</setting-item>
<setting-item name="每块高度(px)">
<n-input-number v-model:value="optionData.itemHeight" :min="0" :step="1" size="small"></n-input-number>
</setting-item>
</SettingItemBox>
<SettingItemBox name="文本">
<setting-item name="所有文字大小">
<n-input-number v-model:value="optionData.valueFontSize" :min="0" :step="1" size="small"></n-input-number>
</setting-item>
<setting-item name="单位">
<n-input v-model:value="optionData.unit" size="small"></n-input>
</setting-item>
<SettingItem>
<n-space>
<n-switch v-model:value="optionData.showValue" size="small"></n-switch>
<n-text>显示数值</n-text>
</n-space>
</SettingItem>
</SettingItemBox>
<SettingItemBox name="颜色">
<setting-item v-for="(item, index) in optionData.colors" :key="index" :name="`颜色${index}`">
<n-color-picker v-model:value="optionData.colors[index]" size="small" :modes="['hex']"></n-color-picker>
</setting-item>
</SettingItemBox>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option & GlobalThemeJsonType>,
required: true
}
})
</script>
@@ -0,0 +1,10 @@
{
"dimensions": ["name", "value"],
"source": [
{ "name": "厦门", "value": 20 },
{ "name": "南阳", "value": 40 },
{ "name": "北京", "value": 60 },
{ "name": "上海", "value": 80 },
{ "name": "新疆", "value": 100 }
]
}
@@ -0,0 +1,15 @@
import image from '@/assets/images/chart/charts/capsule.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const CapsuleChartConfig: ConfigType = {
key: 'CapsuleChart',
chartKey: 'VCapsuleChart',
conKey: 'VCCapsuleChart',
title: '胶囊柱图',
category: ChatCategoryEnum.BAR,
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image
}
@@ -0,0 +1,228 @@
<template>
<div
v-if="state.mergedConfig"
class="go-dv-capsule-chart"
:style="{
fontSize: numberSizeHandle(state.mergedConfig.valueFontSize),
paddingLeft: numberSizeHandle(state.mergedConfig.paddingLeft),
paddingRight: numberSizeHandle(state.mergedConfig.paddingRight)
}"
>
<div class="label-column">
<div
v-for="item in state.mergedConfig.dataset.source"
:key="item[state.mergedConfig.dataset.dimensions[0]]"
:style="{ height: state.capsuleItemHeight, lineHeight: state.capsuleItemHeight }"
>
{{ item[state.mergedConfig.dataset.dimensions[0]] }}
</div>
<div class="laset">&nbsp;</div>
</div>
<div class="capsule-container">
<div
v-for="(capsule, index) in state.capsuleLength"
:key="index"
class="capsule-item"
:style="{ height: state.capsuleItemHeight }"
>
<div
class="capsule-item-column"
:style="`width: ${capsule * 100}%; background-color: ${
state.mergedConfig.colors[index % state.mergedConfig.colors.length]
};height:calc(100% - ${2}px);`"
>
<div v-if="state.mergedConfig.showValue" class="capsule-item-value">
{{ state.capsuleValue[index] }}
</div>
</div>
</div>
<div class="unit-label">
<div v-for="(label, index) in state.labelData" :key="label + index">
{{ label }}
</div>
</div>
</div>
<div v-if="state.mergedConfig.unit" class="unit-text">
{{ state.mergedConfig.unit }}
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, watch, reactive, PropType } from 'vue'
import merge from 'lodash/merge'
import cloneDeep from 'lodash/cloneDeep'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import config, { option } from './config'
type DataProps = {
name: string | number
value: string | number
[key: string]: string | number
}
interface StateProps {
defaultConfig: {
dataset: {
dimensions: Array<string>
source: Array<DataProps>
}
colors: Array<string>
unit: string
showValue: boolean
itemHeight: number
valueFontSize: number
paddingLeft: number
paddingRight: number
}
mergedConfig: any
capsuleLength: Array<number>
capsuleValue: Array<string | Object>
labelData: Array<number>
capsuleItemHeight: string
}
const props = defineProps({
chartConfig: {
type: Object as PropType<config>,
default: () => ({})
}
})
const state = reactive<StateProps>({
defaultConfig: option,
mergedConfig: null,
capsuleLength: [],
capsuleValue: [],
labelData: [],
capsuleItemHeight: ''
})
watch(
() => props.chartConfig.option,
newVal => {
calcData(newVal)
},
{
deep: true
}
)
const calcData = (data: any) => {
mergeConfig(props.chartConfig.option)
calcCapsuleLengthAndLabelData()
}
const mergeConfig = (data: any) => {
state.mergedConfig = merge(cloneDeep(state.defaultConfig), data || {})
}
// 数据解析
const calcCapsuleLengthAndLabelData = () => {
const { source } = state.mergedConfig.dataset
if (!source.length) return
state.capsuleItemHeight = numberSizeHandle(state.mergedConfig.itemHeight)
const capsuleValue = source.map((item: DataProps) => item[state.mergedConfig.dataset.dimensions[1]])
const maxValue = Math.max(...capsuleValue)
state.capsuleValue = capsuleValue
state.capsuleLength = capsuleValue.map((v: any) => (maxValue ? v / maxValue : 0))
const oneFifth = maxValue / 5
const labelData = Array.from(new Set(new Array(6).fill(0).map((v, i) => Math.ceil(i * oneFifth))))
state.labelData = labelData
}
const numberSizeHandle = (val: string | number) => {
return val + 'px'
}
onMounted(() => {
calcData(props.chartConfig.option)
})
// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
calcData(newData)
})
</script>
<style lang="scss" scoped>
@include go('dv-capsule-chart') {
position: relative;
display: flex;
flex-direction: row;
box-sizing: border-box;
padding: 20px;
padding-right: 50px;
color: #b9b8cc;
.label-column {
display: flex;
flex-direction: column;
justify-content: space-between;
box-sizing: border-box;
padding-right: 10px;
text-align: right;
> div:not(:last-child) {
margin: 5px 0;
}
}
.capsule-container {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.capsule-item {
box-shadow: 0 0 3px #999;
height: 10px;
margin: 5px 0px;
border-radius: 5px;
.capsule-item-column {
position: relative;
height: 8px;
margin-top: 1px;
border-radius: 5px;
transition: all 0.3s;
display: flex;
justify-content: flex-end;
align-items: center;
.capsule-item-value {
padding-left: 10px;
transform: translateX(100%);
}
}
}
.unit-label {
height: 20px;
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
}
.unit-text {
text-align: right;
display: flex;
align-items: flex-end;
line-height: 20px;
margin-left: 10px;
}
}
</style>
+2 -1
View File
@@ -1,4 +1,5 @@
import { BarCommonConfig } from './BarCommon/index'
import { BarCrossrangeConfig } from './BarCrossrange/index'
import { CapsuleChartConfig } from './CapsuleChart/index'
export default [BarCommonConfig, BarCrossrangeConfig]
export default [BarCommonConfig, BarCrossrangeConfig, CapsuleChartConfig]
@@ -3,9 +3,6 @@
<global-setting :optionData="optionData"></global-setting>
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`折线图-${index + 1}`" :expanded="true">
<SettingItemBox name="线条">
<setting-item name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.lineStyle.color"></n-color-picker>
</setting-item>
<SettingItem name="宽度">
<n-input-number
v-model:value="item.lineStyle.width"
@@ -0,0 +1,83 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { MapAmapConfig } from './index'
import { chartInitConfig } from '@/settings/designSetting'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export enum ThemeEnum {
NORMAL = 'normal',
DARK = 'dark',
LIGHT = 'light',
WHITES_MOKE = 'whitesmoke',
FRESH = 'fresh',
GREY = 'grey',
GRAFFITI = 'graffiti',
MACARON = 'macaron',
BLUE = 'blue',
DARKBLUE = 'darkblue',
WINE = 'wine'
}
export enum LangEnum {
ZH_CN = 'zh_cn',
EN = 'en',
ZH_EN = 'zh_en'
}
export enum ViewModeEnum {
PLANE = '2D',
STEREOSCOPIC = '3D'
}
export enum FeaturesEnum {
BG = 'bg',
POINT = 'point',
ROAD = 'road',
BUILDING = 'building'
}
export enum MarkerEnum {
// 圆圈
CIRCLE_MARKER = 'CircleMarker',
// 定位标点
MARKER = 'Marker',
// 暂无
NONE = 'none'
}
export const option = {
dataset: dataJson,
mapOptions: {
pitch: 60,
skyColor: '#53A9DE',
amapKey: 'd5f3e16589dbecae64d05fe90e2ba4f2',
amapStyleKey: ThemeEnum.DARK,
amapStyleKeyCustom: '',
amapLon: 116.397428,
amapLat: 39.90923,
amapZindex: 11,
marker: {
fillColor: '#E98984FF',
fillOpacity: 0.5,
strokeColor: 'white',
strokeWeight: 2,
strokeOpacity: 0.5,
zIndex: 10,
bubble: true,
cursor: 'pointer',
clickable: true
},
mapMarkerType: MarkerEnum.CIRCLE_MARKER,
viewMode: ViewModeEnum.PLANE,
lang: LangEnum.ZH_CN,
features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING]
}
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = MapAmapConfig.key
public attr = { ...chartInitConfig, w: 1000, h: 800, zIndex: -1 }
public chartConfig = cloneDeep(MapAmapConfig)
public option = cloneDeep(option)
}
@@ -0,0 +1,199 @@
<template>
<collapse-item name="基础" :expanded="true">
<setting-item-box name="语言类型" :alone="true">
<setting-item>
<n-select size="small" v-model:value="optionData.mapOptions.lang" :options="langOptions" />
</setting-item>
</setting-item-box>
<setting-item-box name="Key" :alone="true">
<setting-item name="请务必使用自己的高德应用 key">
<n-input v-model:value="optionData.mapOptions.amapKey" size="small"></n-input>
</setting-item>
</setting-item-box>
<setting-item-box name="自定义地图样式ID" :alone="true">
<setting-item>
<n-input size="small" v-model:value="optionData.mapOptions.amapStyleKeyCustom" />
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item name="地图" :expanded="true">
<setting-item-box name="主题">
<setting-item>
<n-select size="small" v-model:value="optionData.mapOptions.amapStyleKey" :options="themeOptions" />
</setting-item>
</setting-item-box>
<setting-item-box name="内容" :alone="true">
<n-checkbox-group v-model:value="optionData.mapOptions.features">
<n-space item-style="display: flex;">
<n-checkbox :value="item.value" :label="item.label" v-for="(item, index) in featuresOptions" :key="index" />
</n-space>
</n-checkbox-group>
</setting-item-box>
<setting-item-box name="位置">
<setting-item name="经度">
<n-input-number v-model:value="optionData.mapOptions.amapLon" :show-button="false" size="small">
<template #suffix>°</template>
</n-input-number>
</setting-item>
<setting-item name="纬度">
<n-input-number v-model:value="optionData.mapOptions.amapLat" :show-button="false" size="small">
<template #suffix>°</template>
</n-input-number>
</setting-item>
<setting-item name="初始缩放">
<n-input-number v-model:value="optionData.mapOptions.amapZindex" :min="0" size="small"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="模式" :alone="true">
<setting-item>
<n-radio-group v-model:value="optionData.mapOptions.viewMode" name="radiogroup">
<n-space>
<n-radio v-for="song in viewModeOptions" :key="song.value" :value="song.value">
{{ song.label }}
</n-radio>
</n-space>
</n-radio-group>
</setting-item>
</setting-item-box>
<template v-if="optionData.mapOptions.viewMode === '3D'">
<setting-item-box>
<setting-item name="天空色">
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.mapOptions.skyColor"></n-color-picker>
</setting-item>
<setting-item name="俯仰角">
<n-input-number v-model:value="optionData.mapOptions.pitch" :min="0" :max="83" size="small"></n-input-number>
</setting-item>
</setting-item-box>
</template>
</collapse-item>
<collapse-item name="标记" :expanded="true">
<setting-item-box name="样式">
<setting-item name="类型">
<n-select size="small" v-model:value="optionData.mapOptions.mapMarkerType" :options="MarkerOptions" />
</setting-item>
<setting-item name="颜色">
<n-color-picker v-model:value="optionData.mapOptions.marker.fillColor" size="small"></n-color-picker>
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { option, MarkerEnum, ThemeEnum, LangEnum, ViewModeEnum, FeaturesEnum } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
const themeOptions = [
{
value: ThemeEnum.NORMAL,
label: '标准'
},
{
value: ThemeEnum.DARK,
label: '幻影黑'
},
{
value: ThemeEnum.LIGHT,
label: '月光银'
},
{
value: ThemeEnum.WHITES_MOKE,
label: '远山黛'
},
{
value: ThemeEnum.FRESH,
label: '草色青'
},
{
value: ThemeEnum.GREY,
label: '雅士灰'
},
{
value: ThemeEnum.GRAFFITI,
label: '涂鸦'
},
{
value: ThemeEnum.MACARON,
label: '马卡龙'
},
{
value: ThemeEnum.BLUE,
label: '靛青蓝'
},
{
value: ThemeEnum.DARKBLUE,
label: '极夜蓝'
},
{
value: ThemeEnum.WINE,
label: '酱籽'
}
]
const langOptions = [
{
value: LangEnum.ZH_CN,
label: '中文简体'
},
{
value: LangEnum.EN,
label: '英文'
},
{
value: LangEnum.ZH_EN,
label: '中英文对照'
}
]
const viewModeOptions = [
{
value: ViewModeEnum.PLANE,
label: '2D'
},
{
value: ViewModeEnum.STEREOSCOPIC,
label: '3D'
}
]
const featuresOptions = [
{
value: FeaturesEnum.BG,
label: '显示地图背景'
},
{
value: FeaturesEnum.POINT,
label: '显示标识'
},
{
value: FeaturesEnum.ROAD,
label: '显示道路'
},
{
value: FeaturesEnum.BUILDING,
label: '显示建筑'
}
]
const MarkerOptions = [
{
value: MarkerEnum.CIRCLE_MARKER,
label: '圆形标点'
},
{
value: MarkerEnum.MARKER,
label: '定位标点'
},
{
value: MarkerEnum.NONE,
label: '隐藏标点'
}
]
</script>
@@ -0,0 +1,19 @@
{
"markers": [
{
"name": "某某地市",
"value": 10,
"position": [116.300467, 39.907761]
},
{
"name": "某某地市",
"value": 15,
"position": [116.400567, 39.908761]
},
{
"name": "某某地市",
"value": 20,
"position": [116.200467, 39.937761]
}
]
}
@@ -0,0 +1,15 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import image from '@/assets/images/chart/charts/map_amap.png'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const MapAmapConfig: ConfigType = {
key: 'MapAmap',
chartKey: 'VMapAmap',
conKey: 'VCMapAmap',
title: '高德地图',
category: ChatCategoryEnum.MAP,
categoryName: ChatCategoryEnumName.MAP,
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image
}
@@ -0,0 +1,130 @@
<template>
<div ref="vChartRef"></div>
</template>
<script setup lang="ts">
import { ref, PropType, toRefs, watch } from 'vue'
import AMapLoader from '@amap/amap-jsapi-loader'
import { CreateComponentType } from '@/packages/index.d'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { MarkerEnum } from './config'
import { isArray } from '@/utils'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
let {
amapKey,
amapStyleKey,
amapLon,
amapLat,
amapZindex,
mapMarkerType,
lang,
amapStyleKeyCustom,
features,
viewMode,
pitch,
skyColor,
marker
} = toRefs(props.chartConfig.option.mapOptions)
let mapIns: any = null
let markers: any = []
let AMapIns: any = null
const vChartRef = ref<HTMLElement>()
const initMap = (newData: any) => {
// 初始化
AMapLoader.load({
key: amapKey.value, //api服务key--另外需要在public中使用安全密钥!!!
version: '1.4.8', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 需要使用的的插件列表
})
.then(AMap => {
AMapIns = AMap
mapIns = new AMap.Map(vChartRef.value, {
resizeEnable: true,
zoom: amapZindex.value, // 地图显示的缩放级别
center: [amapLon.value, amapLat.value],
mapStyle: `amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}`, //自定义地图的显示样式
lang: lang.value,
features: features.value,
pitch: pitch.value, // 地图俯仰角度,有效范围 0 度- 83 度
skyColor: skyColor.value,
viewMode: viewMode.value, // 地图模式
willReadFrequently: true
})
dataHandle(props.chartConfig.option.dataset)
})
.catch(e => {})
}
const dataHandle = (newData: any) => {
if (!mapIns && !AMapIns) {
initMap(props.chartConfig.option)
return
}
if (isArray(newData.markers)) {
// 先清除旧标记
mapIns.remove(markers)
markers = []
// 记录新标记
if (mapMarkerType.value === MarkerEnum.MARKER) {
newData.markers.forEach((markerItem: any) => {
const markerInstance = new AMapIns.Marker({
position: [markerItem.position[0], markerItem.position[1]],
offset: new AMapIns.Pixel(-13, -30)
})
markers.push(markerInstance)
markerInstance.setMap(mapIns)
})
} else if (mapMarkerType.value === MarkerEnum.CIRCLE_MARKER) {
newData.markers.forEach((markerItem: any) => {
const markerInstance = new AMapIns.CircleMarker({
center: [markerItem.position[0], markerItem.position[1]],
radius: markerItem.value,
...marker.value
})
markers.push(markerInstance)
markerInstance.setMap(mapIns)
})
}
}
}
const stopWatch = watch(
() => props.chartConfig.option.mapOptions,
option => {
initMap(option)
},
{
immediate: true,
deep: true
}
)
watch(
() => props.chartConfig.option.dataset,
newData => {
try {
dataHandle(newData)
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
stopWatch()
dataHandle(newData)
})
</script>
+2 -1
View File
@@ -1,3 +1,4 @@
import { MapBaseConfig } from './MapBase/index'
import { MapAmapConfig } from './MapAmap/index'
export default [ MapBaseConfig ]
export default [MapBaseConfig, MapAmapConfig]
@@ -3,7 +3,7 @@ import { CreateComponentType } from '@/packages/index.d'
import { CountDownConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
import { chartInitConfig } from '@/settings/designSetting'
import { FlipType } from '@/components/Flipper'
import { FlipType } from '@/components/Pages/Flipper'
type STYLE = '时分秒' | '冒号'
@@ -76,7 +76,7 @@
<script setup lang="ts">
import { PropType, toRefs, watch, ref, onMounted } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import { Flipper } from '@/components/Flipper'
import { Flipper } from '@/components/Pages/Flipper'
import { OptionType } from './config'
import { CountdownInst, CountdownProps } from 'naive-ui/es/countdown/src/Countdown'
@@ -3,7 +3,7 @@ import { CreateComponentType } from '@/packages/index.d'
import { FlipperNumberConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
import { chartInitConfig } from '@/settings/designSetting'
import { FlipType } from '@/components/Flipper'
import { FlipType } from '@/components/Pages/Flipper'
export interface OptionType {
dataset: number | string
@@ -21,7 +21,7 @@ import { PropType, toRefs, watch, ref } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useChartDataFetch } from '@/hooks'
import { Flipper } from '@/components/Flipper'
import { Flipper } from '@/components/Pages/Flipper'
import { OptionType } from './config'
const props = defineProps({
@@ -0,0 +1,20 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { chartInitConfig } from '@/settings/designSetting'
import { IframeConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
// 网站路径
dataset: "https://cn.vuejs.org/",
// 圆角
borderRadius: 10
}
export default class Config extends PublicConfigClass implements CreateComponentType
{
public key = IframeConfig.key
public attr = { ...chartInitConfig, w: 800, h: 800, zIndex: -1 }
public chartConfig = cloneDeep(IframeConfig)
public option = cloneDeep(option)
}
@@ -0,0 +1,36 @@
<template>
<collapse-item name="属性" :expanded="true">
<setting-item-box name="路径" :alone="true">
<setting-item name="请填写 https 协议的网址">
<n-input v-model:value="optionData.dataset" size="small"></n-input>
</setting-item>
</setting-item-box>
<setting-item-box name="样式">
<setting-item name="圆角">
<n-input-number
v-model:value="optionData.borderRadius"
size="small"
:min="0"
placeholder="圆角"
></n-input-number>
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from "vue";
import { option } from "./config";
import {
CollapseItem,
SettingItemBox,
SettingItem,
} from "@/components/Pages/ChartItemSetting";
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true,
},
});
</script>
@@ -0,0 +1,15 @@
import image from '@/assets/images/chart/informations/iframe.png'
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum,ChatCategoryEnumName } from '../../index.d'
export const IframeConfig: ConfigType = {
key: 'Iframe',
chartKey: 'VIframe',
conKey: 'VCIframe',
title: '远程网页',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.INFORMATIONS,
chartFrame: ChartFrameEnum.COMMON,
image
}
@@ -0,0 +1,49 @@
<template>
<div :style="getStyle(borderRadius)">
<iframe :src="option.dataset" :width="w" :height="h" style="border-width: 0"></iframe>
</div>
</template>
<script setup lang="ts">
import { PropType, shallowReactive, watch, toRefs } from 'vue'
import { useChartDataFetch } from '@/hooks'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const { w, h } = toRefs(props.chartConfig.attr)
const { borderRadius } = toRefs(props.chartConfig.option)
const option = shallowReactive({
dataset: ''
})
const getStyle = (radius: number) => {
return {
borderRadius: `${radius}px`,
overflow: 'hidden'
}
}
// 编辑更新
watch(
() => props.chartConfig.option.dataset,
(newData: string) => {
option.dataset = newData
},
{
immediate: true
}
)
// 预览更新
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: string) => {
option.dataset = newData
})
</script>
@@ -46,8 +46,7 @@ watch(
option.dataset = newData
},
{
immediate: true,
deep: false
immediate: true
}
)
@@ -10,6 +10,6 @@ export const VideoConfig: ConfigType = {
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.INFORMATIONS,
chartFrame: ChartFrameEnum.ECHARTS,
chartFrame: ChartFrameEnum.COMMON,
image
}
@@ -1,5 +1,6 @@
import { ImageConfig } from './Image/index'
import { IframeConfig } from './Iframe/index'
import { VideoConfig } from './Video/index'
import { WordCloudConfig } from './WordCloud/index'
export default [ImageConfig, VideoConfig, WordCloudConfig]
export default [WordCloudConfig, ImageConfig, VideoConfig, IframeConfig]
@@ -0,0 +1,42 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { TextBarrageConfig } from './index'
import { chartInitConfig } from '@/settings/designSetting'
import cloneDeep from 'lodash/cloneDeep'
export enum FontWeightEnum {
NORMAL = '常规',
BOLD = '加粗',
}
export const FontWeightObject = {
[FontWeightEnum.NORMAL]: 'normal',
[FontWeightEnum.BOLD]: 'bold',
}
export const option = {
dataset: '让数字化看得见',
fontSize: 32,
fontColor: '#ffffff',
fontWeight: 'normal',
// 字间距
letterSpacing: 5,
//阴影
showShadow: true,
boxShadow: 'none',
hShadow: 0,
vShadow: 0,
blurShadow: 8,
colorShadow: '#0075ff',
//动画
animationTime: 0,
animationSpeed: 50,
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = TextBarrageConfig.key
public attr = { ...chartInitConfig, w: 500, h: 70, zIndex: -1 }
public chartConfig = cloneDeep(TextBarrageConfig)
public option = cloneDeep(option)
}
@@ -0,0 +1,89 @@
<template>
<collapse-item name="信息" :expanded="true">
<setting-item-box name="文字" :alone="true">
<setting-item>
<n-input v-model:value="optionData.dataset" size="small"></n-input>
</setting-item>
</setting-item-box>
</collapse-item>
<collapse-item name="样式" :expanded="true">
<setting-item-box name="文字">
<setting-item name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.fontColor"></n-color-picker>
</setting-item>
<setting-item name="字体大小">
<n-input-number v-model:value="optionData.fontSize" size="small" placeholder="字体大小"></n-input-number>
</setting-item>
<setting-item name="字体粗细">
<n-select v-model:value="optionData.fontWeight" size="small" :options="fontWeightOptions" />
</setting-item>
<setting-item name="字间距">
<n-input-number v-model:value="optionData.letterSpacing" size="small" placeholder="输入字间距"></n-input-number>
</setting-item>
</setting-item-box>
<setting-item-box name="阴影">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.showShadow" size="small" />
<n-text>展示阴影</n-text>
</n-space>
</setting-item>
<setting-item name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.colorShadow"></n-color-picker
></setting-item>
<setting-item name="x">
<n-input-number v-model:value="optionData.hShadow" size="small"></n-input-number
></setting-item>
<setting-item name="y">
<n-input-number v-model:value="optionData.vShadow" size="small"></n-input-number
></setting-item>
<setting-item name="模糊">
<n-input-number v-model:value="optionData.blurShadow" size="small"></n-input-number
></setting-item>
</setting-item-box>
<setting-item-box name="动画">
<setting-item name="动画速度">
<n-input-number
v-model:value="optionData.animationSpeed"
size="small"
placeholder="动画速度"
:min="0"
></n-input-number>
</setting-item>
<setting-item name="动画间隔">
<n-input-number
v-model:value="optionData.animationTime"
size="small"
placeholder="动画间隔"
:min="0"
></n-input-number>
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { option, FontWeightEnum, FontWeightObject } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
const fontWeightOptions = [
{
label: FontWeightEnum.NORMAL,
value: FontWeightObject[FontWeightEnum.NORMAL]
},
{
label: FontWeightEnum.BOLD,
value: FontWeightObject[FontWeightEnum.BOLD]
}
]
</script>
@@ -0,0 +1,14 @@
import image from '@/assets/images/chart/informations/text_barrage.png'
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum,ChatCategoryEnumName } from '../../index.d'
export const TextBarrageConfig: ConfigType = {
key: 'TextBarrage',
chartKey: 'VTextBarrage',
conKey: 'VCTextBarrage',
title: '弹幕文字',
category: ChatCategoryEnum.TEXT,
categoryName: ChatCategoryEnumName.TEXT,
package: PackagesCategoryEnum.INFORMATIONS,
image
}
@@ -0,0 +1,102 @@
<template>
<div class="go-text-box">
<div class="content">
<span>
{{ option.dataset }}
</span>
</div>
</div>
</template>
<script setup lang="ts">
import { PropType, toRefs, shallowReactive, watch, computed, ref } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { option as configOption } from './config'
import { values } from 'lodash'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType & typeof option>,
required: true
}
})
const { w } = toRefs(props.chartConfig.attr)
const { fontColor, fontSize, letterSpacing, fontWeight, animationTime, animationSpeed, boxShadow } = toRefs(
props.chartConfig.option
)
const option = shallowReactive({
dataset: configOption.dataset
})
// 手动更新
watch(
() => props.chartConfig.option.dataset,
(newData: any) => {
option.dataset = newData
},
{
immediate: true,
deep: false
}
)
//阴影
watch(
props.chartConfig.option,
() => {
try {
if (props.chartConfig.option.showShadow) {
boxShadow.value = `${props.chartConfig.option.hShadow}px ${props.chartConfig.option.vShadow}px ${props.chartConfig.option.blurShadow}px ${props.chartConfig.option.colorShadow}`
} else {
boxShadow.value = 'none'
}
} catch (error) {
console.log(error)
}
},
{
immediate: true
}
)
const transitionDuration = computed(() => {
return Math.floor((w.value as any) / (animationSpeed.value as any))
})
// 预览更新
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: string) => {
option.dataset = newData
})
</script>
<style lang="scss" scoped>
@include go('text-box') {
display: flex;
align-items: center;
.content {
width: 100%;
color: v-bind('fontColor');
font-size: v-bind('fontSize + "px"');
letter-spacing: v-bind('letterSpacing + "px"');
font-weight: v-bind('fontWeight');
text-shadow: v-bind('boxShadow');
position: absolute;
animation: barrage v-bind('transitionDuration + "s"') linear v-bind('animationTime + "s"') infinite;
}
@keyframes barrage {
from {
left: 100%;
transform: translateX(0);
}
to {
left: 0;
transform: translateX(-100%);
}
}
}
</style>
@@ -1,4 +1,5 @@
import { TextCommonConfig } from './TextCommon/index'
import { TextBarrageConfig } from './TextBarrage/index'
import { TextGradientConfig } from './TextGradient/index'
export default [TextCommonConfig, TextGradientConfig]
export default [TextCommonConfig, TextGradientConfig, TextBarrageConfig]